source: trunk/src/kernel32/hmthread.cpp

Last change on this file was 21981, checked in by dmik, 13 years ago

kernel32: Fix stack size interpretation in CreateThread().

It now uses the stack size parameter as a number of bytes to
pre-commit, not as a total stack size, unless
STACK_SIZE_PARAM_IS_A_RESERVATION is set.

Closes #77.

File size: 24.8 KB
RevLine 
[9949]1/* $Id: hmthread.cpp,v 1.19 2003-03-27 15:27:37 sandervl Exp $ */
[3128]2
3/*
4 * Project Odin Software License can be found in LICENSE.TXT
5 *
6 * Win32 thread handle class
7 *
8 *
9 * TODO: Handle is not destroyed when thread terminates (or else GetExitCodeThread won't work)
10 * Create thread token during thread creation??
11 * Fix for WaitForSingleObject when thread is already terminated, but
12 * WaitForMultipleObjects can still fail!
13 * WaitForSingle/MultipleObjects needs to be rewritten! (not using
14 * Open32)
15 *
[8877]16 ************************************************************************************
17 * NOTE: If we ever decide to allocate our own stack, then we MUST use VirtualAlloc!!!!
18 * (alignment reasons)
19 ************************************************************************************
20 *
[3128]21 * Copyright 2000 Sander van Leeuwen (sandervl@xs4all.nl)
22 *
23 */
24#include <os2win.h>
25#include <stdlib.h>
26#include <string.h>
27#include <misc.h>
[7532]28#include <wprocess.h>
[3128]29
30#include <HandleManager.H>
31#include "HMThread.h"
[21302]32#include "oslibdos.h"
[9949]33#include "oslibthread.h"
[21302]34#include "oslibmem.h"
[3128]35
[21916]36#include <win/thread.h>
[3128]37#include "thread.h"
[8401]38#include "asmutil.h"
[9667]39#include "winexebase.h"
[3128]40
41#define DBG_LOCALLOG DBG_hmthread
42#include "dbglocal.h"
43
44
[9748]45typedef struct {
46 HANDLE hDupThread; //original thread handle if duplicated
47 DWORD dwState; //THREAD_ALIVE, THREAD_TERMINATED
48} OBJ_THREAD;
49
50#define GET_THREADHANDLE(hThread) (threadobj && threadobj->hDupThread) ? threadobj->hDupThread : hThread
51
[3128]52//******************************************************************************
53//******************************************************************************
54HANDLE HMDeviceThreadClass::CreateThread(PHMHANDLEDATA pHMHandleData,
55 LPSECURITY_ATTRIBUTES lpsa,
56 DWORD cbStack,
57 LPTHREAD_START_ROUTINE lpStartAddr,
58 LPVOID lpvThreadParm,
59 DWORD fdwCreate,
[3140]60 LPDWORD lpIDThread,
[21302]61 BOOL fRegisterThread)
[3128]62{
[8648]63 Win32Thread *winthread;
64 DWORD threadid;
65 HANDLE hThread = pHMHandleData->hHMHandle;
[3128]66
[21916]67 if(lpIDThread == NULL) {
[4609]68 lpIDThread = &threadid;
[8648]69 }
70 pHMHandleData->dwInternalType = HMTYPE_THREAD;
[9748]71 OBJ_THREAD *threadobj = (OBJ_THREAD *)malloc(sizeof(OBJ_THREAD));
72 if(threadobj == 0) {
73 DebugInt3();
74 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
75 return(0);
76 }
77 threadobj->hDupThread = 0; //not a duplicate
78 threadobj->dwState = THREAD_ALIVE;
79 pHMHandleData->dwUserData = (DWORD)threadobj;
[3140]80
[21981]81 // round up to page size
82 cbStack = (cbStack + 0xFFF) & ~0xFFF;
83
84 // per default 1MB stack per thread
85 DWORD cbTotalStack = (WinExe) ? WinExe->getDefaultStackSize() : 0x100000;
86 DWORD cbCommitStack = 0;
87 if (fdwCreate & STACK_SIZE_PARAM_IS_A_RESERVATION) {
88 if (cbStack)
89 cbTotalStack = cbStack;
90 } else {
91 if (cbStack >= cbTotalStack) {
92 // round up the new reserved size to 1MB
93 cbTotalStack = (cbStack + 0xFFFFF) & ~0xFFFFF;
94 cbCommitStack = cbStack;
95 } else if (cbStack) {
96 cbCommitStack = cbStack;
97 }
98 }
99
100 dprintf(("Thread stack size 0x%X (0x%X to commit)", cbTotalStack, cbCommitStack));
101
[8648]102 //SvL: This doesn't really create a thread, but only sets up the
[21302]103 // handle of the current thread.
104 if(fRegisterThread) {
[9748]105 pHMHandleData->hHMHandle = O32_GetCurrentThread(); //return Open32 handle of thread
106 return pHMHandleData->hHMHandle;
[8648]107 }
[21981]108 winthread = new Win32Thread(lpStartAddr, lpvThreadParm, fdwCreate, hThread, cbCommitStack);
[3128]109
[8648]110 if(winthread == 0) {
[21457]111 dprintf(("Win32Thread creation failed, no more memory"));
[8648]112 DebugInt3();
113 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
114 return(0);
115 }
[21457]116 if(winthread->_GetTEB() == 0) {
117 dprintf(("Win32Thread->teb creation failed, no more memory"));
118 DebugInt3();
119 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
120 return(0);
121 }
122
[8877]123 //************************************************************************************
124 //NOTE: If we ever decide to allocate our own stack, then we MUST use VirtualAlloc!!!!
125 // (alignment reasons)
126 //************************************************************************************
[21981]127 pHMHandleData->hHMHandle = O32_CreateThread(lpsa, cbTotalStack, winthread->GetOS2Callback(),
[8648]128 (LPVOID)winthread, fdwCreate, lpIDThread);
[8465]129
[9667]130 if(pHMHandleData->hHMHandle == 0) {
131 dprintf(("Thread creation failed!!"));
132 DebugInt3();
133 }
134
[8648]135 *lpIDThread = MAKE_THREADID(O32_GetCurrentProcessId(), *lpIDThread);
[21916]136
[8648]137 TEB *teb = GetTEBFromThreadHandle(hThread);
138 if(teb) {
139 //store thread id in TEB
[8919]140 teb->o.odin.threadId = *lpIDThread;
141 teb->o.odin.dwSuspend = (fdwCreate & CREATE_SUSPENDED) ? 1 : 0;
[8648]142 }
[8919]143 else DebugInt3();
144
[8648]145 dprintf(("CreateThread created %08x, id %x", pHMHandleData->hHMHandle, *lpIDThread));
[21916]146
[8648]147 return pHMHandleData->hHMHandle;
[3128]148}
[9748]149/*****************************************************************************
150 * Name : HMDeviceFileClass::DuplicateHandle
151 * Purpose :
152 * Parameters:
153 * various parameters as required
154 * Variables :
155 * Result :
156 * Remark : DUPLICATE_CLOSE_SOURCE flag handled in HMDuplicateHandle
157 *
158 * Status : partially implemented
159 *
160 * Author : SvL
161 *****************************************************************************/
162BOOL HMDeviceThreadClass::DuplicateHandle(HANDLE srchandle, PHMHANDLEDATA pHMHandleData,
163 HANDLE srcprocess,
164 PHMHANDLEDATA pHMSrcHandle,
165 HANDLE destprocess,
166 DWORD fdwAccess,
167 BOOL fInherit,
168 DWORD fdwOptions,
169 DWORD fdwOdinOptions)
170{
171 BOOL ret;
172 OBJ_THREAD *threadsrc = (OBJ_THREAD *)pHMSrcHandle->dwUserData;
173
[21302]174 dprintf(("KERNEL32:HMDeviceThreadClass::DuplicateHandle (%08x,%08x,%08x,%08x)",
175 pHMHandleData, srcprocess, pHMSrcHandle->hHMHandle, destprocess));
[9748]176
177 if(destprocess != srcprocess)
178 {
179 dprintf(("ERROR: DuplicateHandle; different processes not supported!!"));
180 SetLastError(ERROR_INVALID_HANDLE); //??
181 return FALSE;
182 }
[21302]183 pHMHandleData->hHMHandle = 0;
184 ret = O32_DuplicateHandle(srcprocess, pHMSrcHandle->hHMHandle, destprocess, &pHMHandleData->hHMHandle, fdwAccess, fInherit, fdwOptions);
[9748]185
186 if(ret == TRUE) {
187 OBJ_THREAD *threaddest = (OBJ_THREAD *)malloc(sizeof(OBJ_THREAD));
188 if(threaddest == NULL) {
[21302]189 O32_CloseHandle(pHMHandleData->hHMHandle);
[9748]190 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
191 return FALSE;
192 }
193 threaddest->hDupThread = 0;
194 threaddest->dwState = THREAD_ALIVE;
195 pHMHandleData->dwUserData = (DWORD)threaddest;
196
197 if(threadsrc) {
198 threaddest->hDupThread = (threadsrc->hDupThread) ? threadsrc->hDupThread : srchandle;
199 threaddest->dwState = threadsrc->dwState;
200 }
201
202 return TRUE;
203 }
[21302]204 else
205 {
206 dprintf(("O32_DuplicateHandle failed for handle %x!!", pHMSrcHandle->hHMHandle));
207 return FALSE;
208 }
[9748]209}
[3128]210//******************************************************************************
211//******************************************************************************
[7532]212DWORD HMDeviceThreadClass::SuspendThread(HANDLE hThread, PHMHANDLEDATA pHMHandleData)
[3128]213{
[8919]214 DWORD dwSuspend;
[9748]215 OBJ_THREAD *threadobj = (OBJ_THREAD *)pHMHandleData->dwUserData;
[3128]216
[9748]217 TEB *teb = GetTEBFromThreadHandle(GET_THREADHANDLE(hThread));
[8919]218 if(teb) {
219 teb->o.odin.dwSuspend++;
220 dprintf(("SuspendThread %08xh): count %d", pHMHandleData->hHMHandle, teb->o.odin.dwSuspend));
221 }
222 dwSuspend = O32_SuspendThread(pHMHandleData->hHMHandle);
223 if(dwSuspend == -1) {
224 teb->o.odin.dwSuspend--;
225 dprintf(("!ERROR!: SuspendThread FAILED"));
226 }
227 return dwSuspend;
[3128]228}
229//******************************************************************************
230//******************************************************************************
[8919]231DWORD HMDeviceThreadClass::ResumeThread(HANDLE hThread, PHMHANDLEDATA pHMHandleData)
232{
233 DWORD dwSuspend;
[21302]234 CONTEXT context;
[9748]235 OBJ_THREAD *threadobj = (OBJ_THREAD *)pHMHandleData->dwUserData;
236
237 TEB *teb = GetTEBFromThreadHandle(GET_THREADHANDLE(hThread));
[21302]238 if(teb == NULL) {
239 dprintf(("ERROR: invalid thread handle"));
240 SetLastError(ERROR_INVALID_THREAD_ID); //??
241 return -1;
242 }
243
244 context.Eip = 0;
245 if(teb->o.odin.context.ContextFlags)
246 {
247 context.ContextFlags = CONTEXT_CONTROL;
248 if(GetThreadContext(hThread, pHMHandleData, &context) == FALSE)
249 {
250 DebugInt3();
251 context.Eip = 0;
252 }
253 if(teb->o.odin.dwSuspend == 1 && teb->o.odin.context.ContextFlags && context.Eip)
254 {//SetThreadContext was called for this thread and it's about to be restored
255
256 //Since there's no equivalent of SetThreadContext in OS/2, we put an
257 //illegal instruction at the instruction pointer of this thread to
258 //make sure an exception is triggered. Inside the exception handler
259 //of the thread we can change the registers.
260 //(XCPT_PRIVILEGED_INSTRUCTION exception handler in exceptions.cpp)
261 //(see detailed description in the HMDeviceThreadClass::SetThreadContext method)
262 USHORT *lpEIP = (USHORT *)context.Eip;
263
264 if(*lpEIP != SETTHREADCONTEXT_INVALID_LOCKOPCODE)
265 {
266 int size;
267
268 teb->o.odin.dwAliasOffset = (DWORD)lpEIP & 0xFFF;
269 if(teb->o.odin.dwAliasOffset + 2 >= PAGE_SIZE) {
270 size = 8192;
271 }
272 else size = teb->o.odin.dwAliasOffset + 2;
273
274 lpEIP = (USHORT *)((DWORD)lpEIP & ~0xFFF);
275
276 if(OSLibDosAliasMem(lpEIP, size, &teb->o.odin.lpAlias, PAG_READ|PAG_WRITE) == 0)
277 {
278 teb->o.odin.savedopcode = *(USHORT*)((char *)teb->o.odin.lpAlias+teb->o.odin.dwAliasOffset);
279
280 //sti -> undefined opcode exception
281 *(USHORT *)((char *)teb->o.odin.lpAlias+teb->o.odin.dwAliasOffset) = SETTHREADCONTEXT_INVALID_LOCKOPCODE;
282 }
283 else DebugInt3();
284
285 //temporarily boost priority to ensure this thread is scheduled first
286 //we reduce the priority in the exception handler
287 OSLibDosSetMaxPriority(ODIN_TO_OS2_THREADID(teb->o.odin.threadId));
288 }
289 else {
290 dprintf(("already patched!?!"));
291 DebugInt3();
292 }
293 }
294 }
295
[8919]296 teb->o.odin.dwSuspend--;
297 dprintf(("ResumeThread (%08xh) : count %d", pHMHandleData->hHMHandle, teb->o.odin.dwSuspend));
[21302]298
[8919]299 dwSuspend = O32_ResumeThread(pHMHandleData->hHMHandle);
[21302]300 if(dwSuspend == -1)
301 {
[8919]302 teb->o.odin.dwSuspend++;
303 dprintf(("!ERROR!: ResumeThread FAILED"));
[21302]304
305 if(teb->o.odin.dwSuspend == 1 && teb->o.odin.context.ContextFlags && context.Eip)
306 {//Undo previous patching
307 char *lpEIP = (char *)context.Eip;
308
309 if(*lpEIP == SETTHREADCONTEXT_INVALID_LOCKOPCODE)
310 {
311 dprintf(("Undo SetThreadContext patching!!"));
312
313 USHORT *lpAlias = (USHORT*)((char *)teb->o.odin.lpAlias + teb->o.odin.dwAliasOffset);
314 //put back old byte
315 *lpAlias = teb->o.odin.savedopcode;
316
317 //restore the original priority (we boosted it to ensure this thread was scheduled first)
318 ::SetThreadPriority(teb->o.odin.hThread, ::GetThreadPriority(teb->o.odin.hThread));
319
320 OSLibDosFreeMem(teb->o.odin.lpAlias);
321 }
322 else {
323 dprintf(("not patched!?!"));
324 DebugInt3();
325 }
326 teb->o.odin.dwAliasOffset = 0;
327 teb->o.odin.lpAlias = NULL;
328 teb->o.odin.context.ContextFlags = 0;
[8919]329 }
[21302]330 }
331
[8919]332 return dwSuspend;
333}
334//******************************************************************************
335//******************************************************************************
[7532]336INT HMDeviceThreadClass::GetThreadPriority(HANDLE hThread, PHMHANDLEDATA pHMHandleData)
[3128]337{
[9748]338 OBJ_THREAD *threadobj = (OBJ_THREAD *)pHMHandleData->dwUserData;
[3128]339
[7532]340 dprintf(("GetThreadPriority(%08xh)\n", pHMHandleData->hHMHandle));
341
[9748]342 TEB *teb = GetTEBFromThreadHandle(GET_THREADHANDLE(hThread));
[7532]343 if(teb == NULL) {
344 dprintf(("!WARNING!: TEB not found!!"));
345 SetLastError(ERROR_INVALID_HANDLE);
346 return THREAD_PRIORITY_ERROR_RETURN;
347 }
348 return teb->delta_priority;
[3128]349}
350//******************************************************************************
351//******************************************************************************
[7532]352BOOL HMDeviceThreadClass::SetThreadPriority(HANDLE hThread, PHMHANDLEDATA pHMHandleData, int priority)
[3128]353{
[9748]354 OBJ_THREAD *threadobj = (OBJ_THREAD *)pHMHandleData->dwUserData;
[3128]355
[7532]356 dprintf(("SetThreadPriority (%08xh,%08xh)", pHMHandleData->hHMHandle, priority));
357
[9748]358 TEB *teb = GetTEBFromThreadHandle(GET_THREADHANDLE(hThread));
[7532]359 if(teb == NULL) {
360 dprintf(("!WARNING!: TEB not found!!"));
361 SetLastError(ERROR_INVALID_HANDLE);
[9561]362 return FALSE;
[7532]363 }
[8015]364 DWORD ret = OSLibDosSetPriority(ODIN_TO_OS2_THREADID(teb->o.odin.threadId), priority);
[7532]365 if(ret == ERROR_SUCCESS) {
366 teb->delta_priority = priority;
367 return TRUE;
368 }
369 else {
370 dprintf(("DosSetPriority failed with rc %d", ret));
371 return FALSE;
372 }
[3128]373}
374//******************************************************************************
375//******************************************************************************
[21302]376#ifdef DEBUG
377void DumpContext(CONTEXT *lpContext)
378{
379 dprintf(("************************ THREAD CONTEXT ************************"));
380 if(lpContext->ContextFlags & CONTEXT_CONTROL) {
381 dprintf(("CS:EIP %04x:%08x FLAGS %08x", lpContext->SegCs, lpContext->Eip, lpContext->EFlags));
382 dprintf(("SS:ESP %04x:%08x EBP %08x", lpContext->SegSs, lpContext->Esp, lpContext->Ebp));
383 }
384 if(lpContext->ContextFlags & CONTEXT_INTEGER) {
385 dprintf(("EAX %08x EBX %08x ECX %08x EDX %08x", lpContext->Eax, lpContext->Ebx, lpContext->Ecx, lpContext->Edx));
386 dprintf(("ESI %08x EDI %08x", lpContext->Esi, lpContext->Edi));
387 }
388 if(lpContext->ContextFlags & CONTEXT_SEGMENTS) {
389 dprintf(("DS %04x ES %04x FS %04x GS %04x", (ULONG)lpContext->SegDs, (ULONG)lpContext->SegEs, (ULONG)lpContext->SegFs, (ULONG)lpContext->SegGs));
390 }
391 dprintf(("************************ THREAD CONTEXT ************************"));
392// if(lpContext->ContextFlags & CONTEXT_FLOATING_POINT) {
393// //TODO: First 7 dwords the same?
394// memcpy(&lpContext->FloatSave, ctxrec.ctx_env, sizeof(ctxrec.ctx_env));
395// memcpy(&lpContext->FloatSave.RegisterArea, ctxrec.ctx_stack, sizeof(ctxrec.ctx_stack));
396// }
397}
398#else
399#define DumpContext(a)
400#endif
401//******************************************************************************
402//******************************************************************************
[7532]403BOOL HMDeviceThreadClass::GetThreadContext(HANDLE hThread, PHMHANDLEDATA pHMHandleData, PCONTEXT lpContext)
[3128]404{
[21302]405 OBJ_THREAD *threadobj = (OBJ_THREAD *)pHMHandleData->dwUserData;
406 BOOL ret;
[3128]407
[21302]408 TEB *teb = GetTEBFromThreadHandle(GET_THREADHANDLE(hThread));
409 if(teb) {
410 if(teb->o.odin.dwSuspend == 0) {
411 dprintf(("ERROR: thread not suspended!!"));
412 DebugInt3();
413 SetLastError(ERROR_INVALID_OPERATION); //???
414 return FALSE;
415 }
[3128]416
[21302]417 ret = OSLibQueryThreadContext(ODIN_TO_OS2_THREADID(teb->o.odin.threadId), teb->teb_sel, lpContext);
418 if(ret == TRUE) {
419 DumpContext(lpContext);
420 }
421 return ret;
422 }
423 dprintf(("!WARNING!: TEB not found!!"));
424 SetLastError(ERROR_INVALID_HANDLE);
425 return FALSE;
[3128]426}
427//******************************************************************************
[21302]428// HMDeviceThreadClass::SetThreadContext
429//
430// Change the context (registers) of a suspended thread
431//
432// Parameters:
433//
434// HANDLE hThread - thread handle
435// PHMHANDLEDATA pHMHandleData - handle data
436// const CONTEXT *lpContext - context record (IN)
437//
438// Returns:
439// TRUE - success
440// FALSE - failure
441//
442// Remarks:
443//
444// Since OS/2 doesn't provide an equivalent for this function, we need to change
445// the thread context manually. (DosDebug isn't really an option)
446//
447// We save the new context in the TEB structure. When this thread is
448// activated by ResumeThread, we'll change the instruction addressed by the
449// thread's EIP to an invalid instruction (sti).
450// When the thread is activated, it will generate an exception. Inside the
451// exception handler we change the registers, restore the original memory
452// and continue.
453// To make sure the thread is executed first and noone else will execute the
454// invalid instruction, we temporarily boost the thread's priority to the max.
455// (time critical, delta +31; max priority of win32 threads is time critical,
456// delta 0)
457// The priority is restored in the exception handler.
458//
[3128]459//******************************************************************************
[7532]460BOOL HMDeviceThreadClass::SetThreadContext(HANDLE hThread, PHMHANDLEDATA pHMHandleData, const CONTEXT *lpContext)
[3128]461{
[21302]462 OBJ_THREAD *threadobj = (OBJ_THREAD *)pHMHandleData->dwUserData;
463 BOOL ret;
[3128]464
[21302]465 DumpContext((CONTEXT *)lpContext);
466
467 TEB *teb = GetTEBFromThreadHandle(GET_THREADHANDLE(hThread));
468 if(teb)
469 {
470 if(teb->o.odin.dwSuspend == 0) {
471 dprintf(("ERROR: thread not suspended!!"));
472 SetLastError(ERROR_INVALID_OPERATION); //???
473 return FALSE;
474 }
475 if(lpContext->ContextFlags & CONTEXT_CONTROL) {
476 teb->o.odin.context.ContextFlags |= CONTEXT_CONTROL;
477 teb->o.odin.context.Ebp = lpContext->Ebp;
478 teb->o.odin.context.Eip = lpContext->Eip;
479 teb->o.odin.context.SegCs = lpContext->SegCs;
480 teb->o.odin.context.EFlags = lpContext->EFlags;
481 teb->o.odin.context.Esp = lpContext->Esp;
482 teb->o.odin.context.SegSs = lpContext->SegSs;
483 }
484 if(lpContext->ContextFlags & CONTEXT_INTEGER) {
485 teb->o.odin.context.ContextFlags |= CONTEXT_INTEGER;
486 teb->o.odin.context.Edi = lpContext->Edi;
487 teb->o.odin.context.Esi = lpContext->Esi;
488 teb->o.odin.context.Ebx = lpContext->Ebx;
489 teb->o.odin.context.Edx = lpContext->Edx;
490 teb->o.odin.context.Ecx = lpContext->Ecx;
491 teb->o.odin.context.Eax = lpContext->Eax;
492 }
493 if(lpContext->ContextFlags & CONTEXT_SEGMENTS) {
494 teb->o.odin.context.ContextFlags |= CONTEXT_SEGMENTS;
495 teb->o.odin.context.SegGs = lpContext->SegGs;
496 teb->o.odin.context.SegFs = lpContext->SegFs;
497 teb->o.odin.context.SegEs = lpContext->SegEs;
498 teb->o.odin.context.SegDs = lpContext->SegDs;
499 }
500 if(lpContext->ContextFlags & CONTEXT_FLOATING_POINT) {
501 teb->o.odin.context.ContextFlags |= CONTEXT_FLOATING_POINT;
502 memcpy(&teb->o.odin.context.FloatSave, &lpContext->FloatSave, sizeof(lpContext->FloatSave));
503 }
504 SetLastError(ERROR_SUCCESS);
505 return TRUE;
506 }
507 dprintf(("!WARNING!: TEB not found!!"));
508 SetLastError(ERROR_INVALID_HANDLE);
[3128]509 return FALSE;
510}
[9748]511/*****************************************************************************
512 * Name : BOOL GetThreadTimes
513 * Purpose : The GetThreadTimes function obtains timing information about a specified thread.
514 * Parameters: HANDLE hThread specifies the thread of interest
515 * LPFILETIME lpCreationTime when the thread was created
516 * LPFILETIME lpExitTime when the thread exited
517 * LPFILETIME lpKernelTime time the thread has spent in kernel mode
518 * LPFILETIME lpUserTime time the thread has spent in user mode
519 * Variables :
520 * Result : TRUE / FALSE
521 * Remark :
522 * Status : UNTESTED STUB
523 *
524 * Author : Patrick Haller [Mon, 1998/06/15 08:00]
525 *****************************************************************************/
526
527BOOL HMDeviceThreadClass::GetThreadTimes(HANDLE hThread,
528 PHMHANDLEDATA pHMHandleData,
529 LPFILETIME lpCreationTime,
530 LPFILETIME lpExitTime,
531 LPFILETIME lpKernelTime,
532 LPFILETIME lpUserTime)
533{
534 dprintf(("Kernel32: GetThreadTimes(%08xh,%08xh,%08xh,%08xh,%08xh) not implemented.\n",
535 hThread,
536 lpCreationTime,
537 lpExitTime,
538 lpKernelTime,
539 lpUserTime));
540
541 return (FALSE);
542}
[3128]543//******************************************************************************
544//******************************************************************************
[7532]545BOOL HMDeviceThreadClass::TerminateThread(HANDLE hThread, PHMHANDLEDATA pHMHandleData, DWORD exitcode)
[3128]546{
[9748]547 OBJ_THREAD *threadobj = (OBJ_THREAD *)pHMHandleData->dwUserData;
548
[3128]549 dprintf(("TerminateThread (%08xh,%08xh)\n",
550 pHMHandleData->hHMHandle,
551 exitcode));
552
[9748]553 if(threadobj) {
554 threadobj->dwState = THREAD_TERMINATED;
555 }
556 else DebugInt3();
[3128]557 return O32_TerminateThread(pHMHandleData->hHMHandle, exitcode);
558}
559//******************************************************************************
560//******************************************************************************
[7532]561BOOL HMDeviceThreadClass::SetThreadTerminated(HANDLE hThread, PHMHANDLEDATA pHMHandleData)
[3128]562{
[9748]563 OBJ_THREAD *threadobj = (OBJ_THREAD *)pHMHandleData->dwUserData;
564
565 if(threadobj) {
566 threadobj->dwState = THREAD_TERMINATED;
567 }
568 else DebugInt3();
569
[3128]570 return TRUE;
571}
572//******************************************************************************
573//******************************************************************************
[7532]574BOOL HMDeviceThreadClass::GetExitCodeThread(HANDLE hThread, PHMHANDLEDATA pHMHandleData, LPDWORD lpExitCode)
[3128]575{
576 dprintf(("GetExitCodeThread (%08xh,%08xh)\n",
577 pHMHandleData->hHMHandle,
578 lpExitCode));
579
580#if 0
[9748]581 OBJ_THREAD *threadobj = (OBJ_THREAD *)pHMHandleData->dwUserData;
582
583 if(threadobj && threadobj->dwState == THREAD_ALIVE) {
[3128]584 lpExitCode == STILL_ALIVE;
585 return TRUE;
586 }
[9748]587 else DebugInt3();
[3128]588#endif
589 return O32_GetExitCodeThread(pHMHandleData->hHMHandle, lpExitCode);
590}
591//******************************************************************************
592//******************************************************************************
[5587]593BOOL HMDeviceThreadClass::CloseHandle(PHMHANDLEDATA pHMHandleData)
[3128]594{
[9748]595 OBJ_THREAD *threadobj = (OBJ_THREAD *)pHMHandleData->dwUserData;
596
[9667]597 dprintf(("HMThread::CloseHandle %08x", pHMHandleData->hHMHandle));
[9748]598
599 if(threadobj) {
600 pHMHandleData->dwUserData = 0;
601 free(threadobj);
602 }
[9667]603 return O32_CloseHandle(pHMHandleData->hHMHandle);
[3128]604}
605//******************************************************************************
606//******************************************************************************
607DWORD HMDeviceThreadClass::WaitForSingleObject(PHMHANDLEDATA pHMHandleData,
608 DWORD dwTimeout)
609{
[9748]610 OBJ_THREAD *threadobj = (OBJ_THREAD *)pHMHandleData->dwUserData;
611
[5920]612 dprintf(("HMThread::WaitForSingleObject (%08xh,%08xh)\n",
613 pHMHandleData->hHMHandle,
614 dwTimeout));
[21916]615
[3128]616 //This doesn't work very well in Open32 (object's state never signaled)
[9748]617 if(threadobj && threadobj->dwState == THREAD_TERMINATED) {
[3128]618 return WAIT_OBJECT_0;
619 }
620 return HMDeviceOpen32Class::WaitForSingleObject(pHMHandleData, dwTimeout);
621}
622//******************************************************************************
623//******************************************************************************
624DWORD HMDeviceThreadClass::WaitForSingleObjectEx(PHMHANDLEDATA pHMHandleData,
625 DWORD dwTimeout,
626 BOOL fAlertable)
627{
[9748]628 OBJ_THREAD *threadobj = (OBJ_THREAD *)pHMHandleData->dwUserData;
629
630 //This doesn't work very well in Open32 (object's state never signaled)
631 if(threadobj && threadobj->dwState == THREAD_TERMINATED) {
[3128]632 return WAIT_OBJECT_0;
633 }
634 return HMDeviceOpen32Class::WaitForSingleObjectEx(pHMHandleData, dwTimeout, fAlertable);
635}
636//******************************************************************************
637//******************************************************************************
Note: See TracBrowser for help on using the repository browser.