Solved

LoadLibrary behaves strangely on Win98

Posted on 2002-07-29
20
287 Views
Last Modified: 2013-11-20
I have an MFC program that should run on W2K, NT, and 98.
The program uses features that exist in the RichEdit control version 2 & 3, that are in riched20.dll.

MFC calls LoadLibraryA("RICHED32.DLL") .
In W2K it works great because the riched32.dll there, is actually an emulator that runs version 2 from riched20.

In NT it doesn't work naively, but I solved the problem by copying the riched32.dll emulator to the same folder where my executables reside. Since LoadLibrary uses a normal directory search algorithm, this riched32.dll is loaded (and not the one from the Windows\System32 directory) and everything again works OK.

In Win 98, I tried the same trick as in NT but it doesn't work. The riched32.dll loaded is always the one from the Windows\system directory, no matter how I play with the PATH. Replacing riched32.dll solves the problem, but that is something I do not want to do on a user's PC because I am changing the system.

How can I get LoadLibrary to take the DLL from the application executable directory (as is documented)?
Alternatively , how else can I resolve the problem?
0
Comment
Question by:mco
  • 9
  • 6
  • 5
20 Comments
 
LVL 86

Expert Comment

by:jkr
Comment Utility
>>How can I get LoadLibrary to take the DLL from the application executable directory (as is documented)?


Use a fully qualified path, e.g.

char acPath [ MAX_PATH];

GetModuleFileName ( NULL, acPath, MAX_PATH);

PathRemoveFileSpec ( acPath);

lstrcat ( acPath, "\\dllname.dll");

HINSTANCE hDll = LoadLibrary ( acPath);
0
 
LVL 1

Author Comment

by:mco
Comment Utility
Sorry, I should have stressed the following point: I do not intend to modify MFC source code. It is a maintenance hell.
0
 
LVL 86

Expert Comment

by:jkr
Comment Utility
>>I do not intend to modify MFC source code

Why should you?
0
 
LVL 1

Author Comment

by:mco
Comment Utility
As I said, the call LoadLibraryA("RICHED32.DLL") , is made from MFC source. That is not my code.
0
 
LVL 86

Expert Comment

by:jkr
Comment Utility
BTW, there's another point -however, so far I was not able to locate the article on MSDN again, so just a quote here:

"There's also a new approach called 'Private DLLs', see http://msdn.microsoft.com/library/techart/dlldanger1.htm :
Private DLLs are also referred to as side-by-side DLLs, because a private copy of a DLL is used in one
specific application while the system DLL is used by other applications. If you run WordPad and SuperApp
concurrently, two copies of Msvcrt.dll are loaded into memory (hence, the "side-by-side" terminology),
even if WordPad and SuperApp use the same version of Msvcrt.dll.
There are two approaches to implementing private DLLs. If you're writing a new application or a new
component, you give each version a unique version number. You then register each DLL or component in
the application directory where you want a private copy. Your application knows to load a private copy
of a shared DLL by version information in the application.
The second side-by-side approach is geared toward existing applications. Suppose C:\SuperApp\SuperApp.exe
is an existing application that you want to protect from future DLL upgrades or was broken by a service
pack upgrade. You simply copy the DLLs you want private to SuperApp into .\SuperApp and create an empty
file in this directory called ".\SuperApp.exe.local." Now when SuperApp fires up and finds the .local
file it searches the current directory for DLLs and COM servers before it searches the standard path.
If your application is broken by a service pack upgrade, you create an install program with the .local
file and the older DLLs you need and provide them to your customers."
0
 
LVL 30

Expert Comment

by:Zoppo
Comment Utility
I agree with jkr ... do something like this instead of calling
AfxInitRichEdit(), i.e. in InitInstance of your app:

extern _AFX_RICHEDIT_STATE* AFX_CDECL AfxGetRichEditState();

_AFX_RICHEDIT_STATE* pState = AfxGetRichEditState();
ASSERT (pState->m_hInstRichEdit == NULL); // to ensure it's not already loaded.
// create path as in jkr's post
...
pState->m_hInstRichEdit = LoadLibrary(<thePathToDLL>);


ZOPPO
0
 
LVL 1

Author Comment

by:mco
Comment Utility
Zoppo,
Actually, writing my own version of AfxInitRichEdit was my first attempt , but I failed even to compile. Did you manage to compile your suggestion?

The code:
#include "afxrich.h"
.
.
.
BOOL CREApp::InitInstance()
{
_AFX_RICHEDIT_STATE* pState = AfxGetRichEditState();
pState->m_hInstRichEdit = 99;

I get an error: error C2027: use of undefined type '_AFX_RICHEDIT_STATE' , on the last line above.
I.e. there is no error on the line where pState is declared and assigned, although the same type is used, but
there is an error on the last line where a field of pState is accessed.
0
 
LVL 86

Expert Comment

by:jkr
Comment Utility
>>error C2027: use of undefined type '_AFX_RICHEDIT_STATE'

You do

#include <afxrich.h>

?
0
 
LVL 30

Accepted Solution

by:
Zoppo earned 300 total points
Comment Utility
hmm ... I found _AFX_RICHEDIT_STATE declare in <afximpl.h>, so

#include <../src/afximpl.h>

solved the compiler errors here.
0
 
LVL 1

Author Comment

by:mco
Comment Utility
I'll try it out soon.
Are there any pitfalls with including an *impl.h file?
I thought they were only for building MFC, not for applications linking with it.
0
Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

 
LVL 30

Expert Comment

by:Zoppo
Comment Utility
>Are there any pitfalls with including an *impl.h file?

Well, I'm not absoluteley sure, but I found some articles in MSDN where <afximpl.h> is included to workaround known
problems, i.e. http://support.microsoft.com/default.aspx?scid=kb;[LN];Q230377

ZOPPO
0
 
LVL 1

Author Comment

by:mco
Comment Utility
Zoppo,
I am going to give you an A because you solved the problem.
For the record, there is a more elegant method that does not require including an internal MFC file: If I just pre-load the desired riched32.dll before calling MFC's original AfxInitiRichEdit, then the load in MFC will not load a different version. It will use the one I have preloaded.
0
 
LVL 86

Expert Comment

by:jkr
Comment Utility
So, using the full path had nothing to do with the solution?
0
 
LVL 30

Expert Comment

by:Zoppo
Comment Utility
Maybe solution was a co-production ... if you want I can offer you half of the points, ok?
0
 
LVL 1

Author Comment

by:mco
Comment Utility
No need. I posted the same question in the W98 topic area and a person there gave the preloading idea and he got full points.
0
 
LVL 1

Author Comment

by:mco
Comment Utility
jkr, of course the full path is needed, but that was not part of the problem. (I knew how to get the fullpath but had  a problem getting MFC to load from there).
0
 
LVL 30

Expert Comment

by:Zoppo
Comment Utility
> jkr, of course the full path is needed, but that was not part of the problem.

Well, sorry, but I don't agree ... the main problem was that
the full path was needed ... how to load the riched20.dll from
a given path was a secondary problem then ...

Therefore I asked jkr whether he agrees if I offer him half of the points.
0
 
LVL 1

Author Comment

by:mco
Comment Utility
1) It is up to you, they are your points and you can do whatever you want with them :-)
2) I am just stating that loading with the full path was not the problem I presented. The problem I presented was that I did not know how to change which DLL MFC will load on a Win98 OS. It is correct that in the solution you also need to load the full path, but you also need to do other things.
Your reply by itself without jkr's, solved the problem.
0
 
LVL 86

Expert Comment

by:jkr
Comment Utility
>>Your reply by itself without jkr's, solved the problem.

The reply was "I agree with jkr"

*shrug*

Have a nice time on EE.
0
 
LVL 1

Author Comment

by:mco
Comment Utility
Look, I also agree with you, jkr. Your posting was correct.
I think though, that points should go to whoever helps solve the problem that was posted, not necessarily to everyone writing truthful information.
Again, the problem I posed was of getting MFC to load the correct DLL, not on loading a specific DLL in general.
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Suggested Solutions

In this article, I'll describe -- and show pictures of -- some of the significant additions that have been made available to programmers in the MFC Feature Pack for Visual C++ 2008.  These same feature are in the MFC libraries that come with Visual …
This is to be the first in a series of articles demonstrating the development of a complete windows based application using the MFC classes.  I’ll try to keep each article focused on one (or a couple) of the tasks that one may meet.   Introductio…
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
Illustrator's Shape Builder tool will let you combine shapes visually and interactively. This video shows the Mac version, but the tool works the same way in Windows. To follow along with this video, you can draw your own shapes or download the file…

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now