Jump to content
Sign in to follow this  
Polyphem

Question to the dllcall experts

Recommended Posts

Polyphem

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

Share this post


Link to post
Share on other sites
CoePSX

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]

Share this post


Link to post
Share on other sites
BrettF

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

Share this post


Link to post
Share on other sites
Polyphem

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

Share this post


Link to post
Share on other sites
Polyphem

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

Share this post


Link to post
Share on other sites
doudou

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:


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 

Share this post


Link to post
Share on other sites
Polyphem

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

Share this post


Link to post
Share on other sites
doudou

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:


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 

Share this post


Link to post
Share on other sites
Polyphem

Nope, same error <_<...


This post will be edited again by Polyphem: Tomorrow, 11:55 AM

Share this post


Link to post
Share on other sites
doudou

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:


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 

Share this post


Link to post
Share on other sites
Polyphem

Thanks for your efforts doudou... but still doenst work for me <_<... doesnt complain about the syntax though, but that system cannot find the source file (directory)...


This post will be edited again by Polyphem: Tomorrow, 11:55 AM

Share this post


Link to post
Share on other sites
BrettF
Gibbo

Just wondering if anyone solved this?

I'm trying to write a program to assign letters to USB drives.

Share this post


Link to post
Share on other sites
Gibbo

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

Share this post


Link to post
Share on other sites
rasim

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

Share this post


Link to post
Share on other sites
ProgAndy

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

Share this post


Link to post
Share on other sites
Gibbo

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.

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
Sign in to follow this  

×