JXINIFile.cpp
上传用户:dengkfang
上传日期:2008-12-30
资源大小:5233k
文件大小:98k
源码类别:

CA认证

开发平台:

Visual C++

  1. /************************************
  2.   REVISION LOG ENTRY
  3.   Written and Revision By: Zhang, Zhefu
  4.   Contact: codetiger@hotmail
  5.   URL: http://www.chi.c.dendai.ac.jp/~zhang/index.htm
  6.   Revised on 2001/09/27 in FujiSoftABC Ltd. Japan
  7.   Comment: JXINIFile Implementation File
  8.  ************************************/
  9. //
  10. //
  11. //Last Modified 2001/9/4
  12. //Reason: NotePad add 0xFF FE to the text file header, make the first
  13. //        section unrecognizable. 
  14. //Fixment: Add member m_pTrueData to pass the 2 byte head
  15. #include "stdAfx.h"
  16. #include "JXIniFile.h"
  17. //dwSize = -1 if szMultiByte null terminated
  18. //dwSize not include the ending null
  19. //return WCHARs
  20. LPWSTR _A2W(LPSTR szMultiByte, DWORD dwSize, DWORD& dwRetSize)
  21. {
  22. static WCHAR szInternalBuffer[8096];
  23. if(szMultiByte == NULL || (dwSize == -1 && ::strlen(szMultiByte) == 0)) 
  24. { dwRetSize = 0; return NULL; }
  25. int nLen = MultiByteToWideChar(CP_ACP, 0,szMultiByte, dwSize, NULL, NULL);
  26. if(nLen > 8096) { dwRetSize = 0; return NULL; } 
  27. //dwRetSize in WCHARs, include null if szMultiByte nulled ended
  28.     dwRetSize = MultiByteToWideChar(CP_ACP, 0, szMultiByte, dwSize, szInternalBuffer, 8096);
  29. if(dwSize == -1)
  30. dwRetSize--;
  31. else
  32.     szInternalBuffer[dwRetSize] = WCHAR('');
  33.     return szInternalBuffer;
  34. }
  35. //return BYTEs
  36. LPSTR _W2A(LPWSTR szUnicode, DWORD dwSize, DWORD& dwRetSize)
  37. {
  38. static char szInternalBuffer[8096];
  39. if(szUnicode == NULL || (dwSize == -1 && ::wcslen(szUnicode) == 0)) 
  40. { dwRetSize = 0; return NULL; }
  41. int nLen = WideCharToMultiByte(CP_ACP, 0,szUnicode, dwSize, NULL, 0, NULL, FALSE);
  42. if(nLen > 8096) { dwRetSize = 0; return NULL; } 
  43. //Ret: in BYTEs, The number includes the byte for the null terminator. if szUnicode null ended
  44. dwRetSize = WideCharToMultiByte(CP_ACP, 0, szUnicode, dwSize, szInternalBuffer, nLen, NULL, FALSE);
  45.     if(dwSize == -1) //dwRetSize include null, szInternalBuffer null ended
  46. dwRetSize--;
  47. else
  48. szInternalBuffer[dwRetSize] = char('');
  49. return szInternalBuffer;
  50. }
  51. CJXINIFile::CJXINIFile() 
  52. {
  53. m_strFilename = _T("");
  54. m_hFile = INVALID_HANDLE_VALUE;
  55. m_hMMF = NULL;
  56. m_dwSize = 0;
  57. m_pData = 0;
  58. m_bSectionMapDirty = TRUE; //No Section Map
  59. m_bSectionMapLock = FALSE;
  60. m_mapSection.InitHashTable(700, TRUE);
  61. }
  62. CJXINIFile::~CJXINIFile()
  63. {
  64. UnloadIniFile();
  65. if(m_pData)
  66. {
  67. ::UnmapViewOfFile(m_pData);
  68. m_pData = NULL;
  69. }
  70. if(m_hMMF != NULL)
  71. {
  72. ::CloseHandle(m_hMMF);
  73. m_hMMF = NULL;
  74. }
  75. if(m_hFile != INVALID_HANDLE_VALUE)
  76. {
  77. ::CloseHandle(m_hFile);
  78. m_hFile = INVALID_HANDLE_VALUE;
  79. }
  80. }
  81. //CMap m_mapSection; 
  82. void CJXINIFile::UpdateMapA()
  83. {
  84. if(m_bSectionMapLock) return;
  85. LPSTR pHead = (LPSTR)m_pTrueData;
  86. LPSTR p1 = pHead;
  87. LPSTR p2 = pHead;
  88. p1 = pHead;
  89.     while(p1- pHead < (int)(m_dwUseSize/sizeof(char)) - 1)
  90. {
  91. while(p1- pHead < (int)(m_dwUseSize/sizeof(char)) - 1 &&
  92. *p1 != char('['))
  93. p1++;
  94. p2 = p1;
  95. while(p2- pHead < (int)(m_dwUseSize/sizeof(char)) - 1 &&
  96. *p2 != char(']'))
  97. p2++;
  98. if(p1- pHead < (int)(m_dwUseSize/sizeof(char)) &&
  99. p2- pHead < (int)(m_dwUseSize/sizeof(char)))
  100. {
  101. //Found, Ready To Map
  102. int lenSection = p2 - p1 - 1;
  103. //Section Name Length must >= 1
  104. if(lenSection >= 1)
  105. {
  106. p1++;
  107. CString strSection;
  108. #ifdef _UNICODE
  109.                 DWORD dwRetSize;
  110. PWSTR pTemp = _A2W(p1, lenSection, dwRetSize);
  111. ::wcsncpy(strSection.GetBuffer(dwRetSize), pTemp, dwRetSize);
  112.                 strSection.ReleaseBuffer(dwRetSize);
  113. #else
  114. ::strncpy(strSection.GetBuffer(lenSection), p1, lenSection);
  115.                 strSection.ReleaseBuffer(lenSection);
  116. #endif
  117. p1--; //point to [
  118. m_mapSection.SetAt(strSection, (LPVOID)p1);
  119. }
  120. p1 = p2 + 1;
  121. }
  122. //Debug Part
  123. m_bSectionMapDirty = FALSE;
  124.     return ;
  125. }
  126. void CJXINIFile::UpdateMapW()
  127. {
  128. if(m_bSectionMapLock) return;
  129. LPWSTR pHead = (LPWSTR)m_pTrueData;
  130. LPWSTR p1 = pHead;
  131. LPWSTR p2 = pHead;
  132.     //Calculate the section number
  133. // int nSection = 0;
  134. //    while(p1- pHead < (int)(m_dwUseSize/sizeof(WCHAR)) - 1)
  135. // {
  136. // if(*p1 == WCHAR('[')) nSection++;
  137. // p1++;
  138. // }
  139. // if(nSection < 13) nSection = 13;
  140. // //allow 20% margine
  141. // m_mapSection.InitHashTable((UINT)(1.2*nSection), TRUE);
  142.     
  143. p1 = pHead;
  144.     while(p1- pHead < (int)(m_dwUseSize/sizeof(WCHAR)) - 1)
  145. {
  146. while(p1- pHead < (int)(m_dwUseSize/sizeof(WCHAR)) - 1 &&
  147. *p1 != WCHAR('['))
  148. p1++;
  149. p2 = p1;
  150. while(p2- pHead < (int)(m_dwUseSize/sizeof(WCHAR)) - 1 &&
  151. *p2 != WCHAR(']'))
  152. p2++;
  153. if(p1- pHead < (int)(m_dwUseSize/sizeof(WCHAR)) &&
  154. p2- pHead < (int)(m_dwUseSize/sizeof(WCHAR)))
  155. {
  156. //Found, Ready To Map
  157. int lenSection = p2 - p1 - 1;
  158. //Section Name Length must >= 1
  159. if(lenSection >= 1)
  160. {
  161. p1++;
  162. CString strSection;
  163. #ifdef _UNICODE
  164. ::wcsncpy(strSection.GetBuffer(lenSection), p1, lenSection);
  165.                 strSection.ReleaseBuffer(lenSection);
  166. #else
  167. DWORD dwRetSize;
  168. PSTR pTemp = _W2A(p1, lenSection, dwRetSize);
  169.                 ::strncpy(strSection.GetBuffer(dwRetSize), pTemp, dwRetSize);
  170.                 strSection.ReleaseBuffer(dwRetSize);
  171. #endif
  172. p1--; //point to [
  173. m_mapSection.SetAt(strSection, (LPVOID)p1);
  174. }
  175. p1 = p2 + 1;
  176. }
  177. //Debug Part
  178. m_bSectionMapDirty = FALSE;
  179. //  int count = m_mapSection.GetCount();
  180. // CString str; str.Format(_T("UpdateW %d"), count); 
  181. // AfxMessageBox(str);
  182. /*
  183. POSITION pos = m_mapSection.GetStartPosition();
  184. while(pos)
  185. {
  186. CString strKey;
  187. LPVOID lpPos;
  188. m_mapSection.GetNextAssoc(pos, strKey, lpPos);
  189. if(AfxMessageBox(strKey, MB_YESNO | MB_ICONINFORMATION) == IDNO)
  190. return;
  191. }
  192. */
  193. return ;
  194. }
  195. void CJXINIFile::ResizeMap(int nNewSize)
  196. {
  197. ASSERT(nNewSize > 0);
  198. m_mapSection.RemoveAll();
  199. m_mapSection.InitHashTable(nNewSize);
  200. }
  201. // return 0 -- no key, size too small to put value
  202. //return -1  -- error
  203. //return string length (of course > 1)
  204. //Ex Version use Map
  205. DWORD CJXINIFile::GetPrivateProfileStringExA(
  206.          LPCSTR lpAppName,        // section name
  207.          LPCSTR lpKeyName,        // key name
  208.          LPCSTR lpDefault,        // default string
  209.          LPSTR lpReturnedString,  // destination buffer
  210.          DWORD nSize,              
  211.  // size of destination buffer,Specifies the size, in TCHARs, 
  212.          LPCSTR lpFileName        // initialization file name
  213.     )
  214. {
  215. BOOL bRet = LoadIniFile(lpFileName, 1);
  216. if(!bRet) return (UINT)-1;
  217. if(lpDefault == NULL) return -1;
  218. if(m_dwUseSize == 0) return -1;
  219. //Section Map Not Available
  220. if(m_bSectionMapDirty && m_bSectionMapLock) //
  221. return GetPrivateProfileStringA(lpAppName,lpKeyName,
  222.    lpDefault,lpReturnedString,nSize,lpFileName);
  223. else if(!m_bSectionMapLock && m_bSectionMapDirty)
  224. {
  225. UpdateMapA();        
  226. }
  227.  
  228. //AfxMessageBox(_T("Using Section Map"));
  229. //Now Map Info Available
  230. if(lpAppName == NULL) //get all section
  231. {
  232. return GetSectionsExA(lpReturnedString, nSize, lpFileName);
  233. }
  234. if(lpKeyName == NULL) //get all key in one section
  235. {
  236. return GetKeysExA(lpAppName, lpReturnedString, nSize, lpFileName);
  237. }
  238. LPSTR pHead = (LPSTR)m_pTrueData;
  239. UINT uSec, uKey;
  240. uSec = (UINT) -1;
  241. uKey = (UINT)-1;
  242. uKey = GetKeyExA(pHead, (UINT)m_dwUseSize, 
  243. lpAppName, lpKeyName, uSec);
  244.     if(uKey == (UINT)-1) //not key
  245. {
  246. if(::strlen(lpDefault) > (int)nSize) return -1;
  247. ::strncpy(lpReturnedString, lpDefault, ::strlen(lpDefault));
  248. //append a null
  249.         lpReturnedString[::strlen(lpDefault)+1] = char('');
  250. return 0;
  251. }
  252. char buffer[MAX_PATH];
  253.     LPSTR pValue = pHead + uKey;
  254. while(pValue - pHead < (int)((m_dwUseSize)/sizeof(char)) && 
  255.  *pValue != char('r') && *pValue != char('n'))
  256. {
  257. pValue++;  //in unicode, +2 byte
  258. }
  259. int len = pValue - pHead - uKey;
  260. pValue = pHead + uKey;
  261. ::strncpy(buffer, pValue, len); 
  262. if(nSize <= (UINT)len)
  263. {
  264. ::strncpy(lpReturnedString, pValue, nSize);
  265.         lpReturnedString[nSize - 1] = char('');
  266. return 0;
  267. }
  268. else
  269. {
  270. ::strncpy(lpReturnedString, pValue, len);
  271. //append null
  272.         lpReturnedString[len] = char('');
  273. return len;
  274. }
  275. return (UINT) -1;
  276. }
  277. // return 0 -- no key, size too small to put value
  278. //return -1  -- error
  279. //return string length (of course > 1)
  280. //Ex Version use Map
  281. DWORD CJXINIFile::GetPrivateProfileStringExW(
  282.          LPCWSTR lpAppName,        // section name
  283.          LPCWSTR lpKeyName,        // key name
  284.          LPCWSTR lpDefault,        // default string
  285.          LPWSTR lpReturnedString,  // destination buffer
  286.          DWORD nSize,              
  287.  // size of destination buffer,Specifies the size, in TCHARs, 
  288.          LPCWSTR lpFileName        // initialization file name
  289.     )
  290. {
  291. BOOL bRet = LoadIniFile(lpFileName, 2);
  292. if(!bRet) return (UINT)-1;
  293. if(lpDefault == NULL) return -1;
  294. if(m_dwUseSize == 0) return -1;
  295. //Section Map Not Available
  296. if(m_bSectionMapDirty && m_bSectionMapLock) //
  297. return GetPrivateProfileStringW(lpAppName,lpKeyName,
  298.    lpDefault,lpReturnedString,nSize,lpFileName);
  299. else if(!m_bSectionMapLock && m_bSectionMapDirty)
  300. {
  301. UpdateMapW();        
  302. }
  303.  
  304. //AfxMessageBox(_T("Using Section Map"));
  305. //Now Map Info Available
  306. if(lpAppName == NULL) //get all section
  307. {
  308. return GetSectionsExW(lpReturnedString, nSize, lpFileName);
  309. }
  310. if(lpKeyName == NULL) //get all key in one section
  311. {
  312. return GetKeysExW(lpAppName, lpReturnedString, nSize, lpFileName);
  313. }
  314. LPWSTR pHead = (LPWSTR)m_pTrueData;
  315. UINT uSec, uKey;
  316. uSec = (UINT) -1;
  317. uKey = (UINT)-1;
  318. uKey = GetKeyExW(pHead, (UINT)m_dwUseSize, 
  319. lpAppName, lpKeyName, uSec);
  320.     if(uKey == (UINT)-1) //not key
  321. {
  322. if(::wcslen(lpDefault) > (int)nSize) return -1;
  323. ::wcsncpy(lpReturnedString, lpDefault, ::wcslen(lpDefault));
  324. //append a null
  325.         lpReturnedString[::wcslen(lpDefault)+1] = WCHAR('');
  326. return 0;
  327. }
  328. WCHAR buffer[MAX_PATH];
  329.     LPWSTR pValue = pHead + uKey;
  330. while(pValue - pHead < (int)((m_dwUseSize)/sizeof(WCHAR)) && 
  331.  *pValue != WCHAR('r') && *pValue != WCHAR('n'))
  332. {
  333. pValue++;  //in unicode, +2 byte
  334. }
  335. int len = pValue - pHead - uKey;
  336. pValue = pHead + uKey;
  337. ::wcsncpy(buffer, pValue, len); 
  338. if(nSize <= (UINT)len)
  339. {
  340. ::wcsncpy(lpReturnedString, pValue, nSize);
  341.         lpReturnedString[nSize - 1] = WCHAR('');
  342. return 0;
  343. }
  344. else
  345. {
  346. ::wcsncpy(lpReturnedString, pValue, len);
  347. //append null
  348.         lpReturnedString[len] = WCHAR('');
  349. return len;
  350. }
  351. return (UINT) -1;
  352. }
  353. //User Query All Section Name in INI File
  354. DWORD CJXINIFile::GetSectionsExA(
  355.          LPSTR lpReturnedString,  // destination buffer
  356.          DWORD nSize, // size of destination buffer, In WCHAR
  357.          LPCSTR lpFileName        // initialization file name
  358.     )
  359. {
  360. ASSERT(!m_bSectionMapDirty);
  361.     BYTE wNULL = 0x00; 
  362. int posRet = 0;
  363. POSITION pos = m_mapSection.GetStartPosition();
  364. while(pos)
  365. {
  366. CString strKey;
  367. LPVOID lpPos;
  368. m_mapSection.GetNextAssoc(pos, strKey, lpPos);
  369. #ifdef _UNICODE
  370. int lenSection = strKey.GetLength();
  371. DWORD dwRetSize;
  372. LPSTR pTemp = _W2A(strKey.GetBuffer(lenSection), lenSection, dwRetSize);
  373. if(dwRetSize + 1 + posRet > (int)nSize) return 0; //nSize - 1;
  374.         ::strncpy(lpReturnedString + posRet, pTemp, dwRetSize);
  375.         posRet += dwRetSize;
  376. #else
  377. int lenSection = strKey.GetLength();
  378. if(lenSection + 1 + posRet > (int)nSize) return 0; //nSize - 1;
  379. ::strncpy(lpReturnedString + posRet, (LPCSTR)strKey, lenSection);
  380.         posRet += lenSection;
  381. #endif
  382. //NULL = 0x00 , 2 Byte
  383. ::memcpy(lpReturnedString + posRet, &wNULL, 1);
  384.         posRet += 1;
  385. }
  386. //last NULL 
  387.     if(1 + posRet > (int)nSize) return 0; //nSize - 1; 
  388.     ::memcpy(lpReturnedString + posRet, &wNULL, 1);
  389. posRet += 1;
  390. return posRet;
  391. }
  392. //User Query All Section Name in INI File
  393. DWORD CJXINIFile::GetSectionsExW(
  394.          LPWSTR lpReturnedString,  // destination buffer
  395.          DWORD nSize, // size of destination buffer, In WCHAR
  396.          LPCWSTR lpFileName        // initialization file name
  397.     )
  398. {
  399. ASSERT(!m_bSectionMapDirty);
  400.     WORD wNULL = 0x0000; 
  401. int posRet = 0;
  402. POSITION pos = m_mapSection.GetStartPosition();
  403. while(pos)
  404. {
  405. CString strKey;
  406. LPVOID lpPos;
  407. m_mapSection.GetNextAssoc(pos, strKey, lpPos);
  408. #ifdef _UNICODE
  409. int lenSection = strKey.GetLength();
  410. if(lenSection + 1 + posRet > (int)nSize) return 0; //nSize - 1;
  411. ::wcsncpy(lpReturnedString + posRet, (LPCWSTR)strKey, lenSection);
  412.         posRet += lenSection;
  413. #else
  414. int lenSection = strKey.GetLength();
  415. DWORD dwRetSize;
  416. PWSTR pTemp = _A2W(strKey.GetBuffer(lenSection), lenSection, dwRetSize);
  417. if(dwRetSize + 1 + posRet > (int)nSize) return 0; //nSize - 1;
  418.         ::wcsncpy(lpReturnedString + posRet, pTemp, dwRetSize);
  419.         posRet += dwRetSize;
  420. #endif
  421. //NULL = 0x00 00, 2 Byte
  422. ::memcpy(lpReturnedString + posRet, &wNULL, 2);
  423.         posRet += 1;
  424. }
  425. //last NULL 
  426.     if(1 + posRet > (int)nSize) return 0; //nSize - 1; 
  427.     ::memcpy(lpReturnedString + posRet, &wNULL, 2);
  428. posRet += 1;
  429. return posRet;
  430. }
  431. //User Query All Keys in a Given Section
  432. DWORD CJXINIFile::GetKeysExA(
  433.  LPCSTR lpAppName,        // section name
  434.          LPSTR lpReturnedString,  // destination buffer
  435.          DWORD nSize,              // size of destination buffer
  436.          LPCSTR lpFileName        // initialization file name
  437.     )
  438. {
  439. int posRet = 0;
  440. int secLen = ::strlen(lpAppName);
  441. LPSTR pHead = (LPSTR)m_pTrueData;
  442. LPSTR pSecHead = NULL; //pointing to [
  443. //Section Map Must be Available
  444. ASSERT(!m_bSectionMapDirty);
  445. #ifdef _UNICODE
  446. DWORD dwRetSize;
  447. LPWSTR pTemp = _A2W((LPSTR)lpAppName, -1, dwRetSize);
  448.     if(0 == m_mapSection.Lookup((LPCWSTR)pTemp, (LPVOID&)pSecHead))
  449. return 0;
  450. #else
  451. if(0 == m_mapSection.Lookup(lpAppName, (LPVOID&)pSecHead))
  452. return 0;
  453. #endif
  454. LPSTR pSecTail = NULL; //point to next [
  455. LPSTR p1 = pSecHead;
  456. LPSTR p2;
  457.         
  458. BYTE wNULL = 0x00; 
  459. while(p1- pHead < (int)(m_dwUseSize/sizeof(char)) - 1)
  460. {
  461. p1++;
  462. if(*p1 == char('['))
  463. {
  464. pSecTail = p1;
  465. break;
  466. }
  467. }
  468. if(pSecHead == NULL) return -1;
  469. if(pSecTail == NULL)
  470. pSecTail = pHead + m_dwUseSize/sizeof(char);
  471. pSecTail--;
  472.     
  473. //Enum Keys in Section
  474.     p1 = pSecHead;
  475. int keyLen;
  476. while(p1 < pSecTail - 1)
  477. {
  478. while(p1 < pSecTail - 1 &&
  479. *p1 != char('r') && *p1 != char('n'))
  480. p1++;
  481. while(p1 < pSecTail - 1 &&
  482. (*p1 == char('r') || *p1 == char('n')))
  483. p1++;
  484. p2 = p1;
  485. while(p2 < pSecTail - 1 &&
  486. *p2 != char('='))
  487. p2++;
  488. if(p1 < pSecTail - 1 && p2 < pSecTail - 1)
  489. {
  490. //Found A Key
  491. keyLen = p2 - p1;
  492. // CString str;
  493. // ::lstrcpyn(str.GetBuffer(keyLen), p1, keyLen);
  494. // str.ReleaseBuffer(keyLen);
  495. // PopMsg(_T("Used %d KeyLen %d, %s"), posRet, keyLen, str);
  496.             
  497. if(keyLen >= 1)
  498. {
  499. if(keyLen + 1 + posRet > (int)nSize) 
  500. {
  501. //PopMsg(_T("You Want Fetch Sections, Buffer %d, Keylen %d, Used %d, in %s"),
  502. // nSize, keyLen, posRet, m_strFilename);
  503. return 0; //nSize - 1;
  504. }
  505. ::strncpy(lpReturnedString + posRet, p1, keyLen);
  506.                 posRet += keyLen;
  507. //NULL = 0x00 , 1 Byte
  508. ::memcpy(lpReturnedString + posRet, &wNULL, 1);
  509.                 posRet += 1;
  510. }
  511. }
  512. p1 = p2 + 1;
  513. }
  514. //last NULL 
  515. //PopMsg(_T("%d"), posRet);
  516.     if(1 + posRet > (int)nSize) return 0; //nSize - 1; 
  517.     ::memcpy(lpReturnedString + posRet, &wNULL, 1);
  518. posRet += 1;
  519. return posRet;
  520. }
  521. //User Query All Keys in a Given Section
  522. DWORD CJXINIFile::GetKeysExW(
  523.  LPCWSTR lpAppName,        // section name
  524.          LPWSTR lpReturnedString,  // destination buffer
  525.          DWORD nSize,              // size of destination buffer
  526.          LPCWSTR lpFileName        // initialization file name
  527.     )
  528. {
  529. int posRet = 0;
  530. int secLen = ::wcslen(lpAppName);
  531. LPWSTR pHead = (LPWSTR)m_pTrueData;
  532. LPWSTR pSecHead = NULL; //pointing to [
  533. //Section Map Must be Available
  534. ASSERT(!m_bSectionMapDirty);
  535. #ifdef _UNICODE
  536. if(0 == m_mapSection.Lookup(lpAppName, (LPVOID&)pSecHead))
  537. return 0;
  538. #else
  539. DWORD dwRetSize;
  540. PSTR pTemp = _W2A((LPWSTR)lpAppName, -1, dwRetSize);
  541.     if(0 == m_mapSection.Lookup((LPCSTR)pTemp, (LPVOID&)pSecHead))
  542. return 0;
  543. #endif
  544. LPWSTR pSecTail = NULL; //point to next [
  545. LPWSTR p1 = pSecHead;
  546. LPWSTR p2;
  547.         
  548. WORD wNULL = 0x0000; 
  549. while(p1- pHead < (int)(m_dwUseSize/sizeof(WCHAR)) - 1)
  550. {
  551. p1++;
  552. if(*p1 == WCHAR('['))
  553. {
  554. pSecTail = p1;
  555. break;
  556. }
  557. }
  558. if(pSecHead == NULL) return -1;
  559. if(pSecTail == NULL)
  560. pSecTail = pHead + m_dwUseSize/sizeof(WCHAR);
  561. pSecTail--;
  562.     
  563. //Enum Keys in Section
  564.     p1 = pSecHead;
  565. int keyLen;
  566. while(p1 < pSecTail - 1)
  567. {
  568. while(p1 < pSecTail - 1 &&
  569. *p1 != WCHAR('r') && *p1 != WCHAR('n'))
  570. p1++;
  571. while(p1 < pSecTail - 1 &&
  572. (*p1 == WCHAR('r') || *p1 == WCHAR('n')))
  573. p1++;
  574. p2 = p1;
  575. while(p2 < pSecTail - 1 &&
  576. *p2 != WCHAR('='))
  577. p2++;
  578. if(p1 < pSecTail - 1 && p2 < pSecTail - 1)
  579. {
  580. //Found A Key
  581. keyLen = p2 - p1;
  582. // CString str;
  583. // ::lstrcpyn(str.GetBuffer(keyLen), p1, keyLen);
  584. // str.ReleaseBuffer(keyLen);
  585. // PopMsg(_T("Used %d KeyLen %d, %s"), posRet, keyLen, str);
  586.             
  587. if(keyLen >= 1)
  588. {
  589. if(keyLen + 1 + posRet > (int)nSize) 
  590. {
  591. //PopMsg(_T("You Want Fetch Sections, Buffer %d, Keylen %d, Used %d, in %s"),
  592. // nSize, keyLen, posRet, m_strFilename);
  593. return 0; //nSize - 1;
  594. }
  595. ::wcsncpy(lpReturnedString + posRet, p1, keyLen);
  596.                 posRet += keyLen;
  597. //NULL = 0x00 00, 2 Byte
  598. ::memcpy(lpReturnedString + posRet, &wNULL, 2);
  599.                 posRet += 1;
  600. }
  601. }
  602. p1 = p2 + 1;
  603. }
  604. //last NULL 
  605. //PopMsg(_T("%d"), posRet);
  606.     if(1 + posRet > (int)nSize) return 0; //nSize - 1; 
  607.     ::memcpy(lpReturnedString + posRet, &wNULL, 2);
  608. posRet += 1;
  609. return posRet;
  610. }
  611. // return 0 -- no key, size too small to put value
  612. //return -1  -- error
  613. //return string length (of course > 1)
  614. DWORD CJXINIFile::GetPrivateProfileStringW(
  615.          LPCWSTR lpAppName,        // section name
  616.          LPCWSTR lpKeyName,        // key name
  617.          LPCWSTR lpDefault,        // default string
  618.          LPWSTR lpReturnedString,  // destination buffer
  619.          DWORD nSize,              
  620.  // size of destination buffer,Specifies the size, in TCHARs, 
  621.          LPCWSTR lpFileName        // initialization file name
  622.     )
  623. {
  624. BOOL bRet = LoadIniFile(lpFileName, 2);
  625. if(!bRet) return (UINT)-1;
  626. if(lpDefault == NULL) return -1;
  627. if(m_dwUseSize == 0) return -1;
  628. if(lpAppName == NULL)
  629. return GetSectionsW(lpReturnedString, nSize, lpFileName);
  630. if(lpKeyName == NULL)
  631. return GetKeysW(lpAppName, lpReturnedString, nSize, lpFileName);
  632. LPWSTR pHead = (LPWSTR)m_pTrueData;
  633. UINT uSec, uKey;
  634. uSec = (UINT) -1;
  635. uKey = (UINT)-1;
  636. uKey = GetKeyW(pHead, (UINT)m_dwUseSize, 
  637. lpAppName, lpKeyName, uSec);
  638.     if(uKey == (UINT)-1) //not key
  639. {
  640. if(::wcslen(lpDefault) > (int)nSize) return -1;
  641. ::wcsncpy(lpReturnedString, lpDefault, ::wcslen(lpDefault));
  642. //append a null
  643.         lpReturnedString[::wcslen(lpDefault)+1] = WCHAR('');
  644. return 0;
  645. }
  646. WCHAR buffer[MAX_PATH];
  647.     LPWSTR pValue = pHead + uKey;
  648. while(pValue - pHead < (int)((m_dwUseSize)/sizeof(WCHAR)) && 
  649.  *pValue != WCHAR('r') && *pValue != WCHAR('n'))
  650. {
  651. pValue++;  //in unicode, +2 byte
  652. }
  653. int len = pValue - pHead - uKey;
  654. pValue = pHead + uKey;
  655. ::wcsncpy(buffer, pValue, len); 
  656. if(nSize <= (UINT)len)
  657. {
  658. ::wcsncpy(lpReturnedString, pValue, nSize);
  659.         lpReturnedString[nSize - 1] = WCHAR('');
  660. return 0;
  661. }
  662. else
  663. {
  664. ::wcsncpy(lpReturnedString, pValue, len);
  665. //append null
  666.         lpReturnedString[len] = WCHAR('');
  667. return len;
  668. }
  669. return (UINT) -1;
  670. }
  671. BOOL CJXINIFile::WritePrivateProfileStringExA(
  672.          LPCSTR lpAppName,  // section name
  673.          LPCSTR lpKeyName,  // key name
  674.          LPCSTR lpString,   // string to add
  675.          LPCSTR lpFileName  // initialization file
  676.     )
  677. {
  678. BOOL bRet = this->LoadIniFile(lpFileName, 1);
  679. if(!bRet) return FALSE;
  680. m_bDirty = TRUE;
  681. if(lpKeyName == NULL)
  682. return DeleteSectionExA(lpAppName);
  683. else if(lpString == NULL)
  684. return this->DeleteKeyExA(lpAppName, lpKeyName);
  685. LPSTR pHead = (LPSTR)m_pTrueData;
  686. //2001/10/19 if lpString.len > MAX_PATH error 
  687. //WCHAR buffer[MAX_PATH];
  688. LPSTR buffer = NULL;
  689. UINT uSec, uKey;  
  690. //Warning: uKey, uSec is measured in WCHARs!!!!!
  691. //in UNICODE now
  692. if(!m_bSectionMapDirty)
  693. uKey = GetKeyExA(pHead, (UINT)m_dwUseSize, 
  694.    lpAppName, lpKeyName, uSec);
  695. else if(!m_bSectionMapLock)
  696. {
  697. UpdateMapA();
  698. uKey = GetKeyExA(pHead, (UINT)m_dwUseSize, 
  699.    lpAppName, lpKeyName, uSec);
  700. }
  701. else
  702.         uKey = GetKeyA(pHead, (UINT)m_dwUseSize, 
  703.    lpAppName, lpKeyName, uSec);
  704.     if(uKey == (UINT)-1 && uSec == (UINT)-1) //no section
  705. {
  706. int len = strlen(lpAppName) + strlen(lpKeyName) + strlen(lpString);
  707. len += 7;
  708. buffer = new char[len+1];
  709. ::sprintf(buffer, "[%s]rn%s=%srn", lpAppName, lpKeyName, lpString);
  710. buffer[len] = 0;
  711. LPSTR pStr = pHead;
  712. pStr += m_dwUseSize/sizeof(char);
  713. ::memcpy(pStr, buffer, len*sizeof(char));
  714. m_dwUseSize += len*sizeof(char);
  715. delete []buffer;
  716. buffer = NULL;
  717.         
  718. CString strSection;
  719. #ifdef _UNICODE
  720. DWORD dwRetSize;
  721. LPWSTR pTemp = _A2W((LPSTR)lpAppName, -1, dwRetSize);
  722.         ::wcsncpy(strSection.GetBuffer(dwRetSize), pTemp, dwRetSize);
  723. strSection.ReleaseBuffer(dwRetSize);
  724. #else
  725. strSection = lpAppName;
  726. #endif
  727. if(!m_bSectionMapLock)
  728. {
  729. m_mapSection.SetAt(strSection, (LPVOID)pStr);
  730. }
  731. else
  732. m_bSectionMapDirty = TRUE;
  733. //No Change //m_bSectionMapDirty = ;
  734. bRet = TRUE;
  735. }
  736. else if(uKey == (UINT)-1 && uSec != (UINT)-1) 
  737. //section exist but value do not exist
  738. {
  739. // Following Write Just After [section],
  740. //that new item become the first of the section
  741.         //$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
  742. //$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
  743. /*
  744. LPWSTR pSection = pHead + uSec;
  745. while(pSection - pHead < (int)(m_dwUseSize/sizeof(WCHAR)) && 
  746.       *pSection != WCHAR('r') && *pSection != WCHAR('n'))
  747. {
  748. pSection++;
  749. }
  750.      while(*pSection == WCHAR('r') || *pSection == WCHAR('n'))
  751. pSection++;
  752. UINT uMoveHead = (UINT)(pSection - pHead); 
  753.         //move memory
  754. ::swprintf(buffer, L"%s=%srn", lpKeyName, lpString);
  755. int len = ::wcslen(buffer);
  756. //also ok
  757. //::memmove(pHead + uMoveHead + len, pHead + uMoveHead, m_dwUseSize-uMoveHead*sizeof(WCHAR));
  758. for(int i = (int)(m_dwUseSize - sizeof(WCHAR)); 
  759.     i >= (int)(uMoveHead*sizeof(WCHAR)); i -= sizeof(WCHAR))
  760. {
  761. ::memcpy(pHead + i/sizeof(WCHAR) + len, 
  762. pHead + i/sizeof(WCHAR), sizeof(WCHAR));
  763. }
  764. */
  765. //Following Write new item the last item in the section
  766.         //$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
  767. //$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
  768.         LPSTR pSection = pHead + uSec + 1;
  769. while(pSection - pHead < (int)(m_dwUseSize/sizeof(char)) && 
  770.       *pSection != char('['))
  771. {
  772. pSection++;
  773. }
  774. // ::swprintf(buffer, L"%s=%srn", lpKeyName, lpString);
  775. // int len = ::wcslen(buffer);
  776. int len = strlen(lpKeyName) + strlen(lpString);
  777. len += 3;
  778. buffer = new char[len+1];
  779. ::sprintf(buffer, "%s=%srn", lpKeyName, lpString);
  780. buffer[len] = 0;
  781.      if(pSection - pHead == (int)(m_dwUseSize/sizeof(char)))
  782. {
  783. //no move needed, file end
  784. //no need to Update Section map
  785. }
  786. else
  787. {
  788. UINT uMoveHead = (UINT)(pSection - pHead); 
  789.             //move memory
  790.     //also ok
  791.     //::memmove(pHead + uMoveHead + len, pHead + uMoveHead, m_dwUseSize-uMoveHead*sizeof(WCHAR));
  792.     for(int i = (int)(m_dwUseSize - sizeof(char)); 
  793.        i >= (int)(uMoveHead*sizeof(char)); i -= sizeof(char))
  794. {
  795.    ::memcpy(pHead + i/sizeof(char) + len, 
  796.      pHead + i/sizeof(char), sizeof(char));
  797. }
  798. if(m_bSectionMapLock)
  799. m_bSectionMapDirty = TRUE;
  800. }
  801. else //update section map
  802. {
  803. POSITION pos = m_mapSection.GetStartPosition();
  804.             while(pos)
  805. {
  806. CString strKey;
  807.             LPVOID lpPos;
  808.             m_mapSection.GetNextAssoc(pos, strKey, lpPos);
  809. //adjust Section Map
  810.     if((LPSTR)lpPos - pSection > 0)
  811. {
  812. LPWSTR pTemp = (LPWSTR)lpPos;
  813. pTemp += len;
  814. lpPos = (LPVOID)pTemp;
  815. m_mapSection.SetAt(strKey, lpPos);
  816. }
  817. }
  818. }
  819. }
  820. ::memcpy(pSection, buffer, sizeof(char)*len);
  821. m_dwUseSize += len*sizeof(char);
  822. delete buffer;
  823. buffer = NULL;
  824. bRet = TRUE;
  825. }
  826. else //key exist
  827. {
  828. ASSERT(uKey != (UINT)-1);
  829.         LPSTR pValue = pHead + uKey;
  830.     while(pValue - pHead < (int)(m_dwUseSize/sizeof(char)) && 
  831.     *pValue != char('r') && *pValue != char('n'))
  832. {
  833. pValue++;
  834. }
  835.     while(*pValue == char('r') || *pValue == char('n'))
  836. pValue++;
  837. UINT uMoveHead = (UINT)(pValue - pHead);
  838. UINT uPrevLen = uMoveHead - uKey;
  839. int len = strlen(lpString);
  840. len += 2;
  841. buffer = new char[len+1];
  842. ::sprintf(buffer, "%srn", lpString);
  843.         buffer[len] = 0;
  844. UINT uCurLen = len;
  845.         //move have 2 direction
  846. if(uCurLen > uPrevLen)
  847. {
  848. int charDiff = uCurLen - uPrevLen;
  849. int begin = (int)(m_dwUseSize - sizeof(char));
  850. int end = (int)uMoveHead*sizeof(char);
  851. for(int i = begin; i >= end; i -= sizeof(char))
  852. {
  853. ::memcpy(pHead + i/sizeof(char) + charDiff,
  854. pHead + i/sizeof(char), sizeof(char));
  855. }
  856. if(m_bSectionMapLock)
  857. m_bSectionMapDirty = TRUE;
  858. else //update section map
  859. {
  860. POSITION pos = m_mapSection.GetStartPosition();
  861.             while(pos)
  862. {
  863. CString strKey;
  864.             LPVOID lpPos;
  865.             m_mapSection.GetNextAssoc(pos, strKey, lpPos);
  866. //adjust Section Map
  867.     if((LPSTR)lpPos - pHead > (int)uMoveHead)
  868. {
  869. LPSTR pTemp = (LPSTR)lpPos;
  870. pTemp += charDiff;
  871. lpPos = (LPVOID)pTemp;
  872. m_mapSection.SetAt(strKey, lpPos);
  873. }
  874. }
  875. }
  876. }
  877. else if(uCurLen < uPrevLen)
  878. {
  879. int charDiff = uPrevLen - uCurLen;
  880. int begin = (int)uMoveHead*sizeof(char);
  881. int end = (int)(m_dwUseSize - sizeof(char));
  882. for(int i = begin; i <= end;  i+=sizeof(char))
  883. {
  884. ::memcpy(pHead + i/sizeof(char) - charDiff,
  885. pHead + i/sizeof(char), sizeof(char));
  886. }
  887. if(m_bSectionMapLock)
  888. m_bSectionMapDirty = TRUE;
  889. else //update section map
  890. {
  891. POSITION pos = m_mapSection.GetStartPosition();
  892.             while(pos)
  893. {
  894. CString strKey;
  895.             LPVOID lpPos;
  896.             m_mapSection.GetNextAssoc(pos, strKey, lpPos);
  897. //adjust Section Map
  898.     if((LPSTR)lpPos - pHead > (int)uMoveHead)
  899. {
  900. LPSTR pTemp = (LPSTR)lpPos;
  901. pTemp -= charDiff;
  902. lpPos = (LPVOID)pTemp;
  903. m_mapSection.SetAt(strKey, lpPos);
  904. }
  905. }
  906. }
  907. }
  908. pValue = pHead + uKey;
  909. ::memcpy(pValue, buffer, sizeof(char)*uCurLen);
  910.         m_dwUseSize += (uCurLen-uPrevLen)*sizeof(char);
  911. delete buffer;
  912. buffer = NULL;
  913.         bRet = TRUE;
  914. }
  915. if(!bRet) 
  916. {
  917. UnloadIniFile();
  918. return FALSE;
  919. }
  920. //If the File is large enough, flush the file
  921. if((int)(m_dwUseSize - m_dwSize) > JXFlushIncrement - 5*JXPage)
  922. {
  923. //Flush Back to HardDisk
  924. UnloadIniFile();
  925. }
  926. return TRUE;
  927. }
  928. BOOL CJXINIFile::WritePrivateProfileStringExW(
  929.          LPCWSTR lpAppName,  // section name
  930.          LPCWSTR lpKeyName,  // key name
  931.          LPCWSTR lpString,   // string to add
  932.          LPCWSTR lpFileName  // initialization file
  933.     )
  934. {
  935. BOOL bRet = this->LoadIniFile(lpFileName, 2);
  936. if(!bRet) return FALSE;
  937. m_bDirty = TRUE;
  938. if(lpKeyName == NULL)
  939. return DeleteSectionExW(lpAppName);
  940. else if(lpString == NULL)
  941. return this->DeleteKeyExW(lpAppName, lpKeyName);
  942. LPWSTR pHead = (LPWSTR)m_pTrueData;
  943. //2001/10/19 if lpString.len > MAX_PATH error 
  944. //WCHAR buffer[MAX_PATH];
  945. LPWSTR buffer = NULL;
  946. UINT uSec, uKey;  
  947. //Warning: uKey, uSec is measured in WCHARs!!!!!
  948. //in UNICODE now
  949. if(!m_bSectionMapDirty)
  950. uKey = GetKeyExW(pHead, (UINT)m_dwUseSize, 
  951.    lpAppName, lpKeyName, uSec);
  952. else if(!m_bSectionMapLock)
  953. {
  954. UpdateMapW();
  955. uKey = GetKeyExW(pHead, (UINT)m_dwUseSize, 
  956.    lpAppName, lpKeyName, uSec);
  957. }
  958. else
  959.         uKey = GetKeyW(pHead, (UINT)m_dwUseSize, 
  960.    lpAppName, lpKeyName, uSec);
  961.     if(uKey == (UINT)-1 && uSec == (UINT)-1) //no section
  962. {
  963. int len = wcslen(lpAppName) + wcslen(lpKeyName) +wcslen(lpString);
  964. len += 7;
  965. buffer = new WCHAR[len+1];
  966. ::swprintf(buffer, L"[%s]rn%s=%srn", lpAppName, lpKeyName, lpString);
  967. buffer[len] = 0;
  968. LPWSTR pStr = pHead;
  969. pStr += m_dwUseSize/sizeof(WCHAR);
  970. ::memcpy(pStr, buffer, len*sizeof(WCHAR));
  971. m_dwUseSize += len*sizeof(WCHAR);
  972. delete []buffer;
  973. buffer = NULL;
  974.         
  975. CString strSection;
  976. #ifdef _UNICODE
  977. strSection = lpAppName;
  978. #else
  979. DWORD dwRetSize;
  980. LPSTR pTemp = _W2A((LPWSTR)lpAppName, -1, dwRetSize);
  981.         ::strncpy(strSection.GetBuffer(dwRetSize), pTemp, dwRetSize);
  982. strSection.ReleaseBuffer(dwRetSize);
  983. #endif
  984. if(!m_bSectionMapLock)
  985. {
  986. m_mapSection.SetAt(strSection, (LPVOID)pStr);
  987. }
  988. else
  989. m_bSectionMapDirty = TRUE;
  990. //No Change //m_bSectionMapDirty = ;
  991. bRet = TRUE;
  992. }
  993. else if(uKey == (UINT)-1 && uSec != (UINT)-1) 
  994. //section exist but value do not exist
  995. {
  996. // Following Write Just After [section],
  997. //that new item become the first of the section
  998.         //$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
  999. //$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
  1000. /*
  1001. LPWSTR pSection = pHead + uSec;
  1002. while(pSection - pHead < (int)(m_dwUseSize/sizeof(WCHAR)) && 
  1003.       *pSection != WCHAR('r') && *pSection != WCHAR('n'))
  1004. {
  1005. pSection++;
  1006. }
  1007.      while(*pSection == WCHAR('r') || *pSection == WCHAR('n'))
  1008. pSection++;
  1009. UINT uMoveHead = (UINT)(pSection - pHead); 
  1010.         //move memory
  1011. ::swprintf(buffer, L"%s=%srn", lpKeyName, lpString);
  1012. int len = ::wcslen(buffer);
  1013. //also ok
  1014. //::memmove(pHead + uMoveHead + len, pHead + uMoveHead, m_dwUseSize-uMoveHead*sizeof(WCHAR));
  1015. for(int i = (int)(m_dwUseSize - sizeof(WCHAR)); 
  1016.     i >= (int)(uMoveHead*sizeof(WCHAR)); i -= sizeof(WCHAR))
  1017. {
  1018. ::memcpy(pHead + i/sizeof(WCHAR) + len, 
  1019. pHead + i/sizeof(WCHAR), sizeof(WCHAR));
  1020. }
  1021. */
  1022. //Following Write new item the last item in the section
  1023.         //$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
  1024. //$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
  1025.         LPWSTR pSection = pHead + uSec + 1;
  1026. while(pSection - pHead < (int)(m_dwUseSize/sizeof(WCHAR)) && 
  1027.       *pSection != WCHAR('['))
  1028. {
  1029. pSection++;
  1030. }
  1031. // ::swprintf(buffer, L"%s=%srn", lpKeyName, lpString);
  1032. // int len = ::wcslen(buffer);
  1033. int len = wcslen(lpKeyName) + wcslen(lpString);
  1034. len += 3;
  1035. buffer = new WCHAR[len+1];
  1036. ::swprintf(buffer, L"%s=%srn", lpKeyName, lpString);
  1037. buffer[len] = 0;
  1038.      if(pSection - pHead == (int)(m_dwUseSize/sizeof(WCHAR)))
  1039. {
  1040. //no move needed, file end
  1041. //no need to Update Section map
  1042. }
  1043. else
  1044. {
  1045. UINT uMoveHead = (UINT)(pSection - pHead); 
  1046.             //move memory
  1047.     //also ok
  1048.     //::memmove(pHead + uMoveHead + len, pHead + uMoveHead, m_dwUseSize-uMoveHead*sizeof(WCHAR));
  1049.     for(int i = (int)(m_dwUseSize - sizeof(WCHAR)); 
  1050.        i >= (int)(uMoveHead*sizeof(WCHAR)); i -= sizeof(WCHAR))
  1051. {
  1052.    ::memcpy(pHead + i/sizeof(WCHAR) + len, 
  1053.      pHead + i/sizeof(WCHAR), sizeof(WCHAR));
  1054. }
  1055. if(m_bSectionMapLock)
  1056. m_bSectionMapDirty = TRUE;
  1057. }
  1058. else //update section map
  1059. {
  1060. POSITION pos = m_mapSection.GetStartPosition();
  1061.             while(pos)
  1062. {
  1063. CString strKey;
  1064.             LPVOID lpPos;
  1065.             m_mapSection.GetNextAssoc(pos, strKey, lpPos);
  1066. //adjust Section Map
  1067.     if((LPWSTR)lpPos - pSection > 0)
  1068. {
  1069. LPWSTR pTemp = (LPWSTR)lpPos;
  1070. pTemp += len;
  1071. lpPos = (LPVOID)pTemp;
  1072. m_mapSection.SetAt(strKey, lpPos);
  1073. }
  1074. }
  1075. }
  1076. }
  1077. ::memcpy(pSection, buffer, sizeof(WCHAR)*len);
  1078. m_dwUseSize += len*sizeof(WCHAR);
  1079. delete buffer;
  1080. buffer = NULL;
  1081. bRet = TRUE;
  1082. }
  1083. else //key exist
  1084. {
  1085. ASSERT(uKey != (UINT)-1);
  1086.         LPWSTR pValue = pHead + uKey;
  1087.     while(pValue - pHead < (int)(m_dwUseSize/sizeof(WCHAR)) && 
  1088.     *pValue != WCHAR('r') && *pValue != WCHAR('n'))
  1089. {
  1090. pValue++;
  1091. }
  1092.     while(*pValue == WCHAR('r') || *pValue == WCHAR('n'))
  1093. pValue++;
  1094. UINT uMoveHead = (UINT)(pValue - pHead);
  1095. UINT uPrevLen = uMoveHead - uKey;
  1096. int len = wcslen(lpString);
  1097. len += 2;
  1098. buffer = new WCHAR[len+1];
  1099. ::swprintf(buffer, L"%srn", lpString);
  1100.         buffer[len] = 0;
  1101. UINT uCurLen = len;
  1102.         //move have 2 direction
  1103. if(uCurLen > uPrevLen)
  1104. {
  1105. int charDiff = uCurLen - uPrevLen;
  1106. int begin = (int)(m_dwUseSize - sizeof(WCHAR));
  1107. int end = (int)uMoveHead*sizeof(WCHAR);
  1108. for(int i = begin; i >= end; i -= sizeof(WCHAR))
  1109. {
  1110. ::memcpy(pHead + i/sizeof(WCHAR) + charDiff,
  1111. pHead + i/sizeof(WCHAR), sizeof(WCHAR));
  1112. }
  1113. if(m_bSectionMapLock)
  1114. m_bSectionMapDirty = TRUE;
  1115. else //update section map
  1116. {
  1117. POSITION pos = m_mapSection.GetStartPosition();
  1118.             while(pos)
  1119. {
  1120. CString strKey;
  1121.             LPVOID lpPos;
  1122.             m_mapSection.GetNextAssoc(pos, strKey, lpPos);
  1123. //adjust Section Map
  1124.     if((LPWSTR)lpPos - pHead > (int)uMoveHead)
  1125. {
  1126. LPWSTR pTemp = (LPWSTR)lpPos;
  1127. pTemp += charDiff;
  1128. lpPos = (LPVOID)pTemp;
  1129. m_mapSection.SetAt(strKey, lpPos);
  1130. }
  1131. }
  1132. }
  1133. }
  1134. else if(uCurLen < uPrevLen)
  1135. {
  1136. int charDiff = uPrevLen - uCurLen;
  1137. int begin = (int)uMoveHead*sizeof(WCHAR);
  1138. int end = (int)(m_dwUseSize - sizeof(WCHAR));
  1139. for(int i = begin; i <= end;  i+=sizeof(WCHAR))
  1140. {
  1141. ::memcpy(pHead + i/sizeof(WCHAR) - charDiff,
  1142. pHead + i/sizeof(WCHAR), sizeof(WCHAR));
  1143. }
  1144. if(m_bSectionMapLock)
  1145. m_bSectionMapDirty = TRUE;
  1146. else //update section map
  1147. {
  1148. POSITION pos = m_mapSection.GetStartPosition();
  1149.             while(pos)
  1150. {
  1151. CString strKey;
  1152.             LPVOID lpPos;
  1153.             m_mapSection.GetNextAssoc(pos, strKey, lpPos);
  1154. //adjust Section Map
  1155.     if((LPWSTR)lpPos - pHead > (int)uMoveHead)
  1156. {
  1157. LPWSTR pTemp = (LPWSTR)lpPos;
  1158. pTemp -= charDiff;
  1159. lpPos = (LPVOID)pTemp;
  1160. m_mapSection.SetAt(strKey, lpPos);
  1161. }
  1162. }
  1163. }
  1164. }
  1165. pValue = pHead + uKey;
  1166. ::memcpy(pValue, buffer, sizeof(WCHAR)*uCurLen);
  1167.         m_dwUseSize += (uCurLen-uPrevLen)*sizeof(WCHAR);
  1168. delete buffer;
  1169. buffer = NULL;
  1170.         bRet = TRUE;
  1171. }
  1172. if(!bRet) 
  1173. {
  1174. UnloadIniFile();
  1175. return FALSE;
  1176. }
  1177. //If the File is large enough, flush the file
  1178. if((int)(m_dwUseSize - m_dwSize) > JXFlushIncrement - 5*JXPage)
  1179. {
  1180. //Flush Back to HardDisk
  1181. UnloadIniFile();
  1182. }
  1183. return TRUE;
  1184. }
  1185. BOOL CJXINIFile::WritePrivateProfileStringW(
  1186.          LPCWSTR lpAppName,  // section name
  1187.          LPCWSTR lpKeyName,  // key name
  1188.          LPCWSTR lpString,   // string to add
  1189.          LPCWSTR lpFileName  // initialization file
  1190.     )
  1191. {
  1192. BOOL bRet = this->LoadIniFile(lpFileName, 2);
  1193. if(!bRet) return FALSE;
  1194. m_bDirty = TRUE;
  1195. if(lpKeyName == NULL)
  1196. return DeleteSectionW(lpAppName);
  1197. else if(lpString == NULL)
  1198. return this->DeleteKeyW(lpAppName, lpKeyName);
  1199. LPWSTR pHead = (LPWSTR)m_pTrueData;
  1200. //2001/10/19 if lpString.len > MAX_PATH error 
  1201. //WCHAR buffer[MAX_PATH];
  1202. LPWSTR buffer = NULL;
  1203. UINT uSec, uKey;  
  1204. //Warning: uKey, uSec is measured in WCHARs!!!!!
  1205. //in UNICODE now
  1206. uKey = GetKeyW(pHead, (UINT)m_dwUseSize, 
  1207. lpAppName, lpKeyName, uSec);
  1208.     if(uKey == (UINT)-1 && uSec == (UINT)-1) //no section
  1209. {
  1210. // ::swprintf(buffer, L"[%s]rn%s=%srn", lpAppName, lpKeyName, lpString);
  1211. // int len = ::wcslen(buffer);
  1212. // LPWSTR pStr = pHead;
  1213. // pStr += m_dwUseSize/sizeof(WCHAR);
  1214. // ::memcpy(pStr, buffer, len*sizeof(WCHAR));
  1215. // m_dwUseSize += len*sizeof(WCHAR);
  1216. int len = wcslen(lpAppName) + wcslen(lpKeyName) +wcslen(lpString);
  1217. len += 7;
  1218. buffer = new WCHAR[len+1];
  1219. ::swprintf(buffer, L"[%s]rn%s=%srn", lpAppName, lpKeyName, lpString);
  1220. buffer[len] = 0;
  1221. LPWSTR pStr = pHead;
  1222. pStr += m_dwUseSize/sizeof(WCHAR);
  1223. ::memcpy(pStr, buffer, len*sizeof(WCHAR));
  1224. m_dwUseSize += len*sizeof(WCHAR);
  1225. delete []buffer;
  1226. buffer = NULL;
  1227. bRet = TRUE;
  1228. }
  1229. else if(uKey == (UINT)-1 && uSec != (UINT)-1) 
  1230. //section exist but value do not exist
  1231. {
  1232. // Following Write Just After [section],
  1233. //that new item become the first of the section
  1234.         //$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
  1235. //$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
  1236. /*
  1237. LPWSTR pSection = pHead + uSec;
  1238. while(pSection - pHead < (int)(m_dwUseSize/sizeof(WCHAR)) && 
  1239.       *pSection != WCHAR('r') && *pSection != WCHAR('n'))
  1240. {
  1241. pSection++;
  1242. }
  1243.      while(*pSection == WCHAR('r') || *pSection == WCHAR('n'))
  1244. pSection++;
  1245. UINT uMoveHead = (UINT)(pSection - pHead); 
  1246.         //move memory
  1247. ::swprintf(buffer, L"%s=%srn", lpKeyName, lpString);
  1248. int len = ::wcslen(buffer);
  1249. //also ok
  1250. //::memmove(pHead + uMoveHead + len, pHead + uMoveHead, m_dwUseSize-uMoveHead*sizeof(WCHAR));
  1251. for(int i = (int)(m_dwUseSize - sizeof(WCHAR)); 
  1252.     i >= (int)(uMoveHead*sizeof(WCHAR)); i -= sizeof(WCHAR))
  1253. {
  1254. ::memcpy(pHead + i/sizeof(WCHAR) + len, 
  1255. pHead + i/sizeof(WCHAR), sizeof(WCHAR));
  1256. }
  1257. */
  1258. //Following Write new item the last item in the section
  1259.         //$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
  1260. //$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
  1261.         LPWSTR pSection = pHead + uSec + 1;
  1262. while(pSection - pHead < (int)(m_dwUseSize/sizeof(WCHAR)) && 
  1263.       *pSection != WCHAR('['))
  1264. {
  1265. pSection++;
  1266. }
  1267. // ::swprintf(buffer, L"%s=%srn", lpKeyName, lpString);
  1268. // int len = ::wcslen(buffer);
  1269. int len = wcslen(lpKeyName) + wcslen(lpString);
  1270. len += 3;
  1271. buffer = new WCHAR[len+1];
  1272. ::swprintf(buffer, L"%s=%srn", lpKeyName, lpString);
  1273. buffer[len] = 0;
  1274.      if(pSection - pHead == (int)(m_dwUseSize/sizeof(WCHAR)))
  1275. {
  1276. //no move needed, file end
  1277. }
  1278. else
  1279. {
  1280. UINT uMoveHead = (UINT)(pSection - pHead); 
  1281.             //move memory
  1282.     //also ok
  1283.     //::memmove(pHead + uMoveHead + len, pHead + uMoveHead, m_dwUseSize-uMoveHead*sizeof(WCHAR));
  1284.     for(int i = (int)(m_dwUseSize - sizeof(WCHAR)); 
  1285.        i >= (int)(uMoveHead*sizeof(WCHAR)); i -= sizeof(WCHAR))
  1286. {
  1287.    ::memcpy(pHead + i/sizeof(WCHAR) + len, 
  1288.      pHead + i/sizeof(WCHAR), sizeof(WCHAR));
  1289. }
  1290. }
  1291. ::memcpy(pSection, buffer, sizeof(WCHAR)*len);
  1292. m_dwUseSize += len*sizeof(WCHAR);
  1293. delete buffer;
  1294. buffer = NULL;
  1295. bRet = TRUE;
  1296. }
  1297. else //key exist
  1298. {
  1299. ASSERT(uKey != (UINT)-1);
  1300.         LPWSTR pValue = pHead + uKey;
  1301.     while(pValue - pHead < (int)(m_dwUseSize/sizeof(WCHAR)) && 
  1302.     *pValue != WCHAR('r') && *pValue != WCHAR('n'))
  1303. {
  1304. pValue++;
  1305. }
  1306.     while(*pValue == WCHAR('r') || *pValue == WCHAR('n'))
  1307. pValue++;
  1308. UINT uMoveHead = (UINT)(pValue - pHead);
  1309. UINT uPrevLen = uMoveHead - uKey;
  1310. int len = wcslen(lpString);
  1311. len += 2;
  1312. buffer = new WCHAR[len+1];
  1313. ::swprintf(buffer, L"%srn", lpString);
  1314.         buffer[len] = 0;
  1315. UINT uCurLen = len;
  1316.         //move have 2 direction
  1317. if(uCurLen > uPrevLen)
  1318. {
  1319. int charDiff = uCurLen - uPrevLen;
  1320. int begin = (int)(m_dwUseSize - sizeof(WCHAR));
  1321. int end = (int)uMoveHead*sizeof(WCHAR);
  1322. for(int i = begin; i >= end; i -= sizeof(WCHAR))
  1323. {
  1324. ::memcpy(pHead + i/sizeof(WCHAR) + charDiff,
  1325. pHead + i/sizeof(WCHAR), sizeof(WCHAR));
  1326. }
  1327. }
  1328. else if(uCurLen < uPrevLen)
  1329. {
  1330. int charDiff = uPrevLen - uCurLen;
  1331. int begin = (int)uMoveHead*sizeof(WCHAR);
  1332. int end = (int)(m_dwUseSize - sizeof(WCHAR));
  1333. for(int i = begin; i <= end;  i+=sizeof(WCHAR))
  1334. {
  1335. ::memcpy(pHead + i/sizeof(WCHAR) - charDiff,
  1336. pHead + i/sizeof(WCHAR), sizeof(WCHAR));
  1337. }
  1338. }
  1339. pValue = pHead + uKey;
  1340. ::memcpy(pValue, buffer, sizeof(WCHAR)*uCurLen);
  1341.         m_dwUseSize += (uCurLen-uPrevLen)*sizeof(WCHAR);
  1342. delete buffer;
  1343. buffer = NULL;
  1344.         bRet = TRUE;
  1345. }
  1346. m_bSectionMapDirty = TRUE;
  1347. if(!bRet) 
  1348. {
  1349. UnloadIniFile();
  1350. return FALSE;
  1351. }
  1352. //If the File is large enough, flush the file
  1353. if((int)(m_dwUseSize - m_dwSize) > JXFlushIncrement - 5*JXPage)
  1354. {
  1355. //Flush Back to HardDisk
  1356. UnloadIniFile();
  1357. }
  1358. return TRUE;
  1359. }
  1360. //User Query All Section Name in INI File
  1361. DWORD CJXINIFile::GetSectionsW(
  1362.          LPWSTR lpReturnedString,  // destination buffer
  1363.          DWORD nSize,              // size of destination buffer
  1364.          LPCWSTR lpFileName        // initialization file name
  1365.     )
  1366. {
  1367.     int posRet = 0;
  1368. LPWSTR pHead = (LPWSTR)m_pTrueData;
  1369. LPWSTR p1 = pHead;
  1370. LPWSTR p2 = pHead;
  1371.         
  1372. WORD wNULL = 0x0000; 
  1373. while(p1- pHead < (int)(m_dwUseSize/sizeof(WCHAR)) - 1)
  1374. {
  1375. while(p1- pHead < (int)(m_dwUseSize/sizeof(WCHAR)) - 1 &&
  1376. *p1 != WCHAR('['))
  1377. p1++;
  1378. p2 = p1;
  1379. while(p2- pHead < (int)(m_dwUseSize/sizeof(WCHAR)) - 1 &&
  1380. *p2 != WCHAR(']'))
  1381. p2++;
  1382. if(p1- pHead < (int)(m_dwUseSize/sizeof(WCHAR)) &&
  1383. p2- pHead < (int)(m_dwUseSize/sizeof(WCHAR)))
  1384. {
  1385. //Found, Ready To Copy To lpReturnedString
  1386. int lenSection = p2 - p1 - 1;
  1387. if(lenSection >= 1)
  1388. {
  1389. p1++;
  1390. if(lenSection + 1 + posRet > (int)nSize) return 0; //nSize - 1;
  1391. ::wcsncpy(lpReturnedString + posRet, p1, lenSection);
  1392.                 posRet += lenSection;
  1393. //NULL = 0x00 00, 2 Byte
  1394. ::memcpy(lpReturnedString + posRet, &wNULL, 2);
  1395.                 posRet += 1;
  1396. }
  1397. p1 = p2 + 1;
  1398. }
  1399. //last NULL 
  1400.     if(1 + posRet > (int)nSize) return 0; //nSize - 1; 
  1401.     ::memcpy(lpReturnedString + posRet, &wNULL, 2);
  1402. posRet += 1;
  1403. return posRet;
  1404. }
  1405. //User Query All Keys in a Given Section
  1406. DWORD CJXINIFile::GetKeysW(
  1407.  LPCWSTR lpAppName,        // section name
  1408.          LPWSTR lpReturnedString,  // destination buffer
  1409.          DWORD nSize,              // size of destination buffer
  1410.          LPCWSTR lpFileName        // initialization file name
  1411.     )
  1412. {
  1413. int posRet = 0;
  1414. int secLen = ::wcslen(lpAppName);
  1415. LPWSTR pHead = (LPWSTR)m_pTrueData;
  1416. LPWSTR p1 = pHead;
  1417. LPWSTR p2 = pHead;
  1418. LPWSTR pSecHead = NULL; //pointing to [
  1419. LPWSTR pSecTail = NULL; //point to next [
  1420.         
  1421. WORD wNULL = 0x0000; 
  1422. while(p1- pHead < (int)(m_dwUseSize/sizeof(WCHAR)) - 1)
  1423. {
  1424. while(p1- pHead < (int)(m_dwUseSize/sizeof(WCHAR)) - 1 &&
  1425. *p1 != WCHAR('['))
  1426. p1++;
  1427. p2 = p1;
  1428. while(p2- pHead < (int)(m_dwUseSize/sizeof(WCHAR)) - 1 &&
  1429. *p2 != WCHAR(']'))
  1430. p2++;
  1431. //p2 points to ]
  1432. if(p1- pHead < (int)(m_dwUseSize/sizeof(WCHAR)) &&
  1433. p2- pHead < (int)(m_dwUseSize/sizeof(WCHAR)))
  1434. {
  1435. //Found A Section
  1436. if(pSecHead != NULL)
  1437. {
  1438. pSecTail = p1;
  1439. break;
  1440. }
  1441. else //pSecHead == NULL
  1442. {
  1443. if(secLen == p2 - p1 - 1) //same length
  1444. {
  1445. p1++;
  1446. LPWSTR p3 = p1; //p3 points to ["X"
  1447.     for(int i = 0; i < secLen; i++)
  1448. {
  1449. if(*p1 != (WCHAR)(lpAppName[i])) break;
  1450. p1++;
  1451. }
  1452.     if(i == secLen) //Found;
  1453. pSecHead = p3 - 1;
  1454. }
  1455. }
  1456. }
  1457. p1 = p2 + 1;
  1458. }
  1459. if(pSecHead == NULL) return -1;
  1460. if(pSecTail == NULL)
  1461. pSecTail = pHead + m_dwUseSize/sizeof(WCHAR);
  1462. pSecTail--;
  1463.     
  1464. //Enum Keys in Section
  1465.     p1 = pSecHead;
  1466. int keyLen;
  1467. while(p1 < pSecTail - 1)
  1468. {
  1469. while(p1 < pSecTail - 1 &&
  1470. *p1 != WCHAR('r') && *p1 != WCHAR('n'))
  1471. p1++;
  1472. while(p1 < pSecTail - 1 &&
  1473. (*p1 == WCHAR('r') || *p1 == WCHAR('n')))
  1474. p1++;
  1475. p2 = p1;
  1476. while(p2 < pSecTail - 1 &&
  1477. *p2 != WCHAR('='))
  1478. p2++;
  1479. if(p1 < pSecTail - 1 && p2 < pSecTail - 1)
  1480. {
  1481. //Found A Key
  1482. keyLen = p2 - p1;
  1483. if(keyLen >= 1)
  1484. {
  1485. if(keyLen + 1 + posRet > (int)nSize) return 0; //nSize - 1;
  1486. ::wcsncpy(lpReturnedString + posRet, p1, keyLen);
  1487.                 posRet += keyLen;
  1488. //NULL = 0x00 00, 2 Byte
  1489. ::memcpy(lpReturnedString + posRet, &wNULL, 2);
  1490.                 posRet += 1;
  1491. }
  1492. }
  1493. p1 = p2 + 1;
  1494. }
  1495. //last NULL 
  1496.     if(1 + posRet > (int)nSize) return 0; //nSize - 1; 
  1497.     ::memcpy(lpReturnedString + posRet, &wNULL, 2);
  1498. posRet += 1;
  1499. return posRet;
  1500. }
  1501. //MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
  1502. //MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
  1503. //ANSI Version ----------------------------------------------
  1504. // return 0 -- no key, size too small to put value
  1505. //return -1  -- error
  1506. //return string length (of course > 1)
  1507. DWORD CJXINIFile::GetPrivateProfileStringA(
  1508.          LPCSTR lpAppName,        // section name
  1509.          LPCSTR lpKeyName,        // key name
  1510.          LPCSTR lpDefault,        // default string
  1511.          LPSTR lpReturnedString,  // destination buffer
  1512.          DWORD nSize,              
  1513.  // size of destination buffer,Specifies the size, in TCHARs, 
  1514.          LPCSTR lpFileName        // initialization file name
  1515.     )
  1516. {
  1517. BOOL bRet = LoadIniFile(lpFileName, 1);
  1518. if(!bRet) return (UINT)-1;
  1519. if(lpDefault == NULL) return -1;
  1520. if(m_dwUseSize == 0) return -1;
  1521. if(lpAppName == NULL)
  1522. return GetSectionsA(lpReturnedString, nSize, lpFileName);
  1523. if(lpKeyName == NULL)
  1524. return GetKeysA(lpAppName, lpReturnedString, nSize, lpFileName);
  1525. LPSTR pHead = (LPSTR)m_pTrueData;
  1526. UINT uSec, uKey;
  1527. uSec = (UINT) -1;
  1528. uKey = (UINT)-1;
  1529. uKey = GetKeyA(pHead, (UINT)m_dwUseSize, 
  1530. lpAppName, lpKeyName, uSec);
  1531.     if(uKey == (UINT)-1) //not key
  1532. {
  1533. if(::strlen(lpDefault) > (int)nSize) return -1;
  1534. ::strncpy(lpReturnedString, lpDefault, ::strlen(lpDefault));
  1535. //append a null
  1536.         lpReturnedString[::strlen(lpDefault)+1] = char('');
  1537. return 0;
  1538. }
  1539. char buffer[MAX_PATH];
  1540.     LPSTR pValue = pHead + uKey;
  1541. while(pValue - pHead < (int)((m_dwUseSize)/sizeof(char)) && 
  1542.  *pValue != char('r') && *pValue != char('n'))
  1543. {
  1544. pValue++;  //in unicode, +2 byte
  1545. }
  1546. int len = pValue - pHead - uKey;
  1547. pValue = pHead + uKey;
  1548. ::strncpy(buffer, pValue, len); 
  1549. if(nSize <= (UINT)len)
  1550. {
  1551. ::strncpy(lpReturnedString, pValue, nSize);
  1552.         lpReturnedString[nSize - 1] = char('');
  1553. return 0;
  1554. }
  1555. else
  1556. {
  1557. ::strncpy(lpReturnedString, pValue, len);
  1558. //append null
  1559.         lpReturnedString[len] = char('');
  1560. return len;
  1561. }
  1562. return (UINT) -1;
  1563. }
  1564. BOOL CJXINIFile::WritePrivateProfileStringA(
  1565.          LPCSTR lpAppName,  // section name
  1566.          LPCSTR lpKeyName,  // key name
  1567.          LPCSTR lpString,   // string to add
  1568.          LPCSTR lpFileName  // initialization file
  1569.     )
  1570. {
  1571. BOOL bRet = this->LoadIniFile(lpFileName, 1);
  1572. if(!bRet) return FALSE;
  1573. m_bDirty = TRUE;
  1574. LPSTR pHead = (LPSTR)m_pTrueData;
  1575. //2001/10/19 if lpString.len > MAX_PATH error 
  1576. //char buffer[MAX_PATH];
  1577. LPSTR buffer = NULL;
  1578. UINT uSec, uKey;  
  1579. //Warning: uKey, uSec is measured in WCHARs!!!!!
  1580. //in UNICODE now
  1581. uKey = GetKeyA(pHead, (UINT)m_dwUseSize, 
  1582. lpAppName, lpKeyName, uSec);
  1583.     if(uKey == (UINT)-1 && uSec == (UINT)-1) //no section
  1584. {
  1585. int len = strlen(lpAppName) + strlen(lpKeyName) +strlen(lpString);
  1586. len += 7;
  1587. buffer = new char[len+1];
  1588. ::sprintf(buffer, "[%s]rn%s=%srn", lpAppName, lpKeyName, lpString);
  1589. buffer[len] = 0;
  1590. LPSTR pStr = pHead;
  1591. pStr += m_dwUseSize/sizeof(char);
  1592. ::memcpy(pStr, buffer, len*sizeof(char));
  1593. m_dwUseSize += len*sizeof(char);
  1594. delete []buffer;
  1595. buffer = NULL;
  1596. bRet = TRUE;
  1597. }
  1598. else if(uKey == (UINT)-1 && uSec != (UINT)-1) 
  1599. //section exist but value do not exist
  1600. {
  1601. // Following Write Just After [section],
  1602. //that new item become the first of the section
  1603.         //$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
  1604. //$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
  1605. /*
  1606. LPSTR pSection = pHead + uSec;
  1607. while(pSection - pHead < (int)(m_dwUseSize/sizeof(char)) && 
  1608.       *pSection != char('r') && *pSection != char('n'))
  1609. {
  1610. pSection++;
  1611. }
  1612.      while(*pSection == char('r') || *pSection == char('n'))
  1613. pSection++;
  1614. UINT uMoveHead = (UINT)(pSection - pHead); 
  1615.         //move memory
  1616. ::sprintf(buffer, L"%s=%srn", lpKeyName, lpString);
  1617. int len = ::strlen(buffer);
  1618. //also ok
  1619. //::memmove(pHead + uMoveHead + len, pHead + uMoveHead, m_dwUseSize-uMoveHead*sizeof(char));
  1620. for(int i = (int)(m_dwUseSize - sizeof(char)); 
  1621.     i >= (int)(uMoveHead*sizeof(char)); i -= sizeof(char))
  1622. {
  1623. ::memcpy(pHead + i/sizeof(char) + len, 
  1624. pHead + i/sizeof(char), sizeof(char));
  1625. }
  1626. */
  1627. //Following Write new item the last item in the section
  1628.         //$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
  1629. //$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
  1630.         LPSTR pSection = pHead + uSec + 1;
  1631. while(pSection - pHead < (int)(m_dwUseSize/sizeof(char)) && 
  1632.       *pSection != char('['))
  1633. {
  1634. pSection++;
  1635. }
  1636. // ::sprintf(buffer, L"%s=%srn", lpKeyName, lpString);
  1637. // int len = ::strlen(buffer);
  1638. int len = strlen(lpKeyName) + strlen(lpString);
  1639. len += 3;
  1640. buffer = new char[len+1];
  1641. ::sprintf(buffer, "%s=%srn", lpKeyName, lpString);
  1642. buffer[len] = 0;
  1643.      if(pSection - pHead == (int)(m_dwUseSize/sizeof(char)))
  1644. {
  1645. //no move needed, file end
  1646. }
  1647. else
  1648. {
  1649. UINT uMoveHead = (UINT)(pSection - pHead); 
  1650.             //move memory
  1651.     //also ok
  1652.     //::memmove(pHead + uMoveHead + len, pHead + uMoveHead, m_dwUseSize-uMoveHead*sizeof(char));
  1653.     for(int i = (int)(m_dwUseSize - sizeof(char)); 
  1654.        i >= (int)(uMoveHead*sizeof(char)); i -= sizeof(char))
  1655. {
  1656.    ::memcpy(pHead + i/sizeof(char) + len, 
  1657.      pHead + i/sizeof(char), sizeof(char));
  1658. }
  1659. }
  1660. ::memcpy(pSection, buffer, sizeof(char)*len);
  1661. m_dwUseSize += len*sizeof(char);
  1662. delete buffer;
  1663. buffer = NULL;
  1664. bRet = TRUE;
  1665. }
  1666. else //key exist
  1667. {
  1668. ASSERT(uKey != (UINT)-1);
  1669.         LPSTR pValue = pHead + uKey;
  1670.     while(pValue - pHead < (int)(m_dwUseSize/sizeof(char)) && 
  1671.     *pValue != char('r') && *pValue != char('n'))
  1672. {
  1673. pValue++;
  1674. }
  1675.     while(*pValue == char('r') || *pValue == char('n'))
  1676. pValue++;
  1677. UINT uMoveHead = (UINT)(pValue - pHead);
  1678. UINT uPrevLen = uMoveHead - uKey;
  1679. int len = strlen(lpString);
  1680. len += 2;
  1681. buffer = new char[len+1];
  1682. ::sprintf(buffer, "%srn", lpString);
  1683.         buffer[len] = 0;
  1684. UINT uCurLen = len;
  1685.         //move have 2 direction
  1686. if(uCurLen > uPrevLen)
  1687. {
  1688. int charDiff = uCurLen - uPrevLen;
  1689. int begin = (int)(m_dwUseSize - sizeof(char));
  1690. int end = (int)uMoveHead*sizeof(char);
  1691. for(int i = begin; i >= end; i -= sizeof(char))
  1692. {
  1693. ::memcpy(pHead + i/sizeof(char) + charDiff,
  1694. pHead + i/sizeof(char), sizeof(char));
  1695. }
  1696. }
  1697. else if(uCurLen < uPrevLen)
  1698. {
  1699. int charDiff = uPrevLen - uCurLen;
  1700. int begin = (int)uMoveHead*sizeof(char);
  1701. int end = (int)(m_dwUseSize - sizeof(char));
  1702. for(int i = begin; i <= end;  i+=sizeof(char))
  1703. {
  1704. ::memcpy(pHead + i/sizeof(char) - charDiff,
  1705. pHead + i/sizeof(char), sizeof(char));
  1706. }
  1707. }
  1708. pValue = pHead + uKey;
  1709. ::memcpy(pValue, buffer, sizeof(char)*uCurLen);
  1710.         m_dwUseSize += (uCurLen-uPrevLen)*sizeof(char);
  1711. delete buffer;
  1712. buffer = NULL;
  1713.         bRet = TRUE;
  1714. }
  1715. m_bSectionMapDirty = TRUE;
  1716. if(!bRet) 
  1717. {
  1718. UnloadIniFile();
  1719. return FALSE;
  1720. }
  1721. //If the File is large enough, flush the file
  1722. if((int)(m_dwUseSize - m_dwSize) > JXFlushIncrement - 5*JXPage)
  1723. {
  1724. //Flush Back to HardDisk
  1725. UnloadIniFile();
  1726. }
  1727. return TRUE;
  1728. }
  1729. //User Query All Section Name in INI File
  1730. DWORD CJXINIFile::GetSectionsA(
  1731.          LPSTR lpReturnedString,  // destination buffer
  1732.          DWORD nSize,              // size of destination buffer
  1733.          LPCSTR lpFileName        // initialization file name
  1734.     )
  1735. {
  1736.     int posRet = 0;
  1737. LPSTR pHead = (LPSTR)m_pData;
  1738. LPSTR p1 = pHead;
  1739. LPSTR p2 = pHead;
  1740.         
  1741. BYTE wNULL = 0x0000; 
  1742. while(p1- pHead < (int)(m_dwUseSize/sizeof(char)) - 1)
  1743. {
  1744. while(p1- pHead < (int)(m_dwUseSize/sizeof(char)) - 1 &&
  1745. *p1 != char('['))
  1746. p1++;
  1747. p2 = p1;
  1748. while(p2- pHead < (int)(m_dwUseSize/sizeof(char)) - 1 &&
  1749. *p2 != char(']'))
  1750. p2++;
  1751. if(p1- pHead < (int)(m_dwUseSize/sizeof(char)) &&
  1752. p2- pHead < (int)(m_dwUseSize/sizeof(char)))
  1753. {
  1754. //Found, Ready To Copy To lpReturnedString
  1755. int lenSection = p2 - p1 - 1;
  1756. if(lenSection >= 1)
  1757. {
  1758. p1++;
  1759. if(lenSection + 1 + posRet > (int)nSize) return 0; //nSize - 1;
  1760. ::strncpy(lpReturnedString + posRet, p1, lenSection);
  1761.                 posRet += lenSection;
  1762. //NULL = 0x00,  1Byte
  1763. ::memcpy(lpReturnedString + posRet, &wNULL, 1);
  1764.                 posRet += 1;
  1765. }
  1766. p1 = p2 + 1;
  1767. }
  1768. //last NULL 
  1769.     if(1 + posRet > (int)nSize) return 0; //nSize - 1; 
  1770.     ::memcpy(lpReturnedString + posRet, &wNULL, 1);
  1771. posRet += 1;
  1772. return posRet;
  1773. }
  1774. //User Query All Keys in a Given Section
  1775. DWORD CJXINIFile::GetKeysA(
  1776.          LPCSTR lpAppName,        // section name
  1777.          LPSTR lpReturnedString,  // destination buffer
  1778.          DWORD nSize,              // size of destination buffer
  1779.          LPCSTR lpFileName        // initialization file name
  1780.     )
  1781. {
  1782. int posRet = 0;
  1783. int secLen = ::strlen(lpAppName);
  1784. LPSTR pHead = (LPSTR)m_pTrueData;
  1785. LPSTR p1 = pHead;
  1786. LPSTR p2 = pHead;
  1787. LPSTR pSecHead = NULL; //pointing to [
  1788. LPSTR pSecTail = NULL; //point to next [
  1789.         
  1790. BYTE byteNULL = 0x00; 
  1791. while(p1- pHead < (int)(m_dwUseSize/sizeof(char)) - 1)
  1792. {
  1793. while(p1- pHead < (int)(m_dwUseSize/sizeof(char)) - 1 &&
  1794. *p1 != char('['))
  1795. p1++;
  1796. p2 = p1;
  1797. while(p2- pHead < (int)(m_dwUseSize/sizeof(char)) - 1 &&
  1798. *p2 != char(']'))
  1799. p2++;
  1800. //p2 points to ]
  1801. if(p1- pHead < (int)(m_dwUseSize/sizeof(char)) &&
  1802. p2- pHead < (int)(m_dwUseSize/sizeof(char)))
  1803. {
  1804. //Found A Section
  1805. if(pSecHead != NULL)
  1806. {
  1807. pSecTail = p1;
  1808. break;
  1809. }
  1810. else //pSecHead == NULL
  1811. {
  1812. if(secLen == p2 - p1 - 1) //same length
  1813. {
  1814. p1++;
  1815. LPSTR p3 = p1; //p3 points to ["X"
  1816.     for(int i = 0; i < secLen; i++)
  1817. {
  1818. if(*p1 != (char)(lpAppName[i])) break;
  1819. p1++;
  1820. }
  1821.     if(i == secLen) //Found;
  1822. pSecHead = p3 - 1;
  1823. }
  1824. }
  1825. }
  1826. p1 = p2 + 1;
  1827. }
  1828. if(pSecHead == NULL) return -1;
  1829. if(pSecTail == NULL)
  1830. pSecTail = pHead + m_dwUseSize/sizeof(char);
  1831. pSecTail--;
  1832.     
  1833. //Enum Keys in Section
  1834.     p1 = pSecHead;
  1835. int keyLen;
  1836. while(p1 < pSecTail - 1)
  1837. {
  1838. while(p1 < pSecTail - 1 &&
  1839. *p1 != char('r') && *p1 != char('n'))
  1840. p1++;
  1841. while(p1 < pSecTail - 1 &&
  1842. (*p1 == char('r') || *p1 == char('n')))
  1843. p1++;
  1844. p2 = p1;
  1845. while(p2 < pSecTail - 1 &&
  1846. *p2 != char('='))
  1847. p2++;
  1848. if(p1 < pSecTail - 1 && p2 < pSecTail - 1)
  1849. {
  1850. //Found A Key
  1851. keyLen = p2 - p1;
  1852. if(keyLen >= 1)
  1853. {
  1854. if(keyLen + 1 + posRet > (int)nSize) return 0; //nSize - 1;
  1855. ::strncpy(lpReturnedString + posRet, p1, keyLen);
  1856.                 posRet += keyLen;
  1857. //NULL = 0x00 , 1 Byte
  1858. ::memcpy(lpReturnedString + posRet, &byteNULL, 1);
  1859.                 posRet += 1;
  1860. }
  1861. }
  1862. p1 = p2 + 1;
  1863. }
  1864. //last NULL 
  1865.     if(1 + posRet > (int)nSize) return 0; //nSize - 1; 
  1866.     ::memcpy(lpReturnedString + posRet, &byteNULL, 1);
  1867. posRet += 1;
  1868. return posRet;
  1869. }
  1870. BOOL CJXINIFile::LoadIniFile(CString strFilename, DWORD dwMode)
  1871. {
  1872. if(dwMode == 0 && sizeof(TCHAR) == 1) m_bUnicode = FALSE;
  1873. if(dwMode == 0 && sizeof(TCHAR) == 2) m_bUnicode = TRUE;
  1874.     if(dwMode == 1) m_bUnicode = FALSE;
  1875. if(dwMode == 2) m_bUnicode = TRUE;
  1876. if(strFilename == _T("")) return FALSE;
  1877. //Already Loaded
  1878. if(m_strFilename == strFilename) return TRUE; 
  1879. if(m_strFilename != _T("")) //Unload First
  1880. {
  1881. UnloadIniFile();
  1882. }
  1883.     
  1884. m_strFilename = strFilename;
  1885. m_bDirty = FALSE;
  1886. m_bSectionMapDirty = TRUE;
  1887.     m_bSectionMapLock = FALSE;
  1888. DWORD dwHigh, dwLow;
  1889. DWORD dwTotal, dwError;
  1890. //Open File Handle
  1891. m_hFile = ::CreateFile(m_strFilename, GENERIC_READ | GENERIC_WRITE,
  1892.  FILE_SHARE_READ, NULL, OPEN_EXISTING, 
  1893.  FILE_ATTRIBUTE_NORMAL, NULL);
  1894. if(m_hFile != INVALID_HANDLE_VALUE)
  1895. {
  1896. //Measure File Size
  1897.     dwLow = GetFileSize(m_hFile, &dwHigh);
  1898.     dwTotal = 0;
  1899.        if(dwLow == -1 && (dwError = GetLastError()) != NO_ERROR)
  1900. {
  1901. ::MessageBox(NULL, _T("File Size Failure"),
  1902. _T("CJXINIFile::Load"), MB_OK | MB_ICONSTOP);
  1903.     if(m_hFile != INVALID_HANDLE_VALUE)
  1904. ::CloseHandle(m_hFile);
  1905.     m_dwSize = 0;
  1906.     m_strFilename = _T("");
  1907.         return FALSE;
  1908. }
  1909. m_dwSize = dwLow;  //32bit -> 4Gb
  1910. }
  1911. else
  1912. {
  1913. m_hFile = ::CreateFile(m_strFilename, GENERIC_READ | GENERIC_WRITE,
  1914.    FILE_SHARE_READ, NULL, OPEN_ALWAYS, 
  1915.    FILE_ATTRIBUTE_NORMAL, NULL);
  1916.     if(m_hFile == INVALID_HANDLE_VALUE)
  1917. {
  1918. ::MessageBox(NULL, _T("CreateFile Failure"),
  1919.               _T("CJXINIFile::Load"), MB_OK | MB_ICONSTOP);
  1920.     if(m_hFile != INVALID_HANDLE_VALUE)
  1921. ::CloseHandle(m_hFile);
  1922.     m_dwSize = 0;
  1923.     m_strFilename = _T("");
  1924.         return FALSE;
  1925. }
  1926. m_dwSize = 0;
  1927. }
  1928.         
  1929. //Open Memory-Mapping File, maximum size = File Size + JXFlushIncrement
  1930. dwLow = m_dwSize + JXFlushIncrement;
  1931. m_hMMF = ::CreateFileMapping(m_hFile, NULL,
  1932. PAGE_READWRITE,  0 , dwLow, NULL);
  1933. if(NULL == m_hMMF)
  1934. {
  1935. ::MessageBox(NULL, _T("CreateFileMapping Failure"),
  1936.                 _T("CJXINIFile::Load"), MB_OK | MB_ICONSTOP);
  1937. if(m_hMMF != NULL)
  1938. ::CloseHandle(m_hMMF);
  1939.     if(m_hFile != INVALID_HANDLE_VALUE)
  1940. ::CloseHandle(m_hFile);
  1941. m_dwSize = 0;
  1942. m_strFilename = _T("");
  1943. return FALSE;
  1944. }
  1945. //Map pointer
  1946. m_pData = ::MapViewOfFile(m_hMMF, FILE_MAP_READ | FILE_MAP_WRITE,
  1947. 0, 0, dwLow);
  1948.     if(m_pData == NULL)
  1949. {
  1950. //ReportErr(_T(""));
  1951. if(m_hMMF != NULL)
  1952. ::CloseHandle(m_hMMF);
  1953.     if(m_hFile != INVALID_HANDLE_VALUE)
  1954. ::CloseHandle(m_hFile);
  1955. m_dwSize = 0;
  1956. m_strFilename = _T("");
  1957. ::MessageBox(NULL, _T("MapViewOfFile Failure"),
  1958.                _T("CJXINIFile::Load"), MB_OK | MB_ICONSTOP);
  1959. return FALSE;
  1960. }
  1961. m_dwUseSize = m_dwSize;
  1962.     
  1963. CutZeroTail();
  1964. //if(sizeof(TCHAR) == 2) //UNICODE only
  1965. if(this->m_bUnicode)
  1966. //Pass Potentail 0xFF FE header if edited by MS NotePad
  1967. {
  1968. LPBYTE pByte = (LPBYTE)m_pData;
  1969.     if(m_dwUseSize >= 2 && *pByte == 0xFF && *(pByte +1) == 0xFE)
  1970. {
  1971. m_pTrueData = (LPVOID)(pByte + 2);
  1972. m_dwUseSize -= 2;
  1973. }
  1974.     else
  1975. {
  1976. if(m_dwUseSize == 0) //a new file, add 0xFF FE header
  1977.                  //for Win2k SP1 need 0xFF FE
  1978. {
  1979. *pByte = 0xFF;
  1980. *(pByte +1) = 0xFE;
  1981. //m_dwUseSize = 2;
  1982. m_pTrueData = (LPVOID)(pByte+2);
  1983. }
  1984. else //old format without 0xFF FE
  1985. {
  1986. ::memmove((LPVOID)(pByte+2), (LPVOID)pByte, m_dwUseSize);
  1987. *pByte = 0xFF;
  1988. *(pByte +1) = 0xFE;
  1989. //m_dwUseSize += 2;
  1990.                 m_pTrueData = (LPVOID)(pByte+2);
  1991. }
  1992. }
  1993. }
  1994. else
  1995. m_pTrueData = m_pData;
  1996.     return TRUE;
  1997. }
  1998. BOOL CJXINIFile::UnloadIniFile()
  1999. {
  2000. DWORD dwFileSize;
  2001. //if(sizeof(TCHAR) == 2) //UNICODE leading 0xFF FE
  2002. if(this->m_bUnicode)
  2003. dwFileSize = m_dwUseSize + 2;
  2004. else
  2005. dwFileSize = m_dwUseSize;
  2006. if(m_strFilename == _T("")) return TRUE; 
  2007.     if(!m_bDirty)
  2008. {
  2009. if(m_pData)
  2010. {
  2011. ::UnmapViewOfFile(m_pData);
  2012. m_pData = NULL;
  2013. }
  2014.     if(m_hMMF != NULL)
  2015. {
  2016. ::CloseHandle(m_hMMF);
  2017. m_hMMF = NULL;
  2018. }
  2019. LONG highDist = 0;
  2020.     ::SetFilePointer(
  2021. m_hFile,                // handle to file
  2022.             dwFileSize,        // bytes to move pointer
  2023.             &highDist,  // bytes to move pointer
  2024.             FILE_BEGIN           // starting point
  2025.         );
  2026.     ::SetEndOfFile(m_hFile);
  2027.     if(m_hFile != INVALID_HANDLE_VALUE)
  2028. {
  2029.     ::CloseHandle(m_hFile);
  2030.     m_hFile = INVALID_HANDLE_VALUE;
  2031. }
  2032. m_strFilename = _T("");
  2033. return TRUE;
  2034. }
  2035. //Modified
  2036. ASSERT(m_pData);
  2037. if(!::FlushViewOfFile(m_pData, m_dwUseSize))
  2038. {
  2039. ::MessageBox(NULL, _T("FlushViewMMF"), _T(""), MB_OK);
  2040. ::UnmapViewOfFile(m_pData);
  2041.     ::CloseHandle(m_hMMF);
  2042. LONG highDist = 0;
  2043.     ::SetFilePointer(
  2044.   m_hFile,                // handle to file
  2045.           dwFileSize,        // bytes to move pointer
  2046.           &highDist,  // bytes to move pointer
  2047.           FILE_BEGIN           // starting point
  2048.         );
  2049. ::SetEndOfFile(m_hFile);
  2050.     ::CloseHandle(m_hFile);
  2051. m_strFilename = _T("");
  2052. m_pData = NULL;
  2053. m_hMMF = NULL;
  2054. m_hFile = INVALID_HANDLE_VALUE;
  2055. m_dwSize = 0;
  2056. return FALSE;
  2057. }
  2058. ::UnmapViewOfFile(m_pData);
  2059. ::CloseHandle(m_hMMF);
  2060. //Adjust File Size
  2061. LONG highDist = 0;
  2062. ::SetFilePointer(
  2063. m_hFile,                // handle to file
  2064.         dwFileSize,        // bytes to move pointer
  2065.         &highDist,  // bytes to move pointer
  2066.         FILE_BEGIN           // starting point
  2067.     );
  2068. ::SetEndOfFile(m_hFile);
  2069. ::CloseHandle(m_hFile);
  2070. m_strFilename = _T("");
  2071. m_pData = NULL;
  2072. m_hMMF = NULL;
  2073. m_hFile = INVALID_HANDLE_VALUE;
  2074. m_dwSize = 0;
  2075. //
  2076. m_mapSection.RemoveAll();
  2077. m_bSectionMapDirty = TRUE;
  2078. m_bSectionMapLock = FALSE;
  2079. return TRUE;
  2080. }
  2081. //return -1 if not find key
  2082. //return first character of the key line 
  2083. //[section name]rn
  2084. //keyname = valuenamern
  2085. //Ex Version use Map
  2086. //posSection & ret all in WCHARs
  2087. UINT CJXINIFile::GetKeyExA(LPSTR pHead, UINT uSize, 
  2088. LPCSTR szSection, LPCSTR szKey, UINT& posSection)
  2089. {
  2090. //Map Must Be Ready Here
  2091. ASSERT(!m_bSectionMapDirty);
  2092. LPSTR pSecHead = NULL; //pointing to [
  2093. #ifdef _UNICODE
  2094. DWORD dwRetSize;
  2095. LPWSTR pTemp = _A2W((LPSTR)szSection, -1, dwRetSize);
  2096.     if(0 == m_mapSection.Lookup(pTemp, (LPVOID&)pSecHead))
  2097. {
  2098.         posSection = (UINT)-1;
  2099. return (UINT)-1; 
  2100. }
  2101. #else
  2102. if(0 == m_mapSection.Lookup(szSection, (LPVOID&)pSecHead))
  2103. {
  2104.         posSection = (UINT)-1;
  2105. return (UINT)-1; 
  2106. }
  2107. #endif
  2108. posSection = -1;
  2109. LPSTR p1 = pSecHead;
  2110. LPSTR p2 = pSecHead;
  2111. int lenSection = ::strlen(szSection);
  2112. char szSection2[MAX_PATH];
  2113. //section --> [section]
  2114.     ::strncpy(szSection2+1, szSection, lenSection);
  2115. szSection2[0] = char('[');
  2116. szSection2[lenSection+1] = char(']');
  2117. szSection2[lenSection+2] = char('');
  2118.         
  2119. BOOL bSection = FALSE; //found the section
  2120. BOOL bKey = FALSE;     //found the key
  2121. char buffer[MAX_PATH]; 
  2122. int line;
  2123. while(p1- pHead < (int)(uSize/sizeof(char)) - 1)
  2124. {
  2125. //WCHAR s1 = (WCHAR)'r'; //13
  2126. //WCHAR s2 = (WCHAR)'n'; //10
  2127. //WCHAR s3 = (WCHAR)0x0A; //10
  2128. //01/7/5 //avoid leak blank line
  2129. int rInc, nInc;
  2130. rInc = nInc = 0;
  2131. while(p1- pHead < (int)(uSize/sizeof(char)-1) && 
  2132. (*p1 == (char)'r' || *p1 == (char)'n'))
  2133. {
  2134. if(*p1 == (char)'r') rInc++;
  2135.             if(*p1 == (char)'n') nInc++;
  2136. p1++;
  2137. }
  2138. if(rInc == 1 && nInc == 1)
  2139. {
  2140. }
  2141. else if(rInc == nInc && rInc > 1)
  2142. line += rInc - 1;
  2143. else if(rInc != nInc)
  2144. {
  2145. line += rInc > nInc ? rInc - 1 : nInc - 1;
  2146. }
  2147. p2 = p1;
  2148. while(p2- pHead < (int)(uSize/sizeof(char))-1)
  2149. {
  2150. //$$$ some file end  with n only
  2151. if(*p2 == (char)'r' && *(p2+1) == (char)'n') 
  2152. {
  2153. break; //touch it
  2154. }
  2155.             if(*p2 == (char)'n') break;
  2156. if(*p2 == (char)'r') break;
  2157.     p2++;
  2158. }
  2159. if(p2 - pHead == (int)(uSize/sizeof(char))-1)
  2160. {
  2161. //the last sentence 
  2162.             while(*p2 == (char)'r' || *p2 == (char)'n') p2--;
  2163. int len = p2 - p1 + 1; 
  2164. line++;
  2165. if(len > 1)
  2166. {
  2167. if(len > MAX_PATH) 
  2168. {
  2169. p1 = p2 + 1;
  2170. continue;
  2171. }
  2172. ::strncpy(buffer, p1, len);
  2173. buffer[len] = char('');
  2174. //a section ?
  2175.     if(buffer[0] == char('[') && 
  2176.     buffer[len-1] == char(']'))
  2177. {
  2178. //AfxMessageBox(buffer);
  2179. if(::strcmp(buffer,szSection2) == 0) //match
  2180. {
  2181. if(!bSection) 
  2182. {
  2183. bSection = TRUE;
  2184.     posSection = (UINT)(p1 - pHead);
  2185. }
  2186. }
  2187.     else
  2188. {
  2189. if(bSection) return (UINT)-1;
  2190. }
  2191. }
  2192.     else //a key line
  2193. {
  2194. if(!bSection)
  2195. {
  2196. }
  2197.     else
  2198. {
  2199. //key name = value name
  2200. int lenKey = ::strlen(szKey);
  2201.     //find =
  2202.     int sam;
  2203.     for(sam = 0; sam < len; sam++)
  2204. if(buffer[sam] == char('=')) break;
  2205.     if(sam >= lenKey && sam < len)
  2206. {
  2207. for(int q = 0; q < sam; q++)
  2208. {
  2209. if(q < lenKey && buffer[q] != szKey[q]) break;
  2210.     if(q > lenKey && buffer[q] != char(' ')) break;
  2211. }
  2212.     if(q == sam) //found
  2213. {
  2214. bKey = TRUE;
  2215.     return (UINT)(p1 - pHead + sam + 1);
  2216.     //return (UINT)(p1 - pHead);
  2217. }
  2218. }
  2219. }
  2220. }
  2221. line++;
  2222. }
  2223.             break;
  2224. }
  2225. p2--;
  2226. //now p2 points to the ending of the sentence
  2227.         int len = p2 - p1 + 1; //in chars
  2228. line++;
  2229. if(len > 1)
  2230. {
  2231. if(len > MAX_PATH) 
  2232. {
  2233. p1 = p2 + 1;
  2234. continue;
  2235. }
  2236. //this sentence must shorter than MAX_PATH
  2237. ::strncpy(buffer, p1, len);
  2238. buffer[len] = char('');
  2239. //???, lstrcpy seems not add null-trminator
  2240. //buffer[len] = WCHAR('');
  2241. //a section ?
  2242. if(buffer[0] == char('[') && 
  2243. buffer[len-1] == char(']'))
  2244. {
  2245. //AfxMessageBox(buffer);
  2246. if(::strcmp(buffer,szSection2) == 0) //match
  2247. {
  2248. if(!bSection) 
  2249. {
  2250. bSection = TRUE;
  2251. posSection = (UINT)(p1 - pHead);
  2252. }
  2253. }
  2254. else
  2255. {
  2256. if(bSection) return (UINT)-1;
  2257. }
  2258. }
  2259. else //a key line
  2260. {
  2261. if(!bSection)
  2262. {
  2263. }
  2264. else
  2265. {
  2266. //key name = value name
  2267. int lenKey = ::strlen(szKey);
  2268. //find =
  2269. int sam;
  2270. for(sam = 0; sam < len; sam++)
  2271. if(buffer[sam] == char('=')) break;
  2272. if(sam >= lenKey && sam < len)
  2273. {
  2274. for(int q = 0; q < sam; q++)
  2275. {
  2276. if(q < lenKey && buffer[q] != szKey[q]) break;
  2277. if(q > lenKey && buffer[q] != char(' ')) break;
  2278. }
  2279. if(q == sam) //found
  2280. {
  2281. bKey = TRUE;
  2282. return (UINT)(p1 - pHead + sam + 1);
  2283. //return (UINT)(p1 - pHead);
  2284. }
  2285. }
  2286. }
  2287. }
  2288. }
  2289. p1 = p2 + 1;
  2290. }
  2291. return (UINT)-1;
  2292. }
  2293. //return -1 if not find key
  2294. //return first character of the key line 
  2295. //[section name]rn
  2296. //keyname = valuenamern
  2297. //Ex Version use Map
  2298. //posSection & ret all in WCHARs
  2299. UINT CJXINIFile::GetKeyExW(LPWSTR pHead, UINT uSize, 
  2300. LPCWSTR szSection, LPCWSTR szKey, UINT& posSection)
  2301. {
  2302. //Map Must Be Ready Here
  2303. ASSERT(!m_bSectionMapDirty);
  2304. LPWSTR pSecHead = NULL; //pointing to [
  2305. #ifdef _UNICODE
  2306. if(0 == m_mapSection.Lookup(szSection, (LPVOID&)pSecHead))
  2307. {
  2308.         posSection = (UINT)-1;
  2309. return (UINT)-1; 
  2310. }
  2311. #else
  2312. DWORD dwRetSize;
  2313. LPSTR pTemp = _W2A((LPWSTR)szSection, -1, dwRetSize);
  2314.     if(0 == m_mapSection.Lookup(pTemp, (LPVOID&)pSecHead))
  2315. {
  2316.         posSection = (UINT)-1;
  2317. return (UINT)-1; 
  2318. }
  2319. #endif
  2320. posSection = -1;
  2321. LPWSTR p1 = pSecHead;
  2322. LPWSTR p2 = pSecHead;
  2323. int lenSection = ::wcslen(szSection);
  2324. WCHAR szSection2[MAX_PATH];
  2325. //section --> [section]
  2326.     ::wcsncpy(szSection2+1, szSection, lenSection);
  2327. szSection2[0] = WCHAR('[');
  2328. szSection2[lenSection+1] = WCHAR(']');
  2329. szSection2[lenSection+2] = WCHAR('');
  2330.         
  2331. BOOL bSection = FALSE; //found the section
  2332. BOOL bKey = FALSE;     //found the key
  2333. WCHAR buffer[MAX_PATH]; 
  2334. int line;
  2335. while(p1- pHead < (int)(uSize/sizeof(WCHAR)) - 1)
  2336. {
  2337. //WCHAR s1 = (WCHAR)'r'; //13
  2338. //WCHAR s2 = (WCHAR)'n'; //10
  2339. //WCHAR s3 = (WCHAR)0x0A; //10
  2340. //01/7/5 //avoid leak blank line
  2341. int rInc, nInc;
  2342. rInc = nInc = 0;
  2343. while(p1- pHead < (int)(uSize/sizeof(WCHAR)-1) && 
  2344. (*p1 == (WCHAR)'r' || *p1 == (WCHAR)'n'))
  2345. {
  2346. if(*p1 == (WCHAR)'r') rInc++;
  2347.             if(*p1 == (WCHAR)'n') nInc++;
  2348. p1++;
  2349. }
  2350. if(rInc == 1 && nInc == 1)
  2351. {
  2352. }
  2353. else if(rInc == nInc && rInc > 1)
  2354. line += rInc - 1;
  2355. else if(rInc != nInc)
  2356. {
  2357. line += rInc > nInc ? rInc - 1 : nInc - 1;
  2358. }
  2359. p2 = p1;
  2360. while(p2- pHead < (int)(uSize/sizeof(WCHAR))-1)
  2361. {
  2362. //$$$ some file end  with n only
  2363. if(*p2 == (WCHAR)'r' && *(p2+1) == (WCHAR)'n') 
  2364. {
  2365. break; //touch it
  2366. }
  2367.             if(*p2 == (WCHAR)'n') break;
  2368. if(*p2 == (WCHAR)'r') break;
  2369.     p2++;
  2370. }
  2371. if(p2 - pHead == (int)(uSize/sizeof(WCHAR))-1)
  2372. {
  2373. //the last sentence 
  2374.             while(*p2 == (WCHAR)'r' || *p2 == (WCHAR)'n') p2--;
  2375. int len = p2 - p1 + 1; 
  2376. line++;
  2377. if(len > 1)
  2378. {
  2379. if(len > MAX_PATH) 
  2380. {
  2381. p1 = p2 + 1;
  2382. continue;
  2383. }
  2384. ::wcsncpy(buffer, p1, len);
  2385. buffer[len] = WCHAR('');
  2386. //a section ?
  2387.     if(buffer[0] == WCHAR('[') && 
  2388.     buffer[len-1] == WCHAR(']'))
  2389. {
  2390. //AfxMessageBox(buffer);
  2391. if(::wcscmp(buffer,szSection2) == 0) //match
  2392. {
  2393. if(!bSection) 
  2394. {
  2395. bSection = TRUE;
  2396.     posSection = (UINT)(p1 - pHead);
  2397. }
  2398. }
  2399.     else
  2400. {
  2401. if(bSection) return (UINT)-1;
  2402. }
  2403. }
  2404.     else //a key line
  2405. {
  2406. if(!bSection)
  2407. {
  2408. }
  2409.     else
  2410. {
  2411. //key name = value name
  2412. int lenKey = ::wcslen(szKey);
  2413.     //find =
  2414.     int sam;
  2415.     for(sam = 0; sam < len; sam++)
  2416. if(buffer[sam] == WCHAR('=')) break;
  2417.     if(sam >= lenKey && sam < len)
  2418. {
  2419. for(int q = 0; q < sam; q++)
  2420. {
  2421. if(q < lenKey && buffer[q] != szKey[q]) break;
  2422.     if(q > lenKey && buffer[q] != WCHAR(' ')) break;
  2423. }
  2424.     if(q == sam) //found
  2425. {
  2426. bKey = TRUE;
  2427.     return (UINT)(p1 - pHead + sam + 1);
  2428.     //return (UINT)(p1 - pHead);
  2429. }
  2430. }
  2431. }
  2432. }
  2433. line++;
  2434. }
  2435.             break;
  2436. }
  2437. p2--;
  2438. //now p2 points to the ending of the sentence
  2439.         int len = p2 - p1 + 1; //in WCHARs
  2440. line++;
  2441. if(len > 1)
  2442. {
  2443. if(len > MAX_PATH) 
  2444. {
  2445. p1 = p2 + 1;
  2446. continue;
  2447. }
  2448. //this sentence must shorter than MAX_PATH
  2449. ::wcsncpy(buffer, p1, len);
  2450. buffer[len] = WCHAR('');
  2451. //???, lstrcpy seems not add null-trminator
  2452. //buffer[len] = WCHAR('');
  2453. //a section ?
  2454. if(buffer[0] == WCHAR('[') && 
  2455. buffer[len-1] == WCHAR(']'))
  2456. {
  2457. //AfxMessageBox(buffer);
  2458. if(::wcscmp(buffer,szSection2) == 0) //match
  2459. {
  2460. if(!bSection) 
  2461. {
  2462. bSection = TRUE;
  2463. posSection = (UINT)(p1 - pHead);
  2464. }
  2465. }
  2466. else
  2467. {
  2468. if(bSection) return (UINT)-1;
  2469. }
  2470. }
  2471. else //a key line
  2472. {
  2473. if(!bSection)
  2474. {
  2475. }
  2476. else
  2477. {
  2478. //key name = value name
  2479. int lenKey = ::wcslen(szKey);
  2480. //find =
  2481. int sam;
  2482. for(sam = 0; sam < len; sam++)
  2483. if(buffer[sam] == WCHAR('=')) break;
  2484. if(sam >= lenKey && sam < len)
  2485. {
  2486. for(int q = 0; q < sam; q++)
  2487. {
  2488. if(q < lenKey && buffer[q] != szKey[q]) break;
  2489. if(q > lenKey && buffer[q] != WCHAR(' ')) break;
  2490. }
  2491. if(q == sam) //found
  2492. {
  2493. bKey = TRUE;
  2494. return (UINT)(p1 - pHead + sam + 1);
  2495. //return (UINT)(p1 - pHead);
  2496. }
  2497. }
  2498. }
  2499. }
  2500. }
  2501. p1 = p2 + 1;
  2502. }
  2503. return (UINT)-1;
  2504. }
  2505. //return -1 if not find key
  2506. //return first character of the key line 
  2507. //[section name]rn
  2508. //keyname = valuenamern
  2509. //posSection & ret all in WCHARs
  2510. UINT CJXINIFile::GetKeyW(LPWSTR pHead, UINT uSize, 
  2511. LPCWSTR szSection, LPCWSTR szKey, UINT& posSection)
  2512. {
  2513. posSection = -1;
  2514. LPWSTR p1 = pHead;
  2515. LPWSTR p2 = pHead;
  2516. int lenSection = ::wcslen(szSection);
  2517. WCHAR szSection2[MAX_PATH];
  2518. //section --> [section]
  2519.     ::wcsncpy(szSection2+1, szSection, lenSection);
  2520. szSection2[0] = WCHAR('[');
  2521. szSection2[lenSection+1] = WCHAR(']');
  2522. szSection2[lenSection+2] = WCHAR('');
  2523.         
  2524. BOOL bSection = FALSE; //found the section
  2525. BOOL bKey = FALSE;     //found the key
  2526. WCHAR buffer[MAX_PATH]; 
  2527. int line;
  2528. while(p1- pHead < (int)(uSize/sizeof(WCHAR)) - 1)
  2529. {
  2530. //WCHAR s1 = (WCHAR)'r'; //13
  2531. //WCHAR s2 = (WCHAR)'n'; //10
  2532. //WCHAR s3 = (WCHAR)0x0A; //10
  2533. //01/7/5 //avoid leak blank line
  2534. int rInc, nInc;
  2535. rInc = nInc = 0;
  2536. while(p1- pHead < (int)(uSize/sizeof(WCHAR)-1) && 
  2537. (*p1 == (WCHAR)'r' || *p1 == (WCHAR)'n'))
  2538. {
  2539. if(*p1 == (WCHAR)'r') rInc++;
  2540.             if(*p1 == (WCHAR)'n') nInc++;
  2541. p1++;
  2542. }
  2543. if(rInc == 1 && nInc == 1)
  2544. {
  2545. }
  2546. else if(rInc == nInc && rInc > 1)
  2547. line += rInc - 1;
  2548. else if(rInc != nInc)
  2549. {
  2550. line += rInc > nInc ? rInc - 1 : nInc - 1;
  2551. }
  2552. p2 = p1;
  2553. while(p2- pHead < (int)(uSize/sizeof(WCHAR))-1)
  2554. {
  2555. //$$$ some file end  with n only
  2556. if(*p2 == (WCHAR)'r' && *(p2+1) == (WCHAR)'n') 
  2557. {
  2558. break; //touch it
  2559. }
  2560.             if(*p2 == (WCHAR)'n') break;
  2561. if(*p2 == (WCHAR)'r') break;
  2562.     p2++;
  2563. }
  2564. if(p2 - pHead == (int)(uSize/sizeof(WCHAR))-1)
  2565. {
  2566. //the last sentence 
  2567.             while(*p2 == (WCHAR)'r' || *p2 == (WCHAR)'n') p2--;
  2568. int len = p2 - p1 + 1; 
  2569. line++;
  2570. if(len > 1)
  2571. {
  2572. if(len > MAX_PATH) 
  2573. {
  2574. p1 = p2 + 1;
  2575. continue;
  2576. }
  2577. ::wcsncpy(buffer, p1, len);
  2578. buffer[len] = WCHAR('');
  2579. //a section ?
  2580.     if(buffer[0] == WCHAR('[') && 
  2581.     buffer[len-1] == WCHAR(']'))
  2582. {
  2583. //AfxMessageBox(buffer);
  2584. if(::wcscmp(buffer,szSection2) == 0) //match
  2585. {
  2586. if(!bSection) 
  2587. {
  2588. bSection = TRUE;
  2589.     posSection = (UINT)(p1 - pHead);
  2590. }
  2591. }
  2592.     else
  2593. {
  2594. if(bSection) return (UINT)-1;
  2595. }
  2596. }
  2597.     else //a key line
  2598. {
  2599. if(!bSection)
  2600. {
  2601. }
  2602.     else
  2603. {
  2604. //key name = value name
  2605. int lenKey = ::wcslen(szKey);
  2606.     //find =
  2607.     int sam;
  2608.     for(sam = 0; sam < len; sam++)
  2609. if(buffer[sam] == WCHAR('=')) break;
  2610.     if(sam >= lenKey && sam < len)
  2611. {
  2612. for(int q = 0; q < sam; q++)
  2613. {
  2614. if(q < lenKey && buffer[q] != szKey[q]) break;
  2615.     if(q > lenKey && buffer[q] != WCHAR(' ')) break;
  2616. }
  2617.     if(q == sam) //found
  2618. {
  2619. bKey = TRUE;
  2620.     return (UINT)(p1 - pHead + sam + 1);
  2621.     //return (UINT)(p1 - pHead);
  2622. }
  2623. }
  2624. }
  2625. }
  2626. line++;
  2627. }
  2628.             break;
  2629. }
  2630. p2--;
  2631. //now p2 points to the ending of the sentence
  2632.         int len = p2 - p1 + 1; //in WCHARs
  2633. line++;
  2634. if(len > 1)
  2635. {
  2636. if(len > MAX_PATH) 
  2637. {
  2638. p1 = p2 + 1;
  2639. continue;
  2640. }
  2641. //this sentence must shorter than MAX_PATH
  2642. ::wcsncpy(buffer, p1, len);
  2643. buffer[len] = WCHAR('');
  2644. //???, lstrcpy seems not add null-trminator
  2645. //buffer[len] = WCHAR('');
  2646. //a section ?
  2647. if(buffer[0] == WCHAR('[') && 
  2648. buffer[len-1] == WCHAR(']'))
  2649. {
  2650. //AfxMessageBox(buffer);
  2651. if(::wcscmp(buffer,szSection2) == 0) //match
  2652. {
  2653. if(!bSection) 
  2654. {
  2655. bSection = TRUE;
  2656. posSection = (UINT)(p1 - pHead);
  2657. }
  2658. }
  2659. else
  2660. {
  2661. if(bSection) return (UINT)-1;
  2662. }
  2663. }
  2664. else //a key line
  2665. {
  2666. if(!bSection)
  2667. {
  2668. }
  2669. else
  2670. {
  2671. //key name = value name
  2672. int lenKey = ::wcslen(szKey);
  2673. //find =
  2674. int sam;
  2675. for(sam = 0; sam < len; sam++)
  2676. if(buffer[sam] == WCHAR('=')) break;
  2677. if(sam >= lenKey && sam < len)
  2678. {
  2679. for(int q = 0; q < sam; q++)
  2680. {
  2681. if(q < lenKey && buffer[q] != szKey[q]) break;
  2682. if(q > lenKey && buffer[q] != WCHAR(' ')) break;
  2683. }
  2684. if(q == sam) //found
  2685. {
  2686. bKey = TRUE;
  2687. return (UINT)(p1 - pHead + sam + 1);
  2688. //return (UINT)(p1 - pHead);
  2689. }
  2690. }
  2691. }
  2692. }
  2693. }
  2694. p1 = p2 + 1;
  2695. }
  2696. return (UINT)-1;
  2697. }
  2698. UINT CJXINIFile::GetKeyA(LPSTR pHead, UINT uSize, 
  2699. LPCSTR szSection, LPCSTR szKey, UINT& posSection)
  2700. {
  2701. posSection = -1;
  2702. LPSTR p1 = pHead;
  2703. LPSTR p2 = pHead;
  2704. int lenSection = ::strlen(szSection);
  2705. char szSection2[MAX_PATH];
  2706. //section --> [section]
  2707.     ::strncpy(szSection2+1, szSection, lenSection);
  2708. szSection2[0] = char('[');
  2709. szSection2[lenSection+1] = char(']');
  2710. szSection2[lenSection+2] = char('');
  2711.         
  2712. BOOL bSection = FALSE; //found the section
  2713. BOOL bKey = FALSE;     //found the key
  2714. char buffer[MAX_PATH]; 
  2715. int line;
  2716. while(p1- pHead < (int)(uSize/sizeof(char)) - 1)
  2717. {
  2718. //char s1 = (char)'r'; //13
  2719. //char s2 = (char)'n'; //10
  2720. //char s3 = (char)0x0A; //10
  2721. //01/7/5 //avoid leak blank line
  2722. int rInc, nInc;
  2723. rInc = nInc = 0;
  2724. while(p1- pHead < (int)(uSize/sizeof(char)-1) && 
  2725. (*p1 == (char)'r' || *p1 == (char)'n'))
  2726. {
  2727. if(*p1 == (char)'r') rInc++;
  2728.             if(*p1 == (char)'n') nInc++;
  2729. p1++;
  2730. }
  2731. if(rInc == 1 && nInc == 1)
  2732. {
  2733. }
  2734. else if(rInc == nInc && rInc > 1)
  2735. line += rInc - 1;
  2736. else if(rInc != nInc)
  2737. {
  2738. line += rInc > nInc ? rInc - 1 : nInc - 1;
  2739. }
  2740. p2 = p1;
  2741. while(p2- pHead < (int)(uSize/sizeof(char))-1)
  2742. {
  2743. //$$$ some file end  with n only
  2744. if(*p2 == (char)'r' && *(p2+1) == (char)'n') 
  2745. {
  2746. break; //touch it
  2747. }
  2748.             if(*p2 == (char)'n') break;
  2749. if(*p2 == (char)'r') break;
  2750.     p2++;
  2751. }
  2752. if(p2 - pHead == (int)(uSize/sizeof(char))-1)
  2753. {
  2754. //the last sentence 
  2755.             while(*p2 == (char)'r' || *p2 == (char)'n') p2--;
  2756. int len = p2 - p1 + 1; 
  2757. line++;
  2758. if(len > 1)
  2759. {
  2760. if(len > MAX_PATH) 
  2761. {
  2762. p1 = p2 + 1;
  2763. continue;
  2764. }
  2765. ::strncpy(buffer, p1, len);
  2766. buffer[len] = char('');
  2767. //a section ?
  2768.     if(buffer[0] == char('[') && 
  2769.     buffer[len-1] == char(']'))
  2770. {
  2771. //AfxMessageBox(buffer);
  2772. if(::strcmp(buffer,szSection2) == 0) //match
  2773. {
  2774. if(!bSection) 
  2775. {
  2776. bSection = TRUE;
  2777.     posSection = (UINT)(p1 - pHead);
  2778. }
  2779. }
  2780.     else
  2781. {
  2782. if(bSection) return (UINT)-1;
  2783. }
  2784. }
  2785.     else //a key line
  2786. {
  2787. if(!bSection)
  2788. {
  2789. }
  2790.     else
  2791. {
  2792. //key name = value name
  2793. int lenKey = ::strlen(szKey);
  2794.     //find =
  2795.     int sam;
  2796.     for(sam = 0; sam < len; sam++)
  2797. if(buffer[sam] == char('=')) break;
  2798.     if(sam >= lenKey && sam < len)
  2799. {
  2800. for(int q = 0; q < sam; q++)
  2801. {
  2802. if(q < lenKey && buffer[q] != szKey[q]) break;
  2803.     if(q > lenKey && buffer[q] != char(' ')) break;
  2804. }
  2805.     if(q == sam) //found
  2806. {
  2807. bKey = TRUE;
  2808.     return (UINT)(p1 - pHead + sam + 1);
  2809.     //return (UINT)(p1 - pHead);
  2810. }
  2811. }
  2812. }
  2813. }
  2814. line++;
  2815. }
  2816.             break;
  2817. }
  2818. p2--;
  2819. //now p2 points to the ending of the sentence
  2820.         int len = p2 - p1 + 1; //in WCHARs
  2821. line++;
  2822. if(len > 1)
  2823. {
  2824. if(len > MAX_PATH) 
  2825. {
  2826. p1 = p2 + 1;
  2827. continue;
  2828. }
  2829. //this sentence must shorter than MAX_PATH
  2830. ::strncpy(buffer, p1, len);
  2831. buffer[len] = char('');
  2832. //???, lstrcpy seems not add null-trminator
  2833. //buffer[len] = char('');
  2834. //a section ?
  2835. if(buffer[0] == char('[') && 
  2836. buffer[len-1] == char(']'))
  2837. {
  2838. //AfxMessageBox(buffer);
  2839. if(::strcmp(buffer,szSection2) == 0) //match
  2840. {
  2841. if(!bSection) 
  2842. {
  2843. bSection = TRUE;
  2844. posSection = (UINT)(p1 - pHead);
  2845. }
  2846. }
  2847. else
  2848. {
  2849. if(bSection) return (UINT)-1;
  2850. }
  2851. }
  2852. else //a key line
  2853. {
  2854. if(!bSection)
  2855. {
  2856. }
  2857. else
  2858. {
  2859. //key name = value name
  2860. int lenKey = ::strlen(szKey);
  2861. //find =
  2862. int sam;
  2863. for(sam = 0; sam < len; sam++)
  2864. if(buffer[sam] == char('=')) break;
  2865. if(sam >= lenKey && sam < len)
  2866. {
  2867. for(int q = 0; q < sam; q++)
  2868. {
  2869. if(q < lenKey && buffer[q] != szKey[q]) break;
  2870. if(q > lenKey && buffer[q] != char(' ')) break;
  2871. }
  2872. if(q == sam) //found
  2873. {
  2874. bKey = TRUE;
  2875. return (UINT)(p1 - pHead + sam + 1);
  2876. //return (UINT)(p1 - pHead);
  2877. }
  2878. }
  2879. }
  2880. }
  2881. }
  2882. p1 = p2 + 1;
  2883. }
  2884. return (UINT)-1;
  2885. }
  2886. void CJXINIFile::CutZeroTail()
  2887. {
  2888. //AfxMessageBox(m_strFilename);
  2889. //::PopMsg(_T("%s - %d"), m_strFilename, m_dwUseSize);
  2890. if(m_dwUseSize == 0) return; //empty file
  2891. int i = m_dwUseSize - 1;
  2892. LPBYTE pByte = (LPBYTE)m_pData; 
  2893. pByte += m_dwUseSize - sizeof(TCHAR);
  2894.     //if(sizeof(TCHAR) == 1) //MBCS
  2895. if(!this->m_bUnicode)
  2896. {
  2897. while(*pByte == 0x00 && pByte - (LPBYTE)m_pData > 0)
  2898. {
  2899. pByte--;
  2900. m_dwUseSize--;
  2901. }
  2902. }
  2903. else //UNICODE
  2904. {
  2905. while(*pByte == 0x00 && *(pByte+1) == 0x00 &&
  2906. pByte - (LPBYTE)m_pTrueData > 0)
  2907. {
  2908. pByte -= 2;
  2909. m_dwUseSize -= 2;
  2910. }
  2911. }
  2912. //DWORD   m_dwSize; //Current Open File Size in BYTEs
  2913. //DWORD   m_dwUseSize; //Curent Using Size in BYTEs
  2914. //AfxMessageBox(_T("")); //妋擣俷俲
  2915. return;
  2916. }
  2917. DWORD CJXINIFile::DeleteSectionW(
  2918.  LPCWSTR lpAppName        // section name
  2919.     )
  2920. {
  2921.     int lenTargetSec = wcslen(lpAppName);
  2922. LPWSTR pSecHead = NULL;
  2923. LPWSTR pHead = (LPWSTR)m_pTrueData;
  2924. LPWSTR p1 = pHead;
  2925. LPWSTR p2 = pHead;
  2926.         
  2927. while(p1- pHead < (int)(m_dwUseSize/sizeof(WCHAR)) - 1)
  2928. {
  2929. while(p1- pHead < (int)(m_dwUseSize/sizeof(WCHAR)) - 1 &&
  2930. *p1 != WCHAR('['))
  2931. p1++;
  2932. p2 = p1;
  2933. while(p2- pHead < (int)(m_dwUseSize/sizeof(WCHAR)) - 1 &&
  2934. *p2 != WCHAR(']'))
  2935. p2++;
  2936. if(p1- pHead < (int)(m_dwUseSize/sizeof(WCHAR)) &&
  2937. p2- pHead < (int)(m_dwUseSize/sizeof(WCHAR)))
  2938. {
  2939. //Found A Section, Check
  2940. int lenSection = p2 - p1 - 1;
  2941. if(lenSection == lenTargetSec)
  2942. {
  2943. pSecHead = p1;
  2944. for(int i = 0; i < lenTargetSec; i++)
  2945. {
  2946. if(lpAppName[i] != (WCHAR)*(p1+1+i))
  2947. {
  2948.                         pSecHead = NULL;
  2949. break;
  2950. }
  2951. }
  2952. }
  2953. if(pSecHead != NULL) break;
  2954. p1 = p2 + 1;
  2955. }
  2956. if(pSecHead == NULL) return -1;
  2957.     p1 = pSecHead + lenTargetSec;
  2958. while(p1- pHead < (int)(m_dwUseSize/sizeof(WCHAR)) - 1 &&
  2959. *p1 != WCHAR('['))
  2960. p1++;
  2961.    
  2962. if(p1- pHead == (int)(m_dwUseSize/sizeof(WCHAR)) - 1)
  2963. {
  2964. //This is the Last Section
  2965.         m_dwUseSize = sizeof(WCHAR)*(pSecHead-pHead);
  2966. return 0;
  2967. }
  2968. else
  2969. {
  2970. int memLen = m_dwUseSize - (p1 - pHead)*sizeof(WCHAR);
  2971. //C++ Run-time Lib handle overlapped mem
  2972.         memmove(pSecHead, p1, memLen);
  2973. m_dwUseSize -= sizeof(WCHAR)*(p1 - pSecHead);
  2974. }
  2975. return 0;
  2976. }
  2977. DWORD CJXINIFile::DeleteKeyW(
  2978.          LPCWSTR lpAppName,  // section name
  2979.          LPCWSTR lpKeyName  // key name
  2980.     )
  2981. {
  2982. LPWSTR pHead = (LPWSTR)m_pTrueData;
  2983. UINT uSec, uKey;  
  2984. //Warning: uKey, uSec is measured in WCHARs!!!!!
  2985. //in UNICODE now
  2986. uKey = GetKeyW(pHead, (UINT)m_dwUseSize, 
  2987. lpAppName, lpKeyName, uSec);
  2988.     if(uKey == (UINT)-1 && uSec == (UINT)-1) //no section
  2989. {
  2990. return -1;
  2991. }
  2992. else if(uKey == (UINT)-1 && uSec != (UINT)-1) 
  2993. //section exist but value do not exist
  2994. {
  2995. return -1;
  2996. }
  2997. else //key exist
  2998. {
  2999. ASSERT(uKey != (UINT)-1);
  3000.         LPWSTR pValue = pHead + uKey;
  3001.     while(pValue - pHead < (int)(m_dwUseSize/sizeof(WCHAR)) && 
  3002.     *pValue != WCHAR('r') && *pValue != WCHAR('n'))
  3003. {
  3004. pValue++;
  3005. }
  3006.     while(*pValue == WCHAR('r') || *pValue == WCHAR('n'))
  3007. pValue++;
  3008. int lenKey = pValue - pHead - uKey;
  3009.         LPWSTR pKeyHead = pHead + uKey;
  3010. int lenMove = m_dwUseSize - (pValue - pHead)*sizeof(WCHAR);
  3011. memmove(pKeyHead, pValue, lenMove);
  3012.         m_dwUseSize -= lenKey*sizeof(WCHAR);
  3013. }
  3014. this->m_bSectionMapDirty = TRUE;
  3015. return 0;
  3016. }
  3017. DWORD CJXINIFile::DeleteSectionExW(
  3018.  LPCWSTR lpAppName        // section name
  3019.     )
  3020. {
  3021. ASSERT(!this->m_bSectionMapLock);
  3022. if(this->m_bSectionMapDirty)
  3023. this->UpdateMapW();
  3024.     LPWSTR lpHead = (LPWSTR)m_pTrueData;    
  3025. CString strKey;
  3026. LPWSTR lpPos;
  3027. #ifdef _UNICODE
  3028. strKey = lpAppName;
  3029. #else
  3030. DWORD dwRetSize;
  3031. LPSTR pTemp = _W2A((LPWSTR)lpAppName, -1, dwRetSize);
  3032. ::strncpy(strKey.GetBuffer(dwRetSize), pTemp, dwRetSize);
  3033. strKey.ReleaseBuffer(dwRetSize);
  3034. #endif
  3035. //No Such Section Exists
  3036. LPVOID lpVoid;
  3037. if(!m_mapSection.Lookup(strKey, lpVoid)) return -1;
  3038.     ASSERT(m_mapSection.RemoveKey(strKey));
  3039. lpPos = (LPWSTR)lpVoid;
  3040. LPWSTR lpSection = (LPWSTR)lpPos;
  3041.     
  3042. LPWSTR lpNextSec = NULL;
  3043. int distance = -1;
  3044. POSITION pos = m_mapSection.GetStartPosition();
  3045. while(pos)
  3046. {
  3047. CString strKey2;
  3048. LPWSTR lpPos2;
  3049. m_mapSection.GetNextAssoc(pos, strKey2, lpVoid);
  3050. lpPos2 = (LPWSTR)lpVoid;
  3051. if(lpPos2 - lpPos > 0)
  3052. {
  3053. if(distance == -1) 
  3054. {
  3055. distance = lpPos2 - lpPos;
  3056. lpNextSec = lpPos2;
  3057. }
  3058. else
  3059. {
  3060. if(lpPos2 - lpPos < distance)
  3061. {
  3062. distance = lpPos2 - lpPos;
  3063.     lpNextSec = lpPos2;
  3064. }
  3065. }
  3066. }
  3067. }
  3068.     
  3069. if(lpNextSec == NULL)
  3070. {
  3071. ASSERT(distance == -1);
  3072. //This is the Last Section
  3073.         m_dwUseSize = sizeof(WCHAR)*(lpPos-lpHead);
  3074. return 0;
  3075. }
  3076. else
  3077. {
  3078. int memLen = m_dwUseSize - (lpNextSec - lpHead)*sizeof(WCHAR);
  3079. //C++ Run-time Lib handle overlapped mem
  3080.         memmove((LPVOID)lpPos, (LPVOID)lpNextSec, memLen);
  3081. m_dwUseSize -= sizeof(WCHAR)*(lpNextSec - lpPos);
  3082. }
  3083.     
  3084. //m_bSectionMapDirty = TRUE;
  3085. //return TRUE;
  3086. int lenSec = lpNextSec - lpPos;
  3087. if(m_bSectionMapLock)
  3088. m_bSectionMapDirty = TRUE;
  3089. }
  3090. else //update section map
  3091. {
  3092. POSITION pos = m_mapSection.GetStartPosition();
  3093.     while(pos)
  3094. {
  3095. CString strTemp;
  3096.         LPVOID lpTemp;
  3097.         m_mapSection.GetNextAssoc(pos, strTemp, lpTemp);
  3098.      //adjust Section Map
  3099. if((LPWSTR)lpTemp - lpSection > 0)
  3100. {
  3101. LPWSTR lp = (LPWSTR)lpTemp;
  3102. lp -= lenSec;
  3103. lpTemp = (LPVOID)lp;
  3104. m_mapSection.SetAt(strTemp, lpTemp);
  3105. }
  3106. }
  3107. }
  3108. return TRUE;
  3109. }
  3110. DWORD CJXINIFile::DeleteKeyExW(
  3111.          LPCWSTR lpAppName,  // section name
  3112.          LPCWSTR lpKeyName  // key name
  3113.     )
  3114. {
  3115. LPWSTR pHead = (LPWSTR)m_pTrueData;
  3116. UINT uSec, uKey;  
  3117. //Warning: uKey, uSec is measured in WCHARs!!!!!
  3118. //in UNICODE now
  3119. uKey = GetKeyExW(pHead, (UINT)m_dwUseSize, 
  3120. lpAppName, lpKeyName, uSec);
  3121.     if(uKey == (UINT)-1 && uSec == (UINT)-1) //no section
  3122. {
  3123. return -1;
  3124. }
  3125. else if(uKey == (UINT)-1 && uSec != (UINT)-1) 
  3126. //section exist but value do not exist
  3127. {
  3128. return -1;
  3129. }
  3130. else //key exist
  3131. {
  3132. ASSERT(uKey != (UINT)-1);
  3133. LPWSTR pSection = pHead + uSec;
  3134.         LPWSTR pValue = pHead + uKey;
  3135.     while(pValue - pHead < (int)(m_dwUseSize/sizeof(WCHAR)) && 
  3136.     *pValue != WCHAR('r') && *pValue != WCHAR('n'))
  3137. {
  3138. pValue++;
  3139. }
  3140.     while(*pValue == WCHAR('r') || *pValue == WCHAR('n'))
  3141. pValue++;
  3142. int lenKey = pValue - pHead - uKey;
  3143.         LPWSTR pKeyHead = pHead + uKey;
  3144. int lenMove = m_dwUseSize - (pValue - pHead)*sizeof(WCHAR);
  3145. memmove(pKeyHead, pValue, lenMove);
  3146.         m_dwUseSize -= lenKey*sizeof(WCHAR);
  3147. if(m_bSectionMapLock)
  3148. m_bSectionMapDirty = TRUE;
  3149. }
  3150. else //update section map
  3151. {
  3152. POSITION pos = m_mapSection.GetStartPosition();
  3153.         while(pos)
  3154. {
  3155. CString strKey;
  3156.         LPVOID lpPos;
  3157.         m_mapSection.GetNextAssoc(pos, strKey, lpPos);
  3158.      //adjust Section Map
  3159. if((LPWSTR)lpPos - pSection > 0)
  3160. {
  3161. LPWSTR pTemp = (LPWSTR)lpPos;
  3162. pTemp -= lenKey;
  3163. lpPos = (LPVOID)pTemp;
  3164. m_mapSection.SetAt(strKey, lpPos);
  3165. }
  3166. }
  3167. }
  3168. }
  3169. return 0;
  3170. }
  3171. DWORD CJXINIFile::DeleteSectionExA(
  3172.  LPCSTR lpAppName        // section name
  3173.     )
  3174. {
  3175. return 0;
  3176. }
  3177. DWORD CJXINIFile::DeleteKeyExA(
  3178.          LPCSTR lpAppName,  // section name
  3179.          LPCSTR lpKeyName  // key name
  3180.     )
  3181. {
  3182. return 0;
  3183. }
  3184. DWORD CJXINIFile::DeleteSectionA(
  3185.  LPCSTR lpAppName        // section name
  3186.     )
  3187. {
  3188. return 0;
  3189. }
  3190. DWORD CJXINIFile::DeleteKeyA(
  3191.          LPCSTR lpAppName,  // section name
  3192.          LPCSTR lpKeyName  // key name
  3193.     )
  3194. {
  3195. return 0;
  3196. }
  3197. //-------------------------------------------------------------------
  3198. //-------------Export Part ------------------------------------------
  3199. //UNICODE & ANSI Version
  3200. CJXINIFile& GetINIFileClass()
  3201. {
  3202. static CJXINIFile g_clsINIFile;
  3203. return g_clsINIFile;
  3204. }
  3205. DWORD JXGetPrivateProfileStringW(
  3206.   LPCWSTR lpAppName,        // section name
  3207.   LPCWSTR lpKeyName,        // key name
  3208.   LPCWSTR lpDefault,        // default string
  3209.   LPWSTR lpReturnedString,  // destination buffer
  3210.   DWORD nSize,              // size of destination buffer
  3211.   LPCWSTR lpFileName        // initialization file name
  3212.  )
  3213. {
  3214. return GetINIFileClass().GetPrivateProfileStringExW(
  3215. lpAppName,        // section name
  3216.         lpKeyName,        // key name
  3217.         lpDefault,        // default string
  3218.         lpReturnedString,  // destination buffer
  3219.         nSize,              // size of destination buffer
  3220.         lpFileName        // initialization file name
  3221. );
  3222. }
  3223. BOOL JXWritePrivateProfileStringW(
  3224.   LPCWSTR lpAppName,  // section namen
  3225.   LPCWSTR lpKeyName,  // key name
  3226.   LPCWSTR lpString,   // string to add
  3227.   LPCWSTR lpFileName  // initialization file
  3228.  )
  3229. {
  3230. return GetINIFileClass().WritePrivateProfileStringExW(
  3231.         lpAppName,  // section namen
  3232.         lpKeyName,  // key name
  3233.         lpString,   // string to add
  3234.         lpFileName  // initialization file
  3235. );
  3236. }
  3237. //ANSI VERSION
  3238. DWORD JXGetPrivateProfileStringA(
  3239.   LPCSTR lpAppName,        // section name
  3240.   LPCSTR lpKeyName,        // key name
  3241.   LPCSTR lpDefault,        // default string
  3242.   LPSTR lpReturnedString,  // destination buffer
  3243.   DWORD nSize,              // size of destination buffer
  3244.   LPCSTR lpFileName        // initialization file name
  3245.  )
  3246. {
  3247. return GetINIFileClass().GetPrivateProfileStringExA(
  3248. lpAppName,        // section name
  3249.         lpKeyName,        // key name
  3250.         lpDefault,        // default string
  3251.         lpReturnedString,  // destination buffer
  3252.         nSize,              // size of destination buffer
  3253.         lpFileName        // initialization file name
  3254. );
  3255. }
  3256. //Warning: Using namespace for WinAPI have the same name
  3257. BOOL JXWritePrivateProfileStringA(
  3258.   LPCSTR lpAppName,  // section namen
  3259.   LPCSTR lpKeyName,  // key name
  3260.   LPCSTR lpString,   // string to add
  3261.   LPCSTR lpFileName  // initialization file
  3262.  )
  3263. {
  3264. return GetINIFileClass().WritePrivateProfileStringExA(
  3265.         lpAppName,  // section namen
  3266.         lpKeyName,  // key name
  3267.         lpString,   // string to add
  3268.         lpFileName  // initialization file
  3269. );
  3270. }
  3271. DWORD ControlINI(DWORD dwControl)
  3272. {
  3273. #define INI_SET_DIRTY_MAP  0
  3274. #define INI_SET_LOCK_MAP   1
  3275. #define INI_SET_UNLOCK_MAP 2
  3276. #define INI_UPDATE_MAP     3
  3277. switch(dwControl)
  3278. {
  3279. case INI_SET_DIRTY_MAP:
  3280.         GetINIFileClass().m_bSectionMapDirty = TRUE;
  3281. break;
  3282. case INI_SET_LOCK_MAP:
  3283.         GetINIFileClass().m_bSectionMapLock = TRUE;
  3284. break;
  3285.     case INI_SET_UNLOCK_MAP:
  3286.         GetINIFileClass().m_bSectionMapLock = FALSE;
  3287. break;
  3288. case INI_UPDATE_MAP:
  3289. #ifdef _UNICODE
  3290. GetINIFileClass().UpdateMapW();
  3291. #else
  3292. GetINIFileClass().UpdateMapA();
  3293. #endif
  3294. break;
  3295. default:
  3296. break;
  3297. }
  3298. return 0;
  3299. }
  3300. //Flush Memory Data To Disk File and Close File Handle
  3301. BOOL JXUnloadPrivateProfile()
  3302. {
  3303. return GetINIFileClass().UnloadIniFile();
  3304. }
  3305. BOOL JXRenameSectionExW(
  3306.   LPCWSTR lpAppName,        // section name
  3307.   LPCWSTR lpNewName,        // new section name
  3308.   LPCWSTR lpFileName        // initialization file name
  3309.  )
  3310. {
  3311. return GetINIFileClass().RenameSectionExW(
  3312. lpAppName,        // section name
  3313.         lpNewName,        // new section name
  3314.         lpFileName        // initialization file name
  3315. );
  3316. }
  3317. BOOL JXCopySectionExW(
  3318.   LPCWSTR lpAppName,        // section name
  3319.   LPCWSTR lpNewName,        // new section name
  3320.   LPCWSTR lpFileName        // initialization file name
  3321.  )
  3322. {
  3323. return GetINIFileClass().CopySectionExW(
  3324. lpAppName,        // section name
  3325.         lpNewName,        // new section name
  3326.         lpFileName        // initialization file name
  3327. );
  3328. }
  3329. BOOL CJXINIFile::RenameSectionExW(
  3330.   LPCWSTR lpAppName,        // section name
  3331.   LPCWSTR lpNewName,        // new section name
  3332.   LPCWSTR lpFileName        // initialization file name
  3333.  )
  3334. {
  3335. BOOL bRet = LoadIniFile(lpFileName, 2);  //Unicode Text
  3336. if(!bRet) 
  3337. {
  3338. AfxMessageBox(_T("CJXINIFile::RenameSectionExW - LoadIniFile Err"));
  3339. return FALSE;
  3340. }
  3341. //If Section Locked And Section Dirty ASSERT(FALSE);
  3342.     ASSERT(!(m_bSectionMapLock && m_bSectionMapDirty));
  3343. if(m_bSectionMapDirty) this->UpdateMapW();
  3344.     LPWSTR pHead = (LPWSTR)m_pTrueData;    
  3345. CString strKey, strNewKey;
  3346. LPWSTR lpPos;
  3347. #ifdef _UNICODE
  3348. strKey = lpAppName;
  3349. strNewKey = lpNewName;
  3350. #else
  3351. DWORD dwRetSize;
  3352. LPSTR pTemp = _W2A((LPWSTR)lpAppName, -1, dwRetSize);
  3353. ::strncpy(strKey.GetBuffer(dwRetSize), pTemp, dwRetSize);
  3354. strKey.ReleaseBuffer(dwRetSize);
  3355. pTemp = _W2A((LPWSTR)lpNewName, -1, dwRetSize);
  3356. ::strncpy(strNewKey.GetBuffer(dwRetSize), pTemp, dwRetSize);
  3357. strNewKey.ReleaseBuffer(dwRetSize);
  3358. #endif
  3359. //No Such Section Exists
  3360. LPVOID lpVoid;
  3361. if(!m_mapSection.Lookup(strKey, lpVoid)) 
  3362. {
  3363. #ifdef _DEBUG
  3364. AfxMessageBox(_T("CJXINIFile::RenameSectionExW - lpAppName Not Found") + strKey);
  3365. #endif
  3366. return FALSE;
  3367. }
  3368.     m_mapSection.RemoveKey(strKey);
  3369. lpPos = (LPWSTR)lpVoid;
  3370. LPWSTR lpSection = (LPWSTR)lpPos;
  3371.     
  3372. int oldLen = ::wcslen(lpAppName);
  3373. int newLen = ::wcslen(lpNewName);
  3374. m_mapSection.SetAt(strNewKey, (LPVOID)lpSection);
  3375. if(newLen == oldLen)
  3376. {
  3377. ::wcscspn((LPWSTR)(lpSection+1), (LPCWSTR)lpNewName); //[
  3378. return TRUE;
  3379. }
  3380. //Hard Time Now
  3381. if(newLen < oldLen)
  3382. {
  3383. int memLen = m_dwUseSize - (lpSection - pHead + oldLen + 2)*sizeof(WCHAR);
  3384. //C++ Run-time Lib handle overlapped mem
  3385. LPWSTR buffer = new WCHAR[newLen+2];
  3386. ::swprintf(buffer, L"[%s]", lpNewName);
  3387. memmove(lpSection+2+newLen, lpSection+2+oldLen, memLen);
  3388. ::wcsncpy(lpSection, buffer, newLen+2);
  3389. m_dwUseSize -= sizeof(WCHAR)*(oldLen-newLen);
  3390. }
  3391. else
  3392. {
  3393. int memLen = m_dwUseSize - (lpSection - pHead + oldLen + 2)*sizeof(WCHAR);
  3394. //C++ Run-time Lib handle overlapped mem
  3395. LPWSTR buffer = new WCHAR[newLen+2];
  3396. ::swprintf(buffer, L"[%s]", lpNewName);
  3397. memmove(lpSection+2+newLen, lpSection+2+oldLen, memLen);
  3398. ::wcsncpy(lpSection, buffer, newLen+2);
  3399. m_dwUseSize += sizeof(WCHAR)*(newLen-oldLen);
  3400. }
  3401.  
  3402. //Adjust Section Map if Applicable
  3403. if(m_bSectionMapLock)
  3404. m_bSectionMapDirty = TRUE;
  3405. }
  3406. else //update section map
  3407. {
  3408. POSITION pos = m_mapSection.GetStartPosition();
  3409.     while(pos)
  3410. {
  3411. CString strKey;
  3412.         LPVOID lpPos;
  3413.         m_mapSection.GetNextAssoc(pos, strKey, lpPos);
  3414.      //adjust Section Map
  3415. if((LPWSTR)lpPos - lpSection > 0)
  3416. {
  3417. LPWSTR pTemp = (LPWSTR)lpPos;
  3418. pTemp += newLen-oldLen;
  3419. lpPos = (LPVOID)pTemp;
  3420. m_mapSection.SetAt(strKey, lpPos);
  3421. }
  3422. }
  3423. }
  3424. return TRUE;
  3425. }
  3426. BOOL CJXINIFile::CopySectionExW(
  3427.   LPCWSTR lpAppName,        // section name
  3428.   LPCWSTR lpNewName,        // new section name
  3429.   LPCWSTR lpFileName        // initialization file name
  3430.  )
  3431. {
  3432.     BOOL bRet = LoadIniFile(lpFileName, 2);  //Unicode Text
  3433. if(!bRet) 
  3434. {
  3435. AfxMessageBox(_T("CJXINIFile::CopySectionExW - LoadIniFile Err"));
  3436. return FALSE;
  3437. }
  3438. if(m_bSectionMapLock) 
  3439. {
  3440. AfxMessageBox(_T("CJXINIFile::CopySectionExW - Map Locked Err"));
  3441. return FALSE;
  3442. }
  3443. if(m_bSectionMapDirty) this->UpdateMapW();
  3444. m_bSectionMapLock = FALSE;
  3445. LPWSTR lpHead = (LPWSTR)m_pTrueData;    
  3446. CString strKey, strNewKey;
  3447. LPWSTR lpPos;
  3448. #ifdef _UNICODE
  3449. strKey = lpAppName;
  3450. strNewKey = lpNewName;
  3451. #else
  3452. DWORD dwRetSize;
  3453. LPSTR pTemp = _W2A((LPWSTR)lpAppName, -1, dwRetSize);
  3454. ::strncpy(strKey.GetBuffer(dwRetSize), pTemp, dwRetSize);
  3455. strKey.ReleaseBuffer(dwRetSize);
  3456. pTemp = _W2A((LPWSTR)lpNewName, -1, dwRetSize);
  3457. ::strncpy(strNewKey.GetBuffer(dwRetSize), pTemp, dwRetSize);
  3458. strNewKey.ReleaseBuffer(dwRetSize);
  3459. #endif
  3460. //No Such Section Exists
  3461. LPVOID lpVoid;
  3462. if(!m_mapSection.Lookup(strKey, lpVoid)) 
  3463. {
  3464. #ifdef _DEBUG
  3465. AfxMessageBox(_T("CJXINIFile::CopySectionExW - lpAppName Not Found") + strKey);
  3466. #endif
  3467. return FALSE;
  3468. }
  3469.     lpPos = (LPWSTR)lpVoid;
  3470. LPWSTR lpSection = (LPWSTR)lpPos;
  3471.    
  3472. //The lpNewName -- New Section Name Should not Exist
  3473.     if(m_mapSection.Lookup(strNewKey, lpVoid)) 
  3474. {
  3475. AfxMessageBox(_T("CJXINIFile::CopySectionExW - lpNewName Exist"));
  3476.     return FALSE;
  3477. }
  3478. UINT secBodySize = GetSectionSizeExW(lpAppName, lpFileName);
  3479.     secBodySize -= 2 + ::wcslen(lpAppName);
  3480. if((int)(m_dwUseSize - m_dwSize + 
  3481. (secBodySize+::wcslen(lpNewName))*sizeof(WCHAR)) > JXFlushIncrement - 5*JXPage)
  3482. {
  3483. //::MessageBoxW(NULL, lpAppName, lpNewName, MB_OK);
  3484. //if the Section Reproduction Need Too Much Space
  3485. //Flush Back to HardDisk First. Then Append It
  3486. LPVOID lpMem = ::VirtualAlloc(NULL, (secBodySize+::wcslen(lpNewName))*sizeof(WCHAR),
  3487. MEM_COMMIT, PAGE_READWRITE);
  3488. if(!lpMem) 
  3489. {
  3490. ::MessageBox(NULL, _T("CopySection"), _T("VirtualAlloc Err"), MB_OK);
  3491. return FALSE;
  3492. }
  3493. ::memcpy(lpMem, lpSection + 2 + ::wcslen(lpAppName), secBodySize*sizeof(WCHAR));
  3494. UnloadIniFile();
  3495. m_bSectionMapDirty = TRUE;
  3496. //Write To Disk
  3497.         HANDLE hFile = ::CreateFileW(lpFileName, GENERIC_WRITE,
  3498.  FILE_SHARE_READ, NULL, OPEN_EXISTING, 
  3499.  FILE_ATTRIBUTE_NORMAL, NULL);
  3500.     if(hFile == INVALID_HANDLE_VALUE) 
  3501. {
  3502. ::MessageBox(NULL, _T("CopySectionExW"), _T("CreateFileW Err"), MB_OK);
  3503. return FALSE;
  3504. }
  3505. LONG l = 0;
  3506. ::SetFilePointer(hFile, 0, &l, FILE_END);
  3507. LPWSTR buffer = new WCHAR[2 + ::wcslen(lpNewName)];
  3508.         ::swprintf(buffer, L"[%s]", lpNewName);
  3509. DWORD dwRet;
  3510. ::WriteFile(hFile, buffer, sizeof(WCHAR)*(2 + ::wcslen(lpNewName)), &dwRet, NULL);
  3511. ::WriteFile(hFile, lpMem, sizeof(WCHAR)*secBodySize, &dwRet, NULL);
  3512. ::CloseHandle(hFile);
  3513. return TRUE;
  3514. }
  3515. else
  3516. {
  3517. LPWSTR lpNewSec = lpHead + m_dwUseSize/sizeof(WCHAR);
  3518. if(!m_bSectionMapLock)
  3519. {
  3520. m_mapSection.SetAt(strNewKey, (LPVOID)lpNewSec);
  3521. }
  3522. else
  3523. m_bSectionMapDirty = TRUE;
  3524.         ::swprintf(lpNewSec, L"[%s]", lpNewName);
  3525. lpNewSec += 2 + ::wcslen(lpNewName);
  3526. ::memcpy(lpNewSec, lpSection + 2 + ::wcslen(lpAppName), sizeof(WCHAR)*secBodySize);
  3527.         m_dwUseSize += (secBodySize + ::wcslen(lpNewName) + 2)*sizeof(WCHAR); 
  3528. }
  3529. return TRUE;
  3530. }
  3531. //in WCHARs, return 0 when err, Section Map Version
  3532. UINT CJXINIFile::GetSectionSizeExW(
  3533.    LPCWSTR lpAppName,        // section name
  3534.        LPCWSTR lpFileName)        // initialization file name
  3535. {
  3536. BOOL bRet = LoadIniFile(lpFileName, 2);  //Unicode Text
  3537. if(!bRet) return FALSE;
  3538. CString strKey;
  3539. #ifdef _UNICODE
  3540. strKey = lpAppName;
  3541. #else
  3542. DWORD dwRetSize;
  3543. LPSTR pTemp = _W2A((LPWSTR)lpAppName, -1, dwRetSize);
  3544. ::strncpy(strKey.GetBuffer(dwRetSize), pTemp, dwRetSize);
  3545. strKey.ReleaseBuffer(dwRetSize);
  3546. #endif
  3547. LPWSTR pHead = (LPWSTR)m_pTrueData; 
  3548. //if No Such Section Exists
  3549. LPVOID lpVoid;
  3550. if(!m_mapSection.Lookup(strKey, lpVoid)) return 0;
  3551.     LPWSTR lpPos = (LPWSTR)lpVoid;
  3552. LPWSTR lpSection = (LPWSTR)lpPos;
  3553. LPWSTR lpNextSec = NULL;
  3554. int distance = -1;
  3555. POSITION pos = m_mapSection.GetStartPosition();
  3556. while(pos)
  3557. {
  3558. CString strKey2;
  3559. LPWSTR lpPos2;
  3560. m_mapSection.GetNextAssoc(pos, strKey2, lpVoid);
  3561. lpPos2 = (LPWSTR)lpVoid;
  3562. if(lpPos2 - lpPos > 0)
  3563. {
  3564. if(distance == -1) 
  3565. {
  3566. distance = lpPos2 - lpPos;
  3567. lpNextSec = lpPos2;
  3568. }
  3569. else
  3570. {
  3571. if(lpPos2 - lpPos < distance)
  3572. {
  3573. distance = lpPos2 - lpPos;
  3574.     lpNextSec = lpPos2;
  3575. }
  3576. }
  3577. }
  3578. }
  3579.  
  3580. if(lpNextSec == NULL)
  3581. {
  3582. ASSERT(distance == -1);
  3583. //This is the Last Section
  3584.         return m_dwUseSize/sizeof(WCHAR) - (lpPos-pHead);
  3585. }
  3586. else
  3587. {
  3588.         return lpNextSec - lpPos;
  3589. }
  3590.     return 0;
  3591. }
  3592. ////in WCHARs, return 0 when err,
  3593. UINT CJXINIFile::GetSectionSizeW(
  3594.    LPCWSTR lpAppName,        // section name
  3595.        LPCWSTR lpFileName)        // initialization file name
  3596. {
  3597. return 0;
  3598. }