Source code of Windows XP (NT5)
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.

444 lines
11 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. tapi.c
  5. Abstract:
  6. This file provides all access to tapi.
  7. Environment:
  8. WIN32 User Mode
  9. Author:
  10. Wesley Witt (wesw) 17-Feb-1996
  11. --*/
  12. #include "faxocm.h"
  13. #pragma hdrstop
  14. #include <initguid.h>
  15. #include <devguid.h>
  16. DWORD TapiApiVersion;
  17. HLINEAPP hLineApp;
  18. HANDLE TapiEvent;
  19. DWORD TapiDevices;
  20. DWORD FaxDevices;
  21. PLINE_INFO LineInfo;
  22. DWORD CurrentLocationId;
  23. LPVOID AdaptiveModems;
  24. #include "modem.c"
  25. LONG
  26. MyLineGetTransCaps(
  27. LPLINETRANSLATECAPS *LineTransCaps
  28. )
  29. {
  30. DWORD LineTransCapsSize;
  31. LONG Rslt = ERROR_SUCCESS;
  32. //
  33. // allocate the initial linetranscaps structure
  34. //
  35. LineTransCapsSize = sizeof(LINETRANSLATECAPS) + 4096;
  36. *LineTransCaps = (LPLINETRANSLATECAPS) MemAlloc( LineTransCapsSize );
  37. if (!*LineTransCaps) {
  38. DebugPrint(( L"MemAlloc() failed, sz=0x%08x", LineTransCapsSize ));
  39. Rslt = ERROR_NOT_ENOUGH_MEMORY;
  40. goto exit;
  41. }
  42. (*LineTransCaps)->dwTotalSize = LineTransCapsSize;
  43. Rslt = lineGetTranslateCaps(
  44. hLineApp,
  45. TapiApiVersion,
  46. *LineTransCaps
  47. );
  48. if (Rslt != 0) {
  49. DebugPrint(( L"lineGetTranslateCaps() failed, ec=0x%08x", Rslt ));
  50. goto exit;
  51. }
  52. if ((*LineTransCaps)->dwNeededSize > (*LineTransCaps)->dwTotalSize) {
  53. //
  54. // re-allocate the LineTransCaps structure
  55. //
  56. LineTransCapsSize = (*LineTransCaps)->dwNeededSize;
  57. MemFree( *LineTransCaps );
  58. *LineTransCaps = (LPLINETRANSLATECAPS) MemAlloc( LineTransCapsSize );
  59. if (!*LineTransCaps) {
  60. DebugPrint(( L"MemAlloc() failed, sz=0x%08x", LineTransCapsSize ));
  61. Rslt = ERROR_NOT_ENOUGH_MEMORY;
  62. goto exit;
  63. }
  64. (*LineTransCaps)->dwTotalSize = LineTransCapsSize;
  65. Rslt = lineGetTranslateCaps(
  66. hLineApp,
  67. TapiApiVersion,
  68. *LineTransCaps
  69. );
  70. if (Rslt != 0) {
  71. DebugPrint(( L"lineGetTranslateCaps() failed, ec=0x%08x", Rslt ));
  72. goto exit;
  73. }
  74. }
  75. exit:
  76. if (Rslt != ERROR_SUCCESS) {
  77. MemFree( *LineTransCaps );
  78. *LineTransCaps = NULL;
  79. }
  80. return Rslt;
  81. }
  82. BOOL
  83. ValidateModem(
  84. PLINE_INFO LineInfo,
  85. LPLINEDEVCAPS LineDevCaps
  86. )
  87. {
  88. PMDM_DEVSPEC MdmDevSpec;
  89. LPWSTR ModemKey;
  90. LPWSTR RespKeyName;
  91. HKEY hKey;
  92. if (LineDevCaps->dwDevSpecificSize == 0) {
  93. return FALSE;
  94. }
  95. MdmDevSpec = (PMDM_DEVSPEC) ((LPBYTE) LineDevCaps + LineDevCaps->dwDevSpecificOffset);
  96. if (MdmDevSpec->Contents != 1 || MdmDevSpec->KeyOffset != 8 && MdmDevSpec->String == NULL) {
  97. return FALSE;
  98. }
  99. ModemKey = AnsiStringToUnicodeString( (LPSTR) MdmDevSpec->String );
  100. if (!ModemKey) {
  101. return FALSE;
  102. }
  103. LineInfo->Flags = FPF_SEND;
  104. hKey = OpenRegistryKey( HKEY_LOCAL_MACHINE, ModemKey, FALSE, KEY_READ );
  105. if (hKey) {
  106. RespKeyName = GetRegistryString( hKey, L"ResponsesKeyName", EMPTY_STRING );
  107. if (RespKeyName) {
  108. if (IsModemAdaptiveAnswer( AdaptiveModems, RespKeyName )) {
  109. LineInfo->Flags |= FPF_RECEIVE;
  110. }
  111. MemFree( RespKeyName );
  112. }
  113. RegCloseKey( hKey );
  114. }
  115. MemFree( ModemKey );
  116. return TRUE;
  117. }
  118. DWORD
  119. DeviceInitialization(
  120. HWND hwnd
  121. )
  122. {
  123. DWORD rVal = 0;
  124. LONG Rslt;
  125. LINEINITIALIZEEXPARAMS LineInitializeExParams;
  126. LINEEXTENSIONID lineExtensionID;
  127. DWORD LineDevCapsSize;
  128. LPLINEDEVCAPS LineDevCaps = NULL;
  129. LPWSTR DeviceClassList;
  130. BOOL UnimodemDevice;
  131. DWORD i;
  132. LPLINETRANSLATECAPS LineTransCaps = NULL;
  133. LPLINELOCATIONENTRY LineLocation = NULL;
  134. BOOL NoClass1 = FALSE;
  135. LPWSTR p;
  136. DWORD LocalTapiApiVersion;
  137. LPSTR ModemKey = NULL;
  138. DebugPrint(( TEXT("faxocm DeviceInitialization") ));
  139. //
  140. // initialize the adaptive answer data
  141. //
  142. AdaptiveModems = InitializeAdaptiveAnswerList( SetupInitComponent.ComponentInfHandle );
  143. //
  144. // initialize tapi
  145. //
  146. LineInitializeExParams.dwTotalSize = sizeof(LINEINITIALIZEEXPARAMS);
  147. LineInitializeExParams.dwNeededSize = 0;
  148. LineInitializeExParams.dwUsedSize = 0;
  149. LineInitializeExParams.dwOptions = LINEINITIALIZEEXOPTION_USEEVENT;
  150. LineInitializeExParams.Handles.hEvent = NULL;
  151. LineInitializeExParams.dwCompletionKey = 0;
  152. LocalTapiApiVersion = TapiApiVersion = 0x00020000;
  153. Rslt = lineInitializeEx(
  154. &hLineApp,
  155. hInstance,
  156. NULL,
  157. L"Fax Setup",
  158. &TapiDevices,
  159. &LocalTapiApiVersion,
  160. &LineInitializeExParams
  161. );
  162. if (Rslt != 0) {
  163. DebugPrint(( L"lineInitializeEx() failed, ec=0x%08x", Rslt ));
  164. hLineApp = NULL;
  165. goto exit;
  166. }
  167. if (TapiDevices == 0) {
  168. goto exit;
  169. }
  170. //
  171. // allocate the lineinfo structure
  172. //
  173. TapiEvent = LineInitializeExParams.Handles.hEvent;
  174. LineInfo = (PLINE_INFO) MemAlloc( TapiDevices * sizeof(LINE_INFO) );
  175. if (!LineInfo) {
  176. goto exit;
  177. }
  178. //
  179. // allocate the initial linedevcaps structure
  180. //
  181. LineDevCapsSize = sizeof(LINEDEVCAPS) + 4096;
  182. LineDevCaps = (LPLINEDEVCAPS) MemAlloc( LineDevCapsSize );
  183. if (!LineDevCaps) {
  184. goto exit;
  185. }
  186. //
  187. // enumerate all of the tapi devices
  188. //
  189. i = 0;
  190. do {
  191. Rslt = lineNegotiateAPIVersion(
  192. hLineApp,
  193. i,
  194. 0x00010003,
  195. TapiApiVersion,
  196. &LocalTapiApiVersion,
  197. &lineExtensionID
  198. );
  199. if (Rslt != 0) {
  200. DebugPrint(( L"lineNegotiateAPIVersion() failed, ec=0x%08x", Rslt ));
  201. goto next_device;
  202. }
  203. ZeroMemory( LineDevCaps, LineDevCapsSize );
  204. LineDevCaps->dwTotalSize = LineDevCapsSize;
  205. Rslt = lineGetDevCaps(
  206. hLineApp,
  207. i,
  208. LocalTapiApiVersion,
  209. 0,
  210. LineDevCaps
  211. );
  212. if (Rslt != 0) {
  213. DebugPrint(( L"lineGetDevCaps() failed, ec=0x%08x", Rslt ));
  214. goto next_device;
  215. }
  216. if (LineDevCaps->dwNeededSize > LineDevCaps->dwTotalSize) {
  217. //
  218. // re-allocate the linedevcaps structure
  219. //
  220. LineDevCapsSize = LineDevCaps->dwNeededSize;
  221. MemFree( LineDevCaps );
  222. LineDevCaps = (LPLINEDEVCAPS) MemAlloc( LineDevCapsSize );
  223. if (!LineDevCaps) {
  224. rVal = ERROR_NOT_ENOUGH_MEMORY;
  225. goto exit;
  226. }
  227. Rslt = lineGetDevCaps(
  228. hLineApp,
  229. i,
  230. TapiApiVersion,
  231. 0,
  232. LineDevCaps
  233. );
  234. if (Rslt != 0) {
  235. DebugPrint(( L"lineGetDevCaps() failed, ec=0x%08x", Rslt ));
  236. goto next_device;
  237. }
  238. }
  239. if (TapiApiVersion != 0x00020000) {
  240. DebugPrint((
  241. L"TAPI device is incompatible with the FAX server: %s",
  242. (LPWSTR)((LPBYTE) LineDevCaps + LineDevCaps->dwLineNameOffset)
  243. ));
  244. goto next_device;
  245. }
  246. //
  247. // save the line id
  248. //
  249. LineInfo[FaxDevices].PermanentLineID = LineDevCaps->dwPermanentLineID;
  250. LineInfo[FaxDevices].DeviceName = StringDup( (LPWSTR)((LPBYTE) LineDevCaps + LineDevCaps->dwLineNameOffset) );
  251. LineInfo[FaxDevices].ProviderName = StringDup( (LPWSTR)((LPBYTE) LineDevCaps + LineDevCaps->dwProviderInfoOffset) );
  252. LineInfo[FaxDevices].Rings = (LineDevCaps->dwLineStates & LINEDEVSTATE_RINGING) ? WizData.Rings : 0;
  253. LineInfo[FaxDevices].Flags = FPF_RECEIVE | FPF_SEND;
  254. //
  255. // filter out the commas because the spooler hates them
  256. //
  257. p = LineInfo[FaxDevices].DeviceName;
  258. while( p ) {
  259. p = wcschr( p, L',' );
  260. if (p) {
  261. *p = L'_';
  262. }
  263. }
  264. //
  265. // check for a modem device
  266. //
  267. UnimodemDevice = FALSE;
  268. if (LineDevCaps->dwDeviceClassesSize && LineDevCaps->dwDeviceClassesOffset) {
  269. DeviceClassList = (LPWSTR)((LPBYTE) LineDevCaps + LineDevCaps->dwDeviceClassesOffset);
  270. while (*DeviceClassList) {
  271. if (wcscmp(DeviceClassList,L"comm/datamodem") == 0) {
  272. UnimodemDevice = TRUE;
  273. break;
  274. }
  275. DeviceClassList += (wcslen(DeviceClassList) + 1);
  276. }
  277. }
  278. if ((!(LineDevCaps->dwBearerModes & LINEBEARERMODE_VOICE)) ||
  279. (!(LineDevCaps->dwBearerModes & LINEBEARERMODE_PASSTHROUGH))) {
  280. //
  281. // unacceptable modem device type
  282. //
  283. UnimodemDevice = FALSE;
  284. }
  285. if (UnimodemDevice) {
  286. if (ValidateModem( &LineInfo[FaxDevices], LineDevCaps )) {
  287. FaxDevices += 1;
  288. }
  289. } else {
  290. if (LineDevCaps->dwMediaModes & LINEMEDIAMODE_G3FAX) {
  291. FaxDevices += 1;
  292. }
  293. }
  294. next_device:
  295. i += 1;
  296. } while ( i < TapiDevices );
  297. if (FaxDevices == 0) {
  298. goto exit;
  299. }
  300. //
  301. // determine the current location information
  302. //
  303. Rslt = MyLineGetTransCaps( &LineTransCaps );
  304. if (Rslt != ERROR_SUCCESS) {
  305. if (Rslt == LINEERR_INIFILECORRUPT) {
  306. //
  307. // need to set the location information
  308. //
  309. if (!NtGuiMode) {
  310. Rslt = lineTranslateDialog( hLineApp, 0, LocalTapiApiVersion, hwnd, NULL );
  311. if (Rslt == ERROR_SUCCESS) {
  312. Rslt = MyLineGetTransCaps( &LineTransCaps );
  313. }
  314. }
  315. }
  316. if (Rslt != ERROR_SUCCESS) {
  317. DebugPrint(( L"MyLineGetTransCaps() failed, ec=0x%08x", Rslt ));
  318. goto exit;
  319. }
  320. }
  321. LineLocation = (LPLINELOCATIONENTRY) ((LPBYTE)LineTransCaps + LineTransCaps->dwLocationListOffset);
  322. for (i=0; i<LineTransCaps->dwNumLocations; i++) {
  323. if (LineTransCaps->dwCurrentLocationID == LineLocation[i].dwPermanentLocationID) {
  324. break;
  325. }
  326. }
  327. if (i == LineTransCaps->dwNumLocations) {
  328. DebugPrint(( L"Could not determine the current location information" ));
  329. goto exit;
  330. }
  331. CurrentLocationId = LineTransCaps->dwCurrentLocationID;
  332. CurrentCountryId = LineLocation->dwCountryID;
  333. CurrentAreaCode = StringDup( (LPWSTR) ((LPBYTE)LineTransCaps + LineLocation->dwCityCodeOffset) );
  334. exit:
  335. MemFree( LineDevCaps );
  336. MemFree( LineTransCaps );
  337. if (hLineApp) {
  338. lineShutdown( hLineApp );
  339. hLineApp = NULL;
  340. }
  341. DebugPrint(( TEXT("faxocm - found %d fax devices"), FaxDevices ));
  342. return 0;
  343. }