TwainApp.cpp 56 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146
  1. /***************************************************************************
  2. * Copyright ?2007 TWAIN Working Group:
  3. * Adobe Systems Incorporated, AnyDoc Software Inc., Eastman Kodak Company,
  4. * Fujitsu Computer Products of America, JFL Peripheral Solutions Inc.,
  5. * Ricoh Corporation, and Xerox Corporation.
  6. * All rights reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions are met:
  10. * * Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * * Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * * Neither the name of the TWAIN Working Group nor the
  16. * names of its contributors may be used to endorse or promote products
  17. * derived from this software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY TWAIN Working Group ``AS IS'' AND ANY
  20. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  21. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  22. * DISCLAIMED. IN NO EVENT SHALL TWAIN Working Group BE LIABLE FOR ANY
  23. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  24. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  25. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  26. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  28. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. *
  30. ***************************************************************************/
  31. /**
  32. * @file TwainApp.cpp
  33. * TWAIN Application.
  34. * A TWAIN Application communicates with the DSM to acquire images.
  35. * The goal of the application is to acquire data from a Source.
  36. * However, applications cannot contact the Source directly. All requests for
  37. * data, capability information, error information, etc. must be handled
  38. * Through the Source Manager.
  39. * @author JFL Peripheral Solutions Inc.
  40. * @date April 2007
  41. */
  42. #include "../stdafx.h"
  43. #include <iostream>
  44. #include <cstdlib>
  45. #include <assert.h>
  46. #include <stdio.h>
  47. #include "TwainApp.h"
  48. #include "CTiffWriter.h"
  49. #include "TwainString.h"
  50. using namespace std;
  51. // used in the OPENDSM logic
  52. extern TW_ENTRYPOINT g_DSM_Entry; // found in DSMInterface.cpp
  53. bool gUSE_CALLBACKS = false; /**< This gets updated to true if the DSM is ver2 */
  54. /*
  55. * defined in main.cpp, this is the callback function to register for this app.
  56. * It will be called by the source when its ready to start the transfer.
  57. */
  58. extern
  59. #ifdef TWH_CMP_MSC
  60. TW_UINT16 FAR PASCAL
  61. #else
  62. FAR PASCAL TW_UINT16
  63. #endif
  64. DSMCallback(pTW_IDENTITY _pOrigin,
  65. pTW_IDENTITY _pDest,
  66. TW_UINT32 _DG,
  67. TW_UINT16 _DAT,
  68. TW_UINT16 _MSG,
  69. TW_MEMREF _pData);
  70. TwainApp* g_pTWAINApp =NULL;
  71. TW_UINT16 FAR PASCAL DSMCallback(pTW_IDENTITY _pOrigin,
  72. pTW_IDENTITY _pDest,
  73. TW_UINT32 _DG,
  74. TW_UINT16 _DAT,
  75. TW_UINT16 _MSG,
  76. TW_MEMREF _pData)
  77. {
  78. TW_UINT16 twrc = TWRC_FAILURE;
  79. // _pData stores the RefCon from the when the callback was registered
  80. // RefCon is a TW_INT32 and can not store a pointer for 64bit
  81. // we are only waiting for callbacks from our datasource, so validate
  82. // that the originator.
  83. if( 0 != _pOrigin
  84. && 0 != g_pTWAINApp
  85. && g_pTWAINApp->getDataSource()
  86. && _pOrigin->Id == g_pTWAINApp->getDataSource()->Id )
  87. {
  88. switch (_MSG)
  89. {
  90. case MSG_XFERREADY:
  91. case MSG_CLOSEDSREQ:
  92. case MSG_CLOSEDSOK:
  93. case MSG_NULL:
  94. g_pTWAINApp->m_DSMessage = _MSG;
  95. twrc = TWRC_SUCCESS;
  96. break;
  97. default:
  98. TRACE("Error - Unknown message in callback routine");
  99. g_pTWAINApp->m_DSMessage = MSG_NULL;
  100. twrc = TWRC_FAILURE;
  101. break;
  102. }
  103. }
  104. return twrc;
  105. }
  106. //////////////////////////////////////////////////////////////////////////////
  107. bool operator== (const TW_FIX32& _fix1, const TW_FIX32& _fix2)
  108. {
  109. return((_fix1.Whole == _fix2.Whole) &&
  110. (_fix1.Frac == _fix2.Frac));
  111. }
  112. void PrintCMDMessage(const char* const pStr, ...)
  113. {
  114. char buffer[200];
  115. va_list valist;
  116. va_start(valist, pStr);
  117. #if (TWNDS_CMP == TWNDS_CMP_GNUGPP)
  118. vsnprintf(buffer, 200, pStr, valist);
  119. #elif (TWNDS_CMP == TWNDS_CMP_VISUALCPP) && (TWNDS_CMP_VERSION >= 1400)
  120. _vsnprintf_s(buffer, 200, 200, pStr, valist);
  121. #elif (TWNDS_CMP == TWNDS_CMP_VISUALCPP)
  122. _vsnprintf(buffer, 200, pStr, valist);
  123. #else
  124. #error Sorry, we do not recognize this system...
  125. #endif
  126. va_end(valist);
  127. #ifdef _WINDOWS
  128. TRACE(buffer);
  129. #else
  130. cout << buffer;
  131. #endif
  132. }
  133. //////////////////////////////////////////////////////////////////////////////
  134. TwainApp::TwainApp(HWND parent /*=NULL*/)
  135. : m_DSMState(1)
  136. , m_pDataSource(NULL)
  137. , m_pExtImageInfo(NULL)
  138. , m_DSMessage(-1)
  139. , m_nGetLableSupported(TWCC_SUCCESS)
  140. , m_nGetHelpSupported(TWCC_SUCCESS)
  141. , m_strSavePath("")
  142. {
  143. g_pTWAINApp = this;
  144. // fill our identity structure
  145. fillIdentity(m_MyInfo);
  146. m_Parent = parent;
  147. m_nXferNum = 0;
  148. return;
  149. }
  150. //////////////////////////////////////////////////////////////////////////////
  151. TwainApp::~TwainApp()
  152. {
  153. unLoadDSMLib();
  154. m_DataSources.erase(m_DataSources.begin(), m_DataSources.end());
  155. if(m_pExtImageInfo)
  156. {
  157. //delete m_pExtImageInfo;
  158. }
  159. }
  160. //////////////////////////////////////////////////////////////////////////////
  161. void TwainApp::fillIdentity(TW_IDENTITY& _identity)
  162. {
  163. _identity.Id = 0;
  164. _identity.Version.MajorNum = 2;
  165. _identity.Version.MinorNum = 0;
  166. _identity.Version.Language = TWLG_ENGLISH_CANADIAN;
  167. _identity.Version.Country = TWCY_CANADA;
  168. SSTRCPY(_identity.Version.Info, sizeof(_identity.Version.Info), "2.0.9");
  169. _identity.ProtocolMajor = TWON_PROTOCOLMAJOR;
  170. _identity.ProtocolMinor = TWON_PROTOCOLMINOR;
  171. _identity.SupportedGroups = DF_APP2 | DG_IMAGE | DG_CONTROL;
  172. SSTRCPY(_identity.Manufacturer, sizeof(_identity.Manufacturer), "App's Manufacturer");
  173. SSTRCPY(_identity.ProductFamily, sizeof(_identity.ProductFamily), "App's Product Family");
  174. SSTRCPY(_identity.ProductName, sizeof(_identity.ProductName), "Specific App Product Name");
  175. return;
  176. }
  177. TW_UINT16 TwainApp::DSM_Entry(TW_UINT32 _DG,TW_UINT16 _DAT, TW_UINT16 _MSG, TW_MEMREF _pData)
  178. {
  179. return _DSM_Entry(&m_MyInfo, m_pDataSource, _DG, _DAT, _MSG, _pData);
  180. }
  181. //////////////////////////////////////////////////////////////////////////////
  182. void TwainApp::exit()
  183. {
  184. if( 3 <= m_DSMState )
  185. {
  186. // If we have selected a source, then it is posible it is open
  187. if( 0 != m_pDataSource && 4 <= m_DSMState )
  188. {
  189. if( 5 <= m_DSMState )
  190. {
  191. disableDS();
  192. // If DisableDS succeeds then m_DSMState will be set down to 4
  193. // if it did NOT succeed, try to cancle any pending transfers.
  194. if( 5 <= m_DSMState )
  195. {
  196. DoAbortXfer();
  197. // Any pending transfers should now be cancled
  198. m_DSMState = 5;
  199. disableDS();
  200. }// END 5 <= m_DSMState
  201. }// END 5 <= m_DSMState
  202. unloadDS();
  203. }// END 4 <= m_DSMState
  204. disconnectDSM();
  205. }// END 3 <= m_DSMState
  206. }
  207. //////////////////////////////////////////////////////////////////////////////
  208. // NOTE: this function needs to be refactored to:
  209. // - have better error handling
  210. // - have 1 output interface for both linux console and Windows
  211. // - look into if we need to cleanup on failures
  212. void TwainApp::connectDSM()
  213. {
  214. if(m_DSMState > 3)
  215. {
  216. PrintCMDMessage("The DSM has already been opened, close it first\n");
  217. return;
  218. }
  219. if(!LoadDSMLib(kTWAIN_DSM_DIR kTWAIN_DSM_DLL_NAME))
  220. {
  221. PrintCMDMessage("The DSM could not be opened. Please ensure that it is installed into a directory that is in the library path:");
  222. PrintCMDMessage(kTWAIN_DSM_DIR kTWAIN_DSM_DLL_NAME);
  223. return;
  224. }
  225. else
  226. {
  227. m_DSMState = 2;
  228. }
  229. TW_UINT16 ret = 0;
  230. if(TWRC_SUCCESS != (ret = _DSM_Entry(
  231. &(m_MyInfo),
  232. 0,
  233. DG_CONTROL,
  234. DAT_PARENT,
  235. MSG_OPENDSM,
  236. (TW_MEMREF)&m_Parent)))
  237. {
  238. PrintCMDMessage("DG_CONTROL / DAT_PARENT / MSG_OPENDSM Failed: %u\n", ret);
  239. return;
  240. }
  241. // check for DSM2 support
  242. if((m_MyInfo.SupportedGroups & DF_DSM2) == DF_DSM2)
  243. {
  244. g_DSM_Entry.Size = sizeof(TW_ENTRYPOINT);
  245. // do a MSG_GET to fill our entrypoints
  246. if(TWRC_SUCCESS != (ret = _DSM_Entry(
  247. &(m_MyInfo),
  248. 0,
  249. DG_CONTROL,
  250. DAT_ENTRYPOINT,
  251. MSG_GET,
  252. (pTW_ENTRYPOINT)&g_DSM_Entry)))
  253. {
  254. PrintCMDMessage("DG_CONTROL / DAT_ENTRYPOINT / MSG_GET Failed: %d\n", ret);
  255. return;
  256. }
  257. }
  258. PrintCMDMessage("Successfully opened the DSM\n");
  259. m_DSMState = 3;
  260. // get list of available sources
  261. m_DataSources.erase(m_DataSources.begin(), m_DataSources.end());
  262. getSources();
  263. return;
  264. }
  265. //////////////////////////////////////////////////////////////////////////////
  266. void TwainApp::disconnectDSM()
  267. {
  268. if(m_DSMState < 3)
  269. {
  270. PrintCMDMessage("The DSM has not been opened, open it first\n");
  271. }
  272. TW_UINT16 ret = _DSM_Entry(
  273. &(m_MyInfo),
  274. 0,
  275. DG_CONTROL,
  276. DAT_PARENT,
  277. MSG_CLOSEDSM,
  278. (TW_MEMREF)&m_Parent);
  279. if(TWRC_SUCCESS == ret)
  280. {
  281. PrintCMDMessage("Successfully closed the DSM\n");
  282. m_DSMState = 2;
  283. }
  284. else
  285. {
  286. printError(0, "Failed to close the DSM");
  287. }
  288. return;
  289. }
  290. //////////////////////////////////////////////////////////////////////////////
  291. TW_IDENTITY _gSource; /**< used to store the source that is return by getDefaultDataSource */
  292. //////////////////////////////////////////////////////////////////////////////
  293. pTW_IDENTITY TwainApp::getDefaultDataSource()
  294. {
  295. if(m_DSMState < 3)
  296. {
  297. cout << "You need to open the DSM first." << endl;
  298. return NULL;
  299. }
  300. // get default
  301. memset(&_gSource, 0, sizeof(TW_IDENTITY));
  302. TW_UINT16 twrc;
  303. twrc = _DSM_Entry(
  304. &m_MyInfo,
  305. 0,
  306. DG_CONTROL,
  307. DAT_IDENTITY,
  308. MSG_GETDEFAULT,
  309. (TW_MEMREF) &_gSource);
  310. switch (twrc)
  311. {
  312. case TWRC_SUCCESS:
  313. break;
  314. case TWRC_FAILURE:
  315. printError(0, "Failed to get the data source info!");
  316. break;
  317. }
  318. return &_gSource;
  319. }
  320. //////////////////////////////////////////////////////////////////////////////
  321. pTW_IDENTITY TwainApp::setDefaultDataSource(unsigned int _index)
  322. {
  323. if(m_DSMState < 3)
  324. {
  325. cout << "You need to open the DSM first." << endl;
  326. return NULL;
  327. }
  328. else if(m_DSMState > 3)
  329. {
  330. PrintCMDMessage("A source has already been opened, please close it first\n");
  331. return NULL;
  332. }
  333. if(_index >= 0 && _index < m_DataSources.size())
  334. {
  335. m_pDataSource = &(m_DataSources[_index]);
  336. // set the specific data source
  337. TW_UINT16 twrc;
  338. twrc = _DSM_Entry(
  339. &m_MyInfo,
  340. 0,
  341. DG_CONTROL,
  342. DAT_IDENTITY,
  343. MSG_SET,
  344. (TW_MEMREF) m_pDataSource);
  345. switch (twrc)
  346. {
  347. case TWRC_SUCCESS:
  348. break;
  349. case TWRC_FAILURE:
  350. printError(0, "Failed to get the data source info!");
  351. break;
  352. }
  353. }
  354. else
  355. {
  356. return NULL;
  357. }
  358. return m_pDataSource;
  359. }
  360. //////////////////////////////////////////////////////////////////////////////
  361. pTW_IDENTITY TwainApp::selectDefaultDataSource()
  362. {
  363. if(m_DSMState < 3)
  364. {
  365. PrintCMDMessage("You need to open the DSM first.\n");
  366. return NULL;
  367. }
  368. // get default
  369. memset(&_gSource, 0, sizeof(TW_IDENTITY));
  370. TW_UINT16 twrc;
  371. twrc = _DSM_Entry(
  372. &m_MyInfo,
  373. 0,
  374. DG_CONTROL,
  375. DAT_IDENTITY,
  376. MSG_USERSELECT,
  377. (TW_MEMREF) &_gSource);
  378. switch (twrc)
  379. {
  380. case TWRC_SUCCESS:
  381. break;
  382. case TWRC_CANCEL:
  383. printError(0, "Canceled select data source!");
  384. return NULL;
  385. break;
  386. case TWRC_FAILURE:
  387. printError(0, "Failed to select the data source!");
  388. return NULL;
  389. break;
  390. }
  391. return &_gSource;
  392. }
  393. void TwainApp::setDSDefaultConfig(){
  394. }
  395. //////////////////////////////////////////////////////////////////////////////
  396. void TwainApp::loadDS(const TW_INT32 _dsID)
  397. {
  398. // The application must be in state 3 to open a Data Source.
  399. if(m_DSMState < 3)
  400. {
  401. PrintCMDMessage("The DSM needs to be opened first.\n");
  402. return;
  403. }
  404. else if(m_DSMState > 3)
  405. {
  406. PrintCMDMessage("A source has already been opened, please close it first\n");
  407. return;
  408. }
  409. // Reinitilize these
  410. m_nGetLableSupported = TWCC_SUCCESS;
  411. m_nGetHelpSupported = TWCC_SUCCESS;
  412. if(_dsID > 0)
  413. {
  414. // first find the data source with id = _dsID
  415. m_pDataSource = 0;
  416. unsigned int x = 0;
  417. for(; x < m_DataSources.size(); ++x)
  418. {
  419. if(_dsID == m_DataSources[x].Id)
  420. {
  421. m_pDataSource = &(m_DataSources[x]);
  422. break;
  423. }
  424. }
  425. if(0 == m_pDataSource)
  426. {
  427. PrintCMDMessage("Data source with id: [%u] can not be found\n", _dsID);
  428. return;
  429. }
  430. }
  431. else
  432. {
  433. //Open the default
  434. memset(&_gSource, 0, sizeof(TW_IDENTITY));
  435. m_pDataSource = &_gSource;
  436. }
  437. TW_CALLBACK callback = {0};
  438. // open the specific data source
  439. TW_UINT16 twrc;
  440. twrc = _DSM_Entry(
  441. &m_MyInfo,
  442. 0,
  443. DG_CONTROL,
  444. DAT_IDENTITY,
  445. MSG_OPENDS,
  446. (TW_MEMREF) m_pDataSource);
  447. switch (twrc)
  448. {
  449. case TWRC_SUCCESS:
  450. PrintCMDMessage("Data source successfully opened!\n");
  451. // Transition application to state 4
  452. m_DSMState = 4;
  453. callback.CallBackProc = (TW_MEMREF)DSMCallback;
  454. /* RefCon, On 32bit Could be used to store a pointer to this class to help
  455. passing the message on to be processed. But RefCon is too small to store
  456. a pointer on 64bit. For 64bit RefCon could storing an index to some
  457. global memory array. But if there is only one instance of the Application
  458. Class connecting to the DSM then the single global pointer to the
  459. application class can be used, and the RefCon can be ignored as we do here. */
  460. callback.RefCon = 0;
  461. if(TWRC_SUCCESS != (twrc = DSM_Entry(DG_CONTROL, DAT_CALLBACK, MSG_REGISTER_CALLBACK, (TW_MEMREF)&callback)))
  462. {
  463. PrintCMDMessage("DG_CONTROL / DAT_CALLBACK / MSG_REGISTER_CALLBACK Failed: %u\n", twrc);
  464. }
  465. else
  466. {
  467. gUSE_CALLBACKS = true;
  468. }
  469. break;
  470. default:
  471. printError(m_pDataSource, "Failed to open data source.");
  472. m_pDataSource = 0;
  473. break;
  474. }
  475. return;
  476. }
  477. //////////////////////////////////////////////////////////////////////////////
  478. void TwainApp::unloadDS()
  479. {
  480. if(m_DSMState < 4)
  481. {
  482. PrintCMDMessage("You need to open a data source first.\n");
  483. return;
  484. }
  485. TW_UINT16 twrc;
  486. twrc = _DSM_Entry(
  487. &m_MyInfo,
  488. 0,
  489. DG_CONTROL,
  490. DAT_IDENTITY,
  491. MSG_CLOSEDS,
  492. (TW_MEMREF) m_pDataSource);
  493. switch (twrc)
  494. {
  495. case TWRC_SUCCESS:
  496. PrintCMDMessage("Data source successfully closed\n");
  497. // Transition application to state 3
  498. m_DSMState = 3;
  499. // reset the active source pointer
  500. m_pDataSource = 0;
  501. break;
  502. default:
  503. printError(0, "Failed to close data source.");
  504. break;
  505. }
  506. return;
  507. }
  508. //////////////////////////////////////////////////////////////////////////////
  509. void TwainApp::getSources()
  510. {
  511. if(m_DSMState < 3)
  512. {
  513. PrintCMDMessage("You need to open the DSM first.\n");
  514. return;
  515. }
  516. // the list should be empty if adding to it.
  517. assert( true == m_DataSources.empty() );
  518. // get first
  519. TW_IDENTITY Source;
  520. memset(&Source, 0, sizeof(TW_IDENTITY));
  521. TW_UINT16 twrc;
  522. twrc = _DSM_Entry(
  523. &m_MyInfo,
  524. 0,
  525. DG_CONTROL,
  526. DAT_IDENTITY,
  527. MSG_GETFIRST,
  528. (TW_MEMREF) &Source);
  529. switch (twrc)
  530. {
  531. case TWRC_SUCCESS:
  532. m_DataSources.push_back(Source);
  533. break;
  534. case TWRC_FAILURE:
  535. printError(0, "Failed to get the data source info!");
  536. break;
  537. case TWRC_ENDOFLIST:
  538. return;
  539. break;
  540. }
  541. // get the rest of the sources
  542. do
  543. {
  544. memset(&Source, 0, sizeof(TW_IDENTITY));
  545. twrc = _DSM_Entry(
  546. &m_MyInfo,
  547. 0,
  548. DG_CONTROL,
  549. DAT_IDENTITY,
  550. MSG_GETNEXT,
  551. (TW_MEMREF) &Source);
  552. switch (twrc)
  553. {
  554. case TWRC_SUCCESS:
  555. m_DataSources.push_back(Source);
  556. break;
  557. case TWRC_FAILURE:
  558. printError(0, "Failed to get the rest of the data source info!");
  559. return;
  560. break;
  561. case TWRC_ENDOFLIST:
  562. return;
  563. break;
  564. }
  565. }
  566. while (TWRC_SUCCESS == twrc);
  567. return;
  568. }
  569. //////////////////////////////////////////////////////////////////////////////
  570. TW_INT16 TwainApp::printError(pTW_IDENTITY _pdestID, const string& _errorMsg)
  571. {
  572. TW_INT16 c = TWCC_SUCCESS;
  573. #ifdef _WINDOWS
  574. TRACE("app: ");
  575. if(_errorMsg.length() > 0)
  576. {
  577. TRACE(_errorMsg.c_str());
  578. }
  579. else
  580. {
  581. TRACE("An error has occurred.");
  582. }
  583. if(TWRC_SUCCESS == getTWCC(_pdestID, c))
  584. {
  585. TRACE(" The condition code is: %s\n", convertConditionCode_toString(c));
  586. }
  587. else
  588. {
  589. TRACE("\n");
  590. }
  591. #else
  592. cerr << "app: ";
  593. if(_errorMsg.length() > 0)
  594. {
  595. cerr << _errorMsg;
  596. }
  597. else
  598. {
  599. cerr << "An error has occurred.";
  600. }
  601. if(TWRC_SUCCESS == getTWCC(_pdestID, c))
  602. {
  603. cerr << " The condition code is: " << convertConditionCode_toString(c) << endl;
  604. }
  605. #endif
  606. return c;
  607. }
  608. //////////////////////////////////////////////////////////////////////////////
  609. TW_UINT16 TwainApp::getTWCC(pTW_IDENTITY _pdestID, TW_INT16& _cc)
  610. {
  611. TW_STATUS status;
  612. memset(&status, 0, sizeof(TW_STATUS));
  613. TW_UINT16 twrc = _DSM_Entry(
  614. &m_MyInfo,
  615. _pdestID,
  616. DG_CONTROL,
  617. DAT_STATUS,
  618. MSG_GET,
  619. (TW_MEMREF)&status);
  620. if(TWRC_SUCCESS == twrc)
  621. {
  622. _cc = status.ConditionCode;
  623. }
  624. return twrc;
  625. }
  626. //////////////////////////////////////////////////////////////////////////////
  627. bool TwainApp::enableDS(TW_HANDLE hWnd, BOOL bShowUI)
  628. {
  629. bool bret = true;
  630. if(m_DSMState < 4)
  631. {
  632. PrintCMDMessage("You need to open the data source first.\n");
  633. return false;
  634. }
  635. m_ui.ShowUI = bShowUI;
  636. m_ui.ModalUI = FALSE;
  637. m_ui.hParent = hWnd;
  638. m_DSMState = 5;
  639. TW_UINT16 twrc = DSM_Entry(DG_CONTROL, DAT_USERINTERFACE, MSG_ENABLEDS, (TW_MEMREF)&(m_ui));
  640. if( TWRC_SUCCESS != twrc &&
  641. TWRC_CHECKSTATUS != twrc )
  642. {
  643. m_DSMState = 4;
  644. printError(m_pDataSource, "Cannot enable source");
  645. bret = false;
  646. }
  647. // Usually at this point the application sits here and waits for the
  648. // scan to start. We are notified that we can start a scan through
  649. // the DSM's callback mechanism. The callback was registered when the DSM
  650. // was opened.
  651. // If callbacks are not being used, then the DSM will be polled to see
  652. // when the DS is ready to start scanning.
  653. return bret;
  654. }
  655. //////////////////////////////////////////////////////////////////////////////
  656. bool TwainApp::enableDSUIOnly(TW_HANDLE hWnd)
  657. {
  658. bool bret = true;
  659. if(m_DSMState < 4)
  660. {
  661. PrintCMDMessage("You need to open the data source first.\n");
  662. return false;
  663. }
  664. m_ui.ShowUI = TRUE;
  665. m_ui.ModalUI = TRUE;
  666. m_ui.hParent = hWnd;
  667. m_DSMState = 5;
  668. m_DSMessage= (TW_INT16)-1;
  669. TW_UINT16 twrc = DSM_Entry(DG_CONTROL, DAT_USERINTERFACE, MSG_ENABLEDSUIONLY, (TW_MEMREF)&(m_ui));
  670. if( TWRC_SUCCESS != twrc &&
  671. TWRC_CHECKSTATUS != twrc )
  672. {
  673. m_DSMState = 4;
  674. printError(m_pDataSource, "Cannot enable source");
  675. bret = false;
  676. }
  677. // Usually at this point the application sits here and waits for the
  678. // scan to start. We are notified that we can start a scan through
  679. // the DSM's callback mechanism. The callback was registered when the DSM
  680. // was opened.
  681. // If callbacks are not being used, then the DSM will be polled to see
  682. // when the DS is ready to start scanning.
  683. return bret;
  684. }
  685. //////////////////////////////////////////////////////////////////////////////
  686. void TwainApp::disableDS()
  687. {
  688. if(m_DSMState < 5)
  689. {
  690. PrintCMDMessage("You need to enable the data source first.\n");
  691. return;
  692. }
  693. TW_UINT16 twrc = DSM_Entry( DG_CONTROL, DAT_USERINTERFACE, MSG_DISABLEDS, (TW_MEMREF)&(m_ui) );
  694. if(TWRC_SUCCESS == twrc)
  695. {
  696. m_DSMState = 4;
  697. }
  698. else
  699. {
  700. printError(m_pDataSource, "Cannot disable source");
  701. }
  702. return;
  703. }
  704. //////////////////////////////////////////////////////////////////////////////
  705. bool TwainApp::updateIMAGEINFO()
  706. {
  707. // clear our image info structure
  708. memset(&m_ImageInfo, 0, sizeof(m_ImageInfo));
  709. // get the image details
  710. PrintCMDMessage("app: Getting the image info...\n");
  711. TW_UINT16 twrc = DSM_Entry( DG_IMAGE, DAT_IMAGEINFO, MSG_GET, (TW_MEMREF)&(m_ImageInfo));
  712. if(TWRC_SUCCESS != twrc)
  713. {
  714. printError(m_pDataSource, "Error while trying to get the image information!");
  715. }
  716. return TWRC_SUCCESS==twrc? true:false;
  717. }
  718. //////////////////////////////////////////////////////////////////////////////
  719. void TwainApp::initiateTransfer_Native()
  720. {
  721. PrintCMDMessage("app: Starting a TWSX_NATIVE transfer...\n");
  722. TW_STR255 szOutFileName;
  723. bool bPendingXfers = true;
  724. TW_UINT16 twrc = TWRC_SUCCESS;
  725. string strPath = m_strSavePath;
  726. if( strlen(strPath.c_str()) )
  727. {
  728. if(strPath[strlen(strPath.c_str())-1] != PATH_SEPERATOR)
  729. {
  730. strPath += PATH_SEPERATOR;
  731. }
  732. }
  733. while(bPendingXfers)
  734. {
  735. m_nXferNum++;
  736. memset(szOutFileName, 0, sizeof(szOutFileName));
  737. if(!updateIMAGEINFO())
  738. {
  739. break;
  740. }
  741. // The data returned by ImageInfo can be used to determine if this image is wanted.
  742. // If it is not then DG_CONTROL / DAT_PENDINGXFERS / MSG_ENDXFER can be
  743. // used to skip to the next image.
  744. TW_MEMREF hImg = 0;
  745. PrintCMDMessage("app: Starting the transfer...\n");
  746. twrc = DSM_Entry( DG_IMAGE, DAT_IMAGENATIVEXFER, MSG_GET, (TW_MEMREF)&hImg);
  747. if(TWRC_XFERDONE == twrc)
  748. {
  749. // -Here we get a handle to a DIB. Save it to disk as a bmp.
  750. // -After saving it to disk, I could open it up again using FreeImage
  751. // if I wanted to do more transforms on it or save it as a different format.
  752. PBITMAPINFOHEADER pDIB = (PBITMAPINFOHEADER)_DSM_LockMemory(hImg);
  753. if(0 == pDIB)
  754. {
  755. printError(m_pDataSource, "App: Unable to lock memory, transfer failed");
  756. break;
  757. }
  758. // Set the filename to save to
  759. SSNPRINTF(szOutFileName, sizeof(szOutFileName), sizeof(szOutFileName), "%sFROM_SCANNER_%06dN.bmp", strPath.c_str(), m_nXferNum);
  760. // If the driver did not fill in the biSizeImage field, then compute it
  761. // Each scan line of the image is aligned on a DWORD (32bit) boundary
  762. if( pDIB->biSizeImage == 0 )
  763. {
  764. pDIB->biSizeImage = ((((pDIB->biWidth * pDIB->biBitCount) + 31) & ~31) / 8) * pDIB->biHeight;
  765. // If a compression scheme is used the result may infact be larger
  766. // Increase the size to account for this.
  767. if (pDIB->biCompression != 0)
  768. {
  769. pDIB->biSizeImage = (pDIB->biSizeImage * 3) / 2;
  770. }
  771. }
  772. navtive_graber(pDIB);
  773. /*
  774. // Save the image to disk
  775. FILE *pFile;
  776. FOPEN(pFile, szOutFileName, "wb");
  777. if(pFile == 0)
  778. {
  779. perror("fopen");
  780. }
  781. else
  782. {
  783. DWORD dwPaletteSize = 0;
  784. switch(pDIB->biBitCount)
  785. {
  786. case 1:
  787. dwPaletteSize = 2;
  788. break;
  789. case 8:
  790. dwPaletteSize = 256;
  791. break;
  792. case 24:
  793. break;
  794. default:
  795. assert(0); //Not going to work!
  796. break;
  797. }
  798. int nImageSize = pDIB->biSizeImage + (sizeof(RGBQUAD)*dwPaletteSize)+sizeof(BITMAPINFOHEADER);
  799. BITMAPFILEHEADER bmpFIH = {0};
  800. bmpFIH.bfType = ( (WORD) ('M' << 8) | 'B');
  801. bmpFIH.bfSize = nImageSize + sizeof(BITMAPFILEHEADER);
  802. bmpFIH.bfOffBits = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+(sizeof(RGBQUAD)*dwPaletteSize);
  803. fwrite(&bmpFIH, 1, sizeof(BITMAPFILEHEADER), pFile);
  804. fwrite(pDIB, 1, nImageSize, pFile);
  805. fclose(pFile);
  806. pFile = 0;
  807. PrintCMDMessage("app: File \"%s\" saved...\n", szOutFileName);
  808. }
  809. */
  810. _DSM_UnlockMemory(hImg);
  811. _DSM_Free(hImg);
  812. pDIB = 0;
  813. //updateEXTIMAGEINFO();
  814. // see if there are any more transfers to do
  815. PrintCMDMessage("app: Checking to see if there are more images to transfer...\n");
  816. TW_PENDINGXFERS pendxfers;
  817. memset( &pendxfers, 0, sizeof(pendxfers) );
  818. twrc = DSM_Entry( DG_CONTROL, DAT_PENDINGXFERS, MSG_ENDXFER, (TW_MEMREF)&pendxfers);
  819. if(TWRC_SUCCESS == twrc)
  820. {
  821. PrintCMDMessage("app: Remaining images to transfer: %u\n", pendxfers.Count);
  822. if(0 == pendxfers.Count)
  823. {
  824. // nothing left to transfer, finished.
  825. bPendingXfers = false;
  826. }
  827. }
  828. else
  829. {
  830. printError(m_pDataSource, "failed to properly end the transfer");
  831. bPendingXfers = false;
  832. }
  833. if(HasStopCommand()){//ÊÇ·ñÇëÇóֹͣɨÃè
  834. break;
  835. }
  836. }
  837. else if(TWRC_CANCEL == twrc)
  838. {
  839. printError(m_pDataSource, "Canceled transfer image");
  840. break;
  841. }
  842. else if(TWRC_FAILURE == twrc)
  843. {
  844. printError(m_pDataSource, "Failed to transfer image");
  845. break;
  846. }
  847. }
  848. // Check to see if we left the scan loop before we were actualy done scanning
  849. // This will hapen if we had an error. Need to let the DS know we are not going
  850. // to transfer more images
  851. if(bPendingXfers == true)
  852. {
  853. twrc = DoAbortXfer();
  854. }
  855. // adjust our state now that the scanning session is done
  856. m_DSMState = 5;
  857. PrintCMDMessage("app: DONE!\n");
  858. return;
  859. }
  860. TW_UINT16 TwainApp::DoAbortXfer()
  861. {
  862. TW_UINT16 twrc = TWRC_SUCCESS;
  863. PrintCMDMessage("app: Stop any transfer we may have started but could not finish...\n");
  864. TW_PENDINGXFERS pendxfers;
  865. memset( &pendxfers, 0, sizeof(pendxfers) );
  866. twrc = DSM_Entry( DG_CONTROL, DAT_PENDINGXFERS, MSG_ENDXFER, (TW_MEMREF)&pendxfers);
  867. // We need to get rid of any pending transfers
  868. if(0 != pendxfers.Count)
  869. {
  870. memset( &pendxfers, 0, sizeof(pendxfers) );
  871. twrc = DSM_Entry( DG_CONTROL, DAT_PENDINGXFERS, MSG_RESET, (TW_MEMREF)&pendxfers);
  872. }
  873. return twrc;
  874. }
  875. void TwainApp::updateEXTIMAGEINFO()
  876. {
  877. int TableBarCodeExtImgInfo[] = {
  878. TWEI_BARCODETYPE,
  879. TWEI_BARCODETEXTLENGTH,
  880. TWEI_BARCODETEXT,
  881. TWEI_BARCODEX,
  882. TWEI_BARCODEY,
  883. TWEI_BARCODEROTATION,
  884. TWEI_BARCODECONFIDENCE };
  885. int TableOtherExtImgInfo[] = {
  886. TWEI_BOOKNAME,
  887. TWEI_CHAPTERNUMBER,
  888. TWEI_DOCUMENTNUMBER,
  889. TWEI_PAGENUMBER,
  890. TWEI_PAGESIDE,
  891. TWEI_CAMERA,
  892. TWEI_FRAMENUMBER,
  893. TWEI_FRAME,
  894. TWEI_PIXELFLAVOR,
  895. TWEI_ENDORSEDTEXT,
  896. TWEI_MAGTYPE,
  897. TWEI_MAGDATA };
  898. int num_BarInfos = sizeof(TableBarCodeExtImgInfo) / sizeof(TableBarCodeExtImgInfo[0]);
  899. int num_OtherInfos = sizeof(TableOtherExtImgInfo) / sizeof(TableOtherExtImgInfo[0]);
  900. TW_UINT16 twrc = TWRC_SUCCESS;
  901. m_strExImageInfo = "";
  902. try
  903. {
  904. TW_EXTIMAGEINFO extImgInfo;
  905. extImgInfo.NumInfos = 1;
  906. extImgInfo.Info[0].InfoID = TWEI_BARCODECOUNT;
  907. extImgInfo.Info[0].NumItems=0;
  908. extImgInfo.Info[0].ItemType = TWTY_UINT32;
  909. extImgInfo.Info[0].Item = 0;
  910. extImgInfo.Info[0].ReturnCode = 0;
  911. twrc = DSM_Entry(DG_IMAGE, DAT_EXTIMAGEINFO, MSG_GET, (TW_MEMREF)&extImgInfo);
  912. if(twrc!= TWRC_SUCCESS)
  913. {
  914. m_strExImageInfo = "Not Supported";
  915. return;
  916. }
  917. int cur_Info = 0;
  918. int num_Infos = 0;
  919. if(TWRC_SUCCESS==extImgInfo.Info[0].ReturnCode)
  920. {
  921. num_Infos = (num_BarInfos * (TW_UINT32)extImgInfo.Info[0].Item) +1;
  922. }
  923. TW_CAPABILITY CapSupportedExtImageInfos;
  924. pTW_ARRAY_UINT16 pCapSupExtImageInfos = 0;
  925. // get the supported capabilies
  926. CapSupportedExtImageInfos.Cap = ICAP_SUPPORTEDEXTIMAGEINFO;
  927. CapSupportedExtImageInfos.hContainer = 0;
  928. get_CAP(CapSupportedExtImageInfos);
  929. if(TWON_ARRAY == CapSupportedExtImageInfos.ConType)
  930. {
  931. pCapSupExtImageInfos = (pTW_ARRAY_UINT16)_DSM_LockMemory(CapSupportedExtImageInfos.hContainer);
  932. if(TWTY_UINT16 != pCapSupExtImageInfos->ItemType)
  933. {
  934. _DSM_UnlockMemory(CapSupportedExtImageInfos.hContainer);
  935. pCapSupExtImageInfos = NULL;
  936. }
  937. else //it is good to use
  938. {
  939. // Add all the non-barcode type ExtImageInfo
  940. int nCount = pCapSupExtImageInfos->NumItems;
  941. bool bAdd;
  942. for(int i=0; i<nCount; i++)
  943. {
  944. if( pCapSupExtImageInfos->ItemList[i] == TWEI_BARCODECOUNT )
  945. {
  946. // already counted
  947. continue;
  948. }
  949. bAdd = true;
  950. for(int BCeii=0; BCeii<num_BarInfos; BCeii++)
  951. {
  952. if( pCapSupExtImageInfos->ItemList[i] == TableBarCodeExtImgInfo[BCeii] )
  953. {
  954. // already counted
  955. bAdd = false;
  956. break;
  957. }
  958. }
  959. if(bAdd)
  960. {
  961. num_Infos++;
  962. }
  963. }
  964. }
  965. }
  966. if(!pCapSupExtImageInfos)
  967. {
  968. num_Infos += num_OtherInfos;
  969. }
  970. TW_HANDLE hExtInfo = _DSM_Alloc(sizeof(TW_EXTIMAGEINFO)+sizeof(TW_INFO)*(num_Infos-1));
  971. TW_EXTIMAGEINFO *pExtImgInfo = (TW_EXTIMAGEINFO*) _DSM_LockMemory(hExtInfo);
  972. memset(pExtImgInfo, 0,sizeof(TW_EXTIMAGEINFO)+sizeof(TW_INFO)*(num_Infos-1));
  973. pExtImgInfo->NumInfos = num_Infos;
  974. if(pCapSupExtImageInfos)
  975. {
  976. int nCount = pCapSupExtImageInfos->NumItems;
  977. bool bAdd;
  978. for(int i=0; i<nCount; i++)
  979. {
  980. if( pCapSupExtImageInfos->ItemList[i] == TWEI_BARCODECOUNT )
  981. {
  982. continue;
  983. }
  984. bAdd = true;
  985. for(int BCeii=0; BCeii<num_BarInfos; BCeii++)
  986. {
  987. if( pCapSupExtImageInfos->ItemList[i] == TableBarCodeExtImgInfo[BCeii] )
  988. {
  989. bAdd = false;
  990. break;
  991. }
  992. }
  993. if(bAdd)
  994. {
  995. pExtImgInfo->Info[cur_Info++].InfoID = pCapSupExtImageInfos->ItemList[i];
  996. }
  997. }
  998. }
  999. else
  1000. {
  1001. for (int nItem = 0; nItem < num_OtherInfos; nItem++)
  1002. {
  1003. pExtImgInfo->Info[cur_Info++].InfoID = TableOtherExtImgInfo[nItem];
  1004. }
  1005. }
  1006. if(TWRC_SUCCESS==extImgInfo.Info[0].ReturnCode)
  1007. {
  1008. // Inform the DS how many Barcode items we can handle for each type.
  1009. pExtImgInfo->Info[cur_Info++] = extImgInfo.Info[0];
  1010. for(unsigned int nCount = 0; nCount < (unsigned int)extImgInfo.Info[0].Item; nCount++)
  1011. {
  1012. for (int nBarItem = 0; nBarItem < num_BarInfos; nBarItem++)
  1013. {
  1014. pExtImgInfo->Info[cur_Info++].InfoID = TableBarCodeExtImgInfo[nBarItem];
  1015. }
  1016. }
  1017. }
  1018. twrc = DSM_Entry(DG_IMAGE, DAT_EXTIMAGEINFO, MSG_GET, (TW_MEMREF)pExtImgInfo);
  1019. if(twrc!= TWRC_SUCCESS)
  1020. {
  1021. m_strExImageInfo = "Not Supported";
  1022. return;
  1023. }
  1024. for(int nIndex = 0; nIndex < num_Infos; nIndex++)
  1025. {
  1026. if(pExtImgInfo->Info[nIndex].ReturnCode != TWRC_INFONOTSUPPORTED)
  1027. {
  1028. m_strExImageInfo += convertExtImageInfoName_toString(pExtImgInfo->Info[nIndex].InfoID);
  1029. m_strExImageInfo += ":\t";
  1030. // Special case for BarCodeText that returns a handel to its data
  1031. if( TWEI_BARCODETEXT == pExtImgInfo->Info[nIndex].InfoID
  1032. && TWTY_HANDLE == pExtImgInfo->Info[nIndex].ItemType
  1033. && nIndex>0
  1034. && TWEI_BARCODETEXTLENGTH == pExtImgInfo->Info[nIndex-1].InfoID
  1035. && pExtImgInfo->Info[nIndex].NumItems > 0
  1036. && pExtImgInfo->Info[nIndex].NumItems == pExtImgInfo->Info[nIndex-1].NumItems )
  1037. {
  1038. char buff[256];
  1039. char *pStrData = (char *)_DSM_LockMemory((TW_HANDLE)pExtImgInfo->Info[nIndex].Item);
  1040. TW_UINT32 *pStrLen = NULL;
  1041. TW_UINT32 StrLen = 0;
  1042. if( pExtImgInfo->Info[nIndex-1].NumItems == 1)
  1043. {
  1044. StrLen = pExtImgInfo->Info[nIndex-1].Item;
  1045. }
  1046. else
  1047. {
  1048. pStrLen = (TW_UINT32 *)_DSM_LockMemory((TW_HANDLE)pExtImgInfo->Info[nIndex-1].Item);
  1049. StrLen = *pStrLen;
  1050. }
  1051. // Data source should not return multiple items in a single Info for BarCodeText
  1052. // because we send a Info for each one it had for us but we will handle the case
  1053. // that the DS sends us multiple items anyway.
  1054. for( int nItem=0; nItem<pExtImgInfo->Info[nIndex].NumItems; nItem++)
  1055. {
  1056. if(nItem)
  1057. {
  1058. m_strExImageInfo +="\r\n\t";
  1059. pStrData += StrLen;
  1060. StrLen = *++pStrLen;
  1061. }
  1062. bool bNonPrintableData = FALSE;
  1063. if( nIndex>1
  1064. && TWEI_BARCODETYPE == pExtImgInfo->Info[nIndex-2].InfoID
  1065. && pExtImgInfo->Info[nIndex-2].InfoID <= TWBT_MAXICODE )
  1066. {
  1067. // The known BarCodeType are printable text
  1068. bNonPrintableData = FALSE;
  1069. }
  1070. else
  1071. {
  1072. // This is an unknown type so check to see if it is printable
  1073. for ( int i=0; i < (int)(min(StrLen-1, 255)); i++ )
  1074. {
  1075. if ( !isprint( (int) pStrData[i] ) )
  1076. {
  1077. bNonPrintableData = TRUE;
  1078. break;
  1079. }
  1080. }
  1081. }
  1082. if(bNonPrintableData)
  1083. {
  1084. for ( int i=0; i < (int)(min(StrLen, 60)); i++ )
  1085. {
  1086. SSNPRINTF(buff, 256, 256, "%2.2X ", pStrData[i]);
  1087. m_strExImageInfo += buff;
  1088. }
  1089. }
  1090. else
  1091. {
  1092. SSTRNCPY(buff, 256, pStrData, min(StrLen, 255));
  1093. m_strExImageInfo += buff;
  1094. }
  1095. }
  1096. _DSM_UnlockMemory((TW_HANDLE)pExtImgInfo->Info[nIndex].Item);
  1097. if(pStrLen)
  1098. {
  1099. _DSM_UnlockMemory((TW_HANDLE)pExtImgInfo->Info[nIndex-1].Item);
  1100. }
  1101. }
  1102. else
  1103. {
  1104. m_strExImageInfo += convertExtImageInfoItem_toString(pExtImgInfo->Info[nIndex]);
  1105. }
  1106. m_strExImageInfo +="\r\n";
  1107. }
  1108. }
  1109. for(int nIndex = 0; nIndex < num_Infos; nIndex++)
  1110. {
  1111. // We have no more use for the item so free the one that are handles
  1112. if( pExtImgInfo->Info[nIndex].ReturnCode == TWRC_SUCCESS
  1113. && pExtImgInfo->Info[nIndex].Item
  1114. && ( getTWTYsize(pExtImgInfo->Info[nIndex].ItemType)*pExtImgInfo->Info[nIndex].NumItems > sizeof(TW_UINT32)
  1115. || pExtImgInfo->Info[nIndex].ItemType == TWTY_HANDLE ) )
  1116. {
  1117. _DSM_Free((TW_HANDLE)pExtImgInfo->Info[nIndex].Item);
  1118. pExtImgInfo->Info[nIndex].Item = 0;
  1119. }
  1120. }
  1121. _DSM_UnlockMemory(hExtInfo);
  1122. _DSM_Free(hExtInfo);
  1123. }
  1124. catch(...)
  1125. {
  1126. //Log("Failure reading extended image info: %s", LPCSTR(error->m_strDescription));
  1127. }
  1128. return;
  1129. }
  1130. //////////////////////////////////////////////////////////////////////////////
  1131. void TwainApp::initiateTransfer_File(TW_UINT16 fileformat /*= TWFF_TIFF*/)
  1132. {
  1133. PrintCMDMessage("app: Starting a TWSX_FILE transfer...\n");
  1134. // start the transfer
  1135. bool bPendingXfers = true;
  1136. TW_UINT16 twrc = TWRC_SUCCESS;
  1137. // setup the file xfer
  1138. TW_SETUPFILEXFER filexfer;
  1139. memset(&filexfer, 0, sizeof(filexfer));
  1140. string strPath = m_strSavePath;
  1141. if( strlen(strPath.c_str()) )
  1142. {
  1143. if(strPath[strlen(strPath.c_str())-1] != PATH_SEPERATOR)
  1144. {
  1145. strPath += PATH_SEPERATOR;
  1146. }
  1147. }
  1148. const char * pExt = convertICAP_IMAGEFILEFORMAT_toExt(fileformat);
  1149. if(fileformat==TWFF_TIFFMULTI)
  1150. {
  1151. SSNPRINTF(filexfer.FileName, sizeof(filexfer.FileName), sizeof(filexfer.FileName), "%sFROM_SCANNER_F%s", strPath.c_str(), pExt);
  1152. }
  1153. else
  1154. {
  1155. SSNPRINTF(filexfer.FileName, sizeof(filexfer.FileName), sizeof(filexfer.FileName), "%sFROM_SCANNER_%06dF%s", strPath.c_str(), m_nXferNum, pExt);
  1156. }
  1157. filexfer.Format = fileformat;
  1158. while(bPendingXfers)
  1159. {
  1160. m_nXferNum++;
  1161. if(!updateIMAGEINFO())
  1162. {
  1163. break;
  1164. }
  1165. // The data returned by ImageInfo can be used to determine if this image is wanted.
  1166. // If it is not then DG_CONTROL / DAT_PENDINGXFERS / MSG_ENDXFER can be
  1167. // used to skip to the next image.
  1168. if(fileformat!=TWFF_TIFFMULTI)
  1169. {
  1170. SSNPRINTF(filexfer.FileName, sizeof(filexfer.FileName), sizeof(filexfer.FileName), "%sFROM_SCANNER_%06dF%s", strPath.c_str(), m_nXferNum, pExt);
  1171. }
  1172. PrintCMDMessage("app: Sending file transfer details...\n");
  1173. twrc = DSM_Entry( DG_CONTROL, DAT_SETUPFILEXFER, MSG_SET, (TW_MEMREF)&(filexfer));
  1174. if(TWRC_SUCCESS != twrc)
  1175. {
  1176. printError(m_pDataSource, "Error while trying to setup the file transfer");
  1177. break;
  1178. }
  1179. PrintCMDMessage("app: Starting file transfer...\n");
  1180. twrc = DSM_Entry( DG_IMAGE, DAT_IMAGEFILEXFER, MSG_GET, 0);
  1181. if(TWRC_XFERDONE == twrc)
  1182. {
  1183. // Findout where the file was actualy saved
  1184. twrc = DSM_Entry( DG_CONTROL, DAT_SETUPFILEXFER, MSG_GET, (TW_MEMREF)&(filexfer));
  1185. PrintCMDMessage("app: File \"%s\" saved...\n", filexfer.FileName);
  1186. updateEXTIMAGEINFO();
  1187. // see if there are any more transfers to do
  1188. PrintCMDMessage("app: Checking to see if there are more images to transfer...\n");
  1189. TW_PENDINGXFERS pendxfers;
  1190. memset(&pendxfers, 0, sizeof(pendxfers));
  1191. twrc = DSM_Entry( DG_CONTROL, DAT_PENDINGXFERS, MSG_ENDXFER, (TW_MEMREF)&pendxfers);
  1192. if(TWRC_SUCCESS == twrc)
  1193. {
  1194. PrintCMDMessage("app: Remaining images to transfer: %u\n", pendxfers.Count);
  1195. if(0 == pendxfers.Count)
  1196. {
  1197. // nothing left to transfer, finished.
  1198. bPendingXfers = false;
  1199. }
  1200. }
  1201. else
  1202. {
  1203. printError(m_pDataSource, "failed to properly end the transfer");
  1204. bPendingXfers = false;
  1205. }
  1206. }
  1207. else if(TWRC_CANCEL == twrc)
  1208. {
  1209. printError(m_pDataSource, "Canceled transfer image");
  1210. break;
  1211. }
  1212. else if(TWRC_FAILURE == twrc)
  1213. {
  1214. printError(m_pDataSource, "Failed to transfer image");
  1215. break;
  1216. }
  1217. }
  1218. // Check to see if we left the scan loop before we were actualy done scanning
  1219. // This will hapen if we had an error. Need to let the DS know we are not going
  1220. // to transfer more images
  1221. if(bPendingXfers == true)
  1222. {
  1223. twrc = DoAbortXfer();
  1224. }
  1225. // adjust our state now that the scanning session is done
  1226. m_DSMState = 5;
  1227. PrintCMDMessage("app: DONE!\n");
  1228. return;
  1229. }
  1230. //////////////////////////////////////////////////////////////////////////////
  1231. void TwainApp::initiateTransfer_Memory()
  1232. {
  1233. PrintCMDMessage("app: Starting a TWSX_MEMORY transfer...\n");
  1234. // For memory transfers, the FreeImage library will not be used, instead a
  1235. // tiff will be progressively written. This method was chosen because it
  1236. // is possible that a 4GB image could be transferred and an image of that
  1237. // size can not fit in most systems memory.
  1238. CTiffWriter *pTifImg = 0;
  1239. TW_STR255 szOutFileName;
  1240. TW_SETUPMEMXFER SourcesBufferSizes; /**< Used to set up the buffer size used by memory transfer method */
  1241. bool bPendingXfers = true;
  1242. TW_UINT16 twrc = TWRC_SUCCESS;
  1243. string strPath = m_strSavePath;
  1244. if( strlen(strPath.c_str()) )
  1245. {
  1246. if(strPath[strlen(strPath.c_str())-1] != PATH_SEPERATOR)
  1247. {
  1248. strPath += PATH_SEPERATOR;
  1249. }
  1250. }
  1251. // start the transfer
  1252. while(bPendingXfers)
  1253. {
  1254. m_nXferNum++;
  1255. memset(szOutFileName, 0, sizeof(szOutFileName));
  1256. if(!updateIMAGEINFO())
  1257. {
  1258. break;
  1259. }
  1260. // The data returned by ImageInfo can be used to determine if this image is wanted.
  1261. // If it is not then DG_CONTROL / DAT_PENDINGXFERS / MSG_ENDXFER can be
  1262. // used to skip to the next image.
  1263. // Set the filename to save to
  1264. SSNPRINTF(szOutFileName, sizeof(szOutFileName), sizeof(szOutFileName), "%sFROM_SCANNER_%06dM.tif", strPath.c_str(), m_nXferNum);
  1265. // get the buffer sizes that the source wants to use
  1266. PrintCMDMessage("app: getting the buffer sizes...\n");
  1267. memset(&SourcesBufferSizes, 0, sizeof(SourcesBufferSizes));
  1268. twrc = DSM_Entry( DG_CONTROL, DAT_SETUPMEMXFER, MSG_GET, (TW_MEMREF)&(SourcesBufferSizes));
  1269. if(TWRC_SUCCESS != twrc)
  1270. {
  1271. printError(m_pDataSource, "Error while trying to get the buffer sizes from the source!");
  1272. break;
  1273. }
  1274. // -setup a buffer to hold the strip from the data source
  1275. // -this buffer is a template that will be used to reset the real
  1276. // buffer before each call to get a strip.
  1277. TW_IMAGEMEMXFER memXferBufTemplate;
  1278. memXferBufTemplate.Compression = TWON_DONTCARE16;
  1279. memXferBufTemplate.BytesPerRow = TWON_DONTCARE32;
  1280. memXferBufTemplate.Columns = TWON_DONTCARE32;
  1281. memXferBufTemplate.Rows = TWON_DONTCARE32;
  1282. memXferBufTemplate.XOffset = TWON_DONTCARE32;
  1283. memXferBufTemplate.YOffset = TWON_DONTCARE32;
  1284. memXferBufTemplate.BytesWritten = TWON_DONTCARE32;
  1285. memXferBufTemplate.Memory.Flags = TWMF_APPOWNS | TWMF_POINTER;
  1286. memXferBufTemplate.Memory.Length = SourcesBufferSizes.Preferred;
  1287. TW_HANDLE hMem = (TW_HANDLE)_DSM_Alloc(SourcesBufferSizes.Preferred);
  1288. if(0 == hMem)
  1289. {
  1290. printError(0, "Error allocating memory");
  1291. break;
  1292. }
  1293. memXferBufTemplate.Memory.TheMem = (TW_MEMREF)_DSM_LockMemory(hMem);
  1294. // this is the real buffer that will be sent to the data source
  1295. TW_IMAGEMEMXFER memXferBuf;
  1296. // this is set to true once one row has been successfully acquired. We have
  1297. // to track this because we can't transition to state 7 until a row has been
  1298. // received.
  1299. bool bScanStarted = false;
  1300. int nBytePerRow = (((m_ImageInfo.ImageWidth * m_ImageInfo.BitsPerPixel)+7)/8);
  1301. // now that the memory has been setup, get the data from the scanner
  1302. PrintCMDMessage("app: starting the memory transfer...\n");
  1303. while(1)
  1304. {
  1305. // reset the xfer buffer
  1306. memcpy(&memXferBuf, &memXferBufTemplate, sizeof(memXferBufTemplate));
  1307. // clear the row data buffer
  1308. memset(memXferBuf.Memory.TheMem, 0, memXferBuf.Memory.Length);
  1309. // get the row data
  1310. twrc = DSM_Entry( DG_IMAGE, DAT_IMAGEMEMXFER, MSG_GET, (TW_MEMREF)&(memXferBuf));
  1311. if(TWRC_SUCCESS == twrc || TWRC_XFERDONE == twrc)
  1312. {
  1313. if(!bScanStarted)
  1314. {
  1315. // the state can be changed to state 7 now that we have successfully
  1316. // received at least one strip
  1317. m_DSMState = 7;
  1318. bScanStarted = true;
  1319. // write the tiff header now that all info needed for the header has
  1320. // been received.
  1321. pTifImg = new CTiffWriter(szOutFileName,
  1322. m_ImageInfo.ImageWidth,
  1323. m_ImageInfo.ImageLength,
  1324. m_ImageInfo.BitsPerPixel,
  1325. nBytePerRow);
  1326. pTifImg->setXResolution(m_ImageInfo.XResolution.Whole, 1);
  1327. pTifImg->setYResolution(m_ImageInfo.YResolution.Whole, 1);
  1328. pTifImg->writeImageHeader();
  1329. }
  1330. char* pbuf = reinterpret_cast<char*>(memXferBuf.Memory.TheMem);
  1331. // write the received image data to the image file
  1332. for(unsigned int x = 0; x < memXferBuf.Rows; ++x)
  1333. {
  1334. pTifImg->WriteTIFFData(pbuf, nBytePerRow);
  1335. pbuf += memXferBuf.BytesPerRow;
  1336. }
  1337. if(TWRC_XFERDONE == twrc)
  1338. {
  1339. // deleting the CTiffWriter object will close the file
  1340. if(pTifImg)
  1341. {
  1342. delete pTifImg;
  1343. pTifImg = 0;
  1344. }
  1345. PrintCMDMessage("app: File \"%s\" saved...\n", szOutFileName);
  1346. updateEXTIMAGEINFO();
  1347. break;
  1348. }
  1349. }
  1350. else if(TWRC_CANCEL == twrc)
  1351. {
  1352. printError(m_pDataSource, "Canceled transfer while trying to get a strip of data from the source!");
  1353. break;
  1354. }
  1355. else if(TWRC_FAILURE == twrc)
  1356. {
  1357. printError(m_pDataSource, "Error while trying to get a strip of data from the source!");
  1358. break;
  1359. }
  1360. }
  1361. // cleanup
  1362. if(pTifImg)
  1363. {
  1364. delete pTifImg;
  1365. pTifImg = 0;
  1366. }
  1367. // cleanup memory used to transfer image
  1368. _DSM_UnlockMemory(hMem);
  1369. _DSM_Free(hMem);
  1370. if(TWRC_XFERDONE != twrc)
  1371. {
  1372. // We were not able to transfer an image don't try to transfer more
  1373. break;
  1374. }
  1375. // The transfer is done. Tell the source
  1376. PrintCMDMessage("app: Checking to see if there are more images to transfer...\n");
  1377. TW_PENDINGXFERS pendxfers;
  1378. memset( &pendxfers, 0, sizeof(pendxfers) );
  1379. twrc = DSM_Entry( DG_CONTROL, DAT_PENDINGXFERS, MSG_ENDXFER, (TW_MEMREF)&pendxfers);
  1380. if(TWRC_SUCCESS == twrc)
  1381. {
  1382. PrintCMDMessage("app: Remaining images to transfer: %u\n", pendxfers.Count);
  1383. if(0 == pendxfers.Count)
  1384. {
  1385. // nothing left to transfer, finished.
  1386. bPendingXfers = false;
  1387. }
  1388. }
  1389. else
  1390. {
  1391. printError(m_pDataSource, "failed to properly end the transfer");
  1392. bPendingXfers = false;
  1393. }
  1394. }
  1395. // Check to see if we left the scan loop before we were actualy done scanning
  1396. // This will hapen if we had an error. Need to let the DS know we are not going
  1397. // to transfer more images
  1398. if(bPendingXfers == true)
  1399. {
  1400. twrc = DoAbortXfer();
  1401. }
  1402. // adjust our state now that the scanning session is done
  1403. m_DSMState = 5;
  1404. PrintCMDMessage("app: DONE!\n");
  1405. return;
  1406. }
  1407. //////////////////////////////////////////////////////////////////////////////
  1408. pTW_IDENTITY TwainApp::getAppIdentity()
  1409. {
  1410. return &m_MyInfo;
  1411. }
  1412. //////////////////////////////////////////////////////////////////////////////
  1413. pTW_IDENTITY TwainApp::getDataSource(TW_INT16 _index /*= -1*/) const
  1414. {
  1415. if(_index < 0 )
  1416. {
  1417. return m_pDataSource;
  1418. }
  1419. else
  1420. {
  1421. if(((unsigned int)_index) < m_DataSources.size())
  1422. {
  1423. return (pTW_IDENTITY)&m_DataSources[_index];
  1424. }
  1425. else
  1426. {
  1427. return NULL;
  1428. }
  1429. }
  1430. }
  1431. //////////////////////////////////////////////////////////////////////////////
  1432. TW_INT16 TwainApp::get_CAP(TW_CAPABILITY& _cap, TW_UINT16 _msg /* = MSG_GET */)
  1433. {
  1434. if(_msg != MSG_GET && _msg != MSG_GETCURRENT && _msg != MSG_GETDEFAULT && _msg != MSG_RESET)
  1435. {
  1436. PrintCMDMessage("Bad Message.\n");
  1437. return TWCC_BUMMER;
  1438. }
  1439. if(m_DSMState < 4)
  1440. {
  1441. PrintCMDMessage("You need to open a data source first.\n");
  1442. return TWCC_SEQERROR;
  1443. }
  1444. TW_INT16 CondCode = TWCC_SUCCESS;
  1445. // Check if this capability structure has memory already alloc'd.
  1446. // If it does, free that memory before the call else we'll have a memory
  1447. // leak because the source allocates memory during a MSG_GET.
  1448. if(0 != _cap.hContainer)
  1449. {
  1450. _DSM_Free(_cap.hContainer);
  1451. _cap.hContainer = 0;
  1452. }
  1453. _cap.ConType = TWON_DONTCARE16;
  1454. // capability structure is set, make the call to the source now
  1455. TW_UINT16 twrc = DSM_Entry( DG_CONTROL, DAT_CAPABILITY, _msg, (TW_MEMREF)&_cap);
  1456. switch(twrc)
  1457. {
  1458. case TWRC_FAILURE:
  1459. string strErr = "Failed to get the capability: [";
  1460. strErr += convertCAP_toString(_cap.Cap);
  1461. strErr += "]";
  1462. CondCode = printError(m_pDataSource, strErr);
  1463. break;
  1464. }
  1465. return CondCode;
  1466. }
  1467. int TwainApp::GetDSMState()
  1468. {
  1469. return m_DSMState;
  1470. }
  1471. //////////////////////////////////////////////////////////////////////////////
  1472. TW_INT16 TwainApp::QuerySupport_CAP(TW_UINT16 _cap, TW_UINT32 &_QS)
  1473. {
  1474. if(m_DSMState < 4)
  1475. {
  1476. PrintCMDMessage("You need to open a data source first.\n");
  1477. return TWCC_SEQERROR;
  1478. }
  1479. TW_CAPABILITY cap = {0};
  1480. cap.Cap = _cap;
  1481. cap.hContainer = 0;
  1482. cap.ConType = TWON_ONEVALUE;
  1483. _QS = 0;
  1484. // capability structure is set, make the call to the source now
  1485. TW_UINT16 twrc = DSM_Entry( DG_CONTROL, DAT_CAPABILITY, MSG_QUERYSUPPORT, (TW_MEMREF)&cap);
  1486. switch(twrc)
  1487. {
  1488. case TWRC_FAILURE:
  1489. default:
  1490. {
  1491. string strErr = "Failed to querry support the capability: [";
  1492. strErr += convertCAP_toString(_cap);
  1493. strErr += "]";
  1494. printError(m_pDataSource, strErr);
  1495. }
  1496. break;
  1497. case TWRC_SUCCESS:
  1498. if(cap.ConType == TWON_ONEVALUE)
  1499. {
  1500. pTW_ONEVALUE pVal = (pTW_ONEVALUE)_DSM_LockMemory(cap.hContainer);
  1501. _QS = pVal->Item;
  1502. _DSM_UnlockMemory(cap.hContainer);
  1503. }
  1504. _DSM_Free(cap.hContainer);
  1505. break;
  1506. }
  1507. return twrc;
  1508. }
  1509. //////////////////////////////////////////////////////////////////////////////
  1510. TW_UINT16 TwainApp::set_CapabilityOneValue(TW_UINT16 Cap, const int _value, TW_UINT16 _type)
  1511. {
  1512. TW_INT16 twrc = TWRC_FAILURE;
  1513. TW_CAPABILITY cap;
  1514. cap.Cap = Cap;
  1515. cap.ConType = TWON_ONEVALUE;
  1516. cap.hContainer = _DSM_Alloc(sizeof(TW_ONEVALUE));// Largest int size
  1517. if(0 == cap.hContainer)
  1518. {
  1519. printError(0, "Error allocating memory");
  1520. return twrc;
  1521. }
  1522. pTW_ONEVALUE pVal = (pTW_ONEVALUE)_DSM_LockMemory(cap.hContainer);
  1523. pVal->ItemType = _type;
  1524. switch(_type)
  1525. {
  1526. case TWTY_INT8:
  1527. *(TW_INT8*)&pVal->Item = (TW_INT8)_value;
  1528. break;
  1529. case TWTY_INT16:
  1530. *(TW_INT16*)&pVal->Item = (TW_INT16)_value;
  1531. break;
  1532. case TWTY_INT32:
  1533. *(TW_INT32*)&pVal->Item = (TW_INT32)_value;
  1534. break;
  1535. case TWTY_UINT8:
  1536. *(TW_UINT8*)&pVal->Item = (TW_UINT8)_value;
  1537. break;
  1538. case TWTY_UINT16:
  1539. *(TW_UINT16*)&pVal->Item = (TW_UINT16)_value;
  1540. break;
  1541. case TWTY_UINT32:
  1542. *(TW_UINT32*)&pVal->Item = (TW_UINT32)_value;
  1543. break;
  1544. case TWTY_BOOL:
  1545. *(TW_BOOL*)&pVal->Item = (TW_BOOL)_value;
  1546. break;
  1547. }
  1548. // capability structure is set, make the call to the source now
  1549. twrc = DSM_Entry( DG_CONTROL, DAT_CAPABILITY, MSG_SET, (TW_MEMREF)&(cap));
  1550. if(TWRC_CHECKSTATUS == twrc)
  1551. {
  1552. }
  1553. else if(TWRC_FAILURE == twrc)
  1554. {
  1555. printError(m_pDataSource, "Could not set capability");
  1556. }
  1557. _DSM_UnlockMemory(cap.hContainer);
  1558. _DSM_Free(cap.hContainer);
  1559. return twrc;
  1560. }
  1561. //////////////////////////////////////////////////////////////////////////////
  1562. TW_UINT16 TwainApp::set_CapabilityOneValue(TW_UINT16 Cap, const pTW_FIX32 _pValue)
  1563. {
  1564. TW_INT16 twrc = TWRC_FAILURE;
  1565. TW_CAPABILITY cap;
  1566. cap.Cap = Cap;
  1567. cap.ConType = TWON_ONEVALUE;
  1568. cap.hContainer = _DSM_Alloc(sizeof(TW_ONEVALUE_FIX32));
  1569. if(0 == cap.hContainer)
  1570. {
  1571. printError(0, "Error allocating memory");
  1572. return twrc;
  1573. }
  1574. pTW_ONEVALUE_FIX32 pVal = (pTW_ONEVALUE_FIX32)_DSM_LockMemory(cap.hContainer);
  1575. pVal->ItemType = TWTY_FIX32;
  1576. pVal->Item = *_pValue;
  1577. // capability structure is set, make the call to the source now
  1578. twrc = DSM_Entry( DG_CONTROL, DAT_CAPABILITY, MSG_SET, (TW_MEMREF)&(cap));
  1579. if(TWRC_CHECKSTATUS == twrc)
  1580. {
  1581. }
  1582. else if(TWRC_FAILURE == twrc)
  1583. {
  1584. printError(m_pDataSource, "Could not set capability");
  1585. }
  1586. _DSM_UnlockMemory(cap.hContainer);
  1587. _DSM_Free(cap.hContainer);
  1588. return twrc;
  1589. }
  1590. //////////////////////////////////////////////////////////////////////////////
  1591. TW_UINT16 TwainApp::set_CapabilityOneValue(TW_UINT16 Cap, const pTW_FRAME _pValue)
  1592. {
  1593. TW_INT16 twrc = TWRC_FAILURE;
  1594. TW_CAPABILITY cap;
  1595. cap.Cap = Cap;
  1596. cap.ConType = TWON_ONEVALUE;
  1597. cap.hContainer = _DSM_Alloc(sizeof(TW_ONEVALUE_FRAME));
  1598. if(0 == cap.hContainer)
  1599. {
  1600. printError(0, "Error allocating memory");
  1601. return twrc;
  1602. }
  1603. pTW_ONEVALUE_FRAME pVal = (pTW_ONEVALUE_FRAME)_DSM_LockMemory(cap.hContainer);
  1604. pVal->ItemType = TWTY_FRAME;
  1605. pVal->Item = *_pValue;
  1606. // capability structure is set, make the call to the source now
  1607. twrc = DSM_Entry( DG_CONTROL, DAT_CAPABILITY, MSG_SET, (TW_MEMREF)&(cap));
  1608. if(TWRC_CHECKSTATUS == twrc)
  1609. {
  1610. }
  1611. else if(TWRC_FAILURE == twrc)
  1612. {
  1613. printError(m_pDataSource, "Could not set capability");
  1614. }
  1615. _DSM_UnlockMemory(cap.hContainer);
  1616. _DSM_Free(cap.hContainer);
  1617. return twrc;
  1618. }
  1619. //////////////////////////////////////////////////////////////////////////////
  1620. TW_UINT16 TwainApp::set_CapabilityArray(TW_UINT16 Cap, const int * _pValues, int Count, TW_UINT16 _type)
  1621. {
  1622. TW_INT16 twrc = TWRC_FAILURE;
  1623. TW_CAPABILITY cap;
  1624. cap.Cap = Cap;
  1625. cap.ConType = TWON_ARRAY;
  1626. cap.hContainer = _DSM_Alloc(sizeof(TW_ARRAY) + getTWTYsize(_type)*Count );// Largest int size
  1627. if(0 == cap.hContainer)
  1628. {
  1629. printError(0, "Error allocating memory");
  1630. return twrc;
  1631. }
  1632. pTW_ARRAY pArray = (pTW_ARRAY)_DSM_LockMemory(cap.hContainer);
  1633. pArray->ItemType = _type;
  1634. pArray->NumItems = Count;
  1635. int i = 0;
  1636. switch(_type)
  1637. {
  1638. case TWTY_INT8:
  1639. for(i=0; i<Count; i++)
  1640. {
  1641. ((pTW_INT8)(&pArray->ItemList))[i] = (TW_INT8)_pValues[i];
  1642. }
  1643. break;
  1644. case TWTY_INT16:
  1645. for(i=0; i<Count; i++)
  1646. {
  1647. ((pTW_INT16)(&pArray->ItemList))[i] = (TW_INT16)_pValues[i];
  1648. }
  1649. break;
  1650. case TWTY_INT32:
  1651. for(i=0; i<Count; i++)
  1652. {
  1653. ((pTW_INT32)(&pArray->ItemList))[i] = (TW_INT32)_pValues[i];
  1654. }
  1655. break;
  1656. case TWTY_UINT8:
  1657. for(i=0; i<Count; i++)
  1658. {
  1659. ((pTW_UINT8)(&pArray->ItemList))[i] = (TW_UINT8)_pValues[i];
  1660. }
  1661. break;
  1662. case TWTY_UINT16:
  1663. for(i=0; i<Count; i++)
  1664. {
  1665. ((pTW_UINT16)(&pArray->ItemList))[i] = (TW_UINT16)_pValues[i];
  1666. }
  1667. break;
  1668. case TWTY_UINT32:
  1669. for(i=0; i<Count; i++)
  1670. {
  1671. ((pTW_UINT32)(&pArray->ItemList))[i] = (TW_UINT32)_pValues[i];
  1672. }
  1673. break;
  1674. case TWTY_BOOL:
  1675. for(i=0; i<Count; i++)
  1676. {
  1677. ((pTW_BOOL)(&pArray->ItemList))[i] = (TW_BOOL)_pValues[i];
  1678. }
  1679. break;
  1680. }
  1681. // capability structure is set, make the call to the source now
  1682. twrc = DSM_Entry( DG_CONTROL, DAT_CAPABILITY, MSG_SET, (TW_MEMREF)&(cap));
  1683. if(TWRC_CHECKSTATUS == twrc)
  1684. {
  1685. }
  1686. else if(TWRC_FAILURE == twrc)
  1687. {
  1688. printError(m_pDataSource, "Could not set capability");
  1689. }
  1690. _DSM_UnlockMemory(cap.hContainer);
  1691. _DSM_Free(cap.hContainer);
  1692. return twrc;
  1693. }
  1694. TW_INT16 TwainApp::GetLabel(TW_UINT16 _cap, string &sLable)
  1695. {
  1696. if(m_nGetLableSupported == TWCC_BADPROTOCOL)
  1697. {
  1698. return TWRC_FAILURE;
  1699. }
  1700. if(m_DSMState < 4)
  1701. {
  1702. PrintCMDMessage("You need to open a data source first.\n");
  1703. return TWCC_SEQERROR;
  1704. }
  1705. TW_CAPABILITY cap = {0};
  1706. cap.Cap = _cap;
  1707. cap.hContainer = 0;
  1708. cap.ConType = TWON_ONEVALUE;
  1709. // capability structure is set, make the call to the source now
  1710. TW_UINT16 twrc = DSM_Entry( DG_CONTROL, DAT_CAPABILITY, MSG_GETLABEL, (TW_MEMREF)&cap);
  1711. switch(twrc)
  1712. {
  1713. case TWRC_FAILURE:
  1714. default:
  1715. {
  1716. string strErr = "Failed to GetLabel for the capability: [";
  1717. strErr += convertCAP_toString(_cap);
  1718. strErr += "]";
  1719. if(TWCC_BADPROTOCOL == printError(m_pDataSource, strErr))
  1720. {
  1721. m_nGetLableSupported = TWCC_BADPROTOCOL;
  1722. }
  1723. }
  1724. break;
  1725. case TWRC_SUCCESS:
  1726. if(cap.ConType == TWON_ONEVALUE)
  1727. {
  1728. pTW_ONEVALUE pVal = (pTW_ONEVALUE)_DSM_LockMemory(cap.hContainer);
  1729. TW_UINT16 type = pVal->ItemType;
  1730. _DSM_UnlockMemory(cap.hContainer);
  1731. switch(type)
  1732. {
  1733. case TWTY_STR32:
  1734. case TWTY_STR64:
  1735. case TWTY_STR128:
  1736. printError(m_pDataSource, "Wrong STR type for MSG_GETLABEL");
  1737. case TWTY_STR255:
  1738. getCurrent(&cap, sLable);
  1739. break;
  1740. default:
  1741. twrc = TWRC_FAILURE;
  1742. break;
  1743. }
  1744. }
  1745. _DSM_Free(cap.hContainer);
  1746. break;
  1747. }
  1748. return twrc;
  1749. }
  1750. TW_INT16 TwainApp::GetHelp(TW_UINT16 _cap, string &sHelp)
  1751. {
  1752. if(m_nGetHelpSupported == TWCC_BADPROTOCOL)
  1753. {
  1754. return TWRC_FAILURE;
  1755. }
  1756. if(m_DSMState < 4)
  1757. {
  1758. PrintCMDMessage("You need to open a data source first.\n");
  1759. return TWCC_SEQERROR;
  1760. }
  1761. TW_CAPABILITY cap = {0};
  1762. cap.Cap = _cap;
  1763. cap.hContainer = 0;
  1764. cap.ConType = TWON_ONEVALUE;
  1765. // capability structure is set, make the call to the source now
  1766. TW_UINT16 twrc = DSM_Entry( DG_CONTROL, DAT_CAPABILITY, MSG_GETHELP, (TW_MEMREF)&cap);
  1767. switch(twrc)
  1768. {
  1769. case TWRC_FAILURE:
  1770. default:
  1771. {
  1772. string strErr = "Failed to GetHelp for the capability: [";
  1773. strErr += convertCAP_toString(_cap);
  1774. strErr += "]";
  1775. if(TWCC_BADPROTOCOL == printError(m_pDataSource, strErr))
  1776. {
  1777. m_nGetHelpSupported = TWCC_BADPROTOCOL;
  1778. }
  1779. }
  1780. break;
  1781. case TWRC_SUCCESS:
  1782. if(cap.ConType == TWON_ONEVALUE)
  1783. {
  1784. pTW_ONEVALUE pVal = (pTW_ONEVALUE)_DSM_LockMemory(cap.hContainer);
  1785. TW_UINT16 type = pVal->ItemType;
  1786. _DSM_UnlockMemory(cap.hContainer);
  1787. switch(type)
  1788. {
  1789. case TWTY_STR32:
  1790. case TWTY_STR64:
  1791. case TWTY_STR128:
  1792. case TWTY_STR255:
  1793. printError(m_pDataSource, "Wrong STR type for MSG_GETHELP");
  1794. // case TWTY_STR4096:
  1795. getCurrent(&cap, sHelp);
  1796. break;
  1797. default:
  1798. twrc = TWRC_FAILURE;
  1799. break;
  1800. }
  1801. }
  1802. _DSM_Free(cap.hContainer);
  1803. break;
  1804. }
  1805. return twrc;
  1806. }
  1807. void TwainApp::navtive_graber( PBITMAPINFOHEADER pDIB )
  1808. {
  1809. return;
  1810. }
  1811. BOOL TwainApp::HasStopCommand()
  1812. {
  1813. return FALSE;
  1814. }
  1815. //#define MSG_GETLABELENUM 0x000b /* Return all of the labels for a capability of type Added 2.1 */