Source code of Windows XP (NT5)
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.

361 lines
11 KiB

  1. /*************************************************************************
  2. * objrules.c
  3. *
  4. * Routines for caching registry object rules and looking up object names.
  5. *
  6. * Copyright (C) 1997-1999 Microsoft Corp.
  7. *************************************************************************/
  8. #include "precomp.h"
  9. #pragma hdrstop
  10. #include <objrules.h>
  11. #include <ntverp.h>
  12. OBJRULELIST SemaRuleList;
  13. OBJRULELIST MutexRuleList;
  14. OBJRULELIST SectionRuleList;
  15. OBJRULELIST EventRuleList;
  16. ULONG NumRuleLists;
  17. RULEINITENTRY RuleInitTab[] =
  18. {
  19. {&SemaRuleList, USER_GLOBAL_SEMAPHORES, SYSTEM_GLOBAL_SEMAPHORES},
  20. {&MutexRuleList, USER_GLOBAL_MUTEXES, SYSTEM_GLOBAL_MUTEXES},
  21. {&SectionRuleList, USER_GLOBAL_SECTIONS, SYSTEM_GLOBAL_SECTIONS},
  22. {&EventRuleList, USER_GLOBAL_EVENTS, SYSTEM_GLOBAL_EVENTS},
  23. };
  24. //*****************************************************************************
  25. // InitRuleList
  26. //
  27. // Initializes an object rule list to empty.
  28. //
  29. // Parameters:
  30. // POBJRULLIST (IN) - ptr to object rule list
  31. // Return Value:
  32. // None.
  33. //*****************************************************************************
  34. void InitRuleList(POBJRULELIST pObjRuleList)
  35. {
  36. pObjRuleList->First = (POBJRULE) NULL;
  37. pObjRuleList->Last = (POBJRULE) NULL;
  38. }
  39. //*****************************************************************************
  40. // GetMultiSzValue
  41. //
  42. // Retrieves the REG_MULTI_SZ value ValueName under key hKey.
  43. //
  44. // Parameters:
  45. // hKey The registry key
  46. // ValueName The registry value name (NULL Terminated)
  47. // pValueInfo Pointer to Pointer receiving a
  48. // PKEY_VALUE_PARTIAL_INFORMATION structure
  49. // upon successful return. This structure
  50. // contains the registry data and its length.
  51. // Return Value:
  52. // Returns TRUE if successful, otherwise FALSE.
  53. // If successful, pValueInfo is updated with a pointer to a
  54. // structure. The caller must free the structure.
  55. //*****************************************************************************
  56. BOOL GetMultiSzValue(HKEY hKey, PWSTR ValueName,
  57. PKEY_VALUE_PARTIAL_INFORMATION *pValueInfo)
  58. {
  59. PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;
  60. UNICODE_STRING UniString;
  61. ULONG BufSize;
  62. ULONG DataLen;
  63. NTSTATUS NtStatus;
  64. BOOL Retried = FALSE;
  65. // Determine the value info buffer size
  66. BufSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + MAX_PATH*sizeof(WCHAR);
  67. for (;;) {
  68. ValueInfo = RtlAllocateHeap(RtlProcessHeap(), 0, BufSize);
  69. if (ValueInfo)
  70. {
  71. RtlInitUnicodeString(&UniString, ValueName);
  72. NtStatus = NtQueryValueKey(hKey,
  73. &UniString,
  74. KeyValuePartialInformation,
  75. ValueInfo,
  76. BufSize,
  77. &DataLen);
  78. if (NT_SUCCESS(NtStatus) && (REG_MULTI_SZ == ValueInfo->Type)) {
  79. *pValueInfo = ValueInfo;
  80. return(TRUE);
  81. }
  82. if (!Retried && (NtStatus == STATUS_BUFFER_OVERFLOW)) {
  83. BufSize = DataLen;
  84. RtlFreeHeap(RtlProcessHeap(), 0, ValueInfo);
  85. Retried = TRUE;
  86. continue;
  87. }
  88. // Key not present or other type of error
  89. RtlFreeHeap(RtlProcessHeap(), 0, ValueInfo);
  90. return(FALSE);
  91. }
  92. else
  93. {
  94. return(FALSE);
  95. }
  96. }
  97. }
  98. //*****************************************************************************
  99. // AddRule
  100. //
  101. // Adds an object rule a rule list.
  102. //
  103. // Parameters:
  104. // RuleList The rule list.
  105. // ObjName The name of the object.
  106. // SystemGlobalRule If true, the object is to be SYSTEM_GLOBAL.
  107. // Return Value:
  108. // None.
  109. //*****************************************************************************
  110. void AddRule(POBJRULELIST RuleList, PWSTR ObjName, BOOL SystemGlobalRule)
  111. {
  112. ULONG AllocSize;
  113. ULONG Length;
  114. POBJRULE pObjRule;
  115. #if DBG
  116. DbgPrint("Adding Rule: %ws SystemGlobal: %d\n",ObjName,SystemGlobalRule);
  117. #endif
  118. Length = wcslen(ObjName);
  119. AllocSize = sizeof(OBJRULE) + (Length + 1) * sizeof(WCHAR);
  120. if (pObjRule = RtlAllocateHeap(RtlProcessHeap(), 0, AllocSize)) {
  121. wcscpy(pObjRule->ObjName, ObjName);
  122. pObjRule->SystemGlobal = SystemGlobalRule;
  123. if (ObjName[Length-1] == L'*') {
  124. pObjRule->WildCard = TRUE;
  125. pObjRule->MatchLen = Length - 1;
  126. // Insert rule at the end of the list
  127. pObjRule->Next = NULL;
  128. if (RuleList->First == NULL) {
  129. RuleList->First = RuleList->Last = pObjRule;
  130. } else {
  131. RuleList->Last->Next = pObjRule;
  132. RuleList->Last = pObjRule;
  133. }
  134. } else {
  135. pObjRule->WildCard = FALSE;
  136. // Insert rule at the begining
  137. if (RuleList->First == NULL) {
  138. RuleList->First = RuleList->Last = pObjRule;
  139. pObjRule->Next = NULL;
  140. } else {
  141. pObjRule->Next = RuleList->First;
  142. RuleList->First = pObjRule;
  143. }
  144. }
  145. }
  146. }
  147. //*****************************************************************************
  148. // LoadRule
  149. //
  150. // Caches all rules for a given registry value (REG_MULTI_SZ).
  151. //
  152. // Parameters:
  153. // RuleList The rule list.
  154. // hKey The registry key.
  155. // ValueName The name of theregistry value.
  156. // SystemGlobalRule If true, the object is to be SYSTEM_GLOBAL.
  157. // Return Value:
  158. // None.
  159. //*****************************************************************************
  160. void LoadRule (POBJRULELIST RuleList, HKEY hKey,
  161. PWSTR ValueName, BOOL SystemGlobalRule)
  162. {
  163. PKEY_VALUE_PARTIAL_INFORMATION ValueInfo = NULL;
  164. PWSTR Token;
  165. PWSTR EndData;
  166. if (!GetMultiSzValue(hKey,ValueName,&ValueInfo)) {
  167. return;
  168. }
  169. EndData = (PWSTR) (ValueInfo->Data + ValueInfo->DataLength);
  170. for (Token = (PWSTR)ValueInfo->Data;
  171. (*Token && (Token < EndData));
  172. Token++) {
  173. AddRule(RuleList, Token, SystemGlobalRule);
  174. while (*Token) {
  175. Token++;
  176. }
  177. }
  178. RtlFreeHeap(RtlProcessHeap(), 0, ValueInfo);
  179. }
  180. //*****************************************************************************
  181. // LoadRules
  182. //
  183. // Caches all rules for in an OBJECTRULES directory.
  184. // (e.g. Citrix\Compatibility\Applications\<APPNAME>\ObjectRules).
  185. //
  186. // Parameters:
  187. // hKey The registry key of the ObjectRules directory.
  188. // Return Value:
  189. // None.
  190. //*****************************************************************************
  191. void LoadRules (HANDLE hKey)
  192. {
  193. ULONG i;
  194. PRULEINITENTRY pTab;
  195. for (i=0, pTab=RuleInitTab;i<NumRuleLists;i++,pTab++) {
  196. LoadRule(pTab->ObjRuleList, hKey, pTab->UserGlobalValue, FALSE);
  197. LoadRule(pTab->ObjRuleList, hKey, pTab->SystemGlobalValue, TRUE);
  198. }
  199. }
  200. #define BuildObjRulePath(BasePath,ModName) \
  201. { \
  202. wcscpy(KeyName,BasePath ); \
  203. wcscat(KeyName,ModName); \
  204. wcscat(KeyName,L"\\"); \
  205. wcscat(KeyName,TERMSRV_COMPAT_OBJRULES); \
  206. RtlInitUnicodeString(&UniString, KeyName); \
  207. InitializeObjectAttributes(&ObjectAttributes, \
  208. &UniString, \
  209. OBJ_CASE_INSENSITIVE, \
  210. NULL, \
  211. NULL); \
  212. }
  213. //*****************************************************************************
  214. // CtxInitObjRuleCache
  215. //
  216. // Loads all object rules for a given application. Called at DLL process
  217. // attach time.
  218. // Rules are in Citrix\Compatibility\Applications\<APPNAME>\ObjectRules
  219. // Also loads all rules for DLLs listed in:
  220. // Citrix\Compatibility\Applications\<APPNAME>\ObjectRules\Dlls
  221. // Parameters:
  222. // None.
  223. // Return Value:
  224. // None.
  225. //*****************************************************************************
  226. void CtxInitObjRuleCache(void)
  227. {
  228. WCHAR ModName[MAX_PATH+1];
  229. WCHAR KeyName[sizeof(TERMSRV_COMPAT_APP)/sizeof(WCHAR)+
  230. sizeof(TERMSRV_COMPAT_OBJRULES)/sizeof(WCHAR)+MAX_PATH+2];
  231. UNICODE_STRING UniString;
  232. PWSTR DllName;
  233. PWSTR EndData;
  234. OBJECT_ATTRIBUTES ObjectAttributes;
  235. PKEY_VALUE_PARTIAL_INFORMATION ValueInfo = NULL;
  236. HKEY hKey = 0;
  237. DWORD AppType;
  238. ULONG i;
  239. // Initialize list to empty
  240. NumRuleLists = sizeof(RuleInitTab) / sizeof(RULEINITENTRY);
  241. for (i=0; i<NumRuleLists ;i++ ) {
  242. InitRuleList(RuleInitTab[i].ObjRuleList);
  243. }
  244. // Get the module name
  245. if (!GetAppTypeAndModName(&AppType,ModName, sizeof(ModName))) {
  246. return;
  247. }
  248. // Determine of the ObjRules Key exists for this app
  249. BuildObjRulePath(TERMSRV_COMPAT_APP,ModName)
  250. if (!NT_SUCCESS(NtOpenKey(&hKey, KEY_READ, &ObjectAttributes))) {
  251. return;
  252. }
  253. LoadRules(hKey);
  254. if (!GetMultiSzValue(hKey,TERMSRV_COMPAT_DLLRULES,&ValueInfo)) {
  255. CloseHandle(hKey);
  256. return;
  257. }
  258. CloseHandle(hKey);
  259. // Load the DLL Rules
  260. EndData = (PWSTR) (ValueInfo->Data + ValueInfo->DataLength);
  261. for(DllName = (PWSTR) ValueInfo->Data;
  262. (*DllName && (DllName < EndData));
  263. DllName++) {
  264. BuildObjRulePath(TERMSRV_COMPAT_DLLS, DllName)
  265. if (NT_SUCCESS(NtOpenKey(&hKey, KEY_READ, &ObjectAttributes))) {
  266. LoadRules(hKey);
  267. CloseHandle(hKey);
  268. }
  269. while (*DllName) {
  270. DllName++;
  271. }
  272. }
  273. RtlFreeHeap(RtlProcessHeap(), 0, ValueInfo);
  274. }
  275. //*****************************************************************************
  276. // CtxLookupObjectRule
  277. //
  278. // Searches for an object rule for the named object. If a rule is found,
  279. // the object attributes are modifed to reflect the desired setting of
  280. // USER_GLOBAL or SYSTEM_GLOBAL. If no rule is found, the object
  281. // atributes are unmodified.
  282. //
  283. // Parameters:
  284. // RuleList The rule list to search (based on object type)
  285. // ObjName The name of the object.
  286. // ObjAttributes The object attribute structure.
  287. // None.
  288. // Return Value:
  289. // None.
  290. //*****************************************************************************
  291. void CtxLookupObjectRule(POBJRULELIST RuleList, LPCWSTR ObjName, LPWSTR ObjNameExt)
  292. {
  293. POBJRULE ObjRule;
  294. #define ApplyRule \
  295. { \
  296. if (ObjRule->SystemGlobal) { \
  297. wcscpy(ObjNameExt,L"Global\\"); \
  298. } else { \
  299. wcscpy(ObjNameExt,L"Local\\"); \
  300. } \
  301. }
  302. for (ObjRule = RuleList->First; ObjRule; ObjRule = ObjRule->Next) {
  303. if (!ObjRule->WildCard) {
  304. if (!_wcsicmp(ObjName, ObjRule->ObjName)) {
  305. #if DBG
  306. DbgPrint("Object rule found for %ws System Global: %d\n",
  307. ObjName, ObjRule->SystemGlobal);
  308. #endif
  309. ApplyRule
  310. return;
  311. }
  312. } else {
  313. if (!_wcsnicmp(ObjName, ObjRule->ObjName, ObjRule->MatchLen)) {
  314. #if DBG
  315. DbgPrint("Object rule found for %ws System Global: %d\n",
  316. ObjName, ObjRule->SystemGlobal);
  317. #endif
  318. ApplyRule
  319. return;
  320. }
  321. }
  322. }
  323. }