me@dev ~/BLDS/temp $ tar -c -h --hard-dereference -l -f test.tar ./bin ./etc ./lib ./sbin ./usr
tar: ./sbin/mount.ntfs-3g: File removed before we read it
tar: ./sbin/mkfs.ntfs: File removed before we read it
tar: ./sbin/mount.lowntfs-3g: File removed before we read it
tar: ./test.tar: file is the archive; not dumped
tar: ./etc/resolv.conf: File removed before we read it
creates the tar we need. (with the omissions outlined above) when pointed at an untarred copy of the rootfs.tar. So perhaps an interim 'expand' and recompress stage will be required.
In my experience the growth factor is between 200-250% given the task I am discussing.
: ) Glad we are doing this.
Thanks for the qt tip. I'll go dig. Qt really was my raison d'etre underlying this. it would be sexy to get the new release (when it makes it in) compiled using the super compliant tools. Probably a complete pig to get it to swallow but worth it I would wager.
I will add here a list of things that BREAK with the 2006q3 TC OOTB
WHY WOULD YOU BOTHER DOING THIS???
Well, Buildroot allows us to create staged sections to each build, meaning that once I have each of these packages built - I can go back an cherry pick which stage to tweak, what Makefile etc...
Basically I also didnt want anyone else to have to try a package only to find it broken.
So there you go, 16 hours later here's the info.
The Deathlist:
Spoiler:
linphone. because it calls ORTP which won't build. (heh, I made a funny)
libgtk2 dies with a recursion error (that's the theme for many of these fails IIRC)
Webkit because it calls libgtk2
(you can apply this principle to all 'RELIES ON blah' packages)
MPD Will pull Glib2 - that needs testing. Currently elided.
ltp-testsuite - dies with 'CAP_LAST_CAP' undeclared (Symbol issue again)
lttng-modules-2.0.3 - dies with a long string of errors
qt 4.8.2: Dies with futex.h:96: error: 'u32' was not declared in this scope
That's a futex header issue I believe. Input taken on that issue.
I did apply the fix knc1 mentioned first.
rt-tests dies with cyclictest.c:906: error: 'SCHED_BATCH' undeclared (first use in this function) (Symbol issue again probably based on a lack of RT in the kernel. pointless tool anways... Bit bucket methinks)
util-linux 2.20.1 - Dies since UUIDD dies.
Code:
../libblkid/src/.libs/libblkid.so: undefined reference to `fdopendir'
../libblkid/src/.libs/libblkid.so: undefined reference to `faccessat'
collect2: ld returned 1 exit status
make[4]: *** [mkswap] Error 1
U-boot Tools - Dies
Code:
fw_env.c:43:27: error: mtd/mtd-user.h: No such file or directory
possibly an incorrect depend
test_urcu_timing.o: In function `thr_writer':
/home/simon/BLDS/buildroot/build/liburcu-0.7.3/tests/test_urcu_timing.c:159: undefined reference to `__sync_lock_test_and_set_4'
KMOD: handle kernel modules (which is already in the device)
Okay onwards. Here is a complete list of everything I EXCLUDED:
Not built: (implicitly excluding the above stuff that died obviously)
These packages were not included in the build - They either were pointless given the hardware - outdated or duplicated - or relied on something that currently can't build, or for some other ineffable reason I didn't like the cut of their gib.
BUSYBOX
Spoiler:
(Install The) watchdog Daemon Startup Script to Busybox
Packages that are provided by Busybox 1.20.x (I'll go back and see what if any can be replaced)
Audio and video applications
Spoiler:
gstreamer - Selects: BR2_PACKAGE_LIBGLIB2
pulseaudio: not chosen
ALSA utils selection
Spoiler:
amidi, iecset, aplaymidi, arecordmidi, aseqdump, aseqnet,speaker-test all not built
mpd- Selects: BR2_PACKAGE_LIBGLIB2
Debugging, profiling and benchmark
Spoiler:
latencytop - we don't have support in kernel right now (shame)
Development tools
Spoiler:
pkg-config (OUCH) - Selects: BR2_PACKAGE_LIBGLIB2
Graphic libraries and applications (graphic/text)
Spoiler:
various dfbuffer examples and drivers (I am going to see if I can get this support in the kernel via a module perhaps? TBC, the excluded stuff seemed pointless.)
LINUX_FUSION: (err I saw no use in the short term)
SAWMAN: (maybe if we get directfb going)
Gob2 - Selects: BR2_PACKAGE_LIBGLIB2
vala - Selects: BR2_PACKAGE_LIBGLIB2
Enlightenment Foundation libraries (Some other poor souls headache)
QT -(OUCH) - Yeah so I mentioned it twice. Ouch. I will use the prebuilt ones from the games projects for now then.
X.org X Window System, X11R7, release 7.5 - err no.
HARDWARE:
Spoiler:
crdkit
cramfs
dbusglib
dbus-python
e2fsprogs - Selects: BR2_PACKAGE_UTIL_LINUX [=n] && BR2_PACKAGE_UTIL_LINUX_LIBBLKID [=n] && BR2_PACKAGE_UTIL_LINUX_LIBUUID - Two of which currently die.
eeprog - err no - Simple tool to read/write i2c eeprom chips.
ocf-linux - no kernel driver right now. ( The emulator cold MAYBE take advantage of this but I don't see any value if it can't be translated back onto the device)
openssl - ocf support was left out for obvious reasons
LIBS: FS
Spoiler:
gamin - Selects: BR2_PACKAGE_LIBGLIB2
liblockfile - nfs - erm not right now
libsysfs - its a 2.6 thing but dunno... support?
LIBS: GRAPHICS
Spoiler:
atk - Selects: BR2_PACKAGE_LIBGLIB2 [=n]
gdk-pixbuf - Selects: BR2_PACKAGE_LIBGLIB2 [=n]
pango - Selects: BR2_PACKAGE_LIBGLIB2
webkit - (OUCH) requires libgtk2
zxing - err no. unless someone REALLY REALLY wants a multi-format 1D/2D barcode image processing library. I've done all the barcode processing I want for one lifetime. InterMec I'm looking at you!
opencv - some support was elided - build tests, performance tests, gstreamer support, qt backend support, did not install 'extra data' - lib v4l support as libv4l does not compile
LIBS: HW
Spoiler:
libraw1394
libts - The Touchscreen tslib Library
libfreefare
LIBFTDI: Userspace access to FTDI USB interface chips
LIBIQRF: This library implement specific protocol which is used for communicating with iqrf devices (http://iqrf.org) over usb. For usb access is used libusb library.
LIBNFC: Public platform independent Near Field Communication (NFC) library.
LIBNFC_LLCP: Library extending libnfc with support for Logical Link Control
Protocol.
LIBS: MULTIMEDIA
Spoiler:
LIBMMS: LibMMS is a common library for parsing mms:// and mmsh:// type network streams. These are commonly used to stream Windows Media Video content over the web. LibMMS itself is only for receiving MMS stream, it doesn't handle sending at all.
Selects: BR2_PACKAGE_LIBGLIB2 [=y]
LIBDVDREAD: libdvdread provides a simple foundation for reading DVD-Video images.
LIBDVDNAV: libdvdnav is a library that allows easy use of sophisticated DVD navigation features such as DVD menus, multiangle playback and even interactive DVD games.
LIBPLAYER: libplayer provides a generic A/V API that relies on various multimedia player for Linux systems. It currently supports MPlayer, xine VLC and GStreamer only
(SINCE WE CANT OFFER ANY BACKEND SUPPORT FOR GSTREAMER / MPLAYER pointless)
MEDIASTREAMER: Mediastreamer is a powerful and lightweighted streaming engine specialized for voice/video telephony applications.
Selects: BR2_PACKAGE_ORTP [=n]
LIBS: NETWORKING
Spoiler:
GLIB_NETWORKING: Network-related GIO modules for glib.
Selects: BR2_PACKAGE_LIBGLIB2 [=n]
LIBMNL: libmnl is a minimalistic user-space library oriented to Netlink developers.
LIBMODBUS: libmodbus is a free software library to send/receive data according
to the Modbus protocol. This library is written in C and supports
RTU (serial) and TCP (Ethernet) communications.
LIBMBUS: libmbus is a library for communicating with energy metering devices.
It supports TCP and RS232 M-bus gateways.
(M-bus standard: http://www.m-bus.com/)
LIBNFNETLINK: libnfnetlink is the low-level library for netfilter related kernel/userspace communication.
LIBNETFILTER_CONNTRACK: libnetfilter_conntrack is a userspace library providing a programming interface (API) to the in-kernel connection tracking state table.
LIBNETFILTER_CTTIMEOUT: libnetfilter_cttimeout is the userspace library that provides the programming interface to the fine-grain connection tracking timeout infrastructure.
LIBNL: A library for applications dealing with netlink socket.
LIBOPING: liboping is a C library to generate ICMP echo requests, better known as "ping packets".
LIBPCAP: A system-independent library for user-level network packet capture.
LIBSOUP: libsoup is an HTTP client/server library. It uses GObject and the GLib main loop, to integrate well with GNOME applications.
Selects: BR2_PACKAGE_LIBXML2 [=y] && BR2_PACKAGE_LIBGLIB2 [=n]
LIBUPNP: The portable SDK for UPnP(tm) Devices (libupnp) provides developers
with an API and open source code for building control points,
devices, and bridges that are compliant with Version 1.0 of the
Universal Plug and Play Device Architecture Specification
LIBVNCSERVER: libvncserver is a VNC server/client library.
ZEROMQ: ØMQ (ZeroMQ, 0MQ, zmq) looks like an embeddable networking
library but acts like a concurrency framework.
LIBS: TEXT
Spoiler:
ENCHANT: Enchant is a spell-checking library that provides a consistent API across a number of spell-checking system backends.
Selects: BR2_PACKAGE_LIBGLIB2 [=n]
MISC:
All elided.
NETWORKING APPS:
Spoiler:
IT IS SHORTER TO LIST WHAT WAS BUILT:
CTORRENT, cifs-utils, LINKS, mutt and Rsync all built okay - rest untested as yet.
Package managers:
IPKG: The Itsy Package Installer from handhelds.org
Opkg built instead.
Real-Time
XENOMAI: Real-Time Framework for Linux http://www.xenomai.org
Xenomai is split in two parts: a kernel part and an userspace part. So, No.
System tools
QUOTA: Implementation of the disk quota system.
Selects: BR2_PACKAGE_UTIL_LINUX (which select UUID stuffs, which die, see death reports)
Text editors and viewers
nano is NOT optimized for size
Host utilities
Spoiler:
LPC3250LOADER: lpc3250loader is a tool to load/burn programs (in particular kickstart
and S1L) on an LPC3250 platform.
OMAP_U_BOOT_UTILS: U-Boot Utilities for Texas Instrument's OMAP platforms.
This is a set of tools to control U-Boot from scripts, generate
OMAP-specific signed image files and more.
OPENOCD: OpenOCD - Open On-Chip Debugger
HOST_SAM_BA: Atmel SAM-BA software provides an open set of tools for
programming the Atmel SAM3, SAM7 and SAM9 ARM-based
microcontrollers.
Bootloaders
Spoiler:
All elided (for now)
BAREBOX: The Barebox bootloader, formerly known as U-Boot v2.
BOOTLETS: Stage1 bootloaders for Freescale iMX23/iMX28 SoCs
BOOT: Build "Das U-Boot" Boot Monitor
That's all folks. Everything else built just fine. More details on that in a moment
Last edited by twobob; 08-18-2012 at 06:32 PM.
Reason: added blah, and a few deaths on the field of battle
Getting the Kindles to provide a "network share" over either USBnet or Wifi is a big step towards getting rid of the FAT-32 formatted user storage area.
Getting the Kindles to provide a "network share" over either USBnet or Wifi is a big step towards getting rid of the FAT-32 formatted user storage area.
To this end I have dug through the lists to see what is just 'on offer'.
There is an ssh based filesystem app that I will attempt to x-compile now and see what that is all about.
For what it's worth I have created a CIFS samba before IIRC you just have to create an authentication section and weld that into the request, or create it on the fly. The server config was all config files IIRC. I'll have a look.
Anyways I'll have a look when I've done nursing this build through. I'm testing a Glib2 dependent inclusion at the moment see how my mileage is today
EDIT: Whoops: libglib2 2.30.2 Building
Code:
CCLD libglib-2.0.la
CCLD gtester
./.libs/libglib-2.0.so: undefined reference to `qsort_r'
collect2: ld returned 1 exit status
make[6]: *** [gtester] Error 1
Another little chore . . . .
FAT-32 does not support symbolic links (required to get the symantics of *nix library sonames correct).
There are (at least) two ways to deal with that:
FAT{,16,32} does partially support hard-links (at least until you run dosfsck on it) ;
The target library of the links could be copied to each of the less specific names (makes a large increase in disk usage, but we have 3Gbytes) ;
or
some combination of the above.
It would probably be appropriate to do that in a custom, post-build, script.
Decisions, decisions, decisions. . . .
On a FAT, your "hard-link" is called a "cross-link". Disk checkers would report that as an error. Cross-linking is a common method of de-duplication used inside .ISO images, which is safe to do when they are mounted read-only (or burned onto read-only media). On a FAT partition it would be better to just provide multiple copies (which is how I did it for my SDL port).
I like how cygwin replaces symlinks with windows shortcuts, but that only works in a cygwin shell. We only have 3GB when the USB drive is not already full of other stuff (like mine), so replacing symlinks with multiple is not an ideal solution, even though it seems to be the most reliable option available on a FAT partition.
Last edited by geekmaster; 08-18-2012 at 11:36 AM.
On a FAT, your "hard-link" is called a "cross-link". Disk checkers would report that as an error. Cross-linking is a common method of de-duplication used inside .ISO images, which is safe to due when they are mounted read-only (or burned onto read-only media). On a FAT partition it would be better to just provide multiple copies (which is how I did it for my SDL port).
I like how cygwin replaces symlinks with windows shortcuts, but that only works in a cygwin shell. We only have 3GB when the USB drive is not already full of other stuff (like mine), so replacing symlinks with multiple is not an ideal solution, even though it seems to be the most reliable option available on a FAT partition.
Yes. There are 3 mainstream MS tools that may be massaged into doing similar roles on various incarnations of MS file systems.
Ranging from a DEBUG Dos hack, another early MS tool whose name evades my mind, XP's "fsutil hardlink foo bar", vista's mlink, 2003 servers linkd, 3rd party things like Symlinker, Winbolic, one could edit the directory-entries manually using a hex editor, we could hijack a related mechanism, etc into more and more obscure and provisional solutions.
I gave it a once over, elegant really. This was the code I was referring to, still not a one stop solution in the short term but maybe... meh. no it doesn't dumass. ntfs again. BAH - note to self translate comments before bothering others.
time will tell how desperate we are. : )
Any awesome ideas warmly welcomed.
Last edited by twobob; 08-18-2012 at 12:36 PM.
Reason: i was wrong. again. good to get one in for the day.
I gave it a once over, elegant really. This was the code I was referring to, still not a one stop solution in the short term but maybe... meh.
Hmm... The source code contains comments and printed text messages in some character set that my text editor does not render correctly. Oh well... "Real" programmers don't need comments, right? EDIT: In that code, where is the FAT symlink support? I only see what looks to me like NTFS support. Am I missing something here? Other peoples' code is hard to follow (too much white space).
Another thing that has annoyed me much too often is no Unicode support on FAT partitions. Some of my drives have file names from a bunch of different code pages, and many of them look scrambled depending on what codepage is loaded. Copying such files to NTFS leaves them scrambled (permanently). Mixed codepage filenames on FAT is a big problem (even worse than no symlinks, IMHO).
Last edited by geekmaster; 08-18-2012 at 11:51 AM.
Hmm... The source code contains comments and printed text messages in some character set that my text editor does not render correctly. Oh well... "Real" programmers don't need comments, right? EDIT: In that code, where is the FAT symlink support? I only see what looks to me like NTFS support. Am I missing something here? Other peoples' code is hard to follow (too much white space).
Another thing that has annoyed me much too often is no Unicode support on FAT partitions. Some of my drives have file names from a bunch of different code pages, and many of them look scrambled depending on what codepage is loaded. Copying such files to NTFS leaves them scrambled (permanently). Mixed codepage filenames on FAT is a big problem (even worse than no symlinks, IMHO).
That would be Japanese
Translated excepts from symlink.h (nothing major here so I just give you the highlights)
[1]
パス名の最大パス長/ / パス 名 の 最大 パス 長
The maximum path length of the name / / path maximum path length of the path name
[2]
作成操作はシンボリックリンクに到達して停止した/ / 作成 操作 は シンボリック リンク に 到達 し て 停止 し た
Create operation stopped after reaching a symbolic link creation operation / / is stopped after reaching a symbolic link
[3]
// IFS Kit で定義/ / IFS Kit で 定義
/ / Defined in the / / IFS Kit defined in the IFS Kit
[4]
高速 I/O テーブルに特定のエントリが存在するかどうか調べる/ / 高速 I / O テーブル に 特定 の エントリ が 存在 する か どうか 調べる
Examine whether there is a specific entry in the I / O speed table / / Check whether there is a specific entry in the I / O fast table
Translated version of symlink.c
// / /
// Symlink - ntfs.sys にパッチを当ててファイルに対するジャンクションを有効にする/ / Symlink - to enable the junction to the ntfs.sys file to patch
// / /
#include <ntddk.h> # Include <ntddk.h>
#include "symlink.h" # Include "symlink.h"
// / /
// このドライバオブジェクト/ / This driver object
// / /
PDRIVER_OBJECT SymlinkDriver; PDRIVER_OBJECT SymlinkDriver;
// / /
// このドライバの制御デバイスオブジェクト/ / Control device object for this driver
// / /
PDEVICE_OBJECT SymlinkController; PDEVICE_OBJECT SymlinkController;
// / /
// アンロード進行中を示すフラグ/ / Flag to indicate progress unload
// / /
BOOLEAN UnloadInProgress = FALSE; BOOLEAN UnloadInProgress = FALSE;
// / /
// 進行中の IRP の数/ / Number of IRP in progress
// / /
#if DBG # If DBG
ULONG OutstandingIRPCount = 0; ULONG OutstandingIRPCount = 0;
KSPIN_LOCK CountMutex; KSPIN_LOCK CountMutex;
#endif // DBG # Endif / / DBG
// / /
// ディスパッチエントリ用の完全パス名の lookaside / / Lookaside the full path name for the dispatch entry
// / /
PAGED_LOOKASIDE_LIST FullPathLookaside; PAGED_LOOKASIDE_LIST FullPathLookaside;
///////////////////////////////////////////////////////////////////////////// / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
// / /
// 各ルーチンにテキストセクションを割り当て/ / Assign text sections for each routine
// / /
///////////////////////////////////////////////////////////////////////////// / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath); NTSTATUS DriverEntry (IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath);
#if DBG # If DBG
VOID SymlinkUnload(IN PDRIVER_OBJECT DriverObject); VOID SymlinkUnload (IN PDRIVER_OBJECT DriverObject);
#endif # Endif
VOID SymlinkFsNotification( VOID SymlinkFsNotification (
PDEVICE_OBJECT DeviceObject, PDEVICE_OBJECT DeviceObject,
BOOLEAN FsActive BOOLEAN FsActive
); );
NTSTATUS NTSTATUS
SymlinkHookDone( SymlinkHookDone (
IN PDEVICE_OBJECT DeviceObject, IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp, IN PIRP Irp,
IN PVOID Context IN PVOID Context
); );
BOOLEAN SymlinkFilterDevice(PDEVICE_OBJECT DeviceObject); BOOLEAN SymlinkFilterDevice (PDEVICE_OBJECT DeviceObject);
VOID SymlinkResolveLink(IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp, IN PWSTR fullPathName); VOID SymlinkResolveLink (IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp, IN PWSTR fullPathName);
BOOLEAN BOOLEAN
SymlinkFastIoCheckIfPossible( SymlinkFastIoCheckIfPossible (
IN PFILE_OBJECT FileObject, IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER FileOffset,
IN ULONG Length, IN ULONG Length,
IN BOOLEAN Wait, IN BOOLEAN Wait,
IN ULONG LockKey, IN ULONG LockKey,
IN BOOLEAN CheckForReadOperation, IN BOOLEAN CheckForReadOperation,
OUT PIO_STATUS_BLOCK IoStatus, OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject IN PDEVICE_OBJECT DeviceObject
); );
BOOLEAN BOOLEAN
SymlinkFastIoRead( SymlinkFastIoRead (
IN PFILE_OBJECT FileObject, IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER FileOffset,
IN ULONG Length, IN ULONG Length,
IN BOOLEAN Wait, IN BOOLEAN Wait,
IN ULONG LockKey, IN ULONG LockKey,
OUT PVOID Buffer, OUT PVOID Buffer,
OUT PIO_STATUS_BLOCK IoStatus, OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject IN PDEVICE_OBJECT DeviceObject
); );
BOOLEAN BOOLEAN
SymlinkFastIoWrite( SymlinkFastIoWrite (
IN PFILE_OBJECT FileObject, IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER FileOffset,
IN ULONG Length, IN ULONG Length,
IN BOOLEAN Wait, IN BOOLEAN Wait,
IN ULONG LockKey, IN ULONG LockKey,
IN PVOID Buffer, IN PVOID Buffer,
OUT PIO_STATUS_BLOCK IoStatus, OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject IN PDEVICE_OBJECT DeviceObject
); );
BOOLEAN BOOLEAN
SymlinkFastIoQueryBasicInfo( SymlinkFastIoQueryBasicInfo (
IN PFILE_OBJECT FileObject, IN PFILE_OBJECT FileObject,
IN BOOLEAN Wait, IN BOOLEAN Wait,
OUT PFILE_BASIC_INFORMATION Buffer, OUT PFILE_BASIC_INFORMATION Buffer,
OUT PIO_STATUS_BLOCK IoStatus, OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject IN PDEVICE_OBJECT DeviceObject
); );
BOOLEAN BOOLEAN
SymlinkFastIoQueryStandardInfo( SymlinkFastIoQueryStandardInfo (
IN PFILE_OBJECT FileObject, IN PFILE_OBJECT FileObject,
IN BOOLEAN Wait, IN BOOLEAN Wait,
OUT PFILE_STANDARD_INFORMATION Buffer, OUT PFILE_STANDARD_INFORMATION Buffer,
OUT PIO_STATUS_BLOCK IoStatus, OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject IN PDEVICE_OBJECT DeviceObject
); );
BOOLEAN BOOLEAN
SymlinkFastIoLock( SymlinkFastIoLock (
IN PFILE_OBJECT FileObject, IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER FileOffset,
IN PLARGE_INTEGER Length, IN PLARGE_INTEGER Length,
PEPROCESS ProcessId, PEPROCESS ProcessId,
ULONG Key, ULONG Key,
BOOLEAN FailImmediately, BOOLEAN FailImmediately,
BOOLEAN ExclusiveLock, BOOLEAN ExclusiveLock,
OUT PIO_STATUS_BLOCK IoStatus, OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject IN PDEVICE_OBJECT DeviceObject
); );
BOOLEAN BOOLEAN
SymlinkFastIoUnlockSingle( SymlinkFastIoUnlockSingle (
IN PFILE_OBJECT FileObject, IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER FileOffset,
IN PLARGE_INTEGER Length, IN PLARGE_INTEGER Length,
PEPROCESS ProcessId, PEPROCESS ProcessId,
ULONG Key, ULONG Key,
OUT PIO_STATUS_BLOCK IoStatus, OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject IN PDEVICE_OBJECT DeviceObject
); );
BOOLEAN BOOLEAN
SymlinkFastIoUnlockAll( SymlinkFastIoUnlockAll (
IN PFILE_OBJECT FileObject, IN PFILE_OBJECT FileObject,
PEPROCESS ProcessId, PEPROCESS ProcessId,
OUT PIO_STATUS_BLOCK IoStatus, OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject IN PDEVICE_OBJECT DeviceObject
); );
BOOLEAN BOOLEAN
SymlinkFastIoUnlockAllByKey( SymlinkFastIoUnlockAllByKey (
IN PFILE_OBJECT FileObject, IN PFILE_OBJECT FileObject,
PEPROCESS ProcessId, PEPROCESS ProcessId,
ULONG Key, ULONG Key,
OUT PIO_STATUS_BLOCK IoStatus, OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject IN PDEVICE_OBJECT DeviceObject
); );
BOOLEAN BOOLEAN
SymlinkFastIoDeviceControl( SymlinkFastIoDeviceControl (
IN PFILE_OBJECT FileObject, IN PFILE_OBJECT FileObject,
IN BOOLEAN Wait, IN BOOLEAN Wait,
IN PVOID InputBuffer, IN PVOID InputBuffer,
IN ULONG InputBufferLength, IN ULONG InputBufferLength,
OUT PVOID OutputBuffer, OUT PVOID OutputBuffer,
IN ULONG OutputBufferLength, IN ULONG OutputBufferLength,
IN ULONG IoControlCode, IN ULONG IoControlCode,
OUT PIO_STATUS_BLOCK IoStatus, OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject IN PDEVICE_OBJECT DeviceObject
); );
VOID VOID
SymlinkFastIoDetachDevice( SymlinkFastIoDetachDevice (
PDEVICE_OBJECT SourceDevice, PDEVICE_OBJECT SourceDevice,
PDEVICE_OBJECT TargetDevice PDEVICE_OBJECT TargetDevice
); );
BOOLEAN BOOLEAN
SymlinkFastIoQueryNetworkOpenInfo( SymlinkFastIoQueryNetworkOpenInfo (
IN PFILE_OBJECT FileObject, IN PFILE_OBJECT FileObject,
IN BOOLEAN Wait, IN BOOLEAN Wait,
OUT struct _FILE_NETWORK_OPEN_INFORMATION *Buffer, OUT struct _FILE_NETWORK_OPEN_INFORMATION * Buffer,
OUT PIO_STATUS_BLOCK IoStatus, OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject IN PDEVICE_OBJECT DeviceObject
); );
BOOLEAN BOOLEAN
SymlinkFastIoMdlRead( SymlinkFastIoMdlRead (
IN PFILE_OBJECT FileObject, IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER FileOffset,
IN ULONG Length, IN ULONG Length,
IN ULONG LockKey, IN ULONG LockKey,
OUT PMDL *MdlChain, OUT PMDL * MdlChain,
OUT PIO_STATUS_BLOCK IoStatus, OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject IN PDEVICE_OBJECT DeviceObject
); );
BOOLEAN BOOLEAN
SymlinkFastIoPrepareMdlWrite( SymlinkFastIoPrepareMdlWrite (
IN PFILE_OBJECT FileObject, IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER FileOffset,
IN ULONG Length, IN ULONG Length,
IN ULONG LockKey, IN ULONG LockKey,
OUT PMDL *MdlChain, OUT PMDL * MdlChain,
OUT PIO_STATUS_BLOCK IoStatus, OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject IN PDEVICE_OBJECT DeviceObject
); );
BOOLEAN BOOLEAN
SymlinkFastIoMdlWriteComplete( SymlinkFastIoMdlWriteComplete (
IN PFILE_OBJECT FileObject, IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER FileOffset,
IN PMDL MdlChain, IN PMDL MdlChain,
IN PDEVICE_OBJECT DeviceObject IN PDEVICE_OBJECT DeviceObject
); );
BOOLEAN BOOLEAN
SymlinkFastIoReadCompressed( SymlinkFastIoReadCompressed (
IN PFILE_OBJECT FileObject, IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER FileOffset,
IN ULONG Length, IN ULONG Length,
IN ULONG LockKey, IN ULONG LockKey,
OUT PVOID Buffer, OUT PVOID Buffer,
OUT PMDL *MdlChain, OUT PMDL * MdlChain,
OUT PIO_STATUS_BLOCK IoStatus, OUT PIO_STATUS_BLOCK IoStatus,
OUT struct _COMPRESSED_DATA_INFO *CompressedDataInfo, OUT struct _COMPRESSED_DATA_INFO * CompressedDataInfo,
IN ULONG CompressedDataInfoLength, IN ULONG CompressedDataInfoLength,
IN PDEVICE_OBJECT DeviceObject IN PDEVICE_OBJECT DeviceObject
); );
BOOLEAN BOOLEAN
SymlinkFastIoWriteCompressed( SymlinkFastIoWriteCompressed (
IN PFILE_OBJECT FileObject, IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER FileOffset,
IN ULONG Length, IN ULONG Length,
IN ULONG LockKey, IN ULONG LockKey,
OUT PVOID Buffer, OUT PVOID Buffer,
OUT PMDL *MdlChain, OUT PMDL * MdlChain,
OUT PIO_STATUS_BLOCK IoStatus, OUT PIO_STATUS_BLOCK IoStatus,
OUT struct _COMPRESSED_DATA_INFO *CompressedDataInfo, OUT struct _COMPRESSED_DATA_INFO * CompressedDataInfo,
IN ULONG CompressedDataInfoLength, IN ULONG CompressedDataInfoLength,
IN PDEVICE_OBJECT DeviceObject IN PDEVICE_OBJECT DeviceObject
); );
BOOLEAN BOOLEAN
SymlinkFastIoQueryOpen( SymlinkFastIoQueryOpen (
IN PIRP Irp, IN PIRP Irp,
OUT PFILE_NETWORK_OPEN_INFORMATION NetworkInformation, OUT PFILE_NETWORK_OPEN_INFORMATION NetworkInformation,
IN PDEVICE_OBJECT DeviceObject IN PDEVICE_OBJECT DeviceObject
); );
BOOLEAN BOOLEAN
SymlinkQueryRoot( SymlinkQueryRoot (
PDEVICE_OBJECT DeviceObject, PDEVICE_OBJECT DeviceObject,
PHOOK_EXTENSION hookExt PHOOK_EXTENSION hookExt
); );
VOID VOID
SymlinkGetFullPath( SymlinkGetFullPath (
PFILE_OBJECT fileObject, PFILE_OBJECT fileObject,
PHOOK_EXTENSION hookExt, PHOOK_EXTENSION hookExt,
PWSTR fullPathName PWSTR fullPathName
); );
VOID SymlinkDeleteDevice(IN PDEVICE_OBJECT DeviceObject); VOID SymlinkDeleteDevice (IN PDEVICE_OBJECT DeviceObject);
BOOLEAN CallBackFastIoDeviceControl( BOOLEAN CallBackFastIoDeviceControl (
IN PFILE_OBJECT FileObject, IN BOOLEAN Wait, IN PFILE_OBJECT FileObject, IN BOOLEAN Wait,
IN PVOID InputBuffer, IN ULONG InputBufferLength, IN PVOID InputBuffer, IN ULONG InputBufferLength,
OUT PVOID OutputBuffer, IN ULONG OutputBufferLength, IN ULONG IoControlCode, OUT PVOID OutputBuffer, IN ULONG OutputBufferLength, IN ULONG IoControlCode,
OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject); OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject);
VOID SymlinkQueryAttributeTag(IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp); VOID SymlinkQueryAttributeTag (IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp);
#ifdef ALLOC_PRAGMA # Ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, DriverEntry) # Pragma alloc_text (INIT, DriverEntry)
#if DBG # If DBG
#pragma alloc_text(PAGE, SymlinkUnload) # Pragma alloc_text (PAGE, SymlinkUnload)
#endif # Endif
#pragma alloc_text(PAGE, SymlinkFsNotification) # Pragma alloc_text (PAGE, SymlinkFsNotification)
#pragma alloc_text(PAGE, SymlinkHookDone) # Pragma alloc_text (PAGE, SymlinkHookDone)
#pragma alloc_text(PAGE, SymlinkFilterDevice) # Pragma alloc_text (PAGE, SymlinkFilterDevice)
#pragma alloc_text(PAGE, SymlinkResolveLink) # Pragma alloc_text (PAGE, SymlinkResolveLink)
#pragma alloc_text(PAGE, SymlinkFastIoCheckIfPossible) # Pragma alloc_text (PAGE, SymlinkFastIoCheckIfPossible)
#pragma alloc_text(PAGE, SymlinkFastIoRead) # Pragma alloc_text (PAGE, SymlinkFastIoRead)
#pragma alloc_text(PAGE, SymlinkFastIoWrite) # Pragma alloc_text (PAGE, SymlinkFastIoWrite)
#pragma alloc_text(PAGE, SymlinkFastIoQueryBasicInfo) # Pragma alloc_text (PAGE, SymlinkFastIoQueryBasicInfo)
#pragma alloc_text(PAGE, SymlinkFastIoQueryStandardInfo) # Pragma alloc_text (PAGE, SymlinkFastIoQueryStandardInfo)
#pragma alloc_text(PAGE, SymlinkFastIoLock) # Pragma alloc_text (PAGE, SymlinkFastIoLock)
#pragma alloc_text(PAGE, SymlinkFastIoUnlockSingle) # Pragma alloc_text (PAGE, SymlinkFastIoUnlockSingle)
#pragma alloc_text(PAGE, SymlinkFastIoUnlockAll) # Pragma alloc_text (PAGE, SymlinkFastIoUnlockAll)
#pragma alloc_text(PAGE, SymlinkFastIoUnlockAllByKey) # Pragma alloc_text (PAGE, SymlinkFastIoUnlockAllByKey)
#pragma alloc_text(PAGE, SymlinkFastIoDeviceControl) # Pragma alloc_text (PAGE, SymlinkFastIoDeviceControl)
#pragma alloc_text(PAGE, SymlinkFastIoDetachDevice) # Pragma alloc_text (PAGE, SymlinkFastIoDetachDevice)
#pragma alloc_text(PAGE, SymlinkFastIoQueryNetworkOpenInfo) # Pragma alloc_text (PAGE, SymlinkFastIoQueryNetworkOpenInfo)
#pragma alloc_text(PAGE, SymlinkFastIoMdlRead) # Pragma alloc_text (PAGE, SymlinkFastIoMdlRead)
#pragma alloc_text(PAGE, SymlinkFastIoPrepareMdlWrite) # Pragma alloc_text (PAGE, SymlinkFastIoPrepareMdlWrite)
#pragma alloc_text(PAGE, SymlinkFastIoMdlWriteComplete) # Pragma alloc_text (PAGE, SymlinkFastIoMdlWriteComplete)
#pragma alloc_text(PAGE, SymlinkFastIoReadCompressed) # Pragma alloc_text (PAGE, SymlinkFastIoReadCompressed)
#pragma alloc_text(PAGE, SymlinkFastIoWriteCompressed) # Pragma alloc_text (PAGE, SymlinkFastIoWriteCompressed)
#pragma alloc_text(PAGE, SymlinkFastIoQueryOpen) # Pragma alloc_text (PAGE, SymlinkFastIoQueryOpen)
#pragma alloc_text(PAGE, SymlinkQueryRoot) # Pragma alloc_text (PAGE, SymlinkQueryRoot)
#pragma alloc_text(PAGE, SymlinkGetFullPath) # Pragma alloc_text (PAGE, SymlinkGetFullPath)
#pragma alloc_text(PAGE, SymlinkDeleteDevice) # Pragma alloc_text (PAGE, SymlinkDeleteDevice)
#pragma alloc_text(PAGE, CallBackFastIoDeviceControl) # Pragma alloc_text (PAGE, CallBackFastIoDeviceControl)
#pragma alloc_text(PAGE, SymlinkQueryAttributeTag) # Pragma alloc_text (PAGE, SymlinkQueryAttributeTag)
#endif # Endif
//---------------------------------------------------------------------- / / ------------------------------------------------ ----------------------
// / /
// SymlinkQueryRoot / / SymlinkQueryRoot
// / /
// hookExt に VDO の名前を設定する。 / / Set the name of the VDO to hookExt.
// hookExt->FileSystem はまだ初期化されていないかもしれないので/ / Because it might not have been initialized yet hookExt-> FileSystem
// 触らないこと。 / / Do not touch.
// / /
//---------------------------------------------------------------------- / / ------------------------------------------------ ----------------------
BOOLEAN BOOLEAN
SymlinkQueryRoot( SymlinkQueryRoot (
PDEVICE_OBJECT DeviceObject, PDEVICE_OBJECT DeviceObject,
PHOOK_EXTENSION hookExt PHOOK_EXTENSION hookExt
) )
{ {
OBJECT_NAME_INFORMATION nameInfo; OBJECT_NAME_INFORMATION nameInfo;
POBJECT_NAME_INFORMATION nameBuffer; POBJECT_NAME_INFORMATION nameBuffer;
ULONG bufferLength; ULONG bufferLength;
NTSTATUS status; NTSTATUS status;
PAGED_CODE(); PAGED_CODE ();
hookExt->RootChecked = TRUE; hookExt-> RootChecked = TRUE;
status = ObQueryNameString(DeviceObject, &nameInfo, sizeof(OBJECT_NAME_INFORMATION), &bufferLength); status = ObQueryNameString (DeviceObject, & nameInfo, sizeof (OBJECT_NAME_INFORMATION), & bufferLength);
if (!NT_SUCCESS(status) && status != STATUS_INFO_LENGTH_MISMATCH) { if (! NT_SUCCESS (status) && status! = STATUS_INFO_LENGTH_MISMATCH) {
KdPrint(("Symlink: Cannot query object name. status=%x\n", status)); KdPrint ((". Symlink: Cannot query object name status =% x \ n", status));
return FALSE; return FALSE;
} }
//KdPrint(("Symlink: required buffer length=%lu\n", bufferLength)); / / KdPrint (("Symlink: required buffer length =% lu \ n", bufferLength));
nameBuffer = ExAllocatePoolWithTag(NonPagedPool, bufferLength, 'lmyS'); nameBuffer = ExAllocatePoolWithTag (NonPagedPool, bufferLength, 'lmyS');
if (!nameBuffer) { if (! nameBuffer) {
KdPrint(("Symlink: Not enough memory allocating name buffer.\n")); KdPrint ((". Symlink: Not enough memory allocating name buffer \ n"));
return FALSE; return FALSE;
} }
status = ObQueryNameString(DeviceObject, nameBuffer, bufferLength, &bufferLength); status = ObQueryNameString (DeviceObject, nameBuffer, bufferLength, & bufferLength);
if (!NT_SUCCESS(status)) { if (! NT_SUCCESS (status)) {
KdPrint(("Symlink: Cannot query object name.\n")); KdPrint ((". Symlink: Cannot query object name \ n"));
ExFreePool(nameBuffer); ExFreePool (nameBuffer);
return FALSE; return FALSE;
} }
// / /
// 名前が空だったらエラーにする/ / If you were to name an empty error
// / /
if (!nameBuffer->Name.Length) { if (! nameBuffer-> Name.Length) {
KdPrint(("Symlink: Object name is empty.\n")); KdPrint ((". Symlink: Object name is empty \ n"));
ExFreePool(nameBuffer); ExFreePool (nameBuffer);
return FALSE; return FALSE;
} }
KdPrint(("Symlink: object name: %wZ\n", &nameBuffer->Name)); KdPrint (("Symlink: object name:% wZ \ n", & nameBuffer-> Name));
hookExt->Root = nameBuffer; hookExt-> Root = nameBuffer;
return TRUE; return TRUE;
} }
//---------------------------------------------------------------------- / / ------------------------------------------------ ----------------------
// / /
// SymlinkGetFullPath / / SymlinkGetFullPath
// / /
// ファイルオブジェクトとファイル名を取り、整形して完全パス名を返す。 / / Takes a file name and a file object and returns the full path name to shape.
// / /
//---------------------------------------------------------------------- / / ------------------------------------------------ ----------------------
VOID VOID
SymlinkGetFullPath( SymlinkGetFullPath (
PFILE_OBJECT fileObject, PFILE_OBJECT fileObject,
PHOOK_EXTENSION hookExt, PHOOK_EXTENSION hookExt,
PWSTR fullPathName PWSTR fullPathName
) )
{ {
ULONG pathLen, prefixLen, slashes; ULONG pathLen, prefixLen, slashes;
PWSTR pathOffset, ptr; PWSTR pathOffset, ptr;
PFILE_OBJECT relatedFileObject; PFILE_OBJECT relatedFileObject;
PUNICODE_STRING fileName; PUNICODE_STRING fileName;
PUNICODE_STRING relatedName; PUNICODE_STRING relatedName;
PAGED_CODE(); PAGED_CODE ();
if (!hookExt || !fullPathName) if (hookExt |! |! fullPathName)
return; return;
fullPathName[0] = 0; fullPathName [0] = 0;
// / /
// 名前をファイルオブジェクトから構築する/ / Construct an object from a file name
// / /
// / /
// ファイルオブジェクトがなければ名前を尋ねることさえできない/ / I can not even ask for the name if there is no object file
// / /
if (!fileObject) if (! fileObject)
return; return;
// / /
// プレフィックスの長さを計算/ / Calculate the length of the prefix
// / /
if (hookExt->Root) { if (hookExt-> Root) {
prefixLen = hookExt->Root->Name.Length / sizeof(WCHAR); prefixLen = hookExt-> Root-> Name.Length / sizeof (WCHAR);
} else if (!hookExt->RootChecked) { } Else if (! HookExt-> RootChecked) {
if (!SymlinkQueryRoot(fileObject->DeviceObject, hookExt)) if (! SymlinkQueryRoot (fileObject-> DeviceObject, hookExt))
return; return;
if (!hookExt->Root) if (! hookExt-> Root)
return; return;
prefixLen = hookExt->Root->Name.Length / sizeof(WCHAR); prefixLen = hookExt-> Root-> Name.Length / sizeof (WCHAR);
} else { } Else {
// ルートディレクトリ名が不明/ / Name of the root directory is unknown
return; return;
} }
// / /
// 変数を初期化/ / Initialize variables
// / /
fileName = NULL; fileName = NULL;
relatedName = NULL; relatedName = NULL;
// / /
// オブジェクト名に基づいて名前を構築/ / Construct a name based on the name of the object
// / /
// / /
// この時点で名前がなければ、デバイスへの raw アクセスを示す/ / If there is no name at this point shows the raw access to the device
// 相対パスの構築においては意味をなさないのでエラーにする/ / I want to error in the construction of the relative path does not make sense
// / /
if (!fileObject->FileName.Buffer) if (! fileObject-> FileName.Buffer)
return; return;
// / /
// 完全なパス名を作成する。 / / Create the full path name.まず、セパレータの空白と先頭のプレフィックスをFirst, the prefix and the first space of the separator
// 考慮して長さを計算する/ / Calculate the length due
// / /
fileName = &fileObject->FileName; fileName = & fileObject-> FileName;
pathLen = fileName->Length / sizeof(WCHAR) + prefixLen; pathLen = fileName-> Length / sizeof (WCHAR) + prefixLen;
relatedFileObject = fileObject->RelatedFileObject; relatedFileObject = fileObject-> RelatedFileObject;
// / /
// 相対ファイル名の場合のみ関連ファイルオブジェクトを見る/ / See the file related object only if a relative file name
// / /
if (fileName->Buffer[0] != L'\\' && if (fileName-> Buffer [0]! = L '\ \' &&
relatedFileObject && relatedFileObject->FileName.Length) { relatedFileObject && relatedFileObject-> FileName.Length) {
relatedName = &relatedFileObject->FileName; relatedName = & relatedFileObject-> FileName;
pathLen += relatedName->Length / sizeof(WCHAR) + 1; pathLen + = relatedName-> Length / sizeof (WCHAR) + 1;
} }
// / /
// 名前が長すぎたら終了/ / End if the name is too long
// / /
if (pathLen >= MAXPATHLEN) if (pathLen> = MAXPATHLEN)
return; return;
// / /
// まずルートディレクトリ名を先頭に追加/ / Add the name of the root directory to the top first
// / /
ASSERT(hookExt->Root); ASSERT (hookExt-> Root);
RtlCopyMemory(fullPathName, hookExt->Root->Name.Buffer, hookExt->Root->Name.Length); RtlCopyMemory (fullPathName, hookExt-> Root-> Name.Buffer, hookExt-> Root-> Name.Length);
// / /
// パス名を構築/ / Build the path name
// / /
fullPathName[pathLen] = 0; fullPathName [pathLen] = 0;
pathOffset = fullPathName + pathLen - fileName->Length / sizeof(WCHAR); pathOffset = fullPathName + pathLen - fileName-> Length / sizeof (WCHAR);
memcpy(pathOffset, fileName->Buffer, fileName->Length); memcpy (pathOffset, fileName-> Buffer, fileName-> Length);
// / /
// FIXME: RelatedFileObject->FileName を見てはいけない/ / FIXME: I do not see the RelatedFileObject-> FileName
// 自力で IRP_MJ_QUERY_INFORMATION を発行して FSD に尋ねるべし/ / I should ask to issue a FSD IRP_MJ_QUERY_INFORMATION on their own
// / /
if (fileName->Buffer[0] != L'\\' && if (fileName-> Buffer [0]! = L '\ \' &&
relatedFileObject && relatedFileObject->FileName.Length) { relatedFileObject && relatedFileObject-> FileName.Length) {
// / /
// バックスラッシュの区切りを追加しつつ構成要素をコピー/ / Copy the elements while adding a backslash separator
// / /
pathOffset[-1] = L'\\'; pathOffset [-1] = L '\ \';
pathOffset -= relatedName->Length / sizeof(WCHAR) + 1; pathOffset - = relatedName-> Length / sizeof (WCHAR) + 1;
memcpy(pathOffset, relatedName->Buffer, relatedName->Length); memcpy (pathOffset, relatedName-> Buffer, relatedName-> Length);
// / /
// 先頭に余分なバックスラッシュがあったら取り除く/ / Remove there was extra backslash to top
// / /
//if (hookExt->LogicalDrive && / / If (hookExt-> LogicalDrive &&
// pathLen > 7 && fullPathName[6] == L'\\' && fullPathName[7] == L'\\') { / / PathLen> 7 && fullPathName [6] == L '\ \' && fullPathName [7] == L '\ \') {
// wcscpy(fullPathName + 6, fullPathName + 7); / / Wcscpy (fullPathName + 6, fullPathName + 7);
//} / /}
} }
} }
//---------------------------------------------------------------------- / / ------------------------------------------------ ----------------------
// / /
// SymlinkDeleteDevice / / SymlinkDeleteDevice
// / /
// Symlinkのデバイスオブジェクトを削除するために必要な処理をすべて行い、 / / Do all the processing required to remove the device object Symlink,
// 削除する/ / Remove
// / /
//---------------------------------------------------------------------- / / ------------------------------------------------ ----------------------
VOID SymlinkDeleteDevice(IN PDEVICE_OBJECT DeviceObject) VOID SymlinkDeleteDevice (IN PDEVICE_OBJECT DeviceObject)
{ {
PHOOK_EXTENSION deviceExtension; PHOOK_EXTENSION deviceExtension;
POBJECT_NAME_INFORMATION nameInfo; POBJECT_NAME_INFORMATION nameInfo;
PAGED_CODE(); PAGED_CODE ();
if (DeviceObject != SymlinkController) { if (DeviceObject! = SymlinkController) {
deviceExtension = (PHOOK_EXTENSION)DeviceObject->DeviceExtension; deviceExtension = (PHOOK_EXTENSION) DeviceObject-> DeviceExtension;
// ファイルシステムオブジェクトがある場合は切り離す/ / If there is a file system object is separated
if (deviceExtension->FileSystem) { if (deviceExtension-> FileSystem) {
KdPrint(("Symlink about to detach %p from %p.\n", DeviceObject, deviceExtension->FileSystem)); KdPrint ((". Symlink about to detach% p from% p \ n", DeviceObject, deviceExtension-> FileSystem));
IoDetachDevice(deviceExtension->FileSystem); IoDetachDevice (deviceExtension-> FileSystem);
deviceExtension->FileSystem = NULL; deviceExtension-> FileSystem = NULL;
} }
// ルートパスを記憶している場合はパス名に使っていたメモリを解放する/ / If you are storing the root path frees the memory that was used in the path name
if (deviceExtension->Root) { if (deviceExtension-> Root) {
nameInfo = deviceExtension->Root; nameInfo = deviceExtension-> Root;
deviceExtension->Root = NULL; deviceExtension-> Root = NULL;
ExFreePool(nameInfo); ExFreePool (nameInfo);
} }
} }
// 最後にデバイスオブジェクト自体を削除/ / Remove the object at the end of the device itself
IoDeleteDevice(DeviceObject); IoDeleteDevice (DeviceObject);
} }
//---------------------------------------------------------------------- / / ------------------------------------------------ ----------------------
// / /
// SymlinkFilterDevice / / SymlinkFilterDevice
// / /
// パラメータで指定されたファイルシステムデバイスにフィルタを取り付ける。 / / Attach the filter to the file system device that is specified by the parameter.
// / /
//---------------------------------------------------------------------- / / ------------------------------------------------ ----------------------
BOOLEAN SymlinkFilterDevice(PDEVICE_OBJECT DeviceObject) BOOLEAN SymlinkFilterDevice (PDEVICE_OBJECT DeviceObject)
{ {
PDEVICE_OBJECT checkDevice, hookDevice; PDEVICE_OBJECT checkDevice, hookDevice;
NTSTATUS status; NTSTATUS status;
PHOOK_EXTENSION deviceExtension; PHOOK_EXTENSION deviceExtension;
PAGED_CODE(); PAGED_CODE ();
// / /
// ファイルシステムに高速 I/O ディスパッチルーチンがなければ、 / / If there is no I / O dispatch routine fast file system,
// フィルタすべきでない/ / You should not filter
// / /
if (!DeviceObject->DriverObject->FastIoDispatch) { if (! DeviceObject-> DriverObject-> FastIoDispatch) {
KdPrint(("Symlink: Choosing not to filter a file system with no " KdPrint (("Symlink: Choosing not to filter a file system with no"
"fast dispatch routines.\n")); ". Fast dispatch routines \ n"));
return FALSE; return FALSE;
} }
// / /
// すでに接続済みなら何もしないで成功とみなす/ / Considered a success without doing anything if already connected
// / /
checkDevice = DeviceObject; checkDevice = DeviceObject;
while (checkDevice) { while (checkDevice) {
if (checkDevice->DriverObject == SymlinkDriver) { if (checkDevice-> DriverObject == SymlinkDriver) {
KdPrint(("Symlink: Already attahced.\n")); KdPrint ((". Symlink: Already attahced \ n"));
return TRUE; return TRUE;
} }
checkDevice = checkDevice->AttachedDevice; checkDevice = checkDevice-> AttachedDevice;
} }
KdPrint(("Symlink: Filtering file system %p\n", DeviceObject)); KdPrint (("Symlink: Filtering file system% p \ n", DeviceObject));
// / /
// ドライブ文字を持っていないボリュームに/ / On a volume that does not have a drive letter
// 「ディスクの管理」からドライブ文字を追加すると、 / / If you add a drive letter from the "Disk Management",
// ドライブ文字を選ぶ前にマウントが発生してしまう。 / / Mount will occur before you choose a drive letter.
// つまりこの段階で適切なドライブ文字を取得することは不可能/ / You can get the appropriate drive letter that is not possible at this stage
// / /
// / /
// ファイルシステムに取り付ける新しいデバイスを作成/ / Create a new device attached to the file system
// / /
status = IoCreateDevice(SymlinkDriver, status = IoCreateDevice (SymlinkDriver,
sizeof(HOOK_EXTENSION), sizeof (HOOK_EXTENSION),
NULL, NULL,
DeviceObject->DeviceType, DeviceObject-> DeviceType,
0, 0,
FALSE, FALSE,
&hookDevice); & HookDevice);
if (!NT_SUCCESS(status)) { if (! NT_SUCCESS (status)) {
return FALSE; return FALSE;
} }
// / /
// 最上位に接続されたデバイスを判定してデバイス拡張を埋め、 / / Fill the expansion device to determine the device that is connected to the top,
// フラグを適切に設定する。 / / Set the flag properly.
// / /
deviceExtension = (PHOOK_EXTENSION)hookDevice->DeviceExtension; deviceExtension = (PHOOK_EXTENSION) hookDevice-> DeviceExtension;
hookDevice->Flags |= (DeviceObject->Flags & (DO_BUFFERED_IO | DO_DIRECT_IO)); hookDevice-> Flags | = (DeviceObject-> Flags & (DO_BUFFERED_IO | DO_DIRECT_IO));
if (DeviceObject->DeviceType == FILE_DEVICE_NETWORK_FILE_SYSTEM) if (DeviceObject-> DeviceType == FILE_DEVICE_NETWORK_FILE_SYSTEM)
SymlinkQueryRoot(DeviceObject, deviceExtension); SymlinkQueryRoot (DeviceObject, deviceExtension);
deviceExtension->FileSystem = deviceExtension-> FileSystem =
IoAttachDeviceToDeviceStack(hookDevice, DeviceObject); IoAttachDeviceToDeviceStack (hookDevice, DeviceObject);
if (!deviceExtension->FileSystem) { if (! deviceExtension-> FileSystem) {
KdPrint(("Symlink: Failed to attach hook device %p to device %p.\n", KdPrint (("Symlink:. Failed to attach hook device% p to device% p \ n",
hookDevice, DeviceObject)); hookDevice, DeviceObject));
SymlinkDeleteDevice(hookDevice); SymlinkDeleteDevice (hookDevice);
return FALSE; return FALSE;
} }
KdPrint(("Symlink: Attached new hook device %p to device %p.\n", KdPrint (("Symlink:. Attached new hook device% p to device% p \ n",
hookDevice, deviceExtension->FileSystem)); hookDevice, deviceExtension-> FileSystem));
hookDevice->Flags &= ~DO_DEVICE_INITIALIZING; hookDevice-> Flags & = ~ DO_DEVICE_INITIALIZING;
return TRUE; return TRUE;
} }
#if DBG # If DBG
//---------------------------------------------------------------------- / / ------------------------------------------------ ----------------------
// / /
// SymlinkQueryUnload / / SymlinkQueryUnload
// / /
// アンロードのためにすべてのデバイスから切り離す/ / Disconnect from all devices for unloading
// / /
//---------------------------------------------------------------------- / / ------------------------------------------------ ----------------------
VOID VOID
SymlinkQueryUnload( SymlinkQueryUnload (
PIO_STATUS_BLOCK IoStatus PIO_STATUS_BLOCK IoStatus
) )
{ {
KIRQL oldirql; KIRQL oldirql;
PDEVICE_OBJECT device, nextDevice; PDEVICE_OBJECT device, nextDevice;
// / /
// スピンロックの区間が存在するのでこのルーチン自体はページング可能/ / This routine itself pageable section of a spin lock because there are
// セクションに置けないが、ページング可能コードを参照しているので/ / You can not put the section, it refers to the pageable code
// ページング不可能なときに呼び出してはいけない/ / I do not call when nonpageable
// / /
PAGED_CODE(); PAGED_CODE ();
// / /
// アンロード可能か? / / Unload it possible?
// / /
KeAcquireSpinLock(&CountMutex, &oldirql); KeAcquireSpinLock (& CountMutex, & oldirql);
IoStatus->Information = OutstandingIRPCount; IoStatus-> Information = OutstandingIRPCount;
// / /
// 進行中の IRP が存在するか? / / IRP in progress exist?
// / /
if (OutstandingIRPCount) { if (OutstandingIRPCount) {
KeReleaseSpinLock(&CountMutex, oldirql); KeReleaseSpinLock (& CountMutex, oldirql);
return; return;
} }
// / /
// なければこれ以上 IRP を処理しない/ / I do not handle any more unless the IRP
// / /
UnloadInProgress = TRUE; UnloadInProgress = TRUE;
KeReleaseSpinLock(&CountMutex, oldirql); KeReleaseSpinLock (& CountMutex, oldirql);
// / /
// ファイルシステムデバイスから切り離す/ / Disconnected from the file system device
// / /
device = SymlinkDriver->DeviceObject; device = SymlinkDriver-> DeviceObject;
while (device) { while (device) {
nextDevice = device->NextDevice; nextDevice = device-> NextDevice;
if (device != SymlinkController) { if (device! = SymlinkController) {
SymlinkDeleteDevice(device); SymlinkDeleteDevice (device);
} }
device = nextDevice; device = nextDevice;
} }
} }
#endif // DBG # Endif / / DBG
//---------------------------------------------------------------------- / / ------------------------------------------------ ----------------------
// 高速 I/O ルーチン/ / I / O routine fast
//---------------------------------------------------------------------- / / ------------------------------------------------ ----------------------
//---------------------------------------------------------------------- / / ------------------------------------------------ ----------------------
// / /
// SymlinkFastIoCheckIfPossible / / SymlinkFastIoCheckIfPossible
// / /
//---------------------------------------------------------------------- / / ------------------------------------------------ ----------------------
BOOLEAN BOOLEAN
SymlinkFastIoCheckIfPossible( SymlinkFastIoCheckIfPossible (
IN PFILE_OBJECT FileObject, IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER FileOffset,
IN ULONG Length, IN ULONG Length,
IN BOOLEAN Wait, IN BOOLEAN Wait,
IN ULONG LockKey, IN ULONG LockKey,
IN BOOLEAN CheckForReadOperation, IN BOOLEAN CheckForReadOperation,
OUT PIO_STATUS_BLOCK IoStatus, OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject IN PDEVICE_OBJECT DeviceObject
) )
{ {
BOOLEAN retval = FALSE; BOOLEAN retval = FALSE;
PHOOK_EXTENSION hookExt; PHOOK_EXTENSION hookExt;
PAGED_CODE(); PAGED_CODE ();
if (!DeviceObject) if (! DeviceObject)
return FALSE; return FALSE;
hookExt = DeviceObject->DeviceExtension; hookExt = DeviceObject-> DeviceExtension;
if (FASTIOPRESENT(hookExt, FastIoCheckIfPossible)) { if (FASTIOPRESENT (hookExt, FastIoCheckIfPossible)) {
retval = hookExt->FileSystem->DriverObject->FastIoDispatch->FastIoCheckIfPossible( retval = hookExt-> FileSystem-> DriverObject-> FastIoDispatch-> FastIoCheckIfPossible (
FileObject, FileOffset, Length, FileObject, FileOffset, Length,
Wait, LockKey, CheckForReadOperation, IoStatus, hookExt->FileSystem); Wait, LockKey, CheckForReadOperation, IoStatus, hookExt-> FileSystem);
} }
return retval; return retval;
} }
//---------------------------------------------------------------------- / / ------------------------------------------------ ----------------------
// / /
// SymlinkFastIoRead / / SymlinkFastIoRead
// / /
//---------------------------------------------------------------------- / / ------------------------------------------------ ----------------------
BOOLEAN BOOLEAN
SymlinkFastIoRead( SymlinkFastIoRead (
IN PFILE_OBJECT FileObject, IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER FileOffset,
IN ULONG Length, IN ULONG Length,
IN BOOLEAN Wait, IN BOOLEAN Wait,
IN ULONG LockKey, IN ULONG LockKey,
OUT PVOID Buffer, OUT PVOID Buffer,
OUT PIO_STATUS_BLOCK IoStatus, OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject IN PDEVICE_OBJECT DeviceObject
) )
{ {
BOOLEAN retval = FALSE; BOOLEAN retval = FALSE;
PHOOK_EXTENSION hookExt; PHOOK_EXTENSION hookExt;
PAGED_CODE(); PAGED_CODE ();
if (!DeviceObject) if (! DeviceObject)
return FALSE; return FALSE;
hookExt = DeviceObject->DeviceExtension; hookExt = DeviceObject-> DeviceExtension;
if (FASTIOPRESENT(hookExt, FastIoRead)) { if (FASTIOPRESENT (hookExt, FastIoRead)) {
retval = hookExt->FileSystem->DriverObject->FastIoDispatch->FastIoRead( retval = hookExt-> FileSystem-> DriverObject-> FastIoDispatch-> FastIoRead (
FileObject, FileOffset, Length, FileObject, FileOffset, Length,
Wait, LockKey, Buffer, IoStatus, hookExt->FileSystem); Wait, LockKey, Buffer, IoStatus, hookExt-> FileSystem);
} }
return retval; return retval;
} }
//---------------------------------------------------------------------- / / ------------------------------------------------ ----------------------
// / /
// SymlinkFastIoWrite / / SymlinkFastIoWrite
// / /
//---------------------------------------------------------------------- / / ------------------------------------------------ ----------------------
BOOLEAN BOOLEAN
SymlinkFastIoWrite( SymlinkFastIoWrite (
IN PFILE_OBJECT FileObject, IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER FileOffset,
IN ULONG Length, IN ULONG Length,
IN BOOLEAN Wait, IN BOOLEAN Wait,
IN ULONG LockKey, IN ULONG LockKey,
IN PVOID Buffer, IN PVOID Buffer,
OUT PIO_STATUS_BLOCK IoStatus, OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject IN PDEVICE_OBJECT DeviceObject
) )
{ {
BOOLEAN retval = FALSE; BOOLEAN retval = FALSE;
PHOOK_EXTENSION hookExt; PHOOK_EXTENSION hookExt;
PAGED_CODE(); PAGED_CODE ();
if (!DeviceObject) if (! DeviceObject)
return FALSE; return FALSE;
hookExt = DeviceObject->DeviceExtension; hookExt = DeviceObject-> DeviceExtension;
if (FASTIOPRESENT( hookExt, FastIoWrite )) { if (FASTIOPRESENT (hookExt, FastIoWrite)) {
retval = hookExt->FileSystem->DriverObject->FastIoDispatch->FastIoWrite( retval = hookExt-> FileSystem-> DriverObject-> FastIoDispatch-> FastIoWrite (
FileObject, FileOffset, Length, Wait, LockKey, FileObject, FileOffset, Length, Wait, LockKey,
Buffer, IoStatus, hookExt->FileSystem); Buffer, IoStatus, hookExt-> FileSystem);
} }
return retval; return retval;
} }
//---------------------------------------------------------------------- / / ------------------------------------------------ ----------------------
// / /
// SymlinkFastIoQueryBasicinfo / / SymlinkFastIoQueryBasicinfo
// / /
//---------------------------------------------------------------------- / / ------------------------------------------------ ----------------------
BOOLEAN BOOLEAN
SymlinkFastIoQueryBasicInfo( SymlinkFastIoQueryBasicInfo (
IN PFILE_OBJECT FileObject, IN PFILE_OBJECT FileObject,
IN BOOLEAN Wait, IN BOOLEAN Wait,
OUT PFILE_BASIC_INFORMATION Buffer, OUT PFILE_BASIC_INFORMATION Buffer,
OUT PIO_STATUS_BLOCK IoStatus, OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject IN PDEVICE_OBJECT DeviceObject
) )
{ {
BOOLEAN retval = FALSE; BOOLEAN retval = FALSE;
PHOOK_EXTENSION hookExt; PHOOK_EXTENSION hookExt;
PAGED_CODE(); PAGED_CODE ();
if (!DeviceObject) if (! DeviceObject)
return FALSE; return FALSE;
hookExt = DeviceObject->DeviceExtension; hookExt = DeviceObject-> DeviceExtension;
if (FASTIOPRESENT(hookExt, FastIoQueryBasicInfo)) { if (FASTIOPRESENT (hookExt, FastIoQueryBasicInfo)) {
retval = hookExt->FileSystem->DriverObject->FastIoDispatch->FastIoQueryBasicInfo( retval = hookExt-> FileSystem-> DriverObject-> FastIoDispatch-> FastIoQueryBasicInfo (
FileObject, Wait, Buffer, IoStatus, hookExt->FileSystem); FileObject, Wait, Buffer, IoStatus, hookExt-> FileSystem);
} }
return retval; return retval;
} }
//---------------------------------------------------------------------- / / ------------------------------------------------ ----------------------
// / /
// SymlinkFastIoQueryStandardInfo / / SymlinkFastIoQueryStandardInfo
// / /
//---------------------------------------------------------------------- / / ------------------------------------------------ ----------------------
BOOLEAN BOOLEAN
SymlinkFastIoQueryStandardInfo( SymlinkFastIoQueryStandardInfo (
IN PFILE_OBJECT FileObject, IN PFILE_OBJECT FileObject,
IN BOOLEAN Wait, IN BOOLEAN Wait,
OUT PFILE_STANDARD_INFORMATION Buffer, OUT PFILE_STANDARD_INFORMATION Buffer,
OUT PIO_STATUS_BLOCK IoStatus, OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject IN PDEVICE_OBJECT DeviceObject
) )
{ {
BOOLEAN retval = FALSE; BOOLEAN retval = FALSE;
PHOOK_EXTENSION hookExt; PHOOK_EXTENSION hookExt;
PAGED_CODE(); PAGED_CODE ();
if (!DeviceObject) if (! DeviceObject)
return FALSE; return FALSE;
hookExt = DeviceObject->DeviceExtension; hookExt = DeviceObject-> DeviceExtension;
if (FASTIOPRESENT(hookExt, FastIoQueryStandardInfo)) { if (FASTIOPRESENT (hookExt, FastIoQueryStandardInfo)) {
retval = hookExt->FileSystem->DriverObject->FastIoDispatch->FastIoQueryStandardInfo( retval = hookExt-> FileSystem-> DriverObject-> FastIoDispatch-> FastIoQueryStandardInfo (
FileObject, Wait, Buffer, IoStatus, hookExt->FileSystem); FileObject, Wait, Buffer, IoStatus, hookExt-> FileSystem);
} }
return retval; return retval;
} }
//---------------------------------------------------------------------- / / ------------------------------------------------ ----------------------
// / /
// SymlinkFastIoLock / / SymlinkFastIoLock
// / /
//---------------------------------------------------------------------- / / ------------------------------------------------ ----------------------
BOOLEAN BOOLEAN
SymlinkFastIoLock( SymlinkFastIoLock (
IN PFILE_OBJECT FileObject, IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER FileOffset,
IN PLARGE_INTEGER Length, IN PLARGE_INTEGER Length,
PEPROCESS ProcessId, PEPROCESS ProcessId,
ULONG Key, ULONG Key,
BOOLEAN FailImmediately, BOOLEAN FailImmediately,
BOOLEAN ExclusiveLock, BOOLEAN ExclusiveLock,
OUT PIO_STATUS_BLOCK IoStatus, OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject IN PDEVICE_OBJECT DeviceObject
) )
{ {
BOOLEAN retval = FALSE; BOOLEAN retval = FALSE;
PHOOK_EXTENSION hookExt; PHOOK_EXTENSION hookExt;
PAGED_CODE(); PAGED_CODE ();
if (!DeviceObject) if (! DeviceObject)
return FALSE; return FALSE;
hookExt = DeviceObject->DeviceExtension; hookExt = DeviceObject-> DeviceExtension;
if (FASTIOPRESENT(hookExt, FastIoLock)) { if (FASTIOPRESENT (hookExt, FastIoLock)) {
retval = hookExt->FileSystem->DriverObject->FastIoDispatch->FastIoLock( retval = hookExt-> FileSystem-> DriverObject-> FastIoDispatch-> FastIoLock (
FileObject, FileOffset, Length, ProcessId, Key, FailImmediately, FileObject, FileOffset, Length, ProcessId, Key, FailImmediately,
ExclusiveLock, IoStatus, hookExt->FileSystem); ExclusiveLock, IoStatus, hookExt-> FileSystem);
} }
return retval; return retval;
} }
//---------------------------------------------------------------------- / / ------------------------------------------------ ----------------------
// / /
// SymlinkFastIoUnlockSingle / / SymlinkFastIoUnlockSingle
// / /
//---------------------------------------------------------------------- / / ------------------------------------------------ ----------------------
BOOLEAN BOOLEAN
SymlinkFastIoUnlockSingle( SymlinkFastIoUnlockSingle (
IN PFILE_OBJECT FileObject, IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER FileOffset,
IN PLARGE_INTEGER Length, IN PLARGE_INTEGER Length,
PEPROCESS ProcessId, PEPROCESS ProcessId,
ULONG Key, ULONG Key,
OUT PIO_STATUS_BLOCK IoStatus, OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject IN PDEVICE_OBJECT DeviceObject
) )
{ {
BOOLEAN retval = FALSE; BOOLEAN retval = FALSE;
PHOOK_EXTENSION hookExt; PHOOK_EXTENSION hookExt;
PAGED_CODE(); PAGED_CODE ();
if (!DeviceObject) if (! DeviceObject)
return FALSE; return FALSE;
hookExt = DeviceObject->DeviceExtension; hookExt = DeviceObject-> DeviceExtension;
if (FASTIOPRESENT(hookExt, FastIoUnlockSingle)) { if (FASTIOPRESENT (hookExt, FastIoUnlockSingle)) {
retval = hookExt->FileSystem->DriverObject->FastIoDispatch->FastIoUnlockSingle( retval = hookExt-> FileSystem-> DriverObject-> FastIoDispatch-> FastIoUnlockSingle (
FileObject, FileOffset, Length, ProcessId, Key, FileObject, FileOffset, Length, ProcessId, Key,
IoStatus, hookExt->FileSystem); IoStatus, hookExt-> FileSystem);
} }
return retval; return retval;
} }
//---------------------------------------------------------------------- / / ------------------------------------------------ ----------------------
// / /
// SymlinkFastIoUnlockAll / / SymlinkFastIoUnlockAll
// / /
//---------------------------------------------------------------------- / / ------------------------------------------------ ----------------------
BOOLEAN BOOLEAN
SymlinkFastIoUnlockAll( SymlinkFastIoUnlockAll (
IN PFILE_OBJECT FileObject, IN PFILE_OBJECT FileObject,
PEPROCESS ProcessId, PEPROCESS ProcessId,
OUT PIO_STATUS_BLOCK IoStatus, OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject IN PDEVICE_OBJECT DeviceObject
) )
{ {
BOOLEAN retval = FALSE; BOOLEAN retval = FALSE;
PHOOK_EXTENSION hookExt; PHOOK_EXTENSION hookExt;
PAGED_CODE(); PAGED_CODE ();
if (!DeviceObject) if (! DeviceObject)
return FALSE; return FALSE;
hookExt = DeviceObject->DeviceExtension; hookExt = DeviceObject-> DeviceExtension;
if (FASTIOPRESENT(hookExt, FastIoUnlockAll)) { if (FASTIOPRESENT (hookExt, FastIoUnlockAll)) {
retval = hookExt->FileSystem->DriverObject->FastIoDispatch->FastIoUnlockAll( retval = hookExt-> FileSystem-> DriverObject-> FastIoDispatch-> FastIoUnlockAll (
FileObject, ProcessId, IoStatus, hookExt->FileSystem); FileObject, ProcessId, IoStatus, hookExt-> FileSystem);
} }
return retval; return retval;
} }
//---------------------------------------------------------------------- / / ------------------------------------------------ ----------------------
// / /
// SymlinkFastIoUnlockAllByKey / / SymlinkFastIoUnlockAllByKey
// / /
//---------------------------------------------------------------------- / / ------------------------------------------------ ----------------------
BOOLEAN BOOLEAN
SymlinkFastIoUnlockAllByKey( SymlinkFastIoUnlockAllByKey (
IN PFILE_OBJECT FileObject, IN PFILE_OBJECT FileObject,
PEPROCESS ProcessId, PEPROCESS ProcessId,
ULONG Key, ULONG Key,
OUT PIO_STATUS_BLOCK IoStatus, OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject IN PDEVICE_OBJECT DeviceObject
) )
{ {
BOOLEAN retval = FALSE; BOOLEAN retval = FALSE;
PHOOK_EXTENSION hookExt; PHOOK_EXTENSION hookExt;
PAGED_CODE(); PAGED_CODE ();
if (!DeviceObject) if (! DeviceObject)
return FALSE; return FALSE;
hookExt = DeviceObject->DeviceExtension; hookExt = DeviceObject-> DeviceExtension;
if (FASTIOPRESENT(hookExt, FastIoUnlockAllByKey)) { if (FASTIOPRESENT (hookExt, FastIoUnlockAllByKey)) {
retval = hookExt->FileSystem->DriverObject->FastIoDispatch->FastIoUnlockAllByKey( retval = hookExt-> FileSystem-> DriverObject-> FastIoDispatch-> FastIoUnlockAllByKey (
FileObject, ProcessId, Key, IoStatus, hookExt->FileSystem); FileObject, ProcessId, Key, IoStatus, hookExt-> FileSystem);
} }
return retval; return retval;
} }
//---------------------------------------------------------------------- / / ------------------------------------------------ ----------------------
// / /
// SymlinkFastIoQueryNetworkOpenInfo / / SymlinkFastIoQueryNetworkOpenInfo
// / /
//---------------------------------------------------------------------- / / ------------------------------------------------ ----------------------
BOOLEAN BOOLEAN
SymlinkFastIoQueryNetworkOpenInfo( SymlinkFastIoQueryNetworkOpenInfo (
IN PFILE_OBJECT FileObject, IN PFILE_OBJECT FileObject,
IN BOOLEAN Wait, IN BOOLEAN Wait,
OUT struct _FILE_NETWORK_OPEN_INFORMATION *Buffer, OUT struct _FILE_NETWORK_OPEN_INFORMATION * Buffer,
OUT PIO_STATUS_BLOCK IoStatus, OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject IN PDEVICE_OBJECT DeviceObject
) )
{ {
BOOLEAN retval = FALSE; BOOLEAN retval = FALSE;
PHOOK_EXTENSION hookExt; PHOOK_EXTENSION hookExt;
PAGED_CODE(); PAGED_CODE ();
if (!DeviceObject) if (! DeviceObject)
return FALSE; return FALSE;
hookExt = DeviceObject->DeviceExtension; hookExt = DeviceObject-> DeviceExtension;
if (FASTIOPRESENT(hookExt, FastIoQueryNetworkOpenInfo)) { if (FASTIOPRESENT (hookExt, FastIoQueryNetworkOpenInfo)) {
retval = hookExt->FileSystem->DriverObject->FastIoDispatch->FastIoQueryNetworkOpenInfo( retval = hookExt-> FileSystem-> DriverObject-> FastIoDispatch-> FastIoQueryNetworkOpenInfo (
FileObject, Wait, Buffer, IoStatus, hookExt->FileSystem); FileObject, Wait, Buffer, IoStatus, hookExt-> FileSystem);
} }
return retval; return retval;
} }
//---------------------------------------------------------------------- / / ------------------------------------------------ ----------------------
// / /
// SymlinkFastIoAcquireForModWrite / / SymlinkFastIoAcquireForModWrite
// / /
//---------------------------------------------------------------------- / / ------------------------------------------------ ----------------------
NTSTATUS NTSTATUS
SymlinkFastIoAcquireForModWrite( SymlinkFastIoAcquireForModWrite (
IN PFILE_OBJECT FileObject, IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER EndingOffset, IN PLARGE_INTEGER EndingOffset,
OUT struct _ERESOURCE **ResourceToRelease, OUT struct _ERESOURCE ** ResourceToRelease,
IN PDEVICE_OBJECT DeviceObject IN PDEVICE_OBJECT DeviceObject
) )
{ {
NTSTATUS retval = STATUS_NOT_IMPLEMENTED; NTSTATUS retval = STATUS_NOT_IMPLEMENTED;
PHOOK_EXTENSION hookExt; PHOOK_EXTENSION hookExt;
if (!DeviceObject) if (! DeviceObject)
return STATUS_NOT_IMPLEMENTED; return STATUS_NOT_IMPLEMENTED;
hookExt = DeviceObject->DeviceExtension; hookExt = DeviceObject-> DeviceExtension;
if (FASTIOPRESENT(hookExt, AcquireForModWrite)) { if (FASTIOPRESENT (hookExt, AcquireForModWrite)) {
retval = hookExt->FileSystem->DriverObject->FastIoDispatch->AcquireForModWrite( retval = hookExt-> FileSystem-> DriverObject-> FastIoDispatch-> AcquireForModWrite (
FileObject, EndingOffset, ResourceToRelease, hookExt->FileSystem); FileObject, EndingOffset, ResourceToRelease, hookExt-> FileSystem);
} }
return retval; return retval;
} }
//---------------------------------------------------------------------- / / ------------------------------------------------ ----------------------
// / /
// SymlinkFastIoMdlRead / / SymlinkFastIoMdlRead
// / /
//---------------------------------------------------------------------- / / ------------------------------------------------ ----------------------
BOOLEAN BOOLEAN
SymlinkFastIoMdlRead( SymlinkFastIoMdlRead (
IN PFILE_OBJECT FileObject, IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER FileOffset,
IN ULONG Length, IN ULONG Length,
IN ULONG LockKey, IN ULONG LockKey,
OUT PMDL *MdlChain, OUT PMDL * MdlChain,
OUT PIO_STATUS_BLOCK IoStatus, OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject IN PDEVICE_OBJECT DeviceObject
) )
{ {
BOOLEAN retval = FALSE; BOOLEAN retval = FALSE;
PHOOK_EXTENSION hookExt; PHOOK_EXTENSION hookExt;
PAGED_CODE(); PAGED_CODE ();
if (!DeviceObject) if (! DeviceObject)
return FALSE; return FALSE;
hookExt = DeviceObject->DeviceExtension; hookExt = DeviceObject-> DeviceExtension;
if (FASTIOPRESENT(hookExt, MdlRead)) { if (FASTIOPRESENT (hookExt, MdlRead)) {
retval = hookExt->FileSystem->DriverObject->FastIoDispatch->MdlRead( retval = hookExt-> FileSystem-> DriverObject-> FastIoDispatch-> MdlRead (
FileObject, FileOffset, Length, LockKey, MdlChain, FileObject, FileOffset, Length, LockKey, MdlChain,
IoStatus, hookExt->FileSystem); IoStatus, hookExt-> FileSystem);
} }
return retval; return retval;
} }
//---------------------------------------------------------------------- / / ------------------------------------------------ ----------------------
// / /
// SymlinkFastIoMdlReadComplete / / SymlinkFastIoMdlReadComplete
// / /
//---------------------------------------------------------------------- / / ------------------------------------------------ ----------------------
BOOLEAN BOOLEAN
SymlinkFastIoMdlReadComplete( SymlinkFastIoMdlReadComplete (
IN PFILE_OBJECT FileObject, IN PFILE_OBJECT FileObject,
IN PMDL MdlChain, IN PMDL MdlChain,
IN PDEVICE_OBJECT DeviceObject IN PDEVICE_OBJECT DeviceObject
) )
{ {
BOOLEAN retval = FALSE; BOOLEAN retval = FALSE;
PHOOK_EXTENSION hookExt; PHOOK_EXTENSION hookExt;
if (!DeviceObject) if (! DeviceObject)
return FALSE; return FALSE;
hookExt = DeviceObject->DeviceExtension; hookExt = DeviceObject-> DeviceExtension;
if (FASTIOPRESENT(hookExt, MdlReadComplete)) { if (FASTIOPRESENT (hookExt, MdlReadComplete)) {
retval = (BOOLEAN) hookExt->FileSystem->DriverObject->FastIoDispatch->MdlReadComplete( retval = (BOOLEAN) hookExt-> FileSystem-> DriverObject-> FastIoDispatch-> MdlReadComplete (
FileObject, MdlChain, hookExt->FileSystem); FileObject, MdlChain, hookExt-> FileSystem);
} }
return retval; return retval;
} }
//---------------------------------------------------------------------- / / ------------------------------------------------ ----------------------
// / /
// SymlinkFastIoPrepareMdlWrite / / SymlinkFastIoPrepareMdlWrite
// / /
//---------------------------------------------------------------------- / / ------------------------------------------------ ----------------------
BOOLEAN BOOLEAN
SymlinkFastIoPrepareMdlWrite( SymlinkFastIoPrepareMdlWrite (
IN PFILE_OBJECT FileObject, IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER FileOffset,
IN ULONG Length, IN ULONG Length,
IN ULONG LockKey, IN ULONG LockKey,
OUT PMDL *MdlChain, OUT PMDL * MdlChain,
OUT PIO_STATUS_BLOCK IoStatus, OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject IN PDEVICE_OBJECT DeviceObject
) )
{ {
BOOLEAN retval = FALSE; BOOLEAN retval = FALSE;
PHOOK_EXTENSION hookExt; PHOOK_EXTENSION hookExt;
PAGED_CODE(); PAGED_CODE ();
if (!DeviceObject) if (! DeviceObject)
return FALSE; return FALSE;
hookExt = DeviceObject->DeviceExtension; hookExt = DeviceObject-> DeviceExtension;
IoStatus->Status = STATUS_NOT_IMPLEMENTED; IoStatus-> Status = STATUS_NOT_IMPLEMENTED;
IoStatus->Information = 0; IoStatus-> Information = 0;
if (FASTIOPRESENT(hookExt, PrepareMdlWrite)) { if (FASTIOPRESENT (hookExt, PrepareMdlWrite)) {
retval = hookExt->FileSystem->DriverObject->FastIoDispatch->PrepareMdlWrite( retval = hookExt-> FileSystem-> DriverObject-> FastIoDispatch-> PrepareMdlWrite (
FileObject, FileOffset, Length, LockKey, MdlChain, IoStatus, FileObject, FileOffset, Length, LockKey, MdlChain, IoStatus,
hookExt->FileSystem); hookExt-> FileSystem);
} }
return retval; return retval;
} }
//---------------------------------------------------------------------- / / ------------------------------------------------ ----------------------
// / /
// SymlinkFastIoMdlWriteComplete / / SymlinkFastIoMdlWriteComplete
// / /
//---------------------------------------------------------------------- / / ------------------------------------------------ ----------------------
BOOLEAN BOOLEAN
SymlinkFastIoMdlWriteComplete( SymlinkFastIoMdlWriteComplete (
IN PFILE_OBJECT FileObject, IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER FileOffset,
IN PMDL MdlChain, IN PMDL MdlChain,
IN PDEVICE_OBJECT DeviceObject IN PDEVICE_OBJECT DeviceObject
) )
{ {
BOOLEAN retval = FALSE; BOOLEAN retval = FALSE;
PHOOK_EXTENSION hookExt; PHOOK_EXTENSION hookExt;
PAGED_CODE(); PAGED_CODE ();
if (!DeviceObject) if (! DeviceObject)
return FALSE; return FALSE;
hookExt = DeviceObject->DeviceExtension; hookExt = DeviceObject-> DeviceExtension;
if (FASTIOPRESENT(hookExt, MdlWriteComplete)) { if (FASTIOPRESENT (hookExt, MdlWriteComplete)) {
retval = hookExt->FileSystem->DriverObject->FastIoDispatch->MdlWriteComplete( retval = hookExt-> FileSystem-> DriverObject-> FastIoDispatch-> MdlWriteComplete (
FileObject, FileOffset, MdlChain, hookExt->FileSystem); FileObject, FileOffset, MdlChain, hookExt-> FileSystem);
} }
return retval; return retval;
} }
//---------------------------------------------------------------------- / / ------------------------------------------------ ----------------------
// / /
// SymlinkFastIoReadCompressed / / SymlinkFastIoReadCompressed
// / /
//---------------------------------------------------------------------- / / ------------------------------------------------ ----------------------
BOOLEAN BOOLEAN
SymlinkFastIoReadCompressed( SymlinkFastIoReadCompressed (
IN PFILE_OBJECT FileObject, IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER FileOffset,
IN ULONG Length, IN ULONG Length,
IN ULONG LockKey, IN ULONG LockKey,
OUT PVOID Buffer, OUT PVOID Buffer,
OUT PMDL *MdlChain, OUT PMDL * MdlChain,
OUT PIO_STATUS_BLOCK IoStatus, OUT PIO_STATUS_BLOCK IoStatus,
OUT struct _COMPRESSED_DATA_INFO *CompressedDataInfo, OUT struct _COMPRESSED_DATA_INFO * CompressedDataInfo,
IN ULONG CompressedDataInfoLength, IN ULONG CompressedDataInfoLength,
IN PDEVICE_OBJECT DeviceObject IN PDEVICE_OBJECT DeviceObject
) )
{ {
BOOLEAN retval = FALSE; BOOLEAN retval = FALSE;
PHOOK_EXTENSION hookExt; PHOOK_EXTENSION hookExt;
PAGED_CODE(); PAGED_CODE ();
if (!DeviceObject) if (! DeviceObject)
return FALSE; return FALSE;
hookExt = DeviceObject->DeviceExtension; hookExt = DeviceObject-> DeviceExtension;
if (FASTIOPRESENT(hookExt, FastIoReadCompressed)) { if (FASTIOPRESENT (hookExt, FastIoReadCompressed)) {
retval = hookExt->FileSystem->DriverObject->FastIoDispatch->FastIoReadCompressed( retval = hookExt-> FileSystem-> DriverObject-> FastIoDispatch-> FastIoReadCompressed (
FileObject, FileOffset, Length, LockKey, Buffer, MdlChain, IoStatus, FileObject, FileOffset, Length, LockKey, Buffer, MdlChain, IoStatus,
CompressedDataInfo, CompressedDataInfoLength, hookExt->FileSystem); CompressedDataInfo, CompressedDataInfoLength, hookExt-> FileSystem);
} }
return retval; return retval;
} }
//---------------------------------------------------------------------- / / ------------------------------------------------ ----------------------
// / /
// SymlinkFastIoWriteCompressed / / SymlinkFastIoWriteCompressed
// / /
//---------------------------------------------------------------------- / / ------------------------------------------------ ----------------------
BOOLEAN BOOLEAN
SymlinkFastIoWriteCompressed( SymlinkFastIoWriteCompressed (
IN PFILE_OBJECT FileObject, IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER FileOffset,
IN ULONG Length, IN ULONG Length,
IN ULONG LockKey, IN ULONG LockKey,
OUT PVOID Buffer, OUT PVOID Buffer,
OUT PMDL *MdlChain, OUT PMDL * MdlChain,
OUT PIO_STATUS_BLOCK IoStatus, OUT PIO_STATUS_BLOCK IoStatus,
OUT struct _COMPRESSED_DATA_INFO *CompressedDataInfo, OUT struct _COMPRESSED_DATA_INFO * CompressedDataInfo,
IN ULONG CompressedDataInfoLength, IN ULONG CompressedDataInfoLength,
IN PDEVICE_OBJECT DeviceObject IN PDEVICE_OBJECT DeviceObject
) )
{ {
BOOLEAN retval = FALSE; BOOLEAN retval = FALSE;
PHOOK_EXTENSION hookExt; PHOOK_EXTENSION hookExt;
PAGED_CODE(); PAGED_CODE ();
if (!DeviceObject) if (! DeviceObject)
return FALSE; return FALSE;
hookExt = DeviceObject->DeviceExtension; hookExt = DeviceObject-> DeviceExtension;
if (FASTIOPRESENT(hookExt, FastIoWriteCompressed)) { if (FASTIOPRESENT (hookExt, FastIoWriteCompressed)) {
retval = hookExt->FileSystem->DriverObject->FastIoDispatch->FastIoWriteCompressed( retval = hookExt-> FileSystem-> DriverObject-> FastIoDispatch-> FastIoWriteCompressed (
FileObject, FileOffset, Length, LockKey, Buffer, MdlChain, IoStatus, FileObject, FileOffset, Length, LockKey, Buffer, MdlChain, IoStatus,
CompressedDataInfo, CompressedDataInfoLength, hookExt->FileSystem); CompressedDataInfo, CompressedDataInfoLength, hookExt-> FileSystem);
} }
return retval; return retval;
} }
//---------------------------------------------------------------------- / / ------------------------------------------------ ----------------------
// / /
// SymlinkFastIoMdlReadCompleteCompressed / / SymlinkFastIoMdlReadCompleteCompressed
// / /
//---------------------------------------------------------------------- / / ------------------------------------------------ ----------------------
BOOLEAN BOOLEAN
SymlinkFastIoMdlReadCompleteCompressed( SymlinkFastIoMdlReadCompleteCompressed (
IN PFILE_OBJECT FileObject, IN PFILE_OBJECT FileObject,
IN PMDL MdlChain, IN PMDL MdlChain,
IN PDEVICE_OBJECT DeviceObject IN PDEVICE_OBJECT DeviceObject
) )
{ {
BOOLEAN retval = FALSE; BOOLEAN retval = FALSE;
PHOOK_EXTENSION hookExt; PHOOK_EXTENSION hookExt;
if (!DeviceObject) if (! DeviceObject)
return FALSE; return FALSE;
hookExt = DeviceObject->DeviceExtension; hookExt = DeviceObject-> DeviceExtension;
if (FASTIOPRESENT(hookExt, MdlReadCompleteCompressed)) { if (FASTIOPRESENT (hookExt, MdlReadCompleteCompressed)) {
retval = hookExt->FileSystem->DriverObject->FastIoDispatch->MdlReadCompleteCompressed( retval = hookExt-> FileSystem-> DriverObject-> FastIoDispatch-> MdlReadCompleteCompressed (
FileObject, MdlChain, hookExt->FileSystem); FileObject, MdlChain, hookExt-> FileSystem);
} }
return retval; return retval;
} }
//---------------------------------------------------------------------- / / ------------------------------------------------ ----------------------
// / /
// SymlinkFastIoMdlWriteCompleteCompressed / / SymlinkFastIoMdlWriteCompleteCompressed
// / /
//---------------------------------------------------------------------- / / ------------------------------------------------ ----------------------
BOOLEAN BOOLEAN
SymlinkFastIoMdlWriteCompleteCompressed( SymlinkFastIoMdlWriteCompleteCompressed (
IN PFILE_OBJECT FileObject, IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER FileOffset,
IN PMDL MdlChain, IN PMDL MdlChain,
IN PDEVICE_OBJECT DeviceObject IN PDEVICE_OBJECT DeviceObject
) )
{ {
BOOLEAN retval = FALSE; BOOLEAN retval = FALSE;
PHOOK_EXTENSION hookExt; PHOOK_EXTENSION hookExt;
if (!DeviceObject) if (! DeviceObject)
return FALSE; return FALSE;
hookExt = DeviceObject->DeviceExtension; hookExt = DeviceObject-> DeviceExtension;
if (FASTIOPRESENT( hookExt, MdlWriteCompleteCompressed)) { if (FASTIOPRESENT (hookExt, MdlWriteCompleteCompressed)) {
retval = hookExt->FileSystem->DriverObject->FastIoDispatch->MdlWriteCompleteCompressed( retval = hookExt-> FileSystem-> DriverObject-> FastIoDispatch-> MdlWriteCompleteCompressed (
FileObject, FileOffset, MdlChain, hookExt->FileSystem); FileObject, FileOffset, MdlChain, hookExt-> FileSystem);
} }
return retval; return retval;
} }
//---------------------------------------------------------------------- / / ------------------------------------------------ ----------------------
// / /
// SymlinkFastIoQueryOpen / / SymlinkFastIoQueryOpen
// / /
// この呼び出しは実際に IRP を渡します! / / This call passes the IRP actually!
// / /
//---------------------------------------------------------------------- / / ------------------------------------------------ ----------------------
BOOLEAN BOOLEAN
SymlinkFastIoQueryOpen( SymlinkFastIoQueryOpen (
IN PIRP Irp, IN PIRP Irp,
OUT PFILE_NETWORK_OPEN_INFORMATION NetworkInformation, OUT PFILE_NETWORK_OPEN_INFORMATION NetworkInformation,
IN PDEVICE_OBJECT DeviceObject IN PDEVICE_OBJECT DeviceObject
) )
{ {
BOOLEAN retval = FALSE; BOOLEAN retval = FALSE;
PHOOK_EXTENSION hookExt; PHOOK_EXTENSION hookExt;
PAGED_CODE(); PAGED_CODE ();
if (!DeviceObject) if (! DeviceObject)
return FALSE; return FALSE;
hookExt = DeviceObject->DeviceExtension;
if (FASTIOPRESENT(hookExt, FastIoQueryOpen)) {
PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp);
PFILE_OBJECT FileObject = currentIrpStack->FileObject;
// / /
// パラメータをスタックの次のレベルに渡す
// / /
*nextIrpStack = *currentIrpStack;
nextIrpStack->DeviceObject = hookExt->FileSystem;
IoSetNextIrpStackLocation(Irp);
retval = hookExt->FileSystem->DriverObject->FastIoDispatch->FastIoQueryOpen(
Irp, NetworkInformation, hookExt->FileSystem);
// / /
// NT 5.0以前の checked ビルドが文句を言うのでスタックの位置を戻す
// / /
Irp->CurrentLocation++;
Irp->Tail.Overlay.CurrentStackLocation++;
} }
return retval;
} }
//----------------------------------------------------------------------
// / /
// SymlinkFastIoReleaseForModWrite
// / /
//----------------------------------------------------------------------
NTSTATUS
SymlinkFastIoReleaseForModWrite(
IN PFILE_OBJECT FileObject,
IN struct _ERESOURCE *ResourceToRelease,
IN PDEVICE_OBJECT DeviceObject
)
{ {
NTSTATUS retval = STATUS_NOT_IMPLEMENTED;
PHOOK_EXTENSION hookExt;
if (!DeviceObject)
return STATUS_NOT_IMPLEMENTED;
hookExt = DeviceObject->DeviceExtension;
if (FASTIOPRESENT(hookExt, ReleaseForModWrite)) {
retval = hookExt->FileSystem->DriverObject->FastIoDispatch->ReleaseForModWrite(
FileObject, ResourceToRelease, hookExt->FileSystem);
} }
return retval;
} }
//----------------------------------------------------------------------
// / /
// SymlinkFastIoAcquireForCcFlush
// / /
//----------------------------------------------------------------------
NTSTATUS
SymlinkFastIoAcquireForCcFlush(
IN PFILE_OBJECT FileObject,
IN PDEVICE_OBJECT DeviceObject
)
{ {
NTSTATUS retval = STATUS_NOT_IMPLEMENTED;
PHOOK_EXTENSION hookExt;
if (!DeviceObject)
return STATUS_NOT_IMPLEMENTED;
hookExt = DeviceObject->DeviceExtension;
if (FASTIOPRESENT(hookExt, AcquireForCcFlush)) {
retval = hookExt->FileSystem->DriverObject->FastIoDispatch->AcquireForCcFlush(
FileObject, hookExt->FileSystem);
} }
return retval;
} }
//----------------------------------------------------------------------
// / /
// SymlinkFastIoReleaseForCcFlush
// / /
//----------------------------------------------------------------------
NTSTATUS
SymlinkFastIoReleaseForCcFlush(
IN PFILE_OBJECT FileObject,
IN PDEVICE_OBJECT DeviceObject
)
{ {
NTSTATUS retval = STATUS_NOT_IMPLEMENTED;
PHOOK_EXTENSION hookExt;
if (!DeviceObject)
return STATUS_NOT_IMPLEMENTED;
hookExt = DeviceObject->DeviceExtension;
if (FASTIOPRESENT(hookExt, ReleaseForCcFlush)) {
retval = hookExt->FileSystem->DriverObject->FastIoDispatch->ReleaseForCcFlush(
FileObject, hookExt->FileSystem);
} }
return retval;
} }
BOOLEAN CallBackFastIoDeviceControl(
IN PFILE_OBJECT FileObject, IN BOOLEAN Wait,
IN PVOID InputBuffer, IN ULONG InputBufferLength,
OUT PVOID OutputBuffer, IN ULONG OutputBufferLength, IN ULONG IoControlCode,
OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject)
{ {
BOOLEAN rv = FALSE;
ULONG i;
PAGED_CODE();
IoStatus->Status = STATUS_SUCCESS; // 成功と仮定
IoStatus->Information = 0; // 何も返されないと仮定
switch (IoControlCode) {
case IOCTL_SYMLINK_VERSION:
// / /
// バージョン番号
// / /
if (OutputBufferLength < sizeof(ULONG)) {
IoStatus->Status = STATUS_BUFFER_TOO_SMALL;
return rv;
} }
*(ULONG *)OutputBuffer = SYMLINKVERSION;
IoStatus->Information = sizeof(ULONG);
break; break;
case IOCTL_SYMLINK_UNLOADQUERY:
#if DBG
SymlinkQueryUnload(IoStatus);
#else // DBG
IoStatus->Information = 1;
#endif // DBG
break; break;
// / /
// 廃止されたIoControlCodeを誤って再利用しないよう
// 明示的に列挙しておく
// / /
case IOCTL_SYMLINK_READ_MEMORY:
// / /
// (廃止)指定したアドレスからデータを読み込む
// fall through
// / /
case IOCTL_SYMLINK_WRITE_MEMORY:
// / /
// (廃止)指定したアドレスにデータを書き込む
// fall through
// / /
case IOCTL_SYMLINK_SETDRIVES:
// / /
// (廃止)ドライブのフックとアンフックを行う
// fall through
// / /
default:
IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST;
break; break;
} }
return TRUE; return TRUE;
} }
//----------------------------------------------------------------------
// / /
// SymlinkFastIoDeviceControl
// / /
//----------------------------------------------------------------------
BOOLEAN
SymlinkFastIoDeviceControl(
IN PFILE_OBJECT FileObject,
IN BOOLEAN Wait,
IN PVOID InputBuffer,
IN ULONG InputBufferLength,
OUT PVOID OutputBuffer,
IN ULONG OutputBufferLength,
IN ULONG IoControlCode,
OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject
)
{ {
BOOLEAN retval = FALSE;
PHOOK_EXTENSION hookExt;
PAGED_CODE();
if (DeviceObject == SymlinkController) {
// / /
// このデバイスへの制御メッセージ
// / /
return CallBackFastIoDeviceControl(FileObject, Wait, InputBuffer, InputBufferLength,
OutputBuffer, OutputBufferLength, IoControlCode, IoStatus, DeviceObject);
} }
// / /
// ファイルシステムからの呼び出し、そのまま渡す
// / /
hookExt = DeviceObject->DeviceExtension;
if (FASTIOPRESENT(hookExt, FastIoDeviceControl)) {
retval = hookExt->FileSystem->DriverObject->FastIoDispatch->FastIoDeviceControl(
FileObject, Wait, InputBuffer, InputBufferLength, OutputBuffer,
OutputBufferLength, IoControlCode, IoStatus, hookExt->FileSystem);
} }
return retval;
} }
//----------------------------------------------------------------------
// / /
// SymlinkFastIoAcquireFile
// / /
//----------------------------------------------------------------------
VOID
SymlinkFastIoAcquireFile(
PFILE_OBJECT FileObject
)
{ {
PDEVICE_OBJECT deviceObject, checkDevice;
PHOOK_EXTENSION hookExt;
// / /
// 自分自身のデバイスオブジェクトを探す
// / /
if (FileObject->DeviceObject->Vpb)
checkDevice = FileObject->DeviceObject->Vpb->DeviceObject;
else else
checkDevice = FileObject->DeviceObject;
while (checkDevice) {
if (checkDevice->DriverObject == SymlinkDriver) {
// / /
// 発見
// / /
deviceObject = checkDevice;
hookExt = deviceObject->DeviceExtension;
if (FASTIOPRESENT(hookExt, AcquireFileForNtCreateSection)) {
hookExt->FileSystem->DriverObject->FastIoDispatch->AcquireFileForNtCreateSection(
FileObject);
} }
return;
} }
checkDevice = checkDevice->AttachedDevice;
} }
} }
//----------------------------------------------------------------------
// / /
// SymlinkFastIoReleaseFile
// / /
//----------------------------------------------------------------------
VOID
SymlinkFastIoReleaseFile(
PFILE_OBJECT FileObject
)
{ {
PDEVICE_OBJECT deviceObject, checkDevice;
PHOOK_EXTENSION hookExt;
// / /
// 自分自身のデバイスオブジェクトを探す
// / /
if (FileObject->DeviceObject->Vpb)
checkDevice = FileObject->DeviceObject->Vpb->DeviceObject;
else else
checkDevice = FileObject->DeviceObject;
while (checkDevice) {
if (checkDevice->DriverObject == SymlinkDriver) {
deviceObject = checkDevice;
hookExt = deviceObject->DeviceExtension;
if (FASTIOPRESENT(hookExt, ReleaseFileForNtCreateSection)) {
hookExt->FileSystem->DriverObject->FastIoDispatch->ReleaseFileForNtCreateSection(FileObject);
} }
return;
} }
checkDevice = checkDevice->AttachedDevice;
} }
} }
//----------------------------------------------------------------------
// / /
// SymlinkFastIoDetachDevice
// / /
// フックしているデバイスが削除されようとしているときに呼び出される。
// これはたとえば、フロッピーがフォーマットされたときに発生する。
// デバイスを切り離して削除しなければならない。
// / /
//----------------------------------------------------------------------
VOID
SymlinkFastIoDetachDevice(
PDEVICE_OBJECT SourceDevice,
PDEVICE_OBJECT TargetDevice
)
{ {
PHOOK_EXTENSION hookExt;
PAGED_CODE();
// / /
// デバイスがこのデバイスの下で削除されようとしているか
// どうか調べる。もしそうなら、そのデバイスが消滅する前にそこから切り離さな
// ければならない
// / /
hookExt = SourceDevice->DeviceExtension;
if (hookExt->FileSystem == TargetDevice) {
if (hookExt->Root) {
KdPrint(("Symlink: Detaching from volume: %wZ\n", &hookExt->Root->Name));
} }
SymlinkDeleteDevice(SourceDevice);
return;
} }
// / /
// FastIoDetachDevice を下位のデバイスに渡すことはない。
// / /
} }
// / /
// 高速 I/O ディスパッチテーブル。NT はファイルシステムドライバが
// 高速 I/O 呼び出しをサポートしていると仮定するため、ファイルシステム
// フィルタドライバにはこのテーブルが存在しなくてはならない。
// / /
static FAST_IO_DISPATCH FastIoHook = {
sizeof(FAST_IO_DISPATCH),
SymlinkFastIoCheckIfPossible,
SymlinkFastIoRead,
SymlinkFastIoWrite,
SymlinkFastIoQueryBasicInfo,
SymlinkFastIoQueryStandardInfo,
SymlinkFastIoLock,
SymlinkFastIoUnlockSingle,
SymlinkFastIoUnlockAll,
SymlinkFastIoUnlockAllByKey,
SymlinkFastIoDeviceControl,
SymlinkFastIoAcquireFile,
SymlinkFastIoReleaseFile,
SymlinkFastIoDetachDevice,
// / /
// NT 4.0 から追加
// / /
SymlinkFastIoQueryNetworkOpenInfo,
SymlinkFastIoAcquireForModWrite,
SymlinkFastIoMdlRead,
SymlinkFastIoMdlReadComplete,
SymlinkFastIoPrepareMdlWrite,
SymlinkFastIoMdlWriteComplete,
SymlinkFastIoReadCompressed,
SymlinkFastIoWriteCompressed,
SymlinkFastIoMdlReadCompleteCompressed,
SymlinkFastIoMdlWriteCompleteCompressed,
SymlinkFastIoQueryOpen,
SymlinkFastIoReleaseForModWrite,
SymlinkFastIoAcquireForCcFlush,
SymlinkFastIoReleaseForCcFlush,
}; };
//----------------------------------------------------------------------
// 通知コールバック関数
//----------------------------------------------------------------------
VOID SymlinkFsNotification(
PDEVICE_OBJECT DeviceObject,
BOOLEAN FsActive
)
{ {
NTSTATUS status;
UNICODE_STRING fsName;
PDEVICE_OBJECT hookDevice, checkDevice, fsDevice;
PHOOK_EXTENSION hookExtension;
PAGED_CODE();
KdPrint(("SymlinkFsNotification(%p, %d)\n", DeviceObject, FsActive ? 1 : 0));
// / /
// デバイスの種類がディスク、CD、テープのいずれかであることを
// 確認(それ以外のデバイスに関して通知されることはないはずであるが)
// リモートコンピュータ上のリンクへのアクセスには未対応
// / /
if (DeviceObject->DeviceType != FILE_DEVICE_DISK_FILE_SYSTEM &&
DeviceObject->DeviceType != FILE_DEVICE_CD_ROM_FILE_SYSTEM &&
DeviceObject->DeviceType != FILE_DEVICE_TAPE_FILE_SYSTEM/* &&
DeviceObject->DeviceType != FILE_DEVICE_NETWORK_FILE_SYSTEM*/)
return;
RtlInitUnicodeString(&fsName, L"\\FileSystem\\Fs_Rec");
if (!RtlCompareUnicodeString(&DeviceObject->DriverObject->DriverName, &fsName, TRUE)) {
// / /
// レコグナイザには接続しない
// / /
return;
} }
RtlInitUnicodeString(&fsName, L"\\FileSystem\\Fastfat");
if (!RtlCompareUnicodeString(&DeviceObject->DriverObject->DriverName, &fsName, TRUE)) {
// / /
// FATはリパースポイントをサポートしない
// Windows 2000 の DFS フィルタのバグを回避するためにも接続しない
// / /
return;
} }
KdPrint(("%wZ (Type=%d)\n", &DeviceObject->DriverObject->DriverName, DeviceObject->DeviceType));
if (FsActive) {
// / /
// リモートファイルシステムにはマウントの概念がない。
// Create IRP は直接コントロールデバイスに飛んでくる。
// / /
if (DeviceObject->DeviceType == FILE_DEVICE_NETWORK_FILE_SYSTEM) {
SymlinkFilterDevice(DeviceObject);
return;
} }
// 以降はローカルファイルシステムの場合
// このデバイスがファイルシステムとして登録されようとしているなら、
// 新しいフィルタデバイスを作成して接続する。フィルタされるデバイスと
// 同じデバイスタイプを使っては*ならない*。さもないと、SISのような
// ものから実際にそのファイルシステムであるとみなされるかもしれない。
status = IoCreateDevice(SymlinkDriver,
sizeof(HOOK_EXTENSION),
NULL,
FILE_DEVICE_FILE_SYSTEM,
0,
FALSE,
&hookDevice);
if (!NT_SUCCESS(status))
return;
KdPrint(("Symlink about to hook onto %p with hook device %p.\n",
DeviceObject, hookDevice));
hookExtension = hookDevice->DeviceExtension;
hookExtension->FileSystem =
IoAttachDeviceToDeviceStack(hookDevice, DeviceObject);
if (hookExtension->FileSystem) {
hookDevice->Flags &= ~DO_DEVICE_INITIALIZING;
KdPrint(("Symlink successfully attached to %p.\n",
hookExtension->FileSystem));
} else { } Else {
KdPrint(("Symlink failed to attach to %p.\n", DeviceObject));
SymlinkDeleteDevice(hookDevice);
} }
// / /
// ファイルシステムドライバのデバイスリストを探索して
// マウント済みのボリュームすべてに接続する。
// / /
for (fsDevice = DeviceObject->DriverObject->DeviceObject;
fsDevice;
fsDevice = fsDevice->NextDevice) {
// コントローラデバイスはスキップ
if (fsDevice == DeviceObject)
continue;
// デバイスの種類を確認
if (fsDevice->DeviceType != FILE_DEVICE_DISK_FILE_SYSTEM &&
fsDevice->DeviceType != FILE_DEVICE_CD_ROM_FILE_SYSTEM &&
fsDevice->DeviceType != FILE_DEVICE_TAPE_FILE_SYSTEM)
continue;
SymlinkFilterDevice(fsDevice);
} }
} else { } Else {
// 引数のデバイスがファイルシステムとして登録解除中であれば、
// 自分をそこから切り離す必要がある。まず、自分が所有していて
// 接続されているデバイスを見つける必要がある。
for (checkDevice = DeviceObject->AttachedDevice;
checkDevice;
checkDevice = checkDevice->AttachedDevice) {
if (checkDevice->DriverObject == SymlinkDriver) {
hookDevice = checkDevice;
KdPrint(("The device going away is attached by Symlink device %p.\n"));
IoDetachDevice(DeviceObject);
hookExtension = hookDevice->DeviceExtension;
hookExtension->FileSystem = NULL;
// デバイスを削除すべきだが、
// 誰かが接続しているときにそうするのは賢くない
if (!hookDevice->AttachedDevice)
SymlinkDeleteDevice(hookDevice);
} }
} }
} }
} }
//----------------------------------------------------------------------
// ディスパッチとフックのエントリポイント
//----------------------------------------------------------------------
VOID SymlinkUnload(IN PDRIVER_OBJECT DriverObject)
{ {
WCHAR deviceLinkBuffer[] = L"\\DosDevices\\SymLink";
UNICODE_STRING deviceLinkUnicodeString;
// / /
// ファイルシステム登録通知の登録を解除
// / /
IoUnregisterFsRegistrationChange(DriverObject, SymlinkFsNotification);
// / /
// シンボリックリンクを削除
// / /
RtlInitUnicodeString(&deviceLinkUnicodeString, deviceLinkBuffer);
IoDeleteSymbolicLink(&deviceLinkUnicodeString);
KdPrint(("Symlink: unloading\n"));
// / /
// デバイスを削除
// / /
while (DriverObject->DeviceObject) {
SymlinkDeleteDevice(DriverObject->DeviceObject);
} }
KdPrint(("Symlink: deleted devices\n"));
// / /
// 割り当てていたメモリをすべて解放
// / /
ExDeletePagedLookasideList(&FullPathLookaside);
} }
//----------------------------------------------------------------------
// / /
// SymlinkResolveLink
// / /
// シンボリックリンクの解決を行う
// / /
//----------------------------------------------------------------------
VOID SymlinkResolveLink(IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp, IN PWSTR fullPathName)
{ {
PREPARSE_DATA_BUFFER reparse;
UNICODE_STRING NewFileName;
PUNICODE_STRING FileName;
UNICODE_STRING directory, unparsed;
BOOLEAN relative;
ULONG bufferLength;
PWSTR ptr;
PAGED_CODE();
// / /
// シンボリックリンクのリパースタグが返ってきたか調べる。違った場合、
// 他のフィルタドライバが処理する可能性があるのでStatus等はそのまま
// / /
if (Irp->IoStatus.Status != STATUS_REPARSE
|| Irp->IoStatus.Information != IO_REPARSE_TAG_SYMLINK) {
return;
} }
// / /
// エラーチェック
// REPARSE_DATA_BUFFERはユーザーモードのコードが好き勝手な値を設定できる
// / /
reparse = (PREPARSE_DATA_BUFFER)Irp->Tail.Overlay.AuxiliaryBuffer;
if (!reparse
|| reparse->ReparseDataLength > MAXIMUM_REPARSE_DATA_BUFFER_SIZE
|| reparse->ReparseDataLength < reparse->SymbolicLinkReparseBuffer.PrintNameOffset
|| reparse->ReparseDataLength < reparse->SymbolicLinkReparseBuffer.PrintNameLength
|| reparse->ReparseDataLength < reparse->SymbolicLinkReparseBuffer.PrintNameOffset
+ reparse->SymbolicLinkReparseBuffer.PrintNameLength) {
Irp->IoStatus.Status = STATUS_IO_REPARSE_DATA_INVALID;
Irp->IoStatus.Information = 0;
KdPrint(("unexpected reprase data buffer.\n"));
return;
} }
// / /
// SRV からの要求であるかどうか調べる
// セキュリティ上の理由からリモートの symlink 解決はクライアント側で
// 行わなくてはならない。
// / /
if (IoIsSystemThread(Irp->Tail.Overlay.Thread)) {
SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
BOOLEAN EffectiveOnly, CopyOnOpen;
//PTOKEN_SOURCE lpTokenSource;
PACCESS_TOKEN lpToken;
lpToken = PsReferenceImpersonationToken(Irp->Tail.Overlay.Thread,
&CopyOnOpen, &EffectiveOnly, &ImpersonationLevel);
if (lpToken) {
KdPrint(("Maybe request from SRV. status=%08x path=%S\n", Irp->IoStatus.Status, fullPathName));
PsDereferenceImpersonationToken(lpToken);
Irp->IoStatus.Status = STATUS_STOPPED_ON_SYMLINK;
Irp->IoStatus.Information = 0;
return;
} }
} }
// / /
// フルパスが必要
// / /
if (!fullPathName || !*fullPathName) {
Irp->IoStatus.Status = STATUS_OBJECT_PATH_NOT_FOUND;
Irp->IoStatus.Information = 0;
KdPrint(("fullPathName is null or empty.\n"));
return;
} }
//if (IrpSp->FileObject) KdPrint((">%.*S\n", IrpSp->FileObject->FileName.Length / sizeof(WCHAR), IrpSp->FileObject->FileName.Buffer));
RtlInitUnicodeString(&directory, fullPathName);
// / /
// Reservedフィールドはパスの未解析の部分のバイト数
// / /
if (directory.Length < reparse->Reserved) {
Irp->IoStatus.Status = STATUS_IO_REPARSE_DATA_INVALID;
Irp->IoStatus.Information = 0;
KdPrint(("directory.Length is insufficient.\n"));
return;
} }
directory.Length -= reparse->Reserved;
// / /
// 末尾がバックスラッシュだったら未解析の部分に含める
// / /
ptr = directory.Buffer + (directory.Length / sizeof(WCHAR)) - 1;
if (ptr > directory.Buffer && *ptr == L'\\') {
ptr--;
directory.Length -= 2;
} }
RtlInitUnicodeString(&unparsed, fullPathName + directory.Length / sizeof(WCHAR));
KdPrint(("%wZ|%wZ\n", &directory.Length, &unparsed));
// / /
// 最終コンポーネントを取り除く
// / /
while (ptr > directory.Buffer) {
if (*ptr == L'\\')
break;
ptr--;
} }
if (ptr <= directory.Buffer) {
Irp->IoStatus.Status = STATUS_OBJECT_PATH_NOT_FOUND;
Irp->IoStatus.Information = 0;
return;
} }
directory.Length = (ptr + 1 - directory.Buffer) * sizeof(WCHAR);
// / /
// リンク先ファイル名の文字列を組み立て
// / /
NewFileName.Length = reparse->SymbolicLinkReparseBuffer.SubstituteNameLength;
NewFileName.MaximumLength = NewFileName.Length + 1;
NewFileName.Buffer = reparse->SymbolicLinkReparseBuffer.PathBuffer +
reparse->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR);
// / /
// 相対パスを解決
// / /
relative = (reparse->SymbolicLinkReparseBuffer.Flags & 1) != 0;
if (relative) {
// / /
// NewFileName の先頭が ..\ だったら削除して
// directory からも一階層取り除く
// / /
while (NewFileName.Length > 3 * sizeof(WCHAR) && NewFileName.Buffer[0] == L'.' &&
NewFileName.Buffer[1] == L'.' && NewFileName.Buffer[2] == L'\\') {
NewFileName.Length -= 3 * sizeof(WCHAR);
NewFileName.MaximumLength -= 3 * sizeof(WCHAR);
NewFileName.Buffer += 3;
// 末尾は必ず \ なのでスキップ
ptr = directory.Buffer + (directory.Length / sizeof(WCHAR)) - 2;
ASSERT(ptr[1] == L'\\');
while (ptr > directory.Buffer) {
if (*ptr == L'\\')
break; break;
ptr--;
} }
if (ptr <= directory.Buffer) {
Irp->IoStatus.Status = STATUS_OBJECT_PATH_NOT_FOUND;
Irp->IoStatus.Information = 0;
return;
} }
directory.Length = (ptr + 1 - directory.Buffer) * sizeof(WCHAR);
} }
bufferLength = directory.Length + NewFileName.Length + unparsed.Length;
} else { } Else {
bufferLength = NewFileName.Length + unparsed.Length;
} }
FileName = &(IrpSp->FileObject->FileName);
//KdPrint(("Reparse(%d): %.*S=>%.*S\n", relative,
//FileName->Length / sizeof(WCHAR), FileName->Buffer,
//NewFileName.Length / sizeof(WCHAR), NewFileName.Buffer));
if (FileName->Length < bufferLength) {
// / /
// 再割り当てを行う
// / /
PVOID FileNameBuffer = ExAllocatePool(NonPagedPool, bufferLength + 1);
if (!FileNameBuffer) {
// / /
// 資源が不足
// / /
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
Irp->IoStatus.Information = 0;
return;
} }
ExFreePool(FileName->Buffer);
FileName->Buffer = FileNameBuffer;
FileName->MaximumLength = (USHORT)bufferLength + 1;
} }
if (relative) {
RtlCopyUnicodeString(FileName, &directory);
RtlAppendUnicodeStringToString(FileName, &NewFileName);
RtlAppendUnicodeStringToString(FileName, &unparsed);
} else { } Else {
RtlCopyUnicodeString(FileName, &NewFileName);
RtlAppendUnicodeStringToString(FileName, &unparsed);
} }
KdPrint(("Reparse(%d): %wZ\n", relative, FileName));
Irp->IoStatus.Information = IO_REPARSE;
} }
//----------------------------------------------------------------------
// / /
// SymlinkQueryAttributeTag
// / /
// FileAttributeTagInformationの問い合わせ結果
// / /
//----------------------------------------------------------------------
VOID SymlinkQueryAttributeTag(IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp)
{ {
PFILE_ATTRIBUTE_TAG_INFORMATION AttrTag;
PAGED_CODE();
// / /
// エラーならここでは何もしない
// / /
if (!NT_SUCCESS(Irp->IoStatus.Status))
return;
// / /
// シンボリックリンク以外ならここでは何もしない
// / /
AttrTag = (PFILE_ATTRIBUTE_TAG_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
if (AttrTag->ReparseTag != IO_REPARSE_TAG_SYMLINK)
return;
// / /
// FileAttributeTagInformationは削除やリネーム前にリパースポイントかどうか、
// またリパースポイントがマウントポイントであるかどうかチェックするために
// 使われる。マウントポイント以外のリパースポイントはすべてリンク先が削除
// されてしまうので、(IsReparseTagNameSurrogateは何のためにあるんだ?)
// リパースポイント属性をクリアしてI/Oマネージャを騙す。
// / /
AttrTag->FileAttributes &= ~(FILE_ATTRIBUTE_REPARSE_POINT);
//KdPrint(("Attr=%08lx, Tag=%08lx\n", AttrTag->FileAttributes, AttrTag->ReparseTag));
} }
//----------------------------------------------------------------------
// / /
// SymlinkHookDone
// / /
// 戻りステータスの情報を得られるようにファイルシステムの操作が
// 完了した後で制御を得る
// / /
//----------------------------------------------------------------------
NTSTATUS
SymlinkHookDone(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
{ {
PIO_STACK_LOCATION IrpSp;
PWSTR fullPathName = (PWSTR)Context;
PAGED_CODE();
// / /
// 要求は完了した - 結果を見る
// / /
IrpSp = IoGetCurrentIrpStackLocation(Irp);
switch (IrpSp->MajorFunction) {
case IRP_MJ_FILE_SYSTEM_CONTROL:
// / /
// エラーのときは何もしない
// / /
if (NT_SUCCESS(Irp->IoStatus.Status))
SymlinkFilterDevice(((PDEVICE_OBJECT)Context)->Vpb->DeviceObject);
break; break;
case IRP_MJ_CREATE:
SymlinkResolveLink(Irp, IrpSp, fullPathName);
// / /
// バッファがあったら解放
// / /
if (fullPathName) {
ExFreeToPagedLookasideList(&FullPathLookaside, fullPathName);
} }
break; break;
case IRP_MJ_QUERY_INFORMATION:
SymlinkQueryAttributeTag(Irp, IrpSp);
break; break;
} }
return Irp->IoStatus.Status;
} }
//----------------------------------------------------------------------
// / /
// SymlinkSignalEvent
// / /
// ディスパッチルーチンへ同期的に戻るためのイベントをシグナルする
// / /
//----------------------------------------------------------------------
NTSTATUS
SymlinkSignalEvent(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
{ {
if (Irp->PendingReturned) {
KeSetEvent((PKEVENT)Context, IO_NO_INCREMENT, FALSE);
} }
return STATUS_MORE_PROCESSING_REQUIRED;
} }
//----------------------------------------------------------------------
// / /
// SymlinkHookRoutine
// / /
// ファイルシステムに送られようとしている呼び出しが何であるか調べる
// メインのフックルーチン
// / /
//----------------------------------------------------------------------
NTSTATUS
SymlinkHookRoutine(
PDEVICE_OBJECT HookDevice,
IN PIRP Irp
)
{ {
PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp);
PFILE_OBJECT FileObject;
PHOOK_EXTENSION hookExt;
PWSTR fullPathName = NULL;
BOOLEAN hookCompletion;
KIRQL oldirql;
PVOID context = NULL;
KEVENT event;
NTSTATUS status;
// / /
// ファイルオブジェクトを IRP から取り出す
// / /
FileObject = currentIrpStack->FileObject;
// / /
// この IRP がどのファイルシステム用なのかの情報を含む
// デバイスエクステンションを指す
// / /
hookExt = HookDevice->DeviceExtension;
hookCompletion = FALSE;
switch (currentIrpStack->MajorFunction) {
case IRP_MJ_FILE_SYSTEM_CONTROL:
// / /
// 接続しているファイルシステムに対するマウント要求を調べる
// スタック位置に空きがあれば完了ルーチンを IRP に設定する
// / /
if (currentIrpStack->MinorFunction == IRP_MN_MOUNT_VOLUME) {
if (hookExt->FileSystem != NULL &&
Irp->CurrentLocation >= HookDevice->StackSize) {
hookCompletion = TRUE;
context = currentIrpStack->Parameters.MountVolume.Vpb->RealDevice;
} }
} }
break; break;
case IRP_MJ_CREATE:
// / /
// test2\test.txt を開こうとしていて
// test2 がリンクの場合、FILE_OPEN_REPARSE_POINT を指定していても
// STATUS_REPARSE が発生するので postCreate の処理は必要
// / /
hookCompletion = TRUE;
fullPathName = ExAllocateFromPagedLookasideList(&FullPathLookaside);
if (fullPathName) {
SymlinkGetFullPath(FileObject, hookExt, fullPathName);
} }
context = fullPathName;
break; break;
case IRP_MJ_QUERY_INFORMATION:
// / /
// 興味があるのは FileAttributeTagInformation のみ
// / /
hookCompletion = currentIrpStack->Parameters.QueryFile.FileInformationClass == FileAttributeTagInformation;
break; break;
} }
// / /
// パラメータを自分の下にあるドライバの次レベルのスタックに渡す
// / /
*nextIrpStack = *currentIrpStack;
#if DBG
// / /
// アンロードが進行中でなければ、
// IRPの戻りステータスを調べられるように完了ルーチンを登録する
// / /
KeAcquireSpinLock(&CountMutex, &oldirql);
#endif # Endif
if (UnloadInProgress)
hookCompletion = FALSE;
if (hookCompletion) {
#if DBG
// / /
// 完了ルーチンを設定するので進行中の IRP の数を増やす
// / /
SymlinkDriver->DriverUnload = NULL;
OutstandingIRPCount++;
//KdPrint(("+%d: %x\n", OutstandingIRPCount, Irp));
#endif // DBG
IoSetCompletionRoutine(Irp, SymlinkSignalEvent, &event, TRUE, TRUE, TRUE);
} else { } Else {
// / /
// 完了ルーチンを設定しない
// / /
IoSetCompletionRoutine(Irp, SymlinkSignalEvent, NULL, FALSE, FALSE, FALSE);
} }
#if DBG
KeReleaseSpinLock(&CountMutex, oldirql);
#endif # Endif
if (hookCompletion) {
KeInitializeEvent(&event, NotificationEvent, FALSE);
status = IoCallDriver(hookExt->FileSystem, Irp);
if (status == STATUS_PENDING) {
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
} }
SymlinkHookDone(HookDevice, Irp, context);
#if DBG
// / /
// IRP の処理を完了したので進行中の IRP の数を減らす
// / /
KeAcquireSpinLock(&CountMutex, &oldirql);
OutstandingIRPCount--;
//KdPrint(("-%d: %x\n", OutstandingIRPCount, Irp));
if (!OutstandingIRPCount)
SymlinkDriver->DriverUnload = SymlinkUnload;
KeReleaseSpinLock(&CountMutex, oldirql);
#endif # Endif
status = Irp->IoStatus.Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
} else { } Else {
status = IoCallDriver(hookExt->FileSystem, Irp);
} }
// / /
// 呼び出し結果を呼び出し元に返す
// / /
return status;
} }
NTSTATUS SymlinkDeviceRoutine(IN PDEVICE_OBJECT DeviceObject, IN PIRP irp)
{ {
PIO_STACK_LOCATION irpStack;
PVOID inputBuffer;
PVOID outputBuffer;
ULONG inputBufferLength;
ULONG outputBufferLength;
ULONG ioControlCode;
NTSTATUS status;
// / /
// 成功と仮定
// / /
irp->IoStatus.Status = STATUS_SUCCESS;
irp->IoStatus.Information = 0;
// / /
// IRP内の現在位置へのポインタを取得
// / /
irpStack = IoGetCurrentIrpStackLocation(irp);
// / /
// 入出力バッファとその長さを取得
// / /
inputBuffer = irp->AssociatedIrp.SystemBuffer;
inputBufferLength = irpStack->Parameters.DeviceIoControl.InputBufferLength;
outputBuffer = irp->AssociatedIrp.SystemBuffer;
outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
switch (irpStack->MajorFunction) {
case IRP_MJ_CREATE:
KdPrint(("Symlink: IRP_MJ_CREATE"));
break; break;
case IRP_MJ_CLOSE:
KdPrint(("Symlink: IRP_MJ_CLOSE"));
break; break;
case IRP_MJ_DEVICE_CONTROL:
KdPrint(("Symlink: IRP_MJ_DEVICE_CONTROL"));
// / /
// 出力バッファがMDLとして渡されていたらそれを取得
// / /
if (irp->MdlAddress) {
outputBuffer = MmGetSystemAddressForMdl(irp->MdlAddress);
} }
// / /
// 高速ハンドラを呼び出すだけ
// / /
CallBackFastIoDeviceControl(irpStack->FileObject, TRUE,
inputBuffer, inputBufferLength,
outputBuffer, outputBufferLength,
ioControlCode, &irp->IoStatus, DeviceObject);
break; break;
} }
// / /
// IoCompleteRequest の後で IRP を参照してはならないので
// ステータスを待避する
// / /
status = irp->IoStatus.Status;
// / /
// IRPを完了する
// / /
IoCompleteRequest(irp, IO_NO_INCREMENT);
return status;
} }
//----------------------------------------------------------------------
// / /
// SymlinkDispatch
// / /
// Irp がどのデバイスに向けられているかに基づいて、ファイルシステム
// フィルタ関数か、自分自身のデバイス処理ルーチンのどちらかを呼び出す。
// / /
//----------------------------------------------------------------------
NTSTATUS
SymlinkDispatch(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{ {
// / /
// リクエストが UI から来たものか、フックしているファイルシステム
// ドライバに向けられたものか判定する。
// / /
if (DeviceObject == SymlinkController) {
return SymlinkDeviceRoutine(DeviceObject, Irp);
} else { } Else {
return SymlinkHookRoutine(DeviceObject, Irp);
} }
} }
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{ {
NTSTATUS status;
PDEVICE_OBJECT device;
WCHAR deviceNameBuffer[] = L"\\Device\\SymLink";
UNICODE_STRING deviceNameUnicodeString;
WCHAR deviceLinkBuffer[] = L"\\DosDevices\\SymLink";
UNICODE_STRING deviceLinkUnicodeString;
ULONG i;
PDEVICE_OBJECT fsDevice;
PFILE_OBJECT fileObject;
KdPrint(("Symlink: entering DriverEntry\n"));
SymlinkDriver = DriverObject;
// / /
// デバイスを作成
// / /
RtlInitUnicodeString(&deviceNameUnicodeString, deviceNameBuffer);
status = IoCreateDevice(DriverObject,
0, // 制御デバイスのデバイス拡張は不要
&deviceNameUnicodeString,
FILE_DEVICE_UNKNOWN,
FILE_DEVICE_SECURE_OPEN,
TRUE,
&device);
if (!NT_SUCCESS(status)) {
KdPrint(("Symlink: failed to create our device!\n"));
return status;
} }
// / /
// 制御デバイスとマーク
// / /
SymlinkController = device;
// / /
// シンボリックリンクを作成
// / /
RtlInitUnicodeString(&deviceLinkUnicodeString, deviceLinkBuffer);
status = IoCreateSymbolicLink(&deviceLinkUnicodeString,
&deviceNameUnicodeString);
if (!NT_SUCCESS(status)) {
KdPrint(("Symlink: IoCreateSymbolicLink failed\n"));
IoDeleteDevice(device);
return status;
} }
// / /
// ディスパッチポイントを作成
// / /
for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) {
DriverObject->MajorFunction[i] = SymlinkDispatch;
} }
#if DBG
DriverObject->DriverUnload = SymlinkUnload;
#endif // DBG
// / /
// 高速 I/O ディスパッチテーブルを設定
// / /
DriverObject->FastIoDispatch = &FastIoHook;
// / /
// 同期オブジェクトを初期化
// / /
#if DBG
KeInitializeSpinLock(&CountMutex);
#endif # Endif
// / /
// ファイル名の lookaside を初期化
// / /
ExInitializePagedLookasideList(&FullPathLookaside, NULL, NULL,
0, MAXPATHLEN * 2, 'lmyS', 0);
// ファイルシステムの有効化/無効化通知を受信できるよう
// このドライバを登録する
status = IoRegisterFsRegistrationChange(DriverObject,
SymlinkFsNotification);
if (!NT_SUCCESS(status)) {
KdPrint(("Symlink: IoRegisterFsRegistrationChange failed\n"));
SymlinkUnload(DriverObject);
return status;
} }
// / /
// Windows 2000 では IoRegisterFsRegistrationChange で
// ロード済みのファイルシステムが通知されないので、
// \Ntfs を自分で開いて通知をシミュレート
// / /
RtlInitUnicodeString(&deviceNameUnicodeString, L"\\Ntfs");
status = IoGetDeviceObjectPointer(&deviceNameUnicodeString, FILE_READ_ATTRIBUTES, &fileObject, &fsDevice);
if (NT_SUCCESS(status)) {
SymlinkFsNotification(fsDevice, TRUE);
ObDereferenceObject(fileObject);
} }
return STATUS_SUCCESS;
} }
<script>_addload(function(){_setupIW();_csi('ja','en','symlink.c');});</script>
Hope that helps somewhat with the looksee. I believe the code was billed as Ln on FAT but reading it now I see it clearly isnt. BAH. I did hear of storing the location info 'separably' but I really didn't like the sound of that either.
FWIW anyway I don't think such a radical solution is the way forward. Most people won't want to use faffy tools. Although a one pass with a certain tool might be okay.
We needs something 'solid'. what? I have no idea ) Thanks for the feedback
tar: ./etc/resolv.conf: File removed before we read it
tar: ./sbin/mount.ntfs-3g: File removed before we read it
tar: ./sbin/mkfs.ntfs: File removed before we read it
tar: ./sbin/mount.lowntfs-3g: File removed before we read it
Results in a 792 Mb final delivery file. - So I was right about 200 - 250% when it starts to even out with bigger numbers.