20 #ifdef HAVE_STRUCTURED_EH 32 : hThread( NULL ), Id( 0 ), UserData( NULL )
35 SimpleThread::~SimpleThread()
40 bool SimpleThread::Start( PTHREAD_START_ROUTINE ThreadFunc,
DWORD msYield )
42 bool ok = (hThread == NULL);
43 if ( !ok ) SetLastError( ERROR_ALREADY_INITIALIZED );
46 hThread = CreateThread( NULL,0, ThreadFunc,
this, 0, (
PDWORD)&Id );
48 if (hThread && msYield) SleepEx( msYield,
true );
49 ok = (hThread != NULL);
54 bool SimpleThread::Stop(
DWORD msWait )
56 bool ok = (hThread == NULL);
61 ok =
WaitFor( hThread, msWait );
65 _F(
"Terminating unresponsive thread 0x%04x. Debug your code!\n"),
69 TerminateThread( hThread, error );
72 if (error) SetLastError( error );
77 void SimpleThread::Close()
91 #define SE_KILLTHREAD \ 92 MAKE_SOFTEXCEPTION( ERROR_SEVERITY_ERROR, FACILITY_ULIB, 1 ) 98 #define PROGCTR(Context) (Context.Eip) 101 #if defined(_M_AMD64) // x64 102 #define PROGCTR(Context) (Context.Rip) 106 #define PROGCTR(Context) (Context.Fir) 110 #define PROGCTR(Context) (Context.Fir) 114 #define PROGCTR(Context) (Context.Iar) 117 #if !defined(PROGCTR) 118 #error Module contains CPU-specific code; modify and recompile. 121 #ifdef INCL_THREAD_W95_SUPPORT 122 static PVOID CreateExceptionHandlerThunks( PHANDLE phFileMap );
123 static void DeleteExceptionHandlerThunks( PVOID pvThunk, HANDLE hFileMap );
129 Thread* _this = (Thread*) arg;
130 while( _this->idThread ) SleepEx( 1000,
true );
137 PTHREAD_START_ROUTINE pFunc,
138 SIZE_T StackSize,
DWORD Flags, PSECURITY_ATTRIBUTES pSec
146 _ThreadFunc = pFunc ? pFunc : __dummyThr;
149 _StkSize = StackSize;
152 _hmControl = _hmDelay = _heEnd = NULL;
155 #ifdef INCL_THREAD_W95_SUPPORT 166 bool Thread::SetThreadProc( PTHREAD_START_ROUTINE pFunc )
168 bool ok = (pFunc != NULL);
169 if (!ok) SetLastError( ERROR_INVALID_PARAMETER );
174 SetLastError( ERROR_ALREADY_ASSIGNED );
190 typedef unsigned (__stdcall *PCRT_THREADFUNC)(
void* arg );
197 if (!_ThreadFunc) SetLastError( ERROR_INVALID_FUNCTION );
201 _hmControl = CreateMutex( NULL, FALSE, NULL );
202 _hmDelay = CreateMutex( NULL, FALSE, NULL );
203 _heEnd = CreateEvent( NULL, TRUE, FALSE, NULL );
205 #ifdef INCL_THREAD_W95_SUPPORT 206 if (_TLSIndex == TLS_OUT_OF_INDEXES) _TLSIndex = TlsAlloc();
212 hThread = (HANDLE)_beginthreadex(
213 _SecAttr, (UINT)_StkSize, (PCRT_THREADFUNC)_TProc,
this,
214 _Flags, (PUINT)&idThread
219 return (hThread != NULL);
224 bool Thread::Stop(
DWORD msWait,
bool Nuke )
229 if (!
WaitFor( hThread, msWait ))
236 if (Nuke && !
WaitFor( hThread, msWait ))
245 TerminateThread( hThread, ERROR_TIMEOUT );
251 return (hThread == NULL);
254 bool Thread::Pause(
bool pause )
256 if (pause) SuspendThread( hThread );
257 else ResumeThread( hThread );
272 WaitForSingleObject( _hmControl, INFINITE );
274 if (WaitForSingleObject( _hmDelay, 0 ) == WAIT_TIMEOUT)
283 if (WaitForSingleObject( hThread, 0 ) == WAIT_TIMEOUT)
287 SuspendThread( hThread );
292 ctx.ContextFlags = CONTEXT_CONTROL;
293 GetThreadContext( hThread, &ctx );
297 PROGCTR(ctx) = (DWORD_PTR)_ForceDeath;
298 SetThreadContext( hThread, &ctx );
303 ResumeThread( hThread );
306 ReleaseMutex( _hmDelay );
308 ReleaseMutex( _hmControl );
312 void Thread::DelayDeath(
bool enable )
320 WaitForSingleObject( _hmControl, INFINITE );
327 WaitForSingleObject( _hmDelay, INFINITE );
333 ReleaseMutex( _hmDelay );
338 if ((_DelayCount == 0)
339 && (WaitForSingleObject( _heEnd, 0 ) == WAIT_OBJECT_0))
344 ReleaseMutex( _hmControl );
349 void Thread::_Cleanup(
bool closeThr )
361 #pragma message("MEMO: [Thread] _TProc requires /EHa compiler switch > " __FILE__ ":" PP_NSTR(__LINE__)) 364 static UINT __tpExFilter( UINT xcodeAct, PEXCEPTION_POINTERS pxp )
366 return (xcodeAct == pxp->ExceptionRecord->ExceptionCode)
367 ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH;
384 #ifdef INCL_THREAD_W95_SUPPORT // The index is pre-allocated 385 TlsSetValue( Thread::_TLSIndex, _this );
388 ExitCode = _this->Execute();
394 __except( __tpExFilter(
SE_KILLTHREAD, GetExceptionInformation() ))
396 ExitCode = ERROR_DBG_RIPEXCEPTION;
397 #ifdef INCL_THREAD_W95_SUPPORT 398 DeleteExceptionHandlerThunks( _this->_pThunk, _this->_hFileMap );
405 _this->_Cleanup(
true );
407 #ifdef INCL_THREAD_W95_SUPPORT 408 TlsSetValue( Thread::_TLSIndex, NULL );
418 void Thread::_ForceDeath(
void )
420 #ifdef INCL_THREAD_W95_SUPPORT // Work around Windows 95 execption problem. 422 _this->_pThunk = CreateExceptionHandlerThunks( &_this->_hFileMap );
425 RaiseException(
SE_KILLTHREAD, EXCEPTION_NONCONTINUABLE, 0, NULL );
430 #ifdef INCL_THREAD_W95_SUPPORT // Work around Windows 95 execption problem 433 DWORD Thread::_TLSIndex = TLS_OUT_OF_INDEXES;
439 typedef struct _EXCEPTIONREGISTRATIONRECORD {
440 _EXCEPTIONREGISTRATIONRECORD *pexrr;
442 } EXCEPTIONREGISTRATIONRECORD, *PEXCEPTIONREGISTRATIONRECORD;
446 const PEXCEPTIONREGISTRATIONRECORD pexrrEndMark =
447 (PEXCEPTIONREGISTRATIONRECORD) 0xFFFFFFFF;
451 const PVOID pvSharedMin = (PVOID) 0x80000000;
455 static const BYTE _MovAxImm[] = { (
BYTE)
'\xB8' };
456 static const BYTE _JmpAx[] = { (
BYTE)
'\xFF', (
BYTE)
'\xE0' };
462 BYTE abMovAxImm[
sizeof(_MovAxImm) ];
463 BYTE abJmpAddr[
sizeof(PROC) ];
464 BYTE abJmpAx[
sizeof(_JmpAx) ];
465 } EXCEPTTHUNK, *PEXCEPTTHUNK;
467 static PVOID CreateExceptionHandlerThunks( PHANDLE phFileMap )
484 PEXCEPTIONREGISTRATIONRECORD pexrrHead;
485 PEXCEPTIONREGISTRATIONRECORD pexrrCur;
489 osvi.dwOSVersionInfoSize =
sizeof(osvi);
490 GetVersionEx( &osvi );
491 BOOL fIsWin95 = (osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS);
497 __asm mov eax, fs:[0]
498 __asm mov pexrrHead, eax
501 pexrrCur = pexrrHead;
503 while (pexrrEndMark != pexrrCur)
506 if (pexrrCur->pvHandler < pvSharedMin)
510 pexrrCur = pexrrCur->pexrr;
515 *phFileMap = CreateFileMapping(
516 INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
517 0, (nThunkCnt+1) *
sizeof(EXCEPTTHUNK), NULL
519 if (NULL != *phFileMap)
521 pvRet = MapViewOfFile( *phFileMap, FILE_MAP_WRITE, 0,0,0 );
524 CloseHandle( *phFileMap );
529 pThunk = (PEXCEPTTHUNK) pvRet;
530 pexrrCur = pexrrHead;
532 while( 0 < nThunkCnt )
535 if (pexrrCur->pvHandler < pvSharedMin)
539 CopyMemory( pThunk->abMovAxImm, _MovAxImm,
sizeof(pThunk->abMovAxImm) );
540 CopyMemory( pThunk->abJmpAddr, &pexrrCur->pvHandler,
sizeof(pThunk->abJmpAddr) );
541 CopyMemory( pThunk->abJmpAx, _JmpAx,
sizeof(pThunk->abJmpAx) );
545 pexrrCur->pvHandler = (PVOID) pThunk;
549 pexrrCur = pexrrCur->pexrr;
552 FillMemory( pThunk,
sizeof(pThunk), 0 );
559 static void DeleteExceptionHandlerThunks( PVOID pvThunk, HANDLE hFileMap )
561 PEXCEPTIONREGISTRATIONRECORD pexrrCur;
563 PEXCEPTTHUNK pThunkCur;
569 __asm mov eax, fs:[0]
570 __asm mov pexrrCur, eax
572 pThunk = (PEXCEPTTHUNK) pvThunk;
576 while(
'\0' != pThunk[nThunkCnt].abMovAxImm[0] )
583 while (pexrrEndMark != pexrrCur)
585 if ( (PVOID) pThunk <= pexrrCur->pvHandler
586 && pexrrCur->pvHandler < (PVOID) &pThunk[nThunkCnt] )
591 pThunkCur = (PEXCEPTTHUNK) pexrrCur->pvHandler;
592 CopyMemory( &pexrrCur->pvHandler, pThunkCur->abJmpAddr,
sizeof(pexrrCur->pvHandler) );
594 pexrrCur = pexrrCur->pexrr;
596 UnmapViewOfFile( pvThunk );
599 if (NULL != hFileMap) CloseHandle( hFileMap );
602 #endif//def INCL_THREAD_W95_SUPPORT 604 #endif//def HAVE_STRUCTURED_EH
HANDLE CloseHandleEx(HANDLE H)
bool WaitFor(HANDLE hObj, DWORD msWait)
#define END_NAMESPACE(name)
void __cdecl DPrint(int Level, CSTR Fmt,...)
BOOL(WINAPI *SysImgList::Shell_GetImageLists)(HIMAGELIST *pimlLarge
Debug and error handling support.
#define BEGIN_NAMESPACE(name)
Common include; Added types, small "ubiquitous" utilities, et c.