Leaked source code of windows server 2003
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.

523 lines
14 KiB

  1. /////////////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1998 Active Voice Corporation. All Rights Reserved.
  4. //
  5. // Active Agent(r) and Unified Communications(tm) are trademarks of Active Voice Corporation.
  6. //
  7. // Other brand and product names used herein are trademarks of their respective owners.
  8. //
  9. // The entire program and user interface including the structure, sequence, selection,
  10. // and arrangement of the dialog, the exclusively "yes" and "no" choices represented
  11. // by "1" and "2," and each dialog message are protected by copyrights registered in
  12. // the United States and by international treaties.
  13. //
  14. // Protected by one or more of the following United States patents: 5,070,526, 5,488,650,
  15. // 5,434,906, 5,581,604, 5,533,102, 5,568,540, 5,625,676, 5,651,054.
  16. //
  17. // Active Voice Corporation
  18. // Seattle, Washington
  19. // USA
  20. //
  21. /////////////////////////////////////////////////////////////////////////////////////////
  22. ////
  23. // ini.c - Windows ini profile functions
  24. ////
  25. #include "winlocal.h"
  26. #include <stdlib.h>
  27. #include "ini.h"
  28. #include "file.h"
  29. #include "mem.h"
  30. #include "str.h"
  31. #include "trace.h"
  32. ////
  33. // private definitions
  34. ////
  35. #define INI_MAXLINELEN 128
  36. // ini control struct
  37. //
  38. typedef struct INI
  39. {
  40. DWORD dwVersion;
  41. HINSTANCE hInst;
  42. HTASK hTask;
  43. HFIL hFile;
  44. LPTSTR lpszFilename;
  45. DWORD dwFlags;
  46. BOOL fReuseLine;
  47. TCHAR szSection[INI_MAXLINELEN];
  48. TCHAR szLine[INI_MAXLINELEN];
  49. } INI, FAR *LPINI;
  50. // helper functions
  51. //
  52. static LPINI IniGetPtr(HINI hIni);
  53. static HINI IniGetHandle(LPINI lpIni);
  54. ////
  55. // public functions
  56. ////
  57. // IniOpen - open ini file
  58. // <dwVersion> (i) must be INI_VERSION
  59. // <hInst> (i) instance handle of calling module
  60. // <lpszFilename> (i) name of ini file
  61. // <dwFlags> (i) reserved, must be 0
  62. // return handle (NULL if error)
  63. //
  64. HINI DLLEXPORT WINAPI IniOpen(DWORD dwVersion, HINSTANCE hInst, LPCTSTR lpszFilename, DWORD dwFlags)
  65. {
  66. BOOL fSuccess = TRUE;
  67. LPINI lpIni = NULL;
  68. if (dwVersion != INI_VERSION)
  69. fSuccess = TraceFALSE(NULL);
  70. else if (hInst == NULL)
  71. fSuccess = TraceFALSE(NULL);
  72. else if (lpszFilename == NULL)
  73. fSuccess = TraceFALSE(NULL);
  74. else if ((lpIni = (LPINI) MemAlloc(NULL, sizeof(INI), 0)) == NULL)
  75. fSuccess = TraceFALSE(NULL);
  76. else
  77. {
  78. lpIni->dwVersion = dwVersion;
  79. lpIni->hInst = hInst;
  80. lpIni->hTask = GetCurrentTask();
  81. lpIni->hFile = NULL;
  82. lpIni->lpszFilename = StrDup(lpszFilename);
  83. lpIni->dwFlags = dwFlags;
  84. lpIni->fReuseLine = FALSE;
  85. *lpIni->szLine = '\0';
  86. // open the ini file for reading
  87. //
  88. if ((lpIni->hFile = FileOpen(lpIni->lpszFilename, OF_READ, TRUE)) == NULL)
  89. fSuccess = TraceFALSE(NULL);
  90. }
  91. if (!fSuccess)
  92. {
  93. IniClose(IniGetHandle(lpIni));
  94. lpIni = NULL;
  95. }
  96. return fSuccess ? IniGetHandle(lpIni) : NULL;
  97. }
  98. // IniClose - close ini file
  99. // <hIni> (i) handle returned from IniOpen
  100. // return 0 if success
  101. //
  102. int DLLEXPORT WINAPI IniClose(HINI hIni)
  103. {
  104. BOOL fSuccess = TRUE;
  105. LPINI lpIni;
  106. if ((lpIni = IniGetPtr(hIni)) == NULL)
  107. fSuccess = TraceFALSE(NULL);
  108. else
  109. {
  110. if (lpIni->hFile != NULL && FileClose(lpIni->hFile) != 0)
  111. fSuccess = TraceFALSE(NULL);
  112. if (lpIni->lpszFilename != NULL && StrDupFree(lpIni->lpszFilename) != 0)
  113. fSuccess = TraceFALSE(NULL);
  114. if ((lpIni = MemFree(NULL, lpIni)) != NULL)
  115. fSuccess = TraceFALSE(NULL);
  116. }
  117. return fSuccess ? 0 : -1;
  118. }
  119. // IniGetInt - read integer value from specified section and entry
  120. // <hIni> (i) handle returned from IniOpen
  121. // <lpszSection> (i) section heading in the ini file
  122. // <lpszEntry> (i) entry whose value is to be retrieved
  123. // <iDefault> (i) return value if entry not found
  124. // return entry value (iDefault if error or not found)
  125. //
  126. UINT DLLEXPORT WINAPI IniGetInt(HINI hIni, LPCTSTR lpszSection, LPCTSTR lpszEntry, int iDefault)
  127. {
  128. UINT uRet;
  129. TCHAR szReturnBuffer[128];
  130. if (IniGetString(hIni, lpszSection, lpszEntry, TEXT(""),
  131. szReturnBuffer, SIZEOFARRAY(szReturnBuffer)) > 0)
  132. uRet = (UINT) StrAtoL(szReturnBuffer);
  133. else
  134. uRet = iDefault;
  135. return uRet;
  136. }
  137. // IniGetString - read string value from specified section and entry
  138. // <hIni> (i) handle returned from IniOpen
  139. // <lpszSection> (i) section heading in the ini file
  140. // <lpszEntry> (i) entry whose value is to be retrieved
  141. // <lpszDefault> (i) return value if entry not found
  142. // <lpszReturnBuffer> (o) destination buffer
  143. // <sizReturnBuffer> (i) size of destination buffer
  144. // return count of bytes copied (0 if error or not found)
  145. //
  146. int DLLEXPORT WINAPI IniGetString(HINI hIni, LPCTSTR lpszSection, LPCTSTR lpszEntry,
  147. LPCTSTR lpszDefault, LPTSTR lpszReturnBuffer, int cbReturnBuffer)
  148. {
  149. BOOL fSuccess = TRUE;
  150. LPINI lpIni;
  151. int nBytesCopied = 0;
  152. if ((lpIni = IniGetPtr(hIni)) == NULL)
  153. fSuccess = TraceFALSE(NULL);
  154. else if (lpszSection == NULL || lpszEntry == NULL ||
  155. lpszDefault == NULL || lpszReturnBuffer == NULL)
  156. fSuccess = TraceFALSE(NULL);
  157. else
  158. StrNCpy(lpszReturnBuffer, lpszDefault, cbReturnBuffer);
  159. while (fSuccess)
  160. {
  161. TCHAR szLineSave[INI_MAXLINELEN];
  162. LPTSTR lpsz;
  163. long nBytesRead;
  164. // read the next line if necessary
  165. //
  166. if (!lpIni->fReuseLine && (nBytesRead = FileReadLine(lpIni->hFile,
  167. lpIni->szLine, SIZEOFARRAY(lpIni->szLine))) <= 0)
  168. {
  169. if (nBytesRead == 0)
  170. fSuccess = FALSE; // no trace needed for eof
  171. else
  172. fSuccess = TraceFALSE(NULL);
  173. continue;
  174. }
  175. StrCpy(szLineSave, lpIni->szLine);
  176. lpIni->fReuseLine = FALSE;
  177. // remove trailing newline char
  178. //
  179. if (StrGetLastChr(lpIni->szLine) == '\n')
  180. StrSetLastChr(lpIni->szLine, '\0');
  181. // check for empty line
  182. //
  183. if (*lpIni->szLine == '\0' || *lpIni->szLine == ';')
  184. continue;
  185. // check for entering new section
  186. //
  187. if (*lpIni->szLine == '[')
  188. {
  189. // save section name
  190. //
  191. StrNCpy(lpIni->szSection, lpIni->szLine + 1, SIZEOFARRAY(lpIni->szSection));
  192. if (StrGetLastChr(lpIni->szSection) == ']')
  193. StrSetLastChr(lpIni->szSection, '\0');
  194. continue;
  195. }
  196. if (StrICmp(lpszSection, lpIni->szSection) != 0)
  197. {
  198. // section mismatch
  199. //
  200. fSuccess = TraceFALSE(NULL);
  201. // we want the next call to this function to reuse this line
  202. //
  203. StrCpy(lpIni->szLine, szLineSave);
  204. lpIni->fReuseLine = TRUE;
  205. continue;
  206. }
  207. if ((lpsz = StrChr(lpIni->szLine, '=')) == NULL)
  208. {
  209. // entry has no equal sign
  210. //
  211. fSuccess = TraceFALSE(NULL);
  212. continue;
  213. }
  214. *lpsz = '\0';
  215. if (StrICmp(lpszEntry, lpIni->szLine) != 0)
  216. {
  217. // entry mismatch
  218. //
  219. fSuccess = TraceFALSE(NULL);
  220. // we want the next call to this function to reuse this line
  221. //
  222. StrCpy(lpIni->szLine, szLineSave);
  223. lpIni->fReuseLine = TRUE;
  224. continue;
  225. }
  226. else
  227. {
  228. // success
  229. //
  230. StrNCpy(lpszReturnBuffer, lpsz + 1, cbReturnBuffer);
  231. break;
  232. }
  233. }
  234. if (fSuccess)
  235. nBytesCopied = StrLen(lpszReturnBuffer);
  236. return fSuccess ? nBytesCopied : 0;
  237. }
  238. // GetPrivateProfileLong - retrieve long from specified section of specified file
  239. // <lpszSection> (i) section name within ini file
  240. // <lpszEntry> (i) entry name within section
  241. // <lDefault> (i) return value if entry not found
  242. // <lpszFilename> (i) name of ini file
  243. // return TRUE if success
  244. //
  245. long DLLEXPORT WINAPI GetPrivateProfileLong(LPCTSTR lpszSection,
  246. LPCTSTR lpszEntry, long lDefault, LPCTSTR lpszFilename)
  247. {
  248. long lValue = lDefault;
  249. TCHAR szValue[33];
  250. GetPrivateProfileString(lpszSection, lpszEntry,
  251. TEXT(""), szValue, SIZEOFARRAY(szValue), lpszFilename);
  252. if (*szValue != '\0')
  253. lValue = StrAtoL(szValue);
  254. return lValue;
  255. }
  256. // GetProfileLong - retrieve long from specified section of win.ini
  257. // <lpszSection> (i) section name within ini file
  258. // <lpszEntry> (i) entry name within section
  259. // <lDefault> (i) return value if entry not found
  260. // return TRUE if success
  261. //
  262. long DLLEXPORT WINAPI GetProfileLong(LPCTSTR lpszSection,
  263. LPCTSTR lpszEntry, long lDefault)
  264. {
  265. long lValue = lDefault;
  266. TCHAR szValue[33];
  267. GetProfileString(lpszSection, lpszEntry,
  268. TEXT(""), szValue, SIZEOFARRAY(szValue));
  269. if (*szValue != '\0')
  270. lValue = StrAtoL(szValue);
  271. return lValue;
  272. }
  273. // WritePrivateProfileInt - write int to specified section of specified file
  274. // <lpszSection> (i) section name within ini file
  275. // <lpszEntry> (i) entry name within section
  276. // <iValue> (i) integer value to assign to entry
  277. // <lpszFilename> (i) name of ini file
  278. // return TRUE if success
  279. //
  280. BOOL DLLEXPORT WINAPI WritePrivateProfileInt(LPCTSTR lpszSection, LPCTSTR lpszEntry, int iValue, LPCTSTR lpszFilename)
  281. {
  282. TCHAR achValue[17];
  283. StrItoA(iValue, achValue, 10);
  284. return WritePrivateProfileString(lpszSection, lpszEntry, achValue, lpszFilename);
  285. }
  286. // WriteProfileInt - write int to specified section of win.ini
  287. // <lpszSection> (i) section name within win.ini file
  288. // <lpszEntry> (i) entry name within section
  289. // <iValue> (i) integer value to assign to entry
  290. // return TRUE if success
  291. //
  292. BOOL DLLEXPORT WINAPI WriteProfileInt(LPCTSTR lpszSection, LPCTSTR lpszEntry, int iValue)
  293. {
  294. TCHAR achValue[17];
  295. StrItoA(iValue, achValue, 10);
  296. return WriteProfileString(lpszSection, lpszEntry, achValue);
  297. }
  298. // WritePrivateProfileLong - write long to specified section of specified file
  299. // <lpszSection> (i) section name within ini file
  300. // <lpszEntry> (i) entry name within section
  301. // <iValue> (i) integer value to assign to entry
  302. // <lpszFilename> (i) name of ini file
  303. // return TRUE if success
  304. //
  305. BOOL DLLEXPORT WINAPI WritePrivateProfileLong(LPCTSTR lpszSection, LPCTSTR lpszEntry, long iValue, LPCTSTR lpszFilename)
  306. {
  307. TCHAR achValue[33];
  308. StrLtoA(iValue, achValue, 10);
  309. return WritePrivateProfileString(lpszSection, lpszEntry, achValue, lpszFilename);
  310. }
  311. // WriteProfileLong - write long to specified section of win.ini
  312. // <lpszSection> (i) section name within win.ini file
  313. // <lpszEntry> (i) entry name within section
  314. // <iValue> (i) integer value to assign to entry
  315. // return TRUE if success
  316. //
  317. BOOL DLLEXPORT WINAPI WriteProfileLong(LPCTSTR lpszSection, LPCTSTR lpszEntry, long iValue)
  318. {
  319. TCHAR achValue[33];
  320. StrLtoA(iValue, achValue, 10);
  321. return WriteProfileString(lpszSection, lpszEntry, achValue);
  322. }
  323. // UpdatePrivateProfileSection - update destination section based on source
  324. // <lpszSection> (i) section name within ini file
  325. // <lpszFileNameSrc> (i) name of source ini file
  326. // <lpszFileNameDst> (i) name of destination ini file
  327. // return 0 if success
  328. //
  329. // NOTE: if the source file has UpdateLocal=1 entry in the specified
  330. // section, each entry in the source file is compared to the corresponding
  331. // entry in the destination file. If no corresponding entry is found,
  332. // it is copied. If a corresponding entry is found, it is overwritten
  333. // ONLY IF the source file entry name is all uppercase.
  334. //
  335. // Src Dst before Dst after
  336. //
  337. // [Section] [Section] [Section]
  338. // UpdateLocal=1
  339. // EntryA=red none EntryA=red
  340. // EntryB=blue EntryB=white EntryB=white
  341. // ENTRYC=blue EntryC=white EntryC=blue
  342. //
  343. int DLLEXPORT WINAPI UpdatePrivateProfileSection(LPCTSTR lpszSection, LPCTSTR lpszFileNameSrc, LPCTSTR lpszFileNameDst)
  344. {
  345. BOOL fSuccess = TRUE;
  346. BOOL fUpdateLocal = GetPrivateProfileInt(lpszSection,
  347. TEXT("UpdateLocal"), FALSE, lpszFileNameSrc);
  348. LPTSTR lpszBuf = NULL;
  349. if (fUpdateLocal)
  350. {
  351. if ((lpszBuf = (LPTSTR) MemAlloc(NULL, 4096 * sizeof(TCHAR), 0)) == NULL)
  352. fSuccess = FALSE;
  353. // copy entire source section to buffer
  354. //
  355. else if (GetPrivateProfileString(lpszSection, NULL, TEXT(""),
  356. lpszBuf, 4096, lpszFileNameSrc) <= 0)
  357. fSuccess = FALSE;
  358. else
  359. {
  360. LPTSTR lpszEntry;
  361. for (lpszEntry = lpszBuf;
  362. lpszEntry != NULL && *lpszEntry != '\0';
  363. lpszEntry = StrNextChr(lpszEntry))
  364. {
  365. TCHAR szValueSrc[128];
  366. TCHAR szValueDst[2];
  367. BOOL fForceUpdate = TRUE;
  368. LPTSTR lpsz;
  369. if (StrICmp(lpszEntry, TEXT("UpdateLocal")) != 0)
  370. {
  371. for (lpsz = lpszEntry; *lpsz != '\0'; lpsz = StrNextChr(lpsz))
  372. {
  373. if (*lpsz != ChrToUpper(*lpsz))
  374. {
  375. fForceUpdate = FALSE;
  376. break;
  377. }
  378. }
  379. GetPrivateProfileString(lpszSection, lpszEntry, TEXT(""),
  380. szValueDst, SIZEOFARRAY(szValueDst), lpszFileNameDst);
  381. if (*szValueDst == '\0' || fForceUpdate)
  382. {
  383. GetPrivateProfileString(lpszSection, lpszEntry, TEXT(""),
  384. szValueSrc, SIZEOFARRAY(szValueSrc), lpszFileNameSrc);
  385. WritePrivateProfileString(lpszSection, lpszEntry,
  386. StrCmp(szValueSrc, TEXT("NULL")) == 0 ? (LPTSTR) NULL :
  387. szValueSrc, lpszFileNameDst);
  388. }
  389. }
  390. lpszEntry = StrChr(lpszEntry, '\0');
  391. }
  392. }
  393. if (lpszBuf != NULL &&
  394. (lpszBuf = MemFree(NULL, lpszBuf)) != NULL)
  395. fSuccess = TraceFALSE(NULL);
  396. }
  397. return fSuccess ? 0 : -1;
  398. }
  399. ////
  400. // helper functions
  401. ////
  402. // IniGetPtr - verify that ini handle is valid,
  403. // <hIni> (i) handle returned from IniOpen
  404. // return corresponding ini pointer (NULL if error)
  405. //
  406. static LPINI IniGetPtr(HINI hIni)
  407. {
  408. BOOL fSuccess = TRUE;
  409. LPINI lpIni;
  410. if ((lpIni = (LPINI) hIni) == NULL)
  411. fSuccess = TraceFALSE(NULL);
  412. else if (IsBadWritePtr(lpIni, sizeof(INI)))
  413. fSuccess = TraceFALSE(NULL);
  414. #ifdef CHECKTASK
  415. // make sure current task owns the ini handle
  416. //
  417. else if (lpIni->hTask != GetCurrentTask())
  418. fSuccess = TraceFALSE(NULL);
  419. #endif
  420. return fSuccess ? lpIni : NULL;
  421. }
  422. // IniGetHandle - verify that ini pointer is valid,
  423. // <lpIni> (i) pointer to INI struct
  424. // return corresponding ini handle (NULL if error)
  425. //
  426. static HINI IniGetHandle(LPINI lpIni)
  427. {
  428. BOOL fSuccess = TRUE;
  429. HINI hIni;
  430. if ((hIni = (HINI) lpIni) == NULL)
  431. fSuccess = TraceFALSE(NULL);
  432. return fSuccess ? hIni : NULL;
  433. }