dentab
asked on
Terminating a shelled program (opened via CreateProcessWithLogonW API)
I have pinched bits of code from various places to make this code work...
Simply, this class allows me to:
-launch an application with a specified priority
-monitor when it closes
-manually terminate it
I have now added code to allow a process to be launched as another user, this used the CreateProcessWithLogonW API, instead of the CreateProcessA procedure. The problem is only if I call my Terminate method, it does not work for applications created by my Initialize as method.
I am sure I am just overlooking something obvious, can anyone help please?
Class Code Below:
Simply, this class allows me to:
-launch an application with a specified priority
-monitor when it closes
-manually terminate it
I have now added code to allow a process to be launched as another user, this used the CreateProcessWithLogonW API, instead of the CreateProcessA procedure. The problem is only if I call my Terminate method, it does not work for applications created by my Initialize as method.
I am sure I am just overlooking something obvious, can anyone help please?
Class Code Below:
Option Explicit
'*****************************
'* API Declarations *
'*****************************
Private Declare Function GetExitCodeProcess Lib "kernel32" (ByVal hProcess As Long, lpExitCode As Long) As Long
Private Declare Function CreateProcessA Lib "kernel32" (ByVal lpApplicationName As String, ByVal lpCommandLine As String, lpProcessAttributes As Any, lpThreadAttributes As Any, ByVal bInheritHandles As Long, ByVal dwCreationFlags As Long, lpEnvironment As Any, ByVal lpCurrentDriectory As String, lpStartupInfo As STARTUPINFO, lpProcessInformation As PROCESS_INFORMATION) As Long
' CreateProcessWithLogonW API is available only on Windows 2000 and later.
Private Declare Function CreateProcessWithLogonW Lib "advapi32.dll" (ByVal lpUsername As String, ByVal lpDomain As String, ByVal lpPassword As String, ByVal dwLogonFlags As Long, ByVal lpApplicationName As Long, ByVal lpCommandLine As String, ByVal dwCreationFlags As Long, ByVal lpEnvironment As Long, ByVal lpCurrentDirectory As String, ByRef lpStartupInfo As STARTUPINFO, ByRef lpProcessInformation As PROCESS_INFORMATION) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function GetPriorityClass Lib "kernel32" (ByVal hProcess 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 ProcessFirst Lib "kernel32" Alias "Process32First" (ByVal hSnapShot As Long, uProcess As PROCESSENTRY32) As Long
Private Declare Function ProcessNext Lib "kernel32" Alias "Process32Next" (ByVal hSnapShot As Long, uProcess As PROCESSENTRY32) As Long
Private Declare Function CreateToolhelpSnapshot Lib "kernel32" Alias "CreateToolhelp32Snapshot" (ByVal lFlags As Long, lProcessID As Long) As Long
Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Private Declare Function WaitForInputIdle Lib "user32" (ByVal hProcess As Long, ByVal dwMilliseconds As Long) As Long
Private Declare Function ResumeThread Lib "kernel32" (ByVal hThread As Long) As Long
' Version Checking APIs
Private Declare Function GetVersionExA Lib "kernel32.dll" (lpVersionInformation As OSVERSIONINFO) As Integer
'*****************************
'* Structures *
'*****************************
Private Type OSVERSIONINFO
dwOSVersionInfoSize As Long
dwMajorVersion As Long
dwMinorVersion As Long
dwBuildNumber As Long
dwPlatformId As Long
szCSDVersion As String * 128
End Type
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 Long
hStdInput As Long
hStdOutput As Long
hStdError As Long
End Type
Private Type PROCESSENTRY32
dwSize As Long
cntUsage As Long
th32ProcessID As Long
th32DefaultHeapID As Long
th32ModuleID As Long
cntThreads As Long
th32ParentProcessID As Long
pcPriClassBase As Long
dwFlags As Long
szexeFile As String * 6400
End Type
'*****************************
'* Constants *
'*****************************
Private Const INFINITE As Long = &HFFFF
Private Const TH32CS_SNAPPROCESS As Long = 2&
Private Const INVALID_HANDLE_VALUE As Long = -1
Private Const WINAPI_TRUE = 1
Private Const PROCESS_TERMINATE = 1
Private Const CREATE_SUSPENDED As Long = &H4
'Version info
Private Const VER_PLATFORM_WIN32_NT = &H2
'Logon Specific
Private Const CREATE_DEFAULT_ERROR_MODE = &H4000000
Private Const LOGON_WITH_PROFILE = &H1
Private Const LOGON_NETCREDENTIALS_ONLY = &H2
Private Const LOGON32_LOGON_INTERACTIVE = 2
Private Const LOGON32_PROVIDER_DEFAULT = 0
'************************************
'* Enumarated Values *
'************************************
Public Enum PROCESS_PRIORITY
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
Public Enum APPLICATION_WINDOWSTATE
SW_HIDE = 0 'Hides the window and activates next.
' Activates and displays a window. If the window is minimized or maximized,
' the system restores it to its original size and position. An application should
' specify this flag when displaying the window for the first time.
SW_SHOWNORMAL = 1
SW_SHOWMINIMIZED = 2 ' Activates the window and displays it as a minimized window.
SW_SHOWMAXIMIZED = 3 ' Activates the window and displays it as a maximized window.
SW_MAXIMIZE = 3 ' Maximizes the specified window - same as SW_SHOWMAXIMIZED.
SW_SHOWNOACTIVATE = 4 ' Same as SW_SHOWNORMAL without activating the window.
SW_SHOW = 5 ' Activates the window and displays it in its current size and position.
SW_MINIMIZE = 6 ' Minimizes the specified window and activates the next.
SW_SHOWMINNOACTIVE = 7 ' Same as SW_SHOWMINIMIZED without activating the window.
SW_SHOWNA = 8 ' Same as SW_SHOW without activating the window.
' Activates and displays the window. If the window is minimized or maximized,
' the system restores it to its original size and position.
' An application should specify this flag when restoring a minimized window.
SW_RESTORE = 9
SW_SHOWDEFAULT = 10 ' Sets the show state based on the SW_ value specified in the STARTUPINFO
SW_FORCEMINIMIZE = 11 '2000/XP+ Minimizes window, even for non-responsive thread.
End Enum
Private Const STARTF_USESHOWWINDOW = &H1 '0x01 If this value is not specified, the wShowWindow member is ignored.
Private Const STARTF_USESIZE = &H2 '0x02 If this value is not specified, the dwXSize and dwYSize members are ignored.
Private Const STARTF_USEPOSITION = &H4 '0x04 If this value is not specified, the dwX and dwY members are ignored.
Private Const STARTF_USECOUNTCHARS = &H8 '0x08 If this value is not specified, the dwXCountChars and dwYCountChars members are ignored.
Private Const STARTF_USEFILLATTRIBUTE = &H10 '0x10 If this value is not specified, the dwFillAttribute member is ignored.
Private Const STARTF_RUNFULLSCREEN = &H20 '0x20 Indicates that the process should be run in full-screen mode, rather than in windowed mode.
Private Const STARTF_FORCEONFEEDBACK = &H40 '0x40 Indicates that the cursor is in feedback mode for two seconds after CreateProcess is called.
Private Const STARTF_FORCEOFFFEEDBACK = &H80 '0x80 Indicates that the feedback cursor is forced off while the process is starting. The normal cursor is displayed.
Private Const STARTF_USESTDHANDLES = &H100 '0x100 Sets the standard input, standard output, and standard error handles for the process to the handles specified in the hStdInput, hStdOutput, and hStdError members of the STARTUPINFO structure.
'******************************
'* Object State variables . . .
'******************************
Private Type PROCESS_TREE
ProcessId As Long
ParentProcessId As Long
End Type
Private Const PROCESS_QUERY_INFORMATION = &H400
Private Const STATUS_PENDING = &H103&
Private mApplication As String
Private mArguments As String
Private mProcessInformation As PROCESS_INFORMATION
Private mSuspended As Boolean
Public Sub Initialise(Optional ByVal ePriority As PROCESS_PRIORITY = PROCESS_PRIORITY.NORMAL_PRIORITY_CLASS, Optional ByVal Suspended As Boolean = False, Optional ByVal WindowState As APPLICATION_WINDOWSTATE = APPLICATION_WINDOWSTATE.SW_SHOWDEFAULT, Optional ByVal Synchronous As Boolean = False)
On Error GoTo ERR_Initialise
Dim lRet As Long
Dim lCreationFlags As Long
Dim uStartUpInfo As STARTUPINFO
Dim uProcessInformation As PROCESS_INFORMATION
'*******************************************************
'* Check to see if Application has been specified . . .
'*******************************************************
If LenB(mApplication) = 0 Then
Err.Raise vbObjectError + 512, , "Application Not Specified"
End If
'***************************************************
'* Check to see if Application actually exists . . .
'***************************************************
If LenB(Dir(mApplication)) = 0 Then
Err.Raise vbObjectError + 512, , "Application '" & mApplication & "' Does Not Exist"
End If
'****************************************
'* Deal with suspended applications . . .
'****************************************
If Suspended Then
lCreationFlags = CREATE_SUSPENDED Or ePriority
mSuspended = True
Else
lCreationFlags = ePriority
mSuspended = False
End If
'**************************
'* Start the Process . . .
'**************************
uStartUpInfo.dwFlags = STARTF_USESHOWWINDOW
uStartUpInfo.wShowWindow = CInt(WindowState)
uStartUpInfo.cb = Len(uStartUpInfo)
lRet = CreateProcessA(vbNullString, mApplication & " " & mArguments, ByVal 0&, ByVal 0&, 1&, lCreationFlags, ByVal 0&, vbNullString, uStartUpInfo, uProcessInformation)
If lRet <> 0 Then
If Synchronous Then
'*****************************************
'* Wait until application terminates . . .
'*****************************************
Call WaitForSingleObject(uProcessInformation.hProcess, INFINITE)
'******************************
'* Release stored handles . . .
'******************************
Call CloseHandle(mProcessInformation.hThread)
Call CloseHandle(mProcessInformation.hProcess)
Else
'************************************
'* Remember the process details . . .
'************************************
mProcessInformation = uProcessInformation
End If
Else
Err.Raise vbObjectError + 512, , "Create Process Failed"
End If
Exit Sub
ERR_Initialise:
Err.Raise Err.Number, "ProcessManager.CShell.Initialise", "Unable to Start Application '" & mApplication & " " & mArguments & _
"' Because '" & Err.Description & "'"
End Sub
Public Sub InitialiseAS(ByVal winDomain As String, ByVal winUser As String, ByVal winPassword As String, Optional ByVal ePriority As PROCESS_PRIORITY = PROCESS_PRIORITY.NORMAL_PRIORITY_CLASS, Optional ByVal Suspended As Boolean = False, Optional ByVal WindowState As APPLICATION_WINDOWSTATE = APPLICATION_WINDOWSTATE.SW_SHOWDEFAULT, Optional ByVal Synchronous As Boolean = False)
On Error GoTo ERR_Initialise
Dim lRet As Long
Dim lCreationFlags As Long
Dim uStartUpInfo As STARTUPINFO
Dim uProcessInformation As PROCESS_INFORMATION
'*******************************************************
'* Check to see if Application has been specified . . .
'*******************************************************
If LenB(mApplication) = 0 Then
Err.Raise vbObjectError + 512, , "Application Not Specified"
End If
'***************************************************
'* Check to see if Application actually exists . . .
'***************************************************
If LenB(Dir(mApplication)) = 0 Then
Err.Raise vbObjectError + 512, , "Application '" & mApplication & "' Does Not Exist"
End If
'****************************************
'* Deal with suspended applications . . .
'****************************************
If Suspended Then
lCreationFlags = CREATE_SUSPENDED Or ePriority
mSuspended = True
Else
lCreationFlags = ePriority
mSuspended = False
End If
'**************************
'* Start the Process . . .
'**************************
uStartUpInfo.dwFlags = STARTF_USESHOWWINDOW
uStartUpInfo.wShowWindow = CInt(WindowState)
uStartUpInfo.cb = Len(uStartUpInfo)
' lRet = CreateProcessA(vbNullString, mApplication & " " & mArguments, ByVal 0&, ByVal 0&, 1&, lCreationFlags, ByVal 0&, vbNullString, uStartUpInfo, uProcessInformation)
lRet = CreateProcessWithLogonW(StrConv(winUser & vbNullChar, vbUnicode), StrConv(winDomain & vbNullChar, vbUnicode), StrConv(winPassword & vbNullChar, vbUnicode), _
LOGON_WITH_PROFILE, 0&, StrConv(mApplication & " " & mArguments & vbNullChar, vbUnicode), _
lCreationFlags, 0&, vbNullString, uStartUpInfo, uProcessInformation)
If lRet <> 0 Then
If Synchronous Then
'*****************************************
'* Wait until application terminates . . .
'*****************************************
Call WaitForSingleObject(uProcessInformation.hProcess, INFINITE)
'******************************
'* Release stored handles . . .
'******************************
Call CloseHandle(mProcessInformation.hThread)
Call CloseHandle(mProcessInformation.hProcess)
Else
'************************************
'* Remember the process details . . .
'************************************
mProcessInformation = uProcessInformation
End If
Else
Err.Raise vbObjectError + 512, , "Create Process Failed"
End If
Exit Sub
ERR_Initialise:
Err.Raise Err.Number, "ProcessManager.CShell.Initialise", "Unable to Start Application '" & mApplication & " " & mArguments & _
"' Because '" & Err.Description & "'"
End Sub
Public Sub Terminate()
On Error GoTo ERR_Terminate
Dim ProcessTree() As PROCESS_TREE
If Not mProcessInformation.dwProcessId = 0 Then
'*************************
'* Kill off the kids . . .
'*************************
ProcessTree = GetProcessList()
KillProcessTree ProcessTree, mProcessInformation.dwProcessId
'***********************************
'* Kill initial (root) process . . .
'***********************************
KillProcess mProcessInformation.dwProcessId
End If
Exit Sub
ERR_Terminate:
Err.Raise Err.Number, "ProcessManager.CShell.Terminate", "Unable To Terminate Application '" & mApplication & "' Because '" & Err.Description & "'"
End Sub
Public Function IsRunning() As Boolean
Dim exitCode As Long
On Error Resume Next
Call GetExitCodeProcess(mProcessInformation.hProcess, exitCode)
If Err Or exitCode = STATUS_PENDING Then
IsRunning = True
Else
IsRunning = False
End If
Err.Clear
On Error GoTo 0
End Function
Public Sub Release()
On Error GoTo ERR_Release
'******************************************************
'* Ensure that the thread is currently suspended . . .
'******************************************************
If mSuspended Then
Call ResumeThread(mProcessInformation.hThread)
mSuspended = False
End If
Exit Sub
ERR_Release:
Err.Raise vbObjectError + 512, "ProcessManager.CShell.Release", "Unable To Release Thread Suspension Because '" & Err.Description & "'"
End Sub
Private Sub KillProcessTree(ProcessTree() As PROCESS_TREE, ParentProcessId As Long)
Dim lCtr As Long
'*********************************************
'* Check every process for it's children . . .
'*********************************************
For lCtr = 0 To UBound(ProcessTree)
If ProcessTree(lCtr).ParentProcessId = ParentProcessId Then
KillProcessTree ProcessTree, ProcessTree(lCtr).ProcessId
KillProcess ProcessTree(lCtr).ProcessId
End If
Next
End Sub
Private Function GetProcessList() As PROCESS_TREE()
On Error GoTo ERR_GetProcessTree
Dim hSnapShot As Long
Dim hProcess As Long
Dim uProcessEntry As PROCESSENTRY32
Dim lSuccess As Long
Dim ProcessTree() As PROCESS_TREE
Dim lCtr As Long
'************************************************************
'* Get a snapshot of all of the processes in the system . . .
'************************************************************
hSnapShot = CreateToolhelpSnapshot(TH32CS_SNAPPROCESS, 0&)
'***********************************************
'* If we don't have a snapshot then finish . . .
'***********************************************
If hSnapShot = INVALID_HANDLE_VALUE Then
Err.Raise vbObjectError + 512, , "Unable To Get Process Snapshot"
Else
'*********************************
'* Get first process in list . . .
'*********************************
uProcessEntry.dwSize = Len(uProcessEntry)
lSuccess = ProcessFirst(hSnapShot, uProcessEntry)
If lSuccess = WINAPI_TRUE Then
lCtr = 0
'**********************************
'* Loop through all processes . . .
'**********************************
Do Until lSuccess <> WINAPI_TRUE
ReDim Preserve ProcessTree(lCtr)
With ProcessTree(lCtr)
.ParentProcessId = uProcessEntry.th32ParentProcessID
.ProcessId = uProcessEntry.th32ProcessID
End With
lCtr = lCtr + 1
lSuccess = ProcessNext(hSnapShot, uProcessEntry)
Loop
Else
Err.Raise vbObjectError + 512, , "Unable To Get First Process In Snapshot"
End If
End If
'********************************
'* Release handle resources . . .
'********************************
CloseHandle (hSnapShot)
GetProcessList = ProcessTree
Exit Function
ERR_GetProcessTree:
CloseHandle (hSnapShot)
Err.Raise Err.Number, Err.Source, Err.Description
End Function
Private Sub KillProcess(ProcessId As Long)
On Error GoTo ERR_KillProcess
Dim hProcess As Long
Dim lExitCode As Long
'*************************************************
'* Kill the process, and release the handle . . .
'*************************************************
hProcess = OpenProcess(PROCESS_TERMINATE, False, ProcessId)
Call TerminateProcess(hProcess, lExitCode)
Call CloseHandle(hProcess)
Exit Sub
ERR_KillProcess:
Call CloseHandle(hProcess)
End Sub
Property Let Application(sApplication As String)
mApplication = sApplication
End Property
Property Get Application() As String
Application = mApplication
End Property
Property Let Arguments(sArguments As String)
mArguments = sArguments
End Property
Property Get Arguments() As String
Arguments = mArguments
End Property
For that, you need the access permissions to do so. If the account you are using is more privileged, that will fail. The only solution then would be to launch a little helper in the same user context with 'CreateProcessWithLogonW() ' that in turn terminates the app.
ASKER
That seems fair, but both accounts for testing were the same.
When you use the same accounts, that is supposed to work. When 'TerminateProcess()' fails, what does 'GetLastError()' tell you?
ASKER
6 - whatever that means.
ASKER
Thanks to your suggestion, I found a simular problem here
https://www.experts-exchange.com/questions/20675885/TerminateProcess-not-working-with-verified-processID.html
https://www.experts-exchange.com/questions/20675885/TerminateProcess-not-working-with-verified-processID.html
ASKER
Further research (thanks to seeing last problem) I found this: http://www.tech-archive.net/Archive/VB/microsoft.public.vb.winapi.networks/2004-09/0008.html
Which works
I am sure between these two resources I will get the problem solved - all thanks to your GetLastError. I will of course accept your answer if this solves it.
FYI: in VB6 GetLastError() should be requested via the error object as err.LastDllError
Which works
I am sure between these two resources I will get the problem solved - all thanks to your GetLastError. I will of course accept your answer if this solves it.
FYI: in VB6 GetLastError() should be requested via the error object as err.LastDllError
The error actually is
//
// MessageId: ERROR_INVALID_HANDLE
//
// MessageText:
//
// The handle is invalid.
//
#define ERROR_INVALID_HANDLE 6L
so the error code of
hProcess = OpenProcess(PROCESS_TERMIN ATE, False, ProcessId)
would be interesting.
//
// MessageId: ERROR_INVALID_HANDLE
//
// MessageText:
//
// The handle is invalid.
//
#define ERROR_INVALID_HANDLE 6L
so the error code of
hProcess = OpenProcess(PROCESS_TERMIN
would be interesting.
ASKER
5...
isn't that access denied?
But it has admin priv??!!
isn't that access denied?
But it has admin priv??!!
'5' in fact is 'access denied'. Are you sure the account is the same and not a local vs. domain account?
ASKER
Right when I said accounts were the same, I meant permissions wize.
If the user is exactly the same it works. I have now tried as admin on limited user... still no joy.
I will have to examing that other code I found to see if it sheds any light
If the user is exactly the same it works. I have now tried as admin on limited user... still no joy.
I will have to examing that other code I found to see if it sheds any light
ASKER
This PC I am testing it on is not on a domain, both are local
You might want to give enabling the 'SeDebugPrivilege' a try, in C/C++ that would be
BOOL EnablePrivilege(PCSTR name)
{
TOKEN_PRIVILEGES priv = {1, {0, 0, SE_PRIVILEGE_ENABLED}};
LookupPrivilegeValue(0, name, &priv.Privileges[0].Luid);
HANDLE hToken;
OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken);
AdjustTokenPrivileges(hToken, FALSE, &priv, sizeof priv, 0, 0);
BOOL rv = GetLastError() == ERROR_SUCCESS;
CloseHandle(hToken);
return rv;
}
ASKER
Thanks, but one of the diferences I noticed in the other example is that the profile was not used on the RunAs...
I changed
lRet = CreateProcessWithLogonW(St rConv(winU ser & vbNullChar, vbUnicode), StrConv(winDomain & vbNullChar, vbUnicode), StrConv(winPassword & vbNullChar, vbUnicode), _
LOGON_WITH_PROFILE, 0&, StrConv(mApplication & " " & mArguments & vbNullChar, vbUnicode), _
lCreationFlags, 0&, vbNullString, uStartUpInfo, uProcessInformation)
to
lRet = CreateProcessWithLogonW(St rConv(winU ser & vbNullChar, vbUnicode), StrConv(winDomain & vbNullChar, vbUnicode), StrConv(winPassword & vbNullChar, vbUnicode), _
LOGON_NETCREDENTIALS_ONLY, 0&, StrConv(mApplication & " " & mArguments & vbNullChar, vbUnicode), _
lCreationFlags, 0&, vbNullString, uStartUpInfo, uProcessInformation)
And it works. It must be something to do with the profile!?
I changed
lRet = CreateProcessWithLogonW(St
LOGON_WITH_PROFILE, 0&, StrConv(mApplication & " " & mArguments & vbNullChar, vbUnicode), _
lCreationFlags, 0&, vbNullString, uStartUpInfo, uProcessInformation)
to
lRet = CreateProcessWithLogonW(St
LOGON_NETCREDENTIALS_ONLY,
lCreationFlags, 0&, vbNullString, uStartUpInfo, uProcessInformation)
And it works. It must be something to do with the profile!?
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
so let me get this right....
it creates a new logon with the same credentials as the caller (i.e. me)
but the new logon has the same permissions as the specified user?
it creates a new logon with the same credentials as the caller (i.e. me)
but the new logon has the same permissions as the specified user?
In general, I think that's what it boils down to. Yet I am still not sure in which way these tokens are different, since following my understanding of the logon process they should be interchangeable, yet they apparently aren't. Mybe Windows assigns a different desktop which is reflected in the token...
ASKER
Well your theory stands up to the evidence...
When I use LOGON_NETCREDENTIALS_ONLY there are two things...
one of them is that the user listed in TaskManager -> processes is me. What concerns me is if I mistype the password it seems to have no effect.
This question is getting more specific on its needs now, and you have more than earnt an A grade. I will close this soon and open a new question asking about the effects of LOGON_NETCREDENTIALS_ONLY and how to end a task created with LOGON_WITH_PROFILE.
Thank you, so far your help has been invaluable.
When I use LOGON_NETCREDENTIALS_ONLY there are two things...
one of them is that the user listed in TaskManager -> processes is me. What concerns me is if I mistype the password it seems to have no effect.
This question is getting more specific on its needs now, and you have more than earnt an A grade. I will close this soon and open a new question asking about the effects of LOGON_NETCREDENTIALS_ONLY and how to end a task created with LOGON_WITH_PROFILE.
Thank you, so far your help has been invaluable.
ASKER
I have enough information to investigate further, possibly generating new posts. I wont be able to do it today and so would like to get this question closed.
Thanks again.
Thanks again.
ASKER
CreateProcessWithLogonW
as opposed to one started using
CreateProcessA