1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

Example using @WINAPI/@CAPI

Discussion in 'Support' started by millardjk, Aug 22, 2008.

  1. millardjk

    Joined:
    Aug 22, 2008
    Messages:
    29
    Likes Received:
    0
    I'm trying to use either @WINAPI or @CAPI to execute a function in a DLL. I've written C++ code that can use the DLL, so I know the name of the function(s), and I know the DLL is working/functional.

    The prototype for the function(s) I'm wishing to "wrap" are:
    LPCSTR (CALLBACK* LPFNDLLFUNC)(LPCSTR)

    The function names are "Encrypt" and "Decrypt".

    As near as I can tell, the correct use of either variable function is something like:

    echo %@xAPI[mydll.dll,Encrypt,aBUFFER,"plaintext"] (where xAPI is either WIN or C)

    and it should return the text value that is the string being pointed to by the function's return value. However, in practice, nothing is returned, so I know that I'm missing something.

    Can anyone shed some light on what I'm missing? I'd really like to be able to use this...
     
  2. Rex Clark

    Joined:
    May 30, 2008
    Messages:
    57
    Likes Received:
    0
    try it without the commas ,

    ----- Original Message -----


    | I'm trying to use either @WINAPI or @CAPI to execute a function in a DLL.
    I've written C++ code that can use the DLL, so I know the name of the
    function(s), and I know the DLL is working/functional.
    |
    | The prototype for the function(s) I'm wishing to "wrap" are:
    | LPCSTR (CALLBACK* LPFNDLLFUNC)(LPCSTR)
    |
    | The function names are "Encrypt" and "Decrypt".
    |
    | As near as I can tell, the correct use of either variable function is
    something like:
    |
    | echo %@xAPI[mydll.dll,Encrypt,aBUFFER,"plaintext"] (where xAPI is either
    WIN or C)
    |
    | and it should return the text value that is the string being pointed to by
    the function's return value. However, in practice, nothing is returned, so I
    know that I'm missing something.
    |
    | Can anyone shed some light on what I'm missing? I'd really like to be able
    to use this...
     
  3. millardjk

    Joined:
    Aug 22, 2008
    Messages:
    29
    Likes Received:
    0
    Why would doing it w/o commas help? At least with the commas, the proc knows which argument is which. In practice, it makes no difference, which is a surprise to me; I thought for certain that I'd end up with argument mismatch errors.

    Additional data--when run as:

    echo %@xAPI[mydll.dll,Encrypt,a"plaintext"]

    an integer is echoed; I'm going to assume that it's the INT representation for the return value, a long-pointer to a c-style string. Unfortunately, there isn't any way that I can conceive to 'get ahold' of the string at that 'address'.
     
  4. logic

    Joined:
    May 30, 2008
    Messages:
    42
    Likes Received:
    0
    From: millardjk
    Sent: Friday, August 22, 2008 4:16 PM
    Subject: RE: [Support-t-407] Re: Example using @WINAPI/@CAPI
    [snip]

    It *is* possible :-) I did it a while back for my BTM file that lists users
    by calling the network APIs. The trick is actually rather devious. Recall
    that @WINAPI can take a BUFFER (or an aBUFFER) as a target into which a
    value for return by @WINAPI can be placed. If you have a pointer, you can
    pass it into the CopyMemory API to have it blitted into the provided buffer.
    The CopyMemory API is actually an intrinsic backed by RtlMoveMemory in
    kernel32.dll, so you could try something like this:

    set ptr_to_string=%@WINAPI[mydll,Encrypt,a"plaintext"]
    set
    ciphertext=%@WINAPI[kernel32,RtlMoveMemory,aBUFFER,%ptr_to_string,%ciphertex
    t_length]

    To do this, you need to determine what the length of the ciphertext
    %ciphertext_length actually is. If this is an easy computation, you can just
    do that and pass it in *plus 1 for the NUL character*. If you need to strlen
    it, then:

    :StringLength [strptr]
    set count=0
    gosub ReadByteFromPtr %@eval[%strptr + %count]
    do while %byte gt 0
    set /a count=count + 1
    gosub ReadByteFromPtr %@eval[%strptr + %count]
    enddo

    return

    :ReadByteFromPtr [byteptr]
    set byte=%@winapi[kernel32,RtlMoveMemory,BUFFER,%byteptr,1]

    iff "%byte" == "" then
    set byte=0
    else
    set byte=%@eval[%@unicode[%byte] %% 256]
    endiff

    return

    I haven't actually tested the StringLength subroutine, but I know
    ReadByteFromPtr works as I copied it directly from ENUMUSERS.BTM. The
    trickiest part of ReadByteFromPtr is the codepage conversion that takes
    place when you return a character. I got around this by returning it as
    Unicode, but since only one byte is asked for I could only RtlMoveMemory a
    single byte. That means that the upper 8 bits of the unicode character could
    be anything. The modulus operator makes quick work of that, returning the
    lower 8 bits only.

    Hope this helps :-)

    Jonathan Gilbert
     
  5. logic

    Joined:
    May 30, 2008
    Messages:
    42
    Likes Received:
    0
    I hit 'Send' at 11:03 AM. Item showed up at 12:01 PM. 58 minute delay! :-(((

    Jonathan Gilbert

    -----Original Message-----
    From: logic [mailto:]
    Sent: Monday, August 25, 2008 12:01 PM
    To: jgilbert@workwireless.com
    Subject: RE: [Support-t-407] Re: Example using @WINAPI/@CAPI

    [snip]

    Hope this helps :-)

    Jonathan Gilbert
     
  6. millardjk

    Joined:
    Aug 22, 2008
    Messages:
    29
    Likes Received:
    0
    Perfect! No issues with the length of the cyphertext, either; this DLL implements a stream cypher, so the length of the cyphertext can be reliably predicted from the length of the plaintext:
    %@EVAL[%@LEN[%plaintext]+1]

    Thanks for the assist; it's now working very reliably!
     

Share This Page