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.

1242 lines
37 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. extern HINSTANCE g_hInst; // used for WIAS_LOGPROC macro
  17. #define THREAD_TERMINATION_TIMEOUT 10000
  18. VOID EventThread( LPVOID lpParameter ); // event thread
  19. /**************************************************************************\
  20. * CWIAScannerDevice::CWIAScannerDevice
  21. *
  22. * Device class constructor
  23. *
  24. * Arguments:
  25. *
  26. * None
  27. *
  28. * Return Value:
  29. *
  30. * None
  31. *
  32. * History:
  33. *
  34. * 7/18/2000 Original Version
  35. *
  36. \**************************************************************************/
  37. CWIAScannerDevice::CWIAScannerDevice(LPUNKNOWN punkOuter):
  38. m_cRef(1),
  39. m_fValid(FALSE),
  40. m_punkOuter(NULL),
  41. m_pIStiDevControl(NULL),
  42. m_bUsdLoadEvent(FALSE),
  43. m_dwLastOperationError(0),
  44. m_dwLockTimeout(100),
  45. m_hSignalEvent(NULL),
  46. m_hShutdownEvent(NULL),
  47. m_hEventNotifyThread(NULL),
  48. m_guidLastEvent(GUID_NULL),
  49. m_bstrDeviceID(NULL),
  50. m_bstrRootFullItemName(NULL),
  51. m_pIWiaEventCallback(NULL),
  52. m_pIDrvItemRoot(NULL),
  53. m_pStiDevice(NULL),
  54. m_hInstance(NULL),
  55. m_pIWiaLog(NULL),
  56. m_NumSupportedFormats(0),
  57. m_NumCapabilities(0),
  58. m_NumSupportedTYMED(0),
  59. m_NumInitialFormats(0),
  60. m_NumSupportedDataTypes(0),
  61. m_NumSupportedIntents(0),
  62. m_NumSupportedCompressionTypes(0),
  63. m_NumSupportedResolutions(0),
  64. m_pSupportedFormats(NULL),
  65. m_pInitialFormats(NULL),
  66. m_pCapabilities(NULL),
  67. m_pSupportedTYMED(NULL),
  68. m_pSupportedDataTypes(NULL),
  69. m_pSupportedIntents(NULL),
  70. m_pSupportedCompressionTypes(NULL),
  71. m_pSupportedResolutions(NULL),
  72. m_pSupportedPreviewModes(NULL),
  73. m_pszRootItemDefaults(NULL),
  74. m_piRootItemDefaults(NULL),
  75. m_pvRootItemDefaults(NULL),
  76. m_psRootItemDefaults(NULL),
  77. m_wpiRootItemDefaults(NULL),
  78. m_pszItemDefaults(NULL),
  79. m_piItemDefaults(NULL),
  80. m_pvItemDefaults(NULL),
  81. m_psItemDefaults(NULL),
  82. m_wpiItemDefaults(NULL),
  83. m_NumRootItemProperties(0),
  84. m_NumItemProperties(0),
  85. m_MaxBufferSize(524280),
  86. m_MinBufferSize(262140),
  87. m_bDeviceLocked(FALSE),
  88. m_DeviceDefaultDataHandle(NULL),
  89. m_pszDeviceNameA(NULL),
  90. m_bADFEnabled(TRUE),
  91. m_pScanAPI(NULL)
  92. {
  93. // See if we are aggregated. If we are (almost always the case) save
  94. // pointer to the controlling Unknown , so subsequent calls will be
  95. // delegated. If not, set the same pointer to "this".
  96. if (punkOuter) {
  97. m_punkOuter = punkOuter;
  98. } else {
  99. // Cast below is needed in order to point to right virtual table
  100. m_punkOuter = reinterpret_cast<IUnknown*>
  101. (static_cast<INonDelegatingUnknown*>
  102. (this));
  103. }
  104. }
  105. /**************************************************************************\
  106. * CWIAScannerDevice::PrivateInitialize
  107. *
  108. * Device class private initialization code
  109. *
  110. * Arguments:
  111. *
  112. * None
  113. *
  114. * Return Value:
  115. *
  116. * HRESULT
  117. *
  118. \**************************************************************************/
  119. HRESULT CWIAScannerDevice::PrivateInitialize()
  120. {
  121. HRESULT hr = S_OK;
  122. #ifdef USE_SERVICE_LOG_CREATION
  123. hr = wiasCreateLogInstance(g_hInst, &m_pIWiaLog);
  124. #else
  125. hr = CoCreateInstance(CLSID_WiaLog, NULL, CLSCTX_INPROC_SERVER,
  126. IID_IWiaLog,(void**)&m_pIWiaLog);
  127. if (SUCCEEDED(hr)) {
  128. m_pIWiaLog->InitializeLog((LONG)(LONG_PTR)g_hInst);
  129. WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL1,("Logging COM object created successfully for wiascroll.dll"));
  130. } else {
  131. #ifdef DEBUG
  132. OutputDebugString(TEXT("Could not CoCreateInstance on Logging COM object for wiafbdrv.dll, because we are STI only\n"));
  133. OutputDebugString(TEXT("********* (Device must have been created for STI only) *********\n"));
  134. #endif
  135. }
  136. #endif
  137. __try {
  138. if(!InitializeCriticalSectionAndSpinCount(&m_csShutdown, MINLONG)) {
  139. hr = HRESULT_FROM_WIN32(::GetLastError());
  140. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CWIAScannerDevice::PrivateInitialize, create shutdown critsec failed"));
  141. }
  142. }
  143. __except(EXCEPTION_EXECUTE_HANDLER) {
  144. hr = E_OUTOFMEMORY;
  145. }
  146. if(hr == S_OK) {
  147. // Create event for syncronization of notifications shutdown.
  148. m_hShutdownEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
  149. if (m_hShutdownEvent && (INVALID_HANDLE_VALUE != m_hShutdownEvent)) {
  150. m_fValid = TRUE;
  151. } else {
  152. hr = HRESULT_FROM_WIN32(::GetLastError());
  153. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CWIAScannerDevice::PrivateInitialize, create shutdown event failed"));
  154. }
  155. }
  156. return hr;
  157. }
  158. /**************************************************************************\
  159. * CWIAScannerDevice::~CWIAScannerDevice
  160. *
  161. * Device class destructor
  162. *
  163. * Arguments:
  164. *
  165. * None
  166. *
  167. * Return Value:
  168. *
  169. * None
  170. *
  171. * History:
  172. *
  173. * 7/18/2000 Original Version
  174. *
  175. \**************************************************************************/
  176. CWIAScannerDevice::~CWIAScannerDevice(void)
  177. {
  178. // Kill notification thread if it exists.
  179. SetNotificationHandle(NULL);
  180. // Close event for syncronization of notifications shutdown.
  181. if (m_hShutdownEvent && (m_hShutdownEvent != INVALID_HANDLE_VALUE)) {
  182. CloseHandle(m_hShutdownEvent);
  183. m_hShutdownEvent = NULL;
  184. }
  185. // Release the device control interface.
  186. if (m_pIStiDevControl) {
  187. m_pIStiDevControl->Release();
  188. m_pIStiDevControl = NULL;
  189. }
  190. //
  191. // WIA member destruction
  192. //
  193. // Tear down the driver item tree.
  194. if (m_pIDrvItemRoot) {
  195. WIAS_LWARNING(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("~CWIAScannerDevice, Deleting Device Item Tree (this is OK)"));
  196. DeleteItemTree();
  197. m_pIDrvItemRoot = NULL;
  198. }
  199. // free any IO handles opened
  200. if(m_DeviceDefaultDataHandle){
  201. WIAS_LWARNING(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("~CWIAScannerDevice, Closing DefaultDeviceDataHandle"));
  202. CloseHandle(m_DeviceDefaultDataHandle);
  203. m_DeviceDefaultDataHandle = NULL;
  204. }
  205. // Cleanup the WIA event sink.
  206. if (m_pIWiaEventCallback) {
  207. m_pIWiaEventCallback->Release();
  208. m_pIWiaEventCallback = NULL;
  209. }
  210. // Free the storage for the device ID.
  211. if (m_bstrDeviceID) {
  212. SysFreeString(m_bstrDeviceID);
  213. m_bstrDeviceID = NULL;
  214. }
  215. // Release the objects supporting device property storage.
  216. if (m_bstrRootFullItemName) {
  217. SysFreeString(m_bstrRootFullItemName);
  218. m_bstrRootFullItemName = NULL;
  219. }
  220. // Delete allocated arrays
  221. DeleteCapabilitiesArrayContents();
  222. DeleteSupportedIntentsArrayContents();
  223. // Free the critical section.
  224. DeleteCriticalSection(&m_csShutdown);
  225. if(m_pIWiaLog)
  226. m_pIWiaLog->Release();
  227. if(m_pScanAPI){
  228. // disable fake scanner device
  229. m_pScanAPI->FakeScanner_DisableDevice();
  230. delete m_pScanAPI;
  231. }
  232. }
  233. /**************************************************************************\
  234. * CWIAScannerDevice::GetCapabilities
  235. *
  236. * Get the device STI capabilities.
  237. *
  238. * Arguments:
  239. *
  240. * pUsdCaps - Pointer to USD capabilities data.
  241. *
  242. * Return Value:
  243. *
  244. * Status.
  245. *
  246. * History:
  247. *
  248. * 7/18/2000 Original Version
  249. *
  250. \**************************************************************************/
  251. STDMETHODIMP CWIAScannerDevice::GetCapabilities(PSTI_USD_CAPS pUsdCaps)
  252. {
  253. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  254. WIALOG_NO_RESOURCE_ID,
  255. WIALOG_LEVEL3,
  256. "CWIAScannerDevice::GetCapabilities");
  257. memset(pUsdCaps, 0, sizeof(STI_USD_CAPS));
  258. pUsdCaps->dwVersion = STI_VERSION;
  259. pUsdCaps->dwGenericCaps = STI_USD_GENCAP_NATIVE_PUSHSUPPORT|
  260. STI_GENCAP_NOTIFICATIONS |
  261. STI_GENCAP_POLLING_NEEDED;
  262. return STI_OK;
  263. }
  264. /**************************************************************************\
  265. * CWIAScannerDevice::GetStatus
  266. *
  267. * Query device online and/or event status.
  268. *
  269. * Arguments:
  270. *
  271. * pDevStatus - Pointer to device status data.
  272. *
  273. * Return Value:
  274. *
  275. * Status.
  276. *
  277. * History:
  278. *
  279. * 7/18/2000 Original Version
  280. *
  281. \**************************************************************************/
  282. STDMETHODIMP CWIAScannerDevice::GetStatus(PSTI_DEVICE_STATUS pDevStatus)
  283. {
  284. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  285. WIALOG_NO_RESOURCE_ID,
  286. WIALOG_LEVEL3,
  287. "CWIAScannerDevice::GetStatus");
  288. HRESULT hr = S_OK;
  289. // Validate parameters.
  290. if (!pDevStatus) {
  291. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CWIAScannerDevice::GetStatus, NULL parameter"));
  292. return E_INVALIDARG;
  293. }
  294. // If we are asked, verify the device is online.
  295. if (pDevStatus->StatusMask & STI_DEVSTATUS_ONLINE_STATE) {
  296. WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("GetStatus, WIA is asking the device if we are ONLINE"));
  297. pDevStatus->dwOnlineState = 0L;
  298. hr = m_pScanAPI->FakeScanner_DeviceOnline();
  299. if(SUCCEEDED(hr)){
  300. WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("GetStatus, Device is ONLINE"));
  301. pDevStatus->dwOnlineState |= STI_ONLINESTATE_OPERATIONAL;
  302. } else {
  303. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("GetStatus, Device is OFFLINE"));
  304. }
  305. }
  306. // If we are asked, verify state of event.
  307. pDevStatus->dwEventHandlingState &= ~STI_EVENTHANDLING_PENDING;
  308. if (pDevStatus->StatusMask & STI_DEVSTATUS_EVENTS_STATE) {
  309. // Generate an event the first time we load.
  310. if (m_bUsdLoadEvent) {
  311. pDevStatus->dwEventHandlingState = STI_EVENTHANDLING_PENDING;
  312. m_guidLastEvent = guidEventFirstLoaded;
  313. m_bUsdLoadEvent = FALSE;
  314. }
  315. // check for device events
  316. LONG lButtonIndex = ID_FAKE_NOEVENT;
  317. hr = m_pScanAPI->FakeScanner_GetDeviceEvent(&lButtonIndex);
  318. if(SUCCEEDED(hr)){
  319. switch(lButtonIndex){
  320. case ID_FAKE_SCANBUTTON:
  321. m_guidLastEvent = WIA_EVENT_SCAN_IMAGE;
  322. WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("GetStatus, Scan Button Pressed!"));
  323. break;
  324. case ID_FAKE_COPYBUTTON:
  325. m_guidLastEvent = WIA_EVENT_SCAN_PRINT_IMAGE;
  326. WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("GetStatus, Copy Button Pressed!"));
  327. break;
  328. case ID_FAKE_FAXBUTTON:
  329. m_guidLastEvent = WIA_EVENT_SCAN_FAX_IMAGE;
  330. WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("GetStatus, Fax Button Pressed!"));
  331. break;
  332. default:
  333. m_guidLastEvent = GUID_NULL;
  334. break;
  335. }
  336. if(m_guidLastEvent != GUID_NULL){
  337. pDevStatus->dwEventHandlingState |= STI_EVENTHANDLING_PENDING;
  338. }
  339. }
  340. }
  341. return STI_OK;
  342. }
  343. /**************************************************************************\
  344. * CWIAScannerDevice::DeviceReset
  345. *
  346. * Reset device.
  347. *
  348. * Arguments:
  349. *
  350. * None
  351. *
  352. * Return Value:
  353. *
  354. * Status.
  355. *
  356. * History:
  357. *
  358. * 7/18/2000 Original Version
  359. *
  360. \**************************************************************************/
  361. STDMETHODIMP CWIAScannerDevice::DeviceReset(void)
  362. {
  363. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  364. WIALOG_NO_RESOURCE_ID,
  365. WIALOG_LEVEL3,
  366. "CWIAScannerDevice::DeviceReset");
  367. return m_pScanAPI->FakeScanner_ResetDevice();
  368. }
  369. /**************************************************************************\
  370. * CWIAScannerDevice::Diagnostic
  371. *
  372. * The test device always passes the diagnostic.
  373. *
  374. * Arguments:
  375. *
  376. * pBuffer - Pointer o diagnostic result data.
  377. *
  378. * Return Value:
  379. *
  380. * None
  381. *
  382. * History:
  383. *
  384. * 7/18/2000 Original Version
  385. *
  386. \**************************************************************************/
  387. STDMETHODIMP CWIAScannerDevice::Diagnostic(LPSTI_DIAG pBuffer)
  388. {
  389. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  390. WIALOG_NO_RESOURCE_ID,
  391. WIALOG_LEVEL3,
  392. "CWIAScannerDevice::Diagnostic");
  393. // Initialize response buffer
  394. memset(&pBuffer->sErrorInfo,0,sizeof(pBuffer->sErrorInfo));
  395. pBuffer->dwStatusMask = 0;
  396. pBuffer->sErrorInfo.dwGenericError = NOERROR;
  397. pBuffer->sErrorInfo.dwVendorError = 0;
  398. return m_pScanAPI->FakeScanner_Diagnostic();
  399. }
  400. /**************************************************************************\
  401. * CWIAScannerDevice::SetNotificationHandle
  402. *
  403. * Starts and stops the event notification thread.
  404. *
  405. * Arguments:
  406. *
  407. * hEvent - If not valid start the notification thread otherwise kill
  408. * the notification thread.
  409. *
  410. * Return Value:
  411. *
  412. * Status.
  413. *
  414. * History:
  415. *
  416. * 7/18/2000 Original Version
  417. *
  418. \**************************************************************************/
  419. STDMETHODIMP CWIAScannerDevice::SetNotificationHandle(HANDLE hEvent)
  420. {
  421. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  422. WIALOG_NO_RESOURCE_ID,
  423. WIALOG_LEVEL3,
  424. "CWIAScannerDevice::SetNotificationHandle");
  425. HRESULT hr = STI_OK;
  426. EnterCriticalSection(&m_csShutdown);
  427. // Are we starting or stopping the notification thread?
  428. if (hEvent && (hEvent != INVALID_HANDLE_VALUE)) {
  429. WIAS_LWARNING(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SetNotificationHandle, hEvent = %d",hEvent));
  430. m_hSignalEvent = hEvent;
  431. m_guidLastEvent = GUID_NULL;
  432. if (NULL == m_hEventNotifyThread) {
  433. DWORD dwThread = 0;
  434. m_hEventNotifyThread = ::CreateThread(NULL,
  435. 0,
  436. (LPTHREAD_START_ROUTINE)EventThread,
  437. (LPVOID)this,
  438. 0,
  439. &dwThread);
  440. if (!m_hEventNotifyThread) {
  441. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("FlatbedScannerUsdDevice::SetNotificationHandle, CreateThread failed"));
  442. hr = STIERR_UNSUPPORTED;
  443. }
  444. }
  445. } else {
  446. WIAS_LWARNING(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SetNotificationHandle, Disabling event Notifications"));
  447. // Disable event notifications.
  448. if (m_hShutdownEvent && (m_hShutdownEvent != INVALID_HANDLE_VALUE)) {
  449. if (!SetEvent(m_hShutdownEvent)) {
  450. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SetNotificationHandle, Setting Shutdown event failed.."));
  451. } else {
  452. if (NULL != m_hEventNotifyThread) {
  453. //
  454. // WAIT for thread to terminate, if one exists
  455. //
  456. WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("SetNotificationHandle, Waiting for Event Thread to terminate (%d ms timeout)",THREAD_TERMINATION_TIMEOUT));
  457. DWORD dwResult = WaitForSingleObject(m_hEventNotifyThread,THREAD_TERMINATION_TIMEOUT);
  458. switch (dwResult) {
  459. case WAIT_TIMEOUT:
  460. WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("SetNotificationHandle, Event Thread termination TIMED OUT!"));
  461. break;
  462. case WAIT_OBJECT_0:
  463. WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("SetNotificationHandle, We are signaled...YAY!"));
  464. break;
  465. case WAIT_ABANDONED:
  466. WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("SetNotificationHandle, Event Thread was abandoned.."));
  467. break;
  468. case WAIT_FAILED:
  469. WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("SetNotificationHandle, Event Thread returned a failure..."));
  470. WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("SetNotificationHandle, GetLastError() Code = %d",::GetLastError()));
  471. break;
  472. default:
  473. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SetNotificationHandle, Unknown signal (%d) received from WaitForSingleObject() call",dwResult));
  474. break;
  475. }
  476. }
  477. //
  478. // Close event for syncronization of notifications shutdown.
  479. //
  480. WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("SetNotificationHandle, Closing m_hShutdownEvent handle (it has been signaled)"));
  481. CloseHandle(m_hShutdownEvent);
  482. m_hShutdownEvent = NULL;
  483. }
  484. }
  485. //
  486. // terminate thread
  487. //
  488. if (NULL != m_hEventNotifyThread) {
  489. WIAS_LWARNING(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SetNotificationHandle, closing event Notifications thread handle"));
  490. CloseHandle(m_hEventNotifyThread);
  491. m_hEventNotifyThread = NULL;
  492. }
  493. m_guidLastEvent = GUID_NULL;
  494. }
  495. LeaveCriticalSection(&m_csShutdown);
  496. return hr;
  497. }
  498. /**************************************************************************\
  499. * CWIAScannerDevice::GetNotificationData
  500. *
  501. * Provides data on an event.
  502. *
  503. * Arguments:
  504. *
  505. * pBuffer - Pointer to event data.
  506. *
  507. * Return Value:
  508. *
  509. * Status.
  510. *
  511. * History:
  512. *
  513. * 7/18/2000 Original Version
  514. *
  515. \**************************************************************************/
  516. STDMETHODIMP CWIAScannerDevice::GetNotificationData( LPSTINOTIFY pBuffer )
  517. {
  518. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  519. WIALOG_NO_RESOURCE_ID,
  520. WIALOG_LEVEL3,
  521. "CWIAScannerDevice::GetNotificationData");
  522. // If we have notification ready - return it's guid
  523. if (!IsEqualIID(m_guidLastEvent, GUID_NULL)) {
  524. memset(&pBuffer->abNotificationData,0,sizeof(pBuffer->abNotificationData));
  525. pBuffer->dwSize = sizeof(STINOTIFY);
  526. pBuffer->guidNotificationCode = m_guidLastEvent;
  527. m_guidLastEvent = GUID_NULL;
  528. } else {
  529. return STIERR_NOEVENTS;
  530. }
  531. return STI_OK;
  532. }
  533. /**************************************************************************\
  534. * CWIAScannerDevice::Escape
  535. *
  536. * Issue a command to the device.
  537. *
  538. * Arguments:
  539. *
  540. * EscapeFunction - Command to be issued.
  541. * pInData - Input data to be passed with command.
  542. * cbInDataSize - Size of input data.
  543. * pOutData - Output data to be passed back from command.
  544. * cbOutDataSize - Size of output data buffer.
  545. * pcbActualData - Size of output data actually written.
  546. *
  547. * Return Value:
  548. *
  549. * None
  550. *
  551. * History:
  552. *
  553. * 7/18/2000 Original Version
  554. *
  555. \**************************************************************************/
  556. STDMETHODIMP CWIAScannerDevice::Escape(
  557. STI_RAW_CONTROL_CODE EscapeFunction,
  558. LPVOID pInData,
  559. DWORD cbInDataSize,
  560. LPVOID pOutData,
  561. DWORD cbOutDataSize,
  562. LPDWORD pcbActualData)
  563. {
  564. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  565. WIALOG_NO_RESOURCE_ID,
  566. WIALOG_LEVEL3,
  567. "CWIAScannerDevice::Escape");
  568. // Write command to device if needed.
  569. return STIERR_UNSUPPORTED;
  570. }
  571. /**************************************************************************\
  572. * CWIAScannerDevice::GetLastError
  573. *
  574. * Get the last error from the device.
  575. *
  576. * Arguments:
  577. *
  578. * pdwLastDeviceError - Pointer to last error data.
  579. *
  580. * Return Value:
  581. *
  582. * Status.
  583. *
  584. * History:
  585. *
  586. * 7/18/2000 Original Version
  587. *
  588. \**************************************************************************/
  589. STDMETHODIMP CWIAScannerDevice::GetLastError(LPDWORD pdwLastDeviceError)
  590. {
  591. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  592. WIALOG_NO_RESOURCE_ID,
  593. WIALOG_LEVEL3,
  594. "CWIAScannerDevice::GetLastError");
  595. if (IsBadWritePtr(pdwLastDeviceError, sizeof(DWORD))) {
  596. return STIERR_INVALID_PARAM;
  597. }
  598. *pdwLastDeviceError = m_dwLastOperationError;
  599. return STI_OK;
  600. }
  601. /**************************************************************************\
  602. * CWIAScannerDevice::GetLastErrorInfo
  603. *
  604. * Get extended error information from the device.
  605. *
  606. * Arguments:
  607. *
  608. * pLastErrorInfo - Pointer to extended device error data.
  609. *
  610. * Return Value:
  611. *
  612. * Status.
  613. *
  614. * History:
  615. *
  616. * 7/18/2000 Original Version
  617. *
  618. \**************************************************************************/
  619. STDMETHODIMP CWIAScannerDevice::GetLastErrorInfo(STI_ERROR_INFO *pLastErrorInfo)
  620. {
  621. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  622. WIALOG_NO_RESOURCE_ID,
  623. WIALOG_LEVEL3,
  624. "CWIAScannerDevice::GetLastErrorInfo");
  625. if (IsBadWritePtr(pLastErrorInfo, sizeof(STI_ERROR_INFO))) {
  626. return STIERR_INVALID_PARAM;
  627. }
  628. pLastErrorInfo->dwGenericError = m_dwLastOperationError;
  629. pLastErrorInfo->szExtendedErrorText[0] = '\0';
  630. return STI_OK;
  631. }
  632. /**************************************************************************\
  633. * CWIAScannerDevice::LockDevice
  634. *
  635. * Lock access to the device.
  636. *
  637. * Arguments:
  638. *
  639. * None
  640. *
  641. * Return Value:
  642. *
  643. * Status.
  644. *
  645. * History:
  646. *
  647. * 7/18/2000 Original Version
  648. *
  649. \**************************************************************************/
  650. STDMETHODIMP CWIAScannerDevice::LockDevice(void)
  651. {
  652. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  653. WIALOG_NO_RESOURCE_ID,
  654. WIALOG_LEVEL3,
  655. "CWIAScannerDevice::LockDevice");
  656. HRESULT hr = STI_OK;
  657. if(m_bDeviceLocked)
  658. hr = STIERR_DEVICE_LOCKED;
  659. else {
  660. m_bDeviceLocked = TRUE;
  661. }
  662. return hr;
  663. }
  664. /**************************************************************************\
  665. * CWIAScannerDevice::UnLockDevice
  666. *
  667. * Unlock access to the device.
  668. *
  669. * Arguments:
  670. *
  671. * None
  672. *
  673. * Return Value:
  674. *
  675. * Status.
  676. *
  677. * History:
  678. *
  679. * 7/18/2000 Original Version
  680. *
  681. \**************************************************************************/
  682. STDMETHODIMP CWIAScannerDevice::UnLockDevice(void)
  683. {
  684. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  685. WIALOG_NO_RESOURCE_ID,
  686. WIALOG_LEVEL3,
  687. "CWIAScannerDevice::UnLockDevice");
  688. HRESULT hr = STI_OK;
  689. if(!m_bDeviceLocked)
  690. hr = STIERR_NEEDS_LOCK;
  691. else {
  692. m_bDeviceLocked = FALSE;
  693. }
  694. return hr;
  695. }
  696. /**************************************************************************\
  697. * CWIAScannerDevice::RawReadData
  698. *
  699. * Read raw data from the device.
  700. *
  701. * Arguments:
  702. *
  703. * lpBuffer - buffer for returned data
  704. * lpdwNumberOfBytes - number of bytes to read/returned
  705. * lpOverlapped - overlap
  706. *
  707. * Return Value:
  708. *
  709. * Status.
  710. *
  711. * History:
  712. *
  713. * 7/18/2000 Original Version
  714. *
  715. \**************************************************************************/
  716. STDMETHODIMP CWIAScannerDevice::RawReadData(
  717. LPVOID lpBuffer,
  718. LPDWORD lpdwNumberOfBytes,
  719. LPOVERLAPPED lpOverlapped)
  720. {
  721. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  722. WIALOG_NO_RESOURCE_ID,
  723. WIALOG_LEVEL3,
  724. "CWIAScannerDevice::RawReadData");
  725. HRESULT hr = STI_OK;
  726. BOOL fRet = FALSE;
  727. DWORD dwBytesReturned = 0;
  728. if (INVALID_HANDLE_VALUE != m_DeviceDefaultDataHandle) {
  729. fRet = ReadFile( m_DeviceDefaultDataHandle,
  730. lpBuffer,
  731. *lpdwNumberOfBytes,
  732. &dwBytesReturned,
  733. lpOverlapped );
  734. m_dwLastOperationError = ::GetLastError();
  735. hr = fRet ? STI_OK : HRESULT_FROM_WIN32(m_dwLastOperationError);
  736. *lpdwNumberOfBytes = (fRet) ? dwBytesReturned : 0;
  737. } else {
  738. hr = STIERR_NOT_INITIALIZED;
  739. }
  740. return hr;
  741. }
  742. /**************************************************************************\
  743. * CWIAScannerDevice::RawWriteData
  744. *
  745. * Write raw data to the device.
  746. *
  747. * Arguments:
  748. *
  749. * lpBuffer - buffer for returned data
  750. * dwNumberOfBytes - number of bytes to write
  751. * lpOverlapped - overlap
  752. *
  753. * Return Value:
  754. *
  755. * Status.
  756. *
  757. * History:
  758. *
  759. * 7/18/2000 Original Version
  760. *
  761. \**************************************************************************/
  762. STDMETHODIMP CWIAScannerDevice::RawWriteData(
  763. LPVOID lpBuffer,
  764. DWORD dwNumberOfBytes,
  765. LPOVERLAPPED lpOverlapped)
  766. {
  767. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  768. WIALOG_NO_RESOURCE_ID,
  769. WIALOG_LEVEL3,
  770. "CWIAScannerDevice::RawWriteData");
  771. HRESULT hr = STI_OK;
  772. BOOL fRet = FALSE;
  773. DWORD dwBytesReturned = 0;
  774. if (INVALID_HANDLE_VALUE != m_DeviceDefaultDataHandle) {
  775. fRet = WriteFile(m_DeviceDefaultDataHandle,lpBuffer,dwNumberOfBytes,&dwBytesReturned,lpOverlapped);
  776. m_dwLastOperationError = ::GetLastError();
  777. hr = fRet ? STI_OK : HRESULT_FROM_WIN32(m_dwLastOperationError);
  778. } else {
  779. hr = STIERR_NOT_INITIALIZED;
  780. }
  781. return STI_OK;
  782. }
  783. /**************************************************************************\
  784. * CWIAScannerDevice::RawReadCommand
  785. *
  786. *
  787. *
  788. * Arguments:
  789. *
  790. * lpBuffer - buffer for returned data
  791. * lpdwNumberOfBytes - number of bytes to read/returned
  792. * lpOverlapped - overlap
  793. *
  794. * Return Value:
  795. *
  796. * Status
  797. *
  798. * History:
  799. *
  800. * 7/18/2000 Original Version
  801. *
  802. \**************************************************************************/
  803. STDMETHODIMP CWIAScannerDevice::RawReadCommand(
  804. LPVOID lpBuffer,
  805. LPDWORD lpdwNumberOfBytes,
  806. LPOVERLAPPED lpOverlapped)
  807. {
  808. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  809. WIALOG_NO_RESOURCE_ID,
  810. WIALOG_LEVEL3,
  811. "CWIAScannerDevice::RawReadCommand");
  812. return STIERR_UNSUPPORTED;
  813. }
  814. /**************************************************************************\
  815. * CWIAScannerDevice::RawWriteCommand
  816. *
  817. *
  818. *
  819. * Arguments:
  820. *
  821. * lpBuffer - buffer for returned data
  822. * nNumberOfBytes - number of bytes to write
  823. * lpOverlapped - overlap
  824. *
  825. * Return Value:
  826. *
  827. * Status.
  828. *
  829. * History:
  830. *
  831. * 7/18/2000 Original Version
  832. *
  833. \**************************************************************************/
  834. STDMETHODIMP CWIAScannerDevice::RawWriteCommand(
  835. LPVOID lpBuffer,
  836. DWORD nNumberOfBytes,
  837. LPOVERLAPPED lpOverlapped)
  838. {
  839. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  840. WIALOG_NO_RESOURCE_ID,
  841. WIALOG_LEVEL3,
  842. "CWIAScannerDevice::RawWriteCommand");
  843. return STIERR_UNSUPPORTED;
  844. }
  845. /**************************************************************************\
  846. * CWIAScannerDevice::Initialize
  847. *
  848. * Initialize the device object.
  849. *
  850. * Arguments:
  851. *
  852. * pIStiDevControlNone - device interface
  853. * dwStiVersion - STI version
  854. * hParametersKey - HKEY for registry reading/writing
  855. *
  856. * Return Value:
  857. *
  858. * Status.
  859. *
  860. * History:
  861. *
  862. * 7/18/2000 Original Version
  863. *
  864. \**************************************************************************/
  865. STDMETHODIMP CWIAScannerDevice::Initialize(
  866. PSTIDEVICECONTROL pIStiDevControl,
  867. DWORD dwStiVersion,
  868. HKEY hParametersKey)
  869. {
  870. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  871. WIALOG_NO_RESOURCE_ID,
  872. WIALOG_LEVEL3,
  873. "CWIAScannerDevice::Initialize");
  874. HRESULT hr = STI_OK;
  875. WCHAR szDeviceNameW[255];
  876. UINT uiNameLen = 0;
  877. if (!pIStiDevControl) {
  878. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CWIAScannerDevice::Initialize, invalid device control interface"));
  879. return STIERR_INVALID_PARAM;
  880. }
  881. // Cache the device control interface.
  882. m_pIStiDevControl = pIStiDevControl;
  883. m_pIStiDevControl->AddRef();
  884. //
  885. // Get the name of the device port
  886. //
  887. hr = m_pIStiDevControl->GetMyDevicePortName(szDeviceNameW,sizeof(szDeviceNameW)/sizeof(WCHAR));
  888. if (!SUCCEEDED(hr) || !*szDeviceNameW) {
  889. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CWIAScannerDevice::Initialize, couldn't get device port"));
  890. return hr;
  891. }
  892. uiNameLen = WideCharToMultiByte(CP_ACP, 0, szDeviceNameW, -1, NULL, NULL, 0, 0);
  893. if (!uiNameLen) {
  894. return STIERR_INVALID_PARAM;
  895. }
  896. m_pszDeviceNameA = new CHAR[uiNameLen+1];
  897. if (!m_pszDeviceNameA) {
  898. return STIERR_INVALID_PARAM;
  899. }
  900. WideCharToMultiByte(CP_ACP, 0, szDeviceNameW, -1, m_pszDeviceNameA, uiNameLen, 0, 0);
  901. //
  902. // Uncomment the comment block below to have the driver create the kernel mode file
  903. // handles.
  904. //
  905. /*
  906. //
  907. // Open kernel mode device driver.
  908. //
  909. m_DeviceDefaultDataHandle = CreateFileA(m_pszDeviceNameA,
  910. GENERIC_READ | GENERIC_WRITE, // Access mask
  911. 0, // Share mode
  912. NULL, // SA
  913. OPEN_EXISTING, // Create disposition
  914. FILE_ATTRIBUTE_SYSTEM, // Attributes
  915. NULL );
  916. m_dwLastOperationError = ::GetLastError();
  917. hr = (m_DeviceDefaultDataHandle != INVALID_HANDLE_VALUE) ?
  918. S_OK : MAKE_HRESULT(SEVERITY_ERROR,FACILITY_WIN32,m_dwLastOperationError);
  919. if (FAILED(hr)) {
  920. return hr;
  921. }
  922. */
  923. //
  924. // Load BITMAP file, (used only as sample scanned data by sample scanner driver)
  925. //
  926. if (SUCCEEDED(hr)) {
  927. hr = CreateInstance(&m_pScanAPI,SCROLLFED_SCANNER_MODE);
  928. if (m_pScanAPI) {
  929. hr = m_pScanAPI->FakeScanner_Initialize();
  930. } else {
  931. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("Initialize, Could not create FakeScanner API object"));
  932. hr = E_OUTOFMEMORY;
  933. WIAS_LHRESULT(m_pIWiaLog, hr);
  934. }
  935. }
  936. //
  937. // Open DeviceData section to read driver specific information
  938. //
  939. HKEY hKey = hParametersKey;
  940. HKEY hOpenKey = NULL;
  941. if (RegOpenKeyEx(hKey, // handle to open key
  942. TEXT("DeviceData"), // address of name of subkey to open
  943. 0, // options (must be NULL)
  944. KEY_QUERY_VALUE|KEY_READ, // just want to QUERY a value
  945. &hOpenKey // address of handle to open key
  946. ) == ERROR_SUCCESS) {
  947. //
  948. // This is where you read registry entries for your device.
  949. // The DeviceData section is the proper place to put this information
  950. //
  951. //
  952. // close registry key when finished
  953. //
  954. RegCloseKey(hOpenKey);
  955. } else {
  956. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CWIAScannerDevice::Initialize, couldn't open DeviceData KEY"));
  957. return E_FAIL;
  958. }
  959. return hr;
  960. }
  961. /**************************************************************************\
  962. * CWIAScannerDevice::DoEventProcessing
  963. *
  964. * Process device events
  965. *
  966. * Arguments:
  967. *
  968. *
  969. * Return Value:
  970. *
  971. * Status.
  972. *
  973. * History:
  974. *
  975. * 7/18/2000 Original Version
  976. *
  977. \**************************************************************************/
  978. HRESULT CWIAScannerDevice::DoEventProcessing()
  979. {
  980. HRESULT hr = S_OK;
  981. OVERLAPPED Overlapped;
  982. ZeroMemory( &Overlapped, sizeof( Overlapped ));
  983. //
  984. // create an Event for the device to signal
  985. //
  986. Overlapped.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
  987. BYTE InterruptData = 0;
  988. DWORD dwIndex = 0;
  989. DWORD dwError = 0;
  990. LONG lButtonIndex = ID_FAKE_NOEVENT;
  991. //
  992. // initialize the Event handle array for WaitForMultipleObjects() call
  993. //
  994. HANDLE hEventArray[2] = {m_hShutdownEvent, Overlapped.hEvent};
  995. //
  996. // Initialize thread control variables
  997. //
  998. BOOL fLooping = TRUE;
  999. BOOL bRet = TRUE;
  1000. while (fLooping) {
  1001. #ifdef _USE_REAL_DEVICE_FOR_EVENTS
  1002. //
  1003. // use the following call for interrupt events on your device
  1004. //
  1005. bRet = DeviceIoControl( m_DeviceDefaultDataHandle,
  1006. IOCTL_WAIT_ON_DEVICE_EVENT,
  1007. NULL,
  1008. 0,
  1009. &InterruptData,
  1010. sizeof(InterruptData),
  1011. &dwError,
  1012. &Overlapped );
  1013. #else
  1014. //
  1015. // This for the FakeScanner API calls
  1016. //
  1017. bRet = TRUE;
  1018. m_pScanAPI->FakeScanner_SetInterruptEventHandle(Overlapped.hEvent);
  1019. #endif
  1020. if ( bRet || ( !bRet && ( ::GetLastError() == ERROR_IO_PENDING ))) {
  1021. //
  1022. // wait for event to happen from device, or a Shutdown event from the WIA service
  1023. //
  1024. dwIndex = WaitForMultipleObjects( 2, hEventArray,FALSE, INFINITE );
  1025. //
  1026. // determine how to handle event from device here
  1027. //
  1028. switch ( dwIndex ) {
  1029. case WAIT_OBJECT_0+1: // EVENT FROM THE DEVICE
  1030. #ifdef _USE_REAL_DEVICE_FOR_EVENTS
  1031. DWORD dwBytesRet = 0;
  1032. //
  1033. // use the following call for interrupt events on your device
  1034. //
  1035. bRet = GetOverlappedResult( m_DeviceDefaultDataHandle, &Overlapped, &dwBytesRet, FALSE );
  1036. #else
  1037. //
  1038. // Fake Scanner API
  1039. //
  1040. //
  1041. // check for device event information
  1042. //
  1043. lButtonIndex = ID_FAKE_NOEVENT;
  1044. hr = m_pScanAPI->FakeScanner_GetDeviceEvent(&lButtonIndex);
  1045. if (SUCCEEDED(hr)) {
  1046. switch (lButtonIndex) {
  1047. case ID_FAKE_SCANBUTTON:
  1048. m_guidLastEvent = WIA_EVENT_SCAN_IMAGE;
  1049. break;
  1050. case ID_FAKE_COPYBUTTON:
  1051. m_guidLastEvent = WIA_EVENT_SCAN_PRINT_IMAGE;
  1052. break;
  1053. case ID_FAKE_FAXBUTTON:
  1054. m_guidLastEvent = WIA_EVENT_SCAN_FAX_IMAGE;
  1055. break;
  1056. default:
  1057. m_guidLastEvent = GUID_NULL;
  1058. break;
  1059. }
  1060. if (m_guidLastEvent != GUID_NULL) {
  1061. SetEvent(m_hSignalEvent);
  1062. }
  1063. }
  1064. #endif
  1065. //
  1066. // manually reset device event, after it has been signaled
  1067. //
  1068. ResetEvent( Overlapped.hEvent );
  1069. break;
  1070. case WAIT_OBJECT_0: // SHUTDOWN EVENT
  1071. default:
  1072. fLooping = FALSE; // for loop to stop
  1073. }
  1074. } else {
  1075. dwError = ::GetLastError();
  1076. break;
  1077. }
  1078. } // end while (fLooping)
  1079. return hr;
  1080. }
  1081. ////////////////////////////////////////////////////////////////////////////////////////
  1082. // THREADS SECTION //
  1083. ////////////////////////////////////////////////////////////////////////////////////////
  1084. VOID EventThread( LPVOID lpParameter )
  1085. {
  1086. PWIASCANNERDEVICE pThisDevice = (PWIASCANNERDEVICE)lpParameter;
  1087. pThisDevice->DoEventProcessing();
  1088. }