Jump to content

Question to the dllcall experts


 Share

Recommended Posts

Hello Folks,

i'm trying to mount a dir as a drive with the api below (i know i could use subst, but my final goal is to play around with HDD drives GUID).

DllCall("kernel32.dll", "int", "SetVolumeMountPoint", "str", "\\?\C:\test_dir", "str", "w:\")

The functions are described here:

http://msdn2.microsoft.com/en-us/library/aa365561.aspx

The directory is empty as required. @error gives me a 0, so the call seems okay, but nothing happens. Anyone got an idea?

Any input on this? Thanks and cheers...

Edited by Polyphem
This post will be edited again by Polyphem: Tomorrow, 11:55 AM
Link to comment
Share on other sites

There's no function called SetVolumeMountPoint in kernel32.dll. Because this function deals with strings, it's actually implemented as ANSI and Unicode versions.

Scroll down the MSDN page and you'll see:

Implemented as SetVolumeMountPointW (Unicode) and SetVolumeMountPointA (ANSI).

Since AutoIt can be either ANSI or Unicode, you could do something like this:

If @Unicode Then
    DllCall("kernel32.dll", "int", "SetVolumeMountPointW", "str", "\\?\C:\test_dir", "str", "w:\")
Else
    DllCall("kernel32.dll", "int", "SetVolumeMountPointA", "str", "\\?\C:\test_dir", "str", "w:\")
EndIf

[quote name='Valik' post='301213' date='Jan 31 2007, 10:36 PM']You seem to have a habit of putting things in the wrong place. I feel sorry for any female you attempt to have sex with.[/quote][font="Lucida Sans Unicode"][/font]

Link to comment
Share on other sites

There's no function called SetVolumeMountPoint in kernel32.dll. Because this function deals with strings, it's actually implemented as ANSI and Unicode versions.

Scroll down the MSDN page and you'll see:

Since AutoIt can be either ANSI or Unicode, you could do something like this:

If @Unicode Then
    DllCall("kernel32.dll", "int", "SetVolumeMountPointW", "str", "\\?\C:\test_dir", "str", "w:\")
Else
    DllCall("kernel32.dll", "int", "SetVolumeMountPointA", "str", "\\?\C:\test_dir", "str", "w:\")
EndIfoÝ÷ Ûú®¢×¥v}ý¶Ø^¥ªÚÆÞ³­r.)¶¬jëh×6If @Unicode Then
    DllCall("kernel32.dll", "int", "SetVolumeMountPointW", "str", "x:\", "str", "\\?\C:\test_dir")
Else
    DllCall("kernel32.dll", "int", "SetVolumeMountPointA", "str", "x:\", "str", "\\?\C:\test_dir")
EndIf
Link to comment
Share on other sites

There's no function called SetVolumeMountPoint in kernel32.dll. Because this function deals with strings, it's actually implemented as ANSI and Unicode versions.

I see, thanks, i'm new to this dll stuff <_<... sadly, neither example above works for me...

This post will be edited again by Polyphem: Tomorrow, 11:55 AM
Link to comment
Share on other sites

Digged on and come up with this

If @Unicode Then
    
    $volumemountpoint = DllCall("kernel32.dll", "int", "GetVolumeNameForVolumeMountPointW", "str", "c:\test_dir\")  
;    DllCall("kernel32.dll", "int", "SetVolumeMountPointW", "str", "w:\", "str", "\\?\C:\test_dir\")
    DllCall("kernel32.dll", "int", "SetVolumeMountPointW", "str", "w:\", "str", $volumemountpoint)
    
Else
    
    $volumemountpoint = DllCall("kernel32.dll", "int", "GetVolumeNameForVolumeMountPointA", "str", "c:\test_dir\")  
;    DllCall("kernel32.dll", "int", "SetVolumeMountPointA", "str", "w:\", "str", "\\?\C:\test_dir\")
    DllCall("kernel32.dll", "int", "SetVolumeMountPointW", "str", "w:\", "str", $volumemountpoint)
    
EndIf

MsgBox(0,"",_GetLastErrorMessage())

;===============================================
;    _GetLastErrorMessage($DisplayMsgBox="")
;    Format the last windows error as a string and return it
;    if $DisplayMsgBox <> "" Then it will display a message box w/ the error
;    Return        Window's error as a string
;===============================================

Func _GetLastErrorMessage($DisplayMsgBox="")
    
    Local $ret,$s
    Local $p    = DllStructCreate("char[4096]")
    Local Const $FORMAT_MESSAGE_FROM_SYSTEM        = 0x00001000

    If @error Then Return ""

    $ret    = DllCall("Kernel32.dll","int","GetLastError")

    $ret    = DllCall("kernel32.dll","int","FormatMessage","int",$FORMAT_MESSAGE_FROM_SYSTEM,"ptr",0,"int",$ret[0],"int",0,"ptr",DllStructGetPtr($p),"int",4096,"ptr",0)
    $s    = DllStructGetData($p,1)
    If $DisplayMsgBox <> "" Then MsgBox(0,"_GetLastErrorMessage",$DisplayMsgBox & @CRLF & $s)
    return $s
    
EndFunc

Sadly, still not working <_<... but the doc says i have to add GetVolumeNameForVolumeMountPointW... maybe anyone willing to dig with me, i'll continue to try...

This post will be edited again by Polyphem: Tomorrow, 11:55 AM
Link to comment
Share on other sites

It should work like this:

If @Unicode Then
    Local $retStruct = DllStructCreate ("wstr szBuff")
    DllCall("kernel32.dll", "int", "GetVolumeNameForVolumeMountPointW", "str", "c:\test_dir\", "ptr", DllStructGetPtr($retStruct, 1), "dword", 32768)   
;   DllCall("kernel32.dll", "int", "SetVolumeMountPointW", "str", "w:\", "str", "\\?\C:\test_dir\")
    DllCall("kernel32.dll", "int", "SetVolumeMountPointW", "wstr", "w:\", "wstr", DllStructGetData($retStruct, 1))
    $retStruct = 0
Else
    Local $retStruct = DllStructCreate ("str szBuff")
    $volumemountpoint = DllCall("kernel32.dll", "int", "GetVolumeNameForVolumeMountPointA", "str", "c:\test_dir\", "ptr", DllStructGetPtr($retStruct, 1), "dword", 32768)   
;   DllCall("kernel32.dll", "int", "SetVolumeMountPointA", "str", "w:\", "str", "\\?\C:\test_dir\")
    DllCall("kernel32.dll", "int", "SetVolumeMountPointA", "str", "w:\", "str", DllStructGetData($retStruct, 1))
    $retStruct = 0
EndIf

UDFS & Apps:

Spoiler

DDEML.au3 - DDE Client + Server
Localization.au3 - localize your scripts
TLI.au3 - type information on COM objects (TLBINF emulation)
TLBAutoEnum.au3 - auto-import of COM constants (enums)
AU3Automation - export AU3 scripts via COM interfaces
TypeLibInspector - OleView was yesterday

Coder's last words before final release: WE APOLOGIZE FOR INCONVENIENCE 

Link to comment
Share on other sites

Thanks for your reply. Sadly

If @Unicode Then
    Local $retStruct = DllStructCreate ("wstr szBuff")
    DllCall("kernel32.dll", "int", "GetVolumeNameForVolumeMountPointW", "str", "\\?\c:\test_dir", "ptr", DllStructGetPtr($retStruct, 1), "dword", 32768)    
    DllCall("kernel32.dll", "int", "SetVolumeMountPointW", "wstr", "w:\", "wstr", DllStructGetData($retStruct, 1))
    $retStruct = 0
Else
    Local $retStruct = DllStructCreate ("str szBuff")
    DllCall("kernel32.dll", "int", "GetVolumeNameForVolumeMountPointA", "str", "\\?\c:\test_dir", "ptr", DllStructGetPtr($retStruct, 1), "dword", 32768)    
    DllCall("kernel32.dll", "int", "SetVolumeMountPointA", "str", "w:\", "str", DllStructGetData($retStruct, 1))
    $retStruct = 0
EndIf

_GetLastErrorMessage("Last Error:")

;===============================================
;    _GetLastErrorMessage($DisplayMsgBox="")
;    Format the last windows error as a string and return it
;    if $DisplayMsgBox <> "" Then it will display a message box w/ the error
;    Return        Window's error as a string
;===============================================

Func _GetLastErrorMessage($DisplayMsgBox="")
    Local $ret,$s
    Local $p    = DllStructCreate("char[4096]")
    Local Const $FORMAT_MESSAGE_FROM_SYSTEM        = 0x00001000
    If @error Then Return ""
    $ret    = DllCall("Kernel32.dll","int","GetLastError")
    $ret    = DllCall("kernel32.dll","int","FormatMessage","int",$FORMAT_MESSAGE_FROM_SYSTEM,"ptr",0,"int",$ret[0],"int",0,"ptr",DllStructGetPtr($p),"int",4096,"ptr",0)
    $s    = DllStructGetData($p,1)
    If $DisplayMsgBox <> "" Then MsgBox(0,"_GetLastErrorMessage",$DisplayMsgBox & @CRLF & $s)
    return $s
EndFunc

still gives me a "filename, dirname or volume label syntax is incorrect". Maybe i'll have to dig a little depper into the docs <_<...

Edited by Polyphem
This post will be edited again by Polyphem: Tomorrow, 11:55 AM
Link to comment
Share on other sites

Perhaps my error in @Unicode block.

Wrong:

DllCall("kernel32.dll", "int", "GetVolumeNameForVolumeMountPointW", "str", "\\?\c:\test_dir", "ptr", DllStructGetPtr($retStruct, 1), "dword", 32768)

Right:

DllCall("kernel32.dll", "int", "GetVolumeNameForVolumeMountPointW", "wstr", "\\?\c:\test_dir", "ptr", DllStructGetPtr($retStruct, 1), "dword", 32768)

UDFS & Apps:

Spoiler

DDEML.au3 - DDE Client + Server
Localization.au3 - localize your scripts
TLI.au3 - type information on COM objects (TLBINF emulation)
TLBAutoEnum.au3 - auto-import of COM constants (enums)
AU3Automation - export AU3 scripts via COM interfaces
TypeLibInspector - OleView was yesterday

Coder's last words before final release: WE APOLOGIZE FOR INCONVENIENCE 

Link to comment
Share on other sites

Well I should test my code before posting it. Me stupid, sorry.

Now:

If @Unicode Then
    Local $res = DllCall("kernel32.dll", "int", "GetVolumeNameForVolumeMountPointW", "wstr", "w:\", "wstr", "", "dword", 32768)
    If $res[0] Then DllCall("kernel32.dll", "int", "SetVolumeMountPointW", "wstr", "c:\test_dir\", "wstr", $res[2])
Else
    Local $res = DllCall("kernel32.dll", "int", "GetVolumeNameForVolumeMountPointA", "str", "w:\", "str", "", "dword", 32768)
    If $res[0] Then DllCall("kernel32.dll", "int", "SetVolumeMountPointA", "str", "c:\test_dir\", "str", $res[2])
EndIf
_GetLastErrorMessage("Last Error:")

UDFS & Apps:

Spoiler

DDEML.au3 - DDE Client + Server
Localization.au3 - localize your scripts
TLI.au3 - type information on COM objects (TLBINF emulation)
TLBAutoEnum.au3 - auto-import of COM constants (enums)
AU3Automation - export AU3 scripts via COM interfaces
TypeLibInspector - OleView was yesterday

Coder's last words before final release: WE APOLOGIZE FOR INCONVENIENCE 

Link to comment
Share on other sites

  • 11 months later...

For those that are interested I have worked it out (unicode) examples are below.

; GetVolumeNameForVolumeMountPoint
Local $retStruct = DllStructCreate ("wchar var1[50]")
DllCall("kernel32.dll", "int", "GetVolumeNameForVolumeMountPointW", "wstr", "P:\", "ptr", DllStructGetPtr($retStruct), "dword", 32768)
ConsoleWrite(@LF & DllStructGetData($retStruct,1) & @LF)

; SetVolumeNameForVolumeMountPoint
DllCall("kernel32.dll", "int", "SetVolumeMountPointW", "wstr", "c:\testdir\", "wstr", "\\?\Volume{da700b4a-9bf8-11dd-b5fd-001b7851e030}\")

; DeleteVolumeMountPoint
DllCall("kernel32.dll", "int", "DeleteVolumeMountPointW", "wstr", "c:\testdir\")
Link to comment
Share on other sites

For those that are interested I have worked it out (unicode) examples are below.

Your example doesn't work. Try this:

$Volume = "C:\"
$PointPath = "D:\MyPointFolder\"

$UniqName = _VolumeGetUniqName($Volume)
If @error Then Exit

_VolumeSetMountPoint($PointPath, $UniqName)
If @error Then Exit

;_VolumeDeleteMountPoint($PointPath)

Func _VolumeGetUniqName($sVolume)
    Local Const $MAX_VOLUME_NAME = 1024
    Local $vNameBuffer = DllStructCreate("wchar[" & $MAX_VOLUME_NAME & "]")

    $aRet = DllCall("kernel32.dll", "int", "GetVolumeNameForVolumeMountPointW", _
                                            "wstr", $sVolume, _
                                            "ptr", DllStructGetPtr($vNameBuffer), _
                                            "int", $MAX_VOLUME_NAME)
    
    If $aRet[0] = 0 Then Return SetError(1, 0, 0)
    Return DllStructGetData($vNameBuffer, 1)
EndFunc

Func _VolumeSetMountPoint($sPath, $sUniqName)
    If Not FileExists($sPath) Then
        If Not DirCreate($sPath) Then Return SetError(1, 0, 0)
    EndIf
    
    $aRet = DllCall("kernel32.dll", "int", "SetVolumeMountPointW", _
                                            "wstr", $sPath, _
                                            "wstr", $sUniqName)
    
    If $aRet[0] = 0 Then Return SetError(2, 0, 0)
    Return 1
EndFunc

Func _VolumeDeleteMountPoint($sPointPath)
    $aRet = DllCall("kernel32.dll", "int", "DeleteVolumeMountPointW", "wstr", $sPointPath)
    
    If $aRet[0] = 0 Then Return SetError(2, 0, 0)
    Return 1
EndFunc

Info:

GetVolumeNameForVolumeMountPoint

SetVolumeMountPoint

DeleteVolumeMountPoint

Edit: Comment the _VolumeDeleteMountPoint() function :P

Edited by rasim
Link to comment
Share on other sites

With the VolumeMountPoint funcs, you can mount a VOLUME as Directory or drive,

but NOT a DIRECTORY as drive :P

//Edit: sorry, didn't read right :( Should be possible, though.

Well, i was right :idea: But you can use thisto mount a directory

Global Const $DDD_EXACT_MATCH_ON_REMOVE = 0x00000004
Global Const $DDD_NO_BROADCAST_SYSTEM = 0x00000008
Global Const $DDD_RAW_TARGET_PATH = 0x00000001
Global Const $DDD_REMOVE_DEFINITION = 0x00000002

$DriveLetter = "J:"
$Directory = "\DosDevices\D:\Vista"
$ret = DllCall("Kernel32.dll","long_ptr","DefineDosDeviceA","dword",$DDD_RAW_TARGET_PATH,"str",$DriveLetter,"str",$Directory)
MsgBox(0, '', $Directory & "mounted as " & $DriveLetter & @CRLF & "Click OK to dismount")
$ret = DllCall("Kernel32.dll","long_ptr","DefineDosDeviceA","dword",$DDD_REMOVE_DEFINITION,"str",$DriveLetter,"ptr",0)
Edited by ProgAndy

*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Link to comment
Share on other sites

With the VolumeMountPoint funcs, you can mount a VOLUME as Directory or drive...

So far I have had no success with mounting a volume as a drive.

Anyone know how to assign a drive letter to a volume (say a USB stick for example) not mount the volume in a directory.

I am trying to solve the horrid XP problem where windows assigns the first available letter to a new USB device, completely ignoring network drives already using that letter.

Replicating (at least in part) what this program does.

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...