VC6 DLL calls VB6 DLL calls back to VC6 DLL: Occasional GPF or ‘Bad DLL calling convention' 
Author Message
 VC6 DLL calls VB6 DLL calls back to VC6 DLL: Occasional GPF or ‘Bad DLL calling convention'

I have a VC++6 DLL that calls a VB6 DLL which calls back into the
VC++6 DLL.  For some weeks it appeared to work.  However, after making
trivial code changes (not interface), I experience GPF's (typically)
or "Bad DLL calling convention" errors (rarely).  Failures do not
appear deterministic ANY code change can change the instruction the
code appears to fail on.  It smells like stack corruption.  Can anyone
offer a suggestion on the potential root cause?...Chris

Sterilized code snippets from MyVCDll.cpp, MyApp.h and MyVBDll files:

////// [from MyVCDll.cpp file]
#include "stdafx.h"
#include <stdarg.h>
#include <stdio.h>
#include "MyApp.h"
#import "dll\MyVBDll.dll" no_namespace

bool DLLEXPORT VCFunc(CID *pID, short iUse_UVW, bool blnDebug)
{
        CoInitialize(NULL);
        bool  bReturn;
        short iReturn;
        _MyVBDllPtr ptr;
        ptr.CreateInstance(__uuidof(MyVBDll));
        iReturn = ptr->VBFunc((int)pID, iUse_UVW, blnDebug);
        return TRUE;
        CoUninitialize();

Quote:
}

////// [from MyApp.h file]
#define DLLEXPORT __declspec(dllexport)

extern "C" DLLEXPORT bool GetValue(CID* pID, LPCTSTR pszName,
  DWORD& dwValue, TosIECDataType& iecDataType);
extern "C" DLLEXPORT int  SetValue(CID* pID, LPCTSTR pszName,
  DWORD dwValue);
extern "C" DLLEXPORT bool WriteMessageSimple(CID* pID,
  TosWriteMessageFlags nFlags, LPCTSTR pszFormat);

////// [from MyVBDll code]
<from class module>
Public Function VBFunc(ByVal hDrive As Long, _
  ByVal intUse_UVW As Integer, ByVal blnDebug As Boolean) As Integer
    gDriveID = hDrive
    <code that calls callback functions like VBSetFunc below>
    VBFunc = 1
End Function

<from code module>
' Read value
Public Declare Function GetValue Lib " MyVCDll.dll" (ByVal pID _
  As Long, ByVal pszName As String, ByRef dwValue As Long, _
  ByRef iecDataType As Integer) As Boolean
' Write value
Public Declare Function SetValue Lib " MyVCDll.dll" (ByVal pID _
  As Long, ByVal pszName As String, ByVal dwValue As Long) As Integer
' Write message
Public Declare Function WriteMessageSimple Lib " MyVCDll.dll" _
  (ByVal pID As Long, ByVal nFlags As Long, _
   ByVal pszFormat As String) As Boolean

Public Function VBSetFunc(SymbolX As String, NewData As Double) _
  As Boolean
Dim lngNewData As Long
Dim intReturn As Integer

    lngNewData = NewData
    intReturn = SetValue(gDriveID, SymbolX, lngNewData)
    If intReturn = 0 Then
        VBSetFunc = True
    Else
        VBSetFunc = False
        WriteMessageSimple gDriveID, MSG_ERROR, "Failed to write " _
          & SymbolX
    End If
End Function



Tue, 20 Sep 2005 00:27:46 GMT  
 VC6 DLL calls VB6 DLL calls back to VC6 DLL: Occasional GPF or ‘Bad DLL calling convention'

Quote:

> I have a VC++6 DLL that calls a VB6 DLL which calls back into the
> VC++6 DLL.  For some weeks it appeared to work.  However, after making
> trivial code changes (not interface), I experience GPF's (typically)
> or "Bad DLL calling convention" errors (rarely).  Failures do not
> appear deterministic ANY code change can change the instruction the
> code appears to fail on.  It smells like stack corruption.  Can anyone
> offer a suggestion on the potential root cause?...Chris

> ////// [from MyApp.h file]
> #define DLLEXPORT __declspec(dllexport)

> extern "C" DLLEXPORT bool GetValue(CID* pID, LPCTSTR pszName,
>   DWORD& dwValue, TosIECDataType& iecDataType);
> extern "C" DLLEXPORT int  SetValue(CID* pID, LPCTSTR pszName,
>   DWORD dwValue);
> extern "C" DLLEXPORT bool WriteMessageSimple(CID* pID,
>   TosWriteMessageFlags nFlags, LPCTSTR pszFormat);

These should all be __stdcall.  If you were relying on the compiler
switch to set the default convention and you accidentally changed it,
that would result in GPFs and bad calling convention errors.

--
Craig Powers
MVP - Visual C++



Tue, 20 Sep 2005 00:44:17 GMT  
 VC6 DLL calls VB6 DLL calls back to VC6 DLL: Occasional GPF or ‘Bad DLL calling convention'

Quote:

> I have a VC++6 DLL that calls a VB6 DLL which calls back into the
> VC++6 DLL.  For some weeks it appeared to work.  However, after making
> trivial code changes (not interface), I experience GPF's (typically)
> or "Bad DLL calling convention" errors (rarely).  Failures do not
> appear deterministic ANY code change can change the instruction the
> code appears to fail on.  It smells like stack corruption.  Can anyone
> offer a suggestion on the potential root cause?...Chris

> Sterilized code snippets from MyVCDll.cpp, MyApp.h and MyVBDll files:

> ////// [from MyVCDll.cpp file]
> #include "stdafx.h"
> #include <stdarg.h>
> #include <stdio.h>
> #include "MyApp.h"
> #import "dll\MyVBDll.dll" no_namespace

> bool DLLEXPORT VCFunc(CID *pID, short iUse_UVW, bool blnDebug)
> {
>         CoInitialize(NULL);
>         bool  bReturn;
>         short iReturn;
>         _MyVBDllPtr ptr;
>         ptr.CreateInstance(__uuidof(MyVBDll));
>         iReturn = ptr->VBFunc((int)pID, iUse_UVW, blnDebug);
>         return TRUE;
>         CoUninitialize();
> }

Unrelated error - ptr is not released prior to the CoUninitialize()
call, which I believe is likely to cause problems when it tries to
Release in its dtor.

--
Craig Powers
MVP - Visual C++



Tue, 20 Sep 2005 00:45:13 GMT  
 VC6 DLL calls VB6 DLL calls back to VC6 DLL: Occasional GPF or ‘Bad DLL calling convention'


Fri, 19 Jun 1992 00:00:00 GMT  
 VC6 DLL calls VB6 DLL calls back to VC6 DLL: Occasional GPF or ‘Bad DLL calling convention'

Quote:
>>         return TRUE;
>>         CoUninitialize();
>> }

> Unrelated error - ptr is not released prior to the CoUninitialize()
> call, which I believe is likely to cause problems when it tries to
> Release in its dtor.

CoUninitialize is never called because is after the return statement.
--
Eduardo A. Morcillo [MS MVP - VB]
http://www.domaindlx.com/e_morcillo


Tue, 20 Sep 2005 03:09:37 GMT  
 VC6 DLL calls VB6 DLL calls back to VC6 DLL: Occasional GPF or ‘Bad DLL calling convention'

Quote:

> >>         return TRUE;
> >>         CoUninitialize();
> >> }

> > Unrelated error - ptr is not released prior to the CoUninitialize()
> > call, which I believe is likely to cause problems when it tries to
> > Release in its dtor.

> CoUninitialize is never called because is after the return statement.

Oops.  Heh.  Still a bug, just not the one I identified.  I also missed
the mismatch of TRUE (integer constant for Windows typedef BOOL) and
the bool return type (the constant for which is true).

So, it should probably be more like this:
        // ...
        ptr.Release();
        CoUninitialize();
        return true;
    }

--
Craig Powers
MVP - Visual C++



Tue, 20 Sep 2005 03:47:10 GMT  
 VC6 DLL calls VB6 DLL calls back to VC6 DLL: Occasional GPF or ‘Bad DLL calling convention'
Hi,

Your code below answers a problem i've been having. How to call a VB ActiveX
dll from a c dll.

I'm a bit confused by the '_MyVBDllPtr ptr;' line, as i am a beginner in
VC++ I don't understand how/where _MyVBDllPtr is being set.

TIA

Andy


Quote:
> I have a VC++6 DLL that calls a VB6 DLL which calls back into the
> VC++6 DLL.  For some weeks it appeared to work.  However, after making
> trivial code changes (not interface), I experience GPF's (typically)
> or "Bad DLL calling convention" errors (rarely).  Failures do not
> appear deterministic - ANY code change can change the instruction the
> code appears to fail on.  It smells like stack corruption.  Can anyone
> offer a suggestion on the potential root cause?...Chris

> Sterilized code snippets from MyVCDll.cpp, MyApp.h and MyVBDll files:

> ////// [from MyVCDll.cpp file]
> #include "stdafx.h"
> #include <stdarg.h>
> #include <stdio.h>
> #include "MyApp.h"
> #import "dll\MyVBDll.dll" no_namespace

> bool DLLEXPORT VCFunc(CID *pID, short iUse_UVW, bool blnDebug)
> {
> CoInitialize(NULL);
> bool  bReturn;
> short iReturn;
> _MyVBDllPtr ptr;
> ptr.CreateInstance(__uuidof(MyVBDll));
> iReturn = ptr->VBFunc((int)pID, iUse_UVW, blnDebug);
> return TRUE;
> CoUninitialize();
> }

> ////// [from MyApp.h file]
> #define DLLEXPORT __declspec(dllexport)

> extern "C" DLLEXPORT bool GetValue(CID* pID, LPCTSTR pszName,
>   DWORD& dwValue, TosIECDataType& iecDataType);
> extern "C" DLLEXPORT int  SetValue(CID* pID, LPCTSTR pszName,
>   DWORD dwValue);
> extern "C" DLLEXPORT bool WriteMessageSimple(CID* pID,
>   TosWriteMessageFlags nFlags, LPCTSTR pszFormat);

> ////// [from MyVBDll code]
> <from class module>
> Public Function VBFunc(ByVal hDrive As Long, _
>   ByVal intUse_UVW As Integer, ByVal blnDebug As Boolean) As Integer
>     gDriveID = hDrive
>     <code that calls callback functions like VBSetFunc below>
>     VBFunc = 1
> End Function

> <from code module>
> ' Read value
> Public Declare Function GetValue Lib " MyVCDll.dll" (ByVal pID _
>   As Long, ByVal pszName As String, ByRef dwValue As Long, _
>   ByRef iecDataType As Integer) As Boolean
> ' Write value
> Public Declare Function SetValue Lib " MyVCDll.dll" (ByVal pID _
>   As Long, ByVal pszName As String, ByVal dwValue As Long) As Integer
> ' Write message
> Public Declare Function WriteMessageSimple Lib " MyVCDll.dll" _
>   (ByVal pID As Long, ByVal nFlags As Long, _
>    ByVal pszFormat As String) As Boolean

> Public Function VBSetFunc(SymbolX As String, NewData As Double) _
>   As Boolean
> Dim lngNewData As Long
> Dim intReturn As Integer

>     lngNewData = NewData
>     intReturn = SetValue(gDriveID, SymbolX, lngNewData)
>     If intReturn = 0 Then
>         VBSetFunc = True
>     Else
>         VBSetFunc = False
>         WriteMessageSimple gDriveID, MSG_ERROR, "Failed to write " _
>           & SymbolX
>     End If
> End Function



Sun, 25 Sep 2005 00:50:39 GMT  
 VC6 DLL calls VB6 DLL calls back to VC6 DLL: Occasional GPF or ‘Bad DLL calling convention'

Quote:

> Your code below answers a problem i've been having. How to call a VB ActiveX
> dll from a c dll.

> I'm a bit confused by the '_MyVBDllPtr ptr;' line, as i am a beginner in
> VC++ I don't understand how/where _MyVBDllPtr is being set.

It's created by the #import statement.

A normal VB class is a COM coclass.  It has one interface, which has
the name of the class but prepended with an underscore (this isn't a
legal VB name, so there's no risk of collision with something defined
by the user).

So if your VB class is MyVBDll, in the type library you'll have a
coclass named MyVBDll which implements as its default interface
a dual interface named _MyVBDll.

#import generates a smart pointer for this which acts an awful lot
like a VB object reference.  It's done in a macro, like so:
    _COM_SMARTPTR_TYPEDEF(_MyVBDll, __uuidof(_MyVBDll));

This macro creates a typedef for the smart pointer named _MyVBDllPtr.

--
Craig Powers
MVP - Visual C++



Sun, 25 Sep 2005 02:20:08 GMT  
 VC6 DLL calls VB6 DLL calls back to VC6 DLL: Occasional GPF or ‘Bad DLL calling convention'
Quote:

> Your code below answers a problem i've been having. How to call a VB ActiveX
> dll from a c dll.

A few additional references (beyond Craig's nice summary) include
Microsoft KB article Q194873 on "HOWTO: Access a Visual Basic ActiveX
DLL from Visual C++" and an MSDN article called "Dr. GUI on
Components, COM, and ATL"
(http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dngu...)


Sun, 25 Sep 2005 23:43:42 GMT  
 VC6 DLL calls VB6 DLL calls back to VC6 DLL: Occasional GPF or ‘Bad DLL calling convention'


Fri, 19 Jun 1992 00:00:00 GMT  
 VC6 DLL calls VB6 DLL calls back to VC6 DLL: Occasional GPF or ‘Bad DLL calling convention'

Quote:

> These should all be __stdcall.  If you were relying on the compiler
> switch to set the default convention and you accidentally changed it,
> that would result in GPFs and bad calling convention errors.

Thanks for the input.  I thought I has solved this problem.  (I am a
total C/VC6 and newsgroup novice.)  Since the VC6 dll is actually
called from both "C" code and an ActiveX dll (VB), I have created
wrappers that allow me to export the VB-related functions with the
stdcall calling convention:

    extern "C" bool __stdcall GetValue32(CTosvert* pTosvert, LPCTSTR
pszName, DWORD& dwValue, TosIECDataType& iecDataType);
    extern "C" int  __stdcall SetValue32(CTosvert* pTosvert, LPCTSTR
pszName, DWORD dwValue);
    extern "C" bool __stdcall WriteMessageSimple32(CTosvert* pTosvert,
TosWriteMessageFlags nFlags, LPCTSTR pszFormat);

This way the same dll supports both types of calls.  Do you see any
flaws in this?



Tue, 27 Sep 2005 06:04:53 GMT  
 VC6 DLL calls VB6 DLL calls back to VC6 DLL: Occasional GPF or ‘Bad DLL calling convention'

Quote:


> > These should all be __stdcall.  If you were relying on the compiler
> > switch to set the default convention and you accidentally changed it,
> > that would result in GPFs and bad calling convention errors.

> Thanks for the input.  I thought I has solved this problem.  (I am a
> total C/VC6 and newsgroup novice.)  Since the VC6 dll is actually
> called from both "C" code and an ActiveX dll (VB), I have created
> wrappers that allow me to export the VB-related functions with the
> stdcall calling convention:

>     extern "C" bool __stdcall GetValue32(CTosvert* pTosvert, LPCTSTR
> pszName, DWORD& dwValue, TosIECDataType& iecDataType);
>     extern "C" int  __stdcall SetValue32(CTosvert* pTosvert, LPCTSTR
> pszName, DWORD dwValue);
>     extern "C" bool __stdcall WriteMessageSimple32(CTosvert* pTosvert,
> TosWriteMessageFlags nFlags, LPCTSTR pszFormat);

> This way the same dll supports both types of calls.  Do you see any
> flaws in this?

Not as such.  As long as you explicitly specify stdcall, you shouldn't
need a parallel cdecl variant, though -- the source of trouble is
reliance on compiler settings to get it right.  But if what you have
is working, I doubt it's worth the effort to change it.

--
Craig Powers
MVP - Visual C++



Fri, 30 Sep 2005 21:58:04 GMT  
 
 [ 12 post ] 

 Relevant Pages 

1. Problem calling into managed DLL that calls unmanaged DLL

2. Bad DLL calling convention in my MFC (for VB) DLL

3. calling from non-net C++ DLL to .net DLL and back

4. Call Back Functions call from within a DLL

5. VC7 calling VC6 MFC DLL

6. VC7 calling VC6 DLL

7. VC6 debugger hangs with DLL called from VBA

8. Calling VB DLL in VC6

9. Calling VB DLL from VC6

10. Calling VB DLL in VC6

11. GPF in VB call to MFC-based DLL (VC++2.1)

12. HOWTO? Calling VB DLL from C++ DLL

 

 
Powered by phpBB® Forum Software