mirror of https://github.com/tongzx/nt5src
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.
771 lines
24 KiB
771 lines
24 KiB
/*
|
|
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
|
|
|
|
(C) Copyright 1998
|
|
All rights reserved.
|
|
|
|
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
|
|
|
|
Portions of this software are:
|
|
|
|
(C) Copyright 1994 TriplePoint, Inc. -- http://www.TriplePoint.com
|
|
License to use this software is granted under the same terms
|
|
outlined in the Microsoft Windows Device Driver Development Kit.
|
|
|
|
(C) Copyright 1992 Microsoft Corp. -- http://www.Microsoft.com
|
|
License to use this software is granted under the terms outlined in
|
|
the Microsoft Windows Device Driver Development Kit.
|
|
|
|
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
|
|
|
|
@doc INTERNAL TpiParam TpiParam_c
|
|
|
|
@module TpiParam.c |
|
|
|
|
This module, along with <f TpiParam\.h>, implements a table driven parser
|
|
for the NDIS registry parameters.
|
|
|
|
@comm
|
|
|
|
See <f Keywords\.h> for details of how to add new parameters.<nl>
|
|
|
|
This is a driver independent module which can be re-used, without
|
|
change, by any NDIS3 driver.
|
|
|
|
@head3 Contents |
|
|
@index class,mfunc,func,msg,mdata,struct,enum | TpiParam_c
|
|
|
|
@end
|
|
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
|
|
*/
|
|
|
|
#define __FILEID__ TPI_MODULE_PARAMS // Unique file ID for error logging
|
|
|
|
#include <ndis.h>
|
|
#include "TpiDebug.h"
|
|
#include "TpiParam.h"
|
|
|
|
#if defined(_VXD_) && !defined(NDIS_LCODE)
|
|
# define NDIS_LCODE code_seg("_LTEXT", "LCODE")
|
|
# define NDIS_LDATA data_seg("_LDATA", "LCODE")
|
|
#endif
|
|
|
|
#if defined(NDIS_LCODE)
|
|
# pragma NDIS_LCODE // Windows 95 wants this code locked down!
|
|
# pragma NDIS_LDATA
|
|
#endif
|
|
|
|
static NDIS_PHYSICAL_ADDRESS g_HighestAcceptableAddress =
|
|
NDIS_PHYSICAL_ADDRESS_CONST(-1,-1);
|
|
|
|
static NDIS_STRING g_NullString =
|
|
NDIS_STRING_CONST("\0");
|
|
|
|
|
|
/* @doc INTERNAL TpiParam TpiParam_c ustrlen
|
|
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
|
|
|
|
@func
|
|
|
|
<f ustrlen> counts the number of characters in
|
|
a UNICODE (wide) string.
|
|
|
|
@comm
|
|
|
|
@rdesc
|
|
|
|
<f ustrlen> returns the length of the UNICODE string
|
|
pointed to by <p string>. The terminating NULL character is not
|
|
counted.
|
|
|
|
*/
|
|
USHORT ustrlen(
|
|
IN PUSHORT string // @parm
|
|
// Pointer to the beginning of a UNICODE string ending
|
|
// with a 0x0000 value.
|
|
)
|
|
{
|
|
USHORT ct;
|
|
|
|
for (ct = 0; *string != 0x0000; string++, ct++)
|
|
;
|
|
|
|
return(ct);
|
|
}
|
|
|
|
|
|
/* @doc INTERNAL TpiParam TpiParam_c ParamUnicodeStringToAnsiString
|
|
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
|
|
|
|
@func
|
|
|
|
<f ParamUnicodeStringToAnsiString> converts a double byte string to a
|
|
single byte string.
|
|
|
|
@comm
|
|
|
|
The original release of the NDIS Wrapper for Windows 95 and 3.1 does not
|
|
return UNICODE strings from the NdisReadConfiguration routine. So this
|
|
routine attempts to auto detect this situation by examining the first
|
|
character of the string. If the second byte of the first character is
|
|
a zero, the string is assumed to be UNICODE, and it is converted to an
|
|
ANSI string; otherwise the ANSI string is just copied.
|
|
<nl>
|
|
<f Note>: This also assumes that the first character of any UNICODE
|
|
string will not use the second byte (i.e. not an extended character).
|
|
This routine will only successfully convert non-extended character
|
|
strings anyway.
|
|
|
|
@xref
|
|
<f ParamParseRegistry>
|
|
*/
|
|
|
|
VOID ParamUnicodeStringToAnsiString(
|
|
OUT PANSI_STRING out, // @parm
|
|
// A pointer to where the converted ANSI string is to be stored.
|
|
|
|
IN PUNICODE_STRING in // @parm
|
|
// A pointer to the UNICODE string to be converted.
|
|
)
|
|
{
|
|
DBG_FUNC("ParamUnicodeStringToAnsiString")
|
|
|
|
UINT Index;
|
|
|
|
/* CAVEAT - NDIS_BUG
|
|
// NDIS driver for Windows 95 does not return UNICODE from
|
|
// registry parser, so we need to kludge it up here.
|
|
*/
|
|
if (in->Length > 1)
|
|
{
|
|
if (((PUCHAR)(in->Buffer))[1] == 0)
|
|
{
|
|
/*
|
|
// Probably a UNICODE string since all our parameters are ASCII
|
|
// strings.
|
|
*/
|
|
DBG_FILTER(DbgInfo, DBG_TRACE_ON,
|
|
("UNICODE STRING IN @%x#%d='%ls'\n",
|
|
in->Buffer, in->Length, in->Buffer));
|
|
for (Index = 0; Index < (in->Length / sizeof(WCHAR)) &&
|
|
Index < out->MaximumLength; Index++)
|
|
{
|
|
out->Buffer[Index] = (UCHAR) in->Buffer[Index];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
// Probably an ANSI string since all our parameters are more
|
|
// than 1 byte long and should not be zero in the second byte.
|
|
*/
|
|
PANSI_STRING in2 = (PANSI_STRING) in;
|
|
|
|
DBG_FILTER(DbgInfo, DBG_TRACE_ON,
|
|
("ANSI STRING IN @%x#%d='%s'\n",
|
|
in2->Buffer, in2->Length, in2->Buffer));
|
|
|
|
for (Index = 0; Index < in2->Length &&
|
|
Index < out->MaximumLength; Index++)
|
|
{
|
|
out->Buffer[Index] = in2->Buffer[Index];
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DBG_WARNING(DbgInfo,("1 BYTE STRING IN @%x=%04x\n",
|
|
in->Buffer, in->Buffer[0]));
|
|
out->Buffer[0] = (UCHAR) in->Buffer[0];
|
|
Index = 1;
|
|
}
|
|
out->Length = (USHORT) Index; // * sizeof(UCHAR);
|
|
|
|
// NULL terminate the string if there's room.
|
|
if (out->Length <= (out->MaximumLength - sizeof(UCHAR)))
|
|
{
|
|
out->Buffer[Index] = 0;
|
|
}
|
|
ASSERT(out->Length <= out->MaximumLength);
|
|
}
|
|
|
|
|
|
/* @doc INTERNAL TpiParam TpiParam_c ParamUnicodeCopyString
|
|
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
|
|
|
|
@func
|
|
|
|
<f ParamUnicodeCopyString> copies a double byte string to a double byte
|
|
string.
|
|
|
|
@comm
|
|
|
|
The original release of the NDIS Wrapper for Windows 95 and 3.1 does not
|
|
return UNICODE strings from the NdisReadConfiguration routine. So this
|
|
routine attempts to auto detect this situation by examining the first
|
|
character of the string. If the second byte of the first character is
|
|
a zero, the string is assumed to be UNICODE, and it just copied;
|
|
otherwise the ANSI string is converted to UNICODE.
|
|
<nl>
|
|
<f Note>: This also assumes that the first character of any UNICODE
|
|
string will not use the second byte (i.e. not an extended character).
|
|
This routine will only successfully convert non-extended character
|
|
strings anyway.
|
|
|
|
@xref
|
|
<f ParamParseRegistry>
|
|
|
|
*/
|
|
|
|
VOID ParamUnicodeCopyString(
|
|
OUT PUNICODE_STRING out, // @parm
|
|
// A pointer to where the new UNICODE string is to be stored.
|
|
|
|
IN PUNICODE_STRING in // @parm
|
|
// A pointer to the UNICODE string to be copied.
|
|
)
|
|
{
|
|
DBG_FUNC("ParamUnicodeCopyString")
|
|
|
|
UINT Index;
|
|
|
|
/* CAVEAT - NDIS_BUG
|
|
// NDIS driver for Windows 95 does not return UNICODE from
|
|
// registry parser, so we need to kludge it up here.
|
|
*/
|
|
if (in->Length > 1)
|
|
{
|
|
if (((PUCHAR)(in->Buffer))[1] == 0)
|
|
{
|
|
/*
|
|
// Probably a UNICODE string since all our parameters are ASCII
|
|
// strings.
|
|
*/
|
|
DBG_FILTER(DbgInfo, DBG_TRACE_ON,
|
|
("UNICODE STRING IN @%x#%d='%ls'\n",
|
|
in->Buffer, in->Length, in->Buffer));
|
|
for (Index = 0; Index < (in->Length / sizeof(WCHAR)) &&
|
|
Index < (out->MaximumLength / sizeof(WCHAR)); Index++)
|
|
{
|
|
out->Buffer[Index] = in->Buffer[Index];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
// Probably an ANSI string since all our parameters are more
|
|
// than 1 byte long and should not be zero in the second byte.
|
|
*/
|
|
PANSI_STRING in2 = (PANSI_STRING) in;
|
|
|
|
DBG_FILTER(DbgInfo, DBG_TRACE_ON,
|
|
("ANSI STRING IN @%x#%d='%s'\n",
|
|
in2->Buffer, in2->Length, in2->Buffer));
|
|
for (Index = 0; Index < in2->Length &&
|
|
Index < (out->MaximumLength / sizeof(WCHAR)); Index++)
|
|
{
|
|
out->Buffer[Index] = (WCHAR) in2->Buffer[Index];
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DBG_WARNING(DbgInfo,("1 BYTE STRING IN @%x=%04x\n",
|
|
in->Buffer, in->Buffer[0]));
|
|
out->Buffer[0] = (WCHAR) in->Buffer[0];
|
|
Index = 1;
|
|
}
|
|
out->Length = Index * sizeof(WCHAR);
|
|
|
|
// NULL terminate the string if there's room.
|
|
if (out->Length <= (out->MaximumLength - sizeof(WCHAR)))
|
|
{
|
|
out->Buffer[Index] = 0;
|
|
}
|
|
ASSERT(out->Length <= out->MaximumLength);
|
|
}
|
|
|
|
|
|
/* @doc INTERNAL TpiParam TpiParam_c ParamGetNumEntries
|
|
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
|
|
|
|
@func
|
|
|
|
<f ParamGetNumEntries> counts the number of records in the registry
|
|
parameter table.
|
|
|
|
@rdesc
|
|
|
|
<f ParamGetNumEntries> returns the number of entries in the parameter
|
|
table.
|
|
|
|
@xref
|
|
<f ParamParseRegistry>
|
|
|
|
*/
|
|
|
|
DBG_STATIC UINT ParamGetNumEntries(
|
|
IN PPARAM_TABLE Parameters // @parm
|
|
// A pointer to an array of registry parameter records.
|
|
)
|
|
{
|
|
UINT NumRecs = 0;
|
|
|
|
/*
|
|
// Scan the parameter array until we find an entry with zero length name.
|
|
*/
|
|
if (Parameters)
|
|
{
|
|
while (Parameters->RegVarName.Length)
|
|
{
|
|
NumRecs++;
|
|
Parameters++;
|
|
}
|
|
}
|
|
return(NumRecs);
|
|
}
|
|
|
|
|
|
/* @doc INTERNAL TpiParam TpiParam_c ParamParseRegistry
|
|
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
|
|
|
|
@func
|
|
|
|
<f ParamParseRegistry> parses the registry parameter table and attempts
|
|
to read a value from the registry for each parameter record.
|
|
|
|
@rdesc
|
|
|
|
<f ParamParseRegistry> returns one of the following values:
|
|
@flag NDIS_STATUS_SUCCESS |
|
|
If this function is successful.
|
|
|
|
<f Note>: A non-zero return value indicates one of the following error codes:
|
|
|
|
@iex
|
|
NDIS_STATUS_FAILURE
|
|
|
|
@xref
|
|
<f MiniportInitialize>
|
|
<f ParamGetNumEntries>
|
|
<f NdisOpenConfiguration>
|
|
<f NdisWriteErrorLogEntry>
|
|
<f NdisReadConfiguration>
|
|
<f NdisCloseConfiguration>
|
|
<f NdisAllocateMemory>
|
|
<f NdisZeroMemory>
|
|
<f ParamUnicodeStringToAnsiString>
|
|
<f ParamUnicodeCopyString>
|
|
*/
|
|
|
|
NDIS_STATUS ParamParseRegistry(
|
|
IN NDIS_HANDLE AdapterHandle, // @parm
|
|
// Handle to pass to NdisWriteErrorLogEntry if any errors are encountered.
|
|
|
|
IN NDIS_HANDLE WrapperConfigurationContext,// @parm
|
|
// Handle to pass to NdisOpenConfiguration.
|
|
|
|
IN PUCHAR BaseContext, // @parm
|
|
// References the base of the structure where the values read from the
|
|
// registry are written. Typically, this will be a pointer to the first
|
|
// byte of the adapter information structure.
|
|
|
|
IN PPARAM_TABLE Parameters // @parm
|
|
// A pointer to an array of registry parameter records <t PARAM_TABLE>.
|
|
)
|
|
{
|
|
DBG_FUNC("ParamParseRegistry")
|
|
|
|
PNDIS_CONFIGURATION_PARAMETER pReturnedValue;
|
|
NDIS_CONFIGURATION_PARAMETER ReturnedValue;
|
|
NDIS_PARAMETER_TYPE ParamType;
|
|
|
|
/*
|
|
// The handle for reading from the registry.
|
|
*/
|
|
NDIS_HANDLE ConfigHandle;
|
|
|
|
UINT NumRecs = ParamGetNumEntries(Parameters);
|
|
UINT i;
|
|
PPARAM_TABLE pParameter;
|
|
NDIS_STATUS Status;
|
|
UINT Value;
|
|
PANSI_STRING pAnsi;
|
|
UINT Length;
|
|
|
|
/*
|
|
// Open the configuration registry so we can get our config values.
|
|
*/
|
|
NdisOpenConfiguration(
|
|
&Status,
|
|
&ConfigHandle,
|
|
WrapperConfigurationContext
|
|
);
|
|
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
/*
|
|
// Log error message and exit.
|
|
*/
|
|
DBG_ERROR(DbgInfo,("NdisOpenConfiguration failed (Status=%X)\n",Status));
|
|
|
|
NdisWriteErrorLogEntry(
|
|
AdapterHandle,
|
|
NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION,
|
|
3,
|
|
Status,
|
|
__FILEID__,
|
|
__LINE__
|
|
);
|
|
return NDIS_STATUS_FAILURE;
|
|
}
|
|
|
|
/*
|
|
// Walk through all the parameters in the table.
|
|
*/
|
|
for (i = 0, pParameter = Parameters; i < NumRecs; i++, pParameter++)
|
|
{
|
|
#if DBG
|
|
ANSI_STRING ansiRegString;
|
|
char ansiRegName[64];
|
|
|
|
/*
|
|
// Get a printable parameter name.
|
|
*/
|
|
ansiRegString.Length = 0;
|
|
ansiRegString.MaximumLength = sizeof(ansiRegName);
|
|
ansiRegString.Buffer = (PCHAR)ansiRegName;
|
|
NdisZeroMemory(ansiRegName, sizeof(ansiRegName));
|
|
ParamUnicodeStringToAnsiString(
|
|
&ansiRegString,
|
|
(PUNICODE_STRING)&pParameter->RegVarName
|
|
);
|
|
#endif // DBG
|
|
|
|
ASSERT(pParameter->Type <= (UINT) NdisParameterMultiString);
|
|
|
|
/*
|
|
// Attempt to read the parameter value from the registry.
|
|
*/
|
|
ParamType = (NDIS_PARAMETER_TYPE) pParameter->Type;
|
|
NdisReadConfiguration(&Status,
|
|
&pReturnedValue,
|
|
ConfigHandle,
|
|
&pParameter->RegVarName,
|
|
ParamType
|
|
);
|
|
/*
|
|
// If value is not present, and it is mandatory, return failure code.
|
|
*/
|
|
if (Status != NDIS_STATUS_SUCCESS && pParameter->Mandantory)
|
|
{
|
|
/*
|
|
// Log error message and exit.
|
|
*/
|
|
DBG_ERROR(DbgInfo,("%s: NOT IN REGISTRY!\n",
|
|
ansiRegName));
|
|
|
|
NdisWriteErrorLogEntry(
|
|
AdapterHandle,
|
|
NDIS_ERROR_CODE_MISSING_CONFIGURATION_PARAMETER,
|
|
4,
|
|
i,
|
|
Status,
|
|
__FILEID__,
|
|
__LINE__
|
|
);
|
|
|
|
NdisCloseConfiguration(ConfigHandle);
|
|
return NDIS_STATUS_FAILURE;
|
|
}
|
|
|
|
/*
|
|
// Determine how the caller wants to interpret this parameter.
|
|
*/
|
|
if (ParamType == NdisParameterInteger ||
|
|
ParamType == NdisParameterHexInteger)
|
|
{
|
|
ASSERT(pParameter->Size <= sizeof(ULONG));
|
|
|
|
/*
|
|
// If value read, use it, otherwise use default.
|
|
*/
|
|
if (Status == NDIS_STATUS_SUCCESS)
|
|
{
|
|
Value = pReturnedValue->ParameterData.IntegerData;
|
|
}
|
|
else
|
|
{
|
|
Value = (UINT) (LONG_PTR)(pParameter->Default);
|
|
}
|
|
|
|
/*
|
|
// If there are min/max boundaries, verify that value is in range.
|
|
*/
|
|
if (pParameter->Min || pParameter->Max)
|
|
{
|
|
if (Value < pParameter->Min)
|
|
{
|
|
DBG_ERROR(DbgInfo,("%s: Value=%X < Min=%X\n",
|
|
ansiRegName, Value, pParameter->Min));
|
|
Value = pParameter->Min;
|
|
}
|
|
else if (Value > pParameter->Max)
|
|
{
|
|
DBG_ERROR(DbgInfo,("%s: Value=%X > Max=%X\n",
|
|
ansiRegName, Value, pParameter->Max));
|
|
Value = pParameter->Max;
|
|
}
|
|
}
|
|
|
|
/*
|
|
// Size of destination in bytes 1, 2, or 4 (default==INT).
|
|
*/
|
|
switch (pParameter->Size)
|
|
{
|
|
case 0:
|
|
*(PUINT)(BaseContext+pParameter->Offset) = (UINT) Value;
|
|
break;
|
|
|
|
case 1:
|
|
if (Value & 0xFFFFFF00)
|
|
{
|
|
DBG_WARNING(DbgInfo,("%s: OVERFLOWS UCHAR\n",
|
|
ansiRegName));
|
|
}
|
|
*(PUCHAR)(BaseContext+pParameter->Offset) = (UCHAR) Value;
|
|
break;
|
|
|
|
case 2:
|
|
if (Value & 0xFFFF0000)
|
|
{
|
|
DBG_WARNING(DbgInfo,("%s: OVERFLOWS USHORT\n",
|
|
ansiRegName));
|
|
}
|
|
*(PUSHORT)(BaseContext+pParameter->Offset) = (USHORT) Value;
|
|
break;
|
|
|
|
case 4:
|
|
*(PULONG)(BaseContext+pParameter->Offset) = (ULONG) Value;
|
|
break;
|
|
|
|
default:
|
|
DBG_ERROR(DbgInfo,("%s: Invalid ParamSize=%d\n",
|
|
ansiRegName, pParameter->Size));
|
|
NdisCloseConfiguration(ConfigHandle);
|
|
return NDIS_STATUS_FAILURE;
|
|
break;
|
|
}
|
|
|
|
if (ParamType == NdisParameterInteger)
|
|
{
|
|
DBG_PARAMS(DbgInfo,("%s: Value=%d Size=%d (%s)\n",
|
|
ansiRegName, Value, pParameter->Size,
|
|
(Status == NDIS_STATUS_SUCCESS) ?
|
|
"Registry" : "Default"));
|
|
}
|
|
else
|
|
{
|
|
DBG_PARAMS(DbgInfo,("%s: Value=0x%X Size=%d (%s)\n",
|
|
ansiRegName, Value, pParameter->Size,
|
|
(Status == NDIS_STATUS_SUCCESS) ?
|
|
"Registry" : "Default"));
|
|
}
|
|
}
|
|
else if (ParamType == NdisParameterString ||
|
|
ParamType == NdisParameterMultiString)
|
|
{
|
|
ASSERT(pParameter->Size == sizeof(ANSI_STRING));
|
|
|
|
/*
|
|
// If value not read from registry.
|
|
*/
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
/*
|
|
// Use our own temporary ReturnedValue.
|
|
*/
|
|
pReturnedValue = &ReturnedValue;
|
|
pReturnedValue->ParameterType = ParamType;
|
|
|
|
/*
|
|
// If default non-zero, use default value.
|
|
*/
|
|
if (pParameter->Default != 0)
|
|
{
|
|
NdisMoveMemory(&pReturnedValue->ParameterData.StringData,
|
|
(PANSI_STRING) pParameter->Default,
|
|
sizeof(ANSI_STRING));
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
// Otherwise, use null string value.
|
|
*/
|
|
NdisMoveMemory(&pReturnedValue->ParameterData.StringData,
|
|
&g_NullString,
|
|
sizeof(g_NullString));
|
|
}
|
|
}
|
|
|
|
/*
|
|
// Assume the string is ANSI and points to the string data
|
|
// structure. We can get away with this because ANSI and
|
|
// UNICODE strings have a common structure header. An extra
|
|
// character is allocated to make room for a null terminator.
|
|
*/
|
|
pAnsi = (PANSI_STRING) (BaseContext+pParameter->Offset);
|
|
Length = pReturnedValue->ParameterData.StringData.Length+1;
|
|
|
|
/*
|
|
// The caller wants a UNICODE string returned, we have to
|
|
// allocated twice as many bytes to hold the result.
|
|
// NOTE:
|
|
// This wouldn't be necessary if NDIS would always return
|
|
// a UNICODE string, but some Win95 versions of NDIS return
|
|
// an ANSI string, so Length will be too small for UNICODE.
|
|
// The down-side is that we may allocate twice as much as
|
|
// we need to hold the string. (oh well)
|
|
*/
|
|
if (pParameter->Flags == PARAM_FLAGS_UNICODESTRING)
|
|
{
|
|
Length *= sizeof(WCHAR);
|
|
}
|
|
|
|
/*
|
|
// Allocate memory for the string.
|
|
*/
|
|
#if !defined(NDIS50_MINIPORT)
|
|
Status = NdisAllocateMemory(
|
|
(PVOID *) &(pAnsi->Buffer),
|
|
Length,
|
|
0,
|
|
g_HighestAcceptableAddress
|
|
);
|
|
#else // NDIS50_MINIPORT
|
|
Status = NdisAllocateMemoryWithTag(
|
|
(PVOID *) &(pAnsi->Buffer),
|
|
Length,
|
|
__FILEID__
|
|
);
|
|
#endif // NDIS50_MINIPORT
|
|
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
/*
|
|
// Log error message and exit.
|
|
*/
|
|
DBG_ERROR(DbgInfo,("NdisAllocateMemory(Size=%d, File=%s, Line=%d) failed (Status=%X)\n",
|
|
Length, __FILE__, __LINE__, Status));
|
|
|
|
NdisWriteErrorLogEntry(
|
|
AdapterHandle,
|
|
NDIS_ERROR_CODE_OUT_OF_RESOURCES,
|
|
4,
|
|
Status,
|
|
Length,
|
|
__FILEID__,
|
|
__LINE__
|
|
);
|
|
NdisCloseConfiguration(ConfigHandle);
|
|
return NDIS_STATUS_FAILURE;
|
|
}
|
|
else
|
|
{
|
|
DBG_FILTER(DbgInfo, DBG_MEMORY_ON,
|
|
("NdisAllocateMemory(Size=%d, Ptr=0x%x)\n",
|
|
Length, pAnsi->Buffer));
|
|
}
|
|
/*
|
|
// Zero the string buffer to start with.
|
|
*/
|
|
ASSERT(pAnsi->Buffer);
|
|
NdisZeroMemory(pAnsi->Buffer, Length);
|
|
pAnsi->MaximumLength = (USHORT) Length;
|
|
|
|
if (pParameter->Flags == PARAM_FLAGS_ANSISTRING)
|
|
{
|
|
/*
|
|
// The caller wants an ANSI string returned, so we convert
|
|
// it from UNICODE to ANSI.
|
|
*/
|
|
ParamUnicodeStringToAnsiString(
|
|
pAnsi,
|
|
(PUNICODE_STRING) &(pReturnedValue->ParameterData.StringData)
|
|
);
|
|
#if DBG
|
|
if (ParamType == NdisParameterMultiString)
|
|
{
|
|
USHORT ct = 0;
|
|
|
|
while (ct < pAnsi->Length)
|
|
{
|
|
DBG_PARAMS(DbgInfo,("%s: ANSI='%s' Len=%d of %d\n",
|
|
ansiRegName,
|
|
&(pAnsi->Buffer[ct]),
|
|
(strlen(&(pAnsi->Buffer[ct]))),
|
|
pAnsi->Length));
|
|
|
|
ct = ct + (strlen(&(pAnsi->Buffer[ct])) + 1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DBG_PARAMS(DbgInfo,("%s: ANSI='%s' Len=%d\n",
|
|
ansiRegName, pAnsi->Buffer, pAnsi->Length));
|
|
}
|
|
#endif
|
|
}
|
|
else // PARAM_FLAGS_UNICODESTRING
|
|
{
|
|
/*
|
|
// The caller wants a UNICODE string returned, so we can
|
|
// just copy it. The pAnsi buffer was allocated large
|
|
// enough to hold the UNICODE string.
|
|
*/
|
|
ParamUnicodeCopyString(
|
|
(PUNICODE_STRING) pAnsi,
|
|
(PUNICODE_STRING) &(pReturnedValue->ParameterData.StringData)
|
|
);
|
|
#if DBG
|
|
if (ParamType == NdisParameterMultiString)
|
|
{
|
|
USHORT ct = 0;
|
|
|
|
BREAKPOINT;
|
|
|
|
while (ct < (pAnsi->Length / 2))
|
|
{
|
|
DBG_PARAMS(DbgInfo,("%s: UNICODE='%ls' Len=%d of %d\n",
|
|
ansiRegName,
|
|
&((PUSHORT)pAnsi->Buffer)[ct],
|
|
(ustrlen(&((PUSHORT)pAnsi->Buffer)[ct]) * 2),
|
|
pAnsi->Length));
|
|
|
|
ct = ct + (ustrlen(&((PUSHORT)pAnsi->Buffer)[ct]) + 1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DBG_PARAMS(DbgInfo,("%s: UNICODE='%ls' Len=%d\n",
|
|
ansiRegName, pAnsi->Buffer, pAnsi->Length));
|
|
}
|
|
#endif
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
// Report a bogus parameter type in the caller's table.
|
|
*/
|
|
DBG_ERROR(DbgInfo,("Invalid ParamType=%d '%s'\n",
|
|
ParamType, ansiRegName));
|
|
|
|
NdisCloseConfiguration(ConfigHandle);
|
|
return NDIS_STATUS_FAILURE;
|
|
}
|
|
}
|
|
NdisCloseConfiguration(ConfigHandle);
|
|
return(NDIS_STATUS_SUCCESS);
|
|
}
|