Announcement

Collapse
No announcement yet.

NTFS JunctionPoints with PB ?

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

  • NTFS JunctionPoints with PB ?

    Hi folks,

    as I would like to create some junction points to solve one specific disk space (/usability) problem, I would like to know if you have any experience with these ?

    This is what I have now to play with, but it will fail even at the CreateFile call (at least )

    (.. I can't use the code tags here because of the "//?/" string??.. so an attachment is provided)

    Please, if you know how to make this example work, tell me.

    Oh, in the MakeJunction call the 1st parameter is the new junction name (should not exist before hand? I don't know yet if it will override..) and the 2nd is an existing folder name.

    cheers.. aSa C[_]
    Attached Files

  • #2
    I can't use the code tags here because of the "//?/" string??.. so an attachment is provided
    Check the "Disable smilies in text" option.

    Code:
    #COMPILE EXE
    #DIM ALL
    
    #INCLUDE "Win32API.inc"
    #INCLUDE "WINIOCTL.INC"
    
    %TMN_REPARSE_DATA_BUFFER_HEADER_SIZE = 8
    
    GLOBAL szBuffer AS ASCIIZ * %MAX_PATH*2
    
    ' Since MS apparently removed this struct (and its documentation) from
    ' the W2k SDK, but still refer to it in 'winioctl.h' for the specific
    ' IOCTLs, I decided to rename it and make it available.
    ' I've made some modifications to this one for easier access.
    '
    ' Structure for FSCTL_SET_REPARSE_POINT, FSCTL_GET_REPARSE_POINT, and
    ' FSCTL_DELETE_REPARSE_POINT.
    ' This version of the reparse data buffer is only for Microsoft tags.
    
    TYPE TMN_REPARSE_DATA_BUFFER
    	 ReparseTag AS LONG
    	 ReparseDataLength AS INTEGER
    	 Reserved AS INTEGER
    	 ' IO_REPARSE_TAG_MOUNT_POINT specifics follow
    	 SubstituteNameOffset AS INTEGER
    	 SubstituteNameLength AS INTEGER
    	 PrintNameOffset AS INTEGER
    	 PrintNameLength AS INTEGER
    	 'PathBuffer AS STRING PTR
    	 'PathBuffer AS INTEGER PTR
    	 PathBuffer AS ASCIIZ PTR
    END TYPE
    
    _______________________________________________________________
    
    
    FUNCTION PBMAIN () AS LONG
    
    	IF ISFALSE(MakeJunction("C:\1JUNCTION","C:\ADOBEAPP\FONTSYS")) THEN
    		MSGBOX "nononous"
    	ELSE
    		MSGBOX "YEShh"
    	END IF
    
    END FUNCTION
    
    _______________________________________________________________
    
    
    FUNCTION MakeJunction(strJunctionDir AS STRING, strDestDir AS STRING) AS LONG
    	LOCAL lngDirHandle, lngRet, lngBytes AS LONG
    	LOCAL nDestMountPointBytes AS INTEGER
    	LOCAL szNewJunctionName AS ASCIIZ * %MAX_PATH
    	LOCAL szDestinationDir AS ASCIIZ * %MAX_PATH
    	LOCAL rdbBuffer AS TMN_REPARSE_DATA_BUFFER
    
    	FUNCTION = 1
    
    	szNewJunctionName = "\\?\" & strJunctionDir & $NUL
    
    '  lngDirHandle = CreateFile("\\?\" & strJunctionDir & CHR(0), %OF_READWRITE, 0, BYVAL 0&, _
    '                          %OPEN_EXISTING, %FILE_FLAG_BACKUP_SEMANTICS OR %FILE_FLAG_OPEN_REPARSE_POINT, 0)
    
    	lngDirHandle = CreateFile(szNewJunctionName, BYVAL %GENERIC_READ OR %GENERIC_WRITE, BYVAL 0, BYVAL 0&, _
    													BYVAL %OPEN_EXISTING, BYVAL %FILE_FLAG_BACKUP_SEMANTICS OR %FILE_FLAG_OPEN_REPARSE_POINT, BYVAL 0)
    
    	IF lngDirHandle = -1 THEN
    		'PrintError
    		FUNCTION = 0
    		EXIT FUNCTION
    	END IF
    
    	szDestinationDir = "\??\" & strDestDir & $NUL
    
    	nDestMountPointBytes = (LEN(szDestinationDir) - 1) * 2
    
    	rdbBuffer.ReparseTag = %IO_REPARSE_TAG_MOUNT_POINT
    	rdbBuffer.ReparseDataLength = nDestMountPointBytes + 12
    	rdbBuffer.Reserved = 0
    	rdbBuffer.SubstituteNameOffset = 0
    	rdbBuffer.SubstituteNameLength = nDestMountPointBytes
    	rdbBuffer.PrintNameOffset = nDestMountPointBytes + 2
    	rdbBuffer.PrintNameLength = 0
    	'rdbBuffer.PathBuffer = StringToIntArray(strDestinationDir)
    	szBuffer = UCODE$(szDestinationDir)
    	rdbBuffer.PathBuffer = VARPTR(szBuffer)
    
    	lngRet = DeviceIoControl(lngDirHandle, %FSCTL_SET_REPARSE_POINT, rdbBuffer, rdbBuffer.ReparseDataLength + _
    													%TMN_REPARSE_DATA_BUFFER_HEADER_SIZE, BYVAL 0&, 0, lngBytes, BYVAL 0&)
    
    	IF lngRet = 0 THEN
    		'PrintError
    		FUNCTION = 0
    	END IF
    
    	CloseHandle lngDirHandle
    
    END FUNCTION
    Forum: http://www.jose.it-berater.org/smfforum/index.php

    Comment


    • #3
      The last parameter in the TMN_REPARSE_DATA_BUFFER structure isn't a pointer, but a variable-length unicode string.

      You can declare PathBuffer AS STRING * [enough number of characters to hold the string].

      Or you can do something like this:

      Code:
      TYPE TMN_REPARSE_DATA_BUFFER
      	 ReparseTag AS LONG
      	 ReparseDataLength AS WORD
      	 Reserved AS WORD
      	 ' IO_REPARSE_TAG_MOUNT_POINT specifics follow
      	 SubstituteNameOffset AS WORD
      	 SubstituteNameLength AS WORD
      	 PrintNameOffset AS WORD
      	 PrintNameLength AS WORD
      END TYPE
      
      rdbBuffer.ReparseTag = %IO_REPARSE_TAG_MOUNT_POINT
      rdbBuffer.ReparseDataLength = nDestMountPointBytes + 12
      rdbBuffer.Reserved = 0
      rdbBuffer.SubstituteNameOffset = 0
      rdbBuffer.SubstituteNameLength = nDestMountPointBytes
      rdbBuffer.PrintNameOffset = nDestMountPointBytes + 2
      rdbBuffer.PrintNameLength = 0
      
      DIM strBuffer AS STRING
      strBuffer = rdbBuffer & UCODE$(szDestinationDir & $NUL)
      lngRet = DeviceIoControl(lngDirHandle, %FSCTL_SET_REPARSE_POINT, BYVAL STRPTR(strBuffer), rdbBuffer.ReparseDataLength + _
      													%TMN_REPARSE_DATA_BUFFER_HEADER_SIZE, BYVAL 0&, 0, lngBytes, BYVAL 0&)
      Last edited by José Roca; 14 Dec 2008, 07:32 AM.
      Forum: http://www.jose.it-berater.org/smfforum/index.php

      Comment


      • #4
        a-haa. Thank You for such a simple solution for the problematic code tagging. Couldn't have thought of that by myself.

        That last parameter was problematic for me to understand correctly, but my intension was to "trial and error" it if nothing else.. but I haven't been able to reach that code part yet as the CreateFile() is not working and I don't know yet why. Thank you for good examples, they will be appreciated.

        I have tried to avoid API calls as I know a zit about them. (well I don't call myself a Windows programmer either..)

        thank you.. aSa C[_]

        Comment


        • #5
          >CreateFile() is not working and I don't know yet why.
          Code:
          lngDirHandle = CreateFile(szNewJunctionName, BYVAL %GENERIC_READ OR %GENERIC_WRITE, BYVAL 0, BYVAL 0&, _ 
                        BYVAL %OPEN_EXISTING, _
                        BYVAL %FILE_FLAG_BACKUP_SEMANTICS OR %FILE_FLAG_OPEN_REPARSE_POINT, BYVAL 0)
          [COLOR="Red"]LastError = GetLastError()[/COLOR]
          IF lngDirHandle = -1 THEN        '   INVALID_HANDLE_VALUE 
             Msg = SystemErrorMessageText (LastError) 
             PRINT Msg
             'PrintError
          
          
          ....
          
          FUNCTION SystemErrorMessageText (BYVAL ECode AS LONG) AS STRING
            LOCAL Buffer AS ASCIIZ * 255
            FormatMessage %FORMAT_MESSAGE_FROM_SYSTEM, BYVAL %NULL, _ 
                 ECode, %NULL, buffer, SIZEOF(buffer), BYVAL %NULL
          
            FUNCTION = FORMAT$(ECode, "##### ") & Buffer
          
          END FUNCTION
          Try that.

          MCM
          Michael Mattias
          Tal Systems (retired)
          Port Washington WI USA
          [email protected]
          http://www.talsystems.com

          Comment


          • #6
            Well, I'm puzzled. I added the code MCM suggested, thank you, and I got no.2: "The system cannot find the file specified". I don't think you're supposed to manually create a directory there (?), so there has to be something wrong with the parameters (??). And the "Adobe directory" does exist with a file in it.

            cheers.. aSa C[_]

            .....

            Seems that you really NEED to create a directory for the "mount". But that "PathBuffer" is still a problem: "The data present in the reparse point buffer is invalid". I have tried with both "PathBuffer as STRING * %MAX_PATH*2" and with that funny looking "TYPE + string data" combo.

            In C++ this TYPE is defined as:
            Code:
             
            struct TMN_REPARSE_DATA_BUFFER  {
              DWORD ReparseTag;
              WORD ReparseDataLength;
              WORD Reserved;
              // IO_REPARSE_TAG_MOUNT_POINT specifics follow
              WORD SubstituteNameOffset;
              WORD SubstituteNameLength;
              WORD PrintNameOffset;
              WORD PrintNameLength;
              WCHAR PathBuffer[1];
            };
            That "PathBuffer" definition is a little bit hard for me to understand clearly.

            cheers.. aSa C[_]
            Last edited by Ari Savola; 14 Dec 2008, 10:00 AM. Reason: Some progress?

            Comment


            • #7
              If the type can be extended then PathBuffer is just two bytes (or one UNICODE character), you can pass a pointer to this around but when referencing it fully you would need to use something like PEEK$/POKE$/MoveMemory.

              This is really like the BITMAPINFO structure with the color array.
              kgpsoftware.com | Slam DBMS | PrpT Control | Other Downloads | Contact Me

              Comment


              • #8
                This is the working version

                Thank you for your kind help. With that even I was able to "fix" this skeleton.

                Here's the working, similar code:


                Code:
                 
                #COMPILE EXE
                #DIM ALL
                 
                #INCLUDE "Win32API.inc"
                #INCLUDE "WINIOCTL.INC"
                 
                %TMN_REPARSE_DATA_BUFFER_HEADER_SIZE = 8
                 
                ' Since MS apparently removed this struct (and its documentation) from
                ' the W2k SDK, but still refer to it in 'winioctl.h' for the specific
                ' IOCTLs, I decided to rename it and make it available.
                ' I've made some modifications to this one for easier access.
                '
                ' Structure for FSCTL_SET_REPARSE_POINT, FSCTL_GET_REPARSE_POINT, and
                ' FSCTL_DELETE_REPARSE_POINT.
                ' This version of the reparse data buffer is only for Microsoft tags.
                TYPE TMN_REPARSE_DATA_BUFFER
                   ReparseTag AS LONG
                   ReparseDataLength AS WORD
                   Reserved AS WORD
                   ' IO_REPARSE_TAG_MOUNT_POINT specifics follow
                   SubstituteNameOffset AS WORD
                   SubstituteNameLength AS WORD
                   PrintNameOffset AS WORD
                   PrintNameLength AS WORD
                   'WCHAR PathBuffer[1];
                END TYPE
                'You NEED to add PathBuffer data AFTER this struct with this type of TYPE definition!
                _______________________________________________________________
                 
                FUNCTION PBMAIN () AS LONG
                 
                  ' The 1st parameter is the new junction point name, the 2nd is the folder path the junction point is pointing to
                  ' Junction point must have an existing folder with the same same as the junction point has (here C:\1JUNCTION must exist)
                  IF ISFALSE(MakeJunction("C:\1JUNCTION","C:\ADOBEAPP\FONTSYS")) THEN
                    MSGBOX "nononous"
                  ELSE
                    MSGBOX "YEShh"
                  END IF
                 
                END FUNCTION
                _______________________________________________________________
                 
                FUNCTION MakeJunction(strJunctionDir AS STRING, strDestDir AS STRING) AS LONG
                  LOCAL lngDirHandle, lngRet, lngBytes, LastError AS LONG
                  LOCAL nDestMountPointBytes AS INTEGER
                  LOCAL strNewJunctionName, strDestinationDir, strBuffer AS STRING
                  LOCAL rdbBuffer AS TMN_REPARSE_DATA_BUFFER
                 
                  FUNCTION = 1
                 
                  lngDirHandle = CreateFile("\\?\" & strJunctionDir & $NUL, BYVAL %GENERIC_READ OR %GENERIC_WRITE, BYVAL 0, BYVAL 0&, _
                                BYVAL %OPEN_EXISTING, BYVAL %FILE_FLAG_BACKUP_SEMANTICS OR %FILE_FLAG_OPEN_REPARSE_POINT, BYVAL 0)
                  IF lngDirHandle = -1 THEN        ' %INVALID_HANDLE_VALUE
                    'PrintError
                    MSGBOX SystemErrorMessageText(GetLastError())
                    FUNCTION = 0
                    EXIT FUNCTION
                  END IF
                 
                  strDestinationDir = "\??\" & strDestDir & $NUL
                  nDestMountPointBytes = (LEN(strDestinationDir)-1)*2
                 
                  rdbBuffer.ReparseTag = %IO_REPARSE_TAG_MOUNT_POINT
                  rdbBuffer.ReparseDataLength = nDestMountPointBytes+12
                  rdbBuffer.Reserved = 0
                  rdbBuffer.SubstituteNameOffset = 0
                  rdbBuffer.SubstituteNameLength = nDestMountPointBytes
                  rdbBuffer.PrintNameOffset = nDestMountPointBytes+2
                  rdbBuffer.PrintNameLength = 0
                 
                  strBuffer = rdbBuffer & UCODE$(strDestinationDir)
                 
                  lngRet = DeviceIoControl(lngDirHandle, %FSCTL_SET_REPARSE_POINT, BYVAL STRPTR(strBuffer), rdbBuffer.ReparseDataLength + _
                   %TMN_REPARSE_DATA_BUFFER_HEADER_SIZE, BYVAL 0&, 0, lngBytes, BYVAL 0&)
                  IF lngRet = 0 THEN
                    'PrintError
                    MSGBOX SystemErrorMessageText(GetLastError())
                    FUNCTION = 0
                  END IF
                 
                  CloseHandle lngDirHandle
                 
                END FUNCTION
                _______________________________________________________________
                 
                FUNCTION SystemErrorMessageText(BYVAL ECode AS LONG) AS STRING
                  LOCAL Buffer AS ASCIIZ*255
                 
                  FormatMessage %FORMAT_MESSAGE_FROM_SYSTEM, BYVAL %NULL, ECode, %NULL, buffer, SIZEOF(buffer), BYVAL %NULL
                  FUNCTION = FORMAT$(ECode, "##### ") & Buffer
                 
                END FUNCTION
                cheers.. aSa C[_]

                PS. @José
                "Disable smileys in text" did not solve the problem with this code sample for me. I HAD to highlight that \\?\ string and click the "Remove link" button + "Automatically parse links" in text is also off. Life is funny if you could always be a bystander ; )

                Comment

                Working...
                X