ReactOS 0.4.16-dev-927-g467dec4
thread.c
Go to the documentation of this file.
1/*
2 * Copyright 2021 Arkadiusz Hiler for CodeWeavers
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17 */
18
19#include <errno.h>
20#include <stdarg.h>
21#include <process.h>
22
23#include <windef.h>
24#include <winbase.h>
25#include "wine/test.h"
26
27#include "threaddll.h"
28
30typedef unsigned int (__stdcall *_beginthreadex_start_routine_t)(void *);
31
33{
36};
37
38static char *get_thread_dll_path(void)
39{
40 static char path[MAX_PATH];
41 const char dll_name[] = "threaddll.dll";
42 DWORD written;
44 HRSRC res;
45 void *ptr;
46
48 strcat(path, dll_name);
49
51 ok(file != INVALID_HANDLE_VALUE, "Failed to create file %s: %lu.\n",
53
54 res = FindResourceA(NULL, dll_name, "TESTDLL");
55 ok(!!res, "Failed to load resource: %lu\n", GetLastError());
58 ok(written == SizeofResource(GetModuleHandleA(NULL), res), "Failed to write resource\n");
60
61 return path;
62}
63
65{
66 void (WINAPI *_set_detach_event)(HANDLE event);
67 _set_detach_event = (void*) GetProcAddress(dll, "set_detach_event");
68 ok(_set_detach_event != NULL, "Failed to get set_detach_event: %lu\n", GetLastError());
69 _set_detach_event(event);
70}
71
72static void test_thread_library_reference(char *thread_dll,
74 enum thread_exit_method exit_method)
75{
78 DWORD ret;
79 uintptr_t thread_handle;
80 struct threaddll_args args;
81
82 args.exit_method = exit_method;
83
85 ok(detach_event != NULL, "Failed to create an event: %lu\n", GetLastError());
86 args.confirm_running = CreateEventA(NULL, FALSE, FALSE, NULL);
87 ok(args.confirm_running != NULL, "Failed to create an event: %lu\n", GetLastError());
88 args.past_free = CreateEventA(NULL, FALSE, FALSE, NULL);
89 ok(args.past_free != NULL, "Failed to create an event: %lu\n", GetLastError());
90
91 dll = LoadLibraryA(thread_dll);
92 ok(dll != NULL, "Failed to load the test dll: %lu\n", GetLastError());
93
95
97 {
98 _beginthreadex_start_routine_t proc = (void*) GetProcAddress(dll, "stdcall_thread_proc");
99 ok(proc != NULL, "Failed to get stdcall_thread_proc: %lu\n", GetLastError());
100 thread_handle = _beginthreadex(NULL, 0, proc, &args, 0, NULL);
101 }
102 else
103 {
104 _beginthread_start_routine_t proc = (void*) GetProcAddress(dll, "cdecl_thread_proc");
105 ok(proc != NULL, "Failed to get stdcall_thread_proc: %lu\n", GetLastError());
106 thread_handle = _beginthread(proc, 0, &args);
107 }
108
109 ok(thread_handle != -1 && thread_handle != 0, "Failed to begin thread: %u\n", errno);
110
112 ok(ret, "Failed to free the library: %lu\n", GetLastError());
113
114 ret = WaitForSingleObject(args.confirm_running, 200);
115 ok(ret == WAIT_OBJECT_0, "Event was not signaled, ret: %lu, err: %lu\n", ret, GetLastError());
116
118 ok(ret == WAIT_TIMEOUT, "Thread detach happened unexpectedly signaling an event, ret: %ld, err: %lu\n", ret, GetLastError());
119
120 ret = SetEvent(args.past_free);
121 ok(ret, "Failed to signal event: %ld\n", GetLastError());
122
124 {
125 ret = WaitForSingleObject((HANDLE)thread_handle, 200);
126 ok(ret == WAIT_OBJECT_0, "Thread has not exited, ret: %ld, err: %lu\n", ret, GetLastError());
127 }
128
130 ok(ret == WAIT_OBJECT_0, "Detach event was not signaled, ret: %ld, err: %lu\n", ret, GetLastError());
131
133 CloseHandle((HANDLE)thread_handle);
134
135 CloseHandle(args.past_free);
136 CloseHandle(args.confirm_running);
138}
139
141
142void CDECL test_invalid_parameter_handler(const wchar_t *expression,
143 const wchar_t *function_name,
144 const wchar_t *file_name,
145 unsigned line_number,
147{
149}
150
152{
155
156 errno = 0;
159 ok(hThread == 0, "_beginthreadex unexpected ret: %Iu\n", hThread);
160 ok(errno == EINVAL, "_beginthreadex unexpected errno: %d\n", errno);
161 ok(handler_called, "Expected invalid_parameter_handler to be called\n");
162
163 errno = 0;
166 ok(hThread == -1, "_beginthread unexpected ret: %Iu\n", hThread);
167 ok(errno == EINVAL, "_beginthread unexpected errno: %d\n", errno);
168 ok(handler_called, "Expected invalid_parameter_handler to be called\n");
169
171}
172
174{
175 BOOL ret;
176 char *thread_dll = get_thread_dll_path();
177
182
183 ret = DeleteFileA(thread_dll);
184 ok(ret, "Failed to remove the test dll, err: %lu\n", GetLastError());
185
187}
#define EINVAL
Definition: acclib.h:90
#define __cdecl
Definition: accygwin.h:79
#define ok(value,...)
Definition: atltest.h:57
#define START_TEST(x)
Definition: atltest.h:75
#define ARRAY_SIZE(A)
Definition: main.h:20
static HANDLE thread
Definition: service.c:33
#define WAIT_TIMEOUT
Definition: dderror.h:14
int const char const *const int const line_number
Definition: debug_heap.cpp:499
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define CDECL
Definition: compat.h:29
#define CloseHandle
Definition: compat.h:739
#define GetProcAddress(x, y)
Definition: compat.h:753
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define CreateFileA(a, b, c, d, e, f, g)
Definition: compat.h:740
#define FreeLibrary(x)
Definition: compat.h:748
#define GENERIC_READ
Definition: compat.h:135
#define MAX_PATH
Definition: compat.h:34
BOOL WINAPI DeleteFileA(IN LPCSTR lpFileName)
Definition: delete.c:24
BOOL WINAPI WriteFile(IN HANDLE hFile, IN LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, OUT LPDWORD lpNumberOfBytesWritten, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:24
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:812
HINSTANCE WINAPI DECLSPEC_HOTPATCH LoadLibraryA(LPCSTR lpLibFileName)
Definition: loader.c:111
DWORD WINAPI GetTempPathA(IN DWORD nBufferLength, OUT LPSTR lpBuffer)
Definition: path.c:2054
HRSRC WINAPI FindResourceA(HMODULE hModule, LPCSTR name, LPCSTR type)
Definition: res.c:155
DWORD WINAPI SizeofResource(HINSTANCE hModule, HRSRC hRsrc)
Definition: res.c:568
LPVOID WINAPI LockResource(HGLOBAL handle)
Definition: res.c:550
HGLOBAL WINAPI LoadResource(HINSTANCE hModule, HRSRC hRsrc)
Definition: res.c:532
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
r reserved
Definition: btrfs.c:3006
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
struct _cl_event * event
Definition: glext.h:7739
GLuint res
Definition: glext.h:9613
_invalid_parameter_handler __cdecl _set_invalid_parameter_handler(_In_opt_ _invalid_parameter_handler _Handler)
void(__cdecl * _invalid_parameter_handler)(const wchar_t *, const wchar_t *, const wchar_t *, unsigned int, uintptr_t)
Definition: stdlib.h:125
wchar_t const *const function_name
#define debugstr_a
Definition: kernel32.h:31
unsigned int uintptr_t
Definition: intrin.h:47
#define CREATE_ALWAYS
Definition: disk.h:72
static PVOID ptr
Definition: dispmode.c:27
static HMODULE dll
Definition: str.c:188
static void test_invalid_parameter_handler(void)
Definition: misc.c:384
static void test_thread_library_reference(char *thread_dll, enum beginthread_method beginthread_method, enum thread_exit_method exit_method)
Definition: thread.c:72
static void set_thead_dll_detach_event(HANDLE dll, HANDLE event)
Definition: thread.c:64
unsigned int(__stdcall * _beginthreadex_start_routine_t)(void *)
Definition: thread.c:30
static BOOL handler_called
Definition: thread.c:140
static char * get_thread_dll_path(void)
Definition: thread.c:38
static void test_thread_invalid_params(void)
Definition: thread.c:151
beginthread_method
Definition: thread.c:33
@ use_beginthreadex
Definition: thread.c:35
@ use_beginthread
Definition: thread.c:34
void(__cdecl * _beginthread_start_routine_t)(void *)
Definition: thread.c:29
static LPCWSTR file_name
Definition: protocol.c:147
HANDLE hThread
Definition: wizard.c:28
#define GENERIC_WRITE
Definition: nt_native.h:90
static HANDLE proc()
Definition: pdb.c:34
#define errno
Definition: errno.h:18
_CRTIMP uintptr_t __cdecl _beginthreadex(_In_opt_ void *_Security, _In_ unsigned _StackSize, _In_ unsigned(__stdcall *_StartAddress)(void *), _In_opt_ void *_ArgList, _In_ unsigned _InitFlag, _Out_opt_ unsigned *_ThrdAddr)
_CRTIMP uintptr_t __cdecl _beginthread(_In_ void(__cdecl *_StartAddress)(void *), _In_ unsigned _StackSize, _In_opt_ void *_ArgList)
strcat
Definition: string.h:92
Definition: match.c:390
Definition: fci.c:127
enum thread_exit_method exit_method
Definition: threaddll.h:29
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
HANDLE WINAPI DECLSPEC_HOTPATCH CreateEventA(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, IN BOOL bManualReset, IN BOOL bInitialState, IN LPCSTR lpName OPTIONAL)
Definition: synch.c:637
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:733
static HANDLE detach_event
Definition: threaddll.c:27
thread_exit_method
Definition: threaddll.h:19
@ thread_exit_endthreadex
Definition: threaddll.h:22
@ thread_exit_return
Definition: threaddll.h:20
@ thread_exit_endthread
Definition: threaddll.h:21
#define __stdcall
Definition: typedefs.h:25
int ret
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define WAIT_OBJECT_0
Definition: winbase.h:432
#define WINAPI
Definition: msvc.h:6