2449 lines
66 KiB
C++
2449 lines
66 KiB
C++
/*++
|
||
|
||
Copyright (C) Microsoft Corporation, 1991 - 1999
|
||
|
||
Module Name:
|
||
|
||
miscnt.cxx
|
||
|
||
Abstract:
|
||
|
||
This file contains NT specific implementations of miscellaneous
|
||
routines.
|
||
|
||
Author:
|
||
|
||
Michael Montague (mikemon) 25-Nov-1991
|
||
|
||
Revision History:
|
||
|
||
Kamen Moutafov (KamenM) Dec 99 - Feb 2000 - Support for cell debugging stuff
|
||
Kamen Moutafov (KamenM) Mar-2000 Support for extended error info
|
||
--*/
|
||
|
||
#include <precomp.hxx>
|
||
#include <rpccfg.h>
|
||
#include <CharConv.hxx>
|
||
|
||
static const char *RPC_REGISTRY_PROTOCOLS =
|
||
"Software\\Microsoft\\Rpc\\ClientProtocols";
|
||
|
||
static const char *RPC_REGISTRY_PROTOCOL_IDS =
|
||
"Software\\Microsoft\\Rpc\\AdditionalProtocols";
|
||
|
||
static const RPC_CHAR *RPC_REGISTRY_DEFAULT_SECURITY_DLL =
|
||
L"System\\CurrentControlSet\\Control\\SecurityProviders";
|
||
|
||
// N.B. This value must agree with the key specified in the system.adm file
|
||
static const RPC_CHAR *RPC_POLICY_SETTINGS =
|
||
L"Software\\Policies\\Microsoft\\Windows NT\\Rpc";
|
||
|
||
static const RPC_CHAR *RPC_REGISTRY_IMAGE_FILE_EXEC =
|
||
L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\";
|
||
|
||
static const RPC_CHAR *RPC_REGISTRY_THREAD_THROTTLE =
|
||
L"\\RpcThreadPoolThrottle";
|
||
|
||
const int IMAGE_FILE_EXEC_LENGTH = 75;
|
||
const int THREAD_THROTTLE_LENGTH = 24;
|
||
|
||
#define MAX_ENDPOINT_LENGTH 128
|
||
#define MAX_ID_LENGTH 6
|
||
#define MAX_DLL_NAME 128
|
||
|
||
typedef struct
|
||
{
|
||
const RPC_CHAR * RpcProtocolSequence;
|
||
const RPC_CHAR * TransportInterfaceDll;
|
||
unsigned long TransportId;
|
||
} RPC_PROTOCOL_SEQUENCE_MAP;
|
||
|
||
static const RPC_PROTOCOL_SEQUENCE_MAP RpcProtocolSequenceMap[] =
|
||
{
|
||
{
|
||
RPC_CONST_STRING("ncacn_np"),
|
||
RPC_CONST_STRING("rpcrt4.dll"),
|
||
NMP_TOWER_ID
|
||
},
|
||
|
||
{
|
||
RPC_CONST_STRING("ncacn_ip_tcp"),
|
||
RPC_CONST_STRING("rpcrt4.dll"),
|
||
TCP_TOWER_ID
|
||
},
|
||
|
||
#ifdef SPX_ON
|
||
{
|
||
RPC_CONST_STRING("ncacn_spx"),
|
||
RPC_CONST_STRING("rpcrt4.dll"),
|
||
SPX_TOWER_ID
|
||
},
|
||
#endif
|
||
|
||
{
|
||
RPC_CONST_STRING("ncadg_ip_udp"),
|
||
RPC_CONST_STRING("rpcrt4.dll"),
|
||
UDP_TOWER_ID
|
||
},
|
||
|
||
#ifdef IPX_ON
|
||
{
|
||
RPC_CONST_STRING("ncadg_ipx"),
|
||
RPC_CONST_STRING("rpcrt4.dll"),
|
||
IPX_TOWER_ID
|
||
},
|
||
#endif
|
||
|
||
#ifdef NETBIOS_ON
|
||
{
|
||
RPC_CONST_STRING("ncacn_nb_tcp"),
|
||
RPC_CONST_STRING("rpcrt4.dll"),
|
||
NB_TOWER_ID
|
||
},
|
||
|
||
{
|
||
RPC_CONST_STRING("ncacn_nb_ipx"),
|
||
RPC_CONST_STRING("rpcrt4.dll"),
|
||
NB_TOWER_ID
|
||
},
|
||
|
||
{
|
||
RPC_CONST_STRING("ncacn_nb_nb"),
|
||
RPC_CONST_STRING("rpcrt4.dll"),
|
||
NB_TOWER_ID
|
||
},
|
||
#endif
|
||
|
||
#ifdef APPLETALK_ON
|
||
{
|
||
RPC_CONST_STRING("ncacn_at_dsp"),
|
||
RPC_CONST_STRING("rpcrt4.dll"),
|
||
DSP_TOWER_ID
|
||
},
|
||
#endif
|
||
|
||
{
|
||
RPC_CONST_STRING("ncacn_http"),
|
||
RPC_CONST_STRING("rpcrt4.dll"),
|
||
HTTP_TOWER_ID
|
||
},
|
||
|
||
{
|
||
RPC_CONST_STRING("ncadg_cluster"),
|
||
RPC_CONST_STRING("rpcrt4.dll"),
|
||
CDP_TOWER_ID
|
||
},
|
||
|
||
#ifdef NCADG_MQ_ON
|
||
{
|
||
RPC_CONST_STRING("ncadg_mq"),
|
||
RPC_CONST_STRING("rpcrt4.dll"),
|
||
MQ_TOWER_ID
|
||
},
|
||
#endif
|
||
|
||
#ifdef BANYAN_ON
|
||
{
|
||
RPC_CONST_STRING("ncacn_vns_spp"),
|
||
RPC_CONST_STRING("rpcrt4.dll"),
|
||
SPP_TOWER_ID
|
||
},
|
||
#endif
|
||
|
||
{
|
||
RPC_CONST_STRING("ncalrpc"),
|
||
0,
|
||
0
|
||
},
|
||
};
|
||
|
||
const int RpcProtseqMapLength = (sizeof(RpcProtocolSequenceMap)
|
||
/ sizeof(RPC_PROTOCOL_SEQUENCE_MAP));
|
||
|
||
static const RPC_PROTOCOL_SEQUENCE_MAP RpcUseAllProtseqMap[] =
|
||
{
|
||
{
|
||
RPC_CONST_STRING("ncacn_np"),
|
||
RPC_CONST_STRING("rpcrt4.dll"),
|
||
NMP_TOWER_ID
|
||
},
|
||
|
||
{
|
||
RPC_CONST_STRING("ncalrpc"),
|
||
0,
|
||
0
|
||
},
|
||
};
|
||
|
||
const int RpcUseAllProtseqMapLength = (sizeof(RpcUseAllProtseqMap)
|
||
/ sizeof(RPC_PROTOCOL_SEQUENCE_MAP));
|
||
|
||
|
||
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";
|
||
static const char *RPC_MISC_SETTINGS =
|
||
"Software\\Microsoft\\Rpc";
|
||
|
||
BOOL DefaultProviderRead = FALSE;
|
||
DWORD DefaultAuthLevel = RPC_C_AUTHN_LEVEL_CONNECT;
|
||
DWORD DefaultProviderId = RPC_C_AUTHN_WINNT;
|
||
|
||
RPC_CHAR *DefaultSecurityDLL = L"secur32.dll";
|
||
BOOL DefaultSecurityDLLRead = FALSE;
|
||
|
||
void
|
||
GetMaxRpcSizeAndThreadPoolParameters (
|
||
void
|
||
)
|
||
{
|
||
HKEY RegistryKey;
|
||
|
||
DWORD Result;
|
||
DWORD RegStatus;
|
||
DWORD Type;
|
||
DWORD DwordSize = sizeof(DWORD);
|
||
RPC_CHAR KeyName[MAX_PATH + IMAGE_FILE_EXEC_LENGTH + THREAD_THROTTLE_LENGTH];
|
||
const RPC_CHAR * ModuleName;
|
||
int ModuleLength;
|
||
RPC_CHAR *CurrentPos;
|
||
|
||
//
|
||
// Get the default Rpc size.
|
||
//
|
||
RegStatus = RegOpenKeyExA(
|
||
HKEY_LOCAL_MACHINE,
|
||
(LPSTR) RPC_MISC_SETTINGS,
|
||
0L, KEY_READ, //Reserved
|
||
&RegistryKey
|
||
);
|
||
|
||
if ( RegStatus != ERROR_SUCCESS )
|
||
{
|
||
return;
|
||
}
|
||
|
||
RegStatus = RegQueryValueExA(
|
||
RegistryKey,
|
||
"MaxRpcSize",
|
||
0,
|
||
&Type,
|
||
(LPBYTE) &Result,
|
||
&DwordSize
|
||
);
|
||
|
||
if (RegStatus == ERROR_SUCCESS
|
||
&& Type == REG_DWORD)
|
||
{
|
||
gMaxRpcSize = Result;
|
||
}
|
||
|
||
RegCloseKey(RegistryKey);
|
||
|
||
//
|
||
// Find out the .EXE name.
|
||
//
|
||
ModuleName = FastGetImageBaseName();
|
||
ModuleLength = RpcpStringLength(ModuleName);
|
||
|
||
CurrentPos = KeyName;
|
||
RpcpMemoryCopy(CurrentPos,
|
||
RPC_REGISTRY_IMAGE_FILE_EXEC,
|
||
IMAGE_FILE_EXEC_LENGTH * 2);
|
||
|
||
CurrentPos += IMAGE_FILE_EXEC_LENGTH - 1;
|
||
RpcpMemoryCopy(CurrentPos,
|
||
ModuleName,
|
||
ModuleLength * 2);
|
||
|
||
CurrentPos += ModuleLength;
|
||
RpcpMemoryCopy(CurrentPos,
|
||
RPC_REGISTRY_THREAD_THROTTLE,
|
||
THREAD_THROTTLE_LENGTH * 2);
|
||
|
||
RegStatus = RegOpenKeyExW(
|
||
HKEY_LOCAL_MACHINE,
|
||
KeyName,
|
||
0L, KEY_READ, //Reserved
|
||
&RegistryKey
|
||
);
|
||
|
||
if ( RegStatus != ERROR_SUCCESS )
|
||
{
|
||
return;
|
||
}
|
||
|
||
DwordSize = sizeof(DWORD);
|
||
|
||
RegStatus = RegQueryValueExA(
|
||
RegistryKey,
|
||
"ProrateMax",
|
||
0,
|
||
&Type,
|
||
(LPBYTE) &Result,
|
||
&DwordSize
|
||
);
|
||
|
||
if (RegStatus == ERROR_SUCCESS
|
||
&& Type == REG_DWORD)
|
||
{
|
||
gProrateMax = Result;
|
||
}
|
||
|
||
DwordSize = sizeof(DWORD);
|
||
|
||
RegStatus = RegQueryValueExA(
|
||
RegistryKey,
|
||
"ProrateFactor",
|
||
0,
|
||
&Type,
|
||
(LPBYTE) &Result,
|
||
&DwordSize
|
||
);
|
||
|
||
if (RegStatus == ERROR_SUCCESS
|
||
&& Type == REG_DWORD)
|
||
{
|
||
gProrateFactor = Result;
|
||
}
|
||
|
||
DwordSize = sizeof(DWORD);
|
||
|
||
RegStatus = RegQueryValueExA(
|
||
RegistryKey,
|
||
"ProrateStart",
|
||
0,
|
||
&Type,
|
||
(LPBYTE) &Result,
|
||
&DwordSize
|
||
);
|
||
|
||
if (RegStatus == ERROR_SUCCESS
|
||
&& Type == REG_DWORD)
|
||
{
|
||
gProrateStart = Result;
|
||
}
|
||
|
||
RegCloseKey(RegistryKey);
|
||
|
||
// if any of these values are invalid, turn it off
|
||
if ((gProrateFactor == 0) || (gProrateMax == 0))
|
||
gProrateStart = 0;
|
||
}
|
||
|
||
|
||
BOOL
|
||
GetDefaultLevel()
|
||
{
|
||
HKEY RegistryKey;
|
||
|
||
DWORD Result;
|
||
DWORD RegStatus;
|
||
DWORD Type;
|
||
DWORD DwordSize = sizeof(DWORD);
|
||
|
||
//
|
||
// Get the default provider level.
|
||
//
|
||
RegStatus = RegOpenKeyExA(
|
||
HKEY_LOCAL_MACHINE,
|
||
(LPSTR) RPC_REGISTRY_SECURITY_PROVIDERS,
|
||
0L, KEY_READ, //Reserved
|
||
&RegistryKey
|
||
);
|
||
|
||
if ( RegStatus != ERROR_SUCCESS )
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
RegStatus = RegQueryValueExA(
|
||
RegistryKey,
|
||
"DefaultAuthLevel",
|
||
0,
|
||
&Type,
|
||
(LPBYTE) &Result,
|
||
&DwordSize
|
||
);
|
||
|
||
if (RegStatus == ERROR_CANTOPEN ||
|
||
RegStatus == ERROR_CANTREAD )
|
||
{
|
||
RegCloseKey(RegistryKey);
|
||
return TRUE;
|
||
}
|
||
|
||
if ( RegStatus != ERROR_SUCCESS )
|
||
{
|
||
RegCloseKey(RegistryKey);
|
||
return FALSE;
|
||
}
|
||
|
||
if ( Type != REG_DWORD )
|
||
{
|
||
RegCloseKey(RegistryKey);
|
||
return TRUE;
|
||
}
|
||
|
||
if (Result >= RPC_C_AUTHN_LEVEL_CONNECT &&
|
||
Result <= RPC_C_AUTHN_LEVEL_PKT_PRIVACY )
|
||
{
|
||
DefaultAuthLevel = Result;
|
||
}
|
||
|
||
RegCloseKey(RegistryKey);
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
void
|
||
RpcpGetDefaultSecurityProviderInfo()
|
||
{
|
||
if (DefaultProviderRead)
|
||
{
|
||
return;
|
||
}
|
||
|
||
if (GetDefaultLevel())
|
||
{
|
||
DefaultProviderRead = TRUE;
|
||
}
|
||
}
|
||
|
||
RPC_STATUS
|
||
GetDefaultSecurityDll (
|
||
IN RPC_CHAR *DllName,
|
||
IN ULONG DllNameLength
|
||
)
|
||
{
|
||
HKEY RegistryKey;
|
||
DWORD RegStatus;
|
||
RPC_CHAR *DuplicateDllName;
|
||
DWORD Type;
|
||
|
||
if (DefaultSecurityDLLRead == FALSE)
|
||
{
|
||
RegStatus = RegOpenKeyEx(
|
||
HKEY_LOCAL_MACHINE,
|
||
RPC_REGISTRY_DEFAULT_SECURITY_DLL,
|
||
0L, KEY_READ, //Reserved
|
||
&RegistryKey
|
||
);
|
||
|
||
if ( RegStatus != ERROR_SUCCESS )
|
||
{
|
||
if (RegStatus == ERROR_FILE_NOT_FOUND)
|
||
{
|
||
DefaultSecurityDLLRead = TRUE;
|
||
return RPC_S_OK;
|
||
}
|
||
|
||
return(RPC_S_UNKNOWN_AUTHN_SERVICE);
|
||
}
|
||
|
||
|
||
RegStatus = RegQueryValueEx(
|
||
RegistryKey,
|
||
L"ClientDll",
|
||
0,
|
||
&Type,
|
||
(unsigned char *)DllName,
|
||
&DllNameLength
|
||
);
|
||
|
||
if ( RegStatus != ERROR_SUCCESS )
|
||
{
|
||
RegCloseKey(RegistryKey);
|
||
if (RegStatus == ERROR_FILE_NOT_FOUND)
|
||
{
|
||
DefaultSecurityDLLRead = TRUE;
|
||
return RPC_S_OK;
|
||
}
|
||
|
||
return(RPC_S_UNKNOWN_AUTHN_SERVICE);
|
||
}
|
||
|
||
if (Type != REG_SZ)
|
||
{
|
||
RegCloseKey(RegistryKey);
|
||
return(RPC_S_UNKNOWN_AUTHN_SERVICE);
|
||
}
|
||
|
||
DuplicateDllName = DuplicateString(DllName);
|
||
|
||
RegCloseKey(RegistryKey);
|
||
|
||
if (DuplicateDllName)
|
||
{
|
||
DefaultSecurityDLL = DuplicateDllName;
|
||
DefaultSecurityDLLRead = TRUE;
|
||
}
|
||
else
|
||
{
|
||
return RPC_S_OUT_OF_MEMORY;
|
||
}
|
||
|
||
}
|
||
|
||
return RPC_S_OK;
|
||
}
|
||
|
||
RPC_STATUS
|
||
RpcGetSecurityProviderInfo(
|
||
IN unsigned long AuthnId,
|
||
OUT RPC_CHAR **Dll,
|
||
OUT 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];
|
||
RPC_CHAR unicodeAuthnIdZ[8];
|
||
RPC_CHAR *pAuthnIdZ;
|
||
RPC_CHAR *ActualDllName;
|
||
|
||
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
|
||
|
||
SimpleAnsiToUnicode(AuthnIdZ, unicodeAuthnIdZ);
|
||
pAuthnIdZ = unicodeAuthnIdZ;
|
||
|
||
RegStatus = RegQueryValueEx(
|
||
RegistryKey,
|
||
(const RPC_SCHAR *)pAuthnIdZ,
|
||
0,
|
||
&Type,
|
||
(unsigned char *)DllName,
|
||
&DllNameLength
|
||
);
|
||
|
||
RegCloseKey(RegistryKey);
|
||
|
||
if (RegStatus != ERROR_SUCCESS)
|
||
{
|
||
RegStatus = GetDefaultSecurityDll(
|
||
DllName,
|
||
DllNameLength);
|
||
|
||
if (RegStatus == RPC_S_OK)
|
||
ActualDllName = DefaultSecurityDLL;
|
||
}
|
||
else
|
||
{
|
||
ActualDllName = DllName;
|
||
}
|
||
|
||
if (RegStatus == ERROR_SUCCESS)
|
||
{
|
||
*Dll = DuplicateString(ActualDllName);
|
||
if (*Dll == 0)
|
||
{
|
||
RegStatus = RPC_S_OUT_OF_MEMORY;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
RegStatus = RPC_S_UNKNOWN_AUTHN_SERVICE;
|
||
}
|
||
|
||
return(RegStatus);
|
||
}
|
||
|
||
DWORD * FourLeggedPackages = 0;
|
||
DWORD NullPackageList[] = { 0 };
|
||
|
||
|
||
|
||
BOOL
|
||
ReadPackageLegInfo()
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
NT 4.0 and previous versions allowed only two or three legs to set up the
|
||
security context. Two were represented on the wire as BIND then BIND_ACK;
|
||
three added an AUTH3 packet. When Jeff added 4- and 6-leg support, he
|
||
made the sequence BIND, BIND-ACK, ALTER-CXT, ALTER-CXT-RESPONSE. Sadly,
|
||
it turns out to be impossible for RPC to tell whether a given package wants
|
||
three or four legs, so the client would have to guess whether to send
|
||
an AUTH3 or an ALTER-CXT to an NT 4 server. To solve this we are adding a
|
||
registry value that lists all the providers that need more than three legs.
|
||
|
||
The format, in regdmp.exe form, is
|
||
|
||
\Registry\Machine\Software\Microsoft\Rpc
|
||
Four-legged packages = REG_MULTI_SZ "16" "18" ""
|
||
|
||
This function opens the registry and converts this data into an in-memory
|
||
array of DWORD package IDs.
|
||
|
||
Not all packages are in this list; see GetPackageLegCount() for details.
|
||
|
||
Return Values:
|
||
|
||
TRUE = the registry data was read, or the value does not exist.
|
||
Calling this function again will have no effect.
|
||
|
||
FALSE = there was a problem reading the data in the registry.
|
||
You can call the fn later and it will try again.
|
||
|
||
--*/
|
||
{
|
||
DWORD Size = 0;
|
||
DWORD RegStatus;
|
||
DWORD Type;
|
||
HKEY RegistryKey;
|
||
wchar_t * Strings;
|
||
|
||
if (FourLeggedPackages)
|
||
{
|
||
return TRUE;
|
||
}
|
||
|
||
SecurityCritSect->VerifyOwned();
|
||
|
||
// open key;
|
||
RegStatus = RegOpenKeyExA(
|
||
HKEY_LOCAL_MACHINE,
|
||
(LPSTR) RPC_REGISTRY_SECURITY_PROVIDERS,
|
||
0L, KEY_READ, //Reserved
|
||
&RegistryKey
|
||
);
|
||
|
||
if ( RegStatus != ERROR_SUCCESS )
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
// get size of strings
|
||
|
||
RegStatus = RegQueryValueExW(
|
||
RegistryKey,
|
||
L"Four-legged packages",
|
||
0,
|
||
&Type,
|
||
0,
|
||
&Size
|
||
);
|
||
|
||
if (RegStatus == ERROR_FILE_NOT_FOUND )
|
||
{
|
||
RegCloseKey(RegistryKey);
|
||
|
||
FourLeggedPackages = NullPackageList;
|
||
return TRUE;
|
||
}
|
||
|
||
if ( RegStatus != ERROR_SUCCESS )
|
||
{
|
||
RegCloseKey(RegistryKey);
|
||
return FALSE;
|
||
}
|
||
|
||
//
|
||
// Place an upper bound on the size to avoid hacker attacks.
|
||
//
|
||
if ( Type != REG_MULTI_SZ || Size > 4000)
|
||
{
|
||
RegCloseKey(RegistryKey);
|
||
FourLeggedPackages = NullPackageList;
|
||
return TRUE;
|
||
}
|
||
|
||
// get string data.
|
||
|
||
Strings = (wchar_t *) _alloca( Size );
|
||
|
||
RegStatus = RegQueryValueExW(
|
||
RegistryKey,
|
||
L"Four-legged packages",
|
||
0,
|
||
&Type,
|
||
(unsigned char *) Strings,
|
||
&Size
|
||
);
|
||
|
||
RegCloseKey(RegistryKey);
|
||
|
||
if (RegStatus == ERROR_CANTOPEN ||
|
||
RegStatus == ERROR_CANTREAD )
|
||
{
|
||
FourLeggedPackages = NullPackageList;
|
||
return TRUE;
|
||
}
|
||
|
||
if ( RegStatus != ERROR_SUCCESS )
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
if ( Type != REG_MULTI_SZ )
|
||
{
|
||
FourLeggedPackages = NullPackageList;
|
||
return TRUE;
|
||
}
|
||
|
||
// count strings; the buffer is terminated by an empty string that will be counted.
|
||
|
||
int Count = 0;
|
||
wchar_t * p;
|
||
for (p=Strings; p < Strings + Size; ++p)
|
||
{
|
||
if (*p == '\0')
|
||
{
|
||
++Count;
|
||
}
|
||
}
|
||
|
||
// allocate memory.
|
||
|
||
DWORD * LegData = new DWORD[Count];
|
||
if (!LegData)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
// transfer data
|
||
int i;
|
||
wchar_t * new_p;
|
||
for (i=0, p=Strings; p < Strings + Size; ++i, p = new_p+1)
|
||
{
|
||
LegData[i] = wcstoul(p, &new_p, 10);
|
||
if (*new_p != '\0')
|
||
{
|
||
// The string is badly formatted. Eliminate it.
|
||
--i;
|
||
new_p += wcslen(new_p);
|
||
}
|
||
}
|
||
|
||
if (FourLeggedPackages && FourLeggedPackages != NullPackageList)
|
||
{
|
||
delete FourLeggedPackages;
|
||
}
|
||
|
||
FourLeggedPackages = LegData;
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
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,
|
||
(LPSTR) &Protseq,
|
||
&ProtseqLength,
|
||
0,
|
||
&Ignore,
|
||
(LPBYTE) MaxValueData,
|
||
&IgnoreLength
|
||
);
|
||
|
||
if (RegStatus == ERROR_SUCCESS)
|
||
{
|
||
//Add this to our table..
|
||
AdditionalProtocolsInfo->RpcProtocolSequence =
|
||
new unsigned char[ProtseqLength+1];
|
||
Value = (char * )&MaxValueData;
|
||
AdditionalProtocolsInfo->RpcSsEndpoint =
|
||
new unsigned char[Length = (strlen(Value) + 1)];
|
||
|
||
|
||
if (AdditionalProtocolsInfo->RpcProtocolSequence == 0
|
||
|| AdditionalProtocolsInfo->RpcSsEndpoint == 0)
|
||
{
|
||
Status = RPC_S_OUT_OF_MEMORY;
|
||
goto Cleanup;
|
||
}
|
||
|
||
RpcpMemoryCopy(
|
||
AdditionalProtocolsInfo->RpcProtocolSequence,
|
||
Protseq,
|
||
ProtseqLength+1
|
||
);
|
||
|
||
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 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.
|
||
|
||
--*/
|
||
{
|
||
unsigned int Index;
|
||
|
||
for (Index = 0; Index < RpcProtseqMapLength; Index++)
|
||
{
|
||
if ( RpcpStringCompare(RpcProtocolSequence,
|
||
RpcProtocolSequenceMap[Index].RpcProtocolSequence) == 0 )
|
||
{
|
||
return((RPC_CHAR *)(RpcProtocolSequenceMap[Index].TransportInterfaceDll));
|
||
}
|
||
}
|
||
|
||
return(0);
|
||
}
|
||
|
||
RPC_STATUS
|
||
RpcGetWellKnownTransportInfo(
|
||
IN unsigned long TransportId,
|
||
OUT RPC_CHAR **PSeq
|
||
)
|
||
{
|
||
unsigned int Index;
|
||
|
||
for (Index = 0; Index < RpcProtseqMapLength; Index++)
|
||
{
|
||
if (TransportId == RpcProtocolSequenceMap[Index].TransportId)
|
||
{
|
||
*PSeq = (RPC_CHAR *)RpcProtocolSequenceMap[Index].RpcProtocolSequence;
|
||
return RPC_S_OK;
|
||
}
|
||
}
|
||
|
||
return(RPC_S_PROTSEQ_NOT_SUPPORTED);
|
||
}
|
||
|
||
|
||
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(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);
|
||
}
|
||
|
||
KeyString = (unsigned char *) RPC_REGISTRY_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 )
|
||
{
|
||
RegStatus = RegCloseKey(RegistryKey);
|
||
ASSERT( RegStatus == ERROR_SUCCESS );
|
||
|
||
return(RPC_S_OUT_OF_MEMORY);
|
||
}
|
||
|
||
Length = (MAX_DLLNAME_LENGTH + 1) * sizeof(RPC_CHAR);
|
||
RegStatus = RegQueryValueEx(RegistryKey, (const RPC_SCHAR *)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
|
||
RpcConfigInquireProtocolSequencesFromKey (
|
||
OUT RPC_PROTSEQ_VECTOR PAPI * PAPI * ProtseqVector,
|
||
unsigned char *RegistryKeyName
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is used to obtain a list of the rpc protocol sequences
|
||
supported by the system using a given registry key as a reference
|
||
point.
|
||
|
||
Arguments:
|
||
|
||
ProtseqVector - Returns a vector of supported rpc protocol sequences
|
||
for this rpc protocol module.
|
||
RegistryKeyName - the path of the registry key, starting from
|
||
HKLM (the HKLM itself should not be supplied)
|
||
|
||
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, MaximumValueLength;
|
||
DWORD ClassLength = 64, ProtseqLength, IgnoreLength;
|
||
BYTE IgnoreData[MAX_DLLNAME_LENGTH];
|
||
FILETIME LastWriteTime;
|
||
HKEY RegistryKey = 0;
|
||
unsigned char ClassName[64];
|
||
DWORD NumberOfValues = 0;
|
||
|
||
RegStatus = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
|
||
(LPSTR) RegistryKeyName, 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);
|
||
}
|
||
|
||
NumberOfValues += RpcUseAllProtseqMapLength;
|
||
|
||
*ProtseqVector = (RPC_PROTSEQ_VECTOR *) new unsigned char[
|
||
sizeof(RPC_PROTSEQ_VECTOR) + (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 < RpcUseAllProtseqMapLength; Index++)
|
||
{
|
||
(*ProtseqVector)->Protseq[Index] = new RPC_CHAR[MAX_PROTSEQ_LENGTH];
|
||
if ( (*ProtseqVector)->Protseq[Index] == 0 )
|
||
{
|
||
RegStatus = RegCloseKey(RegistryKey);
|
||
ASSERT( RegStatus == ERROR_SUCCESS );
|
||
|
||
RpcProtseqVectorFree(ProtseqVector);
|
||
|
||
return(RPC_S_OUT_OF_MEMORY);
|
||
}
|
||
|
||
RpcpStringCopy((*ProtseqVector)->Protseq[Index],
|
||
RpcUseAllProtseqMap[Index].RpcProtocolSequence);
|
||
|
||
}
|
||
|
||
unsigned VectorIndex = Index;
|
||
|
||
for (Index = 0; VectorIndex < NumberOfValues; Index++, VectorIndex++)
|
||
{
|
||
(*ProtseqVector)->Protseq[VectorIndex] = new RPC_CHAR[MAX_PROTSEQ_LENGTH];
|
||
if ( (*ProtseqVector)->Protseq[VectorIndex] == 0 )
|
||
{
|
||
RegStatus = RegCloseKey(RegistryKey);
|
||
ASSERT( RegStatus == ERROR_SUCCESS );
|
||
|
||
RpcProtseqVectorFree(ProtseqVector);
|
||
|
||
return(RPC_S_OUT_OF_MEMORY);
|
||
}
|
||
|
||
ProtseqLength = MAX_PROTSEQ_LENGTH;
|
||
IgnoreLength = MAX_DLLNAME_LENGTH;
|
||
RegStatus = RegEnumValue(RegistryKey, Index,
|
||
(RPC_SCHAR *)(*ProtseqVector)->Protseq[VectorIndex], &ProtseqLength,
|
||
0, &Ignore, (LPBYTE) IgnoreData, &IgnoreLength);
|
||
|
||
ASSERT( RegStatus == ERROR_SUCCESS );
|
||
|
||
if (RpcpStringCompare((RPC_SCHAR *)(*ProtseqVector)->Protseq[VectorIndex], RPC_T("ncacn_np")) == 0)
|
||
{
|
||
// ignore this named pipe value - we have to have it in the registry for
|
||
// compatibility purposes with VB, but we don't really use it
|
||
NumberOfValues --;
|
||
(*ProtseqVector)->Count --;
|
||
delete (*ProtseqVector)->Protseq[VectorIndex];
|
||
VectorIndex --;
|
||
}
|
||
}
|
||
|
||
RegStatus = RegCloseKey(RegistryKey);
|
||
ASSERT( RegStatus == ERROR_SUCCESS );
|
||
|
||
return(RPC_S_OK);
|
||
}
|
||
|
||
RPC_STATUS RpcConfigInquireStaticProtocolSequences(RPC_PROTSEQ_VECTOR **ProtseqVector)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Returns a protseq vector that contains all the protseqs in the static RpcProtocolSequenceMap
|
||
map.
|
||
|
||
Arguments:
|
||
|
||
ProtseqVector - Returns a vector of supported rpc protocol sequences.
|
||
|
||
Return Value:
|
||
|
||
RPC_S_OK - The operation completed successfully.
|
||
|
||
RPC_S_OUT_OF_MEMORY - Insufficient memory is available to construct the vector.
|
||
|
||
--*/
|
||
{
|
||
int nNumberOfValues = sizeof(RpcProtocolSequenceMap) / sizeof(RpcProtocolSequenceMap[0]);
|
||
int i;
|
||
|
||
*ProtseqVector = (RPC_PROTSEQ_VECTOR *) new unsigned char[
|
||
sizeof(RPC_PROTSEQ_VECTOR) + (nNumberOfValues - 1)
|
||
* sizeof(RPC_CHAR *)];
|
||
|
||
if ( *ProtseqVector == 0 )
|
||
return(RPC_S_OUT_OF_MEMORY);
|
||
|
||
(*ProtseqVector)->Count = (unsigned int) nNumberOfValues;
|
||
|
||
for (i = 0; i < nNumberOfValues; i ++)
|
||
{
|
||
(*ProtseqVector)->Protseq[i] = NULL;
|
||
}
|
||
|
||
for (i = 0; i < nNumberOfValues; i ++)
|
||
{
|
||
(*ProtseqVector)->Protseq[i] = new RPC_CHAR[MAX_PROTSEQ_LENGTH];
|
||
if ( (*ProtseqVector)->Protseq[i] == 0 )
|
||
{
|
||
|
||
RpcProtseqVectorFree(ProtseqVector);
|
||
|
||
return(RPC_S_OUT_OF_MEMORY);
|
||
}
|
||
|
||
RpcpStringCopy((*ProtseqVector)->Protseq[i],
|
||
RpcProtocolSequenceMap[i].RpcProtocolSequence);
|
||
|
||
}
|
||
|
||
return RPC_S_OK;
|
||
}
|
||
|
||
int MarkDuplicateEntries(IN RPC_PROTSEQ_VECTOR *ProtseqVector1,
|
||
IN int nVector1CurrentPos,
|
||
IN RPC_PROTSEQ_VECTOR *ProtseqVector2 OPTIONAL,
|
||
IN OUT UCHAR *pfDuplicates1,
|
||
IN OUT UCHAR *pfDuplicates2)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is tightly coupled with RpcConfigInquireProtocolSequences.
|
||
If the current element is already marked as duplicate by previous
|
||
run of this function, we directly return 1. If not,
|
||
it checks whether the current element is duplicate of any element
|
||
starting with the nVetcor1StartingPos from the first vector, and
|
||
going through the whole second vector if it is there, and marking
|
||
all duplicates of the current element as such. Then 0 is returned.
|
||
If the second vector is NULL, the pfDuplicates2 must be NULL also. This
|
||
means that there is one vector only, and its data are passed in
|
||
in RpcProtseqVector1 and in pfDuplicates1.
|
||
|
||
Arguments:
|
||
|
||
RpcProtseqVector1 - the first vector
|
||
nVector1CurrentPos - the current position from the first vector
|
||
RpcProtseqVector2 - the second vector. This argument may be null
|
||
pfDuplicates1 - the array of duplicate flags for the first vector
|
||
pfDuplicates2 - the array of duplicate flags for the second vector. If
|
||
second vector is NULL, must be NULL also.
|
||
|
||
Return Value:
|
||
|
||
1 - the current element is a duplicate of an element that we
|
||
encountered in a previous run of this function.
|
||
0 - the current element is unique in both vectors
|
||
|
||
--*/
|
||
{
|
||
int i;
|
||
RPC_CHAR *pszCurrentElement;
|
||
|
||
ASSERT(nVector1CurrentPos < (int)ProtseqVector1->Count);
|
||
|
||
if (pfDuplicates1[nVector1CurrentPos])
|
||
return 1;
|
||
|
||
pszCurrentElement = ProtseqVector1->Protseq[nVector1CurrentPos];
|
||
|
||
for (i = nVector1CurrentPos + 1; i < (int)ProtseqVector1->Count; i ++)
|
||
{
|
||
if (RpcpStringCompare(pszCurrentElement,
|
||
ProtseqVector1->Protseq[i]) == 0)
|
||
{
|
||
pfDuplicates1[i] = TRUE;
|
||
}
|
||
}
|
||
|
||
if (ProtseqVector2)
|
||
{
|
||
ASSERT(pfDuplicates2 != NULL);
|
||
|
||
for (i = 0; i < (int)ProtseqVector2->Count; i ++)
|
||
{
|
||
if (RpcpStringCompare(pszCurrentElement,
|
||
ProtseqVector2->Protseq[i]) == 0)
|
||
{
|
||
pfDuplicates2[i] = TRUE;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
ASSERT(pfDuplicates2 == NULL);
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
RPC_STATUS
|
||
MergeProtseqVectors (IN OUT RPC_PROTSEQ_VECTOR *ProtseqVector1,
|
||
IN OUT RPC_PROTSEQ_VECTOR *ProtseqVector2 OPTIONAL,
|
||
OUT RPC_PROTSEQ_VECTOR **ProtseqVector
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine takes two protseq vectors, and in the OUT argument ProtseqVector
|
||
returns the resulting vector, which is a union of the two IN
|
||
vectors. Successful or not, the input vectors will be freed on exit.
|
||
|
||
Arguments:
|
||
|
||
ProtseqVector1 - the first vector
|
||
ProtseqVector2 - the second vector. This argument may be null in which case the
|
||
output vector is simply the first vector.
|
||
ProtseqVector - the resulting union vector. If the return value from the function
|
||
is not RPC_S_OK, the out parameter is undefined and should not be used by caller.
|
||
|
||
Return Value:
|
||
|
||
RPC_S_OK - success. The ProtseqVector argument contains the resulting vector.
|
||
error code - the cause of the error.
|
||
|
||
--*/
|
||
{
|
||
unsigned char *pfDuplicate1;
|
||
unsigned char *pfDuplicate2;
|
||
int i, j;
|
||
int nDuplicateElements;
|
||
int nCurrentElement;
|
||
int nUniqueElements;
|
||
|
||
// compare basically each with each
|
||
// construct arrays in which we will mark each duplicate element
|
||
// if it is such
|
||
pfDuplicate1 = (unsigned char *)alloca(ProtseqVector1->Count);
|
||
if (ProtseqVector2)
|
||
pfDuplicate2 = (unsigned char *)alloca(ProtseqVector2->Count);
|
||
else
|
||
pfDuplicate2 = NULL;
|
||
|
||
// all elements are presumed to be unique unless proven otherwise
|
||
memset(pfDuplicate1, 0, ProtseqVector1->Count);
|
||
if (ProtseqVector2)
|
||
memset(pfDuplicate2, 0, ProtseqVector2->Count);
|
||
|
||
nDuplicateElements = 0;
|
||
|
||
// do compare each with each
|
||
// test the first vector for uniqueness
|
||
for (i = 0; i < (int)ProtseqVector1->Count; i ++)
|
||
{
|
||
nDuplicateElements += MarkDuplicateEntries(ProtseqVector1, i,
|
||
ProtseqVector2, pfDuplicate1, pfDuplicate2);
|
||
}
|
||
|
||
if (ProtseqVector2)
|
||
{
|
||
// test the second vector for uniqueness
|
||
for (i = 0; i < (int)ProtseqVector2->Count; i ++)
|
||
{
|
||
nDuplicateElements += MarkDuplicateEntries(ProtseqVector2, i,
|
||
NULL, pfDuplicate2, NULL);
|
||
}
|
||
}
|
||
|
||
// here we must move the unique elements to a new vector
|
||
// first, calculate the length of the new vector
|
||
nUniqueElements = ProtseqVector1->Count - nDuplicateElements;
|
||
if (ProtseqVector2)
|
||
nUniqueElements += ProtseqVector2->Count;
|
||
|
||
// second, alloc the new vector
|
||
*ProtseqVector = (RPC_PROTSEQ_VECTOR *) new unsigned char[
|
||
sizeof(RPC_PROTSEQ_VECTOR) +
|
||
(nUniqueElements - 1) * sizeof(RPC_CHAR *)];
|
||
if (*ProtseqVector == NULL)
|
||
{
|
||
RpcProtseqVectorFree(&ProtseqVector1);
|
||
if (ProtseqVector2)
|
||
RpcProtseqVectorFree(&ProtseqVector2);
|
||
return RPC_S_OUT_OF_MEMORY;
|
||
}
|
||
|
||
// set the count of the union vector
|
||
(*ProtseqVector)->Count = nUniqueElements;
|
||
|
||
nCurrentElement = 0; // counts the current element in the union
|
||
// vector
|
||
for (i = 0; i < (int)ProtseqVector1->Count; i ++)
|
||
{
|
||
if (!pfDuplicate1[i])
|
||
{
|
||
(*ProtseqVector)->Protseq[nCurrentElement] =
|
||
ProtseqVector1->Protseq[i];
|
||
nCurrentElement ++;
|
||
// save the string from deletion
|
||
ProtseqVector1->Protseq[i] = NULL;
|
||
}
|
||
}
|
||
|
||
if (ProtseqVector2)
|
||
{
|
||
for (i = 0; i < (int)ProtseqVector2->Count; i ++)
|
||
{
|
||
if (!pfDuplicate2[i])
|
||
{
|
||
(*ProtseqVector)->Protseq[nCurrentElement] =
|
||
ProtseqVector2->Protseq[i];
|
||
nCurrentElement ++;
|
||
// save the string from deletion
|
||
ProtseqVector2->Protseq[i] = NULL;
|
||
}
|
||
}
|
||
}
|
||
|
||
// we don't need the original vectors anymore - delete them
|
||
RpcProtseqVectorFree(&ProtseqVector1);
|
||
if (ProtseqVector2)
|
||
RpcProtseqVectorFree(&ProtseqVector2);
|
||
|
||
return RPC_S_OK;
|
||
}
|
||
|
||
|
||
RPC_STATUS
|
||
RpcConfigInquireProtocolSequences (
|
||
IN BOOL fGetAllProtseqs,
|
||
OUT RPC_PROTSEQ_VECTOR PAPI * PAPI * ProtseqVector1
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is used to obtain a list of the rpc protocol sequences
|
||
supported by the system.
|
||
|
||
Arguments:
|
||
|
||
fGetAllProtseqs - if TRUE, all protseqs known will be returned. If FALSE,
|
||
only the protseqs currently installed will be returned.
|
||
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 rpc.
|
||
|
||
--*/
|
||
{
|
||
RPC_STATUS RpcStatus1;
|
||
RPC_STATUS RpcStatus2;
|
||
RPC_PROTSEQ_VECTOR *ProtseqVector2 = NULL;
|
||
RPC_PROTSEQ_VECTOR *ProtseqVector;
|
||
|
||
if (fGetAllProtseqs)
|
||
{
|
||
RpcStatus2 = RpcConfigInquireStaticProtocolSequences(&ProtseqVector2);
|
||
if (RpcStatus2 != RPC_S_OK)
|
||
return RpcStatus2;
|
||
}
|
||
|
||
// under NT, failure to query the registry vector is fatal. Under Win98, querying
|
||
// this registry vector is optional, and if we fail, we have to continue gathering the
|
||
// vector from other sources.
|
||
RpcStatus1 = RpcConfigInquireProtocolSequencesFromKey(
|
||
ProtseqVector1, (unsigned char *)RPC_REGISTRY_PROTOCOLS);
|
||
|
||
if (RpcStatus1 != RPC_S_OK)
|
||
{
|
||
RpcProtseqVectorFree(&ProtseqVector2);
|
||
return RpcStatus1;
|
||
}
|
||
|
||
if (fGetAllProtseqs)
|
||
{
|
||
// Merge the static vector and the one from the registry
|
||
RpcStatus1 = MergeProtseqVectors(*ProtseqVector1, ProtseqVector2, &ProtseqVector);
|
||
if (RpcStatus1 != RPC_S_OK)
|
||
{
|
||
return RpcStatus1;
|
||
}
|
||
|
||
*ProtseqVector1 = ProtseqVector;
|
||
}
|
||
|
||
return RpcStatus1;
|
||
}
|
||
|
||
// N.B. This enumration must agree with the values
|
||
// in system.adm
|
||
typedef enum tagStateInformationPolicyValues
|
||
{
|
||
sipvNone,
|
||
sipvAuto1,
|
||
sipvAuto2,
|
||
sipvServer,
|
||
sipvFull
|
||
} StateInformationPolicyValues;
|
||
|
||
// N.B. This enumration must agree with the values
|
||
// in system.adm
|
||
typedef enum tagEEInfoPolicyValues
|
||
{
|
||
eeipvOff,
|
||
eeipvOnWithExceptions,
|
||
eeipvOffWithExceptions,
|
||
eeipvOn
|
||
} EEInfoPolicyValues;
|
||
|
||
void
|
||
SetAutoPolicySettings(
|
||
StateInformationPolicyValues PolicyValue
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine sets the state information maintenance to the appropriate
|
||
level of Auto, depending on machine capacity.
|
||
|
||
Arguments:
|
||
|
||
PolicyValue - sipvAuto1 or sipvAuto2
|
||
|
||
Return Value:
|
||
|
||
RPC_S_OK - The operation completed successfully.
|
||
|
||
other RPC_S_* - error
|
||
|
||
--*/
|
||
{
|
||
NT_PRODUCT_TYPE ProductType;
|
||
BOOL fNeedServer;
|
||
ULONG_PTR MinMemoryNeeded;
|
||
MEMORYSTATUSEX MemoryStatus;
|
||
BOOL fResult;
|
||
|
||
ASSERT((PolicyValue == sipvAuto1) || (PolicyValue == sipvAuto2));
|
||
|
||
// client side debug info is FALSE by default - no need to
|
||
// set it explicitly
|
||
|
||
// see what we have
|
||
// RtlGetNtProductType always returns valid ProductType
|
||
// It may be incorrect during GUI mode setup, but it will
|
||
// be valid
|
||
(VOID) RtlGetNtProductType(&ProductType);
|
||
|
||
MemoryStatus.dwLength = sizeof(MemoryStatus);
|
||
fResult = GlobalMemoryStatusEx(&MemoryStatus);
|
||
ASSERT(fResult);
|
||
|
||
// see what we have been asked for
|
||
if (PolicyValue == sipvAuto1)
|
||
{
|
||
fNeedServer = FALSE;
|
||
MinMemoryNeeded = 64 * 1024 * 1024; // 64MB of RAM
|
||
}
|
||
else
|
||
{
|
||
ASSERT (PolicyValue == sipvAuto2);
|
||
fNeedServer = TRUE;
|
||
MinMemoryNeeded = 127 * 1024 * 1024; // 127MB of RAM
|
||
}
|
||
|
||
// if we need server, but this is workstation, no state info
|
||
if (fNeedServer && (ProductType == NtProductWinNt))
|
||
{
|
||
g_fServerSideDebugInfoEnabled = FALSE;
|
||
return;
|
||
}
|
||
|
||
// if we have less physical memory than the one we need,
|
||
// no state info
|
||
if (MemoryStatus.ullTotalPhys < (ULONGLONG) MinMemoryNeeded)
|
||
{
|
||
g_fServerSideDebugInfoEnabled = FALSE;
|
||
return;
|
||
}
|
||
|
||
g_fServerSideDebugInfoEnabled = TRUE;
|
||
}
|
||
|
||
typedef enum tagExceptionListParserState
|
||
{
|
||
elpsOutsideOfQuotes,
|
||
elpsInsideQuotes,
|
||
elpsReadingWhitespace,
|
||
elpsReadingCharacter
|
||
} ExceptionListParserState;
|
||
|
||
BOOL
|
||
DoesThisProcessCmdLineStartWithThisString (
|
||
IN LPWSTR CmdLine,
|
||
IN LPWSTR CmdLineStart
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Checks if the process name starts with the string given
|
||
in CmdLineStart
|
||
|
||
Arguments:
|
||
|
||
CmdLine - the process command line with path name stripped
|
||
CmdLineStart - the patter to match against
|
||
|
||
Return Value:
|
||
|
||
non-zero - there is a match
|
||
FALSE - there is no match
|
||
|
||
--*/
|
||
{
|
||
int CmdLineLength = RpcpStringLength(CmdLine);
|
||
int CmdLineStartLength = RpcpStringLength(CmdLineStart);
|
||
|
||
if (CmdLineLength >= CmdLineStartLength)
|
||
{
|
||
if (RpcpStringNCompare(CmdLine, CmdLineStart, CmdLineStartLength) == 0)
|
||
return TRUE;
|
||
}
|
||
return FALSE;
|
||
}
|
||
|
||
typedef enum tagExceptionListCharacterTypes
|
||
{
|
||
elctQuotes,
|
||
elctCharacter,
|
||
elctWhitespace
|
||
} ExceptionListCharacterTypes;
|
||
|
||
inline ExceptionListCharacterTypes
|
||
GetCharacterType (
|
||
RPC_CHAR Character
|
||
)
|
||
{
|
||
if (Character == '"')
|
||
return elctQuotes;
|
||
if (Character == ' ')
|
||
return elctWhitespace;
|
||
return elctCharacter;
|
||
}
|
||
|
||
RPC_STATUS
|
||
IsThisProcessAnException (
|
||
IN HKEY RegistryKey,
|
||
BOOL *fThisProcessIsException
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Checks whether the current process is in the exceptions list as
|
||
specified in the ExtErrorInfoExceptions registry key
|
||
|
||
Arguments:
|
||
|
||
RegistryKey - an open key to RPC_POLICY_SETTINGS
|
||
fThisProcessIsException - on output non-zero if this process is
|
||
an exception and FALSE otherwise
|
||
|
||
Return Value:
|
||
|
||
RPC_S_OK or RPC_S_* error
|
||
|
||
--*/
|
||
{
|
||
DWORD RegStatus;
|
||
RPC_CHAR *Buffer = NULL;
|
||
DWORD Type;
|
||
DWORD Size = 0;
|
||
int Retries = 5;
|
||
int State;
|
||
RPC_CHAR *CurrentPos;
|
||
RPC_CHAR *CurrentString;
|
||
RPC_CHAR *CommandLine;
|
||
RPC_CHAR *LastBackslash;
|
||
BOOL fIsSubstring;
|
||
|
||
*fThisProcessIsException = FALSE;
|
||
|
||
while (Retries > 0)
|
||
{
|
||
RegStatus = RegQueryValueExW(
|
||
RegistryKey,
|
||
L"ExtErrorInfoExceptions",
|
||
0,
|
||
&Type,
|
||
(LPBYTE) Buffer,
|
||
&Size
|
||
);
|
||
|
||
if ( (RegStatus != ERROR_SUCCESS) && (RegStatus != ERROR_MORE_DATA) )
|
||
{
|
||
if (RegStatus == ERROR_FILE_NOT_FOUND)
|
||
RegStatus = RPC_S_OK;
|
||
else
|
||
RegStatus = RPC_S_OUT_OF_MEMORY;
|
||
|
||
goto CleanupAndReturn;
|
||
}
|
||
else
|
||
{
|
||
if ((Buffer == NULL) || (RegStatus == ERROR_MORE_DATA))
|
||
{
|
||
if (Buffer)
|
||
delete Buffer;
|
||
|
||
Buffer = new RPC_CHAR[Size];
|
||
if (Buffer == NULL)
|
||
{
|
||
RegStatus = RPC_S_OUT_OF_MEMORY;
|
||
goto CleanupAndReturn;
|
||
}
|
||
|
||
continue;
|
||
}
|
||
|
||
if (Type != REG_SZ)
|
||
{
|
||
RegStatus = RPC_S_INTERNAL_ERROR;
|
||
goto CleanupAndReturn;
|
||
}
|
||
|
||
ASSERT(RegStatus == RPC_S_OK);
|
||
|
||
CommandLine = GetCommandLine();
|
||
LastBackslash = wcsrchr(CommandLine, '\\');
|
||
if (LastBackslash != NULL)
|
||
CommandLine = LastBackslash + 1;
|
||
|
||
// here, Buffer contains the exception string
|
||
// The format of the exception string is:
|
||
// "cmd_line_start" "cmd_line_start" ...
|
||
// If there is only one cmd_line_start, it doesn't have to be in double quotes
|
||
State = elpsOutsideOfQuotes;
|
||
CurrentPos = Buffer;
|
||
CurrentString = NULL;
|
||
while (*CurrentPos != 0)
|
||
{
|
||
switch (State)
|
||
{
|
||
case elpsOutsideOfQuotes:
|
||
switch (GetCharacterType(*CurrentPos))
|
||
{
|
||
case elctQuotes:
|
||
CurrentString = CurrentPos;
|
||
State = elpsInsideQuotes;
|
||
break;
|
||
|
||
case elctCharacter:
|
||
CurrentString = CurrentPos;
|
||
State = elpsReadingCharacter;
|
||
break;
|
||
|
||
case elctWhitespace:
|
||
State = elpsReadingWhitespace;
|
||
break;
|
||
|
||
default:
|
||
ASSERT(0);
|
||
}
|
||
break;
|
||
|
||
case elpsReadingCharacter:
|
||
switch (GetCharacterType(*CurrentPos))
|
||
{
|
||
case elctQuotes:
|
||
*CurrentPos = 0;
|
||
fIsSubstring = DoesThisProcessCmdLineStartWithThisString(
|
||
CommandLine, CurrentString);
|
||
if (fIsSubstring)
|
||
{
|
||
*fThisProcessIsException = TRUE;
|
||
goto CleanupAndReturn;
|
||
}
|
||
CurrentString = CurrentPos + 1;
|
||
State = elpsReadingCharacter;
|
||
break;
|
||
|
||
case elctWhitespace:
|
||
*CurrentPos = 0;
|
||
fIsSubstring = DoesThisProcessCmdLineStartWithThisString(
|
||
CommandLine, CurrentString);
|
||
if (fIsSubstring)
|
||
{
|
||
*fThisProcessIsException = TRUE;
|
||
goto CleanupAndReturn;
|
||
}
|
||
State = elpsReadingCharacter;
|
||
break;
|
||
|
||
// default:
|
||
// can be elpsReadingCharacter
|
||
}
|
||
break;
|
||
|
||
case elpsReadingWhitespace:
|
||
switch (GetCharacterType(*CurrentPos))
|
||
{
|
||
case elctQuotes:
|
||
CurrentString = CurrentPos + 1;
|
||
State = elpsInsideQuotes;
|
||
break;
|
||
|
||
case elctCharacter:
|
||
CurrentString = CurrentPos;
|
||
State = elpsReadingCharacter;
|
||
break;
|
||
|
||
// default:
|
||
// can be elctWhitespace
|
||
}
|
||
break;
|
||
|
||
case elpsInsideQuotes:
|
||
switch (GetCharacterType(*CurrentPos))
|
||
{
|
||
case elctQuotes:
|
||
*CurrentPos = 0;
|
||
fIsSubstring = DoesThisProcessCmdLineStartWithThisString(
|
||
CommandLine, CurrentString);
|
||
if (fIsSubstring)
|
||
{
|
||
*fThisProcessIsException = TRUE;
|
||
goto CleanupAndReturn;
|
||
}
|
||
State = elpsOutsideOfQuotes;
|
||
break;
|
||
|
||
//default:
|
||
// can be elctCharacter or elctWhitespace
|
||
}
|
||
break;
|
||
|
||
default:
|
||
ASSERT(0);
|
||
}
|
||
CurrentPos ++;
|
||
}
|
||
|
||
if (CurrentString)
|
||
{
|
||
fIsSubstring = DoesThisProcessCmdLineStartWithThisString(
|
||
CommandLine, CurrentString);
|
||
if (fIsSubstring)
|
||
{
|
||
*fThisProcessIsException = TRUE;
|
||
goto CleanupAndReturn;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
|
||
Retries --;
|
||
}
|
||
|
||
CleanupAndReturn:
|
||
if (Buffer)
|
||
delete Buffer;
|
||
if (Retries == 0)
|
||
RegStatus = RPC_S_INTERNAL_ERROR;
|
||
return RegStatus;
|
||
}
|
||
|
||
RPC_STATUS ReadPolicySettings(void)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Reads the policy settings for RPC and sets the appropriate global
|
||
variables.
|
||
|
||
Arguments:
|
||
|
||
void
|
||
|
||
Return Value:
|
||
|
||
RPC_S_OK or RPC_S_* error
|
||
|
||
--*/
|
||
{
|
||
HKEY RegistryKey;
|
||
DWORD RegStatus;
|
||
DWORD Result;
|
||
DWORD Type;
|
||
DWORD DwordSize = sizeof(DWORD);
|
||
BOOL ThisProcessIsException;
|
||
|
||
RegStatus = RegOpenKeyExW(
|
||
HKEY_LOCAL_MACHINE,
|
||
(LPWSTR) RPC_POLICY_SETTINGS,
|
||
0L, //Reserved
|
||
KEY_READ,
|
||
&RegistryKey
|
||
);
|
||
|
||
if ( RegStatus != ERROR_SUCCESS )
|
||
{
|
||
if (RegStatus == ERROR_FILE_NOT_FOUND)
|
||
{
|
||
SetAutoPolicySettings(sipvAuto2);
|
||
return RPC_S_OK;
|
||
}
|
||
return RPC_S_OUT_OF_MEMORY;
|
||
}
|
||
|
||
RegStatus = RegQueryValueExW(
|
||
RegistryKey,
|
||
L"StateInformation",
|
||
0,
|
||
&Type,
|
||
(LPBYTE) &Result,
|
||
&DwordSize
|
||
);
|
||
|
||
if ( RegStatus != ERROR_SUCCESS )
|
||
{
|
||
if (RegStatus == ERROR_FILE_NOT_FOUND)
|
||
{
|
||
SetAutoPolicySettings(sipvAuto2);
|
||
RegStatus = RPC_S_OK;
|
||
}
|
||
else
|
||
{
|
||
RegStatus = RPC_S_OUT_OF_MEMORY;
|
||
goto CleanupAndReturn;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
|
||
if (Type != REG_DWORD)
|
||
{
|
||
RegStatus = RPC_S_INTERNAL_ERROR;
|
||
goto CleanupAndReturn;
|
||
}
|
||
|
||
ASSERT(RegStatus == RPC_S_OK);
|
||
|
||
switch (Result)
|
||
{
|
||
case sipvNone:
|
||
// nothing to do - the client/server DebugInfoEnabled values
|
||
// are off by default
|
||
break;
|
||
|
||
case sipvAuto1:
|
||
case sipvAuto2:
|
||
SetAutoPolicySettings((StateInformationPolicyValues)Result);
|
||
break;
|
||
|
||
case sipvServer:
|
||
g_fServerSideDebugInfoEnabled = TRUE;
|
||
break;
|
||
|
||
case sipvFull:
|
||
g_fServerSideDebugInfoEnabled = TRUE;
|
||
g_fClientSideDebugInfoEnabled = TRUE;
|
||
break;
|
||
|
||
default:
|
||
RegStatus = RPC_S_INTERNAL_ERROR;
|
||
goto CleanupAndReturn;
|
||
}
|
||
|
||
}
|
||
|
||
RegStatus = RegQueryValueExW(
|
||
RegistryKey,
|
||
L"ExtErrorInformation",
|
||
0,
|
||
&Type,
|
||
(LPBYTE) &Result,
|
||
&DwordSize
|
||
);
|
||
|
||
if ( RegStatus != ERROR_SUCCESS )
|
||
{
|
||
if (RegStatus == ERROR_FILE_NOT_FOUND)
|
||
{
|
||
RegStatus = RPC_S_OK;
|
||
}
|
||
else
|
||
{
|
||
RegStatus = RPC_S_OUT_OF_MEMORY;
|
||
goto CleanupAndReturn;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
|
||
if (Type != REG_DWORD)
|
||
{
|
||
RegStatus = RPC_S_INTERNAL_ERROR;
|
||
goto CleanupAndReturn;
|
||
}
|
||
|
||
ASSERT(RegStatus == RPC_S_OK);
|
||
|
||
switch (Result)
|
||
{
|
||
case eeipvOff:
|
||
// nothing to do - the g_fSendEEInfo is already false
|
||
break;
|
||
|
||
case eeipvOnWithExceptions:
|
||
RegStatus = IsThisProcessAnException(RegistryKey,
|
||
&ThisProcessIsException);
|
||
if ((RegStatus != RPC_S_OK) || (ThisProcessIsException == FALSE))
|
||
g_fSendEEInfo = TRUE;
|
||
break;
|
||
|
||
case eeipvOffWithExceptions:
|
||
RegStatus = IsThisProcessAnException(RegistryKey,
|
||
&ThisProcessIsException);
|
||
if ((RegStatus == RPC_S_OK) && (ThisProcessIsException == TRUE))
|
||
g_fSendEEInfo = TRUE;
|
||
break;
|
||
|
||
case eeipvOn:
|
||
g_fSendEEInfo = TRUE;
|
||
break;
|
||
|
||
default:
|
||
RegStatus = RPC_S_INTERNAL_ERROR;
|
||
goto CleanupAndReturn;
|
||
}
|
||
}
|
||
|
||
CleanupAndReturn:
|
||
RegCloseKey(RegistryKey);
|
||
return RegStatus;
|
||
}
|
||
|
||
RPCRTAPI
|
||
RPC_STATUS
|
||
RPC_ENTRY
|
||
I_RpcSystemFunction001 (
|
||
IN SystemFunction001Commands FunctionCode,
|
||
IN void *InData,
|
||
OUT void *OutData
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Test hook.
|
||
|
||
Arguments:
|
||
|
||
FunctionCode - which test function to perform
|
||
|
||
InData - input data from the test function
|
||
|
||
OutData - output data from the test function
|
||
|
||
Return Value:
|
||
|
||
RPC_S_OK or RPC_S_* error
|
||
|
||
--*/
|
||
{
|
||
THREAD *Thread;
|
||
|
||
InitializeIfNecessary();
|
||
|
||
Thread = ThreadSelf();
|
||
if (!Thread)
|
||
return RPC_S_OUT_OF_MEMORY;
|
||
|
||
RpcpPurgeEEInfoFromThreadIfNecessary(Thread);
|
||
|
||
switch (FunctionCode)
|
||
{
|
||
case sf001cHttpSetInChannelTarget:
|
||
case sf001cHttpSetOutChannelTarget:
|
||
return HTTP2TestHook (FunctionCode,
|
||
InData,
|
||
OutData
|
||
);
|
||
break;
|
||
|
||
default:
|
||
return RPC_S_CANNOT_SUPPORT;
|
||
}
|
||
|
||
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
|
||
|
||
|
||
|
||
typedef struct {
|
||
RPC_STATUS RpcStatus;
|
||
long NtStatus;
|
||
} STATUS_MAPPING;
|
||
|
||
static const STATUS_MAPPING StatusMap[] =
|
||
{
|
||
{ RPC_S_OK, STATUS_SUCCESS },
|
||
{ 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_CANCELLED, RPC_NT_CALL_CANCELLED },
|
||
{ 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 },
|
||
{ RPC_S_INVALID_ASYNC_HANDLE, RPC_NT_INVALID_ASYNC_HANDLE },
|
||
{ RPC_S_INVALID_ASYNC_CALL, RPC_NT_INVALID_ASYNC_CALL },
|
||
{ RPC_X_PIPE_CLOSED, RPC_NT_PIPE_CLOSED },
|
||
{ RPC_X_PIPE_EMPTY, RPC_NT_PIPE_EMPTY },
|
||
{ RPC_X_PIPE_DISCIPLINE_ERROR, RPC_NT_PIPE_DISCIPLINE_ERROR }
|
||
};
|
||
|
||
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);
|
||
}
|