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 3.3.16.0

 

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:

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

 

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 ****
#AutoIt3Wrapper_Version=Beta
#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

#cs
    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

    http://woshub.com/how-to-access-mapped-network-drives-from-the-elevated-apps/

#ce



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

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

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")
    Exit

EndIf

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

Exit

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)
    _WinAPI_UnmapViewOfFile($pAddress)
    _WinAPI_CloseHandle($hFileMap)

    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
    Else
        $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
    EndIf

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

    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])
                ExitLoop
            EndIf
        Next

        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]
                EndIf

                ExitLoop
            EndIf
        Next

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

    Next

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

    _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
        Next
    EndIf


    Local $hFileMap = _WinAPI_OpenFileMapping("SMF_MappedDrives_Buffer")

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

    _WinAPI_CloseHandle($hFileMap)

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)
    Local $tPROCESS_INFORMATION = DllStructCreate($tagPROCESS_INFORMATION)

    ; 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
        _WinAPI_CloseHandle($hProcess)
        ; 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
            _WinAPI_CloseHandle($hTokOriginal)
            ; 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
                _WinAPI_CloseHandle($hTokDuplicate)
                ; 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")
            EndIf
        EndIf
    EndIf
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...