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.

1713 lines
56 KiB

  1. /*******************************************************************************
  2. *
  3. * (C) COPYRIGHT MICROSOFT CORP., 2000
  4. *
  5. * TITLE: IStiUSD.cpp
  6. *
  7. * VERSION: 1.0
  8. *
  9. * DATE: 18 July, 2000
  10. *
  11. * DESCRIPTION:
  12. * Implementation of the WIA sample scanner IStiUSD methods.
  13. *
  14. *******************************************************************************/
  15. #include "pch.h"
  16. #ifndef INITGUID
  17. #include <initguid.h>
  18. #endif
  19. extern HINSTANCE g_hInst; // used for WIAS_LOGPROC macro
  20. /**************************************************************************\
  21. * CWIADevice::CWIADevice
  22. *
  23. * Device class constructor
  24. *
  25. * Arguments:
  26. *
  27. * None
  28. *
  29. * Return Value:
  30. *
  31. * None
  32. *
  33. * History:
  34. *
  35. * 03/05/2002 Original Version
  36. *
  37. \**************************************************************************/
  38. CWIADevice::CWIADevice(LPUNKNOWN punkOuter):
  39. m_cRef(1),
  40. m_punkOuter(NULL),
  41. m_dwLastOperationError(0),
  42. m_dwLockTimeout(DEFAULT_LOCK_TIMEOUT),
  43. m_bDeviceLocked(FALSE),
  44. m_hDeviceDataHandle(NULL),
  45. m_bPolledEvent(FALSE),
  46. m_hFakeEventKey(NULL),
  47. m_guidLastEvent(GUID_NULL),
  48. m_pIDrvItemRoot(NULL),
  49. m_pStiDevice(NULL),
  50. m_pIWiaLog(NULL),
  51. m_bADFEnabled(FALSE),
  52. m_bADFAttached(TRUE),
  53. m_lClientsConnected(0),
  54. m_pScanAPI(NULL),
  55. m_NumSupportedFormats(0),
  56. m_pSupportedFormats(NULL),
  57. m_NumSupportedCommands(0),
  58. m_NumSupportedEvents(0),
  59. m_pCapabilities(NULL),
  60. m_NumInitialFormats(0),
  61. m_pInitialFormats(NULL)
  62. {
  63. //
  64. // initialize internal structures
  65. //
  66. memset(&m_EventOverlapped,0,sizeof(m_EventOverlapped));
  67. memset(m_EventData,0,sizeof(m_EventData));
  68. memset(&m_SupportedTYMED,0,sizeof(m_SupportedTYMED));
  69. memset(&m_SupportedDataTypes,0,sizeof(m_SupportedDataTypes));
  70. memset(&m_SupportedIntents,0,sizeof(m_SupportedIntents));
  71. memset(&m_SupportedCompressionTypes,0,sizeof(m_SupportedCompressionTypes));
  72. memset(&m_SupportedResolutions,0,sizeof(m_SupportedResolutions));
  73. memset(&m_SupportedPreviewModes,0,sizeof(m_SupportedPreviewModes));
  74. memset(&m_RootItemInitInfo,0,sizeof(m_RootItemInitInfo));
  75. memset(&m_ChildItemInitInfo,0,sizeof(m_ChildItemInitInfo));
  76. // See if we are aggregated. If we are (almost always the case) save
  77. // pointer to the controlling Unknown , so subsequent calls will be
  78. // delegated. If not, set the same pointer to "this".
  79. if (punkOuter) {
  80. m_punkOuter = punkOuter;
  81. } else {
  82. // Cast below is needed in order to point to right virtual table
  83. m_punkOuter = reinterpret_cast<IUnknown*>(static_cast<INonDelegatingUnknown*>(this));
  84. }
  85. #ifdef UNKNOWN_LENGTH_FEEDER_ONLY_SCANNER
  86. //
  87. // since this driver supports a scanner that has only a feeder, the
  88. // ADF Enabled flag needs to be set to TRUE by default. This will
  89. // control the behavior of DrvAcquireItemData() method.
  90. //
  91. m_bADFEnabled = TRUE;
  92. #endif
  93. }
  94. /**************************************************************************\
  95. * CWIADevice::~CWIADevice
  96. *
  97. * Device class destructor
  98. *
  99. * Arguments:
  100. *
  101. * None
  102. *
  103. * Return Value:
  104. *
  105. * None
  106. *
  107. * History:
  108. *
  109. * 03/05/2002 Original Version
  110. *
  111. \**************************************************************************/
  112. CWIADevice::~CWIADevice(void)
  113. {
  114. SetNotificationHandle(NULL);
  115. //
  116. // WIA member destruction
  117. //
  118. // Tear down the driver item tree.
  119. if (m_pIDrvItemRoot) {
  120. WIAS_LWARNING(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("~CWIADevice, Deleting Device Item Tree (this is OK)"));
  121. DeleteItemTree();
  122. m_pIDrvItemRoot = NULL;
  123. }
  124. // free any IO handles opened
  125. if (m_hDeviceDataHandle) {
  126. WIAS_LWARNING(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("~CWIADevice, Closing DefaultDeviceDataHandle"));
  127. CloseHandle(m_hDeviceDataHandle);
  128. m_hDeviceDataHandle = NULL;
  129. }
  130. // Delete allocated arrays
  131. DeleteCapabilitiesArrayContents();
  132. DeleteSupportedIntentsArrayContents();
  133. if (m_pIWiaLog)
  134. m_pIWiaLog->Release();
  135. if (m_pScanAPI) {
  136. // disable fake scanner device
  137. m_pScanAPI->FakeScanner_DisableDevice();
  138. delete m_pScanAPI;
  139. m_pScanAPI = NULL;
  140. }
  141. }
  142. /**************************************************************************\
  143. * CWIADevice::PrivateInitialize()
  144. *
  145. * PrivateInitialize is called from the CreateInstance() method of the
  146. * WIA driver's class factory. It is needed to initialize the WIA
  147. * driver object (CWIADevice). If this initialization fails the
  148. * object will not be returned to the caller. This prevents the creation
  149. * of a nonfunctional WIA device.
  150. *
  151. * Arguments:
  152. *
  153. * None
  154. *
  155. * Return Value:
  156. *
  157. * S_OK - if the operation succeeded
  158. * E_xxx - Error code if the operation fails
  159. *
  160. \**************************************************************************/
  161. HRESULT CWIADevice::PrivateInitialize()
  162. {
  163. //
  164. // attempt to create the IWiaLog interface to log status and errors to
  165. // wiaservc.log file
  166. //
  167. HRESULT hr = CoCreateInstance(CLSID_WiaLog, NULL, CLSCTX_INPROC_SERVER,IID_IWiaLog,(void**)&m_pIWiaLog);
  168. if (S_OK == hr) {
  169. m_pIWiaLog->InitializeLog((LONG)(LONG_PTR)g_hInst);
  170. WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL1,("Logging COM object created successfully for wiascanr.dll"));
  171. } else {
  172. WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL1,("Logging COM object not be created successfully for wiascanr.dll (STI only?)"));
  173. hr = S_OK;
  174. }
  175. return hr;
  176. }
  177. /**************************************************************************\
  178. * CWIADevice::Initialize
  179. *
  180. * Initialize is called by the WIA service when the driver is first loaded.
  181. * Initialize is also called when a client uses the legacy STI APIs and
  182. * calls IStillImage::CreateDevice() method.
  183. *
  184. * This method should initialize the WIA driver and the device for use.
  185. * WIA drivers can store the pIStiDevControl interface if it needs it at a
  186. * later time. IStiDevControl::AddRef() must be called before storing this
  187. * interface. If you do not need to store the interface, then ignore it.
  188. * DO NOT RELEASE the IStiDevControl interface if you have not called
  189. * IStiDevControl::AddRef() first. This may cause unpredictable results.
  190. *
  191. * The IStiDeviceControl interface is needed to get information about your
  192. * device's ports. The port name used in a CreateFile call can be obtained
  193. * by calling the IStiDeviceControl::GetMyDevicePortName() method.
  194. *
  195. * For devices on shared ports, such as serial port devices, opening the port
  196. * in Initialize() is not recommended. The port should only be opened in calls
  197. * to IStiUsd::LockDevice(). The closing of the ports should be internally
  198. * controlled to provide fast access. (opening and closing in
  199. * LockDevice/UnLockDevice is very inefficent. CreateFile() could cause a delay
  200. * making the user's experience appear slow, and nonresponsive)
  201. *
  202. * If this WIA driver can not support multiple CreateFile() calls on the same
  203. * device port, then the IStiDevControl::GetMyDeviceOpenMode() should be called.
  204. *
  205. * The WIA driver should check the returned MODE value for the flag
  206. * STI_DEVICE_CREATE_DATA and open the port accordingly.
  207. *
  208. * The following flags could be set:
  209. *
  210. * STI_DEVICE_CREATE_STATUS - open port for status
  211. * STI_DEVICE_CREATE_DATA - open port for data
  212. * STI_DEVICE_CREATE_BOTH - open port for status and data
  213. *
  214. * If the device port needs to be opened, a call to CreateFile() should be
  215. * used. When opening a port the flag FILE_FLAG_OVERLAPPED should be used.
  216. * This will allow OVERLAPPED i/o to be used when access the device. Using
  217. * OVERLAPPED i/o will help control responsive access to the hardware. When
  218. * a problem is detected the WIA driver can call CancelIo() to stop all
  219. * current hardware access.
  220. *
  221. * Arguments:
  222. *
  223. * pIStiDevControl - device interface used for obtaining port information
  224. * dwStiVersion - STI version
  225. * hParametersKey - HKEY for registry reading/writing
  226. *
  227. * Return Value:
  228. *
  229. * S_OK - if the operation was successful
  230. * E_xxx - if the operation failed
  231. *
  232. * History:
  233. *
  234. * 03/05/2002 Original Version
  235. *
  236. \**************************************************************************/
  237. STDMETHODIMP CWIADevice::Initialize(
  238. PSTIDEVICECONTROL pIStiDevControl,
  239. DWORD dwStiVersion,
  240. HKEY hParametersKey)
  241. {
  242. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  243. WIALOG_NO_RESOURCE_ID,
  244. WIALOG_LEVEL3,
  245. "CWIADevice::Initialize");
  246. if (!pIStiDevControl) {
  247. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CWIADevice::Initialize, invalid device control interface"));
  248. return STIERR_INVALID_PARAM;
  249. }
  250. HRESULT hr = S_OK;
  251. //
  252. // Get the mode of the device to check why we were created. status, data, or both...
  253. //
  254. DWORD dwMode = 0;
  255. hr = pIStiDevControl->GetMyDeviceOpenMode(&dwMode);
  256. if(FAILED(hr)){
  257. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CWIADevice::Initialize, couldn't get device open mode"));
  258. return hr;
  259. }
  260. if(dwMode & STI_DEVICE_CREATE_DATA)
  261. {
  262. //
  263. // device is being opened for data
  264. //
  265. }
  266. if(dwMode & STI_DEVICE_CREATE_STATUS)
  267. {
  268. //
  269. // device is being opened for status
  270. //
  271. }
  272. if(dwMode & STI_DEVICE_CREATE_BOTH)
  273. {
  274. //
  275. // device is being opened for both data and status
  276. //
  277. }
  278. //
  279. // Get the name of the device port to be used in a call to CreateFile().
  280. //
  281. WCHAR szDevicePortNameW[MAX_PATH];
  282. memset(szDevicePortNameW,0,sizeof(szDevicePortNameW));
  283. hr = pIStiDevControl->GetMyDevicePortName(szDevicePortNameW,sizeof(szDevicePortNameW)/sizeof(WCHAR));
  284. if(FAILED(hr)) {
  285. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CWIADevice::Initialize, couldn't get device port"));
  286. return hr;
  287. }
  288. //
  289. // uncomment the code block below to have the driver create the kernel mode file
  290. // handles and open a communication channel to the device.
  291. //
  292. /*
  293. //
  294. // Open kernel mode device driver. Use the FILE_FLAG_OVERLAPPED flag for proper cancellation
  295. // of kernel mode operations and asynchronous file IO. The CancelIo() call will function
  296. // properly if this flag is used. It is recommended to use this flag.
  297. //
  298. m_hDeviceDataHandle = CreateFileW(szDevicePortNameW,
  299. GENERIC_READ | GENERIC_WRITE, // Access mask
  300. 0, // Share mode
  301. NULL, // SA
  302. OPEN_EXISTING, // Create disposition
  303. FILE_ATTRIBUTE_SYSTEM|FILE_FLAG_OVERLAPPED, // Attributes
  304. NULL );
  305. m_dwLastOperationError = ::GetLastError();
  306. hr = (m_hDeviceDataHandle != INVALID_HANDLE_VALUE) ?
  307. S_OK : MAKE_HRESULT(SEVERITY_ERROR,FACILITY_WIN32,m_dwLastOperationError);
  308. if (FAILED(hr)) {
  309. return hr;
  310. }
  311. */
  312. if (SUCCEEDED(hr)) {
  313. //
  314. // creation of fake scanner device is here.
  315. //
  316. #ifdef UNKNOWN_LENGTH_FEEDER_ONLY_SCANNER
  317. hr = CreateFakeScanner(&m_pScanAPI,UNKNOWN_FEEDER_ONLY_SCANNER_MODE);
  318. #else
  319. hr = CreateFakeScanner(&m_pScanAPI,FLATBED_SCANNER_MODE);
  320. #endif
  321. if (m_pScanAPI) {
  322. //
  323. // initialize fake scanner device
  324. //
  325. hr = m_pScanAPI->FakeScanner_Initialize();
  326. } else {
  327. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("Initialize, Could not create FakeScanner API object"));
  328. hr = E_OUTOFMEMORY;
  329. WIAS_LHRESULT(m_pIWiaLog, hr);
  330. }
  331. }
  332. //
  333. // Open DeviceData section to read driver specific information
  334. //
  335. HKEY hKey = hParametersKey;
  336. HKEY hOpenKey = NULL;
  337. if (RegOpenKeyEx(hKey, // handle to open key
  338. TEXT("DeviceData"), // address of name of subkey to open
  339. 0, // options (must be NULL)
  340. KEY_QUERY_VALUE|KEY_READ, // just want to QUERY a value
  341. &hOpenKey // address of handle to open key
  342. ) == ERROR_SUCCESS) {
  343. //
  344. // This is where you read registry entries for your device.
  345. // The DeviceData section is the proper place to put this information. Information about
  346. // your device should have been written using the WIA device's .INF installation file.
  347. // You can access this information from this location in the Registry.
  348. // The hParameters HKEY is owned by the WIA service. DO NOT CLOSE THIS KEY. Always close
  349. // any HKEYS opened by this WIA driver after you are finished.
  350. //
  351. //
  352. // close registry key when finished, reading DeviceData information.
  353. //
  354. RegCloseKey(hOpenKey);
  355. } else {
  356. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CWIADevice::Initialize, couldn't open DeviceData KEY"));
  357. return E_FAIL;
  358. }
  359. return hr;
  360. }
  361. /**************************************************************************\
  362. * CWIADevice::GetCapabilities
  363. *
  364. * GetCapabilities is called by the WIA service to obtain the USD's
  365. * capabilities. The WIA driver should fill out the following fields in the
  366. * STI_USD_CAPS structure:
  367. *
  368. * 1. dwVersion field with STI_VERSION letting the WIA service know what
  369. * version of STI this driver supports.
  370. * 2. dwGenericCaps field with supported capabilities of the WIA device.
  371. *
  372. *
  373. * Arguments:
  374. *
  375. * pUsdCaps - Pointer to a STI_USD_CAPS USD capabilities structure.
  376. *
  377. * Return Value:
  378. *
  379. * S_OK - if the data can be written correctly
  380. * E_xxx - Error code if the operation fails
  381. *
  382. *
  383. * Remarks:
  384. *
  385. * This WIA driver sets the following capability flags:
  386. *
  387. * 1. STI_GENCAP_WIA - This driver supports WIA
  388. * 2. STI_USD_GENCAP_NATIVE_PUSHSUPPORT - This driver supports push buttons
  389. * 3. STI_GENCAP_NOTIFICATIONS - This driver requires the use of interrupt
  390. * events.
  391. *
  392. * History:
  393. *
  394. * 03/05/2002 Original Version
  395. *
  396. \**************************************************************************/
  397. STDMETHODIMP CWIADevice::GetCapabilities(PSTI_USD_CAPS pUsdCaps)
  398. {
  399. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  400. WIALOG_NO_RESOURCE_ID,
  401. WIALOG_LEVEL3,
  402. "CWIADevice::GetCapabilities");
  403. //
  404. // If the caller did not pass in the correct parameters, then fail the
  405. // call with E_INVALIDARG.
  406. //
  407. if (!pUsdCaps) {
  408. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CWIADevice::GetCapabilities, NULL parameter"));
  409. return E_INVALIDARG;
  410. }
  411. memset(pUsdCaps, 0, sizeof(STI_USD_CAPS));
  412. pUsdCaps->dwVersion = STI_VERSION; // STI verison
  413. pUsdCaps->dwGenericCaps = STI_GENCAP_WIA| // WIA support
  414. STI_USD_GENCAP_NATIVE_PUSHSUPPORT| // button support
  415. STI_GENCAP_NOTIFICATIONS; // interrupt event support
  416. return S_OK;
  417. }
  418. /**************************************************************************\
  419. * CWIADevice::GetStatus
  420. *
  421. * GetStatus is called by the WIA service for two major operations:
  422. *
  423. * 1. Checking device ON-LINE status.
  424. * 2. Polling for device events. (like a push button event)
  425. *
  426. * Determining the operation request can be done by checking the StatusMask
  427. * field of the STI_DEVICE_STATUS structure. The StatusMask field can be
  428. * any of the following requests. (STI_DEVSTATUS_ONLINE_STATE or
  429. * STI_DEVSTATUS_EVENTS_STATE)
  430. *
  431. * STI_DEVSTATUS_ONLINE_STATE = check if the device is ON-LINE.
  432. *
  433. * This operation request should be fill by setting the dwOnlinesState
  434. * field of the STI_DEVICE_STATUS structure.
  435. * Value that should be used are:
  436. *
  437. * STI_ONLINESTATE_OPERATIONAL - Device is ON-LINE and operational
  438. * STI_ONLINESTATE_OFFLINE - Device is OFF-LINE and NOT operational
  439. * STI_ONLINESTATE_PENDING - Device has I/O operations pending
  440. * STI_ONLINESTATE_ERROR - Device is currently in an error state
  441. * STI_ONLINESTATE_PAUSED - Device is paused
  442. * STI_ONLINESTATE_PAPER_JAM - Device has a paper jam
  443. * STI_ONLINESTATE_PAPER_PROBLEM - Device has a paper problem
  444. * STI_ONLINESTATE_IO_ACTIVE - Device is active, but not accepting
  445. * commands at this time
  446. * STI_ONLINESTATE_BUSY - Device is busy
  447. * STI_ONLINESTATE_TRANSFERRING - Device is currently transferring data
  448. * STI_ONLINESTATE_INITIALIZING - Device is being initialized
  449. * STI_ONLINESTATE_WARMING_UP - Device is warming up
  450. * STI_ONLINESTATE_USER_INTERVENTION - Device requires user intervention
  451. * to resolve a problem
  452. * STI_ONLINESTATE_POWER_SAVE - Device is in power save mode
  453. *
  454. *
  455. * STI_DEVSTATUS_EVENTS_STATE = check for device events.
  456. *
  457. * This operation request should be filled by setting the dwEventHandlingState
  458. * field of the STI_DEVICE_STATUS structure.
  459. * Values that should be used are:
  460. *
  461. * STI_EVENTHANDLING_PENDING - Device has an event pending and is wanting
  462. * to report it to the WIA service.
  463. *
  464. * It is always a good idea to clear the STI_EVENTHANDLING_PENDING flag from
  465. * the dwEventHandlingState member to make sure that it is properly set when
  466. * a device event occurs.
  467. *
  468. * When the STI_EVENTHANDLING_PENDING is set the WIA service is signaled that
  469. * an event has occured in the WIA driver. The WIA service calls the
  470. * GetNotificationData() entry point to get more information about the event.
  471. * GetNotificationData() is called for polled events and interrupt events.
  472. * This is where you should fill out the proper event information to return to
  473. * the WIA service.
  474. *
  475. *
  476. * Arguments:
  477. *
  478. * pDevStatus - Pointer to a STI_DEVICE_STATUS device status structure.
  479. *
  480. * Return Value:
  481. *
  482. * S_OK - if the data can be written correctly
  483. * E_INVALIDARG - if an invalid parameter was passed in to the GetStatus
  484. * method.
  485. * E_xxx - Error code if the operation fails
  486. *
  487. *
  488. * Remarks:
  489. *
  490. * This WIA driver should set the m_guidLastEvent to the proper event GUID when
  491. * an event is detected. It should also set the m_bPolledEvent flag to TRUE
  492. * indicating that the event was received from a "polled source" (the GetStatus()
  493. * call). The m_guidLastEvent is checked at a later time when the WIA service
  494. * calls GetNotificationData().
  495. *
  496. * History:
  497. *
  498. * 03/05/2002 Original Version
  499. *
  500. \**************************************************************************/
  501. STDMETHODIMP CWIADevice::GetStatus(PSTI_DEVICE_STATUS pDevStatus)
  502. {
  503. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  504. WIALOG_NO_RESOURCE_ID,
  505. WIALOG_LEVEL3,
  506. "CWIADevice::GetStatus");
  507. //
  508. // If the caller did not pass in the correct parameters, then fail the
  509. // call with E_INVALIDARG.
  510. //
  511. if(!pDevStatus)
  512. {
  513. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CWIADevice::GetStatus, NULL parameter"));
  514. return E_INVALIDARG;
  515. }
  516. HRESULT hr = S_OK;
  517. //
  518. // If we are asked, verify the device is online.
  519. //
  520. if (pDevStatus->StatusMask & STI_DEVSTATUS_ONLINE_STATE) {
  521. WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("GetStatus, WIA is asking the device if we are ONLINE"));
  522. //
  523. // assume the device is OFF-LINE before continuing. This will validate
  524. // that the on-line check was successful.
  525. //
  526. pDevStatus->dwOnlineState = STI_ONLINESTATE_OFFLINE;
  527. hr = m_pScanAPI->FakeScanner_DeviceOnline();
  528. if (SUCCEEDED(hr)) {
  529. WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("GetStatus, Device is ONLINE"));
  530. //
  531. // device is ON-LINE and operational
  532. //
  533. pDevStatus->dwOnlineState |= STI_ONLINESTATE_OPERATIONAL;
  534. } else {
  535. //
  536. // device is OFF-LINE and NOT operational
  537. //
  538. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("GetStatus, Device is OFFLINE"));
  539. }
  540. }
  541. //
  542. // If we are asked, verify state of an event handler (front panel buttons, user controlled attachments, etc..).
  543. //
  544. //
  545. // If your device requires polling, then this is where you would specify the event
  546. // result.
  547. //
  548. // *** It is not recommended to have polled events. Interrupt events are better
  549. // for performance, and reliability. See the SetNotificationsHandle() method for how to
  550. // implement interrupt events.
  551. //
  552. //
  553. // clear the dwEventHandlingState field first to make sure we are really setting
  554. // a pending event.
  555. //
  556. pDevStatus->dwEventHandlingState &= ~STI_EVENTHANDLING_PENDING;
  557. if (pDevStatus->StatusMask & STI_DEVSTATUS_EVENTS_STATE) {
  558. //
  559. // set the polled event source flag to true, because this will control the
  560. // behavior of the GetNotificationData() method.
  561. //
  562. m_bPolledEvent = TRUE;
  563. //
  564. // set the polled event result here, for the GetNotificationData() method to
  565. // read and report.
  566. //
  567. m_guidLastEvent = GUID_NULL; // WIA_EVENT_SCAN_IMAGE is an example of an event GUID
  568. if (m_guidLastEvent != GUID_NULL) {
  569. //
  570. // if the event GUID is NOT GUID_NULL, set the STI_EVENTHANDLING_PENDING flag
  571. // letting the WIA service know that we have an event ready. This will tell
  572. // the WIA service to call GetNotificationData() for the event specific information.
  573. //
  574. pDevStatus->dwEventHandlingState |= STI_EVENTHANDLING_PENDING;
  575. }
  576. }
  577. return S_OK;
  578. }
  579. /**************************************************************************\
  580. * CWIADevice::DeviceReset
  581. *
  582. * DeviceReset is called to reset the device to a power-on state.
  583. *
  584. * Arguments:
  585. *
  586. * None
  587. *
  588. * Return Value:
  589. *
  590. * S_OK - if device reset was successful
  591. * E_xxx - Error code if the operation fails
  592. *
  593. * History:
  594. *
  595. * 03/05/2002 Original Version
  596. *
  597. \**************************************************************************/
  598. STDMETHODIMP CWIADevice::DeviceReset(void)
  599. {
  600. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  601. WIALOG_NO_RESOURCE_ID,
  602. WIALOG_LEVEL3,
  603. "CWIADevice::DeviceReset");
  604. if(!m_pScanAPI){
  605. return E_UNEXPECTED;
  606. }
  607. return m_pScanAPI->FakeScanner_ResetDevice();
  608. }
  609. /**************************************************************************\
  610. * CWIADevice::Diagnostic
  611. *
  612. * Diagnostic is called when the device needs to be tested. The device
  613. * default property page "Test Device" button calls this method.
  614. *
  615. * The WIA driver should set the following fields of the STI_DIAG structure:
  616. * sErrorInfo - error information contained in a STI_ERROR_INFO structure,
  617. * detailing the test results of the the diagnostic method.
  618. * The WIA device should set the following members:
  619. * dwGenericError - set to NOERROR if the device passed
  620. * the diagnostic test, or to an error
  621. * code if the device failed the test.
  622. * dwVendorError - set this to give more information
  623. * about the failure. Remember that
  624. * this code is specific to this device
  625. * only. The caller of Diagnostic will
  626. * not know the meaning of this vendor-
  627. * specific code.
  628. * szExtendedErrorText - Extended error text. This member
  629. * is limited to 255 characters.
  630. * dwBasicDiagCode - this code indicates the type of test to be performed.
  631. * Currently this must be set to STI_DIAGCODE_HWPRESENCE.
  632. * dwVendorDiagCode - OPTIONAL - vendor supplied diagnostic test code.
  633. * dwStatusMask - RESERVED FOR FUTURE USE
  634. *
  635. * Arguments:
  636. *
  637. * pBuffer - Pointer to a STI_DIAG diagnostic result structure.
  638. *
  639. * Return Value:
  640. *
  641. * S_OK - if the data can be written correctly
  642. * E_xxx - Error code if the operation fails
  643. *
  644. * History:
  645. *
  646. * 03/05/2002 Original Version
  647. *
  648. \**************************************************************************/
  649. STDMETHODIMP CWIADevice::Diagnostic(LPSTI_DIAG pBuffer)
  650. {
  651. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  652. WIALOG_NO_RESOURCE_ID,
  653. WIALOG_LEVEL3,
  654. "CWIADevice::Diagnostic");
  655. //
  656. // If the caller did not pass in the correct parameters, then fail the
  657. // call with E_INVALIDARG.
  658. //
  659. if(!pBuffer){
  660. return E_INVALIDARG;
  661. }
  662. if(!m_pScanAPI){
  663. return E_UNEXPECTED;
  664. }
  665. //
  666. // initialize response buffer
  667. //
  668. memset(&pBuffer->sErrorInfo,0,sizeof(pBuffer->sErrorInfo));
  669. //
  670. // This sample device does nothing during this diagnostic method call.
  671. // It is recommended to perform a quick test of the hardware to verify
  672. // that it is functional within operational parameters.
  673. //
  674. pBuffer->sErrorInfo.dwGenericError = NOERROR;
  675. pBuffer->sErrorInfo.dwVendorError = 0;
  676. return m_pScanAPI->FakeScanner_Diagnostic();
  677. }
  678. /**************************************************************************\
  679. * CWIADevice::Escape
  680. *
  681. * Escape is called to pass information directly to the hardware. This
  682. * method can be called directly using the original STI (legacy) APIs or
  683. * the IWiaItemExtras::Escape() method.
  684. * Any WIA application can obtain access to the IWiaItemExtras interface.
  685. * It is recommended that you validate all incoming and outgoing calls to
  686. * this method.
  687. *
  688. * Recommended validation order:
  689. * 1. validate the Function code first. If it is not one your codes, fail
  690. * immediately. This will help to prevent incorrect codes from being
  691. * processed in your driver.
  692. * 2. validate the incoming buffer second. If it is not valid, fail
  693. * immediately. Bad incoming buffers coulsd crash the WIA driver.
  694. * 3. validate the outgoing buffer third. If it is not valid, fail
  695. * immediately. If you can not complete the request by writing the
  696. * necessary data why process it?
  697. * 4. validate the outgoing size buffer last. This is important. If you can
  698. * not write the amount of data you just wrote to the outgoing buffer
  699. * then that data can not be properly processed by the caller.
  700. *
  701. * Arguments:
  702. *
  703. * EscapeFunction - Command to be issued.
  704. * pInData - Input data to be passed with command.
  705. * cbInDataSize - Size of input data.
  706. * pOutData - Output data to be passed back from command.
  707. * cbOutDataSize - Size of output data buffer.
  708. * pcbActualData - Size of output data actually written.
  709. *
  710. * Return Value:
  711. *
  712. * S_OK - if the operation was successful
  713. * E_xxx - Error code if the operation fails
  714. *
  715. * History:
  716. *
  717. * 03/05/2002 Original Version
  718. *
  719. \**************************************************************************/
  720. STDMETHODIMP CWIADevice::Escape(
  721. STI_RAW_CONTROL_CODE EscapeFunction,
  722. LPVOID pInData,
  723. DWORD cbInDataSize,
  724. LPVOID pOutData,
  725. DWORD cbOutDataSize,
  726. LPDWORD pcbActualData)
  727. {
  728. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  729. WIALOG_NO_RESOURCE_ID,
  730. WIALOG_LEVEL3,
  731. "CWIADevice::Escape");
  732. //
  733. // only process EscapeFunction codes that are known to your driver.
  734. // Any application can send escape calls to your driver using the
  735. // IWiaItemExtras interface Escape() method call. The driver must
  736. // be prepared to validate all incoming calls to Escape().
  737. //
  738. //
  739. // since this driver does not support any escape functions it will reject all
  740. // incoming EscapeFunction codes.
  741. //
  742. // If your driver supports an EscapeFunction, then add your function code to the
  743. // switch statement, and set hr = S_OK. This will allow the function to continue
  744. // to the incoming/outgoing buffer validation.
  745. //
  746. HRESULT hr = E_NOTIMPL;
  747. switch(EscapeFunction){
  748. case 0:
  749. default:
  750. break;
  751. }
  752. //
  753. // if an EscapeFunction code is supported, then first validate the incoming and
  754. // outgoing buffers.
  755. //
  756. if(S_OK == hr){
  757. //
  758. // validate the incoming data buffer
  759. //
  760. if(IsBadReadPtr(pInData,cbInDataSize)){
  761. hr = E_UNEXPECTED;
  762. }
  763. //
  764. // if the incoming buffer is valid, proceed to validate the
  765. // outgoing buffer
  766. //
  767. if(S_OK == hr){
  768. if(IsBadWritePtr(pOutData,cbOutDataSize)){
  769. hr = E_UNEXPECTED;
  770. } else {
  771. //
  772. // validate the outgoing size pointer
  773. //
  774. if(IsBadWritePtr(pcbActualData,sizeof(DWORD))){
  775. hr = E_UNEXPECTED;
  776. }
  777. }
  778. }
  779. //
  780. // now that buffer validation is complete, proceed to process the proper
  781. // EscapeFunction code.
  782. //
  783. if (S_OK == hr) {
  784. //
  785. // only process a validated EscapeFunction code, and buffers
  786. //
  787. }
  788. }
  789. //
  790. // if your driver will not support this entry point then it needs to return
  791. // E_NOTIMPL. (error, not implemented)
  792. //
  793. return hr;
  794. }
  795. /**************************************************************************\
  796. * CWIADevice::GetLastError
  797. *
  798. * GetLastError is called to obtain the last operation error code reported
  799. * by the WIA device. This is an error code that is specific to the WIA
  800. * driver. If the caller wants more information about this error code then
  801. * they will call GetLastErrorInfo(). The GetLastErrorInfo() method is
  802. * responsible for adding more details about the requested error. (strings,
  803. * extended codes...etc)
  804. *
  805. * Arguments:
  806. *
  807. * pdwLastDeviceError - Pointer to a DWORD indicating the last error code.
  808. *
  809. * Return Value:
  810. *
  811. * S_OK - if the data can be written correctly
  812. * E_xxx - Error code if the operation fails
  813. *
  814. * History:
  815. *
  816. * 03/05/2002 Original Version
  817. *
  818. \**************************************************************************/
  819. STDMETHODIMP CWIADevice::GetLastError(LPDWORD pdwLastDeviceError)
  820. {
  821. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  822. WIALOG_NO_RESOURCE_ID,
  823. WIALOG_LEVEL3,
  824. "CWIADevice::GetLastError");
  825. //
  826. // If the caller did not pass in the correct parameters, then fail the
  827. // call with E_INVALIDARG.
  828. //
  829. if (!pdwLastDeviceError) {
  830. return E_INVALIDARG;
  831. }
  832. *pdwLastDeviceError = m_dwLastOperationError;
  833. return S_OK;
  834. }
  835. /**************************************************************************\
  836. * CWIADevice::LockDevice
  837. *
  838. * LockDevice is called to lock a WIA device for exclusive access. This
  839. * method can be called directly by an application using the legacy STI
  840. * APIs, or by the WIA service.
  841. *
  842. * A device should return STIERR_DEVICE_LOCKED if it has already been
  843. * locked by another client. The WIA service will call LockDevice to
  844. * control the exclusive access to the WIA device.
  845. *
  846. * Do not get this confused with drvLockWiaDevice(). IStiUsd::LockDevice
  847. * can get called directly by an appliation using the legacy STI APIs.
  848. * drvLockWiaDevice() is only called by the WIA service. No appliation can
  849. * call drvLockWiaDevice().
  850. *
  851. * Arguments:
  852. *
  853. * None
  854. *
  855. * Return Value:
  856. *
  857. * S_OK - if the device was successfully locked
  858. * STIERR_DEVICE_LOCKED - Error code if the device is already locked
  859. *
  860. * Remarks:
  861. *
  862. * The WIA shell extension, which controls the visibility of a WIA device
  863. * in the "My Computer" and "Control Panel", calls LockDevice() directly.
  864. * This is used to lock the the device so the IStiUsd::Diagnostic() method
  865. * can get called when the user presses the "TEST Device" button.
  866. *
  867. * History:
  868. *
  869. * 03/05/2002 Original Version
  870. *
  871. \**************************************************************************/
  872. STDMETHODIMP CWIADevice::LockDevice(void)
  873. {
  874. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  875. WIALOG_NO_RESOURCE_ID,
  876. WIALOG_LEVEL3,
  877. "CWIADevice::LockDevice");
  878. //
  879. // be very careful about how long locks are held. An application can
  880. // come in using the STI APIs only, and lock your device. This lock,
  881. // if held indefinitly could prevent access to your device from other
  882. // applications installed on the system.
  883. //
  884. // It might be useful to implement some sort of reasonable locking timeout
  885. // mechanism. If a lock is held too long, then it should be auto-unlocked.
  886. // to allow others to access the device.
  887. // *** This should only be done, if you know it is safe to unlock your hardware.
  888. // Cases that may take a long time (like HUGE scans) can hold a lock for the entire
  889. // length. A good question to ask in a long-locking case, is, "what is my driver
  890. // doing, that requires such a long locking time?"
  891. //
  892. HRESULT hr = S_OK;
  893. if (m_bDeviceLocked) {
  894. hr = STIERR_DEVICE_LOCKED;
  895. } else {
  896. m_bDeviceLocked = TRUE;
  897. }
  898. return hr;
  899. }
  900. /**************************************************************************\
  901. * CWIADevice::UnLockDevice
  902. *
  903. * UnLockDevice is called to unlock a WIA device from exclusive access. This
  904. * method can be called directly by an application using the legacy STI
  905. * APIs, or by the WIA service.
  906. *
  907. * A device should return STIERR_NEEDS_LOCK if it has not already been
  908. * locked by another client. The WIA service will call UnLockDevice to
  909. * release exclusive access to the WIA device.
  910. *
  911. * Do not get this confused with drvUnLockWiaDevice(). IStiUsd::UnLockDevice
  912. * can get called directly by an appliation using the legacy STI APIs.
  913. * drvUnLockWiaDevice() is only called by the WIA service. No appliation can
  914. * call drvUnLockWiaDevice().
  915. *
  916. * Arguments:
  917. *
  918. * None
  919. *
  920. * Return Value:
  921. *
  922. * S_OK - if the device was successfully locked
  923. * STIERR_NEEDS_LOCK - Error code if the device isn't already locked
  924. *
  925. * Remarks:
  926. *
  927. * The WIA shell extension, which controls the visibility of a WIA device
  928. * in the "My Computer" and "Control Panel", calls UnLockDevice() directly.
  929. * (see IStiUsd::LockDevice() for details)
  930. *
  931. * History:
  932. *
  933. * 03/05/2002 Original Version
  934. *
  935. \**************************************************************************/
  936. STDMETHODIMP CWIADevice::UnLockDevice(void)
  937. {
  938. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  939. WIALOG_NO_RESOURCE_ID,
  940. WIALOG_LEVEL3,
  941. "CWIADevice::UnLockDevice");
  942. HRESULT hr = S_OK;
  943. if (!m_bDeviceLocked)
  944. hr = STIERR_NEEDS_LOCK;
  945. else {
  946. m_bDeviceLocked = FALSE;
  947. }
  948. return hr;
  949. }
  950. /**************************************************************************\
  951. * CWIADevice::RawReadData
  952. *
  953. * RawReadData is called to access the hardware directly. Any application
  954. * that uses the legacy STI APIs can call RawReadData(). This method is
  955. * used when an application (useally a vendor-supplied application or library)
  956. * wants to read data from an open device port (controlled by this WIA driver).
  957. *
  958. * Arguments:
  959. *
  960. * lpBuffer - buffer for returned data
  961. * lpdwNumberOfBytes - number of bytes to read/returned
  962. * lpOverlapped - overlap
  963. *
  964. * Return Value:
  965. *
  966. * S_OK - if the read was successful
  967. * E_xxx - if the operation failed
  968. *
  969. * History:
  970. *
  971. * 03/05/2002 Original Version
  972. *
  973. \**************************************************************************/
  974. STDMETHODIMP CWIADevice::RawReadData(
  975. LPVOID lpBuffer,
  976. LPDWORD lpdwNumberOfBytes,
  977. LPOVERLAPPED lpOverlapped)
  978. {
  979. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  980. WIALOG_NO_RESOURCE_ID,
  981. WIALOG_LEVEL3,
  982. "CWIADevice::RawReadData");
  983. //
  984. // If the caller did not pass in the correct parameters, then fail the
  985. // call with E_INVALIDARG.
  986. //
  987. if(!lpdwNumberOfBytes){
  988. return E_INVALIDARG;
  989. }
  990. DWORD dwNumberOfBytes = *lpdwNumberOfBytes;
  991. if(!lpBuffer){
  992. return E_INVALIDARG;
  993. }
  994. //
  995. // lpOverlapped is used by a call to ReadFile, or DeviceIOControl call. This
  996. // parameter can be NULL according to those APIs.
  997. //
  998. HRESULT hr = E_NOTIMPL;
  999. //
  1000. // if your driver will not support this entry point then it needs to return
  1001. // E_NOTIMPL. (error, not implemented)
  1002. //
  1003. return hr;
  1004. }
  1005. /**************************************************************************\
  1006. * CWIADevice::RawWriteData
  1007. *
  1008. * RawWriteData is called to access the hardware directly. Any application
  1009. * that uses the legacy STI APIs can call RawWriteData(). This method is
  1010. * used when an application (useally a vendor-supplied application or library)
  1011. * wants to write data to an open device port (controlled by this WIA driver).
  1012. *
  1013. * Arguments:
  1014. *
  1015. * lpBuffer - buffer for returned data
  1016. * dwNumberOfBytes - number of bytes to write
  1017. * lpOverlapped - overlap
  1018. *
  1019. * Return Value:
  1020. *
  1021. * S_OK - if the write was successful
  1022. * E_xxx - if the operation failed
  1023. *
  1024. * History:
  1025. *
  1026. * 03/05/2002 Original Version
  1027. *
  1028. \**************************************************************************/
  1029. STDMETHODIMP CWIADevice::RawWriteData(
  1030. LPVOID lpBuffer,
  1031. DWORD dwNumberOfBytes,
  1032. LPOVERLAPPED lpOverlapped)
  1033. {
  1034. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  1035. WIALOG_NO_RESOURCE_ID,
  1036. WIALOG_LEVEL3,
  1037. "CWIADevice::RawWriteData");
  1038. //
  1039. // If the caller did not pass in the correct parameters, then fail the
  1040. // call with E_INVALIDARG.
  1041. //
  1042. if(!lpBuffer){
  1043. return E_INVALIDARG;
  1044. }
  1045. //
  1046. // lpOverlapped is used by a call to ReadFile, or DeviceIOControl call. This
  1047. // parameter can be NULL according to those APIs.
  1048. //
  1049. HRESULT hr = E_NOTIMPL;
  1050. //
  1051. // if your driver will not support this entry point then it needs to return
  1052. // E_NOTIMPL. (error, not implemented)
  1053. //
  1054. return hr;
  1055. }
  1056. /**************************************************************************\
  1057. * CWIADevice::RawReadCommand
  1058. *
  1059. * RawReadCommand is called to access the hardware directly. Any application
  1060. * that uses the legacy STI APIs can call RawReadCommand(). This method is
  1061. * used when an application (useally a vendor-supplied application or library)
  1062. * wants to read data from an open device port (controlled by this WIA driver).
  1063. *
  1064. * Arguments:
  1065. *
  1066. * lpBuffer - buffer for returned data
  1067. * lpdwNumberOfBytes - number of bytes to read/returned
  1068. * lpOverlapped - overlap
  1069. *
  1070. * Return Value:
  1071. *
  1072. * S_OK - if the read was successful
  1073. * E_xxx - if the operation failed
  1074. *
  1075. * History:
  1076. *
  1077. * 03/05/2002 Original Version
  1078. *
  1079. \**************************************************************************/
  1080. STDMETHODIMP CWIADevice::RawReadCommand(
  1081. LPVOID lpBuffer,
  1082. LPDWORD lpdwNumberOfBytes,
  1083. LPOVERLAPPED lpOverlapped)
  1084. {
  1085. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  1086. WIALOG_NO_RESOURCE_ID,
  1087. WIALOG_LEVEL3,
  1088. "CWIADevice::RawReadCommand");
  1089. //
  1090. // If the caller did not pass in the correct parameters, then fail the
  1091. // call with E_INVALIDARG.
  1092. //
  1093. if(!lpdwNumberOfBytes){
  1094. return E_INVALIDARG;
  1095. }
  1096. DWORD dwNumberOfBytes = *lpdwNumberOfBytes;
  1097. if(!lpBuffer){
  1098. return E_INVALIDARG;
  1099. }
  1100. //
  1101. // lpOverlapped is used by a call to ReadFile, or DeviceIOControl call. This
  1102. // parameter can be NULL according to those APIs.
  1103. //
  1104. HRESULT hr = E_NOTIMPL;
  1105. //
  1106. // if your driver will not support this entry point then it needs to return
  1107. // E_NOTIMPL. (error, not implemented)
  1108. //
  1109. return hr;
  1110. }
  1111. /**************************************************************************\
  1112. * CWIADevice::RawWriteCommand
  1113. *
  1114. * RawWriteCommand is called to access the hardware directly. Any application
  1115. * that uses the legacy STI APIs can call RawWriteCommand(). This method is
  1116. * used when an application (useally a vendor-supplied application or library)
  1117. * wants to write data to an open device port (controlled by this WIA driver).
  1118. *
  1119. * Arguments:
  1120. *
  1121. * lpBuffer - buffer for returned data
  1122. * nNumberOfBytes - number of bytes to write
  1123. * lpOverlapped - overlap
  1124. *
  1125. * Return Value:
  1126. *
  1127. * S_OK - if the write was successful
  1128. * E_xxx - if the operation failed
  1129. *
  1130. * History:
  1131. *
  1132. * 03/05/2002 Original Version
  1133. *
  1134. \**************************************************************************/
  1135. STDMETHODIMP CWIADevice::RawWriteCommand(
  1136. LPVOID lpBuffer,
  1137. DWORD dwNumberOfBytes,
  1138. LPOVERLAPPED lpOverlapped)
  1139. {
  1140. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  1141. WIALOG_NO_RESOURCE_ID,
  1142. WIALOG_LEVEL3,
  1143. "CWIADevice::RawWriteCommand");
  1144. //
  1145. // If the caller did not pass in the correct parameters, then fail the
  1146. // call with E_INVALIDARG.
  1147. //
  1148. if(!lpBuffer){
  1149. return E_INVALIDARG;
  1150. }
  1151. //
  1152. // lpOverlapped is used by a call to ReadFile, or DeviceIOControl call. This
  1153. // parameter can be NULL according to those APIs.
  1154. //
  1155. HRESULT hr = E_NOTIMPL;
  1156. //
  1157. // if your driver will not support this entry point then it needs to return
  1158. // E_NOTIMPL. (error, not implemented)
  1159. //
  1160. return hr;
  1161. }
  1162. /**************************************************************************\
  1163. * CWIADevice::SetNotificationHandle
  1164. *
  1165. * SetNotificationHandle is called by the WIA service or internally by this
  1166. * driver to start or stop event notifications. The WIA service will pass
  1167. * in a valid handle (created using CreateEvent() ), indicating that it
  1168. * wants the WIA driver to signal this handle when an event occurs in the
  1169. * hardware.
  1170. *
  1171. * NULL can be passed to this SetNotificationHandle() method. NULL
  1172. * indicates that the WIA driver is to STOP all device activity, and exit
  1173. * any event wait operations.
  1174. *
  1175. * Arguments:
  1176. *
  1177. * hEvent - HANDLE to an event created by the WIA service using CreateEvent()
  1178. * This parameter can be NULL, indicating that all previous event
  1179. * waiting should be stopped.
  1180. *
  1181. * Return Value:
  1182. *
  1183. * S_OK - if the operation was successful
  1184. * E_xxx - Error Code if the operation fails
  1185. *
  1186. * History:
  1187. *
  1188. * 03/05/2002 Original Version
  1189. *
  1190. \**************************************************************************/
  1191. STDMETHODIMP CWIADevice::SetNotificationHandle(HANDLE hEvent)
  1192. {
  1193. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  1194. WIALOG_NO_RESOURCE_ID,
  1195. WIALOG_LEVEL3,
  1196. "CWIADevice::SetNotificationHandle");
  1197. HRESULT hr = S_OK;
  1198. if (hEvent && (hEvent != INVALID_HANDLE_VALUE)) {
  1199. //
  1200. // A valid handle indicates that we are asked to start our "wait"
  1201. // for device interrupt events
  1202. //
  1203. WIAS_LWARNING(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SetNotificationHandle, hEvent = %d",hEvent));
  1204. //
  1205. // reset last event GUID to GUID_NULL
  1206. //
  1207. m_guidLastEvent = GUID_NULL;
  1208. //
  1209. // clear EventOverlapped structure
  1210. //
  1211. memset(&m_EventOverlapped,0,sizeof(m_EventOverlapped));
  1212. //
  1213. // fill overlapped hEvent member with the event passed in by the WIA service.
  1214. // This handle will be automatically signaled when an event is triggered at
  1215. // the hardware level.
  1216. //
  1217. m_EventOverlapped.hEvent = hEvent;
  1218. //
  1219. // clear event data buffer. This is the buffer that will be used to determine
  1220. // what event was signaled from the device.
  1221. //
  1222. memset(m_EventData,0,sizeof(m_EventData));
  1223. //
  1224. // the code block below starts an interrupt event session using DeviceIoControl()
  1225. //
  1226. #ifdef USE_REAL_EVENTS
  1227. //
  1228. // use the following call for interrupt events on your device
  1229. //
  1230. DWORD dwError = 0;
  1231. BOOL bResult = DeviceIoControl( m_hDeviceDataHandle,
  1232. IOCTL_WAIT_ON_DEVICE_EVENT,
  1233. NULL,
  1234. 0,
  1235. &m_EventData,
  1236. sizeof(m_EventData),
  1237. &dwError,
  1238. &m_EventOverlapped );
  1239. if (bResult) {
  1240. hr = S_OK;
  1241. } else {
  1242. hr = HRESULT_FROM_WIN32(::GetLastError());
  1243. }
  1244. #else // USE_REAL_EVENTS
  1245. //
  1246. // THIS IS FOR TESTING ONLY, DO NOT USE THIS METHOD FOR PROCESSING DEVICE EVENTS!!!
  1247. //
  1248. if (m_hFakeEventKey) {
  1249. RegCloseKey(m_hFakeEventKey);
  1250. m_hFakeEventKey = NULL;
  1251. }
  1252. DWORD dwDisposition = 0;
  1253. if (RegCreateKeyEx(HKEY_CURRENT_USER,
  1254. HKEY_WIASCANR_FAKE_EVENTS,
  1255. 0,
  1256. NULL,
  1257. 0,
  1258. KEY_READ,
  1259. NULL,
  1260. &m_hFakeEventKey,
  1261. &dwDisposition) == ERROR_SUCCESS) {
  1262. if (RegNotifyChangeKeyValue(
  1263. m_hFakeEventKey, // handle to key to watch
  1264. FALSE, // subkey notification option
  1265. REG_NOTIFY_CHANGE_LAST_SET, // changes to be reported
  1266. m_EventOverlapped.hEvent, // handle to event to be signaled
  1267. TRUE // asynchronous reporting option
  1268. ) == ERROR_SUCCESS ) {
  1269. }
  1270. }
  1271. #endif // USE_REAL_EVENTS
  1272. } else {
  1273. //
  1274. // stop any hardware waiting events here, the WIA service has notified us to kill
  1275. // all hardware event waiting
  1276. //
  1277. WIAS_LWARNING(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SetNotificationHandle, Disabling event Notifications"));
  1278. #ifdef USE_REAL_EVENTS
  1279. //
  1280. // Stop hardware interrupt events. This will actually stop all activity on the device.
  1281. // Since DeviceIOControl was used with OVERLAPPED i/o functionality the CancelIo()
  1282. // can be used to stop all kernel mode activity.
  1283. //
  1284. //
  1285. // NOTE: It is important to use overlapped i/o calls with all activity involving the
  1286. // kernel mode drivers. This will allow for proper time-outs and cancellation
  1287. // of device requests.
  1288. //
  1289. if(m_hDeviceDataHandle){
  1290. if(!CancelIo(m_hDeviceDataHandle)){
  1291. //
  1292. // cancelling of the IO failed, call GetLastError() here to determine the cause.
  1293. //
  1294. LONG lError = ::GetLastError();
  1295. }
  1296. }
  1297. #else // USE_REAL_EVENTS
  1298. if (m_hFakeEventKey) {
  1299. RegCloseKey(m_hFakeEventKey);
  1300. m_hFakeEventKey = NULL;
  1301. }
  1302. #endif // USE_REAL_EVENTS
  1303. }
  1304. return hr;
  1305. }
  1306. /**************************************************************************\
  1307. * CWIADevice::GetNotificationData
  1308. *
  1309. * GetNotificationData is called by the WIA service to get information about
  1310. * an event that has just been signaled. GetNotificationsData can be called
  1311. * as a result of one of two event operations.
  1312. *
  1313. * 1. GetStatus() reported that there was an event pending, by setting the
  1314. * STI_EVENTHANDLING_PENDING flag in the STI_DEVICE_STATUS structure.
  1315. *
  1316. * 2. The hEvent handle passed in by SetNotificationHandle() was signaled
  1317. * by the hardware, or by calling SetEvent() directly.
  1318. *
  1319. * The WIA driver is responsible for filling out the STINOTIFY structure
  1320. * members:
  1321. * dwSize - size of the STINOTIFY structure.
  1322. * guidNotificationCode - GUID that represents the event that is to be
  1323. * responded to. This should be set to GUID_NULL
  1324. * if no event is to be sent. This will tell the
  1325. * WIA service that no event really happened.
  1326. * abNotificationData - OPTIONAL - vendor specific information. This data
  1327. * is limited to 64 bytes of data ONLY.
  1328. *
  1329. * Arguments:
  1330. *
  1331. * pBuffer - Pointer to a STINOTIFY structure.
  1332. *
  1333. * Return Value:
  1334. *
  1335. * S_OK - if the data can be written successfully
  1336. * E_xxx - Error code if the operation fails
  1337. *
  1338. * Remarks:
  1339. *
  1340. * This WIA driver checks the m_bPolledEvent flag to determine where to get
  1341. * the event information from. If this flag is TRUE, it uses the event GUID
  1342. * already set by the GetStatus() call. (see GetStatus comments for details)
  1343. * If this flag is FALSE, then the WIA driver needs to look at the OVERLAPPED
  1344. * result for more information. The m_EventData BYTE array should contain
  1345. * information about the event. This is also where you can ask the device
  1346. * more information about what event just occured.
  1347. *
  1348. * Sample Notes:
  1349. *
  1350. * This WIA sample driver uses the Windows Registry to simulate the interrupt
  1351. * event signaling. It is not recommended to use this method in a production
  1352. * driver. The #define USE_REAL_EVENTS should be defined to build a WIA driver
  1353. * that uses real device events.
  1354. *
  1355. * History:
  1356. *
  1357. * 03/05/2002 Original Version
  1358. *
  1359. \**************************************************************************/
  1360. STDMETHODIMP CWIADevice::GetNotificationData( LPSTINOTIFY pBuffer )
  1361. {
  1362. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  1363. WIALOG_NO_RESOURCE_ID,
  1364. WIALOG_LEVEL3,
  1365. "CWIADevice::GetNotificationData");
  1366. //
  1367. // If the caller did not pass in the correct parameters, then fail the
  1368. // call with E_INVALIDARG.
  1369. //
  1370. if(!pBuffer){
  1371. return E_INVALIDARG;
  1372. }
  1373. DWORD dwBytesRet = 0;
  1374. //
  1375. // check the event source flag, m_bPolledEvent.
  1376. // * If it is TRUE, just pass the event set in GetStatus() call to
  1377. // the STINOTIFY buffer and continue.
  1378. //
  1379. // * If it is FALSE, then you need to read the m_EventData buffer
  1380. // to determine what event was fired.
  1381. //
  1382. if (m_bPolledEvent == FALSE) {
  1383. #ifdef USE_REAL_EVENTS
  1384. BOOL bResult = GetOverlappedResult(m_hDeviceDataHandle, &m_EventOverlapped, &dwBytesRet, FALSE );
  1385. if (bResult) {
  1386. //
  1387. // read the m_EventData buffer to determine the proper event.
  1388. // set the m_guidLastEvent member to the proper event GUID
  1389. // set the m_guidLastEvent to GUID_NULL when an event has
  1390. // not happened that you are concerned with
  1391. //
  1392. }
  1393. #else // USE_REAL_EVENTS
  1394. if(m_hFakeEventKey){
  1395. LONG lEventCode = 0;
  1396. DWORD dwEventCodeSize = sizeof(lEventCode);
  1397. DWORD dwType = REG_DWORD;
  1398. if(RegQueryValueEx(m_hFakeEventKey,
  1399. WIASCANR_DWORD_FAKE_EVENT_CODE,
  1400. NULL,
  1401. &dwType,
  1402. (BYTE*)&lEventCode,
  1403. &dwEventCodeSize) == ERROR_SUCCESS){
  1404. //
  1405. // process event code
  1406. //
  1407. switch(lEventCode){
  1408. case ID_FAKE_SCANBUTTON:
  1409. m_guidLastEvent = WIA_EVENT_SCAN_IMAGE;
  1410. break;
  1411. case ID_FAKE_COPYBUTTON:
  1412. m_guidLastEvent = WIA_EVENT_SCAN_PRINT_IMAGE;
  1413. break;
  1414. case ID_FAKE_FAXBUTTON:
  1415. m_guidLastEvent = WIA_EVENT_SCAN_FAX_IMAGE;
  1416. break;
  1417. case ID_FAKE_NOEVENT:
  1418. default:
  1419. break;
  1420. }
  1421. }
  1422. }
  1423. #endif // USE_REAL_EVENTS
  1424. }
  1425. //
  1426. // If the event was triggered, then fill in the STINOTIFY structure with
  1427. // the proper event information
  1428. //
  1429. if (m_guidLastEvent != GUID_NULL) {
  1430. memset(pBuffer,0,sizeof(STINOTIFY));
  1431. pBuffer->dwSize = sizeof(STINOTIFY);
  1432. pBuffer->guidNotificationCode = m_guidLastEvent;
  1433. //
  1434. // reset the Last event GUID to GUID_NULL to clear the cached event
  1435. //
  1436. m_guidLastEvent = GUID_NULL;
  1437. } else {
  1438. return STIERR_NOEVENTS;
  1439. }
  1440. return S_OK;
  1441. }
  1442. /**************************************************************************\
  1443. * CWIADevice::GetLastErrorInfo
  1444. *
  1445. * GetLastErrorInfo is called to get more information about a WIA device
  1446. * specific error code. This code could come from the IStiUsd::GetLastError()
  1447. * method call, or a vendor specific application may want more information
  1448. * about a known error code.
  1449. *
  1450. *
  1451. * Arguments:
  1452. *
  1453. * pLastErrorInfo - Pointer to extended device error data.
  1454. *
  1455. * Return Value:
  1456. *
  1457. * S_OK - if the data can be written correctly
  1458. * E_xxx - Error code if the operation fails
  1459. *
  1460. * History:
  1461. *
  1462. * 03/05/2002 Original Version
  1463. *
  1464. \**************************************************************************/
  1465. STDMETHODIMP CWIADevice::GetLastErrorInfo(STI_ERROR_INFO *pLastErrorInfo)
  1466. {
  1467. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  1468. WIALOG_NO_RESOURCE_ID,
  1469. WIALOG_LEVEL3,
  1470. "CWIADevice::GetLastErrorInfo");
  1471. //
  1472. // If the caller did not pass in the correct parameters, then fail the
  1473. // call with E_INVALIDARG.
  1474. //
  1475. if (!pLastErrorInfo) {
  1476. return E_INVALIDARG;
  1477. }
  1478. pLastErrorInfo->dwGenericError = m_dwLastOperationError;
  1479. pLastErrorInfo->szExtendedErrorText[0] = '\0';
  1480. return S_OK;
  1481. }