LoadLibrary behaves strangely on Win98

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?
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

>>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);
mcoAuthor Commented:
Sorry, I should have stressed the following point: I do not intend to modify MFC source code. It is a maintenance hell.
>>I do not intend to modify MFC source code

Why should you?
OWASP: Forgery and Phishing

Learn the techniques to avoid forgery and phishing attacks and the types of attacks an application or network may face.

mcoAuthor Commented:
As I said, the call LoadLibraryA("RICHED32.DLL") , is made from MFC source. That is not my code.
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."
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>);

mcoAuthor Commented:
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.
>>error C2027: use of undefined type '_AFX_RICHEDIT_STATE'

You do

#include <afxrich.h>

hmm ... I found _AFX_RICHEDIT_STATE declare in <afximpl.h>, so

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

solved the compiler errors here.

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
mcoAuthor Commented:
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.
>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

mcoAuthor Commented:
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.
So, using the full path had nothing to do with the solution?
Maybe solution was a co-production ... if you want I can offer you half of the points, ok?
mcoAuthor Commented:
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.
mcoAuthor Commented:
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).
> 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.
mcoAuthor Commented:
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.
>>Your reply by itself without jkr's, solved the problem.

The reply was "I agree with jkr"


Have a nice time on EE.
mcoAuthor Commented:
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.
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
System Programming

From novice to tech pro — start learning today.