Example using @WINAPI/@CAPI

  • This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn more.
#1
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
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
try it without the commas ,
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'.
 
May 30, 2008
42
0
#4
From: millardjk
Sent: Friday, August 22, 2008 4:16 PM
Subject: RE: [Support-t-407] Re: Example using @WINAPI/@CAPI
[snip]

> 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'.
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
 
May 30, 2008
42
0
#5
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
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:

[snip]
Hope this helps :-)
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!