Link to home
Start Free TrialLog in
Avatar of Harsh08
Harsh08

asked on

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
Avatar of GrahamSkan
GrahamSkan
Flag of United Kingdom of Great Britain and Northern Ireland image

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

Dim dwEnrollNumber As String * 100
Avatar of Harsh08
Harsh08

ASKER

Tried it but same error
Since it is a 'BSTR*' (i.e. a pointer), you should IMHO declare that as 'ByRef'.
Avatar of Harsh08

ASKER

Thnx...
But I have tried that even....
& I have an application installed, which works fine with this dll
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
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)
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.
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
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
ASKER CERTIFIED SOLUTION
Avatar of HooKooDooKu
HooKooDooKu

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
This question has been classified as abandoned and is closed as part of the Cleanup Program. See the recommendation for more details.