353 lines
11 KiB
C++
353 lines
11 KiB
C++
|
#include "regsvr.h"
|
||
|
|
||
|
#include "reg.h"
|
||
|
#include "str.h"
|
||
|
#include "sfstr.h"
|
||
|
|
||
|
#include "factdata.h"
|
||
|
|
||
|
#include <sddl.h>
|
||
|
|
||
|
|
||
|
#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;
|
||
|
}
|