Solved

c dll calling from VB6 - Parameter Error

Posted on 2013-01-06
12
1,617 Views
Last Modified: 2013-02-06
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
Comment
Question by:Harsh08
12 Comments
 
LVL 76

Expert Comment

by:GrahamSkan
ID: 38748363
Try declaring dwEnrollNumber as a fixed-length string, large enough to accommodate the expected text, e.g.

Dim dwEnrollNumber As String * 100
0
 

Author Comment

by:Harsh08
ID: 38748427
Tried it but same error
0
 
LVL 86

Expert Comment

by:jkr
ID: 38748878
Since it is a 'BSTR*' (i.e. a pointer), you should IMHO declare that as 'ByRef'.
0
 

Author Comment

by:Harsh08
ID: 38748890
Thnx...
But I have tried that even....
& I have an application installed, which works fine with this dll
0
 
LVL 9

Expert Comment

by:shorvath
ID: 38750406
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
What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 
LVL 16

Expert Comment

by:HooKooDooKu
ID: 38756935
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
 
LVL 16

Expert Comment

by:HooKooDooKu
ID: 38756951
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
 
LVL 16

Expert Comment

by:HooKooDooKu
ID: 38756960
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
 
LVL 16

Expert Comment

by:HooKooDooKu
ID: 38756983
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
 
LVL 16

Accepted Solution

by:
HooKooDooKu earned 500 total points
ID: 38760928
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
 
LVL 45

Expert Comment

by:Martin Liss
ID: 38858717
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

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

The debugging module of the VB 6 IDE can be accessed by way of the Debug menu item. That menu item can normally be found in the IDE's main menu line as shown in this picture.   There is also a companion Debug Toolbar that looks like the followin…
Windows programmers of the C/C++ variety, how many of you realise that since Window 9x Microsoft has been lying to you about what constitutes Unicode (http://en.wikipedia.org/wiki/Unicode)? They will have you believe that Unicode requires you to use…
Show developers how to use a criteria form to limit the data that appears on an Access report. It is a common requirement that users can specify the criteria for a report at runtime. The easiest way to accomplish this is using a criteria form that a…
The goal of this video is to provide viewers with basic examples to understand and use structures in the C programming language.

746 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

13 Experts available now in Live!

Get 1:1 Help Now