RunWithLogon

Runs a program as a specified user.

Syntax:

RunWithLogon( program-name, params, directory, display mode, waitflag, username, domain, password, logon-flags)

 

Parameters:

(s) program-name: the name of the desired .EXE, .COM, .PIF, .BAT, .CMD file or a data file.

(s) params: optional parameters as required by the application.

(s) directory:  target directory (if applicable).

(i) display mode: @NORMAL, @ICON, @ZOOMED, @HIDDEN, @NOACTIVATE or 0 for the default mode.

(i) waitflag: @WAIT, @NOWAIT, @GETPROCID.

(s) username: specifies the name of the user account to log on to. Note: If you use the UPN format (user@DNS_domain_name), "domain" must be a blank string ("").

(s) domain: specifies the name of the domain or server whose account database contains the "username" account. Note: If this parameter is a blank string, "username" must be specified in UPN format.

(s) password: specifies the password for the "username" account.

(i) logon-flags: see below.

 

IMPORTANT: You cannot use RunWithLogon to circumvent the UAC elevation prompt, if UAC is on.

 

"logon-flags" one of the following values:

Value

Name

Meaning

0

Default

No logon-flag

1

LOGON_WITH_PROFILE

Log on, then load the user's profile. Loading the
profile can be time-consuming, so it is best to
use this value only if you must access the user's
profile information.

2

LOGON_NETCREDENTIALS_ONLY

Log on, but use the specified credentials on the
network only. This value can be used to create a
process that uses a different set of credentials
locally than it does remotely. This is useful in
inter-domain scenarios where there is no trust
relationship.

 

If a data file is specified instead of an executable file (i.e. EXE, COM, PIF, or BAT file), the function examines the extension of the data file, looks the extension up in the Windows registry to determine the owning application and starts the owning application, passing the data file name as a parameter. Applications that support this command or their setup programs will generally make the necessary modifications to the Windows registry to allow this function to perform successfully.

If the drive and path are not part of the program name, the current directory will be examined first, followed by the Windows and Windows System directories, and then the DOS path will be searched to find the desired executable file.

The @NOACTIVATE value causes the targeted application's window to be displayed in its most recent size and position but without making the application's window the active window when another top-level window is already active.

If the @WAIT parameter is used, the WIL program will suspend processing until the application is closed.

If the @GETPROCID parameter is used, a process-id will be returned that can be used with the function WinItemProcID.

Notes:

 

Windows Server 2003 and Windows XP:

There is a known issue on Windows XP SP1and 2003 where the RunWithLogon function ignoring the 'display mode' parameter. There is a windows service pack update/hotfix that addresses this problem. See Microsoft's knowledgebase article 818858, for details.

RunWithLogon accesses the 'program-name' in the security context of the target user. If the executable you want to launch is on a network and a network drive letter is specified in the path, the network drive letter is not available to the target user, as network drive letters are assigned on a per logon basis, this function will fail. If the executable you want to launch is on a network, use the UNC path.

Issues involved with RunWithLogon and wntRunAsUser when you change the credentials under which a program runs:

RunWithLogon and wntRunAsUser change the security context of the script. Security context is nothing more than a sandbox in which programs can all play. When you are logged on to a NT platform system, your session consists of multiple processes, with each process running one program. When you connect a drive letter to a network resource, that drive letter only exists within your security context. Other sessions [e.g. other terminal sessions on a terminal server system, services running under separate user accounts different from your own] have separate security contexts and thus they don't see your drive letter mappings as they exist in their own private sandboxes.

When you use wntRunAsUser() or RunWithLogon() to make use of impersonation in one form or another, you are causing either your own process [e.g. via wntRunAsuser()] or another process [e.g. via RunWithLogon()] to run in a separate security context.

In the case of using wntRunAsUser(), it is obvious that your existing process continues executing your script, but the first time you attempt to access a resource on via mapped drive you get a failure because that drive letter doesn't exist in your process' security context.

In the case of using RunWithLogon(), things are tougher because the process gets created in a new security context, but when it tries to execute the program that it was created to execute, that program is not accessible as the drive letter for the program path doesn't exist in that process' security context.

Note: If you are using NetWare servers, things are little worse off. When a process is created and it is in a new security context, or if an existing process begins impersonating another user, then the Novell Client's authentication information & mapped drive table changes when the security context changes. In a new security context, the Novell Client isn't authenticated to any servers and thus it has no drive letters mapped. It would be necessary for the program being executed to exist locally so that it could be accessed, and then the program would have to perform its own authentication to NDS/eDir before it could access any NetWare-related resources via either a UNC path or a mapped drive letter.

Under the Win9x platform family, there is no such thing as a security context. Or, to be more accurate, the entire system runs under one single security context so the problem associated with changing security contexts never becomes an issue.

UAC

You cannot use the RunWithLogon function by itself to circumvent the UAC elevation prompt when UAC is enabled.

When UAC is enabled and you attempt to use "RunWithLogon" to start a process that requires elevation, it will fail. The fact that the credentials passed to the function are for an administrator account does not matter. We know this seems counter-intuitive but this is just how UAC works.

UAC uses the “least privileges” rule. Which states that all users and software run with the least privileges possible at all times. Any time a user or software needs administrative privileges a consent prompt appears.

With UAC enabled, Windows Vista and newer either prompts for consent or for credentials for a valid administrator account before launching a program or task that requires a full administrator access token. This prompt ensures that no malicious application can silently install.

Background: The problem is that the RunWithLogon uses the underlying Windows API CreateProcessWithLogonw. When you are launching an application using RunWithLogon, behind the scenes CreateProcessWithLogonw is actually logging on that user. With UAC enabled, if that user is a member of the local Administrators group, that’s going to result in generating two different user tokens: a full administrator’s token and a filtered administrators token. However the application you launch will only use the filtered administrators token until you explicitly elevate.

So how so you explicitly elevate? Well normally you can use the ShellExecute function for creating a process that requires elevation. ShellExecute works because the shell sits in a much higher layer in the OS and consequently is able to take a dependency on elevation. Unfortunately there is no equivalent ShellExecuteWithLogon API!

Examples:
;Example 1
DirChange(DirWindows(0))
;check the platform
If WinVersion(5) >= "2-5-0" ;Win2000 or newer
;NOTE: For security reasons *always* assign the password
; to a variable and then use the variable in the RunWithLogon
; statement. NEVER hardcode the password into the
; RunWithLogon statement or else the password my be
; exposed if the RunWithLogon fails on some kind of error
; This is also a good idea with the userid and domain
; information
runas_user = "Administrator"
runas_pswd = "password"
runas_domain = "." ; validate using the local account database
RunWithLogon("NOTEPAD.EXE", "", "C:\", @NORMAL, @NOWAIT, runas_user, runas_domain, runas_pswd,1)
Else
Message("RunWithLogon","Is not designed for this platform.")
EndIf
Exit

 

;Example 2
;This script supports four subroutines
; :SETINFO - code to specify Admin userid and password and domain
; :BEFORE - code that executes in user mode BEFORE running as admin
; :ADMIN - code that runs as ADMIN
; :AFTER - code that executes in user mode AFTER running as admin
; Basically this script executes the BEFORE subroutine, then does a
; RUNWITHLOGON to run a copy of itself in admin mode. When the admin
; mode portion exits, then this script executes the AFTER subroutine.
; When the original script performs the RUNWITHLOGON it adds an
; additional parameter to the script's command line (if any), which
; is the string URADMIN, to let the admin script know that it is
; already in admin mode so that it can do that portion of the code.
; The top section of this example can generally be used as-is. The
; intent is that all the changes required can be done in the four
; Gosub's at the bottom.
; This picks up the entire passed parameter line to see if the URADMIN
; parameter exits
moiparams=IntControl(1006,0,0,0,0)
; Check passed parameters for URADMIN string
If StrIndexNC(moiparams,"URADMIN",0,@FWDSCAN) == 0
; URDAMIN NOT FOUND. Not running as Admin.
; check to see if doing this is supported
If WinVersion(5) >= "2-5-0" ;Win2000 or newer. Function is supported
; RunWithLogon supported.
; GOSUB BEFORE code
GoSub BEFORE
; Set up to RUN a copy of this script with ADMIN privileges specified above
GoSub SETINFO
moi=WinExename("") ;Get current script name
moiparams=StrCat(moiparams, " URADMIN") ;Add URADMIN to parameter string
RunWithLogon(moi, moiparams, "", @NORMAL, @WAIT, runas_user, runas_domain, runas_pswd,0)
; GOSUB the AFTER code here
GoSub AFTER
;Quit. Script is complete
; Drop out of if/endif to exit statement
Else ; RUNWITHLOGON not supported on this platform
; Provide error message and exit
Message("RunWithLogon","Is not designed for this platform.")
; Drop out of if/endif to exit statement
EndIf
Else
; Already launched as admin
param0 = param0 -1 ; Remove the URADMIN param from further consideration
;Do the ADMIN code
GoSub ADMIN
; Drop out of if/endif to exit statement
EndIf
Exit
;**************************************************************************
;**************************************************************************
:SETINFO
;-------------------------------
; This subroutine is used to setup the account information required to
; Run as the Administrator. Userid, password, and domain are defined here
;-------------------------------
;NOTE: For security reasons *always* assign the password
; to a variable and then use the variable in the RunWithLogon
; statement. NEVER hardcode the password into the
; RunWithLogon statement or else the password my be
; exposed if the RunWithLogon fails on some kind of error
; This is also a good idea with the userid and domain
; information
runas_user = "Administrator"
runas_pswd = "secretpassword"
runas_domain = ComputerNameGet(0); validate using the local account database
Return
;--------------------------------------------------------------------------
:BEFORE
;-------------------------------
; Running in user mode, BEFORE running the admin mode portion of the script
;-------------------------------
Message("Debug","Executing BEFORE section of script")
Return
;--------------------------------------------------------------------------
:ADMIN
;-------------------------------
; Running in ADMIN mode.
;-------------------------------
Message("Debug","Running ADMIN section of script")
Return
;--------------------------------------------------------------------------
:AFTER
;-------------------------------
; Running in user mode, AFTER running the admin mode portion of the script
;-------------------------------
Message("Debug","Executing AFTER section of script")
Return
See Also:

RunShell, Run, RunHide, RunIcon, RunZoomWait, ShellExecute WinClose, WinExeName, WinWaitClose, WinZoom, IntControl 64