test: unc.c Source File

Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

# unc.c

Go to the documentation of this file.

    00001 /*++
    00002
    00003 Copyright (c) 1991  Microsoft Corporation
    00004
    00005 Module Name:
    00006
    00007     unc.c
    00008
    00009 Abstract:
    00010
    00011     This file contains functions to support multiple UNC providers
    00012     on a single NT machine.
    00013
    00014 Author:
    00015
    00016     Manny Weiser     [MannyW]    20-Dec-1991
    00017
    00018 Revision History:
    00019
    00020     Isaac Heizer     [IsaacHe]   16-Nov-1994  Defer loading the MUP
    00021                                               Rewrite
    00022
    00023     Milan Shah       [MilanS]    7-Mar-1996   Check for Dfs client status
    00024                                               before loading the MUP
    00025
    00026 --*/
    00027
    00028 #include "fsrtlp.h"
    00029 #include <zwapi.h>
    00030 #include <ntddmup.h>
    00031 #include <ntddnull.h>
    00032
    00033 static WCHAR MupRegKey[] = L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Mup";
    00034 static WCHAR UNCSymbolicLink[] = L"\\DosDevices\\UNC";
    00035 static WCHAR DevNull[] = L"\\Device\\Null";
    00036 static WCHAR DevMup[] = DD_MUP_DEVICE_NAME;
    00037
    00038 //
    00039 //  Define a tag for general pool allocations from this module
    00040 //
    00041
    00042 #undef MODULE_POOL_TAG
    00043 #define MODULE_POOL_TAG                  ('nuSF')
    00044
    00045 //
    00046 // Local prototypes
    00047 //
    00048
    00049 NTSTATUS
    00050 FsRtlpRegisterProviderWithMUP
    00051 (
    00052     IN HANDLE mupHandle,
    00053     IN PUNICODE_STRING RedirDevName,
    00054     IN BOOLEAN MailslotsSupported
    00055 );
    00056
    00057 NTSTATUS
    00058 FsRtlpOpenDev(
    00059     IN OUT PHANDLE Handle,
    00060     IN LPWSTR DevNameStr
    00061 );
    00062
    00063 VOID
    00064 FsRtlpSetSymbolicLink(
    00065     IN PUNICODE_STRING DevName OPTIONAL
    00066 );
    00067
    00068 BOOLEAN
    00069 FsRtlpIsDfsEnabled();
    00070
    00071 #ifdef ALLOC_PRAGMA
    00072 #pragma alloc_text(PAGE, FsRtlpRegisterProviderWithMUP)
    00073 #pragma alloc_text(PAGE, FsRtlpOpenDev)
    00074 #pragma alloc_text(PAGE, FsRtlpSetSymbolicLink)
    00075 #pragma alloc_text(PAGE, FsRtlDeregisterUncProvider)
    00076 #pragma alloc_text(PAGE, FsRtlRegisterUncProvider)
    00077 #endif
    00078
    00079 //
    00080 // We defer calling the MUP with the registration data until
    00081 //   the second redir loads and Dfs is disabled.  This structure holds the
    00082 //   data necessary to make that call.
    00083 //
    00084 struct {
    00085     HANDLE MupHandle;
    00086     HANDLE ReturnedHandle;
    00087     UNICODE_STRING RedirDevName;
    00088     BOOLEAN MailslotsSupported;
    00089 } FsRtlpDRD = {0};
    00090
    00091 //
    00092 // Resource protection
    00093 //
    00094 KSEMAPHORE FsRtlpUncSemaphore;
    00095
    00096 //
    00097 // Number of times we've loaded redirs.
    00098 //
    00099 ULONG FsRtlpRedirs = 0;
    00100
    00101
    00102 NTSTATUS
    00103 FsRtlpRegisterProviderWithMUP
    00104 (
    00105     IN HANDLE mupHandle,
    00106     IN PUNICODE_STRING RedirDevName,
    00107     IN BOOLEAN MailslotsSupported
    00108 )
    00109 /*++
    00110
    00111 Routine Description:
    00112
    00113     This private routine does the FSCTL to the MUP to tell it about
    00114         a new redir
    00115
    00116 Arguments:
    00117
    00118     mupHandle - Handle to the MUP
    00119
    00120     RedirDevName - The device name of the redir.
    00121
    00122     MailslotsSupported - If TRUE, this redir supports mailslots.
    00123
    00124 Return Value:
    00125
    00126     NTSTATUS - The status of the operation.
    00127
    00128 --*/
    00129 {
    00130     NTSTATUS status;
    00131     IO_STATUS_BLOCK ioStatusBlock;
    00132     ULONG paramLength;
    00133     PREDIRECTOR_REGISTRATION params;
    00134
    00135     PAGED_CODE();
    00136
    00137     paramLength = sizeof( REDIRECTOR_REGISTRATION ) +
    00138                       RedirDevName->Length;
    00139
    00140     params = ExAllocatePoolWithTag( NonPagedPool, paramLength, MODULE_POOL_TAG );
    00141     if( params == NULL )
    00142         return STATUS_INSUFFICIENT_RESOURCES;
    00143
    00144     params->DeviceNameOffset = sizeof( REDIRECTOR_REGISTRATION );
    00145     params->DeviceNameLength = RedirDevName->Length;
    00146     params->MailslotsSupported = MailslotsSupported;
    00147
    00148     RtlMoveMemory(
    00149         (PCHAR)params + params->DeviceNameOffset,
    00150         RedirDevName->Buffer,
    00151         RedirDevName->Length
    00152         );
    00153
    00154     status = NtFsControlFile(
    00155                  mupHandle,
    00156                  0,
    00157                  NULL,
    00158                  NULL,
    00159                  &ioStatusBlock,
    00160                  FSCTL_MUP_REGISTER_UNC_PROVIDER,
    00161                  params,
    00162                  paramLength,
    00163                  NULL,
    00164                  0
    00165                  );
    00166
    00167     if ( status == STATUS_PENDING ) {
    00168         status = NtWaitForSingleObject( mupHandle, TRUE, NULL );
    00169     }
    00170
    00171     if ( NT_SUCCESS( status ) ) {
    00172         status = ioStatusBlock.Status;
    00173     }
    00174
    00175     ASSERT( NT_SUCCESS( status ) );
    00176
    00177     ExFreePool( params );
    00178
    00179     return status;
    00180 }
    00181
    00182 NTSTATUS
    00183 FsRtlpOpenDev(
    00184     IN OUT PHANDLE Handle,
    00185     IN LPWSTR DevNameStr
    00186 )
    00187 {
    00188     NTSTATUS status;
    00189     UNICODE_STRING DevName;
    00190     OBJECT_ATTRIBUTES objectAttributes;
    00191     IO_STATUS_BLOCK ioStatusBlock;
    00192
    00193     PAGED_CODE();
    00194
    00195     RtlInitUnicodeString( &DevName, DevNameStr );
    00196
    00197     InitializeObjectAttributes(
    00198         &objectAttributes,
    00199         &DevName,
    00200         0,
    00201         0,
    00202         NULL
    00203         );
    00204
    00205     status = ZwCreateFile(
    00206                  Handle,
    00207                  GENERIC_WRITE,
    00208                  &objectAttributes,
    00209                  &ioStatusBlock,
    00210                  NULL,
    00211                  FILE_ATTRIBUTE_NORMAL,
    00212                  FILE_SHARE_READ | FILE_SHARE_WRITE,
    00213                  FILE_OPEN,
    00214                  0,
    00215                  NULL,
    00216                  0
    00217                  );
    00218
    00219     if ( NT_SUCCESS( status ) ) {
    00220         status = ioStatusBlock.Status;
    00221     }
    00222
    00223     if( !NT_SUCCESS( status ) ) {
    00224         *Handle = (HANDLE)-1;
    00225     }
    00226
    00227     return status;
    00228 }
    00229
    00230 VOID
    00231 FsRtlpSetSymbolicLink( IN PUNICODE_STRING DevName OPTIONAL )
    00232 {
    00233     NTSTATUS status;
    00234     UNICODE_STRING UncSymbolicName;
    00235
    00236     PAGED_CODE();
    00237
    00238     RtlInitUnicodeString( &UncSymbolicName, UNCSymbolicLink );
    00239     (VOID)IoDeleteSymbolicLink( &UncSymbolicName );
    00240     if( ARGUMENT_PRESENT( DevName ) ) {
    00241         status = IoCreateSymbolicLink( &UncSymbolicName, DevName );
    00242         ASSERT( NT_SUCCESS( status ) );
    00243     }
    00244 }
    00245
    00246 NTSTATUS
    00247 FsRtlRegisterUncProvider(
    00248     IN OUT PHANDLE MupHandle,
    00249     IN PUNICODE_STRING RedirDevName,
    00250     IN BOOLEAN MailslotsSupported
    00251     )
    00252 /*++
    00253
    00254 Routine Description:
    00255
    00256     This routine registers a redir as a UNC provider.
    00257
    00258 Arguments:
    00259
    00260     Handle - Pointer to a handle.  The handle is returned by the routine
    00261         to be used when calling FsRtlDeregisterUncProvider.
    00262         It is valid only if the routines returns STATUS_SUCCESS.
    00263
    00264     RedirDevName - The device name of the redir.
    00265
    00266     MailslotsSupported - If TRUE, this redir supports mailslots.
    00267
    00268 Return Value:
    00269
    00270     NTSTATUS - The status of the operation.
    00271
    00272 --*/
    00273 {
    00274     NTSTATUS status;
    00275     HANDLE mupHandle = (HANDLE)-1;
    00276     UNICODE_STRING mupDriverName;
    00277     BOOLEAN dfsEnabled;
    00278
    00279     PAGED_CODE();
    00280
    00281     KeWaitForSingleObject(&FsRtlpUncSemaphore, Executive, KernelMode, FALSE, NULL );
    00282
    00283     if (FsRtlpRedirs == 0) {
    00284
    00285         dfsEnabled = FsRtlpIsDfsEnabled();
    00286
    00287         if (dfsEnabled) {
    00288             FsRtlpRedirs = 1;
    00289             RtlZeroMemory((PVOID) &FsRtlpDRD, sizeof(FsRtlpDRD));
    00290         }
    00291
    00292     }
    00293
    00294     switch( FsRtlpRedirs ) {
    00295     case 0:
    00296         //
    00297         // Ok, the MUP isn't there and we don't need to use the
    00298         //   MUP for the first redir.
    00299         //
    00300         // We need to return a handle, but we're not really using the MUP yet.
    00301         //   And we may never use it (if there's only 1 redir).  Return
    00302         //   a handle to the NULL device object, since we're committed to returning
    00303         //   a handle to our caller.  Our caller isn't supposed to do anything with
    00304         //   the handle except to call FsRtlDeregisterUncProvider() with it.
    00305         //
    00306         status = FsRtlpOpenDev( &mupHandle, DevNull );
    00307
    00308         if( !NT_SUCCESS( status ) )
    00309             break;
    00310
    00311         //
    00312         // Save up enough state to allow us to call the MUP later with
    00313         // this registration info if necessary.
    00314         //
    00315         FsRtlpDRD.RedirDevName.Buffer = ExAllocatePoolWithTag( NonPagedPool,
    00316                                                                RedirDevName->MaximumLength,
    00317                                                                MODULE_POOL_TAG );
    00318
    00319         if( FsRtlpDRD.RedirDevName.Buffer == NULL ) {
    00320             status =  STATUS_INSUFFICIENT_RESOURCES;
    00321             break;
    00322         }
    00323
    00324         FsRtlpDRD.RedirDevName.Length = RedirDevName->Length;
    00325         FsRtlpDRD.RedirDevName.MaximumLength = RedirDevName->MaximumLength;
    00326
    00327         RtlMoveMemory(
    00328                 (PCHAR)FsRtlpDRD.RedirDevName.Buffer,
    00329                 RedirDevName->Buffer,
    00330                 RedirDevName->MaximumLength
    00331         );
    00332
    00333         FsRtlpDRD.MailslotsSupported = MailslotsSupported;
    00334         FsRtlpDRD.ReturnedHandle = mupHandle;
    00335         FsRtlpDRD.MupHandle = (HANDLE)-1;
    00336
    00337         //
    00338         // Set the UNC symbolic link to point to the redir we just loaded
    00339         //
    00340         FsRtlpSetSymbolicLink( RedirDevName );
    00341
    00342         break;
    00343
    00344     default:
    00345         //
    00346         // This is the second or later redir load -- MUST use the MUP
    00347         //
    00348         status = FsRtlpOpenDev( &mupHandle, DevMup );
    00349
    00350         if( !NT_SUCCESS( status ) ) {
    00351
    00352             RtlInitUnicodeString( &mupDriverName, MupRegKey );
    00353
    00354             (VOID)ZwLoadDriver( &mupDriverName );
    00355
    00356             status = FsRtlpOpenDev( &mupHandle, DevMup );
    00357             if( !NT_SUCCESS( status ) )
    00358                 break;
    00359         }
    00360
    00361         //
    00362         // See if we need to tell the MUP about the first redir that registered
    00363         //
    00364         if( FsRtlpDRD.RedirDevName.Buffer ) {
    00365
    00366             status = FsRtlpRegisterProviderWithMUP( mupHandle,
    00367                     &FsRtlpDRD.RedirDevName,
    00368                     FsRtlpDRD.MailslotsSupported );
    00369
    00370             if( !NT_SUCCESS( status ) )
    00371                 break;
    00372
    00373             FsRtlpDRD.MupHandle = mupHandle;
    00374
    00375             ExFreePool( FsRtlpDRD.RedirDevName.Buffer );
    00376             FsRtlpDRD.RedirDevName.Buffer = NULL;
    00377
    00378             //
    00379             // Set the UNC symbolic link to point to the MUP
    00380             //
    00381             RtlInitUnicodeString(  &mupDriverName, DevMup );
    00382             FsRtlpSetSymbolicLink( &mupDriverName );
    00383
    00384             status = FsRtlpOpenDev( &mupHandle, DevMup );
    00385
    00386             if( !NT_SUCCESS( status ) )
    00387                 break;
    00388         }
    00389
    00390         //
    00391         //  Pass the request to the MUP for this redir
    00392         //
    00393         status = FsRtlpRegisterProviderWithMUP( mupHandle,
    00394                         RedirDevName,
    00395                         MailslotsSupported );
    00396         break;
    00397
    00398     }
    00399
    00400     if( NT_SUCCESS( status ) ) {
    00401         FsRtlpRedirs++;
    00402         *MupHandle = mupHandle;
    00403
    00404     } else {
    00405         if( mupHandle != (HANDLE)-1 && mupHandle != NULL ) {
    00406             ZwClose( mupHandle );
    00407         }
    00408
    00409         *MupHandle = (HANDLE)-1;
    00410     }
    00411
    00412     KeReleaseSemaphore(&FsRtlpUncSemaphore, 0, 1, FALSE );
    00413     return status;
    00414 }
    00415
    00416
    00417 VOID
    00418 FsRtlDeregisterUncProvider(
    00419     IN HANDLE Handle
    00420     )
    00421
    00422 /*++
    00423
    00424 Routine Description:
    00425
    00426     This routine deregisters a redir as a UNC provider.
    00427
    00428 Arguments:
    00429
    00430     Handle - A handle to the Multiple UNC router, returned by the
    00431         registration call.
    00432
    00433 Return Value:
    00434
    00435     None.
    00436
    00437 --*/
    00438
    00439 {
    00440     NTSTATUS status;
    00441
    00442     PAGED_CODE();
    00443
    00444     if( Handle == (HANDLE)-1 || Handle == NULL )
    00445         return;
    00446
    00447     status = ZwClose( Handle );
    00448
    00449     if( !NT_SUCCESS( status ) ) {
    00450         return;
    00451     }
    00452
    00453     KeWaitForSingleObject(&FsRtlpUncSemaphore, Executive, KernelMode, FALSE, NULL );
    00454
    00455     ASSERT( FsRtlpRedirs > 0 );
    00456
    00457     if( Handle == FsRtlpDRD.ReturnedHandle ) {
    00458
    00459         //
    00460         // The first redir in the system is closing.  Release the state we saved
    00461         //  for it, and pass the close on to the MUP if necessary
    00462         //
    00463
    00464         if( FsRtlpDRD.RedirDevName.Buffer != NULL ) {
    00465             ExFreePool( FsRtlpDRD.RedirDevName.Buffer );
    00466             FsRtlpDRD.RedirDevName.Buffer = NULL;
    00467         }
    00468
    00469         if( FsRtlpDRD.MupHandle != (HANDLE)-1 ) {
    00470             ZwClose( FsRtlpDRD.MupHandle );
    00471             FsRtlpDRD.MupHandle = (HANDLE)-1;
    00472         }
    00473
    00474         FsRtlpDRD.ReturnedHandle = (HANDLE)-1;
    00475
    00476     }
    00477
    00478     if( --FsRtlpRedirs == 0 ) {
    00479         FsRtlpSetSymbolicLink( (PUNICODE_STRING)NULL );
    00480     }
    00481
    00482     KeReleaseSemaphore(&FsRtlpUncSemaphore, 0, 1, FALSE );
    00483 }
    00484
    00485
    00486 BOOLEAN
    00487 FsRtlpIsDfsEnabled()
    00488
    00489 /*++
    00490
    00491 Routine Description:
    00492
    00493     This routine checks a registry key to see if the Dfs client is enabled.
    00494     The client is assumed to be enabled by default, and disabled only if there
    00495     is a registry value indicating that it should be disabled.
    00496
    00497 Arguments:
    00498
    00499     None
    00500
    00501 Return Value:
    00502
    00503     TRUE if Dfs client is enabled, FALSE otherwise.
    00504
    00505 --*/
    00506
    00507 {
    00508     NTSTATUS status;
    00509     HANDLE mupRegHandle;
    00510     OBJECT_ATTRIBUTES objectAttributes;
    00511     ULONG valueSize;
    00512     BOOLEAN dfsEnabled = TRUE;
    00513
    00514     UNICODE_STRING mupRegKey = {
    00515         sizeof(MupRegKey) - sizeof(WCHAR),
    00516         sizeof(MupRegKey),
    00517         MupRegKey};
    00518
    00519 #define DISABLE_DFS_VALUE_NAME  L"DisableDfs"
    00520
    00521     UNICODE_STRING disableDfs = {
    00522         sizeof(DISABLE_DFS_VALUE_NAME) - sizeof(WCHAR),
    00523         sizeof(DISABLE_DFS_VALUE_NAME),
    00524         DISABLE_DFS_VALUE_NAME};
    00525
    00526     struct {
    00527         KEY_VALUE_PARTIAL_INFORMATION Info;
    00528         ULONG Buffer;
    00529     } disableDfsValue;
    00530
    00531
    00532     InitializeObjectAttributes(
    00533         &objectAttributes,
    00534         &mupRegKey,
    00535         OBJ_CASE_INSENSITIVE,
    00536         0,
    00537         NULL
    00538         );
    00539
    00540     status = ZwOpenKey(&mupRegHandle, KEY_READ, &objectAttributes);
    00541
    00542     if (NT_SUCCESS(status)) {
    00543
    00544         status = ZwQueryValueKey(
    00545                     mupRegHandle,
    00546                     &disableDfs,
    00547                     KeyValuePartialInformation,
    00548                     (PVOID) &disableDfsValue,
    00549                     sizeof(disableDfsValue),
    00550                     &valueSize);
    00551
    00552         if (NT_SUCCESS(status) && disableDfsValue.Info.Type == REG_DWORD) {
    00553
    00554             if ( (*((PULONG) disableDfsValue.Info.Data)) == 1 )
    00555                 dfsEnabled = FALSE;
    00556
    00557         }
    00558
    00559         ZwClose( mupRegHandle );
    00560
    00561     }
    00562
    00563     return( dfsEnabled );
    00564
    00565 }