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.

650 lines
22 KiB

  1. #include "precomp.h"
  2. #include "dsloader.h"
  3. #include <sti.h>
  4. extern IMessageFilter * g_pOldOleMessageFilter;
  5. const DWORD FINDCONTEXT_SIGNATURE = 0x1F2E4C3D;
  6. HINSTANCE g_hInstance;
  7. TW_STATUS g_twStatus;
  8. typedef struct tagFindContext {
  9. DWORD Signature;
  10. IEnumWIA_DEV_INFO *pEnumDevInfo;
  11. }FINDCONTEXT, *PFINDCONTEXT;
  12. BOOL WINAPI DllMain(HMODULE hModule, DWORD dwReason, void* lpReserved)
  13. {
  14. HRESULT hr = S_OK;
  15. DBG_INIT((HINSTANCE)hModule);
  16. switch (dwReason) {
  17. case DLL_PROCESS_ATTACH:
  18. // Disable thread library calls to avoid
  19. // deadlock when we spin up the worker thread
  20. DisableThreadLibraryCalls(hModule);
  21. g_hInstance = hModule;
  22. InitCommonControls();
  23. break;
  24. case DLL_PROCESS_DETACH:
  25. break;
  26. default:
  27. break;
  28. }
  29. return TRUE ;
  30. }
  31. TW_UINT16 APIENTRY ImportedDSEntry(HANDLE hDS,TW_IDENTITY *AppId,TW_UINT32 DG,
  32. TW_UINT16 DT,TW_UINT16 MSG,TW_MEMREF pData)
  33. {
  34. if (MSG != MSG_PROCESSEVENT) {
  35. if(AppId != NULL) {
  36. #ifdef UNICODE
  37. //
  38. // TWAIN only passes ANSI strings. DPRINTF(DM_TRACE,) is expecting TCHARs which are supposed to
  39. // be WCHAR on NT. Conversion here is only for clear debug output, and will
  40. // not be in release builds. (the calling application name is useful for logging)
  41. //
  42. WCHAR szProductName[255];
  43. MultiByteToWideChar(CP_ACP, 0, AppId->ProductName, -1, szProductName, (sizeof(szProductName) / sizeof(szProductName[0])));
  44. DBG_TRC(("[%ws] Sent to TWAIN Source, DG = %X, DT = %X, MSG = %X",szProductName,DG,DT,MSG));
  45. #else
  46. DBG_TRC(("[%s] Sent to TWAIN Source, DG = %X, DT = %X, MSG = %X",AppId->ProductName,DG,DT,MSG));
  47. #endif
  48. }
  49. if (DT == DAT_CAPABILITY) {
  50. if (g_dwDebugFlags & COREDBG_TRACES) {
  51. char szBuf[256];
  52. memset(szBuf,0,sizeof(szBuf));
  53. switch (MSG) {
  54. case MSG_GET:
  55. lstrcpyA(szBuf,"MSG_GET");
  56. break;
  57. case MSG_GETCURRENT:
  58. lstrcpyA(szBuf,"MSG_GETCURRENT");
  59. break;
  60. case MSG_GETDEFAULT:
  61. lstrcpyA(szBuf,"MSG_GETDEFAULT");
  62. break;
  63. case MSG_SET:
  64. lstrcpyA(szBuf,"MSG_SET");
  65. break;
  66. case MSG_RESET:
  67. lstrcpyA(szBuf,"MSG_RESET");
  68. break;
  69. default:
  70. lstrcpyA(szBuf,"MSG_UNKNOWN");
  71. DBG_TRC(("Unknown MSG = %X",MSG));
  72. break;
  73. }
  74. char szBuf2[256];
  75. memset(szBuf2,0,sizeof(szBuf2));
  76. switch (((TW_CAPABILITY*)pData)->Cap) {
  77. case CAP_CUSTOMBASE:
  78. lstrcpyA(szBuf2,"CAP_CUSTOMBASE");
  79. break;
  80. case CAP_XFERCOUNT:
  81. lstrcpyA(szBuf2,"CAP_XFERCOUNT");
  82. break;
  83. case ICAP_COMPRESSION:
  84. lstrcpyA(szBuf2,"ICAP_COMPRESSION");
  85. break;
  86. case ICAP_PIXELTYPE:
  87. lstrcpyA(szBuf2,"ICAP_PIXELTYPE");
  88. break;
  89. case ICAP_UNITS:
  90. lstrcpyA(szBuf2,"ICAP_UNITS");
  91. break;
  92. case ICAP_XFERMECH:
  93. lstrcpyA(szBuf2,"ICAP_XFERMECH");
  94. break;
  95. case CAP_AUTHOR:
  96. lstrcpyA(szBuf2,"CAP_AUTHOR");
  97. break;
  98. case CAP_CAPTION:
  99. lstrcpyA(szBuf2,"CAP_CAPTION");
  100. break;
  101. case CAP_FEEDERENABLED:
  102. lstrcpyA(szBuf2,"CAP_FEEDERENABLED");
  103. break;
  104. case CAP_FEEDERLOADED:
  105. lstrcpyA(szBuf2,"CAP_FEEDERLOADED");
  106. break;
  107. case CAP_TIMEDATE:
  108. lstrcpyA(szBuf2,"CAP_TIMEDATE");
  109. break;
  110. case CAP_SUPPORTEDCAPS:
  111. lstrcpyA(szBuf2,"CAP_SUPPORTEDCAPS");
  112. break;
  113. case CAP_EXTENDEDCAPS:
  114. lstrcpyA(szBuf2,"CAP_EXTENDEDCAPS");
  115. break;
  116. case CAP_AUTOFEED:
  117. lstrcpyA(szBuf2,"CAP_AUTOFEED");
  118. break;
  119. case CAP_CLEARPAGE:
  120. lstrcpyA(szBuf2,"CAP_CLEARPAGE");
  121. break;
  122. case CAP_FEEDPAGE:
  123. lstrcpyA(szBuf2,"CAP_FEEDPAGE");
  124. break;
  125. case CAP_REWINDPAGE:
  126. lstrcpyA(szBuf2,"CAP_REWINDPAGE");
  127. break;
  128. case CAP_INDICATORS:
  129. lstrcpyA(szBuf2,"CAP_INDICATORS");
  130. break;
  131. case CAP_SUPPORTEDCAPSEXT:
  132. lstrcpyA(szBuf2,"CAP_SUPPORTEDCAPSEXT");
  133. break;
  134. case CAP_PAPERDETECTABLE:
  135. lstrcpyA(szBuf2,"CAP_PAPERDETECTABLE");
  136. break;
  137. case CAP_UICONTROLLABLE:
  138. lstrcpyA(szBuf2,"CAP_UICONTROLLABLE");
  139. break;
  140. case CAP_DEVICEONLINE:
  141. lstrcpyA(szBuf2,"CAP_DEVICEONLINE");
  142. break;
  143. case CAP_AUTOSCAN:
  144. lstrcpyA(szBuf2,"CAP_AUTOSCAN");
  145. break;
  146. case CAP_THUMBNAILSENABLED:
  147. lstrcpyA(szBuf2,"CAP_THUMBNAILSENABLED");
  148. break;
  149. case CAP_DUPLEX:
  150. lstrcpyA(szBuf2,"CAP_DUPLEX");
  151. break;
  152. case CAP_DUPLEXENABLED:
  153. lstrcpyA(szBuf2,"CAP_DUPLEXENABLED");
  154. break;
  155. case CAP_ENABLEDSUIONLY:
  156. lstrcpyA(szBuf2,"CAP_ENABLEDSUIONLY");
  157. break;
  158. case CAP_CUSTOMDSDATA:
  159. lstrcpyA(szBuf2,"CAP_CUSTOMDSDATA");
  160. break;
  161. case CAP_ENDORSER:
  162. lstrcpyA(szBuf2,"CAP_ENDORSER");
  163. break;
  164. case CAP_JOBCONTROL:
  165. lstrcpyA(szBuf2,"CAP_JOBCONTROL");
  166. break;
  167. case ICAP_AUTOBRIGHT:
  168. lstrcpyA(szBuf2,"ICAP_AUTOBRIGHT");
  169. break;
  170. case ICAP_BRIGHTNESS:
  171. lstrcpyA(szBuf2,"ICAP_BRIGHTNESS");
  172. break;
  173. case ICAP_CONTRAST:
  174. lstrcpyA(szBuf2,"ICAP_CONTRAST");
  175. break;
  176. case ICAP_CUSTHALFTONE:
  177. lstrcpyA(szBuf2,"ICAP_CUSTHALFTONE");
  178. break;
  179. case ICAP_EXPOSURETIME:
  180. lstrcpyA(szBuf2,"ICAP_EXPOSURETIME");
  181. break;
  182. case ICAP_FILTER:
  183. lstrcpyA(szBuf2,"ICAP_FILTER");
  184. break;
  185. case ICAP_FLASHUSED:
  186. lstrcpyA(szBuf2,"ICAP_FLASHUSED");
  187. break;
  188. case ICAP_GAMMA:
  189. lstrcpyA(szBuf2,"ICAP_GAMMA");
  190. break;
  191. case ICAP_HALFTONES:
  192. lstrcpyA(szBuf2,"ICAP_HALFTONES");
  193. break;
  194. case ICAP_HIGHLIGHT:
  195. lstrcpyA(szBuf2,"ICAP_HIGHLIGHT");
  196. break;
  197. case ICAP_IMAGEFILEFORMAT:
  198. lstrcpyA(szBuf2,"ICAP_IMAGEFILEFORMAT");
  199. break;
  200. case ICAP_LAMPSTATE:
  201. lstrcpyA(szBuf2,"ICAP_LAMPSTATE");
  202. break;
  203. case ICAP_LIGHTSOURCE:
  204. lstrcpyA(szBuf2,"ICAP_LIGHTSOURCE");
  205. break;
  206. case ICAP_ORIENTATION:
  207. lstrcpyA(szBuf2,"ICAP_ORIENTATION");
  208. break;
  209. case ICAP_PHYSICALWIDTH:
  210. lstrcpyA(szBuf2,"ICAP_PHYSICALWIDTH");
  211. break;
  212. case ICAP_PHYSICALHEIGHT:
  213. lstrcpyA(szBuf2,"ICAP_PHYSICALHEIGHT");
  214. break;
  215. case ICAP_SHADOW:
  216. lstrcpyA(szBuf2,"ICAP_SHADOW");
  217. break;
  218. case ICAP_FRAMES:
  219. lstrcpyA(szBuf2,"ICAP_FRAMES");
  220. break;
  221. case ICAP_XNATIVERESOLUTION:
  222. lstrcpyA(szBuf2,"ICAP_XNATIVERESOLUTION");
  223. break;
  224. case ICAP_YNATIVERESOLUTION:
  225. lstrcpyA(szBuf2,"ICAP_YNATIVERESOLUTION");
  226. break;
  227. case ICAP_XRESOLUTION:
  228. lstrcpyA(szBuf2,"ICAP_XRESOLUTION");
  229. break;
  230. case ICAP_YRESOLUTION:
  231. lstrcpyA(szBuf2,"ICAP_YRESOLUTION");
  232. break;
  233. case ICAP_MAXFRAMES:
  234. lstrcpyA(szBuf2,"ICAP_MAXFRAMES");
  235. break;
  236. case ICAP_TILES:
  237. lstrcpyA(szBuf2,"ICAP_TILES");
  238. break;
  239. case ICAP_BITORDER:
  240. lstrcpyA(szBuf2,"ICAP_BITORDER");
  241. break;
  242. case ICAP_CCITTKFACTOR:
  243. lstrcpyA(szBuf2,"ICAP_CCITTKFACTOR");
  244. break;
  245. case ICAP_LIGHTPATH:
  246. lstrcpyA(szBuf2,"ICAP_LIGHTPATH");
  247. break;
  248. case ICAP_PIXELFLAVOR:
  249. lstrcpyA(szBuf2,"ICAP_PIXELFLAVOR");
  250. break;
  251. case ICAP_PLANARCHUNKY:
  252. lstrcpyA(szBuf2,"ICAP_PLANARCHUNKY");
  253. break;
  254. case ICAP_ROTATION:
  255. lstrcpyA(szBuf2,"ICAP_ROTATION");
  256. break;
  257. case ICAP_SUPPORTEDSIZES:
  258. lstrcpyA(szBuf2,"ICAP_SUPPORTEDSIZES");
  259. break;
  260. case ICAP_THRESHOLD:
  261. lstrcpyA(szBuf2,"ICAP_THRESHOLD");
  262. break;
  263. case ICAP_XSCALING:
  264. lstrcpyA(szBuf2,"ICAP_XSCALING");
  265. break;
  266. case ICAP_YSCALING:
  267. lstrcpyA(szBuf2,"ICAP_YSCALING");
  268. break;
  269. case ICAP_BITORDERCODES:
  270. lstrcpyA(szBuf2,"ICAP_BITORDERCODES");
  271. break;
  272. case ICAP_PIXELFLAVORCODES:
  273. lstrcpyA(szBuf2,"ICAP_PIXELFLAVORCODES");
  274. break;
  275. case ICAP_JPEGPIXELTYPE:
  276. lstrcpyA(szBuf2,"ICAP_JPEGPIXELTYPE");
  277. break;
  278. case ICAP_TIMEFILL:
  279. lstrcpyA(szBuf2,"ICAP_TIMEFILL");
  280. break;
  281. case ICAP_BITDEPTH:
  282. lstrcpyA(szBuf2,"ICAP_BITDEPTH");
  283. break;
  284. case ICAP_BITDEPTHREDUCTION:
  285. lstrcpyA(szBuf2,"ICAP_BITDEPTHREDUCTION");
  286. break;
  287. case ICAP_UNDEFINEDIMAGESIZE:
  288. lstrcpyA(szBuf2,"ICAP_UNDEFINEDIMAGESIZE");
  289. break;
  290. case ICAP_IMAGEDATASET:
  291. lstrcpyA(szBuf2,"ICAP_IMAGEDATASET");
  292. break;
  293. case ICAP_EXTIMAGEINFO:
  294. lstrcpyA(szBuf2,"ICAP_EXTIMAGEINFO");
  295. break;
  296. case ICAP_MINIMUMHEIGHT:
  297. lstrcpyA(szBuf2,"ICAP_MINIMUMHEIGHT");
  298. break;
  299. case ICAP_MINIMUMWIDTH:
  300. lstrcpyA(szBuf2,"ICAP_MINIMUMWIDTH");
  301. break;
  302. default:
  303. lstrcpyA(szBuf2,"(undefined or new CAP)");
  304. break;
  305. }
  306. DBG_TRC(("DAT_CAPABILITY operation, %s on CAP = %s (%x)",szBuf,szBuf2,((TW_CAPABILITY*)pData)->Cap));
  307. }
  308. }
  309. }
  310. CWiaDataSrc *pDataSrc;
  311. pDataSrc = (CWiaDataSrc *)hDS;
  312. if (pDataSrc) {
  313. return pDataSrc->DSEntry(AppId, DG, DT, MSG, pData);
  314. }
  315. return TWRC_FAILURE;
  316. }
  317. TW_UINT16 APIENTRY FindFirstImportDS(PIMPORT_DSINFO pDSInfo,PVOID *Context)
  318. {
  319. DBG_TRC(("FindFirstImportDS - CoInitialize"));
  320. ::CoInitialize(NULL);
  321. if (!pDSInfo || pDSInfo->Size < sizeof(IMPORT_DSINFO) ||
  322. !Context) {
  323. g_twStatus.ConditionCode = TWCC_BADVALUE;
  324. return TWRC_FAILURE;
  325. }
  326. HRESULT hr;
  327. IWiaDevMgr *pWiaDevMgr;
  328. TW_UINT16 twRc;
  329. *Context = NULL;
  330. g_twStatus.ConditionCode = TWCC_OPERATIONERROR;
  331. //
  332. // Presume guilty
  333. //
  334. twRc = TWRC_FAILURE;
  335. //
  336. // Get IWiaDevMgr interface
  337. //
  338. hr = CoCreateInstance(CLSID_WiaDevMgr, NULL,
  339. CLSCTX_LOCAL_SERVER,
  340. IID_IWiaDevMgr,
  341. (void**)&pWiaDevMgr
  342. );
  343. if (SUCCEEDED(hr)) {
  344. //
  345. // Get IEnumWIA_DEV_INFO interface.
  346. // This interface pointer will be saved as part
  347. // of the find context.
  348. //
  349. IEnumWIA_DEV_INFO *pEnumDevInfo = NULL;
  350. hr = pWiaDevMgr->EnumDeviceInfo(0, &pEnumDevInfo);
  351. //
  352. // We do not need the IWiaDevMgr interface anymore. The reference count
  353. // on the IEnumWIA_DEV_INFO will keep the WIA Device Manager
  354. // alive.
  355. //
  356. pWiaDevMgr->Release();
  357. if (SUCCEEDED(hr)) {
  358. //
  359. // Make sure the current position is reset to the begining.
  360. //
  361. pEnumDevInfo->Reset();
  362. //
  363. // Create a new find context
  364. //
  365. PFINDCONTEXT pFindContext;
  366. pFindContext = new FINDCONTEXT;
  367. if (pFindContext) {
  368. pFindContext->pEnumDevInfo = pEnumDevInfo;
  369. pFindContext->Signature = FINDCONTEXT_SIGNATURE;
  370. //
  371. // This gets the first available data source
  372. //
  373. twRc = FindNextImportDS(pDSInfo, pFindContext);
  374. if (TWRC_SUCCESS == twRc) {
  375. *Context = pFindContext;
  376. } else {
  377. //
  378. // The callers will not call CloseFindContext
  379. // if FindFirstContext failed. For this reason
  380. // we have to delete the find context here
  381. //
  382. delete pFindContext;
  383. pFindContext = NULL;
  384. }
  385. } else {
  386. //
  387. // set TWAIN condition code to TWCC_LOWMEMORY
  388. // because we failed to allocate pFindContext
  389. //
  390. g_twStatus.ConditionCode = TWCC_LOWMEMORY;
  391. }
  392. }
  393. //
  394. // release IEnumWIA_DEV_INFO interface when finished
  395. //
  396. /*
  397. if (pEnumDevInfo) {
  398. pEnumDevInfo->Release();
  399. pEnumDevInfo = NULL;
  400. if(*Context){
  401. PFINDCONTEXT pFindContext;
  402. pFindContext = (PFINDCONTEXT)*Context;
  403. pFindContext->pEnumDevInfo = NULL;
  404. }
  405. }
  406. */
  407. }
  408. return twRc;
  409. }
  410. TW_UINT16 APIENTRY FindNextImportDS(PIMPORT_DSINFO pDSInfo,PVOID Context)
  411. {
  412. PFINDCONTEXT pFindContext;
  413. pFindContext = (PFINDCONTEXT)Context;
  414. if (!pDSInfo || pDSInfo->Size < sizeof(IMPORT_DSINFO) ||
  415. !pFindContext || FINDCONTEXT_SIGNATURE != pFindContext->Signature ||
  416. !pFindContext->pEnumDevInfo) {
  417. g_twStatus.ConditionCode = TWCC_BADVALUE;
  418. return TWRC_FAILURE;
  419. }
  420. HRESULT hr = S_OK;
  421. TW_UINT16 twRc = TWRC_FAILURE;
  422. g_twStatus.ConditionCode = TWCC_OPERATIONERROR;
  423. IWiaPropertyStorage *piwps = NULL;
  424. DWORD Count = 0;
  425. while (S_OK == pFindContext->pEnumDevInfo->Next(1, &piwps, &Count)) {
  426. PROPSPEC propSpec;
  427. PROPVARIANT propVar;
  428. propSpec.ulKind = PRSPEC_PROPID;
  429. propSpec.propid = WIA_DIP_DEV_ID;
  430. propVar.vt = VT_BSTR;
  431. hr = piwps->ReadMultiple(1, &propSpec, &propVar);
  432. if (SUCCEEDED(hr)) {
  433. DBG_TRC(("Found Device ID %ws", propVar.bstrVal));
  434. //
  435. // LPOLESTR == LPWSTR. We have to convert the device id
  436. // from UNICODE to ANSI
  437. //
  438. WideCharToMultiByte(CP_ACP, 0, propVar.bstrVal, -1,pDSInfo->DeviceName,
  439. sizeof(pDSInfo->DeviceName) / sizeof(pDSInfo->DeviceName[0]),NULL, NULL);
  440. //
  441. // Remember this or lose memory.
  442. //
  443. SysFreeString(propVar.bstrVal);
  444. //
  445. // Get device type
  446. //
  447. pDSInfo->DeviceFlags &= ~DEVICE_FLAGS_DEVICETYPE;
  448. PropVariantInit(&propVar);
  449. propSpec.propid = WIA_DIP_DEV_TYPE;
  450. hr = piwps->ReadMultiple(1, &propSpec, &propVar);
  451. piwps->Release();
  452. if (SUCCEEDED(hr)) {
  453. switch (GET_STIDEVICE_TYPE(propVar.ulVal)) {
  454. case StiDeviceTypeDigitalCamera:
  455. pDSInfo->DeviceFlags |= DEVICETYPE_DIGITALCAMERA;
  456. break;
  457. case StiDeviceTypeScanner:
  458. pDSInfo->DeviceFlags |= DEVICETYPE_SCANNER;
  459. break;
  460. case StiDeviceTypeStreamingVideo:
  461. pDSInfo->DeviceFlags |= DEVICETYPE_STREAMINGVIDEO;
  462. break;
  463. default:
  464. pDSInfo->DeviceFlags |= DEVICETYPE_UNKNOWN;
  465. }
  466. //
  467. // All our data sources share the same load/unload function
  468. //
  469. pDSInfo->pfnLoadDS = LoadImportDS;
  470. pDSInfo->pfnUnloadDS = UnloadImportDS;
  471. return TWRC_SUCCESS;
  472. } else {
  473. DBG_TRC(("Unable to get DEV_TYPE, hr = %lx", hr));
  474. pDSInfo->DeviceFlags |= DEVICETYPE_UNKNOWN;
  475. }
  476. }
  477. //
  478. // Keep looking
  479. //
  480. }
  481. //
  482. // We are out of data sources.
  483. //
  484. return TWRC_ENDOFLIST;
  485. }
  486. TW_UINT16 APIENTRY CloseFindContext(PVOID Context)
  487. {
  488. PFINDCONTEXT pFindContext;
  489. pFindContext = (PFINDCONTEXT)Context;
  490. if (!pFindContext || FINDCONTEXT_SIGNATURE != pFindContext->Signature) {
  491. g_twStatus.ConditionCode = TWCC_BADVALUE;
  492. return TWRC_FAILURE;
  493. }
  494. if (pFindContext->pEnumDevInfo) {
  495. pFindContext->pEnumDevInfo->Release();
  496. pFindContext->pEnumDevInfo = NULL;
  497. }
  498. delete pFindContext;
  499. DBG_TRC(("CloseFindContext - CoUnIntialize()"));
  500. ::CoUninitialize();
  501. return TWRC_SUCCESS;
  502. }
  503. TW_UINT16 APIENTRY LoadImportDS(LPCSTR DeviceName,DWORD DeviceFlags,HANDLE *phDS,
  504. PFNIMPORTEDDSENTRY *pdsEntry)
  505. {
  506. DBG_TRC(("LoadImportDS - CoInitialize()"));
  507. ::CoInitialize(NULL);
  508. if (!DeviceName || !phDS || !pdsEntry) {
  509. g_twStatus.ConditionCode = TWCC_BADVALUE;
  510. return TWRC_FAILURE;
  511. }
  512. *phDS = NULL;
  513. *pdsEntry = NULL;
  514. //
  515. // Create Data source
  516. //
  517. CWiaDataSrc *pDS;
  518. if (DEVICETYPE_DIGITALCAMERA == (DeviceFlags & DEVICE_FLAGS_DEVICETYPE)) {
  519. pDS = new CWiaCameraDS;
  520. } else if (DEVICETYPE_SCANNER == (DeviceFlags & DEVICE_FLAGS_DEVICETYPE)) {
  521. pDS = new CWiaScannerDS;
  522. } else if (DEVICETYPE_STREAMINGVIDEO == (DeviceFlags & DEVICE_FLAGS_DEVICETYPE)) {
  523. pDS = new CWiaVideoDS;
  524. } else {
  525. //
  526. // Unknown device type
  527. //
  528. g_twStatus.ConditionCode = TWCC_BUMMER;
  529. return TWRC_FAILURE;
  530. }
  531. TW_UINT16 twCc = TWRC_SUCCESS;
  532. if (pDS) {
  533. //
  534. // Initialize the data source
  535. //
  536. #ifdef UNICODE
  537. WCHAR DeviceNameW[MAX_PATH];
  538. MultiByteToWideChar(CP_ACP, 0, DeviceName, -1, DeviceNameW,sizeof(DeviceNameW) / sizeof(DeviceNameW[0]));
  539. twCc = pDS->IWiaDataSrc(DeviceNameW);
  540. #else
  541. twCc = pDS->IWiaDataSrc(DeviceName);
  542. #endif
  543. if (TWCC_SUCCESS != twCc) {
  544. delete pDS;
  545. pDS = NULL;
  546. g_twStatus.ConditionCode = twCc;
  547. return TWRC_FAILURE;
  548. }
  549. *phDS = (HANDLE)pDS;
  550. *pdsEntry = ImportedDSEntry;
  551. return TWRC_SUCCESS;
  552. } else {
  553. g_twStatus.ConditionCode = TWCC_LOWMEMORY;
  554. return TWRC_FAILURE;
  555. }
  556. }
  557. TW_UINT16 APIENTRY UnloadImportDS(HANDLE hDS)
  558. {
  559. CWiaDataSrc *pDS;
  560. pDS = (CWiaDataSrc *)hDS;
  561. if (pDS) {
  562. delete pDS;
  563. DBG_TRC(("UnloadImportDS - CoUnInitialize()"));
  564. ::CoUninitialize();
  565. return TWRC_SUCCESS;
  566. }
  567. g_twStatus.ConditionCode = TWCC_BUMMER;
  568. return TWRC_FAILURE;
  569. }
  570. TW_UINT16 APIENTRY GetLoaderStatus(TW_STATUS *ptwStatus)
  571. {
  572. if (!ptwStatus) {
  573. g_twStatus.ConditionCode = TWCC_BADVALUE;
  574. return TWRC_FAILURE;
  575. }
  576. *ptwStatus = g_twStatus;
  577. return TWRC_SUCCESS;
  578. }
  579. TW_UINT16 APIENTRY FindImportDSByDeviceName(PIMPORT_DSINFO pDSInfo,LPCSTR DeviceName)
  580. {
  581. if (!pDSInfo || pDSInfo->Size < sizeof(IMPORT_DSINFO) ||
  582. !DeviceName) {
  583. g_twStatus.ConditionCode = TWCC_BADVALUE;
  584. return TWRC_FAILURE;
  585. }
  586. PVOID Context;
  587. TW_UINT16 twRc = TWRC_ENDOFLIST;
  588. if (TWRC_SUCCESS == FindFirstImportDS(pDSInfo, &Context)) {
  589. do {
  590. if (!_strcmpi(DeviceName, pDSInfo->DeviceName)) {
  591. twRc = TWRC_SUCCESS;
  592. break;
  593. }
  594. }while (TWRC_SUCCESS == FindNextImportDS(pDSInfo, Context));
  595. CloseFindContext(Context);
  596. }
  597. return twRc;
  598. }