From: Hector Santos on
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
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



"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
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
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.
>