Changeset 21302 for trunk/src/kernel32/hmthread.cpp
- Timestamp:
- Jun 18, 2009, 11:53:26 AM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kernel32/hmthread.cpp
r9949 r21302 30 30 #include <HandleManager.H> 31 31 #include "HMThread.h" 32 #include "oslibdos.h" 32 33 #include "oslibthread.h" 34 #include "oslibmem.h" 33 35 34 36 #include <win\thread.h> … … 57 59 DWORD fdwCreate, 58 60 LPDWORD lpIDThread, 59 BOOL f FirstThread)61 BOOL fRegisterThread) 60 62 { 61 63 Win32Thread *winthread; … … 78 80 79 81 //SvL: This doesn't really create a thread, but only sets up the 80 // handle of th read 081 if(f FirstThread) {82 // handle of the current thread. 83 if(fRegisterThread) { 82 84 pHMHandleData->hHMHandle = O32_GetCurrentThread(); //return Open32 handle of thread 83 85 return pHMHandleData->hHMHandle; … … 144 146 PHMHANDLEDATA pHMSrcHandle, 145 147 HANDLE destprocess, 146 PHANDLE desthandle,147 148 DWORD fdwAccess, 148 149 BOOL fInherit, … … 153 154 OBJ_THREAD *threadsrc = (OBJ_THREAD *)pHMSrcHandle->dwUserData; 154 155 155 dprintf(("KERNEL32:HMDeviceThreadClass::DuplicateHandle (%08x,%08x,%08x,%08x ,%08x)",156 pHMHandleData, srcprocess, pHMSrcHandle->hHMHandle, destprocess , desthandle));156 dprintf(("KERNEL32:HMDeviceThreadClass::DuplicateHandle (%08x,%08x,%08x,%08x)", 157 pHMHandleData, srcprocess, pHMSrcHandle->hHMHandle, destprocess)); 157 158 158 159 if(destprocess != srcprocess) … … 162 163 return FALSE; 163 164 } 164 ret = O32_DuplicateHandle(srcprocess, pHMSrcHandle->hHMHandle, destprocess, desthandle, fdwAccess, fInherit, fdwOptions); 165 pHMHandleData->hHMHandle = 0; 166 ret = O32_DuplicateHandle(srcprocess, pHMSrcHandle->hHMHandle, destprocess, &pHMHandleData->hHMHandle, fdwAccess, fInherit, fdwOptions); 165 167 166 168 if(ret == TRUE) { 167 169 OBJ_THREAD *threaddest = (OBJ_THREAD *)malloc(sizeof(OBJ_THREAD)); 168 170 if(threaddest == NULL) { 169 O32_CloseHandle( *desthandle);171 O32_CloseHandle(pHMHandleData->hHMHandle); 170 172 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 171 173 return FALSE; … … 180 182 } 181 183 182 pHMHandleData->hHMHandle = *desthandle;183 184 return TRUE; 184 185 } 185 else return FALSE; 186 else 187 { 188 dprintf(("O32_DuplicateHandle failed for handle %x!!", pHMSrcHandle->hHMHandle)); 189 return FALSE; 190 } 186 191 } 187 192 //****************************************************************************** … … 209 214 { 210 215 DWORD dwSuspend; 216 CONTEXT context; 211 217 OBJ_THREAD *threadobj = (OBJ_THREAD *)pHMHandleData->dwUserData; 212 218 213 219 TEB *teb = GetTEBFromThreadHandle(GET_THREADHANDLE(hThread)); 214 if(teb) { 220 if(teb == NULL) { 221 dprintf(("ERROR: invalid thread handle")); 222 SetLastError(ERROR_INVALID_THREAD_ID); //?? 223 return -1; 224 } 225 226 context.Eip = 0; 227 if(teb->o.odin.context.ContextFlags) 228 { 229 context.ContextFlags = CONTEXT_CONTROL; 230 if(GetThreadContext(hThread, pHMHandleData, &context) == FALSE) 231 { 232 DebugInt3(); 233 context.Eip = 0; 234 } 235 if(teb->o.odin.dwSuspend == 1 && teb->o.odin.context.ContextFlags && context.Eip) 236 {//SetThreadContext was called for this thread and it's about to be restored 237 238 //Since there's no equivalent of SetThreadContext in OS/2, we put an 239 //illegal instruction at the instruction pointer of this thread to 240 //make sure an exception is triggered. Inside the exception handler 241 //of the thread we can change the registers. 242 //(XCPT_PRIVILEGED_INSTRUCTION exception handler in exceptions.cpp) 243 //(see detailed description in the HMDeviceThreadClass::SetThreadContext method) 244 USHORT *lpEIP = (USHORT *)context.Eip; 245 246 if(*lpEIP != SETTHREADCONTEXT_INVALID_LOCKOPCODE) 247 { 248 int size; 249 250 teb->o.odin.dwAliasOffset = (DWORD)lpEIP & 0xFFF; 251 if(teb->o.odin.dwAliasOffset + 2 >= PAGE_SIZE) { 252 size = 8192; 253 } 254 else size = teb->o.odin.dwAliasOffset + 2; 255 256 lpEIP = (USHORT *)((DWORD)lpEIP & ~0xFFF); 257 258 if(OSLibDosAliasMem(lpEIP, size, &teb->o.odin.lpAlias, PAG_READ|PAG_WRITE) == 0) 259 { 260 teb->o.odin.savedopcode = *(USHORT*)((char *)teb->o.odin.lpAlias+teb->o.odin.dwAliasOffset); 261 262 //sti -> undefined opcode exception 263 *(USHORT *)((char *)teb->o.odin.lpAlias+teb->o.odin.dwAliasOffset) = SETTHREADCONTEXT_INVALID_LOCKOPCODE; 264 } 265 else DebugInt3(); 266 267 //temporarily boost priority to ensure this thread is scheduled first 268 //we reduce the priority in the exception handler 269 OSLibDosSetMaxPriority(ODIN_TO_OS2_THREADID(teb->o.odin.threadId)); 270 } 271 else { 272 dprintf(("already patched!?!")); 273 DebugInt3(); 274 } 275 } 276 } 277 215 278 teb->o.odin.dwSuspend--; 216 279 dprintf(("ResumeThread (%08xh) : count %d", pHMHandleData->hHMHandle, teb->o.odin.dwSuspend)); 217 } 280 218 281 dwSuspend = O32_ResumeThread(pHMHandleData->hHMHandle); 219 if(dwSuspend == -1) { 282 if(dwSuspend == -1) 283 { 220 284 teb->o.odin.dwSuspend++; 221 285 dprintf(("!ERROR!: ResumeThread FAILED")); 222 } 286 287 if(teb->o.odin.dwSuspend == 1 && teb->o.odin.context.ContextFlags && context.Eip) 288 {//Undo previous patching 289 char *lpEIP = (char *)context.Eip; 290 291 if(*lpEIP == SETTHREADCONTEXT_INVALID_LOCKOPCODE) 292 { 293 dprintf(("Undo SetThreadContext patching!!")); 294 295 USHORT *lpAlias = (USHORT*)((char *)teb->o.odin.lpAlias + teb->o.odin.dwAliasOffset); 296 //put back old byte 297 *lpAlias = teb->o.odin.savedopcode; 298 299 //restore the original priority (we boosted it to ensure this thread was scheduled first) 300 ::SetThreadPriority(teb->o.odin.hThread, ::GetThreadPriority(teb->o.odin.hThread)); 301 302 OSLibDosFreeMem(teb->o.odin.lpAlias); 303 } 304 else { 305 dprintf(("not patched!?!")); 306 DebugInt3(); 307 } 308 teb->o.odin.dwAliasOffset = 0; 309 teb->o.odin.lpAlias = NULL; 310 teb->o.odin.context.ContextFlags = 0; 311 } 312 } 313 223 314 return dwSuspend; 224 315 } … … 264 355 } 265 356 //****************************************************************************** 266 //TODO: Implement this?? 357 //****************************************************************************** 358 #ifdef DEBUG 359 void DumpContext(CONTEXT *lpContext) 360 { 361 dprintf(("************************ THREAD CONTEXT ************************")); 362 if(lpContext->ContextFlags & CONTEXT_CONTROL) { 363 dprintf(("CS:EIP %04x:%08x FLAGS %08x", lpContext->SegCs, lpContext->Eip, lpContext->EFlags)); 364 dprintf(("SS:ESP %04x:%08x EBP %08x", lpContext->SegSs, lpContext->Esp, lpContext->Ebp)); 365 } 366 if(lpContext->ContextFlags & CONTEXT_INTEGER) { 367 dprintf(("EAX %08x EBX %08x ECX %08x EDX %08x", lpContext->Eax, lpContext->Ebx, lpContext->Ecx, lpContext->Edx)); 368 dprintf(("ESI %08x EDI %08x", lpContext->Esi, lpContext->Edi)); 369 } 370 if(lpContext->ContextFlags & CONTEXT_SEGMENTS) { 371 dprintf(("DS %04x ES %04x FS %04x GS %04x", (ULONG)lpContext->SegDs, (ULONG)lpContext->SegEs, (ULONG)lpContext->SegFs, (ULONG)lpContext->SegGs)); 372 } 373 dprintf(("************************ THREAD CONTEXT ************************")); 374 // if(lpContext->ContextFlags & CONTEXT_FLOATING_POINT) { 375 // //TODO: First 7 dwords the same? 376 // memcpy(&lpContext->FloatSave, ctxrec.ctx_env, sizeof(ctxrec.ctx_env)); 377 // memcpy(&lpContext->FloatSave.RegisterArea, ctxrec.ctx_stack, sizeof(ctxrec.ctx_stack)); 378 // } 379 } 380 #else 381 #define DumpContext(a) 382 #endif 383 //****************************************************************************** 267 384 //****************************************************************************** 268 385 BOOL HMDeviceThreadClass::GetThreadContext(HANDLE hThread, PHMHANDLEDATA pHMHandleData, PCONTEXT lpContext) 269 386 { 270 dprintf(("GetThreadContext NOT IMPLEMENTED!! (TRUE)\n")); 271 memset(lpContext, 0, sizeof(CONTEXT)); 272 273 /* make up some plausible values for segment registers */ 274 lpContext->SegCs = getCS(); 275 lpContext->SegDs = getDS(); 276 lpContext->SegSs = getSS(); 277 lpContext->SegEs = getES(); 278 lpContext->SegGs = getGS(); 279 lpContext->SegFs = GetFS(); 280 281 return TRUE; 282 } 283 //****************************************************************************** 284 //TODO: Implement this?? 387 OBJ_THREAD *threadobj = (OBJ_THREAD *)pHMHandleData->dwUserData; 388 BOOL ret; 389 390 TEB *teb = GetTEBFromThreadHandle(GET_THREADHANDLE(hThread)); 391 if(teb) { 392 if(teb->o.odin.dwSuspend == 0) { 393 dprintf(("ERROR: thread not suspended!!")); 394 DebugInt3(); 395 SetLastError(ERROR_INVALID_OPERATION); //??? 396 return FALSE; 397 } 398 399 ret = OSLibQueryThreadContext(ODIN_TO_OS2_THREADID(teb->o.odin.threadId), teb->teb_sel, lpContext); 400 if(ret == TRUE) { 401 DumpContext(lpContext); 402 } 403 return ret; 404 } 405 dprintf(("!WARNING!: TEB not found!!")); 406 SetLastError(ERROR_INVALID_HANDLE); 407 return FALSE; 408 } 409 //****************************************************************************** 410 // HMDeviceThreadClass::SetThreadContext 411 // 412 // Change the context (registers) of a suspended thread 413 // 414 // Parameters: 415 // 416 // HANDLE hThread - thread handle 417 // PHMHANDLEDATA pHMHandleData - handle data 418 // const CONTEXT *lpContext - context record (IN) 419 // 420 // Returns: 421 // TRUE - success 422 // FALSE - failure 423 // 424 // Remarks: 425 // 426 // Since OS/2 doesn't provide an equivalent for this function, we need to change 427 // the thread context manually. (DosDebug isn't really an option) 428 // 429 // We save the new context in the TEB structure. When this thread is 430 // activated by ResumeThread, we'll change the instruction addressed by the 431 // thread's EIP to an invalid instruction (sti). 432 // When the thread is activated, it will generate an exception. Inside the 433 // exception handler we change the registers, restore the original memory 434 // and continue. 435 // To make sure the thread is executed first and noone else will execute the 436 // invalid instruction, we temporarily boost the thread's priority to the max. 437 // (time critical, delta +31; max priority of win32 threads is time critical, 438 // delta 0) 439 // The priority is restored in the exception handler. 440 // 285 441 //****************************************************************************** 286 442 BOOL HMDeviceThreadClass::SetThreadContext(HANDLE hThread, PHMHANDLEDATA pHMHandleData, const CONTEXT *lpContext) 287 443 { 288 dprintf(("SetThreadContext NOT IMPLEMENTED!!\n")); 289 444 OBJ_THREAD *threadobj = (OBJ_THREAD *)pHMHandleData->dwUserData; 445 BOOL ret; 446 447 DumpContext((CONTEXT *)lpContext); 448 449 TEB *teb = GetTEBFromThreadHandle(GET_THREADHANDLE(hThread)); 450 if(teb) 451 { 452 if(teb->o.odin.dwSuspend == 0) { 453 dprintf(("ERROR: thread not suspended!!")); 454 SetLastError(ERROR_INVALID_OPERATION); //??? 455 return FALSE; 456 } 457 if(lpContext->ContextFlags & CONTEXT_CONTROL) { 458 teb->o.odin.context.ContextFlags |= CONTEXT_CONTROL; 459 teb->o.odin.context.Ebp = lpContext->Ebp; 460 teb->o.odin.context.Eip = lpContext->Eip; 461 teb->o.odin.context.SegCs = lpContext->SegCs; 462 teb->o.odin.context.EFlags = lpContext->EFlags; 463 teb->o.odin.context.Esp = lpContext->Esp; 464 teb->o.odin.context.SegSs = lpContext->SegSs; 465 } 466 if(lpContext->ContextFlags & CONTEXT_INTEGER) { 467 teb->o.odin.context.ContextFlags |= CONTEXT_INTEGER; 468 teb->o.odin.context.Edi = lpContext->Edi; 469 teb->o.odin.context.Esi = lpContext->Esi; 470 teb->o.odin.context.Ebx = lpContext->Ebx; 471 teb->o.odin.context.Edx = lpContext->Edx; 472 teb->o.odin.context.Ecx = lpContext->Ecx; 473 teb->o.odin.context.Eax = lpContext->Eax; 474 } 475 if(lpContext->ContextFlags & CONTEXT_SEGMENTS) { 476 teb->o.odin.context.ContextFlags |= CONTEXT_SEGMENTS; 477 teb->o.odin.context.SegGs = lpContext->SegGs; 478 teb->o.odin.context.SegFs = lpContext->SegFs; 479 teb->o.odin.context.SegEs = lpContext->SegEs; 480 teb->o.odin.context.SegDs = lpContext->SegDs; 481 } 482 if(lpContext->ContextFlags & CONTEXT_FLOATING_POINT) { 483 teb->o.odin.context.ContextFlags |= CONTEXT_FLOATING_POINT; 484 memcpy(&teb->o.odin.context.FloatSave, &lpContext->FloatSave, sizeof(lpContext->FloatSave)); 485 } 486 SetLastError(ERROR_SUCCESS); 487 return TRUE; 488 } 489 dprintf(("!WARNING!: TEB not found!!")); 490 SetLastError(ERROR_INVALID_HANDLE); 290 491 return FALSE; 291 492 }
Note:
See TracChangeset
for help on using the changeset viewer.