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.

691 lines
20 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // File Name: fxocReg.cpp
  4. //
  5. // Abstract: This provides the registry routines used in the FaxOCM
  6. // code base.
  7. //
  8. // Environment: Windows XP / User Mode
  9. //
  10. // Copyright (c) 2000 Microsoft Corporation
  11. //
  12. // Revision History:
  13. //
  14. // Date: Developer: Comments:
  15. // ----- ---------- ---------
  16. // 21-Mar-2000 Oren Rosenbloom (orenr) Created
  17. //////////////////////////////////////////////////////////////////////////////
  18. #include "faxocm.h"
  19. #pragma hdrstop
  20. #include <Loadperf.h>
  21. //////////////////////// Static Function Prototypes ////////////////////////
  22. static DWORD prv_InstallDynamicRegistry(const TCHAR *pszSection);
  23. static DWORD prv_UninstallDynamicRegistry(const TCHAR *pszSection);
  24. static DWORD prv_CreatePerformanceCounters(void);
  25. static DWORD prv_DeletePerformanceCounters(void);
  26. void prv_AddSecurityPrefix(void);
  27. ///////////////////////////////
  28. // fxocReg_Init
  29. //
  30. // Initialize registry handling
  31. // subsystem
  32. //
  33. // Params:
  34. // - void
  35. // Returns:
  36. // - NO_ERROR on success
  37. // - error code otherwise
  38. //
  39. DWORD fxocReg_Init(void)
  40. {
  41. DWORD dwRes = NO_ERROR;
  42. DBG_ENTER(_T("Init Registry Module"),dwRes);
  43. return dwRes;
  44. }
  45. ///////////////////////////////
  46. // fxocReg_Term
  47. //
  48. // Terminate the registry handling
  49. // subsystem
  50. //
  51. // Params:
  52. // - void
  53. // Returns:
  54. // - NO_ERROR on success
  55. // - error code otherwise
  56. //
  57. DWORD fxocReg_Term(void)
  58. {
  59. DWORD dwRes = NO_ERROR;
  60. DBG_ENTER(_T("Term Registry Module"),dwRes);
  61. return dwRes;
  62. }
  63. ///////////////////////////////
  64. // fxocReg_Install
  65. //
  66. // Create registry settings as
  67. // specified in INF file, as well
  68. // as dynamic settings that can only
  69. // be done at run time (such as
  70. // performance counter setup, etc).
  71. //
  72. // Params:
  73. // - pszSubcomponentId
  74. // - pszInstallSection
  75. // Returns:
  76. // - NO_ERROR on success
  77. // - error code otherwise
  78. //
  79. DWORD fxocReg_Install(const TCHAR *pszSubcomponentId,
  80. const TCHAR *pszInstallSection)
  81. {
  82. DWORD dwReturn = NO_ERROR;
  83. DWORD dwNumDevices = 0;
  84. HINF hInf = faxocm_GetComponentInf();
  85. DBG_ENTER( _T("fxocReg_Install"),
  86. dwReturn,
  87. _T("%s - %s"),
  88. pszSubcomponentId,
  89. pszInstallSection);
  90. if (pszInstallSection == NULL)
  91. {
  92. return ERROR_INVALID_PARAMETER;
  93. }
  94. // Set up the static registry data found in the INF file
  95. // This will perform all necessary install steps as specified
  96. // by the SPINST_* flags below. Since we already queued up our
  97. // files to be copied, we are using this API only to setup our
  98. // registry settings as specified in the FAX install section in
  99. // the INF file.
  100. // Notice that this function works both for installing and uninstalling.
  101. // It determines whether to install or uninstall based on the "pszSection"
  102. // parameter passed in from the INF file. The INF file will be structured
  103. // such that the install sections will have 'AddReg', etc, while the
  104. // uninstall sections will have 'DelReg', etc.
  105. // Lastly, notice the SPINST_* flags specified. We tell it to install
  106. // everything (via SPINST_ALL) with the exception of FILES since they
  107. // were copied over by the QUEUE_OPS operation before, and with the
  108. // exception of PROFILEITEMS (shortcut link creation) because we want
  109. // to do that only after we have confirmed everything has succeeded.
  110. // Shortcut links are explictely created/deleted in faxocm.cpp (via
  111. // fxocLink_Install/fxocLink_Uninstall functions)
  112. dwReturn = fxocUtil_DoSetup(
  113. hInf,
  114. pszInstallSection,
  115. TRUE,
  116. SPINST_ALL & ~(SPINST_FILES | SPINST_PROFILEITEMS),
  117. _T("fxocReg_Install"));
  118. if (dwReturn == NO_ERROR)
  119. {
  120. VERBOSE(DBG_MSG,
  121. _T("Successfully installed static registry ")
  122. _T("settings as specified in INF file"));
  123. // Place any dynamic registry data you need to create on the fly
  124. // here.
  125. //
  126. dwReturn = prv_InstallDynamicRegistry(pszInstallSection);
  127. }
  128. if (dwReturn == NO_ERROR)
  129. {
  130. VERBOSE(DBG_MSG,
  131. _T("Registry Install, installing performance ")
  132. _T("counters..."));
  133. // first delete any performance counters we have before
  134. prv_DeletePerformanceCounters();
  135. // install performance counters
  136. prv_CreatePerformanceCounters();
  137. }
  138. // now do RegSvr for platform dependent DLLs
  139. if (dwReturn == NO_ERROR)
  140. {
  141. VERBOSE(DBG_MSG,_T("Registry Install, Doing REGSVR"));
  142. dwReturn = fxocUtil_SearchAndExecute(pszInstallSection,INF_KEYWORD_REGISTER_DLL_PLATFORM,SPINST_REGSVR,NULL);
  143. if (dwReturn == NO_ERROR)
  144. {
  145. VERBOSE(DBG_MSG,
  146. _T("Successfully Registered Fax DLLs - platform dependent")
  147. _T("from INF file, section '%s'"),
  148. pszInstallSection);
  149. }
  150. else
  151. {
  152. VERBOSE(SETUP_ERR,
  153. _T("Failed to Registered Fax DLLs - platform dependent")
  154. _T("from INF file, section '%s', dwReturn = 0x%lx"),
  155. pszInstallSection,
  156. dwReturn);
  157. }
  158. }
  159. // now do AddReg for platform dependent registry settings
  160. if (dwReturn == NO_ERROR)
  161. {
  162. VERBOSE(DBG_MSG,_T("Registry Install, Doing AddReg_Platform"));
  163. dwReturn = fxocUtil_SearchAndExecute(pszInstallSection,INF_KEYWORD_ADDREG_PLATFORM,SPINST_REGISTRY,NULL);
  164. if (dwReturn == NO_ERROR)
  165. {
  166. VERBOSE(DBG_MSG,
  167. _T("Successfully Installed Registry- platform dependent")
  168. _T("from INF file, section '%s'"),
  169. pszInstallSection);
  170. }
  171. else
  172. {
  173. VERBOSE(SETUP_ERR,
  174. _T("Failed to Install Registry- platform dependent")
  175. _T("from INF file, section '%s', dwReturn = 0x%lx"),
  176. pszInstallSection,
  177. dwReturn);
  178. }
  179. }
  180. // When upgrading from SB3 to >=RC1, need to pre-pend FAX_REG_SECURITY_PREFIX
  181. // to all encripted data
  182. if (dwReturn == NO_ERROR &&
  183. fxState_IsUpgrade() == FXSTATE_UPGRADE_TYPE_XP_DOT_NET)
  184. {
  185. prv_AddSecurityPrefix();
  186. }
  187. // now write the version and SKU into the registry
  188. if (dwReturn == NO_ERROR)
  189. {
  190. VERBOSE(DBG_MSG,_T("Registry Install, Doing SKU and Version"));
  191. HKEY hKey = OpenRegistryKey(HKEY_LOCAL_MACHINE,REGKEY_FAX_SETUP,FALSE,KEY_WRITE);
  192. if (hKey==NULL)
  193. {
  194. dwReturn = GetLastError();
  195. VERBOSE(SETUP_ERR,
  196. _T("Failed to open fax setup registry, dwReturn = 0x%lx"),
  197. dwReturn);
  198. return dwReturn;
  199. }
  200. // write the SKU into the registry
  201. if (!SetRegistryDword(hKey,REGVAL_PRODUCT_SKU,GetProductSKU()))
  202. {
  203. dwReturn = GetLastError();
  204. VERBOSE(SETUP_ERR,
  205. _T("SetRegistryDword REGVAL_PRODUCT_SKU failed , dwReturn = 0x%lx"),
  206. dwReturn);
  207. }
  208. // write the fax version into the registry
  209. if (!SetRegistryDword(hKey,REGVAL_PRODUCT_BUILD,GetProductBuild()))
  210. {
  211. dwReturn = GetLastError();
  212. VERBOSE(SETUP_ERR,
  213. _T("SetRegistryDword REGVAL_PRODUCT_VERSION failed , dwReturn = 0x%lx"),
  214. dwReturn);
  215. }
  216. RegCloseKey(hKey);
  217. }
  218. return dwReturn;
  219. }
  220. ///////////////////////////////
  221. // fxocReg_Uninstall
  222. //
  223. // Delete registry settings as
  224. // specified in INF file, as well
  225. // as dynamic settings that can only
  226. // be done at run time (such as
  227. // performance counter setup, etc).
  228. //
  229. // Params:
  230. // - pszSubcomponentId
  231. // - pszUninstallSection
  232. // Returns:
  233. // - NO_ERROR on success
  234. // - error code otherwise
  235. //
  236. DWORD fxocReg_Uninstall(const TCHAR *pszSubcomponentId,
  237. const TCHAR *pszUninstallSection)
  238. {
  239. DWORD dwReturn = NO_ERROR;
  240. HINF hInf = faxocm_GetComponentInf();
  241. DBG_ENTER( _T("fxocReg_Uninstall"),
  242. dwReturn,
  243. _T("%s - %s"),
  244. pszSubcomponentId,
  245. pszUninstallSection);
  246. if (pszUninstallSection == NULL)
  247. {
  248. return ERROR_INVALID_PARAMETER;
  249. }
  250. // try to cleanup regardless of the return value.
  251. prv_UninstallDynamicRegistry(pszUninstallSection);
  252. // remove any performance counters related to fax.
  253. prv_DeletePerformanceCounters();
  254. // remove the static registry settings specified in the INF file
  255. fxocUtil_DoSetup(hInf,
  256. pszUninstallSection,
  257. FALSE,
  258. SPINST_ALL & ~(SPINST_FILES | SPINST_PROFILEITEMS),
  259. _T("fxocReg_Uninstall"));
  260. return dwReturn;
  261. }
  262. ///////////////////////////////
  263. // prv_InstallDynamicRegistry
  264. //
  265. // Installs dynamic registry
  266. // settings that can only be
  267. // done at run time (as opposed
  268. // to via the faxsetup.inf file)
  269. //
  270. // Params:
  271. // - pszSection -
  272. // Returns:
  273. // - NO_ERROR on success.
  274. // - error code otherwise.
  275. //
  276. static DWORD prv_InstallDynamicRegistry(const TCHAR *pszSection)
  277. {
  278. DWORD dwReturn = NO_ERROR;
  279. LONG lResult = ERROR_SUCCESS;
  280. HKEY hKey = NULL;
  281. BOOL bIsServerInstall = FALSE;
  282. DWORD dwProductType = 0;
  283. DBG_ENTER( _T("prv_InstallDynamicRegistry"),
  284. dwReturn,
  285. _T("%s"),
  286. pszSection);
  287. if (pszSection == NULL)
  288. {
  289. return ERROR_INVALID_PARAMETER;
  290. }
  291. // open the install type registry key.
  292. lResult = RegOpenKeyEx(HKEY_CURRENT_USER,
  293. REGKEY_FAX_SETUP,
  294. 0,
  295. KEY_ALL_ACCESS,
  296. &hKey);
  297. if (lResult == ERROR_SUCCESS)
  298. {
  299. bIsServerInstall = fxState_IsOsServerBeingInstalled();
  300. if (bIsServerInstall)
  301. {
  302. dwProductType = FAX_INSTALL_SERVER;
  303. }
  304. else
  305. {
  306. dwProductType = FAX_INSTALL_WORKSTATION;
  307. }
  308. lResult = ::RegSetValueEx(hKey,
  309. REGVAL_FAXINSTALL_TYPE,
  310. 0,
  311. REG_DWORD,
  312. (BYTE*) &dwProductType,
  313. sizeof(dwProductType));
  314. if (lResult != ERROR_SUCCESS)
  315. {
  316. dwReturn = (DWORD) lResult;
  317. VERBOSE(SETUP_ERR,
  318. _T("Failed to set InstallType, ")
  319. _T("rc = 0x%lx"),
  320. lResult);
  321. }
  322. }
  323. if (hKey)
  324. {
  325. ::RegCloseKey(hKey);
  326. hKey = NULL;
  327. }
  328. if (dwReturn == NO_ERROR)
  329. {
  330. VERBOSE(DBG_MSG,
  331. _T("Successfully installed dynamic Registry ")
  332. _T("settings from INF file, section '%s'"),
  333. pszSection);
  334. }
  335. else
  336. {
  337. VERBOSE(SETUP_ERR,
  338. _T("Failed to install dynamic Registry ")
  339. _T("settings from INF file, section '%s', ")
  340. _T("rc = 0x%lx"),
  341. pszSection,
  342. dwReturn);
  343. }
  344. return dwReturn;
  345. }
  346. ///////////////////////////////
  347. // prv_UninstallDynamicRegistry
  348. //
  349. // Uninstall dynamic registry.
  350. //
  351. // Params:
  352. // - pszSection.
  353. // Returns:
  354. // - NO_ERROR on success.
  355. // - error code otherwise.
  356. //
  357. static DWORD prv_UninstallDynamicRegistry(const TCHAR *pszSection)
  358. {
  359. DWORD dwRes = NO_ERROR;
  360. DBG_ENTER( _T("prv_InstallDynamicRegistry"),
  361. dwRes,
  362. _T("%s"),
  363. pszSection);
  364. return dwRes;
  365. }
  366. ///////////////////////////////
  367. // CreatePerformanceCounters
  368. //
  369. // Create the performance counters
  370. // for fax in the registry.
  371. //
  372. // Params:
  373. // - void
  374. // Returns:
  375. // - NO_ERROR on success.
  376. // - error code otherwise.
  377. //
  378. // Author: Mooly Beery (MoolyB) 17-Aug-2000
  379. //
  380. static DWORD prv_CreatePerformanceCounters()
  381. {
  382. DWORD dwRet = ERROR_SUCCESS;
  383. TCHAR szInstallDir[MAX_PATH] = {0};
  384. TCHAR szInstallCmdLine[MAX_PATH+20] = {0};
  385. DBG_ENTER(_T("CreatePerformanceCounters"),dwRet);
  386. // get the install location of fxsperf.dll from Windows Installer
  387. if (!GetSystemDirectory(szInstallDir,ARR_SIZE(szInstallDir)))
  388. {
  389. dwRet = GetLastError();
  390. VERBOSE (GENERAL_ERR,_T("GetSystemDirectory failed (ec: %ld)."),dwRet);
  391. goto exit;
  392. }
  393. _sntprintf(szInstallCmdLine,ARR_SIZE(szInstallCmdLine)-1,_T("x \"%s%s\""),szInstallDir,FAX_FILENAME_FAXPERF_INI);
  394. VERBOSE(DBG_MSG,_T("Calling LoadPerfCounterTextStrings with %s "),szInstallCmdLine);
  395. dwRet = LoadPerfCounterTextStrings(szInstallCmdLine,TRUE);
  396. if (dwRet==ERROR_SUCCESS)
  397. {
  398. VERBOSE(DBG_MSG,_T("LoadPerfCounterTextStrings success"));
  399. }
  400. else
  401. {
  402. VERBOSE(GENERAL_ERR,_T("LoadPerfCounterTextStrings failed (ec=%d)"),dwRet);
  403. }
  404. exit:
  405. return dwRet;
  406. }
  407. ///////////////////////////////
  408. // DeletePerformanceCounters
  409. //
  410. // Delete the performance counters
  411. // for fax in the registry.
  412. //
  413. // Params:
  414. // - void
  415. // Returns:
  416. // - NO_ERROR on success.
  417. // - error code otherwise.
  418. //
  419. // Author: Mooly Beery (MoolyB) 17-Aug-2000
  420. //
  421. static DWORD prv_DeletePerformanceCounters()
  422. {
  423. DWORD dwRet = ERROR_SUCCESS;
  424. DBG_ENTER(_T("DeletePerformanceCounters"));
  425. dwRet = UnloadPerfCounterTextStrings(_T("x ") FAX_SERVICE_NAME,TRUE);
  426. if (dwRet==ERROR_SUCCESS)
  427. {
  428. VERBOSE(DBG_MSG,_T("UnloadPerfCounterTextStrings success"));
  429. }
  430. else
  431. {
  432. VERBOSE(GENERAL_ERR,_T("UnloadPerfCounterTextStrings failed (ec=%d)"),dwRet);
  433. }
  434. return dwRet;
  435. }
  436. /*++
  437. Routine description:
  438. Pre-pends FAX_REG_SECURITY_PREFIX to a value
  439. Arguments:
  440. hKey [in] - handle of a key
  441. lpszValueName [in] - name of value to work on
  442. Return Value: none
  443. Note: This function is sometimes used as a callback of EnumerateRegistryKeys(),
  444. therefore its signature must be compatible with PREGENUMCALLBACK
  445. --*/
  446. void prv_AddSecurityPrefixToValue(HKEY hKey, LPCTSTR lpszValueName)
  447. {
  448. LPBYTE pData = NULL;
  449. DWORD dwSize = 0;
  450. DWORD dwPrefixSize = sizeof (TCHAR) * wcslen (FAX_REG_SECURITY_PREFIX);
  451. DBG_ENTER(_T("prv_AddSecurityPrefixToValue"), _T("%s"), lpszValueName);
  452. pData = GetRegistryBinary(hKey, lpszValueName, &dwSize);
  453. if (pData)
  454. {
  455. if (dwSize <=1)
  456. {
  457. VERBOSE(DBG_MSG, _T("Size=%d, not real data"), dwSize);
  458. }
  459. else if ((dwSize>dwPrefixSize) && (memcmp(pData, FAX_REG_SECURITY_PREFIX, dwPrefixSize)==0))
  460. {
  461. VERBOSE(DBG_MSG, _T("Size=%d, data already has prefix"), dwSize);
  462. }
  463. else
  464. {
  465. LPBYTE pNewData = NULL;
  466. VERBOSE(DBG_MSG, _T("Size=%d, adding prefix..."), dwSize);
  467. pNewData = (LPBYTE)MemAlloc(dwSize+dwPrefixSize);
  468. if (pNewData)
  469. {
  470. memcpy(pNewData, FAX_REG_SECURITY_PREFIX, dwPrefixSize);
  471. memcpy(&(pNewData[dwPrefixSize]), pData, dwSize);
  472. if (!SetRegistryBinary(hKey, lpszValueName, pNewData, dwSize+dwPrefixSize))
  473. {
  474. VERBOSE(DBG_WARNING, _T("SetRegistryBinary failed, ec=%x"), GetLastError());
  475. }
  476. MemFree(pNewData);
  477. }
  478. }
  479. MemFree(pData);
  480. }
  481. }
  482. /*++
  483. Routine description:
  484. Pre-pends FAX_REG_SECURITY_PREFIX to all binary values in a specified key
  485. Arguments:
  486. hKey [in] - handle of a key
  487. lpszKeyName [in] - If NULL, the function does nothing
  488. (DWORD) - unused
  489. lpContextData [in] - (LPTSTR) name of subkey under hKey in which to work
  490. if NULL, function will work on hKey itself
  491. Return Value: Always returns true
  492. Note: This function is sometimes used as a callback of EnumerateRegistryKeys(),
  493. therefore its signature must be compatible with PREGENUMCALLBACK
  494. --*/
  495. BOOL prv_AddSecurityPrefixToKey(
  496. HKEY hKey, LPWSTR lpszKeyName, DWORD, LPVOID lpContextData)
  497. {
  498. LPTSTR lpszSubkey = (LPTSTR) lpContextData;
  499. HKEY hSubKey = NULL;
  500. int i;
  501. DWORD dwRet = NO_ERROR;
  502. DWORD dwType;
  503. DWORD dwValueNameSize;
  504. TCHAR szValueName[256] = {_T('\0')};
  505. DBG_ENTER(_T("prv_AddSecurityPrefixToKey"), _T("%s \\ %s"),
  506. lpszKeyName ? lpszKeyName : _T(""),
  507. lpContextData ? lpContextData : _T(""));
  508. // EnumerateRegistryKeys calls here once with the subkey - don't need that
  509. if (!lpszKeyName)
  510. {
  511. return TRUE;
  512. }
  513. if (lpContextData)
  514. {
  515. hSubKey = OpenRegistryKey(hKey, lpszSubkey, FALSE, KEY_READ | KEY_WRITE);
  516. if (!hSubKey)
  517. {
  518. return TRUE;
  519. }
  520. }
  521. for (i=0; ; i++)
  522. {
  523. dwValueNameSize = ARR_SIZE(szValueName);
  524. dwRet = RegEnumValue(
  525. lpContextData ? hSubKey : hKey,
  526. i,
  527. szValueName,
  528. &dwValueNameSize,
  529. NULL, // reserved
  530. &dwType,
  531. NULL, // data buffer
  532. NULL); // size of data buffer
  533. if (dwRet == ERROR_NO_MORE_ITEMS)
  534. {
  535. break;
  536. }
  537. else if (dwRet != ERROR_SUCCESS)
  538. {
  539. VERBOSE(SETUP_ERR, _T("RegEnumValue failed, ec=%x"), dwRet);
  540. break;
  541. }
  542. if (dwType == REG_BINARY)
  543. {
  544. prv_AddSecurityPrefixToValue(lpContextData ? hSubKey : hKey, szValueName);
  545. }
  546. }
  547. if (hSubKey)
  548. {
  549. RegCloseKey(hSubKey);
  550. }
  551. return TRUE;
  552. }
  553. /*++
  554. Routine description:
  555. Pre-pends FAX_REG_SECURITY_PREFIX to all encrypted registry values.
  556. Arguments: none
  557. Return Value: none
  558. Note: Encrypted registry values are located at:
  559. Fax\TAPIDevices\<deviceID>
  560. Fax\Devices Cache\<deviceID>\TAPI Data
  561. Fax\Devices\UnassociatedExtensionData
  562. Fax\Receipts (Password value only)
  563. --*/
  564. void prv_AddSecurityPrefix(void)
  565. {
  566. HKEY hKey = NULL;
  567. DBG_ENTER(_T("prv_AddSecurityPrefix"));
  568. // Add prefixes to all values under TAPIDevices\<deviceID>
  569. EnumerateRegistryKeys(
  570. HKEY_LOCAL_MACHINE,
  571. REGKEY_TAPIDEVICES,
  572. TRUE,
  573. prv_AddSecurityPrefixToKey,
  574. NULL);
  575. // EnumerateRegistryKeys returns the number of enumerated subkeys - we don't care about it
  576. // Add prefixes to all values under Devices Cache\<deviceID>\TAPI Data
  577. EnumerateRegistryKeys(
  578. HKEY_LOCAL_MACHINE,
  579. REGKEY_FAX_DEVICES_CACHE,
  580. TRUE,
  581. prv_AddSecurityPrefixToKey,
  582. (LPVOID)REGKEY_TAPI_DATA);
  583. // EnumerateRegistryKeys returns the number of enumerated subkeys - we don't care about it
  584. // Add prefixes to all values under Devices\UnassociatedExtensionData
  585. prv_AddSecurityPrefixToKey(HKEY_LOCAL_MACHINE, _T(""), 0, REGKEY_FAX_UNASS_DATA);
  586. // Add prefix to Receipts\Password
  587. hKey = OpenRegistryKey(HKEY_LOCAL_MACHINE, REGKEY_FAX_RECEIPTS, FALSE, KEY_READ | KEY_WRITE);
  588. if (hKey)
  589. {
  590. prv_AddSecurityPrefixToValue(hKey, REGVAL_RECEIPTS_PASSWORD);
  591. RegCloseKey(hKey);
  592. }
  593. }