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.

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