Does Windows preload ComCtrl32.dll into the application?

I came across a situation where I know the code

I created an MFC application in Visual Studio 2008 that generates a Tray icon and some notifications. I read that I can use a different NOTIFYICONDATA structure for Windows Vista than for Windows XP by setting the cbSize property of the structure to initialize it. I also read that I can use LoadIconMetric in Windows Vista to load my notification icon, while in Windows XP this function is not available to me and I have to use LoadIcon .

In my application, I installed the following:

 #ifndef WINVER #define WINVER 0x0600 // Vista #endif #ifndef _WIN32_WINNT #define _WIN32_WINNT 0x0600 // Vista #end#if #ifndef _WIN32_WINDOWS #define _WIN32_WINDOWS 0x0600 // Vista #endif #ifndef _WIN32_IE #define _WIN32_IE 0x0700 #endif 

I compile and link to the Windows 7 SDK on a Windows 7 x64 computer in Visual Studio 2008. My test for WindowsVista or higher looks like this (directly from MSDN):

 static BOOL IsWinVistaOrLater() { // Initialize the OSVERSIONINFOEX structure. OSVERSIONINFOEX osvi; ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); osvi.dwMajorVersion = 6; osvi.dwMinorVersion = 1; // Initialize the condition mask. DWORDLONG dwlConditionMask = 0; VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL); VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION, VER_GREATER_EQUAL); // Perform the test. return VerifyVersionInfo(&osvi, VER_MAJORVERSION | VER_MINORVERSION, dwlConditionMask); } 

Now here is the interesting part. I use IsWinVistaOrLater to determine if I should use LoadIconMetric or LoadIcon:

 if (IsWinVistaOrLater()) { tnd_Happy.dwInfoFlags = NIIF_LARGE_ICON | tnd_Happy.dwInfoFlags; LoadIconMetric(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDI_ICON_HAPPY), LIM_SMALL, &(tnd_Happy.hIcon)); } else { tnd_Happy.hIcon = LoadIcon(AfxGetInstanceHandle(), MAKEINTRESOURCE (IDI_ICON_HAPPY)); // ICON RESOURCE ID } 

In XP, it crashes with "Ordinal 380 not found in ComCtrl32.dll." If I comment on the LoadIconMetric call, everything will be fine (even with all of these target versions installed for Vista). Does Windows try to import all function calls regardless of the execution code path?

+4
source share
3 answers

Instead of the LoadLibrary and GetProcAddress proposed by Chris, you can write a Vista-only DLL that contains all the Vista-only code, and your main project is still focused on XP. Then you don’t need to download only Vista code unless execution completes checking Vista versions and calling functions exported from Vista DLLs.

+3
source

Just to help others who may encounter very similar problems. I could not get LoadIconMetric to work even on Windows 7 using the Visual Studio C ++ 2010 Express WinApi template application. After adding Comctl32.lib to dependecies, including CommCtrl.h, he continues to say: "Ordinal 380 was not found in ComCtrl32.dll." I was not very clear what I missed because I absolutely did not like switching versions of such components. After some time, I understand that these are valuable sources for this situation:

General Management Versions

I solved the problem by adding this line before enabling CommCtrl.h (note that my application is only for Windows Vista and higher):

 // Need CommCtrl v6 for LoadIconMetric() #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") 

It came from a sample of Microsoft:

Notification Icon Icon - NotificationIcon.zip

+10
source

Setting up header files for Vista will allow you to create applications that will not load on earlier versions of Windows. This is why customizing this file is so important.

To work around the problem:

  • It should be possible to use the / DELAYLOAD switch on comctl32.dll. Without / DELAYLOAD, Windows will try to import all functions in front (regardless of the code path)

  • Reset header file of the target version to 0x0501 (XP). Windows will automatically warn you if you try to use any additional features. Access the new features with LoadLibrary ("comctl32.dll") && & GetProcAddress ("LoadIconMetric"). The disadvantage of this method is that you can make new calls through GetProcAddress, but the structures (if changed) will be the old structures.

Finally, many of the functions of comctl32.dll are a trick: if you don’t have specifically Enabled Visual Styles , then your version of comctl32.dll should always be version 5. (If you had an MFC project built on VS2005 or VS2008, it should have been done automatically). This means that you can install WINVER on Vista, but then ComCtl32 causes the start of a crash because ComCtl32 version 5 does not understand the new larger structures.

+7
source

All Articles