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.

861 lines
23 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 "wizard.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. DWORD CurrentCountryId;
  24. LPTSTR CurrentAreaCode;
  25. #include "modem.c"
  26. LONG
  27. MyLineGetTransCaps(
  28. LPLINETRANSLATECAPS *LineTransCaps
  29. )
  30. {
  31. DWORD LineTransCapsSize;
  32. LONG Rslt = ERROR_SUCCESS;
  33. //
  34. // allocate the initial linetranscaps structure
  35. //
  36. LineTransCapsSize = sizeof(LINETRANSLATECAPS) + 4096;
  37. *LineTransCaps = (LPLINETRANSLATECAPS) MemAlloc( LineTransCapsSize );
  38. if (!*LineTransCaps) {
  39. DebugPrint(( TEXT("MemAlloc() failed, sz=0x%08x"), LineTransCapsSize ));
  40. Rslt = ERROR_NOT_ENOUGH_MEMORY;
  41. goto exit;
  42. }
  43. (*LineTransCaps)->dwTotalSize = LineTransCapsSize;
  44. Rslt = lineGetTranslateCaps(
  45. hLineApp,
  46. TapiApiVersion,
  47. *LineTransCaps
  48. );
  49. if (Rslt != 0) {
  50. DebugPrint(( TEXT("lineGetTranslateCaps() failed, ec=0x%08x"), Rslt ));
  51. goto exit;
  52. }
  53. if ((*LineTransCaps)->dwNeededSize > (*LineTransCaps)->dwTotalSize) {
  54. //
  55. // re-allocate the LineTransCaps structure
  56. //
  57. LineTransCapsSize = (*LineTransCaps)->dwNeededSize;
  58. MemFree( *LineTransCaps );
  59. *LineTransCaps = (LPLINETRANSLATECAPS) MemAlloc( LineTransCapsSize );
  60. if (!*LineTransCaps) {
  61. DebugPrint(( TEXT("MemAlloc() failed, sz=0x%08x"), LineTransCapsSize ));
  62. Rslt = ERROR_NOT_ENOUGH_MEMORY;
  63. goto exit;
  64. }
  65. (*LineTransCaps)->dwTotalSize = LineTransCapsSize;
  66. Rslt = lineGetTranslateCaps(
  67. hLineApp,
  68. TapiApiVersion,
  69. *LineTransCaps
  70. );
  71. if (Rslt != 0) {
  72. DebugPrint(( TEXT("lineGetTranslateCaps() failed, ec=0x%08x"), Rslt ));
  73. goto exit;
  74. }
  75. }
  76. exit:
  77. if (Rslt != ERROR_SUCCESS) {
  78. MemFree( *LineTransCaps );
  79. *LineTransCaps = NULL;
  80. }
  81. return Rslt;
  82. }
  83. BOOL
  84. LookFor351Modems(
  85. VOID
  86. )
  87. {
  88. TCHAR FileName[MAX_PATH*2];
  89. TCHAR Ports[128];
  90. if (!ExpandEnvironmentStrings( TEXT("%windir%\\system32\\ras\\serial.ini"), FileName, sizeof(FileName)/sizeof(TCHAR) )) {
  91. return FALSE;
  92. }
  93. if (!GetPrivateProfileSectionNames( Ports, sizeof(Ports), FileName )) {
  94. return FALSE;
  95. }
  96. return TRUE;
  97. }
  98. DWORD
  99. DeviceInitThread(
  100. HWND hwnd
  101. )
  102. {
  103. DWORD rVal = 0;
  104. LONG Rslt;
  105. LINEINITIALIZEEXPARAMS LineInitializeExParams;
  106. LINEEXTENSIONID lineExtensionID;
  107. DWORD LineDevCapsSize;
  108. LPLINEDEVCAPS LineDevCaps = NULL;
  109. LPTSTR DeviceClassList;
  110. BOOL UnimodemDevice;
  111. DWORD i;
  112. LPLINETRANSLATECAPS LineTransCaps = NULL;
  113. LPLINELOCATIONENTRY LineLocation = NULL;
  114. BOOL FirstTime = TRUE;
  115. BOOL NoClass1 = FALSE;
  116. LPTSTR p;
  117. DWORD Answer;
  118. DWORD LocalTapiApiVersion;
  119. HKEY hKey;
  120. DWORD ValType;
  121. DWORD ValSize;
  122. PMDM_DEVSPEC MdmDevSpec;
  123. LPSTR ModemKey = NULL;
  124. UINT Res;
  125. TCHAR AdaptiveFileName[MAX_PATH*2];
  126. HANDLE AdaptiveFileHandle;
  127. BOOL AdaptiveFileExists = FALSE;
  128. TCHAR Drive[_MAX_DRIVE];
  129. TCHAR Dir[_MAX_DIR];
  130. #define AdaptiveFileMaxSize 20000
  131. BYTE AdaptiveFileBuffer[AdaptiveFileMaxSize]; // temporary needed. Currently < 1K anyway.
  132. DWORD BytesHaveRead;
  133. #define RespKeyMaxSize 1000
  134. BYTE RespKeyName[RespKeyMaxSize];
  135. if (hLineApp) {
  136. return 0;
  137. }
  138. LineInitializeExParams.dwTotalSize = sizeof(LINEINITIALIZEEXPARAMS);
  139. LineInitializeExParams.dwNeededSize = 0;
  140. LineInitializeExParams.dwUsedSize = 0;
  141. LineInitializeExParams.dwOptions = LINEINITIALIZEEXOPTION_USEEVENT;
  142. LineInitializeExParams.Handles.hEvent = NULL;
  143. LineInitializeExParams.dwCompletionKey = 0;
  144. LocalTapiApiVersion = TapiApiVersion = 0x00020000;
  145. if (!Unattended) {
  146. SetDlgItemText(
  147. hwnd,
  148. IDC_DEVICE_PROGRESS_TEXT,
  149. GetString( IDS_INIT_TAPI )
  150. );
  151. }
  152. if (LookFor351Modems()) {
  153. PopUpMsg( hwnd, IDS_351_MODEM, TRUE, 0 );
  154. }
  155. init_again:
  156. Rslt = lineInitializeEx(
  157. &hLineApp,
  158. FaxWizModuleHandle,
  159. NULL,
  160. TEXT("Fax Setup"),
  161. &TapiDevices,
  162. &LocalTapiApiVersion,
  163. &LineInitializeExParams
  164. );
  165. if (Rslt != 0) {
  166. DebugPrint(( TEXT("lineInitializeEx() failed, ec=0x%08x"), Rslt ));
  167. hLineApp = NULL;
  168. goto exit;
  169. }
  170. if (!FirstTime) {
  171. PopUpMsg( hwnd, IDS_NO_TAPI_DEVICES, TRUE, 0 );
  172. ExitProcess(0);
  173. }
  174. if (TapiDevices == 0) {
  175. if (NtGuiMode) {
  176. //
  177. // if running in nt gui mode setup and there
  178. // are no tapi devices then we do nothing,
  179. // but do allow the setup to continue.
  180. //
  181. lineShutdown( hLineApp );
  182. hLineApp = NULL;
  183. return 0;
  184. }
  185. Answer = PopUpMsg( hwnd, IDS_NO_MODEM, FALSE, MB_YESNO );
  186. if (Answer == IDYES) {
  187. if (!CallModemInstallWizard( hwnd )) {
  188. DebugPrint(( TEXT("CallModemInstallWizard() failed, ec=0x%08x"), GetLastError() ));
  189. }
  190. } else {
  191. DebugPrint(( TEXT("No tapi devices, user declined") ));
  192. }
  193. FirstTime = FALSE;
  194. lineShutdown( hLineApp );
  195. hLineApp = NULL;
  196. goto init_again;
  197. }
  198. //
  199. // determine the current location information
  200. //
  201. Rslt = MyLineGetTransCaps( &LineTransCaps );
  202. if (Rslt != ERROR_SUCCESS) {
  203. if (Rslt == LINEERR_INIFILECORRUPT) {
  204. //
  205. // need to set the location information
  206. //
  207. if (!NtGuiMode) {
  208. Rslt = lineTranslateDialog( hLineApp, 0, LocalTapiApiVersion, hwnd, NULL );
  209. if (Rslt == ERROR_SUCCESS) {
  210. Rslt = MyLineGetTransCaps( &LineTransCaps );
  211. }
  212. }
  213. }
  214. if (Rslt != ERROR_SUCCESS) {
  215. DebugPrint(( TEXT("MyLineGetTransCaps() failed, ec=0x%08x"), Rslt ));
  216. goto exit;
  217. }
  218. }
  219. LineLocation = (LPLINELOCATIONENTRY) ((LPBYTE)LineTransCaps + LineTransCaps->dwLocationListOffset);
  220. for (i=0; i<LineTransCaps->dwNumLocations; i++) {
  221. if (LineTransCaps->dwCurrentLocationID == LineLocation[i].dwPermanentLocationID) {
  222. break;
  223. }
  224. }
  225. if (i == LineTransCaps->dwNumLocations) {
  226. DebugPrint(( TEXT("Could not determine the current location information") ));
  227. goto exit;
  228. }
  229. CurrentLocationId = LineTransCaps->dwCurrentLocationID;
  230. CurrentCountryId = LineLocation->dwCountryID;
  231. CurrentAreaCode = StringDup( (LPTSTR) ((LPBYTE)LineTransCaps + LineLocation->dwCityCodeOffset) );
  232. //
  233. // allocate the lineinfo structure
  234. //
  235. TapiEvent = LineInitializeExParams.Handles.hEvent;
  236. LineInfo = (PLINE_INFO) MemAlloc( TapiDevices * sizeof(LINE_INFO) );
  237. if (!LineInfo) {
  238. goto exit;
  239. }
  240. //
  241. // allocate the initial linedevcaps structure
  242. //
  243. LineDevCapsSize = sizeof(LINEDEVCAPS) + 4096;
  244. LineDevCaps = (LPLINEDEVCAPS) MemAlloc( LineDevCapsSize );
  245. if (!LineDevCaps) {
  246. goto exit;
  247. }
  248. if (!Unattended) {
  249. SendMessage( hwnd, WM_MY_PROGRESS, 0xff, TapiDevices * 20 );
  250. }
  251. //
  252. // open FaxAdapt.lst file to decide on enabling RX
  253. // try executable directory first, then- system directory
  254. //
  255. if ( ! GetModuleFileName( FaxWizModuleHandle, AdaptiveFileName, sizeof(AdaptiveFileName) ) ) {
  256. DebugPrint(( TEXT("GetModuleFileName fails , ec=0x%08x "), GetLastError() ));
  257. goto l0;
  258. }
  259. _tsplitpath( AdaptiveFileName, Drive, Dir, NULL, NULL );
  260. _stprintf( AdaptiveFileName, TEXT("%s%s"), Drive, Dir );
  261. if ( _tcslen(AdaptiveFileName) + _tcslen( TEXT("FAXADAPT.LST") ) >= MAX_PATH ) {
  262. DebugPrint(( TEXT("GetCurrentDirectory() too long , MAX_PATH = %d"), MAX_PATH ));
  263. goto l0;
  264. }
  265. _tcscat (AdaptiveFileName, (TEXT ("FAXADAPT.LST")) );
  266. if ( (AdaptiveFileHandle = CreateFile(AdaptiveFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL) )
  267. == INVALID_HANDLE_VALUE ) {
  268. DebugPrint(( TEXT("Could not open adaptive file %s ec=0x%08x"), AdaptiveFileName, GetLastError() ));
  269. goto l0;
  270. }
  271. if (! ReadFile(AdaptiveFileHandle, AdaptiveFileBuffer, AdaptiveFileMaxSize, &BytesHaveRead, NULL ) ) {
  272. DebugPrint(( TEXT("Could not read adaptive file %s ec=0x%08x"), AdaptiveFileName, GetLastError() ));
  273. CloseHandle(AdaptiveFileHandle);
  274. goto l1;
  275. }
  276. if (BytesHaveRead >= AdaptiveFileMaxSize) {
  277. DebugPrint(( TEXT("Adaptive file %s is too big - %d bytes"), AdaptiveFileName, BytesHaveRead ));
  278. CloseHandle(AdaptiveFileHandle);
  279. goto l1;
  280. }
  281. CloseHandle(AdaptiveFileHandle);
  282. AdaptiveFileBuffer[BytesHaveRead] = 0; // need a string
  283. AdaptiveFileExists = TRUE;
  284. goto l1;
  285. //
  286. // only if there is no file in the current directory.
  287. //
  288. l0:
  289. Res = GetSystemDirectory( AdaptiveFileName, MAX_PATH);
  290. if (Res == 0) {
  291. DebugPrint(( TEXT("GetSystemDirectory() failed 0, ec=0x%08x"), GetLastError() ));
  292. goto l1;
  293. }
  294. else if (Res > MAX_PATH) {
  295. DebugPrint(( TEXT("GetSystemDirectory() failed > MAX_PATH = %d"), MAX_PATH ));
  296. goto l1;
  297. }
  298. if (Res + _tcslen( TEXT("\\FAXADAPT.LST") ) >= MAX_PATH ) {
  299. DebugPrint(( TEXT("GetSystemDirectory() too long %d, MAX_PATH = %d"), Res, MAX_PATH ));
  300. goto l1;
  301. }
  302. _tcscat (AdaptiveFileName, (TEXT ("\\FAXADAPT.LST")) );
  303. if ( (AdaptiveFileHandle = CreateFile(AdaptiveFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL) )
  304. == INVALID_HANDLE_VALUE ) {
  305. DebugPrint(( TEXT("Could not open adaptive file %s ec=0x%08x"), AdaptiveFileName, GetLastError() ));
  306. goto l1;
  307. }
  308. if (! ReadFile(AdaptiveFileHandle, AdaptiveFileBuffer, AdaptiveFileMaxSize, &BytesHaveRead, NULL ) ) {
  309. DebugPrint(( TEXT("Could not read adaptive file %s ec=0x%08x"), AdaptiveFileName, GetLastError() ));
  310. CloseHandle(AdaptiveFileHandle);
  311. goto l1;
  312. }
  313. if (BytesHaveRead >= AdaptiveFileMaxSize) {
  314. DebugPrint(( TEXT("Adaptive file %s is too big - %d bytes"), AdaptiveFileName, BytesHaveRead ));
  315. CloseHandle(AdaptiveFileHandle);
  316. goto l1;
  317. }
  318. CloseHandle(AdaptiveFileHandle);
  319. AdaptiveFileBuffer[BytesHaveRead] = 0; // need a string
  320. AdaptiveFileExists = TRUE;
  321. l1:
  322. //
  323. // enumerate all of the tapi devices
  324. //
  325. i = 0;
  326. do {
  327. Rslt = lineNegotiateAPIVersion(
  328. hLineApp,
  329. i,
  330. 0x00010003,
  331. TapiApiVersion,
  332. &LocalTapiApiVersion,
  333. &lineExtensionID
  334. );
  335. if (Rslt != 0) {
  336. DebugPrint(( TEXT("lineNegotiateAPIVersion() failed, ec=0x%08x"), Rslt ));
  337. goto next_device;
  338. }
  339. ZeroMemory( LineDevCaps, LineDevCapsSize );
  340. LineDevCaps->dwTotalSize = LineDevCapsSize;
  341. Rslt = lineGetDevCaps(
  342. hLineApp,
  343. i,
  344. LocalTapiApiVersion,
  345. 0,
  346. LineDevCaps
  347. );
  348. if (Rslt != 0) {
  349. DebugPrint(( TEXT("lineGetDevCaps() failed, ec=0x%08x"), Rslt ));
  350. goto next_device;
  351. }
  352. if (LineDevCaps->dwNeededSize > LineDevCaps->dwTotalSize) {
  353. //
  354. // re-allocate the linedevcaps structure
  355. //
  356. LineDevCapsSize = LineDevCaps->dwNeededSize;
  357. MemFree( LineDevCaps );
  358. LineDevCaps = (LPLINEDEVCAPS) MemAlloc( LineDevCapsSize );
  359. if (!LineDevCaps) {
  360. rVal = ERROR_NOT_ENOUGH_MEMORY;
  361. goto exit;
  362. }
  363. Rslt = lineGetDevCaps(
  364. hLineApp,
  365. i,
  366. TapiApiVersion,
  367. 0,
  368. LineDevCaps
  369. );
  370. if (Rslt != 0) {
  371. DebugPrint(( TEXT("lineGetDevCaps() failed, ec=0x%08x"), Rslt ));
  372. goto next_device;
  373. }
  374. }
  375. if (!Unattended) {
  376. SendMessage( hwnd, WM_MY_PROGRESS, 10, 0 );
  377. }
  378. if (!Unattended) {
  379. SetDlgItemText(
  380. hwnd,
  381. IDC_DEVICE_PROGRESS_TEXT,
  382. (LPTSTR)((LPBYTE) LineDevCaps + LineDevCaps->dwLineNameOffset)
  383. );
  384. }
  385. if (TapiApiVersion != 0x00020000) {
  386. DebugPrint((
  387. TEXT("TAPI device is incompatible with the FAX server: %s"),
  388. (LPTSTR)((LPBYTE) LineDevCaps + LineDevCaps->dwLineNameOffset)
  389. ));
  390. goto next_device;
  391. }
  392. //
  393. // save the line id
  394. //
  395. LineInfo[FaxDevices].PermanentLineID = LineDevCaps->dwPermanentLineID;
  396. LineInfo[FaxDevices].DeviceName = StringDup( (LPTSTR)((LPBYTE) LineDevCaps + LineDevCaps->dwLineNameOffset) );
  397. LineInfo[FaxDevices].ProviderName = StringDup( (LPTSTR)((LPBYTE) LineDevCaps + LineDevCaps->dwProviderInfoOffset) );
  398. LineInfo[FaxDevices].Rings = LineDevCaps->dwLineStates & LINEDEVSTATE_RINGING ? 2 : 0;
  399. LineInfo[FaxDevices].Flags = FPF_RECEIVE | FPF_SEND;
  400. //
  401. // filter out the commas because the spooler hates them
  402. //
  403. p = LineInfo[FaxDevices].DeviceName;
  404. while( p ) {
  405. p = _tcschr( p, TEXT(',') );
  406. if (p) {
  407. *p = TEXT('_');
  408. }
  409. }
  410. //
  411. // check for a modem device
  412. //
  413. UnimodemDevice = FALSE;
  414. if (LineDevCaps->dwDeviceClassesSize && LineDevCaps->dwDeviceClassesOffset) {
  415. DeviceClassList = (LPTSTR)((LPBYTE) LineDevCaps + LineDevCaps->dwDeviceClassesOffset);
  416. while (*DeviceClassList) {
  417. if (_tcscmp(DeviceClassList,TEXT("comm/datamodem")) == 0) {
  418. UnimodemDevice = TRUE;
  419. break;
  420. }
  421. DeviceClassList += (_tcslen(DeviceClassList) + 1);
  422. }
  423. }
  424. if ((!(LineDevCaps->dwBearerModes & LINEBEARERMODE_VOICE)) ||
  425. (!(LineDevCaps->dwBearerModes & LINEBEARERMODE_PASSTHROUGH))) {
  426. //
  427. // unacceptable modem device type
  428. //
  429. UnimodemDevice = FALSE;
  430. }
  431. if (UnimodemDevice) {
  432. LINECALLPARAMS LineCallParams;
  433. HCALL hCall = NULL;
  434. HLINE hLine = NULL;
  435. LINEMESSAGE LineMessage;
  436. DWORD RequestId;
  437. LineInfo[FaxDevices].Flags = FPF_SEND; // Unimodem default
  438. Rslt = lineOpen(
  439. hLineApp,
  440. i,
  441. &hLine,
  442. TapiApiVersion,
  443. 0,
  444. 0,
  445. LINECALLPRIVILEGE_OWNER,
  446. UnimodemDevice ? LINEMEDIAMODE_DATAMODEM : LINEMEDIAMODE_G3FAX,
  447. NULL
  448. );
  449. if (Rslt != 0) {
  450. DebugPrint(( TEXT("lineOpen() failed, ec=0x%08x"), Rslt ));
  451. goto next_device;
  452. }
  453. //
  454. // Get Unimodem key to search Adaptive list.
  455. //
  456. if (! AdaptiveFileExists) {
  457. goto l2;
  458. }
  459. if (! LineDevCaps->dwDevSpecificSize) {
  460. goto l2;
  461. }
  462. MdmDevSpec = (PMDM_DEVSPEC) ((LPBYTE) LineDevCaps + LineDevCaps->dwDevSpecificOffset);
  463. if (MdmDevSpec->Contents == 1 && MdmDevSpec->KeyOffset == 8) {
  464. ModemKey = MdmDevSpec->String;
  465. }
  466. else {
  467. goto l2;
  468. }
  469. if (!ModemKey) {
  470. DebugPrint(( TEXT("Can't get Unimodem key") ));
  471. goto l2;
  472. }
  473. //
  474. // Get ResponsesKeyName
  475. //
  476. Rslt = RegOpenKeyExA(
  477. HKEY_LOCAL_MACHINE,
  478. ModemKey,
  479. 0,
  480. KEY_READ,
  481. &hKey);
  482. if (Rslt != ERROR_SUCCESS) {
  483. DebugPrint(( TEXT("Can't open Unimodem key") ));
  484. goto l2;
  485. }
  486. ValSize = RespKeyMaxSize;
  487. Rslt = RegQueryValueExA(
  488. hKey,
  489. "ResponsesKeyName",
  490. 0,
  491. &ValType,
  492. RespKeyName,
  493. &ValSize);
  494. RegCloseKey(hKey);
  495. if (Rslt != ERROR_SUCCESS) {
  496. DebugPrint(( TEXT("Can't get Unimodem ResponsesKeyName") ));
  497. goto l2;
  498. }
  499. if ( (ValSize >= RespKeyMaxSize) || (ValSize == 0) ) {
  500. DebugPrint(( TEXT("Unimodem ResponsesKeyName key is invalid %d"), RespKeyMaxSize ));
  501. goto l2;
  502. }
  503. if (!RespKeyName) {
  504. DebugPrint(( TEXT("Unimodem ResponsesKeyName key is NULL") ));
  505. goto l2;
  506. }
  507. _strupr(RespKeyName);
  508. //
  509. // check to see if this modem is defined in Adaptive modem list
  510. //
  511. if ( strstr (AdaptiveFileBuffer, RespKeyName) ) {
  512. // enable receive on this device: it is adaptive answer capable.
  513. LineInfo[FaxDevices].Flags = FPF_RECEIVE | FPF_SEND;
  514. }
  515. l2:
  516. ZeroMemory( &LineCallParams, sizeof(LineCallParams) );
  517. LineCallParams.dwTotalSize = sizeof(LINECALLPARAMS);
  518. LineCallParams.dwBearerMode = LINEBEARERMODE_PASSTHROUGH;
  519. hCall = NULL;
  520. Rslt = lineMakeCall( hLine, &hCall, NULL, 0, &LineCallParams );
  521. if (Rslt > 0) {
  522. #define IDVARSTRINGSIZE (sizeof(VARSTRING)+128)
  523. PDEVICEID DeviceID = NULL;
  524. LPVARSTRING LineIdBuffer = MemAlloc( IDVARSTRINGSIZE );
  525. LineIdBuffer->dwTotalSize = IDVARSTRINGSIZE;
  526. RequestId = (DWORD) Rslt;
  527. //
  528. // wait for the call to complete
  529. //
  530. while( TRUE ) {
  531. if (WaitForSingleObject( TapiEvent, 5 * 60 * 1000 ) == WAIT_TIMEOUT) {
  532. DebugPrint(( TEXT("Setup never received a tapi event") ));
  533. rVal = ERROR_INVALID_FUNCTION;
  534. goto exit;
  535. }
  536. Rslt = lineGetMessage( hLineApp, &LineMessage, 0 );
  537. if (Rslt == 0) {
  538. if (LineMessage.dwMessageID == LINE_REPLY && LineMessage.dwParam1 == RequestId) {
  539. switch (LineMessage.dwParam2) {
  540. case 0:
  541. break;
  542. case LINEERR_CALLUNAVAIL:
  543. DebugPrint(( TEXT("lineMakeCall() failed (LINE_REPLY), ec=0x%08x"), LineMessage.dwParam2 ));
  544. goto next_device;
  545. default:
  546. DebugPrint(( TEXT("lineMakeCall() failed (LINE_REPLY), ec=0x%08x"), LineMessage.dwParam2 ));
  547. rVal = LineMessage.dwParam2;
  548. goto exit;
  549. }
  550. break;
  551. }
  552. }
  553. }
  554. //
  555. // get the comm handle
  556. //
  557. Rslt = lineGetID(
  558. hLine,
  559. 0,
  560. hCall,
  561. LINECALLSELECT_CALL,
  562. LineIdBuffer,
  563. TEXT("comm/datamodem")
  564. );
  565. if (Rslt == 0 && LineIdBuffer->dwStringFormat == STRINGFORMAT_BINARY &&
  566. LineIdBuffer->dwUsedSize >= sizeof(DEVICEID)) {
  567. DeviceID = (PDEVICEID) ((LPBYTE)(LineIdBuffer)+LineIdBuffer->dwStringOffset);
  568. if (GetModemClass( DeviceID->hComm ) != 1) {
  569. Rslt = LINEERR_BADDEVICEID;
  570. NoClass1 = TRUE;
  571. DebugPrint(( TEXT("GetModemClass() failed, ec=0x%08x"), Rslt ));
  572. } else {
  573. FaxDevices += 1;
  574. }
  575. CloseHandle( DeviceID->hComm );
  576. } else {
  577. DebugPrint(( TEXT("lineGetID() failed, ec=0x%08x"), Rslt ));
  578. }
  579. MemFree( LineIdBuffer );
  580. } else {
  581. DebugPrint(( TEXT("lineMakeCall() failed, ec=0x%08x"), Rslt ));
  582. }
  583. if (hCall) {
  584. lineDeallocateCall( hCall );
  585. }
  586. if (hLine) {
  587. lineClose( hLine );
  588. }
  589. } else {
  590. if (LineDevCaps->dwMediaModes & LINEMEDIAMODE_G3FAX) {
  591. //
  592. // save the line id
  593. //
  594. FaxDevices += 1;
  595. }
  596. }
  597. next_device:
  598. if (!Unattended) {
  599. SendMessage( hwnd, WM_MY_PROGRESS, 10, 0 );
  600. Sleep( 1000 );
  601. }
  602. i += 1;
  603. } while ( i < TapiDevices );
  604. exit:
  605. MemFree( LineDevCaps );
  606. MemFree( LineTransCaps );
  607. lineShutdown( hLineApp );
  608. if ((rVal != 0) || (FaxDevices == 0)) {
  609. if (NtGuiMode) {
  610. //
  611. // if running in nt gui mode setup and there
  612. // are no tapi devices then we do nothing,
  613. // but do allow the setup to continue.
  614. //
  615. hLineApp = NULL;
  616. return 0;
  617. }
  618. PopUpMsg( hwnd, NoClass1 ? IDS_NO_CLASS1 : IDS_NO_TAPI_DEVICES, TRUE, 0 );
  619. ExitProcess(0);
  620. }
  621. if (!Unattended) {
  622. SetWindowLong( hwnd, DWL_MSGRESULT, 0 );
  623. PropSheet_PressButton( GetParent(hwnd), PSBTN_NEXT );
  624. }
  625. return 0;
  626. }
  627. BOOL
  628. CallModemInstallWizard(
  629. HWND hwnd
  630. )
  631. /* call the Modem.Cpl install wizard to enable the user to install one or more modems
  632. **
  633. ** Return TRUE if the wizard was successfully invoked, FALSE otherwise
  634. **
  635. */
  636. {
  637. HDEVINFO hdi;
  638. BOOL fReturn = FALSE;
  639. // Create a modem DeviceInfoSet
  640. hdi = SetupDiCreateDeviceInfoList((LPGUID)&GUID_DEVCLASS_MODEM, hwnd);
  641. if (hdi)
  642. {
  643. SP_INSTALLWIZARD_DATA iwd;
  644. // Initialize the InstallWizardData
  645. ZeroMemory(&iwd, sizeof(iwd));
  646. iwd.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
  647. iwd.ClassInstallHeader.InstallFunction = DIF_INSTALLWIZARD;
  648. iwd.hwndWizardDlg = hwnd;
  649. // Set the InstallWizardData as the ClassInstallParams
  650. if (SetupDiSetClassInstallParams(hdi, NULL, (PSP_CLASSINSTALL_HEADER)&iwd, sizeof(iwd)))
  651. {
  652. // Call the class installer to invoke the installation
  653. // wizard.
  654. if (SetupDiCallClassInstaller(DIF_INSTALLWIZARD, hdi, NULL))
  655. {
  656. // Success. The wizard was invoked and finished.
  657. // Now cleanup.
  658. fReturn = TRUE;
  659. SetupDiCallClassInstaller(DIF_DESTROYWIZARDDATA, hdi, NULL);
  660. }
  661. }
  662. // Clean up
  663. SetupDiDestroyDeviceInfoList(hdi);
  664. }
  665. return fReturn;
  666. }