Leaked source code of windows server 2003
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.

584 lines
15 KiB

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