#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; static UINT uiNumCritSectsInitialized = 0; 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; InitializeCriticalSection(&g_DispTypeInfoCritSect); ++uiNumCritSectsInitialized; InitializeCriticalSection(&g_StringsCriticalSection); ++uiNumCritSectsInitialized; InitializeCriticalSection(&g_csRouterHeadCritSect); // router initialization ++uiNumCritSectsInitialized; #if DBG==1 InitializeCriticalSection(&g_csDP); // Used by ADsDebug ++uiNumCritSectsInitialized; #ifndef MSVC InitializeCriticalSection(&g_csOT); // Used by Object Tracker ++uiNumCritSectsInitialized; InitializeCriticalSection(&g_csMem); // Used by Object Tracker ++uiNumCritSectsInitialized; #endif #endif } __except (EXCEPTION_EXECUTE_HANDLER) { // // Critical failure // // // Delete the cs we init'ed. The fall through in each case is // intentional, as is the fact that we delete the critical sections // in the reverse order to which we initialized them. // switch(uiNumCritSectsInitialized) { #if DBG==1 #ifndef MSVC case 6: DeleteCriticalSection(&g_csMem); // Used by Object Tracker case 5: DeleteCriticalSection(&g_csOT); // Used by Object Tracker #endif case 4: DeleteCriticalSection(&g_csDP); // Used by ADsDebug #endif case 3: DeleteCriticalSection(&g_csRouterHeadCritSect); case 2: DeleteCriticalSection(&g_StringsCriticalSection); case 1: DeleteCriticalSection(&g_DispTypeInfoCritSect); } // // Reset the counts of critical sections that we have initialized, just // in case LibMain(DLL_PROCESS_DETACH) does get called. // uiNumCritSectsInitialized = 0; return FALSE; } break; case DLL_PROCESS_DETACH: if (g_pRouterHead) { CleanupRouter(g_pRouterHead); } FreeTypeInfoTable(); // // Delete the cs we init'ed. The fall through in each case is // intentional, as is the fact that we delete the critical sections // in the reverse order to which we initialized them. // switch(uiNumCritSectsInitialized) { #if DBG==1 #ifndef MSVC case 6: DeleteCriticalSection(&g_csMem); // Used by Object Tracker case 5: DeleteCriticalSection(&g_csOT); // Used by Object Tracker #endif case 4: DeleteCriticalSection(&g_csDP); // Used by ADsDebug #endif case 3: DeleteCriticalSection(&g_csRouterHeadCritSect); case 2: DeleteCriticalSection(&g_StringsCriticalSection); case 1: DeleteCriticalSection(&g_DispTypeInfoCritSect); } // // 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]; const WCHAR pwTypeLibraryName[] = L"activeds.tlb"; // 15 includes name of the type libaray, NULL terminator, backslash and one extra space WCHAR pwTypeLibPath[MAX_PATH + 15] = L""; HRESULT hr = S_OK; #if (!defined(BUILD_FOR_NT40)) auto_rel 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; ITypeLib *pITypeLib = NULL; UINT iSize = 0; // // 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); goto error; } // register our activeds.tlb iSize = GetSystemDirectoryW(pwTypeLibPath, MAX_PATH + 1); if(iSize == 0 || iSize > MAX_PATH + 1) { wcscpy(pwTypeLibPath, pwTypeLibraryName); } else { wcscat(pwTypeLibPath, L"\\"); wcscat(pwTypeLibPath,pwTypeLibraryName); } hr = LoadTypeLib(pwTypeLibPath, &pITypeLib); if(FAILED(hr)) { AtlTrace(_T("LoadTypeLib() failed! hr=%x\n"), hr); goto error; } hr = RegisterTypeLib(pITypeLib, pwTypeLibPath, NULL); if(FAILED(hr)) { AtlTrace(_T("RegisterTypeLib() failed! hr=%x\n"), hr); } error: CoTaskMemFree(pwszClsid); if (hKeyClsid) { RegCloseKey(hKeyClsid); } if (hKeyDll) { RegCloseKey(hKeyDll); } if(pITypeLib) { pITypeLib->Release(); } #endif return hr; } STDAPI DllUnregisterServer() { PWCHAR pwszClsid = NULL; WCHAR pwszClsidKey[256]; WCHAR pwszDllKey[256]; HRESULT hr = S_OK; LONG lRetVal; ITypeLib *pITypeLib = NULL; const WCHAR pwTypeLibraryName[] = L"activeds.tlb"; // 15 includes name of the type libaray, NULL terminator, backslash and one extra space WCHAR pwTypeLibPath[MAX_PATH + 15] = L""; TLIBATTR* pTLibAttr = NULL; UINT iSize = 0; #if (!defined(BUILD_FOR_NT40)) auto_rel 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); } // Unregister the type library iSize = GetSystemDirectoryW(pwTypeLibPath, MAX_PATH + 1); if(iSize == 0 || iSize > MAX_PATH + 1) { wcscpy(pwTypeLibPath, pwTypeLibraryName); } else { wcscat(pwTypeLibPath, L"\\"); wcscat(pwTypeLibPath,pwTypeLibraryName); } hr = LoadTypeLib(pwTypeLibPath, &pITypeLib); if (SUCCEEDED(hr)) { hr = pITypeLib->GetLibAttr(&pTLibAttr); if(SUCCEEDED(hr)) { hr = UnRegisterTypeLib(pTLibAttr->guid, pTLibAttr->wMajorVerNum, pTLibAttr->wMinorVerNum, pTLibAttr->lcid, pTLibAttr->syskind); pITypeLib->ReleaseTLibAttr(pTLibAttr); } pITypeLib->Release(); } } error: CoTaskMemFree(pwszClsid); #endif return hr; }