/* 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 /* 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 /*---------------------------------------------------------------------------- ** Local prototypes **---------------------------------------------------------------------------- */ DWORD GetRasDevices( IN CHAR* pszDeviceType, OUT RASMAN_DEVICE** ppDevices, OUT WORD* pwEntries ); 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)UlongToPtr(pdev->RD_Handle) == (HPORT)INVALID_HANDLE_VALUE) { return ERROR_INVALID_HANDLE; } ASSERT(g_pRasPortClearStatistics); return (fBundle ? g_pRasBundleClearStatistics((HPORT)UlongToPtr(pdev->RD_Handle)) : g_pRasPortClearStatistics((HPORT)UlongToPtr(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; WORD wPorts; RASMAN_PORT* pPorts; TRACE("DeviceIdFromDeviceName"); dwId = 0xFFFFFFFE; if (pszDeviceName) { dwErr = GetRasPorts( &pPorts, &wPorts ); if (dwErr == 0) { CHAR* pszDeviceNameA; pszDeviceNameA = StrDupAFromT( pszDeviceName ); if (pszDeviceNameA) { INT i; RASMAN_PORT* pPort; for (i = 0, pPort = pPorts; i < wPorts; ++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 GetRasDevices( IN CHAR* pszDeviceType, OUT RASMAN_DEVICE** ppDevices, OUT WORD* pwEntries ) /* 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. */ { WORD wSize = 0; DWORD dwErr; TRACE1("GetRasDevices(%s)",pszDeviceType); ASSERT(g_pRasDeviceEnum); TRACE("RasDeviceEnum..."); dwErr = g_pRasDeviceEnum( pszDeviceType, NULL, &wSize, pwEntries ); TRACE2("RasDeviceEnum=%d,c=%d",dwErr,*pwEntries); if (dwErr == 0) { /* No devices to enumerate. Set up to allocate a single byte anyway, ** so things work without lots of special code. */ wSize = 1; } else if (dwErr != ERROR_BUFFER_TOO_SMALL) return dwErr; *ppDevices = (RASMAN_DEVICE* )Malloc( wSize ); if (!*ppDevices) return ERROR_NOT_ENOUGH_MEMORY; TRACE("RasDeviceEnum..."); dwErr = g_pRasDeviceEnum( pszDeviceType, (PBYTE )*ppDevices, &wSize, pwEntries ); 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; WORD wSize = 0; INT i; TRACE2("GetRasDeviceString(%s,%s)",pszDeviceName,pszKey); *ppszValue = NULL; do { ASSERT(g_pRasDeviceGetInfo); TRACE("RasDeviceGetInfo..."); dwErr = g_pRasDeviceGetInfo( hport, pszDeviceType, pszDeviceName, NULL, &wSize ); TRACE2("RasDeviceGetInfo=%d,s=%d",dwErr,(INT)wSize); if (dwErr != ERROR_BUFFER_TOO_SMALL && dwErr != 0) break; /* So it will fall thru and be "not found". */ if (wSize == 0) wSize = 1; pDeviceInfo = (RASMAN_DEVICEINFO* )Malloc( wSize ); if (!pDeviceInfo) return ERROR_NOT_ENOUGH_MEMORY; TRACE("RasDeviceGetInfo..."); dwErr = g_pRasDeviceGetInfo( hport, pszDeviceType, pszDeviceName, (PBYTE )pDeviceInfo, &wSize ); TRACE2("RasDeviceGetInfo=%d,s=%d",dwErr,(INT)wSize); 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 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 WORD* pwEntries ) /* 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( MXS_PAD_TXT, ppDevices, pwEntries ); } 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; DWORD dwErr; TRACE("GetRasPortMaxBps"); dwErr = GetRasPortString( hport, SER_CONNECTBPS_KEY, &pszValue, XLATE_None ); if (dwErr == 0) *pdwMaxConnectBps = (DWORD )atol( pszValue ); else *pdwMaxConnectBps = 0; dwErr = GetRasPortString( hport, SER_CARRIERBPS_KEY, &pszValue, XLATE_None ); if (dwErr == 0) *pdwMaxCarrierBps = (DWORD )atol( pszValue ); else *pdwMaxCarrierBps = 0; } 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; WORD wSize = 0; INT i; TRACE("GetRasPortParam"); *ppPortInfo = NULL; do { ASSERT(g_pRasPortGetInfo); TRACE("RasPortGetInfo"); dwErr = g_pRasPortGetInfo( hport, NULL, &wSize ); TRACE2("RasPortGetInfo=%d,s=%d",dwErr,(INT)wSize); if (dwErr != ERROR_BUFFER_TOO_SMALL && dwErr != 0) break; /* So it will fall thru and be "not found". */ if (wSize == 0) wSize = 1; *ppPortInfo = (RASMAN_PORTINFO* )Malloc( wSize ); if (!*ppPortInfo) return ERROR_NOT_ENOUGH_MEMORY; TRACE("RasPortGetInfo"); dwErr = g_pRasPortGetInfo( hport, (PBYTE )*ppPortInfo, &wSize ); TRACE2("RasPortGetInfo=%d,s=%d",dwErr,(INT)wSize); 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( OUT RASMAN_PORT** ppPorts, OUT WORD* pwEntries ) /* 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. */ { WORD wSize = 0; DWORD dwErr; TRACE("GetRasPorts"); #if 0 // Phonebook test dummies { RASMAN_PORT* pPort; TRACE("TEST: Fake ISDN ports"); *pwEntries = 5; wSize = *pwEntries * sizeof(RASMAN_PORT); *ppPorts = (RASMAN_PORT* )Malloc( wSize ); if (!*ppPorts) return ERROR_NOT_ENOUGH_MEMORY; pPort = *ppPorts; 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" ); ++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" ); ++pPort; 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" ); ++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" ); ++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" ); return 0; } #else ASSERT(g_pRasPortEnum); TRACE("RasPortEnum..."); dwErr = g_pRasPortEnum( NULL, &wSize, pwEntries ); TRACE2("RasPortEnum=%d,c=%d",dwErr,(INT)*pwEntries); if (dwErr == 0) { /* No ports to enumerate. Set up to allocate a single byte anyway, so ** things work without lots of special code. */ wSize = 1; } else if (dwErr != ERROR_BUFFER_TOO_SMALL) return dwErr; *ppPorts = (RASMAN_PORT* )Malloc( wSize ); if (!*ppPorts) return ERROR_NOT_ENOUGH_MEMORY; TRACE("RasPortEnum..."); dwErr = g_pRasPortEnum( (PBYTE )*ppPorts, &wSize, pwEntries ); TRACE2("RasPortEnum=%d,c=%d",dwErr,(INT)*pwEntries); if (dwErr != 0) { Free( *ppPorts ); *ppPorts = NULL; return dwErr; } #endif #if 1 // Verbose trace { RASMAN_PORT* pPort; WORD i; for (pPort = *ppPorts, i = 0; i < *pwEntries; ++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( OUT RASMAN_DEVICE** ppDevices, OUT WORD* pwEntries ) /* 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( MXS_SWITCH_TXT, ppDevices, pwEntries ); } DWORD GetRasUnimodemBlob( IN HPORT hport, IN CHAR* pszDeviceType, 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; cbBlob = 0; ASSERT(g_pRasGetDevConfig); TRACE("RasGetDevConfig"); dwErr = g_pRasGetDevConfig( hport, pszDeviceType, NULL, &cbBlob ); TRACE1("RasGetDevConfig=%d",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("RasGetDevConfig"); dwErr = g_pRasGetDevConfig( hport, pszDeviceType, pBlob, &cbBlob ); TRACE1("RasGetDevConfig=%d",dwErr); if (dwErr != 0) { Free( pBlob ); return dwErr; } SanitizeUnimodemBlob( pBlob ); } else pBlob = NULL; *ppBlob = pBlob; *pcbBlob = cbBlob; return dwErr; } VOID GetRasUnimodemInfo( 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; DWORD cbBlob; SetDefaultUnimodemInfo( pInfo ); dwErr = GetRasUnimodemBlob( hport, pszDeviceType, &pBlob, &cbBlob ); if (dwErr == 0 && cbBlob > 0) UnimodemInfoFromBlob( pBlob, pInfo ); Free0( pBlob ); } 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; CHAR* pszBuf; CHAR* pszOut; 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'; pszOut = Realloc( pszBuf, lstrlenA( pszBuf ) + 1 ); if(!pszOut) { Free(pszBuf); return NULL; } return pszOut; } VOID SanitizeUnimodemBlob( IN OUT BYTE* pBlob ) /* Fix non-RAS-compatible settings in unimodem blob 'pBlob'. ** ** (Based on Gurdeepian routine) */ { DEVCFG* pDevCfg; MODEMSETTINGS* pModemSettings; pDevCfg = (DEVCFG* )pBlob; pModemSettings = (MODEMSETTINGS* )(((BYTE* )&pDevCfg->commconfig) + pDevCfg->commconfig.dwProviderOffset); /* 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 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; pDevCfg = (DEVCFG* )pBlob; 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; } 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; pDevCfg = (DEVCFG* )pBlob; 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; }