Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

Win32::API and CreateProcessWithLogonW

by slloyd (Hermit)
on Jan 30, 2007 at 05:24 UTC ( #597279=perlquestion: print w/ replies, xml ) Need Help??
slloyd has asked for the wisdom of the Perl Monks concerning the following question:

I am trying to use CreateProcessWithLogonW with Win32::API and cannot seem to get it to work. It always returns "The parameter is incorrect". Any ideas what I am doing wrong?
#!perl use strict; use Win32::API; my $user="username"; my $pass="password"; print createProcessWithLogon('notepad.exe',$user,$pass); exit; ############### sub createProcessWithLogon{ my $program=shift; my $username=shift; my $password=shift; my $LOGON_NETCREDENTIALS_ONLY = 0x2; my $CREATE_NEW_CONSOLE = 0x10; my $CreateProcessWithLogon = new Win32::API('advapi32.dll', 'Creat +eProcessWithLogonW', ['P','P','P','P','P','P','P','P','P','P','P'],'N +') || return $^E; print "calling[$program,$username,$password]\n"; #Set Flag my $dwFlags = 1; # STARTF_USESHOWWINDOW $dwFlags |= 0x100; # STARTF_USESTDHANDLES otherwise we inherit t +he parents handles on 98 # SW_HIDE=0 SW_SHOWNORMAL=1 SW_SHOWMINIMIZED=2 my $show=1; my $si = pack("LLLLLLLLLLLL SS LLLL",68,0,0,0,0,0,0,0,0,0,0,$dwFla +gs,$show,0,0,-1,-1,-1); my $processinfo = pack("LLLL",0,0,0,0); my $num=$CreateProcessWithLogon->Call( $username, #lpUsername undef, #lpDomain $password, #lpPassword $LOGON_NETCREDENTIALS_ONLY, #dwLogonFlags, "hello", #lpApplicationName $program, #lpCommandLine $CREATE_NEW_CONSOLE, #dwLogonFlags, undef, #lpEnvironment ".", #lpCurrentDirectory $si, #lpStartupInfo $processinfo #lpProcessInfo ) || return "Bad Call - $^E"; return $num; }

-------------------------------
Need a good Perl friendly Host Provider?
http://www.dreamhost.com

Comment on Win32::API and CreateProcessWithLogonW
Download Code
Re: Win32::API and CreateProcessWithLogonW
by Anonymous Monk on Jan 30, 2007 at 06:24 UTC
      So isn't there a way to pass in Unicode (wChar) to a Win32::API process?

      -------------------------------
      Need a good Perl friendly Host Provider?
      http://www.dreamhost.com

        Last I checked, to pass via Win32::API a pointer to anything other than a "\0"-terminated string, you have to jump through some extra hoops. You have to say that you want to pass in an int not a pointer ("I" not "P") and then actually pass in unpack( "L", pack "p", $utf18 ). But perhaps the newer versions of Win32::API provide less cumbersome ways.

        - tye        

Re: Win32::API and CreateProcessWithLogonW
by BrowserUk (Pope) on Jan 30, 2007 at 06:40 UTC

    Update: Corrected UTF8LE to UTF-16LE per tye's post below.

    The problem is that your are importing the wide (W) api, CreateProcessWithLogonW(), and attempting to pass it ascii character strings. You will need to promote these to UTF-16LE.

    Google does turn a handful of references to an A variant, CreateProcessWithLogonA(), but none of them are at an MS site, or anywhere that looks authoratative. I also consulted my 'big list of exports', and no A variant is exported from any of the DLLs on my system. Of those that I've catalogued--I may still have missed some.

    I can never remember the official invocations required to convert/promote an ascii string to utf-16le, and you can supersearch as well as I can. "UTF-16LE" would probably be a good search term. From memory, I believe ikegami &| Corion have posted definitive information on this subject, which might serve to speed your search.


    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.

      I convert between UTF-16LE (not "UTF8LE" as you wrote) and ASCII or UTF-8 using pack rather simply:

      $utf16= pack "S*", unpack( "C*", $ascii ), 0; $utf16= pack "S*", unpack( "U*", $utf8 ), 0; $ascii= pack "C*", unpack( "S*", $utf16 ); $ascii =~ s/\0$//; $utf8 = pack "U*", unpack( "S*", $utf16 ); $utf8 =~ s/\0$//;

      but note that this doesn't handle extra large Unicode code points (which Windows doesn't handle by default either but can be configured to support at least partially).

      To feel less hackish, one would likely use the Encode module, which can probably also handle the characters in the Windows-1252 extensions to Latin-1.

      - tye        

        I have a couple of similar routines I use for myself, but I'm reluctant to recommend to others, because of the ire they are likely to draw:

        sub A2W{ pack 'S*', unpack 'C*', $_[0] } sub W2A{ pack 'C*', unpack 'S*', $_[0] }

        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.
Re: Win32::API and CreateProcessWithLogonW
by BrowserUk (Pope) on Jan 30, 2007 at 07:13 UTC

    Since I got this to work, I thought I'd post it, though you'd need to modify it if you don't use Win32::APi::prototype. And my hackish way of converting ASCII to WIDE will probably cause some frowns.

    You'll also need to ensure you have the 'Secondary Logon' service running, even if you use the current user's logon credentials. I routinely have that disabled, which is what was stopping me from getting this to work earlier. The error message:

    The service cannot be started, either because it is disabled or becaus +e it has no enabled devices associated with it at ...

    Is less than helpful, as it doesn't tell you which service it needs, and I have many of the standard ones turned off.

    #! perl -slw use strict; use Win32::API::Prototype; sub A2W{ pack 'S*', unpack 'C*', $_[0] } sub W2A{ pack 'C*', unpack 'S*', $_[0] } ApiLink( 'advapi32.dll', q[ BOOL CreateProcessWithLogonW( LPCWSTR lpUsername, LPCWSTR lpDomain, LPCWSTR lpPassword, DWORD dwLogonFlags, LPCWSTR lpApplicationName, LPTR lpCommandLine, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInfo ) ] ) or die $^E; my $si = pack( 'LLLLLLLLLLLL SS LLLL', 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1|0x100, 1, 0, 0, -1, -1, -1 ); CreateProcessWithLogonW( A2W( 'theUsername' ), A2W( '\\.\ ' ), A2W( 'thePasword' ), 0, A2W( 'C:/windows/system32/notepad.exe' ), 0, 0, 0, 0, $si, chr(0) x 100 ) or die $^E;

    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.

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others surveying the Monastery: (7)
As of 2014-12-26 08:03 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    Is guessing a good strategy for surviving in the IT business?





    Results (168 votes), past polls