From: mk on
Hi Ajay,

thanks for your answer.

> Your entire process should have one MFC dll, either go with 90UD or
> 90D. Why do you need to mix? Also, why do you need R to be not an
> extension DLL?
R is a plug-in used to extend A. A and the other extension dlls are written
by external vendors.

> With Extension DLLs you are going to have issues immediately if different
> version of MFCs are used in the same process(For starters,
> AfxGetMainWnd would be different for each version).
I'm not very familiar with MFC. So, I ask myself why this is a problem. It's
absolutely plausible that the use of two different MFC versions can cause
compatibility problems. But my dlls are all using the same version of MFC
(9.0). 0ne dll accesses MFC via the Ansi interface, the others via the
unicode interface. Why should Microsoft create two interfaces to the same
runtime and prevent them from interacting?

Do you know anythink about the reasons for this behavior?

Thanks, mk
From: Goran on
On Feb 9, 5:57 pm, mk <m...(a)discussions.microsoft.com> wrote:
> Hello,
>
> I am working at an application that has the following (admittedly somewhat
> strange) module architecture:
> * Application "A" dynamically loads my regular Unicode MFC DLL "R"
> (presumably by using LoadLibraryA)
> * "R" statically loads my unicode extension dll "E"
> * "E" itself statically loads two MBCS extension dlls written by a external
> vendor.

(I'll call these EX)

I agree with Joe that this is your problem right here. I don't think
you should be able to load external ANSI MFC extension DLLs EX for use
with, effectively, Unicode regular MFC dll R. (E seems to be
tangential to the issue.).

About your use of Unicode for R: if application is ANSI, why? Unicode
gives you possibility for your code to speak more than one language
(or code page ;-) ). But A can't do it. R is bound to A, so even if it
does speak more languages, A won't grok them. I frankly see no point
in Unicode use in R.

I'd like to comment on the application aspect. You say that R is a
plugin for A. If it's a plugin, chances are that R should exposes pure
C interface A will use. If so, I think you should abstain from any use
of MFC extension DLLs (especially those built with the same MFC
version as A). This is because extension DLLs integrate tightly with
the application - but that's not intended in your case, you seem to
want your DLL R to use EX, not A (is this correct, BTW?). So I think
that you should see with your EX vendor if they have a regular DLL
build - that's IMO a correct option. Or, if A uses a different MFC
version from you, I would not be surprised that all is OK, albeit
really weird (and possibly not future-proof ;-) ).

You see, the thing with extension DLLs is that they really are made
with one executable in mind: everyone plays nicely in a homogenous
environment, in the best interest of the __application__. But your
case is heterogeneous.

(If A exposes MFC-dependant interface (or C++-runtime-dependent one),
R is stuck with whatever MFC version application is built with. That
is IMO highly unlikely. It's not the end of the world, but is a major
annoyance and stupidity on the part of A.)

Goran.
From: Ajay Kalra on
> I'm not very familiar with MFC. So, I ask myself why this is a problem. It's
> absolutely plausible that the use of two different MFC versions can cause
> compatibility problems. But my dlls are all using the same version of MFC
> (9.0). 0ne dll accesses MFC via the Ansi interface, the others via the
> unicode interface. Why should Microsoft create two interfaces to the same
> runtime and prevent them from interacting?


It has nothing to do with Microsoft. If you have static variables/
singletons in a DLL, multiple instances of the DLL in a process will
return different values. This will invalidate any method that you uses
these variables. Mixing unicode and non-unicode of the same version
will cause this issue as well.

We did have the same problem with plug-ins at my previous
employer(Autodesk); with each new version of MFC or when we introduced
Unicode and plugs ins were not, we had to get the correct version of
plug ins. This problem kind of goes away if the plug ins are Regular
DLL as then these will be independent. But then you are loading
multiple versions of MFC.

--
Ajay
From: Joseph M. Newcomer on
See below...
On Wed, 10 Feb 2010 00:32:01 -0800, mk <mk(a)discussions.microsoft.com> wrote:

>Hi Joe,
>
>thank you for your answer.
>
>> You did not say what kind of app it is.
>Well, it is also an application of an external vendor. It can be extended by
>registering plug-in dlls which then are loaded at startup. It's definitely an
>ANSI application. But it's not specified whether the plug-ins are loaded via
>AfxLoadLibrary or via the Win32 LoadLibrary.
****
AfxLoadLibrary is just a fairly trivial wrappon around ::LoadLibrary.
****
>
>> I have no idea what "statically loads" means for a DLL. Did you mean "implicitly loads"?
>Sorry. I indeed meant "implicitly".
>
>> If the executable is an ANSI app, and you load a Unicode extension DLL, you are
>> begging for disaster to strike. This is because you will end up
>> with two completely different, and incompatible, copies of the MFC runtime, one for the
>> executable and one for the extension DLL E
>I'm not calling the extension dll directly from the application. I'm aware,
>that an extension dll and its client application have to use the same version
>of MFCxx.dll. But I thought the CWinApp-derived object in my regular dll
>would act as client and hence would decouple the extension dll from the
>application.
****
The CWinApp-derived object in your regular DLL has nothing to do with application apps and
is invisible to any DLL that is called.
****
>
>> And here you have another disaster scenario. An 8-bit extension DLL will load
>> the 8-bit version of the MFC library; you have a different version loaded for
>> your extension DLL "E", and this might be different from the executable.
>> This is a scenario that, instead of asking "why doesn't it work?", I'm more inclined to
>> ask "How could it possibly work?"
>I'm not familiar with the MFC internals. Accordingly, wasn't quite sure
>whether the 8-bit and the unicode MFC libraries are compatible. But from my
>point of view, there is no reason why the two runtimes of the same version
>shouldn't be able to interact.
****
Actually, there is no reason to assume that they could EVER interact correctly. There's
nothing that makes this possible, or even desirable.
****
>
>> This is a meaningless statement. If it "cannot be loaded", there are error messages
>> issued, or error codes returned. Without knowing what this vague handwave of "cannot be
>> loaded" means, that is, WHAT IS SEEN TO OCCUR, IN DETAIL, I will have to find my old
>> crystal ball and dust it off, and I don't feel like doing that right now.
>Unfortunately, that's my problem as well. The error occurs while the dll is
>loaded. So there are neither error messages nor error codes. I only obtain a
>first chance exception in the ntdll.dll.
>The debugger's output is as follows. Where "NpcDlabQslrD.dll" is the reguar
>dll "R". "NpcDlabQslrUxD.dll" is my extension dll "E". "edaq.dll" and
>"logger.dll" are the external 8-bit extension dlls.
>
>'DASYLAB.EXE': Loaded 'D:\Dlab90\NpcDlabQslrD.dll', Symbols loaded.
>'DASYLAB.EXE': Loaded 'D:\Dlab90\NpcDlabQslrUxD.dll', Symbols loaded.
>'DASYLAB.EXE': Loaded 'D:\Dlab90\eDaq.dll'
>'DASYLAB.EXE': Loaded 'D:\Dlab90\Logger.dll'
>'DASYLAB.EXE': Loaded 'C:\WINDOWS\system32\MFC42D.DLL', Symbols loaded.
>'DASYLAB.EXE': Loaded 'C:\WINDOWS\system32\MSVCRTD.DLL', Symbols loaded.
>'DASYLAB.EXE': Loaded 'C:\WINDOWS\system32\MSVCP60D.DLL', Symbols loaded.
>'DASYLAB.EXE': Loaded 'C:\WINDOWS\system32\MFCN42D.DLL', Symbols loaded.
>First-chance exception at 0x7c9766c6 in DASYLAB.EXE: 0xC0000138: Ordinal Not
>Found.
****
This pretty much says it all. There is an attempt to resolve a DLL via an ordinal entry
point and that ordinal is not defined. This can be caused by a variety of reasons,
including having a DLL compiled for version n of Windows and running it on version n-1 or
lower, or if you have a DLL that is using ordinals to link, having an obsolete version of
the DLL relative to the .lib file you are using.

You will have to figure out which DLL is failing to load.

What version of VS are you using to compile your system? If it is not VS6, you are
already in deep trouble; not only can you not mix Unicode and ANSI versions of the MFC
DLL, you cannot mix versions such as MFC42 and any other version such as MFC70, MFC80 and
MFC90.
****
>
>> Absolutely. As I said, I would expect that this would fail in some interesting fashion,
>> but I would be incredibly surprised if it worked at all. You really can't mix MFC
>> runtimes like this. Each DLL tries to maintain an image of what is going on, and the
>> images will conflict. Not a feasible solution.
>The thing is that I tested this architecture before we implemented it and
>everything worked out fine. For days, I'm trying to build test binaries that
>cause this error. But I can't reproduce it. Hence, this architecture seems to
>work for most configurations.
****
Then you just happened to have a set of circumstances that worked, in spite of the fact
that they are definitely not expected to.
****
>
>> You will have to figure out how to make
>> this work in some other fashion, such as acquiring updated DLLs from the third party, or
>> reverting everything to ANSI/MBCS. But on the whole, I think the current configuration is
>> doomed to never work.
>Provided I could persuade the vendor of the ansi extension dlls to build a
>unicode version, would the module dependencies would look like this:
>Ansi exe -> regular dll unicode -> ext dll Unicode -> ext dll unicode.
>
>Is this constellation officially supported by MFC?
****
On the contrary, it is not only unsupported, but forbidden.
joe
****
>
>Thanks, mk
Joseph M. Newcomer [MVP]
email: newcomer(a)flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
From: mk on
> What version of VS are you using to compile your system? If it is not VS6,
you are
> already in deep trouble; not only can you not mix Unicode and ANSI versions of the MFC
> DLL, you cannot mix versions such as MFC42 and any other version such as MFC70, MFC80 and
> MFC90.
To complete the disater scenario, I actually to use VS2008. But the regular
dll only exposes the following simple interface
int WINAPI SetupDlabDLL ( HWND hwnd )
int WINAPI FinishDlabDLL ( HWND hwnd )
All other communication happens via a simple Winapi window messaging
interface.
There is not a single object (and accordingly no MFC object) passed between
the components. Therefore I hope that the different MFC versions are
irrelevant.

> >Ansi exe -> regular dll unicode -> ext dll Unicode -> ext dll unicode.
> >Is this constellation officially supported by MFC?
> ****
> On the contrary, it is not only unsupported, but forbidden.

In a support article ( http://support.microsoft.com/kb/167929/en-us) I found
the statement that constellations like the following are allowed.

------------- --------------
= = = =
= MFC = Calls = MFC =
= APP = ------------> = USRDLL =
= = = =
= = = =
------------- --------------
| |
| |
| Calls | Calls
| |
\/ \/
------------- --------------
= = = =
= = = =
= MFC40d = = MFC40Ud =
= DLL = = DLL =
= = = =
------------- --------------
\ /
\ /
\ Calls / Calls
\ /
\/ \/
-------------
= =
= =
= MSVCR40d =
= (CRT) =
= =
-------------

Hence, the problem in my constellation is the call from the extension dll to
another extension dll.
Then there should be a chance to bring a constellation to work in which the
Ansi exe calls my Unicode regular dll, and the regular dll directly calls
either ext dll. Am I right with this thought?

Thanks, mk