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.

2148 lines
55 KiB

  1. /* Copyright (c) 1995, Microsoft Corporation, all rights reserved
  2. **
  3. ** rasman.c
  4. ** RAS Manager helpers
  5. ** Listed alphabetically
  6. **
  7. ** These routines have been exempted from the TCHARizing applied to the rest
  8. ** of the library because RASMAN is still an ANSI interface.
  9. **
  10. ** 09/20/95 Steve Cobb
  11. */
  12. #include <windows.h> // Win32 root
  13. #include <stdlib.h> // for atol()
  14. #include <debug.h> // Trace/Assert library
  15. #include <nouiutil.h> // Our public header
  16. #include <raserror.h> // RAS error constants
  17. #include <mcx.h> // Unimodem
  18. #include <unimodem.h>
  19. /* These types are described in MSDN and appear in Win95's unimdm.h private
  20. ** header (complete with typo) but not in any SDK headers.
  21. */
  22. typedef struct tagDEVCFGGDR
  23. {
  24. DWORD dwSize;
  25. DWORD dwVersion;
  26. WORD fwOptions;
  27. WORD wWaitBong;
  28. }
  29. DEVCFGHDR;
  30. typedef struct tagDEVCFG
  31. {
  32. DEVCFGHDR dfgHdr;
  33. COMMCONFIG commconfig;
  34. }
  35. DEVCFG;
  36. #define MANUAL_DIAL 0x0004
  37. #define TERMINAL_PRE 0x0001
  38. // Test rig to return a variety of fake ports from GetRasPorts.
  39. //
  40. #define DUMMYPORTS 0
  41. #if DUMMYPORTS
  42. DWORD g_cPorts = 6;
  43. #endif
  44. /*----------------------------------------------------------------------------
  45. ** Local prototypes
  46. **----------------------------------------------------------------------------
  47. */
  48. DWORD
  49. GetRasDevices(
  50. IN HANDLE hConnection,
  51. IN CHAR* pszDeviceType,
  52. OUT RASMAN_DEVICE** ppDevices,
  53. OUT DWORD* pdwEntries );
  54. DWORD
  55. GetRasPortParam(
  56. IN HPORT hport,
  57. IN CHAR* pszKey,
  58. OUT RASMAN_PORTINFO** ppPortInfo,
  59. OUT RAS_PARAMS** ppParam );
  60. /*----------------------------------------------------------------------------
  61. ** Routines
  62. **----------------------------------------------------------------------------
  63. */
  64. DWORD
  65. ClearRasdevStats(
  66. IN RASDEV* pdev,
  67. IN BOOL fBundle )
  68. /* Resets statistics counters for a device.
  69. **
  70. ** (Abolade Gbadegesin Nov-9-1995)
  71. */
  72. {
  73. if (pdev == NULL) { return ERROR_INVALID_PARAMETER; }
  74. if ((HPORT)pdev->RD_Handle == (HPORT)INVALID_HANDLE_VALUE) {
  75. return ERROR_INVALID_HANDLE;
  76. }
  77. ASSERT(g_pRasPortClearStatistics);
  78. return (fBundle ? g_pRasBundleClearStatistics(NULL, (HPORT)pdev->RD_Handle)
  79. : g_pRasPortClearStatistics(NULL, (HPORT)pdev->RD_Handle));
  80. }
  81. #if 0
  82. DWORD
  83. DeviceIdFromDeviceName(
  84. TCHAR* pszDeviceName )
  85. /* Returns the TAPI device ID associated with 'pszDeviceName'. Returns
  86. ** 0xFFFFFFFE if not found, 0xFFFFFFFF if found but not a Unimodem.
  87. **
  88. ** This routine assumes that TAPI devices have unique names.
  89. */
  90. {
  91. DWORD dwErr;
  92. DWORD dwId;
  93. DWORD dwPorts;
  94. RASMAN_PORT* pPorts;
  95. TRACE("DeviceIdFromDeviceName");
  96. dwId = 0xFFFFFFFE;
  97. if (pszDeviceName)
  98. {
  99. dwErr = GetRasPorts( &pPorts, &dwPorts );
  100. if (dwErr == 0)
  101. {
  102. CHAR* pszDeviceNameA;
  103. pszDeviceNameA = StrDupAFromT( pszDeviceName );
  104. if (pszDeviceNameA)
  105. {
  106. INT i;
  107. RASMAN_PORT* pPort;
  108. for (i = 0, pPort = pPorts; i < dwPorts; ++i, ++pPort)
  109. {
  110. if (lstrcmpiA( pszDeviceNameA, pPort->P_DeviceName ) == 0)
  111. {
  112. dwId = pPort->P_LineDeviceId;
  113. break;
  114. }
  115. }
  116. Free( pszDeviceNameA );
  117. }
  118. Free( pPorts );
  119. }
  120. }
  121. TRACE1("DeviceIdFromDeviceName=%d",dwErr);
  122. return dwId;
  123. }
  124. #endif
  125. DWORD
  126. FreeRasdevTable(
  127. RASDEV* pDevTable,
  128. DWORD iDevCount )
  129. /* Frees a table built by GetRasdevTable.
  130. **
  131. ** Returns 0 if succesful, or an error code.
  132. **
  133. ** (Abolade Gbadegesin Nov-9-1995)
  134. */
  135. {
  136. DWORD i;
  137. //
  138. // validate arguments
  139. //
  140. if (pDevTable == NULL) { return ERROR_INVALID_PARAMETER; }
  141. //
  142. // free the device-name string fields
  143. //
  144. for (i = 0; i < iDevCount; i++) {
  145. if (pDevTable[i].RD_DeviceName) { Free(pDevTable[i].RD_DeviceName); }
  146. }
  147. //
  148. // free the array itself
  149. //
  150. Free(pDevTable);
  151. return NO_ERROR;
  152. }
  153. DWORD
  154. GetConnectTime(
  155. IN HRASCONN hrasconn,
  156. OUT DWORD* pdwConnectTime )
  157. /* Loads '*pdwConnectTime' with the duration in milliseconds of the
  158. ** connection on pdev.
  159. **
  160. ** Returns 0 if succesful, or an error code.
  161. **
  162. ** (Abolade Gbadegesin Nov-9-1995)
  163. */
  164. {
  165. HPORT hport;
  166. DWORD dwErr;
  167. RASMAN_INFO info;
  168. if (pdwConnectTime == NULL) { return ERROR_INVALID_PARAMETER; }
  169. //
  170. // initialize the argument
  171. //
  172. *pdwConnectTime = 0;
  173. //
  174. // get an HPORT for the HRASCONN
  175. //
  176. ASSERT(g_pRasGetHport);
  177. hport = g_pRasGetHport(hrasconn);
  178. if (hport == (HPORT)INVALID_HANDLE_VALUE) { return ERROR_INVALID_HANDLE; }
  179. //
  180. // get information on the HPORT
  181. //
  182. ASSERT(g_pRasGetInfo);
  183. dwErr = g_pRasGetInfo(NULL, hport, &info);
  184. if (dwErr != NO_ERROR) { return dwErr; }
  185. if (info.RI_ConnState != CONNECTED) { *pdwConnectTime = 0; }
  186. else { *pdwConnectTime = info.RI_ConnectDuration; }
  187. return NO_ERROR;
  188. }
  189. DWORD
  190. GetRasconnFraming(
  191. IN HRASCONN hrasconn,
  192. OUT DWORD* pdwSendFraming,
  193. OUT DWORD* pdwRecvFraming )
  194. /* Retrieves the framing bits for an active RAS connection.
  195. **
  196. ** (Abolade Gbadegesin Nov-9-1995)
  197. */
  198. {
  199. DWORD dwErr;
  200. HPORT hport;
  201. RAS_FRAMING_INFO info;
  202. //
  203. // validate arguments
  204. //
  205. if (pdwSendFraming == NULL || pdwRecvFraming == NULL) {
  206. return ERROR_INVALID_HANDLE;
  207. }
  208. //
  209. // retrieve the HPORT for this connection
  210. //
  211. ASSERT(g_pRasGetHport);
  212. hport = g_pRasGetHport(hrasconn);
  213. if (hport == (HPORT)INVALID_HANDLE_VALUE) {
  214. return ERROR_INVALID_HANDLE;
  215. }
  216. //
  217. // retrieve the framing information for this port
  218. //
  219. ASSERT(g_pRasPortGetFramingEx);
  220. dwErr = g_pRasPortGetFramingEx(NULL, hport, &info);
  221. if (dwErr != NO_ERROR) { return dwErr; }
  222. *pdwSendFraming = info.RFI_SendFramingBits;
  223. *pdwRecvFraming = info.RFI_RecvFramingBits;
  224. return NO_ERROR;
  225. }
  226. DWORD
  227. GetRasconnFromRasdev(
  228. IN RASDEV* pdev,
  229. OUT RASCONN** ppconn,
  230. IN RASCONN* pConnTable OPTIONAL,
  231. IN DWORD iConnCount OPTIONAL )
  232. /* Given a RASDEV structure for an active device, this function retrieves
  233. ** the RASCONN which corresponds to the device's current connection. The
  234. ** second and third arguments are optional; they specify a table of
  235. ** RASCONN structures to be searched. This is useful if the caller has
  236. ** already enumerated the active connections, so that this function does
  237. ** not need to re-enumerate them.
  238. **
  239. ** (Abolade Gbadegesin Nov-9-1995)
  240. */
  241. {
  242. BOOL bFreeTable;
  243. DWORD dwErr, i;
  244. RASDEVSTATS stats;
  245. //
  246. // validate arguments
  247. //
  248. if (pdev == NULL || ppconn == NULL) { return ERROR_INVALID_PARAMETER; }
  249. *ppconn = NULL;
  250. //
  251. // get stats for the RASDEV
  252. //
  253. dwErr = GetRasdevStats(pdev, &stats);
  254. if (dwErr != NO_ERROR) { return dwErr; }
  255. bFreeTable = FALSE;
  256. //
  257. // if the caller didn't pass in a table of RASCONNs, retrieve one
  258. //
  259. if (pConnTable == NULL) {
  260. dwErr = GetRasconnTable(&pConnTable, &iConnCount);
  261. if (dwErr != NO_ERROR) { return dwErr; }
  262. bFreeTable = TRUE;
  263. }
  264. //
  265. // find the connection which matches the RASDEV passed in
  266. //
  267. for (i = 0; i < iConnCount; i++) {
  268. if ((HRASCONN)stats.RDS_Hrasconn == (pConnTable + i)->hrasconn) {
  269. break;
  270. }
  271. }
  272. //
  273. // see how the search ended
  274. //
  275. if (i >= iConnCount) {
  276. dwErr = ERROR_NO_DATA;
  277. }
  278. else {
  279. dwErr = NO_ERROR;
  280. if (!bFreeTable) {
  281. //
  282. // point to the place where we found the RASCONN
  283. //
  284. *ppconn = pConnTable + i;
  285. }
  286. else {
  287. //
  288. // make a copy of the RASCONN found
  289. //
  290. *ppconn = Malloc(sizeof(RASCONN));
  291. if (!*ppconn) { dwErr = ERROR_NOT_ENOUGH_MEMORY; }
  292. else { **ppconn = *(pConnTable + i); }
  293. }
  294. }
  295. if (bFreeTable) { Free(pConnTable); }
  296. return dwErr;
  297. }
  298. DWORD
  299. GetRasdevBundle(
  300. IN RASDEV* pdev,
  301. OUT DWORD* pdwBundle )
  302. /* Retrieves a handle which represents the current connection
  303. ** on the given device. This handle has the property that it will be
  304. ** identical for two devices which are multi-linked together.
  305. ** In the case of NT RAS, the RASMAN HBUNDLE is retrieved.
  306. **
  307. ** (Abolade Gbadegesin Mar-6-1996)
  308. */
  309. {
  310. return g_pRasPortGetBundle(NULL, (HPORT)pdev->RD_Handle, (HBUNDLE *)pdwBundle);
  311. }
  312. DWORD
  313. GetRasdevFraming(
  314. IN RASDEV* pdev,
  315. OUT DWORD* pdwFraming )
  316. /* Retrieves the framing bits for an active RAS connection.
  317. **
  318. ** (Abolade Gbadegesin Nov-9-1995)
  319. */
  320. {
  321. DWORD dwErr;
  322. RAS_FRAMING_INFO info;
  323. //
  324. // validate arguments
  325. //
  326. if (pdwFraming == NULL) { return ERROR_INVALID_HANDLE; }
  327. //
  328. // retrieve the framing information for this port
  329. //
  330. ASSERT(g_pRasPortGetFramingEx);
  331. dwErr = g_pRasPortGetFramingEx(NULL, (HPORT)pdev->RD_Handle, &info);
  332. if (dwErr != NO_ERROR) { return dwErr; }
  333. if (info.RFI_SendFramingBits & OLD_RAS_FRAMING) {
  334. *pdwFraming = RASFP_Ras;
  335. }
  336. else
  337. if (info.RFI_SendFramingBits & PPP_MULTILINK_FRAMING ||
  338. info.RFI_SendFramingBits & PPP_FRAMING) {
  339. *pdwFraming = RASFP_Ppp;
  340. }
  341. else
  342. if (info.RFI_SendFramingBits & SLIP_FRAMING) {
  343. *pdwFraming = RASFP_Slip;
  344. }
  345. else {
  346. *pdwFraming = 0;
  347. }
  348. return NO_ERROR;
  349. }
  350. DWORD
  351. GetRasdevFromRasconn(
  352. IN RASCONN* pconn,
  353. OUT RASDEV** ppdev,
  354. IN RASDEV* pDevTable OPTIONAL,
  355. IN DWORD iDevCount OPTIONAL )
  356. /* Given a RASCONN structure for an active connection, this function
  357. ** retrieves the RASDEV for the device over which the connection is
  358. ** active. The second and third arguments are optional; they specify a
  359. ** table of RASDEV structures to be searched. This is useful if the
  360. ** caller has already enumerated the existing devices, so that this
  361. ** function does not need to re-enumerate them.
  362. **
  363. ** (Abolade Gbadegesin Nov-9-1995)
  364. */
  365. {
  366. HPORT hport;
  367. DWORD i, dwErr = NO_ERROR;
  368. BOOL bFreeTable;
  369. //
  370. // validate the arguments
  371. //
  372. if (pconn == NULL || ppdev == NULL) { return ERROR_INVALID_PARAMETER; }
  373. *ppdev = NULL;
  374. //
  375. // retrieve the device table if the caller didn't pass one in
  376. //
  377. bFreeTable = FALSE;
  378. // For whistler bug 26403 gangz
  379. //
  380. do
  381. {
  382. if (pDevTable == NULL) {
  383. dwErr = GetRasdevTable(&pDevTable, &iDevCount);
  384. if (dwErr != NO_ERROR) {
  385. return dwErr;
  386. }
  387. bFreeTable = TRUE;
  388. }
  389. //
  390. // retrieve the HPORT for the RASCONN passed in
  391. //
  392. ASSERT(g_pRasGetHport);
  393. hport = g_pRasGetHport(pconn->hrasconn);
  394. if (hport == (HPORT)INVALID_HANDLE_VALUE)
  395. {
  396. // For whistler bug 26403 gangz
  397. // here to break rather than return;
  398. //
  399. dwErr = ERROR_INVALID_HANDLE;
  400. break;
  401. }
  402. //
  403. // find the device to which the HPORT corresponds
  404. //
  405. for (i = 0; i < iDevCount; i++) {
  406. if (hport == pDevTable[i].RD_Handle) { break; }
  407. }
  408. //
  409. // see how the search ended
  410. //
  411. if (i >= iDevCount)
  412. {
  413. dwErr = ERROR_NO_DATA;
  414. break;
  415. }
  416. else
  417. {
  418. dwErr = NO_ERROR;
  419. if (!bFreeTable) {
  420. *ppdev = pDevTable + i;
  421. }
  422. else {
  423. *ppdev = Malloc(sizeof(RASDEV));
  424. if (!*ppdev) { dwErr = ERROR_NOT_ENOUGH_MEMORY; }
  425. else {
  426. **ppdev = *(pDevTable + i);
  427. (*ppdev)->RD_DeviceName = StrDup(pDevTable[i].RD_DeviceName);
  428. if (!(*ppdev)->RD_DeviceName) {
  429. Free(*ppdev);
  430. *ppdev = NULL;
  431. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  432. break;
  433. }
  434. }
  435. }
  436. }
  437. }while(FALSE);
  438. if (bFreeTable) { FreeRasdevTable(pDevTable, iDevCount); }
  439. return dwErr;
  440. }
  441. DWORD
  442. GetRasDevices(
  443. IN HANDLE hConnection,
  444. IN CHAR* pszDeviceType,
  445. OUT RASMAN_DEVICE** ppDevices,
  446. OUT DWORD* pdwEntries )
  447. /* Fills caller's '*ppDevices' with the address of a heap block containing
  448. ** '*pwEntries' RASMAN_DEVICE structures.
  449. **
  450. ** Returns 0 if successful, otherwise a non-0 error code. If successful,
  451. ** it is the caller's responsibility to free the returned memory block.
  452. */
  453. {
  454. DWORD dwSize = 0;
  455. DWORD dwErr;
  456. TRACE1("GetRasDevices(%s)",pszDeviceType);
  457. ASSERT(g_pRasDeviceEnum);
  458. TRACE("RasDeviceEnum...");
  459. dwErr = g_pRasDeviceEnum(hConnection, pszDeviceType, NULL, &dwSize, pdwEntries );
  460. TRACE2("RasDeviceEnum=%d,c=%d",dwErr,*pdwEntries);
  461. if (dwErr == 0)
  462. {
  463. /* No devices to enumerate. Set up to allocate a single byte anyway,
  464. ** so things work without lots of special code.
  465. */
  466. dwSize = 1;
  467. }
  468. else if (dwErr != ERROR_BUFFER_TOO_SMALL)
  469. return dwErr;
  470. *ppDevices = (RASMAN_DEVICE* )Malloc( dwSize );
  471. if (!*ppDevices)
  472. return ERROR_NOT_ENOUGH_MEMORY;
  473. TRACE("RasDeviceEnum...");
  474. dwErr = g_pRasDeviceEnum(
  475. hConnection,
  476. pszDeviceType,
  477. (PBYTE )*ppDevices,
  478. &dwSize,
  479. pdwEntries );
  480. TRACE1("RasDeviceEnum=%d",dwErr);
  481. if (dwErr != 0)
  482. {
  483. Free( *ppDevices );
  484. return dwErr;
  485. }
  486. return 0;
  487. }
  488. DWORD
  489. GetRasDeviceString(
  490. IN HPORT hport,
  491. IN CHAR* pszDeviceType,
  492. IN CHAR* pszDeviceName,
  493. IN CHAR* pszKey,
  494. OUT CHAR** ppszValue,
  495. IN DWORD dwXlate )
  496. /* Loads callers '*ppszValue' with the address of a heap block containing
  497. ** a NUL-terminated copy of the value string associated with key 'pszKey'
  498. ** for the device on port 'hport'. 'pszDeviceType' specifies the type of
  499. ** device, e.g. "modem". 'pszDeviceName' specifies the name of the
  500. ** device, e.g. "Hayes V-Series 9600". 'dwXlate' is a bit mask of XLATE_
  501. ** bits specifying translations to perform on the returned string.
  502. **
  503. ** Returns 0 if successful, otherwise a non-0 error code. If successful,
  504. ** it is the caller's responsibility to Free the returned string.
  505. */
  506. {
  507. DWORD dwErr = 0;
  508. RASMAN_DEVICEINFO* pDeviceInfo = NULL;
  509. RAS_PARAMS* pParam;
  510. DWORD dwSize = 0;
  511. INT i;
  512. TRACE2("GetRasDeviceString(%s,%s)",pszDeviceName,pszKey);
  513. *ppszValue = NULL;
  514. do
  515. {
  516. ASSERT(g_pRasDeviceGetInfo);
  517. TRACE("RasDeviceGetInfo...");
  518. dwErr = g_pRasDeviceGetInfo(
  519. NULL, hport, pszDeviceType, pszDeviceName, NULL, &dwSize );
  520. TRACE2("RasDeviceGetInfo=%d,s=%d",dwErr,(INT)dwSize);
  521. if (dwErr != ERROR_BUFFER_TOO_SMALL && dwErr != 0)
  522. break;
  523. /* So it will fall thru and be "not found".
  524. */
  525. if (dwSize == 0)
  526. dwSize = 1;
  527. pDeviceInfo = (RASMAN_DEVICEINFO* )Malloc( dwSize );
  528. if (!pDeviceInfo)
  529. return ERROR_NOT_ENOUGH_MEMORY;
  530. TRACE("RasDeviceGetInfo...");
  531. dwErr = g_pRasDeviceGetInfo(
  532. NULL, hport, pszDeviceType, pszDeviceName, (PBYTE )pDeviceInfo, &dwSize );
  533. TRACE2("RasDeviceGetInfo=%d,s=%d",dwErr,(INT)dwSize);
  534. if (dwErr != 0)
  535. break;
  536. dwErr = ERROR_KEY_NOT_FOUND;
  537. for (i = 0, pParam = pDeviceInfo->DI_Params;
  538. i < (INT )pDeviceInfo->DI_NumOfParams;
  539. ++i, ++pParam)
  540. {
  541. if (lstrcmpiA( pParam->P_Key, pszKey ) == 0)
  542. {
  543. *ppszValue = PszFromRasValue( &pParam->P_Value, dwXlate );
  544. dwErr = (*ppszValue) ? 0 : ERROR_NOT_ENOUGH_MEMORY;
  545. break;
  546. }
  547. }
  548. }
  549. while (FALSE);
  550. Free0( pDeviceInfo );
  551. TRACE1("String=\"%s\"",(*ppszValue)?*ppszValue:"");
  552. return dwErr;
  553. }
  554. DWORD
  555. GetRasdevStats(
  556. IN RASDEV* pdev,
  557. OUT RASDEVSTATS* pstats )
  558. /* Retrieves statistics for a device.
  559. **
  560. ** (Abolade Gbadegesin Nov-9-1995)
  561. */
  562. {
  563. DWORD dwsize;
  564. RASMAN_INFO info;
  565. RAS_STATISTICS *prs;
  566. BYTE buffer[sizeof(RAS_STATISTICS) + MAX_STATISTICS * 2 * sizeof(DWORD)];
  567. DWORD dwErr, *pdw, dwGone, dwB, dwBC, dwBU;
  568. if (pdev == NULL || pstats == NULL) { return ERROR_INVALID_PARAMETER; }
  569. ZeroMemory(pstats, sizeof(RASDEVSTATS));
  570. //
  571. // retrieve the condition and connect time
  572. //
  573. ASSERT(g_pRasGetInfo);
  574. dwErr = g_pRasGetInfo(NULL, (HPORT)pdev->RD_Handle, &info);
  575. if (dwErr != NO_ERROR) {
  576. pstats->RDS_Condition = DISCONNECTED;
  577. return dwErr;
  578. }
  579. //
  580. // need to handle ports which are not connected
  581. // already a bug filed.
  582. //
  583. if (info.RI_PortStatus != OPEN) {
  584. pstats->RDS_Condition = DISCONNECTED;
  585. return NO_ERROR;
  586. }
  587. pstats->RDS_Condition = info.RI_ConnState;
  588. if (info.RI_ConnState == CONNECTED) {
  589. pstats->RDS_ConnectTime = info.RI_ConnectDuration;
  590. pstats->RDS_Hrasconn = (HRASCONN)info.RI_ConnectionHandle;
  591. }
  592. //
  593. // get dial-in/dial-out usage
  594. //
  595. if (info.RI_CurrentUsage & CALL_IN)
  596. pstats->RDS_Flags |= RDFLAG_IsDialedIn;
  597. if (info.RI_CurrentUsage & CALL_OUT)
  598. pstats->RDS_Flags |= RDFLAG_IsDialedOut;
  599. if (info.RI_CurrentUsage & CALL_ROUTER)
  600. pstats->RDS_Flags |= RDFLAG_IsRouter;
  601. //
  602. // Retrieve the line speed
  603. //
  604. pstats->RDS_LineSpeed = info.RI_LinkSpeed;
  605. //
  606. // Retrieve the i/o statistics for both the link and the bundle
  607. //
  608. prs = (RAS_STATISTICS *)buffer;
  609. dwsize = sizeof(RAS_STATISTICS) + MAX_STATISTICS * 2 * sizeof(DWORD);
  610. ZeroMemory(buffer, dwsize);
  611. ASSERT(g_pRasBundleGetStatistics);
  612. dwErr = g_pRasBundleGetStatistics(
  613. NULL, (HPORT)pdev->RD_Handle, (PBYTE)prs, &dwsize
  614. );
  615. if (dwErr != NO_ERROR) { return dwErr; }
  616. //
  617. // Save the statistics in the caller's RASDEVSTATS structure.
  618. //
  619. pdw = prs->S_Statistics;
  620. pstats->RDS_InFrames = pdw[FRAMES_RCVED];
  621. pstats->RDS_OutFrames = pdw[FRAMES_XMITED];
  622. pstats->RDS_InBytesTotal =
  623. pdw[BYTES_RCVED] +
  624. pdw[BYTES_RCVED_UNCOMPRESSED] -
  625. pdw[BYTES_RCVED_COMPRESSED];
  626. pstats->RDS_OutBytesTotal =
  627. pdw[BYTES_XMITED] +
  628. pdw[BYTES_XMITED_UNCOMPRESSED] -
  629. pdw[BYTES_XMITED_COMPRESSED];
  630. pstats->RDS_InBytes =
  631. pdw[MAX_STATISTICS + BYTES_RCVED] +
  632. pdw[MAX_STATISTICS + BYTES_RCVED_UNCOMPRESSED] -
  633. pdw[MAX_STATISTICS + BYTES_RCVED_COMPRESSED];
  634. pstats->RDS_OutBytes =
  635. pdw[MAX_STATISTICS + BYTES_XMITED] +
  636. pdw[MAX_STATISTICS + BYTES_XMITED_UNCOMPRESSED] -
  637. pdw[MAX_STATISTICS + BYTES_XMITED_COMPRESSED];
  638. pstats->RDS_ErrCRC =
  639. pdw[MAX_STATISTICS + CRC_ERR];
  640. pstats->RDS_ErrTimeout =
  641. pdw[MAX_STATISTICS + TIMEOUT_ERR];
  642. pstats->RDS_ErrAlignment =
  643. pdw[MAX_STATISTICS + ALIGNMENT_ERR];
  644. pstats->RDS_ErrFraming =
  645. pdw[MAX_STATISTICS + FRAMING_ERR];
  646. pstats->RDS_ErrHwOverruns =
  647. pdw[MAX_STATISTICS + HARDWARE_OVERRUN_ERR];
  648. pstats->RDS_ErrBufOverruns =
  649. pdw[MAX_STATISTICS + BUFFER_OVERRUN_ERR];
  650. #if 0
  651. TRACE4(
  652. "RasBundleGetStatistics(rx=%d,tx=%d,rxb=%d,txb=%d)",
  653. pstats->RDS_InBytes, pstats->RDS_OutBytes,
  654. pstats->RDS_InBytesTotal, pstats->RDS_OutBytesTotal
  655. );
  656. #endif
  657. //
  658. // Compute compression ratios, using the bundle-stats
  659. //
  660. pstats->RDS_InCompRatio = 0;
  661. dwGone = 0;
  662. dwB = pdw[BYTES_RCVED];
  663. dwBC = pdw[BYTES_RCVED_COMPRESSED];
  664. dwBU = pdw[BYTES_RCVED_UNCOMPRESSED];
  665. if (dwBC < dwBU) { dwGone = dwBU - dwBC; }
  666. if (dwB + dwGone > 100) {
  667. DWORD dwDen = (dwB + dwGone) / 100;
  668. pstats->RDS_InCompRatio = (dwGone + (dwDen / 2)) / dwDen;
  669. }
  670. pstats->RDS_OutCompRatio = 0;
  671. dwGone = 0;
  672. dwB = pdw[BYTES_XMITED];
  673. dwBC = pdw[BYTES_XMITED_COMPRESSED];
  674. dwBU = pdw[BYTES_XMITED_UNCOMPRESSED];
  675. if (dwBC < dwBU) { dwGone = dwBU - dwBC; }
  676. if (dwB + dwGone > 100) {
  677. DWORD dwDen = (dwB + dwGone) / 100;
  678. pstats->RDS_OutCompRatio = (dwGone + (dwDen / 2)) / dwDen;
  679. }
  680. return NO_ERROR;
  681. }
  682. DWORD
  683. GetRasdevTable(
  684. OUT RASDEV** ppDevTable,
  685. OUT DWORD* piDevCount )
  686. /* Gets an array of RAS devices configured. Loads '*ppDevTable' with a
  687. ** heap block of '*ppDevTable' entries. On NT, this is essentially the
  688. ** output of GetRasPorts(), in a format which includes a devicename,
  689. ** flags, and a handle. Given a RASMAN_PORT structure, we append the
  690. ** device and port names to make a unique device string which is part of
  691. ** the output.
  692. **
  693. ** Returns 0 if successful, or an error.
  694. **
  695. ** (Abolade Gbadegesin Nov-9-1995)
  696. */
  697. {
  698. DWORD dwPortCount;
  699. DWORD i, iLength, dwErr;
  700. RASDEV *pDevTable, *pdev;
  701. PTSTR pszDevice, pszPort;
  702. TCHAR szDevice[RAS_MaxDeviceName + 1];
  703. RASMAN_PORT *pPortTable, *pport;
  704. //
  705. // validate the arguments
  706. //
  707. if (ppDevTable == NULL || piDevCount == NULL) {
  708. return ERROR_INVALID_PARAMETER;
  709. }
  710. *piDevCount = 0;
  711. *ppDevTable = NULL;
  712. //
  713. // get a table of ports from RASMAN; the string fields are ANSI
  714. //
  715. dwErr = GetRasPorts(NULL, &pPortTable, &dwPortCount);
  716. if (dwErr != NO_ERROR) { return dwErr; }
  717. if (dwPortCount == 0) { return NO_ERROR; }
  718. //
  719. // allocate space for as many device structs as there are ports
  720. //
  721. pDevTable = Malloc(dwPortCount * sizeof(RASDEV));
  722. if (pDevTable == NULL) {
  723. Free(pPortTable);
  724. return ERROR_NOT_ENOUGH_MEMORY;
  725. }
  726. ZeroMemory(pDevTable, dwPortCount * sizeof(RASDEV));
  727. //
  728. // convert each RASMAN_PORT structure to a RASDEV structure.
  729. //
  730. for (i = 0, pport = pPortTable; i < dwPortCount; i++, pport++) {
  731. pdev = pDevTable + i;
  732. //
  733. // copy over code-page-independent fields
  734. //
  735. pdev->RD_Handle = pport->P_Handle;
  736. if (pport->P_ConfiguredUsage & CALL_IN)
  737. pdev->RD_Flags |= RDFLAG_DialIn;
  738. if (pport->P_ConfiguredUsage & CALL_OUT)
  739. pdev->RD_Flags |= RDFLAG_DialOut;
  740. if (pport->P_ConfiguredUsage & CALL_ROUTER)
  741. pdev->RD_Flags |= RDFLAG_Router;
  742. if (pport->P_CurrentUsage & CALL_IN)
  743. pdev->RD_Flags |= RDFLAG_IsDialedIn;
  744. if (pport->P_CurrentUsage & CALL_OUT)
  745. pdev->RD_Flags |= RDFLAG_IsDialedOut;
  746. if (pport->P_CurrentUsage & CALL_ROUTER)
  747. pdev->RD_Flags |= RDFLAG_IsRouter;
  748. //
  749. // copy the device-type string
  750. //
  751. #ifdef UNICODE
  752. StrCpyWFromAUsingAnsiEncoding(
  753. pdev->RD_DeviceType,
  754. pport->P_DeviceType,
  755. RAS_MaxDeviceType);
  756. #else
  757. lstrcpy(pdev->RD_DeviceType, pport->P_DeviceType);
  758. #endif
  759. //
  760. // copy the device-name and portname,
  761. // storing them in temporary strings
  762. //
  763. #ifdef UNICODE
  764. StrCpyWFromAUsingAnsiEncoding(
  765. szDevice,
  766. pport->P_DeviceName,
  767. RAS_MaxDeviceName);
  768. StrCpyWFromAUsingAnsiEncoding(
  769. pdev->RD_PortName,
  770. pport->P_PortName,
  771. MAX_PORT_NAME);
  772. pszDevice = szDevice;
  773. pszPort = pdev->RD_PortName;
  774. #else
  775. pszDevice = pport->P_DeviceName;
  776. lstrcpyn(pdev->RD_PortName, pport->P_PortName, MAX_PORT_NAME + 1);
  777. pszPort = pdev->RD_PortName;
  778. #endif
  779. //
  780. // get a display name from the device and port names
  781. //
  782. pdev->RD_DeviceName = PszFromDeviceAndPort(pszDevice, pszPort);
  783. if (pdev->RD_DeviceName == NULL) {
  784. Free(pPortTable);
  785. FreeRasdevTable(pDevTable, dwPortCount);
  786. return ERROR_NOT_ENOUGH_MEMORY;
  787. }
  788. }
  789. Free(pPortTable);
  790. *ppDevTable = pDevTable;
  791. *piDevCount = dwPortCount;
  792. return NO_ERROR;
  793. }
  794. DWORD
  795. GetRasMessage(
  796. IN HRASCONN hrasconn,
  797. OUT TCHAR** ppszMessage )
  798. /* Loads caller's '*ppszMessage' with the address of a heap block
  799. ** containing the current MXS_MESSAGE_KEY value associated with RAS
  800. ** connection 'hrasconn'.
  801. **
  802. ** Returns 0 if successful or an error code. It is caller's
  803. ** responsibility to Free the returned string.
  804. */
  805. {
  806. DWORD dwErr;
  807. RASCONNSTATUS rcs;
  808. CHAR* pszMessage;
  809. TRACE("GetRasMessage");
  810. *ppszMessage = 0;
  811. ZeroMemory( &rcs, sizeof(rcs) );
  812. rcs.dwSize = sizeof(rcs);
  813. ASSERT(g_pRasGetConnectStatus);
  814. TRACE("RasGetConnectStatus");
  815. dwErr = g_pRasGetConnectStatus( hrasconn, &rcs );
  816. TRACE1("RasGetConnectStatus=%d",dwErr);
  817. if (dwErr == 0)
  818. {
  819. CHAR* pszDeviceTypeA;
  820. CHAR* pszDeviceNameA;
  821. pszDeviceTypeA = StrDupAFromT( rcs.szDeviceType );
  822. pszDeviceNameA = StrDupAFromT( rcs.szDeviceName );
  823. if (!pszDeviceTypeA || !pszDeviceNameA)
  824. {
  825. Free0( pszDeviceNameA );
  826. return ERROR_NOT_ENOUGH_MEMORY;
  827. }
  828. dwErr = GetRasDeviceString(
  829. g_pRasGetHport( hrasconn ), pszDeviceTypeA, pszDeviceNameA,
  830. MXS_MESSAGE_KEY, &pszMessage, XLATE_ErrorResponse );
  831. Free0( pszDeviceTypeA );
  832. Free0( pszDeviceNameA );
  833. if (dwErr == 0)
  834. {
  835. *ppszMessage = StrDupTFromA( pszMessage );
  836. if (!*ppszMessage)
  837. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  838. Free0( pszMessage );
  839. }
  840. }
  841. return dwErr;
  842. }
  843. DWORD
  844. GetRasPads(
  845. OUT RASMAN_DEVICE** ppDevices,
  846. OUT DWORD* pdwEntries )
  847. /* Fills caller's '*ppDevices' with the address of a heap block containing
  848. ** '*pwEntries' X.25 PAD DEVICE structures.
  849. **
  850. ** Returns 0 if successful, otherwise a non-0 error code. If successful,
  851. ** it is the caller's responsibility to free the returned memory block.
  852. */
  853. {
  854. return GetRasDevices( NULL, MXS_PAD_TXT, ppDevices, pdwEntries );
  855. }
  856. VOID
  857. GetRasPortMaxBps(
  858. IN HPORT hport,
  859. OUT DWORD* pdwMaxConnectBps,
  860. OUT DWORD* pdwMaxCarrierBps )
  861. /* Loads callers '*pdwMaxConnectBps' with the maximum port->modem bps rate
  862. ** for port 'pport', or with 0 if not found. '*pdwMaxCarrierBps' is the
  863. ** same but for maximum modem->modem speed.
  864. */
  865. {
  866. CHAR* pszValue = NULL;
  867. DWORD dwErr;
  868. TRACE("GetRasPortMaxBps");
  869. dwErr = GetRasPortString(
  870. hport, SER_CONNECTBPS_KEY, &pszValue, XLATE_None );
  871. if (dwErr == 0)
  872. *pdwMaxConnectBps = (DWORD )atol( pszValue );
  873. else
  874. *pdwMaxConnectBps = 0;
  875. Free0(pszValue);
  876. pszValue = NULL;
  877. dwErr = GetRasPortString(
  878. hport, SER_CARRIERBPS_KEY, &pszValue, XLATE_None );
  879. if (dwErr == 0)
  880. *pdwMaxCarrierBps = (DWORD )atol( pszValue );
  881. else
  882. *pdwMaxCarrierBps = 0;
  883. Free0(pszValue);
  884. }
  885. VOID
  886. GetRasPortModemSettings(
  887. IN HPORT hport,
  888. OUT BOOL* pfHwFlowDefault,
  889. OUT BOOL* pfEcDefault,
  890. OUT BOOL* pfEccDefault )
  891. /* Loads caller's flags with the default setting of Hardware Flow Control,
  892. ** Error Control, and Error Control and Compression for the given 'hport'.
  893. */
  894. {
  895. CHAR* pszValue = NULL;
  896. *pfHwFlowDefault = TRUE;
  897. *pfEcDefault = TRUE;
  898. *pfEccDefault = TRUE;
  899. if (GetRasPortString(
  900. hport, SER_C_DEFAULTOFFSTR_KEY, &pszValue, XLATE_None ) == 0)
  901. {
  902. if (StrStrA( pszValue, MXS_HDWFLOWCONTROL_KEY ) != NULL)
  903. *pfHwFlowDefault = FALSE;
  904. if (StrStrA( pszValue, MXS_PROTOCOL_KEY ) != NULL)
  905. *pfEcDefault = FALSE;
  906. if (StrStrA( pszValue, MXS_COMPRESSION_KEY ) != NULL)
  907. *pfEccDefault = FALSE;
  908. Free0( pszValue );
  909. }
  910. }
  911. DWORD
  912. GetRasPortParam(
  913. IN HPORT hport,
  914. IN CHAR* pszKey,
  915. OUT RASMAN_PORTINFO** ppPortInfo,
  916. OUT RAS_PARAMS** ppParam )
  917. /* Loads callers '*ppParam' with the address of a RAS_PARAM block
  918. ** associated with key 'pszKey', or NULL if none. 'ppPortInfo' is the
  919. ** address of the array of RAS_PARAMS containing the found 'pparam'.
  920. **
  921. ** Returns 0 if successful, otherwise a non-0 error code. If successful,
  922. ** it is the caller's responsibility to Free the returned '*ppPortInfo'.
  923. */
  924. {
  925. DWORD dwErr = 0;
  926. DWORD dwSize = 0;
  927. INT i;
  928. TRACE("GetRasPortParam");
  929. *ppPortInfo = NULL;
  930. do
  931. {
  932. ASSERT(g_pRasPortGetInfo);
  933. TRACE("RasPortGetInfo");
  934. dwErr = g_pRasPortGetInfo(NULL, hport, NULL, &dwSize );
  935. TRACE2("RasPortGetInfo=%d,s=%d",dwErr,(INT)dwSize);
  936. if (dwErr != ERROR_BUFFER_TOO_SMALL && dwErr != 0)
  937. break;
  938. /* So it will fall thru and be "not found".
  939. */
  940. if (dwSize == 0)
  941. dwSize = 1;
  942. *ppPortInfo = (RASMAN_PORTINFO* )Malloc( dwSize );
  943. if (!*ppPortInfo)
  944. return ERROR_NOT_ENOUGH_MEMORY;
  945. TRACE("RasPortGetInfo");
  946. dwErr = g_pRasPortGetInfo(NULL, hport, (PBYTE )*ppPortInfo, &dwSize );
  947. TRACE2("RasPortGetInfo=%d,s=%d",dwErr,(INT)dwSize);
  948. if (dwErr != 0)
  949. break;
  950. for (i = 0, *ppParam = (*ppPortInfo)->PI_Params;
  951. i < (INT )(*ppPortInfo)->PI_NumOfParams;
  952. ++i, ++(*ppParam))
  953. {
  954. if (lstrcmpiA( (*ppParam)->P_Key, pszKey ) == 0)
  955. break;
  956. }
  957. if (i >= (INT )(*ppPortInfo)->PI_NumOfParams)
  958. dwErr = ERROR_KEY_NOT_FOUND;
  959. }
  960. while (FALSE);
  961. return dwErr;
  962. }
  963. DWORD
  964. GetRasPorts(
  965. IN HANDLE hConnection,
  966. OUT RASMAN_PORT** ppPorts,
  967. OUT DWORD* pdwEntries )
  968. /* Enumerate RAS ports. Sets '*ppPort' to the address of a heap memory
  969. ** block containing an array of PORT structures with '*pwEntries'
  970. ** elements.
  971. **
  972. ** Returns 0 if successful, otherwise a non-0 error code. If successful,
  973. ** it is the caller's responsibility to free the returned memory block.
  974. */
  975. {
  976. DWORD dwSize = 0;
  977. DWORD dwErr;
  978. TRACE("GetRasPorts");
  979. #if DUMMYPORTS
  980. {
  981. RASMAN_PORT* pPort;
  982. DWORD c;
  983. TRACE("TEST: Fake ISDN ports");
  984. *pdwEntries = c = g_cPorts;
  985. dwSize = *pdwEntries * sizeof(RASMAN_PORT);
  986. *ppPorts = (RASMAN_PORT* )Malloc( dwSize );
  987. if (!*ppPorts)
  988. return ERROR_NOT_ENOUGH_MEMORY;
  989. do
  990. {
  991. pPort = *ppPorts;
  992. ZeroMemory( pPort, sizeof(*pPort) );
  993. lstrcpyA( pPort->P_PortName, "COM1" );
  994. pPort->P_Status = CLOSED;
  995. pPort->P_ConfiguredUsage = CALL_OUT;
  996. pPort->P_CurrentUsage = CALL_OUT;
  997. lstrcpyA( pPort->P_MediaName, "rasser" );
  998. lstrcpyA( pPort->P_DeviceName, "US Robotics Courier V32 bis" );
  999. lstrcpyA( pPort->P_DeviceType, "MODEM" );
  1000. if (--c == 0)
  1001. break;
  1002. ++pPort;
  1003. ZeroMemory( pPort, sizeof(*pPort) );
  1004. lstrcpyA( pPort->P_PortName, "ISDN1" );
  1005. pPort->P_Status = CLOSED;
  1006. pPort->P_ConfiguredUsage = CALL_OUT;
  1007. pPort->P_CurrentUsage = CALL_OUT;
  1008. lstrcpyA( pPort->P_MediaName, "rastapi" );
  1009. lstrcpyA( pPort->P_DeviceName, "Digiboard PCIMac ISDN adapter" );
  1010. lstrcpyA( pPort->P_DeviceType, "ISDN" );
  1011. if (--c == 0)
  1012. break;
  1013. ++pPort;
  1014. ZeroMemory( pPort, sizeof(*pPort) );
  1015. lstrcpyA( pPort->P_PortName, "ISDN2" );
  1016. pPort->P_Status = CLOSED;
  1017. pPort->P_ConfiguredUsage = CALL_OUT;
  1018. pPort->P_CurrentUsage = CALL_OUT;
  1019. lstrcpyA( pPort->P_MediaName, "rastapi" );
  1020. lstrcpyA( pPort->P_DeviceName, "Digiboard PCIMac ISDN adapter" );
  1021. lstrcpyA( pPort->P_DeviceType, "ISDN" );
  1022. if (--c == 0)
  1023. break;
  1024. ++pPort;
  1025. ZeroMemory( pPort, sizeof(*pPort) );
  1026. lstrcpyA( pPort->P_PortName, "COM500" );
  1027. pPort->P_Status = CLOSED;
  1028. pPort->P_ConfiguredUsage = CALL_OUT;
  1029. pPort->P_CurrentUsage = CALL_OUT;
  1030. lstrcpyA( pPort->P_MediaName, "rasser" );
  1031. lstrcpyA( pPort->P_DeviceName, "Eicon X.PAD" );
  1032. lstrcpyA( pPort->P_DeviceType, "PAD" );
  1033. if (--c == 0)
  1034. break;
  1035. ++pPort;
  1036. ZeroMemory( pPort, sizeof(*pPort) );
  1037. lstrcpyA( pPort->P_PortName, "X251" );
  1038. pPort->P_Status = CLOSED;
  1039. pPort->P_ConfiguredUsage = CALL_OUT;
  1040. pPort->P_CurrentUsage = CALL_OUT;
  1041. lstrcpyA( pPort->P_MediaName, "rastapi" );
  1042. lstrcpyA( pPort->P_DeviceName, "Digiboard X.25 adapter" );
  1043. lstrcpyA( pPort->P_DeviceType, "X25" );
  1044. if (--c == 0)
  1045. break;
  1046. ++pPort;
  1047. ZeroMemory( pPort, sizeof(*pPort) );
  1048. lstrcpyA( pPort->P_PortName, "VPN1" );
  1049. pPort->P_Status = CLOSED;
  1050. pPort->P_ConfiguredUsage = CALL_OUT;
  1051. pPort->P_CurrentUsage = CALL_OUT;
  1052. lstrcpyA( pPort->P_MediaName, "rastapi" );
  1053. lstrcpyA( pPort->P_DeviceName, "RASPPTPM" );
  1054. lstrcpyA( pPort->P_DeviceType, "VPN1" );
  1055. if (--c == 0)
  1056. break;
  1057. }
  1058. while (FALSE);
  1059. }
  1060. #else
  1061. ASSERT(g_pRasPortEnum);
  1062. TRACE("RasPortEnum...");
  1063. dwErr = g_pRasPortEnum(hConnection, NULL, &dwSize, pdwEntries );
  1064. TRACE2("RasPortEnum=%d,c=%d",dwErr,(INT)*pdwEntries);
  1065. if (dwErr == 0)
  1066. {
  1067. /* No ports to enumerate. Set up to allocate a single byte anyway, so
  1068. ** things work without lots of special code.
  1069. */
  1070. dwSize = 1;
  1071. }
  1072. else if (dwErr != ERROR_BUFFER_TOO_SMALL)
  1073. return dwErr;
  1074. *ppPorts = (RASMAN_PORT* )Malloc( dwSize );
  1075. if (!*ppPorts)
  1076. return ERROR_NOT_ENOUGH_MEMORY;
  1077. TRACE("RasPortEnum...");
  1078. dwErr = g_pRasPortEnum(hConnection, (PBYTE )*ppPorts, &dwSize, pdwEntries );
  1079. TRACE2("RasPortEnum=%d,c=%d",dwErr,(INT)*pdwEntries);
  1080. if (dwErr != 0)
  1081. {
  1082. Free( *ppPorts );
  1083. *ppPorts = NULL;
  1084. return dwErr;
  1085. }
  1086. #endif
  1087. #if 1 // Verbose trace
  1088. {
  1089. RASMAN_PORT* pPort;
  1090. DWORD i;
  1091. for (pPort = *ppPorts, i = 0; i < *pdwEntries; ++i, ++pPort)
  1092. {
  1093. TRACE4("Port[%d]=%s,DID=$%08x,AID=$%08x",
  1094. pPort->P_Handle,pPort->P_PortName,
  1095. pPort->P_LineDeviceId,pPort->P_AddressId);
  1096. TRACE3(" M=%s,DT=%s,DN=%s",
  1097. pPort->P_MediaName,pPort->P_DeviceType,pPort->P_DeviceName);
  1098. TRACE3(" S=$%08x,CfgU=$%08x,CurU=$%08x",
  1099. pPort->P_Status,pPort->P_ConfiguredUsage,pPort->P_CurrentUsage);
  1100. }
  1101. }
  1102. #endif
  1103. return 0;
  1104. }
  1105. DWORD
  1106. GetRasPortString(
  1107. IN HPORT hport,
  1108. IN CHAR* pszKey,
  1109. OUT CHAR** ppszValue,
  1110. IN DWORD dwXlate )
  1111. /* Loads callers '*ppszValue' with the address of a heap block containing
  1112. ** a NUL-terminated copy of the value string associated with key 'pszKey'
  1113. ** on port 'hport'. 'dwXlate' is a bit mask of XLATE_ bits specifying
  1114. ** translations to be done on the string value.
  1115. **
  1116. ** Returns 0 if successful, otherwise a non-0 error code. If successful,
  1117. ** it is the caller's responsibility to Free the returned string.
  1118. */
  1119. {
  1120. RASMAN_PORTINFO* pPortInfo;
  1121. RAS_PARAMS* pParam;
  1122. DWORD dwErr;
  1123. TRACE("GetRasPortString");
  1124. dwErr = GetRasPortParam( hport, pszKey, &pPortInfo, &pParam );
  1125. *ppszValue = NULL;
  1126. if (dwErr == 0)
  1127. {
  1128. *ppszValue = PszFromRasValue( &pParam->P_Value, dwXlate );
  1129. dwErr = (*ppszValue) ? 0 : ERROR_NOT_ENOUGH_MEMORY;
  1130. }
  1131. Free0( pPortInfo );
  1132. return dwErr;
  1133. }
  1134. DWORD
  1135. GetRasSwitches(
  1136. IN HANDLE hConnection,
  1137. OUT RASMAN_DEVICE** ppDevices,
  1138. OUT DWORD* pdwEntries )
  1139. /* Fills caller's '*ppDevices' with the address of a heap block containing
  1140. ** '*pwEntries' switch DEVICE structures.
  1141. **
  1142. ** Returns 0 if successful, otherwise a non-0 error code. If successful,
  1143. ** it is the caller's responsibility to free the returned memory block.
  1144. */
  1145. {
  1146. return GetRasDevices( hConnection, MXS_SWITCH_TXT, ppDevices, pdwEntries );
  1147. }
  1148. DWORD
  1149. GetRasUnimodemBlob(
  1150. IN HANDLE hConnection,
  1151. IN HPORT hport,
  1152. IN CHAR* pszDeviceType,
  1153. OUT BYTE** ppBlob,
  1154. OUT DWORD* pcbBlob )
  1155. {
  1156. return GetRasUnimodemBlobEx(
  1157. hConnection,
  1158. hport,
  1159. pszDeviceType,
  1160. FALSE,
  1161. ppBlob,
  1162. pcbBlob);
  1163. }
  1164. DWORD
  1165. GetRasUnimodemBlobEx(
  1166. IN HANDLE hConnection,
  1167. IN HPORT hport,
  1168. IN CHAR* pszDeviceType,
  1169. IN BOOL fGlobal,
  1170. OUT BYTE** ppBlob,
  1171. OUT DWORD* pcbBlob )
  1172. /* Loads '*ppBlob' and '*pcbBlob' with the sanitized Unimodem blob and
  1173. ** size associated with 'hport' and 'pszDeviceType'. It is caller's
  1174. ** responsibility to Free the returned '*ppBlob'.
  1175. **
  1176. ** Returns 0 if successful, or an error code.
  1177. */
  1178. {
  1179. DWORD dwErr;
  1180. BYTE* pBlob;
  1181. DWORD cbBlob;
  1182. PRASGETDEVCONFIG pFunc;
  1183. CHAR* pszFuncName;
  1184. cbBlob = 0;
  1185. pFunc = (fGlobal) ? g_pRasGetDevConfigEx : g_pRasGetDevConfig;
  1186. pszFuncName = (fGlobal) ? "RasGetDevConfigEx" : "RasGetDevConfig";
  1187. ASSERT(pFunc);
  1188. TRACE(pszFuncName);
  1189. dwErr = pFunc(hConnection, hport, pszDeviceType, NULL, &cbBlob );
  1190. TRACE2("%s=%d", pszFuncName, dwErr);
  1191. if (dwErr != 0 && dwErr != ERROR_BUFFER_TOO_SMALL)
  1192. return dwErr;
  1193. if (cbBlob > 0)
  1194. {
  1195. pBlob = Malloc( cbBlob );
  1196. if (!pBlob)
  1197. return ERROR_NOT_ENOUGH_MEMORY;
  1198. TRACE(pszFuncName);
  1199. dwErr = pFunc(hConnection, hport, pszDeviceType, pBlob, &cbBlob );
  1200. TRACE2("%s=%d", pszFuncName, dwErr);
  1201. if (dwErr != 0)
  1202. {
  1203. Free( pBlob );
  1204. return dwErr;
  1205. }
  1206. SanitizeUnimodemBlob( pBlob );
  1207. }
  1208. else
  1209. pBlob = NULL;
  1210. *ppBlob = pBlob;
  1211. *pcbBlob = cbBlob;
  1212. return dwErr;
  1213. }
  1214. VOID
  1215. GetRasUnimodemInfo(
  1216. IN HANDLE hConnection,
  1217. IN HPORT hport,
  1218. IN CHAR* pszDeviceType,
  1219. OUT UNIMODEMINFO* pInfo )
  1220. /* Loads 'pInfo' with the RAS-relevant information of the port 'hport'
  1221. ** with device name 'pszDeviceName'.
  1222. */
  1223. {
  1224. DWORD dwErr;
  1225. BYTE* pBlob = NULL;
  1226. DWORD cbBlob = 0;
  1227. SetDefaultUnimodemInfo( pInfo );
  1228. dwErr = GetRasUnimodemBlob(
  1229. hConnection,
  1230. hport,
  1231. pszDeviceType,
  1232. &pBlob,
  1233. &cbBlob );
  1234. if (dwErr == 0 && cbBlob > 0)
  1235. UnimodemInfoFromBlob( pBlob, pInfo );
  1236. Free0( pBlob );
  1237. }
  1238. TCHAR*
  1239. GetRasX25Diagnostic(
  1240. IN HRASCONN hrasconn )
  1241. /* Returns the X.25 diagnostics string or NULL if none. It is caller's
  1242. ** responsibility to Free the returned string.
  1243. */
  1244. {
  1245. DWORD dwErr;
  1246. HPORT hport;
  1247. RASMAN_INFO info;
  1248. CHAR* pszDiagnosticA = NULL;
  1249. TCHAR* pszDiagnostic = NULL;
  1250. pszDiagnosticA = NULL;
  1251. hport = g_pRasGetHport( hrasconn );
  1252. ASSERT(g_pRasGetInfo);
  1253. TRACE1("RasGetInfo(%d)",hport);
  1254. dwErr = g_pRasGetInfo( NULL, hport, &info );
  1255. TRACE1("RasGetInfo=%d",dwErr);
  1256. /* Error codes are ignored here since the diagnosistic
  1257. ** is informational only. If they fail the diagnostic
  1258. ** will simply appear blank.
  1259. */
  1260. if (dwErr == 0)
  1261. {
  1262. GetRasDeviceString(
  1263. hport, info.RI_DeviceTypeConnecting,
  1264. info.RI_DeviceConnecting, MXS_DIAGNOSTICS_KEY,
  1265. &pszDiagnosticA, XLATE_Diagnostic );
  1266. }
  1267. if(NULL != pszDiagnosticA)
  1268. {
  1269. pszDiagnostic = StrDupTFromA( pszDiagnosticA );
  1270. Free( pszDiagnosticA );
  1271. }
  1272. return pszDiagnostic;
  1273. }
  1274. BOOL
  1275. IsRasdevBundled(
  1276. IN RASDEV* pdev,
  1277. IN RASDEV* pDevTable,
  1278. IN DWORD iDevCount
  1279. )
  1280. /* Determines whether the device described by 'pdev' is bundled,
  1281. ** by looking for another device in 'pDevTable' which has the same bundle
  1282. ** as 'pdev'.
  1283. **
  1284. ** Returnes TRUE if the device is bundled, FALSE otherwise.
  1285. */
  1286. {
  1287. DWORD i;
  1288. RASDEV* pdev2;
  1289. DWORD dwBundle;
  1290. //
  1291. // First get the device's bundle;
  1292. // If this fails, assume it is not connected and return FALSE.
  1293. //
  1294. if (GetRasdevBundle(pdev, &dwBundle) != NO_ERROR) { return FALSE; }
  1295. //
  1296. // Walk through the other devices in the table, looking for one
  1297. // with the same bundle.
  1298. //
  1299. for (i = 0, pdev2 = pDevTable;
  1300. i < iDevCount; i++, pdev2++) {
  1301. DWORD dwBundle2;
  1302. //
  1303. // skip this if it is the device we already know about
  1304. //
  1305. if (pdev->RD_Handle == pdev2->RD_Handle) { continue; }
  1306. //
  1307. // get the bundle
  1308. //
  1309. if (GetRasdevBundle(pdev2, &dwBundle2) != NO_ERROR) { continue; }
  1310. //
  1311. // if the bundle is the same, we know its multilinked
  1312. //
  1313. if (dwBundle == dwBundle2) { return TRUE; }
  1314. }
  1315. return FALSE;
  1316. }
  1317. CHAR*
  1318. PszFromRasValue(
  1319. IN RAS_VALUE* prasvalue,
  1320. IN DWORD dwXlate )
  1321. /* Returns the address of a heap block containing a NUL-terminated string
  1322. ** value from caller's '*prasvalue', or NULL if out of memory. 'dwXlate'
  1323. ** is a bit mask of XLATE_ bits specifying translations to be performed on
  1324. ** the string. The value is assumed to be of format String. It is
  1325. ** translated to modem.inf style.
  1326. */
  1327. {
  1328. #define MAXEXPANDPERCHAR 5
  1329. #define HEXCHARS "0123456789ABCDEF"
  1330. INT i;
  1331. BOOL fXlate;
  1332. BOOL fXlateCtrl;
  1333. BOOL fXlateCr;
  1334. BOOL fXlateCrSpecial;
  1335. BOOL fXlateLf;
  1336. BOOL fXlateLfSpecial;
  1337. BOOL fXlateLAngle;
  1338. BOOL fXlateRAngle;
  1339. BOOL fXlateBSlash;
  1340. BOOL fXlateSSpace;
  1341. BOOL fNoCharSinceLf;
  1342. INT nLen;
  1343. CHAR* pszIn = NULL;
  1344. CHAR* pszBuf = NULL;
  1345. CHAR* pszOut = NULL;
  1346. CHAR* pszTemp = NULL;
  1347. nLen = prasvalue->String.Length;
  1348. pszIn = prasvalue->String.Data;
  1349. pszBuf = Malloc( (nLen * MAXEXPANDPERCHAR) + 1 );
  1350. if (!pszBuf)
  1351. return NULL;
  1352. /* Translate the returned string based on the translation bit map. The
  1353. ** assumption here is that all these devices talk ASCII and not some
  1354. ** localized ANSI.
  1355. */
  1356. fXlate = (dwXlate != 0);
  1357. fXlateCtrl = (dwXlate & XLATE_Ctrl);
  1358. fXlateCr = (dwXlate & XLATE_Cr);
  1359. fXlateCrSpecial = (dwXlate & XLATE_CrSpecial);
  1360. fXlateLf = (dwXlate & XLATE_Lf);
  1361. fXlateLfSpecial = (dwXlate & XLATE_LfSpecial);
  1362. fXlateLAngle = (dwXlate & XLATE_LAngle);
  1363. fXlateRAngle = (dwXlate & XLATE_RAngle);
  1364. fXlateBSlash = (dwXlate & XLATE_BSlash);
  1365. fXlateSSpace = (dwXlate & XLATE_SSpace);
  1366. pszOut = pszBuf;
  1367. fNoCharSinceLf = TRUE;
  1368. for (i = 0; i < nLen; ++i)
  1369. {
  1370. CHAR ch = pszIn[ i ];
  1371. if (fXlate)
  1372. {
  1373. if (ch == 0x0D)
  1374. {
  1375. if (fXlateSSpace && fNoCharSinceLf)
  1376. continue;
  1377. if (fXlateCrSpecial)
  1378. {
  1379. /* Special symbol for carriage return.
  1380. */
  1381. lstrcpyA( pszOut, "<cr>" );
  1382. pszOut += 4;
  1383. continue;
  1384. }
  1385. }
  1386. if (ch == 0x0A)
  1387. {
  1388. if (fXlateSSpace && fNoCharSinceLf)
  1389. continue;
  1390. fNoCharSinceLf = TRUE;
  1391. if (fXlateLfSpecial)
  1392. {
  1393. /* Special symbol for line feed.
  1394. */
  1395. lstrcpyA( pszOut, "<lf>" );
  1396. pszOut += 4;
  1397. continue;
  1398. }
  1399. }
  1400. if (ch != 0x0A && ch != 0x0D)
  1401. fNoCharSinceLf = FALSE;
  1402. if ((((ch < 0x20 || ch > 0x7E)
  1403. && ch != 0x0D && ch != 0x0A) && fXlateCtrl)
  1404. || (ch == 0x0D && fXlateCr)
  1405. || (ch == 0x0A && fXlateLf)
  1406. || (ch == 0x3C && fXlateLAngle)
  1407. || (ch == 0x3E && fXlateRAngle)
  1408. || (ch == 0x5C && fXlateBSlash))
  1409. {
  1410. /* Expand to "dump" form, i.e. <hFF> where FF is the hex value
  1411. ** of the character.
  1412. */
  1413. *pszOut++ = '<';
  1414. *pszOut++ = 'h';
  1415. *pszOut++ = HEXCHARS[ ch / 16 ];
  1416. *pszOut++ = HEXCHARS[ ch % 16 ];
  1417. *pszOut++ = '>';
  1418. continue;
  1419. }
  1420. }
  1421. /* Just copy without translation.
  1422. */
  1423. *pszOut++ = ch;
  1424. }
  1425. *pszOut = '\0';
  1426. // For whistler 517011
  1427. //
  1428. pszTemp = Realloc( pszBuf, lstrlenA( pszBuf ) + 1 );
  1429. if(pszTemp)
  1430. {
  1431. pszBuf = pszTemp;
  1432. }
  1433. else
  1434. {
  1435. Free(pszBuf);
  1436. pszBuf = NULL;
  1437. }
  1438. return pszBuf;
  1439. }
  1440. VOID
  1441. SanitizeUnimodemBlob(
  1442. IN OUT BYTE* pBlob )
  1443. /* Fix non-RAS-compatible settings in unimodem blob 'pBlob'.
  1444. **
  1445. ** (Based on Gurdeepian routine)
  1446. */
  1447. {
  1448. DEVCFG* pDevCfg;
  1449. MODEMSETTINGS* pModemSettings;
  1450. RAS_DEVCONFIG* pRasDevCfg;
  1451. pRasDevCfg = (RAS_DEVCONFIG*)pBlob;
  1452. pDevCfg = (DEVCFG *)
  1453. ((PBYTE) pRasDevCfg + pRasDevCfg->dwOffsetofModemSettings);
  1454. pModemSettings = (MODEMSETTINGS* )(((BYTE* )&pDevCfg->commconfig)
  1455. + pDevCfg->commconfig.dwProviderOffset);
  1456. TRACE1(
  1457. "SanitizeUnimodemBlob: mdm prot=%d",
  1458. MDM_GET_EXTENDEDINFO(pModemSettings->dwPreferredModemOptions));
  1459. /* No unimodem service provider pre/post-connect terminal, operator dial,
  1460. ** or tray lights. RAS does these itself.
  1461. */
  1462. pDevCfg->dfgHdr.fwOptions = 0;
  1463. pDevCfg->commconfig.dcb.fBinary = TRUE;
  1464. pDevCfg->commconfig.dcb.fParity = TRUE;
  1465. pDevCfg->commconfig.dcb.fOutxDsrFlow = FALSE;
  1466. pDevCfg->commconfig.dcb.fDtrControl = DTR_CONTROL_ENABLE;
  1467. pDevCfg->commconfig.dcb.fTXContinueOnXoff = FALSE;
  1468. pDevCfg->commconfig.dcb.fOutX = FALSE;
  1469. pDevCfg->commconfig.dcb.fInX = FALSE;
  1470. pDevCfg->commconfig.dcb.fErrorChar = FALSE;
  1471. pDevCfg->commconfig.dcb.fNull = FALSE;
  1472. pDevCfg->commconfig.dcb.fAbortOnError = FALSE;
  1473. pDevCfg->commconfig.dcb.ByteSize = 8;
  1474. pDevCfg->commconfig.dcb.Parity = NOPARITY;
  1475. pDevCfg->commconfig.dcb.StopBits = ONESTOPBIT;
  1476. /* Wait 55 seconds to establish call.
  1477. */
  1478. /*
  1479. pModemSettings->dwCallSetupFailTimer = 55;
  1480. */
  1481. /* Disable inactivity timeout.
  1482. */
  1483. pModemSettings->dwInactivityTimeout = 0;
  1484. }
  1485. VOID
  1486. SetDefaultUnimodemInfo(
  1487. OUT UNIMODEMINFO* pInfo )
  1488. /* Sets 'pInfo' to default settings.
  1489. */
  1490. {
  1491. pInfo->fHwFlow = FALSE;
  1492. pInfo->fEc = FALSE;
  1493. pInfo->fEcc = FALSE;
  1494. pInfo->dwBps = 9600;
  1495. pInfo->fSpeaker = TRUE;
  1496. pInfo->fOperatorDial = FALSE;
  1497. pInfo->fUnimodemPreTerminal = FALSE;
  1498. }
  1499. VOID
  1500. UnimodemProtInfoFromExtendedCaps(
  1501. OUT UNIMODEMINFO* pInfo,
  1502. IN BYTE* pExtCapsBlob)
  1503. /* Loads the modem protocol info for 'pInfo' from the extended caps
  1504. ** blob retrieved from tapi.
  1505. **
  1506. */
  1507. {
  1508. MODEM_PROTOCOL_CAPS* lpProtCaps = NULL;
  1509. PROTOCOL_ITEM* pProtItem = NULL;
  1510. DWORD dwIndex;
  1511. do
  1512. {
  1513. // Extract the modem caps
  1514. //
  1515. lpProtCaps = (MODEM_PROTOCOL_CAPS *)pExtCapsBlob;
  1516. if (lpProtCaps->hdr.dwSig != dwSIG_MODEM_PROTOCOL_CAPS ||
  1517. lpProtCaps->dwNumProtocols == 0 ||
  1518. lpProtCaps->dwProtocolListOffset == 0)
  1519. {
  1520. break;
  1521. }
  1522. // If no protocols are supported, don't bother creating the
  1523. // list
  1524. if (lpProtCaps->dwNumProtocols == 0)
  1525. {
  1526. break;
  1527. }
  1528. // Create the list
  1529. //
  1530. pInfo->pListProtocols = DtlCreateList(0);
  1531. if (pInfo->pListProtocols == NULL)
  1532. {
  1533. break;
  1534. }
  1535. // Get the list of supported protocols
  1536. //
  1537. pProtItem = (PROTOCOL_ITEM*)
  1538. (((LPBYTE)lpProtCaps) + lpProtCaps->dwProtocolListOffset);
  1539. // Enumerate the protocols
  1540. //
  1541. for (dwIndex = 0;
  1542. dwIndex < lpProtCaps->dwNumProtocols;
  1543. dwIndex++, pProtItem++)
  1544. {
  1545. DTLNODE * pNode = NULL;
  1546. PWCHAR pszName = NULL;
  1547. DWORD dwSize;
  1548. // Get the friendly name from the structure
  1549. //
  1550. pszName = (PWCHAR)
  1551. (pExtCapsBlob + pProtItem->dwProtocolNameOffset);
  1552. if (pszName == NULL)
  1553. {
  1554. continue;
  1555. }
  1556. // Calculate the size of the friendly name
  1557. //
  1558. dwSize = (wcslen(pszName) + 1) * sizeof(WCHAR);
  1559. // Allocate a node accordingly
  1560. //
  1561. pNode =
  1562. DtlCreateSizedNode(dwSize, (LONG_PTR)pProtItem->dwProtocol);
  1563. if (pNode == NULL)
  1564. {
  1565. continue;
  1566. }
  1567. // Initialize the node and add it to the list
  1568. //
  1569. wcscpy((PWCHAR) DtlGetData(pNode), pszName);
  1570. DtlAddNodeLast(pInfo->pListProtocols, pNode);
  1571. }
  1572. } while (FALSE);
  1573. // Cleanup
  1574. {
  1575. }
  1576. }
  1577. VOID
  1578. UnimodemInfoFromBlob(
  1579. IN BYTE* pBlob,
  1580. OUT UNIMODEMINFO* pInfo )
  1581. /* Loads 'pInfo' with RAS-relevant Unimodem information retrieved from
  1582. ** Unimodem blob 'pBlob'.
  1583. **
  1584. ** (Based on Gurdeepian routine)
  1585. */
  1586. {
  1587. DEVCFG* pDevCfg;
  1588. MODEMSETTINGS* pModemSettings;
  1589. RAS_DEVCONFIG* pRasDevCfg;
  1590. pRasDevCfg = (RAS_DEVCONFIG*)pBlob;
  1591. pDevCfg = (DEVCFG *)
  1592. ((PBYTE) pRasDevCfg + pRasDevCfg->dwOffsetofModemSettings);
  1593. pModemSettings = (MODEMSETTINGS* )(((BYTE* )&pDevCfg->commconfig)
  1594. + pDevCfg->commconfig.dwProviderOffset);
  1595. pInfo->fSpeaker =
  1596. (pModemSettings->dwSpeakerMode != MDMSPKR_OFF)
  1597. ? TRUE : FALSE;
  1598. pInfo->fHwFlow =
  1599. (pModemSettings->dwPreferredModemOptions & MDM_FLOWCONTROL_HARD)
  1600. ? TRUE : FALSE;
  1601. pInfo->fEcc =
  1602. (pModemSettings->dwPreferredModemOptions & MDM_COMPRESSION)
  1603. ? TRUE : FALSE;
  1604. pInfo->fEc =
  1605. (pModemSettings->dwPreferredModemOptions & MDM_ERROR_CONTROL)
  1606. ? TRUE : FALSE;
  1607. pInfo->dwBps = pDevCfg->commconfig.dcb.BaudRate;
  1608. pInfo->fOperatorDial =
  1609. (pDevCfg->dfgHdr.fwOptions & MANUAL_DIAL)
  1610. ? TRUE : FALSE;
  1611. pInfo->fUnimodemPreTerminal =
  1612. (pDevCfg->dfgHdr.fwOptions & TERMINAL_PRE)
  1613. ? TRUE : FALSE;
  1614. // Get the modem protocol
  1615. //
  1616. pInfo->dwModemProtocol =
  1617. MDM_GET_EXTENDEDINFO(pModemSettings->dwPreferredModemOptions);
  1618. // Pull out the extended caps stuff
  1619. //
  1620. if ( pRasDevCfg->dwSizeofExtendedCaps )
  1621. {
  1622. UnimodemProtInfoFromExtendedCaps(
  1623. pInfo,
  1624. (BYTE*)(pBlob + pRasDevCfg->dwOffsetofExtendedCaps));
  1625. }
  1626. else
  1627. {
  1628. pInfo->pListProtocols = NULL;
  1629. }
  1630. }
  1631. VOID
  1632. UnimodemInfoToBlob(
  1633. IN UNIMODEMINFO* pInfo,
  1634. IN OUT BYTE* pBlob )
  1635. /* Applies RAS-relevant Unimodem information supplied in 'pInfo' to
  1636. ** Unimodem blob 'pBlob'.
  1637. **
  1638. ** (Based on Gurdeepian routine)
  1639. */
  1640. {
  1641. DEVCFG* pDevCfg;
  1642. MODEMSETTINGS* pModemSettings;
  1643. RAS_DEVCONFIG* pRasDevCfg;
  1644. pRasDevCfg = (RAS_DEVCONFIG*) pBlob;
  1645. // Pull out the device config stuff
  1646. //
  1647. pDevCfg = (DEVCFG *)
  1648. ((PBYTE) pRasDevCfg + pRasDevCfg->dwOffsetofModemSettings);
  1649. pModemSettings = (MODEMSETTINGS* )(((BYTE* )&pDevCfg->commconfig)
  1650. + pDevCfg->commconfig.dwProviderOffset);
  1651. pModemSettings->dwSpeakerMode =
  1652. (pInfo->fSpeaker) ? MDMSPKR_DIAL : MDMSPKR_OFF;
  1653. if (pInfo->fHwFlow)
  1654. {
  1655. pDevCfg->commconfig.dcb.fOutxCtsFlow = TRUE;
  1656. pDevCfg->commconfig.dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
  1657. pModemSettings->dwPreferredModemOptions |= MDM_FLOWCONTROL_HARD;
  1658. }
  1659. else
  1660. {
  1661. pDevCfg->commconfig.dcb.fOutxCtsFlow = FALSE;
  1662. pDevCfg->commconfig.dcb.fRtsControl = RTS_CONTROL_DISABLE;
  1663. pModemSettings->dwPreferredModemOptions &= ~(MDM_FLOWCONTROL_HARD);
  1664. }
  1665. if (pInfo->fEc)
  1666. pModemSettings->dwPreferredModemOptions |= MDM_ERROR_CONTROL;
  1667. else
  1668. pModemSettings->dwPreferredModemOptions &= ~(MDM_ERROR_CONTROL);
  1669. if (pInfo->fEcc)
  1670. pModemSettings->dwPreferredModemOptions |= MDM_COMPRESSION;
  1671. else
  1672. pModemSettings->dwPreferredModemOptions &= ~(MDM_COMPRESSION);
  1673. pDevCfg->commconfig.dcb.BaudRate = pInfo->dwBps;
  1674. if (pInfo->fOperatorDial)
  1675. pDevCfg->dfgHdr.fwOptions |= MANUAL_DIAL;
  1676. if (pInfo->fUnimodemPreTerminal)
  1677. pDevCfg->dfgHdr.fwOptions |= TERMINAL_PRE;
  1678. // Set the modem protocol
  1679. //
  1680. MDM_SET_EXTENDEDINFO(
  1681. pModemSettings->dwPreferredModemOptions,
  1682. pInfo->dwModemProtocol);
  1683. }
  1684. WCHAR *GetUnicodeName(HPORT hport)
  1685. {
  1686. WCHAR *pwsz = Malloc(sizeof(WCHAR) * (MAX_DEVICE_NAME + 1));
  1687. if(NULL != pwsz)
  1688. {
  1689. if(ERROR_SUCCESS != RasGetUnicodeDeviceName(
  1690. hport,
  1691. pwsz))
  1692. {
  1693. Free(pwsz);
  1694. pwsz = NULL;
  1695. }
  1696. }
  1697. return pwsz;
  1698. }