[ros-kernel] Re: Status of Explorer under ReactOS - Bug #42 (I
know the fix)
jonwil at tpgi.com.au
Sat Nov 8 22:43:32 CET 2003
ok, I have the solution here.
Basicly, what we need is this:
1.Both an Ansi window procedure and a Unicode window procedure for the
standard controls (buttons, statics etc). These should ideally be
implemented as stubs that call a shared procedure to do all the work (like
how MS does it), that way they are sharing all the data thats needed.
2.A new version of NtUserRegisterClassExWOW (and therefore IntCreateClass)
such that it takes both ansi and unicode window procedures and sets the
fields of the internal class structure as appropriate.
3.changes to how controls are registered to pass both window procedures.
4.changes to CreateWindowEx so that if one is creating a "standard" window
class (i.e. those defined in user32.dll and having both an ansi and a
unicode window procedure defined in the user32.dll symbol table), it will
ignore the class Unicode field and instead set the window unicode field to
either Ansi or Unicode based on which version of CreateWindowEx was called.
This test should ONLY be done for standard controls, all other calls to
CreateWindowEx should rely on the class unicode field.
Not sure how things like common controls work but based on my analysis of
user32, doing this for the controls that are inside user32.dll will make
things work like they do on windows (even with respect to subclassing,
sending messages and so on).
What would (I hope) now happen in the ANSI version of explorer explorer is
1.the BUTTON class gets registered at startup with both ANSI and Unicode
window procedures. The ANSI window procedure field points to ButtonWndProcA
and the Unicode window procedure field points to ButtonWndProcW.
2.explorer creates an instance of the BUTTON class which contains both ANSI
and Unicode window procedures and has the unicode field set to FALSE. The
ANSI window procedure field points to ButtonWndProcA and the Unicode window
procedure field points to ButtonWndProcW.
3.explorer subclasses the button with its own window procedure (lets call
it ExplorerButtonWndProc since I dont have actual code for explorer to look
up the real name), using SetWindowLongA. SetWindowLongA returns pointer to
ButtonWndProcA, sets ANSI window procedure field to <address of
ExplorerButtonWndProc>, sets Unicode window procedure field to <address of
ExplorerButtonWndProc + 0x80000000> and sets Unicode field to FALSE.
4.explorer calls GetWindowTextA on the button. This calls SendMessageA.
That in turn thunks down into kernel mode, ending up calling IntCallWindowProc.
IntCallWindowProc then tests the Unicode field. Since its false,
IntCallWindowProc then calls CallWindowProcW passing it the contents of the
Ansi window procedure field (in this case its ExplorerButtonWndProc).
CallWindowProcW tests to see if the window is unicode. Since it is not, the
message passed to CallWindowProcW is converted into ANSI. Then, the window
procedure (ExplorerButtonWndProc) is called. ExplorerButtonWndProc doesnt
know how to handle WM_GETTEXT (I assume) so it calls CallWindowProcA and
passes it the Window Procedure that was saved when the subclassing happened
(in this case its ButtonWindowProcA) along with the message details.
Since IsWindowUnicode returns false, all CallWindowProcA needs to do is to
call the procedure (i.e. ButtonWindowProcA).
Then, ButtonWindowProcA does the appropriate processing for WM_GETTEXT and
returns the results as an ANSI string.
The unicode version of explorer would do something similar but with unicode
calls and stuff instead of ANSI.
More information about the Ros-kernel