#include "regsvr.h" #include "reg.h" #include "str.h" #include "sfstr.h" #include "factdata.h" #include #define ARRAYSIZE(a) (sizeof((a))/sizeof((a)[0])) /////////////////////////////////////////////////////////////////////////////// // Internal helper functions prototypes LONG _RecursiveDeleteKey(HKEY hKeyParent, LPCWSTR szKeyChild); /////////////////////////////////////////////////////////////////////////////// // Constants // Size of a CLSID as a string const int CLSID_STRING_SIZE = 39; /////////////////////////////////////////////////////////////////////////////// // Public function implementation HRESULT RegisterAppID(const CLSID* pclsidAppID) { WCHAR szAppID[CLSID_STRING_SIZE]; WCHAR szKey[MAX_KEY] = TEXT("AppID\\"); HRESULT hres = _StringFromGUID(pclsidAppID, szAppID, ARRAYSIZE(szAppID)); if (SUCCEEDED(hres)) { hres = SafeStrCatN(szKey, szAppID, ARRAYSIZE(szKey)); if (SUCCEEDED(hres)) { // Add the CLSID key and the FriendlyName HKEY hkey; hres= _RegCreateKey(HKEY_CLASSES_ROOT, szKey, &hkey, NULL); if (S_OK == hres) { hres = _RegSetString(hkey, L"LocalService", L"ShellHWDetection"); if (SUCCEEDED(hres)) { PSECURITY_DESCRIPTOR pSD; ULONG cbSD; // // NTRAID#NTBUG9-258937-2001/01/17-jeffreys // // Set the launch permissions to prevent COM from ever // launching the service. The only time we want the service // to launch is at system startup. // // Don't think the owner and group matter, but they must be // present, or COM thinks the security descriptor is invalid. // O:SY --> Owner = LocalSystem // G:BA --> Group = Local Administrators group // // The DACL has a single Deny ACE // D:(D;;1;;;WD) --> Deny COM_RIGHTS_EXECUTE (1) to Everyone (WD) // if (ConvertStringSecurityDescriptorToSecurityDescriptorW(L"O:SYG:BAD:(D;;1;;;WD)", SDDL_REVISION, &pSD, &cbSD)) { hres = _RegSetBinary(hkey, L"LaunchPermission", pSD, cbSD); LocalFree(pSD); } else { hres = E_OUTOFMEMORY; } } RegCloseKey(hkey); } } } return hres; } // Register the component in the registry. HRESULT RegisterServer(HMODULE hModule, REFCLSID rclsid, LPCWSTR pszFriendlyName, LPCWSTR pszVerIndProgID, LPCWSTR pszProgID, DWORD dwThreadingModel, BOOL fInprocServer, BOOL fLocalServer, BOOL fLocalService, LPCWSTR pszLocalService, const CLSID* pclsidAppID) { WCHAR szCLSID[CLSID_STRING_SIZE]; WCHAR szKey[MAX_KEY] = TEXT("CLSID\\"); HRESULT hres = _StringFromGUID(&rclsid, szCLSID, ARRAYSIZE(szCLSID)); if (SUCCEEDED(hres)) { LPWSTR pszModel = NULL; WCHAR szFree[] = TEXT("Free"); WCHAR szApartment[] = TEXT("Apartment"); WCHAR szNeutral[] = TEXT("Neutral"); WCHAR szBoth[] = TEXT("Both"); hres = SafeStrCatN(szKey, szCLSID, ARRAYSIZE(szKey)); // Boring set of operations.... if (SUCCEEDED(hres)) { // Add the CLSID key and the FriendlyName hres = _RegSetKeyAndString(HKEY_CLASSES_ROOT, szKey, NULL, NULL, pszFriendlyName); } if (SUCCEEDED(hres)) { switch (dwThreadingModel) { case THREADINGMODEL_BOTH: pszModel = szBoth; break; case THREADINGMODEL_FREE: pszModel = szFree; break; case THREADINGMODEL_APARTMENT: pszModel = szApartment; break; case THREADINGMODEL_NEUTRAL: pszModel = szNeutral; break; default: hres = E_FAIL; break; } } if (SUCCEEDED(hres)) { // Add the server filename subkey under the CLSID key. if (fInprocServer) { WCHAR szModule[MAX_PATH]; DWORD dwResult = GetModuleFileName(hModule, szModule, ARRAYSIZE(szModule)); if (dwResult) { // Register as Inproc hres = _RegSetKeyAndString(HKEY_CLASSES_ROOT, szKey, TEXT("InprocServer32"), NULL, szModule); if (SUCCEEDED(hres)) { hres = _RegSetKeyAndString(HKEY_CLASSES_ROOT, szKey, TEXT("InprocServer32"), TEXT("ThreadingModel"), pszModel); } } } } if (SUCCEEDED(hres)) { // Add the server filename subkey under the CLSID key. if (fLocalServer) { WCHAR szModule[MAX_PATH]; // Note the NULL as 1st arg. This way a DLL can register a // factory as part of an EXE. Obviously, if this is done // from 2 EXE's, only the last one will win... DWORD dwResult = GetModuleFileName(NULL, szModule, ARRAYSIZE(szModule)); if (dwResult) { // Register as LocalServer hres = _RegSetKeyAndString(HKEY_CLASSES_ROOT, szKey, TEXT("LocalServer32"), NULL, szModule); if (SUCCEEDED(hres)) { hres = _RegSetKeyAndString(HKEY_CLASSES_ROOT, szKey, TEXT("LocalServer32"), TEXT("ThreadingModel"), pszModel); } } } } if (SUCCEEDED(hres)) { // Add the server filename subkey under the CLSID key. if (fLocalService) { // Register as LocalServer hres = _RegSetKeyAndString(HKEY_CLASSES_ROOT, szKey, TEXT("LocalService"), NULL, pszLocalService); if (SUCCEEDED(hres)) { hres = _RegSetKeyAndString(HKEY_CLASSES_ROOT, szKey, TEXT("LocalService"), TEXT("ThreadingModel"), pszModel); } { // We had this bug for a while that a LocalServer32 key was // also installed // Delete it on upgrade (stephstm: Jun/02/2000) // Remove this code when nobody will upgrade from // builds earlier than 2242 WCHAR szKeyLocal[MAX_KEY]; SafeStrCpyN(szKeyLocal, szKey, ARRAYSIZE(szKeyLocal)); SafeStrCatN(szKeyLocal, TEXT("\\LocalServer32"), ARRAYSIZE(szKeyLocal)); _RecursiveDeleteKey(HKEY_CLASSES_ROOT, szKeyLocal); } } } if (SUCCEEDED(hres)) { // Add the ProgID subkey under the CLSID key. hres = _RegSetKeyAndString(HKEY_CLASSES_ROOT, szKey, TEXT("ProgID"), NULL, pszProgID); } if (SUCCEEDED(hres)) { // Add the version-independent ProgID subkey under CLSID // key. hres = _RegSetKeyAndString(HKEY_CLASSES_ROOT, szKey, TEXT("VersionIndependentProgID"), NULL, pszVerIndProgID); } if (SUCCEEDED(hres)) { hres = _RegSetKeyAndString(HKEY_CLASSES_ROOT, pszVerIndProgID, NULL, NULL, pszFriendlyName); } if (SUCCEEDED(hres)) { hres = _RegSetKeyAndString(HKEY_CLASSES_ROOT, pszVerIndProgID, TEXT("CLSID"), NULL, szCLSID); } if (SUCCEEDED(hres)) { hres = _RegSetKeyAndString(HKEY_CLASSES_ROOT, pszVerIndProgID, TEXT("CurVer"), NULL, pszProgID); } if (SUCCEEDED(hres)) { // Add the versioned ProgID subkey under HKEY_CLASSES_ROOT hres = _RegSetKeyAndString(HKEY_CLASSES_ROOT, pszProgID, NULL, NULL, pszFriendlyName); } if (SUCCEEDED(hres)) { // Add the versioned ProgID subkey under HKEY_CLASSES_ROOT hres = _RegSetKeyAndString(HKEY_CLASSES_ROOT, pszProgID, TEXT("CLSID"), NULL, szCLSID); } if (SUCCEEDED(hres)) { if (pclsidAppID) { // do the AppID. WCHAR szAppID[CLSID_STRING_SIZE]; hres = _StringFromGUID(pclsidAppID, szAppID, ARRAYSIZE(szAppID)); if (SUCCEEDED(hres)) { hres = _RegSetKeyAndString(HKEY_CLASSES_ROOT, szKey, NULL, TEXT("AppID"), szAppID); } RegisterAppID(pclsidAppID); } } } return hres; } // Remove the component from the registry. HRESULT UnregisterServer(REFCLSID rclsid, LPCWSTR pszVerIndProgID, LPCWSTR pszProgID) { WCHAR szCLSID[CLSID_STRING_SIZE]; WCHAR szKey[MAX_KEY] = TEXT("CLSID\\"); HRESULT hres = _StringFromGUID(&rclsid, szCLSID, ARRAYSIZE(szCLSID)); if (SUCCEEDED(hres)) { SafeStrCatN(szKey, szCLSID, ARRAYSIZE(szKey)); // Delete the CLSID Key - CLSID\{...} _RecursiveDeleteKey(HKEY_CLASSES_ROOT, szKey); // Delete the version-independent ProgID Key. _RecursiveDeleteKey(HKEY_CLASSES_ROOT, pszVerIndProgID); // Delete the ProgID key. _RecursiveDeleteKey(HKEY_CLASSES_ROOT, pszProgID); } return S_OK; } /////////////////////////////////////////////////////////////////////////////// // Internal helper functions // Delete a key and all of its descendents. LONG _RecursiveDeleteKey(HKEY hKeyParent, LPCWSTR pszKeyChild) { HKEY hkeyChild; LONG lRes = RegOpenKeyEx(hKeyParent, pszKeyChild, 0, KEY_ALL_ACCESS, &hkeyChild); if (ERROR_SUCCESS == lRes) { // Enumerate all of the decendents of this child. WCHAR szBuffer[MAX_PATH]; DWORD dwSize = ARRAYSIZE(szBuffer); while ((ERROR_SUCCESS == lRes) && (S_OK == RegEnumKeyEx(hkeyChild, 0, szBuffer, &dwSize, NULL, NULL, NULL, NULL))) { // Delete the decendents of this child. lRes = _RecursiveDeleteKey(hkeyChild, szBuffer); dwSize = ARRAYSIZE(szBuffer); } // Close the child. RegCloseKey(hkeyChild); } if (ERROR_SUCCESS == lRes) { // Delete this child. lRes = RegDeleteKey(hKeyParent, pszKeyChild); } return lRes; }