Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

rtlexec.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1989 Microsoft Corporation 00004 00005 Module Name: 00006 00007 rtlexec.c 00008 00009 Abstract: 00010 00011 User Mode routines for creating user mode processes and threads. 00012 00013 Author: 00014 00015 Steve Wood (stevewo) 18-Aug-1989 00016 00017 Environment: 00018 00019 User Mode or Kernel Mode 00020 00021 Revision History: 00022 00023 --*/ 00024 00025 #include "ntrtlp.h" 00026 #include <nturtl.h> 00027 #include <string.h> 00028 #include "init.h" 00029 #include "ntos.h" 00030 #define ROUND_UP( x, y ) ((ULONG)(x) + ((y)-1) & ~((y)-1)) 00031 #ifdef KERNEL 00032 #define ISTERMINALSERVER() (SharedUserData->SuiteMask & (1 << TerminalServer)) 00033 #else 00034 #define ISTERMINALSERVER() (USER_SHARED_DATA->SuiteMask & (1 << TerminalServer)) 00035 #endif 00036 00037 VOID 00038 RtlpCopyProcString( 00039 IN OUT PWSTR *pDst, 00040 OUT PUNICODE_STRING DestString, 00041 IN PUNICODE_STRING SourceString, 00042 IN ULONG DstAlloc OPTIONAL 00043 ); 00044 00045 NTSTATUS 00046 RtlpOpenImageFile( 00047 IN PUNICODE_STRING ImagePathName, 00048 IN ULONG Attributes, 00049 OUT PHANDLE FileHandle, 00050 IN BOOLEAN ReportErrors 00051 ); 00052 00053 NTSTATUS 00054 RtlpFreeStack( 00055 IN HANDLE Process, 00056 IN PINITIAL_TEB InitialTeb 00057 ); 00058 00059 NTSTATUS 00060 RtlpCreateStack( 00061 IN HANDLE Process, 00062 IN SIZE_T MaximumStackSize OPTIONAL, 00063 IN SIZE_T CommittedStackSize OPTIONAL, 00064 IN ULONG ZeroBits OPTIONAL, 00065 OUT PINITIAL_TEB InitialTeb 00066 ); 00067 00068 #if defined(ALLOC_PRAGMA) && defined(NTOS_KERNEL_RUNTIME) 00069 #pragma alloc_text(INIT,RtlpCopyProcString ) 00070 #pragma alloc_text(INIT,RtlCreateProcessParameters ) 00071 #pragma alloc_text(INIT,RtlDestroyProcessParameters ) 00072 #pragma alloc_text(INIT,RtlNormalizeProcessParams ) 00073 #pragma alloc_text(INIT,RtlDeNormalizeProcessParams ) 00074 #pragma alloc_text(INIT,RtlpOpenImageFile ) 00075 #pragma alloc_text(INIT,RtlpCreateStack ) 00076 #pragma alloc_text(INIT,RtlpFreeStack ) 00077 #pragma alloc_text(INIT,RtlCreateUserProcess ) 00078 #pragma alloc_text(INIT,RtlCreateUserThread ) 00079 #endif 00080 00081 00082 VOID 00083 RtlpCopyProcString( 00084 IN OUT PWSTR *pDst, 00085 OUT PUNICODE_STRING DestString, 00086 IN PUNICODE_STRING SourceString, 00087 IN ULONG DstAlloc OPTIONAL 00088 ) 00089 { 00090 if (!ARGUMENT_PRESENT( (ULONG_PTR)DstAlloc )) { 00091 DstAlloc = SourceString->MaximumLength; 00092 } 00093 00094 if (SourceString->Buffer != NULL && SourceString->Length != 0) { 00095 RtlMoveMemory( *pDst, 00096 SourceString->Buffer, 00097 SourceString->Length 00098 ); 00099 } 00100 00101 DestString->Buffer = *pDst; 00102 DestString->Length = SourceString->Length; 00103 DestString->MaximumLength = (USHORT)DstAlloc; 00104 00105 *pDst = (PWSTR)((PCHAR)(*pDst) + ROUND_UP( DstAlloc, sizeof( ULONG ) ) ); 00106 return; 00107 } 00108 00109 NTSTATUS 00110 RtlCreateProcessParameters( 00111 OUT PRTL_USER_PROCESS_PARAMETERS *ProcessParameters, 00112 IN PUNICODE_STRING ImagePathName, 00113 IN PUNICODE_STRING DllPath OPTIONAL, 00114 IN PUNICODE_STRING CurrentDirectory OPTIONAL, 00115 IN PUNICODE_STRING CommandLine OPTIONAL, 00116 IN PVOID Environment OPTIONAL, 00117 IN PUNICODE_STRING WindowTitle OPTIONAL, 00118 IN PUNICODE_STRING DesktopInfo OPTIONAL, 00119 IN PUNICODE_STRING ShellInfo OPTIONAL, 00120 IN PUNICODE_STRING RuntimeData OPTIONAL 00121 ) 00122 00123 /*++ 00124 00125 Routine Description: 00126 00127 This function formats NT style RTL_USER_PROCESS_PARAMETERS 00128 record. The record is self-contained in a single block of memory 00129 allocated by this function. The allocation method is opaque and 00130 thus the record must be freed by calling the 00131 RtlDestroyProcessParameters function. 00132 00133 The process parameters record is created in a de-normalized form, 00134 thus making it suitable for passing to the RtlCreateUserProcess 00135 function. It is expected that the caller will fill in additional 00136 fields in the process parameters record after this function returns, 00137 but prior to calling RtlCreateUserProcess. 00138 00139 Arguments: 00140 00141 ProcessParameters - Pointer to a variable that will receive the address 00142 of the process parameter structure created by this routinue. The 00143 memory for the structure is allocated in an opaque manner and must 00144 be freed by calling RtlDestroyProcessParameters. 00145 00146 ImagePathName - Required parameter that is the fully qualified NT 00147 path name of the image file that will be used to create the process 00148 that will received these parameters. 00149 00150 DllPath - An optional parameter that is an NT String variable pointing 00151 to the search path the NT Loader is to use in the target process 00152 when searching for Dll modules. If not specified, then the Dll 00153 search path is filled in from the current process's Dll search 00154 path. 00155 00156 CurrentDirectory - An optional parameter that is an NT String variable 00157 pointing to the default directory string for the target process. 00158 If not specified, then the current directory string is filled in 00159 from the current process's current directory string. 00160 00161 CommandLine - An optional parameter that is an NT String variable that 00162 will be passed to the target process as its command line. If not 00163 specified, then the command line passed to the target process will 00164 be a null string. 00165 00166 Environment - An optional parameter that is an opaque pointer to an 00167 environment variable block of the type created by 00168 RtlCreateEnvironment routine. If not specified, then the target 00169 process will receive a copy of the calling process's environment 00170 variable block. 00171 00172 WindowTitle - An optional parameter that is an NT String variable that 00173 points to the title string the target process is to use for its 00174 main window. If not specified, then a null string will be passed 00175 to the target process as its default window title. 00176 00177 DesktopInfo - An optional parameter that is an NT String variable that 00178 contains uninterpreted data that is passed as is to the target 00179 process. If not specified, the target process will receive a 00180 pointer to an empty string. 00181 00182 ShellInfo - An optional parameter that is an NT String variable that 00183 contains uninterpreted data that is passed as is to the target 00184 process. If not specified, the target process will receive a 00185 pointer to an empty string. 00186 00187 RuntimeData - An optional parameter that is an NT String variable that 00188 contains uninterpreted data that is passed as is to the target 00189 process. If not specified, the target process will receive a 00190 pointer to an empty string. 00191 00192 Return Value: 00193 00194 STATUS_SUCCESS - The process parameters is De-Normalized and 00195 contains entries for each of the specified argument and variable 00196 strings. 00197 00198 STATUS_BUFFER_TOO_SMALL - The specified process parameters buffer is 00199 too small to contain the argument and environment strings. The value 00200 of ProcessParameters->Length is modified to contain the buffer 00201 size needed to contain the argument and variable strings. 00202 00203 --*/ 00204 00205 { 00206 PRTL_USER_PROCESS_PARAMETERS p; 00207 NTSTATUS Status; 00208 UNICODE_STRING NullString = {0, 1, L""}; 00209 ULONG ByteCount; 00210 SIZE_T MaxByteCount; 00211 PWSTR pDst; 00212 PPEB Peb = NtCurrentPeb(); 00213 HANDLE CurDirHandle; 00214 00215 // 00216 // Acquire the Peb Lock for the duration while we copy information out 00217 // of it. 00218 // 00219 00220 RtlAcquirePebLock(); 00221 Status = STATUS_SUCCESS; 00222 p = NULL; 00223 CurDirHandle = NULL; 00224 try { 00225 // 00226 // For optional pointer parameters, default them to point to their 00227 // corresponding field in the current process's process parameter 00228 // structure or to a null string. 00229 // 00230 00231 if (!ARGUMENT_PRESENT( DllPath )) { 00232 DllPath = &Peb->ProcessParameters->DllPath; 00233 } 00234 00235 if (!ARGUMENT_PRESENT( CurrentDirectory )) { 00236 00237 if ( Peb->ProcessParameters->CurrentDirectory.Handle ) { 00238 CurDirHandle = (HANDLE)((ULONG_PTR)Peb->ProcessParameters->CurrentDirectory.Handle & ~OBJ_HANDLE_TAGBITS); 00239 CurDirHandle = (HANDLE)((ULONG_PTR)CurDirHandle | RTL_USER_PROC_CURDIR_INHERIT); 00240 } 00241 CurrentDirectory = &Peb->ProcessParameters->CurrentDirectory.DosPath; 00242 } 00243 else { 00244 if ( Peb->ProcessParameters->CurrentDirectory.Handle ) { 00245 CurDirHandle = (HANDLE)((ULONG_PTR)Peb->ProcessParameters->CurrentDirectory.Handle & ~OBJ_HANDLE_TAGBITS); 00246 CurDirHandle = (HANDLE)((ULONG_PTR)CurDirHandle | RTL_USER_PROC_CURDIR_CLOSE); 00247 } 00248 } 00249 00250 if (!ARGUMENT_PRESENT( CommandLine )) { 00251 CommandLine = ImagePathName; 00252 } 00253 00254 if (!ARGUMENT_PRESENT( Environment )) { 00255 Environment = Peb->ProcessParameters->Environment; 00256 } 00257 00258 if (!ARGUMENT_PRESENT( WindowTitle )) { 00259 WindowTitle = &NullString; 00260 } 00261 00262 if (!ARGUMENT_PRESENT( DesktopInfo )) { 00263 DesktopInfo = &NullString; 00264 } 00265 00266 if (!ARGUMENT_PRESENT( ShellInfo )) { 00267 ShellInfo = &NullString; 00268 } 00269 00270 if (!ARGUMENT_PRESENT( RuntimeData )) { 00271 RuntimeData = &NullString; 00272 } 00273 00274 // 00275 // Determine size need to contain the process parameter record 00276 // structure and all of the strings it will point to. Each string 00277 // will be aligned on a ULONG byte boundary. 00278 // 00279 00280 ByteCount = sizeof( **ProcessParameters ); 00281 ByteCount += ROUND_UP( ImagePathName->Length + sizeof(UNICODE_NULL), sizeof( ULONG ) ); 00282 ByteCount += ROUND_UP( DllPath->MaximumLength, sizeof( ULONG ) ); 00283 ByteCount += ROUND_UP( DOS_MAX_PATH_LENGTH*2, sizeof( ULONG ) ); 00284 ByteCount += ROUND_UP( CommandLine->Length + sizeof(UNICODE_NULL), sizeof( ULONG ) ); 00285 ByteCount += ROUND_UP( WindowTitle->MaximumLength, sizeof( ULONG ) ); 00286 ByteCount += ROUND_UP( DesktopInfo->MaximumLength, sizeof( ULONG ) ); 00287 ByteCount += ROUND_UP( ShellInfo->MaximumLength, sizeof( ULONG ) ); 00288 ByteCount += ROUND_UP( RuntimeData->MaximumLength, sizeof( ULONG ) ); 00289 00290 // 00291 // Allocate memory for the process parameter record. 00292 // 00293 00294 MaxByteCount = ByteCount; 00295 Status = ZwAllocateVirtualMemory( NtCurrentProcess(), 00296 (PVOID *)&p, 00297 0, 00298 &MaxByteCount, 00299 MEM_COMMIT, 00300 PAGE_READWRITE 00301 ); 00302 if (!NT_SUCCESS( Status )) { 00303 return( Status ); 00304 } 00305 00306 p->MaximumLength = (ULONG) MaxByteCount; 00307 p->Length = ByteCount; 00308 p->Flags = RTL_USER_PROC_PARAMS_NORMALIZED; 00309 p->Environment = Environment; 00310 p->CurrentDirectory.Handle = CurDirHandle; 00311 00312 // 00313 // Inherits ^C inhibit information 00314 // 00315 00316 p->ConsoleFlags = Peb->ProcessParameters->ConsoleFlags; 00317 00318 pDst = (PWSTR)(p + 1); 00319 RtlpCopyProcString( &pDst, 00320 &p->CurrentDirectory.DosPath, 00321 CurrentDirectory, 00322 DOS_MAX_PATH_LENGTH*2 00323 ); 00324 00325 RtlpCopyProcString( &pDst, &p->DllPath, DllPath, 0 ); 00326 RtlpCopyProcString( &pDst, &p->ImagePathName, ImagePathName, ImagePathName->Length + sizeof(UNICODE_NULL) ); 00327 if (CommandLine->Length == CommandLine->MaximumLength) { 00328 RtlpCopyProcString( &pDst, &p->CommandLine, CommandLine, 0 ); 00329 } 00330 else { 00331 RtlpCopyProcString( &pDst, &p->CommandLine, CommandLine, CommandLine->Length + sizeof(UNICODE_NULL) ); 00332 } 00333 RtlpCopyProcString( &pDst, &p->WindowTitle, WindowTitle, 0 ); 00334 RtlpCopyProcString( &pDst, &p->DesktopInfo, DesktopInfo, 0 ); 00335 RtlpCopyProcString( &pDst, &p->ShellInfo, ShellInfo, 0 ); 00336 if (RuntimeData->Length != 0) { 00337 RtlpCopyProcString( &pDst, &p->RuntimeData, RuntimeData, 0 ); 00338 } 00339 else { 00340 p->RuntimeData.Buffer = NULL; 00341 p->RuntimeData.Length = 0; 00342 p->RuntimeData.MaximumLength = 0; 00343 } 00344 *ProcessParameters = RtlDeNormalizeProcessParams( p ); 00345 p = NULL; 00346 } 00347 finally { 00348 if (AbnormalTermination()) { 00349 Status = STATUS_ACCESS_VIOLATION; 00350 } 00351 00352 if (p != NULL) { 00353 RtlDestroyProcessParameters( p ); 00354 } 00355 00356 RtlReleasePebLock(); 00357 } 00358 00359 return( Status ); 00360 } 00361 00362 00363 00364 NTSTATUS 00365 RtlDestroyProcessParameters( 00366 IN PRTL_USER_PROCESS_PARAMETERS ProcessParameters 00367 ) 00368 { 00369 NTSTATUS Status; 00370 SIZE_T RegionSize; 00371 00372 RegionSize = 0; 00373 Status = ZwFreeVirtualMemory( NtCurrentProcess(), 00374 (PVOID *)&ProcessParameters, 00375 &RegionSize, 00376 MEM_RELEASE 00377 ); 00378 00379 return( Status ); 00380 } 00381 00382 00383 #define RtlpNormalizeProcessParam( Base, p ) \ 00384 if ((p) != NULL) { \ 00385 (p) = (PWSTR)((PCHAR)(p) + (ULONG_PTR)(Base)); \ 00386 } \ 00387 00388 #define RtlpDeNormalizeProcessParam( Base, p ) \ 00389 if ((p) != NULL) { \ 00390 (p) = (PWSTR)((PCHAR)(p) - (ULONG_PTR)(Base)); \ 00391 } \ 00392 00393 00394 PRTL_USER_PROCESS_PARAMETERS 00395 RtlNormalizeProcessParams( 00396 IN OUT PRTL_USER_PROCESS_PARAMETERS ProcessParameters 00397 ) 00398 { 00399 if (!ARGUMENT_PRESENT( ProcessParameters )) { 00400 return( NULL ); 00401 } 00402 00403 if (ProcessParameters->Flags & RTL_USER_PROC_PARAMS_NORMALIZED) { 00404 return( ProcessParameters ); 00405 } 00406 00407 RtlpNormalizeProcessParam( ProcessParameters, 00408 ProcessParameters->CurrentDirectory.DosPath.Buffer 00409 ); 00410 00411 RtlpNormalizeProcessParam( ProcessParameters, 00412 ProcessParameters->DllPath.Buffer 00413 ); 00414 00415 RtlpNormalizeProcessParam( ProcessParameters, 00416 ProcessParameters->ImagePathName.Buffer 00417 ); 00418 00419 RtlpNormalizeProcessParam( ProcessParameters, 00420 ProcessParameters->CommandLine.Buffer 00421 ); 00422 00423 RtlpNormalizeProcessParam( ProcessParameters, 00424 ProcessParameters->WindowTitle.Buffer 00425 ); 00426 00427 RtlpNormalizeProcessParam( ProcessParameters, 00428 ProcessParameters->DesktopInfo.Buffer 00429 ); 00430 00431 RtlpNormalizeProcessParam( ProcessParameters, 00432 ProcessParameters->ShellInfo.Buffer 00433 ); 00434 00435 RtlpNormalizeProcessParam( ProcessParameters, 00436 ProcessParameters->RuntimeData.Buffer 00437 ); 00438 ProcessParameters->Flags |= RTL_USER_PROC_PARAMS_NORMALIZED; 00439 00440 return( ProcessParameters ); 00441 } 00442 00443 PRTL_USER_PROCESS_PARAMETERS 00444 RtlDeNormalizeProcessParams( 00445 IN OUT PRTL_USER_PROCESS_PARAMETERS ProcessParameters 00446 ) 00447 { 00448 if (!ARGUMENT_PRESENT( ProcessParameters )) { 00449 return( NULL ); 00450 } 00451 00452 if (!(ProcessParameters->Flags & RTL_USER_PROC_PARAMS_NORMALIZED)) { 00453 return( ProcessParameters ); 00454 } 00455 00456 RtlpDeNormalizeProcessParam( ProcessParameters, 00457 ProcessParameters->CurrentDirectory.DosPath.Buffer 00458 ); 00459 00460 RtlpDeNormalizeProcessParam( ProcessParameters, 00461 ProcessParameters->DllPath.Buffer 00462 ); 00463 00464 RtlpDeNormalizeProcessParam( ProcessParameters, 00465 ProcessParameters->ImagePathName.Buffer 00466 ); 00467 00468 RtlpDeNormalizeProcessParam( ProcessParameters, 00469 ProcessParameters->CommandLine.Buffer 00470 ); 00471 00472 RtlpDeNormalizeProcessParam( ProcessParameters, 00473 ProcessParameters->WindowTitle.Buffer 00474 ); 00475 00476 RtlpDeNormalizeProcessParam( ProcessParameters, 00477 ProcessParameters->DesktopInfo.Buffer 00478 ); 00479 00480 RtlpDeNormalizeProcessParam( ProcessParameters, 00481 ProcessParameters->ShellInfo.Buffer 00482 ); 00483 00484 RtlpDeNormalizeProcessParam( ProcessParameters, 00485 ProcessParameters->RuntimeData.Buffer 00486 ); 00487 00488 ProcessParameters->Flags &= ~RTL_USER_PROC_PARAMS_NORMALIZED; 00489 return( ProcessParameters ); 00490 } 00491 00492 NTSTATUS 00493 RtlpOpenImageFile( 00494 IN PUNICODE_STRING ImagePathName, 00495 IN ULONG Attributes, 00496 OUT PHANDLE FileHandle, 00497 IN BOOLEAN ReportErrors 00498 ) 00499 { 00500 NTSTATUS Status; 00501 OBJECT_ATTRIBUTES ObjectAttributes; 00502 HANDLE File; 00503 IO_STATUS_BLOCK IoStatus; 00504 00505 *FileHandle = NULL; 00506 00507 InitializeObjectAttributes( &ObjectAttributes, 00508 ImagePathName, 00509 Attributes, 00510 NULL, 00511 NULL 00512 ); 00513 Status = ZwOpenFile( &File, 00514 SYNCHRONIZE | FILE_EXECUTE, 00515 &ObjectAttributes, 00516 &IoStatus, 00517 FILE_SHARE_READ | FILE_SHARE_DELETE, 00518 FILE_NON_DIRECTORY_FILE 00519 ); 00520 00521 if (!NT_SUCCESS( Status )) { 00522 #if DBG 00523 if (ReportErrors) { 00524 DbgPrint( "NTRTL: RtlpOpenImageFile - NtCreateFile( %wZ ) failed. Status == %X\n", 00525 ImagePathName, 00526 Status 00527 ); 00528 } 00529 #endif // DBG 00530 return( Status ); 00531 } 00532 00533 *FileHandle = File; 00534 return( STATUS_SUCCESS ); 00535 } 00536 00537 00538 NTSTATUS 00539 RtlpCreateStack( 00540 IN HANDLE Process, 00541 IN SIZE_T MaximumStackSize OPTIONAL, 00542 IN SIZE_T CommittedStackSize OPTIONAL, 00543 IN ULONG ZeroBits OPTIONAL, 00544 OUT PINITIAL_TEB InitialTeb 00545 ) 00546 { 00547 NTSTATUS Status; 00548 PCH Stack; 00549 SYSTEM_BASIC_INFORMATION SysInfo; 00550 BOOLEAN GuardPage; 00551 SIZE_T RegionSize; 00552 ULONG OldProtect; 00553 #if defined(_IA64_) 00554 PCH Bstore; 00555 SIZE_T CommittedBstoreSize; 00556 SIZE_T MaximumBstoreSize; 00557 SIZE_T MstackPlusBstoreSize; 00558 #endif 00559 00560 Status = ZwQuerySystemInformation( SystemBasicInformation, 00561 (PVOID)&SysInfo, 00562 sizeof( SysInfo ), 00563 NULL 00564 ); 00565 if ( !NT_SUCCESS( Status ) ) { 00566 return( Status ); 00567 } 00568 00569 // 00570 // if stack is in the current process, then default to 00571 // the parameters from the image 00572 // 00573 00574 if ( Process == NtCurrentProcess() ) { 00575 PPEB Peb; 00576 PIMAGE_NT_HEADERS NtHeaders; 00577 00578 00579 Peb = NtCurrentPeb(); 00580 NtHeaders = RtlImageNtHeader(Peb->ImageBaseAddress); 00581 00582 00583 if (!MaximumStackSize) { 00584 MaximumStackSize = NtHeaders->OptionalHeader.SizeOfStackReserve; 00585 } 00586 00587 if (!CommittedStackSize) { 00588 CommittedStackSize = NtHeaders->OptionalHeader.SizeOfStackCommit; 00589 } 00590 00591 } 00592 else { 00593 00594 if (!CommittedStackSize) { 00595 CommittedStackSize = SysInfo.PageSize; 00596 } 00597 00598 if (!MaximumStackSize) { 00599 MaximumStackSize = SysInfo.AllocationGranularity; 00600 } 00601 00602 } 00603 00604 00605 if ( CommittedStackSize >= MaximumStackSize ) { 00606 MaximumStackSize = ROUND_UP(CommittedStackSize, (1024*1024)); 00607 } 00608 00609 00610 CommittedStackSize = ROUND_UP( CommittedStackSize, SysInfo.PageSize ); 00611 MaximumStackSize = ROUND_UP( MaximumStackSize, 00612 SysInfo.AllocationGranularity 00613 ); 00614 00615 Stack = NULL, 00616 00617 #if defined(_IA64_) 00618 00619 // 00620 // Piggyback the backing store with the memory stack 00621 // 00622 00623 CommittedBstoreSize = CommittedStackSize; 00624 MaximumBstoreSize = MaximumStackSize; 00625 MstackPlusBstoreSize = MaximumBstoreSize + MaximumStackSize; 00626 00627 Status = ZwAllocateVirtualMemory( Process, 00628 (PVOID *)&Stack, 00629 ZeroBits, 00630 &MstackPlusBstoreSize, 00631 MEM_RESERVE, 00632 PAGE_READWRITE 00633 ); 00634 #else 00635 00636 Status = ZwAllocateVirtualMemory( Process, 00637 (PVOID *)&Stack, 00638 ZeroBits, 00639 &MaximumStackSize, 00640 MEM_RESERVE, 00641 PAGE_READWRITE 00642 ); 00643 #endif // defined(_IA64_) 00644 00645 if ( !NT_SUCCESS( Status ) ) { 00646 #if DBG 00647 DbgPrint( "NTRTL: RtlpCreateStack( %lx ) failed. Stack Reservation Status == %X\n", 00648 Process, 00649 Status 00650 ); 00651 #endif // DBG 00652 return( Status ); 00653 } 00654 00655 #if defined(_IA64_) 00656 InitialTeb->OldInitialTeb.OldBStoreLimit = NULL; 00657 #endif // defined(_IA64_) 00658 00659 InitialTeb->OldInitialTeb.OldStackBase = NULL; 00660 InitialTeb->OldInitialTeb.OldStackLimit = NULL; 00661 InitialTeb->StackAllocationBase = Stack; 00662 InitialTeb->StackBase = Stack + MaximumStackSize; 00663 00664 Stack += MaximumStackSize - CommittedStackSize; 00665 if (MaximumStackSize > CommittedStackSize) { 00666 Stack -= SysInfo.PageSize; 00667 CommittedStackSize += SysInfo.PageSize; 00668 GuardPage = TRUE; 00669 } 00670 else { 00671 GuardPage = FALSE; 00672 } 00673 Status = ZwAllocateVirtualMemory( Process, 00674 (PVOID *)&Stack, 00675 0, 00676 &CommittedStackSize, 00677 MEM_COMMIT, 00678 PAGE_READWRITE 00679 ); 00680 InitialTeb->StackLimit = Stack; 00681 00682 if ( !NT_SUCCESS( Status ) ) { 00683 #if DBG 00684 DbgPrint( "NTRTL: RtlpCreateStack( %lx ) failed. Stack Commit Status == %X\n", 00685 Process, 00686 Status 00687 ); 00688 #endif // DBG 00689 return( Status ); 00690 } 00691 00692 // 00693 // if we have space, create a guard page. 00694 // 00695 00696 if (GuardPage) { 00697 RegionSize = SysInfo.PageSize; 00698 Status = ZwProtectVirtualMemory( Process, 00699 (PVOID *)&Stack, 00700 &RegionSize, 00701 PAGE_GUARD | PAGE_READWRITE, 00702 &OldProtect); 00703 00704 00705 if ( !NT_SUCCESS( Status ) ) { 00706 #if DBG 00707 DbgPrint( "NTRTL: RtlpCreateStack( %lx ) failed. Guard Page Creation Status == %X\n", 00708 Process, 00709 Status 00710 ); 00711 #endif // DBG 00712 return( Status ); 00713 } 00714 #if defined(_IA64_) 00715 InitialTeb->StackLimit = (PVOID)((PUCHAR)InitialTeb->StackLimit + RegionSize); 00716 #else 00717 InitialTeb->StackLimit = (PVOID)((PUCHAR)InitialTeb->StackLimit - RegionSize); 00718 #endif // defined(_IA64_) 00719 } 00720 00721 #if defined(_IA64_) 00722 00723 // 00724 // Commit backing store pages and create guard pages if there is space 00725 // 00726 00727 Bstore = InitialTeb->StackBase; 00728 if (MaximumBstoreSize > CommittedBstoreSize) { 00729 CommittedBstoreSize += SysInfo.PageSize; 00730 GuardPage = TRUE; 00731 } else { 00732 GuardPage = FALSE; 00733 } 00734 00735 Status = ZwAllocateVirtualMemory( Process, 00736 (PVOID *)&Bstore, 00737 0, 00738 &CommittedBstoreSize, 00739 MEM_COMMIT, 00740 PAGE_READWRITE 00741 ); 00742 00743 InitialTeb->BStoreLimit = Bstore + CommittedBstoreSize; 00744 00745 if ( !NT_SUCCESS(Status) ) { 00746 #if DBG 00747 DbgPrint("NTRTL: RtlpCreateStack( %lx ) failed. Backing Store Commit Status == %X\n", 00748 Process, 00749 Status 00750 ); 00751 #endif // DBG 00752 return (Status); 00753 } 00754 00755 if (GuardPage) { 00756 Bstore = (PCH)InitialTeb->BStoreLimit - SysInfo.PageSize; 00757 RegionSize = SysInfo.PageSize; 00758 Status = ZwProtectVirtualMemory(Process, 00759 (PVOID *)&Bstore, 00760 &RegionSize, 00761 PAGE_GUARD | PAGE_READWRITE, 00762 &OldProtect 00763 ); 00764 if ( !NT_SUCCESS(Status) ) { 00765 #if DBG 00766 DbgPrint("NTRTL: RtlpCreateStack( %lx ) failed. Backing Store Guard Page Creation Status == %X\n", 00767 Process, 00768 Status 00769 ); 00770 #endif // DBG 00771 return (Status); 00772 } 00773 InitialTeb->BStoreLimit = (PVOID)((PUCHAR)InitialTeb->BStoreLimit - RegionSize); 00774 } 00775 00776 #endif // defined(_IA64_) 00777 00778 return( STATUS_SUCCESS ); 00779 } 00780 00781 00782 NTSTATUS 00783 RtlpFreeStack( 00784 IN HANDLE Process, 00785 IN PINITIAL_TEB InitialTeb 00786 ) 00787 { 00788 NTSTATUS Status; 00789 SIZE_T Zero; 00790 00791 Zero = 0; 00792 Status = ZwFreeVirtualMemory( Process, 00793 &InitialTeb->StackAllocationBase, 00794 &Zero, 00795 MEM_RELEASE 00796 ); 00797 if ( !NT_SUCCESS( Status ) ) { 00798 #if DBG 00799 DbgPrint( "NTRTL: RtlpFreeStack( %lx ) failed. Stack DeCommit Status == %X\n", 00800 Process, 00801 Status 00802 ); 00803 #endif // DBG 00804 return( Status ); 00805 } 00806 00807 RtlZeroMemory( InitialTeb, sizeof( *InitialTeb ) ); 00808 return( STATUS_SUCCESS ); 00809 } 00810 00811 00812 NTSTATUS 00813 RtlCreateUserProcess( 00814 IN PUNICODE_STRING NtImagePathName, 00815 IN ULONG Attributes, 00816 IN PRTL_USER_PROCESS_PARAMETERS ProcessParameters, 00817 IN PSECURITY_DESCRIPTOR ProcessSecurityDescriptor OPTIONAL, 00818 IN PSECURITY_DESCRIPTOR ThreadSecurityDescriptor OPTIONAL, 00819 IN HANDLE ParentProcess OPTIONAL, 00820 IN BOOLEAN InheritHandles, 00821 IN HANDLE DebugPort OPTIONAL, 00822 IN HANDLE ExceptionPort OPTIONAL, 00823 OUT PRTL_USER_PROCESS_INFORMATION ProcessInformation 00824 ) 00825 00826 /*++ 00827 00828 Routine Description: 00829 00830 This function creates a user mode process with a single thread with 00831 a suspend count of one. The address space of the new process is 00832 initialized with the contents of specified image file. The caller 00833 can specify the Access Control List for the new process and thread. 00834 The caller can also specify the parent process to inherit process 00835 priority and processor affinity from. The default is to inherit 00836 these from the current process. Finally the caller can specify 00837 whether the new process is to inherit any of the object handles 00838 from the specified parent process or not. 00839 00840 Information about the new process and thread is returned via 00841 the ProcessInformation parameter. 00842 00843 Arguments: 00844 00845 NtImagePathName - A required pointer that points to the NT Path string 00846 that identifies the image file that is to be loaded into the 00847 child process. 00848 00849 ProcessParameters - A required pointer that points to parameters that 00850 are to passed to the child process. 00851 00852 ProcessSecurityDescriptor - An optional pointer to the Security Descriptor 00853 give to the new process. 00854 00855 ThreadSecurityDescriptor - An optional pointer to the Security Descriptor 00856 give to the new thread. 00857 00858 ParentProcess - An optional process handle that will used to inherit 00859 certain properties from. 00860 00861 InheritHandles - A boolean value. TRUE specifies that object handles 00862 associated with the specified parent process are to be inherited 00863 by the new process, provided they have the OBJ_INHERIT attribute. 00864 FALSE specifies that the new process is to inherit no handles. 00865 00866 DebugPort - An optional handle to the debug port associated with this 00867 process. 00868 00869 ExceptionPort - An optional handle to the exception port associated with this 00870 process. 00871 00872 ProcessInformation - A pointer to a variable that receives information 00873 about the new process and thread. 00874 00875 Return Value: 00876 00877 TBS. 00878 00879 --*/ 00880 00881 { 00882 NTSTATUS Status; 00883 HANDLE Section, File; 00884 OBJECT_ATTRIBUTES ObjectAttributes; 00885 PRTL_USER_PROCESS_PARAMETERS Parameters; 00886 SIZE_T ParameterLength; 00887 PVOID Environment; 00888 PWCHAR s; 00889 ULONG EnvironmentLength; 00890 SIZE_T RegionSize; 00891 PROCESS_BASIC_INFORMATION ProcessInfo; 00892 PPEB Peb; 00893 UNICODE_STRING Unicode; 00894 00895 // 00896 // Zero output parameter and probe the addresses at the same time 00897 // 00898 00899 RtlZeroMemory( ProcessInformation, sizeof( *ProcessInformation ) ); 00900 ProcessInformation->Length = sizeof( *ProcessInformation ); 00901 00902 // 00903 // Open the specified image file. 00904 // 00905 00906 Status = RtlpOpenImageFile( NtImagePathName, 00907 Attributes & (OBJ_INHERIT | OBJ_CASE_INSENSITIVE), 00908 &File, 00909 TRUE 00910 ); 00911 if (!NT_SUCCESS( Status )) { 00912 return( Status ); 00913 } 00914 00915 00916 // 00917 // Create a memory section backed by the opened image file 00918 // 00919 00920 Status = ZwCreateSection( &Section, 00921 SECTION_ALL_ACCESS, 00922 NULL, 00923 NULL, 00924 PAGE_EXECUTE, 00925 SEC_IMAGE, 00926 File 00927 ); 00928 ZwClose( File ); 00929 if ( !NT_SUCCESS( Status ) ) { 00930 return( Status ); 00931 } 00932 00933 00934 // 00935 // Create the user mode process, defaulting the parent process to the 00936 // current process if one is not specified. The new process will not 00937 // have a name nor will the handle be inherited by other processes. 00938 // 00939 00940 if (!ARGUMENT_PRESENT( ParentProcess )) { 00941 ParentProcess = NtCurrentProcess(); 00942 } 00943 00944 InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, 00945 ProcessSecurityDescriptor ); 00946 if ( RtlGetNtGlobalFlags() & FLG_ENABLE_CSRDEBUG ) { 00947 if ( wcsstr(NtImagePathName->Buffer,L"csrss") || 00948 wcsstr(NtImagePathName->Buffer,L"CSRSS") 00949 ) { 00950 00951 // 00952 // For Hydra we don't name the CSRSS process to avoid name 00953 // collissions when multiple CSRSS's are started 00954 // 00955 if (ISTERMINALSERVER()) { 00956 00957 InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, 00958 ProcessSecurityDescriptor ); 00959 } else { 00960 00961 RtlInitUnicodeString(&Unicode,L"\\WindowsSS"); 00962 InitializeObjectAttributes( &ObjectAttributes, &Unicode, 0, NULL, 00963 ProcessSecurityDescriptor ); 00964 } 00965 00966 } 00967 } 00968 00969 if ( !InheritHandles ) { 00970 ProcessParameters->CurrentDirectory.Handle = NULL; 00971 } 00972 Status = ZwCreateProcess( &ProcessInformation->Process, 00973 PROCESS_ALL_ACCESS, 00974 &ObjectAttributes, 00975 ParentProcess, 00976 InheritHandles, 00977 Section, 00978 DebugPort, 00979 ExceptionPort 00980 ); 00981 if ( !NT_SUCCESS( Status ) ) { 00982 ZwClose( Section ); 00983 return( Status ); 00984 } 00985 00986 00987 // 00988 // Retreive the interesting information from the image header 00989 // 00990 00991 Status = ZwQuerySection( Section, 00992 SectionImageInformation, 00993 &ProcessInformation->ImageInformation, 00994 sizeof( ProcessInformation->ImageInformation ), 00995 NULL 00996 ); 00997 if ( !NT_SUCCESS( Status ) ) { 00998 ZwClose( ProcessInformation->Process ); 00999 ZwClose( Section ); 01000 return( Status ); 01001 } 01002 01003 Status = ZwQueryInformationProcess( ProcessInformation->Process, 01004 ProcessBasicInformation, 01005 &ProcessInfo, 01006 sizeof( ProcessInfo ), 01007 NULL 01008 ); 01009 if ( !NT_SUCCESS( Status ) ) { 01010 ZwClose( ProcessInformation->Process ); 01011 ZwClose( Section ); 01012 return( Status ); 01013 } 01014 01015 Peb = ProcessInfo.PebBaseAddress; 01016 01017 // 01018 // Duplicate Native handles into new process if any specified. 01019 // Note that the duplicated handles will overlay the input values. 01020 // 01021 01022 try { 01023 Status = STATUS_SUCCESS; 01024 01025 if ( ProcessParameters->StandardInput ) { 01026 01027 Status = ZwDuplicateObject( 01028 ParentProcess, 01029 ProcessParameters->StandardInput, 01030 ProcessInformation->Process, 01031 &ProcessParameters->StandardInput, 01032 0L, 01033 0L, 01034 DUPLICATE_SAME_ACCESS | DUPLICATE_SAME_ATTRIBUTES 01035 ); 01036 if ( !NT_SUCCESS(Status) ) { 01037 return Status; 01038 } 01039 } 01040 01041 if ( ProcessParameters->StandardOutput ) { 01042 01043 Status = ZwDuplicateObject( 01044 ParentProcess, 01045 ProcessParameters->StandardOutput, 01046 ProcessInformation->Process, 01047 &ProcessParameters->StandardOutput, 01048 0L, 01049 0L, 01050 DUPLICATE_SAME_ACCESS | DUPLICATE_SAME_ATTRIBUTES 01051 ); 01052 if ( !NT_SUCCESS(Status) ) { 01053 return Status; 01054 } 01055 } 01056 01057 if ( ProcessParameters->StandardError ) { 01058 01059 Status = ZwDuplicateObject( 01060 ParentProcess, 01061 ProcessParameters->StandardError, 01062 ProcessInformation->Process, 01063 &ProcessParameters->StandardError, 01064 0L, 01065 0L, 01066 DUPLICATE_SAME_ACCESS | DUPLICATE_SAME_ATTRIBUTES 01067 ); 01068 if ( !NT_SUCCESS(Status) ) { 01069 return Status; 01070 } 01071 } 01072 01073 } finally { 01074 if ( !NT_SUCCESS(Status) ) { 01075 ZwClose( ProcessInformation->Process ); 01076 ZwClose( Section ); 01077 } 01078 } 01079 01080 // 01081 // Possibly reserve some address space in the new process 01082 // 01083 01084 if (ProcessInformation->ImageInformation.SubSystemType == IMAGE_SUBSYSTEM_NATIVE ) { 01085 if ( ProcessParameters->Flags & RTL_USER_PROC_RESERVE_1MB ) { 01086 01087 #if defined(_IA64_) 01088 Environment = (PVOID)(UADDRESS_BASE+4); 01089 #else 01090 Environment = (PVOID)(4); 01091 #endif 01092 RegionSize = (1024*1024)-(256); 01093 01094 Status = ZwAllocateVirtualMemory( ProcessInformation->Process, 01095 (PVOID *)&Environment, 01096 0, 01097 &RegionSize, 01098 MEM_RESERVE, 01099 PAGE_READWRITE 01100 ); 01101 if ( !NT_SUCCESS( Status ) ) { 01102 ZwClose( ProcessInformation->Process ); 01103 ZwClose( Section ); 01104 return( Status ); 01105 } 01106 } 01107 } 01108 01109 // 01110 // Allocate virtual memory in the new process and use NtWriteVirtualMemory 01111 // to write a copy of the process environment block into the address 01112 // space of the new process. Save the address of the allocated block in 01113 // the process parameter block so the new process can access it. 01114 // 01115 01116 if (s = (PWCHAR)ProcessParameters->Environment) { 01117 while (*s++) { 01118 while (*s++) { 01119 } 01120 } 01121 EnvironmentLength = (ULONG)(s - (PWCHAR)ProcessParameters->Environment) * sizeof(WCHAR); 01122 01123 Environment = NULL; 01124 RegionSize = EnvironmentLength; 01125 Status = ZwAllocateVirtualMemory( ProcessInformation->Process, 01126 (PVOID *)&Environment, 01127 0, 01128 &RegionSize, 01129 MEM_COMMIT, 01130 PAGE_READWRITE 01131 ); 01132 if ( !NT_SUCCESS( Status ) ) { 01133 ZwClose( ProcessInformation->Process ); 01134 ZwClose( Section ); 01135 return( Status ); 01136 } 01137 01138 Status = ZwWriteVirtualMemory( ProcessInformation->Process, 01139 Environment, 01140 ProcessParameters->Environment, 01141 EnvironmentLength, 01142 NULL 01143 ); 01144 if ( !NT_SUCCESS( Status ) ) { 01145 ZwClose( ProcessInformation->Process ); 01146 ZwClose( Section ); 01147 return( Status ); 01148 } 01149 01150 ProcessParameters->Environment = Environment; 01151 } 01152 01153 // 01154 // Allocate virtual memory in the new process and use NtWriteVirtualMemory 01155 // to write a copy of the process parameters block into the address 01156 // space of the new process. Set the initial parameter to the new thread 01157 // to be the address of the block in the new process's address space. 01158 // 01159 01160 Parameters = NULL; 01161 ParameterLength = ProcessParameters->MaximumLength; 01162 Status = ZwAllocateVirtualMemory( ProcessInformation->Process, 01163 (PVOID *)&Parameters, 01164 0, 01165 &ParameterLength, 01166 MEM_COMMIT, 01167 PAGE_READWRITE 01168 ); 01169 if ( !NT_SUCCESS( Status ) ) { 01170 ZwClose( ProcessInformation->Process ); 01171 ZwClose( Section ); 01172 return( Status ); 01173 } 01174 01175 Status = ZwWriteVirtualMemory( ProcessInformation->Process, 01176 Parameters, 01177 ProcessParameters, 01178 ProcessParameters->Length, 01179 NULL 01180 ); 01181 if ( !NT_SUCCESS( Status ) ) { 01182 ZwClose( ProcessInformation->Process ); 01183 ZwClose( Section ); 01184 return( Status ); 01185 } 01186 01187 Status = ZwWriteVirtualMemory( ProcessInformation->Process, 01188 &Peb->ProcessParameters, 01189 &Parameters, 01190 sizeof( Parameters ), 01191 NULL 01192 ); 01193 if ( !NT_SUCCESS( Status ) ) { 01194 ZwClose( ProcessInformation->Process ); 01195 ZwClose( Section ); 01196 return( Status ); 01197 } 01198 01199 // 01200 // Create a suspended thread in the new process. Specify the size and 01201 // position of the stack, along with the start address, initial parameter 01202 // and an SECURITY_DESCRIPTOR. The new thread will not have a name and its handle will 01203 // not be inherited by other processes. 01204 // 01205 01206 Status = RtlCreateUserThread( 01207 ProcessInformation->Process, 01208 ThreadSecurityDescriptor, 01209 TRUE, 01210 ProcessInformation->ImageInformation.ZeroBits, 01211 ProcessInformation->ImageInformation.MaximumStackSize, 01212 ProcessInformation->ImageInformation.CommittedStackSize, 01213 (PUSER_THREAD_START_ROUTINE) 01214 ProcessInformation->ImageInformation.TransferAddress, 01215 (PVOID)Peb, 01216 &ProcessInformation->Thread, 01217 &ProcessInformation->ClientId 01218 ); 01219 if ( !NT_SUCCESS( Status ) ) { 01220 ZwClose( ProcessInformation->Process ); 01221 ZwClose( Section ); 01222 return( Status ); 01223 } 01224 01225 // 01226 // Now close the section and file handles. The objects they represent 01227 // will not actually go away until the process is destroyed. 01228 // 01229 01230 ZwClose( Section ); 01231 01232 // 01233 // Return success status 01234 // 01235 01236 return( STATUS_SUCCESS ); 01237 } 01238 01239 01240 NTSTATUS 01241 RtlCreateUserThread( 01242 IN HANDLE Process, 01243 IN PSECURITY_DESCRIPTOR ThreadSecurityDescriptor OPTIONAL, 01244 IN BOOLEAN CreateSuspended, 01245 IN ULONG ZeroBits OPTIONAL, 01246 IN SIZE_T MaximumStackSize OPTIONAL, 01247 IN SIZE_T CommittedStackSize OPTIONAL, 01248 IN PUSER_THREAD_START_ROUTINE StartAddress, 01249 IN PVOID Parameter OPTIONAL, 01250 OUT PHANDLE Thread OPTIONAL, 01251 OUT PCLIENT_ID ClientId OPTIONAL 01252 ) 01253 01254 /*++ 01255 01256 Routine Description: 01257 01258 This function creates a user mode thread in a user process. The caller 01259 specifies the attributes of the new thread. A handle to the thread, along 01260 with its Client Id are returned to the caller. 01261 01262 Arguments: 01263 01264 Process - Handle to the target process in which to create the new thread. 01265 01266 ThreadSecurityDescriptor - An optional pointer to the Security Descriptor 01267 give to the new thread. 01268 01269 CreateSuspended - A boolean parameter that specifies whether or not the new 01270 thread is to be created suspended or not. If TRUE, the new thread 01271 will be created with an initial suspend count of 1. If FALSE then 01272 the new thread will be ready to run when this call returns. 01273 01274 ZeroBits - This parameter is passed to the virtual memory manager 01275 when the stack is allocated. Stacks are always allocated with the 01276 MEM_TOP_DOWN allocation attribute. 01277 01278 MaximumStackSize - This is the maximum size of the stack. This size 01279 will be rounded up to the next highest page boundary. If zero is 01280 specified, then the default size will be 64K bytes. 01281 01282 CommittedStackSize - This is the initial committed size of the stack. This 01283 size is rounded up to the next highest page boundary and then an 01284 additional page is added for the guard page. The resulting size 01285 will then be commited and the guard page protection initialized 01286 for the last committed page in the stack. 01287 01288 StartAddress - The initial starting address of the thread. 01289 01290 Parameter - An optional pointer to a 32-bit pointer parameter that is 01291 passed as a single argument to the procedure at the start address 01292 location. 01293 01294 Thread - An optional pointer that, if specified, points to a variable that 01295 will receive the handle of the new thread. 01296 01297 ClientId - An optional pointer that, if specified, points to a variable 01298 that will receive the Client Id of the new thread. 01299 01300 Return Value: 01301 01302 TBS 01303 01304 --*/ 01305 01306 { 01307 NTSTATUS Status; 01308 CONTEXT ThreadContext; 01309 OBJECT_ATTRIBUTES ObjectAttributes; 01310 INITIAL_TEB InitialTeb; 01311 HANDLE ThreadHandle; 01312 CLIENT_ID ThreadClientId; 01313 01314 // 01315 // Allocate a stack for this thread in the address space of the target 01316 // process. 01317 // 01318 01319 Status = RtlpCreateStack( Process, 01320 MaximumStackSize, 01321 CommittedStackSize, 01322 ZeroBits, 01323 &InitialTeb 01324 ); 01325 if ( !NT_SUCCESS( Status ) ) { 01326 return( Status ); 01327 } 01328 01329 // 01330 // Create an initial context for the new thread. 01331 // 01332 01333 01334 RtlInitializeContext( Process, 01335 &ThreadContext, 01336 Parameter, 01337 (PVOID)StartAddress, 01338 InitialTeb.StackBase 01339 ); 01340 01341 // 01342 // Now create a thread in the target process. The new thread will 01343 // not have a name and its handle will not be inherited by other 01344 // processes. 01345 // 01346 01347 InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, 01348 ThreadSecurityDescriptor ); 01349 Status = ZwCreateThread( &ThreadHandle, 01350 THREAD_ALL_ACCESS, 01351 &ObjectAttributes, 01352 Process, 01353 &ThreadClientId, 01354 &ThreadContext, 01355 &InitialTeb, 01356 CreateSuspended 01357 ); 01358 if (!NT_SUCCESS( Status )) { 01359 #if DBG 01360 DbgPrint( "NTRTL: RtlCreateUserThread Failed. NtCreateThread Status == %X\n", 01361 Status ); 01362 #endif // DBG 01363 RtlpFreeStack( Process, &InitialTeb ); 01364 } 01365 else { 01366 if (ARGUMENT_PRESENT( Thread )) { 01367 *Thread = ThreadHandle; 01368 } 01369 01370 if (ARGUMENT_PRESENT( ClientId )) { 01371 *ClientId = ThreadClientId; 01372 } 01373 01374 } 01375 01376 // 01377 // Return status 01378 // 01379 01380 return( Status ); 01381 } 01382 01383 01384 VOID 01385 RtlFreeUserThreadStack( 01386 HANDLE hProcess, 01387 HANDLE hThread 01388 ) 01389 { 01390 NTSTATUS Status; 01391 PTEB Teb; 01392 THREAD_BASIC_INFORMATION ThreadInfo; 01393 PVOID StackDeallocationBase; 01394 ULONG Length; 01395 SIZE_T Size; 01396 01397 Status = NtQueryInformationThread( hThread, 01398 ThreadBasicInformation, 01399 &ThreadInfo, 01400 sizeof( ThreadInfo ), 01401 NULL 01402 ); 01403 Teb = ThreadInfo.TebBaseAddress; 01404 if (!NT_SUCCESS( Status ) || !Teb) { 01405 return; 01406 } 01407 01408 Status = NtReadVirtualMemory( hProcess, 01409 &Teb->DeallocationStack, 01410 &StackDeallocationBase, 01411 sizeof( StackDeallocationBase ), 01412 &Length 01413 ); 01414 if (!NT_SUCCESS( Status ) || !StackDeallocationBase) { 01415 return; 01416 } 01417 01418 Size = 0; 01419 NtFreeVirtualMemory( hProcess, &StackDeallocationBase, &Size, MEM_RELEASE ); 01420 return; 01421 }

Generated on Sat May 15 19:41:41 2004 for test by doxygen 1.3.7