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.

351 lines
7.5 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. twain.c
  5. Abstract:
  6. Enumeration routines for TWAIN data sources.
  7. Author:
  8. Jim Schmidt (jimschm) 13-Aug-1998
  9. Revision History:
  10. --*/
  11. #include "pch.h"
  12. #include "cmn9xp.h"
  13. VOID
  14. pSplitDataIntoWords (
  15. IN PCTSTR Data,
  16. OUT PWORD LeftWord,
  17. OUT PWORD RightWord
  18. )
  19. {
  20. INT a, b;
  21. PCTSTR p;
  22. a = _ttoi (Data);
  23. p = _tcschr (Data, TEXT('.'));
  24. if (!p) {
  25. b = 0;
  26. } else {
  27. b = _ttoi (p + 1);
  28. }
  29. *LeftWord = (WORD) a;
  30. *RightWord = (WORD) b;
  31. }
  32. BOOL
  33. pGetDsInfo16 (
  34. IN PCTSTR DsPath,
  35. OUT TW_IDENTITY *Id
  36. )
  37. {
  38. CHAR CmdLine[MAX_CMDLINE];
  39. STARTUPINFO si;
  40. PROCESS_INFORMATION pi;
  41. BOOL ProcessResult;
  42. DWORD rc;
  43. PSTR Data;
  44. Data = CmdLine;
  45. //
  46. // Launch TWID.EXE
  47. //
  48. wsprintf (CmdLine, TEXT("\"%s\\TWID.EXE\" %s"), g_UpgradeSources, DsPath);
  49. ZeroMemory (&si, sizeof (si));
  50. si.cb = sizeof (si);
  51. si.dwFlags = STARTF_FORCEOFFFEEDBACK;
  52. ProcessResult = CreateProcessA (
  53. NULL,
  54. CmdLine,
  55. NULL,
  56. NULL,
  57. FALSE,
  58. CREATE_DEFAULT_ERROR_MODE,
  59. NULL,
  60. g_WinDir,
  61. &si,
  62. &pi
  63. );
  64. if (ProcessResult) {
  65. CloseHandle (pi.hThread);
  66. } else {
  67. LOG ((LOG_ERROR, "Cannot start %s", CmdLine));
  68. return FALSE;
  69. }
  70. rc = WaitForSingleObject (pi.hProcess, 10000);
  71. if (rc != WAIT_OBJECT_0) {
  72. TerminateProcess (pi.hProcess, 0);
  73. }
  74. CloseHandle (pi.hProcess);
  75. //
  76. // If process terminated, look for win.ini section
  77. //
  78. if (rc == WAIT_OBJECT_0) {
  79. ZeroMemory (Id, sizeof (TW_IDENTITY));
  80. GetProfileString (
  81. TEXT("$TWAINDSINFO$"),
  82. TEXT("Version"),
  83. TEXT("1.0"),
  84. Data,
  85. 32
  86. );
  87. pSplitDataIntoWords (Data, &Id->Version.MajorNum, &Id->Version.MinorNum);
  88. GetProfileString (
  89. TEXT("$TWAINDSINFO$"),
  90. TEXT("Locale"),
  91. TEXT(""),
  92. Data,
  93. 32
  94. );
  95. pSplitDataIntoWords (Data, &Id->Version.Language, &Id->Version.Country);
  96. GetProfileString (
  97. TEXT("$TWAINDSINFO$"),
  98. TEXT("VersionInfo"),
  99. TEXT(""),
  100. Id->Version.Info,
  101. sizeof (Id->Version.Info)
  102. );
  103. GetProfileString (
  104. TEXT("$TWAINDSINFO$"),
  105. TEXT("Mfg"),
  106. TEXT(""),
  107. Id->Manufacturer,
  108. sizeof (Id->Manufacturer)
  109. );
  110. GetProfileString (
  111. TEXT("$TWAINDSINFO$"),
  112. TEXT("Family"),
  113. TEXT(""),
  114. Id->ProductFamily,
  115. sizeof (Id->ProductFamily)
  116. );
  117. GetProfileString (
  118. TEXT("$TWAINDSINFO$"),
  119. TEXT("Name"),
  120. TEXT(""),
  121. Id->ProductName,
  122. sizeof (Id->ProductName)
  123. );
  124. //
  125. // Delete the INI data
  126. //
  127. WriteProfileString (
  128. TEXT("$TWAINDSINFO$"),
  129. NULL,
  130. NULL
  131. );
  132. return *(Id->ProductName) != 0;
  133. }
  134. return FALSE;
  135. }
  136. DWORD g_OrgEsp;
  137. DWORD g_OrgEbp;
  138. #if _MSC_FULL_VER >= 13008827 && defined(_M_IX86)
  139. #pragma warning(push)
  140. #pragma warning(disable:4731) // EBP modified with inline asm
  141. #endif
  142. BOOL
  143. pGetDsInfo32 (
  144. IN PCTSTR DsPath,
  145. OUT TW_IDENTITY *Id
  146. )
  147. {
  148. HINSTANCE DsLib = NULL;
  149. DSENTRYPROC DsEntry;
  150. TW_UINT16 TwainRc;
  151. __try {
  152. //
  153. // Open the DS as a 32-bit library
  154. //
  155. DsLib = LoadLibrary (DsPath);
  156. if (!DsLib) {
  157. return FALSE;
  158. }
  159. //
  160. // Get the DS entry point
  161. //
  162. DsEntry = (DSENTRYPROC) GetProcAddress (DsLib, "DS_Entry");
  163. if (!DsEntry) {
  164. FreeLibrary (DsLib);
  165. return FALSE;
  166. }
  167. //
  168. // Get the TW_IDENTITY struct, and preserve the stack for poorly
  169. // written DSes.
  170. //
  171. __asm {
  172. mov eax, esp
  173. mov [g_OrgEsp], eax
  174. mov [g_OrgEbp], ebp
  175. }
  176. TwainRc = DsEntry (NULL, DG_CONTROL, DAT_IDENTITY, MSG_GET, Id);
  177. __asm {
  178. mov eax, [g_OrgEsp]
  179. mov esp, eax
  180. mov ebp, [g_OrgEbp]
  181. }
  182. }
  183. __except (TRUE) {
  184. TwainRc = ERROR_NOACCESS;
  185. }
  186. if (DsLib) {
  187. FreeLibrary (DsLib);
  188. }
  189. return TwainRc == ERROR_SUCCESS;
  190. }
  191. #if _MSC_FULL_VER >= 13008827
  192. #pragma warning(pop)
  193. #endif
  194. BOOL
  195. EnumFirstTwainDataSource (
  196. OUT PTWAINDATASOURCE_ENUM EnumPtr
  197. )
  198. {
  199. ZeroMemory (EnumPtr, sizeof (EnumPtr));
  200. EnumPtr->State = TE_INIT;
  201. return EnumNextTwainDataSource (EnumPtr);
  202. }
  203. BOOL
  204. EnumNextTwainDataSource (
  205. IN OUT PTWAINDATASOURCE_ENUM EnumPtr
  206. )
  207. {
  208. TCHAR Path[MAX_TCHAR_PATH];
  209. TW_IDENTITY Id;
  210. while (EnumPtr->State != TE_DONE) {
  211. switch (EnumPtr->State) {
  212. case TE_INIT:
  213. EnumPtr->State = TE_BEGIN_ENUM;
  214. EnumPtr->Dir = TEXT("TWAIN\0TWAIN_32\0TWAIN32\0");
  215. break;
  216. case TE_BEGIN_ENUM:
  217. wsprintf (Path, TEXT("%s\\%s"), g_WinDir, EnumPtr->Dir);
  218. if (!EnumFirstFileInTree (&EnumPtr->Enum, Path, TEXT("*.DS"), TRUE)) {
  219. EnumPtr->State = TE_END_ENUM;
  220. } else {
  221. EnumPtr->State = TE_EVALUATE;
  222. }
  223. break;
  224. case TE_EVALUATE:
  225. if (EnumPtr->Enum.Directory) {
  226. EnumPtr->State = TE_NEXT;
  227. } else if (pGetDsInfo16 (EnumPtr->Enum.FullPath, &Id)) {
  228. EnumPtr->State = TE_RETURN;
  229. } else if (pGetDsInfo32 (EnumPtr->Enum.FullPath, &Id)) {
  230. EnumPtr->State = TE_RETURN;
  231. } else {
  232. EnumPtr->State = TE_NEXT;
  233. }
  234. break;
  235. case TE_RETURN:
  236. EnumPtr->State = TE_NEXT;
  237. __try {
  238. StackStringCopy (EnumPtr->Manufacturer, Id.Manufacturer);
  239. StackStringCopy (EnumPtr->ProductFamily, Id.ProductFamily);
  240. StackStringCopy (EnumPtr->DisplayName, Id.ProductName);
  241. StackStringCopy (EnumPtr->DataSourceModule, EnumPtr->Enum.FullPath);
  242. }
  243. __except (TRUE) {
  244. break;
  245. }
  246. return TRUE;
  247. case TE_NEXT:
  248. if (!EnumNextFileInTree (&EnumPtr->Enum)) {
  249. EnumPtr->State = TE_END_ENUM;
  250. } else {
  251. EnumPtr->State = TE_EVALUATE;
  252. }
  253. break;
  254. case TE_END_ENUM:
  255. EnumPtr->Dir = GetEndOfString (EnumPtr->Dir) + 1;
  256. if (*EnumPtr->Dir) {
  257. EnumPtr->State = TE_BEGIN_ENUM;
  258. } else {
  259. EnumPtr->State = TE_DONE;
  260. }
  261. break;
  262. }
  263. }
  264. return FALSE;
  265. }
  266. VOID
  267. AbortTwainDataSourceEnum (
  268. IN OUT PTWAINDATASOURCE_ENUM EnumPtr
  269. )
  270. {
  271. if (EnumPtr->State != TE_DONE) {
  272. AbortEnumFileInTree (&EnumPtr->Enum);
  273. EnumPtr->State = TE_DONE;
  274. }
  275. }