////////////////////////////////////////////////////////////////////////////// // // File Name: fxocReg.cpp // // Abstract: This provides the registry routines used in the FaxOCM // code base. // // Environment: Windows XP / User Mode // // Copyright (c) 2000 Microsoft Corporation // // Revision History: // // Date: Developer: Comments: // ----- ---------- --------- // 21-Mar-2000 Oren Rosenbloom (orenr) Created ////////////////////////////////////////////////////////////////////////////// #include "faxocm.h" #pragma hdrstop #include //////////////////////// Static Function Prototypes //////////////////////// static DWORD prv_InstallDynamicRegistry(const TCHAR *pszSection); static DWORD prv_UninstallDynamicRegistry(const TCHAR *pszSection); static DWORD prv_CreatePerformanceCounters(void); static DWORD prv_DeletePerformanceCounters(void); void prv_AddSecurityPrefix(void); /////////////////////////////// // fxocReg_Init // // Initialize registry handling // subsystem // // Params: // - void // Returns: // - NO_ERROR on success // - error code otherwise // DWORD fxocReg_Init(void) { DWORD dwRes = NO_ERROR; DBG_ENTER(_T("Init Registry Module"),dwRes); return dwRes; } /////////////////////////////// // fxocReg_Term // // Terminate the registry handling // subsystem // // Params: // - void // Returns: // - NO_ERROR on success // - error code otherwise // DWORD fxocReg_Term(void) { DWORD dwRes = NO_ERROR; DBG_ENTER(_T("Term Registry Module"),dwRes); return dwRes; } /////////////////////////////// // fxocReg_Install // // Create registry settings as // specified in INF file, as well // as dynamic settings that can only // be done at run time (such as // performance counter setup, etc). // // Params: // - pszSubcomponentId // - pszInstallSection // Returns: // - NO_ERROR on success // - error code otherwise // DWORD fxocReg_Install(const TCHAR *pszSubcomponentId, const TCHAR *pszInstallSection) { DWORD dwReturn = NO_ERROR; DWORD dwNumDevices = 0; HINF hInf = faxocm_GetComponentInf(); DBG_ENTER( _T("fxocReg_Install"), dwReturn, _T("%s - %s"), pszSubcomponentId, pszInstallSection); if (pszInstallSection == NULL) { return ERROR_INVALID_PARAMETER; } // Set up the static registry data found in the INF file // This will perform all necessary install steps as specified // by the SPINST_* flags below. Since we already queued up our // files to be copied, we are using this API only to setup our // registry settings as specified in the FAX install section in // the INF file. // Notice that this function works both for installing and uninstalling. // It determines whether to install or uninstall based on the "pszSection" // parameter passed in from the INF file. The INF file will be structured // such that the install sections will have 'AddReg', etc, while the // uninstall sections will have 'DelReg', etc. // Lastly, notice the SPINST_* flags specified. We tell it to install // everything (via SPINST_ALL) with the exception of FILES since they // were copied over by the QUEUE_OPS operation before, and with the // exception of PROFILEITEMS (shortcut link creation) because we want // to do that only after we have confirmed everything has succeeded. // Shortcut links are explictely created/deleted in faxocm.cpp (via // fxocLink_Install/fxocLink_Uninstall functions) dwReturn = fxocUtil_DoSetup( hInf, pszInstallSection, TRUE, SPINST_ALL & ~(SPINST_FILES | SPINST_PROFILEITEMS), _T("fxocReg_Install")); if (dwReturn == NO_ERROR) { VERBOSE(DBG_MSG, _T("Successfully installed static registry ") _T("settings as specified in INF file")); // Place any dynamic registry data you need to create on the fly // here. // dwReturn = prv_InstallDynamicRegistry(pszInstallSection); } if (dwReturn == NO_ERROR) { VERBOSE(DBG_MSG, _T("Registry Install, installing performance ") _T("counters...")); // first delete any performance counters we have before prv_DeletePerformanceCounters(); // install performance counters prv_CreatePerformanceCounters(); } // now do RegSvr for platform dependent DLLs if (dwReturn == NO_ERROR) { VERBOSE(DBG_MSG,_T("Registry Install, Doing REGSVR")); dwReturn = fxocUtil_SearchAndExecute(pszInstallSection,INF_KEYWORD_REGISTER_DLL_PLATFORM,SPINST_REGSVR,NULL); if (dwReturn == NO_ERROR) { VERBOSE(DBG_MSG, _T("Successfully Registered Fax DLLs - platform dependent") _T("from INF file, section '%s'"), pszInstallSection); } else { VERBOSE(SETUP_ERR, _T("Failed to Registered Fax DLLs - platform dependent") _T("from INF file, section '%s', dwReturn = 0x%lx"), pszInstallSection, dwReturn); } } // now do AddReg for platform dependent registry settings if (dwReturn == NO_ERROR) { VERBOSE(DBG_MSG,_T("Registry Install, Doing AddReg_Platform")); dwReturn = fxocUtil_SearchAndExecute(pszInstallSection,INF_KEYWORD_ADDREG_PLATFORM,SPINST_REGISTRY,NULL); if (dwReturn == NO_ERROR) { VERBOSE(DBG_MSG, _T("Successfully Installed Registry- platform dependent") _T("from INF file, section '%s'"), pszInstallSection); } else { VERBOSE(SETUP_ERR, _T("Failed to Install Registry- platform dependent") _T("from INF file, section '%s', dwReturn = 0x%lx"), pszInstallSection, dwReturn); } } // When upgrading from SB3 to >=RC1, need to pre-pend FAX_REG_SECURITY_PREFIX // to all encripted data if (dwReturn == NO_ERROR && fxState_IsUpgrade() == FXSTATE_UPGRADE_TYPE_XP_DOT_NET) { prv_AddSecurityPrefix(); } // now write the version and SKU into the registry if (dwReturn == NO_ERROR) { VERBOSE(DBG_MSG,_T("Registry Install, Doing SKU and Version")); HKEY hKey = OpenRegistryKey(HKEY_LOCAL_MACHINE,REGKEY_FAX_SETUP,FALSE,KEY_WRITE); if (hKey==NULL) { dwReturn = GetLastError(); VERBOSE(SETUP_ERR, _T("Failed to open fax setup registry, dwReturn = 0x%lx"), dwReturn); return dwReturn; } // write the SKU into the registry if (!SetRegistryDword(hKey,REGVAL_PRODUCT_SKU,GetProductSKU())) { dwReturn = GetLastError(); VERBOSE(SETUP_ERR, _T("SetRegistryDword REGVAL_PRODUCT_SKU failed , dwReturn = 0x%lx"), dwReturn); } // write the fax version into the registry if (!SetRegistryDword(hKey,REGVAL_PRODUCT_BUILD,GetProductBuild())) { dwReturn = GetLastError(); VERBOSE(SETUP_ERR, _T("SetRegistryDword REGVAL_PRODUCT_VERSION failed , dwReturn = 0x%lx"), dwReturn); } RegCloseKey(hKey); } return dwReturn; } /////////////////////////////// // fxocReg_Uninstall // // Delete registry settings as // specified in INF file, as well // as dynamic settings that can only // be done at run time (such as // performance counter setup, etc). // // Params: // - pszSubcomponentId // - pszUninstallSection // Returns: // - NO_ERROR on success // - error code otherwise // DWORD fxocReg_Uninstall(const TCHAR *pszSubcomponentId, const TCHAR *pszUninstallSection) { DWORD dwReturn = NO_ERROR; HINF hInf = faxocm_GetComponentInf(); DBG_ENTER( _T("fxocReg_Uninstall"), dwReturn, _T("%s - %s"), pszSubcomponentId, pszUninstallSection); if (pszUninstallSection == NULL) { return ERROR_INVALID_PARAMETER; } // try to cleanup regardless of the return value. prv_UninstallDynamicRegistry(pszUninstallSection); // remove any performance counters related to fax. prv_DeletePerformanceCounters(); // remove the static registry settings specified in the INF file fxocUtil_DoSetup(hInf, pszUninstallSection, FALSE, SPINST_ALL & ~(SPINST_FILES | SPINST_PROFILEITEMS), _T("fxocReg_Uninstall")); return dwReturn; } /////////////////////////////// // prv_InstallDynamicRegistry // // Installs dynamic registry // settings that can only be // done at run time (as opposed // to via the faxsetup.inf file) // // Params: // - pszSection - // Returns: // - NO_ERROR on success. // - error code otherwise. // static DWORD prv_InstallDynamicRegistry(const TCHAR *pszSection) { DWORD dwReturn = NO_ERROR; LONG lResult = ERROR_SUCCESS; HKEY hKey = NULL; BOOL bIsServerInstall = FALSE; DWORD dwProductType = 0; DBG_ENTER( _T("prv_InstallDynamicRegistry"), dwReturn, _T("%s"), pszSection); if (pszSection == NULL) { return ERROR_INVALID_PARAMETER; } // open the install type registry key. lResult = RegOpenKeyEx(HKEY_CURRENT_USER, REGKEY_FAX_SETUP, 0, KEY_ALL_ACCESS, &hKey); if (lResult == ERROR_SUCCESS) { bIsServerInstall = fxState_IsOsServerBeingInstalled(); if (bIsServerInstall) { dwProductType = FAX_INSTALL_SERVER; } else { dwProductType = FAX_INSTALL_WORKSTATION; } lResult = ::RegSetValueEx(hKey, REGVAL_FAXINSTALL_TYPE, 0, REG_DWORD, (BYTE*) &dwProductType, sizeof(dwProductType)); if (lResult != ERROR_SUCCESS) { dwReturn = (DWORD) lResult; VERBOSE(SETUP_ERR, _T("Failed to set InstallType, ") _T("rc = 0x%lx"), lResult); } } if (hKey) { ::RegCloseKey(hKey); hKey = NULL; } if (dwReturn == NO_ERROR) { VERBOSE(DBG_MSG, _T("Successfully installed dynamic Registry ") _T("settings from INF file, section '%s'"), pszSection); } else { VERBOSE(SETUP_ERR, _T("Failed to install dynamic Registry ") _T("settings from INF file, section '%s', ") _T("rc = 0x%lx"), pszSection, dwReturn); } return dwReturn; } /////////////////////////////// // prv_UninstallDynamicRegistry // // Uninstall dynamic registry. // // Params: // - pszSection. // Returns: // - NO_ERROR on success. // - error code otherwise. // static DWORD prv_UninstallDynamicRegistry(const TCHAR *pszSection) { DWORD dwRes = NO_ERROR; DBG_ENTER( _T("prv_InstallDynamicRegistry"), dwRes, _T("%s"), pszSection); return dwRes; } /////////////////////////////// // CreatePerformanceCounters // // Create the performance counters // for fax in the registry. // // Params: // - void // Returns: // - NO_ERROR on success. // - error code otherwise. // // Author: Mooly Beery (MoolyB) 17-Aug-2000 // static DWORD prv_CreatePerformanceCounters() { DWORD dwRet = ERROR_SUCCESS; TCHAR szInstallDir[MAX_PATH] = {0}; TCHAR szInstallCmdLine[MAX_PATH+20] = {0}; DBG_ENTER(_T("CreatePerformanceCounters"),dwRet); // get the install location of fxsperf.dll from Windows Installer if (!GetSystemDirectory(szInstallDir,ARR_SIZE(szInstallDir))) { dwRet = GetLastError(); VERBOSE (GENERAL_ERR,_T("GetSystemDirectory failed (ec: %ld)."),dwRet); goto exit; } _sntprintf(szInstallCmdLine,ARR_SIZE(szInstallCmdLine)-1,_T("x \"%s%s\""),szInstallDir,FAX_FILENAME_FAXPERF_INI); VERBOSE(DBG_MSG,_T("Calling LoadPerfCounterTextStrings with %s "),szInstallCmdLine); dwRet = LoadPerfCounterTextStrings(szInstallCmdLine,TRUE); if (dwRet==ERROR_SUCCESS) { VERBOSE(DBG_MSG,_T("LoadPerfCounterTextStrings success")); } else { VERBOSE(GENERAL_ERR,_T("LoadPerfCounterTextStrings failed (ec=%d)"),dwRet); } exit: return dwRet; } /////////////////////////////// // DeletePerformanceCounters // // Delete the performance counters // for fax in the registry. // // Params: // - void // Returns: // - NO_ERROR on success. // - error code otherwise. // // Author: Mooly Beery (MoolyB) 17-Aug-2000 // static DWORD prv_DeletePerformanceCounters() { DWORD dwRet = ERROR_SUCCESS; DBG_ENTER(_T("DeletePerformanceCounters")); dwRet = UnloadPerfCounterTextStrings(_T("x ") FAX_SERVICE_NAME,TRUE); if (dwRet==ERROR_SUCCESS) { VERBOSE(DBG_MSG,_T("UnloadPerfCounterTextStrings success")); } else { VERBOSE(GENERAL_ERR,_T("UnloadPerfCounterTextStrings failed (ec=%d)"),dwRet); } return dwRet; } /*++ Routine description: Pre-pends FAX_REG_SECURITY_PREFIX to a value Arguments: hKey [in] - handle of a key lpszValueName [in] - name of value to work on Return Value: none Note: This function is sometimes used as a callback of EnumerateRegistryKeys(), therefore its signature must be compatible with PREGENUMCALLBACK --*/ void prv_AddSecurityPrefixToValue(HKEY hKey, LPCTSTR lpszValueName) { LPBYTE pData = NULL; DWORD dwSize = 0; DWORD dwPrefixSize = sizeof (TCHAR) * wcslen (FAX_REG_SECURITY_PREFIX); DBG_ENTER(_T("prv_AddSecurityPrefixToValue"), _T("%s"), lpszValueName); pData = GetRegistryBinary(hKey, lpszValueName, &dwSize); if (pData) { if (dwSize <=1) { VERBOSE(DBG_MSG, _T("Size=%d, not real data"), dwSize); } else if ((dwSize>dwPrefixSize) && (memcmp(pData, FAX_REG_SECURITY_PREFIX, dwPrefixSize)==0)) { VERBOSE(DBG_MSG, _T("Size=%d, data already has prefix"), dwSize); } else { LPBYTE pNewData = NULL; VERBOSE(DBG_MSG, _T("Size=%d, adding prefix..."), dwSize); pNewData = (LPBYTE)MemAlloc(dwSize+dwPrefixSize); if (pNewData) { memcpy(pNewData, FAX_REG_SECURITY_PREFIX, dwPrefixSize); memcpy(&(pNewData[dwPrefixSize]), pData, dwSize); if (!SetRegistryBinary(hKey, lpszValueName, pNewData, dwSize+dwPrefixSize)) { VERBOSE(DBG_WARNING, _T("SetRegistryBinary failed, ec=%x"), GetLastError()); } MemFree(pNewData); } } MemFree(pData); } } /*++ Routine description: Pre-pends FAX_REG_SECURITY_PREFIX to all binary values in a specified key Arguments: hKey [in] - handle of a key lpszKeyName [in] - If NULL, the function does nothing (DWORD) - unused lpContextData [in] - (LPTSTR) name of subkey under hKey in which to work if NULL, function will work on hKey itself Return Value: Always returns true Note: This function is sometimes used as a callback of EnumerateRegistryKeys(), therefore its signature must be compatible with PREGENUMCALLBACK --*/ BOOL prv_AddSecurityPrefixToKey( HKEY hKey, LPWSTR lpszKeyName, DWORD, LPVOID lpContextData) { LPTSTR lpszSubkey = (LPTSTR) lpContextData; HKEY hSubKey = NULL; int i; DWORD dwRet = NO_ERROR; DWORD dwType; DWORD dwValueNameSize; TCHAR szValueName[256] = {_T('\0')}; DBG_ENTER(_T("prv_AddSecurityPrefixToKey"), _T("%s \\ %s"), lpszKeyName ? lpszKeyName : _T(""), lpContextData ? lpContextData : _T("")); // EnumerateRegistryKeys calls here once with the subkey - don't need that if (!lpszKeyName) { return TRUE; } if (lpContextData) { hSubKey = OpenRegistryKey(hKey, lpszSubkey, FALSE, KEY_READ | KEY_WRITE); if (!hSubKey) { return TRUE; } } for (i=0; ; i++) { dwValueNameSize = ARR_SIZE(szValueName); dwRet = RegEnumValue( lpContextData ? hSubKey : hKey, i, szValueName, &dwValueNameSize, NULL, // reserved &dwType, NULL, // data buffer NULL); // size of data buffer if (dwRet == ERROR_NO_MORE_ITEMS) { break; } else if (dwRet != ERROR_SUCCESS) { VERBOSE(SETUP_ERR, _T("RegEnumValue failed, ec=%x"), dwRet); break; } if (dwType == REG_BINARY) { prv_AddSecurityPrefixToValue(lpContextData ? hSubKey : hKey, szValueName); } } if (hSubKey) { RegCloseKey(hSubKey); } return TRUE; } /*++ Routine description: Pre-pends FAX_REG_SECURITY_PREFIX to all encrypted registry values. Arguments: none Return Value: none Note: Encrypted registry values are located at: Fax\TAPIDevices\ Fax\Devices Cache\\TAPI Data Fax\Devices\UnassociatedExtensionData Fax\Receipts (Password value only) --*/ void prv_AddSecurityPrefix(void) { HKEY hKey = NULL; DBG_ENTER(_T("prv_AddSecurityPrefix")); // Add prefixes to all values under TAPIDevices\ EnumerateRegistryKeys( HKEY_LOCAL_MACHINE, REGKEY_TAPIDEVICES, TRUE, prv_AddSecurityPrefixToKey, NULL); // EnumerateRegistryKeys returns the number of enumerated subkeys - we don't care about it // Add prefixes to all values under Devices Cache\\TAPI Data EnumerateRegistryKeys( HKEY_LOCAL_MACHINE, REGKEY_FAX_DEVICES_CACHE, TRUE, prv_AddSecurityPrefixToKey, (LPVOID)REGKEY_TAPI_DATA); // EnumerateRegistryKeys returns the number of enumerated subkeys - we don't care about it // Add prefixes to all values under Devices\UnassociatedExtensionData prv_AddSecurityPrefixToKey(HKEY_LOCAL_MACHINE, _T(""), 0, REGKEY_FAX_UNASS_DATA); // Add prefix to Receipts\Password hKey = OpenRegistryKey(HKEY_LOCAL_MACHINE, REGKEY_FAX_RECEIPTS, FALSE, KEY_READ | KEY_WRITE); if (hKey) { prv_AddSecurityPrefixToValue(hKey, REGVAL_RECEIPTS_PASSWORD); RegCloseKey(hKey); } }