Leaked source code of windows server 2003
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.
 
 
 
 
 
 

636 lines
16 KiB

/////////////////////////////////////////////////////////////////////////////////////////////////
//
// MAINDLL.CPP
//
// Purpose: Contains DLL entry points. Also has code that controls
// when the DLL can be unloaded by tracking the number of
// objects and locks as well as routines that support
// self registration.
//
// Copyright (c) 1997-2002 Microsoft Corporation, All Rights Reserved
//
/////////////////////////////////////////////////////////////////////////////////////////////////
#include "precomp.h"
#include <initguid.h>
#include <locale.h>
#include "wdmdefs.h"
#include <stdio.h>
#include <tchar.h>
#include <strsafe.h>
HMODULE ghModule;
CWMIEvent * g_pBinaryMofEvent = NULL;
CCriticalSection g_EventCs;
CCriticalSection g_SharedLocalEventsCs;
CCriticalSection g_ListCs;
CCriticalSection g_LoadUnloadCs;
CCriticalSection *g_pEventCs = &g_EventCs; // pointer for backward comp
CCriticalSection *g_pSharedLocalEventsCs = &g_SharedLocalEventsCs; // pointer for backward comp
CCriticalSection *g_pListCs = &g_ListCs; // pointer for backward comp
CCriticalSection *g_pLoadUnloadCs = &g_LoadUnloadCs; // pointer for backward comp
//Count number of objects and number of locks.
long g_cObj=0;
long g_cLock=0;
long glInits = 0;
long glProvObj = 0;
long glEventsRegistered = 0;
#include "wmiguard.h"
WmiGuard * pGuard = NULL;
/////////////////////////////////////////////////////////////////////////////////////////////////
//
// LibMain32
//
// Purpose: Entry point for DLL. Good place for initialization.
// Return: TRUE if OK.
//
/////////////////////////////////////////////////////////////////////////////////////////////////
BOOL WINAPI DllMain(HINSTANCE hInstance, ULONG ulReason, LPVOID pvReserved)
{
SetStructuredExceptionHandler seh;
BOOL fRc = TRUE;
try
{
switch( ulReason )
{
case DLL_PROCESS_DETACH:
{
//
// release binary mof changes worker
//
SAFE_DELETE_PTR(g_pBinaryMofEvent);
if ( pGuard )
{
delete pGuard;
pGuard = NULL;
if( g_ListCs.IsValid() )
{
g_ListCs.Delete();
}
if( g_EventCs.IsValid() )
{
g_EventCs.Delete();
}
if( g_SharedLocalEventsCs.IsValid() )
{
g_SharedLocalEventsCs.Delete();
}
if( g_LoadUnloadCs.IsValid() )
{
g_LoadUnloadCs.Delete();
}
}
}
break;
case DLL_PROCESS_ATTACH:
{
if ( ( pGuard = new WmiGuard ( ) ) == NULL )
{
fRc = FALSE;
}
else
{
g_LoadUnloadCs.Init();
g_SharedLocalEventsCs.Init();
g_EventCs.Init();
g_ListCs.Init();
fRc = ( g_LoadUnloadCs.IsValid() &&
g_SharedLocalEventsCs.IsValid() &&
g_EventCs.IsValid() &&
g_ListCs.IsValid() ) ? TRUE : FALSE ;
if ( fRc )
{
fRc = pGuard->Init ( g_pSharedLocalEventsCs );
if ( fRc )
{
//
// instantiate worker for driver's
// classes addition and deletion
//
fRc = FALSE;
HRESULT hr = WBEM_S_NO_ERROR ;
try
{
g_pBinaryMofEvent = (CWMIEvent *)new CWMIEvent(INTERNAL_EVENT); // This is the global guy that catches events of new drivers being added at runtime.
if(g_pBinaryMofEvent)
{
if ( g_pBinaryMofEvent->Initialized () )
{
fRc = TRUE ;
}
else
{
delete g_pBinaryMofEvent ;
g_pBinaryMofEvent = NULL ;
}
}
else
{
}
}
STANDARD_CATCH
}
}
}
ghModule = hInstance;
if (!DisableThreadLibraryCalls(ghModule))
{
ERRORTRACE((THISPROVIDER, "DisableThreadLibraryCalls failed\n" ));
}
}
break;
}
}
catch(Structured_Exception e_SE)
{
fRc = FALSE;
}
catch(Heap_Exception e_HE)
{
fRc = FALSE;
}
catch(...)
{
fRc = FALSE;
}
return fRc;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
//
// DllGetClassObject
//
// Purpose: Called by Ole when some client wants a a class factory. Return
// one only if it is the sort of class this DLL supports.
//
/////////////////////////////////////////////////////////////////////////////////////////////////
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, PPVOID ppv)
{
HRESULT hr = CLASS_E_CLASSNOTAVAILABLE ;
CProvFactory *pFactory = NULL;
SetStructuredExceptionHandler seh;
try
{
//============================================================================
// Verify the caller is asking for our type of object.
//============================================================================
if((CLSID_WMIProvider != rclsid) && (CLSID_WMIEventProvider != rclsid) && (CLSID_WMIHiPerfProvider != rclsid) )
{
hr = E_FAIL;
}
else
{
//============================================================================
// Check that we can provide the interface.
//============================================================================
if (IID_IUnknown != riid && IID_IClassFactory != riid)
{
hr = E_NOINTERFACE;
}
else
{
CAutoBlock block (g_pLoadUnloadCs);
//============================================================================
// Get a new class factory.
//============================================================================
pFactory=new CProvFactory(rclsid);
if (NULL!=pFactory)
{
//============================================================================
// Verify we can get an instance.
//============================================================================
hr = pFactory->QueryInterface(riid, ppv);
if ( FAILED ( hr ) )
{
SAFE_DELETE_PTR(pFactory);
}
else
{
//
// it is safe to check if this is 1st object like this
// as there is no way any provider or class factory is
// incrementing global refrence count
//
if ( 1 == g_cObj )
{
//
// GlobalInterfaceTable
//
hr = CoCreateInstance ( CLSID_StdGlobalInterfaceTable,
NULL,
CLSCTX_INPROC_SERVER,
IID_IGlobalInterfaceTable,
(void**)&g_pGIT
);
//
// bail out every resource
//
if ( FAILED ( hr ) )
{
SAFE_DELETE_PTR(pFactory);
SAFE_RELEASE_PTR(g_pGIT);
}
}
}
}
}
}
}
STANDARD_CATCH
return hr;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
//
// DllCanUnloadNow
//
// Purpose: Called periodically by Ole in order to determine if the
// DLL can be freed.//
// Return: TRUE if there are no objects in use and the class factory
// isn't locked.
/////////////////////////////////////////////////////////////////////////////////////////////////
STDAPI DllCanUnloadNow(void)
{
HRESULT sc = S_FALSE ;
try
{
CAutoBlock block (g_pLoadUnloadCs);
//============================================================================
// It is OK to unload if there are no objects or locks on the
// class factory.
//============================================================================
if ( 0L == g_cObj && 0L == g_cLock )
{
sc = S_OK ;
SAFE_RELEASE_PTR(g_pGIT);
}
}
catch ( ... )
{
}
return sc;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
//
// CreateKey
//
// Purpose: Function to create a key
//
// Return: NOERROR if registration successful, error otherwise.
//
/////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CreateKey(TCHAR * szCLSID, TCHAR * szName)
{
HKEY hKey1, hKey2;
HRESULT hr = S_OK;
#ifdef LOCALSERVER
HKEY hKey;
TCHAR szProviderCLSIDAppID[128];
if ( SUCCEEDED ( hr = StringCchPrintf ( szProviderCLSIDAppID, 128, _T("SOFTWARE\\CLASSES\\APPID\\%s"), szName ) ) )
{
hr = RegCreateKeyEx (
HKEY_LOCAL_MACHINE,
szProviderCLSIDAppID,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hKey,
NULL
);
if( ERROR_SUCCESS == hr )
{
RegSetValueEx(hKey, NULL, 0, REG_SZ, (BYTE *)szName, (_tcsclen(szName) + 1) * sizeof(TCHAR));
CloseHandle(hKey);
}
else
{
hr = HRESULT_FROM_WIN32 ( hr );
}
}
#endif
if( S_OK == hr )
{
hr = RegCreateKeyEx (
HKEY_CLASSES_ROOT,
szCLSID,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hKey1,
NULL
);
if( ERROR_SUCCESS == hr )
{
DWORD dwLen;
dwLen = (_tcsclen(szName)+1) * sizeof(TCHAR);
hr = RegSetValueEx(hKey1, NULL, 0, REG_SZ, (CONST BYTE *)szName, dwLen);
if( ERROR_SUCCESS == hr )
{
#ifdef LOCALSERVER
hr = RegCreateKeyEx (
hKey1,
_T("LocalServer32"),
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hKey2,
NULL
);
#else
hr = RegCreateKeyEx (
hKey1,
_T("InprocServer32"),
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hKey2,
NULL
);
#endif
if( ERROR_SUCCESS == hr )
{
TCHAR szModule [MAX_PATH+1];
szModule [MAX_PATH] = 0;
if ( GetModuleFileName(ghModule, szModule, MAX_PATH) )
{
dwLen = (_tcsclen(szModule)+1) * sizeof(TCHAR);
hr = RegSetValueEx(hKey2, NULL, 0, REG_SZ, (CONST BYTE *)szModule, dwLen );
if( ERROR_SUCCESS == hr )
{
dwLen = (_tcsclen(_T("Both"))+1) * sizeof(TCHAR);
hr = RegSetValueEx(hKey2, _T("ThreadingModel"), 0, REG_SZ,(CONST BYTE *)_T("Both"), dwLen);
}
else
{
hr = HRESULT_FROM_WIN32 ( hr );
}
}
else
{
hr = HRESULT_FROM_WIN32 ( ::GetLastError () );
}
CloseHandle(hKey2);
}
else
{
hr = HRESULT_FROM_WIN32 ( hr );
}
}
CloseHandle(hKey1);
}
else
{
hr = HRESULT_FROM_WIN32 ( hr );
}
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
#ifdef _X86_
BOOL IsReallyWOW64( void )
{
// Environment variable should only exist on WOW64
return ( GetEnvironmentVariable( L"PROCESSOR_ARCHITEW6432", 0L, NULL ) != 0L );
}
#endif
STDAPI DllRegisterServer(void)
{
WCHAR wcID[128];
TCHAR szCLSID[128];
HRESULT hr = WBEM_E_FAILED;
SetStructuredExceptionHandler seh;
try{
#ifdef _X86
if (!IsReallyWOW64())
{
// on 32-bit builds, we want to register everything if we are not really running in syswow64
#endif
//==============================================
// Create keys for WDM Instance Provider.
//==============================================
StringFromGUID2(CLSID_WMIProvider, wcID, 128);
StringCchPrintf(szCLSID, 128, _T("CLSID\\%s"), wcID);
hr = CreateKey(szCLSID,_T("WDM Instance Provider"));
if( ERROR_SUCCESS == hr )
{
//==============================================
// Create keys for WDM Event Provider.
//==============================================
StringFromGUID2(CLSID_WMIEventProvider, wcID, 128);
StringCchPrintf(szCLSID, 128, _T("CLSID\\%s"), wcID);
hr = CreateKey(szCLSID,_T("WDM Event Provider"));
if( ERROR_SUCCESS == hr )
{
//==============================================
// Create keys for WDM HiPerf Provider.
//==============================================
StringFromGUID2(CLSID_WMIHiPerfProvider, wcID, 128);
StringCchPrintf(szCLSID, 128, _T("CLSID\\%s"), wcID);
hr = CreateKey(szCLSID,_T("WDM HiPerf Provider"));
}
}
#ifdef _X86
}
else
{
// on 32-bit builds, we want to register only the HiPerf Provider if we are really running in syswow64
//==============================================
// Create keys for WDM HiPerf Provider.
//==============================================
StringFromGUID2(CLSID_WMIHiPerfProvider, wcID, 128);
StringCchPrintf(szCLSID, 128, _T("CLSID\\%s"), wcID);
hr = CreateKey(szCLSID,_T("WDM HiPerf Provider"));
}
#endif
}
STANDARD_CATCH
return hr;
}
/////////////////////////////////////////////////////////////////////////////////////
//
// DeleteKey
//
// Purpose: Called when it is time to remove the registry entries.
//
// Return: NOERROR if registration successful, error otherwise.
//
/////////////////////////////////////////////////////////////////////////////////////
HRESULT DeleteKey(TCHAR * pCLSID, TCHAR * pID)
{
HKEY hKey;
HRESULT hr = S_OK;
#ifdef LOCALSERVER
TCHAR szTmp[MAX_PATH];
StringCchPrintf(szTmp, MAX_PATH, _T("SOFTWARE\\CLASSES\\APPID\\%s"), pID);
//Delete entries under APPID
hr = RegDeleteKey(HKEY_LOCAL_MACHINE, szTmp);
if( ERROR_SUCCESS == hr )
{
StringCchPrintf(szTmp, MAX_PATH, _T("%s\\LocalServer32"), pCLSID);
hr = RegDeleteKey(HKEY_CLASSES_ROOT, szTemp);
}
#endif
hr = RegOpenKey(HKEY_CLASSES_ROOT, pCLSID, &hKey);
if(NO_ERROR == hr)
{
hr = RegDeleteKey(hKey,_T("InprocServer32"));
CloseHandle(hKey);
}
hr = RegOpenKey(HKEY_CLASSES_ROOT, _T("CLSID"), &hKey);
if(NO_ERROR == hr)
{
hr = RegDeleteKey(hKey,pID);
CloseHandle(hKey);
}
return hr;
}
/////////////////////////////////////////////////////////////////////
STDAPI DllUnregisterServer(void)
{
WCHAR wcID[128];
TCHAR strCLSID[MAX_PATH];
HRESULT hr = WBEM_E_FAILED;
try
{
#ifdef _X86
if (!IsReallyWOW64())
{
// on 32-bit builds, we want to unregister everything if we are not really running in syswow64
#endif
//===============================================
// Delete the WMI Instance Provider
//===============================================
StringFromGUID2(CLSID_WMIProvider, wcID, 128);
StringCchPrintf(strCLSID, MAX_PATH, _T("CLSID\\%s"), wcID);
hr = DeleteKey(strCLSID, wcID);
if( ERROR_SUCCESS == hr )
{
//==========================================
// Delete the WMI Event Provider
//==========================================
StringFromGUID2(CLSID_WMIEventProvider, wcID, 128);
StringCchPrintf(strCLSID, MAX_PATH, _T("CLSID\\%s"), wcID);
hr = DeleteKey(strCLSID,wcID);
if( ERROR_SUCCESS == hr )
{
//==========================================
// Delete the WMI HiPerf Provider
//==========================================
StringFromGUID2(CLSID_WMIHiPerfProvider, wcID, 128);
StringCchPrintf(strCLSID, MAX_PATH, _T("CLSID\\%s"), wcID);
hr = DeleteKey(strCLSID,wcID);
}
}
#ifdef _X86
}
else
{
// on 32-bit builds, we need to unregister only the HiPerf provider if we are really running in syswow64
//==========================================
// Delete the WMI HiPerf Provider
//==========================================
StringFromGUID2(CLSID_WMIHiPerfProvider, wcID, 128);
StringCchPrintf(strCLSID, MAX_PATH, _T("CLSID\\%s"), wcID);
hr = DeleteKey(strCLSID,wcID);
}
#endif
}
STANDARD_CATCH
return hr;
}