Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

520 lines
11 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1996 - 1999
  6. //
  7. // File: fparse.cpp
  8. //
  9. // Contents: File parsing api -- INI file types
  10. //
  11. // History: 01-Oct-1997 pberkman create
  12. //
  13. //--------------------------------------------------------------------------
  14. #include "global.hxx"
  15. #include "fparse.hxx"
  16. fParse_::fParse_(WCHAR *pwszFilename, BOOL *pfFailed, DWORD dwMaxLine0, DWORD dwFileAccess, DWORD dwFileSharing)
  17. {
  18. hFile = INVALID_HANDLE_VALUE;
  19. dwMaxLine = dwMaxLine0;
  20. pwszCurrentLine = NULL;
  21. dwCurLineFilePos = 0;
  22. dwLastGroupFilePos = 0;
  23. dwLastTagFilePos = 0;
  24. fEOF = FALSE;
  25. pwszTempFName = NULL;
  26. pwszLastGroupTag = NULL;
  27. __try
  28. {
  29. hFile = CreateFileU(
  30. pwszFilename,
  31. dwFileAccess,
  32. dwFileSharing,
  33. NULL,
  34. OPEN_EXISTING,
  35. FILE_ATTRIBUTE_NORMAL,
  36. NULL);
  37. pwszCurrentLine = new WCHAR[dwMaxLine];
  38. if (pwszFName = new WCHAR[wcslen(pwszFilename) + 1])
  39. {
  40. wcscpy(pwszFName, pwszFilename);
  41. }
  42. if ((hFile == INVALID_HANDLE_VALUE) ||
  43. (pwszCurrentLine == NULL) ||
  44. (pwszFName == NULL))
  45. {
  46. *pfFailed = TRUE;
  47. }
  48. else
  49. {
  50. *pfFailed = FALSE;
  51. }
  52. } // __try
  53. __except(EXCEPTION_EXECUTE_HANDLER)
  54. {
  55. if (hFile != INVALID_HANDLE_VALUE)
  56. {
  57. CloseHandle(hFile);
  58. hFile = INVALID_HANDLE_VALUE;
  59. }
  60. if (pwszCurrentLine != NULL)
  61. {
  62. DELETE_OBJECT(pwszCurrentLine);
  63. pwszCurrentLine = NULL;
  64. }
  65. if (pwszFName != NULL)
  66. {
  67. DELETE_OBJECT(pwszFName);
  68. pwszFName = NULL;
  69. }
  70. *pfFailed = FALSE;
  71. }
  72. }
  73. fParse_::~fParse_(void)
  74. {
  75. if (hFile != INVALID_HANDLE_VALUE)
  76. {
  77. CloseHandle(hFile);
  78. }
  79. if (pwszCurrentLine)
  80. {
  81. DELETE_OBJECT(pwszCurrentLine);
  82. }
  83. DELETE_OBJECT(pwszLastGroupTag);
  84. if (pwszTempFName)
  85. {
  86. CopyFileU(pwszTempFName, pwszFName, FALSE);
  87. DeleteFileU(pwszTempFName);
  88. delete pwszTempFName;
  89. }
  90. if (pwszFName != NULL)
  91. {
  92. DELETE_OBJECT(pwszFName);
  93. }
  94. }
  95. BOOL fParse_::AddTagToFile(WCHAR *pwszGroup, WCHAR *pwszTag, WCHAR *pwszValue)
  96. {
  97. if (!(this->pwszCurrentLine) || (this->hFile == INVALID_HANDLE_VALUE))
  98. {
  99. return(FALSE);
  100. }
  101. char szTFile[MAX_PATH * 2];
  102. WCHAR wszGroup[MAX_PATH];
  103. HANDLE hTFile;
  104. DWORD ccTFile;
  105. DWORD cbWrite;
  106. BOOL fWritten;
  107. if (!(pwszLastGroupTag))
  108. {
  109. return(FALSE);
  110. }
  111. if (pwszTag[0] != L'[')
  112. {
  113. wcscpy(&wszGroup[0], L"[");
  114. wcscat(&wszGroup[0], pwszGroup);
  115. wcscat(&wszGroup[0], L"]");
  116. }
  117. else
  118. {
  119. wcscpy(&wszGroup[0], pwszTag);
  120. }
  121. szTFile[0] = NULL;
  122. GetTempFileName(".", "FPS", 0, &szTFile[0]);
  123. if (!(szTFile[0]))
  124. {
  125. return(FALSE);
  126. }
  127. ccTFile = MultiByteToWideChar(0, 0, &szTFile[0], -1, NULL, 0);
  128. if (ccTFile < 1)
  129. {
  130. return(FALSE);
  131. }
  132. if (!(pwszTempFName = new WCHAR[ccTFile + 1]))
  133. {
  134. return(FALSE);
  135. }
  136. MultiByteToWideChar(0, 0, &szTFile[0], -1, pwszTempFName, ccTFile + 1);
  137. hTFile = CreateFileU(pwszTempFName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS,
  138. FILE_ATTRIBUTE_NORMAL, NULL);
  139. if (hTFile == INVALID_HANDLE_VALUE)
  140. {
  141. return(FALSE);
  142. }
  143. SetFilePointer(this->hFile, 0, NULL, FILE_BEGIN);
  144. fWritten = FALSE;
  145. while (this->GetNextLine())
  146. {
  147. szTFile[0] = NULL;
  148. WideCharToMultiByte(0, 0, this->pwszCurrentLine, wcslen(this->pwszCurrentLine) + 1,
  149. &szTFile[0], MAX_PATH * 2, NULL, NULL);
  150. if (szTFile[0])
  151. {
  152. WriteFile(hTFile, &szTFile[0], strlen(&szTFile[0]), &cbWrite, NULL);
  153. if (!(fWritten))
  154. {
  155. this->EOLRemove();
  156. if (_memicmp(this->pwszCurrentLine, &wszGroup[0],
  157. wcslen(&wszGroup[0]) * sizeof(WCHAR)) == 0)
  158. {
  159. //
  160. // add our line
  161. //
  162. szTFile[0] = NULL;
  163. WideCharToMultiByte(0, 0, pwszTag, wcslen(pwszTag) + 1, &szTFile[0], MAX_PATH, NULL, NULL);
  164. WriteFile(hTFile, &szTFile[0], strlen(&szTFile[0]), &cbWrite, NULL);
  165. WriteFile(hTFile, "=", 1, &cbWrite, NULL);
  166. szTFile[0] = NULL;
  167. WideCharToMultiByte(0, 0, pwszValue, wcslen(pwszValue) + 1, &szTFile[0], MAX_PATH * 2, NULL, NULL);
  168. WriteFile(hTFile, &szTFile[0], strlen(&szTFile[0]), &cbWrite, NULL);
  169. WriteFile(hTFile, "\r\n", 2, &cbWrite, NULL);
  170. fWritten = TRUE;
  171. }
  172. }
  173. }
  174. }
  175. CloseHandle(hTFile);
  176. this->Reset();
  177. return(TRUE);
  178. }
  179. void fParse_::Reset(void)
  180. {
  181. this->dwCurLineFilePos = 0;
  182. this->dwLastGroupFilePos = 0;
  183. this->dwLastTagFilePos = 0;
  184. SetFilePointer(this->hFile, 0, NULL, FILE_BEGIN);
  185. }
  186. BOOL fParse_::PositionAtLastGroup(void)
  187. {
  188. if (SetFilePointer(this->hFile, this->dwLastGroupFilePos, NULL,
  189. FILE_BEGIN) == 0xFFFFFFFF)
  190. {
  191. return(FALSE);
  192. }
  193. return(TRUE);
  194. }
  195. BOOL fParse_::PositionAtLastTag(void)
  196. {
  197. if (this->dwLastTagFilePos == 0)
  198. {
  199. return(FALSE);
  200. }
  201. if (SetFilePointer(this->hFile, this->dwLastTagFilePos, NULL,
  202. FILE_BEGIN) == 0xFFFFFFFF)
  203. {
  204. return(FALSE);
  205. }
  206. return(TRUE);
  207. }
  208. BOOL fParse_::GetLineInCurrentGroup(void)
  209. {
  210. if (this->dwLastGroupFilePos == 0)
  211. {
  212. return(FALSE);
  213. }
  214. if (this->dwLastTagFilePos == 0)
  215. {
  216. this->PositionAtLastGroup();
  217. }
  218. while (this->GetNextLine() > 0)
  219. {
  220. if ((this->pwszCurrentLine[0] == L'#') ||
  221. (this->pwszCurrentLine[0] == L';') ||
  222. (this->pwszCurrentLine[0] == 0x000d))
  223. {
  224. continue;
  225. }
  226. if (this->pwszCurrentLine[0] == L'[')
  227. {
  228. this->pwszCurrentLine[0] = NULL;
  229. return(FALSE);
  230. }
  231. this->EOLRemove();
  232. if (wcslen(this->pwszCurrentLine) > 0)
  233. {
  234. this->dwLastTagFilePos = this->dwCurLineFilePos;
  235. return(TRUE);
  236. }
  237. }
  238. this->pwszCurrentLine[0] = NULL;
  239. return(FALSE);
  240. }
  241. BOOL fParse_::FindTagInCurrentGroup(WCHAR *pwszTag)
  242. {
  243. if (this->dwLastGroupFilePos == 0)
  244. {
  245. return(FALSE);
  246. }
  247. WCHAR wszCheck[MAX_PATH];
  248. WCHAR wszCheck2[MAX_PATH];
  249. LPWSTR pwszEqual;
  250. DWORD ccRet;
  251. DWORD ccLastMember;
  252. BOOL fFoundLast;
  253. wcscpy(&wszCheck[0], pwszTag);
  254. wcscat(&wszCheck[0], L"=");
  255. wcscpy(&wszCheck2[0], pwszTag);
  256. wcscpy(&wszCheck2[0], L" =");
  257. this->PositionAtLastGroup();
  258. while (this->GetNextLine() > 0)
  259. {
  260. if ((this->pwszCurrentLine[0] == L'#') ||
  261. (this->pwszCurrentLine[0] == L';') ||
  262. (this->pwszCurrentLine[0] == 0x000d))
  263. {
  264. continue;
  265. }
  266. if (this->pwszCurrentLine[0] == L'[')
  267. {
  268. this->pwszCurrentLine[0] = NULL;
  269. return(FALSE);
  270. }
  271. if ((_memicmp(this->pwszCurrentLine, &wszCheck[0], wcslen(&wszCheck[0]) * sizeof(WCHAR)) == 0) ||
  272. (_memicmp(this->pwszCurrentLine, &wszCheck2[0], wcslen(&wszCheck2[0]) * sizeof(WCHAR)) == 0))
  273. {
  274. this->dwLastTagFilePos = this->dwCurLineFilePos;
  275. this->EOLRemove();
  276. return(TRUE);
  277. }
  278. }
  279. this->pwszCurrentLine[0] = NULL;
  280. return(FALSE);
  281. }
  282. BOOL fParse_::FindTagFromCurrentPos(WCHAR *pwszTag)
  283. {
  284. WCHAR wszCheck[MAX_PATH];
  285. WCHAR wszCheck2[MAX_PATH];
  286. LPWSTR pwszEqual;
  287. DWORD ccRet;
  288. DWORD ccLastMember;
  289. BOOL fFoundLast;
  290. wcscpy(&wszCheck[0], pwszTag);
  291. wcscat(&wszCheck[0], L"=");
  292. wcscpy(&wszCheck2[0], pwszTag);
  293. wcscat(&wszCheck2[0], L" =");
  294. this->dwLastTagFilePos++;
  295. while (this->GetNextLine() > 0)
  296. {
  297. if ((this->pwszCurrentLine[0] == L'#') ||
  298. (this->pwszCurrentLine[0] == L';') ||
  299. (this->pwszCurrentLine[0] == 0x000d))
  300. {
  301. continue;
  302. }
  303. if ((_memicmp(this->pwszCurrentLine, &wszCheck[0], wcslen(&wszCheck[0]) * sizeof(WCHAR)) == 0) ||
  304. (_memicmp(this->pwszCurrentLine, &wszCheck2[0], wcslen(&wszCheck2[0]) * sizeof(WCHAR)) == 0))
  305. {
  306. this->dwLastTagFilePos = this->dwCurLineFilePos;
  307. this->EOLRemove();
  308. return(TRUE);
  309. }
  310. }
  311. this->pwszCurrentLine[0] = NULL;
  312. return(FALSE);
  313. }
  314. DWORD fParse_::GetNextLine(void)
  315. {
  316. if (!(this->pwszCurrentLine) ||
  317. (this->hFile == INVALID_HANDLE_VALUE))
  318. {
  319. return(0);
  320. }
  321. DWORD dwHold;
  322. DWORD cbRead;
  323. DWORD cwbRead;
  324. DWORD dw;
  325. int iAmt;
  326. BYTE *pb;
  327. if ((dwHold = SetFilePointer(this->hFile, 0, NULL, FILE_CURRENT)) == 0xFFFFFFFF)
  328. {
  329. return(0);
  330. }
  331. if (!(pb = new BYTE[dwMaxLine + 2]))
  332. {
  333. return(0);
  334. }
  335. cbRead = 0;
  336. if (ReadFile(this->hFile, pb, dwMaxLine, &cbRead, NULL))
  337. {
  338. if (cbRead == 0)
  339. {
  340. this->fEOF = TRUE;
  341. delete pb;
  342. return(0);
  343. }
  344. pb[cbRead] = 0x00;
  345. this->fEOF = FALSE;
  346. if (cbRead > 0)
  347. {
  348. iAmt = 0;
  349. for (dw = 0; dw < (cbRead - 1); dw++)
  350. {
  351. if ((pb[dw] == 0x0d) ||
  352. (pb[dw] == 0x0a))
  353. {
  354. iAmt++;
  355. if (pb[dw + 1] == 0x0a)
  356. {
  357. dw++;
  358. iAmt++;
  359. }
  360. if (SetFilePointer(this->hFile, dwHold + (dw + 1),
  361. NULL, FILE_BEGIN) == 0xFFFFFFFF)
  362. {
  363. this->dwCurLineFilePos = 0;
  364. }
  365. else
  366. {
  367. this->dwCurLineFilePos = SetFilePointer(this->hFile, 0, NULL, FILE_CURRENT) - iAmt;
  368. }
  369. pb[dw + 1] = 0x00;
  370. cwbRead = MultiByteToWideChar(0, 0, (const char *)pb, -1,
  371. pwszCurrentLine, dwMaxLine);
  372. delete pb;
  373. return(cwbRead + 1);
  374. }
  375. }
  376. }
  377. }
  378. else
  379. {
  380. delete pb;
  381. return(0);
  382. }
  383. if (pb[cbRead - 1] == 0x1a) /* EOF */
  384. {
  385. cbRead--;
  386. this->dwCurLineFilePos = 0;
  387. this->fEOF = TRUE;
  388. }
  389. else
  390. {
  391. this->dwCurLineFilePos = dwHold;
  392. }
  393. pb[cbRead] = 0x00;
  394. cwbRead = MultiByteToWideChar(0, 0, (const char *)pb, -1,
  395. pwszCurrentLine, dwMaxLine);
  396. delete pb;
  397. return(cwbRead);
  398. }
  399. void fParse_::EOLRemove(void)
  400. {
  401. DWORD i;
  402. DWORD ccLen;
  403. ccLen = wcslen(this->pwszCurrentLine);
  404. for (i = 0; i < ccLen; i++)
  405. {
  406. if ((this->pwszCurrentLine[i] == (WCHAR)0x0a) ||
  407. (this->pwszCurrentLine[i] == (WCHAR)0x0d))
  408. {
  409. this->pwszCurrentLine[i] = NULL;
  410. return;
  411. }
  412. }
  413. this->pwszCurrentLine[ccLen] = NULL;
  414. }