Autor Wątek: Win7 - Documents and Settings  (Przeczytany 2422 razy)

Offline t4fun

  • Użytkownik

# Wrzesień 10, 2010, 23:26:35
Windows 7 (być może w Viscie też) "Documents and Settings" nie jest zwykłym katalogiem tylko jakimś przekierowaniem do "Users". Nie jest symlinkiem, nie jest skrótem z czasów win9x. Pytanie brzmi: czym ten folder jest i jak poprawnie w winapi przejść przez ten katalog?

FindFirstFile z parametrem "c:\Documents and Settings\*" daje INVALID_HANDLE_VALUE, a dokładniej odmowę dostępu.
Listując FindFirstFile z "c:\*", i gdy iteracja dochodzi do tego katalogu, atrybuty tego katalogu różnią się od innych katalogów flagą FILE_ATTRIBUTE_REPARSE_POINT. Domyślam się że gdy napotykam taką flagę powinien odczytać jakąś funkcją prawdziwe miejsce docelowe tego folderu, czego wynikiem powinno być "c:\Users". Problem w tym że nie wiem jaką funkcją mam to zrobić. Spotkał się ktoś z tym problemem?

Offline Mr. Spam

  • Miłośnik przetworów mięsnych

Offline radsun

  • Użytkownik
    • CaRpg


Offline t4fun

  • Użytkownik

# Wrzesień 10, 2010, 23:48:44
To się raczej tyczy gdy w folderze masz zamontowany innym wolumin.
Latam po msdn i dowiedziałem się już że to nie są shortcut, symlink, ani hardlink, to niby się nazywa "Junction Points", może jeszcze dziś wyczytam coś sensownego o tym tworze.

Offline ConayR

  • Użytkownik

# Wrzesień 11, 2010, 01:41:38
To się nazywa Junction Point, jak już zauważyłeś.
//edyta
Find powinien działać. :/

Offline ConayR

  • Użytkownik

# Wrzesień 11, 2010, 02:01:46
Ok, sprawdziłem. Ten kod poprawnie parsuje JP (na XP, ale działanie JP nie uległo zmianie w Vista ani Win7)
#include <windows.h>
#include <strsafe.h>
#include <stdio.h>


void EnterDirectory(WCHAR *wszDir);
void EnterDirectory(WCHAR *wszDir, WCHAR *wszSubdir)
{
    const size_t    cchBuf          = 2000;
    WCHAR           wszBuf[cchBuf]  = {0};
    HRESULT         hr              = S_OK;

    // Concatenate string and produce new path ending with backslash
    hr = StringCchPrintfW(wszBuf, cchBuf, L"%s%s\\", wszDir, wszSubdir);
    if (S_OK == hr)
    {
        EnterDirectory(wszBuf);
    }
}

void EnterDirectory(WCHAR *wszDir)
{
    const size_t    cchBuf          = 2000;
    WCHAR           wszBuf[cchBuf]  = {0};
    WIN32_FIND_DATA FindFileData    = {0};
    HANDLE          hFind           = INVALID_HANDLE_VALUE;
    HRESULT         hr              = S_OK;

    // Concatenate string and produce new path ending with wildcard
    hr = StringCchPrintfW(wszBuf, cchBuf, L"%s*", wszDir);
    if (S_OK != hr)
        goto _exit;

    // Start iterating through the files in the directory
    hFind = FindFirstFileW(wszBuf, &FindFileData);
    if (INVALID_HANDLE_VALUE != hFind)
    {
        do
        {
            // Skip '.' and '..'
            if (L'.' != FindFileData.cFileName[0])
            {
                if (0 != (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
                {
                    EnterDirectory(wszDir, FindFileData.cFileName);
                }
                else
                {
                    wprintf(L"File: %s%s\n", wszDir, FindFileData.cFileName);
                }
            }
        } while (0 != FindNextFile(hFind, &FindFileData));
    }

    // Exit and cleanup
_exit:
    if (INVALID_HANDLE_VALUE != hFind)
    {
        FindClose(hFind);
        hFind = INVALID_HANDLE_VALUE;
    }
}

int __cdecl wmain(
    __in                int     argc,
    __in_ecount(argc)   WCHAR   *argv[]
)
{
    bool    fSuccess    = false;
    int     iLength     = 0;

    // Parameter count
    if (2 != argc)
        goto _exit;

    // Parameter ends with backslash
    iLength = wcslen(argv[1]);
    if (argv[1][iLength -1] != L'\\')
        goto _exit;

    // Traverse directories
    wprintf(L"\nDirectory: %s\n\n", argv[1]);
    EnterDirectory(argv[1]);

    // Exit and cleanup
    fSuccess = true;
_exit:
    if (!fSuccess)
    {
        wprintf(L"\nSyntax:\n\ttraverse [directory ending with \\]\n\n");
    }

    return (fSuccess ? 0 : 1);
}
Przykładowo przy JP D:\jp\b wskazującym na D:\jp\a, uzyskuję wynik:

D:\jp>FindFiles.exe d:\jp\

Directory: d:\jp\

File: d:\jp\a\test.txt
File: d:\jp\b\test.txt
File: d:\jp\FindFiles.exe
File: d:\jp\junction.exe

Coś robisz źle u siebie.

PS. Tak, wiem, rekurencja + nie sprawdzanie pętli == baaaardzo zły pomysł. ;]

Offline t4fun

  • Użytkownik

# Wrzesień 11, 2010, 11:14:42
Twój kod robi w sumie to samo co mój, a teraz cytat z MSDN o zmianach w Viście i JP DaS:

Cytuj
(...) These junction points have file attributes of FILE_ATTRIBUTE_REPARSE_POINT & FILE_ATTRIBUTE_SYSTEM and the ACLs are set to "Everyone Deny Read". Applications must have permissions in order to call out and traverse a specific path. However, enumerating the contents of these junction points is not possible.

Wynika z niego że wszyscy mają zabronione listowanie tego katalogu. I to by się zgadzało że GetLastError zwraca mi "Odmowa dostępu". Ale taki FreeCommander i po próbie wejścia do DaS przechodzi do Users. Szkoda że nie mam wiedzy crakerów o debugowaniu obcych binarek, bym się dowiedział co taki FreeCommander robi.

Offline Karol

  • Użytkownik

# Wrzesień 11, 2010, 12:08:16
Ale taki FreeCommander i po próbie wejścia do DaS przechodzi do Users. Szkoda że nie mam wiedzy crakerów o debugowaniu obcych binarek, bym się dowiedział co taki FreeCommander robi.
Może ma zakodowany głupi warunek if nie można otworzyć doc&set then otwórz users :D.

Offline t4fun

  • Użytkownik

# Wrzesień 11, 2010, 12:22:26
Musiałby mieć całą listę tych warunków, bo oprócz tego DaS, jest jeszcze pełno przekierowań wewnątrz katalogu domowego użytkownika, chyba twórcy nie poszliby na taką łatwiznę

Znalazłem też funkcję DeviceIoControl która powinna mi zwrócić docelową ścieżkę, ale jeden z jej argumentów to HANDLE do źródłowego pliku/katalogu. Ale próba otwarcia przez CreateFile DaS się nie powodzi.

Offline ConayR

  • Użytkownik

# Wrzesień 11, 2010, 14:59:39
Ale próba otwarcia przez CreateFile DaS się nie powodzi.
Musisz otworzyć z parametrem informującym, że to reparse point.
http://msdn.microsoft.com/en-us/library/aa363874(v=VS.85).aspx

Co do Twojego problemu z DaS - odnoszę wrażenie, że to nie jest zmiana dla JP w ogóle a sposób ustawienia ACLs na DaS i kilku konkretnych katalogach/RP. Zmiana działania RP w szerszym zakresie byłaby poważnym zerwaniem kompatybilności wstecznej. Możesz to sprawdzić tworząc w innym miejscu JP przy użyciu mklink. Sądzę, że odziedziczy ACLs rodzica i będzie go można normalnie trawersować FindFirstFile. :)

Offline t4fun

  • Użytkownik

# Wrzesień 13, 2010, 09:28:32
Mógłbyś dać przykład parametrów otwierających DaS? Bo moje próby nie działają

Kod: (c++) [Zaznacz]
HANDLE hDir = CreateFile(dirPath.c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
                FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT | FILE_ATTRIBUTE_REPARSE_POINT | FILE_ATTRIBUTE_DIRECTORY, NULL);

Offline FrostBite

  • Użytkownik

# Wrzesień 13, 2010, 12:57:41

Offline t4fun

  • Użytkownik

# Wrzesień 13, 2010, 13:09:30
Poradziłem sobie w między czasie. Pokaże najważniejsze fragmenty kodu:

Kod: (c++) [Zaznacz]
        HANDLE hDir = CreateFile(dirPath.c_str(), 0, 0, NULL, OPEN_EXISTING,
                FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
        if (hDir != INVALID_HANDLE_VALUE) {

            BYTE buf[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];

            DWORD dwRet;
            BOOL br = DeviceIoControl(hDir, FSCTL_GET_REPARSE_POINT, NULL, 0, buf,
                    MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &dwRet, NULL);

            CloseHandle(hDir);

            if (br != 0) {

                REPARSE_GUID_DATA_BUFFER* repBuf = (REPARSE_GUID_DATA_BUFFER*) buf;

                wcout<<(wchar_t*)repBuf->GenericReparseBuffer.DataBuffer<<endl;

            }
        }

Offline ConayR

  • Użytkownik

# Wrzesień 13, 2010, 13:15:20
Właśnie miałem pisać, że dzielenie do zapisu nie ma sensu (pewnie ACLs Ci na to nie pozwalają) i te atrybuty są najprawdopodobniej zbędne (FILE_ATTRIBUTE_REPARSE_POINT się używa głównie do GetFileAttribute). No ale już po sprawie. :)