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.

1151 lines
34 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(65535),
  86. m_MinBufferSize(65535),
  87. m_bDeviceLocked(FALSE),
  88. m_DeviceDefaultDataHandle(NULL),
  89. m_bLegacyBWRestriction(FALSE),
  90. m_pszDeviceNameA(NULL),
  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 wiafbdrv.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. hr = S_OK;
  136. }
  137. #endif
  138. __try {
  139. if(!InitializeCriticalSectionAndSpinCount(&m_csShutdown, MINLONG)) {
  140. hr = HRESULT_FROM_WIN32(::GetLastError());
  141. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CWIAScannerDevice::PrivateInitialize, create shutdown critsect failed"));
  142. }
  143. }
  144. __except(EXCEPTION_EXECUTE_HANDLER) {
  145. hr = E_OUTOFMEMORY;
  146. }
  147. if(hr == S_OK) {
  148. // Create event for syncronization of notifications shutdown.
  149. m_hShutdownEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
  150. if (m_hShutdownEvent && (INVALID_HANDLE_VALUE != m_hShutdownEvent)) {
  151. m_fValid = TRUE;
  152. } else {
  153. hr = HRESULT_FROM_WIN32(::GetLastError());
  154. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CWIAScannerDevice::PrivateInitialize, create shutdown event failed"));
  155. }
  156. }
  157. return hr;
  158. }
  159. /**************************************************************************\
  160. * CWIAScannerDevice::~CWIAScannerDevice
  161. *
  162. * Device class destructor
  163. *
  164. * Arguments:
  165. *
  166. * None
  167. *
  168. * Return Value:
  169. *
  170. * None
  171. *
  172. * History:
  173. *
  174. * 7/18/2000 Original Version
  175. *
  176. \**************************************************************************/
  177. CWIAScannerDevice::~CWIAScannerDevice(void)
  178. {
  179. if(m_pScanAPI)
  180. m_pScanAPI->UnInitialize();
  181. // Kill notification thread if it exists.
  182. SetNotificationHandle(NULL);
  183. // Close event for syncronization of notifications shutdown.
  184. if (m_hShutdownEvent && (m_hShutdownEvent != INVALID_HANDLE_VALUE)) {
  185. CloseHandle(m_hShutdownEvent);
  186. m_hShutdownEvent = NULL;
  187. }
  188. // Release the device control interface.
  189. if (m_pIStiDevControl) {
  190. m_pIStiDevControl->Release();
  191. m_pIStiDevControl = NULL;
  192. }
  193. //
  194. // WIA member destruction
  195. //
  196. // Tear down the driver item tree.
  197. if (m_pIDrvItemRoot) {
  198. WIAS_LWARNING(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("~CWIAScannerDevice, Deleting Device Item Tree (this is OK)"));
  199. DeleteItemTree();
  200. m_pIDrvItemRoot = NULL;
  201. }
  202. // free any IO handles opened
  203. if(m_DeviceDefaultDataHandle){
  204. WIAS_LWARNING(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("~CWIAScannerDevice, Closing DefaultDeviceDataHandle"));
  205. CloseHandle(m_DeviceDefaultDataHandle);
  206. m_DeviceDefaultDataHandle = NULL;
  207. }
  208. // Cleanup the WIA event sink.
  209. if (m_pIWiaEventCallback) {
  210. m_pIWiaEventCallback->Release();
  211. m_pIWiaEventCallback = NULL;
  212. }
  213. // Free the storage for the device ID.
  214. if (m_bstrDeviceID) {
  215. SysFreeString(m_bstrDeviceID);
  216. m_bstrDeviceID = NULL;
  217. }
  218. // Release the objects supporting device property storage.
  219. if (m_bstrRootFullItemName) {
  220. SysFreeString(m_bstrRootFullItemName);
  221. m_bstrRootFullItemName = NULL;
  222. }
  223. // Delete allocated arrays
  224. DeleteCapabilitiesArrayContents();
  225. DeleteSupportedIntentsArrayContents();
  226. // Free the critical section.
  227. DeleteCriticalSection(&m_csShutdown);
  228. if(m_pIWiaLog)
  229. m_pIWiaLog->Release();
  230. if(m_pScanAPI)
  231. delete m_pScanAPI;
  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->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. hr = m_pScanAPI->GetDeviceEvent(&m_guidLastEvent);
  317. if(SUCCEEDED(hr)){
  318. if(m_guidLastEvent != GUID_NULL){
  319. pDevStatus->dwEventHandlingState |= STI_EVENTHANDLING_PENDING;
  320. }
  321. }
  322. }
  323. return STI_OK;
  324. }
  325. /**************************************************************************\
  326. * CWIAScannerDevice::DeviceReset
  327. *
  328. * Reset device.
  329. *
  330. * Arguments:
  331. *
  332. * None
  333. *
  334. * Return Value:
  335. *
  336. * Status.
  337. *
  338. * History:
  339. *
  340. * 7/18/2000 Original Version
  341. *
  342. \**************************************************************************/
  343. STDMETHODIMP CWIAScannerDevice::DeviceReset(void)
  344. {
  345. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  346. WIALOG_NO_RESOURCE_ID,
  347. WIALOG_LEVEL3,
  348. "CWIAScannerDevice::DeviceReset");
  349. return m_pScanAPI->ResetDevice();
  350. }
  351. /**************************************************************************\
  352. * CWIAScannerDevice::Diagnostic
  353. *
  354. * The test device always passes the diagnostic.
  355. *
  356. * Arguments:
  357. *
  358. * pBuffer - Pointer o diagnostic result data.
  359. *
  360. * Return Value:
  361. *
  362. * None
  363. *
  364. * History:
  365. *
  366. * 7/18/2000 Original Version
  367. *
  368. \**************************************************************************/
  369. STDMETHODIMP CWIAScannerDevice::Diagnostic(LPSTI_DIAG pBuffer)
  370. {
  371. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  372. WIALOG_NO_RESOURCE_ID,
  373. WIALOG_LEVEL3,
  374. "CWIAScannerDevice::Diagnostic");
  375. // Initialize response buffer
  376. memset(&pBuffer->sErrorInfo,0,sizeof(pBuffer->sErrorInfo));
  377. pBuffer->dwStatusMask = 0;
  378. pBuffer->sErrorInfo.dwGenericError = NOERROR;
  379. pBuffer->sErrorInfo.dwVendorError = 0;
  380. return m_pScanAPI->Diagnostic();
  381. }
  382. /**************************************************************************\
  383. * CWIAScannerDevice::SetNotificationHandle
  384. *
  385. * Starts and stops the event notification thread.
  386. *
  387. * Arguments:
  388. *
  389. * hEvent - If not valid start the notification thread otherwise kill
  390. * the notification thread.
  391. *
  392. * Return Value:
  393. *
  394. * Status.
  395. *
  396. * History:
  397. *
  398. * 7/18/2000 Original Version
  399. *
  400. \**************************************************************************/
  401. STDMETHODIMP CWIAScannerDevice::SetNotificationHandle(HANDLE hEvent)
  402. {
  403. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  404. WIALOG_NO_RESOURCE_ID,
  405. WIALOG_LEVEL3,
  406. "CWIAScannerDevice::SetNotificationHandle");
  407. HRESULT hr = STI_OK;
  408. EnterCriticalSection(&m_csShutdown);
  409. // Are we starting or stopping the notification thread?
  410. if (hEvent && (hEvent != INVALID_HANDLE_VALUE)) {
  411. WIAS_LWARNING(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SetNotificationHandle, hEvent = %d",hEvent));
  412. m_hSignalEvent = hEvent;
  413. m_guidLastEvent = GUID_NULL;
  414. if (NULL == m_hEventNotifyThread) {
  415. DWORD dwThread = 0;
  416. m_hEventNotifyThread = ::CreateThread(NULL,
  417. 0,
  418. (LPTHREAD_START_ROUTINE)EventThread,
  419. (LPVOID)this,
  420. 0,
  421. &dwThread);
  422. if (!m_hEventNotifyThread) {
  423. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("FlatbedScannerUsdDevice::SetNotificationHandle, CreateThread failed"));
  424. hr = STIERR_UNSUPPORTED;
  425. }
  426. }
  427. } else {
  428. WIAS_LWARNING(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SetNotificationHandle, Disabling event Notifications"));
  429. // Disable event notifications.
  430. if (m_hShutdownEvent && (m_hShutdownEvent != INVALID_HANDLE_VALUE)) {
  431. if (!SetEvent(m_hShutdownEvent)) {
  432. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SetNotificationHandle, Setting Shutdown event failed.."));
  433. } else {
  434. //
  435. // WAIT for thread to terminate, only if the m_hEventNotifyThread is not NULL
  436. //
  437. if (NULL != m_hEventNotifyThread) {
  438. WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("SetNotificationHandle, Waiting for Event Thread to terminate (%d ms timeout)",THREAD_TERMINATION_TIMEOUT));
  439. DWORD dwResult = WaitForSingleObject(m_hEventNotifyThread,THREAD_TERMINATION_TIMEOUT);
  440. switch (dwResult) {
  441. case WAIT_TIMEOUT:
  442. WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("SetNotificationHandle, Event Thread termination TIMED OUT!"));
  443. break;
  444. case WAIT_OBJECT_0:
  445. WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("SetNotificationHandle, We are signaled...YAY!"));
  446. break;
  447. case WAIT_ABANDONED:
  448. WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("SetNotificationHandle, Event Thread was abandoned.."));
  449. break;
  450. default:
  451. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SetNotificationHandle, Unknown signal (%d) received from WaitForSingleObject() call",dwResult));
  452. break;
  453. }
  454. }
  455. //
  456. // Close event for syncronization of notifications shutdown.
  457. //
  458. WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("SetNotificationHandle, Closing m_hShutdownEvent handle (it has been signaled)"));
  459. CloseHandle(m_hShutdownEvent);
  460. m_hShutdownEvent = NULL;
  461. }
  462. }
  463. //
  464. // terminate thread
  465. //
  466. if (NULL != m_hEventNotifyThread) {
  467. WIAS_LWARNING(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SetNotificationHandle, closing event Notifications thread handle"));
  468. CloseHandle(m_hEventNotifyThread);
  469. m_hEventNotifyThread = NULL;
  470. }
  471. m_guidLastEvent = GUID_NULL;
  472. }
  473. LeaveCriticalSection(&m_csShutdown);
  474. return hr;
  475. }
  476. /**************************************************************************\
  477. * CWIAScannerDevice::GetNotificationData
  478. *
  479. * Provides data on an event.
  480. *
  481. * Arguments:
  482. *
  483. * pBuffer - Pointer to event data.
  484. *
  485. * Return Value:
  486. *
  487. * Status.
  488. *
  489. * History:
  490. *
  491. * 7/18/2000 Original Version
  492. *
  493. \**************************************************************************/
  494. STDMETHODIMP CWIAScannerDevice::GetNotificationData( LPSTINOTIFY pBuffer )
  495. {
  496. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  497. WIALOG_NO_RESOURCE_ID,
  498. WIALOG_LEVEL3,
  499. "CWIAScannerDevice::GetNotificationData");
  500. // If we have notification ready - return it's guid
  501. if (!IsEqualIID(m_guidLastEvent, GUID_NULL)) {
  502. memset(&pBuffer->abNotificationData,0,sizeof(pBuffer->abNotificationData));
  503. pBuffer->dwSize = sizeof(STINOTIFY);
  504. pBuffer->guidNotificationCode = m_guidLastEvent;
  505. m_guidLastEvent = GUID_NULL;
  506. } else {
  507. return STIERR_NOEVENTS;
  508. }
  509. return STI_OK;
  510. }
  511. /**************************************************************************\
  512. * CWIAScannerDevice::Escape
  513. *
  514. * Issue a command to the device.
  515. *
  516. * Arguments:
  517. *
  518. * EscapeFunction - Command to be issued.
  519. * pInData - Input data to be passed with command.
  520. * cbInDataSize - Size of input data.
  521. * pOutData - Output data to be passed back from command.
  522. * cbOutDataSize - Size of output data buffer.
  523. * pcbActualData - Size of output data actually written.
  524. *
  525. * Return Value:
  526. *
  527. * None
  528. *
  529. * History:
  530. *
  531. * 7/18/2000 Original Version
  532. *
  533. \**************************************************************************/
  534. STDMETHODIMP CWIAScannerDevice::Escape(
  535. STI_RAW_CONTROL_CODE EscapeFunction,
  536. LPVOID pInData,
  537. DWORD cbInDataSize,
  538. LPVOID pOutData,
  539. DWORD cbOutDataSize,
  540. LPDWORD pcbActualData)
  541. {
  542. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  543. WIALOG_NO_RESOURCE_ID,
  544. WIALOG_LEVEL3,
  545. "CWIAScannerDevice::Escape");
  546. // Write command to device if needed.
  547. return STIERR_UNSUPPORTED;
  548. }
  549. /**************************************************************************\
  550. * CWIAScannerDevice::GetLastError
  551. *
  552. * Get the last error from the device.
  553. *
  554. * Arguments:
  555. *
  556. * pdwLastDeviceError - Pointer to last error data.
  557. *
  558. * Return Value:
  559. *
  560. * Status.
  561. *
  562. * History:
  563. *
  564. * 7/18/2000 Original Version
  565. *
  566. \**************************************************************************/
  567. STDMETHODIMP CWIAScannerDevice::GetLastError(LPDWORD pdwLastDeviceError)
  568. {
  569. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  570. WIALOG_NO_RESOURCE_ID,
  571. WIALOG_LEVEL3,
  572. "CWIAScannerDevice::GetLastError");
  573. if (IsBadWritePtr(pdwLastDeviceError, sizeof(DWORD))) {
  574. return STIERR_INVALID_PARAM;
  575. }
  576. *pdwLastDeviceError = m_dwLastOperationError;
  577. return STI_OK;
  578. }
  579. /**************************************************************************\
  580. * CWIAScannerDevice::GetLastErrorInfo
  581. *
  582. * Get extended error information from the device.
  583. *
  584. * Arguments:
  585. *
  586. * pLastErrorInfo - Pointer to extended device error data.
  587. *
  588. * Return Value:
  589. *
  590. * Status.
  591. *
  592. * History:
  593. *
  594. * 7/18/2000 Original Version
  595. *
  596. \**************************************************************************/
  597. STDMETHODIMP CWIAScannerDevice::GetLastErrorInfo(STI_ERROR_INFO *pLastErrorInfo)
  598. {
  599. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  600. WIALOG_NO_RESOURCE_ID,
  601. WIALOG_LEVEL3,
  602. "CWIAScannerDevice::GetLastErrorInfo");
  603. if (IsBadWritePtr(pLastErrorInfo, sizeof(STI_ERROR_INFO))) {
  604. return STIERR_INVALID_PARAM;
  605. }
  606. pLastErrorInfo->dwGenericError = m_dwLastOperationError;
  607. pLastErrorInfo->szExtendedErrorText[0] = '\0';
  608. return STI_OK;
  609. }
  610. /**************************************************************************\
  611. * CWIAScannerDevice::LockDevice
  612. *
  613. * Lock access to the device.
  614. *
  615. * Arguments:
  616. *
  617. * None
  618. *
  619. * Return Value:
  620. *
  621. * Status.
  622. *
  623. * History:
  624. *
  625. * 7/18/2000 Original Version
  626. *
  627. \**************************************************************************/
  628. STDMETHODIMP CWIAScannerDevice::LockDevice(void)
  629. {
  630. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  631. WIALOG_NO_RESOURCE_ID,
  632. WIALOG_LEVEL3,
  633. "CWIAScannerDevice::LockDevice");
  634. HRESULT hr = STI_OK;
  635. if(m_bDeviceLocked){
  636. WIAS_LWARNING(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("LockDevice, Device is already locked!!"));
  637. hr = STIERR_DEVICE_LOCKED;
  638. } else {
  639. m_bDeviceLocked = TRUE;
  640. WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("LockDevice, Locking Device successful"));
  641. }
  642. return hr;
  643. }
  644. /**************************************************************************\
  645. * CWIAScannerDevice::UnLockDevice
  646. *
  647. * Unlock access to the device.
  648. *
  649. * Arguments:
  650. *
  651. * None
  652. *
  653. * Return Value:
  654. *
  655. * Status.
  656. *
  657. * History:
  658. *
  659. * 7/18/2000 Original Version
  660. *
  661. \**************************************************************************/
  662. STDMETHODIMP CWIAScannerDevice::UnLockDevice(void)
  663. {
  664. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  665. WIALOG_NO_RESOURCE_ID,
  666. WIALOG_LEVEL3,
  667. "CWIAScannerDevice::UnLockDevice");
  668. HRESULT hr = STI_OK;
  669. if(!m_bDeviceLocked)
  670. hr = STIERR_NEEDS_LOCK;
  671. else {
  672. m_bDeviceLocked = FALSE;
  673. }
  674. return hr;
  675. }
  676. /**************************************************************************\
  677. * CWIAScannerDevice::RawReadData
  678. *
  679. * Read raw data from the device.
  680. *
  681. * Arguments:
  682. *
  683. * lpBuffer - buffer for returned data
  684. * lpdwNumberOfBytes - number of bytes to read/returned
  685. * lpOverlapped - overlap
  686. *
  687. * Return Value:
  688. *
  689. * Status.
  690. *
  691. * History:
  692. *
  693. * 7/18/2000 Original Version
  694. *
  695. \**************************************************************************/
  696. STDMETHODIMP CWIAScannerDevice::RawReadData(
  697. LPVOID lpBuffer,
  698. LPDWORD lpdwNumberOfBytes,
  699. LPOVERLAPPED lpOverlapped)
  700. {
  701. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  702. WIALOG_NO_RESOURCE_ID,
  703. WIALOG_LEVEL3,
  704. "CWIAScannerDevice::RawReadData");
  705. HRESULT hr = STI_OK;
  706. BOOL fRet = FALSE;
  707. DWORD dwBytesReturned = 0;
  708. if (INVALID_HANDLE_VALUE != m_DeviceDefaultDataHandle) {
  709. fRet = ReadFile( m_DeviceDefaultDataHandle,
  710. lpBuffer,
  711. *lpdwNumberOfBytes,
  712. &dwBytesReturned,
  713. lpOverlapped );
  714. m_dwLastOperationError = ::GetLastError();
  715. hr = fRet ? STI_OK : HRESULT_FROM_WIN32(m_dwLastOperationError);
  716. *lpdwNumberOfBytes = (fRet) ? dwBytesReturned : 0;
  717. } else {
  718. hr = STIERR_NOT_INITIALIZED;
  719. }
  720. return hr;
  721. }
  722. /**************************************************************************\
  723. * CWIAScannerDevice::RawWriteData
  724. *
  725. * Write raw data to the device.
  726. *
  727. * Arguments:
  728. *
  729. * lpBuffer - buffer for returned data
  730. * dwNumberOfBytes - number of bytes to write
  731. * lpOverlapped - overlap
  732. *
  733. * Return Value:
  734. *
  735. * Status.
  736. *
  737. * History:
  738. *
  739. * 7/18/2000 Original Version
  740. *
  741. \**************************************************************************/
  742. STDMETHODIMP CWIAScannerDevice::RawWriteData(
  743. LPVOID lpBuffer,
  744. DWORD dwNumberOfBytes,
  745. LPOVERLAPPED lpOverlapped)
  746. {
  747. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  748. WIALOG_NO_RESOURCE_ID,
  749. WIALOG_LEVEL3,
  750. "CWIAScannerDevice::RawWriteData");
  751. HRESULT hr = STI_OK;
  752. BOOL fRet = FALSE;
  753. DWORD dwBytesReturned = 0;
  754. if (INVALID_HANDLE_VALUE != m_DeviceDefaultDataHandle) {
  755. fRet = WriteFile(m_DeviceDefaultDataHandle,lpBuffer,dwNumberOfBytes,&dwBytesReturned,lpOverlapped);
  756. m_dwLastOperationError = ::GetLastError();
  757. hr = fRet ? STI_OK : HRESULT_FROM_WIN32(m_dwLastOperationError);
  758. } else {
  759. hr = STIERR_NOT_INITIALIZED;
  760. }
  761. return STI_OK;
  762. }
  763. /**************************************************************************\
  764. * CWIAScannerDevice::RawReadCommand
  765. *
  766. *
  767. *
  768. * Arguments:
  769. *
  770. * lpBuffer - buffer for returned data
  771. * lpdwNumberOfBytes - number of bytes to read/returned
  772. * lpOverlapped - overlap
  773. *
  774. * Return Value:
  775. *
  776. * Status
  777. *
  778. * History:
  779. *
  780. * 7/18/2000 Original Version
  781. *
  782. \**************************************************************************/
  783. STDMETHODIMP CWIAScannerDevice::RawReadCommand(
  784. LPVOID lpBuffer,
  785. LPDWORD lpdwNumberOfBytes,
  786. LPOVERLAPPED lpOverlapped)
  787. {
  788. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  789. WIALOG_NO_RESOURCE_ID,
  790. WIALOG_LEVEL3,
  791. "CWIAScannerDevice::RawReadCommand");
  792. return STIERR_UNSUPPORTED;
  793. }
  794. /**************************************************************************\
  795. * CWIAScannerDevice::RawWriteCommand
  796. *
  797. *
  798. *
  799. * Arguments:
  800. *
  801. * lpBuffer - buffer for returned data
  802. * nNumberOfBytes - number of bytes to write
  803. * lpOverlapped - overlap
  804. *
  805. * Return Value:
  806. *
  807. * Status.
  808. *
  809. * History:
  810. *
  811. * 7/18/2000 Original Version
  812. *
  813. \**************************************************************************/
  814. STDMETHODIMP CWIAScannerDevice::RawWriteCommand(
  815. LPVOID lpBuffer,
  816. DWORD nNumberOfBytes,
  817. LPOVERLAPPED lpOverlapped)
  818. {
  819. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  820. WIALOG_NO_RESOURCE_ID,
  821. WIALOG_LEVEL3,
  822. "CWIAScannerDevice::RawWriteCommand");
  823. return STIERR_UNSUPPORTED;
  824. }
  825. /**************************************************************************\
  826. * CWIAScannerDevice::Initialize
  827. *
  828. * Initialize the device object.
  829. *
  830. * Arguments:
  831. *
  832. * pIStiDevControlNone - device interface
  833. * dwStiVersion - STI version
  834. * hParametersKey - HKEY for registry reading/writing
  835. *
  836. * Return Value:
  837. *
  838. * Status.
  839. *
  840. * History:
  841. *
  842. * 7/18/2000 Original Version
  843. *
  844. \**************************************************************************/
  845. STDMETHODIMP CWIAScannerDevice::Initialize(
  846. PSTIDEVICECONTROL pIStiDevControl,
  847. DWORD dwStiVersion,
  848. HKEY hParametersKey)
  849. {
  850. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  851. WIALOG_NO_RESOURCE_ID,
  852. WIALOG_LEVEL3,
  853. "CWIAScannerDevice::Initialize");
  854. HRESULT hr = STI_OK;
  855. WCHAR szDeviceNameW[255];
  856. TCHAR szGSDName[255];
  857. TCHAR szMICRO[255];
  858. TCHAR szResolutions[255];
  859. UINT uiNameLen = 0;
  860. INITINFO InitInfo;
  861. memset(&InitInfo,0,sizeof(InitInfo));
  862. if (!pIStiDevControl) {
  863. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CWIAScannerDevice::Initialize, invalid device control interface"));
  864. return STIERR_INVALID_PARAM;
  865. }
  866. // Cache the device control interface.
  867. m_pIStiDevControl = pIStiDevControl;
  868. m_pIStiDevControl->AddRef();
  869. //
  870. // Get the name of the device port
  871. //
  872. hr = m_pIStiDevControl->GetMyDevicePortName(szDeviceNameW,sizeof(szDeviceNameW)/sizeof(WCHAR));
  873. if (!SUCCEEDED(hr) || !*szDeviceNameW) {
  874. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CWIAScannerDevice::Initialize, couldn't get device port"));
  875. return hr;
  876. }
  877. uiNameLen = WideCharToMultiByte(CP_ACP, 0, szDeviceNameW, -1, NULL, NULL, 0, 0);
  878. if (!uiNameLen) {
  879. return STIERR_INVALID_PARAM;
  880. }
  881. m_pszDeviceNameA = new CHAR[uiNameLen+1];
  882. if (!m_pszDeviceNameA) {
  883. return STIERR_INVALID_PARAM;
  884. }
  885. WideCharToMultiByte(CP_ACP, 0, szDeviceNameW, -1, m_pszDeviceNameA, uiNameLen, 0, 0);
  886. //
  887. // Open kernel mode device driver.
  888. //
  889. m_DeviceDefaultDataHandle = CreateFileA(m_pszDeviceNameA,
  890. GENERIC_READ | GENERIC_WRITE, // Access mask
  891. 0, // Share mode
  892. NULL, // SA
  893. OPEN_EXISTING, // Create disposition
  894. FILE_ATTRIBUTE_SYSTEM, // Attributes
  895. NULL );
  896. m_dwLastOperationError = ::GetLastError();
  897. hr = (m_DeviceDefaultDataHandle != INVALID_HANDLE_VALUE) ?
  898. S_OK : MAKE_HRESULT(SEVERITY_ERROR,FACILITY_WIN32,m_dwLastOperationError);
  899. if (FAILED(hr)) {
  900. return hr;
  901. }
  902. InitInfo.hDeviceDataHandle = m_DeviceDefaultDataHandle;
  903. InitInfo.szCreateFileName = m_pszDeviceNameA;
  904. //
  905. // Open DeviceData section to read driver specific information
  906. //
  907. HKEY hKey = hParametersKey;
  908. HKEY hOpenKey = NULL;
  909. if (RegOpenKeyEx(hKey, // handle to open key
  910. TEXT("DeviceData"), // address of name of subkey to open
  911. 0, // options (must be NULL)
  912. KEY_QUERY_VALUE|KEY_READ, // just want to QUERY a value
  913. &hOpenKey // address of handle to open key
  914. ) == ERROR_SUCCESS) {
  915. DWORD dwWritten = sizeof(DWORD);
  916. DWORD dwType = REG_DWORD;
  917. /////////////////////////////////////////////////////////////////////////////
  918. // legacy MicroDriver registry entries, for BW scanners //
  919. /////////////////////////////////////////////////////////////////////////////
  920. LONG lNoColor = 0;
  921. RegQueryValueEx(hOpenKey,
  922. TEXT("NoColor"),
  923. NULL,
  924. &dwType,
  925. (LPBYTE)&lNoColor,
  926. &dwWritten);
  927. if (lNoColor == 1) {
  928. m_bLegacyBWRestriction = TRUE;
  929. }
  930. /////////////////////////////////////////////////////////////////////////////
  931. // Micro driver registry entries, for ***mcro.dll loading //
  932. /////////////////////////////////////////////////////////////////////////////
  933. dwWritten = sizeof(szMICRO);
  934. dwType = REG_SZ;
  935. ZeroMemory(szMICRO,sizeof(szMICRO));
  936. //
  937. // Read Micro driver name
  938. //
  939. if (RegQueryValueEx(hOpenKey,
  940. TEXT("MicroDriver"),
  941. NULL,
  942. &dwType,
  943. (LPBYTE)szMICRO,
  944. &dwWritten) == ERROR_SUCCESS) {
  945. m_pScanAPI = new CMicroDriverAPI;
  946. InitInfo.szModuleFileName = szMICRO;
  947. }
  948. /////////////////////////////////////////////////////////////////////////////
  949. // resolution registry entries, for micro driver resolution restrictions //
  950. /////////////////////////////////////////////////////////////////////////////
  951. dwWritten = sizeof(szResolutions);
  952. dwType = REG_SZ;
  953. ZeroMemory(szGSDName,sizeof(szResolutions));
  954. if (RegQueryValueEx(hOpenKey,
  955. TEXT("Resolutions"),
  956. NULL,
  957. &dwType,
  958. (LPBYTE)szResolutions,
  959. &dwWritten) == ERROR_SUCCESS) {
  960. if(m_pScanAPI){
  961. m_pScanAPI->SetResolutionRestrictionString(szResolutions);
  962. }
  963. }
  964. RegCloseKey(hOpenKey);
  965. } else {
  966. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CWIAScannerDevice::Initialize, couldn't open DeviceData KEY"));
  967. return E_FAIL;
  968. }
  969. //
  970. // give logging interface to SCANAPI object
  971. // so it can log too! (shouldn't leave the little guys out. ;) )
  972. //
  973. m_pScanAPI->SetLoggingInterface(m_pIWiaLog);
  974. // set the HKEY for micro driver's device section
  975. InitInfo.hKEY = hParametersKey;
  976. // initialize the micro driver
  977. hr = m_pScanAPI->Initialize(&InitInfo);
  978. return hr;
  979. }
  980. /**************************************************************************\
  981. * CWIAScannerDevice::DoEventProcessing
  982. *
  983. * Process device events
  984. *
  985. * Arguments:
  986. *
  987. *
  988. * Return Value:
  989. *
  990. * Status.
  991. *
  992. * History:
  993. *
  994. * 7/18/2000 Original Version
  995. *
  996. \**************************************************************************/
  997. HRESULT CWIAScannerDevice::DoEventProcessing()
  998. {
  999. HRESULT hr = S_OK;
  1000. INTERRUPTEVENTINFO EventInfo;
  1001. EventInfo.phSignalEvent = &m_hSignalEvent;
  1002. EventInfo.hShutdownEvent = m_hShutdownEvent;
  1003. EventInfo.pguidEvent = &m_guidLastEvent;
  1004. EventInfo.szDeviceName = m_pszDeviceNameA;
  1005. hr = m_pScanAPI->DoInterruptEventThread(&EventInfo);
  1006. // close the thread handle, when the thread exits
  1007. CloseHandle(m_hEventNotifyThread);
  1008. m_hEventNotifyThread = NULL;
  1009. return hr;
  1010. }
  1011. ////////////////////////////////////////////////////////////////////////////////////////
  1012. // THREADS SECTION //
  1013. ////////////////////////////////////////////////////////////////////////////////////////
  1014. VOID EventThread( LPVOID lpParameter )
  1015. {
  1016. PWIASCANNERDEVICE pThisDevice = (PWIASCANNERDEVICE)lpParameter;
  1017. pThisDevice->DoEventProcessing();
  1018. }