[PATCH] user32: Add support for class versions

Nikolay Sivov bunglehead at gmail.com
Sun Nov 6 05:06:57 CST 2016


On 05.11.2016 19:31, Ivan Akulinchev wrote:
> Sorry, forgot to CC wine-devel at winehq.org...
> 
> -------------
> 
> Hi, thanks for a reply!
> 
> On Saturday, 5 November 2016 17:56:47 CET you wrote:
>> On 05.11.2016 16:36, Ivan Akulinchev wrote:
>>> Signed-off-by: Ivan Akulinchev <ivan.akulinchev at gmail.com>
>>> ---
>>>
>>>  dlls/comctl32/comctl32.manifest |  1 -
>>>  dlls/comctl32/theming.c         | 15 +++++++--
>>>  dlls/user32/class.c             | 73
>>>  +++++++++++++++++++++++++++++++++++++---- dlls/user32/user_private.h    
>>>   |  2 ++
>>>  dlls/user32/win.c               |  7 ++--
>>>  5 files changed, 86 insertions(+), 12 deletions(-)
>>
>> Hi, thanks for looking into this.
>>
>>> diff --git a/dlls/comctl32/comctl32.manifest
>>> b/dlls/comctl32/comctl32.manifest index 4c86137..5aa55a3 100644
>>> --- a/dlls/comctl32/comctl32.manifest
>>> +++ b/dlls/comctl32/comctl32.manifest
>>> @@ -12,7 +12,6 @@
>>>
>>>      <windowClass>NativeFontCtl</windowClass>
>>>      <windowClass>ReBarWindow32</windowClass>
>>>      <windowClass>ScrollBar</windowClass>
>>>
>>> -    <windowClass>Static</windowClass>
>>>
>>>      <windowClass>SysAnimate32</windowClass>
>>>      <windowClass>SysDateTimePick32</windowClass>
>>>      <windowClass>SysHeader32</windowClass>
>>
>> Something tells me we'll need opposite logic here,
>> if versioned classes support are to be added one by one.
>>
> 
> This line ("<windowClass>Static</windowClass>") tells Windows to use the
> "6.0.0.0!Static" class instead of "Static". However this class does not
> exist and all applications crash.
> 
> If you remove this line, the standard Static class from user32 is used.

Right, but we don't want that. The goal is to use class from comctl32,
that's the point of all changes you're making.

> 
>>> diff --git a/dlls/comctl32/theming.c b/dlls/comctl32/theming.c
>>> index 93d6fe6..b78ecc9 100644
>>> --- a/dlls/comctl32/theming.c
>>> +++ b/dlls/comctl32/theming.c
>>> @@ -28,6 +28,7 @@
>>>
>>>  #include "comctl32.h"
>>>  #include "uxtheme.h"
>>>  #include "wine/debug.h"
>>>
>>> +#include "wine/unicode.h"
>>>
>>>  WINE_DEFAULT_DEBUG_CHANNEL(theming);
>>>
>>> @@ -124,8 +125,6 @@ void THEMING_Initialize (void)
>>>
>>>      static const WCHAR refDataPropName[] =
>>>      
>>>          { 'C','C','3','2','T','h','e','m','i','n','g','D','a','t','a',0
>>>          };
>>>
>>> -    if (!IsThemeActive()) return;
>>> -
>>>
>>>      atSubclassProp = GlobalAddAtomW (subclassPropName);
>>>      atRefDataProp = GlobalAddAtomW (refDataPropName);
>>>
>>> @@ -142,6 +141,18 @@ void THEMING_Initialize (void)
>>>
>>>          }
>>>          originalProcs[i] = class.lpfnWndProc;
>>>          class.lpfnWndProc = subclassProcs[i];
>>>
>>> +
>>> +        /*
>>> +         * FIXME: The Dialog class ('#32770') should NOT be overridden
>>> here. +         *
>>> +         * Temporarily ignore this issue using the hack below...
>>> +         */
>>> +        if (strcmpiW(subclasses[i].className, dialogClass) != 0)
>>> +        {
>>> +            /* If not a dialog (see above), make the class global */
>>> +            class.style |= CS_GLOBALCLASS;
>>> +            class.hInstance = NULL;
>>> +        }
>>>
>>>          if (!class.lpfnWndProc)
>>>          {
>>
>> All theming.c should go when transition is complete, because once you're
>> able to create 6.0.0.0!Static it will support theme drawing API
>> regardless if theming is enabled or not.
>>
> 
> The problem here is that it is impossible to create a versioned class
> for #32770, and therefore we can not create a global class - only a
> local one. I believe this stuff is a part of the undocumented Theme
> Hooks API, and not a part of comctl32...
> 
> theming.c is needed because nobody wants to copy & paste the
> corresponding code from user32, as Microsoft did. Maybe we can create a
> private library containing the base classes, used by both libraries?

I actually do want to duplicate code from user32 one way or another, and
once done it want be called theming.c, because it's not limited to
visual appearance.

>>>
>>>  /***********************************************************************
>>>  
>>>   *           register_builtin
>>>
>>> @@ -576,10 +612,12 @@ ATOM WINAPI RegisterClassExA( const WNDCLASSEXA* wc
>>> )
>>>
>>>      if (!IS_INTRESOURCE(wc->lpszClassName))
>>>      {
>>>
>>> +        LPCWSTR versioned_name;
>>>
>>>          WCHAR name[MAX_ATOM_LEN + 1];
>>>          
>>>          if (!MultiByteToWideChar( CP_ACP, 0, wc->lpszClassName, -1, name,
>>>          MAX_ATOM_LEN + 1 )) return 0;> 
>>> -        classPtr = CLASS_RegisterClass( name, instance, !(wc->style &
>>> CS_GLOBALCLASS), +        versioned_name = CLASS_GetVersionedName( name
>>> );
>>> +        classPtr = CLASS_RegisterClass( versioned_name, instance,
>>> !(wc->style & CS_GLOBALCLASS),> 
>>>                                          wc->style, wc->cbClsExtra,
>>>                                          wc->cbWndExtra );
>>>      
>>>      }
>>
>> Why do you need this in -A call too?
>>
> 
> I didn't test the ASCII functions on a real Windows instance, but why do
> you think this shouldn't have the class redirections too?

Yes, sorry about that, I thought that we forward from A to W as we
usually do. It probably makes sense to duplicate GetVersionedName as you
did, if only to avoid calling context functions when class IS_INTRESOURCE().

> 
>>>      else
>>>
>>> @@ -619,6 +657,7 @@ ATOM WINAPI RegisterClassExW( const WNDCLASSEXW* wc )
>>>
>>>      ATOM atom;
>>>      CLASS *classPtr;
>>>      HINSTANCE instance;
>>>
>>> +    LPCWSTR versioned_name;
>>>
>>>      GetDesktopWindow();  /* create the desktop window to trigger builtin
>>>      class registration */> 
>>> @@ -630,7 +669,9 @@ ATOM WINAPI RegisterClassExW( const WNDCLASSEXW* wc )
>>>
>>>      }
>>>      if (!(instance = wc->hInstance)) instance = GetModuleHandleW( NULL );
>>>
>>> -    if (!(classPtr = CLASS_RegisterClass( wc->lpszClassName, instance,
>>> !(wc->style & CS_GLOBALCLASS), +    versioned_name =
>>> CLASS_GetVersionedName( wc->lpszClassName ); +
>>> +    if (!(classPtr = CLASS_RegisterClass( versioned_name, instance,
>>> !(wc->style & CS_GLOBALCLASS),> 
>>>                                            wc->style, wc->cbClsExtra,
>>>                                            wc->cbWndExtra )))
>>>          
>>>          return 0;
>>
>> This part I looks wrong. Why would it register something that is not
>> what user asked for? My understanding is that comctl32 itself should
>> register its versioned classes (and in ideal v5 vs v6 separation only v6
>> module should be doing that). So comctl32 is loaded, it registers
>> regular classes first, like Listview, then it registered versioned names
>> like 6.0.0.0!Listview.
>>
> 
> Well, I had to disassemble this chunk of code, but I can suggest you to
> do the following test, which doesn't violate the Clean Room design.
> 
> 1. On Windows XP or higher, try to register a "Button" class with
>    CS_GLOBALCLASS. This should fail.
> 2. Add a manifest file like:
>    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
>    <assembly xmlns="urn:schemas-microsoft-com:asm.v1"
>              manifestVersion="1.0">
>      <assemblyIdentity type="win32"
>                        name="Wine.TestMe"
>                        version="1.0.0.0" />
>      <file name="yourapp.exe">
>        <windowClass>Button</windowClass>
>      </file>
>    </assembly>
> 3. Launch your application again. Now the "Button" class is registered,
>    and it is actually "1.0.0.0!Button". You can create a new window with
>    both names.

If you disassembled user32/comctl32 dlls, I suggest to stop this
conversation, none of what you submitted is usable now.





More information about the wine-devel mailing list