2 * PROJECT: ReactOS kernel-mode tests
3 * LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory
4 * PURPOSE: Test driver for reparse point operations
5 * PROGRAMMER: Pierre Schweitzer <pierre@reactos.org>
13 #include "IoCreateFile.h"
15 typedef struct _TEST_FCB
17 FSRTL_ADVANCED_FCB_HEADER Header
;
18 SECTION_OBJECT_POINTERS SectionObjectPointers
;
19 FAST_MUTEX HeaderMutex
;
20 } TEST_FCB
, *PTEST_FCB
;
22 static KMT_IRP_HANDLER TestIrpHandler
;
23 static KMT_MESSAGE_HANDLER TestMessageHandler
;
25 static PFILE_OBJECT TestFileObject
;
26 static PDEVICE_OBJECT TestDeviceObject
;
30 _In_ PDRIVER_OBJECT DriverObject
,
31 _In_ PCUNICODE_STRING RegistryPath
,
32 _Out_ PCWSTR
*DeviceName
,
35 NTSTATUS Status
= STATUS_SUCCESS
;
39 UNREFERENCED_PARAMETER(RegistryPath
);
41 *DeviceName
= L
"IoCreateFile";
42 *Flags
= TESTENTRY_NO_EXCLUSIVE_DEVICE
|
43 TESTENTRY_BUFFERED_IO_DEVICE
|
44 TESTENTRY_NO_READONLY_DEVICE
;
46 KmtRegisterIrpHandler(IRP_MJ_CREATE
, NULL
, TestIrpHandler
);
47 KmtRegisterIrpHandler(IRP_MJ_CLEANUP
, NULL
, TestIrpHandler
);
48 KmtRegisterMessageHandler(0, NULL
, TestMessageHandler
);
55 _In_ PDRIVER_OBJECT DriverObject
)
60 static volatile long gNoLinks
= FALSE
;
65 _In_ PDEVICE_OBJECT DeviceObject
,
67 _In_ PIO_STACK_LOCATION IoStack
)
71 CACHE_UNINITIALIZE_EVENT CacheUninitEvent
;
75 DPRINT("IRP %x/%x\n", IoStack
->MajorFunction
, IoStack
->MinorFunction
);
76 ASSERT(IoStack
->MajorFunction
== IRP_MJ_CREATE
||
77 IoStack
->MajorFunction
== IRP_MJ_CLEANUP
);
79 Status
= STATUS_NOT_SUPPORTED
;
80 Irp
->IoStatus
.Information
= 0;
82 if (IoStack
->MajorFunction
== IRP_MJ_CREATE
)
84 ok((IoStack
->Parameters
.Create
.Options
& FILE_OPEN_REPARSE_POINT
) == 0, "FILE_OPEN_REPARSE_POINT set\n");
85 ok((IoStack
->Flags
== 0 && !gNoLinks
) || (IoStack
->Flags
== SL_STOP_ON_SYMLINK
&& gNoLinks
), "IoStack->Flags = %lx\n", IoStack
->Flags
);
87 if (IoStack
->FileObject
->FileName
.Length
>= 2 * sizeof(WCHAR
))
89 TestDeviceObject
= DeviceObject
;
90 TestFileObject
= IoStack
->FileObject
;
92 if (IoStack
->FileObject
->FileName
.Length
>= 2 * sizeof(WCHAR
) &&
93 IoStack
->FileObject
->FileName
.Buffer
[1] == 'M')
95 PREPARSE_DATA_BUFFER Reparse
;
97 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= ExAllocatePoolWithTag(NonPagedPool
, MAXIMUM_REPARSE_DATA_BUFFER_SIZE
, 'FwrI');
98 Reparse
= (PREPARSE_DATA_BUFFER
)Irp
->Tail
.Overlay
.AuxiliaryBuffer
;
100 RtlZeroMemory(Reparse
, MAXIMUM_REPARSE_DATA_BUFFER_SIZE
);
101 Reparse
->ReparseTag
= IO_REPARSE_TAG_MOUNT_POINT
;
102 Reparse
->ReparseDataLength
= 12 + sizeof(L
"\\??\\C:\\Documents and Settings");
103 Reparse
->MountPointReparseBuffer
.SubstituteNameLength
= sizeof(L
"\\??\\C:\\Documents and Settings") - sizeof(UNICODE_NULL
);
104 Reparse
->MountPointReparseBuffer
.PrintNameOffset
= sizeof(L
"\\??\\C:\\Documents and Settings");
105 RtlCopyMemory(Reparse
->MountPointReparseBuffer
.PathBuffer
, L
"\\??\\C:\\Documents and Settings", sizeof(L
"\\??\\C:\\Documents and Settings"));
106 Irp
->IoStatus
.Information
= IO_REPARSE_TAG_MOUNT_POINT
;
107 Status
= STATUS_REPARSE
;
109 else if (IoStack
->FileObject
->FileName
.Length
>= 2 * sizeof(WCHAR
) &&
110 IoStack
->FileObject
->FileName
.Buffer
[1] == 'S')
112 if (IoStack
->Flags
& SL_STOP_ON_SYMLINK
)
114 Status
= STATUS_STOPPED_ON_SYMLINK
;
118 PREPARSE_DATA_BUFFER Reparse
;
120 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= ExAllocatePoolWithTag(NonPagedPool
, MAXIMUM_REPARSE_DATA_BUFFER_SIZE
, 'FwrI');
121 Reparse
= (PREPARSE_DATA_BUFFER
)Irp
->Tail
.Overlay
.AuxiliaryBuffer
;
123 RtlZeroMemory(Reparse
, MAXIMUM_REPARSE_DATA_BUFFER_SIZE
);
124 Reparse
->ReparseTag
= IO_REPARSE_TAG_SYMLINK
;
125 Reparse
->ReparseDataLength
= 12 + sizeof(L
"\\??\\C:\\Documents and Settings");
126 Reparse
->SymbolicLinkReparseBuffer
.SubstituteNameLength
= sizeof(L
"\\??\\C:\\Documents and Settings") - sizeof(UNICODE_NULL
);
127 Reparse
->SymbolicLinkReparseBuffer
.PrintNameOffset
= sizeof(L
"\\??\\C:\\Documents and Settings");
128 RtlCopyMemory(Reparse
->SymbolicLinkReparseBuffer
.PathBuffer
, L
"\\??\\C:\\Documents and Settings", sizeof(L
"\\??\\C:\\Documents and Settings"));
129 Irp
->IoStatus
.Information
= IO_REPARSE_TAG_SYMLINK
;
130 Status
= STATUS_REPARSE
;
135 Fcb
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(*Fcb
), 'FwrI');
136 RtlZeroMemory(Fcb
, sizeof(*Fcb
));
137 ExInitializeFastMutex(&Fcb
->HeaderMutex
);
138 FsRtlSetupAdvancedHeader(&Fcb
->Header
, &Fcb
->HeaderMutex
);
139 Fcb
->Header
.AllocationSize
.QuadPart
= 0;
140 Fcb
->Header
.FileSize
.QuadPart
= 0;
141 Fcb
->Header
.ValidDataLength
.QuadPart
= 0;
142 IoStack
->FileObject
->FsContext
= Fcb
;
143 IoStack
->FileObject
->SectionObjectPointer
= &Fcb
->SectionObjectPointers
;
145 Irp
->IoStatus
.Information
= FILE_OPENED
;
146 Status
= STATUS_SUCCESS
;
149 else if (IoStack
->MajorFunction
== IRP_MJ_CLEANUP
)
151 KeInitializeEvent(&CacheUninitEvent
.Event
, NotificationEvent
, FALSE
);
152 CcUninitializeCacheMap(IoStack
->FileObject
, NULL
, &CacheUninitEvent
);
153 KeWaitForSingleObject(&CacheUninitEvent
.Event
, Executive
, KernelMode
, FALSE
, NULL
);
154 Fcb
= IoStack
->FileObject
->FsContext
;
155 ExFreePoolWithTag(Fcb
, 'FwrI');
156 IoStack
->FileObject
->FsContext
= NULL
;
157 Status
= STATUS_SUCCESS
;
160 Irp
->IoStatus
.Status
= Status
;
161 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
166 static UNICODE_STRING FileObjectFileName
= RTL_CONSTANT_STRING(L
"\\NonSymlinked");
167 static UNICODE_STRING DocumentsAndSettings
= RTL_CONSTANT_STRING(L
"\\Documents and Settings");
172 IN PUNICODE_STRING Path
)
174 OBJECT_ATTRIBUTES ObjectAttributes
;
175 IO_STATUS_BLOCK IoStatusBlock
;
178 PFILE_OBJECT FileObject
;
180 InitializeObjectAttributes(&ObjectAttributes
,
182 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
185 Status
= IoCreateFile(&Handle
,
190 FILE_ATTRIBUTE_NORMAL
,
191 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
193 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_ALERT
,
198 IO_NO_PARAMETER_CHECKING
| (gNoLinks
? IO_STOP_ON_SYMLINK
: 0));
199 if (NT_SUCCESS(Status
))
203 IntStatus
= ObReferenceObjectByHandle(Handle
,
207 (PVOID
*)&FileObject
,
209 ok_eq_hex(IntStatus
, STATUS_SUCCESS
);
210 if (NT_SUCCESS(IntStatus
))
212 ok(RtlCompareUnicodeString(&FileObjectFileName
, &FileObject
->FileName
, TRUE
) == 0 ||
213 RtlCompareUnicodeString(&DocumentsAndSettings
, &FileObject
->FileName
, TRUE
) == 0,
214 "Expected: %wZ or %wZ. Opened: %wZ\n", &FileObjectFileName
, &DocumentsAndSettings
, &FileObject
->FileName
);
215 ObDereferenceObject(FileObject
);
218 IntStatus
= ObCloseHandle(Handle
, KernelMode
);
219 ok_eq_hex(IntStatus
, STATUS_SUCCESS
);
228 IN PDEVICE_OBJECT DeviceObject
,
229 IN ULONG ControlCode
,
230 IN PVOID Buffer OPTIONAL
,
232 IN OUT PSIZE_T OutLength
)
234 NTSTATUS Status
= STATUS_SUCCESS
;
240 case IOCTL_DISABLE_SYMLINK
:
242 if (InterlockedExchange(&gNoLinks
, TRUE
) == TRUE
)
244 Status
= STATUS_UNSUCCESSFUL
;
249 case IOCTL_CALL_CREATE
:
252 UNICODE_STRING PathW
;
254 ok(Buffer
!= NULL
, "Buffer is NULL\n");
255 Path
.Length
= Path
.MaximumLength
= (USHORT
)InLength
;
256 Path
.Buffer
= Buffer
;
258 Status
= RtlAnsiStringToUnicodeString(&PathW
, &Path
, TRUE
);
259 ok_eq_hex(Status
, STATUS_SUCCESS
);
261 Status
= TestIoCreateFile(&PathW
);
263 RtlFreeUnicodeString(&PathW
);
268 return STATUS_NOT_SUPPORTED
;