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.

727 lines
14 KiB

  1. /*******************************************************************************
  2. *
  3. * (C) COPYRIGHT MICROSOFT CORP., 1998
  4. *
  5. * TITLE: TestUsd.Cpp
  6. *
  7. * VERSION: 2.0
  8. *
  9. * AUTHOR: ReedB
  10. *
  11. * DATE: 5 Jan, 1999
  12. *
  13. * DESCRIPTION:
  14. * Implementation of the WIA test scanner class factory and IUNKNOWN interface.
  15. *
  16. *******************************************************************************/
  17. #define INITGUID
  18. #include "testusd.h"
  19. #include "resource.h"
  20. #if !defined(dllexp)
  21. #define DLLEXPORT __declspec( dllexport )
  22. #endif
  23. /*****************************************************************************
  24. *
  25. * Globals
  26. *
  27. *****************************************************************************/
  28. DWORD g_cRef; // USD reference counter.
  29. HINSTANCE g_hInst; // DLL module instance.
  30. CRITICAL_SECTION g_csCOM; // COM initialize syncronization.
  31. // Can we use UNICODE APIs
  32. //BOOL g_NoUnicodePlatform = TRUE;
  33. // Is COM initialized
  34. BOOL g_COMInitialized = FALSE;
  35. // Debugging interface, has TestUsdClassFactory lifetime.
  36. WIA_DECLARE_DEBUGGER();
  37. /**************************************************************************\
  38. * DllAddRef
  39. *
  40. *
  41. *
  42. * Arguments:
  43. *
  44. * None
  45. *
  46. * Return Value:
  47. *
  48. * Status.
  49. *
  50. * History:
  51. *
  52. * 9/11/1998 Original Version
  53. *
  54. \**************************************************************************/
  55. void DllAddRef(void)
  56. {
  57. InterlockedIncrement((LPLONG)&g_cRef);
  58. }
  59. /**************************************************************************\
  60. * DllRelease
  61. *
  62. *
  63. *
  64. * Arguments:
  65. *
  66. * None
  67. *
  68. * Return Value:
  69. *
  70. * Status.
  71. *
  72. * History:
  73. *
  74. * 9/11/1998 Original Version
  75. *
  76. \**************************************************************************/
  77. void DllRelease(void)
  78. {
  79. InterlockedDecrement((LPLONG)&g_cRef);
  80. }
  81. /**************************************************************************\
  82. * DllInitializeCOM
  83. *
  84. *
  85. *
  86. * Arguments:
  87. *
  88. * None
  89. *
  90. * Return Value:
  91. *
  92. * Status.
  93. *
  94. * History:
  95. *
  96. * 9/11/1998 Original Version
  97. *
  98. \**************************************************************************/
  99. BOOL DllInitializeCOM(void)
  100. {
  101. EnterCriticalSection(&g_csCOM);
  102. if (!g_COMInitialized) {
  103. if(SUCCEEDED(CoInitialize(NULL))) {
  104. g_COMInitialized = TRUE;
  105. }
  106. }
  107. LeaveCriticalSection(&g_csCOM);
  108. return g_COMInitialized;
  109. }
  110. /**************************************************************************\
  111. * DllUnInitializeCOM
  112. *
  113. *
  114. *
  115. * Arguments:
  116. *
  117. * None
  118. *
  119. * Return Value:
  120. *
  121. * Status.
  122. *
  123. * History:
  124. *
  125. * 9/11/1998 Original Version
  126. *
  127. \**************************************************************************/
  128. BOOL DllUnInitializeCOM(void)
  129. {
  130. EnterCriticalSection(&g_csCOM);
  131. if(g_COMInitialized) {
  132. CoUninitialize();
  133. g_COMInitialized = FALSE;
  134. }
  135. LeaveCriticalSection(&g_csCOM);
  136. return TRUE;
  137. }
  138. /***************************************************************************\
  139. *
  140. * TestUsdClassFactory
  141. *
  142. \****************************************************************************/
  143. class TestUsdClassFactory : public IClassFactory
  144. {
  145. private:
  146. ULONG m_cRef;
  147. public:
  148. STDMETHODIMP QueryInterface(REFIID riid, LPVOID *ppv);
  149. STDMETHODIMP_(ULONG) AddRef(void);
  150. STDMETHODIMP_(ULONG) Release(void);
  151. STDMETHODIMP CreateInstance(
  152. /* [unique][in] */ IUnknown __RPC_FAR *pUnkOuter,
  153. /* [in] */ REFIID riid,
  154. /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
  155. STDMETHODIMP LockServer(
  156. /* [in] */ BOOL fLock);
  157. TestUsdClassFactory();
  158. ~TestUsdClassFactory();
  159. };
  160. /**************************************************************************\
  161. * TestUsdClassFactory::TestUsdClassFactory(void)
  162. *
  163. *
  164. *
  165. * Arguments:
  166. *
  167. * None
  168. *
  169. * Return Value:
  170. *
  171. * None
  172. *
  173. * History:
  174. *
  175. * 9/11/1998 Original Version
  176. *
  177. \**************************************************************************/
  178. TestUsdClassFactory::TestUsdClassFactory(void)
  179. {
  180. // Constructor logic
  181. m_cRef = 0;
  182. WIAS_TRACE((g_hInst,"Creating TestUsdClassFactory"));
  183. }
  184. /**************************************************************************\
  185. * TestUsdClassFactory::~TestUsdClassFactory(void)
  186. *
  187. *
  188. *
  189. * Arguments:
  190. *
  191. * None
  192. *
  193. * Return Value:
  194. *
  195. * None
  196. *
  197. * History:
  198. *
  199. * 9/11/1998 Original Version
  200. *
  201. \**************************************************************************/
  202. TestUsdClassFactory::~TestUsdClassFactory(void)
  203. {
  204. // Destructor logic
  205. WIAS_TRACE((g_hInst,"Destroying TestUsdClassFactory"));
  206. }
  207. /**************************************************************************\
  208. * TestUsdClassFactory::QueryInterface
  209. *
  210. *
  211. *
  212. * Arguments:
  213. *
  214. * riid -
  215. * ppvObject -
  216. *
  217. * Return Value:
  218. *
  219. * Status.
  220. *
  221. * History:
  222. *
  223. * 9/11/1998 Original Version
  224. *
  225. \**************************************************************************/
  226. STDMETHODIMP TestUsdClassFactory::QueryInterface(
  227. REFIID riid,
  228. void __RPC_FAR *__RPC_FAR *ppvObject)
  229. {
  230. *ppvObject = NULL;
  231. if (IsEqualIID(riid, IID_IUnknown) ||
  232. IsEqualIID(riid, IID_IClassFactory)) {
  233. *ppvObject = (LPVOID)this;
  234. AddRef();
  235. return NOERROR;
  236. }
  237. return ResultFromScode(E_NOINTERFACE);
  238. }
  239. /**************************************************************************\
  240. * TestUsdClassFactory::AddRef
  241. *
  242. *
  243. *
  244. * Arguments:
  245. *
  246. * None
  247. *
  248. * Return Value:
  249. *
  250. * Status.
  251. *
  252. * History:
  253. *
  254. * 9/11/1998 Original Version
  255. *
  256. \**************************************************************************/
  257. STDMETHODIMP_(ULONG) TestUsdClassFactory::AddRef(void)
  258. {
  259. DllAddRef();
  260. return ++m_cRef;
  261. }
  262. /**************************************************************************\
  263. * TestUsdClassFactory::Release
  264. *
  265. *
  266. *
  267. * Arguments:
  268. *
  269. * None
  270. *
  271. * Return Value:
  272. *
  273. * Status.
  274. *
  275. * History:
  276. *
  277. * 9/11/1998 Original Version
  278. *
  279. \**************************************************************************/
  280. STDMETHODIMP_(ULONG) TestUsdClassFactory::Release(void)
  281. {
  282. DllRelease();
  283. if (--m_cRef == 0) {
  284. delete this;
  285. return 0;
  286. }
  287. return m_cRef;
  288. }
  289. /**************************************************************************\
  290. * TestUsdClassFactory::CreateInstance
  291. *
  292. *
  293. *
  294. * Arguments:
  295. *
  296. * punkOuter -
  297. * riid, -
  298. * ppvObject -
  299. *
  300. * Return Value:
  301. *
  302. * Status.
  303. *
  304. * History:
  305. *
  306. * 9/11/1998 Original Version
  307. *
  308. \**************************************************************************/
  309. STDMETHODIMP TestUsdClassFactory::CreateInstance(
  310. IUnknown __RPC_FAR *punkOuter,
  311. REFIID riid,
  312. void __RPC_FAR *__RPC_FAR *ppvObject)
  313. {
  314. if (!IsEqualIID(riid, IID_IStiUSD) &&
  315. !IsEqualIID(riid, IID_IWiaItem) &&
  316. !IsEqualIID(riid, IID_IUnknown)) {
  317. return STIERR_NOINTERFACE;
  318. }
  319. // When created for aggregation, only IUnknown can be requested.
  320. if (punkOuter && !IsEqualIID(riid, IID_IUnknown)) {
  321. return CLASS_E_NOAGGREGATION;
  322. }
  323. TestUsdDevice *pDev = NULL;
  324. HRESULT hres;
  325. pDev = new TestUsdDevice(punkOuter);
  326. if (!pDev) {
  327. return STIERR_OUTOFMEMORY;
  328. }
  329. hres = pDev->PrivateInitialize();
  330. if(hres != S_OK) {
  331. delete pDev;
  332. return hres;
  333. }
  334. // Move to the requested interface if we aren't aggregated.
  335. // Don't do this if aggregated, or we will lose the private
  336. // IUnknown and then the caller will be hosed.
  337. hres = pDev->NonDelegatingQueryInterface(riid,ppvObject);
  338. pDev->NonDelegatingRelease();
  339. return hres;
  340. }
  341. /**************************************************************************\
  342. * TestUsdClassFactory::LockServer
  343. *
  344. *
  345. *
  346. * Arguments:
  347. *
  348. * None
  349. *
  350. * Return Value:
  351. *
  352. * Status.
  353. *
  354. * History:
  355. *
  356. * 9/11/1998 Original Version
  357. *
  358. \**************************************************************************/
  359. STDMETHODIMP TestUsdClassFactory::LockServer(BOOL fLock)
  360. {
  361. if (fLock) {
  362. DllAddRef();
  363. } else {
  364. DllRelease();
  365. }
  366. return NOERROR;
  367. }
  368. /**************************************************************************\
  369. * TestUsdDevice::NonDelegatingQueryInterface
  370. *
  371. *
  372. *
  373. * Arguments:
  374. *
  375. * None
  376. *
  377. * Return Value:
  378. *
  379. * Status.
  380. *
  381. * History:
  382. *
  383. * 9/11/1998 Original Version
  384. *
  385. \**************************************************************************/
  386. STDMETHODIMP TestUsdDevice::NonDelegatingQueryInterface(
  387. REFIID riid,
  388. LPVOID *ppvObj)
  389. {
  390. HRESULT hres = S_OK;
  391. if (!IsValid() || !ppvObj) {
  392. return STIERR_INVALID_PARAM;
  393. }
  394. *ppvObj = NULL;
  395. if (IsEqualIID( riid, IID_IUnknown )) {
  396. *ppvObj = static_cast<INonDelegatingUnknown*>(this);
  397. }
  398. else if (IsEqualIID( riid, IID_IStiUSD )) {
  399. *ppvObj = static_cast<IStiUSD*>(this);
  400. }
  401. else if (IsEqualIID( riid, IID_IWiaMiniDrv )) {
  402. *ppvObj = static_cast<IWiaMiniDrv*>(this);
  403. }
  404. else {
  405. hres = STIERR_NOINTERFACE;
  406. }
  407. if (SUCCEEDED(hres)) {
  408. (reinterpret_cast<IUnknown*>(*ppvObj))->AddRef();
  409. }
  410. return hres;
  411. }
  412. /**************************************************************************\
  413. * TestUsdDevice::NonDelegatingAddRef
  414. *
  415. *
  416. *
  417. * Arguments:
  418. *
  419. * None
  420. *
  421. * Return Value:
  422. *
  423. * Object reference count.
  424. *
  425. * History:
  426. *
  427. * 9/11/1998 Original Version
  428. *
  429. \**************************************************************************/
  430. STDMETHODIMP_(ULONG) TestUsdDevice::NonDelegatingAddRef(void)
  431. {
  432. return InterlockedIncrement((LPLONG)&m_cRef);
  433. }
  434. /**************************************************************************\
  435. * TestUsdDevice::NonDelegatingRelease
  436. *
  437. *
  438. *
  439. * Arguments:
  440. *
  441. * None
  442. *
  443. * Return Value:
  444. *
  445. * Object reference count.
  446. *
  447. * History:
  448. *
  449. * 9/11/1998 Original Version
  450. *
  451. \**************************************************************************/
  452. STDMETHODIMP_(ULONG) TestUsdDevice::NonDelegatingRelease(void)
  453. {
  454. ULONG ulRef;
  455. ulRef = InterlockedDecrement((LPLONG)&m_cRef);
  456. if (!ulRef) {
  457. delete this;
  458. }
  459. return ulRef;
  460. }
  461. /**************************************************************************\
  462. * TestUsdDevice::QueryInterface
  463. *
  464. *
  465. *
  466. * Arguments:
  467. *
  468. * None
  469. *
  470. * Return Value:
  471. *
  472. * Status.
  473. *
  474. * History:
  475. *
  476. * 9/11/1998 Original Version
  477. *
  478. \**************************************************************************/
  479. STDMETHODIMP TestUsdDevice::QueryInterface(REFIID riid, LPVOID *ppvObj)
  480. {
  481. return m_punkOuter->QueryInterface(riid,ppvObj);
  482. }
  483. /**************************************************************************\
  484. * TestUsdDevice::AddRef
  485. *
  486. *
  487. *
  488. * Arguments:
  489. *
  490. * None
  491. *
  492. * Return Value:
  493. *
  494. * Status.
  495. *
  496. * History:
  497. *
  498. * 9/11/1998 Original Version
  499. *
  500. \**************************************************************************/
  501. STDMETHODIMP_(ULONG) TestUsdDevice::AddRef(void)
  502. {
  503. return m_punkOuter->AddRef();
  504. }
  505. /**************************************************************************\
  506. * TestUsdDevice::Release
  507. *
  508. *
  509. *
  510. * Arguments:
  511. *
  512. * None
  513. *
  514. * Return Value:
  515. *
  516. * Status.
  517. *
  518. * History:
  519. *
  520. * 9/11/1998 Original Version
  521. *
  522. \**************************************************************************/
  523. STDMETHODIMP_(ULONG) TestUsdDevice::Release(void)
  524. {
  525. return m_punkOuter->Release();
  526. }
  527. /**************************************************************************\
  528. * DllEntryPoint
  529. *
  530. * Main library entry point. Receives DLL event notification from OS.
  531. *
  532. * We are not interested in thread attaches and detaches,
  533. * so we disable thread notifications for performance reasons.
  534. *
  535. * Arguments:
  536. *
  537. * hinst -
  538. * dwReason -
  539. * lpReserved -
  540. *
  541. * Return Value:
  542. *
  543. * Returns TRUE to allow the DLL to load.
  544. *
  545. * History:
  546. *
  547. * 9/11/1998 Original Version
  548. *
  549. \**************************************************************************/
  550. extern "C"
  551. BOOL APIENTRY
  552. DllEntryPoint(
  553. HINSTANCE hinst,
  554. DWORD dwReason,
  555. LPVOID lpReserved)
  556. {
  557. switch (dwReason) {
  558. case DLL_PROCESS_ATTACH:
  559. g_hInst = hinst;
  560. DisableThreadLibraryCalls(hinst);
  561. __try {
  562. if(!InitializeCriticalSectionAndSpinCount(&g_csCOM, MINLONG)) {
  563. return FALSE;
  564. }
  565. }
  566. __except(EXCEPTION_EXECUTE_HANDLER) {
  567. return FALSE;
  568. }
  569. break;
  570. case DLL_PROCESS_DETACH:
  571. if (g_cRef) {
  572. OutputDebugStringA("TestUsd: Unloaded before all objects releaseed!\n");
  573. }
  574. DeleteCriticalSection(&g_csCOM);
  575. break;
  576. }
  577. return TRUE;
  578. }
  579. /**************************************************************************\
  580. * DllCanUnloadNow
  581. *
  582. * Determines whether the DLL has any outstanding interfaces.
  583. *
  584. * Arguments:
  585. *
  586. * None
  587. *
  588. * Return Value:
  589. *
  590. * Returns S_OK if the DLL can unload, S_FALSE if it is not safe to unload.
  591. *
  592. * History:
  593. *
  594. * 9/11/1998 Original Version
  595. *
  596. \**************************************************************************/
  597. extern "C" STDMETHODIMP DllCanUnloadNow(void)
  598. {
  599. return g_cRef ? S_FALSE : S_OK;
  600. }
  601. /**************************************************************************\
  602. * DllGetClassObject
  603. *
  604. * Create an IClassFactory instance for this DLL. We support only one
  605. * class of objects, so this function does not need to go through a table
  606. * of supported classes, looking for the proper constructor.
  607. *
  608. * Arguments:
  609. *
  610. * rclsid - The object being requested.
  611. * riid - The desired interface on the object.
  612. * ppv - Output pointer to object.
  613. *
  614. * Return Value:
  615. *
  616. * Status.
  617. *
  618. * History:
  619. *
  620. * 9/11/1998 Original Version
  621. *
  622. \**************************************************************************/
  623. extern "C" STDAPI DllGetClassObject(
  624. REFCLSID rclsid,
  625. REFIID riid,
  626. LPVOID *ppv)
  627. {
  628. if (!ppv) {
  629. return ResultFromScode(E_FAIL);
  630. }
  631. if (!IsEqualCLSID(rclsid, CLSID_TestUsd) ) {
  632. return ResultFromScode(E_FAIL);
  633. }
  634. if (!IsEqualIID(riid, IID_IUnknown) &&
  635. !IsEqualIID(riid, IID_IClassFactory)) {
  636. return ResultFromScode(E_NOINTERFACE);
  637. }
  638. if (IsEqualCLSID(rclsid, CLSID_TestUsd)) {
  639. TestUsdClassFactory *pcf = new TestUsdClassFactory;
  640. if (pcf) {
  641. *ppv = (LPVOID)pcf;
  642. }
  643. }
  644. return NOERROR;
  645. }