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.

5702 lines
167 KiB

  1. /*******************************************************************************
  2. *
  3. * (C) COPYRIGHT MICROSOFT CORP., 1998
  4. *
  5. * TITLE: WiaServc.Cpp
  6. *
  7. * VERSION: 2.0
  8. *
  9. * AUTHOR: ReedB
  10. *
  11. * DATE: 20 Aug, 1998
  12. *
  13. * DESCRIPTION:
  14. * Implementation of mini driver services in the WIA device class driver.
  15. *
  16. *******************************************************************************/
  17. #include "precomp.h"
  18. #define STD_PROPS_IN_CONTEXT
  19. #include "stiexe.h"
  20. #include <wiamindr.h>
  21. #include <wiamdef.h>
  22. #include <wiadbg.h>
  23. #include "helpers.h"
  24. #include "wiatiff.h"
  25. #define DOWNSAMPLE_DPI 50
  26. #define ENDORSER_TOKEN_DELIMITER L"$"
  27. #define ESCAPE_CHAR L'\\'
  28. /**************************************************************************\
  29. * wiasDebugTrace
  30. *
  31. * Print a debug trace string in the device manager debug console.
  32. *
  33. * Arguments:
  34. *
  35. * hInstance - Module handle of calling module.
  36. * pszFormat - ANSI format string.
  37. *
  38. * Return Value:
  39. *
  40. * Status
  41. *
  42. * History:
  43. *
  44. * 1/19/1999 Original Version
  45. *
  46. \**************************************************************************/
  47. VOID __cdecl wiasDebugTrace( HINSTANCE hInstance, LPCSTR pszFormat, ... )
  48. {
  49. #if defined(WIA_DEBUG)
  50. _try {
  51. CHAR szMsg[1024 + MAX_PATH];
  52. CHAR szModuleName[MAX_PATH]= { 0 };
  53. va_list arglist;
  54. // Get the module name
  55. GetModuleFileNameA( hInstance, szModuleName, sizeof(szModuleName)/sizeof(szModuleName[0]) - 1);
  56. // Nuke the path
  57. WORD wLen = sizeof(szMsg)/sizeof(szMsg[0]);
  58. GetFileTitleA( szModuleName, szMsg, wLen );
  59. // Nuke the extension
  60. for (LPSTR pszCurr = szMsg + lstrlenA(szMsg); pszCurr>szMsg; pszCurr--) {
  61. if (*(pszCurr-1)=='.') {
  62. *(pszCurr-1)='\0';
  63. break;
  64. }
  65. }
  66. // Append a colon:
  67. lstrcatA( szMsg, ": " );
  68. va_start(arglist, pszFormat);
  69. ::_vsnprintf(szMsg+lstrlenA(szMsg), sizeof(szMsg) - lstrlenA(szMsg) - 1, pszFormat, arglist);
  70. va_end(arglist);
  71. //
  72. // NULL terminate the string
  73. //
  74. szMsg[sizeof(szMsg)/sizeof(szMsg[0]) - 1] = '\0';
  75. DBG_TRC((szMsg));
  76. } _except(EXCEPTION_EXECUTE_HANDLER) {
  77. DBG_ERR(("::wiasDebugTrace, Error processing output string!"));
  78. }
  79. #endif
  80. }
  81. /**************************************************************************\
  82. * wiasDebugError
  83. *
  84. * Print a debug error string in the device manager debug console. The
  85. * output color is always red.
  86. *
  87. * Arguments:
  88. *
  89. * hInstance - Module handle of calling module.
  90. * pszFormat - ANSI format string.
  91. *
  92. * Return Value:
  93. *
  94. * Status
  95. *
  96. * History:
  97. *
  98. * 1/19/1999 Original Version
  99. *
  100. \**************************************************************************/
  101. VOID __cdecl wiasDebugError( HINSTANCE hInstance, LPCSTR pszFormat, ... )
  102. {
  103. #if defined(WIA_DEBUG)
  104. _try {
  105. CHAR szMsg[1024 + MAX_PATH];
  106. CHAR szModuleName[MAX_PATH]= { 0 };
  107. va_list arglist;
  108. // Get the module name
  109. GetModuleFileNameA( hInstance, szModuleName, sizeof(szModuleName)/sizeof(szModuleName[0]) - 1);
  110. // Nuke the path
  111. WORD wLen = sizeof(szMsg)/sizeof(szMsg[0]);
  112. GetFileTitleA( szModuleName, szMsg, wLen );
  113. // Nuke the extension
  114. for (LPSTR pszCurr = szMsg + lstrlenA(szMsg); pszCurr>szMsg; pszCurr--) {
  115. if (*(pszCurr-1)=='.') {
  116. *(pszCurr-1)='\0';
  117. break;
  118. }
  119. }
  120. // Append a colon:
  121. lstrcatA( szMsg, ": " );
  122. va_start(arglist, pszFormat);
  123. ::_vsnprintf(szMsg+lstrlenA(szMsg), sizeof(szMsg) - lstrlenA(szMsg) - 1, pszFormat, arglist);
  124. va_end(arglist);
  125. //
  126. // NULL terminate the string
  127. //
  128. szMsg[sizeof(szMsg)/sizeof(szMsg[0]) - 1] = '\0';
  129. DBG_ERR((szMsg));
  130. } _except (EXCEPTION_EXECUTE_HANDLER) {
  131. DBG_ERR(("::wiasDebugError, Error processing output string!"));
  132. }
  133. #endif
  134. }
  135. /**************************************************************************\
  136. * wiasPrintDebugHResult
  137. *
  138. * Print an HRESULT string on the device manager debug console.
  139. *
  140. * Arguments:
  141. *
  142. * hInstance - Module handle of calling module.
  143. * hr - HRESULT to pe printed.
  144. *
  145. * Return Value:
  146. *
  147. * None.
  148. *
  149. * History:
  150. *
  151. * 1/19/1999 Original Version
  152. *
  153. \**************************************************************************/
  154. VOID __stdcall wiasPrintDebugHResult( HINSTANCE hInstance, HRESULT hr )
  155. {
  156. #if defined(WIA_DEBUG)
  157. DBG_ERR(("HResult = 0x%X", hr));
  158. #endif
  159. }
  160. /**************************************************************************\
  161. * wiasFormatArgs
  162. *
  163. * Format an argument list into a packaged string for logging,
  164. * NOTE: This function adds a format signature, that tells the
  165. * logging engine that it is ok to FREE it.
  166. *
  167. * Arguments:
  168. *
  169. * BSTR pszFormat - ANSI format string.
  170. *
  171. * Return Value:
  172. *
  173. * None.
  174. *
  175. * History:
  176. *
  177. * 8/26/1999 Original Version
  178. *
  179. \**************************************************************************/
  180. BSTR __cdecl wiasFormatArgs(LPCSTR lpszFormat, ...)
  181. {
  182. USES_CONVERSION;
  183. CHAR pszbuffer[4*MAX_PATH];
  184. //
  185. // Signature needs to be defined somewhere else
  186. // It is here, until the old debugging system is
  187. // replaced.
  188. //
  189. CHAR pszFormatSignature[] = "F9762DD2679F";
  190. va_list arglist;
  191. //
  192. // Add signature value, because we are being used to format an
  193. // argument list
  194. //
  195. *pszbuffer = '\0';
  196. lstrcpynA(pszbuffer,pszFormatSignature,lstrlenA(pszFormatSignature) + 1 );
  197. va_start(arglist, lpszFormat);
  198. ::_vsnprintf(pszbuffer+lstrlenA(pszbuffer), sizeof(pszbuffer) - lstrlenA(pszbuffer) - 1, lpszFormat, arglist);
  199. va_end(arglist);
  200. //
  201. // NULL terminate the string
  202. //
  203. pszbuffer[sizeof(pszbuffer)/sizeof(pszbuffer[0]) - 1] = '\0';
  204. return SysAllocString(CSimpleStringConvert::WideString(pszbuffer).String());
  205. }
  206. /**************************************************************************\
  207. * wiasCreateDrvItem
  208. *
  209. * Create a driver item.
  210. *
  211. * Arguments:
  212. *
  213. * lObjectFlags - Object flags.
  214. * bstrItemName - Item name.
  215. * bstrFullItemName - Full item name. Includes path info.
  216. * pIMiniDrv - Pointer to mini-driver interface.
  217. * cbDevSpecContext - Size of device specific context.
  218. * ppDevSpecContext - Pointer to returned device specific context. Optional.
  219. * ppIWiaDrvItem - Pointer to returned driver item.
  220. *
  221. * Return Value:
  222. *
  223. * Status
  224. *
  225. * History:
  226. *
  227. * 1/18/1999 Original Version
  228. *
  229. \**************************************************************************/
  230. HRESULT _stdcall wiasCreateDrvItem(
  231. LONG lObjectFlags,
  232. BSTR bstrItemName,
  233. BSTR bstrFullItemName,
  234. IWiaMiniDrv *pIMiniDrv,
  235. LONG cbDevSpecContext,
  236. BYTE **ppDevSpecContext,
  237. IWiaDrvItem **ppIWiaDrvItem)
  238. {
  239. DBG_FN(::wiasCreateDrvItem);
  240. HRESULT hr = E_FAIL;
  241. //
  242. // Objects can be either folders, files or both
  243. //
  244. if (!(lObjectFlags & (WiaItemTypeFolder | WiaItemTypeFile))) {
  245. DBG_ERR(("wiasCreateDrvItem, bad object flags"));
  246. return E_INVALIDARG;
  247. }
  248. //
  249. // Validate the item name strings.
  250. //
  251. if (IsBadStringPtrW(bstrItemName, SysStringLen(bstrItemName))) {
  252. DBG_ERR(("wiasCreateDrvItem, invalid bstrItemName pointer"));
  253. return E_POINTER;
  254. }
  255. if (IsBadStringPtrW(bstrFullItemName, SysStringLen(bstrFullItemName))) {
  256. DBG_ERR(("wiasCreateDrvItem, invalid bstrFullItemName pointer"));
  257. return E_POINTER;
  258. }
  259. //
  260. // Validate the rest of the pointers
  261. //
  262. if (IsBadReadPtr(pIMiniDrv, sizeof(IWiaMiniDrv))) {
  263. DBG_ERR(("wiasCreateDrvItem, invalid pIMiniDrv pointer"));
  264. return E_POINTER;
  265. }
  266. if (!ppIWiaDrvItem) {
  267. DBG_ERR(("wiasCreateDrvItem, bad ppIWiaItemControl parameter"));
  268. return E_POINTER;
  269. }
  270. if (ppDevSpecContext) {
  271. if (IsBadWritePtr(ppDevSpecContext, sizeof(BYTE*))) {
  272. DBG_ERR(("wiasCreateDrvItem, invalid ppDevSpecContext pointer"));
  273. return E_POINTER;
  274. }
  275. }
  276. if (IsBadWritePtr(ppIWiaDrvItem, sizeof(IWiaDrvItem*))) {
  277. DBG_ERR(("wiasCreateDrvItem, invalid ppIWiaDrvItem pointer"));
  278. return E_POINTER;
  279. }
  280. CWiaDrvItem *pItem = new CWiaDrvItem();
  281. if (pItem) {
  282. hr = pItem->Initialize(lObjectFlags,
  283. bstrItemName,
  284. bstrFullItemName,
  285. pIMiniDrv,
  286. cbDevSpecContext,
  287. ppDevSpecContext);
  288. if (hr == S_OK) {
  289. hr = pItem->QueryInterface(IID_IWiaDrvItem,(void **)ppIWiaDrvItem);
  290. if (FAILED(hr)) {
  291. DBG_ERR(("wiasCreateDrvItem, QI for IID_IWiaDrvItem failed"));
  292. }
  293. }
  294. else {
  295. delete pItem;
  296. }
  297. } else {
  298. DBG_ERR(("wiasCreateDrvItem, out of memory!"));
  299. hr = E_OUTOFMEMORY;
  300. }
  301. return hr;
  302. }
  303. /**************************************************************************\
  304. * wiasReadMultiple
  305. *
  306. * Read multiple properties helper.
  307. *
  308. * Arguments:
  309. *
  310. * pWiasContext - Pointer to WIA item
  311. * ulCount - Number of properties to read.
  312. * ps - A caller allocated array of PROPSPEC.
  313. * pv - A caller allocated array of PROPVARIANTS.
  314. * pvOld - A caller allocated array of PROPVARIANTS for previous values.
  315. * pvOld - A caller allocated array of PROPVARIANTS for the previous values.
  316. *
  317. * Return Value:
  318. *
  319. * Status
  320. *
  321. * History:
  322. *
  323. * 1/19/1999 Original Version
  324. *
  325. \**************************************************************************/
  326. HRESULT _stdcall wiasReadMultiple(
  327. BYTE *pWiasContext,
  328. ULONG ulCount,
  329. const PROPSPEC *ps,
  330. PROPVARIANT *pv,
  331. PROPVARIANT *pvOld)
  332. {
  333. DBG_FN(::wiasReadMultiple);
  334. IWiaItem *pItem = (IWiaItem*) pWiasContext;
  335. HRESULT hr = ValidateWiaItem(pItem);
  336. if (FAILED(hr)) {
  337. DBG_ERR(("wiasReadMultiple, invalid pItem"));
  338. return hr;
  339. }
  340. if (IsBadReadPtr(ps, sizeof(PROPSPEC) * ulCount)) {
  341. DBG_ERR(("wiasReadMultiple, invalid ps pointer"));
  342. return E_POINTER;
  343. }
  344. if (IsBadWritePtr(pv, sizeof(PROPVARIANT) * ulCount)) {
  345. DBG_ERR(("wiasReadMultiple, invalid pv pointer"));
  346. return E_POINTER;
  347. }
  348. if ((pvOld) && IsBadWritePtr(pvOld, sizeof(PROPVARIANT) * ulCount)) {
  349. DBG_ERR(("wiasReadMultiple, invalid pvOld pointer"));
  350. return E_POINTER;
  351. }
  352. IPropertyStorage *pIPropStg, *pIPropOldStg;
  353. hr = ((CWiaItem*)pItem)->GetItemPropStreams(&pIPropStg,
  354. NULL,
  355. NULL,
  356. &pIPropOldStg);
  357. if (FAILED(hr)) {
  358. return hr;
  359. }
  360. //
  361. // Get the current values
  362. //
  363. hr = pIPropStg->ReadMultiple(ulCount, ps, pv);
  364. if (hr == S_OK) {
  365. //
  366. // If requested, get the old values.
  367. //
  368. if (pvOld) {
  369. hr = pIPropOldStg->ReadMultiple(ulCount, ps, pvOld);
  370. };
  371. if (FAILED(hr)) {
  372. ReportReadWriteMultipleError(hr,
  373. "wiasReadMultiple",
  374. "old value",
  375. TRUE,
  376. ulCount,
  377. ps);
  378. }
  379. } else {
  380. ReportReadWriteMultipleError(hr,
  381. "wiasReadMultiple",
  382. "current value",
  383. TRUE,
  384. ulCount,
  385. ps);
  386. }
  387. return hr;
  388. }
  389. /**************************************************************************\
  390. * wiasReadPropStr
  391. *
  392. * Read property string helper.
  393. *
  394. * Arguments:
  395. *
  396. * pWiasContext - Pointer to WIA item
  397. * propid - Property ID
  398. * pbstr - Pointer to returned BSTR
  399. * pbstrOld - Pointer to old returned BSTR for previous value. Can
  400. * be NULL
  401. * bMustExist - Boolean value indicating whether the property must
  402. * exist. If this is true and the property is not found,
  403. * an E_INVALIDARG is returned.
  404. *
  405. * Return Value:
  406. *
  407. * Status
  408. *
  409. * History:
  410. *
  411. * 1/19/1999 Original Version
  412. *
  413. \**************************************************************************/
  414. HRESULT _stdcall wiasReadPropStr(
  415. BYTE *pWiasContext,
  416. PROPID propid,
  417. BSTR *pbstr,
  418. BSTR *pbstrOld,
  419. BOOL bMustExist)
  420. {
  421. DBG_FN(::wiasReadPropStr);
  422. IWiaItem *pItem = (IWiaItem*) pWiasContext;
  423. HRESULT hr = ValidateWiaItem(pItem);
  424. if (FAILED(hr)) {
  425. DBG_ERR(("wiasReadPropStr, invalid pItem"));
  426. return hr;
  427. }
  428. if (IsBadWritePtr(pbstr, sizeof(BSTR*))) {
  429. DBG_ERR(("wiasReadPropStr, invalid pbstr pointer"));
  430. return E_POINTER;
  431. }
  432. if ((pbstrOld) && IsBadWritePtr(pbstrOld, sizeof(BSTR*))) {
  433. DBG_ERR(("wiasReadMultiple, invalid pbstrOld pointer"));
  434. return E_POINTER;
  435. }
  436. IPropertyStorage *pIPropStg, *pIPropOldStg;
  437. hr = ((CWiaItem*)pItem)->GetItemPropStreams(&pIPropStg,
  438. NULL,
  439. NULL,
  440. &pIPropOldStg);
  441. if (FAILED(hr)) {
  442. return hr;
  443. }
  444. //
  445. // Return the current value
  446. //
  447. PROPSPEC propSpec;
  448. PROPVARIANT propVar;
  449. propSpec.ulKind = PRSPEC_PROPID;
  450. propSpec.propid = propid;
  451. hr = pIPropStg->ReadMultiple(1, &propSpec, &propVar);
  452. if (hr == S_OK) {
  453. //
  454. // NULL is a valid bstr value
  455. //
  456. if (propVar.bstrVal == NULL) {
  457. *pbstr = NULL;
  458. if (pbstrOld) {
  459. *pbstrOld = NULL;
  460. }
  461. return S_OK;
  462. }
  463. *pbstr = SysAllocString(propVar.bstrVal);
  464. PropVariantClear(&propVar);
  465. if (*pbstr) {
  466. //
  467. // Check whether we must return the old value.
  468. //
  469. if (pbstrOld) {
  470. hr = pIPropOldStg->ReadMultiple(1, &propSpec, &propVar);
  471. if (hr == S_OK) {
  472. *pbstrOld = SysAllocString(propVar.bstrVal);
  473. PropVariantClear(&propVar);
  474. //
  475. // Clear allocated memory.
  476. //
  477. if (!(*pbstrOld)) {
  478. SysFreeString(*pbstr);
  479. *pbstr = NULL;
  480. DBG_ERR(("wiasReadPropStr, run out of memory"));
  481. return E_OUTOFMEMORY;
  482. }
  483. }
  484. }
  485. } else {
  486. DBG_ERR(("wiasReadPropStr, out of memory error"));
  487. return E_OUTOFMEMORY;
  488. }
  489. }
  490. if (((hr == S_FALSE) && bMustExist) || FAILED(hr)) {
  491. ReportReadWriteMultipleError(hr,
  492. "wiasReadPropStr",
  493. NULL,
  494. TRUE,
  495. 1,
  496. &propSpec);
  497. if (bMustExist) {
  498. hr = E_INVALIDARG;
  499. }
  500. }
  501. return hr;
  502. }
  503. /**************************************************************************\
  504. * wiasReadPropLong
  505. *
  506. * Read property long helper.
  507. *
  508. * Arguments:
  509. *
  510. * pWiasContext - Pointer to WIA item
  511. * propid - Property ID
  512. * plVal - Pointer to returned LONG
  513. * plValOld - Pointer to returned LONG for previous value
  514. * bMustExist - Boolean value indicating whether the property must
  515. * exist. If this is true and the property is not found,
  516. * an E_INVALIDARG is returned.
  517. *
  518. * Return Value:
  519. *
  520. * Status
  521. *
  522. * History:
  523. *
  524. * 1/19/1999 Original Version
  525. *
  526. \**************************************************************************/
  527. HRESULT _stdcall wiasReadPropLong(
  528. BYTE *pWiasContext,
  529. PROPID propid,
  530. LONG *plVal,
  531. LONG *plValOld,
  532. BOOL bMustExist)
  533. {
  534. DBG_FN(::wiasReadPropLong);
  535. IWiaItem *pItem = (IWiaItem*) pWiasContext;
  536. HRESULT hr = ValidateWiaItem(pItem);
  537. if (FAILED(hr)) {
  538. DBG_ERR(("wiasReadPropLong, invalid pItem"));
  539. return hr;
  540. }
  541. if (IsBadWritePtr(plVal, sizeof(LONG))) {
  542. DBG_ERR(("wiasReadPropLong, invalid plVal pointer"));
  543. return E_POINTER;
  544. }
  545. if (plValOld && IsBadWritePtr(plValOld, sizeof(LONG))) {
  546. DBG_ERR(("wiasReadPropLong, invalid plValOld pointer"));
  547. return E_POINTER;
  548. }
  549. IPropertyStorage *pIPropStg, *pIPropOldStg;
  550. hr = ((CWiaItem*)pItem)->GetItemPropStreams(&pIPropStg,
  551. NULL,
  552. NULL,
  553. &pIPropOldStg);
  554. if (FAILED(hr)) {
  555. return hr;
  556. }
  557. //
  558. // Return the current value
  559. //
  560. PROPSPEC propSpec;
  561. PROPVARIANT propVar;
  562. propSpec.ulKind = PRSPEC_PROPID;
  563. propSpec.propid = propid;
  564. hr = pIPropStg->ReadMultiple(1, &propSpec, &propVar);
  565. if (hr == S_OK) {
  566. *plVal = propVar.lVal;
  567. //
  568. // Check whether we must return the old value.
  569. //
  570. if (plValOld) {
  571. hr = pIPropOldStg->ReadMultiple(1, &propSpec, &propVar);
  572. if (hr == S_OK) {
  573. *plValOld = propVar.lVal;
  574. }
  575. }
  576. }
  577. if (((hr == S_FALSE) && bMustExist) || FAILED(hr)) {
  578. ReportReadWriteMultipleError(hr,
  579. "wiasReadPropLong",
  580. NULL,
  581. TRUE,
  582. 1,
  583. &propSpec);
  584. if (bMustExist) {
  585. hr = E_INVALIDARG;
  586. }
  587. }
  588. return hr;
  589. }
  590. /**************************************************************************\
  591. * wiasReadPropFloat
  592. *
  593. * Read property floating point value helper.
  594. *
  595. * Arguments:
  596. *
  597. * pWiasContext - Pointer to WIA item
  598. * propid - Property ID
  599. * pfVal - Pointer to returned float
  600. * pfValOld - Pointer to returned float for previous value
  601. * bMustExist - Boolean value indicating whether the property must
  602. * exist. If this is true and the property is not found,
  603. * an E_INVALIDARG is returned.
  604. *
  605. * Return Value:
  606. *
  607. * Status
  608. *
  609. * History:
  610. *
  611. * 1/19/1999 Original Version
  612. *
  613. \**************************************************************************/
  614. HRESULT _stdcall wiasReadPropFloat(
  615. BYTE *pWiasContext,
  616. PROPID propid,
  617. FLOAT *pfVal,
  618. FLOAT *pfValOld,
  619. BOOL bMustExist)
  620. {
  621. DBG_FN(::wiasReadPropFloat);
  622. IWiaItem *pItem = (IWiaItem*) pWiasContext;
  623. HRESULT hr = ValidateWiaItem(pItem);
  624. if (FAILED(hr)) {
  625. DBG_ERR(("wiasReadPropFloat, invalid pItem"));
  626. return hr;
  627. }
  628. if (IsBadWritePtr(pfVal, sizeof(float))) {
  629. DBG_ERR(("wiasReadPropFloat, invalid pfVal pointer"));
  630. return E_POINTER;
  631. }
  632. if (pfValOld && (IsBadWritePtr(pfValOld, sizeof(float)))) {
  633. DBG_ERR(("wiasReadPropFloat, invalid pfValOld pointer"));
  634. return E_POINTER;
  635. }
  636. IPropertyStorage *pIPropStg, *pIPropOldStg;
  637. hr = ((CWiaItem*)pItem)->GetItemPropStreams(&pIPropStg, NULL, NULL, &pIPropOldStg);
  638. if (FAILED(hr)) {
  639. return hr;
  640. }
  641. //
  642. // Return the current value
  643. //
  644. PROPSPEC propSpec;
  645. PROPVARIANT propVar;
  646. propSpec.ulKind = PRSPEC_PROPID;
  647. propSpec.propid = propid;
  648. hr = pIPropStg->ReadMultiple(1, &propSpec, &propVar);
  649. if (hr == S_OK) {
  650. *pfVal = propVar.fltVal;
  651. //
  652. // Check whether we must return the old value.
  653. //
  654. if (pfValOld) {
  655. hr = pIPropOldStg->ReadMultiple(1, &propSpec, &propVar);
  656. if (hr == S_OK) {
  657. *pfValOld = propVar.fltVal;
  658. }
  659. }
  660. }
  661. if (((hr == S_FALSE) && bMustExist) || FAILED(hr)) {
  662. ReportReadWriteMultipleError(hr,
  663. "wiasReadPropFloat",
  664. NULL,
  665. TRUE,
  666. 1,
  667. &propSpec);
  668. if (bMustExist) {
  669. hr = E_INVALIDARG;
  670. }
  671. }
  672. return hr;
  673. }
  674. /**************************************************************************\
  675. * wiasReadPropGuid
  676. *
  677. * Read property long helper.
  678. *
  679. * Arguments:
  680. *
  681. * pWiasContext - Pointer to WIA item
  682. * propid - Property ID
  683. * pguidVal - Pointer to returned LONG
  684. * pguidValOld - Pointer to returned LONG for previous value
  685. * bMustExist - Boolean value indicating whether the property must
  686. * exist. If this is true and the property is not found,
  687. * an E_INVALIDARG is returned.
  688. *
  689. * Return Value:
  690. *
  691. * Status
  692. *
  693. * History:
  694. *
  695. * 1/19/1999 Original Version
  696. *
  697. \**************************************************************************/
  698. HRESULT _stdcall wiasReadPropGuid(
  699. BYTE *pWiasContext,
  700. PROPID propid,
  701. GUID *pguidVal,
  702. GUID *pguidValOld,
  703. BOOL bMustExist)
  704. {
  705. DBG_FN(::wiasReadPropGuid);
  706. IWiaItem *pItem = (IWiaItem*) pWiasContext;
  707. HRESULT hr = ValidateWiaItem(pItem);
  708. if (FAILED(hr)) {
  709. DBG_ERR(("wiasReadPropGuid, invalid pItem"));
  710. return hr;
  711. }
  712. if (IsBadWritePtr(pguidVal, sizeof(WIA_FORMAT_INFO))) {
  713. DBG_ERR(("wiasReadPropGuid, invalid plVal pointer"));
  714. return E_POINTER;
  715. }
  716. if (pguidValOld && IsBadWritePtr(pguidValOld, sizeof(WIA_FORMAT_INFO))) {
  717. DBG_ERR(("wiasReadPropGuid, invalid plValOld pointer"));
  718. return E_POINTER;
  719. }
  720. IPropertyStorage *pIPropStg, *pIPropOldStg;
  721. hr = ((CWiaItem*)pItem)->GetItemPropStreams(&pIPropStg,
  722. NULL,
  723. NULL,
  724. &pIPropOldStg);
  725. if (FAILED(hr)) {
  726. return hr;
  727. }
  728. //
  729. // Return the current value
  730. //
  731. PROPSPEC propSpec;
  732. PROPVARIANT propVar;
  733. propSpec.ulKind = PRSPEC_PROPID;
  734. propSpec.propid = propid;
  735. hr = pIPropStg->ReadMultiple(1, &propSpec, &propVar);
  736. if (hr == S_OK) {
  737. memcpy(pguidVal, propVar.puuid, sizeof(GUID));
  738. PropVariantClear(&propVar);
  739. //
  740. // Check whether we must return the old value.
  741. //
  742. if (pguidValOld) {
  743. hr = pIPropOldStg->ReadMultiple(1, &propSpec, &propVar);
  744. if (hr == S_OK) {
  745. memcpy(pguidValOld, propVar.puuid, sizeof(GUID));
  746. PropVariantClear(&propVar);
  747. }
  748. }
  749. }
  750. if (((hr == S_FALSE) && bMustExist) || FAILED(hr)) {
  751. ReportReadWriteMultipleError(hr,
  752. "wiasReadPropGuid",
  753. NULL,
  754. TRUE,
  755. 1,
  756. &propSpec);
  757. if (bMustExist) {
  758. hr = E_INVALIDARG;
  759. }
  760. }
  761. return hr;
  762. }
  763. /**************************************************************************\
  764. * wiasReadPropBin
  765. *
  766. * Read property binary helper.
  767. *
  768. * Arguments:
  769. *
  770. * pWiasContext - Pointer to WIA item
  771. * propid - Property ID
  772. * pbVal - Pointer to caller allocated buffer.
  773. * pbValOld - Pointer to caller allocated buffer for previous value.
  774. * bMustExist - Boolean value indicating whether the property must
  775. * exist. If this is true and the property is not found,
  776. * an E_INVALIDARG is returned.
  777. *
  778. * Return Value:
  779. *
  780. * Status
  781. *
  782. * History:
  783. *
  784. * 1/19/1999 Original Version
  785. *
  786. \**************************************************************************/
  787. HRESULT _stdcall wiasReadPropBin(
  788. BYTE *pWiasContext,
  789. PROPID propid,
  790. BYTE **ppbVal,
  791. BYTE **ppbValOld,
  792. BOOL bMustExist)
  793. {
  794. DBG_FN(::wiasReadPropBin);
  795. IWiaItem *pItem = (IWiaItem*) pWiasContext;
  796. HRESULT hr = ValidateWiaItem(pItem);
  797. if (FAILED(hr)) {
  798. DBG_ERR(("wiasReadPropBin, invalid pItem"));
  799. return hr;
  800. }
  801. if (IsBadWritePtr(ppbVal, sizeof(BYTE*))) {
  802. DBG_ERR(("wiasReadPropBin, invalid ppbVal pointer"));
  803. return E_POINTER;
  804. }
  805. if (ppbValOld && (IsBadWritePtr(ppbValOld, sizeof(BYTE*)))) {
  806. DBG_ERR(("wiasReadPropBin, invalid ppbVal pointer"));
  807. return E_POINTER;
  808. }
  809. *ppbVal = NULL;
  810. IPropertyStorage *pIPropStg, *pIPropOldStg;
  811. hr = ((CWiaItem*)pItem)->GetItemPropStreams(&pIPropStg, NULL, NULL, &pIPropOldStg);
  812. if (FAILED(hr)) {
  813. return hr;
  814. }
  815. //
  816. // Return the current value
  817. //
  818. PROPSPEC propSpec;
  819. PROPVARIANT propVar;
  820. propSpec.ulKind = PRSPEC_PROPID;
  821. propSpec.propid = propid;
  822. hr = pIPropStg->ReadMultiple(1, &propSpec, &propVar);
  823. if (hr == S_OK) {
  824. if (propVar.vt == (VT_VECTOR | VT_UI1)) {
  825. *ppbVal = propVar.caub.pElems;
  826. }
  827. else {
  828. DBG_ERR(("wiasReadPropBin, invalid property type: %X", propVar.vt));
  829. PropVariantClear(&propVar);
  830. return E_INVALIDARG;
  831. }
  832. //
  833. // If requested, get the old value.
  834. //
  835. if (ppbValOld) {
  836. hr = pIPropOldStg->ReadMultiple(1, &propSpec, &propVar);
  837. if (hr == S_OK) {
  838. if (propVar.vt == (VT_VECTOR | VT_UI1)) {
  839. *ppbValOld = propVar.caub.pElems;
  840. }
  841. else {
  842. DBG_ERR(("wiasReadPropBin, invalid property type: %X", propVar.vt));
  843. PropVariantClear(&propVar);
  844. return E_INVALIDARG;
  845. }
  846. }
  847. }
  848. }
  849. if (((hr == S_FALSE) && bMustExist) || FAILED(hr)) {
  850. ReportReadWriteMultipleError(hr,
  851. "wiasReadPropBin",
  852. NULL,
  853. TRUE,
  854. 1,
  855. &propSpec);
  856. if (bMustExist) {
  857. hr = E_INVALIDARG;
  858. }
  859. }
  860. return hr;
  861. }
  862. /**************************************************************************\
  863. * wiasWriteMultiple
  864. *
  865. * Write multiple properties helper.
  866. *
  867. * Arguments:
  868. *
  869. * pWiasContext - Pointer to WIA item
  870. * ulCount - Number of properties to write.
  871. * ps - A caller alocated array of PROPSPEC.
  872. * pv - A caller alocated array of PROPVARIANTS.
  873. *
  874. * Return Value:
  875. *
  876. * Status
  877. *
  878. * History:
  879. *
  880. * 1/19/1999 Original Version
  881. *
  882. \**************************************************************************/
  883. HRESULT _stdcall wiasWriteMultiple(
  884. BYTE *pWiasContext,
  885. ULONG ulCount,
  886. const PROPSPEC *ps,
  887. const PROPVARIANT *pv)
  888. {
  889. DBG_FN(::wiasWriteMultiple);
  890. IWiaItem *pItem = (IWiaItem*) pWiasContext;
  891. HRESULT hr = ValidateWiaItem(pItem);
  892. if (FAILED(hr)) {
  893. DBG_ERR(("wiasWriteMultiple, invalid pItem"));
  894. return hr;
  895. }
  896. if (IsBadReadPtr(ps, sizeof(PROPSPEC) * ulCount)) {
  897. DBG_ERR(("wiasWriteMultiple, invalid ps pointer"));
  898. return E_POINTER;
  899. }
  900. if (IsBadReadPtr(pv, sizeof(PROPVARIANT) * ulCount)) {
  901. DBG_ERR(("wiasWriteMultiple, invalid pv pointer"));
  902. return E_POINTER;
  903. }
  904. IPropertyStorage *pIPropStg;
  905. hr = ((CWiaItem*)pItem)->GetItemPropStreams(&pIPropStg, NULL, NULL, NULL);
  906. if (FAILED(hr)) {
  907. return hr;
  908. }
  909. //
  910. // Set the property to the new value
  911. //
  912. hr = pIPropStg->WriteMultiple(ulCount, ps, pv, WIA_DIP_FIRST);
  913. if (FAILED(hr)) {
  914. ReportReadWriteMultipleError(hr,
  915. "wiasWriteMultiple",
  916. NULL,
  917. FALSE,
  918. ulCount,
  919. ps);
  920. }
  921. return hr;
  922. }
  923. /**************************************************************************\
  924. * wiasWritePropStr
  925. *
  926. * Write property string helper.
  927. *
  928. * Arguments:
  929. *
  930. * pWiasContext - Pointer to WIA item
  931. * propid - Property ID
  932. * bstr - BSTR to be written.
  933. *
  934. * Return Value:
  935. *
  936. * Status
  937. *
  938. * History:
  939. *
  940. * 1/19/1999 Original Version
  941. *
  942. \**************************************************************************/
  943. HRESULT _stdcall wiasWritePropStr(
  944. BYTE *pWiasContext,
  945. PROPID propid,
  946. BSTR bstr)
  947. {
  948. DBG_FN(::wiasWritePropStr);
  949. IWiaItem *pItem = (IWiaItem*) pWiasContext;
  950. BSTR bstrOld;
  951. HRESULT hr = ValidateWiaItem(pItem);
  952. if (FAILED(hr)) {
  953. DBG_ERR(("wiasWritePropStr, invalid pItem"));
  954. return hr;
  955. }
  956. // NULL is a valid BSTR value.
  957. if (bstr) {
  958. if (IsBadStringPtrW(bstr, SysStringLen(bstr))) {
  959. DBG_ERR(("wiasWriteMultiple, invalid bstr pointer"));
  960. return E_POINTER;
  961. }
  962. }
  963. IPropertyStorage *pIPropStg;
  964. hr = ((CWiaItem*)pItem)->GetItemPropStreams(&pIPropStg, NULL, NULL, NULL);
  965. if (FAILED(hr)) {
  966. return hr;
  967. }
  968. //
  969. // Set the property to the new value
  970. //
  971. hr = WritePropStr(propid, pIPropStg, bstr);
  972. if (FAILED(hr)) {
  973. DBG_ERR(("wiasWriteMultiple, error writing new value"));
  974. }
  975. return hr;
  976. }
  977. /**************************************************************************\
  978. * wiasWritePropLong
  979. *
  980. * Write property long helper
  981. *
  982. * Arguments:
  983. *
  984. * pWiasContext - Pointer to WIA item
  985. * propid - Property ID
  986. * lVal - Value to write.
  987. *
  988. * Return Value:
  989. *
  990. * Status
  991. *
  992. * History:
  993. *
  994. * 1/19/1999 Original Version
  995. *
  996. \**************************************************************************/
  997. HRESULT _stdcall wiasWritePropLong(
  998. BYTE *pWiasContext,
  999. PROPID propid,
  1000. LONG lVal)
  1001. {
  1002. DBG_FN(::wiasWritePropLong);
  1003. IWiaItem *pItem = (IWiaItem*) pWiasContext;
  1004. LONG lValOld;
  1005. HRESULT hr = ValidateWiaItem(pItem);
  1006. if (FAILED(hr)) {
  1007. DBG_ERR(("wiasWritePropLong, invalid pItem"));
  1008. return hr;
  1009. }
  1010. IPropertyStorage *pIPropStg;
  1011. hr = ((CWiaItem*)pItem)->GetItemPropStreams(&pIPropStg, NULL, NULL, NULL);
  1012. if (FAILED(hr)) {
  1013. return hr;
  1014. }
  1015. //
  1016. // Set new value
  1017. //
  1018. WritePropLong(propid, pIPropStg, lVal);
  1019. return hr;
  1020. }
  1021. /**************************************************************************\
  1022. * wiasWritePropFloat
  1023. *
  1024. * Write property float helper
  1025. *
  1026. * Arguments:
  1027. *
  1028. * pWiasContext - Pointer to WIA item
  1029. * propid - Property ID
  1030. * fVal - Float to be written.
  1031. *
  1032. * Return Value:
  1033. *
  1034. * Status
  1035. *
  1036. * History:
  1037. *
  1038. * 1/19/1999 Original Version
  1039. *
  1040. \**************************************************************************/
  1041. HRESULT _stdcall wiasWritePropFloat(
  1042. BYTE *pWiasContext,
  1043. PROPID propid,
  1044. float fVal)
  1045. {
  1046. DBG_FN(::wiasWritePropFloat);
  1047. IWiaItem *pItem = (IWiaItem*) pWiasContext;
  1048. float fValOld;
  1049. HRESULT hr = ValidateWiaItem(pItem);
  1050. if (FAILED(hr)) {
  1051. DBG_ERR(("wiasWritePropFloat, invalid pItem"));
  1052. return hr;
  1053. }
  1054. IPropertyStorage *pIPropStg;
  1055. hr = ((CWiaItem*)pItem)->GetItemPropStreams(&pIPropStg, NULL, NULL, NULL);
  1056. if (FAILED(hr)) {
  1057. return hr;
  1058. }
  1059. PROPSPEC propSpec;
  1060. PROPVARIANT propVar;
  1061. propSpec.ulKind = PRSPEC_PROPID;
  1062. propSpec.propid = propid;
  1063. //
  1064. // Write new value
  1065. //
  1066. PropVariantInit(&propVar);
  1067. propVar.vt = VT_R4;
  1068. propVar.fltVal = fVal;
  1069. hr = pIPropStg->WriteMultiple(1, &propSpec, &propVar, WIA_DIP_FIRST);
  1070. if (FAILED(hr)) {
  1071. ReportReadWriteMultipleError(hr, "wiasWritePropFloat", NULL, FALSE, 1, &propSpec);
  1072. }
  1073. return hr;
  1074. }
  1075. /**************************************************************************\
  1076. * wiasWritePropGuid
  1077. *
  1078. * Write property float helper
  1079. *
  1080. * Arguments:
  1081. *
  1082. * pWiasContext - Pointer to WIA item
  1083. * propid - Property ID
  1084. * pguidVal - pointer to GUID to be written.
  1085. *
  1086. * Return Value:
  1087. *
  1088. * Status
  1089. *
  1090. * History:
  1091. *
  1092. * 1/19/1999 Original Version
  1093. *
  1094. \**************************************************************************/
  1095. HRESULT _stdcall wiasWritePropGuid(
  1096. BYTE *pWiasContext,
  1097. PROPID propid,
  1098. GUID guidVal)
  1099. {
  1100. DBG_FN(::wiasWritePropGuid);
  1101. IWiaItem *pItem = (IWiaItem*) pWiasContext;
  1102. GUID guidValOld;
  1103. HRESULT hr = ValidateWiaItem(pItem);
  1104. if (FAILED(hr)) {
  1105. DBG_ERR(("wiasWritePropFloat, invalid pItem"));
  1106. return hr;
  1107. }
  1108. IPropertyStorage *pIPropStg;
  1109. hr = ((CWiaItem*)pItem)->GetItemPropStreams(&pIPropStg, NULL, NULL, NULL);
  1110. if (FAILED(hr)) {
  1111. return hr;
  1112. }
  1113. PROPSPEC propSpec;
  1114. PROPVARIANT propVar;
  1115. propSpec.ulKind = PRSPEC_PROPID;
  1116. propSpec.propid = propid;
  1117. //
  1118. // Write new value
  1119. //
  1120. PropVariantInit(&propVar);
  1121. propVar.vt = VT_CLSID;
  1122. propVar.puuid = &guidVal;
  1123. hr = pIPropStg->WriteMultiple(1, &propSpec, &propVar, WIA_DIP_FIRST);
  1124. if (FAILED(hr)) {
  1125. ReportReadWriteMultipleError(hr, "wiasWritePropFloat", NULL, FALSE, 1, &propSpec);
  1126. }
  1127. return hr;
  1128. }
  1129. /**************************************************************************\
  1130. * wiasWritePropBin
  1131. *
  1132. * Write property binary helper
  1133. *
  1134. * Arguments:
  1135. *
  1136. * pWiasContext - Pointer to WIA item
  1137. * propid - Property ID
  1138. * cbVal - Number of bytes to write.
  1139. * pbVal - Pointer to binary value to write.
  1140. *
  1141. * Return Value:
  1142. *
  1143. * Status
  1144. *
  1145. * History:
  1146. *
  1147. * 1/19/1999 Original Version
  1148. *
  1149. \**************************************************************************/
  1150. HRESULT _stdcall wiasWritePropBin(
  1151. BYTE *pWiasContext,
  1152. PROPID propid,
  1153. LONG cbVal,
  1154. BYTE *pbVal)
  1155. {
  1156. DBG_FN(::wiasWritePropBin);
  1157. IWiaItem *pItem = (IWiaItem*) pWiasContext;
  1158. HRESULT hr = ValidateWiaItem(pItem);
  1159. if (FAILED(hr)) {
  1160. DBG_ERR(("wiasWritePropBin, invalid pItem"));
  1161. return hr;
  1162. }
  1163. if (IsBadReadPtr(pbVal, cbVal)) {
  1164. DBG_ERR(("wiasWritePropBin, invalid pbVal pointer"));
  1165. return E_POINTER;
  1166. }
  1167. IPropertyStorage *pIPropStg;
  1168. hr = ((CWiaItem*)pItem)->GetItemPropStreams(&pIPropStg, NULL, NULL, NULL);
  1169. if (FAILED(hr)) {
  1170. return hr;
  1171. }
  1172. PROPSPEC propSpec;
  1173. PROPVARIANT propVar;
  1174. propSpec.ulKind = PRSPEC_PROPID;
  1175. propSpec.propid = propid;
  1176. //
  1177. // Write the new value
  1178. //
  1179. propVar.vt = VT_VECTOR | VT_UI1;
  1180. propVar.caub.pElems = pbVal;
  1181. propVar.caub.cElems = cbVal;
  1182. hr = pIPropStg->WriteMultiple(1, &propSpec, &propVar, WIA_DIP_FIRST);
  1183. if (FAILED(hr)) {
  1184. ReportReadWriteMultipleError(hr, "wiasWritePropBin", NULL, FALSE, 1, &propSpec);
  1185. }
  1186. return hr;
  1187. }
  1188. /**************************************************************************\
  1189. * wiasGetPropertyAttributes
  1190. *
  1191. * Get the access flags and valid values for a property.
  1192. *
  1193. * Arguments:
  1194. *
  1195. * pWiasContext - Pointer to WIA item
  1196. * cPropSpec - The number of properties
  1197. * pPropSpec - array of property specification.
  1198. * pulAccessFlags - array of LONGs access flags.
  1199. * pPropVar - Pointer to returned valid values.
  1200. *
  1201. * Return Value:
  1202. *
  1203. * Status
  1204. *
  1205. * History:
  1206. *
  1207. * 1/19/1999 Original Version
  1208. *
  1209. \**************************************************************************/
  1210. HRESULT _stdcall wiasGetPropertyAttributes(
  1211. BYTE *pWiasContext,
  1212. LONG cPropSpec,
  1213. PROPSPEC *pPropSpec,
  1214. ULONG *pulAccessFlags,
  1215. PROPVARIANT *pPropVar)
  1216. {
  1217. DBG_FN(::wiasGetPropertyAttributes);
  1218. IWiaItem *pItem = (IWiaItem*) pWiasContext;
  1219. //
  1220. // Do parameter validation.
  1221. //
  1222. HRESULT hr = ValidateWiaItem(pItem);
  1223. if (FAILED(hr)) {
  1224. DBG_ERR(("wiasGetPropertyAttributes, invalid pItem"));
  1225. return hr;
  1226. }
  1227. if (IsBadReadPtr(pPropSpec, sizeof(PROPSPEC) * cPropSpec)) {
  1228. DBG_ERR(("wiasGetPropertyAttributes, bad pPropSpec parameter"));
  1229. return E_POINTER;
  1230. }
  1231. if (IsBadWritePtr(pulAccessFlags, sizeof(ULONG) * cPropSpec)) {
  1232. DBG_ERR(("wiasGetPropertyAttributes, bad pulAccessFlags parameter"));
  1233. return E_POINTER;
  1234. }
  1235. if (IsBadWritePtr(pPropVar, sizeof(PROPVARIANT) * cPropSpec)) {
  1236. DBG_ERR(("wiasGetPropertyAttributes, bad pPropVar parameter"));
  1237. return E_POINTER;
  1238. }
  1239. //
  1240. // Now that validation has been done, call helper function to get
  1241. // the property attributes
  1242. //
  1243. return GetPropertyAttributesHelper(pItem,
  1244. cPropSpec,
  1245. pPropSpec,
  1246. pulAccessFlags,
  1247. pPropVar);
  1248. }
  1249. /**************************************************************************\
  1250. * wiasSetPropertyAttributes
  1251. *
  1252. * Set the access flags and valid values for a set of properties.
  1253. *
  1254. * Arguments:
  1255. *
  1256. * pWiasContext - Pointer to WIA item
  1257. * cPropSpec - The number of properties
  1258. * pPropSpec - Pointer to a property specification.
  1259. * pulAccessFlags - Access flags.
  1260. * pPropVar - Pointer to valid values.
  1261. *
  1262. * Return Value:
  1263. *
  1264. * Status
  1265. *
  1266. * History:
  1267. *
  1268. * 1/19/1999 Original Version
  1269. *
  1270. \**************************************************************************/
  1271. HRESULT _stdcall wiasSetPropertyAttributes(
  1272. BYTE *pWiasContext,
  1273. LONG cPropSpec,
  1274. PROPSPEC *pPropSpec,
  1275. ULONG *pulAccessFlags,
  1276. PROPVARIANT *pPropVar)
  1277. {
  1278. DBG_FN(::wiasSetPropertyAttributes);
  1279. IWiaItem *pItem = (IWiaItem*) pWiasContext;
  1280. //
  1281. // May be called by driver or application, do parameter validation.
  1282. //
  1283. HRESULT hr = ValidateWiaItem(pItem);
  1284. if (FAILED(hr)) {
  1285. DBG_ERR(("wiasSetPropertyAttributes, invalid pItem"));
  1286. return hr;
  1287. }
  1288. if (IsBadReadPtr(pPropSpec, sizeof(PROPSPEC) * cPropSpec)) {
  1289. DBG_ERR(("wiasSetPropertyAttributes, bad pPropSpec parameter"));
  1290. return E_POINTER;
  1291. }
  1292. if (IsBadWritePtr(pulAccessFlags, sizeof(ULONG) * cPropSpec)) {
  1293. DBG_ERR(("wiasSetPropertyAttributes, bad pulAccessFlags parameter"));
  1294. return E_POINTER;
  1295. }
  1296. if (IsBadWritePtr(pPropVar, sizeof(PROPVARIANT) * cPropSpec)) {
  1297. DBG_ERR(("wiasSetPropertyAttributes, bad pPropVar parameter"));
  1298. return E_POINTER;
  1299. }
  1300. //
  1301. // Get the item's internal property storage pointers.
  1302. //
  1303. IPropertyStorage *pIPropAccessStg;
  1304. IPropertyStorage *pIPropValidStg;
  1305. hr = ((CWiaItem*)pItem)->GetItemPropStreams(NULL,
  1306. &pIPropAccessStg,
  1307. &pIPropValidStg,
  1308. NULL);
  1309. if (FAILED(hr)) {
  1310. return hr;
  1311. }
  1312. //
  1313. // Set the Access flags for the properties.
  1314. //
  1315. PROPVARIANT *pVar;
  1316. pVar = (PROPVARIANT*) LocalAlloc(LPTR, sizeof(PROPVARIANT) * cPropSpec);
  1317. if (pVar) {
  1318. for (int flagIndex = 0; flagIndex < cPropSpec; flagIndex++) {
  1319. pVar[flagIndex].vt = VT_UI4;
  1320. pVar[flagIndex].ulVal = pulAccessFlags[flagIndex];
  1321. }
  1322. hr = pIPropAccessStg->WriteMultiple(cPropSpec, pPropSpec, pVar, WIA_DIP_FIRST);
  1323. LocalFree(pVar);
  1324. if (SUCCEEDED(hr)) {
  1325. //
  1326. // Set the valid values
  1327. //
  1328. hr = pIPropValidStg->WriteMultiple(cPropSpec, pPropSpec, pPropVar, WIA_DIP_FIRST);
  1329. if (FAILED(hr)) {
  1330. DBG_ERR(("wiasSetPropertyAttributes, could not set valid values"));
  1331. }
  1332. } else {
  1333. DBG_ERR(("wiasSetPropertyAttributes, could not set access flags"));
  1334. }
  1335. } else {
  1336. DBG_ERR(("wiasSetPropertyAttributes, out of memory"));
  1337. return E_OUTOFMEMORY;
  1338. }
  1339. if (FAILED(hr)) {
  1340. ReportReadWriteMultipleError(hr, "wiasSetPropertyAttributes",
  1341. NULL,
  1342. FALSE,
  1343. cPropSpec,
  1344. pPropSpec);
  1345. }
  1346. return hr;
  1347. }
  1348. /**************************************************************************\
  1349. * RangeToPropVariant
  1350. *
  1351. * Move information from a WIA_PROPERTY_INFO struct to a PROPVARIANT. The
  1352. * WIA_PROPERTY_INFO is known to be of type WIA_PROP_RANGE.
  1353. *
  1354. * Arguments:
  1355. *
  1356. * pwpi - pointer to WIA_PROPERTY_INFO structure
  1357. * ppv - pointer to PROPVARIANT structure
  1358. *
  1359. * Return Value:
  1360. *
  1361. * Status - S_OK if successful
  1362. * - E_INVALIDARG if the vt type is not supported.
  1363. * - E_OUTOFMEMORY if storage for the range could not be
  1364. * allocated.
  1365. *
  1366. *
  1367. * History:
  1368. *
  1369. * 10/29/1998 Original Version
  1370. *
  1371. \**************************************************************************/
  1372. //
  1373. // Helper macro
  1374. //
  1375. #define MAKE_RANGE(WPI, PV, Type, VName, RType) { \
  1376. \
  1377. Type *pArray = (Type*) CoTaskMemAlloc(sizeof(Type) * WIA_RANGE_NUM_ELEMS);\
  1378. \
  1379. if (pArray) { \
  1380. PV->VName.cElems = WIA_RANGE_NUM_ELEMS; \
  1381. PV->VName.pElems = (Type*)pArray; \
  1382. PV->VName.pElems[WIA_RANGE_MIN] = (Type) WPI->ValidVal.RType.Min; \
  1383. PV->VName.pElems[WIA_RANGE_NOM] = (Type) WPI->ValidVal.RType.Nom; \
  1384. PV->VName.pElems[WIA_RANGE_MAX] = (Type) WPI->ValidVal.RType.Max; \
  1385. PV->VName.pElems[WIA_RANGE_STEP] = (Type) WPI->ValidVal.RType.Inc; \
  1386. } else { \
  1387. DBG_ERR(("RangeToPropVariant, unable to allocate range list")); \
  1388. hr = E_OUTOFMEMORY; \
  1389. } \
  1390. };
  1391. HRESULT RangeToPropVariant(
  1392. WIA_PROPERTY_INFO *pwpi,
  1393. PROPVARIANT *ppv)
  1394. {
  1395. DBG_FN(::RangeToPropVariant);
  1396. HRESULT hr = S_OK;
  1397. ppv->vt = VT_VECTOR | pwpi->vt;
  1398. switch (pwpi->vt) {
  1399. case (VT_UI1):
  1400. MAKE_RANGE(pwpi, ppv, UCHAR, caub, Range);
  1401. break;
  1402. case (VT_UI2):
  1403. MAKE_RANGE(pwpi, ppv, USHORT, caui, Range);
  1404. break;
  1405. case (VT_UI4):
  1406. MAKE_RANGE(pwpi, ppv, ULONG, caul, Range);
  1407. break;
  1408. case (VT_I2):
  1409. MAKE_RANGE(pwpi, ppv, SHORT, cai, Range);
  1410. break;
  1411. case (VT_I4):
  1412. MAKE_RANGE(pwpi, ppv, LONG, cal, Range);
  1413. break;
  1414. case (VT_R4):
  1415. MAKE_RANGE(pwpi, ppv, FLOAT, caflt, RangeFloat);
  1416. break;
  1417. case (VT_R8):
  1418. MAKE_RANGE(pwpi, ppv, DOUBLE, cadbl, RangeFloat);
  1419. break;
  1420. default:
  1421. //
  1422. // Type not supported
  1423. //
  1424. DBG_ERR(("RangeToPropVariant, type not supported"));
  1425. hr = E_INVALIDARG;
  1426. }
  1427. return hr;
  1428. }
  1429. /**************************************************************************\
  1430. * ListToPropVariant
  1431. *
  1432. * Move information from a WIA_PROPERTY_INFO struct to a PROPVARIANT. The
  1433. * WIA_PROPERTY_INFO is known to be of type WIA_PROP_LIST.
  1434. *
  1435. * Arguments:
  1436. *
  1437. * pwpi - pointer to WIA_PROPERTY_INFO structure
  1438. * ppv - pointer to PROPVARIANT structure
  1439. *
  1440. * Return Value:
  1441. *
  1442. * Status - S_OK if successful
  1443. * - E_INVALIDARG if the vt type is not supported.
  1444. * - E_OUTOFMEMORY if storage for the range could not be
  1445. * allocated.
  1446. *
  1447. *
  1448. * History:
  1449. *
  1450. * 10/29/1998 Original Version
  1451. *
  1452. \**************************************************************************/
  1453. //
  1454. // Helper macros
  1455. //
  1456. #define MAKE_LIST(WPI, PV, Type, Num, VName, LType) { \
  1457. \
  1458. if (IsBadReadPtr(WPI->ValidVal.LType.pList, sizeof(Type) * Num)) { \
  1459. hr = E_POINTER; \
  1460. break; \
  1461. }; \
  1462. \
  1463. Type *pArray = (Type*) CoTaskMemAlloc(sizeof(Type) * (Num + WIA_LIST_VALUES));\
  1464. \
  1465. if (pArray) { \
  1466. PV->VName.cElems = Num + WIA_LIST_VALUES; \
  1467. pArray[WIA_LIST_COUNT] = (Type) Num; \
  1468. pArray[WIA_LIST_NOM] = (Type) WPI->ValidVal.LType.Nom; \
  1469. \
  1470. memcpy(&pArray[WIA_LIST_VALUES], \
  1471. WPI->ValidVal.LType.pList, \
  1472. Num * sizeof(Type)); \
  1473. PV->VName.pElems = pArray; \
  1474. } else { \
  1475. DBG_ERR(("ListToPropVariant (MAKE_LIST), unable to allocate list"));\
  1476. hr = E_OUTOFMEMORY; \
  1477. } \
  1478. };
  1479. #define MAKE_LIST_GUID(WPI, PV, Type, Num) { \
  1480. \
  1481. if (IsBadReadPtr(WPI->ValidVal.ListGuid.pList, sizeof(GUID) * Num)) { \
  1482. hr = E_POINTER; \
  1483. break; \
  1484. }; \
  1485. \
  1486. GUID *pArray = (GUID*) CoTaskMemAlloc(sizeof(GUID) * (Num + WIA_LIST_VALUES));\
  1487. \
  1488. if (pArray) { \
  1489. PV->cauuid.cElems = Num + WIA_LIST_VALUES; \
  1490. pArray[WIA_LIST_COUNT] = WiaImgFmt_UNDEFINED; \
  1491. pArray[WIA_LIST_NOM] = WPI->ValidVal.ListGuid.Nom; \
  1492. \
  1493. memcpy(&pArray[WIA_LIST_VALUES], \
  1494. WPI->ValidVal.ListGuid.pList, \
  1495. Num * sizeof(GUID)); \
  1496. PV->cauuid.pElems = pArray; \
  1497. } else { \
  1498. DBG_ERR(("ListToPropVariant (MAKE_LIST), unable to allocate list"));\
  1499. hr = E_OUTOFMEMORY; \
  1500. } \
  1501. };
  1502. #define MAKE_LIST_BSTR(WPI, PV, Type, Num) { \
  1503. \
  1504. if (IsBadReadPtr(WPI->ValidVal.ListBStr.pList, sizeof(Type) * Num)) { \
  1505. DBG_ERR(("ListToPropVariant (MAKE_LIST_BSTR), pList pointer is bad"));\
  1506. hr = E_POINTER; \
  1507. break; \
  1508. }; \
  1509. \
  1510. Type *pArray = (Type*) CoTaskMemAlloc(sizeof(Type) * (Num + WIA_LIST_VALUES));\
  1511. \
  1512. if (pArray) { \
  1513. PV->cabstr.cElems = Num + WIA_LIST_VALUES; \
  1514. pArray[WIA_LIST_COUNT] = SysAllocString(L""); \
  1515. \
  1516. if(IsBadStringPtrW(WPI->ValidVal.ListBStr.Nom, SysStringLen(WPI->ValidVal.ListBStr.Nom))) {\
  1517. DBG_ERR(("ListToPropVariant (MAKE_LIST_BSTR), Nom BSTR is bad"));\
  1518. hr = E_POINTER; \
  1519. break; \
  1520. } \
  1521. pArray[WIA_LIST_NOM] = SysAllocString(WPI->ValidVal.ListBStr.Nom);\
  1522. if (!pArray[WIA_LIST_NOM]) { \
  1523. DBG_ERR(("ListToPropVariant (MAKE_LIST_BSTR), out of memory"));\
  1524. hr = E_OUTOFMEMORY; \
  1525. break; \
  1526. } \
  1527. \
  1528. for (ULONG i = 0; i < Num; i++) { \
  1529. if(IsBadStringPtrW(WPI->ValidVal.ListBStr.pList[i], SysStringLen(WPI->ValidVal.ListBStr.pList[i]))) {\
  1530. DBG_ERR(("ListToPropVariant (MAKE_LIST_BSTR), Nom BSTR is bad"));\
  1531. hr = E_POINTER; \
  1532. break; \
  1533. } \
  1534. pArray[WIA_LIST_VALUES + i] = SysAllocString(WPI->ValidVal.ListBStr.pList[i]);\
  1535. if (!pArray[WIA_LIST_VALUES + i]) { \
  1536. DBG_ERR(("ListToPropVariant (MAKE_LIST_BSTR), out of memory"));\
  1537. hr = E_OUTOFMEMORY; \
  1538. break; \
  1539. } \
  1540. } \
  1541. PV->cabstr.pElems = pArray; \
  1542. } else { \
  1543. DBG_ERR(("ListToPropVariant (MAKE_LIST_BSTR), unable to allocate list"));\
  1544. hr = E_OUTOFMEMORY; \
  1545. } \
  1546. };
  1547. HRESULT ListToPropVariant(
  1548. WIA_PROPERTY_INFO *pwpi,
  1549. PROPVARIANT *ppv)
  1550. {
  1551. DBG_FN(::ListToPropVariant);
  1552. ULONG cList;
  1553. HRESULT hr = S_OK;
  1554. cList = pwpi->ValidVal.List.cNumList;
  1555. ppv->vt = VT_VECTOR | pwpi->vt;
  1556. switch (pwpi->vt) {
  1557. case (VT_UI1):
  1558. MAKE_LIST(pwpi, ppv, UCHAR, cList, caub, List);
  1559. break;
  1560. case (VT_UI2):
  1561. MAKE_LIST(pwpi, ppv, USHORT, cList, caui, List);
  1562. break;
  1563. case (VT_UI4):
  1564. MAKE_LIST(pwpi, ppv, ULONG, cList, caul, List);
  1565. break;
  1566. case (VT_I2):
  1567. MAKE_LIST(pwpi, ppv, SHORT, cList, cai, List);
  1568. break;
  1569. case (VT_I4):
  1570. MAKE_LIST(pwpi, ppv, LONG, cList, cal, List);
  1571. break;
  1572. case (VT_R4):
  1573. MAKE_LIST(pwpi, ppv, FLOAT, cList, caflt, ListFloat);
  1574. break;
  1575. case (VT_R8):
  1576. MAKE_LIST(pwpi, ppv, DOUBLE, cList, cadbl, ListFloat);
  1577. break;
  1578. case (VT_CLSID):
  1579. MAKE_LIST_GUID(pwpi, ppv, GUID, cList);
  1580. break;
  1581. case (VT_BSTR):
  1582. MAKE_LIST_BSTR(pwpi, ppv, BSTR, cList);
  1583. break;
  1584. default:
  1585. //
  1586. // Type not supported
  1587. //
  1588. DBG_ERR(("ListToPropVariant, type (%d) not supported", pwpi->vt));
  1589. hr = E_INVALIDARG;
  1590. }
  1591. if (FAILED(hr)) {
  1592. PropVariantClear(ppv);
  1593. }
  1594. return hr;
  1595. }
  1596. /**************************************************************************\
  1597. * FlagToPropVariant
  1598. *
  1599. * Move information from a WIA_PROPERTY_INFO struct to a PROPVARIANT. The
  1600. * WIA_PROPERTY_INFO is known to be of type WIA_PROP_FLAG.
  1601. *
  1602. * Arguments:
  1603. *
  1604. * pwpi - pointer to WIA_PROPERTY_INFO structure
  1605. * ppv - pointer to PROPVARIANT structure
  1606. *
  1607. * Return Value:
  1608. *
  1609. * Status - S_OK if successful
  1610. * - E_OUTOFMEMORY if storage for the range could not be
  1611. * allocated.
  1612. *
  1613. *
  1614. * History:
  1615. *
  1616. * 10/29/1998 Original Version
  1617. *
  1618. \**************************************************************************/
  1619. HRESULT FlagToPropVariant(
  1620. WIA_PROPERTY_INFO *pwpi,
  1621. PROPVARIANT *ppv)
  1622. {
  1623. DBG_FN(::FlagToPropVariant);
  1624. //
  1625. // Check flag is of a valid VT
  1626. //
  1627. switch (pwpi->vt) {
  1628. case VT_I4:
  1629. case VT_UI4:
  1630. case VT_I8:
  1631. case VT_UI8:
  1632. break;
  1633. default:
  1634. DBG_ERR(("FlagToPropVariant, Invalid VT type (%d) for flag", pwpi->vt));
  1635. return E_INVALIDARG;
  1636. }
  1637. ppv->caul.pElems = (ULONG*) CoTaskMemAlloc(sizeof(ULONG) * WIA_FLAG_NUM_ELEMS);
  1638. if (ppv->caul.pElems) {
  1639. ppv->vt = VT_VECTOR | pwpi->vt;
  1640. ppv->caul.cElems = WIA_FLAG_NUM_ELEMS;
  1641. ppv->caul.pElems[WIA_FLAG_NOM] = pwpi->ValidVal.Flag.Nom;
  1642. ppv->caul.pElems[WIA_FLAG_VALUES] = pwpi->ValidVal.Flag.ValidBits;
  1643. } else {
  1644. DBG_ERR(("FlagToPropVariant, out of memory"));
  1645. return E_OUTOFMEMORY;
  1646. }
  1647. return S_OK;
  1648. }
  1649. /**************************************************************************\
  1650. * NoneToPropVariant
  1651. *
  1652. * Move information from a WIA_PROPERTY_INFO struct to a PROPVARIANT. The
  1653. * WIA_PROPERTY_INFO is known to be of type WIA_PROP_NONE.
  1654. *
  1655. * Arguments:
  1656. *
  1657. * pwpi - pointer to WIA_PROPERTY_INFO structure
  1658. * ppv - pointer to PROPVARIANT structure
  1659. *
  1660. * Return Value:
  1661. *
  1662. * Status - S_OK if successful
  1663. * - E_OUTOFMEMORY if storage for the range could not be
  1664. * allocated.
  1665. *
  1666. *
  1667. * History:
  1668. *
  1669. * 10/29/1998 Original Version
  1670. *
  1671. \**************************************************************************/
  1672. HRESULT NoneToPropVariant(
  1673. WIA_PROPERTY_INFO *pwpi,
  1674. PROPVARIANT *ppv)
  1675. {
  1676. DBG_FN(::NoneToPropVariant);
  1677. RPC_STATUS rpcs = RPC_S_OK;
  1678. ppv->vt = pwpi->vt;
  1679. switch (pwpi->vt) {
  1680. case VT_CLSID:
  1681. ppv->puuid = (GUID*) CoTaskMemAlloc(sizeof(GUID));
  1682. if (!ppv->puuid) {
  1683. return E_OUTOFMEMORY;
  1684. }
  1685. rpcs = UuidCreateNil(ppv->puuid);
  1686. if (rpcs != RPC_S_OK) {
  1687. DBG_WRN(("::NoneToPropVariant, UuidCreateNil returned 0x%08X", rpcs));
  1688. }
  1689. break;
  1690. default:
  1691. ppv->lVal = 0;
  1692. }
  1693. return S_OK;
  1694. }
  1695. /**************************************************************************\
  1696. * WiaPropertyInfoToPropVariant
  1697. *
  1698. * Move information from a WIA_PROPERTY_INFO struct to a PROPVARIANT.
  1699. *
  1700. * Arguments:
  1701. *
  1702. *
  1703. *
  1704. * Return Value:
  1705. *
  1706. * Status
  1707. *
  1708. * History:
  1709. *
  1710. * 10/29/1998 Original Version
  1711. *
  1712. \**************************************************************************/
  1713. HRESULT WiaPropertyInfoToPropVariant(
  1714. WIA_PROPERTY_INFO *pwpi,
  1715. PROPVARIANT *ppv)
  1716. {
  1717. DBG_FN(::WiaPropertyInfoToPropVariant);
  1718. HRESULT hr = S_OK;
  1719. memset(ppv, 0, sizeof(PROPVARIANT));
  1720. if (pwpi->lAccessFlags & WIA_PROP_NONE) {
  1721. hr = NoneToPropVariant(pwpi, ppv);
  1722. }
  1723. else if (pwpi->lAccessFlags & WIA_PROP_RANGE) {
  1724. hr = RangeToPropVariant(pwpi, ppv);
  1725. }
  1726. else if (pwpi->lAccessFlags & WIA_PROP_LIST) {
  1727. hr = ListToPropVariant(pwpi, ppv);
  1728. }
  1729. else if (pwpi->lAccessFlags & WIA_PROP_FLAG) {
  1730. hr = FlagToPropVariant(pwpi, ppv);
  1731. }
  1732. else {
  1733. DBG_ERR(("WiaPropertyInfoToPropVariant, bad access flags"));
  1734. return E_INVALIDARG;
  1735. }
  1736. return hr;
  1737. }
  1738. /**************************************************************************\
  1739. * wiasSetItemPropAttribs
  1740. *
  1741. * Set the access flags and valid values for a set of properties from
  1742. * an array of WIA_PROPERTY_INFO structures.
  1743. *
  1744. * Arguments:
  1745. *
  1746. * pWiasContext - Pointer to WIA item
  1747. * cPropSpec - The number of properties to set.
  1748. * pPropSpec - Pointer to an array of property specifications.
  1749. * pwpi - Pointer to an array of property information.
  1750. *
  1751. * Return Value:
  1752. *
  1753. * Status
  1754. *
  1755. * History:
  1756. *
  1757. * 1/19/1999 Original Version
  1758. *
  1759. \**************************************************************************/
  1760. HRESULT _stdcall wiasSetItemPropAttribs(
  1761. BYTE *pWiasContext,
  1762. LONG cPropSpec,
  1763. PROPSPEC *pPropSpec,
  1764. PWIA_PROPERTY_INFO pwpi)
  1765. {
  1766. DBG_FN(::wiasSetItemPropAttribs);
  1767. IWiaItem *pItem = (IWiaItem*) pWiasContext;
  1768. //
  1769. // Do parameter validation.
  1770. //
  1771. HRESULT hr = ValidateWiaItem(pItem);
  1772. if (FAILED(hr)) {
  1773. DBG_ERR(("wiasSetItemPropAttribs, invalid pItem"));
  1774. return hr;
  1775. }
  1776. if (IsBadReadPtr(pPropSpec, sizeof(PROPSPEC) * cPropSpec)) {
  1777. DBG_ERR(("wiasSetItemPropAttribs, bad pPropSpec parameter"));
  1778. return E_POINTER;
  1779. }
  1780. if (IsBadReadPtr(pwpi, sizeof(WIA_PROPERTY_INFO) * cPropSpec)) {
  1781. DBG_ERR(("wiasSetItemPropAttribs, bad pwpi parameter"));
  1782. return E_POINTER;
  1783. }
  1784. //
  1785. // Get the item's internal property storage pointers.
  1786. //
  1787. IPropertyStorage *pIPropAccessStg;
  1788. IPropertyStorage *pIPropValidStg;
  1789. hr = ((CWiaItem*)pItem)->GetItemPropStreams(NULL,
  1790. &pIPropAccessStg,
  1791. &pIPropValidStg,
  1792. NULL);
  1793. if (FAILED(hr)) {
  1794. return hr;
  1795. }
  1796. //
  1797. // Set the access flags and valid values for the items properties.
  1798. //
  1799. for (LONG i = 0; i < cPropSpec; i++) {
  1800. PROPVARIANT propvar;
  1801. PropVariantInit(&propvar);
  1802. hr = WiaPropertyInfoToPropVariant(&pwpi[i], &propvar);
  1803. if (FAILED(hr)) {
  1804. break;
  1805. }
  1806. hr = wiasSetPropertyAttributes(pWiasContext,
  1807. 1,
  1808. &pPropSpec[i],
  1809. &pwpi[i].lAccessFlags,
  1810. &propvar);
  1811. //
  1812. // Free any memory used by the propvariant
  1813. //
  1814. PropVariantClear(&propvar);
  1815. if (FAILED(hr)) {
  1816. DBG_ERR(("wiasSetItemPropAttribs, call to wiasSetPropertyAttributes failed"));
  1817. break;
  1818. }
  1819. }
  1820. return hr;
  1821. }
  1822. /**************************************************************************\
  1823. *
  1824. * wiasSetItemPropNames
  1825. *
  1826. * Sets the item property names for all three backing
  1827. * property storages (property, access and valid values).
  1828. *
  1829. * Arguments:
  1830. *
  1831. * pWiasContext - WIA item pointer.
  1832. * cItemProps - Number of property names to write.
  1833. * ppId - Caller allocated array of PROPID's.
  1834. * ppszNames - Caller allocated array of property names.
  1835. *
  1836. * Return Value:
  1837. *
  1838. * status
  1839. *
  1840. * History:
  1841. *
  1842. * 9/3/1998 Original Version
  1843. *
  1844. \**************************************************************************/
  1845. #define MAX_STR_LEN 65535
  1846. HRESULT _stdcall wiasSetItemPropNames(
  1847. BYTE *pWiasContext,
  1848. LONG cItemProps,
  1849. PROPID *ppId,
  1850. LPOLESTR *ppszNames)
  1851. {
  1852. DBG_FN(::wiasSetItemPropNames);
  1853. IWiaItem *pItem = (IWiaItem*) pWiasContext;
  1854. HRESULT hr = ValidateWiaItem(pItem);
  1855. if (FAILED(hr)) {
  1856. DBG_ERR(("wiasSetItemPropNames, invalid pItem"));
  1857. return hr;
  1858. }
  1859. if (IsBadWritePtr(ppId, sizeof(PROPID) * cItemProps)) {
  1860. DBG_ERR(("wiasSetItemPropNames, bad ppId parameter"));
  1861. return E_POINTER;
  1862. }
  1863. if (IsBadWritePtr(ppszNames, sizeof(LPOLESTR) * cItemProps)) {
  1864. DBG_ERR(("wiasSetItemPropNames, bad ppId parameter"));
  1865. return E_POINTER;
  1866. }
  1867. for (LONG i = 0; i < cItemProps; i++) {
  1868. if (IsBadStringPtrW(ppszNames[i], MAX_STR_LEN)) {
  1869. DBG_ERR(("wiasSetItemPropName, invalid ppszNames pointer, index: %d", i));
  1870. return E_POINTER;
  1871. }
  1872. }
  1873. return ((CWiaItem*)pItem)->WriteItemPropNames(cItemProps,
  1874. ppId,
  1875. ppszNames);
  1876. }
  1877. /**************************************************************************\
  1878. * DetermineBMISize
  1879. *
  1880. * Determine the size of the needed BITMAPINFO structure
  1881. *
  1882. * Arguments:
  1883. *
  1884. * headerSize - size of BITMAPINFOHEADER or
  1885. * BITMAPV4HEADER or BITMAPV5HEADER
  1886. * depth - bits per pixel
  1887. * biCompression - BI_RGB,BI_BITFIELDS,BI_RLE4,BI_RLE8,BI_JPEG,BI_PNG
  1888. * pcbBMI - required size/bytes written
  1889. * pcbColorMap - size of color map alone
  1890. *
  1891. * Return Value:
  1892. *
  1893. * Status
  1894. *
  1895. * History:
  1896. *
  1897. * 11/6/1998 Original Version
  1898. *
  1899. \**************************************************************************/
  1900. HRESULT DetermineBMISize(
  1901. LONG headerSize,
  1902. LONG depth,
  1903. LONG biCompression,
  1904. LONG* pcbBMI,
  1905. LONG* pcbColorMap
  1906. )
  1907. {
  1908. DBG_FN(::DetermineBMISize);
  1909. //
  1910. // Validate header size
  1911. //
  1912. *pcbBMI = NULL;
  1913. *pcbColorMap = NULL;
  1914. if (
  1915. #if (WINVER >= 0x0500)
  1916. (headerSize != sizeof(BITMAPINFOHEADER)) &&
  1917. (headerSize != sizeof(BITMAPV4HEADER)) &&
  1918. (headerSize != sizeof(BITMAPV5HEADER))
  1919. #else
  1920. (headerSize != sizeof(BITMAPINFOHEADER)) &&
  1921. (headerSize != sizeof(BITMAPV4HEADER))
  1922. #endif
  1923. ) {
  1924. DBG_ERR(("WriteBMI, unexpected headerSize: %d",headerSize ));
  1925. return E_INVALIDARG;
  1926. }
  1927. //
  1928. // Calculate color table size.
  1929. //
  1930. LONG ColorMapSize = 0;
  1931. if (
  1932. (biCompression == BI_RGB) ||
  1933. (biCompression == BI_BITFIELDS) ||
  1934. (biCompression == BI_RLE4) ||
  1935. (biCompression == BI_RLE8)
  1936. ) {
  1937. switch (depth) {
  1938. case 1:
  1939. ColorMapSize = 2;
  1940. break;
  1941. case 4:
  1942. ColorMapSize = 16;
  1943. break;
  1944. case 8:
  1945. ColorMapSize = 256;
  1946. break;
  1947. case 15:
  1948. case 16:
  1949. ColorMapSize = 3;
  1950. break;
  1951. case 24:
  1952. ColorMapSize = 0;
  1953. break;
  1954. case 32:
  1955. if (biCompression == BI_BITFIELDS) {
  1956. ColorMapSize = 0;
  1957. } else {
  1958. ColorMapSize = 3;
  1959. }
  1960. break;
  1961. default:
  1962. DBG_ERR(("WriteBMI, unexpected depth: %d", depth));
  1963. return E_INVALIDARG;
  1964. }
  1965. }
  1966. //
  1967. // Calculate the BMI size.
  1968. //
  1969. *pcbColorMap = ColorMapSize;
  1970. *pcbBMI = (ColorMapSize * sizeof(RGBQUAD)) + sizeof(BITMAPINFOHEADER);
  1971. return S_OK;
  1972. }
  1973. /**************************************************************************\
  1974. * WriteDibHeader
  1975. *
  1976. * Write the DIB header to a buffer.
  1977. *
  1978. * Arguments:
  1979. *
  1980. * pmdtc - Pointer to mini driver transfer context.
  1981. *
  1982. * Return Value:
  1983. *
  1984. * Status
  1985. *
  1986. * History:
  1987. *
  1988. * 4/5/1999 Original Version
  1989. *
  1990. \**************************************************************************/
  1991. HRESULT WriteDibHeader(
  1992. LONG lColorMapSize,
  1993. PMINIDRV_TRANSFER_CONTEXT pmdtc)
  1994. {
  1995. DBG_FN(::WriteDibHeader);
  1996. UNALIGNED BITMAPINFO* pbmi = (BITMAPINFO*)pmdtc->pTransferBuffer;
  1997. UNALIGNED BITMAPFILEHEADER* pbmf = NULL;
  1998. //
  1999. // If this is a file, fill in file header.
  2000. //
  2001. if (IsEqualGUID(pmdtc->guidFormatID, WiaImgFmt_BMP)) {
  2002. //
  2003. // Setup file header pointers.
  2004. //
  2005. pbmf = (BITMAPFILEHEADER*)pmdtc->pTransferBuffer;
  2006. pbmi = (BITMAPINFO*)((PBYTE)pbmf + sizeof(BITMAPFILEHEADER));
  2007. //
  2008. // fill in bitmapfileheader
  2009. //
  2010. pbmf->bfType = 'MB';
  2011. pbmf->bfSize = pmdtc->lImageSize + pmdtc->lHeaderSize;
  2012. pbmf->bfReserved1 = 0;
  2013. pbmf->bfReserved2 = 0;
  2014. pbmf->bfOffBits = pmdtc->lHeaderSize;
  2015. }
  2016. UNALIGNED BITMAPINFOHEADER* pbmih = (BITMAPINFOHEADER*)pbmi;
  2017. pbmih->biSize = sizeof(BITMAPINFOHEADER);
  2018. pbmih->biWidth = pmdtc->lWidthInPixels;
  2019. pbmih->biHeight = pmdtc->lLines;
  2020. pbmih->biPlanes = 1;
  2021. pbmih->biBitCount = (USHORT)pmdtc->lDepth;
  2022. pbmih->biCompression = BI_RGB;
  2023. pbmih->biSizeImage = pmdtc->lLines * pmdtc->cbWidthInBytes;
  2024. pbmih->biXPelsPerMeter = MulDiv(pmdtc->lXRes,10000,254);
  2025. pbmih->biYPelsPerMeter = MulDiv(pmdtc->lYRes,10000,254);
  2026. pbmih->biClrUsed = 0;
  2027. pbmih->biClrImportant = 0;
  2028. //
  2029. // Fill in the palette, if any.
  2030. //
  2031. // !!! Palette or bitfields must come from
  2032. // driver. We can't assume gray scale
  2033. //
  2034. if (lColorMapSize) {
  2035. PBYTE pPal = (PBYTE)pbmih + sizeof(BITMAPINFOHEADER);
  2036. for (INT i = 0; i < lColorMapSize; i++) {
  2037. if (pmdtc->lDepth == 1) {
  2038. memset(pPal, (i * 0xFF), 3);
  2039. }
  2040. else if (pmdtc->lDepth == 4) {
  2041. memset(pPal, (i * 0x3F), 3);
  2042. }
  2043. else if (pmdtc->lDepth == 8) {
  2044. memset(pPal, i, 3);
  2045. }
  2046. pPal += 3;
  2047. *pPal++ = 0;
  2048. }
  2049. pbmih->biClrUsed = lColorMapSize;
  2050. }
  2051. return S_OK;
  2052. }
  2053. /**************************************************************************\
  2054. * GetDIBImageInfo
  2055. *
  2056. * Calc size of DIB header and file, if adequate header is provided then
  2057. * fill it out
  2058. *
  2059. * Arguments:
  2060. *
  2061. * pmdtc - Pointer to mini driver transfer context.
  2062. *
  2063. * Return Value:
  2064. *
  2065. * Status
  2066. *
  2067. * History:
  2068. *
  2069. * 4/5/1999 Original Version
  2070. *
  2071. \**************************************************************************/
  2072. HRESULT GetDIBImageInfo(PMINIDRV_TRANSFER_CONTEXT pmdtc)
  2073. {
  2074. DBG_FN(::GetDIBImageInfo);
  2075. //
  2076. // Map WIA compression to bitmap info compression.
  2077. //
  2078. LONG biCompression;
  2079. switch (pmdtc->lCompression) {
  2080. case WIA_COMPRESSION_NONE:
  2081. biCompression = BI_RGB;
  2082. break;
  2083. case WIA_COMPRESSION_BI_RLE4:
  2084. biCompression = BI_RLE4;
  2085. break;
  2086. case WIA_COMPRESSION_BI_RLE8:
  2087. biCompression = BI_RLE8;
  2088. break;
  2089. default:
  2090. DBG_ERR(("GetDIBImageInfo, unsupported compression type: 0x%08X", pmdtc->lCompression));
  2091. return E_INVALIDARG;
  2092. }
  2093. //
  2094. // find out bitmapinfoheader size
  2095. //
  2096. LONG lColorMapSize;
  2097. LONG lHeaderSize;
  2098. HRESULT hr = DetermineBMISize(sizeof(BITMAPINFOHEADER),
  2099. pmdtc->lDepth,
  2100. biCompression,
  2101. &lHeaderSize,
  2102. &lColorMapSize);
  2103. if (hr != S_OK) {
  2104. DBG_ERR(("GetDIBImageInfo, DetermineBMISize calc size error"));
  2105. return hr;
  2106. }
  2107. //
  2108. // if this is a file, add file header to size
  2109. //
  2110. if (IsEqualGUID(pmdtc->guidFormatID, WiaImgFmt_BMP)) {
  2111. lHeaderSize += sizeof(BITMAPFILEHEADER);
  2112. }
  2113. //
  2114. // Calculate number of bytes per line, width must be
  2115. // aligned to 4 byte boundary.
  2116. //
  2117. pmdtc->cbWidthInBytes = (pmdtc->lWidthInPixels * pmdtc->lDepth) + 31;
  2118. pmdtc->cbWidthInBytes = (pmdtc->cbWidthInBytes / 8) & 0xfffffffc;
  2119. //
  2120. // Always fill in mini driver context with image size information.
  2121. //
  2122. pmdtc->lImageSize = pmdtc->cbWidthInBytes * pmdtc->lLines;
  2123. pmdtc->lHeaderSize = lHeaderSize;
  2124. //
  2125. // With compression, image size is unknown.
  2126. //
  2127. if (pmdtc->lCompression != WIA_COMPRESSION_NONE) {
  2128. pmdtc->lItemSize = 0;
  2129. }
  2130. else {
  2131. pmdtc->lItemSize = pmdtc->lImageSize + lHeaderSize;
  2132. }
  2133. //
  2134. // If the buffer is null, then just return sizes.
  2135. //
  2136. if (pmdtc->pTransferBuffer == NULL) {
  2137. return S_OK;
  2138. }
  2139. else {
  2140. //
  2141. // make sure passed in header buffer is large enough
  2142. //
  2143. if (pmdtc->lBufferSize < lHeaderSize) {
  2144. DBG_ERR(("GetDIBImageInfo, buffer won't hold header, need: %d", lHeaderSize));
  2145. return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
  2146. }
  2147. //
  2148. // Fill in the header
  2149. //
  2150. return WriteDibHeader(lColorMapSize, pmdtc);
  2151. }
  2152. }
  2153. /**************************************************************************\
  2154. * GetJPEGImageInfo
  2155. *
  2156. * Calc size of JPEG header and file, if adequate header is provided then
  2157. * fill it out
  2158. *
  2159. * Arguments:
  2160. *
  2161. * pmdtc - Pointer to mini driver transfer context.
  2162. *
  2163. * Return Value:
  2164. *
  2165. * Status
  2166. *
  2167. * History:
  2168. *
  2169. * 4/5/1999 Original Version
  2170. *
  2171. \**************************************************************************/
  2172. HRESULT GetJPEGImageInfo(PMINIDRV_TRANSFER_CONTEXT pmdtc)
  2173. {
  2174. DBG_FN(::GetJPEGImageInfo);
  2175. //
  2176. // width in bytes is not defined
  2177. //
  2178. pmdtc->cbWidthInBytes = 0;
  2179. //
  2180. // JPEG requires no separate header
  2181. //
  2182. pmdtc->lHeaderSize = 0;
  2183. //
  2184. // lItemSize comes from the WIA_IPA_ITEM_SIZE property
  2185. // which is set/validated by the mini driver. Since there
  2186. // is no separate header for JPEG it is the total transfer size.
  2187. //
  2188. pmdtc->lImageSize = pmdtc->lItemSize;
  2189. return S_OK;
  2190. }
  2191. /**************************************************************************\
  2192. * wiasGetImageInformation
  2193. *
  2194. * Calulate full file size, header size, or fill in header
  2195. *
  2196. * Arguments:
  2197. *
  2198. * pWiasContext - WIA item pointer.
  2199. * lFlags - Operation flags.
  2200. * pmdtc - Pointer to mini driver transfer context.
  2201. *
  2202. * Return Value:
  2203. *
  2204. * Status
  2205. *
  2206. * History:
  2207. *
  2208. * 11/6/1998 Original Version
  2209. *
  2210. \**************************************************************************/
  2211. HRESULT _stdcall wiasGetImageInformation(
  2212. BYTE *pWiasContext,
  2213. LONG lFlags,
  2214. PMINIDRV_TRANSFER_CONTEXT pmdtc)
  2215. {
  2216. DBG_FN(::wiasGetImageInformation);
  2217. IWiaItem *pItem = (IWiaItem*) pWiasContext;
  2218. HRESULT hr = ValidateWiaItem(pItem);
  2219. if (FAILED(hr)) {
  2220. DBG_ERR(("wiasGetImageInformation, invalid pItem"));
  2221. return hr;
  2222. }
  2223. if (IsBadWritePtr(pmdtc, sizeof(MINIDRV_TRANSFER_CONTEXT))) {
  2224. DBG_ERR(("wiasGetImageInformation, bad input parameters, pmdtc"));
  2225. return E_INVALIDARG;
  2226. }
  2227. //
  2228. // Init the mini driver context from item properties if requested.
  2229. //
  2230. if (lFlags == WIAS_INIT_CONTEXT) {
  2231. hr = InitMiniDrvContext(pItem, pmdtc);
  2232. if (FAILED(hr)) {
  2233. return hr;
  2234. }
  2235. }
  2236. if (IsEqualGUID(pmdtc->guidFormatID, WiaImgFmt_BMP) ||
  2237. (IsEqualGUID(pmdtc->guidFormatID, WiaImgFmt_MEMORYBMP))) {
  2238. return GetDIBImageInfo(pmdtc);
  2239. } else if ((IsEqualGUID(pmdtc->guidFormatID, WiaImgFmt_JPEG)) ||
  2240. (IsEqualGUID(pmdtc->guidFormatID, WiaImgFmt_FLASHPIX))) {
  2241. return GetJPEGImageInfo(pmdtc);
  2242. } else if (IsEqualGUID(pmdtc->guidFormatID, WiaImgFmt_TIFF)) {
  2243. //
  2244. // For callback style data transfers, send single page TIFF
  2245. // since we can not rewind the buffer for page offset updates.
  2246. //
  2247. if (pmdtc->bTransferDataCB) {
  2248. return GetTIFFImageInfo(pmdtc);
  2249. }
  2250. else {
  2251. return GetMultiPageTIFFImageInfo(pmdtc);
  2252. }
  2253. } else {
  2254. return S_FALSE;
  2255. }
  2256. }
  2257. /**************************************************************************\
  2258. * CopyItemPropsAndAttribsHelper
  2259. *
  2260. * Helper for wiasCopyItemPropsAndAttribs.
  2261. *
  2262. * Arguments:
  2263. *
  2264. * pItemSrc - WIA item source.
  2265. * pItemDst - WIA item destination.
  2266. *
  2267. * Return Value:
  2268. *
  2269. * Status
  2270. *
  2271. * History:
  2272. *
  2273. * 10/2/1998 Original Version
  2274. *
  2275. \**************************************************************************/
  2276. HRESULT _stdcall CopyItemPropsAndAttribsHelper(
  2277. IPropertyStorage *pIPropStgSrc,
  2278. IPropertyStorage *pIPropStgDst,
  2279. PROPSPEC *pps,
  2280. LPSTR pszErr)
  2281. {
  2282. DBG_FN(::CopyItemPropsAndAttribsHelper);
  2283. PROPVARIANT pv[1];
  2284. HRESULT hr = pIPropStgSrc->ReadMultiple(1, pps, pv);
  2285. if (SUCCEEDED(hr)) {
  2286. hr = pIPropStgDst->WriteMultiple(1, pps, pv, WIA_DIP_FIRST);
  2287. if (FAILED(hr)) {
  2288. ReportReadWriteMultipleError(hr,
  2289. "CopyItemPropsAndAttribsHelper",
  2290. pszErr,
  2291. FALSE,
  2292. 1,
  2293. pps);
  2294. }
  2295. PropVariantClear(pv);
  2296. }
  2297. else {
  2298. ReportReadWriteMultipleError(hr,
  2299. "wiasCopyItemPropsAndAttribs",
  2300. pszErr,
  2301. TRUE,
  2302. 1,
  2303. pps);
  2304. }
  2305. return hr;
  2306. }
  2307. /**************************************************************************\
  2308. * ValidateListProp
  2309. *
  2310. * Validates a List property. This is a helper function for
  2311. * wiasValidateItemProperties. A data type that is not supported
  2312. * is skipped and S_OK is returned;
  2313. *
  2314. * Arguments:
  2315. *
  2316. * cur - current property value
  2317. * valid - valid values
  2318. *
  2319. * Return Value:
  2320. *
  2321. * Status
  2322. *
  2323. * History:
  2324. *
  2325. * 20/4/1998 Original Version
  2326. *
  2327. \**************************************************************************/
  2328. //
  2329. // Macro used for error output
  2330. //
  2331. #define REP_LIST_ERROR(x, name) { \
  2332. DBG_WRN(("wiasValidateItemProperties, invalid LIST value for : ")); \
  2333. if (pPropSpec->ulKind == PRSPEC_LPWSTR) { \
  2334. DBG_WRN((" (Name) %S, value = %d", pPropSpec->lpwstr, cur->x));\
  2335. } else { \
  2336. DBG_WRN((" (propID) %S, value = %d", \
  2337. GetNameFromWiaPropId(pPropSpec->propid), \
  2338. cur->x)); \
  2339. }; \
  2340. DBG_WRN(("Valid values are:")); \
  2341. for (ULONG j = 0; j < WIA_PROP_LIST_COUNT(valid); j++) { \
  2342. DBG_WRN((" %d", valid->name.pElems[WIA_LIST_VALUES + j])); \
  2343. }; \
  2344. };
  2345. //
  2346. // Macro used to check that an element is in the list. Only used for
  2347. // lists of numbers.
  2348. //
  2349. #define LIST_CHECK(value, name) { \
  2350. for (ULONG i = 0; i < WIA_PROP_LIST_COUNT(valid); i++) {\
  2351. if (cur->value == valid->name.pElems[WIA_LIST_VALUES + i]) { \
  2352. return S_OK; \
  2353. }; \
  2354. }; \
  2355. REP_LIST_ERROR(value, name); \
  2356. return E_INVALIDARG; \
  2357. };
  2358. HRESULT ValidateListProp(
  2359. PROPVARIANT *cur,
  2360. PROPVARIANT *valid,
  2361. PROPSPEC *pPropSpec)
  2362. {
  2363. DBG_FN(::ValidateListProp);
  2364. ULONG ulType;
  2365. ulType = cur->vt & ~((ULONG) VT_VECTOR);
  2366. switch (ulType) {
  2367. case (VT_UI1):
  2368. LIST_CHECK(bVal, caub);
  2369. break;
  2370. case (VT_UI2):
  2371. LIST_CHECK(iVal, cai);
  2372. break;
  2373. case (VT_I4):
  2374. LIST_CHECK(lVal, cal);
  2375. break;
  2376. case (VT_UI4):
  2377. LIST_CHECK(ulVal, caul);
  2378. break;
  2379. case (VT_R4):
  2380. LIST_CHECK(fltVal, caflt);
  2381. break;
  2382. case (VT_R8):
  2383. LIST_CHECK(dblVal, cadbl);
  2384. break;
  2385. case (VT_CLSID): {
  2386. for (ULONG i = 0; i < WIA_PROP_LIST_COUNT(valid); i++) {
  2387. if (*cur->puuid == valid->cauuid.pElems[WIA_LIST_VALUES + i]) {
  2388. return S_OK;
  2389. };
  2390. };
  2391. UCHAR *curVal;
  2392. if (UuidToStringA(cur->puuid, &curVal) != RPC_S_OK)
  2393. {
  2394. DBG_WRN(("wiasValidateItemProperties, Out of memory"));
  2395. return E_OUTOFMEMORY;
  2396. };
  2397. DBG_WRN(("wiasValidateItemProperties, invalid LIST value for : "));
  2398. if (pPropSpec->ulKind == PRSPEC_LPWSTR) {
  2399. DBG_WRN((" (Name) %d, value = %s", pPropSpec->lpwstr, curVal));
  2400. } else {
  2401. DBG_WRN((" (propID) %S, value = %s",
  2402. GetNameFromWiaPropId(pPropSpec->propid),
  2403. curVal));
  2404. };
  2405. RpcStringFreeA(&curVal);
  2406. DBG_WRN(("Valid values are:"));
  2407. for (ULONG j = 0; j < WIA_PROP_LIST_COUNT(valid); j++) {
  2408. if (UuidToStringA(&valid->cauuid.pElems[WIA_LIST_VALUES + j], &curVal) == RPC_S_OK)
  2409. {
  2410. DBG_WRN((" %s", curVal));
  2411. RpcStringFreeA(&curVal);
  2412. }
  2413. };
  2414. return E_INVALIDARG;
  2415. }
  2416. break;
  2417. case (VT_BSTR): {
  2418. //
  2419. // Loop through elements and compare to current value. Loop
  2420. // counter max is (cElemens - 2) to take into account
  2421. // Nominal and Count values which are skipped.
  2422. //
  2423. if (!cur->bstrVal) {
  2424. return S_OK;
  2425. }
  2426. for (ULONG i = 0; i < WIA_PROP_LIST_COUNT(valid); i++) {
  2427. if (!wcscmp(cur->bstrVal, valid->cabstr.pElems[WIA_LIST_VALUES + i])) {
  2428. return S_OK;
  2429. };
  2430. };
  2431. DBG_WRN(("wiasValidateItemProperties, invalid LIST value for : "));
  2432. if (pPropSpec->ulKind == PRSPEC_LPWSTR) {
  2433. DBG_WRN((" (Name) %S, value = %S",
  2434. pPropSpec->lpwstr,
  2435. cur->bstrVal));
  2436. } else {
  2437. DBG_WRN((" (propID) %S, value = %S",
  2438. GetNameFromWiaPropId(pPropSpec->propid),
  2439. cur->bstrVal));
  2440. };
  2441. DBG_WRN(("Valid values are:"));
  2442. for (ULONG j = 0; j < WIA_PROP_LIST_COUNT(valid); j++) {
  2443. DBG_WRN((" %S", valid->cabstr.pElems[WIA_LIST_VALUES + j]));
  2444. };
  2445. return E_INVALIDARG;
  2446. }
  2447. break;
  2448. default:
  2449. //
  2450. // Type not supported, assume S_OK
  2451. //
  2452. return S_OK;
  2453. }
  2454. return S_OK;
  2455. }
  2456. /**************************************************************************\
  2457. * ValidateRangeProp
  2458. *
  2459. * Validates a Range property. This is a helper function for
  2460. * wiasValidateItemProperties. A data type that is not supported
  2461. * is skipped and S_OK is returned;
  2462. *
  2463. * Arguments:
  2464. *
  2465. * cur - current property value
  2466. * valid - valid values
  2467. *
  2468. * Return Value:
  2469. *
  2470. * Status
  2471. *
  2472. * History:
  2473. *
  2474. * 20/4/1998 Original Version
  2475. *
  2476. \**************************************************************************/
  2477. //
  2478. // Macro used for error output, for integers
  2479. //
  2480. #define REP_RANGE_ERROR(x, name) { \
  2481. DBG_WRN(("wiasValidateItemProperties, invalid RANGE value for : ")); \
  2482. if (pPropSpec->ulKind == PRSPEC_LPWSTR) { \
  2483. DBG_WRN((" (Name) %S, value = %d", pPropSpec->lpwstr, cur->x)); \
  2484. } else { \
  2485. DBG_WRN((" (propID) %S, value = %d", \
  2486. GetNameFromWiaPropId(pPropSpec->propid), \
  2487. cur->x)); \
  2488. }; \
  2489. DBG_WRN(("Valid RANGE is: MIN = %d, MAX = %d, STEP = %d", \
  2490. valid->name.pElems[WIA_RANGE_MIN], \
  2491. valid->name.pElems[WIA_RANGE_MAX], \
  2492. valid->name.pElems[WIA_RANGE_STEP])); \
  2493. return E_INVALIDARG; \
  2494. };
  2495. //
  2496. // Macro used for error output, for reals
  2497. //
  2498. #define REP_REAL_RANGE_ERROR(x, name) { \
  2499. DBG_WRN(("wiasValidateItemProperties, invalid RANGE value for : ")); \
  2500. if (pPropSpec->ulKind == PRSPEC_LPWSTR) { \
  2501. DBG_WRN((" (Name) %S, value = %2.3f", pPropSpec->lpwstr, cur->x));\
  2502. } else { \
  2503. DBG_WRN((" (propID) %S, value = %2.3f", \
  2504. GetNameFromWiaPropId(pPropSpec->propid), \
  2505. cur->x)); \
  2506. }; \
  2507. DBG_WRN(("Valid RANGE is: MIN = %2.3f, MAX = %2.3f, STEP = %2.3f", \
  2508. valid->name.pElems[WIA_RANGE_MIN], \
  2509. valid->name.pElems[WIA_RANGE_MAX], \
  2510. valid->name.pElems[WIA_RANGE_STEP])); \
  2511. return E_INVALIDARG; \
  2512. };
  2513. //
  2514. // Macro used to check that x is within the range and matches the correct step
  2515. // (only used for integer ranges)
  2516. //
  2517. #define RANGE_CHECK(x, name) { \
  2518. if (valid->name.pElems[WIA_RANGE_STEP] == 0) \
  2519. { \
  2520. REP_RANGE_ERROR(x, name); \
  2521. } \
  2522. if ((cur->x < valid->name.pElems[WIA_RANGE_MIN]) || \
  2523. (cur->x > valid->name.pElems[WIA_RANGE_MAX]) || \
  2524. ((cur->x - valid->name.pElems[WIA_RANGE_MIN]) % \
  2525. valid->name.pElems[WIA_RANGE_STEP])) { \
  2526. REP_RANGE_ERROR(x, name); \
  2527. }; \
  2528. };
  2529. HRESULT ValidateRangeProp(
  2530. PROPVARIANT *cur,
  2531. PROPVARIANT *valid,
  2532. PROPSPEC *pPropSpec)
  2533. {
  2534. DBG_FN(::ValidateRangeProp);
  2535. LONG ulType;
  2536. //
  2537. // Decide what to do based on type of data
  2538. //
  2539. ulType = cur->vt & ~((ULONG) VT_VECTOR);
  2540. switch (ulType) {
  2541. case (VT_UI1):
  2542. RANGE_CHECK(bVal, caub);
  2543. break;
  2544. case (VT_UI2):
  2545. RANGE_CHECK(uiVal, caui);
  2546. break;
  2547. case (VT_UI4):
  2548. RANGE_CHECK(ulVal, caul);
  2549. break;
  2550. case (VT_I2):
  2551. RANGE_CHECK(iVal, cai);
  2552. break;
  2553. case (VT_I4):
  2554. RANGE_CHECK(lVal, cal);
  2555. break;
  2556. case (VT_R4):
  2557. if ((cur->fltVal < valid->caflt.pElems[WIA_RANGE_MIN]) ||
  2558. (cur->fltVal > valid->caflt.pElems[WIA_RANGE_MAX])) {
  2559. REP_REAL_RANGE_ERROR(fltVal, caflt);
  2560. }
  2561. break;
  2562. case (VT_R8):
  2563. if ((cur->dblVal < valid->cadbl.pElems[WIA_RANGE_MIN]) ||
  2564. (cur->dblVal > valid->cadbl.pElems[WIA_RANGE_MAX])) {
  2565. REP_REAL_RANGE_ERROR(dblVal, cadbl);
  2566. }
  2567. break;
  2568. default:
  2569. //
  2570. // Type not supported, assume S_OK
  2571. //
  2572. return S_OK;
  2573. }
  2574. return S_OK;
  2575. }
  2576. /**************************************************************************\
  2577. * wiasValidateItemProperties
  2578. *
  2579. * Validates a list of properties against their valid values for a given
  2580. * item.
  2581. * NOTE: Validation can only be done on Read/Write properties of type
  2582. * WIA_PROP_FLAG, WIA_PROP_RANGE and WIA_PROP_LIST. Any other
  2583. * type will simply be skipped over.
  2584. *
  2585. * Arguments:
  2586. *
  2587. * pWiasContext - Wia item
  2588. * nPropSpec - number of properties
  2589. * pPropSpec - array of PROPSPEC indicating which properties are to be
  2590. * validated.
  2591. *
  2592. * Return Value:
  2593. *
  2594. * Status
  2595. *
  2596. * History:
  2597. *
  2598. * 20/4/1998 Original Version
  2599. *
  2600. \**************************************************************************/
  2601. //
  2602. // Macro for error output
  2603. //
  2604. #if defined(_DEBUG) || defined(DBG) || defined(WIA_DEBUG)
  2605. #define REP_ERR(text, i) { \
  2606. DBG_WRN((text)); \
  2607. if (pPropSpec[i].ulKind == PRSPEC_LPWSTR) { \
  2608. DBG_WRN((" (Name) %S, value = %d", \
  2609. pPropSpec[i].lpwstr, \
  2610. curVal.ulVal)); \
  2611. } else { \
  2612. DBG_WRN((" (propID) %S, value = %d", \
  2613. GetNameFromWiaPropId(pPropSpec[i].propid), \
  2614. curVal.ulVal)); \
  2615. }; \
  2616. };
  2617. #else
  2618. #define REP_ERR(text, i)
  2619. #endif
  2620. HRESULT _stdcall wiasValidateItemProperties(
  2621. BYTE *pWiasContext,
  2622. ULONG nPropSpec,
  2623. const PROPSPEC *pPropSpec)
  2624. {
  2625. DBG_FN(::wiasValidateItemProperties);
  2626. IWiaItem *pItem = (IWiaItem*) pWiasContext;
  2627. PROPVARIANT curVal, validVal;
  2628. ULONG lAccess;
  2629. HRESULT hr;
  2630. //
  2631. // May be called by driver or application, do parameter validation.
  2632. //
  2633. hr = ValidateWiaItem(pItem);
  2634. if (FAILED(hr)) {
  2635. DBG_ERR(("wiasValidateItemProperties, invalid pItem"));
  2636. return hr;
  2637. }
  2638. if (IsBadReadPtr(pPropSpec, sizeof(PROPSPEC) * nPropSpec)) {
  2639. DBG_ERR(("wiasValidateItemProperties, bad pPropSpec parameter"));
  2640. return E_POINTER;
  2641. }
  2642. //
  2643. // Get the Item's property streams
  2644. //
  2645. IPropertyStorage *pIProp;
  2646. IPropertyStorage *pIPropAccessStgDst;
  2647. IPropertyStorage *pIPropValidStgDst;
  2648. hr = ((CWiaItem*)pItem)->GetItemPropStreams(&pIProp,
  2649. &pIPropAccessStgDst,
  2650. &pIPropValidStgDst,
  2651. NULL);
  2652. if (FAILED(hr)) {
  2653. DBG_WRN(("wiasValidateItemProperties, GetItemPropStreams failed"));
  2654. return E_FAIL;
  2655. }
  2656. //
  2657. // Loop through properties
  2658. //
  2659. for (ULONG i = 0; i < nPropSpec; i++) {
  2660. //
  2661. // Get the access flag and valid values for the property
  2662. //
  2663. lAccess = 0;
  2664. hr = wiasGetPropertyAttributes((BYTE*)pItem,
  2665. 1,
  2666. (PROPSPEC*) &pPropSpec[i],
  2667. &lAccess,
  2668. &validVal);
  2669. if (hr != S_OK) {
  2670. return hr;
  2671. }
  2672. //
  2673. // If the access flag is not RW or one of the three supported types
  2674. // (FLAG, RANGE, LIST) then skip it
  2675. //
  2676. if (!(lAccess & WIA_PROP_RW)) {
  2677. ULONG ulType;
  2678. ulType = lAccess & ~((ULONG)WIA_PROP_RW);
  2679. if ((ulType != WIA_PROP_FLAG) &&
  2680. (ulType != WIA_PROP_RANGE) &&
  2681. (ulType != WIA_PROP_LIST)) {
  2682. PropVariantClear(&validVal);
  2683. continue;
  2684. }
  2685. }
  2686. //
  2687. // Get the current value
  2688. //
  2689. hr = pIProp->ReadMultiple(1, (PROPSPEC*) &pPropSpec[i], &curVal);
  2690. if (hr != S_OK) {
  2691. ReportReadWriteMultipleError(hr, "wiasValidateItemProperties", NULL,
  2692. TRUE, 1, &pPropSpec[i]);
  2693. }
  2694. else {
  2695. //
  2696. // Check whether the value is valid
  2697. //
  2698. ULONG BitsToRemove = (ULONG) (WIA_PROP_RW | WIA_PROP_CACHEABLE);
  2699. switch (lAccess & ~BitsToRemove) {
  2700. case (WIA_PROP_FLAG):
  2701. //
  2702. // Check that current bits are valid.
  2703. //
  2704. if (curVal.ulVal & ~(ULONG) validVal.caul.pElems[WIA_FLAG_VALUES]) {
  2705. DBG_WRN(("wiasValidateItemProperties, invalid value for FLAG :", i));
  2706. DBG_WRN(("Valid mask is: %d", validVal.caul.pElems[WIA_FLAG_VALUES]));
  2707. hr = E_INVALIDARG;
  2708. };
  2709. break;
  2710. case (WIA_PROP_RANGE):
  2711. hr = ValidateRangeProp(&curVal, &validVal, (PROPSPEC*)&pPropSpec[i]);
  2712. break;
  2713. case (WIA_PROP_LIST):
  2714. hr = ValidateListProp(&curVal, &validVal, (PROPSPEC*)&pPropSpec[i]);
  2715. break;
  2716. default:
  2717. hr = S_OK;
  2718. }
  2719. }
  2720. PropVariantClear(&validVal);
  2721. PropVariantClear(&curVal);
  2722. if (hr != S_OK) {
  2723. break;
  2724. }
  2725. };
  2726. return hr;
  2727. }
  2728. /**************************************************************************\
  2729. * wiasWritePageBufToFile
  2730. *
  2731. * Write from a mini driver allocated temporary page buffer
  2732. * to the image file. This is specifically used by drivers to write a
  2733. * page to a multi-page TIFF file. Therefore this function treats
  2734. * WiaImgFmt_TIFF formats as a special case, since it will update
  2735. * the IFD entries correctly. With all other formats, the buffer is
  2736. * simply written to the file as-is.
  2737. *
  2738. * Arguments:
  2739. *
  2740. * pmdtc - Pointer to mini driver transfer context.
  2741. *
  2742. * Return Value:
  2743. *
  2744. * Status
  2745. *
  2746. * History:
  2747. *
  2748. * 11/6/1998 Original Version
  2749. *
  2750. \**************************************************************************/
  2751. HRESULT _stdcall wiasWritePageBufToFile(PMINIDRV_TRANSFER_CONTEXT pmdtc)
  2752. {
  2753. DBG_FN(::wiasWritePageBufToFile);
  2754. HRESULT hr = S_OK;
  2755. if (pmdtc == NULL)
  2756. {
  2757. hr = E_POINTER;
  2758. DBG_ERR(("wiasWritePageBufToFile, received NULL pmdtc pointer, 0x%08x", hr));
  2759. return hr;
  2760. }
  2761. //
  2762. // Multipage TIFF requires special handling since the TIFF
  2763. // header must be updated for each page added.
  2764. //
  2765. if (IsEqualGUID(pmdtc->guidFormatID, WiaImgFmt_TIFF)) {
  2766. hr = WritePageToMultiPageTiff(pmdtc);
  2767. }
  2768. else {
  2769. ULONG ulWritten;
  2770. BOOL bRet;
  2771. if (pmdtc->lItemSize <= pmdtc->lBufferSize) {
  2772. bRet = WriteFile((HANDLE)pmdtc->hFile,
  2773. pmdtc->pTransferBuffer,
  2774. pmdtc->lItemSize,
  2775. &ulWritten,
  2776. NULL);
  2777. if (!bRet) {
  2778. hr = HRESULT_FROM_WIN32(::GetLastError());
  2779. DBG_ERR(("wiasWritePageBufToFile, WriteFile failed (0x%X)", hr));
  2780. }
  2781. }
  2782. else {
  2783. DBG_ERR(("wiasWritePageBufToFile, lItemSize is larger than buffer"));
  2784. hr = E_FAIL;
  2785. }
  2786. }
  2787. return hr;
  2788. }
  2789. /**************************************************************************\
  2790. * wiasWriteBufToFile
  2791. *
  2792. * Write from a specified buffer to the image file.
  2793. *
  2794. * Arguments:
  2795. *
  2796. * lFlags - Operation flags. Should be 0.
  2797. * pmdtc - Pointer to mini driver transfer context.
  2798. *
  2799. * Return Value:
  2800. *
  2801. * Status
  2802. *
  2803. * History:
  2804. *
  2805. * 11/6/1998 Original Version
  2806. *
  2807. \**************************************************************************/
  2808. HRESULT _stdcall wiasWriteBufToFile(
  2809. LONG lFlags,
  2810. PMINIDRV_TRANSFER_CONTEXT pmdtc)
  2811. {
  2812. DBG_FN(::wiasWritePageBufToFile);
  2813. HRESULT hr = S_OK;
  2814. ULONG ulWritten;
  2815. BOOL bRet;
  2816. if (pmdtc == NULL)
  2817. {
  2818. hr = E_POINTER;
  2819. DBG_ERR(("wiasWriteBufToFile, received NULL pmdtc pointer, 0x%08x", hr));
  2820. return hr;
  2821. }
  2822. if (pmdtc->lItemSize <= pmdtc->lBufferSize) {
  2823. bRet = WriteFile((HANDLE)pmdtc->hFile,
  2824. pmdtc->pTransferBuffer,
  2825. pmdtc->lItemSize,
  2826. &ulWritten,
  2827. NULL);
  2828. if (!bRet) {
  2829. hr = HRESULT_FROM_WIN32(::GetLastError());
  2830. DBG_ERR(("wiasWritePageBufToFile, WriteFile failed (0x%X)", hr));
  2831. }
  2832. }
  2833. else {
  2834. DBG_ERR(("wiasWritePageBufToFile, lItemSize is larger than buffer"));
  2835. hr = E_FAIL;
  2836. }
  2837. return hr;
  2838. }
  2839. /**************************************************************************\
  2840. * wiasSendEndOfPage
  2841. *
  2842. * Call client with total page count.
  2843. *
  2844. * Arguments:
  2845. *
  2846. * pWiasContext - WIA item pointer.
  2847. * lPageCount - Zero based count of total pages.
  2848. * pmdtc - Pointer to mini driver transfer context.
  2849. *
  2850. * Return Value:
  2851. *
  2852. * Status
  2853. *
  2854. * History:
  2855. *
  2856. * 11/6/1998 Original Version
  2857. *
  2858. \**************************************************************************/
  2859. HRESULT _stdcall wiasSendEndOfPage(
  2860. BYTE *pWiasContext,
  2861. LONG lPageCount,
  2862. PMINIDRV_TRANSFER_CONTEXT pmdtc)
  2863. {
  2864. DBG_FN(::wiasSendEndOfPage);
  2865. IWiaItem *pItem = (IWiaItem*) pWiasContext;
  2866. HRESULT hr = ValidateWiaItem(pItem);
  2867. if (FAILED(hr)) {
  2868. DBG_ERR(("wiasSendEndOfPage, invalid pItem"));
  2869. return hr;
  2870. }
  2871. if (IsBadWritePtr(pmdtc, sizeof(MINIDRV_TRANSFER_CONTEXT))) {
  2872. DBG_ERR(("wiasSendEndOfPage, bad input parameters, pmdtc"));
  2873. return E_INVALIDARG;
  2874. }
  2875. return ((CWiaItem*)pItem)->SendEndOfPage(lPageCount, pmdtc);
  2876. }
  2877. /**************************************************************************\
  2878. * wiasGetItemType
  2879. *
  2880. * Returns the item type.
  2881. *
  2882. * Arguments:
  2883. *
  2884. * pWiasContext - Pointer to Wia item
  2885. * plType - Address of LONG to receive Item Type value.
  2886. *
  2887. * Return Value:
  2888. *
  2889. * Status
  2890. *
  2891. * History:
  2892. *
  2893. * 5/07/1999 Original Version
  2894. *
  2895. \**************************************************************************/
  2896. HRESULT _stdcall wiasGetItemType(
  2897. BYTE *pWiasContext,
  2898. LONG *plType)
  2899. {
  2900. DBG_FN(::wiasGetItemType);
  2901. IWiaItem *pItem = (IWiaItem*) pWiasContext;
  2902. HRESULT hr = ValidateWiaItem(pItem);
  2903. if (FAILED(hr)) {
  2904. DBG_ERR(("wiasGetItemType, invalid pItem"));
  2905. return hr;
  2906. }
  2907. if (plType) {
  2908. return pItem->GetItemType(plType);
  2909. } else {
  2910. DBG_ERR(("wiasGetItemType, invalid ppIWiaDrvItem"));
  2911. return E_POINTER;
  2912. }
  2913. }
  2914. /**************************************************************************\
  2915. * wiasGetDrvItem
  2916. *
  2917. * Returns the WIA item's corresponding driver item.
  2918. *
  2919. * Arguments:
  2920. *
  2921. * pWiasContext - Pointer to Wia item
  2922. * ppIWiaDrvItem - Address which receives pointer to the Driver Item.
  2923. *
  2924. * Return Value:
  2925. *
  2926. * Status
  2927. *
  2928. * History:
  2929. *
  2930. * 5/07/1999 Original Version
  2931. *
  2932. \**************************************************************************/
  2933. HRESULT _stdcall wiasGetDrvItem(
  2934. BYTE *pWiasContext,
  2935. IWiaDrvItem **ppIWiaDrvItem)
  2936. {
  2937. DBG_FN(::wiasGetDrvItem);
  2938. IWiaItem *pItem = (IWiaItem*) pWiasContext;
  2939. IWiaDrvItem *pIWiaDrvItem;
  2940. HRESULT hr = ValidateWiaItem(pItem);
  2941. if (FAILED(hr)) {
  2942. DBG_ERR(("wiasGetDrvItem, invalid pItem"));
  2943. return hr;
  2944. }
  2945. if (!ppIWiaDrvItem) {
  2946. DBG_ERR(("wiasGetDrvItem, invalid ppIWiaDrvItem"));
  2947. return E_POINTER;
  2948. }
  2949. pIWiaDrvItem = ((CWiaItem*)pItem)->GetDrvItemPtr();
  2950. if (pIWiaDrvItem) {
  2951. *ppIWiaDrvItem = pIWiaDrvItem;
  2952. } else {
  2953. DBG_ERR(("wiasGetDrvItem, Driver Item is NULL"));
  2954. hr = E_FAIL;
  2955. }
  2956. return hr;
  2957. }
  2958. /**************************************************************************\
  2959. * wiasGetRootItem
  2960. *
  2961. * Returns the WIA item's corresponding root item item.
  2962. *
  2963. * Arguments:
  2964. *
  2965. * pWiasContext - Wia item
  2966. * ppIWiaItem - Address which receives pointer to the root Item.
  2967. *
  2968. * Return Value:
  2969. *
  2970. * Status
  2971. *
  2972. * History:
  2973. *
  2974. * 5/07/1999 Original Version
  2975. *
  2976. \**************************************************************************/
  2977. HRESULT _stdcall wiasGetRootItem(
  2978. BYTE *pWiasContext,
  2979. BYTE **ppWiasContext)
  2980. {
  2981. DBG_FN(::wiasGetRootItem);
  2982. IWiaItem *pItem = (IWiaItem*) pWiasContext;
  2983. HRESULT hr = ValidateWiaItem(pItem);
  2984. if (FAILED(hr)) {
  2985. DBG_ERR(("wiasGetRootItem, invalid pItem"));
  2986. return hr;
  2987. }
  2988. if (ppWiasContext) {
  2989. hr = pItem->GetRootItem((IWiaItem**)ppWiasContext);
  2990. ((IWiaItem*)(*ppWiasContext))->Release();
  2991. return hr;
  2992. } else {
  2993. DBG_ERR(("wiasGetRootItem, invalid ppIWiaItem"));
  2994. return E_POINTER;
  2995. }
  2996. }
  2997. /**************************************************************************\
  2998. * SetValidValueHelper
  2999. *
  3000. * Helper to write the valid values for a property. It first does a check
  3001. * that the property is of the specified type.
  3002. *
  3003. * Arguments:
  3004. *
  3005. * pWiasContext - Wia item
  3006. * ulType - specifies type (WIA_PROP_FLAG, WIA_PROP_LIST,
  3007. * WIA_PROP_RANGE)
  3008. * ps - Identifies the property
  3009. * pv - The new valid value
  3010. *
  3011. * Return Value:
  3012. *
  3013. * Status
  3014. *
  3015. * History:
  3016. *
  3017. * 07/21/1999 Original Version
  3018. *
  3019. \**************************************************************************/
  3020. HRESULT _stdcall SetValidValueHelper(
  3021. BYTE *pWiasContext,
  3022. ULONG ulType,
  3023. PROPSPEC *ps,
  3024. PROPVARIANT *pv)
  3025. {
  3026. DBG_FN(::SetValidValueHelper);
  3027. HRESULT hr;
  3028. PROPVARIANT pvAccess[1];
  3029. //
  3030. // Get the access flag and valid value storage. Check that the property
  3031. // is a WIA_PROP_RANGE, and write the new values if it is.
  3032. //
  3033. IPropertyStorage *pIPropAccessStg;
  3034. IPropertyStorage *pIPropValidStg;
  3035. hr = ((CWiaItem*)pWiasContext)->GetItemPropStreams(NULL,
  3036. &pIPropAccessStg,
  3037. &pIPropValidStg,
  3038. NULL);
  3039. if (SUCCEEDED(hr)) {
  3040. hr = pIPropAccessStg->ReadMultiple(1, ps, pvAccess);
  3041. if (SUCCEEDED(hr)) {
  3042. if (pvAccess[0].ulVal & ulType) {
  3043. hr = pIPropValidStg->WriteMultiple(1, ps, pv, WIA_DIP_FIRST);
  3044. if (FAILED(hr)) {
  3045. DBG_ERR(("SetValidValueHelper, Error writing (Property %S)",
  3046. GetNameFromWiaPropId(ps[0].propid)));
  3047. }
  3048. } else {
  3049. DBG_ERR(("SetValidValueHelper, (PropID %S) is not of the correct type",
  3050. GetNameFromWiaPropId(ps[0].propid)));
  3051. DBG_ERR(("Expected type %d but got type %d",
  3052. ulType,
  3053. pvAccess[0].ulVal));
  3054. hr = E_INVALIDARG;
  3055. }
  3056. } else {
  3057. DBG_ERR(("SetValidValueHelper, Could not get access flags (0x%X)", hr));
  3058. }
  3059. } else {
  3060. DBG_ERR(("SetValidValueHelper, GetItemPropStreams failed (0x%X)", hr));
  3061. }
  3062. return hr;
  3063. }
  3064. /**************************************************************************\
  3065. * wiasSetValidFlag
  3066. *
  3067. * Sets the valid values for a WIA_PROP_FLAG property. This function
  3068. * assumes the flag type to be VT_UI4.
  3069. *
  3070. * Arguments:
  3071. *
  3072. * pWiasContext - Wia item
  3073. * propid - Identifies the property
  3074. * ulNom - The flag's nominal value
  3075. * ulValidBits - The flag's valid bits
  3076. *
  3077. * Return Value:
  3078. *
  3079. * Status
  3080. *
  3081. * History:
  3082. *
  3083. * 07/21/1999 Original Version
  3084. *
  3085. \**************************************************************************/
  3086. HRESULT _stdcall wiasSetValidFlag(
  3087. BYTE* pWiasContext,
  3088. PROPID propid,
  3089. ULONG ulNom,
  3090. ULONG ulValidBits)
  3091. {
  3092. DBG_FN(::wiasSetValidFlag);
  3093. HRESULT hr;
  3094. PROPVARIANT pv[1];
  3095. PROPSPEC ps[1];
  3096. ULONG *pFlags;
  3097. //
  3098. // Validate params
  3099. //
  3100. hr = ValidateWiaItem((IWiaItem*)pWiasContext);
  3101. if (FAILED(hr)) {
  3102. DBG_ERR(("wiasSetValidFlag, invalid pItem (0x%X)", hr));
  3103. return hr;
  3104. }
  3105. pFlags = (ULONG*) CoTaskMemAlloc(sizeof(LONG) * WIA_FLAG_NUM_ELEMS);
  3106. if (!pFlags) {
  3107. DBG_ERR(("wiasSetValidFlag, Out of memory"));
  3108. return E_OUTOFMEMORY;
  3109. }
  3110. //
  3111. // Set up the propvariant
  3112. //
  3113. ps[0].ulKind = PRSPEC_PROPID;
  3114. ps[0].propid = propid;
  3115. pFlags[0] = ulNom;
  3116. pFlags[1] = ulValidBits;
  3117. pv[0].vt = VT_VECTOR | VT_UI4;
  3118. pv[0].caul.cElems = WIA_FLAG_NUM_ELEMS;
  3119. pv[0].caul.pElems = pFlags;
  3120. hr = SetValidValueHelper(pWiasContext, WIA_PROP_FLAG, ps, pv);
  3121. if (FAILED(hr)) {
  3122. DBG_ERR(("wiasSetValidFlag, SetValidValueHelper failed (0x%X)", hr));
  3123. }
  3124. PropVariantClear(pv);
  3125. return hr;
  3126. }
  3127. /**************************************************************************\
  3128. * wiasSetValidRangeLong
  3129. *
  3130. * Sets the valid values for a WIA_PROP_RANGE property. This function
  3131. * assumes the property is of type VT_I4.
  3132. *
  3133. * Arguments:
  3134. *
  3135. * pWiasContext - Wia item
  3136. * propid - Identifies the property
  3137. * lMin - minimum
  3138. * lNom - nominal
  3139. * lMax - maximum
  3140. * lStep - step
  3141. *
  3142. * Return Value:
  3143. *
  3144. * Status
  3145. *
  3146. * History:
  3147. *
  3148. * 07/21/1999 Original Version
  3149. *
  3150. \**************************************************************************/
  3151. HRESULT _stdcall wiasSetValidRangeLong(
  3152. BYTE* pWiasContext,
  3153. PROPID propid,
  3154. LONG lMin,
  3155. LONG lNom,
  3156. LONG lMax,
  3157. LONG lStep)
  3158. {
  3159. DBG_FN(::wiasSetValidRangeLong);
  3160. HRESULT hr;
  3161. PROPVARIANT pv[1];
  3162. PROPSPEC ps[1];
  3163. LONG *pRange;
  3164. //
  3165. // Validate params
  3166. //
  3167. hr = ValidateWiaItem((IWiaItem*)pWiasContext);
  3168. if (FAILED(hr)) {
  3169. DBG_ERR(("wiasSetValidRangeLong, invalid pItem (0x%X)", hr));
  3170. return hr;
  3171. }
  3172. pRange = (LONG*) CoTaskMemAlloc(sizeof(LONG) * WIA_RANGE_NUM_ELEMS);
  3173. if (!pRange) {
  3174. DBG_ERR(("wiasSetValidRangeLong, Out of memory"));
  3175. return E_OUTOFMEMORY;
  3176. }
  3177. //
  3178. // Set up the propvariant
  3179. //
  3180. ps[0].ulKind = PRSPEC_PROPID;
  3181. ps[0].propid = propid;
  3182. pRange[WIA_RANGE_MIN] = lMin;
  3183. pRange[WIA_RANGE_NOM] = lNom;
  3184. pRange[WIA_RANGE_MAX] = lMax;
  3185. pRange[WIA_RANGE_STEP] = lStep;
  3186. pv[0].vt = VT_VECTOR | VT_I4;
  3187. pv[0].cal.cElems = WIA_RANGE_NUM_ELEMS;
  3188. pv[0].cal.pElems = pRange;
  3189. //
  3190. // Call the helper to set the valid value
  3191. //
  3192. hr = SetValidValueHelper(pWiasContext, WIA_PROP_RANGE, ps, pv);
  3193. if (FAILED(hr)) {
  3194. DBG_ERR(("wiasSetValidRangeLong, Helper failed (0x%X)", hr));
  3195. }
  3196. PropVariantClear(pv);
  3197. return hr;
  3198. }
  3199. /**************************************************************************\
  3200. * wiasSetValidRangeFloat
  3201. *
  3202. * Sets the valid values for a WIA_PROP_RANGE property. This function
  3203. * assumes the property is of type VT_R4.
  3204. *
  3205. * Arguments:
  3206. *
  3207. * pWiasContext - Wia item
  3208. * propid - Identifies the property
  3209. * lMin - minimum
  3210. * lNom - nominal
  3211. * lMax - maximum
  3212. * lStep - step
  3213. *
  3214. * Return Value:
  3215. *
  3216. * Status
  3217. *
  3218. * History:
  3219. *
  3220. * 07/21/1999 Original Version
  3221. *
  3222. \**************************************************************************/
  3223. HRESULT _stdcall wiasSetValidRangeFloat(
  3224. BYTE* pWiasContext,
  3225. PROPID propid,
  3226. FLOAT fMin,
  3227. FLOAT fNom,
  3228. FLOAT fMax,
  3229. FLOAT fStep)
  3230. {
  3231. DBG_FN(::wiasSetValidRangeFloat);
  3232. HRESULT hr;
  3233. PROPVARIANT pv[1];
  3234. PROPSPEC ps[1];
  3235. FLOAT *pRange;
  3236. //
  3237. // Validate params
  3238. //
  3239. hr = ValidateWiaItem((IWiaItem*)pWiasContext);
  3240. if (FAILED(hr)) {
  3241. DBG_ERR(("wiasSetValidRangeFloat, invalid pItem (0x%X)", hr));
  3242. return hr;
  3243. }
  3244. pRange = (FLOAT*) CoTaskMemAlloc(sizeof(FLOAT) * WIA_RANGE_NUM_ELEMS);
  3245. if (!pRange) {
  3246. DBG_ERR(("wiasSetValidRangeFloat, Out of memory"));
  3247. return E_OUTOFMEMORY;
  3248. }
  3249. //
  3250. // Set up the propvariant
  3251. //
  3252. ps[0].ulKind = PRSPEC_PROPID;
  3253. ps[0].propid = propid;
  3254. pRange[WIA_RANGE_MIN] = fMin;
  3255. pRange[WIA_RANGE_NOM] = fNom;
  3256. pRange[WIA_RANGE_MAX] = fMax;
  3257. pRange[WIA_RANGE_STEP] = fStep;
  3258. pv[0].vt = VT_VECTOR | VT_R4;
  3259. pv[0].caflt.cElems = WIA_RANGE_NUM_ELEMS;
  3260. pv[0].caflt.pElems = pRange;
  3261. //
  3262. // Call the helper to set the valid value
  3263. //
  3264. hr = SetValidValueHelper(pWiasContext, WIA_PROP_RANGE, ps, pv);
  3265. if (FAILED(hr)) {
  3266. DBG_ERR(("wiasSetValidRangeFloat, Helper failed (0x%X)", hr));
  3267. }
  3268. PropVariantClear(pv);
  3269. return hr;
  3270. }
  3271. /**************************************************************************\
  3272. * wiasSetValidFlag
  3273. *
  3274. * Sets the valid values for a WIA_PROP_LIST property. This function
  3275. * assumes the property is of type VT_I4.
  3276. *
  3277. * Arguments:
  3278. *
  3279. * pWiasContext - Wia item
  3280. * propid - Identifies the property
  3281. * ulCount - the number of elements in the list
  3282. * lNom - the list's nominal value
  3283. * plValues - the array of LONGs that make up the valid list
  3284. *
  3285. * Return Value:
  3286. *
  3287. * Status
  3288. *
  3289. * History:
  3290. *
  3291. * 07/21/1999 Original Version
  3292. *
  3293. \**************************************************************************/
  3294. HRESULT _stdcall wiasSetValidListLong(
  3295. BYTE *pWiasContext,
  3296. PROPID propid,
  3297. ULONG ulCount,
  3298. LONG lNom,
  3299. LONG *plValues)
  3300. {
  3301. DBG_FN(::wiasSetValidListLong);
  3302. HRESULT hr;
  3303. PROPVARIANT pv[1];
  3304. PROPSPEC ps[1];
  3305. LONG *pList;
  3306. ULONG cList;
  3307. //
  3308. // Validate params
  3309. //
  3310. hr = ValidateWiaItem((IWiaItem*)pWiasContext);
  3311. if (FAILED(hr)) {
  3312. DBG_ERR(("wiasSetValidListLong, invalid pItem (0x%X)", hr));
  3313. return hr;
  3314. }
  3315. if (IsBadReadPtr(plValues, sizeof(LONG) * ulCount)) {
  3316. DBG_ERR(("wiasSetValidListLong, plValues is an invalid pointer (0x%X)", hr));
  3317. return E_POINTER;
  3318. }
  3319. cList = WIA_LIST_NUM_ELEMS + ulCount;
  3320. pList = (LONG*) CoTaskMemAlloc(sizeof(LONG) * cList);
  3321. if (!pList) {
  3322. DBG_ERR(("wiasSetValidListLong, Out of memory"));
  3323. return E_OUTOFMEMORY;
  3324. }
  3325. //
  3326. // Set up the propvariant
  3327. //
  3328. ps[0].ulKind = PRSPEC_PROPID;
  3329. ps[0].propid = propid;
  3330. pList[WIA_LIST_COUNT] = (LONG) ulCount;
  3331. pList[WIA_LIST_NOM] = lNom;
  3332. memcpy(&pList[WIA_LIST_VALUES], plValues, sizeof(LONG) * ulCount);
  3333. pv[0].vt = VT_VECTOR | VT_I4;
  3334. pv[0].cal.cElems = cList;
  3335. pv[0].cal.pElems = pList;
  3336. //
  3337. // Call the helper to set the valid value
  3338. //
  3339. hr = SetValidValueHelper(pWiasContext, WIA_PROP_LIST, ps, pv);
  3340. if (FAILED(hr)) {
  3341. DBG_ERR(("wiasSetValidListLong, Helper failed (0x%X)", hr));
  3342. }
  3343. PropVariantClear(pv);
  3344. return hr;
  3345. }
  3346. /**************************************************************************\
  3347. * wiasSetValidListFloat
  3348. *
  3349. * Sets the valid values for a WIA_PROP_LIST property. This function
  3350. * assumes the property is of type VT_R4.
  3351. *
  3352. * Arguments:
  3353. *
  3354. * pWiasContext - Wia item
  3355. * propid - Identifies the property
  3356. * ulCount - the number of elements in the list
  3357. * fNom - the list's nominal value
  3358. * pfValues - the array of FLOATs that make up the valid list
  3359. *
  3360. * Return Value:
  3361. *
  3362. * Status
  3363. *
  3364. * History:
  3365. *
  3366. * 07/21/1999 Original Version
  3367. *
  3368. \**************************************************************************/
  3369. HRESULT _stdcall wiasSetValidListFloat(
  3370. BYTE *pWiasContext,
  3371. PROPID propid,
  3372. ULONG ulCount,
  3373. FLOAT fNom,
  3374. FLOAT *pfValues)
  3375. {
  3376. DBG_FN(::wiasSetValidListFloat);
  3377. HRESULT hr;
  3378. PROPVARIANT pv[1];
  3379. PROPSPEC ps[1];
  3380. FLOAT *pList;
  3381. ULONG cList;
  3382. //
  3383. // Validate params
  3384. //
  3385. hr = ValidateWiaItem((IWiaItem*)pWiasContext);
  3386. if (FAILED(hr)) {
  3387. DBG_ERR(("wiasSetValidListFloat, invalid pItem (0x%X)", hr));
  3388. return hr;
  3389. }
  3390. if (IsBadReadPtr(pfValues, sizeof(FLOAT) * ulCount)) {
  3391. DBG_ERR(("wiasSetValidListFloat, plValues is an invalid pointer"));
  3392. return E_POINTER;
  3393. }
  3394. cList = WIA_LIST_NUM_ELEMS + ulCount;
  3395. pList = (FLOAT*) CoTaskMemAlloc(sizeof(FLOAT) * cList);
  3396. if (!pList) {
  3397. DBG_ERR(("wiasSetValidListFloat, Out of memory"));
  3398. return E_OUTOFMEMORY;
  3399. }
  3400. //
  3401. // Set up the propvariant
  3402. //
  3403. ps[0].ulKind = PRSPEC_PROPID;
  3404. ps[0].propid = propid;
  3405. pList[WIA_LIST_COUNT] = (FLOAT) ulCount;
  3406. pList[WIA_LIST_NOM] = fNom;
  3407. memcpy(&pList[WIA_LIST_VALUES], pfValues, sizeof(LONG) * ulCount);
  3408. pv[0].vt = VT_VECTOR | VT_R4;
  3409. pv[0].caflt.cElems = cList;
  3410. pv[0].caflt.pElems = pList;
  3411. //
  3412. // Call the helper to set the valid value
  3413. //
  3414. hr = SetValidValueHelper(pWiasContext, WIA_PROP_LIST, ps, pv);
  3415. if (FAILED(hr)) {
  3416. DBG_ERR(("wiasSetValidListFloat, Helper failed (0x%X)", hr));
  3417. }
  3418. PropVariantClear(pv);
  3419. return hr;
  3420. }
  3421. /**************************************************************************\
  3422. * wiasSetValidListGUID
  3423. *
  3424. * Sets the valid values for a WIA_PROP_LIST property. This function
  3425. * assumes the property is of type VT_CLSID.
  3426. *
  3427. * Arguments:
  3428. *
  3429. * pWiasContext - Wia item
  3430. * propid - Identifies the property
  3431. * ulCount - the number of elements in the list
  3432. * fNom - the list's nominal value
  3433. * pfValues - the array of FLOATs that make up the valid list
  3434. *
  3435. * Return Value:
  3436. *
  3437. * Status
  3438. *
  3439. * History:
  3440. *
  3441. * 07/21/1999 Original Version
  3442. *
  3443. \**************************************************************************/
  3444. HRESULT _stdcall wiasSetValidListGuid(
  3445. BYTE *pWiasContext,
  3446. PROPID propid,
  3447. ULONG ulCount,
  3448. GUID guidNom,
  3449. GUID *pguidValues)
  3450. {
  3451. DBG_FN(::wiasSetValidListGuid);
  3452. HRESULT hr;
  3453. PROPVARIANT pv[1];
  3454. PROPSPEC ps[1];
  3455. GUID *pList;
  3456. ULONG cList;
  3457. //
  3458. // Validate params
  3459. //
  3460. hr = ValidateWiaItem((IWiaItem*)pWiasContext);
  3461. if (FAILED(hr)) {
  3462. DBG_ERR(("wiasSetValidListGuid, invalid pItem (0x%X)", hr));
  3463. return hr;
  3464. }
  3465. if (IsBadReadPtr(pguidValues, sizeof(GUID) * ulCount)) {
  3466. DBG_ERR(("wiasSetValidListGuid, plValues is an invalid pointer"));
  3467. return E_POINTER;
  3468. }
  3469. cList = WIA_LIST_NUM_ELEMS + ulCount;
  3470. pList = (GUID*) CoTaskMemAlloc(sizeof(GUID) * cList);
  3471. if (!pList) {
  3472. DBG_ERR(("wiasSetValidListGuid, Out of memory"));
  3473. return E_OUTOFMEMORY;
  3474. }
  3475. //
  3476. // Set up the propvariant
  3477. //
  3478. ps[0].ulKind = PRSPEC_PROPID;
  3479. ps[0].propid = propid;
  3480. pList[WIA_LIST_COUNT] = WiaImgFmt_UNDEFINED;
  3481. pList[WIA_LIST_NOM] = guidNom;
  3482. for (ULONG index = 0; index < ulCount; index++) {
  3483. pList[WIA_LIST_VALUES + index] = pguidValues[index];
  3484. }
  3485. pv[0].vt = VT_VECTOR | VT_CLSID;
  3486. pv[0].cauuid.cElems = cList;
  3487. pv[0].cauuid.pElems = pList;
  3488. //
  3489. // Call the helper to set the valid value
  3490. //
  3491. hr = SetValidValueHelper(pWiasContext, WIA_PROP_LIST, ps, pv);
  3492. if (FAILED(hr)) {
  3493. DBG_ERR(("wiasSetValidListGuid, Helper failed (0x%X)", hr));
  3494. }
  3495. PropVariantClear(pv);
  3496. return hr;
  3497. }
  3498. /**************************************************************************\
  3499. * wiasSetValidListStr
  3500. *
  3501. * Sets the valid values for a WIA_PROP_LIST property. This function
  3502. * assumes the property is of type VT_BSTR.
  3503. *
  3504. * Arguments:
  3505. *
  3506. * pWiasContext - Wia item
  3507. * propid - Identifies the property
  3508. * ulCount - the number of elements in the list
  3509. * bstrNom - the list's nominal value
  3510. * bstrValues - the array of BSTRs that make up the valid list
  3511. *
  3512. * Return Value:
  3513. *
  3514. * Status
  3515. *
  3516. * History:
  3517. *
  3518. * 07/21/1999 Original Version
  3519. *
  3520. \**************************************************************************/
  3521. HRESULT _stdcall wiasSetValidListStr(
  3522. BYTE *pWiasContext,
  3523. PROPID propid,
  3524. ULONG ulCount,
  3525. BSTR bstrNom,
  3526. BSTR *bstrValues)
  3527. {
  3528. DBG_FN(::wiasSetValidListStr);
  3529. HRESULT hr = S_OK;
  3530. PROPVARIANT pv[1];
  3531. PROPSPEC ps[1];
  3532. BSTR *pList;
  3533. ULONG cList;
  3534. //
  3535. // Validate params
  3536. //
  3537. hr = ValidateWiaItem((IWiaItem*)pWiasContext);
  3538. if (FAILED(hr)) {
  3539. DBG_ERR(("wiasSetValidListStr, invalid pItem (0x%X)", hr));
  3540. return hr;
  3541. }
  3542. if (IsBadReadPtr(bstrValues, sizeof(BSTR) * ulCount)) {
  3543. DBG_ERR(("wiasSetValidListStr, plValues is an invalid pointer"));
  3544. return E_POINTER;
  3545. }
  3546. for (ULONG ulIndex = 0; ulIndex < ulCount; ulIndex++) {
  3547. if (IsBadStringPtrW(bstrValues[ulIndex],
  3548. SysStringLen(bstrValues[ulIndex]))) {
  3549. DBG_ERR(("wiasSetValidListStr, bstrValues[%d] is an invalid string", ulIndex));
  3550. return E_POINTER;
  3551. }
  3552. }
  3553. cList = WIA_LIST_NUM_ELEMS + ulCount;
  3554. pList = (BSTR*) CoTaskMemAlloc(sizeof(BSTR) * cList);
  3555. if (!pList) {
  3556. DBG_ERR(("wiasSetValidListStr, Out of memory"));
  3557. return E_OUTOFMEMORY;
  3558. }
  3559. //
  3560. // Set up the propvariant
  3561. //
  3562. ps[0].ulKind = PRSPEC_PROPID;
  3563. ps[0].propid = propid;
  3564. pList[WIA_LIST_COUNT] = SysAllocString(L"");
  3565. pList[WIA_LIST_NOM] = SysAllocString(bstrNom);
  3566. for (ulIndex = 0; ulIndex < ulCount; ulIndex++) {
  3567. pList[WIA_LIST_VALUES + ulIndex] = SysAllocString(bstrValues[ulIndex]);
  3568. if (!pList[ulIndex]) {
  3569. DBG_ERR(("wiasSetValidListStr, Out of memory"));
  3570. hr = E_OUTOFMEMORY;
  3571. }
  3572. }
  3573. pv[0].vt = VT_VECTOR | VT_BSTR;
  3574. pv[0].cabstr.cElems = cList;
  3575. pv[0].cabstr.pElems = pList;
  3576. if (SUCCEEDED(hr)) {
  3577. //
  3578. // Call the helper to set the valid value
  3579. //
  3580. hr = SetValidValueHelper(pWiasContext, WIA_PROP_LIST, ps, pv);
  3581. if (FAILED(hr)) {
  3582. DBG_ERR(("wiasSetValidListStr, Helper failed (0x%X)", hr));
  3583. }
  3584. }
  3585. PropVariantClear(pv);
  3586. return hr;
  3587. }
  3588. /**************************************************************************\
  3589. * wiasCreatePropContext
  3590. *
  3591. * Allocates and fills in the values for a WIA_PROPERTY_CONTEXT.
  3592. * Entries in the property context are propids of properties that either have
  3593. * dependants, or are themselves dependant on other properties. A context
  3594. * is used to mark which properties are being changed. A property context
  3595. * always has the standard properties listed in the WIA_StdPropsInContext
  3596. * array. The driver can specify optional properties that it is interested
  3597. * in by specifying them in pProps. The Properties that are being written
  3598. * (changed) by an application are specified by an array of PROPSPECs.
  3599. *
  3600. * Arguments:
  3601. *
  3602. * cPropSpec - the number of PropSpecs
  3603. * pPropSpec - an array of propspecs identifying which properties
  3604. * cProps - number of properties, can be 0
  3605. * pProps - array of propids identifying the properties to put into
  3606. * the property context, can be NULL.
  3607. * pContext - a pointer to a property context.
  3608. *
  3609. * Return Value:
  3610. *
  3611. * Status - S_OK if successful
  3612. * E_POINTER if one of the pointer agruments is bad
  3613. * E_OUTOFMEMORY if the space could not be allocated
  3614. *
  3615. * History:
  3616. *
  3617. * 04/04/1999 Original Version
  3618. * 07/22/1999 Moved from drivers to service
  3619. *
  3620. \**************************************************************************/
  3621. HRESULT _stdcall wiasCreatePropContext(
  3622. ULONG cPropSpec,
  3623. PROPSPEC *pPropSpec,
  3624. ULONG cProps,
  3625. PROPID *pProps,
  3626. WIA_PROPERTY_CONTEXT *pContext)
  3627. {
  3628. DBG_FN(::wiasCreatePropContext);
  3629. PROPID *pids;
  3630. BOOL *pChanged;
  3631. ULONG ulNumProps;
  3632. //
  3633. // Validate params
  3634. //
  3635. if (IsBadReadPtr(pPropSpec, cPropSpec)) {
  3636. DBG_ERR(("wiasCreatePropContext, pPropSpec is a bad (read) pointer"));
  3637. return E_POINTER;
  3638. }
  3639. if (IsBadReadPtr(pProps, cProps)) {
  3640. DBG_ERR(("wiasCreatePropContext, pProps is a bad (read) pointer"));
  3641. return E_POINTER;
  3642. }
  3643. if (IsBadWritePtr(pContext, sizeof(WIA_PROPERTY_CONTEXT))) {
  3644. DBG_ERR(("wiasCreatePropContext, pContext is a bad (write) pointer"));
  3645. return E_POINTER;
  3646. }
  3647. //
  3648. // Allocate the arrays needed for the property context
  3649. //
  3650. ulNumProps = (cProps + NUM_STD_PROPS_IN_CONTEXT);
  3651. pids = (PROPID*) CoTaskMemAlloc( sizeof(PROPID) * ulNumProps);
  3652. pChanged = (BOOL*) CoTaskMemAlloc(sizeof(BOOL) * ulNumProps);
  3653. if ((!pids) || (!pChanged)) {
  3654. DBG_ERR(("wiasCreatePropContext, pContext is a bad (write) pointer"));
  3655. return E_OUTOFMEMORY;
  3656. }
  3657. //
  3658. // Initialize the property context. First insert the standard context
  3659. // properties from WIA_StdPropsInContext, then the ones specified by
  3660. // pProps.
  3661. //
  3662. memcpy(pids,
  3663. WIA_StdPropsInContext,
  3664. sizeof(PROPID) * NUM_STD_PROPS_IN_CONTEXT);
  3665. memcpy(&pids[NUM_STD_PROPS_IN_CONTEXT],
  3666. pProps,
  3667. sizeof(PROPID) * cProps);
  3668. memset(pChanged, FALSE, sizeof(PROPID) * ulNumProps);
  3669. pContext->cProps = ulNumProps;
  3670. pContext->pProps = pids;
  3671. pContext->pChanged = pChanged;
  3672. //
  3673. // Scan through list of PropSpecs and mark the bChanged field TRUE
  3674. // if a property matches one in the Context.
  3675. //
  3676. ULONG psIndex;
  3677. ULONG pcIndex;
  3678. for (psIndex = 0; psIndex < cPropSpec; psIndex++) {
  3679. for (pcIndex = 0; pcIndex < pContext->cProps; pcIndex++) {
  3680. if (pContext->pProps[pcIndex] == pPropSpec[psIndex].propid) {
  3681. pContext->pChanged[pcIndex] = TRUE;
  3682. }
  3683. }
  3684. }
  3685. return S_OK;
  3686. }
  3687. /**************************************************************************\
  3688. * wiasFreePropContext
  3689. *
  3690. * Frees up the memory used by a WIA_PROPERTY_CONTEXT.
  3691. *
  3692. * Arguments:
  3693. *
  3694. * pContext - a pointer to a property context.
  3695. *
  3696. * Return Value:
  3697. *
  3698. * Status - S_OK if successful
  3699. * E_POINTER if the context pointer is bad.
  3700. *
  3701. * History:
  3702. *
  3703. * 04/04/1999 Original Version
  3704. * 07/22/1999 Moved from drivers to service
  3705. *
  3706. \**************************************************************************/
  3707. HRESULT _stdcall wiasFreePropContext(
  3708. WIA_PROPERTY_CONTEXT *pContext)
  3709. {
  3710. DBG_FN(::wiasFreePropContext);
  3711. //
  3712. // Validate params
  3713. //
  3714. if (IsBadReadPtr(pContext, sizeof(WIA_PROPERTY_CONTEXT))) {
  3715. DBG_ERR(("wiasFreePropContext, pContext is a bad (read) pointer"));
  3716. return E_POINTER;
  3717. }
  3718. //
  3719. // Free the arrays used by the property context
  3720. //
  3721. CoTaskMemFree(pContext->pProps);
  3722. CoTaskMemFree(pContext->pChanged);
  3723. memset(pContext, 0, sizeof(WIA_PROPERTY_CONTEXT));
  3724. return S_OK;
  3725. }
  3726. /**************************************************************************\
  3727. * wiasIsPropChanged
  3728. *
  3729. * Sets a BOOL parameter to indicate whether a property is being changed
  3730. * or not by looking at the BOOL (bChanged) value in the Property context.
  3731. * Used by driver in property validation to check when an independant
  3732. * property has been changed so that its dependants may be updated.
  3733. *
  3734. * Arguments:
  3735. *
  3736. * propid - identifies the property we're looking for.
  3737. * pContext - the property context
  3738. * pbChanged - the address of where to store the BOOL indicating that
  3739. * the property is being changed.
  3740. *
  3741. * Return Value:
  3742. *
  3743. * Status - E_INVALIDARG will be returned if the property is not
  3744. * found in the context.
  3745. * E_POINTER is returned if any of the pointer arguments
  3746. * are bad.
  3747. * S_OK if the property is found.
  3748. *
  3749. * History:
  3750. *
  3751. * 22/07/1999 Original Version
  3752. *
  3753. \**************************************************************************/
  3754. HRESULT _stdcall wiasIsPropChanged(
  3755. PROPID propid,
  3756. WIA_PROPERTY_CONTEXT *pContext,
  3757. BOOL *pbChanged)
  3758. {
  3759. DBG_FN(::wiasIsPropChanged);
  3760. //
  3761. // Validate params
  3762. //
  3763. if (IsBadReadPtr(pContext, sizeof(WIA_PROPERTY_CONTEXT))) {
  3764. DBG_ERR(("wiasIsPropChanged, pContext is a bad (read) pointer"));
  3765. return E_POINTER;
  3766. }
  3767. if (IsBadReadPtr(pContext->pProps, sizeof(PROPID) * pContext->cProps)) {
  3768. DBG_ERR(("wiasIsPropChanged, pContext->pProps is a bad (read) pointer"));
  3769. return E_POINTER;
  3770. }
  3771. if (IsBadReadPtr(pContext->pChanged, sizeof(BOOL) * pContext->cProps)) {
  3772. DBG_ERR(("wiasIsPropChanged, pContext->pChanged is a bad (read) pointer"));
  3773. return E_POINTER;
  3774. }
  3775. if (IsBadWritePtr(pbChanged, sizeof(BOOL))) {
  3776. DBG_ERR(("wiasIsPropChanged, pulIndex is a bad (write) pointer"));
  3777. return E_POINTER;
  3778. }
  3779. //
  3780. // Look for the property in the property context
  3781. //
  3782. for (ULONG index = 0; index < pContext->cProps; index++) {
  3783. //
  3784. // Property found, so set the BOOL return.
  3785. //
  3786. if (pContext->pProps[index] == propid) {
  3787. *pbChanged = pContext->pChanged[index];
  3788. return S_OK;
  3789. }
  3790. }
  3791. //
  3792. // Property wasn't found
  3793. //
  3794. return E_INVALIDARG;;
  3795. }
  3796. /**************************************************************************\
  3797. * wiasSetPropChanged
  3798. *
  3799. * Sets the pChanged value for the specified property in the property
  3800. * context to indicate that a property is being changed or not. This
  3801. * should be used when a driver changes a property that has dependant
  3802. * properties in validation. E.g. By changing "Current Intent", the
  3803. * "Horizontal Resolution" will be changed and should be marked as changed,
  3804. * so that validation of XResolution and its dependants will still take
  3805. * place.
  3806. *
  3807. * Arguments:
  3808. *
  3809. * propid - identifies the property we're looking for.
  3810. * pContext - the property context
  3811. * bChanged - the BOOL indicating the new pChanged value.
  3812. *
  3813. * Return Value:
  3814. *
  3815. * Status - E_INVALIDARG will be returned if the property is not
  3816. * found in the context.
  3817. * E_POINTER is returned if any of the pointer arguments
  3818. * are bad.
  3819. * S_OK if the property is found.
  3820. *
  3821. * History:
  3822. *
  3823. * 22/07/1999 Original Version
  3824. *
  3825. \**************************************************************************/
  3826. HRESULT _stdcall wiasSetPropChanged(
  3827. PROPID propid,
  3828. WIA_PROPERTY_CONTEXT *pContext,
  3829. BOOL bChanged)
  3830. {
  3831. DBG_FN(::wiasSetPropChanged);
  3832. //
  3833. // Validate params
  3834. //
  3835. if (IsBadReadPtr(pContext, sizeof(WIA_PROPERTY_CONTEXT))) {
  3836. DBG_ERR(("wiasIsPropChanged, pContext is a bad (read) pointer"));
  3837. return E_POINTER;
  3838. }
  3839. if (IsBadReadPtr(pContext->pProps, sizeof(PROPID) * pContext->cProps)) {
  3840. DBG_ERR(("wiasIsPropChanged, pContext->pProps is a bad (read) pointer"));
  3841. return E_POINTER;
  3842. }
  3843. if (IsBadReadPtr(pContext->pChanged, sizeof(BOOL) * pContext->cProps)) {
  3844. DBG_ERR(("wiasIsPropChanged, pContext->pChanged is a bad (read) pointer"));
  3845. return E_POINTER;
  3846. }
  3847. //
  3848. // Look for the property in the property context
  3849. //
  3850. for (ULONG index = 0; index < pContext->cProps; index++) {
  3851. //
  3852. // Property found, so set the pChanged[index] BOOL.
  3853. //
  3854. if (pContext->pProps[index] == propid) {
  3855. pContext->pChanged[index] = bChanged;
  3856. return S_OK;
  3857. }
  3858. }
  3859. //
  3860. // Property wasn't found
  3861. //
  3862. return E_INVALIDARG;;
  3863. }
  3864. /**************************************************************************\
  3865. * wiasGetChangedValueLong
  3866. *
  3867. * This helper method is called to check whether a property is changed,
  3868. * return it's current value and its old value. The properties are assumed
  3869. * to be LONG.
  3870. *
  3871. * Arguments:
  3872. *
  3873. * pWiasContext - A pointer to the Wia item context.
  3874. * bNoValidation - If TRUE, it skips validation of the property.
  3875. * Validation should be skipped when a property's
  3876. * valid values have yet to be updated.
  3877. * pContext - A pointer to the Property Context.
  3878. * propID - Identifies the property.
  3879. * pInfo - A pointer to a WIAS_CHANGED_VALUE_INFO struct
  3880. * where the values to be returned are set.
  3881. *
  3882. * Return Value:
  3883. *
  3884. * Status - S_OK if successful.
  3885. * - E_INVALIDARG if the property fails validation.
  3886. *
  3887. * History:
  3888. *
  3889. * 04/04/1999 Original Version
  3890. * 07/22/1999 Moved from drivers to service
  3891. *
  3892. \**************************************************************************/
  3893. HRESULT _stdcall wiasGetChangedValueLong(
  3894. BYTE *pWiasContext,
  3895. WIA_PROPERTY_CONTEXT *pContext,
  3896. BOOL bNoValidation,
  3897. PROPID propID,
  3898. WIAS_CHANGED_VALUE_INFO *pInfo)
  3899. {
  3900. DBG_FN(::wiasGetChangedValueLong);
  3901. LONG lIndex;
  3902. HRESULT hr = S_OK;
  3903. //
  3904. // Parameter validation for pWiasContext, propID
  3905. // will be done by wiasReadPropLong.
  3906. // Parameter validation for pContex and bChanged will be done by
  3907. // wiasIsChangedValue.
  3908. //
  3909. if(IsBadWritePtr(pInfo, sizeof(WIAS_CHANGED_VALUE_INFO))) {
  3910. DBG_ERR(("wiasGetChangedValueLong, pInfo is a bad (write) pointer"));
  3911. return E_POINTER;
  3912. }
  3913. pInfo->vt = VT_I4;
  3914. //
  3915. // Get the current and old value of the property
  3916. //
  3917. hr = wiasReadPropLong(pWiasContext, propID, &pInfo->Current.lVal, &pInfo->Old.lVal, TRUE);
  3918. if (SUCCEEDED(hr)) {
  3919. //
  3920. // Check whether validation should be skipped or not.
  3921. //
  3922. if (!bNoValidation) {
  3923. PROPSPEC ps[1];
  3924. ps[0].ulKind = PRSPEC_PROPID;
  3925. ps[0].propid = propID;
  3926. //
  3927. // Do validation
  3928. //
  3929. hr = wiasValidateItemProperties(pWiasContext, 1, ps);
  3930. }
  3931. //
  3932. // Set whether the property has changed or not.
  3933. //
  3934. if (SUCCEEDED(hr)) {
  3935. hr = wiasIsPropChanged(propID, pContext, &pInfo->bChanged);
  3936. } else {
  3937. DBG_ERR(("wiasGetChangedValueLong, validate prop %d failed hr: 0x%X", propID, hr));
  3938. }
  3939. } else {
  3940. DBG_ERR(("wiasGetChangedValueLong, read property %d failed hr: 0x%X", propID, hr));
  3941. }
  3942. return hr;
  3943. }
  3944. /**************************************************************************\
  3945. * wiasGetChangedValueFloat
  3946. *
  3947. * This helper method is called to check whether a property is changed,
  3948. * return it's current value and its old value. The properties are assumed
  3949. * to be FLOAT.
  3950. *
  3951. * Arguments:
  3952. *
  3953. * pWiasContext - A pointer to the Wia item context.
  3954. * bNoValidation - If TRUE, it skips validation of the property.
  3955. * Validation should be skipped when a property's
  3956. * valid values have yet to be updated.
  3957. * pContext - A pointer to the Property Context.
  3958. * propID - Identifies the property.
  3959. * pInfo - A pointer to a WIAS_CHANGED_VALUE_INFO struct
  3960. * where the values to be returned are set.
  3961. *
  3962. * Return Value:
  3963. *
  3964. * Status - S_OK if successful.
  3965. * - E_INVALIDARG if the property fails validation.
  3966. *
  3967. * History:
  3968. *
  3969. * 04/04/1999 Original Version
  3970. * 07/22/1999 Moved from drivers to service
  3971. *
  3972. \**************************************************************************/
  3973. HRESULT _stdcall wiasGetChangedValueFloat(
  3974. BYTE *pWiasContext,
  3975. WIA_PROPERTY_CONTEXT *pContext,
  3976. BOOL bNoValidation,
  3977. PROPID propID,
  3978. WIAS_CHANGED_VALUE_INFO *pInfo)
  3979. {
  3980. DBG_FN(::wiasGetChangedValueFloat);
  3981. LONG lIndex;
  3982. HRESULT hr = S_OK;
  3983. //
  3984. // Parameter validation for pWiasContext, propID,
  3985. // will be done by wiasReadPropLong.
  3986. // Parameter validation for pContex and bChanged will be done by
  3987. // wiasIsChangedValue.
  3988. //
  3989. if(IsBadWritePtr(pInfo, sizeof(WIAS_CHANGED_VALUE_INFO))) {
  3990. DBG_ERR(("wiasGetChangedValueFloat, pInfo is a bad (write) pointer"));
  3991. return E_POINTER;
  3992. }
  3993. pInfo->vt = VT_R4;
  3994. //
  3995. // Get the current and old value of the property
  3996. //
  3997. hr = wiasReadPropFloat(pWiasContext, propID, &pInfo->Current.fltVal, &pInfo->Old.fltVal, TRUE);
  3998. if (SUCCEEDED(hr)) {
  3999. //
  4000. // Check whether validation should be skipped or not.
  4001. //
  4002. if (!bNoValidation) {
  4003. PROPSPEC ps[1];
  4004. ps[0].ulKind = PRSPEC_PROPID;
  4005. ps[0].propid = propID;
  4006. //
  4007. // Do validation
  4008. //
  4009. hr = wiasValidateItemProperties(pWiasContext, 1, ps);
  4010. }
  4011. //
  4012. // Set whether the property has changed or not.
  4013. //
  4014. if (SUCCEEDED(hr)) {
  4015. hr = wiasIsPropChanged(propID, pContext, &pInfo->bChanged);
  4016. } else {
  4017. DBG_ERR(("wiasGetChangedValueFloat, validate prop %d failed (0x%X)", propID, hr));
  4018. }
  4019. } else {
  4020. DBG_ERR(("wiasGetChangedValueFloat, read property %d failed (0x%X)", propID, hr));
  4021. }
  4022. return hr;
  4023. }
  4024. /**************************************************************************\
  4025. * wiasGetChangedValueGuid
  4026. *
  4027. * This helper method is called to check whether a property is changed,
  4028. * return it's current value and its old value. The properties are assumed
  4029. * to be FLOAT.
  4030. *
  4031. * Arguments:
  4032. *
  4033. * pWiasContext - A pointer to the Wia item context.
  4034. * bNoValidation - If TRUE, it skips validation of the property.
  4035. * Validation should be skipped when a property's
  4036. * valid values have yet to be updated.
  4037. * pContext - A pointer to the Property Context.
  4038. * propID - Identifies the property.
  4039. * pInfo - A pointer to a WIAS_CHANGED_VALUE_INFO struct
  4040. * where the values to be returned are set.
  4041. *
  4042. * Return Value:
  4043. *
  4044. * Status - S_OK if successful.
  4045. * - E_INVALIDARG if the property fails validation.
  4046. *
  4047. * History:
  4048. *
  4049. * 04/04/1999 Original Version
  4050. * 07/22/1999 Moved from drivers to service
  4051. *
  4052. \**************************************************************************/
  4053. HRESULT _stdcall wiasGetChangedValueGuid(
  4054. BYTE *pWiasContext,
  4055. WIA_PROPERTY_CONTEXT *pContext,
  4056. BOOL bNoValidation,
  4057. PROPID propID,
  4058. WIAS_CHANGED_VALUE_INFO *pInfo)
  4059. {
  4060. DBG_FN(::wiasGetChangedValueGuid);
  4061. LONG lIndex;
  4062. HRESULT hr = S_OK;
  4063. //
  4064. // Parameter validation for pWiasContext, propID,
  4065. // will be done by wiasReadPropLong.
  4066. // Parameter validation for pContex and bChanged will be done by
  4067. // wiasIsChangedValue.
  4068. //
  4069. if(IsBadWritePtr(pInfo, sizeof(WIAS_CHANGED_VALUE_INFO))) {
  4070. DBG_ERR(("wiasGetChangedValueFloat, pInfo is a bad (write) pointer"));
  4071. return E_POINTER;
  4072. }
  4073. pInfo->vt = VT_CLSID;
  4074. //
  4075. // Get the current and old value of the property
  4076. //
  4077. hr = wiasReadPropGuid(pWiasContext, propID, &pInfo->Current.guidVal, &pInfo->Old.guidVal, TRUE);
  4078. if (SUCCEEDED(hr)) {
  4079. //
  4080. // Check whether validation should be skipped or not.
  4081. //
  4082. if (!bNoValidation) {
  4083. PROPSPEC ps[1];
  4084. ps[0].ulKind = PRSPEC_PROPID;
  4085. ps[0].propid = propID;
  4086. //
  4087. // Do validation
  4088. //
  4089. hr = wiasValidateItemProperties(pWiasContext, 1, ps);
  4090. }
  4091. //
  4092. // Set whether the property has changed or not.
  4093. //
  4094. if (SUCCEEDED(hr)) {
  4095. hr = wiasIsPropChanged(propID, pContext, &pInfo->bChanged);
  4096. } else {
  4097. DBG_ERR(("wiasGetChangedValueFloat, validate prop %d failed (0x%X)", propID, hr));
  4098. }
  4099. } else {
  4100. DBG_ERR(("wiasGetChangedValueFloat, read property %d failed (0x%X)", propID, hr));
  4101. }
  4102. return hr;
  4103. }
  4104. /**************************************************************************\
  4105. * wiasGetChangedValueStr
  4106. *
  4107. * This helper method is called to check whether a property is changed,
  4108. * return it's current value and its old value. The properties are assumed
  4109. * to be BSTR.
  4110. *
  4111. * Arguments:
  4112. *
  4113. * pWiasContext - A pointer to the Wia item context.
  4114. * bNoValidation - If TRUE, it skips validation of the property.
  4115. * Validation should be skipped when a property's
  4116. * valid values have yet to be updated.
  4117. * pContext - A pointer to the Property Context.
  4118. * propID - Identifies the property.
  4119. * pInfo - A pointer to a WIAS_CHANGED_VALUE_INFO struct
  4120. * where the values to be returned are set.
  4121. *
  4122. * Return Value:
  4123. *
  4124. * Status - S_OK if successful.
  4125. * - E_INVALIDARG if the property fails validation.
  4126. *
  4127. * History:
  4128. *
  4129. * 04/04/1999 Original Version
  4130. * 07/22/1999 Moved from drivers to service
  4131. *
  4132. \**************************************************************************/
  4133. HRESULT _stdcall wiasGetChangedValueStr(
  4134. BYTE *pWiasContext,
  4135. WIA_PROPERTY_CONTEXT *pContext,
  4136. BOOL bNoValidation,
  4137. PROPID propID,
  4138. WIAS_CHANGED_VALUE_INFO *pInfo)
  4139. {
  4140. DBG_FN(::wiasGetChangedValueStr);
  4141. LONG lIndex;
  4142. HRESULT hr = S_OK;
  4143. //
  4144. // Parameter validation for pWiasContext, propID,
  4145. // will be done by wiasReadPropLong.
  4146. // Parameter validation for pContex and bChanged will be done by
  4147. // wiasIsChangedValue.
  4148. //
  4149. if(IsBadWritePtr(pInfo, sizeof(WIAS_CHANGED_VALUE_INFO))) {
  4150. DBG_ERR(("wiasGetChangedValueStr, pInfo is a bad (write) pointer"));
  4151. return E_POINTER;
  4152. }
  4153. pInfo->vt = VT_BSTR;
  4154. //
  4155. // Get the current and old value of the property
  4156. //
  4157. hr = wiasReadPropStr(pWiasContext, propID, &pInfo->Current.bstrVal, &pInfo->Old.bstrVal, TRUE);
  4158. if (SUCCEEDED(hr)) {
  4159. //
  4160. // Check whether validation should be skipped or not.
  4161. //
  4162. if (!bNoValidation) {
  4163. PROPSPEC ps[1];
  4164. ps[0].ulKind = PRSPEC_PROPID;
  4165. ps[0].propid = propID;
  4166. //
  4167. // Do validation
  4168. //
  4169. hr = wiasValidateItemProperties(pWiasContext, 1, ps);
  4170. }
  4171. //
  4172. // Set whether the property has changed or not.
  4173. //
  4174. if (SUCCEEDED(hr)) {
  4175. hr = wiasIsPropChanged(propID, pContext, &pInfo->bChanged);
  4176. } else {
  4177. DBG_ERR(("wiasGetChangedValueStr, validate prop %d failed (0x%X)", propID, hr));
  4178. }
  4179. } else {
  4180. DBG_ERR(("wiasGetChangedValueStr, read property %d failed (0x%X)", propID, hr));
  4181. }
  4182. return hr;
  4183. }
  4184. /**************************************************************************\
  4185. * wiasGetContextFromName
  4186. *
  4187. * This helper method is called to find a WIA Item by name.
  4188. *
  4189. * Arguments:
  4190. *
  4191. * pWiasContext - A pointer to a Wia item context.
  4192. * lFlags - operational flags.
  4193. * bstrName - The name of the context we are looking for.
  4194. * ppWiasContext - The address where to return the Wia Item context.
  4195. *
  4196. * Return Value:
  4197. *
  4198. * Status - S_OK if the item was found.
  4199. * S_FALSE if the item wasn't found, but there was no error.
  4200. * A standard COM error code if an error occurred.
  4201. *
  4202. * History:
  4203. *
  4204. * 07/28/1999 Original version
  4205. *
  4206. \**************************************************************************/
  4207. HRESULT _stdcall wiasGetContextFromName(
  4208. BYTE *pWiasContext,
  4209. LONG lFlags,
  4210. BSTR bstrName,
  4211. BYTE **ppWiasContext)
  4212. {
  4213. DBG_FN(::wiasGetContextFromName);
  4214. HRESULT hr;
  4215. //
  4216. // Validate params
  4217. //
  4218. hr = ValidateWiaItem((IWiaItem*)pWiasContext);
  4219. if (FAILED(hr)) {
  4220. DBG_ERR(("wiasGetContextFromName, invalid pItem (0x%X)", hr));
  4221. return hr;
  4222. }
  4223. hr = ((CWiaItem*) pWiasContext)->FindItemByName(lFlags,
  4224. bstrName,
  4225. (IWiaItem**)ppWiasContext);
  4226. return hr;
  4227. }
  4228. /**************************************************************************\
  4229. * wiasUpdateScanRect
  4230. *
  4231. * This helper method is called to update the properties making up the
  4232. * scan rect. The appropriate changes are made to the properties which are
  4233. * dependant on those that make up the scan rect. (e.g. a change in
  4234. * horizontal resolution will affect the horizontal extent). This function
  4235. * assumes that the valid values for the vertical and horizontal extents,
  4236. * and vertical and horizontal positions have not been updated yet.
  4237. * The width and height arguments are the maxiumum and minimum dimensions
  4238. * of the scan area in one thousandth's of an inch.
  4239. * Normally, these would be the scan bed dimensions.
  4240. *
  4241. * Arguments:
  4242. *
  4243. * pWiasContext - A pointer to a Wia item context.
  4244. * pContext - A pointer to a WIA property context (created
  4245. * previsouly with wiasCreatePropertyContext).
  4246. * lWidth - the width of the maximum scan area in one thousandth's
  4247. * of an inch. Generally, this would be the horizontal
  4248. * bed size.
  4249. * lHeight - the height of the maximum scan area in one
  4250. * thousandth's of an inch. Generally, this would be
  4251. * the vertical bed size.
  4252. *
  4253. * Return Value:
  4254. *
  4255. * Status
  4256. *
  4257. * History:
  4258. *
  4259. * 07/30/1999 Original version
  4260. *
  4261. \**************************************************************************/
  4262. HRESULT _stdcall wiasUpdateScanRect(
  4263. BYTE *pWiasContext,
  4264. WIA_PROPERTY_CONTEXT *pContext,
  4265. LONG lWidth,
  4266. LONG lHeight)
  4267. {
  4268. DBG_FN(::wiasUpdateScanRect);
  4269. HRESULT hr = S_OK;
  4270. //
  4271. // Validation of pWiasContext will be done by wiasGetRootItem so
  4272. // just need to validate pContext
  4273. //
  4274. if (IsBadReadPtr(pContext, sizeof(WIA_PROPERTY_CONTEXT))) {
  4275. DBG_ERR(("wiasUpdateScanRect, pContext is a bad (read) pointer"));
  4276. return E_POINTER;
  4277. } else if (IsBadReadPtr(pContext->pProps, sizeof(PROPID) * pContext->cProps)) {
  4278. DBG_ERR(("wiasUpdateScanRect, pContext->pProps is a bad (read) pointer"));
  4279. return E_POINTER;
  4280. } else if (IsBadReadPtr(pContext->pChanged, sizeof(BOOL) * pContext->cProps)) {
  4281. DBG_ERR(("wiasUpdateScanRect, pContext->pChanged is a bad (read) pointer"));
  4282. return E_POINTER;
  4283. }
  4284. //
  4285. // Make adjustments to the required properties.
  4286. //
  4287. if (SUCCEEDED(hr)) {
  4288. hr = CheckXResAndUpdate(pWiasContext, pContext, lWidth);
  4289. if (SUCCEEDED(hr)) {
  4290. hr = CheckYResAndUpdate(pWiasContext, pContext, lHeight);
  4291. if (FAILED(hr)) {
  4292. DBG_ERR(("wiasUpdateScanRect, CheckYResAndUpdate failed (0x%X)", hr));
  4293. }
  4294. } else {
  4295. DBG_ERR(("wiasUpdateScanRect, CheckXResAndUpdate failed (0x%X)", hr));
  4296. }
  4297. }
  4298. return hr;
  4299. }
  4300. /**************************************************************************\
  4301. * wiasUpdateValidFormat
  4302. *
  4303. * This helper method is called to update the valid values of the FORMAT
  4304. * property, based on the current TYMED setting. This call uses the
  4305. * drvGetFormatEtc method of the specified mini-driver item to find out
  4306. * the valid FORMAT values for the current TYMED. If the property context
  4307. * indicates that the FORMAT property is not being set, and the current
  4308. * value for FORMAT is not compatible with the current TYMED, then a
  4309. * new value for FORMAT will be chosen (the first item in the list of
  4310. * valid FORMAT values).
  4311. *
  4312. * Arguments:
  4313. *
  4314. * pWiasContext - a pointer to the item context whose properties have
  4315. * changed.
  4316. * pContext - a pointer to the property context (which indicates
  4317. * which properties are being written).
  4318. * pIMiniDrv - a pointer to the calling WIA minidriver.
  4319. *
  4320. * Return Value:
  4321. *
  4322. * Status
  4323. *
  4324. * History:
  4325. *
  4326. * 07/27/1999 Original Version
  4327. *
  4328. \**************************************************************************/
  4329. HRESULT _stdcall wiasUpdateValidFormat(
  4330. BYTE *pWiasContext,
  4331. WIA_PROPERTY_CONTEXT *pContext,
  4332. IWiaMiniDrv *pIMiniDrv)
  4333. {
  4334. DBG_FN(::wiasUpdateValidFormat);
  4335. HRESULT hr;
  4336. LONG tymed;
  4337. WIAS_CHANGED_VALUE_INFO cviTymed, cviFormat;
  4338. BOOL bFormatValid = FALSE;
  4339. GUID guidFirstFormat;
  4340. GUID *pFormatTbl;
  4341. LONG cFormatTbl = 0;
  4342. LONG celt;
  4343. WIA_FORMAT_INFO *pwfi;
  4344. LONG errVal;
  4345. if (IsBadReadPtr(pIMiniDrv, sizeof(IWiaMiniDrv))) {
  4346. DBG_ERR(("wiasUpdateValidFormat, invalid pIMiniDrv pointer"));
  4347. return E_POINTER;
  4348. }
  4349. cviFormat.bChanged = FALSE;
  4350. //
  4351. // Call wiasGetChangedValue for Tymed. Tymed is checked first
  4352. // since it's not dependant on any other property. All properties in
  4353. // this method that follow are dependant properties of CurrentIntent.
  4354. //
  4355. hr = wiasGetChangedValueLong(pWiasContext,
  4356. pContext,
  4357. FALSE,
  4358. WIA_IPA_TYMED,
  4359. &cviTymed);
  4360. if (SUCCEEDED(hr)) {
  4361. if (cviTymed.bChanged) {
  4362. //
  4363. // Get the current Format value and set bFormatChanged to indicate whether Format
  4364. // is being changed.
  4365. //
  4366. hr = wiasGetChangedValueGuid(pWiasContext,
  4367. pContext,
  4368. TRUE,
  4369. WIA_IPA_FORMAT,
  4370. &cviFormat);
  4371. if (FAILED(hr)) {
  4372. DBG_ERR(( "wiasUpdateValidFormat, wiasGetChangedValue (format) failed (0x%X)", hr));
  4373. return hr;
  4374. }
  4375. //
  4376. // Update the valid values for Format. First get the supported
  4377. // TYMED/FORMAT pairs.
  4378. //
  4379. hr = pIMiniDrv->drvGetWiaFormatInfo(pWiasContext,
  4380. 0,
  4381. &celt,
  4382. &pwfi,
  4383. &errVal);
  4384. if (SUCCEEDED(hr)) {
  4385. pFormatTbl = (GUID*) LocalAlloc(LPTR, sizeof(GUID) * celt);
  4386. if (!pFormatTbl) {
  4387. DBG_ERR(("wiasUpdateValidFormat, out of memory"));
  4388. return E_OUTOFMEMORY;
  4389. }
  4390. //
  4391. // Now store each supported format for the current tymed value
  4392. // in the pFormatTbl array.
  4393. //
  4394. for (LONG index = 0; index < celt; index++) {
  4395. if (((LONG) pwfi[index].lTymed) == cviTymed.Current.lVal) {
  4396. pFormatTbl[cFormatTbl] = pwfi[index].guidFormatID;
  4397. cFormatTbl++;
  4398. //
  4399. // Check whether lFormat is one of the valid values.
  4400. //
  4401. if (cviFormat.Current.guidVal == pwfi[index].guidFormatID) {
  4402. bFormatValid = TRUE;
  4403. }
  4404. }
  4405. }
  4406. guidFirstFormat = pFormatTbl[0];
  4407. //
  4408. // Update the valid values for Format
  4409. //
  4410. hr = wiasSetValidListGuid(pWiasContext,
  4411. WIA_IPA_FORMAT,
  4412. cFormatTbl,
  4413. pFormatTbl[0],
  4414. pFormatTbl);
  4415. if (FAILED(hr)) {
  4416. DBG_ERR(( "wiasUpdateValidFormat, wiasSetValidListGuid failed. (0x%X)", hr));
  4417. }
  4418. LocalFree(pFormatTbl);
  4419. } else {
  4420. DBG_ERR(( "wiasUpdateValidFormat, drvGetWiaFormatInfo failed. (0x%X)", hr));
  4421. }
  4422. }
  4423. } else {
  4424. DBG_ERR(( "wiasUpdateValidFormat, wiasGetChangedValue (tymed) failed (0x%X)", hr));
  4425. }
  4426. if (FAILED(hr)) {
  4427. return hr;
  4428. }
  4429. //
  4430. // If the Format is not being set by the app, an it's current value
  4431. // is not in the valid list, fold it to a valid value.
  4432. //
  4433. if (cviTymed.bChanged && !cviFormat.bChanged && !bFormatValid) {
  4434. hr = wiasWritePropGuid(pWiasContext, WIA_IPA_FORMAT, guidFirstFormat);
  4435. if (FAILED(hr)) {
  4436. DBG_ERR(( "wiasUpdateValidFormat, wiasWritePropLong failed. (0x%X)", hr));
  4437. }
  4438. }
  4439. return hr;
  4440. }
  4441. /**************************************************************************\
  4442. * wiasCreateLogInstance
  4443. *
  4444. * This helper method is called to create an instance of the logging
  4445. * object.
  4446. *
  4447. * Arguments:
  4448. *
  4449. * lModuleHandle - The module handle. Used to filter output.
  4450. * ppIWiaLog - The address of a pointer to receive the logging
  4451. * interface.
  4452. *
  4453. * Return Value:
  4454. *
  4455. * Status
  4456. *
  4457. * History:
  4458. *
  4459. * 01/07/2000 Original Version
  4460. *
  4461. \**************************************************************************/
  4462. HRESULT _stdcall wiasCreateLogInstance(
  4463. BYTE *pModuleHandle,
  4464. IWiaLogEx **ppIWiaLogEx)
  4465. {
  4466. HRESULT hr;
  4467. if (ppIWiaLogEx == NULL) {
  4468. DBG_ERR(("wiasCreateLogInstance, Invalid pointer argument"));
  4469. return E_POINTER;
  4470. }
  4471. //
  4472. // Validate the parameter.
  4473. //
  4474. if (IsBadWritePtr((VOID*) *ppIWiaLogEx, sizeof(IWiaLog*))) {
  4475. DBG_ERR(("wiasCreateLogInstance, Invalid pointer argument"));
  4476. return E_POINTER;
  4477. }
  4478. *ppIWiaLogEx = NULL;
  4479. //
  4480. // CoCreate an instance of the logging object. If successful, initialize
  4481. // it with the module handle passed in to us.
  4482. //
  4483. hr = CoCreateInstance(CLSID_WiaLog, NULL, CLSCTX_INPROC_SERVER,
  4484. IID_IWiaLogEx,(VOID**)ppIWiaLogEx);
  4485. if (SUCCEEDED(hr)) {
  4486. hr = (*ppIWiaLogEx)->InitializeLogEx(pModuleHandle);
  4487. } else {
  4488. DBG_ERR(("wiasCreateLogInstance, Failed to CoCreateInstance on Logging object (0x%X)", hr));
  4489. }
  4490. return hr;
  4491. }
  4492. HRESULT _stdcall wiasGetChildrenContexts(
  4493. BYTE *pParentContext,
  4494. ULONG *pulNumChildren,
  4495. BYTE ***pppChildren)
  4496. {
  4497. HRESULT hr = S_OK;
  4498. ULONG ulCount = 0;
  4499. IWiaItem *pParentItem = (IWiaItem*) pParentContext;
  4500. IWiaItem *pWiaItem = NULL;
  4501. BYTE **ppChildItems = NULL;
  4502. IEnumWiaItem *pEnum = NULL;
  4503. hr = ValidateWiaItem((IWiaItem*) pParentContext);
  4504. if (FAILED(hr)) {
  4505. DBG_ERR(("wiasGetChildrenContexts, invalid pParentContext"));
  4506. return hr;
  4507. }
  4508. if (!pParentContext || !pulNumChildren || !pppChildren) {
  4509. DBG_ERR(("wiasGetChildrenContexts, Invalid pointer argument"));
  4510. return E_POINTER;
  4511. }
  4512. *pulNumChildren = 0;
  4513. *pppChildren = NULL;
  4514. hr = pParentItem->EnumChildItems(&pEnum);
  4515. if (SUCCEEDED(hr)) {
  4516. //
  4517. // Get the number of children.
  4518. //
  4519. hr = pEnum->GetCount(&ulCount);
  4520. if (SUCCEEDED(hr) && ulCount) {
  4521. if (ulCount == 0) {
  4522. DBG_WRN(("wiasGetChildrenContexts, No children - returning S_FALSE"));
  4523. hr = S_FALSE;
  4524. } else {
  4525. //
  4526. // Allocate the return array
  4527. //
  4528. ppChildItems = (BYTE**) CoTaskMemAlloc(sizeof(BYTE*) * ulCount);
  4529. if (ppChildItems) {
  4530. //
  4531. // Enumerate through the children and store them in the array
  4532. //
  4533. ULONG ulIndex = 0;
  4534. while ((pEnum->Next(1, &pWiaItem, NULL) == S_OK) && (ulIndex < ulCount)) {
  4535. ppChildItems[ulIndex] = (BYTE*)pWiaItem;
  4536. pWiaItem->Release();
  4537. ulIndex++;
  4538. }
  4539. *pulNumChildren = ulIndex;
  4540. *pppChildren = ppChildItems;
  4541. hr = S_OK;
  4542. } else {
  4543. DBG_ERR(("wiasGetChildrenContexts, Out of memory"));
  4544. hr = E_OUTOFMEMORY;
  4545. }
  4546. }
  4547. } else {
  4548. DBG_ERR(("wiasGetChildrenContexts, GetCount failed (0x%X)", hr));
  4549. }
  4550. pEnum->Release();
  4551. } else {
  4552. DBG_ERR(("wiasGetChildrenContexts, Failed to get item enumerator (0x%X)", hr));
  4553. }
  4554. if (FAILED(hr)) {
  4555. if (ppChildItems) {
  4556. CoTaskMemFree(ppChildItems);
  4557. ppChildItems = NULL;
  4558. }
  4559. }
  4560. return hr;
  4561. }
  4562. HRESULT _stdcall wiasDownSampleBuffer(
  4563. LONG lFlags,
  4564. WIAS_DOWN_SAMPLE_INFO *pInfo
  4565. )
  4566. {
  4567. DBG_FN(::wiasDownSampleBuffer);
  4568. HRESULT hr = S_OK;
  4569. BOOL bAllocatedBuf = FALSE;
  4570. //
  4571. // Do some parameter validation
  4572. //
  4573. if (IsBadWritePtr(pInfo, sizeof(WIAS_DOWN_SAMPLE_INFO))) {
  4574. DBG_ERR(("wiasDownSampleBuffer, cannot write to WIAS_DOWN_SAMPLE_INFO!"));
  4575. return E_INVALIDARG;
  4576. }
  4577. //
  4578. // We try to sample the input data to DOWNSAMPLE_DPI, so if asked let's set the
  4579. // downsampled width and height.
  4580. //
  4581. if (pInfo->ulDownSampledWidth == 0) {
  4582. pInfo->ulDownSampledHeight = (pInfo->ulOriginalHeight * DOWNSAMPLE_DPI) / pInfo->ulXRes;
  4583. pInfo->ulDownSampledWidth = (pInfo->ulOriginalWidth * DOWNSAMPLE_DPI) / pInfo->ulXRes;
  4584. //
  4585. // NOTE: if the resolution is over 300dpi, our in-box WiaFBDrv driver has a problem
  4586. // with the chunk it is giving us, in that it doesn't hold enough pixel lines for us to
  4587. // downsample to 50dpi. For example if the input is at 600dpi and we want a 50dpi
  4588. // sample, we need at least 600 / 50 = 12 input lines to equal one output line.
  4589. // Since the chunk size cannot hold 12 lines, the ulDownSampledHeight becomes zero,
  4590. // and we cannot scale.
  4591. //
  4592. // So for now, we special case anything above 300 dpi
  4593. // to simply be 1/4 the width and height. This slows us down a lot at 600dpi,
  4594. // but cannot be solved without changes to the driver (and possibly adding
  4595. // some service helpers)
  4596. //
  4597. if (pInfo->ulXRes > 300) {
  4598. pInfo->ulDownSampledHeight = pInfo->ulOriginalHeight >> 2;
  4599. pInfo->ulDownSampledWidth = pInfo->ulOriginalWidth >> 2;
  4600. }
  4601. }
  4602. if ((pInfo->ulDownSampledHeight == 0) || (pInfo->ulOriginalHeight == 0)) {
  4603. DBG_WRN(("wiasDownSampleBuffer, height is zero, nothing to do..."));
  4604. return S_FALSE;
  4605. }
  4606. //
  4607. // We need to work out the DWORD aligned width in bytes. Normally we would do this in one step
  4608. // using the supplied bit depth, but we avoid arithmetic overflow conditions that happen
  4609. // in 24bit if we do it in 2 steps like this instead.
  4610. //
  4611. ULONG ulAlignedWidth;
  4612. if (pInfo->ulBitsPerPixel == 1) {
  4613. ulAlignedWidth = (pInfo->ulDownSampledWidth + 7) / 8;
  4614. } else {
  4615. ulAlignedWidth = (pInfo->ulDownSampledWidth * (pInfo->ulBitsPerPixel / 8));
  4616. }
  4617. ulAlignedWidth += (ulAlignedWidth % sizeof(DWORD)) ? (sizeof(DWORD) - (ulAlignedWidth % sizeof(DWORD))) : 0;
  4618. pInfo->ulActualSize = ulAlignedWidth * pInfo->ulDownSampledHeight;
  4619. //
  4620. // If the flag is WIAS_GET_DOWNSAMPLED_SIZE_ONLY, then all we've been requested to do is
  4621. // fill the above information in, so we return here.
  4622. //
  4623. if (lFlags == WIAS_GET_DOWNSAMPLED_SIZE_ONLY) {
  4624. return S_OK;
  4625. }
  4626. //
  4627. // If a destination buffer hasn't been given, then allocate one.
  4628. //
  4629. if (!pInfo->pDestBuffer) {
  4630. //
  4631. // NOTE: We allocate more than we actually need. This is to account for
  4632. // when the driver asks us to allocate on the first band, and then
  4633. // re-uses this buffer for the rest. Since the bands may change
  4634. // size, the pInfo->ulActualSize may be too small.
  4635. // It is recommended that the driver allocates the buffer instead,
  4636. // and that the size of this allocation is as large as the largest
  4637. // chunk it requests from the scanner, so that in the case of
  4638. // downsampling, this will always be larger than the downsampled
  4639. // pixels.
  4640. //
  4641. pInfo->pDestBuffer = (BYTE*)CoTaskMemAlloc(pInfo->ulActualSize * 2);
  4642. if (pInfo->pDestBuffer) {
  4643. pInfo->ulDestBufSize = pInfo->ulActualSize;
  4644. //
  4645. // Mark that we allocated the buffer
  4646. //
  4647. bAllocatedBuf = TRUE;
  4648. } else {
  4649. DBG_ERR(("wiasDownSampleBuffer, Out of memory"));
  4650. hr = E_OUTOFMEMORY;
  4651. }
  4652. } else {
  4653. if (IsBadWritePtr(pInfo->pDestBuffer, pInfo->ulActualSize)) {
  4654. DBG_ERR(("wiasDownSampleBuffer, cannot write ulActualSize bytes to pDestBuffer, it's too small!"));
  4655. hr = E_INVALIDARG;
  4656. }
  4657. }
  4658. //
  4659. // Validate source buffer
  4660. //
  4661. if (IsBadReadPtr(pInfo->pSrcBuffer, pInfo->ulSrcBufSize)) {
  4662. DBG_ERR(("wiasDownSampleBuffer, cannot read ulSrcBufSize bytes from pSrcBuffer!"));
  4663. return E_INVALIDARG;
  4664. }
  4665. if (SUCCEEDED(hr)) {
  4666. //
  4667. // Do the down sampling.
  4668. //
  4669. _try {
  4670. hr = BQADScale(pInfo->pSrcBuffer,
  4671. pInfo->ulOriginalWidth,
  4672. pInfo->ulOriginalHeight,
  4673. pInfo->ulBitsPerPixel,
  4674. pInfo->pDestBuffer,
  4675. pInfo->ulDownSampledWidth,
  4676. pInfo->ulDownSampledHeight);
  4677. }
  4678. _except (EXCEPTION_EXECUTE_HANDLER) {
  4679. DBG_ERR(("wiasDownSampleBuffer, Exception occurred while scaling!"));
  4680. hr = E_UNEXPECTED;
  4681. }
  4682. }
  4683. if (FAILED(hr) && bAllocatedBuf) {
  4684. //
  4685. // Free the buffer
  4686. //
  4687. CoTaskMemFree(pInfo->pDestBuffer);
  4688. pInfo->pDestBuffer = NULL;
  4689. }
  4690. return hr;
  4691. }
  4692. /**************************************************************************\
  4693. * wiasParseEndorserString
  4694. *
  4695. * This helper function is called by drivers to get the resulting endorser
  4696. * string. Applications set the WIA_DPS_ENDORSER_STRING property to
  4697. * a string that may contain tokens (e.g. $DATE$) which need to be replaced
  4698. * by the values they represent. For example, if the application set
  4699. * the endorser string to "This page was scanned on $DATE$", the resulting
  4700. * string would be "This page was scanned on 2000/10/1", assuming the date
  4701. * was October 1, 2000.
  4702. * The list of standard WIA endorser tokens can be found in wiadef.h.
  4703. * Also, drivers may ask wiasParseEndorserString to substitute their own
  4704. * values for custom tokens by filling out the appropriate WIAS_ENDORSER_INFO
  4705. * struct. For example:
  4706. *
  4707. * HRESULT hr = S_OK;
  4708. * BSTR bstrResultingEndorser = NULL;
  4709. *
  4710. * WIAS_ENDORSER_VALUE pMyValues[] = {L"$MY_TOKEN$", L"My value"};
  4711. * WIAS_ENDORSER_INFO weiInfo = {0, 1, pMyValues};
  4712. *
  4713. * hr = wiasParseEndorserString(pWiasContext, 0, &weiInfo, &bstrResultingEndorser);
  4714. * if (SUCCEEDED(hr)) {
  4715. * //
  4716. * // bstrResultingEndorser now contains the resulting endorser string.
  4717. * //
  4718. * }
  4719. *
  4720. * Arguments:
  4721. * pWiasContext - The context of the item containing the
  4722. * WIA_DPS_ENDORSER_STRING property.
  4723. * lFlags - Operational flags
  4724. * pInfo - Structure containing page count and custom list
  4725. * of token/value pairs. Can be NULL.
  4726. * pOutputString - Address of BSTR that receives the resulting
  4727. * endorser string. If (*pOutputString) is non-NULL
  4728. * on entry, then it is assumed the caller allocated
  4729. * the buffer, else the WIA service will allocate it.
  4730. * If the driver caller allocates the buffer, it
  4731. * should zero it out before using this function.
  4732. * If the buffer is not large enough to hold the
  4733. * resulting string, the resulting string will be truncated
  4734. * and copied into the buffer, and HRESULT_FROM_WIN32(ERROR_MORE_DATA)
  4735. * is returned.
  4736. *
  4737. * Return Value:
  4738. *
  4739. * Status
  4740. *
  4741. * History:
  4742. *
  4743. * 10/20/2000 Original Version
  4744. *
  4745. \**************************************************************************/
  4746. HRESULT _stdcall wiasParseEndorserString(
  4747. BYTE *pWiasContext,
  4748. LONG lFlags,
  4749. WIAS_ENDORSER_INFO *pInfo,
  4750. BSTR *pOutputString
  4751. )
  4752. {
  4753. DBG_FN(::wiasParseEndorserString);
  4754. WIAS_ENDORSER_INFO weiTempInfo;
  4755. BSTR bstrEndorser = NULL;
  4756. HRESULT hr = S_OK;
  4757. //
  4758. // Do some parameter validation
  4759. //
  4760. if (!pOutputString) {
  4761. DBG_ERR(("wiasParseEndorserString, pOutputString parameter cannot be NULL!"));
  4762. return E_INVALIDARG;
  4763. }
  4764. /*
  4765. if ((lFlags != 0) && (!(*pOutputString))) {
  4766. DBG_ERR(("wiasParseEndorserString, (*pOutputString) is NULL. lFlags is not 0, so you MUST specify your own output buffer!"));
  4767. return E_INVALIDARG;
  4768. }
  4769. */
  4770. if (!pInfo) {
  4771. memset(&weiTempInfo, 0, sizeof(weiTempInfo));
  4772. pInfo = &weiTempInfo;
  4773. }
  4774. if (pInfo->ulNumEndorserValues > 0) {
  4775. if (IsBadReadPtr(pInfo->pEndorserValues, sizeof(WIAS_ENDORSER_VALUE) * pInfo->ulNumEndorserValues)) {
  4776. DBG_ERR(("wiasParseEndorserString, cannot read %d values from pInfo->pEndorserValues!", pInfo->ulNumEndorserValues));
  4777. return E_INVALIDARG;
  4778. }
  4779. }
  4780. if (!pWiasContext) {
  4781. DBG_ERR(("wiasParseEndorserString, pWiasContext parameter is NULL!"));
  4782. return E_INVALIDARG;
  4783. }
  4784. //
  4785. // Read the endorser string
  4786. //
  4787. hr = wiasReadPropStr(pWiasContext, WIA_DPS_ENDORSER_STRING, &bstrEndorser, NULL, TRUE);
  4788. if (FAILED(hr)) {
  4789. //
  4790. // Maybe caller forgot to pass the correct item, so try getting the root item
  4791. // and reading from there.
  4792. //
  4793. BYTE *pRoot;
  4794. hr = wiasGetRootItem(pWiasContext, &pRoot);
  4795. if (SUCCEEDED(hr)) {
  4796. hr = wiasReadPropStr(pWiasContext, WIA_DPS_ENDORSER_STRING, &bstrEndorser, NULL, TRUE);
  4797. }
  4798. if (FAILED(hr)) {
  4799. return hr;
  4800. }
  4801. }
  4802. //
  4803. // If there is no endorser string value, return S_FALSE, because there's nothing
  4804. // for us to do.
  4805. //
  4806. if (!bstrEndorser)
  4807. {
  4808. return S_FALSE;
  4809. }
  4810. //
  4811. // Parse the string, substituting values for their tokens.
  4812. //
  4813. //
  4814. // Create a list of the Token/Value pairs. Remember to first add our
  4815. // default token/value pairs. These are:
  4816. // Date
  4817. // Time
  4818. // PageCount
  4819. // Day
  4820. // Month
  4821. // Year
  4822. //
  4823. SimpleTokenReplacement::TokenValueList EndorserList;
  4824. CSimpleStringWide cswTempToken;
  4825. CSimpleStringWide cswTempValue;
  4826. SYSTEMTIME sysTime;
  4827. GetLocalTime(&sysTime);
  4828. // Date
  4829. cswTempToken = WIA_ENDORSER_TOK_DATE;
  4830. cswTempValue.Format(L"%04d/%02d/%02d", sysTime.wYear, sysTime.wMonth, sysTime.wDay);
  4831. EndorserList.Add(cswTempToken, cswTempValue);
  4832. // Time
  4833. cswTempToken = WIA_ENDORSER_TOK_TIME;
  4834. cswTempValue.Format(L"%02d:%02d:%02d", sysTime.wHour, sysTime.wMinute, sysTime.wSecond);
  4835. EndorserList.Add(cswTempToken, cswTempValue);
  4836. // Page Count
  4837. cswTempToken = WIA_ENDORSER_TOK_PAGE_COUNT;
  4838. cswTempValue.Format(L"%03d", pInfo->ulPageCount);
  4839. EndorserList.Add(cswTempToken, cswTempValue);
  4840. // Day
  4841. cswTempToken = WIA_ENDORSER_TOK_DAY;
  4842. cswTempValue.Format(L"%02d", sysTime.wDay);
  4843. EndorserList.Add(cswTempToken, cswTempValue);
  4844. // Month
  4845. cswTempToken = WIA_ENDORSER_TOK_MONTH;
  4846. cswTempValue.Format(L"%02d", sysTime.wMonth);
  4847. EndorserList.Add(cswTempToken, cswTempValue);
  4848. // Year
  4849. cswTempToken = WIA_ENDORSER_TOK_YEAR;
  4850. cswTempValue.Format(L"%04d", sysTime.wYear);
  4851. EndorserList.Add(cswTempToken, cswTempValue);
  4852. //
  4853. // Next, we need to add any vendor defined token/value pairs
  4854. //
  4855. for (DWORD dwIndex = 0; dwIndex < pInfo->ulNumEndorserValues; dwIndex++)
  4856. {
  4857. cswTempToken = pInfo->pEndorserValues[dwIndex].wszTokenName;
  4858. cswTempValue = pInfo->pEndorserValues[dwIndex].wszValue;
  4859. EndorserList.Add(cswTempToken, cswTempValue);
  4860. }
  4861. //
  4862. // Now, let's make the substitutions
  4863. //
  4864. SimpleTokenReplacement EndorserResult(bstrEndorser);
  4865. EndorserResult.ExpandArrayOfTokensIntoString(EndorserList);
  4866. //
  4867. // We have the result. Let's see whether we need to allocate it, or
  4868. // whether whether one was provided and we should simply copy the contents
  4869. //
  4870. if (!(*pOutputString))
  4871. {
  4872. *pOutputString = SysAllocString(EndorserResult.getString().String());
  4873. if (!(*pOutputString))
  4874. {
  4875. DBG_ERR(("wiasParseEndorserString, could not allocate space for the endorser string - we are out of memory."));
  4876. hr = E_OUTOFMEMORY;
  4877. }
  4878. }
  4879. else
  4880. {
  4881. //
  4882. // The caller provided a pre-allocated BSTR. Copy as much of the endorser as can fit into
  4883. // this buffer. If it cannot fit, return HRESULT_FROM_WIN32(ERROR_MORE_DATA)
  4884. //
  4885. DWORD dwAllocatedLen = SysStringLen(*pOutputString); // This does NOT include the NULL
  4886. wcsncpy(*pOutputString, EndorserResult.getString().String(), dwAllocatedLen);
  4887. if (EndorserResult.getString().Length() > dwAllocatedLen)
  4888. {
  4889. DBG_ERR(("wiasParseEndorserString, the caller allocated BSTR is too small! String will be truncated."));
  4890. hr = HRESULT_FROM_WIN32(ERROR_MORE_DATA);
  4891. }
  4892. //
  4893. // Make sure we NULL terminate this BSTR. Remember that dwAllocatedLen is the size in WHCARs of the
  4894. // allocated string, not including the space for the NULL.
  4895. //
  4896. (*pOutputString)[dwAllocatedLen] = L'\0';
  4897. }
  4898. return hr;
  4899. }