Jump to content

#RequireAdmin stops FileExists(Mapped folder) working on one PC

Recommended Posts

If I map a network drive as say N and try to access it in a script that needs #RequireAdmin  FileExists(“N:\”) returns 1 (correctly) on PC1 and 0 (incorrectly) on PC2 (Windows Explorer shows N:\ contents OK on PC2)

If I comment out #RequireAdmin it returns 1 on PC2

What do I have to do to PC2 to get FileExists(“N:\”) to return 1 in a script that needs #RequireAdmin.?

Both PCs are Win10 with latest updates and AutoIt3


Link to post
Share on other sites

As Jos mentioned it's more than likely the elevated account has the drive mapped already.

If you need to use a drive letter (sometimes required when managing long file paths), you can map the drive within the script first for example:

Global $g_sShare = "\\Server.local\Share"
DriveMapAdd("N:", $g_sShare, 1)
;~ Do stuff...


Link to post
Share on other sites

run an UAC elevated CMD prompt, then typing "net use" will give you a list of the drive mappings in place, when running UAC elevated.

To arrange them permanent do the mapping with the additional parameter "/persistent:yes", e.g.


net use i: \\file01\install /persistent:yes


Earth is flat, pigs can fly, and Nuclear Power is SAFE!

Link to post
Share on other sites

I wrote this script to analyze the differences I guess in 2017 or something like that.

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
#include <Array.au3>
#include <MsgBoxConstants.au3>
#include <ProcessConstants.au3>
#include <Security.au3>
#include <SecurityConstants.au3>
#include <StructureConstants.au3>
#include <WinAPI.au3>
#include <WinAPIFiles.au3>

Global $b_AddNetworkDrives = True
Global $g_CmdLineRaw = $CmdLineRaw

    There is an easier solution. To implement it, you have to make some changes to the registry:

    - Open the registry editor (regedit.exe)
    - Go to HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System
    - Create a new parameter (DWORD type) with the name EnableLinkedConnections and the value 1
    - Restart your computer



If Not @Compiled Then
    MsgBox(0, "Hint", "Run program compiled to test...")

If StringInStr($g_CmdLineRaw, "SMF_GetMappedDrives", 2) Then
    ; Executed by non-elevated Child process
    If Not IsAdmin() Then _UAC_GetMappedDrives_Child()

ElseIf Not IsAdmin() Then
    ; Run elevated Main process

    ; !!! HINT !!!
    ; > The UAC elevated process MUST NOT contain a manifest with the "requestedExecutionLevel = requireAdministrator"
    ; > the _RunNonElevated() function will not work for these executables
    ; > instead manually start the process with elevated rights manually, either through the "runas" verb or by right-click
    ; !!! HINT !!!
    ShellExecute(@ScriptFullPath, "", @WorkingDir, "runas")


If $b_AddNetworkDrives Then
    ; Executed by elevated Main process
    If IsAdmin() Then _UAC_GetMappedDrives_Parent()


Func _UAC_GetMappedDrives_Parent()

    Local $tSecurity = DllStructCreate("int Length;ptr Descriptor;int InheritHandle") ; $tagSECURITY_ATTRIBUTES
    DllStructSetData($tSecurity, 1, DllStructGetSize($tSecurity))
    DllStructSetData($tSecurity, 2, 0)

    Local $hFileMap = _WinAPI_CreateFileMapping(-1, 65536, "SMF_MappedDrives_Buffer", 0x0004, DllStructGetPtr($tSecurity))

    Local $iPID = _RunNonElevated('"' & @ScriptFullPath & '" SMF_GetMappedDrives')
    ProcessWaitClose($iPID, 10)

    Local $pAddress = _WinAPI_MapViewOfFile($hFileMap)
    Local $tData = DllStructCreate('wchar[32768]', $pAddress)
    Local $s_MappedDrives_Data_Child = DllStructGetData($tData, 1)

    Local $aDrives_Child
    If Not StringInStr($s_MappedDrives_Data_Child, "GetMappedDrives Results - Child:") Then
        Local $aDrives_Child[1]
        $aDrives_Child[0] = -1 ; Error, no info transfered from non-elevated process
        $s_MappedDrives_Data_Child = StringReplace($s_MappedDrives_Data_Child, "GetMappedDrives Results - Child:" & @LF, "")
        $aDrives_Child = StringSplit($s_MappedDrives_Data_Child, @LF)
        StringReplace($s_MappedDrives_Data_Child, @LF, "") ; Detect number of lines in data = number of found mappings
        $aDrives_Child[0] = @extended

    Local $aDrives = DriveGetDrive("NETWORK")
    If @error Or Not IsArray($aDrives) Then
        Local $aDrives[1]
        $aDrives[0] = 0

    Local $a_Drive_Mapping[28][5]
    $a_Drive_Mapping[0][1] = "Elevated Mode"
    $a_Drive_Mapping[0][3] = "Non-Elevated Mode"
    $a_Drive_Mapping[0][4] = "Number of Differences in mapped drives"
    $a_Drive_Mapping[1][1] = $aDrives[0] ; Number of Mapping in Elevated mode
    $a_Drive_Mapping[1][3] = $aDrives_Child[0] ; Number of Mapping in Non-Elevated mode
    $a_Drive_Mapping[1][4] = 0 ; Number of differences in mapped drive paths

    Local $aDrives_Child_Split

    For $i = 2 To 27

        $a_Drive_Mapping[$i][0] = Chr($i + 95) & ":"

        For $y = 1 To $aDrives[0]
            If $aDrives[$y] = Chr($i + 95) & ":" Then
                $a_Drive_Mapping[$i][1] = DriveMapGet($aDrives[$y])
                $a_Drive_Mapping[$i][2] = DriveStatus($a_Drive_Mapping[$i][1])

        For $y = 1 To $aDrives_Child[0]
            If StringLeft($aDrives_Child[$y], 3) = Chr($i + 95) & ":=" Then

                $aDrives_Child[$y] = StringTrimLeft($aDrives_Child[$y], 3)

                $aDrives_Child_Split = StringSplit($aDrives_Child[$y], "|")
                If $aDrives_Child_Split[0] = 2 Then
                    $a_Drive_Mapping[$i][3] = $aDrives_Child_Split[1]
                    $a_Drive_Mapping[$i][4] = $aDrives_Child_Split[2]


        If $a_Drive_Mapping[$i][1] <> $a_Drive_Mapping[$i][3] Then $a_Drive_Mapping[1][4] += 1


    If $a_Drive_Mapping[1][4] > 0 Then
        ; add action if difference in mappings found

    _ArrayDisplay($a_Drive_Mapping, IsAdmin())

EndFunc   ;==>_UAC_GetMappedDrives_Parent

Func _UAC_GetMappedDrives_Child()

    Local $s_MappedDrives_Data = "GetMappedDrives Results - Child:" & @LF

    Local $aDrives = DriveGetDrive("NETWORK")
    If Not @error Then
        For $i = 1 To $aDrives[0]
            $s_MappedDrives_Data &= $aDrives[$i] & "=" & DriveMapGet($aDrives[$i]) & "|" & DriveStatus($aDrives[$i]) & @LF

    Local $hFileMap = _WinAPI_OpenFileMapping("SMF_MappedDrives_Buffer")

    Local $pAddress = _WinAPI_MapViewOfFile($hFileMap)
    Local $tData = DllStructCreate('wchar[32768]', $pAddress)
    DllStructSetData($tData, 1, $s_MappedDrives_Data)


EndFunc   ;==>_UAC_GetMappedDrives_Child

Func _RunNonElevated($sCommandLine = "")
    If Not IsAdmin() Then Return Run($sCommandLine) ; if current process is run non-elevated then just Run new one.

    ; Structures needed for creating process
    Local $tSTARTUPINFO = DllStructCreate($tagSTARTUPINFO)

    ; Process handle of some process that's run non-elevated. For example "Explorer"
    Local $hProcess = _WinAPI_OpenProcess($PROCESS_ALL_ACCESS, 0, ProcessExists("explorer.exe"))

    ; If successful
    If $hProcess Then
        ; Token...
        Local $hTokOriginal = _Security__OpenProcessToken($hProcess, $TOKEN_ALL_ACCESS)
        ; Process handle is no longer needed. Close it
        ; If successful
        If $hTokOriginal Then
            ; Duplicate the original token

            ; https://stackoverflow.com/questions/7004310/bypassing-elevation-when-launching-a-new-process
            ; SetEnvironmentVariable function
            ; https://msdn.microsoft.com/en-us/library/windows/desktop/ms686206(v=vs.85).aspx

            Local $hTokDuplicate = _Security__DuplicateTokenEx($hTokOriginal, $TOKEN_ALL_ACCESS, $SECURITYIMPERSONATION, $TOKENPRIMARY)
            ; Close the original token
            ; If successful
            If $hTokDuplicate Then
                ; Create process with this new token

                Local $aRet = DllCall("kernel32.dll", "int", "SetEnvironmentVariable", "str", "__compat_layer", "str", "RunAsInvoker")

                _Security__CreateProcessWithToken($hTokDuplicate, 0, $sCommandLine, 0, @ScriptDir, $tSTARTUPINFO, $tPROCESS_INFORMATION)

                ; Close that token
                ; Close get handles
                _WinAPI_CloseHandle(DllStructGetData($tPROCESS_INFORMATION, "hProcess"))
                _WinAPI_CloseHandle(DllStructGetData($tPROCESS_INFORMATION, "hThread"))
                ; Return PID of newly created process
                Return DllStructGetData($tPROCESS_INFORMATION, "ProcessID")
EndFunc   ;==>_RunNonElevated


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    No registered users viewing this page.

  • Create New...