From: Pierre Schweitzer Date: Fri, 27 May 2016 12:08:38 +0000 (+0000) Subject: [FFS] X-Git-Tag: ReactOS-0.4.2~533 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=3a3ef631d12d8ac7ee2a95abf8c1c6e4815ac1a5;ds=sidebyside [FFS] Import the FFS driver by Jae-Hong Lee. Patch by Peter Hater CORE-11040 svn path=/trunk/; revision=71425 --- diff --git a/reactos/drivers/filesystems/CMakeLists.txt b/reactos/drivers/filesystems/CMakeLists.txt index cd2549c8f29..ef6e644f571 100644 --- a/reactos/drivers/filesystems/CMakeLists.txt +++ b/reactos/drivers/filesystems/CMakeLists.txt @@ -4,6 +4,7 @@ add_subdirectory(cdfs) add_subdirectory(ext2) add_subdirectory(fastfat) #add_subdirectory(fastfat_new) +add_subdirectory(ffs) add_subdirectory(fs_rec) add_subdirectory(msfs) add_subdirectory(mup) diff --git a/reactos/drivers/filesystems/ffs/CMakeLists.txt b/reactos/drivers/filesystems/ffs/CMakeLists.txt new file mode 100644 index 00000000000..1f353f078be --- /dev/null +++ b/reactos/drivers/filesystems/ffs/CMakeLists.txt @@ -0,0 +1,48 @@ +include_directories(${REACTOS_SOURCE_DIR}/include/reactos/drivers + inc) + +list(APPEND SOURCE + src/block.c + src/cleanup.c + src/close.c + src/cmcb.c + src/create.c + src/debug.c + src/devctl.c + src/dirctl.c + src/dispatch.c + src/except.c + src/fastio.c + src/ffs.c + src/fileinfo.c + src/flush.c + src/fsctl.c + src/init.c + src/lock.c + src/memory.c + src/misc.c + src/pnp.c + src/read.c + src/shutdown.c + src/volinfo.c + src/write.c + inc/ffsdrv.h) + +add_library(ffs SHARED ${SOURCE} src/ffsdrv.rc) + +if(NOT MSVC) + add_target_compile_flags(ffs "-Wno-pointer-sign -Wno-unused-function") + if(NOT CMAKE_C_COMPILER_ID STREQUAL "Clang") + add_target_compile_flags(ffs "-Wno-unused-but-set-variable -Wno-unused-variable -Wno-missing-braces") + endif() +#else() +# replace_compile_flags("/we\"4189\"" " ") +endif() + +add_definitions(-D__KERNEL__) +set_module_type(ffs kernelmodedriver) +target_link_libraries(ffs memcmp ${PSEH_LIB}) +add_importlibs(ffs ntoskrnl hal) +add_pch(ffs inc/ffsdrv.h SOURCE) +add_cd_file(TARGET ffs DESTINATION reactos/system32/drivers NO_CAB FOR all) + diff --git a/reactos/drivers/filesystems/ffs/inc/bootblock.h b/reactos/drivers/filesystems/ffs/inc/bootblock.h new file mode 100644 index 00000000000..f6bf3e07585 --- /dev/null +++ b/reactos/drivers/filesystems/ffs/inc/bootblock.h @@ -0,0 +1,892 @@ +/* $NetBSD: bootblock.h,v 1.24 2004/03/22 07:11:00 lukem Exp $ */ + +/*- + * Copyright (c) 2002-2004 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/*- + * Copyright (C) 1993 Allen K. Briggs, Chris P. Caputo, + * Michael L. Finch, Bradley A. Grantham, and + * Lawrence A. Kesteloot + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Alice Group. + * 4. The names of the Alice Group or any of its members may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE ALICE GROUP ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE ALICE GROUP BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/* + * Copyright (c) 1994, 1999 Christopher G. Demetriou + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christopher G. Demetriou + * for the NetBSD Project. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * Copyright (c) 1994 Rolf Grossmann + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Rolf Grossmann. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SYS_BOOTBLOCK_H +#define _SYS_BOOTBLOCK_H + +#include "type.h" + +#if 0 /* XXX ffsdrv */ +#if !defined(__ASSEMBLER__) +#if defined(_KERNEL) || defined(_STANDALONE) +#include +#else +#include +#endif +#endif /* !defined(__ASSEMBLER__) */ +#endif + +/* ------------------------------------------ + * MBR (Master Boot Record) -- + * definitions for systems that use MBRs + */ + +/* + * Layout of boot records: + * + * Byte range Use Description + * ---------- --- ----------- + * + * 0 - 2 FMP JMP xxx, NOP + * 3 - 10 FP OEM Name + * + * 11 - 61 FMP FAT12/16 BPB + * Whilst not strictly necessary for MBR, + * GRUB reserves this area + * + * 11 - 89 P FAT32 BPB + * (are we ever going to boot off this?) + * + * + * 62 - 217 FMP Boot code + * + * 90 - 217 P FAT32 boot code + * + * 218 - 223 M Win95b/98/me "drive time" + * http://www.geocities.com/thestarman3/asm/mbr/95BMEMBR.htm#MYST + * only changed if all 6 bytes are 0 + * + * 224 - 436 FMP boot code (continued) + * + * 437 - 439 M WinNT/2K/XP MBR "boot language" + * http://www.geocities.com/thestarman3/asm/mbr/Win2kmbr.htm + * not needed by us + * + * 400 - 439 MP NetBSD: mbr_bootsel + * + * 440 - 443 M WinNT/2K/XP Drive Serial Number (NT DSN) + * http://www.geocities.com/thestarman3/asm/mbr/Win2kmbr.htm + * + * 444 - 445 FMP bootcode or unused + * NetBSD: mbr_bootsel_magic + * + * 446 - 509 M partition table + * + * 510 - 511 FMP magic number (0xAA55) + * + * Use: + * ---- + * F Floppy boot sector + * M Master Boot Record + * P Partition Boot record + * + */ + +/* + * MBR (Master Boot Record) + */ +#define MBR_BBSECTOR 0 /* MBR relative sector # */ +#define MBR_BPB_OFFSET 11 /* offsetof(mbr_sector, mbr_bpb) */ +#define MBR_BOOTCODE_OFFSET 90 /* offsetof(mbr_sector, mbr_bootcode) */ +#define MBR_BS_OFFSET 400 /* offsetof(mbr_sector, mbr_bootsel) */ +#define MBR_DSN_OFFSET 440 /* offsetof(mbr_sector, mbr_dsn) */ +#define MBR_BS_MAGIC_OFFSET 444 /* offsetof(mbr_sector, mbr_bootsel_magic) */ +#define MBR_PART_OFFSET 446 /* offsetof(mbr_sector, mbr_part[0]) */ +#define MBR_MAGIC_OFFSET 510 /* offsetof(mbr_sector, mbr_magic) */ +#define MBR_MAGIC 0xaa55 /* MBR magic number */ +#define MBR_BS_MAGIC 0xb5e1 /* mbr_bootsel magic number */ +#define MBR_PART_COUNT 4 /* Number of partitions in MBR */ +#define MBR_BS_PARTNAMESIZE 8 /* Size of name mbr_bootsel nametab */ + /* (excluding trailing NUL) */ + + /* values for mbr_partition.mbrp_flag */ +#define MBR_PFLAG_ACTIVE 0x80 /* The active partition */ + + /* values for mbr_partition.mbrp_type */ +#define MBR_PTYPE_FAT12 0x01 /* 12-bit FAT */ +#define MBR_PTYPE_FAT16S 0x04 /* 16-bit FAT, less than 32M */ +#define MBR_PTYPE_EXT 0x05 /* extended partition */ +#define MBR_PTYPE_FAT16B 0x06 /* 16-bit FAT, more than 32M */ +#define MBR_PTYPE_NTFS 0x07 /* OS/2 HPFS, NTFS, QNX2, Adv. UNIX */ +#define MBR_PTYPE_FAT32 0x0b /* 32-bit FAT */ +#define MBR_PTYPE_FAT32L 0x0c /* 32-bit FAT, LBA-mapped */ +#define MBR_PTYPE_FAT16L 0x0e /* 16-bit FAT, LBA-mapped */ +#define MBR_PTYPE_EXT_LBA 0x0f /* extended partition, LBA-mapped */ +#define MBR_PTYPE_ONTRACK 0x54 +#define MBR_PTYPE_LNXSWAP 0x82 /* Linux swap or Solaris */ +#define MBR_PTYPE_LNXEXT2 0x83 /* Linux native */ +#define MBR_PTYPE_EXT_LNX 0x85 /* Linux extended partition */ +#define MBR_PTYPE_NTFSVOL 0x87 /* NTFS volume set or HPFS mirrored */ +#define MBR_PTYPE_PREP 0x41 /* PReP */ +#define MBR_PTYPE_386BSD 0xa5 /* 386BSD partition type */ +#define MBR_PTYPE_APPLEUFS 0xa8 /* Apple UFS */ +#define MBR_PTYPE_NETBSD 0xa9 /* NetBSD partition type */ +#define MBR_PTYPE_OPENBSD 0xa6 /* OpenBSD partition type */ + +#define MBR_PSECT(s) ((s) & 0x3f) +#define MBR_PCYL(c, s) ((c) + (((s) & 0xc0) << 2)) + +#define MBR_IS_EXTENDED(x) ((x) == MBR_PTYPE_EXT || \ + (x) == MBR_PTYPE_EXT_LBA || \ + (x) == MBR_PTYPE_EXT_LNX) + + /* values for mbr_bootsel.mbrbs_flags */ +#define MBR_BS_ACTIVE 0x01 /* Bootselector active (or code present) */ +#define MBR_BS_EXTINT13 0x02 /* Set by fdisk if LBA needed (deprecated) */ +#define MBR_BS_READ_LBA 0x04 /* Force LBA reads - even for low numbers */ +#define MBR_BS_EXTLBA 0x08 /* Extended ptn capable (LBA reads) */ +#define MBR_BS_NEWMBR 0x80 /* New bootsel at offset 440 */ + +#if !defined(__ASSEMBLER__) /* { */ + +#pragma pack(1) + +/* + * (x86) BIOS Parameter Block for FAT12 + */ +struct mbr_bpbFAT12 { + uint16_t bpbBytesPerSec; /* bytes per sector */ + uint8_t bpbSecPerClust; /* sectors per cluster */ + uint16_t bpbResSectors; /* number of reserved sectors */ + uint8_t bpbFATs; /* number of FATs */ + uint16_t bpbRootDirEnts; /* number of root directory entries */ + uint16_t bpbSectors; /* total number of sectors */ + uint8_t bpbMedia; /* media descriptor */ + uint16_t bpbFATsecs; /* number of sectors per FAT */ + uint16_t bpbSecPerTrack; /* sectors per track */ + uint16_t bpbHeads; /* number of heads */ + uint16_t bpbHiddenSecs; /* # of hidden sectors */ +}; /* __attribute__((__packed__)); */ + +/* + * (x86) BIOS Parameter Block for FAT16 + */ +struct mbr_bpbFAT16 { + uint16_t bpbBytesPerSec; /* bytes per sector */ + uint8_t bpbSecPerClust; /* sectors per cluster */ + uint16_t bpbResSectors; /* number of reserved sectors */ + uint8_t bpbFATs; /* number of FATs */ + uint16_t bpbRootDirEnts; /* number of root directory entries */ + uint16_t bpbSectors; /* total number of sectors */ + uint8_t bpbMedia; /* media descriptor */ + uint16_t bpbFATsecs; /* number of sectors per FAT */ + uint16_t bpbSecPerTrack; /* sectors per track */ + uint16_t bpbHeads; /* number of heads */ + uint32_t bpbHiddenSecs; /* # of hidden sectors */ + uint32_t bpbHugeSectors; /* # of sectors if bpbSectors == 0 */ + uint8_t bsDrvNum; /* Int 0x13 drive number (e.g. 0x80) */ + uint8_t bsReserved1; /* Reserved; set to 0 */ + uint8_t bsBootSig; /* 0x29 if next 3 fields are present */ + uint8_t bsVolID[4]; /* Volume serial number */ + uint8_t bsVolLab[11]; /* Volume label */ + uint8_t bsFileSysType[8]; + /* "FAT12 ", "FAT16 ", "FAT " */ +}; /* __attribute__((__packed__)); */ + +/* + * (x86) BIOS Parameter Block for FAT32 + */ +struct mbr_bpbFAT32 { + uint16_t bpbBytesPerSec; /* bytes per sector */ + uint8_t bpbSecPerClust; /* sectors per cluster */ + uint16_t bpbResSectors; /* number of reserved sectors */ + uint8_t bpbFATs; /* number of FATs */ + uint16_t bpbRootDirEnts; /* number of root directory entries */ + uint16_t bpbSectors; /* total number of sectors */ + uint8_t bpbMedia; /* media descriptor */ + uint16_t bpbFATsecs; /* number of sectors per FAT */ + uint16_t bpbSecPerTrack; /* sectors per track */ + uint16_t bpbHeads; /* number of heads */ + uint32_t bpbHiddenSecs; /* # of hidden sectors */ + uint32_t bpbHugeSectors; /* # of sectors if bpbSectors == 0 */ + uint32_t bpbBigFATsecs; /* like bpbFATsecs for FAT32 */ + uint16_t bpbExtFlags; /* extended flags: */ +#define MBR_FAT32_FATNUM 0x0F /* mask for numbering active FAT */ +#define MBR_FAT32_FATMIRROR 0x80 /* FAT is mirrored (as previously) */ + uint16_t bpbFSVers; /* filesystem version */ +#define MBR_FAT32_FSVERS 0 /* currently only 0 is understood */ + uint32_t bpbRootClust; /* start cluster for root directory */ + uint16_t bpbFSInfo; /* filesystem info structure sector */ + uint16_t bpbBackup; /* backup boot sector */ + uint8_t bsReserved[12]; /* Reserved for future expansion */ + uint8_t bsDrvNum; /* Int 0x13 drive number (e.g. 0x80) */ + uint8_t bsReserved1; /* Reserved; set to 0 */ + uint8_t bsBootSig; /* 0x29 if next 3 fields are present */ + uint8_t bsVolID[4]; /* Volume serial number */ + uint8_t bsVolLab[11]; /* Volume label */ + uint8_t bsFileSysType[8]; /* "FAT32 " */ +}; /* __attribute__((__packed__)); */ + +/* + * (x86) MBR boot selector + */ +struct mbr_bootsel { + uint8_t mbrbs_defkey; + uint8_t mbrbs_flags; + uint16_t mbrbs_timeo; + uint8_t mbrbs_nametab[MBR_PART_COUNT][MBR_BS_PARTNAMESIZE + 1]; +}; /* __attribute__((__packed__)); */ + +/* + * MBR partition + */ +struct mbr_partition { + uint8_t mbrp_flag; /* MBR partition flags */ + uint8_t mbrp_shd; /* Starting head */ + uint8_t mbrp_ssect; /* Starting sector */ + uint8_t mbrp_scyl; /* Starting cylinder */ + uint8_t mbrp_type; /* Partition type (see below) */ + uint8_t mbrp_ehd; /* End head */ + uint8_t mbrp_esect; /* End sector */ + uint8_t mbrp_ecyl; /* End cylinder */ + uint32_t mbrp_start; /* Absolute starting sector number */ + uint32_t mbrp_size; /* Partition size in sectors */ +}; /* __attribute__((__packed__)); */ + +int xlat_mbr_fstype(int); /* in sys/lib/libkern/xlat_mbr_fstype.c */ + +/* + * MBR boot sector. + * This is used by both the MBR (Master Boot Record) in sector 0 of the disk + * and the PBR (Partition Boot Record) in sector 0 of an MBR partition. + */ +struct mbr_sector { + /* Jump instruction to boot code. */ + /* Usually 0xE9nnnn or 0xEBnn90 */ + uint8_t mbr_jmpboot[3]; + /* OEM name and version */ + uint8_t mbr_oemname[8]; + union { /* BIOS Parameter Block */ + struct mbr_bpbFAT12 bpb12; + struct mbr_bpbFAT16 bpb16; + struct mbr_bpbFAT32 bpb32; + } mbr_bpb; + /* Boot code */ + uint8_t mbr_bootcode[310]; + /* Config for /usr/mdec/mbr_bootsel */ + struct mbr_bootsel mbr_bootsel; + /* NT Drive Serial Number */ + uint32_t mbr_dsn; + /* mbr_bootsel magic */ + uint16_t mbr_bootsel_magic; + /* MBR partition table */ + struct mbr_partition mbr_parts[MBR_PART_COUNT]; + /* MBR magic (0xaa55) */ + uint16_t mbr_magic; +}; /* __attribute__((__packed__)); */ + +#endif /* !defined(__ASSEMBLER__) */ /* } */ + +#pragma pack() + + +/* ------------------------------------------ + * shared -- + * definitions shared by many platforms + */ + +#if !defined(__ASSEMBLER__) /* { */ + + /* Maximum # of blocks in bbi_block_table, each bbi_block_size long */ +#define SHARED_BBINFO_MAXBLOCKS 118 /* so sizeof(shared_bbinfo) == 512 */ + +struct shared_bbinfo { + uint8_t bbi_magic[32]; + int32_t bbi_block_size; + int32_t bbi_block_count; + int32_t bbi_block_table[SHARED_BBINFO_MAXBLOCKS]; +}; + +#if 0 /* XXX ffsdrv */ + +/* ------------------------------------------ + * alpha -- + * Alpha (disk, but also tape) Boot Block. + * + * See Section (III) 3.6.1 of the Alpha Architecture Reference Manual. + */ + +struct alpha_boot_block { + uint64_t bb_data[63]; /* data (disklabel, also as below) */ + uint64_t bb_cksum; /* checksum of the boot block, + * taken as uint64_t's + */ +}; +#define bb_secsize bb_data[60] /* secondary size (blocks) */ +#define bb_secstart bb_data[61] /* secondary start (blocks) */ +#define bb_flags bb_data[62] /* unknown flags (set to zero) */ + +#define ALPHA_BOOT_BLOCK_OFFSET 0 /* offset of boot block. */ +#define ALPHA_BOOT_BLOCK_BLOCKSIZE 512 /* block size for sector + * size/start, and for boot + * block itself. + */ + +#define ALPHA_BOOT_BLOCK_CKSUM(bb,cksum) \ + do { \ + const struct alpha_boot_block *_bb = (bb); \ + uint64_t _cksum; \ + int _i; \ + \ + _cksum = 0; \ + for (_i = 0; \ + _i < (sizeof _bb->bb_data / sizeof _bb->bb_data[0]); \ + _i++) \ + _cksum += _bb->bb_data[_i]; \ + *(cksum) = _cksum; \ + } while (/*CONSTCOND*/ 0) + +/* ------------------------------------------ + * apple -- + * Apple computers boot block related information + */ + +/* + * Driver Descriptor Map, from Inside Macintosh: Devices, SCSI Manager + * pp 12-13. The driver descriptor map always resides on physical block 0. + */ +struct apple_drvr_descriptor { + uint32_t descBlock; /* first block of driver */ + uint16_t descSize; /* driver size in blocks */ + uint16_t descType; /* system type */ +}; + +/* + * system types; Apple reserves 0-15 + */ +#define APPLE_DRVR_TYPE_MACINTOSH 1 + +#define APPLE_DRVR_MAP_MAGIC 0x4552 +#define APPLE_DRVR_MAP_MAX_DESCRIPTORS 61 + +struct apple_drvr_map { + uint16_t sbSig; /* map signature */ + uint16_t sbBlockSize; /* block size of device */ + uint32_t sbBlkCount; /* number of blocks on device */ + uint16_t sbDevType; /* (used internally by ROM) */ + uint16_t sbDevID; /* (used internally by ROM) */ + uint32_t sbData; /* (used internally by ROM) */ + uint16_t sbDrvrCount; /* number of driver descriptors */ + struct apple_drvr_descriptor sb_dd[APPLE_DRVR_MAP_MAX_DESCRIPTORS]; + uint16_t pad[3]; +} __attribute__((__packed__)); + +/* + * Partition map structure from Inside Macintosh: Devices, SCSI Manager + * pp. 13-14. The partition map always begins on physical block 1. + * + * With the exception of block 0, all blocks on the disk must belong to + * exactly one partition. The partition map itself belongs to a partition + * of type `APPLE_PARTITION_MAP', and is not limited in size by anything + * other than available disk space. The partition map is not necessarily + * the first partition listed. + */ +#define APPLE_PART_MAP_ENTRY_MAGIC 0x504d + +struct apple_part_map_entry { + uint16_t pmSig; /* partition signature */ + uint16_t pmSigPad; /* (reserved) */ + uint32_t pmMapBlkCnt; /* number of blocks in partition map */ + uint32_t pmPyPartStart; /* first physical block of partition */ + uint32_t pmPartBlkCnt; /* number of blocks in partition */ + uint8_t pmPartName[32]; /* partition name */ + uint8_t pmPartType[32]; /* partition type */ + uint32_t pmLgDataStart; /* first logical block of data area */ + uint32_t pmDataCnt; /* number of blocks in data area */ + uint32_t pmPartStatus; /* partition status information */ + uint32_t pmLgBootStart; /* first logical block of boot code */ + uint32_t pmBootSize; /* size of boot code, in bytes */ + uint32_t pmBootLoad; /* boot code load address */ + uint32_t pmBootLoad2; /* (reserved) */ + uint32_t pmBootEntry; /* boot code entry point */ + uint32_t pmBootEntry2; /* (reserved) */ + uint32_t pmBootCksum; /* boot code checksum */ + int8_t pmProcessor[16]; /* processor type (e.g. "68020") */ + uint8_t pmBootArgs[128]; /* A/UX boot arguments */ + uint8_t pad[248]; /* pad to end of block */ +}; + +#define APPLE_PART_TYPE_DRIVER "APPLE_DRIVER" +#define APPLE_PART_TYPE_DRIVER43 "APPLE_DRIVER43" +#define APPLE_PART_TYPE_DRIVERATA "APPLE_DRIVER_ATA" +#define APPLE_PART_TYPE_DRIVERIOKIT "APPLE_DRIVER_IOKIT" +#define APPLE_PART_TYPE_FWDRIVER "APPLE_FWDRIVER" +#define APPLE_PART_TYPE_FWB_COMPONENT "FWB DRIVER COMPONENTS" +#define APPLE_PART_TYPE_FREE "APPLE_FREE" +#define APPLE_PART_TYPE_MAC "APPLE_HFS" +#define APPLE_PART_TYPE_NETBSD "NETBSD" +#define APPLE_PART_TYPE_NBSD_PPCBOOT "NETBSD/MACPPC" +#define APPLE_PART_TYPE_NBSD_68KBOOT "NETBSD/MAC68K" +#define APPLE_PART_TYPE_PATCHES "APPLE_PATCHES" +#define APPLE_PART_TYPE_PARTMAP "APPLE_PARTITION_MAP" +#define APPLE_PART_TYPE_PATCHES "APPLE_PATCHES" +#define APPLE_PART_TYPE_SCRATCH "APPLE_SCRATCH" +#define APPLE_PART_TYPE_UNIX "APPLE_UNIX_SVR2" + +/* + * "pmBootArgs" for APPLE_UNIX_SVR2 partition. + * NetBSD/mac68k only uses Magic, Cluster, Type, and Flags. + */ +struct apple_blockzeroblock { + uint32_t bzbMagic; + uint8_t bzbCluster; + uint8_t bzbType; + uint16_t bzbBadBlockInode; + uint16_t bzbFlags; + uint16_t bzbReserved; + uint32_t bzbCreationTime; + uint32_t bzbMountTime; + uint32_t bzbUMountTime; +}; + +#define APPLE_BZB_MAGIC 0xABADBABE +#define APPLE_BZB_TYPEFS 1 +#define APPLE_BZB_TYPESWAP 3 +#define APPLE_BZB_ROOTFS 0x8000 +#define APPLE_BZB_USRFS 0x4000 + +/* ------------------------------------------ + * hp300 + * + */ + +/* volume header for "LIF" format volumes */ + +struct hp300_lifvol { + int16_t vol_id; + char vol_label[6]; + int32_t vol_addr; + int16_t vol_oct; + int16_t vol_dummy; + int32_t vol_dirsize; + int16_t vol_version; + int16_t vol_zero; + int32_t vol_huh1; + int32_t vol_huh2; + int32_t vol_length; +}; + +/* LIF directory entry format */ + +struct hp300_lifdir { + char dir_name[10]; + int16_t dir_type; + int32_t dir_addr; + int32_t dir_length; + char dir_toc[6]; + int16_t dir_flag; + int32_t dir_exec; +}; + +/* load header for boot rom */ +struct hp300_load { + int32_t address; + int32_t count; +}; + +#define HP300_VOL_ID -32768 +#define HP300_VOL_OCT 4096 +#define HP300_DIR_TYPE -5822 +#define HP300_DIR_FLAG 0x8001 /* dont ask me! */ +#define HP300_SECTSIZE 256 + +#endif + +/* ------------------------------------------ + * x86 + * + */ + +/* + * Parameters for NetBSD /boot written to start of pbr code by installboot + */ + +struct x86_boot_params { + uint32_t bp_length; /* length of patchable data */ + uint32_t bp_flags; + uint32_t bp_timeout; /* boot timeout in seconds */ + uint32_t bp_consdev; + uint32_t bp_conspeed; + uint8_t bp_password[16]; /* md5 hash of password */ + char bp_keymap[16]; /* keyboard traslation map */ +}; + +#endif /* !defined(__ASSEMBLER__) */ /* } */ + +#define X86_BOOT_MAGIC(n) ('x' << 24 | 0x86b << 12 | 'm' << 4 | (n)) +#define X86_BOOT_MAGIC_1 X86_BOOT_MAGIC(1) /* pbr.S */ +#define X86_BOOT_MAGIC_2 X86_BOOT_MAGIC(2) /* bootxx.S */ +#define X86_BOOT_MAGIC_PXE X86_BOOT_MAGIC(3) /* start_pxe.S */ + + /* values for bp_flags */ +#define X86_BP_FLAGS_RESET_VIDEO 1 +#define X86_BP_FLAGS_PASSWORD 2 + + /* values for bp_consdev */ +#define X86_BP_CONSDEV_PC 0 +#define X86_BP_CONSDEV_COM0 1 +#define X86_BP_CONSDEV_COM1 2 +#define X86_BP_CONSDEV_COM2 3 +#define X86_BP_CONSDEV_COM3 4 +#define X86_BP_CONSDEV_COM0KBD 5 +#define X86_BP_CONSDEV_COM1KBD 6 +#define X86_BP_CONSDEV_COM2KBD 7 +#define X86_BP_CONSDEV_COM3KBD 8 + +#if !defined(__ASSEMBLER__) /* { */ + +#if 0 /* XXX ffsdrv */ +/* ------------------------------------------ + * macppc + */ + +#define MACPPC_BOOT_BLOCK_OFFSET 2048 +#define MACPPC_BOOT_BLOCK_BLOCKSIZE 512 +#define MACPPC_BOOT_BLOCK_MAX_SIZE 2048 /* XXX: could be up to 6144 */ + /* Magic string -- 32 bytes long (including the NUL) */ +#define MACPPC_BBINFO_MAGIC "NetBSD/macppc bootxx 20020515" + +/* ------------------------------------------ + * news68k, newsmips + */ + +#define NEWS_BOOT_BLOCK_LABELOFFSET 64 /* XXX from */ +#define NEWS_BOOT_BLOCK_OFFSET 0 +#define NEWS_BOOT_BLOCK_BLOCKSIZE 512 +#define NEWS_BOOT_BLOCK_MAX_SIZE (512 * 16) + + /* Magic string -- 32 bytes long (including the NUL) */ +#define NEWS68K_BBINFO_MAGIC "NetBSD/news68k bootxx 20020518" +#define NEWSMIPS_BBINFO_MAGIC "NetBSD/newsmips bootxx 20020518" + +/* ------------------------------------------ + * next68k + */ + +#define NEXT68K_LABEL_MAXPARTITIONS 8 /* number of partitions in next68k_disklabel */ +#define NEXT68K_LABEL_CPULBLLEN 24 +#define NEXT68K_LABEL_MAXDNMLEN 24 +#define NEXT68K_LABEL_MAXTYPLEN 24 +#define NEXT68K_LABEL_MAXBFLEN 24 +#define NEXT68K_LABEL_MAXHNLEN 32 +#define NEXT68K_LABEL_MAXMPTLEN 16 +#define NEXT68K_LABEL_MAXFSTLEN 8 +#define NEXT68K_LABEL_NBAD 1670 /* sized to make label ~= 8KB */ + +struct next68k_partition { + int32_t cp_offset; /* starting sector */ + int32_t cp_size; /* number of sectors in partition */ + int16_t cp_bsize; /* block size in bytes */ + int16_t cp_fsize; /* filesystem basic fragment size */ + char cp_opt; /* optimization type: 's'pace/'t'ime */ + char cp_pad1; + int16_t cp_cpg; /* filesystem cylinders per group */ + int16_t cp_density; /* bytes per inode density */ + int8_t cp_minfree; /* minfree (%) */ + int8_t cp_newfs; /* run newfs during init */ + char cp_mountpt[NEXT68K_LABEL_MAXMPTLEN]; + /* default/standard mount point */ + int8_t cp_automnt; /* auto-mount when inserted */ + char cp_type[NEXT68K_LABEL_MAXFSTLEN]; /* file system type name */ + char cp_pad2; +} __attribute__ ((packed)); + +/* The disklabel the way it is on the disk */ +struct next68k_disklabel { + int32_t cd_version; /* label version */ + int32_t cd_label_blkno; /* block # of this label */ + int32_t cd_size; /* size of media area (sectors) */ + char cd_label[NEXT68K_LABEL_CPULBLLEN]; /* disk name (label) */ + uint32_t cd_flags; /* flags */ + uint32_t cd_tag; /* volume tag */ + char cd_name[NEXT68K_LABEL_MAXDNMLEN]; /* drive (hardware) name */ + char cd_type[NEXT68K_LABEL_MAXTYPLEN]; /* drive type */ + int32_t cd_secsize; /* # of bytes per sector */ + int32_t cd_ntracks; /* # of tracks per cylinder */ + int32_t cd_nsectors; /* # of data sectors per track */ + int32_t cd_ncylinders; /* # of data cylinders per unit */ + int32_t cd_rpm; /* rotational speed */ + int16_t cd_front; /* # of sectors in "front porch" */ + int16_t cd_back; /* # of sectors in "back porch" */ + int16_t cd_ngroups; /* # of alt groups */ + int16_t cd_ag_size; /* alt group size (sectors) */ + int16_t cd_ag_alts; /* alternate sectors / alt group */ + int16_t cd_ag_off; /* sector offset to first alternate */ + int32_t cd_boot_blkno[2]; /* boot program locations */ + char cd_kernel[NEXT68K_LABEL_MAXBFLEN]; /* default kernel name */ + char cd_hostname[NEXT68K_LABEL_MAXHNLEN]; + /* host name (usu. where disk was labeled) */ + char cd_rootpartition; /* root partition letter e.g. 'a' */ + char cd_rwpartition; /* r/w partition letter e.g. 'b' */ + struct next68k_partition cd_partitions[NEXT68K_LABEL_MAXPARTITIONS]; + + union { + uint16_t CD_v3_checksum; /* label version 3 checksum */ + int32_t CD_bad[NEXT68K_LABEL_NBAD]; + /* block number that is bad */ + } cd_un; + uint16_t cd_checksum; /* label version 1 or 2 checksum */ +} __attribute__ ((packed)); + +#define NEXT68K_LABEL_cd_checksum cd_checksum +#define NEXT68K_LABEL_cd_v3_checksum cd_un.CD_v3_checksum +#define NEXT68K_LABEL_cd_bad cd_un.CD_bad + +#define NEXT68K_LABEL_SECTOR 0 /* sector containing label */ +#define NEXT68K_LABEL_OFFSET 0 /* offset of label in sector */ +#define NEXT68K_LABEL_SIZE 8192 /* size of label */ +#define NEXT68K_LABEL_CD_V1 0x4e655854 /* version #1: "NeXT" */ +#define NEXT68K_LABEL_CD_V2 0x646c5632 /* version #2: "dlV2" */ +#define NEXT68K_LABEL_CD_V3 0x646c5633 /* version #3: "dlV3" */ +#define NEXT68K_LABEL_DEFAULTFRONTPORCH (160 * 2) +#define NEXT68K_LABEL_DEFAULTBOOT0_1 (32 * 2) +#define NEXT68K_LABEL_DEFAULTBOOT0_2 (96 * 2) + +/* ------------------------------------------ + * pmax -- + * PMAX (DECstation / MIPS) boot block information + */ + +/* + * If mode is 0, there is just one sequence of blocks and one Dec_BootMap + * is used. If mode is 1, there are multiple sequences of blocks + * and multiple Dec_BootMaps are used, the last with numBlocks = 0. + */ +struct pmax_boot_map { + int32_t num_blocks; /* Number of blocks to read. */ + int32_t start_block; /* Starting block on disk. */ +}; + +/* + * This is the structure of a disk or tape boot block. The boot_map + * can either be a single boot count and start block (contiguous mode) + * or a list of up to 61 (to fill a 512 byte sector) block count and + * start block pairs. Under NetBSD, contiguous mode is always used. + */ +struct pmax_boot_block { + uint8_t pad[8]; + int32_t magic; /* PMAX_BOOT_MAGIC */ + int32_t mode; /* Mode for boot info. */ + uint32_t load_addr; /* Address to start loading. */ + uint32_t exec_addr; /* Address to start execing. */ + struct pmax_boot_map map[61]; /* boot program section(s). */ +} __attribute__((__packed__)); + +#define PMAX_BOOT_MAGIC 0x0002757a +#define PMAX_BOOTMODE_CONTIGUOUS 0 +#define PMAX_BOOTMODE_SCATTERED 1 + +#define PMAX_BOOT_BLOCK_OFFSET 0 +#define PMAX_BOOT_BLOCK_BLOCKSIZE 512 + + +/* ------------------------------------------ + * sparc + */ + +#define SPARC_BOOT_BLOCK_OFFSET 512 +#define SPARC_BOOT_BLOCK_BLOCKSIZE 512 +#define SPARC_BOOT_BLOCK_MAX_SIZE (512 * 15) + /* Magic string -- 32 bytes long (including the NUL) */ +#define SPARC_BBINFO_MAGIC "NetBSD/sparc bootxx 20020515" + + +/* ------------------------------------------ + * sparc64 + */ + +#define SPARC64_BOOT_BLOCK_OFFSET 512 +#define SPARC64_BOOT_BLOCK_BLOCKSIZE 512 +#define SPARC64_BOOT_BLOCK_MAX_SIZE (512 * 15) + + +/* ------------------------------------------ + * sun68k (sun2, sun3) + */ + +#define SUN68K_BOOT_BLOCK_OFFSET 512 +#define SUN68K_BOOT_BLOCK_BLOCKSIZE 512 +#define SUN68K_BOOT_BLOCK_MAX_SIZE (512 * 15) + /* Magic string -- 32 bytes long (including the NUL) */ +#define SUN68K_BBINFO_MAGIC "NetBSD/sun68k bootxx 20020515" + + +/* ------------------------------------------ + * vax -- + * VAX boot block information + */ + +struct vax_boot_block { +/* Note that these don't overlap any of the pmax boot block */ + uint8_t pad0[2]; + uint8_t bb_id_offset; /* offset in words to id (magic1)*/ + uint8_t bb_mbone; /* must be one */ + uint16_t bb_lbn_hi; /* lbn (hi word) of bootstrap */ + uint16_t bb_lbn_low; /* lbn (low word) of bootstrap */ + uint8_t pad1[332]; + + /* The rest of these fields are identification area and describe + * the secondary block for uVAX VMB. + */ + uint8_t bb_magic1; /* magic number */ + uint8_t bb_mbz1; /* must be zero */ + uint8_t bb_pad1; /* any value */ + uint8_t bb_sum1; /* ~(magic1 + mbz1 + pad1) */ + + uint8_t bb_mbz2; /* must be zero */ + uint8_t bb_volinfo; /* volinfo */ + uint8_t bb_pad2a; /* any value */ + uint8_t bb_pad2b; /* any value */ + + uint32_t bb_size; /* size in blocks of bootstrap */ + uint32_t bb_load; /* load offset to bootstrap */ + uint32_t bb_entry; /* byte offset in bootstrap */ + uint32_t bb_sum3; /* sum of previous 3 fields */ + + /* The rest is unused. + */ + uint8_t pad2[148]; +} __attribute__((__packed__)); + +#define VAX_BOOT_MAGIC1 0x18 /* size of BB info? */ +#define VAX_BOOT_VOLINFO_NONE 0x00 /* no special info */ +#define VAX_BOOT_VOLINFO_SS 0x01 /* single sided */ +#define VAX_BOOT_VOLINFO_DS 0x81 /* double sided */ + +#define VAX_BOOT_SIZE 15 /* 15 blocks */ +#define VAX_BOOT_LOAD 0 /* no load offset */ +#define VAX_BOOT_ENTRY 0x200 /* one block in */ + +#define VAX_BOOT_BLOCK_OFFSET 0 +#define VAX_BOOT_BLOCK_BLOCKSIZE 512 + + +/* ------------------------------------------ + * x68k + */ + +#define X68K_BOOT_BLOCK_OFFSET 0 +#define X68K_BOOT_BLOCK_BLOCKSIZE 512 +#define X68K_BOOT_BLOCK_MAX_SIZE (512 * 16) + /* Magic string -- 32 bytes long (including the NUL) */ +#define X68K_BBINFO_MAGIC "NetBSD/x68k bootxx 20020601" + +#endif /* !defined(__ASSEMBLER__) */ /* } */ + +#endif + +#endif /* !_SYS_BOOTBLOCK_H */ diff --git a/reactos/drivers/filesystems/ffs/inc/dinode.h b/reactos/drivers/filesystems/ffs/inc/dinode.h new file mode 100644 index 00000000000..3b87eb5b485 --- /dev/null +++ b/reactos/drivers/filesystems/ffs/inc/dinode.h @@ -0,0 +1,177 @@ +/* $NetBSD: dinode.h,v 1.18 2003/08/07 16:34:42 agc Exp $ */ + +/* + * Copyright (c) 2002 Networks Associates Technology, Inc. + * All rights reserved. + * + * This software was developed for the FreeBSD Project by Marshall + * Kirk McKusick and Network Associates Laboratories, the Security + * Research Division of Network Associates, Inc. under DARPA/SPAWAR + * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS + * research program + * + * Copyright (c) 1982, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)dinode.h 8.9 (Berkeley) 3/29/95 + */ + +#ifndef _UFS_UFS_DINODE_H_ +#define _UFS_UFS_DINODE_H_ + +#include "type.h" + +/* + * The root inode is the root of the file system. Inode 0 can't be used for + * normal purposes and historically bad blocks were linked to inode 1, thus + * the root inode is 2. (Inode 1 is no longer used for this purpose, however + * numerous dump tapes make this assumption, so we are stuck with it). + */ +#define ROOTINO ((ino_t)2) + +/* + * The Whiteout inode# is a dummy non-zero inode number which will + * never be allocated to a real file. It is used as a place holder + * in the directory entry which has been tagged as a DT_W entry. + * See the comments about ROOTINO above. + */ +#define WINO ((ino_t)1) + +/* + * A dinode contains all the meta-data associated with a UFS file. + * This structure defines the on-disk format of a dinode. Since + * this structure describes an on-disk structure, all its fields + * are defined by types with precise widths. + */ + +#define NXADDR 2 +#define NDADDR 12 /* Direct addresses in inode. */ +#define NIADDR 3 /* Indirect addresses in inode. */ + +struct ufs1_dinode { + u_int16_t di_mode; /* 0: IFMT, permissions; see below. */ + int16_t di_nlink; /* 2: File link count. */ + union { + u_int16_t oldids[2]; /* 4: Ffs: old user and group ids. */ + u_int32_t inumber; /* 4: Lfs: inode number. */ + } di_u; + u_int64_t di_size; /* 8: File byte count. */ + int32_t di_atime; /* 16: Last access time. */ + int32_t di_atimensec; /* 20: Last access time. */ + int32_t di_mtime; /* 24: Last modified time. */ + int32_t di_mtimensec; /* 28: Last modified time. */ + int32_t di_ctime; /* 32: Last inode change time. */ + int32_t di_ctimensec; /* 36: Last inode change time. */ + int32_t di_db[NDADDR]; /* 40: Direct disk blocks. */ + int32_t di_ib[NIADDR]; /* 88: Indirect disk blocks. */ + u_int32_t di_flags; /* 100: Status flags (chflags). */ + u_int32_t di_blocks; /* 104: Blocks actually held. */ + int32_t di_gen; /* 108: Generation number. */ + u_int32_t di_uid; /* 112: File owner. */ + u_int32_t di_gid; /* 116: File group. */ + int32_t di_spare[2]; /* 120: Reserved; currently unused */ +}; + +struct ufs2_dinode { + u_int16_t di_mode; /* 0: IFMT, permissions; see below. */ + int16_t di_nlink; /* 2: File link count. */ + u_int32_t di_uid; /* 4: File owner. */ + u_int32_t di_gid; /* 8: File group. */ + u_int32_t di_blksize; /* 12: Inode blocksize. */ + u_int64_t di_size; /* 16: File byte count. */ + u_int64_t di_blocks; /* 24: Bytes actually held. */ + int64_t di_atime; /* 32: Last access time. */ + int64_t di_mtime; /* 40: Last modified time. */ + int64_t di_ctime; /* 48: Last inode change time. */ + int64_t di_birthtime; /* 56: Inode creation time. */ + int32_t di_mtimensec; /* 64: Last modified time. */ + int32_t di_atimensec; /* 68: Last access time. */ + int32_t di_ctimensec; /* 72: Last inode change time. */ + int32_t di_birthnsec; /* 76: Inode creation time. */ + int32_t di_gen; /* 80: Generation number. */ + u_int32_t di_kernflags; /* 84: Kernel flags. */ + u_int32_t di_flags; /* 88: Status flags (chflags). */ + int32_t di_extsize; /* 92: External attributes block. */ + int64_t di_extb[NXADDR];/* 96: External attributes block. */ + int64_t di_db[NDADDR]; /* 112: Direct disk blocks. */ + int64_t di_ib[NIADDR]; /* 208: Indirect disk blocks. */ + int64_t di_spare[3]; /* 232: Reserved; currently unused */ +}; + +/* + * The di_db fields may be overlaid with other information for + * file types that do not have associated disk storage. Block + * and character devices overlay the first data block with their + * dev_t value. Short symbolic links place their path in the + * di_db area. + */ +#define di_inumber di_u.inumber +#define di_ogid di_u.oldids[1] +#define di_ouid di_u.oldids[0] +#define di_rdev di_db[0] +#define MAXSYMLINKLEN_UFS1 ((NDADDR + NIADDR) * sizeof(int32_t)) +#define MAXSYMLINKLEN_UFS2 ((NDADDR + NIADDR) * sizeof(int64_t)) + +#define MAXSYMLINKLEN(ip) \ + ((ip)->i_ump->um_fstype == UFS1) ? \ + MAXSYMLINKLEN_UFS1 : MAXSYMLINKLEN_UFS2 + +/* NeXT used to keep short symlinks in the inode even when using + * FS_42INODEFMT. In that case fs->fs_maxsymlinklen is probably -1, + * but short symlinks were stored in inodes shorter than this: + */ +#define APPLEUFS_MAXSYMLINKLEN 60 + +/* File permissions. */ +#define IEXEC 0000100 /* Executable. */ +#define IWRITE 0000200 /* Writable. */ +#define IREAD 0000400 /* Readable. */ +#define ISVTX 0001000 /* Sticky bit. */ +#define ISGID 0002000 /* Set-gid. */ +#define ISUID 0004000 /* Set-uid. */ + +/* File types. */ +#define IFMT 0170000 /* Mask of file type. */ +#define IFIFO 0010000 /* Named pipe (fifo). */ +#define IFCHR 0020000 /* Character device. */ +#define IFDIR 0040000 /* Directory file. */ +#define IFBLK 0060000 /* Block device. */ +#define IFREG 0100000 /* Regular file. */ +#define IFLNK 0120000 /* Symbolic link. */ +#define IFSOCK 0140000 /* UNIX domain socket. */ +#define IFWHT 0160000 /* Whiteout. */ + +/* Size of the on-disk inode. */ +#define DINODE1_SIZE (sizeof(struct ufs1_dinode)) /* 128 */ +#define DINODE2_SIZE (sizeof(struct ufs2_dinode)) + +#endif /* !_UFS_UFS_DINODE_H_ */ diff --git a/reactos/drivers/filesystems/ffs/inc/dir.h b/reactos/drivers/filesystems/ffs/inc/dir.h new file mode 100644 index 00000000000..53b5034cfbe --- /dev/null +++ b/reactos/drivers/filesystems/ffs/inc/dir.h @@ -0,0 +1,162 @@ +/* $NetBSD: dir.h,v 1.17 2003/08/07 16:34:42 agc Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)dir.h 8.5 (Berkeley) 4/27/95 + */ + +#ifndef _UFS_UFS_DIR_H_ +#define _UFS_UFS_DIR_H_ + +#include "type.h" + +/* + * Theoretically, directories can be more than 2Gb in length, however, in + * practice this seems unlikely. So, we define the type doff_t as a 32-bit + * quantity to keep down the cost of doing lookup on a 32-bit machine. + */ +#define doff_t int32_t +#define MAXDIRSIZE (0x7fffffff) + +/* + * A directory consists of some number of blocks of DIRBLKSIZ + * bytes, where DIRBLKSIZ is chosen such that it can be transferred + * to disk in a single atomic operation (e.g. 512 bytes on most machines). + * + * Each DIRBLKSIZ byte block contains some number of directory entry + * structures, which are of variable length. Each directory entry has + * a struct direct at the front of it, containing its inode number, + * the length of the entry, and the length of the name contained in + * the entry. These are followed by the name padded to a 4 byte boundary. + * All names are guaranteed null terminated. + * The maximum length of a name in a directory is MAXNAMLEN. + * + * The macro DIRSIZ(fmt, dp) gives the amount of space required to represent + * a directory entry. Free space in a directory is represented by + * entries which have dp->d_reclen > DIRSIZ(fmt, dp). All DIRBLKSIZ bytes + * in a directory block are claimed by the directory entries. This + * usually results in the last entry in a directory having a large + * dp->d_reclen. When entries are deleted from a directory, the + * space is returned to the previous entry in the same directory + * block by increasing its dp->d_reclen. If the first entry of + * a directory block is free, then its dp->d_ino is set to 0. + * Entries other than the first in a directory do not normally have + * dp->d_ino set to 0. + */ +#undef DIRBLKSIZ +#define DIRBLKSIZ DEV_BSIZE +#undef MAXNAMLEN +#define MAXNAMLEN 255 +#define APPLEUFS_DIRBLKSIZ 1024 + +struct direct { + u_int32_t d_ino; /* inode number of entry */ + u_int16_t d_reclen; /* length of this record */ + u_int8_t d_type; /* file type, see below */ + u_int8_t d_namlen; /* length of string in d_name */ + char d_name[MAXNAMLEN + 1];/* name with length <= MAXNAMLEN */ +}; + +/* + * File types + */ +#define DT_UNKNOWN 0 +#define DT_FIFO 1 +#define DT_CHR 2 +#define DT_DIR 4 +#define DT_BLK 6 +#define DT_REG 8 +#define DT_LNK 10 +#define DT_SOCK 12 +#define DT_WHT 14 + +/* + * Convert between stat structure types and directory types. + */ +#define IFTODT(mode) (((mode) & 0170000) >> 12) +#define DTTOIF(dirtype) ((dirtype) << 12) + +/* + * The DIRSIZ macro gives the minimum record length which will hold + * the directory entry. This requires the amount of space in struct direct + * without the d_name field, plus enough space for the name with a terminating + * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary. + */ +#define DIRECTSIZ(namlen) \ + ((sizeof(struct direct) - (MAXNAMLEN+1)) + (((namlen)+1 + 3) &~ 3)) + +#if (BYTE_ORDER == LITTLE_ENDIAN) +#define DIRSIZ(oldfmt, dp, needswap) \ + (((oldfmt) && !(needswap)) ? \ + DIRECTSIZ((dp)->d_type) : DIRECTSIZ((dp)->d_namlen)) +#else +#define DIRSIZ(oldfmt, dp, needswap) \ + (((oldfmt) && (needswap)) ? \ + DIRECTSIZ((dp)->d_type) : DIRECTSIZ((dp)->d_namlen)) +#endif + +#define OLDDIRFMT 1 +#define NEWDIRFMT 0 + +/* + * Template for manipulating directories. Should use struct direct's, + * but the name field is MAXNAMLEN - 1, and this just won't do. + */ +struct dirtemplate { + u_int32_t dot_ino; + int16_t dot_reclen; + u_int8_t dot_type; + u_int8_t dot_namlen; + char dot_name[4]; /* must be multiple of 4 */ + u_int32_t dotdot_ino; + int16_t dotdot_reclen; + u_int8_t dotdot_type; + u_int8_t dotdot_namlen; + char dotdot_name[4]; /* ditto */ +}; + +/* + * This is the old format of directories, sanz type element. + */ +struct odirtemplate { + u_int32_t dot_ino; + int16_t dot_reclen; + u_int16_t dot_namlen; + char dot_name[4]; /* must be multiple of 4 */ + u_int32_t dotdot_ino; + int16_t dotdot_reclen; + u_int16_t dotdot_namlen; + char dotdot_name[4]; /* ditto */ +}; +#endif /* !_UFS_UFS_DIR_H_ */ diff --git a/reactos/drivers/filesystems/ffs/inc/disklabel.h b/reactos/drivers/filesystems/ffs/inc/disklabel.h new file mode 100644 index 00000000000..f7d7a376e86 --- /dev/null +++ b/reactos/drivers/filesystems/ffs/inc/disklabel.h @@ -0,0 +1,555 @@ +/* $NetBSD: disklabel.h,v 1.88 2003/11/14 12:07:42 lukem Exp $ */ + +/* + * Copyright (c) 1987, 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)disklabel.h 8.2 (Berkeley) 7/10/94 + */ + +#ifndef _SYS_DISKLABEL_H_ +#define _SYS_DISKLABEL_H_ + +#include "type.h" + +/* + * We need for __HAVE_OLD_DISKLABEL + */ +#if 0 /* XXX ffsdrv */ +#ifndef _LOCORE +#include +#endif +#endif + +/* sys/arch/i386/include/type.h XXX ffsdrv */ +#define __HAVE_OLD_DISKLABEL + +/* + * Each disk has a label which includes information about the hardware + * disk geometry, filesystem partitions, and drive specific information. + * The location of the label, as well as the number of partitions the + * label can describe and the number of the "whole disk" (raw) + * paritition are machine dependent. + */ +#if 0 /* XXX ffsdrv */ +#include +#endif + +/* arch/i386/include/disklabel.h */ +#define LABELSECTOR 1 /* sector containing label */ +#define LABELOFFSET 0 /* offset of label in sector */ +#define MAXPARTITIONS 16 /* number of partitions */ +#define OLDMAXPARTITIONS 8 /* number of partitions before 1.6 */ +#define RAW_PART 3 /* raw partition: XX?d (XXX) */ + +/* + * We use the highest bit of the minor number for the partition number. + * This maintains backward compatibility with device nodes created before + * MAXPARTITIONS was increased. + */ +#define __I386_MAXDISKS ((1 << 20) / MAXPARTITIONS) +#define DISKUNIT(dev) ((minor(dev) / OLDMAXPARTITIONS) % __I386_MAXDISKS) +#define DISKPART(dev) ((minor(dev) % OLDMAXPARTITIONS) + \ + ((minor(dev) / (__I386_MAXDISKS * OLDMAXPARTITIONS)) * OLDMAXPARTITIONS)) +#define DISKMINOR(unit, part) \ + (((unit) * OLDMAXPARTITIONS) + ((part) % OLDMAXPARTITIONS) + \ + ((part) / OLDMAXPARTITIONS) * (__I386_MAXDISKS * OLDMAXPARTITIONS)) + +/* Pull in MBR partition definitions. */ +#include "bootblock.h" + +/* end of arch/i386/include/disklabel.h */ + + +/* + * The absolute maximum number of disk partitions allowed. + * This is the maximum value of MAXPARTITIONS for which 'struct disklabel' + * is <= DEV_BSIZE bytes long. If MAXPARTITIONS is greater than this, beware. + */ +#define MAXMAXPARTITIONS 22 +#if MAXPARTITIONS > MAXMAXPARTITIONS +#warning beware: MAXPARTITIONS bigger than MAXMAXPARTITIONS +#endif + +/* + * Ports can switch their MAXPARTITIONS once, as follows: + * + * - define OLDMAXPARTITIONS in as the old number + * - define MAXPARTITIONS as the new number + * - define DISKUNIT, DISKPART and DISKMINOR macros in + * as appropriate for the port (see the i386 one for an example). + * - define __HAVE_OLD_DISKLABEL in + */ + +#if defined(_KERNEL) && defined(__HAVE_OLD_DISKLABEL) && \ + (MAXPARTITIONS < OLDMAXPARTITIONS) +#error "can only grow disklabel size" +#endif + + +/* + * Translate between device numbers and major/disk unit/disk partition. + */ +#ifndef __HAVE_OLD_DISKLABEL +#define DISKUNIT(dev) (minor(dev) / MAXPARTITIONS) +#define DISKPART(dev) (minor(dev) % MAXPARTITIONS) +#define DISKMINOR(unit, part) \ + (((unit) * MAXPARTITIONS) + (part)) +#endif +#define MAKEDISKDEV(maj, unit, part) \ + (makedev((maj), DISKMINOR((unit), (part)))) + +#define DISKMAGIC ((u_int32_t)0x82564557) /* The disk magic number */ + +#ifndef _LOCORE +struct disklabel { + u_int32_t d_magic; /* the magic number */ + u_int16_t d_type; /* drive type */ + u_int16_t d_subtype; /* controller/d_type specific */ + char d_typename[16]; /* type name, e.g. "eagle" */ + + /* + * d_packname contains the pack identifier and is returned when + * the disklabel is read off the disk or in-core copy. + * d_boot0 and d_boot1 are the (optional) names of the + * primary (block 0) and secondary (block 1-15) bootstraps + * as found in /usr/mdec. These are returned when using + * getdiskbyname(3) to retrieve the values from /etc/disktab. + */ + union { + char un_d_packname[16]; /* pack identifier */ + struct { + char *un_d_boot0; /* primary bootstrap name */ + char *un_d_boot1; /* secondary bootstrap name */ + } un_b; + } d_un; +#define d_packname d_un.un_d_packname +#define d_boot0 d_un.un_b.un_d_boot0 +#define d_boot1 d_un.un_b.un_d_boot1 + + /* disk geometry: */ + u_int32_t d_secsize; /* # of bytes per sector */ + u_int32_t d_nsectors; /* # of data sectors per track */ + u_int32_t d_ntracks; /* # of tracks per cylinder */ + u_int32_t d_ncylinders; /* # of data cylinders per unit */ + u_int32_t d_secpercyl; /* # of data sectors per cylinder */ + u_int32_t d_secperunit; /* # of data sectors per unit */ + + /* + * Spares (bad sector replacements) below are not counted in + * d_nsectors or d_secpercyl. Spare sectors are assumed to + * be physical sectors which occupy space at the end of each + * track and/or cylinder. + */ + u_int16_t d_sparespertrack; /* # of spare sectors per track */ + u_int16_t d_sparespercyl; /* # of spare sectors per cylinder */ + /* + * Alternative cylinders include maintenance, replacement, + * configuration description areas, etc. + */ + u_int32_t d_acylinders; /* # of alt. cylinders per unit */ + + /* hardware characteristics: */ + /* + * d_interleave, d_trackskew and d_cylskew describe perturbations + * in the media format used to compensate for a slow controller. + * Interleave is physical sector interleave, set up by the + * formatter or controller when formatting. When interleaving is + * in use, logically adjacent sectors are not physically + * contiguous, but instead are separated by some number of + * sectors. It is specified as the ratio of physical sectors + * traversed per logical sector. Thus an interleave of 1:1 + * implies contiguous layout, while 2:1 implies that logical + * sector 0 is separated by one sector from logical sector 1. + * d_trackskew is the offset of sector 0 on track N relative to + * sector 0 on track N-1 on the same cylinder. Finally, d_cylskew + * is the offset of sector 0 on cylinder N relative to sector 0 + * on cylinder N-1. + */ + u_int16_t d_rpm; /* rotational speed */ + u_int16_t d_interleave; /* hardware sector interleave */ + u_int16_t d_trackskew; /* sector 0 skew, per track */ + u_int16_t d_cylskew; /* sector 0 skew, per cylinder */ + u_int32_t d_headswitch; /* head switch time, usec */ + u_int32_t d_trkseek; /* track-to-track seek, usec */ + u_int32_t d_flags; /* generic flags */ +#define NDDATA 5 + u_int32_t d_drivedata[NDDATA]; /* drive-type specific information */ +#define NSPARE 5 + u_int32_t d_spare[NSPARE]; /* reserved for future use */ + u_int32_t d_magic2; /* the magic number (again) */ + u_int16_t d_checksum; /* xor of data incl. partitions */ + + /* filesystem and partition information: */ + u_int16_t d_npartitions; /* number of partitions in following */ + u_int32_t d_bbsize; /* size of boot area at sn0, bytes */ + u_int32_t d_sbsize; /* max size of fs superblock, bytes */ + struct partition { /* the partition table */ + u_int32_t p_size; /* number of sectors in partition */ + u_int32_t p_offset; /* starting sector */ + union { + u_int32_t fsize; /* FFS, ADOS: + filesystem basic fragment size */ + u_int32_t cdsession; /* ISO9660: session offset */ + } __partition_u2; +#define p_fsize __partition_u2.fsize +#define p_cdsession __partition_u2.cdsession + u_int8_t p_fstype; /* filesystem type, see below */ + u_int8_t p_frag; /* filesystem fragments per block */ + union { + u_int16_t cpg; /* UFS: FS cylinders per group */ + u_int16_t sgs; /* LFS: FS segment shift */ + } __partition_u1; +#define p_cpg __partition_u1.cpg +#define p_sgs __partition_u1.sgs + } d_partitions[MAXPARTITIONS]; /* actually may be more */ +}; + +#ifdef __HAVE_OLD_DISKLABEL +/* + * Same as above, but with OLDMAXPARTITIONS partitions. For use in + * the old DIOC* ioctl calls. + */ +struct olddisklabel { + u_int32_t d_magic; + u_int16_t d_type; + u_int16_t d_subtype; + char d_typename[16]; + union { + char un_d_packname[16]; + struct { + char *un_d_boot0; + char *un_d_boot1; + } un_b; + } d_un; + u_int32_t d_secsize; + u_int32_t d_nsectors; + u_int32_t d_ntracks; + u_int32_t d_ncylinders; + u_int32_t d_secpercyl; + u_int32_t d_secperunit; + u_int16_t d_sparespertrack; + u_int16_t d_sparespercyl; + u_int32_t d_acylinders; + u_int16_t d_rpm; + u_int16_t d_interleave; + u_int16_t d_trackskew; + u_int16_t d_cylskew; + u_int32_t d_headswitch; + u_int32_t d_trkseek; + u_int32_t d_flags; + u_int32_t d_drivedata[NDDATA]; + u_int32_t d_spare[NSPARE]; + u_int32_t d_magic2; + u_int16_t d_checksum; + u_int16_t d_npartitions; + u_int32_t d_bbsize; + u_int32_t d_sbsize; + struct opartition { + u_int32_t p_size; + u_int32_t p_offset; + union { + u_int32_t fsize; + u_int32_t cdsession; + } __partition_u2; + u_int8_t p_fstype; + u_int8_t p_frag; + union { + u_int16_t cpg; + u_int16_t sgs; + } __partition_u1; + } d_partitions[OLDMAXPARTITIONS]; +}; +#endif /* __HAVE_OLD_DISKLABEL */ +#else /* _LOCORE */ + /* + * offsets for asm boot files. + */ + .set d_secsize,40 + .set d_nsectors,44 + .set d_ntracks,48 + .set d_ncylinders,52 + .set d_secpercyl,56 + .set d_secperunit,60 + .set d_end_,276 /* size of disk label */ +#endif /* _LOCORE */ + +/* d_type values: */ +#define DTYPE_SMD 1 /* SMD, XSMD; VAX hp/up */ +#define DTYPE_MSCP 2 /* MSCP */ +#define DTYPE_DEC 3 /* other DEC (rk, rl) */ +#define DTYPE_SCSI 4 /* SCSI */ +#define DTYPE_ESDI 5 /* ESDI interface */ +#define DTYPE_ST506 6 /* ST506 etc. */ +#define DTYPE_HPIB 7 /* CS/80 on HP-IB */ +#define DTYPE_HPFL 8 /* HP Fiber-link */ +#define DTYPE_FLOPPY 10 /* floppy */ +#define DTYPE_CCD 11 /* concatenated disk device */ +#define DTYPE_VND 12 /* vnode pseudo-disk */ +#define DTYPE_ATAPI 13 /* ATAPI */ +#define DTYPE_RAID 14 /* RAIDframe */ +#define DTYPE_LD 15 /* logical disk */ +#define DTYPE_JFS2 16 /* IBM JFS2 */ +#define DTYPE_CGD 17 /* cryptographic pseudo-disk */ +#define DTYPE_VINUM 18 /* vinum volume */ + +#ifdef DKTYPENAMES +static const char *const dktypenames[] = { + "unknown", + "SMD", + "MSCP", + "old DEC", + "SCSI", + "ESDI", + "ST506", + "HP-IB", + "HP-FL", + "type 9", + "floppy", + "ccd", + "vnd", + "ATAPI", + "RAID", + "ld", + "jfs", + "cgd", + "vinum", + NULL +}; +#define DKMAXTYPES (sizeof(dktypenames) / sizeof(dktypenames[0]) - 1) +#endif + +/* + * Filesystem type and version. + * Used to interpret other filesystem-specific + * per-partition information. + * + * These are used only for COMPAT_09 support. + */ +#define FS_UNUSED 0 /* unused */ +#define FS_SWAP 1 /* swap */ +#define FS_V6 2 /* Sixth Edition */ +#define FS_V7 3 /* Seventh Edition */ +#define FS_SYSV 4 /* System V */ +#define FS_V71K 5 /* V7 with 1K blocks (4.1, 2.9) */ +#define FS_V8 6 /* Eighth Edition, 4K blocks */ +#define FS_BSDFFS 7 /* 4.2BSD fast file system */ +#define FS_MSDOS 8 /* MSDOS file system */ +#define FS_BSDLFS 9 /* 4.4BSD log-structured file system */ +#define FS_OTHER 10 /* in use, but unknown/unsupported */ +#define FS_HPFS 11 /* OS/2 high-performance file system */ +#define FS_ISO9660 12 /* ISO 9660, normally CD-ROM */ +#define FS_BOOT 13 /* partition contains bootstrap */ +#define FS_ADOS 14 /* AmigaDOS fast file system */ +#define FS_HFS 15 /* Macintosh HFS */ +#define FS_FILECORE 16 /* Acorn Filecore Filing System */ +#define FS_EX2FS 17 /* Linux Extended 2 file system */ +#define FS_NTFS 18 /* Windows/NT file system */ +#define FS_RAID 19 /* RAIDframe component */ +#define FS_CCD 20 /* concatenated disk component */ +#define FS_JFS2 21 /* IBM JFS2 */ +#define FS_APPLEUFS 22 /* Apple UFS */ +/* XXX this is not the same as FreeBSD. How to solve? */ +#define FS_VINUM 23 /* Vinum */ + +/* Adjust the FSMAXTYPES def below if you add something after APPLEUFS */ + +#ifdef FSTYPENAMES +static const char *const fstypenames[] = { + "unused", + "swap", + "Version 6", + "Version 7", + "System V", + "4.1BSD", + "Eighth Edition", + "4.2BSD", + "MSDOS", + "4.4LFS", + "unknown", + "HPFS", + "ISO9660", + "boot", + "ADOS", + "HFS", + "FILECORE", + "Linux Ext2", + "NTFS", + "RAID", + "ccd", + "jfs", + "Apple UFS", + "vinum", + NULL +}; +#define FSMAXTYPES (sizeof(fstypenames) / sizeof(fstypenames[0]) - 1) +#else +#define FSMAXTYPES (FS_VINUM + 1) +#endif + +#ifdef FSCKNAMES +/* These are the names MOUNT_XXX from */ +static const char *const fscknames[] = { + NULL, /* unused */ + NULL, /* swap */ + NULL, /* Version 6 */ + NULL, /* Version 7 */ + NULL, /* System V */ + NULL, /* 4.1BSD */ + NULL, /* Eighth edition */ + "ffs", /* 4.2BSD */ + "msdos", /* MSDOS */ + "lfs", /* 4.4LFS */ + NULL, /* unknown */ + NULL, /* HPFS */ + NULL, /* ISO9660 */ + NULL, /* boot */ + NULL, /* ADOS */ + NULL, /* HFS */ + NULL, /* FILECORE */ + "ext2fs", /* Linux Ext2 */ + NULL, /* Windows/NT */ + NULL, /* RAID Component */ + NULL, /* concatenated disk component */ + NULL, /* IBM JFS2 */ + "ffs", /* Apple UFS */ + NULL /* NULL */ +}; +#define FSMAXNAMES (sizeof(fscknames) / sizeof(fscknames[0]) - 1) + +#endif + +#ifdef MOUNTNAMES +/* These are the names MOUNT_XXX from */ +static const char *const mountnames[] = { + NULL, /* unused */ + NULL, /* swap */ + NULL, /* Version 6 */ + NULL, /* Version 7 */ + NULL, /* System V */ + NULL, /* 4.1BSD */ + NULL, /* Eighth edition */ + "ffs", /* 4.2BSD */ + "msdos", /* MSDOS */ + "lfs", /* 4.4LFS */ + NULL, /* unknown */ + NULL, /* HPFS */ + "cd9660", /* ISO9660 */ + NULL, /* boot */ + "ados", /* ADOS */ + NULL, /* HFS */ + "filecore", /* FILECORE */ + "ext2fs", /* Linux Ext2 */ + "ntfs", /* Windows/NT */ + NULL, /* RAID Component */ + NULL, /* concatenated disk component */ + NULL, /* IBM JFS2 */ + "ffs", /* Apple UFS */ + NULL /* NULL */ +}; +#define FSMAXMOUNTNAMES (sizeof(mountnames) / sizeof(mountnames[0]) - 1) + +#endif + +/* + * flags shared by various drives: + */ +#define D_REMOVABLE 0x01 /* removable media */ +#define D_ECC 0x02 /* supports ECC */ +#define D_BADSECT 0x04 /* supports bad sector forw. */ +#define D_RAMDISK 0x08 /* disk emulator */ +#define D_CHAIN 0x10 /* can do back-back transfers */ + +/* + * Drive data for SMD. + */ +#define d_smdflags d_drivedata[0] +#define D_SSE 0x1 /* supports skip sectoring */ +#define d_mindist d_drivedata[1] +#define d_maxdist d_drivedata[2] +#define d_sdist d_drivedata[3] + +/* + * Drive data for ST506. + */ +#define d_precompcyl d_drivedata[0] +#define d_gap3 d_drivedata[1] /* used only when formatting */ + +/* + * Drive data for SCSI. + */ +#define d_blind d_drivedata[0] + +#ifndef _LOCORE +/* + * Structure used to perform a format or other raw operation, + * returning data and/or register values. Register identification + * and format are device- and driver-dependent. Currently unused. + */ +struct format_op { + char *df_buf; + int df_count; /* value-result */ + daddr_t df_startblk; + int df_reg[8]; /* result */ +}; + +/* + * Structure used internally to retrieve information about a partition + * on a disk. + */ +struct partinfo { + struct disklabel *disklab; + struct partition *part; +}; + +#ifdef _KERNEL + +struct disk; + +void diskerr __P((const struct buf *, const char *, const char *, int, + int, const struct disklabel *)); +u_int dkcksum __P((struct disklabel *)); +int setdisklabel __P((struct disklabel *, struct disklabel *, u_long, + struct cpu_disklabel *)); +const char *readdisklabel __P((dev_t, void (*)(struct buf *), + struct disklabel *, struct cpu_disklabel *)); +int writedisklabel __P((dev_t, void (*)(struct buf *), struct disklabel *, + struct cpu_disklabel *)); +int bounds_check_with_label __P((struct disk *, struct buf *, int)); +int bounds_check_with_mediasize __P((struct buf *, int, u_int64_t)); +#endif +#endif /* _LOCORE */ + +#if !defined(_KERNEL) && !defined(_LOCORE) + +#if 0 /* XXX ffsdrv */ +#include +#endif + +#endif + +#endif /* !_SYS_DISKLABEL_H_ */ diff --git a/reactos/drivers/filesystems/ffs/inc/ffsdrv.h b/reactos/drivers/filesystems/ffs/inc/ffsdrv.h new file mode 100644 index 00000000000..41d395d373f --- /dev/null +++ b/reactos/drivers/filesystems/ffs/inc/ffsdrv.h @@ -0,0 +1,2178 @@ +/* + * FFS File System Driver for Windows + * + * ffsdrv.h + * + * 2004.5.6 ~ + * + * Lee Jae-Hong, http://www.pyrasis.com + * + */ + +#ifndef _FFS_HEADER_ +#define _FFS_HEADER_ + +/* include files */ +#ifdef __REACTOS__ +#include +#include +#include +#include +#endif +#include "fs.h" +#include "dinode.h" +#include "dir.h" +#include "disklabel.h" +#ifndef __REACTOS__ +#include +#endif + +#ifndef _PREFAST_ +#ifdef _MSC_VER +#pragma warning(disable:4068) +#endif +#define __drv_mustHoldCriticalRegion +#endif // !_PREFAST_ + +#pragma pack(1) + +/* debug */ +#if DBG + #define FFSBreakPoint() /*__asm int 3*/ //DbgBreakPoint() +#else + #define FFSBreakPoint() +#endif + +/* Structs & Consts */ + +#define FFSDRV_VERSION "0.5.2" + +/* + * ffsdrv build options + */ + +/* To build read-only driver */ + +#define FFS_READ_ONLY TRUE + + +/* To support driver dynamics unload */ + +#define FFS_UNLOAD TRUE + +/* + * Constants + */ + +#define FFS_BLOCK_TYPES (0x04) + +#define MAXIMUM_RECORD_LENGTH (0x10000) + +#define SECTOR_BITS (Vcb->SectorBits) +#define SECTOR_SIZE (Vcb->DiskGeometry.BytesPerSector) +#define DEFAULT_SECTOR_SIZE (0x200) + +#define SUPER_BLOCK_OFFSET (0x2000) +#define SUPER_BLOCK_SIZE SBLOCKSIZE + +#define READ_AHEAD_GRANULARITY (0x10000) + +#define SUPER_BLOCK (Vcb->ffs_super_block) +#define FS_VERSION (Vcb->FSVersion) + +#define BLOCK_SIZE (Vcb->BlockSize) +#define BLOCK_BITS FFSLog2(Vcb->BlockSize) + +#define INODES_COUNT (Vcb->ffs_super_block->s_inodes_count) + +#define INODES_PER_GROUP (SUPER_BLOCK->fs_ipg) +#define BLOCKS_PER_GROUP (SUPER_BLOCK->fs_fpg) +#define TOTAL_BLOCKS (SUPER_BLOCK->fs_size) + + + +/* File System Releated */ + +#define DRIVER_NAME "FFS" +#ifndef __REACTOS__ +#define DEVICE_NAME L"\\FileSystem\\FFS" +#else +#define DEVICE_NAME L"\\FFS" +#endif + +/* Registry */ + +#define PARAMETERS_KEY L"\\Parameters" + +#define WRITING_SUPPORT L"WritingSupport" +#define CHECKING_BITMAP L"CheckingBitmap" +#define PARTITION_NUMBER L"PartitionNumber" + +/* To support select BSD partition and ffsdrv unload routine */ +#define DOS_DEVICE_NAME L"\\DosDevices\\ffs" + +/* + * Private IOCTL to make the driver ready to unload + */ +#if FFS_UNLOAD +#define IOCTL_PREPARE_TO_UNLOAD \ +CTL_CODE(FILE_DEVICE_UNKNOWN, 2048, METHOD_NEITHER, FILE_WRITE_ACCESS) +#endif // FFS_UNLOAD + +/* + * Private IOCTL to select BSD partition. + */ +#define IOCTL_SELECT_BSD_PARTITION \ +CTL_CODE(FILE_DEVICE_UNKNOWN, 2049, METHOD_BUFFERED, FILE_WRITE_ACCESS) + + +#ifndef SetFlag +#define SetFlag(x,f) ((x) |= (f)) +#endif + +#ifndef ClearFlag +#define ClearFlag(x,f) ((x) &= ~(f)) +#endif + +#define IsFlagOn(a,b) ((BOOLEAN)(FlagOn(a,b) == b)) + +#define FFSRaiseStatus(IRPCONTEXT,STATUS) { \ + (IRPCONTEXT)->ExceptionCode = (STATUS); \ + ExRaiseStatus( (STATUS) ); \ +} + +#define FFSNormalizeAndRaiseStatus(IRPCONTEXT,STATUS) { \ + /* (IRPCONTEXT)->ExceptionStatus = (STATUS); */ \ + if ((STATUS) == STATUS_VERIFY_REQUIRED) { ExRaiseStatus((STATUS)); } \ + ExRaiseStatus(FsRtlNormalizeNtstatus((STATUS),STATUS_UNEXPECTED_IO_ERROR)); \ +} + +/* + * Define IsEndofFile for read and write operations + */ + +#define FILE_WRITE_TO_END_OF_FILE 0xffffffff +#define FILE_USE_FILE_POINTER_POSITION 0xfffffffe + +#define IsEndOfFile(Pos) ((Pos.LowPart == FILE_WRITE_TO_END_OF_FILE) && \ + (Pos.HighPart == FILE_USE_FILE_POINTER_POSITION )) + +#define IsDirectory(Fcb) IsFlagOn(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY) + +/* + * Bug Check Codes Definitions + */ + +#define FFS_FILE_SYSTEM (FILE_SYSTEM) + +#define FFS_BUGCHK_BLOCK (0x00010000) +#define FFS_BUGCHK_CLEANUP (0x00020000) +#define FFS_BUGCHK_CLOSE (0x00030000) +#define FFS_BUGCHK_CMCB (0x00040000) +#define FFS_BUGCHK_CREATE (0x00050000) +#define FFS_BUGCHK_DEBUG (0x00060000) +#define FFS_BUGCHK_DEVCTL (0x00070000) +#define FFS_BUGCHK_DIRCTL (0x00080000) +#define FFS_BUGCHK_DISPATCH (0x00090000) +#define FFS_BUGCHK_EXCEPT (0x000A0000) +#define FFS_BUGCHK_FFS (0x000B0000) +#define FFS_BUGCHK_FASTIO (0x000C0000) +#define FFS_BUGCHK_FILEINFO (0x000D0000) +#define FFS_BUGCHK_FLUSH (0x000E0000) +#define FFS_BUGCHK_FSCTL (0x000F0000) +#define FFS_BUGCHK_INIT (0x00100000) +#define FFS_BUGCHK_LOCK (0x0011000) +#define FFS_BUGCHK_MEMORY (0x0012000) +#define FFS_BUGCHK_MISC (0x0013000) +#define FFS_BUGCHK_READ (0x00140000) +#define FFS_BUGCHK_SHUTDOWN (0x00150000) +#define FFS_BUGCHK_VOLINFO (0x00160000) +#define FFS_BUGCHK_WRITE (0x00170000) + +#define FFS_BUGCHK_LAST (0x00170000) + +#define FFSBugCheck(A,B,C,D) { KeBugCheckEx(FFS_FILE_SYSTEM, A | __LINE__, B, C, D ); } + + +/* FFS file system definions */ + +/* + * Structure of a directory entry + */ +#define FFS_NAME_LEN 255 + +#define FFS_ROOT_INO 2 /* Root inode */ + + +/* + * FFS_DIR_PAD defines the directory entries boundaries + * + * NOTE: It must be a multiple of 4 + */ +#define FFS_DIR_PAD 4 +#define FFS_DIR_ROUND (FFS_DIR_PAD - 1) +#define FFS_DIR_REC_LEN(name_len) (((name_len) + 8 + FFS_DIR_ROUND) & \ + ~FFS_DIR_ROUND) + + +/* sys/sys/stat.h */ + +#define S_ISDIR(m) ((m & _S_IFMT) == _S_IFDIR) /* directory */ +#define S_ISCHR(m) ((m & _S_IFMT) == _S_IFCHR) /* char special */ +#define S_ISBLK(m) ((m & _S_IFMT) == _S_IFBLK) /* block special */ +#define S_ISREG(m) ((m & _S_IFMT) == _S_IFREG) /* regular file */ +#define S_ISFIFO(m) ((m & _S_IFMT) == _S_IFIFO) /* fifo */ +#define S_ISLNK(m) ((m & _S_IFMT) == _S_IFLNK) /* symbolic link */ +#define S_ISSOCK(m) ((m & _S_IFMT) == _S_IFSOCK) /* socket */ +#define S_ISWHT(m) ((m & _S_IFMT) == _S_IFWHT) /* whiteout */ + + +#define S_IPERMISSION_MASK 0x1FF /* */ + +#define S_IRWXU 0000700 /* RWX mask for owner */ +#define S_IRUSR 0000400 /* R for owner */ +#define S_IWUSR 0000200 /* W for owner */ +#define S_IXUSR 0000100 /* X for owner */ + +#define S_IRWXG 0000070 /* RWX mask for group */ +#define S_IRGRP 0000040 /* R for group */ +#define S_IWGRP 0000020 /* W for group */ +#define S_IXGRP 0000010 /* X for group */ + +#define S_IRWXO 0000007 /* RWX mask for other */ +#define S_IROTH 0000004 /* R for other */ +#define S_IWOTH 0000002 /* W for other */ +#define S_IXOTH 0000001 /* X for other */ + +#define S_ISREADABLE(m) (((m) & S_IPERMISSION_MASK) == (S_IRUSR | S_IRGRP | S_IROTH)) +#define S_ISWRITABLE(m) (((m) & S_IPERMISSION_MASK) == (S_IWUSR | S_IWGRP | S_IWOTH)) + +#define FFSSetReadable(m) (m) = ((m) | (S_IRUSR | S_IRGRP | S_IROTH)) +#define FFSSetWritable(m) (m) = ((m) | (S_IWUSR | S_IWGRP | S_IWOTH)) + +#define FFSSetReadOnly(m) (m) = ((m) & (~(S_IWUSR | S_IWGRP | S_IWOTH))) +#define FFSIsReadOnly(m) (!((m) & (S_IWUSR | S_IWGRP | S_IWOTH))) + +#define FFS_FIRST_DATA_BLOCK (Vcb->ffs_super_block->fs_dblkno) + +typedef struct fs FFS_SUPER_BLOCK, *PFFS_SUPER_BLOCK; + +typedef struct disklabel DISKLABEL, *PDISKLABEL; + +typedef struct ufs1_dinode FFSv1_INODE, *PFFSv1_INODE; +typedef struct ufs2_dinode FFSv2_INODE, *PFFSv2_INODE; + +typedef struct direct FFS_DIR_ENTRY, *PFFS_DIR_ENTRY; + + +/* + * ffsdrv Driver Definitions + */ + +/* + * FFS_IDENTIFIER_TYPE + * + * Identifiers used to mark the structures + */ + +typedef enum _FFS_IDENTIFIER_TYPE { + FFSFGD = ':DGF', + FFSVCB = ':BCV', + FFSFCB = ':BCF', + FFSCCB = ':BCC', + FFSICX = ':XCI', + FFSDRV = ':VRD', + FFSMCB = ':BCM' +} FFS_IDENTIFIER_TYPE; + +/* + * FFS_IDENTIFIER + * + * Header used to mark the structures + */ +typedef struct _FFS_IDENTIFIER { + FFS_IDENTIFIER_TYPE Type; + ULONG Size; +} FFS_IDENTIFIER, *PFFS_IDENTIFIER; + + +#define NodeType(Ptr) (*((FFS_IDENTIFIER_TYPE *)(Ptr))) + +typedef struct _FFS_MCB FFS_MCB, *PFFS_MCB; + + +typedef PVOID PBCB; + +/* + * REPINNED_BCBS List + */ + +#define FFS_REPINNED_BCBS_ARRAY_SIZE (8) + +typedef struct _FFS_REPINNED_BCBS { + + // + // A pointer to the next structure contains additional repinned bcbs + // + + struct _FFS_REPINNED_BCBS *Next; + + // + // A fixed size array of pinned bcbs. Whenever a new bcb is added to + // the repinned bcb structure it is added to this array. If the + // array is already full then another repinned bcb structure is allocated + // and pointed to with Next. + // + + PBCB Bcb[ FFS_REPINNED_BCBS_ARRAY_SIZE ]; + +} FFS_REPINNED_BCBS, *PFFS_REPINNED_BCBS; + + +/* + * FFS_BSD_PARTITION + */ +typedef struct _FFS_BSD_PARTITION +{ + ULONG Number; +} FFS_BSD_PARTITION, *PFFS_BSD_PARTITION; + + +/* + * FFS_GLOBAL_DATA + * + * Data that is not specific to a mounted volume + */ +typedef struct _FFS_GLOBAL { + + // Identifier for this structure + FFS_IDENTIFIER Identifier; + + // Syncronization primitive for this structure + ERESOURCE Resource; + + // Syncronization primitive for Counting + ERESOURCE CountResource; + + // Syncronization primitive for LookAside Lists + ERESOURCE LAResource; + + // Table of pointers to the fast I/O entry points + FAST_IO_DISPATCH FastIoDispatch; + + // Table of pointers to the Cache Manager callbacks + CACHE_MANAGER_CALLBACKS CacheManagerCallbacks; + CACHE_MANAGER_CALLBACKS CacheManagerNoOpCallbacks; + + // Pointer to the driver object + PDRIVER_OBJECT DriverObject; + + // Pointer to the main device object + PDEVICE_OBJECT DeviceObject; + + // List of mounted volumes + LIST_ENTRY VcbList; + + // Look Aside table of IRP_CONTEXT, FCB, MCB, CCB + USHORT MaxDepth; + NPAGED_LOOKASIDE_LIST FFSIrpContextLookasideList; + NPAGED_LOOKASIDE_LIST FFSFcbLookasideList; + NPAGED_LOOKASIDE_LIST FFSCcbLookasideList; + PAGED_LOOKASIDE_LIST FFSMcbLookasideList; + + // Mcb Count ... + USHORT McbAllocated; + +#if DBG + // Fcb Count + USHORT FcbAllocated; + + // IRP_MJ_CLOSE : FCB + USHORT IRPCloseCount; +#endif + + // Global flags for the driver + ULONG Flags; + + ULONG PartitionNumber; + +} FFS_GLOBAL, *PFFS_GLOBAL; + +/* + * Flags for FFS_GLOBAL_DATA + */ +#define FFS_UNLOAD_PENDING 0x00000001 +#define FFS_SUPPORT_WRITING 0x00000002 +#define FFS_CHECKING_BITMAP 0x00000008 + +/* + * Driver Extension define + */ +typedef struct { + FFS_GLOBAL FFSGlobal; +} FFS_EXT, *PFFS_EXT; + + +typedef struct _FFS_FCBVCB { + + // FCB header required by NT + FSRTL_COMMON_FCB_HEADER CommonFCBHeader; + SECTION_OBJECT_POINTERS SectionObject; + ERESOURCE MainResource; + ERESOURCE PagingIoResource; + // end FCB header required by NT + + // Identifier for this structure + FFS_IDENTIFIER Identifier; +} FFS_FCBVCB, *PFFS_FCBVCB; + +/* + * FFS_VCB Volume Control Block + * + * Data that represents a mounted logical volume + * It is allocated as the device extension of the volume device object + */ +typedef struct _FFS_VCB { + + // FCB header required by NT + // The VCB is also used as an FCB for file objects + // that represents the volume itself + FSRTL_COMMON_FCB_HEADER Header; + SECTION_OBJECT_POINTERS SectionObject; + ERESOURCE MainResource; + ERESOURCE PagingIoResource; + // end FCB header required by NT + + // Identifier for this structure + FFS_IDENTIFIER Identifier; + + LIST_ENTRY Next; + + // Share Access for the file object + SHARE_ACCESS ShareAccess; + + // Incremented on IRP_MJ_CREATE, decremented on IRP_MJ_CLEANUP + // for files on this volume. + ULONG OpenFileHandleCount; + + // Incremented on IRP_MJ_CREATE, decremented on IRP_MJ_CLOSE + // for both files on this volume and open instances of the + // volume itself. + ULONG ReferenceCount; + ULONG OpenHandleCount; + + // + // Disk change count + // + + ULONG ChangeCount; + + // Pointer to the VPB in the target device object + PVPB Vpb; + + // The FileObject of Volume used to lock the volume + PFILE_OBJECT LockFile; + + // List of FCBs for open files on this volume + LIST_ENTRY FcbList; + + // List of IRPs pending on directory change notify requests + LIST_ENTRY NotifyList; + + // Pointer to syncronization primitive for this list + PNOTIFY_SYNC NotifySync; + + // This volumes device object + PDEVICE_OBJECT DeviceObject; + + // The physical device object (the disk) + PDEVICE_OBJECT TargetDeviceObject; + + // The physical device object (the disk) + PDEVICE_OBJECT RealDevice; + + // Information about the physical device object + DISK_GEOMETRY DiskGeometry; + PARTITION_INFORMATION PartitionInformation; + + // File System Super Block + PFFS_SUPER_BLOCK ffs_super_block; + + // File System version + ULONG FSVersion; + + // Number of Group Decsciptions + ULONG ffs_groups; + /* + // Bitmap Block per group + PRTL_BITMAP BlockBitMaps; + PRTL_BITMAP InodeBitMaps; + */ + // Block / Cluster size + ULONG BlockSize; + + // Sector size in bits + ULONG SectorBits; + + ULONG dwData[FFS_BLOCK_TYPES]; + ULONG dwMeta[FFS_BLOCK_TYPES]; + + // Flags for the volume + ULONG Flags; + + // Streaming File Object + PFILE_OBJECT StreamObj; + + // Resource Lock for Mcb + ERESOURCE McbResource; + + // Dirty Mcbs of modifications for volume stream + LARGE_MCB DirtyMcbs; + + // Entry of Mcb Tree (Root Node) + PFFS_MCB McbTree; + LIST_ENTRY McbList; + + ULONGLONG FSOffset[MAXPARTITIONS]; + + ULONG RootPartition; + + ULONG PartitionNumber; + +} FFS_VCB, *PFFS_VCB; + +/* + * Flags for FFS_VCB + */ +#define VCB_INITIALIZED 0x00000001 +#define VCB_VOLUME_LOCKED 0x00000002 +#define VCB_MOUNTED 0x00000004 +#define VCB_DISMOUNT_PENDING 0x00000008 +#define VCB_READ_ONLY 0x00000010 + +#define VCB_WRITE_PROTECTED 0x10000000 +#define VCB_FLOPPY_DISK 0x20000000 +#define VCB_REMOVAL_PREVENTED 0x40000000 +#define VCB_REMOVABLE_MEDIA 0x80000000 + + +#define IsMounted(Vcb) (IsFlagOn(Vcb->Flags, VCB_MOUNTED)) + + +/* + * FFS_FCB File Control Block + * + * Data that represents an open file + * There is a single instance of the FCB for every open file + */ +typedef struct _FFS_FCB { + + // FCB header required by NT + FSRTL_COMMON_FCB_HEADER Header; + SECTION_OBJECT_POINTERS SectionObject; + ERESOURCE MainResource; + ERESOURCE PagingIoResource; + // end FCB header required by NT + + // Identifier for this structure + FFS_IDENTIFIER Identifier; + + // List of FCBs for this volume + LIST_ENTRY Next; + + // Share Access for the file object + SHARE_ACCESS ShareAccess; + + // List of byte-range locks for this file + FILE_LOCK FileLockAnchor; + + // Incremented on IRP_MJ_CREATE, decremented on IRP_MJ_CLEANUP + ULONG OpenHandleCount; + + // Incremented on IRP_MJ_CREATE, decremented on IRP_MJ_CLOSE + ULONG ReferenceCount; + + // Incremented on IRP_MJ_CREATE, decremented on IRP_MJ_CLEANUP + // But only for Files with FO_NO_INTERMEDIATE_BUFFERING flag + ULONG NonCachedOpenCount; + + // Flags for the FCB + ULONG Flags; + + // Pointer to the inode + PFFSv1_INODE dinode1; + PFFSv2_INODE dinode2; + + // Hint block for next allocation + ULONG BlkHint; + + // Vcb + + PFFS_VCB Vcb; + + // Mcb Node ... + PFFS_MCB FFSMcb; + + // Full Path Name + UNICODE_STRING LongName; + +#if DBG + // The Ansi Filename for debugging + OEM_STRING AnsiFileName; +#endif + + +} FFS_FCB, *PFFS_FCB; + + +// +// Flags for FFS_FCB +// +#define FCB_FROM_POOL 0x00000001 +#define FCB_PAGE_FILE 0x00000002 +#define FCB_DELETE_ON_CLOSE 0x00000004 +#define FCB_DELETE_PENDING 0x00000008 +#define FCB_FILE_DELETED 0x00000010 +#define FCB_FILE_MODIFIED 0x00000020 + +// Mcb Node + +struct _FFS_MCB { + + // Identifier for this structure + FFS_IDENTIFIER Identifier; + + // Flags + ULONG Flags; + + // Link List Info + + PFFS_MCB Parent; // Parent + PFFS_MCB Child; // Children + PFFS_MCB Next; // Brothers + + // Mcb Node Info + + // -> Fcb + PFFS_FCB FFSFcb; + + // Short name + UNICODE_STRING ShortName; + + // Inode number + ULONG Inode; + + // Dir entry offset in parent + ULONG DeOffset; + + // File attribute + ULONG FileAttr; + + // List Link to Vcb->McbList + LIST_ENTRY Link; +}; + +/* + * Flags for MCB + */ +#define MCB_FROM_POOL 0x00000001 +#define MCB_IN_TREE 0x00000002 +#define MCB_IN_USE 0x00000004 + +#define IsMcbUsed(Mcb) IsFlagOn(Mcb->Flags, MCB_IN_USE) + + +/* + * FFS_CCB Context Control Block + * + * Data that represents one instance of an open file + * There is one instance of the CCB for every instance of an open file + */ +typedef struct _FFS_CCB { + + // Identifier for this structure + FFS_IDENTIFIER Identifier; + + // Flags + ULONG Flags; + + // State that may need to be maintained + ULONG CurrentByteOffset; + UNICODE_STRING DirectorySearchPattern; + +} FFS_CCB, *PFFS_CCB; + +/* + * Flags for CCB + */ + +#define CCB_FROM_POOL 0x00000001 + +#define CCB_ALLOW_EXTENDED_DASD_IO 0x80000000 + + +/* + * FFS_IRP_CONTEXT + * + * Used to pass information about a request between the drivers functions + */ +typedef struct _FFS_IRP_CONTEXT { + + // Identifier for this structure + FFS_IDENTIFIER Identifier; + + // Pointer to the IRP this request describes + PIRP Irp; + + // Flags + ULONG Flags; + + // The major and minor function code for the request + UCHAR MajorFunction; + UCHAR MinorFunction; + + // The device object + PDEVICE_OBJECT DeviceObject; + + // The real device object + PDEVICE_OBJECT RealDevice; + + // The file object + PFILE_OBJECT FileObject; + + PFFS_FCB Fcb; + PFFS_CCB Ccb; + + // If the request is synchronous (we are allowed to block) + BOOLEAN IsSynchronous; + + // If the request is top level + BOOLEAN IsTopLevel; + + // Used if the request needs to be queued for later processing + WORK_QUEUE_ITEM WorkQueueItem; + + // If an exception is currently in progress + BOOLEAN ExceptionInProgress; + + // The exception code when an exception is in progress + NTSTATUS ExceptionCode; + + // Repinned BCBs List + FFS_REPINNED_BCBS Repinned; + +} FFS_IRP_CONTEXT, *PFFS_IRP_CONTEXT; + + +#define IRP_CONTEXT_FLAG_FROM_POOL (0x00000001) +#define IRP_CONTEXT_FLAG_WAIT (0x00000002) +#define IRP_CONTEXT_FLAG_WRITE_THROUGH (0x00000004) +#define IRP_CONTEXT_FLAG_FLOPPY (0x00000008) +#define IRP_CONTEXT_FLAG_RECURSIVE_CALL (0x00000010) +#define IRP_CONTEXT_FLAG_DISABLE_POPUPS (0x00000020) +#define IRP_CONTEXT_FLAG_DEFERRED (0x00000040) +#define IRP_CONTEXT_FLAG_VERIFY_READ (0x00000080) +#define IRP_CONTEXT_STACK_IO_CONTEXT (0x00000100) +#define IRP_CONTEXT_FLAG_REQUEUED (0x00000200) +#define IRP_CONTEXT_FLAG_USER_IO (0x00000400) +#define IRP_CONTEXT_FLAG_DELAY_CLOSE (0x00000800) + + +/* + * FFS_ALLOC_HEADER + * + * In the checked version of the driver this header is put in the beginning of + * every memory allocation + */ +typedef struct _FFS_ALLOC_HEADER { + FFS_IDENTIFIER Identifier; +} FFS_ALLOC_HEADER, *PFFS_ALLOC_HEADER; + +typedef struct _FCB_LIST_ENTRY { + PFFS_FCB Fcb; + LIST_ENTRY Next; +} FCB_LIST_ENTRY, *PFCB_LIST_ENTRY; + + +/* Block Description List */ +typedef struct _FFS_BDL { + LONGLONG Lba; + ULONG Offset; + ULONG Length; + PIRP Irp; +} FFS_BDL, *PFFS_BDL; + +#pragma pack() + + +/* + * The following macro is used to determine if an FSD thread can block + * for I/O or wait for a resource. It returns TRUE if the thread can + * block and FALSE otherwise. This attribute can then be used to call + * the FSD & FSP common work routine with the proper wait value. + */ + +#define CanFFSWait(IRP) IoIsOperationSynchronous(Irp) + +#define FFS_POOL_TAG 'dsfF' + +// +// Block.c +// + +NTSTATUS +FFSLockUserBuffer( + IN PIRP Irp, + IN ULONG Length, + IN LOCK_OPERATION Operation); +PVOID +FFSGetUserBuffer( + IN PIRP Irp); + +NTSTATUS +FFSReadWriteBlocks( + IN PFFS_IRP_CONTEXT IrpContext, + IN PFFS_VCB Vcb, + IN PFFS_BDL FFSBDL, + IN ULONG Length, + IN ULONG Count, + IN BOOLEAN bVerify); + +NTSTATUS +FFSReadSync( + IN PFFS_VCB Vcb, + IN ULONGLONG Offset, + IN ULONG Length, + OUT PVOID Buffer, + IN BOOLEAN bVerify); + +NTSTATUS +FFSReadDisk( + IN PFFS_VCB Vcb, + IN ULONGLONG Offset, + IN ULONG Size, + IN PVOID Buffer, + IN BOOLEAN bVerify); + +NTSTATUS +FFSDiskIoControl( + IN PDEVICE_OBJECT DeviceOjbect, + IN ULONG IoctlCode, + IN PVOID InputBuffer, + IN ULONG InputBufferSize, + IN OUT PVOID OutputBuffer, + IN OUT PULONG OutputBufferSize); + +__drv_mustHoldCriticalRegion +VOID +FFSMediaEjectControl( + IN PFFS_IRP_CONTEXT IrpContext, + IN PFFS_VCB Vcb, + IN BOOLEAN bPrevent); + +NTSTATUS +FFSDiskShutDown( + PFFS_VCB Vcb); + + +// +// Cleanup.c +// + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSCleanup( + IN PFFS_IRP_CONTEXT IrpContext); + + +// +// Close.c +// + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSClose( + IN PFFS_IRP_CONTEXT IrpContext); + +VOID +FFSQueueCloseRequest( + IN PFFS_IRP_CONTEXT IrpContext); + +#ifdef _PREFAST_ +IO_WORKITEM_ROUTINE FFSDeQueueCloseRequest; +#endif // _PREFAST_ + +VOID NTAPI +FFSDeQueueCloseRequest( + IN PVOID Context); + + +// +// Cmcb.c +// + +__drv_mustHoldCriticalRegion +BOOLEAN NTAPI +FFSAcquireForLazyWrite( + IN PVOID Context, + IN BOOLEAN Wait); + +__drv_mustHoldCriticalRegion +VOID NTAPI +FFSReleaseFromLazyWrite( + IN PVOID Context); + +__drv_mustHoldCriticalRegion +BOOLEAN NTAPI +FFSAcquireForReadAhead( + IN PVOID Context, + IN BOOLEAN Wait); + +BOOLEAN NTAPI +FFSNoOpAcquire( + IN PVOID Fcb, + IN BOOLEAN Wait); + +VOID NTAPI +FFSNoOpRelease( + IN PVOID Fcb); + +__drv_mustHoldCriticalRegion +VOID NTAPI +FFSReleaseFromReadAhead( + IN PVOID Context); + + +// +// Create.c +// + +PFFS_FCB +FFSSearchFcbList( + IN PFFS_VCB Vcb, + IN ULONG inode); + +NTSTATUS +FFSv1ScanDir( + IN PFFS_VCB Vcb, + IN PFFS_MCB ParentMcb, + IN PUNICODE_STRING FileName, + IN OUT PULONG Index, + IN PFFSv1_INODE dinode1, + IN PFFS_DIR_ENTRY ffs_dir); + +NTSTATUS +FFSv2ScanDir( + IN PFFS_VCB Vcb, + IN PFFS_MCB ParentMcb, + IN PUNICODE_STRING FileName, + IN OUT PULONG Index, + IN PFFSv2_INODE dinode2, + IN PFFS_DIR_ENTRY ffs_dir); + +NTSTATUS +FFSv1LookupFileName( + IN PFFS_VCB Vcb, + IN PUNICODE_STRING FullFileName, + IN PFFS_MCB ParentMcb, + OUT PFFS_MCB* FFSMcb, + IN OUT PFFSv1_INODE dinode1); + + +NTSTATUS +FFSv2LookupFileName( + IN PFFS_VCB Vcb, + IN PUNICODE_STRING FullFileName, + IN PFFS_MCB ParentMcb, + OUT PFFS_MCB* FFSMcb, + IN OUT PFFSv2_INODE dinode2); + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSCreateFile( + IN PFFS_IRP_CONTEXT IrpContext, + IN PFFS_VCB Vcb); + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSCreateVolume( + IN PFFS_IRP_CONTEXT IrpContext, + IN PFFS_VCB Vcb); + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSCreate( + IN PFFS_IRP_CONTEXT IrpContext); + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSCreateInode( + PFFS_IRP_CONTEXT IrpContext, + PFFS_VCB Vcb, + PFFS_FCB ParentFcb, + ULONG Type, + ULONG FileAttr, + PUNICODE_STRING FileName); + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSSupersedeOrOverWriteFile( + IN PFFS_IRP_CONTEXT IrpContext, + IN PFFS_VCB Vcb, + IN PFFS_FCB Fcb, + IN ULONG Disposition); + + +// +// Debug.c +// + +#define DBG_VITAL 0 +#define DBG_ERROR 1 +#define DBG_USER 2 +#define DBG_TRACE 3 +#define DBG_INFO 4 +#define DBG_FUNC 5 + +#if DBG +#define FFSPrint(arg) FFSPrintf arg +#define FFSPrintNoIndent(arg) FFSNIPrintf arg + +#define FFSCompleteRequest(Irp, bPrint, PriorityBoost) \ + FFSDbgPrintComplete(Irp, bPrint); \ + IoCompleteRequest(Irp, PriorityBoost) + +#else + +#define FFSPrint(arg) + +#define FFSCompleteRequest(Irp, bPrint, PriorityBoost) \ + IoCompleteRequest(Irp, PriorityBoost) + +#endif // DBG + +VOID +__cdecl +FFSPrintf( + LONG DebugPrintLevel, + PCHAR DebugMessage, + ...); + +VOID +__cdecl +FFSNIPrintf( + LONG DebugPrintLevel, + PCHAR DebugMessage, + ...); + +extern ULONG ProcessNameOffset; + +#define FFSGetCurrentProcessName() ( \ + (PCHAR) PsGetCurrentProcess() + ProcessNameOffset \ +) + +ULONG +FFSGetProcessNameOffset( + VOID); + +VOID +FFSDbgPrintCall( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +VOID +FFSDbgPrintComplete( + IN PIRP Irp, + IN BOOLEAN bPrint); + +PCHAR +FFSNtStatusToString( + IN NTSTATUS Status); + + +// +// Devctl.c +// + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSDeviceControlNormal( + IN PFFS_IRP_CONTEXT IrpContext); + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSPrepareToUnload( + IN PFFS_IRP_CONTEXT IrpContext); + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSDeviceControl( + IN PFFS_IRP_CONTEXT IrpContext); + + +// +// Dirctl.c +// + +ULONG +FFSGetInfoLength( + IN FILE_INFORMATION_CLASS FileInformationClass); + +ULONG +FFSProcessDirEntry( + IN PFFS_VCB Vcb, + IN FILE_INFORMATION_CLASS FileInformationClass, + IN ULONG in, + IN PVOID Buffer, + IN ULONG UsedLength, + IN ULONG Length, + IN ULONG FileIndex, + IN PUNICODE_STRING pName, + IN BOOLEAN Single); + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSQueryDirectory( + IN PFFS_IRP_CONTEXT IrpContext); + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSNotifyChangeDirectory( + IN PFFS_IRP_CONTEXT IrpContext); + +VOID +FFSNotifyReportChange( + IN PFFS_IRP_CONTEXT IrpContext, + IN PFFS_VCB Vcb, + IN PFFS_FCB Fcb, + IN ULONG Filter, + IN ULONG Action); + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSDirectoryControl( + IN PFFS_IRP_CONTEXT IrpContext); + +BOOLEAN +FFSIsDirectoryEmpty( + PFFS_VCB Vcb, + PFFS_FCB Dcb); + + +// +// Dispatch.c +// + +NTSTATUS +FFSQueueRequest( + IN PFFS_IRP_CONTEXT IrpContext); + +#ifdef _PREFAST_ +IO_WORKITEM_ROUTINE FFSDeQueueRequest; +#endif // _PREFAST_ + +VOID NTAPI +FFSDeQueueRequest( + IN PVOID Context); + +NTSTATUS +FFSDispatchRequest( + IN PFFS_IRP_CONTEXT IrpContext); + +#ifdef _PREFAST_ +__drv_dispatchType(IRP_MJ_CREATE) +__drv_dispatchType(IRP_MJ_CLOSE) +__drv_dispatchType(IRP_MJ_READ) +__drv_dispatchType(IRP_MJ_WRITE) +__drv_dispatchType(IRP_MJ_QUERY_INFORMATION) +__drv_dispatchType(IRP_MJ_SET_INFORMATION) +__drv_dispatchType(IRP_MJ_FLUSH_BUFFERS) +__drv_dispatchType(IRP_MJ_QUERY_VOLUME_INFORMATION) +__drv_dispatchType(IRP_MJ_SET_VOLUME_INFORMATION) +__drv_dispatchType(IRP_MJ_DIRECTORY_CONTROL) +__drv_dispatchType(IRP_MJ_FILE_SYSTEM_CONTROL) +__drv_dispatchType(IRP_MJ_DEVICE_CONTROL) +__drv_dispatchType(IRP_MJ_SHUTDOWN) +__drv_dispatchType(IRP_MJ_LOCK_CONTROL) +__drv_dispatchType(IRP_MJ_CLEANUP) +__drv_dispatchType(IRP_MJ_PNP) +DRIVER_DISPATCH FFSBuildRequest; +#endif // _PREFAST_ + +NTSTATUS NTAPI +FFSBuildRequest( + PDEVICE_OBJECT DeviceObject, + PIRP Irp); + + +// +// Except.c +// + +NTSTATUS +FFSExceptionFilter( + IN PFFS_IRP_CONTEXT IrpContext, + IN PEXCEPTION_POINTERS ExceptionPointer); + +NTSTATUS +FFSExceptionHandler( + IN PFFS_IRP_CONTEXT IrpContext); + + +// +// ffs.c +// + +PFFS_SUPER_BLOCK +FFSLoadSuper( + IN PFFS_VCB Vcb, + IN BOOLEAN bVerify, + IN ULONGLONG SuperBlockOffset); + +__drv_mustHoldCriticalRegion +BOOLEAN +FFSSaveSuper( + IN PFFS_IRP_CONTEXT IrpContext, + IN PFFS_VCB Vcb); + +BOOLEAN +FFSLoadGroup( + IN PFFS_VCB Vcb); + +BOOLEAN +FFSSaveGroup( + IN PFFS_IRP_CONTEXT IrpContext, + IN PFFS_VCB Vcb); + +BOOLEAN +FFSv1GetInodeLba( + IN PFFS_VCB Vcb, + IN ULONG inode, + OUT PLONGLONG offset); + +BOOLEAN +FFSv2GetInodeLba( + IN PFFS_VCB Vcb, + IN ULONG inode, + OUT PLONGLONG offset); + +BOOLEAN +FFSv1LoadInode( + IN PFFS_VCB Vcb, + IN ULONG inode, + IN PFFSv1_INODE dinode1); + +BOOLEAN +FFSv2LoadInode( + IN PFFS_VCB Vcb, + IN ULONG inode, + IN PFFSv2_INODE dinode2); + +__drv_mustHoldCriticalRegion +BOOLEAN +FFSv1SaveInode( + IN PFFS_IRP_CONTEXT IrpContext, + IN PFFS_VCB Vcb, + IN ULONG Inode, + IN PFFSv1_INODE dinode1); + +__drv_mustHoldCriticalRegion +BOOLEAN +FFSv2SaveInode( + IN PFFS_IRP_CONTEXT IrpContext, + IN PFFS_VCB Vcb, + IN ULONG Inode, + IN PFFSv2_INODE dinode2); + +BOOLEAN +FFSv1LoadBlock( + IN PFFS_VCB Vcb, + IN ULONG dwBlk, + IN PVOID Buffer); + +BOOLEAN +FFSv2LoadBlock( + IN PFFS_VCB Vcb, + IN ULONGLONG dwBlk, + IN PVOID Buffer); + +__drv_mustHoldCriticalRegion +BOOLEAN +FFSSaveBlock( + IN PFFS_IRP_CONTEXT IrpContext, + IN PFFS_VCB Vcb, + IN ULONG dwBlk, + IN PVOID Buf); + +__drv_mustHoldCriticalRegion +BOOLEAN +FFSSaveBuffer( + IN PFFS_IRP_CONTEXT IrpContext, + IN PFFS_VCB Vcb, + IN LONGLONG Offset, + IN ULONG Size, + IN PVOID Buf); + +ULONG +FFSv1GetBlock( + IN PFFS_VCB Vcb, + IN ULONG dwContent, + IN ULONG Index, + IN int layer); + +ULONGLONG +FFSv2GetBlock( + IN PFFS_VCB Vcb, + IN ULONGLONG dwContent, + IN ULONG Index, + IN int layer); + +ULONG +FFSv1BlockMap( + IN PFFS_VCB Vcb, + IN PFFSv1_INODE dinode1, + IN ULONG Index); + +ULONGLONG +FFSv2BlockMap( + IN PFFS_VCB Vcb, + IN PFFSv2_INODE dinode2, + IN ULONG Index); + +ULONG +FFSv1BuildBDL( + IN PFFS_IRP_CONTEXT IrpContext, + IN PFFS_VCB Vcb, + IN PFFSv1_INODE dinode1, + IN ULONGLONG Offset, + IN ULONG Size, + OUT PFFS_BDL *ffs_bdl); + +ULONG +FFSv2BuildBDL( + IN PFFS_IRP_CONTEXT IrpContext, + IN PFFS_VCB Vcb, + IN PFFSv2_INODE dinode2, + IN ULONGLONG Offset, + IN ULONG Size, + OUT PFFS_BDL *ffs_bdl); + +BOOLEAN +FFSNewBlock( + PFFS_IRP_CONTEXT IrpContext, + PFFS_VCB Vcb, + ULONG GroupHint, + ULONG BlockHint, + PULONG dwRet); + +BOOLEAN +FFSFreeBlock( + PFFS_IRP_CONTEXT IrpContext, + PFFS_VCB Vcb, + ULONG Block); + +__drv_mustHoldCriticalRegion +BOOLEAN +FFSExpandBlock( + PFFS_IRP_CONTEXT IrpContext, + PFFS_VCB Vcb, + PFFS_FCB Fcb, + ULONG dwContent, + ULONG Index, + ULONG layer, + BOOLEAN bNew, + ULONG *dwRet); + +BOOLEAN +FFSExpandInode( + PFFS_IRP_CONTEXT IrpContext, + PFFS_VCB Vcb, + PFFS_FCB Fcb, + ULONG *dwRet); + +NTSTATUS +FFSNewInode( + PFFS_IRP_CONTEXT IrpContext, + PFFS_VCB Vcb, + ULONG GroupHint, + ULONG Type, + PULONG Inode); + +BOOLEAN +FFSFreeInode( + PFFS_IRP_CONTEXT IrpContext, + PFFS_VCB Vcb, + ULONG Inode, + ULONG Type); + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSAddEntry( + IN PFFS_IRP_CONTEXT IrpContext, + IN PFFS_VCB Vcb, + IN PFFS_FCB Dcb, + IN ULONG FileType, + IN ULONG Inode, + IN PUNICODE_STRING FileName); + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSRemoveEntry( + IN PFFS_IRP_CONTEXT IrpContext, + IN PFFS_VCB Vcb, + IN PFFS_FCB Dcb, + IN ULONG FileType, + IN ULONG Inode); + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSSetParentEntry( + IN PFFS_IRP_CONTEXT IrpContext, + IN PFFS_VCB Vcb, + IN PFFS_FCB Dcb, + IN ULONG OldParent, + IN ULONG NewParent); + +__drv_mustHoldCriticalRegion +BOOLEAN +FFSTruncateBlock( + IN PFFS_IRP_CONTEXT IrpContext, + IN PFFS_VCB Vcb, + IN PFFS_FCB Fcb, + IN ULONG dwContent, + IN ULONG Index, + IN ULONG layer, + OUT BOOLEAN *bFreed); + +BOOLEAN +FFSTruncateInode( + IN PFFS_IRP_CONTEXT IrpContext, + IN PFFS_VCB Vcb, + IN PFFS_FCB Fcb); + +__drv_mustHoldCriticalRegion +BOOLEAN +FFSAddMcbEntry( + IN PFFS_VCB Vcb, + IN LONGLONG Lba, + IN LONGLONG Length); + +__drv_mustHoldCriticalRegion +VOID +FFSRemoveMcbEntry( + IN PFFS_VCB Vcb, + IN LONGLONG Lba, + IN LONGLONG Length); + +__drv_mustHoldCriticalRegion +BOOLEAN +FFSLookupMcbEntry( + IN PFFS_VCB Vcb, + IN LONGLONG Lba, + OUT PLONGLONG pLba, + OUT PLONGLONG pLength, + OUT PLONGLONG RunStart, + OUT PLONGLONG RunLength, + OUT PULONG Index); + +ULONG +FFSDataBlocks( + PFFS_VCB Vcb, + ULONG TotalBlocks); + +ULONG +FFSTotalBlocks( + PFFS_VCB Vcb, + ULONG DataBlocks); + + +// +// Fastio.c +// + +#ifdef _PREFAST_ +FAST_IO_CHECK_IF_POSSIBLE FFSFastIoCheckIfPossible; +#endif // _PREFAST_ + +BOOLEAN NTAPI +FFSFastIoCheckIfPossible( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN BOOLEAN Wait, + IN ULONG LockKey, + IN BOOLEAN CheckForReadOperation, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject); + +#ifdef _PREFAST_ +FAST_IO_READ FFSFastIoRead; +#endif // _PREFAST_ + +BOOLEAN NTAPI +FFSFastIoRead( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN BOOLEAN Wait, + IN ULONG LockKey, + OUT PVOID Buffer, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject); + +#ifdef _PREFAST_ +FAST_IO_WRITE FFSFastIoWrite; +#endif // _PREFAST_ + +BOOLEAN NTAPI +FFSFastIoWrite( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN BOOLEAN Wait, + IN ULONG LockKey, + OUT PVOID Buffer, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject); + +#ifdef _PREFAST_ +FAST_IO_QUERY_BASIC_INFO FFSFastIoQueryBasicInfo; +#endif // _PREFAST_ + +__drv_mustHoldCriticalRegion +BOOLEAN NTAPI +FFSFastIoQueryBasicInfo( + IN PFILE_OBJECT FileObject, + IN BOOLEAN Wait, + OUT PFILE_BASIC_INFORMATION Buffer, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject); + +#ifdef _PREFAST_ +FAST_IO_QUERY_STANDARD_INFO FFSFastIoQueryStandardInfo; +#endif // _PREFAST_ + +__drv_mustHoldCriticalRegion +BOOLEAN NTAPI +FFSFastIoQueryStandardInfo( + IN PFILE_OBJECT FileObject, + IN BOOLEAN Wait, + OUT PFILE_STANDARD_INFORMATION Buffer, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject); + +#ifdef _PREFAST_ +FAST_IO_LOCK FFSFastIoLock; +#endif // _PREFAST_ + +BOOLEAN NTAPI +FFSFastIoLock( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN PLARGE_INTEGER Length, + IN PEPROCESS Process, + IN ULONG Key, + IN BOOLEAN FailImmediately, + IN BOOLEAN ExclusiveLock, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject); + +#ifdef _PREFAST_ +FAST_IO_UNLOCK_SINGLE FFSFastIoUnlockSingle; +#endif // _PREFAST_ + +BOOLEAN NTAPI +FFSFastIoUnlockSingle( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN PLARGE_INTEGER Length, + IN PEPROCESS Process, + IN ULONG Key, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject); + +#ifdef _PREFAST_ +FAST_IO_UNLOCK_ALL FFSFastIoUnlockAll; +#endif // _PREFAST_ + +BOOLEAN NTAPI +FFSFastIoUnlockAll( + IN PFILE_OBJECT FileObject, + IN PEPROCESS Process, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject); + +#ifdef _PREFAST_ +FAST_IO_UNLOCK_ALL_BY_KEY FFSFastIoUnlockAllByKey; +#endif // _PREFAST_ + +BOOLEAN NTAPI +FFSFastIoUnlockAllByKey( + IN PFILE_OBJECT FileObject, +#ifndef __REACTOS__ + IN PEPROCESS Process, +#else + IN PVOID Process, +#endif + IN ULONG Key, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject); + +#ifdef _PREFAST_ +FAST_IO_QUERY_NETWORK_OPEN_INFO FFSFastIoQueryNetworkOpenInfo; +#endif // _PREFAST_ + +__drv_mustHoldCriticalRegion +BOOLEAN NTAPI +FFSFastIoQueryNetworkOpenInfo( + IN PFILE_OBJECT FileObject, + IN BOOLEAN Wait, + OUT PFILE_NETWORK_OPEN_INFORMATION Buffer, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject); + +// +// FileInfo.c +// + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSQueryInformation( + IN PFFS_IRP_CONTEXT IrpContext); + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSSetInformation( + IN PFFS_IRP_CONTEXT IrpContext); + +BOOLEAN +FFSExpandFile( + PFFS_IRP_CONTEXT IrpContext, + PFFS_VCB Vcb, + PFFS_FCB Fcb, + PLARGE_INTEGER AllocationSize); + +BOOLEAN +FFSTruncateFile( + PFFS_IRP_CONTEXT IrpContext, + PFFS_VCB Vcb, + PFFS_FCB Fcb, + PLARGE_INTEGER AllocationSize); + +NTSTATUS +FFSSetDispositionInfo( + PFFS_IRP_CONTEXT IrpContext, + PFFS_VCB Vcb, + PFFS_FCB Fcb, + BOOLEAN bDelete); + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSSetRenameInfo( + PFFS_IRP_CONTEXT IrpContext, + PFFS_VCB Vcb, + PFFS_FCB Fcb); + +__drv_mustHoldCriticalRegion +BOOLEAN +FFSDeleteFile( + PFFS_IRP_CONTEXT IrpContext, + PFFS_VCB Vcb, + PFFS_FCB Fcb); + + +// +// Flush.c +// + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSFlushFiles( + IN PFFS_VCB Vcb, + BOOLEAN bShutDown); + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSFlushVolume( + IN PFFS_VCB Vcb, + BOOLEAN bShutDown); + +NTSTATUS +FFSFlushFile( + IN PFFS_FCB Fcb); + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSFlush( + IN PFFS_IRP_CONTEXT IrpContext); + + +// +// Fsctl.c +// + +VOID +FFSSetVpbFlag( + IN PVPB Vpb, + IN USHORT Flag); + +VOID +FFSClearVpbFlag( + IN PVPB Vpb, + IN USHORT Flag); + +NTSTATUS +FFSGetPartition( + IN PDEVICE_OBJECT DeviceObject, + OUT ULONGLONG *StartOffset); + +NTSTATUS +FFSLoadDiskLabel( + PDEVICE_OBJECT DeviceObject, + IN PFFS_VCB Vcb); + +__drv_mustHoldCriticalRegion +BOOLEAN +FFSCheckDismount( + IN PFFS_IRP_CONTEXT IrpContext, + IN PFFS_VCB Vcb, + IN BOOLEAN bForce); + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSPurgeVolume( + IN PFFS_VCB Vcb, + IN BOOLEAN FlushBeforePurge); + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSPurgeFile( + IN PFFS_FCB Fcb, + IN BOOLEAN FlushBeforePurge); + +BOOLEAN +FFSIsHandleCountZero( + IN PFFS_VCB Vcb); + +NTSTATUS +FFSLockVcb( + IN PFFS_VCB Vcb, + IN PFILE_OBJECT FileObject); + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSLockVolume( + IN PFFS_IRP_CONTEXT IrpContext); + +NTSTATUS +FFSUnlockVcb( + IN PFFS_VCB Vcb, + IN PFILE_OBJECT FileObject); + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSUnlockVolume( + IN PFFS_IRP_CONTEXT IrpContext); + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSAllowExtendedDasdIo( + IN PFFS_IRP_CONTEXT IrpContext); + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSUserFsRequest( + IN PFFS_IRP_CONTEXT IrpContext); + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSMountVolume( + IN PFFS_IRP_CONTEXT IrpContext); + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSVerifyVolume( + IN PFFS_IRP_CONTEXT IrpContext); + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSIsVolumeMounted( + IN PFFS_IRP_CONTEXT IrpContext); + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSDismountVolume( + IN PFFS_IRP_CONTEXT IrpContext); + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSSelectBSDPartition( + IN PFFS_IRP_CONTEXT IrpContext); + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSFileSystemControl( + IN PFFS_IRP_CONTEXT IrpContext); + + +// +// Init.c +// + +BOOLEAN +FFSQueryParameters( + IN PUNICODE_STRING RegistryPath); + +#ifdef _PREFAST_ +DRIVER_INITIALIZE DriverEntry; +#endif // _PREFAST_ + +#ifdef _PREFAST_ +DRIVER_UNLOAD DriverUnload; +#endif // _PREFAST_ + +VOID NTAPI +DriverUnload( + IN PDRIVER_OBJECT DriverObject); + + +// +// Lock.c +// + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSLockControl( + IN PFFS_IRP_CONTEXT IrpContext); + + +// +// Memory.c +// + +__drv_mustHoldCriticalRegion +PFFS_IRP_CONTEXT +FFSAllocateIrpContext( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +__drv_mustHoldCriticalRegion +VOID +FFSFreeIrpContext( + IN PFFS_IRP_CONTEXT IrpContext); + +__drv_mustHoldCriticalRegion +PFFS_FCB +FFSv1AllocateFcb( + IN PFFS_VCB Vcb, + IN PFFS_MCB FFSMcb, + IN PFFSv1_INODE dinode1); + +__drv_mustHoldCriticalRegion +PFFS_FCB +FFSv2AllocateFcb( + IN PFFS_VCB Vcb, + IN PFFS_MCB FFSMcb, + IN PFFSv2_INODE dinode2); + +__drv_mustHoldCriticalRegion +VOID +FFSFreeFcb( + IN PFFS_FCB Fcb); + +__drv_mustHoldCriticalRegion +PFFS_CCB +FFSAllocateCcb( + VOID); + +__drv_mustHoldCriticalRegion +VOID +FFSFreeMcb( + IN PFFS_MCB Mcb); + +__drv_mustHoldCriticalRegion +PFFS_FCB +FFSCreateFcbFromMcb( + PFFS_VCB Vcb, + PFFS_MCB Mcb); + +__drv_mustHoldCriticalRegion +VOID +FFSFreeCcb( + IN PFFS_CCB Ccb); + +PFFS_MCB +FFSAllocateMcb( + PFFS_VCB Vcb, + PUNICODE_STRING FileName, + ULONG FileAttr); + +PFFS_MCB +FFSSearchMcbTree( + PFFS_VCB Vcb, + PFFS_MCB FFSMcb, + ULONG Inode); + +PFFS_MCB +FFSSearchMcb( + PFFS_VCB Vcb, + PFFS_MCB Parent, + PUNICODE_STRING FileName); + +BOOLEAN +FFSGetFullFileName( + PFFS_MCB Mcb, + PUNICODE_STRING FileName); + +VOID +FFSRefreshMcb( + PFFS_VCB Vcb, PFFS_MCB Mcb); + +VOID +FFSAddMcbNode( + PFFS_VCB Vcb, + PFFS_MCB Parent, + PFFS_MCB Child); + +BOOLEAN +FFSDeleteMcbNode( + PFFS_VCB Vcb, + PFFS_MCB McbTree, + PFFS_MCB FFSMcb); + +__drv_mustHoldCriticalRegion +VOID +FFSFreeMcbTree( + PFFS_MCB McbTree); + +BOOLEAN +FFSCheckSetBlock( + PFFS_IRP_CONTEXT IrpContext, + PFFS_VCB Vcb, + ULONG Block); + +BOOLEAN +FFSCheckBitmapConsistency( + PFFS_IRP_CONTEXT IrpContext, + PFFS_VCB Vcb); + +VOID +FFSInsertVcb( + PFFS_VCB Vcb); + +VOID +FFSRemoveVcb( + PFFS_VCB Vcb); + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSInitializeVcb( + IN PFFS_IRP_CONTEXT IrpContext, + IN PFFS_VCB Vcb, + IN PFFS_SUPER_BLOCK FFSSb, + IN PDEVICE_OBJECT TargetDevice, + IN PDEVICE_OBJECT VolumeDevice, + IN PVPB Vpb); + +__drv_mustHoldCriticalRegion +VOID +FFSFreeVcb( + IN PFFS_VCB Vcb); + +VOID +FFSRepinBcb( + IN PFFS_IRP_CONTEXT IrpContext, + IN PBCB Bcb); + +VOID +FFSUnpinRepinnedBcbs( + IN PFFS_IRP_CONTEXT IrpContext); + + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSCompleteIrpContext( + IN PFFS_IRP_CONTEXT IrpContext, + IN NTSTATUS Status); + +VOID +FFSSyncUninitializeCacheMap( + IN PFILE_OBJECT FileObject); + + +// +// Misc.c +// + +ULONG +FFSLog2( + ULONG Value); + +LARGE_INTEGER +FFSSysTime( + IN ULONG i_time); + +ULONG +FFSInodeTime( + IN LARGE_INTEGER SysTime); + +NTSTATUS +FFSOEMToUnicode( + IN OUT PUNICODE_STRING Unicode, + IN POEM_STRING Oem); + +NTSTATUS +FFSUnicodeToOEM( + IN OUT POEM_STRING Oem, + IN PUNICODE_STRING Unicode); + + +// +// Pnp.c +// + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSPnp( + IN PFFS_IRP_CONTEXT IrpContext); + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSPnpQueryRemove( + PFFS_IRP_CONTEXT IrpContext, + PFFS_VCB Vcb); + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSPnpRemove( + PFFS_IRP_CONTEXT IrpContext, + PFFS_VCB Vcb); + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSPnpCancelRemove( + PFFS_IRP_CONTEXT IrpContext, + PFFS_VCB Vcb); + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSPnpSurpriseRemove( + PFFS_IRP_CONTEXT IrpContext, + PFFS_VCB Vcb); + + +// +// Read.c +// + +BOOLEAN +FFSCopyRead( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN BOOLEAN Wait, + OUT PVOID Buffer, + OUT PIO_STATUS_BLOCK IoStatus); + +NTSTATUS +FFSv1ReadInode( + IN PFFS_IRP_CONTEXT IrpContext, + IN PFFS_VCB Vcb, + IN PFFSv1_INODE dinode1, + IN ULONGLONG offset, + IN PVOID Buffer, + IN ULONG size, + OUT PULONG dwRet); + +NTSTATUS +FFSv2ReadInode( + IN PFFS_IRP_CONTEXT IrpContext, + IN PFFS_VCB Vcb, + IN PFFSv2_INODE dinode2, + IN ULONGLONG offset, + IN PVOID Buffer, + IN ULONG size, + OUT PULONG dwRet); + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSRead( + IN PFFS_IRP_CONTEXT IrpContext); + + +// +// Shutdown.c +// + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSShutDown( + IN PFFS_IRP_CONTEXT IrpContext); + + +// +// Volinfo.c +// + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSQueryVolumeInformation( + IN PFFS_IRP_CONTEXT IrpContext); + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSSetVolumeInformation( + IN PFFS_IRP_CONTEXT IrpContext); + + +// +// Write.c +// + +NTSTATUS +FFSv1WriteInode( + IN PFFS_IRP_CONTEXT IrpContext, + IN PFFS_VCB Vcb, + IN PFFSv1_INODE dinode1, + IN ULONGLONG offset, + IN PVOID Buffer, + IN ULONG size, + IN BOOLEAN bWriteToDisk, + OUT PULONG dwRet); + +NTSTATUS +FFSv2WriteInode( + IN PFFS_IRP_CONTEXT IrpContext, + IN PFFS_VCB Vcb, + IN PFFSv2_INODE dinode2, + IN ULONGLONG offset, + IN PVOID Buffer, + IN ULONG size, + IN BOOLEAN bWriteToDisk, + OUT PULONG dwRet); + +VOID +FFSStartFloppyFlushDpc( + PFFS_VCB Vcb, + PFFS_FCB Fcb, + PFILE_OBJECT FileObject); + +BOOLEAN +FFSZeroHoles( + IN PFFS_IRP_CONTEXT IrpContext, + IN PFFS_VCB Vcb, + IN PFILE_OBJECT FileObject, + IN LONGLONG Offset, + IN LONGLONG Count); + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSWrite( + IN PFFS_IRP_CONTEXT IrpContext); + +NTSTATUS +DeviceControl( + IN PDEVICE_OBJECT pDeviceObject, + IN PIRP pIrp); + +#endif /* _FFS_HEADER_ */ diff --git a/reactos/drivers/filesystems/ffs/inc/fs.h b/reactos/drivers/filesystems/ffs/inc/fs.h new file mode 100644 index 00000000000..dde9bef3d98 --- /dev/null +++ b/reactos/drivers/filesystems/ffs/inc/fs.h @@ -0,0 +1,697 @@ +/* $NetBSD: fs.h,v 1.43 2004/03/21 18:48:24 dsl Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)fs.h 8.13 (Berkeley) 3/21/95 + */ + +#ifndef _UFS_FFS_FS_H_ +#define _UFS_FFS_FS_H_ + +#include "type.h" + +/* + * Each disk drive contains some number of file systems. + * A file system consists of a number of cylinder groups. + * Each cylinder group has inodes and data. + * + * A file system is described by its super-block, which in turn + * describes the cylinder groups. The super-block is critical + * data and is replicated in each cylinder group to protect against + * catastrophic loss. This is done at `newfs' time and the critical + * super-block data does not change, so the copies need not be + * referenced further unless disaster strikes. + * + * For file system fs, the offsets of the various blocks of interest + * are given in the super block as: + * [fs->fs_sblkno] Super-block + * [fs->fs_cblkno] Cylinder group block + * [fs->fs_iblkno] Inode blocks + * [fs->fs_dblkno] Data blocks + * The beginning of cylinder group cg in fs, is given by + * the ``cgbase(fs, cg)'' macro. + * + * Depending on the architecture and the media, the superblock may + * reside in any one of four places. For tiny media where every block + * counts, it is placed at the very front of the partition. Historically, + * UFS1 placed it 8K from the front to leave room for the disk label and + * a small bootstrap. For UFS2 it got moved to 64K from the front to leave + * room for the disk label and a bigger bootstrap, and for really piggy + * systems we check at 256K from the front if the first three fail. In + * all cases the size of the superblock will be SBLOCKSIZE. All values are + * given in byte-offset form, so they do not imply a sector size. The + * SBLOCKSEARCH specifies the order in which the locations should be searched. + * + * Unfortunately the UFS2/FFSv2 change was done without adequate consideration + * of backward compatibility. In particular 'newfs' for a FFSv2 partition + * must overwrite any old FFSv1 superblock at 8k, and preferrably as many + * of the alternates as it can find - otherwise attempting to mount on a + * system that only supports FFSv1 is likely to succeed!. + * For a small FFSv1 filesystem, an old FFSv2 superblock can be left on + * the disk, and a system that tries to find an FFSv2 filesystem in preference + * to and FFSv1 one (as NetBSD does) can mount the old FFSv2 filesystem. + * As a added bonus, the 'first alternate' superblock of a FFSv1 filesystem + * with 64k blocks is at 64k - just where the code looks first when playing + * 'hunt the superblock'. + * + * The ffsv2 superblock layout (which might contain an ffsv1 filesystem) + * can be detected by checking for sb->fs_old_flags & FS_FLAGS_UPDATED. + * This is the default suberblock type for NetBSD since ffsv2 support was added. + */ +#define BBSIZE 8192 +#define BBOFF ((off_t)(0)) +#define BBLOCK ((daddr_t)(0)) + +#define SBLOCK_FLOPPY 0 +#define SBLOCK_UFS1 8192 +#define SBLOCK_UFS2 65536 +#define SBLOCK_PIGGY 262144 +#define SBLOCKSIZE 8192 +/* + * NB: Do not, under any circumstances, look for an ffsv1 filesystem at + * SBLOCK_UFS2. Doing so will find the wrong superblock for filesystems + * with a 64k block size. + */ +#define SBLOCKSEARCH \ + { SBLOCK_UFS2, SBLOCK_UFS1, SBLOCK_FLOPPY, SBLOCK_PIGGY, -1 } + +/* + * Max number of fragments per block. This value is NOT tweakable. + */ +#define MAXFRAG 8 + + + +/* + * Addresses stored in inodes are capable of addressing fragments + * of `blocks'. File system blocks of at most size MAXBSIZE can + * be optionally broken into 2, 4, or 8 pieces, each of which is + * addressable; these pieces may be DEV_BSIZE, or some multiple of + * a DEV_BSIZE unit. + * + * Large files consist of exclusively large data blocks. To avoid + * undue wasted disk space, the last data block of a small file may be + * allocated as only as many fragments of a large block as are + * necessary. The file system format retains only a single pointer + * to such a fragment, which is a piece of a single large block that + * has been divided. The size of such a fragment is determinable from + * information in the inode, using the ``blksize(fs, ip, lbn)'' macro. + * + * The file system records space availability at the fragment level; + * to determine block availability, aligned fragments are examined. + */ + +/* + * MINBSIZE is the smallest allowable block size. + * In order to insure that it is possible to create files of size + * 2^32 with only two levels of indirection, MINBSIZE is set to 4096. + * MINBSIZE must be big enough to hold a cylinder group block, + * thus changes to (struct cg) must keep its size within MINBSIZE. + * Note that super blocks are always of size SBSIZE, + * and that both SBSIZE and MAXBSIZE must be >= MINBSIZE. + */ +#define MINBSIZE 4096 + +/* + * The path name on which the file system is mounted is maintained + * in fs_fsmnt. MAXMNTLEN defines the amount of space allocated in + * the super block for this name. + */ +#define MAXMNTLEN 468 + +/* + * The volume name for this filesystem is maintained in fs_volname. + * MAXVOLLEN defines the length of the buffer allocated. + * This space used to be part of of fs_fsmnt. + */ +#define MAXVOLLEN 32 + +/* + * There is a 128-byte region in the superblock reserved for in-core + * pointers to summary information. Originally this included an array + * of pointers to blocks of struct csum; now there are just four + * pointers and the remaining space is padded with fs_ocsp[]. + * NOCSPTRS determines the size of this padding. One pointer (fs_csp) + * is taken away to point to a contiguous array of struct csum for + * all cylinder groups; a second (fs_maxcluster) points to an array + * of cluster sizes that is computed as cylinder groups are inspected; + * the third (fs_contigdirs) points to an array that tracks the + * creation of new directories; and the fourth (fs_active) is used + * by snapshots. + */ +#define NOCSPTRS ((128 / sizeof(void *)) - 4) + +/* + * A summary of contiguous blocks of various sizes is maintained + * in each cylinder group. Normally this is set by the initial + * value of fs_maxcontig. To conserve space, a maximum summary size + * is set by FS_MAXCONTIG. + */ +#define FS_MAXCONTIG 16 + +/* + * Unused value currently, FreeBSD compat. + */ +#define FSMAXSNAP 20 + +/* + * MINFREE gives the minimum acceptable percentage of file system + * blocks which may be free. If the freelist drops below this level + * only the superuser may continue to allocate blocks. This may + * be set to 0 if no reserve of free blocks is deemed necessary, + * however throughput drops by fifty percent if the file system + * is run at between 95% and 100% full; thus the minimum default + * value of fs_minfree is 5%. However, to get good clustering + * performance, 10% is a better choice. hence we use 10% as our + * default value. With 10% free space, fragmentation is not a + * problem, so we choose to optimize for time. + */ +#define MINFREE 5 +#define DEFAULTOPT FS_OPTTIME + +/* + * Grigoriy Orlov has done some extensive work to fine + * tune the layout preferences for directories within a filesystem. + * His algorithm can be tuned by adjusting the following parameters + * which tell the system the average file size and the average number + * of files per directory. These defaults are well selected for typical + * filesystems, but may need to be tuned for odd cases like filesystems + * being used for squid caches or news spools. + */ +#define AVFILESIZ 16384 /* expected average file size */ +#define AFPDIR 64 /* expected number of files per directory */ + +/* + * Per cylinder group information; summarized in blocks allocated + * from first cylinder group data blocks. These blocks have to be + * read in from fs_csaddr (size fs_cssize) in addition to the + * super block. + */ +struct csum { + int32_t cs_ndir; /* number of directories */ + int32_t cs_nbfree; /* number of free blocks */ + int32_t cs_nifree; /* number of free inodes */ + int32_t cs_nffree; /* number of free frags */ +}; + +struct csum_total { + int64_t cs_ndir; /* number of directories */ + int64_t cs_nbfree; /* number of free blocks */ + int64_t cs_nifree; /* number of free inodes */ + int64_t cs_nffree; /* number of free frags */ + int64_t cs_spare[4]; /* future expansion */ +}; + + +/* + * Super block for an FFS file system in memory. + */ +struct fs { + int32_t fs_firstfield; /* historic file system linked list, */ + int32_t fs_unused_1; /* used for incore super blocks */ + int32_t fs_sblkno; /* addr of super-block in filesys */ + int32_t fs_cblkno; /* offset of cyl-block in filesys */ + int32_t fs_iblkno; /* offset of inode-blocks in filesys */ + int32_t fs_dblkno; /* offset of first data after cg */ + int32_t fs_old_cgoffset; /* cylinder group offset in cylinder */ + int32_t fs_old_cgmask; /* used to calc mod fs_ntrak */ + int32_t fs_old_time; /* last time written */ + int32_t fs_old_size; /* number of blocks in fs */ + int32_t fs_old_dsize; /* number of data blocks in fs */ + int32_t fs_ncg; /* number of cylinder groups */ + int32_t fs_bsize; /* size of basic blocks in fs */ + int32_t fs_fsize; /* size of frag blocks in fs */ + int32_t fs_frag; /* number of frags in a block in fs */ +/* these are configuration parameters */ + int32_t fs_minfree; /* minimum percentage of free blocks */ + int32_t fs_old_rotdelay; /* num of ms for optimal next block */ + int32_t fs_old_rps; /* disk revolutions per second */ +/* these fields can be computed from the others */ + int32_t fs_bmask; /* ``blkoff'' calc of blk offsets */ + int32_t fs_fmask; /* ``fragoff'' calc of frag offsets */ + int32_t fs_bshift; /* ``lblkno'' calc of logical blkno */ + int32_t fs_fshift; /* ``numfrags'' calc number of frags */ +/* these are configuration parameters */ + int32_t fs_maxcontig; /* max number of contiguous blks */ + int32_t fs_maxbpg; /* max number of blks per cyl group */ +/* these fields can be computed from the others */ + int32_t fs_fragshift; /* block to frag shift */ + int32_t fs_fsbtodb; /* fsbtodb and dbtofsb shift constant */ + int32_t fs_sbsize; /* actual size of super block */ + int32_t fs_spare1[2]; /* old fs_csmask */ + /* old fs_csshift */ + int32_t fs_nindir; /* value of NINDIR */ + int32_t fs_inopb; /* value of INOPB */ + int32_t fs_old_nspf; /* value of NSPF */ +/* yet another configuration parameter */ + int32_t fs_optim; /* optimization preference, see below */ +/* these fields are derived from the hardware */ + int32_t fs_old_npsect; /* # sectors/track including spares */ + int32_t fs_old_interleave; /* hardware sector interleave */ + int32_t fs_old_trackskew; /* sector 0 skew, per track */ +/* fs_id takes the space of the unused fs_headswitch and fs_trkseek fields */ + int32_t fs_id[2]; /* unique file system id */ +/* sizes determined by number of cylinder groups and their sizes */ + int32_t fs_old_csaddr; /* blk addr of cyl grp summary area */ + int32_t fs_cssize; /* size of cyl grp summary area */ + int32_t fs_cgsize; /* cylinder group size */ +/* these fields are derived from the hardware */ + int32_t fs_spare2; /* old fs_ntrak */ + int32_t fs_old_nsect; /* sectors per track */ + int32_t fs_old_spc; /* sectors per cylinder */ + int32_t fs_old_ncyl; /* cylinders in file system */ + int32_t fs_old_cpg; /* cylinders per group */ + int32_t fs_ipg; /* inodes per group */ + int32_t fs_fpg; /* blocks per group * fs_frag */ +/* this data must be re-computed after crashes */ + struct csum fs_old_cstotal; /* cylinder summary information */ +/* these fields are cleared at mount time */ + int8_t fs_fmod; /* super block modified flag */ + int8_t fs_clean; /* file system is clean flag */ + int8_t fs_ronly; /* mounted read-only flag */ + uint8_t fs_old_flags; /* see FS_ flags below */ + u_char fs_fsmnt[MAXMNTLEN]; /* name mounted on */ + u_char fs_volname[MAXVOLLEN]; /* volume name */ + uint64_t fs_swuid; /* system-wide uid */ + int32_t fs_pad; +/* these fields retain the current block allocation info */ + int32_t fs_cgrotor; /* last cg searched (UNUSED) */ + void *fs_ocsp[NOCSPTRS]; /* padding; was list of fs_cs buffers */ + u_int8_t *fs_contigdirs; /* # of contiguously allocated dirs */ + struct csum *fs_csp; /* cg summary info buffer for fs_cs */ + int32_t *fs_maxcluster; /* max cluster in each cyl group */ + u_int *fs_active; /* used by snapshots to track fs */ + int32_t fs_old_cpc; /* cyl per cycle in postbl */ +/* this area is otherwise allocated unless fs_old_flags & FS_FLAGS_UPDATED */ + int32_t fs_maxbsize; /* maximum blocking factor permitted */ + int64_t fs_sparecon64[17]; /* old rotation block list head */ + int64_t fs_sblockloc; /* byte offset of standard superblock */ + struct csum_total fs_cstotal; /* cylinder summary information */ + int64_t fs_time; /* last time written */ + int64_t fs_size; /* number of blocks in fs */ + int64_t fs_dsize; /* number of data blocks in fs */ + int64_t fs_csaddr; /* blk addr of cyl grp summary area */ + int64_t fs_pendingblocks; /* blocks in process of being freed */ + int32_t fs_pendinginodes; /* inodes in process of being freed */ + int32_t fs_snapinum[FSMAXSNAP];/* list of snapshot inode numbers */ +/* back to stuff that has been around a while */ + int32_t fs_avgfilesize; /* expected average file size */ + int32_t fs_avgfpdir; /* expected # of files per directory */ + int32_t fs_save_cgsize; /* save real cg size to use fs_bsize */ + int32_t fs_sparecon32[26]; /* reserved for future constants */ + uint32_t fs_flags; /* see FS_ flags below */ +/* back to stuff that has been around a while (again) */ + int32_t fs_contigsumsize; /* size of cluster summary array */ + int32_t fs_maxsymlinklen; /* max length of an internal symlink */ + int32_t fs_old_inodefmt; /* format of on-disk inodes */ + u_int64_t fs_maxfilesize; /* maximum representable file size */ + int64_t fs_qbmask; /* ~fs_bmask for use with 64-bit size */ + int64_t fs_qfmask; /* ~fs_fmask for use with 64-bit size */ + int32_t fs_state; /* validate fs_clean field (UNUSED) */ + int32_t fs_old_postblformat; /* format of positional layout tables */ + int32_t fs_old_nrpos; /* number of rotational positions */ + int32_t fs_spare5[2]; /* old fs_postbloff */ + /* old fs_rotbloff */ + int32_t fs_magic; /* magic number */ +}; + +#define fs_old_postbloff fs_spare5[0] +#define fs_old_rotbloff fs_spare5[1] +#define fs_old_postbl_start fs_maxbsize +#define fs_old_headswitch fs_id[0] +#define fs_old_trkseek fs_id[1] +#define fs_old_csmask fs_spare1[0] +#define fs_old_csshift fs_spare1[1] + +#define FS_42POSTBLFMT -1 /* 4.2BSD rotational table format */ +#define FS_DYNAMICPOSTBLFMT 1 /* dynamic rotational table format */ + +#define old_fs_postbl(fs_, cylno, opostblsave) \ + ((((fs_)->fs_old_postblformat == FS_42POSTBLFMT) || \ + ((fs_)->fs_old_postbloff == offsetof(struct fs, fs_old_postbl_start))) \ + ? ((int16_t *)(opostblsave) + (cylno) * (fs_)->fs_old_nrpos) \ + : ((int16_t *)((uint8_t *)(fs_) + \ + (fs_)->fs_old_postbloff) + (cylno) * (fs_)->fs_old_nrpos)) +#define old_fs_rotbl(fs) \ + (((fs)->fs_old_postblformat == FS_42POSTBLFMT) \ + ? ((uint8_t *)(&(fs)->fs_magic+1)) \ + : ((uint8_t *)((uint8_t *)(fs) + (fs)->fs_old_rotbloff))) + +/* + * File system identification + */ +#define FS_UFS1_MAGIC 0x011954 /* UFS1 fast file system magic number */ +#define FS_UFS2_MAGIC 0x19540119 /* UFS2 fast file system magic number */ +#define FS_UFS1_MAGIC_SWAPPED 0x54190100 +#define FS_UFS2_MAGIC_SWAPPED 0x19015419 +#define FS_OKAY 0x7c269d38 /* superblock checksum */ +#define FS_42INODEFMT -1 /* 4.2BSD inode format */ +#define FS_44INODEFMT 2 /* 4.4BSD inode format */ + +/* + * File system clean flags + */ +#define FS_ISCLEAN 0x01 +#define FS_WASCLEAN 0x02 + +/* + * Preference for optimization. + */ +#define FS_OPTTIME 0 /* minimize allocation time */ +#define FS_OPTSPACE 1 /* minimize disk fragmentation */ + +/* + * File system flags + */ +#define FS_UNCLEAN 0x01 /* file system not clean at mount (unused) */ +#define FS_DOSOFTDEP 0x02 /* file system using soft dependencies */ +#define FS_NEEDSFSCK 0x04 /* needs sync fsck (FreeBSD compat, unused) */ +#define FS_INDEXDIRS 0x08 /* kernel supports indexed directories */ +#define FS_ACLS 0x10 /* file system has ACLs enabled */ +#define FS_MULTILABEL 0x20 /* file system is MAC multi-label */ +#define FS_FLAGS_UPDATED 0x80 /* flags have been moved to new location */ + +/* + * File system internal flags, also in fs_flags. + * (Pick highest number to avoid conflicts with others) + */ +#define FS_SWAPPED 0x80000000 /* file system is endian swapped */ +#define FS_INTERNAL 0x80000000 /* mask for internal flags */ + +/* + * The size of a cylinder group is calculated by CGSIZE. The maximum size + * is limited by the fact that cylinder groups are at most one block. + * Its size is derived from the size of the maps maintained in the + * cylinder group and the (struct cg) size. + */ +#define CGSIZE_IF(fs, ipg, fpg) \ + /* base cg */ (sizeof(struct cg) + sizeof(int32_t) + \ + /* old btotoff */ (fs)->fs_old_cpg * sizeof(int32_t) + \ + /* old boff */ (fs)->fs_old_cpg * sizeof(u_int16_t) + \ + /* inode map */ howmany((ipg), NBBY) + \ + /* block map */ howmany((fpg), NBBY) +\ + /* if present */ ((fs)->fs_contigsumsize <= 0 ? 0 : \ + /* cluster sum */ (fs)->fs_contigsumsize * sizeof(int32_t) + \ + /* cluster map */ howmany(fragstoblks(fs, (fpg)), NBBY))) + +#define CGSIZE(fs) CGSIZE_IF((fs), (fs)->fs_ipg, (fs)->fs_fpg) + +/* + * The minimal number of cylinder groups that should be created. + */ +#define MINCYLGRPS 4 + + +/* + * Convert cylinder group to base address of its global summary info. + */ +#define fs_cs(fs, indx) fs_csp[indx] + +/* + * Cylinder group block for a file system. + */ +#define CG_MAGIC 0x090255 +struct cg { + int32_t cg_firstfield; /* historic cyl groups linked list */ + int32_t cg_magic; /* magic number */ + int32_t cg_old_time; /* time last written */ + int32_t cg_cgx; /* we are the cgx'th cylinder group */ + int16_t cg_old_ncyl; /* number of cyl's this cg */ + int16_t cg_old_niblk; /* number of inode blocks this cg */ + int32_t cg_ndblk; /* number of data blocks this cg */ + struct csum cg_cs; /* cylinder summary information */ + int32_t cg_rotor; /* position of last used block */ + int32_t cg_frotor; /* position of last used frag */ + int32_t cg_irotor; /* position of last used inode */ + int32_t cg_frsum[MAXFRAG]; /* counts of available frags */ + int32_t cg_old_btotoff; /* (int32) block totals per cylinder */ + int32_t cg_old_boff; /* (u_int16) free block positions */ + int32_t cg_iusedoff; /* (u_int8) used inode map */ + int32_t cg_freeoff; /* (u_int8) free block map */ + int32_t cg_nextfreeoff; /* (u_int8) next available space */ + int32_t cg_clustersumoff; /* (u_int32) counts of avail clusters */ + int32_t cg_clusteroff; /* (u_int8) free cluster map */ + int32_t cg_nclusterblks; /* number of clusters this cg */ + int32_t cg_niblk; /* number of inode blocks this cg */ + int32_t cg_initediblk; /* last initialized inode */ + int32_t cg_sparecon32[3]; /* reserved for future use */ + int64_t cg_time; /* time last written */ + int64_t cg_sparecon64[3]; /* reserved for future use */ + u_int8_t cg_space[1]; /* space for cylinder group maps */ +/* actually longer */ +}; + +/* + * The following structure is defined + * for compatibility with old file systems. + */ +struct ocg { + int32_t cg_firstfield; /* historic linked list of cyl groups */ + int32_t cg_unused_1; /* used for incore cyl groups */ + int32_t cg_time; /* time last written */ + int32_t cg_cgx; /* we are the cgx'th cylinder group */ + int16_t cg_ncyl; /* number of cyl's this cg */ + int16_t cg_niblk; /* number of inode blocks this cg */ + int32_t cg_ndblk; /* number of data blocks this cg */ + struct csum cg_cs; /* cylinder summary information */ + int32_t cg_rotor; /* position of last used block */ + int32_t cg_frotor; /* position of last used frag */ + int32_t cg_irotor; /* position of last used inode */ + int32_t cg_frsum[8]; /* counts of available frags */ + int32_t cg_btot[32]; /* block totals per cylinder */ + int16_t cg_b[32][8]; /* positions of free blocks */ + u_int8_t cg_iused[256]; /* used inode map */ + int32_t cg_magic; /* magic number */ + u_int8_t cg_free[1]; /* free block map */ +/* actually longer */ +}; + + +/* + * Macros for access to cylinder group array structures. + */ +#define old_cg_blktot_old(cgp, ns) \ + (((struct ocg *)(cgp))->cg_btot) +#define old_cg_blks_old(fs, cgp, cylno, ns) \ + (((struct ocg *)(cgp))->cg_b[cylno]) + +#define old_cg_blktot_new(cgp, ns) \ + ((int32_t *)((u_int8_t *)(cgp) + \ + ufs_rw32((cgp)->cg_old_btotoff, (ns)))) +#define old_cg_blks_new(fs, cgp, cylno, ns) \ + ((int16_t *)((u_int8_t *)(cgp) + \ + ufs_rw32((cgp)->cg_old_boff, (ns))) + (cylno) * (fs)->fs_old_nrpos) + +#define old_cg_blktot(cgp, ns) \ + ((ufs_rw32((cgp)->cg_magic, (ns)) != CG_MAGIC) ? \ + old_cg_blktot_old(cgp, ns) : old_cg_blktot_new(cgp, ns)) +#define old_cg_blks(fs, cgp, cylno, ns) \ + ((ufs_rw32((cgp)->cg_magic, (ns)) != CG_MAGIC) ? \ + old_cg_blks_old(fs, cgp, cylno, ns) : old_cg_blks_new(fs, cgp, cylno, ns)) + +#define cg_inosused_new(cgp, ns) \ + ((u_int8_t *)((u_int8_t *)(cgp) + \ + ufs_rw32((cgp)->cg_iusedoff, (ns)))) +#define cg_blksfree_new(cgp, ns) \ + ((u_int8_t *)((u_int8_t *)(cgp) + \ + ufs_rw32((cgp)->cg_freeoff, (ns)))) +#define cg_chkmagic_new(cgp, ns) \ + (ufs_rw32((cgp)->cg_magic, (ns)) == CG_MAGIC) + +#define cg_inosused_old(cgp, ns) \ + (((struct ocg *)(cgp))->cg_iused) +#define cg_blksfree_old(cgp, ns) \ + (((struct ocg *)(cgp))->cg_free) +#define cg_chkmagic_old(cgp, ns) \ + (ufs_rw32(((struct ocg *)(cgp))->cg_magic, (ns)) == CG_MAGIC) + +#define cg_inosused(cgp, ns) \ + ((ufs_rw32((cgp)->cg_magic, (ns)) != CG_MAGIC) ? \ + cg_inosused_old(cgp, ns) : cg_inosused_new(cgp, ns)) +#define cg_blksfree(cgp, ns) \ + ((ufs_rw32((cgp)->cg_magic, (ns)) != CG_MAGIC) ? \ + cg_blksfree_old(cgp, ns) : cg_blksfree_new(cgp, ns)) +#define cg_chkmagic(cgp, ns) \ + (cg_chkmagic_new(cgp, ns) || cg_chkmagic_old(cgp, ns)) + +#define cg_clustersfree(cgp, ns) \ + ((u_int8_t *)((u_int8_t *)(cgp) + \ + ufs_rw32((cgp)->cg_clusteroff, (ns)))) +#define cg_clustersum(cgp, ns) \ + ((int32_t *)((u_int8_t *)(cgp) + \ + ufs_rw32((cgp)->cg_clustersumoff, (ns)))) + + +/* + * Turn file system block numbers into disk block addresses. + * This maps file system blocks to device size blocks. + */ +#define fsbtodb(fs, b) ((b) << (fs)->fs_fsbtodb) +#define dbtofsb(fs, b) ((b) >> (fs)->fs_fsbtodb) + +/* + * Cylinder group macros to locate things in cylinder groups. + * They calc file system addresses of cylinder group data structures. + */ +#define cgbase(fs, c) (((daddr_t)(fs)->fs_fpg) * (c)) +#define cgstart_ufs1(fs, c) \ + (cgbase(fs, c) + (fs)->fs_old_cgoffset * ((c) & ~((fs)->fs_old_cgmask))) +#define cgstart_ufs2(fs, c) cgbase((fs), (c)) +#define cgstart(fs, c) ((fs)->fs_magic == FS_UFS2_MAGIC \ + ? cgstart_ufs2((fs), (c)) : cgstart_ufs1((fs), (c))) +#define cgdmin(fs, c) (cgstart(fs, c) + (fs)->fs_dblkno) /* 1st data */ +#define cgimin(fs, c) (cgstart(fs, c) + (fs)->fs_iblkno) /* inode blk */ +#define cgsblock(fs, c) (cgstart(fs, c) + (fs)->fs_sblkno) /* super blk */ +#define cgtod(fs, c) (cgstart(fs, c) + (fs)->fs_cblkno) /* cg block */ + +/* + * Macros for handling inode numbers: + * inode number to file system block offset. + * inode number to cylinder group number. + * inode number to file system block address. + */ +#define ino_to_cg(fs, x) ((x) / (fs)->fs_ipg) +#define ino_to_fsba(fs, x) \ + ((daddr_t)(cgimin(fs, ino_to_cg(fs, x)) + \ + (blkstofrags((fs), (((x) % (fs)->fs_ipg) / INOPB(fs)))))) +#define ino_to_fsbo(fs, x) ((x) % INOPB(fs)) + +/* + * Give cylinder group number for a file system block. + * Give cylinder group block number for a file system block. + */ +#define dtog(fs, d) ((d) / (fs)->fs_fpg) +#define dtogd(fs, d) ((d) % (fs)->fs_fpg) + +/* + * Extract the bits for a block from a map. + * Compute the cylinder and rotational position of a cyl block addr. + */ +#define blkmap(fs, map, loc) \ + (((map)[(loc) / NBBY] >> ((loc) % NBBY)) & (0xff >> (NBBY - (fs)->fs_frag))) +#define old_cbtocylno(fs, bno) \ + (fsbtodb(fs, bno) / (fs)->fs_old_spc) +#define old_cbtorpos(fs, bno) \ + ((fs)->fs_old_nrpos <= 1 ? 0 : \ + (fsbtodb(fs, bno) % (fs)->fs_old_spc / (fs)->fs_old_nsect * (fs)->fs_old_trackskew + \ + fsbtodb(fs, bno) % (fs)->fs_old_spc % (fs)->fs_old_nsect * (fs)->fs_old_interleave) % \ + (fs)->fs_old_nsect * (fs)->fs_old_nrpos / (fs)->fs_old_npsect) + +/* + * The following macros optimize certain frequently calculated + * quantities by using shifts and masks in place of divisions + * modulos and multiplications. + */ +#define blkoff(fs, loc) /* calculates (loc % fs->fs_bsize) */ \ + ((loc) & (fs)->fs_qbmask) +#define fragoff(fs, loc) /* calculates (loc % fs->fs_fsize) */ \ + ((loc) & (fs)->fs_qfmask) +#define lfragtosize(fs, frag) /* calculates ((off_t)frag * fs->fs_fsize) */ \ + (((off_t)(frag)) << (fs)->fs_fshift) +#define lblktosize(fs, blk) /* calculates ((off_t)blk * fs->fs_bsize) */ \ + (((off_t)(blk)) << (fs)->fs_bshift) +#define lblkno(fs, loc) /* calculates (loc / fs->fs_bsize) */ \ + ((loc) >> (fs)->fs_bshift) +#define numfrags(fs, loc) /* calculates (loc / fs->fs_fsize) */ \ + ((loc) >> (fs)->fs_fshift) +#define blkroundup(fs, size) /* calculates roundup(size, fs->fs_bsize) */ \ + (((size) + (fs)->fs_qbmask) & (fs)->fs_bmask) +#define fragroundup(fs, size) /* calculates roundup(size, fs->fs_fsize) */ \ + (((size) + (fs)->fs_qfmask) & (fs)->fs_fmask) +#define fragstoblks(fs, frags) /* calculates (frags / fs->fs_frag) */ \ + ((frags) >> (fs)->fs_fragshift) +#define blkstofrags(fs, blks) /* calculates (blks * fs->fs_frag) */ \ + ((blks) << (fs)->fs_fragshift) +#define fragnum(fs, fsb) /* calculates (fsb % fs->fs_frag) */ \ + ((fsb) & ((fs)->fs_frag - 1)) +#define blknum(fs, fsb) /* calculates rounddown(fsb, fs->fs_frag) */ \ + ((fsb) &~ ((fs)->fs_frag - 1)) + +/* + * Determine the number of available frags given a + * percentage to hold in reserve. + */ +#define freespace(fs, percentreserved) \ + (blkstofrags((fs), (fs)->fs_cstotal.cs_nbfree) + \ + (fs)->fs_cstotal.cs_nffree - \ + (((off_t)((fs)->fs_dsize)) * (percentreserved) / 100)) + +/* + * Determining the size of a file block in the file system. + */ +#define blksize(fs, ip, lbn) \ + (((lbn) >= NDADDR || (ip)->i_size >= lblktosize(fs, (lbn) + 1)) \ + ? (fs)->fs_bsize \ + : (fragroundup(fs, blkoff(fs, (ip)->i_size)))) + +#define sblksize(fs, size, lbn) \ + (((lbn) >= NDADDR || (size) >= ((lbn) + 1) << (fs)->fs_bshift) \ + ? (fs)->fs_bsize \ + : (fragroundup(fs, blkoff(fs, (size))))) + + +/* + * Number of inodes in a secondary storage block/fragment. + */ +#define INOPB(fs) ((fs)->fs_inopb) +#define INOPF(fs) ((fs)->fs_inopb >> (fs)->fs_fragshift) + +/* + * Number of indirects in a file system block. + */ +#define NINDIR(fs) ((fs)->fs_nindir) + +/* + * Apple UFS Label: + * We check for this to decide to use APPLEUFS_DIRBLKSIZ + */ +#define APPLEUFS_LABEL_MAGIC 0x4c41424c /* LABL */ +#define APPLEUFS_LABEL_SIZE 1024 +#define APPLEUFS_LABEL_OFFSET (BBSIZE - APPLEUFS_LABEL_SIZE) /* located at 7k */ +#define APPLEUFS_LABEL_VERSION 1 +#define APPLEUFS_MAX_LABEL_NAME 512 + +#if 0 +struct appleufslabel { + u_int32_t ul_magic; + u_int16_t ul_checksum; + u_int16_t ul_unused0; + u_int32_t ul_version; + u_int32_t ul_time; + u_int16_t ul_namelen; + u_char ul_name[APPLEUFS_MAX_LABEL_NAME]; /* Warning: may not be null terminated */ + u_int16_t ul_unused1; + u_int64_t ul_uuid; /* Note this is only 4 byte aligned */ + u_char ul_reserved[24]; + u_char ul_unused[460]; +} __attribute__((__packed__)); +#endif + + +#endif /* !_UFS_FFS_FS_H_ */ diff --git a/reactos/drivers/filesystems/ffs/inc/gplntifs.h b/reactos/drivers/filesystems/ffs/inc/gplntifs.h new file mode 100644 index 00000000000..d4d9f3a6938 --- /dev/null +++ b/reactos/drivers/filesystems/ffs/inc/gplntifs.h @@ -0,0 +1,9491 @@ +/* + This is a free version of the file ntifs.h, release 58. + The purpose of this include file is to build file system and + file system filter drivers for Windows. + Copyright (C) 1999-2015 Bo Brantén. + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + The GNU General Public License is also available from: + http://www.gnu.org/copyleft/gpl.html + + Windows and Windows NT are either registered trademarks or trademarks of + Microsoft Corporation in the United States and/or other countries. + + DISCLAIMER: I do not encourage anyone to use this include file to build + drivers used in production. Some of the information in this file may not + be available in other publications intended for similar use. Some of the + information in this file may have different names than in other + publications even though they describe the same thing. + + NOTE: This file should be used with the Microsoft® Windows® Driver + Development Kit (DDK) while the file wdkundoc.h is a subset of this + file that should be used with the Microsoft Windows Driver Kit (WDK). + + Please send comments, corrections and contributions to bosse@acc.umu.se. + + The most recent version of this file is available from: + http://www.acc.umu.se/~bosse/ntifs.h + + The most recent version of the file wdkundoc.h is available from: + http://www.acc.umu.se/~bosse/wdkundoc.h + + Thanks to: + Andrey Shedel, Luigi Mori, Louis Joubert, Itai Shaham, David Welch, + Emanuele Aliberti, Anton Altaparmakov, Dan Partelly, Mamaich, Yossi + Yaffe, Gunnar André Dalsnes, Vadim V Vorobev, Ashot Oganesyan K, + Oleg Nikityenko, Matt Wu, Tomas Olsson, Raaf, Anthony Choi, Alexey + Logachyov, Marc-Antoine Ruel, Vyacheslav I. Levtchenko, Yuri Polyakov, + Bruno Milot, Alex Vlasov, Dan Fulger, Petr Semerad, Sobame La Garompa, + Jérôme Hodé and Darja Isaksson. + + Revision history: + + 58. 2015-06-11 + Added: + Externals: + PsInitialSystemProcess + HalPrivateDispatchTable + KeLoaderBlock + KeI386MachineType + KiBugCheckData + InitSafeBootMode + KiEnableTimerWatchdog + KdComPortInUse + KdEnteredDebugger + MmBadPointer + NlsLeadByteInfo + NlsOemLeadByteInfo + NlsMbCodePageTag + NlsMbOemCodePageTag + NlsAnsiCodePage + NlsOemCodePage + IoStatisticsLock + IoReadOperationCount + IoWriteOperationCount + IoReadTransferCount + IoWriteTransferCount + KeDcacheFlushCount + KeIcacheFlushCount + CcFastMdlReadWait + CcFastReadNotPossible + CcFastReadWait + IoAdapterObjectType + IoDeviceObjectType + MmSectionObjectType + PsProcessType + PsThreadType + ExDesktopObjectType + ExWindowStationObjectType + IoDeviceHandlerObjectType + LpcPortObjectType + PsJobType + SeTokenObjectType + TmEnlistmentObjectType + TmResourceManagerObjectType + TmTransactionManagerObjectType + TmTransactionObjectType + CmKeyObjectType + IoDeviceHandlerObjectSize + POGOBuffer + psMUITest + PsUILanguageComitted + + 57. 2015-03-23 + Corrected: + ObGetObjectPointerCount + Added: + Function prototypes: + FsRtlTeardownPerFileContexts + FsRtlTeardownPerStreamContexts + + 56. 2008-07-31 + Corrected: + FSCTL_SET_SPARSE + FSRTL_COMMON_FCB_HEADER + Added: + Defines: + FSRTL_XXX + IO_REPARSE_TAG_XXX + Data types: + FSRTL_ADVANCED_FCB_HEADER + Function prototypes: + FsRtlSetupAdvancedHeader + + 55. 2006-05-15 + Corrected: + TOKEN_OBJECT + Added: + Data types: + SEP_AUDIT_POLICY_VISTA + SID_AND_ATTRIBUTES_HASH + + 54. 2006-05-14 + Corrected: + EXTENDED_IO_STACK_LOCATION + + 53. 2005-11-06 + Added: + Function prototypes: + RtlRandom + RtlRandomEx + RtlSecondsSince1980ToTime + RtlTimeToSecondsSince1980 + + 52. 2005-11-05 + Corrected: + OBJECT_NAME + TOKEN_OBJECT + + 51. 2005-10-16 + Corrected: + ETHREAD + GDI_TEB_BATCH + MMADDRESS_NODE + TEB + + 50. 2005-10-15 + Added: + Data types: + READ_LIST + Function prototypes: + IoAttachDeviceToDeviceStackSafe + IoCheckQuerySetFileInformation + IoCheckQuerySetVolumeInformation + IoCreateFileSpecifyDeviceObjectHint + IoCreateStreamFileObjectEx + IoEnumerateDeviceObjectList + IoGetDeviceAttachmentBaseRef + IoGetDiskDeviceObject + IoGetLowerDeviceObject + IoIsFileOriginRemote + IoQueryFileDosDeviceName + IoQueueThreadIrp + IoSetFileOrigin + KeAcquireQueuedSpinLock + KeInitializeMutant + KeReadStateMutant + KeReleaseMutant + KeReleaseQueuedSpinLock + KeSetIdealProcessorThread + KeSetKernelStackSwapEnable + KeTryToAcquireQueuedSpinLock + MmPrefetchPages + ObDereferenceSecurityDescriptor + ObLogSecurityDescriptor + ObReferenceSecurityDescriptor + PoQueueShutdownWorkItem + RtlxUnicodeStringToAnsiSize + SeAuditHardLinkCreation + SeAuditingHardLinkEvents + SeFilterToken + + 49. 2005-10-09 + Corrected: + EPROCESS + KTHREAD + MMSUPPORT_FLAGS + MMSUPPORT + OBJECT_HEADER + OBJECT_TYPE_INITIALIZER + OBJECT_TYPE + TEB + KeInsertQueueApc + Added: + Defines: + OB_FLAG_XXX + OB_SECURITY_CHARGE + Data types: + ACTIVATION_CONTEXT_STACK + GDI_TEB_BATCH + HANDLE_INFO + KGUARDED_MUTEX + MMADDRESS_NODE + MM_AVL_TABLE + OBJECT_CREATE_INFORMATION + OBJECT_CREATOR_INFO + OBJECT_DIRECTORY + OBJECT_DIRECTORY_ITEM + OBJECT_HANDLE_DB + OBJECT_HANDLE_DB_LIST + OBJECT_HEADER_FLAGS + OBJECT_NAME + OBJECT_QUOTA_CHARGES + OBJECT_QUOTA_INFO + QUOTA_BLOCK + RTL_ACTIVATION_CONTEXT_STACK_FRAME + TEB_ACTIVE_FRAME + TEB_ACTIVE_FRAME_CONTEXT + Wx86ThreadState + Function prototypes: + FsRtlAcquireFileExclusive + FsRtlBalanceReads + FsRtlDissectDbcs + FsRtlDoesDbcsContainWildCards + FsRtlIsDbcsInExpression + FsRtlIsFatDbcsLegal + FsRtlIsHpfsDbcsLegal + FsRtlIsPagingFile + FsRtlIsTotalDeviceFailure + FsRtlMdlReadDev + FsRtlPostPagingFileStackOverflow + FsRtlPostStackOverflow + FsRtlPrepareMdlWriteDev + FsRtlReleaseFile + + 48. 2005-04-16 + Added: + Data types: + THREAD_BASIC_INFORMATION + Function prototypes: + ZwQueryInformationThread + + 47. 2005-03-08 + Corrected: + SYSTEM_PROCESSES_INFORMATION + TOKEN_OBJECT + KeInsertQueueApc + + 46. 2004-06-08 + Added: + Data types: + TOKEN_OBJECT + + 45. 2004-06-06 + Corrected: + SERVICE_DESCRIPTOR_TABLE + Added: + Defines: + TOKEN_SESSION_NOT_REFERENCED + TOKEN_SANDBOX_INERT + TOKEN_HAS_IMPERSONATE_PRIVILEGE + Function prototypes: + FsRtlDissectName + RtlOemStringToCountedUnicodeSize + RtlOemStringToUnicodeSize + RtlOemStringToUnicodeString + RtlUnicodeStringToOemSize + RtlUnicodeStringToOemString + RtlxOemStringToUnicodeSize + RtlxUnicodeStringToOemSize + + 44. 2003-05-06 + Added: + Function prototypes: + InbvAcquireDisplayOwnership + InbvCheckDisplayOwnership + InbvDisplayString + InbvEnableBootDriver + InbvEnableDisplayString + InbvInstallDisplayStringFilter + InbvIsBootDriverInstalled + InbvNotifyDisplayOwnershipLost + InbvResetDisplay + InbvSetScrollRegion + InbvSetTextColor + InbvSolidColorFill + + 43. 2003-04-07 + Added: + Data types: + MCB + Function prototypes: + FsRtlAddMcbEntry + FsRtlInitializeMcb + FsRtlLookupLastMcbEntry + FsRtlLookupMcbEntry + FsRtlNotifyFilterChangeDirectory + FsRtlNotifyFilterReportChange + FsRtlNumberOfRunsInMcb + FsRtlRemoveMcbEntry + FsRtlTruncateMcb + FsRtlUninitializeMcb + + 42. 2003-03-30 + Corrected: + SYSTEM_CACHE_INFORMATION + SYSTEM_INFORMATION_CLASS + Added: + Data types: + SYSTEM_XXX_INFORMATION + THREAD_STATE + + 41. 2003-01-03 + Corrected: + CcMapData + PsDereferenceImpersonationToken + PsDereferencePrimaryToken + PsGetProcessExitTime + PsReferencePrimaryToken + Added: + Defines: + MAP_XXX + Function prototypes: + CcMdlWriteAbort + PsAssignImpersonationToken + PsChargeProcessNonPagedPoolQuota + PsChargeProcessPagedPoolQuota + PsChargeProcessPoolQuota + PsDisableImpersonation + PsImpersonateClient + PsIsSystemThread + PsRestoreImpersonation + SeDeleteAccessState + ZwOpenProcessTokenEx + ZwOpenThreadTokenEx + + 40. 2002-10-02 + Corrected: + HANDLE_TABLE_ENTRY + Added: + Defines: + FSRTL_FLAG_ADVANCED_HEADER + FSRTL_FLAG2_SUPPORTS_FILTER_CONTEXTS + FSRTL_FLAG2_PURGE_WHEN_MAPPED + Data types: + FILE_ID_BOTH_DIR_INFORMATION + FILE_ID_FULL_DIR_INFORMATION + + 39. 2002-08-04 + Added: + Data types: + LARGE_MCB + Function prototypes: + FsRtlAddLargeMcbEntry + FsRtlGetNextLargeMcbEntry + FsRtlInitializeLargeMcb + FsRtlLookupLargeMcbEntry + FsRtlLookupLastLargeMcbEntry + FsRtlLookupLastLargeMcbEntryAndIndex + FsRtlNumberOfRunsInLargeMcb + FsRtlRemoveLargeMcbEntry + FsRtlResetLargeMcb + FsRtlSplitLargeMcb + FsRtlTruncateLargeMcb + FsRtlUninitializeLargeMcb + + 38. 2002-06-30 + Added: + Defines: + FILE_READ_ONLY_VOLUME + Function prototypes: + FsRtlAllocateResource + FsRtlIncrementCcFastReadNotPossible + FsRtlIncrementCcFastReadNoWait + FsRtlIncrementCcFastReadResourceMiss + FsRtlIncrementCcFastReadWait + KeIsAttachedProcess + KeIsExecutingDpc + KeRevertToUserAffinityThread + KeUpdateSystemTime + PsGetCurrentProcessSessionId + PsGetCurrentThreadPreviousMode + PsGetCurrentThreadStackBase + PsGetCurrentThreadStackLimit + RtlGetNtGlobalFlags + + 37. 2002-05-18 + Uppdated for Windows XP: + EPROCESS + ETHREAD + KPROCESS + KTHREAD + MMSUPPORT_FLAGS + MMSUPPORT + PRIVATE_CACHE_MAP_FLAGS + PRIVATE_CACHE_MAP + SHARED_CACHE_MAP + Corrected: + VACB + Added: + Data types: + EPROCESS_QUOTA_ENTRY + EPROCESS_QUOTA_BLOCK + EX_FAST_REF + EX_PUSH_LOCK + EX_RUNDOWN_REF + PAGEFAULT_HISTORY + SE_AUDIT_PROCESS_CREATION_INFO + SECTION_OBJECT + TERMINATION_PORT + + 36. 2002-05-14 + Corrected: + FILE_FS_FULL_SIZE_INFORMATION + + 35. 2002-03-23 + Added: + Defines: + COMPRESSION_XXX + Data types: + COMPRESSED_DATA_INFO + OBJECT_HEADER + VAD_HEADER + Function prototypes: + CcWaitForCurrentLazyWriterActivity + FsRtlCheckOplock + FsRtlCurrentBatchOplock + FsRtlDeregisterUncProvider + FsRtlInitializeOplock + FsRtlOplockFsctrl + FsRtlOplockIsFastIoPossible + FsRtlRegisterUncProvider + FsRtlUninitializeOplock + RtlCompressBuffer + RtlCompressChunks + RtlDecompressBuffer + RtlDecompressChunks + RtlDecompressFragment + RtlDescribeChunk + RtlGetCompressionWorkSpaceSize + RtlReserveChunk + + 34. 2002-02-14 + Corrected: + HARDWARE_PTE + Changed the use of _WIN32_WINNT to VER_PRODUCTBUILD since _WIN32_WINNT + is incorrectly defined in the Windows 2000 build environment included + in the Windows XP DDK. + + 33. 2002-01-20 + Added: + Function prototypes: + PsDereferenceImpersonationToken + PsDereferencePrimaryToken + + 32. 2002-01-18 + Corrected: + ObReferenceObjectByName + FILE_FS_OBJECT_ID_INFORMATION + FILE_OBJECTID_INFORMATION + Added: + Externals: + IoDriverObjectType + SeExports + Defines: + FILE_ACTION_XXX + FSCTL_XXX + IO_FILE_OBJECT_XXX + IRP_BEING_VERIFIED + TOKEN_XXX + Data types: + DEVICE_MAP + FILE_TRACKING_INFORMATION + SE_EXPORTS + Function prototypes: + SeEnableAccessToExports + + 31. 2001-12-23 + Corrected: + QueryQuota in EXTENDED_IO_STACK_LOCATION + FILE_LOCK + CcPinMappedData + CcPinRead + CcPreparePinWrite + FsRtlFastUnlockAll + FsRtlFastUnlockAllByKey + FsRtlFastUnlockSingle + FsRtlInitializeFileLock + FsRtlPrivateLock + FsRtlProcessFileLock + MmForceSectionClosed + MmIsRecursiveIoFault + SeImpersonateClient + SeImpersonateClientEx + Added: + Defines: + More FSRTL_FLAG_XXX + PIN_XXX + VACB_XXX + Data types: + REPARSE_DATA_BUFFER + Function prototypes: + CcCopyWriteWontFlush + CcGetFileSizePointer + CcGetFlushedValidData + CcIsFileCached + CcRemapBcb + ExDisableResourceBoostLite + ExQueryPoolBlockSize + FsRtlAllocateFileLock + FsRtlAreThereCurrentFileLocks + FsRtlFastLock + FsRtlFreeFileLock + IoCheckDesiredAccess + IoCheckEaBufferValidity + IoCheckFunctionAccess + IoCheckQuotaBufferValidity + IoCreateStreamFileObjectLite + IoFastQueryNetworkAttributes + IoGetRequestorProcessId + IoIsFileOpenedExclusively + IoIsSystemThread + IoIsValidNameGraftingBuffer + IoSynchronousPageWrite + IoThreadToProcess + KeInitializeQueue + KeInsertHeadQueue + KeInsertQueue + KeReadStateQueue + KeRemoveQueue + KeRundownQueue + MmSetAddressRangeModified + ObGetObjectPointerCount + ObMakeTemporaryObject + ObQueryObjectAuditingByHandle + PsChargePoolQuota + PsReturnPoolQuota + SeAppendPrivileges + SeAuditingFileEvents + SeAuditingFileOrGlobalEvents + SeCreateClientSecurity + SeCreateClientSecurityFromSubjectContext + SeDeleteClientSecurity + SeDeleteObjectAuditAlarm + SeFreePrivileges + SeLockSubjectContext + SeOpenObjectAuditAlarm + SeOpenObjectForDeleteAuditAlarm + SePrivilegeCheck + SeQueryAuthenticationIdToken + SeQuerySecurityDescriptorInfo + SeQuerySessionIdToken + SeSetAccessStateGenericMapping + SeSetSecurityDescriptorInfo + SeSetSecurityDescriptorInfoEx + SeTokenIsAdmin + SeTokenIsRestricted + SeTokenType + SeUnlockSubjectContext + + 30. 2001-10-24 + Corrected: + KINTERRUPT + OBJECT_TYPE + Added: + Defines: + More FSCTL_XXX + Data types: + BITMAP_RANGE + CreateMailslot in EXTENDED_IO_STACK_LOCATION + CreatePipe in EXTENDED_IO_STACK_LOCATION + QueryQuota in EXTENDED_IO_STACK_LOCATION + MAILSLOT_CREATE_PARAMETERS + MBCB + NAMED_PIPE_CREATE_PARAMETERS + PRIVATE_CACHE_MAP_FLAGS + PRIVATE_CACHE_MAP + SECURITY_CLIENT_CONTEXT + SHARED_CACHE_MAP + VACB + Function prototypes: + HalQueryRealTimeClock + HalSetRealTimeClock + PsGetProcessExitTime + PsIsThreadTerminating + PsLookupProcessThreadByCid + PsLookupThreadByThreadId + SeQueryAuthenticationIdToken + Externals: + KeServiceDescriptorTable + SePublicDefaultDacl + SeSystemDefaultDacl + + 29. 2001-10-06 + Added: + Defines: + FSRTL_VOLUME_XXX + Function prototypes: + FsRtlNotifyChangeDirectory + FsRtlNotifyReportChange + FsRtlNotifyVolumeEvent + + 28. 2001-09-16 + Added: + Function prototypes: + FsRtlNotifyInitializeSync + FsRtlNotifyUninitializeSync + SeImpersonateClientEx + SeReleaseSubjectContext + + 27. 2001-08-25 + Corrected: + KPROCESS + FILE_LOCK_ANCHOR + FsRtlNormalizeNtstatus + RtlSecondsSince1970ToTime + RtlTimeToSecondsSince1970 + SeQueryInformationToken + Added: + Defines: + FS_LFN_APIS + Data types: + FILE_LOCK_ENTRY + FILE_SHARED_LOCK_ENTRY + FILE_EXCLUSIVE_LOCK_ENTRY + Function prototypes: + FsRtlCheckLockForReadAccess + FsRtlCheckLockForWriteAccess + FsRtlFastUnlockAll + FsRtlFastUnlockAllByKey + FsRtlFastUnlockSingle + FsRtlGetFileSize + FsRtlGetNextFileLock + FsRtlInitializeFileLock + FsRtlPrivateLock + FsRtlProcessFileLock + FsRtlUninitializeFileLock + IoUnregisterFsRegistrationChange + PsLookupProcessByProcessId + SeQuerySubjectContextToken + + 26. 2001-04-28 + Added: + Defines: + FSCTL_XXX + Data types: + RTL_SPLAY_LINKS + TUNNEL + Function prototypes: + FsRtlAddToTunnelCache + FsRtlDeleteKeyFromTunnelCache + FsRtlDeleteTunnelCache + FsRtlFindInTunnelCache + FsRtlInitializeTunnelCache + IoSetDeviceToVerify + KeInitializeApc + KeInsertQueueApc + SeQueryInformationToken + + 25. 2001-04-05 + Corrected: + RtlImageNtHeader + LPC_XXX + OBJECT_BASIC_INFO + Added: + Defines: + SID_REVISION + Data types: + DIRECTORY_BASIC_INFORMATION + KINTERRUPT + OBJECT_HANDLE_ATTRIBUTE_INFO + PROCESS_PRIORITY_CLASS + SECTION_BASIC_INFORMATION + SECTION_IMAGE_INFORMATION + SECTION_INFORMATION_CLASS + Function prototypes: + RtlSecondsSince1970ToTime + RtlTimeToSecondsSince1970 + ZwAdjustPrivilegesToken + ZwAlertThread + ZwAccessCheckAndAuditAlarm + ZwClearEvent + ZwCloseObjectAuditAlarm + ZwCreateSection + ZwCreateSymbolicLinkObject + ZwDuplicateToken + ZwFlushInstructionCache + ZwFlushVirtualMemory + ZwInitiatePowerAction + ZwLoadKey + ZwNotifyChangeKey + ZwOpenThread + ZwPowerInformation + ZwPulseEvent + ZwQueryDefaultLocale + ZwQueryDefaultUILanguage + ZwQueryInformationProcess + ZwQueryInstallUILanguage + ZwQuerySection + ZwReplaceKey + ZwResetEvent + ZwRestoreKey + ZwSaveKey + ZwSetDefaultLocale + ZwSetDefaultUILanguage + ZwSetEvent + ZwSetInformationObject + ZwSetInformationProcess + ZwSetSecurityObject + ZwSetSystemTime + ZwTerminateProcess + ZwUnloadKey + ZwWaitForSingleObject + ZwWaitForMultipleObjects + ZwYieldExecution + Removed functions that is not exported in kernel mode: + CcZeroEndOfLastPage + RtlAllocateAndInitializeSid + ZwAcceptConnectPort + ZwCompleteConnectPort + ZwCreatePort + ZwCreateProcess + ZwCreateThread + ZwFlushBuffersFile + ZwGetContextThread + ZwImpersonateClientOfPort + ZwListenPort + ZwLockFile + ZwNotifyChangeDirectoryFile + ZwQueryInformationPort + ZwReadRequestData + ZwReplyPort + ZwReplyWaitReceivePort + ZwReplyWaitReplyPort + ZwRequestPort + ZwUnlockFile + ZwWriteRequestData + + 24. 2001-03-08 + Corrected: + EPROCESS + ETHREAD + FAST_IO_POSSIBLE + QueryEa in EXTENDED_IO_STACK_LOCATION + Added: + Defines: + Some more flags for FileSystemAttributes + Data types: + EXCEPTION_REGISTRATION_RECORD + FILE_FS_FULL_SIZE_INFORMATION + FILE_FS_OBJECT_ID_INFORMATION + HANDLE_TABLE_ENTRY + IO_CLIENT_EXTENSION + PS_IMPERSONATION_INFORMATION + SetEa and SetQuota in EXTENDED_IO_STACK_LOCATION + Function prototypes: + IoPageRead + KeStackAttachProcess + KeUnstackDetachProcess + MmMapViewOfSection + RtlSelfRelativeToAbsoluteSD + SeCreateAccessState + + 23. 2001-01-29 + Corrected: + FSCTL_GET_VOLUME_INFORMATION + FSCTL_READ_MFT_RECORD + HARDWARE_PTE + EPROCESS + ETHREAD + KAPC_STATE + KPROCESS + KTHREAD + MMSUPPORT + Added: + Data types: + KGDTENTRY + KIDTENTRY + MMSUPPORT_FLAGS + + 22. 2000-12-23 + Corrected: + EPROCESS + KPROCESS + Added: + Data types: + HARDWARE_PTE + MMSUPPORT + + 21. 2000-12-12 + Added: + Defines: + IO_TYPE_XXX + OB_TYPE_XXX + THREAD_STATE_XXX + Data types: + EPROCESS + ETHREAD + KAPC_STATE + KEVENT_PAIR + KPROCESS + KTHREAD + KQUEUE + SERVICE_DESCRIPTOR_TABLE + TEB + + 20. 2000-12-03 + Added: + Data types: + OBJECT_TYPE + Function prototypes: + ObCreateObject + ObInsertObject + ObReferenceObjectByName + + 19. 2000-11-25 + Removed a name from credits since the person want to be anonymous. + + 18. 2000-10-13 + Corrected: + PsReferenceImpersonationToken + Added: + Defines: + FILE_PIPE_XXX + LPC_XXX + MAILSLOT_XXX + PORT_XXX + FSCTL_GET_VOLUME_INFORMATION + FSCTL_READ_MFT_RECORD + FSCTL_MAILSLOT_PEEK + FSCTL_PIPE_XXX + Data types: + PORT_INFORMATION_CLASS + BITMAP_DESCRIPTOR + FILE_MAILSLOT_XXX + FILE_PIPE_XXX + MAPPING_PAIR + GET_RETRIEVAL_DESCRIPTOR + LPC_XXX + MOVEFILE_DESCRIPTOR + Function prototypes: + InitializeMessageHeader + MmForceSectionClosed + ZwAcceptConnectPort + ZwCompleteConnectPort + ZwConnectPort + ZwCreateEvent + ZwCreatePort + ZwImpersonateClientOfPort + ZwListenPort + ZwQueryInformationPort + ZwReadRequestData + ZwReplyPort + ZwReplyWaitReceivePort + ZwReplyWaitReplyPort + ZwRequestPort + ZwRequestWaitReplyPort + ZwWriteRequestData + + 17. 2000-05-21 + Added: + Function prototypes: + PsRevertToSelf + SeCreateClientSecurity + SeImpersonateClient + ZwDuplicateObject + + 16. 2000-03-28 + Added: + Defines: + FILE_STORAGE_TYPE_XXX + FILE_VC_XXX + IO_CHECK_CREATE_PARAMETERS + IO_ATTACH_DEVICE + IO_ATTACH_DEVICE_API + IO_COMPLETION_XXX + Data types: + IO_COMPLETION_INFORMATION_CLASS + OBJECT_INFO_CLASS + SYSTEM_INFORMATION_CLASS + FILE_LOCK_ANCHOR + IO_COMPLETION_BASIC_INFORMATION + OBJECT_BASIC_INFO + OBJECT_NAME_INFO + OBJECT_PROTECTION_INFO + OBJECT_TYPE_INFO + OBJECT_ALL_TYPES_INFO + SYSTEM_CACHE_INFORMATION + Function prototypes: + FsRtlAllocatePool + FsRtlAllocatePoolWithQuota + FsRtlAllocatePoolWithQuotaTag + FsRtlAllocatePoolWithTag + FsRtlAreNamesEqual + FsRtlFastCheckLockForRead + FsRtlFastCheckLockForWrite + FsRtlMdlReadComplete + FsRtlMdlWriteComplete + FsRtlNormalizeNtstatus + RtlAllocateHeap + RtlCreateHeap + RtlDestroyHeap + RtlFreeHeap + RtlImageNtHeader + ZwQueryObject + ZwQuerySystemInformation + ZwSetSystemInformation + + 15. 2000-03-15 + Corrected: + Renamed IoQueryFileVolumeInformation to IoQueryVolumeInformation + Comment on: + CcZeroEndOfLastPage + + 14. 2000-03-12 + Corrected: + IoCreateFile + Added: + #if (_WIN32_WINNT < 0x0500)/#endif around stuff that is included in + the Windows 2000 DDK but is missing in the Windows NT 4.0 DDK. + ZwOpenEvent + + 13. 2000-02-08 + Corrected: + PsReferenceImpersonationToken + Comment on: + RtlAllocateAndInitializeSid + + 12. 1999-10-18 + Corrected: + FILE_COMPRESSION_INFORMATION + Added: + Defines: + ACCESS_ALLOWED_ACE_TYPE + ACCESS_DENIED_ACE_TYPE + SYSTEM_AUDIT_ACE_TYPE + SYSTEM_ALARM_ACE_TYPE + ANSI_DOS_STAR/QM/DOT + DOS_STAR/QM/DOT + FILE_EA_TYPE_XXX + FILE_NEED_EA + FILE_OPBATCH_BREAK_UNDERWAY + SECURITY_WORLD_SID_AUTHORITY + SECURITY_WORLD_RID + Data types: + POBJECT + FILE_STORAGE_TYPE + FILE_COMPLETION_INFORMATION + FILE_COPY_ON_WRITE_INFORMATION + FILE_FS_CONTROL_INFORMATION + FILE_GET_EA_INFORMATION + FILE_GET_QUOTA_INFORMATION + FILE_OBJECTID_INFORMATION + FILE_OLE_CLASSID_INFORMATION + FILE_OLE_ALL_INFORMATION + FILE_OLE_DIR_INFORMATION + FILE_OLE_INFORMATION + FILE_OLE_STATE_BITS_INFORMATION + FILE_QUOTA_INFORMATION + Function prototypes: + HalDisplayString + HalMakeBeep + IoGetRequestorProcess + ObQueryNameString + ProbeForWrite + RtlAbsoluteToSelfRelativeSD + RtlGetDaclSecurityDescriptor + RtlGetGroupSecurityDescriptor + RtlGetOwnerSecurityDescriptor + RtlInitializeSid + RtlSetGroupSecurityDescriptor + RtlSetOwnerSecurityDescriptor + RtlSetSaclSecurityDescriptor + ZwDeleteValueKey + ZwDisplayString + ZwQueryDirectoryObject + + 11. 1999-10-13 + Corrected: + ZwOpenProcessToken + ZwOpenThreadToken + Added: + Function prototypes: + RtlAllocateAndInitializeSid + RtlCopySid + RtlEqualSid + RtlFillMemoryUlong + RtlIsNameLegalDOS8Dot3 + RtlLengthRequiredSid + RtlLengthSid + RtlNtStatusToDosError + RtlSubAuthorityCountSid + RtlSubAuthoritySid + RtlValidSid + + 10. 1999-07-15 + Corrected: + RtlConvertSidToUnicodeString + Added: + Externals: + FsRtlLegalAnsiCharacterArray + NtBuildNumber + Defines: + FSRTL_WILD_CHARACTER + FlagOn + FsRtlIsUnicodeCharacterWild + Structures: + FILE_ACCESS_INFORMATION + FILE_MODE_INFORMATION + GENERATE_NAME_CONTEXT + Function prototypes: + FsRtlDoesNameContainWildCards + FsRtlIsNameInExpression + IoSetInformation + RtlGenerate8dot3Name + ZwQuerySecurityObject + + 9. 1999-07-12 + Corrected: + EXTENDED_IO_STACK_LOCATION + QueryDirectory in EXTENDED_IO_STACK_LOCATION + ZwCreateThread + Added: + Structures: + INITIAL_TEB + Function prototypes: + ZwQuerySymbolicLinkObject + + 8. 1999-06-07 + Corrected: + ZwOpenProcessToken + ZwOpenThreadToken + Added: + Defines: + FILE_OPLOCK_BROKEN_TO_LEVEL_2 + FILE_OPLOCK_BROKEN_TO_NONE + FILE_CASE_SENSITIVE_SEARCH + FILE_CASE_PRESERVED_NAMES + FILE_UNICODE_ON_DISK + FILE_PERSISTENT_ACLS + FILE_FILE_COMPRESSION + FILE_VOLUME_IS_COMPRESSED + FSRTL_FLAG_ACQUIRE_MAIN_RSRC_EX + FSRTL_FLAG_ACQUIRE_MAIN_RSRC_SH + IOCTL_REDIR_QUERY_PATH + Structures: + FILE_FS_LABEL_INFORMATION + PATHNAME_BUFFER + In IO_STACK_LOCATION: + FileSystemControl + LockControl + SetVolume + Function prototypes: + FsRtlCopyRead + FsRtlCopyWrite + IoVerifyVolume + + 7. 1999-06-05 + Added: + defines for TOKEN_XXX + SID_NAME_USE + TOKEN_INFORMATION_CLASS + TOKEN_TYPE + FILE_FS_ATTRIBUTE_INFORMATION + FILE_FS_SIZE_INFORMATION + SID_IDENTIFIER_AUTHORITY + SID + SID_AND_ATTRIBUTES + TOKEN_CONTROL + TOKEN_DEFAULT_DACL + TOKEN_GROUPS + TOKEN_OWNER + TOKEN_PRIMARY_GROUP + TOKEN_PRIVILEGES + TOKEN_SOURCE + TOKEN_STATISTICS + TOKEN_USER + IoCreateFile + IoGetAttachedDevice + IoGetBaseFileSystemDeviceObject + PsReferenceImpersonationToken + PsReferencePrimaryToken + RtlConvertSidToUnicodeString + SeCaptureSubjectContext + SeMarkLogonSessionForTerminationNotification + SeRegisterLogonSessionTerminatedRoutine + SeUnregisterLogonSessionTerminatedRoutine + ZwOpenProcessToken + ZwOpenThreadToken + ZwQueryInformationToken + + 6. 1999-05-10 + Corrected declarations of Zw functions. + Added: + ZwCancelIoFile + ZwDeleteFile + ZwFlushBuffersFile + ZwFsControlFile + ZwLockFile + ZwNotifyChangeDirectoryFile + ZwOpenFile + ZwQueryEaFile + ZwSetEaFile + ZwSetVolumeInformationFile + ZwUnlockFile + + 5. 1999-05-09 + Added: + defines for FILE_ACTION_XXX and FILE_NOTIFY_XXX + FILE_FS_VOLUME_INFORMATION + RETRIEVAL_POINTERS_BUFFER + STARTING_VCN_INPUT_BUFFER + FsRtlNotifyFullReportChange + + 4. 1999-04-11 + Corrected: + ZwCreateThread + Added: + define _GNU_NTIFS_ + + 3. 1999-03-30 + Added: + defines for MAP_XXX, MEM_XXX and SEC_XXX + FILE_BOTH_DIR_INFORMATION + FILE_DIRECTORY_INFORMATION + FILE_FULL_DIR_INFORMATION + FILE_NAMES_INFORMATION + FILE_NOTIFY_INFORMATION + FsRtlNotifyCleanup + KeAttachProcess + KeDetachProcess + MmCreateSection + ZwCreateProcess + ZwCreateThread + ZwDeviceIoControlFile + ZwGetContextThread + ZwLoadDriver + ZwOpenDirectoryObject + ZwOpenProcess + ZwOpenSymbolicLinkObject + ZwQueryDirectoryFile + ZwUnloadDriver + + 2. 1999-03-15 + Added: + FILE_COMPRESSION_INFORMATION + FILE_STREAM_INFORMATION + FILE_LINK_INFORMATION + FILE_RENAME_INFORMATION + EXTENDED_IO_STACK_LOCATION + IoQueryFileInformation + IoQueryFileVolumeInformation + ZwQueryVolumeInformationFile + Moved include of ntddk.h to inside extern "C" block. + + 1. 1999-03-11 + Initial release. +*/ + +#ifndef _NTIFS_ +#define _NTIFS_ +#define _GNU_NTIFS_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +// Available in Windows NT 3.1 and later versions. +// Documented in the WDK. +extern PEPROCESS PsInitialSystemProcess; + +// Available in Windows NT 3.5 and later versions. +typedef struct _HAL_PRIVATE_DISPATCH *PHAL_PRIVATE_DISPATCH; +extern PHAL_PRIVATE_DISPATCH HalPrivateDispatchTable; + +// Available in Windows NT 3.5 and later versions. +typedef struct _LOADER_PARAMETER_BLOCK *PLOADER_PARAMETER_BLOCK; +extern PLOADER_PARAMETER_BLOCK KeLoaderBlock; + +// Available in Windows NT 3.5 and later versions. +typedef struct _SERVICE_DESCRIPTOR_TABLE *PSERVICE_DESCRIPTOR_TABLE; +extern PSERVICE_DESCRIPTOR_TABLE KeServiceDescriptorTable; + +// Available in Windows NT 3.5 and later versions. +extern PSHORT NtBuildNumber; +extern PULONG KeI386MachineType; + +// Available in Windows NT 4.0 and later versions. +extern ULONG KiBugCheckData[5]; + +// Available in Windows 2000 and later versions. +extern PULONG InitSafeBootMode; + +// Available from Windows 2000 untill Windows Server 2003. +extern PULONG KiEnableTimerWatchdog; + +// Available in Windows NT 3.5 and later versions. +// +// Set by the kernel debugger on the target system to the address of the +// serial port used to communicate with the host. +// +extern PUCHAR *KdComPortInUse; + +// Available in Windows 2000 and later versions. +extern PULONG KdEnteredDebugger; + +// Available in Windows Vista and later versions. +// Documented in the WDK. +extern PVOID MmBadPointer; + +// Available in Windows NT 3.5 and later versions. +// Documented in the WDK. +extern PUCHAR *FsRtlLegalAnsiCharacterArray; + +// Available in Windows NT 3.5 and later versions. +extern PUSHORT *NlsLeadByteInfo; +extern PUSHORT *NlsOemLeadByteInfo; +extern PBOOLEAN NlsMbCodePageTag; +extern PBOOLEAN NlsMbOemCodePageTag; + +// Available in Windows NT 4.0 and later versions. +extern PUSHORT NlsAnsiCodePage; + +// Available in Windows 2000 and later versions. +extern PUSHORT NlsOemCodePage; + +// Available in Windows NT 3.5 and later versions. +// SeExports is documented in the WDK. +typedef struct _SE_EXPORTS *PSE_EXPORTS; +extern PSE_EXPORTS SeExports; +extern PACL SePublicDefaultDacl; +extern PACL SeSystemDefaultDacl; + +// Available in Windows NT 3.5 and later versions. +// Documented in the WDK. +extern KSPIN_LOCK IoStatisticsLock; +extern ULONG IoReadOperationCount; +extern ULONG IoWriteOperationCount; +extern LARGE_INTEGER IoReadTransferCount; +extern LARGE_INTEGER IoWriteTransferCount; + +// Available from Windows NT 3.5 untill Windows XP. +extern ULONG KeDcacheFlushCount; +extern ULONG KeIcacheFlushCount; + +// Available in Windows NT 4.0 and later versions. +// Documented in the WDK. +extern ULONG CcFastMdlReadWait; +// Available from Windows NT 4.0 untill Windows Server 2003. +extern ULONG CcFastReadNotPossible; +extern ULONG CcFastReadWait; + +// The ExEventObjectType, ExSemaphoreObjectType and IoFileObjectType is +// documented in the DDK and the WDK. +// +// The CmKeyObjectType, SeTokenObjectType, PsProcessType, PsThreadType, +// TmEnlistmentObjectType, TmResourceManagerObjectType, +// TmTransactionManagerObjectType and TmTransactionObjectType +// is documented in the WDK. +// +// Available in Windows NT 3.5 and later versions. +extern POBJECT_TYPE *IoAdapterObjectType; +extern POBJECT_TYPE *IoDeviceObjectType; +extern POBJECT_TYPE *IoDriverObjectType; +extern POBJECT_TYPE *MmSectionObjectType; +extern POBJECT_TYPE *PsProcessType; +extern POBJECT_TYPE *PsThreadType; +// Available in Windows NT 4.0 and later versions. +extern POBJECT_TYPE *ExDesktopObjectType; +extern POBJECT_TYPE *ExWindowStationObjectType; +extern POBJECT_TYPE *IoDeviceHandlerObjectType; +// Available in Windows 2000 and later versions. +extern POBJECT_TYPE *LpcPortObjectType; +extern POBJECT_TYPE *PsJobType; +// Available in Windows XP and later versions. +extern POBJECT_TYPE *SeTokenObjectType; +// Available in Windows Vista and later versions. +extern POBJECT_TYPE *TmEnlistmentObjectType; +extern POBJECT_TYPE *TmResourceManagerObjectType; +extern POBJECT_TYPE *TmTransactionManagerObjectType; +extern POBJECT_TYPE *TmTransactionObjectType; +// Available in Windows 7 and later versions. +extern POBJECT_TYPE *CmKeyObjectType; + +// Available in Windows NT 4.0 and later versions. +extern PULONG IoDeviceHandlerObjectSize; + +// Available in Windows Vista and later versions. +extern PVOID POGOBuffer; +extern PVOID psMUITest; +extern PVOID PsUILanguageComitted; + +#define ACCESS_ALLOWED_ACE_TYPE (0x0) +#define ACCESS_DENIED_ACE_TYPE (0x1) +#define SYSTEM_AUDIT_ACE_TYPE (0x2) +#define SYSTEM_ALARM_ACE_TYPE (0x3) + +#define ANSI_DOS_STAR ('<') +#define ANSI_DOS_QM ('>') +#define ANSI_DOS_DOT ('"') + +#define DOS_STAR (L'<') +#define DOS_QM (L'>') +#define DOS_DOT (L'"') + +#define COMPRESSION_FORMAT_NONE (0x0000) +#define COMPRESSION_FORMAT_DEFAULT (0x0001) +#define COMPRESSION_FORMAT_LZNT1 (0x0002) +#define COMPRESSION_ENGINE_STANDARD (0x0000) +#define COMPRESSION_ENGINE_MAXIMUM (0x0100) +#define COMPRESSION_ENGINE_HIBER (0x0200) + +#define FILE_ACTION_ADDED 0x00000001 +#define FILE_ACTION_REMOVED 0x00000002 +#define FILE_ACTION_MODIFIED 0x00000003 +#define FILE_ACTION_RENAMED_OLD_NAME 0x00000004 +#define FILE_ACTION_RENAMED_NEW_NAME 0x00000005 +#define FILE_ACTION_ADDED_STREAM 0x00000006 +#define FILE_ACTION_REMOVED_STREAM 0x00000007 +#define FILE_ACTION_MODIFIED_STREAM 0x00000008 +#define FILE_ACTION_REMOVED_BY_DELETE 0x00000009 +#define FILE_ACTION_ID_NOT_TUNNELLED 0x0000000A +#define FILE_ACTION_TUNNELLED_ID_COLLISION 0x0000000B + +#define FILE_EA_TYPE_BINARY 0xfffe +#define FILE_EA_TYPE_ASCII 0xfffd +#define FILE_EA_TYPE_BITMAP 0xfffb +#define FILE_EA_TYPE_METAFILE 0xfffa +#define FILE_EA_TYPE_ICON 0xfff9 +#define FILE_EA_TYPE_EA 0xffee +#define FILE_EA_TYPE_MVMT 0xffdf +#define FILE_EA_TYPE_MVST 0xffde +#define FILE_EA_TYPE_ASN1 0xffdd +#define FILE_EA_TYPE_FAMILY_IDS 0xff01 + +#define FILE_NEED_EA 0x00000080 + +#define FILE_NOTIFY_CHANGE_FILE_NAME 0x00000001 +#define FILE_NOTIFY_CHANGE_DIR_NAME 0x00000002 +#define FILE_NOTIFY_CHANGE_NAME 0x00000003 +#define FILE_NOTIFY_CHANGE_ATTRIBUTES 0x00000004 +#define FILE_NOTIFY_CHANGE_SIZE 0x00000008 +#define FILE_NOTIFY_CHANGE_LAST_WRITE 0x00000010 +#define FILE_NOTIFY_CHANGE_LAST_ACCESS 0x00000020 +#define FILE_NOTIFY_CHANGE_CREATION 0x00000040 +#define FILE_NOTIFY_CHANGE_EA 0x00000080 +#define FILE_NOTIFY_CHANGE_SECURITY 0x00000100 +#define FILE_NOTIFY_CHANGE_STREAM_NAME 0x00000200 +#define FILE_NOTIFY_CHANGE_STREAM_SIZE 0x00000400 +#define FILE_NOTIFY_CHANGE_STREAM_WRITE 0x00000800 +#define FILE_NOTIFY_VALID_MASK 0x00000fff + +#define FILE_OPLOCK_BROKEN_TO_LEVEL_2 0x00000007 +#define FILE_OPLOCK_BROKEN_TO_NONE 0x00000008 + +#define FILE_OPBATCH_BREAK_UNDERWAY 0x00000009 + +#define FILE_CASE_SENSITIVE_SEARCH 0x00000001 +#define FILE_CASE_PRESERVED_NAMES 0x00000002 +#define FILE_UNICODE_ON_DISK 0x00000004 +#define FILE_PERSISTENT_ACLS 0x00000008 +#define FILE_FILE_COMPRESSION 0x00000010 +#define FILE_VOLUME_QUOTAS 0x00000020 +#define FILE_SUPPORTS_SPARSE_FILES 0x00000040 +#define FILE_SUPPORTS_REPARSE_POINTS 0x00000080 +#define FILE_SUPPORTS_REMOTE_STORAGE 0x00000100 +#define FS_LFN_APIS 0x00004000 +#define FILE_VOLUME_IS_COMPRESSED 0x00008000 +#define FILE_SUPPORTS_OBJECT_IDS 0x00010000 +#define FILE_SUPPORTS_ENCRYPTION 0x00020000 +#define FILE_NAMED_STREAMS 0x00040000 +#define FILE_READ_ONLY_VOLUME 0x00080000 + +#define FILE_PIPE_BYTE_STREAM_TYPE 0x00000000 +#define FILE_PIPE_MESSAGE_TYPE 0x00000001 + +#define FILE_PIPE_BYTE_STREAM_MODE 0x00000000 +#define FILE_PIPE_MESSAGE_MODE 0x00000001 + +#define FILE_PIPE_QUEUE_OPERATION 0x00000000 +#define FILE_PIPE_COMPLETE_OPERATION 0x00000001 + +#define FILE_PIPE_INBOUND 0x00000000 +#define FILE_PIPE_OUTBOUND 0x00000001 +#define FILE_PIPE_FULL_DUPLEX 0x00000002 + +#define FILE_PIPE_DISCONNECTED_STATE 0x00000001 +#define FILE_PIPE_LISTENING_STATE 0x00000002 +#define FILE_PIPE_CONNECTED_STATE 0x00000003 +#define FILE_PIPE_CLOSING_STATE 0x00000004 + +#define FILE_PIPE_CLIENT_END 0x00000000 +#define FILE_PIPE_SERVER_END 0x00000001 + +#define FILE_PIPE_READ_DATA 0x00000000 +#define FILE_PIPE_WRITE_SPACE 0x00000001 + +#define FILE_STORAGE_TYPE_SPECIFIED 0x00000041 // FILE_DIRECTORY_FILE | FILE_NON_DIRECTORY_FILE +#define FILE_STORAGE_TYPE_DEFAULT (StorageTypeDefault << FILE_STORAGE_TYPE_SHIFT) +#define FILE_STORAGE_TYPE_DIRECTORY (StorageTypeDirectory << FILE_STORAGE_TYPE_SHIFT) +#define FILE_STORAGE_TYPE_FILE (StorageTypeFile << FILE_STORAGE_TYPE_SHIFT) +#define FILE_STORAGE_TYPE_DOCFILE (StorageTypeDocfile << FILE_STORAGE_TYPE_SHIFT) +#define FILE_STORAGE_TYPE_JUNCTION_POINT (StorageTypeJunctionPoint << FILE_STORAGE_TYPE_SHIFT) +#define FILE_STORAGE_TYPE_CATALOG (StorageTypeCatalog << FILE_STORAGE_TYPE_SHIFT) +#define FILE_STORAGE_TYPE_STRUCTURED_STORAGE (StorageTypeStructuredStorage << FILE_STORAGE_TYPE_SHIFT) +#define FILE_STORAGE_TYPE_EMBEDDING (StorageTypeEmbedding << FILE_STORAGE_TYPE_SHIFT) +#define FILE_STORAGE_TYPE_STREAM (StorageTypeStream << FILE_STORAGE_TYPE_SHIFT) +#define FILE_MINIMUM_STORAGE_TYPE FILE_STORAGE_TYPE_DEFAULT +#define FILE_MAXIMUM_STORAGE_TYPE FILE_STORAGE_TYPE_STREAM +#define FILE_STORAGE_TYPE_MASK 0x000f0000 +#define FILE_STORAGE_TYPE_SHIFT 16 + +#define FILE_VC_QUOTA_NONE 0x00000000 +#define FILE_VC_QUOTA_TRACK 0x00000001 +#define FILE_VC_QUOTA_ENFORCE 0x00000002 +#define FILE_VC_QUOTA_MASK 0x00000003 + +#define FILE_VC_QUOTAS_LOG_VIOLATIONS 0x00000004 +#define FILE_VC_CONTENT_INDEX_DISABLED 0x00000008 + +#define FILE_VC_LOG_QUOTA_THRESHOLD 0x00000010 +#define FILE_VC_LOG_QUOTA_LIMIT 0x00000020 +#define FILE_VC_LOG_VOLUME_THRESHOLD 0x00000040 +#define FILE_VC_LOG_VOLUME_LIMIT 0x00000080 + +#define FILE_VC_QUOTAS_INCOMPLETE 0x00000100 +#define FILE_VC_QUOTAS_REBUILDING 0x00000200 + +#define FILE_VC_VALID_MASK 0x000003ff + +#define FSRTL_FCB_HEADER_V0 (0x00) +#define FSRTL_FCB_HEADER_V1 (0x01) + +#define FSRTL_FLAG_FILE_MODIFIED (0x01) +#define FSRTL_FLAG_FILE_LENGTH_CHANGED (0x02) +#define FSRTL_FLAG_LIMIT_MODIFIED_PAGES (0x04) +#define FSRTL_FLAG_ACQUIRE_MAIN_RSRC_EX (0x08) +#define FSRTL_FLAG_ACQUIRE_MAIN_RSRC_SH (0x10) +#define FSRTL_FLAG_USER_MAPPED_FILE (0x20) +#define FSRTL_FLAG_ADVANCED_HEADER (0x40) +#define FSRTL_FLAG_EOF_ADVANCE_ACTIVE (0x80) + +#define FSRTL_FLAG2_DO_MODIFIED_WRITE (0x01) +#define FSRTL_FLAG2_SUPPORTS_FILTER_CONTEXTS (0x02) +#define FSRTL_FLAG2_PURGE_WHEN_MAPPED (0x04) +#define FSRTL_FLAG2_IS_PAGING_FILE (0x08) + +#define FSRTL_FSP_TOP_LEVEL_IRP (0x01) +#define FSRTL_CACHE_TOP_LEVEL_IRP (0x02) +#define FSRTL_MOD_WRITE_TOP_LEVEL_IRP (0x03) +#define FSRTL_FAST_IO_TOP_LEVEL_IRP (0x04) +#define FSRTL_MAX_TOP_LEVEL_IRP_FLAG (0x04) + +#define FSRTL_VOLUME_DISMOUNT 1 +#define FSRTL_VOLUME_DISMOUNT_FAILED 2 +#define FSRTL_VOLUME_LOCK 3 +#define FSRTL_VOLUME_LOCK_FAILED 4 +#define FSRTL_VOLUME_UNLOCK 5 +#define FSRTL_VOLUME_MOUNT 6 + +#define FSRTL_WILD_CHARACTER 0x08 + +#ifdef _X86_ +#define HARDWARE_PTE HARDWARE_PTE_X86 +#define PHARDWARE_PTE PHARDWARE_PTE_X86 +#else +#define HARDWARE_PTE ULONG +#define PHARDWARE_PTE PULONG +#endif + +#define IO_CHECK_CREATE_PARAMETERS 0x0200 +#define IO_ATTACH_DEVICE 0x0400 + +#define IO_ATTACH_DEVICE_API 0x80000000 + +#define IO_COMPLETION_QUERY_STATE 0x0001 +#define IO_COMPLETION_MODIFY_STATE 0x0002 +#define IO_COMPLETION_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|0x3) + +#define IO_FILE_OBJECT_NON_PAGED_POOL_CHARGE 64 +#define IO_FILE_OBJECT_PAGED_POOL_CHARGE 1024 + +#define IO_REPARSE_TAG_RESERVED_ZERO (0) +#define IO_REPARSE_TAG_RESERVED_ONE (1) + +#define IO_TYPE_APC 18 +#define IO_TYPE_DPC 19 +#define IO_TYPE_DEVICE_QUEUE 20 +#define IO_TYPE_EVENT_PAIR 21 +#define IO_TYPE_INTERRUPT 22 +#define IO_TYPE_PROFILE 23 + +#define IRP_BEING_VERIFIED 0x10 + +#define MAILSLOT_CLASS_FIRSTCLASS 1 +#define MAILSLOT_CLASS_SECONDCLASS 2 + +#define MAILSLOT_SIZE_AUTO 0 + +#define MAP_PROCESS 1L +#define MAP_SYSTEM 2L + +#define MEM_DOS_LIM 0x40000000 +#define MEM_IMAGE SEC_IMAGE + +#define OB_FLAG_CREATE_INFO 0x01 /* Object header has OBJECT_CREATE_INFO */ +#define OB_FLAG_KERNEL_MODE 0x02 /* Created by kernel */ +#define OB_FLAG_CREATOR_INFO 0x04 /* Object header has OBJECT_CREATOR_INFO */ +#define OB_FLAG_EXCLUSIVE 0x08 /* OBJ_EXCLUSIVE */ +#define OB_FLAG_PERMAMENT 0x10 /* OBJ_PERMAMENT */ +#define OB_FLAG_SECURITY 0x20 /* Object header has SecurityDescriptor != NULL */ +#define OB_FLAG_SINGLE_PROCESS 0x40 /* absent HandleDBList */ + +#define OB_SECURITY_CHARGE 0x00000800 + +#define OB_TYPE_TYPE 1 +#define OB_TYPE_DIRECTORY 2 +#define OB_TYPE_SYMBOLIC_LINK 3 +#define OB_TYPE_TOKEN 4 +#define OB_TYPE_PROCESS 5 +#define OB_TYPE_THREAD 6 +#define OB_TYPE_EVENT 7 +#define OB_TYPE_EVENT_PAIR 8 +#define OB_TYPE_MUTANT 9 +#define OB_TYPE_SEMAPHORE 10 +#define OB_TYPE_TIMER 11 +#define OB_TYPE_PROFILE 12 +#define OB_TYPE_WINDOW_STATION 13 +#define OB_TYPE_DESKTOP 14 +#define OB_TYPE_SECTION 15 +#define OB_TYPE_KEY 16 +#define OB_TYPE_PORT 17 +#define OB_TYPE_ADAPTER 18 +#define OB_TYPE_CONTROLLER 19 +#define OB_TYPE_DEVICE 20 +#define OB_TYPE_DRIVER 21 +#define OB_TYPE_IO_COMPLETION 22 +#define OB_TYPE_FILE 23 + +#define PIN_WAIT (1) +#define PIN_EXCLUSIVE (2) +#define PIN_NO_READ (4) +#define PIN_IF_BCB (8) + +#define MAP_WAIT (1) +#define MAP_NO_READ (16) + +#define PORT_CONNECT 0x0001 +#define PORT_ALL_ACCESS (STANDARD_RIGHTS_ALL |\ + PORT_CONNECT) + +#define SEC_BASED 0x00200000 +#define SEC_NO_CHANGE 0x00400000 +#define SEC_FILE 0x00800000 +#define SEC_IMAGE 0x01000000 +#define SEC_COMMIT 0x08000000 +#define SEC_NOCACHE 0x10000000 + +#define SECURITY_WORLD_SID_AUTHORITY {0,0,0,0,0,1} +#define SECURITY_WORLD_RID (0x00000000L) + +#define SID_REVISION 1 + +#define THREAD_STATE_INITIALIZED 0 +#define THREAD_STATE_READY 1 +#define THREAD_STATE_RUNNING 2 +#define THREAD_STATE_STANDBY 3 +#define THREAD_STATE_TERMINATED 4 +#define THREAD_STATE_WAIT 5 +#define THREAD_STATE_TRANSITION 6 +#define THREAD_STATE_UNKNOWN 7 + +#define TOKEN_ASSIGN_PRIMARY (0x0001) +#define TOKEN_DUPLICATE (0x0002) +#define TOKEN_IMPERSONATE (0x0004) +#define TOKEN_QUERY (0x0008) +#define TOKEN_QUERY_SOURCE (0x0010) +#define TOKEN_ADJUST_PRIVILEGES (0x0020) +#define TOKEN_ADJUST_GROUPS (0x0040) +#define TOKEN_ADJUST_DEFAULT (0x0080) + +#define TOKEN_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED |\ + TOKEN_ASSIGN_PRIMARY |\ + TOKEN_DUPLICATE |\ + TOKEN_IMPERSONATE |\ + TOKEN_QUERY |\ + TOKEN_QUERY_SOURCE |\ + TOKEN_ADJUST_PRIVILEGES |\ + TOKEN_ADJUST_GROUPS |\ + TOKEN_ADJUST_DEFAULT) + +#define TOKEN_READ (STANDARD_RIGHTS_READ |\ + TOKEN_QUERY) + +#define TOKEN_WRITE (STANDARD_RIGHTS_WRITE |\ + TOKEN_ADJUST_PRIVILEGES |\ + TOKEN_ADJUST_GROUPS |\ + TOKEN_ADJUST_DEFAULT) + +#define TOKEN_EXECUTE (STANDARD_RIGHTS_EXECUTE) + +#define TOKEN_SOURCE_LENGTH 8 + +#define TOKEN_HAS_TRAVERSE_PRIVILEGE 0x01 +#define TOKEN_HAS_BACKUP_PRIVILEGE 0x02 +#define TOKEN_HAS_RESTORE_PRIVILEGE 0x04 +#define TOKEN_HAS_ADMIN_GROUP 0x08 +#define TOKEN_IS_RESTRICTED 0x10 +#define TOKEN_SESSION_NOT_REFERENCED 0x20 +#define TOKEN_SANDBOX_INERT 0x40 +#define TOKEN_HAS_IMPERSONATE_PRIVILEGE 0x80 + +#define VACB_MAPPING_GRANULARITY (0x40000) +#define VACB_OFFSET_SHIFT (18) + +#define FSCTL_REQUEST_OPLOCK_LEVEL_1 CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_REQUEST_OPLOCK_LEVEL_2 CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 1, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_REQUEST_BATCH_OPLOCK CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 2, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_OPLOCK_BREAK_ACKNOWLEDGE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 3, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_OPBATCH_ACK_CLOSE_PENDING CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 4, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_OPLOCK_BREAK_NOTIFY CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 5, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_LOCK_VOLUME CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 6, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_UNLOCK_VOLUME CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 7, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_DISMOUNT_VOLUME CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 8, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define FSCTL_IS_VOLUME_MOUNTED CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 10, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_IS_PATHNAME_VALID CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 11, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_MARK_VOLUME_DIRTY CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 12, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define FSCTL_QUERY_RETRIEVAL_POINTERS CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 14, METHOD_NEITHER, FILE_ANY_ACCESS) +#define FSCTL_GET_COMPRESSION CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 15, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_SET_COMPRESSION CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 16, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA) + + +#define FSCTL_MARK_AS_SYSTEM_HIVE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 19, METHOD_NEITHER, FILE_ANY_ACCESS) +#define FSCTL_OPLOCK_BREAK_ACK_NO_2 CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 20, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_INVALIDATE_VOLUMES CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 21, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_QUERY_FAT_BPB CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 22, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_REQUEST_FILTER_OPLOCK CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 23, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_FILESYSTEM_GET_STATISTICS CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 24, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#if (VER_PRODUCTBUILD >= 1381) + +#define FSCTL_GET_NTFS_VOLUME_DATA CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 25, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_GET_NTFS_FILE_RECORD CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 26, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_GET_VOLUME_BITMAP CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 27, METHOD_NEITHER, FILE_ANY_ACCESS) +#define FSCTL_GET_RETRIEVAL_POINTERS CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 28, METHOD_NEITHER, FILE_ANY_ACCESS) +#define FSCTL_MOVE_FILE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 29, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_IS_VOLUME_DIRTY CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 30, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_GET_HFS_INFORMATION CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 31, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_ALLOW_EXTENDED_DASD_IO CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 32, METHOD_NEITHER, FILE_ANY_ACCESS) + +#endif // (VER_PRODUCTBUILD >= 1381) + +#if (VER_PRODUCTBUILD >= 2195) + +#define FSCTL_READ_PROPERTY_DATA CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 33, METHOD_NEITHER, FILE_ANY_ACCESS) +#define FSCTL_WRITE_PROPERTY_DATA CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 34, METHOD_NEITHER, FILE_ANY_ACCESS) +#define FSCTL_FIND_FILES_BY_SID CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 35, METHOD_NEITHER, FILE_ANY_ACCESS) + +#define FSCTL_DUMP_PROPERTY_DATA CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 37, METHOD_NEITHER, FILE_ANY_ACCESS) +#define FSCTL_SET_OBJECT_ID CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 38, METHOD_BUFFERED, FILE_WRITE_DATA) +#define FSCTL_GET_OBJECT_ID CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 39, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_DELETE_OBJECT_ID CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 40, METHOD_BUFFERED, FILE_WRITE_DATA) +#define FSCTL_SET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 41, METHOD_BUFFERED, FILE_WRITE_DATA) +#define FSCTL_GET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_DELETE_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 43, METHOD_BUFFERED, FILE_WRITE_DATA) +#define FSCTL_ENUM_USN_DATA CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 44, METHOD_NEITHER, FILE_READ_DATA) +#define FSCTL_SECURITY_ID_CHECK CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 45, METHOD_NEITHER, FILE_READ_DATA) +#define FSCTL_READ_USN_JOURNAL CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 46, METHOD_NEITHER, FILE_READ_DATA) +#define FSCTL_SET_OBJECT_ID_EXTENDED CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 47, METHOD_BUFFERED, FILE_WRITE_DATA) +#define FSCTL_CREATE_OR_GET_OBJECT_ID CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 48, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_SET_SPARSE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 49, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) +#define FSCTL_SET_ZERO_DATA CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 50, METHOD_BUFFERED, FILE_WRITE_DATA) +#define FSCTL_QUERY_ALLOCATED_RANGES CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 51, METHOD_NEITHER, FILE_READ_DATA) +#define FSCTL_ENABLE_UPGRADE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 52, METHOD_BUFFERED, FILE_WRITE_DATA) +#define FSCTL_SET_ENCRYPTION CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 53, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_ENCRYPTION_FSCTL_IO CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 54, METHOD_NEITHER, FILE_ANY_ACCESS) +#define FSCTL_WRITE_RAW_ENCRYPTED CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 55, METHOD_NEITHER, FILE_ANY_ACCESS) +#define FSCTL_READ_RAW_ENCRYPTED CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 56, METHOD_NEITHER, FILE_ANY_ACCESS) +#define FSCTL_CREATE_USN_JOURNAL CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 57, METHOD_NEITHER, FILE_READ_DATA) +#define FSCTL_READ_FILE_USN_DATA CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 58, METHOD_NEITHER, FILE_READ_DATA) +#define FSCTL_WRITE_USN_CLOSE_RECORD CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 59, METHOD_NEITHER, FILE_READ_DATA) +#define FSCTL_EXTEND_VOLUME CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 60, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_QUERY_USN_JOURNAL CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 61, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_DELETE_USN_JOURNAL CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 62, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_MARK_HANDLE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 63, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_SIS_COPYFILE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 64, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_SIS_LINK_FILES CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 65, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA) +#define FSCTL_HSM_MSG CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 66, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA) +#define FSCTL_NSS_CONTROL CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 67, METHOD_BUFFERED, FILE_WRITE_DATA) +#define FSCTL_HSM_DATA CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 68, METHOD_NEITHER, FILE_READ_DATA | FILE_WRITE_DATA) +#define FSCTL_RECALL_FILE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 69, METHOD_NEITHER, FILE_ANY_ACCESS) +#define FSCTL_NSS_RCONTROL CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 70, METHOD_BUFFERED, FILE_READ_DATA) +#define FSCTL_READ_FROM_PLEX CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 71, METHOD_OUT_DIRECT, FILE_READ_DATA) +#define FSCTL_FILE_PREFETCH CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 72, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) + +#endif // (VER_PRODUCTBUILD >= 2195) + +#define FSCTL_MAILSLOT_PEEK CTL_CODE(FILE_DEVICE_MAILSLOT, 0, METHOD_NEITHER, FILE_READ_DATA) + +#define FSCTL_NETWORK_SET_CONFIGURATION_INFO CTL_CODE(FILE_DEVICE_NETWORK_FILE_SYSTEM, 102, METHOD_IN_DIRECT, FILE_ANY_ACCESS) +#define FSCTL_NETWORK_GET_CONFIGURATION_INFO CTL_CODE(FILE_DEVICE_NETWORK_FILE_SYSTEM, 103, METHOD_OUT_DIRECT, FILE_ANY_ACCESS) +#define FSCTL_NETWORK_GET_CONNECTION_INFO CTL_CODE(FILE_DEVICE_NETWORK_FILE_SYSTEM, 104, METHOD_NEITHER, FILE_ANY_ACCESS) +#define FSCTL_NETWORK_ENUMERATE_CONNECTIONS CTL_CODE(FILE_DEVICE_NETWORK_FILE_SYSTEM, 105, METHOD_NEITHER, FILE_ANY_ACCESS) +#define FSCTL_NETWORK_DELETE_CONNECTION CTL_CODE(FILE_DEVICE_NETWORK_FILE_SYSTEM, 107, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_NETWORK_GET_STATISTICS CTL_CODE(FILE_DEVICE_NETWORK_FILE_SYSTEM, 116, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_NETWORK_SET_DOMAIN_NAME CTL_CODE(FILE_DEVICE_NETWORK_FILE_SYSTEM, 120, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_NETWORK_REMOTE_BOOT_INIT_SCRT CTL_CODE(FILE_DEVICE_NETWORK_FILE_SYSTEM, 250, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define FSCTL_PIPE_ASSIGN_EVENT CTL_CODE(FILE_DEVICE_NAMED_PIPE, 0, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_PIPE_DISCONNECT CTL_CODE(FILE_DEVICE_NAMED_PIPE, 1, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_PIPE_LISTEN CTL_CODE(FILE_DEVICE_NAMED_PIPE, 2, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_PIPE_PEEK CTL_CODE(FILE_DEVICE_NAMED_PIPE, 3, METHOD_BUFFERED, FILE_READ_DATA) +#define FSCTL_PIPE_QUERY_EVENT CTL_CODE(FILE_DEVICE_NAMED_PIPE, 4, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_PIPE_TRANSCEIVE CTL_CODE(FILE_DEVICE_NAMED_PIPE, 5, METHOD_NEITHER, FILE_READ_DATA | FILE_WRITE_DATA) +#define FSCTL_PIPE_WAIT CTL_CODE(FILE_DEVICE_NAMED_PIPE, 6, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_PIPE_IMPERSONATE CTL_CODE(FILE_DEVICE_NAMED_PIPE, 7, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_PIPE_SET_CLIENT_PROCESS CTL_CODE(FILE_DEVICE_NAMED_PIPE, 8, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_PIPE_QUERY_CLIENT_PROCESS CTL_CODE(FILE_DEVICE_NAMED_PIPE, 9, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_PIPE_INTERNAL_READ CTL_CODE(FILE_DEVICE_NAMED_PIPE, 2045, METHOD_BUFFERED, FILE_READ_DATA) +#define FSCTL_PIPE_INTERNAL_WRITE CTL_CODE(FILE_DEVICE_NAMED_PIPE, 2046, METHOD_BUFFERED, FILE_WRITE_DATA) +#define FSCTL_PIPE_INTERNAL_TRANSCEIVE CTL_CODE(FILE_DEVICE_NAMED_PIPE, 2047, METHOD_NEITHER, FILE_READ_DATA | FILE_WRITE_DATA) +#define FSCTL_PIPE_INTERNAL_READ_OVFLOW CTL_CODE(FILE_DEVICE_NAMED_PIPE, 2048, METHOD_BUFFERED, FILE_READ_DATA) + +#define IOCTL_REDIR_QUERY_PATH CTL_CODE(FILE_DEVICE_NETWORK_FILE_SYSTEM, 99, METHOD_NEITHER, FILE_ANY_ACCESS) + +typedef PVOID PEJOB; +typedef PVOID PNOTIFY_SYNC; +typedef PVOID OPLOCK, *POPLOCK; +typedef PVOID PWOW64_PROCESS; + +typedef ULONG LBN; +typedef LBN *PLBN; + +typedef ULONG VBN; +typedef VBN *PVBN; + +typedef struct _CACHE_MANAGER_CALLBACKS *PCACHE_MANAGER_CALLBACKS; +typedef struct _EPROCESS_QUOTA_BLOCK *PEPROCESS_QUOTA_BLOCK; +typedef struct _FILE_GET_QUOTA_INFORMATION *PFILE_GET_QUOTA_INFORMATION; +typedef struct _HANDLE_TABLE *PHANDLE_TABLE; +typedef struct _KEVENT_PAIR *PKEVENT_PAIR; +typedef struct _KPROCESS *PKPROCESS; +typedef struct _KQUEUE *PKQUEUE; +typedef struct _KTRAP_FRAME *PKTRAP_FRAME; +typedef struct _LPC_MESSAGE *PLPC_MESSAGE; +typedef struct _MAILSLOT_CREATE_PARAMETERS *PMAILSLOT_CREATE_PARAMETERS; +typedef struct _MMWSL *PMMWSL; +typedef struct _NAMED_PIPE_CREATE_PARAMETERS *PNAMED_PIPE_CREATE_PARAMETERS; +typedef struct _OBJECT_DIRECTORY *POBJECT_DIRECTORY; +typedef struct _PAGEFAULT_HISTORY *PPAGEFAULT_HISTORY; +typedef struct _PEB *PPEB; +typedef struct _PS_IMPERSONATION_INFORMATION *PPS_IMPERSONATION_INFORMATION; +typedef struct _SECTION_OBJECT *PSECTION_OBJECT; +typedef struct _SERVICE_DESCRIPTOR_TABLE *PSERVICE_DESCRIPTOR_TABLE; +typedef struct _SHARED_CACHE_MAP *PSHARED_CACHE_MAP; +typedef struct _TERMINATION_PORT *PTERMINATION_PORT; +typedef struct _VACB *PVACB; +typedef struct _VAD_HEADER *PVAD_HEADER; + +#if (VER_PRODUCTBUILD < 2195) +typedef ULONG SIZE_T, *PSIZE_T; +#endif + +typedef enum _FAST_IO_POSSIBLE { + FastIoIsNotPossible, + FastIoIsPossible, + FastIoIsQuestionable +} FAST_IO_POSSIBLE; + +typedef enum _FILE_STORAGE_TYPE { + StorageTypeDefault = 1, + StorageTypeDirectory, + StorageTypeFile, + StorageTypeJunctionPoint, + StorageTypeCatalog, + StorageTypeStructuredStorage, + StorageTypeEmbedding, + StorageTypeStream +} FILE_STORAGE_TYPE; + +typedef enum _IO_COMPLETION_INFORMATION_CLASS { + IoCompletionBasicInformation +} IO_COMPLETION_INFORMATION_CLASS; + +#if (VER_PRODUCTBUILD == 2195) + +typedef enum _KSPIN_LOCK_QUEUE_NUMBER { + LockQueueDispatcherLock, + LockQueueContextSwapLock, + LockQueuePfnLock, + LockQueueSystemSpaceLock, + LockQueueVacbLock, + LockQueueMasterLock, + LockQueueNonPagedPoolLock, + LockQueueIoCancelLock, + LockQueueWorkQueueLock, + LockQueueIoVpbLock, + LockQueueIoDatabaseLock, + LockQueueIoCompletionLock, + LockQueueNtfsStructLock, + LockQueueAfdWorkQueueLock, + LockQueueBcbLock, + LockQueueMaximumLock +} KSPIN_LOCK_QUEUE_NUMBER; + +#endif // (VER_PRODUCTBUILD == 2195) + +typedef enum _LPC_TYPE { + LPC_NEW_MESSAGE, + LPC_REQUEST, + LPC_REPLY, + LPC_DATAGRAM, + LPC_LOST_REPLY, + LPC_PORT_CLOSED, + LPC_CLIENT_DIED, + LPC_EXCEPTION, + LPC_DEBUG_EVENT, + LPC_ERROR_EVENT, + LPC_CONNECTION_REQUEST +} LPC_TYPE; + +typedef enum _MMFLUSH_TYPE { + MmFlushForDelete, + MmFlushForWrite +} MMFLUSH_TYPE; + +typedef enum _OBJECT_INFO_CLASS { + ObjectBasicInfo, + ObjectNameInfo, + ObjectTypeInfo, + ObjectAllTypesInfo, + ObjectProtectionInfo +} OBJECT_INFO_CLASS; + +typedef enum _PORT_INFORMATION_CLASS { + PortNoInformation +} PORT_INFORMATION_CLASS; + +typedef enum _SECTION_INFORMATION_CLASS { + SectionBasicInformation, + SectionImageInformation +} SECTION_INFORMATION_CLASS; + +typedef enum _SID_NAME_USE { + SidTypeUser = 1, + SidTypeGroup, + SidTypeDomain, + SidTypeAlias, + SidTypeWellKnownGroup, + SidTypeDeletedAccount, + SidTypeInvalid, + SidTypeUnknown +} SID_NAME_USE; + +typedef enum _SYSTEM_INFORMATION_CLASS { + SystemBasicInformation, + SystemProcessorInformation, + SystemPerformanceInformation, + SystemTimeOfDayInformation, + SystemNotImplemented1, + SystemProcessesAndThreadsInformation, + SystemCallCounts, + SystemConfigurationInformation, + SystemProcessorTimes, + SystemGlobalFlag, + SystemNotImplemented2, + SystemModuleInformation, + SystemLockInformation, + SystemNotImplemented3, + SystemNotImplemented4, + SystemNotImplemented5, + SystemHandleInformation, + SystemObjectInformation, + SystemPagefileInformation, + SystemInstructionEmulationCounts, + SystemInvalidInfoClass1, + SystemCacheInformation, + SystemPoolTagInformation, + SystemProcessorStatistics, + SystemDpcInformation, + SystemNotImplemented6, + SystemLoadImage, + SystemUnloadImage, + SystemTimeAdjustment, + SystemNotImplemented7, + SystemNotImplemented8, + SystemNotImplemented9, + SystemCrashDumpInformation, + SystemExceptionInformation, + SystemCrashDumpStateInformation, + SystemKernelDebuggerInformation, + SystemContextSwitchInformation, + SystemRegistryQuotaInformation, + SystemLoadAndCallImage, + SystemPrioritySeparation, + SystemNotImplemented10, + SystemNotImplemented11, + SystemInvalidInfoClass2, + SystemInvalidInfoClass3, + SystemTimeZoneInformation, + SystemLookasideInformation, + SystemSetTimeSlipEvent, + SystemCreateSession, + SystemDeleteSession, + SystemInvalidInfoClass4, + SystemRangeStartInformation, + SystemVerifierInformation, + SystemAddVerifier, + SystemSessionProcessesInformation +} SYSTEM_INFORMATION_CLASS; + +typedef enum _THREAD_STATE { + StateInitialized, + StateReady, + StateRunning, + StateStandby, + StateTerminated, + StateWait, + StateTransition, + StateUnknown +} THREAD_STATE; + +typedef enum _TOKEN_INFORMATION_CLASS { + TokenUser = 1, + TokenGroups, + TokenPrivileges, + TokenOwner, + TokenPrimaryGroup, + TokenDefaultDacl, + TokenSource, + TokenType, + TokenImpersonationLevel, + TokenStatistics, + TokenRestrictedSids +} TOKEN_INFORMATION_CLASS; + +typedef enum _TOKEN_TYPE { + TokenPrimary = 1, + TokenImpersonation +} TOKEN_TYPE; + +typedef struct _HARDWARE_PTE_X86 { + ULONG Valid : 1; + ULONG Write : 1; + ULONG Owner : 1; + ULONG WriteThrough : 1; + ULONG CacheDisable : 1; + ULONG Accessed : 1; + ULONG Dirty : 1; + ULONG LargePage : 1; + ULONG Global : 1; + ULONG CopyOnWrite : 1; + ULONG Prototype : 1; + ULONG reserved : 1; + ULONG PageFrameNumber : 20; +} HARDWARE_PTE_X86, *PHARDWARE_PTE_X86; + +typedef struct _KAPC_STATE { + LIST_ENTRY ApcListHead[2]; + PKPROCESS Process; + BOOLEAN KernelApcInProgress; + BOOLEAN KernelApcPending; + BOOLEAN UserApcPending; +} KAPC_STATE, *PKAPC_STATE; + +typedef struct _KGDTENTRY { + USHORT LimitLow; + USHORT BaseLow; + union { + struct { + UCHAR BaseMid; + UCHAR Flags1; + UCHAR Flags2; + UCHAR BaseHi; + } Bytes; + struct { + ULONG BaseMid : 8; + ULONG Type : 5; + ULONG Dpl : 2; + ULONG Pres : 1; + ULONG LimitHi : 4; + ULONG Sys : 1; + ULONG Reserved_0 : 1; + ULONG Default_Big : 1; + ULONG Granularity : 1; + ULONG BaseHi : 8; + } Bits; + } HighWord; +} KGDTENTRY, *PKGDTENTRY; + +typedef struct _KIDTENTRY { + USHORT Offset; + USHORT Selector; + USHORT Access; + USHORT ExtendedOffset; +} KIDTENTRY, *PKIDTENTRY; + +#if (VER_PRODUCTBUILD >= 2600) + +typedef struct _KPROCESS { + DISPATCHER_HEADER Header; + LIST_ENTRY ProfileListHead; + ULONG DirectoryTableBase[2]; + KGDTENTRY LdtDescriptor; + KIDTENTRY Int21Descriptor; + USHORT IopmOffset; + UCHAR Iopl; + UCHAR Unused; + ULONG ActiveProcessors; + ULONG KernelTime; + ULONG UserTime; + LIST_ENTRY ReadyListHead; + SINGLE_LIST_ENTRY SwapListEntry; + PVOID VdmTrapcHandler; + LIST_ENTRY ThreadListHead; + KSPIN_LOCK ProcessLock; + KAFFINITY Affinity; + USHORT StackCount; + CHAR BasePriority; + CHAR ThreadQuantum; + BOOLEAN AutoAlignment; + UCHAR State; + UCHAR ThreadSeed; + BOOLEAN DisableBoost; + UCHAR PowerState; + BOOLEAN DisableQuantum; + UCHAR IdealNode; + UCHAR Spare; +} KPROCESS, *PKPROCESS; + +#else + +typedef struct _KPROCESS { + DISPATCHER_HEADER Header; + LIST_ENTRY ProfileListHead; + ULONG DirectoryTableBase[2]; + KGDTENTRY LdtDescriptor; + KIDTENTRY Int21Descriptor; + USHORT IopmOffset; + UCHAR Iopl; + UCHAR VdmFlag; + ULONG ActiveProcessors; + ULONG KernelTime; + ULONG UserTime; + LIST_ENTRY ReadyListHead; + SINGLE_LIST_ENTRY SwapListEntry; + PVOID Reserved1; + LIST_ENTRY ThreadListHead; + KSPIN_LOCK ProcessLock; + KAFFINITY Affinity; + USHORT StackCount; + UCHAR BasePriority; + UCHAR ThreadQuantum; + BOOLEAN AutoAlignment; + UCHAR State; + UCHAR ThreadSeed; + BOOLEAN DisableBoost; +#if (VER_PRODUCTBUILD >= 2195) + UCHAR PowerState; + BOOLEAN DisableQuantum; + UCHAR IdealNode; + UCHAR Spare; +#endif // (VER_PRODUCTBUILD >= 2195) +} KPROCESS, *PKPROCESS; + +#endif + +#if (VER_PRODUCTBUILD >= 3790) + +typedef struct _KTHREAD { + DISPATCHER_HEADER Header; + LIST_ENTRY MutantListHead; // 0x10 + PVOID InitialStack; // 0x18 + PVOID StackLimit; // 0x1c + PVOID KernelStack; // 0x20 + ULONG ThreadLock; // 0x24 + ULONG ContextSwitches; // 0x28 + UCHAR State; // 0x2c + UCHAR NpxState; // 0x2d + UCHAR WaitIrql; // 0x2e + CHAR WaitMode; // 0x2f + struct _TEB *Teb; // 0x30 + KAPC_STATE ApcState; // 0x34 + KSPIN_LOCK ApcQueueLock; // 0x4c + NTSTATUS WaitStatus; // 0x50 + PKWAIT_BLOCK WaitBlockList; // 0x54 + BOOLEAN Alertable; // 0x58 + UCHAR WaitNext; // 0x59 + UCHAR WaitReason; // 0x5a + CHAR Priority; // 0x5b + BOOLEAN EnableStackSwap; // 0x5c + BOOLEAN SwapBusy; // 0x5d + UCHAR Alerted[2]; // 0x5e + union { + LIST_ENTRY WaitListEntry; // 0x60 + SINGLE_LIST_ENTRY SwapListEntry; // 0x60 + }; + PKQUEUE Queue; // 0x68 + ULONG WaitTime; // 0x6c + union { + struct { + USHORT KernelApcDisable; // 0x70 + USHORT SpecialApcDisable; // 0x72 + }; + USHORT CombinedApcDisable; // 0x70 + }; + KTIMER Timer; // 0x78 + KWAIT_BLOCK WaitBlock[4]; // 0xa0 + LIST_ENTRY QueueListEntry; // 0x100 + UCHAR ApcStateIndex; // 0x108 + BOOLEAN ApcQueueable; // 0x109 + BOOLEAN Preempted; // 0x10a + BOOLEAN ProcessReadyQueue; // 0x10b + BOOLEAN KernelStackResident; // 0x10c + CHAR Saturation; // 0x10d + UCHAR IdealProcessor; // 0x10e + UCHAR NextProcessor; // 0x10f + CHAR BasePriority; // 0x110 + UCHAR Spare4; // 0x111 + CHAR PriorityDecrement; // 0x112 + CHAR Quantum; // 0x113 + BOOLEAN SystemAffinityActive; // 0x114 + CHAR PreviousMode; // 0x115 + UCHAR ResourceIndex; // 0x116 + BOOLEAN DisableBoost; // 0x117 + ULONG UserAffinity; // 0x118 + PKPROCESS Process; // 0x11c + ULONG Affinity; // 0x120 + PSERVICE_DESCRIPTOR_TABLE ServiceTable; // 0x124 + PKAPC_STATE ApcStatePointer[2]; // 0x128 + KAPC_STATE SavedApcState; // 0x130 + PVOID CallbackStack; // 0x148 + PVOID Win32Thread; // 0x14c + PKTRAP_FRAME TrapFrame; // 0x150 + ULONG KernelTime; // 0x154 + ULONG UserTime; // 0x158 + PVOID StackBase; // 0x15c + KAPC SuspendApc; // 0x160 + KSEMAPHORE SuspendSemaphore; // 0x190 + PVOID TlsArray; // 0x1a4 + PVOID LegoData; // 0x1a8 + LIST_ENTRY ThreadListEntry; // 0x1ac + BOOLEAN LargeStack; // 0x1b4 + UCHAR PowerState; // 0x1b5 + UCHAR NpxIrql; // 0x1b6 + UCHAR Spare5; // 0x1b7 + BOOLEAN AutoAlignment; // 0x1b8 + UCHAR Iopl; // 0x1b9 + CHAR FreezeCount; // 0x1ba + CHAR SuspendCount; // 0x1bb + UCHAR Spare0[1]; // 0x1bc + UCHAR UserIdealProcessor; // 0x1bd + UCHAR DeferredProcessor; // 0x1be + UCHAR AdjustReason; // 0x1bf + CHAR AdjustIncrement; // 0x1c0 + UCHAR Spare2[3]; // 0x1c1 +} KTHREAD, *PKTHREAD; + +#elif (VER_PRODUCTBUILD >= 2600) + +typedef struct _KTHREAD { + DISPATCHER_HEADER Header; + LIST_ENTRY MutantListHead; + PVOID InitialStack; + PVOID StackLimit; + struct _TEB *Teb; + PVOID TlsArray; + PVOID KernelStack; + BOOLEAN DebugActive; + UCHAR State; + UCHAR Alerted[2]; + UCHAR Iopl; + UCHAR NpxState; + CHAR Saturation; + CHAR Priority; + KAPC_STATE ApcState; + ULONG ContextSwitches; + UCHAR IdleSwapBlock; + UCHAR Spare0[3]; + NTSTATUS WaitStatus; + UCHAR WaitIrql; + CHAR WaitMode; + UCHAR WaitNext; + UCHAR WaitReason; + PKWAIT_BLOCK WaitBlockList; + union { + LIST_ENTRY WaitListEntry; + SINGLE_LIST_ENTRY SwapListEntry; + }; + ULONG WaitTime; + CHAR BasePriority; + UCHAR DecrementCount; + CHAR PriorityDecrement; + CHAR Quantum; + KWAIT_BLOCK WaitBlock[4]; + PVOID LegoData; + ULONG KernelApcDisable; + ULONG UserAffinity; + BOOLEAN SystemAffinityActive; + UCHAR PowerState; + UCHAR NpxIrql; + UCHAR InitialNode; + PSERVICE_DESCRIPTOR_TABLE ServiceTable; + PKQUEUE Queue; + KSPIN_LOCK ApcQueueLock; + KTIMER Timer; + LIST_ENTRY QueueListEntry; + ULONG SoftAffinity; + ULONG Affinity; + BOOLEAN Preempted; + BOOLEAN ProcessReadyQueue; + BOOLEAN KernelStackResident; + UCHAR NextProcessor; + PVOID CallbackStack; + PVOID Win32Thread; + PKTRAP_FRAME TrapFrame; + PKAPC_STATE ApcStatePointer[2]; + CHAR PreviousMode; + BOOLEAN EnableStackSwap; + BOOLEAN LargeStack; + UCHAR ResourceIndex; + ULONG KernelTime; + ULONG UserTime; + KAPC_STATE SavedApcState; + BOOLEAN Alertable; + UCHAR ApcStateIndex; + BOOLEAN ApcQueueable; + BOOLEAN AutoAlignment; + PVOID StackBase; + KAPC SuspendApc; + KSEMAPHORE SuspendSemaphore; + LIST_ENTRY ThreadListEntry; + CHAR FreezeCount; + CHAR SuspendCount; + UCHAR IdealProcessor; + BOOLEAN DisableBoost; +} KTHREAD, *PKTHREAD; + +#else + +typedef struct _KTHREAD { + DISPATCHER_HEADER Header; + LIST_ENTRY MutantListHead; + PVOID InitialStack; + PVOID StackLimit; + struct _TEB *Teb; + PVOID TlsArray; + PVOID KernelStack; + BOOLEAN DebugActive; + UCHAR State; + USHORT Alerted; + UCHAR Iopl; + UCHAR NpxState; + UCHAR Saturation; + UCHAR Priority; + KAPC_STATE ApcState; + ULONG ContextSwitches; + NTSTATUS WaitStatus; + UCHAR WaitIrql; + UCHAR WaitMode; + UCHAR WaitNext; + UCHAR WaitReason; + PKWAIT_BLOCK WaitBlockList; + LIST_ENTRY WaitListEntry; + ULONG WaitTime; + UCHAR BasePriority; + UCHAR DecrementCount; + UCHAR PriorityDecrement; + UCHAR Quantum; + KWAIT_BLOCK WaitBlock[4]; + ULONG LegoData; + ULONG KernelApcDisable; + ULONG UserAffinity; + BOOLEAN SystemAffinityActive; +#if (VER_PRODUCTBUILD < 2195) + UCHAR Pad[3]; +#else // (VER_PRODUCTBUILD >= 2195) + UCHAR PowerState; + UCHAR NpxIrql; + UCHAR Pad[1]; +#endif // (VER_PRODUCTBUILD >= 2195) + PSERVICE_DESCRIPTOR_TABLE ServiceDescriptorTable; + PKQUEUE Queue; + KSPIN_LOCK ApcQueueLock; + KTIMER Timer; + LIST_ENTRY QueueListEntry; + ULONG Affinity; + BOOLEAN Preempted; + BOOLEAN ProcessReadyQueue; + BOOLEAN KernelStackResident; + UCHAR NextProcessor; + PVOID CallbackStack; + PVOID Win32Thread; + PKTRAP_FRAME TrapFrame; + PKAPC_STATE ApcStatePointer[2]; +#if (VER_PRODUCTBUILD >= 2195) + UCHAR PreviousMode; +#endif // (VER_PRODUCTBUILD >= 2195) + BOOLEAN EnableStackSwap; + BOOLEAN LargeStack; + UCHAR ResourceIndex; +#if (VER_PRODUCTBUILD < 2195) + UCHAR PreviousMode; +#endif // (VER_PRODUCTBUILD < 2195) + ULONG KernelTime; + ULONG UserTime; + KAPC_STATE SavedApcState; + BOOLEAN Alertable; + UCHAR ApcStateIndex; + BOOLEAN ApcQueueable; + BOOLEAN AutoAlignment; + PVOID StackBase; + KAPC SuspendApc; + KSEMAPHORE SuspendSemaphore; + LIST_ENTRY ThreadListEntry; + UCHAR FreezeCount; + UCHAR SuspendCount; + UCHAR IdealProcessor; + BOOLEAN DisableBoost; +} KTHREAD, *PKTHREAD; + +#endif + +#if (VER_PRODUCTBUILD >= 3790) + +typedef struct _MMSUPPORT_FLAGS { + ULONG SessionSpace : 1; + ULONG BeingTrimmed : 1; + ULONG SessionLeader : 1; + ULONG TrimHard : 1; + ULONG MaximumWorkingSetHard : 1; + ULONG ForceTrim : 1; + ULONG MinimumWorkingSetHard : 1; + ULONG Available0 : 1; + ULONG MemoryPriority : 8; + ULONG GrowWsleHash : 1; + ULONG AcquiredUnsafe : 1; + ULONG Available : 14; +} MMSUPPORT_FLAGS, *PMMSUPPORT_FLAGS; + +#elif (VER_PRODUCTBUILD >= 2600) + +typedef struct _MMSUPPORT_FLAGS { + ULONG SessionSpace : 1; + ULONG BeingTrimmed : 1; + ULONG SessionLeader : 1; + ULONG TrimHard : 1; + ULONG WorkingSetHard : 1; + ULONG AddressSpaceBeingDeleted : 1; + ULONG Available : 10; + ULONG AllowWorkingSetAdjustment : 8; + ULONG MemoryPriority : 8; +} MMSUPPORT_FLAGS, *PMMSUPPORT_FLAGS; + +#else + +typedef struct _MMSUPPORT_FLAGS { + ULONG SessionSpace : 1; + ULONG BeingTrimmed : 1; + ULONG ProcessInSession : 1; + ULONG SessionLeader : 1; + ULONG TrimHard : 1; + ULONG WorkingSetHard : 1; + ULONG WriteWatch : 1; + ULONG Filler : 25; +} MMSUPPORT_FLAGS, *PMMSUPPORT_FLAGS; + +#endif + +#if (VER_PRODUCTBUILD >= 3790) +/* +typedef struct _KGUARDED_MUTEX { + LONG Count; + PKTHREAD Owner; // 0x4 + ULONG Contention; // 0x8 + KEVENT Event; // 0xc + union { + struct { + USHORT KernelApcDisable; // 0x1c + USHORT SpecialApcDisable; // 0x1e + }; + USHORT CombinedApcDisable; // 0x1c + }; +} KGUARDED_MUTEX, *PKGUARDED_MUTEX; +*/ +typedef struct _MMSUPPORT { + LIST_ENTRY WorkingSetExpansionLinks; + LARGE_INTEGER LastTrimTime; // 0x8 + MMSUPPORT_FLAGS Flags; // 0x10 + ULONG PageFaultCount; // 0x14 + ULONG PeakWorkingSetSize; // 0x18 + ULONG GrowthSinceLastEstimate; // 0x1c + ULONG MinimumWorkingSetSize; // 0x20 + ULONG MaximumWorkingSetSize; // 0x24 + PMMWSL VmWorkingSetList; // 0x28 + ULONG Claim; // 0x2c + ULONG NextEstimationSlot; // 0x30 + ULONG NextAgingSlot; // 0x34 + ULONG EstimatedAvailable; // 0x38 + ULONG WorkingSetSize; //0x3c + KGUARDED_MUTEX Mutex; // 0x40 +} MMSUPPORT, *PMMSUPPORT; + +#elif (VER_PRODUCTBUILD >= 2600) + +typedef struct _MMSUPPORT { + LARGE_INTEGER LastTrimTime; + MMSUPPORT_FLAGS Flags; + ULONG PageFaultCount; + ULONG PeakWorkingSetSize; + ULONG WorkingSetSize; + ULONG MinimumWorkingSetSize; + ULONG MaximumWorkingSetSize; + PMMWSL VmWorkingSetList; + LIST_ENTRY WorkingSetExpansionLinks; + ULONG Claim; + ULONG NextEstimationSlot; + ULONG NextAgingSlot; + ULONG EstimatedAvailable; + ULONG GrowthSinceLastEstimate; +} MMSUPPORT, *PMMSUPPORT; + +#else + +typedef struct _MMSUPPORT { + LARGE_INTEGER LastTrimTime; + ULONG LastTrimFaultCount; + ULONG PageFaultCount; + ULONG PeakWorkingSetSize; + ULONG WorkingSetSize; + ULONG MinimumWorkingSetSize; + ULONG MaximumWorkingSetSize; + PMMWSL VmWorkingSetList; + LIST_ENTRY WorkingSetExpansionLinks; + BOOLEAN AllowWorkingSetAdjustment; + BOOLEAN AddressSpaceBeingDeleted; + UCHAR ForegroundSwitchCount; + UCHAR MemoryPriority; +#if (VER_PRODUCTBUILD >= 2195) + union { + ULONG LongFlags; + MMSUPPORT_FLAGS Flags; + } u; + ULONG Claim; + ULONG NextEstimationSlot; + ULONG NextAgingSlot; + ULONG EstimatedAvailable; + ULONG GrowthSinceLastEstimate; +#endif // (VER_PRODUCTBUILD >= 2195) +} MMSUPPORT, *PMMSUPPORT; + +#endif + +typedef struct _SE_AUDIT_PROCESS_CREATION_INFO { + POBJECT_NAME_INFORMATION ImageFileName; +} SE_AUDIT_PROCESS_CREATION_INFO, *PSE_AUDIT_PROCESS_CREATION_INFO; + +typedef struct _SID_IDENTIFIER_AUTHORITY { + UCHAR Value[6]; +} SID_IDENTIFIER_AUTHORITY, *PSID_IDENTIFIER_AUTHORITY; + +typedef struct _SID { + UCHAR Revision; + UCHAR SubAuthorityCount; + SID_IDENTIFIER_AUTHORITY IdentifierAuthority; + ULONG SubAuthority[1]; +} SID, *PREAL_SID; + +typedef struct _BITMAP_DESCRIPTOR { + ULONGLONG StartLcn; + ULONGLONG ClustersToEndOfVol; + UCHAR Map[1]; +} BITMAP_DESCRIPTOR, *PBITMAP_DESCRIPTOR; + +typedef struct _BITMAP_RANGE { + LIST_ENTRY Links; + LARGE_INTEGER BasePage; + ULONG FirstDirtyPage; + ULONG LastDirtyPage; + ULONG DirtyPages; + PULONG Bitmap; +} BITMAP_RANGE, *PBITMAP_RANGE; + +typedef struct _CACHE_UNINITIALIZE_EVENT { + struct _CACHE_UNINITIALIZE_EVENT *Next; + KEVENT Event; +} CACHE_UNINITIALIZE_EVENT, *PCACHE_UNINITIALIZE_EVENT; + +typedef struct _CC_FILE_SIZES { + LARGE_INTEGER AllocationSize; + LARGE_INTEGER FileSize; + LARGE_INTEGER ValidDataLength; +} CC_FILE_SIZES, *PCC_FILE_SIZES; + +typedef struct _COMPRESSED_DATA_INFO { + USHORT CompressionFormatAndEngine; + UCHAR CompressionUnitShift; + UCHAR ChunkShift; + UCHAR ClusterShift; + UCHAR Reserved; + USHORT NumberOfChunks; + ULONG CompressedChunkSizes[ANYSIZE_ARRAY]; +} COMPRESSED_DATA_INFO, *PCOMPRESSED_DATA_INFO; + +typedef struct _DEVICE_MAP { + POBJECT_DIRECTORY DosDevicesDirectory; + POBJECT_DIRECTORY GlobalDosDevicesDirectory; + ULONG ReferenceCount; + ULONG DriveMap; + UCHAR DriveType[32]; +} DEVICE_MAP, *PDEVICE_MAP; + +typedef struct _DIRECTORY_BASIC_INFORMATION { + UNICODE_STRING ObjectName; + UNICODE_STRING ObjectTypeName; +} DIRECTORY_BASIC_INFORMATION, *PDIRECTORY_BASIC_INFORMATION; + +#if (VER_PRODUCTBUILD >= 2600) + +typedef struct _EX_FAST_REF { + union { + PVOID Object; + ULONG RefCnt : 3; + ULONG Value; + }; +} EX_FAST_REF, *PEX_FAST_REF; + +typedef struct _EX_PUSH_LOCK { + union { + struct { + ULONG Waiting : 1; + ULONG Exclusive : 1; + ULONG Shared : 30; + }; + ULONG Value; + PVOID Ptr; + }; +} EX_PUSH_LOCK, *PEX_PUSH_LOCK; + +#endif // (VER_PRODUCTBUILD >= 2600) + +#if (VER_PRODUCTBUILD == 2600) + +typedef struct _EX_RUNDOWN_REF { + union { + ULONG Count; + PVOID Ptr; + }; +} EX_RUNDOWN_REF, *PEX_RUNDOWN_REF; + +#endif // (VER_PRODUCTBUILD == 2600) + +#if (VER_PRODUCTBUILD >= 3790) + +typedef struct _MM_ADDRESS_NODE { + union { + ULONG Balance : 2; + struct _MM_ADDRESS_NODE *Parent; // lower 2 bits of Parent are Balance and must be zeroed to obtain Parent + }; + struct _MM_ADDRESS_NODE *LeftChild; + struct _MM_ADDRESS_NODE *RightChild; + ULONG_PTR StartingVpn; + ULONG_PTR EndingVpn; +} MMADDRESS_NODE, *PMMADDRESS_NODE; + +typedef struct _MM_AVL_TABLE { + MMADDRESS_NODE BalancedRoot; // Vadroot; incorrectly represents the NULL pages (EndingVpn should be 0xf, etc.) + ULONG DepthOfTree : 5; // 0x14 + ULONG Unused : 3; + ULONG NumberGenericTableElements : 24; // total number of nodes + PVOID NodeHint; // 0x18 (0x270 in _EPROCESS) + PVOID NodeFreeHint; // 0x1c +} MM_AVL_TABLE, *PMM_AVL_TABLE; + +typedef struct _EPROCESS { + KPROCESS Pcb; // +0x000 + EX_PUSH_LOCK ProcessLock; // +0x06c + LARGE_INTEGER CreateTime; // +0x070 + LARGE_INTEGER ExitTime; // +0x078 + EX_RUNDOWN_REF RundownProtect; // +0x080 + ULONG UniqueProcessId; // +0x084 + LIST_ENTRY ActiveProcessLinks; // +0x088 + ULONG QuotaUsage[3]; // +0x090 + ULONG QuotaPeak[3]; // +0x09c + ULONG CommitCharge; // +0x0a8 + ULONG PeakVirtualSize; // +0x0ac + ULONG VirtualSize; // +0x0b0 + LIST_ENTRY SessionProcessLinks; // +0x0b4 + PVOID DebugPort; // +0x0bc + PVOID ExceptionPort; // +0x0c0 + PHANDLE_TABLE ObjectTable; // +0x0c4 + EX_FAST_REF Token; // +0x0c8 + ULONG WorkingSetPage; // +0x0cc + KGUARDED_MUTEX AddressCreationLock; // +0x0d0 + ULONG HyperSpaceLock; // +0x0f0 + PETHREAD ForkInProgress; // +0x0f4 + ULONG HardwareTrigger; // +0x0f8 + PMM_AVL_TABLE PhysicalVadRoot; // +0x0fc + PVOID CloneRoot; // +0x100 + ULONG NumberOfPrivatePages; // +0x104 + ULONG NumberOfLockedPages; // +0x108 + PVOID Win32Process; // +0x10c + PEJOB Job; // +0x110 + PVOID SectionObject; // +0x114 + PVOID SectionBaseAddress; // +0x118 + PEPROCESS_QUOTA_BLOCK QuotaBlock; // +0x11c + PPAGEFAULT_HISTORY WorkingSetWatch; // +0x120 + PVOID Win32WindowStation; // +0x124 + ULONG InheritedFromUniqueProcessId; // +0x128 + PVOID LdtInformation; // +0x12c + PVOID VadFreeHint; // +0x130 + PVOID VdmObjects; // +0x134 + PVOID DeviceMap; // +0x138 + PVOID Spare0[3]; // +0x13c + union { + HARDWARE_PTE PageDirectoryPte; // +0x148 + UINT64 Filler; // +0x148 + }; + PVOID Session; // +0x150 + UCHAR ImageFileName[16]; // +0x154 + LIST_ENTRY JobLinks; // +0x164 + PVOID LockedPagesList; // +0x16c + LIST_ENTRY ThreadListHead; // +0x170 + PVOID SecurityPort; // +0x178 + PVOID PaeTop; // +0x17c + ULONG ActiveThreads; // +0x180 + ULONG GrantedAccess; // +0x184 + ULONG DefaultHardErrorProcessing; // +0x188 + SHORT LastThreadExitStatus; // +0x18c + PPEB Peb; // +0x190 + EX_FAST_REF PrefetchTrace; // +0x194 + LARGE_INTEGER ReadOperationCount; // +0x198 + LARGE_INTEGER WriteOperationCount; // +0x1a0 + LARGE_INTEGER OtherOperationCount; // +0x1a8 + LARGE_INTEGER ReadTransferCount; // +0x1b0 + LARGE_INTEGER WriteTransferCount; // +0x1b8 + LARGE_INTEGER OtherTransferCount; // +0x1c0 + ULONG CommitChargeLimit; // +0x1c8 + ULONG CommitChargePeak; // +0x1cc + PVOID AweInfo; // +0x1d0 + SE_AUDIT_PROCESS_CREATION_INFO SeAuditProcessCreationInfo; // +0x1d4 + MMSUPPORT Vm; // +0x1d8 + LIST_ENTRY MmProcessLinks; // +0x238 + ULONG ModifiedPageCount; // +0x240 + ULONG JobStatus; // +0x244 + union { + ULONG Flags; // 0x248 + struct { + ULONG CreateReported : 1; + ULONG NoDebugInherit : 1; + ULONG ProcessExiting : 1; + ULONG ProcessDelete : 1; + ULONG Wow64SplitPages : 1; + ULONG VmDeleted : 1; + ULONG OutswapEnabled : 1; + ULONG Outswapped : 1; + ULONG ForkFailed : 1; + ULONG Wow64VaSpace4Gb : 1; + ULONG AddressSpaceInitialized : 2; + ULONG SetTimerResolution : 1; + ULONG BreakOnTermination : 1; + ULONG SessionCreationUnderway : 1; + ULONG WriteWatch : 1; + ULONG ProcessInSession : 1; + ULONG OverrideAddressSpace : 1; + ULONG HasAddressSpace : 1; + ULONG LaunchPrefetched : 1; + ULONG InjectInpageErrors : 1; + ULONG VmTopDown : 1; + ULONG ImageNotifyDone : 1; + ULONG PdeUpdateNeeded : 1; + ULONG VdmAllowed : 1; + ULONG Unused : 7; + }; + }; + NTSTATUS ExitStatus; // +0x24c + USHORT NextPageColor; // +0x250 + union { + struct { + UCHAR SubSystemMinorVersion; // +0x252 + UCHAR SubSystemMajorVersion; // +0x253 + }; + USHORT SubSystemVersion; // +0x252 + }; + UCHAR PriorityClass; // +0x254 + MM_AVL_TABLE VadRoot; // +0x258 +} EPROCESS, *PEPROCESS; // 0x278 in total + +#elif (VER_PRODUCTBUILD >= 2600) + +typedef struct _EPROCESS { + KPROCESS Pcb; + EX_PUSH_LOCK ProcessLock; + LARGE_INTEGER CreateTime; + LARGE_INTEGER ExitTime; + EX_RUNDOWN_REF RundownProtect; + ULONG UniqueProcessId; + LIST_ENTRY ActiveProcessLinks; + ULONG QuotaUsage[3]; + ULONG QuotaPeak[3]; + ULONG CommitCharge; + ULONG PeakVirtualSize; + ULONG VirtualSize; + LIST_ENTRY SessionProcessLinks; + PVOID DebugPort; + PVOID ExceptionPort; + PHANDLE_TABLE ObjectTable; + EX_FAST_REF Token; + FAST_MUTEX WorkingSetLock; + ULONG WorkingSetPage; + FAST_MUTEX AddressCreationLock; + KSPIN_LOCK HyperSpaceLock; + PETHREAD ForkInProgress; + ULONG HardwareTrigger; + PVOID VadRoot; + PVOID VadHint; + PVOID CloneRoot; + ULONG NumberOfPrivatePages; + ULONG NumberOfLockedPages; + PVOID Win32Process; + PEJOB Job; + PSECTION_OBJECT SectionObject; + PVOID SectionBaseAddress; + PEPROCESS_QUOTA_BLOCK QuotaBlock; + PPAGEFAULT_HISTORY WorkingSetWatch; + PVOID Win32WindowStation; + PVOID InheritedFromUniqueProcessId; + PVOID LdtInformation; + PVOID VadFreeHint; + PVOID VdmObjects; + PDEVICE_MAP DeviceMap; + LIST_ENTRY PhysicalVadList; + union { + HARDWARE_PTE PageDirectoryPte; + ULONGLONG Filler; + }; + PVOID Session; + UCHAR ImageFileName[16]; + LIST_ENTRY JobLinks; + PVOID LockedPageList; + LIST_ENTRY ThreadListHead; + PVOID SecurityPort; + PVOID PaeTop; + ULONG ActiveThreads; + ULONG GrantedAccess; + ULONG DefaultHardErrorProcessing; + NTSTATUS LastThreadExitStatus; + PPEB Peb; + EX_FAST_REF PrefetchTrace; + LARGE_INTEGER ReadOperationCount; + LARGE_INTEGER WriteOperationCount; + LARGE_INTEGER OtherOperationCount; + LARGE_INTEGER ReadTransferCount; + LARGE_INTEGER WriteTransferCount; + LARGE_INTEGER OtherTransferCount; + ULONG CommitChargeLimit; + ULONG CommitChargePeek; + PVOID AweInfo; + SE_AUDIT_PROCESS_CREATION_INFO SeAuditProcessCreationInfo; + MMSUPPORT Vm; + ULONG LastFaultCount; + ULONG ModifiedPageCount; + ULONG NumberOfVads; + ULONG JobStatus; + union { + ULONG Flags; + struct { + ULONG CreateReported : 1; + ULONG NoDebugInherit : 1; + ULONG ProcessExiting : 1; + ULONG ProcessDelete : 1; + ULONG Wow64SplitPages : 1; + ULONG VmDeleted : 1; + ULONG OutswapEnabled : 1; + ULONG Outswapped : 1; + ULONG ForkFailed : 1; + ULONG HasPhysicalVad : 1; + ULONG AddressSpaceInitialized : 2; + ULONG SetTimerResolution : 1; + ULONG BreakOnTermination : 1; + ULONG SessionCreationUnderway : 1; + ULONG WriteWatch : 1; + ULONG ProcessInSession : 1; + ULONG OverrideAddressSpace : 1; + ULONG HasAddressSpace : 1; + ULONG LaunchPrefetched : 1; + ULONG InjectInpageErrors : 1; + ULONG Unused : 11; + }; + }; + NTSTATUS ExitStatus; + USHORT NextPageColor; + union { + struct { + UCHAR SubSystemMinorVersion; + UCHAR SubSystemMajorVersion; + }; + USHORT SubSystemVersion; + }; + UCHAR PriorityClass; + BOOLEAN WorkingSetAcquiredUnsafe; +} EPROCESS, *PEPROCESS; + +#else + +typedef struct _EPROCESS { + KPROCESS Pcb; + NTSTATUS ExitStatus; + KEVENT LockEvent; + ULONG LockCount; + LARGE_INTEGER CreateTime; + LARGE_INTEGER ExitTime; + PKTHREAD LockOwner; + ULONG UniqueProcessId; + LIST_ENTRY ActiveProcessLinks; + ULONGLONG QuotaPeakPoolUsage; + ULONGLONG QuotaPoolUsage; + ULONG PagefileUsage; + ULONG CommitCharge; + ULONG PeakPagefileUsage; + ULONG PeakVirtualSize; + ULONGLONG VirtualSize; + MMSUPPORT Vm; +#if (VER_PRODUCTBUILD < 2195) + ULONG LastProtoPteFault; +#else // (VER_PRODUCTBUILD >= 2195) + LIST_ENTRY SessionProcessLinks; +#endif // (VER_PRODUCTBUILD >= 2195) + ULONG DebugPort; + ULONG ExceptionPort; + PHANDLE_TABLE ObjectTable; + PACCESS_TOKEN Token; + FAST_MUTEX WorkingSetLock; + ULONG WorkingSetPage; + BOOLEAN ProcessOutswapEnabled; + BOOLEAN ProcessOutswapped; + BOOLEAN AddressSpaceInitialized; + BOOLEAN AddressSpaceDeleted; + FAST_MUTEX AddressCreationLock; + KSPIN_LOCK HyperSpaceLock; + PETHREAD ForkInProgress; + USHORT VmOperation; + BOOLEAN ForkWasSuccessful; + UCHAR MmAgressiveWsTrimMask; + PKEVENT VmOperationEvent; +#if (VER_PRODUCTBUILD < 2195) + HARDWARE_PTE PageDirectoryPte; +#else // (VER_PRODUCTBUILD >= 2195) + PVOID PaeTop; +#endif // (VER_PRODUCTBUILD >= 2195) + ULONG LastFaultCount; + ULONG ModifiedPageCount; + PVOID VadRoot; + PVOID VadHint; + ULONG CloneRoot; + ULONG NumberOfPrivatePages; + ULONG NumberOfLockedPages; + USHORT NextPageColor; + BOOLEAN ExitProcessCalled; + BOOLEAN CreateProcessReported; + HANDLE SectionHandle; + PPEB Peb; + PVOID SectionBaseAddress; + PEPROCESS_QUOTA_BLOCK QuotaBlock; + NTSTATUS LastThreadExitStatus; + PPROCESS_WS_WATCH_INFORMATION WorkingSetWatch; + HANDLE Win32WindowStation; + HANDLE InheritedFromUniqueProcessId; + ACCESS_MASK GrantedAccess; + ULONG DefaultHardErrorProcessing; + PVOID LdtInformation; + PVOID VadFreeHint; + PVOID VdmObjects; +#if (VER_PRODUCTBUILD < 2195) + KMUTANT ProcessMutant; +#else // (VER_PRODUCTBUILD >= 2195) + PDEVICE_MAP DeviceMap; + ULONG SessionId; + LIST_ENTRY PhysicalVadList; + HARDWARE_PTE PageDirectoryPte; + ULONG Filler; + ULONG PaePageDirectoryPage; +#endif // (VER_PRODUCTBUILD >= 2195) + UCHAR ImageFileName[16]; + ULONG VmTrimFaultValue; + UCHAR SetTimerResolution; + UCHAR PriorityClass; + union { + struct { + UCHAR SubSystemMinorVersion; + UCHAR SubSystemMajorVersion; + }; + USHORT SubSystemVersion; + }; + PVOID Win32Process; +#if (VER_PRODUCTBUILD >= 2195) + PEJOB Job; + ULONG JobStatus; + LIST_ENTRY JobLinks; + PVOID LockedPageList; + PVOID SecurityPort; + PWOW64_PROCESS Wow64Process; + LARGE_INTEGER ReadOperationCount; + LARGE_INTEGER WriteOperationCount; + LARGE_INTEGER OtherOperationCount; + LARGE_INTEGER ReadTransferCount; + LARGE_INTEGER WriteTransferCount; + LARGE_INTEGER OtherTransferCount; + ULONG CommitChargeLimit; + ULONG CommitChargePeek; + LIST_ENTRY ThreadListHead; + PRTL_BITMAP VadPhysicalPagesBitMap; + ULONG VadPhysicalPages; + ULONG AweLock; +#endif // (VER_PRODUCTBUILD >= 2195) +} EPROCESS, *PEPROCESS; + +#endif + +#if (VER_PRODUCTBUILD >= 2600) + +typedef struct _ETHREAD { + KTHREAD Tcb; + union { + LARGE_INTEGER CreateTime; + struct { + ULONG NestedFaultCount : 2; + ULONG ApcNeeded : 1; + }; + }; + union { + LARGE_INTEGER ExitTime; + LIST_ENTRY LpcReplyChain; + LIST_ENTRY KeyedWaitChain; + }; + union { + NTSTATUS ExitStatus; + PVOID OfsChain; + }; + LIST_ENTRY PostBlockList; + union { + PTERMINATION_PORT TerminationPort; + PETHREAD ReaperLink; + PVOID KeyedWaitValue; + }; + KSPIN_LOCK ActiveTimerListLock; + LIST_ENTRY ActiveTimerListHead; + CLIENT_ID Cid; + union { + KSEMAPHORE LpcReplySemaphore; + KSEMAPHORE KeyedWaitSemaphore; + }; + union { + PLPC_MESSAGE LpcReplyMessage; + PVOID LpcWaitingOnPort; + }; + PPS_IMPERSONATION_INFORMATION ImpersonationInfo; + LIST_ENTRY IrpList; + ULONG TopLevelIrp; + PDEVICE_OBJECT DeviceToVerify; + PEPROCESS ThreadsProcess; + PKSTART_ROUTINE StartAddress; + union { + PVOID Win32StartAddress; + ULONG LpcReceivedMessageId; + }; + LIST_ENTRY ThreadListEntry; + EX_RUNDOWN_REF RundownProtect; + EX_PUSH_LOCK ThreadLock; + ULONG LpcReplyMessageId; + ULONG ReadClusterSize; + ACCESS_MASK GrantedAccess; + union { + ULONG CrossThreadFlags; + struct { + ULONG Terminated : 1; + ULONG DeadThread : 1; + ULONG HideFromDebugger : 1; + ULONG ActiveImpersonationInfo : 1; + ULONG SystemThread : 1; + ULONG HardErrorsAreDisabled : 1; + ULONG BreakOnTermination : 1; + ULONG SkipCreationMsg : 1; + ULONG SkipTerminationMsg : 1; + }; + }; + union { + ULONG SameThreadPassiveFlags; + struct { + ULONG ActiveExWorker : 1; + ULONG ExWorkerCanWaitUser : 1; + ULONG MemoryMaker : 1; + ULONG KeyedEventInUse : 1; + }; + }; + union { + ULONG SameThreadApcFlags; + struct { + BOOLEAN LpcReceivedMsgIdValid : 1; + BOOLEAN LpcExitThreadCalled : 1; + BOOLEAN AddressSpaceOwner : 1; + }; + }; + BOOLEAN ForwardClusterOnly; + BOOLEAN DisablePageFaultClustering; +} ETHREAD, *PETHREAD; + +#else + +typedef struct _ETHREAD { + KTHREAD Tcb; + LARGE_INTEGER CreateTime; + union { + LARGE_INTEGER ExitTime; + LIST_ENTRY LpcReplyChain; + }; + union { + NTSTATUS ExitStatus; + PVOID OfsChain; + }; + LIST_ENTRY PostBlockList; + LIST_ENTRY TerminationPortList; + KSPIN_LOCK ActiveTimerListLock; + LIST_ENTRY ActiveTimerListHead; + CLIENT_ID Cid; + KSEMAPHORE LpcReplySemaphore; + PLPC_MESSAGE LpcReplyMessage; + ULONG LpcReplyMessageId; + ULONG PerformanceCountLow; + PPS_IMPERSONATION_INFORMATION ImpersonationInfo; + LIST_ENTRY IrpList; + PVOID TopLevelIrp; + PDEVICE_OBJECT DeviceToVerify; + ULONG ReadClusterSize; + BOOLEAN ForwardClusterOnly; + BOOLEAN DisablePageFaultClustering; + BOOLEAN DeadThread; +#if (VER_PRODUCTBUILD >= 2195) + BOOLEAN HideFromDebugger; +#endif // (VER_PRODUCTBUILD >= 2195) +#if (VER_PRODUCTBUILD < 2195) + BOOLEAN HasTerminated; +#else // (VER_PRODUCTBUILD >= 2195) + ULONG HasTerminated; +#endif // (VER_PRODUCTBUILD >= 2195) +#if (VER_PRODUCTBUILD < 2195) + PKEVENT_PAIR EventPair; +#endif // (VER_PRODUCTBUILD < 2195) + ACCESS_MASK GrantedAccess; + PEPROCESS ThreadsProcess; + PKSTART_ROUTINE StartAddress; + union { + PVOID Win32StartAddress; + ULONG LpcReceivedMessageId; + }; + BOOLEAN LpcExitThreadCalled; + BOOLEAN HardErrorsAreDisabled; + BOOLEAN LpcReceivedMsgIdValid; + BOOLEAN ActiveImpersonationInfo; + ULONG PerformanceCountHigh; +#if (VER_PRODUCTBUILD >= 2195) + LIST_ENTRY ThreadListEntry; +#endif // (VER_PRODUCTBUILD >= 2195) +} ETHREAD, *PETHREAD; + +#endif + +typedef struct _EPROCESS_QUOTA_ENTRY { + ULONG Usage; + ULONG Limit; + ULONG Peak; + ULONG Return; +} EPROCESS_QUOTA_ENTRY, *PEPROCESS_QUOTA_ENTRY; + +typedef struct _EPROCESS_QUOTA_BLOCK { + EPROCESS_QUOTA_ENTRY QuotaEntry[3]; + LIST_ENTRY QuotaList; + ULONG ReferenceCount; + ULONG ProcessCount; +} EPROCESS_QUOTA_BLOCK, *PEPROCESS_QUOTA_BLOCK; + +typedef struct _EXCEPTION_REGISTRATION_RECORD { + struct _EXCEPTION_REGISTRATION_RECORD *Next; + PVOID Handler; +} EXCEPTION_REGISTRATION_RECORD, *PEXCEPTION_REGISTRATION_RECORD; + +/* + * When needing these parameters cast your PIO_STACK_LOCATION to + * PEXTENDED_IO_STACK_LOCATION + */ +#if !defined(_ALPHA_) && !defined(_AMD64_) && !defined(_IA64_) +#include +#endif +typedef struct _EXTENDED_IO_STACK_LOCATION { + + /* Included for padding */ + UCHAR MajorFunction; + UCHAR MinorFunction; + UCHAR Flags; + UCHAR Control; + + union { + + struct { + PIO_SECURITY_CONTEXT SecurityContext; + ULONG Options; + USHORT Reserved; + USHORT ShareAccess; + PMAILSLOT_CREATE_PARAMETERS Parameters; + } CreateMailslot; + + struct { + PIO_SECURITY_CONTEXT SecurityContext; + ULONG Options; + USHORT Reserved; + USHORT ShareAccess; + PNAMED_PIPE_CREATE_PARAMETERS Parameters; + } CreatePipe; + + struct { + ULONG OutputBufferLength; + ULONG InputBufferLength; + ULONG FsControlCode; + PVOID Type3InputBuffer; + } FileSystemControl; + + struct { + PLARGE_INTEGER Length; + ULONG Key; + LARGE_INTEGER ByteOffset; + } LockControl; + + struct { + ULONG Length; + ULONG CompletionFilter; + } NotifyDirectory; + + struct { + ULONG Length; + PUNICODE_STRING FileName; + FILE_INFORMATION_CLASS FileInformationClass; + ULONG FileIndex; + } QueryDirectory; + + struct { + ULONG Length; + PVOID EaList; + ULONG EaListLength; + ULONG EaIndex; + } QueryEa; + + struct { + ULONG Length; + PSID StartSid; + PFILE_GET_QUOTA_INFORMATION SidList; + ULONG SidListLength; + } QueryQuota; + + struct { + ULONG Length; + } SetEa; + + struct { + ULONG Length; + } SetQuota; + + struct { + ULONG Length; + FS_INFORMATION_CLASS FsInformationClass; + } SetVolume; + + } Parameters; + +} EXTENDED_IO_STACK_LOCATION, *PEXTENDED_IO_STACK_LOCATION; +#if !defined(_ALPHA_) && !defined(_AMD64_) && !defined(_IA64_) +#include +#endif + +typedef struct _FILE_ACCESS_INFORMATION { + ACCESS_MASK AccessFlags; +} FILE_ACCESS_INFORMATION, *PFILE_ACCESS_INFORMATION; + +typedef struct _FILE_ALLOCATION_INFORMATION { + LARGE_INTEGER AllocationSize; +} FILE_ALLOCATION_INFORMATION, *PFILE_ALLOCATION_INFORMATION; + +typedef struct _FILE_BOTH_DIR_INFORMATION { + ULONG NextEntryOffset; + ULONG FileIndex; + LARGE_INTEGER CreationTime; + LARGE_INTEGER LastAccessTime; + LARGE_INTEGER LastWriteTime; + LARGE_INTEGER ChangeTime; + LARGE_INTEGER EndOfFile; + LARGE_INTEGER AllocationSize; + ULONG FileAttributes; + ULONG FileNameLength; + ULONG EaSize; + CCHAR ShortNameLength; + WCHAR ShortName[12]; + WCHAR FileName[1]; +} FILE_BOTH_DIR_INFORMATION, *PFILE_BOTH_DIR_INFORMATION; + +typedef struct _FILE_COMPLETION_INFORMATION { + HANDLE Port; + ULONG Key; +} FILE_COMPLETION_INFORMATION, *PFILE_COMPLETION_INFORMATION; + +typedef struct _FILE_COMPRESSION_INFORMATION { + LARGE_INTEGER CompressedFileSize; + USHORT CompressionFormat; + UCHAR CompressionUnitShift; + UCHAR ChunkShift; + UCHAR ClusterShift; + UCHAR Reserved[3]; +} FILE_COMPRESSION_INFORMATION, *PFILE_COMPRESSION_INFORMATION; + +typedef struct _FILE_COPY_ON_WRITE_INFORMATION { + BOOLEAN ReplaceIfExists; + HANDLE RootDirectory; + ULONG FileNameLength; + WCHAR FileName[1]; +} FILE_COPY_ON_WRITE_INFORMATION, *PFILE_COPY_ON_WRITE_INFORMATION; + +typedef struct _FILE_DIRECTORY_INFORMATION { + ULONG NextEntryOffset; + ULONG FileIndex; + LARGE_INTEGER CreationTime; + LARGE_INTEGER LastAccessTime; + LARGE_INTEGER LastWriteTime; + LARGE_INTEGER ChangeTime; + LARGE_INTEGER EndOfFile; + LARGE_INTEGER AllocationSize; + ULONG FileAttributes; + ULONG FileNameLength; + WCHAR FileName[1]; +} FILE_DIRECTORY_INFORMATION, *PFILE_DIRECTORY_INFORMATION; + +typedef struct _FILE_EA_INFORMATION { + ULONG EaSize; +} FILE_EA_INFORMATION, *PFILE_EA_INFORMATION; + +typedef struct _FILE_FS_ATTRIBUTE_INFORMATION { + ULONG FileSystemAttributes; + ULONG MaximumComponentNameLength; + ULONG FileSystemNameLength; + WCHAR FileSystemName[1]; +} FILE_FS_ATTRIBUTE_INFORMATION, *PFILE_FS_ATTRIBUTE_INFORMATION; + +typedef struct _FILE_FS_CONTROL_INFORMATION { + LARGE_INTEGER FreeSpaceStartFiltering; + LARGE_INTEGER FreeSpaceThreshold; + LARGE_INTEGER FreeSpaceStopFiltering; + LARGE_INTEGER DefaultQuotaThreshold; + LARGE_INTEGER DefaultQuotaLimit; + ULONG FileSystemControlFlags; +} FILE_FS_CONTROL_INFORMATION, *PFILE_FS_CONTROL_INFORMATION; + +typedef struct _FILE_FS_FULL_SIZE_INFORMATION { + LARGE_INTEGER TotalAllocationUnits; + LARGE_INTEGER CallerAvailableAllocationUnits; + LARGE_INTEGER ActualAvailableAllocationUnits; + ULONG SectorsPerAllocationUnit; + ULONG BytesPerSector; +} FILE_FS_FULL_SIZE_INFORMATION, *PFILE_FS_FULL_SIZE_INFORMATION; + +typedef struct _FILE_FS_LABEL_INFORMATION { + ULONG VolumeLabelLength; + WCHAR VolumeLabel[1]; +} FILE_FS_LABEL_INFORMATION, *PFILE_FS_LABEL_INFORMATION; + +#if (VER_PRODUCTBUILD >= 2195) + +typedef struct _FILE_FS_OBJECT_ID_INFORMATION { + UCHAR ObjectId[16]; + UCHAR ExtendedInfo[48]; +} FILE_FS_OBJECT_ID_INFORMATION, *PFILE_FS_OBJECT_ID_INFORMATION; + +#endif // (VER_PRODUCTBUILD >= 2195) + +typedef struct _FILE_FS_SIZE_INFORMATION { + LARGE_INTEGER TotalAllocationUnits; + LARGE_INTEGER AvailableAllocationUnits; + ULONG SectorsPerAllocationUnit; + ULONG BytesPerSector; +} FILE_FS_SIZE_INFORMATION, *PFILE_FS_SIZE_INFORMATION; + +typedef struct _FILE_FS_VOLUME_INFORMATION { + LARGE_INTEGER VolumeCreationTime; + ULONG VolumeSerialNumber; + ULONG VolumeLabelLength; + BOOLEAN SupportsObjects; + WCHAR VolumeLabel[1]; +} FILE_FS_VOLUME_INFORMATION, *PFILE_FS_VOLUME_INFORMATION; + +typedef struct _FILE_FULL_DIR_INFORMATION { + ULONG NextEntryOffset; + ULONG FileIndex; + LARGE_INTEGER CreationTime; + LARGE_INTEGER LastAccessTime; + LARGE_INTEGER LastWriteTime; + LARGE_INTEGER ChangeTime; + LARGE_INTEGER EndOfFile; + LARGE_INTEGER AllocationSize; + ULONG FileAttributes; + ULONG FileNameLength; + ULONG EaSize; + WCHAR FileName[1]; +} FILE_FULL_DIR_INFORMATION, *PFILE_FULL_DIR_INFORMATION; + +typedef struct _FILE_GET_EA_INFORMATION { + ULONG NextEntryOffset; + UCHAR EaNameLength; + CHAR EaName[1]; +} FILE_GET_EA_INFORMATION, *PFILE_GET_EA_INFORMATION; + +typedef struct _FILE_GET_QUOTA_INFORMATION { + ULONG NextEntryOffset; + ULONG SidLength; + SID Sid; +} FILE_GET_QUOTA_INFORMATION, *PFILE_GET_QUOTA_INFORMATION; + +typedef struct _FILE_ID_BOTH_DIR_INFORMATION { + ULONG NextEntryOffset; + ULONG FileIndex; + LARGE_INTEGER CreationTime; + LARGE_INTEGER LastAccessTime; + LARGE_INTEGER LastWriteTime; + LARGE_INTEGER ChangeTime; + LARGE_INTEGER EndOfFile; + LARGE_INTEGER AllocationSize; + ULONG FileAttributes; + ULONG FileNameLength; + ULONG EaSize; + CCHAR ShortNameLength; + WCHAR ShortName[12]; + LARGE_INTEGER FileId; + WCHAR FileName[1]; +} FILE_ID_BOTH_DIR_INFORMATION, *PFILE_ID_BOTH_DIR_INFORMATION; + +typedef struct _FILE_ID_FULL_DIR_INFORMATION { + ULONG NextEntryOffset; + ULONG FileIndex; + LARGE_INTEGER CreationTime; + LARGE_INTEGER LastAccessTime; + LARGE_INTEGER LastWriteTime; + LARGE_INTEGER ChangeTime; + LARGE_INTEGER EndOfFile; + LARGE_INTEGER AllocationSize; + ULONG FileAttributes; + ULONG FileNameLength; + ULONG EaSize; + LARGE_INTEGER FileId; + WCHAR FileName[1]; +} FILE_ID_FULL_DIR_INFORMATION, *PFILE_ID_FULL_DIR_INFORMATION; + +typedef struct _FILE_INTERNAL_INFORMATION { + LARGE_INTEGER IndexNumber; +} FILE_INTERNAL_INFORMATION, *PFILE_INTERNAL_INFORMATION; + +typedef struct _FILE_LINK_INFORMATION { + BOOLEAN ReplaceIfExists; + HANDLE RootDirectory; + ULONG FileNameLength; + WCHAR FileName[1]; +} FILE_LINK_INFORMATION, *PFILE_LINK_INFORMATION; + +typedef struct _FILE_LOCK_INFO { + LARGE_INTEGER StartingByte; + LARGE_INTEGER Length; + BOOLEAN ExclusiveLock; + ULONG Key; + PFILE_OBJECT FileObject; + PEPROCESS Process; + LARGE_INTEGER EndingByte; +} FILE_LOCK_INFO, *PFILE_LOCK_INFO; + +// raw internal file lock struct returned from FsRtlGetNextFileLock +typedef struct _FILE_SHARED_LOCK_ENTRY { + PVOID Unknown1; + PVOID Unknown2; + FILE_LOCK_INFO FileLock; +} FILE_SHARED_LOCK_ENTRY, *PFILE_SHARED_LOCK_ENTRY; + +// raw internal file lock struct returned from FsRtlGetNextFileLock +typedef struct _FILE_EXCLUSIVE_LOCK_ENTRY { + LIST_ENTRY ListEntry; + PVOID Unknown1; + PVOID Unknown2; + FILE_LOCK_INFO FileLock; +} FILE_EXCLUSIVE_LOCK_ENTRY, *PFILE_EXCLUSIVE_LOCK_ENTRY; + +typedef NTSTATUS (*PCOMPLETE_LOCK_IRP_ROUTINE) ( + IN PVOID Context, + IN PIRP Irp +); + +typedef VOID (*PUNLOCK_ROUTINE) ( + IN PVOID Context, + IN PFILE_LOCK_INFO FileLockInfo +); + +typedef struct _FILE_LOCK { + PCOMPLETE_LOCK_IRP_ROUTINE CompleteLockIrpRoutine; + PUNLOCK_ROUTINE UnlockRoutine; + BOOLEAN FastIoIsQuestionable; + BOOLEAN Pad[3]; + PVOID LockInformation; + FILE_LOCK_INFO LastReturnedLockInfo; + PVOID LastReturnedLock; +} FILE_LOCK, *PFILE_LOCK; + +typedef struct _FILE_MAILSLOT_PEEK_BUFFER { + ULONG ReadDataAvailable; + ULONG NumberOfMessages; + ULONG MessageLength; +} FILE_MAILSLOT_PEEK_BUFFER, *PFILE_MAILSLOT_PEEK_BUFFER; + +typedef struct _FILE_MAILSLOT_QUERY_INFORMATION { + ULONG MaximumMessageSize; + ULONG MailslotQuota; + ULONG NextMessageSize; + ULONG MessagesAvailable; + LARGE_INTEGER ReadTimeout; +} FILE_MAILSLOT_QUERY_INFORMATION, *PFILE_MAILSLOT_QUERY_INFORMATION; + +typedef struct _FILE_MAILSLOT_SET_INFORMATION { + PLARGE_INTEGER ReadTimeout; +} FILE_MAILSLOT_SET_INFORMATION, *PFILE_MAILSLOT_SET_INFORMATION; + +typedef struct _FILE_MODE_INFORMATION { + ULONG Mode; +} FILE_MODE_INFORMATION, *PFILE_MODE_INFORMATION; + +// This structure is included in the Windows 2000 DDK but is missing in the +// Windows NT 4.0 DDK +#if (VER_PRODUCTBUILD < 2195) +typedef struct _FILE_NAME_INFORMATION { + ULONG FileNameLength; + WCHAR FileName[1]; +} FILE_NAME_INFORMATION, *PFILE_NAME_INFORMATION; +#endif // (VER_PRODUCTBUILD < 2195) + +typedef struct _FILE_ALL_INFORMATION { + FILE_BASIC_INFORMATION BasicInformation; + FILE_STANDARD_INFORMATION StandardInformation; + FILE_INTERNAL_INFORMATION InternalInformation; + FILE_EA_INFORMATION EaInformation; + FILE_ACCESS_INFORMATION AccessInformation; + FILE_POSITION_INFORMATION PositionInformation; + FILE_MODE_INFORMATION ModeInformation; + FILE_ALIGNMENT_INFORMATION AlignmentInformation; + FILE_NAME_INFORMATION NameInformation; +} FILE_ALL_INFORMATION, *PFILE_ALL_INFORMATION; + +typedef struct _FILE_NAMES_INFORMATION { + ULONG NextEntryOffset; + ULONG FileIndex; + ULONG FileNameLength; + WCHAR FileName[1]; +} FILE_NAMES_INFORMATION, *PFILE_NAMES_INFORMATION; + +typedef struct _FILE_NOTIFY_INFORMATION { + ULONG NextEntryOffset; + ULONG Action; + ULONG FileNameLength; + WCHAR FileName[1]; +} FILE_NOTIFY_INFORMATION, *PFILE_NOTIFY_INFORMATION; + +typedef struct _FILE_OBJECTID_INFORMATION { + LONGLONG FileReference; + UCHAR ObjectId[16]; + union { + struct { + UCHAR BirthVolumeId[16]; + UCHAR BirthObjectId[16]; + UCHAR DomainId[16]; + } ; + UCHAR ExtendedInfo[48]; + }; +} FILE_OBJECTID_INFORMATION, *PFILE_OBJECTID_INFORMATION; + +typedef struct _FILE_OLE_CLASSID_INFORMATION { + GUID ClassId; +} FILE_OLE_CLASSID_INFORMATION, *PFILE_OLE_CLASSID_INFORMATION; + +typedef struct _FILE_OLE_ALL_INFORMATION { + FILE_BASIC_INFORMATION BasicInformation; + FILE_STANDARD_INFORMATION StandardInformation; + FILE_INTERNAL_INFORMATION InternalInformation; + FILE_EA_INFORMATION EaInformation; + FILE_ACCESS_INFORMATION AccessInformation; + FILE_POSITION_INFORMATION PositionInformation; + FILE_MODE_INFORMATION ModeInformation; + FILE_ALIGNMENT_INFORMATION AlignmentInformation; + USN LastChangeUsn; + USN ReplicationUsn; + LARGE_INTEGER SecurityChangeTime; + FILE_OLE_CLASSID_INFORMATION OleClassIdInformation; + FILE_OBJECTID_INFORMATION ObjectIdInformation; + FILE_STORAGE_TYPE StorageType; + ULONG OleStateBits; + ULONG OleId; + ULONG NumberOfStreamReferences; + ULONG StreamIndex; + ULONG SecurityId; + BOOLEAN ContentIndexDisable; + BOOLEAN InheritContentIndexDisable; + FILE_NAME_INFORMATION NameInformation; +} FILE_OLE_ALL_INFORMATION, *PFILE_OLE_ALL_INFORMATION; + +typedef struct _FILE_OLE_DIR_INFORMATION { + ULONG NextEntryOffset; + ULONG FileIndex; + LARGE_INTEGER CreationTime; + LARGE_INTEGER LastAccessTime; + LARGE_INTEGER LastWriteTime; + LARGE_INTEGER ChangeTime; + LARGE_INTEGER EndOfFile; + LARGE_INTEGER AllocationSize; + ULONG FileAttributes; + ULONG FileNameLength; + FILE_STORAGE_TYPE StorageType; + GUID OleClassId; + ULONG OleStateBits; + BOOLEAN ContentIndexDisable; + BOOLEAN InheritContentIndexDisable; + WCHAR FileName[1]; +} FILE_OLE_DIR_INFORMATION, *PFILE_OLE_DIR_INFORMATION; + +typedef struct _FILE_OLE_INFORMATION { + LARGE_INTEGER SecurityChangeTime; + FILE_OLE_CLASSID_INFORMATION OleClassIdInformation; + FILE_OBJECTID_INFORMATION ObjectIdInformation; + FILE_STORAGE_TYPE StorageType; + ULONG OleStateBits; + BOOLEAN ContentIndexDisable; + BOOLEAN InheritContentIndexDisable; +} FILE_OLE_INFORMATION, *PFILE_OLE_INFORMATION; + +typedef struct _FILE_OLE_STATE_BITS_INFORMATION { + ULONG StateBits; + ULONG StateBitsMask; +} FILE_OLE_STATE_BITS_INFORMATION, *PFILE_OLE_STATE_BITS_INFORMATION; + +typedef struct _FILE_PIPE_ASSIGN_EVENT_BUFFER { + HANDLE EventHandle; + ULONG KeyValue; +} FILE_PIPE_ASSIGN_EVENT_BUFFER, *PFILE_PIPE_ASSIGN_EVENT_BUFFER; + +typedef struct _FILE_PIPE_CLIENT_PROCESS_BUFFER { + PVOID ClientSession; + PVOID ClientProcess; +} FILE_PIPE_CLIENT_PROCESS_BUFFER, *PFILE_PIPE_CLIENT_PROCESS_BUFFER; + +typedef struct _FILE_PIPE_EVENT_BUFFER { + ULONG NamedPipeState; + ULONG EntryType; + ULONG ByteCount; + ULONG KeyValue; + ULONG NumberRequests; +} FILE_PIPE_EVENT_BUFFER, *PFILE_PIPE_EVENT_BUFFER; + +typedef struct _FILE_PIPE_INFORMATION { + ULONG ReadMode; + ULONG CompletionMode; +} FILE_PIPE_INFORMATION, *PFILE_PIPE_INFORMATION; + +typedef struct _FILE_PIPE_LOCAL_INFORMATION { + ULONG NamedPipeType; + ULONG NamedPipeConfiguration; + ULONG MaximumInstances; + ULONG CurrentInstances; + ULONG InboundQuota; + ULONG ReadDataAvailable; + ULONG OutboundQuota; + ULONG WriteQuotaAvailable; + ULONG NamedPipeState; + ULONG NamedPipeEnd; +} FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION; + +typedef struct _FILE_PIPE_PEEK_BUFFER { + ULONG NamedPipeState; + ULONG ReadDataAvailable; + ULONG NumberOfMessages; + ULONG MessageLength; + CHAR Data[1]; +} FILE_PIPE_PEEK_BUFFER, *PFILE_PIPE_PEEK_BUFFER; + +typedef struct _FILE_PIPE_REMOTE_INFORMATION { + LARGE_INTEGER CollectDataTime; + ULONG MaximumCollectionCount; +} FILE_PIPE_REMOTE_INFORMATION, *PFILE_PIPE_REMOTE_INFORMATION; + +typedef struct _FILE_PIPE_WAIT_FOR_BUFFER { + LARGE_INTEGER Timeout; + ULONG NameLength; + BOOLEAN TimeoutSpecified; + WCHAR Name[1]; +} FILE_PIPE_WAIT_FOR_BUFFER, *PFILE_PIPE_WAIT_FOR_BUFFER; + +typedef struct _FILE_QUOTA_INFORMATION { + ULONG NextEntryOffset; + ULONG SidLength; + LARGE_INTEGER ChangeTime; + LARGE_INTEGER QuotaUsed; + LARGE_INTEGER QuotaThreshold; + LARGE_INTEGER QuotaLimit; + SID Sid; +} FILE_QUOTA_INFORMATION, *PFILE_QUOTA_INFORMATION; + +typedef struct _FILE_RENAME_INFORMATION { + BOOLEAN ReplaceIfExists; + HANDLE RootDirectory; + ULONG FileNameLength; + WCHAR FileName[1]; +} FILE_RENAME_INFORMATION, *PFILE_RENAME_INFORMATION; + +typedef struct _FILE_STREAM_INFORMATION { + ULONG NextEntryOffset; + ULONG StreamNameLength; + LARGE_INTEGER StreamSize; + LARGE_INTEGER StreamAllocationSize; + WCHAR StreamName[1]; +} FILE_STREAM_INFORMATION, *PFILE_STREAM_INFORMATION; + +typedef struct _FILE_TRACKING_INFORMATION { + HANDLE DestinationFile; + ULONG ObjectInformationLength; + CHAR ObjectInformation[1]; +} FILE_TRACKING_INFORMATION, *PFILE_TRACKING_INFORMATION; + +typedef struct _FSRTL_COMMON_FCB_HEADER { + CSHORT NodeTypeCode; + CSHORT NodeByteSize; + UCHAR Flags; + UCHAR IsFastIoPossible; +#if (VER_PRODUCTBUILD >= 1381) + UCHAR Flags2; + UCHAR Reserved : 4; + UCHAR Version : 4; +#endif // (VER_PRODUCTBUILD >= 1381) + PERESOURCE Resource; + PERESOURCE PagingIoResource; + LARGE_INTEGER AllocationSize; + LARGE_INTEGER FileSize; + LARGE_INTEGER ValidDataLength; +} FSRTL_COMMON_FCB_HEADER, *PFSRTL_COMMON_FCB_HEADER; + +#if (VER_PRODUCTBUILD >= 2600) + +#ifdef __cplusplus +typedef struct _FSRTL_ADVANCED_FCB_HEADER:FSRTL_COMMON_FCB_HEADER { +#else // __cplusplus +typedef struct _FSRTL_ADVANCED_FCB_HEADER { + FSRTL_COMMON_FCB_HEADER; +#endif // __cplusplus + PFAST_MUTEX FastMutex; + LIST_ENTRY FilterContexts; + EX_PUSH_LOCK PushLock; + PVOID *FileContextSupportPointer; +} FSRTL_ADVANCED_FCB_HEADER, *PFSRTL_ADVANCED_FCB_HEADER; + +#endif // (VER_PRODUCTBUILD >= 2600) + +typedef struct _GENERATE_NAME_CONTEXT { + USHORT Checksum; + BOOLEAN CheckSumInserted; + UCHAR NameLength; + WCHAR NameBuffer[8]; + ULONG ExtensionLength; + WCHAR ExtensionBuffer[4]; + ULONG LastIndexValue; +} GENERATE_NAME_CONTEXT, *PGENERATE_NAME_CONTEXT; + +typedef struct _HANDLE_INFO { // Information about open handles + union { + PEPROCESS Process; // Pointer to PEPROCESS owning the Handle + ULONG Count; // Count of HANDLE_INFO structures following this structure + } HandleInfo; + USHORT HandleCount; +} HANDLE_INFO, *PHANDLE_INFO; + +typedef struct _HANDLE_TABLE_ENTRY_INFO { + ULONG AuditMask; +} HANDLE_TABLE_ENTRY_INFO, *PHANDLE_TABLE_ENTRY_INFO; + +typedef struct _HANDLE_TABLE_ENTRY { + union { + PVOID Object; + ULONG ObAttributes; + PHANDLE_TABLE_ENTRY_INFO InfoTable; + ULONG Value; + }; + union { + ULONG GrantedAccess; + USHORT GrantedAccessIndex; + LONG NextFreeTableEntry; + }; + USHORT CreatorBackTraceIndex; +} HANDLE_TABLE_ENTRY, *PHANDLE_TABLE_ENTRY; + +typedef struct _MAPPING_PAIR { + ULONGLONG Vcn; + ULONGLONG Lcn; +} MAPPING_PAIR, *PMAPPING_PAIR; + +typedef struct _GET_RETRIEVAL_DESCRIPTOR { + ULONG NumberOfPairs; + ULONGLONG StartVcn; + MAPPING_PAIR Pair[1]; +} GET_RETRIEVAL_DESCRIPTOR, *PGET_RETRIEVAL_DESCRIPTOR; + +typedef struct _INITIAL_TEB { + ULONG Unknown_1; + ULONG Unknown_2; + PVOID StackTop; + PVOID StackBase; + PVOID Unknown_3; +} INITIAL_TEB, *PINITIAL_TEB; + +typedef struct _IO_CLIENT_EXTENSION { + struct _IO_CLIENT_EXTENSION *NextExtension; + PVOID ClientIdentificationAddress; +} IO_CLIENT_EXTENSION, *PIO_CLIENT_EXTENSION; + +typedef struct _IO_COMPLETION_BASIC_INFORMATION { + LONG Depth; +} IO_COMPLETION_BASIC_INFORMATION, *PIO_COMPLETION_BASIC_INFORMATION; + +typedef struct _KEVENT_PAIR { + USHORT Type; + USHORT Size; + KEVENT Event1; + KEVENT Event2; +} KEVENT_PAIR, *PKEVENT_PAIR; + +typedef struct _KINTERRUPT { + CSHORT Type; + CSHORT Size; + LIST_ENTRY InterruptListEntry; + PKSERVICE_ROUTINE ServiceRoutine; + PVOID ServiceContext; + KSPIN_LOCK SpinLock; + ULONG TickCount; + PKSPIN_LOCK ActualLock; + PVOID DispatchAddress; + ULONG Vector; + KIRQL Irql; + KIRQL SynchronizeIrql; + BOOLEAN FloatingSave; + BOOLEAN Connected; + CHAR Number; + UCHAR ShareVector; + KINTERRUPT_MODE Mode; + ULONG ServiceCount; + ULONG DispatchCount; + ULONG DispatchCode[106]; +} KINTERRUPT, *PKINTERRUPT; + +typedef struct _KQUEUE { + DISPATCHER_HEADER Header; + LIST_ENTRY EntryListHead; + ULONG CurrentCount; + ULONG MaximumCount; + LIST_ENTRY ThreadListHead; +} KQUEUE, *PKQUEUE, *RESTRICTED_POINTER PRKQUEUE; + +typedef struct _LARGE_MCB { + PFAST_MUTEX FastMutex; + ULONG MaximumPairCount; + ULONG PairCount; + POOL_TYPE PoolType; + PVOID Mapping; +} LARGE_MCB, *PLARGE_MCB; + +typedef struct _LPC_MESSAGE { + USHORT DataSize; + USHORT MessageSize; + USHORT MessageType; + USHORT VirtualRangesOffset; + CLIENT_ID ClientId; + ULONG MessageId; + ULONG SectionSize; + UCHAR Data[1]; +} LPC_MESSAGE, *PLPC_MESSAGE; + +typedef struct _LPC_SECTION_READ { + ULONG Length; + ULONG ViewSize; + PVOID ViewBase; +} LPC_SECTION_READ, *PLPC_SECTION_READ; + +typedef struct _LPC_SECTION_WRITE { + ULONG Length; + HANDLE SectionHandle; + ULONG SectionOffset; + ULONG ViewSize; + PVOID ViewBase; + PVOID TargetViewBase; +} LPC_SECTION_WRITE, *PLPC_SECTION_WRITE; + +typedef struct _MAILSLOT_CREATE_PARAMETERS { + ULONG MailslotQuota; + ULONG MaximumMessageSize; + LARGE_INTEGER ReadTimeout; + BOOLEAN TimeoutSpecified; +} MAILSLOT_CREATE_PARAMETERS, *PMAILSLOT_CREATE_PARAMETERS; + +typedef struct _MBCB { + CSHORT NodeTypeCode; + CSHORT NodeIsInZone; + ULONG PagesToWrite; + ULONG DirtyPages; + ULONG Reserved; + LIST_ENTRY BitmapRanges; + LONGLONG ResumeWritePage; + BITMAP_RANGE BitmapRange1; + BITMAP_RANGE BitmapRange2; + BITMAP_RANGE BitmapRange3; +} MBCB, *PMBCB; + +typedef struct _MCB { + LARGE_MCB LargeMcb; +} MCB, *PMCB; + +typedef struct _MOVEFILE_DESCRIPTOR { + HANDLE FileHandle; + ULONG Reserved; + LARGE_INTEGER StartVcn; + LARGE_INTEGER TargetLcn; + ULONG NumVcns; + ULONG Reserved1; +} MOVEFILE_DESCRIPTOR, *PMOVEFILE_DESCRIPTOR; + +typedef struct _NAMED_PIPE_CREATE_PARAMETERS { + ULONG NamedPipeType; + ULONG ReadMode; + ULONG CompletionMode; + ULONG MaximumInstances; + ULONG InboundQuota; + ULONG OutboundQuota; + LARGE_INTEGER DefaultTimeout; + BOOLEAN TimeoutSpecified; +} NAMED_PIPE_CREATE_PARAMETERS, *PNAMED_PIPE_CREATE_PARAMETERS; + +typedef struct _QUOTA_BLOCK { + KSPIN_LOCK QuotaLock; + ULONG ReferenceCount; // Number of processes using this block + ULONG PeakNonPagedPoolUsage; + ULONG PeakPagedPoolUsage; + ULONG NonPagedpoolUsage; + ULONG PagedPoolUsage; + ULONG NonPagedPoolLimit; + ULONG PagedPoolLimit; + ULONG PeakPagefileUsage; + ULONG PagefileUsage; + ULONG PageFileLimit; +} QUOTA_BLOCK, *PQUOTA_BLOCK; + +typedef struct _OBJECT_BASIC_INFO { + ULONG Attributes; + ACCESS_MASK GrantedAccess; + ULONG HandleCount; + ULONG ReferenceCount; + ULONG PagedPoolUsage; + ULONG NonPagedPoolUsage; + ULONG Reserved[3]; + ULONG NameInformationLength; + ULONG TypeInformationLength; + ULONG SecurityDescriptorLength; + LARGE_INTEGER CreateTime; +} OBJECT_BASIC_INFO, *POBJECT_BASIC_INFO; + +typedef struct _OBJECT_CREATE_INFORMATION { + ULONG Attributes; + HANDLE RootDirectory; // 0x4 + PVOID ParseContext; // 0x8 + KPROCESSOR_MODE ProbeMode; // 0xc + ULONG PagedPoolCharge; // 0x10 + ULONG NonPagedPoolCharge; // 0x14 + ULONG SecurityDescriptorCharge; // 0x18 + PSECURITY_DESCRIPTOR SecurityDescriptor; // 0x1c + PSECURITY_QUALITY_OF_SERVICE SecurityQos; // 0x20 + SECURITY_QUALITY_OF_SERVICE SecurityQualityOfService; // 0x24 +} OBJECT_CREATE_INFORMATION, *POBJECT_CREATE_INFORMATION; + +typedef struct _OBJECT_CREATOR_INFO { + LIST_ENTRY Creator; + ULONG UniqueProcessId; // Creator's Process ID + ULONG Reserved; // Alignment +} OBJECT_CREATOR_INFO, *POBJECT_CREATOR_INFO; + +typedef struct _OBJECT_DIRECTORY_ITEM { + struct _OBJECT_DIRECTORY_ITEM *Next; + PVOID Object; +} OBJECT_DIRECTORY_ITEM, *POBJECT_DIRECTORY_ITEM; + +typedef struct _OBJECT_DIRECTORY { + POBJECT_DIRECTORY_ITEM HashEntries[0x25]; + POBJECT_DIRECTORY_ITEM LastHashAccess; + ULONG LastHashResult; +} OBJECT_DIRECTORY, *POBJECT_DIRECTORY; + +typedef struct _OBJECT_HANDLE_ATTRIBUTE_INFO { + BOOLEAN Inherit; + BOOLEAN ProtectFromClose; +} OBJECT_HANDLE_ATTRIBUTE_INFO, *POBJECT_HANDLE_ATTRIBUTE_INFO; + +typedef struct _OBJECT_HANDLE_DB { + union { + struct _EPROCESS *Process; + struct _OBJECT_HANDLE_DB_LIST *HandleDBList; + }; + ULONG HandleCount; +} OBJECT_HANDLE_DB, *POBJECT_HANDLE_DB; + +typedef struct _OBJECT_HANDLE_DB_LIST { + ULONG Count; + OBJECT_HANDLE_DB Entries[1]; +} OBJECT_HANDLE_DB_LIST, *POBJECT_HANDLE_DB_LIST; + +typedef struct _OBJECT_HEADER_FLAGS { + ULONG NameInfoOffset : 8; + ULONG HandleInfoOffset : 8; + ULONG QuotaInfoOffset : 8; + ULONG QuotaBlock : 1; // QuotaBlock/ObjectInfo + ULONG KernelMode : 1; // UserMode/KernelMode + ULONG CreatorInfo : 1; + ULONG Exclusive : 1; + ULONG Permanent : 1; + ULONG SecurityDescriptor : 1; + ULONG HandleInfo : 1; + ULONG Reserved : 1; +} OBJECT_HEADER_FLAGS, *POBJECT_HEADER_FLAGS; + +typedef struct _OBJECT_HEADER { + ULONG ReferenceCount; + union { + ULONG HandleCount; + PSINGLE_LIST_ENTRY NextToFree; + }; // 0x4 + POBJECT_TYPE ObjectType; // 0x8 + OBJECT_HEADER_FLAGS Flags; // 0xc + union { + POBJECT_CREATE_INFORMATION ObjectCreateInfo; + PQUOTA_BLOCK QuotaBlock; + }; // 0x10 + PSECURITY_DESCRIPTOR SecurityDescriptor; // 0x14 + QUAD Body; // 0x18 +} OBJECT_HEADER, *POBJECT_HEADER; + +typedef struct _OBJECT_NAME { + POBJECT_DIRECTORY Directory; + UNICODE_STRING ObjectName; + ULONG Reserved; +} OBJECT_NAME, *POBJECT_NAME; + +typedef struct _OBJECT_NAME_INFO { + UNICODE_STRING ObjectName; + WCHAR ObjectNameBuffer[1]; +} OBJECT_NAME_INFO, *POBJECT_NAME_INFO; + +typedef struct _OBJECT_PROTECTION_INFO { + BOOLEAN Inherit; + BOOLEAN ProtectHandle; +} OBJECT_PROTECTION_INFO, *POBJECT_PROTECTION_INFO; + +typedef struct _OBJECT_QUOTA_CHARGES { + ULONG PagedPoolCharge; + ULONG NonPagedPoolCharge; + ULONG SecurityCharge; + ULONG Reserved; +} OBJECT_QUOTA_CHARGES, *POBJECT_QUOTA_CHARGES; + +typedef struct _OBJECT_QUOTA_INFO { + ULONG PagedPoolQuota; + ULONG NonPagedPoolQuota; + ULONG QuotaInformationSize; + PEPROCESS Process; // Owning process +} OBJECT_QUOTA_INFO, *POBJECT_QUOTA_INFO; + +typedef struct _OBJECT_TYPE_INITIALIZER { + USHORT Length; + BOOLEAN UseDefaultObject; + BOOLEAN Reserved1; + ULONG InvalidAttributes; + GENERIC_MAPPING GenericMapping; + ACCESS_MASK ValidAccessMask; + BOOLEAN SecurityRequired; + BOOLEAN MaintainHandleCount; /* OBJECT_HANDLE_DB */ + BOOLEAN MaintainTypeList; /* OBJECT_CREATOR_INFO */ + UCHAR Reserved2; + BOOLEAN PagedPool; + ULONG DefaultPagedPoolCharge; + ULONG DefaultNonPagedPoolCharge; + PVOID DumpProcedure; + PVOID OpenProcedure; + PVOID CloseProcedure; + PVOID DeleteProcedure; + PVOID ParseProcedure; + PVOID SecurityProcedure; /* SeDefaultObjectMethod */ + PVOID QueryNameProcedure; + PVOID OkayToCloseProcedure; +} OBJECT_TYPE_INITIALIZER, *POBJECT_TYPE_INITIALIZER; + +typedef struct _OBJECT_TYPE { + ERESOURCE Lock; + LIST_ENTRY ObjectListHead; /* OBJECT_CREATOR_INFO */ + UNICODE_STRING ObjectTypeName; + union { + PVOID DefaultObject; /* ObpDefaultObject */ + ULONG Code; /* File: 5C, WaitablePort: A0 */ + }; + ULONG ObjectTypeIndex; /* OB_TYPE_INDEX_* */ + ULONG ObjectCount; + ULONG HandleCount; + ULONG PeakObjectCount; + ULONG PeakHandleCount; + OBJECT_TYPE_INITIALIZER TypeInfo; + ULONG ObjectTypeTag; /* OB_TYPE_TAG_* */ +} OBJECT_TYPE, *POBJECT_TYPE; + +typedef struct _OBJECT_TYPE_INFO { + UNICODE_STRING ObjectTypeName; + UCHAR Unknown[0x58]; + WCHAR ObjectTypeNameBuffer[1]; +} OBJECT_TYPE_INFO, *POBJECT_TYPE_INFO; + +typedef struct _OBJECT_ALL_TYPES_INFO { + ULONG NumberOfObjectTypes; + OBJECT_TYPE_INFO ObjectsTypeInfo[1]; +} OBJECT_ALL_TYPES_INFO, *POBJECT_ALL_TYPES_INFO; + +typedef struct _PAGEFAULT_HISTORY { + ULONG CurrentIndex; + ULONG MaxIndex; + KSPIN_LOCK SpinLock; + PVOID Reserved; + PROCESS_WS_WATCH_INFORMATION WatchInfo[1]; +} PAGEFAULT_HISTORY, *PPAGEFAULT_HISTORY; + +typedef struct _PATHNAME_BUFFER { + ULONG PathNameLength; + WCHAR Name[1]; +} PATHNAME_BUFFER, *PPATHNAME_BUFFER; + +#if (VER_PRODUCTBUILD >= 2600) + +typedef struct _PRIVATE_CACHE_MAP_FLAGS { + ULONG DontUse : 16; + ULONG ReadAheadActive : 1; + ULONG ReadAheadEnabled : 1; + ULONG Available : 14; +} PRIVATE_CACHE_MAP_FLAGS, *PPRIVATE_CACHE_MAP_FLAGS; + +typedef struct _PRIVATE_CACHE_MAP { + union { + CSHORT NodeTypeCode; + PRIVATE_CACHE_MAP_FLAGS Flags; + ULONG UlongFlags; + }; + ULONG ReadAheadMask; + PFILE_OBJECT FileObject; + LARGE_INTEGER FileOffset1; + LARGE_INTEGER BeyondLastByte1; + LARGE_INTEGER FileOffset2; + LARGE_INTEGER BeyondLastByte2; + LARGE_INTEGER ReadAheadOffset[2]; + ULONG ReadAheadLength[2]; + KSPIN_LOCK ReadAheadSpinLock; + LIST_ENTRY PrivateLinks; +} PRIVATE_CACHE_MAP, *PPRIVATE_CACHE_MAP; + +#endif + +typedef struct _PROCESS_PRIORITY_CLASS { + BOOLEAN Foreground; + UCHAR PriorityClass; +} PROCESS_PRIORITY_CLASS, *PPROCESS_PRIORITY_CLASS; + +typedef struct _PS_IMPERSONATION_INFORMATION { + PACCESS_TOKEN Token; + BOOLEAN CopyOnOpen; + BOOLEAN EffectiveOnly; + SECURITY_IMPERSONATION_LEVEL ImpersonationLevel; +} PS_IMPERSONATION_INFORMATION, *PPS_IMPERSONATION_INFORMATION; + +typedef struct _PUBLIC_BCB { + CSHORT NodeTypeCode; + CSHORT NodeByteSize; + ULONG MappedLength; + LARGE_INTEGER MappedFileOffset; +} PUBLIC_BCB, *PPUBLIC_BCB; + +typedef struct _QUERY_PATH_REQUEST { + ULONG PathNameLength; + PIO_SECURITY_CONTEXT SecurityContext; + WCHAR FilePathName[1]; +} QUERY_PATH_REQUEST, *PQUERY_PATH_REQUEST; + +typedef struct _QUERY_PATH_RESPONSE { + ULONG LengthAccepted; +} QUERY_PATH_RESPONSE, *PQUERY_PATH_RESPONSE; + +#if (VER_PRODUCTBUILD >= 2600) + +typedef struct _READ_LIST { + PFILE_OBJECT FileObject; + ULONG NumberOfEntries; + LOGICAL IsImage; + FILE_SEGMENT_ELEMENT List[ANYSIZE_ARRAY]; +} READ_LIST, *PREAD_LIST; + +#endif // (VER_PRODUCTBUILD >= 2600) + +typedef struct _REPARSE_DATA_BUFFER { + + ULONG ReparseTag; + USHORT ReparseDataLength; + USHORT Reserved; + + union { + + struct { + USHORT SubstituteNameOffset; + USHORT SubstituteNameLength; + USHORT PrintNameOffset; + USHORT PrintNameLength; + 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; + +typedef struct _RETRIEVAL_POINTERS_BUFFER { + ULONG ExtentCount; + LARGE_INTEGER StartingVcn; + struct { + LARGE_INTEGER NextVcn; + LARGE_INTEGER Lcn; + } Extents[1]; +} RETRIEVAL_POINTERS_BUFFER, *PRETRIEVAL_POINTERS_BUFFER; + +typedef struct _RTL_SPLAY_LINKS { + struct _RTL_SPLAY_LINKS *Parent; + struct _RTL_SPLAY_LINKS *LeftChild; + struct _RTL_SPLAY_LINKS *RightChild; +} RTL_SPLAY_LINKS, *PRTL_SPLAY_LINKS; + +typedef struct _SE_EXPORTS { + + LUID SeCreateTokenPrivilege; + LUID SeAssignPrimaryTokenPrivilege; + LUID SeLockMemoryPrivilege; + LUID SeIncreaseQuotaPrivilege; + LUID SeUnsolicitedInputPrivilege; + LUID SeTcbPrivilege; + LUID SeSecurityPrivilege; + LUID SeTakeOwnershipPrivilege; + LUID SeLoadDriverPrivilege; + LUID SeCreatePagefilePrivilege; + LUID SeIncreaseBasePriorityPrivilege; + LUID SeSystemProfilePrivilege; + LUID SeSystemtimePrivilege; + LUID SeProfileSingleProcessPrivilege; + LUID SeCreatePermanentPrivilege; + LUID SeBackupPrivilege; + LUID SeRestorePrivilege; + LUID SeShutdownPrivilege; + LUID SeDebugPrivilege; + LUID SeAuditPrivilege; + LUID SeSystemEnvironmentPrivilege; + LUID SeChangeNotifyPrivilege; + LUID SeRemoteShutdownPrivilege; + + PSID SeNullSid; + PSID SeWorldSid; + PSID SeLocalSid; + PSID SeCreatorOwnerSid; + PSID SeCreatorGroupSid; + + PSID SeNtAuthoritySid; + PSID SeDialupSid; + PSID SeNetworkSid; + PSID SeBatchSid; + PSID SeInteractiveSid; + PSID SeLocalSystemSid; + PSID SeAliasAdminsSid; + PSID SeAliasUsersSid; + PSID SeAliasGuestsSid; + PSID SeAliasPowerUsersSid; + PSID SeAliasAccountOpsSid; + PSID SeAliasSystemOpsSid; + PSID SeAliasPrintOpsSid; + PSID SeAliasBackupOpsSid; + + PSID SeAuthenticatedUsersSid; + + PSID SeRestrictedSid; + PSID SeAnonymousLogonSid; + + LUID SeUndockPrivilege; + LUID SeSyncAgentPrivilege; + LUID SeEnableDelegationPrivilege; + +} SE_EXPORTS, *PSE_EXPORTS; + +typedef struct _SECTION_BASIC_INFORMATION { + PVOID BaseAddress; + ULONG Attributes; + LARGE_INTEGER Size; +} SECTION_BASIC_INFORMATION, *PSECTION_BASIC_INFORMATION; + +typedef struct _SECTION_IMAGE_INFORMATION { + PVOID EntryPoint; + ULONG Unknown1; + ULONG StackReserve; + ULONG StackCommit; + ULONG Subsystem; + USHORT MinorSubsystemVersion; + USHORT MajorSubsystemVersion; + ULONG Unknown2; + ULONG Characteristics; + USHORT ImageNumber; + BOOLEAN Executable; + UCHAR Unknown3; + ULONG Unknown4[3]; +} SECTION_IMAGE_INFORMATION, *PSECTION_IMAGE_INFORMATION; + +typedef struct _SECTION_OBJECT { + PVOID StartingVa; + PVOID EndingVa; + struct _SECTION_OBJECT *Parent; + struct _SECTION_OBJECT *LeftChild; + struct _SECTION_OBJECT *RightChild; + PVOID Segment; +} SECTION_OBJECT, *PSECTION_OBJECT; + +typedef struct _SEP_AUDIT_POLICY { + // _SEP_AUDIT_POLICY_CATEGORIES + ULONGLONG System : 4; + ULONGLONG Logon : 4; + ULONGLONG ObjectAccess : 4; + ULONGLONG PrivilegeUse : 4; + ULONGLONG DetailedTracking : 4; + ULONGLONG PolicyChange : 4; + ULONGLONG AccountManagement : 4; + ULONGLONG DirectoryServiceAccess : 4; + ULONGLONG AccountLogon : 4; + // _SEP_AUDIT_POLICY_OVERLAY + ULONGLONG SetBit : 1; +} SEP_AUDIT_POLICY, *PSEP_AUDIT_POLICY; + +/* size 0x1C */ +typedef struct _SEP_AUDIT_POLICY_VISTA { + UCHAR PerUserPolicy[25]; /* +0x000 */ + UCHAR PolicySetStatus; /* +0x019 */ + USHORT Alignment; /* +0x01A */ +} SEP_AUDIT_POLICY_VISTA, *PSEP_AUDIT_POLICY_VISTA; + +typedef struct _SERVICE_DESCRIPTOR_TABLE { + /* + * Table containing cServices elements of pointers to service handler + * functions, indexed by service ID. + */ + PVOID *ServiceTable; + /* + * Table that counts how many times each service is used. This table + * is only updated in checked builds. + */ + PULONG CounterTable; + /* + * Number of services contained in this table. + */ + ULONG TableSize; + /* + * Table containing the number of bytes of parameters the handler + * function takes. + */ + PUCHAR ArgumentTable; +} SERVICE_DESCRIPTOR_TABLE, *PSERVICE_DESCRIPTOR_TABLE; + +#if (VER_PRODUCTBUILD >= 2600) + +typedef struct _SHARED_CACHE_MAP { + CSHORT NodeTypeCode; + CSHORT NodeByteSize; + ULONG OpenCount; + LARGE_INTEGER FileSize; + LIST_ENTRY BcbList; + LARGE_INTEGER SectionSize; + LARGE_INTEGER ValidDataLength; + LARGE_INTEGER ValidDataGoal; + PVACB InitialVacbs[4]; + PVACB *Vacbs; + PFILE_OBJECT FileObject; + PVACB ActiveVacb; + PVOID NeedToZero; + ULONG ActivePage; + ULONG NeedToZeroPage; + KSPIN_LOCK ActiveVacbSpinLock; + ULONG VacbActiveCount; + ULONG DirtyPages; + LIST_ENTRY SharedCacheMapLinks; + ULONG Flags; + NTSTATUS Status; + PMBCB Mbcb; + PVOID Section; + PKEVENT CreateEvent; + PKEVENT WaitOnActiveCount; + ULONG PagesToWrite; + LONGLONG BeyondLastFlush; + PCACHE_MANAGER_CALLBACKS Callbacks; + PVOID LazyWriteContext; + LIST_ENTRY PrivateList; + PVOID LogHandle; + PVOID FlushToLsnRoutine; + ULONG DirtyPageThreshold; + ULONG LazyWritePassCount; + PCACHE_UNINITIALIZE_EVENT UninitializeEvent; + PVACB NeedToZeroVacb; + KSPIN_LOCK BcbSpinLock; + PVOID Reserved; + KEVENT Event; + EX_PUSH_LOCK VacbPushLock; + PRIVATE_CACHE_MAP PrivateCacheMap; +} SHARED_CACHE_MAP, *PSHARED_CACHE_MAP; + +#endif + +typedef struct _SID_AND_ATTRIBUTES { + PSID Sid; + ULONG Attributes; +} SID_AND_ATTRIBUTES, *PSID_AND_ATTRIBUTES; + +typedef struct _SID_AND_ATTRIBUTES_HASH { + ULONG SidCount; /* +0x000 */ + PSID_AND_ATTRIBUTES SidAttr; /* +0x004 */ + ULONG Hash[32]; /* +0x008 */ +} SID_AND_ATTRIBUTES_HASH, *PSID_AND_ATTRIBUTES_HASH; + +typedef struct _STARTING_VCN_INPUT_BUFFER { + LARGE_INTEGER StartingVcn; +} STARTING_VCN_INPUT_BUFFER, *PSTARTING_VCN_INPUT_BUFFER; + +// SystemBasicInformation +typedef struct _SYSTEM_BASIC_INFORMATION { + ULONG Unknown; + ULONG MaximumIncrement; + ULONG PhysicalPageSize; + ULONG NumberOfPhysicalPages; + ULONG LowestPhysicalPage; + ULONG HighestPhysicalPage; + ULONG AllocationGranularity; + ULONG LowestUserAddress; + ULONG HighestUserAddress; + ULONG ActiveProcessors; + UCHAR NumberProcessors; +} SYSTEM_BASIC_INFORMATION, *PSYSTEM_BASIC_INFORMATION; + +// SystemProcessorInformation +typedef struct _SYSTEM_PROCESSOR_INFORMATION { + USHORT ProcessorArchitecture; + USHORT ProcessorLevel; + USHORT ProcessorRevision; + USHORT Unknown; + ULONG FeatureBits; +} SYSTEM_PROCESSOR_INFORMATION, *PSYSTEM_PROCESSOR_INFORMATION; + +// SystemPerformanceInformation +typedef struct _SYSTEM_PERFORMANCE_INFORMATION { + LARGE_INTEGER IdleTime; + LARGE_INTEGER ReadTransferCount; + LARGE_INTEGER WriteTransferCount; + LARGE_INTEGER OtherTransferCount; + ULONG ReadOperationCount; + ULONG WriteOperationCount; + ULONG OtherOperationCount; + ULONG AvailablePages; + ULONG TotalCommittedPages; + ULONG TotalCommitLimit; + ULONG PeakCommitment; + ULONG PageFaults; + ULONG WriteCopyFaults; + ULONG TransistionFaults; + ULONG Reserved1; + ULONG DemandZeroFaults; + ULONG PagesRead; + ULONG PageReadIos; + ULONG Reserved2[2]; + ULONG PagefilePagesWritten; + ULONG PagefilePageWriteIos; + ULONG MappedFilePagesWritten; + ULONG MappedFilePageWriteIos; + ULONG PagedPoolUsage; + ULONG NonPagedPoolUsage; + ULONG PagedPoolAllocs; + ULONG PagedPoolFrees; + ULONG NonPagedPoolAllocs; + ULONG NonPagedPoolFrees; + ULONG TotalFreeSystemPtes; + ULONG SystemCodePage; + ULONG TotalSystemDriverPages; + ULONG TotalSystemCodePages; + ULONG SmallNonPagedLookasideListAllocateHits; + ULONG SmallPagedLookasideListAllocateHits; + ULONG Reserved3; + ULONG MmSystemCachePage; + ULONG PagedPoolPage; + ULONG SystemDriverPage; + ULONG FastReadNoWait; + ULONG FastReadWait; + ULONG FastReadResourceMiss; + ULONG FastReadNotPossible; + ULONG FastMdlReadNoWait; + ULONG FastMdlReadWait; + ULONG FastMdlReadResourceMiss; + ULONG FastMdlReadNotPossible; + ULONG MapDataNoWait; + ULONG MapDataWait; + ULONG MapDataNoWaitMiss; + ULONG MapDataWaitMiss; + ULONG PinMappedDataCount; + ULONG PinReadNoWait; + ULONG PinReadWait; + ULONG PinReadNoWaitMiss; + ULONG PinReadWaitMiss; + ULONG CopyReadNoWait; + ULONG CopyReadWait; + ULONG CopyReadNoWaitMiss; + ULONG CopyReadWaitMiss; + ULONG MdlReadNoWait; + ULONG MdlReadWait; + ULONG MdlReadNoWaitMiss; + ULONG MdlReadWaitMiss; + ULONG ReadAheadIos; + ULONG LazyWriteIos; + ULONG LazyWritePages; + ULONG DataFlushes; + ULONG DataPages; + ULONG ContextSwitches; + ULONG FirstLevelTbFills; + ULONG SecondLevelTbFills; + ULONG SystemCalls; +} SYSTEM_PERFORMANCE_INFORMATION, *PSYSTEM_PERFORMANCE_INFORMATION; + +// SystemTimeOfDayInformation +typedef struct _SYSTEM_TIME_OF_DAY_INFORMATION { + LARGE_INTEGER BootTime; + LARGE_INTEGER CurrentTime; + LARGE_INTEGER TimeZoneBias; + ULONG CurrentTimeZoneId; +} SYSTEM_TIME_OF_DAY_INFORMATION, *PSYSTEM_TIME_OF_DAY_INFORMATION; + +typedef struct _SYSTEM_THREADS_INFORMATION { + LARGE_INTEGER KernelTime; + LARGE_INTEGER UserTime; + LARGE_INTEGER CreateTime; + ULONG WaitTime; + PVOID StartAddress; + CLIENT_ID ClientId; + KPRIORITY Priority; + KPRIORITY BasePriority; + ULONG ContextSwitchCount; + THREAD_STATE State; + KWAIT_REASON WaitReason; +} SYSTEM_THREADS_INFORMATION, *PSYSTEM_THREADS_INFORMATION; + +// SystemProcessesAndThreadsInformation +typedef struct _SYSTEM_PROCESSES_INFORMATION { + ULONG NextEntryDelta; + ULONG ThreadCount; + ULONG Reserved1[6]; + LARGE_INTEGER CreateTime; + LARGE_INTEGER UserTime; + LARGE_INTEGER KernelTime; + UNICODE_STRING ProcessName; + KPRIORITY BasePriority; + ULONG ProcessId; + ULONG InheritedFromProcessId; + ULONG HandleCount; + ULONG SessionId; + ULONG Reserved2; + VM_COUNTERS VmCounters; +#if (VER_PRODUCTBUILD >= 2195) + IO_COUNTERS IoCounters; +#endif // (VER_PRODUCTBUILD >= 2195) + SYSTEM_THREADS_INFORMATION Threads[1]; +} SYSTEM_PROCESSES_INFORMATION, *PSYSTEM_PROCESSES_INFORMATION; + +// SystemCallCounts +typedef struct _SYSTEM_CALL_COUNTS { + ULONG Size; + ULONG NumberOfDescriptorTables; + ULONG NumberOfRoutinesInTable[1]; + // On checked build this is followed by a ULONG CallCounts[1] variable length array. +} SYSTEM_CALL_COUNTS, *PSYSTEM_CALL_COUNTS; + +// SystemConfigurationInformation +typedef struct _SYSTEM_CONFIGURATION_INFORMATION { + ULONG DiskCount; + ULONG FloppyCount; + ULONG CdRomCount; + ULONG TapeCount; + ULONG SerialCount; + ULONG ParallelCount; +} SYSTEM_CONFIGURATION_INFORMATION, *PSYSTEM_CONFIGURATION_INFORMATION; + +// SystemProcessorTimes +typedef struct _SYSTEM_PROCESSOR_TIMES { + LARGE_INTEGER IdleTime; + LARGE_INTEGER KernelTime; + LARGE_INTEGER UserTime; + LARGE_INTEGER DpcTime; + LARGE_INTEGER InterruptTime; + ULONG InterruptCount; +} SYSTEM_PROCESSOR_TIMES, *PSYSTEM_PROCESSOR_TIMES; + +// SystemGlobalFlag +typedef struct _SYSTEM_GLOBAL_FLAG { + ULONG GlobalFlag; +} SYSTEM_GLOBAL_FLAG, *PSYSTEM_GLOBAL_FLAG; + +// SystemModuleInformation +typedef struct _SYSTEM_MODULE_INFORMATION { + ULONG Reserved[2]; + PVOID Base; + ULONG Size; + ULONG Flags; + USHORT Index; + USHORT Unknown; + USHORT LoadCount; + USHORT ModuleNameOffset; + CHAR ImageName[256]; +} SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION; + +// SystemLockInformation +typedef struct _SYSTEM_LOCK_INFORMATION { + PVOID Address; + USHORT Type; + USHORT Reserved1; + ULONG ExclusiveOwnerThreadId; + ULONG ActiveCount; + ULONG ContentionCount; + ULONG Reserved2[2]; + ULONG NumberOfSharedWaiters; + ULONG NumberOfExclusiveWaiters; +} SYSTEM_LOCK_INFORMATION, *PSYSTEM_LOCK_INFORMATION; + +// SystemHandleInformation +typedef struct _SYSTEM_HANDLE_INFORMATION { + ULONG ProcessId; + UCHAR ObjectTypeNumber; + UCHAR Flags; + USHORT Handle; + PVOID Object; + ACCESS_MASK GrantedAccess; +} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION; + +// SystemObjectInformation +typedef struct _SYSTEM_OBJECT_TYPE_INFORMATION { + ULONG NextEntryOffset; + ULONG ObjectCount; + ULONG HandleCount; + ULONG TypeNumber; + ULONG InvalidAttributes; + GENERIC_MAPPING GenericMapping; + ACCESS_MASK ValidAccessMask; + POOL_TYPE PoolType; + UCHAR Unknown; + UNICODE_STRING Name; +} SYSTEM_OBJECT_TYPE_INFORMATION, *PSYSTEM_OBJECT_TYPE_INFORMATION; + +typedef struct _SYSTEM_OBJECT_INFORMATION { + ULONG NextEntryOffset; + PVOID Object; + ULONG CreatorProcessId; + USHORT Unknown; + USHORT Flags; + ULONG PointerCount; + ULONG HandleCount; + ULONG PagedPoolUsage; + ULONG NonPagedPoolUsage; + ULONG ExclusiveProcessId; + PSECURITY_DESCRIPTOR SecurityDescriptor; + UNICODE_STRING Name; +} SYSTEM_OBJECT_INFORMATION, *PSYSTEM_OBJECT_INFORMATION; + +// SystemPagefileInformation +typedef struct _SYSTEM_PAGEFILE_INFORMATION { + ULONG NextEntryOffset; + ULONG CurrentSize; + ULONG TotalUsed; + ULONG PeakUsed; + UNICODE_STRING FileName; +} SYSTEM_PAGEFILE_INFORMATION, *PSYSTEM_PAGEFILE_INFORMATION; + +// SystemInstructionEmulationCounts +typedef struct _SYSTEM_INSTRUCTION_EMULATION_COUNTS { + ULONG GenericInvalidOpcode; + ULONG TwoByteOpcode; + ULONG ESprefix; + ULONG CSprefix; + ULONG SSprefix; + ULONG DSprefix; + ULONG FSPrefix; + ULONG GSprefix; + ULONG OPER32prefix; + ULONG ADDR32prefix; + ULONG INSB; + ULONG INSW; + ULONG OUTSB; + ULONG OUTSW; + ULONG PUSHFD; + ULONG POPFD; + ULONG INTnn; + ULONG INTO; + ULONG IRETD; + ULONG FloatingPointOpcode; + ULONG INBimm; + ULONG INWimm; + ULONG OUTBimm; + ULONG OUTWimm; + ULONG INB; + ULONG INW; + ULONG OUTB; + ULONG OUTW; + ULONG LOCKprefix; + ULONG REPNEprefix; + ULONG REPprefix; + ULONG CLI; + ULONG STI; + ULONG HLT; +} SYSTEM_INSTRUCTION_EMULATION_COUNTS, *PSYSTEM_INSTRUCTION_EMULATION_COUNTS; + +// SystemCacheInformation +typedef struct _SYSTEM_CACHE_INFORMATION { + ULONG SystemCacheWsSize; + ULONG SystemCacheWsPeakSize; + ULONG SystemCacheWsFaults; + ULONG SystemCacheWsMinimum; + ULONG SystemCacheWsMaximum; + ULONG TransitionSharedPages; + ULONG TransitionSharedPagesPeak; + ULONG Reserved[2]; +} SYSTEM_CACHE_INFORMATION, *PSYSTEM_CACHE_INFORMATION; + +// SystemPoolTagInformation +typedef struct _SYSTEM_POOL_TAG_INFORMATION { + CHAR Tag[4]; + ULONG PagedPoolAllocs; + ULONG PagedPoolFrees; + ULONG PagedPoolUsage; + ULONG NonPagedPoolAllocs; + ULONG NonPagedPoolFrees; + ULONG NonPagedPoolUsage; +} SYSTEM_POOL_TAG_INFORMATION, *PSYSTEM_POOL_TAG_INFORMATION; + +// SystemProcessorStatistics +typedef struct _SYSTEM_PROCESSOR_STATISTICS { + ULONG ContextSwitches; + ULONG DpcCount; + ULONG DpcRequestRate; + ULONG TimeIncrement; + ULONG DpcBypassCount; + ULONG ApcBypassCount; +} SYSTEM_PROCESSOR_STATISTICS, *PSYSTEM_PROCESSOR_STATISTICS; + +// SystemDpcInformation +typedef struct _SYSTEM_DPC_INFORMATION { + ULONG Reserved; + ULONG MaximumDpcQueueDepth; + ULONG MinimumDpcRate; + ULONG AdjustDpcThreshold; + ULONG IdealDpcRate; +} SYSTEM_DPC_INFORMATION, *PSYSTEM_DPC_INFORMATION; + +// SystemLoadImage +typedef struct _SYSTEM_LOAD_IMAGE { + UNICODE_STRING ModuleName; + PVOID ModuleBase; + PVOID Unknown; + PVOID EntryPoint; + PVOID ExportDirectory; +} SYSTEM_LOAD_IMAGE, *PSYSTEM_LOAD_IMAGE; + +// SystemUnloadImage +typedef struct _SYSTEM_UNLOAD_IMAGE { + PVOID ModuleBase; +} SYSTEM_UNLOAD_IMAGE, *PSYSTEM_UNLOAD_IMAGE; + +// SystemTimeAdjustment +typedef struct _SYSTEM_QUERY_TIME_ADJUSTMENT { + ULONG TimeAdjustment; + ULONG MaximumIncrement; + BOOLEAN TimeSynchronization; +} SYSTEM_QUERY_TIME_ADJUSTMENT, *PSYSTEM_QUERY_TIME_ADJUSTMENT; + +// SystemTimeAdjustment +typedef struct _SYSTEM_SET_TIME_ADJUSTMENT { + ULONG TimeAdjustment; + BOOLEAN TimeSynchronization; +} SYSTEM_SET_TIME_ADJUSTMENT, *PSYSTEM_SET_TIME_ADJUSTMENT; + +// SystemCrashDumpInformation +typedef struct _SYSTEM_CRASH_DUMP_INFORMATION { + HANDLE CrashDumpSectionHandle; +#if (VER_PRODUCTBUILD >= 2195) + HANDLE Unknown; +#endif // (VER_PRODUCTBUILD >= 2195) +} SYSTEM_CRASH_DUMP_INFORMATION, *PSYSTEM_CRASH_DUMP_INFORMATION; + +// SystemExceptionInformation +typedef struct _SYSTEM_EXCEPTION_INFORMATION { + ULONG AlignmentFixupCount; + ULONG ExceptionDispatchCount; + ULONG FloatingEmulationCount; + ULONG Reserved; +} SYSTEM_EXCEPTION_INFORMATION, *PSYSTEM_EXCEPTION_INFORMATION; + +// SystemCrashDumpStateInformation +typedef struct _SYSTEM_CRASH_DUMP_STATE_INFORMATION { + ULONG ValidCrashDump; +#if (VER_PRODUCTBUILD >= 2195) + ULONG Unknown; +#endif // (VER_PRODUCTBUILD >= 2195) +} SYSTEM_CRASH_DUMP_STATE_INFORMATION, *PSYSTEM_CRASH_DUMP_STATE_INFORMATION; + +// SystemKernelDebuggerInformation +typedef struct _SYSTEM_KERNEL_DEBUGGER_INFORMATION { + BOOLEAN DebuggerEnabled; + BOOLEAN DebuggerNotPresent; +} SYSTEM_KERNEL_DEBUGGER_INFORMATION, *PSYSTEM_KERNEL_DEBUGGER_INFORMATION; + +// SystemContextSwitchInformation +typedef struct _SYSTEM_CONTEXT_SWITCH_INFORMATION { + ULONG ContextSwitches; + ULONG ContextSwitchCounters[11]; +} SYSTEM_CONTEXT_SWITCH_INFORMATION, *PSYSTEM_CONTEXT_SWITCH_INFORMATION; + +// SystemRegistryQuotaInformation +typedef struct _SYSTEM_REGISTRY_QUOTA_INFORMATION { + ULONG RegistryQuota; + ULONG RegistryQuotaInUse; + ULONG PagedPoolSize; +} SYSTEM_REGISTRY_QUOTA_INFORMATION, *PSYSTEM_REGISTRY_QUOTA_INFORMATION; + +// SystemLoadAndCallImage +typedef struct _SYSTEM_LOAD_AND_CALL_IMAGE { + UNICODE_STRING ModuleName; +} SYSTEM_LOAD_AND_CALL_IMAGE, *PSYSTEM_LOAD_AND_CALL_IMAGE; + +// SystemPrioritySeparation +typedef struct _SYSTEM_PRIORITY_SEPARATION { + ULONG PrioritySeparation; +} SYSTEM_PRIORITY_SEPARATION, *PSYSTEM_PRIORITY_SEPARATION; + +// SystemTimeZoneInformation +typedef struct _SYSTEM_TIME_ZONE_INFORMATION { + LONG Bias; + WCHAR StandardName[32]; + TIME_FIELDS StandardDate; + LONG StandardBias; + WCHAR DaylightName[32]; + TIME_FIELDS DaylightDate; + LONG DaylightBias; +} SYSTEM_TIME_ZONE_INFORMATION, *PSYSTEM_TIME_ZONE_INFORMATION; + +// SystemLookasideInformation +typedef struct _SYSTEM_LOOKASIDE_INFORMATION { + USHORT Depth; + USHORT MaximumDepth; + ULONG TotalAllocates; + ULONG AllocateMisses; + ULONG TotalFrees; + ULONG FreeMisses; + POOL_TYPE Type; + ULONG Tag; + ULONG Size; +} SYSTEM_LOOKASIDE_INFORMATION, *PSYSTEM_LOOKASIDE_INFORMATION; + +// SystemSetTimeSlipEvent +typedef struct _SYSTEM_SET_TIME_SLIP_EVENT { + HANDLE TimeSlipEvent; +} SYSTEM_SET_TIME_SLIP_EVENT, *PSYSTEM_SET_TIME_SLIP_EVENT; + +// SystemCreateSession +typedef struct _SYSTEM_CREATE_SESSION { + ULONG Session; +} SYSTEM_CREATE_SESSION, *PSYSTEM_CREATE_SESSION; + +// SystemDeleteSession +typedef struct _SYSTEM_DELETE_SESSION { + ULONG Session; +} SYSTEM_DELETE_SESSION, *PSYSTEM_DELETE_SESSION; + +// SystemRangeStartInformation +typedef struct _SYSTEM_RANGE_START_INFORMATION { + PVOID SystemRangeStart; +} SYSTEM_RANGE_START_INFORMATION, *PSYSTEM_RANGE_START_INFORMATION; + +// SystemSessionProcessesInformation +typedef struct _SYSTEM_SESSION_PROCESS_INFORMATION { + ULONG SessionId; + ULONG BufferSize; + PVOID Buffer; +} SYSTEM_SESSION_PROCESS_INFORMATION, *PSYSTEM_SESSION_PROCESS_INFORMATION; + +typedef struct _GDI_TEB_BATCH { + ULONG Offset; + ULONG HDC; + ULONG Buffer[(VER_PRODUCTBUILD >= 2195) ? 0x133 : 0x136]; +} GDI_TEB_BATCH, *PGDI_TEB_BATCH; + +#if (VER_PRODUCTBUILD >= 2600) + +typedef struct _RTL_ACTIVATION_CONTEXT_STACK_FRAME { + struct _RTL_ACTIVATION_CONTEXT_STACK_FRAME* Previous; + struct _ACTIVATION_CONTEXT* ActivationContext; // 0x4 + ULONG Flags; // 0x8 +} RTL_ACTIVATION_CONTEXT_STACK_FRAME, *PRTL_ACTIVATION_CONTEXT_STACK_FRAME; + +typedef struct _ACTIVATION_CONTEXT_STACK { + ULONG Flags; + ULONG NextCookieSequenceNumber; + PRTL_ACTIVATION_CONTEXT_STACK_FRAME ActiveFrame; // 0x8 + LIST_ENTRY FrameListCache; // 0xc +} ACTIVATION_CONTEXT_STACK, *PACTIVATION_CONTEXT_STACK; + +#endif // (VER_PRODUCTBUILD >= 2600) + +typedef struct _Wx86ThreadState { + PULONG CallBx86Eip; + PVOID DeallocationCpu; + UCHAR UseKnownWx86Dll; // 0x8 + UCHAR OleStubInvoked; // 0x9 +} Wx86ThreadState, *PWx86ThreadState; + +typedef struct _TEB_ACTIVE_FRAME_CONTEXT { + ULONG Flags; + PCHAR FrameName; +} TEB_ACTIVE_FRAME_CONTEXT, *PTEB_ACTIVE_FRAME_CONTEXT; + +typedef struct _TEB_ACTIVE_FRAME { + ULONG Flags; + struct _TEB_ACTIVE_FRAME *Previous; + PTEB_ACTIVE_FRAME_CONTEXT Context; +} TEB_ACTIVE_FRAME, *PTEB_ACTIVE_FRAME; + +typedef struct _TEB // from Reactos, Native API; checked and corrected for 2003 and nt 4.0 + // should also work on XP and 2000 + // the reactos version was probably from NT 3.51 SP3 +{ + NT_TIB Tib; /* 00h */ + PVOID EnvironmentPointer; /* 1Ch */ + CLIENT_ID Cid; /* 20h */ + HANDLE RpcHandle; /* 28h */ + PVOID *ThreadLocalStorage; /* 2Ch */ + PPEB Peb; /* 30h */ + ULONG LastErrorValue; /* 34h */ + ULONG CountOfOwnedCriticalSections; /* 38h */ + PVOID CsrClientThread; /* 3Ch */ + struct _W32THREAD* Win32ThreadInfo; /* 40h */ + ULONG User32Reserved[26]; /* 44h */ + ULONG UserReserved[5]; /* ACh */ + PVOID WOW32Reserved; /* C0h */ + LCID CurrentLocale; /* C4h */ + ULONG FpSoftwareStatusRegister; /* C8h */ + PVOID SystemReserved1[0x36]; /* CCh */ +#if (VER_PRODUCTBUILD <= 1381) + PVOID Spare1; /* 1A4h */ +#endif + LONG ExceptionCode; /* 1A4h */ +#if (VER_PRODUCTBUILD >= 2600) + ACTIVATION_CONTEXT_STACK + ActivationContextStack; /* 1A8h */ + UCHAR SpareBytes1[24]; /* 1BCh */ +#elif (VER_PRODUCTBUILD >= 2195) + UCHAR SpareBytes1[0x2c]; /* 1A8h */ +#else /* nt 4.0 */ + ULONG SpareBytes1[0x14]; /* 1ACh */ +#endif + GDI_TEB_BATCH GdiTebBatch; /* 1D4h */ /* 1FC for nt 4.0 */ + ULONG gdiRgn; /* 6A8h */ /* 6DCh for nt 4.0 */ + ULONG gdiPen; /* 6ACh */ + ULONG gdiBrush; /* 6B0h */ + CLIENT_ID RealClientId; /* 6B4h */ /* 6E8h for nt 4.0 */ + PVOID GdiCachedProcessHandle; /* 6BCh */ + ULONG GdiClientPID; /* 6C0h */ + ULONG GdiClientTID; /* 6C4h */ + PVOID GdiThreadLocaleInfo; /* 6C8h */ +#if (VER_PRODUCTBUILD == 1381) + PVOID Win32ClientInfo[5]; /* 700h */ + PVOID glDispatchTable[0x118]; /* 714h */ + ULONG glReserved1[0x1a]; /* B74h */ +#else + PVOID Win32ClientInfo[0x3e]; /* 6CCh */ + PVOID glDispatchTable[0xe9]; /* 7C4h */ + ULONG glReserved1[0x1d]; /* B68h */ +#endif + PVOID glReserved2; /* BDCh */ + PVOID glSectionInfo; /* BE0h */ + PVOID glSection; /* BE4h */ + PVOID glTable; /* BE8h */ + PVOID glCurrentRC; /* BECh */ + PVOID glContext; /* BF0h */ + NTSTATUS LastStatusValue; /* BF4h */ + UNICODE_STRING StaticUnicodeString; /* BF8h */ + WCHAR StaticUnicodeBuffer[0x105]; /* C00h */ + PVOID DeallocationStack; /* E0Ch */ + PVOID TlsSlots[0x40]; /* E10h */ + LIST_ENTRY TlsLinks; /* F10h */ + PVOID Vdm; /* F18h */ + PVOID ReservedForNtRpc; /* F1Ch */ + PVOID DbgSsReserved[0x2]; /* F20h */ + ULONG HardErrorDisabled; /* F28h */ + PVOID Instrumentation[0x10]; /* F2Ch */ + PVOID WinSockData; /* F6Ch */ + ULONG GdiBatchCount; /* F70h */ + BOOLEAN InDbgPrint; /* F74h */ + BOOLEAN FreeStackOnTermination; /* F75h */ + BOOLEAN HasFiberData; /* F76h */ + UCHAR IdealProcessor; /* F77h */ + ULONG Spare3; /* F78h */ + ULONG ReservedForPerf; /* F7Ch */ + PVOID ReservedForOle; /* F80h */ + ULONG WaitingOnLoaderLock; /* F84h */ +#if (VER_PRODUCTBUILD >= 2195) + Wx86ThreadState Wx86Thread; /* F88h */ + PVOID* TlsExpansionSlots; /* F94h */ + ULONG ImpersonationLocale; /* F98h */ + ULONG IsImpersonating; /* F9Ch */ + PVOID NlsCache; /* FA0h */ + PVOID pShimData; /* FA4h */ + ULONG HeapVirtualAffinity; /* FA8h */ + PVOID CurrentTransactionHandle; /* FACh */ + PTEB_ACTIVE_FRAME ActiveFrame; /* FB0h*/ + PVOID FlsSlots; /* FB4h */ +#endif +} TEB, *PTEB; + +typedef struct _TERMINATION_PORT { + struct _TERMINATION_PORT* Next; + PVOID Port; +} TERMINATION_PORT, *PTERMINATION_PORT; + +typedef struct _THREAD_BASIC_INFORMATION { + NTSTATUS ExitStatus; + PVOID TebBaseAddress; + ULONG UniqueProcessId; + ULONG UniqueThreadId; + KAFFINITY AffinityMask; + KPRIORITY BasePriority; + ULONG DiffProcessPriority; +} THREAD_BASIC_INFORMATION, *PTHREAD_BASIC_INFORMATION; + +typedef struct _TOKEN_SOURCE { + CCHAR SourceName[TOKEN_SOURCE_LENGTH]; + LUID SourceIdentifier; +} TOKEN_SOURCE, *PTOKEN_SOURCE; + +typedef struct _TOKEN_CONTROL { + LUID TokenId; + LUID AuthenticationId; + LUID ModifiedId; + TOKEN_SOURCE TokenSource; +} TOKEN_CONTROL, *PTOKEN_CONTROL; + +typedef struct _TOKEN_DEFAULT_DACL { + PACL DefaultDacl; +} TOKEN_DEFAULT_DACL, *PTOKEN_DEFAULT_DACL; + +typedef struct _TOKEN_GROUPS { + ULONG GroupCount; + SID_AND_ATTRIBUTES Groups[1]; +} TOKEN_GROUPS, *PTOKEN_GROUPS; + +/* XP SP2 has same TOKEN_OBJECT structure as Windows Server 2003 (stucture K23 in union). */ +#include +typedef union +{ + struct + { + TOKEN_SOURCE TokenSource; /* 0x0: CHAR SourceName[8] = "*SYSTEM*" | "User32 " + LUID SourceIdentifier = 0x10, *SYSTEM* id == 0 */ + LUID TokenId; /* 0x10: */ + LUID AuthenticationId; /* 0x18: */ + LARGE_INTEGER ExpirationTime; /* 0x20: -1 no expired. *SYSTEM* has expired? */ + LUID ModifiedId; /* 0x28: */ + ULONG UserAndGroupCount; /* 0x30: 3 */ + ULONG PrivilegeCount; /* 0x34: 14 */ + ULONG VariableLength; /* 0x38: 0x37C */ + ULONG DynamicCharged; /* 0x3C: 0x1F4 */ + ULONG DynamicAvailable; /* 0x40: 0x1A4 */ + ULONG DefaultOwnerIndex; /* 0x44: 1 */ + PSID_AND_ATTRIBUTES UserAndGroups;/* 0x48: TOKEN_USER Owners [UserAndGroupCount] DefaultOwnerIndex */ + PSID PrimaryGroup; /* 0x4C: */ + PLUID_AND_ATTRIBUTES Privileges;/* 0x50: */ + PULONG DynamicPart; /* 0x54: */ + PACL DefaultDacl; /* 0x58: */ + TOKEN_TYPE TokenType; /* 0x5C: TokenPrimary | TokenImpersonation */ + SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;/* 0x60: 0 */ + UCHAR TokenFlags; /* 0x64: 1 */ + BOOLEAN TokenInUse; /* 0x65: 1 */ + USHORT Alignment; /* 0x66: 0 */ + PVOID ProxyData; /* 0x68: 0 */ + PVOID AuditData; /* 0x6C: 0 */ + ULONG VariablePart; /* 0x70: */ + } NT; + struct + { + TOKEN_SOURCE TokenSource; /* 0x0: CHAR SourceName[8] = "*SYSTEM*" | "User32 " + LUID SourceIdentifier = 0x10 */ + LUID TokenId; /* 0x10: */ + LUID AuthenticationId; /* 0x18: */ + LUID ParentTokenId; /* 0x20: 0 */ + LARGE_INTEGER ExpirationTime; /* 0x28: -1 no expired */ + LUID ModifiedId; /* 0x30: */ + ULONG SessionId; /* 0x38: 0 */ + ULONG UserAndGroupCount; /* 0x3C: 9 */ + ULONG RestrictedSidCount; /*+0x40: 0 */ + ULONG PrivilegeCount; /* 0x44: 11 */ + ULONG VariableLength; /* 0x48: 0x1F0 */ + ULONG DynamicCharged; /* 0x4C: 0x1F4 */ + ULONG DynamicAvailable; /* 0x50: 0x1A4 */ + ULONG DefaultOwnerIndex; /* 0x54: 3 */ + PSID_AND_ATTRIBUTES UserAndGroups; /* 0x58: TOKEN_USER Owners [UserAndGroupCount] DefaultOwnerIndex */ + PSID_AND_ATTRIBUTES RestrictedSids;/* 0x5C: 0 */ + PSID PrimaryGroup; /* 0x60: */ + PLUID_AND_ATTRIBUTES Privileges;/* 0x64: */ + PULONG DynamicPart; /* 0x68: */ + PACL DefaultDacl; /* 0x6C: */ + TOKEN_TYPE TokenType; /* 0x70: TokenPrimary | TokenImpersonation */ + SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;/* 0x74: 0 */ + UCHAR TokenFlags; /* 0x78: 9 */ + BOOLEAN TokenInUse; /* 0x79: 1 */ + USHORT Alignment; /* 0x7A: 0 */ + PVOID ProxyData; /* 0x7C: 0 */ + PVOID AuditData; /* 0x80: 0 */ + ULONG VariablePart; /* 0x84: */ + } K2; + struct + { + TOKEN_SOURCE TokenSource; /* 0x0: CHAR SourceName[8] = "*SYSTEM*" | "User32 " + LUID SourceIdentifier = 0x10 */ + LUID TokenId; /* 0x10: 0x6F68 */ + LUID AuthenticationId; /* 0x18: */ + LUID ParentTokenId; /* 0x20: 0 */ + LARGE_INTEGER ExpirationTime; /* 0x28: -1 no expired */ + PERESOURCE TokenLock; /*+0x30: 0x8xxxxxxxx */ + LUID ModifiedId; /* 0x34: */ + ULONG SessionId; /* 0x3C: 0x6F6A */ + ULONG UserAndGroupCount; /* 0x40: 4 */ + ULONG RestrictedSidCount; /*+0x44: 0 */ + ULONG VariableLength; /* 0x48: 0x160 */ + ULONG DynamicCharged; /* 0x4C: 0x164 */ + ULONG DynamicAvailable; /* 0x50: 0x1F4 */ + ULONG PrivilegeCount; /* 0x54: 0 */ + ULONG DefaultOwnerIndex; /* 0x58: 1 */ + PSID_AND_ATTRIBUTES UserAndGroups; /* 0x5C: TOKEN_USER Owners [UserAndGroupCount] DefaultOwnerIndex */ + PSID_AND_ATTRIBUTES RestrictedSids;/* 0x60: 0 */ + PSID PrimaryGroup; /* 0x64: */ + PLUID_AND_ATTRIBUTES Privileges;/* 0x68: */ + PULONG DynamicPart; /* 0x6C: */ + PACL DefaultDacl; /* 0x70: */ + TOKEN_TYPE TokenType; /* 0x74: TokenPrimary | TokenImpersonation */ + SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;/* 0x78: 0 */ + UCHAR TokenFlags; /* 0x7C: 9 */ + BOOLEAN TokenInUse; /* 0x7D: 1 */ + USHORT Alignment; /* 0x7E: 4BB4 */ + PVOID ProxyData; /* 0x80: 0 */ + PVOID AuditData; /* 0x84: 0 */ + ULONG VariablePart; /* 0x88: */ + } XP; + struct + { + TOKEN_SOURCE TokenSource; /* 0x0: CHAR SourceName[8] = "*SYSTEM*" | "User32 " + LUID SourceIdentifier = 0x10 */ + LUID TokenId; /* 0x10: 0x6F68 */ + LUID AuthenticationId; /* 0x18: */ + LUID ParentTokenId; /* 0x20: 0 */ + LARGE_INTEGER ExpirationTime; /* 0x28: -1 no expired */ + PERESOURCE TokenLock; /*+0x30: 0x8xxxxxxxx */ + ULONG Padding64; /*+0x34: 0xXxxxxxxxx */ + SEP_AUDIT_POLICY AuditPolicy; /*+0x38: */ + LUID ModifiedId; /*+0x040: 0x6F6A */ + ULONG SessionId; /*+0x048: */ + ULONG UserAndGroupCount; /* 0x4C: 4 */ + ULONG RestrictedSidCount; /*+0x50: 0 */ + ULONG VariableLength; /* 0x54: 0x18 */ + ULONG DynamicCharged; /* 0x58: 0x17C */ + ULONG DynamicAvailable; /* 0x5C: 0x1F4 */ + ULONG PrivilegeCount; /* 0x60: 0 */ + ULONG DefaultOwnerIndex; /* 0x64: 1 */ + PSID_AND_ATTRIBUTES UserAndGroups; /* 0x68: TOKEN_USER Owners [UserAndGroupCount] DefaultOwnerIndex */ + PSID_AND_ATTRIBUTES RestrictedSids;/* 0x6C: 0 */ + PSID PrimaryGroup; /* 0x70: */ + PLUID_AND_ATTRIBUTES Privileges;/* 0x74: */ + PULONG DynamicPart; /* 0x78: */ + PACL DefaultDacl; /* 0x7C: */ + TOKEN_TYPE TokenType; /* 0x80: TokenPrimary | TokenImpersonation */ + SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;/* 0x84: 0 */ + UCHAR TokenFlags; /* 0x88: 9 */ + BOOLEAN TokenInUse; /* 0x89: 1 */ + USHORT Alignment; /* 0x8A: 4BB4 */ + PVOID ProxyData; /* 0x8C: 0x8xxxxxxxx */ + PVOID AuditData; /* 0x90: 0 */ + ULONG VariablePart; /* 0x94: */ + } K23; + struct + { + TOKEN_SOURCE TokenSource; /* +0x0: CHAR SourceName[8] = "*SYSTEM*" | "User32 " + LUID SourceIdentifier = 0x10 */ + LUID TokenId; /* +0x10: 0x6F68 */ + LUID AuthenticationId; /* +0x18: */ + LUID ParentTokenId; /* +0x20: 0 */ + LARGE_INTEGER ExpirationTime; /* +0x28: -1 no expired */ + PERESOURCE TokenLock; /* +0x30: 0x8xxxxxxxx */ + ULONG Padding64; /* +0x34: 0xXxxxxxxxx */ + SEP_AUDIT_POLICY AuditPolicy; /* +0x38: */ + LUID ModifiedId; /* +0x040: 0x6F6A */ + ULONG SessionId; /* +0x048: */ + ULONG UserAndGroupCount; /* +0x04c: 4 */ + ULONG RestrictedSidCount; /* +0x050: 0 */ + ULONG PrivilegeCount; /* +0x054: 0x18 */ + ULONG VariableLength; /* +0x058: 0x17C */ + ULONG DynamicCharged; /* +0x05c: 0x1F4 */ + ULONG DynamicAvailable; /* +0x060: 0 */ + ULONG DefaultOwnerIndex; /* +0x064: 1 */ + PSID_AND_ATTRIBUTES UserAndGroups; /* +0x68: TOKEN_USER Owners [UserAndGroupCount] DefaultOwnerIndex */ + PSID_AND_ATTRIBUTES RestrictedSids; /* +0x6C: 0 */ + PSID PrimaryGroup; /* +0x70: */ + PLUID_AND_ATTRIBUTES Privileges; /* +0x74: */ + PULONG DynamicPart; /* +0x78: */ + PACL DefaultDacl; /* +0x7C: */ + TOKEN_TYPE TokenType; /* +0x80: TokenPrimary | TokenImpersonation */ + SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;/* +0x84: 0 */ + UCHAR TokenFlags; /* +0x88: 9 */ + BOOLEAN TokenInUse; /* +0x89: 1 */ + USHORT Alignment; /* +0x8A: 4BB4 */ + PVOID ProxyData; /* +0x8C: 0x8xxxxxxxx */ + PVOID AuditData; /* +0x90: 0 */ + PVOID LogonSession; /* +0x94: */ + LUID OriginatingLogonSession;/* +0x98: */ + ULONG VariablePart; /* +0xa0: */ + } K23SP1; + struct + { + TOKEN_SOURCE TokenSource; /* +0x000 */ + LUID TokenId; /* +0x010 */ + LUID AuthenticationId; /* +0x018 */ + LUID ParentTokenId; /* +0x020 */ + LARGE_INTEGER ExpirationTime; /* +0x028 */ + PERESOURCE TokenLock; /* +0x030 */ + LUID ModifiedId; /* +0x034 */ + SEP_AUDIT_POLICY_VISTA AuditPolicy; /* +0x03c */ + ULONG SessionId; /* +0x058 */ + ULONG UserAndGroupCount; /* +0x05c */ + ULONG RestrictedSidCount; /* +0x060 */ + ULONG PrivilegeCount; /* +0x064 */ + ULONG VariableLength; /* +0x068 */ + ULONG DynamicCharged; /* +0x06c */ + ULONG DynamicAvailable; /* +0x070 */ + ULONG DefaultOwnerIndex; /* +0x074 */ + PSID_AND_ATTRIBUTES UserAndGroups; /* +0x078 */ + PSID_AND_ATTRIBUTES RestrictedSids; /* +0x07c */ + PSID PrimaryGroup; /* +0x080 */ + PLUID_AND_ATTRIBUTES Privileges; /* +0x084 */ + PULONG DynamicPart; /* +0x088 */ + PACL DefaultDacl; /* +0x08c */ + TOKEN_TYPE TokenType; /* +0x090 */ + SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;/* +0x094 */ + ULONG TokenFlags; /* +0x098 */ + BOOLEAN TokenInUse; /* +0x09c */ + BOOLEAN WriterPresent; /* +0x09d */ + USHORT Alignment; /* +0x09e */ + ULONG IntegrityLevelIndex; /* +0x0a0 */ + ULONG DesktopIntegrityLevelIndex;/* +0x0a4 */ + ULONG MandatoryPolicy; /* +0x0a8 */ + PVOID ProxyData; /* +0x0ac */ + PVOID AuditData; /* +0x0b0 */ + PVOID LogonSession; /* +0x0b4 */ + LUID OriginatingLogonSession;/* +0x0b8 */ + SID_AND_ATTRIBUTES_HASH SidHash; /* +0x0c0 */ + SID_AND_ATTRIBUTES_HASH RestrictedSidHash;/* +0x148 */ + ULONG VariablePart; /* +0x1d0 */ + } VISTA; + struct + { + TOKEN_SOURCE TokenSource; /* +0x000 */ + LUID TokenId; /* +0x010 */ + LUID AuthenticationId; /* +0x018 */ + LUID ParentTokenId; /* +0x020 */ + LARGE_INTEGER ExpirationTime; /* +0x028 */ + PERESOURCE TokenLock; /* +0x030 */ + SEP_AUDIT_POLICY AuditPolicy; /* +0x038 */ + LUID ModifiedId; /* +0x040 */ + ULONG SessionId; /* +0x048 */ + ULONG UserAndGroupCount; /* +0x04c */ + ULONG RestrictedSidCount; /* +0x050 */ + ULONG PrivilegeCount; /* +0x054 */ + ULONG VariableLength; /* +0x058 */ + ULONG DynamicCharged; /* +0x05c */ + ULONG DynamicAvailable; /* +0x060 */ + ULONG DefaultOwnerIndex; /* +0x064 */ + PSID_AND_ATTRIBUTES UserAndGroups; /* +0x068 */ + PSID_AND_ATTRIBUTES RestrictedSids; /* +0x070 */ + PSID PrimaryGroup; /* +0x078 */ + PLUID_AND_ATTRIBUTES Privileges; /* +0x080 */ + PULONG DynamicPart; /* +0x088 */ + PACL DefaultDacl; /* +0x090 */ + TOKEN_TYPE TokenType; /* +0x098 */ + SECURITY_IMPERSONATION_LEVEL ImpersonationLevel; /* +0x09c */ + UCHAR TokenFlags; /* +0x0a0 */ + BOOLEAN TokenInUse; /* +0x0a1 */ + UCHAR Padding64 [6]; /* +0x0a2 */ + PVOID ProxyData; /* +0x0a8 */ + PVOID AuditData; /* +0x0b0 */ + PVOID LogonSession; /* +0x0b8 */ + LUID OriginatingLogonSession;/* +0x0c0 */ + ULONG VariablePart; /* +0x0c8 */ + } XP64; /* equial 2K3SP1x64 */ + /* VariablePart */ +} TOKEN_OBJECT, *PTOKEN_OBJECT; +#include + +typedef struct _TOKEN_OWNER { + PSID Owner; +} TOKEN_OWNER, *PTOKEN_OWNER; + +typedef struct _TOKEN_PRIMARY_GROUP { + PSID PrimaryGroup; +} TOKEN_PRIMARY_GROUP, *PTOKEN_PRIMARY_GROUP; + +typedef struct _TOKEN_PRIVILEGES { + ULONG PrivilegeCount; + LUID_AND_ATTRIBUTES Privileges[1]; +} TOKEN_PRIVILEGES, *PTOKEN_PRIVILEGES; + +typedef struct _TOKEN_STATISTICS { + LUID TokenId; + LUID AuthenticationId; + LARGE_INTEGER ExpirationTime; + TOKEN_TYPE TokenType; + SECURITY_IMPERSONATION_LEVEL ImpersonationLevel; + ULONG DynamicCharged; + ULONG DynamicAvailable; + ULONG GroupCount; + ULONG PrivilegeCount; + LUID ModifiedId; +} TOKEN_STATISTICS, *PTOKEN_STATISTICS; + +typedef struct _TOKEN_USER { + SID_AND_ATTRIBUTES User; +} TOKEN_USER, *PTOKEN_USER; + +typedef struct _SECURITY_CLIENT_CONTEXT { + SECURITY_QUALITY_OF_SERVICE SecurityQos; + PACCESS_TOKEN ClientToken; + BOOLEAN DirectlyAccessClientToken; + BOOLEAN DirectAccessEffectiveOnly; + BOOLEAN ServerIsRemote; + TOKEN_CONTROL ClientTokenControl; +} SECURITY_CLIENT_CONTEXT, *PSECURITY_CLIENT_CONTEXT; + +typedef struct _TUNNEL { + FAST_MUTEX Mutex; + PRTL_SPLAY_LINKS Cache; + LIST_ENTRY TimerQueue; + USHORT NumEntries; +} TUNNEL, *PTUNNEL; + +typedef struct _VACB { + PVOID BaseAddress; + PSHARED_CACHE_MAP SharedCacheMap; + union { + LARGE_INTEGER FileOffset; + USHORT ActiveCount; + } Overlay; + LIST_ENTRY LruList; +} VACB, *PVACB; + +typedef struct _VAD_HEADER { + PVOID StartVPN; + PVOID EndVPN; + PVAD_HEADER ParentLink; + PVAD_HEADER LeftLink; + PVAD_HEADER RightLink; + ULONG Flags; // LSB = CommitCharge + PVOID ControlArea; + PVOID FirstProtoPte; + PVOID LastPTE; + ULONG Unknown; + LIST_ENTRY Secured; +} VAD_HEADER, *PVAD_HEADER; + +NTKERNELAPI +BOOLEAN +CcCanIWrite ( + IN PFILE_OBJECT FileObject, + IN ULONG BytesToWrite, + IN BOOLEAN Wait, + IN BOOLEAN Retrying +); + +NTKERNELAPI +BOOLEAN +CcCopyRead ( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN BOOLEAN Wait, + OUT PVOID Buffer, + OUT PIO_STATUS_BLOCK IoStatus +); + +NTKERNELAPI +BOOLEAN +CcCopyWrite ( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN BOOLEAN Wait, + IN PVOID Buffer +); + +#define CcCopyWriteWontFlush(FO, FOFF, LEN) ((LEN) <= 0x10000) + +typedef VOID (*PCC_POST_DEFERRED_WRITE) ( + IN PVOID Context1, + IN PVOID Context2 +); + +NTKERNELAPI +VOID +CcDeferWrite ( + IN PFILE_OBJECT FileObject, + IN PCC_POST_DEFERRED_WRITE PostRoutine, + IN PVOID Context1, + IN PVOID Context2, + IN ULONG BytesToWrite, + IN BOOLEAN Retrying +); + +NTKERNELAPI +VOID +CcFastCopyRead ( + IN PFILE_OBJECT FileObject, + IN ULONG FileOffset, + IN ULONG Length, + IN ULONG PageCount, + OUT PVOID Buffer, + OUT PIO_STATUS_BLOCK IoStatus +); + +NTKERNELAPI +VOID +CcFastCopyWrite ( + IN PFILE_OBJECT FileObject, + IN ULONG FileOffset, + IN ULONG Length, + IN PVOID Buffer +); + +NTKERNELAPI +VOID +CcFlushCache ( + IN PSECTION_OBJECT_POINTERS SectionObjectPointer, + IN PLARGE_INTEGER FileOffset OPTIONAL, + IN ULONG Length, + OUT PIO_STATUS_BLOCK IoStatus OPTIONAL +); + +typedef VOID (*PDIRTY_PAGE_ROUTINE) ( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN PLARGE_INTEGER OldestLsn, + IN PLARGE_INTEGER NewestLsn, + IN PVOID Context1, + IN PVOID Context2 +); + +NTKERNELAPI +LARGE_INTEGER +CcGetDirtyPages ( + IN PVOID LogHandle, + IN PDIRTY_PAGE_ROUTINE DirtyPageRoutine, + IN PVOID Context1, + IN PVOID Context2 +); + +NTKERNELAPI +PFILE_OBJECT +CcGetFileObjectFromBcb ( + IN PVOID Bcb +); + +NTKERNELAPI +PFILE_OBJECT +CcGetFileObjectFromSectionPtrs ( + IN PSECTION_OBJECT_POINTERS SectionObjectPointer +); + +#define CcGetFileSizePointer(FO) ( \ + ((PLARGE_INTEGER)((FO)->SectionObjectPointer->SharedCacheMap) + 1) \ +) + +#if (VER_PRODUCTBUILD >= 2195) + +NTKERNELAPI +LARGE_INTEGER +CcGetFlushedValidData ( + IN PSECTION_OBJECT_POINTERS SectionObjectPointer, + IN BOOLEAN BcbListHeld +); + +#endif // (VER_PRODUCTBUILD >= 2195) + +NTKERNELAPI +LARGE_INTEGER +CcGetLsnForFileObject ( + IN PFILE_OBJECT FileObject, + OUT PLARGE_INTEGER OldestLsn OPTIONAL +); + +typedef BOOLEAN (*PACQUIRE_FOR_LAZY_WRITE) ( + IN PVOID Context, + IN BOOLEAN Wait +); + +typedef VOID (*PRELEASE_FROM_LAZY_WRITE) ( + IN PVOID Context +); + +typedef BOOLEAN (*PACQUIRE_FOR_READ_AHEAD) ( + IN PVOID Context, + IN BOOLEAN Wait +); + +typedef VOID (*PRELEASE_FROM_READ_AHEAD) ( + IN PVOID Context +); + +typedef struct _CACHE_MANAGER_CALLBACKS { + PACQUIRE_FOR_LAZY_WRITE AcquireForLazyWrite; + PRELEASE_FROM_LAZY_WRITE ReleaseFromLazyWrite; + PACQUIRE_FOR_READ_AHEAD AcquireForReadAhead; + PRELEASE_FROM_READ_AHEAD ReleaseFromReadAhead; +} CACHE_MANAGER_CALLBACKS, *PCACHE_MANAGER_CALLBACKS; + +NTKERNELAPI +VOID +CcInitializeCacheMap ( + IN PFILE_OBJECT FileObject, + IN PCC_FILE_SIZES FileSizes, + IN BOOLEAN PinAccess, + IN PCACHE_MANAGER_CALLBACKS Callbacks, + IN PVOID LazyWriteContext +); + +#define CcIsFileCached(FO) ( \ + ((FO)->SectionObjectPointer != NULL) && \ + (((PSECTION_OBJECT_POINTERS)(FO)->SectionObjectPointer)->SharedCacheMap != NULL) \ +) + +NTKERNELAPI +BOOLEAN +CcIsThereDirtyData ( + IN PVPB Vpb +); + +NTKERNELAPI +BOOLEAN +CcMapData ( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, +#if (VER_PRODUCTBUILD >= 2600) + IN ULONG Flags, +#else + IN BOOLEAN Wait, +#endif + OUT PVOID *Bcb, + OUT PVOID *Buffer +); + +NTKERNELAPI +VOID +CcMdlRead ( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + OUT PMDL *MdlChain, + OUT PIO_STATUS_BLOCK IoStatus +); + +NTKERNELAPI +VOID +CcMdlReadComplete ( + IN PFILE_OBJECT FileObject, + IN PMDL MdlChain +); + +#if (VER_PRODUCTBUILD >= 2600) + +NTKERNELAPI +VOID +CcMdlWriteAbort ( + IN PFILE_OBJECT FileObject, + IN PMDL MdlChain +); + +#endif + +NTKERNELAPI +VOID +CcMdlWriteComplete ( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN PMDL MdlChain +); + +NTKERNELAPI +BOOLEAN +CcPinMappedData ( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, +#if (VER_PRODUCTBUILD >= 2195) + IN ULONG Flags, +#else + IN BOOLEAN Wait, +#endif + IN OUT PVOID *Bcb +); + +NTKERNELAPI +BOOLEAN +CcPinRead ( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, +#if (VER_PRODUCTBUILD >= 2195) + IN ULONG Flags, +#else + IN BOOLEAN Wait, +#endif + OUT PVOID *Bcb, + OUT PVOID *Buffer +); + +NTKERNELAPI +VOID +CcPrepareMdlWrite ( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + OUT PMDL *MdlChain, + OUT PIO_STATUS_BLOCK IoStatus +); + +NTKERNELAPI +BOOLEAN +CcPreparePinWrite ( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN BOOLEAN Zero, +#if (VER_PRODUCTBUILD >= 2195) + IN ULONG Flags, +#else + IN BOOLEAN Wait, +#endif + OUT PVOID *Bcb, + OUT PVOID *Buffer +); + +NTKERNELAPI +BOOLEAN +CcPurgeCacheSection ( + IN PSECTION_OBJECT_POINTERS SectionObjectPointer, + IN PLARGE_INTEGER FileOffset OPTIONAL, + IN ULONG Length, + IN BOOLEAN UninitializeCacheMaps +); + +#define CcReadAhead(FO, FOFF, LEN) ( \ + if ((LEN) >= 256) { \ + CcScheduleReadAhead((FO), (FOFF), (LEN)); \ + } \ +) + +#if (VER_PRODUCTBUILD >= 2195) + +NTKERNELAPI +PVOID +CcRemapBcb ( + IN PVOID Bcb +); + +#endif // (VER_PRODUCTBUILD >= 2195) + +NTKERNELAPI +VOID +CcRepinBcb ( + IN PVOID Bcb +); + +NTKERNELAPI +VOID +CcScheduleReadAhead ( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length +); + +NTKERNELAPI +VOID +CcSetAdditionalCacheAttributes ( + IN PFILE_OBJECT FileObject, + IN BOOLEAN DisableReadAhead, + IN BOOLEAN DisableWriteBehind +); + +NTKERNELAPI +VOID +CcSetBcbOwnerPointer ( + IN PVOID Bcb, + IN PVOID OwnerPointer +); + +NTKERNELAPI +VOID +CcSetDirtyPageThreshold ( + IN PFILE_OBJECT FileObject, + IN ULONG DirtyPageThreshold +); + +NTKERNELAPI +VOID +CcSetDirtyPinnedData ( + IN PVOID BcbVoid, + IN PLARGE_INTEGER Lsn OPTIONAL +); + +NTKERNELAPI +VOID +CcSetFileSizes ( + IN PFILE_OBJECT FileObject, + IN PCC_FILE_SIZES FileSizes +); + +typedef VOID (*PFLUSH_TO_LSN) ( + IN PVOID LogHandle, + IN PLARGE_INTEGER Lsn +); + +NTKERNELAPI +VOID +CcSetLogHandleForFile ( + IN PFILE_OBJECT FileObject, + IN PVOID LogHandle, + IN PFLUSH_TO_LSN FlushToLsnRoutine +); + +NTKERNELAPI +VOID +CcSetReadAheadGranularity ( + IN PFILE_OBJECT FileObject, + IN ULONG Granularity // default: PAGE_SIZE + // allowed: 2^n * PAGE_SIZE +); + +NTKERNELAPI +BOOLEAN +CcUninitializeCacheMap ( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER TruncateSize OPTIONAL, + IN PCACHE_UNINITIALIZE_EVENT UninitializeCompleteEvent OPTIONAL +); + +NTKERNELAPI +VOID +CcUnpinData ( + IN PVOID Bcb +); + +NTKERNELAPI +VOID +CcUnpinDataForThread ( + IN PVOID Bcb, + IN ERESOURCE_THREAD ResourceThreadId +); + +NTKERNELAPI +VOID +CcUnpinRepinnedBcb ( + IN PVOID Bcb, + IN BOOLEAN WriteThrough, + OUT PIO_STATUS_BLOCK IoStatus +); + +#if (VER_PRODUCTBUILD >= 2195) + +NTKERNELAPI +NTSTATUS +CcWaitForCurrentLazyWriterActivity ( + VOID +); + +#endif // (VER_PRODUCTBUILD >= 2195) + +NTKERNELAPI +BOOLEAN +CcZeroData ( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER StartOffset, + IN PLARGE_INTEGER EndOffset, + IN BOOLEAN Wait +); + +NTKERNELAPI +VOID +ExDisableResourceBoostLite ( + IN PERESOURCE Resource +); + +NTKERNELAPI +ULONG +ExQueryPoolBlockSize ( + IN PVOID PoolBlock, + OUT PBOOLEAN QuotaCharged +); + +#define FlagOn(x, f) ((x) & (f)) + +#if (VER_PRODUCTBUILD >= 2195) + +NTKERNELAPI +VOID +FsRtlAcquireFileExclusive ( + IN PFILE_OBJECT FileObject +); + +#endif // (VER_PRODUCTBUILD >= 2195) + +NTKERNELAPI +BOOLEAN +FsRtlAddLargeMcbEntry ( + IN PLARGE_MCB Mcb, + IN LONGLONG Vbn, + IN LONGLONG Lbn, + IN LONGLONG SectorCount +); + +NTKERNELAPI +BOOLEAN +FsRtlAddMcbEntry ( + IN PMCB Mcb, + IN VBN Vbn, + IN LBN Lbn, + IN ULONG SectorCount +); + +NTKERNELAPI +VOID +FsRtlAddToTunnelCache ( + IN PTUNNEL Cache, + IN ULONGLONG DirectoryKey, + IN PUNICODE_STRING ShortName, + IN PUNICODE_STRING LongName, + IN BOOLEAN KeyByShortName, + IN ULONG DataLength, + IN PVOID Data +); + +#if (VER_PRODUCTBUILD >= 2195) + +PFILE_LOCK +FsRtlAllocateFileLock ( + IN PCOMPLETE_LOCK_IRP_ROUTINE CompleteLockIrpRoutine OPTIONAL, + IN PUNLOCK_ROUTINE UnlockRoutine OPTIONAL +); + +#endif // (VER_PRODUCTBUILD >= 2195) + +NTKERNELAPI +PVOID +FsRtlAllocatePool ( + IN POOL_TYPE PoolType, + IN ULONG NumberOfBytes +); + +NTKERNELAPI +PVOID +FsRtlAllocatePoolWithQuota ( + IN POOL_TYPE PoolType, + IN ULONG NumberOfBytes +); + +NTKERNELAPI +PVOID +FsRtlAllocatePoolWithQuotaTag ( + IN POOL_TYPE PoolType, + IN ULONG NumberOfBytes, + IN ULONG Tag +); + +NTKERNELAPI +PVOID +FsRtlAllocatePoolWithTag ( + IN POOL_TYPE PoolType, + IN ULONG NumberOfBytes, + IN ULONG Tag +); + +NTKERNELAPI +PVOID +FsRtlAllocateResource ( + VOID +); + +NTKERNELAPI +BOOLEAN +FsRtlAreNamesEqual ( + IN PUNICODE_STRING Name1, + IN PUNICODE_STRING Name2, + IN BOOLEAN IgnoreCase, + IN PWCHAR UpcaseTable OPTIONAL +); + +#define FsRtlAreThereCurrentFileLocks(FL) ( \ + ((FL)->FastIoIsQuestionable) \ +) + +NTKERNELAPI +NTSTATUS +FsRtlBalanceReads ( + IN PDEVICE_OBJECT TargetDevice +); + +/* + FsRtlCheckLockForReadAccess: + + All this really does is pick out the lock parameters from the irp (io stack + location?), get IoGetRequestorProcess, and pass values on to + FsRtlFastCheckLockForRead. +*/ +NTKERNELAPI +BOOLEAN +FsRtlCheckLockForReadAccess ( + IN PFILE_LOCK FileLock, + IN PIRP Irp +); + +/* + FsRtlCheckLockForWriteAccess: + + All this really does is pick out the lock parameters from the irp (io stack + location?), get IoGetRequestorProcess, and pass values on to + FsRtlFastCheckLockForWrite. +*/ +NTKERNELAPI +BOOLEAN +FsRtlCheckLockForWriteAccess ( + IN PFILE_LOCK FileLock, + IN PIRP Irp +); + +typedef +VOID +(*POPLOCK_WAIT_COMPLETE_ROUTINE) ( + IN PVOID Context, + IN PIRP Irp +); + +typedef +VOID +(*POPLOCK_FS_PREPOST_IRP) ( + IN PVOID Context, + IN PIRP Irp +); + +NTKERNELAPI +NTSTATUS +FsRtlCheckOplock ( + IN POPLOCK Oplock, + IN PIRP Irp, + IN PVOID Context, + IN POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine OPTIONAL, + IN POPLOCK_FS_PREPOST_IRP PostIrpRoutine OPTIONAL +); + +NTKERNELAPI +BOOLEAN +FsRtlCopyRead ( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN BOOLEAN Wait, + IN ULONG LockKey, + OUT PVOID Buffer, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject +); + +NTKERNELAPI +BOOLEAN +FsRtlCopyWrite ( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN BOOLEAN Wait, + IN ULONG LockKey, + IN PVOID Buffer, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject +); + +NTKERNELAPI +BOOLEAN +FsRtlCurrentBatchOplock ( + IN POPLOCK Oplock +); + +NTKERNELAPI +VOID +FsRtlDeleteKeyFromTunnelCache ( + IN PTUNNEL Cache, + IN ULONGLONG DirectoryKey +); + +NTKERNELAPI +VOID +FsRtlDeleteTunnelCache ( + IN PTUNNEL Cache +); + +NTKERNELAPI +VOID +FsRtlDeregisterUncProvider ( + IN HANDLE Handle +); + +NTKERNELAPI +VOID +FsRtlDissectDbcs ( + IN ANSI_STRING InputName, + OUT PANSI_STRING FirstPart, + OUT PANSI_STRING RemainingPart +); + +NTKERNELAPI +VOID +FsRtlDissectName ( + IN UNICODE_STRING Path, + OUT PUNICODE_STRING FirstName, + OUT PUNICODE_STRING RemainingName +); + +NTKERNELAPI +BOOLEAN +FsRtlDoesDbcsContainWildCards ( + IN PANSI_STRING Name +); + +NTKERNELAPI +BOOLEAN +FsRtlDoesNameContainWildCards ( + IN PUNICODE_STRING Name +); + +#define FsRtlEnterFileSystem KeEnterCriticalRegion + +#define FsRtlExitFileSystem KeLeaveCriticalRegion + +NTKERNELAPI +BOOLEAN +FsRtlFastCheckLockForRead ( + IN PFILE_LOCK FileLock, + IN PLARGE_INTEGER FileOffset, + IN PLARGE_INTEGER Length, + IN ULONG Key, + IN PFILE_OBJECT FileObject, + IN PEPROCESS Process +); + +NTKERNELAPI +BOOLEAN +FsRtlFastCheckLockForWrite ( + IN PFILE_LOCK FileLock, + IN PLARGE_INTEGER FileOffset, + IN PLARGE_INTEGER Length, + IN ULONG Key, + IN PFILE_OBJECT FileObject, + IN PEPROCESS Process +); + +#define FsRtlFastLock(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11) ( \ + FsRtlPrivateLock(A1, A2, A3, A4, A5, A6, A7, A8, A9, NULL, A10, A11) \ +) + +NTKERNELAPI +NTSTATUS +FsRtlFastUnlockAll ( + IN PFILE_LOCK FileLock, + IN PFILE_OBJECT FileObject, + IN PEPROCESS Process, + IN PVOID Context OPTIONAL +); +//ret: STATUS_RANGE_NOT_LOCKED + +NTKERNELAPI +NTSTATUS +FsRtlFastUnlockAllByKey ( + IN PFILE_LOCK FileLock, + IN PFILE_OBJECT FileObject, + IN PEPROCESS Process, + IN ULONG Key, + IN PVOID Context OPTIONAL +); +//ret: STATUS_RANGE_NOT_LOCKED + +NTKERNELAPI +NTSTATUS +FsRtlFastUnlockSingle ( + IN PFILE_LOCK FileLock, + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN PLARGE_INTEGER Length, + IN PEPROCESS Process, + IN ULONG Key, + IN PVOID Context OPTIONAL, + IN BOOLEAN AlreadySynchronized +); +//ret: STATUS_RANGE_NOT_LOCKED + +NTKERNELAPI +BOOLEAN +FsRtlFindInTunnelCache ( + IN PTUNNEL Cache, + IN ULONGLONG DirectoryKey, + IN PUNICODE_STRING Name, + OUT PUNICODE_STRING ShortName, + OUT PUNICODE_STRING LongName, + IN OUT PULONG DataLength, + OUT PVOID Data +); + +#if (VER_PRODUCTBUILD >= 2195) + +VOID +FsRtlFreeFileLock ( + IN PFILE_LOCK FileLock +); + +#endif // (VER_PRODUCTBUILD >= 2195) + +NTKERNELAPI +NTSTATUS +FsRtlGetFileSize ( + IN PFILE_OBJECT FileObject, + IN OUT PLARGE_INTEGER FileSize +); + +/* + FsRtlGetNextFileLock: + + ret: NULL if no more locks + + Internals: + FsRtlGetNextFileLock uses FileLock->LastReturnedLockInfo and + FileLock->LastReturnedLock as storage. + LastReturnedLock is a pointer to the 'raw' lock inkl. double linked + list, and FsRtlGetNextFileLock needs this to get next lock on subsequent + calls with Restart = FALSE. +*/ +NTKERNELAPI +PFILE_LOCK_INFO +FsRtlGetNextFileLock ( + IN PFILE_LOCK FileLock, + IN BOOLEAN Restart +); + +NTKERNELAPI +BOOLEAN +FsRtlGetNextLargeMcbEntry ( + IN PLARGE_MCB Mcb, + IN ULONG RunIndex, + OUT PLONGLONG Vbn, + OUT PLONGLONG Lbn, + OUT PLONGLONG SectorCount +); + +NTKERNELAPI +BOOLEAN +FsRtlGetNextMcbEntry ( + IN PMCB Mcb, + IN ULONG RunIndex, + OUT PVBN Vbn, + OUT PLBN Lbn, + OUT PULONG SectorCount +); + +#if (VER_PRODUCTBUILD >= 2600) + +NTKERNELAPI +VOID +FsRtlIncrementCcFastReadNotPossible ( + VOID +); + +NTKERNELAPI +VOID +FsRtlIncrementCcFastReadNoWait ( + VOID +); + +NTKERNELAPI +VOID +FsRtlIncrementCcFastReadResourceMiss ( + VOID +); + +NTKERNELAPI +VOID +FsRtlIncrementCcFastReadWait ( + VOID +); + +#endif // (VER_PRODUCTBUILD >= 2600) + +NTKERNELAPI +VOID +FsRtlInitializeFileLock ( + IN PFILE_LOCK FileLock, + IN PCOMPLETE_LOCK_IRP_ROUTINE CompleteLockIrpRoutine OPTIONAL, + IN PUNLOCK_ROUTINE UnlockRoutine OPTIONAL +); + +NTKERNELAPI +VOID +FsRtlInitializeLargeMcb ( + IN PLARGE_MCB Mcb, + IN POOL_TYPE PoolType +); + +NTKERNELAPI +VOID +FsRtlInitializeMcb ( + IN PMCB Mcb, + IN POOL_TYPE PoolType +); + +NTKERNELAPI +VOID +FsRtlInitializeOplock ( + IN OUT POPLOCK Oplock +); + +NTKERNELAPI +VOID +FsRtlInitializeTunnelCache ( + IN PTUNNEL Cache +); + +NTKERNELAPI +BOOLEAN +FsRtlIsDbcsInExpression ( + IN PANSI_STRING Expression, + IN PANSI_STRING Name +); + +NTKERNELAPI +BOOLEAN +FsRtlIsFatDbcsLegal ( + IN ANSI_STRING DbcsName, + IN BOOLEAN WildCardsPermissible, + IN BOOLEAN PathNamePermissible, + IN BOOLEAN LeadingBackslashPermissible +); + +NTKERNELAPI +BOOLEAN +FsRtlIsHpfsDbcsLegal ( + IN ANSI_STRING DbcsName, + IN BOOLEAN WildCardsPermissible, + IN BOOLEAN PathNamePermissible, + IN BOOLEAN LeadingBackslashPermissible +); + +NTKERNELAPI +BOOLEAN +FsRtlIsNameInExpression ( + IN PUNICODE_STRING Expression, + IN PUNICODE_STRING Name, + IN BOOLEAN IgnoreCase, + IN PWCHAR UpcaseTable OPTIONAL +); + +NTKERNELAPI +BOOLEAN +FsRtlIsNtstatusExpected ( + IN NTSTATUS Ntstatus +); + +#if (VER_PRODUCTBUILD >= 2600) + +NTKERNELAPI +BOOLEAN +FsRtlIsPagingFile ( + IN PFILE_OBJECT FileObject +); + +#endif // (VER_PRODUCTBUILD >= 2600) + +NTKERNELAPI +BOOLEAN +FsRtlIsTotalDeviceFailure ( + IN NTSTATUS Status +); + +#define FsRtlIsUnicodeCharacterWild(C) ( \ + (((C) >= 0x40) ? \ + FALSE : \ + FlagOn((*FsRtlLegalAnsiCharacterArray)[(C)], FSRTL_WILD_CHARACTER )) \ +) + +NTKERNELAPI +BOOLEAN +FsRtlLookupLargeMcbEntry ( + IN PLARGE_MCB Mcb, + IN LONGLONG Vbn, + OUT PLONGLONG Lbn OPTIONAL, + OUT PLONGLONG SectorCountFromLbn OPTIONAL, + OUT PLONGLONG StartingLbn OPTIONAL, + OUT PLONGLONG SectorCountFromStartingLbn OPTIONAL, + OUT PULONG Index OPTIONAL +); + +NTKERNELAPI +BOOLEAN +FsRtlLookupLastLargeMcbEntry ( + IN PLARGE_MCB Mcb, + OUT PLONGLONG Vbn, + OUT PLONGLONG Lbn +); + +#if (VER_PRODUCTBUILD >= 2195) + +NTKERNELAPI +BOOLEAN +FsRtlLookupLastLargeMcbEntryAndIndex ( + IN PLARGE_MCB OpaqueMcb, + OUT PLONGLONG LargeVbn, + OUT PLONGLONG LargeLbn, + OUT PULONG Index +); + +#endif // (VER_PRODUCTBUILD >= 2195) + +NTKERNELAPI +BOOLEAN +FsRtlLookupLastMcbEntry ( + IN PMCB Mcb, + OUT PVBN Vbn, + OUT PLBN Lbn +); + +NTKERNELAPI +BOOLEAN +FsRtlLookupMcbEntry ( + IN PMCB Mcb, + IN VBN Vbn, + OUT PLBN Lbn, + OUT PULONG SectorCount OPTIONAL, + OUT PULONG Index +); + +NTKERNELAPI +BOOLEAN +FsRtlMdlReadComplete ( + IN PFILE_OBJECT FileObject, + IN PMDL MdlChain +); + +NTKERNELAPI +BOOLEAN +FsRtlMdlReadCompleteDev ( + IN PFILE_OBJECT FileObject, + IN PMDL MdlChain, + IN PDEVICE_OBJECT DeviceObject +); + +#if (VER_PRODUCTBUILD >= 1381) + +NTKERNELAPI +BOOLEAN +FsRtlMdlReadDev ( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN ULONG LockKey, + OUT PMDL *MdlChain, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject +); + +#endif // (VER_PRODUCTBUILD >= 1381) + +NTKERNELAPI +BOOLEAN +FsRtlMdlWriteComplete ( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN PMDL MdlChain +); + +NTKERNELAPI +BOOLEAN +FsRtlMdlWriteCompleteDev ( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN PMDL MdlChain, + IN PDEVICE_OBJECT DeviceObject +); + +NTKERNELAPI +NTSTATUS +FsRtlNormalizeNtstatus ( + IN NTSTATUS Exception, + IN NTSTATUS GenericException +); + +NTKERNELAPI +VOID +FsRtlNotifyChangeDirectory ( + IN PNOTIFY_SYNC NotifySync, + IN PVOID FsContext, + IN PSTRING FullDirectoryName, + IN PLIST_ENTRY NotifyList, + IN BOOLEAN WatchTree, + IN ULONG CompletionFilter, + IN PIRP NotifyIrp +); + +NTKERNELAPI +VOID +FsRtlNotifyCleanup ( + IN PNOTIFY_SYNC NotifySync, + IN PLIST_ENTRY NotifyList, + IN PVOID FsContext +); + +typedef BOOLEAN (*PCHECK_FOR_TRAVERSE_ACCESS) ( + IN PVOID NotifyContext, + IN PVOID TargetContext, + IN PSECURITY_SUBJECT_CONTEXT SubjectContext +); + +#if (VER_PRODUCTBUILD >= 2600) + +typedef BOOLEAN (*PFILTER_REPORT_CHANGE) ( + IN PVOID NotifyContext, + IN PVOID FilterContext +); + +NTKERNELAPI +VOID +FsRtlNotifyFilterChangeDirectory ( + IN PNOTIFY_SYNC NotifySync, + IN PLIST_ENTRY NotifyList, + IN PVOID FsContext, + IN PSTRING FullDirectoryName, + IN BOOLEAN WatchTree, + IN BOOLEAN IgnoreBuffer, + IN ULONG CompletionFilter, + IN PIRP NotifyIrp, + IN PCHECK_FOR_TRAVERSE_ACCESS TraverseCallback OPTIONAL, + IN PSECURITY_SUBJECT_CONTEXT SubjectContext OPTIONAL, + IN PFILTER_REPORT_CHANGE FilterCallback OPTIONAL +); + +NTKERNELAPI +VOID +FsRtlNotifyFilterReportChange ( + IN PNOTIFY_SYNC NotifySync, + IN PLIST_ENTRY NotifyList, + IN PSTRING FullTargetName, + IN USHORT TargetNameOffset, + IN PSTRING StreamName OPTIONAL, + IN PSTRING NormalizedParentName OPTIONAL, + IN ULONG FilterMatch, + IN ULONG Action, + IN PVOID TargetContext, + IN PVOID FilterContext +); + +#endif // (VER_PRODUCTBUILD >= 2600) + +NTKERNELAPI +VOID +FsRtlNotifyFullChangeDirectory ( + IN PNOTIFY_SYNC NotifySync, + IN PLIST_ENTRY NotifyList, + IN PVOID FsContext, + IN PSTRING FullDirectoryName, + IN BOOLEAN WatchTree, + IN BOOLEAN IgnoreBuffer, + IN ULONG CompletionFilter, + IN PIRP NotifyIrp, + IN PCHECK_FOR_TRAVERSE_ACCESS TraverseCallback OPTIONAL, + IN PSECURITY_SUBJECT_CONTEXT SubjectContext OPTIONAL +); + +NTKERNELAPI +VOID +FsRtlNotifyFullReportChange ( + IN PNOTIFY_SYNC NotifySync, + IN PLIST_ENTRY NotifyList, + IN PSTRING FullTargetName, + IN USHORT TargetNameOffset, + IN PSTRING StreamName OPTIONAL, + IN PSTRING NormalizedParentName OPTIONAL, + IN ULONG FilterMatch, + IN ULONG Action, + IN PVOID TargetContext +); + +NTKERNELAPI +VOID +FsRtlNotifyInitializeSync ( + IN PNOTIFY_SYNC *NotifySync +); + +NTKERNELAPI +VOID +FsRtlNotifyReportChange ( + IN PNOTIFY_SYNC NotifySync, + IN PLIST_ENTRY NotifyList, + IN PSTRING FullTargetName, + IN PUSHORT FileNamePartLength, + IN ULONG FilterMatch +); + +NTKERNELAPI +VOID +FsRtlNotifyUninitializeSync ( + IN PNOTIFY_SYNC *NotifySync +); + +#if (VER_PRODUCTBUILD >= 2195) + +NTKERNELAPI +NTSTATUS +FsRtlNotifyVolumeEvent ( + IN PFILE_OBJECT FileObject, + IN ULONG EventCode +); + +#endif // (VER_PRODUCTBUILD >= 2195) + +NTKERNELAPI +ULONG +FsRtlNumberOfRunsInLargeMcb ( + IN PLARGE_MCB Mcb +); + +NTKERNELAPI +ULONG +FsRtlNumberOfRunsInMcb ( + IN PMCB Mcb +); + +NTKERNELAPI +NTSTATUS +FsRtlOplockFsctrl ( + IN POPLOCK Oplock, + IN PIRP Irp, + IN ULONG OpenCount +); + +NTKERNELAPI +BOOLEAN +FsRtlOplockIsFastIoPossible ( + IN POPLOCK Oplock +); + +typedef +VOID +(*PFSRTL_STACK_OVERFLOW_ROUTINE) ( + IN PVOID Context, + IN PKEVENT Event + ); + +NTKERNELAPI +VOID +FsRtlPostPagingFileStackOverflow ( + IN PVOID Context, + IN PKEVENT Event, + IN PFSRTL_STACK_OVERFLOW_ROUTINE StackOverflowRoutine +); + +NTKERNELAPI +VOID +FsRtlPostStackOverflow ( + IN PVOID Context, + IN PKEVENT Event, + IN PFSRTL_STACK_OVERFLOW_ROUTINE StackOverflowRoutine +); + +#if (VER_PRODUCTBUILD >= 1381) + +NTKERNELAPI +BOOLEAN +FsRtlPrepareMdlWriteDev ( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN ULONG LockKey, + OUT PMDL *MdlChain, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject +); + +#endif // (VER_PRODUCTBUILD >= 1381) + +/* + FsRtlPrivateLock: + + ret: IoStatus->Status: STATUS_PENDING, STATUS_LOCK_NOT_GRANTED + + Internals: + -Calls IoCompleteRequest if Irp + -Uses exception handling / ExRaiseStatus with STATUS_INSUFFICIENT_RESOURCES +*/ +NTKERNELAPI +BOOLEAN +FsRtlPrivateLock ( + IN PFILE_LOCK FileLock, + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN PLARGE_INTEGER Length, + IN PEPROCESS Process, + IN ULONG Key, + IN BOOLEAN FailImmediately, + IN BOOLEAN ExclusiveLock, + OUT PIO_STATUS_BLOCK IoStatus, + IN PIRP Irp OPTIONAL, + IN PVOID Context, + IN BOOLEAN AlreadySynchronized +); + +/* + FsRtlProcessFileLock: + + ret: + -STATUS_INVALID_DEVICE_REQUEST + -STATUS_RANGE_NOT_LOCKED from unlock routines. + -STATUS_PENDING, STATUS_LOCK_NOT_GRANTED from FsRtlPrivateLock + (redirected IoStatus->Status). + + Internals: + -switch ( Irp->CurrentStackLocation->MinorFunction ) + lock: return FsRtlPrivateLock; + unlocksingle: return FsRtlFastUnlockSingle; + unlockall: return FsRtlFastUnlockAll; + unlockallbykey: return FsRtlFastUnlockAllByKey; + default: IofCompleteRequest with STATUS_INVALID_DEVICE_REQUEST; + return STATUS_INVALID_DEVICE_REQUEST; + + -'AllwaysZero' is passed thru as 'AllwaysZero' to lock / unlock routines. + -'Irp' is passet thru as 'Irp' to FsRtlPrivateLock. +*/ +NTKERNELAPI +NTSTATUS +FsRtlProcessFileLock ( + IN PFILE_LOCK FileLock, + IN PIRP Irp, + IN PVOID Context OPTIONAL +); + +NTKERNELAPI +NTSTATUS +FsRtlRegisterUncProvider ( + IN OUT PHANDLE MupHandle, + IN PUNICODE_STRING RedirectorDeviceName, + IN BOOLEAN MailslotsSupported +); + +#if (VER_PRODUCTBUILD >= 2195) + +NTKERNELAPI +VOID +FsRtlReleaseFile ( + IN PFILE_OBJECT FileObject +); + +#endif // (VER_PRODUCTBUILD >= 2195) + +NTKERNELAPI +VOID +FsRtlRemoveLargeMcbEntry ( + IN PLARGE_MCB Mcb, + IN LONGLONG Vbn, + IN LONGLONG SectorCount +); + +NTKERNELAPI +VOID +FsRtlRemoveMcbEntry ( + IN PMCB Mcb, + IN VBN Vbn, + IN ULONG SectorCount +); + +#if (VER_PRODUCTBUILD >= 2195) + +NTKERNELAPI +VOID +FsRtlResetLargeMcb ( + IN PLARGE_MCB Mcb, + IN BOOLEAN SelfSynchronized +); + +#endif // (VER_PRODUCTBUILD >= 2195) + +#if (VER_PRODUCTBUILD >= 2600) + +#define FsRtlSetupAdvancedHeader( _advhdr, _fmutx ) \ +{ \ + SetFlag( (_advhdr)->Flags, FSRTL_FLAG_ADVANCED_HEADER ); \ + SetFlag( (_advhdr)->Flags2, FSRTL_FLAG2_SUPPORTS_FILTER_CONTEXTS ); \ + (_advhdr)->Version = FSRTL_FCB_HEADER_V1; \ + InitializeListHead( &(_advhdr)->FilterContexts ); \ + if ((_fmutx) != NULL) { \ + (_advhdr)->FastMutex = (_fmutx); \ + } \ + *((PULONG_PTR)(&(_advhdr)->PushLock)) = 0; \ + (_advhdr)->FileContextSupportPointer = NULL; \ +} + +#endif // (VER_PRODUCTBUILD >= 2600) + +NTKERNELAPI +BOOLEAN +FsRtlSplitLargeMcb ( + IN PLARGE_MCB Mcb, + IN LONGLONG Vbn, + IN LONGLONG Amount +); + +#if (VER_PRODUCTBUILD >= 2600) + +NTKERNELAPI +VOID +FsRtlTeardownPerFileContexts ( + IN PVOID *PerFileContextPointer +); + +NTKERNELAPI +VOID +FsRtlTeardownPerStreamContexts ( + IN PFSRTL_ADVANCED_FCB_HEADER AdvancedHeader +); + +#endif // (VER_PRODUCTBUILD >= 2600) + +NTKERNELAPI +VOID +FsRtlTruncateLargeMcb ( + IN PLARGE_MCB Mcb, + IN LONGLONG Vbn +); + +NTKERNELAPI +VOID +FsRtlTruncateMcb ( + IN PMCB Mcb, + IN VBN Vbn +); + +NTKERNELAPI +VOID +FsRtlUninitializeFileLock ( + IN PFILE_LOCK FileLock +); + +NTKERNELAPI +VOID +FsRtlUninitializeLargeMcb ( + IN PLARGE_MCB Mcb +); + +NTKERNELAPI +VOID +FsRtlUninitializeMcb ( + IN PMCB Mcb +); + +NTKERNELAPI +VOID +FsRtlUninitializeOplock ( + IN OUT POPLOCK Oplock +); + +// +// If using HalDisplayString during boot on Windows 2000 or later you must +// first call InbvEnableDisplayString. +// +NTSYSAPI +VOID +NTAPI +HalDisplayString ( + IN PCHAR String +); + +NTSYSAPI +VOID +NTAPI +HalQueryRealTimeClock ( + IN OUT PTIME_FIELDS TimeFields +); + +NTSYSAPI +VOID +NTAPI +HalSetRealTimeClock ( + IN PTIME_FIELDS TimeFields +); + +#if (VER_PRODUCTBUILD >= 2195) + +NTKERNELAPI +VOID +InbvAcquireDisplayOwnership ( + VOID +); + +NTKERNELAPI +BOOLEAN +InbvCheckDisplayOwnership ( + VOID +); + +NTKERNELAPI +BOOLEAN +InbvDisplayString ( + IN PCHAR String +); + +NTKERNELAPI +VOID +InbvEnableBootDriver ( + IN BOOLEAN Enable +); + +NTKERNELAPI +BOOLEAN +InbvEnableDisplayString ( + IN BOOLEAN Enable +); + +NTKERNELAPI +VOID +InbvInstallDisplayStringFilter ( + IN PVOID Unknown +); + +NTKERNELAPI +BOOLEAN +InbvIsBootDriverInstalled ( + VOID +); + +NTKERNELAPI +VOID +InbvNotifyDisplayOwnershipLost ( + IN PVOID Callback +); + +NTKERNELAPI +BOOLEAN +InbvResetDisplay ( + VOID +); + +NTKERNELAPI +VOID +InbvSetScrollRegion ( + IN ULONG Left, + IN ULONG Top, + IN ULONG Width, + IN ULONG Height +); + +NTKERNELAPI +VOID +InbvSetTextColor ( + IN ULONG Color +); + +NTKERNELAPI +VOID +InbvSolidColorFill ( + IN ULONG Left, + IN ULONG Top, + IN ULONG Width, + IN ULONG Height, + IN ULONG Color +); + +#endif // (VER_PRODUCTBUILD >= 2195) + +#define InitializeMessageHeader(m, l, t) { \ + (m)->Length = (USHORT)(l); \ + (m)->DataLength = (USHORT)(l - sizeof( LPC_MESSAGE )); \ + (m)->MessageType = (USHORT)(t); \ + (m)->DataInfoOffset = 0; \ +} + +NTKERNELAPI +VOID +IoAcquireVpbSpinLock ( + OUT PKIRQL Irql +); + +#if (VER_PRODUCTBUILD >= 2600) + +NTKERNELAPI +NTSTATUS +IoAttachDeviceToDeviceStackSafe ( + IN PDEVICE_OBJECT SourceDevice, + IN PDEVICE_OBJECT TargetDevice, + OUT PDEVICE_OBJECT *AttachedToDeviceObject +); + +#endif // (VER_PRODUCTBUILD >= 2600) + +NTKERNELAPI +NTSTATUS +IoCheckDesiredAccess ( + IN OUT PACCESS_MASK DesiredAccess, + IN ACCESS_MASK GrantedAccess +); + +NTKERNELAPI +NTSTATUS +IoCheckEaBufferValidity ( + IN PFILE_FULL_EA_INFORMATION EaBuffer, + IN ULONG EaLength, + OUT PULONG ErrorOffset +); + +NTKERNELAPI +NTSTATUS +IoCheckFunctionAccess ( + IN ACCESS_MASK GrantedAccess, + IN UCHAR MajorFunction, + IN UCHAR MinorFunction, + IN ULONG IoControlCode, + IN PFILE_INFORMATION_CLASS FileInformationClass OPTIONAL, + IN PFS_INFORMATION_CLASS FsInformationClass OPTIONAL +); + +#if (VER_PRODUCTBUILD >= 2195) + +NTKERNELAPI +NTSTATUS +IoCheckQuerySetFileInformation ( + IN FILE_INFORMATION_CLASS FileInformationClass, + IN ULONG Length, + IN BOOLEAN SetOperation +); + +NTKERNELAPI +NTSTATUS +IoCheckQuerySetVolumeInformation ( + IN FS_INFORMATION_CLASS FsInformationClass, + IN ULONG Length, + IN BOOLEAN SetOperation +); + +NTKERNELAPI +NTSTATUS +IoCheckQuotaBufferValidity ( + IN PFILE_QUOTA_INFORMATION QuotaBuffer, + IN ULONG QuotaLength, + OUT PULONG ErrorOffset +); + +#endif // (VER_PRODUCTBUILD >= 2195) + +#if (VER_PRODUCTBUILD >= 2600) + +NTKERNELAPI +NTSTATUS +IoCreateFileSpecifyDeviceObjectHint ( + OUT PHANDLE FileHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN PLARGE_INTEGER AllocationSize OPTIONAL, + IN ULONG FileAttributes, + IN ULONG ShareAccess, + IN ULONG Disposition, + IN ULONG CreateOptions, + IN PVOID EaBuffer OPTIONAL, + IN ULONG EaLength, + IN CREATE_FILE_TYPE CreateFileType, + IN PVOID ExtraCreateParameters OPTIONAL, + IN ULONG Options, + IN PVOID DeviceObject +); + +#endif // (VER_PRODUCTBUILD >= 2600) + +NTKERNELAPI +PFILE_OBJECT +IoCreateStreamFileObject ( + IN PFILE_OBJECT FileObject OPTIONAL, + IN PDEVICE_OBJECT DeviceObject OPTIONAL +); + +#if (VER_PRODUCTBUILD >= 2600) + +NTKERNELAPI +PFILE_OBJECT +IoCreateStreamFileObjectEx ( + IN PFILE_OBJECT FileObject OPTIONAL, + IN PDEVICE_OBJECT DeviceObject OPTIONAL, + OUT PHANDLE FileObjectHandle OPTIONAL +); + +#endif // (VER_PRODUCTBUILD >= 2600) + +#if (VER_PRODUCTBUILD >= 2195) + +NTKERNELAPI +PFILE_OBJECT +IoCreateStreamFileObjectLite ( + IN PFILE_OBJECT FileObject OPTIONAL, + IN PDEVICE_OBJECT DeviceObject OPTIONAL +); + +#endif // (VER_PRODUCTBUILD >= 2195) + +#if (VER_PRODUCTBUILD >= 2600) + +NTKERNELAPI +NTSTATUS +IoEnumerateDeviceObjectList ( + IN PDRIVER_OBJECT DriverObject, + IN PDEVICE_OBJECT *DeviceObjectList, + IN ULONG DeviceObjectListSize, + OUT PULONG ActualNumberDeviceObjects +); + +#endif // (VER_PRODUCTBUILD >= 2600) + +NTKERNELAPI +BOOLEAN +IoFastQueryNetworkAttributes ( + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN ACCESS_MASK DesiredAccess, + IN ULONG OpenOptions, + OUT PIO_STATUS_BLOCK IoStatus, + OUT PFILE_NETWORK_OPEN_INFORMATION Buffer +); + +NTKERNELAPI +PDEVICE_OBJECT +IoGetAttachedDevice ( + IN PDEVICE_OBJECT DeviceObject +); + +NTKERNELAPI +PDEVICE_OBJECT +IoGetBaseFileSystemDeviceObject ( + IN PFILE_OBJECT FileObject +); + +#if (VER_PRODUCTBUILD >= 2600) + +NTKERNELAPI +PDEVICE_OBJECT +IoGetDeviceAttachmentBaseRef ( + IN PDEVICE_OBJECT DeviceObject +); + +NTKERNELAPI +NTSTATUS +IoGetDiskDeviceObject ( + IN PDEVICE_OBJECT FileSystemDeviceObject, + OUT PDEVICE_OBJECT *DiskDeviceObject +); + +NTKERNELAPI +PDEVICE_OBJECT +IoGetLowerDeviceObject ( + IN PDEVICE_OBJECT DeviceObject +); + +#endif // (VER_PRODUCTBUILD >= 2600) + +NTKERNELAPI +PEPROCESS +IoGetRequestorProcess ( + IN PIRP Irp +); + +#if (VER_PRODUCTBUILD >= 2195) + +NTKERNELAPI +ULONG +IoGetRequestorProcessId ( + IN PIRP Irp +); + +#endif // (VER_PRODUCTBUILD >= 2195) + +NTKERNELAPI +PIRP +IoGetTopLevelIrp ( + VOID +); + +#define IoIsFileOpenedExclusively(FileObject) ( \ + (BOOLEAN) !( \ + (FileObject)->SharedRead || \ + (FileObject)->SharedWrite || \ + (FileObject)->SharedDelete \ + ) \ +) + +#if (VER_PRODUCTBUILD >= 2195) + +NTKERNELAPI +BOOLEAN +IoIsFileOriginRemote ( + IN PFILE_OBJECT FileObject +); + +#endif // (VER_PRODUCTBUILD >= 2195) + +NTKERNELAPI +BOOLEAN +IoIsOperationSynchronous ( + IN PIRP Irp +); + +NTKERNELAPI +BOOLEAN +IoIsSystemThread ( + IN PETHREAD Thread +); + +#if (VER_PRODUCTBUILD >= 2195) + +NTKERNELAPI +BOOLEAN +IoIsValidNameGraftingBuffer ( + IN PIRP Irp, + IN PREPARSE_DATA_BUFFER ReparseBuffer +); + +#endif // (VER_PRODUCTBUILD >= 2195) + +NTKERNELAPI +NTSTATUS +IoPageRead ( + IN PFILE_OBJECT FileObject, + IN PMDL Mdl, + IN PLARGE_INTEGER Offset, + IN PKEVENT Event, + OUT PIO_STATUS_BLOCK IoStatusBlock +); + +#if (VER_PRODUCTBUILD >= 2600) + +NTKERNELAPI +NTSTATUS +IoQueryFileDosDeviceName ( + IN PFILE_OBJECT FileObject, + OUT POBJECT_NAME_INFORMATION *ObjectNameInformation +); + +#endif // (VER_PRODUCTBUILD >= 2600) + +NTKERNELAPI +NTSTATUS +IoQueryFileInformation ( + IN PFILE_OBJECT FileObject, + IN FILE_INFORMATION_CLASS FileInformationClass, + IN ULONG Length, + OUT PVOID FileInformation, + OUT PULONG ReturnedLength +); + +NTKERNELAPI +NTSTATUS +IoQueryVolumeInformation ( + IN PFILE_OBJECT FileObject, + IN FS_INFORMATION_CLASS FsInformationClass, + IN ULONG Length, + OUT PVOID FsInformation, + OUT PULONG ReturnedLength +); + +#if (VER_PRODUCTBUILD >= 1381) + +NTKERNELAPI +VOID +IoQueueThreadIrp ( + IN PIRP Irp +); + +#endif // (VER_PRODUCTBUILD >= 1381) + +NTKERNELAPI +VOID +IoRegisterFileSystem ( + IN OUT PDEVICE_OBJECT DeviceObject +); + +#if (VER_PRODUCTBUILD >= 1381) + +typedef VOID (*PDRIVER_FS_NOTIFICATION) ( + IN PDEVICE_OBJECT DeviceObject, + IN BOOLEAN DriverActive +); + +NTKERNELAPI +NTSTATUS +IoRegisterFsRegistrationChange ( + IN PDRIVER_OBJECT DriverObject, + IN PDRIVER_FS_NOTIFICATION DriverNotificationRoutine +); + +#endif // (VER_PRODUCTBUILD >= 1381) + +NTKERNELAPI +VOID +IoReleaseVpbSpinLock ( + IN KIRQL Irql +); + +NTKERNELAPI +VOID +IoSetDeviceToVerify ( + IN PETHREAD Thread, + IN PDEVICE_OBJECT DeviceObject +); + +#if (VER_PRODUCTBUILD >= 2195) + +NTKERNELAPI +NTSTATUS +IoSetFileOrigin ( + IN PFILE_OBJECT FileObject, + IN BOOLEAN Remote +); + +#endif // (VER_PRODUCTBUILD >= 2195) + +NTKERNELAPI +NTSTATUS +IoSetInformation ( + IN PFILE_OBJECT FileObject, + IN FILE_INFORMATION_CLASS FileInformationClass, + IN ULONG Length, + IN PVOID FileInformation +); + +NTKERNELAPI +VOID +IoSetTopLevelIrp ( + IN PIRP Irp +); + +NTKERNELAPI +NTSTATUS +IoSynchronousPageWrite ( + IN PFILE_OBJECT FileObject, + IN PMDL Mdl, + IN PLARGE_INTEGER FileOffset, + IN PKEVENT Event, + OUT PIO_STATUS_BLOCK IoStatusBlock +); + +NTKERNELAPI +PEPROCESS +IoThreadToProcess ( + IN PETHREAD Thread +); + +NTKERNELAPI +VOID +IoUnregisterFileSystem ( + IN OUT PDEVICE_OBJECT DeviceObject +); + +#if (VER_PRODUCTBUILD >= 1381) + +NTKERNELAPI +NTSTATUS +IoUnregisterFsRegistrationChange ( + IN PDRIVER_OBJECT DriverObject, + IN PDRIVER_FS_NOTIFICATION DriverNotificationRoutine +); + +#endif // (VER_PRODUCTBUILD >= 1381) + +NTKERNELAPI +NTSTATUS +IoVerifyVolume ( + IN PDEVICE_OBJECT DeviceObject, + IN BOOLEAN AllowRawMount +); + +#if (VER_PRODUCTBUILD >= 2195) + +NTKERNELAPI +KIRQL +FASTCALL +KeAcquireQueuedSpinLock ( + IN KSPIN_LOCK_QUEUE_NUMBER Number +); + +#endif // (VER_PRODUCTBUILD >= 2195) + +NTKERNELAPI +VOID +KeAttachProcess ( + IN PEPROCESS Process +); + +NTKERNELAPI +VOID +KeDetachProcess ( + VOID +); + +NTKERNELAPI +VOID +KeInitializeApc ( + PKAPC Apc, + PKTHREAD Thread, + UCHAR StateIndex, + PKKERNEL_ROUTINE KernelRoutine, + PKRUNDOWN_ROUTINE RundownRoutine, + PKNORMAL_ROUTINE NormalRoutine, + KPROCESSOR_MODE ApcMode, + PVOID NormalContext +); + +NTKERNELAPI +VOID +KeInitializeMutant ( + IN PRKMUTANT Mutant, + IN BOOLEAN InitialOwner +); + +NTKERNELAPI +VOID +KeInitializeQueue ( + IN PRKQUEUE Queue, + IN ULONG Count OPTIONAL +); + +NTKERNELAPI +LONG +KeInsertHeadQueue ( + IN PRKQUEUE Queue, + IN PLIST_ENTRY Entry +); + +NTKERNELAPI +LONG +KeInsertQueue ( + IN PRKQUEUE Queue, + IN PLIST_ENTRY Entry +); + +NTKERNELAPI +BOOLEAN +KeInsertQueueApc ( + IN PKAPC Apc, + IN PVOID SystemArgument1, + IN PVOID SystemArgument2, + IN KPRIORITY Increment +); + +#if (VER_PRODUCTBUILD >= 2600) + +NTKERNELAPI +BOOLEAN +KeIsAttachedProcess ( + VOID +); + +#endif // (VER_PRODUCTBUILD >= 2600) + +NTKERNELAPI +BOOLEAN +KeIsExecutingDpc ( + VOID +); + +NTKERNELAPI +LONG +KeReadStateMutant ( + IN PRKMUTANT Mutant +); + +NTKERNELAPI +LONG +KeReadStateQueue ( + IN PRKQUEUE Queue +); + +NTKERNELAPI +LONG +KeReleaseMutant ( + IN PRKMUTANT Mutant, + IN KPRIORITY Increment, + IN BOOLEAN Abandoned, + IN BOOLEAN Wait +); + +#if (VER_PRODUCTBUILD >= 2195) + +NTKERNELAPI +VOID +FASTCALL +KeReleaseQueuedSpinLock ( + IN KSPIN_LOCK_QUEUE_NUMBER Number, + IN KIRQL OldIrql +); + +#endif // (VER_PRODUCTBUILD >= 2195) + +NTKERNELAPI +PLIST_ENTRY +KeRemoveQueue ( + IN PRKQUEUE Queue, + IN KPROCESSOR_MODE WaitMode, + IN PLARGE_INTEGER Timeout OPTIONAL +); + +#if (VER_PRODUCTBUILD >= 2195) + +NTKERNELAPI +NTSTATUS +KeRevertToUserAffinityThread ( + VOID +); + +#endif // (VER_PRODUCTBUILD >= 2195) + +NTKERNELAPI +PLIST_ENTRY +KeRundownQueue ( + IN PRKQUEUE Queue +); + +#if (VER_PRODUCTBUILD >= 1381) + +NTKERNELAPI +CCHAR +KeSetIdealProcessorThread ( + IN PKTHREAD Thread, + IN CCHAR Processor +); + +NTKERNELAPI +BOOLEAN +KeSetKernelStackSwapEnable ( + IN BOOLEAN Enable +); + +#endif // (VER_PRODUCTBUILD >= 1381) + +#if (VER_PRODUCTBUILD >= 2195) + +NTKERNELAPI +VOID +KeStackAttachProcess ( + IN PKPROCESS Process, + OUT PKAPC_STATE ApcState +); + +NTKERNELAPI +LOGICAL +FASTCALL +KeTryToAcquireQueuedSpinLock ( + IN KSPIN_LOCK_QUEUE_NUMBER Number, + IN PKIRQL OldIrql +); + +NTKERNELAPI +VOID +KeUnstackDetachProcess ( + IN PKAPC_STATE ApcState +); + +#endif // (VER_PRODUCTBUILD >= 2195) + +NTKERNELAPI +NTSTATUS +KeUpdateSystemTime ( + VOID +); + +NTKERNELAPI +BOOLEAN +MmCanFileBeTruncated ( + IN PSECTION_OBJECT_POINTERS SectionObjectPointer, + IN PLARGE_INTEGER NewFileSize +); + +NTKERNELAPI +NTSTATUS +MmCreateSection ( + OUT PVOID *SectionObject, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, + IN PLARGE_INTEGER MaximumSize, + IN ULONG SectionPageProtection, + IN ULONG AllocationAttributes, + IN HANDLE FileHandle OPTIONAL, + IN PFILE_OBJECT FileObject OPTIONAL +); + +NTKERNELAPI +BOOLEAN +MmFlushImageSection ( + IN PSECTION_OBJECT_POINTERS SectionObjectPointer, + IN MMFLUSH_TYPE FlushType +); + +NTKERNELAPI +BOOLEAN +MmForceSectionClosed ( + IN PSECTION_OBJECT_POINTERS SectionObjectPointer, + IN BOOLEAN DelayClose +); + +#if (VER_PRODUCTBUILD >= 1381) + +NTKERNELAPI +BOOLEAN +MmIsRecursiveIoFault ( + VOID +); + +#else + +#define MmIsRecursiveIoFault() ( \ + (PsGetCurrentThread()->DisablePageFaultClustering) | \ + (PsGetCurrentThread()->ForwardClusterOnly) \ +) + +#endif + +NTKERNELAPI +NTSTATUS +MmMapViewOfSection ( + IN PVOID SectionObject, + IN PEPROCESS Process, + IN OUT PVOID *BaseAddress, + IN ULONG ZeroBits, + IN ULONG CommitSize, + IN OUT PLARGE_INTEGER SectionOffset OPTIONAL, + IN OUT PULONG ViewSize, + IN SECTION_INHERIT InheritDisposition, + IN ULONG AllocationType, + IN ULONG Protect +); + +#if (VER_PRODUCTBUILD >= 2600) + +NTKERNELAPI +NTSTATUS +MmPrefetchPages ( + IN ULONG NumberOfLists, + IN PREAD_LIST *ReadLists +); + +#endif // (VER_PRODUCTBUILD >= 2600) + +NTKERNELAPI +BOOLEAN +MmSetAddressRangeModified ( + IN PVOID Address, + IN SIZE_T Length +); + +NTKERNELAPI +NTSTATUS +ObCreateObject ( + IN KPROCESSOR_MODE ObjectAttributesAccessMode OPTIONAL, + IN POBJECT_TYPE ObjectType, + IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, + IN KPROCESSOR_MODE AccessMode, + IN OUT PVOID ParseContext OPTIONAL, + IN ULONG ObjectSize, + IN ULONG PagedPoolCharge OPTIONAL, + IN ULONG NonPagedPoolCharge OPTIONAL, + OUT PVOID *Object +); + +#if (VER_PRODUCTBUILD >= 2600) + +NTKERNELAPI +VOID +ObDereferenceSecurityDescriptor ( + IN PSECURITY_DESCRIPTOR SecurityDescriptor, + IN ULONG Count +); + +#endif // (VER_PRODUCTBUILD >= 2600) + +#if (VER_PRODUCTBUILD <= 2195) + +NTKERNELAPI +ULONG +ObGetObjectPointerCount ( + IN PVOID Object +); + +#endif // (VER_PRODUCTBUILD <= 2195) + +NTKERNELAPI +NTSTATUS +ObInsertObject ( + IN PVOID Object, + IN PACCESS_STATE PassedAccessState OPTIONAL, + IN ACCESS_MASK DesiredAccess, + IN ULONG AdditionalReferences, + OUT PVOID *ReferencedObject OPTIONAL, + OUT PHANDLE Handle +); + +#if (VER_PRODUCTBUILD >= 2600) + +NTKERNELAPI +NTSTATUS +ObLogSecurityDescriptor ( + IN PSECURITY_DESCRIPTOR InputSecurityDescriptor, + OUT PSECURITY_DESCRIPTOR *OutputSecurityDescriptor, + IN ULONG RefBias +); + +#endif // (VER_PRODUCTBUILD >= 2600) + +NTKERNELAPI +VOID +ObMakeTemporaryObject ( + IN PVOID Object +); + +NTKERNELAPI +NTSTATUS +ObOpenObjectByPointer ( + IN PVOID Object, + IN ULONG HandleAttributes, + IN PACCESS_STATE PassedAccessState OPTIONAL, + IN ACCESS_MASK DesiredAccess OPTIONAL, + IN POBJECT_TYPE ObjectType OPTIONAL, + IN KPROCESSOR_MODE AccessMode, + OUT PHANDLE Handle +); + +NTKERNELAPI +NTSTATUS +ObQueryNameString ( + IN PVOID Object, + OUT POBJECT_NAME_INFORMATION ObjectNameInfo, + IN ULONG Length, + OUT PULONG ReturnLength +); + +NTKERNELAPI +NTSTATUS +ObQueryObjectAuditingByHandle ( + IN HANDLE Handle, + OUT PBOOLEAN GenerateOnClose +); + +NTKERNELAPI +NTSTATUS +ObReferenceObjectByName ( + IN PUNICODE_STRING ObjectName, + IN ULONG Attributes, + IN PACCESS_STATE PassedAccessState OPTIONAL, + IN ACCESS_MASK DesiredAccess OPTIONAL, + IN POBJECT_TYPE ObjectType, + IN KPROCESSOR_MODE AccessMode, + IN OUT PVOID ParseContext OPTIONAL, + OUT PVOID *Object +); + +#if (VER_PRODUCTBUILD >= 2600) + +NTKERNELAPI +VOID +ObReferenceSecurityDescriptor ( + IN PSECURITY_DESCRIPTOR SecurityDescriptor, + IN ULONG Count +); + +NTKERNELAPI +NTSTATUS +PoQueueShutdownWorkItem ( + IN PWORK_QUEUE_ITEM WorkItem +); + +#endif // (VER_PRODUCTBUILD >= 2600) + +NTKERNELAPI +NTSTATUS +PsAssignImpersonationToken ( + IN PETHREAD Thread, + IN HANDLE Token +); + +NTKERNELAPI +VOID +PsChargePoolQuota ( + IN PEPROCESS Process, + IN POOL_TYPE PoolType, + IN ULONG Amount +); + +#if (VER_PRODUCTBUILD >= 2600) + +NTKERNELAPI +NTSTATUS +PsChargeProcessNonPagedPoolQuota ( + IN PEPROCESS Process, + IN ULONG_PTR Amount +); + +NTKERNELAPI +NTSTATUS +PsChargeProcessPagedPoolQuota ( + IN PEPROCESS Process, + IN ULONG_PTR Amount +); + +NTKERNELAPI +NTSTATUS +PsChargeProcessPoolQuota ( + IN PEPROCESS Process, + IN POOL_TYPE PoolType, + IN ULONG_PTR Amount +); + +#endif // (VER_PRODUCTBUILD >= 2600) + +#if (VER_PRODUCTBUILD >= 2600) + +NTKERNELAPI +VOID +PsDereferenceImpersonationToken ( + IN PACCESS_TOKEN ImpersonationToken +); + +NTKERNELAPI +VOID +PsDereferencePrimaryToken ( + IN PACCESS_TOKEN PrimaryToken +); + +#else + +#define PsDereferenceImpersonationToken(T) \ + {if (ARGUMENT_PRESENT(T)) { \ + (ObDereferenceObject((T))); \ + } else { \ + ; \ + } \ +} + +#define PsDereferencePrimaryToken(T) (ObDereferenceObject((T))) + +#endif + +#if (VER_PRODUCTBUILD >= 2195) + +NTKERNELAPI +BOOLEAN +PsDisableImpersonation ( + IN PETHREAD Thread, + IN PSE_IMPERSONATION_STATE ImpersonationState +); + +#endif // (VER_PRODUCTBUILD >= 2195) + +#if (VER_PRODUCTBUILD >= 2600) + +NTKERNELAPI +ULONG +PsGetCurrentProcessSessionId ( + VOID +); + +NTKERNELAPI +KPROCESSOR_MODE +PsGetCurrentThreadPreviousMode ( + VOID +); + +NTKERNELAPI +PVOID +PsGetCurrentThreadStackBase ( + VOID +); + +NTKERNELAPI +PVOID +PsGetCurrentThreadStackLimit ( + VOID +); + +#endif // (VER_PRODUCTBUILD >= 2600) + +NTKERNELAPI +LARGE_INTEGER +PsGetProcessExitTime ( + VOID +); + +NTKERNELAPI +NTSTATUS +PsImpersonateClient ( + IN PETHREAD Thread, + IN PACCESS_TOKEN Token, + IN BOOLEAN CopyOnOpen, + IN BOOLEAN EffectiveOnly, + IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel +); + +#if (VER_PRODUCTBUILD >= 2600) + +NTKERNELAPI +BOOLEAN +PsIsSystemThread ( + IN PETHREAD Thread +); + +#endif // (VER_PRODUCTBUILD >= 2600) + +NTKERNELAPI +BOOLEAN +PsIsThreadTerminating ( + IN PETHREAD Thread +); + +// +// PsLookupProcessByProcessId returns a referenced pointer to the process +// that should be dereferenced after use with a call to ObDereferenceObject. +// +NTKERNELAPI +NTSTATUS +PsLookupProcessByProcessId ( + IN PVOID ProcessId, + OUT PEPROCESS *Process +); + +NTKERNELAPI +NTSTATUS +PsLookupProcessThreadByCid ( + IN PCLIENT_ID Cid, + OUT PEPROCESS *Process OPTIONAL, + OUT PETHREAD *Thread +); + +NTKERNELAPI +NTSTATUS +PsLookupThreadByThreadId ( + IN PVOID UniqueThreadId, + OUT PETHREAD *Thread +); + +NTKERNELAPI +PACCESS_TOKEN +PsReferenceImpersonationToken ( + IN PETHREAD Thread, + OUT PBOOLEAN CopyOnOpen, + OUT PBOOLEAN EffectiveOnly, + OUT PSECURITY_IMPERSONATION_LEVEL ImpersonationLevel +); + +NTKERNELAPI +PACCESS_TOKEN +PsReferencePrimaryToken ( + IN PEPROCESS Process +); + +#if (VER_PRODUCTBUILD >= 2195) + +NTKERNELAPI +VOID +PsRestoreImpersonation ( + IN PETHREAD Thread, + IN PSE_IMPERSONATION_STATE ImpersonationState +); + +#endif // (VER_PRODUCTBUILD >= 2195) + +NTKERNELAPI +VOID +PsReturnPoolQuota ( + IN PEPROCESS Process, + IN POOL_TYPE PoolType, + IN ULONG Amount +); + +#if (VER_PRODUCTBUILD >= 1381) + +NTKERNELAPI +VOID +PsRevertToSelf ( + VOID +); + +#endif // (VER_PRODUCTBUILD >= 1381) + +NTSYSAPI +NTSTATUS +NTAPI +RtlAbsoluteToSelfRelativeSD ( + IN PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor, + IN OUT PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor, + IN PULONG BufferLength +); + +NTSYSAPI +PVOID +NTAPI +RtlAllocateHeap ( + IN HANDLE HeapHandle, + IN ULONG Flags, + IN ULONG Size +); + +NTSYSAPI +NTSTATUS +NTAPI +RtlCompressBuffer ( + IN USHORT CompressionFormatAndEngine, + IN PUCHAR UncompressedBuffer, + IN ULONG UncompressedBufferSize, + OUT PUCHAR CompressedBuffer, + IN ULONG CompressedBufferSize, + IN ULONG UncompressedChunkSize, + OUT PULONG FinalCompressedSize, + IN PVOID WorkSpace +); + +NTSYSAPI +NTSTATUS +NTAPI +RtlCompressChunks ( + IN PUCHAR UncompressedBuffer, + IN ULONG UncompressedBufferSize, + OUT PUCHAR CompressedBuffer, + IN ULONG CompressedBufferSize, + IN OUT PCOMPRESSED_DATA_INFO CompressedDataInfo, + IN ULONG CompressedDataInfoLength, + IN PVOID WorkSpace +); + +NTSYSAPI +NTSTATUS +NTAPI +RtlConvertSidToUnicodeString ( + OUT PUNICODE_STRING DestinationString, + IN PSID Sid, + IN BOOLEAN AllocateDestinationString +); + +NTSYSAPI +NTSTATUS +NTAPI +RtlCopySid ( + IN ULONG Length, + IN PSID Destination, + IN PSID Source +); + +NTSYSAPI +HANDLE +NTAPI +RtlCreateHeap ( + IN ULONG Flags, + IN PVOID Base, + IN ULONG Reserve, + IN ULONG Commit, + IN ULONG Lock, + IN PVOID RtlHeapParams +); + +NTSYSAPI +NTSTATUS +NTAPI +RtlDecompressBuffer ( + IN USHORT CompressionFormat, + OUT PUCHAR UncompressedBuffer, + IN ULONG UncompressedBufferSize, + IN PUCHAR CompressedBuffer, + IN ULONG CompressedBufferSize, + OUT PULONG FinalUncompressedSize +); + +NTSYSAPI +NTSTATUS +NTAPI +RtlDecompressChunks ( + OUT PUCHAR UncompressedBuffer, + IN ULONG UncompressedBufferSize, + IN PUCHAR CompressedBuffer, + IN ULONG CompressedBufferSize, + IN PUCHAR CompressedTail, + IN ULONG CompressedTailSize, + IN PCOMPRESSED_DATA_INFO CompressedDataInfo +); + +NTSYSAPI +NTSTATUS +NTAPI +RtlDecompressFragment ( + IN USHORT CompressionFormat, + OUT PUCHAR UncompressedFragment, + IN ULONG UncompressedFragmentSize, + IN PUCHAR CompressedBuffer, + IN ULONG CompressedBufferSize, + IN ULONG FragmentOffset, + OUT PULONG FinalUncompressedSize, + IN PVOID WorkSpace +); + +NTSYSAPI +NTSTATUS +NTAPI +RtlDescribeChunk ( + IN USHORT CompressionFormat, + IN OUT PUCHAR *CompressedBuffer, + IN PUCHAR EndOfCompressedBufferPlus1, + OUT PUCHAR *ChunkBuffer, + OUT PULONG ChunkSize +); + +NTSYSAPI +NTSTATUS +NTAPI +RtlDestroyHeap ( + IN HANDLE HeapHandle +); + +NTSYSAPI +BOOLEAN +NTAPI +RtlEqualSid ( + IN PSID Sid1, + IN PSID Sid2 +); + +NTSYSAPI +VOID +NTAPI +RtlFillMemoryUlong ( + IN PVOID Destination, + IN ULONG Length, + IN ULONG Fill +); + +NTSYSAPI +BOOLEAN +NTAPI +RtlFreeHeap ( + IN HANDLE HeapHandle, + IN ULONG Flags, + IN PVOID P +); + +NTSYSAPI +VOID +NTAPI +RtlGenerate8dot3Name ( + IN PUNICODE_STRING Name, + IN BOOLEAN AllowExtendedCharacters, + IN OUT PGENERATE_NAME_CONTEXT Context, + OUT PUNICODE_STRING Name8dot3 +); + +NTSYSAPI +NTSTATUS +NTAPI +RtlGetCompressionWorkSpaceSize ( + IN USHORT CompressionFormatAndEngine, + OUT PULONG CompressBufferWorkSpaceSize, + OUT PULONG CompressFragmentWorkSpaceSize +); + +NTSYSAPI +NTSTATUS +NTAPI +RtlGetDaclSecurityDescriptor ( + IN PSECURITY_DESCRIPTOR SecurityDescriptor, + OUT PBOOLEAN DaclPresent, + OUT PACL *Dacl, + OUT PBOOLEAN DaclDefaulted +); + +NTSYSAPI +NTSTATUS +NTAPI +RtlGetGroupSecurityDescriptor ( + IN PSECURITY_DESCRIPTOR SecurityDescriptor, + OUT PSID *Group, + OUT PBOOLEAN GroupDefaulted +); + +#if (VER_PRODUCTBUILD >= 2195) + +NTSYSAPI +ULONG +NTAPI +RtlGetNtGlobalFlags ( + VOID +); + +#endif // (VER_PRODUCTBUILD >= 2195) + +NTSYSAPI +NTSTATUS +NTAPI +RtlGetOwnerSecurityDescriptor ( + IN PSECURITY_DESCRIPTOR SecurityDescriptor, + OUT PSID *Owner, + OUT PBOOLEAN OwnerDefaulted +); + +// +// This function returns a PIMAGE_NT_HEADERS, +// see the standard include file winnt.h +// +NTSYSAPI +PVOID +NTAPI +RtlImageNtHeader ( + IN PVOID BaseAddress +); + +NTSYSAPI +NTSTATUS +NTAPI +RtlInitializeSid ( + IN OUT PSID Sid, + IN PSID_IDENTIFIER_AUTHORITY IdentifierAuthority, + IN UCHAR SubAuthorityCount +); + +NTSYSAPI +BOOLEAN +NTAPI +RtlIsNameLegalDOS8Dot3 ( + IN PUNICODE_STRING UnicodeName, + IN PANSI_STRING AnsiName, + PBOOLEAN Unknown +); + +NTSYSAPI +ULONG +NTAPI +RtlLengthRequiredSid ( + IN UCHAR SubAuthorityCount +); + +NTSYSAPI +ULONG +NTAPI +RtlLengthSid ( + IN PSID Sid +); + +NTSYSAPI +ULONG +NTAPI +RtlNtStatusToDosError ( + IN NTSTATUS Status +); + +#define RtlOemStringToCountedUnicodeSize(STRING) ( \ + (ULONG)(RtlOemStringToUnicodeSize(STRING) - sizeof(UNICODE_NULL)) \ +) + +#define RtlOemStringToUnicodeSize(STRING) ( \ + NLS_MB_OEM_CODE_PAGE_TAG ? \ + RtlxOemStringToUnicodeSize(STRING) : \ + ((STRING)->Length + sizeof(ANSI_NULL)) * sizeof(WCHAR) \ +) + +NTSYSAPI +NTSTATUS +NTAPI +RtlOemStringToUnicodeString ( + OUT PUNICODE_STRING DestinationString, + IN POEM_STRING SourceString, + IN BOOLEAN AllocateDestinationString +); + +NTSYSAPI +ULONG +NTAPI +RtlRandom ( + IN PULONG Seed +); + +#if (VER_PRODUCTBUILD >= 2600) + +NTSYSAPI +ULONG +NTAPI +RtlRandomEx ( + IN PULONG Seed +); + +#endif // (VER_PRODUCTBUILD >= 2600) + +NTSYSAPI +NTSTATUS +NTAPI +RtlReserveChunk ( + IN USHORT CompressionFormat, + IN OUT PUCHAR *CompressedBuffer, + IN PUCHAR EndOfCompressedBufferPlus1, + OUT PUCHAR *ChunkBuffer, + IN ULONG ChunkSize +); + +NTSYSAPI +VOID +NTAPI +RtlSecondsSince1970ToTime ( + IN ULONG SecondsSince1970, + OUT PLARGE_INTEGER Time +); + +NTSYSAPI +VOID +NTAPI +RtlSecondsSince1980ToTime ( + IN ULONG SecondsSince1980, + OUT PLARGE_INTEGER Time +); + +#if (VER_PRODUCTBUILD >= 2195) + +NTSYSAPI +NTSTATUS +NTAPI +RtlSelfRelativeToAbsoluteSD ( + IN PSECURITY_DESCRIPTOR SelfRelativeSD, + OUT PSECURITY_DESCRIPTOR AbsoluteSD, + IN PULONG AbsoluteSDSize, + IN PACL Dacl, + IN PULONG DaclSize, + IN PACL Sacl, + IN PULONG SaclSize, + IN PSID Owner, + IN PULONG OwnerSize, + IN PSID PrimaryGroup, + IN PULONG PrimaryGroupSize +); + +#endif // (VER_PRODUCTBUILD >= 2195) + +NTSYSAPI +NTSTATUS +NTAPI +RtlSetGroupSecurityDescriptor ( + IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor, + IN PSID Group, + IN BOOLEAN GroupDefaulted +); + +NTSYSAPI +NTSTATUS +NTAPI +RtlSetOwnerSecurityDescriptor ( + IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor, + IN PSID Owner, + IN BOOLEAN OwnerDefaulted +); + +NTSYSAPI +NTSTATUS +NTAPI +RtlSetSaclSecurityDescriptor ( + IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor, + IN BOOLEAN SaclPresent, + IN PACL Sacl, + IN BOOLEAN SaclDefaulted +); + +NTSYSAPI +PUCHAR +NTAPI +RtlSubAuthorityCountSid ( + IN PSID Sid +); + +NTSYSAPI +PULONG +NTAPI +RtlSubAuthoritySid ( + IN PSID Sid, + IN ULONG SubAuthority +); + +NTSYSAPI +BOOLEAN +NTAPI +RtlTimeToSecondsSince1970 ( + IN PLARGE_INTEGER Time, + OUT PULONG SecondsSince1970 +); + +NTSYSAPI +BOOLEAN +NTAPI +RtlTimeToSecondsSince1980 ( + IN PLARGE_INTEGER Time, + OUT PULONG SecondsSince1980 +); + +#define RtlUnicodeStringToOemSize(STRING) ( \ + NLS_MB_OEM_CODE_PAGE_TAG ? \ + RtlxUnicodeStringToOemSize(STRING) : \ + ((STRING)->Length + sizeof(UNICODE_NULL)) / sizeof(WCHAR) \ +) + +NTSYSAPI +NTSTATUS +NTAPI +RtlUnicodeStringToOemString ( + OUT POEM_STRING DestinationString, + IN PUNICODE_STRING SourceString, + IN BOOLEAN AllocateDestinationString +); + +NTSYSAPI +BOOLEAN +NTAPI +RtlValidSid ( + IN PSID Sid +); + +NTSYSAPI +ULONG +NTAPI +RtlxOemStringToUnicodeSize ( + IN POEM_STRING OemString +); + +NTSYSAPI +ULONG +NTAPI +RtlxUnicodeStringToAnsiSize ( + IN PUNICODE_STRING UnicodeString +); + +NTSYSAPI +ULONG +NTAPI +RtlxUnicodeStringToOemSize ( + IN PUNICODE_STRING UnicodeString +); + +NTKERNELAPI +NTSTATUS +SeAppendPrivileges ( + PACCESS_STATE AccessState, + PPRIVILEGE_SET Privileges +); + +#if (VER_PRODUCTBUILD >= 2195) + +NTKERNELAPI +VOID +SeAuditHardLinkCreation ( + IN PUNICODE_STRING FileName, + IN PUNICODE_STRING LinkName, + IN BOOLEAN Success +); + +#endif // (VER_PRODUCTBUILD >= 2195) + +NTKERNELAPI +BOOLEAN +SeAuditingFileEvents ( + IN BOOLEAN AccessGranted, + IN PSECURITY_DESCRIPTOR SecurityDescriptor +); + +NTKERNELAPI +BOOLEAN +SeAuditingFileOrGlobalEvents ( + IN BOOLEAN AccessGranted, + IN PSECURITY_DESCRIPTOR SecurityDescriptor, + IN PSECURITY_SUBJECT_CONTEXT SubjectContext +); + +#if (VER_PRODUCTBUILD >= 2195) + +NTKERNELAPI +BOOLEAN +SeAuditingHardLinkEvents ( + IN BOOLEAN AccessGranted, + IN PSECURITY_DESCRIPTOR SecurityDescriptor +); + +#endif // (VER_PRODUCTBUILD >= 2195) + +NTKERNELAPI +VOID +SeCaptureSubjectContext ( + OUT PSECURITY_SUBJECT_CONTEXT SubjectContext +); + +NTKERNELAPI +NTSTATUS +SeCreateAccessState ( + OUT PACCESS_STATE AccessState, + IN PVOID AuxData, + IN ACCESS_MASK AccessMask, + IN PGENERIC_MAPPING Mapping +); + +NTKERNELAPI +NTSTATUS +SeCreateClientSecurity ( + IN PETHREAD Thread, + IN PSECURITY_QUALITY_OF_SERVICE QualityOfService, + IN BOOLEAN RemoteClient, + OUT PSECURITY_CLIENT_CONTEXT ClientContext +); + +#if (VER_PRODUCTBUILD >= 2195) + +NTKERNELAPI +NTSTATUS +SeCreateClientSecurityFromSubjectContext ( + IN PSECURITY_SUBJECT_CONTEXT SubjectContext, + IN PSECURITY_QUALITY_OF_SERVICE QualityOfService, + IN BOOLEAN ServerIsRemote, + OUT PSECURITY_CLIENT_CONTEXT ClientContext +); + +#endif // (VER_PRODUCTBUILD >= 2195) + +NTKERNELAPI +VOID +SeDeleteAccessState ( + IN PACCESS_STATE AccessState +); + +#define SeDeleteClientSecurity(C) { \ + if (SeTokenType((C)->ClientToken) == TokenPrimary) { \ + PsDereferencePrimaryToken( (C)->ClientToken ); \ + } else { \ + PsDereferenceImpersonationToken( (C)->ClientToken ); \ + } \ +} + +NTKERNELAPI +VOID +SeDeleteObjectAuditAlarm ( + IN PVOID Object, + IN HANDLE Handle +); + +#define SeEnableAccessToExports() SeExports = *(PSE_EXPORTS *)SeExports; + +#if (VER_PRODUCTBUILD >= 2600) + +NTKERNELAPI +NTSTATUS +SeFilterToken ( + IN PACCESS_TOKEN ExistingToken, + IN ULONG Flags, + IN PTOKEN_GROUPS SidsToDisable OPTIONAL, + IN PTOKEN_PRIVILEGES PrivilegesToDelete OPTIONAL, + IN PTOKEN_GROUPS RestrictedSids OPTIONAL, + OUT PACCESS_TOKEN *FilteredToken +); + +#endif // (VER_PRODUCTBUILD >= 2600) + +NTKERNELAPI +VOID +SeFreePrivileges ( + IN PPRIVILEGE_SET Privileges +); + +NTKERNELAPI +VOID +SeImpersonateClient ( + IN PSECURITY_CLIENT_CONTEXT ClientContext, + IN PETHREAD ServerThread OPTIONAL +); + +#if (VER_PRODUCTBUILD >= 2195) + +NTKERNELAPI +NTSTATUS +SeImpersonateClientEx ( + IN PSECURITY_CLIENT_CONTEXT ClientContext, + IN PETHREAD ServerThread OPTIONAL +); + +#endif // (VER_PRODUCTBUILD >= 2195) + +NTKERNELAPI +VOID +SeLockSubjectContext ( + IN PSECURITY_SUBJECT_CONTEXT SubjectContext +); + +NTKERNELAPI +NTSTATUS +SeMarkLogonSessionForTerminationNotification ( + IN PLUID LogonId +); + +NTKERNELAPI +VOID +SeOpenObjectAuditAlarm ( + IN PUNICODE_STRING ObjectTypeName, + IN PVOID Object OPTIONAL, + IN PUNICODE_STRING AbsoluteObjectName OPTIONAL, + IN PSECURITY_DESCRIPTOR SecurityDescriptor, + IN PACCESS_STATE AccessState, + IN BOOLEAN ObjectCreated, + IN BOOLEAN AccessGranted, + IN KPROCESSOR_MODE AccessMode, + OUT PBOOLEAN GenerateOnClose +); + +NTKERNELAPI +VOID +SeOpenObjectForDeleteAuditAlarm ( + IN PUNICODE_STRING ObjectTypeName, + IN PVOID Object OPTIONAL, + IN PUNICODE_STRING AbsoluteObjectName OPTIONAL, + IN PSECURITY_DESCRIPTOR SecurityDescriptor, + IN PACCESS_STATE AccessState, + IN BOOLEAN ObjectCreated, + IN BOOLEAN AccessGranted, + IN KPROCESSOR_MODE AccessMode, + OUT PBOOLEAN GenerateOnClose +); + +NTKERNELAPI +BOOLEAN +SePrivilegeCheck ( + IN OUT PPRIVILEGE_SET RequiredPrivileges, + IN PSECURITY_SUBJECT_CONTEXT SubjectContext, + IN KPROCESSOR_MODE AccessMode +); + +NTKERNELAPI +NTSTATUS +SeQueryAuthenticationIdToken ( + IN PACCESS_TOKEN Token, + OUT PLUID LogonId +); + +#if (VER_PRODUCTBUILD >= 2195) + +NTKERNELAPI +NTSTATUS +SeQueryInformationToken ( + IN PACCESS_TOKEN Token, + IN TOKEN_INFORMATION_CLASS TokenInformationClass, + OUT PVOID *TokenInformation +); + +#endif // (VER_PRODUCTBUILD >= 2195) + +NTKERNELAPI +NTSTATUS +SeQuerySecurityDescriptorInfo ( + IN PSECURITY_INFORMATION SecurityInformation, + OUT PSECURITY_DESCRIPTOR SecurityDescriptor, + IN OUT PULONG Length, + IN PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor +); + +#if (VER_PRODUCTBUILD >= 2195) + +NTKERNELAPI +NTSTATUS +SeQuerySessionIdToken ( + IN PACCESS_TOKEN Token, + IN PULONG SessionId +); + +#endif // (VER_PRODUCTBUILD >= 2195) + +#define SeQuerySubjectContextToken( SubjectContext ) \ + ( ARGUMENT_PRESENT( \ + ((PSECURITY_SUBJECT_CONTEXT) SubjectContext)->ClientToken \ + ) ? \ + ((PSECURITY_SUBJECT_CONTEXT) SubjectContext)->ClientToken : \ + ((PSECURITY_SUBJECT_CONTEXT) SubjectContext)->PrimaryToken ) + +typedef NTSTATUS (*PSE_LOGON_SESSION_TERMINATED_ROUTINE) ( + IN PLUID LogonId +); + +NTKERNELAPI +NTSTATUS +SeRegisterLogonSessionTerminatedRoutine ( + IN PSE_LOGON_SESSION_TERMINATED_ROUTINE CallbackRoutine +); + +NTKERNELAPI +VOID +SeReleaseSubjectContext ( + IN PSECURITY_SUBJECT_CONTEXT SubjectContext +); + +NTKERNELAPI +VOID +SeSetAccessStateGenericMapping ( + PACCESS_STATE AccessState, + PGENERIC_MAPPING GenericMapping +); + +NTKERNELAPI +NTSTATUS +SeSetSecurityDescriptorInfo ( + IN PVOID Object OPTIONAL, + IN PSECURITY_INFORMATION SecurityInformation, + IN PSECURITY_DESCRIPTOR SecurityDescriptor, + IN OUT PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor, + IN POOL_TYPE PoolType, + IN PGENERIC_MAPPING GenericMapping +); + +#if (VER_PRODUCTBUILD >= 2195) + +NTKERNELAPI +NTSTATUS +SeSetSecurityDescriptorInfoEx ( + IN PVOID Object OPTIONAL, + IN PSECURITY_INFORMATION SecurityInformation, + IN PSECURITY_DESCRIPTOR ModificationDescriptor, + IN OUT PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor, + IN ULONG AutoInheritFlags, + IN POOL_TYPE PoolType, + IN PGENERIC_MAPPING GenericMapping +); + +NTKERNELAPI +BOOLEAN +SeTokenIsAdmin ( + IN PACCESS_TOKEN Token +); + +NTKERNELAPI +BOOLEAN +SeTokenIsRestricted ( + IN PACCESS_TOKEN Token +); + +#endif // (VER_PRODUCTBUILD >= 2195) + +NTKERNELAPI +TOKEN_TYPE +SeTokenType ( + IN PACCESS_TOKEN Token +); + +NTKERNELAPI +VOID +SeUnlockSubjectContext ( + IN PSECURITY_SUBJECT_CONTEXT SubjectContext +); + +NTKERNELAPI +NTSTATUS +SeUnregisterLogonSessionTerminatedRoutine ( + IN PSE_LOGON_SESSION_TERMINATED_ROUTINE CallbackRoutine +); + +#if (VER_PRODUCTBUILD >= 2195) + +NTSYSAPI +NTSTATUS +NTAPI +ZwAdjustPrivilegesToken ( + IN HANDLE TokenHandle, + IN BOOLEAN DisableAllPrivileges, + IN PTOKEN_PRIVILEGES NewState, + IN ULONG BufferLength, + OUT PTOKEN_PRIVILEGES PreviousState OPTIONAL, + OUT PULONG ReturnLength +); + +#endif // (VER_PRODUCTBUILD >= 2195) + +NTSYSAPI +NTSTATUS +NTAPI +ZwAlertThread ( + IN HANDLE ThreadHandle +); + +NTSYSAPI +NTSTATUS +NTAPI +ZwAllocateVirtualMemory ( + IN HANDLE ProcessHandle, + IN OUT PVOID *BaseAddress, + IN ULONG ZeroBits, + IN OUT PSIZE_T RegionSize, + IN ULONG AllocationType, + IN ULONG Protect +); + +NTSYSAPI +NTSTATUS +NTAPI +ZwAccessCheckAndAuditAlarm ( + IN PUNICODE_STRING SubsystemName, + IN PVOID HandleId, + IN PUNICODE_STRING ObjectTypeName, + IN PUNICODE_STRING ObjectName, + IN PSECURITY_DESCRIPTOR SecurityDescriptor, + IN ACCESS_MASK DesiredAccess, + IN PGENERIC_MAPPING GenericMapping, + IN BOOLEAN ObjectCreation, + OUT PACCESS_MASK GrantedAccess, + OUT PBOOLEAN AccessStatus, + OUT PBOOLEAN GenerateOnClose +); + +#if (VER_PRODUCTBUILD >= 2195) + +NTSYSAPI +NTSTATUS +NTAPI +ZwCancelIoFile ( + IN HANDLE FileHandle, + OUT PIO_STATUS_BLOCK IoStatusBlock +); + +#endif // (VER_PRODUCTBUILD >= 2195) + +NTSYSAPI +NTSTATUS +NTAPI +ZwClearEvent ( + IN HANDLE EventHandle +); + +NTSYSAPI +NTSTATUS +NTAPI +ZwConnectPort ( + OUT PHANDLE ClientPortHandle, + IN PUNICODE_STRING ServerPortName, + IN PSECURITY_QUALITY_OF_SERVICE SecurityQos, + IN OUT PLPC_SECTION_WRITE ClientSharedMemory OPTIONAL, + IN OUT PLPC_SECTION_READ ServerSharedMemory OPTIONAL, + OUT PULONG MaximumMessageLength OPTIONAL, + IN OUT PVOID ConnectionInfo OPTIONAL, + IN OUT PULONG ConnectionInfoLength OPTIONAL +); + +NTSYSAPI +NTSTATUS +NTAPI +ZwCloseObjectAuditAlarm ( + IN PUNICODE_STRING SubsystemName, + IN PVOID HandleId, + IN BOOLEAN GenerateOnClose +); + +NTSYSAPI +NTSTATUS +NTAPI +ZwCreateEvent ( + OUT PHANDLE EventHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, + IN EVENT_TYPE EventType, + IN BOOLEAN InitialState +); + +NTSYSAPI +NTSTATUS +NTAPI +ZwCreateSection ( + OUT PHANDLE SectionHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, + IN PLARGE_INTEGER MaximumSize OPTIONAL, + IN ULONG SectionPageProtection, + IN ULONG AllocationAttributes, + IN HANDLE FileHandle OPTIONAL +); + +NTSYSAPI +NTSTATUS +NTAPI +ZwCreateSymbolicLinkObject ( + OUT PHANDLE SymbolicLinkHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN PUNICODE_STRING TargetName +); + +NTSYSAPI +NTSTATUS +NTAPI +ZwDeleteFile ( + IN POBJECT_ATTRIBUTES ObjectAttributes +); + +NTSYSAPI +NTSTATUS +NTAPI +ZwDeleteValueKey ( + IN HANDLE Handle, + IN PUNICODE_STRING Name +); + +NTSYSAPI +NTSTATUS +NTAPI +ZwDeviceIoControlFile ( + IN HANDLE FileHandle, + IN HANDLE Event OPTIONAL, + IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, + IN PVOID ApcContext OPTIONAL, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG IoControlCode, + IN PVOID InputBuffer OPTIONAL, + IN ULONG InputBufferLength, + OUT PVOID OutputBuffer OPTIONAL, + IN ULONG OutputBufferLength +); + +// +// If using ZwDisplayString during boot on Windows 2000 or later you must +// first call InbvEnableDisplayString. +// +NTSYSAPI +NTSTATUS +NTAPI +ZwDisplayString ( + IN PUNICODE_STRING String +); + +NTSYSAPI +NTSTATUS +NTAPI +ZwDuplicateObject ( + IN HANDLE SourceProcessHandle, + IN HANDLE SourceHandle, + IN HANDLE TargetProcessHandle OPTIONAL, + OUT PHANDLE TargetHandle OPTIONAL, + IN ACCESS_MASK DesiredAccess, + IN ULONG HandleAttributes, + IN ULONG Options +); + +NTSYSAPI +NTSTATUS +NTAPI +ZwDuplicateToken ( + IN HANDLE ExistingTokenHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN BOOLEAN EffectiveOnly, + IN TOKEN_TYPE TokenType, + OUT PHANDLE NewTokenHandle +); + +NTSYSAPI +NTSTATUS +NTAPI +ZwFlushInstructionCache ( + IN HANDLE ProcessHandle, + IN PVOID BaseAddress OPTIONAL, + IN ULONG FlushSize +); + +#if (VER_PRODUCTBUILD >= 2195) + +NTSYSAPI +NTSTATUS +NTAPI +ZwFlushVirtualMemory ( + IN HANDLE ProcessHandle, + IN OUT PVOID *BaseAddress, + IN OUT PSIZE_T RegionSize, + OUT PIO_STATUS_BLOCK IoStatusBlock +); + +#endif // (VER_PRODUCTBUILD >= 2195) + +NTSYSAPI +NTSTATUS +NTAPI +ZwFreeVirtualMemory ( + IN HANDLE ProcessHandle, + IN OUT PVOID *BaseAddress, + IN OUT PSIZE_T RegionSize, + IN ULONG FreeType +); + +NTSYSAPI +NTSTATUS +NTAPI +ZwFsControlFile ( + IN HANDLE FileHandle, + IN HANDLE Event OPTIONAL, + IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, + IN PVOID ApcContext OPTIONAL, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG FsControlCode, + IN PVOID InputBuffer OPTIONAL, + IN ULONG InputBufferLength, + OUT PVOID OutputBuffer OPTIONAL, + IN ULONG OutputBufferLength +); + +#if (VER_PRODUCTBUILD >= 2195) + +NTSYSAPI +NTSTATUS +NTAPI +ZwInitiatePowerAction ( + IN POWER_ACTION SystemAction, + IN SYSTEM_POWER_STATE MinSystemState, + IN ULONG Flags, + IN BOOLEAN Asynchronous +); + +#endif // (VER_PRODUCTBUILD >= 2195) + +NTSYSAPI +NTSTATUS +NTAPI +ZwLoadDriver ( + // "\\Registry\\Machine\\System\\CurrentControlSet\\Services\\" + IN PUNICODE_STRING RegistryPath +); + +NTSYSAPI +NTSTATUS +NTAPI +ZwLoadKey ( + IN POBJECT_ATTRIBUTES KeyObjectAttributes, + IN POBJECT_ATTRIBUTES FileObjectAttributes +); + +NTSYSAPI +NTSTATUS +NTAPI +ZwNotifyChangeKey ( + IN HANDLE KeyHandle, + IN HANDLE EventHandle OPTIONAL, + IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, + IN PVOID ApcContext OPTIONAL, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG NotifyFilter, + IN BOOLEAN WatchSubtree, + IN PVOID Buffer, + IN ULONG BufferLength, + IN BOOLEAN Asynchronous +); + +NTSYSAPI +NTSTATUS +NTAPI +ZwOpenDirectoryObject ( + OUT PHANDLE DirectoryHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes +); + +NTSYSAPI +NTSTATUS +NTAPI +ZwOpenEvent ( + OUT PHANDLE EventHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes +); + +NTSYSAPI +NTSTATUS +NTAPI +ZwOpenProcess ( + OUT PHANDLE ProcessHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN PCLIENT_ID ClientId OPTIONAL +); + +NTSYSAPI +NTSTATUS +NTAPI +ZwOpenProcessToken ( + IN HANDLE ProcessHandle, + IN ACCESS_MASK DesiredAccess, + OUT PHANDLE TokenHandle +); + +#if (VER_PRODUCTBUILD >= 2600) + +NTSYSAPI +NTSTATUS +NTAPI +ZwOpenProcessTokenEx ( + IN HANDLE ProcessHandle, + IN ACCESS_MASK DesiredAccess, + IN ULONG HandleAttributes, + OUT PHANDLE TokenHandle +); + +#endif // (VER_PRODUCTBUILD >= 2600) + +NTSYSAPI +NTSTATUS +NTAPI +ZwOpenThread ( + OUT PHANDLE ThreadHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN PCLIENT_ID ClientId +); + +NTSYSAPI +NTSTATUS +NTAPI +ZwOpenThreadToken ( + IN HANDLE ThreadHandle, + IN ACCESS_MASK DesiredAccess, + IN BOOLEAN OpenAsSelf, + OUT PHANDLE TokenHandle +); + +#if (VER_PRODUCTBUILD >= 2600) + +NTSYSAPI +NTSTATUS +NTAPI +ZwOpenThreadTokenEx ( + IN HANDLE ThreadHandle, + IN ACCESS_MASK DesiredAccess, + IN BOOLEAN OpenAsSelf, + IN ULONG HandleAttributes, + OUT PHANDLE TokenHandle +); + +#endif // (VER_PRODUCTBUILD >= 2600) + +#if (VER_PRODUCTBUILD >= 2195) + +NTSYSAPI +NTSTATUS +NTAPI +ZwPowerInformation ( + IN POWER_INFORMATION_LEVEL PowerInformationLevel, + IN PVOID InputBuffer OPTIONAL, + IN ULONG InputBufferLength, + OUT PVOID OutputBuffer OPTIONAL, + IN ULONG OutputBufferLength +); + +#endif // (VER_PRODUCTBUILD >= 2195) + +NTSYSAPI +NTSTATUS +NTAPI +ZwPulseEvent ( + IN HANDLE EventHandle, + OUT PULONG PreviousState OPTIONAL +); + +NTSYSAPI +NTSTATUS +NTAPI +ZwQueryDefaultLocale ( + IN BOOLEAN ThreadOrSystem, + OUT PLCID Locale +); + +#if (VER_PRODUCTBUILD >= 2195) + +NTSYSAPI +NTSTATUS +NTAPI +ZwQueryDefaultUILanguage ( + OUT LANGID *LanguageId +); + +#endif // (VER_PRODUCTBUILD >= 2195) + +NTSYSAPI +NTSTATUS +NTAPI +ZwQueryDirectoryFile ( + IN HANDLE FileHandle, + IN HANDLE Event OPTIONAL, + IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, + IN PVOID ApcContext OPTIONAL, + OUT PIO_STATUS_BLOCK IoStatusBlock, + OUT PVOID FileInformation, + IN ULONG Length, + IN FILE_INFORMATION_CLASS FileInformationClass, + IN BOOLEAN ReturnSingleEntry, + IN PUNICODE_STRING FileName OPTIONAL, + IN BOOLEAN RestartScan +); + +#if (VER_PRODUCTBUILD >= 2195) + +NTSYSAPI +NTSTATUS +NTAPI +ZwQueryDirectoryObject ( + IN HANDLE DirectoryHandle, + OUT PVOID Buffer, + IN ULONG Length, + IN BOOLEAN ReturnSingleEntry, + IN BOOLEAN RestartScan, + IN OUT PULONG Context, + OUT PULONG ReturnLength OPTIONAL +); + +NTSYSAPI +NTSTATUS +NTAPI +ZwQueryEaFile ( + IN HANDLE FileHandle, + OUT PIO_STATUS_BLOCK IoStatusBlock, + OUT PVOID Buffer, + IN ULONG Length, + IN BOOLEAN ReturnSingleEntry, + IN PVOID EaList OPTIONAL, + IN ULONG EaListLength, + IN PULONG EaIndex OPTIONAL, + IN BOOLEAN RestartScan +); + +#endif // (VER_PRODUCTBUILD >= 2195) + +NTSYSAPI +NTSTATUS +NTAPI +ZwQueryInformationProcess ( + IN HANDLE ProcessHandle, + IN PROCESSINFOCLASS ProcessInformationClass, + OUT PVOID ProcessInformation, + IN ULONG ProcessInformationLength, + OUT PULONG ReturnLength OPTIONAL +); + +#if (VER_PRODUCTBUILD >= 2600) + +NTSYSAPI +NTSTATUS +NTAPI +ZwQueryInformationThread ( + IN HANDLE ThreadHandle, + IN THREADINFOCLASS ThreadInformationClass, + OUT PVOID ThreadInformation, + IN ULONG ThreadInformationLength, + OUT PULONG ReturnLength OPTIONAL +); + +#endif // (VER_PRODUCTBUILD >= 2600) + +NTSYSAPI +NTSTATUS +NTAPI +ZwQueryInformationToken ( + IN HANDLE TokenHandle, + IN TOKEN_INFORMATION_CLASS TokenInformationClass, + OUT PVOID TokenInformation, + IN ULONG TokenInformationLength, + OUT PULONG ReturnLength +); + +#if (VER_PRODUCTBUILD >= 2195) + +NTSYSAPI +NTSTATUS +NTAPI +ZwQueryInstallUILanguage ( + OUT LANGID *LanguageId +); + +#endif // (VER_PRODUCTBUILD >= 2195) + +NTSYSAPI +NTSTATUS +NTAPI +ZwQueryObject ( + IN HANDLE ObjectHandle, + IN OBJECT_INFO_CLASS ObjectInformationClass, + OUT PVOID ObjectInformation, + IN ULONG Length, + OUT PULONG ResultLength +); + +NTSYSAPI +NTSTATUS +NTAPI +ZwQuerySection ( + IN HANDLE SectionHandle, + IN SECTION_INFORMATION_CLASS SectionInformationClass, + OUT PVOID SectionInformation, + IN ULONG SectionInformationLength, + OUT PULONG ResultLength OPTIONAL +); + +NTSYSAPI +NTSTATUS +NTAPI +ZwQuerySecurityObject ( + IN HANDLE FileHandle, + IN SECURITY_INFORMATION SecurityInformation, + OUT PSECURITY_DESCRIPTOR SecurityDescriptor, + IN ULONG Length, + OUT PULONG ResultLength +); + +NTSYSAPI +NTSTATUS +NTAPI +ZwQuerySystemInformation ( + IN SYSTEM_INFORMATION_CLASS SystemInformationClass, + OUT PVOID SystemInformation, + IN ULONG Length, + OUT PULONG ReturnLength +); + +NTSYSAPI +NTSTATUS +NTAPI +ZwQueryVolumeInformationFile ( + IN HANDLE FileHandle, + OUT PIO_STATUS_BLOCK IoStatusBlock, + OUT PVOID FsInformation, + IN ULONG Length, + IN FS_INFORMATION_CLASS FsInformationClass +); + +NTSYSAPI +NTSTATUS +NTAPI +ZwReplaceKey ( + IN POBJECT_ATTRIBUTES NewFileObjectAttributes, + IN HANDLE KeyHandle, + IN POBJECT_ATTRIBUTES OldFileObjectAttributes +); + +NTSYSAPI +NTSTATUS +NTAPI +ZwRequestWaitReplyPort ( + IN HANDLE PortHandle, + IN PLPC_MESSAGE Request, + OUT PLPC_MESSAGE Reply +); + +NTSYSAPI +NTSTATUS +NTAPI +ZwResetEvent ( + IN HANDLE EventHandle, + OUT PULONG PreviousState OPTIONAL +); + +#if (VER_PRODUCTBUILD >= 2195) + +NTSYSAPI +NTSTATUS +NTAPI +ZwRestoreKey ( + IN HANDLE KeyHandle, + IN HANDLE FileHandle, + IN ULONG Flags +); + +#endif // (VER_PRODUCTBUILD >= 2195) + +NTSYSAPI +NTSTATUS +NTAPI +ZwSaveKey ( + IN HANDLE KeyHandle, + IN HANDLE FileHandle +); + +NTSYSAPI +NTSTATUS +NTAPI +ZwSetDefaultLocale ( + IN BOOLEAN ThreadOrSystem, + IN LCID Locale +); + +#if (VER_PRODUCTBUILD >= 2195) + +NTSYSAPI +NTSTATUS +NTAPI +ZwSetDefaultUILanguage ( + IN LANGID LanguageId +); + +NTSYSAPI +NTSTATUS +NTAPI +ZwSetEaFile ( + IN HANDLE FileHandle, + OUT PIO_STATUS_BLOCK IoStatusBlock, + OUT PVOID Buffer, + IN ULONG Length +); + +#endif // (VER_PRODUCTBUILD >= 2195) + +NTSYSAPI +NTSTATUS +NTAPI +ZwSetEvent ( + IN HANDLE EventHandle, + OUT PULONG PreviousState OPTIONAL +); + +NTSYSAPI +NTSTATUS +NTAPI +ZwSetInformationObject ( + IN HANDLE ObjectHandle, + IN OBJECT_INFO_CLASS ObjectInformationClass, + IN PVOID ObjectInformation, + IN ULONG ObjectInformationLength +); + +NTSYSAPI +NTSTATUS +NTAPI +ZwSetInformationProcess ( + IN HANDLE ProcessHandle, + IN PROCESSINFOCLASS ProcessInformationClass, + IN PVOID ProcessInformation, + IN ULONG ProcessInformationLength +); + +#if (VER_PRODUCTBUILD >= 2195) + +NTSYSAPI +NTSTATUS +NTAPI +ZwSetSecurityObject ( + IN HANDLE Handle, + IN SECURITY_INFORMATION SecurityInformation, + IN PSECURITY_DESCRIPTOR SecurityDescriptor +); + +#endif // (VER_PRODUCTBUILD >= 2195) + +NTSYSAPI +NTSTATUS +NTAPI +ZwSetSystemInformation ( + IN SYSTEM_INFORMATION_CLASS SystemInformationClass, + IN PVOID SystemInformation, + IN ULONG Length +); + +NTSYSAPI +NTSTATUS +NTAPI +ZwSetSystemTime ( + IN PLARGE_INTEGER NewTime, + OUT PLARGE_INTEGER OldTime OPTIONAL +); + +#if (VER_PRODUCTBUILD >= 2195) + +NTSYSAPI +NTSTATUS +NTAPI +ZwSetVolumeInformationFile ( + IN HANDLE FileHandle, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN PVOID FsInformation, + IN ULONG Length, + IN FS_INFORMATION_CLASS FsInformationClass +); + +#endif // (VER_PRODUCTBUILD >= 2195) + +NTSYSAPI +NTSTATUS +NTAPI +ZwTerminateProcess ( + IN HANDLE ProcessHandle OPTIONAL, + IN NTSTATUS ExitStatus +); + +NTSYSAPI +NTSTATUS +NTAPI +ZwUnloadDriver ( + // "\\Registry\\Machine\\System\\CurrentControlSet\\Services\\" + IN PUNICODE_STRING RegistryPath +); + +NTSYSAPI +NTSTATUS +NTAPI +ZwUnloadKey ( + IN POBJECT_ATTRIBUTES KeyObjectAttributes +); + +NTSYSAPI +NTSTATUS +NTAPI +ZwWaitForSingleObject ( + IN HANDLE Handle, + IN BOOLEAN Alertable, + IN PLARGE_INTEGER Timeout OPTIONAL +); + +NTSYSAPI +NTSTATUS +NTAPI +ZwWaitForMultipleObjects ( + IN ULONG HandleCount, + IN PHANDLE Handles, + IN WAIT_TYPE WaitType, + IN BOOLEAN Alertable, + IN PLARGE_INTEGER Timeout OPTIONAL +); + +NTSYSAPI +NTSTATUS +NTAPI +ZwYieldExecution ( + VOID +); + +// +// Below is stuff that is included in the Windows 2000 DDK but is missing in +// the Windows NT 4.0 DDK +// + +#if (VER_PRODUCTBUILD < 2195) + +NTSYSAPI +VOID +NTAPI +HalMakeBeep ( + IN ULONG Frequency +); + +#ifndef IoCopyCurrentIrpStackLocationToNext +#define IoCopyCurrentIrpStackLocationToNext( Irp ) { \ + PIO_STACK_LOCATION irpSp; \ + PIO_STACK_LOCATION nextIrpSp; \ + irpSp = IoGetCurrentIrpStackLocation( (Irp) ); \ + nextIrpSp = IoGetNextIrpStackLocation( (Irp) ); \ + RtlCopyMemory( \ + nextIrpSp, \ + irpSp, \ + FIELD_OFFSET(IO_STACK_LOCATION, CompletionRoutine) \ + ); \ + nextIrpSp->Control = 0; } +#endif + +NTKERNELAPI +NTSTATUS +IoCreateFile ( + OUT PHANDLE FileHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN PLARGE_INTEGER AllocationSize OPTIONAL, + IN ULONG FileAttributes, + IN ULONG ShareAccess, + IN ULONG CreateDisposition, + IN ULONG CreateOptions, + IN PVOID EaBuffer OPTIONAL, + IN ULONG EaLength, + IN CREATE_FILE_TYPE CreateFileType, + IN PVOID ExtraCreateParameters, + IN ULONG Options +); + +#ifndef IoSkipCurrentIrpStackLocation +#define IoSkipCurrentIrpStackLocation( Irp ) \ + (Irp)->CurrentLocation++; \ + (Irp)->Tail.Overlay.CurrentStackLocation++; +#endif + +NTSYSAPI +VOID +NTAPI +ProbeForWrite ( + IN PVOID Address, + IN ULONG Length, + IN ULONG Alignment +); + +NTSYSAPI +NTSTATUS +NTAPI +ZwOpenFile ( + OUT PHANDLE FileHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG ShareAccess, + IN ULONG OpenOptions +); + +NTSYSAPI +NTSTATUS +NTAPI +ZwOpenSymbolicLinkObject ( + OUT PHANDLE SymbolicLinkHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes +); + +NTSYSAPI +NTSTATUS +NTAPI +ZwQuerySymbolicLinkObject ( + IN HANDLE LinkHandle, + IN OUT PUNICODE_STRING LinkTarget, + OUT PULONG ReturnedLength OPTIONAL +); + +#endif // (VER_PRODUCTBUILD < 2195) + +#ifdef __cplusplus +} +#endif + +#endif // _NTIFS_ diff --git a/reactos/drivers/filesystems/ffs/inc/type.h b/reactos/drivers/filesystems/ffs/inc/type.h new file mode 100644 index 00000000000..ba398092cf8 --- /dev/null +++ b/reactos/drivers/filesystems/ffs/inc/type.h @@ -0,0 +1,22 @@ +/* type.h */ + +typedef unsigned char u_char; + +typedef __int8 int8_t; +typedef unsigned __int8 uint8_t; +typedef unsigned __int8 u_int8_t; + +typedef __int16 int16_t; +typedef unsigned __int16 u_int16_t; +typedef unsigned __int16 uint16_t; + +typedef __int32 int32_t; +typedef unsigned __int32 u_int; +typedef unsigned __int32 uint32_t; +typedef unsigned __int32 u_int32_t; + +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; +typedef unsigned __int64 u_int64_t; + +typedef __int64 daddr_t; diff --git a/reactos/drivers/filesystems/ffs/src/block.c b/reactos/drivers/filesystems/ffs/src/block.c new file mode 100644 index 00000000000..423842f51b2 --- /dev/null +++ b/reactos/drivers/filesystems/ffs/src/block.c @@ -0,0 +1,681 @@ +/* + * FFS File System Driver for Windows + * + * block.c + * + * 2004.5.6 ~ + * + * Lee Jae-Hong, http://www.pyrasis.com + * + * See License.txt + * + */ + +#include "ntifs.h" +#include "ffsdrv.h" + +/* Globals */ + +extern PFFS_GLOBAL FFSGlobal; + + +/* Definitions */ + +typedef struct _FFS_RW_CONTEXT { + PIRP MasterIrp; + KEVENT Event; + BOOLEAN Wait; + LONG Blocks; + ULONG Length; +} FFS_RW_CONTEXT, *PFFS_RW_CONTEXT; + +#ifdef _PREFAST_ +IO_COMPLETION_ROUTINE FFSReadWriteBlockSyncCompletionRoutine; +IO_COMPLETION_ROUTINE FFSReadWriteBlockAsyncCompletionRoutine; +IO_COMPLETION_ROUTINE FFSMediaEjectControlCompletion; +#endif // _PREFAST_ + +NTSTATUS NTAPI +FFSReadWriteBlockSyncCompletionRoutine( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID Context); + +NTSTATUS NTAPI +FFSReadWriteBlockAsyncCompletionRoutine( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID Context); + +NTSTATUS NTAPI +FFSMediaEjectControlCompletion( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID Contxt); + + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE, FFSLockUserBuffer) +#pragma alloc_text(PAGE, FFSGetUserBuffer) +#pragma alloc_text(PAGE, FFSReadSync) +#pragma alloc_text(PAGE, FFSReadDisk) +#pragma alloc_text(PAGE, FFSDiskIoControl) +#pragma alloc_text(PAGE, FFSReadWriteBlocks) +#pragma alloc_text(PAGE, FFSMediaEjectControl) +#pragma alloc_text(PAGE, FFSDiskShutDown) +#endif + + +NTSTATUS +FFSLockUserBuffer( + IN PIRP Irp, + IN ULONG Length, + IN LOCK_OPERATION Operation) +{ + NTSTATUS Status; + + PAGED_CODE(); + + ASSERT(Irp != NULL); + + if (Irp->MdlAddress != NULL) + { + return STATUS_SUCCESS; + } + + IoAllocateMdl(Irp->UserBuffer, Length, FALSE, FALSE, Irp); + + if (Irp->MdlAddress == NULL) + { + return STATUS_INSUFFICIENT_RESOURCES; + } + + _SEH2_TRY + { + MmProbeAndLockPages(Irp->MdlAddress, Irp->RequestorMode, Operation); + + Status = STATUS_SUCCESS; + } + _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) + { + IoFreeMdl(Irp->MdlAddress); + + Irp->MdlAddress = NULL; + + FFSBreakPoint(); + + Status = STATUS_INVALID_USER_BUFFER; + } _SEH2_END; + + return Status; +} + + +PVOID +FFSGetUserBuffer( + IN PIRP Irp) +{ + PAGED_CODE(); + + ASSERT(Irp != NULL); + + if (Irp->MdlAddress) + { +#if (_WIN32_WINNT >= 0x0500) + return MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority); +#else + return MmGetSystemAddressForMdl(Irp->MdlAddress); +#endif + } + else + { + return Irp->UserBuffer; + } +} + + +NTSTATUS NTAPI +FFSReadWriteBlockSyncCompletionRoutine( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID Context) +{ + PFFS_RW_CONTEXT pContext = (PFFS_RW_CONTEXT)Context; + + if (!NT_SUCCESS(Irp->IoStatus.Status)) + { + + pContext->MasterIrp->IoStatus = Irp->IoStatus; + } + + IoFreeMdl(Irp->MdlAddress); + IoFreeIrp(Irp); + + if (InterlockedDecrement(&pContext->Blocks) == 0) + { + pContext->MasterIrp->IoStatus.Information = 0; + + if (NT_SUCCESS(pContext->MasterIrp->IoStatus.Status)) + { + pContext->MasterIrp->IoStatus.Information = + pContext->Length; + } + + KeSetEvent(&pContext->Event, 0, FALSE); + } + + UNREFERENCED_PARAMETER(DeviceObject); + + return STATUS_MORE_PROCESSING_REQUIRED; +} + +NTSTATUS NTAPI +FFSReadWriteBlockAsyncCompletionRoutine( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID Context) +{ + PFFS_RW_CONTEXT pContext = (PFFS_RW_CONTEXT)Context; + + if (!NT_SUCCESS(Irp->IoStatus.Status)) + { + pContext->MasterIrp->IoStatus = Irp->IoStatus; + } + + if (InterlockedDecrement(&pContext->Blocks) == 0) + { + pContext->MasterIrp->IoStatus.Information = 0; + + if (NT_SUCCESS(pContext->MasterIrp->IoStatus.Status)) + { + pContext->MasterIrp->IoStatus.Information = + pContext->Length; + } + + IoMarkIrpPending(pContext->MasterIrp); + + ExFreePool(pContext); + } + + UNREFERENCED_PARAMETER(DeviceObject); + + return STATUS_SUCCESS; + +} + +NTSTATUS +FFSReadWriteBlocks( + IN PFFS_IRP_CONTEXT IrpContext, + IN PFFS_VCB Vcb, + IN PFFS_BDL FFSBDL, + IN ULONG Length, + IN ULONG Count, + IN BOOLEAN bVerify) +{ + PMDL Mdl; + PIRP Irp; + PIRP MasterIrp = IrpContext->Irp; + PIO_STACK_LOCATION IrpSp; + NTSTATUS Status = STATUS_SUCCESS; + PFFS_RW_CONTEXT pContext = NULL; + ULONG i; + BOOLEAN bBugCheck = FALSE; + + PAGED_CODE(); + + ASSERT(MasterIrp); + + _SEH2_TRY + { + + pContext = ExAllocatePoolWithTag(NonPagedPool, sizeof(FFS_RW_CONTEXT), FFS_POOL_TAG); + + if (!pContext) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + _SEH2_LEAVE; + } + + RtlZeroMemory(pContext, sizeof(FFS_RW_CONTEXT)); + + pContext->Wait = IrpContext->IsSynchronous; + pContext->MasterIrp = MasterIrp; + pContext->Blocks = Count; + pContext->Length = 0; + + if (pContext->Wait) + { + KeInitializeEvent(&(pContext->Event), NotificationEvent, FALSE); + } + + for (i = 0; i < Count; i++) + { + + Irp = IoMakeAssociatedIrp(MasterIrp, + (CCHAR)(Vcb->TargetDeviceObject->StackSize + 1)); + if (!Irp) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + _SEH2_LEAVE; + } + + Mdl = IoAllocateMdl((PCHAR)MasterIrp->UserBuffer + + FFSBDL[i].Offset, + FFSBDL[i].Length, + FALSE, + FALSE, + Irp); + + if (!Mdl) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + _SEH2_LEAVE; + } + + IoBuildPartialMdl(MasterIrp->MdlAddress, + Mdl, + (PCHAR)MasterIrp->UserBuffer + FFSBDL[i].Offset, + FFSBDL[i].Length); + + IoSetNextIrpStackLocation(Irp); + IrpSp = IoGetCurrentIrpStackLocation(Irp); + + + IrpSp->MajorFunction = IrpContext->MajorFunction; + IrpSp->Parameters.Read.Length = FFSBDL[i].Length; + IrpSp->Parameters.Read.ByteOffset.QuadPart = FFSBDL[i].Lba; + + IoSetCompletionRoutine(Irp, + IrpContext->IsSynchronous ? + &FFSReadWriteBlockSyncCompletionRoutine : + &FFSReadWriteBlockAsyncCompletionRoutine, + (PVOID) pContext, + TRUE, + TRUE, + TRUE); + + IrpSp = IoGetNextIrpStackLocation(Irp); + + IrpSp->MajorFunction = IrpContext->MajorFunction; + IrpSp->Parameters.Read.Length = FFSBDL[i].Length; + IrpSp->Parameters.Read.ByteOffset.QuadPart = FFSBDL[i].Lba; + + if (bVerify) + { + SetFlag(IrpSp->Flags, SL_OVERRIDE_VERIFY_VOLUME); + } + + FFSBDL[i].Irp = Irp; + } + + MasterIrp->AssociatedIrp.IrpCount = Count; + + if (IrpContext->IsSynchronous) + { + MasterIrp->AssociatedIrp.IrpCount += 1; + } + + pContext->Length = Length; + + bBugCheck = TRUE; + + for (i = 0; i < Count; i++) + { + Status = IoCallDriver(Vcb->TargetDeviceObject, + FFSBDL[i].Irp); + } + + if (IrpContext->IsSynchronous) + { + KeWaitForSingleObject(&(pContext->Event), + Executive, KernelMode, FALSE, NULL); + + KeClearEvent(&(pContext->Event)); + } + } + + _SEH2_FINALLY + { + if (IrpContext->IsSynchronous) + { + if (MasterIrp) + Status = MasterIrp->IoStatus.Status; + + if (pContext) + ExFreePool(pContext); + + } + else + { + IrpContext->Irp = NULL; + Status = STATUS_PENDING; + } + + if (_SEH2_AbnormalTermination()) + { + if (bBugCheck) + { + FFSBugCheck(FFS_BUGCHK_BLOCK, 0, 0, 0); + } + + for (i = 0; i < Count; i++) + { + if (FFSBDL[i].Irp != NULL) + { + if (FFSBDL[i].Irp->MdlAddress != NULL) + { + IoFreeMdl(FFSBDL[i].Irp->MdlAddress); + } + + IoFreeIrp(FFSBDL[i].Irp); + } + } + } + } _SEH2_END; + + return Status; +} + + +NTSTATUS +FFSReadSync( + IN PFFS_VCB Vcb, + IN ULONGLONG Offset, + IN ULONG Length, + OUT PVOID Buffer, + IN BOOLEAN bVerify) +{ + KEVENT Event; + PIRP Irp; + IO_STATUS_BLOCK IoStatus; + NTSTATUS Status; + + PAGED_CODE(); + + ASSERT(Vcb != NULL); + ASSERT(Vcb->TargetDeviceObject != NULL); + ASSERT(Buffer != NULL); + + KeInitializeEvent(&Event, NotificationEvent, FALSE); + + Irp = IoBuildSynchronousFsdRequest( + IRP_MJ_READ, + Vcb->TargetDeviceObject, + Buffer, + Length, + (PLARGE_INTEGER)(&Offset), + &Event, + &IoStatus); + + if (!Irp) + { + return STATUS_INSUFFICIENT_RESOURCES; + } + + if (bVerify) + { + SetFlag(IoGetNextIrpStackLocation(Irp)->Flags, + SL_OVERRIDE_VERIFY_VOLUME); + } + + Status = IoCallDriver(Vcb->TargetDeviceObject, Irp); + + if (Status == STATUS_PENDING) + { + KeWaitForSingleObject( + &Event, + Suspended, + KernelMode, + FALSE, + NULL); + + Status = IoStatus.Status; + } + + return Status; +} + + +NTSTATUS +FFSReadDisk( + IN PFFS_VCB Vcb, + IN ULONGLONG Offset, + IN ULONG Size, + IN PVOID Buffer, + IN BOOLEAN bVerify) +{ + NTSTATUS Status; + PUCHAR Buf; + ULONG Length; + ULONGLONG Lba; + + PAGED_CODE(); + + Lba = Offset & (~((ULONGLONG)SECTOR_SIZE - 1)); + Length = (ULONG)(Size + Offset + SECTOR_SIZE - 1 - Lba) & + (~((ULONG)SECTOR_SIZE - 1)); + + Buf = ExAllocatePoolWithTag(PagedPool, Length, FFS_POOL_TAG); + if (!Buf) + { + FFSPrint((DBG_ERROR, "FFSReadDisk: no enough memory.\n")); + Status = STATUS_INSUFFICIENT_RESOURCES; + + goto errorout; + } + + Status = FFSReadSync(Vcb, + Lba, + Length, + Buf, + FALSE); + + if (!NT_SUCCESS(Status)) + { + FFSPrint((DBG_ERROR, "FFSReadDisk: Read Block Device error.\n")); + + goto errorout; + } + + RtlCopyMemory(Buffer, &Buf[Offset - Lba], Size); + +errorout: + + if (Buf) + ExFreePool(Buf); + + return Status; +} + + +NTSTATUS +FFSDiskIoControl( + IN PDEVICE_OBJECT DeviceObject, + IN ULONG IoctlCode, + IN PVOID InputBuffer, + IN ULONG InputBufferSize, + IN OUT PVOID OutputBuffer, + IN OUT PULONG OutputBufferSize) +{ + ULONG OutBufferSize = 0; + KEVENT Event; + PIRP Irp; + IO_STATUS_BLOCK IoStatus; + NTSTATUS Status; + + PAGED_CODE(); + + ASSERT(DeviceObject != NULL); + + if (OutputBufferSize) + { + OutBufferSize = *OutputBufferSize; + } + + KeInitializeEvent(&Event, NotificationEvent, FALSE); + + Irp = IoBuildDeviceIoControlRequest( + IoctlCode, + DeviceObject, + InputBuffer, + InputBufferSize, + OutputBuffer, + OutBufferSize, + FALSE, + &Event, + &IoStatus); + + if (Irp == NULL) + { + FFSPrint((DBG_ERROR, "FFSDiskIoControl: Building IRQ error!\n")); + return STATUS_INSUFFICIENT_RESOURCES; + } + + Status = IoCallDriver(DeviceObject, Irp); + + if (Status == STATUS_PENDING) + { + KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); + Status = IoStatus.Status; + } + + if (OutputBufferSize) + { + *OutputBufferSize = (ULONG) IoStatus.Information; + } + + return Status; +} + + +NTSTATUS NTAPI +FFSMediaEjectControlCompletion( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID Contxt) +{ + PKEVENT Event = (PKEVENT)Contxt; + + KeSetEvent(Event, 0, FALSE); + + UNREFERENCED_PARAMETER(DeviceObject); + + return STATUS_SUCCESS; +} + + +__drv_mustHoldCriticalRegion +VOID +FFSMediaEjectControl( + IN PFFS_IRP_CONTEXT IrpContext, + IN PFFS_VCB Vcb, + IN BOOLEAN bPrevent) +{ + PIRP Irp; + KEVENT Event; + NTSTATUS Status; + PREVENT_MEDIA_REMOVAL Prevent; + IO_STATUS_BLOCK IoStatus; + + PAGED_CODE(); + + ExAcquireResourceExclusiveLite( + &Vcb->MainResource, + TRUE); + + if (bPrevent != IsFlagOn(Vcb->Flags, VCB_REMOVAL_PREVENTED)) + { + if (bPrevent) + { + SetFlag(Vcb->Flags, VCB_REMOVAL_PREVENTED); + } + else + { + ClearFlag(Vcb->Flags, VCB_REMOVAL_PREVENTED); + } + } + + ExReleaseResourceForThreadLite( + &Vcb->MainResource, + ExGetCurrentResourceThread()); + + Prevent.PreventMediaRemoval = bPrevent; + + KeInitializeEvent(&Event, NotificationEvent, FALSE); + + Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_MEDIA_REMOVAL, + Vcb->TargetDeviceObject, + &Prevent, + sizeof(PREVENT_MEDIA_REMOVAL), + NULL, + 0, + FALSE, + NULL, + &IoStatus); + + if (Irp != NULL) + { + IoSetCompletionRoutine(Irp, + FFSMediaEjectControlCompletion, + &Event, + TRUE, + TRUE, + TRUE); + + Status = IoCallDriver(Vcb->TargetDeviceObject, Irp); + + if (Status == STATUS_PENDING) + { + Status = KeWaitForSingleObject(&Event, + Executive, + KernelMode, + FALSE, + NULL); + } + } +} + + +NTSTATUS +FFSDiskShutDown( + PFFS_VCB Vcb) +{ + PIRP Irp; + KEVENT Event; + NTSTATUS Status; + IO_STATUS_BLOCK IoStatus; + + PAGED_CODE(); + + KeInitializeEvent(&Event, NotificationEvent, FALSE); + + Irp = IoBuildSynchronousFsdRequest(IRP_MJ_SHUTDOWN, + Vcb->TargetDeviceObject, + NULL, + 0, + NULL, + &Event, + &IoStatus); + + if (Irp) + { + Status = IoCallDriver(Vcb->TargetDeviceObject, Irp); + + if (Status == STATUS_PENDING) + { + KeWaitForSingleObject(&Event, + Executive, + KernelMode, + FALSE, + NULL); + + Status = IoStatus.Status; + } + } + else + { + Status = IoStatus.Status; + } + + return Status; +} diff --git a/reactos/drivers/filesystems/ffs/src/cleanup.c b/reactos/drivers/filesystems/ffs/src/cleanup.c new file mode 100644 index 00000000000..c3be1ed0205 --- /dev/null +++ b/reactos/drivers/filesystems/ffs/src/cleanup.c @@ -0,0 +1,380 @@ +/* + * FFS File System Driver for Windows + * + * cleanup.c + * + * 2004.5.6 ~ + * + * Lee Jae-Hong, http://www.pyrasis.com + * + * See License.txt + * + */ + +#include "ntifs.h" +#include "ffsdrv.h" + +/* Globals */ + +extern PFFS_GLOBAL FFSGlobal; + +/* Definitions */ + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE, FFSCleanup) +#endif + + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSCleanup( + IN PFFS_IRP_CONTEXT IrpContext) +{ + PDEVICE_OBJECT DeviceObject; + NTSTATUS Status = STATUS_SUCCESS; + PFFS_VCB Vcb = 0; + BOOLEAN VcbResourceAcquired = FALSE; + PFILE_OBJECT FileObject; + PFFS_FCB Fcb = 0; + BOOLEAN FcbResourceAcquired = FALSE; + BOOLEAN FcbPagingIoAcquired = FALSE; + PFFS_CCB Ccb; + PIRP Irp; + + PAGED_CODE(); + + _SEH2_TRY + { + ASSERT(IrpContext != NULL); + + ASSERT((IrpContext->Identifier.Type == FFSICX) && + (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); + + DeviceObject = IrpContext->DeviceObject; + + if (DeviceObject == FFSGlobal->DeviceObject) + { + Status = STATUS_SUCCESS; + _SEH2_LEAVE; + } + + Vcb = (PFFS_VCB)DeviceObject->DeviceExtension; + + ASSERT(Vcb != NULL); + + ASSERT((Vcb->Identifier.Type == FFSVCB) && + (Vcb->Identifier.Size == sizeof(FFS_VCB))); + + if (!IsFlagOn(Vcb->Flags, VCB_INITIALIZED)) + { + Status = STATUS_SUCCESS; + _SEH2_LEAVE; + } + +#ifdef _MSC_VER +#pragma prefast( suppress: 28137, "by design" ) +#endif + if (!ExAcquireResourceExclusiveLite( + &Vcb->MainResource, + IrpContext->IsSynchronous)) + { + Status = STATUS_PENDING; + _SEH2_LEAVE; + } + + VcbResourceAcquired = TRUE; + + FileObject = IrpContext->FileObject; + + Fcb = (PFFS_FCB)FileObject->FsContext; + + if (!Fcb) + { + Status = STATUS_SUCCESS; + _SEH2_LEAVE; + } + + if (Fcb->Identifier.Type == FFSVCB) + { + if (IsFlagOn(Vcb->Flags, VCB_VOLUME_LOCKED) && + (Vcb->LockFile == FileObject)) + { + ClearFlag(Vcb->Flags, VCB_VOLUME_LOCKED); + Vcb->LockFile = NULL; + + FFSClearVpbFlag(Vcb->Vpb, VPB_LOCKED); + } + + Vcb->OpenHandleCount--; + + if (!Vcb->OpenHandleCount) + { + IoRemoveShareAccess(FileObject, &Vcb->ShareAccess); + } + + Status = STATUS_SUCCESS; + _SEH2_LEAVE; + } + + ASSERT((Fcb->Identifier.Type == FFSFCB) && + (Fcb->Identifier.Size == sizeof(FFS_FCB))); + +/* + if (!IsFlagOn(Vcb->Flags, VCB_READ_ONLY) && + !IsFlagOn(Fcb->Flags, FCB_PAGE_FILE)) +*/ + { +#ifdef _MSC_VER +#pragma prefast( suppress: 28137, "by design" ) +#endif + if (!ExAcquireResourceExclusiveLite( + &Fcb->MainResource, + IrpContext->IsSynchronous)) + { + Status = STATUS_PENDING; + _SEH2_LEAVE; + } + + FcbResourceAcquired = TRUE; + } + + Ccb = (PFFS_CCB)FileObject->FsContext2; + + if (!Ccb) + { + Status = STATUS_SUCCESS; + _SEH2_LEAVE; + } + + if (IsFlagOn(FileObject->Flags, FO_CLEANUP_COMPLETE)) + { + if (IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED) && + IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK) && + !IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED)) + { + Status = FFSFlushFile(Fcb); + } + + _SEH2_LEAVE; + } + + ASSERT((Ccb->Identifier.Type == FFSCCB) && + (Ccb->Identifier.Size == sizeof(FFS_CCB))); + Irp = IrpContext->Irp; + + Fcb->OpenHandleCount--; + + if (!IsFlagOn(FileObject->Flags, FO_CACHE_SUPPORTED)) + { + Fcb->NonCachedOpenCount--; + } + + Vcb->OpenFileHandleCount--; + + if (IsFlagOn(Fcb->Flags, FCB_DELETE_ON_CLOSE)) + { + SetFlag(Fcb->Flags, FCB_DELETE_PENDING); + + if (IsDirectory(Fcb)) + { + FsRtlNotifyFullChangeDirectory( + Vcb->NotifySync, + &Vcb->NotifyList, + Fcb, + NULL, + FALSE, + FALSE, + 0, + NULL, + NULL, + NULL); + } + } + + if (IsDirectory(Fcb)) + { + FsRtlNotifyCleanup( + Vcb->NotifySync, + &Vcb->NotifyList, + Ccb); + } + else + { + // + // Drop any byte range locks this process may have on the file. + // + FsRtlFastUnlockAll( + &Fcb->FileLockAnchor, + FileObject, + IoGetRequestorProcess(Irp), + NULL); + + // + // If there are no byte range locks owned by other processes on the + // file the fast I/O read/write functions doesn't have to check for + // locks so we set IsFastIoPossible to FastIoIsPossible again. + // + if (!FsRtlGetNextFileLock(&Fcb->FileLockAnchor, TRUE)) + { + if (Fcb->Header.IsFastIoPossible != FastIoIsPossible) + { + FFSPrint(( + DBG_INFO, ": %-16.16s %-31s %s\n", + FFSGetCurrentProcessName(), + "FastIoIsPossible", + Fcb->AnsiFileName.Buffer)); + + Fcb->Header.IsFastIoPossible = FastIoIsPossible; + } + } + } + + if (IsFlagOn(FileObject->Flags, FO_CACHE_SUPPORTED) && + (Fcb->NonCachedOpenCount != 0) && + (Fcb->NonCachedOpenCount == Fcb->ReferenceCount) && + (Fcb->SectionObject.DataSectionObject != NULL)) + { + + if(!IsFlagOn(Vcb->Flags, VCB_READ_ONLY) && + !IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED)) + { + CcFlushCache(&Fcb->SectionObject, NULL, 0, NULL); + } + + ExAcquireResourceExclusiveLite(&(Fcb->PagingIoResource), TRUE); + ExReleaseResourceLite(&(Fcb->PagingIoResource)); + + CcPurgeCacheSection(&Fcb->SectionObject, + NULL, + 0, + FALSE); + } + +#if !FFS_READ_ONLY + if (Fcb->OpenHandleCount == 0) + { + if (IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING)) + { + BOOLEAN bDeleted = FALSE; + + // + // Have to delete this file... + // +#ifdef _MSC_VER +#pragma prefast( suppress: 28137, "by design" ) +#endif + if (!ExAcquireResourceExclusiveLite( + &Fcb->PagingIoResource, + IrpContext->IsSynchronous)) + { + Status = STATUS_PENDING; + _SEH2_LEAVE; + } + + FcbPagingIoAcquired = TRUE; + + bDeleted = FFSDeleteFile(IrpContext, Vcb, Fcb); + + if (bDeleted) + { + if (IsDirectory(Fcb)) + { + FFSNotifyReportChange(IrpContext, Vcb, Fcb, + FILE_NOTIFY_CHANGE_DIR_NAME, + FILE_ACTION_REMOVED); + } + else + { + FFSNotifyReportChange(IrpContext, Vcb, Fcb, + FILE_NOTIFY_CHANGE_FILE_NAME, + FILE_ACTION_REMOVED); + } + } + + if (FcbPagingIoAcquired) + { + ExReleaseResourceForThreadLite( + &Fcb->PagingIoResource, + ExGetCurrentResourceThread()); + + FcbPagingIoAcquired = FALSE; + } + +/* + if (bDeleted) + { + FFSPurgeFile(Fcb, FALSE); + } +*/ + } + } +#endif // !FFS_READ_ONLY + + if (!IsDirectory(Fcb) && FileObject->PrivateCacheMap) + { + FFSPrint((DBG_INFO, "FFSCleanup: CcUninitializeCacheMap is called for %s.\n", + Fcb->AnsiFileName.Buffer)); + + CcUninitializeCacheMap( + FileObject, + (PLARGE_INTEGER)(&(Fcb->Header.FileSize)), + NULL); + } + + if (!Fcb->OpenHandleCount) + { + IoRemoveShareAccess(FileObject, &Fcb->ShareAccess); + } + + FFSPrint((DBG_INFO, "FFSCleanup: OpenCount: %u ReferCount: %u %s\n", + Fcb->OpenHandleCount, Fcb->ReferenceCount, Fcb->AnsiFileName.Buffer)); + + Status = STATUS_SUCCESS; + + if (FileObject) + { + SetFlag(FileObject->Flags, FO_CLEANUP_COMPLETE); + } + } + + _SEH2_FINALLY + { + + if (FcbPagingIoAcquired) + { + ExReleaseResourceForThreadLite( + &Fcb->PagingIoResource, + ExGetCurrentResourceThread()); + } + + if (FcbResourceAcquired) + { + ExReleaseResourceForThreadLite( + &Fcb->MainResource, + ExGetCurrentResourceThread()); + } + + if (VcbResourceAcquired) + { + ExReleaseResourceForThreadLite( + &Vcb->MainResource, + ExGetCurrentResourceThread()); + } + + if (!IrpContext->ExceptionInProgress) + { + if (Status == STATUS_PENDING) + { + FFSQueueRequest(IrpContext); + } + else + { + IrpContext->Irp->IoStatus.Status = Status; + + FFSCompleteIrpContext(IrpContext, Status); + } + } + } _SEH2_END; + + return Status; +} diff --git a/reactos/drivers/filesystems/ffs/src/close.c b/reactos/drivers/filesystems/ffs/src/close.c new file mode 100644 index 00000000000..50ace27c162 --- /dev/null +++ b/reactos/drivers/filesystems/ffs/src/close.c @@ -0,0 +1,342 @@ +/* + * FFS File System Driver for Windows + * + * close.c + * + * 2004.5.6 ~ + * + * Lee Jae-Hong, http://www.pyrasis.com + * + * See License.txt + * + */ + +#include "ntifs.h" +#include "ffsdrv.h" + +/* Globals */ + +extern PFFS_GLOBAL FFSGlobal; + +/* Definitions */ + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE, FFSClose) +#pragma alloc_text(PAGE, FFSQueueCloseRequest) +#pragma alloc_text(PAGE, FFSDeQueueCloseRequest) +#endif + + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSClose( + IN PFFS_IRP_CONTEXT IrpContext) +{ + PDEVICE_OBJECT DeviceObject; + NTSTATUS Status = STATUS_SUCCESS; + PFFS_VCB Vcb = 0; + BOOLEAN VcbResourceAcquired = FALSE; + PFILE_OBJECT FileObject; + PFFS_FCB Fcb = 0; + BOOLEAN FcbResourceAcquired = FALSE; + PFFS_CCB Ccb; + BOOLEAN FreeVcb = FALSE; + + PAGED_CODE(); + + _SEH2_TRY + { + ASSERT(IrpContext != NULL); + + ASSERT((IrpContext->Identifier.Type == FFSICX) && + (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); + + DeviceObject = IrpContext->DeviceObject; + + if (DeviceObject == FFSGlobal->DeviceObject) + { + Status = STATUS_SUCCESS; + _SEH2_LEAVE; + } + + Vcb = (PFFS_VCB) DeviceObject->DeviceExtension; + + ASSERT(Vcb != NULL); + + ASSERT((Vcb->Identifier.Type == FFSVCB) && + (Vcb->Identifier.Size == sizeof(FFS_VCB))); + + ASSERT(IsMounted(Vcb)); + + if (!ExAcquireResourceExclusiveLite( + &Vcb->MainResource, + IrpContext->IsSynchronous)) + { + FFSPrint((DBG_INFO, "FFSClose: PENDING ... Vcb: %xh/%xh\n", + Vcb->OpenFileHandleCount, Vcb->ReferenceCount)); + + Status = STATUS_PENDING; + _SEH2_LEAVE; + } + + VcbResourceAcquired = TRUE; + + FileObject = IrpContext->FileObject; + + if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DELAY_CLOSE)) + { + Fcb = IrpContext->Fcb; + Ccb = IrpContext->Ccb; + } + else + { + Fcb = (PFFS_FCB)FileObject->FsContext; + + if (!Fcb) + { + Status = STATUS_SUCCESS; + _SEH2_LEAVE; + } + + ASSERT(Fcb != NULL); + + Ccb = (PFFS_CCB)FileObject->FsContext2; + } + + if (Fcb->Identifier.Type == FFSVCB) + { + Vcb->ReferenceCount--; + + if (!Vcb->ReferenceCount && FlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING)) + { + FreeVcb = TRUE; + } + + if (Ccb) + { + FFSFreeCcb(Ccb); + if (FileObject) + { + FileObject->FsContext2 = Ccb = NULL; + } + } + + Status = STATUS_SUCCESS; + + _SEH2_LEAVE; + } + + if (Fcb->Identifier.Type != FFSFCB || Fcb->Identifier.Size != sizeof(FFS_FCB)) + { +#if DBG + FFSPrint((DBG_ERROR, "FFSClose: Strange IRP_MJ_CLOSE by system!\n")); + ExAcquireResourceExclusiveLite( + &FFSGlobal->CountResource, + TRUE); + + FFSGlobal->IRPCloseCount++; + + ExReleaseResourceForThreadLite( + &FFSGlobal->CountResource, + ExGetCurrentResourceThread()); +#endif + _SEH2_LEAVE; + } + + ASSERT((Fcb->Identifier.Type == FFSFCB) && + (Fcb->Identifier.Size == sizeof(FFS_FCB))); + + /* + if ((!IsFlagOn(Vcb->Flags, VCB_READ_ONLY)) && + (!IsFlagOn(Fcb->Flags, FCB_PAGE_FILE))) + */ + { + if (!ExAcquireResourceExclusiveLite( + &Fcb->MainResource, + IrpContext->IsSynchronous)) + { + Status = STATUS_PENDING; + _SEH2_LEAVE; + } + + FcbResourceAcquired = TRUE; + } + + if (!Ccb) + { + Status = STATUS_SUCCESS; + _SEH2_LEAVE; + } + + ASSERT((Ccb->Identifier.Type == FFSCCB) && + (Ccb->Identifier.Size == sizeof(FFS_CCB))); + + Fcb->ReferenceCount--; + Vcb->ReferenceCount--; + + if (!Vcb->ReferenceCount && IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING)) + { + FreeVcb = TRUE; + } + + FFSPrint((DBG_INFO, "FFSClose: OpenHandleCount: %u ReferenceCount: %u %s\n", + Fcb->OpenHandleCount, Fcb->ReferenceCount, Fcb->AnsiFileName.Buffer)); + + if (Ccb) + { + FFSFreeCcb(Ccb); + + if (FileObject) + { + FileObject->FsContext2 = Ccb = NULL; + } + } + + if (!Fcb->ReferenceCount) + { + // + // Remove Fcb from Vcb->FcbList ... + // + + RemoveEntryList(&Fcb->Next); + + FFSFreeFcb(Fcb); + + FcbResourceAcquired = FALSE; + } + + Status = STATUS_SUCCESS; + } + + _SEH2_FINALLY + { + if (FcbResourceAcquired) + { + ExReleaseResourceForThreadLite( + &Fcb->MainResource, + ExGetCurrentResourceThread()); + } + + if (VcbResourceAcquired) + { + ExReleaseResourceForThreadLite( + &Vcb->MainResource, + ExGetCurrentResourceThread()); + } + + if (!IrpContext->ExceptionInProgress) + { + if (Status == STATUS_PENDING) + { + FFSQueueCloseRequest(IrpContext); +#if 0 +/* + Status = STATUS_SUCCESS; + + if (IrpContext->Irp != NULL) + { + IrpContext->Irp->IoStatus.Status = Status; + + FFSCompleteRequest( + IrpContext->Irp, + (BOOLEAN)!IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED), + (CCHAR) + (NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT)); + + IrpContext->Irp = NULL; + } +*/ +#endif + } + else + { + FFSCompleteIrpContext(IrpContext, Status); + + if (FreeVcb) + { + ExAcquireResourceExclusiveLite( + &FFSGlobal->Resource, TRUE); + + FFSClearVpbFlag(Vcb->Vpb, VPB_MOUNTED); + + FFSRemoveVcb(Vcb); + + ExReleaseResourceForThreadLite( + &FFSGlobal->Resource, + ExGetCurrentResourceThread()); + + FFSFreeVcb(Vcb); + } + } + } + } _SEH2_END; + + return Status; +} + + +VOID +FFSQueueCloseRequest( + IN PFFS_IRP_CONTEXT IrpContext) +{ + PAGED_CODE(); + + ASSERT(IrpContext); + + ASSERT((IrpContext->Identifier.Type == FFSICX) && + (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); + + if (!IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DELAY_CLOSE)) + { + SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DELAY_CLOSE); + + IrpContext->Fcb = (PFFS_FCB)IrpContext->FileObject->FsContext; + IrpContext->Ccb = (PFFS_CCB)IrpContext->FileObject->FsContext2; + + IrpContext->FileObject = NULL; + } + + // IsSynchronous means we can block (so we don't requeue it) + IrpContext->IsSynchronous = TRUE; + + ExInitializeWorkItem( + &IrpContext->WorkQueueItem, + FFSDeQueueCloseRequest, + IrpContext); + + ExQueueWorkItem(&IrpContext->WorkQueueItem, CriticalWorkQueue); +} + + +VOID NTAPI +FFSDeQueueCloseRequest( + IN PVOID Context) +{ + PFFS_IRP_CONTEXT IrpContext; + + PAGED_CODE(); + + IrpContext = (PFFS_IRP_CONTEXT) Context; + + ASSERT(IrpContext); + + ASSERT((IrpContext->Identifier.Type == FFSICX) && + (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); + + _SEH2_TRY + { + _SEH2_TRY + { + FsRtlEnterFileSystem(); + FFSClose(IrpContext); + } + _SEH2_EXCEPT (FFSExceptionFilter(IrpContext, _SEH2_GetExceptionInformation())) + { + FFSExceptionHandler(IrpContext); + } _SEH2_END; + } + _SEH2_FINALLY + { + FsRtlExitFileSystem(); + } _SEH2_END; +} diff --git a/reactos/drivers/filesystems/ffs/src/cmcb.c b/reactos/drivers/filesystems/ffs/src/cmcb.c new file mode 100644 index 00000000000..b8e90a9b039 --- /dev/null +++ b/reactos/drivers/filesystems/ffs/src/cmcb.c @@ -0,0 +1,218 @@ +/* + * FFS File System Driver for Windows + * + * cmcb.c + * + * 2004.5.6 ~ + * + * Lee Jae-Hong, http://www.pyrasis.com + * + * See License.txt + * + */ + +#include "ntifs.h" +#include "ffsdrv.h" + +/* Globals */ + +extern PFFS_GLOBAL FFSGlobal; + +/* Definitions */ + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE, FFSAcquireForLazyWrite) +#pragma alloc_text(PAGE, FFSReleaseFromLazyWrite) +#pragma alloc_text(PAGE, FFSAcquireForReadAhead) +#pragma alloc_text(PAGE, FFSReleaseFromReadAhead) +#pragma alloc_text(PAGE, FFSNoOpAcquire) +#pragma alloc_text(PAGE, FFSNoOpRelease) +#endif + + +__drv_mustHoldCriticalRegion +BOOLEAN NTAPI +FFSAcquireForLazyWrite( + IN PVOID Context, + IN BOOLEAN Wait) +{ + // + // On a readonly filesystem this function still has to exist but it + // doesn't need to do anything. + + PFFS_FCB Fcb; + + PAGED_CODE(); + + Fcb = (PFFS_FCB)Context; + + ASSERT(Fcb != NULL); + + ASSERT((Fcb->Identifier.Type == FFSFCB) && + (Fcb->Identifier.Size == sizeof(FFS_FCB))); + + FFSPrint((DBG_INFO, "FFSAcquireForLazyWrite: %s %s %s\n", + FFSGetCurrentProcessName(), + "ACQUIRE_FOR_LAZY_WRITE", + Fcb->AnsiFileName.Buffer)); + + + if (!IsFlagOn(Fcb->Vcb->Flags, VCB_READ_ONLY)) + { + FFSPrint((DBG_INFO, "FFSAcquireForLazyWrite: Inode=%xh %S\n", + Fcb->FFSMcb->Inode, Fcb->FFSMcb->ShortName.Buffer)); + + if(!ExAcquireResourceSharedLite( + &Fcb->PagingIoResource, Wait)) + { + return FALSE; + } + } + + ASSERT(IoGetTopLevelIrp() == NULL); + + IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP); + + return TRUE; +} + + +__drv_mustHoldCriticalRegion +VOID NTAPI +FFSReleaseFromLazyWrite( + IN PVOID Context) +{ + // + // On a readonly filesystem this function still has to exist but it + // doesn't need to do anything. + PFFS_FCB Fcb; + + PAGED_CODE(); + + Fcb = (PFFS_FCB)Context; + + ASSERT(Fcb != NULL); + + ASSERT((Fcb->Identifier.Type == FFSFCB) && + (Fcb->Identifier.Size == sizeof(FFS_FCB))); + + FFSPrint((DBG_INFO, "FFSReleaseFromLazyWrite: %s %s %s\n", + FFSGetCurrentProcessName(), + "RELEASE_FROM_LAZY_WRITE", + Fcb->AnsiFileName.Buffer)); + + if (!IsFlagOn(Fcb->Vcb->Flags, VCB_READ_ONLY)) + { + FFSPrint((DBG_INFO, "FFSReleaseFromLazyWrite: Inode=%xh %S\n", + Fcb->FFSMcb->Inode, Fcb->FFSMcb->ShortName.Buffer)); + + ExReleaseResourceLite(&Fcb->PagingIoResource); + } + + ASSERT(IoGetTopLevelIrp() == (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP); + + IoSetTopLevelIrp(NULL); + +} + + +__drv_mustHoldCriticalRegion +BOOLEAN NTAPI +FFSAcquireForReadAhead( + IN PVOID Context, + IN BOOLEAN Wait) +{ + PFFS_FCB Fcb; + + PAGED_CODE(); + + Fcb = (PFFS_FCB)Context; + + ASSERT(Fcb != NULL); + + ASSERT((Fcb->Identifier.Type == FFSFCB) && + (Fcb->Identifier.Size == sizeof(FFS_FCB))); + + FFSPrint((DBG_INFO, "FFSAcquireForReadAhead: Inode=%xh %S\n", + Fcb->FFSMcb->Inode, Fcb->FFSMcb->ShortName.Buffer)); + + if (!ExAcquireResourceSharedLite( + &Fcb->MainResource, Wait)) + return FALSE; + + ASSERT(IoGetTopLevelIrp() == NULL); + + IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP); + + return TRUE; +} + + +__drv_mustHoldCriticalRegion +VOID NTAPI +FFSReleaseFromReadAhead( + IN PVOID Context) +{ + PFFS_FCB Fcb; + + PAGED_CODE(); + + Fcb = (PFFS_FCB)Context; + + ASSERT(Fcb != NULL); + + ASSERT((Fcb->Identifier.Type == FFSFCB) && + (Fcb->Identifier.Size == sizeof(FFS_FCB))); + + FFSPrint((DBG_INFO, "FFSReleaseFromReadAhead: Inode=%xh %S\n", + Fcb->FFSMcb->Inode, Fcb->FFSMcb->ShortName.Buffer)); + + IoSetTopLevelIrp(NULL); + + ExReleaseResourceLite(&Fcb->MainResource); +} + + +BOOLEAN NTAPI +FFSNoOpAcquire( + IN PVOID Fcb, + IN BOOLEAN Wait) +{ + UNREFERENCED_PARAMETER(Fcb); + UNREFERENCED_PARAMETER(Wait); + + // + // This is a kludge because Cc is really the top level. We it + // enters the file system, we will think it is a resursive call + // and complete the request with hard errors or verify. It will + // have to deal with them, somehow.... + // + + PAGED_CODE(); + + ASSERT(IoGetTopLevelIrp() == NULL); + + IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP); + + return TRUE; +} + + +VOID NTAPI +FFSNoOpRelease( + IN PVOID Fcb) +{ + // + // Clear the kludge at this point. + // + + PAGED_CODE(); + + ASSERT(IoGetTopLevelIrp() == (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP); + + IoSetTopLevelIrp(NULL); + + UNREFERENCED_PARAMETER(Fcb); + + return; +} diff --git a/reactos/drivers/filesystems/ffs/src/create.c b/reactos/drivers/filesystems/ffs/src/create.c new file mode 100644 index 00000000000..f21e90519dc --- /dev/null +++ b/reactos/drivers/filesystems/ffs/src/create.c @@ -0,0 +1,2055 @@ +/* + * FFS File System Driver for Windows + * + * create.c + * + * 2004.5.6 ~ + * + * Lee Jae-Hong, http://www.pyrasis.com + * + * See License.txt + * + */ + +#include "ntifs.h" +#include "ffsdrv.h" + +/* Globals */ + +extern PFFS_GLOBAL FFSGlobal; + +/* Definitions */ + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE, FFSv1LookupFileName) +#pragma alloc_text(PAGE, FFSv2LookupFileName) +#pragma alloc_text(PAGE, FFSSearchFcbList) +#pragma alloc_text(PAGE, FFSv1ScanDir) +#pragma alloc_text(PAGE, FFSv2ScanDir) +#pragma alloc_text(PAGE, FFSCreateFile) +#pragma alloc_text(PAGE, FFSCreateVolume) +#pragma alloc_text(PAGE, FFSCreate) +#pragma alloc_text(PAGE, FFSCreateInode) +#pragma alloc_text(PAGE, FFSSupersedeOrOverWriteFile) +#endif + + +NTSTATUS +FFSv1LookupFileName( + IN PFFS_VCB Vcb, + IN PUNICODE_STRING FullFileName, + IN PFFS_MCB ParentMcb, + OUT PFFS_MCB* FFSMcb, + IN OUT PFFSv1_INODE dinode1) +{ + NTSTATUS Status; + UNICODE_STRING FileName; + PFFS_MCB Mcb = 0; + + FFS_DIR_ENTRY ffs_dir; + int i = 0; + BOOLEAN bRun = TRUE; + BOOLEAN bParent = FALSE; + FFSv1_INODE in; + ULONG off = 0; + + PAGED_CODE(); + + Status = STATUS_OBJECT_NAME_NOT_FOUND; + + *FFSMcb = NULL; + + if (ParentMcb) + { + bParent = TRUE; + } + else if (FullFileName->Buffer[0] == L'\\') + { + ParentMcb = Vcb->McbTree; + } + else + { + return STATUS_OBJECT_PATH_NOT_FOUND; + } + + RtlZeroMemory(&ffs_dir, sizeof(FFS_DIR_ENTRY)); + + if (FullFileName->Length == 0) + { + return Status; + } + + if (FullFileName->Length == 2 && FullFileName->Buffer[0] == L'\\') + { + if (!FFSv1LoadInode(Vcb, ParentMcb->Inode, dinode1)) + { + return Status; + } + + *FFSMcb = Vcb->McbTree; + + return STATUS_SUCCESS; + } + + while (bRun && i < FullFileName->Length / 2) + { + int Length; + ULONG FileAttr = FILE_ATTRIBUTE_NORMAL; + + if (bParent) + { + bParent = FALSE; + } + else + { + while(i < FullFileName->Length / 2 && FullFileName->Buffer[i] == L'\\') i++; + } + + Length = i; + + while(i < FullFileName->Length / 2 && (FullFileName->Buffer[i] != L'\\')) i++; + + if (i - Length > 0) + { + FileName = *FullFileName; + FileName.Buffer += Length; + FileName.Length = (USHORT)((i - Length) * 2); + + Mcb = FFSSearchMcb(Vcb, ParentMcb, &FileName); + + if (Mcb) + { + ParentMcb = Mcb; + + Status = STATUS_SUCCESS; + + if (!IsFlagOn(Mcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY)) + { + if (i < FullFileName->Length / 2) + { + Status = STATUS_OBJECT_PATH_NOT_FOUND; + } + + break; + } + } + else + { + if (!FFSv1LoadInode(Vcb, ParentMcb->Inode, &in)) + { + Status = STATUS_OBJECT_NAME_NOT_FOUND; + break; + } + + if ((in.di_mode & IFMT) != IFDIR) + { + if (i < FullFileName->Length / 2) + { + Status = STATUS_OBJECT_NAME_NOT_FOUND; + } + break; + } + + Status = FFSv1ScanDir( + Vcb, + ParentMcb, + &FileName, + &off, + &in, + &ffs_dir); + + if (!NT_SUCCESS(Status)) + { + bRun = FALSE; + /* + if (i >= FullFileName->Length/2) + { + *FFSMcb = ParentMcb; + } + */ + } + else + { +#if 0 + if (IsFlagOn(SUPER_BLOCK->s_feature_incompat, + FFS_FEATURE_INCOMPAT_FILETYPE)) + { + if (ffs_dir.d_type == FFS_FT_DIR) + SetFlag(FileAttr, FILE_ATTRIBUTE_DIRECTORY); + } + else +#endif + { + if (!FFSv1LoadInode(Vcb, ffs_dir.d_ino, &in)) + { + Status = STATUS_OBJECT_NAME_NOT_FOUND; + break; + } + + if ((in.di_mode & IFMT) == IFDIR) + { + SetFlag(FileAttr, FILE_ATTRIBUTE_DIRECTORY); + } + } + + SetFlag(ParentMcb->Flags, MCB_IN_USE); + Mcb = FFSAllocateMcb(Vcb, &FileName, FileAttr); + ClearFlag(ParentMcb->Flags, MCB_IN_USE); + + if (!Mcb) + { + Status = STATUS_OBJECT_NAME_NOT_FOUND; + break; + } + + Mcb->Inode = ffs_dir.d_ino; + Mcb->DeOffset = off; + FFSAddMcbNode(Vcb, ParentMcb, Mcb); + ParentMcb = Mcb; + } + } + } + else + { + break; + } + } + + if (NT_SUCCESS(Status)) + { + *FFSMcb = Mcb; + if (dinode1) + { + if (!FFSv1LoadInode(Vcb, Mcb->Inode, dinode1)) + { + FFSPrint((DBG_ERROR, "FFSv1LookupFileName: error loading Inode %xh\n", + Mcb->Inode)); + Status = STATUS_INSUFFICIENT_RESOURCES; + } + } + } + + return Status; +} + + +NTSTATUS +FFSv2LookupFileName( + IN PFFS_VCB Vcb, + IN PUNICODE_STRING FullFileName, + IN PFFS_MCB ParentMcb, + OUT PFFS_MCB* FFSMcb, + IN OUT PFFSv2_INODE dinode2) +{ + NTSTATUS Status; + UNICODE_STRING FileName; + PFFS_MCB Mcb = 0; + + FFS_DIR_ENTRY ffs_dir; + int i = 0; + BOOLEAN bRun = TRUE; + BOOLEAN bParent = FALSE; + FFSv2_INODE in; + ULONG off = 0; + + PAGED_CODE(); + + Status = STATUS_OBJECT_NAME_NOT_FOUND; + + *FFSMcb = NULL; + + if (ParentMcb) + { + bParent = TRUE; + } + else if (FullFileName->Buffer[0] == L'\\') + { + ParentMcb = Vcb->McbTree; + } + else + { + return STATUS_OBJECT_PATH_NOT_FOUND; + } + + RtlZeroMemory(&ffs_dir, sizeof(FFS_DIR_ENTRY)); + + if (FullFileName->Length == 0) + { + return Status; + } + + if (FullFileName->Length == 2 && FullFileName->Buffer[0] == L'\\') + { + if (!FFSv2LoadInode(Vcb, ParentMcb->Inode, dinode2)) + { + return Status; + } + + *FFSMcb = Vcb->McbTree; + + return STATUS_SUCCESS; + } + + while (bRun && i < FullFileName->Length / 2) + { + int Length; + ULONG FileAttr = FILE_ATTRIBUTE_NORMAL; + + if (bParent) + { + bParent = FALSE; + } + else + { + while(i < FullFileName->Length / 2 && FullFileName->Buffer[i] == L'\\') i++; + } + + Length = i; + + while(i < FullFileName->Length / 2 && (FullFileName->Buffer[i] != L'\\')) i++; + + if (i - Length > 0) + { + FileName = *FullFileName; + FileName.Buffer += Length; + FileName.Length = (USHORT)((i - Length) * 2); + + Mcb = FFSSearchMcb(Vcb, ParentMcb, &FileName); + + if (Mcb) + { + ParentMcb = Mcb; + + Status = STATUS_SUCCESS; + + if (!IsFlagOn(Mcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY)) + { + if (i < FullFileName->Length / 2) + { + Status = STATUS_OBJECT_PATH_NOT_FOUND; + } + + break; + } + } + else + { + if (!FFSv2LoadInode(Vcb, ParentMcb->Inode, &in)) + { + Status = STATUS_OBJECT_NAME_NOT_FOUND; + break; + } + + if ((in.di_mode & IFMT) != IFDIR) + { + if (i < FullFileName->Length / 2) + { + Status = STATUS_OBJECT_NAME_NOT_FOUND; + } + break; + } + + Status = FFSv2ScanDir( + Vcb, + ParentMcb, + &FileName, + &off, + &in, + &ffs_dir); + + if (!NT_SUCCESS(Status)) + { + bRun = FALSE; + /* + if (i >= FullFileName->Length/2) + { + *FFSMcb = ParentMcb; + } + */ + } + else + { +#if 0 + if (IsFlagOn(SUPER_BLOCK->s_feature_incompat, + FFS_FEATURE_INCOMPAT_FILETYPE)) + { + if (ffs_dir.d_type == FFS_FT_DIR) + SetFlag(FileAttr, FILE_ATTRIBUTE_DIRECTORY); + } + else +#endif + { + if (!FFSv2LoadInode(Vcb, ffs_dir.d_ino, &in)) + { + Status = STATUS_OBJECT_NAME_NOT_FOUND; + break; + } + + if ((in.di_mode & IFMT) == IFDIR) + { + SetFlag(FileAttr, FILE_ATTRIBUTE_DIRECTORY); + } + } + + SetFlag(ParentMcb->Flags, MCB_IN_USE); + Mcb = FFSAllocateMcb(Vcb, &FileName, FileAttr); + ClearFlag(ParentMcb->Flags, MCB_IN_USE); + + if (!Mcb) + { + Status = STATUS_OBJECT_NAME_NOT_FOUND; + break; + } + + Mcb->Inode = ffs_dir.d_ino; + Mcb->DeOffset = off; + FFSAddMcbNode(Vcb, ParentMcb, Mcb); + ParentMcb = Mcb; + } + } + } + else + { + break; + } + } + + if (NT_SUCCESS(Status)) + { + *FFSMcb = Mcb; + if (dinode2) + { + if (!FFSv2LoadInode(Vcb, Mcb->Inode, dinode2)) + { + FFSPrint((DBG_ERROR, "FFSv2LookupFileName: error loading Inode %xh\n", + Mcb->Inode)); + Status = STATUS_INSUFFICIENT_RESOURCES; + } + } + } + + return Status; +} + + +NTSTATUS +FFSv1ScanDir( + IN PFFS_VCB Vcb, + IN PFFS_MCB ParentMcb, + IN PUNICODE_STRING FileName, + IN OUT PULONG Index, + IN PFFSv1_INODE dinode1, + IN OUT PFFS_DIR_ENTRY ffs_dir) +{ + NTSTATUS Status = STATUS_UNSUCCESSFUL; + USHORT InodeFileNameLength; + UNICODE_STRING InodeFileName; + + PFFS_DIR_ENTRY pDir = NULL; + ULONG dwBytes = 0; + BOOLEAN bFound = FALSE; + LONGLONG Offset = 0; +#ifndef __REACTOS__ + ULONG inode = ParentMcb->Inode; +#endif + ULONG dwRet; + + PAGED_CODE(); + + _SEH2_TRY + { + + pDir = (PFFS_DIR_ENTRY)ExAllocatePoolWithTag(PagedPool, + sizeof(FFS_DIR_ENTRY), FFS_POOL_TAG); + if (!pDir) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + _SEH2_LEAVE; + } + + InodeFileName.Buffer = ExAllocatePoolWithTag( + PagedPool, + (FFS_NAME_LEN + 1) * 2, FFS_POOL_TAG); + + if (!InodeFileName.Buffer) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + _SEH2_LEAVE; + } + + dwBytes = 0; + + while (!bFound && dwBytes < dinode1->di_size) + { + RtlZeroMemory(pDir, sizeof(FFS_DIR_ENTRY)); + + // Reading the DCB contents + Status = FFSv1ReadInode( + NULL, + Vcb, + dinode1, + dwBytes, + (PVOID)pDir, + sizeof(FFS_DIR_ENTRY), + &dwRet); + + + if (!NT_SUCCESS(Status)) + { + FFSPrint((DBG_ERROR, "FFSv1ScanDir: Reading Directory Content error.\n")); + _SEH2_LEAVE; + } + + if (pDir->d_ino /*&& (pDir->d_ino < INODES_COUNT)*/) + { + OEM_STRING OemName; + OemName.Buffer = pDir->d_name; + OemName.Length = (pDir->d_namlen & 0xff); + OemName.MaximumLength = OemName.Length; + + InodeFileNameLength = (USHORT) + RtlOemStringToCountedUnicodeSize(&OemName); + + InodeFileName.Length = 0; + InodeFileName.MaximumLength = (FFS_NAME_LEN + 1) * 2; + + RtlZeroMemory(InodeFileName.Buffer, + InodeFileNameLength + 2); + + Status = FFSOEMToUnicode( + &InodeFileName, + &OemName); + + if (!NT_SUCCESS(Status)) + { + _SEH2_LEAVE; + } + + if (!RtlCompareUnicodeString( + FileName, + &InodeFileName, + TRUE)) + { + bFound = TRUE; + *Index = dwBytes; + RtlCopyMemory(ffs_dir, pDir, pDir->d_reclen > sizeof(FFS_DIR_ENTRY) + ? sizeof(FFS_DIR_ENTRY) : pDir->d_reclen); + Status = STATUS_SUCCESS; + + FFSPrint((DBG_INFO, "FFSv1ScanDir: Found: Name=%S Inode=%xh\n", InodeFileName.Buffer, pDir->d_ino)); + } + + dwBytes +=pDir->d_reclen; + Offset = (LONGLONG)dwBytes; + } + else + { + if (pDir->d_ino == 0) + { + if (pDir->d_reclen == 0) + { + FFSBreakPoint(); + break; + } + else + { + dwBytes +=pDir->d_reclen; + Offset = (LONGLONG)dwBytes; + } + } + else + { + break; + } + } + } + + if (!bFound) + { + Status = STATUS_NO_SUCH_FILE; + } + } + + _SEH2_FINALLY + { + if (InodeFileName.Buffer != NULL) + { + ExFreePool(InodeFileName.Buffer); + } + + if (pDir) + ExFreePool(pDir); + } _SEH2_END; + + return Status; +} + + +NTSTATUS +FFSv2ScanDir( + IN PFFS_VCB Vcb, + IN PFFS_MCB ParentMcb, + IN PUNICODE_STRING FileName, + IN OUT PULONG Index, + IN PFFSv2_INODE dinode2, + IN OUT PFFS_DIR_ENTRY ffs_dir) +{ + NTSTATUS Status = STATUS_UNSUCCESSFUL; + USHORT InodeFileNameLength; + UNICODE_STRING InodeFileName; + + PFFS_DIR_ENTRY pDir = NULL; + ULONG dwBytes = 0; + BOOLEAN bFound = FALSE; + LONGLONG Offset = 0; +#ifndef __REACTOS__ + ULONG inode = ParentMcb->Inode; +#endif + ULONG dwRet; + + PAGED_CODE(); + + _SEH2_TRY + { + + pDir = (PFFS_DIR_ENTRY)ExAllocatePoolWithTag(PagedPool, + sizeof(FFS_DIR_ENTRY), FFS_POOL_TAG); + if (!pDir) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + _SEH2_LEAVE; + } + + InodeFileName.Buffer = ExAllocatePoolWithTag( + PagedPool, + (FFS_NAME_LEN + 1) * 2, FFS_POOL_TAG); + + if (!InodeFileName.Buffer) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + _SEH2_LEAVE; + } + + dwBytes = 0; + + while (!bFound && dwBytes < dinode2->di_size) + { + RtlZeroMemory(pDir, sizeof(FFS_DIR_ENTRY)); + + // Reading the DCB contents + Status = FFSv2ReadInode( + NULL, + Vcb, + dinode2, + dwBytes, + (PVOID)pDir, + sizeof(FFS_DIR_ENTRY), + &dwRet); + + + if (!NT_SUCCESS(Status)) + { + FFSPrint((DBG_ERROR, "FFSv2ScanDir: Reading Directory Content error.\n")); + _SEH2_LEAVE; + } + + if (pDir->d_ino /*&& (pDir->d_ino < INODES_COUNT)*/) + { + OEM_STRING OemName; + OemName.Buffer = pDir->d_name; + OemName.Length = (pDir->d_namlen & 0xff); + OemName.MaximumLength = OemName.Length; + + InodeFileNameLength = (USHORT) + RtlOemStringToCountedUnicodeSize(&OemName); + + InodeFileName.Length = 0; + InodeFileName.MaximumLength = (FFS_NAME_LEN + 1) * 2; + + RtlZeroMemory(InodeFileName.Buffer, + InodeFileNameLength + 2); + + Status = FFSOEMToUnicode( + &InodeFileName, + &OemName); + + if (!NT_SUCCESS(Status)) + { + _SEH2_LEAVE; + } + + if (!RtlCompareUnicodeString( + FileName, + &InodeFileName, + TRUE)) + { + bFound = TRUE; + *Index = dwBytes; + RtlCopyMemory(ffs_dir, pDir, pDir->d_reclen > sizeof(FFS_DIR_ENTRY) + ? sizeof(FFS_DIR_ENTRY) : pDir->d_reclen); + Status = STATUS_SUCCESS; + + FFSPrint((DBG_VITAL, "FFSv2ScanDir: Found: Name=%S Inode=%xh\n", InodeFileName.Buffer, pDir->d_ino)); + } + + dwBytes +=pDir->d_reclen; + Offset = (LONGLONG)dwBytes; + } + else + { + if (pDir->d_ino == 0) + { + if (pDir->d_reclen == 0) + { + FFSBreakPoint(); + break; + } + else + { + dwBytes +=pDir->d_reclen; + Offset = (LONGLONG)dwBytes; + } + } + else + { + break; + } + } + } + + if (!bFound) + { + Status = STATUS_NO_SUCH_FILE; + } + } + + _SEH2_FINALLY + { + if (InodeFileName.Buffer != NULL) + { + ExFreePool(InodeFileName.Buffer); + } + + if (pDir) + ExFreePool(pDir); + } _SEH2_END; + + return Status; +} + + +/* +PFFS_FCB +FFSSearchFcbList( + IN PFFS_VCB Vcb, + IN ULONG inode) +{ + BOOLEAN bFound = FALSE; + PLIST_ENTRY Link; + PFFS_FCB TmpFcb; + + Link = Vcb->FcbList.Flink; + + while (!bFound && Link != &Vcb->FcbList) + { + TmpFcb = CONTAINING_RECORD(Link, FFS_FCB, Next); + + if (TmpFcb && TmpFcb->Identifier.Type == FCB) + { +#if DBG + FFSPrint((DBG_INFO, "FFSSearchFcbList: [%s,%xh]\n", + TmpFcb->AnsiFileName.Buffer, TmpFcb->Inode)); +#endif + if (TmpFcb->Inode == inode) + { + FFSPrint((DBG_INFO, "FFSSearchMcb: Found FCB for %xh.\n", inode)); + bFound = TRUE; + } + } + Link = Link->Flink; + } + + if (bFound) + return TmpFcb; + else + return NULL; + +} +*/ + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSCreateFile( + PFFS_IRP_CONTEXT IrpContext, + PFFS_VCB Vcb) +{ + NTSTATUS Status = STATUS_UNSUCCESSFUL; + PIO_STACK_LOCATION IrpSp; + PFFS_FCB Fcb = NULL; + PFFS_MCB FFSMcb = NULL; + + PFFS_FCB ParentFcb = NULL; + PFFS_MCB ParentMcb = NULL; + + BOOLEAN bParentFcbCreated = FALSE; + + PFFS_CCB Ccb = NULL; + PFFSv1_INODE dinode1 = 0; + PFFSv2_INODE dinode2 = 0; + BOOLEAN VcbResourceAcquired = FALSE; +#ifndef __REACTOS__ + BOOLEAN bDir = FALSE; +#endif + BOOLEAN bFcbAllocated = FALSE; + BOOLEAN bCreated = FALSE; + UNICODE_STRING FileName; + PIRP Irp; + + ULONG Options; + ULONG CreateDisposition; + + BOOLEAN OpenDirectory; + BOOLEAN OpenTargetDirectory; + BOOLEAN CreateDirectory; + BOOLEAN SequentialOnly; + BOOLEAN NoIntermediateBuffering; + BOOLEAN IsPagingFile; + BOOLEAN DirectoryFile; + BOOLEAN NonDirectoryFile; + BOOLEAN NoEaKnowledge; + BOOLEAN DeleteOnClose; + BOOLEAN TemporaryFile; + BOOLEAN CaseSensitive; + + ACCESS_MASK DesiredAccess; + ULONG ShareAccess; + + PAGED_CODE(); + + Irp = IrpContext->Irp; + IrpSp = IoGetCurrentIrpStackLocation(Irp); + + Options = IrpSp->Parameters.Create.Options; + + DirectoryFile = IsFlagOn(Options, FILE_DIRECTORY_FILE); + OpenTargetDirectory = IsFlagOn(IrpSp->Flags, SL_OPEN_TARGET_DIRECTORY); + + NonDirectoryFile = IsFlagOn(Options, FILE_NON_DIRECTORY_FILE); + SequentialOnly = IsFlagOn(Options, FILE_SEQUENTIAL_ONLY); + NoIntermediateBuffering = IsFlagOn(Options, FILE_NO_INTERMEDIATE_BUFFERING); + NoEaKnowledge = IsFlagOn(Options, FILE_NO_EA_KNOWLEDGE); + DeleteOnClose = IsFlagOn(Options, FILE_DELETE_ON_CLOSE); + + CaseSensitive = IsFlagOn(IrpSp->Flags, SL_CASE_SENSITIVE); + + TemporaryFile = IsFlagOn(IrpSp->Parameters.Create.FileAttributes, + FILE_ATTRIBUTE_TEMPORARY); + + CreateDisposition = (Options >> 24) & 0x000000ff; + + IsPagingFile = IsFlagOn(IrpSp->Flags, SL_OPEN_PAGING_FILE); + + CreateDirectory = (BOOLEAN)(DirectoryFile && + ((CreateDisposition == FILE_CREATE) || + (CreateDisposition == FILE_OPEN_IF))); + + OpenDirectory = (BOOLEAN)(DirectoryFile && + ((CreateDisposition == FILE_OPEN) || + (CreateDisposition == FILE_OPEN_IF))); + + DesiredAccess = IrpSp->Parameters.Create.SecurityContext->DesiredAccess; + ShareAccess = IrpSp->Parameters.Create.ShareAccess; + + FileName.Buffer = NULL; + + _SEH2_TRY + { + ExAcquireResourceExclusiveLite( + &Vcb->MainResource, TRUE); + + VcbResourceAcquired = TRUE; + + if (Irp->Overlay.AllocationSize.HighPart) + { + Status = STATUS_INVALID_PARAMETER; + _SEH2_LEAVE; + } + + if (FS_VERSION == 1) + { + if (!(dinode1 = ExAllocatePoolWithTag( + PagedPool, DINODE1_SIZE, 'EInd'))) + { + _SEH2_LEAVE; + } + + RtlZeroMemory(dinode1, sizeof(DINODE1_SIZE)); + } + else + { + if (!(dinode2 = ExAllocatePoolWithTag( + PagedPool, DINODE2_SIZE, 'EInd'))) + { + _SEH2_LEAVE; + } + + RtlZeroMemory(dinode2, sizeof(DINODE2_SIZE)); + } + + + FileName.MaximumLength = IrpSp->FileObject->FileName.MaximumLength; + FileName.Length = IrpSp->FileObject->FileName.Length; + + FileName.Buffer = ExAllocatePoolWithTag(PagedPool, FileName.MaximumLength, FFS_POOL_TAG); + if (!FileName.Buffer) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + _SEH2_LEAVE; + } + + RtlZeroMemory(FileName.Buffer, FileName.MaximumLength); + RtlCopyMemory(FileName.Buffer, IrpSp->FileObject->FileName.Buffer, FileName.Length); + + if (IrpSp->FileObject->RelatedFileObject) + { + ParentFcb = (PFFS_FCB)(IrpSp->FileObject->RelatedFileObject->FsContext); + } + + if ((FileName.Length > sizeof(WCHAR)) && + (FileName.Buffer[1] == L'\\') && + (FileName.Buffer[0] == L'\\')) { + + FileName.Length -= sizeof(WCHAR); + + RtlMoveMemory(&FileName.Buffer[0], + &FileName.Buffer[1], + FileName.Length); + + // + // Bad Name if there are still beginning backslashes. + // + + if ((FileName.Length > sizeof(WCHAR)) && + (FileName.Buffer[1] == L'\\') && + (FileName.Buffer[0] == L'\\')) + { + + Status = STATUS_OBJECT_NAME_INVALID; + + _SEH2_LEAVE; + } + } + + if (IsFlagOn(Options, FILE_OPEN_BY_FILE_ID)) + { + Status = STATUS_NOT_IMPLEMENTED; + _SEH2_LEAVE; + } + + FFSPrint((DBG_INFO, "FFSCreateFile: %S (NameLen=%xh) Paging=%xh Option: %xh.\n", + FileName.Buffer, FileName.Length, IsPagingFile, IrpSp->Parameters.Create.Options)); + + if (ParentFcb) + { + ParentMcb = ParentFcb->FFSMcb; + } + + if (FS_VERSION == 1) + { + Status = FFSv1LookupFileName( + Vcb, + &FileName, + ParentMcb, + &FFSMcb, + dinode1); + } + else + { + Status = FFSv2LookupFileName( + Vcb, + &FileName, + ParentMcb, + &FFSMcb, + dinode2); + } + + if (!NT_SUCCESS(Status)) + { + UNICODE_STRING PathName; + UNICODE_STRING RealName; + UNICODE_STRING RemainName; +#ifndef __REACTOS__ + LONG i = 0; +#endif + + PathName = FileName; + + FFSPrint((DBG_INFO, "FFSCreateFile: File %S will be created.\n", PathName.Buffer)); + + FFSMcb = NULL; + + if (PathName.Buffer[PathName.Length / 2 - 1] == L'\\') + { + if (DirectoryFile) + { + PathName.Length -= 2; + PathName.Buffer[PathName.Length / 2] = 0; + } + else + { + Status = STATUS_NOT_A_DIRECTORY; + _SEH2_LEAVE; + } + } + + if (!ParentMcb) + { + if (PathName.Buffer[0] != L'\\') + { + Status = STATUS_OBJECT_PATH_NOT_FOUND; + _SEH2_LEAVE; + } + else + { + ParentMcb = Vcb->McbTree; + } + } + +Dissecting: + + FsRtlDissectName(PathName, &RealName, &RemainName); + + if (((RemainName.Length != 0) && (RemainName.Buffer[0] == L'\\')) || + (RealName.Length >= 256 * sizeof(WCHAR))) + { + Status = STATUS_OBJECT_NAME_INVALID; + _SEH2_LEAVE; + } + + if (RemainName.Length != 0) + { + PFFS_MCB RetMcb; + + if (FS_VERSION == 1) + { + Status = FFSv1LookupFileName( + Vcb, + &RealName, + ParentMcb, + &RetMcb, + dinode1); + } + else + { + Status = FFSv2LookupFileName( + Vcb, + &RealName, + ParentMcb, + &RetMcb, + dinode2); + } + + if (!NT_SUCCESS(Status)) + { + Status = STATUS_OBJECT_PATH_NOT_FOUND; + _SEH2_LEAVE; + } + + ParentMcb = RetMcb; + PathName = RemainName; + + goto Dissecting; + } + + if (FsRtlDoesNameContainWildCards(&RealName)) + { + Status = STATUS_OBJECT_NAME_INVALID; + _SEH2_LEAVE; + } + + ParentFcb = ParentMcb->FFSFcb; + + if (!ParentFcb) + { + if (FS_VERSION == 1) + { + PFFSv1_INODE pTmpInode = ExAllocatePoolWithTag(PagedPool, + DINODE1_SIZE, FFS_POOL_TAG); + if (!pTmpInode) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + _SEH2_LEAVE; + } + + if(!FFSv1LoadInode(Vcb, ParentMcb->Inode, pTmpInode)) + { + Status = STATUS_OBJECT_PATH_NOT_FOUND; + _SEH2_LEAVE; + } + + ParentFcb = FFSv1AllocateFcb(Vcb, ParentMcb, pTmpInode); + + if (!ParentFcb) + { + ExFreePool(pTmpInode); + Status = STATUS_INSUFFICIENT_RESOURCES; + _SEH2_LEAVE; + } + } + else + { + PFFSv2_INODE pTmpInode = ExAllocatePoolWithTag(PagedPool, + DINODE2_SIZE, FFS_POOL_TAG); + if (!pTmpInode) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + _SEH2_LEAVE; + } + + if(!FFSv2LoadInode(Vcb, ParentMcb->Inode, pTmpInode)) + { + Status = STATUS_OBJECT_PATH_NOT_FOUND; + _SEH2_LEAVE; + } + + ParentFcb = FFSv2AllocateFcb(Vcb, ParentMcb, pTmpInode); + + if (!ParentFcb) + { + ExFreePool(pTmpInode); + Status = STATUS_INSUFFICIENT_RESOURCES; + _SEH2_LEAVE; + } + } + + bParentFcbCreated = TRUE; + ParentFcb->ReferenceCount++; + } + + // We need to create a new one ? + if ((CreateDisposition == FILE_CREATE) || + (CreateDisposition == FILE_OPEN_IF) || + (CreateDisposition == FILE_OVERWRITE_IF)) + { +#if FFS_READ_ONLY + Status = STATUS_MEDIA_WRITE_PROTECTED; + _SEH2_LEAVE; +#else // !FFS_READ_ONLY + if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY)) + { + Status = STATUS_MEDIA_WRITE_PROTECTED; + _SEH2_LEAVE; + } + + if (IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED)) + { + IoSetHardErrorOrVerifyDevice(IrpContext->Irp, + Vcb->Vpb->RealDevice); + SetFlag(Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME); + + FFSRaiseStatus(IrpContext, STATUS_MEDIA_WRITE_PROTECTED); + } + + if (DirectoryFile) + { + if (TemporaryFile) + { + Status = STATUS_INVALID_PARAMETER; + _SEH2_LEAVE; + } + } + + if (!ParentFcb) + { + Status = STATUS_OBJECT_PATH_NOT_FOUND; + _SEH2_LEAVE; + } + + if (DirectoryFile) + { + if (ParentFcb->FFSMcb->Inode == FFS_ROOT_INO) + { + if ((RealName.Length == 0x10) && + memcmp(RealName.Buffer, L"Recycled\0", 0x10) == 0) + { + SetFlag(IrpSp->Parameters.Create.FileAttributes, + FILE_ATTRIBUTE_READONLY); + } + } + + Status = FFSCreateInode( + IrpContext, + Vcb, + ParentFcb, + DT_DIR, + IrpSp->Parameters.Create.FileAttributes, + &RealName); + } + else + { + Status = FFSCreateInode( + IrpContext, + Vcb, + ParentFcb, + DT_REG, + IrpSp->Parameters.Create.FileAttributes, + &RealName); + } + + if (NT_SUCCESS(Status)) + { + bCreated = TRUE; + + Irp->IoStatus.Information = FILE_CREATED; + + if (FS_VERSION == 1) + { + Status = FFSv1LookupFileName( + Vcb, + &RealName, + ParentMcb, + &FFSMcb, + dinode1); + } + else + { + Status = FFSv2LookupFileName( + Vcb, + &RealName, + ParentMcb, + &FFSMcb, + dinode2); + } + + if (NT_SUCCESS(Status)) + { + if (DirectoryFile) + { + FFSNotifyReportChange( + IrpContext, + Vcb, + ParentFcb, + FILE_NOTIFY_CHANGE_DIR_NAME, + FILE_ACTION_ADDED); + } + else + { + FFSNotifyReportChange( + IrpContext, + Vcb, + ParentFcb, + FILE_NOTIFY_CHANGE_FILE_NAME, + FILE_ACTION_ADDED); + } + } + else + { + FFSBreakPoint(); + } + } + else + { + FFSBreakPoint(); + } +#endif // !FFS_READ_ONLY + } + else if (OpenTargetDirectory) + { + if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY)) + { + Status = STATUS_MEDIA_WRITE_PROTECTED; + _SEH2_LEAVE; + } + + if (!ParentFcb) + { + Status = STATUS_OBJECT_PATH_NOT_FOUND; + _SEH2_LEAVE; + } + + RtlZeroMemory(IrpSp->FileObject->FileName.Buffer, + IrpSp->FileObject->FileName.MaximumLength); + IrpSp->FileObject->FileName.Length = RealName.Length; + + RtlCopyMemory(IrpSp->FileObject->FileName.Buffer, + RealName.Buffer, + RealName.Length); + + Fcb = ParentFcb; + + Irp->IoStatus.Information = FILE_DOES_NOT_EXIST; + Status = STATUS_SUCCESS; + } + else + { + Status = STATUS_OBJECT_NAME_NOT_FOUND; + _SEH2_LEAVE; + } + } + else // File / Dir already exists. + { + if (OpenTargetDirectory) + { + if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY)) + { + Status = STATUS_MEDIA_WRITE_PROTECTED; + _SEH2_LEAVE; + } + + Irp->IoStatus.Information = FILE_EXISTS; + Status = STATUS_SUCCESS; + + RtlZeroMemory(IrpSp->FileObject->FileName.Buffer, + IrpSp->FileObject->FileName.MaximumLength); + IrpSp->FileObject->FileName.Length = FFSMcb->ShortName.Length; + + RtlCopyMemory(IrpSp->FileObject->FileName.Buffer, + FFSMcb->ShortName.Buffer, + FFSMcb->ShortName.Length); + + //Let Mcb pointer to it's parent + FFSMcb = FFSMcb->Parent; + + goto Openit; + } + + // We can not create if one exists + if (CreateDisposition == FILE_CREATE) + { + Irp->IoStatus.Information = FILE_EXISTS; + Status = STATUS_OBJECT_NAME_COLLISION; + _SEH2_LEAVE; + } + + if(IsFlagOn(FFSMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY)) + { + if ((CreateDisposition != FILE_OPEN) && + (CreateDisposition != FILE_OPEN_IF)) + { + + Status = STATUS_OBJECT_NAME_COLLISION; + _SEH2_LEAVE; + } + + if (NonDirectoryFile) + { + Status = STATUS_FILE_IS_A_DIRECTORY; + _SEH2_LEAVE; + } + + if (FFSMcb->Inode == FFS_ROOT_INO) + { + if (DeleteOnClose) + { + Status = STATUS_CANNOT_DELETE; + _SEH2_LEAVE; + } + + if (OpenTargetDirectory) + { + Status = STATUS_INVALID_PARAMETER; + _SEH2_LEAVE; + } + } + } + + Irp->IoStatus.Information = FILE_OPENED; + } + +Openit: + + if (FFSMcb) + { + Fcb = FFSMcb->FFSFcb; + + if (!Fcb) + { + if (FS_VERSION == 1) + { + Fcb = FFSv1AllocateFcb(Vcb, FFSMcb, dinode1); + bFcbAllocated = TRUE; + } + else + { + Fcb = FFSv2AllocateFcb(Vcb, FFSMcb, dinode2); + bFcbAllocated = TRUE; + } + } + } + + if (Fcb) + { + if (IsFlagOn(Fcb->Flags, FCB_FILE_DELETED)) + { + Status = STATUS_FILE_DELETED; + _SEH2_LEAVE; + } + + if (FlagOn(Fcb->Flags, FCB_DELETE_PENDING)) + { + Status = STATUS_DELETE_PENDING; + _SEH2_LEAVE; + } + + if (bCreated) + { +#if !FFS_READ_ONLY + // + // This file is just created. + // + + if (DirectoryFile) + { + UNICODE_STRING EntryName; + USHORT NameBuf[6]; + + RtlZeroMemory(&NameBuf, 6 * sizeof(USHORT)); + + EntryName.Length = EntryName.MaximumLength = 2; + EntryName.Buffer = &NameBuf[0]; + NameBuf[0] = (USHORT)'.'; + + FFSAddEntry(IrpContext, Vcb, Fcb, + DT_DIR, + Fcb->FFSMcb->Inode, + &EntryName); + + if (FS_VERSION == 1) + { + FFSv1SaveInode(IrpContext, Vcb, + Fcb->FFSMcb->Inode, + Fcb->dinode1); + } + else + { + FFSv2SaveInode(IrpContext, Vcb, + Fcb->FFSMcb->Inode, + Fcb->dinode2); + } + + EntryName.Length = EntryName.MaximumLength = 4; + EntryName.Buffer = &NameBuf[0]; + NameBuf[0] = NameBuf[1] = (USHORT)'.'; + + FFSAddEntry(IrpContext, Vcb, Fcb, + DT_DIR, + Fcb->FFSMcb->Parent->Inode, + &EntryName); + + if (FS_VERSION == 1) + { + FFSv1SaveInode(IrpContext, Vcb, + Fcb->FFSMcb->Inode, + Fcb->dinode1); + } + else + { + FFSv2SaveInode(IrpContext, Vcb, + Fcb->FFSMcb->Inode, + Fcb->dinode2); + } + } + else + { + if (!FFSExpandFile( + IrpContext, Vcb, Fcb, + &(Irp->Overlay.AllocationSize))) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + _SEH2_LEAVE; + } + } +#endif // !FFS_READ_ONLY + } + else + { + // + // This file alreayd exists. + // + + if (DeleteOnClose) + { + if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY)) + { + Status = STATUS_MEDIA_WRITE_PROTECTED; + _SEH2_LEAVE; + } + + if (IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED)) + { + Status = STATUS_MEDIA_WRITE_PROTECTED; + + IoSetHardErrorOrVerifyDevice(IrpContext->Irp, + Vcb->Vpb->RealDevice); + + SetFlag(Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME); + + FFSRaiseStatus(IrpContext, STATUS_MEDIA_WRITE_PROTECTED); + } + + SetFlag(Fcb->Flags, FCB_DELETE_ON_CLOSE); + } + else + { + // + // Just to Open file (Open/OverWrite ...) + // + + if ((!IsDirectory(Fcb)) && (IsFlagOn(IrpSp->FileObject->Flags, + FO_NO_INTERMEDIATE_BUFFERING))) + { + Fcb->Header.IsFastIoPossible = FastIoIsPossible; + + if (IsFlagOn(IrpSp->FileObject->Flags, FO_CACHE_SUPPORTED) && + (Fcb->SectionObject.DataSectionObject != NULL)) + { + if (Fcb->NonCachedOpenCount == Fcb->OpenHandleCount) + { + /* IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED) */ + + if(!IsFlagOn(Vcb->Flags, VCB_READ_ONLY)) + { + CcFlushCache(&Fcb->SectionObject, NULL, 0, NULL); + ClearFlag(Fcb->Flags, FCB_FILE_MODIFIED); + } + + CcPurgeCacheSection(&Fcb->SectionObject, + NULL, + 0, + FALSE); + } + } + } + } + } + + if (!IsDirectory(Fcb)) + { + if (!IsFlagOn(Vcb->Flags, VCB_READ_ONLY)) + { + if ((CreateDisposition == FILE_SUPERSEDE) && !IsPagingFile) + { + DesiredAccess |= DELETE; + } + else if (((CreateDisposition == FILE_OVERWRITE) || + (CreateDisposition == FILE_OVERWRITE_IF)) && !IsPagingFile) + { + DesiredAccess |= (FILE_WRITE_DATA | FILE_WRITE_EA | + FILE_WRITE_ATTRIBUTES); + } + } + } + + if (Fcb->OpenHandleCount > 0) + { + Status = IoCheckShareAccess(DesiredAccess, + ShareAccess, + IrpSp->FileObject, + &(Fcb->ShareAccess), + TRUE); + + if (!NT_SUCCESS(Status)) + { + _SEH2_LEAVE; + } + } + else + { + IoSetShareAccess(DesiredAccess, + ShareAccess, + IrpSp->FileObject, + &(Fcb->ShareAccess)); + } + + Ccb = FFSAllocateCcb(); + + Fcb->OpenHandleCount++; + Fcb->ReferenceCount++; + + if (IsFlagOn(IrpSp->FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING)) + { + Fcb->NonCachedOpenCount++; + } + + Vcb->OpenFileHandleCount++; + Vcb->ReferenceCount++; + + IrpSp->FileObject->FsContext = (void*)Fcb; + IrpSp->FileObject->FsContext2 = (void*) Ccb; + IrpSp->FileObject->PrivateCacheMap = NULL; + IrpSp->FileObject->SectionObjectPointer = &(Fcb->SectionObject); + IrpSp->FileObject->Vpb = Vcb->Vpb; + + Status = STATUS_SUCCESS; + + FFSPrint((DBG_INFO, "FFSCreateFile: %s OpenCount: %u ReferCount: %u\n", + Fcb->AnsiFileName.Buffer, Fcb->OpenHandleCount, Fcb->ReferenceCount)); + + if (!IsDirectory(Fcb) && !NoIntermediateBuffering) + { + IrpSp->FileObject->Flags |= FO_CACHE_SUPPORTED; + } + + if (!bCreated && !IsDirectory(Fcb)) + { + if (DeleteOnClose || + IsFlagOn(DesiredAccess, FILE_WRITE_DATA) || + (CreateDisposition == FILE_OVERWRITE) || + (CreateDisposition == FILE_OVERWRITE_IF)) + { + if (!MmFlushImageSection(&Fcb->SectionObject, + MmFlushForWrite)) + { + + Status = DeleteOnClose ? STATUS_CANNOT_DELETE : + STATUS_SHARING_VIOLATION; + _SEH2_LEAVE; + } + } + + if ((CreateDisposition == FILE_SUPERSEDE) || + (CreateDisposition == FILE_OVERWRITE) || + (CreateDisposition == FILE_OVERWRITE_IF)) + { +#if FFS_READ_ONLY + Status = STATUS_MEDIA_WRITE_PROTECTED; + _SEH2_LEAVE; +#else // !FFS_READ_ONLY + BOOLEAN bRet; + + if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY)) + { + Status = STATUS_MEDIA_WRITE_PROTECTED; + _SEH2_LEAVE; + } + + if (IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED)) + { + IoSetHardErrorOrVerifyDevice(IrpContext->Irp, + Vcb->Vpb->RealDevice); + SetFlag(Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME); + + FFSRaiseStatus(IrpContext, STATUS_MEDIA_WRITE_PROTECTED); + } + + Status = FFSSupersedeOrOverWriteFile(IrpContext, + Vcb, + Fcb, + CreateDisposition); + + if (NT_SUCCESS(Status)) + { + _SEH2_LEAVE; + } + + bRet = FFSExpandFile(IrpContext, + Vcb, + Fcb, + &(Irp->Overlay.AllocationSize)); + + if (!bRet) + { + Status = STATUS_DISK_FULL; + _SEH2_LEAVE; + } + + FFSNotifyReportChange( + IrpContext, + Vcb, + Fcb, + FILE_NOTIFY_CHANGE_LAST_WRITE | + FILE_NOTIFY_CHANGE_ATTRIBUTES | + FILE_NOTIFY_CHANGE_SIZE, + FILE_ACTION_MODIFIED); + + + if (CreateDisposition == FILE_SUPERSEDE) + { + Irp->IoStatus.Information = FILE_SUPERSEDED; + } + else + { + Irp->IoStatus.Information = FILE_OVERWRITTEN; + } +#endif // !FFS_READ_ONLY + } + } + } + } + + _SEH2_FINALLY + { + if (FileName.Buffer) + ExFreePool(FileName.Buffer); + + if (bParentFcbCreated) + { + ParentFcb->ReferenceCount--; + } + + if (VcbResourceAcquired) + { + ExReleaseResourceForThreadLite( + &Vcb->MainResource, + ExGetCurrentResourceThread()); + } + + if (!bFcbAllocated) + { + if (FS_VERSION == 1) + { + if (dinode1) + ExFreePool(dinode1); + } + else + { + if (dinode2) + ExFreePool(dinode2); + } + } + else + { + if (FS_VERSION == 1) + { + if (!Fcb && dinode1) + ExFreePool(dinode1); + } + else + { + if (!Fcb && dinode2) + ExFreePool(dinode2); + } + } + } _SEH2_END; + + return Status; +} + + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSCreateVolume( + PFFS_IRP_CONTEXT IrpContext, + PFFS_VCB Vcb) +{ + PIO_STACK_LOCATION IrpSp; + PIRP Irp; + + NTSTATUS Status; + + ACCESS_MASK DesiredAccess; + ULONG ShareAccess; + + ULONG Options; + BOOLEAN DirectoryFile; + BOOLEAN OpenTargetDirectory; + + ULONG CreateDisposition; + + PAGED_CODE(); + + Irp = IrpContext->Irp; + IrpSp = IoGetCurrentIrpStackLocation(Irp); + + Options = IrpSp->Parameters.Create.Options; + + DirectoryFile = IsFlagOn(Options, FILE_DIRECTORY_FILE); + OpenTargetDirectory = IsFlagOn(IrpSp->Flags, SL_OPEN_TARGET_DIRECTORY); + + CreateDisposition = (Options >> 24) & 0x000000ff; + + DesiredAccess = IrpSp->Parameters.Create.SecurityContext->DesiredAccess; + ShareAccess = IrpSp->Parameters.Create.ShareAccess; + + if (DirectoryFile) + { + return STATUS_NOT_A_DIRECTORY; + } + + if (OpenTargetDirectory) + { + return STATUS_INVALID_PARAMETER; + } + + if ((CreateDisposition != FILE_OPEN) && + (CreateDisposition != FILE_OPEN_IF)) + { + return STATUS_ACCESS_DENIED; + } + + Status = STATUS_SUCCESS; + + if (Vcb->OpenHandleCount > 0) + { + Status = IoCheckShareAccess(DesiredAccess, ShareAccess, + IrpSp->FileObject, + &(Vcb->ShareAccess), TRUE); + + if (!NT_SUCCESS(Status)) + { + goto errorout; + } + } + else + { + IoSetShareAccess(DesiredAccess, ShareAccess, + IrpSp->FileObject, + &(Vcb->ShareAccess)); + } + + if (FlagOn(DesiredAccess, FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA)) + { + ExAcquireResourceExclusiveLite(&Vcb->MainResource, TRUE); + FFSFlushFiles(Vcb, FALSE); + FFSFlushVolume(Vcb, FALSE); + ExReleaseResourceLite(&Vcb->MainResource); + } + + { + PFFS_CCB Ccb = FFSAllocateCcb(); + + if (Ccb == NULL) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto errorout; + } + + IrpSp->FileObject->Flags |= FO_NO_INTERMEDIATE_BUFFERING; + IrpSp->FileObject->FsContext = Vcb; + IrpSp->FileObject->FsContext2 = Ccb; + + Vcb->ReferenceCount++; + Vcb->OpenHandleCount++; + + Irp->IoStatus.Information = FILE_OPENED; + } + +errorout: + + return Status; +} + + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSCreate( + IN PFFS_IRP_CONTEXT IrpContext) +{ + PDEVICE_OBJECT DeviceObject; + PIRP Irp; + PIO_STACK_LOCATION IrpSp; + PFFS_VCB Vcb = 0; + NTSTATUS Status = STATUS_OBJECT_NAME_NOT_FOUND; + PFFS_FCBVCB Xcb = NULL; + + PAGED_CODE(); + + DeviceObject = IrpContext->DeviceObject; + + Vcb = (PFFS_VCB)DeviceObject->DeviceExtension; + +#if 0 + /* µå¶óÀ̹ö°¡ ·Îµå µÇ¾ú´ÂÁö °Ë»çÇÒ ¶§ ¸¶¿îÆ®°¡ µÇ¾î ÀÖÁö ¾ÊÀº + °æ¿ìµµ Àֱ⠶§¹®¿¡ ¸ØÃß¸é ¾ÈµÊ. */ + ASSERT(IsMounted(Vcb)); +#endif + + Irp = IrpContext->Irp; + + IrpSp = IoGetCurrentIrpStackLocation(Irp); + + Xcb = (PFFS_FCBVCB)(IrpSp->FileObject->FsContext); + + if (DeviceObject == FFSGlobal->DeviceObject) + { + FFSPrint((DBG_INFO, "FFSCreate: Create on main device object.\n")); + + Status = STATUS_SUCCESS; + + Irp->IoStatus.Information = FILE_OPENED; + + FFSUnpinRepinnedBcbs(IrpContext); + + FFSCompleteIrpContext(IrpContext, Status); + + return Status; + + } + + _SEH2_TRY + { + if (IsFlagOn(Vcb->Flags, VCB_VOLUME_LOCKED)) + { + Status = STATUS_ACCESS_DENIED; + + if (IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING)) + { + Status = STATUS_VOLUME_DISMOUNTED; + } + + _SEH2_LEAVE; + } + + if (((IrpSp->FileObject->FileName.Length == 0) && + (IrpSp->FileObject->RelatedFileObject == NULL)) || + (Xcb && Xcb->Identifier.Type == FFSVCB)) + { + Status = FFSCreateVolume(IrpContext, Vcb); + } + else + { + Status = FFSCreateFile(IrpContext, Vcb); + } + } + + _SEH2_FINALLY + { + + if (!IrpContext->ExceptionInProgress) + { + FFSUnpinRepinnedBcbs(IrpContext); + + FFSCompleteIrpContext(IrpContext, Status); + } + } _SEH2_END; + + return Status; +} + +#if !FFS_READ_ONLY + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSCreateInode( + PFFS_IRP_CONTEXT IrpContext, + PFFS_VCB Vcb, + PFFS_FCB ParentFcb, + ULONG Type, + ULONG FileAttr, + PUNICODE_STRING FileName) +{ + NTSTATUS Status; + ULONG Inode; + ULONG Group; + + FFSv1_INODE dinode1; + + PAGED_CODE(); + + RtlZeroMemory(&dinode1, DINODE1_SIZE); + + Group = (ParentFcb->FFSMcb->Inode - 1) / BLOCKS_PER_GROUP; + + FFSPrint((DBG_INFO, + "FFSCreateInode: %S in %S(Inode=%xh)\n", + FileName->Buffer, + ParentFcb->FFSMcb->ShortName.Buffer, + ParentFcb->FFSMcb->Inode)); + + Status = FFSNewInode(IrpContext, Vcb, Group,Type, &Inode); + + if (!NT_SUCCESS(Status)) + { + goto errorout; + } + + Status = FFSAddEntry(IrpContext, Vcb, ParentFcb, Type, Inode, FileName); + + if (!NT_SUCCESS(Status)) + { + FFSBreakPoint(); + FFSFreeInode(IrpContext, Vcb, Inode, Type); + + goto errorout; + } + + FFSv1SaveInode(IrpContext, Vcb, ParentFcb->FFSMcb->Inode, ParentFcb->dinode1); + + dinode1.di_ctime = ParentFcb->dinode1->di_mtime; + dinode1.di_mode = 0x1FF; + + if (IsFlagOn(FileAttr, FILE_ATTRIBUTE_READONLY)) + { + FFSSetReadOnly(dinode1.di_mode); + } + + if (Type == DT_DIR) + { + SetFlag(dinode1.di_mode, IFDIR); + + dinode1.di_nlink = 2; + } + else + { + dinode1.di_nlink = 1; + SetFlag(dinode1.di_mode, IFLNK); + } + + FFSv1SaveInode(IrpContext, Vcb, Inode, &dinode1); + + FFSPrint((DBG_INFO, "FFSCreateInode: New Inode = %xh (Type=%xh)\n", Inode, Type)); + +errorout: + + return Status; +} + + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSSupersedeOrOverWriteFile( + IN PFFS_IRP_CONTEXT IrpContext, + IN PFFS_VCB Vcb, + IN PFFS_FCB Fcb, + IN ULONG Disposition) +{ + LARGE_INTEGER CurrentTime; + LARGE_INTEGER AllocationSize; + NTSTATUS Status = STATUS_SUCCESS; + + BOOLEAN bRet = FALSE; + + PAGED_CODE(); + + KeQuerySystemTime(&CurrentTime); + + AllocationSize.QuadPart = (LONGLONG)0; + + if (!MmCanFileBeTruncated(&(Fcb->SectionObject), &(AllocationSize))) + { + Status = STATUS_USER_MAPPED_FILE; + + return Status; + } + + bRet = FFSTruncateFile(IrpContext, Vcb, Fcb, &AllocationSize); + + if (bRet) + { + Fcb->Header.AllocationSize.QuadPart = + Fcb->Header.FileSize.QuadPart = (LONGLONG)0; + + Fcb->dinode1->di_size = 0; + + if (Disposition == FILE_SUPERSEDE) + Fcb->dinode1->di_ctime = FFSInodeTime(CurrentTime); + + Fcb->dinode1->di_atime = + Fcb->dinode1->di_mtime = FFSInodeTime(CurrentTime); + } + else + { + if (Fcb->dinode1->di_size > Fcb->Header.AllocationSize.LowPart) + Fcb->dinode1->di_size = Fcb->Header.AllocationSize.LowPart; + + Fcb->Header.FileSize.QuadPart = (LONGLONG)Fcb->dinode1->di_size; + + Status = STATUS_UNSUCCESSFUL; + } + + FFSv1SaveInode(IrpContext, Vcb, Fcb->FFSMcb->Inode, Fcb->dinode1); + + return Status; +} + +#endif // !FFS_READ_ONLY diff --git a/reactos/drivers/filesystems/ffs/src/debug.c b/reactos/drivers/filesystems/ffs/src/debug.c new file mode 100644 index 00000000000..fd8d07fc7be --- /dev/null +++ b/reactos/drivers/filesystems/ffs/src/debug.c @@ -0,0 +1,1780 @@ +/* + * FFS File System Driver for Windows + * + * debug.c + * + * 2004.5.6 ~ + * + * Lee Jae-Hong, http://www.pyrasis.com + * + * See License.txt + * + */ + +#if DBG + +#include "ntifs.h" +#include "ffsdrv.h" +#include "stdarg.h" +#include "stdio.h" + + +/* Globals */ + +extern PFFS_GLOBAL FFSGlobal; + +#define SYSTEM_PROCESS_NAME "System" + +extern PFFS_GLOBAL FFSGlobal; + +LONG DebugLevel = DBG_USER; + +ULONG ProcessNameOffset = 0; + +/* Definitions */ + +#ifdef ALLOC_PRAGMA +//#pragma alloc_text (PAGE, FFSPrintf) +//#pragma alloc_text (PAGE, FFSNIPrintf) +#pragma alloc_text (PAGE, FFSGetProcessNameOffset) +//#pragma alloc_text (PAGE, FFSDbgPrintCall) +//#pragma alloc_text (PAGE, FFSDbgPrintComplete) +//#pragma alloc_text (PAGE, FFSNtStatusToString) +#endif // ALLOC_PRAGMA + +/* Static Definitions ****************************************************/ + +static PCHAR IrpMjStrings[] = { + "IRP_MJ_CREATE", + "IRP_MJ_CREATE_NAMED_PIPE", + "IRP_MJ_CLOSE", + "IRP_MJ_READ", + "IRP_MJ_WRITE", + "IRP_MJ_QUERY_INFORMATION", + "IRP_MJ_SET_INFORMATION", + "IRP_MJ_QUERY_EA", + "IRP_MJ_SET_EA", + "IRP_MJ_FLUSH_BUFFERS", + "IRP_MJ_QUERY_VOLUME_INFORMATION", + "IRP_MJ_SET_VOLUME_INFORMATION", + "IRP_MJ_DIRECTORY_CONTROL", + "IRP_MJ_FILE_SYSTEM_CONTROL", + "IRP_MJ_DEVICE_CONTROL", + "IRP_MJ_INTERNAL_DEVICE_CONTROL", + "IRP_MJ_SHUTDOWN", + "IRP_MJ_LOCK_CONTROL", + "IRP_MJ_CLEANUP", + "IRP_MJ_CREATE_MAILSLOT", + "IRP_MJ_QUERY_SECURITY", + "IRP_MJ_SET_SECURITY", + "IRP_MJ_POWER", + "IRP_MJ_SYSTEM_CONTROL", + "IRP_MJ_DEVICE_CHANGE", + "IRP_MJ_QUERY_QUOTA", + "IRP_MJ_SET_QUOTA", + "IRP_MJ_PNP" +}; + +static PCHAR FileInformationClassStrings[] = { + "Unknown FileInformationClass 0", + "FileDirectoryInformation", + "FileFullDirectoryInformation", + "FileBothDirectoryInformation", + "FileBasicInformation", + "FileStandardInformation", + "FileInternalInformation", + "FileEaInformation", + "FileAccessInformation", + "FileNameInformation", + "FileRenameInformation", + "FileLinkInformation", + "FileNamesInformation", + "FileDispositionInformation", + "FilePositionInformation", + "FileFullEaInformation", + "FileModeInformation", + "FileAlignmentInformation", + "FileAllInformation", + "FileAllocationInformation", + "FileEndOfFileInformation", + "FileAlternateNameInformation", + "FileStreamInformation", + "FilePipeInformation", + "FilePipeLocalInformation", + "FilePipeRemoteInformation", + "FileMailslotQueryInformation", + "FileMailslotSetInformation", + "FileCompressionInformation", + "FileObjectIdInformation", + "FileCompletionInformation", + "FileMoveClusterInformation", + "FileQuotaInformation", + "FileReparsePointInformation", + "FileNetworkOpenInformation", + "FileAttributeTagInformation", + "FileTrackingInformation" +}; + +static PCHAR FsInformationClassStrings[] = { + "Unknown FsInformationClass 0", + "FileFsVolumeInformation", + "FileFsLabelInformation", + "FileFsSizeInformation", + "FileFsDeviceInformation", + "FileFsAttributeInformation", + "FileFsControlInformation", + "FileFsFullSizeInformation", + "FileFsObjectIdInformation" +}; + +/* + * FFSPrintf + * This function is variable-argument, level-sensitive debug print routine. + * If the specified debug level for the print statement is lower or equal + * to the current debug level, the message will be printed. + * + * Arguments: + * DebugPrintLevel - Specifies at which debugging level the string should + * be printed + * DebugMessage - Variable argument ascii c string + * + * Return Value: + * N/A + * + * NOTES: + * N/A + */ + +VOID +FFSPrintf( + LONG DebugPrintLevel, + PCHAR DebugMessage, + ...) +{ + va_list ap; + LARGE_INTEGER CurrentTime; + TIME_FIELDS TimeFields; + + ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL); + + if (DebugPrintLevel <= DebugLevel) + { + CHAR Buffer[0x100]; + va_start(ap, DebugMessage); + + KeQuerySystemTime(&CurrentTime); + RtlTimeToTimeFields(&CurrentTime, &TimeFields); + + vsprintf(Buffer, DebugMessage, ap); + + DbgPrint(DRIVER_NAME": %2.2d:%2.2d:%2.2d:%3.3d %8.8x: %s", + TimeFields.Hour, TimeFields.Minute, + TimeFields.Second, TimeFields.Milliseconds, + PsGetCurrentThread(), Buffer); + + va_end(ap); + } + + + ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL); + +} // FFSPrintf() + + +/* + * FFSNIPrintf + * This function is variable-argument, level-sensitive debug print routine. + * If the specified debug level for the print statement is lower or equal + * to the current debug level, the message will be printed. + * + * Arguments: + * DebugPrintLevel - Specifies at which debugging level the string should + * be printed + * DebugMessage - Variable argument ascii c string + * + * Return Value: + * N/A + * + * NOTES: + * N/A + */ + +VOID +FFSNIPrintf( + LONG DebugPrintLevel, + PCHAR DebugMessage, + ...) +{ + va_list ap; + LARGE_INTEGER CurrentTime; + TIME_FIELDS TimeFields; + + ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL); + + if (DebugPrintLevel <= DebugLevel) + { + CHAR Buffer[0x100]; + va_start(ap, DebugMessage); + + KeQuerySystemTime(&CurrentTime); + RtlTimeToTimeFields(&CurrentTime, &TimeFields); + + vsprintf(Buffer, DebugMessage, ap); + + DbgPrint(DRIVER_NAME": %2.2d:%2.2d:%2.2d:%3.3d %8.8x: %s", + TimeFields.Hour, TimeFields.Minute, + TimeFields.Second, TimeFields.Milliseconds, + PsGetCurrentThread(), Buffer); + + va_end(ap); + } + + + ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL); + +} // FFSNIPrintf() + +ULONG +FFSGetProcessNameOffset( + VOID) +{ + PEPROCESS Process; + ULONG i; + + PAGED_CODE(); + + Process = PsGetCurrentProcess(); + + for(i = 0; i < PAGE_SIZE; i++) + { + if(!strncmp( + SYSTEM_PROCESS_NAME, + (PCHAR) Process + i, + strlen(SYSTEM_PROCESS_NAME))) + { + return i; + } + } + + FFSPrint((DBG_ERROR, ": *** FsdGetProcessNameOffset failed ***\n")); + + return 0; +} + + +VOID +FFSDbgPrintCall( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PIO_STACK_LOCATION IoStackLocation; + PFILE_OBJECT FileObject; + PCHAR FileName; + PFFS_FCB Fcb; + FILE_INFORMATION_CLASS FileInformationClass; + FS_INFORMATION_CLASS FsInformationClass; + + IoStackLocation = IoGetCurrentIrpStackLocation(Irp); + + FileObject = IoStackLocation->FileObject; + + FileName = "Unknown"; + + if (DeviceObject == FFSGlobal->DeviceObject) + { + FileName = "\\" DRIVER_NAME; + } + else if (FileObject && FileObject->FsContext) + { + Fcb = (PFFS_FCB)FileObject->FsContext; + + if (Fcb->Identifier.Type == FFSVCB) + { + FileName = "\\Volume"; + } + else if (Fcb->Identifier.Type == FFSFCB && Fcb->AnsiFileName.Buffer) + { + FileName = Fcb->AnsiFileName.Buffer; + } + } + + switch (IoStackLocation->MajorFunction) + { + case IRP_MJ_CREATE: + + FileName = NULL; + + if (DeviceObject == FFSGlobal->DeviceObject) + { + FileName = "\\" DRIVER_NAME; + } + else if (FileObject && FileObject->FileName.Length == 0) + { + FileName = "\\Volume"; + } + + if (FileName) + { + FFSPrintNoIndent(( + DBG_TRACE, "%s %s %s\n", + FFSGetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName)); + } + else if (FileObject && FileObject->FileName.Buffer) + { + FFSPrintNoIndent(( + DBG_TRACE, "%s %s %S\n", + FFSGetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + IoStackLocation->FileObject->FileName.Buffer)); + } + else + { + FFSPrintNoIndent(( + DBG_TRACE, "%s %s %s\n", + FFSGetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + "Unknown")); + } + + break; + + case IRP_MJ_CLOSE: + + FFSPrintNoIndent(( + DBG_TRACE, "%s %s %s\n", + FFSGetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName)); + + break; + + case IRP_MJ_READ: + + if (IoStackLocation->MinorFunction & IRP_MN_COMPLETE) + { + FFSPrintNoIndent(( + DBG_TRACE, "%s %s %s IRP_MN_COMPLETE\n", + FFSGetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName)); + } + else + { + FFSPrintNoIndent(( + DBG_TRACE, "%s %s %s Offset: %I64xh Length: %xh %s%s%s%s%s%s\n", + FFSGetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName, + IoStackLocation->Parameters.Read.ByteOffset.QuadPart, + IoStackLocation->Parameters.Read.Length, + (IoStackLocation->MinorFunction & IRP_MN_DPC ? "IRP_MN_DPC " : " "), + (IoStackLocation->MinorFunction & IRP_MN_MDL ? "IRP_MN_MDL " : " "), + (IoStackLocation->MinorFunction & IRP_MN_COMPRESSED ? "IRP_MN_COMPRESSED " : " "), + (Irp->Flags & IRP_PAGING_IO ? "IRP_PAGING_IO " : " "), + (Irp->Flags & IRP_NOCACHE ? "IRP_NOCACHE " : " "), + (FileObject->Flags & FO_SYNCHRONOUS_IO ? "FO_SYNCHRONOUS_IO " : " "))); + } + + break; + + case IRP_MJ_WRITE: + + if (IoStackLocation->MinorFunction & IRP_MN_COMPLETE) + { + FFSPrintNoIndent(( + DBG_TRACE, "%s %s %s IRP_MN_COMPLETE\n", + FFSGetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName)); + } + else + { + FFSPrintNoIndent(( + DBG_TRACE, "%s %s %s Offset: %I64xh Length: %xh %s%s%s%s%s%s\n", + FFSGetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName, + IoStackLocation->Parameters.Read.ByteOffset.QuadPart, + IoStackLocation->Parameters.Read.Length, + (IoStackLocation->MinorFunction & IRP_MN_DPC ? "IRP_MN_DPC " : " "), + (IoStackLocation->MinorFunction & IRP_MN_MDL ? "IRP_MN_MDL " : " "), + (IoStackLocation->MinorFunction & IRP_MN_COMPRESSED ? "IRP_MN_COMPRESSED " : " "), + (Irp->Flags & IRP_PAGING_IO ? "IRP_PAGING_IO " : " "), + (Irp->Flags & IRP_NOCACHE ? "IRP_NOCACHE " : " "), + (FileObject->Flags & FO_SYNCHRONOUS_IO ? "FO_SYNCHRONOUS_IO " : " "))); + } + + break; + + case IRP_MJ_QUERY_INFORMATION: + + FileInformationClass = + IoStackLocation->Parameters.QueryFile.FileInformationClass; + + if (FileInformationClass <= FileMaximumInformation) + { + FFSPrintNoIndent(( + DBG_TRACE, "%s %s %s %s\n", + FFSGetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName, + FileInformationClassStrings[FileInformationClass])); + } + else + { + FFSPrintNoIndent(( + DBG_TRACE, + "%s %s %s Unknown FileInformationClass %u\n", + FFSGetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName, + FileInformationClass)); + } + + break; + + case IRP_MJ_SET_INFORMATION: + + FileInformationClass = + IoStackLocation->Parameters.SetFile.FileInformationClass; + + if (FileInformationClass <= FileMaximumInformation) + { + FFSPrintNoIndent(( + DBG_TRACE, "%s %s %s %s\n", + FFSGetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName, + FileInformationClassStrings[FileInformationClass])); + } + else + { + FFSPrintNoIndent(( + DBG_TRACE, + "%s %s %s Unknown FileInformationClass %u\n", + FFSGetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName, + FileInformationClass)); + } + + break; + + case IRP_MJ_QUERY_VOLUME_INFORMATION: + + FsInformationClass = + IoStackLocation->Parameters.QueryVolume.FsInformationClass; + + if (FsInformationClass <= FileFsMaximumInformation) + { + FFSPrintNoIndent(( + DBG_TRACE, "%s %s %s %s\n", + FFSGetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName, + FsInformationClassStrings[FsInformationClass])); + } + else + { + FFSPrintNoIndent(( + DBG_TRACE, + "%s %s %s Unknown FsInformationClass %u\n", + FFSGetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName, + FsInformationClass)); + } + + break; + + case IRP_MJ_DIRECTORY_CONTROL: + + if (IoStackLocation->MinorFunction & IRP_MN_QUERY_DIRECTORY) + { +#if !defined(_GNU_NTIFS_) || defined(__REACTOS__) + FileInformationClass = + IoStackLocation->Parameters.QueryDirectory.FileInformationClass; +#else + FileInformationClass = ((PEXTENDED_IO_STACK_LOCATION) + IoStackLocation)->Parameters.QueryDirectory.FileInformationClass; +#endif + + if (FileInformationClass <= FileMaximumInformation) + { + FFSPrintNoIndent(( + DBG_TRACE, "%s %s %s %s\n", + FFSGetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName, + FileInformationClassStrings[FileInformationClass])); + + if ( +#if !defined(_GNU_NTIFS_) || defined(__REACTOS__) + IoStackLocation->Parameters.QueryDirectory.FileName +#else + ((PEXTENDED_IO_STACK_LOCATION) + IoStackLocation)->Parameters.QueryDirectory.FileName +#endif + ) + { +#if !defined(_GNU_NTIFS_) || defined(__REACTOS__) + FFSPrintNoIndent(( + DBG_TRACE, "%s FileName: %.*S FileIndex: %x %s%s%s\n", + FFSGetCurrentProcessName(), + + IoStackLocation->Parameters.QueryDirectory.FileName->Length / 2, + IoStackLocation->Parameters.QueryDirectory.FileName->Buffer, + IoStackLocation->Parameters.QueryDirectory.FileIndex, + (IoStackLocation->Flags & SL_RESTART_SCAN ? "SL_RESTART_SCAN " : ""), + (IoStackLocation->Flags & SL_RETURN_SINGLE_ENTRY ? "SL_RETURN_SINGLE_ENTRY " : ""), + ((IoStackLocation->Flags & SL_INDEX_SPECIFIED) ? "SL_INDEX_SPECIFIED " : ""))); + +#else + FFSPrintNoIndent(( + DBG_TRACE, "%s FileName: %.*S FileIndex: %x %s%s%s\n", + FFSGetCurrentProcessName(), + + ((PEXTENDED_IO_STACK_LOCATION) + IoStackLocation)->Parameters.QueryDirectory.FileName->Length / 2, + ((PEXTENDED_IO_STACK_LOCATION) + IoStackLocation)->Parameters.QueryDirectory.FileName->Buffer, + ((PEXTENDED_IO_STACK_LOCATION) + IoStackLocation)->Parameters.QueryDirectory.FileIndex, + (IoStackLocation->Flags & SL_RESTART_SCAN ? "SL_RESTART_SCAN " : ""), + (IoStackLocation->Flags & SL_RETURN_SINGLE_ENTRY ? "SL_RETURN_SINGLE_ENTRY " : ""), + ((IoStackLocation->Flags & SL_INDEX_SPECIFIED) ? "SL_INDEX_SPECIFIED " : ""))); +#endif + } + else + { +#if !defined(_GNU_NTIFS_) || defined(__REACTOS__) + FFSPrintNoIndent(( + DBG_TRACE, "%s FileName: FileIndex: %#x %s%s%s\n", + FFSGetCurrentProcessName(), + IoStackLocation->Parameters.QueryDirectory.FileIndex, + (IoStackLocation->Flags & SL_RESTART_SCAN ? "SL_RESTART_SCAN " : ""), + (IoStackLocation->Flags & SL_RETURN_SINGLE_ENTRY ? "SL_RETURN_SINGLE_ENTRY " : ""), + (IoStackLocation->Flags & SL_INDEX_SPECIFIED ? "SL_INDEX_SPECIFIED " : ""))); +#else + FFSPrintNoIndent(( + DBG_TRACE, "%s FileName: FileIndex: %#x %s%s%s\n", + FFSGetCurrentProcessName(), + ((PEXTENDED_IO_STACK_LOCATION) + IoStackLocation)->Parameters.QueryDirectory.FileIndex, + (IoStackLocation->Flags & SL_RESTART_SCAN ? "SL_RESTART_SCAN " : ""), + (IoStackLocation->Flags & SL_RETURN_SINGLE_ENTRY ? "SL_RETURN_SINGLE_ENTRY " : ""), + (IoStackLocation->Flags & SL_INDEX_SPECIFIED ? "SL_INDEX_SPECIFIED " : ""))); +#endif + } + } + else + { + FFSPrintNoIndent(( + DBG_TRACE, + "%s %s %s Unknown FileInformationClass %u\n", + FFSGetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName, + FileInformationClass)); + } + } + else if (IoStackLocation->MinorFunction & IRP_MN_NOTIFY_CHANGE_DIRECTORY) + { + FFSPrintNoIndent(( + DBG_TRACE, "%s %s %s IRP_MN_NOTIFY_CHANGE_DIRECTORY\n", + FFSGetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName)); + } + else + { + FFSPrintNoIndent(( + DBG_TRACE, "%s %s %s Unknown minor function %#x\n", + FFSGetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName, + IoStackLocation->MinorFunction)); + } + + break; + + case IRP_MJ_FILE_SYSTEM_CONTROL: + + if (IoStackLocation->MinorFunction == IRP_MN_USER_FS_REQUEST) + { +#if !defined(_GNU_NTIFS_) || defined(__REACTOS__) + FFSPrintNoIndent(( + DBG_TRACE, + "%s %s %s IRP_MN_USER_FS_REQUEST FsControlCode: %#x\n", + FFSGetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName, + IoStackLocation->Parameters.FileSystemControl.FsControlCode)); +#else + FFSPrintNoIndent(( + DBG_TRACE, + "%s %s %s IRP_MN_USER_FS_REQUEST FsControlCode: %#x\n", + FFSGetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName, + ((PEXTENDED_IO_STACK_LOCATION) + IoStackLocation)->Parameters.FileSystemControl.FsControlCode)); +#endif + } + else if (IoStackLocation->MinorFunction == IRP_MN_MOUNT_VOLUME) + { + FFSPrintNoIndent(( + DBG_TRACE, + "%s %s %s IRP_MN_MOUNT_VOLUME DeviceObject: %#x\n", + FFSGetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName, + IoStackLocation->Parameters.MountVolume.DeviceObject)); + } + else if (IoStackLocation->MinorFunction == IRP_MN_VERIFY_VOLUME) + { + FFSPrintNoIndent(( + DBG_TRACE, + "%s %s %s IRP_MN_VERIFY_VOLUME DeviceObject: %#x\n", + FFSGetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName, + IoStackLocation->Parameters.VerifyVolume.DeviceObject)); + } + else if (IoStackLocation->MinorFunction == IRP_MN_LOAD_FILE_SYSTEM) + { + FFSPrintNoIndent(( + DBG_TRACE, "%s %s %s IRP_MN_LOAD_FILE_SYSTEM\n", + FFSGetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName)); + } +#if (_WIN32_WINNT >= 0x0500) + else if (IoStackLocation->MinorFunction == IRP_MN_KERNEL_CALL) + { + FFSPrintNoIndent(( + DBG_TRACE, "%s %s %s IRP_MN_KERNEL_CALL\n", + FFSGetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName)); + } +#endif // (_WIN32_WINNT >= 0x0500) + else + { + FFSPrintNoIndent(( + DBG_TRACE, "%s %s %s Unknown minor function %#x\n", + FFSGetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName, + IoStackLocation->MinorFunction)); + } + + break; + + case IRP_MJ_DEVICE_CONTROL: + + FFSPrintNoIndent(( + DBG_TRACE, "%s %s %s IoControlCode: %#x\n", + FFSGetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName, + IoStackLocation->Parameters.DeviceIoControl.IoControlCode)); + + break; + + case IRP_MJ_LOCK_CONTROL: + + if (IoStackLocation->MinorFunction & IRP_MN_LOCK) + { +#if !defined(_GNU_NTIFS_) || defined(__REACTOS__) + FFSPrintNoIndent(( + DBG_TRACE, "%s %s %s IRP_MN_LOCK Offset: %I64xh Length: %I64xh Key: %u %s%s\n", + FFSGetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName, + IoStackLocation->Parameters.LockControl.ByteOffset.QuadPart, + IoStackLocation->Parameters.LockControl.Length->QuadPart, + IoStackLocation->Parameters.LockControl.Key, + (IoStackLocation->Flags & SL_FAIL_IMMEDIATELY ? "SL_FAIL_IMMEDIATELY " : ""), + (IoStackLocation->Flags & SL_EXCLUSIVE_LOCK ? "SL_EXCLUSIVE_LOCK " : ""))); +#else + FFSPrintNoIndent(( + DBG_TRACE, "%s %s %s IRP_MN_LOCK Offset: %I64xh Length: %I64xh Key: %u %s%s\n", + FFSGetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName, + ((PEXTENDED_IO_STACK_LOCATION) + IoStackLocation)->Parameters.LockControl.ByteOffset.QuadPart, + ((PEXTENDED_IO_STACK_LOCATION) + IoStackLocation)->Parameters.LockControl.Length->QuadPart, + ((PEXTENDED_IO_STACK_LOCATION) + IoStackLocation)->Parameters.LockControl.Key, + (IoStackLocation->Flags & SL_FAIL_IMMEDIATELY ? "SL_FAIL_IMMEDIATELY " : ""), + (IoStackLocation->Flags & SL_EXCLUSIVE_LOCK ? "SL_EXCLUSIVE_LOCK " : ""))); +#endif + } + else if (IoStackLocation->MinorFunction & IRP_MN_UNLOCK_SINGLE) + { +#if !defined(_GNU_NTIFS_) || defined(__REACTOS__) + FFSPrintNoIndent(( + DBG_TRACE, "%s %s %s IRP_MN_UNLOCK_SINGLE Offset: %I64xh Length: %I64xh Key: %u\n", + FFSGetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName, + IoStackLocation->Parameters.LockControl.ByteOffset.QuadPart, + IoStackLocation->Parameters.LockControl.Length->QuadPart, + IoStackLocation->Parameters.LockControl.Key)); +#else + FFSPrintNoIndent(( + DBG_TRACE, "%s %s %s IRP_MN_UNLOCK_SINGLE Offset: %I64xh Length: %I64xh Key: %u\n", + FFSGetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName, + ((PEXTENDED_IO_STACK_LOCATION) + IoStackLocation)->Parameters.LockControl.ByteOffset.QuadPart, + ((PEXTENDED_IO_STACK_LOCATION) + IoStackLocation)->Parameters.LockControl.Length->QuadPart, + ((PEXTENDED_IO_STACK_LOCATION) + IoStackLocation)->Parameters.LockControl.Key)); +#endif + } + else if (IoStackLocation->MinorFunction & IRP_MN_UNLOCK_ALL) + { + FFSPrintNoIndent(( + DBG_TRACE, "%s %s %s IRP_MN_UNLOCK_ALL\n", + FFSGetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName)); + } + else if (IoStackLocation->MinorFunction & IRP_MN_UNLOCK_ALL_BY_KEY) + { +#if !defined(_GNU_NTIFS_) || defined(__REACTOS__) + FFSPrintNoIndent(( + DBG_TRACE, "%s %s %s IRP_MN_UNLOCK_ALL_BY_KEY Key: %u\n", + FFSGetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName, + IoStackLocation->Parameters.LockControl.Key)); +#else + FFSPrintNoIndent(( + DBG_TRACE, "%s %s %s IRP_MN_UNLOCK_ALL_BY_KEY Key: %u\n", + FFSGetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName, + ((PEXTENDED_IO_STACK_LOCATION) + IoStackLocation)->Parameters.LockControl.Key)); +#endif + } + else + { + FFSPrintNoIndent(( + DBG_TRACE, "%s %s %s Unknown minor function %#x\n", + FFSGetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName, + IoStackLocation->MinorFunction)); + } + + break; + + case IRP_MJ_CLEANUP: + + FFSPrintNoIndent(( + DBG_TRACE, "%s %s %s\n", + FFSGetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName)); + + break; + + case IRP_MJ_SHUTDOWN: + + FFSPrintNoIndent(( + DBG_TRACE, "%s %s %s\n", + FFSGetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName)); + + break; + +#if (_WIN32_WINNT >= 0x0500) + case IRP_MJ_PNP: + + FFSPrintNoIndent(( + DBG_TRACE, "%s %s %s\n", + FFSGetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName)); +#endif // (_WIN32_WINNT >= 0x0500) + break; + + + default: + + FFSPrintNoIndent(( + DBG_TRACE, "%s %s %s\n", + FFSGetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FileName)); + } +} + + +VOID +FFSDbgPrintComplete( + IN PIRP Irp, + IN BOOLEAN bPrint) +{ + PIO_STACK_LOCATION IoStackLocation; + + if (!Irp) + return; + + if (Irp->IoStatus.Status != STATUS_SUCCESS) + { + IoStackLocation = IoGetCurrentIrpStackLocation(Irp); + + if (bPrint) + { + FFSPrintNoIndent(( + DBG_TRACE, "%s %s Status: %s (%#x).\n", + FFSGetCurrentProcessName(), + IrpMjStrings[IoStackLocation->MajorFunction], + FFSNtStatusToString(Irp->IoStatus.Status), + Irp->IoStatus.Status)); + } + } +} + +PCHAR +FFSNtStatusToString( + IN NTSTATUS Status) +{ + switch (Status) + { + case 0x00000000: return "STATUS_SUCCESS"; + case 0x00000001: return "STATUS_WAIT_1"; + case 0x00000002: return "STATUS_WAIT_2"; + case 0x00000003: return "STATUS_WAIT_3"; + case 0x0000003F: return "STATUS_WAIT_63"; + case 0x00000080: return "STATUS_ABANDONED_WAIT_0"; + case 0x000000BF: return "STATUS_ABANDONED_WAIT_63"; + case 0x000000C0: return "STATUS_USER_APC"; + case 0x00000100: return "STATUS_KERNEL_APC"; + case 0x00000101: return "STATUS_ALERTED"; + case 0x00000102: return "STATUS_TIMEOUT"; + case 0x00000103: return "STATUS_PENDING"; + case 0x00000104: return "STATUS_REPARSE"; + case 0x00000105: return "STATUS_MORE_ENTRIES"; + case 0x00000106: return "STATUS_NOT_ALL_ASSIGNED"; + case 0x00000107: return "STATUS_SOME_NOT_MAPPED"; + case 0x00000108: return "STATUS_OPLOCK_BREAK_IN_PROGRESS"; + case 0x00000109: return "STATUS_VOLUME_MOUNTED"; + case 0x0000010A: return "STATUS_RXACT_COMMITTED"; + case 0x0000010B: return "STATUS_NOTIFY_CLEANUP"; + case 0x0000010C: return "STATUS_NOTIFY_ENUM_DIR"; + case 0x0000010D: return "STATUS_NO_QUOTAS_FOR_ACCOUNT"; + case 0x0000010E: return "STATUS_PRIMARY_TRANSPORT_CONNECT_FAILED"; + case 0x00000110: return "STATUS_PAGE_FAULT_TRANSITION"; + case 0x00000111: return "STATUS_PAGE_FAULT_DEMAND_ZERO"; + case 0x00000112: return "STATUS_PAGE_FAULT_COPY_ON_WRITE"; + case 0x00000113: return "STATUS_PAGE_FAULT_GUARD_PAGE"; + case 0x00000114: return "STATUS_PAGE_FAULT_PAGING_FILE"; + case 0x00000115: return "STATUS_CACHE_PAGE_LOCKED"; + case 0x00000116: return "STATUS_CRASH_DUMP"; + case 0x00000117: return "STATUS_BUFFER_ALL_ZEROS"; + case 0x00000118: return "STATUS_REPARSE_OBJECT"; + case 0x00000119: return "STATUS_RESOURCE_REQUIREMENTS_CHANGED"; + case 0x00000120: return "STATUS_TRANSLATION_COMPLETE"; + case 0x00000121: return "STATUS_DS_MEMBERSHIP_EVALUATED_LOCALLY"; + case 0x00010001: return "DBG_EXCEPTION_HANDLED"; + case 0x00010002: return "DBG_CONTINUE"; + case 0x40000000: return "STATUS_OBJECT_NAME_EXISTS"; + case 0x40000001: return "STATUS_THREAD_WAS_SUSPENDED"; + case 0x40000002: return "STATUS_WORKING_SET_LIMIT_RANGE"; + case 0x40000003: return "STATUS_IMAGE_NOT_AT_BASE"; + case 0x40000004: return "STATUS_RXACT_STATE_CREATED"; + case 0x40000005: return "STATUS_SEGMENT_NOTIFICATION"; + case 0x40000006: return "STATUS_LOCAL_USER_SESSION_KEY"; + case 0x40000007: return "STATUS_BAD_CURRENT_DIRECTORY"; + case 0x40000008: return "STATUS_SERIAL_MORE_WRITES"; + case 0x40000009: return "STATUS_REGISTRY_RECOVERED"; + case 0x4000000A: return "STATUS_FT_READ_RECOVERY_FROM_BACKUP"; + case 0x4000000B: return "STATUS_FT_WRITE_RECOVERY"; + case 0x4000000C: return "STATUS_SERIAL_COUNTER_TIMEOUT"; + case 0x4000000D: return "STATUS_NULL_LM_PASSWORD"; + case 0x4000000E: return "STATUS_IMAGE_MACHINE_TYPE_MISMATCH"; + case 0x4000000F: return "STATUS_RECEIVE_PARTIAL"; + case 0x40000010: return "STATUS_RECEIVE_EXPEDITED"; + case 0x40000011: return "STATUS_RECEIVE_PARTIAL_EXPEDITED"; + case 0x40000012: return "STATUS_EVENT_DONE"; + case 0x40000013: return "STATUS_EVENT_PENDING"; + case 0x40000014: return "STATUS_CHECKING_FILE_SYSTEM"; + case 0x40000015: return "STATUS_FATAL_APP_EXIT"; + case 0x40000016: return "STATUS_PREDEFINED_HANDLE"; + case 0x40000017: return "STATUS_WAS_UNLOCKED"; + case 0x40000018: return "STATUS_SERVICE_NOTIFICATION"; + case 0x40000019: return "STATUS_WAS_LOCKED"; + case 0x4000001A: return "STATUS_LOG_HARD_ERROR"; + case 0x4000001B: return "STATUS_ALREADY_WIN32"; + case 0x4000001C: return "STATUS_WX86_UNSIMULATE"; + case 0x4000001D: return "STATUS_WX86_CONTINUE"; + case 0x4000001E: return "STATUS_WX86_SINGLE_STEP"; + case 0x4000001F: return "STATUS_WX86_BREAKPOINT"; + case 0x40000020: return "STATUS_WX86_EXCEPTION_CONTINUE"; + case 0x40000021: return "STATUS_WX86_EXCEPTION_LASTCHANCE"; + case 0x40000022: return "STATUS_WX86_EXCEPTION_CHAIN"; + case 0x40000023: return "STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE"; + case 0x40000024: return "STATUS_NO_YIELD_PERFORMED"; + case 0x40000025: return "STATUS_TIMER_RESUME_IGNORED"; + case 0x40000026: return "STATUS_ARBITRATION_UNHANDLED"; + case 0x40000027: return "STATUS_CARDBUS_NOT_SUPPORTED"; + case 0x40000028: return "STATUS_WX86_CREATEWX86TIB"; + case 0x40000029: return "STATUS_MP_PROCESSOR_MISMATCH"; + case 0x40010001: return "DBG_REPLY_LATER"; + case 0x40010002: return "DBG_UNABLE_TO_PROVIDE_HANDLE"; + case 0x40010003: return "DBG_TERMINATE_THREAD"; + case 0x40010004: return "DBG_TERMINATE_PROCESS"; + case 0x40010005: return "DBG_CONTROL_C"; + case 0x40010006: return "DBG_PRINTEXCEPTION_C"; + case 0x40010007: return "DBG_RIPEXCEPTION"; + case 0x40010008: return "DBG_CONTROL_BREAK"; + case 0x80000001: return "STATUS_GUARD_PAGE_VIOLATION"; + case 0x80000002: return "STATUS_DATATYPE_MISALIGNMENT"; + case 0x80000003: return "STATUS_BREAKPOINT"; + case 0x80000004: return "STATUS_SINGLE_STEP"; + case 0x80000005: return "STATUS_BUFFER_OVERFLOW"; + case 0x80000006: return "STATUS_NO_MORE_FILES"; + case 0x80000007: return "STATUS_WAKE_SYSTEM_DEBUGGER"; + case 0x8000000A: return "STATUS_HANDLES_CLOSED"; + case 0x8000000B: return "STATUS_NO_INHERITANCE"; + case 0x8000000C: return "STATUS_GUID_SUBSTITUTION_MADE"; + case 0x8000000D: return "STATUS_PARTIAL_COPY"; + case 0x8000000E: return "STATUS_DEVICE_PAPER_EMPTY"; + case 0x8000000F: return "STATUS_DEVICE_POWERED_OFF"; + case 0x80000010: return "STATUS_DEVICE_OFF_LINE"; + case 0x80000011: return "STATUS_DEVICE_BUSY"; + case 0x80000012: return "STATUS_NO_MORE_EAS"; + case 0x80000013: return "STATUS_INVALID_EA_NAME"; + case 0x80000014: return "STATUS_EA_LIST_INCONSISTENT"; + case 0x80000015: return "STATUS_INVALID_EA_FLAG"; + case 0x80000016: return "STATUS_VERIFY_REQUIRED"; + case 0x80000017: return "STATUS_EXTRANEOUS_INFORMATION"; + case 0x80000018: return "STATUS_RXACT_COMMIT_NECESSARY"; + case 0x8000001A: return "STATUS_NO_MORE_ENTRIES"; + case 0x8000001B: return "STATUS_FILEMARK_DETECTED"; + case 0x8000001C: return "STATUS_MEDIA_CHANGED"; + case 0x8000001D: return "STATUS_BUS_RESET"; + case 0x8000001E: return "STATUS_END_OF_MEDIA"; + case 0x8000001F: return "STATUS_BEGINNING_OF_MEDIA"; + case 0x80000020: return "STATUS_MEDIA_CHECK"; + case 0x80000021: return "STATUS_SETMARK_DETECTED"; + case 0x80000022: return "STATUS_NO_DATA_DETECTED"; + case 0x80000023: return "STATUS_REDIRECTOR_HAS_OPEN_HANDLES"; + case 0x80000024: return "STATUS_SERVER_HAS_OPEN_HANDLES"; + case 0x80000025: return "STATUS_ALREADY_DISCONNECTED"; + case 0x80000026: return "STATUS_LONGJUMP"; + case 0x80010001: return "DBG_EXCEPTION_NOT_HANDLED"; + case 0xC0000001: return "STATUS_UNSUCCESSFUL"; + case 0xC0000002: return "STATUS_NOT_IMPLEMENTED"; + case 0xC0000003: return "STATUS_INVALID_INFO_CLASS"; + case 0xC0000004: return "STATUS_INFO_LENGTH_MISMATCH"; + case 0xC0000005: return "STATUS_ACCESS_VIOLATION"; + case 0xC0000006: return "STATUS_IN_PAGE_ERROR"; + case 0xC0000007: return "STATUS_PAGEFILE_QUOTA"; + case 0xC0000008: return "STATUS_INVALID_HANDLE"; + case 0xC0000009: return "STATUS_BAD_INITIAL_STACK"; + case 0xC000000A: return "STATUS_BAD_INITIAL_PC"; + case 0xC000000B: return "STATUS_INVALID_CID"; + case 0xC000000C: return "STATUS_TIMER_NOT_CANCELED"; + case 0xC000000D: return "STATUS_INVALID_PARAMETER"; + case 0xC000000E: return "STATUS_NO_SUCH_DEVICE"; + case 0xC000000F: return "STATUS_NO_SUCH_FILE"; + case 0xC0000010: return "STATUS_INVALID_DEVICE_REQUEST"; + case 0xC0000011: return "STATUS_END_OF_FILE"; + case 0xC0000012: return "STATUS_WRONG_VOLUME"; + case 0xC0000013: return "STATUS_NO_MEDIA_IN_DEVICE"; + case 0xC0000014: return "STATUS_UNRECOGNIZED_MEDIA"; + case 0xC0000015: return "STATUS_NONEXISTENT_SECTOR"; + case 0xC0000016: return "STATUS_MORE_PROCESSING_REQUIRED"; + case 0xC0000017: return "STATUS_NO_MEMORY"; + case 0xC0000018: return "STATUS_CONFLICTING_ADDRESSES"; + case 0xC0000019: return "STATUS_NOT_MAPPED_VIEW"; + case 0xC000001A: return "STATUS_UNABLE_TO_FREE_VM"; + case 0xC000001B: return "STATUS_UNABLE_TO_DELETE_SECTION"; + case 0xC000001C: return "STATUS_INVALID_SYSTEM_SERVICE"; + case 0xC000001D: return "STATUS_ILLEGAL_INSTRUCTION"; + case 0xC000001E: return "STATUS_INVALID_LOCK_SEQUENCE"; + case 0xC000001F: return "STATUS_INVALID_VIEW_SIZE"; + case 0xC0000020: return "STATUS_INVALID_FILE_FOR_SECTION"; + case 0xC0000021: return "STATUS_ALREADY_COMMITTED"; + case 0xC0000022: return "STATUS_ACCESS_DENIED"; + case 0xC0000023: return "STATUS_BUFFER_TOO_SMALL"; + case 0xC0000024: return "STATUS_OBJECT_TYPE_MISMATCH"; + case 0xC0000025: return "STATUS_NONCONTINUABLE_EXCEPTION"; + case 0xC0000026: return "STATUS_INVALID_DISPOSITION"; + case 0xC0000027: return "STATUS_UNWIND"; + case 0xC0000028: return "STATUS_BAD_STACK"; + case 0xC0000029: return "STATUS_INVALID_UNWIND_TARGET"; + case 0xC000002A: return "STATUS_NOT_LOCKED"; + case 0xC000002B: return "STATUS_PARITY_ERROR"; + case 0xC000002C: return "STATUS_UNABLE_TO_DECOMMIT_VM"; + case 0xC000002D: return "STATUS_NOT_COMMITTED"; + case 0xC000002E: return "STATUS_INVALID_PORT_ATTRIBUTES"; + case 0xC000002F: return "STATUS_PORT_MESSAGE_TOO_LONG"; + case 0xC0000030: return "STATUS_INVALID_PARAMETER_MIX"; + case 0xC0000031: return "STATUS_INVALID_QUOTA_LOWER"; + case 0xC0000032: return "STATUS_DISK_CORRUPT_ERROR"; + case 0xC0000033: return "STATUS_OBJECT_NAME_INVALID"; + case 0xC0000034: return "STATUS_OBJECT_NAME_NOT_FOUND"; + case 0xC0000035: return "STATUS_OBJECT_NAME_COLLISION"; + case 0xC0000037: return "STATUS_PORT_DISCONNECTED"; + case 0xC0000038: return "STATUS_DEVICE_ALREADY_ATTACHED"; + case 0xC0000039: return "STATUS_OBJECT_PATH_INVALID"; + case 0xC000003A: return "STATUS_OBJECT_PATH_NOT_FOUND"; + case 0xC000003B: return "STATUS_OBJECT_PATH_SYNTAX_BAD"; + case 0xC000003C: return "STATUS_DATA_OVERRUN"; + case 0xC000003D: return "STATUS_DATA_LATE_ERROR"; + case 0xC000003E: return "STATUS_DATA_ERROR"; + case 0xC000003F: return "STATUS_CRC_ERROR"; + case 0xC0000040: return "STATUS_SECTION_TOO_BIG"; + case 0xC0000041: return "STATUS_PORT_CONNECTION_REFUSED"; + case 0xC0000042: return "STATUS_INVALID_PORT_HANDLE"; + case 0xC0000043: return "STATUS_SHARING_VIOLATION"; + case 0xC0000044: return "STATUS_QUOTA_EXCEEDED"; + case 0xC0000045: return "STATUS_INVALID_PAGE_PROTECTION"; + case 0xC0000046: return "STATUS_MUTANT_NOT_OWNED"; + case 0xC0000047: return "STATUS_SEMAPHORE_LIMIT_EXCEEDED"; + case 0xC0000048: return "STATUS_PORT_ALREADY_SET"; + case 0xC0000049: return "STATUS_SECTION_NOT_IMAGE"; + case 0xC000004A: return "STATUS_SUSPEND_COUNT_EXCEEDED"; + case 0xC000004B: return "STATUS_THREAD_IS_TERMINATING"; + case 0xC000004C: return "STATUS_BAD_WORKING_SET_LIMIT"; + case 0xC000004D: return "STATUS_INCOMPATIBLE_FILE_MAP"; + case 0xC000004E: return "STATUS_SECTION_PROTECTION"; + case 0xC000004F: return "STATUS_EAS_NOT_SUPPORTED"; + case 0xC0000050: return "STATUS_EA_TOO_LARGE"; + case 0xC0000051: return "STATUS_NONEXISTENT_EA_ENTRY"; + case 0xC0000052: return "STATUS_NO_EAS_ON_FILE"; + case 0xC0000053: return "STATUS_EA_CORRUPT_ERROR"; + case 0xC0000054: return "STATUS_FILE_LOCK_CONFLICT"; + case 0xC0000055: return "STATUS_LOCK_NOT_GRANTED"; + case 0xC0000056: return "STATUS_DELETE_PENDING"; + case 0xC0000057: return "STATUS_CTL_FILE_NOT_SUPPORTED"; + case 0xC0000058: return "STATUS_UNKNOWN_REVISION"; + case 0xC0000059: return "STATUS_REVISION_MISMATCH"; + case 0xC000005A: return "STATUS_INVALID_OWNER"; + case 0xC000005B: return "STATUS_INVALID_PRIMARY_GROUP"; + case 0xC000005C: return "STATUS_NO_IMPERSONATION_TOKEN"; + case 0xC000005D: return "STATUS_CANT_DISABLE_MANDATORY"; + case 0xC000005E: return "STATUS_NO_LOGON_SERVERS"; + case 0xC000005F: return "STATUS_NO_SUCH_LOGON_SESSION"; + case 0xC0000060: return "STATUS_NO_SUCH_PRIVILEGE"; + case 0xC0000061: return "STATUS_PRIVILEGE_NOT_HELD"; + case 0xC0000062: return "STATUS_INVALID_ACCOUNT_NAME"; + case 0xC0000063: return "STATUS_USER_EXISTS"; + case 0xC0000064: return "STATUS_NO_SUCH_USER"; + case 0xC0000065: return "STATUS_GROUP_EXISTS"; + case 0xC0000066: return "STATUS_NO_SUCH_GROUP"; + case 0xC0000067: return "STATUS_MEMBER_IN_GROUP"; + case 0xC0000068: return "STATUS_MEMBER_NOT_IN_GROUP"; + case 0xC0000069: return "STATUS_LAST_ADMIN"; + case 0xC000006A: return "STATUS_WRONG_PASSWORD"; + case 0xC000006B: return "STATUS_ILL_FORMED_PASSWORD"; + case 0xC000006C: return "STATUS_PASSWORD_RESTRICTION"; + case 0xC000006D: return "STATUS_LOGON_FAILURE"; + case 0xC000006E: return "STATUS_ACCOUNT_RESTRICTION"; + case 0xC000006F: return "STATUS_INVALID_LOGON_HOURS"; + case 0xC0000070: return "STATUS_INVALID_WORKSTATION"; + case 0xC0000071: return "STATUS_PASSWORD_EXPIRED"; + case 0xC0000072: return "STATUS_ACCOUNT_DISABLED"; + case 0xC0000073: return "STATUS_NONE_MAPPED"; + case 0xC0000074: return "STATUS_TOO_MANY_LUIDS_REQUESTED"; + case 0xC0000075: return "STATUS_LUIDS_EXHAUSTED"; + case 0xC0000076: return "STATUS_INVALID_SUB_AUTHORITY"; + case 0xC0000077: return "STATUS_INVALID_ACL"; + case 0xC0000078: return "STATUS_INVALID_SID"; + case 0xC0000079: return "STATUS_INVALID_SECURITY_DESCR"; + case 0xC000007A: return "STATUS_PROCEDURE_NOT_FOUND"; + case 0xC000007B: return "STATUS_INVALID_IMAGE_FORMAT"; + case 0xC000007C: return "STATUS_NO_TOKEN"; + case 0xC000007D: return "STATUS_BAD_INHERITANCE_ACL"; + case 0xC000007E: return "STATUS_RANGE_NOT_LOCKED"; + case 0xC000007F: return "STATUS_DISK_FULL"; + case 0xC0000080: return "STATUS_SERVER_DISABLED"; + case 0xC0000081: return "STATUS_SERVER_NOT_DISABLED"; + case 0xC0000082: return "STATUS_TOO_MANY_GUIDS_REQUESTED"; + case 0xC0000083: return "STATUS_GUIDS_EXHAUSTED"; + case 0xC0000084: return "STATUS_INVALID_ID_AUTHORITY"; + case 0xC0000085: return "STATUS_AGENTS_EXHAUSTED"; + case 0xC0000086: return "STATUS_INVALID_VOLUME_LABEL"; + case 0xC0000087: return "STATUS_SECTION_NOT_EXTENDED"; + case 0xC0000088: return "STATUS_NOT_MAPPED_DATA"; + case 0xC0000089: return "STATUS_RESOURCE_DATA_NOT_FOUND"; + case 0xC000008A: return "STATUS_RESOURCE_TYPE_NOT_FOUND"; + case 0xC000008B: return "STATUS_RESOURCE_NAME_NOT_FOUND"; + case 0xC000008C: return "STATUS_ARRAY_BOUNDS_EXCEEDED"; + case 0xC000008D: return "STATUS_FLOAT_DENORMAL_OPERAND"; + case 0xC000008E: return "STATUS_FLOAT_DIVIDE_BY_ZERO"; + case 0xC000008F: return "STATUS_FLOAT_INEXACT_RESULT"; + case 0xC0000090: return "STATUS_FLOAT_INVALID_OPERATION"; + case 0xC0000091: return "STATUS_FLOAT_OVERFLOW"; + case 0xC0000092: return "STATUS_FLOAT_STACK_CHECK"; + case 0xC0000093: return "STATUS_FLOAT_UNDERFLOW"; + case 0xC0000094: return "STATUS_INTEGER_DIVIDE_BY_ZERO"; + case 0xC0000095: return "STATUS_INTEGER_OVERFLOW"; + case 0xC0000096: return "STATUS_PRIVILEGED_INSTRUCTION"; + case 0xC0000097: return "STATUS_TOO_MANY_PAGING_FILES"; + case 0xC0000098: return "STATUS_FILE_INVALID"; + case 0xC0000099: return "STATUS_ALLOTTED_SPACE_EXCEEDED"; + case 0xC000009A: return "STATUS_INSUFFICIENT_RESOURCES"; + case 0xC000009B: return "STATUS_DFS_EXIT_PATH_FOUND"; + case 0xC000009C: return "STATUS_DEVICE_DATA_ERROR"; + case 0xC000009D: return "STATUS_DEVICE_NOT_CONNECTED"; + case 0xC000009E: return "STATUS_DEVICE_POWER_FAILURE"; + case 0xC000009F: return "STATUS_FREE_VM_NOT_AT_BASE"; + case 0xC00000A0: return "STATUS_MEMORY_NOT_ALLOCATED"; + case 0xC00000A1: return "STATUS_WORKING_SET_QUOTA"; + case 0xC00000A2: return "STATUS_MEDIA_WRITE_PROTECTED"; + case 0xC00000A3: return "STATUS_DEVICE_NOT_READY"; + case 0xC00000A4: return "STATUS_INVALID_GROUP_ATTRIBUTES"; + case 0xC00000A5: return "STATUS_BAD_IMPERSONATION_LEVEL"; + case 0xC00000A6: return "STATUS_CANT_OPEN_ANONYMOUS"; + case 0xC00000A7: return "STATUS_BAD_VALIDATION_CLASS"; + case 0xC00000A8: return "STATUS_BAD_TOKEN_TYPE"; + case 0xC00000A9: return "STATUS_BAD_MASTER_BOOT_RECORD"; + case 0xC00000AA: return "STATUS_INSTRUCTION_MISALIGNMENT"; + case 0xC00000AB: return "STATUS_INSTANCE_NOT_AVAILABLE"; + case 0xC00000AC: return "STATUS_PIPE_NOT_AVAILABLE"; + case 0xC00000AD: return "STATUS_INVALID_PIPE_STATE"; + case 0xC00000AE: return "STATUS_PIPE_BUSY"; + case 0xC00000AF: return "STATUS_ILLEGAL_FUNCTION"; + case 0xC00000B0: return "STATUS_PIPE_DISCONNECTED"; + case 0xC00000B1: return "STATUS_PIPE_CLOSING"; + case 0xC00000B2: return "STATUS_PIPE_CONNECTED"; + case 0xC00000B3: return "STATUS_PIPE_LISTENING"; + case 0xC00000B4: return "STATUS_INVALID_READ_MODE"; + case 0xC00000B5: return "STATUS_IO_TIMEOUT"; + case 0xC00000B6: return "STATUS_FILE_FORCED_CLOSED"; + case 0xC00000B7: return "STATUS_PROFILING_NOT_STARTED"; + case 0xC00000B8: return "STATUS_PROFILING_NOT_STOPPED"; + case 0xC00000B9: return "STATUS_COULD_NOT_INTERPRET"; + case 0xC00000BA: return "STATUS_FILE_IS_A_DIRECTORY"; + case 0xC00000BB: return "STATUS_NOT_SUPPORTED"; + case 0xC00000BC: return "STATUS_REMOTE_NOT_LISTENING"; + case 0xC00000BD: return "STATUS_DUPLICATE_NAME"; + case 0xC00000BE: return "STATUS_BAD_NETWORK_PATH"; + case 0xC00000BF: return "STATUS_NETWORK_BUSY"; + case 0xC00000C0: return "STATUS_DEVICE_DOES_NOT_EXIST"; + case 0xC00000C1: return "STATUS_TOO_MANY_COMMANDS"; + case 0xC00000C2: return "STATUS_ADAPTER_HARDWARE_ERROR"; + case 0xC00000C3: return "STATUS_INVALID_NETWORK_RESPONSE"; + case 0xC00000C4: return "STATUS_UNEXPECTED_NETWORK_ERROR"; + case 0xC00000C5: return "STATUS_BAD_REMOTE_ADAPTER"; + case 0xC00000C6: return "STATUS_PRINT_QUEUE_FULL"; + case 0xC00000C7: return "STATUS_NO_SPOOL_SPACE"; + case 0xC00000C8: return "STATUS_PRINT_CANCELLED"; + case 0xC00000C9: return "STATUS_NETWORK_NAME_DELETED"; + case 0xC00000CA: return "STATUS_NETWORK_ACCESS_DENIED"; + case 0xC00000CB: return "STATUS_BAD_DEVICE_TYPE"; + case 0xC00000CC: return "STATUS_BAD_NETWORK_NAME"; + case 0xC00000CD: return "STATUS_TOO_MANY_NAMES"; + case 0xC00000CE: return "STATUS_TOO_MANY_SESSIONS"; + case 0xC00000CF: return "STATUS_SHARING_PAUSED"; + case 0xC00000D0: return "STATUS_REQUEST_NOT_ACCEPTED"; + case 0xC00000D1: return "STATUS_REDIRECTOR_PAUSED"; + case 0xC00000D2: return "STATUS_NET_WRITE_FAULT"; + case 0xC00000D3: return "STATUS_PROFILING_AT_LIMIT"; + case 0xC00000D4: return "STATUS_NOT_SAME_DEVICE"; + case 0xC00000D5: return "STATUS_FILE_RENAMED"; + case 0xC00000D6: return "STATUS_VIRTUAL_CIRCUIT_CLOSED"; + case 0xC00000D7: return "STATUS_NO_SECURITY_ON_OBJECT"; + case 0xC00000D8: return "STATUS_CANT_WAIT"; + case 0xC00000D9: return "STATUS_PIPE_EMPTY"; + case 0xC00000DA: return "STATUS_CANT_ACCESS_DOMAIN_INFO"; + case 0xC00000DB: return "STATUS_CANT_TERMINATE_SELF"; + case 0xC00000DC: return "STATUS_INVALID_SERVER_STATE"; + case 0xC00000DD: return "STATUS_INVALID_DOMAIN_STATE"; + case 0xC00000DE: return "STATUS_INVALID_DOMAIN_ROLE"; + case 0xC00000DF: return "STATUS_NO_SUCH_DOMAIN"; + case 0xC00000E0: return "STATUS_DOMAIN_EXISTS"; + case 0xC00000E1: return "STATUS_DOMAIN_LIMIT_EXCEEDED"; + case 0xC00000E2: return "STATUS_OPLOCK_NOT_GRANTED"; + case 0xC00000E3: return "STATUS_INVALID_OPLOCK_PROTOCOL"; + case 0xC00000E4: return "STATUS_INTERNAL_DB_CORRUPTION"; + case 0xC00000E5: return "STATUS_INTERNAL_ERROR"; + case 0xC00000E6: return "STATUS_GENERIC_NOT_MAPPED"; + case 0xC00000E7: return "STATUS_BAD_DESCRIPTOR_FORMAT"; + case 0xC00000E8: return "STATUS_INVALID_USER_BUFFER"; + case 0xC00000E9: return "STATUS_UNEXPECTED_IO_ERROR"; + case 0xC00000EA: return "STATUS_UNEXPECTED_MM_CREATE_ERR"; + case 0xC00000EB: return "STATUS_UNEXPECTED_MM_MAP_ERROR"; + case 0xC00000EC: return "STATUS_UNEXPECTED_MM_EXTEND_ERR"; + case 0xC00000ED: return "STATUS_NOT_LOGON_PROCESS"; + case 0xC00000EE: return "STATUS_LOGON_SESSION_EXISTS"; + case 0xC00000EF: return "STATUS_INVALID_PARAMETER_1"; + case 0xC00000F0: return "STATUS_INVALID_PARAMETER_2"; + case 0xC00000F1: return "STATUS_INVALID_PARAMETER_3"; + case 0xC00000F2: return "STATUS_INVALID_PARAMETER_4"; + case 0xC00000F3: return "STATUS_INVALID_PARAMETER_5"; + case 0xC00000F4: return "STATUS_INVALID_PARAMETER_6"; + case 0xC00000F5: return "STATUS_INVALID_PARAMETER_7"; + case 0xC00000F6: return "STATUS_INVALID_PARAMETER_8"; + case 0xC00000F7: return "STATUS_INVALID_PARAMETER_9"; + case 0xC00000F8: return "STATUS_INVALID_PARAMETER_10"; + case 0xC00000F9: return "STATUS_INVALID_PARAMETER_11"; + case 0xC00000FA: return "STATUS_INVALID_PARAMETER_12"; + case 0xC00000FB: return "STATUS_REDIRECTOR_NOT_STARTED"; + case 0xC00000FC: return "STATUS_REDIRECTOR_STARTED"; + case 0xC00000FD: return "STATUS_STACK_OVERFLOW"; + case 0xC00000FE: return "STATUS_NO_SUCH_PACKAGE"; + case 0xC00000FF: return "STATUS_BAD_FUNCTION_TABLE"; + case 0xC0000100: return "STATUS_VARIABLE_NOT_FOUND"; + case 0xC0000101: return "STATUS_DIRECTORY_NOT_EMPTY"; + case 0xC0000102: return "STATUS_FILE_CORRUPT_ERROR"; + case 0xC0000103: return "STATUS_NOT_A_DIRECTORY"; + case 0xC0000104: return "STATUS_BAD_LOGON_SESSION_STATE"; + case 0xC0000105: return "STATUS_LOGON_SESSION_COLLISION"; + case 0xC0000106: return "STATUS_NAME_TOO_LONG"; + case 0xC0000107: return "STATUS_FILES_OPEN"; + case 0xC0000108: return "STATUS_CONNECTION_IN_USE"; + case 0xC0000109: return "STATUS_MESSAGE_NOT_FOUND"; + case 0xC000010A: return "STATUS_PROCESS_IS_TERMINATING"; + case 0xC000010B: return "STATUS_INVALID_LOGON_TYPE"; + case 0xC000010C: return "STATUS_NO_GUID_TRANSLATION"; + case 0xC000010D: return "STATUS_CANNOT_IMPERSONATE"; + case 0xC000010E: return "STATUS_IMAGE_ALREADY_LOADED"; + case 0xC000010F: return "STATUS_ABIOS_NOT_PRESENT"; + case 0xC0000110: return "STATUS_ABIOS_LID_NOT_EXIST"; + case 0xC0000111: return "STATUS_ABIOS_LID_ALREADY_OWNED"; + case 0xC0000112: return "STATUS_ABIOS_NOT_LID_OWNER"; + case 0xC0000113: return "STATUS_ABIOS_INVALID_COMMAND"; + case 0xC0000114: return "STATUS_ABIOS_INVALID_LID"; + case 0xC0000115: return "STATUS_ABIOS_SELECTOR_NOT_AVAILABLE"; + case 0xC0000116: return "STATUS_ABIOS_INVALID_SELECTOR"; + case 0xC0000117: return "STATUS_NO_LDT"; + case 0xC0000118: return "STATUS_INVALID_LDT_SIZE"; + case 0xC0000119: return "STATUS_INVALID_LDT_OFFSET"; + case 0xC000011A: return "STATUS_INVALID_LDT_DESCRIPTOR"; + case 0xC000011B: return "STATUS_INVALID_IMAGE_NE_FORMAT"; + case 0xC000011C: return "STATUS_RXACT_INVALID_STATE"; + case 0xC000011D: return "STATUS_RXACT_COMMIT_FAILURE"; + case 0xC000011E: return "STATUS_MAPPED_FILE_SIZE_ZERO"; + case 0xC000011F: return "STATUS_TOO_MANY_OPENED_FILES"; + case 0xC0000120: return "STATUS_CANCELLED"; + case 0xC0000121: return "STATUS_CANNOT_DELETE"; + case 0xC0000122: return "STATUS_INVALID_COMPUTER_NAME"; + case 0xC0000123: return "STATUS_FILE_DELETED"; + case 0xC0000124: return "STATUS_SPECIAL_ACCOUNT"; + case 0xC0000125: return "STATUS_SPECIAL_GROUP"; + case 0xC0000126: return "STATUS_SPECIAL_USER"; + case 0xC0000127: return "STATUS_MEMBERS_PRIMARY_GROUP"; + case 0xC0000128: return "STATUS_FILE_CLOSED"; + case 0xC0000129: return "STATUS_TOO_MANY_THREADS"; + case 0xC000012A: return "STATUS_THREAD_NOT_IN_PROCESS"; + case 0xC000012B: return "STATUS_TOKEN_ALREADY_IN_USE"; + case 0xC000012C: return "STATUS_PAGEFILE_QUOTA_EXCEEDED"; + case 0xC000012D: return "STATUS_COMMITMENT_LIMIT"; + case 0xC000012E: return "STATUS_INVALID_IMAGE_LE_FORMAT"; + case 0xC000012F: return "STATUS_INVALID_IMAGE_NOT_MZ"; + case 0xC0000130: return "STATUS_INVALID_IMAGE_PROTECT"; + case 0xC0000131: return "STATUS_INVALID_IMAGE_WIN_16"; + case 0xC0000132: return "STATUS_LOGON_SERVER_CONFLICT"; + case 0xC0000133: return "STATUS_TIME_DIFFERENCE_AT_DC"; + case 0xC0000134: return "STATUS_SYNCHRONIZATION_REQUIRED"; + case 0xC0000135: return "STATUS_DLL_NOT_FOUND"; + case 0xC0000136: return "STATUS_OPEN_FAILED"; + case 0xC0000137: return "STATUS_IO_PRIVILEGE_FAILED"; + case 0xC0000138: return "STATUS_ORDINAL_NOT_FOUND"; + case 0xC0000139: return "STATUS_ENTRYPOINT_NOT_FOUND"; + case 0xC000013A: return "STATUS_CONTROL_C_EXIT"; + case 0xC000013B: return "STATUS_LOCAL_DISCONNECT"; + case 0xC000013C: return "STATUS_REMOTE_DISCONNECT"; + case 0xC000013D: return "STATUS_REMOTE_RESOURCES"; + case 0xC000013E: return "STATUS_LINK_FAILED"; + case 0xC000013F: return "STATUS_LINK_TIMEOUT"; + case 0xC0000140: return "STATUS_INVALID_CONNECTION"; + case 0xC0000141: return "STATUS_INVALID_ADDRESS"; + case 0xC0000142: return "STATUS_DLL_INIT_FAILED"; + case 0xC0000143: return "STATUS_MISSING_SYSTEMFILE"; + case 0xC0000144: return "STATUS_UNHANDLED_EXCEPTION"; + case 0xC0000145: return "STATUS_APP_INIT_FAILURE"; + case 0xC0000146: return "STATUS_PAGEFILE_CREATE_FAILED"; + case 0xC0000147: return "STATUS_NO_PAGEFILE"; + case 0xC0000148: return "STATUS_INVALID_LEVEL"; + case 0xC0000149: return "STATUS_WRONG_PASSWORD_CORE"; + case 0xC000014A: return "STATUS_ILLEGAL_FLOAT_CONTEXT"; + case 0xC000014B: return "STATUS_PIPE_BROKEN"; + case 0xC000014C: return "STATUS_REGISTRY_CORRUPT"; + case 0xC000014D: return "STATUS_REGISTRY_IO_FAILED"; + case 0xC000014E: return "STATUS_NO_EVENT_PAIR"; + case 0xC000014F: return "STATUS_UNRECOGNIZED_VOLUME"; + case 0xC0000150: return "STATUS_SERIAL_NO_DEVICE_INITED"; + case 0xC0000151: return "STATUS_NO_SUCH_ALIAS"; + case 0xC0000152: return "STATUS_MEMBER_NOT_IN_ALIAS"; + case 0xC0000153: return "STATUS_MEMBER_IN_ALIAS"; + case 0xC0000154: return "STATUS_ALIAS_EXISTS"; + case 0xC0000155: return "STATUS_LOGON_NOT_GRANTED"; + case 0xC0000156: return "STATUS_TOO_MANY_SECRETS"; + case 0xC0000157: return "STATUS_SECRET_TOO_LONG"; + case 0xC0000158: return "STATUS_INTERNAL_DB_ERROR"; + case 0xC0000159: return "STATUS_FULLSCREEN_MODE"; + case 0xC000015A: return "STATUS_TOO_MANY_CONTEXT_IDS"; + case 0xC000015B: return "STATUS_LOGON_TYPE_NOT_GRANTED"; + case 0xC000015C: return "STATUS_NOT_REGISTRY_FILE"; + case 0xC000015D: return "STATUS_NT_CROSS_ENCRYPTION_REQUIRED"; + case 0xC000015E: return "STATUS_DOMAIN_CTRLR_CONFIG_ERROR"; + case 0xC000015F: return "STATUS_FT_MISSING_MEMBER"; + case 0xC0000160: return "STATUS_ILL_FORMED_SERVICE_ENTRY"; + case 0xC0000161: return "STATUS_ILLEGAL_CHARACTER"; + case 0xC0000162: return "STATUS_UNMAPPABLE_CHARACTER"; + case 0xC0000163: return "STATUS_UNDEFINED_CHARACTER"; + case 0xC0000164: return "STATUS_FLOPPY_VOLUME"; + case 0xC0000165: return "STATUS_FLOPPY_ID_MARK_NOT_FOUND"; + case 0xC0000166: return "STATUS_FLOPPY_WRONG_CYLINDER"; + case 0xC0000167: return "STATUS_FLOPPY_UNKNOWN_ERROR"; + case 0xC0000168: return "STATUS_FLOPPY_BAD_REGISTERS"; + case 0xC0000169: return "STATUS_DISK_RECALIBRATE_FAILED"; + case 0xC000016A: return "STATUS_DISK_OPERATION_FAILED"; + case 0xC000016B: return "STATUS_DISK_RESET_FAILED"; + case 0xC000016C: return "STATUS_SHARED_IRQ_BUSY"; + case 0xC000016D: return "STATUS_FT_ORPHANING"; + case 0xC000016E: return "STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT"; + case 0xC0000172: return "STATUS_PARTITION_FAILURE"; + case 0xC0000173: return "STATUS_INVALID_BLOCK_LENGTH"; + case 0xC0000174: return "STATUS_DEVICE_NOT_PARTITIONED"; + case 0xC0000175: return "STATUS_UNABLE_TO_LOCK_MEDIA"; + case 0xC0000176: return "STATUS_UNABLE_TO_UNLOAD_MEDIA"; + case 0xC0000177: return "STATUS_EOM_OVERFLOW"; + case 0xC0000178: return "STATUS_NO_MEDIA"; + case 0xC000017A: return "STATUS_NO_SUCH_MEMBER"; + case 0xC000017B: return "STATUS_INVALID_MEMBER"; + case 0xC000017C: return "STATUS_KEY_DELETED"; + case 0xC000017D: return "STATUS_NO_LOG_SPACE"; + case 0xC000017E: return "STATUS_TOO_MANY_SIDS"; + case 0xC000017F: return "STATUS_LM_CROSS_ENCRYPTION_REQUIRED"; + case 0xC0000180: return "STATUS_KEY_HAS_CHILDREN"; + case 0xC0000181: return "STATUS_CHILD_MUST_BE_VOLATILE"; + case 0xC0000182: return "STATUS_DEVICE_CONFIGURATION_ERROR"; + case 0xC0000183: return "STATUS_DRIVER_INTERNAL_ERROR"; + case 0xC0000184: return "STATUS_INVALID_DEVICE_STATE"; + case 0xC0000185: return "STATUS_IO_DEVICE_ERROR"; + case 0xC0000186: return "STATUS_DEVICE_PROTOCOL_ERROR"; + case 0xC0000187: return "STATUS_BACKUP_CONTROLLER"; + case 0xC0000188: return "STATUS_LOG_FILE_FULL"; + case 0xC0000189: return "STATUS_TOO_LATE"; + case 0xC000018A: return "STATUS_NO_TRUST_LSA_SECRET"; + case 0xC000018B: return "STATUS_NO_TRUST_SAM_ACCOUNT"; + case 0xC000018C: return "STATUS_TRUSTED_DOMAIN_FAILURE"; + case 0xC000018D: return "STATUS_TRUSTED_RELATIONSHIP_FAILURE"; + case 0xC000018E: return "STATUS_EVENTLOG_FILE_CORRUPT"; + case 0xC000018F: return "STATUS_EVENTLOG_CANT_START"; + case 0xC0000190: return "STATUS_TRUST_FAILURE"; + case 0xC0000191: return "STATUS_MUTANT_LIMIT_EXCEEDED"; + case 0xC0000192: return "STATUS_NETLOGON_NOT_STARTED"; + case 0xC0000193: return "STATUS_ACCOUNT_EXPIRED"; + case 0xC0000194: return "STATUS_POSSIBLE_DEADLOCK"; + case 0xC0000195: return "STATUS_NETWORK_CREDENTIAL_CONFLICT"; + case 0xC0000196: return "STATUS_REMOTE_SESSION_LIMIT"; + case 0xC0000197: return "STATUS_EVENTLOG_FILE_CHANGED"; + case 0xC0000198: return "STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT"; + case 0xC0000199: return "STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT"; + case 0xC000019A: return "STATUS_NOLOGON_SERVER_TRUST_ACCOUNT"; + case 0xC000019B: return "STATUS_DOMAIN_TRUST_INCONSISTENT"; + case 0xC000019C: return "STATUS_FS_DRIVER_REQUIRED"; + case 0xC0000202: return "STATUS_NO_USER_SESSION_KEY"; + case 0xC0000203: return "STATUS_USER_SESSION_DELETED"; + case 0xC0000204: return "STATUS_RESOURCE_LANG_NOT_FOUND"; + case 0xC0000205: return "STATUS_INSUFF_SERVER_RESOURCES"; + case 0xC0000206: return "STATUS_INVALID_BUFFER_SIZE"; + case 0xC0000207: return "STATUS_INVALID_ADDRESS_COMPONENT"; + case 0xC0000208: return "STATUS_INVALID_ADDRESS_WILDCARD"; + case 0xC0000209: return "STATUS_TOO_MANY_ADDRESSES"; + case 0xC000020A: return "STATUS_ADDRESS_ALREADY_EXISTS"; + case 0xC000020B: return "STATUS_ADDRESS_CLOSED"; + case 0xC000020C: return "STATUS_CONNECTION_DISCONNECTED"; + case 0xC000020D: return "STATUS_CONNECTION_RESET"; + case 0xC000020E: return "STATUS_TOO_MANY_NODES"; + case 0xC000020F: return "STATUS_TRANSACTION_ABORTED"; + case 0xC0000210: return "STATUS_TRANSACTION_TIMED_OUT"; + case 0xC0000211: return "STATUS_TRANSACTION_NO_RELEASE"; + case 0xC0000212: return "STATUS_TRANSACTION_NO_MATCH"; + case 0xC0000213: return "STATUS_TRANSACTION_RESPONDED"; + case 0xC0000214: return "STATUS_TRANSACTION_INVALID_ID"; + case 0xC0000215: return "STATUS_TRANSACTION_INVALID_TYPE"; + case 0xC0000216: return "STATUS_NOT_SERVER_SESSION"; + case 0xC0000217: return "STATUS_NOT_CLIENT_SESSION"; + case 0xC0000218: return "STATUS_CANNOT_LOAD_REGISTRY_FILE"; + case 0xC0000219: return "STATUS_DEBUG_ATTACH_FAILED"; + case 0xC000021A: return "STATUS_SYSTEM_PROCESS_TERMINATED"; + case 0xC000021B: return "STATUS_DATA_NOT_ACCEPTED"; + case 0xC000021C: return "STATUS_NO_BROWSER_SERVERS_FOUND"; + case 0xC000021D: return "STATUS_VDM_HARD_ERROR"; + case 0xC000021E: return "STATUS_DRIVER_CANCEL_TIMEOUT"; + case 0xC000021F: return "STATUS_REPLY_MESSAGE_MISMATCH"; + case 0xC0000220: return "STATUS_MAPPED_ALIGNMENT"; + case 0xC0000221: return "STATUS_IMAGE_CHECKSUM_MISMATCH"; + case 0xC0000222: return "STATUS_LOST_WRITEBEHIND_DATA"; + case 0xC0000223: return "STATUS_CLIENT_SERVER_PARAMETERS_INVALID"; + case 0xC0000224: return "STATUS_PASSWORD_MUST_CHANGE"; + case 0xC0000225: return "STATUS_NOT_FOUND"; + case 0xC0000226: return "STATUS_NOT_TINY_STREAM"; + case 0xC0000227: return "STATUS_RECOVERY_FAILURE"; + case 0xC0000228: return "STATUS_STACK_OVERFLOW_READ"; + case 0xC0000229: return "STATUS_FAIL_CHECK"; + case 0xC000022A: return "STATUS_DUPLICATE_OBJECTID"; + case 0xC000022B: return "STATUS_OBJECTID_EXISTS"; + case 0xC000022C: return "STATUS_CONVERT_TO_LARGE"; + case 0xC000022D: return "STATUS_RETRY"; + case 0xC000022E: return "STATUS_FOUND_OUT_OF_SCOPE"; + case 0xC000022F: return "STATUS_ALLOCATE_BUCKET"; + case 0xC0000230: return "STATUS_PROPSET_NOT_FOUND"; + case 0xC0000231: return "STATUS_MARSHALL_OVERFLOW"; + case 0xC0000232: return "STATUS_INVALID_VARIANT"; + case 0xC0000233: return "STATUS_DOMAIN_CONTROLLER_NOT_FOUND"; + case 0xC0000234: return "STATUS_ACCOUNT_LOCKED_OUT"; + case 0xC0000235: return "STATUS_HANDLE_NOT_CLOSABLE"; + case 0xC0000236: return "STATUS_CONNECTION_REFUSED"; + case 0xC0000237: return "STATUS_GRACEFUL_DISCONNECT"; + case 0xC0000238: return "STATUS_ADDRESS_ALREADY_ASSOCIATED"; + case 0xC0000239: return "STATUS_ADDRESS_NOT_ASSOCIATED"; + case 0xC000023A: return "STATUS_CONNECTION_INVALID"; + case 0xC000023B: return "STATUS_CONNECTION_ACTIVE"; + case 0xC000023C: return "STATUS_NETWORK_UNREACHABLE"; + case 0xC000023D: return "STATUS_HOST_UNREACHABLE"; + case 0xC000023E: return "STATUS_PROTOCOL_UNREACHABLE"; + case 0xC000023F: return "STATUS_PORT_UNREACHABLE"; + case 0xC0000240: return "STATUS_REQUEST_ABORTED"; + case 0xC0000241: return "STATUS_CONNECTION_ABORTED"; + case 0xC0000242: return "STATUS_BAD_COMPRESSION_BUFFER"; + case 0xC0000243: return "STATUS_USER_MAPPED_FILE"; + case 0xC0000244: return "STATUS_AUDIT_FAILED"; + case 0xC0000245: return "STATUS_TIMER_RESOLUTION_NOT_SET"; + case 0xC0000246: return "STATUS_CONNECTION_COUNT_LIMIT"; + case 0xC0000247: return "STATUS_LOGIN_TIME_RESTRICTION"; + case 0xC0000248: return "STATUS_LOGIN_WKSTA_RESTRICTION"; + case 0xC0000249: return "STATUS_IMAGE_MP_UP_MISMATCH"; + case 0xC0000250: return "STATUS_INSUFFICIENT_LOGON_INFO"; + case 0xC0000251: return "STATUS_BAD_DLL_ENTRYPOINT"; + case 0xC0000252: return "STATUS_BAD_SERVICE_ENTRYPOINT"; + case 0xC0000253: return "STATUS_LPC_REPLY_LOST"; + case 0xC0000254: return "STATUS_IP_ADDRESS_CONFLICT1"; + case 0xC0000255: return "STATUS_IP_ADDRESS_CONFLICT2"; + case 0xC0000256: return "STATUS_REGISTRY_QUOTA_LIMIT"; + case 0xC0000257: return "STATUS_PATH_NOT_COVERED"; + case 0xC0000258: return "STATUS_NO_CALLBACK_ACTIVE"; + case 0xC0000259: return "STATUS_LICENSE_QUOTA_EXCEEDED"; + case 0xC000025A: return "STATUS_PWD_TOO_SHORT"; + case 0xC000025B: return "STATUS_PWD_TOO_RECENT"; + case 0xC000025C: return "STATUS_PWD_HISTORY_CONFLICT"; + case 0xC000025E: return "STATUS_PLUGPLAY_NO_DEVICE"; + case 0xC000025F: return "STATUS_UNSUPPORTED_COMPRESSION"; + case 0xC0000260: return "STATUS_INVALID_HW_PROFILE"; + case 0xC0000261: return "STATUS_INVALID_PLUGPLAY_DEVICE_PATH"; + case 0xC0000262: return "STATUS_DRIVER_ORDINAL_NOT_FOUND"; + case 0xC0000263: return "STATUS_DRIVER_ENTRYPOINT_NOT_FOUND"; + case 0xC0000264: return "STATUS_RESOURCE_NOT_OWNED"; + case 0xC0000265: return "STATUS_TOO_MANY_LINKS"; + case 0xC0000266: return "STATUS_QUOTA_LIST_INCONSISTENT"; + case 0xC0000267: return "STATUS_FILE_IS_OFFLINE"; + case 0xC0000268: return "STATUS_EVALUATION_EXPIRATION"; + case 0xC0000269: return "STATUS_ILLEGAL_DLL_RELOCATION"; + case 0xC000026A: return "STATUS_LICENSE_VIOLATION"; + case 0xC000026B: return "STATUS_DLL_INIT_FAILED_LOGOFF"; + case 0xC000026C: return "STATUS_DRIVER_UNABLE_TO_LOAD"; + case 0xC000026D: return "STATUS_DFS_UNAVAILABLE"; + case 0xC000026E: return "STATUS_VOLUME_DISMOUNTED"; + case 0xC000026F: return "STATUS_WX86_INTERNAL_ERROR"; + case 0xC0000270: return "STATUS_WX86_FLOAT_STACK_CHECK"; + case 0xC0000271: return "STATUS_VALIDATE_CONTINUE"; + case 0xC0000272: return "STATUS_NO_MATCH"; + case 0xC0000273: return "STATUS_NO_MORE_MATCHES"; + case 0xC0000275: return "STATUS_NOT_A_REPARSE_POINT"; + case 0xC0000276: return "STATUS_IO_REPARSE_TAG_INVALID"; + case 0xC0000277: return "STATUS_IO_REPARSE_TAG_MISMATCH"; + case 0xC0000278: return "STATUS_IO_REPARSE_DATA_INVALID"; + case 0xC0000279: return "STATUS_IO_REPARSE_TAG_NOT_HANDLED"; + case 0xC0000280: return "STATUS_REPARSE_POINT_NOT_RESOLVED"; + case 0xC0000281: return "STATUS_DIRECTORY_IS_A_REPARSE_POINT"; + case 0xC0000282: return "STATUS_RANGE_LIST_CONFLICT"; + case 0xC0000283: return "STATUS_SOURCE_ELEMENT_EMPTY"; + case 0xC0000284: return "STATUS_DESTINATION_ELEMENT_FULL"; + case 0xC0000285: return "STATUS_ILLEGAL_ELEMENT_ADDRESS"; + case 0xC0000286: return "STATUS_MAGAZINE_NOT_PRESENT"; + case 0xC0000287: return "STATUS_REINITIALIZATION_NEEDED"; + case 0x80000288: return "STATUS_DEVICE_REQUIRES_CLEANING"; + case 0x80000289: return "STATUS_DEVICE_DOOR_OPEN"; + case 0xC000028A: return "STATUS_ENCRYPTION_FAILED"; + case 0xC000028B: return "STATUS_DECRYPTION_FAILED"; + case 0xC000028C: return "STATUS_RANGE_NOT_FOUND"; + case 0xC000028D: return "STATUS_NO_RECOVERY_POLICY"; + case 0xC000028E: return "STATUS_NO_EFS"; + case 0xC000028F: return "STATUS_WRONG_EFS"; + case 0xC0000290: return "STATUS_NO_USER_KEYS"; + case 0xC0000291: return "STATUS_FILE_NOT_ENCRYPTED"; + case 0xC0000292: return "STATUS_NOT_EXPORT_FORMAT"; + case 0xC0000293: return "STATUS_FILE_ENCRYPTED"; + case 0x40000294: return "STATUS_WAKE_SYSTEM"; + case 0xC0000295: return "STATUS_WMI_GUID_NOT_FOUND"; + case 0xC0000296: return "STATUS_WMI_INSTANCE_NOT_FOUND"; + case 0xC0000297: return "STATUS_WMI_ITEMID_NOT_FOUND"; + case 0xC0000298: return "STATUS_WMI_TRY_AGAIN"; + case 0xC0000299: return "STATUS_SHARED_POLICY"; + case 0xC000029A: return "STATUS_POLICY_OBJECT_NOT_FOUND"; + case 0xC000029B: return "STATUS_POLICY_ONLY_IN_DS"; + case 0xC000029C: return "STATUS_VOLUME_NOT_UPGRADED"; + case 0xC000029D: return "STATUS_REMOTE_STORAGE_NOT_ACTIVE"; + case 0xC000029E: return "STATUS_REMOTE_STORAGE_MEDIA_ERROR"; + case 0xC000029F: return "STATUS_NO_TRACKING_SERVICE"; + case 0xC00002A0: return "STATUS_SERVER_SID_MISMATCH"; + case 0xC00002A1: return "STATUS_DS_NO_ATTRIBUTE_OR_VALUE"; + case 0xC00002A2: return "STATUS_DS_INVALID_ATTRIBUTE_SYNTAX"; + case 0xC00002A3: return "STATUS_DS_ATTRIBUTE_TYPE_UNDEFINED"; + case 0xC00002A4: return "STATUS_DS_ATTRIBUTE_OR_VALUE_EXISTS"; + case 0xC00002A5: return "STATUS_DS_BUSY"; + case 0xC00002A6: return "STATUS_DS_UNAVAILABLE"; + case 0xC00002A7: return "STATUS_DS_NO_RIDS_ALLOCATED"; + case 0xC00002A8: return "STATUS_DS_NO_MORE_RIDS"; + case 0xC00002A9: return "STATUS_DS_INCORRECT_ROLE_OWNER"; + case 0xC00002AA: return "STATUS_DS_RIDMGR_INIT_ERROR"; + case 0xC00002AB: return "STATUS_DS_OBJ_CLASS_VIOLATION"; + case 0xC00002AC: return "STATUS_DS_CANT_ON_NON_LEAF"; + case 0xC00002AD: return "STATUS_DS_CANT_ON_RDN"; + case 0xC00002AE: return "STATUS_DS_CANT_MOD_OBJ_CLASS"; + case 0xC00002AF: return "STATUS_DS_CROSS_DOM_MOVE_FAILED"; + case 0xC00002B0: return "STATUS_DS_GC_NOT_AVAILABLE"; + case 0xC00002B1: return "STATUS_DIRECTORY_SERVICE_REQUIRED"; + case 0xC00002B2: return "STATUS_REPARSE_ATTRIBUTE_CONFLICT"; + case 0xC00002B3: return "STATUS_CANT_ENABLE_DENY_ONLY"; + case 0xC00002B4: return "STATUS_FLOAT_MULTIPLE_FAULTS"; + case 0xC00002B5: return "STATUS_FLOAT_MULTIPLE_TRAPS"; + case 0xC00002B6: return "STATUS_DEVICE_REMOVED"; + case 0xC00002B7: return "STATUS_JOURNAL_DELETE_IN_PROGRESS"; + case 0xC00002B8: return "STATUS_JOURNAL_NOT_ACTIVE"; + case 0xC00002B9: return "STATUS_NOINTERFACE"; + case 0xC00002C1: return "STATUS_DS_ADMIN_LIMIT_EXCEEDED"; + case 0xC00002C2: return "STATUS_DRIVER_FAILED_SLEEP"; + case 0xC00002C3: return "STATUS_MUTUAL_AUTHENTICATION_FAILED"; + case 0xC00002C4: return "STATUS_CORRUPT_SYSTEM_FILE"; + case 0xC00002C5: return "STATUS_DATATYPE_MISALIGNMENT_ERROR"; + case 0xC00002C6: return "STATUS_WMI_READ_ONLY"; + case 0xC00002C7: return "STATUS_WMI_SET_FAILURE"; + case 0xC00002C8: return "STATUS_COMMITMENT_MINIMUM"; + case 0xC00002C9: return "STATUS_REG_NAT_CONSUMPTION"; + case 0xC00002CA: return "STATUS_TRANSPORT_FULL"; + case 0xC00002CB: return "STATUS_DS_SAM_INIT_FAILURE"; + case 0xC00002CC: return "STATUS_ONLY_IF_CONNECTED"; + case 0xC00002CD: return "STATUS_DS_SENSITIVE_GROUP_VIOLATION"; + case 0xC00002CE: return "STATUS_PNP_RESTART_ENUMERATION"; + case 0xC00002CF: return "STATUS_JOURNAL_ENTRY_DELETED"; + case 0xC00002D0: return "STATUS_DS_CANT_MOD_PRIMARYGROUPID"; + case 0xC00002D1: return "STATUS_SYSTEM_IMAGE_BAD_SIGNATURE"; + case 0xC00002D2: return "STATUS_PNP_REBOOT_REQUIRED"; + case 0xC00002D3: return "STATUS_POWER_STATE_INVALID"; + case 0xC00002D4: return "STATUS_DS_INVALID_GROUP_TYPE"; + case 0xC00002D5: return "STATUS_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN"; + case 0xC00002D6: return "STATUS_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN"; + case 0xC00002D7: return "STATUS_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER"; + case 0xC00002D8: return "STATUS_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER"; + case 0xC00002D9: return "STATUS_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER"; + case 0xC00002DA: return "STATUS_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER"; + case 0xC00002DB: return "STATUS_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER"; + case 0xC00002DC: return "STATUS_DS_HAVE_PRIMARY_MEMBERS"; + case 0xC00002DD: return "STATUS_WMI_NOT_SUPPORTED"; + case 0xC00002DE: return "STATUS_INSUFFICIENT_POWER"; + case 0xC00002DF: return "STATUS_SAM_NEED_BOOTKEY_PASSWORD"; + case 0xC00002E0: return "STATUS_SAM_NEED_BOOTKEY_FLOPPY"; + case 0xC00002E1: return "STATUS_DS_CANT_START"; + case 0xC00002E2: return "STATUS_DS_INIT_FAILURE"; + case 0xC00002E3: return "STATUS_SAM_INIT_FAILURE"; + case 0xC00002E4: return "STATUS_DS_GC_REQUIRED"; + case 0xC00002E5: return "STATUS_DS_LOCAL_MEMBER_OF_LOCAL_ONLY"; + case 0xC00002E6: return "STATUS_DS_NO_FPO_IN_UNIVERSAL_GROUPS"; + case 0xC00002E7: return "STATUS_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED"; + case 0xC00002E8: return "STATUS_MULTIPLE_FAULT_VIOLATION"; + case 0xC0000300: return "STATUS_NOT_SUPPORTED_ON_SBS"; + case 0xC0009898: return "STATUS_WOW_ASSERTION"; + case 0xC0010001: return "DBG_NO_STATE_CHANGE"; + case 0xC0010002: return "DBG_APP_NOT_IDLE"; + case 0xC0020001: return "RPC_NT_INVALID_STRING_BINDING"; + case 0xC0020002: return "RPC_NT_WRONG_KIND_OF_BINDING"; + case 0xC0020003: return "RPC_NT_INVALID_BINDING"; + case 0xC0020004: return "RPC_NT_PROTSEQ_NOT_SUPPORTED"; + case 0xC0020005: return "RPC_NT_INVALID_RPC_PROTSEQ"; + case 0xC0020006: return "RPC_NT_INVALID_STRING_UUID"; + case 0xC0020007: return "RPC_NT_INVALID_ENDPOINT_FORMAT"; + case 0xC0020008: return "RPC_NT_INVALID_NET_ADDR"; + case 0xC0020009: return "RPC_NT_NO_ENDPOINT_FOUND"; + case 0xC002000A: return "RPC_NT_INVALID_TIMEOUT"; + case 0xC002000B: return "RPC_NT_OBJECT_NOT_FOUND"; + case 0xC002000C: return "RPC_NT_ALREADY_REGISTERED"; + case 0xC002000D: return "RPC_NT_TYPE_ALREADY_REGISTERED"; + case 0xC002000E: return "RPC_NT_ALREADY_LISTENING"; + case 0xC002000F: return "RPC_NT_NO_PROTSEQS_REGISTERED"; + case 0xC0020010: return "RPC_NT_NOT_LISTENING"; + case 0xC0020011: return "RPC_NT_UNKNOWN_MGR_TYPE"; + case 0xC0020012: return "RPC_NT_UNKNOWN_IF"; + case 0xC0020013: return "RPC_NT_NO_BINDINGS"; + case 0xC0020014: return "RPC_NT_NO_PROTSEQS"; + case 0xC0020015: return "RPC_NT_CANT_CREATE_ENDPOINT"; + case 0xC0020016: return "RPC_NT_OUT_OF_RESOURCES"; + case 0xC0020017: return "RPC_NT_SERVER_UNAVAILABLE"; + case 0xC0020018: return "RPC_NT_SERVER_TOO_BUSY"; + case 0xC0020019: return "RPC_NT_INVALID_NETWORK_OPTIONS"; + case 0xC002001A: return "RPC_NT_NO_CALL_ACTIVE"; + case 0xC002001B: return "RPC_NT_CALL_FAILED"; + case 0xC002001C: return "RPC_NT_CALL_FAILED_DNE"; + case 0xC002001D: return "RPC_NT_PROTOCOL_ERROR"; + case 0xC002001F: return "RPC_NT_UNSUPPORTED_TRANS_SYN"; + case 0xC0020021: return "RPC_NT_UNSUPPORTED_TYPE"; + case 0xC0020022: return "RPC_NT_INVALID_TAG"; + case 0xC0020023: return "RPC_NT_INVALID_BOUND"; + case 0xC0020024: return "RPC_NT_NO_ENTRY_NAME"; + case 0xC0020025: return "RPC_NT_INVALID_NAME_SYNTAX"; + case 0xC0020026: return "RPC_NT_UNSUPPORTED_NAME_SYNTAX"; + case 0xC0020028: return "RPC_NT_UUID_NO_ADDRESS"; + case 0xC0020029: return "RPC_NT_DUPLICATE_ENDPOINT"; + case 0xC002002A: return "RPC_NT_UNKNOWN_AUTHN_TYPE"; + case 0xC002002B: return "RPC_NT_MAX_CALLS_TOO_SMALL"; + case 0xC002002C: return "RPC_NT_STRING_TOO_LONG"; + case 0xC002002D: return "RPC_NT_PROTSEQ_NOT_FOUND"; + case 0xC002002E: return "RPC_NT_PROCNUM_OUT_OF_RANGE"; + case 0xC002002F: return "RPC_NT_BINDING_HAS_NO_AUTH"; + case 0xC0020030: return "RPC_NT_UNKNOWN_AUTHN_SERVICE"; + case 0xC0020031: return "RPC_NT_UNKNOWN_AUTHN_LEVEL"; + case 0xC0020032: return "RPC_NT_INVALID_AUTH_IDENTITY"; + case 0xC0020033: return "RPC_NT_UNKNOWN_AUTHZ_SERVICE"; + case 0xC0020034: return "EPT_NT_INVALID_ENTRY"; + case 0xC0020035: return "EPT_NT_CANT_PERFORM_OP"; + case 0xC0020036: return "EPT_NT_NOT_REGISTERED"; + case 0xC0020037: return "RPC_NT_NOTHING_TO_EXPORT"; + case 0xC0020038: return "RPC_NT_INCOMPLETE_NAME"; + case 0xC0020039: return "RPC_NT_INVALID_VERS_OPTION"; + case 0xC002003A: return "RPC_NT_NO_MORE_MEMBERS"; + case 0xC002003B: return "RPC_NT_NOT_ALL_OBJS_UNEXPORTED"; + case 0xC002003C: return "RPC_NT_INTERFACE_NOT_FOUND"; + case 0xC002003D: return "RPC_NT_ENTRY_ALREADY_EXISTS"; + case 0xC002003E: return "RPC_NT_ENTRY_NOT_FOUND"; + case 0xC002003F: return "RPC_NT_NAME_SERVICE_UNAVAILABLE"; + case 0xC0020040: return "RPC_NT_INVALID_NAF_ID"; + case 0xC0020041: return "RPC_NT_CANNOT_SUPPORT"; + case 0xC0020042: return "RPC_NT_NO_CONTEXT_AVAILABLE"; + case 0xC0020043: return "RPC_NT_INTERNAL_ERROR"; + case 0xC0020044: return "RPC_NT_ZERO_DIVIDE"; + case 0xC0020045: return "RPC_NT_ADDRESS_ERROR"; + case 0xC0020046: return "RPC_NT_FP_DIV_ZERO"; + case 0xC0020047: return "RPC_NT_FP_UNDERFLOW"; + case 0xC0020048: return "RPC_NT_FP_OVERFLOW"; + case 0xC0030001: return "RPC_NT_NO_MORE_ENTRIES"; + case 0xC0030002: return "RPC_NT_SS_CHAR_TRANS_OPEN_FAIL"; + case 0xC0030003: return "RPC_NT_SS_CHAR_TRANS_SHORT_FILE"; + case 0xC0030004: return "RPC_NT_SS_IN_NULL_CONTEXT"; + case 0xC0030005: return "RPC_NT_SS_CONTEXT_MISMATCH"; + case 0xC0030006: return "RPC_NT_SS_CONTEXT_DAMAGED"; + case 0xC0030007: return "RPC_NT_SS_HANDLES_MISMATCH"; + case 0xC0030008: return "RPC_NT_SS_CANNOT_GET_CALL_HANDLE"; + case 0xC0030009: return "RPC_NT_NULL_REF_POINTER"; + case 0xC003000A: return "RPC_NT_ENUM_VALUE_OUT_OF_RANGE"; + case 0xC003000B: return "RPC_NT_BYTE_COUNT_TOO_SMALL"; + case 0xC003000C: return "RPC_NT_BAD_STUB_DATA"; + case 0xC0020049: return "RPC_NT_CALL_IN_PROGRESS"; + case 0xC002004A: return "RPC_NT_NO_MORE_BINDINGS"; + case 0xC002004B: return "RPC_NT_GROUP_MEMBER_NOT_FOUND"; + case 0xC002004C: return "EPT_NT_CANT_CREATE"; + case 0xC002004D: return "RPC_NT_INVALID_OBJECT"; + case 0xC002004F: return "RPC_NT_NO_INTERFACES"; + case 0xC0020050: return "RPC_NT_CALL_CANCELLED"; + case 0xC0020051: return "RPC_NT_BINDING_INCOMPLETE"; + case 0xC0020052: return "RPC_NT_COMM_FAILURE"; + case 0xC0020053: return "RPC_NT_UNSUPPORTED_AUTHN_LEVEL"; + case 0xC0020054: return "RPC_NT_NO_PRINC_NAME"; + case 0xC0020055: return "RPC_NT_NOT_RPC_ERROR"; + case 0x40020056: return "RPC_NT_UUID_LOCAL_ONLY"; + case 0xC0020057: return "RPC_NT_SEC_PKG_ERROR"; + case 0xC0020058: return "RPC_NT_NOT_CANCELLED"; + case 0xC0030059: return "RPC_NT_INVALID_ES_ACTION"; + case 0xC003005A: return "RPC_NT_WRONG_ES_VERSION"; + case 0xC003005B: return "RPC_NT_WRONG_STUB_VERSION"; + case 0xC003005C: return "RPC_NT_INVALID_PIPE_OBJECT"; + case 0xC003005D: return "RPC_NT_INVALID_PIPE_OPERATION"; + case 0xC003005E: return "RPC_NT_WRONG_PIPE_VERSION"; + case 0xC003005F: return "RPC_NT_PIPE_CLOSED"; + case 0xC0030060: return "RPC_NT_PIPE_DISCIPLINE_ERROR"; + case 0xC0030061: return "RPC_NT_PIPE_EMPTY"; + case 0xC0020062: return "RPC_NT_INVALID_ASYNC_HANDLE"; + case 0xC0020063: return "RPC_NT_INVALID_ASYNC_CALL"; + case 0x400200AF: return "RPC_NT_SEND_INCOMPLETE"; + case 0xC0140001: return "STATUS_ACPI_INVALID_OPCODE"; + case 0xC0140002: return "STATUS_ACPI_STACK_OVERFLOW"; + case 0xC0140003: return "STATUS_ACPI_ASSERT_FAILED"; + case 0xC0140004: return "STATUS_ACPI_INVALID_INDEX"; + case 0xC0140005: return "STATUS_ACPI_INVALID_ARGUMENT"; + case 0xC0140006: return "STATUS_ACPI_FATAL"; + case 0xC0140007: return "STATUS_ACPI_INVALID_SUPERNAME"; + case 0xC0140008: return "STATUS_ACPI_INVALID_ARGTYPE"; + case 0xC0140009: return "STATUS_ACPI_INVALID_OBJTYPE"; + case 0xC014000A: return "STATUS_ACPI_INVALID_TARGETTYPE"; + case 0xC014000B: return "STATUS_ACPI_INCORRECT_ARGUMENT_COUNT"; + case 0xC014000C: return "STATUS_ACPI_ADDRESS_NOT_MAPPED"; + case 0xC014000D: return "STATUS_ACPI_INVALID_EVENTTYPE"; + case 0xC014000E: return "STATUS_ACPI_HANDLER_COLLISION"; + case 0xC014000F: return "STATUS_ACPI_INVALID_DATA"; + case 0xC0140010: return "STATUS_ACPI_INVALID_REGION"; + case 0xC0140011: return "STATUS_ACPI_INVALID_ACCESS_SIZE"; + case 0xC0140012: return "STATUS_ACPI_ACQUIRE_GLOBAL_LOCK"; + case 0xC0140013: return "STATUS_ACPI_ALREADY_INITIALIZED"; + case 0xC0140014: return "STATUS_ACPI_NOT_INITIALIZED"; + case 0xC0140015: return "STATUS_ACPI_INVALID_MUTEX_LEVEL"; + case 0xC0140016: return "STATUS_ACPI_MUTEX_NOT_OWNED"; + case 0xC0140017: return "STATUS_ACPI_MUTEX_NOT_OWNER"; + case 0xC0140018: return "STATUS_ACPI_RS_ACCESS"; + case 0xC0140019: return "STATUS_ACPI_INVALID_TABLE"; + case 0xC0140020: return "STATUS_ACPI_REG_HANDLER_FAILED"; + case 0xC0140021: return "STATUS_ACPI_POWER_REQUEST_FAILED"; + case 0xC00A0001: return "STATUS_CTX_WINSTATION_NAME_INVALID"; + case 0xC00A0002: return "STATUS_CTX_INVALID_PD"; + case 0xC00A0003: return "STATUS_CTX_PD_NOT_FOUND"; + case 0x400A0004: return "STATUS_CTX_CDM_CONNECT"; + case 0x400A0005: return "STATUS_CTX_CDM_DISCONNECT"; + case 0xC00A0006: return "STATUS_CTX_CLOSE_PENDING"; + case 0xC00A0007: return "STATUS_CTX_NO_OUTBUF"; + case 0xC00A0008: return "STATUS_CTX_MODEM_INF_NOT_FOUND"; + case 0xC00A0009: return "STATUS_CTX_INVALID_MODEMNAME"; + case 0xC00A000A: return "STATUS_CTX_RESPONSE_ERROR"; + case 0xC00A000B: return "STATUS_CTX_MODEM_RESPONSE_TIMEOUT"; + case 0xC00A000C: return "STATUS_CTX_MODEM_RESPONSE_NO_CARRIER"; + case 0xC00A000D: return "STATUS_CTX_MODEM_RESPONSE_NO_DIALTONE"; + case 0xC00A000E: return "STATUS_CTX_MODEM_RESPONSE_BUSY"; + case 0xC00A000F: return "STATUS_CTX_MODEM_RESPONSE_VOICE"; + case 0xC00A0010: return "STATUS_CTX_TD_ERROR"; + case 0xC00A0012: return "STATUS_CTX_LICENSE_CLIENT_INVALID"; + case 0xC00A0013: return "STATUS_CTX_LICENSE_NOT_AVAILABLE"; + case 0xC00A0014: return "STATUS_CTX_LICENSE_EXPIRED"; + case 0xC00A0015: return "STATUS_CTX_WINSTATION_NOT_FOUND"; + case 0xC00A0016: return "STATUS_CTX_WINSTATION_NAME_COLLISION"; + case 0xC00A0017: return "STATUS_CTX_WINSTATION_BUSY"; + case 0xC00A0018: return "STATUS_CTX_BAD_VIDEO_MODE"; + case 0xC00A0022: return "STATUS_CTX_GRAPHICS_INVALID"; + case 0xC00A0024: return "STATUS_CTX_NOT_CONSOLE"; + case 0xC00A0026: return "STATUS_CTX_CLIENT_QUERY_TIMEOUT"; + case 0xC00A0027: return "STATUS_CTX_CONSOLE_DISCONNECT"; + case 0xC00A0028: return "STATUS_CTX_CONSOLE_CONNECT"; + case 0xC00A002A: return "STATUS_CTX_SHADOW_DENIED"; + case 0xC00A002B: return "STATUS_CTX_WINSTATION_ACCESS_DENIED"; + case 0xC00A002E: return "STATUS_CTX_INVALID_WD"; + case 0xC00A002F: return "STATUS_CTX_WD_NOT_FOUND"; + case 0xC00A0030: return "STATUS_CTX_SHADOW_INVALID"; + case 0xC00A0031: return "STATUS_CTX_SHADOW_DISABLED"; + case 0xC00A0032: return "STATUS_RDP_PROTOCOL_ERROR"; + case 0xC00A0033: return "STATUS_CTX_CLIENT_LICENSE_NOT_SET"; + case 0xC00A0034: return "STATUS_CTX_CLIENT_LICENSE_IN_USE"; + case 0xC0040035: return "STATUS_PNP_BAD_MPS_TABLE"; + case 0xC0040036: return "STATUS_PNP_TRANSLATION_FAILED"; + case 0xC0040037: return "STATUS_PNP_IRQ_TRANSLATION_FAILED"; + default: return "STATUS_UNKNOWN"; + } +} + +#endif // DBG diff --git a/reactos/drivers/filesystems/ffs/src/devctl.c b/reactos/drivers/filesystems/ffs/src/devctl.c new file mode 100644 index 00000000000..140e34a22dc --- /dev/null +++ b/reactos/drivers/filesystems/ffs/src/devctl.c @@ -0,0 +1,302 @@ +/* + * FFS File System Driver for Windows + * + * devctl.c + * + * 2004.5.6 ~ + * + * Lee Jae-Hong, http://www.pyrasis.com + * + * See License.txt + * + */ + +#include "ntifs.h" +#include "ffsdrv.h" + +/* Globals */ + +extern PFFS_GLOBAL FFSGlobal; + + +/* Definitions */ + +#ifdef _PREFAST_ +IO_COMPLETION_ROUTINE FFSDeviceControlCompletion; +#endif // _PREFAST_ + +NTSTATUS NTAPI +FFSDeviceControlCompletion( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID Context); + + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE, FFSDeviceControl) +#pragma alloc_text(PAGE, FFSDeviceControlNormal) +#if FFS_UNLOAD +#pragma alloc_text(PAGE, FFSPrepareToUnload) +#endif +#endif + + +NTSTATUS NTAPI +FFSDeviceControlCompletion( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID Context) +{ + if (Irp->PendingReturned) + { + IoMarkIrpPending(Irp); + } + + return STATUS_SUCCESS; +} + + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSDeviceControlNormal( + IN PFFS_IRP_CONTEXT IrpContext) +{ + PDEVICE_OBJECT DeviceObject; + BOOLEAN CompleteRequest = TRUE; + NTSTATUS Status = STATUS_UNSUCCESSFUL; + + PFFS_VCB Vcb; + + PIRP Irp; + PIO_STACK_LOCATION IrpSp; + PIO_STACK_LOCATION NextIrpSp; + + PDEVICE_OBJECT TargetDeviceObject; + + PAGED_CODE(); + + _SEH2_TRY + { + ASSERT(IrpContext != NULL); + + ASSERT((IrpContext->Identifier.Type == FFSICX) && + (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); + + CompleteRequest = TRUE; + + DeviceObject = IrpContext->DeviceObject; + + if (DeviceObject == FFSGlobal->DeviceObject) + { + Status = STATUS_INVALID_DEVICE_REQUEST; + + _SEH2_LEAVE; + } + + Irp = IrpContext->Irp; + IrpSp = IoGetCurrentIrpStackLocation(Irp); + + Vcb = (PFFS_VCB)IrpSp->FileObject->FsContext; + + if (!((Vcb) && (Vcb->Identifier.Type == FFSVCB) && + (Vcb->Identifier.Size == sizeof(FFS_VCB)) + ) + ) + { + Status = STATUS_INVALID_PARAMETER; + _SEH2_LEAVE; + } + + TargetDeviceObject = Vcb->TargetDeviceObject; + + // + // Pass on the IOCTL to the driver below + // + + CompleteRequest = FALSE; + + NextIrpSp = IoGetNextIrpStackLocation(Irp); + *NextIrpSp = *IrpSp; + + IoSetCompletionRoutine( + Irp, + FFSDeviceControlCompletion, + NULL, + FALSE, + TRUE, + TRUE); + + Status = IoCallDriver(TargetDeviceObject, Irp); + } + + _SEH2_FINALLY + { + if (!IrpContext->ExceptionInProgress) + { + if (IrpContext) + { + if (!CompleteRequest) + { + IrpContext->Irp = NULL; + } + + FFSCompleteIrpContext(IrpContext, Status); + } + } + } _SEH2_END; + + return Status; +} + + +#if FFS_UNLOAD + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSPrepareToUnload( + IN PFFS_IRP_CONTEXT IrpContext) +{ + PDEVICE_OBJECT DeviceObject; + NTSTATUS Status = STATUS_UNSUCCESSFUL; + BOOLEAN GlobalDataResourceAcquired = FALSE; + + PAGED_CODE(); + + _SEH2_TRY + { + ASSERT(IrpContext != NULL); + + ASSERT((IrpContext->Identifier.Type == FFSICX) && + (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); + + DeviceObject = IrpContext->DeviceObject; + + if (DeviceObject != FFSGlobal->DeviceObject) + { + Status = STATUS_INVALID_DEVICE_REQUEST; + _SEH2_LEAVE; + } + + ExAcquireResourceExclusiveLite( + &FFSGlobal->Resource, + TRUE); + + GlobalDataResourceAcquired = TRUE; + + if (FlagOn(FFSGlobal->Flags, FFS_UNLOAD_PENDING)) + { + FFSPrint((DBG_ERROR, "FFSPrepareUnload: Already ready to unload.\n")); + + Status = STATUS_ACCESS_DENIED; + + _SEH2_LEAVE; + } + + { + PFFS_VCB Vcb; + PLIST_ENTRY ListEntry; + + ListEntry = FFSGlobal->VcbList.Flink; + + while (ListEntry != &(FFSGlobal->VcbList)) + { + Vcb = CONTAINING_RECORD(ListEntry, FFS_VCB, Next); + ListEntry = ListEntry->Flink; + + if (Vcb && (!Vcb->ReferenceCount) && + IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING)) + { + FFSRemoveVcb(Vcb); + FFSClearVpbFlag(Vcb->Vpb, VPB_MOUNTED); + + FFSFreeVcb(Vcb); + } + } + } + + if (!IsListEmpty(&(FFSGlobal->VcbList))) + { + + FFSPrint((DBG_ERROR, "FFSPrepareUnload: Mounted volumes exists.\n")); + + Status = STATUS_ACCESS_DENIED; + + _SEH2_LEAVE; + } + + IoUnregisterFileSystem(FFSGlobal->DeviceObject); + +#ifdef _MSC_VER +#pragma prefast( suppress: 28175, "allowed to unload" ) +#endif + FFSGlobal->DriverObject->DriverUnload = DriverUnload; + + SetFlag(FFSGlobal->Flags, FFS_UNLOAD_PENDING); + + FFSPrint((DBG_INFO, "FFSPrepareToUnload: Driver is ready to unload.\n")); + + Status = STATUS_SUCCESS; + } + _SEH2_FINALLY + { + if (GlobalDataResourceAcquired) + { + ExReleaseResourceForThreadLite( + &FFSGlobal->Resource, + ExGetCurrentResourceThread()); + } + + if (!IrpContext->ExceptionInProgress) + { + FFSCompleteIrpContext(IrpContext, Status); + } + } _SEH2_END; + + return Status; +} + +#endif + + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSDeviceControl( + IN PFFS_IRP_CONTEXT IrpContext) +{ + PIRP Irp; + PIO_STACK_LOCATION IoStackLocation; + ULONG IoControlCode; + NTSTATUS Status; + + PAGED_CODE(); + + ASSERT(IrpContext); + + ASSERT((IrpContext->Identifier.Type == FFSICX) && + (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); + + Irp = IrpContext->Irp; + + IoStackLocation = IoGetCurrentIrpStackLocation(Irp); + + IoControlCode = + IoStackLocation->Parameters.DeviceIoControl.IoControlCode; + + switch (IoControlCode) + { +#if FFS_UNLOAD + case IOCTL_PREPARE_TO_UNLOAD: + Status = FFSPrepareToUnload(IrpContext); + break; +#endif + + case IOCTL_SELECT_BSD_PARTITION: + Status = FFSSelectBSDPartition(IrpContext); + break; + + default: + Status = FFSDeviceControlNormal(IrpContext); + } + + return Status; +} diff --git a/reactos/drivers/filesystems/ffs/src/dirctl.c b/reactos/drivers/filesystems/ffs/src/dirctl.c new file mode 100644 index 00000000000..6db9b4bc3cd --- /dev/null +++ b/reactos/drivers/filesystems/ffs/src/dirctl.c @@ -0,0 +1,1372 @@ +/* + * FFS File System Driver for Windows + * + * dirctl.c + * + * 2004.5.6 ~ + * + * Lee Jae-Hong, http://www.pyrasis.com + * + * See License.txt + * + */ + +#include "ntifs.h" +#include "ffsdrv.h" + +/* Globals */ + +extern PFFS_GLOBAL FFSGlobal; + + +/* Definitions */ + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE, FFSGetInfoLength) +#pragma alloc_text(PAGE, FFSProcessDirEntry) +#pragma alloc_text(PAGE, FFSQueryDirectory) +#pragma alloc_text(PAGE, FFSNotifyChangeDirectory) +#pragma alloc_text(PAGE, FFSDirectoryControl) +#pragma alloc_text(PAGE, FFSIsDirectoryEmpty) +#endif + +ULONG +FFSGetInfoLength( + IN FILE_INFORMATION_CLASS FileInformationClass) +{ + PAGED_CODE(); + + switch (FileInformationClass) + { + case FileDirectoryInformation: + return sizeof(FILE_DIRECTORY_INFORMATION); + break; + + case FileFullDirectoryInformation: + return sizeof(FILE_FULL_DIR_INFORMATION); + break; + + case FileBothDirectoryInformation: + return sizeof(FILE_BOTH_DIR_INFORMATION); + break; + + case FileNamesInformation: + return sizeof(FILE_NAMES_INFORMATION); + break; + + default: + break; + } + + return 0; +} + + +ULONG +FFSProcessDirEntry( + IN PFFS_VCB Vcb, + IN FILE_INFORMATION_CLASS FileInformationClass, + IN ULONG in, + IN PVOID Buffer, + IN ULONG UsedLength, + IN ULONG Length, + IN ULONG FileIndex, + IN PUNICODE_STRING pName, + IN BOOLEAN Single) +{ + FFSv1_INODE dinode1; + FFSv2_INODE dinode2; + PFILE_DIRECTORY_INFORMATION FDI; + PFILE_FULL_DIR_INFORMATION FFI; + PFILE_BOTH_DIR_INFORMATION FBI; + PFILE_NAMES_INFORMATION FNI; + + ULONG InfoLength = 0; + ULONG NameLength = 0; + ULONG dwBytes = 0; + + PAGED_CODE(); + + NameLength = pName->Length; + + if (!in) + { + FFSPrint((DBG_ERROR, "FFSPricessDirEntry: ffs_dir_entry is empty.\n")); + return 0; + } + + InfoLength = FFSGetInfoLength(FileInformationClass); + + if (!InfoLength || InfoLength + NameLength - sizeof(WCHAR) > Length) + { + FFSPrint((DBG_INFO, "FFSPricessDirEntry: Buffer is not enough.\n")); + return 0; + } + + if (FS_VERSION == 1) + { + if(!FFSv1LoadInode(Vcb, in, &dinode1)) + { + FFSPrint((DBG_ERROR, "FFSPricessDirEntry: Loading inode %xh error.\n", in)); + + FFSBreakPoint(); + + return 0; + } + } + else + { + if(!FFSv2LoadInode(Vcb, in, &dinode2)) + { + FFSPrint((DBG_ERROR, "FFSPricessDirEntry: Loading inode %xh error.\n", in)); + + FFSBreakPoint(); + + return 0; + } + } + + switch(FileInformationClass) + { + case FileDirectoryInformation: + FDI = (PFILE_DIRECTORY_INFORMATION) ((PUCHAR)Buffer + UsedLength); + if (!Single) + FDI->NextEntryOffset = InfoLength + NameLength - sizeof(WCHAR); + else + FDI->NextEntryOffset = 0; + FDI->FileIndex = FileIndex; + + if (FS_VERSION == 1) + { + FDI->CreationTime = FFSSysTime(dinode1.di_ctime); + FDI->LastAccessTime = FFSSysTime(dinode1.di_atime); + FDI->LastWriteTime = FFSSysTime(dinode1.di_mtime); + FDI->ChangeTime = FFSSysTime(dinode1.di_mtime); + FDI->EndOfFile.QuadPart = dinode1.di_size; + FDI->AllocationSize.QuadPart = dinode1.di_size; + FDI->FileAttributes = FILE_ATTRIBUTE_NORMAL; + + if (FlagOn(Vcb->Flags, VCB_READ_ONLY) || FFSIsReadOnly(dinode1.di_mode)) + { + SetFlag(FDI->FileAttributes, FILE_ATTRIBUTE_READONLY); + } + + if ((dinode1.di_mode & IFMT) == IFDIR) + FDI->FileAttributes |= FILE_ATTRIBUTE_DIRECTORY; + + FDI->FileNameLength = NameLength; + RtlCopyMemory(FDI->FileName, pName->Buffer, NameLength); + dwBytes = InfoLength + NameLength - sizeof(WCHAR); + break; + } + else + { + FDI->CreationTime = FFSSysTime((ULONG)dinode2.di_ctime); + FDI->LastAccessTime = FFSSysTime((ULONG)dinode2.di_atime); + FDI->LastWriteTime = FFSSysTime((ULONG)dinode2.di_mtime); + FDI->ChangeTime = FFSSysTime((ULONG)dinode2.di_mtime); + FDI->EndOfFile.QuadPart = dinode2.di_size; + FDI->AllocationSize.QuadPart = dinode2.di_size; + FDI->FileAttributes = FILE_ATTRIBUTE_NORMAL; + + if (FlagOn(Vcb->Flags, VCB_READ_ONLY) || FFSIsReadOnly(dinode2.di_mode)) + { + SetFlag(FDI->FileAttributes, FILE_ATTRIBUTE_READONLY); + } + + if ((dinode2.di_mode & IFMT) == IFDIR) + FDI->FileAttributes |= FILE_ATTRIBUTE_DIRECTORY; + + FDI->FileNameLength = NameLength; + RtlCopyMemory(FDI->FileName, pName->Buffer, NameLength); + dwBytes = InfoLength + NameLength - sizeof(WCHAR); + break; + } + + case FileFullDirectoryInformation: + FFI = (PFILE_FULL_DIR_INFORMATION) ((PUCHAR)Buffer + UsedLength); + if (!Single) + FFI->NextEntryOffset = InfoLength + NameLength - sizeof(WCHAR); + else + FFI->NextEntryOffset = 0; + FFI->FileIndex = FileIndex; + + if (FS_VERSION == 1) + { + FFI->CreationTime = FFSSysTime(dinode1.di_ctime); + FFI->LastAccessTime = FFSSysTime(dinode1.di_atime); + FFI->LastWriteTime = FFSSysTime(dinode1.di_mtime); + FFI->ChangeTime = FFSSysTime(dinode1.di_mtime); + FFI->EndOfFile.QuadPart = dinode1.di_size; + FFI->AllocationSize.QuadPart = dinode1.di_size; + FFI->FileAttributes = FILE_ATTRIBUTE_NORMAL; + + if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY) || FFSIsReadOnly(dinode1.di_mode)) + { + SetFlag(FFI->FileAttributes, FILE_ATTRIBUTE_READONLY); + } + + if ((dinode1.di_mode & IFMT) == IFDIR) + FFI->FileAttributes |= FILE_ATTRIBUTE_DIRECTORY; + + FFI->FileNameLength = NameLength; + RtlCopyMemory(FFI->FileName, pName->Buffer, NameLength); + dwBytes = InfoLength + NameLength - sizeof(WCHAR); + + break; + } + else + { + FFI->CreationTime = FFSSysTime((ULONG)dinode2.di_ctime); + FFI->LastAccessTime = FFSSysTime((ULONG)dinode2.di_atime); + FFI->LastWriteTime = FFSSysTime((ULONG)dinode2.di_mtime); + FFI->ChangeTime = FFSSysTime((ULONG)dinode2.di_mtime); + FFI->EndOfFile.QuadPart = dinode2.di_size; + FFI->AllocationSize.QuadPart = dinode2.di_size; + FFI->FileAttributes = FILE_ATTRIBUTE_NORMAL; + + if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY) || FFSIsReadOnly(dinode2.di_mode)) + { + SetFlag(FFI->FileAttributes, FILE_ATTRIBUTE_READONLY); + } + + if ((dinode2.di_mode & IFMT) == IFDIR) + FFI->FileAttributes |= FILE_ATTRIBUTE_DIRECTORY; + + FFI->FileNameLength = NameLength; + RtlCopyMemory(FFI->FileName, pName->Buffer, NameLength); + dwBytes = InfoLength + NameLength - sizeof(WCHAR); + + break; + } + + case FileBothDirectoryInformation: + FBI = (PFILE_BOTH_DIR_INFORMATION) ((PUCHAR)Buffer + UsedLength); + if (!Single) + FBI->NextEntryOffset = InfoLength + NameLength - sizeof(WCHAR); + else + FBI->NextEntryOffset = 0; + + if (FS_VERSION == 1) + { + FBI->CreationTime = FFSSysTime(dinode1.di_ctime); + FBI->LastAccessTime = FFSSysTime(dinode1.di_atime); + FBI->LastWriteTime = FFSSysTime(dinode1.di_mtime); + FBI->ChangeTime = FFSSysTime(dinode1.di_mtime); + + FBI->FileIndex = FileIndex; + FBI->EndOfFile.QuadPart = dinode1.di_size; + FBI->AllocationSize.QuadPart = dinode1.di_size; + FBI->FileAttributes = FILE_ATTRIBUTE_NORMAL; + + if (FlagOn(Vcb->Flags, VCB_READ_ONLY) || FFSIsReadOnly(dinode1.di_mode)) + { + SetFlag(FBI->FileAttributes, FILE_ATTRIBUTE_READONLY); + } + + if ((dinode1.di_mode & IFMT) == IFDIR) + FBI->FileAttributes |= FILE_ATTRIBUTE_DIRECTORY; + FBI->FileNameLength = NameLength; + RtlCopyMemory(FBI->FileName, pName->Buffer, NameLength); + dwBytes = InfoLength + NameLength - sizeof(WCHAR); + + break; + } + else + { + FBI->CreationTime = FFSSysTime((ULONG)dinode2.di_ctime); + FBI->LastAccessTime = FFSSysTime((ULONG)dinode2.di_atime); + FBI->LastWriteTime = FFSSysTime((ULONG)dinode2.di_mtime); + FBI->ChangeTime = FFSSysTime((ULONG)dinode2.di_mtime); + + FBI->FileIndex = FileIndex; + FBI->EndOfFile.QuadPart = dinode2.di_size; + FBI->AllocationSize.QuadPart = dinode2.di_size; + FBI->FileAttributes = FILE_ATTRIBUTE_NORMAL; + + if (FlagOn(Vcb->Flags, VCB_READ_ONLY) || FFSIsReadOnly(dinode2.di_mode)) + { + SetFlag(FBI->FileAttributes, FILE_ATTRIBUTE_READONLY); + } + + if ((dinode2.di_mode & IFMT) == IFDIR) + FBI->FileAttributes |= FILE_ATTRIBUTE_DIRECTORY; + FBI->FileNameLength = NameLength; + RtlCopyMemory(FBI->FileName, pName->Buffer, NameLength); + dwBytes = InfoLength + NameLength - sizeof(WCHAR); + + break; + } + + case FileNamesInformation: + FNI = (PFILE_NAMES_INFORMATION) ((PUCHAR)Buffer + UsedLength); + if (!Single) + FNI->NextEntryOffset = InfoLength + NameLength - sizeof(WCHAR); + else + FNI->NextEntryOffset = 0; + FNI->FileNameLength = NameLength; + RtlCopyMemory(FNI->FileName, pName->Buffer, NameLength); + dwBytes = InfoLength + NameLength - sizeof(WCHAR); + + break; + + default: + break; + } + + return dwBytes; +} + + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSQueryDirectory( + IN PFFS_IRP_CONTEXT IrpContext) +{ + PDEVICE_OBJECT DeviceObject; + NTSTATUS Status = STATUS_UNSUCCESSFUL; + PFFS_VCB Vcb = 0; + PFILE_OBJECT FileObject; + PFFS_FCB Fcb = 0; + PFFS_CCB Ccb; + PIRP Irp; + PIO_STACK_LOCATION IoStackLocation; + FILE_INFORMATION_CLASS FileInformationClass; + ULONG Length; + PUNICODE_STRING FileName; + ULONG FileIndex; + BOOLEAN RestartScan; + BOOLEAN ReturnSingleEntry; + BOOLEAN IndexSpecified; + PUCHAR Buffer; + BOOLEAN FirstQuery; + PFFSv1_INODE dinode1 = NULL; + PFFSv2_INODE dinode2 = NULL; + BOOLEAN FcbResourceAcquired = FALSE; + ULONG UsedLength = 0; + USHORT InodeFileNameLength; + UNICODE_STRING InodeFileName; + PFFS_DIR_ENTRY pDir = NULL; + ULONG dwBytes; + ULONG dwTemp = 0; + ULONG dwSize = 0; + ULONG dwReturn = 0; + BOOLEAN bRun = TRUE; + ULONG ByteOffset; + + PAGED_CODE(); + + InodeFileName.Buffer = NULL; + + _SEH2_TRY + { + ASSERT(IrpContext); + + ASSERT((IrpContext->Identifier.Type == FFSICX) && + (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); + + DeviceObject = IrpContext->DeviceObject; + + // + // This request is not allowed on the main device object + // + if (DeviceObject == FFSGlobal->DeviceObject) + { + Status = STATUS_INVALID_DEVICE_REQUEST; + _SEH2_LEAVE; + } + + Vcb = (PFFS_VCB)DeviceObject->DeviceExtension; + + ASSERT(Vcb != NULL); + + ASSERT((Vcb->Identifier.Type == FFSVCB) && + (Vcb->Identifier.Size == sizeof(FFS_VCB))); + + ASSERT(IsMounted(Vcb)); + + FileObject = IrpContext->FileObject; + + Fcb = (PFFS_FCB)FileObject->FsContext; + + ASSERT(Fcb); + + // + // This request is not allowed on volumes + // + if (Fcb->Identifier.Type == FFSVCB) + { + Status = STATUS_INVALID_PARAMETER; + _SEH2_LEAVE; + } + + ASSERT((Fcb->Identifier.Type == FFSFCB) && + (Fcb->Identifier.Size == sizeof(FFS_FCB))); + + if (!IsDirectory(Fcb)) + { + Status = STATUS_INVALID_PARAMETER; + _SEH2_LEAVE; + } + + Ccb = (PFFS_CCB)FileObject->FsContext2; + + ASSERT(Ccb); + + ASSERT((Ccb->Identifier.Type == FFSCCB) && + (Ccb->Identifier.Size == sizeof(FFS_CCB))); + + Irp = IrpContext->Irp; + + IoStackLocation = IoGetCurrentIrpStackLocation(Irp); + +#if !defined(_GNU_NTIFS_) || defined(__REACTOS__) + + FileInformationClass = + IoStackLocation->Parameters.QueryDirectory.FileInformationClass; + + Length = IoStackLocation->Parameters.QueryDirectory.Length; + + FileName = IoStackLocation->Parameters.QueryDirectory.FileName; + + FileIndex = IoStackLocation->Parameters.QueryDirectory.FileIndex; + +#else // _GNU_NTIFS_ + + FileInformationClass = ((PEXTENDED_IO_STACK_LOCATION) + IoStackLocation)->Parameters.QueryDirectory.FileInformationClass; + + Length = ((PEXTENDED_IO_STACK_LOCATION) + IoStackLocation)->Parameters.QueryDirectory.Length; + + FileName = ((PEXTENDED_IO_STACK_LOCATION) + IoStackLocation)->Parameters.QueryDirectory.FileName; + + FileIndex = ((PEXTENDED_IO_STACK_LOCATION) + IoStackLocation)->Parameters.QueryDirectory.FileIndex; + +#endif // _GNU_NTIFS_ + + RestartScan = FlagOn(IoStackLocation->Flags, SL_RESTART_SCAN); + ReturnSingleEntry = FlagOn(IoStackLocation->Flags, SL_RETURN_SINGLE_ENTRY); + IndexSpecified = FlagOn(IoStackLocation->Flags, SL_INDEX_SPECIFIED); + /* + if (!Irp->MdlAddress && Irp->UserBuffer) + { + ProbeForWrite(Irp->UserBuffer, Length, 1); + } + */ + Buffer = FFSGetUserBuffer(Irp); + + if (Buffer == NULL) + { + FFSBreakPoint(); + Status = STATUS_INVALID_USER_BUFFER; + _SEH2_LEAVE; + } + + if (!IrpContext->IsSynchronous) + { + Status = STATUS_PENDING; + _SEH2_LEAVE; + } + + if (!ExAcquireResourceSharedLite( + &Fcb->MainResource, + IrpContext->IsSynchronous)) + { + Status = STATUS_PENDING; + _SEH2_LEAVE; + } + + FcbResourceAcquired = TRUE; + + if (FileName != NULL) + { + if (Ccb->DirectorySearchPattern.Buffer != NULL) + { + FirstQuery = FALSE; + } + else + { + FirstQuery = TRUE; + + Ccb->DirectorySearchPattern.Length = + Ccb->DirectorySearchPattern.MaximumLength = + FileName->Length; + + Ccb->DirectorySearchPattern.Buffer = + ExAllocatePoolWithTag(PagedPool, FileName->Length, FFS_POOL_TAG); + + if (Ccb->DirectorySearchPattern.Buffer == NULL) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + _SEH2_LEAVE; + } + + Status = RtlUpcaseUnicodeString( + &(Ccb->DirectorySearchPattern), + FileName, + FALSE); + + if (!NT_SUCCESS(Status)) + _SEH2_LEAVE; + } + } + else if (Ccb->DirectorySearchPattern.Buffer != NULL) + { + FirstQuery = FALSE; + FileName = &Ccb->DirectorySearchPattern; + } + else + { + FirstQuery = TRUE; + + Ccb->DirectorySearchPattern.Length = + Ccb->DirectorySearchPattern.MaximumLength = 2; + + Ccb->DirectorySearchPattern.Buffer = + ExAllocatePoolWithTag(PagedPool, 2, FFS_POOL_TAG); + + if (Ccb->DirectorySearchPattern.Buffer == NULL) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + _SEH2_LEAVE; + } + + RtlCopyMemory( + Ccb->DirectorySearchPattern.Buffer, + L"*\0", 2); + } + + if (!IndexSpecified) + { + if (RestartScan || FirstQuery) + { + FileIndex = Fcb->FFSMcb->DeOffset = 0; + } + else + { + FileIndex = Ccb->CurrentByteOffset; + } + } + + if (FS_VERSION == 1) + { + dinode1 = (PFFSv1_INODE)ExAllocatePoolWithTag( + PagedPool, + DINODE1_SIZE, FFS_POOL_TAG); + + if (dinode1 == NULL) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + _SEH2_LEAVE; + } + + RtlZeroMemory(Buffer, Length); + + if (Fcb->dinode1->di_size <= FileIndex) + { + Status = STATUS_NO_MORE_FILES; + _SEH2_LEAVE; + } + } + else + { + dinode2 = (PFFSv2_INODE)ExAllocatePoolWithTag( + PagedPool, + DINODE2_SIZE, FFS_POOL_TAG); + + if (dinode2 == NULL) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + _SEH2_LEAVE; + } + + RtlZeroMemory(Buffer, Length); + + if (Fcb->dinode2->di_size <= FileIndex) + { + Status = STATUS_NO_MORE_FILES; + _SEH2_LEAVE; + } + } + + pDir = ExAllocatePoolWithTag(PagedPool, + sizeof(FFS_DIR_ENTRY), FFS_POOL_TAG); + if (!pDir) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + _SEH2_LEAVE; + } + + + if (FS_VERSION == 1) + { + dwBytes = 0; + dwSize = (ULONG)Fcb->dinode1->di_size - FileIndex - + (sizeof(FFS_DIR_ENTRY) - FFS_NAME_LEN + 1); + + ByteOffset = FileIndex; + + dwTemp = 0; + + while (bRun && UsedLength < Length && dwBytes < dwSize) + { + OEM_STRING OemName; + + RtlZeroMemory(pDir, sizeof(FFS_DIR_ENTRY)); + + Status = FFSv1ReadInode( + NULL, + Vcb, + Fcb->dinode1, + ByteOffset, + (PVOID)pDir, + sizeof(FFS_DIR_ENTRY), + &dwReturn); + + if (!NT_SUCCESS(Status)) + { + _SEH2_LEAVE; + } + + if (!pDir->d_ino) + { + if (pDir->d_reclen == 0) + { + FFSBreakPoint(); + _SEH2_LEAVE; + } + + goto ProcessNextEntryv1; + } + + OemName.Buffer = pDir->d_name; + OemName.Length = (pDir->d_namlen & 0xff); + OemName.MaximumLength = OemName.Length; + +#if 0 +/* + // + // We could not filter the files: "." and ".." + // + + if ((OemName.Length >) 1 && OemName.Buffer[0] == '.') + { + if ( OemName.Length == 2 && OemName.Buffer[1] == '.') + { + } + else + { + goto ProcessNextEntry1; + } + } +*/ +#endif + + InodeFileNameLength = (USHORT) + RtlOemStringToUnicodeSize(&OemName); + + InodeFileName.Length = 0; + InodeFileName.MaximumLength = InodeFileNameLength + 2; + + if (InodeFileNameLength <= 0) + { + break; + } + + InodeFileName.Buffer = ExAllocatePoolWithTag( + PagedPool, + InodeFileNameLength + 2, FFS_POOL_TAG); + + if (!InodeFileName.Buffer) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + _SEH2_LEAVE; + } + + RtlZeroMemory( + InodeFileName.Buffer, + InodeFileNameLength + 2); + + Status = FFSOEMToUnicode(&InodeFileName, + &OemName); + + if (!NT_SUCCESS(Status)) + { + _SEH2_LEAVE; + } + + if (FsRtlDoesNameContainWildCards( + &(Ccb->DirectorySearchPattern)) ? + FsRtlIsNameInExpression( + &(Ccb->DirectorySearchPattern), + &InodeFileName, + TRUE, + NULL) : + !RtlCompareUnicodeString( + &(Ccb->DirectorySearchPattern), + &InodeFileName, + TRUE)) + { + dwReturn = FFSProcessDirEntry( + Vcb, FileInformationClass, + pDir->d_ino, + Buffer, + UsedLength, + Length - UsedLength, + (FileIndex + dwBytes), + &InodeFileName, + ReturnSingleEntry); + + if (dwReturn <= 0) + { + bRun = FALSE; + } + else + { + dwTemp = UsedLength; + UsedLength += dwReturn; + } + } + + if (InodeFileName.Buffer != NULL) + { + ExFreePool(InodeFileName.Buffer); + InodeFileName.Buffer = NULL; + } + +ProcessNextEntryv1: + + if (bRun) + { + dwBytes +=pDir->d_reclen; + Ccb->CurrentByteOffset = FileIndex + dwBytes; + } + + if (UsedLength && ReturnSingleEntry) + { + Status = STATUS_SUCCESS; + _SEH2_LEAVE; + } + + ByteOffset = FileIndex + dwBytes; + } + } + else + { + dwBytes = 0; + dwSize = (ULONG)Fcb->dinode2->di_size - FileIndex - + (sizeof(FFS_DIR_ENTRY) - FFS_NAME_LEN + 1); + + ByteOffset = FileIndex; + + dwTemp = 0; + + while (bRun && UsedLength < Length && dwBytes < dwSize) + { + OEM_STRING OemName; + + RtlZeroMemory(pDir, sizeof(FFS_DIR_ENTRY)); + + Status = FFSv2ReadInode( + NULL, + Vcb, + Fcb->dinode2, + ByteOffset, + (PVOID)pDir, + sizeof(FFS_DIR_ENTRY), + &dwReturn); + + if (!NT_SUCCESS(Status)) + { + _SEH2_LEAVE; + } + + if (!pDir->d_ino) + { + if (pDir->d_reclen == 0) + { + FFSBreakPoint(); + _SEH2_LEAVE; + } + + goto ProcessNextEntryv2; + } + + OemName.Buffer = pDir->d_name; + OemName.Length = (pDir->d_namlen & 0xff); + OemName.MaximumLength = OemName.Length; +#if 0 +/* + // + // We could not filter the files: "." and ".." + // + + if ((OemName.Length >) 1 && OemName.Buffer[0] == '.') + { + if ( OemName.Length == 2 && OemName.Buffer[1] == '.') + { + } + else + { + goto ProcessNextEntry2; + } + } +*/ +#endif + + InodeFileNameLength = (USHORT) + RtlOemStringToUnicodeSize(&OemName); + + InodeFileName.Length = 0; + InodeFileName.MaximumLength = InodeFileNameLength + 2; + + if (InodeFileNameLength <= 0) + { + break; + } + + InodeFileName.Buffer = ExAllocatePoolWithTag( + PagedPool, + InodeFileNameLength + 2, FFS_POOL_TAG); + + if (!InodeFileName.Buffer) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + _SEH2_LEAVE; + } + + RtlZeroMemory( + InodeFileName.Buffer, + InodeFileNameLength + 2); + + Status = FFSOEMToUnicode(&InodeFileName, + &OemName); + + if (!NT_SUCCESS(Status)) + { + _SEH2_LEAVE; + } + + if (FsRtlDoesNameContainWildCards( + &(Ccb->DirectorySearchPattern)) ? + FsRtlIsNameInExpression( + &(Ccb->DirectorySearchPattern), + &InodeFileName, + TRUE, + NULL) : + !RtlCompareUnicodeString( + &(Ccb->DirectorySearchPattern), + &InodeFileName, + TRUE)) + { + dwReturn = FFSProcessDirEntry( + Vcb, FileInformationClass, + pDir->d_ino, + Buffer, + UsedLength, + Length - UsedLength, + (FileIndex + dwBytes), + &InodeFileName, + ReturnSingleEntry); + + if (dwReturn <= 0) + { + bRun = FALSE; + } + else + { + dwTemp = UsedLength; + UsedLength += dwReturn; + } + } + + if (InodeFileName.Buffer != NULL) + { + ExFreePool(InodeFileName.Buffer); + InodeFileName.Buffer = NULL; + } + +ProcessNextEntryv2: + + if (bRun) + { + dwBytes +=pDir->d_reclen; + Ccb->CurrentByteOffset = FileIndex + dwBytes; + } + + if (UsedLength && ReturnSingleEntry) + { + Status = STATUS_SUCCESS; + _SEH2_LEAVE; + } + + ByteOffset = FileIndex + dwBytes; + } + } + + FileIndex += dwBytes; + + ((PULONG)((PUCHAR)Buffer + dwTemp)) [0] = 0; + + if (!UsedLength) + { + if (FirstQuery) + { + Status = STATUS_NO_SUCH_FILE; + } + else + { + Status = STATUS_NO_MORE_FILES; + } + } + else + { + Status = STATUS_SUCCESS; + } + } + + _SEH2_FINALLY + { + + if (FcbResourceAcquired) + { + ExReleaseResourceForThreadLite( + &Fcb->MainResource, + ExGetCurrentResourceThread()); + } + + if (FS_VERSION == 1) + { + if (dinode1 != NULL) + { + ExFreePool(dinode1); + } + } + else + { + if (dinode2 != NULL) + { + ExFreePool(dinode2); + } + } + + if (pDir != NULL) + { + ExFreePool(pDir); + pDir = NULL; + } + + if (InodeFileName.Buffer != NULL) + { + ExFreePool(InodeFileName.Buffer); + } + + if (!IrpContext->ExceptionInProgress) + { + if (Status == STATUS_PENDING) + { + Status = FFSLockUserBuffer( + IrpContext->Irp, + Length, + IoWriteAccess); + + if (NT_SUCCESS(Status)) + { + Status = FFSQueueRequest(IrpContext); + } + else + { + FFSCompleteIrpContext(IrpContext, Status); + } + } + else + { + IrpContext->Irp->IoStatus.Information = UsedLength; + FFSCompleteIrpContext(IrpContext, Status); + } + } + } _SEH2_END; + + return Status; +} + + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSNotifyChangeDirectory( + IN PFFS_IRP_CONTEXT IrpContext) +{ + PDEVICE_OBJECT DeviceObject; + BOOLEAN CompleteRequest; + NTSTATUS Status = STATUS_UNSUCCESSFUL; + PFFS_VCB Vcb; + PFILE_OBJECT FileObject; + PFFS_FCB Fcb = 0; + PIRP Irp; + PIO_STACK_LOCATION IrpSp; + ULONG CompletionFilter; + BOOLEAN WatchTree; + + BOOLEAN bFcbAcquired = FALSE; + + PUNICODE_STRING FullName; + + PAGED_CODE(); + + _SEH2_TRY + { + ASSERT(IrpContext); + + ASSERT((IrpContext->Identifier.Type == FFSICX) && + (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); + + // + // Always set the wait flag in the Irp context for the original request. + // + + SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); + + DeviceObject = IrpContext->DeviceObject; + + if (DeviceObject == FFSGlobal->DeviceObject) + { + CompleteRequest = TRUE; + Status = STATUS_INVALID_DEVICE_REQUEST; + _SEH2_LEAVE; + } + + Vcb = (PFFS_VCB)DeviceObject->DeviceExtension; + + ASSERT(Vcb != NULL); + + ASSERT((Vcb->Identifier.Type == FFSVCB) && + (Vcb->Identifier.Size == sizeof(FFS_VCB))); + + ASSERT(IsMounted(Vcb)); + + FileObject = IrpContext->FileObject; + + Fcb = (PFFS_FCB)FileObject->FsContext; + + ASSERT(Fcb); + + if (Fcb->Identifier.Type == FFSVCB) + { + FFSBreakPoint(); + CompleteRequest = TRUE; + Status = STATUS_INVALID_PARAMETER; + _SEH2_LEAVE; + } + + ASSERT((Fcb->Identifier.Type == FFSFCB) && + (Fcb->Identifier.Size == sizeof(FFS_FCB))); + + if (!IsDirectory(Fcb)) + { + FFSBreakPoint(); + CompleteRequest = TRUE; + Status = STATUS_INVALID_PARAMETER; + _SEH2_LEAVE; + } + + if (ExAcquireResourceExclusiveLite( + &Fcb->MainResource, + TRUE)) + { + bFcbAcquired = TRUE; + } + else + { + Status = STATUS_PENDING; + _SEH2_LEAVE; + } + + Irp = IrpContext->Irp; + + IrpSp = IoGetCurrentIrpStackLocation(Irp); + +#if !defined(_GNU_NTIFS_) || defined(__REACTOS__) + + CompletionFilter = + IrpSp->Parameters.NotifyDirectory.CompletionFilter; + +#else // _GNU_NTIFS_ + + CompletionFilter = ((PEXTENDED_IO_STACK_LOCATION) + IrpSp)->Parameters.NotifyDirectory.CompletionFilter; + +#endif // _GNU_NTIFS_ + + WatchTree = IsFlagOn(IrpSp->Flags, SL_WATCH_TREE); + + if (FlagOn(Fcb->Flags, FCB_DELETE_PENDING)) + { + Status = STATUS_DELETE_PENDING; + _SEH2_LEAVE; + } + + FullName = &Fcb->LongName; + + if (FullName->Buffer == NULL) + { + if (!FFSGetFullFileName(Fcb->FFSMcb, FullName)) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + _SEH2_LEAVE; + } + } + + FsRtlNotifyFullChangeDirectory(Vcb->NotifySync, + &Vcb->NotifyList, + FileObject->FsContext2, + (PSTRING)FullName, + WatchTree, + FALSE, + CompletionFilter, + Irp, + NULL, + NULL); + + CompleteRequest = FALSE; + + Status = STATUS_PENDING; + + /* + Currently the driver is read-only but here is an example on how to use the + FsRtl-functions to report a change: + + ANSI_STRING TestString; + USHORT FileNamePartLength; + + RtlInitAnsiString(&TestString, "\\ntifs.h"); + + FileNamePartLength = 7; + + FsRtlNotifyReportChange( + Vcb->NotifySync, // PNOTIFY_SYNC NotifySync + &Vcb->NotifyList, // PLIST_ENTRY NotifyList + &TestString, // PSTRING FullTargetName + &FileNamePartLength, // PUSHORT FileNamePartLength + FILE_NOTIFY_CHANGE_NAME // ULONG FilterMatch + ); + + or + + ANSI_STRING TestString; + + RtlInitAnsiString(&TestString, "\\ntifs.h"); + + FsRtlNotifyFullReportChange( + Vcb->NotifySync, // PNOTIFY_SYNC NotifySync + &Vcb->NotifyList, // PLIST_ENTRY NotifyList + &TestString, // PSTRING FullTargetName + 1, // USHORT TargetNameOffset + NULL, // PSTRING StreamName OPTIONAL + NULL, // PSTRING NormalizedParentName OPTIONAL + FILE_NOTIFY_CHANGE_NAME, // ULONG FilterMatch + 0, // ULONG Action + NULL // PVOID TargetContext + ); + */ + + } + _SEH2_FINALLY + { + if (bFcbAcquired) + { + ExReleaseResourceForThreadLite( + &Fcb->MainResource, + ExGetCurrentResourceThread()); + } + + if (!IrpContext->ExceptionInProgress) + { + if (!CompleteRequest) + { + IrpContext->Irp = NULL; + } + + FFSCompleteIrpContext(IrpContext, Status); + } + } _SEH2_END; + + return Status; +} + + +VOID +FFSNotifyReportChange( + IN PFFS_IRP_CONTEXT IrpContext, + IN PFFS_VCB Vcb, + IN PFFS_FCB Fcb, + IN ULONG Filter, + IN ULONG Action) +{ + PUNICODE_STRING FullName; + USHORT Offset; + + FullName = &Fcb->LongName; + + // ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL); + + if (FullName->Buffer == NULL) + { + if (!FFSGetFullFileName(Fcb->FFSMcb, FullName)) + { + /*Status = STATUS_INSUFFICIENT_RESOURCES;*/ + return; + } + } + + Offset = (USHORT)(FullName->Length - + Fcb->FFSMcb->ShortName.Length); + + FsRtlNotifyFullReportChange(Vcb->NotifySync, + &(Vcb->NotifyList), + (PSTRING)(FullName), + (USHORT)Offset, + (PSTRING)NULL, + (PSTRING)NULL, + (ULONG)Filter, + (ULONG)Action, + (PVOID)NULL); + + // ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL); +} + + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSDirectoryControl( + IN PFFS_IRP_CONTEXT IrpContext) +{ + NTSTATUS Status; + + PAGED_CODE(); + + ASSERT(IrpContext); + + ASSERT((IrpContext->Identifier.Type == FFSICX) && + (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); + + switch (IrpContext->MinorFunction) + { + case IRP_MN_QUERY_DIRECTORY: + Status = FFSQueryDirectory(IrpContext); + break; + + case IRP_MN_NOTIFY_CHANGE_DIRECTORY: + Status = FFSNotifyChangeDirectory(IrpContext); + break; + + default: + Status = STATUS_INVALID_DEVICE_REQUEST; + FFSCompleteIrpContext(IrpContext, Status); + } + + return Status; +} + + +BOOLEAN +FFSIsDirectoryEmpty( + PFFS_VCB Vcb, + PFFS_FCB Dcb) +{ + NTSTATUS Status = STATUS_UNSUCCESSFUL; + + PFFS_DIR_ENTRY pTarget = NULL; + + ULONG dwBytes = 0; + ULONG dwRet; + + BOOLEAN bRet = TRUE; + + PAGED_CODE(); + + if (!IsFlagOn(Dcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY)) + return TRUE; + + _SEH2_TRY + { + pTarget = (PFFS_DIR_ENTRY)ExAllocatePoolWithTag(PagedPool, + FFS_DIR_REC_LEN(FFS_NAME_LEN), FFS_POOL_TAG); + if (!pTarget) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + _SEH2_LEAVE; + } + + dwBytes = 0; + + + while ((LONGLONG)dwBytes < Dcb->Header.AllocationSize.QuadPart) + { + RtlZeroMemory(pTarget, FFS_DIR_REC_LEN(FFS_NAME_LEN)); + + if (FS_VERSION == 1) + { + Status = FFSv1ReadInode( + NULL, + Vcb, + Dcb->dinode1, + dwBytes, + (PVOID)pTarget, + FFS_DIR_REC_LEN(FFS_NAME_LEN), + &dwRet); + } + else + { + Status = FFSv2ReadInode( + NULL, + Vcb, + Dcb->dinode2, + dwBytes, + (PVOID)pTarget, + FFS_DIR_REC_LEN(FFS_NAME_LEN), + &dwRet); + } + + if (!NT_SUCCESS(Status)) + { + FFSPrint((DBG_ERROR, "FFSRemoveEntry: Reading Directory Content error.\n")); + _SEH2_LEAVE; + } + + if (pTarget->d_ino) + { + if (pTarget->d_namlen == 1 && pTarget->d_name[0] == '.') + { + } + else if (pTarget->d_namlen == 2 && pTarget->d_name[0] == '.' && + pTarget->d_name[1] == '.') + { + } + else + { + bRet = FALSE; + break; + } + } + else + { + break; + } + + dwBytes += pTarget->d_reclen; + } + } + + _SEH2_FINALLY + { + if (pTarget != NULL) + { + ExFreePool(pTarget); + } + } _SEH2_END; + + return bRet; +} diff --git a/reactos/drivers/filesystems/ffs/src/dispatch.c b/reactos/drivers/filesystems/ffs/src/dispatch.c new file mode 100644 index 00000000000..0a8d048b82c --- /dev/null +++ b/reactos/drivers/filesystems/ffs/src/dispatch.c @@ -0,0 +1,252 @@ +/* + * FFS File System Driver for Windows + * + * dipatch.c + * + * 2004.5.6 ~ + * + * Lee Jae-Hong, http://www.pyrasis.com + * + * See License.txt + * + */ + +#include "ntifs.h" +#include "ffsdrv.h" + +/* Globals */ + +extern PFFS_GLOBAL FFSGlobal; + + +/* Definitions */ + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE, FFSQueueRequest) +#pragma alloc_text(PAGE, FFSDeQueueRequest) +#pragma alloc_text(PAGE, FFSDispatchRequest) +#pragma alloc_text(PAGE, FFSBuildRequest) +#endif + + +NTSTATUS +FFSQueueRequest( + IN PFFS_IRP_CONTEXT IrpContext) +{ + PAGED_CODE(); + + ASSERT(IrpContext); + + ASSERT((IrpContext->Identifier.Type == FFSICX) && + (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); + + // IsSynchronous means we can block (so we don't requeue it) + IrpContext->IsSynchronous = TRUE; + + SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED); + + IoMarkIrpPending(IrpContext->Irp); + + ExInitializeWorkItem( + &IrpContext->WorkQueueItem, + FFSDeQueueRequest, + IrpContext); + + ExQueueWorkItem(&IrpContext->WorkQueueItem, CriticalWorkQueue); + + return STATUS_PENDING; +} + + +VOID NTAPI +FFSDeQueueRequest( + IN PVOID Context) +{ + PFFS_IRP_CONTEXT IrpContext; + + PAGED_CODE(); + + IrpContext = (PFFS_IRP_CONTEXT) Context; + + ASSERT(IrpContext); + + ASSERT((IrpContext->Identifier.Type == FFSICX) && + (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); + + _SEH2_TRY + { + _SEH2_TRY + { + FsRtlEnterFileSystem(); + + if (!IrpContext->IsTopLevel) + { + IoSetTopLevelIrp((PIRP) FSRTL_FSP_TOP_LEVEL_IRP); + } + + FFSDispatchRequest(IrpContext); + } + _SEH2_EXCEPT (FFSExceptionFilter(IrpContext, _SEH2_GetExceptionInformation())) + { + FFSExceptionHandler(IrpContext); + } _SEH2_END; + } + _SEH2_FINALLY + { + IoSetTopLevelIrp(NULL); + + FsRtlExitFileSystem(); + } _SEH2_END; +} + + +NTSTATUS +FFSDispatchRequest( + IN PFFS_IRP_CONTEXT IrpContext) +{ + PAGED_CODE(); + + ASSERT(IrpContext); + + ASSERT((IrpContext->Identifier.Type == FFSICX) && + (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); + + switch (IrpContext->MajorFunction) + { + case IRP_MJ_CREATE: + return FFSCreate(IrpContext); + + case IRP_MJ_CLOSE: + return FFSClose(IrpContext); + + case IRP_MJ_READ: + return FFSRead(IrpContext); + +#if !FFS_READ_ONLY + case IRP_MJ_WRITE: + return FFSWrite(IrpContext); +#endif // !FFS_READ_ONLY + + case IRP_MJ_FLUSH_BUFFERS: + return FFSFlush(IrpContext); + + case IRP_MJ_QUERY_INFORMATION: + return FFSQueryInformation(IrpContext); + + case IRP_MJ_SET_INFORMATION: + return FFSSetInformation(IrpContext); + + case IRP_MJ_QUERY_VOLUME_INFORMATION: + return FFSQueryVolumeInformation(IrpContext); + +#if !FFS_READ_ONLY + case IRP_MJ_SET_VOLUME_INFORMATION: + return FFSSetVolumeInformation(IrpContext); +#endif // !FFS_READ_ONLY + + case IRP_MJ_DIRECTORY_CONTROL: + return FFSDirectoryControl(IrpContext); + + case IRP_MJ_FILE_SYSTEM_CONTROL: + return FFSFileSystemControl(IrpContext); + + case IRP_MJ_DEVICE_CONTROL: + return FFSDeviceControl(IrpContext); + + case IRP_MJ_LOCK_CONTROL: + return FFSLockControl(IrpContext); + + case IRP_MJ_CLEANUP: + return FFSCleanup(IrpContext); + + case IRP_MJ_SHUTDOWN: + return FFSShutDown(IrpContext); + +#if (_WIN32_WINNT >= 0x0500) + case IRP_MJ_PNP: + return FFSPnp(IrpContext); +#endif //(_WIN32_WINNT >= 0x0500) + default: + FFSPrint((DBG_ERROR, "FFSDispatchRequest: Unexpected major function: %xh\n", + IrpContext->MajorFunction)); + + FFSCompleteIrpContext(IrpContext, STATUS_DRIVER_INTERNAL_ERROR); + + return STATUS_DRIVER_INTERNAL_ERROR; + } +} + + +NTSTATUS NTAPI +FFSBuildRequest( + PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + BOOLEAN AtIrqlPassiveLevel = FALSE; + BOOLEAN IsTopLevelIrp = FALSE; + PFFS_IRP_CONTEXT IrpContext = NULL; + NTSTATUS Status = STATUS_UNSUCCESSFUL; + + PAGED_CODE(); + + _SEH2_TRY + { + _SEH2_TRY + { +#if DBG + FFSDbgPrintCall(DeviceObject, Irp); +#endif + + AtIrqlPassiveLevel = (KeGetCurrentIrql() == PASSIVE_LEVEL); + + if (AtIrqlPassiveLevel) + { + FsRtlEnterFileSystem(); + } + + if (!IoGetTopLevelIrp()) + { + IsTopLevelIrp = TRUE; + IoSetTopLevelIrp(Irp); + } + + IrpContext = FFSAllocateIrpContext(DeviceObject, Irp); + + if (!IrpContext) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + Irp->IoStatus.Status = Status; + + FFSCompleteRequest(Irp, TRUE, IO_NO_INCREMENT); + } + else + { + if ((IrpContext->MajorFunction == IRP_MJ_CREATE) && + !AtIrqlPassiveLevel) + { + FFSBreakPoint(); + } + + Status = FFSDispatchRequest(IrpContext); + } + } + _SEH2_EXCEPT (FFSExceptionFilter(IrpContext, _SEH2_GetExceptionInformation())) + { + Status = FFSExceptionHandler(IrpContext); + } _SEH2_END; + } + _SEH2_FINALLY + { + if (IsTopLevelIrp) + { + IoSetTopLevelIrp(NULL); + } + + if (AtIrqlPassiveLevel) + { + FsRtlExitFileSystem(); + } + } _SEH2_END; + + return Status; +} diff --git a/reactos/drivers/filesystems/ffs/src/except.c b/reactos/drivers/filesystems/ffs/src/except.c new file mode 100644 index 00000000000..167c2178745 --- /dev/null +++ b/reactos/drivers/filesystems/ffs/src/except.c @@ -0,0 +1,210 @@ +/* + * FFS File System Driver for Windows + * + * except.c + * + * 2004.5.6 ~ + * + * Lee Jae-Hong, http://www.pyrasis.com + * + * See License.txt + * + */ + +#include "ntifs.h" +#include "ffsdrv.h" + +/* Globals */ + +extern PFFS_GLOBAL FFSGlobal; + + +/* Definitions */ + +#ifdef ALLOC_PRAGMA +//#pragma alloc_text(PAGE, FFSExceptionFilter) +//#pragma alloc_text(PAGE, FFSExceptionHandler) +#endif + + +NTSTATUS +FFSExceptionFilter( + IN PFFS_IRP_CONTEXT IrpContext, + IN PEXCEPTION_POINTERS ExceptionPointer) +{ + NTSTATUS Status, ExceptionCode; + PEXCEPTION_RECORD ExceptRecord; + + ExceptRecord = ExceptionPointer->ExceptionRecord; + + ExceptionCode = ExceptRecord->ExceptionCode; + + FFSBreakPoint(); + + // + // Check IrpContext is valid or not + // + + if (IrpContext) + { + if ((IrpContext->Identifier.Type != FFSICX) || + (IrpContext->Identifier.Size != sizeof(FFS_IRP_CONTEXT))) + { + IrpContext = NULL; + } + } + else + { + if (FsRtlIsNtstatusExpected(ExceptionCode)) + { + return EXCEPTION_EXECUTE_HANDLER; + } + else + { + FFSBugCheck(FFS_BUGCHK_EXCEPT, (ULONG_PTR)ExceptRecord, + (ULONG_PTR)ExceptionPointer->ContextRecord, + (ULONG_PTR)ExceptRecord->ExceptionAddress); + } + } + + // + // For the purposes of processing this exception, let's mark this + // request as being able to wait, and neither write through nor on + // removable media if we aren't posting it. + // + + SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); + + if (FsRtlIsNtstatusExpected(ExceptionCode)) + { + // + // If the exception is expected execute our handler + // + + FFSPrint((DBG_ERROR, "FFSExceptionFilter: Catching exception %xh\n", + ExceptionCode)); + + Status = EXCEPTION_EXECUTE_HANDLER; + + if (IrpContext) + { + IrpContext->ExceptionInProgress = TRUE; + IrpContext->ExceptionCode = ExceptionCode; + } + } + else + { + // + // Continue search for an higher level exception handler + // + + FFSPrint((DBG_ERROR, "FFSExceptionFilter: Passing on exception %#x\n", + ExceptionCode)); + + Status = EXCEPTION_CONTINUE_SEARCH; + + if (IrpContext) + { + FFSFreeIrpContext(IrpContext); + } + } + + return Status; +} + + +NTSTATUS +FFSExceptionHandler( + IN PFFS_IRP_CONTEXT IrpContext) +{ + NTSTATUS Status; + + FFSBreakPoint(); + + if (IrpContext) + { + if ((IrpContext->Identifier.Type != FFSICX) || + (IrpContext->Identifier.Size != sizeof(FFS_IRP_CONTEXT))) + { + FFSBreakPoint(); + return STATUS_UNSUCCESSFUL; + } + + Status = IrpContext->ExceptionCode; + + if (IrpContext->Irp) + { + // + // Check if this error is a result of user actions + // + + PIRP Irp = IrpContext->Irp; + + + if (IoIsErrorUserInduced(Status)) + { + // + // Now we will generate a pop-up to user + // + + PDEVICE_OBJECT RealDevice; + PVPB Vpb = NULL; + PETHREAD Thread; + + if (IoGetCurrentIrpStackLocation(Irp)->FileObject != NULL) + { + Vpb = IoGetCurrentIrpStackLocation(Irp)->FileObject->Vpb; + } + + // + // Get the initial thread + // + + Thread = Irp->Tail.Overlay.Thread; + RealDevice = IoGetDeviceToVerify(Thread); + + if (RealDevice == NULL) + { + // + // Get current thread + // + + Thread = PsGetCurrentThread(); + RealDevice = IoGetDeviceToVerify(Thread); + + ASSERT(RealDevice != NULL); + } + + if (RealDevice != NULL) + { + // + // Now we pop-up the error dialog ... + // + + IoMarkIrpPending(Irp); + IoRaiseHardError(Irp, Vpb, RealDevice); + + IoSetDeviceToVerify(Thread, NULL); + + Status = STATUS_PENDING; + goto errorout; + } + } + + IrpContext->Irp->IoStatus.Status = Status; + + FFSCompleteRequest(IrpContext->Irp, FALSE, IO_NO_INCREMENT); + } + +errorout: + + FFSFreeIrpContext(IrpContext); + } + else + { + Status = STATUS_INSUFFICIENT_RESOURCES; + } + + return Status; +} + diff --git a/reactos/drivers/filesystems/ffs/src/fastio.c b/reactos/drivers/filesystems/ffs/src/fastio.c new file mode 100644 index 00000000000..06c4269f16c --- /dev/null +++ b/reactos/drivers/filesystems/ffs/src/fastio.c @@ -0,0 +1,1146 @@ +/* + * FFS File System Driver for Windows + * + * fastio.c + * + * 2004.5.6 ~ + * + * Lee Jae-Hong, http://www.pyrasis.com + * + * See License.txt + * + */ + +#include "ntifs.h" +#include "ffsdrv.h" + +/* Globals */ + +extern PFFS_GLOBAL FFSGlobal; + + +/* Definitions */ + +#ifdef ALLOC_PRAGMA +#if DBG +#pragma alloc_text(PAGE, FFSFastIoRead) +#pragma alloc_text(PAGE, FFSFastIoWrite) +#endif +#pragma alloc_text(PAGE, FFSFastIoCheckIfPossible) +#pragma alloc_text(PAGE, FFSFastIoQueryBasicInfo) +#pragma alloc_text(PAGE, FFSFastIoQueryStandardInfo) +#pragma alloc_text(PAGE, FFSFastIoQueryNetworkOpenInfo) +#pragma alloc_text(PAGE, FFSFastIoLock) +#pragma alloc_text(PAGE, FFSFastIoUnlockSingle) +#pragma alloc_text(PAGE, FFSFastIoUnlockAll) +#pragma alloc_text(PAGE, FFSFastIoUnlockAllByKey) +#endif + + +BOOLEAN NTAPI +FFSFastIoCheckIfPossible( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN BOOLEAN Wait, + IN ULONG LockKey, + IN BOOLEAN CheckForReadOperation, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject) +{ + BOOLEAN bPossible = FALSE; + PFFS_FCB Fcb; + LARGE_INTEGER lLength; + + PAGED_CODE(); + + lLength.QuadPart = Length; + + _SEH2_TRY + { + _SEH2_TRY + { + FsRtlEnterFileSystem(); + + if (DeviceObject == FFSGlobal->DeviceObject) + { + bPossible = FastIoIsNotPossible; + _SEH2_LEAVE; + } + + Fcb = (PFFS_FCB)FileObject->FsContext; + + ASSERT(Fcb != NULL); + + if (Fcb->Identifier.Type == FFSVCB) + { + bPossible = FastIoIsNotPossible; + _SEH2_LEAVE; + } + + ASSERT((Fcb->Identifier.Type == FFSFCB) && + (Fcb->Identifier.Size == sizeof(FFS_FCB))); + + if (IsDirectory(Fcb)) + { + bPossible = FALSE; + _SEH2_LEAVE; + } + + if (CheckForReadOperation) + { + bPossible = FsRtlFastCheckLockForRead( + &Fcb->FileLockAnchor, + FileOffset, + &lLength, + LockKey, + FileObject, + PsGetCurrentProcess()); + + if (!bPossible) + bPossible = FastIoIsQuestionable; + } + else + { + if (IsFlagOn(Fcb->Vcb->Flags, VCB_READ_ONLY) || + IsFlagOn(Fcb->Vcb->Flags, VCB_WRITE_PROTECTED)) + { + bPossible = FastIoIsNotPossible; + } + else + { + bPossible = FsRtlFastCheckLockForWrite( + &Fcb->FileLockAnchor, + FileOffset, + &lLength, + LockKey, + FileObject, + PsGetCurrentProcess()); + + if (!bPossible) + bPossible = FastIoIsQuestionable; + } + } + + FFSPrint((DBG_INFO, "FFSFastIIOCheckPossible: %s %s %s\n", + FFSGetCurrentProcessName(), + "FASTIO_CHECK_IF_POSSIBLE", + Fcb->AnsiFileName.Buffer)); + + FFSPrint((DBG_INFO, + "FFSFastIIOCheckPossible: Offset: %I64xg Length: %xh Key: %u %s %s\n", + FileOffset->QuadPart, + Length, + LockKey, + (CheckForReadOperation ? "CheckForReadOperation:" : + "CheckForWriteOperation:"), + (bPossible ? "Succeeded" : "Failed"))); + } + _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) + { + bPossible = FastIoIsNotPossible; + } _SEH2_END; + } + _SEH2_FINALLY + { + FsRtlExitFileSystem(); + } _SEH2_END; + + return bPossible; +} + + +#if DBG + +BOOLEAN NTAPI +FFSFastIoRead( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN BOOLEAN Wait, + IN ULONG LockKey, + OUT PVOID Buffer, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject) +{ + BOOLEAN Status; + PFFS_FCB Fcb; + + PAGED_CODE(); + + Fcb = (PFFS_FCB)FileObject->FsContext; + + ASSERT(Fcb != NULL); + + ASSERT((Fcb->Identifier.Type == FFSFCB) && + (Fcb->Identifier.Size == sizeof(FFS_FCB))); + + FFSPrint((DBG_INFO, "FFSFastIoRead: %s %s %s\n", + FFSGetCurrentProcessName(), + "FASTIO_READ", + Fcb->AnsiFileName.Buffer)); + + FFSPrint((DBG_INFO, "FFSFastIoRead: Offset: %I64xh Length: %xh Key: %u\n", + FileOffset->QuadPart, + Length, + LockKey)); + + Status = FsRtlCopyRead( + FileObject, FileOffset, Length, Wait, + LockKey, Buffer, IoStatus, DeviceObject); + + return Status; +} + +#if !FFS_READ_ONLY + +BOOLEAN NTAPI +FFSFastIoWrite( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN BOOLEAN Wait, + IN ULONG LockKey, + OUT PVOID Buffer, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject) +{ + BOOLEAN bRet; + PFFS_FCB Fcb; + + PAGED_CODE(); + + Fcb = (PFFS_FCB)FileObject->FsContext; + + ASSERT(Fcb != NULL); + + ASSERT((Fcb->Identifier.Type == FFSFCB) && + (Fcb->Identifier.Size == sizeof(FFS_FCB))); + + FFSPrint((DBG_INFO, + "FFSFastIoWrite: %s %s %s\n", + FFSGetCurrentProcessName(), + "FASTIO_WRITE", + Fcb->AnsiFileName.Buffer)); + + FFSPrint((DBG_INFO, + "FFSFastIoWrite: Offset: %I64xh Length: %xh Key: %xh\n", + FileOffset->QuadPart, + Length, + LockKey)); + + if (IsFlagOn(Fcb->Vcb->Flags, VCB_READ_ONLY)) + { + FFSBreakPoint(); + return FALSE; + } + + bRet = FsRtlCopyWrite( + FileObject, FileOffset, Length, Wait, + LockKey, Buffer, IoStatus, DeviceObject); + + return bRet; +} + +#endif // !FFS_READ_ONLY + +#endif /* DBG */ + + +__drv_mustHoldCriticalRegion +BOOLEAN NTAPI +FFSFastIoQueryBasicInfo( + IN PFILE_OBJECT FileObject, + IN BOOLEAN Wait, + OUT PFILE_BASIC_INFORMATION Buffer, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject) +{ + BOOLEAN Status = FALSE; + PFFS_VCB Vcb; + PFFS_FCB Fcb = 0; + BOOLEAN FcbMainResourceAcquired = FALSE; + + PAGED_CODE(); + + _SEH2_TRY + { + _SEH2_TRY + { + FsRtlEnterFileSystem(); + + if (DeviceObject == FFSGlobal->DeviceObject) + { + IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST; + Status = TRUE; + _SEH2_LEAVE; + } + + Vcb = (PFFS_VCB)DeviceObject->DeviceExtension; + + ASSERT(Vcb != NULL); + + Fcb = (PFFS_FCB)FileObject->FsContext; + + ASSERT(Fcb != NULL); + + if (Fcb->Identifier.Type == FFSVCB) + { + IoStatus->Status = STATUS_INVALID_PARAMETER; + Status = TRUE; + _SEH2_LEAVE; + } + + ASSERT((Fcb->Identifier.Type == FFSFCB) && + (Fcb->Identifier.Size == sizeof(FFS_FCB))); + + FFSPrint((DBG_INFO, + "FFSFastIoQueryBasicInfo: %s %s %s\n", + FFSGetCurrentProcessName(), + "FASTIO_QUERY_BASIC_INFO", + Fcb->AnsiFileName.Buffer)); + + if (!ExAcquireResourceSharedLite( + &Fcb->MainResource, + Wait)) + { + Status = FALSE; + _SEH2_LEAVE; + } + + FcbMainResourceAcquired = TRUE; + + RtlZeroMemory(Buffer, sizeof(FILE_BASIC_INFORMATION)); + + /* + typedef struct _FILE_BASIC_INFORMATION { + LARGE_INTEGER CreationTime; + LARGE_INTEGER LastAccessTime; + LARGE_INTEGER LastWriteTime; + LARGE_INTEGER ChangeTime; + ULONG FileAttributes; + } FILE_BASIC_INFORMATION, *PFILE_BASIC_INFORMATION; + */ + + if (FS_VERSION == 1) + { + Buffer->CreationTime = FFSSysTime(Fcb->dinode1->di_ctime); + Buffer->LastAccessTime = FFSSysTime(Fcb->dinode1->di_atime); + Buffer->LastWriteTime = FFSSysTime(Fcb->dinode1->di_mtime); + Buffer->ChangeTime = FFSSysTime(Fcb->dinode1->di_mtime); + } + else + { + Buffer->CreationTime = FFSSysTime((ULONG)Fcb->dinode2->di_ctime); + Buffer->LastAccessTime = FFSSysTime((ULONG)Fcb->dinode2->di_atime); + Buffer->LastWriteTime = FFSSysTime((ULONG)Fcb->dinode2->di_mtime); + Buffer->ChangeTime = FFSSysTime((ULONG)Fcb->dinode2->di_mtime); + } + + + Buffer->FileAttributes = Fcb->FFSMcb->FileAttr; + + IoStatus->Information = sizeof(FILE_BASIC_INFORMATION); + + IoStatus->Status = STATUS_SUCCESS; + + Status = TRUE; + } + _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) + { + IoStatus->Status = _SEH2_GetExceptionCode(); + Status = TRUE; + } _SEH2_END; + } + + _SEH2_FINALLY + { + if (FcbMainResourceAcquired) + { + ExReleaseResourceForThreadLite( + &Fcb->MainResource, + ExGetCurrentResourceThread()); + } + + FsRtlExitFileSystem(); + } _SEH2_END; + + + if (Status == FALSE) + { + FFSPrint((DBG_ERROR, + "FFSFastIoQueryBasicInfo: %s %s *** Status: FALSE ***\n", + FFSGetCurrentProcessName(), + "FASTIO_QUERY_BASIC_INFO")); + } + else if (IoStatus->Status != STATUS_SUCCESS) + { + FFSPrint((DBG_ERROR, + "FFSFastIoQueryBasicInfo: %s %s *** Status: %s (%#x) ***\n", + FFSFastIoQueryBasicInfo, + "FASTIO_QUERY_BASIC_INFO", + FFSNtStatusToString(IoStatus->Status), + IoStatus->Status)); + } + + return Status; +} + + +__drv_mustHoldCriticalRegion +BOOLEAN NTAPI +FFSFastIoQueryStandardInfo( + IN PFILE_OBJECT FileObject, + IN BOOLEAN Wait, + OUT PFILE_STANDARD_INFORMATION Buffer, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject) +{ + + BOOLEAN Status = FALSE; + PFFS_VCB Vcb; + PFFS_FCB Fcb = 0; + BOOLEAN FcbMainResourceAcquired = FALSE; + + PAGED_CODE(); + + _SEH2_TRY + { + _SEH2_TRY + { + FsRtlEnterFileSystem(); + + if (DeviceObject == FFSGlobal->DeviceObject) + { + IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST; + Status = TRUE; + _SEH2_LEAVE; + } + + Vcb = (PFFS_VCB)DeviceObject->DeviceExtension; + + ASSERT(Vcb != NULL); + + Fcb = (PFFS_FCB)FileObject->FsContext; + + ASSERT(Fcb != NULL); + + if (Fcb->Identifier.Type == FFSVCB) + { + IoStatus->Status = STATUS_INVALID_PARAMETER; + Status = TRUE; + _SEH2_LEAVE; + } + + ASSERT((Fcb->Identifier.Type == FFSFCB) && + (Fcb->Identifier.Size == sizeof(FFS_FCB))); + + FFSPrint((DBG_INFO, + "FFSFastIoQueryStandardInfo: %s %s %s\n", + FFSGetCurrentProcessName(), + "FASTIO_QUERY_STANDARD_INFO", + Fcb->AnsiFileName.Buffer)); + + if (!ExAcquireResourceSharedLite( + &Fcb->MainResource, + Wait)) + { + Status = FALSE; + _SEH2_LEAVE; + } + + FcbMainResourceAcquired = TRUE; + + RtlZeroMemory(Buffer, sizeof(FILE_STANDARD_INFORMATION)); + + /* + typedef struct _FILE_STANDARD_INFORMATION { + LARGE_INTEGER AllocationSize; + LARGE_INTEGER EndOfFile; + ULONG NumberOfLinks; + BOOLEAN DeletePending; + BOOLEAN Directory; + } FILE_STANDARD_INFORMATION, *PFILE_STANDARD_INFORMATION; + */ + + if (FS_VERSION == 1) + { + Buffer->AllocationSize.QuadPart = + (LONGLONG)(Fcb->dinode1->di_size); + + Buffer->EndOfFile.QuadPart = + (LONGLONG)(Fcb->dinode1->di_size); + + Buffer->NumberOfLinks = Fcb->dinode1->di_nlink; + } + else + { + Buffer->AllocationSize.QuadPart = + (LONGLONG)(Fcb->dinode2->di_size); + + Buffer->EndOfFile.QuadPart = + (LONGLONG)(Fcb->dinode2->di_size); + + Buffer->NumberOfLinks = Fcb->dinode2->di_nlink; + } + + + if (IsFlagOn(Fcb->Vcb->Flags, VCB_READ_ONLY)) + { + Buffer->DeletePending = FALSE; + } + else + { + Buffer->DeletePending = IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING); + } + + if (FlagOn(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY)) + { + Buffer->Directory = TRUE; + } + else + { + Buffer->Directory = FALSE; + } + + IoStatus->Information = sizeof(FILE_STANDARD_INFORMATION); + + IoStatus->Status = STATUS_SUCCESS; + + Status = TRUE; + } + _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) + { + IoStatus->Status = _SEH2_GetExceptionCode(); + Status = TRUE; + } _SEH2_END; + } + + _SEH2_FINALLY + { + if (FcbMainResourceAcquired) + { + ExReleaseResourceForThreadLite( + &Fcb->MainResource, + ExGetCurrentResourceThread() + ); + } + + FsRtlExitFileSystem(); + } _SEH2_END; + +#if DBG + if (Status == FALSE) + { + FFSPrint((DBG_INFO, + "FFSFastIoQueryStandardInfo: %s %s *** Status: FALSE ***\n", + FFSGetCurrentProcessName(), + "FASTIO_QUERY_STANDARD_INFO")); + } + else if (IoStatus->Status != STATUS_SUCCESS) + { + FFSPrint((DBG_INFO, + "FFSFastIoQueryStandardInfo: %s %s *** Status: %s (%#x) ***\n", + FFSGetCurrentProcessName(), + "FASTIO_QUERY_STANDARD_INFO", + FFSNtStatusToString(IoStatus->Status), + IoStatus->Status)); + } +#endif + + return Status; +} + + +__drv_mustHoldCriticalRegion +BOOLEAN NTAPI +FFSFastIoQueryNetworkOpenInfo( + IN PFILE_OBJECT FileObject, + IN BOOLEAN Wait, + OUT PFILE_NETWORK_OPEN_INFORMATION Buffer, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject) +{ + BOOLEAN Status = FALSE; + PFFS_VCB Vcb; + PFFS_FCB Fcb = 0; + BOOLEAN FcbMainResourceAcquired = FALSE; + + PAGED_CODE(); + + _SEH2_TRY + { + _SEH2_TRY + { + FsRtlEnterFileSystem(); + + if (DeviceObject == FFSGlobal->DeviceObject) + { + IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST; + Status = TRUE; + _SEH2_LEAVE; + } + + Vcb = (PFFS_VCB)DeviceObject->DeviceExtension; + + ASSERT(Vcb != NULL); + + Fcb = (PFFS_FCB)FileObject->FsContext; + + ASSERT(Fcb != NULL); + + if (Fcb->Identifier.Type == FFSVCB) + { + IoStatus->Status = STATUS_INVALID_PARAMETER; + Status = TRUE; + _SEH2_LEAVE; + } + + ASSERT((Fcb->Identifier.Type == FFSFCB) && + (Fcb->Identifier.Size == sizeof(FFS_FCB))); + + FFSPrint((DBG_INFO, + "%-16.16s %-31s %s\n", + FFSGetCurrentProcessName(), + "FASTIO_QUERY_NETWORK_OPEN_INFO", + Fcb->AnsiFileName.Buffer)); + + if (!ExAcquireResourceSharedLite( + &Fcb->MainResource, + Wait)) + { + Status = FALSE; + _SEH2_LEAVE; + } + + FcbMainResourceAcquired = TRUE; + + RtlZeroMemory(Buffer, sizeof(FILE_NETWORK_OPEN_INFORMATION)); + + /* + typedef struct _FILE_NETWORK_OPEN_INFORMATION { + LARGE_INTEGER CreationTime; + LARGE_INTEGER LastAccessTime; + LARGE_INTEGER LastWriteTime; + LARGE_INTEGER ChangeTime; + LARGE_INTEGER AllocationSize; + LARGE_INTEGER EndOfFile; + ULONG FileAttributes; + } FILE_NETWORK_OPEN_INFORMATION, *PFILE_NETWORK_OPEN_INFORMATION; + */ + + if (FS_VERSION == 1) + { + Buffer->CreationTime = FFSSysTime(Fcb->dinode1->di_ctime); + Buffer->LastAccessTime = FFSSysTime(Fcb->dinode1->di_atime); + Buffer->LastWriteTime = FFSSysTime(Fcb->dinode1->di_mtime); + Buffer->ChangeTime = FFSSysTime(Fcb->dinode1->di_mtime); + Buffer->FileAttributes = Fcb->FFSMcb->FileAttr; + Buffer->AllocationSize.QuadPart = + (LONGLONG)(Fcb->dinode1->di_size); + Buffer->EndOfFile.QuadPart = + (LONGLONG)(Fcb->dinode1->di_size); + } + else + { + Buffer->CreationTime = FFSSysTime((ULONG)Fcb->dinode2->di_ctime); + Buffer->LastAccessTime = FFSSysTime((ULONG)Fcb->dinode2->di_atime); + Buffer->LastWriteTime = FFSSysTime((ULONG)Fcb->dinode2->di_mtime); + Buffer->ChangeTime = FFSSysTime((ULONG)Fcb->dinode2->di_mtime); + Buffer->FileAttributes = Fcb->FFSMcb->FileAttr; + Buffer->AllocationSize.QuadPart = + (LONGLONG)(Fcb->dinode2->di_size); + Buffer->EndOfFile.QuadPart = + (LONGLONG)(Fcb->dinode2->di_size); + } + + Buffer->FileAttributes = Fcb->FFSMcb->FileAttr; + + IoStatus->Information = sizeof(FILE_NETWORK_OPEN_INFORMATION); + + IoStatus->Status = STATUS_SUCCESS; + + Status = TRUE; + } + _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) + { + IoStatus->Status = _SEH2_GetExceptionCode(); + Status = TRUE; + } _SEH2_END; + } + _SEH2_FINALLY + { + if (FcbMainResourceAcquired) + { + ExReleaseResourceForThreadLite( + &Fcb->MainResource, + ExGetCurrentResourceThread() + ); + } + + FsRtlExitFileSystem(); + } _SEH2_END; + + + + if (Status == FALSE) + { + FFSPrint((DBG_ERROR, + "%s %s *** Status: FALSE ***\n", + FFSGetCurrentProcessName(), + "FASTIO_QUERY_NETWORK_OPEN_INFO")); + } + else if (IoStatus->Status != STATUS_SUCCESS) + { + FFSPrint((DBG_ERROR, + "%s %s *** Status: %s (%#x) ***\n", + FFSGetCurrentProcessName(), + "FASTIO_QUERY_NETWORK_OPEN_INFO", + FFSNtStatusToString(IoStatus->Status), + IoStatus->Status)); + } + + return Status; +} + + +BOOLEAN NTAPI +FFSFastIoLock( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN PLARGE_INTEGER Length, + IN PEPROCESS Process, + IN ULONG Key, + IN BOOLEAN FailImmediately, + IN BOOLEAN ExclusiveLock, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject) +{ + BOOLEAN Status = FALSE; + PFFS_FCB Fcb; + + PAGED_CODE(); + + _SEH2_TRY + { + _SEH2_TRY + { + FsRtlEnterFileSystem(); + + if (DeviceObject == FFSGlobal->DeviceObject) + { + IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST; + Status = TRUE; + _SEH2_LEAVE; + } + + Fcb = (PFFS_FCB)FileObject->FsContext; + + ASSERT(Fcb != NULL); + + if (Fcb->Identifier.Type == FFSVCB) + { + IoStatus->Status = STATUS_INVALID_PARAMETER; + Status = TRUE; + _SEH2_LEAVE; + } + + ASSERT((Fcb->Identifier.Type == FFSFCB) && + (Fcb->Identifier.Size == sizeof(FFS_FCB))); + + if (IsDirectory(Fcb)) + { + FFSBreakPoint(); + IoStatus->Status = STATUS_INVALID_PARAMETER; + Status = TRUE; + _SEH2_LEAVE; + } + + FFSPrint((DBG_INFO, + "FFSFastIoLock: %s %s %s\n", + FFSGetCurrentProcessName(), + "FASTIO_LOCK", + Fcb->AnsiFileName.Buffer)); + + FFSPrint((DBG_INFO, + "FFSFastIoLock: Offset: %I64xh Length: %I64xh Key: %u %s%s\n", + FileOffset->QuadPart, + Length->QuadPart, + Key, + (FailImmediately ? "FailImmediately " : ""), + (ExclusiveLock ? "ExclusiveLock " : ""))); + + if (Fcb->Header.IsFastIoPossible != FastIoIsQuestionable) + { + FFSPrint((DBG_INFO, + "FFSFastIoLock: %s %s %s\n", + (PUCHAR) Process + ProcessNameOffset, + "FastIoIsQuestionable", + Fcb->AnsiFileName.Buffer)); + + Fcb->Header.IsFastIoPossible = FastIoIsQuestionable; + } +#ifdef _MSC_VER +#pragma prefast( suppress: 28159, "bug in prefast" ) +#endif + Status = FsRtlFastLock( + &Fcb->FileLockAnchor, + FileObject, + FileOffset, + Length, + Process, + Key, + FailImmediately, + ExclusiveLock, + IoStatus, + NULL, + FALSE); + } + _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) + { + IoStatus->Status = _SEH2_GetExceptionCode(); + Status = TRUE; + } _SEH2_END; + } + + _SEH2_FINALLY + { + FsRtlExitFileSystem(); + } _SEH2_END; + +#if DBG + if (Status == FALSE) + { + FFSPrint((DBG_ERROR, + "FFSFastIoLock: %s %s *** Status: FALSE ***\n", + (PUCHAR) Process + ProcessNameOffset, + "FASTIO_LOCK")); + } + else if (IoStatus->Status != STATUS_SUCCESS) + { + FFSPrint((DBG_ERROR, + "FFSFastIoLock: %s %s *** Status: %s (%#x) ***\n", + (PUCHAR) Process + ProcessNameOffset, + "FASTIO_LOCK", + FFSNtStatusToString(IoStatus->Status), + IoStatus->Status)); + } +#endif + + return Status; +} + + +BOOLEAN NTAPI +FFSFastIoUnlockSingle( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN PLARGE_INTEGER Length, + IN PEPROCESS Process, + IN ULONG Key, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject) +{ + BOOLEAN Status = FALSE; + PFFS_FCB Fcb; + + PAGED_CODE(); + + _SEH2_TRY + { + _SEH2_TRY + { + FsRtlEnterFileSystem(); + + if (DeviceObject == FFSGlobal->DeviceObject) + { + IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST; + Status = TRUE; + _SEH2_LEAVE; + } + + Fcb = (PFFS_FCB)FileObject->FsContext; + + ASSERT(Fcb != NULL); + + if (Fcb->Identifier.Type == FFSVCB) + { + FFSBreakPoint(); + IoStatus->Status = STATUS_INVALID_PARAMETER; + Status = TRUE; + _SEH2_LEAVE; + } + + ASSERT((Fcb->Identifier.Type == FFSFCB) && + (Fcb->Identifier.Size == sizeof(FFS_FCB))); + + if (IsDirectory(Fcb)) + { + FFSBreakPoint(); + IoStatus->Status = STATUS_INVALID_PARAMETER; + Status = TRUE; + _SEH2_LEAVE; + } + + FFSPrint((DBG_INFO, + "FFSFastIoUnlockSingle: %s %s %s\n", + (PUCHAR) Process + ProcessNameOffset, + "FASTIO_UNLOCK_SINGLE", + Fcb->AnsiFileName.Buffer)); + + FFSPrint((DBG_INFO, + "FFSFastIoUnlockSingle: Offset: %I64xh Length: %I64xh Key: %u\n", + FileOffset->QuadPart, + Length->QuadPart, + Key)); + + IoStatus->Status = FsRtlFastUnlockSingle( + &Fcb->FileLockAnchor, + FileObject, + FileOffset, + Length, + Process, + Key, + NULL, + FALSE); + + IoStatus->Information = 0; + + Status = TRUE; + } + _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) + { + IoStatus->Status = _SEH2_GetExceptionCode(); + Status = TRUE; + } _SEH2_END; + } + _SEH2_FINALLY + { + FsRtlExitFileSystem(); + } _SEH2_END; + +#if DBG + if (Status == FALSE) + { + FFSPrint((DBG_ERROR, + "FFSFastIoUnlockSingle: %s %s *** Status: FALSE ***\n", + (PUCHAR) Process + ProcessNameOffset, + "FASTIO_UNLOCK_SINGLE")); + } + else if (IoStatus->Status != STATUS_SUCCESS) + { + FFSPrint((DBG_ERROR, + "FFSFastIoUnlockSingle: %s %s *** Status: %s (%#x) ***\n", + (PUCHAR) Process + ProcessNameOffset, + "FASTIO_UNLOCK_SINGLE", + FFSNtStatusToString(IoStatus->Status), + IoStatus->Status)); + } +#endif + return Status; +} + + +BOOLEAN NTAPI +FFSFastIoUnlockAll( + IN PFILE_OBJECT FileObject, + IN PEPROCESS Process, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject) +{ + BOOLEAN Status = FALSE; + PFFS_FCB Fcb; + + PAGED_CODE(); + + _SEH2_TRY + { + _SEH2_TRY + { + FsRtlEnterFileSystem(); + + if (DeviceObject == FFSGlobal->DeviceObject) + { + IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST; + Status = TRUE; + _SEH2_LEAVE; + } + + Fcb = (PFFS_FCB)FileObject->FsContext; + + ASSERT(Fcb != NULL); + + if (Fcb->Identifier.Type == FFSVCB) + { + FFSBreakPoint(); + IoStatus->Status = STATUS_INVALID_PARAMETER; + Status = TRUE; + _SEH2_LEAVE; + } + + ASSERT((Fcb->Identifier.Type == FFSFCB) && + (Fcb->Identifier.Size == sizeof(FFS_FCB))); + + if (IsDirectory(Fcb)) + { + FFSBreakPoint(); + IoStatus->Status = STATUS_INVALID_PARAMETER; + Status = TRUE; + _SEH2_LEAVE; + } + + FFSPrint((DBG_INFO, + "FFSFastIoUnlockSingle: %s %s %s\n", + (PUCHAR) Process + ProcessNameOffset, + "FASTIO_UNLOCK_ALL", + Fcb->AnsiFileName.Buffer)); + + IoStatus->Status = FsRtlFastUnlockAll( + &Fcb->FileLockAnchor, + FileObject, + Process, + NULL); + + IoStatus->Information = 0; + + Status = TRUE; + } + _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) + { + IoStatus->Status = _SEH2_GetExceptionCode(); + Status = TRUE; + } _SEH2_END; + } + _SEH2_FINALLY + { + FsRtlExitFileSystem(); + } _SEH2_END; + +#if DBG + if (Status == FALSE) + { + FFSPrint((DBG_ERROR, + "FFSFastIoUnlockSingle: %s %s *** Status: FALSE ***\n", + (PUCHAR) Process + ProcessNameOffset, + "FASTIO_UNLOCK_ALL")); + } + else if (IoStatus->Status != STATUS_SUCCESS) + { + FFSPrint((DBG_ERROR, + "FFSFastIoUnlockSingle: %s %s *** Status: %s (%#x) ***\n", + (PUCHAR) Process + ProcessNameOffset, + "FASTIO_UNLOCK_ALL", + FFSNtStatusToString(IoStatus->Status), + IoStatus->Status)); + } +#endif + return Status; +} + + +BOOLEAN NTAPI +FFSFastIoUnlockAllByKey( + IN PFILE_OBJECT FileObject, +#ifndef __REACTOS__ + IN PEPROCESS Process, +#else + IN PVOID Process, +#endif + IN ULONG Key, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject) +{ + BOOLEAN Status = FALSE; + PFFS_FCB Fcb; + + PAGED_CODE(); + + _SEH2_TRY + { + _SEH2_TRY + { + FsRtlEnterFileSystem(); + + if (DeviceObject == FFSGlobal->DeviceObject) + { + IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST; + Status = TRUE; + _SEH2_LEAVE; + } + + Fcb = (PFFS_FCB)FileObject->FsContext; + + ASSERT(Fcb != NULL); + + if (Fcb->Identifier.Type == FFSVCB) + { + FFSBreakPoint(); + IoStatus->Status = STATUS_INVALID_PARAMETER; + Status = TRUE; + _SEH2_LEAVE; + } + + ASSERT((Fcb->Identifier.Type == FFSFCB) && + (Fcb->Identifier.Size == sizeof(FFS_FCB))); + + if (IsDirectory(Fcb)) + { + FFSBreakPoint(); + IoStatus->Status = STATUS_INVALID_PARAMETER; + Status = TRUE; + _SEH2_LEAVE; + } + + FFSPrint((DBG_INFO, + "FFSFastIoUnlockAllByKey: %s %s %s\n", + (PUCHAR) Process + ProcessNameOffset, + "FASTIO_UNLOCK_ALL_BY_KEY", + Fcb->AnsiFileName.Buffer)); + + FFSPrint((DBG_INFO, + "FFSFastIoUnlockAllByKey: Key: %u\n", + Key)); + + IoStatus->Status = FsRtlFastUnlockAllByKey( + &Fcb->FileLockAnchor, + FileObject, + Process, + Key, + NULL); + + IoStatus->Information = 0; + + Status = TRUE; + } + + _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) + { + IoStatus->Status = _SEH2_GetExceptionCode(); + Status = TRUE; + } _SEH2_END; + } + + _SEH2_FINALLY + { + FsRtlExitFileSystem(); + } _SEH2_END; +#if DBG + if (Status == FALSE) + { + FFSPrint((DBG_ERROR, + "FFSFastIoUnlockAllByKey: %s %s *** Status: FALSE ***\n", + (PUCHAR) Process + ProcessNameOffset, + "FASTIO_UNLOCK_ALL_BY_KEY")); + } + else if (IoStatus->Status != STATUS_SUCCESS) + { + FFSPrint((DBG_ERROR, + "FFSFastIoUnlockAllByKey: %s %s *** Status: %s (%#x) ***\n", + (PUCHAR) Process + ProcessNameOffset, + "FASTIO_UNLOCK_ALL_BY_KEY", + FFSNtStatusToString(IoStatus->Status), + IoStatus->Status)); + } +#endif + return Status; +} diff --git a/reactos/drivers/filesystems/ffs/src/ffs.c b/reactos/drivers/filesystems/ffs/src/ffs.c new file mode 100644 index 00000000000..ab73bab5a4b --- /dev/null +++ b/reactos/drivers/filesystems/ffs/src/ffs.c @@ -0,0 +1,3042 @@ +/* + * FFS File System Driver for Windows + * + * ffs.c + * + * 2004.5.6 ~ + * + * Lee Jae-Hong, http://www.pyrasis.com + * + * See License.txt + * + */ + +#include "ntifs.h" +#include "ffsdrv.h" + + +/* Globals */ +extern PFFS_GLOBAL FFSGlobal; + + +/* Definitions */ + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE, FFSLoadSuper) +#pragma alloc_text(PAGE, FFSSaveSuper) + +#pragma alloc_text(PAGE, FFSLoadGroup) +#pragma alloc_text(PAGE, FFSSaveGroup) + +#pragma alloc_text(PAGE, FFSv1GetInodeLba) +#pragma alloc_text(PAGE, FFSv2GetInodeLba) +#pragma alloc_text(PAGE, FFSv1LoadInode) +#pragma alloc_text(PAGE, FFSv2LoadInode) +#pragma alloc_text(PAGE, FFSv1SaveInode) +#pragma alloc_text(PAGE, FFSv2SaveInode) + +#pragma alloc_text(PAGE, FFSv1LoadBlock) +#pragma alloc_text(PAGE, FFSv2LoadBlock) +#pragma alloc_text(PAGE, FFSSaveBlock) + +#pragma alloc_text(PAGE, FFSSaveBuffer) + +#pragma alloc_text(PAGE, FFSv1GetBlock) +#pragma alloc_text(PAGE, FFSv2GetBlock) +#pragma alloc_text(PAGE, FFSv1BlockMap) +#pragma alloc_text(PAGE, FFSv2BlockMap) + +#pragma alloc_text(PAGE, FFSv1BuildBDL) +#pragma alloc_text(PAGE, FFSv2BuildBDL) + +#pragma alloc_text(PAGE, FFSNewBlock) +#pragma alloc_text(PAGE, FFSFreeBlock) + +#pragma alloc_text(PAGE, FFSExpandBlock) +#pragma alloc_text(PAGE, FFSExpandInode) + +#pragma alloc_text(PAGE, FFSNewInode) +#pragma alloc_text(PAGE, FFSFreeInode) + +#pragma alloc_text(PAGE, FFSAddEntry) +#pragma alloc_text(PAGE, FFSRemoveEntry) + +#pragma alloc_text(PAGE, FFSTruncateBlock) +#pragma alloc_text(PAGE, FFSTruncateInode) + +#pragma alloc_text(PAGE, FFSAddMcbEntry) +#pragma alloc_text(PAGE, FFSRemoveMcbEntry) +#pragma alloc_text(PAGE, FFSLookupMcbEntry) + +#endif + + +PFFS_SUPER_BLOCK +FFSLoadSuper( + IN PFFS_VCB Vcb, + IN BOOLEAN bVerify, + IN ULONGLONG SuperBlockOffset) +{ + NTSTATUS Status; + PFFS_SUPER_BLOCK FFSSb = NULL; + + PAGED_CODE(); + + FFSSb = (PFFS_SUPER_BLOCK)ExAllocatePoolWithTag(PagedPool, SUPER_BLOCK_SIZE, FFS_POOL_TAG); + if (!FFSSb) + { + return NULL; + } + + Status = FFSReadDisk(Vcb, + SuperBlockOffset, + SUPER_BLOCK_SIZE, + (PVOID)FFSSb, + bVerify); + + if (!NT_SUCCESS(Status)) + { + FFSPrint((DBG_ERROR, "FFSLoadSuper: Read Block Device error.\n")); + + ExFreePool(FFSSb); + return NULL; + } + + return FFSSb; +} + +#if !FFS_READ_ONLY + +__drv_mustHoldCriticalRegion +BOOLEAN +FFSSaveSuper( + IN PFFS_IRP_CONTEXT IrpContext, + IN PFFS_VCB Vcb) +{ + LONGLONG Offset; + BOOLEAN bRet; + + PAGED_CODE(); + + Offset = (LONGLONG) SUPER_BLOCK_OFFSET; + + bRet = FFSSaveBuffer(IrpContext, + Vcb, + Offset, + SUPER_BLOCK_SIZE, + Vcb->ffs_super_block); + + if (IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK)) + { + FFSStartFloppyFlushDpc(Vcb, NULL, NULL); + } + + return bRet; +} + +#endif // !FFS_READ_ONLY + +#if 0 +BOOLEAN +FFSLoadGroup( + IN PFFS_VCB Vcb) +{ + ULONG Size; + PVOID Buffer; + LONGLONG Lba; + NTSTATUS Status; + + PFFS_SUPER_BLOCK FFSSb; + + PAGED_CODE(); + + FFSSb = Vcb->ffs_super_block; + + Vcb->BlockSize = FFSSb->fs_bsize; + Vcb->SectorBits = FFSLog2(SECTOR_SIZE); + ASSERT(BLOCK_BITS == FFSLog2(BLOCK_SIZE)); + + Vcb->ffs_groups = (FFSSb->s_blocks_count - FFSSb->s_first_data_block + + FFSSb->s_blocks_per_group - 1) / FFSSb->s_blocks_per_group; + + Size = sizeof(FFS_GROUP_DESC) * Vcb->ffs_groups; + + if (Vcb->BlockSize == MINBSIZE) + { + Lba = (LONGLONG)2 * Vcb->BlockSize; + } + + if (Vcb->BlockSize > MINBSIZE) + { + Lba = (LONGLONG)(Vcb->BlockSize); + } + + if (Lba == 0) + { + return FALSE; + } + + Buffer = ExAllocatePoolWithTag(PagedPool, Size, FFS_POOL_TAG); + if (!Buffer) + { + FFSPrint((DBG_ERROR, "FFSLoadSuper: no enough memory.\n")); + return FALSE; + } + + FFSPrint((DBG_INFO, "FFSLoadGroup: Lba=%I64xh Size=%xh\n", Lba, Size)); + + Status = FFSReadDisk(Vcb, + Lba, + Size, + Buffer, + FALSE); + + if (!NT_SUCCESS(Status)) + { + ExFreePool(Buffer); + Buffer = NULL; + + return FALSE; + } + + Vcb->ffs_group_desc = (PFFS_GROUP_DESC) Buffer; + + return TRUE; +} + + +BOOLEAN +FFSSaveGroup( + IN PFFS_IRP_CONTEXT IrpContext, + IN PFFS_VCB Vcb) +{ + LONGLONG Offset; + ULONG Len; + BOOLEAN bRet; + + PAGED_CODE(); + + if (Vcb->BlockSize == FFS_MIN_BLOCK) { + + Offset = (LONGLONG)(2 * Vcb->BlockSize); + + } else { + + Offset = (LONGLONG)(Vcb->BlockSize); + } + + Len = (ULONG)(sizeof(struct ffs_group_desc) * Vcb->ffs_groups); + + bRet = FFSSaveBuffer(IrpContext, Vcb, Offset, + Len, Vcb->ffs_group_desc); + + if (IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK)) + { + FFSStartFloppyFlushDpc(Vcb, NULL, NULL); + } + + return bRet; +} +#endif + + +BOOLEAN +FFSv1GetInodeLba( + IN PFFS_VCB Vcb, + IN ULONG inode, + OUT PLONGLONG offset) +{ + LONGLONG loc; + + PAGED_CODE(); + +#if 0 + if (inode < 1 || inode > INODES_COUNT) + { + FFSPrint((DBG_ERROR, "FFSv1GetInodeLba: Inode value %xh is invalid.\n",inode)); + *offset = 0; + return FALSE; + } +#endif + + loc = cgimin(Vcb->ffs_super_block, ino_to_cg(Vcb->ffs_super_block, inode)) + * Vcb->ffs_super_block->fs_fsize + ((inode % Vcb->ffs_super_block->fs_ipg) * 128); + + *offset = loc; + KdPrint(("FFSv1GetInodeLba() inode : %d, loc : %x, offset : %x\n", inode, loc, offset)); + + return TRUE; +} + + +BOOLEAN +FFSv2GetInodeLba( + IN PFFS_VCB Vcb, + IN ULONG inode, + OUT PLONGLONG offset) +{ + LONGLONG loc; + + PAGED_CODE(); + +#if 0 + if (inode < 1 || inode > INODES_COUNT) + { + FFSPrint((DBG_ERROR, "FFSv2GetInodeLba: Inode value %xh is invalid.\n",inode)); + *offset = 0; + return FALSE; + } +#endif + + loc = cgimin(Vcb->ffs_super_block, ino_to_cg(Vcb->ffs_super_block, inode)) + * Vcb->ffs_super_block->fs_fsize + ((inode % Vcb->ffs_super_block->fs_ipg) * 256); + + *offset = loc; + //KdPrint(("FFSv2GetInodeLba() inode : %d, loc : %x, offset : %x\n", inode, loc, offset)); + + return TRUE; +} + + +BOOLEAN +FFSv1LoadInode( + IN PFFS_VCB Vcb, + IN ULONG inode, + IN PFFSv1_INODE dinode1) +{ + IO_STATUS_BLOCK IoStatus; + LONGLONG Offset; + + PAGED_CODE(); + + if (!FFSv1GetInodeLba(Vcb, inode, &Offset)) + { + FFSPrint((DBG_ERROR, "FFSv1LoadInode: error get inode(%xh)'s addr.\n", inode)); + return FALSE; + } + + if (!FFSCopyRead( + Vcb->StreamObj, + (PLARGE_INTEGER)&Offset, + DINODE1_SIZE, + PIN_WAIT, + (PVOID)dinode1, + &IoStatus)); + + if (!NT_SUCCESS(IoStatus.Status)) + { + return FALSE; + } + + return TRUE; +} + + +BOOLEAN +FFSv2LoadInode( + IN PFFS_VCB Vcb, + IN ULONG inode, + IN PFFSv2_INODE dinode2) +{ + IO_STATUS_BLOCK IoStatus; + LONGLONG Offset; + + PAGED_CODE(); + + if (!FFSv2GetInodeLba(Vcb, inode, &Offset)) + { + FFSPrint((DBG_ERROR, "FFSv2LoadInode: error get inode(%xh)'s addr.\n", inode)); + return FALSE; + } + + Offset += (LONGLONG)Vcb->FSOffset[Vcb->PartitionNumber]; + + if (!FFSCopyRead( + Vcb->StreamObj, + (PLARGE_INTEGER)&Offset, + DINODE2_SIZE, + PIN_WAIT, + (PVOID)dinode2, + &IoStatus)); + + if (!NT_SUCCESS(IoStatus.Status)) + { + return FALSE; + } + + return TRUE; +} + + +/* +BOOLEAN +FFSSaveInode( + IN PFFS_VCB Vcb, + IN ULONG inode, + IN struct dinode *dinode) +{ + ULONG lba; + ULONG offset; + NTSTATUS Status; + + if (!FFSGetInodeLba(Vcb, inode, &lba, &offset)) + { + FFSPrint((DBG_ERROR, "FFSLoadInode: error get inode(%xh)'s addr.\n", inode)); + return FALSE; + } + + Status = FFSWriteDisk(Vcb->TargetDeviceObject, + lba, + offset, + sizeof(FFS_INODE), + (PVOID)dinode); + + if (!NT_SUCCESS(Status)) + { + return FALSE; + } + + return TRUE; +} +*/ + +#if !FFS_READ_ONLY + +__drv_mustHoldCriticalRegion +BOOLEAN +FFSv1SaveInode( + IN PFFS_IRP_CONTEXT IrpContext, + IN PFFS_VCB Vcb, + IN ULONG Inode, + IN PFFSv1_INODE dinode1) +{ + LONGLONG Offset = 0; + LARGE_INTEGER CurrentTime; + BOOLEAN bRet; + + PAGED_CODE(); + + KeQuerySystemTime(&CurrentTime); + dinode1->di_mtime = dinode1->di_atime = + (ULONG)(FFSInodeTime(CurrentTime)); + + FFSPrint((DBG_INFO, "FFSv1SaveInode: Saving Inode %xh: Mode=%xh Size=%xh\n", + Inode, dinode1->di_mode, dinode1->di_size)); + + if (!FFSv1GetInodeLba(Vcb, Inode, &Offset)) + { + FFSPrint((DBG_ERROR, "FFSv1SaveInode: error get inode(%xh)'s addr.\n", Inode)); + return FALSE; + } + + bRet = FFSSaveBuffer(IrpContext, Vcb, Offset, DINODE1_SIZE, dinode1); + + if (IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK)) + { + FFSStartFloppyFlushDpc(Vcb, NULL, NULL); + } + + return bRet; +} + + +__drv_mustHoldCriticalRegion +BOOLEAN +FFSv2SaveInode( + IN PFFS_IRP_CONTEXT IrpContext, + IN PFFS_VCB Vcb, + IN ULONG Inode, + IN PFFSv2_INODE dinode2) +{ + PAGED_CODE(); + + return FALSE; +} + +#endif // !FFS_READ_ONLY + +BOOLEAN +FFSv1LoadBlock( + IN PFFS_VCB Vcb, + IN ULONG dwBlk, + IN PVOID Buffer) +{ + IO_STATUS_BLOCK IoStatus; + LONGLONG Offset; + + PAGED_CODE(); + + Offset = (LONGLONG) dwBlk; + Offset = Offset * SUPER_BLOCK->fs_fsize; // fragment size + + if (!FFSCopyRead( + Vcb->StreamObj, + (PLARGE_INTEGER)&Offset, + Vcb->BlockSize, + PIN_WAIT, + Buffer, + &IoStatus)); + + if (!NT_SUCCESS(IoStatus.Status)) + { + return FALSE; + } + + return TRUE; +} + + +BOOLEAN +FFSv2LoadBlock( + IN PFFS_VCB Vcb, + IN ULONGLONG dwBlk, + IN PVOID Buffer) +{ + IO_STATUS_BLOCK IoStatus; + LONGLONG Offset; + + PAGED_CODE(); + + Offset = (LONGLONG)dwBlk; + Offset = Offset * SUPER_BLOCK->fs_fsize; // fragment size + + Offset += Vcb->FSOffset[Vcb->PartitionNumber]; + + if (!FFSCopyRead( + Vcb->StreamObj, + (PLARGE_INTEGER)&Offset, + Vcb->BlockSize, + PIN_WAIT, + Buffer, + &IoStatus)); + + if (!NT_SUCCESS(IoStatus.Status)) + { + return FALSE; + } + + return TRUE; +} + +#if !FFS_READ_ONLY + +__drv_mustHoldCriticalRegion +BOOLEAN +FFSSaveBlock( + IN PFFS_IRP_CONTEXT IrpContext, + IN PFFS_VCB Vcb, + IN ULONG dwBlk, + IN PVOID Buf) +{ + LONGLONG Offset; + BOOLEAN bRet; + + PAGED_CODE(); + + Offset = (LONGLONG)dwBlk; + Offset = Offset * Vcb->BlockSize; + + bRet = FFSSaveBuffer(IrpContext, Vcb, Offset, Vcb->BlockSize, Buf); + + if (IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK)) + { + FFSStartFloppyFlushDpc(Vcb, NULL, NULL); + } + + return bRet; +} + + +__drv_mustHoldCriticalRegion +BOOLEAN +FFSSaveBuffer( + IN PFFS_IRP_CONTEXT IrpContext, + IN PFFS_VCB Vcb, + IN LONGLONG Offset, + IN ULONG Size, + IN PVOID Buf) +{ + PBCB Bcb; + PVOID Buffer; + + PAGED_CODE(); + + if(!CcPinRead(Vcb->StreamObj, + (PLARGE_INTEGER) (&Offset), + Size, + PIN_WAIT, + &Bcb, + &Buffer)) + { + FFSPrint((DBG_ERROR, "FFSSaveBuffer: PinReading error ...\n")); + return FALSE; + } + + + /*FFSPrint((DBG_INFO, "FFSSaveBuffer: Off=%I64xh Len=%xh Bcb=%xh\n", + Offset, Size, (ULONG)Bcb));*/ + + RtlCopyMemory(Buffer, Buf, Size); + CcSetDirtyPinnedData(Bcb, NULL); + + FFSRepinBcb(IrpContext, Bcb); + + CcUnpinData(Bcb); + + SetFlag(Vcb->StreamObj->Flags, FO_FILE_MODIFIED); + + FFSAddMcbEntry(Vcb, Offset, (LONGLONG)Size); + + return TRUE; +} + +#endif // !FFS_READ_ONLY + +ULONG +FFSv1GetBlock( + IN PFFS_VCB Vcb, + ULONG dwContent, + ULONG Index, + int layer) +{ + ULONG *pData = NULL; + ULONG i = 0, j = 0, temp = 1; + ULONG dwBlk = 0; + + PAGED_CODE(); + + if (layer == 0) + { + dwBlk = dwContent; + } + else if (layer <= 3) + { + pData = (ULONG *)ExAllocatePoolWithTag(PagedPool, + Vcb->BlockSize, FFS_POOL_TAG); + if (!pData) + { + FFSPrint((DBG_ERROR, "FFSGetBlock: no enough memory.\n")); + return dwBlk; + } + + KdPrint(("FFSGetBlock Index : %d, dwContent : %x, layer : %d\n", Index, dwContent, layer)); + + if (!FFSv1LoadBlock(Vcb, dwContent, pData)) + { + ExFreePool(pData); + return 0; + } + + temp = 1 << ((BLOCK_BITS - 2) * (layer - 1)); + + i = Index / temp; + j = Index % temp; + + dwBlk = pData[i]; + + ExFreePool(pData); + + dwBlk = FFSv1GetBlock(Vcb, dwBlk, j, layer - 1); + } + + return dwBlk; +} + + +ULONGLONG +FFSv2GetBlock( + IN PFFS_VCB Vcb, + ULONGLONG dwContent, + ULONG Index, + int layer) +{ + ULONGLONG *pData = NULL; + ULONG i = 0, j = 0, temp = 1; + ULONGLONG dwBlk = 0; + + PAGED_CODE(); + + if (layer == 0) + { + dwBlk = dwContent; + } + else if (layer <= 3) + { + pData = (ULONGLONG *)ExAllocatePoolWithTag(PagedPool, + Vcb->BlockSize, FFS_POOL_TAG); + if (!pData) + { + FFSPrint((DBG_ERROR, "FFSv2GetBlock: no enough memory.\n")); + return dwBlk; + } + + KdPrint(("FFSv2GetBlock Index : %d, dwContent : %x, layer : %d\n", Index, dwContent, layer)); + + if (!FFSv2LoadBlock(Vcb, dwContent, pData)) + { + ExFreePool(pData); + return 0; + } + + if (Index >= (Vcb->BlockSize / 8) && layer == 2) + temp = 1 << ((BLOCK_BITS - 3) * (layer - 1)); + else + temp = 1 << ((BLOCK_BITS - 2) * (layer - 1)); + + i = Index / temp; + j = Index % temp; + + dwBlk = pData[i]; + + ExFreePool(pData); + + dwBlk = FFSv2GetBlock(Vcb, dwBlk, j, layer - 1); + } + + return dwBlk; +} + + +ULONG +FFSv1BlockMap( + IN PFFS_VCB Vcb, + IN PFFSv1_INODE dinode1, + IN ULONG Index) +{ + ULONG dwSizes[FFS_BLOCK_TYPES]; + int i; + ULONG dwBlk; + ULONG Totalblocks; + + PAGED_CODE(); + + for (i = 0; i < FFS_BLOCK_TYPES; i++) + { + dwSizes[i] = Vcb->dwData[i]; + } + + Totalblocks = (dinode1->di_blocks); + + if (Index >= FFSDataBlocks(Vcb, Totalblocks)) + { + FFSPrint((DBG_ERROR, "FFSv1BlockMap: error input paramters.\n")); + + FFSBreakPoint(); + + return 0; + } + + /* Á÷Á¢, °£Á¢, 2Áß °£Á¢ ó¸® */ + for (i = 0; i < FFS_BLOCK_TYPES; i++) + { + if (Index < dwSizes[i]) + { + if (i == 0) + dwBlk = dinode1->di_db[Index]; /* Á÷Á¢ */ + else + dwBlk = dinode1->di_ib[i - 1]; /* °£Á¢ */ +#if DBG + { + ULONG dwRet = FFSv1GetBlock(Vcb, dwBlk, Index , i); + + KdPrint(("FFSv1BlockMap: i : %d, Index : %d, dwBlk : %x, Data Block : %X\n", i, Index, dwRet, (dwRet * 0x400))); + + return dwRet; + } +#else + return FFSv1GetBlock(Vcb, dwBlk, Index , i); +#endif + } + + Index -= dwSizes[i]; + } + + return 0; +} + + +ULONGLONG +FFSv2BlockMap( + IN PFFS_VCB Vcb, + IN PFFSv2_INODE dinode2, + IN ULONG Index) +{ + ULONG dwSizes[FFS_BLOCK_TYPES]; + int i; + ULONGLONG dwBlk; + ULONG Totalblocks; + + PAGED_CODE(); + + for (i = 0; i < FFS_BLOCK_TYPES; i++) + { + dwSizes[i] = Vcb->dwData[i]; + } + + Totalblocks = (ULONG)(dinode2->di_blocks); + + if (Index >= FFSDataBlocks(Vcb, Totalblocks)) + { + FFSPrint((DBG_ERROR, "FFSv2BlockMap: error input paramters.\n")); + + FFSBreakPoint(); + + return 0; + } + + /* Á÷Á¢, °£Á¢, 2Áß °£Á¢ ó¸® */ + for (i = 0; i < FFS_BLOCK_TYPES; i++) + { + if (Index < dwSizes[i]) + { + if (i == 0) + dwBlk = (ULONGLONG)dinode2->di_db[Index]; /* Á÷Á¢ */ + else + dwBlk = (ULONGLONG)dinode2->di_ib[i - 1]; /* °£Á¢ */ +#if 0 + { + ULONGLONG dwRet = FFSv2GetBlock(Vcb, dwBlk, Index , i); + + KdPrint(("FFSv2BlockMap: i : %d, Index : %d, dwBlk : %x, Data Block : %X\n", i, Index, dwRet, (dwRet * 0x400))); + + return dwRet; + } +#else + return FFSv2GetBlock(Vcb, dwBlk, Index , i); +#endif + } + + Index -= dwSizes[i]; + } + + return 0; +} + + +ULONG +FFSv1BuildBDL( + IN PFFS_IRP_CONTEXT IrpContext, + IN PFFS_VCB Vcb, + IN PFFSv1_INODE dinode1, + IN ULONGLONG Offset, + IN ULONG Size, + OUT PFFS_BDL *ffs_bdl) +{ + ULONG nBeg, nEnd, nBlocks; + ULONG dwBlk, i; + ULONG dwBytes = 0; + LONGLONG Lba; + LONGLONG AllocSize; + ULONG Totalblocks; + + PFFS_BDL ffsbdl; + + PAGED_CODE(); + + *ffs_bdl = NULL; + + + Totalblocks = (dinode1->di_blocks); + AllocSize = FFSDataBlocks(Vcb, Totalblocks); + AllocSize = (AllocSize << BLOCK_BITS); + + if ((LONGLONG)Offset >= AllocSize) + { + FFSPrint((DBG_ERROR, "FFSv1BuildBDL: beyond the file range.\n")); + return 0; + } + + if ((LONGLONG)(Offset + Size) > AllocSize) + { + Size = (ULONG)(AllocSize - Offset); + } + + nBeg = (ULONG)(Offset >> BLOCK_BITS); + nEnd = (ULONG)((Size + Offset + Vcb->BlockSize - 1) >> BLOCK_BITS); + +#if DBG + KdPrint(("FFSv1BuildBDL() Offset : %x\n", Offset)); + KdPrint(("FFSv1BuildBDL() Size : %x\n", Size)); + KdPrint(("FFSv1BuildBDL() nBeg : %d, nEnd : %d\n", nBeg, nEnd)); +#endif + + nBlocks = 0; + + if ((nEnd - nBeg) > 0) + { + ffsbdl = ExAllocatePoolWithTag(PagedPool, sizeof(FFS_BDL) * (nEnd - nBeg), FFS_POOL_TAG); + + if (ffsbdl) + { + RtlZeroMemory(ffsbdl, sizeof(FFS_BDL) * (nEnd - nBeg)); + + for (i = nBeg; i < nEnd; i++) + { + dwBlk = FFSv1BlockMap(Vcb, dinode1, i); + + if (dwBlk > 0) + { + Lba = (LONGLONG)dwBlk; + Lba = Lba * SUPER_BLOCK->fs_fsize; // fragment size + + if (nBeg == nEnd - 1) // ie. (nBeg == nEnd - 1) + { + dwBytes = Size; + ffsbdl[nBlocks].Lba = Lba + (LONGLONG)(Offset % (Vcb->BlockSize)); + ffsbdl[nBlocks].Length = dwBytes; + ffsbdl[nBlocks].Offset = 0; + + nBlocks++; + } + else + { + if (i == nBeg) + { + dwBytes = Vcb->BlockSize - (ULONG)(Offset % (Vcb->BlockSize)); + ffsbdl[nBlocks].Lba = Lba + (LONGLONG)(Offset % (Vcb->BlockSize)); + ffsbdl[nBlocks].Length = dwBytes; + ffsbdl[nBlocks].Offset = 0; + + nBlocks++; + } + else if (i == nEnd - 1) + { + if (ffsbdl[nBlocks - 1].Lba + ffsbdl[nBlocks - 1].Length == Lba) + { + ffsbdl[nBlocks - 1].Length += Size - dwBytes; + } + else + { + ffsbdl[nBlocks].Lba = Lba; + ffsbdl[nBlocks].Length = Size - dwBytes; + ffsbdl[nBlocks].Offset = dwBytes; + nBlocks++; + } + + dwBytes = Size; + + } + else + { + if (ffsbdl[nBlocks - 1].Lba + ffsbdl[nBlocks - 1].Length == Lba) + { + ffsbdl[nBlocks - 1].Length += Vcb->BlockSize; + } + else + { + ffsbdl[nBlocks].Lba = Lba; + ffsbdl[nBlocks].Length = Vcb->BlockSize; + ffsbdl[nBlocks].Offset = dwBytes; + nBlocks++; + } + + dwBytes += Vcb->BlockSize; + } + } + } + else + { + break; + } + } + + *ffs_bdl = ffsbdl; + return nBlocks; + } + } + + // Error + return 0; +} + + +ULONG +FFSv2BuildBDL( + IN PFFS_IRP_CONTEXT IrpContext, + IN PFFS_VCB Vcb, + IN PFFSv2_INODE dinode2, + IN ULONGLONG Offset, + IN ULONG Size, + OUT PFFS_BDL *ffs_bdl) +{ + ULONG nBeg, nEnd, nBlocks; + ULONGLONG dwBlk; + ULONG dwBytes = 0, i; + LONGLONG Lba; + LONGLONG AllocSize; + ULONG Totalblocks; + + PFFS_BDL ffsbdl; + + PAGED_CODE(); + + *ffs_bdl = NULL; + + + Totalblocks = (ULONG)(dinode2->di_blocks); + AllocSize = FFSDataBlocks(Vcb, Totalblocks); + AllocSize = (AllocSize << BLOCK_BITS); + + if ((LONGLONG)Offset >= AllocSize) + { + FFSPrint((DBG_ERROR, "FFSv2BuildBDL: beyond the file range.\n")); + return 0; + } + + if ((LONGLONG)(Offset + Size) > AllocSize) + { + Size = (ULONG)(AllocSize - Offset); + } + + nBeg = (ULONG)(Offset >> BLOCK_BITS); + nEnd = (ULONG)((Size + Offset + Vcb->BlockSize - 1) >> BLOCK_BITS); + +#if 0 + KdPrint(("FFSv2BuildBDL() Offset : %x\n", Offset)); + KdPrint(("FFSv2BuildBDL() Size : %x\n", Size)); + KdPrint(("FFSv2BuildBDL() nBeg : %d, nEnd : %d\n", nBeg, nEnd)); +#endif + + nBlocks = 0; + + if ((nEnd - nBeg) > 0) + { + ffsbdl = ExAllocatePoolWithTag(PagedPool, sizeof(FFS_BDL) * (nEnd - nBeg), FFS_POOL_TAG); + + if (ffsbdl) + { + + RtlZeroMemory(ffsbdl, sizeof(FFS_BDL) * (nEnd - nBeg)); + + for (i = nBeg; i < nEnd; i++) + { + dwBlk = FFSv2BlockMap(Vcb, dinode2, i); + + if (dwBlk > 0) + { + Lba = (LONGLONG)dwBlk; + Lba = Lba * SUPER_BLOCK->fs_fsize; // fragment size + Lba += Vcb->FSOffset[Vcb->PartitionNumber]; + + if (nBeg == nEnd - 1) // ie. (nBeg == nEnd - 1) + { + dwBytes = Size; + ffsbdl[nBlocks].Lba = Lba + (LONGLONG)(Offset % (Vcb->BlockSize)); + ffsbdl[nBlocks].Length = dwBytes; + ffsbdl[nBlocks].Offset = 0; + + nBlocks++; + } + else + { + if (i == nBeg) + { + dwBytes = Vcb->BlockSize - (ULONG)(Offset % (Vcb->BlockSize)); + ffsbdl[nBlocks].Lba = Lba + (LONGLONG)(Offset % (Vcb->BlockSize)); + ffsbdl[nBlocks].Length = dwBytes; + ffsbdl[nBlocks].Offset = 0; + + nBlocks++; + } + else if (i == nEnd - 1) + { + if (ffsbdl[nBlocks - 1].Lba + ffsbdl[nBlocks - 1].Length == Lba) + { + ffsbdl[nBlocks - 1].Length += Size - dwBytes; + } + else + { + ffsbdl[nBlocks].Lba = Lba; + ffsbdl[nBlocks].Length = Size - dwBytes; + ffsbdl[nBlocks].Offset = dwBytes; + nBlocks++; + } + + dwBytes = Size; + + } + else + { + if (ffsbdl[nBlocks - 1].Lba + ffsbdl[nBlocks - 1].Length == Lba) + { + ffsbdl[nBlocks - 1].Length += Vcb->BlockSize; + } + else + { + ffsbdl[nBlocks].Lba = Lba; + ffsbdl[nBlocks].Length = Vcb->BlockSize; + ffsbdl[nBlocks].Offset = dwBytes; + nBlocks++; + } + + dwBytes += Vcb->BlockSize; + } + } + } + else + { + break; + } + } + + *ffs_bdl = ffsbdl; + return nBlocks; + } + } + + // Error + return 0; +} + +#if !FFS_READ_ONLY + +BOOLEAN +FFSNewBlock( + PFFS_IRP_CONTEXT IrpContext, + PFFS_VCB Vcb, + ULONG GroupHint, + ULONG BlockHint, + PULONG dwRet) +{ + RTL_BITMAP BlockBitmap; + LARGE_INTEGER Offset; + ULONG Length; + + PBCB BitmapBcb; + PVOID BitmapCache; + + ULONG Group = 0, dwBlk, dwHint = 0; + + PAGED_CODE(); + +#if 0 + *dwRet = 0; + dwBlk = 0XFFFFFFFF; + + if (GroupHint > Vcb->ffs_groups) + GroupHint = Vcb->ffs_groups - 1; + + if (BlockHint != 0) + { + GroupHint = (BlockHint - FFS_FIRST_DATA_BLOCK) / BLOCKS_PER_GROUP; + dwHint = (BlockHint - FFS_FIRST_DATA_BLOCK) % BLOCKS_PER_GROUP; + } + +ScanBitmap: + + // Perform Prefered Group + if (Vcb->ffs_group_desc[GroupHint].bg_free_blocks_count) + { + Offset.QuadPart = (LONGLONG) Vcb->BlockSize; + Offset.QuadPart = Offset.QuadPart * + Vcb->ffs_group_desc[GroupHint].bg_block_bitmap; + + if (GroupHint == Vcb->ffs_groups - 1) + { + Length = TOTAL_BLOCKS % BLOCKS_PER_GROUP; + + /* s_blocks_count is integer multiple of s_blocks_per_group */ + if (Length == 0) + { + Length = BLOCKS_PER_GROUP; + } + } + else + { + Length = BLOCKS_PER_GROUP; + } + + if (!CcPinRead(Vcb->StreamObj, + &Offset, + Vcb->BlockSize, + PIN_WAIT, + &BitmapBcb, + &BitmapCache)) + { + FFSPrint((DBG_ERROR, "FFSNewBlock: PinReading error ...\n")); + return FALSE; + } + + RtlInitializeBitMap(&BlockBitmap, + BitmapCache, + Length); + + Group = GroupHint; + + if (RtlCheckBit(&BlockBitmap, dwHint) == 0) + { + dwBlk = dwHint; + } + else + { + dwBlk = RtlFindClearBits(&BlockBitmap, 1, dwHint); + } + + // We could not get new block in the prefered group. + if (dwBlk == 0xFFFFFFFF) + { + CcUnpinData(BitmapBcb); + BitmapBcb = NULL; + BitmapCache = NULL; + + RtlZeroMemory(&BlockBitmap, sizeof(RTL_BITMAP)); + } + } + + if (dwBlk == 0xFFFFFFFF) + { + for(Group = 0; Group < Vcb->ffs_groups; Group++) + if (Vcb->ffs_group_desc[Group].bg_free_blocks_count) + { + + if (Group == GroupHint) + continue; + + Offset.QuadPart = (LONGLONG) Vcb->BlockSize; + Offset.QuadPart = Offset.QuadPart * Vcb->ffs_group_desc[Group].bg_block_bitmap; + + if (Vcb->ffs_groups == 1) + { + Length = TOTAL_BLOCKS; + } + else + { + if (Group == Vcb->ffs_groups - 1) + { + Length = TOTAL_BLOCKS % BLOCKS_PER_GROUP; + + /* s_blocks_count is integer multiple of s_blocks_per_group */ + if (Length == 0) + { + Length = BLOCKS_PER_GROUP; + } + } + else + { + Length = BLOCKS_PER_GROUP; + } + } + + if (!CcPinRead(Vcb->StreamObj, + &Offset, + Vcb->BlockSize, + PIN_WAIT, + &BitmapBcb, + &BitmapCache)) + { + FFSPrint((DBG_ERROR, "FFSNewBlock: PinReading error ...\n")); + return FALSE; + } + + RtlInitializeBitMap(&BlockBitmap, + BitmapCache, + Length); + + dwBlk = RtlFindClearBits(&BlockBitmap, 1, 0); + + if (dwBlk != 0xFFFFFFFF) + { + break; + } + else + { + CcUnpinData(BitmapBcb); + BitmapBcb = NULL; + BitmapCache = NULL; + + RtlZeroMemory(&BlockBitmap, sizeof(RTL_BITMAP)); + } + } + } + + if (dwBlk < Length) + { + RtlSetBits(&BlockBitmap, dwBlk, 1); + + CcSetDirtyPinnedData(BitmapBcb, NULL); + + FFSRepinBcb(IrpContext, BitmapBcb); + + CcUnpinData(BitmapBcb); + + FFSAddMcbEntry(Vcb, Offset.QuadPart, (LONGLONG)Vcb->BlockSize); + + *dwRet = dwBlk + FFS_FIRST_DATA_BLOCK + Group * BLOCKS_PER_GROUP; + + //Updating Group Desc / Superblock + Vcb->ffs_group_desc[Group].bg_free_blocks_count--; + FFSSaveGroup(IrpContext, Vcb); + + Vcb->ffs_super_block->s_free_blocks_count--; + FFSSaveSuper(IrpContext, Vcb); + + { + ULONG i = 0; + for (i = 0; i < Vcb->ffs_groups; i++) + { + if ((Vcb->ffs_group_desc[i].bg_block_bitmap == *dwRet) || + (Vcb->ffs_group_desc[i].bg_inode_bitmap == *dwRet) || + (Vcb->ffs_group_desc[i].bg_inode_table == *dwRet)) + { + FFSBreakPoint(); + GroupHint = Group; + goto ScanBitmap; + } + } + } + + return TRUE; + } +#endif + return FALSE; +} + + +BOOLEAN +FFSFreeBlock( + PFFS_IRP_CONTEXT IrpContext, + PFFS_VCB Vcb, + ULONG Block) +{ + RTL_BITMAP BlockBitmap; + LARGE_INTEGER Offset; + ULONG Length; + + PBCB BitmapBcb; + PVOID BitmapCache; + + ULONG Group, dwBlk; + BOOLEAN bModified = FALSE; + + PAGED_CODE(); + +#if 0 + if (Block < FFS_FIRST_DATA_BLOCK || Block > (BLOCKS_PER_GROUP * Vcb->ffs_groups)) + { + FFSBreakPoint(); + return TRUE; + } + + FFSPrint((DBG_INFO, "FFSFreeBlock: Block %xh to be freed.\n", Block)); + + Group = (Block - FFS_FIRST_DATA_BLOCK) / BLOCKS_PER_GROUP; + + dwBlk = (Block - FFS_FIRST_DATA_BLOCK) % BLOCKS_PER_GROUP; + + { + Offset.QuadPart = (LONGLONG) Vcb->BlockSize; + Offset.QuadPart = Offset.QuadPart * Vcb->ffs_group_desc[Group].bg_block_bitmap; + + if (Group == Vcb->ffs_groups - 1) + { + Length = TOTAL_BLOCKS % BLOCKS_PER_GROUP; + + /* s_blocks_count is integer multiple of s_blocks_per_group */ + if (Length == 0) + { + Length = BLOCKS_PER_GROUP; + } + } + else + { + Length = BLOCKS_PER_GROUP; + } + + if (!CcPinRead(Vcb->StreamObj, + &Offset, + Vcb->BlockSize, + PIN_WAIT, + &BitmapBcb, + &BitmapCache)) + { + FFSPrint((DBG_ERROR, "FFSDeleteBlock: PinReading error ...\n")); + return FALSE; + } + + RtlInitializeBitMap(&BlockBitmap, + BitmapCache, + Length); + + if (RtlCheckBit(&BlockBitmap, dwBlk) == 0) + { + + } + else + { + RtlClearBits(&BlockBitmap, dwBlk, 1); + bModified = TRUE; + } + + if (!bModified) + { + CcUnpinData(BitmapBcb); + BitmapBcb = NULL; + BitmapCache = NULL; + + RtlZeroMemory(&BlockBitmap, sizeof(RTL_BITMAP)); + } + } + + if (bModified) + { + CcSetDirtyPinnedData(BitmapBcb, NULL); + + FFSRepinBcb(IrpContext, BitmapBcb); + + CcUnpinData(BitmapBcb); + + FFSAddMcbEntry(Vcb, Offset.QuadPart, (LONGLONG)Vcb->BlockSize); + + //Updating Group Desc / Superblock + Vcb->ffs_group_desc[Group].bg_free_blocks_count++; + FFSSaveGroup(IrpContext, Vcb); + + Vcb->ffs_super_block->s_free_blocks_count++; + FFSSaveSuper(IrpContext, Vcb); + + return TRUE; + } +#endif + return FALSE; +} + + +__drv_mustHoldCriticalRegion +BOOLEAN +FFSExpandBlock( + PFFS_IRP_CONTEXT IrpContext, + PFFS_VCB Vcb, + PFFS_FCB Fcb, + ULONG dwContent, + ULONG Index, + ULONG layer, + BOOLEAN bNew, + ULONG *dwRet) +{ + ULONG *pData = NULL; + ULONG i = 0, j = 0, temp = 1; + ULONG dwNewBlk = 0, dwBlk = 0; + BOOLEAN bDirty = FALSE; + BOOLEAN bRet = TRUE; + + PFFSv1_INODE dinode1 = Fcb->dinode1; + PFFS_SUPER_BLOCK FFSSb = Vcb->ffs_super_block; + + PAGED_CODE(); + + pData = (ULONG *)ExAllocatePoolWithTag(PagedPool, Vcb->BlockSize, FFS_POOL_TAG); + + if (!pData) + { + return FALSE; + } + + RtlZeroMemory(pData, Vcb->BlockSize); + + if (bNew) + { + if (layer == 0) + { + if (IsDirectory(Fcb)) + { + PFFS_DIR_ENTRY pEntry; + + pEntry = (PFFS_DIR_ENTRY) pData; + pEntry->d_reclen = (USHORT)(Vcb->BlockSize); + + if (!FFSSaveBlock(IrpContext, Vcb, dwContent, (PVOID)pData)) + { + bRet = FALSE; + goto errorout; + } + } + else + { + LARGE_INTEGER Offset; + + Offset.QuadPart = (LONGLONG)dwContent; + Offset.QuadPart = Offset.QuadPart * Vcb->BlockSize; + + FFSRemoveMcbEntry(Vcb, Offset.QuadPart, (LONGLONG)Vcb->BlockSize); + } + } + else + { + if (!FFSSaveBlock(IrpContext, Vcb, dwContent, (PVOID)pData)) + { + bRet = FALSE; + goto errorout; + } + } + } + + if (layer == 0) + { + dwNewBlk = dwContent; + } + else if (layer <= 3) + { + if (!bNew) + { + bRet = FFSv1LoadBlock(Vcb, dwContent, (void *)pData); + if (!bRet) goto errorout; + } + + temp = 1 << ((BLOCK_BITS - 2) * (layer - 1)); + + i = Index / temp; + j = Index % temp; + + dwBlk = pData[i]; + + if (dwBlk == 0) + { + if (!FFSNewBlock(IrpContext, + Vcb, 0, + dwContent, + &dwBlk)) + { + bRet = FALSE; + FFSPrint((DBG_ERROR, "FFSExpandBlock: get new block error.\n")); + goto errorout; + } + + dinode1->di_blocks += (Vcb->BlockSize / SECTOR_SIZE); + + pData[i] = dwBlk; + bDirty = TRUE; + } + + if (!FFSExpandBlock(IrpContext, + Vcb, Fcb, + dwBlk, j, + layer - 1, + bDirty, + &dwNewBlk)) + { + bRet = FALSE; + FFSPrint((DBG_ERROR, "FFSExpandBlockk: ... error recuise...\n")); + goto errorout; + } + + if (bDirty) + { + bRet = FFSSaveBlock(IrpContext, + Vcb, dwContent, + (void *)pData); + } + } + +errorout: + + if (pData) + ExFreePool(pData); + + if (bRet && dwRet) + *dwRet = dwNewBlk; + + return bRet; +} + + +BOOLEAN +FFSExpandInode( + PFFS_IRP_CONTEXT IrpContext, + PFFS_VCB Vcb, + PFFS_FCB Fcb, + ULONG *dwRet) +{ + ULONG dwSizes[FFS_BLOCK_TYPES]; + ULONG Index = 0; + ULONG dwTotal = 0; + ULONG dwBlk = 0, dwNewBlk = 0; + ULONG i; + BOOLEAN bRet = FALSE; + BOOLEAN bNewBlock = FALSE; + + PFFSv1_INODE dinode1 = Fcb->dinode1; + + PAGED_CODE(); + + Index = (ULONG)(Fcb->Header.AllocationSize.QuadPart >> BLOCK_BITS); + + for (i = 0; i < FFS_BLOCK_TYPES; i++) + { + dwSizes[i] = Vcb->dwData[i]; + dwTotal += dwSizes[i]; + } + + if (Index >= dwTotal) + { + FFSPrint((DBG_ERROR, "FFSExpandInode: beyond the maxinum size of an inode.\n")); + return FALSE; + } + + for (i = 0; i < FFS_BLOCK_TYPES; i++) + { + if (Index < dwSizes[i]) + { + dwBlk = dinode1->di_db[i == 0 ? (Index) : (i + NDADDR - 1)]; + if (dwBlk == 0) + { + if (!FFSNewBlock(IrpContext, + Vcb, + Fcb->BlkHint ? 0 : ((Fcb->FFSMcb->Inode - 1) / INODES_PER_GROUP), + Fcb->BlkHint, + &dwBlk)) + { + FFSPrint((DBG_ERROR, "FFSExpandInode: get new block error.\n")); + break; + } + + dinode1->di_ib[i == 0 ? (Index):(i + NDADDR - 1)] = dwBlk; + + dinode1->di_blocks += (Vcb->BlockSize / SECTOR_SIZE); + + bNewBlock = TRUE; + } + + bRet = FFSExpandBlock(IrpContext, + Vcb, Fcb, + dwBlk, Index, + i, bNewBlock, + &dwNewBlk); + + if (bRet) + { + Fcb->Header.AllocationSize.QuadPart += Vcb->BlockSize; + } + + break; + } + + Index -= dwSizes[i]; + } + + { + ASSERT(FFSDataBlocks(Vcb, (ULONG)(dinode1->di_blocks / (BLOCK_SIZE / SECTOR_SIZE))) + == (Fcb->Header.AllocationSize.QuadPart / BLOCK_SIZE)); + + ASSERT(FFSTotalBlocks(Vcb, (ULONG)(Fcb->Header.AllocationSize.QuadPart / BLOCK_SIZE)) + == (dinode1->di_blocks / (BLOCK_SIZE / SECTOR_SIZE))); + } + + + FFSv1SaveInode(IrpContext, Vcb, Fcb->FFSMcb->Inode, dinode1); + + if (bRet && dwNewBlk) + { + if (dwRet) + { + Fcb->BlkHint = dwNewBlk+1; + *dwRet = dwNewBlk; + + FFSPrint((DBG_INFO, "FFSExpandInode: %S (%xh) i=%2.2xh Index=%8.8xh New Block=%8.8xh\n", Fcb->FFSMcb->ShortName.Buffer, Fcb->FFSMcb->Inode, i, Index, dwNewBlk)); + } + + return TRUE; + } + + return FALSE; +} + + +NTSTATUS +FFSNewInode( + PFFS_IRP_CONTEXT IrpContext, + PFFS_VCB Vcb, + ULONG GroupHint, + ULONG Type, + PULONG Inode) +{ + RTL_BITMAP InodeBitmap; + PVOID BitmapCache; + PBCB BitmapBcb; + + ULONG Group, i, j; + ULONG Average, Length; + LARGE_INTEGER Offset; + + ULONG dwInode; + + PAGED_CODE(); + +#if 0 + *Inode = dwInode = 0XFFFFFFFF; + +repeat: + + Group = i = 0; + + if (Type == DT_DIR) + { + Average = Vcb->ffs_super_block->s_free_inodes_count / Vcb->ffs_groups; + + for (j = 0; j < Vcb->ffs_groups; j++) + { + i = (j + GroupHint) % (Vcb->ffs_groups); + + if ((Vcb->ffs_group_desc[i].bg_used_dirs_count << 8) < + Vcb->ffs_group_desc[i].bg_free_inodes_count) + { + Group = i + 1; + break; + } + } + + if (!Group) + { + for (j = 0; j < Vcb->ffs_groups; j++) + { + if (Vcb->ffs_group_desc[j].bg_free_inodes_count >= Average) + { + if (!Group || (Vcb->ffs_group_desc[j].bg_free_blocks_count > Vcb->ffs_group_desc[Group].bg_free_blocks_count)) + Group = j + 1; + } + } + } + } + else + { + /* + * Try to place the inode in its parent directory (GroupHint) + */ + if (Vcb->ffs_group_desc[GroupHint].bg_free_inodes_count) + { + Group = GroupHint + 1; + } + else + { + i = GroupHint; + + /* + * Use a quadratic hash to find a group with a + * free inode + */ + for (j = 1; j < Vcb->ffs_groups; j <<= 1) + { + + i += j; + if (i > Vcb->ffs_groups) + i -= Vcb->ffs_groups; + + if (Vcb->ffs_group_desc[i].bg_free_inodes_count) + { + Group = i + 1; + break; + } + } + } + + if (!Group) { + /* + * That failed: try linear search for a free inode + */ + i = GroupHint + 1; + for (j = 2; j < Vcb->ffs_groups; j++) + { + if (++i >= Vcb->ffs_groups) i = 0; + + if (Vcb->ffs_group_desc[i].bg_free_inodes_count) + { + Group = i + 1; + break; + } + } + } + } + + // Could not find a proper group. + if (!Group) + { + return STATUS_DISK_FULL; + } + else + { + Group--; + + Offset.QuadPart = (LONGLONG) Vcb->BlockSize; + Offset.QuadPart = Offset.QuadPart * Vcb->ffs_group_desc[Group].bg_inode_bitmap; + + if (Vcb->ffs_groups == 1) + { + Length = INODES_COUNT; + } + else + { + if (Group == Vcb->ffs_groups - 1) + { + Length = INODES_COUNT % INODES_PER_GROUP; + if (!Length) + { + /* INODES_COUNT is integer multiple of INODES_PER_GROUP */ + Length = INODES_PER_GROUP; + } + } + else + { + Length = INODES_PER_GROUP; + } + } + + if (!CcPinRead(Vcb->StreamObj, + &Offset, + Vcb->BlockSize, + PIN_WAIT, + &BitmapBcb, + &BitmapCache)) + { + FFSPrint((DBG_ERROR, "FFSNewInode: PinReading error ...\n")); + + return STATUS_UNSUCCESSFUL; + } + + RtlInitializeBitMap(&InodeBitmap, + BitmapCache, + Length); + + dwInode = RtlFindClearBits(&InodeBitmap, 1, 0); + + if (dwInode == 0xFFFFFFFF) + { + CcUnpinData(BitmapBcb); + BitmapBcb = NULL; + BitmapCache = NULL; + + RtlZeroMemory(&InodeBitmap, sizeof(RTL_BITMAP)); + } + } + + if (dwInode == 0xFFFFFFFF || dwInode >= Length) + { + if (Vcb->ffs_group_desc[Group].bg_free_inodes_count != 0) + { + Vcb->ffs_group_desc[Group].bg_free_inodes_count = 0; + + FFSSaveGroup(IrpContext, Vcb); + } + + goto repeat; + } + else + { + RtlSetBits(&InodeBitmap, dwInode, 1); + + CcSetDirtyPinnedData(BitmapBcb, NULL); + + FFSRepinBcb(IrpContext, BitmapBcb); + + CcUnpinData(BitmapBcb); + + FFSAddMcbEntry(Vcb, Offset.QuadPart, (LONGLONG)Vcb->BlockSize); + + *Inode = dwInode + 1 + Group * INODES_PER_GROUP; + + //Updating Group Desc / Superblock + Vcb->ffs_group_desc[Group].bg_free_inodes_count--; + if (Type == FFS_FT_DIR) + { + Vcb->ffs_group_desc[Group].bg_used_dirs_count++; + } + + FFSSaveGroup(IrpContext, Vcb); + + Vcb->ffs_super_block->s_free_inodes_count--; + FFSSaveSuper(IrpContext, Vcb); + + return STATUS_SUCCESS; + } + + return STATUS_DISK_FULL; +#endif + return STATUS_UNSUCCESSFUL; +} + + +BOOLEAN +FFSFreeInode( + PFFS_IRP_CONTEXT IrpContext, + PFFS_VCB Vcb, + ULONG Inode, + ULONG Type) +{ + RTL_BITMAP InodeBitmap; + PVOID BitmapCache; + PBCB BitmapBcb; + + ULONG Group; + ULONG Length; + LARGE_INTEGER Offset; + + ULONG dwIno; + BOOLEAN bModified = FALSE; + + PAGED_CODE(); + +#if 0 + Group = (Inode - 1) / INODES_PER_GROUP; + dwIno = (Inode - 1) % INODES_PER_GROUP; + + FFSPrint((DBG_INFO, "FFSFreeInode: Inode: %xh (Group/Off = %xh/%xh)\n", + Inode, Group, dwIno)); + + { + Offset.QuadPart = (LONGLONG) Vcb->BlockSize; + Offset.QuadPart = Offset.QuadPart * Vcb->ffs_group_desc[Group].bg_inode_bitmap; + if (Group == Vcb->ffs_groups - 1) + { + Length = INODES_COUNT % INODES_PER_GROUP; + if (!Length) + { /* s_inodes_count is integer multiple of s_inodes_per_group */ + Length = INODES_PER_GROUP; + } + } + else + { + Length = INODES_PER_GROUP; + } + + if (!CcPinRead(Vcb->StreamObj, + &Offset, + Vcb->BlockSize, + PIN_WAIT, + &BitmapBcb, + &BitmapCache)) + { + FFSPrint((DBG_ERROR, "FFSFreeInode: PinReading error ...\n")); + return FALSE; + } + + RtlInitializeBitMap(&InodeBitmap, + BitmapCache, + Length); + + if (RtlCheckBit(&InodeBitmap, dwIno) == 0) + { + + } + else + { + RtlClearBits(&InodeBitmap, dwIno, 1); + bModified = TRUE; + } + + if (!bModified) + { + CcUnpinData(BitmapBcb); + BitmapBcb = NULL; + BitmapCache = NULL; + + RtlZeroMemory(&InodeBitmap, sizeof(RTL_BITMAP)); + } + } + + if (bModified) + { + CcSetDirtyPinnedData(BitmapBcb, NULL); + + FFSRepinBcb(IrpContext, BitmapBcb); + + CcUnpinData(BitmapBcb); + + FFSAddMcbEntry(Vcb, Offset.QuadPart, (LONGLONG)Vcb->BlockSize); + + //Updating Group Desc / Superblock + if (Type == DT_DIR) + { + Vcb->ffs_group_desc[Group].bg_used_dirs_count--; + } + + Vcb->ffs_group_desc[Group].bg_free_inodes_count++; + FFSSaveGroup(IrpContext, Vcb); + + Vcb->ffs_super_block->s_free_inodes_count++; + FFSSaveSuper(IrpContext, Vcb); + + return TRUE; + } +#endif + return FALSE; +} + + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSAddEntry( + IN PFFS_IRP_CONTEXT IrpContext, + IN PFFS_VCB Vcb, + IN PFFS_FCB Dcb, + IN ULONG FileType, + IN ULONG Inode, + IN PUNICODE_STRING FileName) +{ + NTSTATUS Status = STATUS_UNSUCCESSFUL; + + PFFS_DIR_ENTRY pDir = NULL; + PFFS_DIR_ENTRY pNewDir = NULL; + PFFS_DIR_ENTRY pTarget = NULL; + + ULONG Length = 0; + ULONG dwBytes = 0; + + BOOLEAN bFound = FALSE; + BOOLEAN bAdding = FALSE; + + BOOLEAN MainResourceAcquired = FALSE; + + ULONG dwRet; + + PAGED_CODE(); + + if (!IsDirectory(Dcb)) + { + FFSBreakPoint(); + Status = STATUS_INVALID_PARAMETER; + return Status; + } + + MainResourceAcquired = ExAcquireResourceExclusiveLite(&Dcb->MainResource, TRUE); + + _SEH2_TRY + { + Dcb->ReferenceCount++; + + pDir = (PFFS_DIR_ENTRY)ExAllocatePoolWithTag(PagedPool, + FFS_DIR_REC_LEN(FFS_NAME_LEN), FFS_POOL_TAG); + if (!pDir) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + _SEH2_LEAVE; + } + + pTarget = (PFFS_DIR_ENTRY)ExAllocatePoolWithTag(PagedPool, + 2 * FFS_DIR_REC_LEN(FFS_NAME_LEN), FFS_POOL_TAG); + if (!pTarget) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + _SEH2_LEAVE; + } + +#if 0 + if (IsFlagOn(SUPER_BLOCK->s_feature_incompat, + FFS_FEATURE_INCOMPAT_FILETYPE)) + { + pDir->d_type = (UCHAR)FileType; + } + else +#endif + { + pDir->d_type = 0; + } + + { + OEM_STRING OemName; + OemName.Buffer = pDir->d_name; + OemName.MaximumLength = FFS_NAME_LEN; + OemName.Length = 0; + + Status = FFSUnicodeToOEM(&OemName, FileName); + + if (!NT_SUCCESS(Status)) + { + _SEH2_LEAVE; + } + + pDir->d_namlen = (CCHAR)OemName.Length; + } + + pDir->d_ino = Inode; + pDir->d_reclen = (USHORT)(FFS_DIR_REC_LEN(pDir->d_namlen)); + + dwBytes = 0; + +Repeat: + + while ((LONGLONG)dwBytes < Dcb->Header.AllocationSize.QuadPart) + { + RtlZeroMemory(pTarget, FFS_DIR_REC_LEN(FFS_NAME_LEN)); + + // Reading the DCB contents + Status = FFSv1ReadInode( + NULL, + Vcb, + Dcb->dinode1, + dwBytes, + (PVOID)pTarget, + FFS_DIR_REC_LEN(FFS_NAME_LEN), + &dwRet); + + if (!NT_SUCCESS(Status)) + { + FFSPrint((DBG_ERROR, "FFSAddDirectory: Reading Directory Content error.\n")); + _SEH2_LEAVE; + } + + if (((pTarget->d_ino == 0) && pTarget->d_reclen >= pDir->d_reclen) || + (pTarget->d_reclen >= FFS_DIR_REC_LEN(pTarget->d_namlen) + pDir->d_reclen)) + { + if (pTarget->d_ino) + { + RtlZeroMemory(pTarget, 2 * FFS_DIR_REC_LEN(FFS_NAME_LEN)); + + // Reading the DCB contents + Status = FFSv1ReadInode( + NULL, + Vcb, + Dcb->dinode1, + dwBytes, + (PVOID)pTarget, + 2 * FFS_DIR_REC_LEN(FFS_NAME_LEN), + &dwRet); + + if (!NT_SUCCESS(Status)) + { + FFSPrint((DBG_ERROR, "FFSAddDirectory: Reading Directory Content error.\n")); + _SEH2_LEAVE; + } + + Length = FFS_DIR_REC_LEN(pTarget->d_namlen); + + pNewDir = (PFFS_DIR_ENTRY) ((PUCHAR)pTarget + FFS_DIR_REC_LEN(pTarget->d_namlen)); + + pNewDir->d_reclen = pTarget->d_reclen - FFS_DIR_REC_LEN(pTarget->d_namlen); + + pTarget->d_reclen = FFS_DIR_REC_LEN(pTarget->d_namlen); + } + else + { + pNewDir = pTarget; + pNewDir->d_reclen = (USHORT)((ULONG)(Dcb->Header.AllocationSize.QuadPart) - dwBytes); + } + + pNewDir->d_type = pDir->d_type; + pNewDir->d_ino = pDir->d_ino; + pNewDir->d_namlen = pDir->d_namlen; + memcpy(pNewDir->d_name, pDir->d_name, pDir->d_namlen); + Length += FFS_DIR_REC_LEN(pDir->d_namlen); + + bFound = TRUE; + break; + } + + dwBytes += pTarget->d_reclen; + } + + if (bFound) + { + ULONG dwRet; + + if (FileType == DT_DIR) + { + if(((pDir->d_namlen == 1) && (pDir->d_name[0] == '.')) || + ((pDir->d_namlen == 2) && (pDir->d_name[0] == '.') && (pDir->d_name[1] == '.'))) + { + } + else + { + Dcb->dinode1->di_nlink++; + } + } + + Status = FFSv1WriteInode(IrpContext, Vcb, Dcb->dinode1, dwBytes, pTarget, Length, FALSE, &dwRet); + } + else + { + // We should expand the size of the dir inode + if (!bAdding) + { + ULONG dwRet; + + bAdding = FFSExpandInode(IrpContext, Vcb, Dcb, &dwRet); + + if (bAdding) + { + + Dcb->dinode1->di_size = Dcb->Header.AllocationSize.LowPart; + + FFSv1SaveInode(IrpContext, Vcb, Dcb->FFSMcb->Inode, Dcb->dinode1); + + Dcb->Header.FileSize = Dcb->Header.AllocationSize; + + goto Repeat; + } + + _SEH2_LEAVE; + + } + else // Something must be error! + { + _SEH2_LEAVE; + } + } + } + + _SEH2_FINALLY + { + + Dcb->ReferenceCount--; + + if(MainResourceAcquired) + { + ExReleaseResourceForThreadLite( + &Dcb->MainResource, + ExGetCurrentResourceThread()); + } + + if (pTarget != NULL) + { + ExFreePool(pTarget); + } + + if (pDir) + { + ExFreePool(pDir); + } + } _SEH2_END; + + return Status; +} + + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSRemoveEntry( + IN PFFS_IRP_CONTEXT IrpContext, + IN PFFS_VCB Vcb, + IN PFFS_FCB Dcb, + IN ULONG FileType, + IN ULONG Inode) +{ + NTSTATUS Status = STATUS_UNSUCCESSFUL; + + PFFS_DIR_ENTRY pTarget = NULL; + PFFS_DIR_ENTRY pPrevDir = NULL; + + USHORT PrevRecLen = 0; + + ULONG Length = 0; + ULONG dwBytes = 0; + + BOOLEAN bRet = FALSE; + BOOLEAN MainResourceAcquired = FALSE; + + ULONG dwRet; + + PAGED_CODE(); + + if (!IsDirectory(Dcb)) + { + return FALSE; + } + + MainResourceAcquired = + ExAcquireResourceExclusiveLite(&Dcb->MainResource, TRUE); + + _SEH2_TRY + { + + Dcb->ReferenceCount++; + + pTarget = (PFFS_DIR_ENTRY)ExAllocatePoolWithTag(PagedPool, + FFS_DIR_REC_LEN(FFS_NAME_LEN), FFS_POOL_TAG); + if (!pTarget) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + _SEH2_LEAVE; + } + + pPrevDir = (PFFS_DIR_ENTRY)ExAllocatePoolWithTag(PagedPool, + FFS_DIR_REC_LEN(FFS_NAME_LEN), FFS_POOL_TAG); + if (!pPrevDir) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + _SEH2_LEAVE; + } + + dwBytes = 0; + + while ((LONGLONG)dwBytes < Dcb->Header.AllocationSize.QuadPart) + { + RtlZeroMemory(pTarget, FFS_DIR_REC_LEN(FFS_NAME_LEN)); + + Status = FFSv1ReadInode( + NULL, + Vcb, + Dcb->dinode1, + dwBytes, + (PVOID)pTarget, + FFS_DIR_REC_LEN(FFS_NAME_LEN), + &dwRet); + + if (!NT_SUCCESS(Status)) + { + FFSPrint((DBG_ERROR, "FFSRemoveEntry: Reading Directory Content error.\n")); + _SEH2_LEAVE; + } + + if (pTarget->d_ino == Inode) + { + ULONG dwRet; + ULONG RecLen; + + if ((PrevRecLen + pTarget->d_reclen) < MAXIMUM_RECORD_LENGTH) + { + pPrevDir->d_reclen += pTarget->d_reclen; + RecLen = FFS_DIR_REC_LEN(pTarget->d_namlen); + + RtlZeroMemory(pTarget, RecLen); + + FFSv1WriteInode(IrpContext, Vcb, Dcb->dinode1, dwBytes - PrevRecLen, pPrevDir, 8, FALSE, &dwRet); + FFSv1WriteInode(IrpContext, Vcb, Dcb->dinode1, dwBytes, pTarget, RecLen, FALSE, &dwRet); + } + else + { + RecLen = (ULONG)pTarget->d_reclen; + if (RecLen > FFS_DIR_REC_LEN(FFS_NAME_LEN)) + { + RtlZeroMemory(pTarget, FFS_DIR_REC_LEN(FFS_NAME_LEN)); + } + else + { + RtlZeroMemory(pTarget, RecLen); + } + + pTarget->d_reclen = (USHORT)RecLen; + + FFSv1WriteInode(IrpContext, Vcb, Dcb->dinode1, dwBytes, pTarget, RecLen, FALSE, &dwRet); + } + + if (FileType == DT_DIR) + { + if(((pTarget->d_namlen == 1) && (pTarget->d_name[0] == '.')) || + ((pTarget->d_namlen == 2) && (pTarget->d_name[0] == '.') && (pTarget->d_name[1] == '.'))) + { + FFSBreakPoint(); + } + else + { + Dcb->dinode1->di_nlink--; + } + } + + /* Update at least mtime/atime if !FFS_FT_DIR. */ + FFSv1SaveInode(IrpContext, Vcb, Dcb->FFSMcb->Inode, Dcb->dinode1); + + bRet = TRUE; + + break; + } + else + { + RtlCopyMemory(pPrevDir, pTarget, FFS_DIR_REC_LEN(FFS_NAME_LEN)); + PrevRecLen = pTarget->d_reclen; + } + + dwBytes += pTarget->d_reclen; + } + } + + _SEH2_FINALLY + { + + Dcb->ReferenceCount--; + + if(MainResourceAcquired) + ExReleaseResourceForThreadLite( + &Dcb->MainResource, + ExGetCurrentResourceThread()); + + if (pTarget != NULL) + { + ExFreePool(pTarget); + } + + if (pPrevDir != NULL) + { + ExFreePool(pPrevDir); + } + } _SEH2_END; + + return bRet; +} + + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSSetParentEntry( + IN PFFS_IRP_CONTEXT IrpContext, + IN PFFS_VCB Vcb, + IN PFFS_FCB Dcb, + IN ULONG OldParent, + IN ULONG NewParent) +{ + NTSTATUS Status = STATUS_UNSUCCESSFUL; + + PFFS_DIR_ENTRY pSelf = NULL; + PFFS_DIR_ENTRY pParent = NULL; + + ULONG dwBytes = 0; + + BOOLEAN MainResourceAcquired = FALSE; + + ULONG Offset = 0; + + if (!IsDirectory(Dcb)) + { + Status = STATUS_INVALID_PARAMETER; + return Status; + } + + MainResourceAcquired = + ExAcquireResourceExclusiveLite(&Dcb->MainResource, TRUE); + + _SEH2_TRY + { + Dcb->ReferenceCount++; + + pSelf = (PFFS_DIR_ENTRY)ExAllocatePoolWithTag(PagedPool, + FFS_DIR_REC_LEN(1) + FFS_DIR_REC_LEN(2), FFS_POOL_TAG); + if (!pSelf) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + _SEH2_LEAVE; + } + + dwBytes = 0; + + // Reading the DCB contents + Status = FFSv1ReadInode( + NULL, + Vcb, + Dcb->dinode1, + Offset, + (PVOID)pSelf, + FFS_DIR_REC_LEN(1) + FFS_DIR_REC_LEN(2), + &dwBytes); + + if (!NT_SUCCESS(Status)) + { + FFSPrint((DBG_ERROR, "FFSSetParentEntry: Reading Directory Content error.\n")); + _SEH2_LEAVE; + } + + ASSERT(dwBytes == FFS_DIR_REC_LEN(1) + FFS_DIR_REC_LEN(2)); + + pParent = (PFFS_DIR_ENTRY)((PUCHAR)pSelf + pSelf->d_reclen); + + if (pParent->d_ino != OldParent) + { + FFSBreakPoint(); + } + + pParent->d_ino = NewParent; + + Status = FFSv1WriteInode(IrpContext, + Vcb, + Dcb->dinode1, + Offset, + pSelf, + dwBytes, + FALSE, + &dwBytes); + } + + _SEH2_FINALLY + { + Dcb->ReferenceCount--; + + if(MainResourceAcquired) + { + ExReleaseResourceForThreadLite( + &Dcb->MainResource, + ExGetCurrentResourceThread()); + } + + if (pSelf) + { + ExFreePool(pSelf); + } + } _SEH2_END; + + return Status; +} + + +__drv_mustHoldCriticalRegion +BOOLEAN +FFSTruncateBlock( + IN PFFS_IRP_CONTEXT IrpContext, + IN PFFS_VCB Vcb, + IN PFFS_FCB Fcb, + IN ULONG dwContent, + IN ULONG Index, + IN ULONG layer, + OUT BOOLEAN *bFreed) +{ + ULONG *pData = NULL; + ULONG i = 0, j = 0, temp = 1; + BOOLEAN bDirty = FALSE; + BOOLEAN bRet = FALSE; + ULONG dwBlk; + + LONGLONG Offset; + + PBCB Bcb; + + PFFSv1_INODE dinode1 = Fcb->dinode1; + + PAGED_CODE(); + + *bFreed = FALSE; + + if (layer == 0) + { + //if (dwContent > 0 && dwContent < (BLOCKS_PER_GROUP * Vcb->ffs_groups)) + if (dwContent > 0) + { + bRet = FFSFreeBlock(IrpContext, Vcb, dwContent); + + if (bRet) + { + ASSERT(dinode1->di_blocks >= (Vcb->BlockSize / SECTOR_SIZE)); + dinode1->di_blocks -= (Vcb->BlockSize / SECTOR_SIZE); + } + } + else + { + FFSBreakPoint(); + bRet = FALSE; + } + + *bFreed = bRet; + } + else if (layer <= 3) + { + Offset = (LONGLONG)dwContent; + Offset = Offset * Vcb->BlockSize; + + if(!CcPinRead(Vcb->StreamObj, + (PLARGE_INTEGER)(&Offset), + Vcb->BlockSize, + PIN_WAIT, + &Bcb, + &pData)) + { + FFSPrint((DBG_ERROR, "FFSSaveBuffer: PinReading error ...\n")); + goto errorout; + } + + temp = 1 << ((BLOCK_BITS - 2) * (layer - 1)); + + i = Index / temp; + j = Index % temp; + + dwBlk = pData[i]; + + if(!FFSTruncateBlock(IrpContext, Vcb, Fcb, dwBlk, j, layer - 1, &bDirty)) + { + goto errorout; + } + + if (bDirty) + { + pData[i] = 0; + } + + if (i == 0 && j == 0) + { + CcUnpinData(Bcb); + pData = NULL; + + *bFreed = TRUE; + bRet = FFSFreeBlock(IrpContext, Vcb, dwContent); + + if (bRet) + { + ASSERT(dinode1->di_blocks >= (Vcb->BlockSize / SECTOR_SIZE)); + dinode1->di_blocks -= (Vcb->BlockSize / SECTOR_SIZE); + } + } + else + { + CcSetDirtyPinnedData(Bcb, NULL); + FFSRepinBcb(IrpContext, Bcb); + + FFSAddMcbEntry(Vcb, Offset, (LONGLONG)Vcb->BlockSize); + + bRet = TRUE; + *bFreed = FALSE; + } + } + +errorout: + + if (pData) + { + CcUnpinData(Bcb); + } + + return bRet; +} + + +BOOLEAN +FFSTruncateInode( + IN PFFS_IRP_CONTEXT IrpContext, + IN PFFS_VCB Vcb, + IN PFFS_FCB Fcb) +{ + ULONG dwSizes[FFS_BLOCK_TYPES]; + ULONG Index = 0; + ULONG dwTotal = 0; + ULONG dwBlk = 0; + + ULONG i; + BOOLEAN bRet = FALSE; + BOOLEAN bFreed = FALSE; + + PFFSv1_INODE dinode1 = Fcb->dinode1; + + PAGED_CODE(); + + Index = (ULONG)(Fcb->Header.AllocationSize.QuadPart >> BLOCK_BITS); + + if (Index > 0) + { + Index--; + } + else + { + return TRUE; + } + + for (i = 0; i < FFS_BLOCK_TYPES; i++) + { + dwSizes[i] = Vcb->dwData[i]; + dwTotal += dwSizes[i]; + } + + if (Index >= dwTotal) + { + FFSPrint((DBG_ERROR, "FFSTruncateInode: beyond the maxinum size of an inode.\n")); + return TRUE; + } + + for (i = 0; i < FFS_BLOCK_TYPES; i++) + { +#if 0 + if (Index < dwSizes[i]) + { + dwBlk = Inode->i_block[i == 0 ? (Index) : (i + NDADDR - 1)]; + + bRet = FFSTruncateBlock(IrpContext, Vcb, Fcb, dwBlk, Index , i, &bFreed); + + if (bRet) + { + Fcb->Header.AllocationSize.QuadPart -= Vcb->BlockSize; + + if (bFreed) + { + Inode->i_block[i == 0 ? (Index) : (i + NDADDR - 1)] = 0; + } + } + + break; + } +#endif + Index -= dwSizes[i]; + } + + { + ASSERT(FFSDataBlocks(Vcb, (ULONG)(dinode1->di_blocks / (BLOCK_SIZE / SECTOR_SIZE))) + == (Fcb->Header.AllocationSize.QuadPart / BLOCK_SIZE)); + + ASSERT(FFSTotalBlocks(Vcb, (ULONG)(Fcb->Header.AllocationSize.QuadPart / BLOCK_SIZE)) + == (dinode1->di_blocks / (BLOCK_SIZE / SECTOR_SIZE))); + + } + + // + // Inode struct saving is done externally. + // + + FFSv1SaveInode(IrpContext, Vcb, Fcb->FFSMcb->Inode, dinode1); + + + return bRet; +} + +#endif // !FFS_READ_ONLY + +__drv_mustHoldCriticalRegion +BOOLEAN +FFSAddMcbEntry( + IN PFFS_VCB Vcb, + IN LONGLONG Lba, + IN LONGLONG Length) +{ + BOOLEAN bRet = FALSE; + + LONGLONG Offset; + +#if DBG + LONGLONG DirtyLba; + LONGLONG DirtyLen; +#endif + + PAGED_CODE(); + + Offset = Lba & (~((LONGLONG)BLOCK_SIZE - 1)); + + Length = (Length + Lba - Offset + BLOCK_SIZE - 1) & + (~((LONGLONG)BLOCK_SIZE - 1)); + + ASSERT ((Offset & (BLOCK_SIZE - 1)) == 0); + ASSERT ((Length & (BLOCK_SIZE - 1)) == 0); + + Offset = (Offset >> BLOCK_BITS) + 1; + Length = (Length >>BLOCK_BITS); + + ExAcquireResourceExclusiveLite( + &(Vcb->McbResource), + TRUE); + + FFSPrint((DBG_INFO, "FFSAddMcbEntry: Lba=%I64xh Length=%I64xh\n", + Offset, Length)); + +#if DBG + bRet = FsRtlLookupLargeMcbEntry( + &(Vcb->DirtyMcbs), + Offset, + &DirtyLba, + &DirtyLen, + NULL, + NULL, + NULL); + + if (bRet && DirtyLba == Offset && DirtyLen >= Length) + { + FFSPrint((DBG_INFO, "FFSAddMcbEntry: this run already exists.\n")); + } +#endif + + _SEH2_TRY + { + bRet = FsRtlAddLargeMcbEntry( + &(Vcb->DirtyMcbs), + Offset, Offset, + Length); + + } + _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) + { + FFSBreakPoint(); + bRet = FALSE; + } _SEH2_END; + +#if DBG + if (bRet) + { + BOOLEAN bFound = FALSE; + LONGLONG RunStart; + LONGLONG RunLength; + ULONG Index; + + bFound = FsRtlLookupLargeMcbEntry( + &(Vcb->DirtyMcbs), + Offset, + &DirtyLba, + &DirtyLen, + &RunStart, + &RunLength, + &Index); + + if ((!bFound) || (DirtyLba == -1) || + (DirtyLba != Offset) || (DirtyLen < Length)) + { + LONGLONG DirtyVba; + LONGLONG DirtyLba; + LONGLONG DirtyLength; + + FFSBreakPoint(); + + for (Index = 0; + FsRtlGetNextLargeMcbEntry(&(Vcb->DirtyMcbs), + Index, + &DirtyVba, + &DirtyLba, + &DirtyLength); + Index++) + { + FFSPrint((DBG_INFO, "Index = %xh\n", Index)); + FFSPrint((DBG_INFO, "DirtyVba = %I64xh\n", DirtyVba)); + FFSPrint((DBG_INFO, "DirtyLba = %I64xh\n", DirtyLba)); + FFSPrint((DBG_INFO, "DirtyLen = %I64xh\n\n", DirtyLength)); + } + } + } +#endif + + ExReleaseResourceForThreadLite( + &(Vcb->McbResource), + ExGetCurrentResourceThread()); + + return bRet; +} + + +__drv_mustHoldCriticalRegion +VOID +FFSRemoveMcbEntry( + IN PFFS_VCB Vcb, + IN LONGLONG Lba, + IN LONGLONG Length) +{ + LONGLONG Offset; + + PAGED_CODE(); + + Offset = Lba & (~((LONGLONG)BLOCK_SIZE - 1)); + + Length = (Length + Lba - Offset + BLOCK_SIZE - 1) & + (~((LONGLONG)BLOCK_SIZE - 1)); + + ASSERT(Offset == Lba); + + ASSERT ((Offset & (BLOCK_SIZE - 1)) == 0); + ASSERT ((Length & (BLOCK_SIZE - 1)) == 0); + + Offset = (Offset >> BLOCK_BITS) + 1; + Length = (Length >> BLOCK_BITS); + + FFSPrint((DBG_INFO, "FFSRemoveMcbEntry: Lba=%I64xh Length=%I64xh\n", + Offset, Length)); + + ExAcquireResourceExclusiveLite( + &(Vcb->McbResource), + TRUE); + + _SEH2_TRY + { + FsRtlRemoveLargeMcbEntry( + &(Vcb->DirtyMcbs), + Offset, Length); + + } + _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) + { + FFSBreakPoint(); + } _SEH2_END; + +#if DBG + { + BOOLEAN bFound = FALSE; + LONGLONG DirtyLba, DirtyLen; + + bFound = FsRtlLookupLargeMcbEntry( + &(Vcb->DirtyMcbs), + Offset, + &DirtyLba, + &DirtyLen, + NULL, + NULL, + NULL); + + if (bFound &&(DirtyLba != -1)) + { + FFSBreakPoint(); + } + } +#endif + + ExReleaseResourceForThreadLite( + &(Vcb->McbResource), + ExGetCurrentResourceThread()); +} + + +__drv_mustHoldCriticalRegion +BOOLEAN +FFSLookupMcbEntry( + IN PFFS_VCB Vcb, + IN LONGLONG Lba, + OUT PLONGLONG pLba, + OUT PLONGLONG pLength, + OUT PLONGLONG RunStart, + OUT PLONGLONG RunLength, + OUT PULONG Index) +{ + BOOLEAN bRet; + LONGLONG Offset; + + PAGED_CODE(); + + Offset = Lba & (~((LONGLONG)BLOCK_SIZE - 1)); + ASSERT ((Offset & (BLOCK_SIZE - 1)) == 0); + + ASSERT(Lba == Offset); + + Offset = (Offset >> BLOCK_BITS) + 1; + + ExAcquireResourceExclusiveLite( + &(Vcb->McbResource), + TRUE); + + bRet = FsRtlLookupLargeMcbEntry( + &(Vcb->DirtyMcbs), + Offset, + pLba, + pLength, + RunStart, + RunLength, + Index); + + ExReleaseResourceForThreadLite( + &(Vcb->McbResource), + ExGetCurrentResourceThread()); + + if (bRet) + { + if (pLba && ((*pLba) != -1)) + { + ASSERT((*pLba) > 0); + + (*pLba) = (((*pLba) - 1) << BLOCK_BITS); + (*pLba) += ((Lba) & ((LONGLONG)BLOCK_SIZE - 1)); + } + + if (pLength) + { + (*pLength) <<= BLOCK_BITS; + (*pLength) -= ((Lba) & ((LONGLONG)BLOCK_SIZE - 1)); + } + + if (RunStart && (*RunStart != -1)) + { + (*RunStart) = (((*RunStart) - 1) << BLOCK_BITS); + } + + if (RunLength) + { + (*RunLength) <<= BLOCK_BITS; + } + } + + return bRet; +} + + +ULONG +FFSDataBlocks( + PFFS_VCB Vcb, + ULONG TotalBlocks) +{ + ULONG dwData[FFS_BLOCK_TYPES]; + ULONG dwMeta[FFS_BLOCK_TYPES]; + ULONG DataBlocks = 0; + ULONG i, j; + + if (TotalBlocks <= NDADDR) + { + return TotalBlocks; + } + + TotalBlocks -= NDADDR; + + for (i = 0; i < FFS_BLOCK_TYPES; i++) + { + if (i == 0) + { + dwData[i] = 1; + } + else + { + dwData[i] = Vcb->dwData[i]; + } + + dwMeta[i] = Vcb->dwMeta[i]; + } + + for(i = 1; (i < FFS_BLOCK_TYPES) && (TotalBlocks > 0); i++) + { + if (TotalBlocks >= (dwData[i] + dwMeta[i])) + { + TotalBlocks -= (dwData[i] + dwMeta[i]); + DataBlocks += dwData[i]; + } + else + { + ULONG dwDivide = 0; + ULONG dwRemain = 0; + + for (j = i; (j > 0) && (TotalBlocks > 0); j--) + { + dwDivide = (TotalBlocks - 1) / (dwData[j - 1] + dwMeta[j - 1]); + dwRemain = (TotalBlocks - 1) % (dwData[j - 1] + dwMeta[j - 1]); + + DataBlocks += (dwDivide * dwData[j - 1]); + TotalBlocks = dwRemain; + } + } + } + + return (DataBlocks + NDADDR); +} + + +ULONG +FFSTotalBlocks( + PFFS_VCB Vcb, + ULONG DataBlocks) +{ + ULONG dwData[FFS_BLOCK_TYPES]; + ULONG dwMeta[FFS_BLOCK_TYPES]; + ULONG TotalBlocks = 0; + ULONG i, j; + + if (DataBlocks <= NDADDR) + { + return DataBlocks; + } + + DataBlocks -= NDADDR; + + for (i = 0; i < FFS_BLOCK_TYPES; i++) + { + if (i == 0) + { + dwData[i] = 1; + } + else + { + dwData[i] = Vcb->dwData[i]; + } + + dwMeta[i] = Vcb->dwMeta[i]; + } + + for(i = 1; (i < FFS_BLOCK_TYPES) && (DataBlocks > 0); i++) + { + if (DataBlocks >= dwData[i]) + { + DataBlocks -= dwData[i]; + TotalBlocks += (dwData[i] + dwMeta[i]); + } + else + { + ULONG dwDivide = 0; + ULONG dwRemain = 0; + + for (j = i; (j > 0) && (DataBlocks > 0); j--) + { + dwDivide = (DataBlocks) / (dwData[j - 1]); + dwRemain = (DataBlocks) % (dwData[j - 1]); + + TotalBlocks += (dwDivide * (dwData[j - 1] + dwMeta[j - 1]) + 1); + DataBlocks = dwRemain; + } + } + } + + return (TotalBlocks + NDADDR); +} diff --git a/reactos/drivers/filesystems/ffs/src/ffsdrv.rc b/reactos/drivers/filesystems/ffs/src/ffsdrv.rc new file mode 100644 index 00000000000..3ec0042bd48 --- /dev/null +++ b/reactos/drivers/filesystems/ffs/src/ffsdrv.rc @@ -0,0 +1,112 @@ +//Microsoft Developer Studio generated resource script. +// + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#define APSTUDIO_HIDDEN_SYMBOLS +#include "windows.h" +#undef APSTUDIO_HIDDEN_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifndef _MAC +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 0,5,3,0 + PRODUCTVERSION 0,5,3,0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x9L +#else + FILEFLAGS 0x8L +#endif + FILEOS 0x40004L + FILETYPE 0x3L + FILESUBTYPE 0x8L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "000004b0" + BEGIN + VALUE "Comments", "\0" + VALUE "CompanyName", "PYRASIS.COM\0" + VALUE "FileDescription", "FFS File System Driver for Windows\0" + VALUE "FileVersion", "0, 5, 3, 0\0" + VALUE "InternalName", "ffs\0" + VALUE "LegalCopyright", "2004-2015 (C) Lee Jae-Hong. All rights reserved.\0" + VALUE "LegalTrademarks", "\0" + VALUE "OriginalFilename", "ffs.sys\0" + VALUE "PrivateBuild", "2015.10.2\0" + VALUE "ProductName", "FFS Driver\0" + VALUE "ProductVersion", "0, 5, 3, 0\0" + VALUE "SpecialBuild", "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0, 1200 + END +END + +#endif // !_MAC + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#define APSTUDIO_HIDDEN_SYMBOLS\r\n" + "#include ""windows.h""\r\n" + "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/reactos/drivers/filesystems/ffs/src/fileinfo.c b/reactos/drivers/filesystems/ffs/src/fileinfo.c new file mode 100644 index 00000000000..09b6353ad79 --- /dev/null +++ b/reactos/drivers/filesystems/ffs/src/fileinfo.c @@ -0,0 +1,1789 @@ +/* + * FFS File System Driver for Windows + * + * fileinfo.c + * + * 2004.5.6 ~ + * + * Lee Jae-Hong, http://www.pyrasis.com + * + * See License.txt + * + */ + +#include "ntifs.h" +#include "ffsdrv.h" + +/* Globals */ + +extern PFFS_GLOBAL FFSGlobal; + + +/* Definitions */ + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE, FFSQueryInformation) +#pragma alloc_text(PAGE, FFSSetInformation) +#pragma alloc_text(PAGE, FFSExpandFile) +#pragma alloc_text(PAGE, FFSTruncateFile) +#pragma alloc_text(PAGE, FFSSetDispositionInfo) +#pragma alloc_text(PAGE, FFSSetRenameInfo) +#pragma alloc_text(PAGE, FFSDeleteFile) +#endif + + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSQueryInformation( + IN PFFS_IRP_CONTEXT IrpContext) +{ + PDEVICE_OBJECT DeviceObject; + NTSTATUS Status = STATUS_UNSUCCESSFUL; + PFILE_OBJECT FileObject; + PFFS_VCB Vcb; + PFFS_FCB Fcb = 0; + PFFS_CCB Ccb; + PIRP Irp; + PIO_STACK_LOCATION IoStackLocation; + FILE_INFORMATION_CLASS FileInformationClass; + ULONG Length; + PVOID Buffer; + BOOLEAN FcbResourceAcquired = FALSE; + + PAGED_CODE(); + + _SEH2_TRY + { + ASSERT(IrpContext != NULL); + + ASSERT((IrpContext->Identifier.Type == FFSICX) && + (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); + + DeviceObject = IrpContext->DeviceObject; + + // + // This request is not allowed on the main device object + // + if (DeviceObject == FFSGlobal->DeviceObject) + { + Status = STATUS_INVALID_DEVICE_REQUEST; + _SEH2_LEAVE; + } + + FileObject = IrpContext->FileObject; + + Vcb = (PFFS_VCB)DeviceObject->DeviceExtension; + + ASSERT(Vcb != NULL); + + Fcb = (PFFS_FCB)FileObject->FsContext; + + ASSERT(Fcb != NULL); + + // + // This request is not allowed on volumes + // + if (Fcb->Identifier.Type == FFSVCB) + { + Status = STATUS_INVALID_PARAMETER; + _SEH2_LEAVE; + } + + ASSERT((Fcb->Identifier.Type == FFSFCB) && + (Fcb->Identifier.Size == sizeof(FFS_FCB))); + /* + if (!IsFlagOn(Fcb->Vcb->Flags, VCB_READ_ONLY) && + !FlagOn(Fcb->Flags, FCB_PAGE_FILE)) + */ + { + if (!ExAcquireResourceSharedLite( + &Fcb->MainResource, + IrpContext->IsSynchronous)) + { + Status = STATUS_PENDING; + _SEH2_LEAVE; + } + + FcbResourceAcquired = TRUE; + } + + Ccb = (PFFS_CCB)FileObject->FsContext2; + + ASSERT(Ccb != NULL); + + ASSERT((Ccb->Identifier.Type == FFSCCB) && + (Ccb->Identifier.Size == sizeof(FFS_CCB))); + + Irp = IrpContext->Irp; + + IoStackLocation = IoGetCurrentIrpStackLocation(Irp); + + FileInformationClass = + IoStackLocation->Parameters.QueryFile.FileInformationClass; + + Length = IoStackLocation->Parameters.QueryFile.Length; + + Buffer = Irp->AssociatedIrp.SystemBuffer; + + RtlZeroMemory(Buffer, Length); + + switch (FileInformationClass) + { + case FileBasicInformation: + { + PFILE_BASIC_INFORMATION FileBasicInformation; + + if (Length < sizeof(FILE_BASIC_INFORMATION)) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + _SEH2_LEAVE; + } + + FileBasicInformation = (PFILE_BASIC_INFORMATION)Buffer; + + if (FS_VERSION == 1) + { + FileBasicInformation->CreationTime = FFSSysTime(Fcb->dinode1->di_ctime); + + FileBasicInformation->LastAccessTime = FFSSysTime(Fcb->dinode1->di_atime); + + FileBasicInformation->LastWriteTime = FFSSysTime(Fcb->dinode1->di_mtime); + + FileBasicInformation->ChangeTime = FFSSysTime(Fcb->dinode1->di_mtime); + } + else + { + FileBasicInformation->CreationTime = FFSSysTime((ULONG)Fcb->dinode2->di_ctime); + + FileBasicInformation->LastAccessTime = FFSSysTime((ULONG)Fcb->dinode2->di_atime); + + FileBasicInformation->LastWriteTime = FFSSysTime((ULONG)Fcb->dinode2->di_mtime); + + FileBasicInformation->ChangeTime = FFSSysTime((ULONG)Fcb->dinode2->di_mtime); + } + + FileBasicInformation->FileAttributes = Fcb->FFSMcb->FileAttr; + + Irp->IoStatus.Information = sizeof(FILE_BASIC_INFORMATION); + Status = STATUS_SUCCESS; + _SEH2_LEAVE; + } + +#if (_WIN32_WINNT >= 0x0500) + + case FileAttributeTagInformation: + { + PFILE_ATTRIBUTE_TAG_INFORMATION FATI; + + if (Length < sizeof(FILE_ATTRIBUTE_TAG_INFORMATION)) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + _SEH2_LEAVE; + } + + FATI = (PFILE_ATTRIBUTE_TAG_INFORMATION) Buffer; + + FATI->FileAttributes = Fcb->FFSMcb->FileAttr; + FATI->ReparseTag = 0; + + Irp->IoStatus.Information = sizeof(FILE_ATTRIBUTE_TAG_INFORMATION); + Status = STATUS_SUCCESS; + _SEH2_LEAVE; + } +#endif // (_WIN32_WINNT >= 0x0500) + + case FileStandardInformation: + { + PFILE_STANDARD_INFORMATION FileStandardInformation; + + if (Length < sizeof(FILE_STANDARD_INFORMATION)) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + _SEH2_LEAVE; + } + + FileStandardInformation = (PFILE_STANDARD_INFORMATION)Buffer; + + if (FS_VERSION == 1) + { + FileStandardInformation->AllocationSize.QuadPart = + (LONGLONG)(Fcb->dinode1->di_size); + + FileStandardInformation->EndOfFile.QuadPart = + (LONGLONG)(Fcb->dinode1->di_size); + + FileStandardInformation->NumberOfLinks = Fcb->dinode1->di_nlink; + } + else + { + FileStandardInformation->AllocationSize.QuadPart = + (LONGLONG)(Fcb->dinode2->di_size); + + FileStandardInformation->EndOfFile.QuadPart = + (LONGLONG)(Fcb->dinode2->di_size); + + FileStandardInformation->NumberOfLinks = Fcb->dinode2->di_nlink; + } + + if (IsFlagOn(Fcb->Vcb->Flags, VCB_READ_ONLY)) + FileStandardInformation->DeletePending = FALSE; + else + FileStandardInformation->DeletePending = IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING); + + if (Fcb->FFSMcb->FileAttr & FILE_ATTRIBUTE_DIRECTORY) + { + FileStandardInformation->Directory = TRUE; + } + else + { + FileStandardInformation->Directory = FALSE; + } + + Irp->IoStatus.Information = sizeof(FILE_STANDARD_INFORMATION); + Status = STATUS_SUCCESS; + _SEH2_LEAVE; + } + + case FileInternalInformation: + { + PFILE_INTERNAL_INFORMATION FileInternalInformation; + + if (Length < sizeof(FILE_INTERNAL_INFORMATION)) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + _SEH2_LEAVE; + } + + FileInternalInformation = (PFILE_INTERNAL_INFORMATION)Buffer; + + // The "inode number" + FileInternalInformation->IndexNumber.QuadPart = (LONGLONG)Fcb->FFSMcb->Inode; + + Irp->IoStatus.Information = sizeof(FILE_INTERNAL_INFORMATION); + Status = STATUS_SUCCESS; + _SEH2_LEAVE; + } + + case FileEaInformation: + { + PFILE_EA_INFORMATION FileEaInformation; + + if (Length < sizeof(FILE_EA_INFORMATION)) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + _SEH2_LEAVE; + } + + FileEaInformation = (PFILE_EA_INFORMATION)Buffer; + + // Romfs doesn't have any extended attributes + FileEaInformation->EaSize = 0; + + Irp->IoStatus.Information = sizeof(FILE_EA_INFORMATION); + Status = STATUS_SUCCESS; + _SEH2_LEAVE; + } + + case FileNameInformation: + { + PFILE_NAME_INFORMATION FileNameInformation; + + if (Length < sizeof(FILE_NAME_INFORMATION) + + Fcb->FFSMcb->ShortName.Length - sizeof(WCHAR)) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + _SEH2_LEAVE; + } + + FileNameInformation = (PFILE_NAME_INFORMATION)Buffer; + + FileNameInformation->FileNameLength = Fcb->FFSMcb->ShortName.Length; + + RtlCopyMemory( + FileNameInformation->FileName, + Fcb->FFSMcb->ShortName.Buffer, + Fcb->FFSMcb->ShortName.Length); + + Irp->IoStatus.Information = sizeof(FILE_NAME_INFORMATION) + + Fcb->FFSMcb->ShortName.Length - sizeof(WCHAR); + Status = STATUS_SUCCESS; + _SEH2_LEAVE; + } + + case FilePositionInformation: + { + PFILE_POSITION_INFORMATION FilePositionInformation; + + if (Length < sizeof(FILE_POSITION_INFORMATION)) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + _SEH2_LEAVE; + } + + FilePositionInformation = (PFILE_POSITION_INFORMATION)Buffer; + + FilePositionInformation->CurrentByteOffset = + FileObject->CurrentByteOffset; + + Irp->IoStatus.Information = sizeof(FILE_POSITION_INFORMATION); + Status = STATUS_SUCCESS; + _SEH2_LEAVE; + } + + case FileAllInformation: + { + PFILE_ALL_INFORMATION FileAllInformation; + PFILE_BASIC_INFORMATION FileBasicInformation; + PFILE_STANDARD_INFORMATION FileStandardInformation; + PFILE_INTERNAL_INFORMATION FileInternalInformation; + PFILE_EA_INFORMATION FileEaInformation; + PFILE_POSITION_INFORMATION FilePositionInformation; + PFILE_NAME_INFORMATION FileNameInformation; + + if (Length < sizeof(FILE_ALL_INFORMATION)) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + _SEH2_LEAVE; + } + + FileAllInformation = (PFILE_ALL_INFORMATION)Buffer; + + FileBasicInformation = + &FileAllInformation->BasicInformation; + + FileStandardInformation = + &FileAllInformation->StandardInformation; + + FileInternalInformation = + &FileAllInformation->InternalInformation; + + FileEaInformation = + &FileAllInformation->EaInformation; + + FilePositionInformation = + &FileAllInformation->PositionInformation; + + FileNameInformation = + &FileAllInformation->NameInformation; + + if (FS_VERSION == 1) + { + FileBasicInformation->CreationTime = FFSSysTime(Fcb->dinode1->di_ctime); + + FileBasicInformation->LastAccessTime = FFSSysTime(Fcb->dinode1->di_atime); + + FileBasicInformation->LastWriteTime = FFSSysTime(Fcb->dinode1->di_mtime); + + FileBasicInformation->ChangeTime = FFSSysTime(Fcb->dinode1->di_mtime); + + FileBasicInformation->FileAttributes = Fcb->FFSMcb->FileAttr; + + FileStandardInformation->AllocationSize.QuadPart = + (LONGLONG)(Fcb->dinode1->di_size); + + FileStandardInformation->EndOfFile.QuadPart = + (LONGLONG)(Fcb->dinode1->di_size); + + FileStandardInformation->NumberOfLinks = Fcb->dinode1->di_nlink; + } + else + { + FileBasicInformation->CreationTime = FFSSysTime((ULONG)Fcb->dinode2->di_ctime); + + FileBasicInformation->LastAccessTime = FFSSysTime((ULONG)Fcb->dinode2->di_atime); + + FileBasicInformation->LastWriteTime = FFSSysTime((ULONG)Fcb->dinode2->di_mtime); + + FileBasicInformation->ChangeTime = FFSSysTime((ULONG)Fcb->dinode2->di_mtime); + + FileBasicInformation->FileAttributes = Fcb->FFSMcb->FileAttr; + + FileStandardInformation->AllocationSize.QuadPart = + (LONGLONG)(Fcb->dinode2->di_size); + + FileStandardInformation->EndOfFile.QuadPart = + (LONGLONG)(Fcb->dinode2->di_size); + + FileStandardInformation->NumberOfLinks = Fcb->dinode2->di_nlink; + } + + if (IsFlagOn(Fcb->Vcb->Flags, VCB_READ_ONLY)) + FileStandardInformation->DeletePending = FALSE; + else + FileStandardInformation->DeletePending = IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING); + + if (FlagOn(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY)) + { + FileStandardInformation->Directory = TRUE; + } + else + { + FileStandardInformation->Directory = FALSE; + } + + // The "inode number" + FileInternalInformation->IndexNumber.QuadPart = (LONGLONG)Fcb->FFSMcb->Inode; + + // Romfs doesn't have any extended attributes + FileEaInformation->EaSize = 0; + + FilePositionInformation->CurrentByteOffset = + FileObject->CurrentByteOffset; + + if (Length < sizeof(FILE_ALL_INFORMATION) + + Fcb->FFSMcb->ShortName.Length - sizeof(WCHAR)) + { + Irp->IoStatus.Information = sizeof(FILE_ALL_INFORMATION); + Status = STATUS_BUFFER_OVERFLOW; + _SEH2_LEAVE; + } + + FileNameInformation->FileNameLength = Fcb->FFSMcb->ShortName.Length; + + RtlCopyMemory( + FileNameInformation->FileName, + Fcb->FFSMcb->ShortName.Buffer, + Fcb->FFSMcb->ShortName.Length); + + Irp->IoStatus.Information = sizeof(FILE_ALL_INFORMATION) + + Fcb->FFSMcb->ShortName.Length - sizeof(WCHAR); + Status = STATUS_SUCCESS; + _SEH2_LEAVE; + } + + /* + case FileAlternateNameInformation: + { + // TODO: Handle FileAlternateNameInformation + + // Here we would like to use RtlGenerate8dot3Name but I don't + // know how to use the argument PGENERATE_NAME_CONTEXT + } + */ + + case FileNetworkOpenInformation: + { + PFILE_NETWORK_OPEN_INFORMATION FileNetworkOpenInformation; + + if (Length < sizeof(FILE_NETWORK_OPEN_INFORMATION)) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + _SEH2_LEAVE; + } + + FileNetworkOpenInformation = + (PFILE_NETWORK_OPEN_INFORMATION)Buffer; + + if (FS_VERSION == 1) + { + FileNetworkOpenInformation->CreationTime = FFSSysTime(Fcb->dinode1->di_ctime); + + FileNetworkOpenInformation->LastAccessTime = FFSSysTime(Fcb->dinode1->di_atime); + + FileNetworkOpenInformation->LastWriteTime = FFSSysTime(Fcb->dinode1->di_mtime); + + FileNetworkOpenInformation->ChangeTime = FFSSysTime(Fcb->dinode1->di_mtime); + + FileNetworkOpenInformation->AllocationSize.QuadPart = + (LONGLONG)(Fcb->dinode1->di_size); + + FileNetworkOpenInformation->EndOfFile.QuadPart = + (LONGLONG)(Fcb->dinode1->di_size); + } + else + { + FileNetworkOpenInformation->CreationTime = FFSSysTime((ULONG)Fcb->dinode2->di_ctime); + + FileNetworkOpenInformation->LastAccessTime = FFSSysTime((ULONG)Fcb->dinode2->di_atime); + + FileNetworkOpenInformation->LastWriteTime = FFSSysTime((ULONG)Fcb->dinode2->di_mtime); + + FileNetworkOpenInformation->ChangeTime = FFSSysTime((ULONG)Fcb->dinode2->di_mtime); + + FileNetworkOpenInformation->AllocationSize.QuadPart = + (LONGLONG)(Fcb->dinode2->di_size); + + FileNetworkOpenInformation->EndOfFile.QuadPart = + (LONGLONG)(Fcb->dinode2->di_size); + } + + FileNetworkOpenInformation->FileAttributes = + Fcb->FFSMcb->FileAttr; + + Irp->IoStatus.Information = + sizeof(FILE_NETWORK_OPEN_INFORMATION); + Status = STATUS_SUCCESS; + _SEH2_LEAVE; + } + + default: + Status = STATUS_INVALID_INFO_CLASS; + } + } + _SEH2_FINALLY + { + if (FcbResourceAcquired) + { + ExReleaseResourceForThreadLite( + &Fcb->MainResource, + ExGetCurrentResourceThread()); + } + + if (!IrpContext->ExceptionInProgress) + { + if (Status == STATUS_PENDING) + { + FFSQueueRequest(IrpContext); + } + else + { + FFSCompleteIrpContext(IrpContext, Status); + } + } + } _SEH2_END; + + return Status; +} + + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSSetInformation( + IN PFFS_IRP_CONTEXT IrpContext) +{ + PDEVICE_OBJECT DeviceObject; + NTSTATUS Status = STATUS_UNSUCCESSFUL; + PFFS_VCB Vcb = 0; + PFILE_OBJECT FileObject; + PFFS_FCB Fcb = 0; + PFFS_CCB Ccb; + PIRP Irp; + PIO_STACK_LOCATION IoStackLocation; + FILE_INFORMATION_CLASS FileInformationClass; + + ULONG NotifyFilter = 0; + + ULONG Length; + PVOID Buffer; + BOOLEAN FcbMainResourceAcquired = FALSE; + + BOOLEAN VcbResourceAcquired = FALSE; + BOOLEAN FcbPagingIoResourceAcquired = FALSE; + + PAGED_CODE(); + + _SEH2_TRY + { + ASSERT(IrpContext != NULL); + + ASSERT((IrpContext->Identifier.Type == FFSICX) && + (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); + + DeviceObject = IrpContext->DeviceObject; + + // + // This request is not allowed on the main device object + // + if (DeviceObject == FFSGlobal->DeviceObject) + { + Status = STATUS_INVALID_DEVICE_REQUEST; + _SEH2_LEAVE; + } + + Vcb = (PFFS_VCB)DeviceObject->DeviceExtension; + + ASSERT(Vcb != NULL); + + ASSERT((Vcb->Identifier.Type == FFSVCB) && + (Vcb->Identifier.Size == sizeof(FFS_VCB))); + + ASSERT(IsMounted(Vcb)); + + FileObject = IrpContext->FileObject; + + Fcb = (PFFS_FCB)FileObject->FsContext; + + ASSERT(Fcb != NULL); + + // + // This request is not allowed on volumes + // + if (Fcb->Identifier.Type == FFSVCB) + { + FFSBreakPoint(); + + Status = STATUS_INVALID_PARAMETER; + _SEH2_LEAVE; + } + + ASSERT((Fcb->Identifier.Type == FFSFCB) && + (Fcb->Identifier.Size == sizeof(FFS_FCB))); + + if (IsFlagOn(Fcb->Flags, FCB_FILE_DELETED)) + { + Status = STATUS_FILE_DELETED; + _SEH2_LEAVE; + } + + Ccb = (PFFS_CCB)FileObject->FsContext2; + + ASSERT(Ccb != NULL); + + ASSERT((Ccb->Identifier.Type == FFSCCB) && + (Ccb->Identifier.Size == sizeof(FFS_CCB))); + + Irp = IrpContext->Irp; + + IoStackLocation = IoGetCurrentIrpStackLocation(Irp); + + FileInformationClass = + IoStackLocation->Parameters.SetFile.FileInformationClass; + + Length = IoStackLocation->Parameters.SetFile.Length; + + Buffer = Irp->AssociatedIrp.SystemBuffer; + + if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY)) + { + if (FileInformationClass == FileDispositionInformation || + FileInformationClass == FileRenameInformation || + FileInformationClass == FileLinkInformation) + { +#ifdef _MSC_VER +#pragma prefast( suppress: 28137, "by design" ) +#endif + if (!ExAcquireResourceExclusiveLite( + &Vcb->MainResource, + IrpContext->IsSynchronous)) + { + Status = STATUS_PENDING; + _SEH2_LEAVE; + } + + VcbResourceAcquired = TRUE; + } + } + else if (!FlagOn(Fcb->Flags, FCB_PAGE_FILE)) + { +#ifdef _MSC_VER +#pragma prefast( suppress: 28137, "by design" ) +#endif + if (!ExAcquireResourceExclusiveLite( + &Fcb->MainResource, + IrpContext->IsSynchronous)) + { + Status = STATUS_PENDING; + _SEH2_LEAVE; + } + + FcbMainResourceAcquired = TRUE; + } + + if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY)) + { + if (FileInformationClass != FilePositionInformation) + { + Status = STATUS_MEDIA_WRITE_PROTECTED; + _SEH2_LEAVE; + } + } + + if (FileInformationClass == FileDispositionInformation || + FileInformationClass == FileRenameInformation || + FileInformationClass == FileLinkInformation || + FileInformationClass == FileAllocationInformation || + FileInformationClass == FileEndOfFileInformation) + { +#ifdef _MSC_VER +#pragma prefast( suppress: 28137, "by design" ) +#endif + if (!ExAcquireResourceExclusiveLite( + &Fcb->PagingIoResource, + IrpContext->IsSynchronous)) + { + Status = STATUS_PENDING; + _SEH2_LEAVE; + } + + FcbPagingIoResourceAcquired = TRUE; + } + + /* + if (FileInformationClass != FileDispositionInformation + && FlagOn(Fcb->Flags, FCB_DELETE_PENDING)) + { + Status = STATUS_DELETE_PENDING; + _SEH2_LEAVE; + } + */ + + switch (FileInformationClass) + { + +#if !FFS_READ_ONLY + + case FileBasicInformation: + { + PFILE_BASIC_INFORMATION FBI = (PFILE_BASIC_INFORMATION)Buffer; + + if (FS_VERSION == 1) + { + PFFSv1_INODE dinode1 = Fcb->dinode1; + + if(FBI->CreationTime.QuadPart) + { + dinode1->di_ctime = (ULONG)(FFSInodeTime(FBI->CreationTime)); + } + + if(FBI->LastAccessTime.QuadPart) + { + dinode1->di_atime = (ULONG)(FFSInodeTime(FBI->LastAccessTime)); + } + + if(FBI->LastWriteTime.QuadPart) + { + dinode1->di_mtime = (ULONG)(FFSInodeTime(FBI->LastWriteTime)); + } + + if (IsFlagOn(FBI->FileAttributes, FILE_ATTRIBUTE_READONLY)) + { + FFSSetReadOnly(Fcb->dinode1->di_mode); + SetFlag(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_READONLY); + } + else + { + FFSSetWritable(Fcb->dinode1->di_mode); + ClearFlag(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_READONLY); + } + + if(FFSv1SaveInode(IrpContext, Vcb, Fcb->FFSMcb->Inode, dinode1)) + { + Status = STATUS_SUCCESS; + } + + if (FBI->FileAttributes & FILE_ATTRIBUTE_TEMPORARY) + { + SetFlag(FileObject->Flags, FO_TEMPORARY_FILE); + } + else + { + ClearFlag(FileObject->Flags, FO_TEMPORARY_FILE); + } + } + else + { + PFFSv2_INODE dinode2 = Fcb->dinode2; + + if(FBI->CreationTime.QuadPart) + { + dinode2->di_ctime = (ULONG)(FFSInodeTime(FBI->CreationTime)); + } + + if(FBI->LastAccessTime.QuadPart) + { + dinode2->di_atime = (ULONG)(FFSInodeTime(FBI->LastAccessTime)); + } + + if(FBI->LastWriteTime.QuadPart) + { + dinode2->di_mtime = (ULONG)(FFSInodeTime(FBI->LastWriteTime)); + } + + if (IsFlagOn(FBI->FileAttributes, FILE_ATTRIBUTE_READONLY)) + { + FFSSetReadOnly(Fcb->dinode2->di_mode); + SetFlag(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_READONLY); + } + else + { + FFSSetWritable(Fcb->dinode2->di_mode); + ClearFlag(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_READONLY); + } + + if(FFSv2SaveInode(IrpContext, Vcb, Fcb->FFSMcb->Inode, dinode2)) + { + Status = STATUS_SUCCESS; + } + + if (FBI->FileAttributes & FILE_ATTRIBUTE_TEMPORARY) + { + SetFlag(FileObject->Flags, FO_TEMPORARY_FILE); + } + else + { + ClearFlag(FileObject->Flags, FO_TEMPORARY_FILE); + } + } + + NotifyFilter = FILE_NOTIFY_CHANGE_ATTRIBUTES | + FILE_NOTIFY_CHANGE_CREATION | + FILE_NOTIFY_CHANGE_LAST_ACCESS | + FILE_NOTIFY_CHANGE_LAST_WRITE ; + + Status = STATUS_SUCCESS; + } + break; + + case FileAllocationInformation: + { + PFILE_ALLOCATION_INFORMATION FAI = (PFILE_ALLOCATION_INFORMATION)Buffer; + + if (FlagOn(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY)) + { + Status = STATUS_INVALID_DEVICE_REQUEST; + _SEH2_LEAVE; + } + + if (FAI->AllocationSize.QuadPart == + Fcb->Header.AllocationSize.QuadPart) + { + Status = STATUS_SUCCESS; + } + else if (FAI->AllocationSize.QuadPart > + Fcb->Header.AllocationSize.QuadPart) + { + if(FFSExpandFile(IrpContext, + Vcb, Fcb, + &(FAI->AllocationSize))) + { + if (FFSv1SaveInode(IrpContext, + Vcb, + Fcb->FFSMcb->Inode, + Fcb->dinode1)) + { + Status = STATUS_SUCCESS; + } + } + else + { + Status = STATUS_INSUFFICIENT_RESOURCES; + } + } + else + { + if (MmCanFileBeTruncated(&(Fcb->SectionObject), &(FAI->AllocationSize))) + { + LARGE_INTEGER EndOfFile; + + EndOfFile.QuadPart = FAI->AllocationSize.QuadPart + + (LONGLONG)(Vcb->BlockSize - 1); + + if(FFSTruncateFile(IrpContext, Vcb, Fcb, &(EndOfFile))) + { + if (FAI->AllocationSize.QuadPart < + Fcb->Header.FileSize.QuadPart) + { + Fcb->Header.FileSize.QuadPart = + FAI->AllocationSize.QuadPart; + } + + FFSv1SaveInode(IrpContext, + Vcb, + Fcb->FFSMcb->Inode, + Fcb->dinode1); + + Status = STATUS_SUCCESS; + } + } + else + { + Status = STATUS_USER_MAPPED_FILE; + _SEH2_LEAVE; + } + } + + if (NT_SUCCESS(Status)) + { + CcSetFileSizes(FileObject, + (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize))); + SetFlag(FileObject->Flags, FO_FILE_MODIFIED); + + NotifyFilter = FILE_NOTIFY_CHANGE_SIZE | + FILE_NOTIFY_CHANGE_LAST_WRITE ; + + } + + } + break; + + case FileEndOfFileInformation: + { + PFILE_END_OF_FILE_INFORMATION FEOFI = (PFILE_END_OF_FILE_INFORMATION) Buffer; + + BOOLEAN CacheInitialized = FALSE; + + if (IsDirectory(Fcb)) + { + Status = STATUS_INVALID_DEVICE_REQUEST; + _SEH2_LEAVE; + } + + if (FEOFI->EndOfFile.HighPart != 0) + { + Status = STATUS_INVALID_PARAMETER; + _SEH2_LEAVE; + } + + + if (IoStackLocation->Parameters.SetFile.AdvanceOnly) + { + Status = STATUS_SUCCESS; + _SEH2_LEAVE; + } + + if ((FileObject->SectionObjectPointer->DataSectionObject != NULL) && + (FileObject->SectionObjectPointer->SharedCacheMap == NULL) && + !FlagOn(Irp->Flags, IRP_PAGING_IO)) { + + ASSERT(!FlagOn(FileObject->Flags, FO_CLEANUP_COMPLETE)); + + CcInitializeCacheMap( + FileObject, + (PCC_FILE_SIZES)&(Fcb->Header.AllocationSize), + FALSE, + &(FFSGlobal->CacheManagerNoOpCallbacks), + Fcb); + + CacheInitialized = TRUE; + } + + if (FEOFI->EndOfFile.QuadPart == + Fcb->Header.AllocationSize.QuadPart) + { + Status = STATUS_SUCCESS; + } + else if (FEOFI->EndOfFile.QuadPart > + Fcb->Header.AllocationSize.QuadPart) + { + LARGE_INTEGER FileSize = Fcb->Header.FileSize; + + if(FFSExpandFile(IrpContext, Vcb, Fcb, &(FEOFI->EndOfFile))) + { + { + Fcb->Header.FileSize.QuadPart = + FEOFI->EndOfFile.QuadPart; + Fcb->dinode1->di_size = (ULONG)FEOFI->EndOfFile.QuadPart; + Fcb->Header.ValidDataLength.QuadPart = + (LONGLONG)(0x7fffffffffffffff); + } + + if (FFSv1SaveInode(IrpContext, + Vcb, + Fcb->FFSMcb->Inode, + Fcb->dinode1)) + { + Status = STATUS_SUCCESS; + } + } + else + { + Status = STATUS_INSUFFICIENT_RESOURCES; + } + + + if (NT_SUCCESS(Status)) + { + CcSetFileSizes(FileObject, + (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize))); + + SetFlag(FileObject->Flags, FO_FILE_MODIFIED); + + FFSZeroHoles(IrpContext, + Vcb, FileObject, + FileSize.QuadPart, + Fcb->Header.AllocationSize.QuadPart - + FileSize.QuadPart); + + NotifyFilter = FILE_NOTIFY_CHANGE_SIZE | + FILE_NOTIFY_CHANGE_LAST_WRITE ; + + } + } + else + { + if (MmCanFileBeTruncated(&(Fcb->SectionObject), &(FEOFI->EndOfFile))) + { + LARGE_INTEGER EndOfFile = FEOFI->EndOfFile; + + EndOfFile.QuadPart = EndOfFile.QuadPart + + (LONGLONG)(Vcb->BlockSize - 1); + + if(FFSTruncateFile(IrpContext, Vcb, Fcb, &(EndOfFile))) + { + Fcb->Header.FileSize.QuadPart = + FEOFI->EndOfFile.QuadPart; + Fcb->dinode1->di_size = (ULONG)FEOFI->EndOfFile.QuadPart; + + FFSv1SaveInode(IrpContext, + Vcb, + Fcb->FFSMcb->Inode, + Fcb->dinode1); + + Status = STATUS_SUCCESS; + } + } + else + { + Status = STATUS_USER_MAPPED_FILE; + _SEH2_LEAVE; + } + + if (NT_SUCCESS(Status)) + { + CcSetFileSizes(FileObject, + (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize))); + + SetFlag(FileObject->Flags, FO_FILE_MODIFIED); + + NotifyFilter = FILE_NOTIFY_CHANGE_SIZE | + FILE_NOTIFY_CHANGE_LAST_WRITE ; + + } + } + } + + break; + + case FileDispositionInformation: + { + PFILE_DISPOSITION_INFORMATION FDI = (PFILE_DISPOSITION_INFORMATION)Buffer; + + Status = FFSSetDispositionInfo(IrpContext, Vcb, Fcb, FDI->DeleteFile); + } + + break; + + case FileRenameInformation: + { + Status = FFSSetRenameInfo(IrpContext, Vcb, Fcb); + } + + break; + +#endif // !FFS_READ_ONLY + + // + // This is the only set file information request supported on read + // only file systems + // + case FilePositionInformation: + { + PFILE_POSITION_INFORMATION FilePositionInformation; + + if (Length < sizeof(FILE_POSITION_INFORMATION)) + { + Status = STATUS_INVALID_PARAMETER; + _SEH2_LEAVE; + } + + FilePositionInformation = (PFILE_POSITION_INFORMATION) Buffer; + + if ((FlagOn(FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING)) && + (FilePositionInformation->CurrentByteOffset.LowPart & + DeviceObject->AlignmentRequirement)) + { + Status = STATUS_INVALID_PARAMETER; + _SEH2_LEAVE; + } + + FileObject->CurrentByteOffset = + FilePositionInformation->CurrentByteOffset; + + Status = STATUS_SUCCESS; + _SEH2_LEAVE; + } + + break; + + default: + Status = STATUS_INVALID_INFO_CLASS; + } + } + _SEH2_FINALLY + { + + if (FcbPagingIoResourceAcquired) + { + ExReleaseResourceForThreadLite( + &Fcb->PagingIoResource, + ExGetCurrentResourceThread()); + } + + if (NT_SUCCESS(Status) && (NotifyFilter != 0)) + { + FFSNotifyReportChange( + IrpContext, + Vcb, + Fcb, + NotifyFilter, + FILE_ACTION_MODIFIED); + + } + + if (FcbMainResourceAcquired) + { + ExReleaseResourceForThreadLite( + &Fcb->MainResource, + ExGetCurrentResourceThread()); + } + + if (VcbResourceAcquired) + { + ExReleaseResourceForThreadLite( + &Vcb->MainResource, + ExGetCurrentResourceThread()); + } + + if (!IrpContext->ExceptionInProgress) + { + if (Status == STATUS_PENDING) + { + FFSQueueRequest(IrpContext); + } + else + { + FFSCompleteIrpContext(IrpContext, Status); + } + } + } _SEH2_END; + + return Status; +} + +#if !FFS_READ_ONLY + +BOOLEAN +FFSExpandFile( + PFFS_IRP_CONTEXT IrpContext, + PFFS_VCB Vcb, + PFFS_FCB Fcb, + PLARGE_INTEGER AllocationSize) +{ + ULONG dwRet = 0; + BOOLEAN bRet = TRUE; + + PAGED_CODE(); + + if (AllocationSize->QuadPart <= Fcb->Header.AllocationSize.QuadPart) + { + return TRUE; + } + + if (((LONGLONG)SUPER_BLOCK->fs_size - (LONGLONG)SUPER_BLOCK->fs_dsize) * Vcb->BlockSize <= + (AllocationSize->QuadPart - Fcb->Header.AllocationSize.QuadPart)) + { + FFSPrint((DBG_ERROR, "FFSExpandFile: There is no enough disk space available.\n")); + return FALSE; + } + + while (bRet && (AllocationSize->QuadPart > Fcb->Header.AllocationSize.QuadPart)) + { + bRet = FFSExpandInode(IrpContext, Vcb, Fcb, &dwRet); + } + + return bRet; +} + + +BOOLEAN +FFSTruncateFile( + PFFS_IRP_CONTEXT IrpContext, + PFFS_VCB Vcb, + PFFS_FCB Fcb, + PLARGE_INTEGER AllocationSize) +{ + BOOLEAN bRet = TRUE; + + PAGED_CODE(); + + while (bRet && (AllocationSize->QuadPart < + Fcb->Header.AllocationSize.QuadPart)) + { + bRet = FFSTruncateInode(IrpContext, Vcb, Fcb); + } + + return bRet; +} + + +NTSTATUS +FFSSetDispositionInfo( + PFFS_IRP_CONTEXT IrpContext, + PFFS_VCB Vcb, + PFFS_FCB Fcb, + BOOLEAN bDelete) +{ + PIRP Irp = IrpContext->Irp; + PIO_STACK_LOCATION IrpSp; + + PAGED_CODE(); + + IrpSp = IoGetCurrentIrpStackLocation(Irp); + + FFSPrint((DBG_INFO, "FFSSetDispositionInfo: bDelete=%x\n", bDelete)); + + if (bDelete) + { + FFSPrint((DBG_INFO, "FFSSetDispositionInformation: MmFlushImageSection on %s.\n", + Fcb->AnsiFileName.Buffer)); + + if (!MmFlushImageSection(&Fcb->SectionObject, + MmFlushForDelete)) + { + return STATUS_CANNOT_DELETE; + } + + if (Fcb->FFSMcb->Inode == FFS_ROOT_INO) + { + return STATUS_CANNOT_DELETE; + } + + if (IsDirectory(Fcb)) + { + if (!FFSIsDirectoryEmpty(Vcb, Fcb)) + { + return STATUS_DIRECTORY_NOT_EMPTY; + } + } + + SetFlag(Fcb->Flags, FCB_DELETE_PENDING); + IrpSp->FileObject->DeletePending = TRUE; + + if (IsDirectory(Fcb)) + { + FsRtlNotifyFullChangeDirectory(Vcb->NotifySync, + &Vcb->NotifyList, + Fcb, + NULL, + FALSE, + FALSE, + 0, + NULL, + NULL, + NULL); + } + } + else + { + ClearFlag(Fcb->Flags, FCB_DELETE_PENDING); + IrpSp->FileObject->DeletePending = FALSE; + } + + return STATUS_SUCCESS; +} + + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSSetRenameInfo( + PFFS_IRP_CONTEXT IrpContext, + PFFS_VCB Vcb, + PFFS_FCB Fcb) +{ + PFFS_FCB TargetDcb; + PFFS_MCB TargetMcb; + + PFFS_MCB Mcb; + FFSv1_INODE dinode1; + + UNICODE_STRING FileName; + + NTSTATUS Status; + + PIRP Irp; + PIO_STACK_LOCATION IrpSp; + + PFILE_OBJECT FileObject; + PFILE_OBJECT TargetObject; + BOOLEAN ReplaceIfExists; + + BOOLEAN bMove = FALSE; + + PFILE_RENAME_INFORMATION FRI; + + PAGED_CODE(); + + if (Fcb->FFSMcb->Inode == FFS_ROOT_INO) + { + Status = STATUS_INVALID_PARAMETER; + goto errorout; + } + + Irp = IrpContext->Irp; + IrpSp = IoGetCurrentIrpStackLocation(Irp); + + FileObject = IrpSp->FileObject; + TargetObject = IrpSp->Parameters.SetFile.FileObject; + ReplaceIfExists = IrpSp->Parameters.SetFile.ReplaceIfExists; + + FRI = (PFILE_RENAME_INFORMATION)Irp->AssociatedIrp.SystemBuffer; + + if (TargetObject == NULL) + { + UNICODE_STRING NewName; + + NewName.Buffer = FRI->FileName; + NewName.MaximumLength = NewName.Length = (USHORT)FRI->FileNameLength; + + while (NewName.Length > 0 && NewName.Buffer[NewName.Length / 2 - 1] == L'\\') + { + NewName.Buffer[NewName.Length / 2 - 1] = 0; + NewName.Length -= 2; + } + + while (NewName.Length > 0 && NewName.Buffer[NewName.Length / 2 - 1] != L'\\') + { + NewName.Length -= 2; + } + + NewName.Buffer = (USHORT *)((UCHAR *)NewName.Buffer + NewName.Length); + NewName.Length = (USHORT)(FRI->FileNameLength - NewName.Length); + + FileName = NewName; + + TargetDcb = NULL; + TargetMcb = Fcb->FFSMcb->Parent; + + if (FileName.Length >= FFS_NAME_LEN*sizeof(USHORT)) + { + Status = STATUS_OBJECT_NAME_INVALID; + goto errorout; + } + } + else + { + TargetDcb = (PFFS_FCB)(TargetObject->FsContext); + + if (!TargetDcb || TargetDcb->Vcb != Vcb) + { + FFSBreakPoint(); + + Status = STATUS_INVALID_PARAMETER; + goto errorout; + } + + TargetMcb = TargetDcb->FFSMcb; + + FileName = TargetObject->FileName; + } + + if (FsRtlDoesNameContainWildCards(&FileName)) + { + Status = STATUS_OBJECT_NAME_INVALID; + goto errorout; + } + + if (TargetMcb->Inode == Fcb->FFSMcb->Parent->Inode) + { + if (FsRtlAreNamesEqual(&FileName, + &(Fcb->FFSMcb->ShortName), + FALSE, + NULL)) + { + Status = STATUS_SUCCESS; + goto errorout; + } + } + else + { + bMove = TRUE; + } + + TargetDcb = TargetMcb->FFSFcb; + + if (!TargetDcb) + TargetDcb = FFSCreateFcbFromMcb(Vcb, TargetMcb); + + if ((TargetMcb->Inode != Fcb->FFSMcb->Parent->Inode) && + (Fcb->FFSMcb->Parent->FFSFcb == NULL)) + { + FFSCreateFcbFromMcb(Vcb, Fcb->FFSMcb->Parent); + } + + if (!TargetDcb || !(Fcb->FFSMcb->Parent->FFSFcb)) + { + Status = STATUS_UNSUCCESSFUL; + + goto errorout; + } + + Mcb = NULL; + Status = FFSv1LookupFileName( + Vcb, + &FileName, + TargetMcb, + &Mcb, + &dinode1); + + if (NT_SUCCESS(Status)) + { + if ((!ReplaceIfExists) || + (IsFlagOn(Mcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY)) || + (IsFlagOn(Mcb->FileAttr, FILE_ATTRIBUTE_READONLY))) + { + Status = STATUS_OBJECT_NAME_COLLISION; + goto errorout; + } + + if (ReplaceIfExists) + { + Status = STATUS_NOT_IMPLEMENTED; + goto errorout; + } + } + + if (IsDirectory(Fcb)) + { + + Status = FFSRemoveEntry(IrpContext, Vcb, + Fcb->FFSMcb->Parent->FFSFcb, + DT_DIR, + Fcb->FFSMcb->Inode); + + if (!NT_SUCCESS(Status)) + { + FFSBreakPoint(); + + goto errorout; + } + + Status = FFSAddEntry(IrpContext, Vcb, + TargetDcb, + DT_DIR, + Fcb->FFSMcb->Inode, + &FileName); + + if (!NT_SUCCESS(Status)) + { + FFSBreakPoint(); + + FFSAddEntry(IrpContext, Vcb, + Fcb->FFSMcb->Parent->FFSFcb, + DT_DIR, + Fcb->FFSMcb->Inode, + &Fcb->FFSMcb->ShortName); + + goto errorout; + } + + if(!FFSv1SaveInode(IrpContext, + Vcb, + TargetMcb->Inode, + TargetDcb->dinode1)) + { + Status = STATUS_UNSUCCESSFUL; + + FFSBreakPoint(); + + goto errorout; + } + + if(!FFSv1SaveInode(IrpContext, + Vcb, + Fcb->FFSMcb->Parent->Inode, + Fcb->FFSMcb->Parent->FFSFcb->dinode1)) + { + Status = STATUS_UNSUCCESSFUL; + + FFSBreakPoint(); + + goto errorout; + } + + Status = FFSSetParentEntry(IrpContext, Vcb, Fcb, + Fcb->FFSMcb->Parent->Inode, + TargetDcb->FFSMcb->Inode); + + + if (!NT_SUCCESS(Status)) + { + FFSBreakPoint(); + goto errorout; + } + } + else + { + Status = FFSRemoveEntry(IrpContext, Vcb, + Fcb->FFSMcb->Parent->FFSFcb, + DT_REG, + Fcb->FFSMcb->Inode); + if (!NT_SUCCESS(Status)) + { + FFSBreakPoint(); + goto errorout; + } + + Status = FFSAddEntry(IrpContext, + Vcb, TargetDcb, + DT_REG, + Fcb->FFSMcb->Inode, + &FileName); + + if (!NT_SUCCESS(Status)) + { + FFSBreakPoint(); + + FFSAddEntry(IrpContext, Vcb, + Fcb->FFSMcb->Parent->FFSFcb, + DT_REG, + Fcb->FFSMcb->Inode, + &Fcb->FFSMcb->ShortName); + + goto errorout; + } + } + + if (NT_SUCCESS(Status)) + { + if (Fcb->FFSMcb->ShortName.MaximumLength < (FileName.Length + 2)) + { + ExFreePool(Fcb->FFSMcb->ShortName.Buffer); + Fcb->FFSMcb->ShortName.Buffer = + ExAllocatePoolWithTag(PagedPool, FileName.Length + 2, FFS_POOL_TAG); + + if (!Fcb->FFSMcb->ShortName.Buffer) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto errorout; + } + + Fcb->FFSMcb->ShortName.MaximumLength = FileName.Length + 2; + } + + { + RtlZeroMemory(Fcb->FFSMcb->ShortName.Buffer, + Fcb->FFSMcb->ShortName.MaximumLength); + + RtlCopyMemory(Fcb->FFSMcb->ShortName.Buffer, + FileName.Buffer, FileName.Length); + + Fcb->FFSMcb->ShortName.Length = FileName.Length; + } + +#if DBG + + Fcb->AnsiFileName.Length = (USHORT) + RtlxUnicodeStringToOemSize(&FileName); + + if (Fcb->AnsiFileName.MaximumLength < FileName.Length) + { + ExFreePool(Fcb->AnsiFileName.Buffer); + + Fcb->AnsiFileName.Buffer = + ExAllocatePoolWithTag(PagedPool, Fcb->AnsiFileName.Length + 1, FFS_POOL_TAG); + + if (!Fcb->AnsiFileName.Buffer) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto errorout; + } + + RtlZeroMemory(Fcb->AnsiFileName.Buffer, + Fcb->AnsiFileName.Length + 1); + Fcb->AnsiFileName.MaximumLength = + Fcb->AnsiFileName.Length + 1; + } + + FFSUnicodeToOEM(&(Fcb->AnsiFileName), + &FileName); + +#endif + + if (bMove) + { + FFSNotifyReportChange( + IrpContext, + Vcb, + Fcb, + (IsDirectory(Fcb) ? + FILE_NOTIFY_CHANGE_DIR_NAME : + FILE_NOTIFY_CHANGE_FILE_NAME), + FILE_ACTION_REMOVED); + + } + else + { + FFSNotifyReportChange( + IrpContext, + Vcb, + Fcb, + (IsDirectory(Fcb) ? + FILE_NOTIFY_CHANGE_DIR_NAME : + FILE_NOTIFY_CHANGE_FILE_NAME), + FILE_ACTION_RENAMED_OLD_NAME); + + } + + FFSDeleteMcbNode(Vcb, Fcb->FFSMcb->Parent, Fcb->FFSMcb); + FFSAddMcbNode(Vcb, TargetMcb, Fcb->FFSMcb); + + if (bMove) + { + FFSNotifyReportChange( + IrpContext, + Vcb, + Fcb, + (IsDirectory(Fcb) ? + FILE_NOTIFY_CHANGE_DIR_NAME : + FILE_NOTIFY_CHANGE_FILE_NAME), + FILE_ACTION_ADDED); + } + else + { + FFSNotifyReportChange( + IrpContext, + Vcb, + Fcb, + (IsDirectory(Fcb) ? + FILE_NOTIFY_CHANGE_DIR_NAME : + FILE_NOTIFY_CHANGE_FILE_NAME), + FILE_ACTION_RENAMED_NEW_NAME); + + } + } + +errorout: + + return Status; +} + + +__drv_mustHoldCriticalRegion +BOOLEAN +FFSDeleteFile( + PFFS_IRP_CONTEXT IrpContext, + PFFS_VCB Vcb, + PFFS_FCB Fcb) +{ + BOOLEAN bRet = FALSE; + LARGE_INTEGER AllocationSize; + PFFS_FCB Dcb = NULL; + + NTSTATUS Status; + + PAGED_CODE(); + + FFSPrint((DBG_INFO, "FFSDeleteFile: File %S (%xh) will be deleted!\n", + Fcb->FFSMcb->ShortName.Buffer, Fcb->FFSMcb->Inode)); + + if (IsFlagOn(Fcb->Flags, FCB_FILE_DELETED)) + { + return TRUE; + } + + if (FlagOn(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY)) + { + if (!FFSIsDirectoryEmpty(Vcb, Fcb)) + { + ClearFlag(Fcb->Flags, FCB_DELETE_PENDING); + + return FALSE; + } + } + + FFSPrint((DBG_INFO, "FFSDeleteFile: FFSSB->S_FREE_BLOCKS = %xh .\n", + Vcb->ffs_super_block->fs_size - Vcb->ffs_super_block->fs_dsize)); + + Status = STATUS_UNSUCCESSFUL; + + { + if (Fcb->FFSMcb->Parent->FFSFcb) + { + Status = FFSRemoveEntry( + IrpContext, Vcb, + Fcb->FFSMcb->Parent->FFSFcb, + (FlagOn(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY) ? + DT_DIR : DT_REG), + Fcb->FFSMcb->Inode); + } + else + { + Dcb = FFSCreateFcbFromMcb(Vcb, Fcb->FFSMcb->Parent); + if (Dcb) + { + Status = FFSRemoveEntry( + IrpContext, Vcb, Dcb, + (FlagOn(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY) ? + DT_DIR : DT_REG), + Fcb->FFSMcb->Inode); + } + } + } + + if (NT_SUCCESS(Status)) + { + Fcb->dinode1->di_nlink--; + + if (IsDirectory(Fcb)) + { + if (Fcb->dinode1->di_nlink < 2) + { + bRet = TRUE; + } + } + else + { + if (Fcb->dinode1->di_nlink == 0) + { + bRet = TRUE; + } + } + } + + + if (bRet) + { + AllocationSize.QuadPart = (LONGLONG)0; + bRet = FFSTruncateFile(IrpContext, Vcb, Fcb, &AllocationSize); + + // + // Update the inode's data length . It should be ZERO if succeeds. + // + + if (Fcb->dinode1->di_size > Fcb->Header.AllocationSize.LowPart) + { + Fcb->dinode1->di_size = Fcb->Header.AllocationSize.LowPart; + } + + Fcb->Header.FileSize.QuadPart = (LONGLONG) Fcb->dinode1->di_size; + + if (bRet) + { + { + LARGE_INTEGER SysTime; + KeQuerySystemTime(&SysTime); + + /*Fcb->dinode->di_dtime = FFSInodeTime(SysTime); XXX */ + + FFSv1SaveInode(IrpContext, Vcb, Fcb->FFSMcb->Inode, Fcb->dinode1); + } + + if (IsDirectory(Fcb)) + { + bRet = FFSFreeInode(IrpContext, Vcb, Fcb->FFSMcb->Inode, DT_DIR); + } + else + { + bRet = FFSFreeInode(IrpContext, Vcb, Fcb->FFSMcb->Inode, DT_REG); + } + + SetFlag(Fcb->Flags, FCB_FILE_DELETED); + FFSDeleteMcbNode(Vcb, Fcb->FFSMcb->Parent, Fcb->FFSMcb); + } + else + { + FFSv1SaveInode(IrpContext, Vcb, Fcb->FFSMcb->Inode, Fcb->dinode1); + } + } + else + { + FFSv1SaveInode(IrpContext, Vcb, Fcb->FFSMcb->Inode, Fcb->dinode1); + } + + FFSPrint((DBG_INFO, "FFSDeleteFile: Succeed... FFSSB->S_FREE_BLOCKS = %xh .\n", + Vcb->ffs_super_block->fs_size - Vcb->ffs_super_block->fs_dsize)); + + return bRet; +} + +#endif // !FFS_READ_ONLY diff --git a/reactos/drivers/filesystems/ffs/src/flush.c b/reactos/drivers/filesystems/ffs/src/flush.c new file mode 100644 index 00000000000..f3f42319a2d --- /dev/null +++ b/reactos/drivers/filesystems/ffs/src/flush.c @@ -0,0 +1,312 @@ +/* + * FFS File System Driver for Windows + * + * flush.c + * + * 2004.5.6 ~ + * + * Lee Jae-Hong, http://www.pyrasis.com + * + * See License.txt + * + */ + +#include "ntifs.h" +#include "ffsdrv.h" + +/* Globals */ + +extern PFFS_GLOBAL FFSGlobal; + + +/* Definitions */ + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE, FFSFlushFile) +#pragma alloc_text(PAGE, FFSFlushFiles) +#pragma alloc_text(PAGE, FFSFlushVolume) +#pragma alloc_text(PAGE, FFSFlush) +#endif + +#ifdef _PREFAST_ +IO_COMPLETION_ROUTINE FFSFlushCompletionRoutine; +#endif // _PREFAST_ + +NTSTATUS NTAPI +FFSFlushCompletionRoutine( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID Contxt) + +{ + if (Irp->PendingReturned) + IoMarkIrpPending(Irp); + + + if (Irp->IoStatus.Status == STATUS_INVALID_DEVICE_REQUEST) + Irp->IoStatus.Status = STATUS_SUCCESS; + + return STATUS_SUCCESS; +} + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSFlushFiles( + IN PFFS_VCB Vcb, + BOOLEAN bShutDown) +{ + IO_STATUS_BLOCK IoStatus; + + PFFS_FCB Fcb; + PLIST_ENTRY ListEntry; + + PAGED_CODE(); + + if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY) || + IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED)) + { + return STATUS_SUCCESS; + } + + FFSPrint((DBG_INFO, "Flushing Files ...\n")); + + // Flush all Fcbs in Vcb list queue. + { + for (ListEntry = Vcb->FcbList.Flink; + ListEntry != &Vcb->FcbList; + ListEntry = ListEntry->Flink) + { + Fcb = CONTAINING_RECORD(ListEntry, FFS_FCB, Next); + + if (ExAcquireResourceExclusiveLite( + &Fcb->MainResource, + TRUE)) + { + IoStatus.Status = FFSFlushFile(Fcb); +#if 0 +/* + if (bShutDown) + IoStatus.Status = FFSPurgeFile(Fcb, TRUE); + else + IoStatus.Status = FFSFlushFile(Fcb); +*/ +#endif + ExReleaseResourceForThreadLite( + &Fcb->MainResource, + ExGetCurrentResourceThread()); + } + } + } + + return IoStatus.Status; +} + + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSFlushVolume( + IN PFFS_VCB Vcb, + BOOLEAN bShutDown) +{ + IO_STATUS_BLOCK IoStatus; + + PAGED_CODE(); + + if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY) || + IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED)) + { + return STATUS_SUCCESS; + } + + FFSPrint((DBG_INFO, "FFSFlushVolume: Flushing Vcb ...\n")); + + ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE); + ExReleaseResourceLite(&Vcb->PagingIoResource); + + CcFlushCache(&(Vcb->SectionObject), NULL, 0, &IoStatus); + + return IoStatus.Status; +} + + +NTSTATUS +FFSFlushFile( + IN PFFS_FCB Fcb) +{ + IO_STATUS_BLOCK IoStatus; + + PAGED_CODE(); + + ASSERT(Fcb != NULL); + + ASSERT((Fcb->Identifier.Type == FFSFCB) && + (Fcb->Identifier.Size == sizeof(FFS_FCB))); + + if (IsDirectory(Fcb)) + return STATUS_SUCCESS; + + FFSPrint((DBG_INFO, "FFSFlushFile: Flushing File Inode=%xh %S ...\n", + Fcb->FFSMcb->Inode, Fcb->FFSMcb->ShortName.Buffer)); + /* + { + ULONG ResShCnt, ResExCnt; + ResShCnt = ExIsResourceAcquiredSharedLite(&Fcb->PagingIoResource); + ResExCnt = ExIsResourceAcquiredExclusiveLite(&Fcb->PagingIoResource); + + FFSPrint((DBG_INFO, "FFSFlushFile: PagingIoRes: %xh:%xh\n", ResShCnt, ResExCnt)); + } + */ + CcFlushCache(&(Fcb->SectionObject), NULL, 0, &IoStatus); + + ClearFlag(Fcb->Flags, FCB_FILE_MODIFIED); + + return IoStatus.Status; +} + + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSFlush( + IN PFFS_IRP_CONTEXT IrpContext) +{ + NTSTATUS Status; + + PIRP Irp; + PIO_STACK_LOCATION IrpSp; + + PFFS_VCB Vcb = 0; + PFFS_FCBVCB FcbOrVcb = 0; + PFILE_OBJECT FileObject; + + PDEVICE_OBJECT DeviceObject; + + BOOLEAN MainResourceAcquired = FALSE; + + PAGED_CODE(); + + _SEH2_TRY + { + ASSERT(IrpContext); + + ASSERT((IrpContext->Identifier.Type == FFSICX) && + (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); + + DeviceObject = IrpContext->DeviceObject; + + // + // This request is not allowed on the main device object + // + if (DeviceObject == FFSGlobal->DeviceObject) + { + Status = STATUS_INVALID_DEVICE_REQUEST; + _SEH2_LEAVE; + } + + Vcb = (PFFS_VCB)DeviceObject->DeviceExtension; + + ASSERT(Vcb != NULL); + + ASSERT((Vcb->Identifier.Type == FFSVCB) && + (Vcb->Identifier.Size == sizeof(FFS_VCB))); + + ASSERT(IsMounted(Vcb)); + + if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY) || + IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED)) + { + Status = STATUS_SUCCESS; + _SEH2_LEAVE; + } + + Irp = IrpContext->Irp; + + IrpSp = IoGetCurrentIrpStackLocation(Irp); + + FileObject = IrpContext->FileObject; + + FcbOrVcb = (PFFS_FCBVCB)FileObject->FsContext; + + ASSERT(FcbOrVcb != NULL); +#ifdef _MSC_VER +#pragma prefast( suppress: 28137, "by design" ) +#endif + if (!ExAcquireResourceExclusiveLite( + &FcbOrVcb->MainResource, + IrpContext->IsSynchronous)) + { + Status = STATUS_PENDING; + _SEH2_LEAVE; + } + + MainResourceAcquired = TRUE; + + if (FcbOrVcb->Identifier.Type == FFSVCB) + { + Status = FFSFlushFiles((PFFS_VCB)(FcbOrVcb), FALSE); + + if (NT_SUCCESS(Status)) + { + _SEH2_LEAVE; + } + + Status = FFSFlushVolume((PFFS_VCB)(FcbOrVcb), FALSE); + + if (NT_SUCCESS(Status) && IsFlagOn(Vcb->StreamObj->Flags, FO_FILE_MODIFIED)) + { + ClearFlag(Vcb->StreamObj->Flags, FO_FILE_MODIFIED); + } + } + else if (FcbOrVcb->Identifier.Type == FFSFCB) + { + Status = FFSFlushFile((PFFS_FCB)(FcbOrVcb)); + + if (NT_SUCCESS(Status) && IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED)) + { + ClearFlag(FileObject->Flags, FO_FILE_MODIFIED); + } + } + } + + _SEH2_FINALLY + { + if (MainResourceAcquired) + { + ExReleaseResourceForThreadLite( + &FcbOrVcb->MainResource, + ExGetCurrentResourceThread()); + } + + if (!IrpContext->ExceptionInProgress) + { + if (!IsFlagOn(Vcb->Flags, VCB_READ_ONLY)) + { + // Call the disk driver to flush the physial media. + NTSTATUS DriverStatus; + PIO_STACK_LOCATION NextIrpSp; + + IrpSp = IoGetCurrentIrpStackLocation(IrpContext->Irp); + NextIrpSp = IoGetNextIrpStackLocation(IrpContext->Irp); + + *NextIrpSp = *IrpSp; + + IoSetCompletionRoutine(IrpContext->Irp, + FFSFlushCompletionRoutine, + NULL, + TRUE, + TRUE, + TRUE); + + DriverStatus = IoCallDriver(Vcb->TargetDeviceObject, IrpContext->Irp); + + Status = (DriverStatus == STATUS_INVALID_DEVICE_REQUEST) ? + Status : DriverStatus; + + IrpContext->Irp = NULL; + } + + FFSCompleteIrpContext(IrpContext, Status); + } + } _SEH2_END; + + return Status; +} diff --git a/reactos/drivers/filesystems/ffs/src/fsctl.c b/reactos/drivers/filesystems/ffs/src/fsctl.c new file mode 100644 index 00000000000..251ea88b833 --- /dev/null +++ b/reactos/drivers/filesystems/ffs/src/fsctl.c @@ -0,0 +1,1663 @@ +/* + * FFS File System Driver for Windows + * + * fsctl.c + * + * 2004.5.6 ~ + * + * Lee Jae-Hong, http://www.pyrasis.com + * + * See License.txt + * + */ + +#include "ntifs.h" +#include "ffsdrv.h" + +/* Globals */ + +extern PFFS_GLOBAL FFSGlobal; + + +/* Definitions */ + +BOOLEAN +FFSIsMediaWriteProtected ( + IN PFFS_IRP_CONTEXT IrpContext, + IN PDEVICE_OBJECT TargetDevice); + +#ifdef ALLOC_PRAGMA +//#pragma alloc_text(PAGE, FFSSetVpbFlag) +//#pragma alloc_text(PAGE, FFSClearVpbFlag) +#pragma alloc_text(PAGE, FFSGetPartition) +#pragma alloc_text(PAGE, FFSLoadDiskLabel) +#pragma alloc_text(PAGE, FFSIsHandleCountZero) +#pragma alloc_text(PAGE, FFSLockVcb) +#pragma alloc_text(PAGE, FFSLockVolume) +#pragma alloc_text(PAGE, FFSUnlockVcb) +#pragma alloc_text(PAGE, FFSUnlockVolume) +#pragma alloc_text(PAGE, FFSAllowExtendedDasdIo) +#pragma alloc_text(PAGE, FFSUserFsRequest) +#pragma alloc_text(PAGE, FFSIsMediaWriteProtected) +#pragma alloc_text(PAGE, FFSMountVolume) +#pragma alloc_text(PAGE, FFSCheckDismount) +#pragma alloc_text(PAGE, FFSPurgeVolume) +#pragma alloc_text(PAGE, FFSPurgeFile) +#pragma alloc_text(PAGE, FFSDismountVolume) +#pragma alloc_text(PAGE, FFSIsVolumeMounted) +#pragma alloc_text(PAGE, FFSVerifyVolume) +#pragma alloc_text(PAGE, FFSFileSystemControl) +#endif + + +VOID +FFSSetVpbFlag( + IN PVPB Vpb, + IN USHORT Flag) +{ + KIRQL OldIrql; + + IoAcquireVpbSpinLock(&OldIrql); + + Vpb->Flags |= Flag; + + IoReleaseVpbSpinLock(OldIrql); +} + + +VOID +FFSClearVpbFlag( + IN PVPB Vpb, + IN USHORT Flag) +{ + KIRQL OldIrql; + + IoAcquireVpbSpinLock(&OldIrql); + + Vpb->Flags &= ~Flag; + + IoReleaseVpbSpinLock(OldIrql); +} + + +NTSTATUS +FFSGetPartition( + IN PDEVICE_OBJECT DeviceObject, + OUT ULONGLONG *StartOffset) +{ + CHAR Buffer[2048]; + PIRP Irp; + IO_STATUS_BLOCK IoStatus; + KEVENT Event; + NTSTATUS Status; + PARTITION_INFORMATION *PartInfo; + + PAGED_CODE(); + + if (IsFlagOn(DeviceObject->Characteristics, FILE_FLOPPY_DISKETTE)) + { + *StartOffset = 0; + return STATUS_SUCCESS; + } + + KeInitializeEvent(&Event, NotificationEvent, FALSE); + + Irp = IoBuildDeviceIoControlRequest( + IOCTL_DISK_GET_PARTITION_INFO, + DeviceObject, + NULL, + 0, + Buffer, + 2048, + FALSE, + &Event, + &IoStatus); + + if (!Irp) + { + return STATUS_INSUFFICIENT_RESOURCES; + } + + Status = IoCallDriver(DeviceObject, Irp); + if (!NT_SUCCESS(Status)) + { + return Status; + } + + Status = KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); + if (!NT_SUCCESS(Status)) + { + return Status; + } + + PartInfo = (PARTITION_INFORMATION *)Buffer; + *StartOffset = PartInfo->StartingOffset.QuadPart; + + return Status; +} + + +NTSTATUS +FFSLoadDiskLabel( + PDEVICE_OBJECT DeviceObject, + IN PFFS_VCB Vcb) +{ + NTSTATUS Status; + PFFS_SUPER_BLOCK FFSSb; + PDISKLABEL Disklabel; + int i; + int RootFS_VERSION; + ULONGLONG StartOffset = 0; + ULONGLONG FSOffset = 0; + ULONGLONG FSRootOffset = 0; + + PAGED_CODE(); + + Disklabel = (PDISKLABEL)ExAllocatePoolWithTag(PagedPool, sizeof(DISKLABEL), FFS_POOL_TAG); + + FFSReadDisk(Vcb, (LABELSECTOR * SECTOR_SIZE + LABELOFFSET), sizeof(DISKLABEL), (PVOID)Disklabel, FALSE); + + if (Disklabel->d_magic == DISKMAGIC) + { + KdPrint(("FFSLoadDiskLabel() Disklabel magic ok\n")); + + Status = STATUS_SUCCESS; + } + else + { + KdPrint(("FFSLoadDiskLabel() No BSD disklabel found, trying to find BSD file system on \"normal\" partition.\n")); + + if ((FFSSb = FFSLoadSuper(Vcb, FALSE, FSOffset + SBLOCK_UFS1)) && + (FFSSb->fs_magic == FS_UFS1_MAGIC)) + { + FFSPrint((DBG_VITAL, "FFSLoadDiskLabel() \"normal\" partition of FFSv1 file system is found.\n")); +/* + if ((FFSSb->fs_fsmnt[0] == '/') && (FFSSb->fs_fsmnt[1] == '\0')) + { + FFSGlobal->RootPartition = i; + FSRootOffset = FSOffset; + RootFS_VERSION = 1; + } +*/ + FS_VERSION = 1; + Vcb->FSOffset[0] = 0; + Vcb->PartitionNumber = 0; + Vcb->ffs_super_block = FFSSb; + Status = STATUS_SUCCESS; + return Status; + } + else if ((FFSSb = FFSLoadSuper(Vcb, FALSE, FSOffset + SBLOCK_UFS2)) && + (FFSSb->fs_magic == FS_UFS2_MAGIC)) + { + FFSPrint((DBG_VITAL, "FFSLoadDiskLabel() \"normal\" partition of FFSv2 file system is found.\n")); +/* + if ((FFSSb->fs_fsmnt[0] == '/') && (FFSSb->fs_fsmnt[1] == '\0')) + { + FFSGlobal->RootPartition = i; + FSRootOffset = FSOffset; + RootFS_VERSION = 2; + } +*/ + FS_VERSION = 2; + Vcb->FSOffset[0] = 0; + Vcb->PartitionNumber = 0; + Vcb->ffs_super_block = FFSSb; + Status = STATUS_SUCCESS; + return Status; + } + else + { + KdPrint(("FFSLoadDiskLabel() No BSD file system was found on the \"normal\" partition.\n")); + Status = STATUS_UNRECOGNIZED_VOLUME; + return Status; + } + } + + Status = FFSGetPartition(DeviceObject, &StartOffset); + if (!NT_SUCCESS(Status)) + { + KdPrint(("FFSLoadDiskLabel() Slice info failed, Status %u\n", Status)); + return Status; + } + + Vcb->PartitionNumber = FFSGlobal->PartitionNumber; + + KdPrint(("FFSLoadDiskLabel() Selected BSD Label : %d, StartOffset : %x\n", Vcb->PartitionNumber, StartOffset)); + + for (i = 0; i < MAXPARTITIONS; i++) + { + if (Disklabel->d_partitions[i].p_fstype == FS_BSDFFS) + { + /* Important */ + FSOffset = Disklabel->d_partitions[i].p_offset; + FSOffset = FSOffset * SECTOR_SIZE; + //FSOffset = FSOffset - StartOffset; + Vcb->FSOffset[i] = FSOffset; + /* Important */ + + KdPrint(("FFSLoadDiskLabel() Label %d, FS_BSDFFS, %x\n", i, Vcb->FSOffset[i])); + + if ((FFSSb = FFSLoadSuper(Vcb, FALSE, FSOffset + SBLOCK_UFS1)) && + (FFSSb->fs_magic == FS_UFS1_MAGIC)) + { + FFSPrint((DBG_VITAL, "FFSLoadDiskLabel() Label %d of FFSv1 file system is found.\n", i)); + + if ((FFSSb->fs_fsmnt[0] == '/') && (FFSSb->fs_fsmnt[1] == '\0')) + { + Vcb->RootPartition = i; + FSRootOffset = FSOffset; + RootFS_VERSION = 1; + } + + FS_VERSION = 1; + + if (i == (int)Vcb->PartitionNumber) + { + Vcb->ffs_super_block = FFSSb; + } + + Status = STATUS_SUCCESS; + } + else if ((FFSSb = FFSLoadSuper(Vcb, FALSE, FSOffset + SBLOCK_UFS2)) && + (FFSSb->fs_magic == FS_UFS2_MAGIC)) + { + FFSPrint((DBG_VITAL, "FFSLoadDiskLabel() Label %d of FFSv2 file system is found.\n", i)); + + if ((FFSSb->fs_fsmnt[0] == '/') && (FFSSb->fs_fsmnt[1] == '\0')) + { + Vcb->RootPartition = i; + FSRootOffset = FSOffset; + RootFS_VERSION = 2; + } + + FS_VERSION = 2; + + if (i == (int)Vcb->PartitionNumber) + { + Vcb->ffs_super_block = FFSSb; + } + + Status = STATUS_SUCCESS; + } + } +#if 0 + else if (i == (int)FFSGlobal->PartitionNumber) + { + /* ¼±ÅÃµÈ BSD ÆÄƼ¼ÇÀÌ µð½ºÅ©¿¡ ¾øÀ» °æ¿ì Root ÆÄƼ¼ÇÀ¸·Î ´ëü */ + if (RootFS_VERSION == 1) + { + FFSSb = FFSLoadSuper(Vcb, FALSE, FSRootOffset + SBLOCK_UFS1); + Vcb->ffs_super_block = FFSSb; + FFSGlobal->PartitionNumber = FFSGlobal->RootPartition; + } + else + { + FFSSb = FFSLoadSuper(Vcb, FALSE, FSRootOffset + SBLOCK_UFS2); + Vcb->ffs_super_block = FFSSb; + FFSGlobal->PartitionNumber = FFSGlobal->RootPartition; + } + } +#endif + } + + if (Vcb->ffs_super_block == NULL) + Status = STATUS_UNRECOGNIZED_VOLUME; + + return Status; +} + + +BOOLEAN +FFSIsHandleCountZero( + IN PFFS_VCB Vcb) +{ + PFFS_FCB Fcb; + PLIST_ENTRY List; + + PAGED_CODE(); + + for(List = Vcb->FcbList.Flink; + List != &Vcb->FcbList; + List = List->Flink) + { + Fcb = CONTAINING_RECORD(List, FFS_FCB, Next); + + ASSERT((Fcb->Identifier.Type == FFSFCB) && + (Fcb->Identifier.Size == sizeof(FFS_FCB))); + + FFSPrint((DBG_INFO, "FFSIsHandleCountZero: Inode:%xh File:%S OpenHandleCount=%xh\n", + Fcb->FFSMcb->Inode, Fcb->FFSMcb->ShortName.Buffer, Fcb->OpenHandleCount)); + + if (Fcb->OpenHandleCount) + { + return FALSE; + } + } + + return TRUE; +} + + +NTSTATUS +FFSLockVcb( + IN PFFS_VCB Vcb, + IN PFILE_OBJECT FileObject) +{ + NTSTATUS Status; + + PAGED_CODE(); + + _SEH2_TRY + { + if (FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED)) + { + FFSPrint((DBG_INFO, "FFSLockVolume: Volume is already locked.\n")); + + Status = STATUS_ACCESS_DENIED; + + _SEH2_LEAVE; + } + + if (Vcb->OpenFileHandleCount > (ULONG)(FileObject ? 1 : 0)) + { + FFSPrint((DBG_INFO, "FFSLockVcb: There are still opened files.\n")); + + Status = STATUS_ACCESS_DENIED; + + _SEH2_LEAVE; + } + + if (!FFSIsHandleCountZero(Vcb)) + { + FFSPrint((DBG_INFO, "FFSLockVcb: Thare are still opened files.\n")); + + Status = STATUS_ACCESS_DENIED; + + _SEH2_LEAVE; + } + + SetFlag(Vcb->Flags, VCB_VOLUME_LOCKED); + + FFSSetVpbFlag(Vcb->Vpb, VPB_LOCKED); + + Vcb->LockFile = FileObject; + + FFSPrint((DBG_INFO, "FFSLockVcb: Volume locked.\n")); + + Status = STATUS_SUCCESS; + } + + _SEH2_FINALLY + { + // Nothing + } _SEH2_END; + + return Status; +} + + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSLockVolume( + IN PFFS_IRP_CONTEXT IrpContext) +{ + PIO_STACK_LOCATION IrpSp; + PDEVICE_OBJECT DeviceObject; + PFFS_VCB Vcb = 0; + NTSTATUS Status; + BOOLEAN VcbResourceAcquired = FALSE; + + PAGED_CODE(); + + _SEH2_TRY + { + ASSERT(IrpContext != NULL); + + ASSERT((IrpContext->Identifier.Type == FFSICX) && + (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); + + DeviceObject = IrpContext->DeviceObject; + + Status = STATUS_UNSUCCESSFUL; + + // + // This request is not allowed on the main device object + // + if (DeviceObject == FFSGlobal->DeviceObject) + { + Status = STATUS_INVALID_PARAMETER; + _SEH2_LEAVE; + } + + Vcb = (PFFS_VCB)DeviceObject->DeviceExtension; + + ASSERT(Vcb != NULL); + + ASSERT((Vcb->Identifier.Type == FFSVCB) && + (Vcb->Identifier.Size == sizeof(FFS_VCB))); + + ASSERT(IsMounted(Vcb)); + + IrpSp = IoGetCurrentIrpStackLocation(IrpContext->Irp); + +#if (_WIN32_WINNT >= 0x0500) + CcWaitForCurrentLazyWriterActivity(); +#endif + ExAcquireResourceExclusiveLite( + &Vcb->MainResource, + TRUE); + + VcbResourceAcquired = TRUE; + + Status = FFSLockVcb(Vcb, IrpSp->FileObject); + } + + _SEH2_FINALLY + { + if (VcbResourceAcquired) + { + ExReleaseResourceForThreadLite( + &Vcb->MainResource, + ExGetCurrentResourceThread()); + } + + if (!IrpContext->ExceptionInProgress) + { + FFSCompleteIrpContext(IrpContext, Status); + } + } _SEH2_END; + + return Status; +} + + +NTSTATUS +FFSUnlockVcb( + IN PFFS_VCB Vcb, + IN PFILE_OBJECT FileObject) +{ + NTSTATUS Status; + + PAGED_CODE(); + + _SEH2_TRY + { + if (FileObject && FileObject->FsContext != Vcb) + { + Status = STATUS_NOT_LOCKED; + _SEH2_LEAVE; + } + + if (!FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED)) + { + FFSPrint((DBG_ERROR, ": FFSUnlockVcb: Volume is not locked.\n")); + Status = STATUS_NOT_LOCKED; + _SEH2_LEAVE; + } + + if (Vcb->LockFile == FileObject) + { + ClearFlag(Vcb->Flags, VCB_VOLUME_LOCKED); + + FFSClearVpbFlag(Vcb->Vpb, VPB_LOCKED); + + FFSPrint((DBG_INFO, "FFSUnlockVcb: Volume unlocked.\n")); + + Status = STATUS_SUCCESS; + } + else + { + Status = STATUS_NOT_LOCKED; + } + } + + _SEH2_FINALLY + { + // Nothing + } _SEH2_END; + + return Status; +} + + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSUnlockVolume( + IN PFFS_IRP_CONTEXT IrpContext) +{ + PIO_STACK_LOCATION IrpSp; + PDEVICE_OBJECT DeviceObject; + NTSTATUS Status; + PFFS_VCB Vcb = 0; + BOOLEAN VcbResourceAcquired = FALSE; + + PAGED_CODE(); + + _SEH2_TRY + { + ASSERT(IrpContext != NULL); + + ASSERT((IrpContext->Identifier.Type == FFSICX) && + (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); + + DeviceObject = IrpContext->DeviceObject; + + // + // This request is not allowed on the main device object + // + if (DeviceObject == FFSGlobal->DeviceObject) + { + Status = STATUS_INVALID_PARAMETER; + _SEH2_LEAVE; + } + + Vcb = (PFFS_VCB)DeviceObject->DeviceExtension; + + ASSERT(Vcb != NULL); + + ASSERT((Vcb->Identifier.Type == FFSVCB) && + (Vcb->Identifier.Size == sizeof(FFS_VCB))); + + ASSERT(IsMounted(Vcb)); + + IrpSp = IoGetCurrentIrpStackLocation(IrpContext->Irp); + + ExAcquireResourceExclusiveLite( + &Vcb->MainResource, + TRUE); + + VcbResourceAcquired = TRUE; + + Status = FFSUnlockVcb(Vcb, IrpSp->FileObject); + } + _SEH2_FINALLY + { + if (VcbResourceAcquired) + { + ExReleaseResourceForThreadLite( + &Vcb->MainResource, + ExGetCurrentResourceThread()); + } + + if (!IrpContext->ExceptionInProgress) + { + FFSCompleteIrpContext(IrpContext, Status); + } + } _SEH2_END; + + return Status; +} + + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSInvalidateVolumes( + IN PFFS_IRP_CONTEXT IrpContext) +{ + NTSTATUS Status; + PIRP Irp; + PIO_STACK_LOCATION IrpSp; + + HANDLE Handle; + + PLIST_ENTRY ListEntry; + + PFILE_OBJECT FileObject; + PDEVICE_OBJECT DeviceObject; + BOOLEAN GlobalResourceAcquired = FALSE; + + LUID Privilege = {SE_TCB_PRIVILEGE, 0}; + + _SEH2_TRY + { + Irp = IrpContext->Irp; + IrpSp = IoGetCurrentIrpStackLocation(Irp); + + if (!SeSinglePrivilegeCheck(Privilege, Irp->RequestorMode)) + { + Status = STATUS_PRIVILEGE_NOT_HELD; + _SEH2_LEAVE; + } + + if ( +#if !defined(_GNU_NTIFS_) || defined(__REACTOS__) + IrpSp->Parameters.FileSystemControl.InputBufferLength +#else + ((PEXTENDED_IO_STACK_LOCATION)(IrpSp))-> + Parameters.FileSystemControl.InputBufferLength +#endif + != sizeof(HANDLE)) + { + Status = STATUS_INVALID_PARAMETER; + + _SEH2_LEAVE; + } + + Handle = *(PHANDLE)Irp->AssociatedIrp.SystemBuffer; + + Status = ObReferenceObjectByHandle(Handle, + 0, + *IoFileObjectType, + KernelMode, + (void **)&FileObject, + NULL); + + if (!NT_SUCCESS(Status)) + { + _SEH2_LEAVE; + } + else + { + ObDereferenceObject(FileObject); + DeviceObject = FileObject->DeviceObject; + } + + FFSPrint((DBG_INFO, "FFSInvalidateVolumes: FileObject=%xh ...\n", FileObject)); + + ExAcquireResourceExclusiveLite( + &FFSGlobal->Resource, + TRUE); + + GlobalResourceAcquired = TRUE; + + ListEntry = FFSGlobal->VcbList.Flink; + + while (ListEntry != &FFSGlobal->VcbList) + { + PFFS_VCB Vcb; + + Vcb = CONTAINING_RECORD(ListEntry, FFS_VCB, Next); + + ListEntry = ListEntry->Flink; + + FFSPrint((DBG_INFO, "FFSInvalidateVolumes: Vcb=%xh Vcb->Vpb=%xh...\n", Vcb, Vcb->Vpb)); + if (Vcb->Vpb && (Vcb->Vpb->RealDevice == DeviceObject)) + { + ExAcquireResourceExclusiveLite(&Vcb->MainResource, TRUE); + FFSPrint((DBG_INFO, "FFSInvalidateVolumes: FFSPurgeVolume...\n")); + FFSPurgeVolume(Vcb, FALSE); + ClearFlag(Vcb->Flags, VCB_MOUNTED); + ExReleaseResourceLite(&Vcb->MainResource); + + // + // Vcb is still attached on the list ...... + // + + if (ListEntry->Blink == &Vcb->Next) + { + FFSPrint((DBG_INFO, "FFSInvalidateVolumes: FFSCheckDismount...\n")); + FFSCheckDismount(IrpContext, Vcb, FALSE); + } + } + } + } + + _SEH2_FINALLY + { + if (GlobalResourceAcquired) + { + ExReleaseResourceForThreadLite( + &FFSGlobal->Resource, + ExGetCurrentResourceThread()); + } + + FFSCompleteIrpContext(IrpContext, Status); + } _SEH2_END; + + return Status; +} + + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSAllowExtendedDasdIo( + IN PFFS_IRP_CONTEXT IrpContext) +{ + PIO_STACK_LOCATION IrpSp; + PFFS_VCB Vcb; + PFFS_CCB Ccb; + + PAGED_CODE(); + + IrpSp = IoGetCurrentIrpStackLocation(IrpContext->Irp); + + Vcb = (PFFS_VCB)IrpSp->FileObject->FsContext; + Ccb = (PFFS_CCB)IrpSp->FileObject->FsContext2; + + ASSERT(Vcb != NULL); + + ASSERT((Vcb->Identifier.Type == FFSVCB) && + (Vcb->Identifier.Size == sizeof(FFS_VCB))); + + ASSERT(IsMounted(Vcb)); + + if (Ccb) + { + SetFlag(Ccb->Flags, CCB_ALLOW_EXTENDED_DASD_IO); + + FFSCompleteIrpContext(IrpContext, STATUS_SUCCESS); + + return STATUS_SUCCESS; + } + else + { + return STATUS_INVALID_PARAMETER; + } +} + + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSUserFsRequest( + IN PFFS_IRP_CONTEXT IrpContext) +{ + PIRP Irp; + PIO_STACK_LOCATION IoStackLocation; + ULONG FsControlCode; + NTSTATUS Status; + + PAGED_CODE(); + + ASSERT(IrpContext); + + ASSERT((IrpContext->Identifier.Type == FFSICX) && + (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); + + Irp = IrpContext->Irp; + + IoStackLocation = IoGetCurrentIrpStackLocation(Irp); + +#if !defined(_GNU_NTIFS_) || defined(__REACTOS__) + FsControlCode = + IoStackLocation->Parameters.FileSystemControl.FsControlCode; +#else + FsControlCode = ((PEXTENDED_IO_STACK_LOCATION) + IoStackLocation)->Parameters.FileSystemControl.FsControlCode; +#endif + + switch (FsControlCode) + { + case FSCTL_LOCK_VOLUME: + Status = FFSLockVolume(IrpContext); + break; + + case FSCTL_UNLOCK_VOLUME: + Status = FFSUnlockVolume(IrpContext); + break; + + case FSCTL_DISMOUNT_VOLUME: + Status = FFSDismountVolume(IrpContext); + break; + + case FSCTL_IS_VOLUME_MOUNTED: + Status = FFSIsVolumeMounted(IrpContext); + break; + + case FSCTL_INVALIDATE_VOLUMES: + Status = FFSInvalidateVolumes(IrpContext); + break; + +#if (_WIN32_WINNT >= 0x0500) + case FSCTL_ALLOW_EXTENDED_DASD_IO: + Status = FFSAllowExtendedDasdIo(IrpContext); + break; +#endif //(_WIN32_WINNT >= 0x0500) + + default: + + FFSPrint((DBG_ERROR, "FFSUserFsRequest: Invalid User Request: %xh.\n", FsControlCode)); + Status = STATUS_INVALID_DEVICE_REQUEST; + + FFSCompleteIrpContext(IrpContext, Status); + } + + return Status; +} + + +BOOLEAN +FFSIsMediaWriteProtected( + IN PFFS_IRP_CONTEXT IrpContext, + IN PDEVICE_OBJECT TargetDevice) +{ + PIRP Irp; + KEVENT Event; + NTSTATUS Status; + IO_STATUS_BLOCK IoStatus; + + PAGED_CODE(); + + KeInitializeEvent(&Event, NotificationEvent, FALSE); + + Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_IS_WRITABLE, + TargetDevice, + NULL, + 0, + NULL, + 0, + FALSE, + &Event, + &IoStatus); + + if (Irp == NULL) + { + return FALSE; + } + + SetFlag(IoGetNextIrpStackLocation(Irp)->Flags, SL_OVERRIDE_VERIFY_VOLUME); + + Status = IoCallDriver(TargetDevice, Irp); + + if (Status == STATUS_PENDING) + { + + (VOID) KeWaitForSingleObject(&Event, + Executive, + KernelMode, + FALSE, + (PLARGE_INTEGER)NULL); + + Status = IoStatus.Status; + } + + return (BOOLEAN)(Status == STATUS_MEDIA_WRITE_PROTECTED); +} + + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSMountVolume( + IN PFFS_IRP_CONTEXT IrpContext) +{ + PDEVICE_OBJECT MainDeviceObject; + BOOLEAN GlobalDataResourceAcquired = FALSE; + PIRP Irp; + PIO_STACK_LOCATION IoStackLocation; + PDEVICE_OBJECT TargetDeviceObject; + NTSTATUS Status = STATUS_UNRECOGNIZED_VOLUME; + PDEVICE_OBJECT VolumeDeviceObject = NULL; + PFFS_VCB Vcb; + PFFS_SUPER_BLOCK FFSSb = NULL; + ULONG dwBytes; + DISK_GEOMETRY DiskGeometry; + + PAGED_CODE(); + + _SEH2_TRY + { + ASSERT(IrpContext != NULL); + + ASSERT((IrpContext->Identifier.Type == FFSICX) && + (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); + + MainDeviceObject = IrpContext->DeviceObject; + + // + // Make sure we can wait. + // + + SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); + + // + // This request is only allowed on the main device object + // + if (MainDeviceObject != FFSGlobal->DeviceObject) + { + Status = STATUS_INVALID_DEVICE_REQUEST; + _SEH2_LEAVE; + } + + ExAcquireResourceExclusiveLite( + &(FFSGlobal->Resource), + TRUE); + + GlobalDataResourceAcquired = TRUE; + + if (FlagOn(FFSGlobal->Flags, FFS_UNLOAD_PENDING)) + { + Status = STATUS_UNRECOGNIZED_VOLUME; + _SEH2_LEAVE; + } + + Irp = IrpContext->Irp; + + IoStackLocation = IoGetCurrentIrpStackLocation(Irp); + + TargetDeviceObject = + IoStackLocation->Parameters.MountVolume.DeviceObject; + + dwBytes = sizeof(DISK_GEOMETRY); + Status = FFSDiskIoControl( + TargetDeviceObject, + IOCTL_DISK_GET_DRIVE_GEOMETRY, + NULL, + 0, + &DiskGeometry, + &dwBytes); + + if (!NT_SUCCESS(Status)) + { + _SEH2_LEAVE; + } + + Status = IoCreateDevice( + MainDeviceObject->DriverObject, + sizeof(FFS_VCB), + NULL, + FILE_DEVICE_DISK_FILE_SYSTEM, + 0, + FALSE, + &VolumeDeviceObject); + + if (!NT_SUCCESS(Status)) + { + _SEH2_LEAVE; + } + + VolumeDeviceObject->StackSize = (CCHAR)(TargetDeviceObject->StackSize + 1); + + if (TargetDeviceObject->AlignmentRequirement > + VolumeDeviceObject->AlignmentRequirement) + { + + VolumeDeviceObject->AlignmentRequirement = + TargetDeviceObject->AlignmentRequirement; + } + + (IoStackLocation->Parameters.MountVolume.Vpb)->DeviceObject = + VolumeDeviceObject; + + Vcb = (PFFS_VCB)VolumeDeviceObject->DeviceExtension; + + RtlZeroMemory(Vcb, sizeof(FFS_VCB)); + + Vcb->Identifier.Type = FFSVCB; + Vcb->Identifier.Size = sizeof(FFS_VCB); + + Vcb->TargetDeviceObject = TargetDeviceObject; + Vcb->DiskGeometry = DiskGeometry; + + Status = FFSLoadDiskLabel(TargetDeviceObject, Vcb); + + if (!NT_SUCCESS(Status)) + { + _SEH2_LEAVE; + } + + + FFSSb = Vcb->ffs_super_block; + + Vcb->BlockSize = FFSSb->fs_bsize; + Vcb->SectorBits = FFSLog2(SECTOR_SIZE); + + Status = FFSInitializeVcb(IrpContext, Vcb, FFSSb, TargetDeviceObject, + VolumeDeviceObject, IoStackLocation->Parameters.MountVolume.Vpb); + + if (NT_SUCCESS(Status)) + { + if (FFSIsMediaWriteProtected(IrpContext, TargetDeviceObject)) + { + SetFlag(Vcb->Flags, VCB_WRITE_PROTECTED); + } + else + { + ClearFlag(Vcb->Flags, VCB_WRITE_PROTECTED); + } + + SetFlag(Vcb->Flags, VCB_MOUNTED); + + FFSInsertVcb(Vcb); + + ClearFlag(VolumeDeviceObject->Flags, DO_DEVICE_INITIALIZING); + } + } + + _SEH2_FINALLY + { + if (GlobalDataResourceAcquired) + { + ExReleaseResourceForThreadLite( + &FFSGlobal->Resource, + ExGetCurrentResourceThread()); + } + + if (!NT_SUCCESS(Status)) + { + if (FFSSb) + { + ExFreePool(FFSSb); + } + + if (VolumeDeviceObject) + { + IoDeleteDevice(VolumeDeviceObject); + } + } + + if (!IrpContext->ExceptionInProgress) + { + if (NT_SUCCESS(Status)) + { + ClearFlag(VolumeDeviceObject->Flags, DO_DEVICE_INITIALIZING); + } + + FFSCompleteIrpContext(IrpContext, Status); + } + } _SEH2_END; + + return Status; +} + + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSVerifyVolume( + IN PFFS_IRP_CONTEXT IrpContext) +{ + PDEVICE_OBJECT DeviceObject; + NTSTATUS Status = STATUS_UNSUCCESSFUL; + PFFS_SUPER_BLOCK FFSSb = NULL; + PFFS_VCB Vcb = 0; + BOOLEAN VcbResourceAcquired = FALSE; + BOOLEAN GlobalResourceAcquired = FALSE; + PIRP Irp; + PIO_STACK_LOCATION IoStackLocation; + ULONG ChangeCount; + ULONG dwReturn; + + PAGED_CODE(); + + _SEH2_TRY + { + ASSERT(IrpContext != NULL); + + ASSERT((IrpContext->Identifier.Type == FFSICX) && + (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); + + DeviceObject = IrpContext->DeviceObject; + // + // This request is not allowed on the main device object + // + if (DeviceObject == FFSGlobal->DeviceObject) + { + Status = STATUS_INVALID_DEVICE_REQUEST; + _SEH2_LEAVE; + } + + ExAcquireResourceExclusiveLite( + &FFSGlobal->Resource, + TRUE); + + GlobalResourceAcquired = TRUE; + + Vcb = (PFFS_VCB)DeviceObject->DeviceExtension; + + ASSERT(Vcb != NULL); + + ASSERT((Vcb->Identifier.Type == FFSVCB) && + (Vcb->Identifier.Size == sizeof(FFS_VCB))); + + ExAcquireResourceExclusiveLite( + &Vcb->MainResource, + TRUE); + + VcbResourceAcquired = TRUE; + + if (!FlagOn(Vcb->TargetDeviceObject->Flags, DO_VERIFY_VOLUME)) + { + Status = STATUS_SUCCESS; + _SEH2_LEAVE; + } + + if (!IsMounted(Vcb)) + { + Status = STATUS_WRONG_VOLUME; + _SEH2_LEAVE; + } + + dwReturn = sizeof(ULONG); + Status = FFSDiskIoControl( + Vcb->TargetDeviceObject, + IOCTL_DISK_CHECK_VERIFY, + NULL, + 0, + &ChangeCount, + &dwReturn); + + if (ChangeCount != Vcb->ChangeCount) + { + Status = STATUS_WRONG_VOLUME; + _SEH2_LEAVE; + } + + Irp = IrpContext->Irp; + + IoStackLocation = IoGetCurrentIrpStackLocation(Irp); + + if (((((FFSSb = FFSLoadSuper(Vcb, TRUE, SBLOCK_UFS1)) != NULL) && (FFSSb->fs_magic == FS_UFS1_MAGIC)) || + (((FFSSb = FFSLoadSuper(Vcb, TRUE, SBLOCK_UFS2)) != NULL) && (FFSSb->fs_magic == FS_UFS2_MAGIC))) && + (memcmp(FFSSb->fs_id, SUPER_BLOCK->fs_id, 8) == 0) && + (memcmp(FFSSb->fs_volname, SUPER_BLOCK->fs_volname, 16) == 0)) + { + ClearFlag(Vcb->TargetDeviceObject->Flags, DO_VERIFY_VOLUME); + + if (FFSIsMediaWriteProtected(IrpContext, Vcb->TargetDeviceObject)) + { + SetFlag(Vcb->Flags, VCB_WRITE_PROTECTED); + } + else + { + ClearFlag(Vcb->Flags, VCB_WRITE_PROTECTED); + } + + FFSPrint((DBG_INFO, "FFSVerifyVolume: Volume verify succeeded.\n")); + + Status = STATUS_SUCCESS; + } + else + { + Status = STATUS_WRONG_VOLUME; + + FFSPurgeVolume(Vcb, FALSE); + + SetFlag(Vcb->Flags, VCB_DISMOUNT_PENDING); + + ClearFlag(Vcb->TargetDeviceObject->Flags, DO_VERIFY_VOLUME); + + FFSPrint((DBG_INFO, "FFSVerifyVolume: Volume verify failed.\n")); + } + } + + _SEH2_FINALLY + { + if (FFSSb) + ExFreePool(FFSSb); + + if (VcbResourceAcquired) + { + ExReleaseResourceForThreadLite( + &Vcb->MainResource, + ExGetCurrentResourceThread()); + } + + if (GlobalResourceAcquired) + { + ExReleaseResourceForThreadLite( + &FFSGlobal->Resource, + ExGetCurrentResourceThread()); + } + + if (!IrpContext->ExceptionInProgress) + { + FFSCompleteIrpContext(IrpContext, Status); + } + } _SEH2_END; + + return Status; +} + + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSIsVolumeMounted( + IN PFFS_IRP_CONTEXT IrpContext) +{ + PAGED_CODE(); + + ASSERT(IrpContext); + + ASSERT((IrpContext->Identifier.Type == FFSICX) && + (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); + + return FFSVerifyVolume(IrpContext); +} + + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSDismountVolume( + IN PFFS_IRP_CONTEXT IrpContext) +{ + PDEVICE_OBJECT DeviceObject; + NTSTATUS Status = STATUS_UNSUCCESSFUL; + PFFS_VCB Vcb = 0; + BOOLEAN VcbResourceAcquired = FALSE; + + PAGED_CODE(); + + _SEH2_TRY + { + ASSERT(IrpContext != NULL); + + ASSERT((IrpContext->Identifier.Type == FFSICX) && + (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); + + DeviceObject = IrpContext->DeviceObject; + + // + // This request is not allowed on the main device object + // + if (DeviceObject == FFSGlobal->DeviceObject) + { + Status = STATUS_INVALID_DEVICE_REQUEST; + _SEH2_LEAVE; + } + + Vcb = (PFFS_VCB)DeviceObject->DeviceExtension; + + ASSERT(Vcb != NULL); + + ASSERT((Vcb->Identifier.Type == FFSVCB) && + (Vcb->Identifier.Size == sizeof(FFS_VCB))); + + ASSERT(IsMounted(Vcb)); + + ExAcquireResourceExclusiveLite( + &Vcb->MainResource, + TRUE); + + VcbResourceAcquired = TRUE; + + if (IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING)) + { + Status = STATUS_VOLUME_DISMOUNTED; + _SEH2_LEAVE; + } + + /* + if (!FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED)) + { + FFSPrint((DBG_ERROR, "FFSDismount: Volume is not locked.\n")); + + Status = STATUS_ACCESS_DENIED; + _SEH2_LEAVE; + } + */ + + FFSFlushFiles(Vcb, FALSE); + + FFSFlushVolume(Vcb, FALSE); + + FFSPurgeVolume(Vcb, TRUE); + + ExReleaseResourceForThreadLite( + &Vcb->MainResource, + ExGetCurrentResourceThread()); + + VcbResourceAcquired = FALSE; + + FFSCheckDismount(IrpContext, Vcb, TRUE); + + FFSPrint((DBG_INFO, "FFSDismount: Volume dismount pending.\n")); + + Status = STATUS_SUCCESS; + } + _SEH2_FINALLY + { + if (VcbResourceAcquired) + { + ExReleaseResourceForThreadLite( + &Vcb->MainResource, + ExGetCurrentResourceThread()); + } + + if (!IrpContext->ExceptionInProgress) + { + FFSCompleteIrpContext(IrpContext, Status); + } + } _SEH2_END; + + return Status; +} + + +__drv_mustHoldCriticalRegion +BOOLEAN +FFSCheckDismount( + IN PFFS_IRP_CONTEXT IrpContext, + IN PFFS_VCB Vcb, + IN BOOLEAN bForce) +{ + KIRQL Irql; + PVPB Vpb = Vcb->Vpb; + BOOLEAN bDeleted = FALSE; + ULONG UnCleanCount = 0; + + PAGED_CODE(); + + ExAcquireResourceExclusiveLite( + &FFSGlobal->Resource, TRUE); + + ExAcquireResourceExclusiveLite( + &Vcb->MainResource, TRUE); + + if ((IrpContext->MajorFunction == IRP_MJ_CREATE) && + (IrpContext->RealDevice == Vcb->RealDevice)) + { + UnCleanCount = 3; + } + else + { + UnCleanCount = 2; + } + + IoAcquireVpbSpinLock(&Irql); + + if ((Vpb->ReferenceCount == UnCleanCount) || bForce) + { + + if ((Vpb->ReferenceCount != UnCleanCount) && bForce) + { + FFSBreakPoint(); + } + + ClearFlag(Vpb->Flags, VPB_MOUNTED); + ClearFlag(Vpb->Flags, VPB_LOCKED); + + if ((Vcb->RealDevice != Vpb->RealDevice) && +#ifdef _MSC_VER +#pragma prefast( suppress: 28175, "allowed in file system drivers" ) +#endif + (Vcb->RealDevice->Vpb == Vpb)) + { + SetFlag(Vcb->RealDevice->Flags, DO_DEVICE_INITIALIZING); + SetFlag(Vpb->Flags, VPB_PERSISTENT); + } + + FFSRemoveVcb(Vcb); + + ClearFlag(Vpb->Flags, VPB_MOUNTED); + SetFlag(Vcb->Flags, VCB_DISMOUNT_PENDING); + + Vpb->DeviceObject = NULL; + + bDeleted = TRUE; + } + +#if 0 + + else if ((Vpb->RealDevice->Vpb == Vpb) && bForce) + { + PVPB NewVpb; + +#define TAG_VPB ' bpV' + + NewVpb = ExAllocatePoolWithTag(NonPagedPoolMustSucceed, + sizeof(VPB), TAG_VPB); + + NewVpb->Type = IO_TYPE_VPB; + NewVpb->Size = sizeof(VPB); + NewVpb->RealDevice = Vcb->Vpb->RealDevice; + + NewVpb->RealDevice->Vpb = NewVpb; + + NewVpb->Flags = FlagOn(Vcb->Vpb->Flags, VPB_REMOVE_PENDING); + + NewVpb = NULL; + + ClearFlag(Vcb->Flags, VCB_MOUNTED); + ClearFlag(Vcb->Flags, VCB_DISMOUNT_PENDING); + } + +#endif + + IoReleaseVpbSpinLock(Irql); + + ExReleaseResourceForThreadLite( + &Vcb->MainResource, + ExGetCurrentResourceThread()); + + ExReleaseResourceForThreadLite( + &FFSGlobal->Resource, + ExGetCurrentResourceThread()); + + if (bDeleted) + { +#if 0 + FFSBreakPoint(); /* XP¿¡¼­ ºê·¹ÀÌÅ© Æ÷ÀÎÆ® ¹ß»ý */ +#endif + + FFSFreeVcb(Vcb); + } + + return bDeleted; +} + + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSPurgeVolume( + IN PFFS_VCB Vcb, + IN BOOLEAN FlushBeforePurge) +{ + PFFS_FCB Fcb; + LIST_ENTRY FcbList; + PLIST_ENTRY ListEntry; + PFCB_LIST_ENTRY FcbListEntry; + + PAGED_CODE(); + + _SEH2_TRY + { + ASSERT(Vcb != NULL); + + ASSERT((Vcb->Identifier.Type == FFSVCB) && + (Vcb->Identifier.Size == sizeof(FFS_VCB))); + + if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY) || + IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED)) + { + FlushBeforePurge = FALSE; + } + + FcbListEntry= NULL; + InitializeListHead(&FcbList); + + for (ListEntry = Vcb->FcbList.Flink; + ListEntry != &Vcb->FcbList; + ListEntry = ListEntry->Flink) + { + Fcb = CONTAINING_RECORD(ListEntry, FFS_FCB, Next); + + Fcb->ReferenceCount++; + + FFSPrint((DBG_INFO, "FFSPurgeVolume: %s refercount=%xh\n", Fcb->AnsiFileName.Buffer, Fcb->ReferenceCount)); + + FcbListEntry = ExAllocatePoolWithTag(PagedPool, sizeof(FCB_LIST_ENTRY), FFS_POOL_TAG); + + if (FcbListEntry) + { + FcbListEntry->Fcb = Fcb; + + InsertTailList(&FcbList, &FcbListEntry->Next); + } + else + { + FFSPrint((DBG_ERROR, "FFSPurgeVolume: Error allocating FcbListEntry ...\n")); + } + } + + while (!IsListEmpty(&FcbList)) + { + ListEntry = RemoveHeadList(&FcbList); + + FcbListEntry = CONTAINING_RECORD(ListEntry, FCB_LIST_ENTRY, Next); + + Fcb = FcbListEntry->Fcb; + + if (ExAcquireResourceExclusiveLite( + &Fcb->MainResource, + TRUE)) + { + FFSPurgeFile(Fcb, FlushBeforePurge); + + if (!Fcb->OpenHandleCount && Fcb->ReferenceCount == 1) + { + RemoveEntryList(&Fcb->Next); + FFSFreeFcb(Fcb); + } + else + { + ExReleaseResourceForThreadLite( + &Fcb->MainResource, + ExGetCurrentResourceThread()); + } + } + + ExFreePool(FcbListEntry); + } + + if (FlushBeforePurge) + { + ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE); + ExReleaseResourceLite(&Vcb->PagingIoResource); + + CcFlushCache(&Vcb->SectionObject, NULL, 0, NULL); + } + + if (Vcb->SectionObject.ImageSectionObject) + { + MmFlushImageSection(&Vcb->SectionObject, MmFlushForWrite); + } + + if (Vcb->SectionObject.DataSectionObject) + { + CcPurgeCacheSection(&Vcb->SectionObject, NULL, 0, FALSE); + } + + FFSPrint((DBG_INFO, "FFSPurgeVolume: Volume flushed and purged.\n")); + } + _SEH2_FINALLY + { + // Nothing + } _SEH2_END; + + return STATUS_SUCCESS; +} + + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSPurgeFile( + IN PFFS_FCB Fcb, + IN BOOLEAN FlushBeforePurge) +{ + IO_STATUS_BLOCK IoStatus; + + PAGED_CODE(); + + ASSERT(Fcb != NULL); + + ASSERT((Fcb->Identifier.Type == FFSFCB) && + (Fcb->Identifier.Size == sizeof(FFS_FCB))); + + + if(!IsFlagOn(Fcb->Vcb->Flags, VCB_READ_ONLY) && FlushBeforePurge && + !IsFlagOn(Fcb->Vcb->Flags, VCB_WRITE_PROTECTED)) + { + + FFSPrint((DBG_INFO, "FFSPurgeFile: CcFlushCache on %s.\n", + Fcb->AnsiFileName.Buffer)); + + ExAcquireSharedStarveExclusive(&Fcb->PagingIoResource, TRUE); + ExReleaseResourceLite(&Fcb->PagingIoResource); + + CcFlushCache(&Fcb->SectionObject, NULL, 0, &IoStatus); + + ClearFlag(Fcb->Flags, FCB_FILE_MODIFIED); + } + + if (Fcb->SectionObject.ImageSectionObject) + { + + FFSPrint((DBG_INFO, "FFSPurgeFile: MmFlushImageSection on %s.\n", + Fcb->AnsiFileName.Buffer)); + + MmFlushImageSection(&Fcb->SectionObject, MmFlushForWrite); + } + + if (Fcb->SectionObject.DataSectionObject) + { + + FFSPrint((DBG_INFO, "FFSPurgeFile: CcPurgeCacheSection on %s.\n", + Fcb->AnsiFileName.Buffer)); + + CcPurgeCacheSection(&Fcb->SectionObject, NULL, 0, FALSE); + } + + return STATUS_SUCCESS; +} + + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSSelectBSDPartition( + IN PFFS_IRP_CONTEXT IrpContext) +{ + PIRP Irp; + NTSTATUS Status; + PFFS_BSD_PARTITION BSDPartition; + + _SEH2_TRY + { + ASSERT(IrpContext != NULL); + + ASSERT((IrpContext->Identifier.Type == FFSICX) && + (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); + + Irp = IrpContext->Irp; + + BSDPartition = (PFFS_BSD_PARTITION)Irp->AssociatedIrp.SystemBuffer; + FFSGlobal->PartitionNumber = BSDPartition->Number; + + Status = STATUS_SUCCESS; + } + _SEH2_FINALLY + { + if (!IrpContext->ExceptionInProgress) + { + FFSCompleteIrpContext(IrpContext, Status); + } + } _SEH2_END; + + return Status; +} + + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSFileSystemControl( + IN PFFS_IRP_CONTEXT IrpContext) +{ + NTSTATUS Status; + + PAGED_CODE(); + + ASSERT(IrpContext); + + ASSERT((IrpContext->Identifier.Type == FFSICX) && + (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); + + switch (IrpContext->MinorFunction) + { + case IRP_MN_USER_FS_REQUEST: + Status = FFSUserFsRequest(IrpContext); + break; + + case IRP_MN_MOUNT_VOLUME: + Status = FFSMountVolume(IrpContext); + break; + + case IRP_MN_VERIFY_VOLUME: + Status = FFSVerifyVolume(IrpContext); + break; + + default: + + FFSPrint((DBG_ERROR, "FFSFilsSystemControl: Invalid Device Request.\n")); + Status = STATUS_INVALID_DEVICE_REQUEST; + FFSCompleteIrpContext(IrpContext, Status); + } + + return Status; +} diff --git a/reactos/drivers/filesystems/ffs/src/init.c b/reactos/drivers/filesystems/ffs/src/init.c new file mode 100644 index 00000000000..df9189e6c7d --- /dev/null +++ b/reactos/drivers/filesystems/ffs/src/init.c @@ -0,0 +1,453 @@ +/* + * FFS File System Driver for Windows + * + * init.c + * + * 2004.5.6 ~ + * + * Lee Jae-Hong, http://www.pyrasis.com + * + * See License.txt + * + */ + +#include +#ifndef __REACTOS__ +#include +#endif +#include "ffsdrv.h" + +/* Globals */ + +PFFS_GLOBAL FFSGlobal = NULL; + + +/* Definitions */ + +NTSTATUS NTAPI +DriverEntry( + IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath); + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(INIT, FFSQueryParameters) +#pragma alloc_text(INIT, DriverEntry) +#if FFS_UNLOAD +#pragma alloc_text(PAGE, DriverUnload) +#endif +#endif + + +#if FFS_UNLOAD + +/* + * FUNCTION: Called by the system to unload the driver + * ARGUMENTS: + * DriverObject = object describing this driver + * RETURNS: None + */ + +VOID NTAPI +DriverUnload( + IN PDRIVER_OBJECT DriverObject) +{ + UNICODE_STRING DosDeviceName; + + PAGED_CODE(); + + FFSPrint((DBG_FUNC, "ffsdrv: Unloading routine.\n")); + + RtlInitUnicodeString(&DosDeviceName, DOS_DEVICE_NAME); + IoDeleteSymbolicLink(&DosDeviceName); + + ExDeleteResourceLite(&FFSGlobal->LAResource); + ExDeleteResourceLite(&FFSGlobal->CountResource); + ExDeleteResourceLite(&FFSGlobal->Resource); + + ExDeletePagedLookasideList(&(FFSGlobal->FFSMcbLookasideList)); + ExDeleteNPagedLookasideList(&(FFSGlobal->FFSCcbLookasideList)); + ExDeleteNPagedLookasideList(&(FFSGlobal->FFSFcbLookasideList)); + ExDeleteNPagedLookasideList(&(FFSGlobal->FFSIrpContextLookasideList)); + + IoDeleteDevice(FFSGlobal->DeviceObject); +} + +#endif + +BOOLEAN +FFSQueryParameters( + IN PUNICODE_STRING RegistryPath) +{ + NTSTATUS Status; + UNICODE_STRING ParameterPath; + RTL_QUERY_REGISTRY_TABLE QueryTable[2]; + + ULONG WritingSupport; + ULONG CheckingBitmap; + ULONG PartitionNumber; + + ParameterPath.Length = 0; + + ParameterPath.MaximumLength = + RegistryPath->Length + sizeof(PARAMETERS_KEY) + sizeof(WCHAR); + + ParameterPath.Buffer = + (PWSTR) ExAllocatePoolWithTag(PagedPool, ParameterPath.MaximumLength, FFS_POOL_TAG); + + if (!ParameterPath.Buffer) + { + return FALSE; + } + + WritingSupport = 0; + CheckingBitmap = 0; + PartitionNumber = 0; + + RtlCopyUnicodeString(&ParameterPath, RegistryPath); + + RtlAppendUnicodeToString(&ParameterPath, PARAMETERS_KEY); + + RtlZeroMemory(&QueryTable[0], sizeof(RTL_QUERY_REGISTRY_TABLE) * 2); + + QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; + QueryTable[0].Name = WRITING_SUPPORT; + QueryTable[0].EntryContext = &WritingSupport; + + Status = RtlQueryRegistryValues( + RTL_REGISTRY_ABSOLUTE, + ParameterPath.Buffer, + &QueryTable[0], + NULL, + NULL); + + FFSPrint((DBG_USER, "FFSQueryParameters: WritingSupport=%xh\n", WritingSupport)); + + RtlZeroMemory(&QueryTable[0], sizeof(RTL_QUERY_REGISTRY_TABLE) * 2); + + QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; + QueryTable[0].Name = CHECKING_BITMAP; + QueryTable[0].EntryContext = &CheckingBitmap; + + Status = RtlQueryRegistryValues( + RTL_REGISTRY_ABSOLUTE, + ParameterPath.Buffer, + &QueryTable[0], + NULL, + NULL); + + FFSPrint((DBG_USER, "FFSQueryParameters: CheckingBitmap=%xh\n", CheckingBitmap)); + + RtlZeroMemory(&QueryTable[0], sizeof(RTL_QUERY_REGISTRY_TABLE) * 2); + + QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; + QueryTable[0].Name = PARTITION_NUMBER; + QueryTable[0].EntryContext = &PartitionNumber; + + Status = RtlQueryRegistryValues( + RTL_REGISTRY_ABSOLUTE, + ParameterPath.Buffer, + &QueryTable[0], + NULL, + NULL); + + FFSPrint((DBG_USER, "FFSQueryParameters: PartitionNumber=%xh\n", PartitionNumber)); + + { + if (WritingSupport) + { + SetFlag(FFSGlobal->Flags, FFS_SUPPORT_WRITING); + } + else + { + ClearFlag(FFSGlobal->Flags, FFS_SUPPORT_WRITING); + } + + if (CheckingBitmap) + { + SetFlag(FFSGlobal->Flags, FFS_CHECKING_BITMAP); + } + else + { + ClearFlag(FFSGlobal->Flags, FFS_CHECKING_BITMAP); + } + + if (PartitionNumber) + { + FFSGlobal->PartitionNumber = PartitionNumber; + } + + } + + ExFreePool(ParameterPath.Buffer); + + return TRUE; +} + + +#define NLS_OEM_LEAD_BYTE_INFO (*NlsOemLeadByteInfo) + +#ifndef __REACTOS__ +#define FsRtlIsLeadDbcsCharacter(DBCS_CHAR) ( \ + (BOOLEAN)((UCHAR)(DBCS_CHAR) < 0x80 ? FALSE : \ + (NLS_MB_CODE_PAGE_TAG && \ + (NLS_OEM_LEAD_BYTE_INFO[(UCHAR)(DBCS_CHAR)] != 0))) \ +) +#endif + + +/* + * NAME: DriverEntry + * FUNCTION: Called by the system to initalize the driver + * + * ARGUMENTS: + * DriverObject = object describing this driver + * RegistryPath = path to our configuration entries + * RETURNS: Success or failure + */ +NTSTATUS NTAPI +DriverEntry( + IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath) +{ + PDEVICE_OBJECT DeviceObject; + PFAST_IO_DISPATCH FastIoDispatch; + PCACHE_MANAGER_CALLBACKS CacheManagerCallbacks; + PFFS_EXT DeviceExt; + UNICODE_STRING DeviceName; +#ifndef __REACTOS__ + UNICODE_STRING Sddl; +#endif + NTSTATUS Status; +#if FFS_UNLOAD + UNICODE_STRING DosDeviceName; +#endif + + DbgPrint( + "ffsdrv --" + " Version " + FFSDRV_VERSION +#if FFS_READ_ONLY + " (ReadOnly)" +#endif // FFS_READ_ONLY +#if DBG + " Checked" +#else + " Free" +#endif + " - Built at " + __DATE__" " + __TIME__".\n"); + + FFSPrint((DBG_FUNC, "FFS DriverEntry ...\n")); + + RtlInitUnicodeString(&DeviceName, DEVICE_NAME); +#ifndef __REACTOS__ + RtlInitUnicodeString(&Sddl, L"D:P(A;;GA;;;SY)(A;;GA;;;BA)(A;;GA;;;BU)"); + + Status = IoCreateDeviceSecure( + DriverObject, + sizeof(FFS_EXT), + &DeviceName, + FILE_DEVICE_DISK_FILE_SYSTEM, + 0, + FALSE, + &Sddl, + NULL, + &DeviceObject); +#else + + Status = IoCreateDevice( + DriverObject, + sizeof(FFS_EXT), + &DeviceName, + FILE_DEVICE_DISK_FILE_SYSTEM, + 0, + FALSE, + &DeviceObject); +#endif + if (!NT_SUCCESS(Status)) + { + FFSPrint((DBG_ERROR, "IoCreateDevice fs object error.\n")); + return Status; + } + + DeviceExt = (PFFS_EXT)DeviceObject->DeviceExtension; + RtlZeroMemory(DeviceExt, sizeof(FFS_EXT)); + + FFSGlobal = &(DeviceExt->FFSGlobal); + + FFSGlobal->Identifier.Type = FFSFGD; + FFSGlobal->Identifier.Size = sizeof(FFS_GLOBAL); + FFSGlobal->DeviceObject = DeviceObject; + FFSGlobal->DriverObject = DriverObject; + FFSGlobal->PartitionNumber = 0; + + FFSQueryParameters(RegistryPath); + + DriverObject->MajorFunction[IRP_MJ_CREATE] = FFSBuildRequest; + DriverObject->MajorFunction[IRP_MJ_CLOSE] = FFSBuildRequest; + DriverObject->MajorFunction[IRP_MJ_READ] = FFSBuildRequest; +#if !FFS_READ_ONLY + DriverObject->MajorFunction[IRP_MJ_WRITE] = FFSBuildRequest; +#endif // !FFS_READ_ONLY + + DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = FFSBuildRequest; + DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = FFSBuildRequest; + + DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = FFSBuildRequest; + DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = FFSBuildRequest; + + DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = FFSBuildRequest; +#if !FFS_READ_ONLY + DriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION] = FFSBuildRequest; +#endif // !FFS_READ_ONLY + + DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = FFSBuildRequest; + DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = FFSBuildRequest; + DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = FFSBuildRequest; + DriverObject->MajorFunction[IRP_MJ_LOCK_CONTROL] = FFSBuildRequest; + + DriverObject->MajorFunction[IRP_MJ_CLEANUP] = FFSBuildRequest; + +#if (_WIN32_WINNT >= 0x0500) + DriverObject->MajorFunction[IRP_MJ_PNP] = FFSBuildRequest; +#endif //(_WIN32_WINNT >= 0x0500) + +#if FFS_UNLOAD +#ifdef _MSC_VER +#pragma prefast( suppress: 28175, "allowed to unload" ) +#endif + DriverObject->DriverUnload = DriverUnload; +#else +#ifdef _MSC_VER +#pragma prefast( suppress: 28175, "allowed to unload" ) +#endif + DriverObject->DriverUnload = NULL; +#endif + + // + // Initialize the fast I/O entry points + // + + FastIoDispatch = &(FFSGlobal->FastIoDispatch); + + FastIoDispatch->SizeOfFastIoDispatch = sizeof(FAST_IO_DISPATCH); + FastIoDispatch->FastIoCheckIfPossible = FFSFastIoCheckIfPossible; +#if DBG + FastIoDispatch->FastIoRead = FFSFastIoRead; +#if !FFS_READ_ONLY + FastIoDispatch->FastIoWrite = FFSFastIoWrite; +#endif // !FFS_READ_ONLY +#else +#ifdef _MSC_VER +#pragma prefast( suppress: 28155, "allowed in file system drivers" ) +#endif + FastIoDispatch->FastIoRead = FsRtlCopyRead; +#if !FFS_READ_ONLY +#ifdef _MSC_VER +#pragma prefast( suppress: 28155, "allowed in file system drivers" ) +#endif + FastIoDispatch->FastIoWrite = FsRtlCopyWrite; +#endif // !FFS_READ_ONLY +#endif + FastIoDispatch->FastIoQueryBasicInfo = FFSFastIoQueryBasicInfo; + FastIoDispatch->FastIoQueryStandardInfo = FFSFastIoQueryStandardInfo; + FastIoDispatch->FastIoLock = FFSFastIoLock; + FastIoDispatch->FastIoUnlockSingle = FFSFastIoUnlockSingle; + FastIoDispatch->FastIoUnlockAll = FFSFastIoUnlockAll; + FastIoDispatch->FastIoUnlockAllByKey = FFSFastIoUnlockAllByKey; + FastIoDispatch->FastIoQueryNetworkOpenInfo = FFSFastIoQueryNetworkOpenInfo; + +#ifdef _MSC_VER +#pragma prefast( suppress: 28175, "allowed in file system drivers" ) +#endif + DriverObject->FastIoDispatch = FastIoDispatch; + + switch (MmQuerySystemSize()) + { + case MmSmallSystem: + + FFSGlobal->MaxDepth = 16; + break; + + case MmMediumSystem: + + FFSGlobal->MaxDepth = 64; + break; + + case MmLargeSystem: + + FFSGlobal->MaxDepth = 256; + break; + } + + // + // Initialize the Cache Manager callbacks + // + + CacheManagerCallbacks = &(FFSGlobal->CacheManagerCallbacks); + CacheManagerCallbacks->AcquireForLazyWrite = FFSAcquireForLazyWrite; + CacheManagerCallbacks->ReleaseFromLazyWrite = FFSReleaseFromLazyWrite; + CacheManagerCallbacks->AcquireForReadAhead = FFSAcquireForReadAhead; + CacheManagerCallbacks->ReleaseFromReadAhead = FFSReleaseFromReadAhead; + + FFSGlobal->CacheManagerNoOpCallbacks.AcquireForLazyWrite = FFSNoOpAcquire; + FFSGlobal->CacheManagerNoOpCallbacks.ReleaseFromLazyWrite = FFSNoOpRelease; + FFSGlobal->CacheManagerNoOpCallbacks.AcquireForReadAhead = FFSNoOpAcquire; + FFSGlobal->CacheManagerNoOpCallbacks.ReleaseFromReadAhead = FFSNoOpRelease; + + + // + // Initialize the global data + // + + InitializeListHead(&(FFSGlobal->VcbList)); + ExInitializeResourceLite(&(FFSGlobal->Resource)); + ExInitializeResourceLite(&(FFSGlobal->CountResource)); + ExInitializeResourceLite(&(FFSGlobal->LAResource)); + + ExInitializeNPagedLookasideList(&(FFSGlobal->FFSIrpContextLookasideList), + NULL, + NULL, + 0, + sizeof(FFS_IRP_CONTEXT), + 'SFF', + 0); + + ExInitializeNPagedLookasideList(&(FFSGlobal->FFSFcbLookasideList), + NULL, + NULL, + 0, + sizeof(FFS_FCB), + 'SFF', + 0); + + ExInitializeNPagedLookasideList(&(FFSGlobal->FFSCcbLookasideList), + NULL, + NULL, + 0, + sizeof(FFS_CCB), + 'SFF', + 0); + + ExInitializePagedLookasideList(&(FFSGlobal->FFSMcbLookasideList), + NULL, + NULL, + 0, + sizeof(FFS_MCB), + 'SFF', + 0); + +#if FFS_UNLOAD + RtlInitUnicodeString(&DosDeviceName, DOS_DEVICE_NAME); + IoCreateSymbolicLink(&DosDeviceName, &DeviceName); +#endif + +#if DBG + ProcessNameOffset = FFSGetProcessNameOffset(); +#endif + + IoRegisterFileSystem(DeviceObject); + + return Status; +} diff --git a/reactos/drivers/filesystems/ffs/src/lock.c b/reactos/drivers/filesystems/ffs/src/lock.c new file mode 100644 index 00000000000..9ff3ba9b814 --- /dev/null +++ b/reactos/drivers/filesystems/ffs/src/lock.c @@ -0,0 +1,137 @@ +/* + * FFS File System Driver for Windows + * + * lock.c + * + * 2004.5.6 ~ + * + * Lee Jae-Hong, http://www.pyrasis.com + * + * See License.txt + * + */ + +#include "ntifs.h" +#include "ffsdrv.h" + +/* Globals */ + +extern PFFS_GLOBAL FFSGlobal; + + +/* Definitions */ + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE, FFSLockControl) +#endif + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSLockControl( + IN PFFS_IRP_CONTEXT IrpContext) +{ + PDEVICE_OBJECT DeviceObject; + BOOLEAN CompleteRequest; + NTSTATUS Status = STATUS_UNSUCCESSFUL; + PFILE_OBJECT FileObject; + PFFS_FCB Fcb; + PIRP Irp; + + PAGED_CODE(); + + _SEH2_TRY + { + ASSERT(IrpContext != NULL); + + ASSERT((IrpContext->Identifier.Type == FFSICX) && + (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); + + DeviceObject = IrpContext->DeviceObject; + + if (DeviceObject == FFSGlobal->DeviceObject) + { + CompleteRequest = TRUE; + Status = STATUS_INVALID_DEVICE_REQUEST; + _SEH2_LEAVE; + } + + FileObject = IrpContext->FileObject; + + Fcb = (PFFS_FCB)FileObject->FsContext; + + ASSERT(Fcb != NULL); + + if (Fcb->Identifier.Type == FFSVCB) + { + CompleteRequest = TRUE; + Status = STATUS_INVALID_PARAMETER; + _SEH2_LEAVE; + } + + ASSERT((Fcb->Identifier.Type == FFSFCB) && + (Fcb->Identifier.Size == sizeof(FFS_FCB))); + + if (FlagOn(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY)) + { + CompleteRequest = TRUE; + Status = STATUS_INVALID_PARAMETER; + _SEH2_LEAVE; + } + + Irp = IrpContext->Irp; + + // + // While the file has any byte range locks we set IsFastIoPossible to + // FastIoIsQuestionable so that the FastIoCheckIfPossible function is + // called to check the locks for any fast I/O read/write operation. + // + if (Fcb->Header.IsFastIoPossible != FastIoIsQuestionable) + { + + FFSPrint((DBG_INFO, + "FFSLockControl: %-16.16s %-31s %s\n", + FFSGetCurrentProcessName(), + "FastIoIsQuestionable", + Fcb->AnsiFileName.Buffer)); + + Fcb->Header.IsFastIoPossible = FastIoIsQuestionable; + } + + // + // FsRtlProcessFileLock acquires FileObject->FsContext->Resource while + // modifying the file locks and calls IoCompleteRequest when it's done. + // + + CompleteRequest = FALSE; + + Status = FsRtlProcessFileLock( + &Fcb->FileLockAnchor, + Irp, + NULL); + + if (!NT_SUCCESS(Status)) + { + FFSPrint((DBG_ERROR, + "FFSLockControl: %-16.16s %-31s *** Status: %s (%#x) ***\n", + FFSGetCurrentProcessName(), + "IRP_MJ_LOCK_CONTROL", + FFSNtStatusToString(Status), + Status)); + } + } + + _SEH2_FINALLY + { + if (!IrpContext->ExceptionInProgress) + { + if (!CompleteRequest) + { + IrpContext->Irp = NULL; + } + + FFSCompleteIrpContext(IrpContext, Status); + } + } _SEH2_END; + + return Status; +} diff --git a/reactos/drivers/filesystems/ffs/src/memory.c b/reactos/drivers/filesystems/ffs/src/memory.c new file mode 100644 index 00000000000..790a04b854f --- /dev/null +++ b/reactos/drivers/filesystems/ffs/src/memory.c @@ -0,0 +1,1979 @@ +/* + * FFS File System Driver for Windows + * + * memory.c + * + * 2004.5.6 ~ + * + * Lee Jae-Hong, http://www.pyrasis.com + * + * See License.txt + * + */ + +#include "ntifs.h" +#include "ffsdrv.h" + +/* Globals */ + +extern PFFS_GLOBAL FFSGlobal; + + +/* Definitions */ + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE, FFSAllocateIrpContext) +#pragma alloc_text(PAGE, FFSFreeIrpContext) +#pragma alloc_text(PAGE, FFSv1AllocateFcb) +#pragma alloc_text(PAGE, FFSv2AllocateFcb) +#pragma alloc_text(PAGE, FFSFreeFcb) +#pragma alloc_text(PAGE, FFSAllocateMcb) +#pragma alloc_text(PAGE, FFSFreeMcb) +#pragma alloc_text(PAGE, FFSSearchMcbTree) +#pragma alloc_text(PAGE, FFSSearchMcb) +#pragma alloc_text(PAGE, FFSGetFullFileName) +#pragma alloc_text(PAGE, FFSRefreshMcb) +#pragma alloc_text(PAGE, FFSAddMcbNode) +#pragma alloc_text(PAGE, FFSDeleteMcbNode) +#pragma alloc_text(PAGE, FFSFreeMcbTree) +#pragma alloc_text(PAGE, FFSCheckBitmapConsistency) +#pragma alloc_text(PAGE, FFSCheckSetBlock) +#pragma alloc_text(PAGE, FFSInitializeVcb) +#pragma alloc_text(PAGE, FFSFreeCcb) +#pragma alloc_text(PAGE, FFSAllocateCcb) +#pragma alloc_text(PAGE, FFSFreeVcb) +#pragma alloc_text(PAGE, FFSCreateFcbFromMcb) +#pragma alloc_text(PAGE, FFSSyncUninitializeCacheMap) +#endif + + +__drv_mustHoldCriticalRegion +PFFS_IRP_CONTEXT +FFSAllocateIrpContext( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PIO_STACK_LOCATION IoStackLocation; + PFFS_IRP_CONTEXT IrpContext; + + PAGED_CODE(); + + ASSERT(DeviceObject != NULL); + ASSERT(Irp != NULL); + + IoStackLocation = IoGetCurrentIrpStackLocation(Irp); + + ExAcquireResourceExclusiveLite( + &FFSGlobal->LAResource, + TRUE); + + IrpContext = (PFFS_IRP_CONTEXT)(ExAllocateFromNPagedLookasideList(&(FFSGlobal->FFSIrpContextLookasideList))); + + ExReleaseResourceForThreadLite( + &FFSGlobal->LAResource, + ExGetCurrentResourceThread()); + + if (IrpContext == NULL) + { + IrpContext = ExAllocatePoolWithTag(NonPagedPool, sizeof(FFS_IRP_CONTEXT), FFS_POOL_TAG); + + // + // Zero out the irp context and indicate that it is from pool and + // not region allocated + // + + RtlZeroMemory(IrpContext, sizeof(FFS_IRP_CONTEXT)); + + SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_FROM_POOL); + } + else + { + // + // Zero out the irp context and indicate that it is from zone and + // not pool allocated + // + + RtlZeroMemory(IrpContext, sizeof(FFS_IRP_CONTEXT)); + } + + if (!IrpContext) + { + return NULL; + } + + IrpContext->Identifier.Type = FFSICX; + IrpContext->Identifier.Size = sizeof(FFS_IRP_CONTEXT); + + IrpContext->Irp = Irp; + + IrpContext->MajorFunction = IoStackLocation->MajorFunction; + IrpContext->MinorFunction = IoStackLocation->MinorFunction; + + IrpContext->DeviceObject = DeviceObject; + + IrpContext->FileObject = IoStackLocation->FileObject; + + if (IrpContext->FileObject != NULL) + { + IrpContext->RealDevice = IrpContext->FileObject->DeviceObject; + } + else if (IrpContext->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL) + { + if (IoStackLocation->Parameters.MountVolume.Vpb) + { + IrpContext->RealDevice = + IoStackLocation->Parameters.MountVolume.Vpb->RealDevice; + } + } + + if (IrpContext->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL || + IrpContext->MajorFunction == IRP_MJ_DEVICE_CONTROL || + IrpContext->MajorFunction == IRP_MJ_SHUTDOWN) + { + IrpContext->IsSynchronous = TRUE; + } + else if (IrpContext->MajorFunction == IRP_MJ_CLEANUP || + IrpContext->MajorFunction == IRP_MJ_CLOSE) + { + IrpContext->IsSynchronous = FALSE; + } +#if (_WIN32_WINNT >= 0x0500) + else if (IrpContext->MajorFunction == IRP_MJ_PNP) + { + if (IoGetCurrentIrpStackLocation(Irp)->FileObject == NULL) + { + IrpContext->IsSynchronous = TRUE; + } + else + { + IrpContext->IsSynchronous = IoIsOperationSynchronous(Irp); + } + } +#endif //(_WIN32_WINNT >= 0x0500) + else + { + IrpContext->IsSynchronous = IoIsOperationSynchronous(Irp); + } + +#if 0 + // + // Temporary workaround for a bug in close that makes it reference a + // fileobject when it is no longer valid. + // + if (IrpContext->MajorFunction == IRP_MJ_CLOSE) + { + IrpContext->IsSynchronous = TRUE; + } +#endif + + IrpContext->IsTopLevel = (IoGetTopLevelIrp() == Irp); + + IrpContext->ExceptionInProgress = FALSE; + + return IrpContext; +} + + +__drv_mustHoldCriticalRegion +VOID +FFSFreeIrpContext( + IN PFFS_IRP_CONTEXT IrpContext) +{ + PAGED_CODE(); + + ASSERT(IrpContext != NULL); + + ASSERT((IrpContext->Identifier.Type == FFSICX) && + (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); + + FFSUnpinRepinnedBcbs(IrpContext); + + // Return the Irp context record to the region or to pool depending on + // its flag + + if (FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_FROM_POOL)) + { + IrpContext->Identifier.Type = 0; + IrpContext->Identifier.Size = 0; + + ExFreePool(IrpContext); + } + else + { + IrpContext->Identifier.Type = 0; + IrpContext->Identifier.Size = 0; + + ExAcquireResourceExclusiveLite( + &FFSGlobal->LAResource, + TRUE); + + ExFreeToNPagedLookasideList(&(FFSGlobal->FFSIrpContextLookasideList), IrpContext); + + ExReleaseResourceForThreadLite( + &FFSGlobal->LAResource, + ExGetCurrentResourceThread()); + + } +} + + +VOID +FFSRepinBcb( + IN PFFS_IRP_CONTEXT IrpContext, + IN PBCB Bcb) +{ + PFFS_REPINNED_BCBS Repinned; + ULONG i; + + Repinned = &IrpContext->Repinned; + + + return; + + while (Repinned) + { + for (i = 0; i < FFS_REPINNED_BCBS_ARRAY_SIZE; i += 1) + { + if (Repinned->Bcb[i] == Bcb) + { + return; + } + } + + Repinned = Repinned->Next; + } + + while (TRUE) + { + for (i = 0; i < FFS_REPINNED_BCBS_ARRAY_SIZE; i += 1) + { + if (Repinned->Bcb[i] == Bcb) + { + return; + } + + if (Repinned->Bcb[i] == NULL) + { + Repinned->Bcb[i] = Bcb; + CcRepinBcb(Bcb); + + return; + } + } + + if (Repinned->Next == NULL) + { + Repinned->Next = ExAllocatePoolWithTag(PagedPool, sizeof(FFS_REPINNED_BCBS), FFS_POOL_TAG); + RtlZeroMemory(Repinned->Next, sizeof(FFS_REPINNED_BCBS)); + } + + Repinned = Repinned->Next; + } +} + + +VOID +FFSUnpinRepinnedBcbs( + IN PFFS_IRP_CONTEXT IrpContext) +{ + IO_STATUS_BLOCK RaiseIosb; + PFFS_REPINNED_BCBS Repinned; + BOOLEAN WriteThroughToDisk; + PFILE_OBJECT FileObject = NULL; + BOOLEAN ForceVerify = FALSE; + ULONG i; + + Repinned = &IrpContext->Repinned; + RaiseIosb.Status = STATUS_SUCCESS; + + WriteThroughToDisk = (BOOLEAN)(IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WRITE_THROUGH) || + IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_FLOPPY)); + + while (Repinned != NULL) + { + for (i = 0; i < FFS_REPINNED_BCBS_ARRAY_SIZE; i += 1) + { + if (Repinned->Bcb[i] != NULL) + { + IO_STATUS_BLOCK Iosb; + + ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL); + + if (FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_FLOPPY)) + { + FileObject = CcGetFileObjectFromBcb(Repinned->Bcb[i]); + } + + ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL); + + CcUnpinRepinnedBcb(Repinned->Bcb[i], + WriteThroughToDisk, + &Iosb); + + ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL); + + if (!NT_SUCCESS(Iosb.Status)) + { + if (RaiseIosb.Status == STATUS_SUCCESS) + { + RaiseIosb = Iosb; + } + + if (FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_FLOPPY) && + (IrpContext->MajorFunction != IRP_MJ_CLEANUP) && + (IrpContext->MajorFunction != IRP_MJ_FLUSH_BUFFERS) && + (IrpContext->MajorFunction != IRP_MJ_SET_INFORMATION)) + { + + CcPurgeCacheSection(FileObject->SectionObjectPointer, + NULL, + 0, + FALSE); + + ForceVerify = TRUE; + } + } + + Repinned->Bcb[i] = NULL; + + } + else + { + break; + } + } + + if (Repinned != &IrpContext->Repinned) + { + PFFS_REPINNED_BCBS Saved; + + Saved = Repinned->Next; + ExFreePool(Repinned); + Repinned = Saved; + + } + else + { + Repinned = Repinned->Next; + IrpContext->Repinned.Next = NULL; + } + } + + if (!NT_SUCCESS(RaiseIosb.Status)) + { + FFSBreakPoint(); + + if (ForceVerify && FileObject) + { + SetFlag(FileObject->DeviceObject->Flags, DO_VERIFY_VOLUME); + IoSetHardErrorOrVerifyDevice(IrpContext->Irp, + FileObject->DeviceObject); + } + + IrpContext->Irp->IoStatus = RaiseIosb; + FFSNormalizeAndRaiseStatus(IrpContext, RaiseIosb.Status); + } + + return; +} + + +__drv_mustHoldCriticalRegion +PFFS_FCB +FFSv1AllocateFcb( + IN PFFS_VCB Vcb, + IN PFFS_MCB FFSMcb, + IN PFFSv1_INODE dinode1) +{ + PFFS_FCB Fcb; + + PAGED_CODE(); + + ExAcquireResourceExclusiveLite( + &FFSGlobal->LAResource, + TRUE); + + Fcb = (PFFS_FCB)(ExAllocateFromNPagedLookasideList(&(FFSGlobal->FFSFcbLookasideList))); + + ExReleaseResourceForThreadLite( + &FFSGlobal->LAResource, + ExGetCurrentResourceThread()); + + if (Fcb == NULL) + { + Fcb = (PFFS_FCB)ExAllocatePoolWithTag(NonPagedPool, sizeof(FFS_FCB), FFS_POOL_TAG); + + RtlZeroMemory(Fcb, sizeof(FFS_FCB)); + + SetFlag(Fcb->Flags, FCB_FROM_POOL); + } + else + { + RtlZeroMemory(Fcb, sizeof(FFS_FCB)); + } + + if (!Fcb) + { + return NULL; + } + + Fcb->Identifier.Type = FFSFCB; + Fcb->Identifier.Size = sizeof(FFS_FCB); + + FsRtlInitializeFileLock( + &Fcb->FileLockAnchor, + NULL, + NULL); + + Fcb->OpenHandleCount = 0; + Fcb->ReferenceCount = 0; + + Fcb->Vcb = Vcb; + +#if DBG + + Fcb->AnsiFileName.MaximumLength = (USHORT) + RtlxUnicodeStringToOemSize(&(FFSMcb->ShortName)) + 1; + + Fcb->AnsiFileName.Buffer = (PUCHAR) + ExAllocatePoolWithTag(PagedPool, Fcb->AnsiFileName.MaximumLength, FFS_POOL_TAG); + + if (!Fcb->AnsiFileName.Buffer) + { + goto errorout; + } + + RtlZeroMemory(Fcb->AnsiFileName.Buffer, Fcb->AnsiFileName.MaximumLength); + + FFSUnicodeToOEM(&(Fcb->AnsiFileName), + &(FFSMcb->ShortName)); + +#endif + + FFSMcb->FileAttr = FILE_ATTRIBUTE_NORMAL; + + if ((dinode1->di_mode & IFMT) == IFDIR) + { + SetFlag(FFSMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY); + } + + if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY) || + FFSIsReadOnly(dinode1->di_mode)) + { + SetFlag(FFSMcb->FileAttr, FILE_ATTRIBUTE_READONLY); + } + + Fcb->dinode1 = dinode1; + + Fcb->FFSMcb = FFSMcb; + FFSMcb->FFSFcb = Fcb; + + RtlZeroMemory(&Fcb->Header, sizeof(FSRTL_COMMON_FCB_HEADER)); + + Fcb->Header.NodeTypeCode = (USHORT)FFSFCB; + Fcb->Header.NodeByteSize = sizeof(FFS_FCB); + Fcb->Header.IsFastIoPossible = FastIoIsNotPossible; + Fcb->Header.Resource = &(Fcb->MainResource); + Fcb->Header.PagingIoResource = &(Fcb->PagingIoResource); + + { + ULONG Totalblocks = (Fcb->dinode1->di_blocks); + Fcb->Header.AllocationSize.QuadPart = + (((LONGLONG)FFSDataBlocks(Vcb, Totalblocks)) << BLOCK_BITS); + } + + Fcb->Header.FileSize.QuadPart = (LONGLONG)(Fcb->dinode1->di_size); + Fcb->Header.ValidDataLength.QuadPart = (LONGLONG)(0x7fffffffffffffff); + + Fcb->SectionObject.DataSectionObject = NULL; + Fcb->SectionObject.SharedCacheMap = NULL; + Fcb->SectionObject.ImageSectionObject = NULL; + + ExInitializeResourceLite(&(Fcb->MainResource)); + ExInitializeResourceLite(&(Fcb->PagingIoResource)); + + InsertTailList(&Vcb->FcbList, &Fcb->Next); + +#if DBG + + ExAcquireResourceExclusiveLite( + &FFSGlobal->CountResource, + TRUE); + + FFSGlobal->FcbAllocated++; + + ExReleaseResourceForThreadLite( + &FFSGlobal->CountResource, + ExGetCurrentResourceThread()); +#endif + + return Fcb; + +#if DBG +errorout: +#endif + + if (Fcb) + { + +#if DBG + if (Fcb->AnsiFileName.Buffer) + ExFreePool(Fcb->AnsiFileName.Buffer); +#endif + + if (FlagOn(Fcb->Flags, FCB_FROM_POOL)) + { + ExFreePool(Fcb); + } + else + { + ExAcquireResourceExclusiveLite( + &FFSGlobal->LAResource, + TRUE); + + ExFreeToNPagedLookasideList(&(FFSGlobal->FFSFcbLookasideList), Fcb); + + ExReleaseResourceForThreadLite( + &FFSGlobal->LAResource, + ExGetCurrentResourceThread()); + } + + } + + return NULL; +} + + +__drv_mustHoldCriticalRegion +PFFS_FCB +FFSv2AllocateFcb( + IN PFFS_VCB Vcb, + IN PFFS_MCB FFSMcb, + IN PFFSv2_INODE dinode2) +{ + PFFS_FCB Fcb; + + PAGED_CODE(); + + ExAcquireResourceExclusiveLite( + &FFSGlobal->LAResource, + TRUE); + + Fcb = (PFFS_FCB)(ExAllocateFromNPagedLookasideList(&(FFSGlobal->FFSFcbLookasideList))); + + ExReleaseResourceForThreadLite( + &FFSGlobal->LAResource, + ExGetCurrentResourceThread()); + + if (Fcb == NULL) + { + Fcb = (PFFS_FCB)ExAllocatePoolWithTag(NonPagedPool, sizeof(FFS_FCB), FFS_POOL_TAG); + + RtlZeroMemory(Fcb, sizeof(FFS_FCB)); + + SetFlag(Fcb->Flags, FCB_FROM_POOL); + } + else + { + RtlZeroMemory(Fcb, sizeof(FFS_FCB)); + } + + if (!Fcb) + { + return NULL; + } + + Fcb->Identifier.Type = FFSFCB; + Fcb->Identifier.Size = sizeof(FFS_FCB); + + FsRtlInitializeFileLock( + &Fcb->FileLockAnchor, + NULL, + NULL); + + Fcb->OpenHandleCount = 0; + Fcb->ReferenceCount = 0; + + Fcb->Vcb = Vcb; + +#if DBG + + Fcb->AnsiFileName.MaximumLength = (USHORT) + RtlxUnicodeStringToOemSize(&(FFSMcb->ShortName)) + 1; + + Fcb->AnsiFileName.Buffer = (PUCHAR) + ExAllocatePoolWithTag(PagedPool, Fcb->AnsiFileName.MaximumLength, FFS_POOL_TAG); + + if (!Fcb->AnsiFileName.Buffer) + { + goto errorout; + } + + RtlZeroMemory(Fcb->AnsiFileName.Buffer, Fcb->AnsiFileName.MaximumLength); + + FFSUnicodeToOEM(&(Fcb->AnsiFileName), + &(FFSMcb->ShortName)); + +#endif + + FFSMcb->FileAttr = FILE_ATTRIBUTE_NORMAL; + + if ((dinode2->di_mode & IFMT) == IFDIR) + { + SetFlag(FFSMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY); + } + + if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY) || + FFSIsReadOnly(dinode2->di_mode)) + { + SetFlag(FFSMcb->FileAttr, FILE_ATTRIBUTE_READONLY); + } + + Fcb->dinode2 = dinode2; + + Fcb->FFSMcb = FFSMcb; + FFSMcb->FFSFcb = Fcb; + + RtlZeroMemory(&Fcb->Header, sizeof(FSRTL_COMMON_FCB_HEADER)); + + Fcb->Header.NodeTypeCode = (USHORT)FFSFCB; + Fcb->Header.NodeByteSize = sizeof(FFS_FCB); + Fcb->Header.IsFastIoPossible = FastIoIsNotPossible; + Fcb->Header.Resource = &(Fcb->MainResource); + Fcb->Header.PagingIoResource = &(Fcb->PagingIoResource); + + { + ULONG Totalblocks = (ULONG)(Fcb->dinode2->di_blocks); + Fcb->Header.AllocationSize.QuadPart = + (((LONGLONG)FFSDataBlocks(Vcb, Totalblocks)) << BLOCK_BITS); + } + + Fcb->Header.FileSize.QuadPart = (LONGLONG)(Fcb->dinode2->di_size); + Fcb->Header.ValidDataLength.QuadPart = (LONGLONG)(0x7fffffffffffffff); + + Fcb->SectionObject.DataSectionObject = NULL; + Fcb->SectionObject.SharedCacheMap = NULL; + Fcb->SectionObject.ImageSectionObject = NULL; + + ExInitializeResourceLite(&(Fcb->MainResource)); + ExInitializeResourceLite(&(Fcb->PagingIoResource)); + + InsertTailList(&Vcb->FcbList, &Fcb->Next); + +#if DBG + + ExAcquireResourceExclusiveLite( + &FFSGlobal->CountResource, + TRUE); + + FFSGlobal->FcbAllocated++; + + ExReleaseResourceForThreadLite( + &FFSGlobal->CountResource, + ExGetCurrentResourceThread()); +#endif + + return Fcb; + +#if DBG +errorout: +#endif + + if (Fcb) + { + +#if DBG + if (Fcb->AnsiFileName.Buffer) + ExFreePool(Fcb->AnsiFileName.Buffer); +#endif + + if (FlagOn(Fcb->Flags, FCB_FROM_POOL)) + { + ExFreePool(Fcb); + } + else + { + ExAcquireResourceExclusiveLite( + &FFSGlobal->LAResource, + TRUE); + + ExFreeToNPagedLookasideList(&(FFSGlobal->FFSFcbLookasideList), Fcb); + + ExReleaseResourceForThreadLite( + &FFSGlobal->LAResource, + ExGetCurrentResourceThread()); + } + + } + + return NULL; +} + + +__drv_mustHoldCriticalRegion +VOID +FFSFreeFcb( + IN PFFS_FCB Fcb) +{ + PFFS_VCB Vcb; + + PAGED_CODE(); + + ASSERT(Fcb != NULL); + + ASSERT((Fcb->Identifier.Type == FFSFCB) && + (Fcb->Identifier.Size == sizeof(FFS_FCB))); + + Vcb = Fcb->Vcb; + + FsRtlUninitializeFileLock(&Fcb->FileLockAnchor); + + ExDeleteResourceLite(&Fcb->MainResource); + + ExDeleteResourceLite(&Fcb->PagingIoResource); + + Fcb->FFSMcb->FFSFcb = NULL; + + if(IsFlagOn(Fcb->Flags, FCB_FILE_DELETED)) + { + if (Fcb->FFSMcb) + { + FFSDeleteMcbNode(Vcb, Fcb->FFSMcb->Parent, Fcb->FFSMcb); + FFSFreeMcb(Fcb->FFSMcb); + } + } + + if (Fcb->LongName.Buffer) + { + ExFreePool(Fcb->LongName.Buffer); + Fcb->LongName.Buffer = NULL; + } + +#if DBG + ExFreePool(Fcb->AnsiFileName.Buffer); +#endif + + if (FS_VERSION == 1) + { + ExFreePool(Fcb->dinode1); + } + else + { + ExFreePool(Fcb->dinode2); + } + + Fcb->Header.NodeTypeCode = (SHORT)0xCCCC; + Fcb->Header.NodeByteSize = (SHORT)0xC0C0; + + if (FlagOn(Fcb->Flags, FCB_FROM_POOL)) + { + ExFreePool(Fcb); + } + else + { + ExAcquireResourceExclusiveLite( + &FFSGlobal->LAResource, + TRUE); + + ExFreeToNPagedLookasideList(&(FFSGlobal->FFSFcbLookasideList), Fcb); + + ExReleaseResourceForThreadLite( + &FFSGlobal->LAResource, + ExGetCurrentResourceThread()); + } + +#if DBG + + ExAcquireResourceExclusiveLite( + &FFSGlobal->CountResource, + TRUE); + + FFSGlobal->FcbAllocated--; + + ExReleaseResourceForThreadLite( + &FFSGlobal->CountResource, + ExGetCurrentResourceThread()); +#endif + +} + + +__drv_mustHoldCriticalRegion +PFFS_CCB +FFSAllocateCcb( + VOID) +{ + PFFS_CCB Ccb; + + PAGED_CODE(); + + ExAcquireResourceExclusiveLite( + &FFSGlobal->LAResource, + TRUE); + + Ccb = (PFFS_CCB)(ExAllocateFromNPagedLookasideList(&(FFSGlobal->FFSCcbLookasideList))); + + ExReleaseResourceForThreadLite( + &FFSGlobal->LAResource, + ExGetCurrentResourceThread()); + + if (Ccb == NULL) + { + Ccb = (PFFS_CCB)ExAllocatePoolWithTag(NonPagedPool, sizeof(FFS_CCB), FFS_POOL_TAG); + + RtlZeroMemory(Ccb, sizeof(FFS_CCB)); + + SetFlag(Ccb->Flags, CCB_FROM_POOL); + } + else + { + RtlZeroMemory(Ccb, sizeof(FFS_CCB)); + } + + if (!Ccb) + { + return NULL; + } + + Ccb->Identifier.Type = FFSCCB; + Ccb->Identifier.Size = sizeof(FFS_CCB); + + Ccb->CurrentByteOffset = 0; + + Ccb->DirectorySearchPattern.Length = 0; + Ccb->DirectorySearchPattern.MaximumLength = 0; + Ccb->DirectorySearchPattern.Buffer = 0; + + return Ccb; +} + + +__drv_mustHoldCriticalRegion +VOID +FFSFreeCcb( + IN PFFS_CCB Ccb) +{ + PAGED_CODE(); + + ASSERT(Ccb != NULL); + + ASSERT((Ccb->Identifier.Type == FFSCCB) && + (Ccb->Identifier.Size == sizeof(FFS_CCB))); + + if (Ccb->DirectorySearchPattern.Buffer != NULL) + { + ExFreePool(Ccb->DirectorySearchPattern.Buffer); + } + + if (FlagOn(Ccb->Flags, CCB_FROM_POOL)) + { + ExFreePool(Ccb); + } + else + { + ExAcquireResourceExclusiveLite( + &FFSGlobal->LAResource, + TRUE); + + ExFreeToNPagedLookasideList(&(FFSGlobal->FFSCcbLookasideList), Ccb); + + ExReleaseResourceForThreadLite( + &FFSGlobal->LAResource, + ExGetCurrentResourceThread()); + } +} + + +__drv_mustHoldCriticalRegion +PFFS_MCB +FFSAllocateMcb( + PFFS_VCB Vcb, + PUNICODE_STRING FileName, + ULONG FileAttr) +{ + PFFS_MCB Mcb = NULL; + PLIST_ENTRY List = NULL; + + ULONG Extra = 0; + + PAGED_CODE(); + +#define MCB_NUM_SHIFT 0x04 + + if (FFSGlobal->McbAllocated > (FFSGlobal->MaxDepth << MCB_NUM_SHIFT)) + Extra = FFSGlobal->McbAllocated - + (FFSGlobal->MaxDepth << MCB_NUM_SHIFT) + + FFSGlobal->MaxDepth; + + FFSPrint((DBG_INFO, + "FFSAllocateMcb: CurrDepth=%xh/%xh/%xh FileName=%S\n", + FFSGlobal->McbAllocated, + FFSGlobal->MaxDepth << MCB_NUM_SHIFT, + FFSGlobal->FcbAllocated, + FileName->Buffer)); + + List = Vcb->McbList.Flink; + + while ((List != &(Vcb->McbList)) && (Extra > 0)) + { + Mcb = CONTAINING_RECORD(List, FFS_MCB, Link); + List = List->Flink; + + if ((Mcb->Inode != 2) && (Mcb->Child == NULL) && + (Mcb->FFSFcb == NULL) && (!IsMcbUsed(Mcb))) + { + FFSPrint((DBG_INFO, "FFSAllocateMcb: Mcb %S will be freed.\n", + Mcb->ShortName.Buffer)); + + if (FFSDeleteMcbNode(Vcb, Vcb->McbTree, Mcb)) + { + FFSFreeMcb(Mcb); + + Extra--; + } + } + } + + ExAcquireResourceExclusiveLite( + &FFSGlobal->LAResource, + TRUE); + + Mcb = (PFFS_MCB)(ExAllocateFromPagedLookasideList( + &(FFSGlobal->FFSMcbLookasideList))); + + ExReleaseResourceForThreadLite( + &FFSGlobal->LAResource, + ExGetCurrentResourceThread()); + + if (Mcb == NULL) + { + Mcb = (PFFS_MCB)ExAllocatePoolWithTag(PagedPool, sizeof(FFS_MCB), FFS_POOL_TAG); + + RtlZeroMemory(Mcb, sizeof(FFS_MCB)); + + SetFlag(Mcb->Flags, MCB_FROM_POOL); + } + else + { + RtlZeroMemory(Mcb, sizeof(FFS_MCB)); + } + + if (!Mcb) + { + return NULL; + } + + Mcb->Identifier.Type = FFSMCB; + Mcb->Identifier.Size = sizeof(FFS_MCB); + + if (FileName && FileName->Length) + { + Mcb->ShortName.Length = FileName->Length; + Mcb->ShortName.MaximumLength = Mcb->ShortName.Length + 2; + + Mcb->ShortName.Buffer = ExAllocatePoolWithTag(PagedPool, Mcb->ShortName.MaximumLength, FFS_POOL_TAG); + + if (!Mcb->ShortName.Buffer) + goto errorout; + + RtlZeroMemory(Mcb->ShortName.Buffer, Mcb->ShortName.MaximumLength); + RtlCopyMemory(Mcb->ShortName.Buffer, FileName->Buffer, Mcb->ShortName.Length); + } + + Mcb->FileAttr = FileAttr; + + ExAcquireResourceExclusiveLite( + &FFSGlobal->CountResource, + TRUE); + + FFSGlobal->McbAllocated++; + + ExReleaseResourceForThreadLite( + &FFSGlobal->CountResource, + ExGetCurrentResourceThread()); + + return Mcb; + +errorout: + + if (Mcb) + { + if (Mcb->ShortName.Buffer) + ExFreePool(Mcb->ShortName.Buffer); + + if (FlagOn(Mcb->Flags, MCB_FROM_POOL)) + { + ExFreePool(Mcb); + } + else + { + ExAcquireResourceExclusiveLite( + &FFSGlobal->LAResource, + TRUE); + + ExFreeToPagedLookasideList(&(FFSGlobal->FFSMcbLookasideList), Mcb); + + ExReleaseResourceForThreadLite( + &FFSGlobal->LAResource, + ExGetCurrentResourceThread()); + } + } + + return NULL; +} + + +__drv_mustHoldCriticalRegion +VOID +FFSFreeMcb( + IN PFFS_MCB Mcb) +{ +#ifndef __REACTOS__ + PFFS_MCB Parent = Mcb->Parent; +#endif + PAGED_CODE(); + + ASSERT(Mcb != NULL); + + ASSERT((Mcb->Identifier.Type == FFSMCB) && + (Mcb->Identifier.Size == sizeof(FFS_MCB))); + + FFSPrint((DBG_INFO, "FFSFreeMcb: Mcb %S will be freed.\n", Mcb->ShortName.Buffer)); + + if (Mcb->ShortName.Buffer) + ExFreePool(Mcb->ShortName.Buffer); + + if (FlagOn(Mcb->Flags, MCB_FROM_POOL)) + { + ExFreePool(Mcb); + } + else + { + ExAcquireResourceExclusiveLite( + &FFSGlobal->LAResource, + TRUE); + + ExFreeToPagedLookasideList(&(FFSGlobal->FFSMcbLookasideList), Mcb); + + ExReleaseResourceForThreadLite( + &FFSGlobal->LAResource, + ExGetCurrentResourceThread()); + } + + ExAcquireResourceExclusiveLite( + &FFSGlobal->CountResource, + TRUE); + + FFSGlobal->McbAllocated--; + + ExReleaseResourceForThreadLite( + &FFSGlobal->CountResource, + ExGetCurrentResourceThread()); +} + + +__drv_mustHoldCriticalRegion +PFFS_FCB +FFSCreateFcbFromMcb( + PFFS_VCB Vcb, + PFFS_MCB Mcb) +{ + PFFS_FCB Fcb = NULL; + FFSv1_INODE dinode1; + FFSv2_INODE dinode2; + + PAGED_CODE(); + + if (Mcb->FFSFcb) + return Mcb->FFSFcb; + + if (FS_VERSION == 1) + { + if (FFSv1LoadInode(Vcb, Mcb->Inode, &dinode1)) + { + PFFSv1_INODE pTmpInode = ExAllocatePoolWithTag(PagedPool, DINODE1_SIZE, FFS_POOL_TAG); + if (!pTmpInode) + { + goto errorout; + } + + RtlCopyMemory(pTmpInode, &dinode1, DINODE1_SIZE); + Fcb = FFSv1AllocateFcb(Vcb, Mcb, pTmpInode); + if (!Fcb) + { + ExFreePool(pTmpInode); + } + } + } + else + { + if (FFSv2LoadInode(Vcb, Mcb->Inode, &dinode2)) + { + PFFSv2_INODE pTmpInode = ExAllocatePoolWithTag(PagedPool, DINODE2_SIZE, FFS_POOL_TAG); + if (!pTmpInode) + { + goto errorout; + } + + RtlCopyMemory(pTmpInode, &dinode2, DINODE2_SIZE); + Fcb = FFSv2AllocateFcb(Vcb, Mcb, pTmpInode); + if (!Fcb) + { + ExFreePool(pTmpInode); + } + } + } + +errorout: + + return Fcb; +} + + +BOOLEAN +FFSGetFullFileName( + PFFS_MCB Mcb, + PUNICODE_STRING FileName) +{ + USHORT Length = 0; + PFFS_MCB TmpMcb = Mcb; + PUNICODE_STRING FileNames[256]; + SHORT Count = 0 , i = 0, j = 0; + + PAGED_CODE(); + + while(TmpMcb && Count < 256) + { + if (TmpMcb->Inode == FFS_ROOT_INO) + break; + + FileNames[Count++] = &TmpMcb->ShortName; + Length += (2 + TmpMcb->ShortName.Length); + + TmpMcb = TmpMcb->Parent; + } + + if (Count >= 256) + return FALSE; + + if (Count == 0) + Length = 2; + + FileName->Length = Length; + FileName->MaximumLength = Length + 2; + FileName->Buffer = ExAllocatePoolWithTag(PagedPool, Length + 2, FFS_POOL_TAG); + + if (!FileName->Buffer) + { + return FALSE; + } + + RtlZeroMemory(FileName->Buffer, FileName->MaximumLength); + + if (Count == 0) + { + FileName->Buffer[0] = L'\\'; + return TRUE; + } + + for (i = Count - 1; i >= 0 && j < (SHORT)(FileName->MaximumLength); i--) + { + FileName->Buffer[j++] = L'\\'; + + RtlCopyMemory(&(FileName->Buffer[j]), + FileNames[i]->Buffer, + FileNames[i]->Length); + + j += FileNames[i]->Length / 2; + } + + return TRUE; +} + + +PFFS_MCB +FFSSearchMcbTree( + PFFS_VCB Vcb, + PFFS_MCB FFSMcb, + ULONG Inode) +{ + PFFS_MCB Mcb = NULL; + PLIST_ENTRY List = NULL; + BOOLEAN bFind = FALSE; + + PAGED_CODE(); + + List = Vcb->McbList.Flink; + + while ((!bFind) && (List != &(Vcb->McbList))) + { + Mcb = CONTAINING_RECORD(List, FFS_MCB, Link); + List = List->Flink; + + if (Mcb->Inode == Inode) + { + bFind = TRUE; + break; + } + } + + if (bFind) + { + ASSERT(Mcb != NULL); + FFSRefreshMcb(Vcb, Mcb); + } + else + { + Mcb = NULL; + } + + return Mcb; +} + + +PFFS_MCB +FFSSearchMcb( + PFFS_VCB Vcb, + PFFS_MCB Parent, + PUNICODE_STRING FileName) +{ + PFFS_MCB TmpMcb = Parent->Child; + + PAGED_CODE(); + + while (TmpMcb) + { + if (!RtlCompareUnicodeString( + &(TmpMcb->ShortName), + FileName, TRUE)) + break; + + TmpMcb = TmpMcb->Next; + } + + if (TmpMcb) + { + FFSRefreshMcb(Vcb, TmpMcb); + } + + return TmpMcb; +} + + +VOID +FFSRefreshMcb( + PFFS_VCB Vcb, + PFFS_MCB Mcb) +{ + PAGED_CODE(); + + ASSERT (IsFlagOn(Mcb->Flags, MCB_IN_TREE)); + + RemoveEntryList(&(Mcb->Link)); + InsertTailList(&(Vcb->McbList), &(Mcb->Link)); +} + + +VOID +FFSAddMcbNode( + PFFS_VCB Vcb, + PFFS_MCB Parent, + PFFS_MCB Child) +{ + PFFS_MCB TmpMcb = Parent->Child; + + PAGED_CODE(); + + if(IsFlagOn(Child->Flags, MCB_IN_TREE)) + { + FFSBreakPoint(); + FFSPrint((DBG_ERROR, "FFSAddMcbNode: Child Mcb is alreay in the tree.\n")); + return; + } + + if (TmpMcb) + { + ASSERT(TmpMcb->Parent == Parent); + + while (TmpMcb->Next) + { + TmpMcb = TmpMcb->Next; + ASSERT(TmpMcb->Parent == Parent); + } + + TmpMcb->Next = Child; + Child->Parent = Parent; + Child->Next = NULL; + } + else + { + Parent->Child = Child; + Child->Parent = Parent; + Child->Next = NULL; + } + + InsertTailList(&(Vcb->McbList), &(Child->Link)); + SetFlag(Child->Flags, MCB_IN_TREE); +} + + +BOOLEAN +FFSDeleteMcbNode( + PFFS_VCB Vcb, + PFFS_MCB McbTree, + PFFS_MCB FFSMcb) +{ + PFFS_MCB TmpMcb; + + PAGED_CODE(); + + if(!IsFlagOn(FFSMcb->Flags, MCB_IN_TREE)) + { + return TRUE; + } + + if (FFSMcb->Parent) + { + if (FFSMcb->Parent->Child == FFSMcb) + { + FFSMcb->Parent->Child = FFSMcb->Next; + } + else + { + TmpMcb = FFSMcb->Parent->Child; + + while (TmpMcb && TmpMcb->Next != FFSMcb) + TmpMcb = TmpMcb->Next; + + if (TmpMcb) + { + TmpMcb->Next = FFSMcb->Next; + } + else + { + // error + return FALSE; + } + } + } + else if (FFSMcb->Child) + { + return FALSE; + } + + RemoveEntryList(&(FFSMcb->Link)); + ClearFlag(FFSMcb->Flags, MCB_IN_TREE); + + return TRUE; +} + + +__drv_mustHoldCriticalRegion +VOID +FFSFreeMcbTree( + PFFS_MCB McbTree) +{ + PAGED_CODE(); + + if (!McbTree) + return; + + if (McbTree->Child) + { + FFSFreeMcbTree(McbTree->Child); + } + + if (McbTree->Next) + { + PFFS_MCB Current; + PFFS_MCB Next; + + Current = McbTree->Next; + + while (Current) + { + Next = Current->Next; + + if (Current->Child) + { + FFSFreeMcbTree(Current->Child); + } + + FFSFreeMcb(Current); + Current = Next; + } + } + + FFSFreeMcb(McbTree); +} + + +BOOLEAN +FFSCheckSetBlock( + PFFS_IRP_CONTEXT IrpContext, + PFFS_VCB Vcb, + ULONG Block) +{ + PAGED_CODE(); +#if 0 + ULONG Group, dwBlk, Length; + + RTL_BITMAP BlockBitmap; + PVOID BitmapCache; + PBCB BitmapBcb; + + LARGE_INTEGER Offset; + + BOOLEAN bModified = FALSE; + + + //Group = (Block - FFS_FIRST_DATA_BLOCK) / BLOCKS_PER_GROUP; + + dwBlk = (Block - FFS_FIRST_DATA_BLOCK) % BLOCKS_PER_GROUP; + + + Offset.QuadPart = (LONGLONG) Vcb->BlockSize; + Offset.QuadPart = Offset.QuadPart * Vcb->ffs_group_desc[Group].bg_block_bitmap; + + if (Group == Vcb->ffs_groups - 1) + { + Length = TOTAL_BLOCKS % BLOCKS_PER_GROUP; + + /* s_blocks_count is integer multiple of s_blocks_per_group */ + if (Length == 0) + Length = BLOCKS_PER_GROUP; + } + else + { + Length = BLOCKS_PER_GROUP; + } + + if (dwBlk >= Length) + return FALSE; + + if (!CcPinRead(Vcb->StreamObj, + &Offset, + Vcb->BlockSize, + PIN_WAIT, + &BitmapBcb, + &BitmapCache)) + { + FFSPrint((DBG_ERROR, "FFSDeleteBlock: PinReading error ...\n")); + return FALSE; + } + + RtlInitializeBitMap(&BlockBitmap, + BitmapCache, + Length); + + if (RtlCheckBit(&BlockBitmap, dwBlk) == 0) + { + FFSBreakPoint(); + RtlSetBits(&BlockBitmap, dwBlk, 1); + bModified = TRUE; + } + + if (bModified) + { + CcSetDirtyPinnedData(BitmapBcb, NULL); + + FFSRepinBcb(IrpContext, BitmapBcb); + + FFSAddMcbEntry(Vcb, Offset.QuadPart, (LONGLONG)Vcb->BlockSize); + } + + { + CcUnpinData(BitmapBcb); + BitmapBcb = NULL; + BitmapCache = NULL; + + RtlZeroMemory(&BlockBitmap, sizeof(RTL_BITMAP)); + } + + return (!bModified); +#endif + return FALSE; +} + + +BOOLEAN +FFSCheckBitmapConsistency( + PFFS_IRP_CONTEXT IrpContext, + PFFS_VCB Vcb) +{ + PAGED_CODE(); +#if 0 + ULONG i, j, InodeBlocks; + + for (i = 0; i < Vcb->ffs_groups; i++) + { + FFSCheckSetBlock(IrpContext, Vcb, Vcb->ffs_group_desc[i].bg_block_bitmap); + FFSCheckSetBlock(IrpContext, Vcb, Vcb->ffs_group_desc[i].bg_inode_bitmap); + + + if (i == Vcb->ffs_groups - 1) + { + InodeBlocks = ((INODES_COUNT % INODES_PER_GROUP) * sizeof(FFS_INODE) + Vcb->BlockSize - 1) / (Vcb->BlockSize); + } + else + { + InodeBlocks = (INODES_PER_GROUP * sizeof(FFS_INODE) + Vcb->BlockSize - 1) / (Vcb->BlockSize); + } + + for (j = 0; j < InodeBlocks; j++) + FFSCheckSetBlock(IrpContext, Vcb, Vcb->ffs_group_desc[i].bg_inode_table + j); + } + + return TRUE; +#endif + return FALSE; +} + + +VOID +FFSInsertVcb( + PFFS_VCB Vcb) +{ + InsertTailList(&(FFSGlobal->VcbList), &Vcb->Next); +} + + +VOID +FFSRemoveVcb( + PFFS_VCB Vcb) +{ + RemoveEntryList(&Vcb->Next); +} + + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSInitializeVcb( + IN PFFS_IRP_CONTEXT IrpContext, + IN PFFS_VCB Vcb, + IN PFFS_SUPER_BLOCK FFSSb, + IN PDEVICE_OBJECT TargetDevice, + IN PDEVICE_OBJECT VolumeDevice, + IN PVPB Vpb) +{ + BOOLEAN VcbResourceInitialized = FALSE; + USHORT VolumeLabelLength; + ULONG IoctlSize; + BOOLEAN NotifySyncInitialized = FALSE; + LONGLONG DiskSize; + LONGLONG PartSize; + NTSTATUS Status = STATUS_UNSUCCESSFUL; + UNICODE_STRING RootNode; + USHORT Buffer[2]; + ULONG ChangeCount; + + PAGED_CODE(); + + _SEH2_TRY + { + if (!Vpb) + { + Status = STATUS_DEVICE_NOT_READY; + _SEH2_LEAVE; + } + + Buffer[0] = L'\\'; + Buffer[1] = 0; + + RootNode.Buffer = Buffer; + RootNode.MaximumLength = RootNode.Length = 2; + + Vcb->McbTree = FFSAllocateMcb(Vcb, &RootNode, + FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_NORMAL); + + if (!Vcb->McbTree) + { + _SEH2_LEAVE; + } + +#if FFS_READ_ONLY + SetFlag(Vcb->Flags, VCB_READ_ONLY); +#endif // FFS_READ_ONLY + + if (IsFlagOn(Vpb->RealDevice->Characteristics, FILE_REMOVABLE_MEDIA)) + { + SetFlag(Vcb->Flags, VCB_REMOVABLE_MEDIA); + } + + if (IsFlagOn(Vpb->RealDevice->Characteristics, FILE_FLOPPY_DISKETTE)) + { + SetFlag(Vcb->Flags, VCB_FLOPPY_DISK); + } +#if 0 + if (IsFlagOn(FFSGlobal->Flags, FFS_SUPPORT_WRITING)) + { + if (IsFlagOn(FFSGlobal->Flags, FFS_SUPPORT_WRITING)) + { + ClearFlag(Vcb->Flags, VCB_READ_ONLY); + } + else + { + SetFlag(Vcb->Flags, VCB_READ_ONLY); + } + } + else +#endif + { + SetFlag(Vcb->Flags, VCB_READ_ONLY); + } + + ExInitializeResourceLite(&Vcb->MainResource); + ExInitializeResourceLite(&Vcb->PagingIoResource); + + ExInitializeResourceLite(&Vcb->McbResource); + + VcbResourceInitialized = TRUE; + + Vcb->McbTree->Inode = FFS_ROOT_INO; + + Vcb->Vpb = Vpb; + + Vcb->RealDevice = Vpb->RealDevice; + Vpb->DeviceObject = VolumeDevice; + + { + UNICODE_STRING LabelName; + OEM_STRING OemName; + + LabelName.MaximumLength = 16 * 2; + LabelName.Length = 0; + LabelName.Buffer = Vcb->Vpb->VolumeLabel; + + RtlZeroMemory(LabelName.Buffer, LabelName.MaximumLength); + + VolumeLabelLength = 16; + + while((VolumeLabelLength > 0) && + ((FFSSb->fs_volname[VolumeLabelLength-1] == 0x00) || + (FFSSb->fs_volname[VolumeLabelLength-1] == 0x20))) + { + VolumeLabelLength--; + } + + OemName.Buffer = FFSSb->fs_volname; + OemName.MaximumLength = 16; + OemName.Length = VolumeLabelLength; + + Status = FFSOEMToUnicode(&LabelName, + &OemName); + + if (!NT_SUCCESS(Status)) + { + _SEH2_LEAVE; + } + + Vpb->VolumeLabelLength = LabelName.Length; + } + + Vpb->SerialNumber = ((ULONG*)FFSSb->fs_id)[0] + ((ULONG*)FFSSb->fs_id)[1]; + + Vcb->StreamObj = IoCreateStreamFileObject(NULL, Vcb->Vpb->RealDevice); + + if (Vcb->StreamObj) + { + Vcb->StreamObj->SectionObjectPointer = &(Vcb->SectionObject); + Vcb->StreamObj->Vpb = Vcb->Vpb; + Vcb->StreamObj->ReadAccess = TRUE; + if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY)) + { + Vcb->StreamObj->WriteAccess = TRUE; + Vcb->StreamObj->DeleteAccess = TRUE; + } + else + { + Vcb->StreamObj->WriteAccess = TRUE; + Vcb->StreamObj->DeleteAccess = TRUE; + } + Vcb->StreamObj->FsContext = (PVOID) Vcb; + Vcb->StreamObj->FsContext2 = NULL; + Vcb->StreamObj->Vpb = Vcb->Vpb; + + SetFlag(Vcb->StreamObj->Flags, FO_NO_INTERMEDIATE_BUFFERING); + } + else + { + _SEH2_LEAVE; + } + + InitializeListHead(&Vcb->FcbList); + + InitializeListHead(&Vcb->NotifyList); + + FsRtlNotifyInitializeSync(&Vcb->NotifySync); + + NotifySyncInitialized = TRUE; + + Vcb->DeviceObject = VolumeDevice; + + Vcb->TargetDeviceObject = TargetDevice; + + Vcb->OpenFileHandleCount = 0; + + Vcb->ReferenceCount = 0; + + Vcb->ffs_super_block = FFSSb; + + Vcb->Header.NodeTypeCode = (USHORT) FFSVCB; + Vcb->Header.NodeByteSize = sizeof(FFS_VCB); + Vcb->Header.IsFastIoPossible = FastIoIsNotPossible; + Vcb->Header.Resource = &(Vcb->MainResource); + Vcb->Header.PagingIoResource = &(Vcb->PagingIoResource); + + Vcb->Vpb->SerialNumber = 'PS'; + + DiskSize = + Vcb->DiskGeometry.Cylinders.QuadPart * + Vcb->DiskGeometry.TracksPerCylinder * + Vcb->DiskGeometry.SectorsPerTrack * + Vcb->DiskGeometry.BytesPerSector; + + IoctlSize = sizeof(PARTITION_INFORMATION); + + Status = FFSDiskIoControl( + TargetDevice, + IOCTL_DISK_GET_PARTITION_INFO, + NULL, + 0, + &Vcb->PartitionInformation, + &IoctlSize); + + PartSize = Vcb->PartitionInformation.PartitionLength.QuadPart; + + if (!NT_SUCCESS(Status)) + { + Vcb->PartitionInformation.StartingOffset.QuadPart = 0; + + Vcb->PartitionInformation.PartitionLength.QuadPart = + DiskSize; + + PartSize = DiskSize; + + Status = STATUS_SUCCESS; + } + + IoctlSize = sizeof(ULONG); + Status = FFSDiskIoControl( + TargetDevice, + IOCTL_DISK_CHECK_VERIFY, + NULL, + 0, + &ChangeCount, + &IoctlSize); + + if (!NT_SUCCESS(Status)) + { + _SEH2_LEAVE; + } + + Vcb->ChangeCount = ChangeCount; + + Vcb->Header.AllocationSize.QuadPart = + Vcb->Header.FileSize.QuadPart = PartSize; + + Vcb->Header.ValidDataLength.QuadPart = + (LONGLONG)(0x7fffffffffffffff); + /* + Vcb->Header.AllocationSize.QuadPart = (LONGLONG)(ffs_super_block->s_blocks_count - ffs_super_block->s_free_blocks_count) + * (FFS_MIN_BLOCK << ffs_super_block->s_log_block_size); + Vcb->Header.FileSize.QuadPart = Vcb->Header.AllocationSize.QuadPart; + Vcb->Header.ValidDataLength.QuadPart = Vcb->Header.AllocationSize.QuadPart; + */ + + { + CC_FILE_SIZES FileSizes; + + FileSizes.AllocationSize.QuadPart = + FileSizes.FileSize.QuadPart = + Vcb->Header.AllocationSize.QuadPart; + + FileSizes.ValidDataLength.QuadPart= (LONGLONG)(0x7fffffffffffffff); + + CcInitializeCacheMap(Vcb->StreamObj, + &FileSizes, + TRUE, + &(FFSGlobal->CacheManagerNoOpCallbacks), + Vcb); + } +#if 0 // LoadGroup XXX + if (!FFSLoadGroup(Vcb)) + { + Status = STATUS_UNSUCCESSFUL; + _SEH2_LEAVE; + } +#endif + FsRtlInitializeLargeMcb(&(Vcb->DirtyMcbs), PagedPool); + InitializeListHead(&(Vcb->McbList)); + + if (IsFlagOn(FFSGlobal->Flags, FFS_CHECKING_BITMAP)) + { + FFSCheckBitmapConsistency(IrpContext, Vcb); + } + + { + ULONG dwData[FFS_BLOCK_TYPES] = {NDADDR, 1, 1, 1}; + ULONG dwMeta[FFS_BLOCK_TYPES] = {0, 0, 0, 0}; + ULONG i; + + if (FS_VERSION == 1) + { + for (i = 0; i < FFS_BLOCK_TYPES; i++) + { + dwData[i] = dwData[i] << ((BLOCK_BITS - 2) * i); + + if (i > 0) + { + dwMeta[i] = 1 + (dwMeta[i - 1] << (BLOCK_BITS - 2)); + } + + Vcb->dwData[i] = dwData[i]; + Vcb->dwMeta[i] = dwMeta[i]; + } + } + else + { + for (i = 0; i < FFS_BLOCK_TYPES; i++) + { + dwData[i] = dwData[i] << ((BLOCK_BITS - 3) * i); + + if (i > 0) + { + dwMeta[i] = 1 + (dwMeta[i - 1] << (BLOCK_BITS - 3)); + } + + Vcb->dwData[i] = dwData[i]; + Vcb->dwMeta[i] = dwMeta[i]; + } + } + } + + SetFlag(Vcb->Flags, VCB_INITIALIZED); + } + + _SEH2_FINALLY + { + if (!NT_SUCCESS(Status)) + { + if (NotifySyncInitialized) + { + FsRtlNotifyUninitializeSync(&Vcb->NotifySync); + } + + if (Vcb->ffs_super_block) + { + ExFreePool(Vcb->ffs_super_block); + Vcb->ffs_super_block = NULL; + } + + if (VcbResourceInitialized) + { + ExDeleteResourceLite(&Vcb->MainResource); + ExDeleteResourceLite(&Vcb->PagingIoResource); + } + } + } _SEH2_END; + + return Status; +} + + +__drv_mustHoldCriticalRegion +VOID +FFSFreeVcb( + IN PFFS_VCB Vcb) +{ + PAGED_CODE(); + + ASSERT(Vcb != NULL); + + ASSERT((Vcb->Identifier.Type == FFSVCB) && + (Vcb->Identifier.Size == sizeof(FFS_VCB))); + + FsRtlNotifyUninitializeSync(&Vcb->NotifySync); + + if (Vcb->StreamObj) + { + if (IsFlagOn(Vcb->StreamObj->Flags, FO_FILE_MODIFIED)) + { + IO_STATUS_BLOCK IoStatus; + + CcFlushCache(&(Vcb->SectionObject), NULL, 0, &IoStatus); + ClearFlag(Vcb->StreamObj->Flags, FO_FILE_MODIFIED); + } + + if (Vcb->StreamObj->PrivateCacheMap) + FFSSyncUninitializeCacheMap(Vcb->StreamObj); + + ObDereferenceObject(Vcb->StreamObj); + Vcb->StreamObj = NULL; + } + +#if DBG + if (FsRtlNumberOfRunsInLargeMcb(&(Vcb->DirtyMcbs)) != 0) + { + LONGLONG DirtyVba; + LONGLONG DirtyLba; + LONGLONG DirtyLength; + int i; + + for (i = 0; FsRtlGetNextLargeMcbEntry (&(Vcb->DirtyMcbs), i, &DirtyVba, &DirtyLba, &DirtyLength); i++) + { + FFSPrint((DBG_INFO, "DirtyVba = %I64xh\n", DirtyVba)); + FFSPrint((DBG_INFO, "DirtyLba = %I64xh\n", DirtyLba)); + FFSPrint((DBG_INFO, "DirtyLen = %I64xh\n\n", DirtyLength)); + } + + FFSBreakPoint(); + } +#endif + + FsRtlUninitializeLargeMcb(&(Vcb->DirtyMcbs)); + + FFSFreeMcbTree(Vcb->McbTree); + + if (Vcb->ffs_super_block) + { + ExFreePool(Vcb->ffs_super_block); + Vcb->ffs_super_block = NULL; + } + + ExDeleteResourceLite(&Vcb->McbResource); + + ExDeleteResourceLite(&Vcb->PagingIoResource); + + ExDeleteResourceLite(&Vcb->MainResource); + + IoDeleteDevice(Vcb->DeviceObject); +} + + +VOID +FFSSyncUninitializeCacheMap( + IN PFILE_OBJECT FileObject) +{ + CACHE_UNINITIALIZE_EVENT UninitializeCompleteEvent; + NTSTATUS WaitStatus; + LARGE_INTEGER FFSLargeZero = {0, 0}; + + PAGED_CODE(); + + KeInitializeEvent(&UninitializeCompleteEvent.Event, + SynchronizationEvent, + FALSE); + + CcUninitializeCacheMap(FileObject, + &FFSLargeZero, + &UninitializeCompleteEvent); + + WaitStatus = KeWaitForSingleObject(&UninitializeCompleteEvent.Event, + Executive, + KernelMode, + FALSE, + NULL); + + ASSERT (NT_SUCCESS(WaitStatus)); +} diff --git a/reactos/drivers/filesystems/ffs/src/misc.c b/reactos/drivers/filesystems/ffs/src/misc.c new file mode 100644 index 00000000000..da42a752d89 --- /dev/null +++ b/reactos/drivers/filesystems/ffs/src/misc.c @@ -0,0 +1,128 @@ +/* + * FFS File System Driver for Windows + * + * misc.c + * + * 2004.5.6 ~ + * + * Lee Jae-Hong, http://www.pyrasis.com + * + * See License.txt + * + */ + +#include "ntifs.h" +#include "ffsdrv.h" + +/* Globals */ + +extern PFFS_GLOBAL FFSGlobal; + + +/* Definitions */ + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE, FFSLog2) +#pragma alloc_text(PAGE, FFSSysTime) +#pragma alloc_text(PAGE, FFSInodeTime) +#pragma alloc_text(PAGE, FFSOEMToUnicode) +#pragma alloc_text(PAGE, FFSUnicodeToOEM) +#endif + +ULONG +FFSLog2( + ULONG Value) +{ + ULONG Order = 0; + + PAGED_CODE(); + + ASSERT(Value > 0); + + while (Value) + { + Order++; + Value >>= 1; + } + + return (Order - 1); +} + + +LARGE_INTEGER +FFSSysTime( + IN ULONG i_time) +{ + LARGE_INTEGER SysTime; + + PAGED_CODE(); + + RtlSecondsSince1970ToTime(i_time, &SysTime); + + return SysTime; +} + +ULONG +FFSInodeTime( + IN LARGE_INTEGER SysTime) +{ + ULONG FFSTime; + + PAGED_CODE(); + + RtlTimeToSecondsSince1970(&SysTime, &FFSTime); + + return FFSTime; +} + + +NTSTATUS +FFSOEMToUnicode( + IN OUT PUNICODE_STRING Unicode, + IN POEM_STRING Oem) +{ + NTSTATUS Status; + + PAGED_CODE(); + + Status = RtlOemStringToUnicodeString( + Unicode, + Oem, + FALSE); + + if (!NT_SUCCESS(Status)) + { + FFSBreakPoint(); + goto errorout; + } + +errorout: + + return Status; +} + + +NTSTATUS +FFSUnicodeToOEM( + IN OUT POEM_STRING Oem, + IN PUNICODE_STRING Unicode) +{ + NTSTATUS Status; + + PAGED_CODE(); + + Status = RtlUnicodeStringToOemString( + Oem, + Unicode, + FALSE); + + if (!NT_SUCCESS(Status)) + { + FFSBreakPoint(); + goto errorout; + } + +errorout: + + return Status; +} diff --git a/reactos/drivers/filesystems/ffs/src/pnp.c b/reactos/drivers/filesystems/ffs/src/pnp.c new file mode 100644 index 00000000000..7c8427f9dc1 --- /dev/null +++ b/reactos/drivers/filesystems/ffs/src/pnp.c @@ -0,0 +1,463 @@ +/* + * FFS File System Driver for Windows + * + * misc.c + * + * 2004.5.6 ~ + * + * Lee Jae-Hong, http://www.pyrasis.com + * + * See License.txt + * + */ + +#include "ntifs.h" +#include "ffsdrv.h" + + +extern PFFS_GLOBAL FFSGlobal; + +#if (_WIN32_WINNT >= 0x0500) + +/* Globals */ + +extern PFFS_GLOBAL FFSGlobal; + +/* Definitions */ + +#define DBG_PNP DBG_USER + +#ifdef _PREFAST_ +IO_COMPLETION_ROUTINE FFSPnpCompletionRoutine; +#endif // _PREFAST_ + +NTSTATUS NTAPI +FFSPnpCompletionRoutine( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID Contxt); + + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE, FFSPnp) +#pragma alloc_text(PAGE, FFSPnpQueryRemove) +#pragma alloc_text(PAGE, FFSPnpRemove) +#pragma alloc_text(PAGE, FFSPnpCancelRemove) +#pragma alloc_text(PAGE, FFSPnpSurpriseRemove) +#endif + + + +NTSTATUS NTAPI +FFSPnpCompletionRoutine( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID Contxt) +{ + PKEVENT Event = (PKEVENT) Contxt; + + KeSetEvent(Event, 0, FALSE); + + return STATUS_MORE_PROCESSING_REQUIRED; + + UNREFERENCED_PARAMETER(DeviceObject); + UNREFERENCED_PARAMETER(Contxt); +} + + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSPnp( + IN PFFS_IRP_CONTEXT IrpContext) +{ + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + PIRP Irp; + PIO_STACK_LOCATION IrpSp; + PFFS_VCB Vcb = 0; + PDEVICE_OBJECT DeviceObject; + + PAGED_CODE(); + + _SEH2_TRY + { + ASSERT(IrpContext); + + ASSERT((IrpContext->Identifier.Type == FFSICX) && + (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); + + DeviceObject = IrpContext->DeviceObject; + + Vcb = (PFFS_VCB)DeviceObject->DeviceExtension; + + ASSERT(Vcb != NULL); + + if (!((Vcb->Identifier.Type == FFSVCB) && + (Vcb->Identifier.Size == sizeof(FFS_VCB)))) + { + _SEH2_LEAVE; // Status = STATUS_INVALID_PARAMETER + } + + Irp = IrpContext->Irp; + IrpSp = IoGetCurrentIrpStackLocation(Irp); + + SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); + + switch (IrpSp->MinorFunction) + { + + case IRP_MN_QUERY_REMOVE_DEVICE: + + FFSPrint((DBG_PNP, "FFSPnp: FFSPnpQueryRemove...\n")); + Status = FFSPnpQueryRemove(IrpContext, Vcb); + + break; + + case IRP_MN_REMOVE_DEVICE: + + FFSPrint((DBG_PNP, "FFSPnp: FFSPnpRemove...\n")); + Status = FFSPnpRemove(IrpContext, Vcb); + break; + + case IRP_MN_CANCEL_REMOVE_DEVICE: + + FFSPrint((DBG_PNP, "FFSPnp: FFSPnpCancelRemove...\n")); + Status = FFSPnpCancelRemove(IrpContext, Vcb); + break; + + case IRP_MN_SURPRISE_REMOVAL: + + FFSPrint((DBG_PNP, "FFSPnp: FFSPnpSupriseRemove...\n")); + Status = FFSPnpSurpriseRemove(IrpContext, Vcb); + break; + + default: + break; + } + } + + _SEH2_FINALLY + { + if (!IrpContext->ExceptionInProgress) + { + Irp = IrpContext->Irp; + + if (Irp) + { + // + // Here we need pass the IRP to the disk driver. + // + + IoSkipCurrentIrpStackLocation(Irp); + + Status = IoCallDriver(Vcb->TargetDeviceObject, Irp); + + IrpContext->Irp = NULL; + } + + FFSCompleteIrpContext(IrpContext, Status); + } + } _SEH2_END; + + return Status; +} + + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSPnpQueryRemove( + PFFS_IRP_CONTEXT IrpContext, + PFFS_VCB Vcb) +{ + NTSTATUS Status; + KEVENT Event; + BOOLEAN bDeleted = FALSE; + BOOLEAN VcbAcquired = FALSE; + + PAGED_CODE(); + + _SEH2_TRY { + + FFSPrint((DBG_PNP, "FFSPnpQueryRemove by FFSPnp ...\n")); + + FFSPrint((DBG_PNP, "FFSPnpQueryRemove: FFSFlushVolume ...\n")); + +#if (_WIN32_WINNT >= 0x0500) + CcWaitForCurrentLazyWriterActivity(); +#endif + + ExAcquireResourceExclusiveLite( + &Vcb->MainResource, TRUE); + VcbAcquired = TRUE; + + FFSFlushFiles(Vcb, FALSE); + + FFSFlushVolume(Vcb, FALSE); + + FFSPrint((DBG_PNP, "FFSPnpQueryRemove: FFSLockVcb: Vcb=%xh FileObject=%xh ...\n", Vcb, IrpContext->FileObject)); + Status = FFSLockVcb(Vcb, IrpContext->FileObject); + + FFSPrint((DBG_PNP, "FFSPnpQueryRemove: FFSPurgeVolume ...\n")); + FFSPurgeVolume(Vcb, TRUE); + + if (!NT_SUCCESS(Status)) + { + _SEH2_LEAVE; + } + + ExReleaseResourceForThreadLite( + &Vcb->MainResource, + ExGetCurrentResourceThread()); + VcbAcquired = FALSE; + + IoCopyCurrentIrpStackLocationToNext(IrpContext->Irp); + + KeInitializeEvent(&Event, NotificationEvent, FALSE); + IoSetCompletionRoutine(IrpContext->Irp, + FFSPnpCompletionRoutine, + &Event, + TRUE, + TRUE, + TRUE); + + FFSPrint((DBG_PNP, "FFSPnpQueryRemove: Call lower level driver...\n")); + Status = IoCallDriver(Vcb->TargetDeviceObject, + IrpContext->Irp); + + if (Status == STATUS_PENDING) + { + KeWaitForSingleObject(&Event, + Executive, + KernelMode, + FALSE, + NULL); + + Status = IrpContext->Irp->IoStatus.Status; + } + + if (NT_SUCCESS(Status)) + { + FFSPrint((DBG_PNP, "FFSPnpQueryRemove: FFSCheckDismount ...\n")); + bDeleted = FFSCheckDismount(IrpContext, Vcb, TRUE); + FFSPrint((DBG_PNP, "FFSPnpQueryRemove: FFSFlushVolume bDelted=%xh ...\n", bDeleted)); + } + + ASSERT(!(NT_SUCCESS(Status) && !bDeleted)); + } + + _SEH2_FINALLY + { + if (VcbAcquired) + { + ExReleaseResourceForThreadLite( + &Vcb->MainResource, + ExGetCurrentResourceThread()); + } + + FFSCompleteRequest( + IrpContext->Irp, FALSE, (CCHAR)(NT_SUCCESS(Status) ? + IO_DISK_INCREMENT : IO_NO_INCREMENT)); + + IrpContext->Irp = NULL; + } _SEH2_END; + + return Status; +} + + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSPnpRemove( + PFFS_IRP_CONTEXT IrpContext, + PFFS_VCB Vcb) +{ + NTSTATUS Status; + KEVENT Event; + BOOLEAN bDeleted; + + PAGED_CODE(); + + _SEH2_TRY + { + + FFSPrint((DBG_PNP, "FFSPnpRemove by FFSPnp ...\n")); +#if (_WIN32_WINNT >= 0x0500) + CcWaitForCurrentLazyWriterActivity(); +#endif + ExAcquireResourceExclusiveLite( + &Vcb->MainResource, TRUE); + + Status = FFSLockVcb(Vcb, IrpContext->FileObject); + + ExReleaseResourceForThreadLite( + &Vcb->MainResource, + ExGetCurrentResourceThread()); + + // + // Setup the Irp. We'll send it to the lower disk driver. + // + + IoCopyCurrentIrpStackLocationToNext(IrpContext->Irp); + + KeInitializeEvent(&Event, NotificationEvent, FALSE); + IoSetCompletionRoutine(IrpContext->Irp, + FFSPnpCompletionRoutine, + &Event, + TRUE, + TRUE, + TRUE); + + Status = IoCallDriver(Vcb->TargetDeviceObject, + IrpContext->Irp); + + if (Status == STATUS_PENDING) + { + + KeWaitForSingleObject(&Event, + Executive, + KernelMode, + FALSE, + NULL); + + Status = IrpContext->Irp->IoStatus.Status; + } + + ExAcquireResourceExclusiveLite( + &Vcb->MainResource, TRUE); + + FFSPurgeVolume(Vcb, FALSE); + + ExReleaseResourceForThreadLite( + &Vcb->MainResource, + ExGetCurrentResourceThread()); + + bDeleted = FFSCheckDismount(IrpContext, Vcb, TRUE); + } + + _SEH2_FINALLY + { + FFSCompleteRequest( + IrpContext->Irp, FALSE, (CCHAR)(NT_SUCCESS(Status)? + IO_DISK_INCREMENT : IO_NO_INCREMENT)); + + IrpContext->Irp = NULL; + } _SEH2_END; + + return Status; +} + + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSPnpSurpriseRemove( + PFFS_IRP_CONTEXT IrpContext, + PFFS_VCB Vcb) +{ + NTSTATUS Status; + KEVENT Event; + BOOLEAN bDeleted; + + PAGED_CODE(); + + _SEH2_TRY + { + + FFSPrint((DBG_PNP, "FFSPnpSupriseRemove by FFSPnp ...\n")); +#if (_WIN32_WINNT >= 0x0500) + CcWaitForCurrentLazyWriterActivity(); +#endif + ExAcquireResourceExclusiveLite( + &Vcb->MainResource, TRUE); + + Status = FFSLockVcb(Vcb, IrpContext->FileObject); + + ExReleaseResourceForThreadLite( + &Vcb->MainResource, + ExGetCurrentResourceThread()); + + // + // Setup the Irp. We'll send it to the lower disk driver. + // + + IoCopyCurrentIrpStackLocationToNext(IrpContext->Irp); + + KeInitializeEvent(&Event, NotificationEvent, FALSE); + IoSetCompletionRoutine(IrpContext->Irp, + FFSPnpCompletionRoutine, + &Event, + TRUE, + TRUE, + TRUE); + + Status = IoCallDriver(Vcb->TargetDeviceObject, + IrpContext->Irp); + + if (Status == STATUS_PENDING) + { + + KeWaitForSingleObject(&Event, + Executive, + KernelMode, + FALSE, + NULL); + + Status = IrpContext->Irp->IoStatus.Status; + } + + ExAcquireResourceExclusiveLite( + &Vcb->MainResource, TRUE); + + FFSPurgeVolume(Vcb, FALSE); + + ExReleaseResourceForThreadLite( + &Vcb->MainResource, + ExGetCurrentResourceThread()); + + bDeleted = FFSCheckDismount(IrpContext, Vcb, TRUE); + } + + _SEH2_FINALLY + { + FFSCompleteRequest( + IrpContext->Irp, FALSE, (CCHAR)(NT_SUCCESS(Status)? + IO_DISK_INCREMENT : IO_NO_INCREMENT)); + + IrpContext->Irp = NULL; + } _SEH2_END; + + return Status; +} + + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSPnpCancelRemove( + PFFS_IRP_CONTEXT IrpContext, + PFFS_VCB Vcb) +{ + NTSTATUS Status; + + PAGED_CODE(); + + FFSPrint((DBG_PNP, "FFSPnpCancelRemove by FFSPnp ...\n")); + + ExAcquireResourceExclusiveLite( + &Vcb->MainResource, TRUE); + + Status = FFSUnlockVcb(Vcb, IrpContext->FileObject); + + ExReleaseResourceForThreadLite( + &Vcb->MainResource, + ExGetCurrentResourceThread()); + + IoSkipCurrentIrpStackLocation(IrpContext->Irp); + + Status = IoCallDriver(Vcb->TargetDeviceObject, IrpContext->Irp); + + IrpContext->Irp = NULL; + + return Status; +} + + +#endif //(_WIN32_WINNT >= 0x0500) diff --git a/reactos/drivers/filesystems/ffs/src/read.c b/reactos/drivers/filesystems/ffs/src/read.c new file mode 100644 index 00000000000..b5a5cc585a6 --- /dev/null +++ b/reactos/drivers/filesystems/ffs/src/read.c @@ -0,0 +1,1155 @@ +/* + * FFS File System Driver for Windows + * + * read.c + * + * 2004.5.6 ~ + * + * Lee Jae-Hong, http://www.pyrasis.com + * + * See License.txt + * + */ + +#include "ntifs.h" +#include "ffsdrv.h" + +/* Globals */ + +extern PFFS_GLOBAL FFSGlobal; + + +/* Definitions */ + +NTSTATUS +FFSReadComplete( + IN PFFS_IRP_CONTEXT IrpContext); + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSReadFile( + IN PFFS_IRP_CONTEXT IrpContext); + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSReadVolume( + IN PFFS_IRP_CONTEXT IrpContext); + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE, FFSCompleteIrpContext) +#pragma alloc_text(PAGE, FFSCopyRead) +#pragma alloc_text(PAGE, FFSRead) +#pragma alloc_text(PAGE, FFSReadVolume) +#pragma alloc_text(PAGE, FFSv1ReadInode) +#pragma alloc_text(PAGE, FFSv2ReadInode) +#pragma alloc_text(PAGE, FFSReadFile) +#pragma alloc_text(PAGE, FFSReadComplete) + +#endif + + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSCompleteIrpContext( + IN PFFS_IRP_CONTEXT IrpContext, + IN NTSTATUS Status) +{ + PIRP Irp = NULL; + BOOLEAN bPrint; + + PAGED_CODE(); + + Irp = IrpContext->Irp; + + if (Irp != NULL) + { + if (NT_ERROR(Status)) + { + Irp->IoStatus.Information = 0; + } + + Irp->IoStatus.Status = Status; + bPrint = !IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED); + + FFSCompleteRequest( + Irp, bPrint, (CCHAR)(NT_SUCCESS(Status)? + IO_DISK_INCREMENT : IO_NO_INCREMENT)); + + IrpContext->Irp = NULL; + } + + FFSFreeIrpContext(IrpContext); + + return Status; +} + + +BOOLEAN +FFSCopyRead( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN BOOLEAN Wait, + OUT PVOID Buffer, + OUT PIO_STATUS_BLOCK IoStatus) +{ + BOOLEAN bRet; + + PAGED_CODE(); + + bRet = CcCopyRead(FileObject, + FileOffset, + Length, + Wait, + Buffer, + IoStatus); + + if (bRet) + { + ASSERT(NT_SUCCESS(IoStatus->Status)); + } + + return bRet; +/* + PVOID Bcb = NULL; + PVOID Buf = NULL; + + if (CcMapData(FileObject, + FileOffset, + Length, + Wait, + &Bcb, + &Buf)) + { + RtlCopyMemory(Buffer, Buf, Length); + IoStatus->Status = STATUS_SUCCESS; + IoStatus->Information = Length; + CcUnpinData(Bcb); + return TRUE; + + } + else + { + // IoStatus->Status = STATUS_ + return FALSE; + } +*/ +} + + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSReadVolume( + IN PFFS_IRP_CONTEXT IrpContext) +{ + NTSTATUS Status = STATUS_UNSUCCESSFUL; + + PFFS_VCB Vcb = 0; + PFFS_CCB Ccb; + PFFS_FCBVCB FcbOrVcb; + PFILE_OBJECT FileObject; + + PDEVICE_OBJECT DeviceObject; + + PIRP Irp; + PIO_STACK_LOCATION IoStackLocation; + + ULONG Length; + LARGE_INTEGER ByteOffset; + + BOOLEAN PagingIo; + BOOLEAN Nocache; + BOOLEAN SynchronousIo; + BOOLEAN MainResourceAcquired = FALSE; + BOOLEAN PagingIoResourceAcquired = FALSE; + + PUCHAR Buffer = NULL; + PFFS_BDL ffs_bdl = NULL; + + PAGED_CODE(); + + _SEH2_TRY + { + ASSERT(IrpContext); + + ASSERT((IrpContext->Identifier.Type == FFSICX) && + (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); + + DeviceObject = IrpContext->DeviceObject; + + Vcb = (PFFS_VCB)DeviceObject->DeviceExtension; + + ASSERT(Vcb != NULL); + + ASSERT((Vcb->Identifier.Type == FFSVCB) && + (Vcb->Identifier.Size == sizeof(FFS_VCB))); + + FileObject = IrpContext->FileObject; + + FcbOrVcb = (PFFS_FCBVCB)FileObject->FsContext; + + ASSERT(FcbOrVcb); + + if (!(FcbOrVcb->Identifier.Type == FFSVCB && (PVOID)FcbOrVcb == (PVOID)Vcb)) + { + Status = STATUS_INVALID_DEVICE_REQUEST; + _SEH2_LEAVE; + } + + Ccb = (PFFS_CCB)FileObject->FsContext2; + + Irp = IrpContext->Irp; + + Irp->IoStatus.Information = 0; + + IoStackLocation = IoGetCurrentIrpStackLocation(Irp); + + Length = IoStackLocation->Parameters.Read.Length; + ByteOffset = IoStackLocation->Parameters.Read.ByteOffset; + + PagingIo = (Irp->Flags & IRP_PAGING_IO ? TRUE : FALSE); + Nocache = (Irp->Flags & IRP_NOCACHE ? TRUE : FALSE); + SynchronousIo = (FileObject->Flags & FO_SYNCHRONOUS_IO ? TRUE : FALSE); + + if (Length == 0) + { + Irp->IoStatus.Information = 0; + Status = STATUS_SUCCESS; + _SEH2_LEAVE; + } + + if (Ccb != NULL) + { + if(!IsFlagOn(Ccb->Flags, CCB_ALLOW_EXTENDED_DASD_IO)) + { + if (ByteOffset.QuadPart + Length > Vcb->Header.FileSize.QuadPart) + { + Length = (ULONG)(Vcb->Header.FileSize.QuadPart - ByteOffset.QuadPart); + } + } + + { + FFS_BDL BlockArray; + + if ((ByteOffset.LowPart & (SECTOR_SIZE - 1)) || + (Length & (SECTOR_SIZE - 1))) + { + Status = STATUS_INVALID_PARAMETER; + _SEH2_LEAVE; + } + + Status = FFSLockUserBuffer( + IrpContext->Irp, + Length, + IoReadAccess); + + if (!NT_SUCCESS(Status)) + { + _SEH2_LEAVE; + } + + BlockArray.Irp = NULL; + BlockArray.Lba = ByteOffset.QuadPart;; + BlockArray.Offset = 0; + BlockArray.Length = Length; + + Status = FFSReadWriteBlocks(IrpContext, + Vcb, + &BlockArray, + Length, + 1, + FALSE); + Irp = IrpContext->Irp; + + _SEH2_LEAVE; + } + } + + if (Nocache && + ((ByteOffset.LowPart & (SECTOR_SIZE - 1)) || + (Length & (SECTOR_SIZE - 1)))) + { + FFSBreakPoint(); + + Status = STATUS_INVALID_PARAMETER; + _SEH2_LEAVE; + } + + if (FlagOn(IrpContext->MinorFunction, IRP_MN_DPC)) + { + ClearFlag(IrpContext->MinorFunction, IRP_MN_DPC); + Status = STATUS_PENDING; + _SEH2_LEAVE; + } + + if (!PagingIo) + { + if (!ExAcquireResourceSharedLite( + &Vcb->MainResource, + IrpContext->IsSynchronous)) + { + Status = STATUS_PENDING; + _SEH2_LEAVE; + } + + MainResourceAcquired = TRUE; + } + else + { + if (!ExAcquireResourceSharedLite( + &Vcb->PagingIoResource, + IrpContext->IsSynchronous)) + { + Status = STATUS_PENDING; + _SEH2_LEAVE; + } + + PagingIoResourceAcquired = TRUE; + } + + + if (ByteOffset.QuadPart >= + Vcb->PartitionInformation.PartitionLength.QuadPart) + { + Irp->IoStatus.Information = 0; + Status = STATUS_END_OF_FILE; + _SEH2_LEAVE; + } + + if (!Nocache) + { + if ((ByteOffset.QuadPart + Length) > + Vcb->PartitionInformation.PartitionLength.QuadPart) + { + Length = (ULONG)( + Vcb->PartitionInformation.PartitionLength.QuadPart - + ByteOffset.QuadPart); + Length &= ~((ULONG)SECTOR_SIZE - 1); + } + + if (FlagOn(IrpContext->MinorFunction, IRP_MN_MDL)) + { + CcMdlRead( + Vcb->StreamObj, + &ByteOffset, + Length, + &Irp->MdlAddress, + &Irp->IoStatus); + + Status = Irp->IoStatus.Status; + } + else + { + Buffer = FFSGetUserBuffer(Irp); + + if (Buffer == NULL) + { + FFSBreakPoint(); + Status = STATUS_INVALID_USER_BUFFER; + _SEH2_LEAVE; + } + + if (!CcCopyRead( + Vcb->StreamObj, + (PLARGE_INTEGER)&ByteOffset, + Length, + IrpContext->IsSynchronous, + Buffer, + &Irp->IoStatus)) + { + Status = STATUS_PENDING; + _SEH2_LEAVE; + } + + Status = Irp->IoStatus.Status; + } + } + else + { + if ((ByteOffset.QuadPart + Length) > + Vcb->PartitionInformation.PartitionLength.QuadPart + ) + { + Length = (ULONG)( + Vcb->PartitionInformation.PartitionLength.QuadPart - + ByteOffset.QuadPart); + + Length &= ~((ULONG)SECTOR_SIZE - 1); + } + + Status = FFSLockUserBuffer( + IrpContext->Irp, + Length, + IoWriteAccess); + + if (!NT_SUCCESS(Status)) + { + _SEH2_LEAVE; + } + +#if DBG + Buffer = FFSGetUserBuffer(Irp); +#endif + ffs_bdl = ExAllocatePoolWithTag(PagedPool, sizeof(FFS_BDL), FFS_POOL_TAG); + + if (!ffs_bdl) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + _SEH2_LEAVE; + } + + ffs_bdl->Irp = NULL; + ffs_bdl->Lba = ByteOffset.QuadPart; + ffs_bdl->Length = Length; + ffs_bdl->Offset = 0; + + Status = FFSReadWriteBlocks(IrpContext, + Vcb, + ffs_bdl, + Length, + 1, + FALSE); + + if (NT_SUCCESS(Status)) + { + Irp->IoStatus.Information = Length; + } + + Irp = IrpContext->Irp; + + if (!Irp) + _SEH2_LEAVE; + } + } + + _SEH2_FINALLY + { + if (PagingIoResourceAcquired) + { + ExReleaseResourceForThreadLite( + &Vcb->PagingIoResource, + ExGetCurrentResourceThread()); + } + + if (MainResourceAcquired) + { + ExReleaseResourceForThreadLite( + &Vcb->MainResource, + ExGetCurrentResourceThread()); + } + + if (ffs_bdl) + ExFreePool(ffs_bdl); + + if (!IrpContext->ExceptionInProgress) + { + if (IrpContext->Irp) + { + if (Status == STATUS_PENDING && + !IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED)) + { + Status = FFSLockUserBuffer( + IrpContext->Irp, + Length, + IoWriteAccess); + + if (NT_SUCCESS(Status)) + { + Status = FFSQueueRequest(IrpContext); + } + else + { + FFSCompleteIrpContext(IrpContext, Status); + } + } + else + { + if (NT_SUCCESS(Status)) + { + if (SynchronousIo && !PagingIo) + { + IrpContext->FileObject->CurrentByteOffset.QuadPart = + ByteOffset.QuadPart + IrpContext->Irp->IoStatus.Information; + } + + if (!PagingIo) + { + IrpContext->FileObject->Flags &= ~FO_FILE_FAST_IO_READ; + } + } + + FFSCompleteIrpContext(IrpContext, Status); + } + } + else + { + FFSFreeIrpContext(IrpContext); + } + } + } _SEH2_END; + + return Status; +} + + +NTSTATUS +FFSv1ReadInode( + IN PFFS_IRP_CONTEXT IrpContext, + IN PFFS_VCB Vcb, + IN PFFSv1_INODE dinode1, + IN ULONGLONG offset, + IN PVOID Buffer, + IN ULONG size, + OUT PULONG dwRet) +{ + PFFS_BDL ffs_bdl = NULL; + ULONG blocks, i; + NTSTATUS Status = STATUS_UNSUCCESSFUL; + IO_STATUS_BLOCK IoStatus; + + ULONG Totalblocks; + LONGLONG AllocSize; + + PAGED_CODE(); + + if (dwRet) + { + *dwRet = 0; + } + + Totalblocks = (dinode1->di_blocks); + AllocSize = ((LONGLONG)(FFSDataBlocks(Vcb, Totalblocks)) << BLOCK_BITS); + + if ((LONGLONG)offset >= AllocSize) + { + FFSPrint((DBG_ERROR, "FFSv1ReadInode: beyond the file range.\n")); + return STATUS_SUCCESS; + } + + if ((LONGLONG)offset + size > AllocSize) + { + size = (ULONG)(AllocSize - offset); + } + + blocks = FFSv1BuildBDL(IrpContext, Vcb, dinode1, offset, size, &ffs_bdl); + + if (blocks <= 0) + { + FFSBreakPoint(); + goto errorout; + } + + if (IrpContext) + { + // assume offset is aligned. + Status = FFSReadWriteBlocks(IrpContext, Vcb, ffs_bdl, size, blocks, FALSE); + } + else + { + for(i = 0; i < blocks; i++) + { + IoStatus.Information = 0; + +#if DBG + KdPrint(("FFSv1ReadInode() i : %d, Lba : %x, Length : %x, Offset : %x\n", + i, ffs_bdl[i].Lba, ffs_bdl[i].Length, ffs_bdl[i].Offset)); +#endif + + FFSCopyRead( + Vcb->StreamObj, + (PLARGE_INTEGER)(&(ffs_bdl[i].Lba)), + ffs_bdl[i].Length, + PIN_WAIT, + (PVOID)((PUCHAR)Buffer + ffs_bdl[i].Offset), + &IoStatus); + + Status = IoStatus.Status; + } + } + +errorout: + + if (ffs_bdl) + ExFreePool(ffs_bdl); + + if (NT_SUCCESS(Status)) + { + if (dwRet) *dwRet = size; + } + + return Status; +} + + +NTSTATUS +FFSv2ReadInode( + IN PFFS_IRP_CONTEXT IrpContext, + IN PFFS_VCB Vcb, + IN PFFSv2_INODE dinode2, + IN ULONGLONG offset, + IN PVOID Buffer, + IN ULONG size, + OUT PULONG dwRet) +{ + PFFS_BDL ffs_bdl = NULL; + ULONG blocks, i; + NTSTATUS Status = STATUS_UNSUCCESSFUL; + IO_STATUS_BLOCK IoStatus; + + ULONG Totalblocks; + LONGLONG AllocSize; + + PAGED_CODE(); + + if (dwRet) + { + *dwRet = 0; + } + + Totalblocks = (ULONG)(dinode2->di_blocks); + AllocSize = ((LONGLONG)(FFSDataBlocks(Vcb, Totalblocks)) << BLOCK_BITS); + + if ((LONGLONG)offset >= AllocSize) + { + FFSPrint((DBG_ERROR, "FFSv2ReadInode: beyond the file range.\n")); + return STATUS_SUCCESS; + } + + if ((LONGLONG)offset + size > AllocSize) + { + size = (ULONG)(AllocSize - offset); + } + + blocks = FFSv2BuildBDL(IrpContext, Vcb, dinode2, offset, size, &ffs_bdl); + + if (blocks <= 0) + { + FFSBreakPoint(); + goto errorout; + } + + if (IrpContext) + { + // assume offset is aligned. + Status = FFSReadWriteBlocks(IrpContext, Vcb, ffs_bdl, size, blocks, FALSE); + } + else + { + for(i = 0; i < blocks; i++) + { + IoStatus.Information = 0; + +#if 0 + KdPrint(("FFSv2ReadInode() i : %d, Lba : %x, Length : %x, Offset : %x\n", + i, ffs_bdl[i].Lba, ffs_bdl[i].Length, ffs_bdl[i].Offset)); +#endif + + FFSCopyRead( + Vcb->StreamObj, + (PLARGE_INTEGER)(&(ffs_bdl[i].Lba)), + ffs_bdl[i].Length, + PIN_WAIT, + (PVOID)((PUCHAR)Buffer + ffs_bdl[i].Offset), + &IoStatus); + + Status = IoStatus.Status; + } + } + +errorout: + + if (ffs_bdl) + ExFreePool(ffs_bdl); + + if (NT_SUCCESS(Status)) + { + if (dwRet) *dwRet = size; + } + + return Status; +} + + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSReadFile( + IN PFFS_IRP_CONTEXT IrpContext) +{ + NTSTATUS Status = STATUS_UNSUCCESSFUL; + + PFFS_VCB Vcb; + PFFS_FCB Fcb = 0; + PFFS_CCB Ccb; + PFILE_OBJECT FileObject; + PFILE_OBJECT CacheObject; + + PDEVICE_OBJECT DeviceObject; + + PIRP Irp; + PIO_STACK_LOCATION IoStackLocation; + + ULONG Length; + ULONG ReturnedLength; + LARGE_INTEGER ByteOffset; + + BOOLEAN PagingIo; + BOOLEAN Nocache; + BOOLEAN SynchronousIo; + BOOLEAN MainResourceAcquired = FALSE; + BOOLEAN PagingIoResourceAcquired = FALSE; + + PUCHAR Buffer; + + PAGED_CODE(); + + _SEH2_TRY + { + ASSERT(IrpContext); + + ASSERT((IrpContext->Identifier.Type == FFSICX) && + (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); + + DeviceObject = IrpContext->DeviceObject; + + Vcb = (PFFS_VCB)DeviceObject->DeviceExtension; + + ASSERT(Vcb != NULL); + + ASSERT((Vcb->Identifier.Type == FFSVCB) && + (Vcb->Identifier.Size == sizeof(FFS_VCB))); + + FileObject = IrpContext->FileObject; + + Fcb = (PFFS_FCB)FileObject->FsContext; + + ASSERT(Fcb); + + ASSERT((Fcb->Identifier.Type == FFSFCB) && + (Fcb->Identifier.Size == sizeof(FFS_FCB))); + + Ccb = (PFFS_CCB)FileObject->FsContext2; + + Irp = IrpContext->Irp; + + IoStackLocation = IoGetCurrentIrpStackLocation(Irp); + + Length = IoStackLocation->Parameters.Read.Length; + ByteOffset = IoStackLocation->Parameters.Read.ByteOffset; + + PagingIo = (Irp->Flags & IRP_PAGING_IO ? TRUE : FALSE); + Nocache = (Irp->Flags & IRP_NOCACHE ? TRUE : FALSE); + SynchronousIo = (FileObject->Flags & FO_SYNCHRONOUS_IO ? TRUE : FALSE); + +#if 0 +/* + if (IsFlagOn(Fcb->Flags, FCB_FILE_DELETED)) + { + Status = STATUS_FILE_DELETED; + _SEH2_LEAVE; + } + + if (IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING)) + { + Status = STATUS_DELETE_PENDING; + _SEH2_LEAVE; + } +*/ +#endif + + if (Length == 0) + { + Irp->IoStatus.Information = 0; + Status = STATUS_SUCCESS; + _SEH2_LEAVE; + } + + if (Nocache && + (ByteOffset.LowPart & (SECTOR_SIZE - 1) || + Length & (SECTOR_SIZE - 1))) + { + Status = STATUS_INVALID_PARAMETER; + FFSBreakPoint(); + _SEH2_LEAVE; + } + + if (FlagOn(IrpContext->MinorFunction, IRP_MN_DPC)) + { + ClearFlag(IrpContext->MinorFunction, IRP_MN_DPC); + Status = STATUS_PENDING; + FFSBreakPoint(); + _SEH2_LEAVE; + } + + if (!PagingIo) + { + if (!ExAcquireResourceSharedLite( + &Fcb->MainResource, + IrpContext->IsSynchronous)) + { + Status = STATUS_PENDING; + _SEH2_LEAVE; + } + + MainResourceAcquired = TRUE; + + if (!FsRtlCheckLockForReadAccess( + &Fcb->FileLockAnchor, + Irp)) + { + Status = STATUS_FILE_LOCK_CONFLICT; + _SEH2_LEAVE; + } + } + else + { + if (!ExAcquireResourceSharedLite( + &Fcb->PagingIoResource, + IrpContext->IsSynchronous)) + { + Status = STATUS_PENDING; + _SEH2_LEAVE; + } + + PagingIoResourceAcquired = TRUE; + } + + if (!Nocache) + { + if ((ByteOffset.QuadPart + (LONGLONG)Length) > + Fcb->Header.FileSize.QuadPart) + { + if (ByteOffset.QuadPart >= (Fcb->Header.FileSize.QuadPart)) + { + Irp->IoStatus.Information = 0; + Status = STATUS_END_OF_FILE; + _SEH2_LEAVE; + } + + Length = + (ULONG)(Fcb->Header.FileSize.QuadPart - ByteOffset.QuadPart); + + } + + ReturnedLength = Length; + + if (IsDirectory(Fcb)) + { + _SEH2_LEAVE; + } + + { + if (FileObject->PrivateCacheMap == NULL) + { + CcInitializeCacheMap( + FileObject, + (PCC_FILE_SIZES)(&Fcb->Header.AllocationSize), + FALSE, + &FFSGlobal->CacheManagerCallbacks, + Fcb); + } + + CacheObject = FileObject; + } + + if (FlagOn(IrpContext->MinorFunction, IRP_MN_MDL)) + { + CcMdlRead( + CacheObject, + (&ByteOffset), + Length, + &Irp->MdlAddress, + &Irp->IoStatus); + + Status = Irp->IoStatus.Status; + } + else + { + Buffer = FFSGetUserBuffer(Irp); + + if (Buffer == NULL) + { + Status = STATUS_INVALID_USER_BUFFER; + FFSBreakPoint(); + _SEH2_LEAVE; + } + + if (!CcCopyRead( + CacheObject, + (PLARGE_INTEGER)&ByteOffset, + Length, + IrpContext->IsSynchronous, + Buffer, + &Irp->IoStatus)) + { + Status = STATUS_PENDING; + FFSBreakPoint(); + _SEH2_LEAVE; + } + + Status = Irp->IoStatus.Status; + } + } + else + { + /* ByteOffset°ú AllocationSize ¸ðµÎ 0ÀÌ ¾Æ´Ò¶§ */ + if (ByteOffset.QuadPart && Fcb->Header.AllocationSize.QuadPart) + { + if ((ByteOffset.QuadPart + (LONGLONG)Length) > Fcb->Header.AllocationSize.QuadPart) + { + + if (ByteOffset.QuadPart >= Fcb->Header.AllocationSize.QuadPart) + { + Irp->IoStatus.Information = 0; + Status = STATUS_END_OF_FILE; + FFSBreakPoint(); + _SEH2_LEAVE; + } + + Length = + (ULONG)(Fcb->Header.AllocationSize.QuadPart- ByteOffset.QuadPart); + } + } + + ReturnedLength = Length; + + Status = FFSLockUserBuffer( + IrpContext->Irp, + Length, + IoWriteAccess); + + if (!NT_SUCCESS(Status)) + { + _SEH2_LEAVE; + } + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = Length; + + if (FS_VERSION == 1) + { + Status = + FFSv1ReadInode( + IrpContext, + Vcb, + Fcb->dinode1, + ByteOffset.QuadPart, + NULL, + Length, + &ReturnedLength); + } + else + { + Status = + FFSv2ReadInode( + IrpContext, + Vcb, + Fcb->dinode2, + ByteOffset.QuadPart, + NULL, + Length, + &ReturnedLength); + } + + Irp = IrpContext->Irp; + + } + } + + _SEH2_FINALLY + { + if (PagingIoResourceAcquired) + { + ExReleaseResourceForThreadLite( + &Fcb->PagingIoResource, + ExGetCurrentResourceThread()); + } + + if (MainResourceAcquired) + { + ExReleaseResourceForThreadLite( + &Fcb->MainResource, + ExGetCurrentResourceThread()); + } + + if (!IrpContext->ExceptionInProgress) + { + if (IrpContext->Irp) + { + if (Status == STATUS_PENDING) + { + Status = FFSLockUserBuffer( + IrpContext->Irp, + Length, + IoWriteAccess); + + if (NT_SUCCESS(Status)) + { + Status = FFSQueueRequest(IrpContext); + } + else + { + FFSCompleteIrpContext(IrpContext, Status); + } + } + else + { + if (NT_SUCCESS(Status)) + { + if (SynchronousIo && !PagingIo) + { + IrpContext->FileObject->CurrentByteOffset.QuadPart = + ByteOffset.QuadPart + IrpContext->Irp->IoStatus.Information; + } + + if (!PagingIo) + { + IrpContext->FileObject->Flags &= ~FO_FILE_FAST_IO_READ; + } + } + + FFSCompleteIrpContext(IrpContext, Status); + } + } + else + { + FFSFreeIrpContext(IrpContext); + } + } + } _SEH2_END; + + return Status; + +} + + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSReadComplete( + IN PFFS_IRP_CONTEXT IrpContext) +{ + NTSTATUS Status = STATUS_UNSUCCESSFUL; + PFILE_OBJECT FileObject; + PIRP Irp; + + PAGED_CODE(); + + _SEH2_TRY + { + ASSERT(IrpContext); + + ASSERT((IrpContext->Identifier.Type == FFSICX) && + (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); + + FileObject = IrpContext->FileObject; + + Irp = IrpContext->Irp; + + CcMdlReadComplete(FileObject, Irp->MdlAddress); + + Irp->MdlAddress = NULL; + + Status = STATUS_SUCCESS; + } + + _SEH2_FINALLY + { + if (!IrpContext->ExceptionInProgress) + { + FFSCompleteIrpContext(IrpContext, Status); + } + } _SEH2_END; + + return Status; +} + + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSRead( + IN PFFS_IRP_CONTEXT IrpContext) +{ + NTSTATUS Status; + PFFS_VCB Vcb; + PFFS_FCBVCB FcbOrVcb; + PDEVICE_OBJECT DeviceObject; + PFILE_OBJECT FileObject; + BOOLEAN bCompleteRequest; + + PAGED_CODE(); + + ASSERT(IrpContext); + + ASSERT((IrpContext->Identifier.Type == FFSICX) && + (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); + _SEH2_TRY + { + + if (FlagOn(IrpContext->MinorFunction, IRP_MN_COMPLETE)) + { + Status = FFSReadComplete(IrpContext); + bCompleteRequest = FALSE; + } + else + { + DeviceObject = IrpContext->DeviceObject; + + if (DeviceObject == FFSGlobal->DeviceObject) + { + Status = STATUS_INVALID_DEVICE_REQUEST; + bCompleteRequest = TRUE; + _SEH2_LEAVE; + } + + Vcb = (PFFS_VCB)DeviceObject->DeviceExtension; + + if (Vcb->Identifier.Type != FFSVCB || + Vcb->Identifier.Size != sizeof(FFS_VCB)) + { + Status = STATUS_INVALID_DEVICE_REQUEST; + bCompleteRequest = TRUE; + + _SEH2_LEAVE; + } + + if (IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING)) + { + Status = STATUS_TOO_LATE; + bCompleteRequest = TRUE; + _SEH2_LEAVE; + } + + FileObject = IrpContext->FileObject; + + FcbOrVcb = (PFFS_FCBVCB)FileObject->FsContext; + + if (FcbOrVcb->Identifier.Type == FFSVCB) + { + Status = FFSReadVolume(IrpContext); + bCompleteRequest = FALSE; + } + else if (FcbOrVcb->Identifier.Type == FFSFCB) + { + Status = FFSReadFile(IrpContext); + bCompleteRequest = FALSE; + } + else + { + FFSPrint((DBG_ERROR, "FFSRead: INVALID PARAMETER ... \n")); + FFSBreakPoint(); + + Status = STATUS_INVALID_PARAMETER; + bCompleteRequest = TRUE; + } + } + } + + _SEH2_FINALLY + { + if (bCompleteRequest) + { + FFSCompleteIrpContext(IrpContext, Status); + } + } _SEH2_END; + + return Status; +} diff --git a/reactos/drivers/filesystems/ffs/src/shutdown.c b/reactos/drivers/filesystems/ffs/src/shutdown.c new file mode 100644 index 00000000000..67062dab9b6 --- /dev/null +++ b/reactos/drivers/filesystems/ffs/src/shutdown.c @@ -0,0 +1,136 @@ +/* + * FFS File System Driver for Windows + * + * read.c + * + * 2004.5.6 ~ + * + * Lee Jae-Hong, http://www.pyrasis.com + * + * See License.txt + * + */ + +#include "ntifs.h" +#include "ffsdrv.h" + +/* Globals */ + +extern PFFS_GLOBAL FFSGlobal; + + +/* Definitions */ + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE, FFSShutDown) +#endif + + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSShutDown( + IN PFFS_IRP_CONTEXT IrpContext) +{ + NTSTATUS Status; + + PKEVENT Event; + + PIRP Irp; + PIO_STACK_LOCATION IrpSp; + + PFFS_VCB Vcb; + PLIST_ENTRY ListEntry; + + BOOLEAN GlobalResourceAcquired = FALSE; + + PAGED_CODE(); + + _SEH2_TRY + { + ASSERT(IrpContext); + + ASSERT((IrpContext->Identifier.Type == FFSICX) && + (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); + + Status = STATUS_SUCCESS; + + Irp = IrpContext->Irp; + + IrpSp = IoGetCurrentIrpStackLocation(Irp); +#ifdef _MSC_VER +#pragma prefast( suppress: 28137, "by design" ) +#endif + if (!ExAcquireResourceExclusiveLite( + &FFSGlobal->Resource, + IrpContext->IsSynchronous)) + { + Status = STATUS_PENDING; + _SEH2_LEAVE; + } + + GlobalResourceAcquired = TRUE; + + Event = ExAllocatePoolWithTag(NonPagedPool, sizeof(KEVENT), FFS_POOL_TAG); + KeInitializeEvent(Event, NotificationEvent, FALSE); + + for (ListEntry = FFSGlobal->VcbList.Flink; + ListEntry != &(FFSGlobal->VcbList); + ListEntry = ListEntry->Flink) + { + Vcb = CONTAINING_RECORD(ListEntry, FFS_VCB, Next); + + if (ExAcquireResourceExclusiveLite( + &Vcb->MainResource, + TRUE)) + { + + Status = FFSFlushFiles(Vcb, TRUE); + if(!NT_SUCCESS(Status)) + { + FFSBreakPoint(); + } + + Status = FFSFlushVolume(Vcb, TRUE); + + if(!NT_SUCCESS(Status)) + { + FFSBreakPoint(); + } + + FFSDiskShutDown(Vcb); + + ExReleaseResourceForThreadLite( + &Vcb->MainResource, + ExGetCurrentResourceThread()); + } + } + + /* + IoUnregisterFileSystem(FFSGlobal->DeviceObject); + */ + } + + _SEH2_FINALLY + { + if (GlobalResourceAcquired) + { + ExReleaseResourceForThreadLite( + &FFSGlobal->Resource, + ExGetCurrentResourceThread()); + } + + if (!IrpContext->ExceptionInProgress) + { + if (Status == STATUS_PENDING) + { + FFSQueueRequest(IrpContext); + } + else + { + FFSCompleteIrpContext(IrpContext, Status); + } + } + } _SEH2_END; + + return Status; +} diff --git a/reactos/drivers/filesystems/ffs/src/volinfo.c b/reactos/drivers/filesystems/ffs/src/volinfo.c new file mode 100644 index 00000000000..680a30ecd1b --- /dev/null +++ b/reactos/drivers/filesystems/ffs/src/volinfo.c @@ -0,0 +1,478 @@ +/* + * FFS File System Driver for Windows + * + * volinfo.c + * + * 2004.5.6 ~ + * + * Lee Jae-Hong, http://www.pyrasis.com + * + * See License.txt + * + */ + +#include "ntifs.h" +#include "ffsdrv.h" + +/* Globals */ + +extern PFFS_GLOBAL FFSGlobal; + + +/* Definitions */ + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE, FFSQueryVolumeInformation) +#pragma alloc_text(PAGE, FFSSetVolumeInformation) +#endif + + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSQueryVolumeInformation( + IN PFFS_IRP_CONTEXT IrpContext) +{ + PDEVICE_OBJECT DeviceObject; + NTSTATUS Status = STATUS_UNSUCCESSFUL; + PFFS_VCB Vcb = 0; + PIRP Irp; + PIO_STACK_LOCATION IoStackLocation; + FS_INFORMATION_CLASS FsInformationClass; + ULONG Length; + PVOID Buffer; + BOOLEAN VcbResourceAcquired = FALSE; + + PAGED_CODE(); + + _SEH2_TRY + { + ASSERT(IrpContext != NULL); + + ASSERT((IrpContext->Identifier.Type == FFSICX) && + (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); + + DeviceObject = IrpContext->DeviceObject; + + // + // This request is not allowed on the main device object + // + if (DeviceObject == FFSGlobal->DeviceObject) + { + Status = STATUS_INVALID_DEVICE_REQUEST; + _SEH2_LEAVE; + } + + Vcb = (PFFS_VCB)DeviceObject->DeviceExtension; + + ASSERT(Vcb != NULL); + + ASSERT((Vcb->Identifier.Type == FFSVCB) && + (Vcb->Identifier.Size == sizeof(FFS_VCB))); + + ASSERT(IsMounted(Vcb)); + + if (!ExAcquireResourceSharedLite( + &Vcb->MainResource, + IrpContext->IsSynchronous)) + { + Status = STATUS_PENDING; + _SEH2_LEAVE; + } + + VcbResourceAcquired = TRUE; + + Irp = IrpContext->Irp; + + IoStackLocation = IoGetCurrentIrpStackLocation(Irp); + + FsInformationClass = + IoStackLocation->Parameters.QueryVolume.FsInformationClass; + + Length = IoStackLocation->Parameters.QueryVolume.Length; + + Buffer = Irp->AssociatedIrp.SystemBuffer; + + RtlZeroMemory(Buffer, Length); + + switch (FsInformationClass) + { + case FileFsVolumeInformation: + { + PFILE_FS_VOLUME_INFORMATION FsVolInfo; + ULONG VolumeLabelLength; + ULONG RequiredLength; + + if (Length < sizeof(FILE_FS_VOLUME_INFORMATION)) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + _SEH2_LEAVE; + } + + FsVolInfo = (PFILE_FS_VOLUME_INFORMATION)Buffer; + + FsVolInfo->VolumeCreationTime.QuadPart = 0; + + FsVolInfo->VolumeSerialNumber = Vcb->Vpb->SerialNumber; + + VolumeLabelLength = Vcb->Vpb->VolumeLabelLength; + + FsVolInfo->VolumeLabelLength = VolumeLabelLength; + + // I don't know what this means + FsVolInfo->SupportsObjects = FALSE; + + RequiredLength = sizeof(FILE_FS_VOLUME_INFORMATION) + + VolumeLabelLength - sizeof(WCHAR); + + if (Length < RequiredLength) + { + Irp->IoStatus.Information = + sizeof(FILE_FS_VOLUME_INFORMATION); + Status = STATUS_BUFFER_OVERFLOW; + _SEH2_LEAVE; + } + + RtlCopyMemory(FsVolInfo->VolumeLabel, Vcb->Vpb->VolumeLabel, Vcb->Vpb->VolumeLabelLength); + + Irp->IoStatus.Information = RequiredLength; + Status = STATUS_SUCCESS; + _SEH2_LEAVE; + } + + case FileFsSizeInformation: + { + PFILE_FS_SIZE_INFORMATION FsSizeInfo; + + if (Length < sizeof(FILE_FS_SIZE_INFORMATION)) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + _SEH2_LEAVE; + } + + FsSizeInfo = (PFILE_FS_SIZE_INFORMATION)Buffer; + + { + if (FS_VERSION == 1) + { + FsSizeInfo->TotalAllocationUnits.QuadPart = + (Vcb->ffs_super_block->fs_old_size / 8); + + FsSizeInfo->AvailableAllocationUnits.QuadPart = + (Vcb->ffs_super_block->fs_old_cstotal.cs_nbfree / 8); + } + else + { + FsSizeInfo->TotalAllocationUnits.QuadPart = + (Vcb->ffs_super_block->fs_size / 8); + + FsSizeInfo->AvailableAllocationUnits.QuadPart = + (Vcb->ffs_super_block->fs_cstotal.cs_nbfree / 8); + } + } + + FsSizeInfo->SectorsPerAllocationUnit = + Vcb->BlockSize / Vcb->DiskGeometry.BytesPerSector; + + FsSizeInfo->BytesPerSector = + Vcb->DiskGeometry.BytesPerSector; + + Irp->IoStatus.Information = sizeof(FILE_FS_SIZE_INFORMATION); + Status = STATUS_SUCCESS; + _SEH2_LEAVE; + } + + case FileFsDeviceInformation: + { + PFILE_FS_DEVICE_INFORMATION FsDevInfo; + + if (Length < sizeof(FILE_FS_DEVICE_INFORMATION)) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + _SEH2_LEAVE; + } + + FsDevInfo = (PFILE_FS_DEVICE_INFORMATION)Buffer; + + FsDevInfo->DeviceType = + Vcb->TargetDeviceObject->DeviceType; + + FsDevInfo->Characteristics = + Vcb->TargetDeviceObject->Characteristics; + + if (FlagOn(Vcb->Flags, VCB_READ_ONLY)) + { + SetFlag(FsDevInfo->Characteristics, + FILE_READ_ONLY_DEVICE); + } + + Irp->IoStatus.Information = sizeof(FILE_FS_DEVICE_INFORMATION); + Status = STATUS_SUCCESS; + _SEH2_LEAVE; + } + + case FileFsAttributeInformation: + { + PFILE_FS_ATTRIBUTE_INFORMATION FsAttrInfo; + ULONG RequiredLength; + + if (Length < sizeof(FILE_FS_ATTRIBUTE_INFORMATION)) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + _SEH2_LEAVE; + } + + FsAttrInfo = + (PFILE_FS_ATTRIBUTE_INFORMATION)Buffer; + + FsAttrInfo->FileSystemAttributes = + FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES; + + FsAttrInfo->MaximumComponentNameLength = FFS_NAME_LEN; + + FsAttrInfo->FileSystemNameLength = 10; + + RequiredLength = sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + + 10 - sizeof(WCHAR); + + if (Length < RequiredLength) + { + Irp->IoStatus.Information = + sizeof(FILE_FS_ATTRIBUTE_INFORMATION); + Status = STATUS_BUFFER_OVERFLOW; + _SEH2_LEAVE; + } + + RtlCopyMemory( + FsAttrInfo->FileSystemName, + L"FFS\0", 8); + + Irp->IoStatus.Information = RequiredLength; + Status = STATUS_SUCCESS; + _SEH2_LEAVE; + } + +#if (_WIN32_WINNT >= 0x0500) + + case FileFsFullSizeInformation: + { + PFILE_FS_FULL_SIZE_INFORMATION PFFFSI; + + if (Length < sizeof(FILE_FS_FULL_SIZE_INFORMATION)) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + _SEH2_LEAVE; + } + + PFFFSI = (PFILE_FS_FULL_SIZE_INFORMATION)Buffer; + + /* + typedef struct _FILE_FS_FULL_SIZE_INFORMATION { + LARGE_INTEGER TotalAllocationUnits; + LARGE_INTEGER CallerAvailableAllocationUnits; + LARGE_INTEGER ActualAvailableAllocationUnits; + ULONG SectorsPerAllocationUnit; + ULONG BytesPerSector; + } FILE_FS_FULL_SIZE_INFORMATION, *PFILE_FS_FULL_SIZE_INFORMATION; + */ + + { + if (FS_VERSION == 1) + { + PFFFSI->TotalAllocationUnits.QuadPart = + (Vcb->ffs_super_block->fs_old_size / 8); + + PFFFSI->CallerAvailableAllocationUnits.QuadPart = + (Vcb->ffs_super_block->fs_old_cstotal.cs_nbfree / 8); + + PFFFSI->ActualAvailableAllocationUnits.QuadPart = + (Vcb->ffs_super_block->fs_old_cstotal.cs_nbfree / 8); + } + else + { + PFFFSI->TotalAllocationUnits.QuadPart = + (Vcb->ffs_super_block->fs_size / 8); + + PFFFSI->CallerAvailableAllocationUnits.QuadPart = + (Vcb->ffs_super_block->fs_cstotal.cs_nbfree / 8); + + PFFFSI->ActualAvailableAllocationUnits.QuadPart = + (Vcb->ffs_super_block->fs_cstotal.cs_nbfree / 8); + } + } + + PFFFSI->SectorsPerAllocationUnit = + Vcb->BlockSize / Vcb->DiskGeometry.BytesPerSector; + + PFFFSI->BytesPerSector = Vcb->DiskGeometry.BytesPerSector; + + Irp->IoStatus.Information = sizeof(FILE_FS_FULL_SIZE_INFORMATION); + Status = STATUS_SUCCESS; + _SEH2_LEAVE; + } + +#endif // (_WIN32_WINNT >= 0x0500) + + default: + Status = STATUS_INVALID_INFO_CLASS; + } + } + + _SEH2_FINALLY + { + if (VcbResourceAcquired) + { + ExReleaseResourceForThreadLite( + &Vcb->MainResource, + ExGetCurrentResourceThread()); + } + + if (!IrpContext->ExceptionInProgress) + { + if (Status == STATUS_PENDING) + { + FFSQueueRequest(IrpContext); + } + else + { + FFSCompleteIrpContext(IrpContext, Status); + } + } + } _SEH2_END; + + return Status; +} + +#if !FFS_READ_ONLY + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSSetVolumeInformation( + IN PFFS_IRP_CONTEXT IrpContext) +{ + PDEVICE_OBJECT DeviceObject; + NTSTATUS Status = STATUS_UNSUCCESSFUL; + PFFS_VCB Vcb; + PIRP Irp; + PIO_STACK_LOCATION IoStackLocation; + FS_INFORMATION_CLASS FsInformationClass; + + PAGED_CODE(); + + _SEH2_TRY + { + ASSERT(IrpContext != NULL); + + ASSERT((IrpContext->Identifier.Type == FFSICX) && + (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); + + DeviceObject = IrpContext->DeviceObject; + + // + // This request is not allowed on the main device object + // + if (DeviceObject == FFSGlobal->DeviceObject) + { + Status = STATUS_INVALID_DEVICE_REQUEST; + _SEH2_LEAVE; + } + + Vcb = (PFFS_VCB)DeviceObject->DeviceExtension; + + ASSERT(Vcb != NULL); + + ASSERT((Vcb->Identifier.Type == FFSVCB) && + (Vcb->Identifier.Size == sizeof(FFS_VCB))); + + ASSERT(IsMounted(Vcb)); + + if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY)) + { + Status = STATUS_MEDIA_WRITE_PROTECTED; + _SEH2_LEAVE; + } + + Irp = IrpContext->Irp; + + IoStackLocation = IoGetCurrentIrpStackLocation(Irp); + + //Notes: SetVolume is not defined in ntddk.h of win2k ddk, + // But it's same to QueryVolume .... + FsInformationClass = + IoStackLocation->Parameters./*SetVolume*/QueryVolume.FsInformationClass; + + switch (FsInformationClass) + { + case FileFsLabelInformation: + { + PFILE_FS_LABEL_INFORMATION VolLabelInfo = NULL; + ULONG VolLabelLen; + UNICODE_STRING LabelName ; + + OEM_STRING OemName; + + VolLabelInfo = (PFILE_FS_LABEL_INFORMATION)Irp->AssociatedIrp.SystemBuffer; + + VolLabelLen = VolLabelInfo->VolumeLabelLength; + + if(VolLabelLen > (16 * sizeof(WCHAR))) + { + Status = STATUS_INVALID_VOLUME_LABEL; + _SEH2_LEAVE; + } + + RtlCopyMemory(Vcb->Vpb->VolumeLabel, + VolLabelInfo->VolumeLabel, + VolLabelLen); + + RtlZeroMemory(Vcb->ffs_super_block->fs_volname, 16); + + LabelName.Buffer = VolLabelInfo->VolumeLabel; + LabelName.MaximumLength = (USHORT)16 * sizeof(WCHAR); + LabelName.Length = (USHORT)VolLabelLen; + + OemName.Buffer = SUPER_BLOCK->fs_volname; + OemName.Length = 0; + OemName.MaximumLength = 16; + + FFSUnicodeToOEM(&OemName, + &LabelName); + + Vcb->Vpb->VolumeLabelLength = + (USHORT)VolLabelLen; + + if (FFSSaveSuper(IrpContext, Vcb)) + { + Status = STATUS_SUCCESS; + } + + Irp->IoStatus.Information = 0; + + } + break; + + default: + Status = STATUS_INVALID_INFO_CLASS; + } + } + + _SEH2_FINALLY + { + + if (!IrpContext->ExceptionInProgress) + { + if (Status == STATUS_PENDING) + { + FFSQueueRequest(IrpContext); + } + else + { + FFSCompleteIrpContext(IrpContext, Status); + } + } + } _SEH2_END; + + return Status; + +} + +#endif // !FFS_READ_ONLY diff --git a/reactos/drivers/filesystems/ffs/src/write.c b/reactos/drivers/filesystems/ffs/src/write.c new file mode 100644 index 00000000000..24e04b79354 --- /dev/null +++ b/reactos/drivers/filesystems/ffs/src/write.c @@ -0,0 +1,1588 @@ +/* + * FFS File System Driver for Windows + * + * write.c + * + * 2004.5.6 ~ + * + * Lee Jae-Hong, http://www.pyrasis.com + * + * See License.txt + * + */ + +#include "ntifs.h" +#include "ffsdrv.h" + +#if !FFS_READ_ONLY + +/* Globals */ + +extern PFFS_GLOBAL FFSGlobal; + + +/* Definitions */ + +typedef struct _FFS_FLPFLUSH_CONTEXT { + + PFFS_VCB Vcb; + PFFS_FCB Fcb; + PFILE_OBJECT FileObject; + + KDPC Dpc; + KTIMER Timer; + WORK_QUEUE_ITEM Item; + +} FFS_FLPFLUSH_CONTEXT, *PFFS_FLPFLUSH_CONTEXT; + +#ifdef _PREFAST_ +WORKER_THREAD_ROUTINE __drv_mustHoldCriticalRegion FFSFloppyFlush; +#endif // _PREFAST_ + +__drv_mustHoldCriticalRegion +VOID +FFSFloppyFlush( + IN PVOID Parameter); + +#ifdef _PREFAST_ +KDEFERRED_ROUTINE FFSFloppyFlushDpc; +#endif // _PREFAST_ + +VOID +FFSFloppyFlushDpc( + IN PKDPC Dpc, + IN PVOID DeferredContext, + IN PVOID SystemArgument1, + IN PVOID SystemArgument2); + + + +NTSTATUS +FFSWriteComplete( + IN PFFS_IRP_CONTEXT IrpContext); + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSWriteFile( + IN PFFS_IRP_CONTEXT IrpContext); + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSWriteVolume( + IN PFFS_IRP_CONTEXT IrpContext); + +VOID +FFSDeferWrite( + IN PFFS_IRP_CONTEXT, + PIRP Irp); + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE, FFSFloppyFlush) +#pragma alloc_text(PAGE, FFSStartFloppyFlushDpc) +#pragma alloc_text(PAGE, FFSZeroHoles) +#pragma alloc_text(PAGE, FFSWrite) +#pragma alloc_text(PAGE, FFSWriteVolume) +#pragma alloc_text(PAGE, FFSv1WriteInode) +#pragma alloc_text(PAGE, FFSWriteFile) +#pragma alloc_text(PAGE, FFSWriteComplete) +#endif + + +__drv_mustHoldCriticalRegion +VOID +FFSFloppyFlush( + IN PVOID Parameter) +{ + PFFS_FLPFLUSH_CONTEXT Context; + PFILE_OBJECT FileObject; + PFFS_FCB Fcb; + PFFS_VCB Vcb; + + PAGED_CODE(); + + Context = (PFFS_FLPFLUSH_CONTEXT) Parameter; + FileObject = Context->FileObject; + Fcb = Context->Fcb; + Vcb = Context->Vcb; + + FFSPrint((DBG_USER, "FFSFloppyFlushing ...\n")); + + IoSetTopLevelIrp((PIRP)FSRTL_FSP_TOP_LEVEL_IRP); + + if (Vcb) + { + ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE); + ExReleaseResourceLite(&Vcb->PagingIoResource); + + CcFlushCache(&(Vcb->SectionObject), NULL, 0, NULL); + } + + if (FileObject) + { + ASSERT(Fcb == (PFFS_FCB)FileObject->FsContext); + + ExAcquireSharedStarveExclusive(&Fcb->PagingIoResource, TRUE); + ExReleaseResourceLite(&Fcb->PagingIoResource); + + CcFlushCache(&(Fcb->SectionObject), NULL, 0, NULL); + + ObDereferenceObject(FileObject); + } + + IoSetTopLevelIrp(NULL); + + ExFreePool(Parameter); +} + + +VOID +FFSFloppyFlushDpc( + IN PKDPC Dpc, + IN PVOID DeferredContext, + IN PVOID SystemArgument1, + IN PVOID SystemArgument2) +{ + PFFS_FLPFLUSH_CONTEXT Context; + + Context = (PFFS_FLPFLUSH_CONTEXT)DeferredContext; + + FFSPrint((DBG_USER, "FFSFloppyFlushDpc is to be started...\n")); + + ExInitializeWorkItem(&Context->Item, + FFSFloppyFlush, + Context); + + ExQueueWorkItem(&Context->Item, CriticalWorkQueue); +} + + +VOID +FFSStartFloppyFlushDpc( + PFFS_VCB Vcb, + PFFS_FCB Fcb, + PFILE_OBJECT FileObject) +{ + LARGE_INTEGER OneSecond; + PFFS_FLPFLUSH_CONTEXT Context; + + PAGED_CODE(); + + ASSERT(IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK)); + + Context = ExAllocatePoolWithTag(NonPagedPool, sizeof(PFFS_FLPFLUSH_CONTEXT), FFS_POOL_TAG); + + if (!Context) + { + FFSBreakPoint(); + return; + } + + KeInitializeTimer(&Context->Timer); + + KeInitializeDpc(&Context->Dpc, + FFSFloppyFlushDpc, + Context); + + Context->Vcb = Vcb; + Context->Fcb = Fcb; + Context->FileObject = FileObject; + + if (FileObject) + { + ObReferenceObject(FileObject); + } + + OneSecond.QuadPart = (LONGLONG) - 1 * 1000 * 1000 * 10; + KeSetTimer(&Context->Timer, + OneSecond, + &Context->Dpc); +} + + +BOOLEAN +FFSZeroHoles( + IN PFFS_IRP_CONTEXT IrpContext, + IN PFFS_VCB Vcb, + IN PFILE_OBJECT FileObject, + IN LONGLONG Offset, + IN LONGLONG Count) +{ + LARGE_INTEGER StartAddr = {0, 0}; + LARGE_INTEGER EndAddr = {0, 0}; + + PAGED_CODE(); + + StartAddr.QuadPart = (Offset + (SECTOR_SIZE - 1)) & + ~((LONGLONG)SECTOR_SIZE - 1); + + EndAddr.QuadPart = (Offset + Count + (SECTOR_SIZE - 1)) & + ~((LONGLONG)SECTOR_SIZE - 1); + + if (StartAddr.QuadPart < EndAddr.QuadPart) + { + return CcZeroData(FileObject, + &StartAddr, + &EndAddr, + IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)); + } + + return TRUE; +} + + +VOID +FFSDeferWrite( + IN PFFS_IRP_CONTEXT IrpContext, + PIRP Irp) +{ + ASSERT(IrpContext->Irp == Irp); + + FFSQueueRequest(IrpContext); +} + + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSWriteVolume( + IN PFFS_IRP_CONTEXT IrpContext) +{ + NTSTATUS Status = STATUS_UNSUCCESSFUL; + + PFFS_VCB Vcb; + PFFS_CCB Ccb; + PFFS_FCBVCB FcbOrVcb; + PFILE_OBJECT FileObject; + + PDEVICE_OBJECT DeviceObject; + + PIRP Irp; + PIO_STACK_LOCATION IoStackLocation; + + ULONG Length; + LARGE_INTEGER ByteOffset; + + BOOLEAN PagingIo; + BOOLEAN Nocache; + BOOLEAN SynchronousIo; + BOOLEAN MainResourceAcquired = FALSE; + BOOLEAN PagingIoResourceAcquired = FALSE; + + BOOLEAN bDeferred = FALSE; + + PUCHAR Buffer; + + PAGED_CODE(); + + _SEH2_TRY + { + ASSERT(IrpContext); + + ASSERT((IrpContext->Identifier.Type == FFSICX) && + (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); + + DeviceObject = IrpContext->DeviceObject; + + Vcb = (PFFS_VCB)DeviceObject->DeviceExtension; + + ASSERT(Vcb != NULL); + + ASSERT((Vcb->Identifier.Type == FFSVCB) && + (Vcb->Identifier.Size == sizeof(FFS_VCB))); + + FileObject = IrpContext->FileObject; + + FcbOrVcb = (PFFS_FCBVCB)FileObject->FsContext; + + ASSERT(FcbOrVcb); + + if (!(FcbOrVcb->Identifier.Type == FFSVCB && (PVOID)FcbOrVcb == (PVOID)Vcb)) + { + Status = STATUS_INVALID_DEVICE_REQUEST; + _SEH2_LEAVE; + } + + Ccb = (PFFS_CCB)FileObject->FsContext2; + + Irp = IrpContext->Irp; + + IoStackLocation = IoGetCurrentIrpStackLocation(Irp); + + Length = IoStackLocation->Parameters.Write.Length; + ByteOffset = IoStackLocation->Parameters.Write.ByteOffset; + + PagingIo = (Irp->Flags & IRP_PAGING_IO ? TRUE : FALSE); + Nocache = (Irp->Flags & IRP_NOCACHE ? TRUE : FALSE); + SynchronousIo = (FileObject->Flags & FO_SYNCHRONOUS_IO ? TRUE : FALSE); + + FFSPrint((DBG_INFO, "FFSWriteVolume: Off=%I64xh Len=%xh Paging=%xh Nocache=%xh\n", + ByteOffset.QuadPart, Length, PagingIo, Nocache)); + + if (Length == 0) + { + Irp->IoStatus.Information = 0; + Status = STATUS_SUCCESS; + _SEH2_LEAVE; + } + + // For the case of "Direct Access Storage Device", we + // need flush/purge the cache + + if (Ccb != NULL) + { + ExAcquireResourceExclusiveLite(&Vcb->MainResource, TRUE); + MainResourceAcquired = TRUE; + + Status = FFSPurgeVolume(Vcb, TRUE); + + ExReleaseResourceLite(&Vcb->MainResource); + MainResourceAcquired = FALSE; + + if(!IsFlagOn(Ccb->Flags, CCB_ALLOW_EXTENDED_DASD_IO)) + { + if (ByteOffset.QuadPart + Length > Vcb->Header.FileSize.QuadPart) + { + Length = (ULONG)(Vcb->Header.FileSize.QuadPart - ByteOffset.QuadPart); + } + } + + { + FFS_BDL BlockArray; + + if ((ByteOffset.LowPart & (SECTOR_SIZE - 1)) || + (Length & (SECTOR_SIZE - 1))) + { + Status = STATUS_INVALID_PARAMETER; + _SEH2_LEAVE; + } + + Status = FFSLockUserBuffer( + IrpContext->Irp, + Length, + IoReadAccess); + + if (!NT_SUCCESS(Status)) + { + _SEH2_LEAVE; + } + + BlockArray.Irp = NULL; + BlockArray.Lba = ByteOffset.QuadPart;; + BlockArray.Offset = 0; + BlockArray.Length = Length; + + Status = FFSReadWriteBlocks(IrpContext, + Vcb, + &BlockArray, + Length, + 1, + FALSE); + Irp = IrpContext->Irp; + + _SEH2_LEAVE; + } + } + + if (Nocache && + (ByteOffset.LowPart & (SECTOR_SIZE - 1) || + Length & (SECTOR_SIZE - 1))) + { + Status = STATUS_INVALID_PARAMETER; + _SEH2_LEAVE; + } + + if (FlagOn(IrpContext->MinorFunction, IRP_MN_DPC)) + { + ClearFlag(IrpContext->MinorFunction, IRP_MN_DPC); + Status = STATUS_PENDING; + _SEH2_LEAVE; + } + + if (ByteOffset.QuadPart >= + Vcb->PartitionInformation.PartitionLength.QuadPart) + { + Irp->IoStatus.Information = 0; + Status = STATUS_END_OF_FILE; + _SEH2_LEAVE; + } + +#if FALSE + + if (!Nocache) + { + BOOLEAN bAgain = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED); + BOOLEAN bWait = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); + BOOLEAN bQueue = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED); + + if (!CcCanIWrite( + FileObject, + Length, + (bWait && bQueue), + bAgain)) + { + SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED); + + CcDeferWrite(FileObject, + (PCC_POST_DEFERRED_WRITE)FFSDeferWrite, + IrpContext, + Irp, + Length, + bAgain); + + bDeferred = TRUE; + + FFSBreakPoint(); + + Status = STATUS_PENDING; + + _SEH2_LEAVE; + } + } + +#endif + + if (Nocache && !PagingIo && (Vcb->SectionObject.DataSectionObject != NULL)) + { + ExAcquireResourceExclusiveLite(&Vcb->MainResource, TRUE); + MainResourceAcquired = TRUE; + + ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE); + ExReleaseResourceLite(&Vcb->PagingIoResource); + + CcFlushCache(&(Vcb->SectionObject), + &ByteOffset, + Length, + &(Irp->IoStatus)); + + if (!NT_SUCCESS(Irp->IoStatus.Status)) + { + Status = Irp->IoStatus.Status; + _SEH2_LEAVE; + } + + ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE); + ExReleaseResourceLite(&Vcb->PagingIoResource); + + CcPurgeCacheSection(&(Vcb->SectionObject), + (PLARGE_INTEGER)&(ByteOffset), + Length, + FALSE); + + ExReleaseResourceLite(&Vcb->MainResource); + MainResourceAcquired = FALSE; + } + + if (!PagingIo) + { +#pragma prefast( suppress: 28137, "by design" ) + if (!ExAcquireResourceExclusiveLite( + &Vcb->MainResource, + IrpContext->IsSynchronous)) + { + Status = STATUS_PENDING; + _SEH2_LEAVE; + } + + MainResourceAcquired = TRUE; + } + else + { + /* + ULONG ResShCnt, ResExCnt; + ResShCnt = ExIsResourceAcquiredSharedLite(&Vcb->PagingIoResource); + ResExCnt = ExIsResourceAcquiredExclusiveLite(&Vcb->PagingIoResource); + + FFSPrint((DBG_USER, "PagingIoRes: %xh:%xh Synchronous=%xh\n", ResShCnt, ResExCnt, IrpContext->IsSynchronous)); + */ + + if (Ccb) + { + if (!ExAcquireResourceSharedLite( + &Vcb->PagingIoResource, + IrpContext->IsSynchronous)) + { + Status = STATUS_PENDING; + _SEH2_LEAVE; + } + + PagingIoResourceAcquired = TRUE; + } + } + + if (!Nocache) + { + if ((ByteOffset.QuadPart + Length) > + Vcb->PartitionInformation.PartitionLength.QuadPart + ) + { + Length = (ULONG) ( + Vcb->PartitionInformation.PartitionLength.QuadPart - + ByteOffset.QuadPart); + + Length &= ~((ULONG)SECTOR_SIZE - 1); + } + + if (FlagOn(IrpContext->MinorFunction, IRP_MN_MDL)) + { + + CcPrepareMdlWrite( + Vcb->StreamObj, + &ByteOffset, + Length, + &Irp->MdlAddress, + &Irp->IoStatus); + + Status = Irp->IoStatus.Status; + } + else + { + Buffer = FFSGetUserBuffer(Irp); + + if (Buffer == NULL) + { + FFSBreakPoint(); + + Status = STATUS_INVALID_USER_BUFFER; + _SEH2_LEAVE; + } + + if (!CcCopyWrite(Vcb->StreamObj, + (PLARGE_INTEGER)(&ByteOffset), + Length, + TRUE, + Buffer)) + { + Status = STATUS_PENDING; + _SEH2_LEAVE; + } + + Status = Irp->IoStatus.Status; + FFSAddMcbEntry(Vcb, ByteOffset.QuadPart, (LONGLONG)Length); + } + + if (NT_SUCCESS(Status)) + { + Irp->IoStatus.Information = Length; + } + } + else + { + PFFS_BDL ffs_bdl = NULL; + ULONG Blocks = 0; + + LONGLONG DirtyStart; + LONGLONG DirtyLba; + LONGLONG DirtyLength; + LONGLONG RemainLength; + + if ((ByteOffset.QuadPart + Length) > + Vcb->PartitionInformation.PartitionLength.QuadPart) + { + Length = (ULONG)( + Vcb->PartitionInformation.PartitionLength.QuadPart - + ByteOffset.QuadPart); + + Length &= ~((ULONG)SECTOR_SIZE - 1); + } + + Status = FFSLockUserBuffer( + IrpContext->Irp, + Length, + IoReadAccess); + + if (!NT_SUCCESS(Status)) + { + _SEH2_LEAVE; + } + + ffs_bdl = ExAllocatePoolWithTag(PagedPool, + (Length / Vcb->BlockSize) * + sizeof(FFS_BDL), FFS_POOL_TAG); + + if (!ffs_bdl) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + _SEH2_LEAVE; + } + + DirtyLba = ByteOffset.QuadPart; + RemainLength = (LONGLONG)Length; + + while (RemainLength > 0) + { + DirtyStart = DirtyLba; + + if (FFSLookupMcbEntry(Vcb, + DirtyStart, + &DirtyLba, + &DirtyLength, + (PLONGLONG)NULL, + (PLONGLONG)NULL, + (PULONG)NULL)) + { + + if (DirtyLba == -1) + { + DirtyLba = DirtyStart + DirtyLength; + + RemainLength = ByteOffset.QuadPart + + (LONGLONG)Length - + DirtyLba; + continue; + } + + ffs_bdl[Blocks].Irp = NULL; + ffs_bdl[Blocks].Lba = DirtyLba; + ffs_bdl[Blocks].Offset = (ULONG)((LONGLONG)Length + + DirtyStart - + RemainLength - + DirtyLba); + + if (DirtyLba + DirtyLength > DirtyStart + RemainLength) + { + ffs_bdl[Blocks].Length = (ULONG)(DirtyStart + + RemainLength - + DirtyLba); + RemainLength = 0; + } + else + { + ffs_bdl[Blocks].Length = (ULONG)DirtyLength; + RemainLength = (DirtyStart + RemainLength) - + (DirtyLba + DirtyLength); + } + + DirtyLba = DirtyStart + DirtyLength; + Blocks++; + } + else + { + if (Blocks == 0) + { + if (ffs_bdl) + ExFreePool(ffs_bdl); + + // + // Lookup fails at the first time, ie. + // no dirty blocks in the run + // + + FFSBreakPoint(); + + if (RemainLength == (LONGLONG)Length) + Status = STATUS_SUCCESS; + else + Status = STATUS_UNSUCCESSFUL; + + _SEH2_LEAVE; + } + else + { + break; + } + } + } + + if (Blocks > 0) + { + Status = FFSReadWriteBlocks(IrpContext, + Vcb, + ffs_bdl, + Length, + Blocks, + FALSE); + Irp = IrpContext->Irp; + + if (NT_SUCCESS(Status)) + { + ULONG i; + + for (i = 0; i < Blocks; i++) + { + FFSRemoveMcbEntry(Vcb, + ffs_bdl[i].Lba, + ffs_bdl[i].Length); + } + } + + if (ffs_bdl) + ExFreePool(ffs_bdl); + + if (!Irp) + _SEH2_LEAVE; + + } + else + { + if (ffs_bdl) + ExFreePool(ffs_bdl); + + Irp->IoStatus.Information = Length; + + Status = STATUS_SUCCESS; + _SEH2_LEAVE; + } + } + } + + _SEH2_FINALLY + { + if (PagingIoResourceAcquired) + { + ExReleaseResourceForThreadLite( + &Vcb->PagingIoResource, + ExGetCurrentResourceThread()); + } + + if (MainResourceAcquired) + { + ExReleaseResourceForThreadLite( + &Vcb->MainResource, + ExGetCurrentResourceThread()); + } + + if (!IrpContext->ExceptionInProgress) + { + if (Irp) + { + if (Status == STATUS_PENDING) + { + if(!bDeferred) + { + Status = FFSLockUserBuffer( + IrpContext->Irp, + Length, + IoReadAccess); + + if (NT_SUCCESS(Status)) + { + Status = FFSQueueRequest(IrpContext); + } + else + { + FFSCompleteIrpContext(IrpContext, Status); + } + } + } + else + { + if (NT_SUCCESS(Status)) + { + if (SynchronousIo && !PagingIo) + { + FileObject->CurrentByteOffset.QuadPart = + ByteOffset.QuadPart + Irp->IoStatus.Information; + } + + if (!PagingIo) + { + SetFlag(FileObject->Flags, FO_FILE_MODIFIED); + } + } + + FFSCompleteIrpContext(IrpContext, Status); + } + } + else + { + FFSFreeIrpContext(IrpContext); + } + } + } _SEH2_END; + + return Status; +} + + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSv1WriteInode( + IN PFFS_IRP_CONTEXT IrpContext, + IN PFFS_VCB Vcb, + IN PFFSv1_INODE dinode1, + IN ULONGLONG offset, + IN PVOID Buffer, + IN ULONG size, + IN BOOLEAN bWriteToDisk, + OUT PULONG dwRet) +{ + PFFS_BDL ffs_bdl = NULL; + ULONG blocks, i; + NTSTATUS Status = STATUS_UNSUCCESSFUL; + ULONG Totalblocks; + LONGLONG AllocSize; + + PAGED_CODE(); + + if (dwRet) + { + *dwRet = 0; + } + + Totalblocks = (dinode1->di_blocks); + AllocSize = ((LONGLONG)(FFSDataBlocks(Vcb, Totalblocks)) << BLOCK_BITS); + + if ((LONGLONG)offset >= AllocSize) + { + FFSPrint((DBG_ERROR, "FFSv1WriteInode: beyond the file range.\n")); + return STATUS_SUCCESS; + } + + if ((LONGLONG)offset + size > AllocSize) + { + size = (ULONG)(AllocSize - offset); + } + + blocks = FFSv1BuildBDL(IrpContext, Vcb, dinode1, offset, size, &ffs_bdl); + + if (blocks <= 0) + { + return STATUS_SUCCESS; + } + +#if DBG + { + ULONG dwTotal = 0; + FFSPrint((DBG_INFO, "FFSv1WriteInode: BDLCount = %xh Size=%xh Off=%xh\n", + blocks, size, offset)); + for(i = 0; i < blocks; i++) + { + FFSPrint((DBG_INFO, "FFSv1WriteInode: Lba=%I64xh Len=%xh Off=%xh\n", + ffs_bdl[i].Lba, ffs_bdl[i].Length, ffs_bdl[i].Offset)); + dwTotal += ffs_bdl[i].Length; + } + + if (dwTotal != size) + { + FFSBreakPoint(); + } + + FFSPrint((DBG_INFO, "FFSv1WriteInode: Total = %xh (WriteToDisk=%x)\n", + dwTotal, bWriteToDisk)); + } +#endif + + if (bWriteToDisk) + { + +#if 0 + for(i = 0; i < blocks; i++) + { + { + CcFlushCache(&(Vcb->SectionObject), + (PLARGE_INTEGER)&(ffs_bdl[i].Lba), + ffs_bdl[i].Length, + NULL); + + if (Vcb->SectionObject.DataSectionObject != NULL) + { + ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE); + ExReleaseResourceLite(&Vcb->PagingIoResource); + + CcPurgeCacheSection(&(Vcb->SectionObject), + (PLARGE_INTEGER)&(ffs_bdl[i].Lba), + ffs_bdl[i].Length, + FALSE); + } + } + } +#endif + + // assume offset is aligned. + Status = FFSReadWriteBlocks(IrpContext, Vcb, ffs_bdl, size, blocks, FALSE); + } + else + { + for(i = 0; i < blocks; i++) + { + if(!FFSSaveBuffer(IrpContext, Vcb, ffs_bdl[i].Lba, ffs_bdl[i].Length, (PVOID)((PUCHAR)Buffer + ffs_bdl[i].Offset))) + goto errorout; + } + + if (IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK)) + { + FFSPrint((DBG_USER, "FFSv1WriteInode is starting FlushingDpc...\n")); + FFSStartFloppyFlushDpc(Vcb, NULL, NULL); + } + + Status = STATUS_SUCCESS; + } + +errorout: + + if (ffs_bdl) + ExFreePool(ffs_bdl); + + if (NT_SUCCESS(Status)) + { + if (dwRet) *dwRet = size; + } + + return Status; +} + + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSv2WriteInode( + IN PFFS_IRP_CONTEXT IrpContext, + IN PFFS_VCB Vcb, + IN PFFSv2_INODE dinode2, + IN ULONGLONG offset, + IN PVOID Buffer, + IN ULONG size, + IN BOOLEAN bWriteToDisk, + OUT PULONG dwRet) +{ + return STATUS_UNSUCCESSFUL; +} + + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSWriteFile( + IN PFFS_IRP_CONTEXT IrpContext) +{ + NTSTATUS Status = STATUS_UNSUCCESSFUL; + + PFFS_VCB Vcb; + PFFS_FCB Fcb; + PFFS_CCB Ccb; + PFILE_OBJECT FileObject; + PFILE_OBJECT CacheObject; + + PDEVICE_OBJECT DeviceObject; + + PIRP Irp; + PIO_STACK_LOCATION IoStackLocation; + + ULONG Length; + ULONG ReturnedLength; + LARGE_INTEGER ByteOffset; + + BOOLEAN PagingIo; + BOOLEAN Nocache; + BOOLEAN SynchronousIo; + BOOLEAN MainResourceAcquired = FALSE; + BOOLEAN PagingIoResourceAcquired = FALSE; + + BOOLEAN bNeedExtending = FALSE; + BOOLEAN bAppendFile = FALSE; + + BOOLEAN bDeferred = FALSE; + + PUCHAR Buffer; + + PAGED_CODE(); + + _SEH2_TRY + { + ASSERT(IrpContext); + + ASSERT((IrpContext->Identifier.Type == FFSICX) && + (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); + + DeviceObject = IrpContext->DeviceObject; + + Vcb = (PFFS_VCB)DeviceObject->DeviceExtension; + + ASSERT(Vcb != NULL); + + ASSERT((Vcb->Identifier.Type == FFSVCB) && + (Vcb->Identifier.Size == sizeof(FFS_VCB))); + + FileObject = IrpContext->FileObject; + + Fcb = (PFFS_FCB)FileObject->FsContext; + + ASSERT(Fcb); + + ASSERT((Fcb->Identifier.Type == FFSFCB) && + (Fcb->Identifier.Size == sizeof(FFS_FCB))); + + Ccb = (PFFS_CCB)FileObject->FsContext2; + + Irp = IrpContext->Irp; + + IoStackLocation = IoGetCurrentIrpStackLocation(Irp); + + Length = IoStackLocation->Parameters.Write.Length; + ByteOffset = IoStackLocation->Parameters.Write.ByteOffset; + + PagingIo = (Irp->Flags & IRP_PAGING_IO ? TRUE : FALSE); + Nocache = (Irp->Flags & IRP_NOCACHE ? TRUE : FALSE); + SynchronousIo = (FileObject->Flags & FO_SYNCHRONOUS_IO ? TRUE : FALSE); + + FFSPrint((DBG_INFO, "FFSWriteFile: Off=%I64xh Len=%xh Paging=%xh Nocache=%xh\n", + ByteOffset.QuadPart, Length, PagingIo, Nocache)); + + /* + if (IsFlagOn(Fcb->Flags, FCB_FILE_DELETED)) + { + Status = STATUS_FILE_DELETED; + _SEH2_LEAVE; + } + + if (IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING)) + { + Status = STATUS_DELETE_PENDING; + _SEH2_LEAVE; + } + */ + + if (Length == 0) + { + Irp->IoStatus.Information = 0; + Status = STATUS_SUCCESS; + _SEH2_LEAVE; + } + + if (Nocache && + (ByteOffset.LowPart & (SECTOR_SIZE - 1) || + Length & (SECTOR_SIZE - 1))) + { + Status = STATUS_INVALID_PARAMETER; + _SEH2_LEAVE; + } + + if (FlagOn(IrpContext->MinorFunction, IRP_MN_DPC)) + { + ClearFlag(IrpContext->MinorFunction, IRP_MN_DPC); + Status = STATUS_PENDING; + _SEH2_LEAVE; + } + +#if FALSE + if (!Nocache) + { + BOOLEAN bAgain = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED); + BOOLEAN bWait = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); + BOOLEAN bQueue = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED); + + if (!CcCanIWrite( + FileObject, + Length, + (bWait && bQueue), + bAgain)) + { + SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED); + + CcDeferWrite(FileObject, + (PCC_POST_DEFERRED_WRITE)FFSDeferWrite, + IrpContext, + Irp, + Length, + bAgain); + + bDeferred = TRUE; + + FFSBreakPoint(); + + Status = STATUS_PENDING; + _SEH2_LEAVE; + } + } + +#endif + + if (IsEndOfFile(ByteOffset)) + { + bAppendFile = TRUE; + ByteOffset.QuadPart = Fcb->Header.FileSize.QuadPart; + } + + if (FlagOn(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY) && !PagingIo) + { + Status = STATUS_INVALID_DEVICE_REQUEST; + _SEH2_LEAVE; + } + + // + // Do flushing for such cases + // + if (Nocache && !PagingIo && (Fcb->SectionObject.DataSectionObject != NULL)) + { +#pragma prefast( suppress: 28137, "by design" ) + ExAcquireResourceExclusiveLite(&Fcb->MainResource, + IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)); + + MainResourceAcquired = TRUE; + + ExAcquireSharedStarveExclusive(&Fcb->PagingIoResource, TRUE); + ExReleaseResourceLite(&Fcb->PagingIoResource); + + CcFlushCache(&(Fcb->SectionObject), + &ByteOffset, + Length, + &(Irp->IoStatus)); + ClearFlag(Fcb->Flags, FCB_FILE_MODIFIED); + + if (!NT_SUCCESS(Irp->IoStatus.Status)) + { + Status = Irp->IoStatus.Status; + _SEH2_LEAVE; + } + + ExAcquireSharedStarveExclusive(&Fcb->PagingIoResource, TRUE); + ExReleaseResourceLite(&Fcb->PagingIoResource); + + CcPurgeCacheSection(&(Fcb->SectionObject), + (PLARGE_INTEGER)&(ByteOffset), + Length, + FALSE); + + ExReleaseResourceLite(&Fcb->MainResource); + MainResourceAcquired = FALSE; + } + + if (!PagingIo) + { +#pragma prefast( suppress: 28137, "by design" ) + if (!ExAcquireResourceExclusiveLite( + &Fcb->MainResource, + IrpContext->IsSynchronous)) + { + Status = STATUS_PENDING; + _SEH2_LEAVE; + } + + MainResourceAcquired = TRUE; + } + else + { + /* + ULONG ResShCnt, ResExCnt; + ResShCnt = ExIsResourceAcquiredSharedLite(&Fcb->PagingIoResource); + ResExCnt = ExIsResourceAcquiredExclusiveLite(&Fcb->PagingIoResource); + + FFSPrint((DBG_USER, "FFSWriteFile: Inode=%xh %S PagingIo: %xh:%xh Synchronous=%xh\n", + Fcb->FFSMcb->Inode, Fcb->FFSMcb->ShortName.Buffer, ResShCnt, ResExCnt, IrpContext->IsSynchronous)); + */ + if (!ExAcquireResourceSharedLite( + &Fcb->PagingIoResource, + IrpContext->IsSynchronous)) + { + Status = STATUS_PENDING; + _SEH2_LEAVE; + } + + PagingIoResourceAcquired = TRUE; + } + + if (!PagingIo) + { + if (!FsRtlCheckLockForWriteAccess( + &Fcb->FileLockAnchor, + Irp)) + { + Status = STATUS_FILE_LOCK_CONFLICT; + _SEH2_LEAVE; + } + } + + if (Nocache) + { + if ((ByteOffset.QuadPart + Length) > + Fcb->Header.AllocationSize.QuadPart) + { + if (ByteOffset.QuadPart >= + Fcb->Header.AllocationSize.QuadPart) + { + Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + _SEH2_LEAVE; + } + else + { + if (Length > (ULONG)(Fcb->Header.AllocationSize.QuadPart + - ByteOffset.QuadPart)) + { + Length = (ULONG)(Fcb->Header.AllocationSize.QuadPart + - ByteOffset.QuadPart); + } + } + } + } + + if (!Nocache) + { + if (FlagOn(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY)) + { + _SEH2_LEAVE; + } + + if (FileObject->PrivateCacheMap == NULL) + { + CcInitializeCacheMap( + FileObject, + (PCC_FILE_SIZES)(&Fcb->Header.AllocationSize), + FALSE, + &FFSGlobal->CacheManagerCallbacks, + Fcb); + + CcSetReadAheadGranularity( + FileObject, + READ_AHEAD_GRANULARITY); + + CcSetFileSizes( + FileObject, + (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize))); + } + + CacheObject = FileObject; + + // + // Need extending the size of inode ? + // + if ((bAppendFile) || ((ULONG)(ByteOffset.QuadPart + Length) > + (ULONG)(Fcb->Header.FileSize.QuadPart))) + { + + LARGE_INTEGER ExtendSize; + LARGE_INTEGER FileSize; + + bNeedExtending = TRUE; + FileSize = Fcb->Header.FileSize; + ExtendSize.QuadPart = (LONGLONG)(ByteOffset.QuadPart + Length); + + if (ExtendSize.QuadPart > Fcb->Header.AllocationSize.QuadPart) + { + if (!FFSExpandFile(IrpContext, Vcb, Fcb, &ExtendSize)) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + _SEH2_LEAVE; + } + } + + { + Fcb->Header.FileSize.QuadPart = ExtendSize.QuadPart; + Fcb->dinode1->di_size = (ULONG)ExtendSize.QuadPart; + } + + if (FileObject->PrivateCacheMap) + { + CcSetFileSizes(FileObject, (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize))); + + if (ByteOffset.QuadPart > FileSize.QuadPart) + { + FFSZeroHoles(IrpContext, Vcb, FileObject, FileSize.QuadPart, + ByteOffset.QuadPart - FileSize.QuadPart); + } + + if (Fcb->Header.AllocationSize.QuadPart > ExtendSize.QuadPart) + { + FFSZeroHoles(IrpContext, Vcb, FileObject, ExtendSize.QuadPart, + Fcb->Header.AllocationSize.QuadPart - ExtendSize.QuadPart); + } + } + + if (FFSv1SaveInode(IrpContext, Vcb, Fcb->FFSMcb->Inode, Fcb->dinode1)) + { + Status = STATUS_SUCCESS; + } + + FFSNotifyReportChange( + IrpContext, + Vcb, + Fcb, + FILE_NOTIFY_CHANGE_SIZE, + FILE_ACTION_MODIFIED); + } + + if (FlagOn(IrpContext->MinorFunction, IRP_MN_MDL)) + { + CcPrepareMdlWrite( + CacheObject, + (&ByteOffset), + Length, + &Irp->MdlAddress, + &Irp->IoStatus); + + Status = Irp->IoStatus.Status; + } + else + { + Buffer = FFSGetUserBuffer(Irp); + + if (Buffer == NULL) + { + FFSBreakPoint(); + Status = STATUS_INVALID_USER_BUFFER; + _SEH2_LEAVE; + } + + if (!CcCopyWrite( + CacheObject, + (PLARGE_INTEGER)&ByteOffset, + Length, + IrpContext->IsSynchronous, + Buffer)) + { + Status = STATUS_PENDING; + _SEH2_LEAVE; + } + + Status = Irp->IoStatus.Status; + } + + if (NT_SUCCESS(Status)) + { + Irp->IoStatus.Information = Length; + + if (IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK)) + { + FFSPrint((DBG_USER, "FFSWriteFile is starting FlushingDpc...\n")); + FFSStartFloppyFlushDpc(Vcb, Fcb, FileObject); + } + } + } + else + { + ReturnedLength = Length; + + Status = FFSLockUserBuffer( + IrpContext->Irp, + Length, + IoReadAccess); + + if (!NT_SUCCESS(Status)) + { + _SEH2_LEAVE; + } + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = Length; + + Status = + FFSv1WriteInode( + IrpContext, + Vcb, + Fcb->dinode1, + (ULONGLONG)(ByteOffset.QuadPart), + NULL, + Length, + TRUE, + &ReturnedLength); + + Irp = IrpContext->Irp; + + } + } + + _SEH2_FINALLY + { + if (PagingIoResourceAcquired) + { + ExReleaseResourceForThreadLite( + &Fcb->PagingIoResource, + ExGetCurrentResourceThread()); + } + + if (MainResourceAcquired) + { + ExReleaseResourceForThreadLite( + &Fcb->MainResource, + ExGetCurrentResourceThread()); + } + + if (!IrpContext->ExceptionInProgress) + { + if (Irp) + { + if (Status == STATUS_PENDING) + { + if (!bDeferred) + { + Status = FFSLockUserBuffer( + IrpContext->Irp, + Length, + IoReadAccess); + + if (NT_SUCCESS(Status)) + { + Status = FFSQueueRequest(IrpContext); + } + else + { + FFSCompleteIrpContext(IrpContext, Status); + } + } + } + else + { + if (NT_SUCCESS(Status)) + { + if (SynchronousIo && !PagingIo) + { + FileObject->CurrentByteOffset.QuadPart = + ByteOffset.QuadPart + Irp->IoStatus.Information; + } + + if (!PagingIo) + { + SetFlag(FileObject->Flags, FO_FILE_MODIFIED); + SetFlag(Fcb->Flags, FCB_FILE_MODIFIED); + } + } + + FFSCompleteIrpContext(IrpContext, Status); + } + } + else + { + FFSFreeIrpContext(IrpContext); + } + } + } _SEH2_END; + + return Status; + +} + + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSWriteComplete( + IN PFFS_IRP_CONTEXT IrpContext) +{ + NTSTATUS Status = STATUS_UNSUCCESSFUL; + PFILE_OBJECT FileObject; + PIRP Irp; + PIO_STACK_LOCATION IrpSp; + + PAGED_CODE(); + + _SEH2_TRY + { + ASSERT(IrpContext); + + ASSERT((IrpContext->Identifier.Type == FFSICX) && + (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); + + FileObject = IrpContext->FileObject; + + Irp = IrpContext->Irp; + IrpSp = IoGetCurrentIrpStackLocation(Irp); + + CcMdlWriteComplete(FileObject, &(IrpSp->Parameters.Write.ByteOffset), Irp->MdlAddress); + + Irp->MdlAddress = NULL; + + Status = STATUS_SUCCESS; + } + + _SEH2_FINALLY + { + if (!IrpContext->ExceptionInProgress) + { + FFSCompleteIrpContext(IrpContext, Status); + } + } _SEH2_END; + + return Status; +} + + +__drv_mustHoldCriticalRegion +NTSTATUS +FFSWrite( + IN PFFS_IRP_CONTEXT IrpContext) +{ + NTSTATUS Status; + PFFS_FCBVCB FcbOrVcb; + PDEVICE_OBJECT DeviceObject; + PFILE_OBJECT FileObject; + PFFS_VCB Vcb; + BOOLEAN bCompleteRequest = TRUE; + + PAGED_CODE(); + + ASSERT(IrpContext); + + ASSERT((IrpContext->Identifier.Type == FFSICX) && + (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT))); + + _SEH2_TRY + { + if (FlagOn(IrpContext->MinorFunction, IRP_MN_COMPLETE)) + { + Status = FFSWriteComplete(IrpContext); + bCompleteRequest = FALSE; + } + else + { + DeviceObject = IrpContext->DeviceObject; + + if (DeviceObject == FFSGlobal->DeviceObject) + { + Status = STATUS_INVALID_DEVICE_REQUEST; + _SEH2_LEAVE; + } + + Vcb = (PFFS_VCB)DeviceObject->DeviceExtension; + + if (Vcb->Identifier.Type != FFSVCB || + Vcb->Identifier.Size != sizeof(FFS_VCB)) + { + Status = STATUS_INVALID_PARAMETER; + _SEH2_LEAVE; + } + + ASSERT(IsMounted(Vcb)); + + if (IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING)) + { + Status = STATUS_TOO_LATE; + _SEH2_LEAVE; + } + + if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY)) + { + Status = STATUS_MEDIA_WRITE_PROTECTED; + _SEH2_LEAVE; + } + + FileObject = IrpContext->FileObject; + + FcbOrVcb = (PFFS_FCBVCB)FileObject->FsContext; + + if (FcbOrVcb->Identifier.Type == FFSVCB) + { + Status = FFSWriteVolume(IrpContext); + + if (!NT_SUCCESS(Status)) + { + FFSBreakPoint(); + } + + bCompleteRequest = FALSE; + } + else if (FcbOrVcb->Identifier.Type == FFSFCB) + { + Status = FFSWriteFile(IrpContext); + + if (!NT_SUCCESS(Status)) + { + FFSBreakPoint(); + } + + bCompleteRequest = FALSE; + } + else + { + Status = STATUS_INVALID_PARAMETER; + } + } + } + + _SEH2_FINALLY + { + if (bCompleteRequest) + { + FFSCompleteIrpContext(IrpContext, Status); + } + } _SEH2_END; + + return Status; +} + +#endif // !FFS_READ_ONLY