2025-04-27 07:49:33 -04:00

2148 lines
59 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/******************************************************************\
* Microsoft Windows NT *
* Copyright(c) Microsoft Corp., 1992 *
\******************************************************************/
/*++
Module Name:
NMAPI.C
Description:
This module contains code for all the RASADMIN APIs
that communicate with the server using Named pipes.
RasAdminPortEnum
RasAdminPortGetInfo
RasAdminPortClearStatistics
RasAdminServerGetInfo
RasAdminPortDisconnect
BuildPipeName - internal routine
GetRasServerVersion - internal routine
Author:
Janakiram Cherala (RamC) July 7,1992
Revision History:
Jan 04,1993 RamC Set the Media type to MEDIA_RAS10_SERIAL in
RasAdminPortEnum to fix a problem with port
enumeration against downlevel servers.
Changed the hardcoded stats indices to defines
Aug 25,1992 RamC Code review changes:
o changed all lpbBuffers to actual structure
pointers.
o changed all LPWSTR to LPWSTR
July 7,1992 RamC Ported from RAS 1.0 (Original version
written by Narendra Gidwani - nareng)
--*/
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <stdlib.h>
#include <string.h>
#include <lm.h>
#include <malloc.h>
#include <memory.h>
#include <raserror.h>
#include <rassapi.h>
#include <rassapip.h>
#include <util.h> // utility function prototypes
#include "sdebug.h"
#define NUM_PIPE_TRIES 2
static HANDLE hmem, hnewmem;
DWORD PipeRequest(
const WCHAR * Server,
PBYTE Request,
DWORD SizeOfRequest,
PBYTE Response,
DWORD SizeOfResponse
);
DWORD APIENTRY RasAdminPortEnum(
IN const WCHAR * lpszServer,
OUT PRAS_PORT_0 *ppRasPort0,
OUT WORD *pcEntriesRead
)
/*++
Routine Description:
This routine enumerates all the ports on the specified server
and fills up the caller's lpBuffer with an array of RAS_PORT_0
structures for each port. A NULL lpszServer indicates the
local server.
Arguments:
lpszServer name of the server to enumerate ports on.
pRasPort0 pointer to a buffer in which port information is
returned as an array of RAS_PORT_0 structures.
pcEntriesRead The number of RAS_PORT_0 entries loaded.
Return Value:
ERROR_SUCCESS if successful
One of the following non-zero error codes indicating failure:
NERR_ItemNotFound indicates no ports were found.
error codes from CallNamedPipe.
ERROR_MORE_DATA indicating more data is available.
--*/
{
WORD i;
DWORD dwRetCode;
DWORD dwVersion;
PRAS_PORT_0 pRasPort0;
ASSERT( lpszServer );
// find the RasServer Version first
if (dwRetCode = GetRasServerVersion(lpszServer, &dwVersion))
{
return(dwRetCode);
}
IF_DEBUG(STACK_TRACE)
SS_PRINT(("RasAdminPortEnum: Ras Server %ws is Version %d\n",
lpszServer, dwVersion));
//
// do the downlevel thing
//
if (dwVersion == RASDOWNLEVEL)
{
struct PortEnumRequestPkt SendEnum;
P_PORT_ENUM_REQUEST_PKT PSendEnum;
struct PortEnumReceivePkt ReceiveEnum;
P_PORT_ENUM_RECEIVE_PKT PReceiveEnum;
IF_DEBUG(STACK_TRACE)
SS_PRINT(("RasAdminPortEnum: Processing Downlevel code\n"));
SendEnum.Request = RASADMINREQ_ENUM_PORTS;
PackPortEnumRequestPkt(&SendEnum, &PSendEnum);
if (dwRetCode = PipeRequest(
lpszServer,
(PBYTE) &PSendEnum,
sizeof(PSendEnum),
(PBYTE) &PReceiveEnum,
sizeof(PReceiveEnum)) )
{
return (dwRetCode);
}
UnpackPortEnumReceivePkt(&PReceiveEnum, &ReceiveEnum);
if (ReceiveEnum.RetCode)
{
return(ReceiveEnum.RetCode);
}
//
// We have the data. So we'll allocate a buffer for the app
// that we'll copy the data in to and return.
//
*ppRasPort0 = GlobalAlloc(GMEM_FIXED,
ReceiveEnum.TotalAvail * sizeof(RAS_PORT_0));
if (!*ppRasPort0)
{
return (GetLastError());
}
// else copy the data to users buffer item by item
*pcEntriesRead = ReceiveEnum.TotalAvail;
for (i=0, pRasPort0 = *ppRasPort0; i<*pcEntriesRead; i++, pRasPort0++)
{
// convert RAS1.0 info to RAS 2.0 info
struct dialin_port_info_0 *pRas10PortInfo0 = &ReceiveEnum.Data[i];
// get the port name from the RAS 1.0 style PortID
GetPortName(pRas10PortInfo0->dporti0_comid, pRasPort0->wszPortName);
pRasPort0->Flags = MESSENGER_PRESENT;
if ((pRas10PortInfo0->dporti0_modem_condition ==
RAS_MODEM_OPERATIONAL) &&
(pRas10PortInfo0->dporti0_line_condition ==
RAS_PORT_AUTHENTICATED))
{
pRasPort0->Flags |= USER_AUTHENTICATED;
}
// force these flags for a downlevel server
// because these Flags were not available for the downlevel server.
pRasPort0->Flags |= REMOTE_LISTEN;
pRasPort0->Flags |= GATEWAY_ACTIVE;
lstrcpy((LPTSTR) pRasPort0->wszDeviceType,
(LPCTSTR) DEVICE_TYPE_DEFAULT);
lstrcpy((LPTSTR) pRasPort0->wszDeviceName,
(LPCTSTR) DEVICE_NAME_DEFAULT);
lstrcpy((LPTSTR) pRasPort0->wszMediaName,
(LPCTSTR) MEDIA_NAME_DEFAULT);
pRasPort0->reserved = MEDIA_RAS10_SERIAL;
// rest of info is only valid if authenticated
if (pRasPort0->Flags & USER_AUTHENTICATED)
{
mbstowcs(pRasPort0->wszUserName,
pRas10PortInfo0->dporti0_username, LM20_UNLEN);
mbstowcs(pRasPort0->wszComputer,
pRas10PortInfo0->dporti0_computer, NETBIOS_NAME_LEN+1);
pRasPort0->dwStartSessionTime =
pRas10PortInfo0->dporti0_time;
}
else
{
lstrcpyW(pRasPort0->wszUserName, L"");
lstrcpyW(pRasPort0->wszComputer, L"");
pRasPort0->dwStartSessionTime = 0L;
}
//
// Logon domain not supplied by RAS 1.x server, so we NULL it out
//
lstrcpyW(pRasPort0->wszLogonDomain, L"");
pRasPort0->fAdvancedServer = TRUE;
}
} // end if RASDOWNLEVEL
else
{
// RAS 2.0 or greater
CLIENT_REQUEST SendEnum;
P_CLIENT_REQUEST PSendEnum;
PORT_ENUM_RECEIVE RecvEnum;
PP_PORT_ENUM_RECEIVE pPRecvEnum;
DWORD cbPRecvBuf;
DWORD BytesToWrite = sizeof(PSendEnum);
USHORT ResumePort = 0; // if there is > 64K data this resume port
// is used to retrieve additional data
IF_DEBUG(STACK_TRACE)
SS_PRINT(("RasAdminPortEnum: Processing RAS 2.0+ code\n"));
SendEnum.RequestCode = RASADMIN20_REQ_ENUM_PORTS;
SendEnum.RcvBufSize = 0L; // this will force server to tell us how
// many ports there are
pPRecvEnum = GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT,
sizeof(P_PORT_ENUM_RECEIVE));
if (!pPRecvEnum)
{
return (GetLastError());
}
//
// Early versions of NT Admin do not support client version
// number in the request, so we won't write it.
//
if (dwVersion == RAS_SERVER_20)
{
BytesToWrite -= 4;
}
//
// Send the request to the server to find out the buffer size
// required. This call should always fail with
// ReceiveEnum.TotalAvail indicating how many ports are being
// enumerated. We can then get memory for the data and send
// the request to the server again.
//
PackClientRequest(&SendEnum, &PSendEnum);
if (dwRetCode = PipeRequest(
lpszServer,
(PBYTE) &PSendEnum,
BytesToWrite,
(PBYTE) pPRecvEnum,
sizeof(P_PORT_ENUM_RECEIVE) ))
{
GlobalFree(pPRecvEnum);
return (dwRetCode);
}
if (dwRetCode = UnpackPortEnumReceive(pPRecvEnum, &RecvEnum))
{
GlobalFree(pPRecvEnum);
return (dwRetCode);
}
GlobalFree(pPRecvEnum);
// check the result of the request
if (RecvEnum.RetCode)
{
SS_PRINT(("RasAdminPortEnum: server result code=%li\n",
RecvEnum.RetCode));
if (RecvEnum.RetCode == NERR_BufTooSmall)
{
// -1 accounts for the fact that P_PORT_ENUM_RECEIVE contains
// space for 1 P_RAS_PORT_0 structure.
cbPRecvBuf = sizeof(P_PORT_ENUM_RECEIVE) +
sizeof(P_RAS_PORT_0) * (RecvEnum.TotalAvail - 1);
pPRecvEnum = GlobalAlloc(GMEM_FIXED|GMEM_ZEROINIT, cbPRecvBuf);
if (!pPRecvEnum)
{
return (GetLastError());
}
SendEnum.RcvBufSize = cbPRecvBuf;
PackClientRequest(&SendEnum, &PSendEnum);
if (dwRetCode = PipeRequest(
lpszServer,
(PBYTE) &PSendEnum,
BytesToWrite,
(PBYTE) pPRecvEnum,
cbPRecvBuf ))
{
GlobalFree(pPRecvEnum);
return (dwRetCode);
}
dwRetCode = UnpackPortEnumReceive(pPRecvEnum, &RecvEnum);
GlobalFree(pPRecvEnum);
if (dwRetCode)
{
return (dwRetCode);
}
if (RecvEnum.RetCode)
{
// check for more data from the server
if(RecvEnum.RetCode == ERROR_MORE_DATA)
{
// while there are more ports, get them all
while(RecvEnum.RetCode == ERROR_MORE_DATA)
{
ResumePort += RecvEnum.TotalAvail;
SendEnum.RequestCode = RASADMIN20_REQ_ENUM_RESUME;
cbPRecvBuf = sizeof(P_PORT_ENUM_RECEIVE) +
sizeof(P_RAS_PORT_0) *
(RecvEnum.TotalAvail - 1);
pPRecvEnum = GlobalAlloc(GMEM_FIXED|GMEM_ZEROINIT,
cbPRecvBuf);
if (!pPRecvEnum)
{
GlobalFree(pPRecvEnum);
return (GetLastError());
}
SendEnum.RcvBufSize = cbPRecvBuf;
PackResumeRequest(&SendEnum, &PSendEnum, ResumePort);
if (dwRetCode = PipeRequest(lpszServer,
(PBYTE) &PSendEnum,
BytesToWrite,
(PBYTE) pPRecvEnum,
cbPRecvBuf ))
{
GlobalFree(pPRecvEnum);
return (dwRetCode);
}
dwRetCode = UnpackResumeEnumReceive(pPRecvEnum,
&RecvEnum,
ResumePort);
GlobalFree(pPRecvEnum);
if (dwRetCode)
{
return (dwRetCode);
}
}
}
else
{
SS_PRINT(("RasAdminPortEnum: server result code=%li\n",
RecvEnum.RetCode));
return (RecvEnum.RetCode);
}
}
}
else
{
return (RecvEnum.RetCode);
}
}
//
// if no entries found we indicate that
//
*pcEntriesRead = RecvEnum.TotalAvail + ResumePort;
if (*pcEntriesRead == 0)
{
return (NERR_ItemNotFound);
}
//
// We have some ports. Now, get the port information.
//
RecvEnum.Data = (RAS_PORT_0 *)GlobalLock(hmem);
if (!RecvEnum.Data)
{
return (GetLastError());
}
// Allocate the required memory
*ppRasPort0 = GlobalAlloc(GMEM_FIXED,
*pcEntriesRead * sizeof(RAS_PORT_0));
if (!*ppRasPort0)
{
return (GetLastError());
}
// Copy it to the destination buffer
memcpy( *ppRasPort0,
RecvEnum.Data,
*pcEntriesRead * sizeof(RAS_PORT_0));
GlobalUnlock((HGLOBAL)RecvEnum.Data);
GlobalFree(RecvEnum.Data);
if (dwVersion == RAS_SERVER_20)
{
for (i=0, pRasPort0 = *ppRasPort0;
i<*pcEntriesRead; i++, pRasPort0++)
{
// force these flags for a downlevel server
// because these Flags were not available for the downlevel server.
pRasPort0->Flags |= REMOTE_LISTEN;
pRasPort0->Flags |= GATEWAY_ACTIVE;
}
}
} // end else RASDOWNLEVEL
if (insert_list_head(*ppRasPort0, RASADMIN_PORT_ENUM_PTR, 0L))
{
GlobalFree(*ppRasPort0);
return (ERROR_NOT_ENOUGH_MEMORY);
}
SS_PRINT(("RasAdminPortEnum: Completed successfully\n"));
return(ERROR_SUCCESS);
}
DWORD APIENTRY RasAdminPortGetInfo(
IN const WCHAR * lpszServer,
IN const WCHAR * lpszPort,
OUT RAS_PORT_1 * pRasPort1,
OUT RAS_PORT_STATISTICS * pRasStats,
OUT RAS_PARAMETERS ** ppRasParams
)
/*++
Routine Description:
This routine retrieves information associated with a port on the
server. It loads the caller's pRasPort1 with a RAS_PORT_1 structure.
Arguments:
lpszServer name of the server which has the port, eg.,"\\SERVER"
lpszPort port name to retrieve information for, e.g. "COM1".
pRasPort1 pointer to a buffer in which port information is
returned. The returned info is a RAS_PORT_1 structure.
pRasStats pointer to a buffer in which port statistics information is
returned. The returned info is a RAS_PORT_STATISTICS structure.
ppRasParams pointer to a buffer in which port parameters information is
returned. The returned info is an array of RAS_PARAMETERS structure.
It is the responsibility of the caller to free this buffer calling
RasAdminBufferFree.
Return Value:
ERROR_SUCCESS on successful return.
One of the following non-zero error codes indicating failure:
ERROR_MORE_DATA indicating that more data than can fit in
pRasPort1 is available
return codes from CallNamedPipe.
ERROR_DEV_NOT_EXIST indicating requested port is invalid.
--*/
{
DWORD dwVersion;
DWORD dwRetCode;
WCHAR portname[RAS10_MAX_PORT_NAME]; // used in GetPortName
WCHAR tmpbuffer[UNLEN+1]; // used in mbs-wcs conversion
DWORD RasStatsSize;
DWORD NumParms;
ASSERT (lpszServer);
ASSERT (lpszPort);
// find the RasServer Version first
if (dwRetCode = GetRasServerVersion(lpszServer, &dwVersion))
{
return(dwRetCode);
}
if (dwVersion == RASDOWNLEVEL)
{
struct PortInfoRequestPkt SendInfo;
P_PORT_INFO_REQUEST_PKT PSendInfo;
struct PortInfoReceivePkt ReceiveInfo;
P_PORT_INFO_RECEIVE_PKT PReceiveInfo;
SendInfo.Request = RASADMINREQ_GET_PORT_INFO;
if ((SendInfo.ComId = GetPortId(lpszPort)) == -1 ) {
return(ERROR_DEV_NOT_EXIST);
}
PackPortInfoRequestPkt(&SendInfo, &PSendInfo);
if (dwRetCode = PipeRequest(
lpszServer,
(PBYTE) &PSendInfo,
sizeof(PSendInfo),
(PBYTE) &PReceiveInfo,
sizeof(PReceiveInfo) ))
{
return (dwRetCode);
}
UnpackPortInfoReceivePkt(&PReceiveInfo, &ReceiveInfo);
if (ReceiveInfo.RetCode)
{
return (ReceiveInfo.RetCode);
}
else
{
// convert RAS1.0 info to RAS 2.0 info
PRAS_PORT_0 pRasPort0 = &pRasPort1->rasport0;
struct dialin_port_info_1 *pRas10Port1 = &ReceiveInfo.Data;
WpdStatisticsInfo *pRas10Stats = &pRas10Port1->dporti1_stats;
struct dialin_port_info_0 *pRas10Port0 = &pRas10Port1->dporti0;
mbstowcs(tmpbuffer, pRas10Port0->dporti0_username, LM20_UNLEN + 1);
lstrcpy((LPTSTR) pRasPort0->wszUserName, (LPCTSTR) tmpbuffer);
mbstowcs(tmpbuffer, pRas10Port0->dporti0_computer,
NETBIOS_NAME_LEN + 1);
lstrcpy((LPTSTR) pRasPort0->wszComputer, (LPCTSTR) tmpbuffer);
lstrcpy((LPTSTR) pRasPort0->wszLogonDomain, (LPCTSTR) "");
pRasPort0->fAdvancedServer = TRUE;
// get the port name from the RAS 1.0 style PortID
GetPortName(pRas10Port0->dporti0_comid, portname);
lstrcpy((LPTSTR) pRasPort0->wszPortName, (LPCTSTR) portname);
lstrcpy((LPTSTR) pRasPort0->wszDeviceType,
(LPCTSTR) DEVICE_TYPE_DEFAULT);
lstrcpy((LPTSTR) pRasPort0->wszDeviceName,
(LPCTSTR) DEVICE_NAME_DEFAULT);
lstrcpy((LPTSTR) pRasPort0->wszMediaName,
(LPCTSTR) MEDIA_NAME_DEFAULT);
pRasPort0->reserved = MEDIA_RAS10_SERIAL;
pRasPort0->dwStartSessionTime = pRas10Port0->dporti0_time;
pRasPort0->Flags = MESSENGER_PRESENT;
if ((pRas10Port0->dporti0_modem_condition ==
RAS_MODEM_OPERATIONAL) &&
(pRas10Port0->dporti0_line_condition ==
RAS_PORT_AUTHENTICATED))
{
pRasPort0->Flags |= USER_AUTHENTICATED;
}
// force these flags for a downlevel server
// because these Flags were not available for the downlevel server.
pRasPort0->Flags |= REMOTE_LISTEN;
pRasPort0->Flags |= GATEWAY_ACTIVE;
pRasPort1->LineSpeed = pRas10Port1->dporti1_baud;
pRasPort1->LineCondition = pRas10Port0->dporti0_line_condition;
pRasPort1->HardwareCondition = pRas10Port0->dporti0_modem_condition;
// We have no Projection Result information, so just stub out
// the information and copy the computer name into the nbf
// address
if (pRasPort0->Flags & USER_AUTHENTICATED)
{
pRasPort1->ProjResult.nbf.dwError = SUCCESS;
pRasPort1->ProjResult.nbf.dwNetBiosError = 0;
lstrcpy((LPTSTR) pRasPort1->ProjResult.nbf.wszWksta,
(LPTSTR) pRasPort0->wszComputer);
}
else
{
pRasPort1->ProjResult.nbf.dwError = ERROR_PPP_NO_PROTOCOLS_CONFIGURED;
}
pRasPort1->ProjResult.ip.dwError = ERROR_PPP_NO_PROTOCOLS_CONFIGURED;
pRasPort1->ProjResult.ipx.dwError = ERROR_PPP_NO_PROTOCOLS_CONFIGURED;
pRasPort1->ProjResult.at.dwError = ERROR_PPP_NO_PROTOCOLS_CONFIGURED;
// Copy the statistics info
pRasPort1->NumStatistics = RAS10_MAX_STATISTICS;
memset( pRasStats, 0, sizeof(RAS_PORT_STATISTICS));
pRasStats->dwBytesRcved = pRas10Stats->stat_bytesreceived;
pRasStats->dwBytesXmited = pRas10Stats->stat_bytesxmitted;
pRasStats->dwHardwareOverrunErr = pRas10Stats->stat_overrunerr;
pRasStats->dwTimeoutErr = pRas10Stats->stat_timeouterr;
pRasStats->dwFramingErr = pRas10Stats->stat_framingerr;
pRasStats->dwCrcErr = pRas10Stats->stat_crcerr;
// And, we have no media parameters
NumParms = 0L;
pRasPort1->NumMediaParms = 0L;
*ppRasParams = (RAS_PARAMETERS *) NULL;
}
} // end if RASDOWNLEVEL
else
{
// RAS 2.0 or greater
CLIENT_REQUEST SendInfo;
P_CLIENT_REQUEST PSendInfo;
PORT_INFO_RECEIVE ReceiveInfo;
PP_PORT_INFO_RECEIVE pPReceiveInfo;
PP_PORT_INFO_RECEIVE pSavePReceiveInfo;
DWORD BytesToWrite = sizeof(PSendInfo);
WORD NumStatistics;
//
// We need to make 2 calls to the server. First is to tell
// us how big a buffer we need for getting all the the port
// data. Second is to get all the data.
//
SendInfo.RequestCode = RASADMIN20_REQ_GET_PORT_INFO;
SendInfo.RcvBufSize = sizeof(P_PORT_INFO_RECEIVE);
lstrcpy((LPTSTR) SendInfo.PortName, (LPCTSTR) lpszPort);
PackClientRequest(&SendInfo, &PSendInfo);
pPReceiveInfo = GlobalAlloc(GMEM_FIXED, sizeof(P_PORT_INFO_RECEIVE));
if (!pPReceiveInfo)
{
return (GetLastError());
}
pSavePReceiveInfo = pPReceiveInfo;
//
// Early versions of NT Admin do not support client version
// number in the request, so we won't write it.
//
if (dwVersion == RAS_SERVER_20)
{
BytesToWrite -= 4;
}
if (dwRetCode = PipeRequest(
lpszServer,
(PBYTE) &PSendInfo,
BytesToWrite,
(PBYTE) pPReceiveInfo,
sizeof(P_PORT_INFO_RECEIVE) ))
{
SS_PRINT(("RasAdminPortGetInfo: - CallNamedPipe (1) rc=%li\n",
dwRetCode));
GlobalFree(pPReceiveInfo);
return (dwRetCode);
}
UnpackPortInfoReceive(pPReceiveInfo, &ReceiveInfo, dwVersion);
if (ReceiveInfo.RetCode)
{
if ((ReceiveInfo.RetCode == ERROR_MORE_DATA) ||
(ReceiveInfo.RetCode == NERR_BufTooSmall))
{
//
// Now that we know how much space we need, let's get
// some memory and make the call again.
//
SendInfo.RequestCode = RASADMIN20_REQ_GET_PORT_INFO;
SendInfo.RcvBufSize = ReceiveInfo.ReqBufSize;
lstrcpy((LPTSTR) SendInfo.PortName, (LPCTSTR) lpszPort);
PackClientRequest(&SendInfo, &PSendInfo);
GlobalFree(pPReceiveInfo);
pPReceiveInfo = GlobalAlloc(GMEM_FIXED, ReceiveInfo.ReqBufSize);
if (!pPReceiveInfo)
{
return (GetLastError());
}
pSavePReceiveInfo = pPReceiveInfo;
if (dwRetCode = PipeRequest(
lpszServer,
(PBYTE) &PSendInfo,
BytesToWrite,
(PBYTE) pPReceiveInfo,
SendInfo.RcvBufSize ))
{
SS_PRINT(("RasPortGetInfo: - CallNamedPipe (2) rc=%li\n",
dwRetCode));
GlobalFree(pSavePReceiveInfo);
return (dwRetCode);
}
UnpackPortInfoReceive(pPReceiveInfo, &ReceiveInfo, dwVersion);
}
else
{
GlobalFree(pPReceiveInfo);
return (ReceiveInfo.RetCode);
}
}
//
// Ok, we have all the data. Let's unpack it and give it to the app.
//
pPReceiveInfo++;
if (dwVersion == RAS_SERVER_20)
{
pPReceiveInfo = (PP_PORT_INFO_RECEIVE)
(((PBYTE) pPReceiveInfo) - sizeof(P_PPP_PROJECTION_RESULT));
}
*pRasPort1 = ReceiveInfo.Data;
NumStatistics = pRasPort1->NumStatistics;
if (dwVersion == RAS_SERVER_20)
{
PRAS_PORT_0 pRasPort0 = &(pRasPort1->rasport0);
// force these flags for a downlevel server
// because these Flags were not available for the downlevel server.
pRasPort0->Flags |= REMOTE_LISTEN;
pRasPort0->Flags |= GATEWAY_ACTIVE;
// if the downlevel server port is of type ISDN, we need to
// bump up the number of statistics to account for
// BYTES_XMITED_UNCOMP, BYTES_RCVED_UNCOMP, BYTES_XMITED_COMP
// and BYTES_RCVED_COMP which was not part of the ISDN stats
if( pRasPort0->reserved == MEDIA_ISDN)
NumStatistics += 4;
}
// zero the statistics array so that unfilled array members will
// be zero - to account for the RAS_SERVER_20 ISDN server port
memset( pRasStats, 0, sizeof(RAS_PORT_STATISTICS));
// note that even though we use NumStatistics to allocate memory,
// we actually pass (*ppRasPort1)->NumStatistics to UnpackStats
// function. This is to ensure that we don't try to fetch data
// past the number of statistics in the pPReceiveInfo buffer.
UnpackStats(dwVersion, pRasPort1->NumStatistics, (PP_RAS_STATISTIC) pPReceiveInfo, pRasStats);
NumParms = ReceiveInfo.Data.NumMediaParms;
*ppRasParams = GlobalAlloc(GMEM_FIXED, NumParms*sizeof(RAS_PARAMETERS));
if (!*ppRasParams)
{
DWORD dwErr = GetLastError();
GlobalFree(pSavePReceiveInfo);
return (dwErr);
}
pPReceiveInfo = (PP_PORT_INFO_RECEIVE) (((PBYTE) pPReceiveInfo) +
(pRasPort1->NumStatistics * sizeof(DWORD)));
if (dwRetCode = UnpackParams(ReceiveInfo.Data.NumMediaParms,
(PP_RAS_PARAMS) pPReceiveInfo, *ppRasParams))
{
GlobalFree(*ppRasParams);
GlobalFree(pSavePReceiveInfo);
return(dwRetCode);
}
GlobalFree(pSavePReceiveInfo);
} // end else RASDOWNLEVEL
// add the pointers to our list - be sure to check that we are not
// adding a null pointer to the list.
if ((*ppRasParams?
insert_list_head(*ppRasParams,RASADMIN_PORT_PARAMS_PTR,NumParms):
0))
{
if (RasAdminFreeBuffer(*ppRasParams))
{
FreeParams(*ppRasParams, NumParms);
GlobalFree(*ppRasParams);
}
return (ERROR_NOT_ENOUGH_MEMORY);
}
return (ERROR_SUCCESS);
}
DWORD APIENTRY RasAdminPortClearStatistics(
IN const WCHAR * lpszServer,
IN const WCHAR * lpszPort
)
/*++
Routine Description:
This routine clears the statistics associated with the specified
port.
Arguments:
lpszServer name of the server which has the port, eg.,"\\SERVER"
lpszPort port name to retrieve information for, e.g. "COM1".
Return Value:
ERROR_SUCCESS on successful return.
One of the following non-zero error codes indicating failure:
return codes from CallNamedPipe.
ERROR_DEV_NOT_EXIST if the specified port does not belong
to RAS.
--*/
{
DWORD dwVersion;
DWORD dwRetCode;
ASSERT(lpszServer);
ASSERT(lpszPort);
// find the RasServer Version first
if (dwRetCode = GetRasServerVersion(lpszServer, &dwVersion))
{
return(dwRetCode);
}
if (dwVersion == RASDOWNLEVEL)
{
struct PortClearRequestPkt SendClear;
P_PORT_CLEAR_REQUEST_PKT PSendClear;
struct PortClearReceivePkt ReceiveClear;
P_PORT_CLEAR_RECEIVE_PKT PReceiveClear;
SendClear.Request = RASADMINREQ_CLEAR_PORT_STATS;
if((SendClear.ComId = GetPortId(lpszPort)) == -1 ) {
return(ERROR_DEV_NOT_EXIST);
}
PackPortClearRequestPkt(&SendClear, &PSendClear);
if (dwRetCode = PipeRequest(
lpszServer,
(PBYTE) &PSendClear,
sizeof(PSendClear),
(PBYTE) &PReceiveClear,
sizeof(PReceiveClear) ))
{
return (dwRetCode);
}
UnpackPortClearReceivePkt(&PReceiveClear, &ReceiveClear);
if (ReceiveClear.RetCode)
{
return(ReceiveClear.RetCode);
}
}
else
{
// RAS 2.0 or greater
CLIENT_REQUEST SendClear;
P_CLIENT_REQUEST PSendClear;
PORT_CLEAR_RECEIVE ReceiveClear;
P_PORT_CLEAR_RECEIVE PReceiveClear;
DWORD BytesToWrite = sizeof(PSendClear);
SendClear.RequestCode = RASADMIN20_REQ_CLEAR_PORT_STATS;
lstrcpy((LPTSTR) SendClear.PortName, (LPCTSTR) lpszPort);
PackClientRequest(&SendClear, &PSendClear);
//
// Early versions of NT Admin do not support client version
// number in the request, so we won't write it.
//
if (dwVersion == RAS_SERVER_20)
{
BytesToWrite -= 4;
}
if (dwRetCode = PipeRequest(
lpszServer,
(PBYTE) &PSendClear,
BytesToWrite,
(PBYTE) &PReceiveClear,
sizeof(PReceiveClear) ))
{
return (dwRetCode);
}
UnpackPortClearReceive(&PReceiveClear, &ReceiveClear);
if (ReceiveClear.RetCode)
{
return(ReceiveClear.RetCode);
}
}
return(ERROR_SUCCESS);
}
DWORD APIENTRY RasAdminServerGetInfo(
IN const WCHAR * lpszServer,
OUT PRAS_SERVER_0 pRasServer0
)
/*++
Routine Description:
This routine retrieves RAS specific information from the specified
RAS server. The server name can be NULL in which case the local
machine is assumed.
Arguments:
lpszServer name of the RAS server to get information from or
NULL for the local machine.
pRasServer0 points to a buffer to store the returned data. On
successful return this buffer contains a
RAS_SERVER_0 structure.
Return Value:
ERROR_SUCCESS on successful return.
one of the following non-zero error codes on failure:
error codes from CallNamedPipe.
NERR_BufTooSmall indicating that the input buffer is smaller
than size of RAS_SERVER_0.
--*/
{
CLIENT_REQUEST SendInfo;
P_CLIENT_REQUEST PSendInfo;
SERVER_INFO_RECEIVE ReceiveInfo;
P_SERVER_INFO_RECEIVE PReceiveInfo;
DWORD dwRetCode;
// zero the buffer to eliminate junk
memset(&ReceiveInfo, '\0', sizeof(SERVER_INFO_RECEIVE));
memset(&PReceiveInfo, '\0', sizeof(P_SERVER_INFO_RECEIVE));
SendInfo.RequestCode = RASADMIN20_REQ_GET_SERVER_INFO;
PackClientRequest(&SendInfo, &PSendInfo);
if (dwRetCode = PipeRequest(
lpszServer,
(PBYTE) &PSendInfo,
sizeof(PSendInfo.RequestCode), // this sizeof VERY IMPORTANT!!!
(PBYTE) &PReceiveInfo,
sizeof(PReceiveInfo) ))
{
return (dwRetCode);
}
UnpackServerInfoReceive(&PReceiveInfo, &ReceiveInfo);
if (ReceiveInfo.RetCode)
{
IF_DEBUG(STACK_TRACE)
SS_PRINT(("RasAdminServerGetInfo: server return code=%li\n",
ReceiveInfo.RetCode));
return (ReceiveInfo.RetCode);
}
else
{
IF_DEBUG(STACK_TRACE)
SS_PRINT(("RasAdminServerGetInfo: #ports=%i, ports in use=%i,"
" version=%li\n", ReceiveInfo.Data.TotalPorts,
ReceiveInfo.Data.PortsInUse, ReceiveInfo.Data.RasVersion));
memcpy(pRasServer0, &(ReceiveInfo.Data), sizeof(RAS_SERVER_0));
return(ERROR_SUCCESS);
}
}
DWORD APIENTRY RasAdminPortDisconnect(
IN const WCHAR * lpszServer,
IN const WCHAR * lpszPort
)
/*++
Routine Description:
This routine disconnects the user attached to the specified
port on the server lpszServer.
Arguments:
lpszServer name of the RAS server.
lpszPort name of the port, e.g. "COM1"
Return Value:
ERROR_SUCCESS on successful return.
one of the following non-zero error codes on failure:
ERROR_INVALID_PORT indicating the port name is invalid.
error codes from CallNamedPipe.
NERR_UserNotFound indicating that no user is logged on
at the specified port.
--*/
{
DWORD dwVersion;
DWORD dwRetCode;
ASSERT( lpszServer );
ASSERT( lpszPort );
// find the RasServer Version first
if (dwRetCode = GetRasServerVersion(lpszServer, &dwVersion))
{
return(dwRetCode);
}
if (dwVersion == RASDOWNLEVEL)
{
struct DisconnectUserRequestPkt SendDisconnect;
P_DISCONNECT_USER_REQUEST_PKT PSendDisconnect;
struct DisconnectUserReceivePkt ReceiveDisconnect;
P_DISCONNECT_USER_RECEIVE_PKT PReceiveDisconnect;
SendDisconnect.Request = RASADMINREQ_DISCONNECT_USER;
// get RAS 1.0 style port number from port name
if ((SendDisconnect.ComId = GetPortId(lpszPort)) == -1 )
{
return(ERROR_DEV_NOT_EXIST);
}
PackDisconnectUserRequestPkt(&SendDisconnect, &PSendDisconnect);
if (dwRetCode = PipeRequest(
lpszServer,
(PBYTE) &PSendDisconnect,
sizeof(PSendDisconnect),
(PBYTE) &PReceiveDisconnect,
sizeof(PReceiveDisconnect) ))
{
return (dwRetCode);
}
UnpackDisconnectUserReceivePkt(&PReceiveDisconnect, &ReceiveDisconnect);
if (ReceiveDisconnect.RetCode)
{
return(ReceiveDisconnect.RetCode);
}
}
else
{
// RAS 2.0 or greater
CLIENT_REQUEST SendDisconnect;
P_CLIENT_REQUEST PSendDisconnect;
DISCONNECT_USER_RECEIVE ReceiveDisconnect;
P_DISCONNECT_USER_RECEIVE PReceiveDisconnect;
DWORD BytesToWrite = sizeof(PSendDisconnect);
SendDisconnect.RequestCode = RASADMIN20_REQ_DISCONNECT_USER;
lstrcpy((LPTSTR) SendDisconnect.PortName, (LPCTSTR) lpszPort);
PackClientRequest(&SendDisconnect, &PSendDisconnect);
//
// Early versions of NT Admin do not support client version
// number in the request, so we won't write it.
//
if (dwVersion == RAS_SERVER_20)
{
BytesToWrite -= 4;
}
if (dwRetCode = PipeRequest(
lpszServer,
(PBYTE)&PSendDisconnect,
BytesToWrite,
(PBYTE)&PReceiveDisconnect,
sizeof(PReceiveDisconnect) ))
{
return (dwRetCode);
}
UnpackDisconnectUserReceive(&PReceiveDisconnect, &ReceiveDisconnect);
if (ReceiveDisconnect.RetCode)
{
return(ReceiveDisconnect.RetCode);
}
}
return(ERROR_SUCCESS);
}
DWORD RasAdminFreeBuffer(PVOID Pointer)
{
DWORD PointerType;
DWORD NumStructs;
if (remove_list(Pointer, &PointerType, &NumStructs))
{
return (ERROR_INVALID_PARAMETER);
}
switch (PointerType)
{
case RASADMIN_PORT_ENUM_PTR:
case RASADMIN_PORT1_PTR:
case RASADMIN_PORT_STATS_PTR:
GlobalFree(Pointer);
break;
case RASADMIN_PORT_PARAMS_PTR:
{
FreeParams(Pointer, NumStructs);
GlobalFree(Pointer);
break;
}
case LANMAN_API_PTR:
NetApiBufferFree(Pointer);
break;
default:
SS_ASSERT(TRUE);
break;
}
return (ERROR_SUCCESS);
}
VOID FreeParams(PVOID Pointer, DWORD NumParms)
{
DWORD i;
for (i=0; i<NumParms; i++)
{
if (((RAS_PARAMETERS *) Pointer)[i].P_Type == ParamString)
{
GlobalFree(((RAS_PARAMETERS *) Pointer)[i].P_Value.String.Data);
}
}
}
VOID BuildPipeName(
IN const WCHAR * lpszServer,
OUT LPWSTR lpszPipeName
)
/*++
Routine Description:
This routine creates the full UNC path name of the pipe from
the server name specified in lpszServer and returns it in
lpszPipeName
Return Value:
NONE
--*/
{
WCHAR szComputerName[MAX_COMPUTERNAME_LENGTH+1];
DWORD cbComputerNameLen = MAX_COMPUTERNAME_LENGTH+1;
GET_CONSOLE; // for debugging
// adminstrating a remote server
if ((lpszServer) && (*lpszServer))
{
// If the specified server name is the same as the local server name, then
// use the LOCAL_PIPE name. This is an optimization.
if(GetComputerName(szComputerName, &cbComputerNameLen))
{
CHAR szServer[MAX_COMPUTERNAME_LENGTH+3];
CHAR szComputer[MAX_COMPUTERNAME_LENGTH+1];
// need to handle extended characters in the computer name here
// OemToCharW is not returning a unicode string, so we have to
// do the conversion ourselves ;-(
wcstombs(szServer, lpszServer, MAX_COMPUTERNAME_LENGTH+3);
OemToCharA(szServer, szServer);
wcstombs(szComputer, szComputerName, MAX_COMPUTERNAME_LENGTH+1);
OemToCharA(szComputer, szComputer);
// +2 accounts for the leading \\ characters
if(!_stricmp(szServer+2, szComputer))
{
// the computer name specified is the same as the local
// computer name. Use the LOCAL_PIPE name.
lstrcpy((LPTSTR) lpszPipeName, LOCAL_PIPE);
}
else
lstrcpy((LPTSTR) lpszPipeName, (LPCTSTR) lpszServer);
}
}
else
{
// local machine is the server
lstrcpy((LPTSTR) lpszPipeName, LOCAL_PIPE);
}
lstrcat((LPTSTR) lpszPipeName, RASADMIN_PIPE);
return;
}
DWORD GetRasServerVersion(
IN const WCHAR * lpszServerName,
OUT DWORD *pdwVersion
)
/*++
Routine Description:
This routine obtains the RAS version number from the server.
The RAS 2.0 server info structure is a superset of the
RAS 1.0 structure. So, we send a server info request to the
RAS server with a zeroed RAS 2.0 structure. If we get back
a non-zero version number we assume the server is a RAS 2.0
and greater server, else the server is 1.0.
Parameters:
lpszServerName - name of the server whose version number
is required.
pdwVersion - pointer to the variable to receive the
version number. We return the version number
if the server is a RAS 2.0 or greater server
else RASDOWNLEVEL to indicate a RAS 1.0 server.
Return Value:
ERROR_SUCCESS on successful execution.
one of the following non-zero error codes on failure:
error codes from RasAdminServerGetInfo
--*/
{
RAS_SERVER_0 ServerInfo;
NET_API_STATUS dwRetCode;
ASSERT( lpszServerName );
// zero the structure to make sure we have no garbage
memset(&ServerInfo, '\0', sizeof(RAS_SERVER_0));
if (dwRetCode = RasAdminServerGetInfo(lpszServerName, &ServerInfo))
{
IF_DEBUG(STACK_TRACE)
SS_PRINT(("GetRasServerVersion: dwRetCode = %lx\n", dwRetCode));
return (dwRetCode);
}
else
{
if (ServerInfo.RasVersion)
{
*pdwVersion = ServerInfo.RasVersion;
}
else
{
*pdwVersion = RASDOWNLEVEL;
}
}
return (ERROR_SUCCESS);
}
SHORT GetPortId(
IN const WCHAR * lpszPort
)
/*++
Routine Description:
This routine converts the RAS 2.0 style port name to RAS 1.0
style Port ID. Valid Port names are "COM1" - "COM16"
Parameters:
lpszPort - name of the port
Return Value:
returns the Port number equivalent to the port name or
-1 on error.
--*/
{
CHAR PortName[RASSAPI_MAX_PORT_NAME+1];
ASSERT( lpszPort );
wcstombs(PortName, lpszPort, RASSAPI_MAX_PORT_NAME);
if (_strnicmp(PortName, "COM", 3))
{
return (-1);
}
return ((USHORT)atoi(PortName+3));
}
VOID GetPortName(
IN USHORT PortId,
OUT LPWSTR PortName
)
/*++
Routine Description:
This routine converts the RAS 1.0 style port ID to RAS 2.0
style Port name. Valid Port ID's are 1 to 16.
Parameters:
PortId - COM port number.
PortName - returns the Port name equivalent of the Port number.
i.e., returns "COM1" if PortId is 1, "COM2" if 2
and so on.
Return Value:
NONE
--*/
{
CHAR buffer[3]; // port ID can be a max of 16 so 3 bytes should suffice
WCHAR wcbuffer[3]; // port ID can be a max of 16 so 3 bytes should suffice
lstrcpy((LPTSTR) PortName, TEXT("COM"));
// convert port ID to string
_itoa(PortId, buffer, 10);
mbstowcs(wcbuffer, buffer, sizeof(wcbuffer)/sizeof(WCHAR));
lstrcat((LPTSTR) PortName, (LPCTSTR) wcbuffer);
}
DWORD PipeRequest(
const WCHAR * Server,
PBYTE Request,
DWORD SizeOfRequest,
PBYTE Response,
DWORD SizeOfResponse
)
{
DWORD i;
DWORD dwRetCode = 1L;
DWORD BytesRead;
WCHAR PipePath[PATHLEN+1];
//
// build pipe name from the given server name
//
wcscpy(PipePath, L"");
BuildPipeName(Server, PipePath);
IF_DEBUG(STACK_TRACE)
SS_PRINT(("PipeRequest: PipeName is %ws\n", PipePath));
for (i=0; i<NUM_PIPE_TRIES; i++)
{
DWORD Ticker = GetTickCount();
if (CallNamedPipe(PipePath, Request, SizeOfRequest, Response,
SizeOfResponse, &BytesRead, NMPWAIT_NOWAIT))
{
return (0L);
}
else
dwRetCode = GetLastError();
// wait for a while before attempting to connect to the pipe again.
Sleep(250);
SS_PRINT(("Time (in msec) for CallNamedPipe to complete: %li\n",
GetTickCount() - Ticker));
}
return (dwRetCode);
}
VOID PackClientRequest(
IN PCLIENT_REQUEST Request,
OUT PP_CLIENT_REQUEST PRequest
)
{
int i;
PUTUSHORT(PRequest->RequestCode, Request->RequestCode);
for (i=0; i<RASSAPI_MAX_PORT_NAME; i++)
{
PUTUSHORT(&PRequest->PortName[i*2], Request->PortName[i]);
}
PUTULONG(PRequest->RcvBufSize, Request->RcvBufSize);
// identify our version so the server knows what information to pass back
PUTULONG(PRequest->ClientVersion, RASADMIN_CURRENT);
}
VOID
PackResumeRequest(
IN PCLIENT_REQUEST Request,
OUT PP_CLIENT_REQUEST PRequest,
IN USHORT ResumePort)
{
PUTUSHORT(PRequest->RequestCode, Request->RequestCode);
// use the unused port name field to send the resume port number to
// the server.
PUTUSHORT(&PRequest->PortName[0], ResumePort);
PUTULONG(PRequest->RcvBufSize, Request->RcvBufSize);
// identify our version so the server knows what information to pass back
PUTULONG(PRequest->ClientVersion, RASADMIN_CURRENT);
}
VOID UnpackRasPort0(
IN PP_RAS_PORT_0 pprp0,
OUT PRAS_PORT_0 prp0
)
{
int i;
for (i = 0; i < RASSAPI_MAX_PORT_NAME; i++)
{
GETUSHORT(&prp0->wszPortName[i], &pprp0->wszPortName[i*2]);
}
for (i = 0; i < RASSAPI_MAX_DEVICETYPE_NAME; i++)
{
GETUSHORT(&prp0->wszDeviceType[i], &pprp0->wszDeviceType[i*2]);
}
for (i = 0; i < RASSAPI_MAX_DEVICE_NAME; i++)
{
GETUSHORT(&prp0->wszDeviceName[i], &pprp0->wszDeviceName[i*2]);
}
for (i = 0; i < RASSAPI_MAX_MEDIA_NAME; i++)
{
GETUSHORT(&prp0->wszMediaName[i], &pprp0->wszMediaName[i*2]);
}
GETULONG(&prp0->reserved, pprp0->reserved);
GETULONG(&prp0->Flags, pprp0->Flags);
for (i = 0; i < (UNLEN + 1); i++)
{
GETUSHORT(&prp0->wszUserName[i], &pprp0->wszUserName[i*2]);
}
for (i = 0; i < (DNLEN + 1); i++)
{
GETUSHORT(&prp0->wszLogonDomain[i], &pprp0->wszLogonDomain[i*2]);
}
for (i = 0; i < NETBIOS_NAME_LEN; i++)
{
GETUSHORT(&prp0->wszComputer[i], &pprp0->wszComputer[i*2]);
}
GETULONG(&prp0->dwStartSessionTime, pprp0->dwStartSessionTime);
GETULONG(&prp0->fAdvancedServer, pprp0->fAdvancedServer);
}
VOID UnpackRasPort1(
IN PP_RAS_PORT_1 pprp1,
OUT PRAS_PORT_1 prp1,
DWORD dwServerVersion
)
{
DWORD i;
UnpackRasPort0(&pprp1->rasport0, &prp1->rasport0);
GETULONG(&prp1->LineCondition, pprp1->LineCondition);
GETULONG(&prp1->HardwareCondition, pprp1->HardwareCondition);
GETULONG(&prp1->LineSpeed, pprp1->LineSpeed);
GETUSHORT(&prp1->NumStatistics, pprp1->NumStatistics);
GETUSHORT(&prp1->NumMediaParms, pprp1->NumMediaParms);
GETULONG(&prp1->SizeMediaParms, pprp1->SizeMediaParms);
if ((dwServerVersion == RAS_SERVER_20) ||
(!(prp1->rasport0.Flags & PPP_CLIENT)))
{
if (prp1->rasport0.Flags & USER_AUTHENTICATED)
{
prp1->ProjResult.nbf.dwError = SUCCESS;
prp1->ProjResult.nbf.dwNetBiosError = 0;
lstrcpy((LPTSTR) prp1->ProjResult.nbf.wszWksta,
(LPTSTR) prp1->rasport0.wszComputer);
}
else
{
prp1->ProjResult.nbf.dwError = ERROR_PPP_NO_PROTOCOLS_CONFIGURED;
}
prp1->ProjResult.ip.dwError = ERROR_PPP_NO_PROTOCOLS_CONFIGURED;
prp1->ProjResult.ipx.dwError = ERROR_PPP_NO_PROTOCOLS_CONFIGURED;
prp1->ProjResult.at.dwError = ERROR_PPP_NO_PROTOCOLS_CONFIGURED;
}
else
{
GETULONG(&prp1->ProjResult.nbf.dwError, pprp1->ProjResult.nbf.dwError);
GETULONG(&prp1->ProjResult.nbf.dwNetBiosError,
pprp1->ProjResult.nbf.dwNetBiosError);
memcpy(prp1->ProjResult.nbf.szName, pprp1->ProjResult.nbf.szName,
NETBIOS_NAME_LEN+1);
for (i=0; i<NETBIOS_NAME_LEN+1; i++)
{
GETUSHORT(&prp1->ProjResult.nbf.wszWksta[i],
&pprp1->ProjResult.nbf.wszWksta[i*2]);
}
GETULONG(&prp1->ProjResult.ip.dwError, pprp1->ProjResult.ip.dwError);
for (i=0; i<RAS_IPADDRESSLEN+1; i++)
{
GETUSHORT(&prp1->ProjResult.ip.wszAddress[i],
&pprp1->ProjResult.ip.wszAddress[i*2]);
}
/* The server's IP address is not part of the RASADMIN protocol,
** though the PPP engine now reports this for servers that provide it.
** Avoid reporting garbage, just in case.
*/
/* Since we are exposing RAS server side APIs to 3rd parties, let us
** not expose this field that is not set for the server side. We did
** this because we don't want to break compatibility with older version
** of rasadmin
**
** prp1->ProjResult.ip.wszServerAddress[ 0 ] = L'\0';
*/
GETULONG(&prp1->ProjResult.ipx.dwError, pprp1->ProjResult.ipx.dwError);
for (i=0; i<RAS_IPXADDRESSLEN+1; i++)
{
GETUSHORT(&prp1->ProjResult.ipx.wszAddress[i],
&pprp1->ProjResult.ipx.wszAddress[i*2]);
}
GETULONG(&prp1->ProjResult.at.dwError, pprp1->ProjResult.at.dwError);
for (i=0; i<RAS_ATADDRESSLEN+1; i++)
{
GETUSHORT(&prp1->ProjResult.at.wszAddress[i],
&pprp1->ProjResult.at.wszAddress[i*2]);
}
}
return;
}
VOID UnpackRasServer0(
IN PP_RAS_SERVER_0 pprs0,
OUT PRAS_SERVER_0 prs0
)
{
GETUSHORT(&prs0->TotalPorts, pprs0->TotalPorts);
GETUSHORT(&prs0->PortsInUse, pprs0->PortsInUse);
GETULONG(&prs0->RasVersion, pprs0->RasVersion);
}
DWORD UnpackPortEnumReceive(
IN PP_PORT_ENUM_RECEIVE ppper,
OUT PPORT_ENUM_RECEIVE pper
)
{
GETULONG(&pper->RetCode, ppper->RetCode);
GETUSHORT(&pper->TotalAvail, ppper->TotalAvail);
if (!pper->RetCode || pper->RetCode == ERROR_MORE_DATA)
{
WORD i;
//
// Get some memory for the port structures
//
hmem = GlobalAlloc(GMEM_MOVEABLE,
sizeof(RAS_PORT_0) * pper->TotalAvail);
if (!hmem)
{
return (GetLastError());
}
pper->Data = (RAS_PORT_0 *)GlobalLock(hmem);
if (!pper->Data)
{
return (GetLastError());
}
for (i=0; i<pper->TotalAvail; i++)
{
UnpackRasPort0(&ppper->Data[i], &pper->Data[i]);
}
GlobalUnlock(hmem);
}
return (0L);
}
DWORD UnpackResumeEnumReceive(
IN PP_PORT_ENUM_RECEIVE ppper,
OUT PPORT_ENUM_RECEIVE pper,
IN USHORT ResumePort
)
{
GETULONG(&pper->RetCode, ppper->RetCode);
GETUSHORT(&pper->TotalAvail, ppper->TotalAvail);
if (!pper->RetCode || pper->RetCode == ERROR_MORE_DATA)
{
WORD i;
//
// Reallocate memory for the port structures
//
hnewmem = GlobalReAlloc(hmem,
sizeof(RAS_PORT_0) *
(pper->TotalAvail + ResumePort),
GMEM_MOVEABLE);
if (!hnewmem)
{
return (GetLastError());
}
hmem = hnewmem;
pper->Data = (RAS_PORT_0 *)GlobalLock(hmem);
if (!pper->Data)
{
return (GetLastError());
}
pper->Data += ResumePort;
for (i=0; i<pper->TotalAvail; i++)
{
UnpackRasPort0(&ppper->Data[i], &pper->Data[i]);
}
GlobalUnlock(hmem);
}
return (0L);
}
VOID UnpackServerInfoReceive(
IN PP_SERVER_INFO_RECEIVE ppsir,
OUT PSERVER_INFO_RECEIVE psir
)
{
GETUSHORT(&psir->RetCode, ppsir->RetCode);
UnpackRasServer0(&ppsir->Data, &psir->Data);
}
VOID UnpackPortClearReceive(
IN PP_PORT_CLEAR_RECEIVE pppcr,
OUT PPORT_CLEAR_RECEIVE ppcr
)
{
GETULONG(&ppcr->RetCode, pppcr->RetCode);
}
VOID UnpackDisconnectUserReceive(
IN PP_DISCONNECT_USER_RECEIVE ppdur,
OUT PDISCONNECT_USER_RECEIVE pdur
)
{
GETULONG(&pdur->RetCode, ppdur->RetCode);
}
VOID UnpackPortInfoReceive(
IN PP_PORT_INFO_RECEIVE pppir,
OUT PPORT_INFO_RECEIVE ppir,
DWORD dwServerVersion
)
{
GETULONG(&ppir->RetCode, pppir->RetCode);
GETULONG(&ppir->ReqBufSize, pppir->ReqBufSize);
if (!ppir->RetCode)
{
UnpackRasPort1(&pppir->Data, &ppir->Data, dwServerVersion);
}
}
VOID UnpackStats(
IN DWORD dwVersion,
IN WORD NumStats,
IN PP_RAS_STATISTIC PStats,
OUT PRAS_PORT_STATISTICS Stats
)
{
WORD i;
PDWORD pdw = (PDWORD) Stats;
PDWORD pdwIn = (PDWORD) PStats;
for (i=0; i<NumStats; i++, PStats++)
{
GETULONG(&pdw[i], PStats->Stat);
}
// NT 3.5x version didn't report both bundle and link stats, so
// we just copy the bundle stats as link stats.
PStats = (PP_RAS_STATISTIC) pdwIn;
if (dwVersion <= RASADMIN_35) {
for (i=NumStats; i<(NumStats*2); i++, PStats++)
{
GETULONG(&pdw[i], PStats->Stat);
}
}
return;
}
DWORD UnpackParams(
IN WORD NumOfParams,
IN PP_RAS_PARAMS PParams,
OUT RAS_PARAMETERS *Params
)
{
WORD i;
RAS_PARAMETERS *TempParams = Params;
PBYTE PParamData = (PBYTE) (PParams + NumOfParams);
for (i=0; i<NumOfParams; i++, Params++, PParams++)
{
//
// P_Key field
//
memcpy(Params->P_Key, PParams->P_Key, RASSAPI_MAX_PARAM_KEY_SIZE);
//
// P_Type field
//
GETULONG(&Params->P_Type, PParams->P_Type.Format);
//
// P_Attribute field
//
Params->P_Attributes = PParams->P_Attributes;
//
// P_Value field
//
if (Params->P_Type == ParamNumber)
{
//
// Union member Number
//
GETULONG(&Params->P_Value.Number, PParams->P_Value.Number);
}
else
{
//
// Union member String
//
GETULONG(&Params->P_Value.String.Length,
PParams->P_Value.String.Length);
Params->P_Value.String.Data = GlobalAlloc(GMEM_FIXED,
Params->P_Value.String.Length);
if (!Params->P_Value.String.Data)
{
WORD k;
DWORD dwErr = GetLastError();
//
// Start deallocating mem for any previously allocated param
//
for (k=i, Params--; k>0; k--, Params--)
{
if (Params->P_Type == ParamString)
{
GlobalFree(Params->P_Value.String.Data);
}
}
return (dwErr);
}
memcpy(Params->P_Value.String.Data, PParamData,
Params->P_Value.String.Length);
PParamData += Params->P_Value.String.Length;
}
}
return(0L);
}
VOID UnpackWpdStatistics(
IN PP_WPD_STATISTICS_INFO PWpdStats,
OUT WpdStatisticsInfo *WpdStats
)
{
GETULONG(&WpdStats->stat_bytesreceived, PWpdStats->stat_bytesreceived);
GETULONG(&WpdStats->stat_bytesxmitted, PWpdStats->stat_bytesxmitted);
GETUSHORT(&WpdStats->stat_overrunerr, PWpdStats->stat_overrunerr);
GETUSHORT(&WpdStats->stat_timeouterr, PWpdStats->stat_timeouterr);
GETUSHORT(&WpdStats->stat_framingerr, PWpdStats->stat_framingerr);
GETUSHORT(&WpdStats->stat_crcerr, PWpdStats->stat_crcerr);
return;
}
VOID UnpackDialinPortInfo0(
IN PP_DIALIN_PORT_INFO_0 PPortInfo0,
struct dialin_port_info_0 *PortInfo0
)
{
memcpy(PortInfo0->dporti0_username, PPortInfo0->dporti0_username,
LM20_UNLEN+1);
memcpy(PortInfo0->dporti0_computer, PPortInfo0->dporti0_computer,
NETBIOS_NAME_LEN);
GETUSHORT(&PortInfo0->dporti0_comid, PPortInfo0->dporti0_comid);
GETULONG(&PortInfo0->dporti0_time, PPortInfo0->dporti0_time);
GETUSHORT(&PortInfo0->dporti0_line_condition,
PPortInfo0->dporti0_line_condition);
GETUSHORT(&PortInfo0->dporti0_modem_condition,
PPortInfo0->dporti0_modem_condition);
return;
}
VOID UnpackDialinPortInfo1(
IN PP_DIALIN_PORT_INFO_1 PPortInfo1,
struct dialin_port_info_1 *PortInfo1
)
{
UnpackDialinPortInfo0(&PPortInfo1->dporti0, &PortInfo1->dporti0);
GETULONG(&PortInfo1->dporti1_baud, PPortInfo1->dporti1_baud);
UnpackWpdStatistics(&PPortInfo1->dporti1_stats, &PortInfo1->dporti1_stats);
return;
}
VOID UnpackDialinServerInfo0(
IN PP_DIALIN_SERVER_INFO_0 PServerInfo0,
OUT struct dialin_server_info_0 *ServerInfo0
)
{
GETUSHORT(&ServerInfo0->dserveri0_total_ports,
PServerInfo0->dserveri0_total_ports);
GETUSHORT(&ServerInfo0->dserveri0_ports_in_use,
PServerInfo0->dserveri0_ports_in_use);
return;
}
VOID UnpackPortEnumReceivePkt(
IN PP_PORT_ENUM_RECEIVE_PKT PEnumRecv,
OUT struct PortEnumReceivePkt *EnumRecv
)
{
WORD i;
GETUSHORT(&EnumRecv->RetCode, PEnumRecv->RetCode);
GETUSHORT(&EnumRecv->TotalAvail, PEnumRecv->TotalAvail);
for (i=0; i<EnumRecv->TotalAvail; i++)
{
UnpackDialinPortInfo0(&PEnumRecv->Data[i], &EnumRecv->Data[i]);
}
return;
}
VOID UnpackDisconnectUserReceivePkt(
IN PP_DISCONNECT_USER_RECEIVE_PKT PDisconnectUser,
OUT struct DisconnectUserReceivePkt *DisconnectUser
)
{
GETUSHORT(&DisconnectUser->RetCode, PDisconnectUser->RetCode);
return;
}
VOID UnpackPortClearReceivePkt(
IN PP_PORT_CLEAR_RECEIVE_PKT PClearRecv,
OUT struct PortClearReceivePkt *ClearRecv
)
{
GETUSHORT(&ClearRecv->RetCode, PClearRecv->RetCode);
return;
}
VOID UnpackServerInfoReceivePkt(
IN PP_SERVER_INFO_RECEIVE_PKT PInfoRecv,
OUT struct ServerInfoReceivePkt *InfoRecv
)
{
GETUSHORT(&InfoRecv->RetCode, PInfoRecv->RetCode);
UnpackDialinServerInfo0(&PInfoRecv->Data, &InfoRecv->Data);
return;
}
VOID UnpackPortInfoReceivePkt(
IN PP_PORT_INFO_RECEIVE_PKT PInfoRecv,
struct PortInfoReceivePkt *InfoRecv
)
{
GETUSHORT(&InfoRecv->RetCode, PInfoRecv->RetCode);
UnpackDialinPortInfo1(&PInfoRecv->Data, &InfoRecv->Data);
return;
}
VOID PackPortEnumRequestPkt(
IN struct PortEnumRequestPkt *EnumReq,
OUT PP_PORT_ENUM_REQUEST_PKT PEnumReq
)
{
PUTUSHORT(PEnumReq->Request, EnumReq->Request);
return;
}
VOID PackDisconnectUserRequestPkt(
IN struct DisconnectUserRequestPkt *DisconnectReq,
OUT PP_DISCONNECT_USER_REQUEST_PKT PDisconnectReq
)
{
PUTUSHORT(PDisconnectReq->Request, DisconnectReq->Request);
PUTUSHORT(PDisconnectReq->ComId, DisconnectReq->ComId);
return;
}
VOID PackPortClearRequestPkt(
IN struct PortClearRequestPkt *ClearReq,
OUT PP_PORT_CLEAR_REQUEST_PKT PClearReq
)
{
PUTUSHORT(PClearReq->Request, ClearReq->Request);
PUTUSHORT(PClearReq->ComId, ClearReq->ComId);
return;
}
VOID PackServerInfoRequestPkt(
IN struct ServerInfoRequestPkt *InfoReq,
OUT PP_SERVER_INFO_REQUEST_PKT PInfoReq
)
{
PUTUSHORT(PInfoReq->Request, InfoReq->Request);
return;
}
VOID PackPortInfoRequestPkt(
IN struct PortInfoRequestPkt *InfoReq,
OUT PP_PORT_INFO_REQUEST_PKT PInfoReq
)
{
PUTUSHORT(PInfoReq->Request, InfoReq->Request);
PUTUSHORT(PInfoReq->ComId, InfoReq->ComId);
return;
}