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.

425 lines
11 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. smutil.c
  5. Abstract:
  6. Session Manager Utility Functions
  7. Author:
  8. Mark Lucovsky (markl) 04-Oct-1989
  9. Revision History:
  10. --*/
  11. #include "smsrvp.h"
  12. NTSTATUS
  13. SmpSaveRegistryValue(
  14. IN OUT PLIST_ENTRY ListHead,
  15. IN PWSTR Name,
  16. IN PWSTR Value OPTIONAL,
  17. IN BOOLEAN CheckForDuplicate
  18. )
  19. {
  20. PLIST_ENTRY Next;
  21. PSMP_REGISTRY_VALUE p;
  22. UNICODE_STRING UnicodeName;
  23. UNICODE_STRING UnicodeValue;
  24. ANSI_STRING AnsiString;
  25. RtlInitUnicodeString( &UnicodeName, Name );
  26. RtlInitUnicodeString( &UnicodeValue, Value );
  27. if (CheckForDuplicate) {
  28. Next = ListHead->Flink;
  29. p = NULL;
  30. while ( Next != ListHead ) {
  31. p = CONTAINING_RECORD( Next,
  32. SMP_REGISTRY_VALUE,
  33. Entry
  34. );
  35. if (!RtlCompareUnicodeString( &p->Name, &UnicodeName, TRUE )) {
  36. if ((!ARGUMENT_PRESENT( Value ) && p->Value.Buffer == NULL) ||
  37. (ARGUMENT_PRESENT( Value ) &&
  38. !RtlCompareUnicodeString( &p->Value, &UnicodeValue, TRUE )
  39. )
  40. ) {
  41. return( STATUS_OBJECT_NAME_EXISTS );
  42. }
  43. break;
  44. }
  45. Next = Next->Flink;
  46. p = NULL;
  47. }
  48. }
  49. else {
  50. p = NULL;
  51. }
  52. if (p == NULL) {
  53. p = RtlAllocateHeap( RtlProcessHeap(), MAKE_TAG( INIT_TAG ), sizeof( *p ) + UnicodeName.MaximumLength );
  54. if (p == NULL) {
  55. return( STATUS_NO_MEMORY );
  56. }
  57. InitializeListHead( &p->Entry );
  58. p->Name.Buffer = (PWSTR)(p+1);
  59. p->Name.Length = UnicodeName.Length;
  60. p->Name.MaximumLength = UnicodeName.MaximumLength;
  61. RtlMoveMemory( p->Name.Buffer,
  62. UnicodeName.Buffer,
  63. UnicodeName.MaximumLength
  64. );
  65. p->Value.Buffer = NULL;
  66. InsertTailList( ListHead, &p->Entry );
  67. }
  68. if (p->Value.Buffer != NULL) {
  69. RtlFreeHeap( RtlProcessHeap(), 0, p->Value.Buffer );
  70. }
  71. if (ARGUMENT_PRESENT( Value )) {
  72. p->Value.Buffer = (PWSTR)RtlAllocateHeap( RtlProcessHeap(), MAKE_TAG( INIT_TAG ),
  73. UnicodeValue.MaximumLength
  74. );
  75. if (p->Value.Buffer == NULL) {
  76. RemoveEntryList( &p->Entry );
  77. RtlFreeHeap( RtlProcessHeap(), 0, p );
  78. return( STATUS_NO_MEMORY );
  79. }
  80. p->Value.Length = UnicodeValue.Length;
  81. p->Value.MaximumLength = UnicodeValue.MaximumLength;
  82. RtlMoveMemory( p->Value.Buffer,
  83. UnicodeValue.Buffer,
  84. UnicodeValue.MaximumLength
  85. );
  86. p->AnsiValue = (LPSTR)RtlAllocateHeap( RtlProcessHeap(),
  87. MAKE_TAG( INIT_TAG ),
  88. (UnicodeValue.Length / sizeof( WCHAR )) + 1
  89. );
  90. if (p->AnsiValue == NULL) {
  91. RtlFreeHeap( RtlProcessHeap(), 0, p->Value.Buffer );
  92. RemoveEntryList( &p->Entry );
  93. RtlFreeHeap( RtlProcessHeap(), 0, p );
  94. return( STATUS_NO_MEMORY );
  95. }
  96. AnsiString.Buffer = p->AnsiValue;
  97. AnsiString.Length = 0;
  98. AnsiString.MaximumLength = (UnicodeValue.Length / sizeof( WCHAR )) + 1;
  99. RtlUnicodeStringToAnsiString( &AnsiString, &UnicodeValue, FALSE );
  100. }
  101. else {
  102. RtlInitUnicodeString( &p->Value, NULL );
  103. }
  104. return( STATUS_SUCCESS );
  105. }
  106. PSMP_REGISTRY_VALUE
  107. SmpFindRegistryValue(
  108. IN PLIST_ENTRY ListHead,
  109. IN PWSTR Name
  110. )
  111. {
  112. PLIST_ENTRY Next;
  113. PSMP_REGISTRY_VALUE p;
  114. UNICODE_STRING UnicodeName;
  115. RtlInitUnicodeString( &UnicodeName, Name );
  116. Next = ListHead->Flink;
  117. while ( Next != ListHead ) {
  118. p = CONTAINING_RECORD( Next,
  119. SMP_REGISTRY_VALUE,
  120. Entry
  121. );
  122. if (!RtlCompareUnicodeString( &p->Name, &UnicodeName, TRUE )) {
  123. return( p );
  124. }
  125. Next = Next->Flink;
  126. }
  127. return( NULL );
  128. }
  129. typedef struct _SMP_ACQUIRE_STATE {
  130. HANDLE Token;
  131. PTOKEN_PRIVILEGES OldPrivileges;
  132. PTOKEN_PRIVILEGES NewPrivileges;
  133. UCHAR OldPrivBuffer[ 1024 ];
  134. } SMP_ACQUIRE_STATE, *PSMP_ACQUIRE_STATE;
  135. NTSTATUS
  136. SmpAcquirePrivilege(
  137. ULONG Privilege,
  138. PVOID *ReturnedState
  139. )
  140. {
  141. PSMP_ACQUIRE_STATE State;
  142. ULONG cbNeeded;
  143. LUID LuidPrivilege;
  144. NTSTATUS Status;
  145. //
  146. // Make sure we have access to adjust and to get the old token privileges.
  147. //
  148. *ReturnedState = NULL;
  149. State = RtlAllocateHeap( RtlProcessHeap(),
  150. MAKE_TAG( INIT_TAG ),
  151. sizeof(SMP_ACQUIRE_STATE) +
  152. sizeof(TOKEN_PRIVILEGES) +
  153. (1 - ANYSIZE_ARRAY) * sizeof(LUID_AND_ATTRIBUTES)
  154. );
  155. if (State == NULL) {
  156. return STATUS_NO_MEMORY;
  157. }
  158. Status = NtOpenProcessToken(
  159. NtCurrentProcess(),
  160. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  161. &State->Token
  162. );
  163. if ( !NT_SUCCESS( Status )) {
  164. RtlFreeHeap( RtlProcessHeap(), 0, State );
  165. return Status;
  166. }
  167. State->NewPrivileges = (PTOKEN_PRIVILEGES)(State+1);
  168. State->OldPrivileges = (PTOKEN_PRIVILEGES)(State->OldPrivBuffer);
  169. //
  170. // Initialize the privilege adjustment structure.
  171. //
  172. LuidPrivilege = RtlConvertUlongToLuid(Privilege);
  173. State->NewPrivileges->PrivilegeCount = 1;
  174. State->NewPrivileges->Privileges[0].Luid = LuidPrivilege;
  175. State->NewPrivileges->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  176. //
  177. // Enable the privilege.
  178. //
  179. cbNeeded = sizeof( State->OldPrivBuffer );
  180. Status = NtAdjustPrivilegesToken( State->Token,
  181. FALSE,
  182. State->NewPrivileges,
  183. cbNeeded,
  184. State->OldPrivileges,
  185. &cbNeeded
  186. );
  187. if (Status == STATUS_BUFFER_TOO_SMALL) {
  188. State->OldPrivileges = RtlAllocateHeap( RtlProcessHeap(), MAKE_TAG( INIT_TAG ), cbNeeded );
  189. if (State->OldPrivileges == NULL) {
  190. Status = STATUS_NO_MEMORY;
  191. }
  192. else {
  193. Status = NtAdjustPrivilegesToken( State->Token,
  194. FALSE,
  195. State->NewPrivileges,
  196. cbNeeded,
  197. State->OldPrivileges,
  198. &cbNeeded
  199. );
  200. }
  201. }
  202. //
  203. // STATUS_NOT_ALL_ASSIGNED means that the privilege isn't
  204. // in the token, so we can't proceed.
  205. //
  206. // This is a warning level status, so map it to an error status.
  207. //
  208. if (Status == STATUS_NOT_ALL_ASSIGNED) {
  209. Status = STATUS_PRIVILEGE_NOT_HELD;
  210. }
  211. if (!NT_SUCCESS( Status )) {
  212. if (State->OldPrivileges != (PTOKEN_PRIVILEGES)(State->OldPrivBuffer)) {
  213. RtlFreeHeap( RtlProcessHeap(), 0, State->OldPrivileges );
  214. }
  215. NtClose( State->Token );
  216. RtlFreeHeap( RtlProcessHeap(), 0, State );
  217. return Status;
  218. }
  219. *ReturnedState = State;
  220. return STATUS_SUCCESS;
  221. }
  222. VOID
  223. SmpReleasePrivilege(
  224. PVOID StatePointer
  225. )
  226. {
  227. PSMP_ACQUIRE_STATE State = (PSMP_ACQUIRE_STATE)StatePointer;
  228. NtAdjustPrivilegesToken( State->Token,
  229. FALSE,
  230. State->OldPrivileges,
  231. 0,
  232. NULL,
  233. NULL
  234. );
  235. if (State->OldPrivileges != (PTOKEN_PRIVILEGES)(State->OldPrivBuffer)) {
  236. RtlFreeHeap( RtlProcessHeap(), 0, State->OldPrivileges );
  237. }
  238. NtClose( State->Token );
  239. RtlFreeHeap( RtlProcessHeap(), 0, State );
  240. return;
  241. }
  242. #if SMP_SHOW_REGISTRY_DATA
  243. VOID
  244. SmpDumpQuery(
  245. IN PWSTR ModId,
  246. IN PCHAR RoutineName,
  247. IN PWSTR ValueName,
  248. IN ULONG ValueType,
  249. IN PVOID ValueData,
  250. IN ULONG ValueLength
  251. )
  252. {
  253. PWSTR s;
  254. if (ValueName == NULL) {
  255. DbgPrint( "%ws: SmpConfigure%s( %ws )\n", ModId, RoutineName );
  256. return;
  257. }
  258. if (ValueData == NULL) {
  259. DbgPrint( "%ws: SmpConfigure%s( %ws, %ws NULL ValueData )\n", ModId, RoutineName, ValueName );
  260. return;
  261. }
  262. s = (PWSTR)ValueData;
  263. DbgPrint( "%ws: SmpConfigure%s( %ws, %u, (%u) ", ModId, RoutineName, ValueName, ValueType, ValueLength );
  264. if (ValueType == REG_SZ || ValueType == REG_EXPAND_SZ || ValueType == REG_MULTI_SZ) {
  265. while (*s) {
  266. if (s != (PWSTR)ValueData) {
  267. DbgPrint( ", " );
  268. }
  269. DbgPrint( "'%ws'", s );
  270. while(*s++) {
  271. }
  272. if (ValueType != REG_MULTI_SZ) {
  273. break;
  274. }
  275. }
  276. }
  277. else {
  278. DbgPrint( "*** non-string data (%08lx)", *(PULONG)ValueData );
  279. }
  280. DbgPrint( "\n" );
  281. }
  282. #endif
  283. ULONG
  284. SmpQueryNtGlobalFlag(
  285. VOID
  286. )
  287. /*++
  288. Routine Description:
  289. This function queries the registry to get the current NtGlobalFlag value.
  290. HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager:GlobalFlag
  291. Arguments:
  292. None.
  293. Return Value:
  294. Global flag value or zero.
  295. --*/
  296. {
  297. NTSTATUS Status;
  298. UNICODE_STRING KeyName;
  299. UNICODE_STRING ValueName;
  300. OBJECT_ATTRIBUTES ObjectAttributes;
  301. HANDLE Key;
  302. WCHAR ValueBuffer[VALUE_BUFFER_SIZE];
  303. PKEY_VALUE_PARTIAL_INFORMATION KeyValueInfo;
  304. ULONG ValueLength;
  305. //
  306. // Open the registry key.
  307. //
  308. KeyValueInfo = (PKEY_VALUE_PARTIAL_INFORMATION)ValueBuffer;
  309. RtlInitUnicodeString(
  310. &KeyName,
  311. L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Session Manager"
  312. );
  313. InitializeObjectAttributes(
  314. &ObjectAttributes,
  315. &KeyName,
  316. OBJ_CASE_INSENSITIVE,
  317. NULL,
  318. NULL
  319. );
  320. Status = NtOpenKey(&Key, KEY_READ, &ObjectAttributes);
  321. if (!NT_SUCCESS(Status)) {
  322. KdPrint(("SMSS: can't open session manager key: 0x%x\n", Status));
  323. return 0;
  324. }
  325. //
  326. // Query the key value.
  327. //
  328. RtlInitUnicodeString(&ValueName, L"GlobalFlag");
  329. Status = NtQueryValueKey(
  330. Key,
  331. &ValueName,
  332. KeyValuePartialInformation,
  333. (PVOID)KeyValueInfo,
  334. VALUE_BUFFER_SIZE,
  335. &ValueLength
  336. );
  337. ASSERT(ValueLength < VALUE_BUFFER_SIZE);
  338. NtClose(Key);
  339. if (!NT_SUCCESS(Status)) {
  340. KdPrint(("SMSS: can't query value key: 0x%x\n", Status));
  341. return 0;
  342. }
  343. return *((PULONG)&KeyValueInfo->Data);
  344. }