mirror of https://github.com/lianthony/NT4.0
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.
1037 lines
29 KiB
1037 lines
29 KiB
/*++
|
|
|
|
Copyright (c) 1991 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
miscnt.cxx
|
|
|
|
Abstract:
|
|
|
|
This file contains NT specific implementations of miscellaneous
|
|
routines.
|
|
|
|
Author:
|
|
|
|
Michael Montague (mikemon) 25-Nov-1991
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include <precomp.hxx>
|
|
#include <rpccfg.h>
|
|
|
|
|
|
static RPC_CHAR *
|
|
AnsiToWideCharString (
|
|
IN STRING * AnsiString
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is used to convert an ansi string into a unicode
|
|
string.
|
|
|
|
Arguments:
|
|
|
|
AnsiString - Supplies the ansi string to be converted into a unicode
|
|
string.
|
|
|
|
Return Value:
|
|
|
|
A newly allocated unicode string will be returned, unless there is
|
|
insufficient memory, in which case zero will be returned.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS NtStatus;
|
|
UNICODE_STRING UnicodeString;
|
|
RPC_CHAR * WideCharString;
|
|
|
|
NtStatus = RtlAnsiStringToUnicodeString(&UnicodeString, AnsiString, TRUE);
|
|
if (!NT_SUCCESS(NtStatus))
|
|
return(0);
|
|
|
|
WideCharString = new RPC_CHAR[(UnicodeString.Length/2) + 1];
|
|
memcpy(WideCharString, UnicodeString.Buffer, UnicodeString.Length);
|
|
WideCharString[(UnicodeString.Length/2)] = 0;
|
|
RtlFreeUnicodeString(&UnicodeString);
|
|
return(WideCharString);
|
|
}
|
|
|
|
static const char *RPC_REGISTRY_CLIENT_PROTOCOLS =
|
|
"Software\\Microsoft\\Rpc\\ClientProtocols";
|
|
|
|
static const char *RPC_REGISTRY_SERVER_PROTOCOLS =
|
|
"Software\\Microsoft\\Rpc\\ServerProtocols";
|
|
|
|
static const char *RPC_REGISTRY_PROTOCOL_IDS =
|
|
"Software\\Microsoft\\Rpc\\AdditionalProtocols";
|
|
|
|
#define MAX_PROTSEQ_LENGTH 32
|
|
#define MAX_ENDPOINT_LENGTH 128
|
|
#define MAX_ID_LENGTH 6
|
|
#define MAX_DLL_NAME 128
|
|
|
|
typedef struct
|
|
{
|
|
RPC_CHAR * RpcProtocolSequence;
|
|
RPC_CHAR * TransportInterfaceDll;
|
|
} RPC_PROTOCOL_SEQUENCE_MAP;
|
|
|
|
static const RPC_PROTOCOL_SEQUENCE_MAP ServerRpcProtocolSequenceMap[] =
|
|
{
|
|
{
|
|
RPC_CONST_STRING("ncacn_np"),
|
|
RPC_CONST_STRING("rpclts1.dll")
|
|
},
|
|
|
|
{
|
|
RPC_CONST_STRING("ncalrpc"),
|
|
0
|
|
},
|
|
};
|
|
|
|
static const RPC_PROTOCOL_SEQUENCE_MAP ClientRpcProtocolSequenceMap[] =
|
|
{
|
|
{
|
|
RPC_CONST_STRING("ncacn_np"),
|
|
RPC_CONST_STRING("rpcltc1.dll")
|
|
},
|
|
|
|
{
|
|
RPC_CONST_STRING("ncalrpc"),
|
|
0
|
|
},
|
|
};
|
|
|
|
|
|
typedef struct
|
|
{
|
|
unsigned char * RpcProtocolSequence;
|
|
unsigned char * RpcSsEndpoint;
|
|
unsigned long TransportId;
|
|
} RPC_PROTOCOL_INFO;
|
|
|
|
|
|
static const RPC_PROTOCOL_INFO StaticProtocolMapping[] =
|
|
{
|
|
{
|
|
(unsigned char *)"ncacn_np",
|
|
(unsigned char *)"\\pipe\\epmapper",
|
|
0x0F
|
|
}
|
|
};
|
|
|
|
RPC_PROTOCOL_INFO * AdditionalProtocols = 0;
|
|
unsigned long TotalAdditionalProtocols = 0;
|
|
|
|
static const char *RPC_REGISTRY_SECURITY_PROVIDERS =
|
|
"Software\\Microsoft\\Rpc\\SecurityService";
|
|
|
|
RPC_STATUS
|
|
RpcGetSecurityProviderInfo(
|
|
unsigned long AuthnId,
|
|
RPC_CHAR PAPI * PAPI * Dll,
|
|
unsigned long PAPI * Count
|
|
)
|
|
{
|
|
|
|
DWORD RegStatus, Ignore, NumberOfValues, MaximumValueLength;
|
|
unsigned long DllNameLength = MAX_DLL_NAME+1;
|
|
DWORD ClassLength = 64, Type;
|
|
RPC_CHAR DllName[MAX_DLL_NAME+1];
|
|
FILETIME LastWriteTime;
|
|
HKEY RegistryKey;
|
|
unsigned char ClassName[64];
|
|
RPC_STATUS Status = RPC_S_OK;
|
|
char AuthnIdZ[8];
|
|
UNICODE_STRING AuthnIdWC;
|
|
|
|
RpcItoa(AuthnId, AuthnIdZ, 10);
|
|
|
|
RegStatus = RegOpenKeyExA(
|
|
HKEY_LOCAL_MACHINE,
|
|
(LPSTR) RPC_REGISTRY_SECURITY_PROVIDERS,
|
|
0L, KEY_READ, //Reserved
|
|
&RegistryKey
|
|
);
|
|
|
|
if ( RegStatus != ERROR_SUCCESS )
|
|
{
|
|
return(RPC_S_UNKNOWN_AUTHN_SERVICE);
|
|
}
|
|
|
|
RegStatus = RegQueryInfoKeyA(
|
|
RegistryKey,
|
|
(LPSTR) ClassName,
|
|
&ClassLength,
|
|
0, //Reserved
|
|
&Ignore,
|
|
&Ignore,
|
|
&Ignore,
|
|
&NumberOfValues,
|
|
&Ignore,
|
|
&MaximumValueLength,
|
|
&Ignore,
|
|
&LastWriteTime
|
|
);
|
|
|
|
if ( (RegStatus != ERROR_SUCCESS) || (NumberOfValues < 2) )
|
|
{
|
|
RegStatus = RegCloseKey(RegistryKey);
|
|
ASSERT( RegStatus == ERROR_SUCCESS );
|
|
return(RPC_S_UNKNOWN_AUTHN_SERVICE);
|
|
}
|
|
|
|
*Count = NumberOfValues - 2; //Gross
|
|
RegStatus = AnsiToUnicodeString((unsigned char *)AuthnIdZ,
|
|
&AuthnIdWC);
|
|
if (RegStatus != RPC_S_OK)
|
|
{
|
|
RegStatus = RegCloseKey(RegistryKey);
|
|
return(RPC_S_UNKNOWN_AUTHN_SERVICE);
|
|
}
|
|
|
|
RegStatus = RegQueryValueExW(
|
|
RegistryKey,
|
|
AuthnIdWC.Buffer,
|
|
0,
|
|
&Type,
|
|
(unsigned char *)DllName,
|
|
&DllNameLength
|
|
);
|
|
|
|
RegCloseKey(RegistryKey);
|
|
|
|
if (RegStatus == ERROR_SUCCESS)
|
|
{
|
|
*Dll = DuplicateString(DllName);
|
|
if (*Dll == 0)
|
|
{
|
|
RegStatus = RPC_S_OUT_OF_MEMORY;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
RegStatus = RPC_S_UNKNOWN_AUTHN_SERVICE;
|
|
}
|
|
|
|
RtlFreeUnicodeString(&AuthnIdWC);
|
|
|
|
return(RegStatus);
|
|
}
|
|
|
|
|
|
RPC_STATUS
|
|
LoadAdditionalTransportInfo(
|
|
)
|
|
{
|
|
|
|
DWORD RegStatus, Index, Ignore, NumberOfValues, MaximumValueLength;
|
|
DWORD ClassLength = 64, ProtseqLength, IgnoreLength;
|
|
BYTE Protseq[MAX_PROTSEQ_LENGTH+1];
|
|
BYTE MaxValueData[MAX_ENDPOINT_LENGTH+MAX_ID_LENGTH+2+8];
|
|
FILETIME LastWriteTime;
|
|
HKEY RegistryKey;
|
|
unsigned char ClassName[64];
|
|
char * Value;
|
|
RPC_PROTOCOL_INFO * AdditionalProtocolsInfo;
|
|
RPC_STATUS Status = RPC_S_OK;
|
|
unsigned long Length, TransportId;
|
|
|
|
RegStatus = RegOpenKeyExA(
|
|
HKEY_LOCAL_MACHINE,
|
|
(LPSTR) RPC_REGISTRY_PROTOCOL_IDS,
|
|
0L, KEY_READ, //Reserved
|
|
&RegistryKey
|
|
);
|
|
|
|
if ( RegStatus != ERROR_SUCCESS )
|
|
{
|
|
return(RPC_S_INVALID_RPC_PROTSEQ);
|
|
}
|
|
|
|
RegStatus = RegQueryInfoKeyA(
|
|
RegistryKey,
|
|
(LPSTR) ClassName,
|
|
&ClassLength,
|
|
0, //Reserved
|
|
&Ignore,
|
|
&Ignore,
|
|
&Ignore,
|
|
&NumberOfValues,
|
|
&Ignore,
|
|
&MaximumValueLength,
|
|
&Ignore,
|
|
&LastWriteTime
|
|
);
|
|
|
|
if ( (RegStatus != ERROR_SUCCESS) || (NumberOfValues == 0) )
|
|
{
|
|
RegStatus = RegCloseKey(RegistryKey);
|
|
ASSERT( RegStatus == ERROR_SUCCESS );
|
|
return(RPC_S_INVALID_RPC_PROTSEQ);
|
|
}
|
|
|
|
//Allocate a table for additional transports mapping
|
|
|
|
AdditionalProtocolsInfo = (RPC_PROTOCOL_INFO *) new unsigned char [
|
|
sizeof(RPC_PROTOCOL_INFO) * NumberOfValues];
|
|
if (AdditionalProtocolsInfo == 0)
|
|
{
|
|
Status = RPC_S_OUT_OF_MEMORY;
|
|
goto Cleanup;
|
|
}
|
|
|
|
AdditionalProtocols = AdditionalProtocolsInfo;
|
|
TotalAdditionalProtocols = NumberOfValues;
|
|
|
|
for (Index = 0; Index < NumberOfValues; Index++)
|
|
{
|
|
|
|
ProtseqLength = MAX_PROTSEQ_LENGTH;
|
|
IgnoreLength = MAX_ENDPOINT_LENGTH + MAX_ID_LENGTH;
|
|
RegStatus = RegEnumValueA(
|
|
RegistryKey,
|
|
Index,
|
|
(LPTSTR) &Protseq,
|
|
&ProtseqLength,
|
|
0,
|
|
&Ignore,
|
|
(LPBYTE) MaxValueData,
|
|
&IgnoreLength
|
|
);
|
|
|
|
if (RegStatus == ERROR_SUCCESS)
|
|
{
|
|
//Add this to our table..
|
|
AdditionalProtocolsInfo->RpcProtocolSequence =
|
|
new unsigned char[ProtseqLength+1];
|
|
if (AdditionalProtocolsInfo->RpcProtocolSequence == 0)
|
|
{
|
|
Status = RPC_S_OUT_OF_MEMORY;
|
|
goto Cleanup;
|
|
}
|
|
RpcpMemoryCopy(
|
|
AdditionalProtocolsInfo->RpcProtocolSequence,
|
|
Protseq,
|
|
ProtseqLength+1
|
|
);
|
|
|
|
Value = (char * )&MaxValueData;
|
|
AdditionalProtocolsInfo->RpcSsEndpoint =
|
|
new unsigned char[Length = (strlen(Value) + 1)];
|
|
if (AdditionalProtocolsInfo->RpcSsEndpoint == 0)
|
|
{
|
|
Status = RPC_S_OUT_OF_MEMORY;
|
|
goto Cleanup;
|
|
}
|
|
RpcpMemoryCopy(
|
|
AdditionalProtocolsInfo->RpcSsEndpoint,
|
|
Value,
|
|
Length
|
|
);
|
|
Value = Value + Length;
|
|
|
|
for (TransportId = 0;
|
|
(*Value > '0') && (*Value <= '9') && (TransportId <= 255);
|
|
Value++)
|
|
{
|
|
TransportId = TransportId * 10 + (*Value - '0');
|
|
}
|
|
AdditionalProtocolsInfo->TransportId = TransportId;
|
|
|
|
AdditionalProtocolsInfo++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Cleanup:
|
|
RegStatus = RegCloseKey(RegistryKey);
|
|
|
|
if (Status != RPC_S_OK)
|
|
{
|
|
if (AdditionalProtocols != 0)
|
|
{
|
|
AdditionalProtocolsInfo = AdditionalProtocols;
|
|
for (Index = 0; Index < NumberOfValues; Index++)
|
|
{
|
|
if (AdditionalProtocolsInfo->RpcProtocolSequence != 0)
|
|
delete AdditionalProtocolsInfo->RpcProtocolSequence;
|
|
if (AdditionalProtocolsInfo->RpcSsEndpoint != 0)
|
|
delete AdditionalProtocolsInfo->RpcSsEndpoint;
|
|
AdditionalProtocolsInfo++;
|
|
}
|
|
|
|
delete AdditionalProtocols;
|
|
AdditionalProtocols = 0;
|
|
TotalAdditionalProtocols = 0;
|
|
}
|
|
}
|
|
|
|
return(Status);
|
|
}
|
|
|
|
|
|
RPC_STATUS
|
|
RpcGetAdditionalTransportInfo(
|
|
IN unsigned long TransportId,
|
|
OUT unsigned char PAPI * PAPI * ProtocolSequence
|
|
)
|
|
{
|
|
unsigned long i;
|
|
RPC_PROTOCOL_INFO * ProtocolInfo;
|
|
|
|
RequestGlobalMutex();
|
|
|
|
if (AdditionalProtocols == 0)
|
|
{
|
|
LoadAdditionalTransportInfo();
|
|
}
|
|
|
|
ClearGlobalMutex();
|
|
|
|
for (i = 0, ProtocolInfo = AdditionalProtocols ;
|
|
i < TotalAdditionalProtocols;
|
|
i++)
|
|
{
|
|
if (ProtocolInfo->TransportId == TransportId)
|
|
{
|
|
*ProtocolSequence = ProtocolInfo->RpcProtocolSequence;
|
|
return (RPC_S_OK);
|
|
}
|
|
ProtocolInfo ++;
|
|
}
|
|
|
|
return(RPC_S_INVALID_RPC_PROTSEQ);
|
|
|
|
}
|
|
|
|
|
|
|
|
RPC_CHAR *
|
|
LocalMapRpcProtocolSequence (
|
|
IN unsigned int ServerSideFlag,
|
|
IN RPC_CHAR PAPI * RpcProtocolSequence
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
We need to check the supplied protocol sequence (and module) to see
|
|
if we can map them into a transport interface dll without having to
|
|
use the registry.
|
|
|
|
Arguments:
|
|
|
|
ServerSideFlag - Supplies a flag indicating whether this protocol
|
|
sequence is to be mapped for a client or a server; a non-zero
|
|
value indicates that it is being mapped for a server.
|
|
|
|
RpcProtocolSequence - Supplies the protocol sequence which we need to
|
|
map into a transport interface dll.
|
|
|
|
Return Value:
|
|
|
|
If we successfully map the protocol sequence, then a pointer to a static
|
|
string containing the transport interface dll (name) will be returned;
|
|
the caller must duplicate the string. Otherwise, zero will be returned.
|
|
|
|
--*/
|
|
{
|
|
const RPC_PROTOCOL_SEQUENCE_MAP * RpcProtocolSequenceMap;
|
|
unsigned int Length, Index;
|
|
|
|
if ( ServerSideFlag != 0 )
|
|
{
|
|
RpcProtocolSequenceMap = ServerRpcProtocolSequenceMap;
|
|
Length = sizeof(ServerRpcProtocolSequenceMap)
|
|
/ sizeof(RPC_PROTOCOL_SEQUENCE_MAP);
|
|
}
|
|
else
|
|
{
|
|
RpcProtocolSequenceMap = ClientRpcProtocolSequenceMap;
|
|
Length = sizeof(ClientRpcProtocolSequenceMap)
|
|
/ sizeof(RPC_PROTOCOL_SEQUENCE_MAP);
|
|
}
|
|
|
|
for (Index = 0; Index < Length; Index++)
|
|
{
|
|
if ( RpcpStringCompare(RpcProtocolSequence,
|
|
RpcProtocolSequenceMap[Index].RpcProtocolSequence) == 0 )
|
|
{
|
|
return(RpcProtocolSequenceMap[Index].TransportInterfaceDll);
|
|
}
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
|
|
|
|
RPC_STATUS
|
|
RpcConfigMapRpcProtocolSequence (
|
|
IN unsigned int ServerSideFlag,
|
|
IN RPC_CHAR PAPI * RpcProtocolSequence,
|
|
OUT RPC_CHAR * PAPI * TransportInterfaceDll
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is used by the rpc protocol modules to map from an
|
|
rpc protocol sequence to the name of a transport interface dll.
|
|
|
|
Arguments:
|
|
|
|
ServerSideFlag - Supplies a flag indicating whether this protocol
|
|
sequence is to be mapped for a client or a server; a non-zero
|
|
value indicates that it is being mapped for a server.
|
|
|
|
RpcProtocolSequence - Supplies the rpc protocol sequence to map.
|
|
|
|
TransportInterfaceDll - Returns the transport support dll which
|
|
supports the requested rpc protocol sequence. This will be a
|
|
newly allocated string which the caller must free.
|
|
|
|
Return Value:
|
|
|
|
RPC_S_OK - Everything worked out fine.
|
|
|
|
RPC_S_PROTSEQ_NOT_SUPPORTED - The requested rpc protocol sequence
|
|
does not have a mapping to a transport interface dll for this
|
|
rpc protocol module.
|
|
|
|
RPC_S_OUT_OF_MEMORY - We ran out of memory trying to map the rpc
|
|
protocol sequence.
|
|
|
|
--*/
|
|
{
|
|
RPC_CHAR * TempString;
|
|
HKEY RegistryKey;
|
|
DWORD Type;
|
|
long RegStatus;
|
|
unsigned char * KeyString;
|
|
unsigned long Length;
|
|
|
|
TempString = LocalMapRpcProtocolSequence(ServerSideFlag,
|
|
RpcProtocolSequence);
|
|
if ( TempString != 0 )
|
|
{
|
|
*TransportInterfaceDll = new RPC_CHAR[RpcpStringLength(TempString) + 1];
|
|
if ( *TransportInterfaceDll == 0 )
|
|
{
|
|
return(RPC_S_OUT_OF_MEMORY);
|
|
}
|
|
memcpy(*TransportInterfaceDll, TempString,
|
|
(RpcpStringLength(TempString) + 1) * sizeof(RPC_CHAR));
|
|
return(RPC_S_OK);
|
|
}
|
|
|
|
if ( ServerSideFlag == 0 )
|
|
{
|
|
KeyString = (unsigned char *) RPC_REGISTRY_CLIENT_PROTOCOLS;
|
|
}
|
|
else
|
|
{
|
|
KeyString = (unsigned char *) RPC_REGISTRY_SERVER_PROTOCOLS;
|
|
}
|
|
|
|
RegStatus = RegOpenKeyExA(HKEY_LOCAL_MACHINE, (LPSTR) KeyString, 0L,
|
|
KEY_READ, &RegistryKey);
|
|
if ( RegStatus != ERROR_SUCCESS )
|
|
{
|
|
return(RPC_S_PROTSEQ_NOT_SUPPORTED);
|
|
}
|
|
|
|
*TransportInterfaceDll = new RPC_CHAR[MAX_DLLNAME_LENGTH + 1];
|
|
if ( *TransportInterfaceDll == 0 )
|
|
{
|
|
return(RPC_S_OUT_OF_MEMORY);
|
|
}
|
|
|
|
Length = (MAX_DLLNAME_LENGTH + 1) * sizeof(RPC_CHAR);
|
|
RegStatus = RegQueryValueExW(RegistryKey, RpcProtocolSequence,
|
|
0, &Type, (LPBYTE) *TransportInterfaceDll, &Length);
|
|
|
|
if ( RegStatus == ERROR_SUCCESS )
|
|
{
|
|
RegStatus = RegCloseKey(RegistryKey);
|
|
ASSERT( RegStatus == ERROR_SUCCESS );
|
|
|
|
return(RPC_S_OK);
|
|
}
|
|
|
|
RegStatus = RegCloseKey(RegistryKey);
|
|
ASSERT( RegStatus == ERROR_SUCCESS );
|
|
|
|
delete *TransportInterfaceDll;
|
|
|
|
return(RPC_S_PROTSEQ_NOT_SUPPORTED);
|
|
}
|
|
|
|
|
|
RPC_STATUS
|
|
RpcConfigInquireProtocolSequences (
|
|
OUT RPC_PROTSEQ_VECTORW PAPI * PAPI * ProtseqVector
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is used to obtain a list of the rpc protocol sequences
|
|
supported by the system for servers.
|
|
|
|
Arguments:
|
|
|
|
ProtseqVector - Returns a vector of supported rpc protocol sequences
|
|
for this rpc protocol module.
|
|
|
|
Return Value:
|
|
|
|
RPC_S_OK - The operation completed successfully.
|
|
|
|
RPC_S_NO_PROTSEQS - The current system configuration does not
|
|
support any rpc protocol sequences.
|
|
|
|
RPC_S_OUT_OF_MEMORY - Insufficient memory is available to inquire
|
|
the rpc protocol sequences supported by the specified rpc
|
|
protocol sequence.
|
|
|
|
--*/
|
|
{
|
|
DWORD RegStatus, Index, Ignore, NumberOfValues, MaximumValueLength;
|
|
DWORD ClassLength = 64, ProtseqLength, IgnoreLength;
|
|
BYTE IgnoreData[MAX_DLLNAME_LENGTH];
|
|
FILETIME LastWriteTime;
|
|
HKEY RegistryKey;
|
|
unsigned char ClassName[64];
|
|
|
|
RegStatus = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
|
|
(LPSTR) RPC_REGISTRY_SERVER_PROTOCOLS, 0L, KEY_READ, &RegistryKey);
|
|
|
|
if ( RegStatus != ERROR_SUCCESS )
|
|
{
|
|
return(RPC_S_NO_PROTSEQS);
|
|
}
|
|
|
|
RegStatus = RegQueryInfoKeyA(RegistryKey, (LPSTR) ClassName, &ClassLength,
|
|
0, &Ignore, &Ignore, &Ignore, &NumberOfValues,
|
|
&Ignore, &MaximumValueLength, &Ignore, &LastWriteTime);
|
|
|
|
ASSERT( RegStatus == ERROR_SUCCESS );
|
|
|
|
if ( RegStatus != ERROR_SUCCESS )
|
|
{
|
|
RegStatus = RegCloseKey(RegistryKey);
|
|
ASSERT( RegStatus == ERROR_SUCCESS );
|
|
return(RPC_S_NO_PROTSEQS);
|
|
}
|
|
|
|
*ProtseqVector = (RPC_PROTSEQ_VECTORW *) new unsigned char[
|
|
sizeof(RPC_PROTSEQ_VECTORW) + (NumberOfValues - 1)
|
|
* sizeof(RPC_CHAR *)];
|
|
|
|
if ( *ProtseqVector == 0 )
|
|
{
|
|
RegStatus = RegCloseKey(RegistryKey);
|
|
ASSERT( RegStatus == ERROR_SUCCESS );
|
|
return(RPC_S_OUT_OF_MEMORY);
|
|
}
|
|
|
|
(*ProtseqVector)->Count = (unsigned int) NumberOfValues;
|
|
|
|
for (Index = 0; Index < NumberOfValues; Index++)
|
|
{
|
|
(*ProtseqVector)->Protseq[Index] = 0;
|
|
}
|
|
|
|
for (Index = 0; Index < NumberOfValues; Index++)
|
|
{
|
|
|
|
(*ProtseqVector)->Protseq[Index] = new RPC_CHAR[MAX_PROTSEQ_LENGTH];
|
|
if ( (*ProtseqVector)->Protseq[Index] == 0 )
|
|
{
|
|
RegStatus = RegCloseKey(RegistryKey);
|
|
ASSERT( RegStatus == ERROR_SUCCESS );
|
|
|
|
RpcProtseqVectorFreeW(ProtseqVector);
|
|
|
|
return(RPC_S_OUT_OF_MEMORY);
|
|
}
|
|
|
|
ProtseqLength = MAX_PROTSEQ_LENGTH;
|
|
IgnoreLength = MAX_DLLNAME_LENGTH;
|
|
RegStatus = RegEnumValueW(RegistryKey, Index,
|
|
(*ProtseqVector)->Protseq[Index], &ProtseqLength,
|
|
0, &Ignore, (LPBYTE) IgnoreData, &IgnoreLength);
|
|
|
|
ASSERT( RegStatus == ERROR_SUCCESS );
|
|
}
|
|
|
|
RegStatus = RegCloseKey(RegistryKey);
|
|
ASSERT( RegStatus == ERROR_SUCCESS );
|
|
|
|
return(RPC_S_OK);
|
|
|
|
/* unsigned int Size;
|
|
unsigned int Index;
|
|
|
|
Size = sizeof(ServerRpcProtocolSequenceMap)
|
|
/ sizeof(RPC_PROTOCOL_SEQUENCE_MAP);
|
|
|
|
*ProtseqVector = (RPC_PROTSEQ_VECTORW *) new unsigned char[
|
|
sizeof(RPC_PROTSEQ_VECTORW) + (Size - 1)
|
|
* sizeof(RPC_CHAR *)];
|
|
if (*ProtseqVector == 0)
|
|
{
|
|
return(RPC_S_OUT_OF_MEMORY);
|
|
}
|
|
|
|
(*ProtseqVector)->Count = Size;
|
|
for (Index = 0; Index < Size; Index++)
|
|
(*ProtseqVector)->Protseq[Index] = 0;
|
|
|
|
for (Index = 0; Index < Size; Index++)
|
|
{
|
|
|
|
(*ProtseqVector)->Protseq[Index] = new RPC_CHAR[RpcpStringLength(
|
|
ServerRpcProtocolSequenceMap[Index].RpcProtocolSequence) + 1];
|
|
if ((*ProtseqVector)->Protseq[Index] == 0)
|
|
{
|
|
RpcProtseqVectorFreeW(ProtseqVector);
|
|
return(RPC_S_OUT_OF_MEMORY);
|
|
}
|
|
|
|
memcpy((*ProtseqVector)->Protseq[Index],
|
|
ServerRpcProtocolSequenceMap[Index].RpcProtocolSequence,
|
|
(RpcpStringLength(
|
|
ServerRpcProtocolSequenceMap[Index].RpcProtocolSequence)
|
|
+ 1) * sizeof(RPC_CHAR));
|
|
}
|
|
return(RPC_S_OK);*/
|
|
}
|
|
|
|
#ifdef WINNT35_UUIDS
|
|
|
|
unsigned long
|
|
SomeLongValue (
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine, SomeShortValue, AnotherShortValue, and SomeCharacterValue
|
|
are used to generate the fields of a GUID if we can not determine
|
|
the network address from the network card (so we can generate a
|
|
UUID). These routines must generate some pseudo random values
|
|
based on the current time and/or the time since boot as well as the
|
|
current process and thread.
|
|
|
|
For the long value, we will use the current thread identifier and
|
|
current process identifier bitwise exclusive ored together.
|
|
|
|
For the two short values, we use the low part of the time field
|
|
(which is long, which we split into two values).
|
|
|
|
Finally, for the character value, we use a constant.
|
|
|
|
Return Value:
|
|
|
|
An unsigned long value will be returned.
|
|
|
|
--*/
|
|
{
|
|
TEB * CurrentTeb;
|
|
|
|
CurrentTeb = NtCurrentTeb();
|
|
return(((unsigned long) CurrentTeb->ClientId.UniqueThread)
|
|
^ ((unsigned long) CurrentTeb->ClientId.UniqueProcess));
|
|
}
|
|
|
|
|
|
unsigned short
|
|
SomeShortValue (
|
|
)
|
|
/*++
|
|
|
|
See SomeLongValue.
|
|
|
|
--*/
|
|
{
|
|
LARGE_INTEGER SystemTime;
|
|
|
|
for (;;)
|
|
{
|
|
NtQuerySystemTime(&SystemTime);
|
|
if (ThreadSelf()->TimeLow != SystemTime.LowPart)
|
|
break;
|
|
PauseExecution(1L);
|
|
}
|
|
ThreadSelf()->TimeLow = SystemTime.LowPart;
|
|
return((unsigned short) SystemTime.LowPart);
|
|
}
|
|
|
|
|
|
unsigned short
|
|
AnotherShortValue (
|
|
)
|
|
/*++
|
|
|
|
See SomeLongValue.
|
|
|
|
--*/
|
|
{
|
|
return((unsigned short) (ThreadSelf()->TimeLow >> 16));
|
|
}
|
|
|
|
|
|
unsigned char
|
|
SomeCharacterValue (
|
|
)
|
|
/*++
|
|
|
|
See SomeLongValue.
|
|
|
|
--*/
|
|
{
|
|
return(0x69);
|
|
}
|
|
|
|
#endif WINNT35_UUIDS
|
|
|
|
unsigned long WaitToGarbageCollectDelay;
|
|
unsigned int GcThreadStarted = 0;
|
|
unsigned int EnableGc = 0;
|
|
|
|
|
|
void
|
|
GarbageCollectionThread (
|
|
IN void PAPI * Ignore
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the routine executed by the garbage collection thread.
|
|
|
|
Arguments:
|
|
|
|
Ignore - just ignore this; it is not used.
|
|
|
|
--*/
|
|
{
|
|
UNUSED(Ignore);
|
|
|
|
for (;;)
|
|
{
|
|
PerformGarbageCollection();
|
|
PauseExecution(WaitToGarbageCollectDelay * 1000);
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
GarbageCollectionNeeded (
|
|
IN unsigned long EveryNumberOfSeconds
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
If a protocol module needs to be called periodically to clean up
|
|
(garbage collect) idle resources, it will call this routine. We just
|
|
need to arrange things so that each protocol module gets called
|
|
periodically to do this.
|
|
|
|
--*/
|
|
{
|
|
RPC_STATUS RpcStatus = RPC_S_OK;
|
|
THREAD * Thread;
|
|
|
|
WaitToGarbageCollectDelay = EveryNumberOfSeconds;
|
|
|
|
if ( EnableGc != 0 )
|
|
{
|
|
if ( GcThreadStarted == 0 )
|
|
{
|
|
RequestGlobalMutex();
|
|
|
|
if ( GcThreadStarted == 0 )
|
|
{
|
|
Thread = new THREAD(GarbageCollectionThread, 0, &RpcStatus);
|
|
if ( RpcStatus != RPC_S_OK )
|
|
{
|
|
delete Thread;
|
|
}
|
|
else if ( Thread != 0 )
|
|
{
|
|
GcThreadStarted = 1;
|
|
}
|
|
}
|
|
ClearGlobalMutex();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
RPC_STATUS
|
|
EnableGarbageCollection (
|
|
void
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
We need to enable garbage collection.
|
|
|
|
Return Value:
|
|
|
|
RPC_S_OK - This value will always be returned.
|
|
|
|
--*/
|
|
{
|
|
EnableGc = 1;
|
|
|
|
return(RPC_S_OK);
|
|
}
|
|
|
|
|
|
typedef struct {
|
|
RPC_STATUS RpcStatus;
|
|
long NtStatus;
|
|
} STATUS_MAPPING;
|
|
|
|
static const STATUS_MAPPING StatusMap[] =
|
|
{
|
|
{ RPC_S_INVALID_STRING_BINDING, RPC_NT_INVALID_STRING_BINDING },
|
|
{ RPC_S_WRONG_KIND_OF_BINDING, RPC_NT_WRONG_KIND_OF_BINDING },
|
|
{ RPC_S_INVALID_BINDING, RPC_NT_INVALID_BINDING },
|
|
{ RPC_S_PROTSEQ_NOT_SUPPORTED, RPC_NT_PROTSEQ_NOT_SUPPORTED },
|
|
{ RPC_S_INVALID_RPC_PROTSEQ, RPC_NT_INVALID_RPC_PROTSEQ },
|
|
{ RPC_S_INVALID_STRING_UUID, RPC_NT_INVALID_STRING_UUID },
|
|
{ RPC_S_INVALID_ENDPOINT_FORMAT, RPC_NT_INVALID_ENDPOINT_FORMAT },
|
|
{ RPC_S_INVALID_NET_ADDR, RPC_NT_INVALID_NET_ADDR },
|
|
{ RPC_S_NO_ENDPOINT_FOUND, RPC_NT_NO_ENDPOINT_FOUND },
|
|
{ RPC_S_INVALID_TIMEOUT, RPC_NT_INVALID_TIMEOUT },
|
|
{ RPC_S_OBJECT_NOT_FOUND, RPC_NT_OBJECT_NOT_FOUND },
|
|
{ RPC_S_ALREADY_REGISTERED, RPC_NT_ALREADY_REGISTERED },
|
|
{ RPC_S_TYPE_ALREADY_REGISTERED, RPC_NT_TYPE_ALREADY_REGISTERED },
|
|
{ RPC_S_ALREADY_LISTENING, RPC_NT_ALREADY_LISTENING },
|
|
{ RPC_S_NO_PROTSEQS_REGISTERED, RPC_NT_NO_PROTSEQS_REGISTERED },
|
|
{ RPC_S_NOT_LISTENING, RPC_NT_NOT_LISTENING },
|
|
{ RPC_S_UNKNOWN_MGR_TYPE, RPC_NT_UNKNOWN_MGR_TYPE },
|
|
{ RPC_S_UNKNOWN_IF, RPC_NT_UNKNOWN_IF },
|
|
{ RPC_S_NO_BINDINGS, RPC_NT_NO_BINDINGS },
|
|
{ RPC_S_NO_MORE_BINDINGS, RPC_NT_NO_MORE_BINDINGS },
|
|
{ RPC_S_NO_PROTSEQS, RPC_NT_NO_PROTSEQS },
|
|
{ RPC_S_CANT_CREATE_ENDPOINT, RPC_NT_CANT_CREATE_ENDPOINT },
|
|
{ RPC_S_OUT_OF_RESOURCES, RPC_NT_OUT_OF_RESOURCES },
|
|
{ RPC_S_SERVER_UNAVAILABLE, RPC_NT_SERVER_UNAVAILABLE },
|
|
{ RPC_S_SERVER_TOO_BUSY, RPC_NT_SERVER_TOO_BUSY },
|
|
{ RPC_S_INVALID_NETWORK_OPTIONS, RPC_NT_INVALID_NETWORK_OPTIONS },
|
|
{ RPC_S_NO_CALL_ACTIVE, RPC_NT_NO_CALL_ACTIVE },
|
|
{ RPC_S_CALL_FAILED, RPC_NT_CALL_FAILED },
|
|
{ RPC_S_CALL_FAILED_DNE, RPC_NT_CALL_FAILED_DNE },
|
|
{ RPC_S_PROTOCOL_ERROR, RPC_NT_PROTOCOL_ERROR },
|
|
{ RPC_S_UNSUPPORTED_TRANS_SYN, RPC_NT_UNSUPPORTED_TRANS_SYN },
|
|
{ RPC_S_SERVER_OUT_OF_MEMORY, STATUS_INSUFF_SERVER_RESOURCES },
|
|
{ RPC_S_UNSUPPORTED_TYPE, RPC_NT_UNSUPPORTED_TYPE },
|
|
{ RPC_S_INVALID_TAG, RPC_NT_INVALID_TAG },
|
|
{ RPC_S_INVALID_BOUND, RPC_NT_INVALID_BOUND },
|
|
{ RPC_S_NO_ENTRY_NAME, RPC_NT_NO_ENTRY_NAME },
|
|
{ RPC_S_INVALID_NAME_SYNTAX, RPC_NT_INVALID_NAME_SYNTAX },
|
|
{ RPC_S_UNSUPPORTED_NAME_SYNTAX, RPC_NT_UNSUPPORTED_NAME_SYNTAX },
|
|
{ RPC_S_UUID_NO_ADDRESS, RPC_NT_UUID_NO_ADDRESS },
|
|
{ RPC_S_DUPLICATE_ENDPOINT, RPC_NT_DUPLICATE_ENDPOINT },
|
|
{ RPC_S_UNKNOWN_AUTHN_TYPE, RPC_NT_UNKNOWN_AUTHN_TYPE },
|
|
{ RPC_S_MAX_CALLS_TOO_SMALL, RPC_NT_MAX_CALLS_TOO_SMALL },
|
|
{ RPC_S_STRING_TOO_LONG, RPC_NT_STRING_TOO_LONG },
|
|
{ RPC_S_PROTSEQ_NOT_FOUND, RPC_NT_PROTSEQ_NOT_FOUND },
|
|
{ RPC_S_PROCNUM_OUT_OF_RANGE, RPC_NT_PROCNUM_OUT_OF_RANGE },
|
|
{ RPC_S_BINDING_HAS_NO_AUTH, RPC_NT_BINDING_HAS_NO_AUTH },
|
|
{ RPC_S_UNKNOWN_AUTHN_SERVICE, RPC_NT_UNKNOWN_AUTHN_SERVICE },
|
|
{ RPC_S_UNKNOWN_AUTHN_LEVEL, RPC_NT_UNKNOWN_AUTHN_LEVEL },
|
|
{ RPC_S_INVALID_AUTH_IDENTITY, RPC_NT_INVALID_AUTH_IDENTITY },
|
|
{ RPC_S_UNKNOWN_AUTHZ_SERVICE, RPC_NT_UNKNOWN_AUTHZ_SERVICE },
|
|
{ EPT_S_INVALID_ENTRY, EPT_NT_INVALID_ENTRY },
|
|
{ EPT_S_CANT_PERFORM_OP, EPT_NT_CANT_PERFORM_OP },
|
|
{ EPT_S_NOT_REGISTERED, EPT_NT_NOT_REGISTERED },
|
|
{ RPC_S_NOTHING_TO_EXPORT, RPC_NT_NOTHING_TO_EXPORT },
|
|
{ RPC_S_INCOMPLETE_NAME, RPC_NT_INCOMPLETE_NAME },
|
|
{ RPC_S_INVALID_VERS_OPTION, RPC_NT_INVALID_VERS_OPTION },
|
|
{ RPC_S_NO_MORE_MEMBERS, RPC_NT_NO_MORE_MEMBERS },
|
|
{ RPC_S_NOT_ALL_OBJS_UNEXPORTED, RPC_NT_NOT_ALL_OBJS_UNEXPORTED },
|
|
{ RPC_S_INTERFACE_NOT_FOUND, RPC_NT_INTERFACE_NOT_FOUND },
|
|
{ RPC_S_ENTRY_ALREADY_EXISTS, RPC_NT_ENTRY_ALREADY_EXISTS },
|
|
{ RPC_S_ENTRY_NOT_FOUND, RPC_NT_ENTRY_NOT_FOUND },
|
|
{ RPC_S_NAME_SERVICE_UNAVAILABLE, RPC_NT_NAME_SERVICE_UNAVAILABLE },
|
|
{ RPC_S_INVALID_NAF_ID, RPC_NT_INVALID_NAF_ID },
|
|
{ RPC_S_CANNOT_SUPPORT, RPC_NT_CANNOT_SUPPORT },
|
|
{ RPC_S_NO_CONTEXT_AVAILABLE, RPC_NT_NO_CONTEXT_AVAILABLE },
|
|
{ RPC_S_INTERNAL_ERROR, RPC_NT_INTERNAL_ERROR },
|
|
{ RPC_S_ZERO_DIVIDE, RPC_NT_ZERO_DIVIDE },
|
|
{ RPC_S_ADDRESS_ERROR, RPC_NT_ADDRESS_ERROR },
|
|
{ RPC_S_FP_DIV_ZERO, RPC_NT_FP_DIV_ZERO },
|
|
{ RPC_S_FP_UNDERFLOW, RPC_NT_FP_UNDERFLOW },
|
|
{ RPC_S_FP_OVERFLOW, RPC_NT_FP_OVERFLOW },
|
|
{ RPC_X_NO_MORE_ENTRIES, RPC_NT_NO_MORE_ENTRIES },
|
|
{ RPC_X_SS_CHAR_TRANS_OPEN_FAIL, RPC_NT_SS_CHAR_TRANS_OPEN_FAIL },
|
|
{ RPC_X_SS_CHAR_TRANS_SHORT_FILE, RPC_NT_SS_CHAR_TRANS_SHORT_FILE },
|
|
{ RPC_X_SS_IN_NULL_CONTEXT, RPC_NT_SS_IN_NULL_CONTEXT },
|
|
{ RPC_X_SS_CONTEXT_MISMATCH, RPC_NT_SS_CONTEXT_MISMATCH },
|
|
{ RPC_X_SS_CONTEXT_DAMAGED, RPC_NT_SS_CONTEXT_DAMAGED },
|
|
{ RPC_X_SS_HANDLES_MISMATCH, RPC_NT_SS_HANDLES_MISMATCH },
|
|
{ RPC_X_SS_CANNOT_GET_CALL_HANDLE, RPC_NT_SS_CANNOT_GET_CALL_HANDLE },
|
|
{ RPC_X_NULL_REF_POINTER, RPC_NT_NULL_REF_POINTER },
|
|
{ RPC_X_ENUM_VALUE_OUT_OF_RANGE, RPC_NT_ENUM_VALUE_OUT_OF_RANGE },
|
|
{ RPC_X_BYTE_COUNT_TOO_SMALL, RPC_NT_BYTE_COUNT_TOO_SMALL },
|
|
{ RPC_X_BAD_STUB_DATA, RPC_NT_BAD_STUB_DATA },
|
|
{ ERROR_INVALID_PARAMETER, STATUS_INVALID_PARAMETER },
|
|
{ ERROR_OUTOFMEMORY, STATUS_NO_MEMORY },
|
|
{ ERROR_MAX_THRDS_REACHED, STATUS_NO_MEMORY },
|
|
{ ERROR_INSUFFICIENT_BUFFER, STATUS_BUFFER_TOO_SMALL },
|
|
{ ERROR_INVALID_SECURITY_DESCR, STATUS_INVALID_SECURITY_DESCR },
|
|
{ ERROR_ACCESS_DENIED, STATUS_ACCESS_DENIED },
|
|
{ ERROR_NOACCESS, STATUS_ACCESS_VIOLATION },
|
|
{ RPC_S_CALL_IN_PROGRESS, RPC_NT_CALL_IN_PROGRESS },
|
|
{ RPC_S_GROUP_MEMBER_NOT_FOUND, RPC_NT_GROUP_MEMBER_NOT_FOUND },
|
|
{ EPT_S_CANT_CREATE, EPT_NT_CANT_CREATE },
|
|
{ RPC_S_INVALID_OBJECT, RPC_NT_INVALID_OBJECT }
|
|
};
|
|
|
|
long RPC_ENTRY
|
|
I_RpcMapWin32Status (
|
|
IN RPC_STATUS Status
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine maps a WIN32 RPC status code into an NT RPC status code.
|
|
|
|
Arguments:
|
|
|
|
Status - Supplies the WIN32 RPC status code to be mapped.
|
|
|
|
Return Value:
|
|
|
|
The NT RPC status code corresponding to the WIN32 RPC status code
|
|
will be returned.
|
|
|
|
--*/
|
|
{
|
|
register int i;
|
|
for(i = 0; i < sizeof(StatusMap)/sizeof(STATUS_MAPPING); i++)
|
|
{
|
|
if (StatusMap[i].RpcStatus == Status)
|
|
{
|
|
return(StatusMap[i].NtStatus);
|
|
}
|
|
}
|
|
return(Status);
|
|
}
|
|
|