WindowsXP-SP1/ds/adsi/router/libmain.cxx
2020-09-30 16:53:49 +02:00

615 lines
17 KiB
C++

#include "oleds.hxx"
#include "bindercf.hxx"
#include "atlbase.h"
#pragma hdrstop
//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1993.
//
// File: libmain.cxx
//
// Contents: LibMain for ADs.dll
//
// Functions: LibMain, DllGetClassObject
//
// History: 25-Oct-94 KrishnaG Created.
//
//----------------------------------------------------------------------------
HINSTANCE g_hInst = NULL;
PROUTER_ENTRY g_pRouterHead = NULL;
CRITICAL_SECTION g_csRouterHeadCritSect;
//
// Dll's we load dynamically.
//
extern HANDLE g_hDllAdvapi32;
extern const GUID DBGUID_ROOTBINDER =
{0xFF151822, 0xB0BF, 0x11D1, {0xA8, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
//---------------------------------------------------------------------------
// ADs debug print, mem leak and object tracking-related stuff
//---------------------------------------------------------------------------
DECLARE_INFOLEVEL(ADs)
//+---------------------------------------------------------------------------
//
// Function: ShutDown
//
// Synopsis: Function to handle printing out heap debugging display
//
//----------------------------------------------------------------------------
inline VOID ShutDown()
{
#if DBG==1
#ifndef MSVC
DUMP_TRACKING_INFO_DELETE();
AllocArenaDump( NULL );
DeleteCriticalSection(&g_csOT);
#endif // ifndef MSVC
DeleteCriticalSection(&g_csDP);
#endif
}
extern "C" DWORD heapInfoLevel;
extern "C" DWORD OtInfoLevel;
extern "C" DWORD ADsInfoLevel;
//+---------------------------------------------------------------------------
//
// Function: GetINIHeapInfoLevel
//
// Synopsis: Gets various infolevel values from win.ini
//
//----------------------------------------------------------------------------
inline VOID GetINIHeapInfoLevel()
{
#if DBG==1
const INT MAXINFOLEN=11;
WCHAR awcs[MAXINFOLEN];
#ifndef MSVC
if (GetProfileString(L"ADs",L"heapInfoLevel", L"00000003", awcs,MAXINFOLEN))
heapInfoLevel = wcstoul(awcs, NULL, 16);
if (GetProfileString(L"ADs",L"Ot", L"00000003", awcs, MAXINFOLEN))
OtInfoLevel = wcstoul(awcs, NULL, 16);
#endif // MSVC
if (GetProfileString(L"ADs",L"ADsInfoLevel", L"00000003", awcs,MAXINFOLEN))
ADsInfoLevel = wcstoul(awcs, NULL, 16);
#endif
}
// Globals
ULONG g_ulObjCount = 0; // Number of objects alivein ADs.dll
//+------------------------------------------------------------------------
//
// Macro that calculates the number of elements in a statically-defined
// array.
//
// Note - I swiped this from formsary.cxx - A type-safe array class. Remember
// to swipe the whole thing as required.
//-------------------------------------------------------------------------
#define ARRAY_SIZE(_a) (sizeof(_a) / sizeof(_a[0]))
//+------------------------------------------------------------------------
//
// ADs class factories
//
//-------------------------------------------------------------------------
CADsNamespacesCF g_cfNamespaces;
CADsProviderCF g_cfProvider;
CDSOCF g_cfDSO;
CADsSecurityDescriptorCF g_cfSed;
CADsAccessControlListCF g_cfAcl;
CADsAccessControlEntryCF g_cfAce;
CADsPropertyEntryCF g_cfPropEntry;
CADsPropertyValueCF g_cfPropertyValue;
CADsLargeIntegerCF g_cfLargeInteger;
CADsBinderCF g_cfBinder;
CPathnameCF g_cfPathname;
CADsDNWithBinaryCF g_cfDNWithBinary;
CADsDNWithStringCF g_cfDNWithString;
CADsSecurityUtilityCF g_cfADsSecurityUtility;
extern CRITICAL_SECTION g_DispTypeInfoCritSect;
extern CRITICAL_SECTION g_StringsCriticalSection;
struct CLSCACHE
{
const CLSID * pclsid;
IClassFactory * pCF;
};
CLSCACHE g_aclscache[] =
{
&CLSID_ADsNamespaces, &g_cfNamespaces,
&CLSID_ADsProvider, &g_cfProvider,
&CLSID_ADsDSOObject, &g_cfDSO,
&CLSID_SecurityDescriptor, &g_cfSed,
&CLSID_AccessControlList, &g_cfAcl,
&CLSID_AccessControlEntry, &g_cfAce,
&CLSID_PropertyEntry, &g_cfPropEntry,
&CLSID_PropertyValue, &g_cfPropertyValue,
&CLSID_LargeInteger, &g_cfLargeInteger,
&CLSID_ADSI_BINDER, &g_cfBinder,
&CLSID_Pathname, &g_cfPathname,
&CLSID_DNWithBinary, &g_cfDNWithBinary,
&CLSID_DNWithString, &g_cfDNWithString,
&CLSID_ADsSecurityUtility, &g_cfADsSecurityUtility
};
//------------------------------------------------------------------------
// ATL Module definition
//------------------------------------------------------------------------
CComModule _Module;
//+---------------------------------------------------------------
//
// Function: DllGetClassObject
//
// Synopsis: Standard DLL entrypoint for locating class factories
//
//----------------------------------------------------------------
STDAPI
DllGetClassObject(REFCLSID clsid, REFIID iid, LPVOID FAR* ppv)
{
HRESULT hr;
size_t i;
if( ppv == NULL )
RRETURN( E_INVALIDARG );
*ppv = NULL;
for (i = 0; i < ARRAY_SIZE(g_aclscache); i++)
{
if (IsEqualCLSID(clsid, *g_aclscache[i].pclsid))
{
hr = g_aclscache[i].pCF->QueryInterface(iid, ppv);
RRETURN(hr);
}
}
*ppv = NULL;
//
// Add Debugging Code to indicate that the ADs.DllGetClassObject
// has been called with an unknown CLSID.
//
return CLASS_E_CLASSNOTAVAILABLE;
}
//+---------------------------------------------------------------
//
// Function: DllCanUnloadNow
//
// Synopsis: Standard DLL entrypoint to determine if DLL can be unloaded
//
//---------------------------------------------------------------
STDAPI
DllCanUnloadNow(void)
{
HRESULT hr;
hr = S_FALSE;
if (DllReadyToUnload())
hr = S_OK;
return hr;
}
//+---------------------------------------------------------------
//
// Function: LibMain
//
// Synopsis: Standard DLL initialization entrypoint
//
//---------------------------------------------------------------
EXTERN_C BOOL __cdecl
LibMain(HINSTANCE hInst, ULONG ulReason, LPVOID pvReserved)
{
HRESULT hr;
switch (ulReason)
{
case DLL_PROCESS_ATTACH:
//
// Need to put in try catch block as init crit sects can fail.
//
__try {
DisableThreadLibraryCalls(hInst);
g_hInst = hInst;
#if DBG==1
#ifndef MSVC
InitializeCriticalSection(&g_csOT); // Used by Object Tracker
InitializeCriticalSection(&g_csMem); // Used by Object Tracker
#endif
InitializeCriticalSection(&g_csDP); // Used by ADsDebug
#endif
InitializeCriticalSection(&g_DispTypeInfoCritSect);
InitializeCriticalSection(&g_StringsCriticalSection);
InitializeCriticalSection(&g_csRouterHeadCritSect); // router initialization
}
__except (EXCEPTION_EXECUTE_HANDLER) {
//
// Critical failure
//
return FALSE;
}
break;
case DLL_PROCESS_DETACH:
if (g_pRouterHead) {
CleanupRouter(g_pRouterHead);
}
FreeTypeInfoTable();
//
// Delete the cs we inited.
//
#if DBG==1
#ifndef MSVC
DeleteCriticalSection(&g_csOT); // Used by Object Tracker
DeleteCriticalSection(&g_csMem); // Used by Object Tracker
#endif
DeleteCriticalSection(&g_csDP); // Used by ADsDebug
#endif
DeleteCriticalSection(&g_DispTypeInfoCritSect);
DeleteCriticalSection(&g_StringsCriticalSection);
DeleteCriticalSection(&g_csRouterHeadCritSect);
//
// Free any libs we loaded using loadlibrary
//
if (g_hDllAdvapi32) {
FreeLibrary((HMODULE) g_hDllAdvapi32);
g_hDllAdvapi32 = NULL;
}
break;
default:
break;
}
return TRUE;
}
//+---------------------------------------------------------------------------
//
// Function: DllMain
//
// Synopsis: entry point for NT - post .546
//
//----------------------------------------------------------------------------
BOOL
DllMain(HANDLE hDll, DWORD dwReason, LPVOID lpReserved)
{
return LibMain((HINSTANCE)hDll, dwReason, lpReserved);
}
//+------------------------------------------------------------------------
//
// Function: GetCachedClsidIndex
//
// Synopsis: Returns the index of the given CLSID in the cache, or
// -1 if the CLSID is not present in the cache
//
// Arguments: [clsid]
//
// Returns: int
//
//-------------------------------------------------------------------------
int
GetCachedClsidIndex(REFCLSID clsid)
{
int i;
CLSCACHE * pclscache;
for (i = 0, pclscache = g_aclscache;
i < ARRAY_SIZE(g_aclscache);
i ++, pclscache++)
{
if (IsEqualCLSID(*pclscache->pclsid, clsid))
return i;
}
return -1;
}
//+------------------------------------------------------------------------
//
// Function: GetCachedClassFactory
//
// Synopsis: Returns the cached class factory with the given index.
// The pointer returned has been AddRef'd.
//
// Arguments: [iclsid]
//
// Returns: IClassFactory *
//
//-------------------------------------------------------------------------
IClassFactory *
GetCachedClassFactory(int iclsid)
{
IClassFactory * pCF;
// Assert(iclsid >= 0);
// Assert(iclsid < ARRAY_SIZE(g_aclscache));
pCF = g_aclscache[iclsid].pCF;
pCF->AddRef();
return pCF;
}
//+------------------------------------------------------------------------
//
// Function: GetCachedClsid
//
// Synopsis: Returns the CLSID corresponding to the given index.
// Normally, code should call GetCachedClassFactory to get
// the class factory directly.
//
// Arguments: [iclsid] -- Clsid index
// [pclsid] -- Matching clsid returned in *pclsid
//
//-------------------------------------------------------------------------
void
GetCachedClsid(int iclsid, CLSID * pclsid)
{
// Assert(iclsid >= 0);
// Assert(iclsid < ARRAY_SIZE(g_aclscache));
*pclsid = *g_aclscache[iclsid].pclsid;
}
STDAPI DllRegisterServer()
{
PWCHAR pwszClsid = NULL;
WCHAR pwszSubKey[256];
HRESULT hr = S_OK;
#if (!defined(BUILD_FOR_NT40))
auto_rel<IRegisterProvider> pRegisterProvider;
wcscpy(pwszSubKey, L"SOFTWARE\\Classes\\CLSID\\");
hr = StringFromCLSID(CLSID_ADSI_BINDER, &pwszClsid);
if (FAILED(hr))
return hr;
wcscat(pwszSubKey, pwszClsid);
HKEY hKeyClsid = NULL, hKeyDll = NULL;
DWORD dwDisposition;
LONG lRetVal;
//
// Make sure the router has been initialized
//
EnterCriticalSection(&g_csRouterHeadCritSect);
if (!g_pRouterHead) {
g_pRouterHead = InitializeRouter();
}
LeaveCriticalSection(&g_csRouterHeadCritSect);
//Create CLSID entry
lRetVal = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
pwszSubKey,
0,
L"",
0,
KEY_ALL_ACCESS,
NULL,
&hKeyClsid,
&dwDisposition);
if (lRetVal != ERROR_SUCCESS)
BAIL_ON_FAILURE(HRESULT_FROM_WIN32(lRetVal));
//set the value
lRetVal = RegSetValueEx(hKeyClsid,
NULL,
0,
REG_SZ,
(CONST BYTE *)L"Provider Binder for DS OLE DB Provider",
78);
if (lRetVal != ERROR_SUCCESS)
BAIL_ON_FAILURE(HRESULT_FROM_WIN32(lRetVal));
//Create InprocServer32 entry
lRetVal = RegCreateKeyEx(hKeyClsid,
L"InprocServer32",
0,
L"activeds.dll",
0,
KEY_ALL_ACCESS,
NULL,
&hKeyDll,
&dwDisposition);
if (lRetVal != ERROR_SUCCESS)
BAIL_ON_FAILURE(HRESULT_FROM_WIN32(lRetVal));
//set the value
lRetVal = RegSetValueEx(hKeyDll,
NULL,
0,
REG_SZ,
(CONST BYTE *)L"activeds.dll",
26);
if (lRetVal != ERROR_SUCCESS)
BAIL_ON_FAILURE(HRESULT_FROM_WIN32(lRetVal));
//Now set the threadingModel value for the dll key
lRetVal = RegSetValueEx(hKeyDll,
L"ThreadingModel",
0,
REG_SZ,
(CONST BYTE *)L"Both",
10);
if (lRetVal != ERROR_SUCCESS)
BAIL_ON_FAILURE(HRESULT_FROM_WIN32(lRetVal));
//Now register the provider with the root binder.
//Cocreate Root Binder and get IRegisterProvider interface.
hr = CoCreateInstance ( DBGUID_ROOTBINDER,
NULL,
CLSCTX_ALL,
__uuidof(IRegisterProvider),
(void **) &pRegisterProvider
);
if (SUCCEEDED(hr))
{
// Go through list of ADS providers and register each of them
// with the root binder.
for ( PROUTER_ENTRY pProvider = g_pRouterHead;
pProvider != NULL;
pProvider=pProvider->pNext)
{
// Invalid provider ProgID? If so, continue with next provider
if (NULL == pProvider->szProviderProgId)
continue;
hr = pRegisterProvider->SetURLMapping(
pProvider->szProviderProgId,
0,
CLSID_ADSI_BINDER);
if (FAILED(hr))
AtlTrace(_T("Failed to register %s mapping hr = %x\n"),
pProvider->szProviderProgId, hr);
// Ignore error and continue with next provider
hr = S_OK;
}
}
else
{
AtlTrace(_T("Creation of Root Binder failed! hr = %x\n"), hr);
}
error:
CoTaskMemFree(pwszClsid);
if (hKeyClsid) {
RegCloseKey(hKeyClsid);
}
if (hKeyDll) {
RegCloseKey(hKeyDll);
}
#endif
return hr;
}
STDAPI DllUnregisterServer()
{
PWCHAR pwszClsid = NULL;
WCHAR pwszClsidKey[256];
WCHAR pwszDllKey[256];
HRESULT hr = S_OK;
LONG lRetVal;
#if (!defined(BUILD_FOR_NT40))
auto_rel<IRegisterProvider> pRegisterProvider;
wcscpy(pwszClsidKey, L"SOFTWARE\\Classes\\CLSID\\");
hr = StringFromCLSID(CLSID_ADSI_BINDER, &pwszClsid);
if (FAILED(hr))
return hr;
wcscat(pwszClsidKey, pwszClsid);
wcscpy(pwszDllKey, pwszClsidKey);
wcscat(pwszDllKey, L"\\InprocServer32");
//
// Make sure the router has been initialized
//
EnterCriticalSection(&g_csRouterHeadCritSect);
if (!g_pRouterHead) {
g_pRouterHead = InitializeRouter();
}
LeaveCriticalSection(&g_csRouterHeadCritSect);
//Delete InprocServer32 key
lRetVal = RegDeleteKey(HKEY_LOCAL_MACHINE, pwszDllKey);
if (lRetVal != ERROR_SUCCESS)
BAIL_ON_FAILURE(HRESULT_FROM_WIN32(lRetVal));
//Delete key and all its subkeys.
lRetVal = RegDeleteKey(HKEY_LOCAL_MACHINE, pwszClsidKey);
if (lRetVal != ERROR_SUCCESS)
BAIL_ON_FAILURE(HRESULT_FROM_WIN32(lRetVal));
//Now unregister provider binder from Root Binder.
//Cocreate Root Binder and get IRegisterProvider interface.
hr = CoCreateInstance ( DBGUID_ROOTBINDER,
NULL,
CLSCTX_ALL,
__uuidof(IRegisterProvider),
(void **) &pRegisterProvider
);
if (SUCCEEDED(hr))
{
// Unregister each provider with the root binder
for ( PROUTER_ENTRY pProvider = g_pRouterHead;
pProvider != NULL;
pProvider=pProvider->pNext)
{
// Invalid provider ProgID? If so, continue with next provider
if (NULL == pProvider->szProviderProgId)
continue;
pRegisterProvider->UnregisterProvider(
pProvider->szProviderProgId,
0,
CLSID_ADSI_BINDER);
}
}
error:
CoTaskMemFree(pwszClsid);
#endif
return hr;
}