/* Copyright (c) 1995, Microsoft Corporation, all rights reserved ** ** rasman.c ** RAS Manager helpers ** Listed alphabetically ** ** These routines have been exempted from the TCHARizing applied to the rest ** of the library because RASMAN is still an ANSI interface. ** ** 09/20/95 Steve Cobb */ #include // Win32 root #include // for atol() #include // Trace/Assert library #include // Our public header #include // RAS error constants #include // Unimodem #include /* These types are described in MSDN and appear in Win95's unimdm.h private ** header (complete with typo) but not in any SDK headers. */ typedef struct tagDEVCFGGDR { DWORD dwSize; DWORD dwVersion; WORD fwOptions; WORD wWaitBong; } DEVCFGHDR; typedef struct tagDEVCFG { DEVCFGHDR dfgHdr; COMMCONFIG commconfig; } DEVCFG; #define MANUAL_DIAL 0x0004 #define TERMINAL_PRE 0x0001 // Test rig to return a variety of fake ports from GetRasPorts. // #define DUMMYPORTS 0 #if DUMMYPORTS DWORD g_cPorts = 6; #endif /*---------------------------------------------------------------------------- ** Local prototypes **---------------------------------------------------------------------------- */ DWORD GetRasDevices( IN HANDLE hConnection, IN CHAR* pszDeviceType, OUT RASMAN_DEVICE** ppDevices, OUT DWORD* pdwEntries ); DWORD GetRasPortParam( IN HPORT hport, IN CHAR* pszKey, OUT RASMAN_PORTINFO** ppPortInfo, OUT RAS_PARAMS** ppParam ); /*---------------------------------------------------------------------------- ** Routines **---------------------------------------------------------------------------- */ DWORD ClearRasdevStats( IN RASDEV* pdev, IN BOOL fBundle ) /* Resets statistics counters for a device. ** ** (Abolade Gbadegesin Nov-9-1995) */ { if (pdev == NULL) { return ERROR_INVALID_PARAMETER; } if ((HPORT)pdev->RD_Handle == (HPORT)INVALID_HANDLE_VALUE) { return ERROR_INVALID_HANDLE; } ASSERT(g_pRasPortClearStatistics); return (fBundle ? g_pRasBundleClearStatistics(NULL, (HPORT)pdev->RD_Handle) : g_pRasPortClearStatistics(NULL, (HPORT)pdev->RD_Handle)); } #if 0 DWORD DeviceIdFromDeviceName( TCHAR* pszDeviceName ) /* Returns the TAPI device ID associated with 'pszDeviceName'. Returns ** 0xFFFFFFFE if not found, 0xFFFFFFFF if found but not a Unimodem. ** ** This routine assumes that TAPI devices have unique names. */ { DWORD dwErr; DWORD dwId; DWORD dwPorts; RASMAN_PORT* pPorts; TRACE("DeviceIdFromDeviceName"); dwId = 0xFFFFFFFE; if (pszDeviceName) { dwErr = GetRasPorts( &pPorts, &dwPorts ); if (dwErr == 0) { CHAR* pszDeviceNameA; pszDeviceNameA = StrDupAFromT( pszDeviceName ); if (pszDeviceNameA) { INT i; RASMAN_PORT* pPort; for (i = 0, pPort = pPorts; i < dwPorts; ++i, ++pPort) { if (lstrcmpiA( pszDeviceNameA, pPort->P_DeviceName ) == 0) { dwId = pPort->P_LineDeviceId; break; } } Free( pszDeviceNameA ); } Free( pPorts ); } } TRACE1("DeviceIdFromDeviceName=%d",dwErr); return dwId; } #endif DWORD FreeRasdevTable( RASDEV* pDevTable, DWORD iDevCount ) /* Frees a table built by GetRasdevTable. ** ** Returns 0 if succesful, or an error code. ** ** (Abolade Gbadegesin Nov-9-1995) */ { DWORD i; // // validate arguments // if (pDevTable == NULL) { return ERROR_INVALID_PARAMETER; } // // free the device-name string fields // for (i = 0; i < iDevCount; i++) { if (pDevTable[i].RD_DeviceName) { Free(pDevTable[i].RD_DeviceName); } } // // free the array itself // Free(pDevTable); return NO_ERROR; } DWORD GetConnectTime( IN HRASCONN hrasconn, OUT DWORD* pdwConnectTime ) /* Loads '*pdwConnectTime' with the duration in milliseconds of the ** connection on pdev. ** ** Returns 0 if succesful, or an error code. ** ** (Abolade Gbadegesin Nov-9-1995) */ { HPORT hport; DWORD dwErr; RASMAN_INFO info; if (pdwConnectTime == NULL) { return ERROR_INVALID_PARAMETER; } // // initialize the argument // *pdwConnectTime = 0; // // get an HPORT for the HRASCONN // ASSERT(g_pRasGetHport); hport = g_pRasGetHport(hrasconn); if (hport == (HPORT)INVALID_HANDLE_VALUE) { return ERROR_INVALID_HANDLE; } // // get information on the HPORT // ASSERT(g_pRasGetInfo); dwErr = g_pRasGetInfo(NULL, hport, &info); if (dwErr != NO_ERROR) { return dwErr; } if (info.RI_ConnState != CONNECTED) { *pdwConnectTime = 0; } else { *pdwConnectTime = info.RI_ConnectDuration; } return NO_ERROR; } DWORD GetRasconnFraming( IN HRASCONN hrasconn, OUT DWORD* pdwSendFraming, OUT DWORD* pdwRecvFraming ) /* Retrieves the framing bits for an active RAS connection. ** ** (Abolade Gbadegesin Nov-9-1995) */ { DWORD dwErr; HPORT hport; RAS_FRAMING_INFO info; // // validate arguments // if (pdwSendFraming == NULL || pdwRecvFraming == NULL) { return ERROR_INVALID_HANDLE; } // // retrieve the HPORT for this connection // ASSERT(g_pRasGetHport); hport = g_pRasGetHport(hrasconn); if (hport == (HPORT)INVALID_HANDLE_VALUE) { return ERROR_INVALID_HANDLE; } // // retrieve the framing information for this port // ASSERT(g_pRasPortGetFramingEx); dwErr = g_pRasPortGetFramingEx(NULL, hport, &info); if (dwErr != NO_ERROR) { return dwErr; } *pdwSendFraming = info.RFI_SendFramingBits; *pdwRecvFraming = info.RFI_RecvFramingBits; return NO_ERROR; } DWORD GetRasconnFromRasdev( IN RASDEV* pdev, OUT RASCONN** ppconn, IN RASCONN* pConnTable OPTIONAL, IN DWORD iConnCount OPTIONAL ) /* Given a RASDEV structure for an active device, this function retrieves ** the RASCONN which corresponds to the device's current connection. The ** second and third arguments are optional; they specify a table of ** RASCONN structures to be searched. This is useful if the caller has ** already enumerated the active connections, so that this function does ** not need to re-enumerate them. ** ** (Abolade Gbadegesin Nov-9-1995) */ { BOOL bFreeTable; DWORD dwErr, i; RASDEVSTATS stats; // // validate arguments // if (pdev == NULL || ppconn == NULL) { return ERROR_INVALID_PARAMETER; } *ppconn = NULL; // // get stats for the RASDEV // dwErr = GetRasdevStats(pdev, &stats); if (dwErr != NO_ERROR) { return dwErr; } bFreeTable = FALSE; // // if the caller didn't pass in a table of RASCONNs, retrieve one // if (pConnTable == NULL) { dwErr = GetRasconnTable(&pConnTable, &iConnCount); if (dwErr != NO_ERROR) { return dwErr; } bFreeTable = TRUE; } // // find the connection which matches the RASDEV passed in // for (i = 0; i < iConnCount; i++) { if ((HRASCONN)stats.RDS_Hrasconn == (pConnTable + i)->hrasconn) { break; } } // // see how the search ended // if (i >= iConnCount) { dwErr = ERROR_NO_DATA; } else { dwErr = NO_ERROR; if (!bFreeTable) { // // point to the place where we found the RASCONN // *ppconn = pConnTable + i; } else { // // make a copy of the RASCONN found // *ppconn = Malloc(sizeof(RASCONN)); if (!*ppconn) { dwErr = ERROR_NOT_ENOUGH_MEMORY; } else { **ppconn = *(pConnTable + i); } } } if (bFreeTable) { Free(pConnTable); } return dwErr; } DWORD GetRasdevBundle( IN RASDEV* pdev, OUT DWORD* pdwBundle ) /* Retrieves a handle which represents the current connection ** on the given device. This handle has the property that it will be ** identical for two devices which are multi-linked together. ** In the case of NT RAS, the RASMAN HBUNDLE is retrieved. ** ** (Abolade Gbadegesin Mar-6-1996) */ { return g_pRasPortGetBundle(NULL, (HPORT)pdev->RD_Handle, (HBUNDLE *)pdwBundle); } DWORD GetRasdevFraming( IN RASDEV* pdev, OUT DWORD* pdwFraming ) /* Retrieves the framing bits for an active RAS connection. ** ** (Abolade Gbadegesin Nov-9-1995) */ { DWORD dwErr; RAS_FRAMING_INFO info; // // validate arguments // if (pdwFraming == NULL) { return ERROR_INVALID_HANDLE; } // // retrieve the framing information for this port // ASSERT(g_pRasPortGetFramingEx); dwErr = g_pRasPortGetFramingEx(NULL, (HPORT)pdev->RD_Handle, &info); if (dwErr != NO_ERROR) { return dwErr; } if (info.RFI_SendFramingBits & OLD_RAS_FRAMING) { *pdwFraming = RASFP_Ras; } else if (info.RFI_SendFramingBits & PPP_MULTILINK_FRAMING || info.RFI_SendFramingBits & PPP_FRAMING) { *pdwFraming = RASFP_Ppp; } else if (info.RFI_SendFramingBits & SLIP_FRAMING) { *pdwFraming = RASFP_Slip; } else { *pdwFraming = 0; } return NO_ERROR; } DWORD GetRasdevFromRasconn( IN RASCONN* pconn, OUT RASDEV** ppdev, IN RASDEV* pDevTable OPTIONAL, IN DWORD iDevCount OPTIONAL ) /* Given a RASCONN structure for an active connection, this function ** retrieves the RASDEV for the device over which the connection is ** active. The second and third arguments are optional; they specify a ** table of RASDEV structures to be searched. This is useful if the ** caller has already enumerated the existing devices, so that this ** function does not need to re-enumerate them. ** ** (Abolade Gbadegesin Nov-9-1995) */ { HPORT hport; DWORD i, dwErr = NO_ERROR; BOOL bFreeTable; // // validate the arguments // if (pconn == NULL || ppdev == NULL) { return ERROR_INVALID_PARAMETER; } *ppdev = NULL; // // retrieve the device table if the caller didn't pass one in // bFreeTable = FALSE; // For whistler bug 26403 gangz // do { if (pDevTable == NULL) { dwErr = GetRasdevTable(&pDevTable, &iDevCount); if (dwErr != NO_ERROR) { return dwErr; } bFreeTable = TRUE; } // // retrieve the HPORT for the RASCONN passed in // ASSERT(g_pRasGetHport); hport = g_pRasGetHport(pconn->hrasconn); if (hport == (HPORT)INVALID_HANDLE_VALUE) { // For whistler bug 26403 gangz // here to break rather than return; // dwErr = ERROR_INVALID_HANDLE; break; } // // find the device to which the HPORT corresponds // for (i = 0; i < iDevCount; i++) { if (hport == pDevTable[i].RD_Handle) { break; } } // // see how the search ended // if (i >= iDevCount) { dwErr = ERROR_NO_DATA; break; } else { dwErr = NO_ERROR; if (!bFreeTable) { *ppdev = pDevTable + i; } else { *ppdev = Malloc(sizeof(RASDEV)); if (!*ppdev) { dwErr = ERROR_NOT_ENOUGH_MEMORY; } else { **ppdev = *(pDevTable + i); (*ppdev)->RD_DeviceName = StrDup(pDevTable[i].RD_DeviceName); if (!(*ppdev)->RD_DeviceName) { Free(*ppdev); *ppdev = NULL; dwErr = ERROR_NOT_ENOUGH_MEMORY; break; } } } } }while(FALSE); if (bFreeTable) { FreeRasdevTable(pDevTable, iDevCount); } return dwErr; } DWORD GetRasDevices( IN HANDLE hConnection, IN CHAR* pszDeviceType, OUT RASMAN_DEVICE** ppDevices, OUT DWORD* pdwEntries ) /* Fills caller's '*ppDevices' with the address of a heap block containing ** '*pwEntries' RASMAN_DEVICE structures. ** ** Returns 0 if successful, otherwise a non-0 error code. If successful, ** it is the caller's responsibility to free the returned memory block. */ { DWORD dwSize = 0; DWORD dwErr; TRACE1("GetRasDevices(%s)",pszDeviceType); ASSERT(g_pRasDeviceEnum); TRACE("RasDeviceEnum..."); dwErr = g_pRasDeviceEnum(hConnection, pszDeviceType, NULL, &dwSize, pdwEntries ); TRACE2("RasDeviceEnum=%d,c=%d",dwErr,*pdwEntries); if (dwErr == 0) { /* No devices to enumerate. Set up to allocate a single byte anyway, ** so things work without lots of special code. */ dwSize = 1; } else if (dwErr != ERROR_BUFFER_TOO_SMALL) return dwErr; *ppDevices = (RASMAN_DEVICE* )Malloc( dwSize ); if (!*ppDevices) return ERROR_NOT_ENOUGH_MEMORY; TRACE("RasDeviceEnum..."); dwErr = g_pRasDeviceEnum( hConnection, pszDeviceType, (PBYTE )*ppDevices, &dwSize, pdwEntries ); TRACE1("RasDeviceEnum=%d",dwErr); if (dwErr != 0) { Free( *ppDevices ); return dwErr; } return 0; } DWORD GetRasDeviceString( IN HPORT hport, IN CHAR* pszDeviceType, IN CHAR* pszDeviceName, IN CHAR* pszKey, OUT CHAR** ppszValue, IN DWORD dwXlate ) /* Loads callers '*ppszValue' with the address of a heap block containing ** a NUL-terminated copy of the value string associated with key 'pszKey' ** for the device on port 'hport'. 'pszDeviceType' specifies the type of ** device, e.g. "modem". 'pszDeviceName' specifies the name of the ** device, e.g. "Hayes V-Series 9600". 'dwXlate' is a bit mask of XLATE_ ** bits specifying translations to perform on the returned string. ** ** Returns 0 if successful, otherwise a non-0 error code. If successful, ** it is the caller's responsibility to Free the returned string. */ { DWORD dwErr = 0; RASMAN_DEVICEINFO* pDeviceInfo = NULL; RAS_PARAMS* pParam; DWORD dwSize = 0; INT i; TRACE2("GetRasDeviceString(%s,%s)",pszDeviceName,pszKey); *ppszValue = NULL; do { ASSERT(g_pRasDeviceGetInfo); TRACE("RasDeviceGetInfo..."); dwErr = g_pRasDeviceGetInfo( NULL, hport, pszDeviceType, pszDeviceName, NULL, &dwSize ); TRACE2("RasDeviceGetInfo=%d,s=%d",dwErr,(INT)dwSize); if (dwErr != ERROR_BUFFER_TOO_SMALL && dwErr != 0) break; /* So it will fall thru and be "not found". */ if (dwSize == 0) dwSize = 1; pDeviceInfo = (RASMAN_DEVICEINFO* )Malloc( dwSize ); if (!pDeviceInfo) return ERROR_NOT_ENOUGH_MEMORY; TRACE("RasDeviceGetInfo..."); dwErr = g_pRasDeviceGetInfo( NULL, hport, pszDeviceType, pszDeviceName, (PBYTE )pDeviceInfo, &dwSize ); TRACE2("RasDeviceGetInfo=%d,s=%d",dwErr,(INT)dwSize); if (dwErr != 0) break; dwErr = ERROR_KEY_NOT_FOUND; for (i = 0, pParam = pDeviceInfo->DI_Params; i < (INT )pDeviceInfo->DI_NumOfParams; ++i, ++pParam) { if (lstrcmpiA( pParam->P_Key, pszKey ) == 0) { *ppszValue = PszFromRasValue( &pParam->P_Value, dwXlate ); dwErr = (*ppszValue) ? 0 : ERROR_NOT_ENOUGH_MEMORY; break; } } } while (FALSE); Free0( pDeviceInfo ); TRACE1("String=\"%s\"",(*ppszValue)?*ppszValue:""); return dwErr; } DWORD GetRasdevStats( IN RASDEV* pdev, OUT RASDEVSTATS* pstats ) /* Retrieves statistics for a device. ** ** (Abolade Gbadegesin Nov-9-1995) */ { DWORD dwsize; RASMAN_INFO info; RAS_STATISTICS *prs; BYTE buffer[sizeof(RAS_STATISTICS) + MAX_STATISTICS * 2 * sizeof(DWORD)]; DWORD dwErr, *pdw, dwGone, dwB, dwBC, dwBU; if (pdev == NULL || pstats == NULL) { return ERROR_INVALID_PARAMETER; } ZeroMemory(pstats, sizeof(RASDEVSTATS)); // // retrieve the condition and connect time // ASSERT(g_pRasGetInfo); dwErr = g_pRasGetInfo(NULL, (HPORT)pdev->RD_Handle, &info); if (dwErr != NO_ERROR) { pstats->RDS_Condition = DISCONNECTED; return dwErr; } // // need to handle ports which are not connected // already a bug filed. // if (info.RI_PortStatus != OPEN) { pstats->RDS_Condition = DISCONNECTED; return NO_ERROR; } pstats->RDS_Condition = info.RI_ConnState; if (info.RI_ConnState == CONNECTED) { pstats->RDS_ConnectTime = info.RI_ConnectDuration; pstats->RDS_Hrasconn = (HRASCONN)info.RI_ConnectionHandle; } // // get dial-in/dial-out usage // if (info.RI_CurrentUsage & CALL_IN) pstats->RDS_Flags |= RDFLAG_IsDialedIn; if (info.RI_CurrentUsage & CALL_OUT) pstats->RDS_Flags |= RDFLAG_IsDialedOut; if (info.RI_CurrentUsage & CALL_ROUTER) pstats->RDS_Flags |= RDFLAG_IsRouter; // // Retrieve the line speed // pstats->RDS_LineSpeed = info.RI_LinkSpeed; // // Retrieve the i/o statistics for both the link and the bundle // prs = (RAS_STATISTICS *)buffer; dwsize = sizeof(RAS_STATISTICS) + MAX_STATISTICS * 2 * sizeof(DWORD); ZeroMemory(buffer, dwsize); ASSERT(g_pRasBundleGetStatistics); dwErr = g_pRasBundleGetStatistics( NULL, (HPORT)pdev->RD_Handle, (PBYTE)prs, &dwsize ); if (dwErr != NO_ERROR) { return dwErr; } // // Save the statistics in the caller's RASDEVSTATS structure. // pdw = prs->S_Statistics; pstats->RDS_InFrames = pdw[FRAMES_RCVED]; pstats->RDS_OutFrames = pdw[FRAMES_XMITED]; pstats->RDS_InBytesTotal = pdw[BYTES_RCVED] + pdw[BYTES_RCVED_UNCOMPRESSED] - pdw[BYTES_RCVED_COMPRESSED]; pstats->RDS_OutBytesTotal = pdw[BYTES_XMITED] + pdw[BYTES_XMITED_UNCOMPRESSED] - pdw[BYTES_XMITED_COMPRESSED]; pstats->RDS_InBytes = pdw[MAX_STATISTICS + BYTES_RCVED] + pdw[MAX_STATISTICS + BYTES_RCVED_UNCOMPRESSED] - pdw[MAX_STATISTICS + BYTES_RCVED_COMPRESSED]; pstats->RDS_OutBytes = pdw[MAX_STATISTICS + BYTES_XMITED] + pdw[MAX_STATISTICS + BYTES_XMITED_UNCOMPRESSED] - pdw[MAX_STATISTICS + BYTES_XMITED_COMPRESSED]; pstats->RDS_ErrCRC = pdw[MAX_STATISTICS + CRC_ERR]; pstats->RDS_ErrTimeout = pdw[MAX_STATISTICS + TIMEOUT_ERR]; pstats->RDS_ErrAlignment = pdw[MAX_STATISTICS + ALIGNMENT_ERR]; pstats->RDS_ErrFraming = pdw[MAX_STATISTICS + FRAMING_ERR]; pstats->RDS_ErrHwOverruns = pdw[MAX_STATISTICS + HARDWARE_OVERRUN_ERR]; pstats->RDS_ErrBufOverruns = pdw[MAX_STATISTICS + BUFFER_OVERRUN_ERR]; #if 0 TRACE4( "RasBundleGetStatistics(rx=%d,tx=%d,rxb=%d,txb=%d)", pstats->RDS_InBytes, pstats->RDS_OutBytes, pstats->RDS_InBytesTotal, pstats->RDS_OutBytesTotal ); #endif // // Compute compression ratios, using the bundle-stats // pstats->RDS_InCompRatio = 0; dwGone = 0; dwB = pdw[BYTES_RCVED]; dwBC = pdw[BYTES_RCVED_COMPRESSED]; dwBU = pdw[BYTES_RCVED_UNCOMPRESSED]; if (dwBC < dwBU) { dwGone = dwBU - dwBC; } if (dwB + dwGone > 100) { DWORD dwDen = (dwB + dwGone) / 100; pstats->RDS_InCompRatio = (dwGone + (dwDen / 2)) / dwDen; } pstats->RDS_OutCompRatio = 0; dwGone = 0; dwB = pdw[BYTES_XMITED]; dwBC = pdw[BYTES_XMITED_COMPRESSED]; dwBU = pdw[BYTES_XMITED_UNCOMPRESSED]; if (dwBC < dwBU) { dwGone = dwBU - dwBC; } if (dwB + dwGone > 100) { DWORD dwDen = (dwB + dwGone) / 100; pstats->RDS_OutCompRatio = (dwGone + (dwDen / 2)) / dwDen; } return NO_ERROR; } DWORD GetRasdevTable( OUT RASDEV** ppDevTable, OUT DWORD* piDevCount ) /* Gets an array of RAS devices configured. Loads '*ppDevTable' with a ** heap block of '*ppDevTable' entries. On NT, this is essentially the ** output of GetRasPorts(), in a format which includes a devicename, ** flags, and a handle. Given a RASMAN_PORT structure, we append the ** device and port names to make a unique device string which is part of ** the output. ** ** Returns 0 if successful, or an error. ** ** (Abolade Gbadegesin Nov-9-1995) */ { DWORD dwPortCount; DWORD i, iLength, dwErr; RASDEV *pDevTable, *pdev; PTSTR pszDevice, pszPort; TCHAR szDevice[RAS_MaxDeviceName + 1]; RASMAN_PORT *pPortTable, *pport; // // validate the arguments // if (ppDevTable == NULL || piDevCount == NULL) { return ERROR_INVALID_PARAMETER; } *piDevCount = 0; *ppDevTable = NULL; // // get a table of ports from RASMAN; the string fields are ANSI // dwErr = GetRasPorts(NULL, &pPortTable, &dwPortCount); if (dwErr != NO_ERROR) { return dwErr; } if (dwPortCount == 0) { return NO_ERROR; } // // allocate space for as many device structs as there are ports // pDevTable = Malloc(dwPortCount * sizeof(RASDEV)); if (pDevTable == NULL) { Free(pPortTable); return ERROR_NOT_ENOUGH_MEMORY; } ZeroMemory(pDevTable, dwPortCount * sizeof(RASDEV)); // // convert each RASMAN_PORT structure to a RASDEV structure. // for (i = 0, pport = pPortTable; i < dwPortCount; i++, pport++) { pdev = pDevTable + i; // // copy over code-page-independent fields // pdev->RD_Handle = pport->P_Handle; if (pport->P_ConfiguredUsage & CALL_IN) pdev->RD_Flags |= RDFLAG_DialIn; if (pport->P_ConfiguredUsage & CALL_OUT) pdev->RD_Flags |= RDFLAG_DialOut; if (pport->P_ConfiguredUsage & CALL_ROUTER) pdev->RD_Flags |= RDFLAG_Router; if (pport->P_CurrentUsage & CALL_IN) pdev->RD_Flags |= RDFLAG_IsDialedIn; if (pport->P_CurrentUsage & CALL_OUT) pdev->RD_Flags |= RDFLAG_IsDialedOut; if (pport->P_CurrentUsage & CALL_ROUTER) pdev->RD_Flags |= RDFLAG_IsRouter; // // copy the device-type string // #ifdef UNICODE StrCpyWFromAUsingAnsiEncoding( pdev->RD_DeviceType, pport->P_DeviceType, RAS_MaxDeviceType); #else lstrcpy(pdev->RD_DeviceType, pport->P_DeviceType); #endif // // copy the device-name and portname, // storing them in temporary strings // #ifdef UNICODE StrCpyWFromAUsingAnsiEncoding( szDevice, pport->P_DeviceName, RAS_MaxDeviceName); StrCpyWFromAUsingAnsiEncoding( pdev->RD_PortName, pport->P_PortName, MAX_PORT_NAME); pszDevice = szDevice; pszPort = pdev->RD_PortName; #else pszDevice = pport->P_DeviceName; lstrcpyn(pdev->RD_PortName, pport->P_PortName, MAX_PORT_NAME + 1); pszPort = pdev->RD_PortName; #endif // // get a display name from the device and port names // pdev->RD_DeviceName = PszFromDeviceAndPort(pszDevice, pszPort); if (pdev->RD_DeviceName == NULL) { Free(pPortTable); FreeRasdevTable(pDevTable, dwPortCount); return ERROR_NOT_ENOUGH_MEMORY; } } Free(pPortTable); *ppDevTable = pDevTable; *piDevCount = dwPortCount; return NO_ERROR; } DWORD GetRasMessage( IN HRASCONN hrasconn, OUT TCHAR** ppszMessage ) /* Loads caller's '*ppszMessage' with the address of a heap block ** containing the current MXS_MESSAGE_KEY value associated with RAS ** connection 'hrasconn'. ** ** Returns 0 if successful or an error code. It is caller's ** responsibility to Free the returned string. */ { DWORD dwErr; RASCONNSTATUS rcs; CHAR* pszMessage; TRACE("GetRasMessage"); *ppszMessage = 0; ZeroMemory( &rcs, sizeof(rcs) ); rcs.dwSize = sizeof(rcs); ASSERT(g_pRasGetConnectStatus); TRACE("RasGetConnectStatus"); dwErr = g_pRasGetConnectStatus( hrasconn, &rcs ); TRACE1("RasGetConnectStatus=%d",dwErr); if (dwErr == 0) { CHAR* pszDeviceTypeA; CHAR* pszDeviceNameA; pszDeviceTypeA = StrDupAFromT( rcs.szDeviceType ); pszDeviceNameA = StrDupAFromT( rcs.szDeviceName ); if (!pszDeviceTypeA || !pszDeviceNameA) { Free0( pszDeviceNameA ); return ERROR_NOT_ENOUGH_MEMORY; } dwErr = GetRasDeviceString( g_pRasGetHport( hrasconn ), pszDeviceTypeA, pszDeviceNameA, MXS_MESSAGE_KEY, &pszMessage, XLATE_ErrorResponse ); Free0( pszDeviceTypeA ); Free0( pszDeviceNameA ); if (dwErr == 0) { *ppszMessage = StrDupTFromA( pszMessage ); if (!*ppszMessage) dwErr = ERROR_NOT_ENOUGH_MEMORY; Free0( pszMessage ); } } return dwErr; } DWORD GetRasPads( OUT RASMAN_DEVICE** ppDevices, OUT DWORD* pdwEntries ) /* Fills caller's '*ppDevices' with the address of a heap block containing ** '*pwEntries' X.25 PAD DEVICE structures. ** ** Returns 0 if successful, otherwise a non-0 error code. If successful, ** it is the caller's responsibility to free the returned memory block. */ { return GetRasDevices( NULL, MXS_PAD_TXT, ppDevices, pdwEntries ); } VOID GetRasPortMaxBps( IN HPORT hport, OUT DWORD* pdwMaxConnectBps, OUT DWORD* pdwMaxCarrierBps ) /* Loads callers '*pdwMaxConnectBps' with the maximum port->modem bps rate ** for port 'pport', or with 0 if not found. '*pdwMaxCarrierBps' is the ** same but for maximum modem->modem speed. */ { CHAR* pszValue = NULL; DWORD dwErr; TRACE("GetRasPortMaxBps"); dwErr = GetRasPortString( hport, SER_CONNECTBPS_KEY, &pszValue, XLATE_None ); if (dwErr == 0) *pdwMaxConnectBps = (DWORD )atol( pszValue ); else *pdwMaxConnectBps = 0; Free0(pszValue); pszValue = NULL; dwErr = GetRasPortString( hport, SER_CARRIERBPS_KEY, &pszValue, XLATE_None ); if (dwErr == 0) *pdwMaxCarrierBps = (DWORD )atol( pszValue ); else *pdwMaxCarrierBps = 0; Free0(pszValue); } VOID GetRasPortModemSettings( IN HPORT hport, OUT BOOL* pfHwFlowDefault, OUT BOOL* pfEcDefault, OUT BOOL* pfEccDefault ) /* Loads caller's flags with the default setting of Hardware Flow Control, ** Error Control, and Error Control and Compression for the given 'hport'. */ { CHAR* pszValue = NULL; *pfHwFlowDefault = TRUE; *pfEcDefault = TRUE; *pfEccDefault = TRUE; if (GetRasPortString( hport, SER_C_DEFAULTOFFSTR_KEY, &pszValue, XLATE_None ) == 0) { if (StrStrA( pszValue, MXS_HDWFLOWCONTROL_KEY ) != NULL) *pfHwFlowDefault = FALSE; if (StrStrA( pszValue, MXS_PROTOCOL_KEY ) != NULL) *pfEcDefault = FALSE; if (StrStrA( pszValue, MXS_COMPRESSION_KEY ) != NULL) *pfEccDefault = FALSE; Free0( pszValue ); } } DWORD GetRasPortParam( IN HPORT hport, IN CHAR* pszKey, OUT RASMAN_PORTINFO** ppPortInfo, OUT RAS_PARAMS** ppParam ) /* Loads callers '*ppParam' with the address of a RAS_PARAM block ** associated with key 'pszKey', or NULL if none. 'ppPortInfo' is the ** address of the array of RAS_PARAMS containing the found 'pparam'. ** ** Returns 0 if successful, otherwise a non-0 error code. If successful, ** it is the caller's responsibility to Free the returned '*ppPortInfo'. */ { DWORD dwErr = 0; DWORD dwSize = 0; INT i; TRACE("GetRasPortParam"); *ppPortInfo = NULL; do { ASSERT(g_pRasPortGetInfo); TRACE("RasPortGetInfo"); dwErr = g_pRasPortGetInfo(NULL, hport, NULL, &dwSize ); TRACE2("RasPortGetInfo=%d,s=%d",dwErr,(INT)dwSize); if (dwErr != ERROR_BUFFER_TOO_SMALL && dwErr != 0) break; /* So it will fall thru and be "not found". */ if (dwSize == 0) dwSize = 1; *ppPortInfo = (RASMAN_PORTINFO* )Malloc( dwSize ); if (!*ppPortInfo) return ERROR_NOT_ENOUGH_MEMORY; TRACE("RasPortGetInfo"); dwErr = g_pRasPortGetInfo(NULL, hport, (PBYTE )*ppPortInfo, &dwSize ); TRACE2("RasPortGetInfo=%d,s=%d",dwErr,(INT)dwSize); if (dwErr != 0) break; for (i = 0, *ppParam = (*ppPortInfo)->PI_Params; i < (INT )(*ppPortInfo)->PI_NumOfParams; ++i, ++(*ppParam)) { if (lstrcmpiA( (*ppParam)->P_Key, pszKey ) == 0) break; } if (i >= (INT )(*ppPortInfo)->PI_NumOfParams) dwErr = ERROR_KEY_NOT_FOUND; } while (FALSE); return dwErr; } DWORD GetRasPorts( IN HANDLE hConnection, OUT RASMAN_PORT** ppPorts, OUT DWORD* pdwEntries ) /* Enumerate RAS ports. Sets '*ppPort' to the address of a heap memory ** block containing an array of PORT structures with '*pwEntries' ** elements. ** ** Returns 0 if successful, otherwise a non-0 error code. If successful, ** it is the caller's responsibility to free the returned memory block. */ { DWORD dwSize = 0; DWORD dwErr; TRACE("GetRasPorts"); #if DUMMYPORTS { RASMAN_PORT* pPort; DWORD c; TRACE("TEST: Fake ISDN ports"); *pdwEntries = c = g_cPorts; dwSize = *pdwEntries * sizeof(RASMAN_PORT); *ppPorts = (RASMAN_PORT* )Malloc( dwSize ); if (!*ppPorts) return ERROR_NOT_ENOUGH_MEMORY; do { pPort = *ppPorts; ZeroMemory( pPort, sizeof(*pPort) ); lstrcpyA( pPort->P_PortName, "COM1" ); pPort->P_Status = CLOSED; pPort->P_ConfiguredUsage = CALL_OUT; pPort->P_CurrentUsage = CALL_OUT; lstrcpyA( pPort->P_MediaName, "rasser" ); lstrcpyA( pPort->P_DeviceName, "US Robotics Courier V32 bis" ); lstrcpyA( pPort->P_DeviceType, "MODEM" ); if (--c == 0) break; ++pPort; ZeroMemory( pPort, sizeof(*pPort) ); lstrcpyA( pPort->P_PortName, "ISDN1" ); pPort->P_Status = CLOSED; pPort->P_ConfiguredUsage = CALL_OUT; pPort->P_CurrentUsage = CALL_OUT; lstrcpyA( pPort->P_MediaName, "rastapi" ); lstrcpyA( pPort->P_DeviceName, "Digiboard PCIMac ISDN adapter" ); lstrcpyA( pPort->P_DeviceType, "ISDN" ); if (--c == 0) break; ++pPort; ZeroMemory( pPort, sizeof(*pPort) ); lstrcpyA( pPort->P_PortName, "ISDN2" ); pPort->P_Status = CLOSED; pPort->P_ConfiguredUsage = CALL_OUT; pPort->P_CurrentUsage = CALL_OUT; lstrcpyA( pPort->P_MediaName, "rastapi" ); lstrcpyA( pPort->P_DeviceName, "Digiboard PCIMac ISDN adapter" ); lstrcpyA( pPort->P_DeviceType, "ISDN" ); if (--c == 0) break; ++pPort; ZeroMemory( pPort, sizeof(*pPort) ); lstrcpyA( pPort->P_PortName, "COM500" ); pPort->P_Status = CLOSED; pPort->P_ConfiguredUsage = CALL_OUT; pPort->P_CurrentUsage = CALL_OUT; lstrcpyA( pPort->P_MediaName, "rasser" ); lstrcpyA( pPort->P_DeviceName, "Eicon X.PAD" ); lstrcpyA( pPort->P_DeviceType, "PAD" ); if (--c == 0) break; ++pPort; ZeroMemory( pPort, sizeof(*pPort) ); lstrcpyA( pPort->P_PortName, "X251" ); pPort->P_Status = CLOSED; pPort->P_ConfiguredUsage = CALL_OUT; pPort->P_CurrentUsage = CALL_OUT; lstrcpyA( pPort->P_MediaName, "rastapi" ); lstrcpyA( pPort->P_DeviceName, "Digiboard X.25 adapter" ); lstrcpyA( pPort->P_DeviceType, "X25" ); if (--c == 0) break; ++pPort; ZeroMemory( pPort, sizeof(*pPort) ); lstrcpyA( pPort->P_PortName, "VPN1" ); pPort->P_Status = CLOSED; pPort->P_ConfiguredUsage = CALL_OUT; pPort->P_CurrentUsage = CALL_OUT; lstrcpyA( pPort->P_MediaName, "rastapi" ); lstrcpyA( pPort->P_DeviceName, "RASPPTPM" ); lstrcpyA( pPort->P_DeviceType, "VPN1" ); if (--c == 0) break; } while (FALSE); } #else ASSERT(g_pRasPortEnum); TRACE("RasPortEnum..."); dwErr = g_pRasPortEnum(hConnection, NULL, &dwSize, pdwEntries ); TRACE2("RasPortEnum=%d,c=%d",dwErr,(INT)*pdwEntries); if (dwErr == 0) { /* No ports to enumerate. Set up to allocate a single byte anyway, so ** things work without lots of special code. */ dwSize = 1; } else if (dwErr != ERROR_BUFFER_TOO_SMALL) return dwErr; *ppPorts = (RASMAN_PORT* )Malloc( dwSize ); if (!*ppPorts) return ERROR_NOT_ENOUGH_MEMORY; TRACE("RasPortEnum..."); dwErr = g_pRasPortEnum(hConnection, (PBYTE )*ppPorts, &dwSize, pdwEntries ); TRACE2("RasPortEnum=%d,c=%d",dwErr,(INT)*pdwEntries); if (dwErr != 0) { Free( *ppPorts ); *ppPorts = NULL; return dwErr; } #endif #if 1 // Verbose trace { RASMAN_PORT* pPort; DWORD i; for (pPort = *ppPorts, i = 0; i < *pdwEntries; ++i, ++pPort) { TRACE4("Port[%d]=%s,DID=$%08x,AID=$%08x", pPort->P_Handle,pPort->P_PortName, pPort->P_LineDeviceId,pPort->P_AddressId); TRACE3(" M=%s,DT=%s,DN=%s", pPort->P_MediaName,pPort->P_DeviceType,pPort->P_DeviceName); TRACE3(" S=$%08x,CfgU=$%08x,CurU=$%08x", pPort->P_Status,pPort->P_ConfiguredUsage,pPort->P_CurrentUsage); } } #endif return 0; } DWORD GetRasPortString( IN HPORT hport, IN CHAR* pszKey, OUT CHAR** ppszValue, IN DWORD dwXlate ) /* Loads callers '*ppszValue' with the address of a heap block containing ** a NUL-terminated copy of the value string associated with key 'pszKey' ** on port 'hport'. 'dwXlate' is a bit mask of XLATE_ bits specifying ** translations to be done on the string value. ** ** Returns 0 if successful, otherwise a non-0 error code. If successful, ** it is the caller's responsibility to Free the returned string. */ { RASMAN_PORTINFO* pPortInfo; RAS_PARAMS* pParam; DWORD dwErr; TRACE("GetRasPortString"); dwErr = GetRasPortParam( hport, pszKey, &pPortInfo, &pParam ); *ppszValue = NULL; if (dwErr == 0) { *ppszValue = PszFromRasValue( &pParam->P_Value, dwXlate ); dwErr = (*ppszValue) ? 0 : ERROR_NOT_ENOUGH_MEMORY; } Free0( pPortInfo ); return dwErr; } DWORD GetRasSwitches( IN HANDLE hConnection, OUT RASMAN_DEVICE** ppDevices, OUT DWORD* pdwEntries ) /* Fills caller's '*ppDevices' with the address of a heap block containing ** '*pwEntries' switch DEVICE structures. ** ** Returns 0 if successful, otherwise a non-0 error code. If successful, ** it is the caller's responsibility to free the returned memory block. */ { return GetRasDevices( hConnection, MXS_SWITCH_TXT, ppDevices, pdwEntries ); } DWORD GetRasUnimodemBlob( IN HANDLE hConnection, IN HPORT hport, IN CHAR* pszDeviceType, OUT BYTE** ppBlob, OUT DWORD* pcbBlob ) { return GetRasUnimodemBlobEx( hConnection, hport, pszDeviceType, FALSE, ppBlob, pcbBlob); } DWORD GetRasUnimodemBlobEx( IN HANDLE hConnection, IN HPORT hport, IN CHAR* pszDeviceType, IN BOOL fGlobal, OUT BYTE** ppBlob, OUT DWORD* pcbBlob ) /* Loads '*ppBlob' and '*pcbBlob' with the sanitized Unimodem blob and ** size associated with 'hport' and 'pszDeviceType'. It is caller's ** responsibility to Free the returned '*ppBlob'. ** ** Returns 0 if successful, or an error code. */ { DWORD dwErr; BYTE* pBlob; DWORD cbBlob; PRASGETDEVCONFIG pFunc; CHAR* pszFuncName; cbBlob = 0; pFunc = (fGlobal) ? g_pRasGetDevConfigEx : g_pRasGetDevConfig; pszFuncName = (fGlobal) ? "RasGetDevConfigEx" : "RasGetDevConfig"; ASSERT(pFunc); TRACE(pszFuncName); dwErr = pFunc(hConnection, hport, pszDeviceType, NULL, &cbBlob ); TRACE2("%s=%d", pszFuncName, dwErr); if (dwErr != 0 && dwErr != ERROR_BUFFER_TOO_SMALL) return dwErr; if (cbBlob > 0) { pBlob = Malloc( cbBlob ); if (!pBlob) return ERROR_NOT_ENOUGH_MEMORY; TRACE(pszFuncName); dwErr = pFunc(hConnection, hport, pszDeviceType, pBlob, &cbBlob ); TRACE2("%s=%d", pszFuncName, dwErr); if (dwErr != 0) { Free( pBlob ); return dwErr; } SanitizeUnimodemBlob( pBlob ); } else pBlob = NULL; *ppBlob = pBlob; *pcbBlob = cbBlob; return dwErr; } VOID GetRasUnimodemInfo( IN HANDLE hConnection, IN HPORT hport, IN CHAR* pszDeviceType, OUT UNIMODEMINFO* pInfo ) /* Loads 'pInfo' with the RAS-relevant information of the port 'hport' ** with device name 'pszDeviceName'. */ { DWORD dwErr; BYTE* pBlob = NULL; DWORD cbBlob = 0; SetDefaultUnimodemInfo( pInfo ); dwErr = GetRasUnimodemBlob( hConnection, hport, pszDeviceType, &pBlob, &cbBlob ); if (dwErr == 0 && cbBlob > 0) UnimodemInfoFromBlob( pBlob, pInfo ); Free0( pBlob ); } TCHAR* GetRasX25Diagnostic( IN HRASCONN hrasconn ) /* Returns the X.25 diagnostics string or NULL if none. It is caller's ** responsibility to Free the returned string. */ { DWORD dwErr; HPORT hport; RASMAN_INFO info; CHAR* pszDiagnosticA = NULL; TCHAR* pszDiagnostic = NULL; pszDiagnosticA = NULL; hport = g_pRasGetHport( hrasconn ); ASSERT(g_pRasGetInfo); TRACE1("RasGetInfo(%d)",hport); dwErr = g_pRasGetInfo( NULL, hport, &info ); TRACE1("RasGetInfo=%d",dwErr); /* Error codes are ignored here since the diagnosistic ** is informational only. If they fail the diagnostic ** will simply appear blank. */ if (dwErr == 0) { GetRasDeviceString( hport, info.RI_DeviceTypeConnecting, info.RI_DeviceConnecting, MXS_DIAGNOSTICS_KEY, &pszDiagnosticA, XLATE_Diagnostic ); } if(NULL != pszDiagnosticA) { pszDiagnostic = StrDupTFromA( pszDiagnosticA ); Free( pszDiagnosticA ); } return pszDiagnostic; } BOOL IsRasdevBundled( IN RASDEV* pdev, IN RASDEV* pDevTable, IN DWORD iDevCount ) /* Determines whether the device described by 'pdev' is bundled, ** by looking for another device in 'pDevTable' which has the same bundle ** as 'pdev'. ** ** Returnes TRUE if the device is bundled, FALSE otherwise. */ { DWORD i; RASDEV* pdev2; DWORD dwBundle; // // First get the device's bundle; // If this fails, assume it is not connected and return FALSE. // if (GetRasdevBundle(pdev, &dwBundle) != NO_ERROR) { return FALSE; } // // Walk through the other devices in the table, looking for one // with the same bundle. // for (i = 0, pdev2 = pDevTable; i < iDevCount; i++, pdev2++) { DWORD dwBundle2; // // skip this if it is the device we already know about // if (pdev->RD_Handle == pdev2->RD_Handle) { continue; } // // get the bundle // if (GetRasdevBundle(pdev2, &dwBundle2) != NO_ERROR) { continue; } // // if the bundle is the same, we know its multilinked // if (dwBundle == dwBundle2) { return TRUE; } } return FALSE; } CHAR* PszFromRasValue( IN RAS_VALUE* prasvalue, IN DWORD dwXlate ) /* Returns the address of a heap block containing a NUL-terminated string ** value from caller's '*prasvalue', or NULL if out of memory. 'dwXlate' ** is a bit mask of XLATE_ bits specifying translations to be performed on ** the string. The value is assumed to be of format String. It is ** translated to modem.inf style. */ { #define MAXEXPANDPERCHAR 5 #define HEXCHARS "0123456789ABCDEF" INT i; BOOL fXlate; BOOL fXlateCtrl; BOOL fXlateCr; BOOL fXlateCrSpecial; BOOL fXlateLf; BOOL fXlateLfSpecial; BOOL fXlateLAngle; BOOL fXlateRAngle; BOOL fXlateBSlash; BOOL fXlateSSpace; BOOL fNoCharSinceLf; INT nLen; CHAR* pszIn = NULL; CHAR* pszBuf = NULL; CHAR* pszOut = NULL; CHAR* pszTemp = NULL; nLen = prasvalue->String.Length; pszIn = prasvalue->String.Data; pszBuf = Malloc( (nLen * MAXEXPANDPERCHAR) + 1 ); if (!pszBuf) return NULL; /* Translate the returned string based on the translation bit map. The ** assumption here is that all these devices talk ASCII and not some ** localized ANSI. */ fXlate = (dwXlate != 0); fXlateCtrl = (dwXlate & XLATE_Ctrl); fXlateCr = (dwXlate & XLATE_Cr); fXlateCrSpecial = (dwXlate & XLATE_CrSpecial); fXlateLf = (dwXlate & XLATE_Lf); fXlateLfSpecial = (dwXlate & XLATE_LfSpecial); fXlateLAngle = (dwXlate & XLATE_LAngle); fXlateRAngle = (dwXlate & XLATE_RAngle); fXlateBSlash = (dwXlate & XLATE_BSlash); fXlateSSpace = (dwXlate & XLATE_SSpace); pszOut = pszBuf; fNoCharSinceLf = TRUE; for (i = 0; i < nLen; ++i) { CHAR ch = pszIn[ i ]; if (fXlate) { if (ch == 0x0D) { if (fXlateSSpace && fNoCharSinceLf) continue; if (fXlateCrSpecial) { /* Special symbol for carriage return. */ lstrcpyA( pszOut, "" ); pszOut += 4; continue; } } if (ch == 0x0A) { if (fXlateSSpace && fNoCharSinceLf) continue; fNoCharSinceLf = TRUE; if (fXlateLfSpecial) { /* Special symbol for line feed. */ lstrcpyA( pszOut, "" ); pszOut += 4; continue; } } if (ch != 0x0A && ch != 0x0D) fNoCharSinceLf = FALSE; if ((((ch < 0x20 || ch > 0x7E) && ch != 0x0D && ch != 0x0A) && fXlateCtrl) || (ch == 0x0D && fXlateCr) || (ch == 0x0A && fXlateLf) || (ch == 0x3C && fXlateLAngle) || (ch == 0x3E && fXlateRAngle) || (ch == 0x5C && fXlateBSlash)) { /* Expand to "dump" form, i.e. where FF is the hex value ** of the character. */ *pszOut++ = '<'; *pszOut++ = 'h'; *pszOut++ = HEXCHARS[ ch / 16 ]; *pszOut++ = HEXCHARS[ ch % 16 ]; *pszOut++ = '>'; continue; } } /* Just copy without translation. */ *pszOut++ = ch; } *pszOut = '\0'; // For whistler 517011 // pszTemp = Realloc( pszBuf, lstrlenA( pszBuf ) + 1 ); if(pszTemp) { pszBuf = pszTemp; } else { Free(pszBuf); pszBuf = NULL; } return pszBuf; } VOID SanitizeUnimodemBlob( IN OUT BYTE* pBlob ) /* Fix non-RAS-compatible settings in unimodem blob 'pBlob'. ** ** (Based on Gurdeepian routine) */ { DEVCFG* pDevCfg; MODEMSETTINGS* pModemSettings; RAS_DEVCONFIG* pRasDevCfg; pRasDevCfg = (RAS_DEVCONFIG*)pBlob; pDevCfg = (DEVCFG *) ((PBYTE) pRasDevCfg + pRasDevCfg->dwOffsetofModemSettings); pModemSettings = (MODEMSETTINGS* )(((BYTE* )&pDevCfg->commconfig) + pDevCfg->commconfig.dwProviderOffset); TRACE1( "SanitizeUnimodemBlob: mdm prot=%d", MDM_GET_EXTENDEDINFO(pModemSettings->dwPreferredModemOptions)); /* No unimodem service provider pre/post-connect terminal, operator dial, ** or tray lights. RAS does these itself. */ pDevCfg->dfgHdr.fwOptions = 0; pDevCfg->commconfig.dcb.fBinary = TRUE; pDevCfg->commconfig.dcb.fParity = TRUE; pDevCfg->commconfig.dcb.fOutxDsrFlow = FALSE; pDevCfg->commconfig.dcb.fDtrControl = DTR_CONTROL_ENABLE; pDevCfg->commconfig.dcb.fTXContinueOnXoff = FALSE; pDevCfg->commconfig.dcb.fOutX = FALSE; pDevCfg->commconfig.dcb.fInX = FALSE; pDevCfg->commconfig.dcb.fErrorChar = FALSE; pDevCfg->commconfig.dcb.fNull = FALSE; pDevCfg->commconfig.dcb.fAbortOnError = FALSE; pDevCfg->commconfig.dcb.ByteSize = 8; pDevCfg->commconfig.dcb.Parity = NOPARITY; pDevCfg->commconfig.dcb.StopBits = ONESTOPBIT; /* Wait 55 seconds to establish call. */ /* pModemSettings->dwCallSetupFailTimer = 55; */ /* Disable inactivity timeout. */ pModemSettings->dwInactivityTimeout = 0; } VOID SetDefaultUnimodemInfo( OUT UNIMODEMINFO* pInfo ) /* Sets 'pInfo' to default settings. */ { pInfo->fHwFlow = FALSE; pInfo->fEc = FALSE; pInfo->fEcc = FALSE; pInfo->dwBps = 9600; pInfo->fSpeaker = TRUE; pInfo->fOperatorDial = FALSE; pInfo->fUnimodemPreTerminal = FALSE; } VOID UnimodemProtInfoFromExtendedCaps( OUT UNIMODEMINFO* pInfo, IN BYTE* pExtCapsBlob) /* Loads the modem protocol info for 'pInfo' from the extended caps ** blob retrieved from tapi. ** */ { MODEM_PROTOCOL_CAPS* lpProtCaps = NULL; PROTOCOL_ITEM* pProtItem = NULL; DWORD dwIndex; do { // Extract the modem caps // lpProtCaps = (MODEM_PROTOCOL_CAPS *)pExtCapsBlob; if (lpProtCaps->hdr.dwSig != dwSIG_MODEM_PROTOCOL_CAPS || lpProtCaps->dwNumProtocols == 0 || lpProtCaps->dwProtocolListOffset == 0) { break; } // If no protocols are supported, don't bother creating the // list if (lpProtCaps->dwNumProtocols == 0) { break; } // Create the list // pInfo->pListProtocols = DtlCreateList(0); if (pInfo->pListProtocols == NULL) { break; } // Get the list of supported protocols // pProtItem = (PROTOCOL_ITEM*) (((LPBYTE)lpProtCaps) + lpProtCaps->dwProtocolListOffset); // Enumerate the protocols // for (dwIndex = 0; dwIndex < lpProtCaps->dwNumProtocols; dwIndex++, pProtItem++) { DTLNODE * pNode = NULL; PWCHAR pszName = NULL; DWORD dwSize; // Get the friendly name from the structure // pszName = (PWCHAR) (pExtCapsBlob + pProtItem->dwProtocolNameOffset); if (pszName == NULL) { continue; } // Calculate the size of the friendly name // dwSize = (wcslen(pszName) + 1) * sizeof(WCHAR); // Allocate a node accordingly // pNode = DtlCreateSizedNode(dwSize, (LONG_PTR)pProtItem->dwProtocol); if (pNode == NULL) { continue; } // Initialize the node and add it to the list // wcscpy((PWCHAR) DtlGetData(pNode), pszName); DtlAddNodeLast(pInfo->pListProtocols, pNode); } } while (FALSE); // Cleanup { } } VOID UnimodemInfoFromBlob( IN BYTE* pBlob, OUT UNIMODEMINFO* pInfo ) /* Loads 'pInfo' with RAS-relevant Unimodem information retrieved from ** Unimodem blob 'pBlob'. ** ** (Based on Gurdeepian routine) */ { DEVCFG* pDevCfg; MODEMSETTINGS* pModemSettings; RAS_DEVCONFIG* pRasDevCfg; pRasDevCfg = (RAS_DEVCONFIG*)pBlob; pDevCfg = (DEVCFG *) ((PBYTE) pRasDevCfg + pRasDevCfg->dwOffsetofModemSettings); pModemSettings = (MODEMSETTINGS* )(((BYTE* )&pDevCfg->commconfig) + pDevCfg->commconfig.dwProviderOffset); pInfo->fSpeaker = (pModemSettings->dwSpeakerMode != MDMSPKR_OFF) ? TRUE : FALSE; pInfo->fHwFlow = (pModemSettings->dwPreferredModemOptions & MDM_FLOWCONTROL_HARD) ? TRUE : FALSE; pInfo->fEcc = (pModemSettings->dwPreferredModemOptions & MDM_COMPRESSION) ? TRUE : FALSE; pInfo->fEc = (pModemSettings->dwPreferredModemOptions & MDM_ERROR_CONTROL) ? TRUE : FALSE; pInfo->dwBps = pDevCfg->commconfig.dcb.BaudRate; pInfo->fOperatorDial = (pDevCfg->dfgHdr.fwOptions & MANUAL_DIAL) ? TRUE : FALSE; pInfo->fUnimodemPreTerminal = (pDevCfg->dfgHdr.fwOptions & TERMINAL_PRE) ? TRUE : FALSE; // Get the modem protocol // pInfo->dwModemProtocol = MDM_GET_EXTENDEDINFO(pModemSettings->dwPreferredModemOptions); // Pull out the extended caps stuff // if ( pRasDevCfg->dwSizeofExtendedCaps ) { UnimodemProtInfoFromExtendedCaps( pInfo, (BYTE*)(pBlob + pRasDevCfg->dwOffsetofExtendedCaps)); } else { pInfo->pListProtocols = NULL; } } VOID UnimodemInfoToBlob( IN UNIMODEMINFO* pInfo, IN OUT BYTE* pBlob ) /* Applies RAS-relevant Unimodem information supplied in 'pInfo' to ** Unimodem blob 'pBlob'. ** ** (Based on Gurdeepian routine) */ { DEVCFG* pDevCfg; MODEMSETTINGS* pModemSettings; RAS_DEVCONFIG* pRasDevCfg; pRasDevCfg = (RAS_DEVCONFIG*) pBlob; // Pull out the device config stuff // pDevCfg = (DEVCFG *) ((PBYTE) pRasDevCfg + pRasDevCfg->dwOffsetofModemSettings); pModemSettings = (MODEMSETTINGS* )(((BYTE* )&pDevCfg->commconfig) + pDevCfg->commconfig.dwProviderOffset); pModemSettings->dwSpeakerMode = (pInfo->fSpeaker) ? MDMSPKR_DIAL : MDMSPKR_OFF; if (pInfo->fHwFlow) { pDevCfg->commconfig.dcb.fOutxCtsFlow = TRUE; pDevCfg->commconfig.dcb.fRtsControl = RTS_CONTROL_HANDSHAKE; pModemSettings->dwPreferredModemOptions |= MDM_FLOWCONTROL_HARD; } else { pDevCfg->commconfig.dcb.fOutxCtsFlow = FALSE; pDevCfg->commconfig.dcb.fRtsControl = RTS_CONTROL_DISABLE; pModemSettings->dwPreferredModemOptions &= ~(MDM_FLOWCONTROL_HARD); } if (pInfo->fEc) pModemSettings->dwPreferredModemOptions |= MDM_ERROR_CONTROL; else pModemSettings->dwPreferredModemOptions &= ~(MDM_ERROR_CONTROL); if (pInfo->fEcc) pModemSettings->dwPreferredModemOptions |= MDM_COMPRESSION; else pModemSettings->dwPreferredModemOptions &= ~(MDM_COMPRESSION); pDevCfg->commconfig.dcb.BaudRate = pInfo->dwBps; if (pInfo->fOperatorDial) pDevCfg->dfgHdr.fwOptions |= MANUAL_DIAL; if (pInfo->fUnimodemPreTerminal) pDevCfg->dfgHdr.fwOptions |= TERMINAL_PRE; // Set the modem protocol // MDM_SET_EXTENDEDINFO( pModemSettings->dwPreferredModemOptions, pInfo->dwModemProtocol); } WCHAR *GetUnicodeName(HPORT hport) { WCHAR *pwsz = Malloc(sizeof(WCHAR) * (MAX_DEVICE_NAME + 1)); if(NULL != pwsz) { if(ERROR_SUCCESS != RasGetUnicodeDeviceName( hport, pwsz)) { Free(pwsz); pwsz = NULL; } } return pwsz; }