The following code has been tested on Windows 2003 SP2. The calling user account must have 'Assign Primary Token' and 'Increase Quota' permissions to properly execute CreateProcessAsUser; see MS KB285879.
Public Function RunProc(ByVal CMD As String, ByVal ARG As String) As String
Dim er As Int16
Dim exitCode As System.UInt32 = Convert.ToUInt32(123)
Dim saThreadAttributes As SECURITY_ATTRIBUTES = New SECURITY_ATTRIBUTES
saThreadAttributes.nLength = Marshal.SizeOf(saThreadAttributes)
Dim impToken As System.IntPtr = IntPtr.Zero
Dim priToken As System.IntPtr = IntPtr.Zero
If LogonUser("DomainUser", "Domain", "Passwd", LogonType.LOGON32_LOGON_INTERACTIVE, _
LogonProvider.LOGON32_PROVIDER_DEFAULT, impToken) Then
If DuplicateTokenEx(impToken, &H2000000, Nothing, SecurityImpersonationLevel.SecurityDelegation, TOKEN_TYPE.TokenPrimary, priToken) Then
Dim pi As PROCESS_INFORMATION = New PROCESS_INFORMATION
Dim si As STARTUPINFO = New STARTUPINFO
si.cb = Marshal.SizeOf(si)
si.lpDesktop = IntPtr.Zero
Dim saProcessAttributes As SECURITY_ATTRIBUTES = New SECURITY_ATTRIBUTES
saProcessAttributes.nLength = Marshal.SizeOf(saProcessAttributes)
If Not CreateProcessAsUser(priToken, CMD, CMD & " " & ARG, saProcessAttributes, _
saThreadAttributes, False, 0, IntPtr.Zero, "c:\", si, pi) Then
er = Marshal.GetLastWin32Error
RunProc = ("err runas " & er)
Else
WaitForSingleObject(pi.hProcess, Infinite)
GetExitCodeProcess(pi.hProcess, exitCode)
End If
CloseHandle(priToken)
CloseHandle(impToken)
CloseHandle(pi.hProcess)
CloseHandle(pi.hThread)
End If
End If
End Function