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.

4072 lines
133 KiB

  1. /*******************************************************************************
  2. *
  3. * (C) COPYRIGHT MICROSOFT CORP., 1997
  4. *
  5. * TITLE: Helpers.Cpp
  6. *
  7. * VERSION: 2.0
  8. *
  9. * AUTHOR: ReedB
  10. *
  11. * DATE: 12 Mar, 1999
  12. *
  13. * DESCRIPTION:
  14. * Helpers for WIA device manager.
  15. *
  16. *******************************************************************************/
  17. #include "precomp.h"
  18. #include "stiexe.h"
  19. #include <wiadef.h>
  20. #include <icm.h>
  21. #include "wiamindr.h"
  22. #include "devinfo.h"
  23. #define WIA_DECLARE_MANAGED_PROPS
  24. #include "helpers.h"
  25. #include "shpriv.h"
  26. #include "sticfunc.h"
  27. extern "C"
  28. {
  29. //
  30. // From Terminal services
  31. //
  32. #include <winsta.h>
  33. #include <syslib.h>
  34. }
  35. /**************************************************************************\
  36. * LockWiaDevice
  37. *
  38. * Wrapper to request Lock Manager to lock device.
  39. *
  40. * Arguments:
  41. *
  42. * pIWiaMiniDrv - Pointer to mini-driver interface.
  43. * pIWiaItem - Pointer to the wia item
  44. *
  45. * Return Value:
  46. *
  47. * Status
  48. *
  49. * History:
  50. *
  51. * 3/1/1999 Original Version
  52. *
  53. \**************************************************************************/
  54. HRESULT _stdcall LockWiaDevice(IWiaItem *pIWiaItem)
  55. {
  56. DBG_FN(::LockWiaDevice);
  57. HRESULT hr = WIA_ERROR_OFFLINE;
  58. LONG lFlags = 0;
  59. CWiaItem *pItem = (CWiaItem*) pIWiaItem;
  60. if (pItem->m_pActiveDevice) {
  61. hr = pItem->m_pActiveDevice->m_DrvWrapper.WIA_drvLockWiaDevice(
  62. (BYTE*) pItem,
  63. lFlags,
  64. &(pItem->m_lLastDevErrVal));
  65. }
  66. return hr;
  67. }
  68. /**************************************************************************\
  69. * UnLockWiaDevice
  70. *
  71. * Wrapper to request Lock Manager to unlock device.
  72. *
  73. * Arguments:
  74. *
  75. * pIWiaMiniDrv - Pointer to mini-driver interface.
  76. * pIWiaItem - Pointer to the wia item
  77. *
  78. * Return Value:
  79. *
  80. * Status
  81. *
  82. * History:
  83. *
  84. * 3/1/1999 Original Version
  85. *
  86. \**************************************************************************/
  87. HRESULT _stdcall UnLockWiaDevice(IWiaItem *pIWiaItem)
  88. {
  89. DBG_FN(::UnLockWiaDevice);
  90. HRESULT hr = WIA_ERROR_OFFLINE;
  91. LONG lFlags = 0;
  92. LONG lDevErrVal;
  93. CWiaItem *pItem = (CWiaItem*) pIWiaItem;
  94. if (pItem->m_pActiveDevice) {
  95. hr = pItem->m_pActiveDevice->m_DrvWrapper.WIA_drvUnLockWiaDevice(
  96. (BYTE*) pItem,
  97. lFlags,
  98. &(pItem->m_lLastDevErrVal));
  99. }
  100. return hr;
  101. }
  102. /**************************************************************************\
  103. * ValidateWiaItem
  104. *
  105. * Validate a CWiaItem.
  106. *
  107. * Arguments:
  108. *
  109. *
  110. * Return Value:
  111. *
  112. * None
  113. *
  114. * History:
  115. *
  116. * 3/1/1999 Original Version
  117. *
  118. \**************************************************************************/
  119. HRESULT _stdcall ValidateWiaItem(
  120. IWiaItem *pIWiaItem)
  121. {
  122. DBG_FN(::ValidateWiaItem);
  123. HRESULT hr = E_POINTER;
  124. if (pIWiaItem) {
  125. CWiaItem *pWiaItem = (CWiaItem*)pIWiaItem;
  126. if (!IsBadReadPtr(pWiaItem, sizeof(CWiaItem))) {
  127. if (pWiaItem->m_ulSig == CWIAITEM_SIG) {
  128. return S_OK;
  129. }
  130. else {
  131. DBG_ERR(("ValidateWiaItem, invalid signature: %X", pWiaItem->m_ulSig));
  132. hr = E_INVALIDARG;
  133. }
  134. }
  135. else {
  136. DBG_ERR(("ValidateWiaItem, NULL WIA item pointer"));
  137. }
  138. }
  139. else {
  140. DBG_ERR(("ValidateWiaItem, NULL WIA item pointer"));
  141. }
  142. return hr;
  143. }
  144. /**************************************************************************\
  145. * ValidateWiaDrvItemAccess
  146. *
  147. * Validate a CWiaDrvItem.
  148. *
  149. * Arguments:
  150. *
  151. *
  152. * Return Value:
  153. *
  154. * None
  155. *
  156. * History:
  157. *
  158. * 3/1/1999 Original Version
  159. *
  160. \**************************************************************************/
  161. HRESULT _stdcall ValidateWiaDrvItemAccess(
  162. CWiaDrvItem *pWiaDrvItem)
  163. {
  164. DBG_FN(::ValidateWiaDrvItemAccess);
  165. HRESULT hr = S_OK;
  166. if (pWiaDrvItem) {
  167. //
  168. // Verify access to the driver item.
  169. //
  170. if (IsBadReadPtr(pWiaDrvItem, sizeof(CWiaDrvItem))) {
  171. DBG_ERR(("ValidateWiaDrvItemAccess, bad pointer, pWiaDrvItem: %X", pWiaDrvItem));
  172. return E_INVALIDARG;
  173. }
  174. //
  175. // Get the driver item flags.
  176. //
  177. LONG lItemFlags;
  178. pWiaDrvItem->GetItemFlags(&lItemFlags);
  179. //
  180. // Verify the item has been initialized and was inserted in the
  181. // driver item tree at one time.
  182. //
  183. if (lItemFlags == WiaItemTypeFree) {
  184. DBG_ERR(("ValidateWiaDrvItemAccess, application attempting access of unintialized or free item: %0x08X", pWiaDrvItem));
  185. return E_INVALIDARG;
  186. }
  187. if (lItemFlags & WiaItemTypeDeleted) {
  188. DBG_ERR(("ValidateWiaDrvItemAccess, application attempting access of deleted item: %0x08X", pWiaDrvItem));
  189. return WIA_ERROR_ITEM_DELETED;
  190. }
  191. if (lItemFlags & WiaItemTypeDisconnected) {
  192. DBG_ERR(("ValidateWiaDrvItemAccess, application attempting access of disconnected item: %0x08X", pWiaDrvItem));
  193. return WIA_ERROR_OFFLINE;
  194. }
  195. hr = S_OK;
  196. }
  197. else {
  198. DBG_ERR(("ValidateWiaDrvItemAccess, Bad pWiaDrvItem pointer"));
  199. hr = E_INVALIDARG;
  200. }
  201. return hr;
  202. }
  203. /**************************************************************************\
  204. * GetNameFromWiaPropId
  205. *
  206. * Map a WIA property ID to it's corresponding string name.
  207. *
  208. * Arguments:
  209. *
  210. *
  211. * Return Value:
  212. *
  213. * None
  214. *
  215. * History:
  216. *
  217. * 3/1/1999 Original Version
  218. *
  219. \**************************************************************************/
  220. #define MAP_SIZE (sizeof(g_wiaPropIdToName) / sizeof(WIA_PROPID_TO_NAME))
  221. LPOLESTR GetNameFromWiaPropId(PROPID propid)
  222. {
  223. for (INT i = 0; g_wiaPropIdToName[i].propid != 0; i++) {
  224. if (propid == g_wiaPropIdToName[i].propid) {
  225. return g_wiaPropIdToName[i].pszName;
  226. }
  227. }
  228. return g_wiaPropIdToName[i].pszName;
  229. }
  230. /**************************************************************************\
  231. * ReportReadWriteMultipleError
  232. *
  233. * Report errors that occur during ReadMultiple and WriteMultiple calls.
  234. *
  235. * Arguments:
  236. *
  237. * hr - Result from ReadMultiple or WriteMultiple call.
  238. * pszWhere - Where the API was called from (function/method name).
  239. * pszWhat - Optional, which Read/WriteMultiple, used if more than
  240. * one Read/WriteMultiple called in function/method.
  241. * bRead - TRUE for ReadMultiple.
  242. * cpspec - Count of PROPSPEC's in rgpspec.
  243. * rgpspec - Array of PROPSPEC's.
  244. *
  245. * Return Value:
  246. *
  247. * None
  248. *
  249. * History:
  250. *
  251. * 3/1/1999 Original Version
  252. *
  253. \**************************************************************************/
  254. void _stdcall ReportReadWriteMultipleError(
  255. HRESULT hr,
  256. LPSTR pszWhere,
  257. LPSTR pszWhat,
  258. BOOL bRead,
  259. ULONG cpspec,
  260. const PROPSPEC propspec[])
  261. {
  262. DBG_FN(::ReportReadWriteMultipleError);
  263. if (SUCCEEDED(hr)) {
  264. if (hr == S_FALSE) {
  265. if (bRead) {
  266. if (pszWhat) {
  267. DBG_ERR(("%s, ReadMultiple property not found, %s", pszWhere, pszWhat));
  268. }
  269. else {
  270. DBG_ERR(("%s, ReadMultiple property not found", pszWhere));
  271. }
  272. }
  273. else {
  274. if (pszWhat) {
  275. DBG_ERR(("%s, WriteMultiple returned S_FALSE, %s", pszWhere, pszWhat));
  276. }
  277. else {
  278. DBG_ERR(("%s, WriteMultiple returned S_FALSE", pszWhere));
  279. }
  280. }
  281. }
  282. else {
  283. return; // No error.
  284. }
  285. }
  286. else {
  287. if (bRead) {
  288. DBG_ERR(("%s, ReadMultiple failed, %s Error 0x%X", pszWhere, pszWhat ? pszWhat : "(null)", hr));
  289. }
  290. else {
  291. DBG_ERR(("%s, WriteMultiple failed, %s Error 0x%X", pszWhere, pszWhat ? pszWhat : "(null)", hr));
  292. }
  293. }
  294. //
  295. // Output specification information.
  296. //
  297. if (cpspec == 0) {
  298. DBG_ERR((" count of PROPSPEC's is zero"));
  299. }
  300. else if (cpspec == 1) {
  301. if (propspec[0].ulKind == PRSPEC_PROPID) {
  302. DBG_ERR((" property ID: %d, property name: %S", propspec[0].propid, GetNameFromWiaPropId(propspec[0].propid)));
  303. }
  304. else if (propspec[0].ulKind == PRSPEC_LPWSTR) {
  305. DBG_ERR((" property name: %S", propspec[0].lpwstr));
  306. }
  307. else {
  308. DBG_ERR((" bad property specification"));
  309. }
  310. }
  311. else {
  312. DBG_ERR((" count of PROPSPEC's is: %d", cpspec));
  313. for (UINT i = 0; i < cpspec; i++) {
  314. if (propspec[i].ulKind == PRSPEC_PROPID) {
  315. DBG_ERR((" property ID: %d, property name: %S", propspec[i].propid, GetNameFromWiaPropId(propspec[i].propid)));
  316. }
  317. else if (propspec[i].ulKind == PRSPEC_LPWSTR) {
  318. DBG_ERR((" index: %d, property name: %S", i, propspec[i].lpwstr));
  319. }
  320. else {
  321. DBG_ERR((" index: %d, bad property specification", i));
  322. }
  323. }
  324. }
  325. }
  326. /*******************************************************************************
  327. *
  328. * ReadPropStr
  329. *
  330. * DESCRIPTION:
  331. *
  332. * PARAMETERS:
  333. *
  334. *******************************************************************************/
  335. HRESULT _stdcall ReadPropStr(
  336. PROPID propid,
  337. IPropertyStorage *pIPropStg,
  338. BSTR *pbstr)
  339. {
  340. DBG_FN(::ReadPropStr);
  341. HRESULT hr;
  342. PROPSPEC PropSpec[1];
  343. PROPVARIANT PropVar[1];
  344. UINT cbSize;
  345. *pbstr = NULL;
  346. memset(PropVar, 0, sizeof(PropVar));
  347. PropSpec[0].ulKind = PRSPEC_PROPID;
  348. PropSpec[0].propid = propid;
  349. hr = pIPropStg->ReadMultiple(1, PropSpec, PropVar);
  350. if (SUCCEEDED(hr)) {
  351. if (PropVar[0].pwszVal) {
  352. *pbstr = SysAllocString(PropVar[0].pwszVal);
  353. }
  354. else {
  355. *pbstr = SysAllocString(L"");
  356. }
  357. if (*pbstr == NULL) {
  358. DBG_ERR(("ReadPropStr, SysAllocString failed"));
  359. hr = E_OUTOFMEMORY;
  360. }
  361. PropVariantClear(PropVar);
  362. }
  363. else {
  364. DBG_ERR(("ReadPropStr, ReadMultiple of propid: %d, failed", propid));
  365. }
  366. return hr;
  367. }
  368. HRESULT _stdcall ReadPropStr(
  369. PROPID propid,
  370. IWiaPropertyStorage *pIWiaPropStg,
  371. BSTR *pbstr)
  372. {
  373. DBG_FN(::ReadPropStr);
  374. HRESULT hr;
  375. PROPSPEC PropSpec[1];
  376. PROPVARIANT PropVar[1];
  377. UINT cbSize;
  378. *pbstr = NULL;
  379. memset(PropVar, 0, sizeof(PropVar));
  380. PropSpec[0].ulKind = PRSPEC_PROPID;
  381. PropSpec[0].propid = propid;
  382. hr = pIWiaPropStg->ReadMultiple(1, PropSpec, PropVar);
  383. if (SUCCEEDED(hr)) {
  384. if (PropVar[0].pwszVal) {
  385. *pbstr = SysAllocString(PropVar[0].pwszVal);
  386. }
  387. else {
  388. *pbstr = SysAllocString(L"");
  389. }
  390. if (*pbstr == NULL) {
  391. DBG_ERR(("ReadPropStr, SysAllocString failed"));
  392. hr = E_OUTOFMEMORY;
  393. }
  394. PropVariantClear(PropVar);
  395. }
  396. else {
  397. DBG_ERR(("ReadPropStr, ReadMultiple of propid: %d, failed", propid));
  398. }
  399. return hr;
  400. }
  401. HRESULT _stdcall ReadPropStr(IUnknown *pDevice, PROPID propid, BSTR *pbstr)
  402. {
  403. DBG_FN(::ReadPropStr);
  404. HRESULT hr;
  405. PROPVARIANT pv[1];
  406. PROPSPEC ps[1];
  407. IWiaPropertyStorage *pIWiaPropStg;
  408. *pbstr = NULL;
  409. hr = pDevice->QueryInterface(IID_IWiaPropertyStorage, (void**)&pIWiaPropStg);
  410. if (SUCCEEDED(hr)) {
  411. PropVariantInit(pv);
  412. ps[0].ulKind = PRSPEC_PROPID;
  413. ps[0].propid = propid;
  414. hr = pIWiaPropStg->ReadMultiple(1, ps, pv);
  415. if (hr == S_OK) {
  416. *pbstr = SysAllocString(pv[0].pwszVal);
  417. } else {
  418. DBG_ERR(("ReadPropStr, ReadMultiple for propid: %d, failed", propid));
  419. }
  420. PropVariantClear(pv);
  421. pIWiaPropStg->Release();
  422. } else {
  423. DBG_ERR(("ReadPropStr, QI for IWiaPropertyStorage failed"));
  424. }
  425. return hr;
  426. }
  427. /*******************************************************************************
  428. *
  429. * ReadPropLong
  430. *
  431. * DESCRIPTION:
  432. *
  433. * PARAMETERS:
  434. *
  435. *******************************************************************************/
  436. HRESULT _stdcall ReadPropLong(PROPID propid, IPropertyStorage *pIPropStg, LONG *plval)
  437. {
  438. DBG_FN(::ReadPropLong);
  439. HRESULT hr;
  440. PROPSPEC PropSpec[1];
  441. PROPVARIANT PropVar[1];
  442. UINT cbSize;
  443. memset(PropVar, 0, sizeof(PropVar));
  444. PropSpec[0].ulKind = PRSPEC_PROPID;
  445. PropSpec[0].propid = propid;
  446. hr = pIPropStg->ReadMultiple(1, PropSpec, PropVar);
  447. if (SUCCEEDED(hr)) {
  448. *plval = PropVar[0].lVal;
  449. }
  450. else {
  451. DBG_ERR(("ReadPropLong, ReadMultiple of propid: %d, failed", propid));
  452. }
  453. return hr;
  454. }
  455. HRESULT _stdcall ReadPropLong(IUnknown *pDevice, PROPID propid, LONG *plval)
  456. {
  457. DBG_FN(::ReadPropLong);
  458. HRESULT hr;
  459. PROPVARIANT pv[1];
  460. PROPSPEC ps[1];
  461. IWiaPropertyStorage *pIWiaPropStg;
  462. *plval = 0;
  463. hr = pDevice->QueryInterface(IID_IWiaPropertyStorage, (void**)&pIWiaPropStg);
  464. if (SUCCEEDED(hr)) {
  465. PropVariantInit(pv);
  466. ps[0].ulKind = PRSPEC_PROPID;
  467. ps[0].propid = propid;
  468. hr = pIWiaPropStg->ReadMultiple(1, ps, pv);
  469. if (hr == S_OK) {
  470. *plval = pv[0].lVal;
  471. } else {
  472. DBG_ERR(("ReadPropLong, ReadMultiple of propid: %d, failed", propid));
  473. }
  474. pIWiaPropStg->Release();
  475. }
  476. else {
  477. DBG_ERR(("ReadPropLong, QI of IID_IWiaPropertyStorage failed"));
  478. }
  479. return hr;
  480. }
  481. /**************************************************************************\
  482. * WritePropStr
  483. *
  484. * Writes a string property to the specified property storage. This is an
  485. * overloaded function.
  486. *
  487. * Arguments:
  488. *
  489. * propid - propid of the property
  490. * pIPropStg - a pointer to the property storage
  491. * bstr - the string to write
  492. *
  493. * Return Value:
  494. *
  495. * Status
  496. *
  497. * History:
  498. *
  499. * 10/5/1999 Original Version
  500. *
  501. \**************************************************************************/
  502. HRESULT _stdcall WritePropStr(PROPID propid, IPropertyStorage *pIPropStg, BSTR bstr)
  503. {
  504. DBG_FN(::WritePropStr);
  505. HRESULT hr;
  506. PROPSPEC propspec[1];
  507. PROPVARIANT propvar[1];
  508. propspec[0].ulKind = PRSPEC_PROPID;
  509. propspec[0].propid = propid;
  510. propvar[0].vt = VT_BSTR;
  511. propvar[0].pwszVal = bstr;
  512. hr = pIPropStg->WriteMultiple(1, propspec, propvar, 2);
  513. if (FAILED(hr)) {
  514. ReportReadWriteMultipleError( hr,
  515. "Helpers WritePropStr",
  516. NULL,
  517. FALSE,
  518. 1,
  519. propspec);
  520. }
  521. return hr;
  522. }
  523. /**************************************************************************\
  524. * WritePropStr
  525. *
  526. * Writes a string property. This is an overloaded function which calls
  527. * the other WritePropStr.
  528. *
  529. *
  530. * Arguments:
  531. *
  532. * pDevice - A pointer to a device item which will be queried for
  533. * it's IWiaPropertyStorage.
  534. * propid - propid of the property
  535. * bstr - the string to write
  536. *
  537. * Return Value:
  538. *
  539. * Status
  540. *
  541. * History:
  542. *
  543. * 10/5/1999 Original Version
  544. *
  545. \**************************************************************************/
  546. HRESULT _stdcall WritePropStr(IUnknown *pDevice, PROPID propid, BSTR bstr)
  547. {
  548. DBG_FN(::WritePropStr);
  549. HRESULT hr;
  550. PROPVARIANT pv[1];
  551. PROPSPEC ps[1];
  552. IWiaPropertyStorage *pIWiaPropStg;
  553. PropVariantInit(pv);
  554. hr = pDevice->QueryInterface(IID_IWiaPropertyStorage, (void**)&pIWiaPropStg);
  555. if (SUCCEEDED(hr)) {
  556. ps[0].ulKind = PRSPEC_PROPID;
  557. ps[0].propid = propid;
  558. pv[0].vt = VT_BSTR;
  559. pv[0].pwszVal = bstr;
  560. hr = pIWiaPropStg->WriteMultiple(1, ps, pv, 2);
  561. if (FAILED(hr)) {
  562. ReportReadWriteMultipleError( hr,
  563. "Helpers WritePropStr",
  564. NULL,
  565. FALSE,
  566. 1,
  567. ps);
  568. }
  569. pIWiaPropStg->Release();
  570. }
  571. else {
  572. DBG_ERR(("WritePropStr, QI of IID_IWiaPropertyStorage failed"));
  573. }
  574. return hr;
  575. }
  576. /**************************************************************************\
  577. * WritePropLong
  578. *
  579. * Writes a long property to the specified property storage. This is an
  580. * overloaded function.
  581. *
  582. * Arguments:
  583. *
  584. * propid - propid of the property
  585. * pIPropStg - a pointer to the property storage
  586. * lVal - the LONG value to write
  587. *
  588. * Return Value:
  589. *
  590. * Status
  591. *
  592. * History:
  593. *
  594. * 10/5/1999 Original Version
  595. *
  596. \**************************************************************************/
  597. HRESULT _stdcall WritePropLong(PROPID propid, IPropertyStorage *pIPropStg, LONG lVal)
  598. {
  599. DBG_FN(::WritePropLong);
  600. HRESULT hr;
  601. PROPSPEC propspec[1];
  602. PROPVARIANT propvar[1];
  603. propspec[0].ulKind = PRSPEC_PROPID;
  604. propspec[0].propid = propid;
  605. propvar[0].vt = VT_I4;
  606. propvar[0].lVal = lVal;
  607. hr = pIPropStg->WriteMultiple(1, propspec, propvar, 2);
  608. if (FAILED(hr)) {
  609. ReportReadWriteMultipleError( hr,
  610. "Helpers WritePropLong",
  611. NULL,
  612. FALSE,
  613. 1,
  614. propspec);
  615. }
  616. return hr;
  617. }
  618. /**************************************************************************\
  619. * WritePropLong
  620. *
  621. * Writes a long property. This is an overloaded function which calls
  622. * the other WritePropLong.
  623. *
  624. *
  625. * Arguments:
  626. *
  627. * pDevice - A pointer to a device item which will be queried for
  628. * it's IWiaPropertyStorage.
  629. * propid - propid of the property
  630. * lVal - the LONG value to write
  631. *
  632. * Return Value:
  633. *
  634. * Status
  635. *
  636. * History:
  637. *
  638. * 10/5/1999 Original Version
  639. *
  640. \**************************************************************************/
  641. HRESULT _stdcall WritePropLong(IUnknown *pDevice, PROPID propid, LONG lVal)
  642. {
  643. DBG_FN(::WritePropLong);
  644. HRESULT hr;
  645. PROPVARIANT pv[1];
  646. PROPSPEC ps[1];
  647. IWiaPropertyStorage *pIWiaPropStg;
  648. hr = pDevice->QueryInterface(IID_IWiaPropertyStorage, (void**)&pIWiaPropStg);
  649. if (SUCCEEDED(hr)) {
  650. PropVariantInit(pv);
  651. ps[0].ulKind = PRSPEC_PROPID;
  652. ps[0].propid = propid;
  653. pv[0].vt = VT_I4;
  654. pv[0].lVal = lVal;
  655. hr = pIWiaPropStg->WriteMultiple(1, ps, pv, 2);
  656. if (FAILED(hr)) {
  657. ReportReadWriteMultipleError( hr,
  658. "Helpers WritePropLong",
  659. NULL,
  660. FALSE,
  661. 1,
  662. ps);
  663. }
  664. pIWiaPropStg->Release();
  665. }
  666. else {
  667. DBG_ERR(("WritePropLong, QI of IID_IWiaPropertyStorage failed"));
  668. }
  669. return hr;
  670. }
  671. /**************************************************************************\
  672. * InitMiniDrvContext
  673. *
  674. * Initialize a mini driver context from an items properties.
  675. *
  676. * Arguments:
  677. *
  678. * pItem - Pointer to the wia item
  679. * pmdtc - pointer to mini driver context
  680. *
  681. * Return Value:
  682. *
  683. * Status
  684. *
  685. * History:
  686. *
  687. * 6/16/1999 Original Version
  688. *
  689. \**************************************************************************/
  690. HRESULT _stdcall InitMiniDrvContext(
  691. IWiaItem *pItem,
  692. PMINIDRV_TRANSFER_CONTEXT pmdtc)
  693. {
  694. DBG_FN(::InitMiniDrvContext);
  695. //
  696. // Get a property storage from the item.
  697. //
  698. HRESULT hr;
  699. IPropertyStorage *pIPropStg;
  700. hr = ((CWiaItem*)pItem)->GetItemPropStreams(&pIPropStg, NULL, NULL, NULL);
  701. if (FAILED(hr)) {
  702. return hr;
  703. }
  704. //
  705. // Setup the minidriver transfer context. Fill in transfer context
  706. // members which derive from item properties.
  707. //
  708. memset(pmdtc, 0, sizeof(MINIDRV_TRANSFER_CONTEXT));
  709. pmdtc->lSize = sizeof(MINIDRV_TRANSFER_CONTEXT);
  710. #define NUM_IMAGE_SPEC 9
  711. static PROPSPEC PropSpec[NUM_IMAGE_SPEC] =
  712. {
  713. {PRSPEC_PROPID, WIA_IPA_PIXELS_PER_LINE},
  714. {PRSPEC_PROPID, WIA_IPA_NUMBER_OF_LINES},
  715. {PRSPEC_PROPID, WIA_IPA_DEPTH},
  716. {PRSPEC_PROPID, WIA_IPS_XRES},
  717. {PRSPEC_PROPID, WIA_IPS_YRES},
  718. {PRSPEC_PROPID, WIA_IPA_COMPRESSION},
  719. {PRSPEC_PROPID, WIA_IPA_ITEM_SIZE},
  720. {PRSPEC_PROPID, WIA_IPA_FORMAT},
  721. {PRSPEC_PROPID, WIA_IPA_TYMED}
  722. };
  723. PROPVARIANT PropVar[NUM_IMAGE_SPEC];
  724. memset(PropVar, 0, sizeof(PropVar));
  725. hr = pIPropStg->ReadMultiple(NUM_IMAGE_SPEC, PropSpec, PropVar);
  726. if (SUCCEEDED(hr)) {
  727. pmdtc->lWidthInPixels = PropVar[0].lVal;
  728. pmdtc->lLines = PropVar[1].lVal;
  729. pmdtc->lDepth = PropVar[2].lVal;
  730. pmdtc->lXRes = PropVar[3].lVal;
  731. pmdtc->lYRes = PropVar[4].lVal;
  732. pmdtc->lCompression = PropVar[5].lVal;
  733. pmdtc->lItemSize = PropVar[6].lVal;
  734. pmdtc->guidFormatID = *PropVar[7].puuid;
  735. pmdtc->tymed = PropVar[8].lVal;
  736. FreePropVariantArray(NUM_IMAGE_SPEC, PropVar);
  737. }
  738. else {
  739. ReportReadWriteMultipleError(hr, "InitMiniDrvContext", NULL, TRUE, NUM_IMAGE_SPEC, PropSpec);
  740. }
  741. return hr;
  742. }
  743. /**************************************************************************\
  744. * GetPropertyAttributesHelper
  745. *
  746. * Get the access flags and valid values for a property. Used by
  747. * GetPropertyAttributes in the service and by WIA Items. Parameter
  748. * validation is done beforehand by caller.
  749. *
  750. * Arguments:
  751. *
  752. * pItem - Pointer to WIA item
  753. * cPropSpec - The number of properties
  754. * pPropSpec - array of property specification.
  755. * pulAccessFlags - array of LONGs access flags.
  756. * ppvValidValues - Pointer to returned valid values.
  757. *
  758. * Return Value:
  759. *
  760. * Status
  761. *
  762. * History:
  763. *
  764. * 1/19/1999 Original Version
  765. * 05/14/1999 Updated to return multiple attribute values
  766. * 30/06/1999 Parameter validation removed,
  767. *
  768. \**************************************************************************/
  769. HRESULT _stdcall GetPropertyAttributesHelper(
  770. IWiaItem *pItem,
  771. LONG cPropSpec,
  772. PROPSPEC *pPropSpec,
  773. ULONG *pulAccessFlags,
  774. PROPVARIANT *ppvValidValues)
  775. {
  776. DBG_FN(::GetPropertyAttributesHelper);
  777. HRESULT hr;
  778. memset(pulAccessFlags, 0, sizeof(ULONG) * cPropSpec);
  779. memset(ppvValidValues, 0, sizeof(PROPVARIANT) * cPropSpec);
  780. //
  781. // Get the item's internal property storage pointers.
  782. //
  783. IPropertyStorage *pIPropAccessStg;
  784. IPropertyStorage *pIPropValidStg;
  785. hr = ((CWiaItem*)pItem)->GetItemPropStreams(NULL,
  786. &pIPropAccessStg,
  787. &pIPropValidStg,
  788. NULL);
  789. if (FAILED(hr)) {
  790. return hr;
  791. }
  792. //
  793. // Get the Access flags for the properties. Use pPropVar as
  794. // temporary storage.
  795. //
  796. hr = pIPropAccessStg->ReadMultiple(cPropSpec, pPropSpec, ppvValidValues);
  797. if (SUCCEEDED(hr)) {
  798. //
  799. // Fill in the returned access flags
  800. //
  801. for (int flagIndex = 0; flagIndex < cPropSpec; flagIndex++) {
  802. pulAccessFlags[flagIndex] = ppvValidValues[flagIndex].ulVal;
  803. }
  804. //
  805. // Get the valid values
  806. //
  807. hr = pIPropValidStg->ReadMultiple(cPropSpec, pPropSpec, ppvValidValues);
  808. if (FAILED(hr)) {
  809. DBG_ERR(("GetPropertyAttributesHelper, ReadMultiple failed, could not get valid values (0x%X)", hr));
  810. }
  811. } else {
  812. DBG_ERR(("GetPropertyAttributesHelper, ReadMultiple failed, could not get access flags (0x%X)", hr));
  813. }
  814. if (FAILED(hr)) {
  815. //
  816. // Was not successful, so clear the return values and report
  817. // which properties caused the error.
  818. //
  819. FreePropVariantArray(cPropSpec, ppvValidValues);
  820. memset(pulAccessFlags, 0, sizeof(ULONG) * cPropSpec);
  821. ReportReadWriteMultipleError(hr, "GetPropertyAttributesHelper",
  822. NULL,
  823. TRUE,
  824. cPropSpec,
  825. pPropSpec);
  826. }
  827. return hr;
  828. }
  829. /**************************************************************************\
  830. * GetMinAndMaxLong
  831. *
  832. * This helper method is called to get the Min and Max values for a
  833. * WIA_PROP_RANGE property of type VT_I4.
  834. *
  835. * Arguments:
  836. *
  837. * pWiasContext - a pointer to the item context
  838. * propid - identifies the property we're interested in.
  839. * plMin - the address of a LONG to receive the min value
  840. * plMax - the address of a LONG to receive the max value
  841. *
  842. * Return Value:
  843. *
  844. * Status
  845. *
  846. * History:
  847. *
  848. * 04/04/1999 Original Version
  849. *
  850. \**************************************************************************/
  851. HRESULT _stdcall GetMinAndMaxLong(
  852. BYTE* pWiasContext,
  853. PROPID propid,
  854. LONG *plMin,
  855. LONG *plMax)
  856. {
  857. DBG_FN(::GetMinAndMaxLong);
  858. IPropertyStorage *pIValidStg;
  859. PROPSPEC ps[1];
  860. PROPVARIANT pv[1];
  861. HRESULT hr;
  862. ps[0].ulKind = PRSPEC_PROPID;
  863. ps[0].propid = propid;
  864. PropVariantInit(pv);
  865. hr = ((CWiaItem*) pWiasContext)->GetItemPropStreams(NULL,
  866. NULL,
  867. &pIValidStg,
  868. NULL);
  869. if (SUCCEEDED(hr)) {
  870. hr = pIValidStg->ReadMultiple(1, ps, pv);
  871. if (SUCCEEDED(hr)) {
  872. if (plMin) {
  873. *plMin = pv[0].cal.pElems[WIA_RANGE_MIN];
  874. };
  875. if (plMax) {
  876. *plMax = pv[0].cal.pElems[WIA_RANGE_MAX];
  877. };
  878. PropVariantClear(pv);
  879. } else {
  880. DBG_ERR(("GetMinAndMaxLong, Reading property %d (%ws) failed",propid,GetNameFromWiaPropId(propid)));
  881. };
  882. } else {
  883. DBG_ERR(("GetMinAndMaxLong, Could not get valid property stream"));
  884. }
  885. return hr;
  886. }
  887. /**************************************************************************\
  888. * CheckXResAndUpdate
  889. *
  890. * This helper method is called to check whether WIA_IPS_XRES property
  891. * is changed. When this property changes, other dependant
  892. * properties and their valid values must also be changed.
  893. *
  894. * Arguments:
  895. *
  896. * pWiasContext - a pointer to the item context whose properties have
  897. * changed.
  898. * pContext - a pointer to the property context (which indicates
  899. * which properties are being written).
  900. * lWidth - the width of the maximum scan area in one thousandth's
  901. * of an inch. Generally, this would be the horizontal
  902. * bed size.
  903. *
  904. * Return Value:
  905. *
  906. * Status
  907. *
  908. * History:
  909. *
  910. * 04/04/1999 Original Version
  911. *
  912. \**************************************************************************/
  913. HRESULT _stdcall CheckXResAndUpdate(
  914. BYTE *pWiasContext,
  915. WIA_PROPERTY_CONTEXT *pContext,
  916. LONG lWidth)
  917. {
  918. DBG_FN(::CheckXResAndUpdate);
  919. LONG lMinXExt, lMaxXExtOld, lMaxXPosOld;
  920. LONG lMax, lExt;
  921. WIAS_CHANGED_VALUE_INFO cviXRes, cviXPos, cviXExt;
  922. HRESULT hr = S_OK;
  923. //
  924. // Call wiasGetChangedValue for XResolution. XResolution is checked first
  925. // since it's not dependant on any other property. All properties in
  926. // this method that follow are dependant properties of XResolution.
  927. //
  928. hr = wiasGetChangedValueLong(pWiasContext,
  929. pContext,
  930. FALSE,
  931. WIA_IPS_XRES,
  932. &cviXRes);
  933. if (FAILED(hr)) {
  934. return hr;
  935. }
  936. //
  937. // Call wiasGetChangedValue for XPos. XPos is a dependant property of
  938. // XResolution whose valid value changes according to what the current
  939. // value of XResolution is. This is so that when the resoltuion changes,
  940. // the XPos will be in the same relative position.
  941. //
  942. hr = wiasGetChangedValueLong(pWiasContext,
  943. pContext,
  944. cviXRes.bChanged,
  945. WIA_IPS_XPOS,
  946. &cviXPos);
  947. if (FAILED(hr)) {
  948. return hr;
  949. }
  950. //
  951. // Get the minimum and maximum extent values
  952. //
  953. hr = GetMinAndMaxLong(pWiasContext, WIA_IPS_XEXTENT, &lMinXExt, &lMaxXExtOld );
  954. if (FAILED(hr)) {
  955. return hr;
  956. }
  957. hr = GetMinAndMaxLong(pWiasContext, WIA_IPS_XPOS, NULL, &lMaxXPosOld );
  958. if (FAILED(hr)) {
  959. return hr;
  960. }
  961. //
  962. // lMax is the maximum horizontal position (in pixels) that XPos can be
  963. // set to. lXRes is DPI, lWidth is in one thousandth's of an inch,
  964. // and lMinXExt is in pixels.
  965. //
  966. lMax = ((cviXRes.Current.lVal * lWidth) / 1000) - lMinXExt;
  967. if (cviXRes.bChanged) {
  968. //
  969. // XRes changed, so calc and set new XPos valid values.
  970. //
  971. hr = wiasSetValidRangeLong(pWiasContext, WIA_IPS_XPOS, 0, 0, lMax, 1);
  972. if (SUCCEEDED(hr)) {
  973. //
  974. // If XPos is not one of the properties being written, then fold
  975. // it's current value.
  976. //
  977. if (!cviXPos.bChanged) {
  978. cviXPos.Current.lVal = (cviXPos.Old.lVal * lMax) / lMaxXPosOld;
  979. hr = wiasWritePropLong(pWiasContext, WIA_IPS_XPOS, cviXPos.Current.lVal);
  980. if (FAILED(hr)) {
  981. DBG_ERR(("CheckXResAndUpdate, could not write value for WIA_IPS_XPOS"));
  982. }
  983. }
  984. }
  985. }
  986. if (FAILED(hr)) {
  987. return hr;
  988. }
  989. //
  990. // Call wiasGetChangedValue for XExtent. XExtent is a dependant property of
  991. // both XResolution and XPos. The extent should be the same relative
  992. // size no matter what the resolution. However, if the resolution changes
  993. // or if the XPos is set, then the extent has the possibility of being
  994. // too large and so must be folded to a valid value.
  995. //
  996. hr = wiasGetChangedValueLong(pWiasContext,
  997. pContext,
  998. cviXRes.bChanged || cviXPos.bChanged,
  999. WIA_IPS_XEXTENT,
  1000. &cviXExt);
  1001. if (FAILED(hr)) {
  1002. return hr;
  1003. }
  1004. lExt = cviXExt.Current.lVal;
  1005. if (cviXRes.bChanged || cviXPos.bChanged) {
  1006. //
  1007. // XRes or XPos changed, so calc and set new XExtent valid values.
  1008. // The maximum valid value for XExtent is the maximum width allowed,
  1009. // starting at XPos.
  1010. //
  1011. lExt = (lMax - cviXPos.Current.lVal) + lMinXExt;
  1012. hr = wiasSetValidRangeLong(pWiasContext, WIA_IPS_XEXTENT, lMinXExt, lExt, lExt, 1);
  1013. if (SUCCEEDED(hr)) {
  1014. //
  1015. // If XExtent is not one of the properties being written, then fold
  1016. // it's current value.
  1017. //
  1018. if (!cviXExt.bChanged) {
  1019. LONG lXExtScaled;
  1020. //
  1021. // First scale the extent and then check whether it has to be
  1022. // truncated. The old extent should be scaled to keep the
  1023. // same relative size. If the resolution has not changed,
  1024. // then the scaling simply keeps the extent the same size.
  1025. //
  1026. lXExtScaled = (cviXExt.Old.lVal * lExt) / lMaxXExtOld;
  1027. if (lXExtScaled > lExt) {
  1028. //
  1029. // The extent is too large, so clip it.
  1030. //
  1031. lXExtScaled = lExt;
  1032. }
  1033. hr = wiasWritePropLong(pWiasContext, WIA_IPS_XEXTENT, lXExtScaled);
  1034. if (FAILED(hr)) {
  1035. DBG_ERR(("CheckXResAndUpdate, could not write value for WIA_IPS_XEXTENT"));
  1036. }
  1037. }
  1038. }
  1039. }
  1040. if (FAILED(hr)) {
  1041. return hr;
  1042. }
  1043. //
  1044. // Update read-only property : PIXELS_PER_LINE. The width in pixels
  1045. // of the scanned image is the same size as the XExtent.
  1046. //
  1047. hr = wiasReadPropLong(pWiasContext, WIA_IPS_XEXTENT, &lExt, NULL, TRUE);
  1048. if (SUCCEEDED(hr)) {
  1049. hr = wiasWritePropLong(pWiasContext, WIA_IPA_PIXELS_PER_LINE, lExt);
  1050. }
  1051. return hr;
  1052. }
  1053. /**************************************************************************\
  1054. * CheckYResAndUpdate
  1055. *
  1056. * This helper method is called to check whether WIA_IPS_YRES property
  1057. * is changed. When this property changes, other dependant
  1058. * properties and their valid values must also be changed. This is
  1059. * similar to the CheckXResAndUpdateChanged function.
  1060. *
  1061. * Arguments:
  1062. *
  1063. * pWiasContext - a pointer to the item context whose properties have
  1064. * changed.
  1065. * pContext - a pointer to the property context (which indicates
  1066. * which properties are being written).
  1067. * lHeight - the height of the maximum scan area in one
  1068. * thousandth's of an inch. Generally, this would be
  1069. * the vertical bed size.
  1070. *
  1071. * Return Value:
  1072. *
  1073. * Status
  1074. *
  1075. * History:
  1076. *
  1077. * 04/04/1999 Original Version
  1078. *
  1079. \**************************************************************************/
  1080. HRESULT _stdcall CheckYResAndUpdate(
  1081. BYTE *pWiasContext,
  1082. WIA_PROPERTY_CONTEXT *pContext,
  1083. LONG lHeight)
  1084. {
  1085. DBG_FN(::CheckYResAndUpdate);
  1086. LONG lMinYExt, lMaxYExtOld, lMaxYPosOld;
  1087. LONG lMax, lExt;
  1088. WIAS_CHANGED_VALUE_INFO cviYRes, cviYPos, cviYExt;
  1089. HRESULT hr = S_OK;
  1090. //
  1091. // Call wiasGetChangedValue for YResolution. YResolution is checked first
  1092. // since it's not dependant on any other property. All properties in
  1093. // this method that follow are dependant properties of YResolution.
  1094. //
  1095. hr = wiasGetChangedValueLong(pWiasContext,
  1096. pContext,
  1097. FALSE,
  1098. WIA_IPS_YRES,
  1099. &cviYRes);
  1100. if (FAILED(hr)) {
  1101. return hr;
  1102. }
  1103. //
  1104. // Call wiasGetChangedValue for YPos. YPos is a dependant property of
  1105. // YResolution whose valid value changes according to what the current
  1106. // value of YResolution is. This is so that when the resoltuion changes,
  1107. // the YPos will be in the same relative position.
  1108. //
  1109. hr = wiasGetChangedValueLong(pWiasContext,
  1110. pContext,
  1111. cviYRes.bChanged,
  1112. WIA_IPS_YPOS,
  1113. &cviYPos);
  1114. if (FAILED(hr)) {
  1115. return hr;
  1116. }
  1117. //
  1118. // Get the minimum and maximum pos and extent values
  1119. //
  1120. hr = GetMinAndMaxLong(pWiasContext, WIA_IPS_YEXTENT, &lMinYExt, &lMaxYExtOld);
  1121. if (FAILED(hr)) {
  1122. return hr;
  1123. }
  1124. hr = GetMinAndMaxLong(pWiasContext, WIA_IPS_YPOS, NULL, &lMaxYPosOld);
  1125. if (FAILED(hr)) {
  1126. return hr;
  1127. }
  1128. //
  1129. // lMax is the maximum vertical position (in pixels) that YPos can be
  1130. // set to. lYRes is DPI, lPageHeight is in one thousandth's of an inch,
  1131. // and lMinYExt is in pixels.
  1132. //
  1133. lMax = ((cviYRes.Current.lVal * lHeight) / 1000) - lMinYExt;
  1134. if (cviYRes.bChanged) {
  1135. //
  1136. // YRes changed, so calc and set new YPos valid values.
  1137. //
  1138. hr = wiasSetValidRangeLong(pWiasContext, WIA_IPS_YPOS, 0, 0, lMax, 1);
  1139. if (SUCCEEDED(hr)) {
  1140. //
  1141. // If YPos is not one of the properties being written, then fold
  1142. // it's current value.
  1143. //
  1144. if (!cviYPos.bChanged) {
  1145. cviYPos.Current.lVal = (cviYPos.Old.lVal * lMax) / lMaxYPosOld;
  1146. hr = wiasWritePropLong(pWiasContext, WIA_IPS_YPOS, cviYPos.Current.lVal);
  1147. if (FAILED(hr)) {
  1148. DBG_ERR(("CheckYResAndUpdate, could not write value for WIA_IPS_YPOS"));
  1149. }
  1150. }
  1151. }
  1152. }
  1153. if (FAILED(hr)) {
  1154. return hr;
  1155. }
  1156. //
  1157. // Call wiasGetChangedValue for YExtent. YExtent is a dependant property of
  1158. // both YResolution and YPos. The extent should be the same relative
  1159. // size no matter what the resolution. However, if the resolution changes
  1160. // or if the YPos is set, then the extent has the possibility of being
  1161. // too large and so must be folded to a valid value.
  1162. //
  1163. hr = wiasGetChangedValueLong(pWiasContext,
  1164. pContext,
  1165. cviYRes.bChanged || cviYPos.bChanged,
  1166. WIA_IPS_YEXTENT,
  1167. &cviYExt);
  1168. if (FAILED(hr)) {
  1169. return hr;
  1170. }
  1171. lExt = cviYExt.Current.lVal;
  1172. if (cviYRes.bChanged || cviYPos.bChanged) {
  1173. //
  1174. // YRes or YPos changed, so calc and set new YExtent valid values.
  1175. // The maximum valid value for YExtent is the maximum height allowed,
  1176. // starting at YPos.
  1177. //
  1178. lExt = (lMax - cviYPos.Current.lVal) + lMinYExt;
  1179. hr = wiasSetValidRangeLong(pWiasContext, WIA_IPS_YEXTENT, lMinYExt, lExt, lExt, 1);
  1180. if (SUCCEEDED(hr)) {
  1181. //
  1182. // If YExtent is not one of the properties being written, then fold
  1183. // it's current value.
  1184. //
  1185. if (!cviYExt.bChanged) {
  1186. LONG lYExtScaled;
  1187. //
  1188. // First scale the extent and then check whether it has to be
  1189. // truncated. The old extent should be scaled to keep the
  1190. // same relative size. If the resolution has not changed,
  1191. // then the scaling simply keeps the extent the same size.
  1192. //
  1193. lYExtScaled = (cviYExt.Old.lVal * lExt) / lMaxYExtOld;
  1194. if (lYExtScaled > lExt) {
  1195. //
  1196. // The extent is too large, so clip it.
  1197. //
  1198. lYExtScaled = lExt;
  1199. }
  1200. hr = wiasWritePropLong(pWiasContext, WIA_IPS_YEXTENT, lYExtScaled);
  1201. if (FAILED(hr)) {
  1202. DBG_ERR(("CheckYResAndUpdate, could not write value for WIA_IPS_YEXTENT"));
  1203. }
  1204. }
  1205. }
  1206. }
  1207. if (FAILED(hr)) {
  1208. return hr;
  1209. }
  1210. //
  1211. // Update read-only property : NUMBER_OF_LINES. The number of lines in the scanned
  1212. // image is the same as the vertical (Y) extent.
  1213. //
  1214. hr = wiasReadPropLong(pWiasContext, WIA_IPS_YEXTENT, &lExt, NULL, TRUE);
  1215. if (SUCCEEDED(hr)) {
  1216. hr = wiasWritePropLong(pWiasContext, WIA_IPA_NUMBER_OF_LINES, lExt);
  1217. }
  1218. return hr;
  1219. }
  1220. /**************************************************************************\
  1221. * AreWiaInitializedProps
  1222. *
  1223. * This helper method is called to check whether a given set of propspecs
  1224. * identifies only the WIA managed properties. It is used to help
  1225. * performance with lazy intialization.
  1226. *
  1227. * Arguments:
  1228. *
  1229. * cPropSpec - count of propecs in the array
  1230. * pPropSpec - the propspec array
  1231. *
  1232. * Return Value:
  1233. *
  1234. * TRUE - if all properties in the propspec array are WIA managed ones.
  1235. * FALSE - if at least one property is not a WIA managed one.
  1236. *
  1237. * History:
  1238. *
  1239. * 10/10/1999 Original Version
  1240. *
  1241. \**************************************************************************/
  1242. BOOL _stdcall AreWiaInitializedProps(
  1243. ULONG cPropSpec,
  1244. PROPSPEC *pPropSpec)
  1245. {
  1246. DBG_FN(::AreWiaInitializedProps);
  1247. ULONG index;
  1248. ULONG propIndex;
  1249. BOOL bFoundProp = FALSE;
  1250. for (index = 0; index < cPropSpec; index++) {
  1251. bFoundProp = FALSE;
  1252. for (propIndex = 0; propIndex < NUM_WIA_MANAGED_PROPS; propIndex++) {
  1253. if (pPropSpec[index].ulKind == PRSPEC_LPWSTR) {
  1254. if (wcscmp(s_pszItemNameType[propIndex], pPropSpec[index].lpwstr) == 0) {
  1255. bFoundProp = TRUE;
  1256. break;
  1257. }
  1258. } else if (s_piItemNameType[propIndex] == pPropSpec[index].propid) {
  1259. bFoundProp = TRUE;
  1260. break;
  1261. }
  1262. }
  1263. if (!bFoundProp) {
  1264. break;
  1265. }
  1266. }
  1267. return bFoundProp;
  1268. }
  1269. HRESULT _stdcall SetValidProfileNames(
  1270. BYTE *pbData,
  1271. DWORD dwSize,
  1272. IWiaItem *pIWiaItem)
  1273. {
  1274. DBG_FN(::StripProfileNames);
  1275. HRESULT hr;
  1276. ULONG ulNumStrings = 0;
  1277. LPTSTR szProfileName = (LPTSTR) pbData;
  1278. BSTR bstrDefault = NULL;
  1279. BSTR *bstrValidProfiles = NULL;
  1280. ULONG ulIndex = 0;
  1281. USES_CONVERSION;
  1282. //
  1283. // Count number of strings
  1284. //
  1285. while ((BYTE*)szProfileName < (pbData + dwSize)) {
  1286. if (szProfileName[0] != TEXT('\0')) {
  1287. ulNumStrings++;
  1288. szProfileName += lstrlen(szProfileName);
  1289. }
  1290. szProfileName++;
  1291. }
  1292. if (ulNumStrings == 0) {
  1293. DBG_ERR(("StripProfileNames, No profile names!"));
  1294. return E_FAIL;
  1295. }
  1296. //
  1297. // Allocate memory for the string array
  1298. //
  1299. szProfileName = (LPTSTR)pbData;
  1300. bstrDefault = SysAllocString(T2W(szProfileName));
  1301. bstrValidProfiles = (BSTR*) LocalAlloc(LPTR, ulNumStrings * sizeof(BSTR));
  1302. if (!bstrValidProfiles || !bstrDefault) {
  1303. DBG_ERR(("StripProfileNames, could not allocate memory!"));
  1304. hr = E_OUTOFMEMORY;
  1305. } else {
  1306. memset(bstrValidProfiles, 0, ulNumStrings * sizeof(BSTR));
  1307. }
  1308. if (SUCCEEDED(hr)) {
  1309. //
  1310. // Set the string values.
  1311. //
  1312. for (ulIndex = 0; ulIndex < ulNumStrings; ulIndex++) {
  1313. if (szProfileName[0] != TEXT('\0')) {
  1314. bstrValidProfiles[ulIndex] = SysAllocString(T2W(szProfileName));
  1315. if (!bstrValidProfiles[ulIndex]) {
  1316. DBG_ERR(("StripProfileNames, could not allocate strings!"));
  1317. hr = E_OUTOFMEMORY;
  1318. break;
  1319. }
  1320. szProfileName += (lstrlen(szProfileName) + 1);
  1321. }
  1322. }
  1323. //
  1324. // Set the valid values and the current value
  1325. //
  1326. if (SUCCEEDED(hr)) {
  1327. hr = wiasSetValidListStr((BYTE*) pIWiaItem,
  1328. WIA_IPA_ICM_PROFILE_NAME,
  1329. ulNumStrings,
  1330. bstrDefault,
  1331. bstrValidProfiles);
  1332. if (SUCCEEDED(hr)) {
  1333. hr = wiasWritePropStr((BYTE*) pIWiaItem,
  1334. WIA_IPA_ICM_PROFILE_NAME,
  1335. bstrDefault);
  1336. if (FAILED(hr)) {
  1337. DBG_ERR(("StripProfileNames, could not set default color profiles!"));
  1338. }
  1339. } else {
  1340. DBG_ERR(("StripProfileNames, could not set valid list of color profiles!"));
  1341. }
  1342. }
  1343. }
  1344. //
  1345. // Free memory
  1346. //
  1347. if (bstrDefault) {
  1348. SysFreeString(bstrDefault);
  1349. bstrDefault = NULL;
  1350. }
  1351. if (bstrValidProfiles) {
  1352. for (ulIndex = 0; ulIndex < ulNumStrings; ulIndex++) {
  1353. if (bstrValidProfiles[ulIndex]) {
  1354. SysFreeString(bstrValidProfiles[ulIndex]);
  1355. }
  1356. }
  1357. LocalFree(bstrValidProfiles);
  1358. bstrValidProfiles = NULL;
  1359. }
  1360. return hr;
  1361. }
  1362. /**************************************************************************\
  1363. * FillICMPropertyFromRegistry
  1364. *
  1365. * This helper method is called to fill the item properties with the ICM
  1366. * color profile names from a specified device's registry entries.
  1367. * NOTE: This function assumes this is called on a Root before it's called
  1368. * on its children!
  1369. *
  1370. * Arguments:
  1371. *
  1372. * IWiaItem - WIA item
  1373. *
  1374. * Return Value:
  1375. *
  1376. * Status
  1377. *
  1378. * History:
  1379. *
  1380. * 10/10/1999 Original Version
  1381. *
  1382. \**************************************************************************/
  1383. HRESULT _stdcall FillICMPropertyFromRegistry(
  1384. IWiaPropertyStorage *pDevInfoProps,
  1385. IWiaItem *pIWiaItem)
  1386. {
  1387. DBG_FN(::FillICMPropertyFromRegistry);
  1388. PROPSPEC pspec[1] = {{PRSPEC_PROPID, WIA_DIP_DEV_ID}};
  1389. PROPVARIANT pvName[1];
  1390. HRESULT hr = E_FAIL;
  1391. BYTE *pbData = NULL;
  1392. DWORD dwType = 0;
  1393. DWORD dwSize = 0;
  1394. LONG lItemType = 0;
  1395. CWiaItem *pRoot = NULL;
  1396. USES_CONVERSION;
  1397. //
  1398. // Check whether this is the root item. If it is, read the ICM values from the
  1399. // registry, and cache it.
  1400. // NOTE: This should be moved into the STI_WIA_DEVICE_INFORMATION member of
  1401. // ACTIVE_DEVICE, and filled in when STI_WIA_DEVICE_INFORMATION is
  1402. // filled for the first time. This should increase performance.
  1403. // If it isn't the root item, then get the cached ICM values from the root, and
  1404. // fill them in.
  1405. //
  1406. hr = pIWiaItem->GetItemType(&lItemType);
  1407. if (SUCCEEDED(hr)) {
  1408. if (lItemType & WiaItemTypeRoot) {
  1409. //
  1410. // This is a root item, so cache the ICM values.
  1411. // Start by getting the device name...
  1412. //
  1413. pRoot = (CWiaItem*) pIWiaItem;
  1414. if (pDevInfoProps) {
  1415. //
  1416. // Get the color profile names. First get the size, then get the value.
  1417. //
  1418. hr = g_pDevMan->GetDeviceValue(pRoot->m_pActiveDevice,
  1419. STI_DEVICE_VALUE_ICM_PROFILE,
  1420. &dwType,
  1421. NULL,
  1422. &dwSize);
  1423. if (SUCCEEDED(hr)) {
  1424. pbData = (BYTE*) LocalAlloc(LPTR, dwSize);
  1425. if (pbData) {
  1426. dwType = REG_BINARY;
  1427. hr = g_pDevMan->GetDeviceValue(pRoot->m_pActiveDevice,
  1428. STI_DEVICE_VALUE_ICM_PROFILE,
  1429. &dwType,
  1430. pbData,
  1431. &dwSize);
  1432. if (SUCCEEDED(hr)) {
  1433. //
  1434. // Store the ICM value with this root item.
  1435. //
  1436. pRoot->m_pICMValues = pbData;
  1437. pRoot->m_lICMSize = dwSize;
  1438. } else {
  1439. DBG_WRN(("FillICMPropertyFromRegistry, could not get ICM profile value!"));
  1440. LocalFree(pbData);
  1441. }
  1442. } else {
  1443. hr = E_OUTOFMEMORY;
  1444. DBG_ERR(("FillICMPropertyFromRegistry, not enough memory for ICM values!"));
  1445. }
  1446. } else {
  1447. DBG_WRN(("FillICMPropertyFromRegistry, could not get ICM profile size!"));
  1448. }
  1449. } else {
  1450. DBG_ERR(("FillICMPropertyFromRegistry, no property stream provided!"));
  1451. }
  1452. //
  1453. // Always set the return to S_OK if this is the root. Even if the color profile could not
  1454. // be read, when it comes time for the child items to have their profile property filled in,
  1455. // they'll simply get the standard sRGB one instead.
  1456. //
  1457. hr = S_OK;
  1458. } else {
  1459. //
  1460. // This is not a root item, so get the cached ICM values from the root
  1461. // and fill in the ICM property.
  1462. //
  1463. hr = pIWiaItem->GetRootItem((IWiaItem**) &pRoot);
  1464. if (SUCCEEDED(hr)) {
  1465. //
  1466. // Check whether a cached ICM profile list exists. Get a standard one if it doesn't, else
  1467. // just set the property.
  1468. //
  1469. if (!pRoot->m_pICMValues ||
  1470. FAILED(hr = SetValidProfileNames(pRoot->m_pICMValues, pRoot->m_lICMSize, pIWiaItem)))
  1471. {
  1472. TCHAR szSRGB[MAX_PATH] = {TEXT('\0')};
  1473. dwSize = sizeof(szSRGB);
  1474. if (GetStandardColorSpaceProfile(NULL,
  1475. LCS_sRGB,
  1476. szSRGB,
  1477. &dwSize))
  1478. {
  1479. hr = SetValidProfileNames((BYTE*)szSRGB, dwSize, pIWiaItem);
  1480. DBG_TRC(("FillICMPropertyFromRegistry, using default color space profile"));
  1481. } else {
  1482. DBG_ERR(("FillICMPropertyFromRegistry, GetStandardColorSpaceProfile failed!"));
  1483. hr = E_FAIL;
  1484. }
  1485. }
  1486. pRoot->Release();
  1487. } else {
  1488. DBG_ERR(("FillICMPropertyFromRegistry, could not get root item!"));
  1489. }
  1490. }
  1491. } else {
  1492. DBG_ERR(("FillICMPropertyFromRegistry, could not get item type!"));
  1493. }
  1494. return hr;
  1495. }
  1496. /**************************************************************************\
  1497. * GetParentItem
  1498. *
  1499. * Returns the item's parent
  1500. *
  1501. * Arguments:
  1502. *
  1503. * pItem - WIA item
  1504. * ppItem - address to store the parent item.
  1505. *
  1506. * Return Value:
  1507. *
  1508. * Status
  1509. *
  1510. * History:
  1511. *
  1512. * 01/14/2000 Original Version
  1513. *
  1514. \**************************************************************************/
  1515. HRESULT _stdcall GetParentItem(CWiaItem *pItem, CWiaItem **ppParent)
  1516. {
  1517. DBG_FN(::GetParentItem);
  1518. CWiaTree *pTree, *pParentTree;
  1519. HRESULT hr = S_OK;
  1520. pTree = pItem->GetTreePtr();
  1521. if (pTree) {
  1522. hr = pTree->GetParentItem(&pParentTree);
  1523. if (SUCCEEDED(hr)) {
  1524. if (hr == S_OK) {
  1525. pParentTree->GetItemData((VOID**) ppParent);
  1526. }
  1527. } else {
  1528. DBG_ERR(("GetParentItem, could not get root item tree!"));
  1529. }
  1530. } else {
  1531. DBG_ERR(("GetParentItem, item's tree ptr is NULL!"));
  1532. hr = E_INVALIDARG;
  1533. }
  1534. return hr;
  1535. }
  1536. /**************************************************************************\
  1537. * GetBufferValues
  1538. *
  1539. * Fills in the buffer size properties of the WIA_EXTENDED_TRANSFER_INFO
  1540. * struct.
  1541. *
  1542. * Arguments:
  1543. *
  1544. * pCWiaItem - WIA item
  1545. * pTransInfo - Pointer to the extended transfer information struct.
  1546. *
  1547. * Return Value:
  1548. *
  1549. * Status
  1550. *
  1551. * History:
  1552. *
  1553. * 01/23/2000 Original Version
  1554. *
  1555. \**************************************************************************/
  1556. HRESULT _stdcall GetBufferValues(
  1557. CWiaItem *pCWiaItem,
  1558. PWIA_EXTENDED_TRANSFER_INFO pTransInfo)
  1559. {
  1560. DBG_FN(::GetBufferValues);
  1561. HRESULT hr = S_OK;
  1562. IPropertyStorage *pIValidStg = NULL;
  1563. PROPSPEC ps[1] = {{PRSPEC_PROPID, WIA_IPA_BUFFER_SIZE}};
  1564. PROPVARIANT pv[1];
  1565. //
  1566. // Get the valid values for the WIA_IPA_BUFFER_SIZE property.
  1567. // NOTE: The WIA_IPA_BUFFER_SIZE property used to be the
  1568. // WIA_IPA_MIN_BUFFER_SIZE property. If we can't
  1569. // read the valid values for WIA_IPA_BUFFER_SIZE,
  1570. // we must read the current value of WIA_IP_MIN_BUFFER_SIZE
  1571. // and "guess" the other values instead.
  1572. // This is to facilitate drivers that were made with early versions
  1573. // of the WIA DDK.
  1574. //
  1575. hr = pCWiaItem->GetItemPropStreams(NULL, NULL, &pIValidStg, NULL);
  1576. if (SUCCEEDED(hr)) {
  1577. PropVariantInit(pv);
  1578. hr = pIValidStg->ReadMultiple(1, ps, pv);
  1579. if (hr == S_OK) {
  1580. //
  1581. // Check that the returned property really has enough elements
  1582. // to specify min, max and nominal values. If not, set hr to
  1583. // fail so that we catch our attempt to reach MIN_BUFFER_SIZE
  1584. // instead.
  1585. //
  1586. if (pv[0].cal.cElems == WIA_RANGE_NUM_ELEMS) {
  1587. //
  1588. // Valid values for WIA_IPA_BUFFER_SIZE found, so
  1589. // set the returns.
  1590. pTransInfo->ulMinBufferSize = pv[0].cal.pElems[WIA_RANGE_MIN];
  1591. pTransInfo->ulOptimalBufferSize = pv[0].cal.pElems[WIA_RANGE_NOM];
  1592. pTransInfo->ulMaxBufferSize = pv[0].cal.pElems[WIA_RANGE_MAX];
  1593. } else {
  1594. hr = E_FAIL;
  1595. }
  1596. }
  1597. if (hr != S_OK) {
  1598. //
  1599. // Attempt to read the current value of WIA_IPA_MIN_BUFFER_SIZE,
  1600. // since we couldn't find the values we wanted under
  1601. // WIA_IPA_BUFFER_SIZE.
  1602. //
  1603. IPropertyStorage *pICurrentStg = NULL;
  1604. PropVariantClear(pv);
  1605. hr = pCWiaItem->GetItemPropStreams(&pICurrentStg, NULL, NULL, NULL);
  1606. if (SUCCEEDED(hr)) {
  1607. //
  1608. // Note that we can re-use ps, since the propid's of
  1609. // MIN_BUFFER_SIZE and BUFFER_SIZE are the same.
  1610. //
  1611. hr = pICurrentStg->ReadMultiple(1, ps, pv);
  1612. if (hr == S_OK) {
  1613. //
  1614. // Current value for WIA_IPA_MIN_BUFFER_SIZE found, so
  1615. // set the returns.
  1616. pTransInfo->ulMinBufferSize = pv[0].lVal;
  1617. pTransInfo->ulOptimalBufferSize = pv[0].lVal;
  1618. pTransInfo->ulMaxBufferSize = LONG_MAX;
  1619. } else {
  1620. DBG_ERR(("GetBufferValues, Could not read (valid) WIA_IPA_BUFFER_SIZE or (current) WIA_IPA_MIN_BUFFER_SIZE!"));
  1621. hr = E_INVALIDARG;
  1622. }
  1623. } else {
  1624. DBG_ERR(("GetBufferValues, Could not get item prop streams!"));
  1625. }
  1626. }
  1627. PropVariantClear(pv);
  1628. } else {
  1629. DBG_ERR(("GetBufferValues, failed to get item prop streams!"));
  1630. }
  1631. return hr;
  1632. }
  1633. /**************************************************************************\
  1634. * BQADScale
  1635. *
  1636. * This routine implements Byron's Quick And Dirty scaling algorithm. This
  1637. * specific implementation is meant for 1, 8, or 24bit only. Caller
  1638. * is responsible for all parameter checks!
  1639. *
  1640. * Please note: this is assumed to scale a band of BITMAP data. As such,
  1641. * the source should contain DWORD aligned pixel data, and the ouput buffer
  1642. * will contain DWORD aligned pixel data upon return.
  1643. *
  1644. * Arguments:
  1645. *
  1646. * pSrcBuffer - Pointer to the source buffer
  1647. * lSrcWidth - the source data width in pixels
  1648. * lSrcHeight - the source data height in pixels
  1649. * lSrcDepth - the bit depth of the source data
  1650. * pDestBuffer - Pointer to the destination buffer
  1651. * lDestWidth - the resultant width in pixels
  1652. * lDestHeight - the resultant height in pixels
  1653. *
  1654. * Return Value:
  1655. *
  1656. * Status
  1657. *
  1658. * History:
  1659. *
  1660. * 08/28/2000 Original Version
  1661. *
  1662. \**************************************************************************/
  1663. HRESULT _stdcall BQADScale(BYTE* pSrcBuffer,
  1664. LONG lSrcWidth,
  1665. LONG lSrcHeight,
  1666. LONG lSrcDepth,
  1667. BYTE* pDestBuffer,
  1668. LONG lDestWidth,
  1669. LONG lDestHeight)
  1670. {
  1671. //
  1672. // We only deal with 1, 8 and 24 bit data
  1673. //
  1674. if ((lSrcDepth != 8) && (lSrcDepth != 1) && (lSrcDepth != 24)) {
  1675. DBG_ERR(("BQADScale, We only scale 1bit, 8bit or 24bit data right now, data is %dbit\n", lSrcDepth));
  1676. return E_INVALIDARG;
  1677. }
  1678. //
  1679. // Make adjustments so we also work in all supported bit depths. We can get a performance increase
  1680. // by having separate implementations of all of these, but for now, we stick to a single generic
  1681. // implementation.
  1682. //
  1683. LONG lBytesPerPixel = (lSrcDepth + 7) / 8; // This is the ceiling of the number of
  1684. // bytes needed to hold a single pixel
  1685. ULONG lSrcRawWidth = ((lSrcWidth * lSrcDepth) + 7) / 8; // This is the width in bytes
  1686. ULONG lSrcWidthInBytes; // This is the DWORD-aligned width
  1687. ULONG lDestWidthInBytes; // This is the DWORD-aligned width
  1688. //
  1689. // We need to work out the DWORD aligned width in bytes. Normally we would do this in one step
  1690. // using the supplied lSrcDepth, but we avoid arithmetic overflow conditions that happen
  1691. // in 24bit if we do it in 2 steps like this instead.
  1692. //
  1693. if (lSrcDepth == 1) {
  1694. lSrcWidthInBytes = (lSrcWidth + 7) / 8;
  1695. lDestWidthInBytes = (lDestWidth + 7) / 8;
  1696. } else {
  1697. lSrcWidthInBytes = (lSrcWidth * lBytesPerPixel);
  1698. lDestWidthInBytes = (lDestWidth * lBytesPerPixel);
  1699. }
  1700. lSrcWidthInBytes += (lSrcWidthInBytes % sizeof(DWORD)) ? (sizeof(DWORD) - (lSrcWidthInBytes % sizeof(DWORD))) : 0;
  1701. lDestWidthInBytes += (lDestWidthInBytes % sizeof(DWORD)) ? (sizeof(DWORD) - (lDestWidthInBytes % sizeof(DWORD))) : 0;
  1702. //
  1703. // Define local variables and do the initial calculations needed for
  1704. // the scaling algorithm
  1705. //
  1706. BYTE *pDestPixel = NULL;
  1707. BYTE *pSrcPixel = NULL;
  1708. BYTE *pEnd = NULL;
  1709. BYTE *pDestLine = NULL;
  1710. BYTE *pSrcLine = NULL;
  1711. BYTE *pEndLine = NULL;
  1712. LONG lXEndSize = lBytesPerPixel * lDestWidth;
  1713. LONG lXNum = lSrcWidth; // Numerator in X direction
  1714. LONG lXDen = lDestWidth; // Denomiator in X direction
  1715. LONG lXInc = (lXNum / lXDen) * lBytesPerPixel; // Increment in X direction
  1716. LONG lXDeltaInc = lXNum % lXDen; // DeltaIncrement in X direction
  1717. LONG lXRem = 0; // Remainder in X direction
  1718. LONG lYNum = lSrcHeight; // Numerator in Y direction
  1719. LONG lYDen = lDestHeight; // Denomiator in Y direction
  1720. LONG lYInc = (lYNum / lYDen) * lSrcWidthInBytes; // Increment in Y direction
  1721. LONG lYDeltaInc = lYNum % lYDen; // DeltaIncrement in Y direction
  1722. LONG lYDestInc = lDestWidthInBytes;
  1723. LONG lYRem = 0; // Remainder in Y direction
  1724. pSrcLine = pSrcBuffer; // This is where we start in the source
  1725. pDestLine = pDestBuffer; // This is the start of the destination buffer
  1726. // This is where we end overall
  1727. pEndLine = pDestBuffer + (lDestWidthInBytes * lDestHeight);
  1728. while (pDestLine < pEndLine) { // Start LoopY (Decides where the src and dest lines start)
  1729. pSrcPixel = pSrcLine; // We're starting at the beginning of a new line
  1730. pDestPixel = pDestLine;
  1731. // Calc. where we end the line
  1732. pEnd = pDestPixel + lXEndSize;
  1733. lXRem = 0; // Reset the remainder for the horizontal direction
  1734. while (pDestPixel < pEnd) { // Start LoopX (puts pixels in the destination line)
  1735. // Put the pixel
  1736. if (lBytesPerPixel > 1) {
  1737. pDestPixel[0] = pSrcPixel[0];
  1738. pDestPixel[1] = pSrcPixel[1];
  1739. pDestPixel[2] = pSrcPixel[2];
  1740. } else {
  1741. *pDestPixel = *pSrcPixel;
  1742. }
  1743. // Move the destination pointer to the next pixel
  1744. pDestPixel += lBytesPerPixel;
  1745. pSrcPixel += lXInc; // Move the source pointer over by the horizontal increment
  1746. lXRem += lXDeltaInc; // Increase the horizontal remainder - this decides when we "overflow"
  1747. if (lXRem >= lXDen) { // This is our "overflow" condition. It means we're now one
  1748. // pixel off.
  1749. // In Overflow case, we need to shift one pixel over
  1750. pSrcPixel += lBytesPerPixel;
  1751. lXRem -= lXDen; // Decrease the remainder by the X denominator. This is essentially
  1752. // lXRem MOD lXDen.
  1753. }
  1754. } // End LoopX (puts pixels in the destination line)
  1755. pSrcLine += lYInc; // We've finished a horizontal line, time to move to the next one
  1756. lYRem += lYDeltaInc; // Increase our vertical remainder. This decides when we "overflow"
  1757. if (lYRem > lYDen) { // This is our vertical overflow condition.
  1758. // We need to move to the next line down
  1759. pSrcLine += lSrcWidthInBytes;
  1760. lYRem -= lYDen; // Decrease the remainder by the Y denominator. This is essentially
  1761. // lYRem MOD lYDen.
  1762. }
  1763. pDestLine += lYDestInc; // Move the destination pointer to the start of the next line in the
  1764. // destination buffer
  1765. } // End LoopY (Decides where the src and dest lines start)
  1766. return S_OK;
  1767. }
  1768. /**************************************************************************\
  1769. * AllocReadRegistryString
  1770. *
  1771. * This function reads a REG_SZ value from the registry. The memory for
  1772. * the srting value ius allocated with new. The caller should use
  1773. * "delete" when it is finished with it.
  1774. *
  1775. * Arguments:
  1776. *
  1777. * hKey - Registry key to read from
  1778. * *wszValueName - Value to read
  1779. * **pwszReturnValue - Addess of pointer that will receive the allocated
  1780. * string
  1781. *
  1782. * Return Value:
  1783. *
  1784. * Status.
  1785. *
  1786. * History:
  1787. *
  1788. * 11/06/2000 Original Version
  1789. *
  1790. \**************************************************************************/
  1791. HRESULT AllocReadRegistryString(
  1792. HKEY hKey,
  1793. WCHAR *wszValueName,
  1794. WCHAR **pwszReturnValue)
  1795. {
  1796. HRESULT hr = S_OK;
  1797. DWORD dwError = 0;
  1798. DWORD cbData = 0;
  1799. DWORD dwType = REG_SZ;
  1800. if (!wszValueName || !pwszReturnValue) {
  1801. DBG_WRN(("::AllocReadRegistryString, NULL parameter"));
  1802. return E_INVALIDARG;
  1803. }
  1804. *pwszReturnValue = NULL;
  1805. //
  1806. // Get the number of bytes neded to store the string value.
  1807. //
  1808. dwError = RegQueryValueExW(hKey,
  1809. wszValueName,
  1810. NULL,
  1811. &dwType,
  1812. NULL,
  1813. &cbData);
  1814. if (dwError == ERROR_SUCCESS) {
  1815. //
  1816. // Allocate the correct number of bytes (leave space for terminator)
  1817. //
  1818. *pwszReturnValue = (WCHAR*) new BYTE[cbData + sizeof(L"\0")];
  1819. if (*pwszReturnValue) {
  1820. memset(*pwszReturnValue, 0, cbData + sizeof(L"\0"));
  1821. //
  1822. // Get the string
  1823. //
  1824. dwError = RegQueryValueExW(hKey,
  1825. wszValueName,
  1826. NULL,
  1827. &dwType,
  1828. (LPBYTE)(*pwszReturnValue),
  1829. &cbData);
  1830. if (dwError == ERROR_SUCCESS) {
  1831. } else {
  1832. DBG_WRN(("::AllocReadRegistryString, second RegQueryValueExW returned %d", dwError));
  1833. hr = HRESULT_FROM_WIN32(dwError);
  1834. }
  1835. } else {
  1836. DBG_WRN(("::AllocReadRegistryString, Out of memory!"));
  1837. hr = E_OUTOFMEMORY;
  1838. }
  1839. } else {
  1840. hr = S_FALSE;
  1841. }
  1842. if (hr != S_OK) {
  1843. if (*pwszReturnValue) {
  1844. delete[] *pwszReturnValue;
  1845. }
  1846. *pwszReturnValue = NULL;
  1847. }
  1848. return hr;
  1849. }
  1850. /**************************************************************************\
  1851. * AllocCopyString
  1852. *
  1853. * This function copies a widestring. The memory for the string is
  1854. * allocated with new. The caller should use "delete" to free the string
  1855. * when it is finished with it.
  1856. *
  1857. * Arguments:
  1858. *
  1859. * wszString - WideString to copy.
  1860. *
  1861. * Return Value:
  1862. *
  1863. * Pointer to newly allocated string. Null otherwise.
  1864. *
  1865. * History:
  1866. *
  1867. * 11/06/2000 Original Version
  1868. *
  1869. \**************************************************************************/
  1870. WCHAR* AllocCopyString(
  1871. WCHAR* wszString)
  1872. {
  1873. WCHAR *wszOut = NULL;
  1874. ULONG ulLen = 0;
  1875. //
  1876. // Get length of string including terminating NULL
  1877. //
  1878. ulLen = lstrlenW(wszString) + 2;
  1879. //
  1880. // Allocate memory for the string
  1881. //
  1882. wszOut = new WCHAR[ulLen];
  1883. if (wszOut) {
  1884. //
  1885. // Copy it
  1886. //
  1887. lstrcpynW(wszOut, wszString, ulLen);
  1888. }
  1889. return wszOut;
  1890. }
  1891. /**************************************************************************\
  1892. * AllocCatString
  1893. *
  1894. * This function concatenates 2 strings. The memory for the string is
  1895. * allocated with new. The caller should use "delete []" to free the string
  1896. * when it is finished with it.
  1897. *
  1898. * Arguments:
  1899. *
  1900. * wszString1 - First WideString.
  1901. * wszString2 - Second WideString to add to first.
  1902. *
  1903. * Return Value:
  1904. *
  1905. * Pointer to newly allocated string. Null otherwise.
  1906. *
  1907. * History:
  1908. *
  1909. * 16/02/2001 Original Version
  1910. *
  1911. \**************************************************************************/
  1912. WCHAR* AllocCatString(WCHAR* wszString1, WCHAR* wszString2)
  1913. {
  1914. WCHAR *wszOut = NULL;
  1915. ULONG ulLen = 0;
  1916. //ASSERT (!wszString1 && !wszString2)
  1917. //
  1918. // Get length of string including terminating NULL
  1919. //
  1920. ulLen = lstrlenW(wszString1) + lstrlenW(wszString2) + 1;
  1921. //
  1922. // Allocate memory for the string
  1923. //
  1924. wszOut = new WCHAR[ulLen];
  1925. if (wszOut) {
  1926. //
  1927. // Copy 1st string
  1928. //
  1929. lstrcpynW(wszOut, wszString1, ulLen);
  1930. //
  1931. // Concatenate the strings
  1932. //
  1933. lstrcpynW(wszOut + lstrlenW(wszOut), wszString2, ulLen - lstrlenW(wszOut));
  1934. //
  1935. // Always terminate the string
  1936. //
  1937. wszOut[ulLen - 1] = L'\0';
  1938. }
  1939. return wszOut;
  1940. }
  1941. /**************************************************************************\
  1942. * ReadRegistryDWORD
  1943. *
  1944. * This function reads a dword value from the registry.
  1945. *
  1946. * Arguments:
  1947. *
  1948. * hKey - Registry key to read from
  1949. * wszValueName - Value to read from key
  1950. * pdwReturnValue - Address of variable to receive the data
  1951. *
  1952. * Return Value:
  1953. *
  1954. * Status
  1955. *
  1956. * History:
  1957. *
  1958. * 11/06/2000 Original Version
  1959. *
  1960. \**************************************************************************/
  1961. HRESULT ReadRegistryDWORD(
  1962. HKEY hKey,
  1963. WCHAR *wszValueName,
  1964. DWORD *pdwReturnValue)
  1965. {
  1966. HRESULT hr = S_OK;
  1967. DWORD dwError = 0;
  1968. DWORD cbData = sizeof(DWORD);
  1969. DWORD dwType = REG_DWORD;
  1970. if (!pdwReturnValue || !wszValueName) {
  1971. DBG_WRN(("::ReadRegistryDWORD called with NULL"));
  1972. return E_UNEXPECTED;
  1973. }
  1974. *pdwReturnValue = 0;
  1975. dwError = RegQueryValueExW(hKey,
  1976. wszValueName,
  1977. NULL,
  1978. &dwType,
  1979. (LPBYTE)pdwReturnValue,
  1980. &cbData);
  1981. if (dwError != ERROR_SUCCESS) {
  1982. DBG_TRC(("::ReadRegistryDWORD, RegQueryValueExW returned %d", dwError));
  1983. hr = HRESULT_FROM_WIN32(dwError);
  1984. }
  1985. if (FAILED(hr)) {
  1986. *pdwReturnValue = 0;
  1987. }
  1988. return hr;
  1989. }
  1990. /**************************************************************************\
  1991. * CreateDevInfoFromHKey
  1992. *
  1993. * This function creates and fills out a DEVICE_INFO struct. Most of
  1994. * the information is read from the registry. This is called for Devnode
  1995. * and interface devices (volume devices don't have registry entries)
  1996. *
  1997. * Arguments:
  1998. *
  1999. * hKeyDev - Device registry key
  2000. * dwDeviceState - The device state
  2001. * pspDevInfoData - The devnode data
  2002. * pspDevInterfaceData - The interface data - will be NULL for devnode
  2003. * devices.
  2004. * Return Value:
  2005. *
  2006. * Pointer to newly created DEVICE_INFO struct. NULL if one could not
  2007. * be allocated.
  2008. *
  2009. * History:
  2010. *
  2011. * 11/06/2000 Original Version
  2012. *
  2013. \**************************************************************************/
  2014. DEVICE_INFO* CreateDevInfoFromHKey(
  2015. HKEY hKeyDev,
  2016. DWORD dwDeviceState,
  2017. SP_DEVINFO_DATA *pspDevInfoData,
  2018. SP_DEVICE_INTERFACE_DATA *pspDevInterfaceData)
  2019. {
  2020. HRESULT hr = E_OUTOFMEMORY;
  2021. DEVICE_INFO *pDeviceInfo = NULL;
  2022. HKEY hDeviceDataKey = NULL;
  2023. DWORD dwMajorType = 0;
  2024. DWORD dwMinorType = 0;
  2025. BOOL bFatalError = FALSE;
  2026. DWORD dwTemp;
  2027. WCHAR *wszTemp = NULL;
  2028. pDeviceInfo = new DEVICE_INFO;
  2029. if (!pDeviceInfo) {
  2030. DBG_WRN(("CWiaDevMan::CreateDevInfoFromHKey, Out of memory"));
  2031. return NULL;
  2032. }
  2033. memset(pDeviceInfo, 0, sizeof(DEVICE_INFO));
  2034. pDeviceInfo->bValid = FALSE;
  2035. pDeviceInfo->dwDeviceState = dwDeviceState;
  2036. //
  2037. // Copy the SP_DEVINFO_DATA and SP_DEVICE_INTERFACE_DATA
  2038. //
  2039. if (pspDevInfoData) {
  2040. memmove(&pDeviceInfo->spDevInfoData, pspDevInfoData, sizeof(SP_DEVINFO_DATA));
  2041. if (pspDevInterfaceData) {
  2042. memmove(&pDeviceInfo->spDevInterfaceData, pspDevInterfaceData, sizeof(SP_DEVICE_INTERFACE_DATA));
  2043. }
  2044. }
  2045. //
  2046. // NOTE: To avoid any alignment faults, we read into &wszTemp, then assign wszTemp to
  2047. // the appropriate structure member.
  2048. //
  2049. hr = AllocReadRegistryString(hKeyDev, REGSTR_VAL_DEVICE_ID_W, &wszTemp);
  2050. if (FAILED(hr)) {
  2051. DBG_WRN(("::CreateDevInfoFromHKey, Failed to read %ws, fatal for this device (NULL name)", REGSTR_VAL_DEVICE_ID_W));
  2052. bFatalError = TRUE;
  2053. } else {
  2054. pDeviceInfo->wszDeviceInternalName = wszTemp;
  2055. }
  2056. hr = AllocReadRegistryString(hKeyDev, REGSTR_VAL_DEVICE_ID_W, &wszTemp);
  2057. if (FAILED(hr)) {
  2058. DBG_WRN(("::CreateDevInfoFromHKey, Failed to read %ws (remote), fatal for this device (NULL name)", REGSTR_VAL_DEVICE_ID_W));
  2059. bFatalError = TRUE;
  2060. } else {
  2061. pDeviceInfo->wszDeviceRemoteName = wszTemp;
  2062. }
  2063. hr = AllocReadRegistryString(hKeyDev, REGSTR_VAL_USD_CLASS_W, &wszTemp);
  2064. if (FAILED(hr)) {
  2065. DBG_WRN(("::CreateDevInfoFromHKey, Failed to read %ws, fatal for this device (%ws)", REGSTR_VAL_USD_CLASS_W, pDeviceInfo->wszDeviceInternalName));
  2066. bFatalError = TRUE;
  2067. } else {
  2068. pDeviceInfo->wszUSDClassId = wszTemp;
  2069. }
  2070. hr = AllocReadRegistryString(hKeyDev, REGSTR_VAL_VENDOR_NAME_W, &wszTemp);
  2071. if (FAILED(hr)) {
  2072. DBG_TRC(("::CreateDevInfoFromHKey, Failed to read %ws, non-fatal for device (%ws)", REGSTR_VAL_VENDOR_NAME_W, pDeviceInfo->wszDeviceInternalName));
  2073. } else {
  2074. pDeviceInfo->wszVendorDescription = wszTemp;
  2075. }
  2076. hr = AllocReadRegistryString(hKeyDev, REGSTR_VAL_DEVICE_NAME_W, &wszTemp);
  2077. if (FAILED(hr)) {
  2078. DBG_TRC(("::CreateDevInfoFromHKey, Failed to read %ws, non-fatal for device (%ws)", REGSTR_VAL_DEVICE_NAME_W, pDeviceInfo->wszDeviceInternalName));
  2079. } else {
  2080. pDeviceInfo->wszDeviceDescription = wszTemp;
  2081. }
  2082. hr = AllocReadRegistryString(hKeyDev, REGSTR_VAL_DEVICEPORT_W, &wszTemp);
  2083. if (FAILED(hr)) {
  2084. DBG_TRC(("::CreateDevInfoFromHKey, Failed to read %ws, non-fatal for device (%ws)", REGSTR_VAL_DEVICEPORT_W, pDeviceInfo->wszDeviceInternalName));
  2085. } else {
  2086. pDeviceInfo->wszPortName = wszTemp;
  2087. }
  2088. hr = AllocReadRegistryString(hKeyDev, REGSTR_VAL_PROP_PROVIDER_W, &wszTemp);
  2089. if (FAILED(hr)) {
  2090. DBG_TRC(("::CreateDevInfoFromHKey, Failed to read %ws, non-fatal for device (%ws)", REGSTR_VAL_PROP_PROVIDER_W, pDeviceInfo->wszDeviceInternalName));
  2091. } else {
  2092. pDeviceInfo->wszPropProvider = wszTemp;
  2093. }
  2094. hr = AllocReadRegistryString(hKeyDev, REGSTR_VAL_FRIENDLY_NAME_W, &wszTemp);
  2095. if (FAILED(hr)) {
  2096. DBG_TRC(("::CreateDevInfoFromHKey, Failed to read %ws, non-fatal for device (%ws)", REGSTR_VAL_FRIENDLY_NAME_W, pDeviceInfo->wszDeviceInternalName));
  2097. } else {
  2098. pDeviceInfo->wszLocalName = wszTemp;
  2099. }
  2100. hr = ReadRegistryDWORD(hKeyDev, REGSTR_VAL_HARDWARE_W, &dwTemp);
  2101. if (FAILED(hr)) {
  2102. DBG_TRC(("::CreateDevInfoFromHKey, Failed to read %ws, non-fatal for device (%ws)", REGSTR_VAL_HARDWARE_W, pDeviceInfo->wszDeviceInternalName));
  2103. } else {
  2104. pDeviceInfo->dwHardwareConfiguration = dwTemp;
  2105. }
  2106. hr = ReadRegistryDWORD(hKeyDev, REGSTR_VAL_DEVICETYPE_W, &dwMajorType);
  2107. if (FAILED(hr)) {
  2108. DBG_TRC(("::CreateDevInfoFromHKey, Failed to read %ws, non-fatal for device (%ws)", REGSTR_VAL_DEVICETYPE_W, pDeviceInfo->wszDeviceInternalName));
  2109. }
  2110. hr = ReadRegistryDWORD(hKeyDev, REGSTR_VAL_DEVICESUBTYPE_W, &dwMinorType);
  2111. if (FAILED(hr)) {
  2112. DBG_TRC(("::CreateDevInfoFromHKey, Failed to read %ws, non-fatal for device (%ws)", REGSTR_VAL_DEVICESUBTYPE_W, pDeviceInfo->wszDeviceInternalName));
  2113. }
  2114. pDeviceInfo->DeviceType = MAKELONG(dwMinorType,dwMajorType);
  2115. hr = ReadRegistryDWORD(hKeyDev, REGSTR_VAL_GENERIC_CAPS_W, &dwTemp);
  2116. if (FAILED(hr)) {
  2117. DBG_TRC(("::CreateDevInfoFromHKey, Failed to read %ws, non-fatal for device (%ws)", REGSTR_VAL_GENERIC_CAPS_W, pDeviceInfo->wszDeviceInternalName));
  2118. } else {
  2119. pDeviceInfo->DeviceCapabilities.dwGenericCaps = dwTemp;
  2120. }
  2121. //
  2122. // Set the Internal Device type
  2123. //
  2124. pDeviceInfo->dwInternalType = INTERNAL_DEV_TYPE_REAL;
  2125. if (pDeviceInfo->DeviceCapabilities.dwGenericCaps & STI_GENCAP_WIA) {
  2126. pDeviceInfo->dwInternalType |= INTERNAL_DEV_TYPE_WIA;
  2127. }
  2128. if (pspDevInterfaceData) {
  2129. pDeviceInfo->dwInternalType |= INTERNAL_DEV_TYPE_INTERFACE;
  2130. }
  2131. //
  2132. // Read everything we can from DeviceData section under Device Registry Key
  2133. //
  2134. hr = RegCreateKeyExW(hKeyDev, REGSTR_VAL_DATA_W, NULL, NULL, REG_OPTION_NON_VOLATILE, KEY_READ,
  2135. NULL, &hDeviceDataKey, NULL);
  2136. hr = AllocReadRegistryString(hDeviceDataKey, WIA_DIP_SERVER_NAME_STR, &wszTemp);
  2137. if (FAILED(hr)) {
  2138. DBG_WRN(("::CreateDevInfoFromHKey, Failed to read %ws, fatal for device (%ws)", WIA_DIP_SERVER_NAME_STR, pDeviceInfo->wszDeviceInternalName));
  2139. bFatalError = TRUE;
  2140. } else {
  2141. pDeviceInfo->wszServer = wszTemp;
  2142. if (!pDeviceInfo->wszServer) {
  2143. pDeviceInfo->wszServer = AllocCopyString(LOCAL_DEVICE_STR);
  2144. }
  2145. if (pDeviceInfo->wszServer) {
  2146. if (lstrcmpiW(pDeviceInfo->wszServer, LOCAL_DEVICE_STR) == 0) {
  2147. //
  2148. // Mark this device as being local
  2149. //
  2150. pDeviceInfo->dwInternalType |= INTERNAL_DEV_TYPE_LOCAL;
  2151. }
  2152. }
  2153. }
  2154. hr = AllocReadRegistryString(hDeviceDataKey, WIA_DIP_UI_CLSID_STR, &wszTemp);
  2155. if (FAILED(hr)) {
  2156. DBG_WRN(("::CreateDevInfoFromHKey, Failed to read %ws, fatal for device (%ws)", WIA_DIP_SERVER_NAME_STR, pDeviceInfo->wszDeviceInternalName));
  2157. } else {
  2158. pDeviceInfo->wszUIClassId = wszTemp;
  2159. if (!pDeviceInfo->wszUIClassId) {
  2160. pDeviceInfo->wszUIClassId = AllocCopyString(DEF_UI_CLSID_STR);
  2161. }
  2162. }
  2163. hr = AllocReadRegistryString(hDeviceDataKey, REGSTR_VAL_BAUDRATE, &wszTemp);
  2164. if (FAILED(hr)) {
  2165. DBG_TRC(("::CreateDevInfoFromHKey, Failed to read %ws, non-fatal for device (%ws)", REGSTR_VAL_BAUDRATE, pDeviceInfo->wszDeviceInternalName));
  2166. } else {
  2167. if (( pDeviceInfo->dwHardwareConfiguration & STI_HW_CONFIG_SERIAL ) &&
  2168. (hr == S_FALSE)) {
  2169. //
  2170. // Only for serial devices we need to set default baud rate in case it is not set in the
  2171. // registry.
  2172. pDeviceInfo->wszBaudRate = AllocCopyString(DEF_BAUD_RATE_STR);
  2173. } else {
  2174. pDeviceInfo->wszBaudRate = wszTemp;
  2175. }
  2176. DBG_TRC(("::CreateDevInfoFromHKey, Read baud rate %ws ",pDeviceInfo->wszBaudRate));
  2177. }
  2178. hr = ReadRegistryDWORD(hDeviceDataKey, STI_DEVICE_VALUE_HOLDINGTIME_W, &dwTemp);
  2179. if (FAILED(hr)) {
  2180. DBG_TRC(("::CreateDevInfoFromHKey, Failed to read %ws, non-fatal for device (%ws)", STI_DEVICE_VALUE_HOLDINGTIME_W, pDeviceInfo->wszDeviceInternalName));
  2181. } else {
  2182. pDeviceInfo->dwLockHoldingTime = dwTemp;
  2183. }
  2184. hr = ReadRegistryDWORD(hDeviceDataKey, STI_DEVICE_VALUE_TIMEOUT, &dwTemp);
  2185. if (FAILED(hr)) {
  2186. DBG_TRC(("::CreateDevInfoFromHKey, Failed to read %ws, non-fatal for device (%ws)", STI_DEVICE_VALUE_TIMEOUT, pDeviceInfo->wszDeviceInternalName));
  2187. } else {
  2188. pDeviceInfo->dwPollTimeout = dwTemp;
  2189. }
  2190. hr = ReadRegistryDWORD(hDeviceDataKey, STI_DEVICE_VALUE_DISABLE_NOTIFICATIONS, &dwTemp);
  2191. if (FAILED(hr)) {
  2192. DBG_TRC(("::CreateDevInfoFromHKey, Failed to read %ws, non-fatal for device (%ws)", STI_DEVICE_VALUE_DISABLE_NOTIFICATIONS, pDeviceInfo->wszDeviceInternalName));
  2193. } else {
  2194. pDeviceInfo->dwDisableNotifications = dwTemp;
  2195. }
  2196. RegCloseKey(hDeviceDataKey);
  2197. if (!bFatalError) {
  2198. pDeviceInfo->bValid = TRUE;
  2199. } else {
  2200. DBG_WRN(("::CreateDevInfoFromHKey, marking device info. as invalid"));
  2201. }
  2202. return pDeviceInfo;
  2203. }
  2204. /**************************************************************************\
  2205. * RefreshDevInfoFromHKey
  2206. *
  2207. * This function refreshes fields that are subject to change
  2208. *
  2209. * Arguments:
  2210. *
  2211. * pDeviceInfo - Pointer to the DEVICE_INFO struct to update
  2212. * hKeyDev - Device registry key
  2213. * dwDeviceState - The new device state
  2214. * pspDevInfoData - The devnode data
  2215. * pspDevInterfaceData - The interface data - will be NULL for devnode
  2216. * devices.
  2217. *
  2218. * Return Value:
  2219. *
  2220. * True - Everything successfully updated
  2221. * False - Could not update
  2222. *
  2223. * History:
  2224. *
  2225. * 11/06/2000 Original Version
  2226. *
  2227. \**************************************************************************/
  2228. BOOL RefreshDevInfoFromHKey(
  2229. DEVICE_INFO *pDeviceInfo,
  2230. HKEY hKeyDev,
  2231. DWORD dwDeviceState,
  2232. SP_DEVINFO_DATA *pspDevInfoData,
  2233. SP_DEVICE_INTERFACE_DATA *pspDevInterfaceData)
  2234. {
  2235. HRESULT hr = E_OUTOFMEMORY;
  2236. BOOL Succeeded = TRUE;
  2237. WCHAR *wszTemp = NULL;
  2238. //
  2239. // Set new device state
  2240. //
  2241. pDeviceInfo->dwDeviceState = dwDeviceState;
  2242. //
  2243. // Copy the SP_DEVINFO_DATA and SP_DEVICE_INTERFACE_DATA
  2244. //
  2245. if (pspDevInfoData) {
  2246. memcpy(&pDeviceInfo->spDevInfoData, pspDevInfoData, sizeof(SP_DEVINFO_DATA));
  2247. if (pspDevInterfaceData) {
  2248. memcpy(&pDeviceInfo->spDevInterfaceData, pspDevInterfaceData, sizeof(SP_DEVICE_INTERFACE_DATA));
  2249. }
  2250. }
  2251. //
  2252. // Set new port name. First free the old one if it exists
  2253. //
  2254. if (pDeviceInfo->wszPortName) {
  2255. delete [] pDeviceInfo->wszPortName;
  2256. pDeviceInfo->wszPortName = NULL;
  2257. }
  2258. hr = AllocReadRegistryString(hKeyDev, REGSTR_VAL_DEVICEPORT_W, &wszTemp);
  2259. if (FAILED(hr)) {
  2260. DBG_WRN(("::RefreshDevInfoFromHKey, Failed to update %ws, may be fatal for device (%ws)", REGSTR_VAL_DEVICEPORT_W, pDeviceInfo->wszDeviceInternalName));
  2261. Succeeded = FALSE;
  2262. } else {
  2263. pDeviceInfo->wszPortName = wszTemp;
  2264. }
  2265. //
  2266. // Grab new Local name. First free the old one...
  2267. //
  2268. if (pDeviceInfo->wszLocalName) {
  2269. delete [] pDeviceInfo->wszLocalName;
  2270. pDeviceInfo->wszLocalName = NULL;
  2271. }
  2272. hr = AllocReadRegistryString(hKeyDev, REGSTR_VAL_FRIENDLY_NAME_W, &wszTemp);
  2273. if (FAILED(hr)) {
  2274. DBG_TRC(("::RefreshDevInfoFromHKey, Failed to read %ws, non-fatal for device (%ws)", REGSTR_VAL_FRIENDLY_NAME_W, pDeviceInfo->wszDeviceInternalName));
  2275. } else {
  2276. pDeviceInfo->wszLocalName = wszTemp;
  2277. }
  2278. //
  2279. // Grab new Device Description. First free the old one...
  2280. //
  2281. if (pDeviceInfo->wszDeviceDescription) {
  2282. delete [] pDeviceInfo->wszDeviceDescription;
  2283. pDeviceInfo->wszDeviceDescription = NULL;
  2284. }
  2285. hr = AllocReadRegistryString(hKeyDev, REGSTR_VAL_DEVICE_NAME_W, &wszTemp);
  2286. if (FAILED(hr)) {
  2287. DBG_TRC(("::RefreshDevInfoFromHKey, Failed to read %ws, non-fatal for device (%ws)", REGSTR_VAL_DEVICE_NAME_W, pDeviceInfo->wszDeviceInternalName));
  2288. } else {
  2289. pDeviceInfo->wszDeviceDescription = wszTemp;
  2290. }
  2291. //
  2292. // Grab new Vendor name. First free the old one...
  2293. //
  2294. if (pDeviceInfo->wszVendorDescription) {
  2295. delete [] pDeviceInfo->wszVendorDescription;
  2296. pDeviceInfo->wszVendorDescription = NULL;
  2297. }
  2298. hr = AllocReadRegistryString(hKeyDev, REGSTR_VAL_VENDOR_NAME_W, &wszTemp);
  2299. if (FAILED(hr)) {
  2300. DBG_TRC(("::RefreshDevInfoFromHKey, Failed to read %ws, non-fatal for device (%ws)", REGSTR_VAL_VENDOR_NAME_W, pDeviceInfo->wszDeviceInternalName));
  2301. } else {
  2302. pDeviceInfo->wszVendorDescription = wszTemp;
  2303. }
  2304. return Succeeded;
  2305. }
  2306. /**************************************************************************\
  2307. * RefreshDevInfoFromMountPoint
  2308. *
  2309. * This function refreshes fields that are subject to change for volume
  2310. * devices.
  2311. *
  2312. * Arguments:
  2313. *
  2314. * pDeviceInfo - Pointer to the DEVICE_INFO struct to update
  2315. *
  2316. * Return Value:
  2317. *
  2318. * True - Everything successfully updated
  2319. * False - Could not update
  2320. *
  2321. * History:
  2322. *
  2323. * 16/03/2001 Original Version
  2324. *
  2325. \**************************************************************************/
  2326. BOOL RefreshDevInfoFromMountPoint(
  2327. DEVICE_INFO *pDeviceInfo,
  2328. WCHAR *wszMountPoint)
  2329. {
  2330. HRESULT hr = E_OUTOFMEMORY;
  2331. BOOL Succeeded = TRUE;
  2332. WCHAR wszLabel[MAX_PATH];
  2333. //
  2334. // Grab the friendly name of the FS device
  2335. //
  2336. hr = GetMountPointLabel(wszMountPoint, wszLabel, sizeof(wszLabel) / sizeof(wszLabel[0]));
  2337. if (FAILED(hr)) {
  2338. DBG_WRN(("RefreshDevInfoFromMountPoint, GetMountPointLabel failed - could not get display name - using mount point instead"));
  2339. lstrcpynW(wszLabel, wszMountPoint, sizeof(wszLabel) / sizeof(wszLabel[0]));
  2340. }
  2341. //
  2342. // Update the appropriate fields that rely on the display name.
  2343. //
  2344. if (pDeviceInfo->wszVendorDescription) {
  2345. delete [] pDeviceInfo->wszVendorDescription;
  2346. pDeviceInfo->wszVendorDescription = NULL;
  2347. }
  2348. if (pDeviceInfo->wszDeviceDescription) {
  2349. delete [] pDeviceInfo->wszDeviceDescription;
  2350. pDeviceInfo->wszDeviceDescription = NULL;
  2351. }
  2352. if (pDeviceInfo->wszLocalName) {
  2353. delete [] pDeviceInfo->wszLocalName;
  2354. pDeviceInfo->wszLocalName = NULL;
  2355. }
  2356. pDeviceInfo->wszVendorDescription = AllocCopyString(wszLabel);
  2357. pDeviceInfo->wszDeviceDescription = AllocCopyString(wszLabel);
  2358. pDeviceInfo->wszLocalName = AllocCopyString(wszLabel);
  2359. return Succeeded;
  2360. }
  2361. /**************************************************************************\
  2362. * CreateDevInfoForFSDriver
  2363. *
  2364. * Create a device info struct containing all the relevant info for our
  2365. * volume devices.
  2366. *
  2367. * Arguments:
  2368. *
  2369. * wszMountPoint - The mount point of this volume
  2370. *
  2371. * Return Value:
  2372. *
  2373. * Pointer to a newly created DEVICE_INFO. NULL on error.
  2374. *
  2375. * History:
  2376. *
  2377. * 11/06/2000 Original Version
  2378. *
  2379. \**************************************************************************/
  2380. DEVICE_INFO* CreateDevInfoForFSDriver(WCHAR *wszMountPoint)
  2381. {
  2382. HRESULT hr = E_OUTOFMEMORY;
  2383. DEVICE_INFO *pDeviceInfo = NULL;
  2384. BOOL bFatalError = FALSE;
  2385. DWORD dwMajorType = StiDeviceTypeDigitalCamera;
  2386. DWORD dwMinorType = 1;
  2387. WCHAR wszDevId[STI_MAX_INTERNAL_NAME_LENGTH];
  2388. WCHAR wszLabel[MAX_PATH];
  2389. pDeviceInfo = new DEVICE_INFO;
  2390. if (!pDeviceInfo) {
  2391. DBG_WRN(("CWiaDevMan::CreateDevInfoForFSDriver, Out of memory"));
  2392. return NULL;
  2393. }
  2394. memset(pDeviceInfo, 0, sizeof(DEVICE_INFO));
  2395. memset(wszDevId, 0, sizeof(wszDevId));
  2396. //
  2397. // Grab the friendly name of the FS device
  2398. //
  2399. hr = GetMountPointLabel(wszMountPoint, wszLabel, sizeof(wszLabel) / sizeof(wszLabel[0]));
  2400. if (FAILED(hr)) {
  2401. DBG_WRN(("CWiaDevMan::CreateDevInfoForFSDriver, GetMountPointLabel failed - could not get display name - using mount point instead"));
  2402. lstrcpynW(wszLabel, wszMountPoint, sizeof(wszLabel) / sizeof(wszLabel[0]));
  2403. }
  2404. pDeviceInfo->bValid = FALSE;
  2405. pDeviceInfo->dwDeviceState = 0;
  2406. pDeviceInfo->wszAlternateID = AllocCopyString(wszMountPoint);
  2407. if (!pDeviceInfo->wszAlternateID) {
  2408. DBG_WRN(("::CreateDevInfoForFSDriver, out of memory allocating wszAlternateID"));
  2409. bFatalError = TRUE;
  2410. }
  2411. //
  2412. // Construct Device ID. Device ID looks like:
  2413. // {MountPoint}
  2414. // e.g. {e:\}
  2415. //
  2416. lstrcpyW(wszDevId, L"{");
  2417. //
  2418. // We don't want to overrun our internal name length constarint, so we first check
  2419. // to see whether the string length of wszMountPoint is short enough to allow concatenation
  2420. // of {, }, wszMountPoint and NULL terminator, and still fit all this into a string of
  2421. // length STI_MAX_INTERNAL_NAME_LENGTH.
  2422. // Note the space after the brackets in sizeof(L"{} ").
  2423. //
  2424. if (lstrlenW(wszMountPoint) > (STI_MAX_INTERNAL_NAME_LENGTH - (sizeof(L"{} ") / sizeof(WCHAR)))) {
  2425. //
  2426. // The name is too long, so we just insert our own name instead
  2427. //
  2428. lstrcatW(wszDevId, L"NameTooLong");
  2429. } else {
  2430. lstrcatW(wszDevId, wszMountPoint);
  2431. }
  2432. lstrcatW(wszDevId, L"}");
  2433. pDeviceInfo->wszDeviceInternalName = AllocCopyString(wszDevId);
  2434. if (!pDeviceInfo->wszAlternateID) {
  2435. DBG_WRN(("::CreateDevInfoForFSDriver, out of memory allocating wszDeviceInternalName"));
  2436. bFatalError = TRUE;
  2437. }
  2438. pDeviceInfo->wszDeviceRemoteName = AllocCopyString(wszDevId);
  2439. if (!pDeviceInfo->wszDeviceRemoteName) {
  2440. DBG_WRN(("::CreateDevInfoForFSDriver, out of memory allocating wszDeviceRemoteName"));
  2441. bFatalError = TRUE;
  2442. }
  2443. pDeviceInfo->wszPortName = AllocCopyString(wszMountPoint);
  2444. if (!pDeviceInfo->wszPortName) {
  2445. DBG_WRN(("::CreateDevInfoForFSDriver, out of memory allocating wszPortName"));
  2446. bFatalError = TRUE;
  2447. }
  2448. pDeviceInfo->wszUSDClassId = AllocCopyString(FS_USD_CLSID);
  2449. if (!pDeviceInfo->wszUSDClassId) {
  2450. DBG_WRN(("::CreateDevInfoForFSDriver, out of memory allocating wszUSDClassId"));
  2451. bFatalError = TRUE;
  2452. }
  2453. //
  2454. // We can't get the manufacturer string for these devices, so
  2455. // load our standard Manufacturer resource string
  2456. // (something like "(Not available)").
  2457. //
  2458. WCHAR wszManufacturer[32];
  2459. INT iRet = LoadStringW(g_hInst,
  2460. IDS_MSC_MANUFACTURER_STR,
  2461. wszManufacturer,
  2462. sizeof(wszManufacturer)/sizeof(wszManufacturer[0]));
  2463. if (iRet) {
  2464. pDeviceInfo->wszVendorDescription = AllocCopyString(wszManufacturer);
  2465. } else {
  2466. //
  2467. // Can't load it, so give it an empty string
  2468. //
  2469. pDeviceInfo->wszVendorDescription = AllocCopyString(L"");
  2470. }
  2471. pDeviceInfo->wszDeviceDescription = AllocCopyString(wszLabel);
  2472. pDeviceInfo->wszLocalName = AllocCopyString(wszLabel);
  2473. pDeviceInfo->wszServer = AllocCopyString(LOCAL_DEVICE_STR);
  2474. pDeviceInfo->wszBaudRate = NULL;
  2475. pDeviceInfo->wszUIClassId = AllocCopyString(FS_UI_CLSID);
  2476. pDeviceInfo->dwDeviceState = DEV_STATE_ACTIVE;
  2477. pDeviceInfo->DeviceType = MAKELONG(dwMinorType,dwMajorType);
  2478. pDeviceInfo->dwLockHoldingTime = 0;
  2479. pDeviceInfo->dwPollTimeout = 0;
  2480. pDeviceInfo->dwDisableNotifications = 0;
  2481. pDeviceInfo->DeviceCapabilities.dwVersion = STI_VERSION_REAL;
  2482. pDeviceInfo->DeviceCapabilities.dwGenericCaps = STI_GENCAP_WIA;
  2483. pDeviceInfo->dwHardwareConfiguration = HEL_DEVICE_TYPE_WDM;
  2484. pDeviceInfo->dwInternalType = INTERNAL_DEV_TYPE_WIA | INTERNAL_DEV_TYPE_LOCAL;
  2485. //
  2486. // Check whther this volume is really a camera device representing
  2487. // itself as a volume...
  2488. //
  2489. if (IsMassStorageCamera(wszMountPoint)) {
  2490. pDeviceInfo->dwInternalType |= INTERNAL_DEV_TYPE_MSC_CAMERA;
  2491. //
  2492. // Here is a good time to set up the Device's registry entries. We'll call
  2493. // g_pDevMan->GetHKeyFromMountPoint(..), since this has the effect of creating
  2494. // the keys if the don't exist.
  2495. //
  2496. HKEY hKeyDev = g_pDevMan->GetHKeyFromMountPoint(wszMountPoint);
  2497. if (hKeyDev) {
  2498. RegCloseKey(hKeyDev);
  2499. }
  2500. } else {
  2501. pDeviceInfo->dwInternalType |= INTERNAL_DEV_TYPE_VOL;
  2502. }
  2503. if (!bFatalError) {
  2504. pDeviceInfo->bValid = TRUE;
  2505. } else {
  2506. pDeviceInfo->bValid = FALSE;
  2507. }
  2508. return pDeviceInfo;
  2509. }
  2510. /**************************************************************************\
  2511. * CreateDevInfoForRemoteDevice
  2512. *
  2513. * Create a device info struct containing all the relevant info for our
  2514. * remote devices.
  2515. *
  2516. * Arguments:
  2517. *
  2518. * hKeyDev - Device registry key
  2519. *
  2520. * Return Value:
  2521. *
  2522. * Pointer to a newly created DEVICE_INFO. NULL on error.
  2523. *
  2524. * History:
  2525. *
  2526. * 15/02/2001 Original Version
  2527. *
  2528. \**************************************************************************/
  2529. DEVICE_INFO* CreateDevInfoForRemoteDevice(
  2530. HKEY hKeyDev)
  2531. {
  2532. HRESULT hr = E_OUTOFMEMORY;
  2533. DEVICE_INFO *pDeviceInfo = NULL;
  2534. BOOL bFatalError = FALSE;
  2535. DWORD dwTemp;
  2536. WCHAR *wszTemp = NULL;
  2537. pDeviceInfo = new DEVICE_INFO;
  2538. if (!pDeviceInfo) {
  2539. DBG_WRN(("::CreateDevInfoForRemoteDevice, Out of memory"));
  2540. return NULL;
  2541. }
  2542. memset(pDeviceInfo, 0, sizeof(DEVICE_INFO));
  2543. pDeviceInfo->bValid = FALSE;
  2544. //
  2545. // Always assume remote devices are ACTIVE
  2546. //
  2547. pDeviceInfo->dwDeviceState = DEV_STATE_ACTIVE;
  2548. //
  2549. // NOTE: To avoid any alignment faults, we read into &wszTemp, then assign wszTemp to
  2550. // the appropriate structure member.
  2551. //
  2552. hr = AllocReadRegistryString(hKeyDev, WIA_DIP_SERVER_NAME_STR, &wszTemp);
  2553. if (FAILED(hr)) {
  2554. DBG_TRC(("::CreateDevInfoFromHKey, Failed to read %ws, fatal for device (%ws)", WIA_DIP_SERVER_NAME_STR, pDeviceInfo->wszServer));
  2555. bFatalError = TRUE;
  2556. } else {
  2557. pDeviceInfo->wszServer = wszTemp;
  2558. }
  2559. hr = AllocReadRegistryString(hKeyDev, WIA_DIP_REMOTE_DEV_ID_STR, &wszTemp);
  2560. if (FAILED(hr)) {
  2561. DBG_TRC(("::CreateDevInfoFromHKey, Failed to read %ws, fatal for device (%ws)", WIA_DIP_REMOTE_DEV_ID_STR, pDeviceInfo->wszDeviceRemoteName));
  2562. bFatalError = TRUE;
  2563. } else {
  2564. pDeviceInfo->wszDeviceRemoteName = wszTemp;
  2565. }
  2566. pDeviceInfo->wszDeviceInternalName = AllocCatString(pDeviceInfo->wszServer, pDeviceInfo->wszDeviceRemoteName);
  2567. if (!pDeviceInfo->wszDeviceInternalName) {
  2568. DBG_TRC(("::CreateDevInfoFromHKey, Failed allocate memory for Device Name, fatal for device (%ws)", pDeviceInfo->wszDeviceInternalName));
  2569. bFatalError = TRUE;
  2570. }
  2571. hr = AllocReadRegistryString(hKeyDev, WIA_DIP_VEND_DESC_STR, &wszTemp);
  2572. if (FAILED(hr)) {
  2573. DBG_TRC(("::CreateDevInfoFromHKey, Failed to read %ws, non-fatal for device (%ws)", WIA_DIP_VEND_DESC_STR, pDeviceInfo->wszDeviceInternalName));
  2574. } else {
  2575. pDeviceInfo->wszVendorDescription = wszTemp;
  2576. }
  2577. hr = AllocReadRegistryString(hKeyDev, WIA_DIP_DEV_NAME_STR, &wszTemp);
  2578. if (FAILED(hr)) {
  2579. DBG_TRC(("::CreateDevInfoFromHKey, Failed to read %ws, non-fatal for device (%ws)", WIA_DIP_DEV_NAME_STR, pDeviceInfo->wszDeviceInternalName));
  2580. } else {
  2581. pDeviceInfo->wszLocalName = wszTemp;
  2582. }
  2583. hr = AllocReadRegistryString(hKeyDev, WIA_DIP_DEV_DESC_STR, &wszTemp);
  2584. if (FAILED(hr)) {
  2585. DBG_TRC(("::CreateDevInfoFromHKey, Failed to read %ws, non-fatal for device (%ws)", WIA_DIP_DEV_DESC_STR, pDeviceInfo->wszDeviceInternalName));
  2586. } else {
  2587. pDeviceInfo->wszDeviceDescription = wszTemp;
  2588. }
  2589. hr = AllocReadRegistryString(hKeyDev, WIA_DIP_PORT_NAME_STR, &wszTemp);
  2590. if (FAILED(hr)) {
  2591. DBG_TRC(("::CreateDevInfoFromHKey, Failed to read %ws, non-fatal for device (%ws)", WIA_DIP_PORT_NAME_STR, pDeviceInfo->wszDeviceInternalName));
  2592. } else {
  2593. pDeviceInfo->wszPortName = wszTemp;
  2594. }
  2595. hr = AllocReadRegistryString(hKeyDev, WIA_DIP_UI_CLSID_STR, &wszTemp);
  2596. if (FAILED(hr)) {
  2597. DBG_TRC(("::CreateDevInfoFromHKey, Failed to read %ws, non-fatal for device (%ws)", WIA_DIP_UI_CLSID_STR, pDeviceInfo->wszDeviceInternalName));
  2598. } else {
  2599. pDeviceInfo->wszUIClassId = wszTemp;
  2600. }
  2601. hr = ReadRegistryDWORD(hKeyDev, WIA_DIP_DEV_TYPE_STR, &dwTemp);
  2602. if (FAILED(hr)) {
  2603. DBG_TRC(("::CreateDevInfoFromHKey, Failed to read %ws, non-fatal for device (%ws)", WIA_DIP_DEV_TYPE_STR, pDeviceInfo->wszDeviceInternalName));
  2604. } else {
  2605. pDeviceInfo->DeviceType = dwTemp;
  2606. }
  2607. pDeviceInfo->DeviceCapabilities.dwGenericCaps = STI_GENCAP_WIA;
  2608. //
  2609. // Set the Internal Device type
  2610. //
  2611. pDeviceInfo->dwInternalType = INTERNAL_DEV_TYPE_REAL | INTERNAL_DEV_TYPE_WIA;
  2612. if (!bFatalError) {
  2613. pDeviceInfo->bValid = TRUE;
  2614. } else {
  2615. //
  2616. // If it's not valid, free the memory
  2617. // TDB: Remove the bValid field
  2618. //
  2619. DestroyDevInfo(pDeviceInfo);
  2620. pDeviceInfo = NULL;
  2621. }
  2622. return pDeviceInfo;
  2623. }
  2624. /**************************************************************************\
  2625. * DestroyDevInfo
  2626. *
  2627. * Frees up any resources help by the DEVICE_INFO struct (like strings).
  2628. * It will then delete the structure itsself.
  2629. *
  2630. * Arguments:
  2631. *
  2632. * pInfo - Pointer to DEVICE_INFO struct
  2633. *
  2634. * Return Value:
  2635. *
  2636. * None.
  2637. *
  2638. * History:
  2639. *
  2640. * 11/06/2000 Original Version
  2641. *
  2642. \**************************************************************************/
  2643. VOID DestroyDevInfo(DEVICE_INFO *pInfo)
  2644. {
  2645. if (pInfo) {
  2646. //
  2647. // Free struct members first
  2648. //
  2649. if (pInfo->wszAlternateID) {
  2650. delete [] pInfo->wszAlternateID;
  2651. pInfo->wszAlternateID = NULL;
  2652. }
  2653. if (pInfo->wszUSDClassId) {
  2654. delete [] pInfo->wszUSDClassId;
  2655. pInfo->wszUSDClassId = NULL;
  2656. }
  2657. if (pInfo->wszDeviceInternalName) {
  2658. delete [] pInfo->wszDeviceInternalName;
  2659. pInfo->wszDeviceInternalName = NULL;
  2660. }
  2661. if (pInfo->wszDeviceRemoteName) {
  2662. delete [] pInfo->wszDeviceRemoteName;
  2663. pInfo->wszDeviceRemoteName = NULL;
  2664. }
  2665. if (pInfo->wszVendorDescription) {
  2666. delete [] pInfo->wszVendorDescription;
  2667. pInfo->wszVendorDescription = NULL;
  2668. }
  2669. if (pInfo->wszDeviceDescription) {
  2670. delete [] pInfo->wszDeviceDescription;
  2671. pInfo->wszDeviceDescription = NULL;
  2672. }
  2673. if (pInfo->wszPortName) {
  2674. delete [] pInfo->wszPortName;
  2675. pInfo->wszPortName = NULL;
  2676. }
  2677. if (pInfo->wszPropProvider) {
  2678. delete [] pInfo->wszPropProvider;
  2679. pInfo->wszPropProvider = NULL;
  2680. }
  2681. if (pInfo->wszLocalName) {
  2682. delete [] pInfo->wszLocalName;
  2683. pInfo->wszLocalName = NULL;
  2684. }
  2685. if (pInfo->wszServer) {
  2686. delete [] pInfo->wszServer;
  2687. pInfo->wszServer = NULL;
  2688. }
  2689. if (pInfo->wszBaudRate) {
  2690. delete [] pInfo->wszBaudRate;
  2691. pInfo->wszBaudRate = NULL;
  2692. }
  2693. if (pInfo->wszUIClassId) {
  2694. delete [] pInfo->wszUIClassId;
  2695. pInfo->wszUIClassId = NULL;
  2696. }
  2697. //
  2698. // Now free the struct itsself. NOTE: The caller must
  2699. // not attempt to use this pointer again!
  2700. //
  2701. delete pInfo;
  2702. }
  2703. }
  2704. /**************************************************************************\
  2705. * DumpDevInfo
  2706. *
  2707. * Used for debugging, this dumps a few members of the DEVICE_INFO struct.
  2708. *
  2709. * Arguments:
  2710. *
  2711. * pInfo - Pointer to DEVICE_INFO struct
  2712. *
  2713. * Return Value:
  2714. *
  2715. * None.
  2716. *
  2717. * History:
  2718. *
  2719. * 11/06/2000 Original Version
  2720. *
  2721. \**************************************************************************/
  2722. VOID DumpDevInfo(DEVICE_INFO *pInfo)
  2723. {
  2724. if (pInfo) {
  2725. DBG_PRT(("------------------------------------------------", pInfo));
  2726. DBG_PRT(("::DumpDevInfo (0x%08X)", pInfo));
  2727. //
  2728. // Output field values we're interested in
  2729. //
  2730. DBG_PRT(("\t\t bValid (%d)", pInfo->bValid));
  2731. DBG_PRT(("\t\t wszLocalName \t(%ws)", pInfo->wszLocalName));
  2732. DBG_PRT(("\t\t wszInternalName \t(%ws)", pInfo->wszDeviceInternalName));
  2733. DBG_PRT(("\t\t wszRemoteName \t(%ws)", pInfo->wszDeviceRemoteName));
  2734. DBG_PRT(("\t\t wszAlternateID \t(%ws)", pInfo->wszAlternateID));
  2735. DBG_PRT(("\t\t wszPortName \t(%ws)", pInfo->wszPortName));
  2736. DBG_PRT(("\t\t dwInternalType \t(%d)", pInfo->dwInternalType));
  2737. DBG_PRT(("------------------------------------------------", pInfo));
  2738. }
  2739. }
  2740. /**************************************************************************\
  2741. * CreateDevInfoStg
  2742. *
  2743. * This helper method takes a DEVICE_INFO struct and creates an
  2744. * IWiaPropertyStorage filled with the appropriate entries.
  2745. *
  2746. * Arguments:
  2747. *
  2748. * pInfo - Pointer to DEVICE_INFO struct
  2749. *
  2750. * Return Value:
  2751. *
  2752. * Pointer to IWiaPropertyStorage. Will be NULL on error.
  2753. *
  2754. * History:
  2755. *
  2756. * 11/06/2000 Original Version
  2757. *
  2758. \**************************************************************************/
  2759. IWiaPropertyStorage* CreateDevInfoStg(DEVICE_INFO *pInfo)
  2760. {
  2761. CWIADevInfo *pWiaDevInfo = NULL;
  2762. HRESULT hr = E_FAIL;
  2763. ULONG ulIndex = 0;
  2764. WCHAR *wszTmp = NULL;
  2765. PROPID propid = 0;
  2766. PROPSPEC propspec[WIA_NUM_DIP];
  2767. PROPVARIANT propvar[WIA_NUM_DIP];
  2768. WCHAR wszVer[MAX_PATH];
  2769. IWiaPropertyStorage *pIWiaPropStg = NULL;
  2770. //
  2771. // Create the CWIADevInfo class
  2772. //
  2773. pWiaDevInfo = new CWIADevInfo();
  2774. if (!pWiaDevInfo) {
  2775. return NULL;
  2776. }
  2777. hr = pWiaDevInfo->Initialize();
  2778. if (SUCCEEDED(hr)) {
  2779. //
  2780. // Insert the properties
  2781. //
  2782. // Set the property specifications and data. Order must match DEVMANGR.IDL
  2783. memset(propspec, 0, sizeof(PROPSPEC) * WIA_NUM_DIP);
  2784. memset(propvar, 0, sizeof(VARIANT) * WIA_NUM_DIP);
  2785. memset(wszVer ,0, sizeof(wszVer));
  2786. for (ulIndex = 0; ulIndex < WIA_NUM_DIP; ulIndex++) {
  2787. propid = g_piDeviceInfo[ulIndex];
  2788. wszTmp = NULL;
  2789. // Setup property specification.
  2790. propspec[ulIndex].ulKind = PRSPEC_PROPID;
  2791. propspec[ulIndex].propid = propid;
  2792. propvar[ulIndex].vt = VT_BSTR;
  2793. propvar[ulIndex].bstrVal = NULL;
  2794. switch (propid) {
  2795. case WIA_DIP_DEV_ID:
  2796. wszTmp = pInfo->wszDeviceInternalName;
  2797. break;
  2798. case WIA_DIP_REMOTE_DEV_ID:
  2799. wszTmp = pInfo->wszDeviceRemoteName;
  2800. break;
  2801. case WIA_DIP_SERVER_NAME:
  2802. wszTmp = pInfo->wszServer;
  2803. break;
  2804. case WIA_DIP_VEND_DESC:
  2805. wszTmp = pInfo->wszVendorDescription;
  2806. break;
  2807. case WIA_DIP_DEV_DESC:
  2808. wszTmp = pInfo->wszDeviceDescription;
  2809. break;
  2810. case WIA_DIP_DEV_TYPE:
  2811. propvar[ulIndex].vt = VT_I4;
  2812. propvar[ulIndex].lVal = (LONG) pInfo->DeviceType;
  2813. break;
  2814. case WIA_DIP_PORT_NAME:
  2815. wszTmp = pInfo->wszPortName;
  2816. break;
  2817. case WIA_DIP_DEV_NAME:
  2818. wszTmp = pInfo->wszLocalName;
  2819. break;
  2820. case WIA_DIP_UI_CLSID:
  2821. wszTmp = pInfo->wszUIClassId;
  2822. break;
  2823. case WIA_DIP_HW_CONFIG:
  2824. propvar[ulIndex].vt = VT_I4;
  2825. propvar[ulIndex].lVal = (LONG) pInfo->dwHardwareConfiguration;
  2826. break;
  2827. case WIA_DIP_BAUDRATE:
  2828. wszTmp = pInfo->wszBaudRate;
  2829. break;
  2830. case WIA_DIP_STI_GEN_CAPABILITIES:
  2831. propvar[ulIndex].vt = VT_I4;
  2832. propvar[ulIndex].lVal = (LONG) pInfo->DeviceCapabilities.dwGenericCaps;
  2833. break;
  2834. case WIA_DIP_WIA_VERSION:
  2835. wsprintf(wszVer,L"%d.%d",LOWORD(STI_VERSION_REAL),HIWORD(STI_VERSION_REAL));
  2836. wszTmp = wszVer;
  2837. break;
  2838. case WIA_DIP_DRIVER_VERSION:
  2839. if(FALSE == GetDriverDLLVersion(pInfo,wszVer,sizeof(wszVer))){
  2840. DBG_WRN(("GetDriverDLLVersion, unable to alloc get driver version resource information, defaulting to 0.0.0.0"));
  2841. lstrcpyW(wszVer,L"0.0.0.0");
  2842. }
  2843. wszTmp = wszVer;
  2844. break;
  2845. default:
  2846. hr = E_FAIL;
  2847. DBG_ERR(("CreateDevInfoStg, Unknown device property"));
  2848. DBG_ERR((" propid = %li",propid));
  2849. }
  2850. // Allocate and assign BSTR's.
  2851. if (propvar[ulIndex].vt == VT_BSTR) {
  2852. if (wszTmp) {
  2853. propvar[ulIndex].bstrVal = SysAllocString(wszTmp);
  2854. if (!propvar[ulIndex].bstrVal) {
  2855. DBG_WRN(("CreateDevInfoStg, unable to alloc dev info strings"));
  2856. }
  2857. } else {
  2858. DBG_TRC(("CreateDevInfoStg, NULL device property string"));
  2859. DBG_TRC((" propid = %li",propid));
  2860. propvar[ulIndex].bstrVal = SysAllocString(L"Empty");
  2861. }
  2862. }
  2863. }
  2864. IPropertyStorage *pIPropStg = pWiaDevInfo->m_pIPropStg;
  2865. if (pIPropStg) {
  2866. // Set the device information properties.
  2867. hr = pIPropStg->WriteMultiple(WIA_NUM_DIP,
  2868. propspec,
  2869. propvar,
  2870. WIA_DIP_FIRST);
  2871. // Write the property names.
  2872. if (SUCCEEDED(hr)) {
  2873. hr = pIPropStg->WritePropertyNames(WIA_NUM_DIP,
  2874. g_piDeviceInfo,
  2875. g_pszDeviceInfo);
  2876. if (SUCCEEDED(hr)) {
  2877. hr = pWiaDevInfo->QueryInterface(IID_IWiaPropertyStorage, (void**) &pIWiaPropStg);
  2878. } else {
  2879. DBG_WRN(("CreateDevInfoStg, WritePropertyNames Failed (0x%X)", hr));
  2880. }
  2881. }
  2882. else {
  2883. ReportReadWriteMultipleError(hr, "CreateDevInfoStg", NULL, FALSE, WIA_NUM_DIP, propspec);
  2884. }
  2885. } else {
  2886. DBG_WRN(("CreateDevInfoStg, IPropertyStorage is NULL"));
  2887. hr = E_UNEXPECTED;
  2888. }
  2889. // Free the allocated BSTR's.
  2890. FreePropVariantArray(WIA_NUM_DIP, propvar);
  2891. }
  2892. //
  2893. // On failure, delete pWiaDevInfo
  2894. //
  2895. if (FAILED(hr)) {
  2896. if (pWiaDevInfo) {
  2897. delete pWiaDevInfo;
  2898. pWiaDevInfo = NULL;
  2899. pIWiaPropStg = NULL;
  2900. }
  2901. }
  2902. return pIWiaPropStg;
  2903. }
  2904. /**************************************************************************\
  2905. * _CoCreateInstanceInConsoleSession
  2906. *
  2907. * This helper function acts the same as CoCreateInstance, but will launch
  2908. * a out-of-process COM server on the correct user's desktop, taking
  2909. * fast user switching into account. (Normal CoCreateInstance will
  2910. * launch it on the first logged on user's desktop, instead of the currently
  2911. * logged on one).
  2912. *
  2913. * This code was taken with permission from the Shell's Hardware
  2914. * Notification service, on behalf of StephStm.
  2915. *
  2916. * Arguments:
  2917. *
  2918. * rclsid, // Class identifier (CLSID) of the object
  2919. * pUnkOuter, // Pointer to controlling IUnknown
  2920. * dwClsContext // Context for running executable code
  2921. * riid, // Reference to the identifier of the interface
  2922. * ppv // Address of output variable that receives
  2923. * // the interface pointer requested in riid
  2924. *
  2925. * Return Value:
  2926. *
  2927. * Status
  2928. *
  2929. * History:
  2930. *
  2931. * 03/01/2001 Original Version
  2932. *
  2933. \**************************************************************************/
  2934. HRESULT _CoCreateInstanceInConsoleSession(REFCLSID rclsid,
  2935. IUnknown* punkOuter,
  2936. DWORD dwClsContext,
  2937. REFIID riid,
  2938. void** ppv)
  2939. {
  2940. IBindCtx *pbc = NULL;
  2941. HRESULT hr = CreateBindCtx(0, &pbc); // Create a bind context for use with Moniker
  2942. //
  2943. // Set the return
  2944. //
  2945. *ppv = NULL;
  2946. if (SUCCEEDED(hr)) {
  2947. WCHAR wszCLSID[39];
  2948. //
  2949. // Convert the riid to GUID string for use in binding to moniker
  2950. //
  2951. if (StringFromGUID2(rclsid, wszCLSID, sizeof(wszCLSID)/sizeof(wszCLSID[0]))) {
  2952. ULONG ulEaten = 0;
  2953. IMoniker* pmoniker = NULL;
  2954. WCHAR wszDisplayName[sizeof(SESSION_MONIKER)/sizeof(WCHAR) + sizeof(wszCLSID)/sizeof(wszCLSID[0]) + 2] = SESSION_MONIKER;
  2955. //
  2956. // We want something like: "Session:Console!clsid:760befd0-5b0b-44d7-957e-969af35ce954"
  2957. // Notice that we don't want the leading and trailing brackets {..} around the GUID.
  2958. // So, first get rid of trailing bracket by overwriting it with termintaing '\0'
  2959. //
  2960. wszCLSID[lstrlenW(wszCLSID) - 1] = L'\0';
  2961. //
  2962. // Form display name string. To get rid of the leading bracket, we pass in the
  2963. // address of the next character as the start of the string.
  2964. //
  2965. if (lstrcatW(wszDisplayName, &(wszCLSID[1]))) {
  2966. //
  2967. // Parse the name and get a moniker:
  2968. //
  2969. hr = MkParseDisplayName(pbc, wszDisplayName, &ulEaten, &pmoniker);
  2970. if (SUCCEEDED(hr)) {
  2971. IClassFactory *pcf = NULL;
  2972. //
  2973. // Attempt to get the class factory
  2974. //
  2975. hr = pmoniker->BindToObject(pbc, NULL, IID_IClassFactory, (void**)&pcf);
  2976. if (SUCCEEDED(hr))
  2977. {
  2978. //
  2979. // Attempt to create the object
  2980. //
  2981. hr = pcf->CreateInstance(punkOuter, riid, ppv);
  2982. DBG_TRC(("_CoCreateInstanceInConsoleSession, pcf->CreateInstance returned: hr = 0x%08X", hr));
  2983. pcf->Release();
  2984. } else {
  2985. DBG_WRN(("_CoCreateInstanceInConsoleSession, pmoniker->BindToObject returned: hr = 0x%08X", hr));
  2986. }
  2987. pmoniker->Release();
  2988. } else {
  2989. DBG_WRN(("_CoCreateInstanceInConsoleSession, MkParseDisplayName returned: hr = 0x%08X", hr));
  2990. }
  2991. } else {
  2992. DBG_WRN(("_CoCreateInstanceInConsoleSession, string concatenation failed"));
  2993. hr = E_INVALIDARG;
  2994. }
  2995. } else {
  2996. DBG_WRN(("_CoCreateInstanceInConsoleSession, StringFromGUID2 failed"));
  2997. hr = E_INVALIDARG;
  2998. }
  2999. pbc->Release();
  3000. } else {
  3001. DBG_WRN(("_CoCreateInstanceInConsoleSession, CreateBindCtxt returned: hr = 0x%08X", hr));
  3002. }
  3003. return hr;
  3004. }
  3005. /**************************************************************************\
  3006. * GetUserTokenForConsoleSession
  3007. *
  3008. * This helper function will grab the currently logged on interactive
  3009. * user's token, which can be used in a call to CreateProcessAsUser.
  3010. * Caller is responsible for closing this Token handle.
  3011. *
  3012. * It first grabs the impersontaed token from the current session (our
  3013. * service runs in session 0, but with Fast User Switching, the currently
  3014. * active user may be in a different session). It then creates a
  3015. * primary token from the impersonated one.
  3016. *
  3017. * Arguments:
  3018. *
  3019. * None
  3020. *
  3021. * Return Value:
  3022. *
  3023. * HANDLE to Token for logged on user in the currently active session.
  3024. * NULL otherwise.
  3025. *
  3026. * History:
  3027. *
  3028. * 03/05/2001 Original Version
  3029. *
  3030. \**************************************************************************/
  3031. HANDLE GetUserTokenForConsoleSession()
  3032. {
  3033. HANDLE hImpersonationToken = NULL;
  3034. HANDLE hTokenUser = NULL;
  3035. //
  3036. // Get interactive user's token
  3037. //
  3038. if (GetWinStationUserToken(GetCurrentSessionID(), &hImpersonationToken)) {
  3039. //
  3040. // Maybe nobody is logged on, so do a check first.
  3041. //
  3042. if (hImpersonationToken) {
  3043. //
  3044. // We duplicate the token, since the returned token is an
  3045. // impersonated one, and we need it to be primary for
  3046. // use in CreateProcessAsUser.
  3047. //
  3048. if (!DuplicateTokenEx(hImpersonationToken,
  3049. 0,
  3050. NULL,
  3051. SecurityImpersonation,
  3052. TokenPrimary,
  3053. &hTokenUser)) {
  3054. DBG_WRN(("CEventNotifier::StartCallbackProgram, DuplicateTokenEx failed! GetLastError() = 0x%08X", GetLastError()));
  3055. }
  3056. } else {
  3057. DBG_PRT(("CEventNotifier::StartCallbackProgram, No user appears to be logged on..."));
  3058. }
  3059. } else {
  3060. DBG_WRN(("CEventNotifier::StartCallbackProgram, GetWinStationUserToken failed! GetLastError() = 0x%08X", GetLastError()));
  3061. }
  3062. //
  3063. // Close the impersonated token, since we no longer need it.
  3064. //
  3065. if (hImpersonationToken) {
  3066. CloseHandle(hImpersonationToken);
  3067. }
  3068. return hTokenUser;
  3069. }
  3070. /**************************************************************************\
  3071. * IsMassStorageCamera
  3072. *
  3073. * This helper function will use the shell's CustomDeviceProperty API
  3074. * to check whether a given volume device (represented by it's mount point)
  3075. * reports itsself as a digital camera.
  3076. *
  3077. * Arguments:
  3078. *
  3079. * wszMountPoint - The mount point for a specified volume.
  3080. *
  3081. * Return Value:
  3082. *
  3083. * TRUE - The custom device property says this device is really a camera
  3084. * FALSE - This device is not reported as a camera
  3085. *
  3086. * History:
  3087. *
  3088. * 03/08/2001 Original Version
  3089. *
  3090. \**************************************************************************/
  3091. BOOL IsMassStorageCamera(
  3092. WCHAR *wszMountPoint)
  3093. {
  3094. HRESULT hr = E_FAIL;
  3095. IHWDeviceCustomProperties *pIHWDeviceCustomProperties = NULL;
  3096. BOOL bIsCamera = FALSE;
  3097. //
  3098. // CoCreate the CLSID_HWDeviceCustomProperties and grab the
  3099. // IHWDeviceCustomProperties interface.
  3100. //
  3101. hr = CoCreateInstance(CLSID_HWDeviceCustomProperties,
  3102. NULL,
  3103. CLSCTX_LOCAL_SERVER,
  3104. IID_IHWDeviceCustomProperties,
  3105. (VOID**)&pIHWDeviceCustomProperties);
  3106. if (SUCCEEDED(hr))
  3107. {
  3108. //
  3109. // Make sure we initialize the device property interface, so it
  3110. // will know which device we're talking about.
  3111. //
  3112. hr = pIHWDeviceCustomProperties->InitFromDeviceID(wszMountPoint,
  3113. HWDEVCUSTOMPROP_USEVOLUMEPROCESSING);
  3114. if (SUCCEEDED(hr)) {
  3115. //
  3116. // Check whether this mass storage device is really a camera
  3117. //
  3118. DWORD dwVal = 0;
  3119. hr = pIHWDeviceCustomProperties->GetDWORDProperty(IS_DIGITAL_CAMERA_STR,
  3120. &dwVal);
  3121. if (SUCCEEDED(hr) && (dwVal == IS_DIGITAL_CAMERA_VAL)) {
  3122. bIsCamera = TRUE;
  3123. }
  3124. } else {
  3125. DBG_WRN(("IsMassStorageCamera, Initialize failed with (0x%08X)", hr));
  3126. }
  3127. pIHWDeviceCustomProperties->Release();
  3128. } else {
  3129. DBG_WRN(("IsMassStorageCamera, CoCreateInstance failed with (0x%08X)", hr));
  3130. }
  3131. //
  3132. // Log whether we think this device is a camera or not
  3133. //
  3134. DBG_PRT(("IsMassStorageCamera, Returning %ws for drive (%ws)", bIsCamera ? L"TRUE" : L"FALSE", wszMountPoint));
  3135. return bIsCamera;
  3136. }
  3137. /**************************************************************************\
  3138. * GetMountPointLabel
  3139. *
  3140. * This helper function is a replacement for SHGetFileInfoW. It will
  3141. * fill in the label string of the specified mountpoint.
  3142. *
  3143. * Arguments:
  3144. *
  3145. * wszMountPoint - The mount point for a specified volume.
  3146. * pszLabel - Pointer to a caller allocated buffer
  3147. * cchLabel - Number of characters available in pszLabel
  3148. *
  3149. * Return Value:
  3150. *
  3151. * Status
  3152. *
  3153. * History:
  3154. *
  3155. * 03/08/2001 Original Version
  3156. *
  3157. \**************************************************************************/
  3158. HRESULT GetMountPointLabel(WCHAR* wszMountPoint, LPTSTR pszLabel, DWORD cchLabel)
  3159. {
  3160. HRESULT hr = S_OK;
  3161. BOOL fFoundIt = FALSE;
  3162. UINT uDriveType = GetDriveTypeW(wszMountPoint);
  3163. if (!wszMountPoint) {
  3164. DBG_WRN(("GetMountPointLabel, called with NULL string"));
  3165. return E_INVALIDARG;
  3166. }
  3167. if (!fFoundIt)
  3168. {
  3169. //
  3170. // Grab "Label" property, if it exists
  3171. //
  3172. //
  3173. // CoCreate the CLSID_HWDeviceCustomProperties and grab the
  3174. // IHWDeviceCustomProperties interface.
  3175. //
  3176. IHWDeviceCustomProperties *pIHWDeviceCustomProperties = NULL;
  3177. hr = CoCreateInstance(CLSID_HWDeviceCustomProperties,
  3178. NULL,
  3179. CLSCTX_LOCAL_SERVER,
  3180. IID_IHWDeviceCustomProperties,
  3181. (VOID**)&pIHWDeviceCustomProperties);
  3182. if (SUCCEEDED(hr))
  3183. {
  3184. //
  3185. // Make sure we initialize the device property interface, so it
  3186. // will know which device we're talking about.
  3187. //
  3188. hr = pIHWDeviceCustomProperties->InitFromDeviceID(wszMountPoint,
  3189. HWDEVCUSTOMPROP_USEVOLUMEPROCESSING);
  3190. if (SUCCEEDED(hr)) {
  3191. //
  3192. // Check whether this mass storage device is really a camera
  3193. //
  3194. LPWSTR pwszLabel = NULL;
  3195. hr = pIHWDeviceCustomProperties->GetStringProperty(L"Label",
  3196. &pwszLabel);
  3197. if (SUCCEEDED(hr)) {
  3198. lstrcpynW(pszLabel, pwszLabel, cchLabel);
  3199. CoTaskMemFree(pwszLabel);
  3200. fFoundIt = TRUE;
  3201. }
  3202. } else {
  3203. DBG_WRN(("GetMountPointLabel, Initialize failed with (0x%08X)", hr));
  3204. }
  3205. pIHWDeviceCustomProperties->Release();
  3206. } else {
  3207. DBG_WRN(("GetMountPointLabel, CoCreateInstance failed with (0x%08X)", hr));
  3208. }
  3209. //
  3210. // Make sure to set hr to S_OK, since it is not a problem if we can't get the
  3211. // custom label (one might not exist).
  3212. //
  3213. hr = S_OK;
  3214. }
  3215. if (!fFoundIt)
  3216. {
  3217. //
  3218. // If the drive is REMOVABLE, and the mountpoint begins with 'A' or 'B', then it is considered
  3219. // a floppy drive. We only want to call GetVolumeInformationW(..) if it is NOT a floppy...
  3220. //
  3221. if (!((uDriveType == DRIVE_REMOVABLE) && ((towupper(wszMountPoint[0]) == L'A') || (towupper(wszMountPoint[0]) == L'B')))) {
  3222. //
  3223. // This is not a floppy, so find out its volume info.
  3224. //
  3225. if (!GetVolumeInformationW(wszMountPoint,
  3226. pszLabel,
  3227. cchLabel,
  3228. NULL,
  3229. NULL,
  3230. NULL,
  3231. NULL,
  3232. 0))
  3233. {
  3234. //
  3235. // Failure case
  3236. //
  3237. *pszLabel = 0;
  3238. } else {
  3239. fFoundIt = TRUE;
  3240. }
  3241. }
  3242. }
  3243. if (!fFoundIt)
  3244. {
  3245. UINT uResId = 0;
  3246. INT iRet = 0;
  3247. switch (uDriveType)
  3248. {
  3249. case DRIVE_REMOVABLE:
  3250. uResId = IDS_DRIVES_REMOVABLE_STR;
  3251. break;
  3252. case DRIVE_CDROM:
  3253. uResId = IDS_DRIVES_CDROM_STR;
  3254. break;
  3255. case DRIVE_FIXED:
  3256. default:
  3257. uResId = IDS_DRIVES_FIXED_STR;
  3258. break;
  3259. }
  3260. iRet = LoadString(g_hInst,
  3261. uResId,
  3262. pszLabel,
  3263. cchLabel);
  3264. if (iRet) {
  3265. fFoundIt = TRUE;
  3266. } else {
  3267. hr = E_FAIL;
  3268. }
  3269. }
  3270. if (fFoundIt) {
  3271. int iLabelLen = lstrlenW(pszLabel);
  3272. if ((iLabelLen + (sizeof(L" ()") / sizeof(WCHAR)) + lstrlenW(wszMountPoint)) < cchLabel)
  3273. {
  3274. int iLenToChopOff = 1;
  3275. lstrcatW(pszLabel, L" (");
  3276. lstrcatW(pszLabel, wszMountPoint);
  3277. lstrcpy(&pszLabel[lstrlenW(pszLabel) - iLenToChopOff], L")");
  3278. }
  3279. }
  3280. return hr;
  3281. }
  3282. /**************************************************************************\
  3283. * GetDriverDLLVersion
  3284. *
  3285. * This helper function is for reading a DLL version resource
  3286. * fill in the label string of the specified mountpoint.
  3287. *
  3288. * Arguments:
  3289. *
  3290. * wszMountPoint - The mount point for a specified volume.
  3291. * pszLabel - Pointer to a caller allocated buffer
  3292. * cchLabel - Number of characters available in pszLabel
  3293. *
  3294. * Return Value:
  3295. *
  3296. * TRUE - The custom device property says this device is really a camera
  3297. * FALSE - This device is not reported as a camera
  3298. *
  3299. * History:
  3300. *
  3301. * 03/08/2001 Original Version
  3302. *
  3303. \**************************************************************************/
  3304. BOOL GetDriverDLLVersion(DEVICE_INFO *pDeviceInfo, WCHAR *wszVersion, UINT uiSize)
  3305. {
  3306. BOOL bSuccess = FALSE;
  3307. if((NULL == wszVersion)||(NULL == pDeviceInfo)){
  3308. return bSuccess;
  3309. }
  3310. //
  3311. // clear the version string buffer
  3312. //
  3313. memset(wszVersion,0,uiSize);
  3314. //
  3315. // get COM DLL path from registry
  3316. //
  3317. CLSID clsid;
  3318. memset(&clsid,0,sizeof(clsid));
  3319. if (SUCCEEDED(CLSIDFromString(pDeviceInfo->wszUSDClassId, &clsid))) {
  3320. HKEY hk = NULL;
  3321. LONG lRet = 0;
  3322. WCHAR wszKey[MAX_PATH + 40];
  3323. //
  3324. // Look up the CLSID in HKEY_CLASSES_ROOT.
  3325. //
  3326. swprintf(wszKey, L"CLSID\\%s\\InProcServer32", pDeviceInfo->wszUSDClassId);
  3327. lRet = RegOpenKeyExW(HKEY_CLASSES_ROOT, wszKey, 0, KEY_QUERY_VALUE, &hk);
  3328. if (lRet == ERROR_SUCCESS) {
  3329. WCHAR wszDll[MAX_PATH];
  3330. memset(wszDll,0,sizeof(wszDll));
  3331. LONG cb = 0;
  3332. cb = cbX(wszDll);
  3333. lRet = RegQueryValueW(hk, 0, wszDll, &cb);
  3334. if (lRet == ERROR_SUCCESS) {
  3335. //
  3336. // get version information size
  3337. //
  3338. DWORD dwFileInfoVersionSize = GetFileVersionInfoSizeW(wszDll,NULL);
  3339. if (dwFileInfoVersionSize > 0) {
  3340. //
  3341. // allocate version information buffer
  3342. //
  3343. void *pFileVersionData = LocalAlloc(LPTR,dwFileInfoVersionSize);
  3344. if (pFileVersionData) {
  3345. memset(pFileVersionData,0,(dwFileInfoVersionSize));
  3346. //
  3347. // fill version information buffer
  3348. //
  3349. if (GetFileVersionInfoW(wszDll,NULL,dwFileInfoVersionSize, pFileVersionData)) {
  3350. VS_FIXEDFILEINFO *pFileVersionInfo = NULL;
  3351. UINT uLen = 0;
  3352. //
  3353. // extract file version from version information buffer
  3354. //
  3355. if (VerQueryValue(pFileVersionData,TEXT("\\"),(LPVOID*)&pFileVersionInfo, &uLen)) {
  3356. //
  3357. // write the dll version resource into the string buffer
  3358. //
  3359. wsprintf(wszVersion,L"%d.%d.%d.%d",
  3360. HIWORD(pFileVersionInfo->dwFileVersionMS),
  3361. LOWORD(pFileVersionInfo->dwFileVersionMS),
  3362. HIWORD(pFileVersionInfo->dwFileVersionLS),
  3363. LOWORD(pFileVersionInfo->dwFileVersionLS));
  3364. bSuccess = TRUE;
  3365. } else {
  3366. DBG_WRN(("GetDriverDLLVersion, VerQueryValue Failed"));
  3367. }
  3368. } else {
  3369. DBG_WRN(("GetDriverDLLVersion, GetFileVersionInfoW Failed"));
  3370. }
  3371. //
  3372. // free allocated memory
  3373. //
  3374. LocalFree(pFileVersionData);
  3375. pFileVersionData = NULL;
  3376. } else {
  3377. DBG_WRN(("GetDriverDLLVersion, Could not allocate memory for file version information"));
  3378. }
  3379. } else {
  3380. DBG_WRN(("GetDriverDLLVersion, File Version Information Size is < 0 (File may be missing version resource)"));
  3381. }
  3382. } else {
  3383. DBG_WRN(("GetDriverDLLVersion, No InprocServer32"));
  3384. }
  3385. //
  3386. // close registry KEY
  3387. //
  3388. RegCloseKey(hk);
  3389. } else {
  3390. DBG_WRN(("GetDriverDLLVersion, CLSID not registered"));
  3391. }
  3392. } else {
  3393. DBG_WRN(("GetDriverDLLVersion, Invalid CLSID string"));
  3394. }
  3395. return bSuccess;
  3396. }
  3397. /**************************************************************************\
  3398. * CreateMSCRegEntries
  3399. *
  3400. * This helper function creates the registry sub-keys and value entries for
  3401. * an MSC Camera device.
  3402. *
  3403. * Arguments:
  3404. *
  3405. * hDevRegKey - The relevent key under MSCDevList, which specifies
  3406. * which device key we're initializing.
  3407. * wszMountPoint - The mount point for a specified volume.
  3408. *
  3409. * Return Value:
  3410. *
  3411. * Status
  3412. *
  3413. * History:
  3414. *
  3415. * 04/07/2001 Original Version
  3416. *
  3417. \**************************************************************************/
  3418. HRESULT CreateMSCRegEntries(
  3419. HKEY hDevRegKey,
  3420. WCHAR *wszMountPoint)
  3421. {
  3422. HRESULT hr = S_OK;
  3423. if (hDevRegKey && wszMountPoint) {
  3424. DWORD dwError = 0;
  3425. DWORD dwDisposition = 0;
  3426. HKEY hKey = NULL;
  3427. //
  3428. // Write the DeviceID. This is used to retsore event handlers for this device.
  3429. //
  3430. WCHAR wszInternalName[STI_MAX_INTERNAL_NAME_LENGTH];
  3431. //
  3432. // Make sure that there is enough space to enclose the mount point in {}.
  3433. //
  3434. if (lstrlenW(wszMountPoint) < (STI_MAX_INTERNAL_NAME_LENGTH - lstrlenW(L"{}"))) {
  3435. wsprintf(wszInternalName, L"{%ws}", wszMountPoint);
  3436. dwError = RegSetValueEx(hDevRegKey,
  3437. REGSTR_VAL_DEVICE_ID_W,
  3438. 0,
  3439. REG_SZ,
  3440. (BYTE*)wszInternalName,
  3441. sizeof(wszInternalName));
  3442. }
  3443. //
  3444. // Create the DeviceData sub-key
  3445. //
  3446. dwError = RegCreateKeyExW(hDevRegKey,
  3447. REGSTR_VAL_DATA_W,
  3448. 0,
  3449. NULL,
  3450. REG_OPTION_NON_VOLATILE,
  3451. KEY_ALL_ACCESS,
  3452. NULL,
  3453. &hKey,
  3454. &dwDisposition);
  3455. if (dwError == ERROR_SUCCESS) {
  3456. //
  3457. // We created the DeviceData sub-key. We need to add
  3458. // color profile entry
  3459. //
  3460. WCHAR wszSRGB[MAX_PATH];
  3461. DWORD dwSize = 0;
  3462. //
  3463. // We insert sRGB as the color profile. We don't hardcode the
  3464. // name, so call the API to get it... Notice
  3465. // that the entry is a double NULL terminated list, so we
  3466. // set the size parameter to exclude the last 2 characters,
  3467. // so we're guaranteed to have 2 NULLs at the end.
  3468. //
  3469. memset(wszSRGB, 0, sizeof(wszSRGB));
  3470. dwSize = sizeof(wszSRGB) - sizeof(L"\0\0");
  3471. if (GetStandardColorSpaceProfileW(NULL,
  3472. LCS_sRGB,
  3473. wszSRGB,
  3474. &dwSize))
  3475. {
  3476. //
  3477. // We must calculate the number of bytes in this string,
  3478. // remembering to include the size for two terminating NULLs.
  3479. //
  3480. dwSize = (lstrlenW(wszSRGB) * sizeof(wszSRGB[0])) + sizeof("\0\0");
  3481. //
  3482. // Let's write the color profile entry.
  3483. //
  3484. dwError = RegSetValueEx(hKey,
  3485. NULL,
  3486. 0,
  3487. REG_BINARY,
  3488. (BYTE*)wszSRGB,
  3489. dwSize);
  3490. } else {
  3491. DBG_WRN(("CreateMSCRegEntries, GetStandardColorSpaceProfile failed!"));
  3492. }
  3493. //
  3494. // Nothing left to do with this key, so close it.
  3495. //
  3496. RegCloseKey(hKey);
  3497. hKey = NULL;
  3498. dwDisposition = 0;
  3499. }
  3500. //
  3501. // Create the Events sub-key
  3502. //
  3503. dwError = RegCreateKeyExW(hDevRegKey,
  3504. EVENTS,
  3505. 0,
  3506. NULL,
  3507. REG_OPTION_NON_VOLATILE,
  3508. KEY_ALL_ACCESS,
  3509. NULL,
  3510. &hKey,
  3511. &dwDisposition);
  3512. if (dwError == ERROR_SUCCESS) {
  3513. //
  3514. // We created the Events sub-key. Let's fill in some event info
  3515. //
  3516. WCHAR wszCLSID[39]; // {GUID} is 38 characters long, 39 including NULL
  3517. HKEY hKeyTemp = NULL;
  3518. if (StringFromGUID2(WIA_EVENT_DEVICE_CONNECTED, wszCLSID, sizeof(wszCLSID) / sizeof(wszCLSID[0]))) {
  3519. //
  3520. // Create the entry for WIA_EVENT_DEVICE_CONNECTED
  3521. //
  3522. dwError = RegCreateKeyExW(hKey,
  3523. WIA_EVENT_DEVICE_CONNECTED_STR,
  3524. 0,
  3525. NULL,
  3526. REG_OPTION_NON_VOLATILE,
  3527. KEY_ALL_ACCESS,
  3528. NULL,
  3529. &hKeyTemp,
  3530. &dwDisposition);
  3531. if (dwError == ERROR_SUCCESS) {
  3532. //
  3533. // Fill in the values for the sub-key.
  3534. // The result is as follows:
  3535. // [Device connected]
  3536. // Default: "Device connected"
  3537. // GUID: "{a28bbade-x64b6-11d2-a231-00c0-4fa31809}"
  3538. // LaunchApplications: "*"
  3539. //
  3540. // Note that we don't care about error returns.
  3541. //
  3542. dwError = RegSetValueEx(hKeyTemp,
  3543. NULL,
  3544. 0,
  3545. REG_SZ,
  3546. (BYTE*)WIA_EVENT_DEVICE_CONNECTED_STR,
  3547. sizeof(WIA_EVENT_DEVICE_CONNECTED_STR));
  3548. dwError = RegSetValueEx(hKeyTemp,
  3549. REGSTR_VAL_GUID_W,
  3550. 0,
  3551. REG_SZ,
  3552. (BYTE*)wszCLSID,
  3553. sizeof(wszCLSID));
  3554. dwError = RegSetValueEx(hKeyTemp,
  3555. REGSTR_VAL_LAUNCH_APPS_W,
  3556. 0,
  3557. REG_SZ,
  3558. (BYTE*)L"*",
  3559. sizeof(L"*"));
  3560. RegCloseKey(hKeyTemp);
  3561. hKeyTemp = NULL;
  3562. }
  3563. } else {
  3564. DBG_WRN(("::CreateMSCRegEntries, StringFromGUID2 for WIA_EVENT_DEVICE_CONNECTED failed!"));
  3565. }
  3566. RegCloseKey(hKey);
  3567. hKey = NULL;
  3568. dwDisposition = 0;
  3569. }
  3570. } else {
  3571. DBG_WRN(("::CreateMSCRegEntries, Can't have NULL parameters!"));
  3572. }
  3573. return hr;
  3574. }