ReactOS 0.4.15-dev-8061-g57b775e
unc.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/fsrtl/unc.c
5 * PURPOSE: Manages UNC support routines for file system drivers.
6 * PROGRAMMERS: Pierre Schweitzer (pierre@reactos.org)
7 */
8
9/* INCLUDES ******************************************************************/
10
11#include <ntoskrnl.h>
12#define NDEBUG
13#include <debug.h>
14
16
18
19struct
20{
26
29{
30 HANDLE Key;
35 struct
36 {
38 ULONG KeyValue;
39 } KeyQueryOutput;
40
41 /* You recognize MuppIsDfsEnabled()! Congratz :-) */
42 KeyName.Buffer = L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Mup";
43 KeyName.Length = sizeof(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Mup") - sizeof(UNICODE_NULL);
44 KeyName.MaximumLength = sizeof(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Mup");
45
46 /* Simply query registry to get whether DFS is disabled.
47 * If DFS isn't disabled from registry side, assume it is enabled
48 * and go through MUP.
49 * MUP itself might disable it, but that's not our concern
50 * any longer
51 */
53 &KeyName,
55 NULL,
56 NULL);
57 Status = ZwOpenKey(&Key, KEY_READ, &ObjectAttributes);
58 if (!NT_SUCCESS(Status))
59 {
60 return TRUE;
61 }
62
63 KeyName.Buffer = L"DisableDfs";
64 KeyName.Length = sizeof(L"DisableDfs") - sizeof(UNICODE_NULL);
65 KeyName.MaximumLength = sizeof(L"DisableDfs");
66
67 Status = ZwQueryValueKey(Key, &KeyName, KeyValuePartialInformation, &KeyQueryOutput, sizeof(KeyQueryOutput), &Length);
68 ZwClose(Key);
69 if (!NT_SUCCESS(Status) || KeyQueryOutput.KeyInfo.Type != REG_DWORD)
70 {
71 return TRUE;
72 }
73
74 return ((*(PULONG)KeyQueryOutput.KeyInfo.Data) != 1);
75}
76
80{
82 UNICODE_STRING StrDeviceName;
85
86 PAGED_CODE();
87
88 /* Just open the device and return the obtained handle */
89 RtlInitUnicodeString(&StrDeviceName, DeviceName);
91 &StrDeviceName,
92 0,
93 NULL,
94 NULL);
95 Status = ZwCreateFile(DeviceHandle,
99 NULL,
102 FILE_OPEN, 0, NULL, 0);
103 if (NT_SUCCESS(Status))
104 {
106 }
107
108 if (!NT_SUCCESS(Status))
109 {
111 }
112
113 return Status;
114}
115
116VOID
118{
120 UNICODE_STRING UncDevice;
121
122 PAGED_CODE();
123
124 /* Delete the old link, and set the new one if we have a name */
125 RtlInitUnicodeString(&UncDevice, L"\\DosDevices\\UNC");
126 IoDeleteSymbolicLink(&UncDevice);
127 if (DeviceName != NULL)
128 {
131 }
132}
133
138{
142 PMUP_PROVIDER_REGISTRATION_INFO RegistrationInfo;
143
144 PAGED_CODE();
145
146 DPRINT1("FsRtlpRegisterProviderWithMUP(%p, %wZ, %u)\n", (PVOID)MupHandle, RedirectorDeviceName, MailslotsSupported);
147
148 /* We have to be able to store the name and the registration information */
151 if (RegistrationInfo == NULL)
152 {
154 }
155
156 /* Set the information about the provider (including its name) */
159 RegistrationInfo->MailslotsSupported = MailslotsSupported;
160 RtlCopyMemory((PWSTR)((ULONG_PTR)RegistrationInfo + RegistrationInfo->RedirectorDeviceNameOffset),
162
163 /* Call MUP with the registration FSCTL */
166 RegistrationInfo, BufferSize, NULL, 0);
167 if (Status == STATUS_PENDING)
168 {
170 }
171
172 if (NT_SUCCESS(Status))
173 {
175 }
176
177 /* And we're done! */
179 ExFreePoolWithTag(RegistrationInfo, TAG_UNC);
180
181 return Status;
182}
183
184/* PUBLIC FUNCTIONS **********************************************************/
185
186/*++
187 * @name FsRtlDeregisterUncProvider
188 * @implemented
189 *
190 * FILLME
191 *
192 * @param Handle
193 * FILLME
194 *
195 * @return None
196 *
197 * @remarks None
198 *
199 *--*/
200VOID
201NTAPI
203{
204 PAGED_CODE();
205
206 /* We won't work on invalid input */
207 if (Handle == INVALID_HANDLE_VALUE || Handle == 0)
208 {
209 return;
210 }
211
213
214 /* Sanity check: we need to have providers */
215 ASSERT(FsRtlpRedirs > 0);
216
217 /* At that point, we had only one provider at a time */
218 if (Handle == (HANDLE)FsRtlpDRD.NullHandle)
219 {
220 /* Free its name if possible (it might have been overtaken in case of
221 * registration of other UNC provider */
222 if (FsRtlpDRD.RedirectorDeviceName.Buffer != NULL)
223 {
224 ExFreePoolWithTag(FsRtlpDRD.RedirectorDeviceName.Buffer, TAG_UNC);
225 FsRtlpDRD.RedirectorDeviceName.Buffer = NULL;
226 }
227
228 /* Close the handle to MUP */
229 if (FsRtlpDRD.MupHandle != INVALID_HANDLE_VALUE)
230 {
231 ZwClose(FsRtlpDRD.MupHandle);
233 }
234
235 /* Last handle isn't required anymore */
236 FsRtlpDRD.NullHandle = INVALID_HANDLE_VALUE;
237 }
238
239 /* One less provider */
240 --FsRtlpRedirs;
241
242 /* In case we reach no provider anylonger, reset the symbolic link */
243 if (FsRtlpRedirs == 0)
244 {
246 }
247
249
250 /* Final note:
251 * NULL device handle and 'normal' MUP device handle are not closed by
252 * FsRtl. It's up to the user to close them afterwards.
253 * If the handle is leaked, MUP will never be notified about the
254 * unregistration.
255 */
256}
257
258/*++
259 * @name FsRtlRegisterUncProvider
260 * @implemented
261 *
262 * FILLME
263 *
264 * @param Handle
265 * FILLME
266 *
267 * @param RedirectorDeviceName
268 * FILLME
269 *
270 * @param MailslotsSupported
271 * FILLME
272 *
273 * @return None
274 *
275 * @remarks None
276 *
277 *--*/
279NTAPI
283{
286 UNICODE_STRING MupString;
287
288 PAGED_CODE();
289
290 DPRINT1("FsRtlRegisterUncProvider(%p, %wZ, %u)\n", Handle, RedirectorDeviceName, MailslotsSupported);
291
293
294 /* In case no provider was registered yet, check for DFS present.
295 * If DFS is present, we need to go with MUP, whatever the case
296 */
297 if (FsRtlpRedirs == 0)
298 {
299 if (FsRtlpIsDfsEnabled())
300 {
301 DPRINT1("DFS is not disabled. Going through MUP\n");
302
303 /* We've to go with MUP, make sure our internal structure doesn't
304 * contain any leftover data and raise redirs to one, to make sure
305 * we use MUP.
306 */
308 FsRtlpRedirs = 1;
309 }
310 }
311
312 /* In case no UNC provider was already registered,
313 * We'll proceed without MUP and directly redirect
314 * UNC to the provider.
315 */
316 if (FsRtlpRedirs == 0)
317 {
318 /* As we don't provide MUP, just give a handle to NULL device */
319 Status = FsRtlpOpenDev(&DeviceHandle, L"\\Device\\Null");
320 if (!NT_SUCCESS(Status))
321 {
322 goto Cleanup;
323 }
324
325 /* Allocate a buffer big enough to keep a local copy of UNC provider device */
327 if (FsRtlpDRD.RedirectorDeviceName.Buffer == NULL)
328 {
330 goto Cleanup;
331 }
332
333 FsRtlpDRD.RedirectorDeviceName.Length = RedirectorDeviceName->Length;
334 FsRtlpDRD.RedirectorDeviceName.MaximumLength = RedirectorDeviceName->MaximumLength;
336
337 /* We don't have MUP, and copy provider information */
339 FsRtlpDRD.MailslotsSupported = MailslotsSupported;
340 FsRtlpDRD.NullHandle = DeviceHandle;
341
342 /* Set DOS device UNC to use provider device */
344 }
345 else
346 {
347 /* We (will) have several providers, MUP is required */
348 Status = FsRtlpOpenDev(&DeviceHandle, L"\\Device\\Mup");
349 if (!NT_SUCCESS(Status))
350 {
351 /* Opening MUP may have failed because the driver was not loaded, so load it and retry */
352 RtlInitUnicodeString(&MupString, L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Mup");
353 ZwLoadDriver(&MupString);
354 Status = FsRtlpOpenDev(&DeviceHandle, L"\\Device\\Mup");
355 if (!NT_SUCCESS(Status))
356 {
357 goto Cleanup;
358 }
359 }
360
361 /* In case we had a single provider till now, we have to forward the old provider to MUP
362 * And then, register the new one to MUP as well
363 */
364 if (FsRtlpDRD.RedirectorDeviceName.Buffer != NULL)
365 {
366 /* We will only continue if we can register previous provider in MUP */
367 Status = FsRtlpRegisterProviderWithMUP(DeviceHandle, &FsRtlpDRD.RedirectorDeviceName, FsRtlpDRD.MailslotsSupported);
368 if (!NT_SUCCESS(Status))
369 {
370 goto Cleanup;
371 }
372
373 /* Save our Mup handle for later usage */
374 FsRtlpDRD.MupHandle = DeviceHandle;
375
376 /* Release information about previous provider */
377 ExFreePoolWithTag(FsRtlpDRD.RedirectorDeviceName.Buffer, TAG_UNC);
378 FsRtlpDRD.RedirectorDeviceName.Buffer = NULL;
379
380 /* Re-open MUP to have a handle to give back to the user */
381 Status = FsRtlpOpenDev(&DeviceHandle, L"\\Device\\Mup");
382 if (!NT_SUCCESS(Status))
383 {
384 goto Cleanup;
385 }
386 }
387
388 /* Redirect UNC DOS device to MUP */
389 RtlInitUnicodeString(&MupString, L"\\Device\\Mup");
390 FsRtlpSetSymbolicLink(&MupString);
391
392 /* Register new provider */
394 }
395
396Cleanup:
397
398 /* In case of success, increment number of providers and return handle
399 * to the device pointed by UNC DOS device
400 */
401 if (NT_SUCCESS(Status))
402 {
403 ++FsRtlpRedirs;
405 }
406 else
407 {
408 /* Cleanup in case of failure */
410 {
412 }
413
415 }
416
418 return Status;
419}
#define PAGED_CODE()
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
#define BufferSize
Definition: mmc.h:75
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
#define FILE_SHARE_READ
Definition: compat.h:136
static const WCHAR Cleanup[]
Definition: register.c:80
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define NonPagedPool
Definition: env_spec_w32.h:307
#define FILE_OPEN
Definition: from_kernel.h:54
ULONG Handle
Definition: gdb_input.c:15
Status
Definition: gdiplustypes.h:25
_Inout_ PUSB_DEVICE_HANDLE DeviceHandle
Definition: hubbusif.h:121
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
#define ASSERT(a)
Definition: mode.c:44
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define FSCTL_MUP_REGISTER_PROVIDER
Definition: muptypes.h:12
struct _MUP_PROVIDER_REGISTRATION_INFO MUP_PROVIDER_REGISTRATION_INFO
#define KernelMode
Definition: asm.h:34
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
@ KeyValuePartialInformation
Definition: nt_native.h:1182
#define KEY_READ
Definition: nt_native.h:1023
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
NTSYSAPI NTSTATUS NTAPI NtWaitForSingleObject(IN HANDLE hObject, IN BOOLEAN bAlertable, IN PLARGE_INTEGER Timeout)
#define GENERIC_WRITE
Definition: nt_native.h:90
NTSYSAPI NTSTATUS NTAPI NtFsControlFile(IN HANDLE hFile, IN HANDLE hEvent OPTIONAL, IN PIO_APC_ROUTINE IoApcRoutine OPTIONAL, IN PVOID IoApcContext OPTIONAL, OUT PIO_STATUS_BLOCK pIoStatusBlock, IN ULONG DeviceIoControlCode, IN PVOID InBuffer OPTIONAL, IN ULONG InBufferLength, OUT PVOID OutBuffer OPTIONAL, IN ULONG OutBufferLength)
#define UNICODE_NULL
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:455
#define STATUS_PENDING
Definition: ntstatus.h:82
#define L(x)
Definition: ntvdm.h:50
#define REG_DWORD
Definition: sdbapi.c:596
LONG NTAPI KeReleaseSemaphore(IN PKSEMAPHORE Semaphore, IN KPRIORITY Increment, IN LONG Adjustment, IN BOOLEAN Wait)
Definition: semphobj.c:54
USHORT MaximumLength
Definition: env_spec_w32.h:370
#define TAG_UNC
Definition: tag.h:47
uint16_t * PWSTR
Definition: typedefs.h:56
uint32_t * PULONG
Definition: typedefs.h:59
const uint16_t * PCWSTR
Definition: typedefs.h:57
#define NTAPI
Definition: typedefs.h:36
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
HANDLE MupHandle
Definition: unc.c:21
NTSTATUS FsRtlpOpenDev(OUT PHANDLE DeviceHandle, IN PCWSTR DeviceName)
Definition: unc.c:78
ULONG FsRtlpRedirs
Definition: unc.c:17
HANDLE NullHandle
Definition: unc.c:22
UNICODE_STRING RedirectorDeviceName
Definition: unc.c:23
BOOLEAN FsRtlpIsDfsEnabled(VOID)
Definition: unc.c:28
struct @1742 FsRtlpDRD
VOID NTAPI FsRtlDeregisterUncProvider(IN HANDLE Handle)
Definition: unc.c:202
BOOLEAN MailslotsSupported
Definition: unc.c:24
NTSTATUS FsRtlpRegisterProviderWithMUP(IN HANDLE MupHandle, IN PCUNICODE_STRING RedirectorDeviceName, IN BOOLEAN MailslotsSupported)
Definition: unc.c:135
VOID FsRtlpSetSymbolicLink(IN PCUNICODE_STRING DeviceName)
Definition: unc.c:117
KSEMAPHORE FsRtlpUncSemaphore
Definition: unc.c:15
NTSTATUS NTAPI FsRtlRegisterUncProvider(OUT PHANDLE Handle, IN PCUNICODE_STRING RedirectorDeviceName, IN BOOLEAN MailslotsSupported)
Definition: unc.c:280
_Must_inspect_result_ _In_ WDFDEVICE _In_ PCUNICODE_STRING KeyName
Definition: wdfdevice.h:2699
_Must_inspect_result_ _In_ PWDFDEVICE_INIT _In_opt_ PCUNICODE_STRING DeviceName
Definition: wdfdevice.h:3275
_In_ WDFMEMORY _Out_opt_ size_t * BufferSize
Definition: wdfmemory.h:254
#define IO_NO_INCREMENT
Definition: iotypes.h:598
@ Executive
Definition: ketypes.h:415