- Final ROSRTL removal patch. The next patch will remove the actual library and code.
- Changes:
- CreateProcess
* Cleanup creation of the initial thread using new utility functions and remove rosrtl
* Almost entirely rewrote the function to support features such as:
- SxS (locally only, patch will follow),
- SFP (SAFER) (locally only, patch will follow),
- DllPaths (locally only, patch will follow),
- Proper process environment/paramter block creation
- Proper console handle management (needs more work in kernel32/csr),
- Tokens/CreateProcessAsUser (locally only, patch will follow),
- Simpler code for path lookup, and more robust.
- Support for "auto-correction" (see Raymond Chen's blog)
- 16-bit/NE detection
- A variety of creation flags are now properly supported
- Added support for an undocumented-yet-known (see comment) shell flag
- Alert for flags we don't support yet
- Catch invalid flag combinations and other caller errors
- Improve and correct path searcing to use documented behaviours
- Created a multitude of helper functions to make the code easier to read
and allow them to be used for other apis as time goes on.
- BaseProcessStartup
* Call NtSetThreadInformation to let the Kernel know of the Thread's Start Address.
* Correct prototype of Thread Startup function for this case.
This fixes MANY things, some of which may not be evident, and possibly creates regressions which I have not yet seen but will try to correct. Some of these may be caused by the fact that I've seen code send CreateProcessW incorrect flags. Some things of note: DO NOT send partial names as "lpApplicationName". It's not supposed to work unless you're in the same current directory. Also, do NOT send CREATE_UNICODE_ENVIRONMENT if you don't have a unicode environement, and vice-versa. I've seen lots of code doing mistakes related to this. I hope you appreciate this patch and won't all jump on me for possbile regressions :(.
svn path=/trunk/; revision=16730
2005-07-26 04:14:10 +00:00
|
|
|
/*
|
1999-01-16 02:11:45 +00:00
|
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
|
|
* PROJECT: ReactOS system libraries
|
|
|
|
* FILE: lib/kernel32/thread/thread.c
|
|
|
|
* PURPOSE: Thread functions
|
- Final ROSRTL removal patch. The next patch will remove the actual library and code.
- Changes:
- CreateProcess
* Cleanup creation of the initial thread using new utility functions and remove rosrtl
* Almost entirely rewrote the function to support features such as:
- SxS (locally only, patch will follow),
- SFP (SAFER) (locally only, patch will follow),
- DllPaths (locally only, patch will follow),
- Proper process environment/paramter block creation
- Proper console handle management (needs more work in kernel32/csr),
- Tokens/CreateProcessAsUser (locally only, patch will follow),
- Simpler code for path lookup, and more robust.
- Support for "auto-correction" (see Raymond Chen's blog)
- 16-bit/NE detection
- A variety of creation flags are now properly supported
- Added support for an undocumented-yet-known (see comment) shell flag
- Alert for flags we don't support yet
- Catch invalid flag combinations and other caller errors
- Improve and correct path searcing to use documented behaviours
- Created a multitude of helper functions to make the code easier to read
and allow them to be used for other apis as time goes on.
- BaseProcessStartup
* Call NtSetThreadInformation to let the Kernel know of the Thread's Start Address.
* Correct prototype of Thread Startup function for this case.
This fixes MANY things, some of which may not be evident, and possibly creates regressions which I have not yet seen but will try to correct. Some of these may be caused by the fact that I've seen code send CreateProcessW incorrect flags. Some things of note: DO NOT send partial names as "lpApplicationName". It's not supposed to work unless you're in the same current directory. Also, do NOT send CREATE_UNICODE_ENVIRONMENT if you don't have a unicode environement, and vice-versa. I've seen lots of code doing mistakes related to this. I hope you appreciate this patch and won't all jump on me for possbile regressions :(.
svn path=/trunk/; revision=16730
2005-07-26 04:14:10 +00:00
|
|
|
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
|
|
|
|
* Ariadne ( ariadne@xs4all.nl)
|
2003-12-30 00:12:47 +00:00
|
|
|
*
|
1999-01-16 02:11:45 +00:00
|
|
|
*/
|
|
|
|
|
1999-05-29 00:15:17 +00:00
|
|
|
/* INCLUDES ******************************************************************/
|
|
|
|
|
2003-01-15 21:24:36 +00:00
|
|
|
#include <k32.h>
|
1999-01-16 02:11:45 +00:00
|
|
|
|
1999-12-13 22:04:41 +00:00
|
|
|
#define NDEBUG
|
2004-01-23 21:16:04 +00:00
|
|
|
#include "../include/debug.h"
|
1999-09-05 10:22:05 +00:00
|
|
|
|
1999-05-29 00:15:17 +00:00
|
|
|
/* FUNCTIONS *****************************************************************/
|
2005-06-20 04:07:19 +00:00
|
|
|
_SEH_FILTER(BaseThreadExceptionFilter)
|
1999-09-06 21:32:57 +00:00
|
|
|
{
|
2005-06-20 04:07:19 +00:00
|
|
|
EXCEPTION_POINTERS * ExceptionInfo = _SEH_GetExceptionPointers();
|
|
|
|
LONG ExceptionDisposition = EXCEPTION_EXECUTE_HANDLER;
|
2004-12-13 13:32:24 +00:00
|
|
|
|
|
|
|
if (GlobalTopLevelExceptionFilter != NULL)
|
|
|
|
{
|
|
|
|
_SEH_TRY
|
|
|
|
{
|
2005-06-20 04:07:19 +00:00
|
|
|
ExceptionDisposition = GlobalTopLevelExceptionFilter(ExceptionInfo);
|
2004-12-13 13:32:24 +00:00
|
|
|
}
|
|
|
|
_SEH_HANDLE
|
|
|
|
{
|
2005-06-20 04:07:19 +00:00
|
|
|
ExceptionDisposition = UnhandledExceptionFilter(ExceptionInfo);
|
2004-12-13 13:32:24 +00:00
|
|
|
}
|
|
|
|
_SEH_END;
|
|
|
|
}
|
|
|
|
|
2005-06-20 04:07:19 +00:00
|
|
|
return ExceptionDisposition;
|
2002-12-02 21:28:40 +00:00
|
|
|
}
|
1999-09-06 21:32:57 +00:00
|
|
|
|
2005-07-19 21:04:19 +00:00
|
|
|
__declspec(noreturn)
|
|
|
|
VOID
|
|
|
|
STDCALL
|
|
|
|
BaseThreadStartup(LPTHREAD_START_ROUTINE lpStartAddress,
|
|
|
|
LPVOID lpParameter)
|
2002-12-02 21:28:40 +00:00
|
|
|
{
|
2005-07-19 21:04:19 +00:00
|
|
|
volatile UINT uExitCode = 0;
|
2002-12-02 21:28:40 +00:00
|
|
|
|
2005-07-19 21:04:19 +00:00
|
|
|
/* Attempt to call the Thread Start Address */
|
|
|
|
_SEH_TRY
|
|
|
|
{
|
|
|
|
/* Get the exit code from the Thread Start */
|
|
|
|
uExitCode = (lpStartAddress)((PVOID)lpParameter);
|
|
|
|
}
|
|
|
|
_SEH_EXCEPT(BaseThreadExceptionFilter)
|
|
|
|
{
|
|
|
|
/* Get the Exit code from the SEH Handler */
|
|
|
|
uExitCode = _SEH_GetExceptionCode();
|
|
|
|
} _SEH_END;
|
2005-06-20 04:07:19 +00:00
|
|
|
|
2005-07-19 21:04:19 +00:00
|
|
|
/* Exit the Thread */
|
|
|
|
ExitThread(uExitCode);
|
1999-09-06 21:32:57 +00:00
|
|
|
}
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
- Final ROSRTL removal patch. The next patch will remove the actual library and code.
- Changes:
- CreateProcess
* Cleanup creation of the initial thread using new utility functions and remove rosrtl
* Almost entirely rewrote the function to support features such as:
- SxS (locally only, patch will follow),
- SFP (SAFER) (locally only, patch will follow),
- DllPaths (locally only, patch will follow),
- Proper process environment/paramter block creation
- Proper console handle management (needs more work in kernel32/csr),
- Tokens/CreateProcessAsUser (locally only, patch will follow),
- Simpler code for path lookup, and more robust.
- Support for "auto-correction" (see Raymond Chen's blog)
- 16-bit/NE detection
- A variety of creation flags are now properly supported
- Added support for an undocumented-yet-known (see comment) shell flag
- Alert for flags we don't support yet
- Catch invalid flag combinations and other caller errors
- Improve and correct path searcing to use documented behaviours
- Created a multitude of helper functions to make the code easier to read
and allow them to be used for other apis as time goes on.
- BaseProcessStartup
* Call NtSetThreadInformation to let the Kernel know of the Thread's Start Address.
* Correct prototype of Thread Startup function for this case.
This fixes MANY things, some of which may not be evident, and possibly creates regressions which I have not yet seen but will try to correct. Some of these may be caused by the fact that I've seen code send CreateProcessW incorrect flags. Some things of note: DO NOT send partial names as "lpApplicationName". It's not supposed to work unless you're in the same current directory. Also, do NOT send CREATE_UNICODE_ENVIRONMENT if you don't have a unicode environement, and vice-versa. I've seen lots of code doing mistakes related to this. I hope you appreciate this patch and won't all jump on me for possbile regressions :(.
svn path=/trunk/; revision=16730
2005-07-26 04:14:10 +00:00
|
|
|
HANDLE
|
|
|
|
STDCALL
|
|
|
|
CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes,
|
|
|
|
DWORD dwStackSize,
|
|
|
|
LPTHREAD_START_ROUTINE lpStartAddress,
|
|
|
|
LPVOID lpParameter,
|
|
|
|
DWORD dwCreationFlags,
|
|
|
|
LPDWORD lpThreadId)
|
1999-01-16 02:11:45 +00:00
|
|
|
{
|
- Final ROSRTL removal patch. The next patch will remove the actual library and code.
- Changes:
- CreateProcess
* Cleanup creation of the initial thread using new utility functions and remove rosrtl
* Almost entirely rewrote the function to support features such as:
- SxS (locally only, patch will follow),
- SFP (SAFER) (locally only, patch will follow),
- DllPaths (locally only, patch will follow),
- Proper process environment/paramter block creation
- Proper console handle management (needs more work in kernel32/csr),
- Tokens/CreateProcessAsUser (locally only, patch will follow),
- Simpler code for path lookup, and more robust.
- Support for "auto-correction" (see Raymond Chen's blog)
- 16-bit/NE detection
- A variety of creation flags are now properly supported
- Added support for an undocumented-yet-known (see comment) shell flag
- Alert for flags we don't support yet
- Catch invalid flag combinations and other caller errors
- Improve and correct path searcing to use documented behaviours
- Created a multitude of helper functions to make the code easier to read
and allow them to be used for other apis as time goes on.
- BaseProcessStartup
* Call NtSetThreadInformation to let the Kernel know of the Thread's Start Address.
* Correct prototype of Thread Startup function for this case.
This fixes MANY things, some of which may not be evident, and possibly creates regressions which I have not yet seen but will try to correct. Some of these may be caused by the fact that I've seen code send CreateProcessW incorrect flags. Some things of note: DO NOT send partial names as "lpApplicationName". It's not supposed to work unless you're in the same current directory. Also, do NOT send CREATE_UNICODE_ENVIRONMENT if you don't have a unicode environement, and vice-versa. I've seen lots of code doing mistakes related to this. I hope you appreciate this patch and won't all jump on me for possbile regressions :(.
svn path=/trunk/; revision=16730
2005-07-26 04:14:10 +00:00
|
|
|
/* Act as if we're going to create a remote thread in ourselves */
|
|
|
|
return CreateRemoteThread(NtCurrentProcess(),
|
|
|
|
lpThreadAttributes,
|
|
|
|
dwStackSize,
|
|
|
|
lpStartAddress,
|
|
|
|
lpParameter,
|
|
|
|
dwCreationFlags,
|
|
|
|
lpThreadId);
|
1999-01-16 02:11:45 +00:00
|
|
|
}
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
- Final ROSRTL removal patch. The next patch will remove the actual library and code.
- Changes:
- CreateProcess
* Cleanup creation of the initial thread using new utility functions and remove rosrtl
* Almost entirely rewrote the function to support features such as:
- SxS (locally only, patch will follow),
- SFP (SAFER) (locally only, patch will follow),
- DllPaths (locally only, patch will follow),
- Proper process environment/paramter block creation
- Proper console handle management (needs more work in kernel32/csr),
- Tokens/CreateProcessAsUser (locally only, patch will follow),
- Simpler code for path lookup, and more robust.
- Support for "auto-correction" (see Raymond Chen's blog)
- 16-bit/NE detection
- A variety of creation flags are now properly supported
- Added support for an undocumented-yet-known (see comment) shell flag
- Alert for flags we don't support yet
- Catch invalid flag combinations and other caller errors
- Improve and correct path searcing to use documented behaviours
- Created a multitude of helper functions to make the code easier to read
and allow them to be used for other apis as time goes on.
- BaseProcessStartup
* Call NtSetThreadInformation to let the Kernel know of the Thread's Start Address.
* Correct prototype of Thread Startup function for this case.
This fixes MANY things, some of which may not be evident, and possibly creates regressions which I have not yet seen but will try to correct. Some of these may be caused by the fact that I've seen code send CreateProcessW incorrect flags. Some things of note: DO NOT send partial names as "lpApplicationName". It's not supposed to work unless you're in the same current directory. Also, do NOT send CREATE_UNICODE_ENVIRONMENT if you don't have a unicode environement, and vice-versa. I've seen lots of code doing mistakes related to this. I hope you appreciate this patch and won't all jump on me for possbile regressions :(.
svn path=/trunk/; revision=16730
2005-07-26 04:14:10 +00:00
|
|
|
HANDLE
|
|
|
|
STDCALL
|
|
|
|
CreateRemoteThread(HANDLE hProcess,
|
|
|
|
LPSECURITY_ATTRIBUTES lpThreadAttributes,
|
|
|
|
DWORD dwStackSize,
|
|
|
|
LPTHREAD_START_ROUTINE lpStartAddress,
|
|
|
|
LPVOID lpParameter,
|
|
|
|
DWORD dwCreationFlags,
|
|
|
|
LPDWORD lpThreadId)
|
2001-08-03 17:21:38 +00:00
|
|
|
{
|
- Final ROSRTL removal patch. The next patch will remove the actual library and code.
- Changes:
- CreateProcess
* Cleanup creation of the initial thread using new utility functions and remove rosrtl
* Almost entirely rewrote the function to support features such as:
- SxS (locally only, patch will follow),
- SFP (SAFER) (locally only, patch will follow),
- DllPaths (locally only, patch will follow),
- Proper process environment/paramter block creation
- Proper console handle management (needs more work in kernel32/csr),
- Tokens/CreateProcessAsUser (locally only, patch will follow),
- Simpler code for path lookup, and more robust.
- Support for "auto-correction" (see Raymond Chen's blog)
- 16-bit/NE detection
- A variety of creation flags are now properly supported
- Added support for an undocumented-yet-known (see comment) shell flag
- Alert for flags we don't support yet
- Catch invalid flag combinations and other caller errors
- Improve and correct path searcing to use documented behaviours
- Created a multitude of helper functions to make the code easier to read
and allow them to be used for other apis as time goes on.
- BaseProcessStartup
* Call NtSetThreadInformation to let the Kernel know of the Thread's Start Address.
* Correct prototype of Thread Startup function for this case.
This fixes MANY things, some of which may not be evident, and possibly creates regressions which I have not yet seen but will try to correct. Some of these may be caused by the fact that I've seen code send CreateProcessW incorrect flags. Some things of note: DO NOT send partial names as "lpApplicationName". It's not supposed to work unless you're in the same current directory. Also, do NOT send CREATE_UNICODE_ENVIRONMENT if you don't have a unicode environement, and vice-versa. I've seen lots of code doing mistakes related to this. I hope you appreciate this patch and won't all jump on me for possbile regressions :(.
svn path=/trunk/; revision=16730
2005-07-26 04:14:10 +00:00
|
|
|
NTSTATUS Status;
|
|
|
|
INITIAL_TEB InitialTeb;
|
|
|
|
CONTEXT Context;
|
|
|
|
CLIENT_ID ClientId;
|
|
|
|
OBJECT_ATTRIBUTES LocalObjectAttributes;
|
|
|
|
POBJECT_ATTRIBUTES ObjectAttributes;
|
|
|
|
HANDLE hThread;
|
|
|
|
ULONG Dummy;
|
|
|
|
|
|
|
|
DPRINT("CreateRemoteThread: hProcess: %ld dwStackSize: %ld lpStartAddress"
|
|
|
|
": %p lpParameter: %lx, dwCreationFlags: %lx\n", hProcess,
|
|
|
|
dwStackSize, lpStartAddress, lpParameter, dwCreationFlags);
|
|
|
|
|
|
|
|
/* Clear the Context */
|
|
|
|
RtlZeroMemory(&Context, sizeof(CONTEXT));
|
|
|
|
|
|
|
|
/* Write PID */
|
|
|
|
ClientId.UniqueProcess = hProcess;
|
|
|
|
|
|
|
|
/* Create the Stack */
|
|
|
|
Status = BasepCreateStack(hProcess,
|
|
|
|
dwStackSize,
|
|
|
|
dwCreationFlags & STACK_SIZE_PARAM_IS_A_RESERVATION ?
|
|
|
|
dwStackSize : 0,
|
|
|
|
&InitialTeb);
|
|
|
|
if(!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
SetLastErrorByStatus(Status);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Create Initial Context */
|
|
|
|
BasepInitializeContext(&Context,
|
|
|
|
lpParameter,
|
|
|
|
lpStartAddress,
|
|
|
|
InitialTeb.StackBase,
|
|
|
|
1);
|
|
|
|
|
|
|
|
/* initialize the attributes for the thread object */
|
|
|
|
ObjectAttributes = BasepConvertObjectAttributes(&LocalObjectAttributes,
|
|
|
|
lpThreadAttributes,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
/* Create the Kernel Thread Object */
|
|
|
|
Status = NtCreateThread(&hThread,
|
|
|
|
THREAD_ALL_ACCESS,
|
|
|
|
ObjectAttributes,
|
|
|
|
hProcess,
|
|
|
|
&ClientId,
|
|
|
|
&Context,
|
|
|
|
&InitialTeb,
|
|
|
|
TRUE);
|
|
|
|
if(!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
BasepFreeStack(hProcess, &InitialTeb);
|
|
|
|
SetLastErrorByStatus(Status);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef SXS_SUPPORT_ENABLED
|
|
|
|
/* Are we in the same process? */
|
|
|
|
if (Process = NtCurrentProcess())
|
|
|
|
{
|
|
|
|
PTEB Teb;
|
|
|
|
PVOID ActivationContextStack;
|
|
|
|
PTHREAD_BASIC_INFORMATION ThreadBasicInfo;
|
|
|
|
PACTIVATION_CONTEXT_BASIC_INFORMATION ActivationCtxInfo;
|
|
|
|
ULONG_PTR Cookie;
|
|
|
|
|
|
|
|
/* Get the TEB */
|
|
|
|
Status = NtQueryInformationThread(hThread,
|
|
|
|
ThreadBasicIformation,
|
|
|
|
&ThreadBasicInfo,
|
|
|
|
sizeof(ThreadBasicInfo),
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
/* Allocate the Activation Context Stack */
|
|
|
|
Status = RtlAllocateActivationContextStack(&ActivationContextStack);
|
|
|
|
Teb = ThreadBasicInfo.TebBaseAddress;
|
|
|
|
|
|
|
|
/* Save it */
|
|
|
|
Teb->ActivationContextStackPointer = ActivationContextStack;
|
|
|
|
|
|
|
|
/* Query the Context */
|
|
|
|
Status = RtlQueryInformationActivationContext(1,
|
|
|
|
0,
|
|
|
|
NULL,
|
|
|
|
ActivationContextBasicInformation,
|
|
|
|
&ActivationCtxInfo,
|
|
|
|
sizeof(ActivationCtxInfo),
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
/* Does it need to be activated? */
|
|
|
|
if (!ActivationCtxInfo.hActCtx)
|
|
|
|
{
|
|
|
|
/* Activate it */
|
|
|
|
Status = RtlActivateActivationContextEx(1,
|
|
|
|
Teb,
|
|
|
|
ActivationCtxInfo.hActCtx,
|
|
|
|
&Cookie);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* FIXME: Notify CSR */
|
|
|
|
|
|
|
|
/* Success */
|
|
|
|
if(lpThreadId) *lpThreadId = (DWORD)ClientId.UniqueThread;
|
|
|
|
|
|
|
|
/* Resume it if asked */
|
|
|
|
if (!(dwCreationFlags & CREATE_SUSPENDED))
|
|
|
|
{
|
|
|
|
NtResumeThread(hThread, &Dummy);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Return handle to thread */
|
|
|
|
return hThread;
|
|
|
|
}
|
2005-05-09 01:46:57 +00:00
|
|
|
|
- Final ROSRTL removal patch. The next patch will remove the actual library and code.
- Changes:
- CreateProcess
* Cleanup creation of the initial thread using new utility functions and remove rosrtl
* Almost entirely rewrote the function to support features such as:
- SxS (locally only, patch will follow),
- SFP (SAFER) (locally only, patch will follow),
- DllPaths (locally only, patch will follow),
- Proper process environment/paramter block creation
- Proper console handle management (needs more work in kernel32/csr),
- Tokens/CreateProcessAsUser (locally only, patch will follow),
- Simpler code for path lookup, and more robust.
- Support for "auto-correction" (see Raymond Chen's blog)
- 16-bit/NE detection
- A variety of creation flags are now properly supported
- Added support for an undocumented-yet-known (see comment) shell flag
- Alert for flags we don't support yet
- Catch invalid flag combinations and other caller errors
- Improve and correct path searcing to use documented behaviours
- Created a multitude of helper functions to make the code easier to read
and allow them to be used for other apis as time goes on.
- BaseProcessStartup
* Call NtSetThreadInformation to let the Kernel know of the Thread's Start Address.
* Correct prototype of Thread Startup function for this case.
This fixes MANY things, some of which may not be evident, and possibly creates regressions which I have not yet seen but will try to correct. Some of these may be caused by the fact that I've seen code send CreateProcessW incorrect flags. Some things of note: DO NOT send partial names as "lpApplicationName". It's not supposed to work unless you're in the same current directory. Also, do NOT send CREATE_UNICODE_ENVIRONMENT if you don't have a unicode environement, and vice-versa. I've seen lots of code doing mistakes related to this. I hope you appreciate this patch and won't all jump on me for possbile regressions :(.
svn path=/trunk/; revision=16730
2005-07-26 04:14:10 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
VOID
|
|
|
|
STDCALL
|
|
|
|
ExitThread(DWORD uExitCode)
|
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
|
|
BOOLEAN LastThread;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Terminate process if this is the last thread
|
|
|
|
* of the current process
|
|
|
|
*/
|
|
|
|
Status = NtQueryInformationThread(NtCurrentThread(),
|
|
|
|
ThreadAmILastThread,
|
|
|
|
&LastThread,
|
|
|
|
sizeof(BOOLEAN),
|
|
|
|
NULL);
|
|
|
|
if (NT_SUCCESS(Status) && LastThread)
|
|
|
|
{
|
|
|
|
/* Exit the Process */
|
|
|
|
ExitProcess(uExitCode);
|
|
|
|
}
|
My biggest commit so far (everything compiles and apparently runs fine):
- replaced DWORD with ULONG in a couple of places
- replaced some ULONGs with LONGs in the KD GDB stub
- replaced INITIAL_TEB with USER_STACK, as per Nebbet's book, to support both fixed size and expandable stacks
- added InterlockedExchangePointer
- added the ASM_BREAKPOINT macro as the architecture-dependent assembler code to raise a breakpoint exception
- corrected definitions of INT, LONG, DWORD, UINT, ULONG and ULONG32
- corrected IoSetCancelRoutine to use InterlockedExchangePointer
- corrected definition of NtCurrentTeb and NtCurrentPeb
- corrected DbgBreakPoint and DbgUserBreakPoint not to set up a stack frame (temporary fix with inline assembler - why doesn't GCC understand __declspec(naked)?)
- corrected various calls to Interlocked* functions to cast OUT operands to LONG *
- corrected various printf format strings
- corrected DbgUiIssueRemoteBreakin to use the smallest possible stack (this is what started everything)
- removed a DPRINT that accessed pageable memory at non-PASSIVE_LEVEL IRQL
- beautified CreateProcessA (another temporary fix - all the new functions will be isolated in the upcoming stand-alone RTL)
- prefixed LdrInitializeThunk with a nop that can be overwritten with a breakpoint for debugging purposes (temporary debugging aid until we have user-mode debugger support). Will add support for this to the breakin utility soon
- thread creation code rewritten from scratch (some glitches documented inline, but works fine)
- thread creation code now duplicated just twice, as opposed to five times (temporary fix - three new, non standard functions have been exported from NTDLL.DLL, will fix later)
svn path=/trunk/; revision=4595
2003-04-26 23:13:33 +00:00
|
|
|
|
- Final ROSRTL removal patch. The next patch will remove the actual library and code.
- Changes:
- CreateProcess
* Cleanup creation of the initial thread using new utility functions and remove rosrtl
* Almost entirely rewrote the function to support features such as:
- SxS (locally only, patch will follow),
- SFP (SAFER) (locally only, patch will follow),
- DllPaths (locally only, patch will follow),
- Proper process environment/paramter block creation
- Proper console handle management (needs more work in kernel32/csr),
- Tokens/CreateProcessAsUser (locally only, patch will follow),
- Simpler code for path lookup, and more robust.
- Support for "auto-correction" (see Raymond Chen's blog)
- 16-bit/NE detection
- A variety of creation flags are now properly supported
- Added support for an undocumented-yet-known (see comment) shell flag
- Alert for flags we don't support yet
- Catch invalid flag combinations and other caller errors
- Improve and correct path searcing to use documented behaviours
- Created a multitude of helper functions to make the code easier to read
and allow them to be used for other apis as time goes on.
- BaseProcessStartup
* Call NtSetThreadInformation to let the Kernel know of the Thread's Start Address.
* Correct prototype of Thread Startup function for this case.
This fixes MANY things, some of which may not be evident, and possibly creates regressions which I have not yet seen but will try to correct. Some of these may be caused by the fact that I've seen code send CreateProcessW incorrect flags. Some things of note: DO NOT send partial names as "lpApplicationName". It's not supposed to work unless you're in the same current directory. Also, do NOT send CREATE_UNICODE_ENVIRONMENT if you don't have a unicode environement, and vice-versa. I've seen lots of code doing mistakes related to this. I hope you appreciate this patch and won't all jump on me for possbile regressions :(.
svn path=/trunk/; revision=16730
2005-07-26 04:14:10 +00:00
|
|
|
/* Notify DLLs and TLS Callbacks of termination */
|
|
|
|
LdrShutdownThread();
|
|
|
|
|
|
|
|
/* Tell the Kernel to free the Stack */
|
|
|
|
NtCurrentTeb()->FreeStackOnTermination = TRUE;
|
|
|
|
NtTerminateThread(NULL, uExitCode);
|
|
|
|
|
|
|
|
/* We will never reach this place. This silences the compiler */
|
|
|
|
ExitThread(uExitCode);
|
1999-01-16 02:11:45 +00:00
|
|
|
}
|
|
|
|
|
2004-07-30 19:18:39 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
HANDLE
|
|
|
|
STDCALL
|
|
|
|
OpenThread(
|
|
|
|
DWORD dwDesiredAccess,
|
|
|
|
BOOL bInheritHandle,
|
|
|
|
DWORD dwThreadId
|
|
|
|
)
|
|
|
|
{
|
|
|
|
NTSTATUS errCode;
|
|
|
|
HANDLE ThreadHandle;
|
|
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
|
|
CLIENT_ID ClientId ;
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2005-08-07 21:45:12 +00:00
|
|
|
ClientId.UniqueProcess = 0;
|
2004-07-30 19:18:39 +00:00
|
|
|
ClientId.UniqueThread = (HANDLE)dwThreadId;
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2004-10-24 12:16:54 +00:00
|
|
|
InitializeObjectAttributes (&ObjectAttributes,
|
|
|
|
NULL,
|
|
|
|
(bInheritHandle ? OBJ_INHERIT : 0),
|
|
|
|
NULL,
|
|
|
|
NULL);
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2004-07-30 19:18:39 +00:00
|
|
|
errCode = NtOpenThread(&ThreadHandle,
|
|
|
|
dwDesiredAccess,
|
|
|
|
&ObjectAttributes,
|
|
|
|
&ClientId);
|
|
|
|
if (!NT_SUCCESS(errCode))
|
|
|
|
{
|
|
|
|
SetLastErrorByStatus (errCode);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return ThreadHandle;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2001-08-03 17:21:38 +00:00
|
|
|
PTEB
|
|
|
|
GetTeb(VOID)
|
1999-01-16 02:11:45 +00:00
|
|
|
{
|
2001-08-03 17:21:38 +00:00
|
|
|
return(NtCurrentTeb());
|
1999-01-16 02:11:45 +00:00
|
|
|
}
|
|
|
|
|
2002-12-02 21:28:40 +00:00
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2004-01-23 21:16:04 +00:00
|
|
|
BOOL STDCALL
|
2001-08-03 17:21:38 +00:00
|
|
|
SwitchToThread(VOID)
|
1999-01-16 02:11:45 +00:00
|
|
|
{
|
2005-03-26 21:16:42 +00:00
|
|
|
NTSTATUS Status;
|
|
|
|
Status = NtYieldExecution();
|
|
|
|
return Status != STATUS_NO_YIELD_PERFORMED;
|
1999-01-16 02:11:45 +00:00
|
|
|
}
|
|
|
|
|
2002-12-02 21:28:40 +00:00
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2001-08-03 17:21:38 +00:00
|
|
|
DWORD STDCALL
|
2002-12-02 21:28:40 +00:00
|
|
|
GetCurrentThreadId(VOID)
|
1999-01-16 02:11:45 +00:00
|
|
|
{
|
2002-12-02 21:28:40 +00:00
|
|
|
return((DWORD)(NtCurrentTeb()->Cid).UniqueThread);
|
1999-01-16 02:11:45 +00:00
|
|
|
}
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2004-01-23 21:16:04 +00:00
|
|
|
BOOL STDCALL
|
2002-12-02 21:28:40 +00:00
|
|
|
GetThreadTimes(HANDLE hThread,
|
|
|
|
LPFILETIME lpCreationTime,
|
|
|
|
LPFILETIME lpExitTime,
|
|
|
|
LPFILETIME lpKernelTime,
|
|
|
|
LPFILETIME lpUserTime)
|
1999-01-16 02:11:45 +00:00
|
|
|
{
|
2003-01-22 02:24:36 +00:00
|
|
|
KERNEL_USER_TIMES KernelUserTimes;
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
Status = NtQueryInformationThread(hThread,
|
|
|
|
ThreadTimes,
|
|
|
|
&KernelUserTimes,
|
|
|
|
sizeof(KERNEL_USER_TIMES),
|
2004-09-24 20:55:58 +00:00
|
|
|
NULL);
|
2003-01-22 02:24:36 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
SetLastErrorByStatus(Status);
|
|
|
|
return(FALSE);
|
|
|
|
}
|
|
|
|
|
2004-09-19 12:45:55 +00:00
|
|
|
lpCreationTime->dwLowDateTime = KernelUserTimes.CreateTime.u.LowPart;
|
|
|
|
lpCreationTime->dwHighDateTime = KernelUserTimes.CreateTime.u.HighPart;
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2004-09-19 12:45:55 +00:00
|
|
|
lpExitTime->dwLowDateTime = KernelUserTimes.ExitTime.u.LowPart;
|
|
|
|
lpExitTime->dwHighDateTime = KernelUserTimes.ExitTime.u.HighPart;
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2004-09-19 12:45:55 +00:00
|
|
|
lpKernelTime->dwLowDateTime = KernelUserTimes.KernelTime.u.LowPart;
|
|
|
|
lpKernelTime->dwHighDateTime = KernelUserTimes.KernelTime.u.HighPart;
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2004-09-19 12:45:55 +00:00
|
|
|
lpUserTime->dwLowDateTime = KernelUserTimes.UserTime.u.LowPart;
|
|
|
|
lpUserTime->dwHighDateTime = KernelUserTimes.UserTime.u.HighPart;
|
2003-01-22 02:24:36 +00:00
|
|
|
|
|
|
|
return(TRUE);
|
1999-01-16 02:11:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2004-01-23 21:16:04 +00:00
|
|
|
BOOL STDCALL
|
2002-12-02 21:28:40 +00:00
|
|
|
GetThreadContext(HANDLE hThread,
|
|
|
|
LPCONTEXT lpContext)
|
1999-01-16 02:11:45 +00:00
|
|
|
{
|
2002-12-02 21:28:40 +00:00
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
Status = NtGetContextThread(hThread,
|
|
|
|
lpContext);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
SetLastErrorByStatus(Status);
|
|
|
|
return(FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
return(TRUE);
|
1999-01-16 02:11:45 +00:00
|
|
|
}
|
|
|
|
|
2002-12-02 21:28:40 +00:00
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2004-01-23 21:16:04 +00:00
|
|
|
BOOL STDCALL
|
2002-12-02 21:28:40 +00:00
|
|
|
SetThreadContext(HANDLE hThread,
|
|
|
|
CONST CONTEXT *lpContext)
|
1999-01-16 02:11:45 +00:00
|
|
|
{
|
2002-12-02 21:28:40 +00:00
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
Status = NtSetContextThread(hThread,
|
|
|
|
(void *)lpContext);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
SetLastErrorByStatus(Status);
|
|
|
|
return(FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
return(TRUE);
|
1999-01-16 02:11:45 +00:00
|
|
|
}
|
|
|
|
|
2002-12-02 21:28:40 +00:00
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2004-01-23 21:16:04 +00:00
|
|
|
BOOL STDCALL
|
2002-12-02 21:28:40 +00:00
|
|
|
GetExitCodeThread(HANDLE hThread,
|
|
|
|
LPDWORD lpExitCode)
|
1999-01-16 02:11:45 +00:00
|
|
|
{
|
2002-12-02 21:28:40 +00:00
|
|
|
THREAD_BASIC_INFORMATION ThreadBasic;
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
Status = NtQueryInformationThread(hThread,
|
|
|
|
ThreadBasicInformation,
|
|
|
|
&ThreadBasic,
|
|
|
|
sizeof(THREAD_BASIC_INFORMATION),
|
2004-09-24 20:55:58 +00:00
|
|
|
NULL);
|
2002-12-02 21:28:40 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
SetLastErrorByStatus(Status);
|
|
|
|
return(FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(lpExitCode, &ThreadBasic.ExitStatus, sizeof(DWORD));
|
|
|
|
|
|
|
|
return(TRUE);
|
1999-01-16 02:11:45 +00:00
|
|
|
}
|
|
|
|
|
2002-12-02 21:28:40 +00:00
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2002-12-02 21:28:40 +00:00
|
|
|
DWORD STDCALL
|
|
|
|
ResumeThread(HANDLE hThread)
|
1999-01-16 02:11:45 +00:00
|
|
|
{
|
2002-12-02 21:28:40 +00:00
|
|
|
ULONG PreviousResumeCount;
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
Status = NtResumeThread(hThread,
|
|
|
|
&PreviousResumeCount);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
SetLastErrorByStatus(Status);
|
|
|
|
return(-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
return(PreviousResumeCount);
|
1999-01-16 02:11:45 +00:00
|
|
|
}
|
|
|
|
|
1999-10-02 20:20:44 +00:00
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2004-01-23 21:16:04 +00:00
|
|
|
BOOL STDCALL
|
2002-12-02 21:28:40 +00:00
|
|
|
TerminateThread(HANDLE hThread,
|
|
|
|
DWORD dwExitCode)
|
1999-10-02 20:20:44 +00:00
|
|
|
{
|
2002-12-02 21:28:40 +00:00
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
if (0 == hThread)
|
2001-08-15 20:35:39 +00:00
|
|
|
{
|
2002-12-02 21:28:40 +00:00
|
|
|
SetLastError(ERROR_INVALID_HANDLE);
|
|
|
|
return(FALSE);
|
2001-08-15 20:35:39 +00:00
|
|
|
}
|
2002-12-02 21:28:40 +00:00
|
|
|
|
|
|
|
Status = NtTerminateThread(hThread,
|
|
|
|
dwExitCode);
|
|
|
|
if (!NT_SUCCESS(Status))
|
2001-08-15 20:35:39 +00:00
|
|
|
{
|
2002-12-02 21:28:40 +00:00
|
|
|
SetLastErrorByStatus(Status);
|
|
|
|
return(FALSE);
|
2001-08-15 20:35:39 +00:00
|
|
|
}
|
2002-12-02 21:28:40 +00:00
|
|
|
|
|
|
|
return(TRUE);
|
1999-10-02 20:20:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2002-12-02 21:28:40 +00:00
|
|
|
DWORD STDCALL
|
|
|
|
SuspendThread(HANDLE hThread)
|
1999-01-16 02:11:45 +00:00
|
|
|
{
|
2002-12-02 21:28:40 +00:00
|
|
|
ULONG PreviousSuspendCount;
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
Status = NtSuspendThread(hThread,
|
|
|
|
&PreviousSuspendCount);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
SetLastErrorByStatus(Status);
|
|
|
|
return(-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
return(PreviousSuspendCount);
|
1999-01-16 02:11:45 +00:00
|
|
|
}
|
|
|
|
|
2002-12-02 21:28:40 +00:00
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2002-12-02 21:28:40 +00:00
|
|
|
DWORD STDCALL
|
|
|
|
SetThreadAffinityMask(HANDLE hThread,
|
|
|
|
DWORD dwThreadAffinityMask)
|
1999-01-16 02:11:45 +00:00
|
|
|
{
|
2002-12-02 21:28:40 +00:00
|
|
|
THREAD_BASIC_INFORMATION ThreadBasic;
|
|
|
|
KAFFINITY AffinityMask;
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
AffinityMask = (KAFFINITY)dwThreadAffinityMask;
|
|
|
|
|
|
|
|
Status = NtQueryInformationThread(hThread,
|
|
|
|
ThreadBasicInformation,
|
|
|
|
&ThreadBasic,
|
|
|
|
sizeof(THREAD_BASIC_INFORMATION),
|
2004-09-24 20:55:58 +00:00
|
|
|
NULL);
|
2002-12-02 21:28:40 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
SetLastErrorByStatus(Status);
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = NtSetInformationThread(hThread,
|
|
|
|
ThreadAffinityMask,
|
|
|
|
&AffinityMask,
|
|
|
|
sizeof(KAFFINITY));
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
SetLastErrorByStatus(Status);
|
|
|
|
|
|
|
|
return(ThreadBasic.AffinityMask);
|
1999-01-16 02:11:45 +00:00
|
|
|
}
|
|
|
|
|
2002-12-02 21:28:40 +00:00
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2004-01-23 21:16:04 +00:00
|
|
|
BOOL STDCALL
|
2002-12-02 21:28:40 +00:00
|
|
|
SetThreadPriority(HANDLE hThread,
|
|
|
|
int nPriority)
|
1999-01-16 02:11:45 +00:00
|
|
|
{
|
2003-04-30 22:00:41 +00:00
|
|
|
ULONG Prio = nPriority;
|
2002-12-02 21:28:40 +00:00
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
Status = NtSetInformationThread(hThread,
|
2003-04-30 22:00:41 +00:00
|
|
|
ThreadBasePriority,
|
|
|
|
&Prio,
|
|
|
|
sizeof(ULONG));
|
|
|
|
|
2002-12-02 21:28:40 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
SetLastErrorByStatus(Status);
|
|
|
|
return(FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
return(TRUE);
|
1999-01-16 02:11:45 +00:00
|
|
|
}
|
|
|
|
|
2002-12-02 21:28:40 +00:00
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2002-12-02 21:28:40 +00:00
|
|
|
int STDCALL
|
|
|
|
GetThreadPriority(HANDLE hThread)
|
1999-01-16 02:11:45 +00:00
|
|
|
{
|
2002-12-02 21:28:40 +00:00
|
|
|
THREAD_BASIC_INFORMATION ThreadBasic;
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
Status = NtQueryInformationThread(hThread,
|
|
|
|
ThreadBasicInformation,
|
|
|
|
&ThreadBasic,
|
|
|
|
sizeof(THREAD_BASIC_INFORMATION),
|
2004-09-24 20:55:58 +00:00
|
|
|
NULL);
|
2002-12-02 21:28:40 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
SetLastErrorByStatus(Status);
|
|
|
|
return(THREAD_PRIORITY_ERROR_RETURN);
|
|
|
|
}
|
|
|
|
|
|
|
|
return(ThreadBasic.BasePriority);
|
1999-01-16 02:11:45 +00:00
|
|
|
}
|
2000-04-14 01:50:38 +00:00
|
|
|
|
2003-01-22 02:24:36 +00:00
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2004-01-23 21:16:04 +00:00
|
|
|
BOOL STDCALL
|
2003-01-22 02:24:36 +00:00
|
|
|
GetThreadPriorityBoost(IN HANDLE hThread,
|
|
|
|
OUT PBOOL pDisablePriorityBoost)
|
|
|
|
{
|
|
|
|
ULONG PriorityBoost;
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
Status = NtQueryInformationThread(hThread,
|
|
|
|
ThreadPriorityBoost,
|
|
|
|
&PriorityBoost,
|
|
|
|
sizeof(ULONG),
|
2004-09-24 20:55:58 +00:00
|
|
|
NULL);
|
2003-01-22 02:24:36 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
SetLastErrorByStatus(Status);
|
|
|
|
return(FALSE);
|
|
|
|
}
|
|
|
|
|
2004-01-23 21:16:04 +00:00
|
|
|
*pDisablePriorityBoost = !((BOOL)PriorityBoost);
|
2003-01-22 02:24:36 +00:00
|
|
|
|
|
|
|
return(TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2004-01-23 21:16:04 +00:00
|
|
|
BOOL STDCALL
|
2003-01-22 02:24:36 +00:00
|
|
|
SetThreadPriorityBoost(IN HANDLE hThread,
|
2004-01-23 21:16:04 +00:00
|
|
|
IN BOOL bDisablePriorityBoost)
|
2003-01-22 02:24:36 +00:00
|
|
|
{
|
|
|
|
ULONG PriorityBoost;
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
PriorityBoost = (ULONG)!bDisablePriorityBoost;
|
|
|
|
|
|
|
|
Status = NtSetInformationThread(hThread,
|
|
|
|
ThreadPriorityBoost,
|
|
|
|
&PriorityBoost,
|
|
|
|
sizeof(ULONG));
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
SetLastErrorByStatus(Status);
|
|
|
|
return(FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
return(TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2004-01-23 21:16:04 +00:00
|
|
|
BOOL STDCALL
|
2003-01-22 02:24:36 +00:00
|
|
|
GetThreadSelectorEntry(IN HANDLE hThread,
|
|
|
|
IN DWORD dwSelector,
|
|
|
|
OUT LPLDT_ENTRY lpSelectorEntry)
|
|
|
|
{
|
2004-09-24 20:55:58 +00:00
|
|
|
DESCRIPTOR_TABLE_ENTRY DescriptionTableEntry;
|
|
|
|
NTSTATUS Status;
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2004-09-24 20:55:58 +00:00
|
|
|
DescriptionTableEntry.Selector = dwSelector;
|
|
|
|
Status = NtQueryInformationThread(hThread,
|
|
|
|
ThreadDescriptorTableEntry,
|
|
|
|
&DescriptionTableEntry,
|
|
|
|
sizeof(DESCRIPTOR_TABLE_ENTRY),
|
|
|
|
NULL);
|
|
|
|
if(!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
SetLastErrorByStatus(Status);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
*lpSelectorEntry = DescriptionTableEntry.Descriptor;
|
|
|
|
return TRUE;
|
2003-01-22 02:24:36 +00:00
|
|
|
}
|
|
|
|
|
2003-02-03 14:20:24 +00:00
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2004-06-13 20:04:56 +00:00
|
|
|
DWORD STDCALL
|
2003-02-03 14:20:24 +00:00
|
|
|
SetThreadIdealProcessor(HANDLE hThread,
|
|
|
|
DWORD dwIdealProcessor)
|
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
Status = NtSetInformationThread(hThread,
|
|
|
|
ThreadIdealProcessor,
|
2004-06-13 20:04:56 +00:00
|
|
|
&dwIdealProcessor,
|
2003-02-03 14:20:24 +00:00
|
|
|
sizeof(ULONG));
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
SetLastErrorByStatus(Status);
|
2004-06-13 20:04:56 +00:00
|
|
|
return -1;
|
2003-02-03 14:20:24 +00:00
|
|
|
}
|
|
|
|
|
2004-06-13 20:04:56 +00:00
|
|
|
return dwIdealProcessor;
|
2003-02-03 14:20:24 +00:00
|
|
|
}
|
|
|
|
|
2004-11-02 21:51:25 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
DWORD STDCALL
|
|
|
|
GetProcessIdOfThread(HANDLE Thread)
|
|
|
|
{
|
|
|
|
THREAD_BASIC_INFORMATION ThreadBasic;
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
Status = NtQueryInformationThread(Thread,
|
|
|
|
ThreadBasicInformation,
|
|
|
|
&ThreadBasic,
|
|
|
|
sizeof(THREAD_BASIC_INFORMATION),
|
|
|
|
NULL);
|
|
|
|
if(!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
SetLastErrorByStatus(Status);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (DWORD)ThreadBasic.ClientId.UniqueProcess;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
DWORD STDCALL
|
|
|
|
GetThreadId(HANDLE Thread)
|
|
|
|
{
|
|
|
|
THREAD_BASIC_INFORMATION ThreadBasic;
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
Status = NtQueryInformationThread(Thread,
|
|
|
|
ThreadBasicInformation,
|
|
|
|
&ThreadBasic,
|
|
|
|
sizeof(THREAD_BASIC_INFORMATION),
|
|
|
|
NULL);
|
|
|
|
if(!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
SetLastErrorByStatus(Status);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (DWORD)ThreadBasic.ClientId.UniqueThread;
|
|
|
|
}
|
|
|
|
|
2004-11-02 20:42:06 +00:00
|
|
|
/*
|
|
|
|
* @unimplemented
|
|
|
|
*/
|
2005-07-29 17:31:59 +00:00
|
|
|
LANGID STDCALL
|
|
|
|
SetThreadUILanguage(WORD wReserved)
|
2004-11-02 20:42:06 +00:00
|
|
|
{
|
2005-07-29 23:03:12 +00:00
|
|
|
DPRINT1("SetThreadUILanguage(0x%4x) unimplemented!\n", wReserved);
|
2005-07-29 17:31:59 +00:00
|
|
|
return 0;
|
2004-11-02 20:42:06 +00:00
|
|
|
}
|
|
|
|
|
2004-12-04 19:30:09 +00:00
|
|
|
static void CALLBACK
|
|
|
|
IntCallUserApc(PVOID Function, PVOID dwData, PVOID Argument3)
|
|
|
|
{
|
|
|
|
PAPCFUNC pfnAPC = (PAPCFUNC)Function;
|
|
|
|
pfnAPC((ULONG_PTR)dwData);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
DWORD STDCALL
|
|
|
|
QueueUserAPC(PAPCFUNC pfnAPC, HANDLE hThread, ULONG_PTR dwData)
|
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
Status = NtQueueApcThread(hThread, IntCallUserApc, pfnAPC,
|
|
|
|
(PVOID)dwData, NULL);
|
|
|
|
if (Status)
|
|
|
|
SetLastErrorByStatus(Status);
|
|
|
|
|
|
|
|
return NT_SUCCESS(Status);
|
|
|
|
}
|
|
|
|
|
2004-12-09 19:11:07 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
BOOL STDCALL
|
|
|
|
GetThreadIOPendingFlag(HANDLE hThread,
|
|
|
|
PBOOL lpIOIsPending)
|
|
|
|
{
|
|
|
|
ULONG IoPending;
|
|
|
|
NTSTATUS Status;
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2004-12-09 19:11:07 +00:00
|
|
|
if(lpIOIsPending == NULL)
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2004-12-09 19:11:07 +00:00
|
|
|
Status = NtQueryInformationThread(hThread,
|
|
|
|
ThreadIsIoPending,
|
|
|
|
(PVOID)&IoPending,
|
|
|
|
sizeof(IoPending),
|
|
|
|
NULL);
|
|
|
|
if(NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
*lpIOIsPending = ((IoPending != 0) ? TRUE : FALSE);
|
|
|
|
return TRUE;
|
|
|
|
}
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2004-12-09 19:11:07 +00:00
|
|
|
SetLastErrorByStatus(Status);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2005-01-27 14:11:19 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
VOID STDCALL
|
|
|
|
Sleep(DWORD dwMilliseconds)
|
|
|
|
{
|
|
|
|
SleepEx(dwMilliseconds, FALSE);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
DWORD STDCALL
|
|
|
|
SleepEx(DWORD dwMilliseconds,
|
|
|
|
BOOL bAlertable)
|
|
|
|
{
|
|
|
|
LARGE_INTEGER Interval;
|
|
|
|
NTSTATUS errCode;
|
|
|
|
|
|
|
|
if (dwMilliseconds != INFINITE)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* System time units are 100 nanoseconds (a nanosecond is a billionth of
|
|
|
|
* a second).
|
|
|
|
*/
|
|
|
|
Interval.QuadPart = -((ULONGLONG)dwMilliseconds * 10000);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Approximately 292000 years hence */
|
|
|
|
Interval.QuadPart = -0x7FFFFFFFFFFFFFFFLL;
|
|
|
|
}
|
|
|
|
|
|
|
|
errCode = NtDelayExecution ((bAlertable ? TRUE : FALSE), &Interval);
|
|
|
|
if (!NT_SUCCESS(errCode))
|
|
|
|
{
|
|
|
|
SetLastErrorByStatus (errCode);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2000-04-14 01:50:38 +00:00
|
|
|
/* EOF */
|