English 中文(简体)
LoadLibrary on OCX file fails in Windows 7 x64
原标题:

I need to open a html help file from within a legacy windows application written in old version of C++ Builder. HtmlHelp is loaded via HtmlHelp.ocx, which I am loading via LoadLibrary.

This has worked fine for years, but it does not work anymore in Windows 7 x64. It might also fail under Windows7 x86, but I don t have any computer with this OS, so I can t try it out at the moment.

I am loading hhctrl.ocx dynamically as follows:

#define HHPathRegKey "CLSID\{adb880a6-d8ff-11cf-9377-00aa003b7a11}\InprocServer32"

bool THTMLHelper::LoadHtmlHelp()
{
  HKEY HHKey;
  DWORD PathSize = 255;
  char Path[255];
  bool R = false;

  if (::RegOpenKeyExA(HKEY_CLASSES_ROOT, HHPathRegKey, 0, KEY_QUERY_VALUE, (void **)&HHKey) == ERROR_SUCCESS)
  {
    if (::RegQueryValueExA(HHKey, "", NULL, NULL, (LPBYTE)Path, &PathSize) == ERROR_SUCCESS)
    {
      //*****************************************
      //LOADING FAILS HERE
      //PATH IS %SystemRoot%System32hhctrl.ocx          
      //*****************************************
      HHLibrary = ::LoadLibrary(Path);
      if (HHLibrary != 0)
      {
        __HtmlHelp = (HTML_HELP_PROC) ::GetProcAddress(HHLibrary, "HtmlHelpA");
        R = (__HtmlHelp != NULL);
        if (!R)
        {
          ::FreeLibrary(HHLibrary);
          HHLibrary = 0;
        }
      }
    }
    ::RegCloseKey(HHKey);
  }
  return R;
}

I checked if %SystemRoot%System32hhctrl.ocx exists on the Windows 7 system and it does.

Why does loading it via LoadLibrary fail? How can I work around this problem?

EDIT: GetLastError says (in German, so I am just translating): "Could not find file." But I debugged the function and the path is "%SystemRoot%System32hhctrl.ocx" and the file does exist.

Also, since two answers point in the direction of 64-bit vs 32-bit problems: My application is a 32 bit executable compiled in C++ Builder 5, so it should be a 32 bit process if I m not mistaken. Or am I wrong to assume that?

最佳回答

Use ExpandEnvironmentStrings function to expand %SystemRoot%System32hhctrl.ocx to real path on user s intallation. 64bit OS will redirect expanded path to 32bit dll correctly.

问题回答

You can t load 32bit dlls in a 64bit process, and visa versa. ActiveX controls are, of course, Dlls.

You can sometimes work around this by getting the 32bit ActiveX to load as an out-of-process server - its then hosted in a seperate 32bit (or 64bit) process as appropriate. This requires that the ActiveX onlyuses interfaces the system already knows how to marshal, and/or the project built 64bit AND 32bit versions of the proxy stub dll.


Depends is a tool that is very useful when you need to figure out why Dlls wont load. Of course, as a 32 bit application on a 64bit OS you need to know that 32 bit applications do NOT get access to %SYSTEMROOT%System32 and, also do NOT read and write from HKCR directly. System32 actually contains the 64bit OS binaries, and HKCR contains the registry entries for 64bit apps.

A kernel process called reflection redirects 32bit apps completely transparently to from System32 to %SYSTEMROOT%SysWow64. Likewise, registry access to HKEY_CLASSES_ROOT is redirected to `HKEY_CLASSES_ROOTWow6432Node . You need to know this of course, because explorer and regedit are 64bit processes and will happily show you the 64bit contents of System32 and HKCR. You need to explicitly navigate to the 32bit nodes to double check the view your 32bit process is going to get.

I have the exact same problem right now running W7 (x64).

I got it to work when I changed the "%SystemRoot%System32hhctrl.ocx" to "c:windowsSystem32hhctrl.ocx", but I guess I need to figure out why %SystemRoot% resolves wrong.

btw: I m building a 32bit app on BCB2007.





相关问题
How to read exact number of bytes from a stream (tcp) socket?

In winsock, both the sync recv and the async WSARecv complete as soon as there is data available in a stream socket, regardless of the size specified (which is only the upper limit). This means that ...

AcquireCredentialsHandle returns SEC_E_NO_CREDENTIALS

I created a self-signed certificate (created using OpenSSL) and installed it into the Certificate Store using the Certificates MMC snap-in (CertMgr.msc) on Windows Vista Ultimate. I have managed to ...

Calling Win32 EnumThreadWindows() in C#

I m trying to get a call to EnumThreadWindows working, but I always get a Wrong Parameter-Error, although my code is nearly the same as this example on pinvoke.net. I don t know why this doesn t work: ...

COM Basic links

folks can you provide me the tutorial link or .pdf for learning basic COM?. i do google it.. still i recommend answers of stackoverflow so please pass me.. Thanks

Handling multiple windows WIN32 API

HI I m trying to create an application in the Win32 environment containing more than one window. How do i do that? all the Win32 Tutorials on web i found only showed how to manage one window. How do i ...

Creating a thread in DllMain?

It seems that when a thread is created from within DllMain upon DLL_PROCESS_ATTACH it won t begin until all dll s have been loaded. Since I need to make sure the thread runs before I continue, I get a ...

热门标签