Link to home
Start Free TrialLog in
Avatar of AsafG
AsafG

asked on

CreateProcessAsUser is ignoring wshowwindow's value

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?
Avatar of DarkoLord
DarkoLord
Flag of Slovenia image

Hi, the code below works for me (both in 2000 and XP)... Maybe the problem is that you're passing eStyle parameter as enSW structure instead of integer/long?

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 ABOVE_NORMAL_PRIORITY_CLASS = &H8000&
Private Const BELOW_NORMAL_PRIORITY_CLASS = &H4000&
Private Const HIGH_PRIORITY_CLASS = &H80&
Private Const IDLE_PRIORITY_CLASS = &H40&
Private Const NORMAL_PRIORITY_CLASS = &H20&
Private Const REALTIME_PRIORITY_CLASS = &H100&
Private Const STARTF_USESHOWWINDOW = &H1
Private Const SW_MAXIMIZE = 3

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 Long
    lpDesktop As Long
    lpTitle As Long
    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 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 Sub cmd_Ok_Click()
    Dim lpUsername As String, lpDomain As String, lpPassword As String, lpApplicationName As String
    Dim lpCommandLine As String, lpCurrentDirectory As String
    Dim StartInfo As STARTUPINFO, ProcessInfo As PROCESS_INFORMATION
   
    lpUsername = "username" '"OtherUser"
    lpDomain = vbNullString
    lpPassword = "password"
    lpApplicationName = "C:\WINDOWS\NOTEPAD.EXE"
    lpCommandLine = vbNullString 'use the same as lpApplicationName
    lpCurrentDirectory = vbNullString 'use standard directory
    StartInfo.cb = LenB(StartInfo) 'initialize structure
    StartInfo.dwFlags = STARTF_USESHOWWINDOW
    StartInfo.wShowWindow = SW_MAXIMIZE
    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
    CloseHandle ProcessInfo.hThread 'close the handle to the main thread, since we don't use it
    CloseHandle ProcessInfo.hProcess 'close the handle to the process, since we don't use it
    'note that closing the handles of the main thread and the process do not terminate the process
    'unload this application
    Unload Me

End Sub



Darko
Avatar of AsafG
AsafG

ASKER

Hi Darko.
I tryed your code as well (on more than 1 macines) and unfortunately it seems to have the same problem.
Do u have an idea?
Asaf
Avatar of AsafG

ASKER

Found the solution:

Private Declare Function GetProcessMemoryInfo Lib "PSAPI.DLL" (ByVal hProcess As Long, ppsmemCounters As PROCESS_MEMORY_COUNTERS, ByVal cb As Long) As Long
Private Declare Function Process32First Lib "kernel32" (ByVal hSnapshot As Long, lppe As PROCESSENTRY32) As Long
Private Declare Function Process32Next Lib "kernel32" (ByVal hSnapshot As Long, lppe As PROCESSENTRY32) As Long
Private Declare Function CloseHandle Lib "kernel32.dll" (ByVal Handle As Long) As Long
Private Declare Function OpenProcess Lib "kernel32.dll" (ByVal dwDesiredAccessas As Long, ByVal bInheritHandle As Long, ByVal dwProcId As Long) As Long
Private Declare Function EnumProcesses Lib "PSAPI.DLL" (ByRef lpidProcess As Long, ByVal cb As Long, ByRef cbNeeded As Long) As Long
Private Declare Function GetModuleFileNameExA Lib "PSAPI.DLL" (ByVal hProcess As Long, ByVal hModule As Long, ByVal ModuleName As String, ByVal nSize As Long) As Long
Private Declare Function EnumProcessModules Lib "PSAPI.DLL" (ByVal hProcess As Long, ByRef lphModule As Long, ByVal cb As Long, ByRef cbNeeded As Long) As Long
Private Declare Function CreateToolhelp32Snapshot Lib "kernel32" (ByVal dwFlags As Long, ByVal th32ProcessID As Long) As Long
Private Declare Function GetVersionExA Lib "kernel32" (lpVersionInformation As OSVERSIONINFO) As Integer
Private Declare Function SetTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long
Private Declare Function KillTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long) As Long
Private Declare Sub GlobalMemoryStatus Lib "kernel32" (lpBuffer As MEMORYSTATUS)
Private Declare Function TerminateProcess Lib "kernel32" (ByVal hProcess As Long, ByVal uExitCode As Long) As Long
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 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 Function SleepEx Lib "kernel32.dll" (ByVal dwMilliseconds As Long, ByVal bAlertable As Long) As Long
Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
Private Declare Function GetExitCodeProcess Lib "kernel32" (ByVal hProcess As Long, lpExitCode As Long) As Long
''''
Private Declare Function GetLastError Lib "kernel32" () As Long
Private Declare Sub SetLastError Lib "kernel32" (ByVal dwErrCode As Long)
Private Declare Function FormatMessage Lib "kernel32" Alias "FormatMessageA" (ByVal dwFlags As Long, lpSource As Any, ByVal dwMessageId As Long, ByVal dwLanguageId As Long, ByVal lpBuffer As String, ByVal nSize As Long, Arguments As Long) As Long
Const FORMAT_MESSAGE_ALLOCATE_BUFFER = &H100
Const FORMAT_MESSAGE_FROM_SYSTEM = &H1000
Const LANG_NEUTRAL = &H0
Const SUBLANG_DEFAULT = &H1
Const ERROR_BAD_USERNAME = 2202&
Public Const INFINITE = &HFFFF      '  Infinite timeout

''''
Private Const PROCESS_QUERY_INFORMATION = 1024
Private Const PROCESS_VM_READ = 16
Private Const MAX_PATH = 260
Private Const STANDARD_RIGHTS_REQUIRED = &HF0000
Private Const SYNCHRONIZE = &H100000
Private Const PROCESS_ALL_ACCESS = &H1F0FFF
Private Const TH32CS_SNAPPROCESS = &H2&
Private Const hNull = 0
Private Const WIN95_System_Found = 1
Private Const WINNT_System_Found = 2
Private Const Default_Log_Size = 10000000
Private Const Default_Log_Days = 0
Private Const SPECIFIC_RIGHTS_ALL = &HFFFF
Private Const STANDARD_RIGHTS_ALL = &H1F0000

Private Const LOGON_WITH_PROFILE = &H1&
Private Const LOGON_NETCREDENTIALS_ONLY = &H2&
Private Const STARTF_USESHOWWINDOW = &H1

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&

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 Long
    lpDesktop As Long
    lpTitle As Long
    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 MEMORYSTATUS
    dwLength As Long
    dwMemoryLoad As Long
    dwTotalPhys As Long
    dwAvailPhys As Long
    dwTotalPageFile As Long
    dwAvailPageFile As Long
    dwTotalVirtual As Long
    dwAvailVirtual As Long
End Type


Private Type PROCESS_MEMORY_COUNTERS
    cb As Long
    PageFaultCount As Long
    PeakWorkingSetSize As Long
    WorkingSetSize As Long
    QuotaPeakPagedPoolUsage As Long
    QuotaPagedPoolUsage As Long
    QuotaPeakNonPagedPoolUsage As Long
    QuotaNonPagedPoolUsage As Long
    PagefileUsage As Long
    PeakPagefileUsage As Long
End Type


Private Type PROCESSENTRY32
    dwSize As Long
    cntUsage As Long
    th32ProcessID As Long ' This process
    th32DefaultHeapID As Long
    th32ModuleID As Long ' Associated exe
    cntThreads As Long
    th32ParentProcessID As Long ' This process's parent process
    pcPriClassBase As Long ' Base priority of process threads
    dwFlags As Long
    szExeFile As String * 260 ' MAX_PATH
    End Type


Private Type OSVERSIONINFO
    dwOSVersionInfoSize As Long
    dwMajorVersion As Long
    dwMinorVersion As Long
    dwBuildNumber As Long
    dwPlatformId As Long '1 = Windows 95.
    '2 = Windows NT
    szCSDVersion As String * 128
End Type

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

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



Public Function execute(sCMDLine As String, _
                        Optional eSize As enSW = SW_NORMAL, _
                        Optional sUserName As String, _
                        Optional sDomain As String, _
                        Optional sPassword As String, _
                        Optional bLoadProfile As Boolean = True, _
                        Optional bWaitB4Return As Boolean = False, _
                        Optional lTimeOut As Long = 60, _
                        Optional bTerminateWhenTimeoutExceeds As Boolean, _
                        Optional lProcID As Long, _
                        Optional sCurDir As String, _
                        Optional lExitCode As Long) As Long

    Dim sApplicationName As String
    Dim sCurrentDirectory As String
    Dim tStartInfo As STARTUPINFO
    Dim tProcessInfo As PROCESS_INFORMATION
    Dim sNullSTR As String
    Dim lLogonType As Long
    If sCurDir = "" Then sCurrentDirectory = CurDir Else sCurrentDirectory = sCurDir
    sNullSTR = vbNullString
    tStartInfo.cb = LenB(tStartInfo)
    tStartInfo.dwFlags = STARTF_USESHOWWINDOW
    tStartInfo.wShowWindow = eSize
    If bLoadProfile = True Then lLogonType = LOGON_WITH_PROFILE Else lLogonType = LOGON_NETCREDENTIALS_ONLY

    If sUserName = "" Then
            Dim tSec1 As SECURITY_ATTRIBUTES
            Dim tSec2 As SECURITY_ATTRIBUTES
            tSec1.nLength = Len(tSec1)
            tSec2.nLength = Len(tSec2)
            CreateProcess vbNullString, sCMDLine, tSec1, tSec2, False, NORMAL_PRIORITY_CLASS, 0&, sNullSTR, tStartInfo, tProcessInfo
    Else
        'CreateProcessWithLogon StrPtr(sUserName), StrPtr(sDomain), StrPtr(sPassword), LOGON_WITH_PROFILE, StrPtr(sApplicationName), StrPtr(lpCommandLine), CREATE_DEFAULT_ERROR_MODE Or CREATE_NEW_CONSOLE Or CREATE_NEW_PROCESS_GROUP, ByVal 0&, StrPtr(lpCurrentDirectory), StartInfo, ProcessInfo
        CreateProcessWithLogon StrPtr(sUserName), StrPtr(sDomain), StrPtr(sPassword), lLogonType, StrPtr(sNullSTR), StrPtr(sCMDLine), CREATE_DEFAULT_ERROR_MODE Or CREATE_NEW_CONSOLE Or CREATE_NEW_PROCESS_GROUP, ByVal 0&, StrPtr(sCurrentDirectory), tStartInfo, tProcessInfo
'    Dim Buffer As String
'    Buffer = Space(200)
'    FormatMessage FORMAT_MESSAGE_FROM_SYSTEM, ByVal 0&, GetLastError, LANG_NEUTRAL, Buffer, 200, ByVal 0&
'    MsgBox Buffer

    End If
    If bWaitB4Return Then
        WaitForSingleObject tProcessInfo.hProcess, lTimeOut * 1000
        If bTerminateWhenTimeoutExceeds Then TerminateProcess tProcessInfo.hProcess, 0
    End If
    lProcID = tProcessInfo.dwProcessId
    If lProcID = 0 Then execute = 1
    Call GetExitCodeProcess(tProcessInfo.hProcess, lExitCode)
    CloseHandle tProcessInfo.hThread
    CloseHandle tProcessInfo.hProcess
End Function
ASKER CERTIFIED SOLUTION
Avatar of ee_ai_construct
ee_ai_construct
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial