Announcement

Collapse
No announcement yet.

Mount file/folder as drive

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Mount file/folder as drive

    Hello.

    I'am trying to mount a file (such as ZIP, encrypted file etc.) or a folder as a local drive (like SUBST). I thought i could work with SetVolumeMountPoint function, but i cannot pass a path to it directly i think. So i looked up some C example and found GetVolumeNameforVolumeMountPoint function. In C (WIN.H) it is declared as follwows:

    BOOL WINAPI GetVolumeNameforVolumeMountPointA(LPCSTR,LPSTR,DWORD);

    This is my implementation, but i does not compile (mismatch with prior definition): Any ideas?

    Code:
    #COMPILE EXE
    #DIM ALL
    #INCLUDE "WIN32API.INC"
    
    DECLARE FUNCTION SetVolumeMountPoint LIB "KERNEL32.DLL" ALIAS "SetVolumeMountPointA" ( lpszVolumeMountPoint AS ASCIIZ, lpszVolumeName AS ASCIIZ ) AS DWORD
    DECLARE FUNCTION DeleteVolumeMountPoint LIB "KERNEL32.DLL" ALIAS "DeleteVolumeMountPointA" ( lpszVolumeMountPoint AS ASCIIZ ) AS DWORD
    DECLARE FUNCTION GetVolumeNameForVolumeMountPoint LIB "KERNEL32.DLL" ALIAS "GetVolumeNameForVolumeMountPointA" (lpszVolumeMountPoint AS ASCIIZ, lpszVolumeName AS ASCIIZ, cchBufferLength AS DWORD) AS DWORD
    
    '----------------------------------------------------------------------
    ' Function  SystemErrorMessageText
    '           deliver a text message for a given API-error number
    ' in        error code by GetLastError()
    ' out       error text
    '----------------------------------------------------------------------
    FUNCTION SystemErrorMessageText (BYVAL ECode AS LONG) AS STRING
    
      LOCAL Buffer  AS ASCIIZ * 255
      LOCAL sText   AS STRING
    
      FormatMessage %FORMAT_MESSAGE_FROM_SYSTEM, BYVAL %Null, ECode, %Null, buffer, SIZEOF(buffer), BYVAL %Null
      sText = FORMAT$(ECode, "##### ") & Buffer
      FUNCTION = TRIM$( sText )
    
    END FUNCTION
    
    
    
    FUNCTION PBMAIN () AS LONG
    
        LOCAL Drv   AS ASCIIZ * 30
        LOCAL Path  AS ASCIIZ * %Max_Path
        LOCAL lResult   AS LONG
    
        Drv = "Y:\"
        'Path= "\\?\T:\VMmachines\"
        Path= "T:\VMmachines\"
        lResult = SetVolumeMountPoint( Drv, Path )
        'lResult = SetVolumeMountPoint( Drv, Path )
        IF lResult = 0 THEN
            lResult = GetLastError()
            MSGBOX "error "+SystemErrorMessageText(lResult)
        ELSE
            MSGBOX "Mount successful"
            lResult = DeleteVolumeMountPoint( Drv )
        END IF
    
    END FUNCTION
    I'am still confused...but on a higher level.

  • #2
    Michael,

    If you look in WIN32API.INC you will see that it is already declared, parameters as ASCIZ, ASCIZ, DWORD resp., result is LONG.

    Comment


    • #3
      SHELLing SUBST might work. I use SUBST all the time, and as soon as I open a command prompt and type the SUBST command, Explorer refreshes itself with the SUBST'd drive in the tree on the left hand panel.

      (But I do like this SetVolumeMountPoint call, and shall have to play with it. Might be nice to have 'in-process alias' to replace these ultra-long path/file names I often end up with)
      Michael Mattias
      Tal Systems (retired)
      Port Washington WI USA
      [email protected]
      http://www.talsystems.com

      Comment


      • #4
        From MSDN: http://msdn2.microsoft.com/en-us/library/aa364994.aspx

        BOOL WINAPI GetVolumeNameForVolumeMountPoint(
        __in LPCTSTR lpszVolumeMountPoint,
        __out LPTSTR lpszVolumeName,
        __in DWORD cchBufferLength
        );
        Parameters
        lpszVolumeMountPoint
        The path of a volume mount point (with a trailing backslash, "\") or a drive letter indicating a root directory (in the form "D:\").

        lpszVolumeName
        A pointer to a string that receives the volume name. This name is a unique volume name of the form "\\?\Volume{GUID}\" where GUID is the GUID that identifies the volume.

        cchBufferLength
        The length of the output buffer, in TCHARs. A reasonable size for the buffer to accommodate the largest possible volume name is 50 characters.

        Return Value
        If the function succeeds, the return value is nonzero.
        Unless I completely mis-read the above, lpszVolumeName will be in the form of a GUID. It doesn't appear to be optional.

        I completely misread it: : dunce_cap:

        "\\?\Volume{GUID}\"

        where GUID is a globally unique identifier (GUID) that identifies the volume.

        The \\?\ prefix disables path parsing and is not parsed along with the path — for example, "\\?\C:\myworld\private" is parsed as "C:\myworld\private". By prepending paths with \\?\, you can specify paths that are 32,767 Unicode characters long. However, each component in the path cannot be more than a file-system-specific value returned by the function GetVolumeInformation.

        You must specify full paths when using specifying unique volume names with \\?\. This prefix can also be used with paths constructed according to the universal naming convention (UNC), such as "\\OtherComputer\Directory\Filename.ext".

        All volume mount point functions that take a unique volume name as a parameter require the trailing backslash; and all volume mount point functions that return a unique volume name provide the trailing backslash. However, this is not the case with CreateFile. You can open a volume by calling CreateFile and omit the trailing backslash from the volume name you specify. CreateFile processes a unique volume name with an appended backslash as the root directory of the volume.

        Scott
        Last edited by Scott Hauser; 19 Feb 2008, 03:07 AM.
        The most exasperating part of the "rat race" is how often the rats are in the lead!

        Comment


        • #5
          Here is a working example for SetVolumeMountPoint() function.
          Code:
          #COMPILE EXE
          #DIM ALL
          #INCLUDE "WIN32API.INC"
          
          DECLARE FUNCTION SetVolumeMountPoint LIB "KERNEL32.DLL" ALIAS "SetVolumeMountPointA" ( lpszVolumeMountPoint AS ASCIIZ, lpszVolumeName AS ASCIIZ ) AS DWORD
          DECLARE FUNCTION DeleteVolumeMountPoint LIB "KERNEL32.DLL" ALIAS "DeleteVolumeMountPointA" ( lpszVolumeMountPoint AS ASCIIZ ) AS DWORD
          'DECLARE FUNCTION GetVolumeNameForVolumeMountPoint LIB "KERNEL32.DLL" ALIAS "GetVolumeNameForVolumeMountPointA" (lpszVolumeMountPoint AS ASCIIZ, byval lpszVolumeName AS ASCIIZ ptr, Byval cchBufferLength AS DWORD) AS LONG
          
          '----------------------------------------------------------------------
          ' Function  SystemErrorMessageText
          '           deliver a text message for a given API-error number
          ' in        error code by GetLastError()
          ' out       error text
          '----------------------------------------------------------------------
          FUNCTION SystemErrorMessageText (BYVAL ECode AS LONG) AS STRING
          
            LOCAL Buffer  AS ASCIIZ * 255
            LOCAL sText   AS STRING
          
            FormatMessage %FORMAT_MESSAGE_FROM_SYSTEM, BYVAL %Null, ECode, %Null, buffer, SIZEOF(buffer), BYVAL %Null
            sText = FORMAT$(ECode, "##### ") & Buffer
            FUNCTION = TRIM$( sText )
          
          END FUNCTION
          
          
          
          FUNCTION PBMAIN () AS LONG
          
              LOCAL Drv       AS ASCIIZ * 30
              LOCAL Path      AS ASCIIZ * %Max_Path
              LOCAL buffer    AS ASCIIZ * %Max_Path
              LOCAL lResult   AS LONG
              LOCAL bufLen    AS DWORD
              LOCAL lerr      AS DWORD
          
              Drv = "C:\"
              Path= "K:\test\"
              buffer = STRING$(%Max_Path, " ")
              bufLen = SIZEOF(buffer)
              lResult = GetVolumeNameForVolumeMountPoint( Drv, buffer, bufLen )
              lerr = GetLastError
              IF lResult <> 0 THEN
                  lResult = SetVolumeMountPoint( Path, buffer )
                  lerr = GetLastError()
                  IF lResult = 0 THEN
                      MSGBOX "Buffer="+buffer+$CRLF+"SetVolumeMountPoint-Error "+SystemErrorMessageText(lerr)
                  ELSE
                      MSGBOX "Mount successful, look up in explorer!"
                      MSGBOX "Dismount drive now: "+Drv
                      lResult = DeleteVolumeMountPoint( Drv )
                  END IF
              ELSE
                  MSGBOX "Received no volumename for mountpoint. Error:"+SystemErrorMessageText(lerr)
              END IF
          
          END FUNCTION
          Also there is a fast way to display a folder as a new drive (loke DOS SUBST):
          Code:
          #COMPILE EXE
          #DIM ALL
          #INCLUDE "WIN32API.INC"
          
          DECLARE FUNCTION SetVolumeMountPoint LIB "KERNEL32.DLL" ALIAS "SetVolumeMountPointA" ( lpszVolumeMountPoint AS ASCIIZ, lpszVolumeName AS ASCIIZ ) AS DWORD
          DECLARE FUNCTION DeleteVolumeMountPoint LIB "KERNEL32.DLL" ALIAS "DeleteVolumeMountPointA" ( lpszVolumeMountPoint AS ASCIIZ ) AS DWORD
          'DECLARE FUNCTION GetVolumeNameForVolumeMountPoint LIB "KERNEL32.DLL" ALIAS "GetVolumeNameForVolumeMountPointA" (lpszVolumeMountPoint AS ASCIIZ, byval lpszVolumeName AS ASCIIZ ptr, Byval cchBufferLength AS DWORD) AS LONG
          
          '----------------------------------------------------------------------
          ' Function  SystemErrorMessageText
          '           deliver a text message for a given API-error number
          ' in        error code by GetLastError()
          ' out       error text
          '----------------------------------------------------------------------
          FUNCTION SystemErrorMessageText (BYVAL ECode AS LONG) AS STRING
          
            LOCAL Buffer  AS ASCIIZ * 255
            LOCAL sText   AS STRING
          
            FormatMessage %FORMAT_MESSAGE_FROM_SYSTEM, BYVAL %Null, ECode, %Null, buffer, SIZEOF(buffer), BYVAL %Null
            sText = FORMAT$(ECode, "##### ") & Buffer
            FUNCTION = TRIM$( sText )
          
          END FUNCTION
          
          
          
          FUNCTION PBMAIN () AS LONG
          
              LOCAL Drv       AS ASCIIZ * 3
              LOCAL Path      AS ASCIIZ * 50
              LOCAL lResult   AS LONG
              LOCAL lerr      AS DWORD
          
              Drv = "Y:"
              Path= "\DosDevices\C:\Windows"
              lResult = DefineDosDevice(%DDD_RAW_TARGET_PATH, Drv, Path )
              lerr = GetLastError
              IF lResult = 0 THEN
                  MSGBOX "DDD-error: "+SystemErrorMessageText(lerr)
              ELSE
                  MSGBOX "success"
                  lResult = DefineDosDevice( %DDD_REMOVE_DEFINITION, Drv, "")
                  IF lResult <> 0 THEN
                      MSGBOX "Drive "+Drv+" removed."
                  ELSE
                      MSGBOX "Could not remove drive "+Drv
                  END IF
              END IF
          
          END FUNCTION
          Though the codes above is working, it does not what i intendet with. Searched MSDN for more information: if you want to mount a virtual drive with the contents of a file you need to write a devicedriver. This looks complicated and therefore a lot of books have been written for this.
          I will begin with this one: Developing Windows NT Device Drivers: A Programmer's Handbook (ISBN:0201695901) and with the MSDN DDK of course.
          I'am still confused...but on a higher level.

          Comment

          Working...
          X