MiscSupport.cpp
上传用户:surprise9
上传日期:2007-01-04
资源大小:426k
文件大小:30k
源码类别:

Ftp客户端

开发平台:

Visual C++

  1. // This is part of the WAR SOFTWARE SERIES initiated by Jarle Aase
  2. // Copyright 1996 by Jarle Aase. All rights reserved.
  3. // See the "War Software Series Licende Agreement" for details concerning 
  4. // use and distribution.
  5. // ---
  6. // This source code, executables and programs containing source code or
  7. // binaries or proprietetary technology from the War Software Series are
  8. // NOT alloed used, viewed or tested by any governmental agencies in
  9. // any countries. This includes the government, departments, police, 
  10. // military etc.
  11. // ---
  12. // This file is intended for use with Tab space = 2
  13. // Created and maintained in MSVC Developer Studio
  14. // ---
  15. // NAME : MiscSupport.cpp
  16. // PURPOSE : Misc. support functions
  17. // PROGRAM : 
  18. // DATE : Sept. 21 1996
  19. // AUTHOR : Jarle Aase
  20. // ---
  21. // REVISION HISTORY
  22. // 
  23. #include "stdafx.h"
  24. #include "WarSoftware.h"
  25. #include "parser.h"
  26. #ifdef _DEBUG
  27. #define new DEBUG_NEW
  28. #undef THIS_FILE
  29. static char THIS_FILE[] = __FILE__;
  30. #endif
  31. ////////////////////////////////////////////////////////////////////////////////
  32. // Global variable initialization
  33. LPSTR StrDataTypeName[] = 
  34. {
  35. "CString",
  36. "int",
  37. "BOOL",
  38. "LPSTR",
  39. ""
  40. };
  41. ////////////////////////////////////////////////////////////////////////////////
  42. // Timer functions
  43. // class CWarTimer
  44. CWarTimer::CWarTimer()
  45. {
  46. Reset();
  47. }
  48. void CWarTimer::Reset()
  49. {
  50. m_TimerVal = GetTickCount();
  51. }
  52. BOOL CWarTimer::TimeOut(DWORD Milliseconds)
  53. {
  54. return TimeDiff() >= Milliseconds;
  55. }
  56. DWORD CWarTimer::TimeLeft(DWORD Milliseconds)
  57. {
  58. if (!TimeOut(Milliseconds))
  59. return Milliseconds - TimeDiff();
  60. else
  61. return 0;
  62. }
  63. DWORD CWarTimer::TimeDiff()
  64. {
  65. return TimeDiff(GetTickCount());
  66. }
  67. DWORD CWarTimer::TimeDiff(DWORD Milliseconds)
  68. {
  69. if (Milliseconds < m_TimerVal)
  70. {
  71. // Scroll around.
  72. // This is not exact, but good enough for the timeout stuff.
  73. // It will only happen each 37th day or something like that...
  74. // 64 bit aretmetics will only add overhead.
  75. m_TimerVal = 0;
  76. }
  77. return Milliseconds - m_TimerVal;
  78. }
  79. ////////////////////////////////////////////////////////////////////////////////
  80. // System query functions
  81. BOOL IsNT()
  82. {
  83. OSVERSIONINFO os;
  84. os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  85. return (GetVersionEx(&os) && (os.dwPlatformId == VER_PLATFORM_WIN32_NT));
  86. }
  87. BOOL HasShell()
  88. {
  89. static int Rval = -1;
  90. if (Rval == -1)
  91. {
  92. OSVERSIONINFO os;
  93. os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  94. if (!GetVersionEx(&os))
  95. Rval = FALSE;
  96. else if (os.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
  97. Rval = TRUE;
  98. else if ((os.dwPlatformId == VER_PLATFORM_WIN32_NT) && (os.dwMajorVersion >= 4))
  99. Rval = TRUE;
  100. else
  101. Rval = FALSE;
  102. }
  103. return Rval;
  104. }
  105. LPCSTR OsName()
  106. {
  107. OSVERSIONINFO os;
  108. static char Rval[32];
  109. if (*Rval)
  110. return Rval;
  111. os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  112. if (GetVersionEx(&os))
  113. {
  114. sprintf(Rval,"WIN32 (%s %d.%d %d)",
  115. (os.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) ? "Win95"
  116. : (os.dwPlatformId == VER_PLATFORM_WIN32_NT) ? "NT" : "Unknown",
  117. os.dwMajorVersion,
  118. os.dwMinorVersion,
  119. os.dwBuildNumber);
  120. }
  121. return Rval;
  122. }
  123. ////////////////////////////////////////////////////////////////////////////////
  124. // Generic data manipulation
  125. // class CLinkedListItem
  126. IMPLEMENT_DYNCREATE(CLinkedListItem, CObject)
  127. CLinkedListItem::CLinkedListItem()
  128. {
  129. m_Next = NULL;
  130. m_Prev = NULL;
  131. m_Ptr = NULL;
  132. }
  133. CLinkedListItem::~CLinkedListItem()
  134. {
  135. #ifdef _DEBUG
  136. ASSERT(m_Next == NULL);
  137. ASSERT(m_Prev == NULL);
  138. ASSERT(m_Ptr == NULL);
  139. #endif
  140. }
  141. // Class CLinkedList
  142. IMPLEMENT_DYNCREATE(CLinkedList, CObject)
  143. CLinkedList::CLinkedList()
  144. {
  145. m_NumItems = 0;
  146. m_First = NULL,
  147. m_Last = NULL;
  148. }
  149. CLinkedList::~CLinkedList()
  150. {
  151. #ifdef _DEBUG
  152. ASSERT(m_NumItems == 0);
  153. #endif
  154. }
  155. // Delete all pointrs and the object.
  156. void CLinkedList::Kill()
  157. {
  158. KillAll();
  159. delete this;
  160. }
  161. void CLinkedList::KillAll()
  162. {
  163. LPVOID p;
  164. while((p = GetAndDeleteFirst()) != NULL)
  165. delete p;
  166. }
  167. void CLinkedList::Empty()
  168. {
  169. while(GetAndDeleteFirst())
  170. ;
  171. }
  172. CLinkedListItem *CLinkedList::First()
  173. {
  174. ASSERT(m_First ? m_First->m_Prev == NULL : TRUE);
  175. return m_First;
  176. }
  177. CLinkedListItem *CLinkedList::Last()
  178. {
  179. ASSERT(m_Last ? m_Last->m_Next == NULL : TRUE);
  180. return m_Last;
  181. }
  182. LPVOID CLinkedList::FirstPtr()
  183. {
  184. ASSERT(m_First ? m_First->m_Prev == NULL : TRUE);
  185. return m_First ? m_First->m_Ptr : NULL;
  186. }
  187. LPVOID CLinkedList::LastPtr()
  188. {
  189. ASSERT(m_Last ? m_Last->m_Next == NULL : TRUE);
  190. return m_Last ? m_Last->m_Ptr : NULL;
  191. }
  192. LPVOID CLinkedList::Ptr(CLinkedListItem *Item)
  193. {
  194. ASSERT(Item);
  195. return Item->m_Ptr;
  196. }
  197. CLinkedListItem *CLinkedList::Next(CLinkedListItem *Item)
  198. {
  199. ASSERT(Item);
  200. return Item->m_Next;
  201. }
  202. CLinkedListItem *CLinkedList::Prev(CLinkedListItem *Item)
  203. {
  204. ASSERT(Item);
  205. return Item->m_Prev;
  206. }
  207. CLinkedListItem *CLinkedList::FindPtr(LPVOID Ptr)
  208. {
  209. CLinkedListItem *SearchItem = First();
  210. while(SearchItem)
  211. {
  212. if (SearchItem->m_Ptr == Ptr)
  213. break;
  214. SearchItem = Next(SearchItem);
  215. }
  216. return SearchItem;
  217. }
  218. BOOL CLinkedList::DeletePtr(LPVOID Ptr)
  219. {
  220. ASSERT(Ptr);
  221. CLinkedListItem *Item = FindPtr(Ptr);
  222. if (Item)
  223. DeleteItem(Item);
  224. return Item != NULL;
  225. }
  226. void CLinkedList::DeleteItem(CLinkedListItem *Item)
  227. {
  228. ASSERT(Item);
  229. if (Item->m_Prev)
  230. Item->m_Prev->m_Next = Item->m_Next;
  231. else
  232. m_First = Item->m_Next;
  233. if (Item->m_Next)
  234. Item->m_Next->m_Prev = Item->m_Prev;
  235. else
  236. m_Last = Item->m_Prev;
  237. --m_NumItems;
  238. ASSERT(m_NumItems >= 0);
  239. #ifdef _DEBUG
  240. Item->m_Next = NULL;
  241. Item->m_Prev = NULL;
  242. Item->m_Ptr = NULL;
  243. #endif
  244. delete Item;
  245. }
  246. void CLinkedList::AddFirst(LPVOID Ptr)
  247. {
  248. CLinkedListItem *Item = First();
  249. AddPtr(Item, NULL, Ptr);
  250. }
  251. void CLinkedList::AddLast(LPVOID Ptr)
  252. {
  253. CLinkedListItem *Item = Last();
  254. AddPtr(NULL, Item, Ptr);
  255. }
  256. void CLinkedList::AddPtr(CLinkedListItem *Next, CLinkedListItem *Prev, LPVOID Ptr)
  257. {
  258. CLinkedListItem *NewItem = new CLinkedListItem;
  259. NewItem->m_Ptr = Ptr;
  260. if ((NewItem->m_Prev = Prev) != NULL)
  261. NewItem->m_Prev->m_Next = NewItem;
  262. else
  263. m_First = NewItem;
  264. if ((NewItem->m_Next = Next) != NULL)
  265. NewItem->m_Next->m_Prev = NewItem;
  266. else
  267. m_Last = NewItem;
  268. ++m_NumItems;
  269. }
  270. LPVOID CLinkedList::GetAndDeleteFirst()
  271. {
  272. if (!First())
  273. return NULL;
  274. LPVOID Ptr = FirstPtr();
  275. DeleteItem(First());
  276. return Ptr;
  277. }
  278. LPVOID CLinkedList::GetAndDeleteLast()
  279. {
  280. if (!Last())
  281. return NULL;
  282. LPVOID Ptr = LastPtr();
  283. DeleteItem(Last());
  284. return Ptr;
  285. }
  286. void CLinkedList::Sort(int (*SortFunc)(const void *, const void *))
  287. {
  288. CLinkedListItem **array = new CLinkedListItem *[m_NumItems];
  289. CLinkedListItem *Curr = m_First;
  290. int Index;
  291. if (!m_NumItems)
  292. return; // Nothing to sort...
  293. for(Index = 0; Index < m_NumItems; Index++, Curr = Curr->m_Next)
  294. array[Index] = Curr;
  295. ASSERT(Curr == NULL);
  296. qsort((LPVOID) array, m_NumItems, sizeof(CLinkedListItem *), SortFunc);
  297. // Relink list
  298. m_First = array[0];
  299. m_Last = array[m_NumItems - 1];
  300. for(Index = 0; Index < m_NumItems; Index++)
  301. {
  302. Curr = array[Index];
  303. if (Index)
  304. {
  305. Curr->m_Prev = array[Index - 1];
  306. Curr->m_Prev->m_Next = Curr;
  307. }
  308. else
  309. Curr->m_Prev = NULL;
  310. Curr->m_Next = NULL;
  311. }
  312. delete array;
  313. }
  314. void CLinkedList::operator = (CLinkedList& List)
  315. {
  316. Empty();
  317. Cat(List);
  318. }
  319. void CLinkedList::Cat(CLinkedList& List)
  320. {
  321. CLinkedListItem *Item;
  322. for(Item = List.First(); Item; Item = List.Next(Item))
  323. AddLast(List.Ptr(Item));
  324. }
  325. ////////////////////////////////////////////////////////////////////////////////
  326. // CHistory - derived from CLinkedList
  327. // Newest on bottom, oldest on top.
  328. void CHistory::Add(LPVOID Ptr, int MaxItems, BOOL DeletePtr)
  329. {
  330. // Decrease the items
  331. while (m_NumItems && (m_NumItems >= MaxItems))
  332. {
  333. if (DeletePtr)
  334. delete (CString *)FirstPtr();
  335. DeleteItem(First());
  336. }
  337. AddLast(Ptr);
  338. }
  339. void CHistory::Add(LPCSTR Ptr, int MaxItems)
  340. {
  341. CString *cs = new CString((LPCSTR)Ptr);
  342. cs->TrimRight();
  343. Add((LPVOID)cs, MaxItems, TRUE);
  344. }
  345. void CHistory::KillAll()
  346. {
  347. CString *cs;
  348. while(cs = (CString *)GetAndDeleteFirst())
  349. delete cs;
  350. }
  351. ////////////////////////////////////////////////////////////////////////////////
  352. // CLookupListItem
  353. // Only used by CLookupList, and destroyed by 
  354. CLookupListItem::CLookupListItem(LPVOID Ptr, DWORD NumSymbol, LPCSTR TextSymbol, int DataType)
  355. {
  356. m_Name = strdup(TextSymbol);
  357. m_Number = NumSymbol;
  358. m_Ptr = Ptr;
  359. m_DataType = DataType;
  360. };
  361. CLookupListItem::~CLookupListItem()
  362. {
  363. delete m_Name;
  364. }
  365. LPCSTR CLookupListItem::GetData(CString& cBuf)
  366. {
  367. return ::GetData(Ptr(),m_DataType,cBuf);
  368. }
  369. ////////////////////////////////////////////////////////////////////////////////
  370. // CLookupList
  371. // Used to store pointers to objects that can be searched by name or symbolic number
  372. CLookupList::~CLookupList()
  373. {
  374. while(m_List.First())
  375. m_List.GetAndDeleteFirst();
  376. }
  377. void CLookupList::AddItem(LPVOID Ptr, DWORD NumSymbol, LPCSTR TextSymbol, int DataType)
  378. {
  379. ASSERT(NumSymbol != 0);
  380. m_List.AddLast((LPVOID)(new CLookupListItem(Ptr,NumSymbol,TextSymbol,DataType)));
  381. }
  382. CLinkedListItem *CLookupList::FindItem(DWORD NumSymbol, LPCSTR TextSymbol)
  383. {
  384. CLinkedListItem *ListItem = m_List.First();
  385. CLookupListItem *Item;
  386. while(ListItem)
  387. {
  388. Item = (CLookupListItem *) (m_List.Ptr(ListItem));
  389. if (NumSymbol == Item->m_Number)
  390. break;
  391. if (TextSymbol && !strcmp(TextSymbol,Item->m_Name))
  392. break;
  393. ListItem = m_List.Next(ListItem);
  394. }
  395. return ListItem;
  396. }
  397. LPVOID CLookupList::Find(DWORD NumSymbol, LPCSTR TextSymbol)
  398. {
  399. CLinkedListItem *ListItem = FindItem(NumSymbol, TextSymbol);
  400. if (!ListItem)
  401. return NULL;
  402. ASSERT(ListItem);
  403. ASSERT(AfxIsValidAddress(ListItem,sizeof(CLinkedListItem)));
  404. ASSERT(AfxIsValidAddress(ListItem->m_Ptr,4));
  405. return Ptr(ListItem);
  406. }
  407. void CLookupList::DeleteItem(DWORD NumSymbol, LPCSTR TextSymbol)
  408. {
  409. CLinkedListItem *Item = FindItem(NumSymbol, TextSymbol);
  410. if (Item)
  411. {
  412. CLookupListItem *LookupItem = (CLookupListItem *)m_List.Ptr(Item);
  413. delete LookupItem;
  414. m_List.DeleteItem(Item);
  415. }
  416. }
  417. CLinkedListItem *CLookupList::First()
  418. {
  419. return m_List.First();
  420. }
  421. CLinkedListItem *CLookupList::Next(CLinkedListItem *Item)
  422. {
  423. ASSERT(Item);
  424. return m_List.Next(Item);
  425. }
  426. // Return pointer to the CLookup list node
  427. CLookupListItem *CLookupList::LookupPtr(CLinkedListItem *Item)
  428. {
  429. ASSERT(Item);
  430. ASSERT(AfxIsValidAddress(Item,sizeof(CLinkedListItem)));
  431. ASSERT(AfxIsValidAddress(Item->m_Ptr,4));
  432. return ((CLookupListItem*)m_List.Ptr(Item));
  433. }
  434. // Return pointer to the actual data (Name list --> Name node --> Ptr)
  435. LPVOID CLookupList::Ptr(CLookupListItem *LookupItem)
  436. {
  437. ASSERT(LookupItem);
  438. ASSERT(AfxIsValidAddress(LookupItem,sizeof(CLookupListItem)));
  439. ASSERT(AfxIsValidAddress(LookupItem->m_Ptr,4));
  440. ASSERT(AfxIsValidString(LookupItem->m_Name));
  441. return LookupItem->m_Ptr;
  442. }
  443. // Return pointer to the actual data (Name list --> Name node --> Ptr)
  444. // from pointer to the underlaying list
  445. LPVOID CLookupList::Ptr(CLinkedListItem *LookupItem)
  446. {
  447. return Ptr(LookupPtr(LookupItem));
  448. }
  449. // Get data for use in printf()
  450. LPCSTR CLookupList::GetData(CLinkedListItem *Item, CString& cBuf)
  451. {
  452. return GetData(LookupPtr(Item), cBuf);
  453. }
  454. // Get data for use in printf
  455. LPCSTR CLookupList::GetData(CLookupListItem *LookupItem, CString& cBuf)
  456. {
  457. ASSERT(LookupItem);
  458. ASSERT(AfxIsValidAddress(LookupItem,sizeof(CLookupListItem)));
  459. ASSERT(AfxIsValidAddress(LookupItem->m_Ptr,4));
  460. return LookupItem->GetData(cBuf);
  461. }
  462. void CLookupList::KillAll()
  463. {
  464. //m_List.KillAll();
  465. CLinkedListItem *Item;
  466. while(Item = m_List.First())
  467. {
  468. CLookupListItem *pLI = (CLookupListItem *)m_List.Ptr(Item);
  469. delete pLI;
  470. m_List.DeleteItem(Item);
  471. }
  472. }
  473. ////////////////////////////////////////////////////////////////////////////////
  474. // CString derived class to handle va_list argList
  475. void CWarString::FormatVaList(LPCTSTR lpszFormat, va_list argList)
  476. {
  477. va_list argListSave = argList;
  478. FormatV(lpszFormat,argList);
  479. va_end(argListSave);
  480. }
  481. void CWarString::FormatCat(LPCTSTR lpszFormat, ...)
  482. {
  483. va_list argList = va_start(argList, lpszFormat);
  484. FormatCatV(lpszFormat,argList);
  485. va_end(argList);
  486. }
  487. int CWarString::FormatCatV(LPCTSTR lpszFormat, va_list argList)
  488. {
  489. int OldLen = GetLength();
  490. va_list argListSave = argList;
  491. CString cBuf = *this;
  492. Empty();
  493. FormatV(lpszFormat,argList);
  494. va_end(argListSave);
  495. cBuf += *this;
  496. Format("%s", cBuf);
  497. return GetLength() - OldLen;
  498. }
  499. ////////////////////////////////////////////////////////////////////////////////
  500. // Safe string array
  501. LPCSTR SafeStringIndexExp(LPCSTR File, int Line, LPCSTR *StrIndex, int Index, int Limit)
  502. {
  503. if ((Index < 0) || (Index >= Limit))
  504. {
  505. LPSTR Buf = new char[512];
  506. sprintf(Buf,"Error: String[%d] in file %s line %d is invalid.",
  507. Index, File, Line);
  508. return Buf;
  509. }
  510. ASSERT(AfxIsValidString(StrIndex[Index]));
  511. return StrIndex[Index];
  512. }
  513. ////////////////////////////////////////////////////////////////////////////////
  514. // CCmdArgs
  515. CCmdArgs::CCmdArgs()
  516. {
  517. Initialize();
  518. }
  519. CCmdArgs::CCmdArgs(LPCSTR Name, LPCSTR CommandLine, CCommandParser& Parser)
  520. {
  521. Initialize();
  522. AddArg(Name);
  523. LPCSTR LexCmdLine = CommandLine;
  524. while(Parser.yyLex(
  525. &LexCmdLine, 
  526. Parser.m_Tokens, 
  527. ' ', 
  528. LEX_WANT_STRING | LEX_PARSE_QUOTES, 
  529. *this) == TOK_STRING)
  530. {
  531. ;
  532. }
  533. }
  534. CCmdArgs::~CCmdArgs()
  535. {
  536. Empty();
  537. }
  538. void CCmdArgs::Empty()
  539. {
  540. IsReInitialized = FALSE;
  541. int Index;
  542. AssertValid();
  543. for(Index = 0; Index < m_argc; Index++)
  544. delete m_argv[Index];
  545. delete m_argv;
  546. }
  547. void CCmdArgs::Initialize()
  548. {
  549. IsReInitialized = TRUE;
  550. m_argc = 0;
  551. m_argc_max = 16;
  552. m_argv = new LPSTR[16];
  553. }
  554. void CCmdArgs::PrepereNew()
  555. {
  556. if (!IsReInitialized)
  557. {
  558. Empty();
  559. Initialize();
  560. }
  561. }
  562. LPCSTR CCmdArgs::Insert(int Index, LPCSTR Arg, int Len)
  563. {
  564. if (Index > m_argc)
  565. {
  566. ASSERT(FALSE); // Bad index
  567. return NULL;
  568. }
  569. if (Index == m_argc)
  570. return AddArg(Arg, Len);
  571. void Check();
  572. for(int i = Index; i < m_argc; i++)
  573. {
  574. m_argv[i +1] = m_argv[i];
  575. }
  576. ++m_argc;
  577. if (!Len)
  578. Len = strlen(Arg);
  579. m_argv[Index] = new char[Len + 1];
  580. memcpy(m_argv[Index], Arg, Len);
  581. m_argv[Index][Len] = 0;
  582. return m_argv[Index];
  583. };
  584. LPCSTR CCmdArgs::Replace(int Index, LPCSTR Arg, int Len)
  585. {
  586. if (Index > m_argc)
  587. {
  588. ASSERT(FALSE); // Bad index
  589. return NULL;
  590. }
  591. if (Index < m_argc)
  592. delete m_argv[Index];
  593. if (Arg == NULL)
  594. m_argv[Index] = NULL;
  595. else
  596. {
  597. if (!Len)
  598. Len = strlen(Arg);
  599. m_argv[Index] = new char[Len + 1];
  600. memcpy(m_argv[Index], Arg, Len);
  601. m_argv[Index][Len] = 0;
  602. }
  603. return m_argv[Index];
  604. }
  605. LPCSTR CCmdArgs::AddArg(LPCSTR Arg, int Len)
  606. {
  607. ASSERT(AfxIsValidAddress(Arg,sizeof(LPCSTR)));
  608. ASSERT(AfxIsValidString(Arg));
  609. IsReInitialized = FALSE;
  610. Check();
  611. if (!Len)
  612. Len = strlen(Arg);
  613. m_argv[m_argc] = new char[Len + 1];
  614. memcpy(m_argv[m_argc], Arg, Len);
  615. m_argv[m_argc][Len] = 0;
  616. return m_argv[m_argc++];
  617. }
  618. void CCmdArgs::Check()
  619. {
  620. if (m_argc >= (m_argc_max - 1))
  621. {
  622. // Realloc argv
  623. LPSTR *tmp = new LPSTR[m_argc_max + 256];
  624. memcpy(tmp, m_argv, sizeof(char *) * m_argc_max);
  625. m_argc_max += 256;
  626. delete m_argv;
  627. m_argv = tmp;
  628. }
  629. }
  630. void CCmdArgs::AssertValid()
  631. {
  632. int Index;
  633. ASSERT(AfxIsValidAddress(this,sizeof(CCmdArgs)));
  634. ASSERT(m_argc >= 0);
  635. for(Index = 0; Index < m_argc; Index++)
  636. {
  637. ASSERT(AfxIsValidAddress(m_argv[Index],sizeof(LPCSTR)));
  638. ASSERT(AfxIsValidString(m_argv[Index]));
  639. }
  640. }
  641. // Return an argument
  642. LPCSTR CCmdArgs::Arg(int Index)
  643. {
  644. AssertValid();
  645. if ((Index < 0) || (Index >= m_argc))
  646. return "error: CCmdArgs::Arg: Invalid argument number requested.";
  647. return m_argv[Index];
  648. }
  649. int CCmdArgs::operator = (CCmdArgs& Arg)
  650. {
  651. int i;
  652. PrepereNew();
  653. for(i = 0; i < Arg.m_argc; i++)
  654. AddArg(Arg[i]);
  655. return m_argc;
  656. }
  657. ////////////////////////////////////////////////////////////////////////////////
  658. // GetData() - return pointer (or value) for use in printf.
  659. LPCSTR GetData(LPVOID Ptr, int DataType, CString& cBuf)
  660. {
  661. ASSERT(AfxIsValidAddress(Ptr,sizeof(LPVOID)));
  662. LPCSTR ReturnPtr = "";
  663. switch(DataType)
  664. {
  665. case DATATYPE_CSTRING:
  666. cBuf = (*(CString *)Ptr);
  667. break;
  668. case DATATYPE_INT:
  669. cBuf.Format("%d",(*(int *)Ptr));
  670. break;
  671. case DATATYPE_BOOL:
  672. cBuf.Format("%s",(*(int *)Ptr) ? "TRUE" : "FALSE");
  673. break;
  674. case DATATYPE_LPSTR:
  675. ASSERT(AfxIsValidString((LPCSTR)Ptr));
  676. cBuf = (LPCSTR)Ptr;
  677. break;
  678. default:
  679. ReturnPtr = "Error: Invalid Datatype";
  680. break;
  681. }
  682. ReturnPtr = (LPCSTR)cBuf;
  683. ASSERT(AfxIsValidString(ReturnPtr));
  684. return ReturnPtr;
  685. }
  686. BOOL PutData(LPVOID Ptr, int DataType, LPCSTR Value)
  687. {
  688. switch(DataType)
  689. {
  690. case DATATYPE_CSTRING:
  691. (*(CString *)Ptr) = Value;
  692. break;
  693. case DATATYPE_INT:
  694. (*(int *)Ptr) = atoi(Value);
  695. break;
  696. case DATATYPE_BOOL:
  697. (*(int *)Ptr) = atoi(Value) ? TRUE 
  698. : (!stricmp(Value,"TRUE") || !stricmp(Value,"YES")) ? TRUE : FALSE;
  699. break;
  700. case DATATYPE_LPSTR:
  701. ASSERT(FALSE);
  702. break;
  703. default:
  704. ASSERT(FALSE);
  705. break;
  706. }
  707. return TRUE;
  708. }
  709. ////////////////////////////////////////////////////////////////////////////////
  710. // GetlastErrorText()
  711. CString GetLastErrorText()
  712. {
  713. return GetLastErrorText(GetLastError());
  714. }
  715. CString GetLastErrorText(int Errno)
  716. {
  717. LPVOID lpMsgBuf = NULL;
  718. CString cBuf;
  719. FormatMessage( 
  720.     FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  721.     NULL,
  722.     Errno,
  723.     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  724.     (LPTSTR) &lpMsgBuf,
  725.     0,
  726.     NULL);
  727. if (lpMsgBuf)
  728. {
  729. ASSERT(AfxIsValidString((LPCSTR)lpMsgBuf));
  730. cBuf = (LPCSTR)lpMsgBuf;
  731. LocalFree(lpMsgBuf);
  732. }
  733. else
  734. {
  735. cBuf.Format("%d", GetLastError());
  736. }
  737. ASSERT(AfxIsValidString(cBuf));
  738. cBuf.TrimRight();
  739. return cBuf;
  740. }
  741. ////////////////////////////////////////////////////////////////////////////////
  742. // MySscanf()
  743. // Does a little better job than the standard lib function...
  744. // Handles %I64. %C is CString. %O automatically detects octal or binary
  745. // based on the first digit. (0 = octal, and other digit = 10base).
  746. int Digits[127];
  747. int MySscanf(LPCSTR buf, LPCSTR Format, ...)
  748. {
  749. va_list marker;
  750. va_start(marker, Format);
  751. int Rval = 0;
  752. char *p;
  753. int *i;
  754. __int64 *i64;
  755. int base;
  756. int IntegerLength = 32;
  757. CString *pC;
  758. Digits['1'] = 1;
  759. Digits['2'] = 2;
  760. Digits['3'] = 3;
  761. Digits['4'] = 4;
  762. Digits['5'] = 5;
  763. Digits['6'] = 6;
  764. Digits['7'] = 7;
  765. Digits['8'] = 8;
  766. Digits['9'] = 9;
  767. Digits['a'] = 10;
  768. Digits['b'] = 11;
  769. Digits['c'] = 12;
  770. Digits['d'] = 13;
  771. Digits['e'] = 14;
  772. Digits['f'] = 15;
  773. Digits['A'] = 10;
  774. Digits['B'] = 11;
  775. Digits['C'] = 12;
  776. Digits['D'] = 13;
  777. Digits['E'] = 14;
  778. Digits['F'] = 15;
  779. while(*Format)
  780. {
  781. if (*Format == '%')
  782. {
  783. again:
  784. switch(*++Format)
  785. {
  786. case 'c':
  787. p = va_arg(marker,char *);
  788. *p = *buf++;
  789. ++Rval;
  790. break;
  791. case 's':
  792. p = va_arg(marker,char *);
  793. while(*buf && (!Format[1] || (*buf != Format[1])))
  794. *p++ = *buf++;
  795. *p = 0;
  796. ++Rval;
  797. break;
  798. case 'C':
  799. pC = va_arg(marker,CString *);
  800. pC->Empty();
  801. while(*buf && (!Format[1] || (*buf != Format[1])))
  802. *pC += *buf++;
  803. ++Rval;
  804. break;
  805. case 'I':
  806. if (!memcmp(Format, "I64", 3))
  807. {
  808. Format += 2;
  809. IntegerLength = 64;
  810. goto again;
  811. }
  812. break;
  813. case 'l':
  814. IntegerLength = 32;
  815. goto again;
  816. case 'O':
  817. base = 10;
  818. if (*buf == '0')
  819. base = 8; // Octal
  820. goto scandigit;
  821. case 'o':
  822. base = 8;
  823. goto scandigit;
  824. case 'd':
  825. base = 10;
  826. scandigit:
  827. if (IntegerLength == 64)
  828. {
  829. i64 = va_arg(marker, __int64 *);
  830. *i64 = 0;
  831. }
  832. else
  833. {
  834. i = va_arg(marker, int *);
  835. *i = 0;
  836. }
  837. while(*buf && ((*buf == '0') || (Digits[*buf] && (Digits[*buf] < base))))
  838. {
  839. if (IntegerLength == 64)
  840. {
  841. *i64 *= base;
  842. *i64 += Digits[*buf];
  843. }
  844. else
  845. {
  846. *i *= base;
  847. *i += Digits[*buf];
  848. }
  849. ++buf;
  850. }
  851. IntegerLength = 32;
  852. ++Rval;
  853. break;
  854. case 'x':
  855. case 'X':
  856. base = 16;
  857. goto scandigit;
  858. }
  859. ++Format;
  860. }
  861. else
  862. {
  863. while(*buf && (*buf != *Format))
  864. ++buf;
  865. while(*buf && (*buf == *Format))
  866. ++buf;
  867. ++Format;
  868. //++buf;
  869. }
  870. }
  871. va_end(marker);
  872. return Rval;
  873. }
  874. ////////////////////////////////////////////////////////////////////////////////
  875. // Generic pattern compare function. Several patterns can exist, 
  876. // seperated with rn
  877. BOOL PatternMatchesName(LPCSTR OrgName, LPCSTR Pattern)
  878. {
  879. LPCSTR Name = OrgName, MarkerName = NULL, MarkerPattern = NULL;
  880. for(;*Pattern ; Pattern++)
  881. {
  882. again:
  883. if ((*Pattern == 'r') || (*Pattern == 'n'))
  884. {
  885. if (MarkerName)
  886. {
  887. Name = MarkerName;
  888. Pattern = MarkerPattern;
  889. MarkerPattern = NULL;
  890. MarkerName = NULL;
  891. goto again;
  892. }
  893. if (!*Name)
  894. return TRUE;
  895. Name = OrgName;
  896. continue;
  897. }
  898. if ((*Pattern == '*') && (!Pattern[1] || (Pattern[1] == 'r') || (Pattern[1] == 'n')))
  899. return TRUE;
  900. if (*Pattern == '*')
  901. {
  902. MarkerPattern = Pattern;
  903. while(tolower(*Name) != tolower(Pattern[1]))
  904. {
  905. if (!*Name)
  906. goto next_file;
  907. ++Name;
  908. }
  909. MarkerName = Name +1;
  910. }
  911. else if (*Pattern == '?')
  912. {
  913. ++Name;
  914. }
  915. else if (tolower(*Pattern) != tolower(*Name++))
  916. {
  917. if (MarkerName)
  918. {
  919. Name = MarkerName;
  920. Pattern = MarkerPattern;
  921. MarkerPattern = NULL;
  922. MarkerName = NULL;
  923. goto again;
  924. }
  925. next_file:
  926. // Skip to next file
  927. while(*Pattern && (*Pattern != 'r') && (*Pattern != 'n'))
  928. ++Pattern;
  929. Name = OrgName;
  930. if (!*Pattern)
  931. return FALSE;
  932. }
  933. else if (!*Name)
  934. {
  935. MarkerName = NULL;
  936. MarkerPattern = NULL;
  937. }
  938. }
  939. return *Name == '';
  940. }
  941. ////////////////////////////////////////////////////////////////////////////////
  942. // Load a resource string
  943. LPCSTR LoadString(UINT nID, CString& cBuf)
  944. {
  945. if (cBuf.LoadString(nID))
  946. return (LPCSTR)cBuf;
  947. else
  948. return "*ERR*";
  949. }
  950. //////////////////////////////////////////////////////////////////////////////////////
  951. // CDaemonStatus
  952. // Current server state
  953. IMPLEMENT_SERIAL(CDaemonStatus, CObject, VERSIONABLE_SCHEMA | 1)
  954. CDaemonStatus * CDaemonStatus::m_pMe = NULL;
  955. CDaemonStatus::CDaemonStatus()
  956. {
  957. GetSystemTime(&m_ServerStarted);
  958. m_UserConnections = 0;
  959. m_OperatorConnections = 0;
  960. m_UserConnectionsTotal = 0;
  961. m_OperatorConnectionsTotal = 0;
  962. m_FileXfers = 0;
  963. m_FileXfersTotal = 0;
  964. m_IsOnline = FALSE;
  965. m_ShutdownPending = FALSE;
  966. m_ServerName = "";
  967. m_ServerEmail = "";
  968. m_ServerType = "";
  969. m_ServerPort = 0;
  970. m_ServerListeningIP = "";
  971. if (!m_pMe)
  972. m_pMe = this;
  973. }
  974. CDaemonStatus::~CDaemonStatus()
  975. {
  976. m_ServerName.Empty();
  977. m_ServerEmail.Empty();
  978. m_ServerType.Empty();
  979. m_ServerListeningIP.Empty();
  980. if (m_pMe == this)
  981. m_pMe = NULL;
  982. }
  983. // Extract the data from a formatted notification from the server
  984. BOOL CDaemonStatus::Extract(LPSTR Msg)
  985. {
  986. LPSTR p, pp;
  987. for(p = strtok(Msg,"1"); p; p = strtok(NULL, "1"))
  988. {
  989. pp = p;
  990. while(isdigit(*pp))
  991. ++pp;
  992. if (*pp == ' ')
  993. ++pp;
  994. switch(atoi(p))
  995. {
  996. case 1: m_ServerType = pp; break;
  997. case 2: m_ServerName = pp; break;
  998. case 3: m_ServerStartedFmt = pp; break;
  999. case 4: m_ShutdownPending = (stricmp(pp, "Pending") == 0); break;
  1000. case 5: m_IsOnline = (stricmp(pp, "YES") == 0); break;
  1001. case 6: m_ServerListeningIP = pp; break;
  1002. case 7: m_ServerPort = atoi(pp); break;
  1003. case 8: m_UserConnections = atoi(pp); break;
  1004. case 9: m_OperatorConnections = atoi(pp); break;
  1005. case 10: m_FileXfers = atoi(pp); break;
  1006. case 11: m_UserConnectionsTotal = atoi(pp); break;
  1007. case 12: m_OperatorConnectionsTotal = atoi(pp); break;
  1008. case 13: m_FileXfersTotal = atoi(pp); break;
  1009. }
  1010. }
  1011. return TRUE;
  1012. }
  1013. void CDaemonStatus::Serialize(CArchive& ar)
  1014. {
  1015. CObject::Serialize(ar);
  1016. int nVersion = 1;
  1017. if (ar.IsLoading())
  1018. {
  1019. ar >> nVersion;
  1020. if (nVersion != 1)
  1021. {
  1022. AfxThrowFileException(ERROR_BAD_FORMAT);
  1023. return;
  1024. }
  1025. ar >> m_ServerName;
  1026. ar >> m_ServerEmail;
  1027. ar >> m_ServerType;
  1028. ar >> m_ServerPort;
  1029. ar >> m_ServerListeningIP;
  1030. }
  1031. else
  1032. {
  1033. ar << nVersion;
  1034. ar << m_ServerName;
  1035. ar << m_ServerEmail;
  1036. ar << m_ServerType;
  1037. ar << m_ServerPort;
  1038. ar << m_ServerListeningIP;
  1039. }
  1040. }
  1041. ////////////////////////////////////////////////////////////////////////////////
  1042. // Get a command line option
  1043. LPCSTR GetLineParam(LPCSTR Tag, CString& cValue, LPCSTR Default)
  1044. {
  1045. LPCSTR p = AfxGetApp()->m_lpCmdLine;
  1046. ASSERT(AfxIsValidString(p));
  1047. ASSERT(AfxIsValidString(Tag));
  1048. ASSERT(AfxIsValidString(Default));
  1049. int len = strlen(Tag);
  1050. ASSERT(len > 0);
  1051. cValue.Empty();
  1052. char TagCh = ' ';
  1053. while(*p)
  1054. {
  1055. if (!strnicmp(p, Tag, len) && ((p == Tag) || (p[-1] == ' ')))
  1056. {
  1057. p += len;
  1058. while(*p && (*p == ' '))
  1059. ++p;
  1060. if (*p == '"')
  1061. TagCh = *(p++);
  1062. while(*p && (*p != TagCh))
  1063. cValue += *p++;
  1064. return cValue;
  1065. }
  1066. ++p;
  1067. }
  1068. cValue = Default;
  1069. return cValue;
  1070. }
  1071. ////////////////////////////////////////////////////////////////////////////////
  1072. // Expand string macros
  1073. // String macros as as in CTime.Format()
  1074. // Extentions: 
  1075. //   %T Type - FTP, MAIL etc.
  1076. //   %P Service Port number
  1077. //   %R Remote interface port number
  1078. LPCSTR ExpandStringMacros(LPCSTR Str, CString& cValue, CDaemonStatus *Stat)
  1079. { ASSERT(AfxIsValidString(Str));
  1080. cValue.Empty();
  1081. CString cBuf;
  1082. CTime ct = CTime::GetCurrentTime();
  1083. char buf[64];
  1084. if (!Stat)
  1085. Stat = CDaemonStatus::GetStat();
  1086. while(*Str)
  1087. {
  1088. if (*Str == '%')
  1089. {
  1090. if (Str[1] == 'T')
  1091. {
  1092. if (Stat)
  1093. cBuf += Stat->m_ServerType;
  1094. Str += 2;
  1095. continue;
  1096. }
  1097. if (Str[1] == 'P')
  1098. {
  1099. if (Stat)
  1100. cBuf += itoa(Stat->m_ServerPort, buf, 10);
  1101. Str += 2;
  1102. continue;
  1103. }
  1104. if (Str[1] == 'R')
  1105. {
  1106. if (Stat)
  1107. cBuf += itoa(Stat->m_RemoteAPort, buf, 10);
  1108. Str += 2;
  1109. continue;
  1110. }
  1111. }
  1112. cBuf += *Str;
  1113. ++Str;
  1114. }
  1115. cValue = ct.Format(cBuf);
  1116. return cValue;
  1117. }
  1118. ////////////////////////////////////////////////////////////////////////////////
  1119. // Make sure that the path exist. 
  1120. // Eventually, create the directories
  1121. BOOL ExpandPath(LPCSTR Path)
  1122. {
  1123. CString cBuf("");
  1124. while(*Path)
  1125. {
  1126. if (*Path == '\')
  1127. {
  1128. if (!cBuf.IsEmpty())
  1129. {
  1130. DWORD attr = GetFileAttributes(cBuf);
  1131. if (attr == 0xFFFFFFFF)
  1132. {
  1133. if (!CreateDirectory(cBuf, NULL))
  1134. return FALSE;
  1135. }
  1136. else if (!(attr & FILE_ATTRIBUTE_DIRECTORY))
  1137. return FALSE;
  1138. }
  1139. }
  1140. cBuf += *(Path++);
  1141. }
  1142. return TRUE;
  1143. }
  1144. ////////////////////////////////////////////////////////////////////////////////
  1145. // Get free disk space
  1146. __int64 GetFreeDiskSpace(LPCSTR Path)
  1147. {
  1148. CString cBuf(Path);
  1149. char *DriveLetter = cBuf.GetBuffer(1);
  1150. if (DriveLetter[2] == '\' && (cBuf.GetLength() > 3))
  1151. DriveLetter[3] = 0;
  1152. cBuf.ReleaseBuffer();
  1153. DWORD SectorsPerCluster, BytesPerSector, NumberOfFreeClusters, TotalNumberOfClusters;
  1154. if (!GetDiskFreeSpace(cBuf,&SectorsPerCluster,&BytesPerSector,&NumberOfFreeClusters,&TotalNumberOfClusters))
  1155. return 0;
  1156. return (__int64)NumberOfFreeClusters * (__int64)SectorsPerCluster * (__int64)BytesPerSector / (__int64)1024;
  1157. }
  1158. ////////////////////////////////////////////////////////////////////////////////
  1159. // Get the starrtup dir
  1160. CString GetStartupPath()
  1161. {
  1162. extern char far *_pgmptr;
  1163. CString cPath = _pgmptr;
  1164. LPSTR p = strrchr(cPath.GetBuffer(1),'\');
  1165. if (p && *p)
  1166. *p = 0;
  1167. cPath.ReleaseBuffer();
  1168. return cPath;
  1169. }
  1170. ////////////////////////////////////////////////////////////////////////////////
  1171. // Time conversion
  1172. // Does not convert to/from local time..
  1173. __int64 CTimeToDate(const CTime& ct)
  1174. {
  1175. SYSTEMTIME st;
  1176. st.wYear = ct.GetYear();
  1177.   st.wMonth = ct.GetMonth();
  1178.   st.wDayOfWeek = ct.GetDayOfWeek();
  1179.   st.wDay = ct.GetDay();
  1180.   st.wHour = ct.GetHour();
  1181.   st.wMinute = ct.GetMinute();
  1182.   st.wSecond = ct.GetSecond();
  1183.   st.wMilliseconds = 0;
  1184. FILETIME ft, utcft;
  1185. SystemTimeToFileTime(&st, &ft);
  1186. LocalFileTimeToFileTime(&ft,&utcft);
  1187. return FiletimeToDate(utcft);
  1188. }
  1189. CTime DateToCTime(const __int64 dt)
  1190. {
  1191. return CTime(DateToFiletime(dt));
  1192. }
  1193. __int64 FiletimeToDate(const FILETIME& ft)
  1194. {
  1195. __int64 MyDate = 0;
  1196. MyDate = ft.dwHighDateTime;
  1197. MyDate = MyDate << 32;
  1198. MyDate |= ft.dwLowDateTime;
  1199. return MyDate;
  1200. }
  1201. FILETIME DateToFiletime(const __int64 dt)
  1202. {
  1203. FILETIME ft;
  1204. __int64 MyDate = dt;
  1205. ft.dwLowDateTime = (DWORD)(MyDate & 0xffffffff);
  1206. MyDate = MyDate >> 32;
  1207. ft.dwHighDateTime = (DWORD)MyDate;
  1208. return ft;
  1209. }
  1210. char *Months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
  1211. int GetMonthFromLiteral(LPCSTR Month)
  1212. {
  1213. for(int i = 0; i < 12; i++)
  1214. {
  1215. if (!strnicmp(Months[i], Month, 3))
  1216. return ++i;
  1217. }
  1218. return 1;
  1219. }
  1220. BOOL IsMultiline(LPCSTR Text)
  1221. {
  1222. LPCSTR p = strchr(Text,'r');
  1223. while(p && isspace(*p))
  1224. ++p;
  1225. return p && *p;
  1226. }
  1227. CString PrepereForWnd(LPCSTR Text)
  1228. {
  1229. CString cBuf("");
  1230. ASSERT(AfxIsValidString(Text));
  1231. while(*Text)
  1232. {
  1233. if (*Text == 0x0a)
  1234. cBuf += "rn";
  1235. else if (*Text != 0x0d)
  1236. cBuf += *Text;
  1237. ++Text;
  1238. }
  1239. return cBuf;
  1240. }
  1241. // Map the string so that sprintf( str) can be called
  1242. CString MapStringValid(LPCSTR Text)
  1243. {
  1244. CString cBuf("");
  1245. ASSERT(AfxIsValidString(Text));
  1246. while(*Text)
  1247. {
  1248. if (*Text == '%')
  1249. cBuf += '%';
  1250. cBuf += *Text++;
  1251. }
  1252. return cBuf;
  1253. }