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.

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