Ignore:
Timestamp:
Jun 18, 2009, 11:53:26 AM (16 years ago)
Author:
ydario
Message:

Kernel32 updates.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/kernel32/hmthread.cpp

    r9949 r21302  
    3030#include <HandleManager.H>
    3131#include "HMThread.h"
     32#include "oslibdos.h"
    3233#include "oslibthread.h"
     34#include "oslibmem.h"
    3335
    3436#include <win\thread.h>
     
    5759                                         DWORD                  fdwCreate,
    5860                                         LPDWORD                lpIDThread,
    59                                          BOOL                   fFirstThread)
     61                                         BOOL                   fRegisterThread)
    6062{
    6163    Win32Thread *winthread;
     
    7880
    7981    //SvL: This doesn't really create a thread, but only sets up the
    80     //     handle of thread 0
    81     if(fFirstThread) {
     82    //     handle of the current thread.
     83    if(fRegisterThread) {
    8284        pHMHandleData->hHMHandle = O32_GetCurrentThread(); //return Open32 handle of thread
    8385        return pHMHandleData->hHMHandle;
     
    144146                                          PHMHANDLEDATA pHMSrcHandle,
    145147                                          HANDLE  destprocess,
    146                                           PHANDLE desthandle,
    147148                                          DWORD   fdwAccess,
    148149                                          BOOL    fInherit,
     
    153154  OBJ_THREAD *threadsrc = (OBJ_THREAD *)pHMSrcHandle->dwUserData;
    154155
    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));
    157158
    158159  if(destprocess != srcprocess)
     
    162163      return FALSE;
    163164  }
    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);
    165167
    166168  if(ret == TRUE) {
    167169       OBJ_THREAD *threaddest = (OBJ_THREAD *)malloc(sizeof(OBJ_THREAD));
    168170       if(threaddest == NULL) {
    169            O32_CloseHandle(*desthandle);
     171           O32_CloseHandle(pHMHandleData->hHMHandle);
    170172           SetLastError(ERROR_NOT_ENOUGH_MEMORY);
    171173           return FALSE;
     
    180182       }
    181183
    182        pHMHandleData->hHMHandle = *desthandle;
    183184       return TRUE;
    184185  }
    185   else return FALSE;
     186  else
     187  {
     188      dprintf(("O32_DuplicateHandle failed for handle %x!!", pHMSrcHandle->hHMHandle));
     189      return FALSE;
     190  }
    186191}
    187192//******************************************************************************
     
    209214{
    210215    DWORD dwSuspend;
     216    CONTEXT     context;
    211217    OBJ_THREAD *threadobj = (OBJ_THREAD *)pHMHandleData->dwUserData;
    212218
    213219    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
    215278        teb->o.odin.dwSuspend--;
    216279        dprintf(("ResumeThread (%08xh) : count %d", pHMHandleData->hHMHandle, teb->o.odin.dwSuspend));
    217     }
     280
    218281    dwSuspend = O32_ResumeThread(pHMHandleData->hHMHandle);
    219     if(dwSuspend == -1) {
     282    if(dwSuspend == -1)
     283    {
    220284        teb->o.odin.dwSuspend++;
    221285        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
    223314    return dwSuspend;
    224315}
     
    264355}
    265356//******************************************************************************
    266 //TODO: Implement this??
     357//******************************************************************************
     358#ifdef DEBUG
     359void 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//******************************************************************************
    267384//******************************************************************************
    268385BOOL HMDeviceThreadClass::GetThreadContext(HANDLE hThread, PHMHANDLEDATA pHMHandleData, PCONTEXT lpContext)
    269386{
    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//
    285441//******************************************************************************
    286442BOOL HMDeviceThreadClass::SetThreadContext(HANDLE hThread, PHMHANDLEDATA pHMHandleData, const CONTEXT *lpContext)
    287443{
    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);
    290491  return FALSE;
    291492}
Note: See TracChangeset for help on using the changeset viewer.