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.

813 lines
24 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // AppWiz.cpl - "Add or Remove Programs" CPL.
  4. // Copyright (C) Microsoft
  5. //
  6. // File: Scripts.CPP
  7. // authomates running of TS application compatibility scripts
  8. //
  9. // History: Nov-14-2000 skuzin Created
  10. //
  11. //--------------------------------------------------------------------------
  12. #include <nt.h>
  13. #include <ntrtl.h>
  14. #include <nturtl.h>
  15. #include <windows.h>
  16. #include <regapi.h>
  17. #include <tsappcmp.h>
  18. #include "Scripts.h"
  19. #include <list>
  20. using namespace std;
  21. //
  22. //Struct to establish correspondence between app. name (key name)
  23. //and install and uninstall script names
  24. //
  25. class CAppScript
  26. {
  27. private:
  28. LPWSTR m_szKeyName; //key name that represents installed application
  29. LPWSTR m_szInstallScript; //install script name
  30. LPWSTR m_szUninstallScript; //uninstall script name
  31. DWORD m_bNeedReboot; //If set - then scripts must be run after reboot.
  32. BOOL m_bAlreadyInstalled; //
  33. public:
  34. //
  35. CAppScript() :
  36. m_szKeyName(NULL), m_szInstallScript(NULL), m_szUninstallScript(NULL),
  37. m_bNeedReboot(FALSE), m_bAlreadyInstalled(FALSE)
  38. {
  39. }
  40. ~CAppScript()
  41. {
  42. if(m_szKeyName)
  43. {
  44. LocalFree(m_szKeyName);
  45. }
  46. if(m_szInstallScript)
  47. {
  48. LocalFree(m_szInstallScript);
  49. }
  50. if(m_szUninstallScript)
  51. {
  52. LocalFree(m_szUninstallScript);
  53. }
  54. }
  55. BOOL Load(HKEY hKeyParent,LPCWSTR szKeyName);
  56. BOOL RunScriptIfApplicable();
  57. private:
  58. BOOL RunScript(LPCWSTR szDir, LPCWSTR szScript);
  59. BOOL PrepareScriptForReboot(LPCWSTR szInstallDir, LPCWSTR szScript);
  60. //BUGBUG this function is public for test only
  61. };
  62. //This class describes a list of pointers
  63. //to objects of class CAppScript
  64. class CAppScriptList : public list<CAppScript*>
  65. {
  66. public:
  67. //Deletes all CAppScript objects
  68. //before destroing the list itself.
  69. ~CAppScriptList()
  70. {
  71. CAppScriptList::iterator it;
  72. for(it=begin();it!=end(); it++)
  73. {
  74. delete (*it);
  75. }
  76. }
  77. };
  78. class CAppScriptManager
  79. {
  80. private:
  81. CAppScriptList m_AppScriptList;
  82. public:
  83. CAppScriptManager(){};
  84. ~CAppScriptManager(){};
  85. BOOL Init();
  86. BOOL RunScripts();
  87. private:
  88. BOOL LoadSupportedAppList();
  89. BOOL IsAppCompatOn();
  90. };
  91. //Functions - helpers.
  92. DWORD RegLoadString(HKEY hKey, LPCWSTR szValueName, LPWSTR *pszValue);
  93. DWORD RegLoadDWORD(HKEY hKey, LPCWSTR szValueName, DWORD *pdwValue);
  94. BOOL RegIsKeyExist(HKEY hKeyParent, LPCWSTR szKeyName);
  95. DWORD RegGetKeyInfo(HKEY hKey, LPDWORD pcSubKeys, LPDWORD pcMaxNameLen);
  96. DWORD RegKeyEnum(HKEY hKey, DWORD dwIndex, LPWSTR szSubKeyName, DWORD cSubKeyName);
  97. ///////////////////////////////////////////////////////////////////////////////
  98. //Exports
  99. ///////////////////////////////////////////////////////////////////////////////
  100. extern "C"
  101. LPVOID
  102. ScriptManagerInitScripts()
  103. {
  104. CAppScriptManager *pScriptManager = new CAppScriptManager();
  105. if(pScriptManager)
  106. {
  107. if(!pScriptManager->Init())
  108. {
  109. delete pScriptManager;
  110. pScriptManager = NULL;
  111. }
  112. }
  113. return pScriptManager;
  114. }
  115. extern "C"
  116. void
  117. ScriptManagerRunScripts(
  118. LPVOID *ppScriptManager)
  119. {
  120. if(*ppScriptManager)
  121. {
  122. CAppScriptManager *pScriptManager = reinterpret_cast<CAppScriptManager *>(*ppScriptManager);
  123. pScriptManager->RunScripts();
  124. delete pScriptManager;
  125. *ppScriptManager = NULL;
  126. }
  127. }
  128. ///////////////////////////////////////////////////////////////////////////////
  129. //class CAppScript
  130. ///////////////////////////////////////////////////////////////////////////////
  131. /******************************************************************************
  132. CAppScript::Load()
  133. Purpose:
  134. Loads script information from the registry
  135. Sets m_bIsInitiallyInstalled to TRUE if app already installed
  136. ******************************************************************************/
  137. BOOL
  138. CAppScript::Load(
  139. HKEY hKeyParent,
  140. LPCWSTR szKeyName)
  141. {
  142. DWORD err;
  143. HKEY hKey;
  144. err = RegOpenKeyExW(hKeyParent, szKeyName, 0, KEY_QUERY_VALUE, &hKey );
  145. if(err == ERROR_SUCCESS)
  146. {
  147. RegLoadString(hKey, L"KeyName", &m_szKeyName);
  148. RegLoadString(hKey, L"InstallScript", &m_szInstallScript);
  149. RegLoadString(hKey, L"UninstallScript", &m_szUninstallScript);
  150. RegLoadDWORD(hKey, L"NeedReboot", &m_bNeedReboot);
  151. RegCloseKey(hKey);
  152. if(m_szKeyName)
  153. {
  154. m_bAlreadyInstalled = RegIsKeyExist(HKEY_LOCAL_MACHINE, m_szKeyName);
  155. return TRUE;
  156. }
  157. }
  158. return FALSE;
  159. }
  160. /******************************************************************************
  161. CAppScript::RunScriptIfApplicable()
  162. Purpose:
  163. Checks if the application was installed or uninstalled and runs the script.
  164. If m_bNeedReboot flag is set - schedules the script to run after reboot.
  165. ******************************************************************************/
  166. BOOL
  167. CAppScript::RunScriptIfApplicable()
  168. {
  169. KdPrint(("CAppScript::RunScriptIfApplicable() - ENTER\n"));
  170. const WCHAR szInstallSubDir[] = L"\\Application Compatibility Scripts\\Install";
  171. const WCHAR szUninstallSubDir[] = L"\\Application Compatibility Scripts\\Uninstall";
  172. static WCHAR szInstallDir[MAX_PATH+sizeof(szInstallSubDir)/sizeof(WCHAR)+1] = L"";
  173. static WCHAR szUninstallDir[MAX_PATH+sizeof(szUninstallSubDir)/sizeof(WCHAR)+1] = L"";
  174. if(!szInstallDir[0])
  175. {
  176. //Get the scripts location
  177. //We need to do it only once
  178. //get Windows directory name
  179. if(!GetSystemWindowsDirectoryW(szInstallDir,MAX_PATH))
  180. {
  181. KdPrint(("CAppScript::RunScriptIfApplicable() - GetWindowsDirectoryW() FAILED\n"));
  182. return FALSE;
  183. }
  184. wcscpy(szUninstallDir,szInstallDir);
  185. wcscat(szInstallDir,szInstallSubDir);
  186. wcscat(szUninstallDir,szUninstallSubDir);
  187. }
  188. if(!m_bAlreadyInstalled && RegIsKeyExist(HKEY_LOCAL_MACHINE, m_szKeyName) && m_szInstallScript)
  189. {
  190. //Application was installed
  191. if(m_bNeedReboot)
  192. {
  193. //Setup will continue after reboot
  194. //Create RunOnce entry to run script after system is rebooted
  195. KdPrint(("CAppScript::RunScriptIfApplicable() - PrepareScriptForReboot %ws\n",m_szInstallScript));
  196. if(!PrepareScriptForReboot(szInstallDir, m_szInstallScript))
  197. {
  198. KdPrint(("CAppScript::PrepareScriptForReboot() - FAILED\n",m_szInstallScript));
  199. return FALSE;
  200. }
  201. }
  202. else
  203. {
  204. KdPrint(("CAppScript::RunScriptIfApplicable() - executing script %ws\n",m_szInstallScript));
  205. if(!RunScript(szInstallDir,m_szInstallScript))
  206. {
  207. KdPrint(("CAppScript::RunScriptIfApplicable() - executing script FAILED\n",m_szInstallScript));
  208. return FALSE;
  209. }
  210. }
  211. m_bAlreadyInstalled = TRUE;
  212. }
  213. else
  214. {
  215. if(m_bAlreadyInstalled && !RegIsKeyExist(HKEY_LOCAL_MACHINE, m_szKeyName) && m_szUninstallScript)
  216. {
  217. //Application was uninstalled
  218. KdPrint(("CAppScript::RunScriptIfApplicable() - executing script %ws\n",m_szUninstallScript));
  219. if(!RunScript(szUninstallDir,m_szUninstallScript))
  220. {
  221. KdPrint(("CAppScript::RunScriptIfApplicable() - executing script FAILED\n",m_szUninstallScript));
  222. return FALSE;
  223. }
  224. m_bAlreadyInstalled = FALSE;
  225. }
  226. }
  227. return TRUE;
  228. }
  229. /******************************************************************************
  230. CAppScript::RunScript()
  231. Purpose:
  232. Runs script
  233. Waits untill script finishes
  234. ******************************************************************************/
  235. BOOL
  236. CAppScript::RunScript(
  237. LPCWSTR szDir,
  238. LPCWSTR szScript)
  239. {
  240. WCHAR szCmdLineTemplate[] = L"cmd.exe /C %s";
  241. DWORD dwSize = wcslen(szScript)*sizeof(WCHAR)+sizeof(szCmdLineTemplate);
  242. LPWSTR szCmdLine = (LPWSTR)LocalAlloc(LPTR,dwSize);
  243. if(!szCmdLine)
  244. {
  245. return FALSE;
  246. }
  247. swprintf(szCmdLine,szCmdLineTemplate,szScript);
  248. STARTUPINFO si; // startup information
  249. PROCESS_INFORMATION pi; // process information
  250. //Prepare startup info
  251. ZeroMemory(&si, sizeof(STARTUPINFO));
  252. si.cb = sizeof(STARTUPINFO);
  253. BOOL bResult = CreateProcessW(
  254. NULL, // name of executable module
  255. szCmdLine, // command line string
  256. NULL, // SD
  257. NULL, // SD
  258. FALSE, // handle inheritance option
  259. CREATE_NEW_CONSOLE, // creation flags
  260. NULL, // new environment block
  261. szDir, // current directory name
  262. &si, // startup information
  263. &pi // process information
  264. );
  265. LocalFree(szCmdLine);
  266. if(bResult)
  267. {
  268. WaitForSingleObject(pi.hProcess, INFINITE);
  269. CloseHandle(pi.hProcess);
  270. CloseHandle(pi.hThread);
  271. }
  272. return bResult;
  273. }
  274. /******************************************************************************
  275. CAppScript::PrepareScriptForReboot()
  276. Purpose:
  277. Creates CMD file that will change current directory to
  278. ...\Application Compatibility Scripts\Install
  279. and then run the script.
  280. Schedules this CMD file to be run after reboot by creating an entry uder
  281. "HKCU\Software\Microsoft\Windows\CurrentVersion\RunOnce" key.
  282. ******************************************************************************/
  283. BOOL
  284. CAppScript::PrepareScriptForReboot(
  285. LPCWSTR szInstallDir,
  286. LPCWSTR szScript)
  287. {
  288. WCHAR szFileNameTemplate[] = L"%s\\RunOnce.cmd";
  289. LPWSTR szFullFileName = (LPWSTR)LocalAlloc(LPTR,
  290. wcslen(szInstallDir)*sizeof(WCHAR)+sizeof(szFileNameTemplate));
  291. if(!szFullFileName)
  292. {
  293. return FALSE;
  294. }
  295. //Assemble full file name
  296. swprintf(szFullFileName,szFileNameTemplate,szInstallDir);
  297. HANDLE hFile = CreateFile(
  298. szFullFileName, // file name
  299. GENERIC_WRITE, // access mode
  300. 0, // share mode
  301. NULL, // SD
  302. CREATE_NEW, // how to create
  303. FILE_ATTRIBUTE_NORMAL, // file attributes
  304. NULL // handle to template file
  305. );
  306. LocalFree(szFullFileName);
  307. //File did not exist
  308. if(hFile != INVALID_HANDLE_VALUE)
  309. {
  310. //File did not exist before
  311. //create code and write it into the file.
  312. //need code in ANSI
  313. char szCodeTemplate[] = "cd %S\r\n%%1\r\n";
  314. DWORD nNumberOfBytesToWrite = wcslen(szInstallDir)+sizeof(szCodeTemplate);
  315. DWORD nNumberOfBytesWritten = 0;
  316. LPSTR szFileCode = (LPSTR)LocalAlloc(LPTR, nNumberOfBytesToWrite);
  317. if(!szFileCode)
  318. {
  319. CloseHandle(hFile);
  320. return FALSE;
  321. }
  322. sprintf(szFileCode, szCodeTemplate,szInstallDir);
  323. nNumberOfBytesToWrite = strlen(szFileCode);
  324. BOOL bResult = WriteFile(
  325. hFile, // handle to file
  326. (LPCVOID)szFileCode, // data buffer
  327. nNumberOfBytesToWrite, // number of bytes to write
  328. &nNumberOfBytesWritten, // number of bytes written
  329. NULL // overlapped buffer
  330. );
  331. CloseHandle(hFile);
  332. LocalFree(szFileCode);
  333. if(!bResult || nNumberOfBytesToWrite != nNumberOfBytesWritten )
  334. {
  335. return FALSE;
  336. }
  337. }
  338. else
  339. {
  340. if(GetLastError()!=ERROR_FILE_EXISTS)
  341. {
  342. return FALSE;
  343. }
  344. //If file already exists - do only registry changes.
  345. }
  346. //Registry changes:
  347. WCHAR szCommandTemplate[] = L"\"%s\\RunOnce.cmd\" %s";
  348. DWORD cbCommandLen = (wcslen(szInstallDir)+wcslen(szScript))*sizeof(WCHAR)+sizeof(szCommandTemplate);
  349. LPWSTR szCommand = (LPWSTR)LocalAlloc(LPTR,cbCommandLen);
  350. if(!szCommand)
  351. {
  352. return FALSE;
  353. }
  354. swprintf(szCommand,szCommandTemplate,szInstallDir,szScript);
  355. cbCommandLen = (wcslen(szCommand)+1)*sizeof(WCHAR);
  356. HKEY hKey;
  357. LONG err;
  358. err = RegCreateKeyExW(HKEY_CURRENT_USER,
  359. L"Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce",
  360. 0,
  361. NULL,
  362. 0,
  363. KEY_WRITE,
  364. NULL,
  365. &hKey,
  366. NULL);
  367. if(err == ERROR_SUCCESS)
  368. {
  369. err = RegSetValueExW(hKey,
  370. L"ZZZAppCompatScript",
  371. 0,
  372. REG_SZ,
  373. (CONST BYTE *)szCommand,
  374. cbCommandLen);
  375. RegCloseKey(hKey);
  376. }
  377. LocalFree(szCommand);
  378. if(err == ERROR_SUCCESS)
  379. {
  380. return TRUE;
  381. }
  382. else
  383. {
  384. return FALSE;
  385. }
  386. }
  387. ///////////////////////////////////////////////////////////////////////////////
  388. //class CAppScriptManager
  389. ///////////////////////////////////////////////////////////////////////////////
  390. /******************************************************************************
  391. CAppScriptManager::Init()
  392. Purpose:
  393. Initialization.
  394. Returns FALSE if TS Application Compatibility if OFF or list of supported
  395. applications was not found in the registry.
  396. ******************************************************************************/
  397. BOOL
  398. CAppScriptManager::Init()
  399. {
  400. //DebugBreak();
  401. KdPrint(("CAppScriptManager::Init() - ENTER\n"));
  402. if(!IsAppCompatOn())
  403. {
  404. KdPrint(("CAppScriptManager::Init() - TS App Compat is off!\n"));
  405. return FALSE;
  406. }
  407. if(!LoadSupportedAppList())
  408. {
  409. KdPrint(("CAppScriptManager::Init() - LoadSupportedAppList() FAILED\n"));
  410. return FALSE;
  411. }
  412. KdPrint(("CAppScriptManager::Init() - OK\n"));
  413. return TRUE;
  414. }
  415. /******************************************************************************
  416. CAppScriptManager::LoadSupportedAppList()
  417. Purpose:
  418. Loads from the registry the list of applications we care about
  419. along with their script names. Save this information in array of
  420. APP_SCRIPT structures.
  421. ******************************************************************************/
  422. BOOL
  423. CAppScriptManager::LoadSupportedAppList()
  424. {
  425. HKEY hKey;
  426. LONG err;
  427. DWORD cSubKeys;
  428. DWORD cMaxSubKeyLen;
  429. KdPrint(("CAppScriptManager::LoadSupportedAppList() - ENTER\n"));
  430. err = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
  431. L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Terminal Server\\Compatibility\\Scripts",
  432. 0, KEY_READ, &hKey );
  433. if(err == ERROR_SUCCESS)
  434. {
  435. err = RegGetKeyInfo(hKey, &cSubKeys, &cMaxSubKeyLen);
  436. if(err == ERROR_SUCCESS)
  437. {
  438. cMaxSubKeyLen+=1; //to include terminating NULL character
  439. KdPrint(("CAppScriptManager::LoadSupportedAppList() - %d apps supported\n",cSubKeys));
  440. //Allocate buffer for subkey names
  441. LPWSTR szKeyName = (LPWSTR)LocalAlloc(LPTR,cMaxSubKeyLen*sizeof(WCHAR));
  442. if(!szKeyName)
  443. {
  444. RegCloseKey(hKey);
  445. return FALSE;
  446. }
  447. CAppScript *pAppScript = NULL;
  448. for(DWORD i=0;i<cSubKeys;i++)
  449. {
  450. //Get the key name
  451. err = RegKeyEnum(hKey, i, szKeyName, cMaxSubKeyLen );
  452. if(err != ERROR_SUCCESS)
  453. {
  454. break;
  455. }
  456. KdPrint(("CAppScriptManager::LoadSupportedAppList() - loading %ws\n",szKeyName));
  457. pAppScript = new CAppScript();
  458. if(!pAppScript)
  459. {
  460. break;
  461. }
  462. if(pAppScript->Load(hKey, szKeyName))
  463. {
  464. m_AppScriptList.push_back(pAppScript);
  465. }
  466. else
  467. {
  468. KdPrint(("CAppScriptManager::LoadSupportedAppList() - FAILED to load\n"));
  469. delete pAppScript;
  470. }
  471. }
  472. LocalFree(szKeyName);
  473. }
  474. RegCloseKey(hKey);
  475. }
  476. if(err != ERROR_SUCCESS)
  477. {
  478. return FALSE;
  479. }
  480. else
  481. {
  482. return TRUE;
  483. }
  484. }
  485. /******************************************************************************
  486. CAppScriptManager::RunScripts()
  487. Purpose:
  488. Runs scripts for all installed or uninstalled applications.
  489. ******************************************************************************/
  490. BOOL
  491. CAppScriptManager::RunScripts()
  492. {
  493. BOOL bInstallMode = FALSE;
  494. KdPrint(("CAppScriptManager::RunScripts() - ENTER\n"));
  495. //system must be now in INSTALL mode, set EXECUTE mode
  496. if(TermsrvAppInstallMode())
  497. {
  498. bInstallMode = TRUE;
  499. KdPrint(("CAppScriptManager::RunScripts() - set EXECUTE mode\n"));
  500. if(!SetTermsrvAppInstallMode(FALSE))
  501. {
  502. KdPrint(("CAppScriptManager::RunScripts() - SetTermsrvAppInstallMode() FAILED\n"));
  503. return FALSE;
  504. }
  505. }
  506. CAppScriptList::iterator it;
  507. for(it=m_AppScriptList.begin();it!=m_AppScriptList.end(); it++)
  508. {
  509. (*it)->RunScriptIfApplicable();
  510. }
  511. if(bInstallMode)
  512. {
  513. //Restore INSTALL mode
  514. KdPrint(("CAppScriptManager::RunScripts() - return to INSTALL mode\n"));
  515. if(!SetTermsrvAppInstallMode(TRUE))
  516. {
  517. KdPrint(("CAppScriptManager::RunScripts() - SetTermsrvAppInstallMode() FAILED\n"));
  518. return FALSE;
  519. }
  520. }
  521. KdPrint(("CAppScriptManager::RunScripts() - FINISH\n"));
  522. return TRUE;
  523. }
  524. /******************************************************************************
  525. CAppScriptManager::IsAppCompatOn()
  526. Purpose:
  527. Checks if TS Application Compatibility mode is enabled.
  528. Returns TRUE if enabled,
  529. otherwise, as well as in case of any error, returns FALSE.
  530. ******************************************************************************/
  531. BOOL
  532. CAppScriptManager::IsAppCompatOn()
  533. {
  534. HKEY hKey;
  535. DWORD dwData;
  536. BOOL fResult = FALSE;
  537. KdPrint(("CAppScriptManager::IsAppCompatOn() - ENTER\n"));
  538. if( RegOpenKeyExW(HKEY_LOCAL_MACHINE,
  539. REG_CONTROL_TSERVER,
  540. 0,
  541. KEY_QUERY_VALUE,
  542. &hKey) == ERROR_SUCCESS )
  543. {
  544. if(RegLoadDWORD(hKey, L"TSAppCompat", &dwData) == ERROR_SUCCESS )
  545. {
  546. KdPrint(("CAppScriptManager::IsAppCompatOn() - OK; Result=%d\n",dwData));
  547. fResult = dwData;
  548. }
  549. RegCloseKey(hKey);
  550. }
  551. return fResult;
  552. }
  553. ///////////////////////////////////////////////////////////////////////////////
  554. //Functions - helpers.
  555. ///////////////////////////////////////////////////////////////////////////////
  556. /******************************************************************************
  557. RegLoadString()
  558. Purpose:
  559. Loads a REG_SZ value from the registry
  560. Allocates buffer.
  561. Buffer then need to be freed using LocalFree function.
  562. ******************************************************************************/
  563. DWORD
  564. RegLoadString(
  565. HKEY hKey,
  566. LPCWSTR szValueName,
  567. LPWSTR *pszValue)
  568. {
  569. DWORD cbData = 0;
  570. *pszValue = NULL;
  571. DWORD err = RegQueryValueExW(
  572. hKey, // handle to key
  573. szValueName, // value name
  574. NULL, // reserved
  575. NULL, // type buffer
  576. NULL, // data buffer
  577. &cbData // size of data buffer
  578. );
  579. if(err == ERROR_SUCCESS)
  580. {
  581. *pszValue = (LPWSTR)LocalAlloc(LPTR,cbData);
  582. if(!*pszValue)
  583. {
  584. return GetLastError();
  585. }
  586. err = RegQueryValueExW(
  587. hKey, // handle to key
  588. szValueName, // value name
  589. NULL, // reserved
  590. NULL, // type buffer
  591. (LPBYTE)*pszValue, // data buffer
  592. &cbData // size of data buffer
  593. );
  594. if(err !=ERROR_SUCCESS)
  595. {
  596. LocalFree(*pszValue);
  597. *pszValue = NULL;
  598. }
  599. }
  600. return err;
  601. }
  602. /******************************************************************************
  603. RegLoadDWORD()
  604. Purpose:
  605. Loads a REG_DWORD value from the registry
  606. ******************************************************************************/
  607. DWORD
  608. RegLoadDWORD(
  609. HKEY hKey,
  610. LPCWSTR szValueName,
  611. DWORD *pdwValue)
  612. {
  613. DWORD cbData = sizeof(DWORD);
  614. return RegQueryValueExW(
  615. hKey, // handle to key
  616. szValueName, // value name
  617. NULL, // reserved
  618. NULL, // type buffer
  619. (LPBYTE)pdwValue, // data buffer
  620. &cbData // size of data buffer
  621. );
  622. }
  623. /******************************************************************************
  624. RegIsKeyExist()
  625. Purpose:
  626. Checks if key exists
  627. ******************************************************************************/
  628. BOOL
  629. RegIsKeyExist(
  630. HKEY hKeyParent,
  631. LPCWSTR szKeyName)
  632. {
  633. LONG err;
  634. HKEY hKey;
  635. KdPrint(("RegIsKeyExist() - Opening key: hKeyParent=%d Key: %ws\n",hKeyParent,szKeyName));
  636. err = RegOpenKeyExW(hKeyParent, szKeyName, 0, MAXIMUM_ALLOWED, &hKey );
  637. if(err == ERROR_SUCCESS)
  638. {
  639. KdPrint(("RegIsKeyExist() - Key Exists!\n",err));
  640. RegCloseKey(hKey);
  641. return TRUE;
  642. }
  643. else
  644. {
  645. KdPrint(("RegIsKeyExist() - err=%d\n",err));
  646. return FALSE;
  647. }
  648. }
  649. /******************************************************************************
  650. RegGetKeyInfo()
  651. Purpose:
  652. Gets key's number of sub keys and max sub key name length
  653. ******************************************************************************/
  654. DWORD
  655. RegGetKeyInfo(
  656. HKEY hKey,
  657. LPDWORD pcSubKeys,
  658. LPDWORD pcMaxNameLen)
  659. {
  660. return RegQueryInfoKey(
  661. hKey, // handle to key
  662. NULL, // class buffer
  663. NULL, // size of class buffer
  664. NULL, // reserved
  665. pcSubKeys, // number of subkeys
  666. pcMaxNameLen, // longest subkey name (in TCHARs)
  667. NULL, // longest class string
  668. NULL, // number of value entries
  669. NULL, // longest value name
  670. NULL, // longest value data
  671. NULL, // descriptor length
  672. NULL // last write time
  673. );
  674. }
  675. /******************************************************************************
  676. RegKeyEnum()
  677. Purpose:
  678. Enumerates sub keys of the registry key
  679. ******************************************************************************/
  680. DWORD
  681. RegKeyEnum(
  682. HKEY hKey, // handle to key to enumerate
  683. DWORD dwIndex, // subkey index
  684. LPWSTR szSubKeyName, // subkey name
  685. DWORD cSubKeyName)
  686. {
  687. FILETIME ftLastWriteTime;
  688. return RegEnumKeyExW(
  689. hKey, // handle to key to enumerate
  690. dwIndex, // subkey index
  691. szSubKeyName, // subkey name
  692. &cSubKeyName, // size of subkey buffer
  693. NULL, // reserved
  694. NULL, // class string buffer
  695. NULL, // size of class string buffer
  696. &ftLastWriteTime // last write time
  697. );
  698. }