Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygensmutil.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS Windows-Compatible Session Manager 00003 * LICENSE: BSD 2-Clause License 00004 * FILE: base/system/smss/smss.c 00005 * PURPOSE: Main SMSS Code 00006 * PROGRAMMERS: Alex Ionescu 00007 */ 00008 00009 /* INCLUDES *******************************************************************/ 00010 00011 #include "smss.h" 00012 #define NDEBUG 00013 #include "debug.h" 00014 00015 /* GLOBALS ********************************************************************/ 00016 00017 // 00018 // Taken from an ASSERT 00019 // 00020 #define VALUE_BUFFER_SIZE (sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 512) 00021 00022 typedef struct _SMP_PRIVILEGE_STATE 00023 { 00024 HANDLE TokenHandle; 00025 PTOKEN_PRIVILEGES OldPrivileges; 00026 PTOKEN_PRIVILEGES NewPrivileges; 00027 UCHAR OldBuffer[1024]; 00028 TOKEN_PRIVILEGES NewBuffer; 00029 } SMP_PRIVILEGE_STATE, *PSMP_PRIVILEGE_STATE; 00030 00031 UNICODE_STRING SmpDebugKeyword, SmpASyncKeyword, SmpAutoChkKeyword; 00032 00033 /* FUNCTIONS ******************************************************************/ 00034 00035 NTSTATUS 00036 NTAPI 00037 SmpAcquirePrivilege(IN ULONG Privilege, 00038 OUT PVOID *PrivilegeState) 00039 { 00040 PSMP_PRIVILEGE_STATE State; 00041 ULONG Size; 00042 NTSTATUS Status; 00043 00044 /* Assume failure */ 00045 *PrivilegeState = NULL; 00046 00047 /* Acquire the state structure to hold everything we need */ 00048 State = RtlAllocateHeap(SmpHeap, 00049 0, 00050 sizeof(SMP_PRIVILEGE_STATE) + 00051 sizeof(TOKEN_PRIVILEGES) + 00052 sizeof(LUID_AND_ATTRIBUTES)); 00053 if (!State) return STATUS_NO_MEMORY; 00054 00055 /* Open our token */ 00056 Status = NtOpenProcessToken(NtCurrentProcess(), 00057 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, 00058 &State->TokenHandle); 00059 if (!NT_SUCCESS(Status)) 00060 { 00061 /* Fail */ 00062 RtlFreeHeap(SmpHeap, 0, State); 00063 return Status; 00064 } 00065 00066 /* Set one privilege in the enabled state */ 00067 State->NewPrivileges = &State->NewBuffer; 00068 State->OldPrivileges = (PTOKEN_PRIVILEGES)&State->OldBuffer; 00069 State->NewPrivileges->PrivilegeCount = 1; 00070 State->NewPrivileges->Privileges[0].Luid = RtlConvertUlongToLuid(Privilege); 00071 State->NewPrivileges->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 00072 00073 /* Adjust the privileges in the token */ 00074 Size = sizeof(State->OldBuffer); 00075 Status = NtAdjustPrivilegesToken(State->TokenHandle, 00076 FALSE, 00077 State->NewPrivileges, 00078 Size, 00079 State->OldPrivileges, 00080 &Size); 00081 if (Status == STATUS_BUFFER_TOO_SMALL) 00082 { 00083 /* Our static buffer is not big enough, allocate a bigger one */ 00084 State->OldPrivileges = RtlAllocateHeap(SmpHeap, 0, Size); 00085 if (!State->OldPrivileges) 00086 { 00087 /* Out of memory, fail */ 00088 Status = STATUS_NO_MEMORY; 00089 goto Quickie; 00090 } 00091 00092 /* Now try again */ 00093 Status = NtAdjustPrivilegesToken(State->TokenHandle, 00094 FALSE, 00095 State->NewPrivileges, 00096 Size, 00097 State->OldPrivileges, 00098 &Size); 00099 } 00100 00101 /* Normalize failure code and check for success */ 00102 if (Status == STATUS_NOT_ALL_ASSIGNED) Status = STATUS_PRIVILEGE_NOT_HELD; 00103 if (NT_SUCCESS(Status)) 00104 { 00105 /* We got the privilege, return */ 00106 *PrivilegeState = State; 00107 return STATUS_SUCCESS; 00108 } 00109 00110 Quickie: 00111 /* Check if we used a dynamic buffer */ 00112 if (State->OldPrivileges != (PTOKEN_PRIVILEGES)&State->OldBuffer) 00113 { 00114 /* Free it */ 00115 RtlFreeHeap(SmpHeap, 0, State->OldPrivileges); 00116 } 00117 00118 /* Close the token handle and free the state structure */ 00119 NtClose(State->TokenHandle); 00120 RtlFreeHeap(SmpHeap, 0, State); 00121 return Status; 00122 } 00123 00124 VOID 00125 NTAPI 00126 SmpReleasePrivilege(IN PVOID PrivState) 00127 { 00128 PSMP_PRIVILEGE_STATE State = (PSMP_PRIVILEGE_STATE)PrivState; 00129 00130 /* Adjust the privileges in the token */ 00131 NtAdjustPrivilegesToken(State->TokenHandle, 00132 FALSE, 00133 State->OldPrivileges, 00134 0, 00135 NULL, 00136 NULL); 00137 00138 /* Check if we used a dynamic buffer */ 00139 if (State->OldPrivileges != (PTOKEN_PRIVILEGES)&State->OldBuffer) 00140 { 00141 /* Free it */ 00142 RtlFreeHeap(SmpHeap, 0, State->OldPrivileges); 00143 } 00144 00145 /* Close the token handle and free the state structure */ 00146 NtClose(State->TokenHandle); 00147 RtlFreeHeap(SmpHeap, 0, State); 00148 } 00149 00150 NTSTATUS 00151 NTAPI 00152 SmpParseToken(IN PUNICODE_STRING Input, 00153 IN BOOLEAN SecondPass, 00154 OUT PUNICODE_STRING Token) 00155 { 00156 PWCHAR p, pp; 00157 ULONG Length, TokenLength, InputLength; 00158 00159 /* Initialize to NULL to start with */ 00160 RtlInitUnicodeString(Token, NULL); 00161 00162 /* Save the input length */ 00163 InputLength = Input->Length; 00164 00165 /* Parse the buffer until the first character */ 00166 p = Input->Buffer; 00167 Length = 0; 00168 while (Length < InputLength) 00169 { 00170 if (*p > L' ' ) break; 00171 ++p; 00172 Length += sizeof(WCHAR); 00173 } 00174 00175 /* Are we being called for argument pick-up? */ 00176 if (SecondPass) 00177 { 00178 /* Then assume everything else is an argument */ 00179 TokenLength = InputLength - Length * sizeof(WCHAR); 00180 pp = (PWSTR)((ULONG_PTR)p + TokenLength); 00181 } 00182 else 00183 { 00184 /* No -- so loop until the next space */ 00185 pp = p; 00186 while (Length < InputLength) 00187 { 00188 if (*pp <= L' ' ) break; 00189 ++pp; 00190 Length += sizeof(WCHAR); 00191 } 00192 00193 /* Now compute how long this token is, and loop until the next char */ 00194 TokenLength = (ULONG_PTR)pp - (ULONG_PTR)p; 00195 while (Length < InputLength) 00196 { 00197 if (*pp > L' ' ) break; 00198 ++pp; 00199 Length += sizeof(WCHAR); 00200 } 00201 } 00202 00203 /* Did we find a token? */ 00204 if (TokenLength) 00205 { 00206 /* Allocate a buffer for it */ 00207 Token->Buffer = RtlAllocateHeap(SmpHeap, 00208 SmBaseTag, 00209 TokenLength + sizeof(UNICODE_NULL)); 00210 if (!Token->Buffer) return STATUS_NO_MEMORY; 00211 00212 /* Fill in the unicode string to hold it */ 00213 Token->MaximumLength = TokenLength + sizeof(UNICODE_NULL); 00214 Token->Length = TokenLength; 00215 RtlCopyMemory(Token->Buffer, p, TokenLength); 00216 Token->Buffer[TokenLength / sizeof(WCHAR)] = UNICODE_NULL; 00217 } 00218 00219 /* Modify the input string with the position of where the next token begins */ 00220 Input->Length -= (ULONG_PTR)pp - (ULONG_PTR)Input->Buffer; 00221 Input->Buffer = pp; 00222 return STATUS_SUCCESS; 00223 } 00224 00225 NTSTATUS 00226 NTAPI 00227 SmpParseCommandLine(IN PUNICODE_STRING CommandLine, 00228 OUT PULONG Flags, 00229 OUT PUNICODE_STRING FileName, 00230 OUT PUNICODE_STRING Directory, 00231 OUT PUNICODE_STRING Arguments) 00232 { 00233 ULONG Length; 00234 UNICODE_STRING EnvString, PathString, CmdLineCopy, Token; 00235 WCHAR PathBuffer[MAX_PATH]; 00236 PWCHAR FilePart; 00237 NTSTATUS Status; 00238 UNICODE_STRING FullPathString; 00239 00240 /* Initialize output arguments to NULL */ 00241 RtlInitUnicodeString(FileName, NULL); 00242 RtlInitUnicodeString(Arguments, NULL); 00243 if (Directory) RtlInitUnicodeString(Directory, NULL); 00244 00245 /* Check if we haven't yet built a full default path or system root yet */ 00246 if (!SmpSystemRoot.Length) 00247 { 00248 /* Initialize it based on shared user data string */ 00249 RtlInitUnicodeString(&SmpSystemRoot, SharedUserData->NtSystemRoot); 00250 00251 /* Allocate an empty string for the path */ 00252 Length = SmpDefaultLibPath.MaximumLength + SmpSystemRoot.MaximumLength + 00253 sizeof(L"\\system32;"); 00254 RtlInitEmptyUnicodeString(&FullPathString, 00255 RtlAllocateHeap(SmpHeap, SmBaseTag, Length), 00256 Length); 00257 if (FullPathString.Buffer) 00258 { 00259 /* Append the root, system32;, and then the current library path */ 00260 RtlAppendUnicodeStringToString(&FullPathString, &SmpSystemRoot); 00261 RtlAppendUnicodeToString(&FullPathString, L"\\system32;"); 00262 RtlAppendUnicodeStringToString(&FullPathString, &SmpDefaultLibPath); 00263 RtlFreeHeap(SmpHeap, 0, SmpDefaultLibPath.Buffer); 00264 SmpDefaultLibPath = FullPathString; 00265 } 00266 } 00267 00268 /* Consume the command line */ 00269 CmdLineCopy = *CommandLine; 00270 while (TRUE) 00271 { 00272 /* Parse the first token and check for modifiers/specifiers */ 00273 Status = SmpParseToken(&CmdLineCopy, FALSE, &Token); 00274 if (!(NT_SUCCESS(Status)) || !(Token.Buffer)) return STATUS_UNSUCCESSFUL; 00275 if (!Flags) break; 00276 00277 /* Debug requested? */ 00278 if (RtlEqualUnicodeString(&Token, &SmpDebugKeyword, TRUE)) 00279 { 00280 /* Convert into a flag */ 00281 *Flags |= SMP_DEBUG_FLAG; 00282 } 00283 else if (RtlEqualUnicodeString(&Token, &SmpASyncKeyword, TRUE)) 00284 { 00285 /* Asynch requested, convert into a flag */ 00286 *Flags |= SMP_ASYNC_FLAG; 00287 } 00288 else if (RtlEqualUnicodeString(&Token, &SmpAutoChkKeyword, TRUE)) 00289 { 00290 /* Autochk requested, convert into a flag */ 00291 *Flags |= SMP_AUTOCHK_FLAG; 00292 } 00293 else 00294 { 00295 /* No specifier found, keep going */ 00296 break; 00297 } 00298 00299 /* Get rid of this token and get the next */ 00300 RtlFreeHeap(SmpHeap, 0, Token.Buffer); 00301 } 00302 00303 /* Initialize a string to hold the current path */ 00304 RtlInitUnicodeString(&EnvString, L"Path"); 00305 Length = PAGE_SIZE; 00306 RtlInitEmptyUnicodeString(&PathString, 00307 RtlAllocateHeap(SmpHeap, SmBaseTag, Length), 00308 Length); 00309 if (!PathString.Buffer) 00310 { 00311 /* Fail if we have no memory for this */ 00312 RtlFreeHeap(SmpHeap, 0, Token.Buffer); 00313 return STATUS_INSUFFICIENT_RESOURCES; 00314 } 00315 00316 /* Query the path from the environment */ 00317 Status = RtlQueryEnvironmentVariable_U(SmpDefaultEnvironment, 00318 &EnvString, 00319 &PathString); 00320 if (Status == STATUS_BUFFER_TOO_SMALL) 00321 { 00322 /* Our buffer was too small, free it */ 00323 RtlFreeHeap(SmpHeap, 0, PathString.Buffer); 00324 00325 /* And allocate one big enough */ 00326 Length = PathString.Length + sizeof(UNICODE_NULL); 00327 RtlInitEmptyUnicodeString(&PathString, 00328 RtlAllocateHeap(SmpHeap, SmBaseTag, Length), 00329 Length); 00330 if (!PathString.Buffer) 00331 { 00332 /* Fail if we have no memory for this */ 00333 RtlFreeHeap(SmpHeap, 0, Token.Buffer); 00334 return STATUS_INSUFFICIENT_RESOURCES; 00335 } 00336 00337 /* Now try again, this should work */ 00338 Status = RtlQueryEnvironmentVariable_U(SmpDefaultEnvironment, 00339 &EnvString, 00340 &PathString); 00341 } 00342 if (!NT_SUCCESS(Status)) 00343 { 00344 /* Another failure means that the kernel hasn't passed the path correctly */ 00345 DPRINT1("SMSS: %wZ environment variable not defined.\n", &EnvString); 00346 Status = STATUS_OBJECT_NAME_NOT_FOUND; 00347 } 00348 else 00349 { 00350 /* Check if the caller expects any flags out of here */ 00351 if (Flags) 00352 { 00353 /* We can return the image not found flag -- so does the image exist */ 00354 if (!(RtlDosSearchPath_U(PathString.Buffer, 00355 Token.Buffer, 00356 L".exe", 00357 sizeof(PathBuffer), 00358 PathBuffer, 00359 &FilePart)) && 00360 !(RtlDosSearchPath_U(SmpDefaultLibPath.Buffer, 00361 Token.Buffer, 00362 L".exe", 00363 sizeof(PathBuffer), 00364 PathBuffer, 00365 &FilePart))) 00366 { 00367 /* It doesn't, let the caller know about it and exit */ 00368 *Flags |= SMP_INVALID_PATH; 00369 *FileName = Token; 00370 RtlFreeHeap(SmpHeap, 0, PathString.Buffer); 00371 return STATUS_SUCCESS; 00372 } 00373 } 00374 else 00375 { 00376 /* Caller doesn't want flags, probably wants the image itself */ 00377 wcscpy(PathBuffer, Token.Buffer); 00378 } 00379 } 00380 00381 /* Free tokens and such, all that's left is to convert the image name */ 00382 RtlFreeHeap(SmpHeap, 0, Token.Buffer); 00383 RtlFreeHeap(SmpHeap, 0, PathString.Buffer); 00384 if (!NT_SUCCESS(Status)) return Status; 00385 00386 /* Convert it and bail out if this failed */ 00387 if (!RtlDosPathNameToNtPathName_U(PathBuffer, FileName, NULL, NULL)) 00388 { 00389 DPRINT1("SMSS: Unable to translate %ws into an NT File Name\n", 00390 &PathBuffer); 00391 Status = STATUS_OBJECT_PATH_INVALID; 00392 } 00393 if (!NT_SUCCESS(Status)) return Status; 00394 00395 /* Finally, check if the caller also wanted the directory */ 00396 if (Directory) 00397 { 00398 /* Is the file a relative name with no directory? */ 00399 if (FilePart <= PathBuffer) 00400 { 00401 /* Clear it */ 00402 RtlInitUnicodeString(Directory, NULL); 00403 } 00404 else 00405 { 00406 /* There is a directory, and a filename -- separate those two */ 00407 *--FilePart = UNICODE_NULL; 00408 RtlCreateUnicodeString(Directory, PathBuffer); 00409 } 00410 } 00411 00412 /* We are done -- move on to the second pass to get the arguments */ 00413 return SmpParseToken(&CmdLineCopy, TRUE, Arguments); 00414 } 00415 00416 BOOLEAN 00417 NTAPI 00418 SmpQueryRegistrySosOption(VOID) 00419 { 00420 NTSTATUS Status; 00421 UNICODE_STRING KeyName, ValueName; 00422 OBJECT_ATTRIBUTES ObjectAttributes; 00423 HANDLE KeyHandle; 00424 WCHAR ValueBuffer[VALUE_BUFFER_SIZE]; 00425 PKEY_VALUE_PARTIAL_INFORMATION PartialInfo = (PVOID)ValueBuffer; 00426 ULONG Length; 00427 00428 /* Open the key */ 00429 RtlInitUnicodeString(&KeyName, 00430 L"\\Registry\\Machine\\System\\CurrentControlSet\\Control"); 00431 InitializeObjectAttributes(&ObjectAttributes, 00432 &KeyName, 00433 OBJ_CASE_INSENSITIVE, 00434 NULL, 00435 NULL); 00436 Status = NtOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes); 00437 if (!NT_SUCCESS(Status)) 00438 { 00439 DPRINT1("SMSS: can't open control key: 0x%x\n", Status); 00440 return FALSE; 00441 } 00442 00443 /* Query the value */ 00444 RtlInitUnicodeString(&ValueName, L"SystemStartOptions"); 00445 Status = NtQueryValueKey(KeyHandle, 00446 &ValueName, 00447 KeyValuePartialInformation, 00448 PartialInfo, 00449 sizeof(ValueBuffer), 00450 &Length); 00451 ASSERT(Length < VALUE_BUFFER_SIZE); 00452 NtClose(KeyHandle); 00453 if (!NT_SUCCESS(Status)) 00454 { 00455 DPRINT1("SMSS: can't query value key: 0x%x\n", Status); 00456 return FALSE; 00457 } 00458 00459 /* Check if it's set to SOS or sos */ 00460 if (!(wcsstr((PWCHAR)PartialInfo->Data, L"SOS")) || 00461 (wcsstr((PWCHAR)PartialInfo->Data, L"sos"))) 00462 { 00463 /* It's not set, return FALSE */ 00464 return FALSE; 00465 } 00466 00467 /* It's set, return TRUE */ 00468 return TRUE; 00469 } 00470 00471 BOOLEAN 00472 NTAPI 00473 SmpSaveAndClearBootStatusData(OUT PBOOLEAN BootOkay, 00474 OUT PBOOLEAN ShutdownOkay) 00475 { 00476 NTSTATUS Status; 00477 BOOLEAN Value = TRUE; 00478 PVOID BootStatusDataHandle; 00479 00480 /* Assume failure */ 00481 *BootOkay = FALSE; 00482 *ShutdownOkay = FALSE; 00483 00484 /* Lock the BSD and fail if we couldn't */ 00485 Status = RtlLockBootStatusData(&BootStatusDataHandle); 00486 if (!NT_SUCCESS(Status)) return FALSE; 00487 00488 /* Read the old settings */ 00489 RtlGetSetBootStatusData(BootStatusDataHandle, 00490 TRUE, 00491 RtlBsdItemBootGood, 00492 BootOkay, 00493 sizeof(BOOLEAN), 00494 NULL); 00495 RtlGetSetBootStatusData(BootStatusDataHandle, 00496 TRUE, 00497 RtlBsdItemBootShutdown, 00498 ShutdownOkay, 00499 sizeof(BOOLEAN), 00500 NULL); 00501 00502 /* Set new ones indicating we got at least this far */ 00503 RtlGetSetBootStatusData(BootStatusDataHandle, 00504 FALSE, 00505 RtlBsdItemBootGood, 00506 &Value, 00507 sizeof(Value), 00508 NULL); 00509 RtlGetSetBootStatusData(BootStatusDataHandle, 00510 FALSE, 00511 RtlBsdItemBootShutdown, 00512 &Value, 00513 sizeof(Value), 00514 NULL); 00515 00516 /* Unlock the BSD and return */ 00517 RtlUnlockBootStatusData(BootStatusDataHandle); 00518 return TRUE; 00519 } 00520 00521 VOID 00522 NTAPI 00523 SmpRestoreBootStatusData(IN BOOLEAN BootOkay, 00524 IN BOOLEAN ShutdownOkay) 00525 { 00526 NTSTATUS Status; 00527 PVOID BootState; 00528 00529 /* Lock the BSD */ 00530 Status = RtlLockBootStatusData(&BootState); 00531 if (NT_SUCCESS(Status)) 00532 { 00533 /* Write the bootokay and bootshudown values */ 00534 RtlGetSetBootStatusData(BootState, 00535 FALSE, 00536 RtlBsdItemBootGood, 00537 &BootOkay, 00538 sizeof(BootOkay), 00539 NULL); 00540 RtlGetSetBootStatusData(BootState, 00541 FALSE, 00542 RtlBsdItemBootShutdown, 00543 &ShutdownOkay, 00544 sizeof(ShutdownOkay), 00545 NULL); 00546 00547 /* Unlock the BSD and return */ 00548 RtlUnlockBootStatusData(BootState); 00549 } 00550 } Generated on Sun May 27 2012 04:18:53 for ReactOS by
1.7.6.1
|