Import the FFS driver by Jae-Hong Lee.
Patch by Peter Hater
CORE-11040
svn path=/trunk/; revision=71425
add_subdirectory(ext2)
add_subdirectory(fastfat)
#add_subdirectory(fastfat_new)
+add_subdirectory(ffs)
add_subdirectory(fs_rec)
add_subdirectory(msfs)
add_subdirectory(mup)
--- /dev/null
+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)
+
--- /dev/null
+/* $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 <sys/stdint.h>
+#else
+#include <stdint.h>
+#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 <machine/disklabel.h> */
+#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 */
--- /dev/null
+/* $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_ */
--- /dev/null
+/* $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_ */
--- /dev/null
+/* $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 <machine/types.h> for __HAVE_OLD_DISKLABEL
+ */
+#if 0 /* XXX ffsdrv */
+#ifndef _LOCORE
+#include <sys/types.h>
+#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 <machine/disklabel.h>
+#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 <machine/disklabel.h> as the old number
+ * - define MAXPARTITIONS as the new number
+ * - define DISKUNIT, DISKPART and DISKMINOR macros in <machine/disklabel.h>
+ * as appropriate for the port (see the i386 one for an example).
+ * - define __HAVE_OLD_DISKLABEL in <machine/types.h>
+ */
+
+#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 <sys/mount.h> */
+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 <sys/mount.h> */
+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 <sys/cdefs.h>
+#endif
+
+#endif
+
+#endif /* !_SYS_DISKLABEL_H_ */
--- /dev/null
+/*
+ * 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 <ntifs.h>
+#include <ntddk.h>
+#include <ntdddisk.h>
+#include <pseh/pseh2.h>
+#endif
+#include "fs.h"
+#include "dinode.h"
+#include "dir.h"
+#include "disklabel.h"
+#ifndef __REACTOS__
+#include <ntdddisk.h>
+#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_ */
--- /dev/null
+/* $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 <gluk@ptci.ru> 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_ */
--- /dev/null
+/*
+ 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 <ntddk.h>
+#include <ntverp.h>
+
+// 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 <pshpack4.h>
+#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 <poppack.h>
+#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 <pshpack1.h>
+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 <poppack.h>
+
+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\\<DriverName>"
+ 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\\<DriverName>"
+ 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_
--- /dev/null
+/* 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;
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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;
+}
+
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+//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
+
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * FFS File System Driver for Windows
+ *
+ * init.c
+ *
+ * 2004.5.6 ~
+ *
+ * Lee Jae-Hong, http://www.pyrasis.com
+ *
+ * See License.txt
+ *
+ */
+
+#include <ntifs.h>
+#ifndef __REACTOS__
+#include <wdmsec.h>
+#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;
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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));
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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)
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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