Leaked source code of windows server 2003
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.

424 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. } else {
  49. p = NULL;
  50. }
  51. if (p == NULL) {
  52. p = RtlAllocateHeap( RtlProcessHeap(), MAKE_TAG( INIT_TAG ), sizeof( *p ) + UnicodeName.MaximumLength );
  53. if (p == NULL) {
  54. return( STATUS_NO_MEMORY );
  55. }
  56. InitializeListHead( &p->Entry );
  57. p->Name.Buffer = (PWSTR)(p+1);
  58. p->Name.Length = UnicodeName.Length;
  59. p->Name.MaximumLength = UnicodeName.MaximumLength;
  60. p->AnsiValue = NULL;
  61. RtlCopyMemory( 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. RtlCopyMemory( 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. } else {
  101. RtlInitUnicodeString( &p->Value, NULL );
  102. }
  103. return( STATUS_SUCCESS );
  104. }
  105. PSMP_REGISTRY_VALUE
  106. SmpFindRegistryValue(
  107. IN PLIST_ENTRY ListHead,
  108. IN PWSTR Name
  109. )
  110. {
  111. PLIST_ENTRY Next;
  112. PSMP_REGISTRY_VALUE p;
  113. UNICODE_STRING UnicodeName;
  114. RtlInitUnicodeString( &UnicodeName, Name );
  115. Next = ListHead->Flink;
  116. while ( Next != ListHead ) {
  117. p = CONTAINING_RECORD( Next,
  118. SMP_REGISTRY_VALUE,
  119. Entry
  120. );
  121. if (!RtlCompareUnicodeString( &p->Name, &UnicodeName, TRUE )) {
  122. return( p );
  123. }
  124. Next = Next->Flink;
  125. }
  126. return( NULL );
  127. }
  128. typedef struct _SMP_ACQUIRE_STATE {
  129. HANDLE Token;
  130. PTOKEN_PRIVILEGES OldPrivileges;
  131. PTOKEN_PRIVILEGES NewPrivileges;
  132. UCHAR OldPrivBuffer[ 1024 ];
  133. } SMP_ACQUIRE_STATE, *PSMP_ACQUIRE_STATE;
  134. NTSTATUS
  135. SmpAcquirePrivilege(
  136. ULONG Privilege,
  137. PVOID *ReturnedState
  138. )
  139. {
  140. PSMP_ACQUIRE_STATE State;
  141. ULONG cbNeeded;
  142. LUID LuidPrivilege;
  143. NTSTATUS Status;
  144. //
  145. // Make sure we have access to adjust and to get the old token privileges.
  146. //
  147. *ReturnedState = NULL;
  148. State = RtlAllocateHeap( RtlProcessHeap(),
  149. MAKE_TAG( INIT_TAG ),
  150. sizeof(SMP_ACQUIRE_STATE) +
  151. sizeof(TOKEN_PRIVILEGES) +
  152. (1 - ANYSIZE_ARRAY) * sizeof(LUID_AND_ATTRIBUTES)
  153. );
  154. if (State == NULL) {
  155. return STATUS_NO_MEMORY;
  156. }
  157. Status = NtOpenProcessToken(
  158. NtCurrentProcess(),
  159. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  160. &State->Token
  161. );
  162. if ( !NT_SUCCESS( Status )) {
  163. RtlFreeHeap( RtlProcessHeap(), 0, State );
  164. return Status;
  165. }
  166. State->NewPrivileges = (PTOKEN_PRIVILEGES)(State+1);
  167. State->OldPrivileges = (PTOKEN_PRIVILEGES)(State->OldPrivBuffer);
  168. //
  169. // Initialize the privilege adjustment structure.
  170. //
  171. LuidPrivilege = RtlConvertUlongToLuid(Privilege);
  172. State->NewPrivileges->PrivilegeCount = 1;
  173. State->NewPrivileges->Privileges[0].Luid = LuidPrivilege;
  174. State->NewPrivileges->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  175. //
  176. // Enable the privilege.
  177. //
  178. cbNeeded = sizeof( State->OldPrivBuffer );
  179. Status = NtAdjustPrivilegesToken( State->Token,
  180. FALSE,
  181. State->NewPrivileges,
  182. cbNeeded,
  183. State->OldPrivileges,
  184. &cbNeeded
  185. );
  186. if (Status == STATUS_BUFFER_TOO_SMALL) {
  187. State->OldPrivileges = RtlAllocateHeap( RtlProcessHeap(), MAKE_TAG( INIT_TAG ), cbNeeded );
  188. if (State->OldPrivileges == NULL) {
  189. Status = STATUS_NO_MEMORY;
  190. }
  191. else {
  192. Status = NtAdjustPrivilegesToken( State->Token,
  193. FALSE,
  194. State->NewPrivileges,
  195. cbNeeded,
  196. State->OldPrivileges,
  197. &cbNeeded
  198. );
  199. }
  200. }
  201. //
  202. // STATUS_NOT_ALL_ASSIGNED means that the privilege isn't
  203. // in the token, so we can't proceed.
  204. //
  205. // This is a warning level status, so map it to an error status.
  206. //
  207. if (Status == STATUS_NOT_ALL_ASSIGNED) {
  208. Status = STATUS_PRIVILEGE_NOT_HELD;
  209. }
  210. if (!NT_SUCCESS( Status )) {
  211. if (State->OldPrivileges != (PTOKEN_PRIVILEGES)(State->OldPrivBuffer)) {
  212. RtlFreeHeap( RtlProcessHeap(), 0, State->OldPrivileges );
  213. }
  214. NtClose( State->Token );
  215. RtlFreeHeap( RtlProcessHeap(), 0, State );
  216. return Status;
  217. }
  218. *ReturnedState = State;
  219. return STATUS_SUCCESS;
  220. }
  221. VOID
  222. SmpReleasePrivilege(
  223. PVOID StatePointer
  224. )
  225. {
  226. PSMP_ACQUIRE_STATE State = (PSMP_ACQUIRE_STATE)StatePointer;
  227. NtAdjustPrivilegesToken( State->Token,
  228. FALSE,
  229. State->OldPrivileges,
  230. 0,
  231. NULL,
  232. NULL
  233. );
  234. if (State->OldPrivileges != (PTOKEN_PRIVILEGES)(State->OldPrivBuffer)) {
  235. RtlFreeHeap( RtlProcessHeap(), 0, State->OldPrivileges );
  236. }
  237. NtClose( State->Token );
  238. RtlFreeHeap( RtlProcessHeap(), 0, State );
  239. return;
  240. }
  241. #if SMP_SHOW_REGISTRY_DATA
  242. VOID
  243. SmpDumpQuery(
  244. IN PWSTR ModId,
  245. IN PCHAR RoutineName,
  246. IN PWSTR ValueName,
  247. IN ULONG ValueType,
  248. IN PVOID ValueData,
  249. IN ULONG ValueLength
  250. )
  251. {
  252. PWSTR s;
  253. if (ValueName == NULL) {
  254. DbgPrint( "%ws: SmpConfigure%s( %ws )\n", ModId, RoutineName );
  255. return;
  256. }
  257. if (ValueData == NULL) {
  258. DbgPrint( "%ws: SmpConfigure%s( %ws, %ws NULL ValueData )\n", ModId, RoutineName, ValueName );
  259. return;
  260. }
  261. s = (PWSTR)ValueData;
  262. DbgPrint( "%ws: SmpConfigure%s( %ws, %u, (%u) ", ModId, RoutineName, ValueName, ValueType, ValueLength );
  263. if (ValueType == REG_SZ || ValueType == REG_EXPAND_SZ || ValueType == REG_MULTI_SZ) {
  264. while (*s) {
  265. if (s != (PWSTR)ValueData) {
  266. DbgPrint( ", " );
  267. }
  268. DbgPrint( "'%ws'", s );
  269. while(*s++) {
  270. }
  271. if (ValueType != REG_MULTI_SZ) {
  272. break;
  273. }
  274. }
  275. }
  276. else {
  277. DbgPrint( "*** non-string data (%08lx)", *(PULONG)ValueData );
  278. }
  279. DbgPrint( "\n" );
  280. }
  281. #endif
  282. ULONG
  283. SmpQueryNtGlobalFlag(
  284. VOID
  285. )
  286. /*++
  287. Routine Description:
  288. This function queries the registry to get the current NtGlobalFlag value.
  289. HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager:GlobalFlag
  290. Arguments:
  291. None.
  292. Return Value:
  293. Global flag value or zero.
  294. --*/
  295. {
  296. NTSTATUS Status;
  297. UNICODE_STRING KeyName;
  298. UNICODE_STRING ValueName;
  299. OBJECT_ATTRIBUTES ObjectAttributes;
  300. HANDLE Key;
  301. UCHAR ValueBuffer[VALUE_BUFFER_SIZE];
  302. PKEY_VALUE_PARTIAL_INFORMATION KeyValueInfo;
  303. ULONG ValueLength;
  304. //
  305. // Open the registry key.
  306. //
  307. KeyValueInfo = (PKEY_VALUE_PARTIAL_INFORMATION)ValueBuffer;
  308. RtlInitUnicodeString(
  309. &KeyName,
  310. L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Session Manager"
  311. );
  312. InitializeObjectAttributes(
  313. &ObjectAttributes,
  314. &KeyName,
  315. OBJ_CASE_INSENSITIVE,
  316. NULL,
  317. NULL
  318. );
  319. Status = NtOpenKey(&Key, KEY_READ, &ObjectAttributes);
  320. if (!NT_SUCCESS(Status)) {
  321. KdPrint(("SMSS: can't open session manager key: 0x%x\n", Status));
  322. return 0;
  323. }
  324. //
  325. // Query the key value.
  326. //
  327. RtlInitUnicodeString(&ValueName, L"GlobalFlag");
  328. Status = NtQueryValueKey(
  329. Key,
  330. &ValueName,
  331. KeyValuePartialInformation,
  332. (PVOID)KeyValueInfo,
  333. sizeof (ValueBuffer),
  334. &ValueLength
  335. );
  336. ASSERT(ValueLength < VALUE_BUFFER_SIZE);
  337. NtClose(Key);
  338. if (!NT_SUCCESS(Status)) {
  339. KdPrint(("SMSS: can't query value key: 0x%x\n", Status));
  340. return 0;
  341. }
  342. return *((PULONG)&KeyValueInfo->Data);
  343. }