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.

672 lines
16 KiB

  1. /*******************************************************************************
  2. *
  3. * (C) COPYRIGHT MICROSOFT CORP., 1999
  4. *
  5. * TITLE: IEnumDC.Cpp
  6. *
  7. * VERSION: 1.01
  8. *
  9. * AUTHOR: ByronC
  10. *
  11. * DATE: 16 March, 1999
  12. *
  13. * DESCRIPTION:
  14. * Implementation of CEnumWIA_DEV_CAPS for the WIA device class driver.
  15. *
  16. *******************************************************************************/
  17. #include "precomp.h"
  18. #include "stiexe.h"
  19. #include "wiamindr.h"
  20. #include "ienumdc.h"
  21. #include "helpers.h"
  22. /*******************************************************************************\
  23. *
  24. * QueryInterface
  25. * AddRef
  26. * Release
  27. *
  28. * DESCRIPTION:
  29. * IUnknown Interface.
  30. *
  31. * PARAMETERS:
  32. *
  33. \*******************************************************************************/
  34. HRESULT _stdcall CEnumDC::QueryInterface(const IID& iid, void** ppv)
  35. {
  36. *ppv = NULL;
  37. if (iid == IID_IUnknown || iid == IID_IEnumWIA_DEV_CAPS) {
  38. *ppv = (IEnumWIA_DEV_CAPS*) this;
  39. } else {
  40. return E_NOINTERFACE;
  41. }
  42. AddRef();
  43. return (S_OK);
  44. }
  45. ULONG _stdcall CEnumDC::AddRef()
  46. {
  47. InterlockedIncrement((long*) &m_cRef);
  48. return m_cRef;
  49. }
  50. ULONG _stdcall CEnumDC::Release()
  51. {
  52. ULONG ulRefCount = m_cRef - 1;
  53. if (InterlockedDecrement((long*) &m_cRef) == 0) {
  54. delete this;
  55. return 0;
  56. }
  57. return ulRefCount;
  58. }
  59. /**************************************************************************\
  60. * CEnumWiaDC::CEnumDC
  61. *
  62. * Constructor. Initializes the member fields to 0.
  63. *
  64. * Arguments:
  65. *
  66. *
  67. * Return Value:
  68. *
  69. *
  70. * History:
  71. *
  72. * 16/03/99 Original Version
  73. *
  74. \**************************************************************************/
  75. CEnumDC::CEnumDC()
  76. {
  77. m_cRef = 0;
  78. m_ulIndex = 0;
  79. m_pActiveDevice = NULL;
  80. m_pDeviceCapabilities = NULL;
  81. }
  82. /**************************************************************************\
  83. * CEnumWiaDC::Initialize
  84. *
  85. * Initializes the enumerator by querying the device for it's capabilities
  86. * and then keeping a local copy in m_pDeviceCapabilities.
  87. *
  88. * Arguments:
  89. *
  90. * ulFlags - indicates Capability type: WIA_DEVICE_COMMANDS or
  91. * WIA_DEVICE_EVENTS or both
  92. * pActiveDevice - pointer to the device's MiniDriver Interface
  93. * pCWiaItem - pointer to the wia item
  94. *
  95. * Return Value:
  96. *
  97. *
  98. * History:
  99. *
  100. * 16/03/99 Original Version
  101. *
  102. \**************************************************************************/
  103. HRESULT CEnumDC::Initialize(
  104. ULONG ulFlags,
  105. CWiaItem *pCWiaItem)
  106. {
  107. DBG_FN(CEnumDC::Initialize);
  108. HRESULT hr = S_OK;
  109. WIA_DEV_CAP_DRV *pDevCap = NULL;
  110. LONG cIndex = 0;
  111. //
  112. // Validate parameters
  113. //
  114. if ((!pCWiaItem)) {
  115. DBG_ERR(("CEnumDC::Initialize, NULL input parameter"));
  116. return E_POINTER;
  117. }
  118. m_ulFlags = ulFlags;
  119. m_pCWiaItem = pCWiaItem;
  120. m_ulIndex = 0;
  121. //
  122. // Ask minidriver for Capabilities supported
  123. //
  124. {
  125. LOCK_WIA_DEVICE _LWD(m_pCWiaItem, &hr);
  126. if(SUCCEEDED(hr)) {
  127. hr = m_pCWiaItem->m_pActiveDevice->m_DrvWrapper.WIA_drvGetCapabilities(
  128. (BYTE*)pCWiaItem,
  129. ulFlags,
  130. &m_lCount,
  131. &pDevCap,
  132. &(m_pCWiaItem->m_lLastDevErrVal));
  133. }
  134. }
  135. if (FAILED(hr)) {
  136. DBG_ERR(("CEnumDC::Initialize, Error calling driver: drvGetCapabilities failed"));
  137. return hr;
  138. }
  139. if (m_lCount <= 0) {
  140. m_lCount = 0;
  141. DBG_ERR(("CEnumDC::Initialize, drvGetCapabilities returned invalid count"));
  142. return WIA_ERROR_INVALID_DRIVER_RESPONSE;
  143. }
  144. //
  145. // Check whether pointer received is valid
  146. //
  147. if (IsBadReadPtr(pDevCap, sizeof(WIA_DEV_CAP_DRV) * m_lCount)) {
  148. DBG_ERR(("CEnumDC::Initialize, drvGetFormatEtc returned invalid pointer"));
  149. return E_POINTER;
  150. }
  151. //
  152. // Make a local copy in case minidriver goes away.
  153. //
  154. m_pDeviceCapabilities = (WIA_DEV_CAP*) LocalAlloc(LPTR, sizeof(WIA_DEV_CAP) * m_lCount);
  155. if (m_pDeviceCapabilities) {
  156. memset(m_pDeviceCapabilities, 0, sizeof(WIA_DEV_CAP) * m_lCount);
  157. while (cIndex < m_lCount) {
  158. memcpy(&m_pDeviceCapabilities[cIndex].guid, pDevCap[cIndex].guid, sizeof(GUID));
  159. m_pDeviceCapabilities[cIndex].ulFlags = pDevCap[cIndex].ulFlags;
  160. m_pDeviceCapabilities[cIndex].bstrDescription = SysAllocString(pDevCap[cIndex].wszDescription);
  161. m_pDeviceCapabilities[cIndex].bstrName = SysAllocString(pDevCap[cIndex].wszName);
  162. m_pDeviceCapabilities[cIndex].bstrIcon = SysAllocString(pDevCap[cIndex].wszIcon);
  163. //
  164. // Check that the strings were actually allocated
  165. //
  166. if ((! (m_pDeviceCapabilities[cIndex].bstrDescription)) ||
  167. (! (m_pDeviceCapabilities[cIndex].bstrName)) ||
  168. (! (m_pDeviceCapabilities[cIndex].bstrIcon))) {
  169. DBG_ERR(("CEnumDC::Initialize, unable to allocate names buffer"));
  170. LocalFree(m_pDeviceCapabilities);
  171. return E_OUTOFMEMORY;
  172. }
  173. cIndex++;
  174. }
  175. }
  176. else {
  177. DBG_ERR(("CEnumDC::Initialize, unable to allocate capabilities buffer"));
  178. return E_OUTOFMEMORY;
  179. }
  180. return hr;
  181. }
  182. /**************************************************************************\
  183. * CEnumWiaDC::Initialize
  184. *
  185. * Initializes the enumerator, caller is responsible for allocating memory
  186. *
  187. * Arguments:
  188. *
  189. * lCount - total number of event handlers
  190. * pEventInfo - persistent event handler information
  191. *
  192. * Return Value:
  193. *
  194. *
  195. * History:
  196. *
  197. * 16/03/99 Original Version
  198. *
  199. \**************************************************************************/
  200. HRESULT CEnumDC::Initialize(
  201. LONG lCount,
  202. WIA_EVENT_HANDLER *pHandlerInfo)
  203. {
  204. DBG_FN(CEnumDC::Initialize);
  205. m_pActiveDevice = NULL;
  206. m_pCWiaItem = NULL;
  207. m_ulFlags = 0;
  208. m_ulIndex = 0;
  209. m_pDeviceCapabilities = (WIA_DEV_CAP *)pHandlerInfo;
  210. m_lCount = lCount;
  211. return S_OK;
  212. }
  213. /********************************************************************************\
  214. *
  215. * CopyCaps
  216. *
  217. * DESCRIPTION:
  218. * Copies an array of WIA_DEV_CAP structures.
  219. *
  220. * Arguments:
  221. *
  222. * ulCount - the number of elements to copy
  223. * pwdcIn - a pointer to the capabilities source array
  224. * pwdcOut - a pointer to the capabilities dest array
  225. *
  226. * Return Value:
  227. *
  228. * Status. - E_POINTER if pwdcIn or pwdcOut are bad read pointers
  229. * - S_OK if successful.
  230. *
  231. *
  232. * History:
  233. *
  234. * 16/03/99 Original Version
  235. *
  236. \********************************************************************************/
  237. HRESULT CopyCaps(
  238. ULONG ulCount,
  239. WIA_DEV_CAP *pwdcIn,
  240. WIA_DEV_CAP *pwdcOut)
  241. {
  242. DBG_FN(::CopyCaps);
  243. HRESULT hr = S_OK;
  244. ULONG i;
  245. if (ulCount == 0) {
  246. return (hr);
  247. }
  248. memset(pwdcOut, 0, sizeof(WIA_DEV_CAP) * ulCount);
  249. for (i = 0; i < ulCount; i++) {
  250. memcpy(&pwdcOut[i].guid, &pwdcIn[i].guid, sizeof(GUID));
  251. pwdcOut[i].ulFlags = pwdcIn[i].ulFlags;
  252. if (pwdcIn[i].bstrName) {
  253. pwdcOut[i].bstrName = SysAllocString(pwdcIn[i].bstrName);
  254. if (!pwdcOut[i].bstrName) {
  255. hr = E_OUTOFMEMORY;
  256. }
  257. }
  258. if (pwdcIn[i].bstrDescription) {
  259. pwdcOut[i].bstrDescription = SysAllocString(pwdcIn[i].bstrDescription);
  260. if (!pwdcOut[i].bstrDescription) {
  261. hr = E_OUTOFMEMORY;
  262. }
  263. }
  264. if (pwdcIn[i].bstrIcon) {
  265. pwdcOut[i].bstrIcon = SysAllocString(pwdcIn[i].bstrIcon);
  266. if (!pwdcOut[i].bstrIcon) {
  267. hr = E_OUTOFMEMORY;
  268. }
  269. }
  270. if (pwdcIn[i].bstrCommandline) {
  271. pwdcOut[i].bstrCommandline = SysAllocString(pwdcIn[i].bstrCommandline);
  272. if (!pwdcOut[i].bstrCommandline) {
  273. hr = E_OUTOFMEMORY;
  274. }
  275. }
  276. if (FAILED(hr)) {
  277. break;
  278. }
  279. }
  280. if (hr == S_OK) {
  281. return (hr);
  282. } else {
  283. //
  284. // Unwind the partial result
  285. //
  286. for (ULONG j = 0; j <= i; j++) {
  287. if (pwdcOut[i].bstrDescription) {
  288. SysFreeString(pwdcOut[i].bstrDescription);
  289. }
  290. if (pwdcOut[i].bstrName) {
  291. SysFreeString(pwdcOut[i].bstrName);
  292. }
  293. if (pwdcOut[i].bstrIcon) {
  294. SysFreeString(pwdcOut[i].bstrIcon);
  295. }
  296. if (pwdcOut[i].bstrCommandline) {
  297. SysFreeString(pwdcOut[i].bstrCommandline);
  298. }
  299. }
  300. return (hr);
  301. }
  302. }
  303. /**************************************************************************\
  304. * CEnumWiaDC::~CEnumDC
  305. *
  306. * Destructor for CEnumDC. It frees up the m_pDeviceCapabilities structure
  307. * that was allocated in the constructor.
  308. *
  309. * Arguments:
  310. *
  311. *
  312. * Return Value:
  313. *
  314. *
  315. * History:
  316. *
  317. * 16/03/99 Original Version
  318. *
  319. \**************************************************************************/
  320. CEnumDC::~CEnumDC()
  321. {
  322. DBG_FN(CEnumDC::~CEnumDC);
  323. LONG cIndex = 0;
  324. if (m_pDeviceCapabilities) {
  325. while(cIndex < m_lCount) {
  326. if (m_pDeviceCapabilities[cIndex].bstrName) {
  327. SysFreeString(m_pDeviceCapabilities[cIndex].bstrName);
  328. }
  329. if (m_pDeviceCapabilities[cIndex].bstrDescription) {
  330. SysFreeString(m_pDeviceCapabilities[cIndex].bstrDescription);
  331. }
  332. if (m_pDeviceCapabilities[cIndex].bstrIcon) {
  333. SysFreeString(m_pDeviceCapabilities[cIndex].bstrIcon);
  334. }
  335. if (m_pDeviceCapabilities[cIndex].bstrCommandline) {
  336. SysFreeString(m_pDeviceCapabilities[cIndex].bstrCommandline);
  337. }
  338. cIndex++;
  339. }
  340. LocalFree(m_pDeviceCapabilities);
  341. m_pDeviceCapabilities = NULL;
  342. }
  343. m_cRef = 0;
  344. m_ulIndex = 0;
  345. m_pCWiaItem = NULL;
  346. }
  347. /**************************************************************************\
  348. * CEnumWiaDC::Next
  349. *
  350. * Device capability enumerator, this enumerator returns an array of
  351. * WIA_DEV_CAP structs.
  352. * Next_Proxy ensures that last parameter is non-NULL.
  353. *
  354. * Arguments:
  355. *
  356. * celt - number requested.
  357. * rgelt - capabilities returned in this array
  358. * pceltFetched - returned number of entries written. NULLs are
  359. * ignored.
  360. *
  361. * Return Value:
  362. *
  363. *
  364. * History:
  365. *
  366. * 16/03/99 Original Version
  367. *
  368. \**************************************************************************/
  369. HRESULT _stdcall CEnumDC::Next(
  370. ULONG celt,
  371. WIA_DEV_CAP *rgelt,
  372. ULONG *pceltFetched)
  373. {
  374. DBG_FN(CEnumDC::Next);
  375. HRESULT hr;
  376. ULONG ulCount;
  377. *pceltFetched = 0L;
  378. //
  379. // Clear returned WIA_DEV_CAP structures
  380. //
  381. memset(rgelt, 0, sizeof(WIA_DEV_CAP) *celt);
  382. //
  383. // Validate parameters
  384. //
  385. if (NULL == m_pDeviceCapabilities) {
  386. return (S_FALSE);
  387. }
  388. //
  389. // Check whether any more elements exist to enumerate through.
  390. //
  391. if (m_ulIndex >= (ULONG)m_lCount) {
  392. return (S_FALSE);
  393. }
  394. //
  395. // Check that the requested number of elements exist. If not,
  396. // set ulCount to the remaining number of elements.
  397. //
  398. if (celt > (m_lCount - m_ulIndex)) {
  399. ulCount = m_lCount - m_ulIndex;
  400. } else {
  401. ulCount = celt;
  402. }
  403. hr = CopyCaps(ulCount, &m_pDeviceCapabilities[m_ulIndex], rgelt);
  404. if (FAILED(hr)) {
  405. DBG_ERR(("CEnumDC::Next, could not copy capabilities!"));
  406. return (hr);
  407. }
  408. m_ulIndex+= ulCount;
  409. *pceltFetched = ulCount;
  410. //
  411. // Return S_FALSE if we returned less elements than requested
  412. //
  413. if (ulCount < celt) {
  414. hr = S_FALSE;
  415. }
  416. return (hr);
  417. }
  418. /**************************************************************************\
  419. * CEnumWiaDC::Skip
  420. *
  421. * Skips device capabilities in the enumeration.
  422. *
  423. * Arguments:
  424. *
  425. * celt - number of items to skip.
  426. *
  427. * Return Value:
  428. *
  429. *
  430. * History:
  431. *
  432. * 16/03/99 Original Version
  433. *
  434. \**************************************************************************/
  435. HRESULT _stdcall CEnumDC::Skip(ULONG celt)
  436. {
  437. DBG_FN(CEnumDC::Skip);
  438. //
  439. // Check that we actually have a capabilities list and that we don't
  440. // exceed the number of elements
  441. //
  442. if((m_pDeviceCapabilities != NULL) &&
  443. ((m_ulIndex + celt) < (ULONG)m_lCount)) {
  444. m_ulIndex += celt;
  445. return S_OK;
  446. }
  447. return S_FALSE;
  448. }
  449. /**************************************************************************\
  450. * EnumDC::Reset
  451. *
  452. * Resets the enumeration to the first element
  453. *
  454. * Arguments:
  455. *
  456. *
  457. * Return Value:
  458. *
  459. * status
  460. *
  461. * History:
  462. *
  463. * 16/03/99 Original Version
  464. *
  465. \**************************************************************************/
  466. HRESULT _stdcall CEnumDC::Reset(void)
  467. {
  468. DBG_FN(CEnumDC::Reset);
  469. m_ulIndex = 0;
  470. return S_OK;
  471. }
  472. /**************************************************************************\
  473. * CEnumDC::Clone
  474. *
  475. * Creates another IEnumWIA_DEV_CAPS enumeration object and returns an
  476. * interface pointer to it.
  477. *
  478. * Arguments:
  479. *
  480. * ppIEnum - Address that receives the new enumeration object
  481. *
  482. * Return Value:
  483. *
  484. * Status
  485. *
  486. * History:
  487. *
  488. * 16/03/99 Original Version
  489. *
  490. \**************************************************************************/
  491. HRESULT _stdcall CEnumDC::Clone(IEnumWIA_DEV_CAPS **ppIEnum)
  492. {
  493. DBG_FN(CEnumDC::Clone);
  494. HRESULT hr = S_OK;
  495. WIA_DEV_CAP *pDevCaps;
  496. CEnumDC *pClone;
  497. *ppIEnum = NULL;
  498. //
  499. // Create the clone
  500. //
  501. pClone = new CEnumDC();
  502. if (!pClone) {
  503. DBG_ERR(("CEnumDC::Clone, new CEnumDC failed"));
  504. return E_OUTOFMEMORY;
  505. }
  506. //
  507. // Copy the registered event handler info
  508. //
  509. pDevCaps = (WIA_DEV_CAP *) LocalAlloc(LPTR, m_lCount * sizeof(WIA_DEV_CAP));
  510. if (! pDevCaps) {
  511. hr = E_OUTOFMEMORY;
  512. } else {
  513. hr = CopyCaps(m_lCount, m_pDeviceCapabilities, pDevCaps);
  514. if (SUCCEEDED(hr)) {
  515. //
  516. // Initialize other members of the clone
  517. //
  518. pClone->m_pCWiaItem = NULL;
  519. pClone->m_ulFlags = 0;
  520. pClone->m_lCount = m_lCount;
  521. pClone->m_ulIndex = m_ulIndex;
  522. pClone->m_pDeviceCapabilities = pDevCaps;
  523. } else {
  524. LocalFree(pDevCaps);
  525. pDevCaps = NULL;
  526. hr = E_OUTOFMEMORY;
  527. }
  528. }
  529. if (SUCCEEDED(hr)) {
  530. pClone->AddRef();
  531. *ppIEnum = pClone;
  532. } else {
  533. delete pClone;
  534. }
  535. return hr;
  536. }
  537. /**************************************************************************\
  538. * CEnumWiaDC::GetCount
  539. *
  540. * Returns the number of elements stored in this enumerator.
  541. *
  542. * Arguments:
  543. *
  544. * pcelt - address of ULONG where to put the number of elements.
  545. *
  546. * Return Value:
  547. *
  548. * Status - S_OK if successful
  549. * E_FAIL if failed
  550. *
  551. * History:
  552. *
  553. * 05/07/99 Original Version
  554. *
  555. \**************************************************************************/
  556. HRESULT _stdcall CEnumDC::GetCount(ULONG *pcelt)
  557. {
  558. DBG_FN(CEnumDC::GetCount);
  559. if (pcelt) {
  560. *pcelt = 0;
  561. }
  562. //
  563. // Check that we actually have a capabilities list.
  564. //
  565. if(m_pDeviceCapabilities) {
  566. if (pcelt) {
  567. *pcelt = m_lCount;
  568. }
  569. }
  570. return S_OK;
  571. }