source: trunk/src/kernel32/hmthread.cpp@ 21457

Last change on this file since 21457 was 21457, checked in by ydario, 15 years ago

In low mem situations, DosAllocMem() can fail while new() can still work, check for a valid TEB structure also.

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