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?