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 comment
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 comment
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 comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...