285 lines
8.6 KiB
C++
285 lines
8.6 KiB
C++
/****************************************************************************
|
|
*
|
|
* REGISTRY.cpp
|
|
*
|
|
* Microsoft Confidential
|
|
* Copyright (c) Microsoft Corporation 1992-1997
|
|
* All rights reserved
|
|
*
|
|
* This module provides functionality for self-registering/unregistering via
|
|
* the regsvr32.exe
|
|
*
|
|
* The code comes almost verbatim from Chapter 7 of Dale Rogerson's
|
|
* "Inside COM", and thus is minimally commented.
|
|
*
|
|
* 05/14/98 donaldm copied from INETCFG
|
|
*
|
|
***************************************************************************/
|
|
|
|
#include "pre.h"
|
|
#include "registry.h"
|
|
|
|
////////////////////////////////////////////////////////
|
|
//
|
|
// Internal helper functions prototypes
|
|
//
|
|
BOOL setKeyAndValue(const LPTSTR pszPath,
|
|
const LPTSTR szSubkey,
|
|
const LPTSTR szValue,
|
|
const LPTSTR szName = NULL) ;
|
|
// Convert a CLSID into a tchar string.
|
|
void CLSIDtochar(const CLSID& clsid,
|
|
LPTSTR szCLSID,
|
|
int length) ;
|
|
|
|
// Delete szKeyChild and all of its descendents.
|
|
LONG recursiveDeleteKey(HKEY hKeyParent, const LPTSTR szKeyChild) ;
|
|
|
|
////////////////////////////////////////////////////////
|
|
//
|
|
// Constants
|
|
//
|
|
|
|
// Size of a CLSID as a string
|
|
const int CLSID_STRING_SIZE = 39 ;
|
|
|
|
/////////////////////////////////////////////////////////
|
|
//
|
|
// Public function implementation
|
|
//
|
|
|
|
//
|
|
// Register the component in the registry.
|
|
//
|
|
BOOL WINAPI RegisterServer(HMODULE hModule, // DLL module handle
|
|
const CLSID& clsid, // Class ID
|
|
const LPTSTR szFriendlyName, // Friendly Name
|
|
const LPTSTR szVerIndProgID, // Programmatic
|
|
const LPTSTR szProgID) // IDs
|
|
{
|
|
BOOL bRet = FALSE;
|
|
|
|
// Get server location.
|
|
TCHAR szModule[512] ;
|
|
DWORD dwResult =
|
|
::GetModuleFileName(hModule,
|
|
szModule,
|
|
sizeof(szModule)/sizeof(TCHAR)) ;
|
|
if (0 != dwResult )
|
|
{
|
|
|
|
while (1)
|
|
{
|
|
// Convert the CLSID into a TCHAR.
|
|
TCHAR szCLSID[CLSID_STRING_SIZE] ;
|
|
CLSIDtochar(clsid, szCLSID, sizeof(szCLSID)) ;
|
|
|
|
// Build the key CLSID\\{...}
|
|
TCHAR szKey[CLSID_STRING_SIZE + 10] ;
|
|
lstrcpy(szKey, TEXT("CLSID\\")) ;
|
|
lstrcat(szKey, szCLSID) ;
|
|
|
|
// Add the CLSID to the registry.
|
|
bRet = setKeyAndValue(szKey, NULL, szFriendlyName) ;
|
|
if (!bRet)
|
|
break;
|
|
|
|
// Add the server filename subkey under the CLSID key.
|
|
bRet = setKeyAndValue(szKey, TEXT("InprocServer32"), szModule) ;
|
|
if (!bRet)
|
|
break;
|
|
|
|
// 7/2/97 jmazner IE bug #41852
|
|
// Add Threading Model
|
|
bRet = setKeyAndValue(szKey,
|
|
TEXT("InprocServer32"),
|
|
TEXT("Apartment"),
|
|
TEXT("ThreadingModel")) ;
|
|
if (!bRet)
|
|
break;
|
|
|
|
// Add the ProgID subkey under the CLSID key.
|
|
bRet = setKeyAndValue(szKey, TEXT("ProgID"), szProgID) ;
|
|
if (!bRet)
|
|
break;
|
|
|
|
// Add the version-independent ProgID subkey under CLSID key.
|
|
bRet = setKeyAndValue(szKey, TEXT("VersionIndependentProgID"),
|
|
szVerIndProgID) ;
|
|
if (!bRet)
|
|
break;
|
|
|
|
// Add the version-independent ProgID subkey under HKEY_CLASSES_ROOT.
|
|
bRet = setKeyAndValue(szVerIndProgID, NULL, szFriendlyName) ;
|
|
if (!bRet)
|
|
break;
|
|
|
|
bRet = setKeyAndValue(szVerIndProgID, TEXT("CLSID"), szCLSID) ;
|
|
if (!bRet)
|
|
break;
|
|
|
|
bRet = setKeyAndValue(szVerIndProgID, TEXT("CurVer"), szProgID) ;
|
|
if (!bRet)
|
|
break;
|
|
|
|
// Add the versioned ProgID subkey under HKEY_CLASSES_ROOT.
|
|
bRet = setKeyAndValue(szProgID, NULL, szFriendlyName) ;
|
|
if (!bRet)
|
|
break;
|
|
|
|
bRet = setKeyAndValue(szProgID, TEXT("CLSID"), szCLSID) ;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return bRet ;
|
|
}
|
|
|
|
//
|
|
// Remove the component from the registry.
|
|
//
|
|
BOOL WINAPI UnregisterServer(const CLSID& clsid, // Class ID
|
|
const LPTSTR szVerIndProgID, // Programmatic
|
|
const LPTSTR szProgID) // IDs
|
|
{
|
|
// Convert the CLSID into a TCHAR.
|
|
TCHAR szCLSID[CLSID_STRING_SIZE] ;
|
|
CLSIDtochar(clsid, szCLSID, sizeof(szCLSID)) ;
|
|
|
|
// Build the key CLSID\\{...}
|
|
TCHAR szKey[64] ;
|
|
lstrcpy(szKey, TEXT("CLSID\\")) ;
|
|
lstrcat(szKey, szCLSID) ;
|
|
|
|
// Delete the CLSID Key - CLSID\{...}
|
|
LONG lResult = recursiveDeleteKey(HKEY_CLASSES_ROOT, szKey) ;
|
|
ASSERT((lResult == ERROR_SUCCESS) ||
|
|
(lResult == ERROR_FILE_NOT_FOUND)) ; // Subkey may not exist.
|
|
|
|
// Delete the version-independent ProgID Key.
|
|
lResult = recursiveDeleteKey(HKEY_CLASSES_ROOT, szVerIndProgID) ;
|
|
ASSERT((lResult == ERROR_SUCCESS) ||
|
|
(lResult == ERROR_FILE_NOT_FOUND)) ; // Subkey may not exist.
|
|
|
|
// Delete the ProgID key.
|
|
lResult = recursiveDeleteKey(HKEY_CLASSES_ROOT, szProgID) ;
|
|
ASSERT((lResult == ERROR_SUCCESS) ||
|
|
(lResult == ERROR_FILE_NOT_FOUND)) ; // Subkey may not exist.
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
//
|
|
// Internal helper functions
|
|
//
|
|
|
|
// Convert a CLSID to a TCHAR string.
|
|
void CLSIDtochar(const CLSID& clsid,
|
|
LPTSTR szCLSID,
|
|
int length)
|
|
{
|
|
ASSERT(length >= CLSID_STRING_SIZE) ;
|
|
// Get CLSID
|
|
LPOLESTR wszCLSID = NULL ;
|
|
HRESULT hr = StringFromCLSID(clsid, &wszCLSID) ;
|
|
ASSERT(SUCCEEDED(hr)) ;
|
|
|
|
// Covert from wide characters to non-wide.
|
|
#ifdef UNICODE
|
|
lstrcpyn(szCLSID, wszCLSID, length / sizeof(WCHAR)) ;
|
|
#else
|
|
wcstombs(szCLSID, wszCLSID, length) ;
|
|
#endif
|
|
|
|
// Free memory.
|
|
CoTaskMemFree(wszCLSID) ;
|
|
}
|
|
|
|
//
|
|
// Delete a key and all of its descendents.
|
|
//
|
|
LONG recursiveDeleteKey(HKEY hKeyParent, // Parent of key to delete
|
|
const LPTSTR lpszKeyChild) // Key to delete
|
|
{
|
|
// Open the child.
|
|
HKEY hKeyChild ;
|
|
LONG lRes = RegOpenKeyEx(hKeyParent, lpszKeyChild, 0,
|
|
KEY_ALL_ACCESS, &hKeyChild) ;
|
|
if (lRes != ERROR_SUCCESS)
|
|
{
|
|
return lRes ;
|
|
}
|
|
|
|
// Enumerate all of the decendents of this child.
|
|
FILETIME time ;
|
|
TCHAR szBuffer[256] ;
|
|
DWORD dwSize = 256 ;
|
|
while (RegEnumKeyEx(hKeyChild, 0, szBuffer, &dwSize, NULL,
|
|
NULL, NULL, &time) == S_OK)
|
|
{
|
|
// Delete the decendents of this child.
|
|
lRes = recursiveDeleteKey(hKeyChild, szBuffer) ;
|
|
if (lRes != ERROR_SUCCESS)
|
|
{
|
|
// Cleanup before exiting.
|
|
RegCloseKey(hKeyChild) ;
|
|
return lRes;
|
|
}
|
|
dwSize = 256 ;
|
|
}
|
|
|
|
// Close the child.
|
|
RegCloseKey(hKeyChild) ;
|
|
|
|
// Delete this child.
|
|
return RegDeleteKey(hKeyParent, lpszKeyChild) ;
|
|
}
|
|
|
|
//
|
|
// Create a key and set its value.
|
|
// - This helper function was borrowed and modifed from
|
|
// Kraig Brockschmidt's book Inside OLE.
|
|
//
|
|
BOOL setKeyAndValue(const LPTSTR szKey,
|
|
const LPTSTR szSubkey,
|
|
const LPTSTR szValue,
|
|
const LPTSTR szName)
|
|
{
|
|
HKEY hKey;
|
|
TCHAR szKeyBuf[1024] ;
|
|
|
|
// Copy keyname into buffer.
|
|
lstrcpy(szKeyBuf, szKey) ;
|
|
|
|
// Add subkey name to buffer.
|
|
if (szSubkey != NULL)
|
|
{
|
|
lstrcat(szKeyBuf, TEXT("\\")) ;
|
|
lstrcat(szKeyBuf, szSubkey ) ;
|
|
}
|
|
|
|
// Create and open key and subkey.
|
|
long lResult = RegCreateKeyEx(HKEY_CLASSES_ROOT ,
|
|
szKeyBuf,
|
|
0, NULL, REG_OPTION_NON_VOLATILE,
|
|
KEY_ALL_ACCESS, NULL,
|
|
&hKey, NULL) ;
|
|
if (lResult != ERROR_SUCCESS)
|
|
{
|
|
return FALSE ;
|
|
}
|
|
|
|
// Set the Value.
|
|
if (szValue != NULL)
|
|
{
|
|
RegSetValueEx(hKey, szName, 0, REG_SZ,
|
|
(BYTE *)szValue,
|
|
sizeof(TCHAR)*(lstrlen(szValue)+1)) ;
|
|
}
|
|
|
|
RegCloseKey(hKey) ;
|
|
return TRUE ;
|
|
}
|
|
|