Funkcje obsługi lokalnych plików, katalogów i dysków
Jacek Matulewski
30 kwietnia 2015 Programowanie Windows
http://www.fizyka.umk.pl/~jacek/dydaktyka/winprog/
Systemy plików w Windows
• FAT (ang. file allocation table) – system plików opracowany przez QDOS (dyskietki, 70s), system kupiony przez Microsoft.
Potem używany także w MS-DOS i Windows.
Tablica alokacji plików przechowuje informacje o ułożeniu poszczególnych plików w klastrach (jednostkach alokacji),
na które podzielony jest nośnik.
1983 – FAT16 dla dysków twardych (65535 klastrów, < 2GB) 1997 – FAT32 dla dysków > 2GB, teoretycznie do 124GB
• NTFS – dziennik zmian, szyfrowanie, kompresja „w locie”, prawa dostępu do plików i katalogów (ACL), transakcyjność
• WinFS – eksperymentalny system plików oparty na bazie danych SQL Server (projekt wycofany w 2006)
• ReFS (ang. resilient file system, odporny) – następca NTFS w Windows Server 2012 i Windows 8, pliki i informacje o plikach (metadane)
umieszczone w bazie danych, samonaprawiający się, autodetekcja, 16EB
Funkcje jądra dotyczące plików
• Większość zaimplementowana w kernel32.dll
• Operacje na plikach: kopiowanie, przenoszenie, usuwanie, tworzenie, odczytywanie zawartości, zapisywanie
• Odczytywanie informacji o plikach
• Łącza symboliczne, twarde, miękkie
• Wyszukiwanie plików, listowanie plików w katalogu
• Kompresja (LZ), zob. także Compression API
• Szyfrowanie, zob. także CryptoAPI
Funkcje jądra – operacje na plikach
• Funkcje z biblioteki kernel32.dll
• Kopiowanie plików: CopyFile(źródło, nowy, czyNadpisać)
• CopyFileEx – dodatkowo: funkcja zwrotna (callback), do której przesyłane są informacje o postępie kopiowania, możliwość anulowania procesu, CopyProgressRoutine
opcje: wyłączenie buforowania, ponowienie przy niepowodzeniu, kopiowanie zaszyfrowanych, obsługa linków symbolicznych
• CopyFileTransacted – transakcyjne kopiowanie plików, część większego API Transcactional NTFS API (TxF),
dodane w Windows Vista, ale wycofywane z użycia
• CopyFile2(źródło, cel, dużoParametrów) – Windows 8/2012, także w dla Store Apps, uporządkowane API
Funkcje jądra – operacje na plikach
• Przykład użycia CopyFileEx do kopiowania ze śledzeniem postępu
CopyFileEx(
_T("C:\\Katalog-Źródło\\Plik-Źródło.rozsz"), //źródło _T("C:\\Katalog-Cel\\Plik-Cel.rozsz "), //cel
(LPPROGRESS_ROUTINE)&ProceduraKopiowania, //callback func.
NULL, //dane przesyłane do procedury
0, //anulowanie, przy ponownym uruchomieniu
COPY_FILE_ALLOW_DECRYPTED_DESTINATION); //opcje
Przykładowa flaga: kopiowanie pliku powiedzie się nawet, gdy plik docelowy nie będzie mógł być zaszyfrowany
Funkcje jądra – operacje na plikach
• Procedura kopiowania – sygnatura (wszystkie parametry _In_)
DWORD CALLBACK ProceduraKopiowania(
LARGE_INTEGER TotalFileSize, //rozmiar pliku
LARGE_INTEGER TotalBytesTransferred, //bajty przesłane LARGE_INTEGER StreamSize, //rozmiar strumienia w bajtach LARGE_INTEGER StreamBytesTransferred, //b. przesł. strum.
DWORD dwStreamNumber, //numer bieżącego strumienia DWORD dwCallbackReason, //powód wywołania procedury HANDLE hSourceFile, //uchwyt pliku źródłowego
HANDLE hDestinationFile, //uchwyt pliku docelowego
LPVOID lpData) //dane przesyłane z CopyFileEx, 4. par.
{
...
}
Funkcje jądra – operacje na plikach
• Procedura kopiowania – przykładowe ciało
DWORD CALLBACK ProceduraKopiowania(...) {
double procent =
(double(TotalBytesTransferred.QuadPart*100)) / (double(TotalFileSize.QuadPart));
if(procent >= 100) {
MessageBox(NULL, _T("Kopiowanie zakończone"), _T("Kopiowanie pliku"), MB_OK);
return PROGRESS_STOP;
}
else return PROGRESS_CONTINUE;
}
Funkcje jądra – operacje na plikach
• Analogicznie wygląda przenoszenie plików,
funkcje: MoveFile(Ex) i MoveFileTransacted
• DeleteFile – usuwanie pliku
• OpenFile CreateFile(2) – otwarcie istniejącego
lub utworzenie nowego pliku (zwraca uchwyt HANDLE do pliku) np. do czytania lub pisania: ReadFile(Ex), WriteFile(Ex)
hPlik = CreateFile("Plik.dat", //nazwa pliku
GENERIC_WRITE, //tylko do czytania 0, //bez współdzielenia
NULL, //domyślne ust. bezpiecz.
CREATE_NEW, //tylko tworzenie nowego FILE_ATTRIBUTE_NORMAL, //zwykły plik (atr) NULL); //plik-szablon/wzór atr.
Funkcje jądra – operacje na plikach
• Analogicznie wygląda przenoszenie plików,
funkcje: MoveFile(Ex) i MoveFileTransacted
• DeleteFile – usuwanie pliku
• OpenFile CreateFile(2) – otwarcie istniejącego
lub utworzenie nowego pliku (zwraca uchwyt HANDLE do pliku) np. do czytania lub pisania: ReadFile(Ex), WriteFile(Ex)
BOOL wynik = WriteFile(
hPlik, //uchwyt otwartego wcześniej pliku
bufor, //np. char bufor[] = "Tekst do zapisania"
rozmiar, //liczba bajtów do zapisania
&rozmiarZapisany, //liczba bajtów zapisana NULL); //bez ustawiania współdzielenia
Funkcje jądra – operacje na plikach
• LockFile(Ex) – rezerwowanie dostępu do całego lub części pliku tylko dla bieżącego procesu; blokowanie dostępu z innych
• UnlockFile(Ex) – odblokowywanie dostępu
• EncryptFile, DecryptFile – szyfrowanie i deszyfrowanie plików z kluczem publicznym, rozszerz. Encrypted File System (czymś innym jest CryptoAPI, CPS, CAPICOM, WinTrust)
• FileEncryptionStatus + wiele innych dot. szyfrowania
• LZInit, LZOpenFile, LZClose, LZCopy, LZRead – kompresja (kodowanie słownikowe) metodą Lempel-Ziv (LZ)
Funkcje jądra – łącza (links)
• CreateSymbolicLink, CreateHardLink – tworzy łącze
• Usuwanie: DeleteFile lub RemoveDirectory
Funkcje jądra – łącza (links)
• CreateSymbolicLink, CreateHardLink – tworzy łącze
• Usuwanie: DeleteFile lub RemoveDirectory W NTFS trzy typy łączy:
Łącze symboliczne (ang. symbolic link) – specjalny typ pliku
wskazujący na inny plik; łącze jest niewidoczne przy typowych operacjach (np. kopiowanie), które są przekierowywane do pliku docelowego i na nim wykonywane
Łącze stałe (ang. hard link) – dodatkowa nazwa/ścieżka do pliku;
plik jest kasowany po usunięciu wszystkich ścieżek/nazw
Łącze miękkie (ang. soft link, junction) – jak łącza stałe między katalogami, ale może łączyć też katalogi na różnych dyskach
Funkcje jądra – informcje o plikach
• GetFileSize(Ex) – pobiera rozmiar pliku w bajtach
• GetFullPathName – pełna ścieżka pliku
• GetLongPathName, GetShortPathName (8.3)
• GetTempFileName – generuje unikalną nazwę pliku tymczasowego (w katalogu – GetTempPath)
• GetFileAttributes, SetFileAttributes (ASRH)
Funkcje jądra – wyszukiwanie plik.
• Szukanie konkretnego pliku: SearchPath (uwaga, nieco inna ścieżka przeszukiwania niż w funkcji LoadLibrary)
• Listowanie zawartości katalogu (może być rekursywne):
FindFirstFile(Ex), FindNextFile, FindClose
• Przykład ze strony MSDN (bez przeszukiwania rekursywnego)
https://msdn.microsoft.com/pl-pl/library/windows/desktop/aa365200(v=vs.85).aspx
WIN32_FIND_DATA ffd;
LARGE_INTEGER filesize;
HANDLE hFind = INVALID_HANDLE_VALUE;
hFind = FindFirstFile(TEXT("C:\\Windows"), &ffd);
if (INVALID_HANDLE_VALUE == hFind) MessageBox(/* Błąd! */);
Funkcje jądra – wyszukiwanie plik.
• Przykład ze strony MSDN (c.d.)
https://msdn.microsoft.com/pl-pl/library/windows/desktop/aa365200(v=vs.85).aspx
do {
if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) _tprintf(TEXT(" %s <DIR>\n"), ffd.cFileName);
else {
filesize.LowPart = ffd.nFileSizeLow;
filesize.HighPart = ffd.nFileSizeHigh;
_tprintf(TEXT(" %s %ld bytes\n"),
ffd.cFileName, filesize.QuadPart);
} }
while(FindNextFile(hFind, &ffd) != 0);
Funkcje jądra – wyszukiwanie plik.
• Przykład ze strony MSDN (c.d.)
https://msdn.microsoft.com/pl-pl/library/windows/desktop/aa365200(v=vs.85).aspx
}
while(FindNextFile(hFind, &ffd) != 0);
dwError = GetLastError();
if (dwError != ERROR_NO_MORE_FILES) MessageBox(/* Błąd! */);
FindClose(hFind);
Funkcje jądra dotyczące katalogów
• Większość zaimplementowana w kernel32.dll
• Tworzenie katalogu: CreateDirectory(Ex) np.
CreateDirectory(Text("D:\\UMK"), NULL);
• Usuwanie katalogu:
RemoveDirectory(Text("D:\\UMK"));
• Odczyt katalogu bieżącego (roboczego) aplikacji:
(może być inny niż katalog, w którym jest plik .exe!) char bufor[MAX_PATH+1];
DWORD rozmiarBufora = MAX_PATH;
GetCurrentDirectory(rozmiarBufora, bufor);
//bufor[MAX_PATH + 1] = '\0';
Funkcje jądra dotyczące katalogów
• Zmiana bieżącego (roboczego) katalogu aplikacji:
SetCurrentDirectory((Text("D:\\UMK"));
• Podobne funkcje z System Information API:
GetWindowsDirectory, GetSystemDirectory
• Śledzenie zmian w katalogu:
FindFirstChangeNotification, FindNextChangeNotification, FindCloseChangeNotification
(por. klasa FileSystemWatcher z platformy .NET)
Funkcje jądra dotyczące katalogów
• Śledzenie zmian w katalogu – przykład z MSDN
https://msdn.microsoft.com/en-us/library/windows/desktop/aa365261(v=vs.85).aspx
1) Obserwowanie zmian nazw plików w bieżącym katalogu
LPTSTR lpKatalog = TEXT("D:\\UMK");
HANDLE dwUchwytyZmian[2];
dwUchwytyZmian[0] = FindFirstChangeNotification(
lpKatalog, //obserwowany katalog
FALSE, //czy obserwować podkatalogi
FILE_NOTIFY_CHANGE_FILE_NAME); //tylko nazwy plików if (dwUchwytyZmian[0] == INVALID_HANDLE_VALUE) ...
Funkcje jądra dotyczące katalogów
• Śledzenie zmian w katalogu – przykład z MSDN
https://msdn.microsoft.com/en-us/library/windows/desktop/aa365261(v=vs.85).aspx
2) Obserwowanie tworzenia katalogów w całym pod-drzewie
TCHAR lpDysk[4] = "D:\\\0"; //D:\, null-terminated dwUchwytyZmian[1] = FindFirstChangeNotification(
lpDysk, //obserwowany katalog
TRUE, //czy obserwować podkatalogi
FILE_NOTIFY_CHANGE_DIR_NAME); //zmiany katalogów if (dwUchwytyZmian[1] == INVALID_HANDLE_VALUE) ...
Funkcje jądra dotyczące katalogów
• Śledzenie zmian w katalogu – przykład z MSDN
https://msdn.microsoft.com/en-us/library/windows/desktop/aa365261(v=vs.85).aspx
3) Czekanie na powiadomienia
while(TRUE) {
dwStan = WaitForMultipleObjects(
2, dwUchwytyZmian, FALSE, INFINITE);
switch (dwStan) {
case WAIT_OBJECT_0: //pierwsza sytuacja case WAIT_OBJECT_0 + 1: //druga sytuacja
case WAIT_TIMEOUT: //nie w przypadku INFINITE }
}
Funkcje jądra dotyczące katalogów
• Śledzenie zmian w katalogu – przykład z MSDN
https://msdn.microsoft.com/en-us/library/windows/desktop/aa365261(v=vs.85).aspx
4) Ponawianie zapotrzebowania na notyfikację
case WAIT_OBJECT_0:
//plik utworzony, usunięty lub zmieniona nazwa //np. odświeżyć listę plików w katalogu lpKatalog ...
//ponowienie
if(FindNextChangeNotification(dwUchwytyZmian[0]) ==FALSE)
{ ... } break;
Funkcje jądra dotyczące katalogów
• Śledzenie zmian w katalogu – przykład z MSDN
https://msdn.microsoft.com/en-us/library/windows/desktop/aa365261(v=vs.85).aspx
5) Ponawianie zapotrzebowania na notyfikację
case WAIT_OBJECT_0 + 1:
//katalog utworzony, usunięty lub zmieniona nazwa //np. odświeżyć drzewo katalogów
...
//ponowienie
if(FindNextChangeNotification(dwUchwytyZmian[1]) ==FALSE)
{ ... } break;
Funkcje jądra dotyczące dysków
• Tylko jedna funkcja GetDiskFreeSpace(Ex)
• Więcej informacji można uzyskać korzystając z dwóch dodatkowych funkcji:
• GetDriveType
– 0 – dysk nie istnieje,
– 1 – dysk nie jest sformatowany,
– DRIVE_REMOVABLE – dysk wymienny, DRIVE_FIXED – lokalny – DRIVE_REMOTE – sieciowy, DRIVE_CDROM, DRIVE_RAMDISK
• GetVolumeInformation – nazwa dysku, S/N,
typ systemu plików i jego własności, maksymalna dłg. ścieżki
• Informacji sprzętowych (np. producent) można szukać w WMI (Windows Management Instrumentation)
Demo: DiskInfo
1. Pobieranie informacji o dyskach (logicznych)
2. W kodzie obejrzeć funkcję: PobierzInformacjeODysku (pliki InformacjeODysku.h/.cpp)
Demo: DiskInfo
1. Pobieranie informacji o dyskach (logicznych)
2. W kodzie obejrzeć funkcję: PobierzInformacjeODysku (pliki InformacjeODysku.h/.cpp)
Powłoka
• Powłoka Windows to cały graficzny interfejs użytkownika (GUI) systemu Windows. Obecnie dwa: desktop + ekran Start
• Możliwości powłoki systemu Windows w zakresie plików można utożsamiać z możliwościami Eksploratora Windows:
kosz, skróty (pliki .lnk), katalogi specjalne, przeciąganie (d&d)
• Okna dialogowe (potwierdzenie, postęp)
• Funkcje powłoki (Shell API) są zazwyczaj znacznie prostsze od funkcji jądra, a przy tym ogólniejsze
(por. ShellExecute i CreateProcess)
• Obsługa menu Start/ekranu Start, pasku zadań, zasobnik (tray)
• My omówimy jedynie niektóre funkcje dotyczące plików
Funkcje powłoki – pliki
• Funkcje powłoki dodane w Windows 95 i Windows NT 4.0
• Biblioteka shell32.dll (Shell API)
• Operacje na plikach (kopiowanie, przenoszenie, usuwanie):
jedna funkcja SHFileOperation
BOOL OperacjaNaPliku(HWND uchwyt, LPCTSTR szZrodlo, LPCTSTR szCel, DWORD operacja, DWORD opcje)
{
if(!PathFileExists(szZrodlo)) //także funkcja powłoki shlwapi.dll {
MessageBox(L"Nie odnaleziono pliku"));
return FALSE;
}
SHFILEOPSTRUCT parametryOperacji;
parametryOperacji.hwnd = uchwyt;
parametryOperacji.wFunc = operacja;
Funkcje powłoki – pliki
• Operacje na plikach – c.d. (funkcja SHFileOperation):
BOOL OperacjaNaPliku(HWND uchwyt, LPCTSTR szZrodlo, LPCTSTR szCel, DWORD operacja, DWORD opcje)
{
...
if (szZrodlo != L"") parametryOperacji.pFrom = szZrodlo;
else parametryOperacji.pFrom = NULL;
if (szCel != L"") parametryOperacji.pTo = szCel;
else {
parametryOperacji.pTo = NULL;
parametryOperacji.fFlags = opcje;
parametryOperacji.hNameMappings = NULL;
parametryOperacji.lpszProgressTitle = NULL;
}
return (SHFileOperation(¶metryOperacji) == 0);
}
Funkcje powłoki – pliki
• Kopiowanie i przenoszenie pliku
BOOL KopiowaniePliku(HWND uchwyt, LPCTSTR szZrodlo, LPCTSTR szCel) {
TCHAR lpBuffer[MAX_PATH] = {0};
GetFullPathName(szZrodlo, MAX_PATH, lpBuffer, NULL);
return OperacjaNaPliku(uchwyt, lpBuffer, szCel, FO_COPY, 0);
}
BOOL PrzenoszeniePliku(HWND uchwyt, LPCTSTR szZrodlo, LPCTSTR szCel) {
TCHAR lpBuffer[MAX_PATH] = {0};
GetFullPathName(szZrodlo, MAX_PATH, lpBuffer, NULL);
return OperacjaNaPliku(uchwyt, lpBuffer, szCel, FO_MOVE, 0);
}
Funkcje powłoki – pliki
• Kopiowanie i przenoszenie pliku
BOOL UsuwaniePliku(HWND uchwyt, LPCTSTR szZrodlo) {
TCHAR lpBuffer[MAX_PATH] = {0};
GetFullPathName(szZrodlo, MAX_PATH, lpBuffer, NULL);
return OperacjaNaPliku(uchwyt, lpBuffer, L"", FO_DELETE, 0);
}
• Przykłady użycia (podczas debugowania)
TCHAR path[MAX_PATH] = {0};
GetModuleFileName(GetModuleHandle(NULL), path, MAX_PATH);
KopiowaniePliku(m_hWnd, path, L"d:\\Kopia projektu.sln");
PrzenoszeniePliku(m_hWnd, L"d:\\Kopia projektu.sln", L"d:\\Kopia pliku.xml");
UsuwaniePliku(m_hWnd, L"d:\\Kopia pliku.xml");
Funkcje powłoki - pliki
• Interfejs IFileOperation dodany
w Windows Vista i Windows Server 2008
• Biblioteka Shell32.dll
• Umożliwia śledzenie postępu operacji, wykonywanie wielu operacji jednocześnie, szczegółowe informacje o błędach, usuwanie plików do kosza i operacje na całych katalogach
• Interfejs graficzny:
okna dialogowe z pytaniem o potwierdzenie postępu,
automatyczne pokazywanie postępu przy dużych plikach, itp.
• Wybrane metody: CopyItem(s), MoveItem(s), RenameItem(s), DeleteItem(s),
SetProgressDialog, SetProgressMessage
Dema: OperacjeNaPlikach(IFO)
1. Projekt OperacjeNaPlikach (funkcje z poprzednich slajdów) 2. Projekt OperacjeNaPlikachIFO – użycie IFileOperation
1. funkcja OperacjaNaPlikuIF
2. Korzystające z niej funkcje: KopiowaniePliku, PrzenoszeniePliku, UsuwaniePliku
3. usuwanie bez potwierdzenia – FOF_NONCONFIRMATION 4. usuwanie do kosza – FOF_ALLOWUNDO
5. operacje na katalogach – służą do tego te same metody IFO (używając funkcji jądra musielibyśmy kopiować plik po pliku) Aby uniknąć okien dialogowych: FOF_NOCONFIRMMKDIR Operacje tylko na plikach zgodnych z maską: FOF_FILEONLY
Funkcje powłoki – ścieżki plików
1. Zbiór funkcji powłoki służących do manipulacji ścieżkami plików (Shell Ligtweight Utility):
PathAddBackslash, PathAppend, PathCombine, PathFileExists, PathFindOnPath,
PathIsDirectory, PathIsNetworkPath, PathIsRoot, PathIsSystemFolder, i inne 2. Pełna lista: https://msdn.microsoft.com/en-
us/library/windows/desktop/bb773559(v=vs.85).aspx 3. Od Windows 8 i Windows Server 2012 zbiór funkcji
PathCch... np. PathCchAddBackslash:
akceptuje ścieżki z przedrostkami "\\", "\\?\" lub "\\?\UNC\"
Katalogi specjalne
Funkcja SHGetSpecialFolderPath:
TCHAR path[MAX_PATH];
SHGetSpecialFolderPath(NULL, path, CSIDL_WINDOWS, FALSE);
Przykłady:
CSIDL_WINDOWS – katalog Windows np. C:\Windows
CSIDL_SYSTEM – katalog systemowy np. C:\Windows\system32 CSIDL_PERSONAL – katalog Documents / Moje dokumenty
CSIDL_COMMON_DESKTOPDIRECTORY - wspólny
CSIDL_DESKTOPDIRECTORY – bieżącego użytkownika
Demo: Katalogi specjalne
Wyświetlanie przykładów katalogów specjalnych
Funkcje powłoki – Inne
• W menu Start, Dokumenty – lista ostatnio otwieranych dokumentów (nie jest tworzona automatycznie)
• Dodawanie dokumentów do tej listy: SHAddToRecentDocs np.
SHAddToRecentDocs(SHARD_PATH, nazwa_pliku);
• Przeciąganie plików (drag & drop):
DragQueryFile, DragQueryPoint, DragAcceptFiles, DragFinish
• Przykład w MFC:
http://www.codeproject.com/Articles/840/How-to-Implement- Drag-and-Drop-Between-Your-Progra
Dodatek: COM – pliki skrótu .lnk
• Interfejsy IShellLink, IPersistFile należące do COM (Component Object Model)
• COM to część szerszego API nazywanego System Services
• Do System Services należy także Compression API
• Zob. WWW: https://msdn.microsoft.com/en-
us/library/windows/desktop/ee663297(v=vs.85).aspx
• Możliwość tworzenia skrótu i odczytywania informacji z istniejącego pliku skrótu
• Podstawowe metody IShellLink: SetPath, SetWorkingDirectory, SetDescription,
SetIconLocation, SetShowCmd, SetHotkey, Save
Demo: Tworzenie skrótów
Tworzenie skrótu w katalogu roboczym (funkcja TworzSkrot) Odczytanie parametrów skrótu (funkcja CzytajSkrot)
Tworzenie skrótu na pulpicie
(metoda CPlikSkrotuDlg::TworzSkrotNaPulpicie)
Dodatek: informacje o pliku .exe
Odczytanie wersji i informacji o pliku .exe lub .dll:
VS_FIXEDFILEINFO – struktura zawierająca informacje o pliku GetFileVersionInfoSize(Ex) – pobieranie rozmiaru
GetFileVersionInfo(Ex) – pobieranie samej struktury
VerQueryInfo – odczytywanie informacji z pobranej struktury
Poza obsługą plików lokalnych…
• Mapowanie dysków sieciowych – WNetAddConnection2
• Pobieranie plików ze stron WWW – URLDownloadToFile
• Obsługa protokółu FTP: FtpFindFirstFile,
InternetFindNextFile, InternetCloseHandle, FtpGetFile, FtpPutFile
• Mapowanie – wiązanie zawartości pliku z fragmentem przestrzeni adresowej:
https://msdn.microsoft.com/en-
us/library/windows/desktop/aa366556(v=vs.85).aspx