createProcessususer函数从服务运行GUI程序

发布于 2025-01-23 03:16:36 字数 3531 浏览 3 评论 0原文

以下是我用来从服务应用程序运行GUI应用程序的代码。我正在传递CMD字符串“ C:\ Windows \ Notepad.exe”。

它没有打开记事本,甚至没有任何错误。即使使用WTSQueryUserToken之后,Htoken也是无效的。 以下是用户创建过程的文档链接: https://lealen.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsathreadsapi-createprocessasusera

private void cpasUser(String cmd) {
        HANDLE h = null; 
        final HANDLEByReference childStdInRead = new HANDLEByReference();
        final HANDLEByReference childStdInWrite = new HANDLEByReference();
        final HANDLEByReference childStdOutRead = new HANDLEByReference();
        final HANDLEByReference childStdOutWrite = new HANDLEByReference();
        
        final int HANDLE_FLAG_INHERIT = 0x00000001;
        final int HANDLE_FLAG_PROTECT_FROM_CLOSE = 0x00000002;
        
        final int BUFSIZE = 4096;
        final int GENERIC_READ = 0x80000000;
        final int FILE_ATTRIBUTE_READONLY = 1;
        final int OPEN_EXISTING = 3;
        final DWORD STD_OUTPUT_HANDLE = new DWORD(-11);
        final int STARTF_USESTDHANDLES = 0x00000100;
        
        String szCmdline = cmd;

        PROCESS_INFORMATION processInformation = new PROCESS_INFORMATION();
        STARTUPINFO startupInfo = new STARTUPINFO();
        startupInfo.cb = new DWORD(processInformation.size());
        startupInfo.hStdError = childStdOutWrite.getValue();
        startupInfo.hStdOutput = childStdOutWrite.getValue();
        startupInfo.hStdInput = childStdInRead.getValue();
        startupInfo.dwFlags |= STARTF_USESTDHANDLES;
 
        // Create the child process. 
        HANDLE hToken = null;
        MyWtsapi32 mw = MyWtsapi32.INSTANCE;
        mw.WTSQueryUserToken(Kernel32Ext.INSTANCE.WTSGetActiveConsoleSessionId(), hToken) ;

      //be sure that the handle is correct ! (can be the issue)
      if (hToken == null) logger.info("Token error.");
        if (!Advapi32.INSTANCE.CreateProcessAsUser(
                hToken, 
                szCmdline, 
                null, 
                null, 
                null,
                true, 
                32, 
                null, 
                null, 
                startupInfo, 
                processInformation)){
           // System.err.println(Advapi32.INSTANCE.GetLastError());
            logger.error("Cannot create process as User ");
            logger.error("error code "+Native.getLastError());
        }

mywtsapi32.java

public interface MyWtsapi32 extends Wtsapi32 {
      // Your own instance to access your functions
     MyWtsapi32 INSTANCE =  Native.load("Wtsapi32", MyWtsapi32.class, W32APIOptions.DEFAULT_OPTIONS);
    
    // From https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messagebox
    int MB_OK = 0; 

    // The function to send the message
      boolean WTSSendMessageW(HANDLE hServer, int SessionId,
        LPWSTR pTitle, int TitleLength,
        LPWSTR pMessage, int MessageLength,
        int Style, int Timeout, IntByReference pResponse, boolean bWait);
      
      boolean WTSQueryUserToken(long SessionId,HANDLE hServer);
}

强>

public interface Kernel32Ext extends Kernel32{
    Kernel32Ext INSTANCE = Native.load("Kernel32",Kernel32Ext.class,W32APIOptions.DEFAULT_OPTIONS);
    
    int WTSGetActiveConsoleSessionId();
}

Below is the code I am using to run a GUI app from service application. I am passing cmd string "C:\Windows\notepad.exe".

It is not opening the Notepad and not even giving any error. hToken is null even after using WTSQueryUserToken.
Here is a documentation link for create process as user : https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessasusera

private void cpasUser(String cmd) {
        HANDLE h = null; 
        final HANDLEByReference childStdInRead = new HANDLEByReference();
        final HANDLEByReference childStdInWrite = new HANDLEByReference();
        final HANDLEByReference childStdOutRead = new HANDLEByReference();
        final HANDLEByReference childStdOutWrite = new HANDLEByReference();
        
        final int HANDLE_FLAG_INHERIT = 0x00000001;
        final int HANDLE_FLAG_PROTECT_FROM_CLOSE = 0x00000002;
        
        final int BUFSIZE = 4096;
        final int GENERIC_READ = 0x80000000;
        final int FILE_ATTRIBUTE_READONLY = 1;
        final int OPEN_EXISTING = 3;
        final DWORD STD_OUTPUT_HANDLE = new DWORD(-11);
        final int STARTF_USESTDHANDLES = 0x00000100;
        
        String szCmdline = cmd;

        PROCESS_INFORMATION processInformation = new PROCESS_INFORMATION();
        STARTUPINFO startupInfo = new STARTUPINFO();
        startupInfo.cb = new DWORD(processInformation.size());
        startupInfo.hStdError = childStdOutWrite.getValue();
        startupInfo.hStdOutput = childStdOutWrite.getValue();
        startupInfo.hStdInput = childStdInRead.getValue();
        startupInfo.dwFlags |= STARTF_USESTDHANDLES;
 
        // Create the child process. 
        HANDLE hToken = null;
        MyWtsapi32 mw = MyWtsapi32.INSTANCE;
        mw.WTSQueryUserToken(Kernel32Ext.INSTANCE.WTSGetActiveConsoleSessionId(), hToken) ;

      //be sure that the handle is correct ! (can be the issue)
      if (hToken == null) logger.info("Token error.");
        if (!Advapi32.INSTANCE.CreateProcessAsUser(
                hToken, 
                szCmdline, 
                null, 
                null, 
                null,
                true, 
                32, 
                null, 
                null, 
                startupInfo, 
                processInformation)){
           // System.err.println(Advapi32.INSTANCE.GetLastError());
            logger.error("Cannot create process as User ");
            logger.error("error code "+Native.getLastError());
        }

MyWtsApi32.java

public interface MyWtsapi32 extends Wtsapi32 {
      // Your own instance to access your functions
     MyWtsapi32 INSTANCE =  Native.load("Wtsapi32", MyWtsapi32.class, W32APIOptions.DEFAULT_OPTIONS);
    
    // From https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messagebox
    int MB_OK = 0; 

    // The function to send the message
      boolean WTSSendMessageW(HANDLE hServer, int SessionId,
        LPWSTR pTitle, int TitleLength,
        LPWSTR pMessage, int MessageLength,
        int Style, int Timeout, IntByReference pResponse, boolean bWait);
      
      boolean WTSQueryUserToken(long SessionId,HANDLE hServer);
}

Kernel32Ext.java

public interface Kernel32Ext extends Kernel32{
    Kernel32Ext INSTANCE = Native.load("Kernel32",Kernel32Ext.class,W32APIOptions.DEFAULT_OPTIONS);
    
    int WTSGetActiveConsoleSessionId();
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

苯莒 2025-01-30 03:16:36

当您的JNA功能映射不起作用时,第一个调试步骤应该是检查您的功能映射。

wtsqueryusertoken定义为:

BOOL WTSQueryUserToken(
    ULONG SessionId,
    PHANDLE phToken
);

Windows类型ulong is 一个无符号的32位整数;它应映射为int,而不是long

phandle是指向handle>的指针,而不是句柄本身。正确的JNA映射为handleByReference

因此,您的接口函数映射应该是:

boolean WTSQueryUserToken(int SessionId, HANDLEByReference hServer);

您要调用的代码应为:

HANDLEByReference phToken = new HANDLEByReference();
MyWtsapi32 mw = MyWtsapi32.INSTANCE;
// you should probably check the return value here
// on failure throw LastErrorException
mw.WTSQueryUserToken(Kernel32Ext.INSTANCE.WTSGetActiveConsoleSessionId(), phToken);

// Extract the HANDLE for use in later code
HANDLE hToken = phToken.getValue();

When your JNA function mappings don't work, the first debugging step should be to check your function mappings.

WTSQueryUserToken is defined as:

BOOL WTSQueryUserToken(
    ULONG SessionId,
    PHANDLE phToken
);

The Windows type ULONG is an unsigned 32-bit integer; it should be mapped as int, not long.

PHANDLE is a pointer to a HANDLE, not the handle itself. The correct JNA mapping is HANDLEByReference.

So your interface function mapping should be:

boolean WTSQueryUserToken(int SessionId, HANDLEByReference hServer);

And your code to call it should be:

HANDLEByReference phToken = new HANDLEByReference();
MyWtsapi32 mw = MyWtsapi32.INSTANCE;
// you should probably check the return value here
// on failure throw LastErrorException
mw.WTSQueryUserToken(Kernel32Ext.INSTANCE.WTSGetActiveConsoleSessionId(), phToken);

// Extract the HANDLE for use in later code
HANDLE hToken = phToken.getValue();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文