We help IT Professionals succeed at work.
Get Started

CreateProcessAsUser is ignoring wshowwindow's value

AsafG
AsafG asked
on
549 Views
Last Modified: 2013-12-25
Hi all,
This is tough question about CreateProcessAsUser.
I'm trying to build a function that would execute files as a different user than the logged in user.
It works, but I can't get it to obey to the wshowwinsow value as I set it to HIDE / MAXIMIZE / NORMAL. It always shows as normal.
It works fine on w2000 machines, but not on XP !
The CreateProcess function works fine.

Hereunder my code:

Option Explicit

Private Const LOGON_WITH_PROFILE = &H1&
Private Const LOGON_NETCREDENTIALS_ONLY = &H2&
Private Const CREATE_DEFAULT_ERROR_MODE = &H4000000
Private Const CREATE_NEW_CONSOLE = &H10&
Private Const CREATE_NEW_PROCESS_GROUP = &H200&
Private Const CREATE_SEPARATE_WOW_VDM = &H800&
Private Const CREATE_SUSPENDED = &H4&
Private Const CREATE_UNICODE_ENVIRONMENT = &H400&
Private Const INFINITE = &HFFFF
Public Const STARTF_USESTDHANDLES = &H100
Public Const STARTF_USESIZE = &H2
Public Const STARTF_USESHOWWINDOW = &H1


Public Enum enPriority_Class
    ABOVE_NORMAL_PRIORITY_CLASS = &H8000&
    BELOW_NORMAL_PRIORITY_CLASS = &H4000&
    HIGH_PRIORITY_CLASS = &H80&
    IDLE_PRIORITY_CLASS = &H40&
    NORMAL_PRIORITY_CLASS = &H20&
    REALTIME_PRIORITY_CLASS = &H100&
End Enum

Private Type PROCESS_INFORMATION
    hProcess As Long
    hThread As Long
    dwProcessId As Long
    dwThreadId As Long
End Type

Private Type STARTUPINFO
    cb As Long
    lpReserved As String
    lpDesktop As String
    lpTitle As String
    dwX As Long
    dwY As Long
    dwXSize As Long
    dwYSize As Long
    dwXCountChars As Long
    dwYCountChars As Long
    dwFillAttribute As Long
    dwFlags As Long
    wShowWindow As Integer
    cbReserved2 As Integer
    lpReserved2 As Byte
    hStdInput As Long
    hStdOutput As Long
    hStdError As Long
End Type


Private Type SECURITY_ATTRIBUTES
    nLength As Long
    lpSecurityDescriptor As Long
    bInheritHandle As Long
End Type

Public Enum enSW
    SW_HIDE = 0
    SW_NORMAL = 1
    SW_MAXIMIZE = 3
    SW_MINIMIZE = 6
End Enum

Private Declare Function CreateProcessWithLogon Lib "Advapi32" Alias "CreateProcessWithLogonW" (ByVal lpUsername As Long, ByVal lpDomain As Long, ByVal lpPassword As Long, ByVal dwLogonFlags As Long, ByVal lpApplicationName As Long, ByVal lpCommandLine As Long, ByVal dwCreationFlags As Long, ByVal lpEnvironment As Long, ByVal lpCurrentDirectory As Long, lpStartupInfo As STARTUPINFO, lpProcessInfo As PROCESS_INFORMATION) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
Private Declare Function TerminateProcess Lib "kernel32" (ByVal hProcess As Long, ByVal uExitCode As Long) As Long
Private Declare Function CreateProcess Lib "kernel32.dll" Alias "CreateProcessA" (ByVal lpApplicationName As String, ByVal lpCommandLine As String, lpProcessAttributes As SECURITY_ATTRIBUTES, lpThreadAttributes As SECURITY_ATTRIBUTES, ByVal bInheritHandles As Long, ByVal dwCreationFlags As Long, lpEnvironment As Any, ByVal lpCurrentDriectory As String, lpStartupInfo As STARTUPINFO, lpProcessInformation As PROCESS_INFORMATION) As Long
Private Declare Sub GetStartupInfoA Lib "kernel32" (lpInfo As STARTUPINFO)
Private Declare Function CreatePipe Lib "kernel32" (phReadPipe As Long, phWritePipe As Long, lpPipeAttributes As SECURITY_ATTRIBUTES, ByVal nSize As Long) As Long
Private Declare Function ReadFile Lib "kernel32" (ByVal hFile As Long, ByVal lpBuffer As String, ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long, lpOverlapped As Any) As Long
Private Declare Function PeekNamedPipe Lib "kernel32" (ByVal hReadPipe As Long, lpBuffer As Any, ByVal nBufferSize As Long, lpBytesRead As Long, lpTotalBytesAvail As Long, lpBytesLeftThisMessage As Long) As Long
Private Declare Function GetExitCodeProcess Lib "kernel32" (ByVal hProcess As Long, lpExitCode As Long) As Long
   
Public Sub execute(lpCommandLine As String, _
                   Optional lpUsername As String, _
                   Optional lpDomain As String, _
                   Optional lpPassword As String, _
                   Optional bSync As Boolean = False, _
                   Optional lTimeOut As Long = INFINITE, _
                   Optional bKillAfterTimeOut As Boolean, _
                   Optional ePriorityClass As enPriority_Class, _
                   Optional ByVal eStyle As enSW, _
                   Optional lExitCode As Long)
    Dim lpApplicationName As String, lpCurrentDirectory As String, lMultiplier As Long
    Dim StartInfo As STARTUPINFO, ProcessInfo As PROCESS_INFORMATION, ret As Long

       
   
    lpApplicationName = vbNullString
    lpCurrentDirectory = vbNullString 'use standard directory

    StartInfo.cb = Len(StartInfo)
    StartInfo.dwFlags = STARTF_USESHOWWINDOW
    StartInfo.wShowWindow = eStyle
   
    If lTimeOut = INFINITE Then lMultiplier = 1 Else lMultiplier = 1000
   
    If lpUsername = "" Then
        Dim tSec1 As SECURITY_ATTRIBUTES
        Dim tSec2 As SECURITY_ATTRIBUTES
        tSec1.nLength = Len(tSec1)
        tSec2.nLength = Len(tSec2)
        CreateProcess lpApplicationName, lpCommandLine, tSec1, tSec2, False, ePriorityClass, ByVal 0&, vbNullString, StartInfo, ProcessInfo
    Else
        'CreateProcessWithLogon StrPtr(lpUsername), StrPtr(lpDomain), StrPtr(lpPassword), LOGON_WITH_PROFILE, StrPtr(lpApplicationName), StrPtr(lpCommandLine), CREATE_DEFAULT_ERROR_MODE Or CREATE_NEW_CONSOLE Or CREATE_NEW_PROCESS_GROUP, ByVal 0&, StrPtr(lpCurrentDirectory), StartInfo, ProcessInfo
        CreateProcessWithLogon StrPtr(lpUsername), StrPtr(lpDomain), StrPtr(lpPassword), LOGON_WITH_PROFILE, StrPtr(lpApplicationName), StrPtr(lpCommandLine), ePriorityClass, ByVal 0&, StrPtr(lpCurrentDirectory), StartInfo, ProcessInfo
        'CloseHandle ProcessInfo.hThread 'close the handle to the main thread, since we don't use it
    End If
   
    If bSync Then
        WaitForSingleObject ProcessInfo.hProcess, lTimeOut * lMultiplier
        If bKillAfterTimeOut Then TerminateProcess ProcessInfo.hProcess, 0
    End If
    ret = GetExitCodeProcess(ProcessInfo.hProcess, lExitCode)
    CloseHandle ProcessInfo.hThread
    CloseHandle ProcessInfo.hProcess 'close the handle to the process, since we don't use it
End Sub

sub main
      call execute("c:\windows\system32\notepad.exe","test1","mymachine","123456789",True,,,,SW_MAXIMIZE)
end sub

Any ideas?
Comment
Watch Question
This problem has been solved!
Unlock 1 Answer and 4 Comments.
See Answer
Why Experts Exchange?

Experts Exchange always has the answer, or at the least points me in the correct direction! It is like having another employee that is extremely experienced.

Jim Murphy
Programmer at Smart IT Solutions

When asked, what has been your best career decision?

Deciding to stick with EE.

Mohamed Asif
Technical Department Head

Being involved with EE helped me to grow personally and professionally.

Carl Webster
CTP, Sr Infrastructure Consultant
Ask ANY Question

Connect with Certified Experts to gain insight and support on specific technology challenges including:

  • Troubleshooting
  • Research
  • Professional Opinions
Did You Know?

We've partnered with two important charities to provide clean water and computer science education to those who need it most. READ MORE