From: Hector Santos on 3 Jan 2010 20:19 Folks, I'm trying to get a handle of this situation which makes it hard to find out what the issue because of all the different version of Windows and all possible all the different security patches available. I have an old Borland C/C++ OWL (Object Windows Library) GUI application that depending on the version of XP and 2003, it fails to run with a GPF in its WndProc procedure. I was able to repeat it on my boxes: XP SP2 20003 SP1 I updated the XP box to SP3 and this resolved the issue. But other customers still with XP SP2 it works fine. In the 2003 box, I updated it SP2 and it still has the problem. I just asked a large customer who has every current windows, and he just reported it works find on VISTA, 2008, Windows 7 and an older box with 2003. He is always updated, so I take it the 2003 is SP2. The issue seems to be related to the version of USER32.DLL and possible SetWindowLong. The old BC45 compiler didn't have a wrapper for the SetWindowLongPtr() so I set that. Its just a wrapper to a pointer. There are some KB articles, namely, this security patch: http://support.microsoft.com/default.aspx?scid=kb;en-us;840987 Anyway, I am not 100% familar with "thunking" or why it is needed for a 32 bit application, but the BC45 OWL library has this for its InitWndProc which is used in the WNDCLASS.lpfnWndProc; // // Creation window pointer for InitWndProc // TWindow* _OWLDATA CreationWindow = 0; void _OWLFUNC SetCreationWindow(TWindow* w) { CreationWindow = w; } 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)); //---------------- GPF IN 2003 occurs here ------------- return (*(WNDPROC)(thunk))(hWindow, message, wParam, lParam); } What I traced in the OWL library it shows that after it create a TFrameWindow which is a sub class TWindow, it calls TWindow::Create() and in here it prepares the class and registers it: void TWindow::GetWindowClass(WNDCLASS& wndClass) { wndClass.cbClsExtra = 0; wndClass.cbWndExtra = 0; wndClass.hInstance = *GetModule(); wndClass.hIcon = 0; wndClass.hCursor = ::LoadCursor(0, IDC_ARROW); wndClass.hbrBackground = HBRUSH(COLOR_WINDOW + 1); wndClass.lpszMenuName = 0; wndClass.lpszClassName = GetClassName(); wndClass.style = CS_DBLCLKS; wndClass.lpfnWndProc = ::InitWndProc; } In the TWindows.RegisterClass(), it finally calls the global SetCreationWindow() function: ::SetCreationWindow(this) with this being TWindow * object. It sets the TWindow.Thunk member accessed by TWindow:GetThunk() used in InitWndProc() above in the TWindow constructor using the following: 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; } The problem is that this is nearly 15+ year old code By Borland for what was a solid OWL library and worked on very windows until recently and right now it seems to be only with Window 2003. So I am wondering if there a known issue. I did see one "How to Thunk" KB where it shows using the Call 0xE9 instead of 0xE8 as shown above. Some guidance would be appreciated from Win32 Kernel experts. I have exhausted everything I can think of. Thanks -- HLS
From: Ivan Brugiolo [MSFT] on 3 Jan 2010 21:34 First of all, have you considered Data-Execution-Protection / NX issues ? NX is disabled in all but trusted system processes on WinXp, while it is enabled on all but explicitly disabled applications on Server SKUs. There is a long list of DLLs, more or less known to the system and complete , where DEP is disabled for a process that fails to set the execution bit on pieces of memory where it uses to generate code to be later-on executed. SetProcessDEPPolicy should be your friend here, if you are writing code, or, the UI for DEP/NX should allow you to white-list that application. -- -- This posting is provided "AS IS" with no warranties, and confers no rights. Use of any included script samples are subject to the terms specified at http://www.microsoft.com/info/cpyright.htm "Hector Santos" <sant9442(a)nospam.gmail.com> wrote in message news:uAkbawNjKHA.2780(a)TK2MSFTNGP05.phx.gbl... > Folks, > > I'm trying to get a handle of this situation which makes it hard to find > out what the issue because of all the different version of Windows and all > possible all the different security patches available. > > I have an old Borland C/C++ OWL (Object Windows Library) GUI application > that depending on the version of XP and 2003, it fails to run with a GPF > in its WndProc procedure. > > I was able to repeat it on my boxes: > > XP SP2 > 20003 SP1 > > I updated the XP box to SP3 and this resolved the issue. But other > customers still with XP SP2 it works fine. In the 2003 box, I updated it > SP2 and it still has the problem. > > I just asked a large customer who has every current windows, and he just > reported it works find on VISTA, 2008, Windows 7 and an older box with > 2003. He is always updated, so I take it the 2003 is SP2. > > The issue seems to be related to the version of USER32.DLL and possible > SetWindowLong. The old BC45 compiler didn't have a wrapper for the > SetWindowLongPtr() so I set that. Its just a wrapper to a pointer. > > There are some KB articles, namely, this security patch: > > http://support.microsoft.com/default.aspx?scid=kb;en-us;840987 > > Anyway, I am not 100% familar with "thunking" or why it is needed for a 32 > bit application, but the BC45 OWL library has this for its InitWndProc > which is used in the WNDCLASS.lpfnWndProc; > > // > // Creation window pointer for InitWndProc > // > TWindow* _OWLDATA CreationWindow = 0; > > void _OWLFUNC > SetCreationWindow(TWindow* w) > { > CreationWindow = w; > } > > 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)); > > //---------------- GPF IN 2003 occurs here ------------- > return (*(WNDPROC)(thunk))(hWindow, message, wParam, lParam); > } > > What I traced in the OWL library it shows that after it create a > TFrameWindow which is a sub class TWindow, it calls TWindow::Create() and > in here it prepares the class and registers it: > > void > TWindow::GetWindowClass(WNDCLASS& wndClass) > { > wndClass.cbClsExtra = 0; > wndClass.cbWndExtra = 0; > wndClass.hInstance = *GetModule(); > wndClass.hIcon = 0; > wndClass.hCursor = ::LoadCursor(0, IDC_ARROW); > wndClass.hbrBackground = HBRUSH(COLOR_WINDOW + 1); > wndClass.lpszMenuName = 0; > wndClass.lpszClassName = GetClassName(); > wndClass.style = CS_DBLCLKS; > wndClass.lpfnWndProc = ::InitWndProc; > } > > In the TWindows.RegisterClass(), it finally calls the global > SetCreationWindow() function: > > ::SetCreationWindow(this) > > with this being TWindow * object. > > It sets the TWindow.Thunk member accessed by TWindow:GetThunk() used in > InitWndProc() above in the TWindow constructor using the following: > > 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; > } > > The problem is that this is nearly 15+ year old code By Borland for what > was a solid OWL library and worked on very windows until recently and > right now it seems to be only with Window 2003. > > So I am wondering if there a known issue. > > I did see one "How to Thunk" KB where it shows using the Call 0xE9 instead > of 0xE8 as shown above. > > Some guidance would be appreciated from Win32 Kernel experts. I have > exhausted everything I can think of. > > Thanks > > -- > HLS
From: Jogy on 15 Jan 2010 06:32 "Hector Santos" wrote: > Folks, > > I'm trying to get a handle of this situation which makes it hard to > find out what the issue because of all the different version of > Windows and all possible all the different security patches available. > > I have an old Borland C/C++ OWL (Object Windows Library) GUI > application that depending on the version of XP and 2003, it fails to > run with a GPF in its WndProc procedure. > > I was able to repeat it on my boxes: > > XP SP2 > 20003 SP1 > > I updated the XP box to SP3 and this resolved the issue. But other > customers still with XP SP2 it works fine. In the 2003 box, I updated > it SP2 and it still has the problem. > > I just asked a large customer who has every current windows, and he > just reported it works find on VISTA, 2008, Windows 7 and an older box > with 2003. He is always updated, so I take it the 2003 is SP2. > > The issue seems to be related to the version of USER32.DLL and > possible SetWindowLong. The old BC45 compiler didn't have a wrapper > for the SetWindowLongPtr() so I set that. Its just a wrapper to a pointer. > > There are some KB articles, namely, this security patch: > > http://support.microsoft.com/default.aspx?scid=kb;en-us;840987 > > Anyway, I am not 100% familar with "thunking" or why it is needed for > a 32 bit application, but the BC45 OWL library has this for its > InitWndProc which is used in the WNDCLASS.lpfnWndProc; Hello, This is a known issue. The OWL uses a thunking mechanism in order to maintain the relation between the framework class (TWindow) and the Windows handle (a HWND) All C++ GUI frameworks have to di this in one way or another, in order to be able to process Windows messages in an object-oriented way. The MFC approach was, I believe, to use a map between HWNDs and CWnd pointers. The OWL approach, with low level thunks, was faster, but non-portable. OWL was dropped by Borland 10 years ago, but an open-source project named OWLNext picked it up and continued the development. The latest versions of OWLNext solve the DEP/thunking problems, and also have added support for modern Windows GUI elements, and can be used with recent C++ compilers like Visual C++ 2008/2010 If you are interested in upgrading your application, come to the OWLNext project site (http://owlnext.sourceforge.net/) for more information. Jogy
From: Hector Santos on 16 Jan 2010 01:47 Hi Jogy, I really did try to search for a "group" that took over OWL. It was hard to believe that this issue was not already encountered and addressed in some OWL patch or 3rd party update. I am normally a good researcher but I missed this one. :) So I appreciate your input and I will most definitely look into OwlNext. I will be interested to see how much single sourcing I can do by compiling with the VS C/C++ compiler. :) Thanks for the input again. -- HLS Jogy wrote: > > Hello, > > This is a known issue. > > The OWL uses a thunking mechanism in order to maintain the relation > between the framework class (TWindow) and the Windows handle (a HWND) > > All C++ GUI frameworks have to di this in one way or another, > in order to be able to process Windows messages in an object-oriented way. > > The MFC approach was, I believe, to use a map between HWNDs and CWnd pointers. > > The OWL approach, with low level thunks, was faster, but non-portable. > > OWL was dropped by Borland 10 years ago, but an open-source project > named OWLNext picked it up and continued the development. > > The latest versions of OWLNext solve the DEP/thunking problems, > and also have added support for modern Windows GUI elements, > and can be used with recent C++ compilers like Visual C++ 2008/2010 > > If you are interested in upgrading your application, come to the OWLNext > project site > (http://owlnext.sourceforge.net/) for more information. > > Jogy >
From: Hector Santos on 16 Jan 2010 02:50 Jogy, I'm been trying to download the OwlNext source code from http://cc.embarcadero.com/item/27219 There is no server response and I tried from SOHO and from my company network - two different sub-nets. What gives with this company that took over the once upon a time 'best kept secret' in the market? :) Also, is there a minimum patch available to resolve the thunking issue within a BC 4.5 compile? Thanks -- HLS Hector Santos wrote: > Hi Jogy, > > I really did try to search for a "group" that took over OWL. It was hard > to believe that this issue was not already encountered and addressed in > some OWL patch or 3rd party update. I am normally a good researcher but > I missed this one. :) > > So I appreciate your input and I will most definitely look into > OwlNext. I will be interested to see how much single sourcing I can do > by compiling with the VS C/C++ compiler. :) > > Thanks for the input again. >
|
Next
|
Last
Pages: 1 2 Prev: WM_TIMECHANGE Message Event Next: SetWindowLong GWL_WNDPROC XP,2003 - SOLVED |