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.

1329 lines
36 KiB

  1. //****************************************************************************
  2. //
  3. // Terminal Server CDmodem
  4. //
  5. //
  6. // Copyright 1996, Citrix Systems Inc.
  7. // Copyright (C) 1994-95 Microsft Corporation. All rights reserved.
  8. //
  9. // Filename: init.c
  10. //
  11. // Revision History
  12. //
  13. // Nov 1998 updated by Qunbiao Guo for terminal server
  14. // Mar 28 1992 Gurdeep Singh Pall Created for RASMAN
  15. //
  16. // Description: This file contains init code for cdmodem
  17. //
  18. //****************************************************************************
  19. #include <nt.h>
  20. #include <ntrtl.h>
  21. #include <nturtl.h>
  22. #include <windows.h>
  23. #include <tapi.h>
  24. #include <rasndis.h>
  25. #include <wanioctl.h>
  26. #include <rasman.h>
  27. #include <raserror.h>
  28. #include <eventlog.h>
  29. #include <media.h>
  30. #include <device.h>
  31. #include <rasmxs.h>
  32. #include <isdn.h>
  33. #include <stdlib.h>
  34. #include <malloc.h>
  35. #include <string.h>
  36. #include "rastapi.h"
  37. #ifdef CITRIX
  38. #include <winstaw.h>
  39. #include <icadd.h>
  40. #include <icaapi.h>
  41. #include "cdmodem.h"
  42. #endif // CITRIX
  43. #ifdef CITRIX
  44. #ifdef DBG
  45. #define DBGPRINT(_arg) DbgPrint _arg
  46. #else
  47. #define DBGPRINT(_arg) { }
  48. #endif
  49. #endif // CITRIX
  50. #pragma warning (error:4312)
  51. HLINEAPP RasLine = 0 ;
  52. HINSTANCE RasInstance = 0 ;
  53. TapiLineInfo *RasTapiLineInfo ;
  54. DWORD TotalLines = 0 ;
  55. DWORD TotalPorts ;
  56. TapiPortControlBlock *RasPorts ;
  57. TapiPortControlBlock *RasPortsEnd ;
  58. //DWORD NegotiatedApiVersion ;
  59. //DWORD NegotiatedExtVersion ;
  60. HANDLE RasTapiMutex ;
  61. BOOL Initialized = FALSE ;
  62. DWORD TapiThreadId ;
  63. HANDLE TapiThreadHandle;
  64. DWORD LoaderThreadId;
  65. DWORD ValidPorts = 0;
  66. DWORD NumberOfRings = 1 ;
  67. HANDLE ghAsyMac = INVALID_HANDLE_VALUE ;
  68. //DWORD EnumerateTapiPorts () ;
  69. BOOL ReadUsageInfoFromRegistry() ;
  70. TapiLineInfo *FindLineByHandle (HLINE) ;
  71. TapiPortControlBlock *FindPortByRequestId (DWORD) ;
  72. TapiPortControlBlock *FindPortByAddressId (TapiLineInfo *, DWORD) ;
  73. TapiPortControlBlock *FindPortByAddress (CHAR *) ;
  74. DWORD InitiatePortDisconnection (TapiPortControlBlock *hIOPort) ;
  75. TapiPortControlBlock *FindPortByAddressAndName (CHAR *address, CHAR *name) ;
  76. //* InitTapi()
  77. //
  78. //
  79. //*
  80. BOOL
  81. InitRasTapi (HANDLE hInst, DWORD ul_reason_being_called, LPVOID lpReserved)
  82. {
  83. STARTUPINFO startupinfo ;
  84. DWORD dwErr;
  85. static BOOLEAN DllInitialized = FALSE ;
  86. DBGPRINT(( "CDMODEM: InitRasTapi: hInst 0x%x, reason 0x%x\n",
  87. hInst, ul_reason_being_called ));
  88. switch (ul_reason_being_called) {
  89. case DLL_PROCESS_ATTACH:
  90. if (RasPorts != 0)
  91. return 1 ;
  92. RasInstance = hInst ;
  93. ReadUsageInfoFromRegistry();
  94. if ((RasTapiMutex = CreateMutex (NULL, FALSE, NULL)) == NULL)
  95. return 0 ;
  96. DllInitialized = TRUE ;
  97. break ;
  98. case DLL_PROCESS_DETACH:
  99. //
  100. // If DLL did not successfully initialize for this process dont try to clean up
  101. //
  102. if (!DllInitialized)
  103. break ;
  104. lineShutdown (RasLine) ;
  105. PostThreadMessage (TapiThreadId, WM_QUIT, 0, 0) ;
  106. break ;
  107. case DLL_THREAD_ATTACH:
  108. break;
  109. case DLL_THREAD_DETACH:
  110. #ifndef CITRIX
  111. //
  112. // If the thread that has created the TAPI
  113. // message queue thread via EnumerateTapiPorts
  114. // is exiting, also clean up the TAPI message
  115. // queue thread at this time.
  116. //
  117. // NOTE: We cannot do an explicit WaitForSingleObject()
  118. // on the TAPI message queue thread because we are
  119. // in a DLL init proc. This would cause a deadlock,
  120. // since the exiting thread has to execute this DLL
  121. // init proc before exiting. The TAPI message queue
  122. // thread actually takes care of the final DLL unload.
  123. // See EnumerateTapiPorts below.
  124. //
  125. if (GetCurrentThreadId() == LoaderThreadId)
  126. PostThreadMessage (TapiThreadId, WM_QUIT, 0, 0) ;
  127. #endif // CITRIX
  128. break;
  129. }
  130. return 1 ;
  131. }
  132. //* EnumerateTapiPorts()
  133. //
  134. // Function: First we call line initialize and construct a TLI for each line
  135. // Then for each line we enumerate addresses and go through each address
  136. // If the address is configured to be used with RAS we fill in the
  137. // approp. info into the TPCB for the address (now port).
  138. //
  139. // Return: GetLastError(), SUCCESS
  140. //
  141. //*
  142. DWORD
  143. EnumerateTapiPorts (HANDLE event)
  144. {
  145. WORD i, k ;
  146. TapiLineInfo *nextline ;
  147. DWORD lines = 0 ;
  148. BYTE buffer[800] ;
  149. LINEADDRESSCAPS *lineaddrcaps ;
  150. LINEDEVCAPS *linedevcaps ;
  151. CHAR address[40] ;
  152. CHAR devicetype[MAX_DEVICETYPE_NAME] = {0};
  153. DWORD devicetypelength;
  154. CHAR devicename[MAX_DEVICE_NAME] = {0};
  155. DWORD devicenamelength;
  156. CHAR szregkey[128];
  157. LINEEXTENSIONID extensionid ;
  158. DWORD totaladdresses ;
  159. #ifndef CITRIX
  160. TapiPortControlBlock *nextport ;
  161. #else // CITRIX
  162. DWORD addresses ;
  163. TapiPortControlBlock *nextport = NULL, *port ;
  164. #endif // CITRIX
  165. MSG msg ;
  166. HINSTANCE hInst;
  167. TapiPortControlBlock *pports ;
  168. LINEINITIALIZEEXPARAMS param ;
  169. DWORD version = HIGH_VERSION ;
  170. memset (&param, 0, sizeof (LINEINITIALIZEEXPARAMS)) ;
  171. param.dwOptions = LINEINITIALIZEEXOPTION_USEHIDDENWINDOW ;
  172. param.dwTotalSize = sizeof(param) ;
  173. #ifdef CITRIX
  174. DBGPRINT(( "CDMODEM: EnumerateTapiPorts: Entry\n" ));
  175. #endif // CITRIX
  176. if (lineInitializeEx (&RasLine,
  177. RasInstance,
  178. (LINECALLBACK) RasTapiCallback,
  179. REMOTEACCESS_APP,
  180. &lines,
  181. &version,
  182. &param) )
  183. goto error ;
  184. if (lines == 0) {
  185. goto error;
  186. }
  187. nextline = RasTapiLineInfo = LocalAlloc (LPTR, sizeof (TapiLineInfo) * lines) ;
  188. if (nextline == NULL)
  189. goto error ;
  190. TotalLines = lines ;
  191. #ifdef CITRIX
  192. totaladdresses = 0;
  193. #endif // CITRIX
  194. for (i=0; i<lines; i++) { // for all lines get the addresses -> ports
  195. if (lineNegotiateAPIVersion(RasLine,
  196. i,
  197. LOW_VERSION,
  198. HIGH_VERSION,
  199. &nextline->NegotiatedApiVersion,
  200. &extensionid) ) {
  201. #ifdef CITRIX
  202. totaladdresses++;
  203. #endif // CITRIX
  204. nextline->TLI_LineState = PS_UNINITIALIZED ;
  205. nextline++ ;
  206. continue ;
  207. }
  208. if (lineNegotiateExtVersion(RasLine,
  209. i,
  210. nextline->NegotiatedApiVersion,
  211. LOW_EXT_VERSION,
  212. HIGH_EXT_VERSION,
  213. &nextline->NegotiatedExtVersion)) {
  214. nextline->NegotiatedExtVersion = 0;
  215. }
  216. memset (buffer, 0, sizeof(buffer)) ;
  217. linedevcaps = (LINEDEVCAPS *)buffer ;
  218. linedevcaps->dwTotalSize = sizeof (buffer) ;
  219. // Get a count of all addresses across all lines
  220. //
  221. if (lineGetDevCaps (RasLine,
  222. i,
  223. nextline->NegotiatedApiVersion,
  224. nextline->NegotiatedExtVersion,
  225. linedevcaps)) {
  226. #ifdef CITRIX
  227. totaladdresses += linedevcaps->dwNumAddresses;
  228. #endif // CITRIX
  229. nextline->TLI_LineState = PS_UNINITIALIZED ;
  230. nextline++ ;
  231. continue ;
  232. }
  233. #ifdef CITRIX
  234. totaladdresses++;
  235. #endif // CITRIX
  236. nextline->TLI_LineId = i ; // fill TLI struct. id.
  237. nextline->TLI_LineState = PS_CLOSED ;
  238. nextline++ ;
  239. }
  240. #ifdef CITRIX
  241. DBGPRINT(( "CDMODEM: ETP: totaladdresses %d\n", totaladdresses));
  242. #endif // CITRIX
  243. // Now that we know the number of lines and number of addresses per line
  244. // we now fillin the TPCB structure per address
  245. //
  246. for (i=0, nextline = RasTapiLineInfo; i<TotalLines ; i++, nextline++) {
  247. BOOL fModem = FALSE ;
  248. if (RasTapiLineInfo[i].TLI_LineState == PS_UNINITIALIZED)
  249. continue ;
  250. memset (buffer, 0, sizeof(buffer)) ;
  251. linedevcaps = (LINEDEVCAPS *)buffer ;
  252. linedevcaps->dwTotalSize = sizeof(buffer) ;
  253. // Get a count of all addresses across all lines
  254. //
  255. if (lineGetDevCaps (RasLine,
  256. i,
  257. nextline->NegotiatedApiVersion,
  258. nextline->NegotiatedExtVersion,
  259. linedevcaps))
  260. goto error ;
  261. // Figure out if this is a unimodem device or not
  262. //
  263. if (nextline->NegotiatedApiVersion == HIGH_VERSION) {
  264. // first convert all nulls in the device class string to non nulls.
  265. //
  266. DWORD j ;
  267. char *temp ;
  268. for (j=0, temp = (CHAR *)linedevcaps+linedevcaps->dwDeviceClassesOffset;
  269. j<linedevcaps->dwDeviceClassesSize;
  270. j++, temp++)
  271. if (*temp == '\0')
  272. *temp = ' ' ;
  273. #ifdef CITRIX
  274. DBGPRINT(( "CDMODEM: HIGH VERSION provider: %s, line name: %s \n",
  275. (char*) linedevcaps+linedevcaps->dwProviderInfoOffset,
  276. (CHAR *)linedevcaps+linedevcaps->dwLineNameOffset));
  277. #endif
  278. // select only those devices that have comm/datamodem as a device class
  279. //
  280. if ( (strstr((CHAR *)linedevcaps+linedevcaps->dwDeviceClassesOffset, "comm/datamodem") != NULL) ||
  281. (strstr((CHAR *)linedevcaps+linedevcaps->dwProviderInfoOffset, "Modem") != NULL) ) {
  282. DWORD stringlen = (linedevcaps->dwLineNameSize > MAX_DEVICE_NAME - 1 ? MAX_DEVICE_NAME - 1 : linedevcaps->dwLineNameSize) ;
  283. strcpy (devicetype, DEVICETYPE_UNIMODEM) ;
  284. strncpy (devicename, (CHAR *)linedevcaps+linedevcaps->dwLineNameOffset, stringlen) ;
  285. devicename[stringlen] = '\0' ;
  286. lstrcpynA(szregkey, (CHAR *)linedevcaps+linedevcaps->dwDevSpecificOffset+(2*sizeof(DWORD)), linedevcaps->dwDevSpecificSize);
  287. szregkey[linedevcaps->dwDevSpecificSize] = '\0';
  288. fModem = TRUE ;
  289. }
  290. } else {
  291. // Provider info is of the following format
  292. // <media name>\0<device name>\0
  293. // where - media name is - ISDN, SWITCH56, FRAMERELAY, etc.
  294. // device name is Digiboard PCIMAC, Cirel, Intel, etc.
  295. //
  296. // Since this format is used only by NDISWAN miniports this may not be present if the TSP
  297. // is a non unimodem and a non NDISWAN miniport. The following code (carefully) tries to
  298. // parse the
  299. //
  300. DWORD copylen ;
  301. DWORD providerinfosize = linedevcaps->dwProviderInfoSize + 2;
  302. BYTE* providerinfo = LocalAlloc (LPTR, providerinfosize) ;
  303. if (providerinfo == NULL)
  304. goto error ;
  305. memcpy (providerinfo, (CHAR *)linedevcaps+linedevcaps->dwProviderInfoOffset, linedevcaps->dwProviderInfoSize) ;
  306. providerinfo[providerinfosize-1] = '\0' ;
  307. providerinfo[providerinfosize-2] = '\0' ;
  308. #ifdef CITRIX
  309. DBGPRINT(( "CDMODEM: None High Version, version: %d \n",nextline->NegotiatedApiVersion));
  310. #endif
  311. if (strlen (providerinfo) > MAX_DEVICETYPE_NAME) {
  312. //
  313. // If this name is longer than specified for a devicetype name then this is not a
  314. // wan miniport device. In this case copy the provider info into the devicename
  315. //
  316. copylen = (strlen(providerinfo) > MAX_DEVICE_NAME ? MAX_DEVICE_NAME : strlen(providerinfo)) ;
  317. strcpy (devicetype, "XXXX") ; // put in a dummy device type - this will get skipped.
  318. strncpy (devicename, providerinfo, copylen) ;
  319. } else {
  320. //
  321. // treat this case as the the properly formatted name
  322. //
  323. strcpy (devicetype, providerinfo) ;
  324. copylen = (strlen(providerinfo+strlen(providerinfo)+1) > MAX_DEVICE_NAME ? MAX_DEVICE_NAME : strlen(providerinfo+strlen(providerinfo)+1)) ;
  325. strncpy (devicename, providerinfo+strlen(providerinfo)+1, copylen) ;
  326. devicename[copylen] = '\0' ;
  327. }
  328. }
  329. #ifndef CITRIX
  330. totaladdresses = linedevcaps->dwNumAddresses ;
  331. for (k=0; k < totaladdresses; k++) {
  332. #else // CITRIX
  333. for (k=0; k < linedevcaps->dwNumAddresses; k++) {
  334. #endif // CITRIX
  335. if (!fModem) {
  336. memset (buffer, 0, sizeof(buffer)) ;
  337. lineaddrcaps = (LINEADDRESSCAPS*) buffer ;
  338. lineaddrcaps->dwTotalSize = sizeof (buffer) ;
  339. if (lineGetAddressCaps (RasLine, i, k, nextline->NegotiatedApiVersion, nextline->NegotiatedExtVersion, lineaddrcaps)) {
  340. DBGPRINT(( "CDMODEM: ETP: linegetaddresecaps error\n" ));
  341. continue;
  342. }
  343. memcpy (address, (CHAR *)lineaddrcaps + lineaddrcaps->dwAddressOffset, sizeof (address) -1 ) ;
  344. #ifndef CITRIX
  345. if ((nextport = FindPortByAddress(address)) == NULL)
  346. continue ; // this address not configured for remoteaccess
  347. #endif // CITRIX
  348. } else {
  349. GetAssociatedPortName (szregkey, address) ;
  350. #ifndef CITRIX
  351. if ((nextport = FindPortByAddressAndName(address, devicename)) == NULL)
  352. continue ; // this address not configured for remoteaccess
  353. #endif // CITRIX
  354. }
  355. #ifndef CITRIX
  356. // nextport is the TPCB for this address
  357. nextport->TPCB_Line = &RasTapiLineInfo[i] ;
  358. nextport->TPCB_State = PS_CLOSED ;
  359. nextport->TPCB_Endpoint = 0xffffffff ;
  360. nextport->TPCB_AddressId = k ;
  361. // Copy over the devicetype and devicename
  362. strcpy (nextport->TPCB_DeviceType, devicetype) ;
  363. #else // CITRIX
  364. // Under RAS, the TPCB was allocated and partially
  365. // set up in the function ReadUsageInfoFromRegistry,
  366. // since WinFrame doesn't have this info convienently
  367. // sectioned off in the Registry it is built here
  368. // from the info garnered from TAPI itself. This
  369. // potentially could add lines to the table that
  370. // WinFrame has no interest in, but it will do no
  371. // harm, since the lines are only acted upon when
  372. // an upper-level WinFrame API is called for a true
  373. // WinFrame-configured line. (Bruce Fortune, Citrix)
  374. //
  375. if (nextport == NULL) {
  376. int i;
  377. // Allocate the linear list of TPCBs based on the number
  378. // of addresses. This may be wasteful, and a better
  379. // solution would be to cull the info from WinFrame's
  380. // registry info. (Bruce Fortune, Citrix)
  381. //
  382. TotalPorts = totaladdresses;
  383. port = nextport = RasPorts = LocalAlloc (LPTR,
  384. sizeof (TapiPortControlBlock) * TotalPorts) ;
  385. if (!port) {
  386. goto error;
  387. }
  388. RasPortsEnd = RasPorts + TotalPorts ;
  389. while (port < RasPortsEnd) {
  390. DBGPRINT(( "CDMODEM: ETP: TPCB init loop\n" ));
  391. port->TPCB_State = PS_UNINITIALIZED;
  392. port++;
  393. }
  394. port = nextport++;
  395. } else {
  396. // Look for this address in the table, just in case
  397. // of duplicates. If the lookup fails, use the
  398. // next TPCB in the linear list.
  399. //
  400. if ((port = FindPortByAddress(address)) == NULL) {
  401. port = nextport++; // use next available entry
  402. if (port >= RasPortsEnd) {
  403. DbgPrint("CDMODEM: ETP: Insufficient TPCB.\n");
  404. DbgBreakPoint();
  405. }
  406. }
  407. }
  408. port->TPCB_Signature = CONTROLBLOCKSIGNATURE ;
  409. port->TPCB_Line = &RasTapiLineInfo[i] ;
  410. port->TPCB_State = PS_CLOSED ;
  411. port->TPCB_Endpoint = 0xffffffff ;
  412. port->TPCB_AddressId = k ;
  413. port->TPCB_Usage = CALL_IN_OUT;
  414. strcpy (port->TPCB_DeviceType, devicetype) ;
  415. strncpy (port->TPCB_Name, devicename, sizeof(port->TPCB_Name)-1 ) ;
  416. port->TPCB_Name[sizeof(port->TPCB_Name)-1] = 0;
  417. strncpy (port->TPCB_Address, address, sizeof(port->TPCB_Address)-1) ;
  418. port->TPCB_Address[sizeof(port->TPCB_Address)-1] = 0;
  419. #endif // CITRIX
  420. // For unimodem devices we need to fix up names
  421. //
  422. if (fModem) {
  423. // Device Name is of the form "COM1: Hayes"
  424. //
  425. DBGPRINT(("CDMODEM: address %s, devicename %s \n", address, devicename));
  426. strcpy (port->TPCB_DeviceName, address) ;
  427. strcpy (port->TPCB_DeviceName, ":") ;
  428. strcpy (port->TPCB_DeviceName, devicename) ;
  429. strncpy (port->TPCB_Name, address, sizeof(port->TPCB_Name)-1) ;
  430. port->TPCB_Name[sizeof(port->TPCB_Name)-1] = 0;
  431. } else {
  432. if (devicename[0] != '\0')
  433. strcpy (port->TPCB_DeviceName, devicename) ; // default
  434. }
  435. DBGPRINT(( "CDMODEM: ETP: p 0x%x, DN \"%s\", a \"%s\"\n",
  436. port, port->TPCB_DeviceName, port->TPCB_Name ));
  437. }
  438. }
  439. #ifndef CITRIX
  440. //
  441. // Calculate the number of valid ports
  442. //
  443. for (pports = RasPorts, i=0; i < TotalPorts; i++, pports++) {
  444. if (pports->TPCB_State == PS_UNINITIALIZED)
  445. continue ;
  446. ValidPorts++;
  447. }
  448. #else // CITRIX
  449. //
  450. // Okay, if this DLL got loaded, then at least one TAPI port
  451. // is being used by WinFrame. Since this is all we know,
  452. // ValidPorts will be used here just to indicate that
  453. // there is *at least* one port worth doing this for...
  454. //
  455. ValidPorts = 1;
  456. #endif // CITRIX
  457. //
  458. // Increase the reference count on our DLL
  459. // so it won't get unloaded out from under us.
  460. //
  461. hInst = LoadLibrary("cdmodem.dll");
  462. // Notify the api that the initialization is done
  463. //
  464. SetEvent (event) ;
  465. //
  466. // If there are ports, then we hang around until
  467. // we are shut down. Otherwise, we exit immediately.
  468. //
  469. if (ValidPorts) {
  470. while (GetMessage(&msg, NULL, 0, 0)) {
  471. TranslateMessage(&msg);
  472. DispatchMessage(&msg) ;
  473. }
  474. DBGPRINT(( "CDMODEM: ETP: WM_QUIT Message received, shutting down\n" ));
  475. }
  476. lineShutdown (RasLine) ;
  477. //
  478. // The following call atomically unloads our
  479. // DLL and terminates this thread.
  480. //
  481. FreeLibraryAndExitThread(hInst, SUCCESS);
  482. error:
  483. if (RasLine) {
  484. lineShutdown (RasLine) ;
  485. }
  486. RasLine = 0 ;
  487. SetEvent (event) ;
  488. return ((DWORD)-1) ;
  489. }
  490. //* ReadUsageInfoFromRegistry()
  491. //
  492. //
  493. //
  494. //
  495. //
  496. //*
  497. BOOL
  498. ReadUsageInfoFromRegistry()
  499. {
  500. DWORD size;
  501. DWORD type;
  502. HKEY hkey;
  503. //
  504. // Read the number of rings key from the registry
  505. //
  506. if (RegOpenKey (HKEY_LOCAL_MACHINE, TEXT("System\\CurrentControlSet\\Services\\Rasman\\Parameters"), &hkey))
  507. return FALSE;
  508. size = sizeof(DWORD) ;
  509. if (RegQueryValueEx (hkey, TEXT("NumberOfRings"), NULL, &type, (LPBYTE)&NumberOfRings, &size))
  510. NumberOfRings = 1 ;
  511. if ((NumberOfRings < 1) || (NumberOfRings > 20))
  512. NumberOfRings = 1 ;
  513. RegCloseKey (hkey) ;
  514. return TRUE;
  515. }
  516. //* RasTapiCallback()
  517. //
  518. // Function: Callback entrypoint for TAPI.
  519. //
  520. // Returns: Nothing.
  521. //*
  522. VOID FAR PASCAL
  523. RasTapiCallback (HANDLE context, DWORD msg, DWORD instance, DWORD param1, DWORD param2, DWORD param3)
  524. {
  525. LINECALLINFO *linecallinfo ;
  526. BYTE buffer [1000] ;
  527. HCALL hcall ;
  528. HLINE linehandle ;
  529. TapiLineInfo *line ;
  530. TapiPortControlBlock *port ;
  531. DWORD i ;
  532. DWORD retcode ;
  533. // **** Exclusion Begin ****
  534. GetMutex (RasTapiMutex, INFINITE) ;
  535. DBGPRINT(( "RasTapiCallback: Ctx 0x%x, Msg: %d, Inst 0x%x, Param1: %d\n",
  536. context, msg, instance, param1 ));
  537. switch (msg) {
  538. case LINE_CALLSTATE:
  539. hcall = (HCALL) (ULONG_PTR) context ;
  540. line = ULongToPtr(instance);
  541. // If line is closed dont bother
  542. //
  543. if (line->TLI_LineState == PS_CLOSED)
  544. break ;
  545. memset (buffer, 0, sizeof(buffer)) ;
  546. linecallinfo = (LINECALLINFO *) buffer ;
  547. linecallinfo->dwTotalSize = sizeof(buffer) ;
  548. // If line get call info fails return.
  549. //
  550. if (lineGetCallInfo (hcall, linecallinfo) > 0x80000000)
  551. break ;
  552. // Locate the ras port for this call
  553. //
  554. if ((port = FindPortByAddressId (line, linecallinfo->dwAddressID)) == NULL) {
  555. // Did not find a ras port for the call. Ignore it.
  556. //
  557. break ;
  558. }
  559. DBGPRINT(("RasTapiCallBack: LINE_CALLSTATE check param1 \n"));
  560. // A new call is coming in
  561. //
  562. if (param1 == LINECALLSTATE_OFFERING) {
  563. if ((line->TLI_LineState == PS_LISTENING) && (port->TPCB_State == PS_LISTENING)) {
  564. port->TPCB_CallHandle = hcall ;
  565. //
  566. // for unimodem devices wait for the specified number of rings
  567. //
  568. if (_stricmp (port->TPCB_DeviceType, DEVICETYPE_UNIMODEM) == 0) {
  569. //
  570. // call has already been answered by somebody else and is being offered to me
  571. //
  572. if (linecallinfo->dwCallStates == LINECALLSTATE_CONNECTED) {
  573. port->TPCB_ListenState = LS_COMPLETE ;
  574. //
  575. // Complete event so that rasman calls DeviceWork to proceed the listen state machine.
  576. //
  577. SetEvent (port->TPCB_ReqNotificationHandle) ;
  578. } else {
  579. port->TPCB_ListenState = LS_RINGING ;
  580. port->TPCB_NumberOfRings = NumberOfRings ;
  581. }
  582. } else {
  583. //
  584. // For other devices make transition to next listening state
  585. //
  586. port->TPCB_ListenState = LS_ACCEPT ;
  587. //
  588. // Complete event so that rasman calls DeviceWork to proceed the listen state machine.
  589. //
  590. SetEvent (port->TPCB_ReqNotificationHandle) ;
  591. }
  592. } else {
  593. //
  594. // We were not expecting the call. Make transition to next listening state
  595. //
  596. port->TPCB_ListenState = LS_ERROR ;
  597. port->TPCB_CallHandle = hcall ;
  598. //
  599. // not interested in call, drop it.
  600. //
  601. InitiatePortDisconnection (port) ;
  602. }
  603. break ;
  604. }
  605. // Call connected.
  606. //
  607. if (param1 == LINECALLSTATE_CONNECTED ) {
  608. DBGPRINT((" RasTapiCallBack: LINECALLSTATE_CONNECTED \n"));
  609. if (port->TPCB_State == PS_CONNECTING) {
  610. //
  611. // We were requesting the call. Complete event so that rasman calls DeviceWork() to complete the
  612. // connection process.
  613. //
  614. SetEvent (port->TPCB_ReqNotificationHandle) ;
  615. } else {
  616. port->TPCB_CallHandle = hcall ;
  617. // This is a call we are asnwering. Now we can indicate to rasman that the call has come in.
  618. //
  619. // Setting listen state to LS_COMPLETE may be redundant but handles the case where the answer
  620. // completes *after* the connection is indicated
  621. //
  622. port->TPCB_ListenState = LS_COMPLETE ;
  623. //
  624. // Complete event so that rasman knows of incoming call and calls devicework.
  625. //
  626. SetEvent (port->TPCB_ReqNotificationHandle) ;
  627. }
  628. }
  629. //
  630. // Failure of sorts.
  631. //
  632. if ((param1 == LINECALLSTATE_BUSY) || (param1 == LINECALLSTATE_SPECIALINFO)) {
  633. // If we were connecting, notify rasman to call devicework so that the connection attempt can
  634. // be gracefully failed.
  635. //
  636. if (port->TPCB_State == PS_CONNECTING)
  637. SetEvent (port->TPCB_ReqNotificationHandle) ;
  638. // Can this be received for the answering case?
  639. //
  640. }
  641. //
  642. // Disconnection happened
  643. //
  644. if (param1 == LINECALLSTATE_DISCONNECTED) {
  645. // If we were connecting, notify rasman to call devicework so that the connection attempt can
  646. // be gracefully failed.
  647. //
  648. if (port->TPCB_State == PS_CONNECTING) {
  649. if (param2 == LINEDISCONNECTMODE_BUSY)
  650. port->TPCB_AsyncErrorCode = ERROR_LINE_BUSY ;
  651. else if (param2 == LINEDISCONNECTMODE_NOANSWER)
  652. port->TPCB_AsyncErrorCode = ERROR_NO_ANSWER ;
  653. else if (param2 == LINEDISCONNECTMODE_NODIALTONE)
  654. port->TPCB_AsyncErrorCode = ERROR_NO_DIALTONE ;
  655. else if (param2 == LINEDISCONNECTMODE_CANCELLED)
  656. port->TPCB_AsyncErrorCode = ERROR_USER_DISCONNECTION;
  657. SetEvent (port->TPCB_ReqNotificationHandle) ;
  658. } else if (port->TPCB_State != PS_CLOSED) {
  659. // If we were connected and got a disconnect notification then this could be hardware failure or
  660. // a remote disconnection. Determine this and save the reason away.
  661. //
  662. if (port->TPCB_State == PS_CONNECTED) {
  663. LINECALLSTATUS *pcallstatus ;
  664. BYTE buffer[200] ;
  665. memset (buffer, 0, sizeof(buffer)) ;
  666. pcallstatus = (LINECALLSTATUS *) buffer ;
  667. pcallstatus->dwTotalSize = sizeof (buffer) ;
  668. lineGetCallStatus (port->TPCB_CallHandle, pcallstatus) ;
  669. if (pcallstatus->dwCallState == LINECALLSTATE_DISCONNECTED)
  670. port->TPCB_DisconnectReason = SS_LINKDROPPED ;
  671. else
  672. port->TPCB_DisconnectReason = SS_HARDWAREFAILURE ;
  673. } else
  674. port->TPCB_DisconnectReason = 0 ;
  675. //
  676. // This means that we got a disconnect indication in one of the other states (listening, connected, etc.)
  677. // We initiate our disconnect state machine.
  678. //
  679. if (InitiatePortDisconnection (port) != PENDING) {
  680. // Disconnection succeeded or failed. Both are end states for the disconnect state machine so notify
  681. // rasman that a disconnection has happened.
  682. //
  683. // DbgPrint("SignalDisc: 1\n") ;
  684. SetEvent (port->TPCB_DiscNotificationHandle) ;
  685. }
  686. }
  687. }
  688. //
  689. // A busy call state - our attempt to dialout failed
  690. //
  691. if (param1 == LINECALLSTATE_BUSY) {
  692. if (port->TPCB_State == PS_CONNECTING) {
  693. port->TPCB_AsyncErrorCode = ERROR_LINE_BUSY ;
  694. SetEvent (port->TPCB_ReqNotificationHandle) ;
  695. }
  696. }
  697. // Idle indication is useful to complete the disconnect state machine.
  698. //
  699. if (param1 == LINECALLSTATE_IDLE) {
  700. // DbgPrint ("I, State = %d\n", port->TPCB_State) ;
  701. if ((port->TPCB_State == PS_DISCONNECTING) && (port->TPCB_RequestId == INFINITE)) {
  702. // IDLE notification came after LineDrop Succeeded so safe to
  703. // deallocate the call
  704. //
  705. port->TPCB_State = PS_OPEN ;
  706. lineDeallocateCall (port->TPCB_CallHandle) ;
  707. // DbgPrint ("D + Signal Disc\n") ;
  708. port->TPCB_CallHandle = (HCALL) 0xffffffff ;
  709. line->IdleReceived = FALSE;
  710. SetEvent (port->TPCB_DiscNotificationHandle) ;
  711. } else {
  712. // We have not yet disconnected so do not deallocate call
  713. // yet. This will be done when the disconnect completes.
  714. //
  715. line->IdleReceived = TRUE;
  716. // DbgPrint ("IdleNoAction\n") ;
  717. }
  718. }
  719. break ;
  720. case LINE_REPLY:
  721. // This message is sent to indicate completion of an asynchronous API.
  722. //
  723. DbgPrint ("LineReply: ReqId:%d", param1) ;
  724. // Find for which port the async request succeeded. This is done by searching for pending
  725. // request id that is also provided in this message.
  726. //
  727. if ((port = FindPortByRequestId (param1)) == NULL) {
  728. DbgPrint ("\n") ;
  729. break ;
  730. } else
  731. DbgPrint (" State = %d\n", port->TPCB_State) ;
  732. // Set request id to invalid.
  733. //
  734. port->TPCB_RequestId = INFINITE ;
  735. if (port->TPCB_State == PS_DISCONNECTING) {
  736. // lineDrop completed. Note that we ignore the return code in param2. This is
  737. // because we cant do anything else.
  738. //
  739. if (port->TPCB_Line->IdleReceived) {
  740. // We received IDLE notification before/during disconnect
  741. // so deallocate this call
  742. //
  743. port->TPCB_Line->IdleReceived = FALSE;
  744. port->TPCB_State = PS_OPEN ;
  745. lineDeallocateCall (port->TPCB_CallHandle) ;
  746. // DbgPrint ("D + SignalDisc\n") ;
  747. port->TPCB_CallHandle = (HCALL) 0xffffffff ;
  748. SetEvent (port->TPCB_DiscNotificationHandle) ;
  749. } else {
  750. // wait for idle message before signalling disconnect
  751. //
  752. ; // DbgPrint ("DropCompNoAction\n") ;
  753. }
  754. break ;
  755. }
  756. // Some other api completed
  757. //
  758. if (param2 == SUCCESS) {
  759. // Success means take no action - unless we are listening
  760. // in which case it means move to the next state - we simply
  761. // set the event that will result in a call to DeviceWork() to
  762. // make the actual call for the next state
  763. //
  764. if (port->TPCB_State != PS_LISTENING)
  765. break ;
  766. // Proceed to the next listening sub-state
  767. //
  768. if (port->TPCB_ListenState == LS_ACCEPT) {
  769. port->TPCB_ListenState = LS_ANSWER ;
  770. SetEvent (port->TPCB_ReqNotificationHandle) ;
  771. } else if (port->TPCB_ListenState == LS_ANSWER) {
  772. port->TPCB_ListenState = LS_COMPLETE ;
  773. }
  774. } else {
  775. // For connecting and listening ports this means the attempt failed
  776. // because of some error
  777. //
  778. if (port->TPCB_State == PS_CONNECTING) {
  779. port->TPCB_AsyncErrorCode = ERROR_PORT_OR_DEVICE ;
  780. SetEvent (port->TPCB_ReqNotificationHandle) ;
  781. } else if (port->TPCB_State == PS_LISTENING) {
  782. // Because ACCEPT may not be supported by the device - treat error as success
  783. //
  784. if (port->TPCB_ListenState == LS_ACCEPT)
  785. port->TPCB_ListenState = LS_ANSWER ;
  786. else
  787. port->TPCB_ListenState = LS_ERROR ;
  788. SetEvent (port->TPCB_ReqNotificationHandle) ;
  789. }
  790. // Some other API failed, we dont know and we dont care. Ignore.
  791. //
  792. else if (port->TPCB_State != PS_CLOSED) {
  793. ; // DbgPrint ("RASTAPI: LINE_REPLY failed. Ignored.\n") ;
  794. }
  795. }
  796. break ;
  797. case LINE_CLOSE:
  798. // Typically sent when things go really wrong.
  799. //
  800. DbgPrint ("RASTAPI: received LINE_CLOSE message\n") ;
  801. // Find which line is indication came for.
  802. //
  803. line = ULongToPtr(instance) ;
  804. // if line not found or if it is closed just return
  805. //
  806. if ((line == NULL) || (line->TLI_LineState == PS_CLOSED))
  807. break ;
  808. // For every port that is on the line - open the line again and signal
  809. // hw failure
  810. //
  811. for (port = RasPorts, i = 0; i < TotalPorts; i++, port++) {
  812. // Skip ports that arent initialized
  813. //
  814. if (port->TPCB_State == PS_UNINITIALIZED)
  815. continue ;
  816. if (port->TPCB_Line == line) {
  817. if (retcode = lineOpen (RasLine,
  818. port->TPCB_Line->TLI_LineId,
  819. &port->TPCB_Line->TLI_LineHandle,
  820. port->TPCB_Line->NegotiatedApiVersion,
  821. port->TPCB_Line->NegotiatedExtVersion,
  822. (ULONG) (ULONG_PTR) port->TPCB_Line,
  823. LINECALLPRIVILEGE_OWNER,
  824. port->TPCB_MediaMode,
  825. NULL)); //
  826. // Set monitoring of rings
  827. //
  828. lineSetStatusMessages (port->TPCB_Line->TLI_LineHandle, LINEDEVSTATE_RINGING, 0) ;
  829. // If the port is listening - then we do not need to do anything since the listen is
  830. // posted implicitly,
  831. //
  832. if (port->TPCB_State != PS_LISTENING) {
  833. //
  834. // These settings should cause connections and connect attempts to
  835. // fail.
  836. //
  837. port->TPCB_AsyncErrorCode = ERROR_FROM_DEVICE ;
  838. port->TPCB_CallHandle = (HCALL) 0xffffffff ;
  839. port->TPCB_ListenState = LS_ERROR ;
  840. // Signal hardware failure to rasman.
  841. //
  842. // DbgPrint ("SignalDisc: 3\n") ;
  843. SetEvent (port->TPCB_DiscNotificationHandle) ;
  844. }
  845. }
  846. }
  847. break ;
  848. case LINE_LINEDEVSTATE:
  849. //
  850. // we are only interested in ringing message
  851. //
  852. if (param1 != LINEDEVSTATE_RINGING)
  853. break ;
  854. // Find which line is indication came for.
  855. //
  856. line = ULongToPtr(instance) ;
  857. // if line not found or if it is closed just return
  858. //
  859. if ((line == NULL) || (line->TLI_LineState == PS_CLOSED))
  860. break ;
  861. // get the port from the line
  862. //
  863. for (port = RasPorts, i = 0; i < TotalPorts; i++, port++) {
  864. // Skip ports that arent initialized
  865. //
  866. if (port->TPCB_State == PS_UNINITIALIZED)
  867. continue ;
  868. if ((port->TPCB_Line == line) && (port->TPCB_State == PS_LISTENING) && (port->TPCB_ListenState == LS_RINGING)) {
  869. //
  870. // count down the rings
  871. //
  872. port->TPCB_NumberOfRings -= 1 ;
  873. // DbgPrint ("Ring count = %d\n", port->TPCB_NumberOfRings) ;
  874. //
  875. // if the ring count has gone down to zero this means that we should pick up the call.
  876. //
  877. if (port->TPCB_NumberOfRings == 0) {
  878. port->TPCB_ListenState = LS_ACCEPT ;
  879. //
  880. // Complete event so that rasman calls DeviceWork to proceed the listen state machine.
  881. //
  882. SetEvent (port->TPCB_ReqNotificationHandle) ;
  883. }
  884. break ;
  885. }
  886. }
  887. break ;
  888. case LINE_ADDRESSSTATE:
  889. case LINE_CALLINFO:
  890. case LINE_CREATE:
  891. case LINE_DEVSPECIFIC:
  892. case LINE_DEVSPECIFICFEATURE:
  893. case LINE_GATHERDIGITS:
  894. case LINE_GENERATE:
  895. case LINE_MONITORDIGITS:
  896. case LINE_MONITORMEDIA:
  897. case LINE_MONITORTONE:
  898. case LINE_REQUEST:
  899. default:
  900. // All unhandled unsolicited messages.
  901. //
  902. ;
  903. }
  904. // **** Exclusion End ****
  905. FreeMutex (RasTapiMutex) ;
  906. }
  907. //* FindPortByAddressId()
  908. //
  909. //
  910. //
  911. //
  912. //*
  913. TapiPortControlBlock *
  914. FindPortByAddressId (TapiLineInfo *line, DWORD addid)
  915. {
  916. DWORD i ;
  917. TapiPortControlBlock *port ;
  918. for (i=0, port=RasPorts; i<TotalPorts; i++, port++) {
  919. if ((port->TPCB_AddressId == addid) && (port->TPCB_Line == line))
  920. return port ;
  921. }
  922. return NULL ;
  923. }
  924. //* FindPortByAddress()
  925. //
  926. //
  927. //
  928. //
  929. //*
  930. TapiPortControlBlock *
  931. FindPortByAddress (CHAR *address)
  932. {
  933. DWORD i ;
  934. TapiPortControlBlock *port ;
  935. for (i=0, port=RasPorts; i<TotalPorts; i++, port++) {
  936. if (_stricmp (port->TPCB_Address, address) == 0)
  937. return port ;
  938. }
  939. return NULL ;
  940. }
  941. //* FindPortByAddress()
  942. //
  943. //
  944. //
  945. //
  946. //*
  947. TapiPortControlBlock *
  948. FindPortByAddressAndName (CHAR *address, CHAR *name)
  949. {
  950. DWORD i ;
  951. TapiPortControlBlock *port ;
  952. for (i=0, port=RasPorts; i<TotalPorts; i++, port++) {
  953. if ((_stricmp (port->TPCB_Address, address) == 0) &&
  954. (_strnicmp (port->TPCB_Name, name, MAX_PORT_NAME-1) == 0))
  955. return port ;
  956. }
  957. return NULL ;
  958. }
  959. //* FindPortByRequestId()
  960. //
  961. //
  962. //
  963. //
  964. //*
  965. TapiPortControlBlock *
  966. FindPortByRequestId (DWORD reqid)
  967. {
  968. DWORD i ;
  969. TapiPortControlBlock *port ;
  970. for (i=0, port=RasPorts; i<TotalPorts; i++, port++) {
  971. if (port->TPCB_RequestId == reqid)
  972. return port ;
  973. }
  974. return NULL ;
  975. }
  976. //* FindLineByHandle()
  977. //
  978. //
  979. //
  980. //
  981. //*
  982. TapiLineInfo *
  983. FindLineByHandle (HLINE linehandle)
  984. {
  985. DWORD i ;
  986. TapiLineInfo *line ;
  987. for (i=0, line=RasTapiLineInfo; i<TotalLines; i++, line++) {
  988. if (line->TLI_LineHandle == linehandle)
  989. return line ;
  990. }
  991. return NULL ;
  992. }
  993. #define VALNAME_ATTACHEDTO "AttachedTo"
  994. BOOL
  995. GetAssociatedPortName(
  996. char * szKeyName,
  997. CHAR * szPortName)
  998. /*
  999. * Given the registry key name 'szRegistryKeyName' corresponding to the modem entry, fills in
  1000. * 'wszAddress' with the associated port like COM1, ..
  1001. *
  1002. */
  1003. {
  1004. HKEY hKeyModem;
  1005. DWORD dwType;
  1006. DWORD cbValueBuf;
  1007. #if 0
  1008. char buf[256];
  1009. #endif
  1010. #if 0
  1011. wsprintfA(buf,"RegistryKey -> %s \n", szKeyName);
  1012. OutputDebugStringA(buf);
  1013. #endif
  1014. if ( RegOpenKeyExA(HKEY_LOCAL_MACHINE,
  1015. szKeyName,
  1016. 0,
  1017. KEY_READ,
  1018. &hKeyModem ) )
  1019. {
  1020. return( FALSE );
  1021. }
  1022. cbValueBuf = 40 ;
  1023. if ( RegQueryValueExA(hKeyModem,
  1024. VALNAME_ATTACHEDTO,
  1025. NULL,
  1026. &dwType,
  1027. (LPBYTE)szPortName,
  1028. &cbValueBuf ))
  1029. {
  1030. return ( FALSE );
  1031. }
  1032. RegCloseKey( hKeyModem );
  1033. return ( TRUE );
  1034. }
  1035.