Opened 5 years ago

Closed 5 years ago

Last modified 5 years ago

#14474 closed defect (invalid)

::GetModuleHandle("comctl32.dll") returns 0 when executed from a dll calling wxWidgets code on windows 7

Reported by: jgmdev Owned by:
Priority: high Milestone:
Component: wxMSW Version: stable-latest
Keywords: Cc:
Blocked By: Blocking:
Patch: yes

Description

Using the wxDatePickerCtrl using the wxPHP binding fails on windows 7, After doing some testing the culprit is ::GetModuleHandle("comctl32.dll"). This function is returning 0 on windows 7 when executed on a dll with wxWidgets code loaded by another executable which is the case of wxPHP.

php.exe loads php_wxwidgets.dll and this dll makes calls to wxWidgets class methods.

Here is the code that blocks wxDatePickerCtrl (msw\datecontrols.cpp) if comctl32 version is to old:

if ( wxApp::GetComCtl32Version() < 470 )
{

wxLogError(_("This system doesn't support date controls, please upgrade your version of comctl32.dll"));

return false;

}

GetComCtl32Version() tries to get the handle of already loaded comctl32.dll to get its version, but it fails by returning 0 if code is executed inside a dll on windows 7.

Works well on windows xp with same code but not on windows 7 and it seems is the same problem reported here:

http://trac.wxwidgets.org/ticket/10744

I have applied the patch provided on mentioned previous ticket and now it works without an issue. I have adapted the patch for current wxwidgets trunk.

Also I tested the python wxDatePickerCtrl on win 7 but it is using generic one instead of native, maybe because of this issue.

Attachments (1)

getmodulehandle_msw_vista_7_fix.patch download (9.8 KB) - added by jgmdev 5 years ago.

Download all attachments as: .zip

Change History (8)

Changed 5 years ago by jgmdev

comment:1 Changed 5 years ago by jgmdev

Applying this patch also fixed a strange behavior on wxListCtrl when displayed with multiple columns. A row would not be selected by clicking on a column that it isn't the first one. Also clicking on the first column only selected the first column of the row and not the whole row.

Behavior also present on windows 7

comment:2 follow-up: Changed 5 years ago by aasselin

You should definitely not use this patch, your problem is that your messing with Side by Side activation. If you use those functions you are going to get the handle for an unexpected version of comctl32.dll

You need to read Side by Side "activation context" stuff. The reason for all that 'mess' is that you expect to get 6.0 common controls whereas the default is (lower number don't remember exactly). Thus Windows refuses to tell "control32.dll version 6 is here". Windows is _right_ this is _not_ a bug.
Just use the right activation context and everything will work normally.

see documentation in MSDN:
http://msdn.microsoft.com/en-us/library/windows/desktop/aa374166(v=vs.85).aspx

comment:3 follow-up: Changed 5 years ago by vadz

  • Resolution set to invalid
  • Status changed from new to closed

Yes, comment:2 is completely correct. You should either ensure that the main application uses a proper manifest or build with ISOLATION_AWARE_ENABLED, see wx/msw/wx.rc.

This patch is not the right fix.

comment:4 in reply to: ↑ 3 Changed 5 years ago by jgmdev

Replying to vadz:

Yes, comment:2 is completely correct. You should either ensure that the main application uses a proper manifest or build with ISOLATION_AWARE_ENABLED, see wx/msw/wx.rc.

This patch is not the right fix.

Compiling the php_wxwidgets.dll with ISOLATION_AWARE_ENABLED defined didn't solved the problem, even including another manifest file as '2 24 "manifest_file"' doesn't worked. I'm not getting 6.0 controls on wxphp applications either.

It seems I jumped a step on the report of how php works on windows:

php-win.exe -> php5.dll -> php_wxwidgets.dll

I guess it is the same way as python, but I have run out of ideas.

comment:5 in reply to: ↑ 2 Changed 5 years ago by jgmdev

Replying to aasselin:

You should definitely not use this patch, your problem is that your messing with Side by Side activation. If you use those functions you are going to get the handle for an unexpected version of comctl32.dll

You need to read Side by Side "activation context" stuff. The reason for all that 'mess' is that you expect to get 6.0 common controls whereas the default is (lower number don't remember exactly). Thus Windows refuses to tell "control32.dll version 6 is here". Windows is _right_ this is _not_ a bug.
Just use the right activation context and everything will work normally.

see documentation in MSDN:
http://msdn.microsoft.com/en-us/library/windows/desktop/aa374166(v=vs.85).aspx

So what you are saying is that I need to use one of those activation functions on the php_wxwidgets.dll in order for it to work normally?

In any case php works like the following:

php-win.exe -> php5.dll -> php_wxwidgets.dll

I'm still not sure what to do

comment:6 Changed 5 years ago by vadz

I also think it's the same as Python so I think the same solution should work here. Unfortunately I don't know the details of what wxPython does, perhaps you should ask on wxPython mailing list.

comment:7 Changed 5 years ago by aasselin

@jgmdev:
the whole problem with the "DLL and side by side" problem is that when the .exe functions call the functions in a .DLL the manifest of the .DLL is totally ignored (there is no special code involved in there, the internals of DLL did not change at all when manifests were added and thus all this activation context mess). I mean there is no magic "GetProcAddressWithActivationCtxt", it would be cool but it does not exist, and linking to a DLL is essentially calling many GetProcAddress and storing pointers, and calling them does nothing more than calling the bare code... so no use of DLL manifest by default.

using ISOLATION_AWARE_ENABLED while building wxwidgets will place an activation aware stub (which activates the manifest of the dll the particular code is linked into) around most functions such as CreateWindow, LoadLibrary and so on which actually care about the version of common controls.
if there are only a very few entry points to your own DLL (which depends on wx), placing the right activation context in a prolog object at the start of each entry point is OK as well.

note that the manifest of the DLL is respected inside the LoadLibrary call loading it, but that's the only moment when it is naturally used, else you need your own call to activation context API or ISOLATION_AWARE_ENABLED flag when building wx dll (as this wx code which actually call CreateWindowEx).

to verify that the right manifest is well loaded by ISOLATION_AWARE_ENABLED enabled function, search for it in the .h and place breakpoints in these functions, it is probable that the manifest is not loaded, has some error or whatsoever... or some other function code takes place in between and activate yet another bad context.

hope it helps, Armel

Note: See TracTickets for help on using tickets.