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 }

Generated on Sat May 15 19:42:11 2004 for test by doxygen 1.3.7