Source code of Windows XP (NT5)
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.

367 lines
11 KiB

  1. //***************************************************************************
  2. // Copyright (c) Microsoft Corporation
  3. //
  4. // Module Name:
  5. // EventConsumerProvider.CPP
  6. //
  7. // Abstract:
  8. // Contains DLL entry points. code that controls
  9. // when the DLL can be unloaded by tracking the number of
  10. // objects and locks as well as routines that support
  11. // self registration.
  12. //
  13. // Author:
  14. // Vasundhara .G
  15. //
  16. // Revision History:
  17. // Vasundhara .G 9-oct-2k : Created It.
  18. //***************************************************************************
  19. #include "pch.h"
  20. #include "EventConsumerProvider.h"
  21. #include "TriggerFactory.h"
  22. //
  23. // constants / defines / enumerations
  24. //
  25. #define THREAD_MODEL_BOTH _T( "Both" )
  26. #define THREAD_MODEL_APARTMENT _T( "Apartment" )
  27. #define RUNAS_INTERACTIVEUSER _T( "Interactive User" )
  28. #define FMT_CLS_ID _T( "CLSID\\%s" )
  29. #define FMT_APP_ID _T( "APPID\\%s" )
  30. #define PROVIDER_TITLE _T( "Command line Trigger Consumer" )
  31. #define KEY_INPROCSERVER32 _T( "InprocServer32" )
  32. #define KEY_THREADINGMODEL _T( "ThreadingModel" )
  33. #define KEY_CLSID _T( "CLSID" )
  34. #define KEY_APPID _T( "APPID" )
  35. #define KEY_RUNAS _T( "RunAs" )
  36. #define KAY_DLLSURROGATE _T( "DllSurrogate" )
  37. //
  38. // global variables
  39. //
  40. DWORD g_dwLocks = 0; // holds the active locks count
  41. DWORD g_dwInstances = 0; // holds the active instances of the component
  42. HMODULE g_hModule = NULL; // holds the current module handle
  43. CRITICAL_SECTION g_critical_sec; // critical section variable
  44. DWORD g_criticalsec_count = 0; // to keep tab on when to release critical section
  45. // {797EF3B3-127B-4283-8096-1E8084BF67A6}
  46. DEFINE_GUID( CLSID_EventTriggersConsumerProvider,
  47. 0x797ef3b3, 0x127b, 0x4283, 0x80, 0x96, 0x1e, 0x80, 0x84, 0xbf, 0x67, 0xa6 );
  48. //
  49. // dll entry point
  50. //
  51. // *************************************************************************
  52. // Routine Description:
  53. // Entry point for dll.
  54. //
  55. // Arguments:
  56. // hModule [in] : Instance of the caller.
  57. // ul_reason_for_call [in] : Reason being called like process attach
  58. // or process detach.
  59. // lpReserved [in] : reserved.
  60. //
  61. // Return Value:
  62. // TRUE if loading is successful.
  63. // FALSE if loading fails.
  64. // *************************************************************************
  65. BOOL WINAPI DllMain( HINSTANCE hModule, DWORD ul_reason_for_call, LPVOID lpReserved )
  66. {
  67. // check the reason for this function call
  68. // if this going to be attached to a process, save the module handle
  69. if ( ul_reason_for_call == DLL_PROCESS_ATTACH )
  70. {
  71. g_hModule = hModule;
  72. InitializeCriticalSection( &g_critical_sec );
  73. InterlockedIncrement( ( LPLONG ) &g_criticalsec_count );
  74. }
  75. else if ( ul_reason_for_call == DLL_PROCESS_DETACH )
  76. {
  77. if ( InterlockedDecrement( ( LPLONG ) &g_criticalsec_count ) == 0 )
  78. {
  79. DeleteCriticalSection( &g_critical_sec );
  80. }
  81. }
  82. // dll loaded successfully ... inform the same
  83. return TRUE;
  84. }
  85. //
  86. // exported functions
  87. //
  88. // *************************************************************************
  89. // Routine Description:
  90. // Called periodically by OLE in order to determine if the DLL can be freed.
  91. //
  92. // Arguments:
  93. // none.
  94. //
  95. // Return Value:
  96. // S_OK if there are no objects in use and the class factory isn't locked.
  97. // S_FALSE if server locks or components still exsists.
  98. // *************************************************************************
  99. STDAPI DllCanUnloadNow()
  100. {
  101. // the dll cannot be unloaded if there are any server locks or active instances
  102. if ( g_dwLocks == 0 && g_dwInstances == 0 )
  103. {
  104. return S_OK;
  105. }
  106. // dll cannot be unloaded ... server locks (or) components still alive
  107. return S_FALSE;
  108. }
  109. // *************************************************************************
  110. // Routine Description:
  111. // Called by OLE when some client wants a class factory.
  112. // Return one only if it is the sort of class this DLL supports.
  113. //
  114. // Arguments:
  115. // rclsid [in] : CLSID for the class object.
  116. // riid [in] : Reference to the identifier of the interface
  117. // that communicates with the class object.
  118. // ppv [out] : Address of output variable that receives the
  119. // interface pointer requested in riid.
  120. //
  121. // Return Value:
  122. // returns status.
  123. // *************************************************************************
  124. STDAPI DllGetClassObject( REFCLSID rclsid, REFIID riid, LPVOID* ppv )
  125. {
  126. // local variables
  127. HRESULT hr = NULL;
  128. CTriggerFactory* pFactory = NULL;
  129. // check whether this module supports the requested class id
  130. if ( rclsid != CLSID_EventTriggersConsumerProvider )
  131. {
  132. return E_FAIL; // not supported by this module
  133. }
  134. // create the factory
  135. pFactory = new CTriggerFactory();
  136. if ( pFactory == NULL )
  137. {
  138. return E_OUTOFMEMORY; // insufficient memory
  139. }
  140. // get the requested interface
  141. hr = pFactory->QueryInterface( riid, ppv );
  142. if ( FAILED( hr ) )
  143. {
  144. delete pFactory; // error getting interface ... deallocate memory
  145. }
  146. // return the result (appropriate result)
  147. return hr;
  148. }
  149. // *************************************************************************
  150. // Routine Description:
  151. // Called during setup or by regsvr32.
  152. //
  153. // Arguments:
  154. // none.
  155. //
  156. // Return Value:
  157. // NOERROR.
  158. // *************************************************************************
  159. STDAPI DllRegisterServer()
  160. {
  161. // local variables
  162. HKEY hkMain = NULL;
  163. HKEY hkDetails = NULL;
  164. TCHAR szID[ LENGTH_UUID ] = NULL_STRING;
  165. TCHAR szCLSID[ LENGTH_UUID ] = NULL_STRING;
  166. TCHAR szAppID[ LENGTH_UUID ] = NULL_STRING;
  167. TCHAR szModule[ MAX_PATH ] = NULL_STRING;
  168. TCHAR szTitle[ MAX_STRING_LENGTH ] = NULL_STRING;
  169. TCHAR szThreadingModel[ MAX_STRING_LENGTH ] = NULL_STRING;
  170. TCHAR szRunAs[ MAX_STRING_LENGTH ] = NULL_STRING;
  171. DWORD dwResult = 0;
  172. // kick off
  173. // Note:-
  174. // Normally we want to use "Both" as the threading model since
  175. // the DLL is free threaded, but NT 3.51 Ole doesnt work unless
  176. // the model is "Aparment"
  177. lstrcpy( szTitle, PROVIDER_TITLE ); // provider title
  178. GetModuleFileName( g_hModule, szModule, MAX_PATH ); // get the current module name
  179. lstrcpy( szThreadingModel, THREAD_MODEL_BOTH );
  180. lstrcpy( szRunAs, RUNAS_INTERACTIVEUSER );
  181. //
  182. // create the class id path
  183. #ifdef UNICODE
  184. // get the GUID in the string format
  185. StringFromGUID2( CLSID_EventTriggersConsumerProvider, szID, LENGTH_UUID );
  186. #else
  187. // StrignFromGUID2 will return the value in UNICODE version
  188. // but, as the current version is of non UNICODE we need to convert the
  189. // value into multi-byte character set and then use it
  190. WCHAR wszID[ LENGTH_UUID ] = L"\0";
  191. StringFromGUID2( CLSID_EventTriggersConsumerProvider, wszID, LENGTH_UUID );
  192. wcstombs( szID, wszID, LENGTH_UUID ); // unicode -> mbcs conversion
  193. #endif // UNICODE
  194. // finally form the class id path
  195. wsprintf( szCLSID, FMT_CLS_ID, szID );
  196. wsprintf( szAppID, FMT_APP_ID, szID );
  197. //
  198. // now, create the entries in registry under CLSID branch
  199. // create / save / put class id information
  200. dwResult = RegCreateKey( HKEY_CLASSES_ROOT, szCLSID, &hkMain );
  201. if( dwResult != ERROR_SUCCESS )
  202. {
  203. return dwResult; // failed in opening the key.
  204. }
  205. dwResult = RegSetValueEx( hkMain, NULL, 0, REG_SZ,
  206. ( LPBYTE ) szTitle, ( lstrlen( szTitle ) + 1 ) * sizeof( TCHAR ) );
  207. if( dwResult != ERROR_SUCCESS )
  208. {
  209. RegCloseKey( hkMain );
  210. return dwResult; // failed to set key value.
  211. }
  212. // now create the server information
  213. dwResult = RegCreateKey( hkMain, KEY_INPROCSERVER32, &hkDetails );
  214. if( dwResult != ERROR_SUCCESS )
  215. { RegCloseKey( hkMain );
  216. return dwResult; // failed in opening the key.
  217. }
  218. dwResult = RegSetValueEx( hkDetails, NULL, 0, REG_SZ,
  219. ( LPBYTE ) szModule, ( lstrlen( szModule ) + 1 ) * sizeof( TCHAR ) );
  220. if( dwResult != ERROR_SUCCESS )
  221. { RegCloseKey( hkMain );
  222. RegCloseKey( hkDetails );
  223. return dwResult; // failed to set key value.
  224. }
  225. // set the threading model we support
  226. dwResult = RegSetValueEx( hkDetails, KEY_THREADINGMODEL, 0, REG_SZ,
  227. ( LPBYTE ) szThreadingModel, ( lstrlen( szThreadingModel ) + 1 ) * sizeof( TCHAR ) );
  228. if( dwResult != ERROR_SUCCESS )
  229. { RegCloseKey( hkMain );
  230. RegCloseKey( hkDetails );
  231. return dwResult; // failed to set key value.
  232. }
  233. // close the open register keys
  234. RegCloseKey( hkMain );
  235. RegCloseKey( hkDetails );
  236. //
  237. // now, create the entries in registry under AppID branch
  238. // create / save / put class id information
  239. dwResult = RegCreateKey( HKEY_CLASSES_ROOT, szAppID, &hkMain );
  240. if(dwResult != ERROR_SUCCESS )
  241. {
  242. return dwResult;
  243. }
  244. dwResult = RegSetValueEx( hkMain, NULL, 0, REG_SZ,
  245. ( LPBYTE ) szTitle, ( lstrlen( szTitle ) + 1 ) * sizeof( TCHAR ) );
  246. if( dwResult != ERROR_SUCCESS )
  247. {
  248. RegCloseKey( hkMain );
  249. return dwResult;
  250. }
  251. // now set run as information
  252. dwResult = RegSetValueEx( hkMain, KEY_RUNAS, 0, REG_SZ,
  253. ( LPBYTE ) szRunAs, ( lstrlen( szRunAs ) + 1 ) * sizeof( TCHAR ) );
  254. if( dwResult != ERROR_SUCCESS )
  255. {
  256. RegCloseKey( hkMain );
  257. return dwResult;
  258. }
  259. // close the open register keys
  260. RegCloseKey( hkMain );
  261. // registration is successfull ... inform the same
  262. return NOERROR;
  263. }
  264. // *************************************************************************
  265. // Routine Description:
  266. // Called when it is time to remove the registry entries.
  267. //
  268. // Arguments:
  269. // none.
  270. //
  271. // Return Value:
  272. // NOERROR if unregistration successful.
  273. // Otherwise error.
  274. // *************************************************************************
  275. STDAPI DllUnregisterServer()
  276. {
  277. // local variables
  278. HKEY hKey;
  279. DWORD dwResult = 0;
  280. TCHAR szID[ LENGTH_UUID ];
  281. TCHAR szCLSID[ LENGTH_UUID ];
  282. TCHAR szAppID[ LENGTH_UUID ] = NULL_STRING;
  283. //
  284. // create the class id path
  285. #ifdef UNICODE
  286. StringFromGUID2( CLSID_EventTriggersConsumerProvider, szID, LENGTH_UUID );
  287. #else
  288. // StrignFromGUID2 will return the value in UNICODE version
  289. // but, as the current version is of non UNICODE we need to convert the
  290. // value into multi-byte character set and then use it
  291. WCHAR wszID[ LENGTH_UUID ] = L"\0";
  292. StringFromGUID2( CLSID_EventTriggersConsumerProvider, wszID, LENGTH_UUID );
  293. wcstombs( szID, wszID, LENGTH_UUID ); // unicode -> mbcs conversion
  294. #endif // UNICODE
  295. // finally form the class id path
  296. wsprintf( szCLSID, FMT_CLS_ID, szID );
  297. wsprintf( szAppID, FMT_APP_ID, szID );
  298. // open the clsid
  299. dwResult = RegOpenKey( HKEY_CLASSES_ROOT, szCLSID, &hKey );
  300. if ( dwResult != NO_ERROR )
  301. {
  302. return dwResult; // failed in opening the key ... inform the same
  303. }
  304. // clsid opened ... first delete the InProcServer32
  305. RegDeleteKey( hKey, KEY_INPROCSERVER32 );
  306. // now delete the clsid
  307. dwResult = RegOpenKey( HKEY_CLASSES_ROOT, KEY_CLSID, &hKey );
  308. if ( dwResult != NO_ERROR )
  309. {
  310. return dwResult; // failed in opening the key ... inform the same
  311. }
  312. // delete the clsid also from the registry
  313. RegDeleteKey( hKey, szID );
  314. // now delete the appid
  315. dwResult = RegOpenKey( HKEY_CLASSES_ROOT, KEY_APPID, &hKey );
  316. if ( dwResult != NO_ERROR )
  317. {
  318. return dwResult; // failed in opening the key ... inform the same
  319. }
  320. // delete the cls id also from the registry
  321. RegDeleteKey( hKey, szID );
  322. // unregistration is successfull ... inform the same
  323. return NOERROR;
  324. }