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