362 lines
11 KiB
C
362 lines
11 KiB
C
/*************************************************************************
|
|
* objrules.c
|
|
*
|
|
* Routines for caching registry object rules and looking up object names.
|
|
*
|
|
* Copyright (C) 1997-1999 Microsoft Corp.
|
|
*************************************************************************/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
#include <objrules.h>
|
|
#include <ntverp.h>
|
|
|
|
OBJRULELIST SemaRuleList;
|
|
OBJRULELIST MutexRuleList;
|
|
OBJRULELIST SectionRuleList;
|
|
OBJRULELIST EventRuleList;
|
|
ULONG NumRuleLists;
|
|
|
|
RULEINITENTRY RuleInitTab[] =
|
|
{
|
|
{&SemaRuleList, USER_GLOBAL_SEMAPHORES, SYSTEM_GLOBAL_SEMAPHORES},
|
|
{&MutexRuleList, USER_GLOBAL_MUTEXES, SYSTEM_GLOBAL_MUTEXES},
|
|
{&SectionRuleList, USER_GLOBAL_SECTIONS, SYSTEM_GLOBAL_SECTIONS},
|
|
{&EventRuleList, USER_GLOBAL_EVENTS, SYSTEM_GLOBAL_EVENTS},
|
|
};
|
|
|
|
//*****************************************************************************
|
|
// InitRuleList
|
|
//
|
|
// Initializes an object rule list to empty.
|
|
//
|
|
// Parameters:
|
|
// POBJRULLIST (IN) - ptr to object rule list
|
|
// Return Value:
|
|
// None.
|
|
//*****************************************************************************
|
|
void InitRuleList(POBJRULELIST pObjRuleList)
|
|
{
|
|
pObjRuleList->First = (POBJRULE) NULL;
|
|
pObjRuleList->Last = (POBJRULE) NULL;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
// GetMultiSzValue
|
|
//
|
|
// Retrieves the REG_MULTI_SZ value ValueName under key hKey.
|
|
//
|
|
// Parameters:
|
|
// hKey The registry key
|
|
// ValueName The registry value name (NULL Terminated)
|
|
// pValueInfo Pointer to Pointer receiving a
|
|
// PKEY_VALUE_PARTIAL_INFORMATION structure
|
|
// upon successful return. This structure
|
|
// contains the registry data and its length.
|
|
// Return Value:
|
|
// Returns TRUE if successful, otherwise FALSE.
|
|
// If successful, pValueInfo is updated with a pointer to a
|
|
// structure. The caller must free the structure.
|
|
//*****************************************************************************
|
|
|
|
BOOL GetMultiSzValue(HKEY hKey, PWSTR ValueName,
|
|
PKEY_VALUE_PARTIAL_INFORMATION *pValueInfo)
|
|
{
|
|
PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;
|
|
UNICODE_STRING UniString;
|
|
ULONG BufSize;
|
|
ULONG DataLen;
|
|
NTSTATUS NtStatus;
|
|
BOOL Retried = FALSE;
|
|
|
|
// Determine the value info buffer size
|
|
BufSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + MAX_PATH*sizeof(WCHAR);
|
|
|
|
for (;;) {
|
|
ValueInfo = RtlAllocateHeap(RtlProcessHeap(), 0, BufSize);
|
|
|
|
if (ValueInfo)
|
|
{
|
|
RtlInitUnicodeString(&UniString, ValueName);
|
|
NtStatus = NtQueryValueKey(hKey,
|
|
&UniString,
|
|
KeyValuePartialInformation,
|
|
ValueInfo,
|
|
BufSize,
|
|
&DataLen);
|
|
|
|
if (NT_SUCCESS(NtStatus) && (REG_MULTI_SZ == ValueInfo->Type)) {
|
|
*pValueInfo = ValueInfo;
|
|
return(TRUE);
|
|
}
|
|
|
|
if (!Retried && (NtStatus == STATUS_BUFFER_OVERFLOW)) {
|
|
BufSize = DataLen;
|
|
RtlFreeHeap(RtlProcessHeap(), 0, ValueInfo);
|
|
Retried = TRUE;
|
|
continue;
|
|
}
|
|
// Key not present or other type of error
|
|
RtlFreeHeap(RtlProcessHeap(), 0, ValueInfo);
|
|
return(FALSE);
|
|
}
|
|
else
|
|
{
|
|
return(FALSE);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
//*****************************************************************************
|
|
// AddRule
|
|
//
|
|
// Adds an object rule a rule list.
|
|
//
|
|
// Parameters:
|
|
// RuleList The rule list.
|
|
// ObjName The name of the object.
|
|
// SystemGlobalRule If true, the object is to be SYSTEM_GLOBAL.
|
|
// Return Value:
|
|
// None.
|
|
//*****************************************************************************
|
|
|
|
void AddRule(POBJRULELIST RuleList, PWSTR ObjName, BOOL SystemGlobalRule)
|
|
{
|
|
ULONG AllocSize;
|
|
ULONG Length;
|
|
POBJRULE pObjRule;
|
|
|
|
#if DBG
|
|
DbgPrint("Adding Rule: %ws SystemGlobal: %d\n",ObjName,SystemGlobalRule);
|
|
#endif
|
|
Length = wcslen(ObjName);
|
|
AllocSize = sizeof(OBJRULE) + (Length + 1) * sizeof(WCHAR);
|
|
if (pObjRule = RtlAllocateHeap(RtlProcessHeap(), 0, AllocSize)) {
|
|
wcscpy(pObjRule->ObjName, ObjName);
|
|
pObjRule->SystemGlobal = SystemGlobalRule;
|
|
if (ObjName[Length-1] == L'*') {
|
|
pObjRule->WildCard = TRUE;
|
|
pObjRule->MatchLen = Length - 1;
|
|
// Insert rule at the end of the list
|
|
pObjRule->Next = NULL;
|
|
if (RuleList->First == NULL) {
|
|
RuleList->First = RuleList->Last = pObjRule;
|
|
} else {
|
|
RuleList->Last->Next = pObjRule;
|
|
RuleList->Last = pObjRule;
|
|
}
|
|
} else {
|
|
pObjRule->WildCard = FALSE;
|
|
// Insert rule at the begining
|
|
if (RuleList->First == NULL) {
|
|
RuleList->First = RuleList->Last = pObjRule;
|
|
pObjRule->Next = NULL;
|
|
} else {
|
|
pObjRule->Next = RuleList->First;
|
|
RuleList->First = pObjRule;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//*****************************************************************************
|
|
// LoadRule
|
|
//
|
|
// Caches all rules for a given registry value (REG_MULTI_SZ).
|
|
//
|
|
// Parameters:
|
|
// RuleList The rule list.
|
|
// hKey The registry key.
|
|
// ValueName The name of theregistry value.
|
|
// SystemGlobalRule If true, the object is to be SYSTEM_GLOBAL.
|
|
// Return Value:
|
|
// None.
|
|
//*****************************************************************************
|
|
|
|
void LoadRule (POBJRULELIST RuleList, HKEY hKey,
|
|
PWSTR ValueName, BOOL SystemGlobalRule)
|
|
{
|
|
PKEY_VALUE_PARTIAL_INFORMATION ValueInfo = NULL;
|
|
PWSTR Token;
|
|
PWSTR EndData;
|
|
|
|
if (!GetMultiSzValue(hKey,ValueName,&ValueInfo)) {
|
|
return;
|
|
}
|
|
EndData = (PWSTR) (ValueInfo->Data + ValueInfo->DataLength);
|
|
for (Token = (PWSTR)ValueInfo->Data;
|
|
(*Token && (Token < EndData));
|
|
Token++) {
|
|
AddRule(RuleList, Token, SystemGlobalRule);
|
|
while (*Token) {
|
|
Token++;
|
|
}
|
|
}
|
|
|
|
RtlFreeHeap(RtlProcessHeap(), 0, ValueInfo);
|
|
}
|
|
|
|
//*****************************************************************************
|
|
// LoadRules
|
|
//
|
|
// Caches all rules for in an OBJECTRULES directory.
|
|
// (e.g. Citrix\Compatibility\Applications\<APPNAME>\ObjectRules).
|
|
//
|
|
// Parameters:
|
|
// hKey The registry key of the ObjectRules directory.
|
|
// Return Value:
|
|
// None.
|
|
//*****************************************************************************
|
|
|
|
void LoadRules (HANDLE hKey)
|
|
{
|
|
ULONG i;
|
|
PRULEINITENTRY pTab;
|
|
|
|
for (i=0, pTab=RuleInitTab;i<NumRuleLists;i++,pTab++) {
|
|
LoadRule(pTab->ObjRuleList, hKey, pTab->UserGlobalValue, FALSE);
|
|
LoadRule(pTab->ObjRuleList, hKey, pTab->SystemGlobalValue, TRUE);
|
|
}
|
|
}
|
|
|
|
#define BuildObjRulePath(BasePath,ModName) \
|
|
{ \
|
|
wcscpy(KeyName,BasePath ); \
|
|
wcscat(KeyName,ModName); \
|
|
wcscat(KeyName,L"\\"); \
|
|
wcscat(KeyName,TERMSRV_COMPAT_OBJRULES); \
|
|
RtlInitUnicodeString(&UniString, KeyName); \
|
|
InitializeObjectAttributes(&ObjectAttributes, \
|
|
&UniString, \
|
|
OBJ_CASE_INSENSITIVE, \
|
|
NULL, \
|
|
NULL); \
|
|
}
|
|
|
|
//*****************************************************************************
|
|
// CtxInitObjRuleCache
|
|
//
|
|
// Loads all object rules for a given application. Called at DLL process
|
|
// attach time.
|
|
// Rules are in Citrix\Compatibility\Applications\<APPNAME>\ObjectRules
|
|
// Also loads all rules for DLLs listed in:
|
|
// Citrix\Compatibility\Applications\<APPNAME>\ObjectRules\Dlls
|
|
// Parameters:
|
|
// None.
|
|
// Return Value:
|
|
// None.
|
|
//*****************************************************************************
|
|
|
|
void CtxInitObjRuleCache(void)
|
|
{
|
|
WCHAR ModName[MAX_PATH+1];
|
|
WCHAR KeyName[sizeof(TERMSRV_COMPAT_APP)/sizeof(WCHAR)+
|
|
sizeof(TERMSRV_COMPAT_OBJRULES)/sizeof(WCHAR)+MAX_PATH+2];
|
|
UNICODE_STRING UniString;
|
|
PWSTR DllName;
|
|
PWSTR EndData;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
PKEY_VALUE_PARTIAL_INFORMATION ValueInfo = NULL;
|
|
HKEY hKey = 0;
|
|
DWORD AppType;
|
|
ULONG i;
|
|
|
|
// Initialize list to empty
|
|
NumRuleLists = sizeof(RuleInitTab) / sizeof(RULEINITENTRY);
|
|
for (i=0; i<NumRuleLists ;i++ ) {
|
|
InitRuleList(RuleInitTab[i].ObjRuleList);
|
|
}
|
|
|
|
// Get the module name
|
|
if (!GetAppTypeAndModName(&AppType,ModName, sizeof(ModName))) {
|
|
return;
|
|
}
|
|
|
|
// Determine of the ObjRules Key exists for this app
|
|
BuildObjRulePath(TERMSRV_COMPAT_APP,ModName)
|
|
if (!NT_SUCCESS(NtOpenKey(&hKey, KEY_READ, &ObjectAttributes))) {
|
|
return;
|
|
}
|
|
LoadRules(hKey);
|
|
|
|
|
|
if (!GetMultiSzValue(hKey,TERMSRV_COMPAT_DLLRULES,&ValueInfo)) {
|
|
CloseHandle(hKey);
|
|
return;
|
|
}
|
|
|
|
CloseHandle(hKey);
|
|
|
|
// Load the DLL Rules
|
|
EndData = (PWSTR) (ValueInfo->Data + ValueInfo->DataLength);
|
|
|
|
for(DllName = (PWSTR) ValueInfo->Data;
|
|
(*DllName && (DllName < EndData));
|
|
DllName++) {
|
|
BuildObjRulePath(TERMSRV_COMPAT_DLLS, DllName)
|
|
if (NT_SUCCESS(NtOpenKey(&hKey, KEY_READ, &ObjectAttributes))) {
|
|
LoadRules(hKey);
|
|
CloseHandle(hKey);
|
|
}
|
|
while (*DllName) {
|
|
DllName++;
|
|
}
|
|
}
|
|
|
|
RtlFreeHeap(RtlProcessHeap(), 0, ValueInfo);
|
|
}
|
|
|
|
//*****************************************************************************
|
|
// CtxLookupObjectRule
|
|
//
|
|
// Searches for an object rule for the named object. If a rule is found,
|
|
// the object attributes are modifed to reflect the desired setting of
|
|
// USER_GLOBAL or SYSTEM_GLOBAL. If no rule is found, the object
|
|
// atributes are unmodified.
|
|
//
|
|
// Parameters:
|
|
// RuleList The rule list to search (based on object type)
|
|
// ObjName The name of the object.
|
|
// ObjAttributes The object attribute structure.
|
|
// None.
|
|
// Return Value:
|
|
// None.
|
|
//*****************************************************************************
|
|
void CtxLookupObjectRule(POBJRULELIST RuleList, LPCWSTR ObjName, LPWSTR ObjNameExt)
|
|
{
|
|
POBJRULE ObjRule;
|
|
|
|
#define ApplyRule \
|
|
{ \
|
|
if (ObjRule->SystemGlobal) { \
|
|
wcscpy(ObjNameExt,L"Global\\"); \
|
|
} else { \
|
|
wcscpy(ObjNameExt,L"Local\\"); \
|
|
} \
|
|
}
|
|
|
|
for (ObjRule = RuleList->First; ObjRule; ObjRule = ObjRule->Next) {
|
|
if (!ObjRule->WildCard) {
|
|
if (!_wcsicmp(ObjName, ObjRule->ObjName)) {
|
|
#if DBG
|
|
DbgPrint("Object rule found for %ws System Global: %d\n",
|
|
ObjName, ObjRule->SystemGlobal);
|
|
#endif
|
|
ApplyRule
|
|
return;
|
|
}
|
|
} else {
|
|
if (!_wcsnicmp(ObjName, ObjRule->ObjName, ObjRule->MatchLen)) {
|
|
#if DBG
|
|
DbgPrint("Object rule found for %ws System Global: %d\n",
|
|
ObjName, ObjRule->SystemGlobal);
|
|
#endif
|
|
ApplyRule
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|