Jump to content
TroyT

DriveMapGet fails when AutoIt3Wrapper_Res_requestedExecutionLevel=requireAdministrator is set.

Recommended Posts

TroyT

DriveMapGet fails when AutoIt3Wrapper_Res_requestedExecutionLevel=requireAdministrator is set. 

The drive is mapped and DriveMapGet reports the drive as mapped when AutoIt3Wrapper_Res_requestedExecutionLevel=requireAdministrator is not set, and fails to detect that the drive is mapped when AutoIt3Wrapper_Res_requestedExecutionLevel=requireAdministrator is set.  I'm sure I'm just missing something.

Here is the code:

#include <File.au3>
#include <AutoItConstants.au3>
#include <MsgBoxConstants.au3>

Local $sDrive = "B:"
Local $sAppPath = DriveMapGet($sDrive)& "\Apps\App.exe"
Local $sWorkingFolder = DriveMapGet($sDrive)& "\Apps"
Local $sCmdLine = "/controlfile  Rfile.pot"

if ("" = DriveMapGet($sDrive)) Then
    MsgBox( $MB_OK, "Error - No Drive mapping", "The " &$sDrive & " is not mapped.")
Else
    ;Check to see if we can find the exe file.
    if FileExists( $sAppPath ) Then

        if FileExists( $sWorkingFolder & "\Rfile.pot" ) Then
            Local $iPID = ShellExecute ( $sAppPath , $sCmdLine, $sWorkingFolder )
        Else
            MsgBox( $MB_OK, "ERROR - File not found!", "Can not locate file: " & $sWorkingFolder & "\Rfile.pot" )
        EndIf

    Else
        MsgBox( $MB_OK, "ERROR - File not found!", "Can not locate file: " & $sAppPath )
    EndIf
EndIf

 

Thanks in advance.

Troy

Share this post


Link to post
Share on other sites
Jos

Are you using the exact same credentials when running elevated ?

Jos

Edited by Jos

Visit the SciTE4AutoIt3 Download page for the latest versions  - Beta files                                How to post scriptsource        Forum Rules
 
Live for the present,
Dream of the future,
Learn from the past.
  :)

Share this post


Link to post
Share on other sites
TroyT

Yes, I'm logged in as the admin.

Share this post


Link to post
Share on other sites
KaFu
KaFu

Here's a proof of concept:

#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

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

 

Share this post


Link to post
Share on other sites
Deye

putting this Q here for now ..

When not having a network drive to test this all out as in my case ..
In your best opinion how will the "net use" command should look like -> "tested"  (if it can help in using a mapped drive from an admin privileged script ..?)

* If I map a vmware drive it will show as a fixed drive type and non accessible from an admin privileged script
Also DriveMapGet will fail either ways since it doesn't get the UNC Path in this case ..

And I also want to distinguish when a drive can be accessed like  Z:\folder   never like: \\server\path\folder  And work with the drive in admin mode if the "net use" command proves to work

when using DriveGetDrive("NETWORK")  will i also need to  DriveMapGet("Z:")  it to check if its mapped or will it give UNC paths (if not mapped)  ?

Thanks

Share this post


Link to post
Share on other sites
Deye

at least i'll need to know what do you get for DriveGetDrive("NETWORK") is it essentially a mapped drive or a discovered network drive returning a UNC path "\\" , Can it be accessed like Z:\folder\some_file.ext

anyone ..
Thanks

Share this post


Link to post
Share on other sites
Earthshine

I took Troy's code above and used a mapped drive I have. it gives this

 

Capture.PNG


My resources are limited. You must ask the right questions

 

Share this post


Link to post
Share on other sites
Earthshine

I just updated his code to work with our drives and directory structure and got an app of mine to produce a generated output file just fine though.


My resources are limited. You must ask the right questions

 

Share this post


Link to post
Share on other sites
argumentum
1 minute ago, Earthshine said:

I just updated his code to work

SO ??/,  show me the code !! :P 

  • Like 1

Share this post


Link to post
Share on other sites
Earthshine
Posted (edited)

well, it just uses a test app that searches for stuff. no major changes. working folder, drive that is mapped, etc. not like you could reproduce it. mine works properly with admin rights granted or not, but, I have UAC turned all the way down I believe, checked, no I don't. I don't know what kind of issue he is having. it works either way, same for me. His code with my drive and folder info.

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Res_requestedExecutionLevel=requireAdministrator
#AutoIt3Wrapper_Add_Constants=n
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
#include <File.au3>
#include <AutoItConstants.au3>
#include <MsgBoxConstants.au3>

Local $sDrive = "S:"
Local $sAppPath = DriveMapGet($sDrive)& "\public\company\listfiles.exe"
Local $sWorkingFolder = DriveMapGet($sDrive)& "\public\company"
Local $sCmdLine = "d: *.pdf"

if ("" = DriveMapGet($sDrive)) Then
    MsgBox( $MB_OK, "Error - No Drive mapping", "The " &$sDrive & " is not mapped.")
Else
    ;Check to see if we can find the exe file.
    if FileExists( $sAppPath ) Then

;~         if FileExists( $sWorkingFolder & "\Rfile.pot" ) Then
            Local $iPID = ShellExecute ( $sAppPath , $sCmdLine, $sWorkingFolder )
;~         Else
;~             MsgBox( $MB_OK, "ERROR - File not found!", "Can not locate file: " & $sWorkingFolder & "\Rfile.pot" )
;~         EndIf

    Else
        MsgBox( $MB_OK, "ERROR - File not found!", "Can not locate file: " & $sAppPath )
    EndIf
EndIf

 

Edited by Earthshine
  • Like 1

My resources are limited. You must ask the right questions

 

Share this post


Link to post
Share on other sites
Deye
Posted (edited)

SO if I had to use FileCopy ( "Z:\folder\some_file.ext", $dest ) when its a mapped drive will this then fail ?

 

 

Edited by Deye

Share this post


Link to post
Share on other sites
Earthshine
2 minutes ago, Deye said:

SO if I had to use FileCopy ( "Z:\folder\some_file.ext", $dest ) when its a mapped drive will this then fail ?

Earthshine,

 did you try running it with #RequireAdmin ?

 

YES. Admin or not, it worked fine. I can call any app on that directory.

  • Like 1

My resources are limited. You must ask the right questions

 

Share this post


Link to post
Share on other sites
Deye

ohh OK then .. as i said couldn't test this out formyself and thanks again :) 

  • Like 1

Share this post


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

×