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.

1566 lines
45 KiB

  1. /**************************************************************************
  2. *
  3. * (C) COPYRIGHT MICROSOFT CORP., 2000
  4. *
  5. * TITLE: scanapi.cpp
  6. *
  7. * VERSION: 1.0
  8. *
  9. * DATE: 18 July, 2000
  10. *
  11. * DESCRIPTION:
  12. * Fake Scanner device library
  13. *
  14. ***************************************************************************/
  15. #include "pch.h"
  16. #include "scanapi.h" // private header for SCANAPI
  17. #include "time.h"
  18. #define THREAD_TERMINATION_TIMEOUT 10000
  19. CFScanAPI::CFScanAPI()
  20. {
  21. #ifdef _USE_BITMAP_DATA
  22. m_hSrcFileHandle = NULL;
  23. m_hSrcMappingHandle = NULL;
  24. m_pSrcData = NULL; // 24-bit only
  25. m_pRawData = NULL;
  26. m_hRawDataFileHandle = NULL;
  27. m_hRawDataMappingHandle = NULL;
  28. #endif
  29. m_hEventHandle = NULL;
  30. m_hKillEventThread = NULL;
  31. m_hEventNotifyThread = NULL;
  32. m_lLastEvent = ID_FAKE_NOEVENT;
  33. m_hrLastADFError = S_OK;
  34. m_bGreen = TRUE;
  35. m_dwBytesWrittenSoFAR = 0;
  36. m_TotalDataInDevice = 0;
  37. memset(&m_ftScanButton,0,sizeof(FILETIME));
  38. memset(&m_ftCopyButton,0,sizeof(FILETIME));
  39. memset(&m_ftFaxButton, 0,sizeof(FILETIME));
  40. memset(&m_RawDataInfo, 0,sizeof(RAW_DATA_INFORMATION));
  41. memset(&m_SrcDataInfo, 0,sizeof(RAW_DATA_INFORMATION));
  42. }
  43. CFScanAPI::~CFScanAPI()
  44. {
  45. #ifdef _USE_BITMAP_DATA
  46. if(m_hSrcMappingHandle){
  47. CloseHandle(m_hSrcMappingHandle);
  48. m_hSrcMappingHandle = NULL;
  49. }
  50. if(m_hSrcFileHandle){
  51. CloseHandle(m_hSrcFileHandle);
  52. m_hSrcFileHandle = NULL;
  53. }
  54. CloseRAW();
  55. #endif
  56. }
  57. HRESULT CFScanAPI::FakeScanner_Initialize()
  58. {
  59. HRESULT hr = E_FAIL;
  60. if (NULL == m_hEventNotifyThread) {
  61. //
  62. // create KILL event to signal, for device
  63. // shutdown of the fake scanner's events
  64. //
  65. m_hKillEventThread = CreateEvent(NULL,FALSE,FALSE,NULL);
  66. ::ResetEvent(m_hKillEventThread);
  67. if(NULL != m_hKillEventThread){
  68. //
  69. // create event thread, for file change status to fake scanner events
  70. //
  71. DWORD dwThread = 0;
  72. m_hEventNotifyThread = ::CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)FakeScannerEventThread,
  73. (LPVOID)this,0,&dwThread);
  74. if(NULL != m_hEventNotifyThread){
  75. hr = S_OK;
  76. }
  77. }
  78. }
  79. return hr;
  80. }
  81. HRESULT CFScanAPI::Load24bitScanData(LPTSTR szBitmapFileName)
  82. {
  83. HRESULT hr = S_OK;
  84. #ifdef _USE_BITMAP_DATA
  85. m_hSrcFileHandle = NULL;
  86. m_hSrcFileHandle = CreateFile(szBitmapFileName,GENERIC_READ,FILE_SHARE_READ,NULL,
  87. OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
  88. if(NULL != m_hSrcFileHandle && INVALID_HANDLE_VALUE != m_hSrcFileHandle){
  89. m_hSrcMappingHandle = CreateFileMapping(m_hSrcFileHandle, NULL, PAGE_READONLY, 0, 0, NULL);
  90. m_pSrcData = (PBYTE)MapViewOfFileEx(m_hSrcMappingHandle, FILE_MAP_READ, 0, 0, 0,NULL);
  91. DWORD dwBytesRead = 0;
  92. m_pSrcData = m_pSrcData + sizeof(BITMAPFILEHEADER);
  93. if(m_pSrcData){
  94. //
  95. // check bitmap info
  96. //
  97. BITMAPINFOHEADER *pbmih;
  98. pbmih = (BITMAPINFOHEADER*)m_pSrcData;
  99. if(pbmih->biBitCount != 24){
  100. hr = E_INVALIDARG;
  101. } else {
  102. m_SrcDataInfo.bpp = pbmih->biBitCount;
  103. m_SrcDataInfo.lHeightPixels = pbmih->biHeight;
  104. m_SrcDataInfo.lWidthPixels = pbmih->biWidth;
  105. m_SrcDataInfo.lOffset = 0;
  106. }
  107. }
  108. } else {
  109. hr = E_FAIL;
  110. }
  111. if(FAILED(hr)){
  112. CloseHandle(m_hSrcMappingHandle);
  113. m_hSrcMappingHandle = NULL;
  114. CloseHandle(m_hSrcFileHandle);
  115. m_hSrcFileHandle = NULL;
  116. }
  117. #endif
  118. return hr;
  119. }
  120. HRESULT CFScanAPI::FakeScanner_GetRootPropertyInfo(PROOT_ITEM_INFORMATION pRootItemInfo)
  121. {
  122. HRESULT hr = S_OK;
  123. //
  124. // Fill in Root item property defaults
  125. //
  126. if(m_lMode == SCROLLFED_SCANNER_MODE){
  127. pRootItemInfo->DocumentFeederCaps = FEEDER;
  128. pRootItemInfo->DocumentFeederStatus = FEED_READY;
  129. pRootItemInfo->DocumentFeederHReg = CENTERED;
  130. pRootItemInfo->DocumentFeederReg = CENTERED;
  131. } else {
  132. pRootItemInfo->DocumentFeederCaps = FEEDER|FLATBED;
  133. pRootItemInfo->DocumentFeederStatus = FLAT_READY;
  134. pRootItemInfo->DocumentFeederHReg = LEFT_JUSTIFIED;
  135. pRootItemInfo->DocumentFeederReg = LEFT_JUSTIFIED;
  136. }
  137. pRootItemInfo->DocumentFeederWidth = 8500;
  138. pRootItemInfo->DocumentFeederHeight = 11000;
  139. pRootItemInfo->DocumentFeederHReg = LEFT_JUSTIFIED;
  140. pRootItemInfo->DocumentFeederReg = LEFT_JUSTIFIED;
  141. pRootItemInfo->DocumentFeederVReg = TOP_JUSTIFIED;
  142. pRootItemInfo->MaxPageCapacity = MAX_PAGE_CAPACITY;
  143. pRootItemInfo->MaxScanTime = MAX_SCANNING_TIME;
  144. pRootItemInfo->OpticalXResolution = 300;
  145. pRootItemInfo->OpticalYResolution = 300;
  146. pRootItemInfo->ScanBedWidth = 8500;
  147. pRootItemInfo->ScanBedHeight = 11000;
  148. //
  149. // copy firmware version in string form to WCHAR array
  150. //
  151. lstrcpy(pRootItemInfo->FirmwareVersion,L"1.0a");
  152. return hr;
  153. }
  154. HRESULT CFScanAPI::FakeScanner_GetTopPropertyInfo(PTOP_ITEM_INFORMATION pTopItemInfo)
  155. {
  156. HRESULT hr = S_OK;
  157. pTopItemInfo->bUseResolutionList = TRUE; // use default resolution list
  158. pTopItemInfo->Brightness.lInc = 1;
  159. pTopItemInfo->Brightness.lMax = 200;
  160. pTopItemInfo->Brightness.lMin = -200;
  161. pTopItemInfo->Brightness.lNom = 10;
  162. pTopItemInfo->Contrast.lInc = 1;
  163. pTopItemInfo->Contrast.lMax = 200;
  164. pTopItemInfo->Contrast.lMin = -200;
  165. pTopItemInfo->Contrast.lNom = 10;
  166. pTopItemInfo->Threshold.lInc = 1;
  167. pTopItemInfo->Threshold.lMax = 200;
  168. pTopItemInfo->Threshold.lMin = -200;
  169. pTopItemInfo->Threshold.lNom = 10;
  170. pTopItemInfo->lMaxLampWarmupTime = MAX_LAMP_WARMUP_TIME;
  171. pTopItemInfo->lMinimumBufferSize = 262140;
  172. pTopItemInfo->XResolution.lInc = 1;
  173. pTopItemInfo->XResolution.lMax = 600;
  174. pTopItemInfo->XResolution.lMin = 75;
  175. pTopItemInfo->XResolution.lNom = 150;
  176. pTopItemInfo->YResolution.lInc = 1;
  177. pTopItemInfo->YResolution.lMax = 600;
  178. pTopItemInfo->YResolution.lMin = 75;
  179. pTopItemInfo->YResolution.lNom = 150;
  180. return hr;
  181. }
  182. HRESULT CFScanAPI::FakeScanner_Scan(LONG lState, PBYTE pData, DWORD dwBytesToRead, PDWORD pdwBytesWritten)
  183. {
  184. HRESULT hr = S_OK;
  185. switch (lState) {
  186. case SCAN_START:
  187. m_dwBytesWrittenSoFAR = 0;
  188. m_TotalDataInDevice = CalcRandomDeviceDataTotalBytes();
  189. break;
  190. case SCAN_CONTINUE:
  191. break;
  192. case SCAN_END:
  193. m_bGreen = TRUE; // set back to green
  194. return S_OK;
  195. default:
  196. break;
  197. }
  198. //Trace(TEXT("Requesting %d, of %d Total Image bytes"),dwBytesToRead,m_TotalDataInDevice);
  199. if (NULL != pData) {
  200. switch (m_RawDataInfo.bpp) {
  201. case 24:
  202. {
  203. //
  204. // write green data for color
  205. //
  206. BYTE *pTempData = pData;
  207. for (DWORD dwBytes = 0; dwBytes < dwBytesToRead; dwBytes+=3) {
  208. if(m_bGreen){
  209. pTempData[0] = 0;
  210. pTempData[1] = 128; // green
  211. pTempData[2] = 0;
  212. } else {
  213. pTempData[0] = 0;
  214. pTempData[1] = 0;
  215. pTempData[2] = 128; // blue
  216. }
  217. pTempData += 3;
  218. }
  219. }
  220. break;
  221. case 1:
  222. case 8:
  223. default:
  224. //
  225. // write simple gray for grayscale,
  226. // write vertical B/W stripes for threshold
  227. //
  228. if(m_bGreen){
  229. memset(pData,128,dwBytesToRead);
  230. } else {
  231. memset(pData,200,dwBytesToRead);
  232. }
  233. break;
  234. }
  235. }
  236. //
  237. // fill out bytes written
  238. //
  239. if(NULL != pdwBytesWritten){
  240. *pdwBytesWritten = dwBytesToRead;
  241. }
  242. if (m_bGreen) {
  243. m_bGreen = FALSE;
  244. } else {
  245. m_bGreen = TRUE;
  246. }
  247. if(m_lMode == SCROLLFED_SCANNER_MODE){
  248. //
  249. // keep track of bytes written so far
  250. //
  251. if(m_TotalDataInDevice == 0){
  252. //
  253. // no data left in device
  254. //
  255. *pdwBytesWritten = 0;
  256. Trace(TEXT("Device is out of Data..."));
  257. return hr;
  258. }
  259. if((LONG)dwBytesToRead > m_TotalDataInDevice){
  260. //
  261. // only give what is left in device
  262. //
  263. *pdwBytesWritten = dwBytesToRead;
  264. //*pdwBytesWritten = m_TotalDataInDevice;
  265. //Trace(TEXT("Device only has %d left..."),m_TotalDataInDevice);
  266. m_TotalDataInDevice = 0;
  267. } else {
  268. //
  269. // give full amount requested
  270. //
  271. m_TotalDataInDevice -= dwBytesToRead;
  272. if(m_TotalDataInDevice < 0){
  273. m_TotalDataInDevice = 0;
  274. }
  275. }
  276. }
  277. return hr;
  278. }
  279. HRESULT CFScanAPI::FakeScanner_SetDataType(LONG lDataType)
  280. {
  281. HRESULT hr = S_OK;
  282. switch(lDataType){
  283. case WIA_DATA_COLOR:
  284. m_RawDataInfo.bpp = 24;
  285. break;
  286. case WIA_DATA_THRESHOLD:
  287. m_RawDataInfo.bpp = 1;
  288. break;
  289. case WIA_DATA_GRAYSCALE:
  290. m_RawDataInfo.bpp = 8;
  291. break;
  292. default:
  293. hr = E_INVALIDARG;
  294. break;
  295. }
  296. return hr;
  297. }
  298. HRESULT CFScanAPI::FakeScanner_SetXYResolution(LONG lXResolution, LONG lYResolution)
  299. {
  300. HRESULT hr = S_OK;
  301. m_RawDataInfo.lXRes = lXResolution;
  302. m_RawDataInfo.lYRes = lYResolution;
  303. return hr;
  304. }
  305. HRESULT CFScanAPI::FakeScanner_SetSelectionArea(LONG lXPos, LONG lYPos, LONG lXExt, LONG lYExt)
  306. {
  307. HRESULT hr = S_OK;
  308. //
  309. // record RAW data width and height
  310. //
  311. m_RawDataInfo.lWidthPixels = lXExt;
  312. m_RawDataInfo.lHeightPixels = lYExt;
  313. return hr;
  314. }
  315. HRESULT CFScanAPI::FakeScanner_SetContrast(LONG lContrast)
  316. {
  317. HRESULT hr = S_OK;
  318. //
  319. // do nothing.. we are not concerned with Contrast
  320. //
  321. return hr;
  322. }
  323. HRESULT CFScanAPI::FakeScanner_SetIntensity(LONG lIntensity)
  324. {
  325. HRESULT hr = S_OK;
  326. //
  327. // do nothing.. we are not concerned with Intensity
  328. //
  329. return hr;
  330. }
  331. HRESULT CFScanAPI::FakeScanner_DisableDevice()
  332. {
  333. HRESULT hr = S_OK;
  334. if (m_hKillEventThread) {
  335. //
  336. // signal event thread to shutdown
  337. //
  338. //::SetEvent(m_hKillEventThread);
  339. if (!SetEvent(m_hKillEventThread)) {
  340. hr = HRESULT_FROM_WIN32(::GetLastError());
  341. } else {
  342. if (NULL != m_hEventNotifyThread) {
  343. //
  344. // WAIT for thread to terminate, if one exists
  345. //
  346. DWORD dwResult = WaitForSingleObject(m_hEventNotifyThread,THREAD_TERMINATION_TIMEOUT);
  347. switch (dwResult) {
  348. case WAIT_TIMEOUT:
  349. hr = HRESULT_FROM_WIN32(::GetLastError());
  350. break;
  351. case WAIT_OBJECT_0:
  352. hr = S_OK;
  353. break;
  354. case WAIT_ABANDONED:
  355. hr = HRESULT_FROM_WIN32(::GetLastError());
  356. break;
  357. case WAIT_FAILED:
  358. hr = HRESULT_FROM_WIN32(::GetLastError());
  359. break;
  360. default:
  361. hr = HRESULT_FROM_WIN32(::GetLastError());
  362. break;
  363. }
  364. }
  365. //
  366. // Close event for syncronization of notifications shutdown.
  367. //
  368. CloseHandle(m_hKillEventThread);
  369. m_hKillEventThread = NULL;
  370. }
  371. }
  372. //
  373. // terminate thread
  374. //
  375. if (NULL != m_hEventNotifyThread) {
  376. CloseHandle(m_hEventNotifyThread);
  377. m_hEventNotifyThread = NULL;
  378. }
  379. return hr;
  380. }
  381. HRESULT CFScanAPI::FakeScanner_EnableDevice()
  382. {
  383. HRESULT hr = S_OK;
  384. //
  385. // do nothing.. (unused at this time)
  386. //
  387. return hr;
  388. }
  389. HRESULT CFScanAPI::FakeScanner_DeviceOnline()
  390. {
  391. HRESULT hr = S_OK;
  392. //
  393. // Fake device is always on-line
  394. //
  395. return hr;
  396. }
  397. HRESULT CFScanAPI::FakeScanner_Diagnostic()
  398. {
  399. HRESULT hr = S_OK;
  400. //
  401. // Fake device is always healthy
  402. //
  403. return hr;
  404. }
  405. HRESULT CFScanAPI::FakeScanner_GetBedWidthAndHeight(PLONG pWidth, PLONG pHeight)
  406. {
  407. HRESULT hr = E_FAIL;
  408. //
  409. // get our Root item settings, so we can use the width and height values
  410. //
  411. ROOT_ITEM_INFORMATION RootItemInfo;
  412. hr = FakeScanner_GetRootPropertyInfo(&RootItemInfo);
  413. if(SUCCEEDED(hr)) {
  414. *pWidth = RootItemInfo.ScanBedWidth;
  415. *pHeight = RootItemInfo.ScanBedHeight;
  416. }
  417. return hr;
  418. }
  419. HRESULT CFScanAPI::FakeScanner_GetDeviceEvent(LONG *pEvent)
  420. {
  421. HRESULT hr = S_OK;
  422. if(pEvent){
  423. //
  424. // assign event ID
  425. //
  426. *pEvent = m_lLastEvent;
  427. //Trace(TEXT("FakeScanner_GetDeviceEvent() ,m_lLastEvent = %d"),m_lLastEvent);
  428. //
  429. // reset event ID
  430. //
  431. m_lLastEvent = ID_FAKE_NOEVENT;
  432. } else {
  433. hr = E_INVALIDARG;
  434. }
  435. return hr;
  436. }
  437. VOID CFScanAPI::FakeScanner_SetInterruptEventHandle(HANDLE hEvent)
  438. {
  439. //
  440. // save event handle, created by main driver, so we can signal it
  441. // when we have a "hardware" event (like button presses)
  442. //
  443. m_hEventHandle = hEvent;
  444. //Trace(TEXT("Interrupt Handle Set in Fake Device = %d"),m_hEventHandle);
  445. }
  446. //
  447. // standard device operations
  448. //
  449. HRESULT CFScanAPI::FakeScanner_ResetDevice()
  450. {
  451. HRESULT hr = S_OK;
  452. //
  453. // do nothing..
  454. //
  455. return hr;
  456. }
  457. HRESULT CFScanAPI::FakeScanner_SetEmulationMode(LONG lDeviceMode)
  458. {
  459. HRESULT hr = S_OK;
  460. switch(lDeviceMode){
  461. case SCROLLFED_SCANNER_MODE:
  462. {
  463. //
  464. // set any library restrictions for scroll fed scanners
  465. //
  466. m_lMode = SCROLLFED_SCANNER_MODE;
  467. }
  468. break;
  469. case MULTIFUNCTION_DEVICE_MODE:
  470. {
  471. //
  472. // set any library restrictions for multi-function devices
  473. //
  474. m_lMode = SCROLLFED_SCANNER_MODE;
  475. }
  476. break;
  477. default:
  478. {
  479. //
  480. // set any library restrictions for scroll flatbed scanners
  481. //
  482. m_lMode = FLATBED_SCANNER_MODE;
  483. }
  484. break;
  485. }
  486. return hr;
  487. }
  488. //
  489. // Automatic document feeder functions
  490. //
  491. HRESULT CFScanAPI::FakeScanner_ADFHasPaper()
  492. {
  493. HRESULT hr = S_OK;
  494. //
  495. // check paper count
  496. //
  497. if(m_PagesInADF <= 0){
  498. hr = S_FALSE;
  499. }
  500. return hr;
  501. }
  502. HRESULT CFScanAPI::FakeScanner_ADFAvailable()
  503. {
  504. HRESULT hr = S_OK;
  505. //
  506. // check ADF on-line
  507. //
  508. if(!m_ADFIsAvailable){
  509. hr = S_FALSE;
  510. }
  511. return hr;
  512. }
  513. HRESULT CFScanAPI::FakeScanner_ADFFeedPage()
  514. {
  515. HRESULT hr = S_OK;
  516. if(S_OK != FakeScanner_ADFHasPaper()){
  517. //
  518. // set paper empty error code
  519. //
  520. hr = WIA_ERROR_PAPER_EMPTY;
  521. }
  522. //
  523. // update paper count for ADF
  524. //
  525. m_PagesInADF--;
  526. if(m_PagesInADF <0){
  527. m_PagesInADF = 0;
  528. }
  529. return hr;
  530. }
  531. HRESULT CFScanAPI::FakeScanner_ADFUnFeedPage()
  532. {
  533. HRESULT hr = S_OK;
  534. //
  535. // do nothing.. paper will always eject
  536. //
  537. return hr;
  538. }
  539. HRESULT CFScanAPI::FakeScanner_ADFStatus()
  540. {
  541. return m_hrLastADFError;
  542. }
  543. HRESULT CFScanAPI::FakeScanner_ADFAttached()
  544. {
  545. HRESULT hr = S_OK;
  546. return hr;
  547. }
  548. HRESULT CFScanAPI::Raw24bitToRawXbitData(LONG DestDepth, BYTE* pDestBuffer, BYTE* pSrcBuffer, LONG lSrcWidth, LONG lSrcHeight)
  549. {
  550. HRESULT hr = E_INVALIDARG;
  551. switch(DestDepth){
  552. case 1:
  553. hr = Raw24bitToRaw1bitBW(pDestBuffer, pSrcBuffer, lSrcWidth, lSrcHeight);
  554. break;
  555. case 8:
  556. hr = Raw24bitToRaw8bitGray(pDestBuffer, pSrcBuffer, lSrcWidth, lSrcHeight);
  557. break;
  558. case 24:
  559. hr = Raw24bitToRaw24bitColor(pDestBuffer, pSrcBuffer, lSrcWidth, lSrcHeight);
  560. break;
  561. default:
  562. break;
  563. }
  564. return hr;
  565. }
  566. HRESULT CFScanAPI::Raw24bitToRaw1bitBW(BYTE* pDestBuffer, BYTE* pSrcBuffer, LONG lSrcWidth, LONG lSrcHeight)
  567. {
  568. HRESULT hr = S_OK;
  569. BYTE* ptDest = NULL;
  570. BYTE* ptSrc = NULL;
  571. int BitIdx = 0;
  572. BYTE Bits = 0;
  573. BYTE GrayByte = 0;
  574. for (LONG lHeight =0; lHeight < lSrcHeight; lHeight++) {
  575. ptDest = pDestBuffer + (lHeight*((lSrcWidth+7)/8));
  576. ptSrc = pSrcBuffer + lHeight*lSrcWidth*3;
  577. BitIdx = 0;
  578. Bits = 0;
  579. for (LONG lWidth =0; lWidth < lSrcWidth; lWidth++) {
  580. GrayByte = (BYTE)((ptSrc[0] * 11 + ptSrc[1] * 59 + ptSrc[2] * 30)/100);
  581. Bits *= 2;
  582. if (GrayByte > 128) Bits += 1;
  583. BitIdx++;
  584. if (BitIdx >= 8) {
  585. BitIdx = 0;
  586. *ptDest++ = Bits;
  587. }
  588. ptSrc += 3;
  589. }
  590. // Write out the last byte if matters
  591. if (BitIdx)
  592. *ptDest = Bits;
  593. }
  594. return hr;
  595. }
  596. HRESULT CFScanAPI::Raw24bitToRaw8bitGray(BYTE* pDestBuffer, BYTE* pSrcBuffer, LONG lSrcWidth, LONG lSrcHeight)
  597. {
  598. HRESULT hr = S_OK;
  599. BYTE* ptDest = NULL;
  600. BYTE* ptSrc = NULL;
  601. for (LONG lHeight=0; lHeight < lSrcHeight; lHeight++) {
  602. ptDest = pDestBuffer + (lHeight*lSrcWidth);
  603. ptSrc = pSrcBuffer + lHeight*lSrcWidth*3;
  604. for (LONG lWidth =0; lWidth < lSrcWidth; lWidth++) {
  605. *ptDest++ = (BYTE)((ptSrc[0] * 11 + ptSrc[1] * 59 + ptSrc[2] * 30)/100);
  606. ptSrc += 3;
  607. }
  608. }
  609. return hr;
  610. }
  611. HRESULT CFScanAPI::Raw24bitToRaw24bitColor(BYTE* pDestBuffer, BYTE* pSrcBuffer, LONG lSrcWidth, LONG lSrcHeight)
  612. {
  613. HRESULT hr = S_OK;
  614. BYTE* ptDest = NULL;
  615. BYTE* ptSrc = NULL;
  616. for (LONG lHeight=0; lHeight < lSrcHeight; lHeight++) {
  617. ptDest = pDestBuffer + lHeight*lSrcWidth*3;
  618. ptSrc = pSrcBuffer + lHeight*lSrcWidth*3;
  619. for (LONG lWidth =0; lWidth < lSrcWidth; lWidth++) {
  620. ptDest[0] = ptSrc[2];
  621. ptDest[1] = ptSrc[1];
  622. ptDest[2] = ptSrc[0];
  623. ptDest+=3;
  624. ptSrc+=3;
  625. }
  626. }
  627. return hr;
  628. }
  629. LONG CFScanAPI::WidthToDIBWidth(LONG lWidth)
  630. {
  631. return(lWidth+3)&0xfffffffc;
  632. }
  633. VOID CFScanAPI::CloseRAW()
  634. {
  635. #ifdef _USE_BITMAP_DATA
  636. CloseHandle(m_hRawDataMappingHandle);
  637. m_hRawDataMappingHandle = NULL;
  638. CloseHandle(m_hRawDataFileHandle);
  639. m_hRawDataFileHandle = NULL;
  640. m_pRawData = NULL;
  641. #endif
  642. }
  643. BOOL CFScanAPI::SrcToRAW()
  644. {
  645. #ifdef _USE_BITMAP_DATA
  646. CloseRAW();
  647. UNALIGNED BITMAPINFOHEADER *pbmih;
  648. pbmih = (BITMAPINFOHEADER*)m_pSrcData;
  649. if(pbmih){
  650. BYTE* pSrc = m_pSrcData + sizeof(BITMAPINFOHEADER);
  651. if(pSrc){
  652. //
  653. // allocate buffer large enough for entire RAW data set
  654. //
  655. LONG lTotalImageSize = CalcTotalImageSize();
  656. m_hRawDataFileHandle = CreateFile(TEXT("Raw.RAW"), GENERIC_WRITE | GENERIC_READ,
  657. FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL,
  658. NULL);
  659. DWORD dwHighSize = 0;
  660. DWORD dwLowSize = 0;
  661. dwLowSize = lTotalImageSize;
  662. m_hRawDataMappingHandle = CreateFileMapping(m_hRawDataFileHandle,NULL,
  663. PAGE_READWRITE,dwHighSize, dwLowSize, NULL);
  664. m_pRawData = (PBYTE)MapViewOfFileEx(m_hRawDataMappingHandle, FILE_MAP_WRITE,
  665. 0,0, dwLowSize, NULL);
  666. if (m_pRawData) {
  667. memset(m_pRawData,255,lTotalImageSize);
  668. //
  669. // copy SRC to RAW buffer
  670. //
  671. LONG lRawWidthBytes = CalcRawByteWidth();
  672. LONG lPadPerLineBytes = pbmih->biWidth % 4;
  673. LONG lSrcWidthBytes = ((pbmih->biWidth *3) + lPadPerLineBytes);
  674. LONG lPixPerPixCount = (LONG)((m_RawDataInfo.lWidthPixels / pbmih->biWidth));
  675. LONG lLinePerLineCount = (LONG)((m_RawDataInfo.lHeightPixels / pbmih->biHeight));
  676. BYTE *pDst = m_pRawData;
  677. BYTE *pCurDst = pDst;
  678. BYTE *pCurSrc = pSrc;
  679. BYTE *pTempSrc = pSrc;
  680. DWORD dwBytesWritten = 0;
  681. DWORD dwBytesRead = 0;
  682. DWORD dwRawWidthBytes = 0;
  683. for (LONG lHeight = 0; lHeight < pbmih->biHeight; lHeight++){
  684. // up sample data..
  685. for (LONG lRawHeight = 0; lRawHeight < lLinePerLineCount; lRawHeight++) {
  686. pTempSrc = pCurSrc;
  687. for (LONG lWidth = 0; lWidth < pbmih->biWidth; lWidth++) {
  688. for (LONG lPixCount = 0; lPixCount < lPixPerPixCount; lPixCount++) {
  689. memcpy(pCurDst,pTempSrc,3);
  690. pCurDst += 3;
  691. dwBytesWritten += 3;
  692. }
  693. pTempSrc += 3;
  694. dwBytesRead += 3;
  695. }
  696. pTempSrc += lPadPerLineBytes;
  697. dwBytesRead += lPadPerLineBytes;
  698. dwRawWidthBytes = 0;
  699. }
  700. pCurSrc = pTempSrc;
  701. // same data to same data...
  702. /*
  703. memcpy(pCurDst,pCurSrc,lSrcWidthBytes - lPadPerLineBytes);
  704. pCurSrc += lSrcWidthBytes;
  705. dwBytesRead += lSrcWidthBytes;
  706. pCurDst += lRawWidthBytes;
  707. dwBytesWritten += lRawWidthBytes;
  708. */
  709. }
  710. m_RawDataInfo.lOffset = 0;
  711. return TRUE;
  712. }
  713. }
  714. }
  715. #endif
  716. return FALSE;
  717. }
  718. LONG CFScanAPI::CalcTotalImageSize()
  719. {
  720. LONG lTotalSize = 0;
  721. switch(m_RawDataInfo.bpp){
  722. case 1:
  723. lTotalSize = ((m_RawDataInfo.lHeightPixels * m_RawDataInfo.lWidthPixels) + 7) / 8;
  724. break;
  725. case 8:
  726. lTotalSize = m_RawDataInfo.lHeightPixels * m_RawDataInfo.lWidthPixels;
  727. break;
  728. case 24:
  729. lTotalSize = (m_RawDataInfo.lHeightPixels * m_RawDataInfo.lWidthPixels) * 3;
  730. break;
  731. default:
  732. break;
  733. }
  734. return lTotalSize;
  735. }
  736. LONG CFScanAPI::CalcRawByteWidth()
  737. {
  738. LONG lRawWidthBytes = 0;
  739. switch(m_RawDataInfo.bpp){
  740. case 1:
  741. lRawWidthBytes = ((m_RawDataInfo.lWidthPixels) + 7) / 8;
  742. break;
  743. case 8:
  744. lRawWidthBytes = m_RawDataInfo.lWidthPixels;
  745. break;
  746. case 24:
  747. lRawWidthBytes = (m_RawDataInfo.lWidthPixels) * 3;
  748. break;
  749. default:
  750. break;
  751. }
  752. return lRawWidthBytes;
  753. }
  754. LONG CFScanAPI::CalcSrcByteWidth()
  755. {
  756. LONG lSrcWidthBytes = 0;
  757. switch(m_SrcDataInfo.bpp){
  758. case 1:
  759. lSrcWidthBytes = ((m_SrcDataInfo.lWidthPixels) + 7) / 8;
  760. break;
  761. case 8:
  762. lSrcWidthBytes = m_SrcDataInfo.lWidthPixels;
  763. break;
  764. case 24:
  765. lSrcWidthBytes = (m_SrcDataInfo.lWidthPixels) * 3;
  766. break;
  767. default:
  768. break;
  769. }
  770. return lSrcWidthBytes;
  771. }
  772. HRESULT CFScanAPI::BQADScale(BYTE* pSrcBuffer, LONG lSrcWidth, LONG lSrcHeight, LONG lSrcDepth,
  773. BYTE* pDestBuffer,LONG lDestWidth,LONG lDestHeight)
  774. {
  775. //
  776. // We only deal with 1, 8 and 24 bit data
  777. //
  778. if ((lSrcDepth != 8) && (lSrcDepth != 1) && (lSrcDepth != 24)) {
  779. return E_INVALIDARG;
  780. }
  781. //
  782. // Make adjustments so we also work in all supported bit depths. We can get a performance increase
  783. // by having separate implementations of all of these, but for now, we stick to a single generic
  784. // implementation.
  785. //
  786. LONG lBytesPerPixel = (lSrcDepth + 7) / 8;
  787. ULONG lSrcRawWidth = ((lSrcWidth * lSrcDepth) + 7) / 8; // This is the width in pixels
  788. ULONG lSrcWidthInBytes; // This is the DWORD-aligned width in bytes
  789. ULONG lDestWidthInBytes; // This is the DWORD-aligned width in bytes
  790. //
  791. // We need to work out the DWORD aligned width in bytes. Normally we would do this in one step
  792. // using the supplied lSrcDepth, but we avoid arithmetic overflow conditions that happen
  793. // in 24bit if we do it in 2 steps like this instead.
  794. //
  795. if (lSrcDepth == 1) {
  796. lSrcWidthInBytes = (lSrcWidth + 7) / 8;
  797. lDestWidthInBytes = (lDestWidth + 7) / 8;
  798. } else {
  799. lSrcWidthInBytes = (lSrcWidth * lBytesPerPixel);
  800. lDestWidthInBytes = (lDestWidth * lBytesPerPixel);
  801. }
  802. lSrcWidthInBytes += (lSrcWidthInBytes % 4) ? (4 - (lSrcWidthInBytes % 4)) : 0;
  803. //
  804. // uncomment to work with ALIGNED data
  805. // lDestWidthInBytes += (lDestWidthInBytes % 4) ? (4 - (lDestWidthInBytes % 4)) : 0;
  806. //
  807. //
  808. // Define local variables and do the initial calculations needed for
  809. // the scaling algorithm
  810. //
  811. BYTE *pDestPixel = NULL;
  812. BYTE *pSrcPixel = NULL;
  813. BYTE *pEnd = NULL;
  814. BYTE *pDestLine = NULL;
  815. BYTE *pSrcLine = NULL;
  816. BYTE *pEndLine = NULL;
  817. LONG lXEndSize = lBytesPerPixel * lDestWidth;
  818. LONG lXNum = lSrcWidth; // Numerator in X direction
  819. LONG lXDen = lDestWidth; // Denomiator in X direction
  820. LONG lXInc = (lXNum / lXDen) * lBytesPerPixel; // Increment in X direction
  821. LONG lXDeltaInc = lXNum % lXDen; // DeltaIncrement in X direction
  822. LONG lXRem = 0; // Remainder in X direction
  823. LONG lYNum = lSrcHeight; // Numerator in Y direction
  824. LONG lYDen = lDestHeight; // Denomiator in Y direction
  825. LONG lYInc = (lYNum / lYDen) * lSrcWidthInBytes; // Increment in Y direction
  826. LONG lYDeltaInc = lYNum % lYDen; // DeltaIncrement in Y direction
  827. LONG lYDestInc = lDestWidthInBytes;
  828. LONG lYRem = 0; // Remainder in Y direction
  829. pSrcLine = pSrcBuffer; // This is where we start in the source
  830. pDestLine = pDestBuffer; // This is the start of the destination buffer
  831. // This is where we end overall
  832. pEndLine = pDestBuffer + ((lDestWidthInBytes - 1) * lDestHeight);
  833. while (pDestLine < pEndLine) { // Start LoopY (Decides where the src and dest lines start)
  834. pSrcPixel = pSrcLine; // We're starting at the beginning of a new line
  835. pDestPixel = pDestLine;
  836. // Calc. where we end the line
  837. pEnd = pDestPixel + lXEndSize;
  838. lXRem = 0; // Reset the remainder for the horizontal direction
  839. while (pDestPixel < pEnd) { // Start LoopX (puts pixels in the destination line)
  840. // Put the pixel
  841. if (lBytesPerPixel > 1) {
  842. pDestPixel[0] = pSrcPixel[0];
  843. pDestPixel[1] = pSrcPixel[1];
  844. pDestPixel[2] = pSrcPixel[2];
  845. } else {
  846. *pDestPixel = *pSrcPixel;
  847. }
  848. // Move the destination pointer to the next pixel
  849. pDestPixel += lBytesPerPixel;
  850. pSrcPixel += lXInc; // Move the source pointer over by the horizontal increment
  851. lXRem += lXDeltaInc; // Increase the horizontal remainder - this decides when we "overflow"
  852. if (lXRem >= lXDen) { // This is our "overflow" condition. It means we're now one
  853. // pixel off.
  854. pSrcPixel += lBytesPerPixel; // In Overflow case, we need to shift one pixel over
  855. lXRem -= lXDen; // Decrease the remainder by the X denominator. This is essentially
  856. // lXRem MOD lXDen.
  857. }
  858. } // End LoopX (puts pixels in the destination line)
  859. pSrcLine += lYInc; // We've finished a horizontal line, time to move to the next one
  860. lYRem += lYDeltaInc; // Increase our vertical remainder. This decides when we "overflow"
  861. if (lYRem > lYDen) { // This is our vertical overflow condition.
  862. // We need to move to the next line down
  863. pSrcLine += lSrcWidthInBytes;
  864. lYRem -= lYDen; // Decrease the remainder by the Y denominator. This is essentially
  865. // lYRem MOD lYDen.
  866. }
  867. pDestLine += lYDestInc; // Move the destination pointer to the start of the next line in the
  868. // destination buffer
  869. } // End LoopY (Decides where the src and dest lines start)
  870. return S_OK;
  871. }
  872. LONG CFScanAPI::CalcRandomDeviceDataTotalBytes()
  873. {
  874. LONG lTotalBytes = 0;
  875. srand((unsigned)time(NULL));
  876. LONG lPageLengthInches = ((rand()%17) + 5);// max 22 inches, and min of 5 inches
  877. Trace(TEXT("Random Page Length is %d inches"),lPageLengthInches);
  878. LONG lImageHeight = m_RawDataInfo.lYRes * lPageLengthInches;
  879. Trace(TEXT("Random Page Length is %d pixels"),lImageHeight);
  880. lTotalBytes = (CalcRawByteWidth() * lImageHeight);
  881. Trace(TEXT("Random Page Total Data Size = %d"),lTotalBytes);
  882. return lTotalBytes;
  883. }
  884. HRESULT CFScanAPI::CreateButtonEventFiles()
  885. {
  886. HRESULT hr = E_FAIL;
  887. HANDLE hFileHandle = NULL;
  888. TCHAR szSystemDirectory[MAX_PATH]; // system directory
  889. UINT uiSystemPathLen = 0; // length of system path
  890. uiSystemPathLen = GetSystemDirectory(szSystemDirectory,MAX_PATH);
  891. if (uiSystemPathLen <= 0) {
  892. return E_FAIL;
  893. }
  894. memset(m_ScanButtonFile,0,(sizeof(TCHAR) * MAX_PATH));
  895. lstrcpy(m_ScanButtonFile,szSystemDirectory);
  896. lstrcat(m_ScanButtonFile,TEXT("\\"));
  897. lstrcat(m_ScanButtonFile,SCANBUTTON_FILE);
  898. //
  899. // create Scan button event file
  900. //
  901. hFileHandle = CreateFile(m_ScanButtonFile, GENERIC_WRITE | GENERIC_READ,FILE_SHARE_WRITE, NULL, OPEN_ALWAYS,
  902. FILE_ATTRIBUTE_NORMAL,NULL);
  903. if (INVALID_HANDLE_VALUE != hFileHandle && NULL != hFileHandle) {
  904. CloseHandle(hFileHandle);
  905. hFileHandle = NULL;
  906. memset(m_CopyButtonFile,0,(sizeof(TCHAR) * MAX_PATH));
  907. lstrcpy(m_CopyButtonFile,szSystemDirectory);
  908. lstrcat(m_CopyButtonFile,TEXT("\\"));
  909. lstrcat(m_CopyButtonFile,COPYBUTTON_FILE);
  910. //
  911. // create Copy button event file
  912. //
  913. hFileHandle = CreateFile(m_CopyButtonFile, GENERIC_WRITE | GENERIC_READ,FILE_SHARE_WRITE, NULL, OPEN_ALWAYS,
  914. FILE_ATTRIBUTE_NORMAL,NULL);
  915. if (INVALID_HANDLE_VALUE != hFileHandle && NULL != hFileHandle) {
  916. CloseHandle(hFileHandle);
  917. hFileHandle = NULL;
  918. memset(m_FaxButtonFile,0,(sizeof(TCHAR) * MAX_PATH));
  919. lstrcpy(m_FaxButtonFile,szSystemDirectory);
  920. lstrcat(m_FaxButtonFile,TEXT("\\"));
  921. lstrcat(m_FaxButtonFile,FAXBUTTON_FILE);
  922. //
  923. // create Fax button event file
  924. //
  925. hFileHandle = CreateFile(m_FaxButtonFile, GENERIC_WRITE | GENERIC_READ,FILE_SHARE_WRITE, NULL, OPEN_ALWAYS,
  926. FILE_ATTRIBUTE_NORMAL,NULL);
  927. if (INVALID_HANDLE_VALUE != hFileHandle && NULL != hFileHandle) {
  928. CloseHandle(hFileHandle);
  929. hFileHandle = NULL;
  930. memset(m_ADFEventFile,0,(sizeof(TCHAR) * MAX_PATH));
  931. lstrcpy(m_ADFEventFile,szSystemDirectory);
  932. lstrcat(m_ADFEventFile,TEXT("\\"));
  933. lstrcat(m_ADFEventFile,ADF_FILE);
  934. //
  935. // create ADF load event file
  936. //
  937. hFileHandle = CreateFile(m_ADFEventFile, GENERIC_WRITE | GENERIC_READ,FILE_SHARE_WRITE, NULL, OPEN_ALWAYS,
  938. FILE_ATTRIBUTE_NORMAL,NULL);
  939. if (INVALID_HANDLE_VALUE != hFileHandle && NULL != hFileHandle) {
  940. //
  941. // write default headers to ADF event file
  942. //
  943. SetEndOfFile(hFileHandle);
  944. TCHAR szBuffer[1024];
  945. memset(szBuffer,0,sizeof(szBuffer));
  946. _stprintf(szBuffer,TEXT("%s\r\n%s10\r\n%s\r\n%s\r\n"),LOADPAGES_HEADER,
  947. LOADPAGES_PAGES,
  948. ADFERRORS_HEADER,
  949. ADFERRORS_ERROR);
  950. DWORD dwBytesWritten = 0;
  951. WriteFile(hFileHandle,szBuffer,(lstrlen(szBuffer)*sizeof(TCHAR)),&dwBytesWritten,NULL);
  952. CloseHandle(hFileHandle);
  953. hFileHandle = NULL;
  954. hr = S_OK;
  955. }
  956. }
  957. }
  958. }
  959. return hr;
  960. }
  961. HRESULT CFScanAPI::DoEventProcessing()
  962. {
  963. HRESULT hr = E_FAIL;
  964. //
  965. // loop checking for file change messages
  966. //
  967. if(FAILED(CreateButtonEventFiles())){
  968. return E_FAIL;
  969. }
  970. //
  971. // call IsValidDeviceEvent() once, to set internal variables
  972. //
  973. IsValidDeviceEvent();
  974. HANDLE hNotifyFileSysChange = NULL; // handle to file change object
  975. DWORD dwErr = 0; // error return value
  976. TCHAR szSystemDirectory[MAX_PATH]; // system directory
  977. UINT uiSystemPathLen = 0; // length of system path
  978. uiSystemPathLen = GetSystemDirectory(szSystemDirectory,MAX_PATH);
  979. if(uiSystemPathLen <= 0){
  980. return E_FAIL;
  981. }
  982. hNotifyFileSysChange = FindFirstChangeNotification(szSystemDirectory,
  983. FALSE,
  984. FILE_NOTIFY_CHANGE_SIZE |
  985. FILE_NOTIFY_CHANGE_LAST_WRITE |
  986. FILE_NOTIFY_CHANGE_FILE_NAME |
  987. FILE_NOTIFY_CHANGE_DIR_NAME);
  988. if (hNotifyFileSysChange == INVALID_HANDLE_VALUE) {
  989. return E_FAIL;
  990. }
  991. //
  992. // set up event handle array. (Kill Thread handle, and File change handle)
  993. //
  994. HANDLE hEvents[2] = {m_hKillEventThread,hNotifyFileSysChange};
  995. //
  996. // set looping to TRUE
  997. //
  998. BOOL bLooping = TRUE;
  999. //
  1000. // Wait for file system change or kill event thread event.
  1001. //
  1002. while (bLooping) {
  1003. //
  1004. // Wait
  1005. //
  1006. dwErr = ::WaitForMultipleObjects(2,hEvents,FALSE,INFINITE);
  1007. //
  1008. // process signal
  1009. //
  1010. switch (dwErr) {
  1011. case WAIT_OBJECT_0+1: // FILE CHANGED EVENT
  1012. //
  1013. // check to see if it was one of our "known" files that
  1014. // changed
  1015. //
  1016. if(IsValidDeviceEvent()){
  1017. //
  1018. // signal the interrupt handle if it exists
  1019. //
  1020. if(NULL != m_hEventHandle){
  1021. //
  1022. // set the event
  1023. //
  1024. //Trace(TEXT("signaling Event Handle (%d)"),m_hEventHandle);
  1025. ::SetEvent(m_hEventHandle);
  1026. } else {
  1027. //Trace(TEXT("No Event Handle to signal"));
  1028. }
  1029. }
  1030. //
  1031. // Wait again.. for next file system event
  1032. //
  1033. FindNextChangeNotification(hNotifyFileSysChange);
  1034. break;
  1035. case WAIT_OBJECT_0: // SHUTDOWN EVENT
  1036. //
  1037. // set looping boolean to FALSE, so we exit out thread
  1038. //
  1039. bLooping = FALSE;
  1040. break;
  1041. default:
  1042. //
  1043. // do nothing...we don't know
  1044. //
  1045. break;
  1046. }
  1047. }
  1048. //
  1049. // close file system event handle
  1050. //
  1051. FindCloseChangeNotification(hNotifyFileSysChange);
  1052. return S_OK;
  1053. }
  1054. BOOL CFScanAPI::IsValidDeviceEvent()
  1055. {
  1056. BOOL bValidEvent = FALSE;
  1057. LARGE_INTEGER liNewHugeSize;
  1058. FILETIME ftLastWriteTime;
  1059. WIN32_FIND_DATA sNewFileAttributes;
  1060. HANDLE hFind = INVALID_HANDLE_VALUE;
  1061. DWORD dwError = NOERROR;
  1062. ////////////////////////////////////////////////////////////
  1063. // Scan Button file check
  1064. ////////////////////////////////////////////////////////////
  1065. //
  1066. // Get the file attributes.
  1067. //
  1068. ZeroMemory(&sNewFileAttributes, sizeof(sNewFileAttributes));
  1069. hFind = FindFirstFile( m_ScanButtonFile, &sNewFileAttributes );
  1070. if (hFind != INVALID_HANDLE_VALUE) {
  1071. ftLastWriteTime = sNewFileAttributes.ftLastWriteTime;
  1072. liNewHugeSize.LowPart = sNewFileAttributes.nFileSizeLow;
  1073. liNewHugeSize.HighPart = sNewFileAttributes.nFileSizeHigh;
  1074. FindClose( hFind );
  1075. } else {
  1076. dwError = ::GetLastError();
  1077. }
  1078. if (NOERROR == dwError) {
  1079. //
  1080. // check file date/time.
  1081. //
  1082. if (CompareFileTime(&m_ftScanButton,&ftLastWriteTime) == -1) {
  1083. //
  1084. // we have a Button event...so set the event flag to TRUE
  1085. // and set the BUTTON ID to the correct event.
  1086. //
  1087. //Trace(TEXT("Scan button pressed on fake Hardware"));
  1088. bValidEvent = TRUE;
  1089. m_lLastEvent = ID_FAKE_SCANBUTTON;
  1090. }
  1091. m_ftScanButton = ftLastWriteTime;
  1092. }
  1093. ////////////////////////////////////////////////////////////
  1094. // Copy Button file check
  1095. ////////////////////////////////////////////////////////////
  1096. //
  1097. // Get the file attributes.
  1098. //
  1099. ZeroMemory(&sNewFileAttributes, sizeof(sNewFileAttributes));
  1100. hFind = FindFirstFile( m_CopyButtonFile, &sNewFileAttributes );
  1101. if (hFind != INVALID_HANDLE_VALUE) {
  1102. ftLastWriteTime = sNewFileAttributes.ftLastWriteTime;
  1103. liNewHugeSize.LowPart = sNewFileAttributes.nFileSizeLow;
  1104. liNewHugeSize.HighPart = sNewFileAttributes.nFileSizeHigh;
  1105. FindClose( hFind );
  1106. } else {
  1107. dwError = ::GetLastError();
  1108. }
  1109. if (NOERROR == dwError) {
  1110. //
  1111. // check file date/time.
  1112. //
  1113. if (CompareFileTime(&m_ftCopyButton,&ftLastWriteTime) == -1) {
  1114. //
  1115. // we have a Button event...so set the event flag to TRUE
  1116. // and set the BUTTON ID to the correct event.
  1117. //
  1118. bValidEvent = TRUE;
  1119. m_lLastEvent = ID_FAKE_COPYBUTTON;
  1120. }
  1121. m_ftCopyButton = ftLastWriteTime;
  1122. }
  1123. ////////////////////////////////////////////////////////////
  1124. // Fax Button file check
  1125. ////////////////////////////////////////////////////////////
  1126. //
  1127. // Get the file attributes.
  1128. //
  1129. ZeroMemory(&sNewFileAttributes, sizeof(sNewFileAttributes));
  1130. hFind = FindFirstFile( m_FaxButtonFile, &sNewFileAttributes );
  1131. if (hFind != INVALID_HANDLE_VALUE) {
  1132. ftLastWriteTime = sNewFileAttributes.ftLastWriteTime;
  1133. liNewHugeSize.LowPart = sNewFileAttributes.nFileSizeLow;
  1134. liNewHugeSize.HighPart = sNewFileAttributes.nFileSizeHigh;
  1135. FindClose( hFind );
  1136. } else {
  1137. dwError = ::GetLastError();
  1138. }
  1139. if (NOERROR == dwError) {
  1140. //
  1141. // check file date/time.
  1142. //
  1143. if (CompareFileTime(&m_ftFaxButton,&ftLastWriteTime) == -1) {
  1144. //
  1145. // we have a Button event...so set the event flag to TRUE
  1146. // and set the BUTTON ID to the correct event.
  1147. //
  1148. bValidEvent = TRUE;
  1149. m_lLastEvent = ID_FAKE_FAXBUTTON;
  1150. }
  1151. m_ftFaxButton = ftLastWriteTime;
  1152. }
  1153. ////////////////////////////////////////////////////////////
  1154. // ADF Event file check
  1155. ////////////////////////////////////////////////////////////
  1156. //
  1157. // Get the file attributes.
  1158. //
  1159. ZeroMemory(&sNewFileAttributes, sizeof(sNewFileAttributes));
  1160. hFind = FindFirstFile( m_ADFEventFile, &sNewFileAttributes );
  1161. if (hFind != INVALID_HANDLE_VALUE) {
  1162. ftLastWriteTime = sNewFileAttributes.ftLastWriteTime;
  1163. liNewHugeSize.LowPart = sNewFileAttributes.nFileSizeLow;
  1164. liNewHugeSize.HighPart = sNewFileAttributes.nFileSizeHigh;
  1165. FindClose( hFind );
  1166. } else {
  1167. dwError = ::GetLastError();
  1168. }
  1169. if (NOERROR == dwError) {
  1170. //
  1171. // check file date/time.
  1172. //
  1173. if (CompareFileTime(&m_ftFaxButton,&ftLastWriteTime) == -1) {
  1174. //
  1175. // we have an ADF event...so set the event flag to TRUE
  1176. // and set the ID to the correct event.
  1177. //
  1178. //bValidEvent = TRUE;
  1179. //m_lLastEvent = ID_FAKE_ADFEVENT;
  1180. ProcessADFEvent();
  1181. }
  1182. m_ftFaxButton = ftLastWriteTime;
  1183. }
  1184. return bValidEvent;
  1185. }
  1186. HRESULT CFScanAPI::ProcessADFEvent()
  1187. {
  1188. HRESULT hr = S_OK;
  1189. m_PagesInADF = GetPrivateProfileInt(TEXT("Load Pages"),
  1190. TEXT("Pages"),
  1191. 10,
  1192. m_ADFEventFile);
  1193. Trace(TEXT("ADF has %d pages loaded"),m_PagesInADF);
  1194. DWORD dwReturn = 0;
  1195. TCHAR szError[MAX_PATH];
  1196. memset(szError,0,sizeof(szError));
  1197. dwReturn = GetPrivateProfileString(TEXT("ADF Error"),
  1198. TEXT("Error"),
  1199. TEXT(""),
  1200. szError,
  1201. (sizeof(szError)/sizeof(TCHAR)),
  1202. m_ADFEventFile);
  1203. if (lstrlen(szError) > 0) {
  1204. if (lstrcmpi(szError,ADFERRORS_JAM) == 0) {
  1205. m_hrLastADFError = WIA_ERROR_PAPER_JAM;
  1206. Trace(TEXT("ADF has a paper JAM"));
  1207. } else if (lstrcmpi(szError,ADFERRORS_EMPTY) == 0) {
  1208. m_hrLastADFError = WIA_ERROR_PAPER_EMPTY;
  1209. Trace(TEXT("ADF has no paper"));
  1210. } else if (lstrcmpi(szError,ADFERRORS_PROBLEM) == 0) {
  1211. m_hrLastADFError = WIA_ERROR_PAPER_PROBLEM;
  1212. Trace(TEXT("ADF has a paper problem"));
  1213. } else if (lstrcmpi(szError,ADFERRORS_GENERAL) == 0) {
  1214. m_hrLastADFError = WIA_ERROR_GENERAL_ERROR;
  1215. Trace(TEXT("ADF encountered a general error"));
  1216. } else if (lstrcmpi(szError,ADFERRORS_OFFLINE) == 0) {
  1217. m_hrLastADFError = WIA_ERROR_OFFLINE;
  1218. Trace(TEXT("ADF is off-line"));
  1219. } else {
  1220. Trace(TEXT("ADF is READY"));
  1221. m_hrLastADFError = S_OK;
  1222. }
  1223. } else {
  1224. Trace(TEXT("ADF is READY"));
  1225. m_hrLastADFError = S_OK;
  1226. }
  1227. return hr;
  1228. }
  1229. VOID CFScanAPI::Trace(LPCTSTR format,...)
  1230. {
  1231. #ifdef DEBUG
  1232. TCHAR Buffer[1024];
  1233. va_list arglist;
  1234. va_start(arglist, format);
  1235. wvsprintf(Buffer, format, arglist);
  1236. va_end(arglist);
  1237. OutputDebugString(Buffer);
  1238. OutputDebugString(TEXT("\n"));
  1239. #endif
  1240. }
  1241. HRESULT CreateInstance(CFakeScanAPI **ppFakeScanAPI, LONG lMode)
  1242. {
  1243. HRESULT hr = S_OK;
  1244. if(ppFakeScanAPI){
  1245. *ppFakeScanAPI = NULL;
  1246. *ppFakeScanAPI = new CFScanAPI;
  1247. if(NULL == *ppFakeScanAPI){
  1248. hr = E_OUTOFMEMORY;
  1249. }
  1250. CFScanAPI* pScanAPI = (CFScanAPI*)*ppFakeScanAPI;
  1251. pScanAPI->FakeScanner_SetEmulationMode(lMode);
  1252. }
  1253. return hr;
  1254. }
  1255. ////////////////////////////////////////////////////////////////////////////////////////
  1256. // THREADS SECTION //
  1257. ////////////////////////////////////////////////////////////////////////////////////////
  1258. VOID FakeScannerEventThread( LPVOID lpParameter )
  1259. {
  1260. PSCANNERDEVICE pThisDevice = (PSCANNERDEVICE)lpParameter;
  1261. pThisDevice->DoEventProcessing();
  1262. }