Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1725
  • Last Modified:

c dll calling from VB6 - Parameter Error

Private Declare Function SSR_GetGeneralLogData Lib "c:\Windows\System32\zkemkeeper.DLL" (ByVal dwMachineNumber As Long, _
ByVal dwEnrollNumber As String, ByVal dwSize As Long, ByVal dwVerifyMode As Long, _
ByVal dwInOutMode As Long, ByRef dwYear As Long, ByRef dwYear As Long, ByRef dwMonth As Long, ByRef dwDay As Long, ByRef dwHour As Long, ByRef dwMinute As Long, ByRef dwsecond As Long, ByRef dwWorkCode As Long) As Boolean

 Dim ver As String
    Dim vMachineNumber
    Dim dwEnrollNumber As String
    Dim dwVerifyMode As Long
    Dim dwInOutMode As Long
    Dim timeStr As String
    Dim i As Long
    Dim dwMachineNum As Long
    Dim dwEMachineNum As Long
    Dim dwYear As Long
    Dim dwMonth As Long
    Dim dwDay As Long
    Dim dwHour As Long
    Dim dwMinute As Long
    Dim dwsecond As Long
    Dim dwWorkCode As Long
    Dim dwReserved As Long
   
     Dim s As String
 
    'DLL PARAMETERS
    '[in] LONG dwMachineNumber,
    '[out] BSTR* dwEnrollNumber,
    '[out] LONG* dwVerifyMode,
    '[out] LONG* dwInOutMode,
    '[out] LONG* dwYear,
    '[out]LONG* dwMonth,
    '[out] LONG* dwDay,
    '[out] LONG* dwHour,
    '[out] LONG* dwMinute,
    '[out] LONG* dwSecond,
    '[out,retval] VARIANT_BOOL* pVal

   
    If CZKEM1.ReadGeneralLogData(1) Then
        BUFFER OVERRUN AFTER EXECUTING FOLLOWING LINE

        While CZKEM1.SSR_GetGeneralLogData(1, dwEnrollNumber, dwVerifyMode, dwInOutMode, dwYear, dwMonth, dwDay, dwHour, dwMinute, dwsecond, dwWorkCode)



        DoEvents
        i = i + 1
        'Write to database
       
        'MsgBox strSQL
'''''''            dbs.Execute strSQL, dbFailOnError
        Wend
        End If
        MsgBox "Processed Successfully!"
    End If
0
Harsh08
Asked:
Harsh08
1 Solution
 
GrahamSkanCommented:
Try declaring dwEnrollNumber as a fixed-length string, large enough to accommodate the expected text, e.g.

Dim dwEnrollNumber As String * 100
0
 
Harsh08Author Commented:
Tried it but same error
0
 
jkrCommented:
Since it is a 'BSTR*' (i.e. a pointer), you should IMHO declare that as 'ByRef'.
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
Harsh08Author Commented:
Thnx...
But I have tried that even....
& I have an application installed, which works fine with this dll
0
 
shorvathCommented:
From this link:

http://msdn.microsoft.com/en-us/library/aa263531%28v=vs.60%29.aspx

Some DLLs may be written specifically to work with Automation data types like BSTR, using procedures supplied by Automation.

Because Visual Basic uses Automation data types as its own data types, Visual Basic arguments can be passed by reference to any DLL that expects Automation data types. Thus, if a DLL procedure expects a Visual Basic string as an argument, you do not need to declare the argument with the ByVal keyword, unless the procedure specifically needs the string passed by value.

Some DLL procedures may return strings to the calling procedure. A DLL function cannot return strings unless it is written specifically for use with Automation data types. If it is, the DLL probably supplies a type library that describes the procedures. Consult the documentation for that DLL.

A DLL procedure can modify data in a string variable that it receives as an argument. However, if the changed data is longer than the original string, the procedure writes beyond the end of the string, probably corrupting other data.

You can avoid this problem by making the string argument long enough so that the DLL procedure can never write past the end of it


Then try

Dim dwEnrollNumber As String * 255
0
 
HooKooDooKuCommented:
I've never had to do exactly what you are trying, but my experience says that your best bet might be to:
1. Change your declaration for the parameter to 'ByRef'
2. Rather than passing 'dwEnrollNumber', try passing 'VarPtr( dwEnrollNumber )'

Private Declare Function SSR_GetGeneralLogData Lib "c:\Windows\System32\zkemkeeper.DLL" (ByVal dwMachineNumber As Long, _
ByRef dwEnrollNumber As String, ByVal dwSize As Long, ByVal dwVerifyMode As Long, _
ByVal dwInOutMode As Long, ByRef dwYear As Long, ByRef dwYear As Long, ByRef dwMonth As Long, ByRef dwDay As Long, ByRef dwHour As Long, ByRef dwMinute As Long, ByRef dwsecond As Long, ByRef dwWorkCode As Long) As Boolean

While CZKEM1.SSR_GetGeneralLogData(1, VarPtr(dwEnrollNumber), dwVerifyMode, dwInOutMode, dwYear, dwMonth, dwDay, dwHour, dwMinute, dwsecond, dwWorkCode)
0
 
HooKooDooKuCommented:
A few follow up details:

When you pass a VB String to a dll ByVal, you don't really pass it "By Value".  What actually happens is that the VB Unicode String is converted to ANSI and a char* of the ANSI string is sent to the dll.  When the function returns, the ANSI string at the char* is converted into a VB Unicode String and the original VB String is updated with the new value.  So in reality, passing a VB String ByVal still passes ByRef.  And BTW, if the dll makes the char* longer, bad things can happen when VB goes to return the results back into the original string.

When you pass a VB String to a dll ByRef, I believe that a BSTR is sent to the dll.  I don't know that I've ever passed a VB String ByRef, but I do know that if you declare a dll function as returning a BSTR (and not a BSTR*) that you can have code that looks like this:

Declare Function DllThatReturnsBSTR() as String
Dim Str
Str = DllThatReturnsBSTR();

And finally, it's widely known today, but there is a 'hidden' function in VB,  VarPtr().  It returns a pointer to the variable.
0
 
HooKooDooKuCommented:
Oh, and now that I remembered the VarPtr function, you might also try replacing the VarPtr I listed above with either StrPtr or ObjPtr.  Don't know if they will work, but StrPtr is defined as "gives the memory address of the contents of a string".  That might just be the BSTR* (but I'm not sure).  But it is worth a try.

http://www.codeproject.com/Articles/5685/Pointers-in-Visual-Basic-using-Undocumented-Functi
0
 
HooKooDooKuCommented:
One last idea.  Try changing the declare to 'ByRef' and 'As Any').

Private Declare Function SSR_GetGeneralLogData Lib "c:\Windows\System32\zkemkeeper.DLL" (ByVal dwMachineNumber As Long, _
ByRef dwEnrollNumber As Any, ByVal dwSize As Long, ByVal dwVerifyMode As Long, _
ByVal dwInOutMode As Long, ByRef dwYear As Long, ByRef dwYear As Long, ByRef dwMonth As Long, ByRef dwDay As Long, ByRef dwHour As Long, ByRef dwMinute As Long, ByRef dwsecond As Long, ByRef dwWorkCode As Long) As Boolean

The try passing the original variable: dwEnrollNumber
and try passing the pointer to the original value: VarPtr( dwEnrollNumber )
and try passing the pointer to the contents: StrPtr( dwEnrollNumber )
and finally the pointer to the object: ObjPtr( dwEnrollNumber ).

Again, I've never had to try exactly what you are doing (and currently don't have any test code or the time to look for the exact solution).  But one of those combinations should eventually work.


Just to rehash:
1. Try declaring the variable ByRef and ByVal
2. Try declaring the variable 'As String' and 'As Any'
3. Try passing the variable, VarPtr(variable), StrPtr(variable), and ObjPtr(variable).

Try all the possible combinations of these options.  If it still does not work, then the last thing I can think of:

Declare the variable ByVal and As Long (good for passing pointer) and pass VarPtr, StrPtr, and ObjPtr.


Otherwise, the only other thing I can even contemplate on how to fix the issue involved changing the dll (to take something OTHER than a BSTR*... such as a BSTR or char* instead).
3. Also try 'ByRef dwEnrollNumber As Long' (good for passing pointers).
4.

and finally try passing the
0
 
HooKooDooKuCommented:
I got an opportunity to try a test.  It looks like the 1st suggestion of my previous post appears to work (simply declare the variable 'ByRef' and 'as Any').

Here's my test code:

C Source Code for ChkMan32.dll
==========================
long __declspec(dllexport) FAR PASCAL TestBSTR(char* psz, BSTR* strOut )
{
      int len = strlen( psz );
      *strOut = SysAllocStringByteLen( psz, len );
      return 0;
}


VB BAS file Declaration
===================
Public Declare Function TestBSTR Lib "ChkMan32" Alias "_TestBSTR@8" (ByVal psz As String, ByRef strOut As Any) As Long


VB Code
=======
Dim str As String
Dim psz As String

    psz = "ABCDEFG"
    Call TestBSTR(psz, str)
    MsgBox str

"ABCDEFG" appeared in the Message Box
0
 
Martin LissRetired ProgrammerCommented:
This question has been classified as abandoned and is closed as part of the Cleanup Program. See the recommendation for more details.
0

Featured Post

New feature and membership benefit!

New feature! Upgrade and increase expert visibility of your issues with Priority Questions.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now