Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much
 
PerlMonks  

calling a function from a dll

by nmeijer (Initiate)
on Dec 31, 2012 at 16:24 UTC ( [id://1011073]=perlquestion: print w/replies, xml ) Need Help??

nmeijer has asked for the wisdom of the Perl Monks concerning the following question:

Usually I am pretty good at coding different perl scenarios, but I am at a loss on this one.. please help!

So I received a dll that I dropped on my machine. and was provided with the function call
void XYZDecrypt(char *value,char *key, BSTR *encrypted)

I figured this would be quite easy as I would just..

use Win32::API; $function = Win32::API->new( 'C:\NLSClientLibrary\x86\NLSClientLibrary +.dll', 'void XYZDecrypt(char *value,char *key, BSTR *encrypted)', ); print $function->Call('','8B3A06617FEC4276A5711FBA4861B467', '[000001] +C0808FC9B3062D91E7B9B1D9A7B79216' );

but apparantly it is not that easy as I get errors from an "unknown paramater type BSTR*' as well as a dialog box that pops up indicating that the perl command line interpreter has stopped working. Can anyone help?

Replies are listed 'Best First'.
Re: calling a function from a dll
by Corion (Patriarch) on Dec 31, 2012 at 17:02 UTC

    I never could get the "C type parser" of Win32::API to work. I always had more luck manually constructing the parameter string using the P and I chars, and then using unpack for strings passed in and out.

    In your case, maybe the following construct works:

    $function = Win32::API->new('NSLClientLibrary', 'XYZDecrypt', 'PPP', ' +I'); sub call_function { my ($value, $key, $encrypted) = @_; # Here we pad $value to the expected length, to avoid a buffer ove +rrun # I guess that the result is at most as long as the encrypted stri +ng $value = ' ' x length $encrypted; $function->( $value, $key, $encrypted ); $value =~ s!\0.*!!; # we assume that the first \0 returned indicat +es end of the string return $value };
      $value =~ s!\0.*!!; # we assume that the first \0 returned indicates end of the string

      That is a pretty bad assumption. BSTRs are fixed length arrays of unsigned shorts with a prefix length and can contain multiple nulls.

      See http://blogs.msdn.com/b/ericlippert/archive/2003/09/12/52976.aspx


      With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.

        what is interesting is that the prefix length is a byte count and not a character count,although BSTR is always Unicode

        So to find the end of the string you have to get to the stored length which is stored in the first 2 bytes

        the example at : BSTR layout shows the byte count and the terminated nulls,both required by BSTR

      Am I perhaps calling the function wrong or something? as I get a
      Not a CODE reference at xx.pl line 14
      which is where the $function is called in the sub routine

      #!/usr/bin/perl use Win32::API; my $function = Win32::API->new('C:\XYZClientLibrary\x86\XYZClientLibra +ry.dll', 'XYZDecrypt', 'PPP', 'I'); print call_function('9','8B3A06617FEC4276A5711FBA4861B467', '[000001]C +0808FC9B3062D91E7B9B1D9A7B79216'); sub call_function { my ($value, $key, $encrypted) = @_; # Here we pad $value to the expected length, to avoid a buffer ove +rrun # I guess that the result is at most as long as the encrypted stri +ng $value = ' ' x length($encrypted); print (" $value, $key, $encrypted\n"); $value = $function->( $value, $key, $encrypted ); $value =~ s!\0.*!!; # we assume that the first \0 returned indicat +es end of the string return $value };

        nmeijer:

        Looking at the Win32::API docs, it looks like line 14 should be:

        $value = $function->Call( $value, $key, $encrypted );

        ...roboticus

        When your only tool is a hammer, all problems look like your thumb.

Re: calling a function from a dll
by bulk88 (Priest) on Jan 01, 2013 at 02:54 UTC
    http://msdn.microsoft.com/en-us/library/windows/desktop/ms221069%28v=vs.85%29.aspx

    A BSTR * is something similar to a char **, but it is NOT a char ** or WCHAR **. If the function wants to realloc, free, or take ownership of the BSTR, it can typically do so by put a NULL in your BSTR * or putting a different BSTR into the BSTR *. I am guessing since you didn't provide any docs on the C function it can take ownership. Win32::OLE has a couple nice looking C SV to BSTR and BSTR to SV functions but they are not exported from the DLL by default. A BSTR comes from a foreign memory allocation, you can't treat a BSTR as a regular string-ish scalar (I am not going to write an overload.pm module that implements BSTRs, sorry). You will probably have to treat it as an integer in Perl, then use Perl XS subs or pack() to read, write, and free it. I don't see anything very difficult here, it is just going to take more code in Perl to do it than in C. Windows OS has way too many memory allocators and string formats. Soon someone will want to use ASCII_STRING and UNICODE_STRING with Win32::API.

    TLDR: If your BSTR didn't come from SysAllocString or the like, you will probably crash.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1011073]
Approved by ww
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others chanting in the Monastery: (5)
As of 2024-03-29 05:35 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found