Announcement

Collapse
No announcement yet.

Getattr - win7

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

  • Gösta H. Lovgren-2
    replied
    Originally posted by Bernhard Fomm View Post
    You have Windows VISTA oder 7?
    Ni, I use XP.

    ==================================
    "A man with a new idea is a crank
    until the idea succeeds."
    Mark Twain
    ==================================

    Leave a comment:


  • Bernhard Fomm
    replied
    You have Windows VISTA oder 7?

    Leave a comment:


  • Gösta H. Lovgren-2
    replied
    Originally posted by Bernhard Fomm View Post
    Thanks for the links.

    I hope that someone look at my example code...
    Is everything programmed correctly?
    Bernhard,

    On my compiter I get "C:\Documents and Settings is not a mount point or symlink" and then nothing for "C:\Users\All Users" (program ends).

    I don't have a "C:\Users\All Users" folder on my hard drive.

    Hope that helps.

    =============================
    That's cool beyond cold, Man.
    Swede
    =============================

    Leave a comment:


  • Bernhard Fomm
    replied
    Thanks for the links.

    I hope that someone look at my example code...
    Is everything programmed correctly?

    Leave a comment:


  • Knuth Konrad
    replied
    When it comes to directories, MS refers to those "redirects" as Junction Points.

    See

    http://msdn.microsoft.com/en-us/libr...8VS.85%29.aspx
    http://msdn.microsoft.com/en-us/library/bb756982.aspx

    Leave a comment:


  • Bernhard Fomm
    replied
    With the following code corresponding links can be read.
    In the program I do not understand one point:
    Why is counted once Buffer.SubstituteNameOffset-4 ?
    (See red marker.)
    Is the code really properly? Or I made a bug?

    Code:
    #COMPILE EXE
    #DIM ALL
    #INCLUDE "win32api.inc"
    #INCLUDE "winioctl.inc"
    
    [COLOR="SeaGreen"]' Constant is missing in Win32API.inc[/COLOR]
    %IO_REPARSE_TAG_SYMLINK      = &hA000000C
    
    [COLOR="SeaGreen"]' http://msdn.microsoft.com/en-us/library/ms791514.aspx[/COLOR]
    TYPE REPARSE_DATA_BUFFER
        ReparseTag              AS LONG
        ReparseDataLength       AS WORD
        Reserved                AS WORD
        SubstituteNameOffset    AS WORD
        SubstituteNameLength    AS WORD
        PrintNameOffset         AS WORD
        PrintNameLength         AS WORD
        Flags                   AS LONG
        PathBuffer(%MAXIMUM_REPARSE_DATA_BUFFER_SIZE) AS WORD   [COLOR="SeaGreen"]' Unicode[/COLOR]
    END TYPE
    
    FUNCTION GetDirectoryTarget (BYVAL pDir AS STRING) AS STRING
    LOCAL mDir             AS ASCIIZ * %MAX_PATH
    LOCAL TokenHandle      AS LONG
    LOCAL TokenPrivilleges AS TOKEN_PRIVILEGES
    LOCAL hDirectory       AS LONG
    LOCAL BufferSize       AS LONG
    LOCAL Buffer           AS REPARSE_DATA_BUFFER
    LOCAL BytesReturned    AS LONG
    LOCAL lRet             AS LONG
    LOCAL ResultW          AS STRING
    LOCAL ResultA          AS STRING
    
        mDir = pDir
        [COLOR="SeaGreen"]' Check if the directory is a reparse point (link or mount point)[/COLOR]
        IF (GetFileAttributes(mDir) AND %FILE_ATTRIBUTE_REPARSE_POINT) = %FILE_ATTRIBUTE_REPARSE_POINT THEN
            [COLOR="SeaGreen"]' The backup privilege is required to open a directory for io queries
            ' So try to set it on our process token. (usually it should be set already)[/COLOR]
            IF OpenProcessToken(GetCurrentProcess(), %TOKEN_ADJUST_PRIVILEGES, TokenHandle) THEN
                TokenPrivilleges.PrivilegeCount = 1
                TokenPrivilleges.Privileges(0).Attributes = %SE_PRIVILEGE_ENABLED
                IF LookupPrivilegeValue($NUL, $SE_BACKUP_NAME, TokenPrivilleges.Privileges(0).pLuid) THEN
                    AdjustTokenPrivileges(TokenHandle, %FALSE, TokenPrivilleges, SIZEOF(TokenPrivilleges), BYVAL 0, BYVAL 0)
                END IF
                CloseHandle (TokenHandle)
            END IF
            [COLOR="SeaGreen"]' Open directory[/COLOR]
            hDirectory = CreateFile(mDir, BYVAL 0, %FILE_SHARE_READ OR %FILE_SHARE_WRITE, BYVAL 0, %OPEN_EXISTING, %FILE_FLAG_OPEN_REPARSE_POINT OR %FILE_FLAG_BACKUP_SEMANTICS, BYVAL 0)
            IF hDirectory <> %INVALID_HANDLE_VALUE THEN
                [COLOR="SeaGreen"]' Query the directory for reparse point information[/COLOR]
                BufferSize = SIZEOF(Buffer)
                lRet = DeviceIoControl(hDirectory, %FSCTL_GET_REPARSE_POINT, BYVAL %NULL, 0, Buffer, BufferSize, BytesReturned, BYVAL %NULL)
                IF lRet <> 0 THEN
                    [COLOR="SeaGreen"]' Check the kind of reparse point (device drivers can create their own tags, so this is important)[/COLOR]
                    IF (Buffer.ReparseTag AND &hFFFFFFFF) = %IO_REPARSE_TAG_[COLOR="Red"][B]MOUNT_POINT[/B][/COLOR] THEN
                        [COLOR="SeaGreen"]' Read the result. The offset and length are in bytes. Peek$ needs length in characters[/COLOR]
                        ResultW = PEEK$(VARPTR(Buffer.PathBuffer(0)) + [COLOR="Red"][B]Buffer.SubstituteNameOffset - 4[/B][/COLOR], Buffer.SubstituteNameLength)
                        ResultA = ACODE$(ResultW)
                        MSGBOX "Reparse: " + pDir + $CR + "Target: " + ResultA,,"IO_REPARSE_TAG_MOUNT_POINT"
                    END IF
                    IF (Buffer.ReparseTag AND &hFFFFFFFF) = %IO_REPARSE_[COLOR="DarkOrange"][B]TAG_SYMLINK[/B][/COLOR] THEN
                        [COLOR="SeaGreen"]' Read the result. The offset and length are in bytes. Peek$ needs length in characters[/COLOR]
                        ResultW = PEEK$(VARPTR(Buffer.PathBuffer(0)) + [COLOR="DarkOrange"][B]Buffer.SubstituteNameOffset[/B][/COLOR], Buffer.SubstituteNameLength)
                        ResultA = ACODE$(ResultW)
                        MSGBOX "Reparse: " + pDir + $CR + "Target: " + ResultA,,"IO_REPARSE_TAG_SYMLINK"
                    END IF
                END IF
            END IF
            CloseHandle(hDirectory)
        ELSE
            MSGBOX pDir + " is not a mount point or symlink"
        END IF
        FUNCTION = ResultA
    END FUNCTION
    
    
    FUNCTION PBMAIN () AS LONG
    
        CALL GetDirectoryTarget("C:\Documents and Settings")
        CALL GetDirectoryTarget("C:\Users\All Users")
    
    END FUNCTION

    Leave a comment:


  • Bernhard Fomm
    replied
    Originally posted by Michael Mattias View Post
    I have three dollars sixty-two cents says simply skipping files/folders with attribute FILE_ATTRIBUTE_VIRTUAL solves your problem.. whatever that problem is.

    You have not described the application, so darned if I know what you are trying to accomplish here... what is this, some kind of 'backup' application?
    I will collect all the files in a folder or drive. After this, the files are processed. However, no duplicate files to be processed further.

    I think I could use DeviceIoControl and WinIOCtl.inc -> %FSCTL_GET_REPARSE_POINT

    Please help me translate the C-structure.
    REPARSE_DATA_BUFFER

    Code:
    typedef struct _REPARSE_DATA_BUFFER {
      ULONG  ReparseTag;
      USHORT  ReparseDataLength;
      USHORT  Reserved;
      union {
        struct {
          USHORT  SubstituteNameOffset;
          USHORT  SubstituteNameLength;
          USHORT  PrintNameOffset;
          USHORT  PrintNameLength;
          ULONG  Flags;
          WCHAR  PathBuffer[1];
          } SymbolicLinkReparseBuffer;
        struct {
          USHORT  SubstituteNameOffset;
          USHORT  SubstituteNameLength;
          USHORT  PrintNameOffset;
          USHORT  PrintNameLength;
          WCHAR  PathBuffer[1];
          } MountPointReparseBuffer;
        struct {
          UCHAR  DataBuffer[1];
        } GenericReparseBuffer;
      };
    } REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;

    Leave a comment:


  • Michael Mattias
    replied
    I have three dollars sixty-two cents says simply skipping files/folders with attribute FILE_ATTRIBUTE_VIRTUAL solves your problem.. whatever that problem is.

    You have not described the application, so darned if I know what you are trying to accomplish here... what is this, some kind of 'backup' application?

    Leave a comment:


  • Bernhard Fomm
    replied
    I think I could use DeviceIoControl and WinIOCtl.inc -> %FSCTL_GET_REPARSE_POINT

    Please help me translate the C-structure.
    REPARSE_DATA_BUFFER

    Leave a comment:


  • Bernhard Fomm
    replied
    It would be better if I had a API function that shows me which folders are linked (hard-, soft-, symbolic link, etc.).

    Leave a comment:


  • Michael Mattias
    replied
    FILE_ATTRIBUTE_REPARSE_POINT 1024 0x0400 A file or directory that has an associated reparse point, or a file that is a symbolic link.

    One of your two folders has this attribute. Skip it.

    Or, perhaps better still, skip the file with the "Virtual" attribute. Even though the attribute is "reserved for system use" and not further documented, "virtual" sounds like "not real" and therefore not worthy of inclusion in your list of "real" files.

    Sometimes you just have to make a guess.

    Leave a comment:


  • Bernhard Fomm
    replied
    C:\Users\All Users and C:\ProgramData

    Both folders point to the same content.
    How can I find out if included in the collection duplicate file objects?
    I probably must to look (open) at the linking of the virtual folders (FILE_ATTRIBUTE_VIRTUAL).
    But how?

    Code:
    #COMPILE EXE
    #DIM ALL
    #INCLUDE "WIN32API.INC"
    
    GLOBAL gcFiles      AS LONG
    GLOBAL gcFolders    AS LONG
    GLOBAL glFileAtt()  AS LONG
    GLOBAL glFoldAtt()  AS LONG
    GLOBAL gsFiles()    AS STRING
    GLOBAL gsFolders()  AS STRING
    
    SUB GetAllFiles (BYVAL sStartFolder AS STRING)
    LOCAL hSearch  AS DWORD
    LOCAL WFD      AS WIN32_FIND_DATA
        sStartFolder = RTRIM$(sStartFolder, "\")
        hSearch = FindFirstFile(BUILD$(sStartFolder,"\*"), WFD)
        IF hSearch <> %INVALID_HANDLE_VALUE THEN
            DO
                IF (WFD.dwFileAttributes AND %FILE_ATTRIBUTE_DIRECTORY) = %FILE_ATTRIBUTE_DIRECTORY THEN
                    IF ASC(WFD.cFileName) <> 46 THEN ' 46 = "."
                        REDIM PRESERVE gsFolders (gcFolders) AS STRING
                        REDIM PRESERVE glFoldAtt (gcFolders) AS LONG
                        gsFolders (gcFolders) = sStartFolder + "\" + WFD.cFileName
                        glFoldAtt (gcFolders) = WFD.dwFileAttributes
                        INCR gcFolders
                        CALL GetAllFiles (sStartFolder + "\" + WFD.cFileName)
                    END IF
                ELSE
                    REDIM PRESERVE gsFiles   (gcFiles) AS STRING
                    REDIM PRESERVE glFileAtt (gcFiles) AS LONG
                    gsFiles   (gcFiles) = sStartFolder + "\" + WFD.cFileName
                    glFileAtt (gcFiles) = WFD.dwFileAttributes
                    INCR gcFiles
                END IF
            LOOP WHILE FindNextFile(hSearch, WFD)
            FindClose hSearch
        END IF
    END SUB
    
    SUB PB_DeleteFile(BYVAL pFile AS STRING)
    ON ERROR RESUME NEXT
        KILL pFile
    END SUB
    
    SUB PB_WriteFile (BYVAL pFile AS STRING, pFiles() AS STRING, pAttr() AS LONG)
    ON ERROR GOTO FN_ERR
    LOCAL f AS LONG
    LOCAL i AS LONG
        f = FREEFILE
        OPEN pFile FOR OUTPUT ACCESS WRITE AS #f
            FOR i = LBOUND(pFiles) TO UBOUND(pFiles)
                PRINT #f, FORMAT$(pAttr(i)) + $TAB + pFiles(i)
            NEXT i
        CLOSE #f
    FN_EXIT:
        EXIT SUB
    FN_ERR:
        MSGBOX ERROR$,,FUNCNAME$
        RESUME FN_EXIT
    END SUB
    
    FUNCTION PBMAIN () AS LONG
    LOCAL StartFolder AS STRING
    LOCAL tmp AS STRING
    LOCAL i AS LONG
    
        StartFolder = "C:\"
    
        tmp = "CALL GetAllFiles (" + $DQ + StartFolder + $DQ + ")"
        #IF %DEF(%PB_CC32)
            STDOUT tmp
        #ELSE
            MSGBOX tmp
        #ENDIF
    
        DIM gsFiles(0) AS STRING
        CALL GetAllFiles (StartFolder)
        
        ' sort and write log-file...
        ARRAY SORT gsFiles(), TAGARRAY glFileAtt()
        ARRAY SORT gsFolders(), TAGARRAY glFoldAtt()
        CALL PB_DeleteFile (EXE.FULL$+".files.txt")
        CALL PB_DeleteFile (EXE.FULL$+".folders.txt")
        CALL PB_WriteFile  (EXE.FULL$+".files.txt", gsFiles(), glFileAtt())
        CALL PB_WriteFile  (EXE.FULL$+".folders.txt", gsFolders(), glFoldAtt())
        ' --------------------------------------------------------
        
        tmp = FORMAT$(gcFiles) + " files in " + StartFolder
        tmp = tmp + $CRLF + $CRLF + "Log files:" + $CRLF + EXE.FULL$+".files.txt" + $CRLF + EXE.FULL$+".folders.txt"
        #IF %DEF(%PB_CC32)
            STDOUT tmp
            WAITKEY$
        #ELSE
            MSGBOX tmp
        #ENDIF
    END FUNCTION

    Leave a comment:


  • Michael Mattias
    replied
    >And, what is FILE_ATTRIBUTE_VIRTUAL?

    What part of "This value is reserved for system use" don't you understand?

    Leave a comment:


  • Bernhard Fomm
    replied
    Originally posted by Michael Mattias View Post
    The answer is right here. It took me close to forty(40) seconds to find it.

    http://msdn.microsoft.com/en-us/libr...30(VS.85).aspx
    Thanks for you help.
    And, what is FILE_ATTRIBUTE_VIRTUAL?

    Leave a comment:


  • Michael Mattias
    replied
    The answer is right here. It took me close to forty(40) seconds to find it.

    http://msdn.microsoft.com/en-us/libr...30(VS.85).aspx

    Leave a comment:


  • Bernhard Fomm
    replied
    Originally posted by Edwin Knoppert View Post
    GetAttr() returns styles, you should use them accordingly

    If GetAttr(...) AND ... style then...

    And thus not by some 'total' number!
    I found the following attributes:

    %FILE_ATTRIBUTE_READONLY = &H00000001
    %FILE_ATTRIBUTE_HIDDEN = &H00000002
    %FILE_ATTRIBUTE_SYSTEM = &H00000004
    %FILE_ATTRIBUTE_DIRECTORY = &H00000010
    %FILE_ATTRIBUTE_ARCHIVE = &H00000020
    %FILE_ATTRIBUTE_DEVICE = &H00000040
    %FILE_ATTRIBUTE_NORMAL = &H00000080
    %FILE_ATTRIBUTE_TEMPORARY = &H00000100
    %FILE_ATTRIBUTE_SPARSE_FILE = &H00000200
    %FILE_ATTRIBUTE_REPARSE_POINT = &H00000400
    %FILE_ATTRIBUTE_COMPRESSED = &H00000800
    %FILE_ATTRIBUTE_OFFLINE = &H00001000
    %FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = &H00002000
    %FILE_ATTRIBUTE_ENCRYPTED = &H00004000

    Thus:
    GETATTR("C:\Users\All Users") = 9238 = &h2416 = HIDDEN or SYSTEM or DIRECTORY or REPARSE_POINT or NOT_CONTENT_INDEXED

    But what is:
    GETATTR("C:\ProgramData") = 73746 = &h00012012 =

    Leave a comment:


  • Michael Mattias
    replied
    FindFirstFileEX?

    Per doc allows you to filter the attributes of files returned.

    Leave a comment:


  • Edwin Knoppert
    replied
    GetAttr() returns styles, you should use them accordingly

    If GetAttr(...) AND ... style then...

    And thus not by some 'total' number!

    Leave a comment:


  • Mel Bishop
    replied
    Since you haven't posted an example of how you are finding these files, a couple of thoughts comes to mind.

    1. DIR$
    2. Check the path(s) for unwanted files.

    Leave a comment:


  • Bernhard Fomm
    replied
    C:\Users\All Users and C:\ProgramData

    Both folders contain the same files.

    If the C: is scanned (with FindFirstFile, FindNextFile),
    then corresponding files are counted twice.

    How can I prevent this?

    Leave a comment:

Working...
X