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.

784 lines
18 KiB

  1. //=======================================================================
  2. //
  3. // Copyright (c) 1998-2000 Microsoft Corporation. All Rights Reserved.
  4. //
  5. // File: RegUtil.CPP
  6. // Author: Charles Ma, 10/20/2000
  7. //
  8. // Revision History:
  9. //
  10. //
  11. //
  12. //
  13. // Description:
  14. //
  15. // Implement IU registry accessing utility library
  16. //
  17. //=======================================================================
  18. #include <windows.h>
  19. #include <tchar.h>
  20. #include <logging.h>
  21. #include <memutil.h>
  22. #include <fileutil.h>
  23. #include <stringutil.h>
  24. #include <shlwapi.h>
  25. #include "wusafefn.h"
  26. #include <regutil.h>
  27. #include<iucommon.h>
  28. #include <MISTSAFE.h>
  29. const int REG_BUF_SIZE = 1024;
  30. const LPCTSTR REG_ROOTKEY_STR[7] = {
  31. _T("HKEY_LOCAL_MACHINE"),
  32. _T("HKEY_CLASSES_ROOT"),
  33. _T("HKEY_CURRENT_USER"),
  34. _T("HKEY_CURRENT_CONFIG"),
  35. _T("HKEY_USERS"),
  36. _T("HKEY_PERFORMANCE_DATA"), // NT only
  37. _T("HKEY_DYN_DATA") // W9x only
  38. };
  39. const HKEY REG_ROOTKEY[7] = {
  40. HKEY_LOCAL_MACHINE,
  41. HKEY_CLASSES_ROOT,
  42. HKEY_CURRENT_USER,
  43. HKEY_CURRENT_CONFIG,
  44. HKEY_USERS,
  45. HKEY_PERFORMANCE_DATA,
  46. HKEY_DYN_DATA
  47. };
  48. typedef BOOL (WINAPI * PFN_StrToInt64Ex)(LPCTSTR pszString,
  49. DWORD dwFlags,
  50. LONGLONG * pllRet);
  51. // ----------------------------------------------------------------------
  52. //
  53. // private function to split a full reg path into
  54. // two parts: root key and subkey
  55. //
  56. // ----------------------------------------------------------------------
  57. LPCTSTR SplitRegPath(LPCTSTR lpsRegPath, HKEY* phRootKey)
  58. {
  59. LPTSTR lpSubKey = NULL;
  60. for (int i = 0; i < sizeof(REG_ROOTKEY)/sizeof(HKEY); i++)
  61. {
  62. if ((lpSubKey = StrStrI(lpsRegPath, REG_ROOTKEY_STR[i])) == lpsRegPath)
  63. {
  64. *phRootKey = REG_ROOTKEY[i];
  65. lpSubKey += lstrlen(REG_ROOTKEY_STR[i]);
  66. lpSubKey = CharNext(lpSubKey); // skip past "\", if any (or remain on NULL)
  67. return lpSubKey;
  68. }
  69. }
  70. //
  71. // if come to here, must be no right root key
  72. //
  73. *phRootKey = 0;
  74. return lpsRegPath;
  75. }
  76. // ----------------------------------------------------------------------
  77. //
  78. // public function to tell if a reg key exists
  79. //
  80. // ----------------------------------------------------------------------
  81. BOOL RegKeyExists(
  82. LPCTSTR lpsKeyPath, // key path
  83. LPCTSTR lpsValName // optional value name
  84. )
  85. {
  86. LOG_Block("RegKeyExists()");
  87. HKEY hRootKey = 0, hKey = 0;
  88. LPCTSTR lpsSubKey = NULL;
  89. BOOL rc = FALSE;
  90. DWORD dwType = 0x0;
  91. if (NULL == lpsKeyPath)
  92. {
  93. LOG_ErrorMsg(E_INVALIDARG);
  94. return FALSE;
  95. }
  96. LOG_Out(_T("Parameters: (%s, %s)"), lpsKeyPath, lpsValName);
  97. lpsSubKey = SplitRegPath(lpsKeyPath, &hRootKey);
  98. if (hRootKey && ERROR_SUCCESS == RegOpenKeyEx(hRootKey, lpsSubKey, 0, KEY_QUERY_VALUE, &hKey))
  99. {
  100. rc = (NULL == lpsValName) ||
  101. (ERROR_SUCCESS == RegQueryValueEx(hKey, lpsValName, NULL, &dwType, NULL, NULL));
  102. }
  103. if (hKey)
  104. {
  105. RegCloseKey(hKey);
  106. }
  107. LOG_Out(_T("Result: %s"), rc ? _T("TRUE") : _T("FALSE"));
  108. return rc;
  109. }
  110. // ----------------------------------------------------------------------
  111. //
  112. // public function to tell is a reg value in reg matches given value
  113. //
  114. // ----------------------------------------------------------------------
  115. BOOL RegKeyValueMatch(
  116. LPCTSTR lpsKeyPath, // key path
  117. LPCTSTR lpsValName, // optional value name
  118. LPCTSTR lpsValue // value value
  119. )
  120. {
  121. LOG_Block("RegKeyValueMatch()");
  122. HKEY hRootKey = 0, hKey = 0;
  123. LPCTSTR lpsSubKey = NULL;
  124. BOOL rc = FALSE;
  125. BYTE btBuffer[REG_BUF_SIZE];
  126. LPBYTE pBuffer = btBuffer;
  127. LPCTSTR lpCurStr;
  128. DWORD dwType = 0x0;
  129. DWORD dwSize = sizeof(btBuffer);
  130. DWORD dwCode = 0x0;
  131. HRESULT hr=S_OK;
  132. USES_MY_MEMORY;
  133. if (NULL == lpsKeyPath || NULL == lpsValue)
  134. {
  135. LOG_ErrorMsg(E_INVALIDARG);
  136. goto CleanUp;
  137. }
  138. LOG_Out(_T("Parameters: (%s, %s, %s)"), lpsKeyPath, lpsValName, lpsValue);
  139. lpsSubKey = SplitRegPath(lpsKeyPath, &hRootKey);
  140. if (0 == hRootKey || (ERROR_SUCCESS != RegOpenKeyEx(hRootKey, lpsSubKey, 0, KEY_QUERY_VALUE, &hKey)))
  141. {
  142. goto CleanUp;
  143. }
  144. //
  145. // try to query the value with existing buffer.
  146. //
  147. dwCode = RegQueryValueEx(hKey, lpsValName, NULL, &dwType, btBuffer, &dwSize);
  148. if (ERROR_MORE_DATA == dwCode)
  149. {
  150. //
  151. // if found the existing buffer not large enough,
  152. // then allocate memory large enough to store the data now
  153. //
  154. if (NULL == (pBuffer = (LPBYTE) MemAlloc(dwSize)))
  155. {
  156. goto CleanUp;
  157. }
  158. dwCode = RegQueryValueEx(hKey, lpsValName, NULL, &dwType, pBuffer, &dwSize);
  159. }
  160. if (ERROR_SUCCESS != dwCode)
  161. {
  162. goto CleanUp;
  163. }
  164. //
  165. // since the value to compare was read from XML doc, obviously only
  166. // the following 4 types possible to compare with
  167. //
  168. switch (dwType)
  169. {
  170. case REG_DWORD:
  171. {
  172. int x, y = *((int *) pBuffer);
  173. DWORD dwFlag = STIF_DEFAULT;
  174. //
  175. // check if the value from manifest is a hex value:
  176. // starts with x, or starts with 0x
  177. //
  178. LPCTSTR lpSecondChar = lpsValue + 1;
  179. if (_T('0') == *lpsValue && (_T('x') == *lpSecondChar || _T('X') == *lpSecondChar))
  180. {
  181. dwFlag = STIF_SUPPORT_HEX;
  182. }
  183. if (StrToIntEx(lpsValue, dwFlag, &x))
  184. {
  185. rc = ( x == y);
  186. }
  187. }
  188. break;
  189. case REG_SZ:
  190. case REG_EXPAND_SZ: // for mult-string, we only compair its first substring
  191. rc = (lstrcmpi((LPCTSTR)lpsValue, (LPCTSTR) pBuffer) == 0);
  192. if (!rc)
  193. {
  194. //
  195. // if the ressult is not equal, it's possibly caused by
  196. // path variables
  197. //
  198. // ASSUMPTION: these reg strings are for file path only, so we only
  199. // handle cases not longer than MAX_PATH.
  200. //
  201. TCHAR szRegStr[MAX_PATH], szValStr[MAX_PATH];
  202. if (dwSize >= MAX_PATH || lstrlen(lpsValue) >= MAX_PATH)
  203. {
  204. break;
  205. }
  206. if (SUCCEEDED(ExpandFilePath(lpsValue, szValStr, sizeof(szValStr)/sizeof(szValStr[0]))))
  207. {
  208. //
  209. // if we can expand the given sub-string,
  210. // then try to expand the reg string if QueryRegValue says
  211. // this string is expandable. Otherwise, use the
  212. // string retrieved only.
  213. //
  214. if (REG_EXPAND_SZ == dwType)
  215. {
  216. ExpandFilePath((LPCTSTR)pBuffer, szRegStr, sizeof(szRegStr)/sizeof(szRegStr[0]));
  217. }
  218. else
  219. {
  220. hr=StringCchCopyEx(szRegStr,ARRAYSIZE(szRegStr),(LPTSTR) pBuffer,NULL,NULL,MISTSAFE_STRING_FLAGS);
  221. if(FAILED(hr)) break;
  222. }
  223. //
  224. // compare in expanded mode
  225. //
  226. rc = (lstrcmpi((LPCTSTR)szRegStr, szValStr) == 0);
  227. }
  228. }
  229. break;
  230. case REG_MULTI_SZ:
  231. {
  232. TCHAR szRegStr[MAX_PATH], szValStr[MAX_PATH];
  233. szValStr[0] = '\0';
  234. lpCurStr = (LPCTSTR)pBuffer;
  235. //
  236. // try to match each SZ in this multi sz.
  237. //
  238. do
  239. {
  240. //
  241. // see if the value contains the substring passed in
  242. //
  243. rc = (lstrcmpi((LPCTSTR)lpsValue, (LPCTSTR)pBuffer) == 0);
  244. //
  245. // if not found, it's possibly caused by
  246. // path variable or environment variable embedded
  247. //
  248. if (!rc && _T('\0') == szValStr[0])
  249. {
  250. if (FAILED(ExpandFilePath(lpsValue, szValStr, sizeof(szValStr)/sizeof(szValStr[0]))))
  251. {
  252. szValStr[0] = '\0';
  253. }
  254. }
  255. //
  256. // compare expanded XML str with current reg str expanded
  257. // since this is REG_MULTI_SZ type, we have no way to tell
  258. // if this SZ inside MULTI_SZ is expandable or not, we
  259. // we will always try to expand it.
  260. //
  261. if (!rc && _T('\0') != szValStr[0])
  262. {
  263. rc = (SUCCEEDED(ExpandFilePath((LPCTSTR)lpCurStr, szRegStr, sizeof(szRegStr)/sizeof(szRegStr[0])))) &&
  264. (lstrcmpi((LPCTSTR)szRegStr, szValStr) == 0);
  265. }
  266. if (!rc)
  267. {
  268. //
  269. // move to next string
  270. //
  271. lpCurStr += (lstrlen(lpCurStr) + 1);
  272. if (_T('\0') == *lpCurStr)
  273. {
  274. break; // no more string to read
  275. }
  276. }
  277. } while (!rc); // repeat to next string
  278. }
  279. break;
  280. case REG_QWORD:
  281. {
  282. HMODULE hLib = LoadLibraryFromSystemDir(_T("Shlwapi.dll"));
  283. if (hLib)
  284. {
  285. #if defined(UNICODE) || defined(_UNICODE)
  286. PFN_StrToInt64Ex pfnStrToInt64Ex = (PFN_StrToInt64Ex) GetProcAddress(hLib, "StrToInt64ExW");
  287. #else
  288. PFN_StrToInt64Ex pfnStrToInt64Ex = (PFN_StrToInt64Ex) GetProcAddress(hLib, "StrToInt64ExA");
  289. #endif
  290. if (pfnStrToInt64Ex)
  291. {
  292. LONGLONG llNum;
  293. rc = (pfnStrToInt64Ex((LPCTSTR)lpsValue, STIF_DEFAULT, &llNum) &&
  294. (llNum == (LONGLONG)pBuffer));
  295. }
  296. FreeLibrary(hLib);
  297. }
  298. }
  299. break;
  300. case REG_BINARY:
  301. rc = (CmpBinaryToString(pBuffer, dwSize, lpsValue) == 0);
  302. break;
  303. default:
  304. rc = FALSE;
  305. }
  306. CleanUp:
  307. if (hKey)
  308. {
  309. RegCloseKey(hKey);
  310. }
  311. LOG_Out(_T("Result: %s"), rc ? _T("TRUE") : _T("FALSE"));
  312. return rc;
  313. }
  314. // ----------------------------------------------------------------------
  315. //
  316. // public function to tell is a reg key has a string type value
  317. // that contains given string
  318. //
  319. // ----------------------------------------------------------------------
  320. BOOL RegKeySubstring(
  321. LPCTSTR lpsKeyPath, // key path
  322. LPCTSTR lpsValName, // optional value name
  323. LPCTSTR lpsSubString // substring to see if contained in value
  324. )
  325. {
  326. LOG_Block("RegKeySubstring()");
  327. HKEY hRootKey = 0, hKey = 0;
  328. LPCTSTR lpsSubKey = NULL;
  329. BOOL rc = FALSE;
  330. BYTE btBuffer[REG_BUF_SIZE];
  331. LPBYTE pBuffer = btBuffer;
  332. LPTSTR lpCurStr = (LPTSTR) pBuffer;
  333. DWORD dwType = 0x0;
  334. DWORD dwSize = sizeof(btBuffer);
  335. DWORD dwCode = 0x0;
  336. TCHAR szRegStr[MAX_PATH];
  337. TCHAR szValStr[MAX_PATH]; // buffer for expanding
  338. USES_MY_MEMORY;
  339. if (NULL == lpsKeyPath || NULL == lpsSubString)
  340. {
  341. LOG_ErrorMsg(E_INVALIDARG);
  342. return FALSE;
  343. }
  344. LOG_Out(_T("Parameters: (%s, %s, %s)"), lpsKeyPath, lpsValName, lpsSubString);
  345. lpsSubKey = SplitRegPath(lpsKeyPath, &hRootKey);
  346. if (0 == hRootKey || (ERROR_SUCCESS != RegOpenKeyEx(hRootKey, lpsSubKey, 0, KEY_QUERY_VALUE, &hKey)))
  347. {
  348. goto CleanUp;
  349. }
  350. //
  351. // try to query the value with existing buffer.
  352. //
  353. dwCode = RegQueryValueEx(hKey, lpsValName, NULL, &dwType, btBuffer, &dwSize);
  354. if (ERROR_MORE_DATA == dwCode)
  355. {
  356. //
  357. // if found the existing buffer not large enough,
  358. // then allocate memory large enough to store the data now
  359. //
  360. if (NULL == (pBuffer = (LPBYTE) MemAlloc(dwSize)))
  361. {
  362. goto CleanUp;
  363. }
  364. lpCurStr = (LPTSTR) pBuffer;
  365. dwCode = RegQueryValueEx(hKey, lpsValName, NULL, &dwType, pBuffer, &dwSize);
  366. }
  367. if (ERROR_SUCCESS != dwCode || REG_SZ != dwType && REG_EXPAND_SZ != dwType && REG_MULTI_SZ != dwType)
  368. {
  369. goto CleanUp;
  370. }
  371. szValStr[0] = _T('\0');
  372. do
  373. {
  374. //
  375. // see if the value contains the substring passed in
  376. //
  377. rc = (StrStrI((LPCTSTR)lpCurStr, lpsSubString) != NULL);
  378. //
  379. // if not found, it's possibly caused by
  380. // path variable or environment variable embedded
  381. //
  382. if (!rc && _T('\0') == szValStr[0])
  383. {
  384. if (FAILED(ExpandFilePath(lpsSubString, szValStr, sizeof(szValStr)/sizeof(szValStr[0]))))
  385. {
  386. break;
  387. }
  388. rc = StrStrI((LPCTSTR)szRegStr, szValStr) != NULL;
  389. }
  390. if (!rc && _T('\0') != szValStr[0] && (REG_EXPAND_SZ == dwType ))
  391. {
  392. //
  393. // try to expand string from reg if this string is expandable
  394. //
  395. rc = (SUCCEEDED(ExpandFilePath((LPCTSTR)lpCurStr, szRegStr, sizeof(szRegStr)/sizeof(szRegStr[0])))) &&
  396. (StrStrI((LPCTSTR)szRegStr, szValStr) != NULL);
  397. } // if not found
  398. if (!rc && REG_MULTI_SZ == dwType)
  399. {
  400. //
  401. // move to next string
  402. //
  403. lpCurStr += (lstrlen(lpCurStr) + 1);
  404. if (_T('\0') == *lpCurStr)
  405. {
  406. break; // no more string to read
  407. }
  408. }
  409. } while (!rc && REG_MULTI_SZ == dwType); // repeat to next string if REG_MULTI_SZ
  410. CleanUp:
  411. if (hKey)
  412. {
  413. RegCloseKey(hKey);
  414. }
  415. LOG_Out(_T("Result: %s"), rc ? _T("TRUE") : _T("FALSE"));
  416. return rc;
  417. }
  418. // ----------------------------------------------------------------------
  419. //
  420. // public function to tell is a reg key has a string type value
  421. // that contains given string
  422. //
  423. // since this is a comparision function, rather than to check existance,
  424. // anything wrong to get the reg version will make the reg having default
  425. // version: 0.0.0.0
  426. //
  427. // ----------------------------------------------------------------------
  428. BOOL RegKeyVersion(
  429. LPCTSTR lpsKeyPath, // key path
  430. LPCTSTR lpsValName, // optional value name
  431. LPCTSTR lpsVersion, // version in string to compare
  432. _VER_STATUS CompareVerb // how to compair
  433. )
  434. {
  435. LOG_Block("RegKeyVersion()");
  436. HKEY hRootKey = 0, hKey = 0;
  437. LPCTSTR lpsSubKey = NULL;
  438. BOOL rc = FALSE;
  439. BYTE btBuffer[REG_BUF_SIZE];
  440. LPBYTE pBuffer = btBuffer;
  441. DWORD dwType = 0x0;
  442. DWORD dwSize = sizeof(btBuffer);
  443. DWORD dwCode = 0x0;
  444. FILE_VERSION verReg, verXml;
  445. int verCompare;
  446. HRESULT hr=S_OK;
  447. USES_IU_CONVERSION;
  448. if (NULL == lpsKeyPath || NULL == lpsVersion)
  449. {
  450. LOG_ErrorMsg(E_INVALIDARG);
  451. return FALSE;
  452. }
  453. LOG_Out(_T("Parameters: (%s, %s, %s, %d)"), lpsKeyPath, lpsValName, lpsVersion, (int)CompareVerb);
  454. //
  455. // initialize the reg version string buffer
  456. //
  457. //The buffer size of btBuffer is sufficient to hold the source string
  458. if(FAILED(hr=StringCchCopyEx((LPTSTR)btBuffer,ARRAYSIZE(btBuffer)/sizeof(TCHAR),_T("0.0.0.0"),NULL,NULL,MISTSAFE_STRING_FLAGS)))
  459. {
  460. LOG_ErrorMsg(hr);
  461. return FALSE;
  462. }
  463. lpsSubKey = SplitRegPath(lpsKeyPath, &hRootKey);
  464. if (0 == hRootKey || (ERROR_SUCCESS != RegOpenKeyEx(hRootKey, lpsSubKey, 0, KEY_QUERY_VALUE, &hKey)))
  465. {
  466. // LOG_ErrorMsg(ERROR_BADKEY); don't log error since we don't know if this key HAS to be there or not
  467. goto GotVersion;
  468. }
  469. //
  470. // try to query the value with existing buffer.
  471. //
  472. dwCode = RegQueryValueEx(hKey, lpsValName, NULL, &dwType, btBuffer, &dwSize);
  473. if (ERROR_MORE_DATA == dwCode)
  474. {
  475. //
  476. // if found the existing buffer not large enough,
  477. // then allocate memory large enough to store the data now
  478. //
  479. pBuffer = (LPBYTE) MemAlloc(dwSize);
  480. if (NULL == pBuffer)
  481. {
  482. goto GotVersion;
  483. }
  484. dwCode = RegQueryValueEx(hKey, lpsValName, NULL, &dwType, pBuffer, &dwSize);
  485. }
  486. if (ERROR_SUCCESS != dwCode || REG_SZ != dwType)
  487. {
  488. hr=StringCchCopyEx((LPTSTR)pBuffer,dwSize/sizeof(TCHAR),_T("0.0.0.0"),NULL,NULL,MISTSAFE_STRING_FLAGS);
  489. if(FAILED(hr))
  490. {
  491. LOG_ErrorMsg(hr);
  492. goto CleanUp;
  493. }
  494. }
  495. GotVersion:
  496. //
  497. // convert the retrieved reg value to version
  498. //
  499. if (!ConvertStringVerToFileVer(T2CA((LPCTSTR) pBuffer), &verReg) ||
  500. !ConvertStringVerToFileVer(T2CA((LPCTSTR) lpsVersion), &verXml))
  501. {
  502. goto CleanUp;
  503. }
  504. //
  505. // maybe we successfully read data from reg, but that data can't be converted
  506. // into version at all. In this case, we still want to use the default version
  507. // for comparision
  508. //
  509. if (0 > verReg.Major)
  510. {
  511. verReg.Major = verReg.Minor = verReg.Build = verReg.Ext = 0;
  512. }
  513. //
  514. // compare version number. if a < b, -1; a > b, +1
  515. //
  516. verCompare = CompareFileVersion(verReg, verXml);
  517. switch (CompareVerb)
  518. {
  519. case DETX_LOWER:
  520. //
  521. // if reg key version less than XML version
  522. //
  523. rc = (verCompare < 0);
  524. break;
  525. case DETX_LOWER_OR_EQUAL:
  526. //
  527. // if reg key version less than or equal to XML version
  528. //
  529. rc = (verCompare <= 0);
  530. break;
  531. case DETX_SAME:
  532. //
  533. // if reg key version same as XML version
  534. //
  535. rc = (0 == verCompare);
  536. break;
  537. case DETX_HIGHER_OR_EQUAL:
  538. //
  539. // if reg key version higher than or equal to XML version
  540. //
  541. rc = (verCompare >= 0);
  542. break;
  543. case DETX_HIGHER:
  544. //
  545. // if reg key versiong higher than XML version
  546. //
  547. rc = (verCompare > 0);
  548. break;
  549. default:
  550. //
  551. // should never happen
  552. //
  553. rc = FALSE;
  554. break;
  555. }
  556. CleanUp:
  557. if (hKey)
  558. {
  559. RegCloseKey(hKey);
  560. }
  561. LOG_Out(_T("Result: %s"), rc ? _T("TRUE") : _T("FALSE"));
  562. return rc;
  563. }
  564. // ----------------------------------------------------------------------------------
  565. //
  566. // public function to find out the file path based on reg
  567. // assumption:
  568. // lpsFilePath points to a buffer at least MAX_PATH long.
  569. //
  570. // ----------------------------------------------------------------------------------
  571. BOOL GetFilePathFromReg(
  572. LPCTSTR lpsKeyPath, // key path
  573. LPCTSTR lpsValName, // optional value name
  574. LPCTSTR lpsRelativePath,// optional additonal relative path to add to path in reg
  575. LPCTSTR lpsFileName, // optional file name to append to path
  576. LPTSTR lpsFilePath
  577. )
  578. {
  579. LOG_Block("GetFilePathFromReg()");
  580. HKEY hRootKey = 0, hKey = 0;
  581. LPCTSTR lpsSubKey = NULL;
  582. BOOL rc = FALSE;
  583. BYTE btBuffer[REG_BUF_SIZE];
  584. LPBYTE pBuffer = btBuffer;
  585. DWORD dwType = 0x0;
  586. DWORD dwSize = sizeof(btBuffer);
  587. DWORD dwCode = 0x0;
  588. FILE_VERSION verReg, verXml;
  589. int verCompare;
  590. HRESULT hr=S_OK;
  591. USES_IU_CONVERSION;
  592. if (NULL == lpsKeyPath || NULL == lpsFilePath)
  593. {
  594. LOG_ErrorMsg(E_INVALIDARG);
  595. return FALSE;
  596. }
  597. //
  598. // initialize file path
  599. //
  600. *lpsFilePath = '\0';
  601. LOG_Out(_T("Parameters: (%s, %s, %s, %s)"), lpsKeyPath, lpsValName, lpsRelativePath, lpsFileName);
  602. lpsSubKey = SplitRegPath(lpsKeyPath, &hRootKey);
  603. if (0 == hRootKey || (ERROR_SUCCESS != RegOpenKeyEx(hRootKey, lpsSubKey, 0, KEY_QUERY_VALUE, &hKey)))
  604. {
  605. // LOG_ErrorMsg(ERROR_BADKEY); --- key probably not required to exist!
  606. goto CleanUp;
  607. }
  608. //
  609. // try to query the value with existing buffer.
  610. //
  611. dwCode = RegQueryValueEx(hKey, lpsValName, NULL, &dwType, btBuffer, &dwSize);
  612. if (ERROR_MORE_DATA == dwCode)
  613. {
  614. //
  615. // if found the existing buffer not large enough,
  616. // then allocate memory large enough to store the data now
  617. //
  618. if (NULL == (pBuffer = (LPBYTE) MemAlloc(dwSize + sizeof(TCHAR))))
  619. {
  620. goto CleanUp;
  621. }
  622. dwCode = RegQueryValueEx(hKey, lpsValName, NULL, &dwType, pBuffer, &dwSize);
  623. }
  624. if (ERROR_SUCCESS != dwCode || REG_SZ != dwType)
  625. {
  626. LOG_ErrorMsg(ERROR_BADKEY);
  627. goto CleanUp;
  628. }
  629. //
  630. // validate the to-be-combined path can fit into the buffer
  631. //
  632. if (lstrlen(lpsRelativePath) + lstrlen(lpsFileName) + dwSize/sizeof(TCHAR) >= MAX_PATH)
  633. {
  634. LOG_ErrorMsg(ERROR_BUFFER_OVERFLOW);
  635. goto CleanUp;
  636. }
  637. //
  638. // combile the path with optional relative path and file name
  639. //
  640. //The size of lpsFilePath is not available for using Safe String Functions
  641. hr=StringCchCopyEx(lpsFilePath,MAX_PATH,(LPCTSTR) pBuffer,NULL,NULL,MISTSAFE_STRING_FLAGS);
  642. if ( SUCCEEDED(hr) && (NULL == lpsRelativePath || SUCCEEDED(PathCchAppend(lpsFilePath,MAX_PATH,lpsRelativePath)) ) && (NULL == lpsFileName || SUCCEEDED(PathCchAppend(lpsFilePath,MAX_PATH,lpsFileName)) ))
  643. {
  644. rc = TRUE;
  645. }
  646. CleanUp:
  647. if (hKey)
  648. {
  649. RegCloseKey(hKey);
  650. }
  651. if (!rc)
  652. {
  653. //
  654. // make sure the buffer is set to empty string if error
  655. //
  656. *lpsFilePath = _T('\0');
  657. }
  658. else
  659. {
  660. LOG_Out(_T("Found path: %s"), lpsFilePath);
  661. }
  662. return rc;
  663. }