/************************************************************************* * 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 #include 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\\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;iObjRuleList, 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\\ObjectRules // Also loads all rules for DLLs listed in: // Citrix\Compatibility\Applications\\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; iData + 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; } } } }