From: Billy Laws blaws05@gmail.com
--- dlls/ntdll/tests/Makefile.in | 2 + dlls/ntdll/tests/testdll.c | 40 ++++++++++++++++ dlls/ntdll/tests/testdll.spec | 2 + dlls/ntdll/tests/thread.c | 86 +++++++++++++++++++++++++++++++++++ include/winternl.h | 66 +++++++++++++++++++++++++-- 5 files changed, 193 insertions(+), 3 deletions(-) create mode 100644 dlls/ntdll/tests/testdll.c create mode 100644 dlls/ntdll/tests/testdll.spec
diff --git a/dlls/ntdll/tests/Makefile.in b/dlls/ntdll/tests/Makefile.in index 3742968c415..04657aee627 100644 --- a/dlls/ntdll/tests/Makefile.in +++ b/dlls/ntdll/tests/Makefile.in @@ -23,6 +23,8 @@ SOURCES = \ string.c \ sync.c \ thread.c \ + testdll.c \ + testdll.spec \ threadpool.c \ time.c \ unwind.c \ diff --git a/dlls/ntdll/tests/testdll.c b/dlls/ntdll/tests/testdll.c new file mode 100644 index 00000000000..7be1c9f84c7 --- /dev/null +++ b/dlls/ntdll/tests/testdll.c @@ -0,0 +1,40 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + * + */ + +#if 0 +#pragma makedep testdll +#endif + +#include <windows.h> + +BOOL seen_thread_attach; +BOOL seen_thread_detach; + +BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved) +{ + switch (reason) + { + case DLL_THREAD_ATTACH: + seen_thread_attach = TRUE; + break; + case DLL_THREAD_DETACH: + seen_thread_detach = TRUE; + break; + } + + return TRUE; +} diff --git a/dlls/ntdll/tests/testdll.spec b/dlls/ntdll/tests/testdll.spec new file mode 100644 index 00000000000..75feb73a990 --- /dev/null +++ b/dlls/ntdll/tests/testdll.spec @@ -0,0 +1,2 @@ +@ extern seen_thread_attach +@ extern seen_thread_detach diff --git a/dlls/ntdll/tests/thread.c b/dlls/ntdll/tests/thread.c index 4941b791bcd..926e3b0bc8c 100644 --- a/dlls/ntdll/tests/thread.c +++ b/dlls/ntdll/tests/thread.c @@ -356,6 +356,91 @@ static void test_NtQueueApcThreadEx(void) SleepEx( 0, TRUE ); }
+static void extract_resource(const char *name, const char *type, const char *path) +{ + DWORD written; + HANDLE file; + HRSRC res; + void *ptr; + + file = CreateFileA(path, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0); + ok(file != INVALID_HANDLE_VALUE, "file creation failed, at %s, error %ld\n", path, GetLastError()); + + res = FindResourceA(NULL, name, type); + ok( res != 0, "couldn't find resource\n" ); + ptr = LockResource( LoadResource( GetModuleHandleA(NULL), res )); + WriteFile( file, ptr, SizeofResource( GetModuleHandleA(NULL), res ), &written, NULL ); + ok( written == SizeofResource( GetModuleHandleA(NULL), res ), "couldn't write resource\n" ); + CloseHandle( file ); +} + +struct skip_thread_attach_args +{ + BOOL teb_flag; + PVOID teb_tls_pointer; + PVOID teb_fls_slots; +}; + +static void CALLBACK test_skip_thread_attach_proc(void *param) +{ + struct skip_thread_attach_args *args = param; + args->teb_flag = NtCurrentTeb()->SkipThreadAttach; + args->teb_tls_pointer = NtCurrentTeb()->ThreadLocalStoragePointer; + args->teb_fls_slots = NtCurrentTeb()->FlsSlots; +} + +static void test_skip_thread_attach(void) +{ + BOOL *seen_thread_attach, *seen_thread_detach; + struct skip_thread_attach_args args; + HANDLE thread; + NTSTATUS status; + char path_dll_local[MAX_PATH + 11]; + char path_tmp[MAX_PATH]; + HMODULE module; + + if (!pNtCreateThreadEx) + { + win_skip( "NtCreateThreadEx is not available.\n" ); + return; + } + + GetTempPathA(sizeof(path_tmp), path_tmp); + + sprintf(path_dll_local, "%s%s", path_tmp, "testdll.dll"); + extract_resource("testdll.dll", "TESTDLL", path_dll_local); + + module = LoadLibraryA(path_dll_local); + if (!module) { + trace("Could not load testdll.\n"); + goto delete; + } + + seen_thread_attach = (BOOL *)GetProcAddress(module, "seen_thread_attach"); + seen_thread_detach = (BOOL *)GetProcAddress(module, "seen_thread_detach"); + + ok( !*seen_thread_attach, "Unexpected\n" ); + ok( !*seen_thread_detach, "Unexpected\n" ); + + status = pNtCreateThreadEx( &thread, THREAD_ALL_ACCESS, NULL, GetCurrentProcess(), test_skip_thread_attach_proc, + &args, THREAD_CREATE_FLAGS_SKIP_THREAD_ATTACH, 0, 0, 0, NULL ); + todo_wine ok( status == STATUS_SUCCESS, "Got unexpected status %#lx.\n", status ); + + WaitForSingleObject( thread, INFINITE ); + + CloseHandle( thread ); + + todo_wine ok( !*seen_thread_attach, "Unexpected\n" ); + todo_wine ok( !*seen_thread_detach, "Unexpected\n" ); + todo_wine ok( args.teb_flag, "Unexpected\n" ); + todo_wine ok( !args.teb_tls_pointer, "Unexpected\n" ); + todo_wine ok( !args.teb_fls_slots, "Unexpected\n" ); + + FreeLibrary(module); +delete: + DeleteFileA(path_dll_local); +} + START_TEST(thread) { init_function_pointers(); @@ -378,4 +463,5 @@ START_TEST(thread) test_NtCreateUserProcess(); test_thread_bypass_process_freeze(); test_NtQueueApcThreadEx(); + test_skip_thread_attach(); } diff --git a/include/winternl.h b/include/winternl.h index 64e82b20eca..52d4703145c 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -610,7 +610,27 @@ typedef struct _TEB PVOID MergedPrefLanguages; /* fc0/17e0 */ ULONG MuiImpersonation; /* fc4/17e8 */ USHORT CrossTebFlags; /* fc8/17ec */ - USHORT SameTebFlags; /* fca/17ee */ + union { + USHORT SameTebFlags; /* fca/17ee */ + struct { + USHORT SafeThunkCall : 1; + USHORT InDebugPrint : 1; + USHORT HasFiberData : 1; + USHORT SkipThreadAttach : 1; + USHORT WerInShipAssertCode : 1; + USHORT RanProcessInit : 1; + USHORT ClonedThread : 1; + USHORT SuppressDebugMsg : 1; + USHORT DisableUserStackWalk : 1; + USHORT RtlExceptionAttached : 1; + USHORT InitialThread : 1; + USHORT SessionAware : 1; + USHORT LoadOwner : 1; + USHORT LoaderWorker : 1; + USHORT SkipLoaderInit : 1; + USHORT SkipFileAPIBrokering : 1; + } DUMMYSTRUCTNAME; + } DUMMYUNIONNAME1; PVOID TxnScopeEnterCallback; /* fcc/17f0 */ PVOID TxnScopeExitCallback; /* fd0/17f8 */ PVOID TxnScopeContext; /* fd4/1800 */ @@ -1143,7 +1163,27 @@ typedef struct _TEB32 ULONG MergedPrefLanguages; /* 0fc0 */ ULONG MuiImpersonation; /* 0fc4 */ USHORT CrossTebFlags; /* 0fc8 */ - USHORT SameTebFlags; /* 0fca */ + union { + USHORT SameTebFlags; /* 0fca */ + struct { + USHORT SafeThunkCall : 1; + USHORT InDebugPrint : 1; + USHORT HasFiberData : 1; + USHORT SkipThreadAttach : 1; + USHORT WerInShipAssertCode : 1; + USHORT RanProcessInit : 1; + USHORT ClonedThread : 1; + USHORT SuppressDebugMsg : 1; + USHORT DisableUserStackWalk : 1; + USHORT RtlExceptionAttached : 1; + USHORT InitialThread : 1; + USHORT SessionAware : 1; + USHORT LoadOwner : 1; + USHORT LoaderWorker : 1; + USHORT SkipLoaderInit : 1; + USHORT SkipFileAPIBrokering : 1; + } DUMMYSTRUCTNAME; + } DUMMYUNIONNAME1; ULONG TxnScopeEnterCallback; /* 0fcc */ ULONG TxnScopeExitCallback; /* 0fd0 */ ULONG TxnScopeContext; /* 0fd4 */ @@ -1249,7 +1289,27 @@ typedef struct _TEB64 ULONG64 MergedPrefLanguages; /* 17e0 */ ULONG MuiImpersonation; /* 17e8 */ USHORT CrossTebFlags; /* 17ec */ - USHORT SameTebFlags; /* 17ee */ + union { + USHORT SameTebFlags; /* 17ee */ + struct { + USHORT SafeThunkCall : 1; + USHORT InDebugPrint : 1; + USHORT HasFiberData : 1; + USHORT SkipThreadAttach : 1; + USHORT WerInShipAssertCode : 1; + USHORT RanProcessInit : 1; + USHORT ClonedThread : 1; + USHORT SuppressDebugMsg : 1; + USHORT DisableUserStackWalk : 1; + USHORT RtlExceptionAttached : 1; + USHORT InitialThread : 1; + USHORT SessionAware : 1; + USHORT LoadOwner : 1; + USHORT LoaderWorker : 1; + USHORT SkipLoaderInit : 1; + USHORT SkipFileAPIBrokering : 1; + } DUMMYSTRUCTNAME; + } DUMMYUNIONNAME1; ULONG64 TxnScopeEnterCallback; /* 17f0 */ ULONG64 TxnScopeExitCallback; /* 17f8 */ ULONG64 TxnScopeContext; /* 1800 */