mirror of https://github.com/lianthony/NT4.0
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.
1448 lines
41 KiB
1448 lines
41 KiB
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1992 - 1993.
|
|
//
|
|
// File: init.cxx
|
|
//
|
|
// Contents: functions to load cache from registry
|
|
//
|
|
// Functions: HexStringToDword
|
|
// GUIDFromString
|
|
// get_reg_value
|
|
// LoadClassCache
|
|
//
|
|
// History: 22-Apr-93 Ricksa Created
|
|
// 31-Dec-93 ErikGav Chicago port
|
|
// 03-Jan-95 BillMo Added impl for StringFromGUID2 so
|
|
// we don't link to ole32.dll
|
|
// 11-Sep-95 MurthyS Removed StringFromGUID2...use from
|
|
// common.lib instead
|
|
// 07-Dec-95 BruceMa Add RunAs support
|
|
// 12-Jan-96 BruceMa Add per-user registry support
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
#include <headers.cxx>
|
|
#pragma hdrstop
|
|
|
|
#include <scm.hxx>
|
|
#include "port.hxx"
|
|
#include <scm.h>
|
|
#include "cls.hxx"
|
|
#include "compname.hxx"
|
|
#include "init.hxx"
|
|
extern "C"
|
|
{
|
|
#include <userenv.h>
|
|
}
|
|
|
|
//
|
|
// global keys that are opened during initialization
|
|
//
|
|
|
|
HKEY g_hkClsID = 0;
|
|
HKEY g_hkAppID = 0;
|
|
|
|
extern WCHAR wszSOFTWAREClassesCLSID[1];
|
|
WCHAR wszLocalServer16[] = L"LocalServer";
|
|
static WCHAR wszLocalServer[] = L"LocalServer32";
|
|
static WCHAR wszService[] = L"LocalService";
|
|
static WCHAR wszRunAs[] = L"RunAs";
|
|
static WCHAR wszShared[] = L"Shared";
|
|
static WCHAR wszAppIDName[] = L"AppID";
|
|
|
|
extern WCHAR wszInProcServer[] = L"InProcServer32";
|
|
|
|
//
|
|
// Threading Model Registry Constants
|
|
//
|
|
|
|
static TCHAR tszDllThreadModel[] = TEXT("ThreadingModel");
|
|
static TCHAR tszAptModel[] = TEXT("Apartment");
|
|
static TCHAR tszBothModel[] = TEXT("Both");
|
|
static TCHAR wszFreeModel[] = TEXT("Free");
|
|
|
|
WCHAR wszActivateAtStorage[] = L"ActivateAtStorage";
|
|
WCHAR wszRemoteServerName[] = L"RemoteServerName";
|
|
WCHAR wszErrorControl[] = L"ErrorControl";
|
|
WCHAR wszServiceParameters[] = L"ServiceParameters";
|
|
WCHAR wszLaunchPermission[] = L"LaunchPermission";
|
|
WCHAR wszServicesKey[] = L"SYSTEM\\CurrentControlSet\\Services";
|
|
|
|
TCHAR tszOLE2[] = TEXT("SOFTWARE\\Microsoft\\OLE2");
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Function: GetRegistrySecDesc, internal
|
|
//
|
|
// Synopsis: Convert a security descriptor from self relative to
|
|
// absolute form. Stuff in an owner and a group.
|
|
//
|
|
// Notes: REGDB_E_INVALIDVALUE is returned when there is something
|
|
// at the specified value, but it is not a security descriptor.
|
|
//
|
|
// This is ALMOST the same as the routine by the same name in com\dcomrem,
|
|
// but it uses ScmMemAlloc instead of PrivMemAlloc
|
|
//
|
|
//--------------------------------------------------------------------
|
|
HRESULT GetRegistrySecDesc( HKEY hKey, WCHAR *pValue,
|
|
SECURITY_DESCRIPTOR **pSD )
|
|
|
|
{
|
|
SID *pGroup;
|
|
SID *pOwner;
|
|
DWORD cbSD;
|
|
DWORD lType;
|
|
HRESULT hr;
|
|
|
|
// Find put how much memory to allocate for the security
|
|
// descriptor.
|
|
cbSD = 0;
|
|
*pSD = NULL;
|
|
hr = RegQueryValueEx( hKey, pValue, NULL, &lType, NULL, &cbSD );
|
|
if (hr != ERROR_SUCCESS)
|
|
return MAKE_SCODE( SEVERITY_ERROR, FACILITY_WIN32, hr );
|
|
if (lType != REG_BINARY || cbSD < sizeof(SECURITY_DESCRIPTOR))
|
|
return REGDB_E_INVALIDVALUE;
|
|
|
|
// Allocate memory for the security descriptor plus the owner and
|
|
// group SIDs.
|
|
*pSD = (SECURITY_DESCRIPTOR *) ScmMemAlloc( cbSD );
|
|
if (*pSD == NULL)
|
|
return E_OUTOFMEMORY;
|
|
|
|
// Read the security descriptor.
|
|
hr = RegQueryValueEx( hKey, pValue, NULL, &lType, (unsigned char *) *pSD,
|
|
&cbSD );
|
|
if (hr != ERROR_SUCCESS)
|
|
return MAKE_SCODE( SEVERITY_ERROR, FACILITY_WIN32, hr );
|
|
if (lType != REG_BINARY)
|
|
return REGDB_E_INVALIDVALUE;
|
|
|
|
// Fix up the security descriptor.
|
|
(*pSD)->Control &= ~SE_SELF_RELATIVE;
|
|
(*pSD)->Sacl = NULL;
|
|
if ((*pSD)->Dacl != NULL)
|
|
{
|
|
if (cbSD < sizeof(ACL) + sizeof(SECURITY_DESCRIPTOR) ||
|
|
(ULONG) (*pSD)->Dacl > cbSD - sizeof(ACL))
|
|
return REGDB_E_INVALIDVALUE;
|
|
(*pSD)->Dacl = (ACL *) (((char *) *pSD) + ((ULONG) (*pSD)->Dacl));
|
|
if ((*pSD)->Dacl->AclSize + sizeof(SECURITY_DESCRIPTOR) > cbSD)
|
|
return REGDB_E_INVALIDVALUE;
|
|
}
|
|
|
|
// Set up the owner and group SIDs.
|
|
if ((*pSD)->Group == 0 || ((ULONG) (*pSD)->Group) + sizeof(SID) > cbSD ||
|
|
(*pSD)->Owner == 0 || ((ULONG) (*pSD)->Owner) + sizeof(SID) > cbSD)
|
|
return REGDB_E_INVALIDVALUE;
|
|
(*pSD)->Group = (SID *) (((BYTE *) *pSD) + (ULONG) (*pSD)->Group);
|
|
(*pSD)->Owner = (SID *) (((BYTE *) *pSD) + (ULONG) (*pSD)->Owner);
|
|
|
|
// Check the security descriptor.
|
|
#if DBG==1
|
|
if (!IsValidSecurityDescriptor( *pSD ))
|
|
return REGDB_E_INVALIDVALUE;
|
|
#endif
|
|
return S_OK;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: HexStringToDword
|
|
//
|
|
// Synopsis: Convert a character string hex digits to a DWORD
|
|
//
|
|
// Arguments: [lpsz] - string to convert
|
|
// [Value] - where to put the value
|
|
// [cDigits] - number of digits expected
|
|
// [chDelim] - delimiter for end of string
|
|
//
|
|
// Returns: TRUE - string converted to a DWORD
|
|
// FALSE - string could not be converted
|
|
//
|
|
// Algorithm: For each digit in the string, shift the value and
|
|
// add the value of the digit to the output value. When
|
|
// all the digits are processed, if a delimiter is
|
|
// provided, make sure the last character is the delimiter.
|
|
//
|
|
// History: 22-Apr-93 Ricksa Created
|
|
//
|
|
// Notes: Lifted from CairOLE sources so that SCM will have no
|
|
// dependency on compobj.dll.
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
#if !defined(_CHICAGO_)
|
|
BOOL HexStringToDword(
|
|
LPCWSTR FAR& lpsz,
|
|
DWORD FAR& Value,
|
|
int cDigits,
|
|
WCHAR chDelim)
|
|
{
|
|
int Count;
|
|
|
|
Value = 0;
|
|
|
|
for (Count = 0; Count < cDigits; Count++, lpsz++)
|
|
{
|
|
if (*lpsz >= '0' && *lpsz <= '9')
|
|
{
|
|
Value = (Value << 4) + *lpsz - '0';
|
|
}
|
|
else if (*lpsz >= 'A' && *lpsz <= 'F')
|
|
{
|
|
Value = (Value << 4) + *lpsz - 'A' + 10;
|
|
}
|
|
else if (*lpsz >= 'a' && *lpsz <= 'f')
|
|
{
|
|
Value = (Value << 4) + *lpsz - 'a' + 10;
|
|
}
|
|
else
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
if (chDelim != 0)
|
|
{
|
|
return *lpsz++ == chDelim;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
#endif
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: GUIDFromString
|
|
//
|
|
// Synopsis: Convert a string in Registry to a GUID.
|
|
//
|
|
// Arguments: [lpsz] - string from registry
|
|
// [pguid] - where to put the guid.
|
|
//
|
|
// Returns: TRUE - GUID conversion successful
|
|
// FALSE - GUID conversion failed.
|
|
//
|
|
// Algorithm: Convert each part of the GUID string to the
|
|
// appropriate structure member in the guid using
|
|
// HexStringToDword. If all conversions work return
|
|
// TRUE.
|
|
//
|
|
// History: 22-Apr-93 Ricksa Created
|
|
//
|
|
// Notes: Lifted from CairOLE sources so that SCM will have no
|
|
// dependency on compobj.dll.
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
#if !defined(_CHICAGO_)
|
|
BOOL GUIDFromString(LPCWSTR lpsz, LPGUID pguid)
|
|
{
|
|
DWORD dw;
|
|
|
|
if (*lpsz++ != '{')
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if (!HexStringToDword(lpsz, pguid->Data1, sizeof(DWORD)*2, '-'))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if (!HexStringToDword(lpsz, dw, sizeof(WORD)*2, '-'))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
pguid->Data2 = (WORD)dw;
|
|
|
|
if (!HexStringToDword(lpsz, dw, sizeof(WORD)*2, '-'))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
pguid->Data3 = (WORD)dw;
|
|
|
|
if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
pguid->Data4[0] = (BYTE)dw;
|
|
|
|
if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, '-'))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
pguid->Data4[1] = (BYTE)dw;
|
|
|
|
if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
pguid->Data4[2] = (BYTE)dw;
|
|
|
|
if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
pguid->Data4[3] = (BYTE)dw;
|
|
|
|
if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
pguid->Data4[4] = (BYTE)dw;
|
|
|
|
if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
pguid->Data4[5] = (BYTE)dw;
|
|
|
|
if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
pguid->Data4[6] = (BYTE)dw;
|
|
|
|
if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, /*(*/ '}'))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
pguid->Data4[7] = (BYTE)dw;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
#endif
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAppIDData::CAppIDData
|
|
//
|
|
// Synopsis: init.
|
|
//
|
|
//
|
|
//--------------------------------------------------------------------
|
|
CAppIDData::CAppIDData()
|
|
{
|
|
dwSaveErr = 0;
|
|
|
|
pwszRemoteServerName = NULL;
|
|
|
|
pSD = NULL;
|
|
|
|
fHasService = FALSE;
|
|
pwszLocalService = NULL;
|
|
pwszServiceArgs = NULL;
|
|
pwszRunAsUserName = NULL;
|
|
pwszRunAsDomainName = NULL;
|
|
|
|
fHasRemoteServerName = 0;
|
|
fHasService = FALSE;
|
|
fActivateAtStorage = FALSE;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CClassRegistryReader::~CClassRegistryReader
|
|
//
|
|
// Synopsis: Close the registry at root of all classes and
|
|
// free stuff.
|
|
//
|
|
//--------------------------------------------------------------------
|
|
CAppIDData::~CAppIDData()
|
|
{
|
|
//
|
|
// All allocated data is inherited by CClassData and thereafter owned
|
|
// and later freed by the CClassData class. Upon failure of the
|
|
// CClassData constructor, the CAppIDData::Cleanup method is called to
|
|
// free allocated data.
|
|
//
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAppIDData::Cleanup
|
|
//
|
|
// Synopsis: Free allocated data. Should be called only if CClassData new
|
|
// fails.
|
|
//
|
|
//
|
|
//--------------------------------------------------------------------
|
|
void
|
|
CAppIDData::Cleanup()
|
|
{
|
|
if ( pwszRemoteServerName )
|
|
{
|
|
ScmMemFree( pwszRemoteServerName );
|
|
pwszRemoteServerName = 0;
|
|
}
|
|
if ( pwszLocalService )
|
|
{
|
|
ScmMemFree( pwszLocalService );
|
|
pwszLocalService = 0;
|
|
}
|
|
if ( pwszServiceArgs )
|
|
{
|
|
ScmMemFree( pwszServiceArgs );
|
|
pwszServiceArgs = 0;
|
|
}
|
|
if ( pwszRunAsUserName )
|
|
{
|
|
ScmMemFree( pwszRunAsUserName );
|
|
pwszRunAsUserName = 0;
|
|
}
|
|
if ( pwszRunAsDomainName )
|
|
{
|
|
ScmMemFree( pwszRunAsDomainName );
|
|
pwszRunAsDomainName = 0;
|
|
}
|
|
if ( pSD )
|
|
{
|
|
ScmMemFree( pSD );
|
|
pSD = 0;
|
|
}
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CClassRegistryReader::CClassRegistryReader
|
|
//
|
|
// Synopsis: Open the registry at root of all classes and init.
|
|
//
|
|
// Notes: Sets errClsReg with result of RegOpenKeyEx.
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
CClassRegistryReader::CClassRegistryReader()
|
|
{
|
|
cName = sizeof(awName);
|
|
iSubKey = 0;
|
|
dwSaveErr = 0;
|
|
#ifdef DCOM
|
|
// NT 5.0 _fShared = TRUE;
|
|
#endif // DCOM
|
|
pwszLocalServer = awcsLocalServer;
|
|
lLocalServer = sizeof(awcsLocalServer);
|
|
pwszAppID = awcsAppID;
|
|
lAppID = sizeof(awcsAppID);
|
|
pAppIDData = NULL;
|
|
|
|
#ifdef _CHICAGO_
|
|
errClsReg = RegOpenKeyExA(HKEY_CLASSES_ROOT, tszCLSID , NULL, KEY_READ, &hClsReg);
|
|
#endif //_CHICAGO_
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CClassRegistryReader::~CClassRegistryReader
|
|
//
|
|
// Synopsis: Close the registry at root of all classes and
|
|
// free stuff.
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
CClassRegistryReader::~CClassRegistryReader()
|
|
{
|
|
#ifdef _CHICAGO_
|
|
if (errClsReg == ERROR_SUCCESS)
|
|
RegCloseKey(hClsReg);
|
|
#endif
|
|
|
|
if (pwszLocalServer != awcsLocalServer)
|
|
{
|
|
ScmMemFree(pwszLocalServer);
|
|
}
|
|
|
|
if ( pAppIDData )
|
|
{
|
|
delete pAppIDData;
|
|
}
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CClassRegistryReader::InitInner
|
|
//
|
|
// Synopsis: Reinitialize the variables used by the loop in
|
|
// LoadClassCache.
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
void
|
|
CClassRegistryReader::InitInner(void)
|
|
{
|
|
lDebug = sizeof(awcsDebug);
|
|
fHasLocalServer = 0;
|
|
f16Bit = FALSE;
|
|
}
|
|
|
|
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: QueryStripRegValue
|
|
//
|
|
// Synopsis: Get the DLL information for a 32 bit DLL and
|
|
// strip off any leading and trailing "
|
|
//
|
|
// Arguments: [hkey] - class handle
|
|
// [pwszSubKey] - key to open
|
|
// [pwszValue] - where to return data
|
|
// [pcbValue] - length of above buffer in bytes
|
|
//
|
|
// Returns: ERROR_SUCCESS - read DLL path information
|
|
// Other - registry entries could not be found
|
|
//
|
|
// Algorithm: Read the value requested.
|
|
// If first character is not ", exit
|
|
// Otherwise, copy data after quote to beginning of buffer.
|
|
//
|
|
//
|
|
// History: 05-Jan-94 BillMo Created
|
|
// 26-Sep-95 BruceMa Support environment variable expansion
|
|
// for shell viewers
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
LONG
|
|
QueryStripRegValue(HKEY hkey, // handle of key to query
|
|
LPCWSTR pwszSubKey, // address of name of subkey to query
|
|
LPWSTR pwszValue, // address of buffer for returned string
|
|
PLONG pcbValue) // address of buffer for size of returned string
|
|
{
|
|
HKEY hSubKey;
|
|
DWORD dwType;
|
|
LONG lErr;
|
|
|
|
Win4Assert(pwszValue != NULL);
|
|
Win4Assert(pcbValue != NULL);
|
|
|
|
// Open the subkey
|
|
lErr = RegOpenKeyEx(hkey, pwszSubKey, NULL, KEY_READ, &hSubKey);
|
|
|
|
// Read the value into the user's buffer
|
|
if (lErr == ERROR_SUCCESS)
|
|
{
|
|
lErr = RegQueryValueEx(hSubKey, NULL , NULL, &dwType,
|
|
(BYTE *) pwszValue, (ULONG *) pcbValue);
|
|
if (lErr == ERROR_SUCCESS)
|
|
{
|
|
WCHAR *pwszScan = pwszValue; // used to scan along string
|
|
WCHAR *pwszDest = pwszValue; // used as destination when copying
|
|
|
|
// if the name is quoted then ...
|
|
if (*pwszScan == L'\"')
|
|
{
|
|
pwszScan++;
|
|
|
|
// copy all non-quote characters down to base of buffer
|
|
// until end of quoted string
|
|
while (*pwszScan != L'\0' && *pwszScan != L'\"')
|
|
{
|
|
*pwszDest++ = *pwszScan++;
|
|
}
|
|
|
|
// terminate string and get length in bytes including nul
|
|
*pwszDest++ = L'\0';
|
|
*pcbValue = (pwszDest - pwszValue) * sizeof(WCHAR);
|
|
}
|
|
|
|
// find first non-white space character
|
|
pwszScan = pwszValue;
|
|
while (*pwszScan) {
|
|
USHORT CharType[1];
|
|
|
|
GetStringTypeW (CT_CTYPE1, pwszScan, 1, CharType);
|
|
if ((CharType[0] & C1_SPACE) == 0) {
|
|
break;
|
|
}
|
|
pwszScan++;
|
|
}
|
|
|
|
// if there are no non-white space characters this will be true
|
|
if (*pwszScan == L'\0')
|
|
{
|
|
lErr = ERROR_FILE_NOT_FOUND;
|
|
*pcbValue = 0;
|
|
}
|
|
|
|
// Chicago does not support ExpandEnvironmentStrings
|
|
#ifndef _CHICAGO_
|
|
// If the value type is REG_EXPAND_SZ then do environment variable
|
|
// expansion
|
|
if (dwType == REG_EXPAND_SZ)
|
|
{
|
|
// Expand any embedded environemnt variable expressions
|
|
WCHAR wszTemp[MAX_PATH];
|
|
|
|
lstrcpyW(wszTemp, pwszValue);
|
|
*pcbValue = ExpandEnvironmentStrings(wszTemp, pwszValue,
|
|
MAX_PATH);
|
|
}
|
|
#endif // !_CHICAGO_
|
|
}
|
|
|
|
RegCloseKey(hSubKey);
|
|
}
|
|
return lErr;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: QueryStripRegNamedValue
|
|
//
|
|
// Synopsis: Get the DLL information for a 32 bit DLL and
|
|
// strip off any leading and trailing "
|
|
//
|
|
// Arguments: [hkey] - class handle
|
|
// [pwszSubKey] - named value to open
|
|
// [pwszValue] - where to return data
|
|
// [pcbValue] - length of above buffer in bytes
|
|
//
|
|
// Returns: ERROR_SUCCESS - read DLL path information
|
|
// Other - registry entries could not be found
|
|
//
|
|
// Algorithm: Read the value requested.
|
|
// If first character is not ", exit
|
|
// Otherwise, copy data after quote to beginning of buffer.
|
|
//
|
|
//
|
|
// History: 05-Jan-94 BillMo Created
|
|
// 26-Sep-95 BruceMa Support environment variable expansion
|
|
// for shell viewers
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
LONG
|
|
QueryStripRegNamedValue(HKEY hkey, // handle of key to query
|
|
LPCWSTR pwszSubKey, // address of name of value to query
|
|
LPWSTR pwszValue, // address of buffer for returned string
|
|
PLONG pcbValue,
|
|
BOOL* pfValueRead) // whether or not a value was read ) // address of buffer for size of returned string
|
|
{
|
|
DWORD dwType;
|
|
LONG lErr;
|
|
|
|
Win4Assert(pwszValue != NULL);
|
|
Win4Assert(pcbValue != NULL);
|
|
|
|
// Read the value into the user's buffer
|
|
lErr = RegQueryValueEx(hkey, pwszSubKey , NULL, &dwType,
|
|
(BYTE *) pwszValue, (ULONG *) pcbValue);
|
|
if (*pfValueRead =(lErr == ERROR_SUCCESS))
|
|
{
|
|
WCHAR *pwszScan = pwszValue; // used to scan along string
|
|
WCHAR *pwszDest = pwszValue; // used as destination when copying
|
|
|
|
// if the name is quoted then ...
|
|
if (*pwszScan == L'\"')
|
|
{
|
|
pwszScan++;
|
|
|
|
// copy all non-quote characters down to base of buffer
|
|
// until end of quoted string
|
|
while (*pwszScan != L'\0' && *pwszScan != L'\"')
|
|
{
|
|
*pwszDest++ = *pwszScan++;
|
|
}
|
|
|
|
// terminate string and get length in bytes including nul
|
|
*pwszDest++ = L'\0';
|
|
*pcbValue = (pwszDest - pwszValue) * sizeof(WCHAR);
|
|
}
|
|
|
|
// find first non-white space character
|
|
pwszScan = pwszValue;
|
|
while (*pwszScan) {
|
|
USHORT CharType[1];
|
|
|
|
GetStringTypeW (CT_CTYPE1, pwszScan, 1, CharType);
|
|
if ((CharType[0] & C1_SPACE) == 0) {
|
|
break;
|
|
}
|
|
pwszScan++;
|
|
}
|
|
|
|
// if there are no non-white space characters this will be true
|
|
if (*pwszScan == L'\0')
|
|
{
|
|
lErr = ERROR_FILE_NOT_FOUND;
|
|
*pcbValue = 0;
|
|
}
|
|
|
|
// Chicago does not support ExpandEnvironmentStrings
|
|
#ifndef _CHICAGO_
|
|
// If the value type is REG_EXPAND_SZ then do environment variable
|
|
// expansion
|
|
if (dwType == REG_EXPAND_SZ)
|
|
{
|
|
// Expand any embedded environemnt variable expressions
|
|
WCHAR wszTemp[MAX_PATH];
|
|
|
|
lstrcpyW(wszTemp, pwszValue);
|
|
*pcbValue = ExpandEnvironmentStrings(wszTemp, pwszValue,
|
|
MAX_PATH);
|
|
}
|
|
#endif // !_CHICAGO_
|
|
}
|
|
|
|
return lErr;
|
|
}
|
|
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAppIDData::ReadEntries
|
|
//
|
|
// Synopsis: Set the state of this object by reading the
|
|
// registry entry given by contents of awName.
|
|
//
|
|
//--------------------------------------------------------------------
|
|
LONG
|
|
CAppIDData::ReadEntries( LPOLESTR pwszAppID )
|
|
{
|
|
HKEY hkThisAppID;
|
|
WCHAR wszYN[16];
|
|
WCHAR wszRemoteServer[MAX_COMPUTERNAME_LENGTH+1];
|
|
LONG lSize;
|
|
LONG lRemoteServerName;
|
|
DWORD dwType;
|
|
|
|
// first get open the correct AppID key
|
|
err = RegOpenKeyEx( g_hkAppID,
|
|
pwszAppID,
|
|
0,
|
|
KEY_READ,
|
|
&hkThisAppID );
|
|
|
|
if ( err != ERROR_SUCCESS )
|
|
{
|
|
dwSaveErr = err;
|
|
return err;
|
|
}
|
|
|
|
// Look for the "RunAs" key
|
|
WCHAR wszDomainUser[256];
|
|
ULONG dwSize = sizeof( wszDomainUser );
|
|
UINT cCh;
|
|
BOOL fReadValue;
|
|
|
|
if (RegQueryValueEx(hkThisAppID,
|
|
wszRunAs,
|
|
NULL,
|
|
NULL,
|
|
(LPBYTE)wszDomainUser,
|
|
&dwSize)
|
|
== ERROR_SUCCESS)
|
|
{
|
|
// Parse the domain
|
|
for (cCh = 0;
|
|
wszDomainUser[cCh] && wszDomainUser[cCh] != L'\\';
|
|
cCh++)
|
|
{
|
|
}
|
|
|
|
// If no domain specified, use the computer name
|
|
if (wszDomainUser[cCh] == L'\0')
|
|
{
|
|
CComputerName compName;
|
|
|
|
cCh = lstrlenW(compName.GetComputerName()) + 1;
|
|
pwszRunAsDomainName = (WCHAR *) ScmMemAlloc(cCh
|
|
* sizeof(WCHAR));
|
|
if (pwszRunAsDomainName == NULL)
|
|
{
|
|
err = E_OUTOFMEMORY;
|
|
goto cleanup_and_exit;
|
|
}
|
|
memcpy(pwszRunAsDomainName, compName.GetComputerName(),
|
|
cCh * sizeof(WCHAR));
|
|
cCh = 0;
|
|
}
|
|
|
|
// Else save the specified domain
|
|
else
|
|
{
|
|
pwszRunAsDomainName = (WCHAR *) ScmMemAlloc((cCh + 1)
|
|
* sizeof(WCHAR));
|
|
if (pwszRunAsDomainName == NULL)
|
|
{
|
|
err = E_OUTOFMEMORY;
|
|
goto cleanup_and_exit;
|
|
}
|
|
wszDomainUser[cCh++] = L'\0';
|
|
memcpy(pwszRunAsDomainName, wszDomainUser, 2 * cCh);
|
|
}
|
|
|
|
// Check for user name.
|
|
if ( (dwSize / 2) - cCh > 1 )
|
|
{
|
|
pwszRunAsUserName = (WCHAR *) ScmMemAlloc((dwSize/2 - cCh)
|
|
* sizeof(WCHAR));
|
|
if (pwszRunAsUserName == NULL)
|
|
{
|
|
err = E_OUTOFMEMORY;
|
|
goto cleanup_and_exit;
|
|
}
|
|
memcpy(pwszRunAsUserName, &wszDomainUser[cCh], dwSize - 2 * cCh);
|
|
}
|
|
else
|
|
{
|
|
ScmMemFree(pwszRunAsDomainName);
|
|
pwszRunAsDomainName = 0;
|
|
}
|
|
}
|
|
|
|
lSize = sizeof(wszYN);
|
|
err = QueryStripRegNamedValue(
|
|
hkThisAppID,
|
|
wszActivateAtStorage,
|
|
wszYN,
|
|
&lSize,
|
|
&fReadValue);
|
|
|
|
if ( (err == ERROR_SUCCESS) &&
|
|
((wszYN[0] == 'Y') || (wszYN[0] == 'y')) )
|
|
{
|
|
fActivateAtStorage = TRUE;
|
|
}
|
|
|
|
lRemoteServerName = sizeof(wszRemoteServer);
|
|
|
|
err = QueryStripRegNamedValue(
|
|
hkThisAppID,
|
|
wszRemoteServerName,
|
|
wszRemoteServer,
|
|
&lRemoteServerName,
|
|
&fReadValue);
|
|
|
|
if (err == ERROR_SUCCESS)
|
|
{
|
|
fHasRemoteServerName = TRUE;
|
|
pwszRemoteServerName = (WCHAR *)ScmMemAlloc((lstrlenW(wszRemoteServer)+1)*sizeof(WCHAR));
|
|
lstrcpyW( pwszRemoteServerName, wszRemoteServer );
|
|
}
|
|
else if (err == ERROR_MORE_DATA)
|
|
{
|
|
pwszRemoteServerName = (WCHAR *)ScmMemAlloc(lRemoteServerName);
|
|
if (pwszRemoteServerName == NULL)
|
|
{
|
|
err =(ERROR_NOT_ENOUGH_MEMORY);
|
|
goto cleanup_and_exit;
|
|
}
|
|
|
|
err = QueryStripRegNamedValue(
|
|
hkThisAppID,
|
|
wszRemoteServerName,
|
|
pwszRemoteServerName,
|
|
&lRemoteServerName,
|
|
&fReadValue);
|
|
|
|
if (err != ERROR_SUCCESS)
|
|
{
|
|
CairoleDebugOut((DEB_IWARN, "Unexpected error from RegQueryValue: (local server 32) %x, %d\n", err, __LINE__));
|
|
dwSaveErr = err;
|
|
}
|
|
else
|
|
{
|
|
fHasRemoteServerName = TRUE;
|
|
}
|
|
}
|
|
|
|
// Now look for "Service" registrations
|
|
HKEY hService;
|
|
WCHAR wszServiceName[MAX_PATH];
|
|
DWORD dwErrCtrl;
|
|
|
|
// Check for a "Service" named value
|
|
lSize = MAX_PATH;
|
|
if ((err = QueryStripRegNamedValue(hkThisAppID, wszService, wszServiceName,
|
|
&lSize,&fReadValue)) == ERROR_SUCCESS)
|
|
{
|
|
// Validate the existence of this service before overriding any
|
|
// LocalServer32 name
|
|
HKEY hServicesKey;
|
|
HKEY hServiceKey;
|
|
|
|
if ((err = RegOpenKeyEx(HKEY_LOCAL_MACHINE, wszServicesKey,
|
|
0, KEY_READ, &hServicesKey)) == ERROR_SUCCESS)
|
|
{
|
|
if ((err = RegOpenKeyEx(hServicesKey, wszServiceName,
|
|
0, KEY_READ, &hServiceKey)) == ERROR_SUCCESS)
|
|
{
|
|
lSize = sizeof(DWORD);
|
|
if ((err = RegQueryValueEx(hServiceKey, wszErrorControl, NULL,
|
|
&dwType, (BYTE *) &dwErrCtrl,
|
|
(ULONG *) &lSize)) == ERROR_SUCCESS)
|
|
{
|
|
// We have a valid, accessible service
|
|
fHasService = TRUE;
|
|
}
|
|
RegCloseKey(hServiceKey);
|
|
}
|
|
RegCloseKey(hServicesKey);
|
|
}
|
|
|
|
// Open the Service key
|
|
if (fHasService)
|
|
{
|
|
DWORD dwType;
|
|
WCHAR bCmdArgs[200];
|
|
DWORD dwSize = sizeof(bCmdArgs);
|
|
|
|
// Save the service name
|
|
pwszLocalService = (WCHAR *)ScmMemAlloc((lstrlenW(wszServiceName)+1)*sizeof(WCHAR));
|
|
if (pwszLocalService == NULL)
|
|
{
|
|
err = E_OUTOFMEMORY;
|
|
goto cleanup_and_exit;
|
|
}
|
|
lstrcpyW(pwszLocalService, wszServiceName);
|
|
|
|
// Fetch any command line argments
|
|
if ((err = RegQueryValueEx(hkThisAppID, wszServiceParameters,
|
|
NULL, &dwType, (BYTE*)bCmdArgs, &dwSize))
|
|
== ERROR_SUCCESS)
|
|
{
|
|
// Save the command line arguments
|
|
pwszServiceArgs = (WCHAR * ) ScmMemAlloc(dwSize);
|
|
if (pwszServiceArgs == NULL)
|
|
{
|
|
err = E_OUTOFMEMORY;
|
|
goto cleanup_and_exit;
|
|
}
|
|
memcpy((void *) pwszServiceArgs, bCmdArgs, dwSize);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// We look for the value "LaunchPermission" here and save it off for later
|
|
err = GetRegistrySecDesc( hkThisAppID, wszLaunchPermission, &pSD );
|
|
|
|
#ifdef DCOM_WITH_PER_USER_REG
|
|
// Look for the named value "Shared"
|
|
DWORD cbSize;
|
|
|
|
cbSize = 2;
|
|
err = RegQueryValueEx(hkThisAppID, wszShared, NULL, &dwType,
|
|
(BYTE *) wszYN, &cbSize);
|
|
*pfShared = (err == ERROR_SUCCESS);
|
|
#endif // DCOM
|
|
|
|
cleanup_and_exit:
|
|
RegCloseKey(hkThisAppID);
|
|
|
|
return err;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CClassRegistryReader::ReadClassEntry
|
|
//
|
|
// Synopsis: Set the state of this object by reading the
|
|
// registry entry given by contents of awName.
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
LONG
|
|
CClassRegistryReader::ReadClassEntry(
|
|
HKEY hKey,
|
|
BOOL CheckTreatAs,
|
|
BOOL CheckAutoConvert)
|
|
{
|
|
|
|
HKEY hClsRegEntry;
|
|
WCHAR wszYN[16];
|
|
WCHAR wszNewClsid[40];
|
|
LONG lSize;
|
|
DWORD dwType;
|
|
|
|
#ifdef _CHICAGO_
|
|
if ((err = RegOpenKeyExA(hKey, awName, NULL, KEY_READ, &hClsRegEntry))
|
|
!= ERROR_SUCCESS)
|
|
{
|
|
CairoleDebugOut((DEB_IWARN, "Unexpected error from RegOpenKeyEx opening %s: %x, %d\n", awName, err, __LINE__));
|
|
return err;
|
|
}
|
|
#else
|
|
if ((err = RegOpenKeyEx(hKey, awName, NULL, KEY_READ, &hClsRegEntry))
|
|
!= ERROR_SUCCESS)
|
|
{
|
|
CairoleDebugOut((DEB_IWARN, "Unexpected error from RegOpenKeyEx opening %ws: %x, %d\n", awName, err, __LINE__));
|
|
return err;
|
|
}
|
|
#endif
|
|
|
|
if ( CheckAutoConvert )
|
|
{
|
|
lSize = sizeof( wszNewClsid );
|
|
err = QueryStripRegValue(
|
|
hClsRegEntry,
|
|
L"AutoConvertTo",
|
|
wszNewClsid,
|
|
&lSize);
|
|
|
|
if ( err = ERROR_SUCCESS )
|
|
{
|
|
RegCloseKey( hClsRegEntry );
|
|
err = RegOpenKeyEx(hKey, wszNewClsid, NULL, KEY_READ, &hClsRegEntry);
|
|
if ( err != ERROR_SUCCESS )
|
|
return err;
|
|
}
|
|
}
|
|
|
|
if ( CheckTreatAs )
|
|
{
|
|
lSize = sizeof( wszNewClsid );
|
|
err = QueryStripRegValue(
|
|
hClsRegEntry,
|
|
L"TreatAs",
|
|
wszNewClsid,
|
|
&lSize);
|
|
|
|
if ( err = ERROR_SUCCESS )
|
|
{
|
|
RegCloseKey( hClsRegEntry );
|
|
err = RegOpenKeyEx(hKey, wszNewClsid, NULL, KEY_READ, &hClsRegEntry);
|
|
if ( err != ERROR_SUCCESS )
|
|
return err;
|
|
}
|
|
}
|
|
|
|
err = QueryStripRegValue(
|
|
hClsRegEntry,
|
|
wszLocalServer,
|
|
pwszLocalServer,
|
|
&lLocalServer);
|
|
|
|
if (err == ERROR_SUCCESS)
|
|
{
|
|
fHasLocalServer = TRUE;
|
|
}
|
|
else if (err == ERROR_MORE_DATA)
|
|
{
|
|
if (pwszLocalServer != awcsLocalServer)
|
|
{
|
|
ScmMemFree (pwszLocalServer);
|
|
}
|
|
pwszLocalServer = (WCHAR *) ScmMemAlloc (lLocalServer);
|
|
if (pwszLocalServer == NULL)
|
|
{
|
|
return(ERROR_NOT_ENOUGH_MEMORY);
|
|
}
|
|
|
|
err = QueryStripRegValue(
|
|
hClsRegEntry,
|
|
wszLocalServer,
|
|
pwszLocalServer,
|
|
&lLocalServer);
|
|
|
|
if (err != ERROR_SUCCESS)
|
|
{
|
|
CairoleDebugOut((DEB_IWARN, "Unexpected error from RegQueryValue: (local server 32) %x, %d\n", err, __LINE__));
|
|
dwSaveErr = err;
|
|
}
|
|
|
|
fHasLocalServer = TRUE;
|
|
}
|
|
else if (NotFoundError(err)) // == ERROR_FILE_NOT_FOUND)
|
|
{
|
|
err = QueryStripRegValue(
|
|
hClsRegEntry,
|
|
wszLocalServer16,
|
|
pwszLocalServer,
|
|
&lLocalServer);
|
|
|
|
if (err == ERROR_SUCCESS)
|
|
{
|
|
//
|
|
// The 16 bit version is the one we want. Add it to the
|
|
// flags.
|
|
//
|
|
f16Bit = TRUE;
|
|
fHasLocalServer = TRUE;
|
|
}
|
|
else if (err == ERROR_MORE_DATA)
|
|
{
|
|
if (pwszLocalServer != awcsLocalServer)
|
|
{
|
|
ScmMemFree (pwszLocalServer);
|
|
}
|
|
pwszLocalServer = (WCHAR *) ScmMemAlloc (lLocalServer);
|
|
if (pwszLocalServer == NULL)
|
|
{
|
|
CairoleDebugOut((DEB_ERROR, "Not enough memory, file=scm\\init.cxx, line=%d\n", __LINE__));
|
|
dwSaveErr = err;
|
|
}
|
|
|
|
err = QueryStripRegValue(
|
|
hClsRegEntry,
|
|
wszLocalServer16,
|
|
pwszLocalServer,
|
|
&lLocalServer);
|
|
|
|
if (err != ERROR_SUCCESS)
|
|
{
|
|
CairoleDebugOut((DEB_IWARN, "Unexpected error from RegQueryValue: (local server 16) %x, line=%d\n", err, __LINE__));
|
|
dwSaveErr = err;
|
|
}
|
|
|
|
//
|
|
// The 16 bit version is the one we want. Add it to the
|
|
// flags.
|
|
//
|
|
f16Bit = TRUE;
|
|
fHasLocalServer = TRUE;
|
|
}
|
|
else if (!NotFoundError(err)) // != ERROR_FILE_NOT_FOUND)
|
|
{
|
|
CairoleDebugOut((DEB_ERROR, "Unexpected error from RegQueryValue: (local server 16) %x, line=%d\n", err, __LINE__));
|
|
dwSaveErr = err;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CairoleDebugOut((DEB_ERROR, "Unexpected error from RegQueryValue: (local server 16) %x, line=%d\n", err, __LINE__));
|
|
dwSaveErr = err;
|
|
}
|
|
|
|
// find the AppID, if any
|
|
if ( RegQueryValueEx( hClsRegEntry,
|
|
wszAppIDName,
|
|
NULL,
|
|
&dwType,
|
|
(LPBYTE) pwszAppID,
|
|
&lAppID )
|
|
== ERROR_SUCCESS )
|
|
{
|
|
// Scarf up all the AppID entries
|
|
pAppIDData = new CAppIDData();
|
|
|
|
pAppIDData->ReadEntries( pwszAppID );
|
|
}
|
|
|
|
RegCloseKey(hClsRegEntry);
|
|
return(dwSaveErr);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CClassRegistryReader::ReadSingleClass
|
|
//
|
|
// Synopsis: Set this objects data by reading entry for
|
|
// given class.
|
|
//
|
|
// Arguments: [rclsid] -- class id of class info to read from registry.
|
|
//
|
|
// Returns: LONG error code.
|
|
//
|
|
// Algorithm: Initialize as if doing enumeration for single
|
|
// CLSID (by setting awName) and then just read one
|
|
// entry.
|
|
//
|
|
// Notes:
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
LONG CClassRegistryReader::ReadSingleClass(
|
|
REFCLSID rclsid,
|
|
BOOL CheckTreatAs,
|
|
BOOL CheckAutoConvert )
|
|
{
|
|
#ifdef _CHICAGO_
|
|
if (errClsReg != ERROR_SUCCESS)
|
|
{
|
|
CairoleDebugOut((DEB_ERROR, "Unexpected error from RegOpenKeyEx: %x, line=%d\n", errClsReg, __LINE__));
|
|
Win4Assert(FALSE && "RegOpenKey failed!");
|
|
return errClsReg;
|
|
}
|
|
#endif
|
|
|
|
InitInner();
|
|
|
|
guidClassID = rclsid;
|
|
|
|
#ifdef _CHICAGO_
|
|
cName = wStringFromGUID2A(guidClassID, awName, sizeof(awName)) - 1;
|
|
#else
|
|
cName = wStringFromGUID2(guidClassID, awName, sizeof(awName)) - 1;
|
|
#endif //_CHICAGO_
|
|
|
|
// sets internal state
|
|
err = ReadClassEntry(g_hkClsID, CheckTreatAs, CheckAutoConvert);
|
|
|
|
// NT 5.0
|
|
#if 0
|
|
/*
|
|
// If PersonalClasses is not turned on then read from the common part
|
|
// of the registry
|
|
if (!gpClassCache->GetPersonalClasses())
|
|
{
|
|
err = ReadClassEntry(g_hkClsID, &_fShared); // sets internal state
|
|
_fShared = TRUE;
|
|
}
|
|
|
|
// Otherwise read from the per-user part of the registry.
|
|
// Note that if pUserSid != NULL then we are guaranteed to be
|
|
// still impersonating
|
|
else
|
|
{
|
|
HKEY hUserClsReg;
|
|
|
|
// Check if we have the per-user registry handle cached
|
|
hUserClsReg = gpClassCache->GetHkey(pUserSid);
|
|
|
|
// Otherwise open the key \\HKEY_USERS\<sid>_MergedClasses\CLSID
|
|
// and cache the handle
|
|
if (hUserClsReg == NULL)
|
|
{
|
|
HANDLE hUserToken;
|
|
PROFILEINFOW sProfileInfo;
|
|
UNICODE_STRING sCurrentUserKey;
|
|
WCHAR wszRegPath[128];
|
|
|
|
hUserToken = 0;
|
|
|
|
// Impersonate the client
|
|
RpcImpersonateClient((RPC_BINDING_HANDLE) 0 );
|
|
|
|
// Get the user token while impersonating
|
|
NTSTATUS NtStatus = NtOpenThreadToken(NtCurrentThread(),
|
|
TOKEN_DUPLICATE | TOKEN_QUERY,
|
|
TRUE,
|
|
&hUserToken);
|
|
if (!NT_SUCCESS(NtStatus))
|
|
{
|
|
err = ERROR_NO_IMPERSONATION_TOKEN;
|
|
}
|
|
|
|
// Load this user's profile if it's not the interactive user
|
|
if (err == ERROR_SUCCESS && !fInteractiveUser)
|
|
{
|
|
// if (!LoadNonInteractiveUserProfile(hUserToken, &sProfileInfo))
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//////////TEMPORARY TEMPORARY TEMPORARY TEMPORARY TEMPORARY TEMPORARY ///////
|
|
if (!LoadUserProfileW(hUserToken, &sProfileInfo))
|
|
//////////TEMPORARY TEMPORARY TEMPORARY TEMPORARY TEMPORARY TEMPORARY ///////
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
{
|
|
err = ERROR_CANNOT_OPEN_PROFILE;
|
|
}
|
|
}
|
|
|
|
// Only if we were successful to here
|
|
if (err == ERROR_SUCCESS)
|
|
{
|
|
// Formulate the registry path
|
|
RtlFormatCurrentUserKeyPath(&sCurrentUserKey);
|
|
memcpy(wszRegPath, sCurrentUserKey.Buffer,
|
|
2 * sCurrentUserKey.Length);
|
|
wszRegPath[sCurrentUserKey.Length] = L'\0';
|
|
RtlFreeUnicodeString(&sCurrentUserKey);
|
|
lstrcatW(wszRegPath, L"_MergedClasses\\");
|
|
lstrcatW(wszRegPath, tszCLSID);
|
|
|
|
// Open the key
|
|
err = RegOpenKeyEx(HKEY_USERS, wszRegPath, NULL, KEY_READ,
|
|
&hUserClsReg);
|
|
|
|
// Cache the per-user registry handle
|
|
if (err == ERROR_SUCCESS)
|
|
{
|
|
if (!gpClassCache->SetHkey(pUserSid, hUserClsReg))
|
|
{
|
|
err = ERROR_OUTOFMEMORY;
|
|
}
|
|
}
|
|
}
|
|
|
|
NtClose( hUserToken );
|
|
}
|
|
|
|
// Read the registry
|
|
if (err == ERROR_SUCCESS)
|
|
{
|
|
err = ReadClassEntry(hUserClsReg, &_fShared);
|
|
}
|
|
|
|
// Whether success or failure we're done impersonating for awhile
|
|
RpcRevertToSelf();
|
|
}
|
|
*/
|
|
#endif // 0
|
|
|
|
if (err != ERROR_SUCCESS)
|
|
{
|
|
CairoleDebugOut((DEB_IWARN, "Unexpected error from ReadClassEntry: %x, line=%d\n", err, __LINE__));
|
|
}
|
|
return(err);
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CClassRegistryReader::NewClassData
|
|
//
|
|
// Synopsis: Create a CClassData with data in this object which
|
|
// was previously set by ReadClassEntry.
|
|
//
|
|
// Arguments: [hr] -- Set to an error code on failure, untouched
|
|
// otherwise.
|
|
//
|
|
// Returns: NULL on failure, else pointer to new CClassData allocated
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
CClassData * CClassRegistryReader::NewClassData(HRESULT &hr)
|
|
// NT 5.0 PSID pUserSid
|
|
{
|
|
CClassID ccid(guidClassID);
|
|
|
|
CClassData *pccdNew;
|
|
|
|
if ( pAppIDData )
|
|
{
|
|
WCHAR * pwszCloneAppID = 0;
|
|
DWORD Bytes;
|
|
|
|
Bytes = (lstrlenW(pwszAppID)+1)*sizeof(WCHAR);
|
|
pwszCloneAppID = (WCHAR*) ScmMemAlloc( Bytes );
|
|
if ( ! pwszCloneAppID )
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
return NULL;
|
|
}
|
|
memcpy( pwszCloneAppID, pwszAppID, Bytes );
|
|
|
|
// Create a new class object
|
|
pccdNew = new CClassData(ccid,
|
|
pwszCloneAppID,
|
|
(pAppIDData->fHasService ? pAppIDData->pwszLocalService
|
|
: (fHasLocalServer ? pwszLocalServer : NULL)),
|
|
pAppIDData->pwszRemoteServerName,
|
|
pAppIDData->fHasService,
|
|
pAppIDData->fHasService ? pAppIDData->pwszServiceArgs : NULL,
|
|
pAppIDData->pwszRunAsUserName,
|
|
pAppIDData->pwszRunAsDomainName,
|
|
#ifdef DCOM
|
|
// NT 5.0 _fShared ? NULL : pUserSid,
|
|
#endif // DCOM
|
|
pAppIDData->fActivateAtStorage,
|
|
pAppIDData->fHasRemoteServerName,
|
|
pAppIDData->pSD,
|
|
f16Bit,
|
|
hr);
|
|
|
|
if ( ! pccdNew )
|
|
{
|
|
ScmMemFree( pwszCloneAppID );
|
|
pAppIDData->Cleanup();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Create a new class object
|
|
pccdNew = new CClassData(ccid,
|
|
NULL,
|
|
fHasLocalServer ? pwszLocalServer : NULL,
|
|
NULL,
|
|
FALSE,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
#ifdef DCOM
|
|
// NT 5.0 _fShared ? NULL : pUserSid,
|
|
#endif // DCOM
|
|
FALSE,
|
|
FALSE,
|
|
FALSE,
|
|
f16Bit,
|
|
hr);
|
|
}
|
|
|
|
if ( ! pccdNew )
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
else if ( FAILED(hr) )
|
|
{
|
|
pccdNew->DeleteThis();
|
|
pccdNew = NULL;
|
|
}
|
|
|
|
return pccdNew;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: InitSCMRegistry
|
|
//
|
|
// Synopsis: fill in initial global keys from the registry.
|
|
//
|
|
// Arguments: none
|
|
//
|
|
// Returns: HRESULT on failure
|
|
//
|
|
//--------------------------------------------------------------------
|
|
HRESULT
|
|
InitSCMRegistry()
|
|
{
|
|
HRESULT hr;
|
|
LONG err;
|
|
DWORD dwDisp;
|
|
|
|
err = RegOpenKeyEx( HKEY_CLASSES_ROOT,
|
|
L"ClsID",
|
|
0,
|
|
KEY_READ,
|
|
&g_hkClsID );
|
|
|
|
if ( err != ERROR_SUCCESS )
|
|
{
|
|
g_hkClsID = 0;
|
|
Win4Assert( !"failed to open CLSID key");
|
|
return E_FAIL;
|
|
}
|
|
|
|
err = RegCreateKeyEx( HKEY_CLASSES_ROOT,
|
|
L"AppID",
|
|
0,
|
|
NULL,
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_ALL_ACCESS,
|
|
NULL,
|
|
&g_hkAppID,
|
|
&dwDisp );
|
|
|
|
if ( err != ERROR_SUCCESS )
|
|
{
|
|
g_hkAppID = 0;
|
|
Win4Assert(!"failed to open AppID key");
|
|
return E_FAIL;
|
|
}
|
|
|
|
return S_OK;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|