ReactOS  0.4.13-dev-101-g0ca4b50
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 
19 struct
20 {
25 } FsRtlpDRD;
26 
27 BOOLEAN
29 {
30  HANDLE Key;
31  ULONG Length;
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 
116 VOID
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 
134 NTSTATUS
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  *--*/
200 VOID
201 NTAPI
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);
232  FsRtlpDRD.MupHandle = INVALID_HANDLE_VALUE;
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  *--*/
278 NTSTATUS
279 NTAPI
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  */
307  RtlZeroMemory(&FsRtlpDRD, sizeof(FsRtlpDRD));
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 */
338  FsRtlpDRD.MupHandle = INVALID_HANDLE_VALUE;
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 
396 Cleanup:
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;
404  *Handle = DeviceHandle;
405  }
406  else
407  {
408  /* Cleanup in case of failure */
410  {
412  }
413 
415  }
416 
418  return Status;
419 }
HANDLE MupHandle
Definition: unc.c:21
NTSTATUS FsRtlpRegisterProviderWithMUP(IN HANDLE MupHandle, IN PCUNICODE_STRING RedirectorDeviceName, IN BOOLEAN MailslotsSupported)
Definition: unc.c:135
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
_Must_inspect_result_ _Out_ PNDIS_STATUS _In_ NDIS_HANDLE _In_ ULONG _Out_ PNDIS_STRING KeyName
Definition: ndis.h:4693
const uint16_t * PCWSTR
Definition: typedefs.h:55
#define IN
Definition: typedefs.h:38
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_Inout_ PUSB_DEVICE_HANDLE DeviceHandle
Definition: hubbusif.h:121
IN PLARGE_INTEGER IN PLARGE_INTEGER PEPROCESS ULONG Key
Definition: fatprocs.h:2697
ULONG FsRtlpRedirs
Definition: unc.c:17
USHORT MaximumLength
Definition: env_spec_w32.h:370
#define KEY_READ
Definition: nt_native.h:1023
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
uint16_t * PWSTR
Definition: typedefs.h:54
#define TAG_UNC
Definition: tag.h:33
LONG NTSTATUS
Definition: precomp.h:26
#define INVALID_HANDLE_VALUE
Definition: compat.h:391
NTSYSCALLAPI NTSTATUS NTAPI NtFsControlFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, ULONG FsControlCode, PVOID InputBuffer, ULONG InputBufferLength, PVOID OutputBuffer, ULONG OutputBufferLength)
struct _MUP_PROVIDER_REGISTRATION_INFO MUP_PROVIDER_REGISTRATION_INFO
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
WCHAR DeviceName[]
Definition: adapter.cpp:21
NTSTATUS NTAPI KeWaitForSingleObject(IN PVOID Object, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: wait.c:416
#define PAGED_CODE()
Definition: video.h:57
#define FILE_SHARE_READ
Definition: compat.h:125
uint32_t ULONG_PTR
Definition: typedefs.h:63
KSEMAPHORE FsRtlpUncSemaphore
Definition: unc.c:15
BOOLEAN MailslotsSupported
Definition: unc.c:24
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define UNICODE_NULL
#define GENERIC_WRITE
Definition: nt_native.h:90
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
NTSTATUS FsRtlpOpenDev(OUT PHANDLE DeviceHandle, IN PCWSTR DeviceName)
Definition: unc.c:78
struct @1664 FsRtlpDRD
_In_ HANDLE Handle
Definition: extypes.h:390
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
#define BufferSize
Definition: classpnp.h:419
HANDLE NullHandle
Definition: unc.c:22
#define FSCTL_MUP_REGISTER_PROVIDER
Definition: muptypes.h:12
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
BOOLEAN FsRtlpIsDfsEnabled(VOID)
Definition: unc.c:28
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:126
static const WCHAR L[]
Definition: oid.c:1250
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:414
static const WCHAR Cleanup[]
Definition: register.c:80
Status
Definition: gdiplustypes.h:24
#define FILE_OPEN
Definition: from_kernel.h:54
LONG NTAPI KeReleaseSemaphore(IN PKSEMAPHORE Semaphore, IN KPRIORITY Increment, IN LONG Adjustment, IN BOOLEAN Wait)
Definition: semphobj.c:54
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
unsigned int * PULONG
Definition: retypes.h:1
#define DPRINT1
Definition: precomp.h:8
#define OUT
Definition: typedefs.h:39
unsigned int ULONG
Definition: retypes.h:1
#define IO_NO_INCREMENT
Definition: iotypes.h:565
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
VOID FsRtlpSetSymbolicLink(IN PCUNICODE_STRING DeviceName)
Definition: unc.c:117
#define REG_DWORD
Definition: sdbapi.c:596
NTSTATUS NTAPI FsRtlRegisterUncProvider(OUT PHANDLE Handle, IN PCUNICODE_STRING RedirectorDeviceName, IN BOOLEAN MailslotsSupported)
Definition: unc.c:280
UNICODE_STRING RedirectorDeviceName
Definition: unc.c:23
VOID NTAPI FsRtlDeregisterUncProvider(IN HANDLE Handle)
Definition: unc.c:202
NTSYSAPI NTSTATUS NTAPI NtWaitForSingleObject(IN HANDLE hObject, IN BOOLEAN bAlertable, IN PLARGE_INTEGER Timeout)