Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

969 lines
34 KiB

//depot/Lab03_N/Net/rras/ndis/raspptp/nt/thread.c#6 - edit change 19457 (text)
/*******************************************************************
*
* Copyright (c) 1998-1999 Microsoft Corporation
*
* DESCRIPTION: THREAD.C - Thread handling routines, for NT
* Also implements work items.
*
* AUTHOR: Stan Adermann (StanA)
*
* DATE:10/20/1998
*
*******************************************************************/
#include "raspptp.h"
#include <stdarg.h>
#include <stdio.h>
extern struct PPTP_ADAPTER * pgAdapter;
//ULONG ProcCountTxQ[2] = {0, 0};
//ULONG ProcCountRxQ[2] = {0, 0};
HANDLE hPassiveThread = NULL;
KEVENT EventPassiveThread;
KEVENT EventKillThread;
LIST_ENTRY WorkItemList;
NDIS_SPIN_LOCK GlobalThreadLock;
BOOLEAN ThreadingInitialized = FALSE;
NDIS_STATUS
ScheduleWorkItem(
WORK_PROC Callback,
PVOID Context,
PVOID InfoBuf,
ULONG InfoBufLen)
{
PPPTP_WORK_ITEM pWorkItem;
NDIS_STATUS Status = NDIS_STATUS_FAILURE;
DEBUGMSG(DBG_FUNC, (DTEXT("+ScheduleWorkItem\n")));
ASSERT(ThreadingInitialized);
pWorkItem = MyMemAlloc(sizeof(PPTP_WORK_ITEM), TAG_WORK_ITEM);
if (pWorkItem != NULL)
{
pWorkItem->Context = Context;
pWorkItem->pBuffer = InfoBuf;
pWorkItem->Length = InfoBufLen;
/*
** This interface was designed to use NdisScheduleWorkItem(), which
** would be good except that we're really only supposed to use that
** interface during startup and shutdown, due to the limited pool of
** threads available to service NdisScheduleWorkItem(). Therefore,
** instead of scheduling real work items, we simulate them, and use
** our own thread to process the calls. This also makes it easy to
** expand the size of our own thread pool, if we wish.
**
** Our version is slightly different from actual NDIS_WORK_ITEMs,
** because that is an NDIS 5.0 structure, and we want people to
** (at least temporarily) build this with NDIS 4.0 headers.
*/
pWorkItem->Callback = Callback;
/*
** Our worker thread checks this list for new jobs, whenever its event
** is signalled.
*/
MyInterlockedInsertTailList(&WorkItemList,
&pWorkItem->ListEntry,
&GlobalThreadLock);
// Wake up our thread.
KeSetEvent(&EventPassiveThread, 0, FALSE);
Status = NDIS_STATUS_SUCCESS;
}
else
{
gCounters.ulWorkItemFail++;
}
return Status;
}
STATIC VOID
MainPassiveLevelThread(
IN OUT PVOID Context
)
{
NDIS_STATUS Status;
NTSTATUS NtStatus;
PLIST_ENTRY pListEntry;
PKEVENT EventList[2];
DEBUGMSG(DBG_FUNC, (DTEXT("+MainPassiveLevelThread\n")));
//KeSetPriorityThread(KeGetCurrentThread(), LOW_REALTIME_PRIORITY);
EventList[0] = &EventPassiveThread;
EventList[1] = &EventKillThread;
for (;;)
{
//
// The EventPassiveThread is an auto-clearing event, so
// we don't need to reset the event.
//
NtStatus = KeWaitForMultipleObjects(2,
EventList,
WaitAny,
Executive,
KernelMode,
FALSE,
NULL,
NULL);
if (NtStatus==0) // The first event, for a work item, was signalled
{
while (pListEntry = MyInterlockedRemoveHeadList(&WorkItemList,
&GlobalThreadLock))
{
PPPTP_WORK_ITEM pWorkItem = CONTAINING_RECORD(pListEntry,
PPTP_WORK_ITEM,
ListEntry);
ASSERT(KeGetCurrentIrql()<DISPATCH_LEVEL);
pWorkItem->Callback(pWorkItem);
ASSERT(KeGetCurrentIrql()<DISPATCH_LEVEL);
FreeWorkItem(pWorkItem);
}
}
else
{
// A kill event was received.
DEBUGMSG(DBG_THREAD, (DTEXT("Thread: HALT %08x\n"), NtStatus));
// Free any pending requests
while (pListEntry = MyInterlockedRemoveHeadList(&WorkItemList,
&GlobalThreadLock))
{
PPPTP_WORK_ITEM pWorkItem = CONTAINING_RECORD(pListEntry,
PPTP_WORK_ITEM,
ListEntry);
DEBUGMSG(DBG_WARN, (DTEXT("Releasing work item %08x\n"), pWorkItem));
FreeWorkItem(pWorkItem);
}
hPassiveThread = NULL;
DEBUGMSG(DBG_FUNC, (DTEXT("PsTerminateSystemThread MainPassiveLevelThread\n")));
PsTerminateSystemThread(STATUS_SUCCESS);
break;
}
}
DEBUGMSG(DBG_FUNC, (DTEXT("-MainPassiveLevelThread\n")));
}
NDIS_STATUS
CallQueueTransmitPacket(
PCALL_SESSION pCall,
PNDIS_WAN_PACKET pWanPacket
)
{
NDIS_STATUS Status = NDIS_STATUS_PENDING;
DEBUGMSG(DBG_FUNC, (DTEXT("+CallQueueTransmitPacket\n")));
//++ProcCountTxQ[KeGetCurrentProcessorNumber()];
if (!IS_CALL(pCall) || pCall->State!=STATE_CALL_ESTABLISHED)
{
// Drop the packet.
Status = NDIS_STATUS_SUCCESS;
goto cqtpDone;
}
NdisAcquireSpinLock(&pCall->Lock);
InsertTailList(&pCall->TxPacketList, &pWanPacket->WanPacketQueue);
if (!pCall->Transferring)
{
pCall->Transferring = TRUE;
REFERENCE_OBJECT(pCall);
NdisScheduleWorkItem(&pCall->SendWorkItem);
}
NdisReleaseSpinLock(&pCall->Lock);
cqtpDone:
DEBUGMSG(DBG_FUNC, (DTEXT("-CallQueueTransmitPacket\n")));
return Status;
}
NDIS_STATUS
CallQueueReceivePacket(
PCALL_SESSION pCall,
PDGRAM_CONTEXT pDgContext
)
{
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
PGRE_HEADER pGre = pDgContext->pGreHeader;
ULONG_PTR ProcNum = 0;
PULONG pSequence;
ULONG Sequence;
DEBUGMSG(DBG_FUNC, (DTEXT("+CallQueueReceivePacket\n")));
//++ProcCountRxQ[KeGetCurrentProcessorNumber()];
if(!pGre->SequenceNumberPresent)
{
return NDIS_STATUS_FAILURE;
}
NdisAcquireSpinLock(&pCall->Lock);
if (pCall->RxPacketsPending > 256 ||
htons(pGre->KeyCallId)!=pCall->Packet.CallId ||
pCall->State!=STATE_CALL_ESTABLISHED ||
!IS_LINE_UP(pCall))
{
NdisReleaseSpinLock(&pCall->Lock);
DEBUGMSG(DBG_PACKET|DBG_RX, (DTEXT("Rx: GRE CallId invalid or call in wrong state\n")));
Status = NDIS_STATUS_FAILURE;
goto cqrpDone;
}
// The packet has passed all of our tests.
if (IsListEmpty(&pCall->RxPacketList))
{
InsertTailList(&pCall->RxPacketList, &pDgContext->ListEntry);
pCall->RxPacketsPending++;
}
else
{
// There are packets already queued. Put this one in order.
pSequence = (PULONG)(pGre + 1);
Sequence = htonl(*pSequence);
// We don't check the sequence # anymore, just put it on the queue in order
{
// There are packets already queued. Put this one in order.
// The sequence # is the one we want soon to be the one we want.
PLIST_ENTRY pListEntry;
BOOLEAN OnList = FALSE;
for (pListEntry = pCall->RxPacketList.Flink;
pListEntry != &pCall->RxPacketList;
pListEntry = pListEntry->Flink)
{
PDGRAM_CONTEXT pListDg = CONTAINING_RECORD(pListEntry,
DGRAM_CONTEXT,
ListEntry);
if ((signed)htonl(GreSequence(pListDg->pGreHeader)) - (signed)Sequence > 0)
{
// The one on the list is newer! Put this one before it.
InsertTailList(&pListDg->ListEntry, &pDgContext->ListEntry);
pCall->RxPacketsPending++;
OnList = TRUE;
break;
}
}
if (!OnList)
{
// There were no packets on this list with a greater sequence.
// Put this at the end.
InsertTailList(&pCall->RxPacketList, &pDgContext->ListEntry);
pCall->RxPacketsPending++;
}
}
}
if (!pCall->Receiving)
{
pCall->Receiving = TRUE;
REFERENCE_OBJECT(pCall);
NdisScheduleWorkItem(&pCall->RecvWorkItem);
// PptpQueueDpc(&pCall->ReceiveDpc);
}
NdisReleaseSpinLock(&pCall->Lock);
cqrpDone:
DEBUGMSG(DBG_FUNC, (DTEXT("-CallQueueReceivePacket\n")));
return Status;
}
NDIS_STATUS
InitThreading(
NDIS_HANDLE hMiniportAdapter
)
{
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
NTSTATUS NtStatus;
UNREFERENCED_PARAMETER(hMiniportAdapter);
DEBUGMSG(DBG_FUNC, (DTEXT("+InitializeThreading\n")));
if (ThreadingInitialized)
{
ASSERT(!"Threading initialized twice");
goto itDone;
}
NdisInitializeListHead(&WorkItemList);
NdisAllocateSpinLock(&GlobalThreadLock);
KeInitializeEvent(
&EventPassiveThread,
SynchronizationEvent, // auto-clearing event
FALSE // event initially non-signalled
);
KeInitializeEvent(
&EventKillThread,
SynchronizationEvent, // auto-clearing event
FALSE // event initially non-signalled
);
NtStatus = PsCreateSystemThread(&hPassiveThread,
(ACCESS_MASK) 0L,
NULL,
NULL,
NULL,
MainPassiveLevelThread,
NULL);
if (NtStatus == STATUS_SUCCESS)
{
ThreadingInitialized = TRUE;
}
else
{
DEBUGMSG(DBG_ERROR, (DTEXT("PsCreateSystemThread failed. %08x\n"), Status));
Status = NDIS_STATUS_FAILURE;
goto itDone;
}
itDone:
DEBUGMSG(DBG_FUNC, (DTEXT("-InitializeThreading %08x\n"), Status));
return Status;
}
VOID STATIC WaitForThreadToDieAndCloseIt(HANDLE hThread, PRKEVENT pKillEvent)
{
PVOID pThread = NULL;
NTSTATUS Status;
DEBUGMSG(DBG_FUNC, (DTEXT("+WaitForThreadToDie\n")));
if ( hThread != NULL && pKillEvent != NULL )
{
Status = ObReferenceObjectByHandle(hThread, 0, NULL, KernelMode, &pThread, NULL);
if (Status==STATUS_SUCCESS)
{
KeSetEvent(pKillEvent, 0, FALSE);
KeWaitForSingleObject(pThread, Executive, KernelMode, FALSE, NULL);
ObDereferenceObject(pThread);
}
ZwClose(hThread);
}
DEBUGMSG(DBG_FUNC, (DTEXT("-WaitForThreadToDie\n")));
}
VOID
DeinitThreading()
{
DEBUGMSG(DBG_FUNC, (DTEXT("+DeinitThreading\n")));
ThreadingInitialized = FALSE;
WaitForThreadToDieAndCloseIt( hPassiveThread,
&EventKillThread );
DEBUGMSG(DBG_FUNC, (DTEXT("-DeinitThreading\n")));
}
UCHAR TapiLineNameBuffer[64] = TAPI_LINE_NAME_STRING;
ANSI_STRING TapiLineName = {
sizeof(TAPI_LINE_NAME_STRING),
sizeof(TapiLineNameBuffer),
TapiLineNameBuffer
};
typedef UCHAR TAPI_CHAR_TYPE;
ANSI_STRING TapiLineAddrList = { 0, 0, NULL };
#define READ_NDIS_REG_ULONG(hConfig, Var, Value) \
{ \
PNDIS_CONFIGURATION_PARAMETER RegValue; \
NDIS_STATUS Status; \
NDIS_STRING String = NDIS_STRING_CONST(Value); \
\
NdisReadConfiguration(&Status, \
&RegValue, \
hConfig, \
&String, \
NdisParameterInteger); \
if (Status==NDIS_STATUS_SUCCESS) \
{ \
(Var) = RegValue->ParameterData.IntegerData; \
DEBUGMSG(DBG_INIT, (DTEXT(#Var"==%d\n"), (Var))); \
} \
else \
{ \
DEBUGMSG(DBG_INIT, (DTEXT(Value", default==%d\n"), (Var)));\
} \
}
#define READ_NDIS_REG_USHORT(hConfig, Var, Value) \
{ \
PNDIS_CONFIGURATION_PARAMETER RegValue; \
NDIS_STATUS Status; \
NDIS_STRING String = NDIS_STRING_CONST(Value); \
\
NdisReadConfiguration(&Status, \
&RegValue, \
hConfig, \
&String, \
NdisParameterInteger); \
if (Status==NDIS_STATUS_SUCCESS) \
{ \
(Var) = (USHORT)(RegValue->ParameterData.IntegerData&0xffff); \
DEBUGMSG(DBG_INIT, (DTEXT(#Var"==%d\n"), (Var))); \
} \
else \
{ \
DEBUGMSG(DBG_INIT, (DTEXT(Value", default==%d\n"), (Var)));\
} \
}
#define READ_NDIS_REG_BOOL(hConfig, Var, Value) \
{ \
PNDIS_CONFIGURATION_PARAMETER RegValue; \
NDIS_STATUS Status; \
NDIS_STRING String = NDIS_STRING_CONST(Value); \
\
NdisReadConfiguration(&Status, \
&RegValue, \
hConfig, \
&String, \
NdisParameterInteger); \
if (Status==NDIS_STATUS_SUCCESS) \
{ \
(Var) = RegValue->ParameterData.IntegerData ? TRUE : FALSE; \
DEBUGMSG(DBG_INIT, (DTEXT(#Var"==%d\n"), (Var))); \
} \
else \
{ \
DEBUGMSG(DBG_INIT, (DTEXT(Value", default==%d\n"), (Var)));\
} \
}
ULONG ReadClientAddressAndMaskList(
IN NDIS_HANDLE hConfig,
IN PNDIS_STRING IpAddressesString,
IN PNDIS_STRING IpMasksString,
IN OUT PCLIENT_ADDRESS *pClientAddressList
)
//
// Read the IP addresses and masks in multi string formats
//
{
NDIS_STATUS Status = NDIS_STATUS_FAILURE;
PNDIS_CONFIGURATION_PARAMETER Value = NULL;
ULONG ulNumIpAddresses = 0;
PCLIENT_ADDRESS ClientList = NULL;
*pClientAddressList = NULL;
NdisReadConfiguration(&Status, // Not required value
&Value,
hConfig,
IpAddressesString,
NdisParameterMultiString);
if (Status==NDIS_STATUS_SUCCESS)
{
ULONG i, ulAddressIndex = 0;
BOOLEAN InEntry, ValidAddress;
PWCHAR AddressList = Value->ParameterData.StringData.Buffer;
TA_IP_ADDRESS Address;
// Loop and count the addresses, so we can allocate proper size to hold them.
for (i=0, InEntry=FALSE; i<(Value->ParameterData.StringData.Length/sizeof(WCHAR))-1; i++)
{
if (!InEntry)
{
if (AddressList[i]!=L'\0')
{
InEntry = TRUE;
StringToIpAddressW(&AddressList[i],
&Address,
&ValidAddress);
if (ValidAddress)
{
ulAddressIndex++;
}
}
}
else
{
if (AddressList[i]==L'\0')
{
InEntry = FALSE;
}
}
}
ulNumIpAddresses = ulAddressIndex;
if (ulNumIpAddresses)
{
ClientList = MyMemAlloc(sizeof(CLIENT_ADDRESS)*ulNumIpAddresses, TAG_PPTP_ADDR_LIST);
if (ClientList)
{
ulAddressIndex = 0;
for (i=0, InEntry=FALSE;
i<(Value->ParameterData.StringData.Length/sizeof(WCHAR))-1 && (ulAddressIndex < ulNumIpAddresses);
i++)
{
if (!InEntry)
{
if (AddressList[i]!=L'\0')
{
InEntry = TRUE;
StringToIpAddressW(&AddressList[i],
&Address,
&ValidAddress);
if (ValidAddress)
{
ClientList[ulAddressIndex].Address = Address.Address[0].Address[0].in_addr;
ClientList[ulAddressIndex].Mask = 0xFFFFFFFF;
ulAddressIndex++;
}
}
}
else
{
if (AddressList[i]==L'\0')
{
InEntry = FALSE;
}
}
}
NdisReadConfiguration(&Status, // Not required value
&Value,
hConfig,
IpMasksString,
NdisParameterMultiString);
if (Status==NDIS_STATUS_SUCCESS)
{
AddressList = Value->ParameterData.StringData.Buffer;
ulAddressIndex = 0;
for (i=0, InEntry=FALSE;
i<(Value->ParameterData.StringData.Length/sizeof(WCHAR))-1 && (ulAddressIndex < ulNumIpAddresses);
i++)
{
if (!InEntry)
{
if (AddressList[i]!=L'\0')
{
InEntry = TRUE;
StringToIpAddressW(&AddressList[i],
&Address,
&ValidAddress);
if (ValidAddress)
{
ClientList[ulAddressIndex].Mask = Address.Address[0].Address[0].in_addr;
ulAddressIndex++;
}
}
}
else
{
if (AddressList[i]==L'\0')
{
InEntry = FALSE;
}
}
}
}
for (i=0; i<ulNumIpAddresses; i++)
{
DEBUGMSG(DBG_INIT, (DTEXT("Client Address:%d.%d.%d.%d Mask:%d.%d.%d.%d\n"),
IPADDR(ClientList[i].Address), IPADDR(ClientList[i].Mask)));
}
}
else
{
ulNumIpAddresses = 0;
}
}
}
if(ulNumIpAddresses)
{
*pClientAddressList = ClientList;
}
else
{
ASSERT(ClientList == NULL);
}
return ulNumIpAddresses;
}
VOID
OsReadConfig(
NDIS_HANDLE hConfig
)
{
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
PNDIS_CONFIGURATION_PARAMETER Value;
NDIS_STRING TapiLineNameString = NDIS_STRING_CONST("TapiLineName");
#if VER_PRODUCTVERSION_W < 0x0500
NDIS_STRING TapiLineAddrString = NDIS_STRING_CONST("AddressList");
#endif
NDIS_STRING PeerClientIpAddressString = NDIS_STRING_CONST("ClientIpAddresses");
NDIS_STRING PeerClientIpMaskString = NDIS_STRING_CONST("ClientIpMasks");
NDIS_STRING TrustedIpAddressString = NDIS_STRING_CONST("TrustedIpAddresses");
NDIS_STRING TrustedIpMaskString = NDIS_STRING_CONST("TrustedIpMasks");
DEBUGMSG(DBG_FUNC, (DTEXT("+OsReadConfig\n")));
READ_NDIS_REG_USHORT(hConfig, PptpControlPort, "TcpPortNumber");
READ_NDIS_REG_ULONG (hConfig, PptpWanEndpoints, "MaxWanEndpoints");
READ_NDIS_REG_ULONG (hConfig, PptpBaseCallId, "BaseCallId");
READ_NDIS_REG_ULONG (hConfig, PptpMaxTransmit, "MaxTransmit");
READ_NDIS_REG_ULONG (hConfig, PptpEchoTimeout, "InactivityIdleSeconds");
READ_NDIS_REG_BOOL (hConfig, PptpEchoAlways, "AlwaysEcho");
READ_NDIS_REG_ULONG (hConfig, CtdiTcpDisconnectTimeout, "TcpDisconnectTimeout");
READ_NDIS_REG_ULONG (hConfig, CtdiTcpConnectTimeout, "TcpConnectTimeout");
READ_NDIS_REG_BOOL (hConfig, PptpAuthenticateIncomingCalls, "AuthenticateIncomingCalls");
READ_NDIS_REG_ULONG (hConfig, PptpTraceMask, "PptpTraceMask");
READ_NDIS_REG_ULONG (hConfig, PptpValidateAddress, "ValidateAddress");
READ_NDIS_REG_ULONG (hConfig, PptpMaxTunnelsPerIpAddress, "MaxTunnelsPerIpAddress");
// Validate some reg values
if(PptpWanEndpoints == 0)
{
PptpWanEndpoints = OS_DEFAULT_WAN_ENDPOINTS;
}
if(PptpMaxTunnelsPerIpAddress > PptpWanEndpoints)
{
PptpMaxTunnelsPerIpAddress = -1;
}
OS_RANGE_CHECK_ENDPOINTS(PptpWanEndpoints, PptpBaseCallId);
OS_RANGE_CHECK_MAX_TRANSMIT(PptpMaxTransmit);
// Read client IP addresses/masks to accept (old behavior)
if(PptpAuthenticateIncomingCalls)
{
DEBUGMSG(DBG_INIT, (DTEXT("Accept IP Addresses/Masks\n")));
g_ulAcceptClientAddresses = ReadClientAddressAndMaskList(
hConfig,
&PeerClientIpAddressString,
&PeerClientIpMaskString,
&g_AcceptClientList);
}
// Read trusted client IP addresses/masks
DEBUGMSG(DBG_INIT, (DTEXT("Trsuted IP Addresses/Masks\n")));
g_ulTrustedClientAddresses = ReadClientAddressAndMaskList(
hConfig,
&TrustedIpAddressString,
&TrustedIpMaskString,
&g_TrustedClientList);
NdisReadConfiguration(&Status, // Not required value
&Value,
hConfig,
&TapiLineNameString,
NdisParameterString);
if (Status==NDIS_STATUS_SUCCESS)
{
RtlUnicodeStringToAnsiString(&TapiLineName, &Value->ParameterData.StringData, FALSE);
*(TAPI_CHAR_TYPE*)(TapiLineName.Buffer+TapiLineName.MaximumLength-sizeof(TAPI_CHAR_TYPE)) = (TAPI_CHAR_TYPE)0;
}
#if VER_PRODUCTVERSION_W < 0x0500
NdisReadConfiguration(&Status, // Not required value
&Value,
hConfig,
&TapiLineAddrString,
NdisParameterMultiString);
if (Status==NDIS_STATUS_SUCCESS)
{
RtlInitAnsiString( &TapiLineAddrList, NULL );
if (RtlUnicodeStringToAnsiString(&TapiLineAddrList, &Value->ParameterData.StringData, TRUE)==NDIS_STATUS_SUCCESS)
{
// NT4 doesn't have the same registry value to tell us how many lines to publish.
// We work around that by counting the number of address strings here
PUCHAR p = TapiLineAddrList.Buffer;
DEBUGMEM(DBG_TAPI, TapiLineAddrList.Buffer, TapiLineAddrList.Length, 1);
PptpWanEndpoints = 0;
if (p)
{
// Count the valid MULTI_SZ entries.
while (*p++)
{
PptpWanEndpoints++;
while (*p++); // This also skips the first NULL
}
}
DBG_D(DBG_INIT, PptpWanEndpoints);
}
}
#endif
DEBUGMSG(DBG_FUNC, (DTEXT("-OsReadConfig\n")));
}
#if 0
VOID OsGetFullHostName(VOID)
{
NTSTATUS status;
OBJECT_ATTRIBUTES objattr;
UNICODE_STRING uni;
HANDLE hParams;
KEY_VALUE_PARTIAL_INFORMATION* pNameValue;
ULONG ulAllocSize, ulSize, ulIndex, ulDomainIndex;
hParams = NULL;
pNameValue = NULL;
NdisZeroMemory(PptpHostName, MAX_HOSTNAME_LENGTH);
do
{
// Get a handle to the TCPIP Parameters registry key.
RtlInitUnicodeString(
&uni,
L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Tcpip\\Parameters" );
InitializeObjectAttributes(
&objattr, &uni, OBJ_CASE_INSENSITIVE, NULL, NULL );
status = ZwOpenKey(&hParams, KEY_QUERY_VALUE, &objattr);
if (status != STATUS_SUCCESS)
{
break;
}
ulAllocSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + MAX_HOSTNAME_LENGTH * 2;
// Query the "Hostname" registry value.
pNameValue = MyMemAlloc(ulAllocSize, TAG_REG);
if (!pNameValue)
{
break;
}
RtlInitUnicodeString( &uni, L"Hostname");
status = ZwQueryValueKey(
hParams, &uni, KeyValuePartialInformation,
pNameValue, ulAllocSize, &ulSize );
if (status != STATUS_SUCCESS || pNameValue->Type != REG_SZ || pNameValue->DataLength < sizeof(WCHAR) * 2)
{
break;
}
// Convert host unicode to ASCII, put it in PptpHostName;
ulSize = min(pNameValue->DataLength/2, MAX_HOSTNAME_LENGTH);
for(ulIndex = 0; ulIndex < ulSize; ulIndex++)
{
PptpHostName[ulIndex] = pNameValue->Data[ulIndex*2];
}
// Query the "Domain" registry value.
RtlInitUnicodeString( &uni, L"Domain");
status = ZwQueryValueKey(
hParams, &uni, KeyValuePartialInformation,
pNameValue, ulAllocSize, &ulSize );
// Convert domain unicode to ASCII, append it in PptpHostName;
if (status == STATUS_SUCCESS
&& pNameValue->Type == REG_SZ
&& pNameValue->DataLength > sizeof(WCHAR)
&& ((WCHAR* )pNameValue->Data)[ 0 ] != L'\0')
{
PptpHostName[--ulIndex] = '.';
++ulIndex;
for(ulDomainIndex = 0;
ulIndex < MAX_HOSTNAME_LENGTH && ulDomainIndex < pNameValue->DataLength/2;
ulIndex++, ulDomainIndex++)
{
PptpHostName[ulIndex] = pNameValue->Data[ulDomainIndex*2];
}
}
PptpHostName[MAX_HOSTNAME_LENGTH -1] = '\0';
}
while (FALSE);
if(hParams)
{
ZwClose(hParams);
}
if(pNameValue)
{
MyMemFree(pNameValue, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + MAX_HOSTNAME_LENGTH * 2);
}
}
#endif
VOID
OsGetTapiLineAddress(ULONG Index, PUCHAR s, ULONG Length)
{
ASSERT(Length);
#if VER_PRODUCTVERSION_W < 0x0500
PUCHAR pAddr = TapiLineAddrList.Buffer;
*s = 0;
if (pAddr)
{
UINT i;
for (i=0; i<Index; i++)
{
if (!*pAddr)
{
// No string at index
return;
}
while (*pAddr) pAddr++;
pAddr++;
}
strncpy(s, pAddr, Length);
s[Length-1] = 0;
}
#else // VER_PRODUCTVERSION_W >= 0x0500
strncpy(s, TAPI_LINE_ADDR_STRING, Length);
s[Length-1] = 0;
#endif
}
NDIS_STATUS
OsSpecificTapiGetDevCaps(
ULONG_PTR ulDeviceId,
IN OUT PNDIS_TAPI_GET_DEV_CAPS pRequest
)
{
PUCHAR pTmp, pTmp2;
ULONG_PTR Index;
DEBUGMSG(DBG_FUNC, (DTEXT("+OsSpecificTapiGetDevCaps\n")));
// Convert to our internal index
ulDeviceId -= pgAdapter->Tapi.DeviceIdBase;
pRequest->LineDevCaps.ulStringFormat = STRINGFORMAT_ASCII;
// The *6 at the end adds enough space for " 9999"
pRequest->LineDevCaps.ulNeededSize = sizeof(pRequest->LineDevCaps) +
sizeof(TAPI_PROVIDER_STRING) +
TapiLineName.Length +
sizeof(TAPI_CHAR_TYPE) * 6;
if (pRequest->LineDevCaps.ulTotalSize<pRequest->LineDevCaps.ulNeededSize)
{
DEBUGMSG(DBG_FUNC|DBG_WARN, (DTEXT("-TapiGetDevCaps NDIS_STATUS_SUCCESS without PROVIDER or LINE_NAME strings\n")));
return NDIS_STATUS_SUCCESS;
}
// Tack the provider string to the end of the LineDevCaps structure.
pRequest->LineDevCaps.ulProviderInfoSize = sizeof(TAPI_PROVIDER_STRING);
pRequest->LineDevCaps.ulProviderInfoOffset = sizeof(pRequest->LineDevCaps);
pTmp = ((PUCHAR)&pRequest->LineDevCaps) + sizeof(pRequest->LineDevCaps);
NdisMoveMemory(pTmp, TAPI_PROVIDER_STRING, sizeof(TAPI_PROVIDER_STRING));
pTmp += sizeof(TAPI_PROVIDER_STRING);
// Tack on the LineName after the provider string.
pRequest->LineDevCaps.ulLineNameSize = TapiLineName.Length + sizeof(TAPI_CHAR_TYPE);
pRequest->LineDevCaps.ulLineNameOffset = pRequest->LineDevCaps.ulProviderInfoOffset +
pRequest->LineDevCaps.ulProviderInfoSize;
NdisMoveMemory(pTmp, TapiLineName.Buffer, TapiLineName.Length+sizeof(TAPI_CHAR_TYPE));
while (*pTmp) pTmp++; // Find the NULL
*pTmp++ = ' ';
pRequest->LineDevCaps.ulLineNameSize++;
// Put a number at the end of the string.
if (ulDeviceId==0)
{
*pTmp++ = '0';
*pTmp++ = '\0';
pRequest->LineDevCaps.ulLineNameSize += 2;
}
else
{
Index = ulDeviceId;
ASSERT(Index<100000);
if(Index >= 100000)
{
// Index value is usually small, but just make sure it's within boundary
Index = 99999;
}
pTmp2 = pTmp;
while (Index)
{
*pTmp2++ = (UCHAR)((Index%10) + '0');
Index /= 10;
pRequest->LineDevCaps.ulLineNameSize++;
}
*pTmp2-- = '\0'; // Null terminate and point to the last digit.
pRequest->LineDevCaps.ulLineNameSize++;
// We put the number in backwards, now reverse it.
while (pTmp<pTmp2)
{
UCHAR t = *pTmp;
*pTmp++ = *pTmp2;
*pTmp2-- = t;
}
}
pRequest->LineDevCaps.ulUsedSize = pRequest->LineDevCaps.ulNeededSize;
DEBUGMSG(DBG_FUNC, (DTEXT("-OsSpecificTapiGetDevCaps\n")));
return NDIS_STATUS_SUCCESS;
}