368 lines
11 KiB
C++
368 lines
11 KiB
C++
|
//***************************************************************************
|
||
|
// Copyright (c) Microsoft Corporation
|
||
|
//
|
||
|
// Module Name:
|
||
|
// EventConsumerProvider.CPP
|
||
|
//
|
||
|
// Abstract:
|
||
|
// Contains DLL entry points. 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.
|
||
|
//
|
||
|
// Author:
|
||
|
// Vasundhara .G
|
||
|
//
|
||
|
// Revision History:
|
||
|
// Vasundhara .G 9-oct-2k : Created It.
|
||
|
//***************************************************************************
|
||
|
|
||
|
#include "pch.h"
|
||
|
#include "EventConsumerProvider.h"
|
||
|
#include "TriggerFactory.h"
|
||
|
|
||
|
//
|
||
|
// constants / defines / enumerations
|
||
|
//
|
||
|
#define THREAD_MODEL_BOTH _T( "Both" )
|
||
|
#define THREAD_MODEL_APARTMENT _T( "Apartment" )
|
||
|
#define RUNAS_INTERACTIVEUSER _T( "Interactive User" )
|
||
|
#define FMT_CLS_ID _T( "CLSID\\%s" )
|
||
|
#define FMT_APP_ID _T( "APPID\\%s" )
|
||
|
#define PROVIDER_TITLE _T( "Command line Trigger Consumer" )
|
||
|
|
||
|
#define KEY_INPROCSERVER32 _T( "InprocServer32" )
|
||
|
#define KEY_THREADINGMODEL _T( "ThreadingModel" )
|
||
|
#define KEY_CLSID _T( "CLSID" )
|
||
|
#define KEY_APPID _T( "APPID" )
|
||
|
#define KEY_RUNAS _T( "RunAs" )
|
||
|
#define KAY_DLLSURROGATE _T( "DllSurrogate" )
|
||
|
|
||
|
|
||
|
//
|
||
|
// global variables
|
||
|
//
|
||
|
DWORD g_dwLocks = 0; // holds the active locks count
|
||
|
DWORD g_dwInstances = 0; // holds the active instances of the component
|
||
|
HMODULE g_hModule = NULL; // holds the current module handle
|
||
|
CRITICAL_SECTION g_critical_sec; // critical section variable
|
||
|
DWORD g_criticalsec_count = 0; // to keep tab on when to release critical section
|
||
|
|
||
|
// {797EF3B3-127B-4283-8096-1E8084BF67A6}
|
||
|
DEFINE_GUID( CLSID_EventTriggersConsumerProvider,
|
||
|
0x797ef3b3, 0x127b, 0x4283, 0x80, 0x96, 0x1e, 0x80, 0x84, 0xbf, 0x67, 0xa6 );
|
||
|
|
||
|
//
|
||
|
// dll entry point
|
||
|
//
|
||
|
|
||
|
// *************************************************************************
|
||
|
// Routine Description:
|
||
|
// Entry point for dll.
|
||
|
//
|
||
|
// Arguments:
|
||
|
// hModule [in] : Instance of the caller.
|
||
|
// ul_reason_for_call [in] : Reason being called like process attach
|
||
|
// or process detach.
|
||
|
// lpReserved [in] : reserved.
|
||
|
//
|
||
|
// Return Value:
|
||
|
// TRUE if loading is successful.
|
||
|
// FALSE if loading fails.
|
||
|
// *************************************************************************
|
||
|
BOOL WINAPI DllMain( HINSTANCE hModule, DWORD ul_reason_for_call, LPVOID lpReserved )
|
||
|
{
|
||
|
// check the reason for this function call
|
||
|
// if this going to be attached to a process, save the module handle
|
||
|
if ( ul_reason_for_call == DLL_PROCESS_ATTACH )
|
||
|
{
|
||
|
g_hModule = hModule;
|
||
|
InitializeCriticalSection( &g_critical_sec );
|
||
|
InterlockedIncrement( ( LPLONG ) &g_criticalsec_count );
|
||
|
}
|
||
|
else if ( ul_reason_for_call == DLL_PROCESS_DETACH )
|
||
|
{
|
||
|
if ( InterlockedDecrement( ( LPLONG ) &g_criticalsec_count ) == 0 )
|
||
|
{
|
||
|
DeleteCriticalSection( &g_critical_sec );
|
||
|
}
|
||
|
}
|
||
|
// dll loaded successfully ... inform the same
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// exported functions
|
||
|
//
|
||
|
|
||
|
// *************************************************************************
|
||
|
// Routine Description:
|
||
|
// Called periodically by OLE in order to determine if the DLL can be freed.
|
||
|
//
|
||
|
// Arguments:
|
||
|
// none.
|
||
|
//
|
||
|
// Return Value:
|
||
|
// S_OK if there are no objects in use and the class factory isn't locked.
|
||
|
// S_FALSE if server locks or components still exsists.
|
||
|
// *************************************************************************
|
||
|
STDAPI DllCanUnloadNow()
|
||
|
{
|
||
|
// the dll cannot be unloaded if there are any server locks or active instances
|
||
|
if ( g_dwLocks == 0 && g_dwInstances == 0 )
|
||
|
{
|
||
|
return S_OK;
|
||
|
}
|
||
|
// dll cannot be unloaded ... server locks (or) components still alive
|
||
|
return S_FALSE;
|
||
|
}
|
||
|
|
||
|
// *************************************************************************
|
||
|
// Routine Description:
|
||
|
// Called by OLE when some client wants a class factory.
|
||
|
// Return one only if it is the sort of class this DLL supports.
|
||
|
//
|
||
|
// Arguments:
|
||
|
// rclsid [in] : CLSID for the class object.
|
||
|
// riid [in] : Reference to the identifier of the interface
|
||
|
// that communicates with the class object.
|
||
|
// ppv [out] : Address of output variable that receives the
|
||
|
// interface pointer requested in riid.
|
||
|
//
|
||
|
// Return Value:
|
||
|
// returns status.
|
||
|
// *************************************************************************
|
||
|
|
||
|
STDAPI DllGetClassObject( REFCLSID rclsid, REFIID riid, LPVOID* ppv )
|
||
|
{
|
||
|
// local variables
|
||
|
HRESULT hr = NULL;
|
||
|
CTriggerFactory* pFactory = NULL;
|
||
|
|
||
|
// check whether this module supports the requested class id
|
||
|
if ( rclsid != CLSID_EventTriggersConsumerProvider )
|
||
|
{
|
||
|
return E_FAIL; // not supported by this module
|
||
|
}
|
||
|
// create the factory
|
||
|
pFactory = new CTriggerFactory();
|
||
|
if ( pFactory == NULL )
|
||
|
{
|
||
|
return E_OUTOFMEMORY; // insufficient memory
|
||
|
}
|
||
|
// get the requested interface
|
||
|
hr = pFactory->QueryInterface( riid, ppv );
|
||
|
if ( FAILED( hr ) )
|
||
|
{
|
||
|
delete pFactory; // error getting interface ... deallocate memory
|
||
|
}
|
||
|
// return the result (appropriate result)
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
// *************************************************************************
|
||
|
// Routine Description:
|
||
|
// Called during setup or by regsvr32.
|
||
|
//
|
||
|
// Arguments:
|
||
|
// none.
|
||
|
//
|
||
|
// Return Value:
|
||
|
// NOERROR.
|
||
|
// *************************************************************************
|
||
|
|
||
|
STDAPI DllRegisterServer()
|
||
|
{
|
||
|
// local variables
|
||
|
HKEY hkMain = NULL;
|
||
|
HKEY hkDetails = NULL;
|
||
|
TCHAR szID[ LENGTH_UUID ] = NULL_STRING;
|
||
|
TCHAR szCLSID[ LENGTH_UUID ] = NULL_STRING;
|
||
|
TCHAR szAppID[ LENGTH_UUID ] = NULL_STRING;
|
||
|
TCHAR szModule[ MAX_PATH ] = NULL_STRING;
|
||
|
TCHAR szTitle[ MAX_STRING_LENGTH ] = NULL_STRING;
|
||
|
TCHAR szThreadingModel[ MAX_STRING_LENGTH ] = NULL_STRING;
|
||
|
TCHAR szRunAs[ MAX_STRING_LENGTH ] = NULL_STRING;
|
||
|
DWORD dwResult = 0;
|
||
|
|
||
|
// kick off
|
||
|
// Note:-
|
||
|
// Normally we want to use "Both" as the threading model since
|
||
|
// the DLL is free threaded, but NT 3.51 Ole doesnt work unless
|
||
|
// the model is "Aparment"
|
||
|
lstrcpy( szTitle, PROVIDER_TITLE ); // provider title
|
||
|
GetModuleFileName( g_hModule, szModule, MAX_PATH ); // get the current module name
|
||
|
lstrcpy( szThreadingModel, THREAD_MODEL_BOTH );
|
||
|
lstrcpy( szRunAs, RUNAS_INTERACTIVEUSER );
|
||
|
|
||
|
//
|
||
|
// create the class id path
|
||
|
|
||
|
#ifdef UNICODE
|
||
|
|
||
|
// get the GUID in the string format
|
||
|
StringFromGUID2( CLSID_EventTriggersConsumerProvider, szID, LENGTH_UUID );
|
||
|
#else
|
||
|
|
||
|
// StrignFromGUID2 will return the value in UNICODE version
|
||
|
// but, as the current version is of non UNICODE we need to convert the
|
||
|
// value into multi-byte character set and then use it
|
||
|
WCHAR wszID[ LENGTH_UUID ] = L"\0";
|
||
|
StringFromGUID2( CLSID_EventTriggersConsumerProvider, wszID, LENGTH_UUID );
|
||
|
wcstombs( szID, wszID, LENGTH_UUID ); // unicode -> mbcs conversion
|
||
|
#endif // UNICODE
|
||
|
|
||
|
// finally form the class id path
|
||
|
wsprintf( szCLSID, FMT_CLS_ID, szID );
|
||
|
wsprintf( szAppID, FMT_APP_ID, szID );
|
||
|
|
||
|
//
|
||
|
// now, create the entries in registry under CLSID branch
|
||
|
|
||
|
// create / save / put class id information
|
||
|
dwResult = RegCreateKey( HKEY_CLASSES_ROOT, szCLSID, &hkMain );
|
||
|
if( dwResult != ERROR_SUCCESS )
|
||
|
{
|
||
|
return dwResult; // failed in opening the key.
|
||
|
}
|
||
|
dwResult = RegSetValueEx( hkMain, NULL, 0, REG_SZ,
|
||
|
( LPBYTE ) szTitle, ( lstrlen( szTitle ) + 1 ) * sizeof( TCHAR ) );
|
||
|
if( dwResult != ERROR_SUCCESS )
|
||
|
{
|
||
|
RegCloseKey( hkMain );
|
||
|
return dwResult; // failed to set key value.
|
||
|
}
|
||
|
|
||
|
// now create the server information
|
||
|
dwResult = RegCreateKey( hkMain, KEY_INPROCSERVER32, &hkDetails );
|
||
|
if( dwResult != ERROR_SUCCESS )
|
||
|
{ RegCloseKey( hkMain );
|
||
|
return dwResult; // failed in opening the key.
|
||
|
}
|
||
|
|
||
|
dwResult = RegSetValueEx( hkDetails, NULL, 0, REG_SZ,
|
||
|
( LPBYTE ) szModule, ( lstrlen( szModule ) + 1 ) * sizeof( TCHAR ) );
|
||
|
if( dwResult != ERROR_SUCCESS )
|
||
|
{ RegCloseKey( hkMain );
|
||
|
RegCloseKey( hkDetails );
|
||
|
return dwResult; // failed to set key value.
|
||
|
}
|
||
|
|
||
|
// set the threading model we support
|
||
|
dwResult = RegSetValueEx( hkDetails, KEY_THREADINGMODEL, 0, REG_SZ,
|
||
|
( LPBYTE ) szThreadingModel, ( lstrlen( szThreadingModel ) + 1 ) * sizeof( TCHAR ) );
|
||
|
if( dwResult != ERROR_SUCCESS )
|
||
|
{ RegCloseKey( hkMain );
|
||
|
RegCloseKey( hkDetails );
|
||
|
return dwResult; // failed to set key value.
|
||
|
}
|
||
|
|
||
|
// close the open register keys
|
||
|
RegCloseKey( hkMain );
|
||
|
RegCloseKey( hkDetails );
|
||
|
|
||
|
//
|
||
|
// now, create the entries in registry under AppID branch
|
||
|
// create / save / put class id information
|
||
|
dwResult = RegCreateKey( HKEY_CLASSES_ROOT, szAppID, &hkMain );
|
||
|
if(dwResult != ERROR_SUCCESS )
|
||
|
{
|
||
|
return dwResult;
|
||
|
}
|
||
|
dwResult = RegSetValueEx( hkMain, NULL, 0, REG_SZ,
|
||
|
( LPBYTE ) szTitle, ( lstrlen( szTitle ) + 1 ) * sizeof( TCHAR ) );
|
||
|
if( dwResult != ERROR_SUCCESS )
|
||
|
{
|
||
|
RegCloseKey( hkMain );
|
||
|
return dwResult;
|
||
|
}
|
||
|
|
||
|
// now set run as information
|
||
|
dwResult = RegSetValueEx( hkMain, KEY_RUNAS, 0, REG_SZ,
|
||
|
( LPBYTE ) szRunAs, ( lstrlen( szRunAs ) + 1 ) * sizeof( TCHAR ) );
|
||
|
if( dwResult != ERROR_SUCCESS )
|
||
|
{
|
||
|
RegCloseKey( hkMain );
|
||
|
return dwResult;
|
||
|
}
|
||
|
// close the open register keys
|
||
|
RegCloseKey( hkMain );
|
||
|
|
||
|
// registration is successfull ... inform the same
|
||
|
return NOERROR;
|
||
|
}
|
||
|
|
||
|
// *************************************************************************
|
||
|
// Routine Description:
|
||
|
// Called when it is time to remove the registry entries.
|
||
|
//
|
||
|
// Arguments:
|
||
|
// none.
|
||
|
//
|
||
|
// Return Value:
|
||
|
// NOERROR if unregistration successful.
|
||
|
// Otherwise error.
|
||
|
// *************************************************************************
|
||
|
|
||
|
STDAPI DllUnregisterServer()
|
||
|
{
|
||
|
// local variables
|
||
|
HKEY hKey;
|
||
|
DWORD dwResult = 0;
|
||
|
TCHAR szID[ LENGTH_UUID ];
|
||
|
TCHAR szCLSID[ LENGTH_UUID ];
|
||
|
TCHAR szAppID[ LENGTH_UUID ] = NULL_STRING;
|
||
|
|
||
|
//
|
||
|
// create the class id path
|
||
|
|
||
|
#ifdef UNICODE
|
||
|
|
||
|
StringFromGUID2( CLSID_EventTriggersConsumerProvider, szID, LENGTH_UUID );
|
||
|
#else
|
||
|
|
||
|
// StrignFromGUID2 will return the value in UNICODE version
|
||
|
// but, as the current version is of non UNICODE we need to convert the
|
||
|
// value into multi-byte character set and then use it
|
||
|
WCHAR wszID[ LENGTH_UUID ] = L"\0";
|
||
|
StringFromGUID2( CLSID_EventTriggersConsumerProvider, wszID, LENGTH_UUID );
|
||
|
wcstombs( szID, wszID, LENGTH_UUID ); // unicode -> mbcs conversion
|
||
|
#endif // UNICODE
|
||
|
|
||
|
// finally form the class id path
|
||
|
wsprintf( szCLSID, FMT_CLS_ID, szID );
|
||
|
wsprintf( szAppID, FMT_APP_ID, szID );
|
||
|
|
||
|
// open the clsid
|
||
|
dwResult = RegOpenKey( HKEY_CLASSES_ROOT, szCLSID, &hKey );
|
||
|
if ( dwResult != NO_ERROR )
|
||
|
{
|
||
|
return dwResult; // failed in opening the key ... inform the same
|
||
|
}
|
||
|
// clsid opened ... first delete the InProcServer32
|
||
|
RegDeleteKey( hKey, KEY_INPROCSERVER32 );
|
||
|
|
||
|
// now delete the clsid
|
||
|
dwResult = RegOpenKey( HKEY_CLASSES_ROOT, KEY_CLSID, &hKey );
|
||
|
if ( dwResult != NO_ERROR )
|
||
|
{
|
||
|
return dwResult; // failed in opening the key ... inform the same
|
||
|
}
|
||
|
|
||
|
// delete the clsid also from the registry
|
||
|
RegDeleteKey( hKey, szID );
|
||
|
|
||
|
// now delete the appid
|
||
|
dwResult = RegOpenKey( HKEY_CLASSES_ROOT, KEY_APPID, &hKey );
|
||
|
if ( dwResult != NO_ERROR )
|
||
|
{
|
||
|
return dwResult; // failed in opening the key ... inform the same
|
||
|
}
|
||
|
|
||
|
// delete the cls id also from the registry
|
||
|
RegDeleteKey( hKey, szID );
|
||
|
|
||
|
// unregistration is successfull ... inform the same
|
||
|
return NOERROR;
|
||
|
}
|