int parse_url( int history_file, double filever, int currrecoff, char *delim, int filesize, char *type, std::vector< URLRec * > &urls ) { char fourbytes[4]; char hashrecflagsstr[4]; char eightbytes[8]; char chr; int filenameoff; int httpheadersoff; int urloff; int i; int reclen; int dirnameoff; time_t modtime; time_t accesstime; char ascmodtime[26], ascaccesstime[26]; char dirname[9]; char *url; char *filename; char *httpheaders; int year, mon; struct tm *accesstm, *modtm; pread( history_file, fourbytes, 4, currrecoff+4 ); reclen = bah_to_i( fourbytes, 4 )*BLOCK_SIZE; pread( history_file, eightbytes, 8, currrecoff+8 ); modtime = win_time_to_unix( eightbytes ); pread( history_file, eightbytes, 8, currrecoff+16 ); accesstime = win_time_to_unix( eightbytes ); accesstm = localtime( &accesstime ); year = accesstm->tm_year + 1900; mon = accesstm->tm_mon + 1; sprintf( ascaccesstime, "%02d/%02d/%02d %02d:%02d:%02d", mon, accesstm->tm_mday, year, accesstm->tm_hour, accesstm->tm_min, accesstm->tm_sec ); modtm = localtime( &modtime ); year = modtm->tm_year + 1900; mon = modtm->tm_mon + 1; sprintf( ascmodtime, "%02d/%02d/%02d %02d:%02d:%02d", mon, modtm->tm_mday, year, modtm->tm_hour, modtm->tm_min, modtm->tm_sec ); if (accesstime == 0) { ascaccesstime[0] = '\0'; } if (modtime == 0) { ascmodtime[0] = '\0'; } url = (char *)malloc( reclen+1 ); if (filever >= 5) { pread( history_file, &chr, 1, currrecoff+0x34 ); } else { pread( history_file, &chr, 1, currrecoff+0x38 ); } urloff = (unsigned char)chr; i = 0; pread( history_file, &chr, 1, currrecoff+urloff ); while ( chr != '\0' && currrecoff+urloff+i+1 < filesize ) { url[i] = chr; pread( history_file, &chr, 1, currrecoff+urloff+i+1 ); i++; } url[i] = '\0'; filename = (char *)malloc( reclen+1 ); if (filever >= 5) { pread( history_file, fourbytes, 4, currrecoff+0x3C ); } else { pread( history_file, fourbytes, 4, currrecoff+0x40 ); } filenameoff = bah_to_i( fourbytes, 4 ) + currrecoff; i = 0; if (filenameoff > currrecoff+0x3C) { pread( history_file, &chr, 1, filenameoff ); while ( chr != '\0' && filenameoff+i+1 < filesize ) { filename[i] = chr; pread( history_file, &chr, 1, filenameoff+i+1 ); i++; } } filename[i] = '\0'; if (filever >= 5.2) { pread( history_file, &chr, 1, currrecoff+0x38 ); } else if (filever >= 5) { pread( history_file, &chr, 1, currrecoff+0x39 ); } else { pread( history_file, &chr, 1, currrecoff+0x3C ); } dirnameoff = (unsigned char)chr; if (0x50+(12*dirnameoff)+8 < filesize) { pread( history_file, dirname, 8, 0x50+(12*dirnameoff) ); dirname[8] = '\0'; } else { dirname[0] = '\0'; } httpheaders = (char *)malloc( reclen+1 ); if (filever >= 5) { pread( history_file, fourbytes, 4, currrecoff+0x44 ); } else { pread( history_file, fourbytes, 4, currrecoff+0x48 ); } httpheadersoff = bah_to_i( fourbytes, 4 ) + currrecoff; i = 0; if (httpheadersoff > currrecoff+0x44) { pread( history_file, &chr, 1, httpheadersoff ); while ( chr != '\0' && httpheadersoff+i+1 < currrecoff+reclen && httpheadersoff+i+1 < filesize ) { httpheaders[i] = chr; pread( history_file, &chr, 1, httpheadersoff+i+1 ); i++; } } httpheaders[i] = '\0'; printablestring( type ); printablestring( url ); printablestring( ascmodtime ); printablestring( ascaccesstime ); printablestring( filename ); printablestring( dirname ); printablestring( httpheaders ); if (type[3] == ' ') { type[3] = '\0'; } URLRec *urlrec = new URLRec(type, url, ascmodtime, ascaccesstime, filename, dirname, httpheaders); urls.push_back(urlrec); type[0] = '\0'; dirname[0] = '\0'; ascmodtime[0] = '\0'; ascaccesstime[0] = '\0'; free( url ); free( filename ); free( httpheaders ); }
static NTSTATUS query_dir_item(fcb* fcb, ccb* ccb, void* buf, LONG* len, PIRP Irp, dir_entry* de, root* r) { PIO_STACK_LOCATION IrpSp; LONG needed; UINT64 inode; INODE_ITEM ii; NTSTATUS Status; ULONG atts = 0, ealen = 0; file_ref* fileref = ccb->fileref; IrpSp = IoGetCurrentIrpStackLocation(Irp); if (de->key.obj_type == TYPE_ROOT_ITEM) { // subvol LIST_ENTRY* le; r = NULL; le = fcb->Vcb->roots.Flink; while (le != &fcb->Vcb->roots) { root* subvol = CONTAINING_RECORD(le, root, list_entry); if (subvol->id == de->key.obj_id) { r = subvol; break; } le = le->Flink; } if (r && r->parent != fcb->subvol->id) r = NULL; inode = SUBVOL_ROOT_INODE; } else { inode = de->key.obj_id; } if (IrpSp->Parameters.QueryDirectory.FileInformationClass != FileNamesInformation) { // FIXME - object ID and reparse point classes too? switch (de->dir_entry_type) { case DirEntryType_File: { if (!r) { LARGE_INTEGER time; ii = fcb->Vcb->dummy_fcb->inode_item; atts = fcb->Vcb->dummy_fcb->atts; ealen = fcb->Vcb->dummy_fcb->ealen; KeQuerySystemTime(&time); win_time_to_unix(time, &ii.otime); ii.st_atime = ii.st_mtime = ii.st_ctime = ii.otime; } else { BOOL found = FALSE; if (de->dc && de->dc->fileref && de->dc->fileref->fcb) { ii = de->dc->fileref->fcb->inode_item; atts = de->dc->fileref->fcb->atts; ealen = de->dc->fileref->fcb->ealen; found = TRUE; } if (!found) { KEY searchkey; traverse_ptr tp; searchkey.obj_id = inode; searchkey.obj_type = TYPE_INODE_ITEM; searchkey.offset = 0xffffffffffffffff; Status = find_item(fcb->Vcb, r, &tp, &searchkey, FALSE, Irp); if (!NT_SUCCESS(Status)) { ERR("error - find_item returned %08x\n", Status); return Status; } if (tp.item->key.obj_id != searchkey.obj_id || tp.item->key.obj_type != searchkey.obj_type) { ERR("could not find inode item for inode %llx in root %llx\n", inode, r->id); return STATUS_INTERNAL_ERROR; } RtlZeroMemory(&ii, sizeof(INODE_ITEM)); if (tp.item->size > 0) RtlCopyMemory(&ii, tp.item->data, min(sizeof(INODE_ITEM), tp.item->size)); if (IrpSp->Parameters.QueryDirectory.FileInformationClass == FileBothDirectoryInformation || IrpSp->Parameters.QueryDirectory.FileInformationClass == FileDirectoryInformation || IrpSp->Parameters.QueryDirectory.FileInformationClass == FileFullDirectoryInformation || IrpSp->Parameters.QueryDirectory.FileInformationClass == FileIdBothDirectoryInformation || IrpSp->Parameters.QueryDirectory.FileInformationClass == FileIdFullDirectoryInformation) { BOOL dotfile = de->name.Length > sizeof(WCHAR) && de->name.Buffer[0] == '.'; atts = get_file_attributes(fcb->Vcb, r, inode, de->type, dotfile, FALSE, Irp); } if (IrpSp->Parameters.QueryDirectory.FileInformationClass == FileBothDirectoryInformation || IrpSp->Parameters.QueryDirectory.FileInformationClass == FileFullDirectoryInformation || IrpSp->Parameters.QueryDirectory.FileInformationClass == FileIdBothDirectoryInformation || IrpSp->Parameters.QueryDirectory.FileInformationClass == FileIdFullDirectoryInformation) { ealen = get_ea_len(fcb->Vcb, r, inode, Irp); } } } break; } case DirEntryType_Self: ii = fcb->inode_item; r = fcb->subvol; inode = fcb->inode; atts = fcb->atts; ealen = fcb->ealen; break; case DirEntryType_Parent: if (fileref && fileref->parent) { ii = fileref->parent->fcb->inode_item; r = fileref->parent->fcb->subvol; inode = fileref->parent->fcb->inode; atts = fileref->parent->fcb->atts; ealen = fileref->parent->fcb->ealen; } else { ERR("no fileref\n"); return STATUS_INTERNAL_ERROR; } break; } if (atts == 0) atts = FILE_ATTRIBUTE_NORMAL; } switch (IrpSp->Parameters.QueryDirectory.FileInformationClass) { case FileBothDirectoryInformation: { FILE_BOTH_DIR_INFORMATION* fbdi = buf; TRACE("FileBothDirectoryInformation\n"); needed = sizeof(FILE_BOTH_DIR_INFORMATION) - sizeof(WCHAR) + de->name.Length; if (needed > *len) { TRACE("buffer overflow - %u > %u\n", needed, *len); return STATUS_BUFFER_OVERFLOW; } fbdi->NextEntryOffset = 0; fbdi->FileIndex = 0; fbdi->CreationTime.QuadPart = unix_time_to_win(&ii.otime); fbdi->LastAccessTime.QuadPart = unix_time_to_win(&ii.st_atime); fbdi->LastWriteTime.QuadPart = unix_time_to_win(&ii.st_mtime); fbdi->ChangeTime.QuadPart = unix_time_to_win(&ii.st_ctime); fbdi->EndOfFile.QuadPart = de->type == BTRFS_TYPE_SYMLINK ? 0 : ii.st_size; if (de->type == BTRFS_TYPE_SYMLINK) fbdi->AllocationSize.QuadPart = 0; else if (atts & FILE_ATTRIBUTE_SPARSE_FILE) fbdi->AllocationSize.QuadPart = ii.st_blocks; else fbdi->AllocationSize.QuadPart = sector_align(ii.st_size, fcb->Vcb->superblock.sector_size); fbdi->FileAttributes = atts; fbdi->FileNameLength = de->name.Length; fbdi->EaSize = (r && atts & FILE_ATTRIBUTE_REPARSE_POINT) ? get_reparse_tag(fcb->Vcb, r, inode, de->type, atts, ccb->lxss, Irp) : ealen; fbdi->ShortNameLength = 0; RtlCopyMemory(fbdi->FileName, de->name.Buffer, de->name.Length); *len -= needed; return STATUS_SUCCESS; } case FileDirectoryInformation: { FILE_DIRECTORY_INFORMATION* fdi = buf; TRACE("FileDirectoryInformation\n"); needed = sizeof(FILE_DIRECTORY_INFORMATION) - sizeof(WCHAR) + de->name.Length; if (needed > *len) { TRACE("buffer overflow - %u > %u\n", needed, *len); return STATUS_BUFFER_OVERFLOW; } fdi->NextEntryOffset = 0; fdi->FileIndex = 0; fdi->CreationTime.QuadPart = unix_time_to_win(&ii.otime); fdi->LastAccessTime.QuadPart = unix_time_to_win(&ii.st_atime); fdi->LastWriteTime.QuadPart = unix_time_to_win(&ii.st_mtime); fdi->ChangeTime.QuadPart = unix_time_to_win(&ii.st_ctime); fdi->EndOfFile.QuadPart = de->type == BTRFS_TYPE_SYMLINK ? 0 : ii.st_size; if (de->type == BTRFS_TYPE_SYMLINK) fdi->AllocationSize.QuadPart = 0; else if (atts & FILE_ATTRIBUTE_SPARSE_FILE) fdi->AllocationSize.QuadPart = ii.st_blocks; else fdi->AllocationSize.QuadPart = sector_align(ii.st_size, fcb->Vcb->superblock.sector_size); fdi->FileAttributes = atts; fdi->FileNameLength = de->name.Length; RtlCopyMemory(fdi->FileName, de->name.Buffer, de->name.Length); *len -= needed; return STATUS_SUCCESS; } case FileFullDirectoryInformation: { FILE_FULL_DIR_INFORMATION* ffdi = buf; TRACE("FileFullDirectoryInformation\n"); needed = sizeof(FILE_FULL_DIR_INFORMATION) - sizeof(WCHAR) + de->name.Length; if (needed > *len) { TRACE("buffer overflow - %u > %u\n", needed, *len); return STATUS_BUFFER_OVERFLOW; } ffdi->NextEntryOffset = 0; ffdi->FileIndex = 0; ffdi->CreationTime.QuadPart = unix_time_to_win(&ii.otime); ffdi->LastAccessTime.QuadPart = unix_time_to_win(&ii.st_atime); ffdi->LastWriteTime.QuadPart = unix_time_to_win(&ii.st_mtime); ffdi->ChangeTime.QuadPart = unix_time_to_win(&ii.st_ctime); ffdi->EndOfFile.QuadPart = de->type == BTRFS_TYPE_SYMLINK ? 0 : ii.st_size; if (de->type == BTRFS_TYPE_SYMLINK) ffdi->AllocationSize.QuadPart = 0; else if (atts & FILE_ATTRIBUTE_SPARSE_FILE) ffdi->AllocationSize.QuadPart = ii.st_blocks; else ffdi->AllocationSize.QuadPart = sector_align(ii.st_size, fcb->Vcb->superblock.sector_size); ffdi->FileAttributes = atts; ffdi->FileNameLength = de->name.Length; ffdi->EaSize = (r && atts & FILE_ATTRIBUTE_REPARSE_POINT) ? get_reparse_tag(fcb->Vcb, r, inode, de->type, atts, ccb->lxss, Irp) : ealen; RtlCopyMemory(ffdi->FileName, de->name.Buffer, de->name.Length); *len -= needed; return STATUS_SUCCESS; } case FileIdBothDirectoryInformation: { FILE_ID_BOTH_DIR_INFORMATION* fibdi = buf; TRACE("FileIdBothDirectoryInformation\n"); needed = sizeof(FILE_ID_BOTH_DIR_INFORMATION) - sizeof(WCHAR) + de->name.Length; if (needed > *len) { TRACE("buffer overflow - %u > %u\n", needed, *len); return STATUS_BUFFER_OVERFLOW; } fibdi->NextEntryOffset = 0; fibdi->FileIndex = 0; fibdi->CreationTime.QuadPart = unix_time_to_win(&ii.otime); fibdi->LastAccessTime.QuadPart = unix_time_to_win(&ii.st_atime); fibdi->LastWriteTime.QuadPart = unix_time_to_win(&ii.st_mtime); fibdi->ChangeTime.QuadPart = unix_time_to_win(&ii.st_ctime); fibdi->EndOfFile.QuadPart = de->type == BTRFS_TYPE_SYMLINK ? 0 : ii.st_size; if (de->type == BTRFS_TYPE_SYMLINK) fibdi->AllocationSize.QuadPart = 0; else if (atts & FILE_ATTRIBUTE_SPARSE_FILE) fibdi->AllocationSize.QuadPart = ii.st_blocks; else fibdi->AllocationSize.QuadPart = sector_align(ii.st_size, fcb->Vcb->superblock.sector_size); fibdi->FileAttributes = atts; fibdi->FileNameLength = de->name.Length; fibdi->EaSize = (r && atts & FILE_ATTRIBUTE_REPARSE_POINT) ? get_reparse_tag(fcb->Vcb, r, inode, de->type, atts, ccb->lxss, Irp) : ealen; fibdi->ShortNameLength = 0; fibdi->FileId.QuadPart = r ? make_file_id(r, inode) : make_file_id(fcb->Vcb->dummy_fcb->subvol, fcb->Vcb->dummy_fcb->inode); RtlCopyMemory(fibdi->FileName, de->name.Buffer, de->name.Length); *len -= needed; return STATUS_SUCCESS; } case FileIdFullDirectoryInformation: { FILE_ID_FULL_DIR_INFORMATION* fifdi = buf; TRACE("FileIdFullDirectoryInformation\n"); needed = sizeof(FILE_ID_FULL_DIR_INFORMATION) - sizeof(WCHAR) + de->name.Length; if (needed > *len) { TRACE("buffer overflow - %u > %u\n", needed, *len); return STATUS_BUFFER_OVERFLOW; } fifdi->NextEntryOffset = 0; fifdi->FileIndex = 0; fifdi->CreationTime.QuadPart = unix_time_to_win(&ii.otime); fifdi->LastAccessTime.QuadPart = unix_time_to_win(&ii.st_atime); fifdi->LastWriteTime.QuadPart = unix_time_to_win(&ii.st_mtime); fifdi->ChangeTime.QuadPart = unix_time_to_win(&ii.st_ctime); fifdi->EndOfFile.QuadPart = de->type == BTRFS_TYPE_SYMLINK ? 0 : ii.st_size; if (de->type == BTRFS_TYPE_SYMLINK) fifdi->AllocationSize.QuadPart = 0; else if (atts & FILE_ATTRIBUTE_SPARSE_FILE) fifdi->AllocationSize.QuadPart = ii.st_blocks; else fifdi->AllocationSize.QuadPart = sector_align(ii.st_size, fcb->Vcb->superblock.sector_size); fifdi->FileAttributes = atts; fifdi->FileNameLength = de->name.Length; fifdi->EaSize = (r && atts & FILE_ATTRIBUTE_REPARSE_POINT) ? get_reparse_tag(fcb->Vcb, r, inode, de->type, atts, ccb->lxss, Irp) : ealen; fifdi->FileId.QuadPart = r ? make_file_id(r, inode) : make_file_id(fcb->Vcb->dummy_fcb->subvol, fcb->Vcb->dummy_fcb->inode); RtlCopyMemory(fifdi->FileName, de->name.Buffer, de->name.Length); *len -= needed; return STATUS_SUCCESS; } case FileNamesInformation: { FILE_NAMES_INFORMATION* fni = buf; TRACE("FileNamesInformation\n"); needed = sizeof(FILE_NAMES_INFORMATION) - sizeof(WCHAR) + de->name.Length; if (needed > *len) { TRACE("buffer overflow - %u > %u\n", needed, *len); return STATUS_BUFFER_OVERFLOW; } fni->NextEntryOffset = 0; fni->FileIndex = 0; fni->FileNameLength = de->name.Length; RtlCopyMemory(fni->FileName, de->name.Buffer, de->name.Length); *len -= needed; return STATUS_SUCCESS; } case FileObjectIdInformation: FIXME("STUB: FileObjectIdInformation\n"); return STATUS_NOT_IMPLEMENTED; case FileQuotaInformation: FIXME("STUB: FileQuotaInformation\n"); return STATUS_NOT_IMPLEMENTED; case FileReparsePointInformation: FIXME("STUB: FileReparsePointInformation\n"); return STATUS_NOT_IMPLEMENTED; default: WARN("Unknown FileInformationClass %u\n", IrpSp->Parameters.QueryDirectory.FileInformationClass); return STATUS_NOT_IMPLEMENTED; } return STATUS_NO_MORE_FILES; }