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.

480 lines
11 KiB

  1. //***************************************************************************
  2. //
  3. // Copyright (c) 1996-2001, Microsoft Corporation, All rights reserved
  4. //
  5. // SERVER.CPP
  6. //
  7. // Generic COM server framework, adapted for the NT perf counter sample
  8. //
  9. // This module contains nothing specific to the NT perf counter provider
  10. // except what is defined in the section bracketed by the CLSID SPECIFIC
  11. // comments below.
  12. //
  13. // History:
  14. // raymcc 25-Nov-97 Created.
  15. // raymcc 18-Feb-98 Updated for NT5 Beta 2 version.
  16. //
  17. //***************************************************************************
  18. #include <windows.h>
  19. #include <stdio.h>
  20. #include <time.h>
  21. #include <initguid.h>
  22. /////////////////////////////////////////////////////////////////////////////
  23. //
  24. // BEGIN CLSID SPECIFIC SECTION
  25. //
  26. //
  27. #include <wbemidl.h>
  28. #include <evcons.h>
  29. // {4916157B-FBE7-11d1-AEC4-00C04FB68820}
  30. DEFINE_GUID(CLSID_MyEventConsumer,
  31. 0x4916157b, 0xfbe7, 0x11d1, 0xae, 0xc4, 0x0, 0xc0, 0x4f, 0xb6, 0x88, 0x20);
  32. #define IMPLEMENTED_CLSID CLSID_MyEventConsumer
  33. #define SERVER_REGISTRY_COMMENT L"WBEM Test Consumer"
  34. #define CPP_CLASS_NAME CMyEventConsumer
  35. #define INTERFACE_CAST (IWbemProviderInit *)
  36. //
  37. // END CLSID SPECIFIC SECTION
  38. //
  39. /////////////////////////////////////////////////////////////////////////////
  40. HINSTANCE g_hInstance;
  41. static ULONG g_cLock = 0;
  42. void ObjectCreated() { g_cLock++; }
  43. void ObjectDestroyed() { g_cLock--; }
  44. //***************************************************************************
  45. //
  46. // class CFactory
  47. //
  48. // Generic implementation of IClassFactory for CWbemLocator.
  49. //
  50. //***************************************************************************
  51. class CFactory : public IClassFactory
  52. {
  53. ULONG m_cRef;
  54. CLSID m_ClsId;
  55. public:
  56. CFactory(const CLSID & ClsId);
  57. ~CFactory();
  58. //
  59. // IUnknown members
  60. //
  61. STDMETHODIMP QueryInterface(REFIID, LPVOID *);
  62. STDMETHODIMP_(ULONG) AddRef(void);
  63. STDMETHODIMP_(ULONG) Release(void);
  64. //
  65. // IClassFactory members
  66. //
  67. STDMETHODIMP CreateInstance(LPUNKNOWN, REFIID, LPVOID *);
  68. STDMETHODIMP LockServer(BOOL);
  69. };
  70. //***************************************************************************
  71. //
  72. // DllMain
  73. //
  74. // Dll entry point.
  75. //
  76. // PARAMETERS:
  77. //
  78. // HINSTANCE hinstDLL The handle to our DLL.
  79. // DWORD dwReason DLL_PROCESS_ATTACH on load,
  80. // DLL_PROCESS_DETACH on shutdown,
  81. // DLL_THREAD_ATTACH/DLL_THREAD_DETACH otherwise.
  82. // LPVOID lpReserved Reserved
  83. //
  84. // RETURN VALUES:
  85. //
  86. // TRUE is successful, FALSE if a fatal error occured.
  87. // NT behaves very ugly if FALSE is returned.
  88. //
  89. //***************************************************************************
  90. BOOL WINAPI DllMain(
  91. HINSTANCE hinstDLL,
  92. DWORD dwReason,
  93. LPVOID lpReserved
  94. )
  95. {
  96. if (dwReason == DLL_PROCESS_ATTACH)
  97. {
  98. g_hInstance = hinstDLL;
  99. }
  100. else if (dwReason == DLL_PROCESS_DETACH)
  101. {
  102. }
  103. return TRUE;
  104. }
  105. //***************************************************************************
  106. //
  107. // DllGetClassObject
  108. //
  109. // Standard OLE In-Process Server entry point to return an class factory
  110. // instance.
  111. //
  112. // PARAMETERS:
  113. //
  114. // RETURNS:
  115. //
  116. // S_OK Success
  117. // E_NOINTERFACE An interface other that IClassFactory was asked for
  118. // E_OUTOFMEMORY
  119. // E_FAILED Initialization failed, or an unsupported clsid was
  120. // asked for.
  121. //
  122. //***************************************************************************
  123. extern "C"
  124. HRESULT APIENTRY DllGetClassObject(
  125. REFCLSID rclsid,
  126. REFIID riid,
  127. LPVOID * ppv
  128. )
  129. {
  130. CFactory *pFactory;
  131. //
  132. // Verify the caller is asking for our type of object.
  133. //
  134. if (IMPLEMENTED_CLSID != rclsid)
  135. return ResultFromScode(E_FAIL);
  136. //
  137. // Check that we can provide the interface.
  138. //
  139. if (IID_IUnknown != riid && IID_IClassFactory != riid)
  140. return ResultFromScode(E_NOINTERFACE);
  141. //
  142. // Get a new class factory.
  143. //
  144. pFactory = new CFactory(rclsid);
  145. if (!pFactory)
  146. return ResultFromScode(E_OUTOFMEMORY);
  147. //
  148. // Verify we can get an instance.
  149. //
  150. HRESULT hRes = pFactory->QueryInterface(riid, ppv);
  151. if (FAILED(hRes))
  152. delete pFactory;
  153. return hRes;
  154. }
  155. //***************************************************************************
  156. //
  157. // DllCanUnloadNow
  158. //
  159. // Standard OLE entry point for server shutdown request. Allows shutdown
  160. // only if no outstanding objects or locks are present.
  161. //
  162. // RETURN VALUES:
  163. //
  164. // S_OK May unload now.
  165. // S_FALSE May not.
  166. //
  167. //***************************************************************************
  168. extern "C"
  169. HRESULT APIENTRY DllCanUnloadNow(void)
  170. {
  171. SCODE sc = TRUE;
  172. if (g_cLock)
  173. sc = S_FALSE;
  174. return sc;
  175. }
  176. //***************************************************************************
  177. //
  178. // DllRegisterServer
  179. //
  180. // Standard OLE entry point for registering the server.
  181. //
  182. // RETURN VALUES:
  183. //
  184. // S_OK Registration was successful
  185. // E_FAIL Registration failed.
  186. //
  187. //***************************************************************************
  188. extern "C"
  189. HRESULT APIENTRY DllRegisterServer(void)
  190. {
  191. wchar_t Path[1024];
  192. wchar_t *pGuidStr = 0;
  193. wchar_t KeyPath[1024];
  194. // Where are we?
  195. // =============
  196. GetModuleFileNameW(g_hInstance, Path, 1024);
  197. // Convert CLSID to string.
  198. // ========================
  199. StringFromCLSID(IMPLEMENTED_CLSID, &pGuidStr);
  200. swprintf(KeyPath, L"Software\\Classes\\CLSID\\\\%s", pGuidStr);
  201. // Place it in registry.
  202. // CLSID\\CLSID_Nt5PerProvider_v1 : <no_name> : "name"
  203. // \\CLSID_Nt5PerProvider_v1\\InProcServer32 : <no_name> : "path to DLL"
  204. // : ThreadingModel : "both"
  205. // ==============================================================
  206. HKEY hKey;
  207. LONG lRes = RegCreateKeyW(HKEY_LOCAL_MACHINE, KeyPath, &hKey);
  208. if (lRes)
  209. return E_FAIL;
  210. wchar_t *pName = SERVER_REGISTRY_COMMENT;
  211. RegSetValueExW(hKey, 0, 0, REG_SZ, (const BYTE *) pName, wcslen(pName) * 2 + 2);
  212. HKEY hSubkey;
  213. lRes = RegCreateKey(hKey, "InprocServer32", &hSubkey);
  214. RegSetValueExW(hSubkey, 0, 0, REG_SZ, (const BYTE *) Path, wcslen(Path) * 2 + 2);
  215. RegSetValueExW(hSubkey, L"ThreadingModel", 0, REG_SZ, (const BYTE *) L"Both", wcslen(L"Both") * 2 + 2);
  216. RegCloseKey(hSubkey);
  217. RegCloseKey(hKey);
  218. CoTaskMemFree(pGuidStr);
  219. return S_OK;
  220. }
  221. //***************************************************************************
  222. //
  223. // DllUnregisterServer
  224. //
  225. // Standard OLE entry point for unregistering the server.
  226. //
  227. // RETURN VALUES:
  228. //
  229. // S_OK Unregistration was successful
  230. // E_FAIL Unregistration failed.
  231. //
  232. //***************************************************************************
  233. extern "C"
  234. HRESULT APIENTRY DllUnregisterServer(void)
  235. {
  236. wchar_t *pGuidStr = 0;
  237. HKEY hKey;
  238. wchar_t KeyPath[256];
  239. StringFromCLSID(IMPLEMENTED_CLSID, &pGuidStr);
  240. swprintf(KeyPath, L"Software\\Classes\\CLSID\\\\%s", pGuidStr);
  241. // Delete InProcServer32 subkey.
  242. // =============================
  243. LONG lRes = RegOpenKeyW(HKEY_LOCAL_MACHINE, KeyPath, &hKey);
  244. if (lRes)
  245. return E_FAIL;
  246. RegDeleteKeyW(hKey, L"InprocServer32");
  247. RegCloseKey(hKey);
  248. // Delete CLSID GUID key.
  249. // ======================
  250. lRes = RegOpenKeyW(HKEY_LOCAL_MACHINE, L"Software\\Classes\\CLSID", &hKey);
  251. if (lRes)
  252. return E_FAIL;
  253. RegDeleteKeyW(hKey, pGuidStr);
  254. RegCloseKey(hKey);
  255. CoTaskMemFree(pGuidStr);
  256. return S_OK;
  257. }
  258. //***************************************************************************
  259. //
  260. // CFactory::CFactory
  261. //
  262. // Constructs the class factory given the CLSID of the objects it is supposed
  263. // to create.
  264. //
  265. // PARAMETERS:
  266. //
  267. // const CLSID & ClsId The CLSID.
  268. //
  269. //***************************************************************************
  270. CFactory::CFactory(const CLSID & ClsId)
  271. {
  272. m_cRef = 0;
  273. ObjectCreated();
  274. m_ClsId = ClsId;
  275. }
  276. //***************************************************************************
  277. //
  278. // CFactory::~CFactory
  279. //
  280. // Destructor.
  281. //
  282. //***************************************************************************
  283. CFactory::~CFactory()
  284. {
  285. ObjectDestroyed();
  286. }
  287. //***************************************************************************
  288. //
  289. // CFactory::QueryInterface, AddRef and Release
  290. //
  291. // Standard IUnknown methods.
  292. //
  293. //***************************************************************************
  294. STDMETHODIMP CFactory::QueryInterface(REFIID riid, LPVOID * ppv)
  295. {
  296. *ppv = 0;
  297. if (IID_IUnknown==riid || IID_IClassFactory==riid)
  298. {
  299. *ppv = this;
  300. AddRef();
  301. return NOERROR;
  302. }
  303. return ResultFromScode(E_NOINTERFACE);
  304. }
  305. ULONG CFactory::AddRef()
  306. {
  307. return ++m_cRef;
  308. }
  309. ULONG CFactory::Release()
  310. {
  311. if (0 != --m_cRef)
  312. return m_cRef;
  313. delete this;
  314. return 0;
  315. }
  316. //***************************************************************************
  317. //
  318. // CFactory::CreateInstance
  319. //
  320. // PARAMETERS:
  321. //
  322. // LPUNKNOWN pUnkOuter IUnknown of the aggregator. Must be NULL.
  323. // REFIID riid Interface ID required.
  324. // LPVOID * ppvObj Destination for the interface pointer.
  325. //
  326. // RETURN VALUES:
  327. //
  328. // S_OK Success
  329. // CLASS_E_NOAGGREGATION pUnkOuter must be NULL
  330. // E_NOINTERFACE No such interface supported.
  331. //
  332. //***************************************************************************
  333. STDMETHODIMP CFactory::CreateInstance(
  334. LPUNKNOWN pUnkOuter,
  335. REFIID riid,
  336. LPVOID * ppvObj)
  337. {
  338. IUnknown* pObj;
  339. HRESULT hr;
  340. //
  341. // Defaults
  342. //
  343. *ppvObj=NULL;
  344. hr = ResultFromScode(E_OUTOFMEMORY);
  345. //
  346. // We aren't supporting aggregation.
  347. //
  348. if (pUnkOuter)
  349. return ResultFromScode(CLASS_E_NOAGGREGATION);
  350. if (m_ClsId == IMPLEMENTED_CLSID)
  351. {
  352. pObj = INTERFACE_CAST new CPP_CLASS_NAME;
  353. }
  354. if (!pObj)
  355. return hr;
  356. //
  357. // Initialize the object and verify that it can return the
  358. // interface in question.
  359. //
  360. hr = pObj->QueryInterface(riid, ppvObj);
  361. //
  362. // Kill the object if initial creation or Init failed.
  363. //
  364. if (FAILED(hr))
  365. delete pObj;
  366. return hr;
  367. }
  368. //***************************************************************************
  369. //
  370. // CFactory::LockServer
  371. //
  372. // Increments or decrements the lock count of the server. The DLL will not
  373. // unload while the lock count is positive.
  374. //
  375. // PARAMETERS:
  376. //
  377. // BOOL fLock If TRUE, locks; otherwise, unlocks.
  378. //
  379. // RETURN VALUES:
  380. //
  381. // S_OK
  382. //
  383. //***************************************************************************
  384. STDMETHODIMP CFactory::LockServer(BOOL fLock)
  385. {
  386. if (fLock)
  387. InterlockedIncrement((LONG *) &g_cLock);
  388. else
  389. InterlockedDecrement((LONG *) &g_cLock);
  390. return NOERROR;
  391. }