[FFS]
authorPierre Schweitzer <pierre@reactos.org>
Fri, 27 May 2016 12:08:38 +0000 (12:08 +0000)
committerPierre Schweitzer <pierre@reactos.org>
Fri, 27 May 2016 12:08:38 +0000 (12:08 +0000)
Import the FFS driver by Jae-Hong Lee.
Patch by Peter Hater

CORE-11040

svn path=/trunk/; revision=71425

35 files changed:
reactos/drivers/filesystems/CMakeLists.txt
reactos/drivers/filesystems/ffs/CMakeLists.txt [new file with mode: 0644]
reactos/drivers/filesystems/ffs/inc/bootblock.h [new file with mode: 0644]
reactos/drivers/filesystems/ffs/inc/dinode.h [new file with mode: 0644]
reactos/drivers/filesystems/ffs/inc/dir.h [new file with mode: 0644]
reactos/drivers/filesystems/ffs/inc/disklabel.h [new file with mode: 0644]
reactos/drivers/filesystems/ffs/inc/ffsdrv.h [new file with mode: 0644]
reactos/drivers/filesystems/ffs/inc/fs.h [new file with mode: 0644]
reactos/drivers/filesystems/ffs/inc/gplntifs.h [new file with mode: 0644]
reactos/drivers/filesystems/ffs/inc/type.h [new file with mode: 0644]
reactos/drivers/filesystems/ffs/src/block.c [new file with mode: 0644]
reactos/drivers/filesystems/ffs/src/cleanup.c [new file with mode: 0644]
reactos/drivers/filesystems/ffs/src/close.c [new file with mode: 0644]
reactos/drivers/filesystems/ffs/src/cmcb.c [new file with mode: 0644]
reactos/drivers/filesystems/ffs/src/create.c [new file with mode: 0644]
reactos/drivers/filesystems/ffs/src/debug.c [new file with mode: 0644]
reactos/drivers/filesystems/ffs/src/devctl.c [new file with mode: 0644]
reactos/drivers/filesystems/ffs/src/dirctl.c [new file with mode: 0644]
reactos/drivers/filesystems/ffs/src/dispatch.c [new file with mode: 0644]
reactos/drivers/filesystems/ffs/src/except.c [new file with mode: 0644]
reactos/drivers/filesystems/ffs/src/fastio.c [new file with mode: 0644]
reactos/drivers/filesystems/ffs/src/ffs.c [new file with mode: 0644]
reactos/drivers/filesystems/ffs/src/ffsdrv.rc [new file with mode: 0644]
reactos/drivers/filesystems/ffs/src/fileinfo.c [new file with mode: 0644]
reactos/drivers/filesystems/ffs/src/flush.c [new file with mode: 0644]
reactos/drivers/filesystems/ffs/src/fsctl.c [new file with mode: 0644]
reactos/drivers/filesystems/ffs/src/init.c [new file with mode: 0644]
reactos/drivers/filesystems/ffs/src/lock.c [new file with mode: 0644]
reactos/drivers/filesystems/ffs/src/memory.c [new file with mode: 0644]
reactos/drivers/filesystems/ffs/src/misc.c [new file with mode: 0644]
reactos/drivers/filesystems/ffs/src/pnp.c [new file with mode: 0644]
reactos/drivers/filesystems/ffs/src/read.c [new file with mode: 0644]
reactos/drivers/filesystems/ffs/src/shutdown.c [new file with mode: 0644]
reactos/drivers/filesystems/ffs/src/volinfo.c [new file with mode: 0644]
reactos/drivers/filesystems/ffs/src/write.c [new file with mode: 0644]

index cd2549c..ef6e644 100644 (file)
@@ -4,6 +4,7 @@ add_subdirectory(cdfs)
 add_subdirectory(ext2)
 add_subdirectory(fastfat)
 #add_subdirectory(fastfat_new)
+add_subdirectory(ffs)
 add_subdirectory(fs_rec)
 add_subdirectory(msfs)
 add_subdirectory(mup)
diff --git a/reactos/drivers/filesystems/ffs/CMakeLists.txt b/reactos/drivers/filesystems/ffs/CMakeLists.txt
new file mode 100644 (file)
index 0000000..1f353f0
--- /dev/null
@@ -0,0 +1,48 @@
+include_directories(${REACTOS_SOURCE_DIR}/include/reactos/drivers
+                    inc)
+
+list(APPEND SOURCE
+    src/block.c
+    src/cleanup.c
+    src/close.c
+    src/cmcb.c
+    src/create.c
+    src/debug.c
+    src/devctl.c
+    src/dirctl.c
+    src/dispatch.c
+    src/except.c
+    src/fastio.c
+    src/ffs.c
+    src/fileinfo.c
+    src/flush.c
+    src/fsctl.c
+    src/init.c
+    src/lock.c
+    src/memory.c
+    src/misc.c
+    src/pnp.c
+    src/read.c
+    src/shutdown.c
+    src/volinfo.c
+    src/write.c
+    inc/ffsdrv.h)
+
+add_library(ffs SHARED ${SOURCE} src/ffsdrv.rc)
+
+if(NOT MSVC)
+    add_target_compile_flags(ffs "-Wno-pointer-sign -Wno-unused-function")
+    if(NOT CMAKE_C_COMPILER_ID STREQUAL "Clang")
+        add_target_compile_flags(ffs "-Wno-unused-but-set-variable -Wno-unused-variable -Wno-missing-braces")
+    endif()
+#else()
+#    replace_compile_flags("/we\"4189\"" " ")
+endif()
+
+add_definitions(-D__KERNEL__)
+set_module_type(ffs kernelmodedriver)
+target_link_libraries(ffs memcmp ${PSEH_LIB})
+add_importlibs(ffs ntoskrnl hal)
+add_pch(ffs inc/ffsdrv.h SOURCE)
+add_cd_file(TARGET ffs DESTINATION reactos/system32/drivers NO_CAB FOR all)
+
diff --git a/reactos/drivers/filesystems/ffs/inc/bootblock.h b/reactos/drivers/filesystems/ffs/inc/bootblock.h
new file mode 100644 (file)
index 0000000..f6bf3e0
--- /dev/null
@@ -0,0 +1,892 @@
+/*     $NetBSD: bootblock.h,v 1.24 2004/03/22 07:11:00 lukem Exp $     */
+
+/*-
+ * Copyright (c) 2002-2004 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the NetBSD
+ *     Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+/*-
+ * Copyright (C) 1993  Allen K. Briggs, Chris P. Caputo,
+ *                     Michael L. Finch, Bradley A. Grantham, and
+ *                     Lawrence A. Kesteloot
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the Alice Group.
+ * 4. The names of the Alice Group or any of its members may not be used
+ *    to endorse or promote products derived from this software without
+ *    specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE ALICE GROUP ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE ALICE GROUP BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+/*
+ * Copyright (c) 1994, 1999 Christopher G. Demetriou
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Christopher G. Demetriou
+ *      for the NetBSD Project.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * Copyright (c) 1994 Rolf Grossmann
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Rolf Grossmann.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _SYS_BOOTBLOCK_H
+#define        _SYS_BOOTBLOCK_H
+
+#include "type.h"
+
+#if 0 /* XXX ffsdrv */
+#if !defined(__ASSEMBLER__)
+#if defined(_KERNEL) || defined(_STANDALONE)
+#include <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 */
diff --git a/reactos/drivers/filesystems/ffs/inc/dinode.h b/reactos/drivers/filesystems/ffs/inc/dinode.h
new file mode 100644 (file)
index 0000000..3b87eb5
--- /dev/null
@@ -0,0 +1,177 @@
+/*     $NetBSD: dinode.h,v 1.18 2003/08/07 16:34:42 agc Exp $  */
+
+/*
+ * Copyright (c) 2002 Networks Associates Technology, Inc.
+ * All rights reserved.
+ *
+ * This software was developed for the FreeBSD Project by Marshall
+ * Kirk McKusick and Network Associates Laboratories, the Security
+ * Research Division of Network Associates, Inc. under DARPA/SPAWAR
+ * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS
+ * research program
+ *
+ * Copyright (c) 1982, 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)dinode.h    8.9 (Berkeley) 3/29/95
+ */
+
+#ifndef        _UFS_UFS_DINODE_H_
+#define        _UFS_UFS_DINODE_H_
+
+#include "type.h"
+
+/*
+ * The root inode is the root of the file system.  Inode 0 can't be used for
+ * normal purposes and historically bad blocks were linked to inode 1, thus
+ * the root inode is 2.  (Inode 1 is no longer used for this purpose, however
+ * numerous dump tapes make this assumption, so we are stuck with it).
+ */
+#define        ROOTINO ((ino_t)2)
+
+/*
+ * The Whiteout inode# is a dummy non-zero inode number which will
+ * never be allocated to a real file.  It is used as a place holder
+ * in the directory entry which has been tagged as a DT_W entry.
+ * See the comments about ROOTINO above.
+ */
+#define        WINO    ((ino_t)1)
+
+/*
+ * A dinode contains all the meta-data associated with a UFS file.
+ * This structure defines the on-disk format of a dinode. Since
+ * this structure describes an on-disk structure, all its fields
+ * are defined by types with precise widths.
+ */
+
+#define NXADDR 2
+#define        NDADDR  12                      /* Direct addresses in inode. */
+#define        NIADDR  3                       /* Indirect addresses in inode. */
+
+struct ufs1_dinode {
+       u_int16_t       di_mode;        /*   0: IFMT, permissions; see below. */
+       int16_t         di_nlink;       /*   2: File link count. */
+       union {
+               u_int16_t oldids[2];    /*   4: Ffs: old user and group ids. */
+               u_int32_t inumber;      /*   4: Lfs: inode number. */
+       } di_u;
+       u_int64_t       di_size;        /*   8: File byte count. */
+       int32_t         di_atime;       /*  16: Last access time. */
+       int32_t         di_atimensec;   /*  20: Last access time. */
+       int32_t         di_mtime;       /*  24: Last modified time. */
+       int32_t         di_mtimensec;   /*  28: Last modified time. */
+       int32_t         di_ctime;       /*  32: Last inode change time. */
+       int32_t         di_ctimensec;   /*  36: Last inode change time. */
+       int32_t         di_db[NDADDR];  /*  40: Direct disk blocks. */
+       int32_t         di_ib[NIADDR];  /*  88: Indirect disk blocks. */
+       u_int32_t       di_flags;       /* 100: Status flags (chflags). */
+       u_int32_t       di_blocks;      /* 104: Blocks actually held. */
+       int32_t         di_gen;         /* 108: Generation number. */
+       u_int32_t       di_uid;         /* 112: File owner. */
+       u_int32_t       di_gid;         /* 116: File group. */
+       int32_t         di_spare[2];    /* 120: Reserved; currently unused */
+};
+
+struct ufs2_dinode {
+       u_int16_t       di_mode;        /*   0: IFMT, permissions; see below. */
+       int16_t         di_nlink;       /*   2: File link count. */
+       u_int32_t       di_uid;         /*   4: File owner. */
+       u_int32_t       di_gid;         /*   8: File group. */
+       u_int32_t       di_blksize;     /*  12: Inode blocksize. */
+       u_int64_t       di_size;        /*  16: File byte count. */
+       u_int64_t       di_blocks;      /*  24: Bytes actually held. */
+       int64_t         di_atime;       /*  32: Last access time. */
+       int64_t         di_mtime;       /*  40: Last modified time. */
+       int64_t         di_ctime;       /*  48: Last inode change time. */
+       int64_t         di_birthtime;   /*  56: Inode creation time. */
+       int32_t         di_mtimensec;   /*  64: Last modified time. */
+       int32_t         di_atimensec;   /*  68: Last access time. */
+       int32_t         di_ctimensec;   /*  72: Last inode change time. */
+       int32_t         di_birthnsec;   /*  76: Inode creation time. */
+       int32_t         di_gen;         /*  80: Generation number. */
+       u_int32_t       di_kernflags;   /*  84: Kernel flags. */
+       u_int32_t       di_flags;       /*  88: Status flags (chflags). */
+       int32_t         di_extsize;     /*  92: External attributes block. */
+       int64_t         di_extb[NXADDR];/*  96: External attributes block. */
+       int64_t         di_db[NDADDR];  /* 112: Direct disk blocks. */
+       int64_t         di_ib[NIADDR];  /* 208: Indirect disk blocks. */
+       int64_t         di_spare[3];    /* 232: Reserved; currently unused */
+};
+
+/*
+ * The di_db fields may be overlaid with other information for
+ * file types that do not have associated disk storage. Block
+ * and character devices overlay the first data block with their
+ * dev_t value. Short symbolic links place their path in the
+ * di_db area.
+ */
+#define        di_inumber      di_u.inumber
+#define        di_ogid         di_u.oldids[1]
+#define        di_ouid         di_u.oldids[0]
+#define        di_rdev         di_db[0]
+#define MAXSYMLINKLEN_UFS1     ((NDADDR + NIADDR) * sizeof(int32_t))
+#define MAXSYMLINKLEN_UFS2     ((NDADDR + NIADDR) * sizeof(int64_t))
+
+#define MAXSYMLINKLEN(ip) \
+       ((ip)->i_ump->um_fstype == UFS1) ? \
+       MAXSYMLINKLEN_UFS1 : MAXSYMLINKLEN_UFS2
+
+/* NeXT used to keep short symlinks in the inode even when using
+ * FS_42INODEFMT.  In that case fs->fs_maxsymlinklen is probably -1,
+ * but short symlinks were stored in inodes shorter than this:
+ */
+#define        APPLEUFS_MAXSYMLINKLEN 60
+
+/* File permissions. */
+#define        IEXEC           0000100         /* Executable. */
+#define        IWRITE          0000200         /* Writable. */
+#define        IREAD           0000400         /* Readable. */
+#define        ISVTX           0001000         /* Sticky bit. */
+#define        ISGID           0002000         /* Set-gid. */
+#define        ISUID           0004000         /* Set-uid. */
+
+/* File types. */
+#define        IFMT            0170000         /* Mask of file type. */
+#define        IFIFO           0010000         /* Named pipe (fifo). */
+#define        IFCHR           0020000         /* Character device. */
+#define        IFDIR           0040000         /* Directory file. */
+#define        IFBLK           0060000         /* Block device. */
+#define        IFREG           0100000         /* Regular file. */
+#define        IFLNK           0120000         /* Symbolic link. */
+#define        IFSOCK          0140000         /* UNIX domain socket. */
+#define        IFWHT           0160000         /* Whiteout. */
+
+/* Size of the on-disk inode. */
+#define        DINODE1_SIZE    (sizeof(struct ufs1_dinode))            /* 128 */
+#define        DINODE2_SIZE    (sizeof(struct ufs2_dinode))
+
+#endif /* !_UFS_UFS_DINODE_H_ */
diff --git a/reactos/drivers/filesystems/ffs/inc/dir.h b/reactos/drivers/filesystems/ffs/inc/dir.h
new file mode 100644 (file)
index 0000000..53b5034
--- /dev/null
@@ -0,0 +1,162 @@
+/*     $NetBSD: dir.h,v 1.17 2003/08/07 16:34:42 agc Exp $     */
+
+/*
+ * Copyright (c) 1982, 1986, 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)dir.h       8.5 (Berkeley) 4/27/95
+ */
+
+#ifndef _UFS_UFS_DIR_H_
+#define        _UFS_UFS_DIR_H_
+
+#include "type.h"
+
+/*
+ * Theoretically, directories can be more than 2Gb in length, however, in
+ * practice this seems unlikely. So, we define the type doff_t as a 32-bit
+ * quantity to keep down the cost of doing lookup on a 32-bit machine.
+ */
+#define        doff_t          int32_t
+#define        MAXDIRSIZE      (0x7fffffff)
+
+/*
+ * A directory consists of some number of blocks of DIRBLKSIZ
+ * bytes, where DIRBLKSIZ is chosen such that it can be transferred
+ * to disk in a single atomic operation (e.g. 512 bytes on most machines).
+ *
+ * Each DIRBLKSIZ byte block contains some number of directory entry
+ * structures, which are of variable length.  Each directory entry has
+ * a struct direct at the front of it, containing its inode number,
+ * the length of the entry, and the length of the name contained in
+ * the entry.  These are followed by the name padded to a 4 byte boundary.
+ * All names are guaranteed null terminated.
+ * The maximum length of a name in a directory is MAXNAMLEN.
+ *
+ * The macro DIRSIZ(fmt, dp) gives the amount of space required to represent
+ * a directory entry.  Free space in a directory is represented by
+ * entries which have dp->d_reclen > DIRSIZ(fmt, dp).  All DIRBLKSIZ bytes
+ * in a directory block are claimed by the directory entries.  This
+ * usually results in the last entry in a directory having a large
+ * dp->d_reclen.  When entries are deleted from a directory, the
+ * space is returned to the previous entry in the same directory
+ * block by increasing its dp->d_reclen.  If the first entry of
+ * a directory block is free, then its dp->d_ino is set to 0.
+ * Entries other than the first in a directory do not normally have
+ * dp->d_ino set to 0.
+ */
+#undef DIRBLKSIZ
+#define        DIRBLKSIZ       DEV_BSIZE
+#undef MAXNAMLEN
+#define        MAXNAMLEN       255
+#define APPLEUFS_DIRBLKSIZ 1024
+
+struct direct {
+       u_int32_t d_ino;                /* inode number of entry */
+       u_int16_t d_reclen;             /* length of this record */
+       u_int8_t  d_type;               /* file type, see below */
+       u_int8_t  d_namlen;             /* length of string in d_name */
+       char      d_name[MAXNAMLEN + 1];/* name with length <= MAXNAMLEN */
+};
+
+/*
+ * File types
+ */
+#define        DT_UNKNOWN       0
+#define        DT_FIFO          1
+#define        DT_CHR           2
+#define        DT_DIR           4
+#define        DT_BLK           6
+#define        DT_REG           8
+#define        DT_LNK          10
+#define        DT_SOCK         12
+#define        DT_WHT          14
+
+/*
+ * Convert between stat structure types and directory types.
+ */
+#define        IFTODT(mode)    (((mode) & 0170000) >> 12)
+#define        DTTOIF(dirtype) ((dirtype) << 12)
+
+/*
+ * The DIRSIZ macro gives the minimum record length which will hold
+ * the directory entry.  This requires the amount of space in struct direct
+ * without the d_name field, plus enough space for the name with a terminating
+ * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary.
+ */
+#define        DIRECTSIZ(namlen) \
+       ((sizeof(struct direct) - (MAXNAMLEN+1)) + (((namlen)+1 + 3) &~ 3))
+
+#if (BYTE_ORDER == LITTLE_ENDIAN)
+#define DIRSIZ(oldfmt, dp, needswap)   \
+    (((oldfmt) && !(needswap)) ?       \
+    DIRECTSIZ((dp)->d_type) : DIRECTSIZ((dp)->d_namlen))
+#else
+#define DIRSIZ(oldfmt, dp, needswap)   \
+    (((oldfmt) && (needswap)) ?                \
+    DIRECTSIZ((dp)->d_type) : DIRECTSIZ((dp)->d_namlen))
+#endif
+
+#define OLDDIRFMT      1
+#define NEWDIRFMT      0
+
+/*
+ * Template for manipulating directories.  Should use struct direct's,
+ * but the name field is MAXNAMLEN - 1, and this just won't do.
+ */
+struct dirtemplate {
+       u_int32_t       dot_ino;
+       int16_t         dot_reclen;
+       u_int8_t        dot_type;
+       u_int8_t        dot_namlen;
+       char            dot_name[4];    /* must be multiple of 4 */
+       u_int32_t       dotdot_ino;
+       int16_t         dotdot_reclen;
+       u_int8_t        dotdot_type;
+       u_int8_t        dotdot_namlen;
+       char            dotdot_name[4]; /* ditto */
+};
+
+/*
+ * This is the old format of directories, sanz type element.
+ */
+struct odirtemplate {
+       u_int32_t       dot_ino;
+       int16_t         dot_reclen;
+       u_int16_t       dot_namlen;
+       char            dot_name[4];    /* must be multiple of 4 */
+       u_int32_t       dotdot_ino;
+       int16_t         dotdot_reclen;
+       u_int16_t       dotdot_namlen;
+       char            dotdot_name[4]; /* ditto */
+};
+#endif /* !_UFS_UFS_DIR_H_ */
diff --git a/reactos/drivers/filesystems/ffs/inc/disklabel.h b/reactos/drivers/filesystems/ffs/inc/disklabel.h
new file mode 100644 (file)
index 0000000..f7d7a37
--- /dev/null
@@ -0,0 +1,555 @@
+/*     $NetBSD: disklabel.h,v 1.88 2003/11/14 12:07:42 lukem Exp $     */
+
+/*
+ * Copyright (c) 1987, 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)disklabel.h 8.2 (Berkeley) 7/10/94
+ */
+
+#ifndef _SYS_DISKLABEL_H_
+#define        _SYS_DISKLABEL_H_
+
+#include "type.h"
+
+/*
+ * We need <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_ */
diff --git a/reactos/drivers/filesystems/ffs/inc/ffsdrv.h b/reactos/drivers/filesystems/ffs/inc/ffsdrv.h
new file mode 100644 (file)
index 0000000..41d395d
--- /dev/null
@@ -0,0 +1,2178 @@
+/* 
+ * FFS File System Driver for Windows
+ *
+ * ffsdrv.h
+ *
+ * 2004.5.6 ~
+ *
+ * Lee Jae-Hong, http://www.pyrasis.com
+ *
+ */
+
+#ifndef _FFS_HEADER_
+#define _FFS_HEADER_
+
+/* include files */
+#ifdef __REACTOS__
+#include <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_ */
diff --git a/reactos/drivers/filesystems/ffs/inc/fs.h b/reactos/drivers/filesystems/ffs/inc/fs.h
new file mode 100644 (file)
index 0000000..dde9bef
--- /dev/null
@@ -0,0 +1,697 @@
+/*     $NetBSD: fs.h,v 1.43 2004/03/21 18:48:24 dsl Exp $      */
+
+/*
+ * Copyright (c) 1982, 1986, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)fs.h        8.13 (Berkeley) 3/21/95
+ */
+
+#ifndef        _UFS_FFS_FS_H_
+#define        _UFS_FFS_FS_H_
+
+#include "type.h"
+
+/*
+ * Each disk drive contains some number of file systems.
+ * A file system consists of a number of cylinder groups.
+ * Each cylinder group has inodes and data.
+ *
+ * A file system is described by its super-block, which in turn
+ * describes the cylinder groups.  The super-block is critical
+ * data and is replicated in each cylinder group to protect against
+ * catastrophic loss.  This is done at `newfs' time and the critical
+ * super-block data does not change, so the copies need not be
+ * referenced further unless disaster strikes.
+ *
+ * For file system fs, the offsets of the various blocks of interest
+ * are given in the super block as:
+ *     [fs->fs_sblkno]         Super-block
+ *     [fs->fs_cblkno]         Cylinder group block
+ *     [fs->fs_iblkno]         Inode blocks
+ *     [fs->fs_dblkno]         Data blocks
+ * The beginning of cylinder group cg in fs, is given by
+ * the ``cgbase(fs, cg)'' macro.
+ *
+ * Depending on the architecture and the media, the superblock may
+ * reside in any one of four places. For tiny media where every block 
+ * counts, it is placed at the very front of the partition. Historically,
+ * UFS1 placed it 8K from the front to leave room for the disk label and
+ * a small bootstrap. For UFS2 it got moved to 64K from the front to leave
+ * room for the disk label and a bigger bootstrap, and for really piggy
+ * systems we check at 256K from the front if the first three fail. In
+ * all cases the size of the superblock will be SBLOCKSIZE. All values are
+ * given in byte-offset form, so they do not imply a sector size. The
+ * SBLOCKSEARCH specifies the order in which the locations should be searched.
+ *
+ * Unfortunately the UFS2/FFSv2 change was done without adequate consideration
+ * of backward compatibility.  In particular 'newfs' for a FFSv2 partition
+ * must overwrite any old FFSv1 superblock at 8k, and preferrably as many
+ * of the alternates as it can find - otherwise attempting to mount on a
+ * system that only supports FFSv1 is likely to succeed!.
+ * For a small FFSv1 filesystem, an old FFSv2 superblock can be left on
+ * the disk, and a system that tries to find an FFSv2 filesystem in preference
+ * to and FFSv1 one (as NetBSD does) can mount the old FFSv2 filesystem.
+ * As a added bonus, the 'first alternate' superblock of a FFSv1 filesystem
+ * with 64k blocks is at 64k - just where the code looks first when playing
+ * 'hunt the superblock'.
+ *
+ * The ffsv2 superblock layout (which might contain an ffsv1 filesystem)
+ * can be detected by checking for sb->fs_old_flags & FS_FLAGS_UPDATED.
+ * This is the default suberblock type for NetBSD since ffsv2 support was added.
+ */
+#define        BBSIZE          8192
+#define        BBOFF           ((off_t)(0))
+#define        BBLOCK          ((daddr_t)(0))
+
+#define SBLOCK_FLOPPY      0
+#define SBLOCK_UFS1     8192
+#define SBLOCK_UFS2    65536
+#define SBLOCK_PIGGY  262144
+#define SBLOCKSIZE      8192
+/*
+ * NB: Do not, under any circumstances, look for an ffsv1 filesystem at
+ * SBLOCK_UFS2.  Doing so will find the wrong superblock for filesystems
+ * with a 64k block size.
+ */
+#define SBLOCKSEARCH \
+       { SBLOCK_UFS2, SBLOCK_UFS1, SBLOCK_FLOPPY, SBLOCK_PIGGY, -1 }
+
+/*
+ * Max number of fragments per block. This value is NOT tweakable.
+ */
+#define MAXFRAG                8
+
+
+
+/*
+ * Addresses stored in inodes are capable of addressing fragments
+ * of `blocks'. File system blocks of at most size MAXBSIZE can
+ * be optionally broken into 2, 4, or 8 pieces, each of which is
+ * addressable; these pieces may be DEV_BSIZE, or some multiple of
+ * a DEV_BSIZE unit.
+ *
+ * Large files consist of exclusively large data blocks.  To avoid
+ * undue wasted disk space, the last data block of a small file may be
+ * allocated as only as many fragments of a large block as are
+ * necessary.  The file system format retains only a single pointer
+ * to such a fragment, which is a piece of a single large block that
+ * has been divided.  The size of such a fragment is determinable from
+ * information in the inode, using the ``blksize(fs, ip, lbn)'' macro.
+ *
+ * The file system records space availability at the fragment level;
+ * to determine block availability, aligned fragments are examined.
+ */
+
+/*
+ * MINBSIZE is the smallest allowable block size.
+ * In order to insure that it is possible to create files of size
+ * 2^32 with only two levels of indirection, MINBSIZE is set to 4096.
+ * MINBSIZE must be big enough to hold a cylinder group block,
+ * thus changes to (struct cg) must keep its size within MINBSIZE.
+ * Note that super blocks are always of size SBSIZE,
+ * and that both SBSIZE and MAXBSIZE must be >= MINBSIZE.
+ */
+#define        MINBSIZE        4096
+
+/*
+ * The path name on which the file system is mounted is maintained
+ * in fs_fsmnt. MAXMNTLEN defines the amount of space allocated in
+ * the super block for this name.
+ */
+#define        MAXMNTLEN       468
+
+/*
+ * The volume name for this filesystem is maintained in fs_volname.
+ * MAXVOLLEN defines the length of the buffer allocated.
+ * This space used to be part of of fs_fsmnt.
+ */
+#define MAXVOLLEN      32
+
+/*
+ * There is a 128-byte region in the superblock reserved for in-core
+ * pointers to summary information. Originally this included an array
+ * of pointers to blocks of struct csum; now there are just four
+ * pointers and the remaining space is padded with fs_ocsp[].
+ * NOCSPTRS determines the size of this padding. One pointer (fs_csp)
+ * is taken away to point to a contiguous array of struct csum for
+ * all cylinder groups; a second (fs_maxcluster) points to an array
+ * of cluster sizes that is computed as cylinder groups are inspected;
+ * the third (fs_contigdirs) points to an array that tracks the
+ * creation of new directories; and the fourth (fs_active) is used
+ * by snapshots.
+ */
+#define        NOCSPTRS        ((128 / sizeof(void *)) - 4)
+
+/*
+ * A summary of contiguous blocks of various sizes is maintained
+ * in each cylinder group. Normally this is set by the initial
+ * value of fs_maxcontig. To conserve space, a maximum summary size
+ * is set by FS_MAXCONTIG.
+ */
+#define        FS_MAXCONTIG    16
+
+/*
+ * Unused value currently, FreeBSD compat.
+ */
+#define FSMAXSNAP 20
+
+/*
+ * MINFREE gives the minimum acceptable percentage of file system
+ * blocks which may be free. If the freelist drops below this level
+ * only the superuser may continue to allocate blocks. This may
+ * be set to 0 if no reserve of free blocks is deemed necessary,
+ * however throughput drops by fifty percent if the file system
+ * is run at between 95% and 100% full; thus the minimum default
+ * value of fs_minfree is 5%. However, to get good clustering
+ * performance, 10% is a better choice. hence we use 10% as our
+ * default value. With 10% free space, fragmentation is not a
+ * problem, so we choose to optimize for time.
+ */
+#define        MINFREE         5
+#define        DEFAULTOPT      FS_OPTTIME
+
+/*
+ * Grigoriy Orlov <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_ */
diff --git a/reactos/drivers/filesystems/ffs/inc/gplntifs.h b/reactos/drivers/filesystems/ffs/inc/gplntifs.h
new file mode 100644 (file)
index 0000000..d4d9f3a
--- /dev/null
@@ -0,0 +1,9491 @@
+/*
+    This is a free version of the file ntifs.h, release 58.
+    The purpose of this include file is to build file system and
+    file system filter drivers for Windows.
+    Copyright (C) 1999-2015 Bo Brantén.
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+    The GNU General Public License is also available from:
+    http://www.gnu.org/copyleft/gpl.html
+
+    Windows and Windows NT are either registered trademarks or trademarks of
+    Microsoft Corporation in the United States and/or other countries.
+
+    DISCLAIMER: I do not encourage anyone to use this include file to build
+    drivers used in production. Some of the information in this file may not
+    be available in other publications intended for similar use. Some of the
+    information in this file may have different names than in other
+    publications even though they describe the same thing.
+
+    NOTE: This file should be used with the Microsoft® Windows® Driver
+    Development Kit (DDK) while the file wdkundoc.h is a subset of this
+    file that should be used with the Microsoft Windows Driver Kit (WDK).
+
+    Please send comments, corrections and contributions to bosse@acc.umu.se.
+
+    The most recent version of this file is available from:
+    http://www.acc.umu.se/~bosse/ntifs.h
+
+    The most recent version of the file wdkundoc.h is available from:
+    http://www.acc.umu.se/~bosse/wdkundoc.h
+
+    Thanks to:
+      Andrey Shedel, Luigi Mori, Louis Joubert, Itai Shaham, David Welch,
+      Emanuele Aliberti, Anton Altaparmakov, Dan Partelly, Mamaich, Yossi
+      Yaffe, Gunnar André Dalsnes, Vadim V Vorobev, Ashot Oganesyan K,
+      Oleg Nikityenko, Matt Wu, Tomas Olsson, Raaf, Anthony Choi, Alexey
+      Logachyov, Marc-Antoine Ruel, Vyacheslav I. Levtchenko, Yuri Polyakov,
+      Bruno Milot, Alex Vlasov, Dan Fulger, Petr Semerad, Sobame La Garompa,
+      Jérôme Hodé and Darja Isaksson.
+
+    Revision history:
+
+    58. 2015-06-11
+        Added:
+          Externals:
+            PsInitialSystemProcess
+            HalPrivateDispatchTable
+            KeLoaderBlock
+            KeI386MachineType
+            KiBugCheckData
+            InitSafeBootMode
+            KiEnableTimerWatchdog
+            KdComPortInUse
+            KdEnteredDebugger
+            MmBadPointer
+            NlsLeadByteInfo
+            NlsOemLeadByteInfo
+            NlsMbCodePageTag
+            NlsMbOemCodePageTag
+            NlsAnsiCodePage
+            NlsOemCodePage
+            IoStatisticsLock
+            IoReadOperationCount
+            IoWriteOperationCount
+            IoReadTransferCount
+            IoWriteTransferCount
+            KeDcacheFlushCount
+            KeIcacheFlushCount
+            CcFastMdlReadWait
+            CcFastReadNotPossible
+            CcFastReadWait
+            IoAdapterObjectType
+            IoDeviceObjectType
+            MmSectionObjectType
+            PsProcessType
+            PsThreadType
+            ExDesktopObjectType
+            ExWindowStationObjectType
+            IoDeviceHandlerObjectType
+            LpcPortObjectType
+            PsJobType
+            SeTokenObjectType
+            TmEnlistmentObjectType
+            TmResourceManagerObjectType
+            TmTransactionManagerObjectType
+            TmTransactionObjectType
+            CmKeyObjectType
+            IoDeviceHandlerObjectSize
+            POGOBuffer
+            psMUITest
+            PsUILanguageComitted
+
+    57. 2015-03-23
+        Corrected:
+          ObGetObjectPointerCount
+        Added:
+          Function prototypes:
+            FsRtlTeardownPerFileContexts
+            FsRtlTeardownPerStreamContexts
+
+    56. 2008-07-31
+        Corrected:
+          FSCTL_SET_SPARSE
+          FSRTL_COMMON_FCB_HEADER
+        Added:
+          Defines:
+            FSRTL_XXX
+            IO_REPARSE_TAG_XXX
+          Data types:
+            FSRTL_ADVANCED_FCB_HEADER
+          Function prototypes:
+            FsRtlSetupAdvancedHeader
+
+    55. 2006-05-15
+        Corrected:
+          TOKEN_OBJECT
+        Added:
+          Data types:
+            SEP_AUDIT_POLICY_VISTA
+            SID_AND_ATTRIBUTES_HASH
+
+    54. 2006-05-14
+        Corrected:
+          EXTENDED_IO_STACK_LOCATION
+
+    53. 2005-11-06
+        Added:
+          Function prototypes:
+            RtlRandom
+            RtlRandomEx
+            RtlSecondsSince1980ToTime
+            RtlTimeToSecondsSince1980
+
+    52. 2005-11-05
+        Corrected:
+          OBJECT_NAME
+          TOKEN_OBJECT
+
+    51. 2005-10-16
+        Corrected:
+          ETHREAD
+          GDI_TEB_BATCH
+          MMADDRESS_NODE
+          TEB
+
+    50. 2005-10-15
+        Added:
+          Data types:
+            READ_LIST
+          Function prototypes:
+            IoAttachDeviceToDeviceStackSafe
+            IoCheckQuerySetFileInformation
+            IoCheckQuerySetVolumeInformation
+            IoCreateFileSpecifyDeviceObjectHint
+            IoCreateStreamFileObjectEx
+            IoEnumerateDeviceObjectList
+            IoGetDeviceAttachmentBaseRef
+            IoGetDiskDeviceObject
+            IoGetLowerDeviceObject
+            IoIsFileOriginRemote
+            IoQueryFileDosDeviceName
+            IoQueueThreadIrp
+            IoSetFileOrigin
+            KeAcquireQueuedSpinLock
+            KeInitializeMutant
+            KeReadStateMutant
+            KeReleaseMutant
+            KeReleaseQueuedSpinLock
+            KeSetIdealProcessorThread
+            KeSetKernelStackSwapEnable
+            KeTryToAcquireQueuedSpinLock
+            MmPrefetchPages
+            ObDereferenceSecurityDescriptor
+            ObLogSecurityDescriptor
+            ObReferenceSecurityDescriptor
+            PoQueueShutdownWorkItem
+            RtlxUnicodeStringToAnsiSize
+            SeAuditHardLinkCreation
+            SeAuditingHardLinkEvents
+            SeFilterToken
+
+    49. 2005-10-09
+        Corrected:
+          EPROCESS
+          KTHREAD
+          MMSUPPORT_FLAGS
+          MMSUPPORT
+          OBJECT_HEADER
+          OBJECT_TYPE_INITIALIZER
+          OBJECT_TYPE
+          TEB
+          KeInsertQueueApc
+        Added:
+          Defines:
+            OB_FLAG_XXX
+            OB_SECURITY_CHARGE
+          Data types:
+            ACTIVATION_CONTEXT_STACK
+            GDI_TEB_BATCH
+            HANDLE_INFO
+            KGUARDED_MUTEX
+            MMADDRESS_NODE
+            MM_AVL_TABLE
+            OBJECT_CREATE_INFORMATION
+            OBJECT_CREATOR_INFO
+            OBJECT_DIRECTORY
+            OBJECT_DIRECTORY_ITEM
+            OBJECT_HANDLE_DB
+            OBJECT_HANDLE_DB_LIST
+            OBJECT_HEADER_FLAGS
+            OBJECT_NAME
+            OBJECT_QUOTA_CHARGES
+            OBJECT_QUOTA_INFO
+            QUOTA_BLOCK
+            RTL_ACTIVATION_CONTEXT_STACK_FRAME
+            TEB_ACTIVE_FRAME
+            TEB_ACTIVE_FRAME_CONTEXT
+            Wx86ThreadState
+          Function prototypes:
+            FsRtlAcquireFileExclusive
+            FsRtlBalanceReads
+            FsRtlDissectDbcs
+            FsRtlDoesDbcsContainWildCards
+            FsRtlIsDbcsInExpression
+            FsRtlIsFatDbcsLegal
+            FsRtlIsHpfsDbcsLegal
+            FsRtlIsPagingFile
+            FsRtlIsTotalDeviceFailure
+            FsRtlMdlReadDev
+            FsRtlPostPagingFileStackOverflow
+            FsRtlPostStackOverflow
+            FsRtlPrepareMdlWriteDev
+            FsRtlReleaseFile
+
+    48. 2005-04-16
+        Added:
+          Data types:
+            THREAD_BASIC_INFORMATION
+          Function prototypes:
+            ZwQueryInformationThread
+
+    47. 2005-03-08
+        Corrected:
+          SYSTEM_PROCESSES_INFORMATION
+          TOKEN_OBJECT
+          KeInsertQueueApc
+
+    46. 2004-06-08
+        Added:
+          Data types:
+            TOKEN_OBJECT
+
+    45. 2004-06-06
+        Corrected:
+          SERVICE_DESCRIPTOR_TABLE
+        Added:
+          Defines:
+            TOKEN_SESSION_NOT_REFERENCED
+            TOKEN_SANDBOX_INERT
+            TOKEN_HAS_IMPERSONATE_PRIVILEGE
+          Function prototypes:
+            FsRtlDissectName
+            RtlOemStringToCountedUnicodeSize
+            RtlOemStringToUnicodeSize
+            RtlOemStringToUnicodeString
+            RtlUnicodeStringToOemSize
+            RtlUnicodeStringToOemString
+            RtlxOemStringToUnicodeSize
+            RtlxUnicodeStringToOemSize
+
+    44. 2003-05-06
+        Added:
+          Function prototypes:
+            InbvAcquireDisplayOwnership
+            InbvCheckDisplayOwnership
+            InbvDisplayString
+            InbvEnableBootDriver
+            InbvEnableDisplayString
+            InbvInstallDisplayStringFilter
+            InbvIsBootDriverInstalled
+            InbvNotifyDisplayOwnershipLost
+            InbvResetDisplay
+            InbvSetScrollRegion
+            InbvSetTextColor
+            InbvSolidColorFill
+
+    43. 2003-04-07
+        Added:
+          Data types:
+            MCB
+          Function prototypes:
+            FsRtlAddMcbEntry
+            FsRtlInitializeMcb
+            FsRtlLookupLastMcbEntry
+            FsRtlLookupMcbEntry
+            FsRtlNotifyFilterChangeDirectory
+            FsRtlNotifyFilterReportChange
+            FsRtlNumberOfRunsInMcb
+            FsRtlRemoveMcbEntry
+            FsRtlTruncateMcb
+            FsRtlUninitializeMcb
+
+    42. 2003-03-30
+        Corrected:
+          SYSTEM_CACHE_INFORMATION
+          SYSTEM_INFORMATION_CLASS
+        Added:
+          Data types:
+            SYSTEM_XXX_INFORMATION
+            THREAD_STATE
+
+    41. 2003-01-03
+        Corrected:
+          CcMapData
+          PsDereferenceImpersonationToken
+          PsDereferencePrimaryToken
+          PsGetProcessExitTime
+          PsReferencePrimaryToken
+        Added:
+          Defines:
+            MAP_XXX
+          Function prototypes:
+            CcMdlWriteAbort
+            PsAssignImpersonationToken
+            PsChargeProcessNonPagedPoolQuota
+            PsChargeProcessPagedPoolQuota
+            PsChargeProcessPoolQuota
+            PsDisableImpersonation
+            PsImpersonateClient
+            PsIsSystemThread
+            PsRestoreImpersonation
+            SeDeleteAccessState
+            ZwOpenProcessTokenEx
+            ZwOpenThreadTokenEx
+
+    40. 2002-10-02
+        Corrected:
+          HANDLE_TABLE_ENTRY
+        Added:
+          Defines:
+            FSRTL_FLAG_ADVANCED_HEADER
+            FSRTL_FLAG2_SUPPORTS_FILTER_CONTEXTS
+            FSRTL_FLAG2_PURGE_WHEN_MAPPED
+          Data types:
+            FILE_ID_BOTH_DIR_INFORMATION
+            FILE_ID_FULL_DIR_INFORMATION
+
+    39. 2002-08-04
+        Added:
+          Data types:
+            LARGE_MCB
+          Function prototypes:
+            FsRtlAddLargeMcbEntry
+            FsRtlGetNextLargeMcbEntry
+            FsRtlInitializeLargeMcb
+            FsRtlLookupLargeMcbEntry
+            FsRtlLookupLastLargeMcbEntry
+            FsRtlLookupLastLargeMcbEntryAndIndex
+            FsRtlNumberOfRunsInLargeMcb
+            FsRtlRemoveLargeMcbEntry
+            FsRtlResetLargeMcb
+            FsRtlSplitLargeMcb
+            FsRtlTruncateLargeMcb
+            FsRtlUninitializeLargeMcb
+
+    38. 2002-06-30
+        Added:
+          Defines:
+            FILE_READ_ONLY_VOLUME
+          Function prototypes:
+            FsRtlAllocateResource
+            FsRtlIncrementCcFastReadNotPossible
+            FsRtlIncrementCcFastReadNoWait
+            FsRtlIncrementCcFastReadResourceMiss
+            FsRtlIncrementCcFastReadWait
+            KeIsAttachedProcess
+            KeIsExecutingDpc
+            KeRevertToUserAffinityThread
+            KeUpdateSystemTime
+            PsGetCurrentProcessSessionId
+            PsGetCurrentThreadPreviousMode
+            PsGetCurrentThreadStackBase
+            PsGetCurrentThreadStackLimit
+            RtlGetNtGlobalFlags
+
+    37. 2002-05-18
+        Uppdated for Windows XP:
+          EPROCESS
+          ETHREAD
+          KPROCESS
+          KTHREAD
+          MMSUPPORT_FLAGS
+          MMSUPPORT
+          PRIVATE_CACHE_MAP_FLAGS
+          PRIVATE_CACHE_MAP
+          SHARED_CACHE_MAP
+        Corrected:
+          VACB
+        Added:
+          Data types:
+            EPROCESS_QUOTA_ENTRY
+            EPROCESS_QUOTA_BLOCK
+            EX_FAST_REF
+            EX_PUSH_LOCK
+            EX_RUNDOWN_REF
+            PAGEFAULT_HISTORY
+            SE_AUDIT_PROCESS_CREATION_INFO
+            SECTION_OBJECT
+            TERMINATION_PORT
+
+    36. 2002-05-14
+        Corrected:
+          FILE_FS_FULL_SIZE_INFORMATION
+
+    35. 2002-03-23
+        Added:
+          Defines:
+            COMPRESSION_XXX
+          Data types:
+            COMPRESSED_DATA_INFO
+            OBJECT_HEADER
+            VAD_HEADER
+          Function prototypes:
+            CcWaitForCurrentLazyWriterActivity
+            FsRtlCheckOplock
+            FsRtlCurrentBatchOplock
+            FsRtlDeregisterUncProvider
+            FsRtlInitializeOplock
+            FsRtlOplockFsctrl
+            FsRtlOplockIsFastIoPossible
+            FsRtlRegisterUncProvider
+            FsRtlUninitializeOplock
+            RtlCompressBuffer
+            RtlCompressChunks
+            RtlDecompressBuffer
+            RtlDecompressChunks
+            RtlDecompressFragment
+            RtlDescribeChunk
+            RtlGetCompressionWorkSpaceSize
+            RtlReserveChunk
+
+    34. 2002-02-14
+        Corrected:
+          HARDWARE_PTE
+          Changed the use of _WIN32_WINNT to VER_PRODUCTBUILD since _WIN32_WINNT
+          is incorrectly defined in the Windows 2000 build environment included
+          in the Windows XP DDK.
+
+    33. 2002-01-20
+        Added:
+          Function prototypes:
+            PsDereferenceImpersonationToken
+            PsDereferencePrimaryToken
+
+    32. 2002-01-18
+        Corrected:
+          ObReferenceObjectByName
+          FILE_FS_OBJECT_ID_INFORMATION
+          FILE_OBJECTID_INFORMATION
+        Added:
+          Externals:
+            IoDriverObjectType
+            SeExports
+          Defines:
+            FILE_ACTION_XXX
+            FSCTL_XXX
+            IO_FILE_OBJECT_XXX
+            IRP_BEING_VERIFIED
+            TOKEN_XXX
+          Data types:
+            DEVICE_MAP
+            FILE_TRACKING_INFORMATION
+            SE_EXPORTS
+          Function prototypes:
+            SeEnableAccessToExports
+
+    31. 2001-12-23
+        Corrected:
+          QueryQuota in EXTENDED_IO_STACK_LOCATION
+          FILE_LOCK
+          CcPinMappedData
+          CcPinRead
+          CcPreparePinWrite
+          FsRtlFastUnlockAll
+          FsRtlFastUnlockAllByKey
+          FsRtlFastUnlockSingle
+          FsRtlInitializeFileLock
+          FsRtlPrivateLock
+          FsRtlProcessFileLock
+          MmForceSectionClosed
+          MmIsRecursiveIoFault
+          SeImpersonateClient
+          SeImpersonateClientEx
+        Added:
+          Defines:
+            More FSRTL_FLAG_XXX
+            PIN_XXX
+            VACB_XXX
+          Data types:
+            REPARSE_DATA_BUFFER
+          Function prototypes:
+            CcCopyWriteWontFlush
+            CcGetFileSizePointer
+            CcGetFlushedValidData
+            CcIsFileCached
+            CcRemapBcb
+            ExDisableResourceBoostLite
+            ExQueryPoolBlockSize
+            FsRtlAllocateFileLock
+            FsRtlAreThereCurrentFileLocks
+            FsRtlFastLock
+            FsRtlFreeFileLock
+            IoCheckDesiredAccess
+            IoCheckEaBufferValidity
+            IoCheckFunctionAccess
+            IoCheckQuotaBufferValidity
+            IoCreateStreamFileObjectLite
+            IoFastQueryNetworkAttributes
+            IoGetRequestorProcessId
+            IoIsFileOpenedExclusively
+            IoIsSystemThread
+            IoIsValidNameGraftingBuffer
+            IoSynchronousPageWrite
+            IoThreadToProcess
+            KeInitializeQueue
+            KeInsertHeadQueue
+            KeInsertQueue
+            KeReadStateQueue
+            KeRemoveQueue
+            KeRundownQueue
+            MmSetAddressRangeModified
+            ObGetObjectPointerCount
+            ObMakeTemporaryObject
+            ObQueryObjectAuditingByHandle
+            PsChargePoolQuota
+            PsReturnPoolQuota
+            SeAppendPrivileges
+            SeAuditingFileEvents
+            SeAuditingFileOrGlobalEvents
+            SeCreateClientSecurity
+            SeCreateClientSecurityFromSubjectContext
+            SeDeleteClientSecurity
+            SeDeleteObjectAuditAlarm
+            SeFreePrivileges
+            SeLockSubjectContext
+            SeOpenObjectAuditAlarm
+            SeOpenObjectForDeleteAuditAlarm
+            SePrivilegeCheck
+            SeQueryAuthenticationIdToken
+            SeQuerySecurityDescriptorInfo
+            SeQuerySessionIdToken
+            SeSetAccessStateGenericMapping
+            SeSetSecurityDescriptorInfo
+            SeSetSecurityDescriptorInfoEx
+            SeTokenIsAdmin
+            SeTokenIsRestricted
+            SeTokenType
+            SeUnlockSubjectContext
+
+    30. 2001-10-24
+        Corrected:
+          KINTERRUPT
+          OBJECT_TYPE
+        Added:
+          Defines:
+            More FSCTL_XXX
+          Data types:
+            BITMAP_RANGE
+            CreateMailslot in EXTENDED_IO_STACK_LOCATION
+            CreatePipe in EXTENDED_IO_STACK_LOCATION
+            QueryQuota in EXTENDED_IO_STACK_LOCATION
+            MAILSLOT_CREATE_PARAMETERS
+            MBCB
+            NAMED_PIPE_CREATE_PARAMETERS
+            PRIVATE_CACHE_MAP_FLAGS
+            PRIVATE_CACHE_MAP
+            SECURITY_CLIENT_CONTEXT
+            SHARED_CACHE_MAP
+            VACB
+          Function prototypes:
+            HalQueryRealTimeClock
+            HalSetRealTimeClock
+            PsGetProcessExitTime
+            PsIsThreadTerminating
+            PsLookupProcessThreadByCid
+            PsLookupThreadByThreadId
+            SeQueryAuthenticationIdToken
+          Externals:
+            KeServiceDescriptorTable
+            SePublicDefaultDacl
+            SeSystemDefaultDacl
+
+    29. 2001-10-06
+        Added:
+          Defines:
+            FSRTL_VOLUME_XXX
+          Function prototypes:
+            FsRtlNotifyChangeDirectory
+            FsRtlNotifyReportChange
+            FsRtlNotifyVolumeEvent
+
+    28. 2001-09-16
+        Added:
+          Function prototypes:
+            FsRtlNotifyInitializeSync
+            FsRtlNotifyUninitializeSync
+            SeImpersonateClientEx
+            SeReleaseSubjectContext
+
+    27. 2001-08-25
+        Corrected:
+          KPROCESS
+          FILE_LOCK_ANCHOR
+          FsRtlNormalizeNtstatus
+          RtlSecondsSince1970ToTime
+          RtlTimeToSecondsSince1970
+          SeQueryInformationToken
+        Added:
+          Defines:
+            FS_LFN_APIS
+          Data types:
+            FILE_LOCK_ENTRY
+            FILE_SHARED_LOCK_ENTRY
+            FILE_EXCLUSIVE_LOCK_ENTRY
+          Function prototypes:
+            FsRtlCheckLockForReadAccess
+            FsRtlCheckLockForWriteAccess
+            FsRtlFastUnlockAll
+            FsRtlFastUnlockAllByKey
+            FsRtlFastUnlockSingle
+            FsRtlGetFileSize
+            FsRtlGetNextFileLock
+            FsRtlInitializeFileLock
+            FsRtlPrivateLock
+            FsRtlProcessFileLock
+            FsRtlUninitializeFileLock
+            IoUnregisterFsRegistrationChange
+            PsLookupProcessByProcessId
+            SeQuerySubjectContextToken
+
+    26. 2001-04-28
+        Added:
+          Defines:
+            FSCTL_XXX
+          Data types:
+            RTL_SPLAY_LINKS
+            TUNNEL
+          Function prototypes:
+            FsRtlAddToTunnelCache
+            FsRtlDeleteKeyFromTunnelCache
+            FsRtlDeleteTunnelCache
+            FsRtlFindInTunnelCache
+            FsRtlInitializeTunnelCache
+            IoSetDeviceToVerify
+            KeInitializeApc
+            KeInsertQueueApc
+            SeQueryInformationToken
+
+    25. 2001-04-05
+        Corrected:
+          RtlImageNtHeader
+          LPC_XXX
+          OBJECT_BASIC_INFO
+        Added:
+          Defines:
+            SID_REVISION
+          Data types:
+            DIRECTORY_BASIC_INFORMATION
+            KINTERRUPT
+            OBJECT_HANDLE_ATTRIBUTE_INFO
+            PROCESS_PRIORITY_CLASS
+            SECTION_BASIC_INFORMATION
+            SECTION_IMAGE_INFORMATION
+            SECTION_INFORMATION_CLASS
+          Function prototypes:
+            RtlSecondsSince1970ToTime
+            RtlTimeToSecondsSince1970
+            ZwAdjustPrivilegesToken
+            ZwAlertThread
+            ZwAccessCheckAndAuditAlarm
+            ZwClearEvent
+            ZwCloseObjectAuditAlarm
+            ZwCreateSection
+            ZwCreateSymbolicLinkObject
+            ZwDuplicateToken
+            ZwFlushInstructionCache
+            ZwFlushVirtualMemory
+            ZwInitiatePowerAction
+            ZwLoadKey
+            ZwNotifyChangeKey
+            ZwOpenThread
+            ZwPowerInformation
+            ZwPulseEvent
+            ZwQueryDefaultLocale
+            ZwQueryDefaultUILanguage
+            ZwQueryInformationProcess
+            ZwQueryInstallUILanguage
+            ZwQuerySection
+            ZwReplaceKey
+            ZwResetEvent
+            ZwRestoreKey
+            ZwSaveKey
+            ZwSetDefaultLocale
+            ZwSetDefaultUILanguage
+            ZwSetEvent
+            ZwSetInformationObject
+            ZwSetInformationProcess
+            ZwSetSecurityObject
+            ZwSetSystemTime
+            ZwTerminateProcess
+            ZwUnloadKey
+            ZwWaitForSingleObject
+            ZwWaitForMultipleObjects
+            ZwYieldExecution
+        Removed functions that is not exported in kernel mode:
+          CcZeroEndOfLastPage
+          RtlAllocateAndInitializeSid
+          ZwAcceptConnectPort
+          ZwCompleteConnectPort
+          ZwCreatePort
+          ZwCreateProcess
+          ZwCreateThread
+          ZwFlushBuffersFile
+          ZwGetContextThread
+          ZwImpersonateClientOfPort
+          ZwListenPort
+          ZwLockFile
+          ZwNotifyChangeDirectoryFile
+          ZwQueryInformationPort
+          ZwReadRequestData
+          ZwReplyPort
+          ZwReplyWaitReceivePort
+          ZwReplyWaitReplyPort
+          ZwRequestPort
+          ZwUnlockFile
+          ZwWriteRequestData
+
+    24. 2001-03-08
+        Corrected:
+          EPROCESS
+          ETHREAD
+          FAST_IO_POSSIBLE
+          QueryEa in EXTENDED_IO_STACK_LOCATION
+        Added:
+          Defines:
+            Some more flags for FileSystemAttributes
+          Data types:
+            EXCEPTION_REGISTRATION_RECORD
+            FILE_FS_FULL_SIZE_INFORMATION
+            FILE_FS_OBJECT_ID_INFORMATION
+            HANDLE_TABLE_ENTRY
+            IO_CLIENT_EXTENSION
+            PS_IMPERSONATION_INFORMATION
+            SetEa and SetQuota in EXTENDED_IO_STACK_LOCATION
+          Function prototypes:
+            IoPageRead
+            KeStackAttachProcess
+            KeUnstackDetachProcess
+            MmMapViewOfSection
+            RtlSelfRelativeToAbsoluteSD
+            SeCreateAccessState
+
+    23. 2001-01-29
+        Corrected:
+          FSCTL_GET_VOLUME_INFORMATION
+          FSCTL_READ_MFT_RECORD
+          HARDWARE_PTE
+          EPROCESS
+          ETHREAD
+          KAPC_STATE
+          KPROCESS
+          KTHREAD
+          MMSUPPORT
+        Added:
+          Data types:
+            KGDTENTRY
+            KIDTENTRY
+            MMSUPPORT_FLAGS
+
+    22. 2000-12-23
+        Corrected:
+          EPROCESS
+          KPROCESS
+        Added:
+          Data types:
+            HARDWARE_PTE
+            MMSUPPORT
+
+    21. 2000-12-12
+        Added:
+          Defines:
+            IO_TYPE_XXX
+            OB_TYPE_XXX
+            THREAD_STATE_XXX
+          Data types:
+            EPROCESS
+            ETHREAD
+            KAPC_STATE
+            KEVENT_PAIR
+            KPROCESS
+            KTHREAD
+            KQUEUE
+            SERVICE_DESCRIPTOR_TABLE
+            TEB
+
+    20. 2000-12-03
+        Added:
+          Data types:
+            OBJECT_TYPE
+          Function prototypes:
+            ObCreateObject
+            ObInsertObject
+            ObReferenceObjectByName
+
+    19. 2000-11-25
+        Removed a name from credits since the person want to be anonymous.
+
+    18. 2000-10-13
+        Corrected:
+          PsReferenceImpersonationToken
+        Added:
+          Defines:
+            FILE_PIPE_XXX
+            LPC_XXX
+            MAILSLOT_XXX
+            PORT_XXX
+            FSCTL_GET_VOLUME_INFORMATION
+            FSCTL_READ_MFT_RECORD
+            FSCTL_MAILSLOT_PEEK
+            FSCTL_PIPE_XXX
+          Data types:
+            PORT_INFORMATION_CLASS
+            BITMAP_DESCRIPTOR
+            FILE_MAILSLOT_XXX
+            FILE_PIPE_XXX
+            MAPPING_PAIR
+            GET_RETRIEVAL_DESCRIPTOR
+            LPC_XXX
+            MOVEFILE_DESCRIPTOR
+          Function prototypes:
+            InitializeMessageHeader
+            MmForceSectionClosed
+            ZwAcceptConnectPort
+            ZwCompleteConnectPort
+            ZwConnectPort
+            ZwCreateEvent
+            ZwCreatePort
+            ZwImpersonateClientOfPort
+            ZwListenPort
+            ZwQueryInformationPort
+            ZwReadRequestData
+            ZwReplyPort
+            ZwReplyWaitReceivePort
+            ZwReplyWaitReplyPort
+            ZwRequestPort
+            ZwRequestWaitReplyPort
+            ZwWriteRequestData
+
+    17. 2000-05-21
+        Added:
+          Function prototypes:
+            PsRevertToSelf
+            SeCreateClientSecurity
+            SeImpersonateClient
+            ZwDuplicateObject
+
+    16. 2000-03-28
+        Added:
+          Defines:
+            FILE_STORAGE_TYPE_XXX
+            FILE_VC_XXX
+            IO_CHECK_CREATE_PARAMETERS
+            IO_ATTACH_DEVICE
+            IO_ATTACH_DEVICE_API
+            IO_COMPLETION_XXX
+          Data types:
+            IO_COMPLETION_INFORMATION_CLASS
+            OBJECT_INFO_CLASS
+            SYSTEM_INFORMATION_CLASS
+            FILE_LOCK_ANCHOR
+            IO_COMPLETION_BASIC_INFORMATION
+            OBJECT_BASIC_INFO
+            OBJECT_NAME_INFO
+            OBJECT_PROTECTION_INFO
+            OBJECT_TYPE_INFO
+            OBJECT_ALL_TYPES_INFO
+            SYSTEM_CACHE_INFORMATION
+          Function prototypes:
+            FsRtlAllocatePool
+            FsRtlAllocatePoolWithQuota
+            FsRtlAllocatePoolWithQuotaTag
+            FsRtlAllocatePoolWithTag
+            FsRtlAreNamesEqual
+            FsRtlFastCheckLockForRead
+            FsRtlFastCheckLockForWrite
+            FsRtlMdlReadComplete
+            FsRtlMdlWriteComplete
+            FsRtlNormalizeNtstatus
+            RtlAllocateHeap
+            RtlCreateHeap
+            RtlDestroyHeap
+            RtlFreeHeap
+            RtlImageNtHeader
+            ZwQueryObject
+            ZwQuerySystemInformation
+            ZwSetSystemInformation
+
+    15. 2000-03-15
+        Corrected:
+          Renamed IoQueryFileVolumeInformation to IoQueryVolumeInformation
+        Comment on:
+          CcZeroEndOfLastPage
+
+    14. 2000-03-12
+        Corrected:
+          IoCreateFile
+        Added:
+          #if (_WIN32_WINNT < 0x0500)/#endif around stuff that is included in
+          the Windows 2000 DDK but is missing in the Windows NT 4.0 DDK.
+          ZwOpenEvent
+
+    13. 2000-02-08
+        Corrected:
+          PsReferenceImpersonationToken
+        Comment on:
+          RtlAllocateAndInitializeSid
+
+    12. 1999-10-18
+        Corrected:
+          FILE_COMPRESSION_INFORMATION
+        Added:
+          Defines:
+            ACCESS_ALLOWED_ACE_TYPE
+            ACCESS_DENIED_ACE_TYPE
+            SYSTEM_AUDIT_ACE_TYPE
+            SYSTEM_ALARM_ACE_TYPE
+            ANSI_DOS_STAR/QM/DOT
+            DOS_STAR/QM/DOT
+            FILE_EA_TYPE_XXX
+            FILE_NEED_EA
+            FILE_OPBATCH_BREAK_UNDERWAY
+            SECURITY_WORLD_SID_AUTHORITY
+            SECURITY_WORLD_RID
+          Data types:
+            POBJECT
+            FILE_STORAGE_TYPE
+            FILE_COMPLETION_INFORMATION
+            FILE_COPY_ON_WRITE_INFORMATION
+            FILE_FS_CONTROL_INFORMATION
+            FILE_GET_EA_INFORMATION
+            FILE_GET_QUOTA_INFORMATION
+            FILE_OBJECTID_INFORMATION
+            FILE_OLE_CLASSID_INFORMATION
+            FILE_OLE_ALL_INFORMATION
+            FILE_OLE_DIR_INFORMATION
+            FILE_OLE_INFORMATION
+            FILE_OLE_STATE_BITS_INFORMATION
+            FILE_QUOTA_INFORMATION
+          Function prototypes:
+            HalDisplayString
+            HalMakeBeep
+            IoGetRequestorProcess
+            ObQueryNameString
+            ProbeForWrite
+            RtlAbsoluteToSelfRelativeSD
+            RtlGetDaclSecurityDescriptor
+            RtlGetGroupSecurityDescriptor
+            RtlGetOwnerSecurityDescriptor
+            RtlInitializeSid
+            RtlSetGroupSecurityDescriptor
+            RtlSetOwnerSecurityDescriptor
+            RtlSetSaclSecurityDescriptor
+            ZwDeleteValueKey
+            ZwDisplayString
+            ZwQueryDirectoryObject
+
+    11. 1999-10-13
+        Corrected:
+          ZwOpenProcessToken
+          ZwOpenThreadToken
+        Added:
+          Function prototypes:
+            RtlAllocateAndInitializeSid
+            RtlCopySid
+            RtlEqualSid
+            RtlFillMemoryUlong
+            RtlIsNameLegalDOS8Dot3
+            RtlLengthRequiredSid
+            RtlLengthSid
+            RtlNtStatusToDosError
+            RtlSubAuthorityCountSid
+            RtlSubAuthoritySid
+            RtlValidSid
+
+    10. 1999-07-15
+        Corrected:
+          RtlConvertSidToUnicodeString
+        Added:
+          Externals:
+            FsRtlLegalAnsiCharacterArray
+            NtBuildNumber
+          Defines:
+            FSRTL_WILD_CHARACTER
+            FlagOn
+            FsRtlIsUnicodeCharacterWild
+          Structures:
+            FILE_ACCESS_INFORMATION
+            FILE_MODE_INFORMATION
+            GENERATE_NAME_CONTEXT
+          Function prototypes:
+            FsRtlDoesNameContainWildCards
+            FsRtlIsNameInExpression
+            IoSetInformation
+            RtlGenerate8dot3Name
+            ZwQuerySecurityObject
+
+    9. 1999-07-12
+       Corrected:
+         EXTENDED_IO_STACK_LOCATION
+         QueryDirectory in EXTENDED_IO_STACK_LOCATION
+         ZwCreateThread
+       Added:
+         Structures:
+           INITIAL_TEB
+         Function prototypes:
+           ZwQuerySymbolicLinkObject
+
+    8. 1999-06-07
+       Corrected:
+         ZwOpenProcessToken
+         ZwOpenThreadToken
+       Added:
+         Defines:
+           FILE_OPLOCK_BROKEN_TO_LEVEL_2
+           FILE_OPLOCK_BROKEN_TO_NONE
+           FILE_CASE_SENSITIVE_SEARCH
+           FILE_CASE_PRESERVED_NAMES
+           FILE_UNICODE_ON_DISK
+           FILE_PERSISTENT_ACLS
+           FILE_FILE_COMPRESSION
+           FILE_VOLUME_IS_COMPRESSED
+           FSRTL_FLAG_ACQUIRE_MAIN_RSRC_EX
+           FSRTL_FLAG_ACQUIRE_MAIN_RSRC_SH
+           IOCTL_REDIR_QUERY_PATH
+         Structures:
+           FILE_FS_LABEL_INFORMATION
+           PATHNAME_BUFFER
+         In IO_STACK_LOCATION:
+           FileSystemControl
+           LockControl
+           SetVolume
+         Function prototypes:
+           FsRtlCopyRead
+           FsRtlCopyWrite
+           IoVerifyVolume
+
+    7. 1999-06-05
+       Added:
+         defines for TOKEN_XXX
+         SID_NAME_USE
+         TOKEN_INFORMATION_CLASS
+         TOKEN_TYPE
+         FILE_FS_ATTRIBUTE_INFORMATION
+         FILE_FS_SIZE_INFORMATION
+         SID_IDENTIFIER_AUTHORITY
+         SID
+         SID_AND_ATTRIBUTES
+         TOKEN_CONTROL
+         TOKEN_DEFAULT_DACL
+         TOKEN_GROUPS
+         TOKEN_OWNER
+         TOKEN_PRIMARY_GROUP
+         TOKEN_PRIVILEGES
+         TOKEN_SOURCE
+         TOKEN_STATISTICS
+         TOKEN_USER
+         IoCreateFile
+         IoGetAttachedDevice
+         IoGetBaseFileSystemDeviceObject
+         PsReferenceImpersonationToken
+         PsReferencePrimaryToken
+         RtlConvertSidToUnicodeString
+         SeCaptureSubjectContext
+         SeMarkLogonSessionForTerminationNotification
+         SeRegisterLogonSessionTerminatedRoutine
+         SeUnregisterLogonSessionTerminatedRoutine
+         ZwOpenProcessToken
+         ZwOpenThreadToken
+         ZwQueryInformationToken
+
+    6. 1999-05-10
+       Corrected declarations of Zw functions.
+       Added:
+         ZwCancelIoFile
+         ZwDeleteFile
+         ZwFlushBuffersFile
+         ZwFsControlFile
+         ZwLockFile
+         ZwNotifyChangeDirectoryFile
+         ZwOpenFile
+         ZwQueryEaFile
+         ZwSetEaFile
+         ZwSetVolumeInformationFile
+         ZwUnlockFile
+
+    5. 1999-05-09
+       Added:
+         defines for FILE_ACTION_XXX and FILE_NOTIFY_XXX
+         FILE_FS_VOLUME_INFORMATION
+         RETRIEVAL_POINTERS_BUFFER
+         STARTING_VCN_INPUT_BUFFER
+         FsRtlNotifyFullReportChange
+
+    4. 1999-04-11
+       Corrected:
+         ZwCreateThread
+       Added:
+         define _GNU_NTIFS_
+
+    3. 1999-03-30
+       Added:
+         defines for MAP_XXX, MEM_XXX and SEC_XXX
+         FILE_BOTH_DIR_INFORMATION
+         FILE_DIRECTORY_INFORMATION
+         FILE_FULL_DIR_INFORMATION
+         FILE_NAMES_INFORMATION
+         FILE_NOTIFY_INFORMATION
+         FsRtlNotifyCleanup
+         KeAttachProcess
+         KeDetachProcess
+         MmCreateSection
+         ZwCreateProcess
+         ZwCreateThread
+         ZwDeviceIoControlFile
+         ZwGetContextThread
+         ZwLoadDriver
+         ZwOpenDirectoryObject
+         ZwOpenProcess
+         ZwOpenSymbolicLinkObject
+         ZwQueryDirectoryFile
+         ZwUnloadDriver
+
+    2. 1999-03-15
+       Added:
+         FILE_COMPRESSION_INFORMATION
+         FILE_STREAM_INFORMATION
+         FILE_LINK_INFORMATION
+         FILE_RENAME_INFORMATION
+         EXTENDED_IO_STACK_LOCATION
+         IoQueryFileInformation
+         IoQueryFileVolumeInformation
+         ZwQueryVolumeInformationFile
+       Moved include of ntddk.h to inside extern "C" block.
+
+    1. 1999-03-11
+       Initial release.
+*/
+
+#ifndef _NTIFS_
+#define _NTIFS_
+#define _GNU_NTIFS_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <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_
diff --git a/reactos/drivers/filesystems/ffs/inc/type.h b/reactos/drivers/filesystems/ffs/inc/type.h
new file mode 100644 (file)
index 0000000..ba39809
--- /dev/null
@@ -0,0 +1,22 @@
+/* type.h */
+
+typedef unsigned char     u_char;
+
+typedef __int8            int8_t;
+typedef unsigned __int8   uint8_t;
+typedef unsigned __int8   u_int8_t;
+
+typedef __int16           int16_t;
+typedef unsigned __int16  u_int16_t;
+typedef unsigned __int16  uint16_t;
+
+typedef __int32           int32_t;
+typedef unsigned __int32  u_int;
+typedef unsigned __int32  uint32_t;
+typedef unsigned __int32  u_int32_t;
+
+typedef __int64           int64_t;
+typedef unsigned __int64  uint64_t;
+typedef unsigned __int64  u_int64_t;
+
+typedef __int64           daddr_t;
diff --git a/reactos/drivers/filesystems/ffs/src/block.c b/reactos/drivers/filesystems/ffs/src/block.c
new file mode 100644 (file)
index 0000000..423842f
--- /dev/null
@@ -0,0 +1,681 @@
+/* 
+ * FFS File System Driver for Windows
+ *
+ * block.c
+ *
+ * 2004.5.6 ~
+ *
+ * Lee Jae-Hong, http://www.pyrasis.com
+ *
+ * See License.txt
+ *
+ */
+
+#include "ntifs.h"
+#include "ffsdrv.h"
+
+/* Globals */
+
+extern PFFS_GLOBAL FFSGlobal;
+
+
+/* Definitions */
+
+typedef struct _FFS_RW_CONTEXT {
+       PIRP        MasterIrp;
+       KEVENT      Event;
+       BOOLEAN     Wait;
+       LONG        Blocks;
+       ULONG       Length;
+} FFS_RW_CONTEXT, *PFFS_RW_CONTEXT;
+
+#ifdef _PREFAST_
+IO_COMPLETION_ROUTINE FFSReadWriteBlockSyncCompletionRoutine;
+IO_COMPLETION_ROUTINE FFSReadWriteBlockAsyncCompletionRoutine;
+IO_COMPLETION_ROUTINE FFSMediaEjectControlCompletion;
+#endif // _PREFAST_
+
+NTSTATUS NTAPI
+FFSReadWriteBlockSyncCompletionRoutine(
+       IN PDEVICE_OBJECT DeviceObject,
+       IN PIRP           Irp,
+       IN PVOID          Context);
+
+NTSTATUS NTAPI
+FFSReadWriteBlockAsyncCompletionRoutine(
+       IN PDEVICE_OBJECT DeviceObject,
+       IN PIRP           Irp,
+       IN PVOID          Context);
+
+NTSTATUS NTAPI
+FFSMediaEjectControlCompletion(
+       IN PDEVICE_OBJECT DeviceObject,
+       IN PIRP           Irp,
+       IN PVOID          Contxt);
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE, FFSLockUserBuffer)
+#pragma alloc_text(PAGE, FFSGetUserBuffer)
+#pragma alloc_text(PAGE, FFSReadSync)
+#pragma alloc_text(PAGE, FFSReadDisk)
+#pragma alloc_text(PAGE, FFSDiskIoControl)
+#pragma alloc_text(PAGE, FFSReadWriteBlocks)
+#pragma alloc_text(PAGE, FFSMediaEjectControl)
+#pragma alloc_text(PAGE, FFSDiskShutDown)
+#endif
+
+
+NTSTATUS
+FFSLockUserBuffer(
+       IN PIRP             Irp,
+       IN ULONG            Length,
+       IN LOCK_OPERATION   Operation)
+{
+       NTSTATUS Status;
+
+    PAGED_CODE();
+
+       ASSERT(Irp != NULL);
+
+       if (Irp->MdlAddress != NULL)
+       {
+               return STATUS_SUCCESS;
+       }
+
+       IoAllocateMdl(Irp->UserBuffer, Length, FALSE, FALSE, Irp);
+
+       if (Irp->MdlAddress == NULL)
+       {
+               return STATUS_INSUFFICIENT_RESOURCES;
+       }
+
+       _SEH2_TRY
+       {
+               MmProbeAndLockPages(Irp->MdlAddress, Irp->RequestorMode, Operation);
+
+               Status = STATUS_SUCCESS;
+       }
+       _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER)
+       {
+               IoFreeMdl(Irp->MdlAddress);
+
+               Irp->MdlAddress = NULL;
+
+               FFSBreakPoint();
+
+               Status = STATUS_INVALID_USER_BUFFER;
+       } _SEH2_END;
+
+       return Status;
+}
+
+
+PVOID
+FFSGetUserBuffer(
+       IN PIRP Irp)
+{
+    PAGED_CODE();
+
+       ASSERT(Irp != NULL);
+
+       if (Irp->MdlAddress)
+       {
+#if (_WIN32_WINNT >= 0x0500)
+               return MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
+#else
+               return MmGetSystemAddressForMdl(Irp->MdlAddress);
+#endif
+       }
+       else
+       {
+               return Irp->UserBuffer;
+       }
+}
+
+
+NTSTATUS NTAPI
+FFSReadWriteBlockSyncCompletionRoutine(
+       IN PDEVICE_OBJECT DeviceObject,
+       IN PIRP           Irp,
+       IN PVOID          Context)
+{
+       PFFS_RW_CONTEXT pContext = (PFFS_RW_CONTEXT)Context;
+
+       if (!NT_SUCCESS(Irp->IoStatus.Status))
+       {
+
+               pContext->MasterIrp->IoStatus = Irp->IoStatus;
+       }
+
+       IoFreeMdl(Irp->MdlAddress);
+       IoFreeIrp(Irp);
+
+       if (InterlockedDecrement(&pContext->Blocks) == 0)
+       {
+               pContext->MasterIrp->IoStatus.Information = 0;
+
+               if (NT_SUCCESS(pContext->MasterIrp->IoStatus.Status))
+               {
+                       pContext->MasterIrp->IoStatus.Information =
+                               pContext->Length;
+               }
+
+               KeSetEvent(&pContext->Event, 0, FALSE);
+       }
+
+       UNREFERENCED_PARAMETER(DeviceObject);
+
+       return STATUS_MORE_PROCESSING_REQUIRED;
+}
+
+NTSTATUS NTAPI
+FFSReadWriteBlockAsyncCompletionRoutine(
+       IN PDEVICE_OBJECT DeviceObject,
+       IN PIRP Irp,
+       IN PVOID Context)
+{
+       PFFS_RW_CONTEXT pContext = (PFFS_RW_CONTEXT)Context;
+
+       if (!NT_SUCCESS(Irp->IoStatus.Status))
+       {
+               pContext->MasterIrp->IoStatus = Irp->IoStatus;
+       }
+
+       if (InterlockedDecrement(&pContext->Blocks) == 0)
+       {
+               pContext->MasterIrp->IoStatus.Information = 0;
+
+               if (NT_SUCCESS(pContext->MasterIrp->IoStatus.Status))
+               {
+                       pContext->MasterIrp->IoStatus.Information =
+                               pContext->Length;
+               }
+
+               IoMarkIrpPending(pContext->MasterIrp);
+
+               ExFreePool(pContext);
+       }
+
+       UNREFERENCED_PARAMETER(DeviceObject);
+
+       return STATUS_SUCCESS;
+
+}
+
+NTSTATUS
+FFSReadWriteBlocks(
+       IN PFFS_IRP_CONTEXT IrpContext,
+       IN PFFS_VCB         Vcb,
+       IN PFFS_BDL         FFSBDL,
+       IN ULONG            Length,
+       IN ULONG            Count,
+       IN BOOLEAN          bVerify)
+{
+       PMDL                Mdl;
+       PIRP                Irp;
+       PIRP                MasterIrp = IrpContext->Irp;
+       PIO_STACK_LOCATION  IrpSp;
+       NTSTATUS            Status = STATUS_SUCCESS;
+       PFFS_RW_CONTEXT     pContext = NULL;
+       ULONG               i;
+       BOOLEAN             bBugCheck = FALSE;
+
+    PAGED_CODE();
+
+       ASSERT(MasterIrp);
+
+       _SEH2_TRY
+       {
+
+               pContext = ExAllocatePoolWithTag(NonPagedPool, sizeof(FFS_RW_CONTEXT), FFS_POOL_TAG);
+
+               if (!pContext)
+               {
+                       Status = STATUS_INSUFFICIENT_RESOURCES;
+                       _SEH2_LEAVE;
+               }
+
+               RtlZeroMemory(pContext, sizeof(FFS_RW_CONTEXT));
+
+               pContext->Wait = IrpContext->IsSynchronous;
+               pContext->MasterIrp = MasterIrp;
+               pContext->Blocks = Count;
+               pContext->Length = 0;
+
+               if (pContext->Wait)
+               {
+                       KeInitializeEvent(&(pContext->Event), NotificationEvent, FALSE);
+               }
+
+               for (i = 0; i < Count; i++)
+               {
+
+                       Irp = IoMakeAssociatedIrp(MasterIrp,
+                                       (CCHAR)(Vcb->TargetDeviceObject->StackSize + 1));
+                       if (!Irp)
+                       {
+                               Status = STATUS_INSUFFICIENT_RESOURCES;
+                               _SEH2_LEAVE;
+                       }
+
+                       Mdl = IoAllocateMdl((PCHAR)MasterIrp->UserBuffer +
+                                       FFSBDL[i].Offset,
+                                       FFSBDL[i].Length,
+                                       FALSE,
+                                       FALSE,
+                                       Irp);
+
+                       if (!Mdl)
+                       {
+                               Status = STATUS_INSUFFICIENT_RESOURCES;
+                               _SEH2_LEAVE;
+                       }
+
+                       IoBuildPartialMdl(MasterIrp->MdlAddress,
+                                       Mdl,
+                                       (PCHAR)MasterIrp->UserBuffer + FFSBDL[i].Offset,
+                                       FFSBDL[i].Length);
+
+                       IoSetNextIrpStackLocation(Irp);
+                       IrpSp = IoGetCurrentIrpStackLocation(Irp);
+
+
+                       IrpSp->MajorFunction = IrpContext->MajorFunction;
+                       IrpSp->Parameters.Read.Length = FFSBDL[i].Length;
+                       IrpSp->Parameters.Read.ByteOffset.QuadPart = FFSBDL[i].Lba;
+
+                       IoSetCompletionRoutine(Irp,
+                                       IrpContext->IsSynchronous ?
+                                       &FFSReadWriteBlockSyncCompletionRoutine :
+                                       &FFSReadWriteBlockAsyncCompletionRoutine,
+                                       (PVOID) pContext,
+                                       TRUE,
+                                       TRUE,
+                                       TRUE);
+
+                       IrpSp = IoGetNextIrpStackLocation(Irp);
+
+                       IrpSp->MajorFunction = IrpContext->MajorFunction;
+                       IrpSp->Parameters.Read.Length = FFSBDL[i].Length;
+                       IrpSp->Parameters.Read.ByteOffset.QuadPart = FFSBDL[i].Lba;
+
+                       if (bVerify)
+                       {
+                               SetFlag(IrpSp->Flags, SL_OVERRIDE_VERIFY_VOLUME);
+                       }
+
+                       FFSBDL[i].Irp = Irp;
+               }
+
+               MasterIrp->AssociatedIrp.IrpCount = Count;
+
+               if (IrpContext->IsSynchronous)
+               {
+                       MasterIrp->AssociatedIrp.IrpCount += 1;
+               }
+
+               pContext->Length = Length;
+
+               bBugCheck = TRUE;
+
+               for (i = 0; i < Count; i++)
+               {
+                       Status = IoCallDriver(Vcb->TargetDeviceObject,
+                                       FFSBDL[i].Irp);
+               }
+
+               if (IrpContext->IsSynchronous)
+               {
+                       KeWaitForSingleObject(&(pContext->Event),
+                                       Executive, KernelMode, FALSE, NULL);
+
+                       KeClearEvent(&(pContext->Event));
+               }
+       }
+
+       _SEH2_FINALLY
+       {
+               if (IrpContext->IsSynchronous)
+               {
+                       if (MasterIrp)
+                               Status = MasterIrp->IoStatus.Status;
+
+                       if (pContext)
+                               ExFreePool(pContext);
+
+               }
+               else
+               {
+                       IrpContext->Irp = NULL;
+                       Status = STATUS_PENDING;
+               }
+
+               if (_SEH2_AbnormalTermination())
+               {
+                       if (bBugCheck)
+                       {
+                               FFSBugCheck(FFS_BUGCHK_BLOCK, 0, 0, 0);
+                       }
+
+                       for (i = 0; i < Count; i++)
+                       {
+                               if (FFSBDL[i].Irp != NULL)
+                               {
+                                       if (FFSBDL[i].Irp->MdlAddress != NULL)
+                                       {
+                                               IoFreeMdl(FFSBDL[i].Irp->MdlAddress);
+                                       }
+
+                                       IoFreeIrp(FFSBDL[i].Irp);
+                               }
+                       }
+               }
+       } _SEH2_END;
+
+       return Status;
+}
+
+
+NTSTATUS
+FFSReadSync(
+       IN PFFS_VCB         Vcb,
+       IN ULONGLONG        Offset,
+       IN ULONG            Length,
+       OUT PVOID           Buffer,
+       IN BOOLEAN          bVerify)
+{
+       KEVENT          Event;
+       PIRP            Irp;
+       IO_STATUS_BLOCK IoStatus;
+       NTSTATUS        Status;
+
+    PAGED_CODE();
+
+       ASSERT(Vcb != NULL);
+       ASSERT(Vcb->TargetDeviceObject != NULL);
+       ASSERT(Buffer != NULL);
+
+       KeInitializeEvent(&Event, NotificationEvent, FALSE);
+
+       Irp = IoBuildSynchronousFsdRequest(
+                       IRP_MJ_READ,
+                       Vcb->TargetDeviceObject,
+                       Buffer,
+                       Length,
+                       (PLARGE_INTEGER)(&Offset),
+                       &Event,
+                       &IoStatus);
+
+       if (!Irp)
+       {
+               return STATUS_INSUFFICIENT_RESOURCES;
+       }
+
+       if (bVerify)
+       {
+               SetFlag(IoGetNextIrpStackLocation(Irp)->Flags, 
+                               SL_OVERRIDE_VERIFY_VOLUME);
+       }
+
+       Status = IoCallDriver(Vcb->TargetDeviceObject, Irp);
+
+       if (Status == STATUS_PENDING)
+       {
+               KeWaitForSingleObject(
+                               &Event,
+                               Suspended,
+                               KernelMode,
+                               FALSE,
+                               NULL);
+
+               Status = IoStatus.Status;
+       }
+
+       return Status;
+}
+
+
+NTSTATUS
+FFSReadDisk(
+       IN PFFS_VCB    Vcb,
+       IN ULONGLONG   Offset,
+       IN ULONG       Size,
+       IN PVOID       Buffer,
+       IN BOOLEAN     bVerify)
+{
+       NTSTATUS    Status;
+       PUCHAR      Buf;
+       ULONG       Length;
+       ULONGLONG   Lba;
+
+    PAGED_CODE();
+
+       Lba = Offset & (~((ULONGLONG)SECTOR_SIZE - 1));
+       Length = (ULONG)(Size + Offset + SECTOR_SIZE - 1 - Lba) &
+               (~((ULONG)SECTOR_SIZE - 1));
+
+       Buf = ExAllocatePoolWithTag(PagedPool, Length, FFS_POOL_TAG);
+       if (!Buf)
+       {
+               FFSPrint((DBG_ERROR, "FFSReadDisk: no enough memory.\n"));
+               Status = STATUS_INSUFFICIENT_RESOURCES;
+
+               goto errorout;
+       }
+
+       Status = FFSReadSync(Vcb, 
+                       Lba,
+                       Length,
+                       Buf,
+                       FALSE);
+
+       if (!NT_SUCCESS(Status))
+       {
+               FFSPrint((DBG_ERROR, "FFSReadDisk: Read Block Device error.\n"));
+
+               goto errorout;
+       }
+
+       RtlCopyMemory(Buffer, &Buf[Offset - Lba], Size);
+
+errorout:
+
+       if (Buf)
+               ExFreePool(Buf);
+
+       return Status;
+}
+
+
+NTSTATUS 
+FFSDiskIoControl(
+       IN PDEVICE_OBJECT   DeviceObject,
+       IN ULONG            IoctlCode,
+       IN PVOID            InputBuffer,
+       IN ULONG            InputBufferSize,
+       IN OUT PVOID        OutputBuffer,
+       IN OUT PULONG       OutputBufferSize)
+{
+       ULONG           OutBufferSize = 0;
+       KEVENT          Event;
+       PIRP            Irp;
+       IO_STATUS_BLOCK IoStatus;
+       NTSTATUS        Status;
+
+    PAGED_CODE();
+
+       ASSERT(DeviceObject != NULL);
+
+       if (OutputBufferSize)
+       {
+               OutBufferSize = *OutputBufferSize;
+       }
+
+       KeInitializeEvent(&Event, NotificationEvent, FALSE);
+
+       Irp = IoBuildDeviceIoControlRequest(
+                       IoctlCode,
+                       DeviceObject,
+                       InputBuffer,
+                       InputBufferSize,
+                       OutputBuffer,
+                       OutBufferSize,
+                       FALSE,
+                       &Event,
+                       &IoStatus);
+
+       if (Irp == NULL)
+       {
+               FFSPrint((DBG_ERROR, "FFSDiskIoControl: Building IRQ error!\n"));
+               return STATUS_INSUFFICIENT_RESOURCES;
+       }
+
+       Status = IoCallDriver(DeviceObject, Irp);
+
+       if (Status == STATUS_PENDING)
+       {
+               KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
+               Status = IoStatus.Status;
+       }
+
+       if (OutputBufferSize)
+       {
+               *OutputBufferSize = (ULONG) IoStatus.Information;
+       }
+
+       return Status;
+}
+
+
+NTSTATUS NTAPI
+FFSMediaEjectControlCompletion(
+       IN PDEVICE_OBJECT DeviceObject,
+       IN PIRP           Irp,
+       IN PVOID          Contxt)
+{
+       PKEVENT Event = (PKEVENT)Contxt;
+
+       KeSetEvent(Event, 0, FALSE);
+
+       UNREFERENCED_PARAMETER(DeviceObject);
+
+       return STATUS_SUCCESS;
+}
+
+
+__drv_mustHoldCriticalRegion
+VOID
+FFSMediaEjectControl(
+       IN PFFS_IRP_CONTEXT IrpContext,
+       IN PFFS_VCB         Vcb,
+       IN BOOLEAN          bPrevent)
+{
+       PIRP                    Irp;
+       KEVENT                  Event;
+       NTSTATUS                Status;
+       PREVENT_MEDIA_REMOVAL   Prevent;
+       IO_STATUS_BLOCK         IoStatus;
+
+    PAGED_CODE();
+
+       ExAcquireResourceExclusiveLite(
+                       &Vcb->MainResource,
+                       TRUE);
+
+       if (bPrevent != IsFlagOn(Vcb->Flags, VCB_REMOVAL_PREVENTED))
+       {
+               if (bPrevent)
+               {
+                       SetFlag(Vcb->Flags, VCB_REMOVAL_PREVENTED);
+               }
+               else
+               {
+                       ClearFlag(Vcb->Flags, VCB_REMOVAL_PREVENTED);
+               }
+       }
+
+       ExReleaseResourceForThreadLite(
+                       &Vcb->MainResource,
+                       ExGetCurrentResourceThread());
+
+       Prevent.PreventMediaRemoval = bPrevent;
+
+       KeInitializeEvent(&Event, NotificationEvent, FALSE);
+
+       Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_MEDIA_REMOVAL,
+                       Vcb->TargetDeviceObject,
+                       &Prevent,
+                       sizeof(PREVENT_MEDIA_REMOVAL),
+                       NULL,
+                       0,
+                       FALSE,
+                       NULL,
+                       &IoStatus);
+
+       if (Irp != NULL)
+       {
+               IoSetCompletionRoutine(Irp,
+                               FFSMediaEjectControlCompletion,
+                               &Event,
+                               TRUE,
+                               TRUE,
+                               TRUE);
+
+               Status = IoCallDriver(Vcb->TargetDeviceObject, Irp);
+
+               if (Status == STATUS_PENDING)
+               {
+                       Status = KeWaitForSingleObject(&Event,
+                                       Executive,
+                                       KernelMode,
+                                       FALSE,
+                                       NULL);
+               }
+       }
+}
+
+
+NTSTATUS
+FFSDiskShutDown(
+       PFFS_VCB Vcb)
+{
+       PIRP                Irp;
+       KEVENT              Event;
+       NTSTATUS            Status;
+       IO_STATUS_BLOCK     IoStatus;
+
+    PAGED_CODE();
+
+       KeInitializeEvent(&Event, NotificationEvent, FALSE);
+
+       Irp = IoBuildSynchronousFsdRequest(IRP_MJ_SHUTDOWN,
+                       Vcb->TargetDeviceObject,
+                       NULL,
+                       0,
+                       NULL,
+                       &Event,
+                       &IoStatus);
+
+       if (Irp)
+       {
+               Status = IoCallDriver(Vcb->TargetDeviceObject, Irp);
+
+               if (Status == STATUS_PENDING)
+               {
+                       KeWaitForSingleObject(&Event,
+                                       Executive,
+                                       KernelMode,
+                                       FALSE,
+                                       NULL);
+
+                       Status = IoStatus.Status;
+               }
+       }
+       else
+       {
+               Status = IoStatus.Status;
+       }
+
+       return Status;
+}
diff --git a/reactos/drivers/filesystems/ffs/src/cleanup.c b/reactos/drivers/filesystems/ffs/src/cleanup.c
new file mode 100644 (file)
index 0000000..c3be1ed
--- /dev/null
@@ -0,0 +1,380 @@
+/* 
+ * FFS File System Driver for Windows
+ *
+ * cleanup.c
+ *
+ * 2004.5.6 ~
+ *
+ * Lee Jae-Hong, http://www.pyrasis.com
+ *
+ * See License.txt
+ *
+ */
+
+#include "ntifs.h"
+#include "ffsdrv.h"
+
+/* Globals */
+
+extern PFFS_GLOBAL FFSGlobal;
+
+/* Definitions */
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE, FFSCleanup)
+#endif
+
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSCleanup(
+       IN PFFS_IRP_CONTEXT IrpContext)
+{
+       PDEVICE_OBJECT  DeviceObject;
+       NTSTATUS        Status = STATUS_SUCCESS;
+       PFFS_VCB        Vcb = 0;
+       BOOLEAN         VcbResourceAcquired = FALSE;
+       PFILE_OBJECT    FileObject;
+       PFFS_FCB        Fcb = 0;
+       BOOLEAN         FcbResourceAcquired = FALSE;
+       BOOLEAN         FcbPagingIoAcquired = FALSE;
+       PFFS_CCB        Ccb;
+       PIRP            Irp;
+
+    PAGED_CODE();
+
+       _SEH2_TRY
+       {
+               ASSERT(IrpContext != NULL);
+
+               ASSERT((IrpContext->Identifier.Type == FFSICX) &&
+                       (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
+
+               DeviceObject = IrpContext->DeviceObject;
+               
+               if (DeviceObject == FFSGlobal->DeviceObject)
+               {
+                       Status = STATUS_SUCCESS;
+                       _SEH2_LEAVE;
+               }
+               
+               Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;
+
+               ASSERT(Vcb != NULL);
+
+               ASSERT((Vcb->Identifier.Type == FFSVCB) &&
+                       (Vcb->Identifier.Size == sizeof(FFS_VCB)));
+
+               if (!IsFlagOn(Vcb->Flags, VCB_INITIALIZED))
+               {
+                       Status = STATUS_SUCCESS;
+                       _SEH2_LEAVE;
+               }
+
+#ifdef _MSC_VER
+#pragma prefast( suppress: 28137, "by design" )
+#endif
+               if (!ExAcquireResourceExclusiveLite(
+                               &Vcb->MainResource,
+                               IrpContext->IsSynchronous))
+               {
+                       Status = STATUS_PENDING;
+                       _SEH2_LEAVE;
+               }
+
+               VcbResourceAcquired = TRUE;
+
+               FileObject = IrpContext->FileObject;
+
+               Fcb = (PFFS_FCB)FileObject->FsContext;
+
+               if (!Fcb)
+               {
+                       Status = STATUS_SUCCESS;
+                       _SEH2_LEAVE;
+               }
+
+               if (Fcb->Identifier.Type == FFSVCB)
+               {
+                       if (IsFlagOn(Vcb->Flags, VCB_VOLUME_LOCKED) &&
+                               (Vcb->LockFile == FileObject))
+                       {
+                               ClearFlag(Vcb->Flags, VCB_VOLUME_LOCKED);
+                               Vcb->LockFile = NULL;
+
+                               FFSClearVpbFlag(Vcb->Vpb, VPB_LOCKED);
+                       }
+
+                       Vcb->OpenHandleCount--;
+
+                       if (!Vcb->OpenHandleCount)
+                       {
+                               IoRemoveShareAccess(FileObject, &Vcb->ShareAccess);
+                       }
+
+                       Status = STATUS_SUCCESS;
+                       _SEH2_LEAVE;
+               }
+
+               ASSERT((Fcb->Identifier.Type == FFSFCB) &&
+                       (Fcb->Identifier.Size == sizeof(FFS_FCB)));
+
+/*
+               if (!IsFlagOn(Vcb->Flags, VCB_READ_ONLY) &&
+                        !IsFlagOn(Fcb->Flags, FCB_PAGE_FILE))
+*/
+               {
+#ifdef _MSC_VER
+#pragma prefast( suppress: 28137, "by design" )
+#endif
+                       if (!ExAcquireResourceExclusiveLite(
+                                       &Fcb->MainResource,
+                                       IrpContext->IsSynchronous))
+                       {
+                               Status = STATUS_PENDING;
+                               _SEH2_LEAVE;
+                       }
+
+                       FcbResourceAcquired = TRUE;
+               }
+               
+               Ccb = (PFFS_CCB)FileObject->FsContext2;
+
+               if (!Ccb)
+               {
+                       Status = STATUS_SUCCESS;
+                       _SEH2_LEAVE;
+               }
+
+               if (IsFlagOn(FileObject->Flags, FO_CLEANUP_COMPLETE))
+               {
+                       if (IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED) &&
+                                IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK) &&
+                                !IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED))
+                       {
+                               Status = FFSFlushFile(Fcb);
+                       }
+
+                       _SEH2_LEAVE;
+               }
+               
+               ASSERT((Ccb->Identifier.Type == FFSCCB) &&
+                       (Ccb->Identifier.Size == sizeof(FFS_CCB)));             
+               Irp = IrpContext->Irp;
+
+               Fcb->OpenHandleCount--;
+
+               if (!IsFlagOn(FileObject->Flags, FO_CACHE_SUPPORTED))
+               {
+                       Fcb->NonCachedOpenCount--;
+               }
+
+               Vcb->OpenFileHandleCount--;
+
+               if (IsFlagOn(Fcb->Flags, FCB_DELETE_ON_CLOSE))
+               {
+                       SetFlag(Fcb->Flags, FCB_DELETE_PENDING);
+
+                       if (IsDirectory(Fcb))
+                       {
+                               FsRtlNotifyFullChangeDirectory(
+                                                                                       Vcb->NotifySync,
+                                                                                       &Vcb->NotifyList,
+                                                                                       Fcb,
+                                                                                       NULL,
+                                                                                       FALSE,
+                                                                                       FALSE,
+                                                                                       0,
+                                                                                       NULL,
+                                                                                       NULL,
+                                                                                       NULL);
+                       }
+               }
+
+               if (IsDirectory(Fcb))
+               {
+                       FsRtlNotifyCleanup(
+                               Vcb->NotifySync,
+                               &Vcb->NotifyList,
+                               Ccb);
+               }
+               else
+               {
+                       //
+                       // Drop any byte range locks this process may have on the file.
+                       //
+                       FsRtlFastUnlockAll(
+                               &Fcb->FileLockAnchor,
+                               FileObject,
+                               IoGetRequestorProcess(Irp),
+                               NULL);
+
+                       //
+                       // If there are no byte range locks owned by other processes on the
+                       // file the fast I/O read/write functions doesn't have to check for
+                       // locks so we set IsFastIoPossible to FastIoIsPossible again.
+                       //
+                       if (!FsRtlGetNextFileLock(&Fcb->FileLockAnchor, TRUE))
+                       {
+                               if (Fcb->Header.IsFastIoPossible != FastIoIsPossible)
+                               {
+                                       FFSPrint((
+                                               DBG_INFO, ": %-16.16s %-31s %s\n",
+                                               FFSGetCurrentProcessName(),
+                                               "FastIoIsPossible",
+                                               Fcb->AnsiFileName.Buffer));
+
+                                       Fcb->Header.IsFastIoPossible = FastIoIsPossible;
+                               }
+                       }
+               }
+
+               if (IsFlagOn(FileObject->Flags, FO_CACHE_SUPPORTED) &&
+                        (Fcb->NonCachedOpenCount != 0) &&
+                        (Fcb->NonCachedOpenCount == Fcb->ReferenceCount) &&
+                        (Fcb->SectionObject.DataSectionObject != NULL))
+               {
+
+                       if(!IsFlagOn(Vcb->Flags, VCB_READ_ONLY) &&
+                               !IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED))
+                       {
+                               CcFlushCache(&Fcb->SectionObject, NULL, 0, NULL);
+                       }
+
+                       ExAcquireResourceExclusiveLite(&(Fcb->PagingIoResource), TRUE);
+                       ExReleaseResourceLite(&(Fcb->PagingIoResource));
+
+                       CcPurgeCacheSection(&Fcb->SectionObject,
+                                                               NULL,
+                                                               0,
+                                                               FALSE);
+               }
+
+#if !FFS_READ_ONLY
+               if (Fcb->OpenHandleCount == 0)
+               {
+                       if (IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING))
+                       {
+                               BOOLEAN  bDeleted = FALSE;
+
+                               //
+                               //  Have to delete this file...
+                               //
+#ifdef _MSC_VER
+#pragma prefast( suppress: 28137, "by design" )
+#endif
+                               if (!ExAcquireResourceExclusiveLite(
+                                                &Fcb->PagingIoResource,
+                                                IrpContext->IsSynchronous))
+                               {
+                                       Status = STATUS_PENDING;
+                                       _SEH2_LEAVE;
+                               }
+
+                               FcbPagingIoAcquired = TRUE;
+
+                               bDeleted = FFSDeleteFile(IrpContext, Vcb, Fcb);
+
+                               if (bDeleted)
+                               {
+                                       if (IsDirectory(Fcb))
+                                       {
+                                               FFSNotifyReportChange(IrpContext, Vcb, Fcb,
+                                                                                               FILE_NOTIFY_CHANGE_DIR_NAME,
+                                                                                               FILE_ACTION_REMOVED);
+                                       }
+                                       else
+                                       {
+                                               FFSNotifyReportChange(IrpContext, Vcb, Fcb,
+                                                                                               FILE_NOTIFY_CHANGE_FILE_NAME,
+                                                                                               FILE_ACTION_REMOVED);
+                                       }
+                               }
+
+                               if (FcbPagingIoAcquired)
+                               {
+                                       ExReleaseResourceForThreadLite(
+                                               &Fcb->PagingIoResource,
+                                               ExGetCurrentResourceThread());
+
+                                       FcbPagingIoAcquired = FALSE;
+                               }
+
+/*
+                               if (bDeleted)
+                               {
+                                       FFSPurgeFile(Fcb, FALSE);
+                               }
+*/
+                       }
+               }
+#endif // !FFS_READ_ONLY
+
+               if (!IsDirectory(Fcb) && FileObject->PrivateCacheMap)
+               {
+                       FFSPrint((DBG_INFO, "FFSCleanup: CcUninitializeCacheMap is called for %s.\n",
+                                                                 Fcb->AnsiFileName.Buffer));
+
+                       CcUninitializeCacheMap(
+                                       FileObject,
+                                       (PLARGE_INTEGER)(&(Fcb->Header.FileSize)),
+                                       NULL);
+               }
+
+               if (!Fcb->OpenHandleCount)
+               {
+                       IoRemoveShareAccess(FileObject, &Fcb->ShareAccess);
+               }
+
+               FFSPrint((DBG_INFO, "FFSCleanup: OpenCount: %u ReferCount: %u %s\n",
+                       Fcb->OpenHandleCount, Fcb->ReferenceCount, Fcb->AnsiFileName.Buffer));
+
+               Status = STATUS_SUCCESS;
+
+               if (FileObject)
+               {
+                       SetFlag(FileObject->Flags, FO_CLEANUP_COMPLETE);
+               }
+       }
+
+       _SEH2_FINALLY
+       {
+          
+               if (FcbPagingIoAcquired)
+               {
+                       ExReleaseResourceForThreadLite(
+                               &Fcb->PagingIoResource,
+                               ExGetCurrentResourceThread());
+               }
+
+               if (FcbResourceAcquired)
+               {
+                       ExReleaseResourceForThreadLite(
+                               &Fcb->MainResource,
+                               ExGetCurrentResourceThread());
+               }
+
+               if (VcbResourceAcquired)
+               {
+                       ExReleaseResourceForThreadLite(
+                               &Vcb->MainResource,
+                               ExGetCurrentResourceThread());
+               }
+
+               if (!IrpContext->ExceptionInProgress)
+               {
+                       if (Status == STATUS_PENDING)
+                       {
+                               FFSQueueRequest(IrpContext);
+                       }
+                       else
+                       {
+                               IrpContext->Irp->IoStatus.Status = Status;
+
+                               FFSCompleteIrpContext(IrpContext, Status);
+                       }
+               }
+       } _SEH2_END;
+
+       return Status;
+}
diff --git a/reactos/drivers/filesystems/ffs/src/close.c b/reactos/drivers/filesystems/ffs/src/close.c
new file mode 100644 (file)
index 0000000..50ace27
--- /dev/null
@@ -0,0 +1,342 @@
+/* 
+ * FFS File System Driver for Windows
+ *
+ * close.c
+ *
+ * 2004.5.6 ~
+ *
+ * Lee Jae-Hong, http://www.pyrasis.com
+ *
+ * See License.txt
+ *
+ */
+
+#include "ntifs.h"
+#include "ffsdrv.h"
+
+/* Globals */
+
+extern PFFS_GLOBAL FFSGlobal;
+
+/* Definitions */
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE, FFSClose)
+#pragma alloc_text(PAGE, FFSQueueCloseRequest)
+#pragma alloc_text(PAGE, FFSDeQueueCloseRequest)
+#endif
+
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSClose(
+       IN PFFS_IRP_CONTEXT IrpContext)
+{
+       PDEVICE_OBJECT  DeviceObject;
+       NTSTATUS        Status = STATUS_SUCCESS;
+       PFFS_VCB        Vcb = 0;
+       BOOLEAN         VcbResourceAcquired = FALSE;
+       PFILE_OBJECT    FileObject;
+       PFFS_FCB        Fcb = 0;
+       BOOLEAN         FcbResourceAcquired = FALSE;
+       PFFS_CCB        Ccb;
+       BOOLEAN         FreeVcb = FALSE;
+
+    PAGED_CODE();
+
+       _SEH2_TRY
+       {
+               ASSERT(IrpContext != NULL);
+
+               ASSERT((IrpContext->Identifier.Type == FFSICX) &&
+                               (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
+
+               DeviceObject = IrpContext->DeviceObject;
+
+               if (DeviceObject == FFSGlobal->DeviceObject)
+               {
+                       Status = STATUS_SUCCESS;
+                       _SEH2_LEAVE;
+               }
+
+               Vcb = (PFFS_VCB) DeviceObject->DeviceExtension;
+
+               ASSERT(Vcb != NULL);
+
+               ASSERT((Vcb->Identifier.Type == FFSVCB) &&
+                               (Vcb->Identifier.Size == sizeof(FFS_VCB)));
+
+               ASSERT(IsMounted(Vcb));
+
+               if (!ExAcquireResourceExclusiveLite(
+                                       &Vcb->MainResource,
+                                       IrpContext->IsSynchronous))
+               {
+                       FFSPrint((DBG_INFO, "FFSClose: PENDING ... Vcb: %xh/%xh\n",
+                                               Vcb->OpenFileHandleCount, Vcb->ReferenceCount));
+
+                       Status = STATUS_PENDING;
+                       _SEH2_LEAVE;
+               }
+
+               VcbResourceAcquired = TRUE;
+
+               FileObject = IrpContext->FileObject;
+
+               if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DELAY_CLOSE))
+               {
+                       Fcb = IrpContext->Fcb;
+                       Ccb = IrpContext->Ccb;
+               }
+               else
+               {
+                       Fcb = (PFFS_FCB)FileObject->FsContext;
+
+                       if (!Fcb)
+                       {
+                               Status = STATUS_SUCCESS;
+                               _SEH2_LEAVE;
+                       }
+
+                       ASSERT(Fcb != NULL);
+
+                       Ccb = (PFFS_CCB)FileObject->FsContext2;
+               }
+
+               if (Fcb->Identifier.Type == FFSVCB)
+               {
+                       Vcb->ReferenceCount--;
+
+                       if (!Vcb->ReferenceCount && FlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING))
+                       {
+                               FreeVcb = TRUE;
+                       }
+
+                       if (Ccb)
+                       {
+                               FFSFreeCcb(Ccb);
+                               if (FileObject)
+                               {
+                                       FileObject->FsContext2 = Ccb = NULL;
+                               }
+                       }
+
+                       Status = STATUS_SUCCESS;
+
+                       _SEH2_LEAVE;
+               }
+
+               if (Fcb->Identifier.Type != FFSFCB || Fcb->Identifier.Size != sizeof(FFS_FCB))
+               {
+#if DBG
+                       FFSPrint((DBG_ERROR, "FFSClose: Strange IRP_MJ_CLOSE by system!\n"));
+                       ExAcquireResourceExclusiveLite(
+                                       &FFSGlobal->CountResource,
+                                       TRUE);
+
+                       FFSGlobal->IRPCloseCount++;
+
+                       ExReleaseResourceForThreadLite(
+                                       &FFSGlobal->CountResource,
+                                       ExGetCurrentResourceThread());
+#endif
+                       _SEH2_LEAVE;
+               }
+
+               ASSERT((Fcb->Identifier.Type == FFSFCB) &&
+                               (Fcb->Identifier.Size == sizeof(FFS_FCB)));
+
+               /*        
+                         if ((!IsFlagOn(Vcb->Flags, VCB_READ_ONLY)) && 
+                         (!IsFlagOn(Fcb->Flags, FCB_PAGE_FILE)))
+                         */
+               {
+                       if (!ExAcquireResourceExclusiveLite(
+                                               &Fcb->MainResource,
+                                               IrpContext->IsSynchronous))
+                       {
+                               Status = STATUS_PENDING;
+                               _SEH2_LEAVE;
+                       }
+
+                       FcbResourceAcquired = TRUE;
+               }
+
+               if (!Ccb)
+               {
+                       Status = STATUS_SUCCESS;
+                       _SEH2_LEAVE;
+               }
+
+               ASSERT((Ccb->Identifier.Type == FFSCCB) &&
+                               (Ccb->Identifier.Size == sizeof(FFS_CCB)));
+
+               Fcb->ReferenceCount--;
+               Vcb->ReferenceCount--;
+
+               if (!Vcb->ReferenceCount && IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING))
+               {
+                       FreeVcb = TRUE;
+               }
+
+               FFSPrint((DBG_INFO, "FFSClose: OpenHandleCount: %u ReferenceCount: %u %s\n",
+                                       Fcb->OpenHandleCount, Fcb->ReferenceCount, Fcb->AnsiFileName.Buffer));
+
+               if (Ccb)
+               {
+                       FFSFreeCcb(Ccb);
+
+                       if (FileObject)
+                       {
+                               FileObject->FsContext2 = Ccb = NULL;
+                       }
+               }
+
+               if (!Fcb->ReferenceCount)
+               {
+                       //
+                       // Remove Fcb from Vcb->FcbList ...
+                       //
+
+                       RemoveEntryList(&Fcb->Next);
+
+                       FFSFreeFcb(Fcb);
+
+                       FcbResourceAcquired = FALSE;
+               }
+
+               Status = STATUS_SUCCESS;
+       }
+
+       _SEH2_FINALLY
+       {
+               if (FcbResourceAcquired)
+               {
+                       ExReleaseResourceForThreadLite(
+                                       &Fcb->MainResource,
+                                       ExGetCurrentResourceThread());
+               }
+
+               if (VcbResourceAcquired)
+               {
+                       ExReleaseResourceForThreadLite(
+                                       &Vcb->MainResource,
+                                       ExGetCurrentResourceThread());
+               }
+
+               if (!IrpContext->ExceptionInProgress)
+               {
+                       if (Status == STATUS_PENDING)
+                       {
+                               FFSQueueCloseRequest(IrpContext);
+#if 0
+/*
+                               Status = STATUS_SUCCESS;
+
+                               if (IrpContext->Irp != NULL)
+                               {
+                                       IrpContext->Irp->IoStatus.Status = Status;
+
+                                       FFSCompleteRequest(
+                                                       IrpContext->Irp,
+                                                       (BOOLEAN)!IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED),
+                                                       (CCHAR)
+                                                       (NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT));
+
+                                       IrpContext->Irp = NULL;
+                               }
+*/
+#endif
+                       }
+                       else
+                       {
+                               FFSCompleteIrpContext(IrpContext, Status);
+
+                               if (FreeVcb)
+                               {
+                                       ExAcquireResourceExclusiveLite(
+                                                       &FFSGlobal->Resource, TRUE);
+
+                                       FFSClearVpbFlag(Vcb->Vpb, VPB_MOUNTED);
+
+                                       FFSRemoveVcb(Vcb);
+
+                                       ExReleaseResourceForThreadLite(
+                                                       &FFSGlobal->Resource,
+                                                       ExGetCurrentResourceThread());
+
+                                       FFSFreeVcb(Vcb);
+                               }
+                       }
+               }
+       } _SEH2_END;
+
+       return Status;
+}
+
+
+VOID
+FFSQueueCloseRequest(
+       IN PFFS_IRP_CONTEXT IrpContext)
+{
+    PAGED_CODE();
+
+       ASSERT(IrpContext);
+
+       ASSERT((IrpContext->Identifier.Type == FFSICX) &&
+                       (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
+
+       if (!IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DELAY_CLOSE))
+       {
+               SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DELAY_CLOSE);
+
+               IrpContext->Fcb = (PFFS_FCB)IrpContext->FileObject->FsContext;
+               IrpContext->Ccb = (PFFS_CCB)IrpContext->FileObject->FsContext2;
+
+               IrpContext->FileObject = NULL;
+       }
+
+       // IsSynchronous means we can block (so we don't requeue it)
+       IrpContext->IsSynchronous = TRUE;
+
+       ExInitializeWorkItem(
+                       &IrpContext->WorkQueueItem,
+                       FFSDeQueueCloseRequest,
+                       IrpContext);
+
+       ExQueueWorkItem(&IrpContext->WorkQueueItem, CriticalWorkQueue);
+}
+
+
+VOID NTAPI
+FFSDeQueueCloseRequest(
+       IN PVOID Context)
+{
+       PFFS_IRP_CONTEXT IrpContext;
+
+    PAGED_CODE();
+
+       IrpContext = (PFFS_IRP_CONTEXT) Context;
+
+       ASSERT(IrpContext);
+
+       ASSERT((IrpContext->Identifier.Type == FFSICX) &&
+                       (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
+
+       _SEH2_TRY
+       {
+               _SEH2_TRY
+               {
+                       FsRtlEnterFileSystem();
+                       FFSClose(IrpContext);
+               }
+               _SEH2_EXCEPT (FFSExceptionFilter(IrpContext, _SEH2_GetExceptionInformation()))
+               {
+                       FFSExceptionHandler(IrpContext);
+               } _SEH2_END;
+       }
+       _SEH2_FINALLY
+       {
+               FsRtlExitFileSystem();
+       } _SEH2_END;
+}
diff --git a/reactos/drivers/filesystems/ffs/src/cmcb.c b/reactos/drivers/filesystems/ffs/src/cmcb.c
new file mode 100644 (file)
index 0000000..b8e90a9
--- /dev/null
@@ -0,0 +1,218 @@
+/* 
+ * FFS File System Driver for Windows
+ *
+ * cmcb.c
+ *
+ * 2004.5.6 ~
+ *
+ * Lee Jae-Hong, http://www.pyrasis.com
+ *
+ * See License.txt
+ *
+ */
+
+#include "ntifs.h"
+#include "ffsdrv.h"
+
+/* Globals */
+
+extern PFFS_GLOBAL FFSGlobal;
+
+/* Definitions */
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE, FFSAcquireForLazyWrite)
+#pragma alloc_text(PAGE, FFSReleaseFromLazyWrite)
+#pragma alloc_text(PAGE, FFSAcquireForReadAhead)
+#pragma alloc_text(PAGE, FFSReleaseFromReadAhead)
+#pragma alloc_text(PAGE, FFSNoOpAcquire)
+#pragma alloc_text(PAGE, FFSNoOpRelease)
+#endif
+
+
+__drv_mustHoldCriticalRegion
+BOOLEAN NTAPI
+FFSAcquireForLazyWrite(
+       IN PVOID    Context,
+       IN BOOLEAN  Wait)
+{
+       //
+       // On a readonly filesystem this function still has to exist but it
+       // doesn't need to do anything.
+
+       PFFS_FCB     Fcb;
+
+    PAGED_CODE();
+
+       Fcb = (PFFS_FCB)Context;
+
+       ASSERT(Fcb != NULL);
+
+       ASSERT((Fcb->Identifier.Type == FFSFCB) &&
+                       (Fcb->Identifier.Size == sizeof(FFS_FCB)));
+
+       FFSPrint((DBG_INFO, "FFSAcquireForLazyWrite: %s %s %s\n",
+                               FFSGetCurrentProcessName(),
+                               "ACQUIRE_FOR_LAZY_WRITE",
+                               Fcb->AnsiFileName.Buffer));
+
+
+       if (!IsFlagOn(Fcb->Vcb->Flags, VCB_READ_ONLY))
+       {
+               FFSPrint((DBG_INFO, "FFSAcquireForLazyWrite: Inode=%xh %S\n", 
+                                       Fcb->FFSMcb->Inode, Fcb->FFSMcb->ShortName.Buffer));
+
+               if(!ExAcquireResourceSharedLite(
+                                       &Fcb->PagingIoResource, Wait))
+               {
+                       return FALSE;
+               }
+       }
+
+       ASSERT(IoGetTopLevelIrp() == NULL);
+
+       IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
+
+       return TRUE;
+}
+
+
+__drv_mustHoldCriticalRegion
+VOID NTAPI
+FFSReleaseFromLazyWrite(
+       IN PVOID Context)
+{
+       //
+       // On a readonly filesystem this function still has to exist but it
+       // doesn't need to do anything.
+       PFFS_FCB Fcb;
+
+    PAGED_CODE();
+
+       Fcb = (PFFS_FCB)Context;
+
+       ASSERT(Fcb != NULL);
+
+       ASSERT((Fcb->Identifier.Type == FFSFCB) &&
+                       (Fcb->Identifier.Size == sizeof(FFS_FCB)));
+
+       FFSPrint((DBG_INFO, "FFSReleaseFromLazyWrite: %s %s %s\n",
+                               FFSGetCurrentProcessName(),
+                               "RELEASE_FROM_LAZY_WRITE",
+                               Fcb->AnsiFileName.Buffer));
+
+       if (!IsFlagOn(Fcb->Vcb->Flags, VCB_READ_ONLY))
+       {
+               FFSPrint((DBG_INFO, "FFSReleaseFromLazyWrite: Inode=%xh %S\n", 
+                                       Fcb->FFSMcb->Inode, Fcb->FFSMcb->ShortName.Buffer));
+
+               ExReleaseResourceLite(&Fcb->PagingIoResource);
+       }
+
+       ASSERT(IoGetTopLevelIrp() == (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
+
+       IoSetTopLevelIrp(NULL);
+
+}
+
+
+__drv_mustHoldCriticalRegion
+BOOLEAN NTAPI
+FFSAcquireForReadAhead(
+       IN PVOID    Context,
+       IN BOOLEAN  Wait)
+{
+       PFFS_FCB    Fcb;
+
+    PAGED_CODE();
+
+       Fcb = (PFFS_FCB)Context;
+
+       ASSERT(Fcb != NULL);
+
+       ASSERT((Fcb->Identifier.Type == FFSFCB) &&
+                       (Fcb->Identifier.Size == sizeof(FFS_FCB)));
+
+       FFSPrint((DBG_INFO, "FFSAcquireForReadAhead: Inode=%xh %S\n", 
+                               Fcb->FFSMcb->Inode, Fcb->FFSMcb->ShortName.Buffer));
+
+       if (!ExAcquireResourceSharedLite(
+                               &Fcb->MainResource, Wait))
+               return FALSE;
+
+       ASSERT(IoGetTopLevelIrp() == NULL);
+
+       IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
+
+       return TRUE;
+}
+
+
+__drv_mustHoldCriticalRegion
+VOID NTAPI
+FFSReleaseFromReadAhead(
+       IN PVOID Context)
+{
+       PFFS_FCB Fcb;
+
+    PAGED_CODE();
+
+       Fcb = (PFFS_FCB)Context;
+
+       ASSERT(Fcb != NULL);
+
+       ASSERT((Fcb->Identifier.Type == FFSFCB) &&
+                       (Fcb->Identifier.Size == sizeof(FFS_FCB)));
+
+       FFSPrint((DBG_INFO, "FFSReleaseFromReadAhead: Inode=%xh %S\n", 
+                               Fcb->FFSMcb->Inode, Fcb->FFSMcb->ShortName.Buffer));
+
+       IoSetTopLevelIrp(NULL);
+
+       ExReleaseResourceLite(&Fcb->MainResource);
+}
+
+
+BOOLEAN NTAPI
+FFSNoOpAcquire(
+       IN PVOID Fcb,
+       IN BOOLEAN Wait)
+{
+       UNREFERENCED_PARAMETER(Fcb);
+       UNREFERENCED_PARAMETER(Wait);
+
+       //
+       //  This is a kludge because Cc is really the top level.  We it
+       //  enters the file system, we will think it is a resursive call
+       //  and complete the request with hard errors or verify.  It will
+       //  have to deal with them, somehow....
+       //
+
+    PAGED_CODE();
+
+       ASSERT(IoGetTopLevelIrp() == NULL);
+
+       IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
+
+       return TRUE;
+}
+
+
+VOID NTAPI
+FFSNoOpRelease(
+       IN PVOID Fcb)
+{
+       //
+       //  Clear the kludge at this point.
+       //
+
+    PAGED_CODE();
+
+       ASSERT(IoGetTopLevelIrp() == (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
+
+       IoSetTopLevelIrp(NULL);
+
+       UNREFERENCED_PARAMETER(Fcb);
+
+       return;
+}
diff --git a/reactos/drivers/filesystems/ffs/src/create.c b/reactos/drivers/filesystems/ffs/src/create.c
new file mode 100644 (file)
index 0000000..f21e905
--- /dev/null
@@ -0,0 +1,2055 @@
+/* 
+ * FFS File System Driver for Windows
+ *
+ * create.c
+ *
+ * 2004.5.6 ~
+ *
+ * Lee Jae-Hong, http://www.pyrasis.com
+ *
+ * See License.txt
+ *
+ */
+
+#include "ntifs.h"
+#include "ffsdrv.h"
+
+/* Globals */
+
+extern PFFS_GLOBAL FFSGlobal;
+
+/* Definitions */
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE, FFSv1LookupFileName)
+#pragma alloc_text(PAGE, FFSv2LookupFileName)
+#pragma alloc_text(PAGE, FFSSearchFcbList)
+#pragma alloc_text(PAGE, FFSv1ScanDir)
+#pragma alloc_text(PAGE, FFSv2ScanDir)
+#pragma alloc_text(PAGE, FFSCreateFile)
+#pragma alloc_text(PAGE, FFSCreateVolume)
+#pragma alloc_text(PAGE, FFSCreate)
+#pragma alloc_text(PAGE, FFSCreateInode)
+#pragma alloc_text(PAGE, FFSSupersedeOrOverWriteFile)
+#endif
+
+
+NTSTATUS
+FFSv1LookupFileName(
+       IN PFFS_VCB            Vcb,
+       IN PUNICODE_STRING     FullFileName,
+       IN PFFS_MCB            ParentMcb,
+       OUT PFFS_MCB*          FFSMcb,
+       IN OUT PFFSv1_INODE    dinode1)
+{
+       NTSTATUS        Status;
+       UNICODE_STRING  FileName;
+       PFFS_MCB        Mcb = 0;
+
+       FFS_DIR_ENTRY   ffs_dir;
+       int             i = 0;
+       BOOLEAN         bRun = TRUE;
+       BOOLEAN         bParent = FALSE;
+       FFSv1_INODE     in;
+       ULONG           off = 0;
+
+    PAGED_CODE();
+
+       Status = STATUS_OBJECT_NAME_NOT_FOUND;
+
+       *FFSMcb = NULL;
+
+       if (ParentMcb)
+       {
+               bParent = TRUE;
+       }
+       else if (FullFileName->Buffer[0] == L'\\')
+       {
+               ParentMcb = Vcb->McbTree;
+       }
+       else
+       {
+               return STATUS_OBJECT_PATH_NOT_FOUND;
+       }
+
+       RtlZeroMemory(&ffs_dir, sizeof(FFS_DIR_ENTRY));
+
+       if (FullFileName->Length == 0)
+       {
+               return Status;
+       }
+
+       if (FullFileName->Length == 2 && FullFileName->Buffer[0] == L'\\')
+       {
+               if (!FFSv1LoadInode(Vcb, ParentMcb->Inode, dinode1))
+               {
+                       return Status;      
+               }
+
+               *FFSMcb = Vcb->McbTree;
+
+               return STATUS_SUCCESS;
+       }
+
+       while (bRun && i < FullFileName->Length / 2)
+       {
+               int Length;
+               ULONG FileAttr = FILE_ATTRIBUTE_NORMAL;
+
+               if (bParent)
+               {
+                       bParent = FALSE;
+               }
+               else
+               {
+                       while(i < FullFileName->Length / 2 && FullFileName->Buffer[i] == L'\\') i++;
+               }
+
+               Length = i;
+
+               while(i < FullFileName->Length / 2 && (FullFileName->Buffer[i] != L'\\')) i++;
+
+               if (i - Length > 0)
+               {
+                       FileName = *FullFileName;
+                       FileName.Buffer += Length;
+                       FileName.Length = (USHORT)((i - Length) * 2);
+
+                       Mcb = FFSSearchMcb(Vcb, ParentMcb, &FileName);
+
+                       if (Mcb)
+                       {
+                               ParentMcb = Mcb;
+
+                               Status = STATUS_SUCCESS;
+
+                               if (!IsFlagOn(Mcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY))
+                               {
+                                       if (i < FullFileName->Length / 2)
+                                       {
+                                               Status = STATUS_OBJECT_PATH_NOT_FOUND;
+                                       }
+
+                                       break;
+                               }
+                       }
+                       else
+                       {
+                               if (!FFSv1LoadInode(Vcb, ParentMcb->Inode, &in))
+                               {
+                                       Status = STATUS_OBJECT_NAME_NOT_FOUND;
+                                       break;
+                               }
+
+                               if ((in.di_mode & IFMT) != IFDIR)
+                               {
+                                       if (i < FullFileName->Length / 2)
+                                       {
+                                               Status =  STATUS_OBJECT_NAME_NOT_FOUND;
+                                       }
+                                       break;
+                               }
+
+                               Status = FFSv1ScanDir(
+                                               Vcb,
+                                               ParentMcb,
+                                               &FileName,
+                                               &off,
+                                               &in,
+                                               &ffs_dir);
+
+                               if (!NT_SUCCESS(Status))
+                               {
+                                       bRun = FALSE;
+                                       /*
+                                          if (i >= FullFileName->Length/2)
+                                          {
+                                        *FFSMcb = ParentMcb;
+                                        }
+                                        */
+                               }
+                               else
+                               {
+#if 0
+                                       if (IsFlagOn(SUPER_BLOCK->s_feature_incompat, 
+                                                               FFS_FEATURE_INCOMPAT_FILETYPE))
+                                       {
+                                               if (ffs_dir.d_type == FFS_FT_DIR)
+                                                       SetFlag(FileAttr, FILE_ATTRIBUTE_DIRECTORY);
+                                       }
+                                       else
+#endif
+                                       {
+                                               if (!FFSv1LoadInode(Vcb, ffs_dir.d_ino, &in))
+                                               {
+                                                       Status = STATUS_OBJECT_NAME_NOT_FOUND;
+                                                       break;
+                                               }
+
+                                               if ((in.di_mode & IFMT) == IFDIR)
+                                               {
+                                                       SetFlag(FileAttr, FILE_ATTRIBUTE_DIRECTORY);
+                                               }
+                                       }
+
+                                       SetFlag(ParentMcb->Flags, MCB_IN_USE);
+                                       Mcb = FFSAllocateMcb(Vcb, &FileName, FileAttr);
+                                       ClearFlag(ParentMcb->Flags, MCB_IN_USE);
+
+                                       if (!Mcb)
+                                       {
+                                               Status = STATUS_OBJECT_NAME_NOT_FOUND;
+                                               break;
+                                       }
+
+                                       Mcb->Inode = ffs_dir.d_ino;
+                                       Mcb->DeOffset = off;
+                                       FFSAddMcbNode(Vcb, ParentMcb, Mcb);
+                                       ParentMcb = Mcb;
+                               }
+                       }
+               }
+               else
+               {
+                       break;
+               }
+       }
+
+       if (NT_SUCCESS(Status))
+       {
+               *FFSMcb = Mcb;
+               if (dinode1)
+               {
+                       if (!FFSv1LoadInode(Vcb, Mcb->Inode, dinode1))
+                       {
+                               FFSPrint((DBG_ERROR, "FFSv1LookupFileName: error loading Inode %xh\n",
+                                                       Mcb->Inode));
+                               Status = STATUS_INSUFFICIENT_RESOURCES;
+                       }
+               }
+       }
+
+       return Status;
+}
+
+
+NTSTATUS
+FFSv2LookupFileName(
+       IN PFFS_VCB            Vcb,
+       IN PUNICODE_STRING     FullFileName,
+       IN PFFS_MCB            ParentMcb,
+       OUT PFFS_MCB*          FFSMcb,
+       IN OUT PFFSv2_INODE    dinode2)
+{
+       NTSTATUS        Status;
+       UNICODE_STRING  FileName;
+       PFFS_MCB        Mcb = 0;
+
+       FFS_DIR_ENTRY   ffs_dir;
+       int             i = 0;
+       BOOLEAN         bRun = TRUE;
+       BOOLEAN         bParent = FALSE;
+       FFSv2_INODE     in;
+       ULONG           off = 0;
+
+    PAGED_CODE();
+
+       Status = STATUS_OBJECT_NAME_NOT_FOUND;
+
+       *FFSMcb = NULL;
+
+       if (ParentMcb)
+       {
+               bParent = TRUE;
+       }
+       else if (FullFileName->Buffer[0] == L'\\')
+       {
+               ParentMcb = Vcb->McbTree;
+       }
+       else
+       {
+               return STATUS_OBJECT_PATH_NOT_FOUND;
+       }
+
+       RtlZeroMemory(&ffs_dir, sizeof(FFS_DIR_ENTRY));
+
+       if (FullFileName->Length == 0)
+       {
+               return Status;
+       }
+
+       if (FullFileName->Length == 2 && FullFileName->Buffer[0] == L'\\')
+       {
+               if (!FFSv2LoadInode(Vcb, ParentMcb->Inode, dinode2))
+               {
+                       return Status;      
+               }
+
+               *FFSMcb = Vcb->McbTree;
+
+               return STATUS_SUCCESS;
+       }
+
+       while (bRun && i < FullFileName->Length / 2)
+       {
+               int Length;
+               ULONG FileAttr = FILE_ATTRIBUTE_NORMAL;
+
+               if (bParent)
+               {
+                       bParent = FALSE;
+               }
+               else
+               {
+                       while(i < FullFileName->Length / 2 && FullFileName->Buffer[i] == L'\\') i++;
+               }
+
+               Length = i;
+
+               while(i < FullFileName->Length / 2 && (FullFileName->Buffer[i] != L'\\')) i++;
+
+               if (i - Length > 0)
+               {
+                       FileName = *FullFileName;
+                       FileName.Buffer += Length;
+                       FileName.Length = (USHORT)((i - Length) * 2);
+
+                       Mcb = FFSSearchMcb(Vcb, ParentMcb, &FileName);
+
+                       if (Mcb)
+                       {
+                               ParentMcb = Mcb;
+
+                               Status = STATUS_SUCCESS;
+
+                               if (!IsFlagOn(Mcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY))
+                               {
+                                       if (i < FullFileName->Length / 2)
+                                       {
+                                               Status = STATUS_OBJECT_PATH_NOT_FOUND;
+                                       }
+
+                                       break;
+                               }
+                       }
+                       else
+                       {
+                               if (!FFSv2LoadInode(Vcb, ParentMcb->Inode, &in))
+                               {
+                                       Status = STATUS_OBJECT_NAME_NOT_FOUND;
+                                       break;
+                               }
+
+                               if ((in.di_mode & IFMT) != IFDIR)
+                               {
+                                       if (i < FullFileName->Length / 2)
+                                       {
+                                               Status =  STATUS_OBJECT_NAME_NOT_FOUND;
+                                       }
+                                       break;
+                               }
+
+                               Status = FFSv2ScanDir(
+                                               Vcb,
+                                               ParentMcb,
+                                               &FileName,
+                                               &off,
+                                               &in,
+                                               &ffs_dir);
+
+                               if (!NT_SUCCESS(Status))
+                               {
+                                       bRun = FALSE;
+                                       /*
+                                          if (i >= FullFileName->Length/2)
+                                          {
+                                        *FFSMcb = ParentMcb;
+                                        }
+                                        */
+                               }
+                               else
+                               {
+#if 0
+                                       if (IsFlagOn(SUPER_BLOCK->s_feature_incompat, 
+                                                               FFS_FEATURE_INCOMPAT_FILETYPE))
+                                       {
+                                               if (ffs_dir.d_type == FFS_FT_DIR)
+                                                       SetFlag(FileAttr, FILE_ATTRIBUTE_DIRECTORY);
+                                       }
+                                       else
+#endif
+                                       {
+                                               if (!FFSv2LoadInode(Vcb, ffs_dir.d_ino, &in))
+                                               {
+                                                       Status = STATUS_OBJECT_NAME_NOT_FOUND;
+                                                       break;
+                                               }
+
+                                               if ((in.di_mode & IFMT) == IFDIR)
+                                               {
+                                                       SetFlag(FileAttr, FILE_ATTRIBUTE_DIRECTORY);
+                                               }
+                                       }
+
+                                       SetFlag(ParentMcb->Flags, MCB_IN_USE);
+                                       Mcb = FFSAllocateMcb(Vcb, &FileName, FileAttr);
+                                       ClearFlag(ParentMcb->Flags, MCB_IN_USE);
+
+                                       if (!Mcb)
+                                       {
+                                               Status = STATUS_OBJECT_NAME_NOT_FOUND;
+                                               break;
+                                       }
+
+                                       Mcb->Inode = ffs_dir.d_ino;
+                                       Mcb->DeOffset = off;
+                                       FFSAddMcbNode(Vcb, ParentMcb, Mcb);
+                                       ParentMcb = Mcb;
+                               }
+                       }
+               }
+               else
+               {
+                       break;
+               }
+       }
+
+       if (NT_SUCCESS(Status))
+       {
+               *FFSMcb = Mcb;
+               if (dinode2)
+               {
+                       if (!FFSv2LoadInode(Vcb, Mcb->Inode, dinode2))
+                       {
+                               FFSPrint((DBG_ERROR, "FFSv2LookupFileName: error loading Inode %xh\n",
+                                                       Mcb->Inode));
+                               Status = STATUS_INSUFFICIENT_RESOURCES;
+                       }
+               }
+       }
+
+       return Status;
+}
+
+
+NTSTATUS
+FFSv1ScanDir(
+       IN PFFS_VCB            Vcb,
+       IN PFFS_MCB            ParentMcb,
+       IN PUNICODE_STRING     FileName,
+       IN OUT PULONG          Index,
+       IN PFFSv1_INODE        dinode1,
+       IN OUT PFFS_DIR_ENTRY  ffs_dir)
+{
+       NTSTATUS                Status = STATUS_UNSUCCESSFUL;
+       USHORT                  InodeFileNameLength;
+       UNICODE_STRING          InodeFileName;
+
+       PFFS_DIR_ENTRY          pDir = NULL;
+       ULONG                   dwBytes = 0;
+       BOOLEAN                 bFound = FALSE;
+       LONGLONG                Offset = 0;
+#ifndef __REACTOS__
+    ULONG                   inode = ParentMcb->Inode;
+#endif
+       ULONG                   dwRet;
+
+    PAGED_CODE();
+
+       _SEH2_TRY
+       {
+
+               pDir = (PFFS_DIR_ENTRY)ExAllocatePoolWithTag(PagedPool,
+                               sizeof(FFS_DIR_ENTRY), FFS_POOL_TAG);
+               if (!pDir)
+               {
+                       Status = STATUS_INSUFFICIENT_RESOURCES;
+                       _SEH2_LEAVE;
+               }
+
+               InodeFileName.Buffer = ExAllocatePoolWithTag(
+                               PagedPool,
+                               (FFS_NAME_LEN + 1) * 2, FFS_POOL_TAG);
+
+               if (!InodeFileName.Buffer)
+               {
+                       Status = STATUS_INSUFFICIENT_RESOURCES;
+                       _SEH2_LEAVE;
+               }
+
+               dwBytes = 0;
+
+               while (!bFound && dwBytes < dinode1->di_size)
+               {
+                       RtlZeroMemory(pDir, sizeof(FFS_DIR_ENTRY));
+
+                       // Reading the DCB contents
+                       Status = FFSv1ReadInode(
+                                       NULL,
+                                       Vcb,
+                                       dinode1,
+                                       dwBytes,
+                                       (PVOID)pDir,
+                                       sizeof(FFS_DIR_ENTRY),
+                                       &dwRet);
+
+
+                       if (!NT_SUCCESS(Status))
+                       {
+                               FFSPrint((DBG_ERROR, "FFSv1ScanDir: Reading Directory Content error.\n"));
+                               _SEH2_LEAVE;
+                       }
+
+                       if (pDir->d_ino /*&& (pDir->d_ino < INODES_COUNT)*/)
+                       {
+                               OEM_STRING OemName;
+                               OemName.Buffer = pDir->d_name;
+                               OemName.Length = (pDir->d_namlen & 0xff);
+                               OemName.MaximumLength = OemName.Length;
+
+                               InodeFileNameLength = (USHORT)
+                                       RtlOemStringToCountedUnicodeSize(&OemName);
+
+                               InodeFileName.Length = 0;
+                               InodeFileName.MaximumLength = (FFS_NAME_LEN + 1) * 2;
+
+                               RtlZeroMemory(InodeFileName.Buffer,
+                                               InodeFileNameLength + 2);
+
+                               Status = FFSOEMToUnicode(
+                                               &InodeFileName,
+                                               &OemName);
+
+                               if (!NT_SUCCESS(Status))
+                               {
+                                       _SEH2_LEAVE;
+                               }
+
+                               if (!RtlCompareUnicodeString(
+                                                       FileName,
+                                                       &InodeFileName,
+                                                       TRUE))
+                               {
+                                       bFound = TRUE;
+                                       *Index = dwBytes;
+                                       RtlCopyMemory(ffs_dir, pDir, pDir->d_reclen > sizeof(FFS_DIR_ENTRY)
+                                                       ? sizeof(FFS_DIR_ENTRY) : pDir->d_reclen);
+                                       Status = STATUS_SUCCESS;
+
+                                       FFSPrint((DBG_INFO, "FFSv1ScanDir: Found: Name=%S Inode=%xh\n", InodeFileName.Buffer, pDir->d_ino));
+                               }
+
+                               dwBytes +=pDir->d_reclen;
+                               Offset = (LONGLONG)dwBytes;
+                       }
+                       else
+                       {
+                               if (pDir->d_ino == 0)
+                               {
+                                       if (pDir->d_reclen == 0)
+                                       {
+                                               FFSBreakPoint();
+                                               break;
+                                       }
+                                       else
+                                       {
+                                               dwBytes +=pDir->d_reclen;
+                                               Offset = (LONGLONG)dwBytes;
+                                       }
+                               }
+                               else
+                               {
+                                       break;
+                               }
+                       }
+               }
+
+               if (!bFound)
+               {
+                       Status = STATUS_NO_SUCH_FILE;
+               }
+       }
+
+       _SEH2_FINALLY
+       {
+               if (InodeFileName.Buffer != NULL)
+               {
+                       ExFreePool(InodeFileName.Buffer);
+               }
+
+               if (pDir)
+                       ExFreePool(pDir);
+       } _SEH2_END;
+
+       return Status;
+}
+
+
+NTSTATUS
+FFSv2ScanDir(
+       IN PFFS_VCB            Vcb,
+       IN PFFS_MCB            ParentMcb,
+       IN PUNICODE_STRING     FileName,
+       IN OUT PULONG          Index,
+       IN PFFSv2_INODE        dinode2,
+       IN OUT PFFS_DIR_ENTRY  ffs_dir)
+{
+       NTSTATUS                Status = STATUS_UNSUCCESSFUL;
+       USHORT                  InodeFileNameLength;
+       UNICODE_STRING          InodeFileName;
+
+       PFFS_DIR_ENTRY          pDir = NULL;
+       ULONG                   dwBytes = 0;
+       BOOLEAN                 bFound = FALSE;
+       LONGLONG                Offset = 0;
+#ifndef __REACTOS__
+    ULONG                   inode = ParentMcb->Inode;
+#endif
+       ULONG                   dwRet;
+
+    PAGED_CODE();
+
+       _SEH2_TRY
+       {
+
+               pDir = (PFFS_DIR_ENTRY)ExAllocatePoolWithTag(PagedPool,
+                               sizeof(FFS_DIR_ENTRY), FFS_POOL_TAG);
+               if (!pDir)
+               {
+                       Status = STATUS_INSUFFICIENT_RESOURCES;
+                       _SEH2_LEAVE;
+               }
+
+               InodeFileName.Buffer = ExAllocatePoolWithTag(
+                               PagedPool,
+                               (FFS_NAME_LEN + 1) * 2, FFS_POOL_TAG);
+
+               if (!InodeFileName.Buffer)
+               {
+                       Status = STATUS_INSUFFICIENT_RESOURCES;
+                       _SEH2_LEAVE;
+               }
+
+               dwBytes = 0;
+
+               while (!bFound && dwBytes < dinode2->di_size)
+               {
+                       RtlZeroMemory(pDir, sizeof(FFS_DIR_ENTRY));
+
+                       // Reading the DCB contents
+                       Status = FFSv2ReadInode(
+                                       NULL,
+                                       Vcb,
+                                       dinode2,
+                                       dwBytes,
+                                       (PVOID)pDir,
+                                       sizeof(FFS_DIR_ENTRY),
+                                       &dwRet);
+
+
+                       if (!NT_SUCCESS(Status))
+                       {
+                               FFSPrint((DBG_ERROR, "FFSv2ScanDir: Reading Directory Content error.\n"));
+                               _SEH2_LEAVE;
+                       }
+
+                       if (pDir->d_ino /*&& (pDir->d_ino < INODES_COUNT)*/)
+                       {
+                               OEM_STRING OemName;
+                               OemName.Buffer = pDir->d_name;
+                               OemName.Length = (pDir->d_namlen & 0xff);
+                               OemName.MaximumLength = OemName.Length;
+
+                               InodeFileNameLength = (USHORT)
+                                       RtlOemStringToCountedUnicodeSize(&OemName);
+
+                               InodeFileName.Length = 0;
+                               InodeFileName.MaximumLength = (FFS_NAME_LEN + 1) * 2;
+
+                               RtlZeroMemory(InodeFileName.Buffer,
+                                               InodeFileNameLength + 2);
+
+                               Status = FFSOEMToUnicode(
+                                               &InodeFileName,
+                                               &OemName);
+
+                               if (!NT_SUCCESS(Status))
+                               {
+                                       _SEH2_LEAVE;
+                               }
+
+                               if (!RtlCompareUnicodeString(
+                                                       FileName,
+                                                       &InodeFileName,
+                                                       TRUE))
+                               {
+                                       bFound = TRUE;
+                                       *Index = dwBytes;
+                                       RtlCopyMemory(ffs_dir, pDir, pDir->d_reclen > sizeof(FFS_DIR_ENTRY)
+                                                       ? sizeof(FFS_DIR_ENTRY) : pDir->d_reclen);
+                                       Status = STATUS_SUCCESS;
+
+                                       FFSPrint((DBG_VITAL, "FFSv2ScanDir: Found: Name=%S Inode=%xh\n", InodeFileName.Buffer, pDir->d_ino));
+                               }
+
+                               dwBytes +=pDir->d_reclen;
+                               Offset = (LONGLONG)dwBytes;
+                       }
+                       else
+                       {
+                               if (pDir->d_ino == 0)
+                               {
+                                       if (pDir->d_reclen == 0)
+                                       {
+                                               FFSBreakPoint();
+                                               break;
+                                       }
+                                       else
+                                       {
+                                               dwBytes +=pDir->d_reclen;
+                                               Offset = (LONGLONG)dwBytes;
+                                       }
+                               }
+                               else
+                               {
+                                       break;
+                               }
+                       }
+               }
+
+               if (!bFound)
+               {
+                       Status = STATUS_NO_SUCH_FILE;
+               }
+       }
+
+       _SEH2_FINALLY
+       {
+               if (InodeFileName.Buffer != NULL)
+               {
+                       ExFreePool(InodeFileName.Buffer);
+               }
+
+               if (pDir)
+                       ExFreePool(pDir);
+       } _SEH2_END;
+
+       return Status;
+}
+
+
+/*
+PFFS_FCB
+FFSSearchFcbList(
+       IN PFFS_VCB     Vcb,
+       IN ULONG        inode)
+{
+       BOOLEAN             bFound = FALSE;
+       PLIST_ENTRY         Link;
+       PFFS_FCB            TmpFcb;
+
+       Link = Vcb->FcbList.Flink;
+
+       while (!bFound && Link != &Vcb->FcbList)
+       {
+               TmpFcb = CONTAINING_RECORD(Link, FFS_FCB, Next);
+
+               if (TmpFcb && TmpFcb->Identifier.Type == FCB)
+               {
+#if DBG
+                       FFSPrint((DBG_INFO, "FFSSearchFcbList: [%s,%xh]\n", 
+                               TmpFcb->AnsiFileName.Buffer, TmpFcb->Inode));
+#endif          
+                       if (TmpFcb->Inode == inode)
+                       {
+                               FFSPrint((DBG_INFO, "FFSSearchMcb: Found FCB for %xh.\n", inode));
+                               bFound = TRUE;
+                       }
+               }
+               Link = Link->Flink;
+       }
+
+       if (bFound)
+               return TmpFcb;
+       else
+               return NULL;
+
+}
+*/
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSCreateFile(
+       PFFS_IRP_CONTEXT IrpContext,
+       PFFS_VCB         Vcb)
+{
+       NTSTATUS            Status = STATUS_UNSUCCESSFUL;
+       PIO_STACK_LOCATION  IrpSp;
+       PFFS_FCB            Fcb = NULL;
+       PFFS_MCB            FFSMcb = NULL;
+
+       PFFS_FCB            ParentFcb = NULL;
+       PFFS_MCB            ParentMcb = NULL;
+
+       BOOLEAN             bParentFcbCreated = FALSE;
+
+       PFFS_CCB            Ccb = NULL;
+       PFFSv1_INODE        dinode1 = 0;
+       PFFSv2_INODE        dinode2 = 0;
+       BOOLEAN             VcbResourceAcquired = FALSE;
+#ifndef __REACTOS__
+    BOOLEAN             bDir = FALSE;
+#endif
+       BOOLEAN             bFcbAllocated = FALSE;
+       BOOLEAN             bCreated = FALSE;
+       UNICODE_STRING      FileName;
+       PIRP                Irp;
+
+       ULONG               Options;
+       ULONG               CreateDisposition;
+
+       BOOLEAN             OpenDirectory;
+       BOOLEAN             OpenTargetDirectory;
+       BOOLEAN             CreateDirectory;
+       BOOLEAN             SequentialOnly;
+       BOOLEAN             NoIntermediateBuffering;
+       BOOLEAN             IsPagingFile;
+       BOOLEAN             DirectoryFile;
+       BOOLEAN             NonDirectoryFile;
+       BOOLEAN             NoEaKnowledge;
+       BOOLEAN             DeleteOnClose;
+       BOOLEAN             TemporaryFile;
+       BOOLEAN             CaseSensitive;
+
+       ACCESS_MASK         DesiredAccess;
+       ULONG               ShareAccess;
+
+    PAGED_CODE();
+
+       Irp = IrpContext->Irp;
+       IrpSp = IoGetCurrentIrpStackLocation(Irp);
+
+       Options  = IrpSp->Parameters.Create.Options;
+
+       DirectoryFile = IsFlagOn(Options, FILE_DIRECTORY_FILE);
+       OpenTargetDirectory = IsFlagOn(IrpSp->Flags, SL_OPEN_TARGET_DIRECTORY);
+
+       NonDirectoryFile = IsFlagOn(Options, FILE_NON_DIRECTORY_FILE);
+       SequentialOnly = IsFlagOn(Options, FILE_SEQUENTIAL_ONLY);
+       NoIntermediateBuffering = IsFlagOn(Options, FILE_NO_INTERMEDIATE_BUFFERING);
+       NoEaKnowledge = IsFlagOn(Options, FILE_NO_EA_KNOWLEDGE);
+       DeleteOnClose = IsFlagOn(Options, FILE_DELETE_ON_CLOSE);
+
+       CaseSensitive = IsFlagOn(IrpSp->Flags, SL_CASE_SENSITIVE);
+
+       TemporaryFile = IsFlagOn(IrpSp->Parameters.Create.FileAttributes,
+                       FILE_ATTRIBUTE_TEMPORARY);
+
+       CreateDisposition = (Options >> 24) & 0x000000ff;
+
+       IsPagingFile = IsFlagOn(IrpSp->Flags, SL_OPEN_PAGING_FILE);
+
+       CreateDirectory = (BOOLEAN)(DirectoryFile &&
+                       ((CreateDisposition == FILE_CREATE) ||
+                        (CreateDisposition == FILE_OPEN_IF)));
+
+       OpenDirectory   = (BOOLEAN)(DirectoryFile &&
+                       ((CreateDisposition == FILE_OPEN) ||
+                        (CreateDisposition == FILE_OPEN_IF)));
+
+       DesiredAccess = IrpSp->Parameters.Create.SecurityContext->DesiredAccess;
+       ShareAccess   = IrpSp->Parameters.Create.ShareAccess;
+
+       FileName.Buffer = NULL;
+
+       _SEH2_TRY
+       {
+               ExAcquireResourceExclusiveLite(
+                               &Vcb->MainResource, TRUE);
+
+               VcbResourceAcquired = TRUE;
+
+               if (Irp->Overlay.AllocationSize.HighPart) 
+               {
+                       Status = STATUS_INVALID_PARAMETER;
+                       _SEH2_LEAVE;
+               }
+
+               if (FS_VERSION == 1)
+               {
+                       if (!(dinode1 = ExAllocatePoolWithTag(
+                                                       PagedPool, DINODE1_SIZE, 'EInd')))
+                       {
+                               _SEH2_LEAVE;
+                       }
+
+                       RtlZeroMemory(dinode1, sizeof(DINODE1_SIZE));
+               }
+               else
+               {
+                       if (!(dinode2 = ExAllocatePoolWithTag(
+                                                       PagedPool, DINODE2_SIZE, 'EInd')))
+                       {
+                               _SEH2_LEAVE;
+                       }
+
+                       RtlZeroMemory(dinode2, sizeof(DINODE2_SIZE));
+               }
+
+
+               FileName.MaximumLength = IrpSp->FileObject->FileName.MaximumLength;
+               FileName.Length = IrpSp->FileObject->FileName.Length;
+
+               FileName.Buffer = ExAllocatePoolWithTag(PagedPool, FileName.MaximumLength, FFS_POOL_TAG);
+               if (!FileName.Buffer)
+               {   
+                       Status = STATUS_INSUFFICIENT_RESOURCES;
+                       _SEH2_LEAVE;
+               }
+
+               RtlZeroMemory(FileName.Buffer, FileName.MaximumLength);
+               RtlCopyMemory(FileName.Buffer, IrpSp->FileObject->FileName.Buffer, FileName.Length);
+
+               if (IrpSp->FileObject->RelatedFileObject)
+               {
+                       ParentFcb = (PFFS_FCB)(IrpSp->FileObject->RelatedFileObject->FsContext);
+               }
+
+               if ((FileName.Length > sizeof(WCHAR)) &&
+                               (FileName.Buffer[1] == L'\\') &&
+                               (FileName.Buffer[0] == L'\\')) {
+
+                       FileName.Length -= sizeof(WCHAR);
+
+                       RtlMoveMemory(&FileName.Buffer[0],
+                                       &FileName.Buffer[1],
+                                       FileName.Length);
+
+                       //
+                       //  Bad Name if there are still beginning backslashes.
+                       //
+
+                       if ((FileName.Length > sizeof(WCHAR)) &&
+                                       (FileName.Buffer[1] == L'\\') &&
+                                       (FileName.Buffer[0] == L'\\'))
+                       {
+
+                               Status = STATUS_OBJECT_NAME_INVALID;
+
+                               _SEH2_LEAVE;
+                       }
+               }
+
+               if (IsFlagOn(Options, FILE_OPEN_BY_FILE_ID))
+               {
+                       Status = STATUS_NOT_IMPLEMENTED;
+                       _SEH2_LEAVE;
+               }
+
+               FFSPrint((DBG_INFO, "FFSCreateFile: %S (NameLen=%xh) Paging=%xh Option: %xh.\n",
+                                       FileName.Buffer, FileName.Length, IsPagingFile, IrpSp->Parameters.Create.Options));
+
+               if (ParentFcb)
+               {
+                       ParentMcb = ParentFcb->FFSMcb;
+               }
+
+               if (FS_VERSION == 1)
+               {
+                       Status = FFSv1LookupFileName(
+                                               Vcb,
+                                               &FileName,
+                                               ParentMcb,
+                                               &FFSMcb,
+                                               dinode1);
+               }
+               else
+               {
+                       Status = FFSv2LookupFileName(
+                                               Vcb,
+                                               &FileName,
+                                               ParentMcb,
+                                               &FFSMcb,
+                                               dinode2);
+               }
+
+               if (!NT_SUCCESS(Status))
+               {
+                       UNICODE_STRING  PathName;
+                       UNICODE_STRING  RealName;
+                       UNICODE_STRING  RemainName;
+#ifndef __REACTOS__
+                       LONG            i = 0;
+#endif
+
+                       PathName = FileName;
+
+                       FFSPrint((DBG_INFO, "FFSCreateFile: File %S will be created.\n", PathName.Buffer));
+
+                       FFSMcb = NULL;
+
+                       if (PathName.Buffer[PathName.Length / 2 - 1] == L'\\')
+                       {
+                               if (DirectoryFile)
+                               {
+                                       PathName.Length -= 2;
+                                       PathName.Buffer[PathName.Length / 2] = 0;
+                               }
+                               else
+                               {
+                                       Status = STATUS_NOT_A_DIRECTORY;
+                                       _SEH2_LEAVE;
+                               }
+                       }
+
+                       if (!ParentMcb)
+                       {
+                               if (PathName.Buffer[0] != L'\\')
+                               {
+                                       Status = STATUS_OBJECT_PATH_NOT_FOUND;
+                                       _SEH2_LEAVE;
+                               }
+                               else
+                               {
+                                       ParentMcb = Vcb->McbTree;
+                               }
+                       }
+
+Dissecting:
+
+                       FsRtlDissectName(PathName, &RealName, &RemainName);
+
+                       if (((RemainName.Length != 0) && (RemainName.Buffer[0] == L'\\')) ||
+                                       (RealName.Length >= 256 * sizeof(WCHAR)))
+                       {
+                               Status = STATUS_OBJECT_NAME_INVALID;
+                               _SEH2_LEAVE;
+                       }
+
+                       if (RemainName.Length != 0)
+                       {
+                               PFFS_MCB   RetMcb;
+
+                               if (FS_VERSION == 1)
+                               {
+                                       Status = FFSv1LookupFileName(
+                                                               Vcb,
+                                                               &RealName,
+                                                               ParentMcb,
+                                                               &RetMcb,
+                                                               dinode1);
+                               }
+                               else
+                               {
+                                       Status = FFSv2LookupFileName(
+                                                               Vcb,
+                                                               &RealName,
+                                                               ParentMcb,
+                                                               &RetMcb,
+                                                               dinode2);
+                               }
+
+                               if (!NT_SUCCESS(Status))
+                               {
+                                       Status = STATUS_OBJECT_PATH_NOT_FOUND;
+                                       _SEH2_LEAVE;
+                               }
+
+                               ParentMcb = RetMcb;
+                               PathName  = RemainName;
+
+                               goto Dissecting;
+                       }
+
+                       if (FsRtlDoesNameContainWildCards(&RealName))
+                       {
+                               Status = STATUS_OBJECT_NAME_INVALID;
+                               _SEH2_LEAVE;
+                       }
+
+                       ParentFcb = ParentMcb->FFSFcb;
+
+                       if (!ParentFcb)
+                       {
+                               if (FS_VERSION == 1)
+                               {
+                                       PFFSv1_INODE pTmpInode = ExAllocatePoolWithTag(PagedPool, 
+                                                       DINODE1_SIZE, FFS_POOL_TAG);
+                                       if (!pTmpInode)
+                                       {
+                                               Status = STATUS_INSUFFICIENT_RESOURCES;
+                                               _SEH2_LEAVE;
+                                       }
+
+                                       if(!FFSv1LoadInode(Vcb, ParentMcb->Inode, pTmpInode))
+                                       {
+                                               Status = STATUS_OBJECT_PATH_NOT_FOUND;
+                                               _SEH2_LEAVE;
+                                       }
+
+                                       ParentFcb = FFSv1AllocateFcb(Vcb, ParentMcb, pTmpInode);
+
+                                       if (!ParentFcb)
+                                       {
+                                               ExFreePool(pTmpInode);
+                                               Status = STATUS_INSUFFICIENT_RESOURCES;
+                                               _SEH2_LEAVE;
+                                       }
+                               }
+                               else
+                               {
+                                       PFFSv2_INODE pTmpInode = ExAllocatePoolWithTag(PagedPool, 
+                                                       DINODE2_SIZE, FFS_POOL_TAG);
+                                       if (!pTmpInode)
+                                       {
+                                               Status = STATUS_INSUFFICIENT_RESOURCES;
+                                               _SEH2_LEAVE;
+                                       }
+
+                                       if(!FFSv2LoadInode(Vcb, ParentMcb->Inode, pTmpInode))
+                                       {
+                                               Status = STATUS_OBJECT_PATH_NOT_FOUND;
+                                               _SEH2_LEAVE;
+                                       }
+
+                                       ParentFcb = FFSv2AllocateFcb(Vcb, ParentMcb, pTmpInode);
+
+                                       if (!ParentFcb)
+                                       {
+                                               ExFreePool(pTmpInode);
+                                               Status = STATUS_INSUFFICIENT_RESOURCES;
+                                               _SEH2_LEAVE;
+                                       }
+                               }
+
+                               bParentFcbCreated = TRUE;
+                               ParentFcb->ReferenceCount++;
+                       }
+
+                       // We need to create a new one ?
+                       if ((CreateDisposition == FILE_CREATE) ||
+                                       (CreateDisposition == FILE_OPEN_IF) ||
+                                       (CreateDisposition == FILE_OVERWRITE_IF))
+                       {
+#if FFS_READ_ONLY
+                               Status = STATUS_MEDIA_WRITE_PROTECTED;
+                               _SEH2_LEAVE;
+#else // !FFS_READ_ONLY
+                               if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY))
+                               {
+                                       Status = STATUS_MEDIA_WRITE_PROTECTED;
+                                       _SEH2_LEAVE;
+                               }
+
+                               if (IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED))
+                               {
+                                       IoSetHardErrorOrVerifyDevice(IrpContext->Irp,
+                                                       Vcb->Vpb->RealDevice);
+                                       SetFlag(Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME);
+
+                                       FFSRaiseStatus(IrpContext, STATUS_MEDIA_WRITE_PROTECTED);
+                               }
+
+                               if (DirectoryFile)
+                               {
+                                       if (TemporaryFile)
+                                       {
+                                               Status = STATUS_INVALID_PARAMETER;
+                                               _SEH2_LEAVE;
+                                       }
+                               }
+
+                               if (!ParentFcb)
+                               {
+                                       Status = STATUS_OBJECT_PATH_NOT_FOUND;
+                                       _SEH2_LEAVE;
+                               }
+
+                               if (DirectoryFile)
+                               {
+                                       if (ParentFcb->FFSMcb->Inode == FFS_ROOT_INO) 
+                                       {
+                                               if ((RealName.Length == 0x10) && 
+                                                               memcmp(RealName.Buffer, L"Recycled\0", 0x10) == 0)
+                                               {
+                                                       SetFlag(IrpSp->Parameters.Create.FileAttributes,
+                                                                       FILE_ATTRIBUTE_READONLY);
+                                               }
+                                       }
+
+                                       Status = FFSCreateInode(
+                                                               IrpContext,
+                                                               Vcb, 
+                                                               ParentFcb,
+                                                               DT_DIR,
+                                                               IrpSp->Parameters.Create.FileAttributes,
+                                                               &RealName);
+                               }
+                               else
+                               {
+                                       Status = FFSCreateInode(
+                                                               IrpContext,
+                                                               Vcb,
+                                                               ParentFcb,
+                                                               DT_REG,
+                                                               IrpSp->Parameters.Create.FileAttributes,
+                                                               &RealName);
+                               }
+
+                               if (NT_SUCCESS(Status))
+                               {
+                                       bCreated = TRUE;
+
+                                       Irp->IoStatus.Information = FILE_CREATED;
+
+                                       if (FS_VERSION == 1)
+                                       {
+                                               Status = FFSv1LookupFileName(
+                                                                       Vcb,
+                                                                       &RealName,
+                                                                       ParentMcb,
+                                                                       &FFSMcb,
+                                                                       dinode1);
+                                       }
+                                       else
+                                       {
+                                               Status = FFSv2LookupFileName(
+                                                                       Vcb,
+                                                                       &RealName,
+                                                                       ParentMcb,
+                                                                       &FFSMcb,
+                                                                       dinode2);
+                                       }
+
+                                       if (NT_SUCCESS(Status))
+                                       {
+                                               if (DirectoryFile)
+                                               {
+                                                       FFSNotifyReportChange(
+                                                               IrpContext,
+                                                               Vcb,
+                                                               ParentFcb,
+                                                               FILE_NOTIFY_CHANGE_DIR_NAME,
+                                                               FILE_ACTION_ADDED);
+                                               }
+                                               else
+                                               {
+                                                       FFSNotifyReportChange(
+                                                               IrpContext,
+                                                               Vcb,
+                                                               ParentFcb,
+                                                               FILE_NOTIFY_CHANGE_FILE_NAME,
+                                                               FILE_ACTION_ADDED);
+                                               }
+                                       }
+                                       else
+                                       {
+                                               FFSBreakPoint();
+                                       }
+                               }
+                               else
+                               {
+                                       FFSBreakPoint();
+                               }
+#endif // !FFS_READ_ONLY
+                       }
+                       else if (OpenTargetDirectory)
+                       {
+                               if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY))
+                               {
+                                       Status = STATUS_MEDIA_WRITE_PROTECTED;
+                                       _SEH2_LEAVE;
+                               }
+
+                               if (!ParentFcb)
+                               {
+                                       Status = STATUS_OBJECT_PATH_NOT_FOUND;
+                                       _SEH2_LEAVE;
+                               }
+
+                               RtlZeroMemory(IrpSp->FileObject->FileName.Buffer,
+                                               IrpSp->FileObject->FileName.MaximumLength);
+                               IrpSp->FileObject->FileName.Length = RealName.Length;
+
+                               RtlCopyMemory(IrpSp->FileObject->FileName.Buffer,
+                                               RealName.Buffer,
+                                               RealName.Length);
+
+                               Fcb = ParentFcb;
+
+                               Irp->IoStatus.Information = FILE_DOES_NOT_EXIST;
+                               Status = STATUS_SUCCESS;
+                       }
+                       else
+                       {
+                               Status = STATUS_OBJECT_NAME_NOT_FOUND;
+                               _SEH2_LEAVE;
+                       }
+               }
+               else // File / Dir already exists.
+               {
+                       if (OpenTargetDirectory)
+                       {
+                               if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY))
+                               {
+                                       Status = STATUS_MEDIA_WRITE_PROTECTED;
+                                       _SEH2_LEAVE;
+                               }
+
+                               Irp->IoStatus.Information = FILE_EXISTS;
+                               Status = STATUS_SUCCESS;
+
+                               RtlZeroMemory(IrpSp->FileObject->FileName.Buffer,
+                                               IrpSp->FileObject->FileName.MaximumLength);
+                               IrpSp->FileObject->FileName.Length = FFSMcb->ShortName.Length;
+
+                               RtlCopyMemory(IrpSp->FileObject->FileName.Buffer,
+                                               FFSMcb->ShortName.Buffer,
+                                               FFSMcb->ShortName.Length);
+
+                               //Let Mcb pointer to it's parent
+                               FFSMcb = FFSMcb->Parent;
+
+                               goto Openit;
+                       }
+
+                       // We can not create if one exists
+                       if (CreateDisposition == FILE_CREATE)
+                       {
+                               Irp->IoStatus.Information = FILE_EXISTS;
+                               Status = STATUS_OBJECT_NAME_COLLISION;
+                               _SEH2_LEAVE;
+                       }
+
+                       if(IsFlagOn(FFSMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY))
+                       {
+                               if ((CreateDisposition != FILE_OPEN) &&
+                                               (CreateDisposition != FILE_OPEN_IF))
+                               {
+
+                                       Status = STATUS_OBJECT_NAME_COLLISION;
+                                       _SEH2_LEAVE;
+                               }
+
+                               if (NonDirectoryFile) 
+                               {
+                                       Status = STATUS_FILE_IS_A_DIRECTORY;
+                                       _SEH2_LEAVE;
+                               }
+
+                               if (FFSMcb->Inode == FFS_ROOT_INO)
+                               {
+                                       if (DeleteOnClose)
+                                       {
+                                               Status = STATUS_CANNOT_DELETE;
+                                               _SEH2_LEAVE;
+                                       }
+
+                                       if (OpenTargetDirectory)
+                                       {
+                                               Status = STATUS_INVALID_PARAMETER;
+                                               _SEH2_LEAVE;
+                                       }
+                               }
+                       }
+
+                       Irp->IoStatus.Information = FILE_OPENED;
+               }
+
+Openit:
+
+               if (FFSMcb)
+               {
+                       Fcb = FFSMcb->FFSFcb;
+
+                       if (!Fcb)
+                       {
+                               if (FS_VERSION == 1)
+                               {
+                                       Fcb = FFSv1AllocateFcb(Vcb, FFSMcb, dinode1);
+                                       bFcbAllocated = TRUE;
+                               }
+                               else
+                               {
+                                       Fcb = FFSv2AllocateFcb(Vcb, FFSMcb, dinode2);
+                                       bFcbAllocated = TRUE;
+                               }
+                       }
+               }
+
+               if (Fcb)
+               {
+                       if (IsFlagOn(Fcb->Flags, FCB_FILE_DELETED))
+                       {
+                               Status = STATUS_FILE_DELETED;
+                               _SEH2_LEAVE;
+                       }
+
+                       if (FlagOn(Fcb->Flags, FCB_DELETE_PENDING))
+                       {
+                               Status = STATUS_DELETE_PENDING;
+                               _SEH2_LEAVE;
+                       }
+
+                       if (bCreated)
+                       {
+#if !FFS_READ_ONLY
+                               //
+                               //  This file is just created.
+                               //
+
+                               if (DirectoryFile)
+                               {
+                                       UNICODE_STRING EntryName;
+                                       USHORT  NameBuf[6];
+
+                                       RtlZeroMemory(&NameBuf, 6 * sizeof(USHORT));
+
+                                       EntryName.Length = EntryName.MaximumLength = 2;
+                                       EntryName.Buffer = &NameBuf[0];
+                                       NameBuf[0] = (USHORT)'.';
+
+                                       FFSAddEntry(IrpContext, Vcb, Fcb,
+                                                       DT_DIR,
+                                                       Fcb->FFSMcb->Inode,
+                                                       &EntryName);
+
+                                       if (FS_VERSION == 1)
+                                       {
+                                               FFSv1SaveInode(IrpContext, Vcb,
+                                                               Fcb->FFSMcb->Inode,
+                                                               Fcb->dinode1);
+                                       }
+                                       else
+                                       {
+                                               FFSv2SaveInode(IrpContext, Vcb,
+                                                               Fcb->FFSMcb->Inode,
+                                                               Fcb->dinode2);
+                                       }
+
+                                       EntryName.Length = EntryName.MaximumLength = 4;
+                                       EntryName.Buffer = &NameBuf[0];
+                                       NameBuf[0] = NameBuf[1] = (USHORT)'.';
+
+                                       FFSAddEntry(IrpContext, Vcb, Fcb,
+                                                       DT_DIR,
+                                                       Fcb->FFSMcb->Parent->Inode,
+                                                       &EntryName);
+
+                                       if (FS_VERSION == 1)
+                                       {
+                                               FFSv1SaveInode(IrpContext, Vcb,
+                                                               Fcb->FFSMcb->Inode,
+                                                               Fcb->dinode1);
+                                       }
+                                       else
+                                       {
+                                               FFSv2SaveInode(IrpContext, Vcb,
+                                                               Fcb->FFSMcb->Inode,
+                                                               Fcb->dinode2);
+                                       }
+                               }
+                               else
+                               {
+                                       if (!FFSExpandFile(
+                                                               IrpContext, Vcb, Fcb,
+                                                               &(Irp->Overlay.AllocationSize)))
+                                       {
+                                               Status = STATUS_INSUFFICIENT_RESOURCES;
+                                               _SEH2_LEAVE;
+                                       }
+                               }
+#endif // !FFS_READ_ONLY
+                       }
+                       else
+                       {
+                               //
+                               //  This file alreayd exists.
+                               //
+
+                               if (DeleteOnClose)
+                               {
+                                       if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY))
+                                       {
+                                               Status = STATUS_MEDIA_WRITE_PROTECTED;
+                                               _SEH2_LEAVE;
+                                       }
+
+                                       if (IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED))
+                                       {
+                                               Status = STATUS_MEDIA_WRITE_PROTECTED;
+
+                                               IoSetHardErrorOrVerifyDevice(IrpContext->Irp,
+                                                               Vcb->Vpb->RealDevice);
+
+                                               SetFlag(Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME);
+
+                                               FFSRaiseStatus(IrpContext, STATUS_MEDIA_WRITE_PROTECTED);
+                                       }
+
+                                       SetFlag(Fcb->Flags, FCB_DELETE_ON_CLOSE);
+                               }
+                               else
+                               {
+                                       //
+                                       // Just to Open file (Open/OverWrite ...)
+                                       //
+
+                                       if ((!IsDirectory(Fcb)) && (IsFlagOn(IrpSp->FileObject->Flags,
+                                                                       FO_NO_INTERMEDIATE_BUFFERING)))
+                                       {
+                                               Fcb->Header.IsFastIoPossible = FastIoIsPossible;
+
+                                               if (IsFlagOn(IrpSp->FileObject->Flags, FO_CACHE_SUPPORTED) &&
+                                                               (Fcb->SectionObject.DataSectionObject != NULL))
+                                               {
+                                                       if (Fcb->NonCachedOpenCount == Fcb->OpenHandleCount)
+                                                       {
+                                                               /* IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED) */
+
+                                                               if(!IsFlagOn(Vcb->Flags, VCB_READ_ONLY))
+                                                               {
+                                                                       CcFlushCache(&Fcb->SectionObject, NULL, 0, NULL);
+                                                                       ClearFlag(Fcb->Flags, FCB_FILE_MODIFIED);
+                                                               }
+
+                                                               CcPurgeCacheSection(&Fcb->SectionObject,
+                                                                               NULL,
+                                                                               0,
+                                                                               FALSE);
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+
+                       if (!IsDirectory(Fcb))
+                       {
+                               if (!IsFlagOn(Vcb->Flags, VCB_READ_ONLY))
+                               {
+                                       if ((CreateDisposition == FILE_SUPERSEDE) && !IsPagingFile)
+                                       {
+                                               DesiredAccess |= DELETE;
+                                       }
+                                       else if (((CreateDisposition == FILE_OVERWRITE) ||
+                                                               (CreateDisposition == FILE_OVERWRITE_IF)) && !IsPagingFile)
+                                       {
+                                               DesiredAccess |= (FILE_WRITE_DATA | FILE_WRITE_EA |
+                                                               FILE_WRITE_ATTRIBUTES);
+                                       }
+                               }
+                       }
+
+                       if (Fcb->OpenHandleCount > 0) 
+                       {
+                               Status = IoCheckShareAccess(DesiredAccess,
+                                               ShareAccess,
+                                               IrpSp->FileObject,
+                                               &(Fcb->ShareAccess),
+                                               TRUE);
+
+                               if (!NT_SUCCESS(Status))
+                               {
+                                       _SEH2_LEAVE;
+                               }
+                       } 
+                       else 
+                       {
+                               IoSetShareAccess(DesiredAccess,
+                                               ShareAccess,
+                                               IrpSp->FileObject,
+                                               &(Fcb->ShareAccess));
+                       }
+
+                       Ccb = FFSAllocateCcb();
+
+                       Fcb->OpenHandleCount++;
+                       Fcb->ReferenceCount++;
+
+                       if (IsFlagOn(IrpSp->FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING))
+                       {
+                               Fcb->NonCachedOpenCount++;
+                       }
+
+                       Vcb->OpenFileHandleCount++;
+                       Vcb->ReferenceCount++;
+
+                       IrpSp->FileObject->FsContext = (void*)Fcb;
+                       IrpSp->FileObject->FsContext2 = (void*) Ccb;
+                       IrpSp->FileObject->PrivateCacheMap = NULL;
+                       IrpSp->FileObject->SectionObjectPointer = &(Fcb->SectionObject);
+                       IrpSp->FileObject->Vpb = Vcb->Vpb;
+
+                       Status = STATUS_SUCCESS;
+
+                       FFSPrint((DBG_INFO, "FFSCreateFile: %s OpenCount: %u ReferCount: %u\n",
+                                               Fcb->AnsiFileName.Buffer, Fcb->OpenHandleCount, Fcb->ReferenceCount));
+
+                       if (!IsDirectory(Fcb) && !NoIntermediateBuffering)
+                       {
+                               IrpSp->FileObject->Flags |= FO_CACHE_SUPPORTED;
+                       }
+
+                       if (!bCreated && !IsDirectory(Fcb))
+                       {
+                               if (DeleteOnClose || 
+                                               IsFlagOn(DesiredAccess, FILE_WRITE_DATA) || 
+                                               (CreateDisposition == FILE_OVERWRITE) ||
+                                               (CreateDisposition == FILE_OVERWRITE_IF))
+                               {
+                                       if (!MmFlushImageSection(&Fcb->SectionObject,
+                                                               MmFlushForWrite))
+                                       {
+
+                                               Status = DeleteOnClose ? STATUS_CANNOT_DELETE :
+                                                       STATUS_SHARING_VIOLATION;
+                                               _SEH2_LEAVE;
+                                       }
+                               }
+
+                               if ((CreateDisposition == FILE_SUPERSEDE) ||
+                                               (CreateDisposition == FILE_OVERWRITE) ||
+                                               (CreateDisposition == FILE_OVERWRITE_IF))
+                               {
+#if FFS_READ_ONLY
+                                       Status = STATUS_MEDIA_WRITE_PROTECTED;
+                                       _SEH2_LEAVE;
+#else // !FFS_READ_ONLY
+                                       BOOLEAN bRet;
+
+                                       if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY))
+                                       {
+                                               Status = STATUS_MEDIA_WRITE_PROTECTED;
+                                               _SEH2_LEAVE;
+                                       }
+
+                                       if (IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED))
+                                       {
+                                               IoSetHardErrorOrVerifyDevice(IrpContext->Irp,
+                                                               Vcb->Vpb->RealDevice);
+                                               SetFlag(Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME);
+
+                                               FFSRaiseStatus(IrpContext, STATUS_MEDIA_WRITE_PROTECTED);
+                                       }
+
+                                       Status = FFSSupersedeOrOverWriteFile(IrpContext,
+                                                       Vcb,
+                                                       Fcb,
+                                                       CreateDisposition);
+
+                                       if (NT_SUCCESS(Status))
+                                       {
+                                               _SEH2_LEAVE;
+                                       }
+
+                                       bRet = FFSExpandFile(IrpContext,
+                                                       Vcb,
+                                                       Fcb,
+                                                       &(Irp->Overlay.AllocationSize));
+
+                                       if (!bRet)
+                                       {
+                                               Status = STATUS_DISK_FULL;
+                                               _SEH2_LEAVE;
+                                       }
+
+                                       FFSNotifyReportChange(
+                                                       IrpContext,
+                                                       Vcb,
+                                                       Fcb,
+                                                       FILE_NOTIFY_CHANGE_LAST_WRITE |
+                                                       FILE_NOTIFY_CHANGE_ATTRIBUTES |
+                                                       FILE_NOTIFY_CHANGE_SIZE,
+                                                       FILE_ACTION_MODIFIED);
+
+
+                                       if (CreateDisposition == FILE_SUPERSEDE)
+                                       {
+                                               Irp->IoStatus.Information = FILE_SUPERSEDED;
+                                       }
+                                       else
+                                       {
+                                               Irp->IoStatus.Information = FILE_OVERWRITTEN;
+                                       }
+#endif // !FFS_READ_ONLY
+                               }
+                       }
+               }
+       }
+
+       _SEH2_FINALLY
+       {
+               if (FileName.Buffer)
+                       ExFreePool(FileName.Buffer);
+
+               if (bParentFcbCreated)
+               {
+                       ParentFcb->ReferenceCount--;
+               }
+
+               if (VcbResourceAcquired)
+               {
+                       ExReleaseResourceForThreadLite(
+                                       &Vcb->MainResource,
+                                       ExGetCurrentResourceThread());
+               }
+
+               if (!bFcbAllocated)
+               {
+                       if (FS_VERSION == 1)
+                       {
+                               if (dinode1)
+                                       ExFreePool(dinode1);
+                       }
+                       else
+                       {
+                               if (dinode2)
+                                       ExFreePool(dinode2);
+                       }
+               }
+               else
+               {
+                       if (FS_VERSION == 1)
+                       {
+                               if (!Fcb && dinode1)
+                                       ExFreePool(dinode1);
+                       }
+                       else
+                       {
+                               if (!Fcb && dinode2)
+                                       ExFreePool(dinode2);
+                       }
+               }
+       } _SEH2_END;
+
+       return Status;
+}
+
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSCreateVolume(
+       PFFS_IRP_CONTEXT IrpContext,
+       PFFS_VCB         Vcb)
+{
+       PIO_STACK_LOCATION  IrpSp;
+       PIRP                Irp;
+
+       NTSTATUS            Status;
+
+       ACCESS_MASK         DesiredAccess;
+       ULONG               ShareAccess;
+
+       ULONG               Options;
+       BOOLEAN             DirectoryFile;
+       BOOLEAN             OpenTargetDirectory;
+
+       ULONG               CreateDisposition;
+
+    PAGED_CODE();
+
+       Irp = IrpContext->Irp;
+       IrpSp = IoGetCurrentIrpStackLocation(Irp);
+
+       Options  = IrpSp->Parameters.Create.Options;
+
+       DirectoryFile = IsFlagOn(Options, FILE_DIRECTORY_FILE);
+       OpenTargetDirectory = IsFlagOn(IrpSp->Flags, SL_OPEN_TARGET_DIRECTORY);
+
+       CreateDisposition = (Options >> 24) & 0x000000ff;
+
+       DesiredAccess = IrpSp->Parameters.Create.SecurityContext->DesiredAccess;
+       ShareAccess   = IrpSp->Parameters.Create.ShareAccess;
+
+       if (DirectoryFile)
+       {
+               return STATUS_NOT_A_DIRECTORY;
+       }
+
+       if (OpenTargetDirectory)
+       {
+               return STATUS_INVALID_PARAMETER;
+       }
+
+       if ((CreateDisposition != FILE_OPEN) && 
+                       (CreateDisposition != FILE_OPEN_IF)) 
+       {
+               return STATUS_ACCESS_DENIED;
+       }
+
+       Status = STATUS_SUCCESS;
+
+       if (Vcb->OpenHandleCount > 0) 
+       {
+               Status = IoCheckShareAccess(DesiredAccess, ShareAccess,
+                               IrpSp->FileObject,
+                               &(Vcb->ShareAccess), TRUE);
+
+               if (!NT_SUCCESS(Status)) 
+               {
+                       goto errorout;
+               }
+       } 
+       else 
+       {
+               IoSetShareAccess(DesiredAccess, ShareAccess,
+                               IrpSp->FileObject,
+                               &(Vcb->ShareAccess));
+       }
+
+       if (FlagOn(DesiredAccess, FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA))
+       {
+               ExAcquireResourceExclusiveLite(&Vcb->MainResource, TRUE);
+               FFSFlushFiles(Vcb, FALSE);
+               FFSFlushVolume(Vcb, FALSE);
+               ExReleaseResourceLite(&Vcb->MainResource);
+       }
+
+       {
+               PFFS_CCB Ccb = FFSAllocateCcb();
+
+               if (Ccb == NULL)
+               {
+                       Status = STATUS_INSUFFICIENT_RESOURCES;
+                       goto errorout;
+               }
+
+               IrpSp->FileObject->Flags |= FO_NO_INTERMEDIATE_BUFFERING;
+               IrpSp->FileObject->FsContext  = Vcb;
+               IrpSp->FileObject->FsContext2 = Ccb;
+
+               Vcb->ReferenceCount++;
+               Vcb->OpenHandleCount++;
+
+               Irp->IoStatus.Information = FILE_OPENED;
+       }
+
+errorout:
+
+       return Status;
+}
+
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSCreate(
+       IN PFFS_IRP_CONTEXT IrpContext)
+{
+       PDEVICE_OBJECT      DeviceObject;
+       PIRP                Irp;
+       PIO_STACK_LOCATION  IrpSp;
+       PFFS_VCB            Vcb = 0;
+       NTSTATUS            Status = STATUS_OBJECT_NAME_NOT_FOUND;
+       PFFS_FCBVCB         Xcb = NULL;
+
+    PAGED_CODE();
+
+       DeviceObject = IrpContext->DeviceObject;
+
+       Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;
+
+#if 0
+       /* µå¶óÀ̹ö°¡ ·Îµå µÇ¾ú´ÂÁö °Ë»çÇÒ ¶§ ¸¶¿îÆ®°¡ µÇ¾î ÀÖÁö ¾ÊÀº
+          °æ¿ìµµ Àֱ⠶§¹®¿¡ ¸ØÃ߸頾ȵÊ. */
+       ASSERT(IsMounted(Vcb));
+#endif 
+
+       Irp = IrpContext->Irp;
+
+       IrpSp = IoGetCurrentIrpStackLocation(Irp);
+
+       Xcb = (PFFS_FCBVCB)(IrpSp->FileObject->FsContext);
+
+       if (DeviceObject == FFSGlobal->DeviceObject)
+       {
+               FFSPrint((DBG_INFO, "FFSCreate: Create on main device object.\n"));
+
+               Status = STATUS_SUCCESS;
+
+               Irp->IoStatus.Information = FILE_OPENED;
+
+               FFSUnpinRepinnedBcbs(IrpContext);
+
+               FFSCompleteIrpContext(IrpContext, Status);        
+
+               return Status;
+
+       }
+
+       _SEH2_TRY
+       {
+               if (IsFlagOn(Vcb->Flags, VCB_VOLUME_LOCKED))
+               {
+                       Status = STATUS_ACCESS_DENIED;
+
+                       if (IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING))
+                       {
+                               Status = STATUS_VOLUME_DISMOUNTED;
+                       }
+
+                       _SEH2_LEAVE;
+               }
+
+               if (((IrpSp->FileObject->FileName.Length == 0) &&
+                                       (IrpSp->FileObject->RelatedFileObject == NULL)) || 
+                               (Xcb && Xcb->Identifier.Type == FFSVCB))
+               {
+                       Status = FFSCreateVolume(IrpContext, Vcb);
+               }
+               else
+               {
+                       Status = FFSCreateFile(IrpContext, Vcb);
+               }
+       }
+
+       _SEH2_FINALLY
+       {
+
+               if (!IrpContext->ExceptionInProgress)
+               {
+                       FFSUnpinRepinnedBcbs(IrpContext);
+
+                       FFSCompleteIrpContext(IrpContext, Status);
+               }
+       } _SEH2_END;
+
+       return Status;
+}
+
+#if !FFS_READ_ONLY
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSCreateInode(
+       PFFS_IRP_CONTEXT    IrpContext,
+       PFFS_VCB            Vcb,
+       PFFS_FCB            ParentFcb,
+       ULONG               Type,
+       ULONG               FileAttr,
+       PUNICODE_STRING     FileName)
+{
+       NTSTATUS    Status;
+       ULONG       Inode;
+       ULONG       Group;
+
+       FFSv1_INODE dinode1;
+
+    PAGED_CODE();
+
+       RtlZeroMemory(&dinode1, DINODE1_SIZE);
+
+       Group = (ParentFcb->FFSMcb->Inode - 1) / BLOCKS_PER_GROUP;
+
+       FFSPrint((DBG_INFO,
+                               "FFSCreateInode: %S in %S(Inode=%xh)\n",
+                               FileName->Buffer, 
+                               ParentFcb->FFSMcb->ShortName.Buffer, 
+                               ParentFcb->FFSMcb->Inode));
+
+       Status = FFSNewInode(IrpContext, Vcb, Group,Type, &Inode);
+
+       if (!NT_SUCCESS(Status))
+       {
+               goto errorout;
+       }
+
+       Status = FFSAddEntry(IrpContext, Vcb, ParentFcb, Type, Inode, FileName);
+
+       if (!NT_SUCCESS(Status))
+       {
+               FFSBreakPoint();
+               FFSFreeInode(IrpContext, Vcb, Inode, Type);
+
+               goto errorout;
+       }
+
+       FFSv1SaveInode(IrpContext, Vcb, ParentFcb->FFSMcb->Inode, ParentFcb->dinode1);
+
+       dinode1.di_ctime = ParentFcb->dinode1->di_mtime;
+       dinode1.di_mode =  0x1FF;
+
+       if (IsFlagOn(FileAttr, FILE_ATTRIBUTE_READONLY))
+       {
+               FFSSetReadOnly(dinode1.di_mode);
+       }
+
+       if (Type == DT_DIR)
+       {
+               SetFlag(dinode1.di_mode, IFDIR);
+
+               dinode1.di_nlink = 2;
+       }
+       else
+       {
+               dinode1.di_nlink = 1;
+               SetFlag(dinode1.di_mode, IFLNK);
+       }
+
+       FFSv1SaveInode(IrpContext, Vcb, Inode, &dinode1);
+
+       FFSPrint((DBG_INFO, "FFSCreateInode: New Inode = %xh (Type=%xh)\n", Inode, Type));
+
+errorout:
+
+       return Status;
+}
+
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSSupersedeOrOverWriteFile(
+       IN PFFS_IRP_CONTEXT IrpContext,
+       IN PFFS_VCB         Vcb,
+       IN PFFS_FCB         Fcb,
+       IN ULONG            Disposition)
+{
+       LARGE_INTEGER   CurrentTime;
+       LARGE_INTEGER   AllocationSize;
+       NTSTATUS        Status = STATUS_SUCCESS;
+
+       BOOLEAN         bRet = FALSE;
+
+    PAGED_CODE();
+
+       KeQuerySystemTime(&CurrentTime);
+
+       AllocationSize.QuadPart = (LONGLONG)0;
+
+       if (!MmCanFileBeTruncated(&(Fcb->SectionObject), &(AllocationSize))) 
+       {
+               Status = STATUS_USER_MAPPED_FILE;
+
+               return Status;
+       }
+
+       bRet = FFSTruncateFile(IrpContext, Vcb, Fcb, &AllocationSize);
+
+       if (bRet)
+       {
+               Fcb->Header.AllocationSize.QuadPart = 
+                       Fcb->Header.FileSize.QuadPart = (LONGLONG)0;
+
+               Fcb->dinode1->di_size = 0;
+
+               if (Disposition == FILE_SUPERSEDE)
+                       Fcb->dinode1->di_ctime = FFSInodeTime(CurrentTime);
+
+               Fcb->dinode1->di_atime =
+                       Fcb->dinode1->di_mtime = FFSInodeTime(CurrentTime);
+       }
+       else
+       {
+               if (Fcb->dinode1->di_size > Fcb->Header.AllocationSize.LowPart)
+                       Fcb->dinode1->di_size = Fcb->Header.AllocationSize.LowPart;
+
+               Fcb->Header.FileSize.QuadPart = (LONGLONG)Fcb->dinode1->di_size;
+
+               Status = STATUS_UNSUCCESSFUL;
+       }
+
+       FFSv1SaveInode(IrpContext, Vcb, Fcb->FFSMcb->Inode, Fcb->dinode1);
+
+       return Status;
+}
+
+#endif // !FFS_READ_ONLY
diff --git a/reactos/drivers/filesystems/ffs/src/debug.c b/reactos/drivers/filesystems/ffs/src/debug.c
new file mode 100644 (file)
index 0000000..fd8d07f
--- /dev/null
@@ -0,0 +1,1780 @@
+/* 
+ * FFS File System Driver for Windows
+ *
+ * debug.c
+ *
+ * 2004.5.6 ~
+ *
+ * Lee Jae-Hong, http://www.pyrasis.com
+ *
+ * See License.txt
+ *
+ */
+
+#if DBG
+
+#include "ntifs.h"
+#include "ffsdrv.h"
+#include "stdarg.h"
+#include "stdio.h"
+
+
+/* Globals */
+
+extern PFFS_GLOBAL FFSGlobal;
+
+#define SYSTEM_PROCESS_NAME "System"
+
+extern PFFS_GLOBAL FFSGlobal;
+
+LONG   DebugLevel = DBG_USER;
+
+ULONG  ProcessNameOffset = 0;
+
+/* Definitions */
+
+#ifdef ALLOC_PRAGMA
+//#pragma alloc_text (PAGE, FFSPrintf)
+//#pragma alloc_text (PAGE, FFSNIPrintf)
+#pragma alloc_text (PAGE, FFSGetProcessNameOffset)
+//#pragma alloc_text (PAGE, FFSDbgPrintCall)
+//#pragma alloc_text (PAGE, FFSDbgPrintComplete)
+//#pragma alloc_text (PAGE, FFSNtStatusToString)
+#endif // ALLOC_PRAGMA
+
+/* Static Definitions ****************************************************/
+
+static PCHAR IrpMjStrings[] = {
+       "IRP_MJ_CREATE",
+       "IRP_MJ_CREATE_NAMED_PIPE",
+       "IRP_MJ_CLOSE",
+       "IRP_MJ_READ",
+       "IRP_MJ_WRITE",
+       "IRP_MJ_QUERY_INFORMATION",
+       "IRP_MJ_SET_INFORMATION",
+       "IRP_MJ_QUERY_EA",
+       "IRP_MJ_SET_EA",
+       "IRP_MJ_FLUSH_BUFFERS",
+       "IRP_MJ_QUERY_VOLUME_INFORMATION",
+       "IRP_MJ_SET_VOLUME_INFORMATION",
+       "IRP_MJ_DIRECTORY_CONTROL",
+       "IRP_MJ_FILE_SYSTEM_CONTROL",
+       "IRP_MJ_DEVICE_CONTROL",
+       "IRP_MJ_INTERNAL_DEVICE_CONTROL",
+       "IRP_MJ_SHUTDOWN",
+       "IRP_MJ_LOCK_CONTROL",
+       "IRP_MJ_CLEANUP",
+       "IRP_MJ_CREATE_MAILSLOT",
+       "IRP_MJ_QUERY_SECURITY",
+       "IRP_MJ_SET_SECURITY",
+       "IRP_MJ_POWER",
+       "IRP_MJ_SYSTEM_CONTROL",
+       "IRP_MJ_DEVICE_CHANGE",
+       "IRP_MJ_QUERY_QUOTA",
+       "IRP_MJ_SET_QUOTA",
+       "IRP_MJ_PNP"
+};
+
+static PCHAR FileInformationClassStrings[] = {
+       "Unknown FileInformationClass 0",
+       "FileDirectoryInformation",
+       "FileFullDirectoryInformation",
+       "FileBothDirectoryInformation",
+       "FileBasicInformation",
+       "FileStandardInformation",
+       "FileInternalInformation",
+       "FileEaInformation",
+       "FileAccessInformation",
+       "FileNameInformation",
+       "FileRenameInformation",
+       "FileLinkInformation",
+       "FileNamesInformation",
+       "FileDispositionInformation",
+       "FilePositionInformation",
+       "FileFullEaInformation",
+       "FileModeInformation",
+       "FileAlignmentInformation",
+       "FileAllInformation",
+       "FileAllocationInformation",
+       "FileEndOfFileInformation",
+       "FileAlternateNameInformation",
+       "FileStreamInformation",
+       "FilePipeInformation",
+       "FilePipeLocalInformation",
+       "FilePipeRemoteInformation",
+       "FileMailslotQueryInformation",
+       "FileMailslotSetInformation",
+       "FileCompressionInformation",
+       "FileObjectIdInformation",
+       "FileCompletionInformation",
+       "FileMoveClusterInformation",
+       "FileQuotaInformation",
+       "FileReparsePointInformation",
+       "FileNetworkOpenInformation",
+       "FileAttributeTagInformation",
+       "FileTrackingInformation"
+};
+
+static PCHAR FsInformationClassStrings[] = {
+       "Unknown FsInformationClass 0",
+       "FileFsVolumeInformation",
+       "FileFsLabelInformation",
+       "FileFsSizeInformation",
+       "FileFsDeviceInformation",
+       "FileFsAttributeInformation",
+       "FileFsControlInformation",
+       "FileFsFullSizeInformation",
+       "FileFsObjectIdInformation"
+};
+
+/*
+ * FFSPrintf
+ *   This function is variable-argument, level-sensitive debug print routine.
+ *   If the specified debug level for the print statement is lower or equal
+ *   to the current debug level, the message will be printed.
+ *
+ * Arguments:
+ *   DebugPrintLevel - Specifies at which debugging level the string should
+ *                     be printed
+ *   DebugMessage - Variable argument ascii c string
+ *
+ * Return Value:
+ *   N/A
+ *
+ * NOTES: 
+ *   N/A
+ */
+
+VOID
+FFSPrintf(
+       LONG  DebugPrintLevel,
+       PCHAR DebugMessage,
+       ...)
+{
+       va_list             ap;
+       LARGE_INTEGER       CurrentTime;
+       TIME_FIELDS         TimeFields;
+
+       ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
+
+       if (DebugPrintLevel <= DebugLevel)
+       {
+               CHAR Buffer[0x100];
+               va_start(ap, DebugMessage);
+
+               KeQuerySystemTime(&CurrentTime);
+               RtlTimeToTimeFields(&CurrentTime, &TimeFields);
+
+               vsprintf(Buffer, DebugMessage, ap);
+
+               DbgPrint(DRIVER_NAME": %2.2d:%2.2d:%2.2d:%3.3d %8.8x:   %s",
+                               TimeFields.Hour, TimeFields.Minute,
+                               TimeFields.Second, TimeFields.Milliseconds,
+                               PsGetCurrentThread(), Buffer);
+
+               va_end(ap);
+       }
+
+
+       ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
+
+} // FFSPrintf()
+
+
+/*
+ * FFSNIPrintf
+ *   This function is variable-argument, level-sensitive debug print routine.
+ *   If the specified debug level for the print statement is lower or equal
+ *   to the current debug level, the message will be printed.
+ *
+ * Arguments:
+ *   DebugPrintLevel - Specifies at which debugging level the string should
+ *                     be printed
+ *   DebugMessage - Variable argument ascii c string
+ *
+ * Return Value:
+ *   N/A
+ *
+ * NOTES: 
+ *   N/A
+ */
+
+VOID
+FFSNIPrintf(
+       LONG  DebugPrintLevel,
+       PCHAR DebugMessage,
+       ...)
+{
+       va_list             ap;
+       LARGE_INTEGER       CurrentTime;
+       TIME_FIELDS         TimeFields;
+
+       ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
+
+       if (DebugPrintLevel <= DebugLevel)
+       {
+               CHAR Buffer[0x100];
+               va_start(ap, DebugMessage);
+
+               KeQuerySystemTime(&CurrentTime);
+               RtlTimeToTimeFields(&CurrentTime, &TimeFields);
+
+               vsprintf(Buffer, DebugMessage, ap);
+
+               DbgPrint(DRIVER_NAME": %2.2d:%2.2d:%2.2d:%3.3d %8.8x: %s",
+                               TimeFields.Hour, TimeFields.Minute,
+                               TimeFields.Second, TimeFields.Milliseconds,
+                               PsGetCurrentThread(), Buffer);
+
+               va_end(ap);
+       }
+
+
+       ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
+
+} // FFSNIPrintf()
+
+ULONG 
+FFSGetProcessNameOffset(
+       VOID)
+{
+       PEPROCESS   Process;
+       ULONG       i;
+
+    PAGED_CODE();
+
+       Process = PsGetCurrentProcess();
+
+       for(i = 0; i < PAGE_SIZE; i++)
+       {
+               if(!strncmp(
+                                       SYSTEM_PROCESS_NAME,
+                                       (PCHAR) Process + i,
+                                       strlen(SYSTEM_PROCESS_NAME)))
+               {
+                       return i;
+               }
+       }
+
+       FFSPrint((DBG_ERROR, ": *** FsdGetProcessNameOffset failed ***\n"));
+
+       return 0;
+}
+
+
+VOID
+FFSDbgPrintCall(
+       IN PDEVICE_OBJECT   DeviceObject,
+       IN PIRP             Irp)
+{
+       PIO_STACK_LOCATION      IoStackLocation;
+       PFILE_OBJECT            FileObject;
+       PCHAR                   FileName;
+       PFFS_FCB                Fcb;
+       FILE_INFORMATION_CLASS  FileInformationClass;
+       FS_INFORMATION_CLASS    FsInformationClass;
+
+       IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
+
+       FileObject = IoStackLocation->FileObject;
+
+       FileName = "Unknown";
+
+       if (DeviceObject == FFSGlobal->DeviceObject)
+       {
+               FileName = "\\" DRIVER_NAME;
+       }
+       else if (FileObject && FileObject->FsContext)
+       {
+               Fcb = (PFFS_FCB)FileObject->FsContext;
+
+               if (Fcb->Identifier.Type == FFSVCB)
+               {
+                       FileName = "\\Volume";
+               }
+               else if (Fcb->Identifier.Type == FFSFCB && Fcb->AnsiFileName.Buffer)
+               {
+                       FileName = Fcb->AnsiFileName.Buffer;
+               }
+       }
+
+       switch (IoStackLocation->MajorFunction)
+       {
+               case IRP_MJ_CREATE:
+
+                       FileName = NULL;
+
+                       if (DeviceObject == FFSGlobal->DeviceObject)
+                       {
+                               FileName = "\\" DRIVER_NAME;
+                       }
+                       else if (FileObject && FileObject->FileName.Length == 0)
+                       {
+                               FileName = "\\Volume";
+                       }
+
+                       if (FileName)
+                       {
+                               FFSPrintNoIndent((
+                                                       DBG_TRACE, "%s %s %s\n",
+                                                       FFSGetCurrentProcessName(),
+                                                       IrpMjStrings[IoStackLocation->MajorFunction],
+                                                       FileName));
+                       }
+                       else if (FileObject && FileObject->FileName.Buffer)
+                       {
+                               FFSPrintNoIndent((
+                                                       DBG_TRACE, "%s %s %S\n",
+                                                       FFSGetCurrentProcessName(),
+                                                       IrpMjStrings[IoStackLocation->MajorFunction],
+                                                       IoStackLocation->FileObject->FileName.Buffer));
+                       }
+                       else
+                       {
+                               FFSPrintNoIndent((
+                                                       DBG_TRACE, "%s %s %s\n",
+                                                       FFSGetCurrentProcessName(),
+                                                       IrpMjStrings[IoStackLocation->MajorFunction],
+                                                       "Unknown"));
+                       }
+
+                       break;
+
+               case IRP_MJ_CLOSE:
+
+                       FFSPrintNoIndent((
+                                               DBG_TRACE, "%s %s %s\n",
+                                               FFSGetCurrentProcessName(),
+                                               IrpMjStrings[IoStackLocation->MajorFunction],
+                                               FileName));
+
+                       break;
+
+               case IRP_MJ_READ:
+
+                       if (IoStackLocation->MinorFunction & IRP_MN_COMPLETE)
+                       {
+                               FFSPrintNoIndent((
+                                                       DBG_TRACE, "%s %s %s IRP_MN_COMPLETE\n",
+                                                       FFSGetCurrentProcessName(),
+                                                       IrpMjStrings[IoStackLocation->MajorFunction],
+                                                       FileName));
+                       }
+                       else
+                       {
+                               FFSPrintNoIndent((
+                                                       DBG_TRACE, "%s %s %s Offset: %I64xh Length: %xh %s%s%s%s%s%s\n",
+                                                       FFSGetCurrentProcessName(),
+                                                       IrpMjStrings[IoStackLocation->MajorFunction],
+                                                       FileName,
+                                                       IoStackLocation->Parameters.Read.ByteOffset.QuadPart,
+                                                       IoStackLocation->Parameters.Read.Length,
+                                                       (IoStackLocation->MinorFunction & IRP_MN_DPC ? "IRP_MN_DPC " : " "),
+                                                       (IoStackLocation->MinorFunction & IRP_MN_MDL ? "IRP_MN_MDL " : " "),
+                                                       (IoStackLocation->MinorFunction & IRP_MN_COMPRESSED ? "IRP_MN_COMPRESSED " : " "),
+                                                       (Irp->Flags & IRP_PAGING_IO ? "IRP_PAGING_IO " : " "),
+                                                       (Irp->Flags & IRP_NOCACHE ? "IRP_NOCACHE " : " "),
+                                                       (FileObject->Flags & FO_SYNCHRONOUS_IO ? "FO_SYNCHRONOUS_IO " : " ")));
+                       }
+
+                       break;
+
+               case IRP_MJ_WRITE:
+
+                       if (IoStackLocation->MinorFunction & IRP_MN_COMPLETE)
+                       {
+                               FFSPrintNoIndent((
+                                                       DBG_TRACE, "%s %s %s IRP_MN_COMPLETE\n",
+                                                       FFSGetCurrentProcessName(),
+                                                       IrpMjStrings[IoStackLocation->MajorFunction],
+                                                       FileName));
+                       }
+                       else
+                       {
+                               FFSPrintNoIndent((
+                                                       DBG_TRACE, "%s %s %s Offset: %I64xh Length: %xh %s%s%s%s%s%s\n",
+                                                       FFSGetCurrentProcessName(),
+                                                       IrpMjStrings[IoStackLocation->MajorFunction],
+                                                       FileName,
+                                                       IoStackLocation->Parameters.Read.ByteOffset.QuadPart,
+                                                       IoStackLocation->Parameters.Read.Length,
+                                                       (IoStackLocation->MinorFunction & IRP_MN_DPC ? "IRP_MN_DPC " : " "),
+                                                       (IoStackLocation->MinorFunction & IRP_MN_MDL ? "IRP_MN_MDL " : " "),
+                                                       (IoStackLocation->MinorFunction & IRP_MN_COMPRESSED ? "IRP_MN_COMPRESSED " : " "),
+                                                       (Irp->Flags & IRP_PAGING_IO ? "IRP_PAGING_IO " : " "),
+                                                       (Irp->Flags & IRP_NOCACHE ? "IRP_NOCACHE " : " "),
+                                                       (FileObject->Flags & FO_SYNCHRONOUS_IO ? "FO_SYNCHRONOUS_IO " : " ")));
+                       }
+
+                       break;
+
+               case IRP_MJ_QUERY_INFORMATION:
+
+                       FileInformationClass =
+                               IoStackLocation->Parameters.QueryFile.FileInformationClass;
+
+                       if (FileInformationClass <= FileMaximumInformation)
+                       {
+                               FFSPrintNoIndent((
+                                                       DBG_TRACE, "%s %s %s %s\n",
+                                                       FFSGetCurrentProcessName(),
+                                                       IrpMjStrings[IoStackLocation->MajorFunction],
+                                                       FileName,
+                                                       FileInformationClassStrings[FileInformationClass]));
+                       }
+                       else
+                       {
+                               FFSPrintNoIndent((
+                                                       DBG_TRACE,
+                                                       "%s %s %s Unknown FileInformationClass %u\n",
+                                                       FFSGetCurrentProcessName(),
+                                                       IrpMjStrings[IoStackLocation->MajorFunction],
+                                                       FileName,
+                                                       FileInformationClass));
+                       }
+
+                       break;
+
+               case IRP_MJ_SET_INFORMATION:
+
+                       FileInformationClass =
+                               IoStackLocation->Parameters.SetFile.FileInformationClass;
+
+                       if (FileInformationClass <= FileMaximumInformation)
+                       {
+                               FFSPrintNoIndent((
+                                                       DBG_TRACE, "%s %s %s %s\n",
+                                                       FFSGetCurrentProcessName(),
+                                                       IrpMjStrings[IoStackLocation->MajorFunction],
+                                                       FileName,
+                                                       FileInformationClassStrings[FileInformationClass]));
+                       }
+                       else
+                       {
+                               FFSPrintNoIndent((
+                                                       DBG_TRACE, 
+                                                       "%s %s %s Unknown FileInformationClass %u\n",
+                                                       FFSGetCurrentProcessName(),
+                                                       IrpMjStrings[IoStackLocation->MajorFunction],
+                                                       FileName,
+                                                       FileInformationClass));
+                       }
+
+                       break;
+
+               case IRP_MJ_QUERY_VOLUME_INFORMATION:
+
+                       FsInformationClass =
+                               IoStackLocation->Parameters.QueryVolume.FsInformationClass;
+
+                       if (FsInformationClass <= FileFsMaximumInformation)
+                       {
+                               FFSPrintNoIndent((
+                                                       DBG_TRACE, "%s %s %s %s\n",
+                                                       FFSGetCurrentProcessName(),
+                                                       IrpMjStrings[IoStackLocation->MajorFunction],
+                                                       FileName,
+                                                       FsInformationClassStrings[FsInformationClass]));
+                       }
+                       else
+                       {
+                               FFSPrintNoIndent((
+                                                       DBG_TRACE, 
+                                                       "%s %s %s Unknown FsInformationClass %u\n",
+                                                       FFSGetCurrentProcessName(),
+                                                       IrpMjStrings[IoStackLocation->MajorFunction],
+                                                       FileName,
+                                                       FsInformationClass));
+                       }
+
+                       break;
+
+               case IRP_MJ_DIRECTORY_CONTROL:
+
+                       if (IoStackLocation->MinorFunction & IRP_MN_QUERY_DIRECTORY)
+                       {
+#if !defined(_GNU_NTIFS_) || defined(__REACTOS__)
+                               FileInformationClass =
+                                       IoStackLocation->Parameters.QueryDirectory.FileInformationClass;
+#else
+                               FileInformationClass = ((PEXTENDED_IO_STACK_LOCATION)
+                                               IoStackLocation)->Parameters.QueryDirectory.FileInformationClass;
+#endif
+
+                               if (FileInformationClass <= FileMaximumInformation)
+                               {
+                                       FFSPrintNoIndent((
+                                                               DBG_TRACE, "%s %s %s %s\n",
+                                                               FFSGetCurrentProcessName(),
+                                                               IrpMjStrings[IoStackLocation->MajorFunction],
+                                                               FileName,
+                                                               FileInformationClassStrings[FileInformationClass]));
+
+                                       if (
+#if !defined(_GNU_NTIFS_) || defined(__REACTOS__)
+                                                       IoStackLocation->Parameters.QueryDirectory.FileName
+#else
+                                                       ((PEXTENDED_IO_STACK_LOCATION)
+                                                        IoStackLocation)->Parameters.QueryDirectory.FileName
+#endif
+                                          )
+                                       {
+#if !defined(_GNU_NTIFS_) || defined(__REACTOS__)
+                                               FFSPrintNoIndent((
+                                                                       DBG_TRACE, "%s FileName: %.*S FileIndex: %x %s%s%s\n",
+                                                                       FFSGetCurrentProcessName(),
+
+                                                                       IoStackLocation->Parameters.QueryDirectory.FileName->Length / 2,
+                                                                       IoStackLocation->Parameters.QueryDirectory.FileName->Buffer,
+                                                                       IoStackLocation->Parameters.QueryDirectory.FileIndex,
+                                                                       (IoStackLocation->Flags & SL_RESTART_SCAN ? "SL_RESTART_SCAN " : ""),
+                                                                       (IoStackLocation->Flags & SL_RETURN_SINGLE_ENTRY ? "SL_RETURN_SINGLE_ENTRY " : ""),
+                                                                       ((IoStackLocation->Flags & SL_INDEX_SPECIFIED) ? "SL_INDEX_SPECIFIED " : "")));
+
+#else
+                                               FFSPrintNoIndent((
+                                                                       DBG_TRACE, "%s FileName: %.*S FileIndex: %x %s%s%s\n",
+                                                                       FFSGetCurrentProcessName(),
+
+                                                                       ((PEXTENDED_IO_STACK_LOCATION)
+                                                                        IoStackLocation)->Parameters.QueryDirectory.FileName->Length / 2,
+                                                                       ((PEXTENDED_IO_STACK_LOCATION)
+                                                                        IoStackLocation)->Parameters.QueryDirectory.FileName->Buffer,
+                                                                       ((PEXTENDED_IO_STACK_LOCATION)
+                                                                        IoStackLocation)->Parameters.QueryDirectory.FileIndex,
+                                                                       (IoStackLocation->Flags & SL_RESTART_SCAN ? "SL_RESTART_SCAN " : ""),
+                                                                       (IoStackLocation->Flags & SL_RETURN_SINGLE_ENTRY ? "SL_RETURN_SINGLE_ENTRY " : ""),
+                                                                       ((IoStackLocation->Flags & SL_INDEX_SPECIFIED) ? "SL_INDEX_SPECIFIED " : "")));
+#endif
+                                       }
+                                       else
+                                       {
+#if !defined(_GNU_NTIFS_) || defined(__REACTOS__)
+                                               FFSPrintNoIndent((
+                                                                       DBG_TRACE, "%s FileName: FileIndex: %#x %s%s%s\n",
+                                                                       FFSGetCurrentProcessName(),
+                                                                       IoStackLocation->Parameters.QueryDirectory.FileIndex,
+                                                                       (IoStackLocation->Flags & SL_RESTART_SCAN ? "SL_RESTART_SCAN " : ""),
+                                                                       (IoStackLocation->Flags & SL_RETURN_SINGLE_ENTRY ? "SL_RETURN_SINGLE_ENTRY " : ""),
+                                                                       (IoStackLocation->Flags & SL_INDEX_SPECIFIED ? "SL_INDEX_SPECIFIED " : "")));
+#else
+                                               FFSPrintNoIndent((
+                                                                       DBG_TRACE, "%s FileName: FileIndex: %#x %s%s%s\n",
+                                                                       FFSGetCurrentProcessName(),
+                                                                       ((PEXTENDED_IO_STACK_LOCATION)
+                                                                        IoStackLocation)->Parameters.QueryDirectory.FileIndex,
+                                                                       (IoStackLocation->Flags & SL_RESTART_SCAN ? "SL_RESTART_SCAN " : ""),
+                                                                       (IoStackLocation->Flags & SL_RETURN_SINGLE_ENTRY ? "SL_RETURN_SINGLE_ENTRY " : ""),
+                                                                       (IoStackLocation->Flags & SL_INDEX_SPECIFIED ? "SL_INDEX_SPECIFIED " : "")));
+#endif
+                                       }
+                               }
+                               else
+                               {
+                                       FFSPrintNoIndent((
+                                                               DBG_TRACE, 
+                                                               "%s %s %s Unknown FileInformationClass %u\n",
+                                                               FFSGetCurrentProcessName(),
+                                                               IrpMjStrings[IoStackLocation->MajorFunction],
+                                                               FileName,
+                                                               FileInformationClass));
+                               }
+                       }
+                       else if (IoStackLocation->MinorFunction & IRP_MN_NOTIFY_CHANGE_DIRECTORY)
+                       {
+                               FFSPrintNoIndent((
+                                                       DBG_TRACE, "%s %s %s IRP_MN_NOTIFY_CHANGE_DIRECTORY\n",
+                                                       FFSGetCurrentProcessName(),
+                                                       IrpMjStrings[IoStackLocation->MajorFunction],
+                                                       FileName));
+                       }
+                       else
+                       {
+                               FFSPrintNoIndent((
+                                                       DBG_TRACE, "%s %s %s Unknown minor function %#x\n",
+                                                       FFSGetCurrentProcessName(),
+                                                       IrpMjStrings[IoStackLocation->MajorFunction],
+                                                       FileName,
+                                                       IoStackLocation->MinorFunction));
+                       }
+
+                       break;
+
+               case IRP_MJ_FILE_SYSTEM_CONTROL:
+
+                       if (IoStackLocation->MinorFunction == IRP_MN_USER_FS_REQUEST)
+                       {
+#if !defined(_GNU_NTIFS_) || defined(__REACTOS__)
+                               FFSPrintNoIndent((
+                                                       DBG_TRACE, 
+                                                       "%s %s %s IRP_MN_USER_FS_REQUEST FsControlCode: %#x\n",
+                                                       FFSGetCurrentProcessName(),
+                                                       IrpMjStrings[IoStackLocation->MajorFunction],
+                                                       FileName,
+                                                       IoStackLocation->Parameters.FileSystemControl.FsControlCode));
+#else
+                               FFSPrintNoIndent((
+                                                       DBG_TRACE, 
+                                                       "%s %s %s IRP_MN_USER_FS_REQUEST FsControlCode: %#x\n",
+                                                       FFSGetCurrentProcessName(),
+                                                       IrpMjStrings[IoStackLocation->MajorFunction],
+                                                       FileName,
+                                                       ((PEXTENDED_IO_STACK_LOCATION)
+                                                        IoStackLocation)->Parameters.FileSystemControl.FsControlCode));
+#endif
+                       }
+                       else if (IoStackLocation->MinorFunction == IRP_MN_MOUNT_VOLUME)
+                       {
+                               FFSPrintNoIndent((
+                                                       DBG_TRACE, 
+                                                       "%s %s %s IRP_MN_MOUNT_VOLUME DeviceObject: %#x\n",
+                                                       FFSGetCurrentProcessName(),
+                                                       IrpMjStrings[IoStackLocation->MajorFunction],
+                                                       FileName,
+                                                       IoStackLocation->Parameters.MountVolume.DeviceObject));
+                       }
+                       else if (IoStackLocation->MinorFunction == IRP_MN_VERIFY_VOLUME)
+                       {
+                               FFSPrintNoIndent((
+                                                       DBG_TRACE, 
+                                                       "%s %s %s IRP_MN_VERIFY_VOLUME DeviceObject: %#x\n",
+                                                       FFSGetCurrentProcessName(),
+                                                       IrpMjStrings[IoStackLocation->MajorFunction],
+                                                       FileName,
+                                                       IoStackLocation->Parameters.VerifyVolume.DeviceObject));
+                       }
+                       else if (IoStackLocation->MinorFunction == IRP_MN_LOAD_FILE_SYSTEM)
+                       {
+                               FFSPrintNoIndent((
+                                                       DBG_TRACE, "%s %s %s IRP_MN_LOAD_FILE_SYSTEM\n",
+                                                       FFSGetCurrentProcessName(),
+                                                       IrpMjStrings[IoStackLocation->MajorFunction],
+                                                       FileName));
+                       }
+#if (_WIN32_WINNT >= 0x0500)
+                       else if (IoStackLocation->MinorFunction == IRP_MN_KERNEL_CALL)
+                       {
+                               FFSPrintNoIndent((
+                                                       DBG_TRACE, "%s %s %s IRP_MN_KERNEL_CALL\n",
+                                                       FFSGetCurrentProcessName(),
+                                                       IrpMjStrings[IoStackLocation->MajorFunction],
+                                                       FileName));
+                       }
+#endif // (_WIN32_WINNT >= 0x0500)
+                       else
+                       {
+                               FFSPrintNoIndent((
+                                                       DBG_TRACE, "%s %s %s Unknown minor function %#x\n",
+                                                       FFSGetCurrentProcessName(),
+                                                       IrpMjStrings[IoStackLocation->MajorFunction],
+                                                       FileName,
+                                                       IoStackLocation->MinorFunction));
+                       }
+
+                       break;
+
+               case IRP_MJ_DEVICE_CONTROL:
+
+                       FFSPrintNoIndent((
+                                               DBG_TRACE, "%s %s %s IoControlCode: %#x\n",
+                                               FFSGetCurrentProcessName(),
+                                               IrpMjStrings[IoStackLocation->MajorFunction],
+                                               FileName,
+                                               IoStackLocation->Parameters.DeviceIoControl.IoControlCode));
+
+                       break;
+
+               case IRP_MJ_LOCK_CONTROL:
+
+                       if (IoStackLocation->MinorFunction & IRP_MN_LOCK)
+                       {
+#if !defined(_GNU_NTIFS_) || defined(__REACTOS__)
+                               FFSPrintNoIndent((
+                                                       DBG_TRACE, "%s %s %s IRP_MN_LOCK Offset: %I64xh Length: %I64xh Key: %u %s%s\n",
+                                                       FFSGetCurrentProcessName(),
+                                                       IrpMjStrings[IoStackLocation->MajorFunction],
+                                                       FileName,
+                                                       IoStackLocation->Parameters.LockControl.ByteOffset.QuadPart,
+                                                       IoStackLocation->Parameters.LockControl.Length->QuadPart,
+                                                       IoStackLocation->Parameters.LockControl.Key,
+                                                       (IoStackLocation->Flags & SL_FAIL_IMMEDIATELY ? "SL_FAIL_IMMEDIATELY " : ""),
+                                                       (IoStackLocation->Flags & SL_EXCLUSIVE_LOCK ? "SL_EXCLUSIVE_LOCK " : "")));
+#else
+                               FFSPrintNoIndent((
+                                                       DBG_TRACE, "%s %s %s IRP_MN_LOCK Offset: %I64xh Length: %I64xh Key: %u %s%s\n",
+                                                       FFSGetCurrentProcessName(),
+                                                       IrpMjStrings[IoStackLocation->MajorFunction],
+                                                       FileName,
+                                                       ((PEXTENDED_IO_STACK_LOCATION)
+                                                        IoStackLocation)->Parameters.LockControl.ByteOffset.QuadPart,
+                                                       ((PEXTENDED_IO_STACK_LOCATION)
+                                                        IoStackLocation)->Parameters.LockControl.Length->QuadPart,
+                                                       ((PEXTENDED_IO_STACK_LOCATION)
+                                                        IoStackLocation)->Parameters.LockControl.Key,
+                                                       (IoStackLocation->Flags & SL_FAIL_IMMEDIATELY ? "SL_FAIL_IMMEDIATELY " : ""),
+                                                       (IoStackLocation->Flags & SL_EXCLUSIVE_LOCK ? "SL_EXCLUSIVE_LOCK " : "")));
+#endif
+                       }
+                       else if (IoStackLocation->MinorFunction & IRP_MN_UNLOCK_SINGLE)
+                       {
+#if !defined(_GNU_NTIFS_) || defined(__REACTOS__)
+                               FFSPrintNoIndent((
+                                                       DBG_TRACE, "%s %s %s IRP_MN_UNLOCK_SINGLE Offset: %I64xh Length: %I64xh Key: %u\n",
+                                                       FFSGetCurrentProcessName(),
+                                                       IrpMjStrings[IoStackLocation->MajorFunction],
+                                                       FileName,
+                                                       IoStackLocation->Parameters.LockControl.ByteOffset.QuadPart,
+                                                       IoStackLocation->Parameters.LockControl.Length->QuadPart,
+                                                       IoStackLocation->Parameters.LockControl.Key));
+#else
+                               FFSPrintNoIndent((
+                                                       DBG_TRACE, "%s %s %s IRP_MN_UNLOCK_SINGLE Offset: %I64xh Length: %I64xh Key: %u\n",
+                                                       FFSGetCurrentProcessName(),
+                                                       IrpMjStrings[IoStackLocation->MajorFunction],
+                                                       FileName,
+                                                       ((PEXTENDED_IO_STACK_LOCATION)
+                                                        IoStackLocation)->Parameters.LockControl.ByteOffset.QuadPart,
+                                                       ((PEXTENDED_IO_STACK_LOCATION)
+                                                        IoStackLocation)->Parameters.LockControl.Length->QuadPart,
+                                                       ((PEXTENDED_IO_STACK_LOCATION)
+                                                        IoStackLocation)->Parameters.LockControl.Key));
+#endif
+                       }
+                       else if (IoStackLocation->MinorFunction & IRP_MN_UNLOCK_ALL)
+                       {
+                               FFSPrintNoIndent((
+                                                       DBG_TRACE, "%s %s %s IRP_MN_UNLOCK_ALL\n",
+                                                       FFSGetCurrentProcessName(),
+                                                       IrpMjStrings[IoStackLocation->MajorFunction],
+                                                       FileName));
+                       }
+                       else if (IoStackLocation->MinorFunction & IRP_MN_UNLOCK_ALL_BY_KEY)
+                       {
+#if !defined(_GNU_NTIFS_) || defined(__REACTOS__)
+                               FFSPrintNoIndent((
+                                                       DBG_TRACE, "%s %s %s IRP_MN_UNLOCK_ALL_BY_KEY Key: %u\n",
+                                                       FFSGetCurrentProcessName(),
+                                                       IrpMjStrings[IoStackLocation->MajorFunction],
+                                                       FileName,
+                                                       IoStackLocation->Parameters.LockControl.Key));
+#else
+                               FFSPrintNoIndent((
+                                                       DBG_TRACE, "%s %s %s IRP_MN_UNLOCK_ALL_BY_KEY Key: %u\n",
+                                                       FFSGetCurrentProcessName(),
+                                                       IrpMjStrings[IoStackLocation->MajorFunction],
+                                                       FileName,
+                                                       ((PEXTENDED_IO_STACK_LOCATION)
+                                                        IoStackLocation)->Parameters.LockControl.Key));
+#endif
+                       }
+                       else
+                       {
+                               FFSPrintNoIndent((
+                                                       DBG_TRACE, "%s %s %s Unknown minor function %#x\n",
+                                                       FFSGetCurrentProcessName(),
+                                                       IrpMjStrings[IoStackLocation->MajorFunction],
+                                                       FileName,
+                                                       IoStackLocation->MinorFunction));
+                       }
+
+                       break;
+
+               case IRP_MJ_CLEANUP:
+
+                       FFSPrintNoIndent((
+                                               DBG_TRACE, "%s %s %s\n",
+                                               FFSGetCurrentProcessName(),
+                                               IrpMjStrings[IoStackLocation->MajorFunction],
+                                               FileName));
+
+                       break;
+
+               case IRP_MJ_SHUTDOWN:
+
+                       FFSPrintNoIndent((
+                                               DBG_TRACE, "%s %s %s\n",
+                                               FFSGetCurrentProcessName(),
+                                               IrpMjStrings[IoStackLocation->MajorFunction],
+                                               FileName));
+
+                       break;
+
+#if (_WIN32_WINNT >= 0x0500)
+               case IRP_MJ_PNP:
+
+                       FFSPrintNoIndent((
+                                               DBG_TRACE, "%s %s %s\n",
+                                               FFSGetCurrentProcessName(),
+                                               IrpMjStrings[IoStackLocation->MajorFunction],
+                                               FileName));
+#endif // (_WIN32_WINNT >= 0x0500)
+                       break;
+
+
+               default:
+
+                       FFSPrintNoIndent((
+                                               DBG_TRACE, "%s %s %s\n",
+                                               FFSGetCurrentProcessName(),
+                                               IrpMjStrings[IoStackLocation->MajorFunction],
+                                               FileName));
+       }
+}
+
+
+VOID
+FFSDbgPrintComplete(
+       IN PIRP Irp,
+       IN BOOLEAN bPrint)
+{
+       PIO_STACK_LOCATION IoStackLocation;
+
+       if (!Irp)
+               return;
+
+       if (Irp->IoStatus.Status != STATUS_SUCCESS)
+       {
+               IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
+
+               if (bPrint)
+               {
+                       FFSPrintNoIndent((
+                                               DBG_TRACE, "%s %s Status: %s (%#x).\n",
+                                               FFSGetCurrentProcessName(),
+                                               IrpMjStrings[IoStackLocation->MajorFunction],
+                                               FFSNtStatusToString(Irp->IoStatus.Status),
+                                               Irp->IoStatus.Status));
+               }
+       }
+}
+
+PCHAR
+FFSNtStatusToString(
+       IN NTSTATUS Status)
+{
+       switch (Status)
+       {
+               case 0x00000000: return "STATUS_SUCCESS";
+               case 0x00000001: return "STATUS_WAIT_1";
+               case 0x00000002: return "STATUS_WAIT_2";
+               case 0x00000003: return "STATUS_WAIT_3";
+               case 0x0000003F: return "STATUS_WAIT_63";
+               case 0x00000080: return "STATUS_ABANDONED_WAIT_0";
+               case 0x000000BF: return "STATUS_ABANDONED_WAIT_63";
+               case 0x000000C0: return "STATUS_USER_APC";
+               case 0x00000100: return "STATUS_KERNEL_APC";
+               case 0x00000101: return "STATUS_ALERTED";
+               case 0x00000102: return "STATUS_TIMEOUT";
+               case 0x00000103: return "STATUS_PENDING";
+               case 0x00000104: return "STATUS_REPARSE";
+               case 0x00000105: return "STATUS_MORE_ENTRIES";
+               case 0x00000106: return "STATUS_NOT_ALL_ASSIGNED";
+               case 0x00000107: return "STATUS_SOME_NOT_MAPPED";
+               case 0x00000108: return "STATUS_OPLOCK_BREAK_IN_PROGRESS";
+               case 0x00000109: return "STATUS_VOLUME_MOUNTED";
+               case 0x0000010A: return "STATUS_RXACT_COMMITTED";
+               case 0x0000010B: return "STATUS_NOTIFY_CLEANUP";
+               case 0x0000010C: return "STATUS_NOTIFY_ENUM_DIR";
+               case 0x0000010D: return "STATUS_NO_QUOTAS_FOR_ACCOUNT";
+               case 0x0000010E: return "STATUS_PRIMARY_TRANSPORT_CONNECT_FAILED";
+               case 0x00000110: return "STATUS_PAGE_FAULT_TRANSITION";
+               case 0x00000111: return "STATUS_PAGE_FAULT_DEMAND_ZERO";
+               case 0x00000112: return "STATUS_PAGE_FAULT_COPY_ON_WRITE";
+               case 0x00000113: return "STATUS_PAGE_FAULT_GUARD_PAGE";
+               case 0x00000114: return "STATUS_PAGE_FAULT_PAGING_FILE";
+               case 0x00000115: return "STATUS_CACHE_PAGE_LOCKED";
+               case 0x00000116: return "STATUS_CRASH_DUMP";
+               case 0x00000117: return "STATUS_BUFFER_ALL_ZEROS";
+               case 0x00000118: return "STATUS_REPARSE_OBJECT";
+               case 0x00000119: return "STATUS_RESOURCE_REQUIREMENTS_CHANGED";
+               case 0x00000120: return "STATUS_TRANSLATION_COMPLETE";
+               case 0x00000121: return "STATUS_DS_MEMBERSHIP_EVALUATED_LOCALLY";
+               case 0x00010001: return "DBG_EXCEPTION_HANDLED";
+               case 0x00010002: return "DBG_CONTINUE";
+               case 0x40000000: return "STATUS_OBJECT_NAME_EXISTS";
+               case 0x40000001: return "STATUS_THREAD_WAS_SUSPENDED";
+               case 0x40000002: return "STATUS_WORKING_SET_LIMIT_RANGE";
+               case 0x40000003: return "STATUS_IMAGE_NOT_AT_BASE";
+               case 0x40000004: return "STATUS_RXACT_STATE_CREATED";
+               case 0x40000005: return "STATUS_SEGMENT_NOTIFICATION";
+               case 0x40000006: return "STATUS_LOCAL_USER_SESSION_KEY";
+               case 0x40000007: return "STATUS_BAD_CURRENT_DIRECTORY";
+               case 0x40000008: return "STATUS_SERIAL_MORE_WRITES";
+               case 0x40000009: return "STATUS_REGISTRY_RECOVERED";
+               case 0x4000000A: return "STATUS_FT_READ_RECOVERY_FROM_BACKUP";
+               case 0x4000000B: return "STATUS_FT_WRITE_RECOVERY";
+               case 0x4000000C: return "STATUS_SERIAL_COUNTER_TIMEOUT";
+               case 0x4000000D: return "STATUS_NULL_LM_PASSWORD";
+               case 0x4000000E: return "STATUS_IMAGE_MACHINE_TYPE_MISMATCH";
+               case 0x4000000F: return "STATUS_RECEIVE_PARTIAL";
+               case 0x40000010: return "STATUS_RECEIVE_EXPEDITED";
+               case 0x40000011: return "STATUS_RECEIVE_PARTIAL_EXPEDITED";
+               case 0x40000012: return "STATUS_EVENT_DONE";
+               case 0x40000013: return "STATUS_EVENT_PENDING";
+               case 0x40000014: return "STATUS_CHECKING_FILE_SYSTEM";
+               case 0x40000015: return "STATUS_FATAL_APP_EXIT";
+               case 0x40000016: return "STATUS_PREDEFINED_HANDLE";
+               case 0x40000017: return "STATUS_WAS_UNLOCKED";
+               case 0x40000018: return "STATUS_SERVICE_NOTIFICATION";
+               case 0x40000019: return "STATUS_WAS_LOCKED";
+               case 0x4000001A: return "STATUS_LOG_HARD_ERROR";
+               case 0x4000001B: return "STATUS_ALREADY_WIN32";
+               case 0x4000001C: return "STATUS_WX86_UNSIMULATE";
+               case 0x4000001D: return "STATUS_WX86_CONTINUE";
+               case 0x4000001E: return "STATUS_WX86_SINGLE_STEP";
+               case 0x4000001F: return "STATUS_WX86_BREAKPOINT";
+               case 0x40000020: return "STATUS_WX86_EXCEPTION_CONTINUE";
+               case 0x40000021: return "STATUS_WX86_EXCEPTION_LASTCHANCE";
+               case 0x40000022: return "STATUS_WX86_EXCEPTION_CHAIN";
+               case 0x40000023: return "STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE";
+               case 0x40000024: return "STATUS_NO_YIELD_PERFORMED";
+               case 0x40000025: return "STATUS_TIMER_RESUME_IGNORED";
+               case 0x40000026: return "STATUS_ARBITRATION_UNHANDLED";
+               case 0x40000027: return "STATUS_CARDBUS_NOT_SUPPORTED";
+               case 0x40000028: return "STATUS_WX86_CREATEWX86TIB";
+               case 0x40000029: return "STATUS_MP_PROCESSOR_MISMATCH";
+               case 0x40010001: return "DBG_REPLY_LATER";
+               case 0x40010002: return "DBG_UNABLE_TO_PROVIDE_HANDLE";
+               case 0x40010003: return "DBG_TERMINATE_THREAD";
+               case 0x40010004: return "DBG_TERMINATE_PROCESS";
+               case 0x40010005: return "DBG_CONTROL_C";
+               case 0x40010006: return "DBG_PRINTEXCEPTION_C";
+               case 0x40010007: return "DBG_RIPEXCEPTION";
+               case 0x40010008: return "DBG_CONTROL_BREAK";
+               case 0x80000001: return "STATUS_GUARD_PAGE_VIOLATION";
+               case 0x80000002: return "STATUS_DATATYPE_MISALIGNMENT";
+               case 0x80000003: return "STATUS_BREAKPOINT";
+               case 0x80000004: return "STATUS_SINGLE_STEP";
+               case 0x80000005: return "STATUS_BUFFER_OVERFLOW";
+               case 0x80000006: return "STATUS_NO_MORE_FILES";
+               case 0x80000007: return "STATUS_WAKE_SYSTEM_DEBUGGER";
+               case 0x8000000A: return "STATUS_HANDLES_CLOSED";
+               case 0x8000000B: return "STATUS_NO_INHERITANCE";
+               case 0x8000000C: return "STATUS_GUID_SUBSTITUTION_MADE";
+               case 0x8000000D: return "STATUS_PARTIAL_COPY";
+               case 0x8000000E: return "STATUS_DEVICE_PAPER_EMPTY";
+               case 0x8000000F: return "STATUS_DEVICE_POWERED_OFF";
+               case 0x80000010: return "STATUS_DEVICE_OFF_LINE";
+               case 0x80000011: return "STATUS_DEVICE_BUSY";
+               case 0x80000012: return "STATUS_NO_MORE_EAS";
+               case 0x80000013: return "STATUS_INVALID_EA_NAME";
+               case 0x80000014: return "STATUS_EA_LIST_INCONSISTENT";
+               case 0x80000015: return "STATUS_INVALID_EA_FLAG";
+               case 0x80000016: return "STATUS_VERIFY_REQUIRED";
+               case 0x80000017: return "STATUS_EXTRANEOUS_INFORMATION";
+               case 0x80000018: return "STATUS_RXACT_COMMIT_NECESSARY";
+               case 0x8000001A: return "STATUS_NO_MORE_ENTRIES";
+               case 0x8000001B: return "STATUS_FILEMARK_DETECTED";
+               case 0x8000001C: return "STATUS_MEDIA_CHANGED";
+               case 0x8000001D: return "STATUS_BUS_RESET";
+               case 0x8000001E: return "STATUS_END_OF_MEDIA";
+               case 0x8000001F: return "STATUS_BEGINNING_OF_MEDIA";
+               case 0x80000020: return "STATUS_MEDIA_CHECK";
+               case 0x80000021: return "STATUS_SETMARK_DETECTED";
+               case 0x80000022: return "STATUS_NO_DATA_DETECTED";
+               case 0x80000023: return "STATUS_REDIRECTOR_HAS_OPEN_HANDLES";
+               case 0x80000024: return "STATUS_SERVER_HAS_OPEN_HANDLES";
+               case 0x80000025: return "STATUS_ALREADY_DISCONNECTED";
+               case 0x80000026: return "STATUS_LONGJUMP";
+               case 0x80010001: return "DBG_EXCEPTION_NOT_HANDLED";
+               case 0xC0000001: return "STATUS_UNSUCCESSFUL";
+               case 0xC0000002: return "STATUS_NOT_IMPLEMENTED";
+               case 0xC0000003: return "STATUS_INVALID_INFO_CLASS";
+               case 0xC0000004: return "STATUS_INFO_LENGTH_MISMATCH";
+               case 0xC0000005: return "STATUS_ACCESS_VIOLATION";
+               case 0xC0000006: return "STATUS_IN_PAGE_ERROR";
+               case 0xC0000007: return "STATUS_PAGEFILE_QUOTA";
+               case 0xC0000008: return "STATUS_INVALID_HANDLE";
+               case 0xC0000009: return "STATUS_BAD_INITIAL_STACK";
+               case 0xC000000A: return "STATUS_BAD_INITIAL_PC";
+               case 0xC000000B: return "STATUS_INVALID_CID";
+               case 0xC000000C: return "STATUS_TIMER_NOT_CANCELED";
+               case 0xC000000D: return "STATUS_INVALID_PARAMETER";
+               case 0xC000000E: return "STATUS_NO_SUCH_DEVICE";
+               case 0xC000000F: return "STATUS_NO_SUCH_FILE";
+               case 0xC0000010: return "STATUS_INVALID_DEVICE_REQUEST";
+               case 0xC0000011: return "STATUS_END_OF_FILE";
+               case 0xC0000012: return "STATUS_WRONG_VOLUME";
+               case 0xC0000013: return "STATUS_NO_MEDIA_IN_DEVICE";
+               case 0xC0000014: return "STATUS_UNRECOGNIZED_MEDIA";
+               case 0xC0000015: return "STATUS_NONEXISTENT_SECTOR";
+               case 0xC0000016: return "STATUS_MORE_PROCESSING_REQUIRED";
+               case 0xC0000017: return "STATUS_NO_MEMORY";
+               case 0xC0000018: return "STATUS_CONFLICTING_ADDRESSES";
+               case 0xC0000019: return "STATUS_NOT_MAPPED_VIEW";
+               case 0xC000001A: return "STATUS_UNABLE_TO_FREE_VM";
+               case 0xC000001B: return "STATUS_UNABLE_TO_DELETE_SECTION";
+               case 0xC000001C: return "STATUS_INVALID_SYSTEM_SERVICE";
+               case 0xC000001D: return "STATUS_ILLEGAL_INSTRUCTION";
+               case 0xC000001E: return "STATUS_INVALID_LOCK_SEQUENCE";
+               case 0xC000001F: return "STATUS_INVALID_VIEW_SIZE";
+               case 0xC0000020: return "STATUS_INVALID_FILE_FOR_SECTION";
+               case 0xC0000021: return "STATUS_ALREADY_COMMITTED";
+               case 0xC0000022: return "STATUS_ACCESS_DENIED";
+               case 0xC0000023: return "STATUS_BUFFER_TOO_SMALL";
+               case 0xC0000024: return "STATUS_OBJECT_TYPE_MISMATCH";
+               case 0xC0000025: return "STATUS_NONCONTINUABLE_EXCEPTION";
+               case 0xC0000026: return "STATUS_INVALID_DISPOSITION";
+               case 0xC0000027: return "STATUS_UNWIND";
+               case 0xC0000028: return "STATUS_BAD_STACK";
+               case 0xC0000029: return "STATUS_INVALID_UNWIND_TARGET";
+               case 0xC000002A: return "STATUS_NOT_LOCKED";
+               case 0xC000002B: return "STATUS_PARITY_ERROR";
+               case 0xC000002C: return "STATUS_UNABLE_TO_DECOMMIT_VM";
+               case 0xC000002D: return "STATUS_NOT_COMMITTED";
+               case 0xC000002E: return "STATUS_INVALID_PORT_ATTRIBUTES";
+               case 0xC000002F: return "STATUS_PORT_MESSAGE_TOO_LONG";
+               case 0xC0000030: return "STATUS_INVALID_PARAMETER_MIX";
+               case 0xC0000031: return "STATUS_INVALID_QUOTA_LOWER";
+               case 0xC0000032: return "STATUS_DISK_CORRUPT_ERROR";
+               case 0xC0000033: return "STATUS_OBJECT_NAME_INVALID";
+               case 0xC0000034: return "STATUS_OBJECT_NAME_NOT_FOUND";
+               case 0xC0000035: return "STATUS_OBJECT_NAME_COLLISION";
+               case 0xC0000037: return "STATUS_PORT_DISCONNECTED";
+               case 0xC0000038: return "STATUS_DEVICE_ALREADY_ATTACHED";
+               case 0xC0000039: return "STATUS_OBJECT_PATH_INVALID";
+               case 0xC000003A: return "STATUS_OBJECT_PATH_NOT_FOUND";
+               case 0xC000003B: return "STATUS_OBJECT_PATH_SYNTAX_BAD";
+               case 0xC000003C: return "STATUS_DATA_OVERRUN";
+               case 0xC000003D: return "STATUS_DATA_LATE_ERROR";
+               case 0xC000003E: return "STATUS_DATA_ERROR";
+               case 0xC000003F: return "STATUS_CRC_ERROR";
+               case 0xC0000040: return "STATUS_SECTION_TOO_BIG";
+               case 0xC0000041: return "STATUS_PORT_CONNECTION_REFUSED";
+               case 0xC0000042: return "STATUS_INVALID_PORT_HANDLE";
+               case 0xC0000043: return "STATUS_SHARING_VIOLATION";
+               case 0xC0000044: return "STATUS_QUOTA_EXCEEDED";
+               case 0xC0000045: return "STATUS_INVALID_PAGE_PROTECTION";
+               case 0xC0000046: return "STATUS_MUTANT_NOT_OWNED";
+               case 0xC0000047: return "STATUS_SEMAPHORE_LIMIT_EXCEEDED";
+               case 0xC0000048: return "STATUS_PORT_ALREADY_SET";
+               case 0xC0000049: return "STATUS_SECTION_NOT_IMAGE";
+               case 0xC000004A: return "STATUS_SUSPEND_COUNT_EXCEEDED";
+               case 0xC000004B: return "STATUS_THREAD_IS_TERMINATING";
+               case 0xC000004C: return "STATUS_BAD_WORKING_SET_LIMIT";
+               case 0xC000004D: return "STATUS_INCOMPATIBLE_FILE_MAP";
+               case 0xC000004E: return "STATUS_SECTION_PROTECTION";
+               case 0xC000004F: return "STATUS_EAS_NOT_SUPPORTED";
+               case 0xC0000050: return "STATUS_EA_TOO_LARGE";
+               case 0xC0000051: return "STATUS_NONEXISTENT_EA_ENTRY";
+               case 0xC0000052: return "STATUS_NO_EAS_ON_FILE";
+               case 0xC0000053: return "STATUS_EA_CORRUPT_ERROR";
+               case 0xC0000054: return "STATUS_FILE_LOCK_CONFLICT";
+               case 0xC0000055: return "STATUS_LOCK_NOT_GRANTED";
+               case 0xC0000056: return "STATUS_DELETE_PENDING";
+               case 0xC0000057: return "STATUS_CTL_FILE_NOT_SUPPORTED";
+               case 0xC0000058: return "STATUS_UNKNOWN_REVISION";
+               case 0xC0000059: return "STATUS_REVISION_MISMATCH";
+               case 0xC000005A: return "STATUS_INVALID_OWNER";
+               case 0xC000005B: return "STATUS_INVALID_PRIMARY_GROUP";
+               case 0xC000005C: return "STATUS_NO_IMPERSONATION_TOKEN";
+               case 0xC000005D: return "STATUS_CANT_DISABLE_MANDATORY";
+               case 0xC000005E: return "STATUS_NO_LOGON_SERVERS";
+               case 0xC000005F: return "STATUS_NO_SUCH_LOGON_SESSION";
+               case 0xC0000060: return "STATUS_NO_SUCH_PRIVILEGE";
+               case 0xC0000061: return "STATUS_PRIVILEGE_NOT_HELD";
+               case 0xC0000062: return "STATUS_INVALID_ACCOUNT_NAME";
+               case 0xC0000063: return "STATUS_USER_EXISTS";
+               case 0xC0000064: return "STATUS_NO_SUCH_USER";
+               case 0xC0000065: return "STATUS_GROUP_EXISTS";
+               case 0xC0000066: return "STATUS_NO_SUCH_GROUP";
+               case 0xC0000067: return "STATUS_MEMBER_IN_GROUP";
+               case 0xC0000068: return "STATUS_MEMBER_NOT_IN_GROUP";
+               case 0xC0000069: return "STATUS_LAST_ADMIN";
+               case 0xC000006A: return "STATUS_WRONG_PASSWORD";
+               case 0xC000006B: return "STATUS_ILL_FORMED_PASSWORD";
+               case 0xC000006C: return "STATUS_PASSWORD_RESTRICTION";
+               case 0xC000006D: return "STATUS_LOGON_FAILURE";
+               case 0xC000006E: return "STATUS_ACCOUNT_RESTRICTION";
+               case 0xC000006F: return "STATUS_INVALID_LOGON_HOURS";
+               case 0xC0000070: return "STATUS_INVALID_WORKSTATION";
+               case 0xC0000071: return "STATUS_PASSWORD_EXPIRED";
+               case 0xC0000072: return "STATUS_ACCOUNT_DISABLED";
+               case 0xC0000073: return "STATUS_NONE_MAPPED";
+               case 0xC0000074: return "STATUS_TOO_MANY_LUIDS_REQUESTED";
+               case 0xC0000075: return "STATUS_LUIDS_EXHAUSTED";
+               case 0xC0000076: return "STATUS_INVALID_SUB_AUTHORITY";
+               case 0xC0000077: return "STATUS_INVALID_ACL";
+               case 0xC0000078: return "STATUS_INVALID_SID";
+               case 0xC0000079: return "STATUS_INVALID_SECURITY_DESCR";
+               case 0xC000007A: return "STATUS_PROCEDURE_NOT_FOUND";
+               case 0xC000007B: return "STATUS_INVALID_IMAGE_FORMAT";
+               case 0xC000007C: return "STATUS_NO_TOKEN";
+               case 0xC000007D: return "STATUS_BAD_INHERITANCE_ACL";
+               case 0xC000007E: return "STATUS_RANGE_NOT_LOCKED";
+               case 0xC000007F: return "STATUS_DISK_FULL";
+               case 0xC0000080: return "STATUS_SERVER_DISABLED";
+               case 0xC0000081: return "STATUS_SERVER_NOT_DISABLED";
+               case 0xC0000082: return "STATUS_TOO_MANY_GUIDS_REQUESTED";
+               case 0xC0000083: return "STATUS_GUIDS_EXHAUSTED";
+               case 0xC0000084: return "STATUS_INVALID_ID_AUTHORITY";
+               case 0xC0000085: return "STATUS_AGENTS_EXHAUSTED";
+               case 0xC0000086: return "STATUS_INVALID_VOLUME_LABEL";
+               case 0xC0000087: return "STATUS_SECTION_NOT_EXTENDED";
+               case 0xC0000088: return "STATUS_NOT_MAPPED_DATA";
+               case 0xC0000089: return "STATUS_RESOURCE_DATA_NOT_FOUND";
+               case 0xC000008A: return "STATUS_RESOURCE_TYPE_NOT_FOUND";
+               case 0xC000008B: return "STATUS_RESOURCE_NAME_NOT_FOUND";
+               case 0xC000008C: return "STATUS_ARRAY_BOUNDS_EXCEEDED";
+               case 0xC000008D: return "STATUS_FLOAT_DENORMAL_OPERAND";
+               case 0xC000008E: return "STATUS_FLOAT_DIVIDE_BY_ZERO";
+               case 0xC000008F: return "STATUS_FLOAT_INEXACT_RESULT";
+               case 0xC0000090: return "STATUS_FLOAT_INVALID_OPERATION";
+               case 0xC0000091: return "STATUS_FLOAT_OVERFLOW";
+               case 0xC0000092: return "STATUS_FLOAT_STACK_CHECK";
+               case 0xC0000093: return "STATUS_FLOAT_UNDERFLOW";
+               case 0xC0000094: return "STATUS_INTEGER_DIVIDE_BY_ZERO";
+               case 0xC0000095: return "STATUS_INTEGER_OVERFLOW";
+               case 0xC0000096: return "STATUS_PRIVILEGED_INSTRUCTION";
+               case 0xC0000097: return "STATUS_TOO_MANY_PAGING_FILES";
+               case 0xC0000098: return "STATUS_FILE_INVALID";
+               case 0xC0000099: return "STATUS_ALLOTTED_SPACE_EXCEEDED";
+               case 0xC000009A: return "STATUS_INSUFFICIENT_RESOURCES";
+               case 0xC000009B: return "STATUS_DFS_EXIT_PATH_FOUND";
+               case 0xC000009C: return "STATUS_DEVICE_DATA_ERROR";
+               case 0xC000009D: return "STATUS_DEVICE_NOT_CONNECTED";
+               case 0xC000009E: return "STATUS_DEVICE_POWER_FAILURE";
+               case 0xC000009F: return "STATUS_FREE_VM_NOT_AT_BASE";
+               case 0xC00000A0: return "STATUS_MEMORY_NOT_ALLOCATED";
+               case 0xC00000A1: return "STATUS_WORKING_SET_QUOTA";
+               case 0xC00000A2: return "STATUS_MEDIA_WRITE_PROTECTED";
+               case 0xC00000A3: return "STATUS_DEVICE_NOT_READY";
+               case 0xC00000A4: return "STATUS_INVALID_GROUP_ATTRIBUTES";
+               case 0xC00000A5: return "STATUS_BAD_IMPERSONATION_LEVEL";
+               case 0xC00000A6: return "STATUS_CANT_OPEN_ANONYMOUS";
+               case 0xC00000A7: return "STATUS_BAD_VALIDATION_CLASS";
+               case 0xC00000A8: return "STATUS_BAD_TOKEN_TYPE";
+               case 0xC00000A9: return "STATUS_BAD_MASTER_BOOT_RECORD";
+               case 0xC00000AA: return "STATUS_INSTRUCTION_MISALIGNMENT";
+               case 0xC00000AB: return "STATUS_INSTANCE_NOT_AVAILABLE";
+               case 0xC00000AC: return "STATUS_PIPE_NOT_AVAILABLE";
+               case 0xC00000AD: return "STATUS_INVALID_PIPE_STATE";
+               case 0xC00000AE: return "STATUS_PIPE_BUSY";
+               case 0xC00000AF: return "STATUS_ILLEGAL_FUNCTION";
+               case 0xC00000B0: return "STATUS_PIPE_DISCONNECTED";
+               case 0xC00000B1: return "STATUS_PIPE_CLOSING";
+               case 0xC00000B2: return "STATUS_PIPE_CONNECTED";
+               case 0xC00000B3: return "STATUS_PIPE_LISTENING";
+               case 0xC00000B4: return "STATUS_INVALID_READ_MODE";
+               case 0xC00000B5: return "STATUS_IO_TIMEOUT";
+               case 0xC00000B6: return "STATUS_FILE_FORCED_CLOSED";
+               case 0xC00000B7: return "STATUS_PROFILING_NOT_STARTED";
+               case 0xC00000B8: return "STATUS_PROFILING_NOT_STOPPED";
+               case 0xC00000B9: return "STATUS_COULD_NOT_INTERPRET";
+               case 0xC00000BA: return "STATUS_FILE_IS_A_DIRECTORY";
+               case 0xC00000BB: return "STATUS_NOT_SUPPORTED";
+               case 0xC00000BC: return "STATUS_REMOTE_NOT_LISTENING";
+               case 0xC00000BD: return "STATUS_DUPLICATE_NAME";
+               case 0xC00000BE: return "STATUS_BAD_NETWORK_PATH";
+               case 0xC00000BF: return "STATUS_NETWORK_BUSY";
+               case 0xC00000C0: return "STATUS_DEVICE_DOES_NOT_EXIST";
+               case 0xC00000C1: return "STATUS_TOO_MANY_COMMANDS";
+               case 0xC00000C2: return "STATUS_ADAPTER_HARDWARE_ERROR";
+               case 0xC00000C3: return "STATUS_INVALID_NETWORK_RESPONSE";
+               case 0xC00000C4: return "STATUS_UNEXPECTED_NETWORK_ERROR";
+               case 0xC00000C5: return "STATUS_BAD_REMOTE_ADAPTER";
+               case 0xC00000C6: return "STATUS_PRINT_QUEUE_FULL";
+               case 0xC00000C7: return "STATUS_NO_SPOOL_SPACE";
+               case 0xC00000C8: return "STATUS_PRINT_CANCELLED";
+               case 0xC00000C9: return "STATUS_NETWORK_NAME_DELETED";
+               case 0xC00000CA: return "STATUS_NETWORK_ACCESS_DENIED";
+               case 0xC00000CB: return "STATUS_BAD_DEVICE_TYPE";
+               case 0xC00000CC: return "STATUS_BAD_NETWORK_NAME";
+               case 0xC00000CD: return "STATUS_TOO_MANY_NAMES";
+               case 0xC00000CE: return "STATUS_TOO_MANY_SESSIONS";
+               case 0xC00000CF: return "STATUS_SHARING_PAUSED";
+               case 0xC00000D0: return "STATUS_REQUEST_NOT_ACCEPTED";
+               case 0xC00000D1: return "STATUS_REDIRECTOR_PAUSED";
+               case 0xC00000D2: return "STATUS_NET_WRITE_FAULT";
+               case 0xC00000D3: return "STATUS_PROFILING_AT_LIMIT";
+               case 0xC00000D4: return "STATUS_NOT_SAME_DEVICE";
+               case 0xC00000D5: return "STATUS_FILE_RENAMED";
+               case 0xC00000D6: return "STATUS_VIRTUAL_CIRCUIT_CLOSED";
+               case 0xC00000D7: return "STATUS_NO_SECURITY_ON_OBJECT";
+               case 0xC00000D8: return "STATUS_CANT_WAIT";
+               case 0xC00000D9: return "STATUS_PIPE_EMPTY";
+               case 0xC00000DA: return "STATUS_CANT_ACCESS_DOMAIN_INFO";
+               case 0xC00000DB: return "STATUS_CANT_TERMINATE_SELF";
+               case 0xC00000DC: return "STATUS_INVALID_SERVER_STATE";
+               case 0xC00000DD: return "STATUS_INVALID_DOMAIN_STATE";
+               case 0xC00000DE: return "STATUS_INVALID_DOMAIN_ROLE";
+               case 0xC00000DF: return "STATUS_NO_SUCH_DOMAIN";
+               case 0xC00000E0: return "STATUS_DOMAIN_EXISTS";
+               case 0xC00000E1: return "STATUS_DOMAIN_LIMIT_EXCEEDED";
+               case 0xC00000E2: return "STATUS_OPLOCK_NOT_GRANTED";
+               case 0xC00000E3: return "STATUS_INVALID_OPLOCK_PROTOCOL";
+               case 0xC00000E4: return "STATUS_INTERNAL_DB_CORRUPTION";
+               case 0xC00000E5: return "STATUS_INTERNAL_ERROR";
+               case 0xC00000E6: return "STATUS_GENERIC_NOT_MAPPED";
+               case 0xC00000E7: return "STATUS_BAD_DESCRIPTOR_FORMAT";
+               case 0xC00000E8: return "STATUS_INVALID_USER_BUFFER";
+               case 0xC00000E9: return "STATUS_UNEXPECTED_IO_ERROR";
+               case 0xC00000EA: return "STATUS_UNEXPECTED_MM_CREATE_ERR";
+               case 0xC00000EB: return "STATUS_UNEXPECTED_MM_MAP_ERROR";
+               case 0xC00000EC: return "STATUS_UNEXPECTED_MM_EXTEND_ERR";
+               case 0xC00000ED: return "STATUS_NOT_LOGON_PROCESS";
+               case 0xC00000EE: return "STATUS_LOGON_SESSION_EXISTS";
+               case 0xC00000EF: return "STATUS_INVALID_PARAMETER_1";
+               case 0xC00000F0: return "STATUS_INVALID_PARAMETER_2";
+               case 0xC00000F1: return "STATUS_INVALID_PARAMETER_3";
+               case 0xC00000F2: return "STATUS_INVALID_PARAMETER_4";
+               case 0xC00000F3: return "STATUS_INVALID_PARAMETER_5";
+               case 0xC00000F4: return "STATUS_INVALID_PARAMETER_6";
+               case 0xC00000F5: return "STATUS_INVALID_PARAMETER_7";
+               case 0xC00000F6: return "STATUS_INVALID_PARAMETER_8";
+               case 0xC00000F7: return "STATUS_INVALID_PARAMETER_9";
+               case 0xC00000F8: return "STATUS_INVALID_PARAMETER_10";
+               case 0xC00000F9: return "STATUS_INVALID_PARAMETER_11";
+               case 0xC00000FA: return "STATUS_INVALID_PARAMETER_12";
+               case 0xC00000FB: return "STATUS_REDIRECTOR_NOT_STARTED";
+               case 0xC00000FC: return "STATUS_REDIRECTOR_STARTED";
+               case 0xC00000FD: return "STATUS_STACK_OVERFLOW";
+               case 0xC00000FE: return "STATUS_NO_SUCH_PACKAGE";
+               case 0xC00000FF: return "STATUS_BAD_FUNCTION_TABLE";
+               case 0xC0000100: return "STATUS_VARIABLE_NOT_FOUND";
+               case 0xC0000101: return "STATUS_DIRECTORY_NOT_EMPTY";
+               case 0xC0000102: return "STATUS_FILE_CORRUPT_ERROR";
+               case 0xC0000103: return "STATUS_NOT_A_DIRECTORY";
+               case 0xC0000104: return "STATUS_BAD_LOGON_SESSION_STATE";
+               case 0xC0000105: return "STATUS_LOGON_SESSION_COLLISION";
+               case 0xC0000106: return "STATUS_NAME_TOO_LONG";
+               case 0xC0000107: return "STATUS_FILES_OPEN";
+               case 0xC0000108: return "STATUS_CONNECTION_IN_USE";
+               case 0xC0000109: return "STATUS_MESSAGE_NOT_FOUND";
+               case 0xC000010A: return "STATUS_PROCESS_IS_TERMINATING";
+               case 0xC000010B: return "STATUS_INVALID_LOGON_TYPE";
+               case 0xC000010C: return "STATUS_NO_GUID_TRANSLATION";
+               case 0xC000010D: return "STATUS_CANNOT_IMPERSONATE";
+               case 0xC000010E: return "STATUS_IMAGE_ALREADY_LOADED";
+               case 0xC000010F: return "STATUS_ABIOS_NOT_PRESENT";
+               case 0xC0000110: return "STATUS_ABIOS_LID_NOT_EXIST";
+               case 0xC0000111: return "STATUS_ABIOS_LID_ALREADY_OWNED";
+               case 0xC0000112: return "STATUS_ABIOS_NOT_LID_OWNER";
+               case 0xC0000113: return "STATUS_ABIOS_INVALID_COMMAND";
+               case 0xC0000114: return "STATUS_ABIOS_INVALID_LID";
+               case 0xC0000115: return "STATUS_ABIOS_SELECTOR_NOT_AVAILABLE";
+               case 0xC0000116: return "STATUS_ABIOS_INVALID_SELECTOR";
+               case 0xC0000117: return "STATUS_NO_LDT";
+               case 0xC0000118: return "STATUS_INVALID_LDT_SIZE";
+               case 0xC0000119: return "STATUS_INVALID_LDT_OFFSET";
+               case 0xC000011A: return "STATUS_INVALID_LDT_DESCRIPTOR";
+               case 0xC000011B: return "STATUS_INVALID_IMAGE_NE_FORMAT";
+               case 0xC000011C: return "STATUS_RXACT_INVALID_STATE";
+               case 0xC000011D: return "STATUS_RXACT_COMMIT_FAILURE";
+               case 0xC000011E: return "STATUS_MAPPED_FILE_SIZE_ZERO";
+               case 0xC000011F: return "STATUS_TOO_MANY_OPENED_FILES";
+               case 0xC0000120: return "STATUS_CANCELLED";
+               case 0xC0000121: return "STATUS_CANNOT_DELETE";
+               case 0xC0000122: return "STATUS_INVALID_COMPUTER_NAME";
+               case 0xC0000123: return "STATUS_FILE_DELETED";
+               case 0xC0000124: return "STATUS_SPECIAL_ACCOUNT";
+               case 0xC0000125: return "STATUS_SPECIAL_GROUP";
+               case 0xC0000126: return "STATUS_SPECIAL_USER";
+               case 0xC0000127: return "STATUS_MEMBERS_PRIMARY_GROUP";
+               case 0xC0000128: return "STATUS_FILE_CLOSED";
+               case 0xC0000129: return "STATUS_TOO_MANY_THREADS";
+               case 0xC000012A: return "STATUS_THREAD_NOT_IN_PROCESS";
+               case 0xC000012B: return "STATUS_TOKEN_ALREADY_IN_USE";
+               case 0xC000012C: return "STATUS_PAGEFILE_QUOTA_EXCEEDED";
+               case 0xC000012D: return "STATUS_COMMITMENT_LIMIT";
+               case 0xC000012E: return "STATUS_INVALID_IMAGE_LE_FORMAT";
+               case 0xC000012F: return "STATUS_INVALID_IMAGE_NOT_MZ";
+               case 0xC0000130: return "STATUS_INVALID_IMAGE_PROTECT";
+               case 0xC0000131: return "STATUS_INVALID_IMAGE_WIN_16";
+               case 0xC0000132: return "STATUS_LOGON_SERVER_CONFLICT";
+               case 0xC0000133: return "STATUS_TIME_DIFFERENCE_AT_DC";
+               case 0xC0000134: return "STATUS_SYNCHRONIZATION_REQUIRED";
+               case 0xC0000135: return "STATUS_DLL_NOT_FOUND";
+               case 0xC0000136: return "STATUS_OPEN_FAILED";
+               case 0xC0000137: return "STATUS_IO_PRIVILEGE_FAILED";
+               case 0xC0000138: return "STATUS_ORDINAL_NOT_FOUND";
+               case 0xC0000139: return "STATUS_ENTRYPOINT_NOT_FOUND";
+               case 0xC000013A: return "STATUS_CONTROL_C_EXIT";
+               case 0xC000013B: return "STATUS_LOCAL_DISCONNECT";
+               case 0xC000013C: return "STATUS_REMOTE_DISCONNECT";
+               case 0xC000013D: return "STATUS_REMOTE_RESOURCES";
+               case 0xC000013E: return "STATUS_LINK_FAILED";
+               case 0xC000013F: return "STATUS_LINK_TIMEOUT";
+               case 0xC0000140: return "STATUS_INVALID_CONNECTION";
+               case 0xC0000141: return "STATUS_INVALID_ADDRESS";
+               case 0xC0000142: return "STATUS_DLL_INIT_FAILED";
+               case 0xC0000143: return "STATUS_MISSING_SYSTEMFILE";
+               case 0xC0000144: return "STATUS_UNHANDLED_EXCEPTION";
+               case 0xC0000145: return "STATUS_APP_INIT_FAILURE";
+               case 0xC0000146: return "STATUS_PAGEFILE_CREATE_FAILED";
+               case 0xC0000147: return "STATUS_NO_PAGEFILE";
+               case 0xC0000148: return "STATUS_INVALID_LEVEL";
+               case 0xC0000149: return "STATUS_WRONG_PASSWORD_CORE";
+               case 0xC000014A: return "STATUS_ILLEGAL_FLOAT_CONTEXT";
+               case 0xC000014B: return "STATUS_PIPE_BROKEN";
+               case 0xC000014C: return "STATUS_REGISTRY_CORRUPT";
+               case 0xC000014D: return "STATUS_REGISTRY_IO_FAILED";
+               case 0xC000014E: return "STATUS_NO_EVENT_PAIR";
+               case 0xC000014F: return "STATUS_UNRECOGNIZED_VOLUME";
+               case 0xC0000150: return "STATUS_SERIAL_NO_DEVICE_INITED";
+               case 0xC0000151: return "STATUS_NO_SUCH_ALIAS";
+               case 0xC0000152: return "STATUS_MEMBER_NOT_IN_ALIAS";
+               case 0xC0000153: return "STATUS_MEMBER_IN_ALIAS";
+               case 0xC0000154: return "STATUS_ALIAS_EXISTS";
+               case 0xC0000155: return "STATUS_LOGON_NOT_GRANTED";
+               case 0xC0000156: return "STATUS_TOO_MANY_SECRETS";
+               case 0xC0000157: return "STATUS_SECRET_TOO_LONG";
+               case 0xC0000158: return "STATUS_INTERNAL_DB_ERROR";
+               case 0xC0000159: return "STATUS_FULLSCREEN_MODE";
+               case 0xC000015A: return "STATUS_TOO_MANY_CONTEXT_IDS";
+               case 0xC000015B: return "STATUS_LOGON_TYPE_NOT_GRANTED";
+               case 0xC000015C: return "STATUS_NOT_REGISTRY_FILE";
+               case 0xC000015D: return "STATUS_NT_CROSS_ENCRYPTION_REQUIRED";
+               case 0xC000015E: return "STATUS_DOMAIN_CTRLR_CONFIG_ERROR";
+               case 0xC000015F: return "STATUS_FT_MISSING_MEMBER";
+               case 0xC0000160: return "STATUS_ILL_FORMED_SERVICE_ENTRY";
+               case 0xC0000161: return "STATUS_ILLEGAL_CHARACTER";
+               case 0xC0000162: return "STATUS_UNMAPPABLE_CHARACTER";
+               case 0xC0000163: return "STATUS_UNDEFINED_CHARACTER";
+               case 0xC0000164: return "STATUS_FLOPPY_VOLUME";
+               case 0xC0000165: return "STATUS_FLOPPY_ID_MARK_NOT_FOUND";
+               case 0xC0000166: return "STATUS_FLOPPY_WRONG_CYLINDER";
+               case 0xC0000167: return "STATUS_FLOPPY_UNKNOWN_ERROR";
+               case 0xC0000168: return "STATUS_FLOPPY_BAD_REGISTERS";
+               case 0xC0000169: return "STATUS_DISK_RECALIBRATE_FAILED";
+               case 0xC000016A: return "STATUS_DISK_OPERATION_FAILED";
+               case 0xC000016B: return "STATUS_DISK_RESET_FAILED";
+               case 0xC000016C: return "STATUS_SHARED_IRQ_BUSY";
+               case 0xC000016D: return "STATUS_FT_ORPHANING";
+               case 0xC000016E: return "STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT";
+               case 0xC0000172: return "STATUS_PARTITION_FAILURE";
+               case 0xC0000173: return "STATUS_INVALID_BLOCK_LENGTH";
+               case 0xC0000174: return "STATUS_DEVICE_NOT_PARTITIONED";
+               case 0xC0000175: return "STATUS_UNABLE_TO_LOCK_MEDIA";
+               case 0xC0000176: return "STATUS_UNABLE_TO_UNLOAD_MEDIA";
+               case 0xC0000177: return "STATUS_EOM_OVERFLOW";
+               case 0xC0000178: return "STATUS_NO_MEDIA";
+               case 0xC000017A: return "STATUS_NO_SUCH_MEMBER";
+               case 0xC000017B: return "STATUS_INVALID_MEMBER";
+               case 0xC000017C: return "STATUS_KEY_DELETED";
+               case 0xC000017D: return "STATUS_NO_LOG_SPACE";
+               case 0xC000017E: return "STATUS_TOO_MANY_SIDS";
+               case 0xC000017F: return "STATUS_LM_CROSS_ENCRYPTION_REQUIRED";
+               case 0xC0000180: return "STATUS_KEY_HAS_CHILDREN";
+               case 0xC0000181: return "STATUS_CHILD_MUST_BE_VOLATILE";
+               case 0xC0000182: return "STATUS_DEVICE_CONFIGURATION_ERROR";
+               case 0xC0000183: return "STATUS_DRIVER_INTERNAL_ERROR";
+               case 0xC0000184: return "STATUS_INVALID_DEVICE_STATE";
+               case 0xC0000185: return "STATUS_IO_DEVICE_ERROR";
+               case 0xC0000186: return "STATUS_DEVICE_PROTOCOL_ERROR";
+               case 0xC0000187: return "STATUS_BACKUP_CONTROLLER";
+               case 0xC0000188: return "STATUS_LOG_FILE_FULL";
+               case 0xC0000189: return "STATUS_TOO_LATE";
+               case 0xC000018A: return "STATUS_NO_TRUST_LSA_SECRET";
+               case 0xC000018B: return "STATUS_NO_TRUST_SAM_ACCOUNT";
+               case 0xC000018C: return "STATUS_TRUSTED_DOMAIN_FAILURE";
+               case 0xC000018D: return "STATUS_TRUSTED_RELATIONSHIP_FAILURE";
+               case 0xC000018E: return "STATUS_EVENTLOG_FILE_CORRUPT";
+               case 0xC000018F: return "STATUS_EVENTLOG_CANT_START";
+               case 0xC0000190: return "STATUS_TRUST_FAILURE";
+               case 0xC0000191: return "STATUS_MUTANT_LIMIT_EXCEEDED";
+               case 0xC0000192: return "STATUS_NETLOGON_NOT_STARTED";
+               case 0xC0000193: return "STATUS_ACCOUNT_EXPIRED";
+               case 0xC0000194: return "STATUS_POSSIBLE_DEADLOCK";
+               case 0xC0000195: return "STATUS_NETWORK_CREDENTIAL_CONFLICT";
+               case 0xC0000196: return "STATUS_REMOTE_SESSION_LIMIT";
+               case 0xC0000197: return "STATUS_EVENTLOG_FILE_CHANGED";
+               case 0xC0000198: return "STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT";
+               case 0xC0000199: return "STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT";
+               case 0xC000019A: return "STATUS_NOLOGON_SERVER_TRUST_ACCOUNT";
+               case 0xC000019B: return "STATUS_DOMAIN_TRUST_INCONSISTENT";
+               case 0xC000019C: return "STATUS_FS_DRIVER_REQUIRED";
+               case 0xC0000202: return "STATUS_NO_USER_SESSION_KEY";
+               case 0xC0000203: return "STATUS_USER_SESSION_DELETED";
+               case 0xC0000204: return "STATUS_RESOURCE_LANG_NOT_FOUND";
+               case 0xC0000205: return "STATUS_INSUFF_SERVER_RESOURCES";
+               case 0xC0000206: return "STATUS_INVALID_BUFFER_SIZE";
+               case 0xC0000207: return "STATUS_INVALID_ADDRESS_COMPONENT";
+               case 0xC0000208: return "STATUS_INVALID_ADDRESS_WILDCARD";
+               case 0xC0000209: return "STATUS_TOO_MANY_ADDRESSES";
+               case 0xC000020A: return "STATUS_ADDRESS_ALREADY_EXISTS";
+               case 0xC000020B: return "STATUS_ADDRESS_CLOSED";
+               case 0xC000020C: return "STATUS_CONNECTION_DISCONNECTED";
+               case 0xC000020D: return "STATUS_CONNECTION_RESET";
+               case 0xC000020E: return "STATUS_TOO_MANY_NODES";
+               case 0xC000020F: return "STATUS_TRANSACTION_ABORTED";
+               case 0xC0000210: return "STATUS_TRANSACTION_TIMED_OUT";
+               case 0xC0000211: return "STATUS_TRANSACTION_NO_RELEASE";
+               case 0xC0000212: return "STATUS_TRANSACTION_NO_MATCH";
+               case 0xC0000213: return "STATUS_TRANSACTION_RESPONDED";
+               case 0xC0000214: return "STATUS_TRANSACTION_INVALID_ID";
+               case 0xC0000215: return "STATUS_TRANSACTION_INVALID_TYPE";
+               case 0xC0000216: return "STATUS_NOT_SERVER_SESSION";
+               case 0xC0000217: return "STATUS_NOT_CLIENT_SESSION";
+               case 0xC0000218: return "STATUS_CANNOT_LOAD_REGISTRY_FILE";
+               case 0xC0000219: return "STATUS_DEBUG_ATTACH_FAILED";
+               case 0xC000021A: return "STATUS_SYSTEM_PROCESS_TERMINATED";
+               case 0xC000021B: return "STATUS_DATA_NOT_ACCEPTED";
+               case 0xC000021C: return "STATUS_NO_BROWSER_SERVERS_FOUND";
+               case 0xC000021D: return "STATUS_VDM_HARD_ERROR";
+               case 0xC000021E: return "STATUS_DRIVER_CANCEL_TIMEOUT";
+               case 0xC000021F: return "STATUS_REPLY_MESSAGE_MISMATCH";
+               case 0xC0000220: return "STATUS_MAPPED_ALIGNMENT";
+               case 0xC0000221: return "STATUS_IMAGE_CHECKSUM_MISMATCH";
+               case 0xC0000222: return "STATUS_LOST_WRITEBEHIND_DATA";
+               case 0xC0000223: return "STATUS_CLIENT_SERVER_PARAMETERS_INVALID";
+               case 0xC0000224: return "STATUS_PASSWORD_MUST_CHANGE";
+               case 0xC0000225: return "STATUS_NOT_FOUND";
+               case 0xC0000226: return "STATUS_NOT_TINY_STREAM";
+               case 0xC0000227: return "STATUS_RECOVERY_FAILURE";
+               case 0xC0000228: return "STATUS_STACK_OVERFLOW_READ";
+               case 0xC0000229: return "STATUS_FAIL_CHECK";
+               case 0xC000022A: return "STATUS_DUPLICATE_OBJECTID";
+               case 0xC000022B: return "STATUS_OBJECTID_EXISTS";
+               case 0xC000022C: return "STATUS_CONVERT_TO_LARGE";
+               case 0xC000022D: return "STATUS_RETRY";
+               case 0xC000022E: return "STATUS_FOUND_OUT_OF_SCOPE";
+               case 0xC000022F: return "STATUS_ALLOCATE_BUCKET";
+               case 0xC0000230: return "STATUS_PROPSET_NOT_FOUND";
+               case 0xC0000231: return "STATUS_MARSHALL_OVERFLOW";
+               case 0xC0000232: return "STATUS_INVALID_VARIANT";
+               case 0xC0000233: return "STATUS_DOMAIN_CONTROLLER_NOT_FOUND";
+               case 0xC0000234: return "STATUS_ACCOUNT_LOCKED_OUT";
+               case 0xC0000235: return "STATUS_HANDLE_NOT_CLOSABLE";
+               case 0xC0000236: return "STATUS_CONNECTION_REFUSED";
+               case 0xC0000237: return "STATUS_GRACEFUL_DISCONNECT";
+               case 0xC0000238: return "STATUS_ADDRESS_ALREADY_ASSOCIATED";
+               case 0xC0000239: return "STATUS_ADDRESS_NOT_ASSOCIATED";
+               case 0xC000023A: return "STATUS_CONNECTION_INVALID";
+               case 0xC000023B: return "STATUS_CONNECTION_ACTIVE";
+               case 0xC000023C: return "STATUS_NETWORK_UNREACHABLE";
+               case 0xC000023D: return "STATUS_HOST_UNREACHABLE";
+               case 0xC000023E: return "STATUS_PROTOCOL_UNREACHABLE";
+               case 0xC000023F: return "STATUS_PORT_UNREACHABLE";
+               case 0xC0000240: return "STATUS_REQUEST_ABORTED";
+               case 0xC0000241: return "STATUS_CONNECTION_ABORTED";
+               case 0xC0000242: return "STATUS_BAD_COMPRESSION_BUFFER";
+               case 0xC0000243: return "STATUS_USER_MAPPED_FILE";
+               case 0xC0000244: return "STATUS_AUDIT_FAILED";
+               case 0xC0000245: return "STATUS_TIMER_RESOLUTION_NOT_SET";
+               case 0xC0000246: return "STATUS_CONNECTION_COUNT_LIMIT";
+               case 0xC0000247: return "STATUS_LOGIN_TIME_RESTRICTION";
+               case 0xC0000248: return "STATUS_LOGIN_WKSTA_RESTRICTION";
+               case 0xC0000249: return "STATUS_IMAGE_MP_UP_MISMATCH";
+               case 0xC0000250: return "STATUS_INSUFFICIENT_LOGON_INFO";
+               case 0xC0000251: return "STATUS_BAD_DLL_ENTRYPOINT";
+               case 0xC0000252: return "STATUS_BAD_SERVICE_ENTRYPOINT";
+               case 0xC0000253: return "STATUS_LPC_REPLY_LOST";
+               case 0xC0000254: return "STATUS_IP_ADDRESS_CONFLICT1";
+               case 0xC0000255: return "STATUS_IP_ADDRESS_CONFLICT2";
+               case 0xC0000256: return "STATUS_REGISTRY_QUOTA_LIMIT";
+               case 0xC0000257: return "STATUS_PATH_NOT_COVERED";
+               case 0xC0000258: return "STATUS_NO_CALLBACK_ACTIVE";
+               case 0xC0000259: return "STATUS_LICENSE_QUOTA_EXCEEDED";
+               case 0xC000025A: return "STATUS_PWD_TOO_SHORT";
+               case 0xC000025B: return "STATUS_PWD_TOO_RECENT";
+               case 0xC000025C: return "STATUS_PWD_HISTORY_CONFLICT";
+               case 0xC000025E: return "STATUS_PLUGPLAY_NO_DEVICE";
+               case 0xC000025F: return "STATUS_UNSUPPORTED_COMPRESSION";
+               case 0xC0000260: return "STATUS_INVALID_HW_PROFILE";
+               case 0xC0000261: return "STATUS_INVALID_PLUGPLAY_DEVICE_PATH";
+               case 0xC0000262: return "STATUS_DRIVER_ORDINAL_NOT_FOUND";
+               case 0xC0000263: return "STATUS_DRIVER_ENTRYPOINT_NOT_FOUND";
+               case 0xC0000264: return "STATUS_RESOURCE_NOT_OWNED";
+               case 0xC0000265: return "STATUS_TOO_MANY_LINKS";
+               case 0xC0000266: return "STATUS_QUOTA_LIST_INCONSISTENT";
+               case 0xC0000267: return "STATUS_FILE_IS_OFFLINE";
+               case 0xC0000268: return "STATUS_EVALUATION_EXPIRATION";
+               case 0xC0000269: return "STATUS_ILLEGAL_DLL_RELOCATION";
+               case 0xC000026A: return "STATUS_LICENSE_VIOLATION";
+               case 0xC000026B: return "STATUS_DLL_INIT_FAILED_LOGOFF";
+               case 0xC000026C: return "STATUS_DRIVER_UNABLE_TO_LOAD";
+               case 0xC000026D: return "STATUS_DFS_UNAVAILABLE";
+               case 0xC000026E: return "STATUS_VOLUME_DISMOUNTED";
+               case 0xC000026F: return "STATUS_WX86_INTERNAL_ERROR";
+               case 0xC0000270: return "STATUS_WX86_FLOAT_STACK_CHECK";
+               case 0xC0000271: return "STATUS_VALIDATE_CONTINUE";
+               case 0xC0000272: return "STATUS_NO_MATCH";
+               case 0xC0000273: return "STATUS_NO_MORE_MATCHES";
+               case 0xC0000275: return "STATUS_NOT_A_REPARSE_POINT";
+               case 0xC0000276: return "STATUS_IO_REPARSE_TAG_INVALID";
+               case 0xC0000277: return "STATUS_IO_REPARSE_TAG_MISMATCH";
+               case 0xC0000278: return "STATUS_IO_REPARSE_DATA_INVALID";
+               case 0xC0000279: return "STATUS_IO_REPARSE_TAG_NOT_HANDLED";
+               case 0xC0000280: return "STATUS_REPARSE_POINT_NOT_RESOLVED";
+               case 0xC0000281: return "STATUS_DIRECTORY_IS_A_REPARSE_POINT";
+               case 0xC0000282: return "STATUS_RANGE_LIST_CONFLICT";
+               case 0xC0000283: return "STATUS_SOURCE_ELEMENT_EMPTY";
+               case 0xC0000284: return "STATUS_DESTINATION_ELEMENT_FULL";
+               case 0xC0000285: return "STATUS_ILLEGAL_ELEMENT_ADDRESS";
+               case 0xC0000286: return "STATUS_MAGAZINE_NOT_PRESENT";
+               case 0xC0000287: return "STATUS_REINITIALIZATION_NEEDED";
+               case 0x80000288: return "STATUS_DEVICE_REQUIRES_CLEANING";
+               case 0x80000289: return "STATUS_DEVICE_DOOR_OPEN";
+               case 0xC000028A: return "STATUS_ENCRYPTION_FAILED";
+               case 0xC000028B: return "STATUS_DECRYPTION_FAILED";
+               case 0xC000028C: return "STATUS_RANGE_NOT_FOUND";
+               case 0xC000028D: return "STATUS_NO_RECOVERY_POLICY";
+               case 0xC000028E: return "STATUS_NO_EFS";
+               case 0xC000028F: return "STATUS_WRONG_EFS";
+               case 0xC0000290: return "STATUS_NO_USER_KEYS";
+               case 0xC0000291: return "STATUS_FILE_NOT_ENCRYPTED";
+               case 0xC0000292: return "STATUS_NOT_EXPORT_FORMAT";
+               case 0xC0000293: return "STATUS_FILE_ENCRYPTED";
+               case 0x40000294: return "STATUS_WAKE_SYSTEM";
+               case 0xC0000295: return "STATUS_WMI_GUID_NOT_FOUND";
+               case 0xC0000296: return "STATUS_WMI_INSTANCE_NOT_FOUND";
+               case 0xC0000297: return "STATUS_WMI_ITEMID_NOT_FOUND";
+               case 0xC0000298: return "STATUS_WMI_TRY_AGAIN";
+               case 0xC0000299: return "STATUS_SHARED_POLICY";
+               case 0xC000029A: return "STATUS_POLICY_OBJECT_NOT_FOUND";
+               case 0xC000029B: return "STATUS_POLICY_ONLY_IN_DS";
+               case 0xC000029C: return "STATUS_VOLUME_NOT_UPGRADED";
+               case 0xC000029D: return "STATUS_REMOTE_STORAGE_NOT_ACTIVE";
+               case 0xC000029E: return "STATUS_REMOTE_STORAGE_MEDIA_ERROR";
+               case 0xC000029F: return "STATUS_NO_TRACKING_SERVICE";
+               case 0xC00002A0: return "STATUS_SERVER_SID_MISMATCH";
+               case 0xC00002A1: return "STATUS_DS_NO_ATTRIBUTE_OR_VALUE";
+               case 0xC00002A2: return "STATUS_DS_INVALID_ATTRIBUTE_SYNTAX";
+               case 0xC00002A3: return "STATUS_DS_ATTRIBUTE_TYPE_UNDEFINED";
+               case 0xC00002A4: return "STATUS_DS_ATTRIBUTE_OR_VALUE_EXISTS";
+               case 0xC00002A5: return "STATUS_DS_BUSY";
+               case 0xC00002A6: return "STATUS_DS_UNAVAILABLE";
+               case 0xC00002A7: return "STATUS_DS_NO_RIDS_ALLOCATED";
+               case 0xC00002A8: return "STATUS_DS_NO_MORE_RIDS";
+               case 0xC00002A9: return "STATUS_DS_INCORRECT_ROLE_OWNER";
+               case 0xC00002AA: return "STATUS_DS_RIDMGR_INIT_ERROR";
+               case 0xC00002AB: return "STATUS_DS_OBJ_CLASS_VIOLATION";
+               case 0xC00002AC: return "STATUS_DS_CANT_ON_NON_LEAF";
+               case 0xC00002AD: return "STATUS_DS_CANT_ON_RDN";
+               case 0xC00002AE: return "STATUS_DS_CANT_MOD_OBJ_CLASS";
+               case 0xC00002AF: return "STATUS_DS_CROSS_DOM_MOVE_FAILED";
+               case 0xC00002B0: return "STATUS_DS_GC_NOT_AVAILABLE";
+               case 0xC00002B1: return "STATUS_DIRECTORY_SERVICE_REQUIRED";
+               case 0xC00002B2: return "STATUS_REPARSE_ATTRIBUTE_CONFLICT";
+               case 0xC00002B3: return "STATUS_CANT_ENABLE_DENY_ONLY";
+               case 0xC00002B4: return "STATUS_FLOAT_MULTIPLE_FAULTS";
+               case 0xC00002B5: return "STATUS_FLOAT_MULTIPLE_TRAPS";
+               case 0xC00002B6: return "STATUS_DEVICE_REMOVED";
+               case 0xC00002B7: return "STATUS_JOURNAL_DELETE_IN_PROGRESS";
+               case 0xC00002B8: return "STATUS_JOURNAL_NOT_ACTIVE";
+               case 0xC00002B9: return "STATUS_NOINTERFACE";
+               case 0xC00002C1: return "STATUS_DS_ADMIN_LIMIT_EXCEEDED";
+               case 0xC00002C2: return "STATUS_DRIVER_FAILED_SLEEP";
+               case 0xC00002C3: return "STATUS_MUTUAL_AUTHENTICATION_FAILED";
+               case 0xC00002C4: return "STATUS_CORRUPT_SYSTEM_FILE";
+               case 0xC00002C5: return "STATUS_DATATYPE_MISALIGNMENT_ERROR";
+               case 0xC00002C6: return "STATUS_WMI_READ_ONLY";
+               case 0xC00002C7: return "STATUS_WMI_SET_FAILURE";
+               case 0xC00002C8: return "STATUS_COMMITMENT_MINIMUM";
+               case 0xC00002C9: return "STATUS_REG_NAT_CONSUMPTION";
+               case 0xC00002CA: return "STATUS_TRANSPORT_FULL";
+               case 0xC00002CB: return "STATUS_DS_SAM_INIT_FAILURE";
+               case 0xC00002CC: return "STATUS_ONLY_IF_CONNECTED";
+               case 0xC00002CD: return "STATUS_DS_SENSITIVE_GROUP_VIOLATION";
+               case 0xC00002CE: return "STATUS_PNP_RESTART_ENUMERATION";
+               case 0xC00002CF: return "STATUS_JOURNAL_ENTRY_DELETED";
+               case 0xC00002D0: return "STATUS_DS_CANT_MOD_PRIMARYGROUPID";
+               case 0xC00002D1: return "STATUS_SYSTEM_IMAGE_BAD_SIGNATURE";
+               case 0xC00002D2: return "STATUS_PNP_REBOOT_REQUIRED";
+               case 0xC00002D3: return "STATUS_POWER_STATE_INVALID";
+               case 0xC00002D4: return "STATUS_DS_INVALID_GROUP_TYPE";
+               case 0xC00002D5: return "STATUS_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN";
+               case 0xC00002D6: return "STATUS_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN";
+               case 0xC00002D7: return "STATUS_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER";
+               case 0xC00002D8: return "STATUS_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER";
+               case 0xC00002D9: return "STATUS_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER";
+               case 0xC00002DA: return "STATUS_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER";
+               case 0xC00002DB: return "STATUS_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER";
+               case 0xC00002DC: return "STATUS_DS_HAVE_PRIMARY_MEMBERS";
+               case 0xC00002DD: return "STATUS_WMI_NOT_SUPPORTED";
+               case 0xC00002DE: return "STATUS_INSUFFICIENT_POWER";
+               case 0xC00002DF: return "STATUS_SAM_NEED_BOOTKEY_PASSWORD";
+               case 0xC00002E0: return "STATUS_SAM_NEED_BOOTKEY_FLOPPY";
+               case 0xC00002E1: return "STATUS_DS_CANT_START";
+               case 0xC00002E2: return "STATUS_DS_INIT_FAILURE";
+               case 0xC00002E3: return "STATUS_SAM_INIT_FAILURE";
+               case 0xC00002E4: return "STATUS_DS_GC_REQUIRED";
+               case 0xC00002E5: return "STATUS_DS_LOCAL_MEMBER_OF_LOCAL_ONLY";
+               case 0xC00002E6: return "STATUS_DS_NO_FPO_IN_UNIVERSAL_GROUPS";
+               case 0xC00002E7: return "STATUS_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED";
+               case 0xC00002E8: return "STATUS_MULTIPLE_FAULT_VIOLATION";
+               case 0xC0000300: return "STATUS_NOT_SUPPORTED_ON_SBS";
+               case 0xC0009898: return "STATUS_WOW_ASSERTION";
+               case 0xC0010001: return "DBG_NO_STATE_CHANGE";
+               case 0xC0010002: return "DBG_APP_NOT_IDLE";
+               case 0xC0020001: return "RPC_NT_INVALID_STRING_BINDING";
+               case 0xC0020002: return "RPC_NT_WRONG_KIND_OF_BINDING";
+               case 0xC0020003: return "RPC_NT_INVALID_BINDING";
+               case 0xC0020004: return "RPC_NT_PROTSEQ_NOT_SUPPORTED";
+               case 0xC0020005: return "RPC_NT_INVALID_RPC_PROTSEQ";
+               case 0xC0020006: return "RPC_NT_INVALID_STRING_UUID";
+               case 0xC0020007: return "RPC_NT_INVALID_ENDPOINT_FORMAT";
+               case 0xC0020008: return "RPC_NT_INVALID_NET_ADDR";
+               case 0xC0020009: return "RPC_NT_NO_ENDPOINT_FOUND";
+               case 0xC002000A: return "RPC_NT_INVALID_TIMEOUT";
+               case 0xC002000B: return "RPC_NT_OBJECT_NOT_FOUND";
+               case 0xC002000C: return "RPC_NT_ALREADY_REGISTERED";
+               case 0xC002000D: return "RPC_NT_TYPE_ALREADY_REGISTERED";
+               case 0xC002000E: return "RPC_NT_ALREADY_LISTENING";
+               case 0xC002000F: return "RPC_NT_NO_PROTSEQS_REGISTERED";
+               case 0xC0020010: return "RPC_NT_NOT_LISTENING";
+               case 0xC0020011: return "RPC_NT_UNKNOWN_MGR_TYPE";
+               case 0xC0020012: return "RPC_NT_UNKNOWN_IF";
+               case 0xC0020013: return "RPC_NT_NO_BINDINGS";
+               case 0xC0020014: return "RPC_NT_NO_PROTSEQS";
+               case 0xC0020015: return "RPC_NT_CANT_CREATE_ENDPOINT";
+               case 0xC0020016: return "RPC_NT_OUT_OF_RESOURCES";
+               case 0xC0020017: return "RPC_NT_SERVER_UNAVAILABLE";
+               case 0xC0020018: return "RPC_NT_SERVER_TOO_BUSY";
+               case 0xC0020019: return "RPC_NT_INVALID_NETWORK_OPTIONS";
+               case 0xC002001A: return "RPC_NT_NO_CALL_ACTIVE";
+               case 0xC002001B: return "RPC_NT_CALL_FAILED";
+               case 0xC002001C: return "RPC_NT_CALL_FAILED_DNE";
+               case 0xC002001D: return "RPC_NT_PROTOCOL_ERROR";
+               case 0xC002001F: return "RPC_NT_UNSUPPORTED_TRANS_SYN";
+               case 0xC0020021: return "RPC_NT_UNSUPPORTED_TYPE";
+               case 0xC0020022: return "RPC_NT_INVALID_TAG";
+               case 0xC0020023: return "RPC_NT_INVALID_BOUND";
+               case 0xC0020024: return "RPC_NT_NO_ENTRY_NAME";
+               case 0xC0020025: return "RPC_NT_INVALID_NAME_SYNTAX";
+               case 0xC0020026: return "RPC_NT_UNSUPPORTED_NAME_SYNTAX";
+               case 0xC0020028: return "RPC_NT_UUID_NO_ADDRESS";
+               case 0xC0020029: return "RPC_NT_DUPLICATE_ENDPOINT";
+               case 0xC002002A: return "RPC_NT_UNKNOWN_AUTHN_TYPE";
+               case 0xC002002B: return "RPC_NT_MAX_CALLS_TOO_SMALL";
+               case 0xC002002C: return "RPC_NT_STRING_TOO_LONG";
+               case 0xC002002D: return "RPC_NT_PROTSEQ_NOT_FOUND";
+               case 0xC002002E: return "RPC_NT_PROCNUM_OUT_OF_RANGE";
+               case 0xC002002F: return "RPC_NT_BINDING_HAS_NO_AUTH";
+               case 0xC0020030: return "RPC_NT_UNKNOWN_AUTHN_SERVICE";
+               case 0xC0020031: return "RPC_NT_UNKNOWN_AUTHN_LEVEL";
+               case 0xC0020032: return "RPC_NT_INVALID_AUTH_IDENTITY";
+               case 0xC0020033: return "RPC_NT_UNKNOWN_AUTHZ_SERVICE";
+               case 0xC0020034: return "EPT_NT_INVALID_ENTRY";
+               case 0xC0020035: return "EPT_NT_CANT_PERFORM_OP";
+               case 0xC0020036: return "EPT_NT_NOT_REGISTERED";
+               case 0xC0020037: return "RPC_NT_NOTHING_TO_EXPORT";
+               case 0xC0020038: return "RPC_NT_INCOMPLETE_NAME";
+               case 0xC0020039: return "RPC_NT_INVALID_VERS_OPTION";
+               case 0xC002003A: return "RPC_NT_NO_MORE_MEMBERS";
+               case 0xC002003B: return "RPC_NT_NOT_ALL_OBJS_UNEXPORTED";
+               case 0xC002003C: return "RPC_NT_INTERFACE_NOT_FOUND";
+               case 0xC002003D: return "RPC_NT_ENTRY_ALREADY_EXISTS";
+               case 0xC002003E: return "RPC_NT_ENTRY_NOT_FOUND";
+               case 0xC002003F: return "RPC_NT_NAME_SERVICE_UNAVAILABLE";
+               case 0xC0020040: return "RPC_NT_INVALID_NAF_ID";
+               case 0xC0020041: return "RPC_NT_CANNOT_SUPPORT";
+               case 0xC0020042: return "RPC_NT_NO_CONTEXT_AVAILABLE";
+               case 0xC0020043: return "RPC_NT_INTERNAL_ERROR";
+               case 0xC0020044: return "RPC_NT_ZERO_DIVIDE";
+               case 0xC0020045: return "RPC_NT_ADDRESS_ERROR";
+               case 0xC0020046: return "RPC_NT_FP_DIV_ZERO";
+               case 0xC0020047: return "RPC_NT_FP_UNDERFLOW";
+               case 0xC0020048: return "RPC_NT_FP_OVERFLOW";
+               case 0xC0030001: return "RPC_NT_NO_MORE_ENTRIES";
+               case 0xC0030002: return "RPC_NT_SS_CHAR_TRANS_OPEN_FAIL";
+               case 0xC0030003: return "RPC_NT_SS_CHAR_TRANS_SHORT_FILE";
+               case 0xC0030004: return "RPC_NT_SS_IN_NULL_CONTEXT";
+               case 0xC0030005: return "RPC_NT_SS_CONTEXT_MISMATCH";
+               case 0xC0030006: return "RPC_NT_SS_CONTEXT_DAMAGED";
+               case 0xC0030007: return "RPC_NT_SS_HANDLES_MISMATCH";
+               case 0xC0030008: return "RPC_NT_SS_CANNOT_GET_CALL_HANDLE";
+               case 0xC0030009: return "RPC_NT_NULL_REF_POINTER";
+               case 0xC003000A: return "RPC_NT_ENUM_VALUE_OUT_OF_RANGE";
+               case 0xC003000B: return "RPC_NT_BYTE_COUNT_TOO_SMALL";
+               case 0xC003000C: return "RPC_NT_BAD_STUB_DATA";
+               case 0xC0020049: return "RPC_NT_CALL_IN_PROGRESS";
+               case 0xC002004A: return "RPC_NT_NO_MORE_BINDINGS";
+               case 0xC002004B: return "RPC_NT_GROUP_MEMBER_NOT_FOUND";
+               case 0xC002004C: return "EPT_NT_CANT_CREATE";
+               case 0xC002004D: return "RPC_NT_INVALID_OBJECT";
+               case 0xC002004F: return "RPC_NT_NO_INTERFACES";
+               case 0xC0020050: return "RPC_NT_CALL_CANCELLED";
+               case 0xC0020051: return "RPC_NT_BINDING_INCOMPLETE";
+               case 0xC0020052: return "RPC_NT_COMM_FAILURE";
+               case 0xC0020053: return "RPC_NT_UNSUPPORTED_AUTHN_LEVEL";
+               case 0xC0020054: return "RPC_NT_NO_PRINC_NAME";
+               case 0xC0020055: return "RPC_NT_NOT_RPC_ERROR";
+               case 0x40020056: return "RPC_NT_UUID_LOCAL_ONLY";
+               case 0xC0020057: return "RPC_NT_SEC_PKG_ERROR";
+               case 0xC0020058: return "RPC_NT_NOT_CANCELLED";
+               case 0xC0030059: return "RPC_NT_INVALID_ES_ACTION";
+               case 0xC003005A: return "RPC_NT_WRONG_ES_VERSION";
+               case 0xC003005B: return "RPC_NT_WRONG_STUB_VERSION";
+               case 0xC003005C: return "RPC_NT_INVALID_PIPE_OBJECT";
+               case 0xC003005D: return "RPC_NT_INVALID_PIPE_OPERATION";
+               case 0xC003005E: return "RPC_NT_WRONG_PIPE_VERSION";
+               case 0xC003005F: return "RPC_NT_PIPE_CLOSED";
+               case 0xC0030060: return "RPC_NT_PIPE_DISCIPLINE_ERROR";
+               case 0xC0030061: return "RPC_NT_PIPE_EMPTY";
+               case 0xC0020062: return "RPC_NT_INVALID_ASYNC_HANDLE";
+               case 0xC0020063: return "RPC_NT_INVALID_ASYNC_CALL";
+               case 0x400200AF: return "RPC_NT_SEND_INCOMPLETE";
+               case 0xC0140001: return "STATUS_ACPI_INVALID_OPCODE";
+               case 0xC0140002: return "STATUS_ACPI_STACK_OVERFLOW";
+               case 0xC0140003: return "STATUS_ACPI_ASSERT_FAILED";
+               case 0xC0140004: return "STATUS_ACPI_INVALID_INDEX";
+               case 0xC0140005: return "STATUS_ACPI_INVALID_ARGUMENT";
+               case 0xC0140006: return "STATUS_ACPI_FATAL";
+               case 0xC0140007: return "STATUS_ACPI_INVALID_SUPERNAME";
+               case 0xC0140008: return "STATUS_ACPI_INVALID_ARGTYPE";
+               case 0xC0140009: return "STATUS_ACPI_INVALID_OBJTYPE";
+               case 0xC014000A: return "STATUS_ACPI_INVALID_TARGETTYPE";
+               case 0xC014000B: return "STATUS_ACPI_INCORRECT_ARGUMENT_COUNT";
+               case 0xC014000C: return "STATUS_ACPI_ADDRESS_NOT_MAPPED";
+               case 0xC014000D: return "STATUS_ACPI_INVALID_EVENTTYPE";
+               case 0xC014000E: return "STATUS_ACPI_HANDLER_COLLISION";
+               case 0xC014000F: return "STATUS_ACPI_INVALID_DATA";
+               case 0xC0140010: return "STATUS_ACPI_INVALID_REGION";
+               case 0xC0140011: return "STATUS_ACPI_INVALID_ACCESS_SIZE";
+               case 0xC0140012: return "STATUS_ACPI_ACQUIRE_GLOBAL_LOCK";
+               case 0xC0140013: return "STATUS_ACPI_ALREADY_INITIALIZED";
+               case 0xC0140014: return "STATUS_ACPI_NOT_INITIALIZED";
+               case 0xC0140015: return "STATUS_ACPI_INVALID_MUTEX_LEVEL";
+               case 0xC0140016: return "STATUS_ACPI_MUTEX_NOT_OWNED";
+               case 0xC0140017: return "STATUS_ACPI_MUTEX_NOT_OWNER";
+               case 0xC0140018: return "STATUS_ACPI_RS_ACCESS";
+               case 0xC0140019: return "STATUS_ACPI_INVALID_TABLE";
+               case 0xC0140020: return "STATUS_ACPI_REG_HANDLER_FAILED";
+               case 0xC0140021: return "STATUS_ACPI_POWER_REQUEST_FAILED";
+               case 0xC00A0001: return "STATUS_CTX_WINSTATION_NAME_INVALID";
+               case 0xC00A0002: return "STATUS_CTX_INVALID_PD";
+               case 0xC00A0003: return "STATUS_CTX_PD_NOT_FOUND";
+               case 0x400A0004: return "STATUS_CTX_CDM_CONNECT";
+               case 0x400A0005: return "STATUS_CTX_CDM_DISCONNECT";
+               case 0xC00A0006: return "STATUS_CTX_CLOSE_PENDING";
+               case 0xC00A0007: return "STATUS_CTX_NO_OUTBUF";
+               case 0xC00A0008: return "STATUS_CTX_MODEM_INF_NOT_FOUND";
+               case 0xC00A0009: return "STATUS_CTX_INVALID_MODEMNAME";
+               case 0xC00A000A: return "STATUS_CTX_RESPONSE_ERROR";
+               case 0xC00A000B: return "STATUS_CTX_MODEM_RESPONSE_TIMEOUT";
+               case 0xC00A000C: return "STATUS_CTX_MODEM_RESPONSE_NO_CARRIER";
+               case 0xC00A000D: return "STATUS_CTX_MODEM_RESPONSE_NO_DIALTONE";
+               case 0xC00A000E: return "STATUS_CTX_MODEM_RESPONSE_BUSY";
+               case 0xC00A000F: return "STATUS_CTX_MODEM_RESPONSE_VOICE";
+               case 0xC00A0010: return "STATUS_CTX_TD_ERROR";
+               case 0xC00A0012: return "STATUS_CTX_LICENSE_CLIENT_INVALID";
+               case 0xC00A0013: return "STATUS_CTX_LICENSE_NOT_AVAILABLE";
+               case 0xC00A0014: return "STATUS_CTX_LICENSE_EXPIRED";
+               case 0xC00A0015: return "STATUS_CTX_WINSTATION_NOT_FOUND";
+               case 0xC00A0016: return "STATUS_CTX_WINSTATION_NAME_COLLISION";
+               case 0xC00A0017: return "STATUS_CTX_WINSTATION_BUSY";
+               case 0xC00A0018: return "STATUS_CTX_BAD_VIDEO_MODE";
+               case 0xC00A0022: return "STATUS_CTX_GRAPHICS_INVALID";
+               case 0xC00A0024: return "STATUS_CTX_NOT_CONSOLE";
+               case 0xC00A0026: return "STATUS_CTX_CLIENT_QUERY_TIMEOUT";
+               case 0xC00A0027: return "STATUS_CTX_CONSOLE_DISCONNECT";
+               case 0xC00A0028: return "STATUS_CTX_CONSOLE_CONNECT";
+               case 0xC00A002A: return "STATUS_CTX_SHADOW_DENIED";
+               case 0xC00A002B: return "STATUS_CTX_WINSTATION_ACCESS_DENIED";
+               case 0xC00A002E: return "STATUS_CTX_INVALID_WD";
+               case 0xC00A002F: return "STATUS_CTX_WD_NOT_FOUND";
+               case 0xC00A0030: return "STATUS_CTX_SHADOW_INVALID";
+               case 0xC00A0031: return "STATUS_CTX_SHADOW_DISABLED";
+               case 0xC00A0032: return "STATUS_RDP_PROTOCOL_ERROR";
+               case 0xC00A0033: return "STATUS_CTX_CLIENT_LICENSE_NOT_SET";
+               case 0xC00A0034: return "STATUS_CTX_CLIENT_LICENSE_IN_USE";
+               case 0xC0040035: return "STATUS_PNP_BAD_MPS_TABLE";
+               case 0xC0040036: return "STATUS_PNP_TRANSLATION_FAILED";
+               case 0xC0040037: return "STATUS_PNP_IRQ_TRANSLATION_FAILED";
+               default:         return "STATUS_UNKNOWN";
+       }
+}
+
+#endif // DBG
diff --git a/reactos/drivers/filesystems/ffs/src/devctl.c b/reactos/drivers/filesystems/ffs/src/devctl.c
new file mode 100644 (file)
index 0000000..140e34a
--- /dev/null
@@ -0,0 +1,302 @@
+/* 
+ * FFS File System Driver for Windows
+ *
+ * devctl.c
+ *
+ * 2004.5.6 ~
+ *
+ * Lee Jae-Hong, http://www.pyrasis.com
+ *
+ * See License.txt
+ *
+ */
+
+#include "ntifs.h"
+#include "ffsdrv.h"
+
+/* Globals */
+
+extern PFFS_GLOBAL FFSGlobal;
+
+
+/* Definitions */
+
+#ifdef _PREFAST_
+IO_COMPLETION_ROUTINE FFSDeviceControlCompletion;
+#endif // _PREFAST_
+
+NTSTATUS NTAPI
+FFSDeviceControlCompletion(
+       IN PDEVICE_OBJECT   DeviceObject,
+       IN PIRP             Irp,
+       IN PVOID            Context);
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE, FFSDeviceControl)
+#pragma alloc_text(PAGE, FFSDeviceControlNormal)
+#if FFS_UNLOAD
+#pragma alloc_text(PAGE, FFSPrepareToUnload)
+#endif
+#endif
+
+
+NTSTATUS NTAPI
+FFSDeviceControlCompletion(
+       IN PDEVICE_OBJECT   DeviceObject,
+       IN PIRP             Irp,
+       IN PVOID            Context)
+{
+       if (Irp->PendingReturned)
+       {
+               IoMarkIrpPending(Irp);
+       }
+
+       return STATUS_SUCCESS;
+}
+
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSDeviceControlNormal(
+       IN PFFS_IRP_CONTEXT IrpContext)
+{
+       PDEVICE_OBJECT  DeviceObject;
+       BOOLEAN         CompleteRequest = TRUE;
+       NTSTATUS        Status = STATUS_UNSUCCESSFUL;
+
+       PFFS_VCB        Vcb;
+
+       PIRP            Irp;
+       PIO_STACK_LOCATION IrpSp;
+       PIO_STACK_LOCATION NextIrpSp;
+
+       PDEVICE_OBJECT  TargetDeviceObject;
+
+    PAGED_CODE();
+
+       _SEH2_TRY
+       {
+               ASSERT(IrpContext != NULL);
+
+               ASSERT((IrpContext->Identifier.Type == FFSICX) &&
+                               (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
+
+               CompleteRequest = TRUE;
+
+               DeviceObject = IrpContext->DeviceObject;
+
+               if (DeviceObject == FFSGlobal->DeviceObject)
+               {
+                       Status = STATUS_INVALID_DEVICE_REQUEST;
+
+                       _SEH2_LEAVE;
+               }
+
+               Irp = IrpContext->Irp;
+               IrpSp = IoGetCurrentIrpStackLocation(Irp);
+
+               Vcb = (PFFS_VCB)IrpSp->FileObject->FsContext;
+
+               if (!((Vcb) && (Vcb->Identifier.Type == FFSVCB) &&
+                                       (Vcb->Identifier.Size == sizeof(FFS_VCB))
+                   )
+                 )
+               {
+                       Status = STATUS_INVALID_PARAMETER;
+                       _SEH2_LEAVE;
+               }
+
+               TargetDeviceObject = Vcb->TargetDeviceObject;
+
+               //
+               // Pass on the IOCTL to the driver below
+               //
+
+               CompleteRequest = FALSE;
+
+               NextIrpSp = IoGetNextIrpStackLocation(Irp);
+               *NextIrpSp = *IrpSp;
+
+               IoSetCompletionRoutine(
+                               Irp,
+                               FFSDeviceControlCompletion,
+                               NULL,
+                               FALSE,
+                               TRUE,
+                               TRUE);
+
+               Status = IoCallDriver(TargetDeviceObject, Irp);
+       }
+
+       _SEH2_FINALLY
+       {
+               if (!IrpContext->ExceptionInProgress)
+               {
+                       if (IrpContext)
+                       {
+                               if (!CompleteRequest)
+                               {
+                                       IrpContext->Irp = NULL;
+                               }
+
+                               FFSCompleteIrpContext(IrpContext, Status);
+                       }
+               }
+       } _SEH2_END;
+
+       return Status;
+}
+
+
+#if FFS_UNLOAD
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSPrepareToUnload(
+       IN PFFS_IRP_CONTEXT IrpContext)
+{
+       PDEVICE_OBJECT  DeviceObject;
+       NTSTATUS        Status = STATUS_UNSUCCESSFUL;
+       BOOLEAN         GlobalDataResourceAcquired = FALSE;
+
+    PAGED_CODE();
+
+       _SEH2_TRY
+       {
+               ASSERT(IrpContext != NULL);
+
+               ASSERT((IrpContext->Identifier.Type == FFSICX) &&
+                               (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
+
+               DeviceObject = IrpContext->DeviceObject;
+
+               if (DeviceObject != FFSGlobal->DeviceObject)
+               {
+                       Status = STATUS_INVALID_DEVICE_REQUEST;
+                       _SEH2_LEAVE;
+               }
+
+               ExAcquireResourceExclusiveLite(
+                               &FFSGlobal->Resource,
+                               TRUE);
+
+               GlobalDataResourceAcquired = TRUE;
+
+               if (FlagOn(FFSGlobal->Flags, FFS_UNLOAD_PENDING))
+               {
+                       FFSPrint((DBG_ERROR, "FFSPrepareUnload:  Already ready to unload.\n"));
+
+                       Status = STATUS_ACCESS_DENIED;
+
+                       _SEH2_LEAVE;
+               }
+
+               {
+                       PFFS_VCB                Vcb;
+                       PLIST_ENTRY             ListEntry;
+
+                       ListEntry = FFSGlobal->VcbList.Flink;
+
+                       while (ListEntry != &(FFSGlobal->VcbList))
+                       {
+                               Vcb = CONTAINING_RECORD(ListEntry, FFS_VCB, Next);
+                               ListEntry = ListEntry->Flink;
+
+                               if (Vcb && (!Vcb->ReferenceCount) &&
+                                               IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING))
+                               {
+                                       FFSRemoveVcb(Vcb);
+                                       FFSClearVpbFlag(Vcb->Vpb, VPB_MOUNTED);
+
+                                       FFSFreeVcb(Vcb);
+                               }
+                       }
+               }
+
+               if (!IsListEmpty(&(FFSGlobal->VcbList)))
+               {
+
+                       FFSPrint((DBG_ERROR, "FFSPrepareUnload:  Mounted volumes exists.\n"));
+
+                       Status = STATUS_ACCESS_DENIED;
+
+                       _SEH2_LEAVE;
+               }
+
+               IoUnregisterFileSystem(FFSGlobal->DeviceObject);
+
+#ifdef _MSC_VER
+#pragma prefast( suppress: 28175, "allowed to unload" )
+#endif
+               FFSGlobal->DriverObject->DriverUnload = DriverUnload;
+
+               SetFlag(FFSGlobal->Flags, FFS_UNLOAD_PENDING);
+
+               FFSPrint((DBG_INFO, "FFSPrepareToUnload: Driver is ready to unload.\n"));
+
+               Status = STATUS_SUCCESS;
+       }
+       _SEH2_FINALLY
+       {
+               if (GlobalDataResourceAcquired)
+               {
+                       ExReleaseResourceForThreadLite(
+                                       &FFSGlobal->Resource,
+                                       ExGetCurrentResourceThread());
+               }
+
+               if (!IrpContext->ExceptionInProgress)
+               {
+                       FFSCompleteIrpContext(IrpContext, Status);
+               }
+       } _SEH2_END;
+
+       return Status;
+}
+
+#endif
+
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSDeviceControl(
+       IN PFFS_IRP_CONTEXT IrpContext)
+{
+       PIRP                Irp;
+       PIO_STACK_LOCATION  IoStackLocation;
+       ULONG               IoControlCode;
+       NTSTATUS            Status;
+
+    PAGED_CODE();
+
+       ASSERT(IrpContext);
+
+       ASSERT((IrpContext->Identifier.Type == FFSICX) &&
+                       (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
+
+       Irp = IrpContext->Irp;
+
+       IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
+
+       IoControlCode =
+               IoStackLocation->Parameters.DeviceIoControl.IoControlCode;
+
+       switch (IoControlCode)
+       {
+#if FFS_UNLOAD
+               case IOCTL_PREPARE_TO_UNLOAD:
+                       Status = FFSPrepareToUnload(IrpContext);
+                       break;
+#endif
+
+               case IOCTL_SELECT_BSD_PARTITION:
+                       Status = FFSSelectBSDPartition(IrpContext);
+                       break;
+
+               default:
+                       Status = FFSDeviceControlNormal(IrpContext);
+       }
+
+       return Status;
+}
diff --git a/reactos/drivers/filesystems/ffs/src/dirctl.c b/reactos/drivers/filesystems/ffs/src/dirctl.c
new file mode 100644 (file)
index 0000000..6db9b4b
--- /dev/null
@@ -0,0 +1,1372 @@
+/* 
+ * FFS File System Driver for Windows
+ *
+ * dirctl.c
+ *
+ * 2004.5.6 ~
+ *
+ * Lee Jae-Hong, http://www.pyrasis.com
+ *
+ * See License.txt
+ *
+ */
+
+#include "ntifs.h"
+#include "ffsdrv.h"
+
+/* Globals */
+
+extern PFFS_GLOBAL FFSGlobal;
+
+
+/* Definitions */
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE, FFSGetInfoLength)
+#pragma alloc_text(PAGE, FFSProcessDirEntry)
+#pragma alloc_text(PAGE, FFSQueryDirectory)
+#pragma alloc_text(PAGE, FFSNotifyChangeDirectory)
+#pragma alloc_text(PAGE, FFSDirectoryControl)
+#pragma alloc_text(PAGE, FFSIsDirectoryEmpty)
+#endif
+
+ULONG
+FFSGetInfoLength(
+       IN FILE_INFORMATION_CLASS  FileInformationClass)
+{
+    PAGED_CODE();
+
+       switch (FileInformationClass)
+       {
+               case FileDirectoryInformation:
+                       return sizeof(FILE_DIRECTORY_INFORMATION);
+                       break;
+
+               case FileFullDirectoryInformation:
+                       return sizeof(FILE_FULL_DIR_INFORMATION);
+                       break;
+
+               case FileBothDirectoryInformation:
+                       return sizeof(FILE_BOTH_DIR_INFORMATION);
+                       break;
+
+               case FileNamesInformation:
+                       return sizeof(FILE_NAMES_INFORMATION);
+                       break;
+
+               default:
+                       break;
+       }
+
+       return 0;
+}
+
+
+ULONG
+FFSProcessDirEntry(
+       IN PFFS_VCB                Vcb,
+       IN FILE_INFORMATION_CLASS  FileInformationClass,
+       IN ULONG                   in,
+       IN PVOID                   Buffer,
+       IN ULONG                   UsedLength,
+       IN ULONG                   Length,
+       IN ULONG                   FileIndex,
+       IN PUNICODE_STRING         pName,
+       IN BOOLEAN                 Single)
+{
+       FFSv1_INODE dinode1;
+       FFSv2_INODE dinode2;
+       PFILE_DIRECTORY_INFORMATION FDI;
+       PFILE_FULL_DIR_INFORMATION FFI;
+       PFILE_BOTH_DIR_INFORMATION FBI;
+       PFILE_NAMES_INFORMATION FNI;
+
+       ULONG InfoLength = 0;
+       ULONG NameLength = 0;
+       ULONG dwBytes = 0;
+
+    PAGED_CODE();
+
+       NameLength = pName->Length;
+
+       if (!in)
+       {
+               FFSPrint((DBG_ERROR, "FFSPricessDirEntry: ffs_dir_entry is empty.\n"));
+               return 0;
+       }
+
+       InfoLength = FFSGetInfoLength(FileInformationClass);
+
+       if (!InfoLength || InfoLength + NameLength - sizeof(WCHAR) > Length)
+       {
+               FFSPrint((DBG_INFO, "FFSPricessDirEntry: Buffer is not enough.\n"));
+               return 0;
+       }
+
+       if (FS_VERSION == 1)
+       {
+               if(!FFSv1LoadInode(Vcb, in, &dinode1))
+               {
+                       FFSPrint((DBG_ERROR, "FFSPricessDirEntry: Loading inode %xh error.\n", in));
+
+                       FFSBreakPoint();
+
+                       return 0;
+               }
+       }
+       else
+       {
+               if(!FFSv2LoadInode(Vcb, in, &dinode2))
+               {
+                       FFSPrint((DBG_ERROR, "FFSPricessDirEntry: Loading inode %xh error.\n", in));
+
+                       FFSBreakPoint();
+
+                       return 0;
+               }
+       }
+
+       switch(FileInformationClass)
+       {
+               case FileDirectoryInformation:
+                       FDI = (PFILE_DIRECTORY_INFORMATION) ((PUCHAR)Buffer + UsedLength);
+                       if (!Single)
+                               FDI->NextEntryOffset = InfoLength + NameLength - sizeof(WCHAR);
+                       else
+                               FDI->NextEntryOffset = 0;
+                       FDI->FileIndex = FileIndex;
+
+                       if (FS_VERSION == 1)
+                       {
+                               FDI->CreationTime = FFSSysTime(dinode1.di_ctime);
+                               FDI->LastAccessTime = FFSSysTime(dinode1.di_atime);
+                               FDI->LastWriteTime = FFSSysTime(dinode1.di_mtime);
+                               FDI->ChangeTime = FFSSysTime(dinode1.di_mtime);
+                               FDI->EndOfFile.QuadPart = dinode1.di_size;
+                               FDI->AllocationSize.QuadPart = dinode1.di_size;
+                               FDI->FileAttributes = FILE_ATTRIBUTE_NORMAL;
+
+                               if (FlagOn(Vcb->Flags, VCB_READ_ONLY) || FFSIsReadOnly(dinode1.di_mode))
+                               {
+                                       SetFlag(FDI->FileAttributes, FILE_ATTRIBUTE_READONLY);
+                               }
+
+                               if ((dinode1.di_mode & IFMT) == IFDIR)
+                                       FDI->FileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
+
+                               FDI->FileNameLength = NameLength;
+                               RtlCopyMemory(FDI->FileName, pName->Buffer, NameLength);
+                               dwBytes = InfoLength + NameLength - sizeof(WCHAR); 
+                               break;
+                       }
+                       else
+                       {
+                               FDI->CreationTime = FFSSysTime((ULONG)dinode2.di_ctime);
+                               FDI->LastAccessTime = FFSSysTime((ULONG)dinode2.di_atime);
+                               FDI->LastWriteTime = FFSSysTime((ULONG)dinode2.di_mtime);
+                               FDI->ChangeTime = FFSSysTime((ULONG)dinode2.di_mtime);
+                               FDI->EndOfFile.QuadPart = dinode2.di_size;
+                               FDI->AllocationSize.QuadPart = dinode2.di_size;
+                               FDI->FileAttributes = FILE_ATTRIBUTE_NORMAL;
+
+                               if (FlagOn(Vcb->Flags, VCB_READ_ONLY) || FFSIsReadOnly(dinode2.di_mode))
+                               {
+                                       SetFlag(FDI->FileAttributes, FILE_ATTRIBUTE_READONLY);
+                               }
+
+                               if ((dinode2.di_mode & IFMT) == IFDIR)
+                                       FDI->FileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
+
+                               FDI->FileNameLength = NameLength;
+                               RtlCopyMemory(FDI->FileName, pName->Buffer, NameLength);
+                               dwBytes = InfoLength + NameLength - sizeof(WCHAR); 
+                               break;
+                       }
+
+               case FileFullDirectoryInformation:
+                       FFI = (PFILE_FULL_DIR_INFORMATION) ((PUCHAR)Buffer + UsedLength);
+                       if (!Single)
+                               FFI->NextEntryOffset = InfoLength + NameLength - sizeof(WCHAR);
+                       else
+                               FFI->NextEntryOffset = 0;
+                       FFI->FileIndex = FileIndex;
+
+                       if (FS_VERSION == 1)
+                       {
+                               FFI->CreationTime = FFSSysTime(dinode1.di_ctime);
+                               FFI->LastAccessTime = FFSSysTime(dinode1.di_atime);
+                               FFI->LastWriteTime = FFSSysTime(dinode1.di_mtime);
+                               FFI->ChangeTime = FFSSysTime(dinode1.di_mtime);
+                               FFI->EndOfFile.QuadPart = dinode1.di_size;
+                               FFI->AllocationSize.QuadPart = dinode1.di_size;
+                               FFI->FileAttributes = FILE_ATTRIBUTE_NORMAL;
+
+                               if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY)  || FFSIsReadOnly(dinode1.di_mode))
+                               {
+                                       SetFlag(FFI->FileAttributes, FILE_ATTRIBUTE_READONLY);
+                               }
+
+                               if ((dinode1.di_mode & IFMT) == IFDIR)
+                                       FFI->FileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
+
+                               FFI->FileNameLength = NameLength;
+                               RtlCopyMemory(FFI->FileName, pName->Buffer, NameLength);
+                               dwBytes = InfoLength + NameLength - sizeof(WCHAR); 
+
+                               break;
+                       }
+                       else
+                       {
+                               FFI->CreationTime = FFSSysTime((ULONG)dinode2.di_ctime);
+                               FFI->LastAccessTime = FFSSysTime((ULONG)dinode2.di_atime);
+                               FFI->LastWriteTime = FFSSysTime((ULONG)dinode2.di_mtime);
+                               FFI->ChangeTime = FFSSysTime((ULONG)dinode2.di_mtime);
+                               FFI->EndOfFile.QuadPart = dinode2.di_size;
+                               FFI->AllocationSize.QuadPart = dinode2.di_size;
+                               FFI->FileAttributes = FILE_ATTRIBUTE_NORMAL;
+
+                               if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY)  || FFSIsReadOnly(dinode2.di_mode))
+                               {
+                                       SetFlag(FFI->FileAttributes, FILE_ATTRIBUTE_READONLY);
+                               }
+
+                               if ((dinode2.di_mode & IFMT) == IFDIR)
+                                       FFI->FileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
+
+                               FFI->FileNameLength = NameLength;
+                               RtlCopyMemory(FFI->FileName, pName->Buffer, NameLength);
+                               dwBytes = InfoLength + NameLength - sizeof(WCHAR); 
+
+                               break;
+                       }
+
+               case FileBothDirectoryInformation:
+                       FBI = (PFILE_BOTH_DIR_INFORMATION) ((PUCHAR)Buffer + UsedLength);
+                       if (!Single)
+                               FBI->NextEntryOffset = InfoLength + NameLength - sizeof(WCHAR);
+                       else
+                               FBI->NextEntryOffset = 0;
+
+                       if (FS_VERSION == 1)
+                       {
+                               FBI->CreationTime = FFSSysTime(dinode1.di_ctime);
+                               FBI->LastAccessTime = FFSSysTime(dinode1.di_atime);
+                               FBI->LastWriteTime = FFSSysTime(dinode1.di_mtime);
+                               FBI->ChangeTime = FFSSysTime(dinode1.di_mtime);
+
+                               FBI->FileIndex = FileIndex;
+                               FBI->EndOfFile.QuadPart = dinode1.di_size;
+                               FBI->AllocationSize.QuadPart = dinode1.di_size;
+                               FBI->FileAttributes = FILE_ATTRIBUTE_NORMAL;
+
+                               if (FlagOn(Vcb->Flags, VCB_READ_ONLY) || FFSIsReadOnly(dinode1.di_mode))
+                               {
+                                       SetFlag(FBI->FileAttributes, FILE_ATTRIBUTE_READONLY);
+                               }
+
+                               if ((dinode1.di_mode & IFMT) == IFDIR)
+                                       FBI->FileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
+                               FBI->FileNameLength = NameLength;
+                               RtlCopyMemory(FBI->FileName, pName->Buffer, NameLength);
+                               dwBytes = InfoLength + NameLength - sizeof(WCHAR); 
+
+                               break;
+                       }
+                       else
+                       {
+                               FBI->CreationTime = FFSSysTime((ULONG)dinode2.di_ctime);
+                               FBI->LastAccessTime = FFSSysTime((ULONG)dinode2.di_atime);
+                               FBI->LastWriteTime = FFSSysTime((ULONG)dinode2.di_mtime);
+                               FBI->ChangeTime = FFSSysTime((ULONG)dinode2.di_mtime);
+
+                               FBI->FileIndex = FileIndex;
+                               FBI->EndOfFile.QuadPart = dinode2.di_size;
+                               FBI->AllocationSize.QuadPart = dinode2.di_size;
+                               FBI->FileAttributes = FILE_ATTRIBUTE_NORMAL;
+
+                               if (FlagOn(Vcb->Flags, VCB_READ_ONLY) || FFSIsReadOnly(dinode2.di_mode))
+                               {
+                                       SetFlag(FBI->FileAttributes, FILE_ATTRIBUTE_READONLY);
+                               }
+
+                               if ((dinode2.di_mode & IFMT) == IFDIR)
+                                       FBI->FileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
+                               FBI->FileNameLength = NameLength;
+                               RtlCopyMemory(FBI->FileName, pName->Buffer, NameLength);
+                               dwBytes = InfoLength + NameLength - sizeof(WCHAR); 
+
+                               break;
+                       }
+
+               case FileNamesInformation:
+                       FNI = (PFILE_NAMES_INFORMATION) ((PUCHAR)Buffer + UsedLength);
+                       if (!Single)
+                               FNI->NextEntryOffset = InfoLength + NameLength - sizeof(WCHAR);
+                       else
+                               FNI->NextEntryOffset = 0;
+                       FNI->FileNameLength = NameLength;
+                       RtlCopyMemory(FNI->FileName, pName->Buffer, NameLength);
+                       dwBytes = InfoLength + NameLength - sizeof(WCHAR); 
+
+                       break;
+
+               default:
+                       break;
+       }
+
+       return dwBytes;
+}
+
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSQueryDirectory(
+       IN PFFS_IRP_CONTEXT IrpContext)
+{
+       PDEVICE_OBJECT          DeviceObject;
+       NTSTATUS                Status = STATUS_UNSUCCESSFUL;
+       PFFS_VCB                Vcb = 0;
+       PFILE_OBJECT            FileObject;
+       PFFS_FCB                Fcb = 0;
+       PFFS_CCB                Ccb;
+       PIRP                    Irp;
+       PIO_STACK_LOCATION      IoStackLocation;
+       FILE_INFORMATION_CLASS  FileInformationClass;
+       ULONG                   Length;
+       PUNICODE_STRING         FileName;
+       ULONG                   FileIndex;
+       BOOLEAN                 RestartScan;
+       BOOLEAN                 ReturnSingleEntry;
+       BOOLEAN                 IndexSpecified;
+       PUCHAR                  Buffer;
+       BOOLEAN                 FirstQuery;
+       PFFSv1_INODE            dinode1 = NULL;
+       PFFSv2_INODE            dinode2 = NULL;
+       BOOLEAN                 FcbResourceAcquired = FALSE;
+       ULONG                   UsedLength = 0;
+       USHORT                  InodeFileNameLength;
+       UNICODE_STRING          InodeFileName;
+       PFFS_DIR_ENTRY          pDir = NULL;
+       ULONG                   dwBytes;
+       ULONG                   dwTemp = 0;
+       ULONG                   dwSize = 0;
+       ULONG                   dwReturn = 0;
+       BOOLEAN                 bRun = TRUE;
+       ULONG                   ByteOffset;
+
+    PAGED_CODE();
+
+       InodeFileName.Buffer = NULL;
+
+       _SEH2_TRY
+       {
+               ASSERT(IrpContext);
+
+               ASSERT((IrpContext->Identifier.Type == FFSICX) &&
+                               (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
+
+               DeviceObject = IrpContext->DeviceObject;
+
+               //
+               // This request is not allowed on the main device object
+               //
+               if (DeviceObject == FFSGlobal->DeviceObject)
+               {
+                       Status = STATUS_INVALID_DEVICE_REQUEST;
+                       _SEH2_LEAVE;
+               }
+
+               Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;
+
+               ASSERT(Vcb != NULL);
+
+               ASSERT((Vcb->Identifier.Type == FFSVCB) &&
+                               (Vcb->Identifier.Size == sizeof(FFS_VCB)));
+
+               ASSERT(IsMounted(Vcb));
+
+               FileObject = IrpContext->FileObject;
+
+               Fcb = (PFFS_FCB)FileObject->FsContext;
+
+               ASSERT(Fcb);
+
+               //
+               // This request is not allowed on volumes
+               //
+               if (Fcb->Identifier.Type == FFSVCB)
+               {
+                       Status = STATUS_INVALID_PARAMETER;
+                       _SEH2_LEAVE;
+               }
+
+               ASSERT((Fcb->Identifier.Type == FFSFCB) &&
+                               (Fcb->Identifier.Size == sizeof(FFS_FCB)));
+
+               if (!IsDirectory(Fcb))
+               {
+                       Status = STATUS_INVALID_PARAMETER;
+                       _SEH2_LEAVE;
+               }
+
+               Ccb = (PFFS_CCB)FileObject->FsContext2;
+
+               ASSERT(Ccb);
+
+               ASSERT((Ccb->Identifier.Type == FFSCCB) &&
+                               (Ccb->Identifier.Size == sizeof(FFS_CCB)));
+
+               Irp = IrpContext->Irp;
+
+               IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
+
+#if !defined(_GNU_NTIFS_) || defined(__REACTOS__)
+
+               FileInformationClass =
+                       IoStackLocation->Parameters.QueryDirectory.FileInformationClass;
+
+               Length = IoStackLocation->Parameters.QueryDirectory.Length;
+
+               FileName = IoStackLocation->Parameters.QueryDirectory.FileName;
+
+               FileIndex = IoStackLocation->Parameters.QueryDirectory.FileIndex;
+
+#else // _GNU_NTIFS_
+
+               FileInformationClass = ((PEXTENDED_IO_STACK_LOCATION)
+                               IoStackLocation)->Parameters.QueryDirectory.FileInformationClass;
+
+               Length = ((PEXTENDED_IO_STACK_LOCATION)
+                               IoStackLocation)->Parameters.QueryDirectory.Length;
+
+               FileName = ((PEXTENDED_IO_STACK_LOCATION)
+                               IoStackLocation)->Parameters.QueryDirectory.FileName;
+
+               FileIndex = ((PEXTENDED_IO_STACK_LOCATION)
+                               IoStackLocation)->Parameters.QueryDirectory.FileIndex;
+
+#endif // _GNU_NTIFS_
+
+               RestartScan = FlagOn(IoStackLocation->Flags, SL_RESTART_SCAN);
+               ReturnSingleEntry = FlagOn(IoStackLocation->Flags, SL_RETURN_SINGLE_ENTRY);
+               IndexSpecified = FlagOn(IoStackLocation->Flags, SL_INDEX_SPECIFIED);
+               /*
+               if (!Irp->MdlAddress && Irp->UserBuffer)
+               {
+                       ProbeForWrite(Irp->UserBuffer, Length, 1);
+               }
+               */
+               Buffer = FFSGetUserBuffer(Irp);
+
+               if (Buffer == NULL)
+               {
+                       FFSBreakPoint();
+                       Status = STATUS_INVALID_USER_BUFFER;
+                       _SEH2_LEAVE;
+               }
+
+               if (!IrpContext->IsSynchronous)
+               {
+                       Status = STATUS_PENDING;
+                       _SEH2_LEAVE;
+               }
+
+               if (!ExAcquireResourceSharedLite(
+                                       &Fcb->MainResource,
+                                       IrpContext->IsSynchronous))
+               {
+                       Status = STATUS_PENDING;
+                       _SEH2_LEAVE;
+               }
+
+               FcbResourceAcquired = TRUE;
+
+               if (FileName != NULL)
+               {
+                       if (Ccb->DirectorySearchPattern.Buffer != NULL)
+                       {
+                               FirstQuery = FALSE;
+                       }
+                       else
+                       {
+                               FirstQuery = TRUE;
+
+                               Ccb->DirectorySearchPattern.Length =
+                                       Ccb->DirectorySearchPattern.MaximumLength =
+                                       FileName->Length;
+
+                               Ccb->DirectorySearchPattern.Buffer =
+                                       ExAllocatePoolWithTag(PagedPool, FileName->Length, FFS_POOL_TAG);
+
+                               if (Ccb->DirectorySearchPattern.Buffer == NULL)
+                               {
+                                       Status = STATUS_INSUFFICIENT_RESOURCES;
+                                       _SEH2_LEAVE;
+                               }
+
+                               Status = RtlUpcaseUnicodeString(
+                                               &(Ccb->DirectorySearchPattern),
+                                               FileName,
+                                               FALSE);
+
+                               if (!NT_SUCCESS(Status))
+                                       _SEH2_LEAVE;
+                       }
+               }
+               else if (Ccb->DirectorySearchPattern.Buffer != NULL)
+               {
+                       FirstQuery = FALSE;
+                       FileName = &Ccb->DirectorySearchPattern;
+               }
+               else
+               {
+                       FirstQuery = TRUE;
+
+                       Ccb->DirectorySearchPattern.Length =
+                               Ccb->DirectorySearchPattern.MaximumLength = 2;
+
+                       Ccb->DirectorySearchPattern.Buffer =
+                               ExAllocatePoolWithTag(PagedPool, 2, FFS_POOL_TAG);
+
+                       if (Ccb->DirectorySearchPattern.Buffer == NULL)
+                       {
+                               Status = STATUS_INSUFFICIENT_RESOURCES;
+                               _SEH2_LEAVE;
+                       }
+
+                       RtlCopyMemory(
+                                       Ccb->DirectorySearchPattern.Buffer,
+                                       L"*\0", 2);
+               }
+
+               if (!IndexSpecified)
+               {
+                       if (RestartScan || FirstQuery)
+                       {
+                               FileIndex = Fcb->FFSMcb->DeOffset = 0;
+                       }
+                       else
+                       {
+                               FileIndex = Ccb->CurrentByteOffset;
+                       }
+               }
+
+               if (FS_VERSION == 1)
+               {
+                       dinode1 = (PFFSv1_INODE)ExAllocatePoolWithTag(
+                                       PagedPool,
+                                       DINODE1_SIZE, FFS_POOL_TAG);
+
+                       if (dinode1 == NULL)
+                       {
+                               Status = STATUS_INSUFFICIENT_RESOURCES;
+                               _SEH2_LEAVE;
+                       }
+
+                       RtlZeroMemory(Buffer, Length);
+
+                       if (Fcb->dinode1->di_size <= FileIndex)
+                       {
+                               Status = STATUS_NO_MORE_FILES;
+                               _SEH2_LEAVE;
+                       }
+               }
+               else
+               {
+                       dinode2 = (PFFSv2_INODE)ExAllocatePoolWithTag(
+                                       PagedPool,
+                                       DINODE2_SIZE, FFS_POOL_TAG);
+
+                       if (dinode2 == NULL)
+                       {
+                               Status = STATUS_INSUFFICIENT_RESOURCES;
+                               _SEH2_LEAVE;
+                       }
+
+                       RtlZeroMemory(Buffer, Length);
+
+                       if (Fcb->dinode2->di_size <= FileIndex)
+                       {
+                               Status = STATUS_NO_MORE_FILES;
+                               _SEH2_LEAVE;
+                       }
+               }
+
+               pDir = ExAllocatePoolWithTag(PagedPool,
+                               sizeof(FFS_DIR_ENTRY), FFS_POOL_TAG);
+               if (!pDir)
+               {
+                       Status = STATUS_INSUFFICIENT_RESOURCES;
+                       _SEH2_LEAVE;
+               }
+
+
+               if (FS_VERSION == 1)
+               {
+                       dwBytes = 0;
+                       dwSize = (ULONG)Fcb->dinode1->di_size - FileIndex -
+                               (sizeof(FFS_DIR_ENTRY) - FFS_NAME_LEN + 1);
+
+                       ByteOffset = FileIndex;
+
+                       dwTemp = 0;
+
+                       while (bRun && UsedLength < Length  && dwBytes < dwSize)
+                       {
+                               OEM_STRING  OemName;
+
+                               RtlZeroMemory(pDir, sizeof(FFS_DIR_ENTRY));
+
+                               Status = FFSv1ReadInode(
+                                                       NULL,
+                                                       Vcb,
+                                                       Fcb->dinode1,
+                                                       ByteOffset,
+                                                       (PVOID)pDir,
+                                                       sizeof(FFS_DIR_ENTRY),
+                                                       &dwReturn);
+
+                               if (!NT_SUCCESS(Status))
+                               {
+                                       _SEH2_LEAVE;
+                               }
+
+                               if (!pDir->d_ino)
+                               {
+                                       if (pDir->d_reclen == 0)
+                                       {
+                                               FFSBreakPoint();
+                                               _SEH2_LEAVE;
+                                       }
+
+                                       goto ProcessNextEntryv1;
+                               }
+
+                               OemName.Buffer = pDir->d_name;
+                               OemName.Length = (pDir->d_namlen & 0xff);
+                               OemName.MaximumLength = OemName.Length;
+
+#if 0
+/*
+                               //
+                               // We could not filter the files: "." and ".."
+                               //
+
+                               if ((OemName.Length >) 1 && OemName.Buffer[0] == '.')
+                               {
+                                       if ( OemName.Length == 2 && OemName.Buffer[1] == '.')
+                                       {
+                                       }
+                                       else
+                                       {
+                                               goto ProcessNextEntry1;
+                                       }
+                               }
+*/
+#endif
+
+                               InodeFileNameLength = (USHORT)
+                                       RtlOemStringToUnicodeSize(&OemName);
+
+                               InodeFileName.Length = 0;
+                               InodeFileName.MaximumLength = InodeFileNameLength + 2;
+
+                               if (InodeFileNameLength <= 0)
+                               {
+                                       break;
+                               }
+
+                               InodeFileName.Buffer = ExAllocatePoolWithTag(
+                                               PagedPool,
+                                               InodeFileNameLength + 2, FFS_POOL_TAG);
+
+                               if (!InodeFileName.Buffer)
+                               {
+                                       Status = STATUS_INSUFFICIENT_RESOURCES;
+                                       _SEH2_LEAVE;
+                               }
+
+                               RtlZeroMemory(
+                                               InodeFileName.Buffer, 
+                                               InodeFileNameLength + 2);
+
+                               Status = FFSOEMToUnicode(&InodeFileName,
+                                               &OemName);
+
+                               if (!NT_SUCCESS(Status))
+                               {
+                                       _SEH2_LEAVE;
+                               }
+
+                               if (FsRtlDoesNameContainWildCards(
+                                                       &(Ccb->DirectorySearchPattern)) ?
+                                               FsRtlIsNameInExpression(
+                                                       &(Ccb->DirectorySearchPattern),
+                                                       &InodeFileName,
+                                                       TRUE,
+                                                       NULL) :
+                                               !RtlCompareUnicodeString(
+                                                       &(Ccb->DirectorySearchPattern),
+                                                       &InodeFileName,
+                                                       TRUE))
+                               {
+                                       dwReturn = FFSProcessDirEntry(
+                                                       Vcb, FileInformationClass,
+                                                       pDir->d_ino,
+                                                       Buffer,
+                                                       UsedLength, 
+                                                       Length - UsedLength,
+                                                       (FileIndex + dwBytes),
+                                                       &InodeFileName,
+                                                       ReturnSingleEntry);
+
+                                       if (dwReturn <= 0)
+                                       {
+                                               bRun = FALSE;
+                                       }
+                                       else
+                                       {
+                                               dwTemp = UsedLength;
+                                               UsedLength += dwReturn;
+                                       }
+                               }
+
+                               if (InodeFileName.Buffer != NULL)
+                               {
+                                       ExFreePool(InodeFileName.Buffer);
+                                       InodeFileName.Buffer = NULL;
+                               }
+
+ProcessNextEntryv1:
+
+                               if (bRun)
+                               {
+                                       dwBytes +=pDir->d_reclen;
+                                       Ccb->CurrentByteOffset = FileIndex + dwBytes;
+                               }
+
+                               if (UsedLength && ReturnSingleEntry)
+                               {
+                                       Status = STATUS_SUCCESS;
+                                       _SEH2_LEAVE;
+                               }
+
+                               ByteOffset = FileIndex + dwBytes;
+                       }
+               }
+               else
+               {
+                       dwBytes = 0;
+                       dwSize = (ULONG)Fcb->dinode2->di_size - FileIndex -
+                               (sizeof(FFS_DIR_ENTRY) - FFS_NAME_LEN + 1);
+
+                       ByteOffset = FileIndex;
+
+                       dwTemp = 0;
+
+                       while (bRun && UsedLength < Length  && dwBytes < dwSize)
+                       {
+                               OEM_STRING  OemName;
+
+                               RtlZeroMemory(pDir, sizeof(FFS_DIR_ENTRY));
+
+                               Status = FFSv2ReadInode(
+                                                       NULL,
+                                                       Vcb,
+                                                       Fcb->dinode2,
+                                                       ByteOffset,
+                                                       (PVOID)pDir,
+                                                       sizeof(FFS_DIR_ENTRY),
+                                                       &dwReturn);
+
+                               if (!NT_SUCCESS(Status))
+                               {
+                                       _SEH2_LEAVE;
+                               }
+
+                               if (!pDir->d_ino)
+                               {
+                                       if (pDir->d_reclen == 0)
+                                       {
+                                               FFSBreakPoint();
+                                               _SEH2_LEAVE;
+                                       }
+
+                                       goto ProcessNextEntryv2;
+                               }
+
+                               OemName.Buffer = pDir->d_name;
+                               OemName.Length = (pDir->d_namlen & 0xff);
+                               OemName.MaximumLength = OemName.Length;
+#if 0
+/*
+                               //
+                               // We could not filter the files: "." and ".."
+                               //
+
+                               if ((OemName.Length >) 1 && OemName.Buffer[0] == '.')
+                               {
+                                       if ( OemName.Length == 2 && OemName.Buffer[1] == '.')
+                                       {
+                                       }
+                                       else
+                                       {
+                                               goto ProcessNextEntry2;
+                                       }
+                               }
+*/
+#endif
+
+                               InodeFileNameLength = (USHORT)
+                                       RtlOemStringToUnicodeSize(&OemName);
+
+                               InodeFileName.Length = 0;
+                               InodeFileName.MaximumLength = InodeFileNameLength + 2;
+
+                               if (InodeFileNameLength <= 0)
+                               {
+                                       break;
+                               }
+
+                               InodeFileName.Buffer = ExAllocatePoolWithTag(
+                                               PagedPool,
+                                               InodeFileNameLength + 2, FFS_POOL_TAG);
+
+                               if (!InodeFileName.Buffer)
+                               {
+                                       Status = STATUS_INSUFFICIENT_RESOURCES;
+                                       _SEH2_LEAVE;
+                               }
+
+                               RtlZeroMemory(
+                                               InodeFileName.Buffer, 
+                                               InodeFileNameLength + 2);
+
+                               Status = FFSOEMToUnicode(&InodeFileName,
+                                               &OemName);
+
+                               if (!NT_SUCCESS(Status))
+                               {
+                                       _SEH2_LEAVE;
+                               }
+
+                               if (FsRtlDoesNameContainWildCards(
+                                                       &(Ccb->DirectorySearchPattern)) ?
+                                               FsRtlIsNameInExpression(
+                                                       &(Ccb->DirectorySearchPattern),
+                                                       &InodeFileName,
+                                                       TRUE,
+                                                       NULL) :
+                                               !RtlCompareUnicodeString(
+                                                       &(Ccb->DirectorySearchPattern),
+                                                       &InodeFileName,
+                                                       TRUE))
+                               {
+                                       dwReturn = FFSProcessDirEntry(
+                                                       Vcb, FileInformationClass,
+                                                       pDir->d_ino,
+                                                       Buffer,
+                                                       UsedLength, 
+                                                       Length - UsedLength,
+                                                       (FileIndex + dwBytes),
+                                                       &InodeFileName,
+                                                       ReturnSingleEntry);
+
+                                       if (dwReturn <= 0)
+                                       {
+                                               bRun = FALSE;
+                                       }
+                                       else
+                                       {
+                                               dwTemp = UsedLength;
+                                               UsedLength += dwReturn;
+                                       }
+                               }
+
+                               if (InodeFileName.Buffer != NULL)
+                               {
+                                       ExFreePool(InodeFileName.Buffer);
+                                       InodeFileName.Buffer = NULL;
+                               }
+
+ProcessNextEntryv2:
+
+                               if (bRun)
+                               {
+                                       dwBytes +=pDir->d_reclen;
+                                       Ccb->CurrentByteOffset = FileIndex + dwBytes;
+                               }
+
+                               if (UsedLength && ReturnSingleEntry)
+                               {
+                                       Status = STATUS_SUCCESS;
+                                       _SEH2_LEAVE;
+                               }
+
+                               ByteOffset = FileIndex + dwBytes;
+                       }
+               }
+
+               FileIndex += dwBytes;
+
+               ((PULONG)((PUCHAR)Buffer + dwTemp)) [0] = 0;
+
+               if (!UsedLength)
+               {
+                       if (FirstQuery)
+                       {
+                               Status = STATUS_NO_SUCH_FILE;
+                       }
+                       else
+                       {
+                               Status = STATUS_NO_MORE_FILES;
+                       }
+               }
+               else
+               {
+                       Status = STATUS_SUCCESS;
+               }
+       }
+
+       _SEH2_FINALLY
+       {
+
+               if (FcbResourceAcquired)
+               {
+                       ExReleaseResourceForThreadLite(
+                                       &Fcb->MainResource,
+                                       ExGetCurrentResourceThread());
+               }
+
+               if (FS_VERSION == 1)
+               {
+                       if (dinode1 != NULL)
+                       {
+                               ExFreePool(dinode1);
+                       }
+               }
+               else
+               {
+                       if (dinode2 != NULL)
+                       {
+                               ExFreePool(dinode2);
+                       }
+               }
+
+               if (pDir != NULL)
+               {
+                       ExFreePool(pDir);
+                       pDir = NULL;
+               }
+
+               if (InodeFileName.Buffer != NULL)
+               {
+                       ExFreePool(InodeFileName.Buffer);
+               }
+
+               if (!IrpContext->ExceptionInProgress)
+               {
+                       if (Status == STATUS_PENDING)
+                       {
+                               Status = FFSLockUserBuffer(
+                                               IrpContext->Irp,
+                                               Length,
+                                               IoWriteAccess);
+
+                               if (NT_SUCCESS(Status))
+                               {
+                                       Status = FFSQueueRequest(IrpContext);
+                               }
+                               else
+                               {
+                                       FFSCompleteIrpContext(IrpContext, Status);
+                               }
+                       }
+                       else
+                       {
+                               IrpContext->Irp->IoStatus.Information = UsedLength;
+                               FFSCompleteIrpContext(IrpContext, Status);
+                       }
+               }
+       } _SEH2_END;
+
+       return Status;
+}
+
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSNotifyChangeDirectory(
+       IN PFFS_IRP_CONTEXT IrpContext)
+{
+       PDEVICE_OBJECT      DeviceObject;
+       BOOLEAN             CompleteRequest;
+       NTSTATUS            Status = STATUS_UNSUCCESSFUL;
+       PFFS_VCB            Vcb;
+       PFILE_OBJECT        FileObject;
+       PFFS_FCB            Fcb = 0;
+       PIRP                Irp;
+       PIO_STACK_LOCATION  IrpSp;
+       ULONG               CompletionFilter;
+       BOOLEAN             WatchTree;
+
+       BOOLEAN             bFcbAcquired = FALSE;
+
+       PUNICODE_STRING     FullName;
+
+    PAGED_CODE();
+
+       _SEH2_TRY
+       {
+               ASSERT(IrpContext);
+
+               ASSERT((IrpContext->Identifier.Type == FFSICX) &&
+                               (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
+
+               //
+               //  Always set the wait flag in the Irp context for the original request.
+               //
+
+               SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
+
+               DeviceObject = IrpContext->DeviceObject;
+
+               if (DeviceObject == FFSGlobal->DeviceObject)
+               {
+                       CompleteRequest = TRUE;
+                       Status = STATUS_INVALID_DEVICE_REQUEST;
+                       _SEH2_LEAVE;
+               }
+
+               Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;
+
+               ASSERT(Vcb != NULL);
+
+               ASSERT((Vcb->Identifier.Type == FFSVCB) &&
+                               (Vcb->Identifier.Size == sizeof(FFS_VCB)));
+
+               ASSERT(IsMounted(Vcb));
+
+               FileObject = IrpContext->FileObject;
+
+               Fcb = (PFFS_FCB)FileObject->FsContext;
+
+               ASSERT(Fcb);
+
+               if (Fcb->Identifier.Type == FFSVCB)
+               {
+                       FFSBreakPoint();
+                       CompleteRequest = TRUE;
+                       Status = STATUS_INVALID_PARAMETER;
+                       _SEH2_LEAVE;
+               }
+
+               ASSERT((Fcb->Identifier.Type == FFSFCB) &&
+                               (Fcb->Identifier.Size == sizeof(FFS_FCB)));
+
+               if (!IsDirectory(Fcb))
+               {
+                       FFSBreakPoint();
+                       CompleteRequest = TRUE;
+                       Status = STATUS_INVALID_PARAMETER;
+                       _SEH2_LEAVE;
+               }
+
+               if (ExAcquireResourceExclusiveLite(
+                                       &Fcb->MainResource,
+                                       TRUE))
+               {
+                       bFcbAcquired = TRUE;
+               }
+               else
+               {
+                       Status = STATUS_PENDING;
+                       _SEH2_LEAVE;
+               }
+
+               Irp = IrpContext->Irp;
+
+               IrpSp = IoGetCurrentIrpStackLocation(Irp);
+
+#if !defined(_GNU_NTIFS_) || defined(__REACTOS__)
+
+               CompletionFilter =
+                       IrpSp->Parameters.NotifyDirectory.CompletionFilter;
+
+#else // _GNU_NTIFS_
+
+               CompletionFilter = ((PEXTENDED_IO_STACK_LOCATION)
+                               IrpSp)->Parameters.NotifyDirectory.CompletionFilter;
+
+#endif // _GNU_NTIFS_
+
+               WatchTree = IsFlagOn(IrpSp->Flags, SL_WATCH_TREE);
+
+               if (FlagOn(Fcb->Flags, FCB_DELETE_PENDING))
+               {
+                       Status = STATUS_DELETE_PENDING;
+                       _SEH2_LEAVE;
+               }
+
+               FullName = &Fcb->LongName;
+
+               if (FullName->Buffer == NULL)
+               {
+                       if (!FFSGetFullFileName(Fcb->FFSMcb, FullName))
+                       {
+                               Status = STATUS_INSUFFICIENT_RESOURCES;
+                               _SEH2_LEAVE;
+                       }
+               }
+
+               FsRtlNotifyFullChangeDirectory(Vcb->NotifySync,
+                               &Vcb->NotifyList,
+                               FileObject->FsContext2,
+                               (PSTRING)FullName,
+                               WatchTree,
+                               FALSE,
+                               CompletionFilter,
+                               Irp,
+                               NULL,
+                               NULL);
+
+               CompleteRequest = FALSE;
+
+               Status = STATUS_PENDING;
+
+               /*
+                  Currently the driver is read-only but here is an example on how to use the
+                  FsRtl-functions to report a change:
+
+                  ANSI_STRING TestString;
+                  USHORT      FileNamePartLength;
+
+                  RtlInitAnsiString(&TestString, "\\ntifs.h");
+
+                  FileNamePartLength = 7;
+
+                  FsRtlNotifyReportChange(
+                  Vcb->NotifySync,            // PNOTIFY_SYNC NotifySync
+                  &Vcb->NotifyList,           // PLIST_ENTRY  NotifyList
+                  &TestString,                // PSTRING      FullTargetName
+                  &FileNamePartLength,        // PUSHORT      FileNamePartLength
+                  FILE_NOTIFY_CHANGE_NAME     // ULONG        FilterMatch
+                  );
+
+                  or
+
+                  ANSI_STRING TestString;
+
+                  RtlInitAnsiString(&TestString, "\\ntifs.h");
+
+                  FsRtlNotifyFullReportChange(
+                  Vcb->NotifySync,            // PNOTIFY_SYNC NotifySync
+                  &Vcb->NotifyList,           // PLIST_ENTRY  NotifyList
+                  &TestString,                // PSTRING      FullTargetName
+                  1,                          // USHORT       TargetNameOffset
+                  NULL,                       // PSTRING      StreamName OPTIONAL
+                  NULL,                       // PSTRING      NormalizedParentName OPTIONAL
+                  FILE_NOTIFY_CHANGE_NAME,    // ULONG        FilterMatch
+                  0,                          // ULONG        Action
+                  NULL                        // PVOID        TargetContext
+                  );
+                  */
+
+       }
+       _SEH2_FINALLY
+       {
+               if (bFcbAcquired)
+               {
+                       ExReleaseResourceForThreadLite(
+                                       &Fcb->MainResource,
+                                       ExGetCurrentResourceThread());
+               }
+
+               if (!IrpContext->ExceptionInProgress)
+               {
+                       if (!CompleteRequest)
+                       {
+                               IrpContext->Irp = NULL;
+                       }
+
+                       FFSCompleteIrpContext(IrpContext, Status);
+               }
+       } _SEH2_END;
+
+       return Status;
+}
+
+
+VOID
+FFSNotifyReportChange(
+       IN PFFS_IRP_CONTEXT  IrpContext,
+       IN PFFS_VCB          Vcb,
+       IN PFFS_FCB          Fcb,
+       IN ULONG             Filter,
+       IN ULONG             Action)
+{
+       PUNICODE_STRING FullName;
+       USHORT          Offset;
+
+       FullName = &Fcb->LongName;
+
+       // ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
+
+       if (FullName->Buffer == NULL)
+       {
+               if (!FFSGetFullFileName(Fcb->FFSMcb, FullName))
+               {
+                       /*Status = STATUS_INSUFFICIENT_RESOURCES;*/
+                       return;
+               }
+       }
+
+       Offset = (USHORT)(FullName->Length - 
+                       Fcb->FFSMcb->ShortName.Length);
+
+       FsRtlNotifyFullReportChange(Vcb->NotifySync,
+                       &(Vcb->NotifyList),
+                       (PSTRING)(FullName),
+                       (USHORT)Offset,
+                       (PSTRING)NULL,
+                       (PSTRING)NULL,
+                       (ULONG)Filter,
+                       (ULONG)Action,
+                       (PVOID)NULL);
+
+       // ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
+}
+
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSDirectoryControl(
+       IN PFFS_IRP_CONTEXT IrpContext)
+{
+       NTSTATUS Status;
+
+    PAGED_CODE();
+
+       ASSERT(IrpContext);
+
+       ASSERT((IrpContext->Identifier.Type == FFSICX) &&
+                       (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
+
+       switch (IrpContext->MinorFunction)
+       {
+               case IRP_MN_QUERY_DIRECTORY:
+                       Status = FFSQueryDirectory(IrpContext);
+                       break;
+
+               case IRP_MN_NOTIFY_CHANGE_DIRECTORY:
+                       Status = FFSNotifyChangeDirectory(IrpContext);
+                       break;
+
+               default:
+                       Status = STATUS_INVALID_DEVICE_REQUEST;
+                       FFSCompleteIrpContext(IrpContext, Status);
+       }
+
+       return Status;
+}
+
+
+BOOLEAN
+FFSIsDirectoryEmpty(
+       PFFS_VCB Vcb,
+       PFFS_FCB Dcb)
+{
+       NTSTATUS                Status = STATUS_UNSUCCESSFUL;
+
+       PFFS_DIR_ENTRY          pTarget = NULL;
+
+       ULONG                   dwBytes = 0;
+       ULONG                   dwRet;
+
+       BOOLEAN                 bRet = TRUE;
+
+    PAGED_CODE();
+
+       if (!IsFlagOn(Dcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY))
+               return TRUE;
+
+       _SEH2_TRY
+       {
+               pTarget = (PFFS_DIR_ENTRY)ExAllocatePoolWithTag(PagedPool,
+                               FFS_DIR_REC_LEN(FFS_NAME_LEN), FFS_POOL_TAG);
+               if (!pTarget)
+               {
+                       Status = STATUS_INSUFFICIENT_RESOURCES;
+                       _SEH2_LEAVE;
+               }
+
+               dwBytes = 0;
+
+
+               while ((LONGLONG)dwBytes < Dcb->Header.AllocationSize.QuadPart)
+               {
+                       RtlZeroMemory(pTarget, FFS_DIR_REC_LEN(FFS_NAME_LEN));
+
+                       if (FS_VERSION == 1)
+                       {
+                               Status = FFSv1ReadInode(
+                                               NULL,
+                                               Vcb,
+                                               Dcb->dinode1,
+                                               dwBytes,
+                                               (PVOID)pTarget,
+                                               FFS_DIR_REC_LEN(FFS_NAME_LEN),
+                                               &dwRet);
+                       }
+                       else
+                       {
+                               Status = FFSv2ReadInode(
+                                               NULL,
+                                               Vcb,
+                                               Dcb->dinode2,
+                                               dwBytes,
+                                               (PVOID)pTarget,
+                                               FFS_DIR_REC_LEN(FFS_NAME_LEN),
+                                               &dwRet);
+                       }
+
+                       if (!NT_SUCCESS(Status))
+                       {
+                               FFSPrint((DBG_ERROR, "FFSRemoveEntry: Reading Directory Content error.\n"));
+                               _SEH2_LEAVE;
+                       }
+
+                       if (pTarget->d_ino)
+                       {
+                               if (pTarget->d_namlen == 1 && pTarget->d_name[0] == '.')
+                               {
+                               }
+                               else if (pTarget->d_namlen == 2 && pTarget->d_name[0] == '.' && 
+                                               pTarget->d_name[1] == '.')
+                               {
+                               }
+                               else
+                               {
+                                       bRet = FALSE;
+                                       break;
+                               }
+                       }
+                       else
+                       {
+                               break;
+                       }
+
+                       dwBytes += pTarget->d_reclen;
+               }
+       }
+
+       _SEH2_FINALLY
+       {
+               if (pTarget != NULL)
+               {
+                       ExFreePool(pTarget);
+               }
+       } _SEH2_END;
+
+       return bRet;
+}
diff --git a/reactos/drivers/filesystems/ffs/src/dispatch.c b/reactos/drivers/filesystems/ffs/src/dispatch.c
new file mode 100644 (file)
index 0000000..0a8d048
--- /dev/null
@@ -0,0 +1,252 @@
+/* 
+ * FFS File System Driver for Windows
+ *
+ * dipatch.c
+ *
+ * 2004.5.6 ~
+ *
+ * Lee Jae-Hong, http://www.pyrasis.com
+ *
+ * See License.txt
+ *
+ */
+
+#include "ntifs.h"
+#include "ffsdrv.h"
+
+/* Globals */
+
+extern PFFS_GLOBAL FFSGlobal;
+
+
+/* Definitions */
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE, FFSQueueRequest)
+#pragma alloc_text(PAGE, FFSDeQueueRequest)
+#pragma alloc_text(PAGE, FFSDispatchRequest)
+#pragma alloc_text(PAGE, FFSBuildRequest)
+#endif
+
+
+NTSTATUS
+FFSQueueRequest(
+       IN PFFS_IRP_CONTEXT IrpContext)
+{
+    PAGED_CODE();
+
+       ASSERT(IrpContext);
+
+       ASSERT((IrpContext->Identifier.Type == FFSICX) &&
+                       (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
+
+       // IsSynchronous means we can block (so we don't requeue it)
+       IrpContext->IsSynchronous = TRUE;
+
+       SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED);
+
+       IoMarkIrpPending(IrpContext->Irp);
+
+       ExInitializeWorkItem(
+                       &IrpContext->WorkQueueItem,
+                       FFSDeQueueRequest,
+                       IrpContext);
+
+       ExQueueWorkItem(&IrpContext->WorkQueueItem, CriticalWorkQueue);
+
+       return STATUS_PENDING;
+}
+
+
+VOID NTAPI
+FFSDeQueueRequest(
+       IN PVOID Context)
+{
+       PFFS_IRP_CONTEXT IrpContext;
+
+    PAGED_CODE();
+
+       IrpContext = (PFFS_IRP_CONTEXT) Context;
+
+       ASSERT(IrpContext);
+
+       ASSERT((IrpContext->Identifier.Type == FFSICX) &&
+                       (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
+
+       _SEH2_TRY
+       {
+               _SEH2_TRY
+               {
+                       FsRtlEnterFileSystem();
+
+                       if (!IrpContext->IsTopLevel)
+                       {
+                               IoSetTopLevelIrp((PIRP) FSRTL_FSP_TOP_LEVEL_IRP);
+                       }
+
+                       FFSDispatchRequest(IrpContext);
+               }
+               _SEH2_EXCEPT (FFSExceptionFilter(IrpContext, _SEH2_GetExceptionInformation()))
+               {
+                       FFSExceptionHandler(IrpContext);
+               } _SEH2_END;
+       }
+       _SEH2_FINALLY
+       {
+               IoSetTopLevelIrp(NULL);
+
+               FsRtlExitFileSystem();
+       } _SEH2_END;
+}
+
+
+NTSTATUS
+FFSDispatchRequest(
+       IN PFFS_IRP_CONTEXT IrpContext)
+{
+    PAGED_CODE();
+
+       ASSERT(IrpContext);
+
+       ASSERT((IrpContext->Identifier.Type == FFSICX) &&
+                       (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
+
+       switch (IrpContext->MajorFunction)
+       {
+               case IRP_MJ_CREATE:
+                       return FFSCreate(IrpContext);
+
+               case IRP_MJ_CLOSE:
+                       return FFSClose(IrpContext);
+
+               case IRP_MJ_READ:
+                       return FFSRead(IrpContext);
+
+#if !FFS_READ_ONLY
+               case IRP_MJ_WRITE:
+                       return FFSWrite(IrpContext);
+#endif // !FFS_READ_ONLY
+
+               case IRP_MJ_FLUSH_BUFFERS:
+                       return FFSFlush(IrpContext);
+
+               case IRP_MJ_QUERY_INFORMATION:
+                       return FFSQueryInformation(IrpContext);
+
+               case IRP_MJ_SET_INFORMATION:
+                       return FFSSetInformation(IrpContext);
+
+               case IRP_MJ_QUERY_VOLUME_INFORMATION:
+                       return FFSQueryVolumeInformation(IrpContext);
+
+#if !FFS_READ_ONLY
+               case IRP_MJ_SET_VOLUME_INFORMATION:
+                       return FFSSetVolumeInformation(IrpContext);
+#endif // !FFS_READ_ONLY
+
+               case IRP_MJ_DIRECTORY_CONTROL:
+                       return FFSDirectoryControl(IrpContext);
+
+               case IRP_MJ_FILE_SYSTEM_CONTROL:
+                       return FFSFileSystemControl(IrpContext);
+
+               case IRP_MJ_DEVICE_CONTROL:
+                       return FFSDeviceControl(IrpContext);
+
+               case IRP_MJ_LOCK_CONTROL:
+                       return FFSLockControl(IrpContext);
+
+               case IRP_MJ_CLEANUP:
+                       return FFSCleanup(IrpContext);
+
+               case IRP_MJ_SHUTDOWN:
+                       return FFSShutDown(IrpContext);
+
+#if (_WIN32_WINNT >= 0x0500)
+               case IRP_MJ_PNP:
+                       return FFSPnp(IrpContext);
+#endif //(_WIN32_WINNT >= 0x0500)        
+               default:
+                       FFSPrint((DBG_ERROR, "FFSDispatchRequest: Unexpected major function: %xh\n",
+                                               IrpContext->MajorFunction));
+
+                       FFSCompleteIrpContext(IrpContext, STATUS_DRIVER_INTERNAL_ERROR);
+
+                       return STATUS_DRIVER_INTERNAL_ERROR;
+       }
+}
+
+
+NTSTATUS NTAPI
+FFSBuildRequest(
+       PDEVICE_OBJECT   DeviceObject,
+       PIRP             Irp)
+{
+       BOOLEAN             AtIrqlPassiveLevel = FALSE;
+       BOOLEAN             IsTopLevelIrp = FALSE;
+       PFFS_IRP_CONTEXT    IrpContext = NULL;
+       NTSTATUS            Status = STATUS_UNSUCCESSFUL;
+
+    PAGED_CODE();
+
+       _SEH2_TRY
+       {
+               _SEH2_TRY
+               {
+#if DBG
+                       FFSDbgPrintCall(DeviceObject, Irp);
+#endif
+
+                       AtIrqlPassiveLevel = (KeGetCurrentIrql() == PASSIVE_LEVEL);
+
+                       if (AtIrqlPassiveLevel)
+                       {
+                               FsRtlEnterFileSystem();
+                       }
+
+                       if (!IoGetTopLevelIrp())
+                       {
+                               IsTopLevelIrp = TRUE;
+                               IoSetTopLevelIrp(Irp);
+                       }
+
+                       IrpContext = FFSAllocateIrpContext(DeviceObject, Irp);
+
+                       if (!IrpContext)
+                       {
+                               Status = STATUS_INSUFFICIENT_RESOURCES;
+                               Irp->IoStatus.Status = Status;
+
+                               FFSCompleteRequest(Irp, TRUE, IO_NO_INCREMENT);
+                       }
+                       else
+                       {
+                               if ((IrpContext->MajorFunction == IRP_MJ_CREATE) &&
+                                               !AtIrqlPassiveLevel)
+                               {
+                                       FFSBreakPoint();
+                               }
+
+                               Status = FFSDispatchRequest(IrpContext);
+                       }
+               }
+               _SEH2_EXCEPT (FFSExceptionFilter(IrpContext, _SEH2_GetExceptionInformation()))
+               {
+                       Status = FFSExceptionHandler(IrpContext);
+               } _SEH2_END;
+       }
+       _SEH2_FINALLY
+       {
+               if (IsTopLevelIrp)
+               {
+                       IoSetTopLevelIrp(NULL);
+               }
+
+               if (AtIrqlPassiveLevel)
+               {
+                       FsRtlExitFileSystem();
+               }       
+       } _SEH2_END;
+
+       return Status;
+}
diff --git a/reactos/drivers/filesystems/ffs/src/except.c b/reactos/drivers/filesystems/ffs/src/except.c
new file mode 100644 (file)
index 0000000..167c217
--- /dev/null
@@ -0,0 +1,210 @@
+/* 
+ * FFS File System Driver for Windows
+ *
+ * except.c
+ *
+ * 2004.5.6 ~
+ *
+ * Lee Jae-Hong, http://www.pyrasis.com
+ *
+ * See License.txt
+ *
+ */
+
+#include "ntifs.h"
+#include "ffsdrv.h"
+
+/* Globals */
+
+extern PFFS_GLOBAL FFSGlobal;
+
+
+/* Definitions */
+
+#ifdef ALLOC_PRAGMA
+//#pragma alloc_text(PAGE, FFSExceptionFilter)
+//#pragma alloc_text(PAGE, FFSExceptionHandler)
+#endif
+
+
+NTSTATUS
+FFSExceptionFilter(
+       IN PFFS_IRP_CONTEXT    IrpContext,
+       IN PEXCEPTION_POINTERS ExceptionPointer)
+{
+       NTSTATUS Status, ExceptionCode;
+       PEXCEPTION_RECORD ExceptRecord;
+
+       ExceptRecord = ExceptionPointer->ExceptionRecord;
+
+       ExceptionCode = ExceptRecord->ExceptionCode;
+
+       FFSBreakPoint();
+
+       //
+       // Check IrpContext is valid or not
+       //
+
+       if (IrpContext)
+       {
+               if ((IrpContext->Identifier.Type != FFSICX) ||
+                               (IrpContext->Identifier.Size != sizeof(FFS_IRP_CONTEXT)))
+               {
+                       IrpContext = NULL;
+               }
+       }
+       else
+       {
+               if (FsRtlIsNtstatusExpected(ExceptionCode))
+               {
+                       return EXCEPTION_EXECUTE_HANDLER;
+               }
+               else
+               {
+                       FFSBugCheck(FFS_BUGCHK_EXCEPT, (ULONG_PTR)ExceptRecord,
+                                       (ULONG_PTR)ExceptionPointer->ContextRecord,
+                                       (ULONG_PTR)ExceptRecord->ExceptionAddress);
+               }
+       }
+
+       //
+       //  For the purposes of processing this exception, let's mark this
+       //  request as being able to wait, and neither write through nor on
+       //  removable media if we aren't posting it.
+       //
+
+       SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
+
+       if (FsRtlIsNtstatusExpected(ExceptionCode))
+       {
+               //
+               // If the exception is expected execute our handler
+               //
+
+               FFSPrint((DBG_ERROR, "FFSExceptionFilter: Catching exception %xh\n",
+                                       ExceptionCode));
+
+               Status = EXCEPTION_EXECUTE_HANDLER;
+
+               if (IrpContext)
+               {
+                       IrpContext->ExceptionInProgress = TRUE;
+                       IrpContext->ExceptionCode = ExceptionCode;
+               }
+       }
+       else
+       {
+               //
+               // Continue search for an higher level exception handler
+               //
+
+               FFSPrint((DBG_ERROR, "FFSExceptionFilter: Passing on exception %#x\n",
+                                       ExceptionCode));
+
+               Status = EXCEPTION_CONTINUE_SEARCH;
+
+               if (IrpContext)
+               {
+                       FFSFreeIrpContext(IrpContext);
+               }
+       }
+
+       return Status;
+}
+
+
+NTSTATUS
+FFSExceptionHandler(
+       IN PFFS_IRP_CONTEXT IrpContext)
+{
+       NTSTATUS Status;
+
+       FFSBreakPoint();
+
+       if (IrpContext)
+       {
+               if ((IrpContext->Identifier.Type != FFSICX) || 
+                               (IrpContext->Identifier.Size != sizeof(FFS_IRP_CONTEXT)))
+               {
+                       FFSBreakPoint();
+                       return STATUS_UNSUCCESSFUL;
+               }
+
+               Status = IrpContext->ExceptionCode;
+
+               if (IrpContext->Irp)
+               {
+                       //
+                       // Check if this error is a result of user actions
+                       //
+
+                       PIRP Irp = IrpContext->Irp;
+
+
+                       if (IoIsErrorUserInduced(Status))
+                       {
+                               //
+                               //  Now we will generate a pop-up to user
+                               //
+
+                               PDEVICE_OBJECT RealDevice;
+                               PVPB           Vpb = NULL;
+                               PETHREAD       Thread;
+
+                               if (IoGetCurrentIrpStackLocation(Irp)->FileObject != NULL)
+                               {
+                                       Vpb = IoGetCurrentIrpStackLocation(Irp)->FileObject->Vpb;
+                               }
+
+                               //
+                               // Get the initial thread
+                               //
+
+                               Thread = Irp->Tail.Overlay.Thread;
+                               RealDevice = IoGetDeviceToVerify(Thread);
+
+                               if (RealDevice == NULL)
+                               {
+                                       //
+                                       // Get current thread
+                                       //
+
+                                       Thread = PsGetCurrentThread();
+                                       RealDevice = IoGetDeviceToVerify(Thread);
+
+                                       ASSERT(RealDevice != NULL);
+                               }
+
+                               if (RealDevice != NULL)
+                               {
+                                       //
+                                       //  Now we pop-up the error dialog ...
+                                       //
+
+                                       IoMarkIrpPending(Irp);
+                                       IoRaiseHardError(Irp, Vpb, RealDevice);
+
+                                       IoSetDeviceToVerify(Thread, NULL);
+
+                                       Status =  STATUS_PENDING;
+                                       goto errorout;
+                               }
+                       }
+
+                       IrpContext->Irp->IoStatus.Status = Status;
+
+                       FFSCompleteRequest(IrpContext->Irp, FALSE, IO_NO_INCREMENT);
+               }
+
+errorout:
+
+               FFSFreeIrpContext(IrpContext);
+       }
+       else
+       {
+               Status = STATUS_INSUFFICIENT_RESOURCES;
+       }
+
+       return Status;
+}
+
diff --git a/reactos/drivers/filesystems/ffs/src/fastio.c b/reactos/drivers/filesystems/ffs/src/fastio.c
new file mode 100644 (file)
index 0000000..06c4269
--- /dev/null
@@ -0,0 +1,1146 @@
+/* 
+ * FFS File System Driver for Windows
+ *
+ * fastio.c
+ *
+ * 2004.5.6 ~
+ *
+ * Lee Jae-Hong, http://www.pyrasis.com
+ *
+ * See License.txt
+ *
+ */
+
+#include "ntifs.h"
+#include "ffsdrv.h"
+
+/* Globals */
+
+extern PFFS_GLOBAL FFSGlobal;
+
+
+/* Definitions */
+
+#ifdef ALLOC_PRAGMA
+#if DBG
+#pragma alloc_text(PAGE, FFSFastIoRead)
+#pragma alloc_text(PAGE, FFSFastIoWrite)
+#endif
+#pragma alloc_text(PAGE, FFSFastIoCheckIfPossible)
+#pragma alloc_text(PAGE, FFSFastIoQueryBasicInfo)
+#pragma alloc_text(PAGE, FFSFastIoQueryStandardInfo)
+#pragma alloc_text(PAGE, FFSFastIoQueryNetworkOpenInfo)
+#pragma alloc_text(PAGE, FFSFastIoLock)
+#pragma alloc_text(PAGE, FFSFastIoUnlockSingle)
+#pragma alloc_text(PAGE, FFSFastIoUnlockAll)
+#pragma alloc_text(PAGE, FFSFastIoUnlockAllByKey)
+#endif
+
+
+BOOLEAN NTAPI
+FFSFastIoCheckIfPossible(
+       IN PFILE_OBJECT         FileObject,
+       IN PLARGE_INTEGER       FileOffset,
+       IN ULONG                Length,
+       IN BOOLEAN              Wait,
+       IN ULONG                LockKey,
+       IN BOOLEAN              CheckForReadOperation,
+       OUT PIO_STATUS_BLOCK    IoStatus,
+       IN PDEVICE_OBJECT       DeviceObject)
+{
+       BOOLEAN          bPossible = FALSE;
+       PFFS_FCB         Fcb;
+       LARGE_INTEGER    lLength;
+
+    PAGED_CODE();
+
+       lLength.QuadPart = Length;
+
+       _SEH2_TRY
+       {
+               _SEH2_TRY
+               {
+            FsRtlEnterFileSystem();
+
+                       if (DeviceObject == FFSGlobal->DeviceObject)
+                       {
+                               bPossible = FastIoIsNotPossible;
+                               _SEH2_LEAVE;
+                       }
+
+                       Fcb = (PFFS_FCB)FileObject->FsContext;
+
+                       ASSERT(Fcb != NULL);
+
+                       if (Fcb->Identifier.Type == FFSVCB)
+                       {
+                               bPossible = FastIoIsNotPossible;
+                               _SEH2_LEAVE;
+                       }
+
+                       ASSERT((Fcb->Identifier.Type == FFSFCB) &&
+                                       (Fcb->Identifier.Size == sizeof(FFS_FCB)));
+
+                       if (IsDirectory(Fcb))
+                       {
+                               bPossible = FALSE;
+                               _SEH2_LEAVE;
+                       }
+
+                       if (CheckForReadOperation)
+                       {
+                               bPossible = FsRtlFastCheckLockForRead(
+                                                               &Fcb->FileLockAnchor,
+                                                               FileOffset,
+                                                               &lLength,
+                                                               LockKey,
+                                                               FileObject,
+                                                               PsGetCurrentProcess());
+
+                               if (!bPossible)
+                                       bPossible = FastIoIsQuestionable;
+                       }
+                       else
+                       {
+                               if (IsFlagOn(Fcb->Vcb->Flags, VCB_READ_ONLY) ||
+                                               IsFlagOn(Fcb->Vcb->Flags, VCB_WRITE_PROTECTED))
+                               {
+                                       bPossible = FastIoIsNotPossible;
+                               }
+                               else
+                               {
+                                       bPossible = FsRtlFastCheckLockForWrite(
+                                                                       &Fcb->FileLockAnchor,
+                                                                       FileOffset,
+                                                                       &lLength,
+                                                                       LockKey,
+                                                                       FileObject,
+                                                                       PsGetCurrentProcess());
+
+                                       if (!bPossible)
+                                               bPossible = FastIoIsQuestionable;
+                               }
+                       }
+
+                       FFSPrint((DBG_INFO, "FFSFastIIOCheckPossible: %s %s %s\n",
+                                               FFSGetCurrentProcessName(),
+                                               "FASTIO_CHECK_IF_POSSIBLE",
+                                               Fcb->AnsiFileName.Buffer));
+
+                       FFSPrint((DBG_INFO, 
+                                               "FFSFastIIOCheckPossible: Offset: %I64xg Length: %xh Key: %u %s %s\n",
+                                               FileOffset->QuadPart,
+                                               Length,
+                                               LockKey,
+                                               (CheckForReadOperation ? "CheckForReadOperation:" :
+                                                "CheckForWriteOperation:"),
+                                               (bPossible ? "Succeeded" : "Failed")));
+               }
+               _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER)
+               {
+                       bPossible = FastIoIsNotPossible;
+               } _SEH2_END;
+       }
+       _SEH2_FINALLY
+       {
+               FsRtlExitFileSystem();
+       } _SEH2_END;
+
+       return bPossible;
+}
+
+
+#if DBG
+
+BOOLEAN NTAPI
+FFSFastIoRead(
+       IN PFILE_OBJECT         FileObject,
+       IN PLARGE_INTEGER       FileOffset,
+       IN ULONG                Length,
+       IN BOOLEAN              Wait,
+       IN ULONG                LockKey,
+       OUT PVOID               Buffer,
+       OUT PIO_STATUS_BLOCK    IoStatus,
+       IN PDEVICE_OBJECT       DeviceObject)
+{
+       BOOLEAN     Status;
+       PFFS_FCB    Fcb;
+
+    PAGED_CODE();
+
+       Fcb = (PFFS_FCB)FileObject->FsContext;
+
+       ASSERT(Fcb != NULL);
+
+       ASSERT((Fcb->Identifier.Type == FFSFCB) &&
+                       (Fcb->Identifier.Size == sizeof(FFS_FCB)));
+
+       FFSPrint((DBG_INFO, "FFSFastIoRead: %s %s %s\n",
+                               FFSGetCurrentProcessName(),
+                               "FASTIO_READ",
+                               Fcb->AnsiFileName.Buffer));
+
+       FFSPrint((DBG_INFO, "FFSFastIoRead: Offset: %I64xh Length: %xh Key: %u\n",
+                               FileOffset->QuadPart,
+                               Length,
+                               LockKey));
+
+       Status = FsRtlCopyRead(
+                       FileObject, FileOffset, Length, Wait,
+                       LockKey, Buffer, IoStatus, DeviceObject);
+
+       return Status;
+}
+
+#if !FFS_READ_ONLY
+
+BOOLEAN NTAPI
+FFSFastIoWrite(
+       IN PFILE_OBJECT         FileObject,
+       IN PLARGE_INTEGER       FileOffset,
+       IN ULONG                Length,
+       IN BOOLEAN              Wait,
+       IN ULONG                LockKey,
+       OUT PVOID               Buffer,
+       OUT PIO_STATUS_BLOCK    IoStatus,
+       IN PDEVICE_OBJECT       DeviceObject)
+{
+       BOOLEAN      bRet;
+       PFFS_FCB     Fcb;
+
+    PAGED_CODE();
+
+       Fcb = (PFFS_FCB)FileObject->FsContext;
+
+       ASSERT(Fcb != NULL);
+
+       ASSERT((Fcb->Identifier.Type == FFSFCB) &&
+                       (Fcb->Identifier.Size == sizeof(FFS_FCB)));
+
+       FFSPrint((DBG_INFO,
+                               "FFSFastIoWrite: %s %s %s\n",
+                               FFSGetCurrentProcessName(),
+                               "FASTIO_WRITE",
+                               Fcb->AnsiFileName.Buffer));
+
+       FFSPrint((DBG_INFO,
+                               "FFSFastIoWrite: Offset: %I64xh Length: %xh Key: %xh\n",
+                               FileOffset->QuadPart,
+                               Length,
+                               LockKey));
+
+       if (IsFlagOn(Fcb->Vcb->Flags, VCB_READ_ONLY))
+       {
+               FFSBreakPoint();
+               return FALSE;
+       }
+
+       bRet = FsRtlCopyWrite(
+                       FileObject, FileOffset, Length, Wait,
+                       LockKey, Buffer, IoStatus, DeviceObject);
+
+       return bRet;
+}
+
+#endif // !FFS_READ_ONLY
+
+#endif /* DBG */
+
+
+__drv_mustHoldCriticalRegion
+BOOLEAN NTAPI
+FFSFastIoQueryBasicInfo(
+       IN PFILE_OBJECT             FileObject,
+       IN BOOLEAN                  Wait,
+       OUT PFILE_BASIC_INFORMATION Buffer,
+       OUT PIO_STATUS_BLOCK        IoStatus,
+       IN PDEVICE_OBJECT           DeviceObject)
+{
+       BOOLEAN     Status = FALSE;
+       PFFS_VCB    Vcb;
+       PFFS_FCB    Fcb = 0;
+       BOOLEAN     FcbMainResourceAcquired = FALSE;
+
+    PAGED_CODE();
+
+       _SEH2_TRY
+       {
+               _SEH2_TRY
+               {
+            FsRtlEnterFileSystem();
+
+                       if (DeviceObject == FFSGlobal->DeviceObject)
+                       {
+                               IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST;
+                               Status = TRUE;
+                               _SEH2_LEAVE;
+                       }
+
+                       Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;
+
+                       ASSERT(Vcb != NULL);
+
+                       Fcb = (PFFS_FCB)FileObject->FsContext;
+
+                       ASSERT(Fcb != NULL);
+
+                       if (Fcb->Identifier.Type == FFSVCB)
+                       {
+                               IoStatus->Status = STATUS_INVALID_PARAMETER;
+                               Status = TRUE;
+                               _SEH2_LEAVE;
+                       }
+
+                       ASSERT((Fcb->Identifier.Type == FFSFCB) &&
+                                       (Fcb->Identifier.Size == sizeof(FFS_FCB)));
+
+                       FFSPrint((DBG_INFO, 
+                                               "FFSFastIoQueryBasicInfo: %s %s %s\n",
+                                               FFSGetCurrentProcessName(),
+                                               "FASTIO_QUERY_BASIC_INFO",
+                                               Fcb->AnsiFileName.Buffer));
+
+                       if (!ExAcquireResourceSharedLite(
+                                               &Fcb->MainResource,
+                                               Wait))
+                       {
+                               Status = FALSE;
+                               _SEH2_LEAVE;
+                       }
+
+                       FcbMainResourceAcquired = TRUE;
+
+                       RtlZeroMemory(Buffer, sizeof(FILE_BASIC_INFORMATION));
+
+                       /*
+                          typedef struct _FILE_BASIC_INFORMATION {
+                          LARGE_INTEGER   CreationTime;
+                          LARGE_INTEGER   LastAccessTime;
+                          LARGE_INTEGER   LastWriteTime;
+                          LARGE_INTEGER   ChangeTime;
+                          ULONG           FileAttributes;
+                          } FILE_BASIC_INFORMATION, *PFILE_BASIC_INFORMATION;
+                          */
+
+                       if (FS_VERSION == 1)
+                       {
+                               Buffer->CreationTime = FFSSysTime(Fcb->dinode1->di_ctime);
+                               Buffer->LastAccessTime = FFSSysTime(Fcb->dinode1->di_atime);
+                               Buffer->LastWriteTime = FFSSysTime(Fcb->dinode1->di_mtime);
+                               Buffer->ChangeTime = FFSSysTime(Fcb->dinode1->di_mtime);
+                       }
+                       else
+                       {
+                               Buffer->CreationTime = FFSSysTime((ULONG)Fcb->dinode2->di_ctime);
+                               Buffer->LastAccessTime = FFSSysTime((ULONG)Fcb->dinode2->di_atime);
+                               Buffer->LastWriteTime = FFSSysTime((ULONG)Fcb->dinode2->di_mtime);
+                               Buffer->ChangeTime = FFSSysTime((ULONG)Fcb->dinode2->di_mtime);
+                       }
+
+
+                       Buffer->FileAttributes = Fcb->FFSMcb->FileAttr;
+
+                       IoStatus->Information = sizeof(FILE_BASIC_INFORMATION);
+
+                       IoStatus->Status = STATUS_SUCCESS;
+
+                       Status =  TRUE;
+               }
+               _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER)
+               {
+                       IoStatus->Status = _SEH2_GetExceptionCode();
+                       Status = TRUE;
+               } _SEH2_END;
+       }
+
+       _SEH2_FINALLY
+       {
+               if (FcbMainResourceAcquired)
+               {
+                       ExReleaseResourceForThreadLite(
+                                       &Fcb->MainResource,
+                                       ExGetCurrentResourceThread());
+               }
+
+               FsRtlExitFileSystem();
+       } _SEH2_END;
+
+
+       if (Status == FALSE)
+       {
+               FFSPrint((DBG_ERROR, 
+                                       "FFSFastIoQueryBasicInfo: %s %s *** Status: FALSE ***\n",
+                                       FFSGetCurrentProcessName(),
+                                       "FASTIO_QUERY_BASIC_INFO"));
+       }
+       else if (IoStatus->Status != STATUS_SUCCESS)
+       {
+               FFSPrint((DBG_ERROR, 
+                                       "FFSFastIoQueryBasicInfo: %s %s *** Status: %s (%#x) ***\n",
+                                       FFSFastIoQueryBasicInfo,
+                                       "FASTIO_QUERY_BASIC_INFO",
+                                       FFSNtStatusToString(IoStatus->Status),
+                                       IoStatus->Status));
+       }
+
+       return Status;
+}
+
+
+__drv_mustHoldCriticalRegion
+BOOLEAN NTAPI
+FFSFastIoQueryStandardInfo(
+       IN PFILE_OBJECT                 FileObject,
+       IN BOOLEAN                      Wait,
+       OUT PFILE_STANDARD_INFORMATION  Buffer,
+       OUT PIO_STATUS_BLOCK            IoStatus,
+       IN PDEVICE_OBJECT               DeviceObject)
+{
+
+       BOOLEAN     Status = FALSE;
+       PFFS_VCB    Vcb;
+       PFFS_FCB    Fcb = 0;
+       BOOLEAN     FcbMainResourceAcquired = FALSE;
+
+    PAGED_CODE();
+
+       _SEH2_TRY
+       {
+               _SEH2_TRY
+               {
+            FsRtlEnterFileSystem();
+
+                       if (DeviceObject == FFSGlobal->DeviceObject)
+                       {
+                               IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST;
+                               Status = TRUE;
+                               _SEH2_LEAVE;
+                       }
+
+                       Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;
+
+                       ASSERT(Vcb != NULL);
+
+                       Fcb = (PFFS_FCB)FileObject->FsContext;
+
+                       ASSERT(Fcb != NULL);
+
+                       if (Fcb->Identifier.Type == FFSVCB)
+                       {
+                               IoStatus->Status = STATUS_INVALID_PARAMETER;
+                               Status = TRUE;
+                               _SEH2_LEAVE;
+                       }
+
+                       ASSERT((Fcb->Identifier.Type == FFSFCB) &&
+                                       (Fcb->Identifier.Size == sizeof(FFS_FCB)));
+
+                       FFSPrint((DBG_INFO,
+                                               "FFSFastIoQueryStandardInfo: %s %s %s\n",
+                                               FFSGetCurrentProcessName(),
+                                               "FASTIO_QUERY_STANDARD_INFO",
+                                               Fcb->AnsiFileName.Buffer));
+
+                       if (!ExAcquireResourceSharedLite(
+                                               &Fcb->MainResource,
+                                               Wait))
+                       {
+                               Status = FALSE;
+                               _SEH2_LEAVE;
+                       }
+
+                       FcbMainResourceAcquired = TRUE;
+
+                       RtlZeroMemory(Buffer, sizeof(FILE_STANDARD_INFORMATION));
+
+                       /*
+                          typedef struct _FILE_STANDARD_INFORMATION {
+                          LARGE_INTEGER   AllocationSize;
+                          LARGE_INTEGER   EndOfFile;
+                          ULONG           NumberOfLinks;
+                          BOOLEAN         DeletePending;
+                          BOOLEAN         Directory;
+                          } FILE_STANDARD_INFORMATION, *PFILE_STANDARD_INFORMATION;
+                          */
+
+                       if (FS_VERSION == 1)
+                       {
+                               Buffer->AllocationSize.QuadPart =
+                                       (LONGLONG)(Fcb->dinode1->di_size);
+
+                               Buffer->EndOfFile.QuadPart =
+                                       (LONGLONG)(Fcb->dinode1->di_size);
+
+                               Buffer->NumberOfLinks = Fcb->dinode1->di_nlink;
+                       }
+                       else
+                       {
+                               Buffer->AllocationSize.QuadPart =
+                                       (LONGLONG)(Fcb->dinode2->di_size);
+
+                               Buffer->EndOfFile.QuadPart =
+                                       (LONGLONG)(Fcb->dinode2->di_size);
+
+                               Buffer->NumberOfLinks = Fcb->dinode2->di_nlink;
+                       }
+
+
+                       if (IsFlagOn(Fcb->Vcb->Flags, VCB_READ_ONLY))
+                       {
+                               Buffer->DeletePending = FALSE;
+                       }
+                       else
+                       {
+                               Buffer->DeletePending = IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING);
+                       }
+
+                       if (FlagOn(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY))
+                       {
+                               Buffer->Directory = TRUE;
+                       }
+                       else
+                       {
+                               Buffer->Directory = FALSE;
+                       }
+
+                       IoStatus->Information = sizeof(FILE_STANDARD_INFORMATION);
+
+                       IoStatus->Status = STATUS_SUCCESS;
+
+                       Status =  TRUE;
+               }
+               _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER)
+               {
+                       IoStatus->Status = _SEH2_GetExceptionCode();
+                       Status = TRUE;
+               } _SEH2_END;
+       }
+
+       _SEH2_FINALLY
+       {
+               if (FcbMainResourceAcquired)
+               {
+                       ExReleaseResourceForThreadLite(
+                                       &Fcb->MainResource,
+                                       ExGetCurrentResourceThread()
+                                       );
+               }
+
+               FsRtlExitFileSystem();
+       } _SEH2_END;
+
+#if DBG
+       if (Status == FALSE)
+       {
+               FFSPrint((DBG_INFO,
+                                       "FFSFastIoQueryStandardInfo: %s %s *** Status: FALSE ***\n",
+                                       FFSGetCurrentProcessName(),
+                                       "FASTIO_QUERY_STANDARD_INFO"));
+       }
+       else if (IoStatus->Status != STATUS_SUCCESS)
+       {
+               FFSPrint((DBG_INFO,
+                                       "FFSFastIoQueryStandardInfo: %s %s *** Status: %s (%#x) ***\n",
+                                       FFSGetCurrentProcessName(),
+                                       "FASTIO_QUERY_STANDARD_INFO",
+                                       FFSNtStatusToString(IoStatus->Status),
+                                       IoStatus->Status));
+       }
+#endif
+
+       return Status;
+}
+
+
+__drv_mustHoldCriticalRegion
+BOOLEAN NTAPI
+FFSFastIoQueryNetworkOpenInfo(
+       IN PFILE_OBJECT                     FileObject,
+       IN BOOLEAN                          Wait,
+       OUT PFILE_NETWORK_OPEN_INFORMATION  Buffer,
+       OUT PIO_STATUS_BLOCK                IoStatus,
+       IN PDEVICE_OBJECT                   DeviceObject)
+{
+       BOOLEAN     Status = FALSE;
+       PFFS_VCB    Vcb;
+       PFFS_FCB    Fcb = 0;
+       BOOLEAN     FcbMainResourceAcquired = FALSE;
+
+    PAGED_CODE();
+
+       _SEH2_TRY
+       {
+               _SEH2_TRY
+               {
+            FsRtlEnterFileSystem();
+
+                       if (DeviceObject == FFSGlobal->DeviceObject)
+                       {
+                               IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST;
+                               Status = TRUE;
+                               _SEH2_LEAVE;
+                       }
+
+                       Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;
+
+                       ASSERT(Vcb != NULL);
+
+                       Fcb = (PFFS_FCB)FileObject->FsContext;
+
+                       ASSERT(Fcb != NULL);
+
+                       if (Fcb->Identifier.Type == FFSVCB)
+                       {
+                               IoStatus->Status = STATUS_INVALID_PARAMETER;
+                               Status = TRUE;
+                               _SEH2_LEAVE;
+                       }
+
+                       ASSERT((Fcb->Identifier.Type == FFSFCB) &&
+                                       (Fcb->Identifier.Size == sizeof(FFS_FCB)));
+
+                       FFSPrint((DBG_INFO, 
+                                               "%-16.16s %-31s %s\n",
+                                               FFSGetCurrentProcessName(),
+                                               "FASTIO_QUERY_NETWORK_OPEN_INFO",
+                                               Fcb->AnsiFileName.Buffer));
+
+                       if (!ExAcquireResourceSharedLite(
+                                               &Fcb->MainResource,
+                                               Wait))
+                       {
+                               Status = FALSE;
+                               _SEH2_LEAVE;
+                       }
+
+                       FcbMainResourceAcquired = TRUE;
+
+                       RtlZeroMemory(Buffer, sizeof(FILE_NETWORK_OPEN_INFORMATION));
+
+                       /*
+                       typedef struct _FILE_NETWORK_OPEN_INFORMATION {
+                               LARGE_INTEGER   CreationTime;
+                               LARGE_INTEGER   LastAccessTime;
+                               LARGE_INTEGER   LastWriteTime;
+                               LARGE_INTEGER   ChangeTime;
+                               LARGE_INTEGER   AllocationSize;
+                               LARGE_INTEGER   EndOfFile;
+                               ULONG           FileAttributes;
+                       } FILE_NETWORK_OPEN_INFORMATION, *PFILE_NETWORK_OPEN_INFORMATION;
+                       */
+
+                       if (FS_VERSION == 1)
+                       {
+                               Buffer->CreationTime = FFSSysTime(Fcb->dinode1->di_ctime);
+                               Buffer->LastAccessTime = FFSSysTime(Fcb->dinode1->di_atime);
+                               Buffer->LastWriteTime = FFSSysTime(Fcb->dinode1->di_mtime);
+                               Buffer->ChangeTime = FFSSysTime(Fcb->dinode1->di_mtime);
+                               Buffer->FileAttributes = Fcb->FFSMcb->FileAttr;
+                               Buffer->AllocationSize.QuadPart =
+                                       (LONGLONG)(Fcb->dinode1->di_size);
+                               Buffer->EndOfFile.QuadPart =
+                                       (LONGLONG)(Fcb->dinode1->di_size);
+                       }
+                       else
+                       {
+                               Buffer->CreationTime = FFSSysTime((ULONG)Fcb->dinode2->di_ctime);
+                               Buffer->LastAccessTime = FFSSysTime((ULONG)Fcb->dinode2->di_atime);
+                               Buffer->LastWriteTime = FFSSysTime((ULONG)Fcb->dinode2->di_mtime);
+                               Buffer->ChangeTime = FFSSysTime((ULONG)Fcb->dinode2->di_mtime);
+                               Buffer->FileAttributes = Fcb->FFSMcb->FileAttr;
+                               Buffer->AllocationSize.QuadPart =
+                                       (LONGLONG)(Fcb->dinode2->di_size);
+                               Buffer->EndOfFile.QuadPart =
+                                       (LONGLONG)(Fcb->dinode2->di_size);
+                       }
+
+                       Buffer->FileAttributes = Fcb->FFSMcb->FileAttr;
+
+                       IoStatus->Information = sizeof(FILE_NETWORK_OPEN_INFORMATION);
+
+                       IoStatus->Status = STATUS_SUCCESS;
+
+                       Status = TRUE;
+               }
+               _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER)
+               {
+                       IoStatus->Status = _SEH2_GetExceptionCode();
+                       Status = TRUE;
+               } _SEH2_END;
+       }
+       _SEH2_FINALLY
+       {
+               if (FcbMainResourceAcquired)
+               {
+                       ExReleaseResourceForThreadLite(
+                                       &Fcb->MainResource,
+                                       ExGetCurrentResourceThread()
+                                       );
+               }
+
+               FsRtlExitFileSystem();
+       } _SEH2_END;
+
+
+
+       if (Status == FALSE)
+       {
+               FFSPrint((DBG_ERROR,
+                                       "%s %s *** Status: FALSE ***\n",
+                                       FFSGetCurrentProcessName(),
+                                       "FASTIO_QUERY_NETWORK_OPEN_INFO"));
+       }
+       else if (IoStatus->Status != STATUS_SUCCESS)
+       {
+               FFSPrint((DBG_ERROR,
+                                       "%s %s *** Status: %s (%#x) ***\n",
+                                       FFSGetCurrentProcessName(),
+                                       "FASTIO_QUERY_NETWORK_OPEN_INFO",
+                                       FFSNtStatusToString(IoStatus->Status),
+                                       IoStatus->Status));
+       }
+
+       return Status;
+}
+
+
+BOOLEAN NTAPI
+FFSFastIoLock(
+       IN PFILE_OBJECT         FileObject,
+       IN PLARGE_INTEGER       FileOffset,
+       IN PLARGE_INTEGER       Length,
+       IN PEPROCESS            Process,
+       IN ULONG                Key,
+       IN BOOLEAN              FailImmediately,
+       IN BOOLEAN              ExclusiveLock,
+       OUT PIO_STATUS_BLOCK    IoStatus,
+       IN PDEVICE_OBJECT       DeviceObject)
+{
+       BOOLEAN     Status = FALSE;
+       PFFS_FCB    Fcb;
+
+    PAGED_CODE();
+
+       _SEH2_TRY
+       {
+               _SEH2_TRY
+               {
+            FsRtlEnterFileSystem();
+
+                       if (DeviceObject == FFSGlobal->DeviceObject)
+                       {
+                               IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST;
+                               Status = TRUE;
+                               _SEH2_LEAVE;
+                       }
+
+                       Fcb = (PFFS_FCB)FileObject->FsContext;
+
+                       ASSERT(Fcb != NULL);
+
+                       if (Fcb->Identifier.Type == FFSVCB)
+                       {
+                               IoStatus->Status = STATUS_INVALID_PARAMETER;
+                               Status = TRUE;
+                               _SEH2_LEAVE;
+                       }
+
+                       ASSERT((Fcb->Identifier.Type == FFSFCB) &&
+                                       (Fcb->Identifier.Size == sizeof(FFS_FCB)));
+
+                       if (IsDirectory(Fcb))
+                       {
+                               FFSBreakPoint();
+                               IoStatus->Status = STATUS_INVALID_PARAMETER;
+                               Status = TRUE;
+                               _SEH2_LEAVE;
+                       }
+
+                       FFSPrint((DBG_INFO,
+                                               "FFSFastIoLock: %s %s %s\n",
+                                               FFSGetCurrentProcessName(),
+                                               "FASTIO_LOCK",
+                                               Fcb->AnsiFileName.Buffer));
+
+                       FFSPrint((DBG_INFO,
+                                               "FFSFastIoLock: Offset: %I64xh Length: %I64xh Key: %u %s%s\n",
+                                               FileOffset->QuadPart,
+                                               Length->QuadPart,
+                                               Key,
+                                               (FailImmediately ? "FailImmediately " : ""),
+                                               (ExclusiveLock ? "ExclusiveLock " : "")));
+
+                       if (Fcb->Header.IsFastIoPossible != FastIoIsQuestionable)
+                       {
+                               FFSPrint((DBG_INFO,
+                                                       "FFSFastIoLock: %s %s %s\n",
+                                                       (PUCHAR) Process + ProcessNameOffset,
+                                                       "FastIoIsQuestionable",
+                                                       Fcb->AnsiFileName.Buffer));
+
+                               Fcb->Header.IsFastIoPossible = FastIoIsQuestionable;
+                       }
+#ifdef _MSC_VER
+#pragma prefast( suppress: 28159, "bug in prefast" )
+#endif
+                       Status = FsRtlFastLock(
+                                               &Fcb->FileLockAnchor,
+                                               FileObject,
+                                               FileOffset,
+                                               Length,
+                                               Process,
+                                               Key,
+                                               FailImmediately,
+                                               ExclusiveLock,
+                                               IoStatus,
+                                               NULL,
+                                               FALSE);
+               }
+               _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER)
+               {
+                       IoStatus->Status = _SEH2_GetExceptionCode();
+                       Status = TRUE;
+               } _SEH2_END;
+       }
+
+       _SEH2_FINALLY
+       {
+               FsRtlExitFileSystem();
+       } _SEH2_END;
+
+#if DBG 
+       if (Status == FALSE)
+       {
+               FFSPrint((DBG_ERROR, 
+                                       "FFSFastIoLock: %s %s *** Status: FALSE ***\n",
+                                       (PUCHAR) Process + ProcessNameOffset,
+                                       "FASTIO_LOCK"));
+       }
+       else if (IoStatus->Status != STATUS_SUCCESS)
+       {
+               FFSPrint((DBG_ERROR,
+                                       "FFSFastIoLock: %s %s *** Status: %s (%#x) ***\n",
+                                       (PUCHAR) Process + ProcessNameOffset,
+                                       "FASTIO_LOCK",
+                                       FFSNtStatusToString(IoStatus->Status),
+                                       IoStatus->Status));
+       }
+#endif
+
+       return Status;
+}
+
+
+BOOLEAN NTAPI
+FFSFastIoUnlockSingle(
+       IN PFILE_OBJECT         FileObject,
+       IN PLARGE_INTEGER       FileOffset,
+       IN PLARGE_INTEGER       Length,
+       IN PEPROCESS            Process,
+       IN ULONG                Key,
+       OUT PIO_STATUS_BLOCK    IoStatus,
+       IN PDEVICE_OBJECT       DeviceObject)
+{
+       BOOLEAN     Status = FALSE;
+       PFFS_FCB    Fcb;
+
+    PAGED_CODE();
+
+       _SEH2_TRY
+       {
+               _SEH2_TRY
+               {
+            FsRtlEnterFileSystem();
+
+                       if (DeviceObject == FFSGlobal->DeviceObject)
+                       {
+                               IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST;
+                               Status = TRUE;
+                               _SEH2_LEAVE;
+                       }
+
+                       Fcb = (PFFS_FCB)FileObject->FsContext;
+
+                       ASSERT(Fcb != NULL);
+
+                       if (Fcb->Identifier.Type == FFSVCB)
+                       {
+                               FFSBreakPoint();
+                               IoStatus->Status = STATUS_INVALID_PARAMETER;
+                               Status = TRUE;
+                               _SEH2_LEAVE;
+                       }
+
+                       ASSERT((Fcb->Identifier.Type == FFSFCB) &&
+                                       (Fcb->Identifier.Size == sizeof(FFS_FCB)));
+
+                       if (IsDirectory(Fcb))
+                       {
+                               FFSBreakPoint();
+                               IoStatus->Status = STATUS_INVALID_PARAMETER;
+                               Status = TRUE;
+                               _SEH2_LEAVE;
+                       }
+
+                       FFSPrint((DBG_INFO,
+                                               "FFSFastIoUnlockSingle: %s %s %s\n",
+                                               (PUCHAR) Process + ProcessNameOffset,
+                                               "FASTIO_UNLOCK_SINGLE",
+                                               Fcb->AnsiFileName.Buffer));
+
+                       FFSPrint((DBG_INFO,
+                                               "FFSFastIoUnlockSingle: Offset: %I64xh Length: %I64xh Key: %u\n",
+                                               FileOffset->QuadPart,
+                                               Length->QuadPart,
+                                               Key));
+
+                       IoStatus->Status = FsRtlFastUnlockSingle(
+                                                                       &Fcb->FileLockAnchor,
+                                                                       FileObject,
+                                                                       FileOffset,
+                                                                       Length,
+                                                                       Process,
+                                                                       Key,
+                                                                       NULL,
+                                                                       FALSE);                      
+
+                       IoStatus->Information = 0;
+
+                       Status =  TRUE;
+               }
+               _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER)
+               {
+                       IoStatus->Status = _SEH2_GetExceptionCode();
+                       Status = TRUE;
+               } _SEH2_END;
+       }
+       _SEH2_FINALLY
+       {
+               FsRtlExitFileSystem();
+       } _SEH2_END;
+
+#if DBG 
+       if (Status == FALSE)
+       {
+               FFSPrint((DBG_ERROR,
+                                       "FFSFastIoUnlockSingle: %s %s *** Status: FALSE ***\n",
+                                       (PUCHAR) Process + ProcessNameOffset,
+                                       "FASTIO_UNLOCK_SINGLE"));
+       }
+       else if (IoStatus->Status != STATUS_SUCCESS)
+       {
+               FFSPrint((DBG_ERROR,
+                                       "FFSFastIoUnlockSingle: %s %s *** Status: %s (%#x) ***\n",
+                                       (PUCHAR) Process + ProcessNameOffset,
+                                       "FASTIO_UNLOCK_SINGLE",
+                                       FFSNtStatusToString(IoStatus->Status),
+                                       IoStatus->Status));
+       }
+#endif  
+       return Status;
+}
+
+
+BOOLEAN NTAPI
+FFSFastIoUnlockAll(
+       IN PFILE_OBJECT         FileObject,
+       IN PEPROCESS            Process,
+       OUT PIO_STATUS_BLOCK    IoStatus,
+       IN PDEVICE_OBJECT       DeviceObject)
+{
+       BOOLEAN     Status = FALSE;
+       PFFS_FCB    Fcb;
+
+    PAGED_CODE();
+
+       _SEH2_TRY
+       {
+               _SEH2_TRY
+               {
+            FsRtlEnterFileSystem();
+
+                       if (DeviceObject == FFSGlobal->DeviceObject)
+                       {
+                               IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST;
+                               Status = TRUE;
+                               _SEH2_LEAVE;
+                       }
+
+                       Fcb = (PFFS_FCB)FileObject->FsContext;
+
+                       ASSERT(Fcb != NULL);
+
+                       if (Fcb->Identifier.Type == FFSVCB)
+                       {
+                               FFSBreakPoint();
+                               IoStatus->Status = STATUS_INVALID_PARAMETER;
+                               Status = TRUE;
+                               _SEH2_LEAVE;
+                       }
+
+                       ASSERT((Fcb->Identifier.Type == FFSFCB) &&
+                                       (Fcb->Identifier.Size == sizeof(FFS_FCB)));
+
+                       if (IsDirectory(Fcb))
+                       {
+                               FFSBreakPoint();
+                               IoStatus->Status = STATUS_INVALID_PARAMETER;
+                               Status = TRUE;
+                               _SEH2_LEAVE;
+                       }
+
+                       FFSPrint((DBG_INFO,
+                                               "FFSFastIoUnlockSingle: %s %s %s\n",
+                                               (PUCHAR) Process + ProcessNameOffset,
+                                               "FASTIO_UNLOCK_ALL",
+                                               Fcb->AnsiFileName.Buffer));
+
+                       IoStatus->Status = FsRtlFastUnlockAll(
+                                                                       &Fcb->FileLockAnchor,
+                                                                       FileObject,
+                                                                       Process,
+                                                                       NULL);
+
+                       IoStatus->Information = 0;
+
+                       Status = TRUE;
+               }
+               _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER)
+               {
+                       IoStatus->Status = _SEH2_GetExceptionCode();
+                       Status = TRUE;
+               } _SEH2_END;
+       }
+       _SEH2_FINALLY
+       {
+               FsRtlExitFileSystem();
+       } _SEH2_END;
+
+#if DBG 
+       if (Status == FALSE)
+       {
+               FFSPrint((DBG_ERROR,
+                                       "FFSFastIoUnlockSingle: %s %s *** Status: FALSE ***\n",
+                                       (PUCHAR) Process + ProcessNameOffset,
+                                       "FASTIO_UNLOCK_ALL"));
+       }
+       else if (IoStatus->Status != STATUS_SUCCESS)
+       {
+               FFSPrint((DBG_ERROR,
+                                       "FFSFastIoUnlockSingle: %s %s *** Status: %s (%#x) ***\n",
+                                       (PUCHAR) Process + ProcessNameOffset,
+                                       "FASTIO_UNLOCK_ALL",
+                                       FFSNtStatusToString(IoStatus->Status),
+                                       IoStatus->Status));
+       }
+#endif  
+       return Status;
+}
+
+
+BOOLEAN NTAPI
+FFSFastIoUnlockAllByKey(
+       IN PFILE_OBJECT         FileObject,
+#ifndef __REACTOS__
+       IN PEPROCESS            Process,
+#else
+       IN PVOID                Process,
+#endif
+       IN ULONG                Key,
+       OUT PIO_STATUS_BLOCK    IoStatus,
+       IN PDEVICE_OBJECT       DeviceObject)
+{
+       BOOLEAN     Status = FALSE;
+       PFFS_FCB    Fcb;
+
+    PAGED_CODE();
+
+       _SEH2_TRY
+       {
+               _SEH2_TRY
+               {
+            FsRtlEnterFileSystem();
+
+                       if (DeviceObject == FFSGlobal->DeviceObject)
+                       {
+                               IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST;
+                               Status = TRUE;
+                               _SEH2_LEAVE;
+                       }
+
+                       Fcb = (PFFS_FCB)FileObject->FsContext;
+
+                       ASSERT(Fcb != NULL);
+
+                       if (Fcb->Identifier.Type == FFSVCB)
+                       {
+                               FFSBreakPoint();
+                               IoStatus->Status = STATUS_INVALID_PARAMETER;
+                               Status = TRUE;
+                               _SEH2_LEAVE;
+                       }
+
+                       ASSERT((Fcb->Identifier.Type == FFSFCB) &&
+                                       (Fcb->Identifier.Size == sizeof(FFS_FCB)));
+
+                       if (IsDirectory(Fcb))
+                       {
+                               FFSBreakPoint();
+                               IoStatus->Status = STATUS_INVALID_PARAMETER;
+                               Status = TRUE;
+                               _SEH2_LEAVE;
+                       }
+
+                       FFSPrint((DBG_INFO,
+                                               "FFSFastIoUnlockAllByKey: %s %s %s\n",
+                                               (PUCHAR) Process + ProcessNameOffset,
+                                               "FASTIO_UNLOCK_ALL_BY_KEY",
+                                               Fcb->AnsiFileName.Buffer));
+
+                       FFSPrint((DBG_INFO,
+                                               "FFSFastIoUnlockAllByKey: Key: %u\n",
+                                               Key));
+
+                       IoStatus->Status = FsRtlFastUnlockAllByKey(
+                                                                       &Fcb->FileLockAnchor,
+                                                                       FileObject,
+                                                                       Process,
+                                                                       Key,
+                                                                       NULL);  
+
+                       IoStatus->Information = 0;
+
+                       Status =  TRUE;
+               }
+
+               _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER)
+               {
+                       IoStatus->Status = _SEH2_GetExceptionCode();
+                       Status = TRUE;
+               } _SEH2_END;
+       }
+
+       _SEH2_FINALLY
+       {
+               FsRtlExitFileSystem();
+       } _SEH2_END;
+#if DBG 
+       if (Status == FALSE)
+       {
+               FFSPrint((DBG_ERROR,
+                                       "FFSFastIoUnlockAllByKey: %s %s *** Status: FALSE ***\n",
+                                       (PUCHAR) Process + ProcessNameOffset,
+                                       "FASTIO_UNLOCK_ALL_BY_KEY"));
+       }
+       else if (IoStatus->Status != STATUS_SUCCESS)
+       {
+               FFSPrint((DBG_ERROR,
+                                       "FFSFastIoUnlockAllByKey: %s %s *** Status: %s (%#x) ***\n",
+                                       (PUCHAR) Process + ProcessNameOffset,
+                                       "FASTIO_UNLOCK_ALL_BY_KEY",
+                                       FFSNtStatusToString(IoStatus->Status),
+                                       IoStatus->Status));
+       }
+#endif  
+       return Status;
+}
diff --git a/reactos/drivers/filesystems/ffs/src/ffs.c b/reactos/drivers/filesystems/ffs/src/ffs.c
new file mode 100644 (file)
index 0000000..ab73bab
--- /dev/null
@@ -0,0 +1,3042 @@
+/* 
+ * FFS File System Driver for Windows
+ *
+ * ffs.c
+ *
+ * 2004.5.6 ~
+ *
+ * Lee Jae-Hong, http://www.pyrasis.com
+ *
+ * See License.txt
+ *
+ */
+
+#include "ntifs.h"
+#include "ffsdrv.h"
+
+
+/* Globals */
+extern PFFS_GLOBAL   FFSGlobal;
+
+
+/* Definitions */
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE, FFSLoadSuper)
+#pragma alloc_text(PAGE, FFSSaveSuper)
+
+#pragma alloc_text(PAGE, FFSLoadGroup)
+#pragma alloc_text(PAGE, FFSSaveGroup)
+
+#pragma alloc_text(PAGE, FFSv1GetInodeLba)
+#pragma alloc_text(PAGE, FFSv2GetInodeLba)
+#pragma alloc_text(PAGE, FFSv1LoadInode)
+#pragma alloc_text(PAGE, FFSv2LoadInode)
+#pragma alloc_text(PAGE, FFSv1SaveInode)
+#pragma alloc_text(PAGE, FFSv2SaveInode)
+
+#pragma alloc_text(PAGE, FFSv1LoadBlock)
+#pragma alloc_text(PAGE, FFSv2LoadBlock)
+#pragma alloc_text(PAGE, FFSSaveBlock)
+
+#pragma alloc_text(PAGE, FFSSaveBuffer)
+
+#pragma alloc_text(PAGE, FFSv1GetBlock)
+#pragma alloc_text(PAGE, FFSv2GetBlock)
+#pragma alloc_text(PAGE, FFSv1BlockMap)
+#pragma alloc_text(PAGE, FFSv2BlockMap)
+
+#pragma alloc_text(PAGE, FFSv1BuildBDL)
+#pragma alloc_text(PAGE, FFSv2BuildBDL)
+
+#pragma alloc_text(PAGE, FFSNewBlock)
+#pragma alloc_text(PAGE, FFSFreeBlock)
+
+#pragma alloc_text(PAGE, FFSExpandBlock)
+#pragma alloc_text(PAGE, FFSExpandInode)
+
+#pragma alloc_text(PAGE, FFSNewInode)
+#pragma alloc_text(PAGE, FFSFreeInode)
+
+#pragma alloc_text(PAGE, FFSAddEntry)
+#pragma alloc_text(PAGE, FFSRemoveEntry)
+
+#pragma alloc_text(PAGE, FFSTruncateBlock)
+#pragma alloc_text(PAGE, FFSTruncateInode)
+
+#pragma alloc_text(PAGE, FFSAddMcbEntry)
+#pragma alloc_text(PAGE, FFSRemoveMcbEntry)
+#pragma alloc_text(PAGE, FFSLookupMcbEntry)
+
+#endif
+
+
+PFFS_SUPER_BLOCK
+FFSLoadSuper(
+       IN PFFS_VCB       Vcb,
+       IN BOOLEAN        bVerify,
+       IN ULONGLONG      SuperBlockOffset)
+{
+       NTSTATUS         Status;
+       PFFS_SUPER_BLOCK FFSSb = NULL;
+
+    PAGED_CODE();
+
+       FFSSb = (PFFS_SUPER_BLOCK)ExAllocatePoolWithTag(PagedPool, SUPER_BLOCK_SIZE, FFS_POOL_TAG);
+       if (!FFSSb)
+       {
+               return NULL;
+       }
+
+       Status = FFSReadDisk(Vcb,
+                               SuperBlockOffset,
+                               SUPER_BLOCK_SIZE,
+                               (PVOID)FFSSb,
+                               bVerify);
+
+       if (!NT_SUCCESS(Status))
+       {
+               FFSPrint((DBG_ERROR, "FFSLoadSuper: Read Block Device error.\n"));
+
+               ExFreePool(FFSSb);
+               return NULL;
+       }
+
+       return FFSSb;
+}
+
+#if !FFS_READ_ONLY
+
+__drv_mustHoldCriticalRegion
+BOOLEAN
+FFSSaveSuper(
+       IN PFFS_IRP_CONTEXT    IrpContext,
+       IN PFFS_VCB            Vcb)
+{
+       LONGLONG    Offset;
+       BOOLEAN     bRet;
+
+    PAGED_CODE();
+
+       Offset = (LONGLONG) SUPER_BLOCK_OFFSET;
+
+       bRet = FFSSaveBuffer(IrpContext,
+                               Vcb,
+                               Offset,
+                               SUPER_BLOCK_SIZE,
+                               Vcb->ffs_super_block);
+
+       if (IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK))
+       {
+               FFSStartFloppyFlushDpc(Vcb, NULL, NULL);
+       }
+
+       return bRet;
+}
+
+#endif // !FFS_READ_ONLY
+
+#if 0
+BOOLEAN
+FFSLoadGroup(
+       IN PFFS_VCB Vcb)
+{
+       ULONG       Size;
+       PVOID       Buffer;
+       LONGLONG    Lba;
+       NTSTATUS    Status;
+
+       PFFS_SUPER_BLOCK FFSSb;
+
+    PAGED_CODE();
+
+       FFSSb = Vcb->ffs_super_block;
+
+       Vcb->BlockSize  = FFSSb->fs_bsize;
+       Vcb->SectorBits = FFSLog2(SECTOR_SIZE);
+       ASSERT(BLOCK_BITS == FFSLog2(BLOCK_SIZE));
+
+       Vcb->ffs_groups = (FFSSb->s_blocks_count - FFSSb->s_first_data_block +
+                       FFSSb->s_blocks_per_group - 1) / FFSSb->s_blocks_per_group;
+
+       Size = sizeof(FFS_GROUP_DESC) * Vcb->ffs_groups;
+
+       if (Vcb->BlockSize == MINBSIZE)
+       {
+               Lba = (LONGLONG)2 * Vcb->BlockSize;
+       }
+
+       if (Vcb->BlockSize > MINBSIZE)
+       {
+               Lba = (LONGLONG)(Vcb->BlockSize);
+       }
+
+       if (Lba == 0)
+       {
+               return FALSE;
+       }
+
+       Buffer = ExAllocatePoolWithTag(PagedPool, Size, FFS_POOL_TAG);
+       if (!Buffer)
+       {
+               FFSPrint((DBG_ERROR, "FFSLoadSuper: no enough memory.\n"));
+               return FALSE;
+       }
+
+       FFSPrint((DBG_INFO, "FFSLoadGroup: Lba=%I64xh Size=%xh\n", Lba, Size));
+
+       Status = FFSReadDisk(Vcb,
+                               Lba,
+                               Size,
+                               Buffer,
+                               FALSE);
+
+       if (!NT_SUCCESS(Status))
+       {
+               ExFreePool(Buffer);
+               Buffer = NULL;
+
+               return FALSE;
+       }
+
+       Vcb->ffs_group_desc = (PFFS_GROUP_DESC) Buffer;
+
+       return TRUE;
+}
+
+
+BOOLEAN
+FFSSaveGroup(
+       IN PFFS_IRP_CONTEXT    IrpContext,
+       IN PFFS_VCB            Vcb)
+{
+       LONGLONG    Offset;
+       ULONG       Len;
+       BOOLEAN     bRet;
+
+    PAGED_CODE();
+
+       if (Vcb->BlockSize == FFS_MIN_BLOCK) {
+
+               Offset = (LONGLONG)(2 * Vcb->BlockSize);
+
+       } else {
+
+               Offset = (LONGLONG)(Vcb->BlockSize);
+       }
+
+       Len = (ULONG)(sizeof(struct ffs_group_desc) * Vcb->ffs_groups);
+
+       bRet = FFSSaveBuffer(IrpContext, Vcb, Offset,
+                       Len, Vcb->ffs_group_desc);
+
+       if (IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK))
+       {
+               FFSStartFloppyFlushDpc(Vcb, NULL, NULL);
+       }
+
+       return bRet;
+}
+#endif
+
+
+BOOLEAN
+FFSv1GetInodeLba(
+       IN PFFS_VCB   Vcb,
+       IN  ULONG     inode,
+       OUT PLONGLONG offset)
+{
+       LONGLONG loc;
+
+    PAGED_CODE();
+
+#if 0
+       if (inode < 1 || inode > INODES_COUNT)
+       {
+               FFSPrint((DBG_ERROR, "FFSv1GetInodeLba: Inode value %xh is invalid.\n",inode));
+               *offset = 0;
+               return FALSE;
+       }
+#endif
+
+       loc = cgimin(Vcb->ffs_super_block, ino_to_cg(Vcb->ffs_super_block, inode)) 
+               * Vcb->ffs_super_block->fs_fsize + ((inode % Vcb->ffs_super_block->fs_ipg) * 128);
+
+       *offset = loc;
+       KdPrint(("FFSv1GetInodeLba() inode : %d, loc : %x, offset : %x\n", inode, loc, offset));
+
+       return TRUE;
+}
+
+
+BOOLEAN
+FFSv2GetInodeLba(
+       IN PFFS_VCB   Vcb,
+       IN  ULONG     inode,
+       OUT PLONGLONG offset)
+{
+       LONGLONG loc;
+
+    PAGED_CODE();
+
+#if 0
+       if (inode < 1 || inode > INODES_COUNT)
+       {
+               FFSPrint((DBG_ERROR, "FFSv2GetInodeLba: Inode value %xh is invalid.\n",inode));
+               *offset = 0;
+               return FALSE;
+       }
+#endif
+
+       loc = cgimin(Vcb->ffs_super_block, ino_to_cg(Vcb->ffs_super_block, inode)) 
+               * Vcb->ffs_super_block->fs_fsize + ((inode % Vcb->ffs_super_block->fs_ipg) * 256);
+
+       *offset = loc;
+       //KdPrint(("FFSv2GetInodeLba() inode : %d, loc : %x, offset : %x\n", inode, loc, offset));
+
+       return TRUE;
+}
+
+
+BOOLEAN
+FFSv1LoadInode(
+       IN PFFS_VCB     Vcb,
+       IN ULONG        inode,
+       IN PFFSv1_INODE dinode1)
+{
+       IO_STATUS_BLOCK     IoStatus;
+       LONGLONG            Offset;
+
+    PAGED_CODE();
+
+       if (!FFSv1GetInodeLba(Vcb, inode, &Offset))
+       {
+               FFSPrint((DBG_ERROR, "FFSv1LoadInode: error get inode(%xh)'s addr.\n", inode));
+               return FALSE;
+       }
+
+       if (!FFSCopyRead(
+                               Vcb->StreamObj,
+                               (PLARGE_INTEGER)&Offset,
+                               DINODE1_SIZE,
+                               PIN_WAIT,
+                               (PVOID)dinode1,
+                               &IoStatus));
+
+       if (!NT_SUCCESS(IoStatus.Status))
+       {
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+
+BOOLEAN
+FFSv2LoadInode(
+       IN PFFS_VCB     Vcb,
+       IN ULONG        inode,
+       IN PFFSv2_INODE dinode2)
+{
+       IO_STATUS_BLOCK     IoStatus;
+       LONGLONG            Offset;
+
+    PAGED_CODE();
+
+       if (!FFSv2GetInodeLba(Vcb, inode, &Offset))
+       {
+               FFSPrint((DBG_ERROR, "FFSv2LoadInode: error get inode(%xh)'s addr.\n", inode));
+               return FALSE;
+       }
+
+       Offset += (LONGLONG)Vcb->FSOffset[Vcb->PartitionNumber];
+
+       if (!FFSCopyRead(
+                               Vcb->StreamObj,
+                               (PLARGE_INTEGER)&Offset,
+                               DINODE2_SIZE,
+                               PIN_WAIT,
+                               (PVOID)dinode2,
+                               &IoStatus));
+
+       if (!NT_SUCCESS(IoStatus.Status))
+       {
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+
+/*
+BOOLEAN
+FFSSaveInode(
+       IN PFFS_VCB      Vcb,
+       IN ULONG         inode,
+       IN struct dinode *dinode)
+{
+       ULONG       lba;
+       ULONG       offset;
+       NTSTATUS    Status;
+
+       if (!FFSGetInodeLba(Vcb, inode, &lba, &offset))
+       {
+               FFSPrint((DBG_ERROR, "FFSLoadInode: error get inode(%xh)'s addr.\n", inode));
+               return FALSE;
+       }
+
+       Status = FFSWriteDisk(Vcb->TargetDeviceObject,
+               lba,
+               offset,
+               sizeof(FFS_INODE),
+               (PVOID)dinode);
+
+       if (!NT_SUCCESS(Status))
+       {
+               return FALSE;
+       }
+
+       return TRUE;
+}
+*/
+
+#if !FFS_READ_ONLY
+
+__drv_mustHoldCriticalRegion
+BOOLEAN
+FFSv1SaveInode(
+       IN PFFS_IRP_CONTEXT IrpContext,
+       IN PFFS_VCB         Vcb,
+       IN ULONG            Inode,
+       IN PFFSv1_INODE     dinode1)
+{
+       LONGLONG        Offset = 0;
+       LARGE_INTEGER   CurrentTime;
+       BOOLEAN         bRet;
+
+    PAGED_CODE();
+
+       KeQuerySystemTime(&CurrentTime);
+       dinode1->di_mtime = dinode1->di_atime = 
+               (ULONG)(FFSInodeTime(CurrentTime));
+
+       FFSPrint((DBG_INFO, "FFSv1SaveInode: Saving Inode %xh: Mode=%xh Size=%xh\n",
+                               Inode, dinode1->di_mode, dinode1->di_size));
+
+       if (!FFSv1GetInodeLba(Vcb, Inode, &Offset))
+       {
+               FFSPrint((DBG_ERROR, "FFSv1SaveInode: error get inode(%xh)'s addr.\n", Inode));
+               return FALSE;
+       }
+
+       bRet = FFSSaveBuffer(IrpContext, Vcb, Offset, DINODE1_SIZE, dinode1);
+
+       if (IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK))
+       {
+               FFSStartFloppyFlushDpc(Vcb, NULL, NULL);
+       }
+
+       return bRet;
+}
+
+
+__drv_mustHoldCriticalRegion
+BOOLEAN
+FFSv2SaveInode(
+       IN PFFS_IRP_CONTEXT IrpContext,
+       IN PFFS_VCB         Vcb,
+       IN ULONG            Inode,
+       IN PFFSv2_INODE     dinode2)
+{
+    PAGED_CODE();
+
+       return FALSE;
+}
+
+#endif // !FFS_READ_ONLY
+
+BOOLEAN
+FFSv1LoadBlock(
+       IN PFFS_VCB  Vcb,
+       IN ULONG     dwBlk,
+       IN PVOID     Buffer)
+{
+       IO_STATUS_BLOCK     IoStatus;
+       LONGLONG            Offset;
+
+    PAGED_CODE();
+
+       Offset = (LONGLONG) dwBlk;
+       Offset = Offset * SUPER_BLOCK->fs_fsize; // fragment size
+
+       if (!FFSCopyRead(
+                               Vcb->StreamObj,
+                               (PLARGE_INTEGER)&Offset,
+                               Vcb->BlockSize,
+                               PIN_WAIT,
+                               Buffer,
+                               &IoStatus));
+
+       if (!NT_SUCCESS(IoStatus.Status))
+       {
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+
+BOOLEAN
+FFSv2LoadBlock(
+       IN PFFS_VCB  Vcb,
+       IN ULONGLONG dwBlk,
+       IN PVOID     Buffer)
+{
+       IO_STATUS_BLOCK     IoStatus;
+       LONGLONG            Offset;
+
+    PAGED_CODE();
+
+       Offset = (LONGLONG)dwBlk;
+       Offset = Offset * SUPER_BLOCK->fs_fsize; // fragment size
+
+       Offset += Vcb->FSOffset[Vcb->PartitionNumber];
+
+       if (!FFSCopyRead(
+                               Vcb->StreamObj,
+                               (PLARGE_INTEGER)&Offset,
+                               Vcb->BlockSize,
+                               PIN_WAIT,
+                               Buffer,
+                               &IoStatus));
+
+       if (!NT_SUCCESS(IoStatus.Status))
+       {
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+#if !FFS_READ_ONLY
+
+__drv_mustHoldCriticalRegion
+BOOLEAN
+FFSSaveBlock(
+       IN PFFS_IRP_CONTEXT IrpContext,
+       IN PFFS_VCB         Vcb,
+       IN ULONG            dwBlk,
+       IN PVOID            Buf)
+{
+       LONGLONG Offset;
+       BOOLEAN  bRet;
+
+    PAGED_CODE();
+
+       Offset = (LONGLONG)dwBlk;
+       Offset = Offset * Vcb->BlockSize;
+
+       bRet = FFSSaveBuffer(IrpContext, Vcb, Offset, Vcb->BlockSize, Buf);
+
+       if (IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK))
+       {
+               FFSStartFloppyFlushDpc(Vcb, NULL, NULL);
+       }
+
+       return bRet;
+}
+
+
+__drv_mustHoldCriticalRegion
+BOOLEAN
+FFSSaveBuffer(
+       IN PFFS_IRP_CONTEXT IrpContext,
+       IN PFFS_VCB         Vcb,
+       IN LONGLONG         Offset,
+       IN ULONG            Size,
+       IN PVOID            Buf)
+{
+       PBCB        Bcb;
+       PVOID       Buffer;
+
+    PAGED_CODE();
+
+       if(!CcPinRead(Vcb->StreamObj,
+                               (PLARGE_INTEGER) (&Offset),
+                               Size,
+                               PIN_WAIT,
+                               &Bcb,
+                               &Buffer))
+       {
+               FFSPrint((DBG_ERROR, "FFSSaveBuffer: PinReading error ...\n"));
+               return FALSE;
+       }
+
+
+       /*FFSPrint((DBG_INFO, "FFSSaveBuffer: Off=%I64xh Len=%xh Bcb=%xh\n",
+                               Offset, Size, (ULONG)Bcb));*/
+
+       RtlCopyMemory(Buffer, Buf, Size);
+       CcSetDirtyPinnedData(Bcb, NULL);
+
+       FFSRepinBcb(IrpContext, Bcb);
+
+       CcUnpinData(Bcb);
+
+       SetFlag(Vcb->StreamObj->Flags, FO_FILE_MODIFIED);
+
+       FFSAddMcbEntry(Vcb, Offset, (LONGLONG)Size);
+
+       return TRUE;
+}
+
+#endif // !FFS_READ_ONLY
+
+ULONG
+FFSv1GetBlock(
+       IN PFFS_VCB Vcb,
+       ULONG       dwContent,
+       ULONG       Index,
+       int         layer)
+{
+       ULONG       *pData = NULL;
+       ULONG       i = 0, j = 0, temp = 1;
+       ULONG       dwBlk = 0;
+
+    PAGED_CODE();
+
+       if (layer == 0)
+       {
+               dwBlk = dwContent;
+       }
+       else if (layer <= 3)
+       {
+               pData = (ULONG *)ExAllocatePoolWithTag(PagedPool,
+                               Vcb->BlockSize, FFS_POOL_TAG);
+               if (!pData)
+               {
+                       FFSPrint((DBG_ERROR, "FFSGetBlock: no enough memory.\n"));
+                       return dwBlk;
+               }
+
+               KdPrint(("FFSGetBlock Index : %d, dwContent : %x, layer : %d\n", Index, dwContent, layer));
+
+               if (!FFSv1LoadBlock(Vcb, dwContent, pData))
+               {
+                       ExFreePool(pData);
+                       return 0;
+               }
+
+               temp = 1 << ((BLOCK_BITS - 2) * (layer - 1));
+
+               i = Index / temp;
+               j = Index % temp;
+
+               dwBlk = pData[i];
+
+               ExFreePool(pData);
+
+               dwBlk = FFSv1GetBlock(Vcb, dwBlk, j, layer - 1);
+       }
+
+       return dwBlk;
+}
+
+
+ULONGLONG
+FFSv2GetBlock(
+       IN PFFS_VCB Vcb,
+       ULONGLONG   dwContent,
+       ULONG       Index,
+       int         layer)
+{
+       ULONGLONG   *pData = NULL;
+       ULONG       i = 0, j = 0, temp = 1;
+       ULONGLONG   dwBlk = 0;
+
+    PAGED_CODE();
+
+       if (layer == 0)
+       {
+               dwBlk = dwContent;
+       }
+       else if (layer <= 3)
+       {
+               pData = (ULONGLONG *)ExAllocatePoolWithTag(PagedPool,
+                               Vcb->BlockSize, FFS_POOL_TAG);
+               if (!pData)
+               {
+                       FFSPrint((DBG_ERROR, "FFSv2GetBlock: no enough memory.\n"));
+                       return dwBlk;
+               }
+
+               KdPrint(("FFSv2GetBlock Index : %d, dwContent : %x, layer : %d\n", Index, dwContent, layer));
+
+               if (!FFSv2LoadBlock(Vcb, dwContent, pData))
+               {
+                       ExFreePool(pData);
+                       return 0;
+               }
+
+               if (Index >= (Vcb->BlockSize / 8) && layer == 2)
+                       temp = 1 << ((BLOCK_BITS - 3) * (layer - 1));
+               else
+                       temp = 1 << ((BLOCK_BITS - 2) * (layer - 1));
+
+               i = Index / temp;
+               j = Index % temp;
+
+               dwBlk = pData[i];
+
+               ExFreePool(pData);
+
+               dwBlk = FFSv2GetBlock(Vcb, dwBlk, j, layer - 1);
+       }
+
+       return dwBlk;
+}
+
+
+ULONG
+FFSv1BlockMap(
+       IN PFFS_VCB     Vcb,
+       IN PFFSv1_INODE dinode1,
+       IN ULONG        Index)
+{
+       ULONG   dwSizes[FFS_BLOCK_TYPES];
+       int     i;
+       ULONG   dwBlk;
+       ULONG   Totalblocks;
+
+    PAGED_CODE();
+
+       for (i = 0; i < FFS_BLOCK_TYPES; i++)
+       {
+               dwSizes[i] = Vcb->dwData[i];
+       }
+
+       Totalblocks = (dinode1->di_blocks);
+
+       if (Index >= FFSDataBlocks(Vcb, Totalblocks))
+       {
+               FFSPrint((DBG_ERROR, "FFSv1BlockMap: error input paramters.\n"));
+
+               FFSBreakPoint();
+
+               return 0;
+       }       
+
+       /* Á÷Á¢, °£Á¢, 2Áß °£Á¢ Ã³¸® */
+       for (i = 0; i < FFS_BLOCK_TYPES; i++)
+       {
+               if (Index < dwSizes[i])
+               {
+                       if (i == 0)
+                               dwBlk = dinode1->di_db[Index]; /* Á÷Á¢ */
+                       else
+                               dwBlk = dinode1->di_ib[i - 1]; /* °£Á¢ */
+#if DBG
+                       {   
+                               ULONG dwRet = FFSv1GetBlock(Vcb, dwBlk, Index , i);
+
+                               KdPrint(("FFSv1BlockMap: i : %d, Index : %d, dwBlk : %x, Data Block : %X\n", i, Index, dwRet, (dwRet * 0x400)));
+
+                               return dwRet;
+                       }
+#else
+                       return FFSv1GetBlock(Vcb, dwBlk, Index , i);
+#endif
+               }
+
+               Index -= dwSizes[i];
+       }
+
+       return 0;
+}
+
+
+ULONGLONG
+FFSv2BlockMap(
+       IN PFFS_VCB     Vcb,
+       IN PFFSv2_INODE dinode2,
+       IN ULONG        Index)
+{
+       ULONG     dwSizes[FFS_BLOCK_TYPES];
+       int       i;
+       ULONGLONG dwBlk;
+       ULONG     Totalblocks;
+
+    PAGED_CODE();
+
+       for (i = 0; i < FFS_BLOCK_TYPES; i++)
+       {
+               dwSizes[i] = Vcb->dwData[i];
+       }
+
+       Totalblocks = (ULONG)(dinode2->di_blocks);
+
+       if (Index >= FFSDataBlocks(Vcb, Totalblocks))
+       {
+               FFSPrint((DBG_ERROR, "FFSv2BlockMap: error input paramters.\n"));
+
+               FFSBreakPoint();
+
+               return 0;
+       }       
+
+       /* Á÷Á¢, °£Á¢, 2Áß °£Á¢ Ã³¸® */
+       for (i = 0; i < FFS_BLOCK_TYPES; i++)
+       {
+               if (Index < dwSizes[i])
+               {
+                       if (i == 0)
+                               dwBlk = (ULONGLONG)dinode2->di_db[Index]; /* Á÷Á¢ */
+                       else
+                               dwBlk = (ULONGLONG)dinode2->di_ib[i - 1]; /* °£Á¢ */
+#if 0
+                       {   
+                               ULONGLONG dwRet = FFSv2GetBlock(Vcb, dwBlk, Index , i);
+
+                               KdPrint(("FFSv2BlockMap: i : %d, Index : %d, dwBlk : %x, Data Block : %X\n", i, Index, dwRet, (dwRet * 0x400)));
+
+                               return dwRet;
+                       }
+#else
+                       return FFSv2GetBlock(Vcb, dwBlk, Index , i);
+#endif
+               }
+
+               Index -= dwSizes[i];
+       }
+
+       return 0;
+}
+
+
+ULONG
+FFSv1BuildBDL(
+       IN PFFS_IRP_CONTEXT IrpContext,
+       IN PFFS_VCB         Vcb,
+       IN PFFSv1_INODE     dinode1,
+       IN ULONGLONG        Offset, 
+       IN ULONG            Size, 
+       OUT PFFS_BDL        *ffs_bdl)
+{
+       ULONG    nBeg, nEnd, nBlocks;
+       ULONG    dwBlk, i;
+       ULONG    dwBytes = 0;
+       LONGLONG Lba;
+       LONGLONG AllocSize;
+       ULONG    Totalblocks;
+
+       PFFS_BDL   ffsbdl;
+
+    PAGED_CODE();
+
+       *ffs_bdl = NULL;
+
+
+       Totalblocks = (dinode1->di_blocks);
+       AllocSize = FFSDataBlocks(Vcb, Totalblocks);
+       AllocSize = (AllocSize << BLOCK_BITS);
+
+       if ((LONGLONG)Offset >= AllocSize)
+       {
+               FFSPrint((DBG_ERROR, "FFSv1BuildBDL: beyond the file range.\n"));
+               return 0;
+       }
+
+       if ((LONGLONG)(Offset + Size) > AllocSize)
+       {
+               Size = (ULONG)(AllocSize - Offset);
+       }
+
+       nBeg = (ULONG)(Offset >> BLOCK_BITS);
+       nEnd = (ULONG)((Size + Offset + Vcb->BlockSize - 1) >> BLOCK_BITS);
+
+#if DBG
+       KdPrint(("FFSv1BuildBDL() Offset : %x\n", Offset));
+       KdPrint(("FFSv1BuildBDL() Size : %x\n", Size));
+       KdPrint(("FFSv1BuildBDL() nBeg : %d, nEnd : %d\n", nBeg, nEnd));
+#endif
+
+       nBlocks = 0;
+
+       if ((nEnd - nBeg) > 0)
+       {
+               ffsbdl = ExAllocatePoolWithTag(PagedPool, sizeof(FFS_BDL) * (nEnd - nBeg), FFS_POOL_TAG);
+
+               if (ffsbdl)
+               {
+                       RtlZeroMemory(ffsbdl, sizeof(FFS_BDL) * (nEnd - nBeg));
+
+                       for (i = nBeg; i < nEnd; i++)
+                       {
+                               dwBlk = FFSv1BlockMap(Vcb, dinode1, i);
+
+                               if (dwBlk > 0)
+                               {
+                                       Lba = (LONGLONG)dwBlk;
+                                       Lba = Lba * SUPER_BLOCK->fs_fsize; // fragment size
+
+                                       if (nBeg == nEnd - 1) // ie. (nBeg == nEnd - 1)
+                                       {
+                                               dwBytes = Size;
+                                               ffsbdl[nBlocks].Lba = Lba + (LONGLONG)(Offset % (Vcb->BlockSize));
+                                               ffsbdl[nBlocks].Length = dwBytes;
+                                               ffsbdl[nBlocks].Offset = 0;
+
+                                               nBlocks++;
+                                       }
+                                       else
+                                       {
+                                               if (i == nBeg)
+                                               {
+                                                       dwBytes = Vcb->BlockSize - (ULONG)(Offset % (Vcb->BlockSize));
+                                                       ffsbdl[nBlocks].Lba = Lba + (LONGLONG)(Offset % (Vcb->BlockSize));
+                                                       ffsbdl[nBlocks].Length = dwBytes;
+                                                       ffsbdl[nBlocks].Offset = 0;
+
+                                                       nBlocks++;
+                                               }
+                                               else if (i == nEnd - 1)
+                                               {
+                                                       if (ffsbdl[nBlocks - 1].Lba + ffsbdl[nBlocks - 1].Length == Lba)
+                                                       {
+                                                               ffsbdl[nBlocks - 1].Length += Size - dwBytes;
+                                                       }
+                                                       else
+                                                       {
+                                                               ffsbdl[nBlocks].Lba = Lba;
+                                                               ffsbdl[nBlocks].Length = Size - dwBytes;
+                                                               ffsbdl[nBlocks].Offset = dwBytes;
+                                                               nBlocks++;
+                                                       }
+
+                                                       dwBytes = Size;
+
+                                               }
+                                               else
+                                               {
+                                                       if (ffsbdl[nBlocks - 1].Lba + ffsbdl[nBlocks - 1].Length == Lba)
+                                                       {
+                                                               ffsbdl[nBlocks - 1].Length += Vcb->BlockSize;
+                                                       }
+                                                       else
+                                                       {
+                                                               ffsbdl[nBlocks].Lba = Lba;
+                                                               ffsbdl[nBlocks].Length = Vcb->BlockSize;
+                                                               ffsbdl[nBlocks].Offset = dwBytes;
+                                                               nBlocks++;
+                                                       }
+
+                                                       dwBytes +=  Vcb->BlockSize;
+                                               }
+                                       }
+                               }
+                               else
+                               {
+                                       break;
+                               }
+                       }
+
+                       *ffs_bdl = ffsbdl;
+                       return nBlocks;
+               }
+       }
+
+       // Error
+       return 0;
+}
+
+
+ULONG
+FFSv2BuildBDL(
+       IN PFFS_IRP_CONTEXT IrpContext,
+       IN PFFS_VCB         Vcb,
+       IN PFFSv2_INODE     dinode2,
+       IN ULONGLONG        Offset, 
+       IN ULONG            Size, 
+       OUT PFFS_BDL        *ffs_bdl)
+{
+       ULONG     nBeg, nEnd, nBlocks;
+       ULONGLONG dwBlk;
+       ULONG     dwBytes = 0, i;
+       LONGLONG  Lba;
+       LONGLONG  AllocSize;
+       ULONG     Totalblocks;
+
+       PFFS_BDL   ffsbdl;
+
+    PAGED_CODE();
+
+       *ffs_bdl = NULL;
+
+
+       Totalblocks = (ULONG)(dinode2->di_blocks);
+       AllocSize = FFSDataBlocks(Vcb, Totalblocks);
+       AllocSize = (AllocSize << BLOCK_BITS);
+
+       if ((LONGLONG)Offset >= AllocSize)
+       {
+               FFSPrint((DBG_ERROR, "FFSv2BuildBDL: beyond the file range.\n"));
+               return 0;
+       }
+
+       if ((LONGLONG)(Offset + Size) > AllocSize)
+       {
+               Size = (ULONG)(AllocSize - Offset);
+       }
+
+       nBeg = (ULONG)(Offset >> BLOCK_BITS);
+       nEnd = (ULONG)((Size + Offset + Vcb->BlockSize - 1) >> BLOCK_BITS);
+
+#if 0
+       KdPrint(("FFSv2BuildBDL() Offset : %x\n", Offset));
+       KdPrint(("FFSv2BuildBDL() Size : %x\n", Size));
+       KdPrint(("FFSv2BuildBDL() nBeg : %d, nEnd : %d\n", nBeg, nEnd));
+#endif
+
+       nBlocks = 0;
+
+       if ((nEnd - nBeg) > 0)
+       {
+               ffsbdl = ExAllocatePoolWithTag(PagedPool, sizeof(FFS_BDL) * (nEnd - nBeg), FFS_POOL_TAG);
+
+               if (ffsbdl)
+               {
+
+                       RtlZeroMemory(ffsbdl, sizeof(FFS_BDL) * (nEnd - nBeg));
+
+                       for (i = nBeg; i < nEnd; i++)
+                       {
+                               dwBlk = FFSv2BlockMap(Vcb, dinode2, i);
+
+                               if (dwBlk > 0)
+                               {
+                                       Lba = (LONGLONG)dwBlk;
+                                       Lba = Lba * SUPER_BLOCK->fs_fsize; // fragment size
+                                       Lba += Vcb->FSOffset[Vcb->PartitionNumber];
+
+                                       if (nBeg == nEnd - 1) // ie. (nBeg == nEnd - 1)
+                                       {
+                                               dwBytes = Size;
+                                               ffsbdl[nBlocks].Lba = Lba + (LONGLONG)(Offset % (Vcb->BlockSize));
+                                               ffsbdl[nBlocks].Length = dwBytes;
+                                               ffsbdl[nBlocks].Offset = 0;
+
+                                               nBlocks++;
+                                       }
+                                       else
+                                       {
+                                               if (i == nBeg)
+                                               {
+                                                       dwBytes = Vcb->BlockSize - (ULONG)(Offset % (Vcb->BlockSize));
+                                                       ffsbdl[nBlocks].Lba = Lba + (LONGLONG)(Offset % (Vcb->BlockSize));
+                                                       ffsbdl[nBlocks].Length = dwBytes;
+                                                       ffsbdl[nBlocks].Offset = 0;
+
+                                                       nBlocks++;
+                                               }
+                                               else if (i == nEnd - 1)
+                                               {
+                                                       if (ffsbdl[nBlocks - 1].Lba + ffsbdl[nBlocks - 1].Length == Lba)
+                                                       {
+                                                               ffsbdl[nBlocks - 1].Length += Size - dwBytes;
+                                                       }
+                                                       else
+                                                       {
+                                                               ffsbdl[nBlocks].Lba = Lba;
+                                                               ffsbdl[nBlocks].Length = Size - dwBytes;
+                                                               ffsbdl[nBlocks].Offset = dwBytes;
+                                                               nBlocks++;
+                                                       }
+
+                                                       dwBytes = Size;
+
+                                               }
+                                               else
+                                               {
+                                                       if (ffsbdl[nBlocks - 1].Lba + ffsbdl[nBlocks - 1].Length == Lba)
+                                                       {
+                                                               ffsbdl[nBlocks - 1].Length += Vcb->BlockSize;
+                                                       }
+                                                       else
+                                                       {
+                                                               ffsbdl[nBlocks].Lba = Lba;
+                                                               ffsbdl[nBlocks].Length = Vcb->BlockSize;
+                                                               ffsbdl[nBlocks].Offset = dwBytes;
+                                                               nBlocks++;
+                                                       }
+
+                                                       dwBytes +=  Vcb->BlockSize;
+                                               }
+                                       }
+                               }
+                               else
+                               {
+                                       break;
+                               }
+                       }
+
+                       *ffs_bdl = ffsbdl;
+                       return nBlocks;
+               }
+       }
+
+       // Error
+       return 0;
+}
+
+#if !FFS_READ_ONLY
+
+BOOLEAN
+FFSNewBlock(
+       PFFS_IRP_CONTEXT IrpContext,
+       PFFS_VCB         Vcb,
+       ULONG            GroupHint,
+       ULONG            BlockHint,  
+       PULONG           dwRet)
+{
+       RTL_BITMAP      BlockBitmap;
+       LARGE_INTEGER   Offset;
+       ULONG           Length;
+
+       PBCB            BitmapBcb;
+       PVOID           BitmapCache;
+
+       ULONG           Group = 0, dwBlk, dwHint = 0;
+
+    PAGED_CODE();
+
+#if 0
+       *dwRet = 0;
+       dwBlk = 0XFFFFFFFF;
+
+       if (GroupHint > Vcb->ffs_groups)
+               GroupHint = Vcb->ffs_groups - 1;
+
+       if (BlockHint != 0)
+       {
+               GroupHint = (BlockHint - FFS_FIRST_DATA_BLOCK) / BLOCKS_PER_GROUP;
+               dwHint = (BlockHint - FFS_FIRST_DATA_BLOCK) % BLOCKS_PER_GROUP;
+       }
+
+ScanBitmap:
+
+       // Perform Prefered Group
+       if (Vcb->ffs_group_desc[GroupHint].bg_free_blocks_count)
+       {
+               Offset.QuadPart = (LONGLONG) Vcb->BlockSize;
+               Offset.QuadPart = Offset.QuadPart * 
+                       Vcb->ffs_group_desc[GroupHint].bg_block_bitmap;
+
+               if (GroupHint == Vcb->ffs_groups - 1)
+               {
+                       Length = TOTAL_BLOCKS % BLOCKS_PER_GROUP;
+
+                       /* s_blocks_count is integer multiple of s_blocks_per_group */
+                       if (Length == 0)
+                       {
+                               Length = BLOCKS_PER_GROUP;
+                       }
+               }
+               else
+               {
+                       Length = BLOCKS_PER_GROUP;
+               }
+
+               if (!CcPinRead(Vcb->StreamObj,
+                                       &Offset,
+                                       Vcb->BlockSize,
+                                       PIN_WAIT,
+                                       &BitmapBcb,
+                                       &BitmapCache))
+               {
+                       FFSPrint((DBG_ERROR, "FFSNewBlock: PinReading error ...\n"));
+                       return FALSE;
+               }
+
+               RtlInitializeBitMap(&BlockBitmap,
+                               BitmapCache,
+                               Length);
+
+               Group = GroupHint;
+
+               if (RtlCheckBit(&BlockBitmap, dwHint) == 0)
+               {
+                       dwBlk = dwHint;
+               }
+               else
+               {
+                       dwBlk = RtlFindClearBits(&BlockBitmap, 1, dwHint);
+               }
+
+               // We could not get new block in the prefered group.
+               if (dwBlk == 0xFFFFFFFF)
+               {
+                       CcUnpinData(BitmapBcb);
+                       BitmapBcb = NULL;
+                       BitmapCache = NULL;
+
+                       RtlZeroMemory(&BlockBitmap, sizeof(RTL_BITMAP));
+               }
+       }
+
+       if (dwBlk == 0xFFFFFFFF)
+       {
+               for(Group = 0; Group < Vcb->ffs_groups; Group++)
+                       if (Vcb->ffs_group_desc[Group].bg_free_blocks_count)
+                       {
+
+                               if (Group == GroupHint)
+                                       continue;
+
+                               Offset.QuadPart = (LONGLONG) Vcb->BlockSize;
+                               Offset.QuadPart = Offset.QuadPart * Vcb->ffs_group_desc[Group].bg_block_bitmap;
+
+                               if (Vcb->ffs_groups == 1)
+                               {
+                                       Length = TOTAL_BLOCKS;
+                               }
+                               else
+                               {
+                                       if (Group == Vcb->ffs_groups - 1)
+                                       {
+                                               Length = TOTAL_BLOCKS % BLOCKS_PER_GROUP;
+
+                                               /* s_blocks_count is integer multiple of s_blocks_per_group */
+                                               if (Length == 0)
+                                               {
+                                                       Length = BLOCKS_PER_GROUP;
+                                               }
+                                       }
+                                       else
+                                       {
+                                               Length = BLOCKS_PER_GROUP;
+                                       }
+                               }
+
+                               if (!CcPinRead(Vcb->StreamObj,
+                                                       &Offset,
+                                                       Vcb->BlockSize,
+                                                       PIN_WAIT,
+                                                       &BitmapBcb,
+                                                       &BitmapCache))
+                               {
+                                       FFSPrint((DBG_ERROR, "FFSNewBlock: PinReading error ...\n"));
+                                       return FALSE;
+                               }
+
+                               RtlInitializeBitMap(&BlockBitmap,
+                                               BitmapCache,
+                                               Length);
+
+                               dwBlk = RtlFindClearBits(&BlockBitmap, 1, 0);
+
+                               if (dwBlk != 0xFFFFFFFF)
+                               {
+                                       break;
+                               }
+                               else
+                               {
+                                       CcUnpinData(BitmapBcb);
+                                       BitmapBcb = NULL;
+                                       BitmapCache = NULL;
+
+                                       RtlZeroMemory(&BlockBitmap, sizeof(RTL_BITMAP));
+                               }
+                       }
+       }
+
+       if (dwBlk < Length)
+       {
+               RtlSetBits(&BlockBitmap, dwBlk, 1);
+
+               CcSetDirtyPinnedData(BitmapBcb, NULL);
+
+               FFSRepinBcb(IrpContext, BitmapBcb);
+
+               CcUnpinData(BitmapBcb);
+
+               FFSAddMcbEntry(Vcb, Offset.QuadPart, (LONGLONG)Vcb->BlockSize);
+
+               *dwRet = dwBlk + FFS_FIRST_DATA_BLOCK + Group * BLOCKS_PER_GROUP;
+
+               //Updating Group Desc / Superblock
+               Vcb->ffs_group_desc[Group].bg_free_blocks_count--;
+               FFSSaveGroup(IrpContext, Vcb);
+
+               Vcb->ffs_super_block->s_free_blocks_count--;
+               FFSSaveSuper(IrpContext, Vcb);
+
+               {
+                       ULONG i = 0;
+                       for (i = 0; i < Vcb->ffs_groups; i++)
+                       {
+                               if ((Vcb->ffs_group_desc[i].bg_block_bitmap == *dwRet) ||
+                                               (Vcb->ffs_group_desc[i].bg_inode_bitmap == *dwRet) ||
+                                               (Vcb->ffs_group_desc[i].bg_inode_table == *dwRet))
+                               {
+                                       FFSBreakPoint();
+                                       GroupHint = Group;
+                                       goto ScanBitmap;
+                               }
+                       }
+               }
+
+               return TRUE;
+       }
+#endif
+       return FALSE;
+}
+
+
+BOOLEAN
+FFSFreeBlock(
+       PFFS_IRP_CONTEXT IrpContext,
+       PFFS_VCB         Vcb,
+       ULONG            Block)
+{
+       RTL_BITMAP      BlockBitmap;
+       LARGE_INTEGER   Offset;
+       ULONG           Length;
+
+       PBCB            BitmapBcb;
+       PVOID           BitmapCache;
+
+       ULONG           Group, dwBlk;
+       BOOLEAN         bModified = FALSE;
+
+    PAGED_CODE();
+
+#if 0
+       if (Block < FFS_FIRST_DATA_BLOCK || Block > (BLOCKS_PER_GROUP * Vcb->ffs_groups))
+       {
+               FFSBreakPoint();
+               return TRUE;
+       }
+
+       FFSPrint((DBG_INFO, "FFSFreeBlock: Block %xh to be freed.\n", Block));
+
+       Group = (Block - FFS_FIRST_DATA_BLOCK) / BLOCKS_PER_GROUP;
+
+       dwBlk = (Block - FFS_FIRST_DATA_BLOCK) % BLOCKS_PER_GROUP;
+
+       {
+               Offset.QuadPart = (LONGLONG) Vcb->BlockSize;
+               Offset.QuadPart = Offset.QuadPart * Vcb->ffs_group_desc[Group].bg_block_bitmap;
+
+               if (Group == Vcb->ffs_groups - 1)
+               {
+                       Length = TOTAL_BLOCKS % BLOCKS_PER_GROUP;
+
+                       /* s_blocks_count is integer multiple of s_blocks_per_group */
+                       if (Length == 0)
+                       {
+                               Length = BLOCKS_PER_GROUP;
+                       }
+               }
+               else
+               {
+                       Length = BLOCKS_PER_GROUP;
+               }
+
+               if (!CcPinRead(Vcb->StreamObj,
+                                       &Offset,
+                                       Vcb->BlockSize,
+                                       PIN_WAIT,
+                                       &BitmapBcb,
+                                       &BitmapCache))
+               {
+                       FFSPrint((DBG_ERROR, "FFSDeleteBlock: PinReading error ...\n"));
+                       return FALSE;
+               }
+
+               RtlInitializeBitMap(&BlockBitmap,
+                               BitmapCache,
+                               Length);
+
+               if (RtlCheckBit(&BlockBitmap, dwBlk) == 0)
+               {
+
+               }
+               else
+               {
+                       RtlClearBits(&BlockBitmap, dwBlk, 1);
+                       bModified = TRUE;
+               }
+
+               if (!bModified)
+               {
+                       CcUnpinData(BitmapBcb);
+                       BitmapBcb = NULL;
+                       BitmapCache = NULL;
+
+                       RtlZeroMemory(&BlockBitmap, sizeof(RTL_BITMAP));
+               }
+       }
+
+       if (bModified)
+       {
+               CcSetDirtyPinnedData(BitmapBcb, NULL);
+
+               FFSRepinBcb(IrpContext, BitmapBcb);
+
+               CcUnpinData(BitmapBcb);
+
+               FFSAddMcbEntry(Vcb, Offset.QuadPart, (LONGLONG)Vcb->BlockSize);
+
+               //Updating Group Desc / Superblock
+               Vcb->ffs_group_desc[Group].bg_free_blocks_count++;
+               FFSSaveGroup(IrpContext, Vcb);
+
+               Vcb->ffs_super_block->s_free_blocks_count++;
+               FFSSaveSuper(IrpContext, Vcb);
+
+               return TRUE;
+       }
+#endif
+       return FALSE;
+}
+
+
+__drv_mustHoldCriticalRegion
+BOOLEAN
+FFSExpandBlock(
+       PFFS_IRP_CONTEXT IrpContext,
+       PFFS_VCB         Vcb,
+       PFFS_FCB         Fcb,
+       ULONG            dwContent,
+       ULONG            Index,
+       ULONG            layer,
+       BOOLEAN          bNew,
+       ULONG            *dwRet)
+{
+       ULONG       *pData = NULL;
+       ULONG       i = 0, j = 0, temp = 1;
+       ULONG       dwNewBlk = 0, dwBlk = 0;
+       BOOLEAN     bDirty = FALSE;
+       BOOLEAN     bRet = TRUE;
+
+       PFFSv1_INODE     dinode1 = Fcb->dinode1;
+       PFFS_SUPER_BLOCK FFSSb = Vcb->ffs_super_block;
+
+    PAGED_CODE();
+
+       pData = (ULONG *)ExAllocatePoolWithTag(PagedPool, Vcb->BlockSize, FFS_POOL_TAG);
+
+       if (!pData)
+       {
+               return FALSE;
+       }
+
+       RtlZeroMemory(pData, Vcb->BlockSize);
+
+       if (bNew)
+       {
+               if (layer == 0)
+               {
+                       if (IsDirectory(Fcb))
+                       {
+                               PFFS_DIR_ENTRY pEntry;
+
+                               pEntry = (PFFS_DIR_ENTRY) pData;
+                               pEntry->d_reclen = (USHORT)(Vcb->BlockSize);
+
+                               if (!FFSSaveBlock(IrpContext, Vcb, dwContent, (PVOID)pData))
+                               {
+                                       bRet = FALSE;
+                                       goto errorout;
+                               }
+                       }
+                       else
+                       {
+                               LARGE_INTEGER Offset;
+
+                               Offset.QuadPart = (LONGLONG)dwContent;
+                               Offset.QuadPart = Offset.QuadPart * Vcb->BlockSize;
+
+                               FFSRemoveMcbEntry(Vcb, Offset.QuadPart, (LONGLONG)Vcb->BlockSize);
+                       }
+               }
+               else
+               {
+                       if (!FFSSaveBlock(IrpContext, Vcb, dwContent, (PVOID)pData))
+                       {
+                               bRet = FALSE;
+                               goto errorout;
+                       }
+               }
+       }
+
+       if (layer == 0)
+       {
+               dwNewBlk = dwContent;
+       }
+       else if (layer <= 3)
+       {
+               if (!bNew)
+               {
+                       bRet = FFSv1LoadBlock(Vcb, dwContent, (void *)pData);
+                       if (!bRet) goto errorout;
+               }
+
+               temp = 1 << ((BLOCK_BITS - 2) * (layer - 1));
+
+               i = Index / temp;
+               j = Index % temp;
+
+               dwBlk = pData[i];
+
+               if (dwBlk == 0)
+               {
+                       if (!FFSNewBlock(IrpContext,
+                                               Vcb, 0,
+                                               dwContent,
+                                               &dwBlk))
+                       {
+                               bRet = FALSE;
+                               FFSPrint((DBG_ERROR, "FFSExpandBlock: get new block error.\n"));
+                               goto errorout;
+                       }
+
+                       dinode1->di_blocks += (Vcb->BlockSize / SECTOR_SIZE);
+
+                       pData[i] = dwBlk;
+                       bDirty = TRUE;
+               }
+
+               if (!FFSExpandBlock(IrpContext,
+                                       Vcb, Fcb,
+                                       dwBlk, j,
+                                       layer - 1,
+                                       bDirty,
+                                       &dwNewBlk))
+               {
+                       bRet = FALSE;
+                       FFSPrint((DBG_ERROR, "FFSExpandBlockk: ... error recuise...\n"));
+                       goto errorout;
+               }
+
+               if (bDirty)
+               {
+                       bRet = FFSSaveBlock(IrpContext,
+                                       Vcb, dwContent,
+                                       (void *)pData);
+               }
+       }
+
+errorout:
+
+       if (pData)
+               ExFreePool(pData);
+
+       if (bRet && dwRet)
+               *dwRet = dwNewBlk;
+
+       return bRet;
+}
+
+
+BOOLEAN
+FFSExpandInode(
+       PFFS_IRP_CONTEXT IrpContext,
+       PFFS_VCB         Vcb,
+       PFFS_FCB         Fcb,
+       ULONG            *dwRet)
+{
+       ULONG    dwSizes[FFS_BLOCK_TYPES];
+       ULONG    Index = 0;
+       ULONG    dwTotal = 0;
+       ULONG    dwBlk = 0, dwNewBlk = 0;
+       ULONG    i;
+       BOOLEAN  bRet = FALSE;
+       BOOLEAN  bNewBlock = FALSE;
+
+       PFFSv1_INODE dinode1 = Fcb->dinode1;
+
+    PAGED_CODE();
+
+       Index = (ULONG)(Fcb->Header.AllocationSize.QuadPart >> BLOCK_BITS);
+
+       for (i = 0; i < FFS_BLOCK_TYPES; i++)
+       {
+               dwSizes[i] = Vcb->dwData[i];
+               dwTotal += dwSizes[i];
+       }
+
+       if (Index >= dwTotal)
+       {
+               FFSPrint((DBG_ERROR, "FFSExpandInode: beyond the maxinum size of an inode.\n"));
+               return FALSE;
+       }
+
+       for (i = 0; i < FFS_BLOCK_TYPES; i++)
+       {
+               if (Index < dwSizes[i])
+               {
+                       dwBlk = dinode1->di_db[i == 0 ? (Index) : (i + NDADDR - 1)];
+                       if (dwBlk == 0)
+                       {
+                               if (!FFSNewBlock(IrpContext,
+                                                       Vcb,
+                                                       Fcb->BlkHint ? 0 : ((Fcb->FFSMcb->Inode - 1) / INODES_PER_GROUP),
+                                                       Fcb->BlkHint,
+                                                       &dwBlk))
+                               {
+                                       FFSPrint((DBG_ERROR, "FFSExpandInode: get new block error.\n"));
+                                       break;
+                               }
+
+                               dinode1->di_ib[i == 0 ? (Index):(i + NDADDR - 1)] = dwBlk;
+
+                               dinode1->di_blocks += (Vcb->BlockSize / SECTOR_SIZE);
+
+                               bNewBlock = TRUE;
+                       }
+
+                       bRet = FFSExpandBlock(IrpContext,
+                                       Vcb, Fcb,
+                                       dwBlk, Index,
+                                       i, bNewBlock,
+                                       &dwNewBlk); 
+
+                       if (bRet)
+                       {
+                               Fcb->Header.AllocationSize.QuadPart += Vcb->BlockSize;
+                       }
+
+                       break;
+               }
+
+               Index -= dwSizes[i];
+       }
+
+       {
+               ASSERT(FFSDataBlocks(Vcb, (ULONG)(dinode1->di_blocks / (BLOCK_SIZE / SECTOR_SIZE)))
+                               == (Fcb->Header.AllocationSize.QuadPart / BLOCK_SIZE));
+
+               ASSERT(FFSTotalBlocks(Vcb, (ULONG)(Fcb->Header.AllocationSize.QuadPart / BLOCK_SIZE))
+                               == (dinode1->di_blocks / (BLOCK_SIZE / SECTOR_SIZE)));
+       }
+
+
+       FFSv1SaveInode(IrpContext, Vcb, Fcb->FFSMcb->Inode, dinode1);
+
+       if (bRet && dwNewBlk)
+       {
+               if (dwRet)
+               {
+                       Fcb->BlkHint = dwNewBlk+1;
+                       *dwRet = dwNewBlk;
+
+                       FFSPrint((DBG_INFO, "FFSExpandInode: %S (%xh) i=%2.2xh Index=%8.8xh New Block=%8.8xh\n", Fcb->FFSMcb->ShortName.Buffer, Fcb->FFSMcb->Inode, i, Index, dwNewBlk));
+               }
+
+               return TRUE;
+       }
+
+       return FALSE;
+}
+
+
+NTSTATUS
+FFSNewInode(
+       PFFS_IRP_CONTEXT IrpContext,
+       PFFS_VCB         Vcb,
+       ULONG            GroupHint,
+       ULONG            Type,
+       PULONG           Inode)
+{
+       RTL_BITMAP      InodeBitmap;
+       PVOID           BitmapCache;
+       PBCB            BitmapBcb;
+
+       ULONG           Group, i, j;
+       ULONG           Average, Length;
+       LARGE_INTEGER   Offset;
+
+       ULONG           dwInode;
+
+    PAGED_CODE();
+
+#if 0
+       *Inode = dwInode = 0XFFFFFFFF;
+
+repeat:
+
+       Group = i = 0;
+
+       if (Type == DT_DIR)
+       {
+               Average = Vcb->ffs_super_block->s_free_inodes_count / Vcb->ffs_groups;
+
+               for (j = 0; j < Vcb->ffs_groups; j++)
+               {
+                       i = (j + GroupHint) % (Vcb->ffs_groups);
+
+                       if ((Vcb->ffs_group_desc[i].bg_used_dirs_count << 8) < 
+                                       Vcb->ffs_group_desc[i].bg_free_inodes_count)
+                       {
+                               Group = i + 1;
+                               break;
+                       }
+               }
+
+               if (!Group)
+               {
+                       for (j = 0; j < Vcb->ffs_groups; j++)
+                       {
+                               if (Vcb->ffs_group_desc[j].bg_free_inodes_count >= Average)
+                               {
+                                       if (!Group || (Vcb->ffs_group_desc[j].bg_free_blocks_count > Vcb->ffs_group_desc[Group].bg_free_blocks_count))
+                                               Group = j + 1;
+                               }
+                       }
+               }
+       }
+       else 
+       {
+               /*
+                * Try to place the inode in its parent directory (GroupHint)
+                */
+               if (Vcb->ffs_group_desc[GroupHint].bg_free_inodes_count)
+               {
+                       Group = GroupHint + 1;
+               }
+               else
+               {
+                       i = GroupHint;
+
+                       /*
+                        * Use a quadratic hash to find a group with a
+                        * free inode
+                        */
+                       for (j = 1; j < Vcb->ffs_groups; j <<= 1)
+                       {
+
+                               i += j;
+                               if (i > Vcb->ffs_groups) 
+                                       i -= Vcb->ffs_groups;
+
+                               if (Vcb->ffs_group_desc[i].bg_free_inodes_count)
+                               {
+                                       Group = i + 1;
+                                       break;
+                               }
+                       }
+               }
+
+               if (!Group) {
+                       /*
+                        * That failed: try linear search for a free inode
+                        */
+                       i = GroupHint + 1;
+                       for (j = 2; j < Vcb->ffs_groups; j++)
+                       {
+                               if (++i >= Vcb->ffs_groups) i = 0;
+
+                               if (Vcb->ffs_group_desc[i].bg_free_inodes_count)
+                               {
+                                       Group = i + 1;
+                                       break;
+                               }
+                       }
+               }
+       }
+
+       // Could not find a proper group.
+       if (!Group)
+       {
+               return STATUS_DISK_FULL;
+       }
+       else
+       {
+               Group--;
+
+               Offset.QuadPart = (LONGLONG) Vcb->BlockSize;
+               Offset.QuadPart = Offset.QuadPart * Vcb->ffs_group_desc[Group].bg_inode_bitmap;
+
+               if (Vcb->ffs_groups == 1)
+               {
+                       Length = INODES_COUNT;
+               }
+               else
+               {
+                       if (Group == Vcb->ffs_groups - 1)
+                       {
+                               Length = INODES_COUNT % INODES_PER_GROUP;
+                               if (!Length) 
+                               {
+                                       /* INODES_COUNT is integer multiple of INODES_PER_GROUP */
+                                       Length = INODES_PER_GROUP;
+                               }
+                       }
+                       else
+                       {
+                               Length = INODES_PER_GROUP;
+                       }
+               }
+
+               if (!CcPinRead(Vcb->StreamObj,
+                                       &Offset,
+                                       Vcb->BlockSize,
+                                       PIN_WAIT,
+                                       &BitmapBcb,
+                                       &BitmapCache))
+               {
+                       FFSPrint((DBG_ERROR, "FFSNewInode: PinReading error ...\n"));
+
+                       return STATUS_UNSUCCESSFUL;
+               }
+
+               RtlInitializeBitMap(&InodeBitmap,
+                               BitmapCache,
+                               Length);
+
+               dwInode = RtlFindClearBits(&InodeBitmap, 1, 0);
+
+               if (dwInode == 0xFFFFFFFF)
+               {
+                       CcUnpinData(BitmapBcb);
+                       BitmapBcb = NULL;
+                       BitmapCache = NULL;
+
+                       RtlZeroMemory(&InodeBitmap, sizeof(RTL_BITMAP));
+               }
+       }
+
+       if (dwInode == 0xFFFFFFFF || dwInode >= Length)
+       {
+               if (Vcb->ffs_group_desc[Group].bg_free_inodes_count != 0)
+               {
+                       Vcb->ffs_group_desc[Group].bg_free_inodes_count = 0;
+
+                       FFSSaveGroup(IrpContext, Vcb);            
+               }
+
+               goto repeat;
+       }
+       else
+       {
+               RtlSetBits(&InodeBitmap, dwInode, 1);
+
+               CcSetDirtyPinnedData(BitmapBcb, NULL);
+
+               FFSRepinBcb(IrpContext, BitmapBcb);
+
+               CcUnpinData(BitmapBcb);
+
+               FFSAddMcbEntry(Vcb, Offset.QuadPart, (LONGLONG)Vcb->BlockSize);
+
+               *Inode = dwInode + 1 + Group * INODES_PER_GROUP;
+
+               //Updating Group Desc / Superblock
+               Vcb->ffs_group_desc[Group].bg_free_inodes_count--;
+               if (Type == FFS_FT_DIR)
+               {
+                       Vcb->ffs_group_desc[Group].bg_used_dirs_count++;
+               }
+
+               FFSSaveGroup(IrpContext, Vcb);
+
+               Vcb->ffs_super_block->s_free_inodes_count--;
+               FFSSaveSuper(IrpContext, Vcb);
+
+               return STATUS_SUCCESS;        
+       }
+
+       return STATUS_DISK_FULL;
+#endif
+       return STATUS_UNSUCCESSFUL;
+}
+
+
+BOOLEAN
+FFSFreeInode(
+       PFFS_IRP_CONTEXT IrpContext,
+       PFFS_VCB         Vcb,
+       ULONG            Inode,
+       ULONG            Type)
+{
+       RTL_BITMAP      InodeBitmap;
+       PVOID           BitmapCache;
+       PBCB            BitmapBcb;
+
+       ULONG           Group;
+       ULONG           Length;
+       LARGE_INTEGER   Offset;
+
+       ULONG           dwIno;
+       BOOLEAN         bModified = FALSE;
+
+    PAGED_CODE();
+
+#if 0
+       Group = (Inode - 1) / INODES_PER_GROUP;
+       dwIno = (Inode - 1) % INODES_PER_GROUP;
+
+       FFSPrint((DBG_INFO, "FFSFreeInode: Inode: %xh (Group/Off = %xh/%xh)\n",
+                               Inode, Group, dwIno));
+
+       {
+               Offset.QuadPart = (LONGLONG) Vcb->BlockSize;
+               Offset.QuadPart = Offset.QuadPart * Vcb->ffs_group_desc[Group].bg_inode_bitmap;
+               if (Group == Vcb->ffs_groups - 1)
+               {
+                       Length = INODES_COUNT % INODES_PER_GROUP;
+                       if (!Length)
+                       { /* s_inodes_count is integer multiple of s_inodes_per_group */
+                               Length = INODES_PER_GROUP;
+                       }
+               }
+               else
+               {
+                       Length = INODES_PER_GROUP;
+               }
+
+               if (!CcPinRead(Vcb->StreamObj,
+                                       &Offset,
+                                       Vcb->BlockSize,
+                                       PIN_WAIT,
+                                       &BitmapBcb,
+                                       &BitmapCache))
+               {
+                       FFSPrint((DBG_ERROR, "FFSFreeInode: PinReading error ...\n"));
+                       return FALSE;
+               }
+
+               RtlInitializeBitMap(&InodeBitmap,
+                               BitmapCache,
+                               Length);
+
+               if (RtlCheckBit(&InodeBitmap, dwIno) == 0)
+               {
+
+               }
+               else
+               {
+                       RtlClearBits(&InodeBitmap, dwIno, 1);
+                       bModified = TRUE;
+               }
+
+               if (!bModified)
+               {
+                       CcUnpinData(BitmapBcb);
+                       BitmapBcb = NULL;
+                       BitmapCache = NULL;
+
+                       RtlZeroMemory(&InodeBitmap, sizeof(RTL_BITMAP));
+               }
+       }
+
+       if (bModified)
+       {
+               CcSetDirtyPinnedData(BitmapBcb, NULL);
+
+               FFSRepinBcb(IrpContext, BitmapBcb);
+
+               CcUnpinData(BitmapBcb);
+
+               FFSAddMcbEntry(Vcb, Offset.QuadPart, (LONGLONG)Vcb->BlockSize);
+
+               //Updating Group Desc / Superblock
+               if (Type == DT_DIR)
+               {
+                       Vcb->ffs_group_desc[Group].bg_used_dirs_count--;
+               }
+
+               Vcb->ffs_group_desc[Group].bg_free_inodes_count++;
+               FFSSaveGroup(IrpContext, Vcb);
+
+               Vcb->ffs_super_block->s_free_inodes_count++;
+               FFSSaveSuper(IrpContext, Vcb);
+
+               return TRUE;
+       }
+#endif
+       return FALSE;
+}
+
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSAddEntry(
+       IN PFFS_IRP_CONTEXT IrpContext,
+       IN PFFS_VCB         Vcb,
+       IN PFFS_FCB         Dcb,
+       IN ULONG            FileType,
+       IN ULONG            Inode,
+       IN PUNICODE_STRING  FileName)
+{
+       NTSTATUS                Status = STATUS_UNSUCCESSFUL;
+
+       PFFS_DIR_ENTRY          pDir = NULL;
+       PFFS_DIR_ENTRY          pNewDir = NULL;
+       PFFS_DIR_ENTRY          pTarget = NULL;
+
+       ULONG                   Length = 0;
+       ULONG                   dwBytes = 0;
+
+       BOOLEAN                 bFound = FALSE;
+       BOOLEAN                 bAdding = FALSE;
+
+       BOOLEAN                 MainResourceAcquired = FALSE;
+
+       ULONG                   dwRet;
+
+    PAGED_CODE();
+
+       if (!IsDirectory(Dcb))
+       {
+               FFSBreakPoint();
+               Status = STATUS_INVALID_PARAMETER;
+               return Status;
+       }
+
+       MainResourceAcquired = ExAcquireResourceExclusiveLite(&Dcb->MainResource, TRUE);
+
+       _SEH2_TRY
+       {
+               Dcb->ReferenceCount++;
+
+               pDir = (PFFS_DIR_ENTRY)ExAllocatePoolWithTag(PagedPool,
+                               FFS_DIR_REC_LEN(FFS_NAME_LEN), FFS_POOL_TAG);
+               if (!pDir)
+               {
+                       Status = STATUS_INSUFFICIENT_RESOURCES;
+                       _SEH2_LEAVE;
+               }
+
+               pTarget = (PFFS_DIR_ENTRY)ExAllocatePoolWithTag(PagedPool,
+                               2 * FFS_DIR_REC_LEN(FFS_NAME_LEN), FFS_POOL_TAG);
+               if (!pTarget)
+               {
+                       Status = STATUS_INSUFFICIENT_RESOURCES;
+                       _SEH2_LEAVE;
+               }
+
+#if 0
+               if (IsFlagOn(SUPER_BLOCK->s_feature_incompat, 
+                                       FFS_FEATURE_INCOMPAT_FILETYPE))
+               {
+                       pDir->d_type = (UCHAR)FileType;
+               }
+               else
+#endif
+               {
+                       pDir->d_type = 0;
+               }
+
+               {
+                       OEM_STRING OemName;
+                       OemName.Buffer = pDir->d_name;
+                       OemName.MaximumLength = FFS_NAME_LEN;
+                       OemName.Length = 0;
+
+                       Status = FFSUnicodeToOEM(&OemName, FileName);
+
+                       if (!NT_SUCCESS(Status))
+                       {
+                               _SEH2_LEAVE;
+                       }
+
+                       pDir->d_namlen = (CCHAR)OemName.Length;
+               }
+
+               pDir->d_ino  = Inode;
+               pDir->d_reclen = (USHORT)(FFS_DIR_REC_LEN(pDir->d_namlen));
+
+               dwBytes = 0;
+
+Repeat:
+
+               while ((LONGLONG)dwBytes < Dcb->Header.AllocationSize.QuadPart)
+               {
+                       RtlZeroMemory(pTarget, FFS_DIR_REC_LEN(FFS_NAME_LEN));
+
+                       // Reading the DCB contents
+                       Status = FFSv1ReadInode(
+                                               NULL,
+                                               Vcb,
+                                               Dcb->dinode1,
+                                               dwBytes,
+                                               (PVOID)pTarget,
+                                               FFS_DIR_REC_LEN(FFS_NAME_LEN),
+                                               &dwRet);
+
+                       if (!NT_SUCCESS(Status))
+                       {
+                               FFSPrint((DBG_ERROR, "FFSAddDirectory: Reading Directory Content error.\n"));
+                               _SEH2_LEAVE;
+                       }
+
+                       if (((pTarget->d_ino == 0) && pTarget->d_reclen >= pDir->d_reclen) || 
+                                       (pTarget->d_reclen >= FFS_DIR_REC_LEN(pTarget->d_namlen) + pDir->d_reclen))
+                       {
+                               if (pTarget->d_ino)
+                               {
+                                       RtlZeroMemory(pTarget, 2 * FFS_DIR_REC_LEN(FFS_NAME_LEN));
+
+                                       // Reading the DCB contents
+                                       Status = FFSv1ReadInode(
+                                                       NULL,
+                                                       Vcb,
+                                                       Dcb->dinode1,
+                                                       dwBytes,
+                                                       (PVOID)pTarget,
+                                                       2 * FFS_DIR_REC_LEN(FFS_NAME_LEN),
+                                                       &dwRet);
+
+                                       if (!NT_SUCCESS(Status))
+                                       {
+                                               FFSPrint((DBG_ERROR, "FFSAddDirectory: Reading Directory Content error.\n"));
+                                               _SEH2_LEAVE;
+                                       }
+
+                                       Length = FFS_DIR_REC_LEN(pTarget->d_namlen);
+
+                                       pNewDir = (PFFS_DIR_ENTRY) ((PUCHAR)pTarget + FFS_DIR_REC_LEN(pTarget->d_namlen));
+
+                                       pNewDir->d_reclen = pTarget->d_reclen - FFS_DIR_REC_LEN(pTarget->d_namlen);
+
+                                       pTarget->d_reclen = FFS_DIR_REC_LEN(pTarget->d_namlen);
+                               }
+                               else
+                               {
+                                       pNewDir = pTarget;
+                                       pNewDir->d_reclen = (USHORT)((ULONG)(Dcb->Header.AllocationSize.QuadPart) - dwBytes);
+                               }
+
+                               pNewDir->d_type = pDir->d_type;
+                               pNewDir->d_ino = pDir->d_ino;
+                               pNewDir->d_namlen = pDir->d_namlen;
+                               memcpy(pNewDir->d_name, pDir->d_name, pDir->d_namlen);
+                               Length += FFS_DIR_REC_LEN(pDir->d_namlen);
+
+                               bFound = TRUE;
+                               break;
+                       }
+
+                       dwBytes += pTarget->d_reclen;
+               }
+
+               if (bFound)
+               {
+                       ULONG dwRet;
+
+                       if (FileType == DT_DIR)
+                       {
+                               if(((pDir->d_namlen == 1) && (pDir->d_name[0] == '.')) ||
+                                               ((pDir->d_namlen == 2) && (pDir->d_name[0] == '.') && (pDir->d_name[1] == '.')))
+                               {
+                               }
+                               else
+                               {
+                                       Dcb->dinode1->di_nlink++;
+                               }
+                       }
+
+                       Status = FFSv1WriteInode(IrpContext, Vcb, Dcb->dinode1, dwBytes, pTarget, Length, FALSE, &dwRet);
+               }
+               else
+               {
+                       // We should expand the size of the dir inode 
+                       if (!bAdding)
+                       {
+                               ULONG dwRet;
+
+                               bAdding = FFSExpandInode(IrpContext, Vcb, Dcb, &dwRet);
+
+                               if (bAdding)
+                               {
+
+                                       Dcb->dinode1->di_size = Dcb->Header.AllocationSize.LowPart;
+
+                                       FFSv1SaveInode(IrpContext, Vcb, Dcb->FFSMcb->Inode, Dcb->dinode1);
+
+                                       Dcb->Header.FileSize = Dcb->Header.AllocationSize;
+
+                                       goto Repeat;
+                               }
+
+                               _SEH2_LEAVE;
+
+                       }
+                       else  // Something must be error!
+                       {
+                               _SEH2_LEAVE;
+                       }
+               }
+       }
+
+       _SEH2_FINALLY
+       {
+
+               Dcb->ReferenceCount--;
+
+               if(MainResourceAcquired)
+               {
+                       ExReleaseResourceForThreadLite(
+                                       &Dcb->MainResource,
+                                       ExGetCurrentResourceThread());
+               }
+
+               if (pTarget != NULL)
+               {
+                       ExFreePool(pTarget);
+               }
+
+               if (pDir)
+               {
+                       ExFreePool(pDir);
+               }
+       } _SEH2_END;
+
+       return Status;
+}
+
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSRemoveEntry(
+       IN PFFS_IRP_CONTEXT IrpContext,
+       IN PFFS_VCB         Vcb,
+       IN PFFS_FCB         Dcb,
+       IN ULONG            FileType,
+       IN ULONG            Inode)
+{
+       NTSTATUS                Status = STATUS_UNSUCCESSFUL;
+
+       PFFS_DIR_ENTRY          pTarget = NULL;
+       PFFS_DIR_ENTRY          pPrevDir = NULL;
+
+       USHORT                  PrevRecLen = 0;
+
+       ULONG                   Length = 0;
+       ULONG                   dwBytes = 0;
+
+       BOOLEAN                 bRet = FALSE;
+       BOOLEAN                 MainResourceAcquired = FALSE;
+
+       ULONG                   dwRet;
+
+    PAGED_CODE();
+
+       if (!IsDirectory(Dcb))
+       {
+               return FALSE;
+       }
+
+       MainResourceAcquired = 
+               ExAcquireResourceExclusiveLite(&Dcb->MainResource, TRUE);
+
+       _SEH2_TRY
+       {
+
+               Dcb->ReferenceCount++;
+
+               pTarget = (PFFS_DIR_ENTRY)ExAllocatePoolWithTag(PagedPool,
+                               FFS_DIR_REC_LEN(FFS_NAME_LEN), FFS_POOL_TAG);
+               if (!pTarget)
+               {
+                       Status = STATUS_INSUFFICIENT_RESOURCES;
+                       _SEH2_LEAVE;
+               }
+
+               pPrevDir = (PFFS_DIR_ENTRY)ExAllocatePoolWithTag(PagedPool,
+                               FFS_DIR_REC_LEN(FFS_NAME_LEN), FFS_POOL_TAG);
+               if (!pPrevDir)
+               {
+                       Status = STATUS_INSUFFICIENT_RESOURCES;
+                       _SEH2_LEAVE;
+               }
+
+               dwBytes = 0;
+
+               while ((LONGLONG)dwBytes < Dcb->Header.AllocationSize.QuadPart)
+               {
+                       RtlZeroMemory(pTarget, FFS_DIR_REC_LEN(FFS_NAME_LEN));
+
+                       Status = FFSv1ReadInode(
+                                               NULL,
+                                               Vcb,
+                                               Dcb->dinode1,
+                                               dwBytes,
+                                               (PVOID)pTarget,
+                                               FFS_DIR_REC_LEN(FFS_NAME_LEN),
+                                               &dwRet);
+
+                       if (!NT_SUCCESS(Status))
+                       {
+                               FFSPrint((DBG_ERROR, "FFSRemoveEntry: Reading Directory Content error.\n"));
+                               _SEH2_LEAVE;
+                       }
+
+                       if (pTarget->d_ino == Inode)
+                       {
+                               ULONG   dwRet;
+                               ULONG   RecLen;
+
+                               if ((PrevRecLen + pTarget->d_reclen) < MAXIMUM_RECORD_LENGTH)
+                               {
+                                       pPrevDir->d_reclen += pTarget->d_reclen;
+                                       RecLen = FFS_DIR_REC_LEN(pTarget->d_namlen);
+
+                                       RtlZeroMemory(pTarget, RecLen);
+
+                                       FFSv1WriteInode(IrpContext, Vcb, Dcb->dinode1, dwBytes - PrevRecLen, pPrevDir, 8, FALSE, &dwRet);
+                                       FFSv1WriteInode(IrpContext, Vcb, Dcb->dinode1, dwBytes, pTarget, RecLen, FALSE, &dwRet);
+                               }
+                               else
+                               {
+                                       RecLen = (ULONG)pTarget->d_reclen;
+                                       if (RecLen > FFS_DIR_REC_LEN(FFS_NAME_LEN))
+                                       {
+                                               RtlZeroMemory(pTarget, FFS_DIR_REC_LEN(FFS_NAME_LEN));
+                                       }
+                                       else
+                                       {
+                                               RtlZeroMemory(pTarget, RecLen);
+                                       }
+
+                                       pTarget->d_reclen = (USHORT)RecLen;
+
+                                       FFSv1WriteInode(IrpContext, Vcb, Dcb->dinode1, dwBytes, pTarget, RecLen, FALSE, &dwRet);
+                               }
+
+                               if (FileType == DT_DIR)
+                               {
+                                       if(((pTarget->d_namlen == 1) && (pTarget->d_name[0] == '.')) ||
+                                                       ((pTarget->d_namlen == 2) && (pTarget->d_name[0] == '.') && (pTarget->d_name[1] == '.')))
+                                       {
+                                               FFSBreakPoint();
+                                       }
+                                       else
+                                       {
+                                               Dcb->dinode1->di_nlink--;
+                                       }
+                               }
+
+                               /* Update at least mtime/atime if !FFS_FT_DIR. */
+                               FFSv1SaveInode(IrpContext, Vcb, Dcb->FFSMcb->Inode, Dcb->dinode1);
+
+                               bRet = TRUE;
+
+                               break;
+                       }
+                       else
+                       {
+                               RtlCopyMemory(pPrevDir, pTarget, FFS_DIR_REC_LEN(FFS_NAME_LEN));
+                               PrevRecLen = pTarget->d_reclen;
+                       }
+
+                       dwBytes += pTarget->d_reclen;
+               }
+       }
+
+       _SEH2_FINALLY
+       {
+
+               Dcb->ReferenceCount--;
+
+               if(MainResourceAcquired)
+                       ExReleaseResourceForThreadLite(
+                                       &Dcb->MainResource,
+                                       ExGetCurrentResourceThread());
+
+               if (pTarget != NULL)
+               {
+                       ExFreePool(pTarget);
+               }
+
+               if (pPrevDir != NULL)
+               {
+                       ExFreePool(pPrevDir);
+               }
+       } _SEH2_END;
+
+       return bRet;
+}
+
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSSetParentEntry(
+       IN PFFS_IRP_CONTEXT IrpContext,
+       IN PFFS_VCB         Vcb,
+       IN PFFS_FCB         Dcb,
+       IN ULONG            OldParent,
+       IN ULONG            NewParent)
+{
+       NTSTATUS                Status = STATUS_UNSUCCESSFUL;
+
+       PFFS_DIR_ENTRY          pSelf   = NULL;
+       PFFS_DIR_ENTRY          pParent = NULL;
+
+       ULONG                   dwBytes = 0;
+
+       BOOLEAN                 MainResourceAcquired = FALSE;
+
+       ULONG                   Offset = 0;
+
+       if (!IsDirectory(Dcb))
+       {
+               Status = STATUS_INVALID_PARAMETER;
+               return Status;
+       }
+
+       MainResourceAcquired = 
+               ExAcquireResourceExclusiveLite(&Dcb->MainResource, TRUE);
+
+       _SEH2_TRY
+       {
+               Dcb->ReferenceCount++;
+
+               pSelf = (PFFS_DIR_ENTRY)ExAllocatePoolWithTag(PagedPool,
+                               FFS_DIR_REC_LEN(1) + FFS_DIR_REC_LEN(2), FFS_POOL_TAG);
+               if (!pSelf)
+               {
+                       Status = STATUS_INSUFFICIENT_RESOURCES;
+                       _SEH2_LEAVE;
+               }
+
+               dwBytes = 0;
+
+               // Reading the DCB contents
+               Status = FFSv1ReadInode(
+                                       NULL,
+                                       Vcb,
+                                       Dcb->dinode1,
+                                       Offset,
+                                       (PVOID)pSelf,
+                                       FFS_DIR_REC_LEN(1) + FFS_DIR_REC_LEN(2),
+                                       &dwBytes);
+
+               if (!NT_SUCCESS(Status))
+               {
+                       FFSPrint((DBG_ERROR, "FFSSetParentEntry: Reading Directory Content error.\n"));
+                       _SEH2_LEAVE;
+               }
+
+               ASSERT(dwBytes == FFS_DIR_REC_LEN(1) + FFS_DIR_REC_LEN(2));
+
+               pParent = (PFFS_DIR_ENTRY)((PUCHAR)pSelf + pSelf->d_reclen);
+
+               if (pParent->d_ino != OldParent)
+               {
+                       FFSBreakPoint();
+               }
+
+               pParent->d_ino = NewParent;
+
+               Status = FFSv1WriteInode(IrpContext,
+                                       Vcb, 
+                                       Dcb->dinode1,
+                                       Offset,
+                                       pSelf,
+                                       dwBytes,
+                                       FALSE,
+                                       &dwBytes);
+       }
+
+       _SEH2_FINALLY
+       {
+               Dcb->ReferenceCount--;
+
+               if(MainResourceAcquired)
+               {
+                       ExReleaseResourceForThreadLite(
+                                       &Dcb->MainResource,
+                                       ExGetCurrentResourceThread());
+               }
+
+               if (pSelf)
+               {
+                       ExFreePool(pSelf);
+               }
+       } _SEH2_END;
+
+       return Status;
+}
+
+
+__drv_mustHoldCriticalRegion
+BOOLEAN
+FFSTruncateBlock(
+       IN PFFS_IRP_CONTEXT IrpContext,
+       IN PFFS_VCB         Vcb,
+       IN PFFS_FCB         Fcb,
+       IN ULONG            dwContent,
+       IN ULONG            Index,
+       IN ULONG            layer,
+       OUT BOOLEAN         *bFreed)
+{
+       ULONG       *pData = NULL;
+       ULONG       i = 0, j = 0, temp = 1;
+       BOOLEAN     bDirty = FALSE;
+       BOOLEAN     bRet = FALSE;
+       ULONG       dwBlk;
+
+       LONGLONG    Offset;
+
+       PBCB        Bcb;
+
+       PFFSv1_INODE dinode1 = Fcb->dinode1;
+
+    PAGED_CODE();
+
+       *bFreed = FALSE;
+
+       if (layer == 0)
+       {
+               //if (dwContent > 0 && dwContent < (BLOCKS_PER_GROUP * Vcb->ffs_groups))
+               if (dwContent > 0)
+               {
+                       bRet = FFSFreeBlock(IrpContext, Vcb, dwContent);
+
+                       if (bRet)
+                       {
+                               ASSERT(dinode1->di_blocks >= (Vcb->BlockSize / SECTOR_SIZE));
+                               dinode1->di_blocks -= (Vcb->BlockSize / SECTOR_SIZE);            
+                       }
+               }
+               else
+               {
+                       FFSBreakPoint();
+                       bRet = FALSE;
+               }
+
+               *bFreed = bRet;
+       }
+       else if (layer <= 3)
+       {
+               Offset = (LONGLONG)dwContent;
+               Offset = Offset * Vcb->BlockSize;
+
+               if(!CcPinRead(Vcb->StreamObj,
+                                       (PLARGE_INTEGER)(&Offset),
+                                       Vcb->BlockSize,
+                                       PIN_WAIT,
+                                       &Bcb,
+                                       &pData))
+               {
+                       FFSPrint((DBG_ERROR, "FFSSaveBuffer: PinReading error ...\n"));
+                       goto errorout;
+               }
+
+               temp = 1 << ((BLOCK_BITS - 2) * (layer - 1));
+
+               i = Index / temp;
+               j = Index % temp;
+
+               dwBlk = pData[i];
+
+               if(!FFSTruncateBlock(IrpContext, Vcb, Fcb, dwBlk, j, layer - 1, &bDirty))
+               {
+                       goto errorout;
+               }
+
+               if (bDirty)
+               {
+                       pData[i] = 0;
+               }
+
+               if (i == 0 && j == 0)
+               {
+                       CcUnpinData(Bcb);
+                       pData = NULL;
+
+                       *bFreed = TRUE;
+                       bRet = FFSFreeBlock(IrpContext, Vcb, dwContent);
+
+                       if (bRet)
+                       {
+                               ASSERT(dinode1->di_blocks >= (Vcb->BlockSize / SECTOR_SIZE));
+                               dinode1->di_blocks -= (Vcb->BlockSize / SECTOR_SIZE);
+                       }
+               }
+               else
+               {
+                       CcSetDirtyPinnedData(Bcb, NULL);
+                       FFSRepinBcb(IrpContext, Bcb);
+
+                       FFSAddMcbEntry(Vcb, Offset, (LONGLONG)Vcb->BlockSize);
+
+                       bRet = TRUE;
+                       *bFreed = FALSE;
+               }
+       }
+
+errorout:
+
+       if (pData)
+       {
+               CcUnpinData(Bcb);
+       }
+
+       return bRet;
+}
+
+
+BOOLEAN
+FFSTruncateInode(
+       IN PFFS_IRP_CONTEXT IrpContext,
+       IN PFFS_VCB         Vcb,
+       IN PFFS_FCB         Fcb)
+{
+       ULONG    dwSizes[FFS_BLOCK_TYPES];
+       ULONG    Index = 0;
+       ULONG    dwTotal = 0;
+       ULONG    dwBlk = 0;
+
+       ULONG    i;
+       BOOLEAN  bRet = FALSE;
+       BOOLEAN  bFreed = FALSE;
+
+       PFFSv1_INODE dinode1 = Fcb->dinode1;
+
+    PAGED_CODE();
+
+       Index = (ULONG)(Fcb->Header.AllocationSize.QuadPart >> BLOCK_BITS);
+
+       if (Index > 0) 
+       {
+               Index--;
+       }
+       else
+       {
+               return TRUE;
+       }
+
+       for (i = 0; i < FFS_BLOCK_TYPES; i++)
+       {
+               dwSizes[i] = Vcb->dwData[i];
+               dwTotal += dwSizes[i];
+       }
+
+       if (Index >= dwTotal)
+       {
+               FFSPrint((DBG_ERROR, "FFSTruncateInode: beyond the maxinum size of an inode.\n"));
+               return TRUE;
+       }
+
+       for (i = 0; i < FFS_BLOCK_TYPES; i++)
+       {
+#if 0
+               if (Index < dwSizes[i])
+               {
+                       dwBlk = Inode->i_block[i == 0 ? (Index) : (i + NDADDR - 1)];
+
+                       bRet = FFSTruncateBlock(IrpContext, Vcb, Fcb, dwBlk, Index , i, &bFreed); 
+
+                       if (bRet)
+                       {
+                               Fcb->Header.AllocationSize.QuadPart -= Vcb->BlockSize;
+
+                               if (bFreed)
+                               {
+                                       Inode->i_block[i == 0 ? (Index) : (i + NDADDR - 1)] = 0;
+                               }
+                       }
+
+                       break;
+               }
+#endif
+               Index -= dwSizes[i];
+       }
+
+       {
+               ASSERT(FFSDataBlocks(Vcb, (ULONG)(dinode1->di_blocks / (BLOCK_SIZE / SECTOR_SIZE)))
+                               == (Fcb->Header.AllocationSize.QuadPart / BLOCK_SIZE));
+
+               ASSERT(FFSTotalBlocks(Vcb, (ULONG)(Fcb->Header.AllocationSize.QuadPart / BLOCK_SIZE))
+                               == (dinode1->di_blocks / (BLOCK_SIZE / SECTOR_SIZE)));
+
+       }
+
+       //
+       // Inode struct saving is done externally.
+       //
+
+       FFSv1SaveInode(IrpContext, Vcb, Fcb->FFSMcb->Inode, dinode1);
+
+
+       return bRet;
+}
+
+#endif // !FFS_READ_ONLY
+
+__drv_mustHoldCriticalRegion
+BOOLEAN
+FFSAddMcbEntry(
+       IN PFFS_VCB Vcb,
+       IN LONGLONG Lba,
+       IN LONGLONG Length)
+{
+       BOOLEAN     bRet = FALSE;
+
+       LONGLONG    Offset;
+
+#if DBG
+       LONGLONG    DirtyLba;
+       LONGLONG    DirtyLen;
+#endif
+
+    PAGED_CODE();
+
+       Offset = Lba & (~((LONGLONG)BLOCK_SIZE - 1));
+
+       Length = (Length + Lba - Offset + BLOCK_SIZE - 1) &
+               (~((LONGLONG)BLOCK_SIZE - 1));
+
+       ASSERT ((Offset & (BLOCK_SIZE - 1)) == 0);
+       ASSERT ((Length & (BLOCK_SIZE - 1)) == 0);
+
+       Offset = (Offset >> BLOCK_BITS) + 1;
+       Length = (Length >>BLOCK_BITS);
+
+       ExAcquireResourceExclusiveLite(
+                       &(Vcb->McbResource),
+                       TRUE);
+
+       FFSPrint((DBG_INFO, "FFSAddMcbEntry: Lba=%I64xh Length=%I64xh\n",
+                               Offset, Length));
+
+#if DBG
+       bRet = FsRtlLookupLargeMcbEntry(
+                       &(Vcb->DirtyMcbs),
+                       Offset,
+                       &DirtyLba,
+                       &DirtyLen,
+                       NULL,
+                       NULL,
+                       NULL);
+
+       if (bRet && DirtyLba == Offset && DirtyLen >= Length)
+       {
+               FFSPrint((DBG_INFO, "FFSAddMcbEntry: this run already exists.\n"));
+       }
+#endif
+
+       _SEH2_TRY
+       {
+               bRet = FsRtlAddLargeMcbEntry(
+                               &(Vcb->DirtyMcbs),
+                               Offset, Offset,
+                               Length);
+
+       }
+       _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER)
+       {
+               FFSBreakPoint();
+               bRet = FALSE;
+       } _SEH2_END;
+
+#if DBG
+       if (bRet)
+       {
+               BOOLEAN     bFound = FALSE;
+               LONGLONG    RunStart;
+               LONGLONG    RunLength;
+               ULONG       Index;
+
+               bFound = FsRtlLookupLargeMcbEntry(
+                               &(Vcb->DirtyMcbs),
+                               Offset,
+                               &DirtyLba,
+                               &DirtyLen,
+                               &RunStart,
+                               &RunLength,
+                               &Index);
+
+               if ((!bFound) || (DirtyLba == -1) ||
+                               (DirtyLba != Offset) || (DirtyLen < Length))
+               {
+                       LONGLONG            DirtyVba;
+                       LONGLONG            DirtyLba;
+                       LONGLONG            DirtyLength;
+
+                       FFSBreakPoint();
+
+                       for (Index = 0; 
+                                       FsRtlGetNextLargeMcbEntry(&(Vcb->DirtyMcbs),
+                                               Index,
+                                               &DirtyVba,
+                                               &DirtyLba,
+                                               &DirtyLength); 
+                                       Index++)
+                       {
+                               FFSPrint((DBG_INFO, "Index = %xh\n", Index));
+                               FFSPrint((DBG_INFO, "DirtyVba = %I64xh\n", DirtyVba));
+                               FFSPrint((DBG_INFO, "DirtyLba = %I64xh\n", DirtyLba));
+                               FFSPrint((DBG_INFO, "DirtyLen = %I64xh\n\n", DirtyLength));
+                       }
+               }
+       }
+#endif
+
+       ExReleaseResourceForThreadLite(
+                       &(Vcb->McbResource),
+                       ExGetCurrentResourceThread());
+
+       return bRet;
+}
+
+
+__drv_mustHoldCriticalRegion
+VOID
+FFSRemoveMcbEntry(
+       IN PFFS_VCB Vcb,
+       IN LONGLONG Lba,
+       IN LONGLONG Length)
+{
+       LONGLONG Offset;
+
+    PAGED_CODE();
+
+       Offset = Lba & (~((LONGLONG)BLOCK_SIZE - 1));
+
+       Length = (Length + Lba - Offset + BLOCK_SIZE - 1) &
+               (~((LONGLONG)BLOCK_SIZE - 1));
+
+       ASSERT(Offset == Lba);
+
+       ASSERT ((Offset & (BLOCK_SIZE - 1)) == 0);
+       ASSERT ((Length & (BLOCK_SIZE - 1)) == 0);
+
+       Offset = (Offset >> BLOCK_BITS) + 1;
+       Length = (Length >> BLOCK_BITS);
+
+       FFSPrint((DBG_INFO, "FFSRemoveMcbEntry: Lba=%I64xh Length=%I64xh\n",
+                               Offset, Length));
+
+       ExAcquireResourceExclusiveLite(
+                       &(Vcb->McbResource),
+                       TRUE);
+
+       _SEH2_TRY
+       {
+               FsRtlRemoveLargeMcbEntry(
+                               &(Vcb->DirtyMcbs),
+                               Offset, Length);
+
+       }
+       _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER)
+       {
+               FFSBreakPoint();
+       } _SEH2_END;
+
+#if DBG
+       {
+               BOOLEAN  bFound = FALSE;
+               LONGLONG DirtyLba, DirtyLen;
+
+               bFound = FsRtlLookupLargeMcbEntry(
+                                       &(Vcb->DirtyMcbs),
+                                       Offset,
+                                       &DirtyLba,
+                                       &DirtyLen,
+                                       NULL,
+                                       NULL,
+                                       NULL);
+
+               if (bFound &&(DirtyLba != -1))
+               {
+                       FFSBreakPoint();
+               }
+       }
+#endif
+
+       ExReleaseResourceForThreadLite(
+                       &(Vcb->McbResource),
+                       ExGetCurrentResourceThread());
+}
+
+
+__drv_mustHoldCriticalRegion
+BOOLEAN
+FFSLookupMcbEntry(
+       IN PFFS_VCB     Vcb,
+       IN LONGLONG     Lba,
+       OUT PLONGLONG   pLba,
+       OUT PLONGLONG   pLength,
+       OUT PLONGLONG   RunStart,
+       OUT PLONGLONG   RunLength,
+       OUT PULONG      Index)
+{
+       BOOLEAN     bRet;
+       LONGLONG    Offset;
+
+    PAGED_CODE();
+
+       Offset = Lba & (~((LONGLONG)BLOCK_SIZE - 1));
+       ASSERT ((Offset & (BLOCK_SIZE - 1)) == 0);
+
+       ASSERT(Lba == Offset);
+
+       Offset = (Offset >> BLOCK_BITS) + 1;
+
+       ExAcquireResourceExclusiveLite(
+                       &(Vcb->McbResource),
+                       TRUE);
+
+       bRet = FsRtlLookupLargeMcbEntry(
+                       &(Vcb->DirtyMcbs),
+                       Offset,
+                       pLba,
+                       pLength,
+                       RunStart,
+                       RunLength,
+                       Index);
+
+       ExReleaseResourceForThreadLite(
+                       &(Vcb->McbResource),
+                       ExGetCurrentResourceThread());
+
+       if (bRet)
+       {
+               if (pLba && ((*pLba) != -1))
+               {
+                       ASSERT((*pLba) > 0);
+
+                       (*pLba) = (((*pLba) - 1) << BLOCK_BITS);
+                       (*pLba) += ((Lba) & ((LONGLONG)BLOCK_SIZE - 1));
+               }
+
+               if (pLength)
+               {
+                       (*pLength) <<= BLOCK_BITS;
+                       (*pLength)  -= ((Lba) & ((LONGLONG)BLOCK_SIZE - 1));
+               }
+
+               if (RunStart && (*RunStart != -1))
+               {
+                       (*RunStart) = (((*RunStart) - 1) << BLOCK_BITS);
+               }
+
+               if (RunLength)
+               {
+                       (*RunLength) <<= BLOCK_BITS;
+               }
+       }
+
+       return bRet;
+}
+
+
+ULONG
+FFSDataBlocks(
+       PFFS_VCB Vcb,
+       ULONG TotalBlocks)
+{
+       ULONG   dwData[FFS_BLOCK_TYPES];
+       ULONG   dwMeta[FFS_BLOCK_TYPES];
+       ULONG   DataBlocks = 0;
+       ULONG   i, j;
+
+       if (TotalBlocks <= NDADDR)
+       {
+               return TotalBlocks;
+       }
+
+       TotalBlocks -= NDADDR;
+
+       for (i = 0; i < FFS_BLOCK_TYPES; i++)
+       {
+               if (i == 0)
+               {
+                       dwData[i] = 1;
+               }
+               else
+               {
+                       dwData[i] = Vcb->dwData[i];
+               }
+
+               dwMeta[i] = Vcb->dwMeta[i];
+       }
+
+       for(i = 1; (i < FFS_BLOCK_TYPES) && (TotalBlocks > 0); i++)
+       {
+               if (TotalBlocks >= (dwData[i] + dwMeta[i]))
+               {
+                       TotalBlocks -= (dwData[i] + dwMeta[i]);
+                       DataBlocks  += dwData[i];
+               }
+               else
+               {
+                       ULONG   dwDivide = 0;
+                       ULONG   dwRemain = 0;
+
+                       for (j = i; (j > 0) && (TotalBlocks > 0); j--)
+                       {
+                               dwDivide = (TotalBlocks - 1) / (dwData[j - 1] + dwMeta[j - 1]);
+                               dwRemain = (TotalBlocks - 1) % (dwData[j - 1] + dwMeta[j - 1]);
+
+                               DataBlocks += (dwDivide * dwData[j - 1]);
+                               TotalBlocks = dwRemain;
+                       }
+               }
+       }
+
+       return (DataBlocks + NDADDR);
+}
+
+
+ULONG
+FFSTotalBlocks(
+       PFFS_VCB Vcb,
+       ULONG DataBlocks)
+{
+       ULONG   dwData[FFS_BLOCK_TYPES];
+       ULONG   dwMeta[FFS_BLOCK_TYPES];
+       ULONG   TotalBlocks = 0;
+       ULONG   i, j;
+
+       if (DataBlocks <= NDADDR)
+       {
+               return DataBlocks;
+       }
+
+       DataBlocks -= NDADDR;
+
+       for (i = 0; i < FFS_BLOCK_TYPES; i++)
+       {
+               if (i == 0)
+               {
+                       dwData[i] = 1;
+               }
+               else
+               {
+                       dwData[i] = Vcb->dwData[i];
+               }
+
+               dwMeta[i] = Vcb->dwMeta[i];
+       }
+
+       for(i = 1; (i < FFS_BLOCK_TYPES) && (DataBlocks > 0); i++)
+       {
+               if (DataBlocks >= dwData[i])
+               {
+                       DataBlocks  -= dwData[i];
+                       TotalBlocks += (dwData[i] + dwMeta[i]);
+               }
+               else
+               {
+                       ULONG   dwDivide = 0;
+                       ULONG   dwRemain = 0;
+
+                       for (j = i; (j > 0) && (DataBlocks > 0); j--)
+                       {
+                               dwDivide = (DataBlocks) / (dwData[j - 1]);
+                               dwRemain = (DataBlocks) % (dwData[j - 1]);
+
+                               TotalBlocks += (dwDivide * (dwData[j - 1] + dwMeta[j - 1]) + 1);
+                               DataBlocks = dwRemain;
+                       }
+               }
+       }
+
+       return (TotalBlocks + NDADDR);
+}
diff --git a/reactos/drivers/filesystems/ffs/src/ffsdrv.rc b/reactos/drivers/filesystems/ffs/src/ffsdrv.rc
new file mode 100644 (file)
index 0000000..3ec0042
--- /dev/null
@@ -0,0 +1,112 @@
+//Microsoft Developer Studio generated resource script.
+//
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#define APSTUDIO_HIDDEN_SYMBOLS
+#include "windows.h"
+#undef APSTUDIO_HIDDEN_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifndef _MAC
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 0,5,3,0
+ PRODUCTVERSION 0,5,3,0
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x9L
+#else
+ FILEFLAGS 0x8L
+#endif
+ FILEOS 0x40004L
+ FILETYPE 0x3L
+ FILESUBTYPE 0x8L
+BEGIN
+    BLOCK "StringFileInfo"
+    BEGIN
+        BLOCK "000004b0"
+        BEGIN
+            VALUE "Comments", "\0"
+            VALUE "CompanyName", "PYRASIS.COM\0"
+            VALUE "FileDescription", "FFS File System Driver for Windows\0"
+            VALUE "FileVersion", "0, 5, 3, 0\0"
+            VALUE "InternalName", "ffs\0"
+            VALUE "LegalCopyright", "2004-2015 (C) Lee Jae-Hong. All rights reserved.\0"
+            VALUE "LegalTrademarks", "\0"
+            VALUE "OriginalFilename", "ffs.sys\0"
+            VALUE "PrivateBuild", "2015.10.2\0"
+            VALUE "ProductName", "FFS Driver\0"
+            VALUE "ProductVersion", "0, 5, 3, 0\0"
+            VALUE "SpecialBuild", "\0"
+        END
+    END
+    BLOCK "VarFileInfo"
+    BEGIN
+        VALUE "Translation", 0x0, 1200
+    END
+END
+
+#endif    // !_MAC
+
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE 
+BEGIN
+    "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE 
+BEGIN
+    "#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
+    "#include ""windows.h""\r\n"
+    "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
+    "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE 
+BEGIN
+    "\r\n"
+    "\0"
+END
+
+#endif    // APSTUDIO_INVOKED
+
+#endif    // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif    // not APSTUDIO_INVOKED
+
diff --git a/reactos/drivers/filesystems/ffs/src/fileinfo.c b/reactos/drivers/filesystems/ffs/src/fileinfo.c
new file mode 100644 (file)
index 0000000..09b6353
--- /dev/null
@@ -0,0 +1,1789 @@
+/* 
+ * FFS File System Driver for Windows
+ *
+ * fileinfo.c
+ *
+ * 2004.5.6 ~
+ *
+ * Lee Jae-Hong, http://www.pyrasis.com
+ *
+ * See License.txt
+ *
+ */
+
+#include "ntifs.h"
+#include "ffsdrv.h"
+
+/* Globals */
+
+extern PFFS_GLOBAL FFSGlobal;
+
+
+/* Definitions */
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE, FFSQueryInformation)
+#pragma alloc_text(PAGE, FFSSetInformation)
+#pragma alloc_text(PAGE, FFSExpandFile)
+#pragma alloc_text(PAGE, FFSTruncateFile)
+#pragma alloc_text(PAGE, FFSSetDispositionInfo)
+#pragma alloc_text(PAGE, FFSSetRenameInfo)
+#pragma alloc_text(PAGE, FFSDeleteFile)
+#endif
+
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSQueryInformation(
+       IN PFFS_IRP_CONTEXT IrpContext)
+{
+       PDEVICE_OBJECT          DeviceObject;
+       NTSTATUS                Status = STATUS_UNSUCCESSFUL;
+       PFILE_OBJECT            FileObject;
+       PFFS_VCB                Vcb;
+       PFFS_FCB                Fcb = 0;
+       PFFS_CCB                Ccb;
+       PIRP                    Irp;
+       PIO_STACK_LOCATION      IoStackLocation;
+       FILE_INFORMATION_CLASS  FileInformationClass;
+       ULONG                   Length;
+       PVOID                   Buffer;
+       BOOLEAN                 FcbResourceAcquired = FALSE;
+
+    PAGED_CODE();
+
+       _SEH2_TRY
+       {
+               ASSERT(IrpContext != NULL);
+
+               ASSERT((IrpContext->Identifier.Type == FFSICX) &&
+                               (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
+
+               DeviceObject = IrpContext->DeviceObject;
+
+               //
+               // This request is not allowed on the main device object
+               //
+               if (DeviceObject == FFSGlobal->DeviceObject)
+               {
+                       Status = STATUS_INVALID_DEVICE_REQUEST;
+                       _SEH2_LEAVE;
+               }
+
+               FileObject = IrpContext->FileObject;
+
+               Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;
+
+               ASSERT(Vcb != NULL);
+
+               Fcb = (PFFS_FCB)FileObject->FsContext;
+
+               ASSERT(Fcb != NULL);
+
+               //
+               // This request is not allowed on volumes
+               //
+               if (Fcb->Identifier.Type == FFSVCB)
+               {
+                       Status = STATUS_INVALID_PARAMETER;
+                       _SEH2_LEAVE;
+               }
+
+               ASSERT((Fcb->Identifier.Type == FFSFCB) &&
+                               (Fcb->Identifier.Size == sizeof(FFS_FCB)));
+               /*        
+               if (!IsFlagOn(Fcb->Vcb->Flags, VCB_READ_ONLY) &&
+                       !FlagOn(Fcb->Flags, FCB_PAGE_FILE))
+               */
+               {
+                       if (!ExAcquireResourceSharedLite(
+                                               &Fcb->MainResource,
+                                               IrpContext->IsSynchronous))
+                       {
+                               Status = STATUS_PENDING;
+                               _SEH2_LEAVE;
+                       }
+
+                       FcbResourceAcquired = TRUE;
+               }
+
+               Ccb = (PFFS_CCB)FileObject->FsContext2;
+
+               ASSERT(Ccb != NULL);
+
+               ASSERT((Ccb->Identifier.Type == FFSCCB) &&
+                               (Ccb->Identifier.Size == sizeof(FFS_CCB)));
+
+               Irp = IrpContext->Irp;
+
+               IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
+
+               FileInformationClass =
+                       IoStackLocation->Parameters.QueryFile.FileInformationClass;
+
+               Length = IoStackLocation->Parameters.QueryFile.Length;
+
+               Buffer = Irp->AssociatedIrp.SystemBuffer;
+
+               RtlZeroMemory(Buffer, Length);
+
+               switch (FileInformationClass)
+               {
+                       case FileBasicInformation:
+                               {
+                                       PFILE_BASIC_INFORMATION FileBasicInformation;
+
+                                       if (Length < sizeof(FILE_BASIC_INFORMATION))
+                                       {
+                                               Status = STATUS_INFO_LENGTH_MISMATCH;
+                                               _SEH2_LEAVE;
+                                       }
+
+                                       FileBasicInformation = (PFILE_BASIC_INFORMATION)Buffer;
+
+                                       if (FS_VERSION == 1)
+                                       {
+                                               FileBasicInformation->CreationTime = FFSSysTime(Fcb->dinode1->di_ctime);
+
+                                               FileBasicInformation->LastAccessTime = FFSSysTime(Fcb->dinode1->di_atime);
+
+                                               FileBasicInformation->LastWriteTime = FFSSysTime(Fcb->dinode1->di_mtime);
+
+                                               FileBasicInformation->ChangeTime = FFSSysTime(Fcb->dinode1->di_mtime);
+                                       }
+                                       else
+                                       {
+                                               FileBasicInformation->CreationTime = FFSSysTime((ULONG)Fcb->dinode2->di_ctime);
+
+                                               FileBasicInformation->LastAccessTime = FFSSysTime((ULONG)Fcb->dinode2->di_atime);
+
+                                               FileBasicInformation->LastWriteTime = FFSSysTime((ULONG)Fcb->dinode2->di_mtime);
+
+                                               FileBasicInformation->ChangeTime = FFSSysTime((ULONG)Fcb->dinode2->di_mtime);
+                                       }
+
+                                       FileBasicInformation->FileAttributes = Fcb->FFSMcb->FileAttr;
+
+                                       Irp->IoStatus.Information = sizeof(FILE_BASIC_INFORMATION);
+                                       Status = STATUS_SUCCESS;
+                                       _SEH2_LEAVE;
+                               }
+
+#if (_WIN32_WINNT >= 0x0500)
+
+                       case FileAttributeTagInformation:
+                               {
+                                       PFILE_ATTRIBUTE_TAG_INFORMATION FATI;
+
+                                       if (Length < sizeof(FILE_ATTRIBUTE_TAG_INFORMATION))
+                                       {
+                                               Status = STATUS_INFO_LENGTH_MISMATCH;
+                                               _SEH2_LEAVE;
+                                       }
+
+                                       FATI = (PFILE_ATTRIBUTE_TAG_INFORMATION) Buffer;
+
+                                       FATI->FileAttributes = Fcb->FFSMcb->FileAttr;
+                                       FATI->ReparseTag = 0;
+
+                                       Irp->IoStatus.Information = sizeof(FILE_ATTRIBUTE_TAG_INFORMATION);
+                                       Status = STATUS_SUCCESS;
+                                       _SEH2_LEAVE;
+                               }
+#endif // (_WIN32_WINNT >= 0x0500)
+
+                       case FileStandardInformation:
+                               {
+                                       PFILE_STANDARD_INFORMATION FileStandardInformation;
+
+                                       if (Length < sizeof(FILE_STANDARD_INFORMATION))
+                                       {
+                                               Status = STATUS_INFO_LENGTH_MISMATCH;
+                                               _SEH2_LEAVE;
+                                       }
+
+                                       FileStandardInformation = (PFILE_STANDARD_INFORMATION)Buffer;
+
+                                       if (FS_VERSION == 1)
+                                       {
+                                               FileStandardInformation->AllocationSize.QuadPart =
+                                                       (LONGLONG)(Fcb->dinode1->di_size);
+
+                                               FileStandardInformation->EndOfFile.QuadPart =
+                                                       (LONGLONG)(Fcb->dinode1->di_size);
+
+                                               FileStandardInformation->NumberOfLinks = Fcb->dinode1->di_nlink;
+                                       }
+                                       else
+                                       {
+                                               FileStandardInformation->AllocationSize.QuadPart =
+                                                       (LONGLONG)(Fcb->dinode2->di_size);
+
+                                               FileStandardInformation->EndOfFile.QuadPart =
+                                                       (LONGLONG)(Fcb->dinode2->di_size);
+
+                                               FileStandardInformation->NumberOfLinks = Fcb->dinode2->di_nlink;
+                                       }
+
+                                       if (IsFlagOn(Fcb->Vcb->Flags, VCB_READ_ONLY))
+                                               FileStandardInformation->DeletePending = FALSE;
+                                       else
+                                               FileStandardInformation->DeletePending = IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING);                
+
+                                       if (Fcb->FFSMcb->FileAttr & FILE_ATTRIBUTE_DIRECTORY)
+                                       {
+                                               FileStandardInformation->Directory = TRUE;
+                                       }
+                                       else
+                                       {
+                                               FileStandardInformation->Directory = FALSE;
+                                       }
+
+                                       Irp->IoStatus.Information = sizeof(FILE_STANDARD_INFORMATION);
+                                       Status = STATUS_SUCCESS;
+                                       _SEH2_LEAVE;
+                               }
+
+                       case FileInternalInformation:
+                               {
+                                       PFILE_INTERNAL_INFORMATION FileInternalInformation;
+
+                                       if (Length < sizeof(FILE_INTERNAL_INFORMATION))
+                                       {
+                                               Status = STATUS_INFO_LENGTH_MISMATCH;
+                                               _SEH2_LEAVE;
+                                       }
+
+                                       FileInternalInformation = (PFILE_INTERNAL_INFORMATION)Buffer;
+
+                                       // The "inode number"
+                                       FileInternalInformation->IndexNumber.QuadPart = (LONGLONG)Fcb->FFSMcb->Inode;
+
+                                       Irp->IoStatus.Information = sizeof(FILE_INTERNAL_INFORMATION);
+                                       Status = STATUS_SUCCESS;
+                                       _SEH2_LEAVE;
+                               }
+
+                       case FileEaInformation:
+                               {
+                                       PFILE_EA_INFORMATION FileEaInformation;
+
+                                       if (Length < sizeof(FILE_EA_INFORMATION))
+                                       {
+                                               Status = STATUS_INFO_LENGTH_MISMATCH;
+                                               _SEH2_LEAVE;
+                                       }
+
+                                       FileEaInformation = (PFILE_EA_INFORMATION)Buffer;
+
+                                       // Romfs doesn't have any extended attributes
+                                       FileEaInformation->EaSize = 0;
+
+                                       Irp->IoStatus.Information = sizeof(FILE_EA_INFORMATION);
+                                       Status = STATUS_SUCCESS;
+                                       _SEH2_LEAVE;
+                               }
+
+                       case FileNameInformation:
+                               {
+                                       PFILE_NAME_INFORMATION FileNameInformation;
+
+                                       if (Length < sizeof(FILE_NAME_INFORMATION) +
+                                                       Fcb->FFSMcb->ShortName.Length - sizeof(WCHAR))
+                                       {
+                                               Status = STATUS_INFO_LENGTH_MISMATCH;
+                                               _SEH2_LEAVE;
+                                       }
+
+                                       FileNameInformation = (PFILE_NAME_INFORMATION)Buffer;
+
+                                       FileNameInformation->FileNameLength = Fcb->FFSMcb->ShortName.Length;
+
+                                       RtlCopyMemory(
+                                                       FileNameInformation->FileName,
+                                                       Fcb->FFSMcb->ShortName.Buffer,
+                                                       Fcb->FFSMcb->ShortName.Length);
+
+                                       Irp->IoStatus.Information = sizeof(FILE_NAME_INFORMATION) +
+                                               Fcb->FFSMcb->ShortName.Length - sizeof(WCHAR);
+                                       Status = STATUS_SUCCESS;
+                                       _SEH2_LEAVE;
+                               }
+
+                       case FilePositionInformation:
+                               {
+                                       PFILE_POSITION_INFORMATION FilePositionInformation;
+
+                                       if (Length < sizeof(FILE_POSITION_INFORMATION))
+                                       {
+                                               Status = STATUS_INFO_LENGTH_MISMATCH;
+                                               _SEH2_LEAVE;
+                                       }
+
+                                       FilePositionInformation = (PFILE_POSITION_INFORMATION)Buffer;
+
+                                       FilePositionInformation->CurrentByteOffset =
+                                               FileObject->CurrentByteOffset;
+
+                                       Irp->IoStatus.Information = sizeof(FILE_POSITION_INFORMATION);
+                                       Status = STATUS_SUCCESS;
+                                       _SEH2_LEAVE;
+                               }
+
+                       case FileAllInformation:
+                               {
+                                       PFILE_ALL_INFORMATION       FileAllInformation;
+                                       PFILE_BASIC_INFORMATION     FileBasicInformation;
+                                       PFILE_STANDARD_INFORMATION  FileStandardInformation;
+                                       PFILE_INTERNAL_INFORMATION  FileInternalInformation;
+                                       PFILE_EA_INFORMATION        FileEaInformation;
+                                       PFILE_POSITION_INFORMATION  FilePositionInformation;
+                                       PFILE_NAME_INFORMATION      FileNameInformation;
+
+                                       if (Length < sizeof(FILE_ALL_INFORMATION))
+                                       {
+                                               Status = STATUS_INFO_LENGTH_MISMATCH;
+                                               _SEH2_LEAVE;
+                                       }
+
+                                       FileAllInformation = (PFILE_ALL_INFORMATION)Buffer;
+
+                                       FileBasicInformation =
+                                               &FileAllInformation->BasicInformation;
+
+                                       FileStandardInformation =
+                                               &FileAllInformation->StandardInformation;
+
+                                       FileInternalInformation =
+                                               &FileAllInformation->InternalInformation;
+
+                                       FileEaInformation =
+                                               &FileAllInformation->EaInformation;
+
+                                       FilePositionInformation =
+                                               &FileAllInformation->PositionInformation;
+
+                                       FileNameInformation =
+                                               &FileAllInformation->NameInformation;
+
+                                       if (FS_VERSION == 1)
+                                       {
+                                               FileBasicInformation->CreationTime = FFSSysTime(Fcb->dinode1->di_ctime);
+
+                                               FileBasicInformation->LastAccessTime = FFSSysTime(Fcb->dinode1->di_atime);
+
+                                               FileBasicInformation->LastWriteTime = FFSSysTime(Fcb->dinode1->di_mtime);
+
+                                               FileBasicInformation->ChangeTime = FFSSysTime(Fcb->dinode1->di_mtime);
+
+                                               FileBasicInformation->FileAttributes = Fcb->FFSMcb->FileAttr;
+
+                                               FileStandardInformation->AllocationSize.QuadPart =
+                                                       (LONGLONG)(Fcb->dinode1->di_size);
+
+                                               FileStandardInformation->EndOfFile.QuadPart =
+                                                       (LONGLONG)(Fcb->dinode1->di_size);
+
+                                               FileStandardInformation->NumberOfLinks = Fcb->dinode1->di_nlink;
+                                       }
+                                       else
+                                       {
+                                               FileBasicInformation->CreationTime = FFSSysTime((ULONG)Fcb->dinode2->di_ctime);
+
+                                               FileBasicInformation->LastAccessTime = FFSSysTime((ULONG)Fcb->dinode2->di_atime);
+
+                                               FileBasicInformation->LastWriteTime = FFSSysTime((ULONG)Fcb->dinode2->di_mtime);
+
+                                               FileBasicInformation->ChangeTime = FFSSysTime((ULONG)Fcb->dinode2->di_mtime);
+
+                                               FileBasicInformation->FileAttributes = Fcb->FFSMcb->FileAttr;
+
+                                               FileStandardInformation->AllocationSize.QuadPart =
+                                                       (LONGLONG)(Fcb->dinode2->di_size);
+
+                                               FileStandardInformation->EndOfFile.QuadPart =
+                                                       (LONGLONG)(Fcb->dinode2->di_size);
+
+                                               FileStandardInformation->NumberOfLinks = Fcb->dinode2->di_nlink;
+                                       }
+
+                                       if (IsFlagOn(Fcb->Vcb->Flags, VCB_READ_ONLY))
+                                               FileStandardInformation->DeletePending = FALSE;
+                                       else
+                                               FileStandardInformation->DeletePending = IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING);
+
+                                       if (FlagOn(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY))
+                                       {
+                                               FileStandardInformation->Directory = TRUE;
+                                       }
+                                       else
+                                       {
+                                               FileStandardInformation->Directory = FALSE;
+                                       }
+
+                                       // The "inode number"
+                                       FileInternalInformation->IndexNumber.QuadPart = (LONGLONG)Fcb->FFSMcb->Inode;
+
+                                       // Romfs doesn't have any extended attributes
+                                       FileEaInformation->EaSize = 0;
+
+                                       FilePositionInformation->CurrentByteOffset =
+                                               FileObject->CurrentByteOffset;
+
+                                       if (Length < sizeof(FILE_ALL_INFORMATION) +
+                                                       Fcb->FFSMcb->ShortName.Length - sizeof(WCHAR))
+                                       {
+                                               Irp->IoStatus.Information = sizeof(FILE_ALL_INFORMATION);
+                                               Status = STATUS_BUFFER_OVERFLOW;
+                                               _SEH2_LEAVE;
+                                       }
+
+                                       FileNameInformation->FileNameLength = Fcb->FFSMcb->ShortName.Length;
+
+                                       RtlCopyMemory(
+                                                       FileNameInformation->FileName,
+                                                       Fcb->FFSMcb->ShortName.Buffer,
+                                                       Fcb->FFSMcb->ShortName.Length);
+
+                                       Irp->IoStatus.Information = sizeof(FILE_ALL_INFORMATION) +
+                                               Fcb->FFSMcb->ShortName.Length - sizeof(WCHAR);
+                                       Status = STATUS_SUCCESS;
+                                       _SEH2_LEAVE;
+                               }
+
+                       /*
+                       case FileAlternateNameInformation:
+                          {
+                               // TODO: Handle FileAlternateNameInformation
+
+                               // Here we would like to use RtlGenerate8dot3Name but I don't
+                               // know how to use the argument PGENERATE_NAME_CONTEXT
+                       }
+                       */
+
+                       case FileNetworkOpenInformation:
+                               {
+                                       PFILE_NETWORK_OPEN_INFORMATION FileNetworkOpenInformation;
+
+                                       if (Length < sizeof(FILE_NETWORK_OPEN_INFORMATION))
+                                       {
+                                               Status = STATUS_INFO_LENGTH_MISMATCH;
+                                               _SEH2_LEAVE;
+                                       }
+
+                                       FileNetworkOpenInformation =
+                                               (PFILE_NETWORK_OPEN_INFORMATION)Buffer;
+
+                                       if (FS_VERSION == 1)
+                                       {
+                                               FileNetworkOpenInformation->CreationTime = FFSSysTime(Fcb->dinode1->di_ctime);
+
+                                               FileNetworkOpenInformation->LastAccessTime = FFSSysTime(Fcb->dinode1->di_atime);
+
+                                               FileNetworkOpenInformation->LastWriteTime = FFSSysTime(Fcb->dinode1->di_mtime);
+
+                                               FileNetworkOpenInformation->ChangeTime = FFSSysTime(Fcb->dinode1->di_mtime);
+
+                                               FileNetworkOpenInformation->AllocationSize.QuadPart =
+                                                       (LONGLONG)(Fcb->dinode1->di_size);
+
+                                               FileNetworkOpenInformation->EndOfFile.QuadPart =
+                                                       (LONGLONG)(Fcb->dinode1->di_size);
+                                       }
+                                       else
+                                       {
+                                               FileNetworkOpenInformation->CreationTime = FFSSysTime((ULONG)Fcb->dinode2->di_ctime);
+
+                                               FileNetworkOpenInformation->LastAccessTime = FFSSysTime((ULONG)Fcb->dinode2->di_atime);
+
+                                               FileNetworkOpenInformation->LastWriteTime = FFSSysTime((ULONG)Fcb->dinode2->di_mtime);
+
+                                               FileNetworkOpenInformation->ChangeTime = FFSSysTime((ULONG)Fcb->dinode2->di_mtime);
+
+                                               FileNetworkOpenInformation->AllocationSize.QuadPart =
+                                                       (LONGLONG)(Fcb->dinode2->di_size);
+
+                                               FileNetworkOpenInformation->EndOfFile.QuadPart =
+                                                       (LONGLONG)(Fcb->dinode2->di_size);
+                                       }
+
+                                       FileNetworkOpenInformation->FileAttributes =
+                                               Fcb->FFSMcb->FileAttr;
+
+                                       Irp->IoStatus.Information =
+                                               sizeof(FILE_NETWORK_OPEN_INFORMATION);
+                                       Status = STATUS_SUCCESS;
+                                       _SEH2_LEAVE;
+                               }
+
+                       default:
+                               Status = STATUS_INVALID_INFO_CLASS;
+               }
+       }
+       _SEH2_FINALLY
+       {
+               if (FcbResourceAcquired)
+               {
+                       ExReleaseResourceForThreadLite(
+                                       &Fcb->MainResource,
+                                       ExGetCurrentResourceThread());
+               }
+
+               if (!IrpContext->ExceptionInProgress)
+               {
+                       if (Status == STATUS_PENDING)
+                       {
+                               FFSQueueRequest(IrpContext);
+                       }
+                       else
+                       {
+                               FFSCompleteIrpContext(IrpContext,  Status);
+                       }
+               }
+       } _SEH2_END;
+
+       return Status;
+}
+
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSSetInformation(
+       IN PFFS_IRP_CONTEXT IrpContext)
+{
+       PDEVICE_OBJECT          DeviceObject;
+       NTSTATUS                Status = STATUS_UNSUCCESSFUL;
+       PFFS_VCB                Vcb = 0;
+       PFILE_OBJECT            FileObject;
+       PFFS_FCB                Fcb = 0;
+       PFFS_CCB                Ccb;
+       PIRP                    Irp;
+       PIO_STACK_LOCATION      IoStackLocation;
+       FILE_INFORMATION_CLASS  FileInformationClass;
+
+       ULONG                   NotifyFilter = 0;
+
+       ULONG                   Length;
+       PVOID                   Buffer;
+       BOOLEAN                 FcbMainResourceAcquired = FALSE;
+
+       BOOLEAN                 VcbResourceAcquired = FALSE;
+       BOOLEAN                 FcbPagingIoResourceAcquired = FALSE;
+
+    PAGED_CODE();
+
+       _SEH2_TRY
+       {
+               ASSERT(IrpContext != NULL);
+
+               ASSERT((IrpContext->Identifier.Type == FFSICX) &&
+                               (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
+
+               DeviceObject = IrpContext->DeviceObject;
+
+               //
+               // This request is not allowed on the main device object
+               //
+               if (DeviceObject == FFSGlobal->DeviceObject)
+               {
+                       Status = STATUS_INVALID_DEVICE_REQUEST;
+                       _SEH2_LEAVE;
+               }
+
+               Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;
+
+               ASSERT(Vcb != NULL);
+
+               ASSERT((Vcb->Identifier.Type == FFSVCB) &&
+                               (Vcb->Identifier.Size == sizeof(FFS_VCB)));
+
+               ASSERT(IsMounted(Vcb));
+
+               FileObject = IrpContext->FileObject;
+
+               Fcb = (PFFS_FCB)FileObject->FsContext;
+
+               ASSERT(Fcb != NULL);
+
+               //
+               // This request is not allowed on volumes
+               //
+               if (Fcb->Identifier.Type == FFSVCB)
+               {
+                       FFSBreakPoint();
+
+                       Status = STATUS_INVALID_PARAMETER;
+                       _SEH2_LEAVE;
+               }
+
+               ASSERT((Fcb->Identifier.Type == FFSFCB) &&
+                               (Fcb->Identifier.Size == sizeof(FFS_FCB)));
+
+               if (IsFlagOn(Fcb->Flags, FCB_FILE_DELETED))
+               {
+                       Status = STATUS_FILE_DELETED;
+                       _SEH2_LEAVE;
+               }
+
+               Ccb = (PFFS_CCB)FileObject->FsContext2;
+
+               ASSERT(Ccb != NULL);
+
+               ASSERT((Ccb->Identifier.Type == FFSCCB) &&
+                               (Ccb->Identifier.Size == sizeof(FFS_CCB)));
+
+               Irp = IrpContext->Irp;
+
+               IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
+
+               FileInformationClass =
+                       IoStackLocation->Parameters.SetFile.FileInformationClass;
+
+               Length = IoStackLocation->Parameters.SetFile.Length;
+
+               Buffer = Irp->AssociatedIrp.SystemBuffer;
+
+               if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY))
+               {
+                       if (FileInformationClass == FileDispositionInformation ||
+                                       FileInformationClass == FileRenameInformation ||
+                                       FileInformationClass == FileLinkInformation)
+                       {
+#ifdef _MSC_VER
+#pragma prefast( suppress: 28137, "by design" )
+#endif
+                               if (!ExAcquireResourceExclusiveLite(
+                                                       &Vcb->MainResource,
+                                                       IrpContext->IsSynchronous))
+                               {
+                                       Status = STATUS_PENDING;
+                                       _SEH2_LEAVE;
+                               }
+
+                               VcbResourceAcquired = TRUE;
+                       }
+               }
+               else if (!FlagOn(Fcb->Flags, FCB_PAGE_FILE))
+               {
+#ifdef _MSC_VER
+#pragma prefast( suppress: 28137, "by design" )
+#endif
+                       if (!ExAcquireResourceExclusiveLite(
+                                               &Fcb->MainResource,
+                                               IrpContext->IsSynchronous))
+                       {
+                               Status = STATUS_PENDING;
+                               _SEH2_LEAVE;
+                       }
+
+                       FcbMainResourceAcquired = TRUE;
+               }
+
+               if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY))
+               {
+                       if (FileInformationClass != FilePositionInformation)
+                       {
+                               Status = STATUS_MEDIA_WRITE_PROTECTED;
+                               _SEH2_LEAVE;
+                       }
+               }
+
+               if (FileInformationClass == FileDispositionInformation ||
+                               FileInformationClass == FileRenameInformation ||
+                               FileInformationClass == FileLinkInformation ||
+                               FileInformationClass == FileAllocationInformation ||
+                               FileInformationClass == FileEndOfFileInformation)
+               {
+#ifdef _MSC_VER
+#pragma prefast( suppress: 28137, "by design" )
+#endif
+                       if (!ExAcquireResourceExclusiveLite(
+                                               &Fcb->PagingIoResource,
+                                               IrpContext->IsSynchronous))
+                       {
+                               Status = STATUS_PENDING;
+                               _SEH2_LEAVE;
+                       }
+
+                       FcbPagingIoResourceAcquired = TRUE;
+               }
+
+               /*        
+               if (FileInformationClass != FileDispositionInformation 
+                        && FlagOn(Fcb->Flags, FCB_DELETE_PENDING))
+               {
+                       Status = STATUS_DELETE_PENDING;
+                       _SEH2_LEAVE;
+               }
+               */
+
+               switch (FileInformationClass)
+               {
+
+#if !FFS_READ_ONLY
+
+                       case FileBasicInformation:
+                               {
+                                       PFILE_BASIC_INFORMATION FBI = (PFILE_BASIC_INFORMATION)Buffer;
+
+                                       if (FS_VERSION == 1)
+                                       {
+                                               PFFSv1_INODE dinode1 = Fcb->dinode1;
+
+                                               if(FBI->CreationTime.QuadPart)
+                                               {
+                                                       dinode1->di_ctime = (ULONG)(FFSInodeTime(FBI->CreationTime));
+                                               }
+
+                                               if(FBI->LastAccessTime.QuadPart)
+                                               {
+                                                       dinode1->di_atime = (ULONG)(FFSInodeTime(FBI->LastAccessTime));
+                                               }
+
+                                               if(FBI->LastWriteTime.QuadPart)
+                                               {
+                                                       dinode1->di_mtime = (ULONG)(FFSInodeTime(FBI->LastWriteTime));
+                                               }
+
+                                               if (IsFlagOn(FBI->FileAttributes, FILE_ATTRIBUTE_READONLY)) 
+                                               {
+                                                       FFSSetReadOnly(Fcb->dinode1->di_mode);
+                                                       SetFlag(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_READONLY);
+                                               }
+                                               else
+                                               {
+                                                       FFSSetWritable(Fcb->dinode1->di_mode);
+                                                       ClearFlag(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_READONLY);
+                                               }
+
+                                               if(FFSv1SaveInode(IrpContext, Vcb, Fcb->FFSMcb->Inode, dinode1))
+                                               {
+                                                       Status = STATUS_SUCCESS;
+                                               }
+
+                                               if (FBI->FileAttributes & FILE_ATTRIBUTE_TEMPORARY) 
+                                               {
+                                                       SetFlag(FileObject->Flags, FO_TEMPORARY_FILE);
+                                               } 
+                                               else 
+                                               {
+                                                       ClearFlag(FileObject->Flags, FO_TEMPORARY_FILE);
+                                               }
+                                       }
+                                       else
+                                       {
+                                               PFFSv2_INODE dinode2 = Fcb->dinode2;
+
+                                               if(FBI->CreationTime.QuadPart)
+                                               {
+                                                       dinode2->di_ctime = (ULONG)(FFSInodeTime(FBI->CreationTime));
+                                               }
+
+                                               if(FBI->LastAccessTime.QuadPart)
+                                               {
+                                                       dinode2->di_atime = (ULONG)(FFSInodeTime(FBI->LastAccessTime));
+                                               }
+
+                                               if(FBI->LastWriteTime.QuadPart)
+                                               {
+                                                       dinode2->di_mtime = (ULONG)(FFSInodeTime(FBI->LastWriteTime));
+                                               }
+
+                                               if (IsFlagOn(FBI->FileAttributes, FILE_ATTRIBUTE_READONLY)) 
+                                               {
+                                                       FFSSetReadOnly(Fcb->dinode2->di_mode);
+                                                       SetFlag(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_READONLY);
+                                               }
+                                               else
+                                               {
+                                                       FFSSetWritable(Fcb->dinode2->di_mode);
+                                                       ClearFlag(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_READONLY);
+                                               }
+
+                                               if(FFSv2SaveInode(IrpContext, Vcb, Fcb->FFSMcb->Inode, dinode2))
+                                               {
+                                                       Status = STATUS_SUCCESS;
+                                               }
+
+                                               if (FBI->FileAttributes & FILE_ATTRIBUTE_TEMPORARY) 
+                                               {
+                                                       SetFlag(FileObject->Flags, FO_TEMPORARY_FILE);
+                                               } 
+                                               else 
+                                               {
+                                                       ClearFlag(FileObject->Flags, FO_TEMPORARY_FILE);
+                                               }
+                                       }
+
+                                       NotifyFilter = FILE_NOTIFY_CHANGE_ATTRIBUTES |
+                                               FILE_NOTIFY_CHANGE_CREATION |
+                                               FILE_NOTIFY_CHANGE_LAST_ACCESS |
+                                               FILE_NOTIFY_CHANGE_LAST_WRITE ;
+
+                                       Status = STATUS_SUCCESS;
+                               }
+                               break;
+
+                       case FileAllocationInformation:
+                               {
+                                       PFILE_ALLOCATION_INFORMATION FAI = (PFILE_ALLOCATION_INFORMATION)Buffer;
+
+                                       if (FlagOn(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY))
+                                       {
+                                               Status = STATUS_INVALID_DEVICE_REQUEST;
+                                               _SEH2_LEAVE;
+                                       }
+
+                                       if (FAI->AllocationSize.QuadPart == 
+                                                       Fcb->Header.AllocationSize.QuadPart)
+                                       {
+                                               Status = STATUS_SUCCESS;
+                                       }
+                                       else if (FAI->AllocationSize.QuadPart >
+                                                       Fcb->Header.AllocationSize.QuadPart)
+                                       {
+                                               if(FFSExpandFile(IrpContext,
+                                                                       Vcb, Fcb,
+                                                                       &(FAI->AllocationSize)))
+                                               {
+                                                       if (FFSv1SaveInode(IrpContext,
+                                                                               Vcb,
+                                                                               Fcb->FFSMcb->Inode,
+                                                                               Fcb->dinode1))
+                                                       {
+                                                               Status = STATUS_SUCCESS;
+                                                       }
+                                               }
+                                               else
+                                               {
+                                                       Status = STATUS_INSUFFICIENT_RESOURCES;
+                                               }
+                                       }
+                                       else
+                                       {
+                                               if (MmCanFileBeTruncated(&(Fcb->SectionObject), &(FAI->AllocationSize))) 
+                                               {
+                                                       LARGE_INTEGER EndOfFile;
+
+                                                       EndOfFile.QuadPart = FAI->AllocationSize.QuadPart +
+                                                               (LONGLONG)(Vcb->BlockSize - 1);
+
+                                                       if(FFSTruncateFile(IrpContext, Vcb, Fcb, &(EndOfFile)))
+                                                       {
+                                                               if (FAI->AllocationSize.QuadPart < 
+                                                                               Fcb->Header.FileSize.QuadPart)
+                                                               {
+                                                                       Fcb->Header.FileSize.QuadPart = 
+                                                                               FAI->AllocationSize.QuadPart;
+                                                               }
+
+                                                               FFSv1SaveInode(IrpContext,
+                                                                               Vcb,
+                                                                               Fcb->FFSMcb->Inode,
+                                                                               Fcb->dinode1);
+
+                                                               Status = STATUS_SUCCESS;
+                                                       }
+                                               }
+                                               else
+                                               {
+                                                       Status = STATUS_USER_MAPPED_FILE;
+                                                       _SEH2_LEAVE;
+                                               }
+                                       }
+
+                                       if (NT_SUCCESS(Status))
+                                       {
+                                               CcSetFileSizes(FileObject, 
+                                                               (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
+                                               SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
+
+                                               NotifyFilter = FILE_NOTIFY_CHANGE_SIZE |
+                                                       FILE_NOTIFY_CHANGE_LAST_WRITE ;
+
+                                       }
+
+                               }
+                               break;
+
+                       case FileEndOfFileInformation:
+                               {
+                                       PFILE_END_OF_FILE_INFORMATION FEOFI = (PFILE_END_OF_FILE_INFORMATION) Buffer;
+
+                                       BOOLEAN CacheInitialized = FALSE;
+
+                                       if (IsDirectory(Fcb))
+                                       {
+                                               Status = STATUS_INVALID_DEVICE_REQUEST;
+                                               _SEH2_LEAVE;
+                                       }
+
+                                       if (FEOFI->EndOfFile.HighPart != 0)
+                                       {
+                                               Status = STATUS_INVALID_PARAMETER;
+                                               _SEH2_LEAVE;
+                                       }
+
+
+                                       if (IoStackLocation->Parameters.SetFile.AdvanceOnly)
+                                       {
+                                               Status = STATUS_SUCCESS;
+                                               _SEH2_LEAVE;
+                                       }
+
+                                       if ((FileObject->SectionObjectPointer->DataSectionObject != NULL) &&
+                                                       (FileObject->SectionObjectPointer->SharedCacheMap == NULL) &&
+                                                       !FlagOn(Irp->Flags, IRP_PAGING_IO)) {
+
+                                               ASSERT(!FlagOn(FileObject->Flags, FO_CLEANUP_COMPLETE));
+
+                                               CcInitializeCacheMap(
+                                                               FileObject,
+                                                               (PCC_FILE_SIZES)&(Fcb->Header.AllocationSize),
+                                                               FALSE,
+                                                               &(FFSGlobal->CacheManagerNoOpCallbacks),
+                                                               Fcb);
+
+                                               CacheInitialized = TRUE;
+                                       }
+
+                                       if (FEOFI->EndOfFile.QuadPart == 
+                                                       Fcb->Header.AllocationSize.QuadPart)
+                                       {
+                                               Status = STATUS_SUCCESS;
+                                       }
+                                       else if (FEOFI->EndOfFile.QuadPart > 
+                                                       Fcb->Header.AllocationSize.QuadPart)
+                                       {
+                                               LARGE_INTEGER FileSize = Fcb->Header.FileSize;
+
+                                               if(FFSExpandFile(IrpContext, Vcb, Fcb, &(FEOFI->EndOfFile)))
+                                               {
+                                                       {
+                                                               Fcb->Header.FileSize.QuadPart = 
+                                                                       FEOFI->EndOfFile.QuadPart;
+                                                               Fcb->dinode1->di_size = (ULONG)FEOFI->EndOfFile.QuadPart;
+                                                               Fcb->Header.ValidDataLength.QuadPart = 
+                                                                       (LONGLONG)(0x7fffffffffffffff);
+                                                       }
+
+                                                       if (FFSv1SaveInode(IrpContext,
+                                                                               Vcb,
+                                                                               Fcb->FFSMcb->Inode,
+                                                                               Fcb->dinode1))
+                                                       {
+                                                               Status = STATUS_SUCCESS;
+                                                       }
+                                               }
+                                               else
+                                               {
+                                                       Status = STATUS_INSUFFICIENT_RESOURCES;
+                                               }
+
+
+                                               if (NT_SUCCESS(Status))
+                                               {
+                                                       CcSetFileSizes(FileObject, 
+                                                                       (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
+
+                                                       SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
+
+                                                       FFSZeroHoles(IrpContext, 
+                                                                       Vcb, FileObject, 
+                                                                       FileSize.QuadPart,
+                                                                       Fcb->Header.AllocationSize.QuadPart - 
+                                                                       FileSize.QuadPart);
+
+                                                       NotifyFilter = FILE_NOTIFY_CHANGE_SIZE |
+                                                               FILE_NOTIFY_CHANGE_LAST_WRITE ;
+
+                                               }
+                                       }
+                                       else
+                                       {
+                                               if (MmCanFileBeTruncated(&(Fcb->SectionObject), &(FEOFI->EndOfFile))) 
+                                               {
+                                                       LARGE_INTEGER EndOfFile = FEOFI->EndOfFile;
+
+                                                       EndOfFile.QuadPart = EndOfFile.QuadPart + 
+                                                               (LONGLONG)(Vcb->BlockSize - 1);
+
+                                                       if(FFSTruncateFile(IrpContext, Vcb, Fcb, &(EndOfFile)))
+                                                       {
+                                                               Fcb->Header.FileSize.QuadPart = 
+                                                                       FEOFI->EndOfFile.QuadPart;
+                                                               Fcb->dinode1->di_size = (ULONG)FEOFI->EndOfFile.QuadPart;
+
+                                                               FFSv1SaveInode(IrpContext,
+                                                                               Vcb,
+                                                                               Fcb->FFSMcb->Inode,
+                                                                               Fcb->dinode1);
+
+                                                               Status = STATUS_SUCCESS;
+                                                       }
+                                               }
+                                               else
+                                               {
+                                                       Status = STATUS_USER_MAPPED_FILE;
+                                                       _SEH2_LEAVE;
+                                               }
+
+                                               if (NT_SUCCESS(Status))
+                                               {
+                                                       CcSetFileSizes(FileObject, 
+                                                                       (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
+
+                                                       SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
+
+                                                       NotifyFilter = FILE_NOTIFY_CHANGE_SIZE |
+                                                               FILE_NOTIFY_CHANGE_LAST_WRITE ;
+
+                                               }
+                                       }
+                               }
+
+                               break;
+
+                       case FileDispositionInformation:
+                               {
+                                       PFILE_DISPOSITION_INFORMATION FDI = (PFILE_DISPOSITION_INFORMATION)Buffer;
+
+                                       Status = FFSSetDispositionInfo(IrpContext, Vcb, Fcb, FDI->DeleteFile);
+                               }
+
+                               break;
+
+                       case FileRenameInformation:
+                               {
+                                       Status = FFSSetRenameInfo(IrpContext, Vcb, Fcb);
+                               }
+
+                               break;
+
+#endif // !FFS_READ_ONLY
+
+                               //
+                               // This is the only set file information request supported on read
+                               // only file systems
+                               //
+                       case FilePositionInformation:
+                               {
+                                       PFILE_POSITION_INFORMATION FilePositionInformation;
+
+                                       if (Length < sizeof(FILE_POSITION_INFORMATION))
+                                       {
+                                               Status = STATUS_INVALID_PARAMETER;
+                                               _SEH2_LEAVE;
+                                       }
+
+                                       FilePositionInformation = (PFILE_POSITION_INFORMATION) Buffer;
+
+                                       if ((FlagOn(FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING)) &&
+                                                       (FilePositionInformation->CurrentByteOffset.LowPart &
+                                                        DeviceObject->AlignmentRequirement))
+                                       {
+                                               Status = STATUS_INVALID_PARAMETER;
+                                               _SEH2_LEAVE;
+                                       }
+
+                                       FileObject->CurrentByteOffset =
+                                               FilePositionInformation->CurrentByteOffset;
+
+                                       Status = STATUS_SUCCESS;
+                                       _SEH2_LEAVE;
+                               }
+
+                               break;
+
+                       default:
+                               Status = STATUS_INVALID_INFO_CLASS;
+               }
+       }
+       _SEH2_FINALLY
+       {
+
+               if (FcbPagingIoResourceAcquired)
+               {
+                       ExReleaseResourceForThreadLite(
+                                       &Fcb->PagingIoResource,
+                                       ExGetCurrentResourceThread());
+               }
+
+               if (NT_SUCCESS(Status) && (NotifyFilter != 0))
+               {
+                       FFSNotifyReportChange(
+                                       IrpContext,
+                                       Vcb,
+                                       Fcb,
+                                       NotifyFilter,
+                                       FILE_ACTION_MODIFIED);
+
+               }
+
+               if (FcbMainResourceAcquired)
+               {
+                       ExReleaseResourceForThreadLite(
+                                       &Fcb->MainResource,
+                                       ExGetCurrentResourceThread());
+               }
+
+               if (VcbResourceAcquired)
+               {
+                       ExReleaseResourceForThreadLite(
+                                       &Vcb->MainResource,
+                                       ExGetCurrentResourceThread());
+               }
+
+               if (!IrpContext->ExceptionInProgress)
+               {
+                       if (Status == STATUS_PENDING)
+                       {
+                               FFSQueueRequest(IrpContext);
+                       }
+                       else
+                       {
+                               FFSCompleteIrpContext(IrpContext,  Status);
+                       }
+               }
+       } _SEH2_END;
+
+       return Status;
+}
+
+#if !FFS_READ_ONLY
+
+BOOLEAN
+FFSExpandFile(
+       PFFS_IRP_CONTEXT IrpContext, 
+       PFFS_VCB         Vcb,
+       PFFS_FCB         Fcb,
+       PLARGE_INTEGER   AllocationSize)
+{
+       ULONG   dwRet = 0;
+       BOOLEAN bRet = TRUE;
+
+    PAGED_CODE();
+
+       if (AllocationSize->QuadPart <= Fcb->Header.AllocationSize.QuadPart)
+       {
+               return TRUE;
+       }
+
+       if (((LONGLONG)SUPER_BLOCK->fs_size - (LONGLONG)SUPER_BLOCK->fs_dsize) * Vcb->BlockSize <=
+                       (AllocationSize->QuadPart - Fcb->Header.AllocationSize.QuadPart))
+       {
+               FFSPrint((DBG_ERROR, "FFSExpandFile: There is no enough disk space available.\n"));
+               return FALSE;
+       }
+
+       while (bRet && (AllocationSize->QuadPart > Fcb->Header.AllocationSize.QuadPart))
+       {
+               bRet = FFSExpandInode(IrpContext, Vcb, Fcb, &dwRet);
+       }
+
+       return bRet;
+}
+
+
+BOOLEAN
+FFSTruncateFile(
+       PFFS_IRP_CONTEXT IrpContext,
+       PFFS_VCB         Vcb,
+       PFFS_FCB         Fcb,
+       PLARGE_INTEGER   AllocationSize)
+{
+       BOOLEAN bRet = TRUE;
+
+    PAGED_CODE();
+
+       while (bRet && (AllocationSize->QuadPart <
+                               Fcb->Header.AllocationSize.QuadPart))
+       {
+               bRet = FFSTruncateInode(IrpContext, Vcb, Fcb);
+       }
+
+       return bRet;
+}
+
+
+NTSTATUS
+FFSSetDispositionInfo(
+       PFFS_IRP_CONTEXT IrpContext,
+       PFFS_VCB         Vcb,
+       PFFS_FCB         Fcb,
+       BOOLEAN          bDelete)
+{
+       PIRP    Irp = IrpContext->Irp;
+       PIO_STACK_LOCATION IrpSp;
+
+    PAGED_CODE();
+
+       IrpSp = IoGetCurrentIrpStackLocation(Irp);
+
+       FFSPrint((DBG_INFO, "FFSSetDispositionInfo: bDelete=%x\n", bDelete));
+
+       if (bDelete)
+       {
+               FFSPrint((DBG_INFO, "FFSSetDispositionInformation: MmFlushImageSection on %s.\n", 
+                                       Fcb->AnsiFileName.Buffer));
+
+               if (!MmFlushImageSection(&Fcb->SectionObject,
+                                       MmFlushForDelete))
+               {
+                       return STATUS_CANNOT_DELETE;
+               }
+
+               if (Fcb->FFSMcb->Inode == FFS_ROOT_INO)
+               {
+                       return STATUS_CANNOT_DELETE;
+               }
+
+               if (IsDirectory(Fcb))
+               {
+                       if (!FFSIsDirectoryEmpty(Vcb, Fcb))
+                       {
+                               return STATUS_DIRECTORY_NOT_EMPTY;
+                       }
+               }
+
+               SetFlag(Fcb->Flags, FCB_DELETE_PENDING);
+               IrpSp->FileObject->DeletePending = TRUE;
+
+               if (IsDirectory(Fcb))
+               {
+                       FsRtlNotifyFullChangeDirectory(Vcb->NotifySync,
+                                       &Vcb->NotifyList,
+                                       Fcb,
+                                       NULL,
+                                       FALSE,
+                                       FALSE,
+                                       0,
+                                       NULL,
+                                       NULL,
+                                       NULL);
+               }
+       }
+       else
+       {
+               ClearFlag(Fcb->Flags, FCB_DELETE_PENDING);
+               IrpSp->FileObject->DeletePending = FALSE;
+       }
+
+       return STATUS_SUCCESS;
+}  
+
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSSetRenameInfo(
+       PFFS_IRP_CONTEXT IrpContext,
+       PFFS_VCB         Vcb,
+       PFFS_FCB         Fcb)
+{
+       PFFS_FCB                TargetDcb;
+       PFFS_MCB                TargetMcb;
+
+       PFFS_MCB                Mcb;
+       FFSv1_INODE             dinode1;
+
+       UNICODE_STRING          FileName;
+
+       NTSTATUS                Status;
+
+       PIRP                    Irp;
+       PIO_STACK_LOCATION      IrpSp;
+
+       PFILE_OBJECT            FileObject;
+       PFILE_OBJECT            TargetObject;
+       BOOLEAN                 ReplaceIfExists;
+
+       BOOLEAN                 bMove = FALSE;
+
+       PFILE_RENAME_INFORMATION    FRI;
+
+    PAGED_CODE();
+
+       if (Fcb->FFSMcb->Inode == FFS_ROOT_INO)
+       {
+               Status = STATUS_INVALID_PARAMETER;
+               goto errorout;
+       }
+
+       Irp = IrpContext->Irp;
+       IrpSp = IoGetCurrentIrpStackLocation(Irp);
+
+       FileObject = IrpSp->FileObject;
+       TargetObject = IrpSp->Parameters.SetFile.FileObject;
+       ReplaceIfExists = IrpSp->Parameters.SetFile.ReplaceIfExists;
+
+       FRI = (PFILE_RENAME_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
+
+       if (TargetObject == NULL)
+       {
+               UNICODE_STRING  NewName;
+
+               NewName.Buffer = FRI->FileName;
+               NewName.MaximumLength = NewName.Length = (USHORT)FRI->FileNameLength;
+
+               while (NewName.Length > 0 && NewName.Buffer[NewName.Length / 2 - 1] == L'\\')
+               {
+                       NewName.Buffer[NewName.Length / 2 - 1] = 0;
+                       NewName.Length -= 2;
+               }
+
+               while (NewName.Length > 0 && NewName.Buffer[NewName.Length / 2 - 1] != L'\\')
+               {
+                       NewName.Length -= 2;
+               }
+
+               NewName.Buffer = (USHORT *)((UCHAR *)NewName.Buffer + NewName.Length);
+               NewName.Length = (USHORT)(FRI->FileNameLength - NewName.Length);
+
+               FileName = NewName;
+
+               TargetDcb = NULL;
+               TargetMcb = Fcb->FFSMcb->Parent;
+
+               if (FileName.Length >= FFS_NAME_LEN*sizeof(USHORT))
+               {
+                       Status = STATUS_OBJECT_NAME_INVALID;
+                       goto errorout;
+               }
+       }
+       else
+       {
+               TargetDcb = (PFFS_FCB)(TargetObject->FsContext);
+
+               if (!TargetDcb || TargetDcb->Vcb != Vcb)
+               {
+                       FFSBreakPoint();
+
+                       Status = STATUS_INVALID_PARAMETER;
+                       goto errorout;
+               }
+
+               TargetMcb = TargetDcb->FFSMcb;
+
+               FileName = TargetObject->FileName;
+       }
+
+       if (FsRtlDoesNameContainWildCards(&FileName))
+       {
+               Status = STATUS_OBJECT_NAME_INVALID;
+               goto errorout;
+       }
+
+       if (TargetMcb->Inode == Fcb->FFSMcb->Parent->Inode)
+       {
+               if (FsRtlAreNamesEqual(&FileName,
+                                       &(Fcb->FFSMcb->ShortName),
+                                       FALSE,
+                                       NULL))
+               {
+                       Status = STATUS_SUCCESS;
+                       goto errorout;
+               }
+       }
+       else
+       {
+               bMove = TRUE;
+       }
+
+       TargetDcb = TargetMcb->FFSFcb;
+
+       if (!TargetDcb)
+               TargetDcb = FFSCreateFcbFromMcb(Vcb, TargetMcb);
+
+       if ((TargetMcb->Inode != Fcb->FFSMcb->Parent->Inode) &&
+                       (Fcb->FFSMcb->Parent->FFSFcb == NULL))
+       {
+               FFSCreateFcbFromMcb(Vcb, Fcb->FFSMcb->Parent);
+       }
+
+       if (!TargetDcb || !(Fcb->FFSMcb->Parent->FFSFcb))
+       {
+               Status = STATUS_UNSUCCESSFUL;
+
+               goto errorout;
+       }
+
+       Mcb = NULL;
+       Status = FFSv1LookupFileName(
+                               Vcb,
+                               &FileName,
+                               TargetMcb,
+                               &Mcb,
+                               &dinode1); 
+
+       if (NT_SUCCESS(Status))   
+       {
+               if ((!ReplaceIfExists) ||
+                               (IsFlagOn(Mcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY)) ||
+                               (IsFlagOn(Mcb->FileAttr, FILE_ATTRIBUTE_READONLY)))
+               {
+                       Status = STATUS_OBJECT_NAME_COLLISION;
+                       goto errorout;
+               }
+
+               if (ReplaceIfExists)
+               {
+                       Status = STATUS_NOT_IMPLEMENTED;
+                       goto errorout;
+               }
+       }
+
+       if (IsDirectory(Fcb))
+       {
+
+               Status = FFSRemoveEntry(IrpContext, Vcb, 
+                                       Fcb->FFSMcb->Parent->FFSFcb,
+                                       DT_DIR,
+                                       Fcb->FFSMcb->Inode);
+
+               if (!NT_SUCCESS(Status))
+               {
+                       FFSBreakPoint();
+
+                       goto errorout;
+               }
+
+               Status = FFSAddEntry(IrpContext, Vcb, 
+                                       TargetDcb,
+                                       DT_DIR,
+                                       Fcb->FFSMcb->Inode,
+                                       &FileName);
+
+               if (!NT_SUCCESS(Status))
+               {
+                       FFSBreakPoint();
+
+                       FFSAddEntry(IrpContext, Vcb, 
+                                       Fcb->FFSMcb->Parent->FFSFcb,
+                                       DT_DIR,
+                                       Fcb->FFSMcb->Inode,
+                                       &Fcb->FFSMcb->ShortName);
+
+                       goto errorout;
+               }
+
+               if(!FFSv1SaveInode(IrpContext,
+                                       Vcb, 
+                                       TargetMcb->Inode,
+                                       TargetDcb->dinode1))
+               {
+                       Status = STATUS_UNSUCCESSFUL;
+
+                       FFSBreakPoint();
+
+                       goto errorout;
+               }
+
+               if(!FFSv1SaveInode(IrpContext,
+                                       Vcb, 
+                                       Fcb->FFSMcb->Parent->Inode,
+                                       Fcb->FFSMcb->Parent->FFSFcb->dinode1))
+               {
+                       Status = STATUS_UNSUCCESSFUL;
+
+                       FFSBreakPoint();
+
+                       goto errorout;
+               }
+
+               Status = FFSSetParentEntry(IrpContext, Vcb, Fcb,
+                                       Fcb->FFSMcb->Parent->Inode,
+                                       TargetDcb->FFSMcb->Inode);
+
+
+               if (!NT_SUCCESS(Status))
+               {
+                       FFSBreakPoint();
+                       goto errorout;
+               }
+       }
+       else
+       {
+               Status = FFSRemoveEntry(IrpContext, Vcb,
+                                       Fcb->FFSMcb->Parent->FFSFcb,
+                                       DT_REG,
+                                       Fcb->FFSMcb->Inode);
+               if (!NT_SUCCESS(Status))
+               {
+                       FFSBreakPoint();
+                       goto errorout;
+               }
+
+               Status = FFSAddEntry(IrpContext,
+                                       Vcb, TargetDcb,
+                                       DT_REG,
+                                       Fcb->FFSMcb->Inode,
+                                       &FileName);
+
+               if (!NT_SUCCESS(Status))
+               {
+                       FFSBreakPoint();
+
+                       FFSAddEntry(IrpContext, Vcb, 
+                                       Fcb->FFSMcb->Parent->FFSFcb,
+                                       DT_REG,
+                                       Fcb->FFSMcb->Inode,
+                                       &Fcb->FFSMcb->ShortName);
+
+                       goto errorout;
+               }
+       }
+
+       if (NT_SUCCESS(Status))
+       {
+               if (Fcb->FFSMcb->ShortName.MaximumLength < (FileName.Length + 2))
+               {
+                       ExFreePool(Fcb->FFSMcb->ShortName.Buffer);
+                       Fcb->FFSMcb->ShortName.Buffer = 
+                               ExAllocatePoolWithTag(PagedPool, FileName.Length + 2, FFS_POOL_TAG);
+
+                       if (!Fcb->FFSMcb->ShortName.Buffer)
+                       {
+                               Status = STATUS_INSUFFICIENT_RESOURCES;
+                               goto errorout;
+                       }
+
+                       Fcb->FFSMcb->ShortName.MaximumLength = FileName.Length + 2;
+               }
+
+               {
+                       RtlZeroMemory(Fcb->FFSMcb->ShortName.Buffer,
+                                       Fcb->FFSMcb->ShortName.MaximumLength);
+
+                       RtlCopyMemory(Fcb->FFSMcb->ShortName.Buffer,
+                                       FileName.Buffer, FileName.Length);
+
+                       Fcb->FFSMcb->ShortName.Length = FileName.Length;
+               }
+
+#if DBG    
+
+               Fcb->AnsiFileName.Length = (USHORT)
+                       RtlxUnicodeStringToOemSize(&FileName);
+
+               if (Fcb->AnsiFileName.MaximumLength < FileName.Length)
+               {
+                       ExFreePool(Fcb->AnsiFileName.Buffer);
+
+                       Fcb->AnsiFileName.Buffer = 
+                               ExAllocatePoolWithTag(PagedPool, Fcb->AnsiFileName.Length + 1, FFS_POOL_TAG);
+
+                       if (!Fcb->AnsiFileName.Buffer)
+                       {
+                               Status = STATUS_INSUFFICIENT_RESOURCES;
+                               goto errorout;
+                       }
+
+                       RtlZeroMemory(Fcb->AnsiFileName.Buffer, 
+                                       Fcb->AnsiFileName.Length + 1);
+                       Fcb->AnsiFileName.MaximumLength = 
+                               Fcb->AnsiFileName.Length + 1;
+               }
+
+               FFSUnicodeToOEM(&(Fcb->AnsiFileName),
+                               &FileName);
+
+#endif
+
+               if (bMove)
+               {
+                       FFSNotifyReportChange(
+                                       IrpContext,
+                                       Vcb,
+                                       Fcb,
+                                       (IsDirectory(Fcb) ?
+                                               FILE_NOTIFY_CHANGE_DIR_NAME :
+                                               FILE_NOTIFY_CHANGE_FILE_NAME),
+                                       FILE_ACTION_REMOVED);
+
+               }
+               else
+               {
+                       FFSNotifyReportChange(
+                                       IrpContext,
+                                       Vcb,
+                                       Fcb,
+                                       (IsDirectory(Fcb) ?
+                                               FILE_NOTIFY_CHANGE_DIR_NAME :
+                                               FILE_NOTIFY_CHANGE_FILE_NAME),
+                                       FILE_ACTION_RENAMED_OLD_NAME);
+
+               }
+
+               FFSDeleteMcbNode(Vcb, Fcb->FFSMcb->Parent, Fcb->FFSMcb);
+               FFSAddMcbNode(Vcb, TargetMcb, Fcb->FFSMcb);
+
+               if (bMove)
+               {
+                       FFSNotifyReportChange(
+                                       IrpContext,
+                                       Vcb,
+                                       Fcb,
+                                       (IsDirectory(Fcb) ?
+                                               FILE_NOTIFY_CHANGE_DIR_NAME :
+                                               FILE_NOTIFY_CHANGE_FILE_NAME),
+                                       FILE_ACTION_ADDED);
+               }
+               else
+               {
+                       FFSNotifyReportChange(
+                                       IrpContext,
+                                       Vcb,
+                                       Fcb,
+                                       (IsDirectory(Fcb) ?
+                                               FILE_NOTIFY_CHANGE_DIR_NAME :
+                                               FILE_NOTIFY_CHANGE_FILE_NAME),
+                                       FILE_ACTION_RENAMED_NEW_NAME);
+
+               }
+       }
+
+errorout:
+
+       return Status;
+}
+
+
+__drv_mustHoldCriticalRegion
+BOOLEAN
+FFSDeleteFile(
+       PFFS_IRP_CONTEXT IrpContext,
+       PFFS_VCB         Vcb,
+       PFFS_FCB         Fcb)
+{
+       BOOLEAN         bRet = FALSE;
+       LARGE_INTEGER   AllocationSize;
+       PFFS_FCB        Dcb = NULL;
+
+       NTSTATUS        Status;
+
+    PAGED_CODE();
+
+       FFSPrint((DBG_INFO, "FFSDeleteFile: File %S (%xh) will be deleted!\n",
+                               Fcb->FFSMcb->ShortName.Buffer, Fcb->FFSMcb->Inode));
+
+       if (IsFlagOn(Fcb->Flags, FCB_FILE_DELETED))
+       {
+               return TRUE;
+       }
+
+       if (FlagOn(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY))
+       {
+               if (!FFSIsDirectoryEmpty(Vcb, Fcb))
+               {
+                       ClearFlag(Fcb->Flags, FCB_DELETE_PENDING);
+
+                       return FALSE;
+               }
+       }
+
+       FFSPrint((DBG_INFO, "FFSDeleteFile: FFSSB->S_FREE_BLOCKS = %xh .\n",
+                               Vcb->ffs_super_block->fs_size - Vcb->ffs_super_block->fs_dsize));
+
+       Status = STATUS_UNSUCCESSFUL;
+
+       {
+               if (Fcb->FFSMcb->Parent->FFSFcb)
+               {
+                       Status = FFSRemoveEntry(
+                                       IrpContext, Vcb, 
+                                       Fcb->FFSMcb->Parent->FFSFcb,
+                                       (FlagOn(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY) ?
+                                               DT_DIR : DT_REG),
+                                       Fcb->FFSMcb->Inode);
+               }
+               else
+               {
+                       Dcb = FFSCreateFcbFromMcb(Vcb, Fcb->FFSMcb->Parent);
+                       if (Dcb)
+                       {
+                               Status = FFSRemoveEntry(
+                                               IrpContext, Vcb, Dcb,
+                                               (FlagOn(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY) ?
+                                                       DT_DIR : DT_REG),
+                                               Fcb->FFSMcb->Inode);
+                       }
+               }
+       }
+
+       if (NT_SUCCESS(Status))
+       {
+               Fcb->dinode1->di_nlink--;
+
+               if (IsDirectory(Fcb))
+               {
+                       if (Fcb->dinode1->di_nlink < 2)
+                       {
+                               bRet = TRUE;
+                       }
+               }
+               else
+               {
+                       if (Fcb->dinode1->di_nlink == 0)
+                       {
+                               bRet = TRUE;
+                       }
+               }
+       }
+
+
+       if (bRet)
+       {
+               AllocationSize.QuadPart = (LONGLONG)0;
+               bRet = FFSTruncateFile(IrpContext, Vcb, Fcb, &AllocationSize);
+
+               //
+               // Update the inode's data length . It should be ZERO if succeeds.
+               //
+
+               if (Fcb->dinode1->di_size > Fcb->Header.AllocationSize.LowPart)
+               {
+                       Fcb->dinode1->di_size = Fcb->Header.AllocationSize.LowPart;
+               }
+
+               Fcb->Header.FileSize.QuadPart = (LONGLONG) Fcb->dinode1->di_size;
+
+               if (bRet)
+               {
+                       {
+                               LARGE_INTEGER SysTime;
+                               KeQuerySystemTime(&SysTime);
+
+                               /*Fcb->dinode->di_dtime = FFSInodeTime(SysTime); XXX */
+
+                               FFSv1SaveInode(IrpContext, Vcb, Fcb->FFSMcb->Inode, Fcb->dinode1);
+                       }
+
+                       if (IsDirectory(Fcb))
+                       {
+                               bRet = FFSFreeInode(IrpContext, Vcb, Fcb->FFSMcb->Inode, DT_DIR);
+                       }
+                       else
+                       {
+                               bRet = FFSFreeInode(IrpContext, Vcb, Fcb->FFSMcb->Inode, DT_REG);
+                       }
+
+                       SetFlag(Fcb->Flags, FCB_FILE_DELETED);
+                       FFSDeleteMcbNode(Vcb, Fcb->FFSMcb->Parent, Fcb->FFSMcb);
+               }
+               else
+               {
+                       FFSv1SaveInode(IrpContext, Vcb, Fcb->FFSMcb->Inode, Fcb->dinode1);
+               }
+       }
+       else
+       {
+               FFSv1SaveInode(IrpContext, Vcb, Fcb->FFSMcb->Inode, Fcb->dinode1);
+       }
+
+       FFSPrint((DBG_INFO, "FFSDeleteFile: Succeed... FFSSB->S_FREE_BLOCKS = %xh .\n",
+                               Vcb->ffs_super_block->fs_size - Vcb->ffs_super_block->fs_dsize));
+
+       return bRet;
+}
+
+#endif // !FFS_READ_ONLY
diff --git a/reactos/drivers/filesystems/ffs/src/flush.c b/reactos/drivers/filesystems/ffs/src/flush.c
new file mode 100644 (file)
index 0000000..f3f4231
--- /dev/null
@@ -0,0 +1,312 @@
+/* 
+ * FFS File System Driver for Windows
+ *
+ * flush.c
+ *
+ * 2004.5.6 ~
+ *
+ * Lee Jae-Hong, http://www.pyrasis.com
+ *
+ * See License.txt
+ *
+ */
+
+#include "ntifs.h"
+#include "ffsdrv.h"
+
+/* Globals */
+
+extern PFFS_GLOBAL FFSGlobal;
+
+
+/* Definitions */
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE, FFSFlushFile)
+#pragma alloc_text(PAGE, FFSFlushFiles)
+#pragma alloc_text(PAGE, FFSFlushVolume)
+#pragma alloc_text(PAGE, FFSFlush)
+#endif
+
+#ifdef _PREFAST_
+IO_COMPLETION_ROUTINE FFSFlushCompletionRoutine;
+#endif // _PREFAST_
+
+NTSTATUS NTAPI
+FFSFlushCompletionRoutine(
+       IN PDEVICE_OBJECT DeviceObject,
+       IN PIRP Irp,
+       IN PVOID Contxt)
+
+{
+       if (Irp->PendingReturned)
+               IoMarkIrpPending(Irp);
+
+
+       if (Irp->IoStatus.Status == STATUS_INVALID_DEVICE_REQUEST)
+               Irp->IoStatus.Status = STATUS_SUCCESS;
+
+       return STATUS_SUCCESS;
+}
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSFlushFiles(
+       IN PFFS_VCB Vcb,
+       BOOLEAN     bShutDown)
+{
+       IO_STATUS_BLOCK    IoStatus;
+
+       PFFS_FCB        Fcb;
+       PLIST_ENTRY     ListEntry;
+
+    PAGED_CODE();
+
+       if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY) ||
+                       IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED))
+       {
+               return STATUS_SUCCESS;
+       }
+
+       FFSPrint((DBG_INFO, "Flushing Files ...\n"));
+
+       // Flush all Fcbs in Vcb list queue.
+       {
+               for (ListEntry = Vcb->FcbList.Flink;
+                               ListEntry != &Vcb->FcbList;
+                               ListEntry = ListEntry->Flink)
+               {
+                       Fcb = CONTAINING_RECORD(ListEntry, FFS_FCB, Next);
+
+                       if (ExAcquireResourceExclusiveLite(
+                                               &Fcb->MainResource,
+                                               TRUE))
+                       {
+                               IoStatus.Status = FFSFlushFile(Fcb);
+#if 0
+/*
+                               if (bShutDown)
+                                       IoStatus.Status = FFSPurgeFile(Fcb, TRUE);
+                               else
+                                       IoStatus.Status = FFSFlushFile(Fcb);
+*/
+#endif
+                               ExReleaseResourceForThreadLite(
+                                               &Fcb->MainResource,
+                                               ExGetCurrentResourceThread());
+                       }
+               }
+       }
+
+       return IoStatus.Status;
+}
+
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSFlushVolume(
+       IN PFFS_VCB Vcb,
+       BOOLEAN     bShutDown)
+{
+       IO_STATUS_BLOCK    IoStatus;
+
+    PAGED_CODE();
+
+       if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY) ||
+                       IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED))
+       {
+               return STATUS_SUCCESS;
+       }
+
+       FFSPrint((DBG_INFO, "FFSFlushVolume: Flushing Vcb ...\n"));
+
+       ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
+       ExReleaseResourceLite(&Vcb->PagingIoResource);
+
+       CcFlushCache(&(Vcb->SectionObject), NULL, 0, &IoStatus);
+
+       return IoStatus.Status;       
+}
+
+
+NTSTATUS
+FFSFlushFile(
+       IN PFFS_FCB Fcb)
+{
+       IO_STATUS_BLOCK    IoStatus;
+
+    PAGED_CODE();
+
+       ASSERT(Fcb != NULL);
+
+       ASSERT((Fcb->Identifier.Type == FFSFCB) &&
+                       (Fcb->Identifier.Size == sizeof(FFS_FCB)));
+
+       if (IsDirectory(Fcb))
+               return STATUS_SUCCESS;
+
+       FFSPrint((DBG_INFO, "FFSFlushFile: Flushing File Inode=%xh %S ...\n", 
+                               Fcb->FFSMcb->Inode, Fcb->FFSMcb->ShortName.Buffer));
+       /*
+       {
+               ULONG ResShCnt, ResExCnt; 
+               ResShCnt = ExIsResourceAcquiredSharedLite(&Fcb->PagingIoResource);
+               ResExCnt = ExIsResourceAcquiredExclusiveLite(&Fcb->PagingIoResource);
+
+               FFSPrint((DBG_INFO, "FFSFlushFile: PagingIoRes: %xh:%xh\n", ResShCnt, ResExCnt));
+       }
+       */
+       CcFlushCache(&(Fcb->SectionObject), NULL, 0, &IoStatus);
+
+       ClearFlag(Fcb->Flags, FCB_FILE_MODIFIED);
+
+       return IoStatus.Status;
+}
+
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSFlush(
+       IN PFFS_IRP_CONTEXT IrpContext)
+{
+       NTSTATUS                Status;
+
+       PIRP                    Irp;
+       PIO_STACK_LOCATION      IrpSp;
+
+       PFFS_VCB                Vcb = 0;
+       PFFS_FCBVCB             FcbOrVcb = 0;
+       PFILE_OBJECT            FileObject;
+
+       PDEVICE_OBJECT          DeviceObject;
+
+       BOOLEAN                 MainResourceAcquired = FALSE;
+
+    PAGED_CODE();
+
+       _SEH2_TRY
+       {
+               ASSERT(IrpContext);
+
+               ASSERT((IrpContext->Identifier.Type == FFSICX) &&
+                               (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
+
+               DeviceObject = IrpContext->DeviceObject;
+
+               //
+               // This request is not allowed on the main device object
+               //
+               if (DeviceObject == FFSGlobal->DeviceObject)
+               {
+                       Status = STATUS_INVALID_DEVICE_REQUEST;
+                       _SEH2_LEAVE;
+               }
+
+               Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;
+
+               ASSERT(Vcb != NULL);
+
+               ASSERT((Vcb->Identifier.Type == FFSVCB) &&
+                               (Vcb->Identifier.Size == sizeof(FFS_VCB)));
+
+               ASSERT(IsMounted(Vcb));
+
+               if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY) ||
+                               IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED))
+               {
+                       Status = STATUS_SUCCESS;
+                       _SEH2_LEAVE;
+               }
+
+               Irp = IrpContext->Irp;
+
+               IrpSp = IoGetCurrentIrpStackLocation(Irp);
+
+               FileObject = IrpContext->FileObject;
+
+               FcbOrVcb = (PFFS_FCBVCB)FileObject->FsContext;
+
+               ASSERT(FcbOrVcb != NULL);
+#ifdef _MSC_VER
+#pragma prefast( suppress: 28137, "by design" )
+#endif
+               if (!ExAcquireResourceExclusiveLite(
+                                       &FcbOrVcb->MainResource,
+                                       IrpContext->IsSynchronous))
+               {
+                       Status = STATUS_PENDING;
+                       _SEH2_LEAVE;
+               }
+
+               MainResourceAcquired = TRUE;
+
+               if (FcbOrVcb->Identifier.Type == FFSVCB)
+               {
+                       Status = FFSFlushFiles((PFFS_VCB)(FcbOrVcb), FALSE);
+
+                       if (NT_SUCCESS(Status))
+                       {
+                               _SEH2_LEAVE;
+                       }
+
+                       Status = FFSFlushVolume((PFFS_VCB)(FcbOrVcb), FALSE);
+
+                       if (NT_SUCCESS(Status) && IsFlagOn(Vcb->StreamObj->Flags, FO_FILE_MODIFIED))
+                       {
+                               ClearFlag(Vcb->StreamObj->Flags, FO_FILE_MODIFIED);
+                       }
+               }
+               else if (FcbOrVcb->Identifier.Type == FFSFCB)
+               {
+                       Status = FFSFlushFile((PFFS_FCB)(FcbOrVcb));
+
+                       if (NT_SUCCESS(Status) && IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED))
+                       {
+                               ClearFlag(FileObject->Flags, FO_FILE_MODIFIED);
+                       }
+               }
+       }
+
+       _SEH2_FINALLY
+       {
+               if (MainResourceAcquired)
+               {
+                       ExReleaseResourceForThreadLite(
+                                       &FcbOrVcb->MainResource,
+                                       ExGetCurrentResourceThread());
+               }
+
+               if (!IrpContext->ExceptionInProgress)
+               {
+                       if (!IsFlagOn(Vcb->Flags, VCB_READ_ONLY))
+                       {
+                               // Call the disk driver to flush the physial media.
+                               NTSTATUS DriverStatus;
+                               PIO_STACK_LOCATION NextIrpSp;
+
+                IrpSp = IoGetCurrentIrpStackLocation(IrpContext->Irp);
+                               NextIrpSp = IoGetNextIrpStackLocation(IrpContext->Irp);
+
+                               *NextIrpSp = *IrpSp;
+
+                               IoSetCompletionRoutine(IrpContext->Irp,
+                                               FFSFlushCompletionRoutine,
+                                               NULL,
+                                               TRUE,
+                                               TRUE,
+                                               TRUE);
+
+                               DriverStatus = IoCallDriver(Vcb->TargetDeviceObject, IrpContext->Irp);
+
+                               Status = (DriverStatus == STATUS_INVALID_DEVICE_REQUEST) ?
+                                       Status : DriverStatus;
+
+                               IrpContext->Irp = NULL;
+                       }
+
+                       FFSCompleteIrpContext(IrpContext, Status);
+               }
+       } _SEH2_END;
+
+       return Status;
+}
diff --git a/reactos/drivers/filesystems/ffs/src/fsctl.c b/reactos/drivers/filesystems/ffs/src/fsctl.c
new file mode 100644 (file)
index 0000000..251ea88
--- /dev/null
@@ -0,0 +1,1663 @@
+/* 
+ * FFS File System Driver for Windows
+ *
+ * fsctl.c
+ *
+ * 2004.5.6 ~
+ *
+ * Lee Jae-Hong, http://www.pyrasis.com
+ *
+ * See License.txt
+ *
+ */
+
+#include "ntifs.h"
+#include "ffsdrv.h"
+
+/* Globals */
+
+extern PFFS_GLOBAL FFSGlobal;
+
+
+/* Definitions */
+
+BOOLEAN
+FFSIsMediaWriteProtected (
+       IN PFFS_IRP_CONTEXT  IrpContext,
+       IN PDEVICE_OBJECT     TargetDevice);
+
+#ifdef ALLOC_PRAGMA
+//#pragma alloc_text(PAGE, FFSSetVpbFlag)
+//#pragma alloc_text(PAGE, FFSClearVpbFlag)
+#pragma alloc_text(PAGE, FFSGetPartition)
+#pragma alloc_text(PAGE, FFSLoadDiskLabel)
+#pragma alloc_text(PAGE, FFSIsHandleCountZero)
+#pragma alloc_text(PAGE, FFSLockVcb)
+#pragma alloc_text(PAGE, FFSLockVolume)
+#pragma alloc_text(PAGE, FFSUnlockVcb)
+#pragma alloc_text(PAGE, FFSUnlockVolume)
+#pragma alloc_text(PAGE, FFSAllowExtendedDasdIo)
+#pragma alloc_text(PAGE, FFSUserFsRequest)
+#pragma alloc_text(PAGE, FFSIsMediaWriteProtected)
+#pragma alloc_text(PAGE, FFSMountVolume)
+#pragma alloc_text(PAGE, FFSCheckDismount)
+#pragma alloc_text(PAGE, FFSPurgeVolume)
+#pragma alloc_text(PAGE, FFSPurgeFile)
+#pragma alloc_text(PAGE, FFSDismountVolume)
+#pragma alloc_text(PAGE, FFSIsVolumeMounted)
+#pragma alloc_text(PAGE, FFSVerifyVolume)
+#pragma alloc_text(PAGE, FFSFileSystemControl)
+#endif
+
+
+VOID
+FFSSetVpbFlag(
+       IN PVPB     Vpb,
+       IN USHORT   Flag)
+{
+       KIRQL OldIrql;
+
+       IoAcquireVpbSpinLock(&OldIrql);
+
+       Vpb->Flags |= Flag;
+
+       IoReleaseVpbSpinLock(OldIrql);
+}
+
+
+VOID
+FFSClearVpbFlag(
+       IN PVPB     Vpb,
+       IN USHORT   Flag)
+{
+       KIRQL OldIrql;
+
+       IoAcquireVpbSpinLock(&OldIrql);
+
+       Vpb->Flags &= ~Flag;
+
+       IoReleaseVpbSpinLock(OldIrql);
+}
+
+
+NTSTATUS
+FFSGetPartition(
+       IN PDEVICE_OBJECT DeviceObject,
+       OUT ULONGLONG     *StartOffset)
+{
+    CHAR                  Buffer[2048];
+    PIRP                  Irp;
+    IO_STATUS_BLOCK       IoStatus;
+    KEVENT                Event;
+    NTSTATUS              Status;
+    PARTITION_INFORMATION *PartInfo;
+
+    PAGED_CODE();
+
+    if (IsFlagOn(DeviceObject->Characteristics, FILE_FLOPPY_DISKETTE))
+    {
+        *StartOffset = 0;
+        return STATUS_SUCCESS;
+    }
+
+    KeInitializeEvent(&Event, NotificationEvent, FALSE);
+
+    Irp = IoBuildDeviceIoControlRequest(
+                       IOCTL_DISK_GET_PARTITION_INFO,
+                       DeviceObject,
+                       NULL,
+                       0,
+                       Buffer,
+                       2048,
+                       FALSE,
+                       &Event,
+                       &IoStatus);
+
+    if (!Irp)
+       {
+               return STATUS_INSUFFICIENT_RESOURCES;
+       }
+
+    Status = IoCallDriver(DeviceObject, Irp);
+    if (!NT_SUCCESS(Status))
+       {
+               return Status;
+       }
+
+    Status = KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
+    if (!NT_SUCCESS(Status))
+       {
+               return Status;
+       }
+
+    PartInfo = (PARTITION_INFORMATION *)Buffer;
+    *StartOffset = PartInfo->StartingOffset.QuadPart;
+
+    return Status;
+}
+
+
+NTSTATUS
+FFSLoadDiskLabel(
+       PDEVICE_OBJECT  DeviceObject,
+       IN PFFS_VCB     Vcb)
+{
+       NTSTATUS         Status;
+       PFFS_SUPER_BLOCK FFSSb;
+       PDISKLABEL       Disklabel;
+       int              i;
+       int              RootFS_VERSION;
+       ULONGLONG        StartOffset = 0;
+       ULONGLONG        FSOffset = 0;
+       ULONGLONG        FSRootOffset = 0;
+
+    PAGED_CODE();
+
+       Disklabel = (PDISKLABEL)ExAllocatePoolWithTag(PagedPool, sizeof(DISKLABEL), FFS_POOL_TAG);
+       
+       FFSReadDisk(Vcb, (LABELSECTOR * SECTOR_SIZE + LABELOFFSET), sizeof(DISKLABEL), (PVOID)Disklabel, FALSE);
+
+       if (Disklabel->d_magic == DISKMAGIC)
+       {
+               KdPrint(("FFSLoadDiskLabel() Disklabel magic ok\n"));
+
+               Status = STATUS_SUCCESS;
+       }
+       else
+       {
+                       KdPrint(("FFSLoadDiskLabel() No BSD disklabel found, trying to find BSD file system on \"normal\" partition.\n"));
+
+                       if ((FFSSb = FFSLoadSuper(Vcb, FALSE, FSOffset + SBLOCK_UFS1)) &&
+                               (FFSSb->fs_magic == FS_UFS1_MAGIC))
+                       {
+                               FFSPrint((DBG_VITAL, "FFSLoadDiskLabel() \"normal\" partition of FFSv1 file system is found.\n"));
+/*
+                               if ((FFSSb->fs_fsmnt[0] == '/') && (FFSSb->fs_fsmnt[1] == '\0'))
+                               {
+                                       FFSGlobal->RootPartition = i;
+                                       FSRootOffset = FSOffset;
+                                       RootFS_VERSION = 1;
+                               }
+*/
+                               FS_VERSION = 1;
+                Vcb->FSOffset[0] = 0;
+                Vcb->PartitionNumber = 0;
+                               Vcb->ffs_super_block = FFSSb;
+                               Status = STATUS_SUCCESS;
+                return Status;
+                       }
+                       else if ((FFSSb = FFSLoadSuper(Vcb, FALSE, FSOffset + SBLOCK_UFS2)) &&
+                                       (FFSSb->fs_magic == FS_UFS2_MAGIC))
+                       {
+                               FFSPrint((DBG_VITAL, "FFSLoadDiskLabel() \"normal\" partition of FFSv2 file system is found.\n"));
+/*
+                               if ((FFSSb->fs_fsmnt[0] == '/') && (FFSSb->fs_fsmnt[1] == '\0'))
+                               {
+                                       FFSGlobal->RootPartition = i;
+                                       FSRootOffset = FSOffset;
+                                       RootFS_VERSION = 2;
+                               }
+*/
+                               FS_VERSION = 2;
+                Vcb->FSOffset[0] = 0;
+                Vcb->PartitionNumber = 0;
+                               Vcb->ffs_super_block = FFSSb;
+                               Status = STATUS_SUCCESS;
+                return Status;
+                       }
+            else
+            {
+                KdPrint(("FFSLoadDiskLabel() No BSD file system was found on the \"normal\" partition.\n"));
+                Status = STATUS_UNRECOGNIZED_VOLUME;
+                return Status;
+            }
+       }
+
+       Status = FFSGetPartition(DeviceObject, &StartOffset);
+       if (!NT_SUCCESS(Status))
+       {
+               KdPrint(("FFSLoadDiskLabel() Slice info failed, Status %u\n", Status));
+               return Status;
+       }
+
+    Vcb->PartitionNumber = FFSGlobal->PartitionNumber;
+
+       KdPrint(("FFSLoadDiskLabel() Selected BSD Label : %d, StartOffset : %x\n", Vcb->PartitionNumber, StartOffset));
+
+       for (i = 0; i < MAXPARTITIONS; i++)
+       {
+               if (Disklabel->d_partitions[i].p_fstype == FS_BSDFFS)
+               {
+                       /* Important */
+                       FSOffset = Disklabel->d_partitions[i].p_offset;
+                       FSOffset = FSOffset * SECTOR_SIZE;
+                       //FSOffset = FSOffset - StartOffset;
+                       Vcb->FSOffset[i] = FSOffset;
+                       /* Important */
+
+                       KdPrint(("FFSLoadDiskLabel() Label %d, FS_BSDFFS, %x\n", i, Vcb->FSOffset[i]));
+
+                       if ((FFSSb = FFSLoadSuper(Vcb, FALSE, FSOffset + SBLOCK_UFS1)) &&
+                               (FFSSb->fs_magic == FS_UFS1_MAGIC))
+                       {
+                               FFSPrint((DBG_VITAL, "FFSLoadDiskLabel() Label %d of FFSv1 file system is found.\n", i));
+
+                               if ((FFSSb->fs_fsmnt[0] == '/') && (FFSSb->fs_fsmnt[1] == '\0'))
+                               {
+                                       Vcb->RootPartition = i;
+                                       FSRootOffset = FSOffset;
+                                       RootFS_VERSION = 1;
+                               }
+
+                               FS_VERSION = 1;
+                               
+                               if (i == (int)Vcb->PartitionNumber)
+                               {
+                                       Vcb->ffs_super_block = FFSSb;
+                               }
+
+                               Status = STATUS_SUCCESS;
+                       }
+                       else if ((FFSSb = FFSLoadSuper(Vcb, FALSE, FSOffset + SBLOCK_UFS2)) &&
+                                       (FFSSb->fs_magic == FS_UFS2_MAGIC))
+                       {
+                               FFSPrint((DBG_VITAL, "FFSLoadDiskLabel() Label %d of FFSv2 file system is found.\n", i));
+
+                               if ((FFSSb->fs_fsmnt[0] == '/') && (FFSSb->fs_fsmnt[1] == '\0'))
+                               {
+                                       Vcb->RootPartition = i;
+                                       FSRootOffset = FSOffset;
+                                       RootFS_VERSION = 2;
+                               }
+
+                               FS_VERSION = 2;
+
+                               if (i == (int)Vcb->PartitionNumber)
+                               {
+                                       Vcb->ffs_super_block = FFSSb;
+                               }
+
+                               Status = STATUS_SUCCESS;
+                       }
+               }
+#if 0
+               else if (i == (int)FFSGlobal->PartitionNumber)
+               {
+                       /* ¼±ÅõȠBSD ÆÄƼ¼ÇÀÌ µð½ºÅ©¿¡ ¾øÀ» °æ¿ì Root ÆÄƼ¼ÇÀ¸·Î ´ëü */
+                       if (RootFS_VERSION == 1)
+                       {
+                               FFSSb = FFSLoadSuper(Vcb, FALSE, FSRootOffset + SBLOCK_UFS1);
+                               Vcb->ffs_super_block = FFSSb;
+                               FFSGlobal->PartitionNumber = FFSGlobal->RootPartition;
+                       }
+                       else
+                       {
+                               FFSSb = FFSLoadSuper(Vcb, FALSE, FSRootOffset + SBLOCK_UFS2);
+                               Vcb->ffs_super_block = FFSSb;
+                               FFSGlobal->PartitionNumber = FFSGlobal->RootPartition;
+                       }
+               }
+#endif
+       }
+
+       if (Vcb->ffs_super_block == NULL)
+               Status = STATUS_UNRECOGNIZED_VOLUME;
+
+       return Status;
+}
+
+
+BOOLEAN
+FFSIsHandleCountZero(
+       IN PFFS_VCB Vcb)
+{
+       PFFS_FCB   Fcb;
+       PLIST_ENTRY List;
+
+    PAGED_CODE();
+
+       for(List = Vcb->FcbList.Flink;
+                       List != &Vcb->FcbList;
+                       List = List->Flink)
+       {
+               Fcb = CONTAINING_RECORD(List, FFS_FCB, Next);
+
+               ASSERT((Fcb->Identifier.Type == FFSFCB) &&
+                               (Fcb->Identifier.Size == sizeof(FFS_FCB)));
+
+               FFSPrint((DBG_INFO, "FFSIsHandleCountZero: Inode:%xh File:%S OpenHandleCount=%xh\n",
+                                       Fcb->FFSMcb->Inode, Fcb->FFSMcb->ShortName.Buffer, Fcb->OpenHandleCount));
+
+               if (Fcb->OpenHandleCount)
+               {
+                       return FALSE;
+               }
+       }
+
+       return TRUE;
+}
+
+
+NTSTATUS
+FFSLockVcb(
+       IN PFFS_VCB     Vcb,
+       IN PFILE_OBJECT FileObject)
+{
+       NTSTATUS           Status;
+
+    PAGED_CODE();
+
+       _SEH2_TRY
+       {
+               if (FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED))
+               {
+                       FFSPrint((DBG_INFO, "FFSLockVolume: Volume is already locked.\n"));
+
+                       Status = STATUS_ACCESS_DENIED;
+
+                       _SEH2_LEAVE;
+               }
+
+               if (Vcb->OpenFileHandleCount > (ULONG)(FileObject ? 1 : 0))
+               {
+                       FFSPrint((DBG_INFO, "FFSLockVcb: There are still opened files.\n"));
+
+                       Status = STATUS_ACCESS_DENIED;
+
+                       _SEH2_LEAVE;
+               }
+
+               if (!FFSIsHandleCountZero(Vcb))
+               {
+                       FFSPrint((DBG_INFO, "FFSLockVcb: Thare are still opened files.\n"));
+
+                       Status = STATUS_ACCESS_DENIED;
+
+                       _SEH2_LEAVE;
+               }
+
+               SetFlag(Vcb->Flags, VCB_VOLUME_LOCKED);
+
+               FFSSetVpbFlag(Vcb->Vpb, VPB_LOCKED);
+
+               Vcb->LockFile = FileObject;
+
+               FFSPrint((DBG_INFO, "FFSLockVcb: Volume locked.\n"));
+
+               Status = STATUS_SUCCESS;
+       }
+
+       _SEH2_FINALLY
+       {
+               // Nothing
+       } _SEH2_END;
+
+       return Status;
+}
+
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSLockVolume(
+       IN PFFS_IRP_CONTEXT IrpContext)
+{
+       PIO_STACK_LOCATION IrpSp;
+       PDEVICE_OBJECT     DeviceObject;
+       PFFS_VCB           Vcb = 0;
+       NTSTATUS           Status;
+       BOOLEAN VcbResourceAcquired = FALSE;
+
+    PAGED_CODE();
+
+       _SEH2_TRY
+       {
+               ASSERT(IrpContext != NULL);
+
+               ASSERT((IrpContext->Identifier.Type == FFSICX) &&
+                               (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
+
+               DeviceObject = IrpContext->DeviceObject;
+
+               Status = STATUS_UNSUCCESSFUL;
+
+               //
+               // This request is not allowed on the main device object
+               //
+               if (DeviceObject == FFSGlobal->DeviceObject)
+               {
+                       Status = STATUS_INVALID_PARAMETER;
+                       _SEH2_LEAVE;
+               }
+
+               Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;
+
+               ASSERT(Vcb != NULL);
+
+               ASSERT((Vcb->Identifier.Type == FFSVCB) &&
+                               (Vcb->Identifier.Size == sizeof(FFS_VCB)));
+
+               ASSERT(IsMounted(Vcb));
+
+               IrpSp = IoGetCurrentIrpStackLocation(IrpContext->Irp);
+
+#if (_WIN32_WINNT >= 0x0500)
+               CcWaitForCurrentLazyWriterActivity();
+#endif
+               ExAcquireResourceExclusiveLite(
+                               &Vcb->MainResource,
+                               TRUE);
+
+               VcbResourceAcquired = TRUE;
+
+               Status = FFSLockVcb(Vcb, IrpSp->FileObject);        
+       }
+
+       _SEH2_FINALLY
+       {
+               if (VcbResourceAcquired)
+               {
+                       ExReleaseResourceForThreadLite(
+                                       &Vcb->MainResource,
+                                       ExGetCurrentResourceThread());
+               }
+
+               if (!IrpContext->ExceptionInProgress)
+               {
+                       FFSCompleteIrpContext(IrpContext,  Status);
+               }
+       } _SEH2_END;
+
+       return Status;
+}
+
+
+NTSTATUS
+FFSUnlockVcb(
+       IN PFFS_VCB     Vcb,
+       IN PFILE_OBJECT FileObject)
+{
+       NTSTATUS        Status;
+
+    PAGED_CODE();
+
+       _SEH2_TRY
+       {
+               if (FileObject && FileObject->FsContext != Vcb)
+               {
+                       Status = STATUS_NOT_LOCKED;
+                       _SEH2_LEAVE;
+               }
+
+               if (!FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED))
+               {
+                       FFSPrint((DBG_ERROR, ": FFSUnlockVcb: Volume is not locked.\n"));
+                       Status = STATUS_NOT_LOCKED;
+                       _SEH2_LEAVE;
+               }
+
+               if (Vcb->LockFile == FileObject)
+               {
+                       ClearFlag(Vcb->Flags, VCB_VOLUME_LOCKED);
+
+                       FFSClearVpbFlag(Vcb->Vpb, VPB_LOCKED);
+
+                       FFSPrint((DBG_INFO, "FFSUnlockVcb: Volume unlocked.\n"));
+
+                       Status = STATUS_SUCCESS;
+               }
+               else
+               {
+                       Status = STATUS_NOT_LOCKED;
+               }
+       }
+
+       _SEH2_FINALLY
+       {
+               // Nothing
+       } _SEH2_END;
+
+       return Status;
+}
+
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSUnlockVolume(
+       IN PFFS_IRP_CONTEXT IrpContext)
+{
+       PIO_STACK_LOCATION IrpSp;
+       PDEVICE_OBJECT     DeviceObject;
+       NTSTATUS           Status;
+       PFFS_VCB           Vcb = 0;
+       BOOLEAN            VcbResourceAcquired = FALSE;
+
+    PAGED_CODE();
+
+       _SEH2_TRY
+       {
+               ASSERT(IrpContext != NULL);
+
+               ASSERT((IrpContext->Identifier.Type == FFSICX) &&
+                               (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
+
+               DeviceObject = IrpContext->DeviceObject;
+
+               //
+               // This request is not allowed on the main device object
+               //
+               if (DeviceObject == FFSGlobal->DeviceObject)
+               {
+                       Status = STATUS_INVALID_PARAMETER;
+                       _SEH2_LEAVE;
+               }
+
+               Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;
+
+               ASSERT(Vcb != NULL);
+
+               ASSERT((Vcb->Identifier.Type == FFSVCB) &&
+                               (Vcb->Identifier.Size == sizeof(FFS_VCB)));
+
+               ASSERT(IsMounted(Vcb));
+
+               IrpSp = IoGetCurrentIrpStackLocation(IrpContext->Irp);
+
+               ExAcquireResourceExclusiveLite(
+                               &Vcb->MainResource,
+                               TRUE);
+
+               VcbResourceAcquired = TRUE;
+
+               Status = FFSUnlockVcb(Vcb, IrpSp->FileObject);
+       }
+       _SEH2_FINALLY
+       {
+               if (VcbResourceAcquired)
+               {
+                       ExReleaseResourceForThreadLite(
+                                       &Vcb->MainResource,
+                                       ExGetCurrentResourceThread());
+               }
+
+               if (!IrpContext->ExceptionInProgress)
+               {
+                       FFSCompleteIrpContext(IrpContext,  Status);
+               }
+       } _SEH2_END;
+
+       return Status;
+}
+
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSInvalidateVolumes(
+       IN PFFS_IRP_CONTEXT IrpContext)
+{
+       NTSTATUS            Status;
+       PIRP                Irp;
+       PIO_STACK_LOCATION  IrpSp;
+
+       HANDLE              Handle;
+
+       PLIST_ENTRY         ListEntry;
+
+       PFILE_OBJECT        FileObject;
+       PDEVICE_OBJECT      DeviceObject;
+       BOOLEAN             GlobalResourceAcquired = FALSE;
+
+       LUID Privilege = {SE_TCB_PRIVILEGE, 0};
+
+       _SEH2_TRY
+       {
+               Irp   = IrpContext->Irp;
+               IrpSp = IoGetCurrentIrpStackLocation(Irp);
+
+               if (!SeSinglePrivilegeCheck(Privilege, Irp->RequestorMode))
+               {
+                       Status = STATUS_PRIVILEGE_NOT_HELD;
+                       _SEH2_LEAVE;
+               }
+
+               if (
+#if !defined(_GNU_NTIFS_) || defined(__REACTOS__)
+                               IrpSp->Parameters.FileSystemControl.InputBufferLength
+#else
+                               ((PEXTENDED_IO_STACK_LOCATION)(IrpSp))->
+                               Parameters.FileSystemControl.InputBufferLength
+#endif
+                               != sizeof(HANDLE))
+               {
+                       Status = STATUS_INVALID_PARAMETER;
+
+                       _SEH2_LEAVE;
+               }
+
+               Handle = *(PHANDLE)Irp->AssociatedIrp.SystemBuffer;
+
+               Status = ObReferenceObjectByHandle(Handle,
+                               0,
+                               *IoFileObjectType,
+                               KernelMode,
+                               (void **)&FileObject,
+                               NULL);
+
+               if (!NT_SUCCESS(Status))
+               {
+                       _SEH2_LEAVE;
+               }
+               else
+               {
+                       ObDereferenceObject(FileObject);
+                       DeviceObject = FileObject->DeviceObject;
+               }
+
+               FFSPrint((DBG_INFO, "FFSInvalidateVolumes: FileObject=%xh ...\n", FileObject));
+
+               ExAcquireResourceExclusiveLite(
+                               &FFSGlobal->Resource,
+                               TRUE);
+
+               GlobalResourceAcquired = TRUE;
+
+               ListEntry = FFSGlobal->VcbList.Flink;
+
+               while (ListEntry != &FFSGlobal->VcbList)
+               {
+                       PFFS_VCB Vcb;
+
+                       Vcb = CONTAINING_RECORD(ListEntry, FFS_VCB, Next);
+
+                       ListEntry = ListEntry->Flink;
+
+                       FFSPrint((DBG_INFO, "FFSInvalidateVolumes: Vcb=%xh Vcb->Vpb=%xh...\n", Vcb, Vcb->Vpb));
+                       if (Vcb->Vpb && (Vcb->Vpb->RealDevice == DeviceObject))
+                       {
+                               ExAcquireResourceExclusiveLite(&Vcb->MainResource, TRUE);
+                               FFSPrint((DBG_INFO, "FFSInvalidateVolumes: FFSPurgeVolume...\n"));
+                               FFSPurgeVolume(Vcb, FALSE);
+                               ClearFlag(Vcb->Flags, VCB_MOUNTED);
+                               ExReleaseResourceLite(&Vcb->MainResource);
+
+                               //
+                               // Vcb is still attached on the list ......
+                               //
+
+                               if (ListEntry->Blink == &Vcb->Next)
+                               {
+                                       FFSPrint((DBG_INFO, "FFSInvalidateVolumes: FFSCheckDismount...\n"));
+                                       FFSCheckDismount(IrpContext, Vcb, FALSE);
+                               }
+                       }
+               }
+       }
+
+       _SEH2_FINALLY
+       {
+               if (GlobalResourceAcquired)
+               {
+                       ExReleaseResourceForThreadLite(
+                                       &FFSGlobal->Resource,
+                                       ExGetCurrentResourceThread());
+               }
+
+               FFSCompleteIrpContext(IrpContext, Status);
+       } _SEH2_END;
+
+       return Status;
+}
+
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSAllowExtendedDasdIo(
+       IN PFFS_IRP_CONTEXT IrpContext)
+{
+       PIO_STACK_LOCATION IrpSp;
+       PFFS_VCB Vcb;
+       PFFS_CCB Ccb;
+
+    PAGED_CODE();
+
+       IrpSp = IoGetCurrentIrpStackLocation(IrpContext->Irp);
+
+       Vcb = (PFFS_VCB)IrpSp->FileObject->FsContext;
+       Ccb = (PFFS_CCB)IrpSp->FileObject->FsContext2;
+
+       ASSERT(Vcb != NULL);
+
+       ASSERT((Vcb->Identifier.Type == FFSVCB) &&
+                       (Vcb->Identifier.Size == sizeof(FFS_VCB)));
+
+       ASSERT(IsMounted(Vcb));
+
+       if (Ccb)
+       {
+               SetFlag(Ccb->Flags, CCB_ALLOW_EXTENDED_DASD_IO);
+
+               FFSCompleteIrpContext(IrpContext, STATUS_SUCCESS);
+
+               return STATUS_SUCCESS;
+       }
+       else
+       {
+               return STATUS_INVALID_PARAMETER;
+       }
+}
+
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSUserFsRequest(
+       IN PFFS_IRP_CONTEXT IrpContext)
+{
+       PIRP                Irp;
+       PIO_STACK_LOCATION  IoStackLocation;
+       ULONG               FsControlCode;
+       NTSTATUS            Status;
+
+    PAGED_CODE();
+
+       ASSERT(IrpContext);
+
+       ASSERT((IrpContext->Identifier.Type == FFSICX) &&
+                       (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
+
+       Irp = IrpContext->Irp;
+
+       IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
+
+#if !defined(_GNU_NTIFS_) || defined(__REACTOS__)
+       FsControlCode =
+               IoStackLocation->Parameters.FileSystemControl.FsControlCode;
+#else
+       FsControlCode = ((PEXTENDED_IO_STACK_LOCATION)
+                       IoStackLocation)->Parameters.FileSystemControl.FsControlCode;
+#endif
+
+       switch (FsControlCode)
+       {
+               case FSCTL_LOCK_VOLUME:
+                       Status = FFSLockVolume(IrpContext);
+                       break;
+
+               case FSCTL_UNLOCK_VOLUME:
+                       Status = FFSUnlockVolume(IrpContext);
+                       break;
+
+               case FSCTL_DISMOUNT_VOLUME:
+                       Status = FFSDismountVolume(IrpContext);
+                       break;
+
+               case FSCTL_IS_VOLUME_MOUNTED:
+                       Status = FFSIsVolumeMounted(IrpContext);
+                       break;
+
+               case FSCTL_INVALIDATE_VOLUMES:
+                       Status = FFSInvalidateVolumes(IrpContext);
+                       break;
+
+#if (_WIN32_WINNT >= 0x0500)
+               case FSCTL_ALLOW_EXTENDED_DASD_IO:
+                       Status = FFSAllowExtendedDasdIo(IrpContext);
+                       break;
+#endif //(_WIN32_WINNT >= 0x0500)
+
+               default:
+
+                       FFSPrint((DBG_ERROR, "FFSUserFsRequest: Invalid User Request: %xh.\n", FsControlCode));
+                       Status = STATUS_INVALID_DEVICE_REQUEST;
+
+                       FFSCompleteIrpContext(IrpContext,  Status);
+       }
+
+       return Status;
+}
+
+
+BOOLEAN
+FFSIsMediaWriteProtected(
+       IN PFFS_IRP_CONTEXT   IrpContext,
+       IN PDEVICE_OBJECT     TargetDevice)
+{
+       PIRP            Irp;
+       KEVENT          Event;
+       NTSTATUS        Status;
+       IO_STATUS_BLOCK IoStatus;
+
+    PAGED_CODE();
+
+       KeInitializeEvent(&Event, NotificationEvent, FALSE);
+
+       Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_IS_WRITABLE,
+                       TargetDevice,
+                       NULL,
+                       0,
+                       NULL,
+                       0,
+                       FALSE,
+                       &Event,
+                       &IoStatus);
+
+       if (Irp == NULL)
+       {
+               return FALSE;
+       }
+
+       SetFlag(IoGetNextIrpStackLocation(Irp)->Flags, SL_OVERRIDE_VERIFY_VOLUME);
+
+       Status = IoCallDriver(TargetDevice, Irp);
+
+       if (Status == STATUS_PENDING)
+       {
+
+               (VOID) KeWaitForSingleObject(&Event,
+                                             Executive,
+                                             KernelMode,
+                                             FALSE,
+                                             (PLARGE_INTEGER)NULL);
+
+               Status = IoStatus.Status;
+       }
+
+       return (BOOLEAN)(Status == STATUS_MEDIA_WRITE_PROTECTED);
+}
+
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSMountVolume(
+       IN PFFS_IRP_CONTEXT IrpContext)
+{
+       PDEVICE_OBJECT              MainDeviceObject;
+       BOOLEAN                     GlobalDataResourceAcquired = FALSE;
+       PIRP                        Irp;
+       PIO_STACK_LOCATION          IoStackLocation;
+       PDEVICE_OBJECT              TargetDeviceObject;
+       NTSTATUS                    Status = STATUS_UNRECOGNIZED_VOLUME;
+       PDEVICE_OBJECT              VolumeDeviceObject = NULL;
+       PFFS_VCB                    Vcb;
+       PFFS_SUPER_BLOCK            FFSSb = NULL;
+       ULONG                       dwBytes;
+       DISK_GEOMETRY               DiskGeometry;
+
+    PAGED_CODE();
+
+       _SEH2_TRY
+       {
+               ASSERT(IrpContext != NULL);
+
+               ASSERT((IrpContext->Identifier.Type == FFSICX) &&
+                               (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
+
+               MainDeviceObject = IrpContext->DeviceObject;
+
+               //
+               //  Make sure we can wait.
+               //
+
+               SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
+
+               //
+               // This request is only allowed on the main device object
+               //
+               if (MainDeviceObject != FFSGlobal->DeviceObject)
+               {
+                       Status = STATUS_INVALID_DEVICE_REQUEST;
+                       _SEH2_LEAVE;
+               }
+
+               ExAcquireResourceExclusiveLite(
+                               &(FFSGlobal->Resource),
+                               TRUE);
+
+               GlobalDataResourceAcquired = TRUE;
+
+               if (FlagOn(FFSGlobal->Flags, FFS_UNLOAD_PENDING))
+               {
+                       Status = STATUS_UNRECOGNIZED_VOLUME;
+                       _SEH2_LEAVE;
+               }
+
+               Irp = IrpContext->Irp;
+
+               IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
+
+               TargetDeviceObject =
+                       IoStackLocation->Parameters.MountVolume.DeviceObject;
+
+               dwBytes = sizeof(DISK_GEOMETRY);
+               Status = FFSDiskIoControl(
+                                       TargetDeviceObject,
+                                       IOCTL_DISK_GET_DRIVE_GEOMETRY,
+                                       NULL,
+                                       0,
+                                       &DiskGeometry,
+                                       &dwBytes);
+
+               if (!NT_SUCCESS(Status))
+               {
+                       _SEH2_LEAVE;
+               }
+
+               Status = IoCreateDevice(
+                                       MainDeviceObject->DriverObject,
+                                       sizeof(FFS_VCB),
+                                       NULL,
+                                       FILE_DEVICE_DISK_FILE_SYSTEM,
+                                       0,
+                                       FALSE,
+                                       &VolumeDeviceObject);
+
+               if (!NT_SUCCESS(Status))
+               {
+                       _SEH2_LEAVE;
+               }
+
+               VolumeDeviceObject->StackSize = (CCHAR)(TargetDeviceObject->StackSize + 1);
+
+               if (TargetDeviceObject->AlignmentRequirement > 
+                               VolumeDeviceObject->AlignmentRequirement)
+               {
+
+                       VolumeDeviceObject->AlignmentRequirement = 
+                               TargetDeviceObject->AlignmentRequirement;
+               }
+
+               (IoStackLocation->Parameters.MountVolume.Vpb)->DeviceObject =
+                       VolumeDeviceObject;
+
+               Vcb = (PFFS_VCB)VolumeDeviceObject->DeviceExtension;
+
+               RtlZeroMemory(Vcb, sizeof(FFS_VCB));
+
+               Vcb->Identifier.Type = FFSVCB;
+               Vcb->Identifier.Size = sizeof(FFS_VCB);
+
+               Vcb->TargetDeviceObject = TargetDeviceObject;
+               Vcb->DiskGeometry = DiskGeometry;
+
+               Status = FFSLoadDiskLabel(TargetDeviceObject, Vcb);
+
+               if (!NT_SUCCESS(Status))
+               {
+                       _SEH2_LEAVE;
+               }
+
+
+               FFSSb = Vcb->ffs_super_block;
+
+               Vcb->BlockSize = FFSSb->fs_bsize;
+               Vcb->SectorBits = FFSLog2(SECTOR_SIZE);
+
+               Status = FFSInitializeVcb(IrpContext, Vcb, FFSSb, TargetDeviceObject, 
+                               VolumeDeviceObject, IoStackLocation->Parameters.MountVolume.Vpb);
+
+               if (NT_SUCCESS(Status))
+               {
+                       if (FFSIsMediaWriteProtected(IrpContext, TargetDeviceObject))
+                       {
+                               SetFlag(Vcb->Flags, VCB_WRITE_PROTECTED);
+                       }
+                       else
+                       {
+                               ClearFlag(Vcb->Flags, VCB_WRITE_PROTECTED);
+                       }
+
+                       SetFlag(Vcb->Flags, VCB_MOUNTED);
+
+                       FFSInsertVcb(Vcb);
+
+                       ClearFlag(VolumeDeviceObject->Flags, DO_DEVICE_INITIALIZING);
+               }
+       }
+
+       _SEH2_FINALLY
+       {
+               if (GlobalDataResourceAcquired)
+               {
+                       ExReleaseResourceForThreadLite(
+                                       &FFSGlobal->Resource,
+                                       ExGetCurrentResourceThread());
+               }
+
+               if (!NT_SUCCESS(Status))
+               {
+                       if (FFSSb)
+                       {
+                               ExFreePool(FFSSb);
+                       }
+
+                       if (VolumeDeviceObject)
+                       {
+                               IoDeleteDevice(VolumeDeviceObject);
+                       }
+               }
+
+               if (!IrpContext->ExceptionInProgress)
+               {
+                       if (NT_SUCCESS(Status))
+                       {
+                               ClearFlag(VolumeDeviceObject->Flags, DO_DEVICE_INITIALIZING);
+                       }
+
+                       FFSCompleteIrpContext(IrpContext,  Status);
+               }
+       } _SEH2_END;
+
+       return Status;
+}
+
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSVerifyVolume(
+       IN PFFS_IRP_CONTEXT IrpContext)
+{
+       PDEVICE_OBJECT          DeviceObject;
+       NTSTATUS                Status = STATUS_UNSUCCESSFUL;
+       PFFS_SUPER_BLOCK        FFSSb = NULL;
+       PFFS_VCB                Vcb = 0;
+       BOOLEAN                 VcbResourceAcquired = FALSE;
+       BOOLEAN                 GlobalResourceAcquired = FALSE;
+       PIRP                    Irp;
+       PIO_STACK_LOCATION      IoStackLocation;
+       ULONG                   ChangeCount;
+       ULONG                   dwReturn;
+
+    PAGED_CODE();
+
+       _SEH2_TRY
+       {
+               ASSERT(IrpContext != NULL);
+
+               ASSERT((IrpContext->Identifier.Type == FFSICX) &&
+                               (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
+
+               DeviceObject = IrpContext->DeviceObject;
+               //
+               // This request is not allowed on the main device object
+               //
+               if (DeviceObject == FFSGlobal->DeviceObject)
+               {
+                       Status = STATUS_INVALID_DEVICE_REQUEST;
+                       _SEH2_LEAVE;
+               }
+
+               ExAcquireResourceExclusiveLite(
+                               &FFSGlobal->Resource,
+                               TRUE);
+
+               GlobalResourceAcquired = TRUE;
+
+               Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;
+
+               ASSERT(Vcb != NULL);
+
+               ASSERT((Vcb->Identifier.Type == FFSVCB) &&
+                               (Vcb->Identifier.Size == sizeof(FFS_VCB)));
+
+               ExAcquireResourceExclusiveLite(
+                               &Vcb->MainResource,
+                               TRUE);
+
+               VcbResourceAcquired = TRUE;
+
+               if (!FlagOn(Vcb->TargetDeviceObject->Flags, DO_VERIFY_VOLUME))
+               {
+                       Status = STATUS_SUCCESS;
+                       _SEH2_LEAVE;
+               }
+
+               if (!IsMounted(Vcb))
+               {
+                       Status = STATUS_WRONG_VOLUME;
+                       _SEH2_LEAVE;
+               }
+
+               dwReturn = sizeof(ULONG);
+               Status = FFSDiskIoControl(
+                               Vcb->TargetDeviceObject,
+                               IOCTL_DISK_CHECK_VERIFY,
+                               NULL,
+                               0,
+                               &ChangeCount,
+                               &dwReturn);
+
+               if (ChangeCount != Vcb->ChangeCount)
+               {
+                       Status = STATUS_WRONG_VOLUME;
+                       _SEH2_LEAVE;
+               }
+
+               Irp = IrpContext->Irp;
+
+               IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
+
+               if (((((FFSSb = FFSLoadSuper(Vcb, TRUE, SBLOCK_UFS1)) != NULL) && (FFSSb->fs_magic == FS_UFS1_MAGIC)) ||
+                        (((FFSSb = FFSLoadSuper(Vcb, TRUE, SBLOCK_UFS2)) != NULL) && (FFSSb->fs_magic == FS_UFS2_MAGIC))) &&
+                               (memcmp(FFSSb->fs_id, SUPER_BLOCK->fs_id, 8) == 0) &&
+                               (memcmp(FFSSb->fs_volname, SUPER_BLOCK->fs_volname, 16) == 0))
+               {
+                       ClearFlag(Vcb->TargetDeviceObject->Flags, DO_VERIFY_VOLUME);
+
+                       if (FFSIsMediaWriteProtected(IrpContext, Vcb->TargetDeviceObject))
+                       {
+                               SetFlag(Vcb->Flags, VCB_WRITE_PROTECTED);
+                       }
+                       else
+                       {
+                               ClearFlag(Vcb->Flags, VCB_WRITE_PROTECTED);
+                       }
+
+                       FFSPrint((DBG_INFO, "FFSVerifyVolume: Volume verify succeeded.\n"));
+
+                       Status = STATUS_SUCCESS;
+               }
+               else
+               {
+                       Status = STATUS_WRONG_VOLUME;
+
+                       FFSPurgeVolume(Vcb, FALSE);
+
+                       SetFlag(Vcb->Flags, VCB_DISMOUNT_PENDING);
+
+                       ClearFlag(Vcb->TargetDeviceObject->Flags, DO_VERIFY_VOLUME);
+
+                       FFSPrint((DBG_INFO, "FFSVerifyVolume: Volume verify failed.\n"));
+               }
+       }
+
+       _SEH2_FINALLY
+       {
+               if (FFSSb)
+                       ExFreePool(FFSSb);
+
+               if (VcbResourceAcquired)
+               {
+                       ExReleaseResourceForThreadLite(
+                                       &Vcb->MainResource,
+                                       ExGetCurrentResourceThread());
+               }
+
+               if (GlobalResourceAcquired)
+               {
+                       ExReleaseResourceForThreadLite(
+                                       &FFSGlobal->Resource,
+                                       ExGetCurrentResourceThread());
+               }
+
+               if (!IrpContext->ExceptionInProgress)
+               {
+                       FFSCompleteIrpContext(IrpContext,  Status);
+               }
+       } _SEH2_END;
+
+       return Status;
+}
+
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSIsVolumeMounted(
+       IN PFFS_IRP_CONTEXT IrpContext)
+{
+    PAGED_CODE();
+
+       ASSERT(IrpContext);
+
+       ASSERT((IrpContext->Identifier.Type == FFSICX) &&
+                       (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
+
+       return FFSVerifyVolume(IrpContext);
+}
+
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSDismountVolume(
+       IN PFFS_IRP_CONTEXT IrpContext)
+{
+       PDEVICE_OBJECT  DeviceObject;
+       NTSTATUS        Status = STATUS_UNSUCCESSFUL;
+       PFFS_VCB        Vcb = 0;
+       BOOLEAN         VcbResourceAcquired = FALSE;
+
+    PAGED_CODE();
+
+       _SEH2_TRY
+       {
+               ASSERT(IrpContext != NULL);
+
+               ASSERT((IrpContext->Identifier.Type == FFSICX) &&
+                               (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
+
+               DeviceObject = IrpContext->DeviceObject;
+
+               //
+               // This request is not allowed on the main device object
+               //
+               if (DeviceObject == FFSGlobal->DeviceObject)
+               {
+                       Status = STATUS_INVALID_DEVICE_REQUEST;
+                       _SEH2_LEAVE;
+               }
+
+               Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;
+
+               ASSERT(Vcb != NULL);
+
+               ASSERT((Vcb->Identifier.Type == FFSVCB) &&
+                               (Vcb->Identifier.Size == sizeof(FFS_VCB)));
+
+               ASSERT(IsMounted(Vcb));
+
+               ExAcquireResourceExclusiveLite(
+                               &Vcb->MainResource,
+                               TRUE);
+
+               VcbResourceAcquired = TRUE;
+
+               if (IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING))
+               {
+                       Status = STATUS_VOLUME_DISMOUNTED;
+                       _SEH2_LEAVE;
+               }
+
+               /*        
+               if (!FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED))
+               {
+                       FFSPrint((DBG_ERROR, "FFSDismount: Volume is not locked.\n"));
+
+                       Status = STATUS_ACCESS_DENIED;
+                       _SEH2_LEAVE;
+               }
+               */
+
+               FFSFlushFiles(Vcb, FALSE);
+
+               FFSFlushVolume(Vcb, FALSE);
+
+               FFSPurgeVolume(Vcb, TRUE);
+
+               ExReleaseResourceForThreadLite(
+                               &Vcb->MainResource,
+                               ExGetCurrentResourceThread());
+
+               VcbResourceAcquired = FALSE;
+
+               FFSCheckDismount(IrpContext, Vcb, TRUE);
+
+               FFSPrint((DBG_INFO, "FFSDismount: Volume dismount pending.\n"));
+
+               Status = STATUS_SUCCESS;
+       }
+       _SEH2_FINALLY
+       {
+               if (VcbResourceAcquired)
+               {
+                       ExReleaseResourceForThreadLite(
+                                       &Vcb->MainResource,
+                                       ExGetCurrentResourceThread());
+               }
+
+               if (!IrpContext->ExceptionInProgress)
+               {
+                       FFSCompleteIrpContext(IrpContext,  Status);
+               }
+       } _SEH2_END;
+
+       return Status;
+}
+
+
+__drv_mustHoldCriticalRegion
+BOOLEAN
+FFSCheckDismount(
+       IN PFFS_IRP_CONTEXT  IrpContext,
+       IN PFFS_VCB          Vcb,
+       IN BOOLEAN           bForce)
+{
+       KIRQL   Irql;
+       PVPB    Vpb = Vcb->Vpb;
+       BOOLEAN bDeleted = FALSE;
+       ULONG   UnCleanCount = 0;
+
+    PAGED_CODE();
+
+       ExAcquireResourceExclusiveLite(
+                       &FFSGlobal->Resource, TRUE);
+
+       ExAcquireResourceExclusiveLite(
+                       &Vcb->MainResource, TRUE);
+
+       if ((IrpContext->MajorFunction == IRP_MJ_CREATE) &&
+                       (IrpContext->RealDevice == Vcb->RealDevice))
+       {
+               UnCleanCount = 3;
+       }
+       else
+       {
+               UnCleanCount = 2;
+       }
+
+       IoAcquireVpbSpinLock(&Irql);
+
+       if ((Vpb->ReferenceCount == UnCleanCount) || bForce)
+       {
+
+               if ((Vpb->ReferenceCount != UnCleanCount) && bForce)
+               {
+                       FFSBreakPoint();
+               }
+
+               ClearFlag(Vpb->Flags, VPB_MOUNTED);
+               ClearFlag(Vpb->Flags, VPB_LOCKED);
+
+               if ((Vcb->RealDevice != Vpb->RealDevice) &&
+#ifdef _MSC_VER
+#pragma prefast( suppress: 28175, "allowed in file system drivers" )
+#endif
+                               (Vcb->RealDevice->Vpb == Vpb))
+               {
+                       SetFlag(Vcb->RealDevice->Flags, DO_DEVICE_INITIALIZING);
+                       SetFlag(Vpb->Flags, VPB_PERSISTENT);
+               }
+
+               FFSRemoveVcb(Vcb);
+
+               ClearFlag(Vpb->Flags, VPB_MOUNTED);
+               SetFlag(Vcb->Flags, VCB_DISMOUNT_PENDING);
+
+               Vpb->DeviceObject = NULL;
+
+               bDeleted = TRUE;
+       }
+
+#if 0
+
+       else if ((Vpb->RealDevice->Vpb == Vpb) && bForce)
+       {
+               PVPB NewVpb;
+
+#define TAG_VPB                         ' bpV'
+
+               NewVpb = ExAllocatePoolWithTag(NonPagedPoolMustSucceed, 
+                               sizeof(VPB), TAG_VPB);
+
+               NewVpb->Type = IO_TYPE_VPB;
+               NewVpb->Size = sizeof(VPB);
+               NewVpb->RealDevice = Vcb->Vpb->RealDevice;
+
+               NewVpb->RealDevice->Vpb = NewVpb;
+
+               NewVpb->Flags = FlagOn(Vcb->Vpb->Flags, VPB_REMOVE_PENDING);
+
+               NewVpb = NULL;
+
+               ClearFlag(Vcb->Flags, VCB_MOUNTED);
+               ClearFlag(Vcb->Flags, VCB_DISMOUNT_PENDING);
+       }
+
+#endif
+
+       IoReleaseVpbSpinLock(Irql);
+
+       ExReleaseResourceForThreadLite(
+                       &Vcb->MainResource,
+                       ExGetCurrentResourceThread());
+
+       ExReleaseResourceForThreadLite(
+                       &FFSGlobal->Resource,
+                       ExGetCurrentResourceThread());
+
+       if (bDeleted)
+       {
+#if 0
+               FFSBreakPoint(); /* XP¿¡¼­ ºê·¹ÀÌÅ© Æ÷ÀÎÆ® ¹ß»ý */
+#endif
+
+               FFSFreeVcb(Vcb);
+       }
+
+       return bDeleted;
+}
+
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSPurgeVolume(
+       IN PFFS_VCB Vcb,
+       IN BOOLEAN  FlushBeforePurge)
+{
+       PFFS_FCB        Fcb;
+       LIST_ENTRY      FcbList;
+       PLIST_ENTRY     ListEntry;
+       PFCB_LIST_ENTRY FcbListEntry;
+
+    PAGED_CODE();
+
+       _SEH2_TRY
+       {
+               ASSERT(Vcb != NULL);
+
+               ASSERT((Vcb->Identifier.Type == FFSVCB) &&
+                               (Vcb->Identifier.Size == sizeof(FFS_VCB)));
+
+               if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY) ||
+                               IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED))
+               {
+                       FlushBeforePurge = FALSE;
+               }
+
+               FcbListEntry= NULL;
+               InitializeListHead(&FcbList);
+
+               for (ListEntry = Vcb->FcbList.Flink;
+                               ListEntry != &Vcb->FcbList;
+                               ListEntry = ListEntry->Flink)
+               {
+                       Fcb = CONTAINING_RECORD(ListEntry, FFS_FCB, Next);
+
+                       Fcb->ReferenceCount++;
+
+                       FFSPrint((DBG_INFO, "FFSPurgeVolume: %s refercount=%xh\n", Fcb->AnsiFileName.Buffer, Fcb->ReferenceCount));
+
+                       FcbListEntry = ExAllocatePoolWithTag(PagedPool, sizeof(FCB_LIST_ENTRY), FFS_POOL_TAG);
+
+                       if (FcbListEntry)
+                       {
+                               FcbListEntry->Fcb = Fcb;
+
+                               InsertTailList(&FcbList, &FcbListEntry->Next);
+                       }
+                       else
+                       {
+                               FFSPrint((DBG_ERROR, "FFSPurgeVolume: Error allocating FcbListEntry ...\n"));
+                       }
+               }
+
+               while (!IsListEmpty(&FcbList))
+               {
+                       ListEntry = RemoveHeadList(&FcbList);
+
+                       FcbListEntry = CONTAINING_RECORD(ListEntry, FCB_LIST_ENTRY, Next);
+
+                       Fcb = FcbListEntry->Fcb;
+
+                       if (ExAcquireResourceExclusiveLite(
+                                               &Fcb->MainResource,
+                                               TRUE))
+                       {
+                               FFSPurgeFile(Fcb, FlushBeforePurge);
+
+                               if (!Fcb->OpenHandleCount && Fcb->ReferenceCount == 1)
+                               {
+                                       RemoveEntryList(&Fcb->Next);
+                                       FFSFreeFcb(Fcb);
+                               }
+                               else
+                               {
+                                       ExReleaseResourceForThreadLite(
+                                               &Fcb->MainResource,
+                                               ExGetCurrentResourceThread());
+                               }
+                       }
+
+                       ExFreePool(FcbListEntry);
+               }
+
+               if (FlushBeforePurge)
+               {
+                       ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
+                       ExReleaseResourceLite(&Vcb->PagingIoResource);
+
+                       CcFlushCache(&Vcb->SectionObject, NULL, 0, NULL);
+               }
+
+               if (Vcb->SectionObject.ImageSectionObject)
+               {
+                       MmFlushImageSection(&Vcb->SectionObject, MmFlushForWrite);
+               }
+
+               if (Vcb->SectionObject.DataSectionObject)
+               {
+                       CcPurgeCacheSection(&Vcb->SectionObject, NULL, 0, FALSE);
+               }
+
+               FFSPrint((DBG_INFO, "FFSPurgeVolume: Volume flushed and purged.\n"));
+       }
+       _SEH2_FINALLY
+       {
+               // Nothing
+       } _SEH2_END;
+
+       return STATUS_SUCCESS;
+}
+
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSPurgeFile(
+       IN PFFS_FCB Fcb,
+       IN BOOLEAN  FlushBeforePurge)
+{
+       IO_STATUS_BLOCK    IoStatus;
+
+    PAGED_CODE();
+
+       ASSERT(Fcb != NULL);
+
+       ASSERT((Fcb->Identifier.Type == FFSFCB) &&
+                       (Fcb->Identifier.Size == sizeof(FFS_FCB)));
+
+
+       if(!IsFlagOn(Fcb->Vcb->Flags, VCB_READ_ONLY) && FlushBeforePurge &&
+                       !IsFlagOn(Fcb->Vcb->Flags, VCB_WRITE_PROTECTED))
+       {
+
+               FFSPrint((DBG_INFO, "FFSPurgeFile: CcFlushCache on %s.\n", 
+                                       Fcb->AnsiFileName.Buffer));
+
+               ExAcquireSharedStarveExclusive(&Fcb->PagingIoResource, TRUE);
+               ExReleaseResourceLite(&Fcb->PagingIoResource);
+
+               CcFlushCache(&Fcb->SectionObject, NULL, 0, &IoStatus);
+
+               ClearFlag(Fcb->Flags, FCB_FILE_MODIFIED);
+       }
+
+       if (Fcb->SectionObject.ImageSectionObject)
+       {
+
+               FFSPrint((DBG_INFO, "FFSPurgeFile: MmFlushImageSection on %s.\n", 
+                                       Fcb->AnsiFileName.Buffer));
+
+               MmFlushImageSection(&Fcb->SectionObject, MmFlushForWrite);
+       }
+
+       if (Fcb->SectionObject.DataSectionObject)
+       {
+
+               FFSPrint((DBG_INFO, "FFSPurgeFile: CcPurgeCacheSection on %s.\n",
+                                       Fcb->AnsiFileName.Buffer));
+
+               CcPurgeCacheSection(&Fcb->SectionObject, NULL, 0, FALSE);
+       }
+
+       return STATUS_SUCCESS;
+}
+
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSSelectBSDPartition(
+       IN PFFS_IRP_CONTEXT IrpContext)
+{
+       PIRP                Irp;
+       NTSTATUS            Status;
+       PFFS_BSD_PARTITION  BSDPartition;
+
+       _SEH2_TRY
+       {
+               ASSERT(IrpContext != NULL);
+
+               ASSERT((IrpContext->Identifier.Type == FFSICX) &&
+                               (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
+
+               Irp = IrpContext->Irp;
+
+               BSDPartition = (PFFS_BSD_PARTITION)Irp->AssociatedIrp.SystemBuffer;
+               FFSGlobal->PartitionNumber = BSDPartition->Number;
+
+               Status = STATUS_SUCCESS;
+       }
+       _SEH2_FINALLY
+       {
+               if (!IrpContext->ExceptionInProgress)
+               {
+                       FFSCompleteIrpContext(IrpContext,  Status);
+               }
+       } _SEH2_END;
+
+       return Status;
+}
+
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSFileSystemControl(
+       IN PFFS_IRP_CONTEXT IrpContext)
+{
+       NTSTATUS    Status;
+
+    PAGED_CODE();
+
+       ASSERT(IrpContext);
+
+       ASSERT((IrpContext->Identifier.Type == FFSICX) &&
+                       (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
+
+       switch (IrpContext->MinorFunction)
+       {
+               case IRP_MN_USER_FS_REQUEST:
+                       Status = FFSUserFsRequest(IrpContext);
+                       break;
+
+               case IRP_MN_MOUNT_VOLUME:
+                       Status = FFSMountVolume(IrpContext);
+                       break;
+
+               case IRP_MN_VERIFY_VOLUME:
+                       Status = FFSVerifyVolume(IrpContext);
+                       break;
+
+               default:
+
+                       FFSPrint((DBG_ERROR, "FFSFilsSystemControl: Invalid Device Request.\n"));
+                       Status = STATUS_INVALID_DEVICE_REQUEST;
+                       FFSCompleteIrpContext(IrpContext,  Status);
+       }
+
+       return Status;
+}
diff --git a/reactos/drivers/filesystems/ffs/src/init.c b/reactos/drivers/filesystems/ffs/src/init.c
new file mode 100644 (file)
index 0000000..df9189e
--- /dev/null
@@ -0,0 +1,453 @@
+/* 
+ * FFS File System Driver for Windows
+ *
+ * init.c
+ *
+ * 2004.5.6 ~
+ *
+ * Lee Jae-Hong, http://www.pyrasis.com
+ *
+ * See License.txt
+ *
+ */
+
+#include <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;
+}
diff --git a/reactos/drivers/filesystems/ffs/src/lock.c b/reactos/drivers/filesystems/ffs/src/lock.c
new file mode 100644 (file)
index 0000000..9ff3ba9
--- /dev/null
@@ -0,0 +1,137 @@
+/* 
+ * FFS File System Driver for Windows
+ *
+ * lock.c
+ *
+ * 2004.5.6 ~
+ *
+ * Lee Jae-Hong, http://www.pyrasis.com
+ *
+ * See License.txt
+ *
+ */
+
+#include "ntifs.h"
+#include "ffsdrv.h"
+
+/* Globals */
+
+extern PFFS_GLOBAL FFSGlobal;
+
+
+/* Definitions */
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE, FFSLockControl)
+#endif
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSLockControl(
+       IN PFFS_IRP_CONTEXT IrpContext)
+{
+       PDEVICE_OBJECT  DeviceObject;
+       BOOLEAN         CompleteRequest;
+       NTSTATUS        Status = STATUS_UNSUCCESSFUL;
+       PFILE_OBJECT    FileObject;
+       PFFS_FCB        Fcb;
+       PIRP            Irp;
+
+    PAGED_CODE();
+
+       _SEH2_TRY
+       {
+               ASSERT(IrpContext != NULL);
+
+               ASSERT((IrpContext->Identifier.Type == FFSICX) &&
+                               (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
+
+               DeviceObject = IrpContext->DeviceObject;
+
+               if (DeviceObject == FFSGlobal->DeviceObject)
+               {
+                       CompleteRequest = TRUE;
+                       Status = STATUS_INVALID_DEVICE_REQUEST;
+                       _SEH2_LEAVE;
+               }
+
+               FileObject = IrpContext->FileObject;
+
+               Fcb = (PFFS_FCB)FileObject->FsContext;
+
+               ASSERT(Fcb != NULL);
+
+               if (Fcb->Identifier.Type == FFSVCB)
+               {
+                       CompleteRequest = TRUE;
+                       Status = STATUS_INVALID_PARAMETER;
+                       _SEH2_LEAVE;
+               }
+
+               ASSERT((Fcb->Identifier.Type == FFSFCB) &&
+                               (Fcb->Identifier.Size == sizeof(FFS_FCB)));
+
+               if (FlagOn(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY))
+               {
+                       CompleteRequest = TRUE;
+                       Status = STATUS_INVALID_PARAMETER;
+                       _SEH2_LEAVE;
+               }
+
+               Irp = IrpContext->Irp;
+
+               //
+               // While the file has any byte range locks we set IsFastIoPossible to
+               // FastIoIsQuestionable so that the FastIoCheckIfPossible function is
+               // called to check the locks for any fast I/O read/write operation.
+               //
+               if (Fcb->Header.IsFastIoPossible != FastIoIsQuestionable)
+               {
+
+                       FFSPrint((DBG_INFO,
+                                               "FFSLockControl: %-16.16s %-31s %s\n",
+                                               FFSGetCurrentProcessName(),
+                                               "FastIoIsQuestionable",
+                                               Fcb->AnsiFileName.Buffer));
+
+                       Fcb->Header.IsFastIoPossible = FastIoIsQuestionable;
+               }
+
+               //
+               // FsRtlProcessFileLock acquires FileObject->FsContext->Resource while
+               // modifying the file locks and calls IoCompleteRequest when it's done.
+               //
+
+               CompleteRequest = FALSE;
+
+               Status = FsRtlProcessFileLock(
+                               &Fcb->FileLockAnchor,
+                               Irp,
+                               NULL);
+
+               if (!NT_SUCCESS(Status))
+               {
+                       FFSPrint((DBG_ERROR, 
+                                               "FFSLockControl: %-16.16s %-31s *** Status: %s (%#x) ***\n",
+                                               FFSGetCurrentProcessName(),
+                                               "IRP_MJ_LOCK_CONTROL",
+                                               FFSNtStatusToString(Status),
+                                               Status));
+               }
+       }
+
+       _SEH2_FINALLY
+       {
+               if (!IrpContext->ExceptionInProgress)
+               {
+                       if (!CompleteRequest)
+                       {
+                               IrpContext->Irp = NULL;
+                       }
+
+                       FFSCompleteIrpContext(IrpContext, Status);
+               }
+       } _SEH2_END;
+
+       return Status;
+}
diff --git a/reactos/drivers/filesystems/ffs/src/memory.c b/reactos/drivers/filesystems/ffs/src/memory.c
new file mode 100644 (file)
index 0000000..790a04b
--- /dev/null
@@ -0,0 +1,1979 @@
+/* 
+ * FFS File System Driver for Windows
+ *
+ * memory.c
+ *
+ * 2004.5.6 ~
+ *
+ * Lee Jae-Hong, http://www.pyrasis.com
+ *
+ * See License.txt
+ *
+ */
+
+#include "ntifs.h"
+#include "ffsdrv.h"
+
+/* Globals */
+
+extern PFFS_GLOBAL FFSGlobal;
+
+
+/* Definitions */
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE, FFSAllocateIrpContext)
+#pragma alloc_text(PAGE, FFSFreeIrpContext)
+#pragma alloc_text(PAGE, FFSv1AllocateFcb)
+#pragma alloc_text(PAGE, FFSv2AllocateFcb)
+#pragma alloc_text(PAGE, FFSFreeFcb)
+#pragma alloc_text(PAGE, FFSAllocateMcb)
+#pragma alloc_text(PAGE, FFSFreeMcb)
+#pragma alloc_text(PAGE, FFSSearchMcbTree)
+#pragma alloc_text(PAGE, FFSSearchMcb)
+#pragma alloc_text(PAGE, FFSGetFullFileName)
+#pragma alloc_text(PAGE, FFSRefreshMcb)
+#pragma alloc_text(PAGE, FFSAddMcbNode)
+#pragma alloc_text(PAGE, FFSDeleteMcbNode)
+#pragma alloc_text(PAGE, FFSFreeMcbTree)
+#pragma alloc_text(PAGE, FFSCheckBitmapConsistency)
+#pragma alloc_text(PAGE, FFSCheckSetBlock)
+#pragma alloc_text(PAGE, FFSInitializeVcb)
+#pragma alloc_text(PAGE, FFSFreeCcb)
+#pragma alloc_text(PAGE, FFSAllocateCcb)
+#pragma alloc_text(PAGE, FFSFreeVcb)
+#pragma alloc_text(PAGE, FFSCreateFcbFromMcb)
+#pragma alloc_text(PAGE, FFSSyncUninitializeCacheMap)
+#endif
+
+
+__drv_mustHoldCriticalRegion
+PFFS_IRP_CONTEXT
+FFSAllocateIrpContext(
+       IN PDEVICE_OBJECT   DeviceObject,
+       IN PIRP             Irp)
+{
+       PIO_STACK_LOCATION  IoStackLocation;
+       PFFS_IRP_CONTEXT    IrpContext;
+
+    PAGED_CODE();
+
+       ASSERT(DeviceObject != NULL);
+       ASSERT(Irp != NULL);
+
+       IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
+
+       ExAcquireResourceExclusiveLite(
+                       &FFSGlobal->LAResource,
+                       TRUE);
+
+       IrpContext = (PFFS_IRP_CONTEXT)(ExAllocateFromNPagedLookasideList(&(FFSGlobal->FFSIrpContextLookasideList)));
+
+       ExReleaseResourceForThreadLite(
+                       &FFSGlobal->LAResource,
+                       ExGetCurrentResourceThread());
+
+       if (IrpContext == NULL)
+       {
+               IrpContext = ExAllocatePoolWithTag(NonPagedPool, sizeof(FFS_IRP_CONTEXT), FFS_POOL_TAG);
+
+               //
+               //  Zero out the irp context and indicate that it is from pool and
+               //  not region allocated
+               //
+
+               RtlZeroMemory(IrpContext, sizeof(FFS_IRP_CONTEXT));
+
+               SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_FROM_POOL);
+       }
+       else
+       {
+               //
+               //  Zero out the irp context and indicate that it is from zone and
+               //  not pool allocated
+               //
+
+               RtlZeroMemory(IrpContext, sizeof(FFS_IRP_CONTEXT));
+       }
+
+       if (!IrpContext)
+       {
+               return NULL;
+       }
+
+       IrpContext->Identifier.Type = FFSICX;
+       IrpContext->Identifier.Size = sizeof(FFS_IRP_CONTEXT);
+
+       IrpContext->Irp = Irp;
+
+       IrpContext->MajorFunction = IoStackLocation->MajorFunction;
+       IrpContext->MinorFunction = IoStackLocation->MinorFunction;
+
+       IrpContext->DeviceObject = DeviceObject;
+
+       IrpContext->FileObject = IoStackLocation->FileObject;
+
+       if (IrpContext->FileObject != NULL)
+       {
+               IrpContext->RealDevice = IrpContext->FileObject->DeviceObject;
+       }
+       else if (IrpContext->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL)
+       {
+               if (IoStackLocation->Parameters.MountVolume.Vpb)
+               {
+                       IrpContext->RealDevice = 
+                               IoStackLocation->Parameters.MountVolume.Vpb->RealDevice;
+               }
+       }
+
+       if (IrpContext->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL ||
+                       IrpContext->MajorFunction == IRP_MJ_DEVICE_CONTROL ||
+                       IrpContext->MajorFunction == IRP_MJ_SHUTDOWN)
+       {
+               IrpContext->IsSynchronous = TRUE;
+       }
+       else if (IrpContext->MajorFunction == IRP_MJ_CLEANUP ||
+                       IrpContext->MajorFunction == IRP_MJ_CLOSE)
+       {
+               IrpContext->IsSynchronous = FALSE;
+       }
+#if (_WIN32_WINNT >= 0x0500)
+       else if (IrpContext->MajorFunction == IRP_MJ_PNP)
+       {
+               if (IoGetCurrentIrpStackLocation(Irp)->FileObject == NULL)
+               {
+                       IrpContext->IsSynchronous = TRUE;
+               }
+               else
+               {
+                       IrpContext->IsSynchronous = IoIsOperationSynchronous(Irp);
+               }
+       }
+#endif //(_WIN32_WINNT >= 0x0500)
+       else
+       {
+               IrpContext->IsSynchronous = IoIsOperationSynchronous(Irp);
+       }
+
+#if 0    
+       //
+       // Temporary workaround for a bug in close that makes it reference a
+       // fileobject when it is no longer valid.
+       //
+       if (IrpContext->MajorFunction == IRP_MJ_CLOSE)
+       {
+               IrpContext->IsSynchronous = TRUE;
+       }
+#endif
+
+       IrpContext->IsTopLevel = (IoGetTopLevelIrp() == Irp);
+
+       IrpContext->ExceptionInProgress = FALSE;
+
+       return IrpContext;
+}
+
+
+__drv_mustHoldCriticalRegion
+VOID
+FFSFreeIrpContext(
+       IN PFFS_IRP_CONTEXT IrpContext)
+{
+    PAGED_CODE();
+
+       ASSERT(IrpContext != NULL);
+
+       ASSERT((IrpContext->Identifier.Type == FFSICX) &&
+                       (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
+
+       FFSUnpinRepinnedBcbs(IrpContext);
+
+       //  Return the Irp context record to the region or to pool depending on
+       //  its flag
+
+       if (FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_FROM_POOL))
+       {
+               IrpContext->Identifier.Type = 0;
+               IrpContext->Identifier.Size = 0;
+
+               ExFreePool(IrpContext);
+       }
+       else
+       {
+               IrpContext->Identifier.Type = 0;
+               IrpContext->Identifier.Size = 0;
+
+               ExAcquireResourceExclusiveLite(
+                               &FFSGlobal->LAResource,
+                               TRUE);
+
+               ExFreeToNPagedLookasideList(&(FFSGlobal->FFSIrpContextLookasideList), IrpContext);
+
+               ExReleaseResourceForThreadLite(
+                               &FFSGlobal->LAResource,
+                               ExGetCurrentResourceThread());
+
+       }
+}
+
+
+VOID
+FFSRepinBcb(
+       IN PFFS_IRP_CONTEXT IrpContext,
+       IN PBCB             Bcb)
+{
+       PFFS_REPINNED_BCBS Repinned;
+       ULONG i;
+
+       Repinned = &IrpContext->Repinned;
+
+
+       return;
+
+       while (Repinned)
+       {
+               for (i = 0; i < FFS_REPINNED_BCBS_ARRAY_SIZE; i += 1)
+               {
+                       if (Repinned->Bcb[i] == Bcb)
+                       {
+                               return;
+                       }
+               }
+
+               Repinned = Repinned->Next;
+       }
+
+       while (TRUE)
+       {
+               for (i = 0; i < FFS_REPINNED_BCBS_ARRAY_SIZE; i += 1)
+               {
+                       if (Repinned->Bcb[i] == Bcb)
+                       {
+                               return;
+                       }
+
+                       if (Repinned->Bcb[i] == NULL)
+                       {
+                               Repinned->Bcb[i] = Bcb;
+                               CcRepinBcb(Bcb);
+
+                               return;
+                       }
+               }
+
+               if (Repinned->Next == NULL)
+               {
+                       Repinned->Next = ExAllocatePoolWithTag(PagedPool, sizeof(FFS_REPINNED_BCBS), FFS_POOL_TAG);
+                       RtlZeroMemory(Repinned->Next, sizeof(FFS_REPINNED_BCBS));
+               }
+
+               Repinned = Repinned->Next;
+       }
+}
+
+
+VOID
+FFSUnpinRepinnedBcbs(
+       IN PFFS_IRP_CONTEXT IrpContext)
+{
+       IO_STATUS_BLOCK    RaiseIosb;
+       PFFS_REPINNED_BCBS Repinned;
+       BOOLEAN            WriteThroughToDisk;
+       PFILE_OBJECT       FileObject = NULL;
+       BOOLEAN            ForceVerify = FALSE;
+       ULONG              i;
+
+       Repinned = &IrpContext->Repinned;
+       RaiseIosb.Status = STATUS_SUCCESS;
+
+       WriteThroughToDisk = (BOOLEAN)(IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WRITE_THROUGH) ||
+                       IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_FLOPPY));
+
+       while (Repinned != NULL)
+       {
+               for (i = 0; i < FFS_REPINNED_BCBS_ARRAY_SIZE; i += 1)
+               {
+                       if (Repinned->Bcb[i] != NULL)
+                       {
+                               IO_STATUS_BLOCK Iosb;
+
+                               ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
+
+                               if (FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_FLOPPY))
+                               {
+                                       FileObject = CcGetFileObjectFromBcb(Repinned->Bcb[i]);
+                               }
+
+                               ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
+
+                               CcUnpinRepinnedBcb(Repinned->Bcb[i],
+                                               WriteThroughToDisk,
+                                               &Iosb);
+
+                               ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
+
+                               if (!NT_SUCCESS(Iosb.Status))
+                               {
+                                       if (RaiseIosb.Status == STATUS_SUCCESS)
+                                       {
+                                               RaiseIosb = Iosb;
+                                       }
+
+                                       if (FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_FLOPPY) &&
+                                                       (IrpContext->MajorFunction != IRP_MJ_CLEANUP) &&
+                                                       (IrpContext->MajorFunction != IRP_MJ_FLUSH_BUFFERS) &&
+                                                       (IrpContext->MajorFunction != IRP_MJ_SET_INFORMATION))
+                                       {
+
+                                               CcPurgeCacheSection(FileObject->SectionObjectPointer,
+                                                               NULL,
+                                                               0,
+                                                               FALSE);
+
+                                               ForceVerify = TRUE;
+                                       }
+                               }
+
+                               Repinned->Bcb[i] = NULL;
+
+                       }
+                       else
+                       {
+                               break;
+                       }
+               }
+
+               if (Repinned != &IrpContext->Repinned)
+               {
+                       PFFS_REPINNED_BCBS Saved;
+
+                       Saved = Repinned->Next;
+                       ExFreePool(Repinned);
+                       Repinned = Saved;
+
+               }
+               else
+               {
+                       Repinned = Repinned->Next;
+                       IrpContext->Repinned.Next = NULL;
+               }
+       }
+
+       if (!NT_SUCCESS(RaiseIosb.Status))
+       {
+               FFSBreakPoint();
+
+               if (ForceVerify && FileObject)
+               {
+                       SetFlag(FileObject->DeviceObject->Flags, DO_VERIFY_VOLUME);
+                       IoSetHardErrorOrVerifyDevice(IrpContext->Irp,
+                                       FileObject->DeviceObject);
+               }
+
+               IrpContext->Irp->IoStatus = RaiseIosb;
+               FFSNormalizeAndRaiseStatus(IrpContext, RaiseIosb.Status);
+       }
+
+       return;
+}
+
+
+__drv_mustHoldCriticalRegion
+PFFS_FCB
+FFSv1AllocateFcb(
+       IN PFFS_VCB           Vcb,
+       IN PFFS_MCB           FFSMcb,
+       IN PFFSv1_INODE       dinode1)
+{
+       PFFS_FCB Fcb;
+
+    PAGED_CODE();
+
+       ExAcquireResourceExclusiveLite(
+                       &FFSGlobal->LAResource,
+                       TRUE);
+
+       Fcb = (PFFS_FCB)(ExAllocateFromNPagedLookasideList(&(FFSGlobal->FFSFcbLookasideList)));
+
+       ExReleaseResourceForThreadLite(
+                       &FFSGlobal->LAResource,
+                       ExGetCurrentResourceThread());
+
+       if (Fcb == NULL)
+       {
+               Fcb = (PFFS_FCB)ExAllocatePoolWithTag(NonPagedPool, sizeof(FFS_FCB), FFS_POOL_TAG);
+
+               RtlZeroMemory(Fcb, sizeof(FFS_FCB));
+
+               SetFlag(Fcb->Flags, FCB_FROM_POOL);
+       }
+       else
+       {
+               RtlZeroMemory(Fcb, sizeof(FFS_FCB));
+       }
+
+       if (!Fcb)
+       {
+               return NULL;
+       }
+
+       Fcb->Identifier.Type = FFSFCB;
+       Fcb->Identifier.Size = sizeof(FFS_FCB);
+
+       FsRtlInitializeFileLock(
+                       &Fcb->FileLockAnchor,
+                       NULL,
+                       NULL);
+
+       Fcb->OpenHandleCount = 0;
+       Fcb->ReferenceCount = 0;
+
+       Fcb->Vcb = Vcb;
+
+#if DBG    
+
+       Fcb->AnsiFileName.MaximumLength = (USHORT)
+               RtlxUnicodeStringToOemSize(&(FFSMcb->ShortName)) + 1;
+
+       Fcb->AnsiFileName.Buffer = (PUCHAR) 
+               ExAllocatePoolWithTag(PagedPool, Fcb->AnsiFileName.MaximumLength, FFS_POOL_TAG);
+
+       if (!Fcb->AnsiFileName.Buffer)
+       {
+               goto errorout;
+       }
+
+       RtlZeroMemory(Fcb->AnsiFileName.Buffer, Fcb->AnsiFileName.MaximumLength);
+
+       FFSUnicodeToOEM(&(Fcb->AnsiFileName),
+                       &(FFSMcb->ShortName));
+
+#endif
+
+       FFSMcb->FileAttr = FILE_ATTRIBUTE_NORMAL;
+
+       if ((dinode1->di_mode & IFMT) == IFDIR)
+       {
+               SetFlag(FFSMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY);
+       }
+
+       if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY) || 
+                       FFSIsReadOnly(dinode1->di_mode))
+       {
+               SetFlag(FFSMcb->FileAttr, FILE_ATTRIBUTE_READONLY);
+       }
+
+       Fcb->dinode1 = dinode1;
+
+       Fcb->FFSMcb = FFSMcb;
+       FFSMcb->FFSFcb = Fcb;
+
+       RtlZeroMemory(&Fcb->Header, sizeof(FSRTL_COMMON_FCB_HEADER));
+
+       Fcb->Header.NodeTypeCode = (USHORT)FFSFCB;
+       Fcb->Header.NodeByteSize = sizeof(FFS_FCB);
+       Fcb->Header.IsFastIoPossible = FastIoIsNotPossible;
+       Fcb->Header.Resource = &(Fcb->MainResource);
+       Fcb->Header.PagingIoResource = &(Fcb->PagingIoResource);
+
+       {
+               ULONG Totalblocks = (Fcb->dinode1->di_blocks);
+               Fcb->Header.AllocationSize.QuadPart = 
+                       (((LONGLONG)FFSDataBlocks(Vcb, Totalblocks)) << BLOCK_BITS);
+       }
+
+       Fcb->Header.FileSize.QuadPart = (LONGLONG)(Fcb->dinode1->di_size);
+       Fcb->Header.ValidDataLength.QuadPart = (LONGLONG)(0x7fffffffffffffff);
+
+       Fcb->SectionObject.DataSectionObject = NULL;
+       Fcb->SectionObject.SharedCacheMap = NULL;
+       Fcb->SectionObject.ImageSectionObject = NULL;
+
+       ExInitializeResourceLite(&(Fcb->MainResource));
+       ExInitializeResourceLite(&(Fcb->PagingIoResource));
+
+       InsertTailList(&Vcb->FcbList, &Fcb->Next);
+
+#if DBG
+
+       ExAcquireResourceExclusiveLite(
+                       &FFSGlobal->CountResource,
+                       TRUE);
+
+       FFSGlobal->FcbAllocated++;
+
+       ExReleaseResourceForThreadLite(
+                       &FFSGlobal->CountResource,
+                       ExGetCurrentResourceThread());
+#endif
+
+       return Fcb;
+
+#if DBG
+errorout:
+#endif
+
+       if (Fcb)
+       {
+
+#if DBG
+               if (Fcb->AnsiFileName.Buffer)
+                       ExFreePool(Fcb->AnsiFileName.Buffer);
+#endif
+
+               if (FlagOn(Fcb->Flags, FCB_FROM_POOL))
+               {
+                       ExFreePool(Fcb);
+               }
+               else
+               {
+                       ExAcquireResourceExclusiveLite(
+                                       &FFSGlobal->LAResource,
+                                       TRUE);
+
+                       ExFreeToNPagedLookasideList(&(FFSGlobal->FFSFcbLookasideList), Fcb);
+
+                       ExReleaseResourceForThreadLite(
+                                       &FFSGlobal->LAResource,
+                                       ExGetCurrentResourceThread());
+               }
+
+       }
+
+       return NULL;
+}
+
+
+__drv_mustHoldCriticalRegion
+PFFS_FCB
+FFSv2AllocateFcb(
+       IN PFFS_VCB           Vcb,
+       IN PFFS_MCB           FFSMcb,
+       IN PFFSv2_INODE       dinode2)
+{
+       PFFS_FCB Fcb;
+
+    PAGED_CODE();
+
+       ExAcquireResourceExclusiveLite(
+                       &FFSGlobal->LAResource,
+                       TRUE);
+
+       Fcb = (PFFS_FCB)(ExAllocateFromNPagedLookasideList(&(FFSGlobal->FFSFcbLookasideList)));
+
+       ExReleaseResourceForThreadLite(
+                       &FFSGlobal->LAResource,
+                       ExGetCurrentResourceThread());
+
+       if (Fcb == NULL)
+       {
+               Fcb = (PFFS_FCB)ExAllocatePoolWithTag(NonPagedPool, sizeof(FFS_FCB), FFS_POOL_TAG);
+
+               RtlZeroMemory(Fcb, sizeof(FFS_FCB));
+
+               SetFlag(Fcb->Flags, FCB_FROM_POOL);
+       }
+       else
+       {
+               RtlZeroMemory(Fcb, sizeof(FFS_FCB));
+       }
+
+       if (!Fcb)
+       {
+               return NULL;
+       }
+
+       Fcb->Identifier.Type = FFSFCB;
+       Fcb->Identifier.Size = sizeof(FFS_FCB);
+
+       FsRtlInitializeFileLock(
+                       &Fcb->FileLockAnchor,
+                       NULL,
+                       NULL);
+
+       Fcb->OpenHandleCount = 0;
+       Fcb->ReferenceCount = 0;
+
+       Fcb->Vcb = Vcb;
+
+#if DBG    
+
+       Fcb->AnsiFileName.MaximumLength = (USHORT)
+               RtlxUnicodeStringToOemSize(&(FFSMcb->ShortName)) + 1;
+
+       Fcb->AnsiFileName.Buffer = (PUCHAR) 
+               ExAllocatePoolWithTag(PagedPool, Fcb->AnsiFileName.MaximumLength, FFS_POOL_TAG);
+
+       if (!Fcb->AnsiFileName.Buffer)
+       {
+               goto errorout;
+       }
+
+       RtlZeroMemory(Fcb->AnsiFileName.Buffer, Fcb->AnsiFileName.MaximumLength);
+
+       FFSUnicodeToOEM(&(Fcb->AnsiFileName),
+                       &(FFSMcb->ShortName));
+
+#endif
+
+       FFSMcb->FileAttr = FILE_ATTRIBUTE_NORMAL;
+
+       if ((dinode2->di_mode & IFMT) == IFDIR)
+       {
+               SetFlag(FFSMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY);
+       }
+
+       if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY) || 
+                       FFSIsReadOnly(dinode2->di_mode))
+       {
+               SetFlag(FFSMcb->FileAttr, FILE_ATTRIBUTE_READONLY);
+       }
+
+       Fcb->dinode2 = dinode2;
+
+       Fcb->FFSMcb = FFSMcb;
+       FFSMcb->FFSFcb = Fcb;
+
+       RtlZeroMemory(&Fcb->Header, sizeof(FSRTL_COMMON_FCB_HEADER));
+
+       Fcb->Header.NodeTypeCode = (USHORT)FFSFCB;
+       Fcb->Header.NodeByteSize = sizeof(FFS_FCB);
+       Fcb->Header.IsFastIoPossible = FastIoIsNotPossible;
+       Fcb->Header.Resource = &(Fcb->MainResource);
+       Fcb->Header.PagingIoResource = &(Fcb->PagingIoResource);
+
+       {
+               ULONG Totalblocks = (ULONG)(Fcb->dinode2->di_blocks);
+               Fcb->Header.AllocationSize.QuadPart = 
+                       (((LONGLONG)FFSDataBlocks(Vcb, Totalblocks)) << BLOCK_BITS);
+       }
+
+       Fcb->Header.FileSize.QuadPart = (LONGLONG)(Fcb->dinode2->di_size);
+       Fcb->Header.ValidDataLength.QuadPart = (LONGLONG)(0x7fffffffffffffff);
+
+       Fcb->SectionObject.DataSectionObject = NULL;
+       Fcb->SectionObject.SharedCacheMap = NULL;
+       Fcb->SectionObject.ImageSectionObject = NULL;
+
+       ExInitializeResourceLite(&(Fcb->MainResource));
+       ExInitializeResourceLite(&(Fcb->PagingIoResource));
+
+       InsertTailList(&Vcb->FcbList, &Fcb->Next);
+
+#if DBG
+
+       ExAcquireResourceExclusiveLite(
+                       &FFSGlobal->CountResource,
+                       TRUE);
+
+       FFSGlobal->FcbAllocated++;
+
+       ExReleaseResourceForThreadLite(
+                       &FFSGlobal->CountResource,
+                       ExGetCurrentResourceThread());
+#endif
+
+       return Fcb;
+
+#if DBG
+errorout:
+#endif
+
+       if (Fcb)
+       {
+
+#if DBG
+               if (Fcb->AnsiFileName.Buffer)
+                       ExFreePool(Fcb->AnsiFileName.Buffer);
+#endif
+
+               if (FlagOn(Fcb->Flags, FCB_FROM_POOL))
+               {
+                       ExFreePool(Fcb);
+               }
+               else
+               {
+                       ExAcquireResourceExclusiveLite(
+                                       &FFSGlobal->LAResource,
+                                       TRUE);
+
+                       ExFreeToNPagedLookasideList(&(FFSGlobal->FFSFcbLookasideList), Fcb);
+
+                       ExReleaseResourceForThreadLite(
+                                       &FFSGlobal->LAResource,
+                                       ExGetCurrentResourceThread());
+               }
+
+       }
+
+       return NULL;
+}
+
+
+__drv_mustHoldCriticalRegion
+VOID
+FFSFreeFcb(
+       IN PFFS_FCB Fcb)
+{
+       PFFS_VCB       Vcb;
+
+    PAGED_CODE();
+
+       ASSERT(Fcb != NULL);
+
+       ASSERT((Fcb->Identifier.Type == FFSFCB) &&
+                       (Fcb->Identifier.Size == sizeof(FFS_FCB)));
+
+       Vcb = Fcb->Vcb;
+
+       FsRtlUninitializeFileLock(&Fcb->FileLockAnchor);
+
+       ExDeleteResourceLite(&Fcb->MainResource);
+
+       ExDeleteResourceLite(&Fcb->PagingIoResource);
+
+       Fcb->FFSMcb->FFSFcb = NULL;
+
+       if(IsFlagOn(Fcb->Flags, FCB_FILE_DELETED))
+       {
+               if (Fcb->FFSMcb)
+               {
+                       FFSDeleteMcbNode(Vcb, Fcb->FFSMcb->Parent, Fcb->FFSMcb);
+                       FFSFreeMcb(Fcb->FFSMcb);
+               }
+       }
+
+       if (Fcb->LongName.Buffer)
+       {
+               ExFreePool(Fcb->LongName.Buffer);
+               Fcb->LongName.Buffer = NULL;
+       }
+
+#if DBG    
+       ExFreePool(Fcb->AnsiFileName.Buffer);
+#endif
+
+       if (FS_VERSION == 1)
+       {
+               ExFreePool(Fcb->dinode1);
+       }
+       else
+       {
+               ExFreePool(Fcb->dinode2);
+       }
+
+       Fcb->Header.NodeTypeCode = (SHORT)0xCCCC;
+       Fcb->Header.NodeByteSize = (SHORT)0xC0C0;
+
+       if (FlagOn(Fcb->Flags, FCB_FROM_POOL))
+       {
+               ExFreePool(Fcb);
+       }
+       else
+       {
+               ExAcquireResourceExclusiveLite(
+                               &FFSGlobal->LAResource,
+                               TRUE);
+
+               ExFreeToNPagedLookasideList(&(FFSGlobal->FFSFcbLookasideList), Fcb);
+
+               ExReleaseResourceForThreadLite(
+                               &FFSGlobal->LAResource,
+                               ExGetCurrentResourceThread());
+       }
+
+#if DBG
+
+       ExAcquireResourceExclusiveLite(
+                       &FFSGlobal->CountResource,
+                       TRUE);
+
+       FFSGlobal->FcbAllocated--;
+
+       ExReleaseResourceForThreadLite(
+                       &FFSGlobal->CountResource,
+                       ExGetCurrentResourceThread());
+#endif
+
+}
+
+
+__drv_mustHoldCriticalRegion
+PFFS_CCB
+FFSAllocateCcb(
+       VOID)
+{
+       PFFS_CCB Ccb;
+
+    PAGED_CODE();
+
+       ExAcquireResourceExclusiveLite(
+                       &FFSGlobal->LAResource,
+                       TRUE);
+
+       Ccb = (PFFS_CCB)(ExAllocateFromNPagedLookasideList(&(FFSGlobal->FFSCcbLookasideList)));
+
+       ExReleaseResourceForThreadLite(
+                       &FFSGlobal->LAResource,
+                       ExGetCurrentResourceThread());
+
+       if (Ccb == NULL)
+       {
+               Ccb = (PFFS_CCB)ExAllocatePoolWithTag(NonPagedPool, sizeof(FFS_CCB), FFS_POOL_TAG);
+
+               RtlZeroMemory(Ccb, sizeof(FFS_CCB));
+
+               SetFlag(Ccb->Flags, CCB_FROM_POOL);
+       }
+       else
+       {
+               RtlZeroMemory(Ccb, sizeof(FFS_CCB));
+       }
+
+       if (!Ccb)
+       {
+               return NULL;
+       }
+
+       Ccb->Identifier.Type = FFSCCB;
+       Ccb->Identifier.Size = sizeof(FFS_CCB);
+
+       Ccb->CurrentByteOffset = 0;
+
+       Ccb->DirectorySearchPattern.Length = 0;
+       Ccb->DirectorySearchPattern.MaximumLength = 0;
+       Ccb->DirectorySearchPattern.Buffer = 0;
+
+       return Ccb;
+}
+
+
+__drv_mustHoldCriticalRegion
+VOID
+FFSFreeCcb(
+       IN PFFS_CCB Ccb)
+{
+    PAGED_CODE();
+
+       ASSERT(Ccb != NULL);
+
+       ASSERT((Ccb->Identifier.Type == FFSCCB) &&
+                       (Ccb->Identifier.Size == sizeof(FFS_CCB)));
+
+       if (Ccb->DirectorySearchPattern.Buffer != NULL)
+       {
+               ExFreePool(Ccb->DirectorySearchPattern.Buffer);
+       }
+
+       if (FlagOn(Ccb->Flags, CCB_FROM_POOL))
+       {
+               ExFreePool(Ccb);
+       }
+       else
+       {
+               ExAcquireResourceExclusiveLite(
+                               &FFSGlobal->LAResource,
+                               TRUE);
+
+               ExFreeToNPagedLookasideList(&(FFSGlobal->FFSCcbLookasideList), Ccb);
+
+               ExReleaseResourceForThreadLite(
+                               &FFSGlobal->LAResource,
+                               ExGetCurrentResourceThread());
+       }
+}
+
+
+__drv_mustHoldCriticalRegion
+PFFS_MCB
+FFSAllocateMcb(
+       PFFS_VCB        Vcb,
+       PUNICODE_STRING FileName,
+       ULONG           FileAttr)
+{
+       PFFS_MCB    Mcb = NULL;
+       PLIST_ENTRY List = NULL;
+
+       ULONG       Extra = 0;
+
+    PAGED_CODE();
+
+#define MCB_NUM_SHIFT   0x04
+
+       if (FFSGlobal->McbAllocated > (FFSGlobal->MaxDepth << MCB_NUM_SHIFT))
+               Extra = FFSGlobal->McbAllocated - 
+                       (FFSGlobal->MaxDepth << MCB_NUM_SHIFT) +
+                       FFSGlobal->MaxDepth;
+
+       FFSPrint((DBG_INFO,
+                               "FFSAllocateMcb: CurrDepth=%xh/%xh/%xh FileName=%S\n", 
+                               FFSGlobal->McbAllocated,
+                               FFSGlobal->MaxDepth << MCB_NUM_SHIFT,
+                               FFSGlobal->FcbAllocated,
+                               FileName->Buffer));
+
+       List = Vcb->McbList.Flink;
+
+       while ((List != &(Vcb->McbList)) && (Extra > 0))
+       {
+               Mcb = CONTAINING_RECORD(List, FFS_MCB, Link);
+               List = List->Flink;
+
+               if ((Mcb->Inode != 2) && (Mcb->Child == NULL) &&
+                               (Mcb->FFSFcb == NULL) && (!IsMcbUsed(Mcb)))
+               {
+                       FFSPrint((DBG_INFO, "FFSAllocateMcb: Mcb %S will be freed.\n",
+                                               Mcb->ShortName.Buffer));
+
+                       if (FFSDeleteMcbNode(Vcb, Vcb->McbTree, Mcb))
+                       {
+                               FFSFreeMcb(Mcb);
+
+                               Extra--;
+                       }
+               }
+       }
+
+       ExAcquireResourceExclusiveLite(
+                       &FFSGlobal->LAResource,
+                       TRUE);
+
+       Mcb = (PFFS_MCB)(ExAllocateFromPagedLookasideList(
+                               &(FFSGlobal->FFSMcbLookasideList)));
+
+       ExReleaseResourceForThreadLite(
+                       &FFSGlobal->LAResource,
+                       ExGetCurrentResourceThread());
+
+       if (Mcb == NULL)
+       {
+               Mcb = (PFFS_MCB)ExAllocatePoolWithTag(PagedPool, sizeof(FFS_MCB), FFS_POOL_TAG);
+
+               RtlZeroMemory(Mcb, sizeof(FFS_MCB));
+
+               SetFlag(Mcb->Flags, MCB_FROM_POOL);
+       }
+       else
+       {
+               RtlZeroMemory(Mcb, sizeof(FFS_MCB));
+       }
+
+       if (!Mcb)
+       {
+               return NULL;
+       }
+
+       Mcb->Identifier.Type = FFSMCB;
+       Mcb->Identifier.Size = sizeof(FFS_MCB);
+
+       if (FileName && FileName->Length)
+       {
+               Mcb->ShortName.Length = FileName->Length;
+               Mcb->ShortName.MaximumLength = Mcb->ShortName.Length + 2;
+
+               Mcb->ShortName.Buffer = ExAllocatePoolWithTag(PagedPool, Mcb->ShortName.MaximumLength, FFS_POOL_TAG);
+
+               if (!Mcb->ShortName.Buffer)
+                       goto errorout;
+
+               RtlZeroMemory(Mcb->ShortName.Buffer, Mcb->ShortName.MaximumLength);
+               RtlCopyMemory(Mcb->ShortName.Buffer, FileName->Buffer, Mcb->ShortName.Length);
+       } 
+
+       Mcb->FileAttr = FileAttr;
+
+       ExAcquireResourceExclusiveLite(
+                       &FFSGlobal->CountResource,
+                       TRUE);
+
+       FFSGlobal->McbAllocated++;
+
+       ExReleaseResourceForThreadLite(
+                       &FFSGlobal->CountResource,
+                       ExGetCurrentResourceThread());
+
+       return Mcb;
+
+errorout:
+
+       if (Mcb)
+       {
+               if (Mcb->ShortName.Buffer)
+                       ExFreePool(Mcb->ShortName.Buffer);
+
+               if (FlagOn(Mcb->Flags, MCB_FROM_POOL))
+               {
+                       ExFreePool(Mcb);
+               }
+               else
+               {
+                       ExAcquireResourceExclusiveLite(
+                                       &FFSGlobal->LAResource,
+                                       TRUE);
+
+                       ExFreeToPagedLookasideList(&(FFSGlobal->FFSMcbLookasideList), Mcb);
+
+                       ExReleaseResourceForThreadLite(
+                                       &FFSGlobal->LAResource,
+                                       ExGetCurrentResourceThread());
+               }
+       }
+
+       return NULL;
+}
+
+
+__drv_mustHoldCriticalRegion
+VOID
+FFSFreeMcb(
+       IN PFFS_MCB Mcb)
+{
+#ifndef __REACTOS__
+    PFFS_MCB   Parent = Mcb->Parent;
+#endif
+    PAGED_CODE();
+
+       ASSERT(Mcb != NULL);
+
+       ASSERT((Mcb->Identifier.Type == FFSMCB) &&
+                       (Mcb->Identifier.Size == sizeof(FFS_MCB)));
+
+       FFSPrint((DBG_INFO, "FFSFreeMcb: Mcb %S will be freed.\n", Mcb->ShortName.Buffer));
+
+       if (Mcb->ShortName.Buffer)
+               ExFreePool(Mcb->ShortName.Buffer);
+
+       if (FlagOn(Mcb->Flags, MCB_FROM_POOL))
+       {
+               ExFreePool(Mcb);
+       }
+       else
+       {
+               ExAcquireResourceExclusiveLite(
+                               &FFSGlobal->LAResource,
+                               TRUE);
+
+               ExFreeToPagedLookasideList(&(FFSGlobal->FFSMcbLookasideList), Mcb);
+
+               ExReleaseResourceForThreadLite(
+                               &FFSGlobal->LAResource,
+                               ExGetCurrentResourceThread());
+       }
+
+       ExAcquireResourceExclusiveLite(
+                       &FFSGlobal->CountResource,
+                       TRUE);
+
+       FFSGlobal->McbAllocated--;
+
+       ExReleaseResourceForThreadLite(
+                       &FFSGlobal->CountResource,
+                       ExGetCurrentResourceThread());
+}
+
+
+__drv_mustHoldCriticalRegion
+PFFS_FCB
+FFSCreateFcbFromMcb(
+       PFFS_VCB Vcb,
+       PFFS_MCB Mcb)
+{
+       PFFS_FCB       Fcb = NULL;
+       FFSv1_INODE    dinode1;
+       FFSv2_INODE    dinode2;
+
+    PAGED_CODE();
+
+       if (Mcb->FFSFcb)
+               return Mcb->FFSFcb;
+
+       if (FS_VERSION == 1)
+       {
+               if (FFSv1LoadInode(Vcb, Mcb->Inode, &dinode1))
+               {
+                       PFFSv1_INODE pTmpInode = ExAllocatePoolWithTag(PagedPool, DINODE1_SIZE, FFS_POOL_TAG);
+                       if (!pTmpInode)
+                       {
+                               goto errorout;
+                       }
+
+                       RtlCopyMemory(pTmpInode, &dinode1, DINODE1_SIZE);
+                       Fcb = FFSv1AllocateFcb(Vcb, Mcb, pTmpInode);
+                       if (!Fcb)
+                       {
+                               ExFreePool(pTmpInode);
+                       }
+               }
+       }
+       else
+       {
+               if (FFSv2LoadInode(Vcb, Mcb->Inode, &dinode2))
+               {
+                       PFFSv2_INODE pTmpInode = ExAllocatePoolWithTag(PagedPool, DINODE2_SIZE, FFS_POOL_TAG);
+                       if (!pTmpInode)
+                       {
+                               goto errorout;
+                       }
+
+                       RtlCopyMemory(pTmpInode, &dinode2, DINODE2_SIZE);
+                       Fcb = FFSv2AllocateFcb(Vcb, Mcb, pTmpInode);
+                       if (!Fcb)
+                       {
+                               ExFreePool(pTmpInode);
+                       }
+               }
+       }
+
+errorout:
+
+       return Fcb;
+}
+
+
+BOOLEAN
+FFSGetFullFileName(
+       PFFS_MCB        Mcb,
+       PUNICODE_STRING FileName)
+{
+       USHORT          Length = 0;
+       PFFS_MCB        TmpMcb = Mcb;
+       PUNICODE_STRING FileNames[256];
+       SHORT           Count = 0 , i = 0, j = 0;
+
+    PAGED_CODE();
+
+       while(TmpMcb && Count < 256)
+       {
+               if (TmpMcb->Inode == FFS_ROOT_INO)
+                       break;
+
+               FileNames[Count++] = &TmpMcb->ShortName;
+               Length += (2 + TmpMcb->ShortName.Length);
+
+               TmpMcb = TmpMcb->Parent;
+       }
+
+       if (Count >= 256)
+               return FALSE;
+
+       if (Count == 0)
+               Length = 2;
+
+       FileName->Length = Length;
+       FileName->MaximumLength = Length + 2;
+       FileName->Buffer = ExAllocatePoolWithTag(PagedPool, Length + 2, FFS_POOL_TAG);
+
+       if (!FileName->Buffer)
+       {
+               return FALSE;
+       }
+
+       RtlZeroMemory(FileName->Buffer, FileName->MaximumLength);
+
+       if (Count == 0)
+       {
+               FileName->Buffer[0] = L'\\';
+               return  TRUE;
+       }
+
+       for (i = Count - 1; i >= 0 && j < (SHORT)(FileName->MaximumLength); i--)
+       {
+               FileName->Buffer[j++] = L'\\';
+
+               RtlCopyMemory(&(FileName->Buffer[j]),
+                               FileNames[i]->Buffer,
+                               FileNames[i]->Length);
+
+               j += FileNames[i]->Length / 2;
+       }
+
+       return TRUE;
+}
+
+
+PFFS_MCB
+FFSSearchMcbTree(
+       PFFS_VCB Vcb,
+       PFFS_MCB FFSMcb,
+       ULONG    Inode)
+{
+       PFFS_MCB    Mcb = NULL;
+       PLIST_ENTRY List = NULL;
+       BOOLEAN     bFind = FALSE;
+
+    PAGED_CODE();
+
+       List = Vcb->McbList.Flink;
+
+       while ((!bFind) && (List != &(Vcb->McbList)))
+       {
+               Mcb = CONTAINING_RECORD(List, FFS_MCB, Link);
+               List = List->Flink;
+
+               if (Mcb->Inode == Inode)
+               {
+                       bFind = TRUE;
+                       break;
+               }
+       }
+
+       if (bFind)
+       {
+               ASSERT(Mcb != NULL);
+               FFSRefreshMcb(Vcb, Mcb);
+       }
+       else
+       {
+               Mcb = NULL;
+       }
+
+       return Mcb;
+}
+
+
+PFFS_MCB
+FFSSearchMcb(
+       PFFS_VCB        Vcb,
+       PFFS_MCB        Parent,
+       PUNICODE_STRING FileName)
+{
+       PFFS_MCB TmpMcb = Parent->Child;
+
+    PAGED_CODE();
+
+       while (TmpMcb)
+       {
+               if (!RtlCompareUnicodeString(
+                                       &(TmpMcb->ShortName),
+                                       FileName, TRUE))
+                       break;
+
+               TmpMcb = TmpMcb->Next;
+       }
+
+       if (TmpMcb)
+       {
+               FFSRefreshMcb(Vcb, TmpMcb);
+       }
+
+       return TmpMcb;
+}
+
+
+VOID
+FFSRefreshMcb(
+       PFFS_VCB Vcb,
+       PFFS_MCB Mcb)
+{
+    PAGED_CODE();
+
+       ASSERT (IsFlagOn(Mcb->Flags, MCB_IN_TREE));
+
+       RemoveEntryList(&(Mcb->Link));
+       InsertTailList(&(Vcb->McbList), &(Mcb->Link));
+}
+
+
+VOID
+FFSAddMcbNode(
+       PFFS_VCB Vcb,
+       PFFS_MCB Parent,
+       PFFS_MCB Child)
+{
+       PFFS_MCB TmpMcb = Parent->Child;
+
+    PAGED_CODE();
+
+       if(IsFlagOn(Child->Flags, MCB_IN_TREE))
+       {
+               FFSBreakPoint();
+               FFSPrint((DBG_ERROR, "FFSAddMcbNode: Child Mcb is alreay in the tree.\n"));
+               return;
+       }
+
+       if (TmpMcb)
+       {
+               ASSERT(TmpMcb->Parent == Parent);
+
+               while (TmpMcb->Next)
+               {
+                       TmpMcb = TmpMcb->Next;
+                       ASSERT(TmpMcb->Parent == Parent);
+               }
+
+               TmpMcb->Next = Child;
+               Child->Parent = Parent;
+               Child->Next = NULL;
+       }
+       else
+       {
+               Parent->Child = Child;
+               Child->Parent = Parent;
+               Child->Next = NULL;
+       }
+
+       InsertTailList(&(Vcb->McbList), &(Child->Link));
+       SetFlag(Child->Flags, MCB_IN_TREE);
+}
+
+
+BOOLEAN
+FFSDeleteMcbNode(
+       PFFS_VCB Vcb,
+       PFFS_MCB McbTree,
+       PFFS_MCB FFSMcb)
+{
+       PFFS_MCB   TmpMcb;
+
+    PAGED_CODE();
+
+       if(!IsFlagOn(FFSMcb->Flags, MCB_IN_TREE))
+       {
+               return TRUE;
+       }
+
+       if (FFSMcb->Parent)
+       {
+               if (FFSMcb->Parent->Child == FFSMcb)
+               {
+                       FFSMcb->Parent->Child = FFSMcb->Next;
+               }
+               else
+               {
+                       TmpMcb = FFSMcb->Parent->Child;
+
+                       while (TmpMcb && TmpMcb->Next != FFSMcb)
+                               TmpMcb = TmpMcb->Next;
+
+                       if (TmpMcb)
+                       {
+                               TmpMcb->Next = FFSMcb->Next;
+                       }
+                       else
+                       {
+                               // error
+                               return FALSE;
+                       }
+               }
+       }
+       else if (FFSMcb->Child)
+       {
+               return FALSE;
+       }
+
+       RemoveEntryList(&(FFSMcb->Link));
+       ClearFlag(FFSMcb->Flags, MCB_IN_TREE);
+
+       return TRUE;
+}
+
+
+__drv_mustHoldCriticalRegion
+VOID
+FFSFreeMcbTree(
+       PFFS_MCB McbTree)
+{
+    PAGED_CODE();
+
+       if (!McbTree)
+               return;
+
+       if (McbTree->Child)
+       {
+               FFSFreeMcbTree(McbTree->Child);
+       }
+
+       if (McbTree->Next)
+       {
+               PFFS_MCB   Current;
+               PFFS_MCB   Next;
+
+               Current = McbTree->Next;
+
+               while (Current)
+               {
+                       Next = Current->Next;
+
+                       if (Current->Child)
+                       {
+                               FFSFreeMcbTree(Current->Child);
+                       }
+
+                       FFSFreeMcb(Current);
+                       Current = Next;
+               }
+       }
+
+       FFSFreeMcb(McbTree);
+}
+
+
+BOOLEAN
+FFSCheckSetBlock(
+       PFFS_IRP_CONTEXT IrpContext,
+       PFFS_VCB         Vcb,
+       ULONG            Block)
+{
+    PAGED_CODE();
+#if 0
+       ULONG           Group, dwBlk, Length;
+
+       RTL_BITMAP      BlockBitmap;
+       PVOID           BitmapCache;
+       PBCB            BitmapBcb;
+
+       LARGE_INTEGER   Offset;
+
+       BOOLEAN         bModified = FALSE;
+
+
+       //Group = (Block - FFS_FIRST_DATA_BLOCK) / BLOCKS_PER_GROUP;
+
+       dwBlk = (Block - FFS_FIRST_DATA_BLOCK) % BLOCKS_PER_GROUP;
+
+
+       Offset.QuadPart = (LONGLONG) Vcb->BlockSize;
+       Offset.QuadPart = Offset.QuadPart * Vcb->ffs_group_desc[Group].bg_block_bitmap;
+
+       if (Group == Vcb->ffs_groups - 1)
+       {
+               Length = TOTAL_BLOCKS % BLOCKS_PER_GROUP;
+
+               /* s_blocks_count is integer multiple of s_blocks_per_group */
+               if (Length == 0)
+                       Length = BLOCKS_PER_GROUP;
+       }
+       else
+       {
+               Length = BLOCKS_PER_GROUP;
+       }
+
+       if (dwBlk >= Length)
+               return FALSE;
+
+       if (!CcPinRead(Vcb->StreamObj,
+                               &Offset,
+                               Vcb->BlockSize,
+                               PIN_WAIT,
+                               &BitmapBcb,
+                               &BitmapCache))
+       {
+               FFSPrint((DBG_ERROR, "FFSDeleteBlock: PinReading error ...\n"));
+               return FALSE;
+       }
+
+       RtlInitializeBitMap(&BlockBitmap,
+                       BitmapCache,
+                       Length);
+
+       if (RtlCheckBit(&BlockBitmap, dwBlk) == 0)
+       {
+               FFSBreakPoint();
+               RtlSetBits(&BlockBitmap, dwBlk, 1);
+               bModified = TRUE;
+       }
+
+       if (bModified)
+       {
+               CcSetDirtyPinnedData(BitmapBcb, NULL);
+
+               FFSRepinBcb(IrpContext, BitmapBcb);
+
+               FFSAddMcbEntry(Vcb, Offset.QuadPart, (LONGLONG)Vcb->BlockSize);
+       }
+
+       {
+               CcUnpinData(BitmapBcb);
+               BitmapBcb = NULL;
+               BitmapCache = NULL;
+
+               RtlZeroMemory(&BlockBitmap, sizeof(RTL_BITMAP));
+       }
+
+       return (!bModified);
+#endif
+       return FALSE;
+}
+
+
+BOOLEAN
+FFSCheckBitmapConsistency(
+       PFFS_IRP_CONTEXT IrpContext,
+       PFFS_VCB         Vcb)
+{
+    PAGED_CODE();
+#if 0
+       ULONG i, j, InodeBlocks;
+
+       for (i = 0; i < Vcb->ffs_groups; i++)
+       {
+               FFSCheckSetBlock(IrpContext, Vcb, Vcb->ffs_group_desc[i].bg_block_bitmap);
+               FFSCheckSetBlock(IrpContext, Vcb, Vcb->ffs_group_desc[i].bg_inode_bitmap);
+
+
+               if (i == Vcb->ffs_groups - 1)
+               {
+                       InodeBlocks = ((INODES_COUNT % INODES_PER_GROUP) * sizeof(FFS_INODE) + Vcb->BlockSize - 1) / (Vcb->BlockSize);
+               }
+               else
+               {
+                       InodeBlocks = (INODES_PER_GROUP * sizeof(FFS_INODE) + Vcb->BlockSize - 1) / (Vcb->BlockSize);
+               }
+
+               for (j = 0; j < InodeBlocks; j++)
+                       FFSCheckSetBlock(IrpContext, Vcb, Vcb->ffs_group_desc[i].bg_inode_table + j);
+       }
+
+       return TRUE;
+#endif
+       return FALSE;
+}
+
+
+VOID
+FFSInsertVcb(
+       PFFS_VCB Vcb)
+{
+       InsertTailList(&(FFSGlobal->VcbList), &Vcb->Next);
+}
+
+
+VOID
+FFSRemoveVcb(
+       PFFS_VCB Vcb)
+{
+       RemoveEntryList(&Vcb->Next);
+}
+
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSInitializeVcb(
+       IN PFFS_IRP_CONTEXT IrpContext, 
+       IN PFFS_VCB         Vcb, 
+       IN PFFS_SUPER_BLOCK FFSSb,
+       IN PDEVICE_OBJECT   TargetDevice,
+       IN PDEVICE_OBJECT   VolumeDevice,
+       IN PVPB             Vpb)
+{
+       BOOLEAN                     VcbResourceInitialized = FALSE;
+       USHORT                      VolumeLabelLength;
+       ULONG                       IoctlSize;
+       BOOLEAN                     NotifySyncInitialized = FALSE;
+       LONGLONG                    DiskSize;
+       LONGLONG                    PartSize;
+       NTSTATUS                    Status = STATUS_UNSUCCESSFUL;
+       UNICODE_STRING              RootNode;
+       USHORT                      Buffer[2];
+       ULONG                       ChangeCount;
+
+    PAGED_CODE();
+
+       _SEH2_TRY
+       {
+               if (!Vpb)
+               {
+                       Status = STATUS_DEVICE_NOT_READY;
+                       _SEH2_LEAVE;
+               }
+
+               Buffer[0] = L'\\';
+               Buffer[1] = 0;
+
+               RootNode.Buffer = Buffer;
+               RootNode.MaximumLength = RootNode.Length = 2;
+
+               Vcb->McbTree = FFSAllocateMcb(Vcb, &RootNode,
+                               FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_NORMAL);
+
+               if (!Vcb->McbTree)
+               {
+                       _SEH2_LEAVE;
+               }
+
+#if FFS_READ_ONLY
+               SetFlag(Vcb->Flags, VCB_READ_ONLY);
+#endif // FFS_READ_ONLY
+
+               if (IsFlagOn(Vpb->RealDevice->Characteristics, FILE_REMOVABLE_MEDIA))
+               {
+                       SetFlag(Vcb->Flags, VCB_REMOVABLE_MEDIA);
+               }
+
+               if (IsFlagOn(Vpb->RealDevice->Characteristics, FILE_FLOPPY_DISKETTE))
+               {
+                       SetFlag(Vcb->Flags, VCB_FLOPPY_DISK);
+               }
+#if 0
+               if (IsFlagOn(FFSGlobal->Flags, FFS_SUPPORT_WRITING))
+               {
+                       if (IsFlagOn(FFSGlobal->Flags, FFS_SUPPORT_WRITING))
+                       {
+                               ClearFlag(Vcb->Flags, VCB_READ_ONLY);
+                       }
+                       else
+                       {
+                               SetFlag(Vcb->Flags, VCB_READ_ONLY);
+                       }
+               }
+               else
+#endif
+               {
+                       SetFlag(Vcb->Flags, VCB_READ_ONLY);
+               }
+
+               ExInitializeResourceLite(&Vcb->MainResource);
+               ExInitializeResourceLite(&Vcb->PagingIoResource);
+
+               ExInitializeResourceLite(&Vcb->McbResource);
+
+               VcbResourceInitialized = TRUE;
+
+               Vcb->McbTree->Inode = FFS_ROOT_INO;
+
+               Vcb->Vpb = Vpb;
+
+               Vcb->RealDevice = Vpb->RealDevice;
+               Vpb->DeviceObject = VolumeDevice;
+
+               {
+                       UNICODE_STRING      LabelName;
+                       OEM_STRING          OemName;
+
+                       LabelName.MaximumLength = 16 * 2;
+                       LabelName.Length    = 0;
+                       LabelName.Buffer    = Vcb->Vpb->VolumeLabel;
+
+                       RtlZeroMemory(LabelName.Buffer, LabelName.MaximumLength);
+
+                       VolumeLabelLength = 16;
+
+                       while((VolumeLabelLength > 0) &&
+                                       ((FFSSb->fs_volname[VolumeLabelLength-1] == 0x00) ||
+                                        (FFSSb->fs_volname[VolumeLabelLength-1] == 0x20)))
+                       {
+                               VolumeLabelLength--;
+                       }
+
+                       OemName.Buffer = FFSSb->fs_volname;
+                       OemName.MaximumLength = 16;
+                       OemName.Length = VolumeLabelLength;
+
+                       Status = FFSOEMToUnicode(&LabelName,
+                                       &OemName);
+
+                       if (!NT_SUCCESS(Status))
+                       {
+                               _SEH2_LEAVE;
+                       }
+
+                       Vpb->VolumeLabelLength = LabelName.Length;
+               }
+
+               Vpb->SerialNumber = ((ULONG*)FFSSb->fs_id)[0] + ((ULONG*)FFSSb->fs_id)[1];
+
+               Vcb->StreamObj = IoCreateStreamFileObject(NULL, Vcb->Vpb->RealDevice);
+
+               if (Vcb->StreamObj)
+               {
+                       Vcb->StreamObj->SectionObjectPointer = &(Vcb->SectionObject);
+                       Vcb->StreamObj->Vpb = Vcb->Vpb;
+                       Vcb->StreamObj->ReadAccess = TRUE;
+                       if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY))
+                       {
+                               Vcb->StreamObj->WriteAccess = TRUE;
+                               Vcb->StreamObj->DeleteAccess = TRUE;
+                       }
+                       else
+                       {
+                               Vcb->StreamObj->WriteAccess = TRUE;
+                               Vcb->StreamObj->DeleteAccess = TRUE;
+                       }
+                       Vcb->StreamObj->FsContext = (PVOID) Vcb;
+                       Vcb->StreamObj->FsContext2 = NULL;
+                       Vcb->StreamObj->Vpb = Vcb->Vpb;
+
+                       SetFlag(Vcb->StreamObj->Flags, FO_NO_INTERMEDIATE_BUFFERING);
+               }
+               else
+               {
+                       _SEH2_LEAVE;
+               }
+
+               InitializeListHead(&Vcb->FcbList);
+
+               InitializeListHead(&Vcb->NotifyList);
+
+               FsRtlNotifyInitializeSync(&Vcb->NotifySync);
+
+               NotifySyncInitialized = TRUE;
+
+               Vcb->DeviceObject = VolumeDevice;
+
+               Vcb->TargetDeviceObject = TargetDevice;
+
+               Vcb->OpenFileHandleCount = 0;
+
+               Vcb->ReferenceCount = 0;
+
+               Vcb->ffs_super_block = FFSSb;
+
+               Vcb->Header.NodeTypeCode = (USHORT) FFSVCB;
+               Vcb->Header.NodeByteSize = sizeof(FFS_VCB);
+               Vcb->Header.IsFastIoPossible = FastIoIsNotPossible;
+               Vcb->Header.Resource = &(Vcb->MainResource);
+               Vcb->Header.PagingIoResource = &(Vcb->PagingIoResource);
+
+               Vcb->Vpb->SerialNumber = 'PS';
+
+               DiskSize =
+                       Vcb->DiskGeometry.Cylinders.QuadPart *
+                       Vcb->DiskGeometry.TracksPerCylinder *
+                       Vcb->DiskGeometry.SectorsPerTrack *
+                       Vcb->DiskGeometry.BytesPerSector;
+
+               IoctlSize = sizeof(PARTITION_INFORMATION);
+
+               Status = FFSDiskIoControl(
+                                       TargetDevice,
+                                       IOCTL_DISK_GET_PARTITION_INFO,
+                                       NULL,
+                                       0,
+                                       &Vcb->PartitionInformation,
+                                       &IoctlSize);
+
+               PartSize = Vcb->PartitionInformation.PartitionLength.QuadPart;
+
+               if (!NT_SUCCESS(Status))
+               {
+                       Vcb->PartitionInformation.StartingOffset.QuadPart = 0;
+
+                       Vcb->PartitionInformation.PartitionLength.QuadPart =
+                               DiskSize;
+
+                       PartSize = DiskSize;
+
+                       Status = STATUS_SUCCESS;
+               }
+
+               IoctlSize = sizeof(ULONG);
+               Status = FFSDiskIoControl(
+                                       TargetDevice,
+                                       IOCTL_DISK_CHECK_VERIFY,
+                                       NULL,
+                                       0,
+                                       &ChangeCount,
+                                       &IoctlSize);
+
+               if (!NT_SUCCESS(Status))
+               {
+                       _SEH2_LEAVE;
+               }
+
+               Vcb->ChangeCount = ChangeCount;
+
+               Vcb->Header.AllocationSize.QuadPart =
+                       Vcb->Header.FileSize.QuadPart = PartSize;
+
+               Vcb->Header.ValidDataLength.QuadPart = 
+                       (LONGLONG)(0x7fffffffffffffff);
+               /*
+               Vcb->Header.AllocationSize.QuadPart = (LONGLONG)(ffs_super_block->s_blocks_count - ffs_super_block->s_free_blocks_count)
+                       * (FFS_MIN_BLOCK << ffs_super_block->s_log_block_size);
+                       Vcb->Header.FileSize.QuadPart = Vcb->Header.AllocationSize.QuadPart;
+                       Vcb->Header.ValidDataLength.QuadPart = Vcb->Header.AllocationSize.QuadPart;
+               */
+
+               {
+                       CC_FILE_SIZES FileSizes;
+
+                       FileSizes.AllocationSize.QuadPart =
+                               FileSizes.FileSize.QuadPart =
+                               Vcb->Header.AllocationSize.QuadPart;
+
+                       FileSizes.ValidDataLength.QuadPart= (LONGLONG)(0x7fffffffffffffff);
+
+                       CcInitializeCacheMap(Vcb->StreamObj,
+                                       &FileSizes,
+                                       TRUE,
+                                       &(FFSGlobal->CacheManagerNoOpCallbacks),
+                                       Vcb);
+               }
+#if 0 //       LoadGroup XXX
+               if (!FFSLoadGroup(Vcb))
+               {
+                       Status = STATUS_UNSUCCESSFUL;
+                       _SEH2_LEAVE;
+               }
+#endif
+               FsRtlInitializeLargeMcb(&(Vcb->DirtyMcbs), PagedPool);
+               InitializeListHead(&(Vcb->McbList));
+
+               if (IsFlagOn(FFSGlobal->Flags, FFS_CHECKING_BITMAP))
+               {
+                       FFSCheckBitmapConsistency(IrpContext, Vcb);
+               }
+
+               {
+                       ULONG   dwData[FFS_BLOCK_TYPES] = {NDADDR, 1, 1, 1};
+                       ULONG   dwMeta[FFS_BLOCK_TYPES] = {0, 0, 0, 0};
+                       ULONG   i;
+
+                       if (FS_VERSION == 1)
+                       {
+                               for (i = 0; i < FFS_BLOCK_TYPES; i++)
+                               {
+                                       dwData[i] = dwData[i] << ((BLOCK_BITS - 2) * i);
+
+                                       if (i > 0)
+                                       {
+                                               dwMeta[i] = 1 + (dwMeta[i - 1] << (BLOCK_BITS - 2));
+                                       }
+
+                                       Vcb->dwData[i] = dwData[i];
+                                       Vcb->dwMeta[i] = dwMeta[i];
+                               }
+                       }
+                       else
+                       {
+                               for (i = 0; i < FFS_BLOCK_TYPES; i++)
+                               {
+                                       dwData[i] = dwData[i] << ((BLOCK_BITS - 3) * i);
+
+                                       if (i > 0)
+                                       {
+                                               dwMeta[i] = 1 + (dwMeta[i - 1] << (BLOCK_BITS - 3));
+                                       }
+
+                                       Vcb->dwData[i] = dwData[i];
+                                       Vcb->dwMeta[i] = dwMeta[i];
+                               }
+                       }
+               }
+
+               SetFlag(Vcb->Flags, VCB_INITIALIZED);
+       }
+
+       _SEH2_FINALLY
+       {
+               if (!NT_SUCCESS(Status))
+               {
+                       if (NotifySyncInitialized)
+                       {
+                               FsRtlNotifyUninitializeSync(&Vcb->NotifySync);
+                       }
+
+                       if (Vcb->ffs_super_block)
+                       {
+                               ExFreePool(Vcb->ffs_super_block);
+                               Vcb->ffs_super_block = NULL;
+                       }
+
+                       if (VcbResourceInitialized)
+                       {
+                               ExDeleteResourceLite(&Vcb->MainResource);
+                               ExDeleteResourceLite(&Vcb->PagingIoResource);
+                       }
+               }
+       } _SEH2_END;
+
+       return Status;
+}
+
+
+__drv_mustHoldCriticalRegion
+VOID
+FFSFreeVcb(
+       IN PFFS_VCB Vcb)
+{
+    PAGED_CODE();
+
+       ASSERT(Vcb != NULL);
+
+       ASSERT((Vcb->Identifier.Type == FFSVCB) &&
+                       (Vcb->Identifier.Size == sizeof(FFS_VCB)));
+
+       FsRtlNotifyUninitializeSync(&Vcb->NotifySync);
+
+       if (Vcb->StreamObj)
+       {
+               if (IsFlagOn(Vcb->StreamObj->Flags, FO_FILE_MODIFIED))
+               {
+                       IO_STATUS_BLOCK IoStatus;
+
+                       CcFlushCache(&(Vcb->SectionObject), NULL, 0, &IoStatus);
+                       ClearFlag(Vcb->StreamObj->Flags, FO_FILE_MODIFIED);
+               }
+
+               if (Vcb->StreamObj->PrivateCacheMap)
+                       FFSSyncUninitializeCacheMap(Vcb->StreamObj);
+
+               ObDereferenceObject(Vcb->StreamObj);
+               Vcb->StreamObj = NULL;
+       }
+
+#if DBG
+       if (FsRtlNumberOfRunsInLargeMcb(&(Vcb->DirtyMcbs)) != 0)
+       {
+               LONGLONG            DirtyVba;
+               LONGLONG            DirtyLba;
+               LONGLONG            DirtyLength;
+               int                 i;
+
+               for (i = 0; FsRtlGetNextLargeMcbEntry (&(Vcb->DirtyMcbs), i, &DirtyVba, &DirtyLba, &DirtyLength); i++)
+               {
+                       FFSPrint((DBG_INFO, "DirtyVba = %I64xh\n", DirtyVba));
+                       FFSPrint((DBG_INFO, "DirtyLba = %I64xh\n", DirtyLba));
+                       FFSPrint((DBG_INFO, "DirtyLen = %I64xh\n\n", DirtyLength));
+               }
+
+               FFSBreakPoint();
+       }
+#endif
+
+       FsRtlUninitializeLargeMcb(&(Vcb->DirtyMcbs));
+
+       FFSFreeMcbTree(Vcb->McbTree);
+
+       if (Vcb->ffs_super_block)
+       {
+               ExFreePool(Vcb->ffs_super_block);
+               Vcb->ffs_super_block = NULL;
+       }
+
+       ExDeleteResourceLite(&Vcb->McbResource);
+
+       ExDeleteResourceLite(&Vcb->PagingIoResource);
+
+       ExDeleteResourceLite(&Vcb->MainResource);
+
+       IoDeleteDevice(Vcb->DeviceObject);
+}
+
+
+VOID
+FFSSyncUninitializeCacheMap(
+       IN PFILE_OBJECT FileObject)
+{
+       CACHE_UNINITIALIZE_EVENT UninitializeCompleteEvent;
+       NTSTATUS WaitStatus;
+       LARGE_INTEGER FFSLargeZero = {0, 0};
+
+    PAGED_CODE();
+
+       KeInitializeEvent(&UninitializeCompleteEvent.Event,
+                       SynchronizationEvent,
+                       FALSE);
+
+       CcUninitializeCacheMap(FileObject,
+                       &FFSLargeZero,
+                       &UninitializeCompleteEvent);
+
+       WaitStatus = KeWaitForSingleObject(&UninitializeCompleteEvent.Event,
+                       Executive,
+                       KernelMode,
+                       FALSE,
+                       NULL);
+
+       ASSERT (NT_SUCCESS(WaitStatus));
+}
diff --git a/reactos/drivers/filesystems/ffs/src/misc.c b/reactos/drivers/filesystems/ffs/src/misc.c
new file mode 100644 (file)
index 0000000..da42a75
--- /dev/null
@@ -0,0 +1,128 @@
+/* 
+ * FFS File System Driver for Windows
+ *
+ * misc.c
+ *
+ * 2004.5.6 ~
+ *
+ * Lee Jae-Hong, http://www.pyrasis.com
+ *
+ * See License.txt
+ *
+ */
+
+#include "ntifs.h"
+#include "ffsdrv.h"
+
+/* Globals */
+
+extern PFFS_GLOBAL FFSGlobal;
+
+
+/* Definitions */
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE, FFSLog2)
+#pragma alloc_text(PAGE, FFSSysTime)
+#pragma alloc_text(PAGE, FFSInodeTime)
+#pragma alloc_text(PAGE, FFSOEMToUnicode)
+#pragma alloc_text(PAGE, FFSUnicodeToOEM)
+#endif
+
+ULONG
+FFSLog2(
+       ULONG Value)
+{
+       ULONG Order = 0;
+
+    PAGED_CODE();
+
+       ASSERT(Value > 0);
+
+       while (Value)
+       {
+               Order++;
+               Value >>= 1;
+       }
+
+       return (Order - 1);
+}
+
+
+LARGE_INTEGER
+FFSSysTime(
+       IN ULONG i_time)
+{
+       LARGE_INTEGER SysTime;
+
+    PAGED_CODE();
+
+       RtlSecondsSince1970ToTime(i_time, &SysTime);
+
+       return SysTime;
+}
+
+ULONG
+FFSInodeTime(
+       IN LARGE_INTEGER SysTime)
+{
+       ULONG   FFSTime;
+
+    PAGED_CODE();
+
+       RtlTimeToSecondsSince1970(&SysTime, &FFSTime);
+
+       return FFSTime;
+}
+
+
+NTSTATUS
+FFSOEMToUnicode(
+       IN OUT PUNICODE_STRING Unicode,
+       IN     POEM_STRING     Oem)
+{
+       NTSTATUS  Status;
+
+    PAGED_CODE();
+
+       Status = RtlOemStringToUnicodeString(
+                       Unicode, 
+                       Oem,
+                       FALSE);
+
+       if (!NT_SUCCESS(Status))
+       {
+               FFSBreakPoint();
+               goto errorout;
+       }
+
+errorout:
+
+       return Status;
+}
+
+
+NTSTATUS
+FFSUnicodeToOEM(
+       IN OUT POEM_STRING Oem,
+       IN PUNICODE_STRING Unicode)
+{
+       NTSTATUS Status;
+
+    PAGED_CODE();
+
+       Status = RtlUnicodeStringToOemString(
+                       Oem,
+                       Unicode,
+                       FALSE);
+
+       if (!NT_SUCCESS(Status))
+       {
+               FFSBreakPoint();
+               goto errorout;
+       }
+
+errorout:
+
+       return Status;
+}
diff --git a/reactos/drivers/filesystems/ffs/src/pnp.c b/reactos/drivers/filesystems/ffs/src/pnp.c
new file mode 100644 (file)
index 0000000..7c8427f
--- /dev/null
@@ -0,0 +1,463 @@
+/* 
+ * FFS File System Driver for Windows
+ *
+ * misc.c
+ *
+ * 2004.5.6 ~
+ *
+ * Lee Jae-Hong, http://www.pyrasis.com
+ *
+ * See License.txt
+ *
+ */
+
+#include "ntifs.h"
+#include "ffsdrv.h"
+
+
+extern PFFS_GLOBAL FFSGlobal;
+
+#if (_WIN32_WINNT >= 0x0500)
+
+/* Globals */
+
+extern PFFS_GLOBAL FFSGlobal;
+
+/* Definitions */
+
+#define DBG_PNP DBG_USER
+
+#ifdef _PREFAST_
+IO_COMPLETION_ROUTINE FFSPnpCompletionRoutine;
+#endif // _PREFAST_
+
+NTSTATUS NTAPI
+FFSPnpCompletionRoutine(
+       IN PDEVICE_OBJECT DeviceObject,
+       IN PIRP           Irp,
+       IN PVOID          Contxt);
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE, FFSPnp)
+#pragma alloc_text(PAGE, FFSPnpQueryRemove)
+#pragma alloc_text(PAGE, FFSPnpRemove)
+#pragma alloc_text(PAGE, FFSPnpCancelRemove)
+#pragma alloc_text(PAGE, FFSPnpSurpriseRemove)
+#endif
+
+
+
+NTSTATUS NTAPI
+FFSPnpCompletionRoutine(
+       IN PDEVICE_OBJECT DeviceObject,
+       IN PIRP Irp,
+       IN PVOID Contxt)
+{
+       PKEVENT Event = (PKEVENT) Contxt;
+
+       KeSetEvent(Event, 0, FALSE);
+
+       return STATUS_MORE_PROCESSING_REQUIRED;
+
+       UNREFERENCED_PARAMETER(DeviceObject);
+       UNREFERENCED_PARAMETER(Contxt);
+}
+
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSPnp(
+       IN PFFS_IRP_CONTEXT IrpContext)
+{
+       NTSTATUS            Status = STATUS_INVALID_PARAMETER;
+
+       PIRP                Irp;
+       PIO_STACK_LOCATION  IrpSp;
+       PFFS_VCB            Vcb = 0;
+       PDEVICE_OBJECT      DeviceObject;
+
+    PAGED_CODE();
+
+       _SEH2_TRY
+       {
+               ASSERT(IrpContext);
+
+               ASSERT((IrpContext->Identifier.Type == FFSICX) &&
+                               (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
+
+               DeviceObject = IrpContext->DeviceObject;
+
+               Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;
+
+               ASSERT(Vcb != NULL);
+
+               if (!((Vcb->Identifier.Type == FFSVCB) &&
+                       (Vcb->Identifier.Size == sizeof(FFS_VCB))))
+               {
+                       _SEH2_LEAVE; // Status = STATUS_INVALID_PARAMETER
+               }
+
+               Irp = IrpContext->Irp;
+               IrpSp = IoGetCurrentIrpStackLocation(Irp);
+
+               SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
+
+               switch (IrpSp->MinorFunction)
+               {
+
+                       case IRP_MN_QUERY_REMOVE_DEVICE:
+
+                               FFSPrint((DBG_PNP, "FFSPnp: FFSPnpQueryRemove...\n"));
+                               Status = FFSPnpQueryRemove(IrpContext, Vcb);
+
+                               break;
+
+                       case IRP_MN_REMOVE_DEVICE:
+
+                               FFSPrint((DBG_PNP, "FFSPnp: FFSPnpRemove...\n"));
+                               Status = FFSPnpRemove(IrpContext, Vcb);
+                               break;
+
+                       case IRP_MN_CANCEL_REMOVE_DEVICE:
+
+                               FFSPrint((DBG_PNP, "FFSPnp: FFSPnpCancelRemove...\n"));
+                               Status = FFSPnpCancelRemove(IrpContext, Vcb);
+                               break;
+
+                       case IRP_MN_SURPRISE_REMOVAL:
+
+                               FFSPrint((DBG_PNP, "FFSPnp: FFSPnpSupriseRemove...\n"));
+                               Status = FFSPnpSurpriseRemove(IrpContext, Vcb);
+                               break;
+
+                       default:
+                               break;
+               }
+       }
+
+       _SEH2_FINALLY
+       {
+               if (!IrpContext->ExceptionInProgress)
+               {
+                       Irp = IrpContext->Irp;
+
+                       if (Irp)
+                       {
+                               //
+                               // Here we need pass the IRP to the disk driver.
+                               //
+
+                               IoSkipCurrentIrpStackLocation(Irp);
+
+                               Status = IoCallDriver(Vcb->TargetDeviceObject, Irp);
+
+                               IrpContext->Irp = NULL;
+                       }
+
+                       FFSCompleteIrpContext(IrpContext, Status);
+               }
+       } _SEH2_END;
+
+       return Status;
+}
+
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSPnpQueryRemove(
+       PFFS_IRP_CONTEXT IrpContext,
+       PFFS_VCB         Vcb)
+{
+       NTSTATUS Status;
+       KEVENT   Event;
+       BOOLEAN  bDeleted = FALSE;
+       BOOLEAN  VcbAcquired = FALSE;
+
+    PAGED_CODE();
+
+       _SEH2_TRY {
+
+               FFSPrint((DBG_PNP, "FFSPnpQueryRemove by FFSPnp ...\n"));
+
+               FFSPrint((DBG_PNP, "FFSPnpQueryRemove: FFSFlushVolume ...\n"));
+
+#if (_WIN32_WINNT >= 0x0500)
+               CcWaitForCurrentLazyWriterActivity();
+#endif
+
+               ExAcquireResourceExclusiveLite(
+                       &Vcb->MainResource, TRUE);
+               VcbAcquired = TRUE;
+
+               FFSFlushFiles(Vcb, FALSE);
+
+               FFSFlushVolume(Vcb, FALSE);
+
+               FFSPrint((DBG_PNP, "FFSPnpQueryRemove: FFSLockVcb: Vcb=%xh FileObject=%xh ...\n", Vcb, IrpContext->FileObject));
+               Status = FFSLockVcb(Vcb, IrpContext->FileObject);
+
+               FFSPrint((DBG_PNP, "FFSPnpQueryRemove: FFSPurgeVolume ...\n"));
+               FFSPurgeVolume(Vcb, TRUE);
+
+               if (!NT_SUCCESS(Status))
+               {
+                       _SEH2_LEAVE;
+               }
+
+               ExReleaseResourceForThreadLite(
+                               &Vcb->MainResource,
+                               ExGetCurrentResourceThread());
+               VcbAcquired = FALSE;
+
+               IoCopyCurrentIrpStackLocationToNext(IrpContext->Irp);
+
+               KeInitializeEvent(&Event, NotificationEvent, FALSE);
+               IoSetCompletionRoutine(IrpContext->Irp,
+                               FFSPnpCompletionRoutine,
+                               &Event,
+                               TRUE,
+                               TRUE,
+                               TRUE);
+
+               FFSPrint((DBG_PNP, "FFSPnpQueryRemove: Call lower level driver...\n"));
+               Status = IoCallDriver(Vcb->TargetDeviceObject, 
+                               IrpContext->Irp);
+
+               if (Status == STATUS_PENDING)
+               {
+                       KeWaitForSingleObject(&Event,
+                                       Executive,
+                                       KernelMode,
+                                       FALSE,
+                                       NULL);
+
+                       Status = IrpContext->Irp->IoStatus.Status;
+               }
+
+               if (NT_SUCCESS(Status))
+               {
+                       FFSPrint((DBG_PNP, "FFSPnpQueryRemove: FFSCheckDismount ...\n"));
+                       bDeleted = FFSCheckDismount(IrpContext, Vcb, TRUE);
+                       FFSPrint((DBG_PNP, "FFSPnpQueryRemove: FFSFlushVolume bDelted=%xh ...\n", bDeleted));
+               }
+
+               ASSERT(!(NT_SUCCESS(Status) && !bDeleted));
+       }
+
+       _SEH2_FINALLY
+       {
+               if (VcbAcquired)
+               {
+                       ExReleaseResourceForThreadLite(
+                                       &Vcb->MainResource,
+                                       ExGetCurrentResourceThread());
+               }
+
+               FFSCompleteRequest(
+                               IrpContext->Irp, FALSE, (CCHAR)(NT_SUCCESS(Status) ?
+                                       IO_DISK_INCREMENT : IO_NO_INCREMENT));
+
+               IrpContext->Irp = NULL;
+       } _SEH2_END;
+
+       return Status;
+}
+
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSPnpRemove(
+       PFFS_IRP_CONTEXT IrpContext,
+       PFFS_VCB         Vcb)
+{
+       NTSTATUS Status;
+       KEVENT   Event;
+       BOOLEAN  bDeleted;
+
+    PAGED_CODE();
+
+       _SEH2_TRY
+       {
+
+               FFSPrint((DBG_PNP, "FFSPnpRemove by FFSPnp ...\n"));
+#if (_WIN32_WINNT >= 0x0500)
+               CcWaitForCurrentLazyWriterActivity();
+#endif
+               ExAcquireResourceExclusiveLite(
+                               &Vcb->MainResource,  TRUE);
+
+               Status = FFSLockVcb(Vcb, IrpContext->FileObject);
+
+               ExReleaseResourceForThreadLite(
+                               &Vcb->MainResource,
+                               ExGetCurrentResourceThread());
+
+               //
+               // Setup the Irp. We'll send it to the lower disk driver.
+               //
+
+               IoCopyCurrentIrpStackLocationToNext(IrpContext->Irp);
+
+               KeInitializeEvent(&Event, NotificationEvent, FALSE);
+               IoSetCompletionRoutine(IrpContext->Irp,
+                               FFSPnpCompletionRoutine,
+                               &Event,
+                               TRUE,
+                               TRUE,
+                               TRUE);
+
+               Status = IoCallDriver(Vcb->TargetDeviceObject, 
+                               IrpContext->Irp);
+
+               if (Status == STATUS_PENDING)
+               {
+
+                       KeWaitForSingleObject(&Event,
+                                       Executive,
+                                       KernelMode,
+                                       FALSE,
+                                       NULL);
+
+                       Status = IrpContext->Irp->IoStatus.Status;
+               }
+
+               ExAcquireResourceExclusiveLite(
+                               &Vcb->MainResource, TRUE);
+
+               FFSPurgeVolume(Vcb, FALSE);
+
+               ExReleaseResourceForThreadLite(
+                               &Vcb->MainResource,
+                               ExGetCurrentResourceThread());
+
+               bDeleted = FFSCheckDismount(IrpContext, Vcb, TRUE);
+       }
+
+       _SEH2_FINALLY
+       {
+               FFSCompleteRequest(
+                               IrpContext->Irp, FALSE, (CCHAR)(NT_SUCCESS(Status)?
+                                       IO_DISK_INCREMENT : IO_NO_INCREMENT));
+
+               IrpContext->Irp = NULL;
+       } _SEH2_END;
+
+       return Status;
+}
+
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSPnpSurpriseRemove(
+       PFFS_IRP_CONTEXT IrpContext,
+       PFFS_VCB         Vcb)
+{
+       NTSTATUS Status;
+       KEVENT   Event;
+       BOOLEAN  bDeleted;
+
+    PAGED_CODE();
+
+       _SEH2_TRY
+       {
+
+               FFSPrint((DBG_PNP, "FFSPnpSupriseRemove by FFSPnp ...\n"));
+#if (_WIN32_WINNT >= 0x0500)
+               CcWaitForCurrentLazyWriterActivity();
+#endif
+               ExAcquireResourceExclusiveLite(
+                               &Vcb->MainResource,  TRUE);
+
+               Status = FFSLockVcb(Vcb, IrpContext->FileObject);
+
+               ExReleaseResourceForThreadLite(
+                               &Vcb->MainResource,
+                               ExGetCurrentResourceThread());
+
+               //
+               // Setup the Irp. We'll send it to the lower disk driver.
+               //
+
+               IoCopyCurrentIrpStackLocationToNext(IrpContext->Irp);
+
+               KeInitializeEvent(&Event, NotificationEvent, FALSE);
+               IoSetCompletionRoutine(IrpContext->Irp,
+                               FFSPnpCompletionRoutine,
+                               &Event,
+                               TRUE,
+                               TRUE,
+                               TRUE);
+
+               Status = IoCallDriver(Vcb->TargetDeviceObject, 
+                                       IrpContext->Irp);
+
+               if (Status == STATUS_PENDING)
+               {
+
+                       KeWaitForSingleObject(&Event,
+                                       Executive,
+                                       KernelMode,
+                                       FALSE,
+                                       NULL);
+
+                       Status = IrpContext->Irp->IoStatus.Status;
+               }
+
+               ExAcquireResourceExclusiveLite(
+                               &Vcb->MainResource, TRUE);
+
+               FFSPurgeVolume(Vcb, FALSE);
+
+               ExReleaseResourceForThreadLite(
+                               &Vcb->MainResource,
+                               ExGetCurrentResourceThread());
+
+               bDeleted = FFSCheckDismount(IrpContext, Vcb, TRUE);
+       }
+
+       _SEH2_FINALLY
+       {
+               FFSCompleteRequest(
+                               IrpContext->Irp, FALSE, (CCHAR)(NT_SUCCESS(Status)?
+                                       IO_DISK_INCREMENT : IO_NO_INCREMENT));
+
+               IrpContext->Irp = NULL;
+       } _SEH2_END;
+
+       return Status;
+}
+
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSPnpCancelRemove(
+       PFFS_IRP_CONTEXT IrpContext,
+       PFFS_VCB         Vcb)
+{
+       NTSTATUS Status;
+
+    PAGED_CODE();
+
+       FFSPrint((DBG_PNP, "FFSPnpCancelRemove by FFSPnp ...\n"));
+
+       ExAcquireResourceExclusiveLite(
+                       &Vcb->MainResource, TRUE);
+
+       Status = FFSUnlockVcb(Vcb, IrpContext->FileObject);
+
+       ExReleaseResourceForThreadLite(
+                       &Vcb->MainResource,
+                       ExGetCurrentResourceThread());
+
+       IoSkipCurrentIrpStackLocation(IrpContext->Irp);
+
+       Status = IoCallDriver(Vcb->TargetDeviceObject, IrpContext->Irp);
+
+       IrpContext->Irp = NULL;
+
+       return Status;
+}
+
+
+#endif //(_WIN32_WINNT >= 0x0500)
diff --git a/reactos/drivers/filesystems/ffs/src/read.c b/reactos/drivers/filesystems/ffs/src/read.c
new file mode 100644 (file)
index 0000000..b5a5cc5
--- /dev/null
@@ -0,0 +1,1155 @@
+/* 
+ * FFS File System Driver for Windows
+ *
+ * read.c
+ *
+ * 2004.5.6 ~
+ *
+ * Lee Jae-Hong, http://www.pyrasis.com
+ *
+ * See License.txt
+ *
+ */
+
+#include "ntifs.h"
+#include "ffsdrv.h"
+
+/* Globals */
+
+extern PFFS_GLOBAL FFSGlobal;
+
+
+/* Definitions */
+
+NTSTATUS
+FFSReadComplete(
+       IN PFFS_IRP_CONTEXT IrpContext);
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSReadFile(
+       IN PFFS_IRP_CONTEXT IrpContext);
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSReadVolume(
+       IN PFFS_IRP_CONTEXT IrpContext);
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE, FFSCompleteIrpContext)
+#pragma alloc_text(PAGE, FFSCopyRead)
+#pragma alloc_text(PAGE, FFSRead)
+#pragma alloc_text(PAGE, FFSReadVolume)
+#pragma alloc_text(PAGE, FFSv1ReadInode)
+#pragma alloc_text(PAGE, FFSv2ReadInode)
+#pragma alloc_text(PAGE, FFSReadFile)
+#pragma alloc_text(PAGE, FFSReadComplete)
+
+#endif
+
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSCompleteIrpContext(
+       IN PFFS_IRP_CONTEXT IrpContext,
+       IN NTSTATUS         Status)
+{
+       PIRP    Irp = NULL;
+       BOOLEAN bPrint;
+
+    PAGED_CODE();
+
+       Irp = IrpContext->Irp;
+
+       if (Irp != NULL)
+       {
+               if (NT_ERROR(Status))
+               {
+                       Irp->IoStatus.Information = 0;
+               }
+
+               Irp->IoStatus.Status = Status;
+               bPrint = !IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED);
+
+               FFSCompleteRequest(
+                               Irp, bPrint, (CCHAR)(NT_SUCCESS(Status)?
+                                       IO_DISK_INCREMENT : IO_NO_INCREMENT));
+
+               IrpContext->Irp = NULL;               
+       }
+
+       FFSFreeIrpContext(IrpContext);
+
+       return Status;
+}
+
+
+BOOLEAN 
+FFSCopyRead(
+       IN PFILE_OBJECT       FileObject,
+       IN PLARGE_INTEGER     FileOffset,
+       IN ULONG              Length,
+       IN BOOLEAN            Wait,
+       OUT PVOID             Buffer,
+       OUT PIO_STATUS_BLOCK  IoStatus)
+{
+       BOOLEAN bRet;
+
+    PAGED_CODE();
+
+       bRet =  CcCopyRead(FileObject,
+                               FileOffset,
+                               Length,
+                               Wait,
+                               Buffer,
+                               IoStatus);
+
+       if (bRet)
+       {
+               ASSERT(NT_SUCCESS(IoStatus->Status));
+       }
+
+       return bRet;
+/*
+          PVOID Bcb = NULL;
+          PVOID Buf = NULL;
+
+          if (CcMapData(FileObject,
+                       FileOffset,
+                       Length,
+                       Wait,
+                       &Bcb,
+                       &Buf))
+          {
+                       RtlCopyMemory(Buffer,  Buf, Length);
+                       IoStatus->Status = STATUS_SUCCESS;
+                       IoStatus->Information = Length;
+                       CcUnpinData(Bcb);
+                       return TRUE;
+                  
+          }
+          else
+          {
+                       // IoStatus->Status = STATUS_
+                       return FALSE;
+          }
+*/
+}
+
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSReadVolume(
+       IN PFFS_IRP_CONTEXT IrpContext)
+{
+       NTSTATUS            Status = STATUS_UNSUCCESSFUL;
+
+       PFFS_VCB            Vcb = 0;
+       PFFS_CCB            Ccb;
+       PFFS_FCBVCB         FcbOrVcb;
+       PFILE_OBJECT        FileObject;
+
+       PDEVICE_OBJECT      DeviceObject;
+
+       PIRP                Irp;
+       PIO_STACK_LOCATION  IoStackLocation;
+
+       ULONG               Length;
+       LARGE_INTEGER       ByteOffset;
+
+       BOOLEAN             PagingIo;
+       BOOLEAN             Nocache;
+       BOOLEAN             SynchronousIo;
+       BOOLEAN             MainResourceAcquired = FALSE;
+       BOOLEAN             PagingIoResourceAcquired = FALSE;
+
+       PUCHAR              Buffer = NULL;
+       PFFS_BDL            ffs_bdl = NULL;
+
+    PAGED_CODE();
+
+       _SEH2_TRY
+       {
+               ASSERT(IrpContext);
+
+               ASSERT((IrpContext->Identifier.Type == FFSICX) &&
+                               (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
+
+               DeviceObject = IrpContext->DeviceObject;
+
+               Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;
+
+               ASSERT(Vcb != NULL);
+
+               ASSERT((Vcb->Identifier.Type == FFSVCB) &&
+                               (Vcb->Identifier.Size == sizeof(FFS_VCB)));
+
+               FileObject = IrpContext->FileObject;
+
+               FcbOrVcb = (PFFS_FCBVCB)FileObject->FsContext;
+
+               ASSERT(FcbOrVcb);
+
+               if (!(FcbOrVcb->Identifier.Type == FFSVCB && (PVOID)FcbOrVcb == (PVOID)Vcb))
+               {
+                       Status = STATUS_INVALID_DEVICE_REQUEST;
+                       _SEH2_LEAVE;
+               }
+
+               Ccb = (PFFS_CCB)FileObject->FsContext2;
+
+               Irp = IrpContext->Irp;
+
+               Irp->IoStatus.Information = 0;
+
+               IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
+
+               Length = IoStackLocation->Parameters.Read.Length;
+               ByteOffset = IoStackLocation->Parameters.Read.ByteOffset;
+
+               PagingIo = (Irp->Flags & IRP_PAGING_IO ? TRUE : FALSE);
+               Nocache = (Irp->Flags & IRP_NOCACHE ? TRUE : FALSE);
+               SynchronousIo = (FileObject->Flags & FO_SYNCHRONOUS_IO ? TRUE : FALSE);
+
+               if (Length == 0)
+               {
+                       Irp->IoStatus.Information = 0;
+                       Status = STATUS_SUCCESS;
+                       _SEH2_LEAVE;
+               }
+
+               if (Ccb != NULL)
+               {
+                       if(!IsFlagOn(Ccb->Flags, CCB_ALLOW_EXTENDED_DASD_IO))
+                       {
+                               if (ByteOffset.QuadPart + Length > Vcb->Header.FileSize.QuadPart)
+                               {
+                                       Length = (ULONG)(Vcb->Header.FileSize.QuadPart - ByteOffset.QuadPart);
+                               }
+                       }
+
+                       {
+                               FFS_BDL BlockArray;
+
+                               if ((ByteOffset.LowPart & (SECTOR_SIZE - 1)) ||
+                                               (Length & (SECTOR_SIZE - 1)))
+                               {
+                                       Status = STATUS_INVALID_PARAMETER;
+                                       _SEH2_LEAVE;
+                               }
+
+                               Status = FFSLockUserBuffer(
+                                                       IrpContext->Irp,
+                                                       Length,
+                                                       IoReadAccess);
+
+                               if (!NT_SUCCESS(Status))
+                               {
+                                       _SEH2_LEAVE;
+                               }
+
+                               BlockArray.Irp = NULL;
+                               BlockArray.Lba = ByteOffset.QuadPart;;
+                               BlockArray.Offset = 0;
+                               BlockArray.Length = Length;
+
+                               Status = FFSReadWriteBlocks(IrpContext,
+                                                       Vcb,
+                                                       &BlockArray,
+                                                       Length,
+                                                       1,
+                                                       FALSE);
+                               Irp = IrpContext->Irp;
+
+                               _SEH2_LEAVE;
+                       }
+               }
+
+               if (Nocache &&
+                               ((ByteOffset.LowPart & (SECTOR_SIZE - 1)) ||
+                                 (Length & (SECTOR_SIZE - 1))))
+               {
+                       FFSBreakPoint();
+
+                       Status = STATUS_INVALID_PARAMETER;
+                       _SEH2_LEAVE;
+               }
+
+               if (FlagOn(IrpContext->MinorFunction, IRP_MN_DPC))
+               {
+                       ClearFlag(IrpContext->MinorFunction, IRP_MN_DPC);
+                       Status = STATUS_PENDING;
+                       _SEH2_LEAVE;
+               }
+
+               if (!PagingIo)
+               {
+                       if (!ExAcquireResourceSharedLite(
+                                               &Vcb->MainResource,
+                                               IrpContext->IsSynchronous))
+                       {
+                               Status = STATUS_PENDING;
+                               _SEH2_LEAVE;
+                       }
+
+                       MainResourceAcquired = TRUE;
+               }
+               else
+               {
+                       if (!ExAcquireResourceSharedLite(
+                                               &Vcb->PagingIoResource,
+                                               IrpContext->IsSynchronous))
+                       {
+                               Status = STATUS_PENDING;
+                               _SEH2_LEAVE;
+                       }
+
+                       PagingIoResourceAcquired = TRUE;
+               }
+
+
+               if (ByteOffset.QuadPart >=
+                               Vcb->PartitionInformation.PartitionLength.QuadPart)
+               {
+                       Irp->IoStatus.Information = 0;
+                       Status = STATUS_END_OF_FILE;
+                       _SEH2_LEAVE;
+               }
+
+               if (!Nocache)
+               {
+                       if ((ByteOffset.QuadPart + Length) >
+                                       Vcb->PartitionInformation.PartitionLength.QuadPart)
+                       {
+                               Length = (ULONG)(
+                                               Vcb->PartitionInformation.PartitionLength.QuadPart -
+                                               ByteOffset.QuadPart);
+                               Length &= ~((ULONG)SECTOR_SIZE - 1);
+                       }
+
+                       if (FlagOn(IrpContext->MinorFunction, IRP_MN_MDL))
+                       {
+                               CcMdlRead(
+                                               Vcb->StreamObj,
+                                               &ByteOffset,
+                                               Length,
+                                               &Irp->MdlAddress,
+                                               &Irp->IoStatus);
+
+                               Status = Irp->IoStatus.Status;
+                       }
+                       else
+                       {
+                               Buffer = FFSGetUserBuffer(Irp);
+
+                               if (Buffer == NULL)
+                               {
+                                       FFSBreakPoint();
+                                       Status = STATUS_INVALID_USER_BUFFER;
+                                       _SEH2_LEAVE;
+                               }
+
+                               if (!CcCopyRead(
+                                                       Vcb->StreamObj,
+                                                       (PLARGE_INTEGER)&ByteOffset,
+                                                       Length,
+                                                       IrpContext->IsSynchronous,
+                                                       Buffer,
+                                                       &Irp->IoStatus))
+                               {
+                                       Status = STATUS_PENDING;
+                                       _SEH2_LEAVE;
+                               }
+
+                               Status = Irp->IoStatus.Status;
+                       }
+               }
+               else
+               {
+                       if ((ByteOffset.QuadPart + Length) >
+                                       Vcb->PartitionInformation.PartitionLength.QuadPart
+                       )
+                       {
+                               Length = (ULONG)(
+                                               Vcb->PartitionInformation.PartitionLength.QuadPart -
+                                               ByteOffset.QuadPart);
+
+                               Length &= ~((ULONG)SECTOR_SIZE - 1);
+                       }
+
+                       Status = FFSLockUserBuffer(
+                                       IrpContext->Irp,
+                                       Length,
+                                       IoWriteAccess);
+
+                       if (!NT_SUCCESS(Status))
+                       {
+                               _SEH2_LEAVE;
+                       }
+
+#if DBG
+                       Buffer = FFSGetUserBuffer(Irp);
+#endif
+                       ffs_bdl = ExAllocatePoolWithTag(PagedPool, sizeof(FFS_BDL), FFS_POOL_TAG);
+
+                       if (!ffs_bdl)
+                       {
+                               Status = STATUS_INSUFFICIENT_RESOURCES;
+                               _SEH2_LEAVE;
+                       }
+
+                       ffs_bdl->Irp = NULL;
+                       ffs_bdl->Lba = ByteOffset.QuadPart;
+                       ffs_bdl->Length = Length;
+                       ffs_bdl->Offset = 0;
+
+                       Status = FFSReadWriteBlocks(IrpContext,
+                                               Vcb,
+                                               ffs_bdl,
+                                               Length,
+                                               1,
+                                               FALSE);
+
+                       if (NT_SUCCESS(Status))
+                       {
+                               Irp->IoStatus.Information = Length;
+                       }
+
+                       Irp = IrpContext->Irp;
+
+                       if (!Irp)
+                               _SEH2_LEAVE;
+               }
+       }
+
+       _SEH2_FINALLY
+       {
+               if (PagingIoResourceAcquired)
+               {
+                       ExReleaseResourceForThreadLite(
+                                       &Vcb->PagingIoResource,
+                                       ExGetCurrentResourceThread());
+               }
+
+               if (MainResourceAcquired)
+               {
+                       ExReleaseResourceForThreadLite(
+                                       &Vcb->MainResource,
+                                       ExGetCurrentResourceThread());
+               }
+
+               if (ffs_bdl)
+                       ExFreePool(ffs_bdl);
+
+               if (!IrpContext->ExceptionInProgress)
+               {
+                       if (IrpContext->Irp)
+                       {
+                               if (Status == STATUS_PENDING &&
+                                               !IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED))
+                               {
+                                       Status = FFSLockUserBuffer(
+                                                               IrpContext->Irp,
+                                                               Length,
+                                                               IoWriteAccess);
+
+                                       if (NT_SUCCESS(Status))
+                                       {
+                                               Status = FFSQueueRequest(IrpContext);
+                                       }
+                                       else
+                                       {
+                                               FFSCompleteIrpContext(IrpContext, Status);
+                                       }
+                               }
+                               else
+                               {
+                                       if (NT_SUCCESS(Status))
+                                       {
+                                               if (SynchronousIo && !PagingIo)
+                                               {
+                                                       IrpContext->FileObject->CurrentByteOffset.QuadPart =
+                                                               ByteOffset.QuadPart + IrpContext->Irp->IoStatus.Information;
+                                               }
+
+                                               if (!PagingIo)
+                                               {
+                                                       IrpContext->FileObject->Flags &= ~FO_FILE_FAST_IO_READ;
+                                               }
+                                       }
+
+                                       FFSCompleteIrpContext(IrpContext, Status);
+                               }
+                       }
+                       else
+                       {
+                               FFSFreeIrpContext(IrpContext);
+                       }
+               }
+       } _SEH2_END;
+
+       return Status;
+}
+
+
+NTSTATUS
+FFSv1ReadInode(
+       IN PFFS_IRP_CONTEXT     IrpContext,
+       IN PFFS_VCB             Vcb,
+       IN PFFSv1_INODE         dinode1,
+       IN ULONGLONG            offset,
+       IN PVOID                Buffer,
+       IN ULONG                size,
+       OUT PULONG              dwRet)
+{
+       PFFS_BDL    ffs_bdl = NULL;
+       ULONG       blocks, i;
+       NTSTATUS    Status = STATUS_UNSUCCESSFUL;
+       IO_STATUS_BLOCK IoStatus;
+
+       ULONG       Totalblocks;
+       LONGLONG    AllocSize;
+
+    PAGED_CODE();
+
+       if (dwRet)
+       {
+               *dwRet = 0;
+       }
+
+       Totalblocks = (dinode1->di_blocks);
+       AllocSize = ((LONGLONG)(FFSDataBlocks(Vcb, Totalblocks)) << BLOCK_BITS);
+
+       if ((LONGLONG)offset >= AllocSize)
+       {
+               FFSPrint((DBG_ERROR, "FFSv1ReadInode: beyond the file range.\n"));
+               return STATUS_SUCCESS;
+       }
+
+       if ((LONGLONG)offset + size > AllocSize)
+       {
+               size = (ULONG)(AllocSize - offset);
+       }
+
+       blocks = FFSv1BuildBDL(IrpContext, Vcb, dinode1, offset, size, &ffs_bdl);
+
+       if (blocks <= 0)
+       {
+               FFSBreakPoint();
+               goto errorout;
+       }
+
+       if (IrpContext)
+       {
+               // assume offset is aligned.
+               Status = FFSReadWriteBlocks(IrpContext, Vcb, ffs_bdl, size, blocks, FALSE);
+       }
+       else
+       {
+               for(i = 0; i < blocks; i++)
+               {
+                       IoStatus.Information = 0;
+
+#if DBG
+                       KdPrint(("FFSv1ReadInode() i : %d, Lba : %x, Length : %x, Offset : %x\n", 
+                               i, ffs_bdl[i].Lba, ffs_bdl[i].Length, ffs_bdl[i].Offset));
+#endif
+
+                       FFSCopyRead(
+                                       Vcb->StreamObj, 
+                                       (PLARGE_INTEGER)(&(ffs_bdl[i].Lba)), 
+                                       ffs_bdl[i].Length,
+                                       PIN_WAIT,
+                                       (PVOID)((PUCHAR)Buffer + ffs_bdl[i].Offset), 
+                                       &IoStatus);
+
+                       Status = IoStatus.Status;
+               }
+       }
+
+errorout:
+
+       if (ffs_bdl)
+               ExFreePool(ffs_bdl);
+
+       if (NT_SUCCESS(Status))
+       {
+               if (dwRet) *dwRet = size;
+       }
+
+       return Status;
+}
+
+
+NTSTATUS
+FFSv2ReadInode(
+       IN PFFS_IRP_CONTEXT     IrpContext,
+       IN PFFS_VCB             Vcb,
+       IN PFFSv2_INODE         dinode2,
+       IN ULONGLONG            offset,
+       IN PVOID                Buffer,
+       IN ULONG                size,
+       OUT PULONG              dwRet)
+{
+       PFFS_BDL    ffs_bdl = NULL;
+       ULONG       blocks, i;
+       NTSTATUS    Status = STATUS_UNSUCCESSFUL;
+       IO_STATUS_BLOCK IoStatus;
+
+       ULONG       Totalblocks;
+       LONGLONG    AllocSize;
+
+    PAGED_CODE();
+
+       if (dwRet)
+       {
+               *dwRet = 0;
+       }
+
+       Totalblocks = (ULONG)(dinode2->di_blocks);
+       AllocSize = ((LONGLONG)(FFSDataBlocks(Vcb, Totalblocks)) << BLOCK_BITS);
+
+       if ((LONGLONG)offset >= AllocSize)
+       {
+               FFSPrint((DBG_ERROR, "FFSv2ReadInode: beyond the file range.\n"));
+               return STATUS_SUCCESS;
+       }
+
+       if ((LONGLONG)offset + size > AllocSize)
+       {
+               size = (ULONG)(AllocSize - offset);
+       }
+
+       blocks = FFSv2BuildBDL(IrpContext, Vcb, dinode2, offset, size, &ffs_bdl);
+
+       if (blocks <= 0)
+       {
+               FFSBreakPoint();
+               goto errorout;
+       }
+
+       if (IrpContext)
+       {
+               // assume offset is aligned.
+               Status = FFSReadWriteBlocks(IrpContext, Vcb, ffs_bdl, size, blocks, FALSE);
+       }
+       else
+       {
+               for(i = 0; i < blocks; i++)
+               {
+                       IoStatus.Information = 0;
+
+#if 0
+                       KdPrint(("FFSv2ReadInode() i : %d, Lba : %x, Length : %x, Offset : %x\n", 
+                               i, ffs_bdl[i].Lba, ffs_bdl[i].Length, ffs_bdl[i].Offset));
+#endif
+
+                       FFSCopyRead(
+                                       Vcb->StreamObj, 
+                                       (PLARGE_INTEGER)(&(ffs_bdl[i].Lba)), 
+                                       ffs_bdl[i].Length,
+                                       PIN_WAIT,
+                                       (PVOID)((PUCHAR)Buffer + ffs_bdl[i].Offset), 
+                                       &IoStatus);
+
+                       Status = IoStatus.Status;
+               }
+       }
+
+errorout:
+
+       if (ffs_bdl)
+               ExFreePool(ffs_bdl);
+
+       if (NT_SUCCESS(Status))
+       {
+               if (dwRet) *dwRet = size;
+       }
+
+       return Status;
+}
+
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSReadFile(
+       IN PFFS_IRP_CONTEXT IrpContext)
+{
+       NTSTATUS            Status = STATUS_UNSUCCESSFUL;
+
+       PFFS_VCB            Vcb;
+       PFFS_FCB            Fcb = 0;
+       PFFS_CCB            Ccb;
+       PFILE_OBJECT        FileObject;
+       PFILE_OBJECT        CacheObject;
+
+       PDEVICE_OBJECT      DeviceObject;
+
+       PIRP                Irp;
+       PIO_STACK_LOCATION  IoStackLocation;
+
+       ULONG               Length;
+       ULONG               ReturnedLength;
+       LARGE_INTEGER       ByteOffset;
+
+       BOOLEAN             PagingIo;
+       BOOLEAN             Nocache;
+       BOOLEAN             SynchronousIo;
+       BOOLEAN             MainResourceAcquired = FALSE;
+       BOOLEAN             PagingIoResourceAcquired = FALSE;
+
+       PUCHAR              Buffer;
+
+    PAGED_CODE();
+
+       _SEH2_TRY
+       {
+               ASSERT(IrpContext);
+
+               ASSERT((IrpContext->Identifier.Type == FFSICX) &&
+                               (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
+
+               DeviceObject = IrpContext->DeviceObject;
+
+               Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;
+
+               ASSERT(Vcb != NULL);
+
+               ASSERT((Vcb->Identifier.Type == FFSVCB) &&
+                               (Vcb->Identifier.Size == sizeof(FFS_VCB)));
+
+               FileObject = IrpContext->FileObject;
+
+               Fcb = (PFFS_FCB)FileObject->FsContext;
+
+               ASSERT(Fcb);
+
+               ASSERT((Fcb->Identifier.Type == FFSFCB) &&
+                               (Fcb->Identifier.Size == sizeof(FFS_FCB)));
+
+               Ccb = (PFFS_CCB)FileObject->FsContext2;
+
+               Irp = IrpContext->Irp;
+
+               IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
+
+               Length = IoStackLocation->Parameters.Read.Length;
+               ByteOffset = IoStackLocation->Parameters.Read.ByteOffset;
+
+               PagingIo = (Irp->Flags & IRP_PAGING_IO ? TRUE : FALSE);
+               Nocache = (Irp->Flags & IRP_NOCACHE ? TRUE : FALSE);
+               SynchronousIo = (FileObject->Flags & FO_SYNCHRONOUS_IO ? TRUE : FALSE);
+
+#if 0
+/*
+               if (IsFlagOn(Fcb->Flags, FCB_FILE_DELETED))
+               {
+                       Status = STATUS_FILE_DELETED;
+                       _SEH2_LEAVE;
+               }
+
+               if (IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING))
+               {
+                       Status = STATUS_DELETE_PENDING;
+                       _SEH2_LEAVE;
+               }
+*/
+#endif
+
+               if (Length == 0)
+               {
+                       Irp->IoStatus.Information = 0;
+                       Status = STATUS_SUCCESS;
+                       _SEH2_LEAVE;
+               }
+
+               if (Nocache &&
+                               (ByteOffset.LowPart & (SECTOR_SIZE - 1) ||
+                                Length & (SECTOR_SIZE - 1)))
+               {
+                       Status = STATUS_INVALID_PARAMETER;
+                       FFSBreakPoint();
+                       _SEH2_LEAVE;
+               }
+
+               if (FlagOn(IrpContext->MinorFunction, IRP_MN_DPC))
+               {
+                       ClearFlag(IrpContext->MinorFunction, IRP_MN_DPC);
+                       Status = STATUS_PENDING;
+                       FFSBreakPoint();
+                       _SEH2_LEAVE;
+               }
+
+               if (!PagingIo)
+               {
+                       if (!ExAcquireResourceSharedLite(
+                                               &Fcb->MainResource,
+                                               IrpContext->IsSynchronous))
+                       {
+                               Status = STATUS_PENDING;
+                               _SEH2_LEAVE;
+                       }
+
+                       MainResourceAcquired = TRUE;
+
+                       if (!FsRtlCheckLockForReadAccess(
+                                               &Fcb->FileLockAnchor,
+                                               Irp))
+                       {
+                               Status = STATUS_FILE_LOCK_CONFLICT;
+                               _SEH2_LEAVE;
+                       }
+               }
+               else
+               {
+                       if (!ExAcquireResourceSharedLite(
+                                               &Fcb->PagingIoResource,
+                                               IrpContext->IsSynchronous))
+                       {
+                               Status = STATUS_PENDING;
+                               _SEH2_LEAVE;
+                       }
+
+                       PagingIoResourceAcquired = TRUE;
+               }
+
+               if (!Nocache)
+               {
+                       if ((ByteOffset.QuadPart + (LONGLONG)Length) >
+                                       Fcb->Header.FileSize.QuadPart)
+                       {
+                               if (ByteOffset.QuadPart >= (Fcb->Header.FileSize.QuadPart))
+                               {
+                                       Irp->IoStatus.Information = 0;
+                                       Status = STATUS_END_OF_FILE;
+                                       _SEH2_LEAVE;
+                               }
+
+                               Length =
+                                       (ULONG)(Fcb->Header.FileSize.QuadPart - ByteOffset.QuadPart);
+
+                       }
+
+                       ReturnedLength = Length;
+
+                       if (IsDirectory(Fcb))
+                       {
+                               _SEH2_LEAVE;
+                       }
+
+                       {
+                               if (FileObject->PrivateCacheMap == NULL)
+                               {
+                                       CcInitializeCacheMap(
+                                                       FileObject,
+                                                       (PCC_FILE_SIZES)(&Fcb->Header.AllocationSize),
+                                                       FALSE,
+                                                       &FFSGlobal->CacheManagerCallbacks,
+                                                       Fcb);
+                               }
+
+                               CacheObject = FileObject;
+                       }
+
+                       if (FlagOn(IrpContext->MinorFunction, IRP_MN_MDL))
+                       {
+                               CcMdlRead(
+                                               CacheObject,
+                                               (&ByteOffset),
+                                               Length,
+                                               &Irp->MdlAddress,
+                                               &Irp->IoStatus);
+
+                               Status = Irp->IoStatus.Status;
+                       }
+                       else
+                       {
+                               Buffer = FFSGetUserBuffer(Irp);
+
+                               if (Buffer == NULL)
+                               {
+                                       Status = STATUS_INVALID_USER_BUFFER;
+                                       FFSBreakPoint();
+                                       _SEH2_LEAVE;
+                               }
+
+                               if (!CcCopyRead(
+                                                       CacheObject,
+                                                       (PLARGE_INTEGER)&ByteOffset,
+                                                       Length,
+                                                       IrpContext->IsSynchronous,
+                                                       Buffer,
+                                                       &Irp->IoStatus))
+                               {
+                                       Status = STATUS_PENDING;
+                                       FFSBreakPoint();
+                                       _SEH2_LEAVE;
+                               }
+
+                               Status = Irp->IoStatus.Status;
+                       }
+               }
+               else
+               {
+                       /* ByteOffset°ú AllocationSize ¸ðµÎ 0ÀÌ ¾Æ´Ò¶§ */
+                       if (ByteOffset.QuadPart && Fcb->Header.AllocationSize.QuadPart)
+                       {
+                               if ((ByteOffset.QuadPart + (LONGLONG)Length) > Fcb->Header.AllocationSize.QuadPart)
+                               {
+
+                                       if (ByteOffset.QuadPart >= Fcb->Header.AllocationSize.QuadPart)
+                                       {
+                                               Irp->IoStatus.Information = 0;
+                                               Status = STATUS_END_OF_FILE;
+                                               FFSBreakPoint();
+                                               _SEH2_LEAVE;
+                                       }
+
+                                       Length =
+                                               (ULONG)(Fcb->Header.AllocationSize.QuadPart- ByteOffset.QuadPart);
+                               }
+                       }
+
+                       ReturnedLength = Length;
+
+                       Status = FFSLockUserBuffer(
+                                       IrpContext->Irp,
+                                       Length,
+                                       IoWriteAccess);
+
+                       if (!NT_SUCCESS(Status))
+                       {
+                               _SEH2_LEAVE;
+                       }
+
+                       Irp->IoStatus.Status = STATUS_SUCCESS;
+                       Irp->IoStatus.Information = Length;
+
+                       if (FS_VERSION == 1)
+                       {
+                               Status = 
+                                       FFSv1ReadInode(
+                                                       IrpContext,
+                                                       Vcb,
+                                                       Fcb->dinode1,
+                                                       ByteOffset.QuadPart,
+                                                       NULL,
+                                                       Length,
+                                                       &ReturnedLength);
+                       }
+                       else
+                       {
+                               Status = 
+                                       FFSv2ReadInode(
+                                                       IrpContext,
+                                                       Vcb,
+                                                       Fcb->dinode2,
+                                                       ByteOffset.QuadPart,
+                                                       NULL,
+                                                       Length,
+                                                       &ReturnedLength);
+                       }
+
+                       Irp = IrpContext->Irp;
+
+               }
+       }
+
+       _SEH2_FINALLY
+       {
+               if (PagingIoResourceAcquired)
+               {
+                       ExReleaseResourceForThreadLite(
+                                       &Fcb->PagingIoResource,
+                                       ExGetCurrentResourceThread());
+               }
+
+               if (MainResourceAcquired)
+               {
+                       ExReleaseResourceForThreadLite(
+                                       &Fcb->MainResource,
+                                       ExGetCurrentResourceThread());
+               }
+
+               if (!IrpContext->ExceptionInProgress)
+               {
+                       if (IrpContext->Irp)
+                       {
+                               if (Status == STATUS_PENDING)
+                               {
+                                       Status = FFSLockUserBuffer(
+                                                       IrpContext->Irp,
+                                                       Length,
+                                                       IoWriteAccess);
+
+                                       if (NT_SUCCESS(Status))
+                                       {
+                                               Status = FFSQueueRequest(IrpContext);
+                                       }
+                                       else
+                                       {
+                                               FFSCompleteIrpContext(IrpContext, Status);
+                                       }
+                               }
+                               else
+                               {
+                                       if (NT_SUCCESS(Status))
+                                       {
+                                               if (SynchronousIo && !PagingIo)
+                                               {
+                                                       IrpContext->FileObject->CurrentByteOffset.QuadPart =
+                                                               ByteOffset.QuadPart + IrpContext->Irp->IoStatus.Information;
+                                               }
+
+                                               if (!PagingIo)
+                                               {
+                                                       IrpContext->FileObject->Flags &= ~FO_FILE_FAST_IO_READ;
+                                               }
+                                       }
+
+                                       FFSCompleteIrpContext(IrpContext, Status);
+                               }
+                       }
+                       else
+                       {
+                               FFSFreeIrpContext(IrpContext);
+                       }
+               }
+       } _SEH2_END;
+
+       return Status;
+
+}
+
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSReadComplete(
+       IN PFFS_IRP_CONTEXT IrpContext)
+{
+       NTSTATUS        Status = STATUS_UNSUCCESSFUL;
+       PFILE_OBJECT    FileObject;
+       PIRP            Irp;
+
+    PAGED_CODE();
+
+       _SEH2_TRY
+       {
+               ASSERT(IrpContext);
+
+               ASSERT((IrpContext->Identifier.Type == FFSICX) &&
+                               (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
+
+               FileObject = IrpContext->FileObject;
+
+               Irp = IrpContext->Irp;
+
+               CcMdlReadComplete(FileObject, Irp->MdlAddress);
+
+               Irp->MdlAddress = NULL;
+
+               Status = STATUS_SUCCESS;
+       }
+
+       _SEH2_FINALLY
+       {
+               if (!IrpContext->ExceptionInProgress)
+               {
+                       FFSCompleteIrpContext(IrpContext, Status);
+               }
+       } _SEH2_END;
+
+       return Status;
+}
+
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSRead(
+       IN PFFS_IRP_CONTEXT IrpContext)
+{
+       NTSTATUS            Status;
+       PFFS_VCB            Vcb;
+       PFFS_FCBVCB         FcbOrVcb;
+       PDEVICE_OBJECT      DeviceObject;
+       PFILE_OBJECT        FileObject;
+       BOOLEAN             bCompleteRequest;
+
+    PAGED_CODE();
+
+       ASSERT(IrpContext);
+
+       ASSERT((IrpContext->Identifier.Type == FFSICX) &&
+                       (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
+       _SEH2_TRY
+       {
+
+               if (FlagOn(IrpContext->MinorFunction, IRP_MN_COMPLETE))
+               {
+                       Status = FFSReadComplete(IrpContext);
+                       bCompleteRequest = FALSE;
+               }
+               else
+               {
+                       DeviceObject = IrpContext->DeviceObject;
+
+                       if (DeviceObject == FFSGlobal->DeviceObject)
+                       {
+                               Status = STATUS_INVALID_DEVICE_REQUEST;
+                               bCompleteRequest = TRUE;
+                               _SEH2_LEAVE;
+                       }
+
+                       Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;
+
+                       if (Vcb->Identifier.Type != FFSVCB ||
+                                       Vcb->Identifier.Size != sizeof(FFS_VCB))
+                       {
+                               Status = STATUS_INVALID_DEVICE_REQUEST;
+                               bCompleteRequest = TRUE;
+
+                               _SEH2_LEAVE;
+                       }
+
+                       if (IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING))
+                       {
+                               Status = STATUS_TOO_LATE;
+                               bCompleteRequest = TRUE;
+                               _SEH2_LEAVE;
+                       }
+
+                       FileObject = IrpContext->FileObject;
+
+                       FcbOrVcb = (PFFS_FCBVCB)FileObject->FsContext;
+
+                       if (FcbOrVcb->Identifier.Type == FFSVCB)
+                       {
+                               Status = FFSReadVolume(IrpContext);
+                               bCompleteRequest = FALSE;
+                       }
+                       else if (FcbOrVcb->Identifier.Type == FFSFCB)
+                       {
+                               Status = FFSReadFile(IrpContext);
+                               bCompleteRequest = FALSE;
+                       }
+                       else
+                       {
+                               FFSPrint((DBG_ERROR, "FFSRead: INVALID PARAMETER ... \n"));
+                               FFSBreakPoint();
+
+                               Status = STATUS_INVALID_PARAMETER;
+                               bCompleteRequest = TRUE;
+                       }
+               }
+       }
+
+       _SEH2_FINALLY
+       {
+               if (bCompleteRequest)
+               {
+                       FFSCompleteIrpContext(IrpContext, Status);
+               }
+       } _SEH2_END;
+
+       return Status;
+}
diff --git a/reactos/drivers/filesystems/ffs/src/shutdown.c b/reactos/drivers/filesystems/ffs/src/shutdown.c
new file mode 100644 (file)
index 0000000..67062da
--- /dev/null
@@ -0,0 +1,136 @@
+/* 
+ * FFS File System Driver for Windows
+ *
+ * read.c
+ *
+ * 2004.5.6 ~
+ *
+ * Lee Jae-Hong, http://www.pyrasis.com
+ *
+ * See License.txt
+ *
+ */
+
+#include "ntifs.h"
+#include "ffsdrv.h"
+
+/* Globals */
+
+extern PFFS_GLOBAL FFSGlobal;
+
+
+/* Definitions */
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE, FFSShutDown)
+#endif
+
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSShutDown(
+       IN PFFS_IRP_CONTEXT IrpContext)
+{
+       NTSTATUS                Status;
+
+       PKEVENT                 Event;
+
+       PIRP                    Irp;
+       PIO_STACK_LOCATION      IrpSp;
+
+       PFFS_VCB                Vcb;
+       PLIST_ENTRY             ListEntry;
+
+       BOOLEAN                 GlobalResourceAcquired = FALSE;
+
+    PAGED_CODE();
+
+       _SEH2_TRY
+       {
+               ASSERT(IrpContext);
+
+               ASSERT((IrpContext->Identifier.Type == FFSICX) &&
+                               (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
+
+               Status = STATUS_SUCCESS;
+
+               Irp = IrpContext->Irp;
+
+               IrpSp = IoGetCurrentIrpStackLocation(Irp);
+#ifdef _MSC_VER
+#pragma prefast( suppress: 28137, "by design" )
+#endif
+               if (!ExAcquireResourceExclusiveLite(
+                                       &FFSGlobal->Resource,
+                                       IrpContext->IsSynchronous))
+               {
+                       Status = STATUS_PENDING;
+                       _SEH2_LEAVE;
+               }
+
+               GlobalResourceAcquired = TRUE;
+
+               Event = ExAllocatePoolWithTag(NonPagedPool, sizeof(KEVENT), FFS_POOL_TAG);
+               KeInitializeEvent(Event, NotificationEvent, FALSE);
+
+               for (ListEntry = FFSGlobal->VcbList.Flink;
+                               ListEntry != &(FFSGlobal->VcbList);
+                               ListEntry = ListEntry->Flink)
+               {
+                       Vcb = CONTAINING_RECORD(ListEntry, FFS_VCB, Next);
+
+                       if (ExAcquireResourceExclusiveLite(
+                                               &Vcb->MainResource,
+                                               TRUE))
+                       {
+
+                               Status = FFSFlushFiles(Vcb, TRUE);
+                               if(!NT_SUCCESS(Status))
+                               {
+                                       FFSBreakPoint();
+                               }
+
+                               Status = FFSFlushVolume(Vcb, TRUE);
+
+                               if(!NT_SUCCESS(Status))
+                               {
+                                       FFSBreakPoint();
+                               }
+
+                               FFSDiskShutDown(Vcb);
+
+                               ExReleaseResourceForThreadLite(
+                                               &Vcb->MainResource,
+                                               ExGetCurrentResourceThread());
+                       }
+               }
+
+               /*
+               IoUnregisterFileSystem(FFSGlobal->DeviceObject);
+               */
+       }
+
+       _SEH2_FINALLY
+       {
+               if (GlobalResourceAcquired)
+               {
+                       ExReleaseResourceForThreadLite(
+                                       &FFSGlobal->Resource,
+                                       ExGetCurrentResourceThread());
+               }
+
+               if (!IrpContext->ExceptionInProgress)
+               {
+                       if (Status == STATUS_PENDING)
+                       {
+                               FFSQueueRequest(IrpContext);
+                       }
+                       else
+                       {
+                               FFSCompleteIrpContext(IrpContext, Status);
+                       }
+               }
+       } _SEH2_END;
+
+       return Status;
+}
diff --git a/reactos/drivers/filesystems/ffs/src/volinfo.c b/reactos/drivers/filesystems/ffs/src/volinfo.c
new file mode 100644 (file)
index 0000000..680a30e
--- /dev/null
@@ -0,0 +1,478 @@
+/* 
+ * FFS File System Driver for Windows
+ *
+ * volinfo.c
+ *
+ * 2004.5.6 ~
+ *
+ * Lee Jae-Hong, http://www.pyrasis.com
+ *
+ * See License.txt
+ *
+ */
+
+#include "ntifs.h"
+#include "ffsdrv.h"
+
+/* Globals */
+
+extern PFFS_GLOBAL FFSGlobal;
+
+
+/* Definitions */
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE, FFSQueryVolumeInformation)
+#pragma alloc_text(PAGE, FFSSetVolumeInformation)
+#endif
+
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSQueryVolumeInformation(
+       IN PFFS_IRP_CONTEXT IrpContext)
+{
+       PDEVICE_OBJECT          DeviceObject;
+       NTSTATUS                Status = STATUS_UNSUCCESSFUL;
+       PFFS_VCB                Vcb = 0;
+       PIRP                    Irp;
+       PIO_STACK_LOCATION      IoStackLocation;
+       FS_INFORMATION_CLASS    FsInformationClass;
+       ULONG                   Length;
+       PVOID                   Buffer;
+       BOOLEAN                 VcbResourceAcquired = FALSE;
+
+    PAGED_CODE();
+
+       _SEH2_TRY
+       {
+               ASSERT(IrpContext != NULL);
+
+               ASSERT((IrpContext->Identifier.Type == FFSICX) &&
+                               (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
+
+               DeviceObject = IrpContext->DeviceObject;
+
+               //
+               // This request is not allowed on the main device object
+               //
+               if (DeviceObject == FFSGlobal->DeviceObject)
+               {
+                       Status = STATUS_INVALID_DEVICE_REQUEST;
+                       _SEH2_LEAVE;
+               }
+
+               Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;
+
+               ASSERT(Vcb != NULL);
+
+               ASSERT((Vcb->Identifier.Type == FFSVCB) &&
+                               (Vcb->Identifier.Size == sizeof(FFS_VCB)));
+
+               ASSERT(IsMounted(Vcb));
+
+               if (!ExAcquireResourceSharedLite(
+                                       &Vcb->MainResource,
+                                       IrpContext->IsSynchronous))
+               {
+                       Status = STATUS_PENDING;
+                       _SEH2_LEAVE;
+               }
+
+               VcbResourceAcquired = TRUE;
+
+               Irp = IrpContext->Irp;
+
+               IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
+
+               FsInformationClass =
+                       IoStackLocation->Parameters.QueryVolume.FsInformationClass;
+
+               Length = IoStackLocation->Parameters.QueryVolume.Length;
+
+               Buffer = Irp->AssociatedIrp.SystemBuffer;
+
+               RtlZeroMemory(Buffer, Length);
+
+               switch (FsInformationClass)
+               {
+                       case FileFsVolumeInformation:
+                               {
+                                       PFILE_FS_VOLUME_INFORMATION FsVolInfo;
+                                       ULONG                       VolumeLabelLength;
+                                       ULONG                       RequiredLength;
+
+                                       if (Length < sizeof(FILE_FS_VOLUME_INFORMATION))
+                                       {
+                                               Status = STATUS_INFO_LENGTH_MISMATCH;
+                                               _SEH2_LEAVE;
+                                       }
+
+                                       FsVolInfo = (PFILE_FS_VOLUME_INFORMATION)Buffer;
+
+                                       FsVolInfo->VolumeCreationTime.QuadPart = 0;
+
+                                       FsVolInfo->VolumeSerialNumber = Vcb->Vpb->SerialNumber;
+
+                                       VolumeLabelLength = Vcb->Vpb->VolumeLabelLength;
+
+                                       FsVolInfo->VolumeLabelLength = VolumeLabelLength;
+
+                                       // I don't know what this means
+                                       FsVolInfo->SupportsObjects = FALSE;
+
+                                       RequiredLength = sizeof(FILE_FS_VOLUME_INFORMATION)
+                                               + VolumeLabelLength - sizeof(WCHAR);
+
+                                       if (Length < RequiredLength)
+                                       {
+                                               Irp->IoStatus.Information =
+                                                       sizeof(FILE_FS_VOLUME_INFORMATION);
+                                               Status = STATUS_BUFFER_OVERFLOW;
+                                               _SEH2_LEAVE;
+                                       }
+
+                                       RtlCopyMemory(FsVolInfo->VolumeLabel, Vcb->Vpb->VolumeLabel, Vcb->Vpb->VolumeLabelLength);
+
+                                       Irp->IoStatus.Information = RequiredLength;
+                                       Status = STATUS_SUCCESS;
+                                       _SEH2_LEAVE;
+                               }
+
+                       case FileFsSizeInformation:
+                               {
+                                       PFILE_FS_SIZE_INFORMATION FsSizeInfo;
+
+                                       if (Length < sizeof(FILE_FS_SIZE_INFORMATION))
+                                       {
+                                               Status = STATUS_INFO_LENGTH_MISMATCH;
+                                               _SEH2_LEAVE;
+                                       }
+
+                                       FsSizeInfo = (PFILE_FS_SIZE_INFORMATION)Buffer;
+
+                                       {
+                                               if (FS_VERSION == 1)
+                                               {
+                                                       FsSizeInfo->TotalAllocationUnits.QuadPart =
+                                                               (Vcb->ffs_super_block->fs_old_size / 8);
+
+                                                       FsSizeInfo->AvailableAllocationUnits.QuadPart =
+                                                               (Vcb->ffs_super_block->fs_old_cstotal.cs_nbfree / 8);
+                                               }
+                                               else
+                                               {
+                                                       FsSizeInfo->TotalAllocationUnits.QuadPart =
+                                                               (Vcb->ffs_super_block->fs_size / 8);
+
+                                                       FsSizeInfo->AvailableAllocationUnits.QuadPart =
+                                                               (Vcb->ffs_super_block->fs_cstotal.cs_nbfree / 8);
+                                               }
+                                       }
+
+                                       FsSizeInfo->SectorsPerAllocationUnit =
+                                               Vcb->BlockSize / Vcb->DiskGeometry.BytesPerSector;
+
+                                       FsSizeInfo->BytesPerSector =
+                                               Vcb->DiskGeometry.BytesPerSector;
+
+                                       Irp->IoStatus.Information = sizeof(FILE_FS_SIZE_INFORMATION);
+                                       Status = STATUS_SUCCESS;
+                                       _SEH2_LEAVE;
+                               }
+
+                       case FileFsDeviceInformation:
+                               {
+                                       PFILE_FS_DEVICE_INFORMATION FsDevInfo;
+
+                                       if (Length < sizeof(FILE_FS_DEVICE_INFORMATION))
+                                       {
+                                               Status = STATUS_INFO_LENGTH_MISMATCH;
+                                               _SEH2_LEAVE;
+                                       }
+
+                                       FsDevInfo = (PFILE_FS_DEVICE_INFORMATION)Buffer;
+
+                                       FsDevInfo->DeviceType =
+                                               Vcb->TargetDeviceObject->DeviceType;
+
+                                       FsDevInfo->Characteristics =
+                                               Vcb->TargetDeviceObject->Characteristics;
+
+                                       if (FlagOn(Vcb->Flags, VCB_READ_ONLY))
+                                       {
+                                               SetFlag(FsDevInfo->Characteristics,
+                                                               FILE_READ_ONLY_DEVICE);
+                                       }
+
+                                       Irp->IoStatus.Information = sizeof(FILE_FS_DEVICE_INFORMATION);
+                                       Status = STATUS_SUCCESS;
+                                       _SEH2_LEAVE;
+                               }
+
+                       case FileFsAttributeInformation:
+                               {
+                                       PFILE_FS_ATTRIBUTE_INFORMATION  FsAttrInfo;
+                                       ULONG                           RequiredLength;
+
+                                       if (Length < sizeof(FILE_FS_ATTRIBUTE_INFORMATION))
+                                       {
+                                               Status = STATUS_INFO_LENGTH_MISMATCH;
+                                               _SEH2_LEAVE;
+                                       }
+
+                                       FsAttrInfo =
+                                               (PFILE_FS_ATTRIBUTE_INFORMATION)Buffer;
+
+                                       FsAttrInfo->FileSystemAttributes =
+                                               FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
+
+                                       FsAttrInfo->MaximumComponentNameLength = FFS_NAME_LEN;
+
+                                       FsAttrInfo->FileSystemNameLength = 10;
+
+                                       RequiredLength = sizeof(FILE_FS_ATTRIBUTE_INFORMATION) +
+                                               10 - sizeof(WCHAR);
+
+                                       if (Length < RequiredLength)
+                                       {
+                                               Irp->IoStatus.Information =
+                                                       sizeof(FILE_FS_ATTRIBUTE_INFORMATION);
+                                               Status = STATUS_BUFFER_OVERFLOW;
+                                               _SEH2_LEAVE;
+                                       }
+
+                                       RtlCopyMemory(
+                                                       FsAttrInfo->FileSystemName,
+                                                       L"FFS\0", 8);
+
+                                       Irp->IoStatus.Information = RequiredLength;
+                                       Status = STATUS_SUCCESS;
+                                       _SEH2_LEAVE;
+                               }
+
+#if (_WIN32_WINNT >= 0x0500)
+
+                       case FileFsFullSizeInformation:
+                               {
+                                       PFILE_FS_FULL_SIZE_INFORMATION PFFFSI;
+
+                                       if (Length < sizeof(FILE_FS_FULL_SIZE_INFORMATION))
+                                       {
+                                               Status = STATUS_INFO_LENGTH_MISMATCH;
+                                               _SEH2_LEAVE;
+                                       }
+
+                                       PFFFSI = (PFILE_FS_FULL_SIZE_INFORMATION)Buffer;
+
+                                       /*
+                                       typedef struct _FILE_FS_FULL_SIZE_INFORMATION {
+                                               LARGE_INTEGER   TotalAllocationUnits;
+                                               LARGE_INTEGER   CallerAvailableAllocationUnits;
+                                               LARGE_INTEGER   ActualAvailableAllocationUnits;
+                                               ULONG           SectorsPerAllocationUnit;
+                                               ULONG           BytesPerSector;
+                                       } FILE_FS_FULL_SIZE_INFORMATION, *PFILE_FS_FULL_SIZE_INFORMATION;
+                                       */
+
+                                       {
+                                               if (FS_VERSION == 1)
+                                               {
+                                                       PFFFSI->TotalAllocationUnits.QuadPart =
+                                                               (Vcb->ffs_super_block->fs_old_size / 8);
+
+                                                       PFFFSI->CallerAvailableAllocationUnits.QuadPart =
+                                                               (Vcb->ffs_super_block->fs_old_cstotal.cs_nbfree / 8);
+
+                                                       PFFFSI->ActualAvailableAllocationUnits.QuadPart =
+                                                               (Vcb->ffs_super_block->fs_old_cstotal.cs_nbfree / 8);
+                                               }
+                                               else
+                                               {
+                                                       PFFFSI->TotalAllocationUnits.QuadPart =
+                                                               (Vcb->ffs_super_block->fs_size / 8);
+
+                                                       PFFFSI->CallerAvailableAllocationUnits.QuadPart =
+                                                               (Vcb->ffs_super_block->fs_cstotal.cs_nbfree / 8);
+
+                                                       PFFFSI->ActualAvailableAllocationUnits.QuadPart =
+                                                               (Vcb->ffs_super_block->fs_cstotal.cs_nbfree / 8);
+                                               }
+                                       }
+
+                                       PFFFSI->SectorsPerAllocationUnit =
+                                               Vcb->BlockSize / Vcb->DiskGeometry.BytesPerSector;
+
+                                       PFFFSI->BytesPerSector = Vcb->DiskGeometry.BytesPerSector;
+
+                                       Irp->IoStatus.Information = sizeof(FILE_FS_FULL_SIZE_INFORMATION);
+                                       Status = STATUS_SUCCESS;
+                                       _SEH2_LEAVE;
+                               }
+
+#endif // (_WIN32_WINNT >= 0x0500)
+
+                       default:
+                               Status = STATUS_INVALID_INFO_CLASS;
+               }
+       }
+
+       _SEH2_FINALLY
+       {
+               if (VcbResourceAcquired)
+               {
+                       ExReleaseResourceForThreadLite(
+                                       &Vcb->MainResource,
+                                       ExGetCurrentResourceThread());
+               }
+
+               if (!IrpContext->ExceptionInProgress)
+               {
+                       if (Status == STATUS_PENDING)
+                       {
+                               FFSQueueRequest(IrpContext);
+                       }
+                       else
+                       {
+                               FFSCompleteIrpContext(IrpContext, Status);
+                       }
+               }
+       } _SEH2_END;
+
+       return Status;
+}
+
+#if !FFS_READ_ONLY
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSSetVolumeInformation(
+       IN PFFS_IRP_CONTEXT IrpContext)
+{
+       PDEVICE_OBJECT          DeviceObject;
+       NTSTATUS                Status = STATUS_UNSUCCESSFUL;
+       PFFS_VCB                Vcb;
+       PIRP                    Irp;
+       PIO_STACK_LOCATION      IoStackLocation;
+       FS_INFORMATION_CLASS    FsInformationClass;
+
+    PAGED_CODE();
+
+       _SEH2_TRY
+       {
+               ASSERT(IrpContext != NULL);
+
+               ASSERT((IrpContext->Identifier.Type == FFSICX) &&
+                               (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
+
+               DeviceObject = IrpContext->DeviceObject;
+
+               //
+               // This request is not allowed on the main device object
+               //
+               if (DeviceObject == FFSGlobal->DeviceObject)
+               {
+                       Status = STATUS_INVALID_DEVICE_REQUEST;
+                       _SEH2_LEAVE;
+               }
+
+               Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;
+
+               ASSERT(Vcb != NULL);
+
+               ASSERT((Vcb->Identifier.Type == FFSVCB) &&
+                               (Vcb->Identifier.Size == sizeof(FFS_VCB)));
+
+               ASSERT(IsMounted(Vcb));
+
+               if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY))
+               {
+                       Status = STATUS_MEDIA_WRITE_PROTECTED;
+                       _SEH2_LEAVE;
+               }
+
+               Irp = IrpContext->Irp;
+
+               IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
+
+               //Notes: SetVolume is not defined in ntddk.h of win2k ddk,
+               //       But it's same to QueryVolume ....
+               FsInformationClass =
+                       IoStackLocation->Parameters./*SetVolume*/QueryVolume.FsInformationClass;
+
+               switch (FsInformationClass)
+               {
+                       case FileFsLabelInformation:
+                               {
+                                       PFILE_FS_LABEL_INFORMATION      VolLabelInfo = NULL;
+                                       ULONG                           VolLabelLen;
+                                       UNICODE_STRING                  LabelName  ;
+
+                                       OEM_STRING                      OemName;
+
+                                       VolLabelInfo = (PFILE_FS_LABEL_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
+
+                                       VolLabelLen = VolLabelInfo->VolumeLabelLength;
+
+                                       if(VolLabelLen > (16 * sizeof(WCHAR)))
+                                       {
+                                               Status = STATUS_INVALID_VOLUME_LABEL;
+                                               _SEH2_LEAVE;
+                                       }
+
+                                       RtlCopyMemory(Vcb->Vpb->VolumeLabel,
+                                                       VolLabelInfo->VolumeLabel,
+                                                       VolLabelLen);
+
+                                       RtlZeroMemory(Vcb->ffs_super_block->fs_volname, 16);
+
+                                       LabelName.Buffer = VolLabelInfo->VolumeLabel;
+                                       LabelName.MaximumLength = (USHORT)16 * sizeof(WCHAR);
+                                       LabelName.Length = (USHORT)VolLabelLen;
+
+                                       OemName.Buffer = SUPER_BLOCK->fs_volname;
+                                       OemName.Length  = 0;
+                                       OemName.MaximumLength = 16;
+
+                                       FFSUnicodeToOEM(&OemName,
+                                                       &LabelName);
+
+                                       Vcb->Vpb->VolumeLabelLength = 
+                                               (USHORT)VolLabelLen;
+
+                                       if (FFSSaveSuper(IrpContext, Vcb))
+                                       {
+                                               Status = STATUS_SUCCESS;
+                                       }
+
+                                       Irp->IoStatus.Information = 0;
+
+                               }
+                               break;
+
+                       default:
+                               Status = STATUS_INVALID_INFO_CLASS;
+               }
+       }
+
+       _SEH2_FINALLY
+       {
+
+               if (!IrpContext->ExceptionInProgress)
+               {
+                       if (Status == STATUS_PENDING)
+                       {
+                               FFSQueueRequest(IrpContext);
+                       }
+                       else
+                       {
+                               FFSCompleteIrpContext(IrpContext, Status);
+                       }
+               }
+       } _SEH2_END;
+
+       return Status;
+
+}
+
+#endif // !FFS_READ_ONLY
diff --git a/reactos/drivers/filesystems/ffs/src/write.c b/reactos/drivers/filesystems/ffs/src/write.c
new file mode 100644 (file)
index 0000000..24e04b7
--- /dev/null
@@ -0,0 +1,1588 @@
+/* 
+ * FFS File System Driver for Windows
+ *
+ * write.c
+ *
+ * 2004.5.6 ~
+ *
+ * Lee Jae-Hong, http://www.pyrasis.com
+ *
+ * See License.txt
+ *
+ */
+
+#include "ntifs.h"
+#include "ffsdrv.h"
+
+#if !FFS_READ_ONLY
+
+/* Globals */
+
+extern PFFS_GLOBAL FFSGlobal;
+
+
+/* Definitions */
+
+typedef struct _FFS_FLPFLUSH_CONTEXT {
+
+       PFFS_VCB     Vcb;
+       PFFS_FCB     Fcb;
+       PFILE_OBJECT FileObject;
+
+       KDPC         Dpc;
+       KTIMER       Timer;
+       WORK_QUEUE_ITEM Item;
+
+} FFS_FLPFLUSH_CONTEXT, *PFFS_FLPFLUSH_CONTEXT;
+
+#ifdef _PREFAST_
+WORKER_THREAD_ROUTINE __drv_mustHoldCriticalRegion FFSFloppyFlush;
+#endif // _PREFAST_
+
+__drv_mustHoldCriticalRegion
+VOID
+FFSFloppyFlush(
+       IN PVOID Parameter);
+
+#ifdef _PREFAST_
+KDEFERRED_ROUTINE FFSFloppyFlushDpc;
+#endif // _PREFAST_
+
+VOID
+FFSFloppyFlushDpc(
+       IN PKDPC Dpc,
+       IN PVOID DeferredContext,
+       IN PVOID SystemArgument1,
+       IN PVOID SystemArgument2);
+
+
+
+NTSTATUS
+FFSWriteComplete(
+       IN PFFS_IRP_CONTEXT IrpContext);
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSWriteFile(
+       IN PFFS_IRP_CONTEXT IrpContext);
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSWriteVolume(
+       IN PFFS_IRP_CONTEXT IrpContext);
+
+VOID
+FFSDeferWrite(
+       IN   PFFS_IRP_CONTEXT,
+       PIRP Irp);
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE, FFSFloppyFlush)
+#pragma alloc_text(PAGE, FFSStartFloppyFlushDpc)
+#pragma alloc_text(PAGE, FFSZeroHoles)
+#pragma alloc_text(PAGE, FFSWrite)
+#pragma alloc_text(PAGE, FFSWriteVolume)
+#pragma alloc_text(PAGE, FFSv1WriteInode)
+#pragma alloc_text(PAGE, FFSWriteFile)
+#pragma alloc_text(PAGE, FFSWriteComplete)
+#endif
+
+
+__drv_mustHoldCriticalRegion
+VOID
+FFSFloppyFlush(
+       IN PVOID Parameter)
+{
+       PFFS_FLPFLUSH_CONTEXT Context;
+       PFILE_OBJECT          FileObject;
+       PFFS_FCB              Fcb;
+       PFFS_VCB              Vcb;
+
+    PAGED_CODE();
+
+       Context = (PFFS_FLPFLUSH_CONTEXT) Parameter;
+       FileObject = Context->FileObject;
+       Fcb = Context->Fcb;
+       Vcb = Context->Vcb;
+
+       FFSPrint((DBG_USER, "FFSFloppyFlushing ...\n"));
+
+       IoSetTopLevelIrp((PIRP)FSRTL_FSP_TOP_LEVEL_IRP);
+
+       if (Vcb)
+       {
+               ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
+               ExReleaseResourceLite(&Vcb->PagingIoResource);
+
+               CcFlushCache(&(Vcb->SectionObject), NULL, 0, NULL);
+       }
+
+       if (FileObject)
+       {
+               ASSERT(Fcb == (PFFS_FCB)FileObject->FsContext);
+
+               ExAcquireSharedStarveExclusive(&Fcb->PagingIoResource, TRUE);
+               ExReleaseResourceLite(&Fcb->PagingIoResource);
+
+               CcFlushCache(&(Fcb->SectionObject), NULL, 0, NULL);
+
+               ObDereferenceObject(FileObject);
+       }
+
+       IoSetTopLevelIrp(NULL);
+
+       ExFreePool(Parameter);
+}
+
+
+VOID
+FFSFloppyFlushDpc(
+       IN PKDPC Dpc,
+       IN PVOID DeferredContext,
+       IN PVOID SystemArgument1,
+       IN PVOID SystemArgument2)
+{
+       PFFS_FLPFLUSH_CONTEXT Context;
+
+       Context = (PFFS_FLPFLUSH_CONTEXT)DeferredContext;
+
+       FFSPrint((DBG_USER, "FFSFloppyFlushDpc is to be started...\n"));
+
+       ExInitializeWorkItem(&Context->Item,
+                       FFSFloppyFlush,
+                       Context);
+
+       ExQueueWorkItem(&Context->Item, CriticalWorkQueue);
+}
+
+
+VOID
+FFSStartFloppyFlushDpc(
+       PFFS_VCB     Vcb,
+       PFFS_FCB     Fcb,
+       PFILE_OBJECT FileObject)
+{
+       LARGE_INTEGER          OneSecond;
+       PFFS_FLPFLUSH_CONTEXT Context;
+
+    PAGED_CODE();
+
+       ASSERT(IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK));
+
+       Context = ExAllocatePoolWithTag(NonPagedPool, sizeof(PFFS_FLPFLUSH_CONTEXT), FFS_POOL_TAG);
+
+       if (!Context)
+       {
+               FFSBreakPoint();
+               return;
+       }
+
+       KeInitializeTimer(&Context->Timer);
+
+       KeInitializeDpc(&Context->Dpc,
+                       FFSFloppyFlushDpc,
+                       Context);
+
+       Context->Vcb = Vcb;
+       Context->Fcb = Fcb;
+       Context->FileObject = FileObject;
+
+       if (FileObject)
+       {
+               ObReferenceObject(FileObject);
+       }
+
+       OneSecond.QuadPart = (LONGLONG) - 1 * 1000 * 1000 * 10;
+       KeSetTimer(&Context->Timer,
+                       OneSecond,
+                       &Context->Dpc);
+}
+
+
+BOOLEAN
+FFSZeroHoles(
+       IN PFFS_IRP_CONTEXT IrpContext,
+       IN PFFS_VCB         Vcb,
+       IN PFILE_OBJECT     FileObject,
+       IN LONGLONG         Offset,
+       IN LONGLONG         Count)
+{
+       LARGE_INTEGER StartAddr = {0, 0};
+       LARGE_INTEGER EndAddr = {0, 0};
+
+    PAGED_CODE();
+
+       StartAddr.QuadPart = (Offset + (SECTOR_SIZE - 1)) &
+               ~((LONGLONG)SECTOR_SIZE - 1);
+
+       EndAddr.QuadPart = (Offset + Count + (SECTOR_SIZE - 1)) &
+               ~((LONGLONG)SECTOR_SIZE - 1);
+
+       if (StartAddr.QuadPart < EndAddr.QuadPart)
+       {
+               return CcZeroData(FileObject,
+                               &StartAddr,
+                               &EndAddr,
+                               IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT));
+       }
+
+       return TRUE;
+}
+
+
+VOID
+FFSDeferWrite(
+       IN PFFS_IRP_CONTEXT IrpContext,
+       PIRP Irp)
+{
+       ASSERT(IrpContext->Irp == Irp);
+
+       FFSQueueRequest(IrpContext);
+}
+
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSWriteVolume(
+       IN PFFS_IRP_CONTEXT IrpContext)
+{
+       NTSTATUS            Status = STATUS_UNSUCCESSFUL;
+
+       PFFS_VCB            Vcb;
+       PFFS_CCB            Ccb;
+       PFFS_FCBVCB         FcbOrVcb;
+       PFILE_OBJECT        FileObject;
+
+       PDEVICE_OBJECT      DeviceObject;
+
+       PIRP                Irp;
+       PIO_STACK_LOCATION  IoStackLocation;
+
+       ULONG               Length;
+       LARGE_INTEGER       ByteOffset;
+
+       BOOLEAN             PagingIo;
+       BOOLEAN             Nocache;
+       BOOLEAN             SynchronousIo;
+       BOOLEAN             MainResourceAcquired = FALSE;
+       BOOLEAN             PagingIoResourceAcquired = FALSE;
+
+       BOOLEAN             bDeferred = FALSE;
+
+       PUCHAR              Buffer;
+
+    PAGED_CODE();
+
+       _SEH2_TRY
+       {
+               ASSERT(IrpContext);
+
+               ASSERT((IrpContext->Identifier.Type == FFSICX) &&
+                               (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
+
+               DeviceObject = IrpContext->DeviceObject;
+
+               Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;
+
+               ASSERT(Vcb != NULL);
+
+               ASSERT((Vcb->Identifier.Type == FFSVCB) &&
+                               (Vcb->Identifier.Size == sizeof(FFS_VCB)));
+
+               FileObject = IrpContext->FileObject;
+
+               FcbOrVcb = (PFFS_FCBVCB)FileObject->FsContext;
+
+               ASSERT(FcbOrVcb);
+
+               if (!(FcbOrVcb->Identifier.Type == FFSVCB && (PVOID)FcbOrVcb == (PVOID)Vcb))
+               {
+                       Status = STATUS_INVALID_DEVICE_REQUEST;
+                       _SEH2_LEAVE;
+               }
+
+               Ccb = (PFFS_CCB)FileObject->FsContext2;
+
+               Irp = IrpContext->Irp;
+
+               IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
+
+               Length = IoStackLocation->Parameters.Write.Length;
+               ByteOffset = IoStackLocation->Parameters.Write.ByteOffset;
+
+               PagingIo = (Irp->Flags & IRP_PAGING_IO ? TRUE : FALSE);
+               Nocache = (Irp->Flags & IRP_NOCACHE ? TRUE : FALSE);
+               SynchronousIo = (FileObject->Flags & FO_SYNCHRONOUS_IO ? TRUE : FALSE);
+
+               FFSPrint((DBG_INFO, "FFSWriteVolume: Off=%I64xh Len=%xh Paging=%xh Nocache=%xh\n",
+                                       ByteOffset.QuadPart, Length, PagingIo, Nocache));
+
+               if (Length == 0)
+               {
+                       Irp->IoStatus.Information = 0;
+                       Status = STATUS_SUCCESS;
+                       _SEH2_LEAVE;
+               }
+
+               // For the case of "Direct Access Storage Device", we
+               // need flush/purge the cache
+
+               if (Ccb != NULL)
+               {
+                       ExAcquireResourceExclusiveLite(&Vcb->MainResource, TRUE);
+                       MainResourceAcquired = TRUE;
+
+                       Status = FFSPurgeVolume(Vcb, TRUE);
+
+                       ExReleaseResourceLite(&Vcb->MainResource);
+                       MainResourceAcquired = FALSE;
+
+                       if(!IsFlagOn(Ccb->Flags, CCB_ALLOW_EXTENDED_DASD_IO))
+                       {
+                               if (ByteOffset.QuadPart + Length > Vcb->Header.FileSize.QuadPart)
+                               {
+                                       Length = (ULONG)(Vcb->Header.FileSize.QuadPart - ByteOffset.QuadPart);
+                               }
+                       }
+
+                       {
+                               FFS_BDL BlockArray;
+
+                               if ((ByteOffset.LowPart & (SECTOR_SIZE - 1)) ||
+                                               (Length & (SECTOR_SIZE - 1)))
+                               {
+                                       Status = STATUS_INVALID_PARAMETER;
+                                       _SEH2_LEAVE;
+                               }
+
+                               Status = FFSLockUserBuffer(
+                                                       IrpContext->Irp,
+                                                       Length,
+                                                       IoReadAccess);
+
+                               if (!NT_SUCCESS(Status))
+                               {
+                                       _SEH2_LEAVE;
+                               }
+
+                               BlockArray.Irp = NULL;
+                               BlockArray.Lba = ByteOffset.QuadPart;;
+                               BlockArray.Offset = 0;
+                               BlockArray.Length = Length;
+
+                               Status = FFSReadWriteBlocks(IrpContext,
+                                                       Vcb,
+                                                       &BlockArray,
+                                                       Length,
+                                                       1,
+                                                       FALSE);
+                               Irp = IrpContext->Irp;
+
+                               _SEH2_LEAVE;
+                       }
+               }                    
+
+               if (Nocache &&
+                               (ByteOffset.LowPart & (SECTOR_SIZE - 1) ||
+                                Length & (SECTOR_SIZE - 1)))
+               {
+                       Status = STATUS_INVALID_PARAMETER;
+                       _SEH2_LEAVE;
+               }
+
+               if (FlagOn(IrpContext->MinorFunction, IRP_MN_DPC))
+               {
+                       ClearFlag(IrpContext->MinorFunction, IRP_MN_DPC);
+                       Status = STATUS_PENDING;
+                       _SEH2_LEAVE;
+               }
+
+               if (ByteOffset.QuadPart >=
+                               Vcb->PartitionInformation.PartitionLength.QuadPart)
+               {
+                       Irp->IoStatus.Information = 0;
+                       Status = STATUS_END_OF_FILE;
+                       _SEH2_LEAVE;
+               }
+
+#if FALSE
+
+               if (!Nocache)
+               {
+                       BOOLEAN bAgain = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED);
+                       BOOLEAN bWait  = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
+                       BOOLEAN bQueue = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED);
+
+                       if (!CcCanIWrite(
+                                               FileObject,
+                                               Length,
+                                               (bWait && bQueue),
+                                               bAgain))
+                       {
+                               SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED);
+
+                               CcDeferWrite(FileObject,
+                                               (PCC_POST_DEFERRED_WRITE)FFSDeferWrite,
+                                               IrpContext,
+                                               Irp,
+                                               Length,
+                                               bAgain);
+
+                               bDeferred = TRUE;
+
+                               FFSBreakPoint();
+
+                               Status = STATUS_PENDING;
+
+                               _SEH2_LEAVE;
+                       }
+               }
+
+#endif
+
+               if (Nocache && !PagingIo && (Vcb->SectionObject.DataSectionObject != NULL)) 
+               {
+                       ExAcquireResourceExclusiveLite(&Vcb->MainResource, TRUE);
+                       MainResourceAcquired = TRUE;
+
+                       ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
+                       ExReleaseResourceLite(&Vcb->PagingIoResource);
+
+                       CcFlushCache(&(Vcb->SectionObject),
+                                       &ByteOffset,
+                                       Length,
+                                       &(Irp->IoStatus));
+
+                       if (!NT_SUCCESS(Irp->IoStatus.Status)) 
+                       {
+                               Status = Irp->IoStatus.Status;
+                               _SEH2_LEAVE;
+                       }
+
+                       ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
+                       ExReleaseResourceLite(&Vcb->PagingIoResource);
+
+                       CcPurgeCacheSection(&(Vcb->SectionObject),
+                                       (PLARGE_INTEGER)&(ByteOffset),
+                                       Length,
+                                       FALSE);
+
+                       ExReleaseResourceLite(&Vcb->MainResource);
+                       MainResourceAcquired = FALSE;
+               }
+
+               if (!PagingIo)
+               {
+#pragma prefast( suppress: 28137, "by design" )
+                       if (!ExAcquireResourceExclusiveLite(
+                                               &Vcb->MainResource,
+                                               IrpContext->IsSynchronous))
+                       {
+                               Status = STATUS_PENDING;
+                               _SEH2_LEAVE;
+                       }
+
+                       MainResourceAcquired = TRUE;
+               }
+               else
+               {
+                       /*
+                       ULONG ResShCnt, ResExCnt; 
+                       ResShCnt = ExIsResourceAcquiredSharedLite(&Vcb->PagingIoResource);
+                       ResExCnt = ExIsResourceAcquiredExclusiveLite(&Vcb->PagingIoResource);
+
+                       FFSPrint((DBG_USER, "PagingIoRes: %xh:%xh Synchronous=%xh\n", ResShCnt, ResExCnt, IrpContext->IsSynchronous));
+                       */
+
+                       if (Ccb)
+                       {
+                               if (!ExAcquireResourceSharedLite(
+                                                       &Vcb->PagingIoResource,
+                                                       IrpContext->IsSynchronous))
+                               {
+                                       Status = STATUS_PENDING;
+                                       _SEH2_LEAVE;
+                               }
+
+                               PagingIoResourceAcquired = TRUE;
+                       }
+               }
+
+               if (!Nocache)
+               {
+                       if ((ByteOffset.QuadPart + Length) >
+                                       Vcb->PartitionInformation.PartitionLength.QuadPart
+                       )
+                       {
+                               Length = (ULONG) (
+                                               Vcb->PartitionInformation.PartitionLength.QuadPart -
+                                               ByteOffset.QuadPart);
+
+                               Length &= ~((ULONG)SECTOR_SIZE - 1);
+                       }
+
+                       if (FlagOn(IrpContext->MinorFunction, IRP_MN_MDL))
+                       {
+
+                               CcPrepareMdlWrite(
+                                               Vcb->StreamObj,
+                                               &ByteOffset,
+                                               Length,
+                                               &Irp->MdlAddress,
+                                               &Irp->IoStatus);
+
+                               Status = Irp->IoStatus.Status;
+                       }
+                       else
+                       {
+                               Buffer = FFSGetUserBuffer(Irp);
+
+                               if (Buffer == NULL)
+                               {
+                                       FFSBreakPoint();
+
+                                       Status = STATUS_INVALID_USER_BUFFER;
+                                       _SEH2_LEAVE;
+                               }
+
+                               if (!CcCopyWrite(Vcb->StreamObj,
+                                                       (PLARGE_INTEGER)(&ByteOffset),
+                                                       Length,
+                                                       TRUE,
+                                                       Buffer))
+                               {
+                                       Status = STATUS_PENDING;
+                                       _SEH2_LEAVE;
+                               }
+
+                               Status = Irp->IoStatus.Status;
+                               FFSAddMcbEntry(Vcb, ByteOffset.QuadPart, (LONGLONG)Length);
+                       }
+
+                       if (NT_SUCCESS(Status))
+                       {
+                               Irp->IoStatus.Information = Length;
+                       }
+               }
+               else
+               {
+                       PFFS_BDL            ffs_bdl = NULL;
+                       ULONG               Blocks = 0;
+
+                       LONGLONG            DirtyStart;
+                       LONGLONG            DirtyLba;
+                       LONGLONG            DirtyLength;
+                       LONGLONG            RemainLength;
+
+                       if ((ByteOffset.QuadPart + Length) >
+                                       Vcb->PartitionInformation.PartitionLength.QuadPart)
+                       {
+                               Length = (ULONG)(
+                                               Vcb->PartitionInformation.PartitionLength.QuadPart -
+                                               ByteOffset.QuadPart);
+
+                               Length &= ~((ULONG)SECTOR_SIZE - 1);
+                       }
+
+                       Status = FFSLockUserBuffer(
+                                       IrpContext->Irp,
+                                       Length,
+                                       IoReadAccess);
+
+                       if (!NT_SUCCESS(Status))
+                       {
+                               _SEH2_LEAVE;
+                       }
+
+                       ffs_bdl = ExAllocatePoolWithTag(PagedPool, 
+                                       (Length / Vcb->BlockSize) *
+                                       sizeof(FFS_BDL), FFS_POOL_TAG);
+
+                       if (!ffs_bdl)
+                       {
+                               Status = STATUS_INSUFFICIENT_RESOURCES;
+                               _SEH2_LEAVE;
+                       }
+
+                       DirtyLba = ByteOffset.QuadPart;
+                       RemainLength = (LONGLONG)Length;
+
+                       while (RemainLength > 0)
+                       {
+                               DirtyStart = DirtyLba;
+
+                               if (FFSLookupMcbEntry(Vcb, 
+                                                       DirtyStart,
+                                                       &DirtyLba,
+                                                       &DirtyLength,
+                                                       (PLONGLONG)NULL,
+                                                       (PLONGLONG)NULL,
+                                                       (PULONG)NULL))
+                               {
+
+                                       if (DirtyLba == -1)
+                                       {
+                                               DirtyLba = DirtyStart + DirtyLength;
+
+                                               RemainLength = ByteOffset.QuadPart + 
+                                                       (LONGLONG)Length -
+                                                       DirtyLba;
+                                               continue;
+                                       }
+
+                                       ffs_bdl[Blocks].Irp = NULL;
+                                       ffs_bdl[Blocks].Lba = DirtyLba;
+                                       ffs_bdl[Blocks].Offset = (ULONG)((LONGLONG)Length +
+                                                       DirtyStart -
+                                                       RemainLength - 
+                                                       DirtyLba);
+
+                                       if (DirtyLba + DirtyLength > DirtyStart + RemainLength)
+                                       {
+                                               ffs_bdl[Blocks].Length = (ULONG)(DirtyStart +
+                                                               RemainLength -
+                                                               DirtyLba);
+                                               RemainLength = 0;
+                                       }
+                                       else
+                                       {
+                                               ffs_bdl[Blocks].Length = (ULONG)DirtyLength;
+                                               RemainLength =  (DirtyStart + RemainLength) -
+                                                       (DirtyLba + DirtyLength);
+                                       }
+
+                                       DirtyLba = DirtyStart + DirtyLength;
+                                       Blocks++;
+                               }
+                               else
+                               {
+                                       if (Blocks == 0)
+                                       {
+                                               if (ffs_bdl)
+                                                       ExFreePool(ffs_bdl);
+
+                                               //
+                                               // Lookup fails at the first time, ie. 
+                                               // no dirty blocks in the run
+                                               //
+
+                                               FFSBreakPoint();
+
+                                               if (RemainLength == (LONGLONG)Length)
+                                                       Status = STATUS_SUCCESS;
+                                               else
+                                                       Status = STATUS_UNSUCCESSFUL;
+
+                                               _SEH2_LEAVE;
+                                       }
+                                       else
+                                       {
+                                               break;
+                                       }
+                               }
+                       }
+
+                       if (Blocks > 0)
+                       {
+                               Status = FFSReadWriteBlocks(IrpContext,
+                                                       Vcb,
+                                                       ffs_bdl,
+                                                       Length,
+                                                       Blocks,
+                                                       FALSE);
+                               Irp = IrpContext->Irp;
+
+                               if (NT_SUCCESS(Status))
+                               {
+                                       ULONG   i;
+
+                                       for (i = 0; i < Blocks; i++)
+                                       {
+                                               FFSRemoveMcbEntry(Vcb,
+                                                               ffs_bdl[i].Lba,
+                                                               ffs_bdl[i].Length);
+                                       }
+                               }
+
+                               if (ffs_bdl)
+                                       ExFreePool(ffs_bdl);
+
+                               if (!Irp)
+                                       _SEH2_LEAVE;
+
+                       }
+                       else
+                       {
+                               if (ffs_bdl)
+                                       ExFreePool(ffs_bdl);
+
+                               Irp->IoStatus.Information = Length;
+
+                               Status = STATUS_SUCCESS;
+                               _SEH2_LEAVE;
+                       }
+               }
+       }
+
+       _SEH2_FINALLY
+       {
+               if (PagingIoResourceAcquired)
+               {
+                       ExReleaseResourceForThreadLite(
+                                       &Vcb->PagingIoResource,
+                                       ExGetCurrentResourceThread());
+               }
+
+               if (MainResourceAcquired)
+               {
+                       ExReleaseResourceForThreadLite(
+                                       &Vcb->MainResource,
+                                       ExGetCurrentResourceThread());
+               }
+
+               if (!IrpContext->ExceptionInProgress)
+               {
+                       if (Irp)
+                       {
+                               if (Status == STATUS_PENDING)
+                               {
+                                       if(!bDeferred)
+                                       {
+                                               Status = FFSLockUserBuffer(
+                                                               IrpContext->Irp,
+                                                               Length,
+                                                               IoReadAccess);
+
+                                               if (NT_SUCCESS(Status))
+                                               {
+                                                       Status = FFSQueueRequest(IrpContext);
+                                               }
+                                               else
+                                               {
+                                                       FFSCompleteIrpContext(IrpContext, Status);
+                                               }
+                                       }
+                               }
+                               else
+                               {
+                                       if (NT_SUCCESS(Status))
+                                       {
+                                               if (SynchronousIo && !PagingIo)
+                                               {
+                                                       FileObject->CurrentByteOffset.QuadPart =
+                                                               ByteOffset.QuadPart + Irp->IoStatus.Information;
+                                               }
+
+                                               if (!PagingIo)
+                                               {
+                                                       SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
+                                               }
+                                       }
+
+                                       FFSCompleteIrpContext(IrpContext, Status);
+                               }
+                       }
+                       else
+                       {
+                               FFSFreeIrpContext(IrpContext);
+                       }
+               }
+       } _SEH2_END;
+
+       return Status;
+}
+
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSv1WriteInode(
+       IN PFFS_IRP_CONTEXT     IrpContext,
+       IN PFFS_VCB             Vcb,
+       IN PFFSv1_INODE         dinode1,
+       IN ULONGLONG            offset,
+       IN PVOID                Buffer,
+       IN ULONG                size,
+       IN BOOLEAN              bWriteToDisk,
+       OUT PULONG              dwRet)
+{
+       PFFS_BDL    ffs_bdl = NULL;
+       ULONG       blocks, i;
+       NTSTATUS    Status = STATUS_UNSUCCESSFUL;
+       ULONG       Totalblocks;
+       LONGLONG    AllocSize;
+
+    PAGED_CODE();
+
+       if (dwRet)
+       {
+               *dwRet = 0;
+       }
+
+       Totalblocks = (dinode1->di_blocks);
+       AllocSize = ((LONGLONG)(FFSDataBlocks(Vcb, Totalblocks)) << BLOCK_BITS);
+
+       if ((LONGLONG)offset >= AllocSize)
+       {
+               FFSPrint((DBG_ERROR, "FFSv1WriteInode: beyond the file range.\n"));
+               return STATUS_SUCCESS;
+       }
+
+       if ((LONGLONG)offset + size > AllocSize)
+       {
+               size = (ULONG)(AllocSize - offset);
+       }
+
+       blocks = FFSv1BuildBDL(IrpContext, Vcb, dinode1, offset, size, &ffs_bdl);
+
+       if (blocks <= 0)
+       {
+               return STATUS_SUCCESS;
+       }
+
+#if DBG
+       {
+               ULONG   dwTotal = 0;
+               FFSPrint((DBG_INFO, "FFSv1WriteInode: BDLCount = %xh Size=%xh Off=%xh\n",
+                                       blocks, size, offset));
+               for(i = 0; i < blocks; i++)
+               {
+                       FFSPrint((DBG_INFO, "FFSv1WriteInode: Lba=%I64xh Len=%xh Off=%xh\n",
+                                               ffs_bdl[i].Lba, ffs_bdl[i].Length, ffs_bdl[i].Offset));
+                       dwTotal += ffs_bdl[i].Length;
+               }
+
+               if (dwTotal != size)
+               {
+                       FFSBreakPoint();
+               }
+
+               FFSPrint((DBG_INFO, "FFSv1WriteInode: Total = %xh (WriteToDisk=%x)\n",
+                                       dwTotal, bWriteToDisk));
+       }
+#endif
+
+       if (bWriteToDisk)
+       {
+
+#if 0
+               for(i = 0; i < blocks; i++)
+               {
+                       {
+                               CcFlushCache(&(Vcb->SectionObject),
+                                               (PLARGE_INTEGER)&(ffs_bdl[i].Lba),
+                                               ffs_bdl[i].Length,
+                                               NULL);
+
+                               if (Vcb->SectionObject.DataSectionObject != NULL)
+                               {
+                                       ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
+                                       ExReleaseResourceLite(&Vcb->PagingIoResource);
+
+                                       CcPurgeCacheSection(&(Vcb->SectionObject),
+                                                       (PLARGE_INTEGER)&(ffs_bdl[i].Lba),
+                                                       ffs_bdl[i].Length,
+                                                       FALSE);
+                               }
+                       }
+               }
+#endif
+
+               // assume offset is aligned.
+               Status = FFSReadWriteBlocks(IrpContext, Vcb, ffs_bdl, size, blocks, FALSE);
+       }
+       else
+       {
+               for(i = 0; i < blocks; i++)
+               {
+                       if(!FFSSaveBuffer(IrpContext, Vcb, ffs_bdl[i].Lba, ffs_bdl[i].Length, (PVOID)((PUCHAR)Buffer + ffs_bdl[i].Offset)))
+                               goto errorout;
+               }
+
+               if (IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK))
+               {
+                       FFSPrint((DBG_USER, "FFSv1WriteInode is starting FlushingDpc...\n"));
+                       FFSStartFloppyFlushDpc(Vcb, NULL, NULL);
+               }
+
+               Status = STATUS_SUCCESS;
+       }
+
+errorout:
+
+       if (ffs_bdl)
+               ExFreePool(ffs_bdl);
+
+       if (NT_SUCCESS(Status))
+       {
+               if (dwRet) *dwRet = size;
+       }
+
+       return Status;
+}
+
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSv2WriteInode(
+       IN PFFS_IRP_CONTEXT     IrpContext,
+       IN PFFS_VCB             Vcb,
+       IN PFFSv2_INODE         dinode2,
+       IN ULONGLONG            offset,
+       IN PVOID                Buffer,
+       IN ULONG                size,
+       IN BOOLEAN              bWriteToDisk,
+       OUT PULONG              dwRet)
+{
+       return STATUS_UNSUCCESSFUL;
+}
+
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSWriteFile(
+       IN PFFS_IRP_CONTEXT IrpContext)
+{
+       NTSTATUS            Status = STATUS_UNSUCCESSFUL;
+
+       PFFS_VCB            Vcb;
+       PFFS_FCB            Fcb;
+       PFFS_CCB            Ccb;
+       PFILE_OBJECT        FileObject;
+       PFILE_OBJECT        CacheObject;
+
+       PDEVICE_OBJECT      DeviceObject;
+
+       PIRP                Irp;
+       PIO_STACK_LOCATION  IoStackLocation;
+
+       ULONG               Length;
+       ULONG               ReturnedLength;
+       LARGE_INTEGER       ByteOffset;
+
+       BOOLEAN             PagingIo;
+       BOOLEAN             Nocache;
+       BOOLEAN             SynchronousIo;
+       BOOLEAN             MainResourceAcquired = FALSE;
+       BOOLEAN             PagingIoResourceAcquired = FALSE;
+
+       BOOLEAN             bNeedExtending = FALSE;
+       BOOLEAN             bAppendFile = FALSE;
+
+       BOOLEAN             bDeferred = FALSE;
+
+       PUCHAR              Buffer;
+
+    PAGED_CODE();
+
+       _SEH2_TRY
+       {
+               ASSERT(IrpContext);
+
+               ASSERT((IrpContext->Identifier.Type == FFSICX) &&
+                               (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
+
+               DeviceObject = IrpContext->DeviceObject;
+
+               Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;
+
+               ASSERT(Vcb != NULL);
+
+               ASSERT((Vcb->Identifier.Type == FFSVCB) &&
+                               (Vcb->Identifier.Size == sizeof(FFS_VCB)));
+
+               FileObject = IrpContext->FileObject;
+
+               Fcb = (PFFS_FCB)FileObject->FsContext;
+
+               ASSERT(Fcb);
+
+               ASSERT((Fcb->Identifier.Type == FFSFCB) &&
+                               (Fcb->Identifier.Size == sizeof(FFS_FCB)));
+
+               Ccb = (PFFS_CCB)FileObject->FsContext2;
+
+               Irp = IrpContext->Irp;
+
+               IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
+
+               Length = IoStackLocation->Parameters.Write.Length;
+               ByteOffset = IoStackLocation->Parameters.Write.ByteOffset;
+
+               PagingIo = (Irp->Flags & IRP_PAGING_IO ? TRUE : FALSE);
+               Nocache = (Irp->Flags & IRP_NOCACHE ? TRUE : FALSE);
+               SynchronousIo = (FileObject->Flags & FO_SYNCHRONOUS_IO ? TRUE : FALSE);
+
+               FFSPrint((DBG_INFO, "FFSWriteFile: Off=%I64xh Len=%xh Paging=%xh Nocache=%xh\n",
+                                       ByteOffset.QuadPart, Length, PagingIo, Nocache));
+
+               /*
+               if (IsFlagOn(Fcb->Flags, FCB_FILE_DELETED))
+               {
+                       Status = STATUS_FILE_DELETED;
+                       _SEH2_LEAVE;
+               }
+
+               if (IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING))
+               {
+                       Status = STATUS_DELETE_PENDING;
+                       _SEH2_LEAVE;
+               }
+               */
+
+               if (Length == 0)
+               {
+                       Irp->IoStatus.Information = 0;
+                       Status = STATUS_SUCCESS;
+                       _SEH2_LEAVE;
+               }
+
+               if (Nocache &&
+                               (ByteOffset.LowPart & (SECTOR_SIZE - 1) ||
+                                Length & (SECTOR_SIZE - 1)))
+               {
+                       Status = STATUS_INVALID_PARAMETER;
+                       _SEH2_LEAVE;
+               }
+
+               if (FlagOn(IrpContext->MinorFunction, IRP_MN_DPC))
+               {
+                       ClearFlag(IrpContext->MinorFunction, IRP_MN_DPC);
+                       Status = STATUS_PENDING;
+                       _SEH2_LEAVE;
+               }
+
+#if FALSE
+               if (!Nocache)
+               {
+                       BOOLEAN bAgain = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED);
+                       BOOLEAN bWait  = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
+                       BOOLEAN bQueue = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED);
+
+                       if (!CcCanIWrite(
+                                               FileObject,
+                                               Length,
+                                               (bWait && bQueue),
+                                               bAgain))
+                       {
+                               SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED);
+
+                               CcDeferWrite(FileObject,
+                                               (PCC_POST_DEFERRED_WRITE)FFSDeferWrite,
+                                               IrpContext,
+                                               Irp,
+                                               Length,
+                                               bAgain);
+
+                               bDeferred = TRUE;
+
+                               FFSBreakPoint();
+
+                               Status = STATUS_PENDING;
+                               _SEH2_LEAVE;
+                       }
+               }
+
+#endif
+
+               if (IsEndOfFile(ByteOffset))
+               {
+                       bAppendFile = TRUE;
+                       ByteOffset.QuadPart = Fcb->Header.FileSize.QuadPart;
+               }
+
+               if (FlagOn(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY) && !PagingIo)
+               {
+                       Status = STATUS_INVALID_DEVICE_REQUEST;
+                       _SEH2_LEAVE;
+               }
+
+               //
+               //  Do flushing for such cases
+               //
+               if (Nocache && !PagingIo && (Fcb->SectionObject.DataSectionObject != NULL)) 
+               {
+#pragma prefast( suppress: 28137, "by design" )
+                       ExAcquireResourceExclusiveLite(&Fcb->MainResource, 
+                                       IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT));
+
+                       MainResourceAcquired = TRUE;
+
+                       ExAcquireSharedStarveExclusive(&Fcb->PagingIoResource, TRUE);
+                       ExReleaseResourceLite(&Fcb->PagingIoResource);
+
+                       CcFlushCache(&(Fcb->SectionObject),
+                                       &ByteOffset,
+                                       Length,
+                                       &(Irp->IoStatus));
+                       ClearFlag(Fcb->Flags, FCB_FILE_MODIFIED);
+
+                       if (!NT_SUCCESS(Irp->IoStatus.Status)) 
+                       {
+                               Status = Irp->IoStatus.Status;
+                               _SEH2_LEAVE;
+                       }
+
+                       ExAcquireSharedStarveExclusive(&Fcb->PagingIoResource, TRUE);
+                       ExReleaseResourceLite(&Fcb->PagingIoResource);
+
+                       CcPurgeCacheSection(&(Fcb->SectionObject),
+                                       (PLARGE_INTEGER)&(ByteOffset),
+                                       Length,
+                                       FALSE);
+
+                       ExReleaseResourceLite(&Fcb->MainResource);
+                       MainResourceAcquired = FALSE;
+               }
+
+               if (!PagingIo)
+               {
+#pragma prefast( suppress: 28137, "by design" )
+                       if (!ExAcquireResourceExclusiveLite(
+                                               &Fcb->MainResource,
+                                               IrpContext->IsSynchronous))
+                       {
+                               Status = STATUS_PENDING;
+                               _SEH2_LEAVE;
+                       }
+
+                       MainResourceAcquired = TRUE;
+               }
+               else
+               {
+                       /*
+                       ULONG ResShCnt, ResExCnt; 
+                       ResShCnt = ExIsResourceAcquiredSharedLite(&Fcb->PagingIoResource);
+                       ResExCnt = ExIsResourceAcquiredExclusiveLite(&Fcb->PagingIoResource);
+
+                       FFSPrint((DBG_USER, "FFSWriteFile: Inode=%xh %S PagingIo: %xh:%xh Synchronous=%xh\n",
+                       Fcb->FFSMcb->Inode, Fcb->FFSMcb->ShortName.Buffer, ResShCnt, ResExCnt, IrpContext->IsSynchronous));
+                       */
+                       if (!ExAcquireResourceSharedLite(
+                                               &Fcb->PagingIoResource,
+                                               IrpContext->IsSynchronous))
+                       {
+                               Status = STATUS_PENDING;
+                               _SEH2_LEAVE;
+                       }
+
+                       PagingIoResourceAcquired = TRUE;
+               }
+
+               if (!PagingIo)
+               {
+                       if (!FsRtlCheckLockForWriteAccess(
+                                               &Fcb->FileLockAnchor,
+                                               Irp))
+                       {
+                               Status = STATUS_FILE_LOCK_CONFLICT;
+                               _SEH2_LEAVE;
+                       }
+               }
+
+               if (Nocache)
+               {
+                       if ((ByteOffset.QuadPart + Length) >
+                                       Fcb->Header.AllocationSize.QuadPart)
+                       {
+                               if (ByteOffset.QuadPart >= 
+                                               Fcb->Header.AllocationSize.QuadPart)
+                               {
+                                       Status = STATUS_SUCCESS;
+                                       Irp->IoStatus.Information = 0;
+                                       _SEH2_LEAVE;
+                               }
+                               else
+                               {
+                                       if (Length > (ULONG)(Fcb->Header.AllocationSize.QuadPart
+                                                               - ByteOffset.QuadPart))
+                                       {
+                                               Length = (ULONG)(Fcb->Header.AllocationSize.QuadPart
+                                                               - ByteOffset.QuadPart);
+                                       }
+                               }
+                       }
+               }
+
+               if (!Nocache)
+               {
+                       if (FlagOn(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY))
+                       {
+                               _SEH2_LEAVE;
+                       }
+
+                       if (FileObject->PrivateCacheMap == NULL)
+                       {
+                               CcInitializeCacheMap(
+                                               FileObject,
+                                               (PCC_FILE_SIZES)(&Fcb->Header.AllocationSize),
+                                               FALSE,
+                                               &FFSGlobal->CacheManagerCallbacks,
+                                               Fcb);
+
+                               CcSetReadAheadGranularity(
+                                               FileObject,
+                                               READ_AHEAD_GRANULARITY);
+
+                               CcSetFileSizes(
+                                               FileObject, 
+                                               (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
+                       }
+
+                       CacheObject = FileObject;
+
+                       //
+                       //  Need extending the size of inode ?
+                       //
+                       if ((bAppendFile) || ((ULONG)(ByteOffset.QuadPart + Length) >
+                                               (ULONG)(Fcb->Header.FileSize.QuadPart)))
+                       {
+
+                               LARGE_INTEGER   ExtendSize;
+                               LARGE_INTEGER   FileSize;
+
+                               bNeedExtending = TRUE;
+                               FileSize = Fcb->Header.FileSize;
+                               ExtendSize.QuadPart = (LONGLONG)(ByteOffset.QuadPart + Length);
+
+                               if (ExtendSize.QuadPart > Fcb->Header.AllocationSize.QuadPart)
+                               {
+                                       if (!FFSExpandFile(IrpContext, Vcb, Fcb, &ExtendSize))
+                                       {
+                                               Status = STATUS_INSUFFICIENT_RESOURCES;
+                                               _SEH2_LEAVE;
+                                       }
+                               }
+
+                               {
+                                       Fcb->Header.FileSize.QuadPart = ExtendSize.QuadPart;
+                                       Fcb->dinode1->di_size = (ULONG)ExtendSize.QuadPart;
+                               }
+
+                               if (FileObject->PrivateCacheMap)
+                               {
+                                       CcSetFileSizes(FileObject, (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
+
+                                       if (ByteOffset.QuadPart > FileSize.QuadPart)
+                                       {
+                                               FFSZeroHoles(IrpContext, Vcb, FileObject, FileSize.QuadPart, 
+                                                               ByteOffset.QuadPart - FileSize.QuadPart);
+                                       }
+
+                                       if (Fcb->Header.AllocationSize.QuadPart > ExtendSize.QuadPart)
+                                       {
+                                               FFSZeroHoles(IrpContext, Vcb, FileObject, ExtendSize.QuadPart, 
+                                                               Fcb->Header.AllocationSize.QuadPart - ExtendSize.QuadPart);
+                                       }
+                               }
+
+                               if (FFSv1SaveInode(IrpContext, Vcb, Fcb->FFSMcb->Inode, Fcb->dinode1))
+                               {
+                                       Status = STATUS_SUCCESS;
+                               }
+
+                               FFSNotifyReportChange(
+                                               IrpContext,
+                                               Vcb,
+                                               Fcb,
+                                               FILE_NOTIFY_CHANGE_SIZE,
+                                               FILE_ACTION_MODIFIED);
+                       }
+
+                       if (FlagOn(IrpContext->MinorFunction, IRP_MN_MDL))
+                       {
+                               CcPrepareMdlWrite(
+                                               CacheObject,
+                                               (&ByteOffset),
+                                               Length,
+                                               &Irp->MdlAddress,
+                                               &Irp->IoStatus);
+
+                               Status = Irp->IoStatus.Status;
+                       }
+                       else
+                       {
+                               Buffer = FFSGetUserBuffer(Irp);
+
+                               if (Buffer == NULL)
+                               {
+                                       FFSBreakPoint();
+                                       Status = STATUS_INVALID_USER_BUFFER;
+                                       _SEH2_LEAVE;
+                               }
+
+                               if (!CcCopyWrite(
+                                                       CacheObject,
+                                                       (PLARGE_INTEGER)&ByteOffset,
+                                                       Length,
+                                                       IrpContext->IsSynchronous,
+                                                       Buffer))
+                               {
+                                       Status = STATUS_PENDING;
+                                       _SEH2_LEAVE;
+                               }
+
+                               Status = Irp->IoStatus.Status;
+                       }
+
+                       if (NT_SUCCESS(Status))
+                       {
+                               Irp->IoStatus.Information = Length;
+
+                               if (IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK))
+                               {
+                                       FFSPrint((DBG_USER, "FFSWriteFile is starting FlushingDpc...\n"));
+                                       FFSStartFloppyFlushDpc(Vcb, Fcb, FileObject);
+                               }
+                       }
+               }
+               else
+               {
+                       ReturnedLength = Length;
+
+                       Status = FFSLockUserBuffer(
+                                       IrpContext->Irp,
+                                       Length,
+                                       IoReadAccess);
+
+                       if (!NT_SUCCESS(Status))
+                       {
+                               _SEH2_LEAVE;
+                       }
+
+                       Irp->IoStatus.Status = STATUS_SUCCESS;
+                       Irp->IoStatus.Information = Length;
+
+                       Status = 
+                               FFSv1WriteInode(
+                                               IrpContext,
+                                               Vcb,
+                                               Fcb->dinode1,
+                                               (ULONGLONG)(ByteOffset.QuadPart),
+                                               NULL,
+                                               Length,
+                                               TRUE,
+                                               &ReturnedLength);
+
+                       Irp = IrpContext->Irp;
+
+               }
+       }
+
+       _SEH2_FINALLY
+       {
+               if (PagingIoResourceAcquired)
+               {
+                       ExReleaseResourceForThreadLite(
+                                       &Fcb->PagingIoResource,
+                                       ExGetCurrentResourceThread());
+               }
+
+               if (MainResourceAcquired)
+               {
+                       ExReleaseResourceForThreadLite(
+                                       &Fcb->MainResource,
+                                       ExGetCurrentResourceThread());
+               }
+
+               if (!IrpContext->ExceptionInProgress)
+               {
+                       if (Irp)
+                       {
+                               if (Status == STATUS_PENDING)
+                               {
+                                       if (!bDeferred)
+                                       {
+                                               Status = FFSLockUserBuffer(
+                                                                       IrpContext->Irp,
+                                                                       Length,
+                                                                       IoReadAccess);
+
+                                               if (NT_SUCCESS(Status))
+                                               {
+                                                       Status = FFSQueueRequest(IrpContext);
+                                               }
+                                               else
+                                               {
+                                                       FFSCompleteIrpContext(IrpContext, Status);
+                                               }
+                                       }
+                               }
+                               else
+                               {
+                                       if (NT_SUCCESS(Status))
+                                       {
+                                               if (SynchronousIo && !PagingIo)
+                                               {
+                                                       FileObject->CurrentByteOffset.QuadPart =
+                                                               ByteOffset.QuadPart + Irp->IoStatus.Information;
+                                               }
+
+                                               if (!PagingIo)
+                                               {
+                                                       SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
+                                                       SetFlag(Fcb->Flags, FCB_FILE_MODIFIED);
+                                               }
+                                       }
+
+                                       FFSCompleteIrpContext(IrpContext, Status);
+                               }
+                       }
+                       else
+                       {
+                               FFSFreeIrpContext(IrpContext);
+                       }
+               }
+       } _SEH2_END;
+
+       return Status;
+
+}
+
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSWriteComplete(
+       IN PFFS_IRP_CONTEXT IrpContext)
+{
+       NTSTATUS        Status = STATUS_UNSUCCESSFUL;
+       PFILE_OBJECT    FileObject;
+       PIRP            Irp;
+       PIO_STACK_LOCATION IrpSp;
+
+    PAGED_CODE();
+
+       _SEH2_TRY
+       {
+               ASSERT(IrpContext);
+
+               ASSERT((IrpContext->Identifier.Type == FFSICX) &&
+                               (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
+
+               FileObject = IrpContext->FileObject;
+
+               Irp = IrpContext->Irp;
+               IrpSp = IoGetCurrentIrpStackLocation(Irp);
+
+               CcMdlWriteComplete(FileObject, &(IrpSp->Parameters.Write.ByteOffset), Irp->MdlAddress);
+
+               Irp->MdlAddress = NULL;
+
+               Status = STATUS_SUCCESS;
+       }
+
+       _SEH2_FINALLY
+       {
+               if (!IrpContext->ExceptionInProgress)
+               {
+                       FFSCompleteIrpContext(IrpContext, Status);
+               }
+       } _SEH2_END;
+
+       return Status;
+}
+
+
+__drv_mustHoldCriticalRegion
+NTSTATUS
+FFSWrite(
+       IN PFFS_IRP_CONTEXT IrpContext)
+{
+       NTSTATUS            Status;
+       PFFS_FCBVCB         FcbOrVcb;
+       PDEVICE_OBJECT      DeviceObject;
+       PFILE_OBJECT        FileObject;
+       PFFS_VCB            Vcb;
+       BOOLEAN             bCompleteRequest = TRUE;
+
+    PAGED_CODE();
+
+       ASSERT(IrpContext);
+
+       ASSERT((IrpContext->Identifier.Type == FFSICX) &&
+                       (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
+
+       _SEH2_TRY
+       {
+               if (FlagOn(IrpContext->MinorFunction, IRP_MN_COMPLETE))
+               {
+                       Status = FFSWriteComplete(IrpContext);
+                       bCompleteRequest = FALSE;
+               }
+               else
+               {
+                       DeviceObject = IrpContext->DeviceObject;
+
+                       if (DeviceObject == FFSGlobal->DeviceObject)
+                       {
+                               Status = STATUS_INVALID_DEVICE_REQUEST;
+                               _SEH2_LEAVE;
+                       }
+
+                       Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;
+
+                       if (Vcb->Identifier.Type != FFSVCB ||
+                                       Vcb->Identifier.Size != sizeof(FFS_VCB))
+                       {
+                               Status = STATUS_INVALID_PARAMETER;
+                               _SEH2_LEAVE;
+                       }
+
+                       ASSERT(IsMounted(Vcb));
+
+                       if (IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING))
+                       {
+                               Status = STATUS_TOO_LATE;
+                               _SEH2_LEAVE;
+                       }
+
+                       if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY))
+                       {
+                               Status = STATUS_MEDIA_WRITE_PROTECTED;
+                               _SEH2_LEAVE;
+                       }
+
+                       FileObject = IrpContext->FileObject;
+
+                       FcbOrVcb = (PFFS_FCBVCB)FileObject->FsContext;
+
+                       if (FcbOrVcb->Identifier.Type == FFSVCB)
+                       {
+                               Status = FFSWriteVolume(IrpContext);
+
+                               if (!NT_SUCCESS(Status))
+                               {
+                                       FFSBreakPoint();
+                               }
+
+                               bCompleteRequest = FALSE;
+                       }
+                       else if (FcbOrVcb->Identifier.Type == FFSFCB)
+                       {
+                               Status = FFSWriteFile(IrpContext);
+
+                               if (!NT_SUCCESS(Status))
+                               {
+                                       FFSBreakPoint();
+                               }
+
+                               bCompleteRequest = FALSE;
+                       }
+                       else
+                       {
+                               Status = STATUS_INVALID_PARAMETER;
+                       }
+               }
+       }
+
+       _SEH2_FINALLY
+       {
+               if (bCompleteRequest)
+               {
+                       FFSCompleteIrpContext(IrpContext, Status);
+               }
+       } _SEH2_END;
+
+       return Status;
+}
+
+#endif // !FFS_READ_ONLY