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.

537 lines
13 KiB

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