//---------------------------------------------------------------------------- // ObjectWindows // (C) Copyright 1991, 1994 by Borland International, All Rights Reserved // // Internal object thunk creation & maintanance. //---------------------------------------------------------------------------- #include #include #include #include #if defined(BI_PLAT_WIN32) # include #endif LRESULT FAR PASCAL _export StdWndProc(HWND, uint, WPARAM, LPARAM); TProcInstance StdWndProcInstance((FARPROC)StdWndProc); // // Creation window pointer for InitWndProc // TWindow* _OWLDATA CreationWindow = 0; void _OWLFUNC SetCreationWindow(TWindow* w) { CreationWindow = w; } uint16 far _OWLFUNC OWLGetVersion() { return OWLVersion; } // // Initial WndProc called when an Owl window is first created. // Subclasses the window function by installing the thunk then calls the // thunk to get this first message to the window. // LRESULT CALLBACK __export InitWndProc(HWND hWindow, uint message, WPARAM wParam, LPARAM lParam) { // If there's no creation window, i.e. we'll be aliasing a resource, // then we can't do anything now. Create() will take care of it later // if (!CreationWindow) return ::DefWindowProc(hWindow, message, wParam, lParam); // install "DefWindowProc" as the window function BEFORE we request the // subclassings; otherwise it looks like we subclassed "InitWndProc" // CreationWindow->HWindow = hWindow; #if defined(BI_PLAT_WIN32) CreationWindow->DefaultProc = (WNDPROC)GetProcAddress( (HINSTANCE)GetModuleHandle("USER32"), "DefWindowProcA"); #else CreationWindow->DefaultProc = ::DefWindowProc; #endif // Get the thunk & then zero out creation window so that it is not // inadvertently used. // WNDPROC thunk = CreationWindow->GetThunk(); CreationWindow = 0; // Set the thunk as the window proc, & call it with this first message. // SetWindowLong(hWindow, GWL_WNDPROC, uint32(thunk)); return (*(WNDPROC)(thunk))(hWindow, message, wParam, lParam); } // // Win32 version of the instance thunking mechanism // #if defined(BI_PLAT_WIN32) struct TInstanceThunk { char Call; int Offset; PROC WndProcPtr; TWindow* Window; char Code[6]; }; static const int CODEDISP = offsetof(TInstanceThunk, Code) - offsetof(TInstanceThunk, WndProcPtr); WNDPROC CreateInstanceThunk(TWindow* w) { TInstanceThunk* thunk = new TInstanceThunk; thunk->Call = 0xE8; // CALL rel32 thunk->Offset = CODEDISP; // relative displacement to Code[5] thunk->WndProcPtr = StdWndProcInstance; thunk->Window = w; // // POP ECX // // pop return address of call into ecx (address of member "WndProcPtr") // thunk->Code[0] = 0x59; // // MOV EAX,[ECX+4] // // load "Window" into ebx // thunk->Code[1] = 0x8B; // MOV r32,r/m32 thunk->Code[2] = 0x41; // eax,disp8[ECX] thunk->Code[3] = 0x04; // +4 // // JMP [ECX] // // jump to window function StdWndProc // thunk->Code[4] = 0xFF; // JMP r/m32 thunk->Code[5] = 0x21; // [ECX] return (WNDPROC)thunk; } void FreeInstanceThunk(WNDPROC proc) { delete (TInstanceThunk*)proc; } // // Win16 version of the instance thunking mechanism // #elif defined(BI_PLAT_WIN16) // // AllocCSToDSAlias was not declared in windows.h // extern "C" uint16 FAR PASCAL AllocCSToDSAlias(uint16); struct TInstanceThunk { char Code; uint16 Offset; union Ptr { struct TInstanceThunk far* Next; TWindow far* Window; } ptr; }; struct TThunkBlock { uint16 Next; char Code[5]; void far* WndProcPtr; struct TInstanceThunk Thunks[34]; }; static uint16 ThunkBlockList = 0; static TInstanceThunk far* ThunkFreeList = 0; WNDPROC CreateInstanceThunk(TWindow* w) { char blockCode[5]; TThunkBlock far* block; TInstanceThunk far* thunk; WNDPROC objInstance; // POP BX blockCode[0] = 0x5b; // LES BX, CS:[BX] blockCode[1] = 0x2e; blockCode[2] = 0xc4; blockCode[3] = 0x1f; // JMP FAR StdWndProc blockCode[4] = 0xea; if (!ThunkFreeList) { block = (TThunkBlock far*)GlobalLock(GlobalAlloc(GMEM_FIXED | GMEM_SHARE | GMEM_NOT_BANKED, sizeof(TThunkBlock))); block->Next = ThunkBlockList; memcpy(block->Code, blockCode, 5); block->WndProcPtr = (void far*)StdWndProcInstance; thunk = block->Thunks; do { thunk->Code = 0xE8; thunk->Offset = (2 - 3) - FP_OFF(thunk); thunk->ptr.Next = ThunkFreeList; ThunkFreeList = thunk; thunk = (TInstanceThunk far*)MK_FP( FP_SEG(thunk), FP_OFF(thunk)+sizeof(TInstanceThunk) ); } while (FP_OFF(thunk) != sizeof(TThunkBlock)); ThunkBlockList = FP_SEG(block); PrestoChangoSelector(FP_SEG(block), FP_SEG(block)); } objInstance = (WNDPROC)ThunkFreeList; thunk = (TInstanceThunk far*)MK_FP(AllocCSToDSAlias(FP_SEG(ThunkFreeList)), FP_OFF(ThunkFreeList)); ThunkFreeList = thunk->ptr.Next; thunk->ptr.Window = (TWindow far*)w; FreeSelector(FP_SEG(thunk)); return objInstance; } void FreeInstanceThunk(WNDPROC p) { TInstanceThunk far* thunk = (TInstanceThunk far*)MK_FP(AllocCSToDSAlias(FP_SEG(p)), FP_OFF(p)); thunk->ptr.Next = ThunkFreeList; FreeSelector(FP_SEG(thunk)); ThunkFreeList = (TInstanceThunk far*)p; } #endif // BI_PLAT_XXX