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.

530 lines
11 KiB

  1. /****************************************************************************
  2. *
  3. * SampUSD.CPP
  4. *
  5. * Copyright (C) Microsoft Corporation 1996-1999
  6. * All rights reserved
  7. *
  8. ***************************************************************************/
  9. #define INITGUID
  10. #include "Sampusd.h"
  11. #include "resource.h"
  12. /*****************************************************************************
  13. *
  14. * Globals
  15. *
  16. *****************************************************************************/
  17. // Reference counter for the whole library
  18. DWORD g_cRef;
  19. // DLL module instance
  20. HINSTANCE g_hInst;
  21. // Critical section for low level syncronization
  22. CRITICAL_SECTION g_crstDll;
  23. // Can we use UNICODE APIs
  24. BOOL g_NoUnicodePlatform = TRUE;
  25. // Is COM initialized
  26. BOOL g_COMInitialized = FALSE;
  27. /*****************************************************************************
  28. *
  29. * @doc INTERNAL
  30. *
  31. * @func void | DllEnterCrit |
  32. *
  33. * Take the DLL critical section.
  34. *
  35. * The DLL critical section is the lowest level critical section.
  36. * You may not attempt to acquire any other critical sections or
  37. * yield while the DLL critical section is held.
  38. *
  39. *****************************************************************************/
  40. void
  41. DllEnterCrit(void)
  42. {
  43. EnterCriticalSection(&g_crstDll);
  44. }
  45. /*****************************************************************************
  46. *
  47. * @doc INTERNAL
  48. *
  49. * @func void | DllLeaveCrit |
  50. *
  51. * Leave the DLL critical section.
  52. *
  53. *****************************************************************************/
  54. void
  55. DllLeaveCrit(void)
  56. {
  57. LeaveCriticalSection(&g_crstDll);
  58. }
  59. /*****************************************************************************
  60. *
  61. * @doc INTERNAL
  62. *
  63. * @func void | DllAddRef |
  64. *
  65. * Increment the reference count on the DLL.
  66. *
  67. *****************************************************************************/
  68. void
  69. DllAddRef(void)
  70. {
  71. InterlockedIncrement((LPLONG)&g_cRef);
  72. }
  73. /*****************************************************************************
  74. *
  75. * @doc INTERNAL
  76. *
  77. * @func void | DllRelease |
  78. *
  79. * Decrement the reference count on the DLL.
  80. *
  81. *****************************************************************************/
  82. void
  83. DllRelease(void)
  84. {
  85. InterlockedDecrement((LPLONG)&g_cRef);
  86. }
  87. /*****************************************************************************
  88. *
  89. * @doc INTERNAL
  90. *
  91. * @func HRESULT | DllInitializeCOM |
  92. *
  93. * Initialize COM libraries
  94. *
  95. * @parm IN | |
  96. *
  97. * @returns
  98. *
  99. * Returns a boolean error code.
  100. *
  101. *****************************************************************************/
  102. BOOL
  103. DllInitializeCOM(
  104. void
  105. )
  106. {
  107. DllEnterCrit();
  108. if(!g_COMInitialized) {
  109. if(SUCCEEDED(CoInitialize(NULL))) {
  110. g_COMInitialized = TRUE;
  111. }
  112. }
  113. DllLeaveCrit();
  114. return g_COMInitialized;
  115. }
  116. /*****************************************************************************
  117. *
  118. * @doc INTERNAL
  119. *
  120. * @func HRESULT | DllUnInitializeCOM |
  121. *
  122. * UnInitialize COM libraries
  123. *
  124. * @parm IN | |
  125. *
  126. * @returns
  127. *
  128. * Returns a boolean error code.
  129. *
  130. *****************************************************************************/
  131. BOOL
  132. DllUnInitializeCOM(
  133. void
  134. )
  135. {
  136. DllEnterCrit();
  137. if(g_COMInitialized) {
  138. CoUninitialize();
  139. g_COMInitialized = FALSE;
  140. }
  141. DllLeaveCrit();
  142. return TRUE;
  143. }
  144. /*****************************************************************************
  145. *
  146. * @class UsdSampClassFactory |
  147. *
  148. *****************************************************************************/
  149. class UsdSampClassFactory : public IClassFactory
  150. {
  151. private:
  152. ULONG m_cRef;
  153. public:
  154. STDMETHODIMP QueryInterface(REFIID riid, LPVOID *ppv);
  155. STDMETHODIMP_(ULONG) AddRef(void);
  156. STDMETHODIMP_(ULONG) Release(void);
  157. STDMETHODIMP CreateInstance(
  158. /* [unique][in] */ IUnknown __RPC_FAR *pUnkOuter,
  159. /* [in] */ REFIID riid,
  160. /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
  161. STDMETHODIMP LockServer(
  162. /* [in] */ BOOL fLock);
  163. UsdSampClassFactory();
  164. };
  165. UsdSampClassFactory::UsdSampClassFactory()
  166. {
  167. //DEBUGPRINTF((DBG_LVL_DEBUG, TEXT("UsdSampClassFactory: Constructor")));
  168. // Constructor logic
  169. m_cRef = 0;
  170. }
  171. STDMETHODIMP UsdSampClassFactory::QueryInterface(
  172. /* [in] */ REFIID riid,
  173. /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject)
  174. {
  175. // DEBUGPRINTF((DBG_LVL_DEBUG, TEXT("UsdSampClassFactory: QueryInterface")));
  176. *ppvObject = NULL;
  177. if (IsEqualIID(riid, IID_IUnknown) ||
  178. IsEqualIID(riid, IID_IClassFactory)) {
  179. *ppvObject = (LPVOID)this;
  180. AddRef();
  181. return NOERROR;
  182. }
  183. return ResultFromScode(E_NOINTERFACE);
  184. }
  185. STDMETHODIMP_(ULONG) UsdSampClassFactory::AddRef(void)
  186. {
  187. DllAddRef();
  188. return ++m_cRef;
  189. }
  190. STDMETHODIMP_(ULONG) UsdSampClassFactory::Release(void)
  191. {
  192. DllRelease();
  193. if (--m_cRef == 0) {
  194. delete this;
  195. return 0;
  196. }
  197. return m_cRef;
  198. }
  199. STDMETHODIMP UsdSampClassFactory::CreateInstance(
  200. /* [unique][in] */ IUnknown __RPC_FAR *punkOuter,
  201. /* [in] */ REFIID riid,
  202. /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject)
  203. {
  204. if (!IsEqualIID(riid, IID_IStiUSD) &&
  205. !IsEqualIID(riid, IID_IUnknown)) {
  206. return STIERR_NOINTERFACE;
  207. }
  208. // When created for aggregation, only IUnknown can be requested, so fail
  209. // call if not.
  210. if (punkOuter && !IsEqualIID(riid, IID_IUnknown)) {
  211. return CLASS_E_NOAGGREGATION;
  212. }
  213. UsdSampDevice *pDev = NULL;
  214. HRESULT hres;
  215. pDev = new UsdSampDevice(punkOuter);
  216. if (!pDev) {
  217. return STIERR_OUTOFMEMORY;
  218. }
  219. //
  220. // Move to the requested interface
  221. //
  222. hres = pDev->NonDelegatingQueryInterface(riid,ppvObject);
  223. pDev->NonDelegatingRelease();
  224. return hres;
  225. }
  226. STDMETHODIMP UsdSampClassFactory::LockServer(
  227. /* [in] */ BOOL fLock)
  228. {
  229. if (fLock) {
  230. DllAddRef();
  231. } else {
  232. DllRelease();
  233. }
  234. return NOERROR;
  235. }
  236. /*****************************************************************************
  237. *
  238. * @class UsdSampDevice | INonDelegatingUnknown
  239. *
  240. *****************************************************************************/
  241. STDMETHODIMP UsdSampDevice::NonDelegatingQueryInterface( REFIID riid, LPVOID* ppvObj )
  242. {
  243. HRESULT hres;
  244. if( !IsValid() || !ppvObj )
  245. {
  246. return STIERR_INVALID_PARAM;
  247. }
  248. *ppvObj = NULL;
  249. if( IsEqualIID( riid, IID_IUnknown ))
  250. {
  251. *ppvObj = static_cast<INonDelegatingUnknown*>(this);
  252. hres = S_OK;
  253. }
  254. else if( IsEqualIID( riid, IID_IStiUSD ))
  255. {
  256. *ppvObj = static_cast<IStiUSD*>(this);
  257. hres = S_OK;
  258. }
  259. else
  260. {
  261. hres = STIERR_NOINTERFACE;
  262. }
  263. if (SUCCEEDED(hres)) {
  264. (reinterpret_cast<IUnknown*>(*ppvObj))->AddRef();
  265. }
  266. return hres;
  267. }
  268. STDMETHODIMP_(ULONG) UsdSampDevice::NonDelegatingAddRef( VOID )
  269. {
  270. ULONG ulRef;
  271. ulRef = InterlockedIncrement((LPLONG)&m_cRef);
  272. return ulRef;
  273. }
  274. STDMETHODIMP_(ULONG) UsdSampDevice::NonDelegatingRelease( VOID )
  275. {
  276. ULONG ulRef;
  277. ulRef = InterlockedDecrement((LPLONG)&m_cRef);
  278. if(!ulRef)
  279. {
  280. delete this;
  281. }
  282. return ulRef;
  283. }
  284. /*****************************************************************************
  285. *
  286. * @class UsdSampDevice | IUnknown (Delegating)
  287. *
  288. * Delegating unknown methods.
  289. *
  290. *****************************************************************************/
  291. STDMETHODIMP UsdSampDevice::QueryInterface( REFIID riid, LPVOID* ppvObj )
  292. {
  293. return m_punkOuter->QueryInterface(riid,ppvObj);
  294. }
  295. STDMETHODIMP_(ULONG) UsdSampDevice::AddRef( VOID )
  296. {
  297. return m_punkOuter->AddRef();
  298. }
  299. STDMETHODIMP_(ULONG) UsdSampDevice::Release( VOID )
  300. {
  301. return m_punkOuter->Release();
  302. }
  303. /*****************************************************************************
  304. *
  305. * @doc INTERNAL
  306. *
  307. * @func BOOL | DllEntryPoint |
  308. *
  309. * Called to notify the DLL about various things that can happen.
  310. *
  311. * We are not interested in thread attaches and detaches,
  312. * so we disable thread notifications for performance reasons.
  313. *
  314. * @parm HINSTANCE | hinst |
  315. *
  316. * The instance handle of this DLL.
  317. *
  318. * @parm DWORD | dwReason |
  319. *
  320. * Notification code.
  321. *
  322. * @parm LPVOID | lpReserved |
  323. *
  324. * Not used.
  325. *
  326. * @returns
  327. *
  328. * Returns <c TRUE> to allow the DLL to load.
  329. *
  330. *****************************************************************************/
  331. extern "C"
  332. DLLEXPORT
  333. BOOL APIENTRY
  334. DllEntryPoint(HINSTANCE hinst, DWORD dwReason, LPVOID lpReserved)
  335. {
  336. switch (dwReason) {
  337. case DLL_PROCESS_ATTACH:
  338. g_hInst = hinst;
  339. // Disable thread library calls to avoid
  340. // deadlock when we spin up the worker thread
  341. DisableThreadLibraryCalls(hinst);
  342. InitializeCriticalSection(&g_crstDll);
  343. // Set global flags
  344. // g_NoUnicodePlatform = !OSUtil_IsPlatformUnicode();
  345. break;
  346. case DLL_PROCESS_DETACH:
  347. if (g_cRef) {
  348. // DPRINTF("Sampusd: Unloaded before all objects Release()d! Crash soon!\r\n");
  349. }
  350. // Free COM libraries if connected to them
  351. // DllUnInitializeCOM();
  352. break;
  353. }
  354. return 1;
  355. }
  356. extern "C"
  357. DLLEXPORT
  358. BOOL WINAPI
  359. DllMain(HINSTANCE hinst, DWORD dwReason, LPVOID lpReserved)
  360. {
  361. return DllEntryPoint(hinst, dwReason, lpReserved);
  362. }
  363. /*****************************************************************************
  364. *
  365. * @doc INTERNAL
  366. *
  367. * @func HRESULT | DllCanUnloadNow |
  368. *
  369. * Determine whether the DLL has any outstanding interfaces.
  370. *
  371. * @returns
  372. *
  373. * Returns <c S_OK> if the DLL can unload, <c S_FALSE> if
  374. * it is not safe to unload.
  375. *
  376. *****************************************************************************/
  377. extern "C"
  378. STDMETHODIMP
  379. DllCanUnloadNow(void)
  380. {
  381. HRESULT hres;
  382. hres = g_cRef ? S_FALSE : S_OK;
  383. return hres;
  384. }
  385. /*****************************************************************************
  386. *
  387. * @doc INTERNAL
  388. *
  389. * @func HRESULT | DllGetClassObject |
  390. *
  391. * Create an <i IClassFactory> instance for this DLL.
  392. *
  393. * @parm REFCLSID | rclsid |
  394. *
  395. * The object being requested.
  396. *
  397. * @parm RIID | riid |
  398. *
  399. * The desired interface on the object.
  400. *
  401. * @parm PPV | ppvOut |
  402. *
  403. * Output pointer.
  404. *
  405. * @notes
  406. * We support only one class of objects , so this function does not need
  407. * to go through table of supported classes , looking for proper constructor
  408. *
  409. *
  410. *****************************************************************************/
  411. extern "C"
  412. STDAPI DllGetClassObject(
  413. REFCLSID rclsid,
  414. REFIID riid,
  415. LPVOID *ppv)
  416. {
  417. if (!ppv) {
  418. return ResultFromScode(E_FAIL);
  419. }
  420. if (!IsEqualCLSID(rclsid, CLSID_SampUSDObj) ) {
  421. return ResultFromScode(E_FAIL);
  422. }
  423. if (!IsEqualIID(riid, IID_IUnknown) &&
  424. !IsEqualIID(riid, IID_IClassFactory)) {
  425. return ResultFromScode(E_NOINTERFACE);
  426. }
  427. if (IsEqualCLSID(rclsid, CLSID_SampUSDObj)) {
  428. UsdSampClassFactory *pcf = new UsdSampClassFactory;
  429. if (pcf) {
  430. *ppv = (LPVOID)pcf;
  431. }
  432. }
  433. return NOERROR;
  434. }