Start a process as an another user using JNA (Windows) Tag(s): JNA/JNI


JNA (Java Native Access) provides Java programs easy access to native shared libraries (DLLs on Windows) without writing anything but Java code - no JNI or native code is required.

We use the CreateProcessWithLogin API to start a process as a different user. We need to provide the credentials (username/password and domain (if required)).

First we define the interface.

import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.WString;
import com.sun.jna.platform.win32.Advapi32;
import com.sun.jna.platform.win32.WinBase.PROCESS_INFORMATION;
import com.sun.jna.platform.win32.WinBase.STARTUPINFO;

// https://github.com/twall/jna#readme
// you need 2 jars : jna-3.5.1.jar and platform-3.5.1.jar

public interface MoreAdvApi32 extends Advapi32 {
  MoreAdvApi32 INSTANCE =
        (MoreAdvApi32) Native.loadLibrary("AdvApi32", MoreAdvApi32.class);

  /*
   * BOOL WINAPI CreateProcessWithLogonW( __in LPCWSTR lpUsername,
   * __in_opt LPCWSTR lpDomain, __in LPCWSTR lpPassword, __in DWORD
   * dwLogonFlags, __in_opt LPCWSTR lpApplicationName, __inout_opt LPWSTR
   * lpCommandLine, __in DWORD dwCreationFlags, __in_opt LPVOID
   * lpEnvironment, __in_opt LPCWSTR lpCurrentDirectory, __in
   * LPSTARTUPINFOW lpStartupInfo, __out LPPROCESS_INFORMATION
   * lpProcessInfo );
  */

  // http://msdn.microsoft.com/en-us/library/windows/desktop/ms682431%28v=vs.85%29.aspx
  boolean CreateProcessWithLogonW
            (WString lpUsername,
             WString lpDomain,
             WString lpPassword,
             int dwLogonFlags,
             WString lpApplicationName,
             WString lpCommandLine,
             int dwCreationFlags,
             Pointer lpEnvironment,
             WString lpCurrentDirectory,
             STARTUPINFO  lpStartupInfo,
             PROCESS_INFORMATION lpProcessInfo);

  public static final int LOGON_WITH_PROFILE          = 0x00000001;
  public static final int LOGON_NETCREDENTIALS_ONLY   = 0x00000002;


  int CREATE_NO_WINDOW            = 0x08000000;
  int CREATE_UNICODE_ENVIRONMENT  = 0x00000400;
  int CREATE_NEW_CONSOLE          = 0x00000010;
  int DETACHED_PROCESS            = 0x00000008;
}
To use it :
import com.sun.jna.WString;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.Kernel32Util;
import com.sun.jna.platform.win32.WinBase.PROCESS_INFORMATION;
import com.sun.jna.platform.win32.WinBase.STARTUPINFO;

public class CreateProcessAsUser {
  public static void  main(String ... args ) {
    WString nullW = null;
    PROCESS_INFORMATION processInformation = new PROCESS_INFORMATION();
    STARTUPINFO startupInfo = new STARTUPINFO();
    boolean result = MoreAdvApi32.INSTANCE.CreateProcessWithLogonW
       (new WString("username"),                         // user
        nullW,                                           // domain , null if local
        new WString("password"),                         // password
        MoreAdvApi32.LOGON_WITH_PROFILE,                 // dwLogonFlags
        nullW,                                           // lpApplicationName
        new WString("c:\\windows\\system32\\cmd.exe"),   // command line
        MoreAdvApi32.CREATE_NEW_CONSOLE,                 // dwCreationFlags
        null,                                            // lpEnvironment
        new WString("C:\\temp\\test"),                   // directory
        startupInfo,
        processInformation);

        if (!result) {
          int error = Kernel32.INSTANCE.GetLastError();
          System.out.println("OS error #" + error);
          System.out.println(Kernel32Util.formatMessageFromLastErrorCode(error));
        }
    }
}

blog comments powered by Disqus