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

oblink.c File Reference

#include "obp.h"

Go to the source code of this file.

Defines

#define CREATE_SYMBOLIC_LINK   0
#define DELETE_SYMBOLIC_LINK   1
#define MAX_DEPTH   16

Functions

VOID ObpProcessDosDeviceSymbolicLink (POBJECT_SYMBOLIC_LINK SymbolicLink, ULONG Action)
NTSTATUS NtCreateSymbolicLinkObject (OUT PHANDLE LinkHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN PUNICODE_STRING LinkTarget)
NTSTATUS NtOpenSymbolicLinkObject (OUT PHANDLE LinkHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes)
NTSTATUS NtQuerySymbolicLinkObject (IN HANDLE LinkHandle, IN OUT PUNICODE_STRING LinkTarget, OUT PULONG ReturnedLength OPTIONAL)
NTSTATUS ObpParseSymbolicLink (IN PVOID ParseObject, IN PVOID ObjectType, IN PACCESS_STATE AccessState, IN KPROCESSOR_MODE AccessMode, IN ULONG Attributes, IN OUT PUNICODE_STRING CompleteName, IN OUT PUNICODE_STRING RemainingName, IN OUT PVOID Context OPTIONAL, IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL, OUT PVOID *Object)
VOID ObpDeleteSymbolicLink (IN PVOID Object)
VOID ObpDeleteSymbolicLinkName (POBJECT_SYMBOLIC_LINK SymbolicLink)
VOID ObpCreateSymbolicLinkName (POBJECT_SYMBOLIC_LINK SymbolicLink)

Variables

POBJECT_TYPE IoDeviceObjectType


Define Documentation

#define CREATE_SYMBOLIC_LINK   0
 

Definition at line 41 of file oblink.c.

Referenced by ObpCreateSymbolicLinkName(), and ObpProcessDosDeviceSymbolicLink().

#define DELETE_SYMBOLIC_LINK   1
 

Definition at line 42 of file oblink.c.

Referenced by ObpDeleteSymbolicLinkName().

#define MAX_DEPTH   16
 

Definition at line 1118 of file oblink.c.

Referenced by ObpProcessDosDeviceSymbolicLink().


Function Documentation

NTSTATUS NtCreateSymbolicLinkObject OUT PHANDLE  LinkHandle,
IN ACCESS_MASK  DesiredAccess,
IN POBJECT_ATTRIBUTES  ObjectAttributes,
IN PUNICODE_STRING  LinkTarget
 

Definition at line 52 of file oblink.c.

References ExAllocatePoolWithTag, EXCEPTION_EXECUTE_HANDLER, Handle, KeQuerySystemTime(), KernelMode, KPROCESSOR_MODE, NT_SUCCESS, NTSTATUS(), NULL, ObCreateObject(), ObDereferenceObject, ObInsertObject(), ObjectAttributes, ObpSymbolicLinkObjectType, PAGED_CODE, PagedPool, ProbeForRead, ProbeForWriteHandle, RtlInitUnicodeString(), and Status.

Referenced by IopReassignSystemRoot(), ObpCreateDosDevicesDirectory(), and TestParent().

00061 : 00062 00063 This function creates a symbolic link object, sets it initial value to 00064 value specified in the LinkTarget parameter, and opens a handle to the 00065 object with the specified desired access. 00066 00067 Arguments: 00068 00069 LinkHandle - Supplies a pointer to a variable that will receive the 00070 symbolic link object handle. 00071 00072 DesiredAccess - Supplies the desired types of access for the symbolic link 00073 object. 00074 00075 ObjectAttributes - Supplies a pointer to an object attributes structure. 00076 00077 LinkTarget - Supplies the target name for the symbolic link object. 00078 00079 Return Value: 00080 00081 An appropriate status value 00082 00083 --*/ 00084 00085 { 00086 KPROCESSOR_MODE PreviousMode; 00087 NTSTATUS Status; 00088 POBJECT_SYMBOLIC_LINK SymbolicLink; 00089 PVOID Object; 00090 HANDLE Handle; 00091 UNICODE_STRING CapturedLinkTarget; 00092 00093 PAGED_CODE(); 00094 00095 // 00096 // Get previous processor mode and probe output arguments if necessary. 00097 // 00098 00099 PreviousMode = KeGetPreviousMode(); 00100 00101 if (PreviousMode != KernelMode) { 00102 00103 try { 00104 00105 // 00106 // **** we probably don't need to do this first one because 00107 // the ob create object will cause the probe to happen for us 00108 // 00109 00110 ProbeForRead( ObjectAttributes, 00111 sizeof( OBJECT_ATTRIBUTES ), 00112 sizeof( ULONG )); 00113 00114 ProbeForRead( LinkTarget, 00115 sizeof( *LinkTarget ), 00116 sizeof( UCHAR )); 00117 00118 CapturedLinkTarget = *LinkTarget; 00119 00120 ProbeForRead( CapturedLinkTarget.Buffer, 00121 CapturedLinkTarget.MaximumLength, 00122 sizeof( UCHAR )); 00123 00124 ProbeForWriteHandle( LinkHandle ); 00125 00126 } except( EXCEPTION_EXECUTE_HANDLER ) { 00127 00128 return( GetExceptionCode() ); 00129 } 00130 00131 } else { 00132 00133 CapturedLinkTarget = *LinkTarget; 00134 } 00135 00136 // 00137 // Check if there is an odd MaximumLength 00138 // 00139 00140 if (CapturedLinkTarget.MaximumLength % sizeof( WCHAR )) { 00141 00142 // 00143 // Round down the MaximumLength to a valid even size 00144 // 00145 00146 CapturedLinkTarget.MaximumLength = (CapturedLinkTarget.MaximumLength / sizeof( WCHAR )) * sizeof( WCHAR ); 00147 } 00148 00149 // 00150 // Error if link target name length is odd, the length is greater than 00151 // the maximum length, or zero and creating. 00152 // 00153 00154 if ((CapturedLinkTarget.MaximumLength == 0) || 00155 (CapturedLinkTarget.Length > CapturedLinkTarget.MaximumLength) || 00156 (CapturedLinkTarget.Length % sizeof( WCHAR ))) { 00157 00158 KdPrint(( "OB: Invalid symbolic link target - %wZ\n", &CapturedLinkTarget )); 00159 00160 return( STATUS_INVALID_PARAMETER ); 00161 } 00162 00163 // 00164 // Create the symbolic link object 00165 // 00166 00167 Status = ObCreateObject( PreviousMode, 00168 ObpSymbolicLinkObjectType, 00169 ObjectAttributes, 00170 PreviousMode, 00171 NULL, 00172 sizeof( *SymbolicLink ), 00173 0, 00174 0, 00175 (PVOID *)&SymbolicLink ); 00176 00177 if (!NT_SUCCESS( Status )) { 00178 00179 return( Status ); 00180 } 00181 00182 // 00183 // Fill in symbolic link object with link target name string 00184 // 00185 00186 KeQuerySystemTime( &SymbolicLink->CreationTime ); 00187 00188 SymbolicLink->DosDeviceDriveIndex = 0; 00189 SymbolicLink->LinkTargetObject = NULL; 00190 00191 RtlInitUnicodeString( &SymbolicLink->LinkTargetRemaining, NULL ); 00192 00193 SymbolicLink->LinkTarget.MaximumLength = CapturedLinkTarget.MaximumLength; 00194 SymbolicLink->LinkTarget.Length = CapturedLinkTarget.Length; 00195 SymbolicLink->LinkTarget.Buffer = (PWCH)ExAllocatePoolWithTag( PagedPool, 00196 CapturedLinkTarget.MaximumLength, 00197 'tmyS' ); 00198 00199 if (SymbolicLink->LinkTarget.Buffer == NULL) { 00200 00201 ObDereferenceObject( SymbolicLink ); 00202 00203 return STATUS_NO_MEMORY; 00204 } 00205 00206 try { 00207 00208 RtlMoveMemory( SymbolicLink->LinkTarget.Buffer, 00209 CapturedLinkTarget.Buffer, 00210 CapturedLinkTarget.MaximumLength ); 00211 00212 } except( EXCEPTION_EXECUTE_HANDLER ) { 00213 00214 ObDereferenceObject( SymbolicLink ); 00215 00216 return( GetExceptionCode() ); 00217 } 00218 00219 // 00220 // Insert symbolic link object in the current processes object table, 00221 // set symbolic link handle value and return status. 00222 // 00223 00224 Status = ObInsertObject( SymbolicLink, 00225 NULL, 00226 DesiredAccess, 00227 0, 00228 (PVOID *)&Object, 00229 &Handle ); 00230 00231 try { 00232 00233 *LinkHandle = Handle; 00234 00235 } except( EXCEPTION_EXECUTE_HANDLER ) { 00236 00237 // 00238 // Fall through, since we do not want to undo what we have done. 00239 // 00240 } 00241 00242 return( Status ); 00243 }

NTSTATUS NtOpenSymbolicLinkObject OUT PHANDLE  LinkHandle,
IN ACCESS_MASK  DesiredAccess,
IN POBJECT_ATTRIBUTES  ObjectAttributes
 

Definition at line 247 of file oblink.c.

References EXCEPTION_EXECUTE_HANDLER, Handle, KernelMode, KPROCESSOR_MODE, NTSTATUS(), NULL, ObjectAttributes, ObOpenObjectByName(), ObpSymbolicLinkObjectType, PAGED_CODE, ProbeForWriteHandle, and Status.

Referenced by CleanupSessionObjectDirectories(), DumpObjectDirs(), IopReassignSystemRoot(), IopStoreSystemPartitionInformation(), LdrpInitializeProcess(), and SubstituteDeviceName().

00255 : 00256 00257 This function opens a handle to an symbolic link object with the specified 00258 desired access. 00259 00260 Arguments: 00261 00262 LinkHandle - Supplies a pointer to a variable that will receive the 00263 symbolic link object handle. 00264 00265 DesiredAccess - Supplies the desired types of access for the symbolic link 00266 object. 00267 00268 ObjectAttributes - Supplies a pointer to an object attributes structure. 00269 00270 Return Value: 00271 00272 An appropriate status value 00273 00274 --*/ 00275 00276 { 00277 KPROCESSOR_MODE PreviousMode; 00278 NTSTATUS Status; 00279 HANDLE Handle; 00280 00281 PAGED_CODE(); 00282 00283 // 00284 // Get previous processor mode and probe output arguments if necessary. 00285 // The object attributes does not need to be probed because the 00286 // ObOpenObjectByName does the probe for us 00287 // 00288 00289 PreviousMode = KeGetPreviousMode(); 00290 00291 if (PreviousMode != KernelMode) { 00292 00293 try { 00294 00295 ProbeForWriteHandle( LinkHandle ); 00296 00297 } except( EXCEPTION_EXECUTE_HANDLER ) { 00298 00299 return( GetExceptionCode() ); 00300 } 00301 } 00302 00303 // 00304 // Open handle to the symbolic link object with the specified desired 00305 // access, set symbolic link handle value, and return service completion 00306 // status. 00307 // 00308 00309 Status = ObOpenObjectByName( ObjectAttributes, 00310 ObpSymbolicLinkObjectType, 00311 PreviousMode, 00312 NULL, 00313 DesiredAccess, 00314 NULL, 00315 &Handle ); 00316 00317 try { 00318 00319 *LinkHandle = Handle; 00320 00321 } except( EXCEPTION_EXECUTE_HANDLER ) { 00322 00323 // 00324 // Fall through, since we do not want to undo what we have done. 00325 // 00326 } 00327 00328 return( Status ); 00329 }

NTSTATUS NtQuerySymbolicLinkObject IN HANDLE  LinkHandle,
IN OUT PUNICODE_STRING  LinkTarget,
OUT PULONG ReturnedLength  OPTIONAL
 

Definition at line 333 of file oblink.c.

References EXCEPTION_EXECUTE_HANDLER, KernelMode, KPROCESSOR_MODE, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObpEnterObjectTypeMutex, ObpLeaveObjectTypeMutex, ObpSymbolicLinkObjectType, ObReferenceObjectByHandle(), PAGED_CODE, ProbeForRead, ProbeForWrite(), ProbeForWriteUlong, ProbeForWriteUshort, and Status.

Referenced by DumpObjectDirs(), IopReassignSystemRoot(), IopStoreSystemPartitionInformation(), LdrpInitializeProcess(), and SubstituteDeviceName().

00341 : 00342 00343 This function queries the state of a symbolic link object and returns the 00344 requested information in the specified record structure. 00345 00346 Arguments: 00347 00348 LinkHandle - Supplies a handle to a symbolic link object. This handle 00349 must have SYMBOLIC_LINK_QUERY access granted. 00350 00351 LinkTarget - Supplies a pointer to a record that is to receive the 00352 target name of the symbolic link object. 00353 00354 ReturnedLength - Optionally receives the maximum length, in bytes, of 00355 the link target on return 00356 00357 Return Value: 00358 00359 An appropriate status value 00360 00361 --*/ 00362 00363 { 00364 KPROCESSOR_MODE PreviousMode; 00365 NTSTATUS Status; 00366 POBJECT_SYMBOLIC_LINK SymbolicLink; 00367 UNICODE_STRING CapturedLinkTarget; 00368 00369 // 00370 // Get previous processor mode and probe output arguments if necessary. 00371 // 00372 00373 PAGED_CODE(); 00374 00375 PreviousMode = KeGetPreviousMode(); 00376 00377 if (PreviousMode != KernelMode) { 00378 00379 try { 00380 00381 ProbeForRead( LinkTarget, 00382 sizeof( *LinkTarget ), 00383 sizeof( WCHAR ) ); 00384 00385 ProbeForWriteUshort( &LinkTarget->Length ); 00386 00387 ProbeForWriteUshort( &LinkTarget->MaximumLength ); 00388 00389 CapturedLinkTarget = *LinkTarget; 00390 00391 ProbeForWrite( CapturedLinkTarget.Buffer, 00392 CapturedLinkTarget.MaximumLength, 00393 sizeof( UCHAR ) ); 00394 00395 if (ARGUMENT_PRESENT( ReturnedLength )) { 00396 00397 ProbeForWriteUlong( ReturnedLength ); 00398 } 00399 00400 } except( EXCEPTION_EXECUTE_HANDLER ) { 00401 00402 return( GetExceptionCode() ); 00403 } 00404 00405 } else { 00406 00407 CapturedLinkTarget = *LinkTarget; 00408 } 00409 00410 // 00411 // Reference symbolic link object by handle, read current state, deference 00412 // symbolic link object, fill in target name structure and return service 00413 // status. 00414 // 00415 00416 Status = ObReferenceObjectByHandle( LinkHandle, 00417 SYMBOLIC_LINK_QUERY, 00418 ObpSymbolicLinkObjectType, 00419 PreviousMode, 00420 (PVOID *)&SymbolicLink, 00421 NULL ); 00422 00423 if (NT_SUCCESS( Status )) { 00424 00425 ObpEnterObjectTypeMutex( ObpSymbolicLinkObjectType ); 00426 00427 // 00428 // If the caller wants a return length and what we found can easily 00429 // fit in the output buffer then we copy into the output buffer all 00430 // the bytes from the link. 00431 // 00432 // If the caller did not want a return length and we found can still 00433 // easily fit in the output buffer then copy over the bytes that just 00434 // make up the string and nothing extra 00435 // 00436 00437 if ((ARGUMENT_PRESENT( ReturnedLength ) && 00438 (SymbolicLink->LinkTarget.MaximumLength <= CapturedLinkTarget.MaximumLength)) 00439 00440 || 00441 00442 (!ARGUMENT_PRESENT( ReturnedLength ) && 00443 (SymbolicLink->LinkTarget.Length <= CapturedLinkTarget.MaximumLength)) ) { 00444 00445 try { 00446 00447 RtlMoveMemory( CapturedLinkTarget.Buffer, 00448 SymbolicLink->LinkTarget.Buffer, 00449 ARGUMENT_PRESENT( ReturnedLength ) ? SymbolicLink->LinkTarget.MaximumLength 00450 : SymbolicLink->LinkTarget.Length ); 00451 00452 LinkTarget->Length = SymbolicLink->LinkTarget.Length; 00453 00454 if (ARGUMENT_PRESENT( ReturnedLength )) { 00455 00456 *ReturnedLength = SymbolicLink->LinkTarget.MaximumLength; 00457 } 00458 00459 } except( EXCEPTION_EXECUTE_HANDLER ) { 00460 00461 // 00462 // Fall through, since we do cannot undo what we have done. 00463 // 00464 } 00465 00466 } else { 00467 00468 // 00469 // The output buffer is just too small for the link target, but 00470 // we'll tell the user how much is needed if they asked for that 00471 // return value 00472 // 00473 00474 if (ARGUMENT_PRESENT( ReturnedLength )) { 00475 00476 try { 00477 00478 *ReturnedLength = SymbolicLink->LinkTarget.MaximumLength; 00479 00480 } except( EXCEPTION_EXECUTE_HANDLER ) { 00481 00482 // 00483 // Fall through, since we do cannot undo what we have done. 00484 // 00485 } 00486 } 00487 00488 Status = STATUS_BUFFER_TOO_SMALL; 00489 } 00490 00491 ObpLeaveObjectTypeMutex( ObpSymbolicLinkObjectType ); 00492 00493 ObDereferenceObject( SymbolicLink ); 00494 } 00495 00496 return( Status ); 00497 }

VOID ObpCreateSymbolicLinkName POBJECT_SYMBOLIC_LINK  SymbolicLink  ) 
 

Definition at line 1015 of file oblink.c.

References CREATE_SYMBOLIC_LINK, _OBJECT_DIRECTORY::DeviceMap, _OBJECT_HEADER_NAME_INFO::Directory, _OBJECT_SYMBOLIC_LINK::DosDeviceDriveIndex, L, _OBJECT_HEADER_NAME_INFO::Name, NULL, OBJECT_HEADER_TO_NAME_INFO, OBJECT_TO_OBJECT_HEADER, ObpProcessDosDeviceSymbolicLink(), and RtlUpcaseUnicodeChar().

Referenced by ObInsertObject().

01021 : 01022 01023 This routine does extra processing for symbolic links being created in 01024 object directories controlled by device map objects. 01025 01026 This processing consists of: 01027 01028 1. Determine if the name of the symbolic link is a drive letter. 01029 If so, then we will need to update the drive type in the 01030 associated device map object. 01031 01032 2. Process the link target, trying to resolve it into a pointer to 01033 an object other than a object directory object. All object 01034 directories traversed must grant world traverse access other 01035 wise we bail out. If we successfully find a non object 01036 directory object, then reference the object pointer and store it 01037 in the symbolic link object, along with a remaining string if 01038 any. ObpLookupObjectName will used this cache object pointer to 01039 short circuit the name lookup directly to the cached object's 01040 parse routine. For any object directory objects traversed along 01041 the way, increment their symbolic link SymbolicLinkUsageCount 01042 field. This field is used whenever an object directory is 01043 deleted or its security is changed such that it no longer grants 01044 world traverse access. In either case, if the field is non-zero 01045 we walk all the symbolic links and resnap them. 01046 01047 Arguments: 01048 01049 SymbolicLink - pointer to symbolic link object being created. 01050 01051 Return Value: 01052 01053 None. 01054 01055 --*/ 01056 01057 { 01058 POBJECT_HEADER ObjectHeader; 01059 POBJECT_HEADER_NAME_INFO NameInfo; 01060 WCHAR DosDeviceDriveLetter; 01061 ULONG DosDeviceDriveIndex; 01062 01063 // 01064 // Now see if this symbolic link is being created in an object directory 01065 // controlled by a device map object. Since we are only called from 01066 // NtCreateSymbolicLinkObject, after the handle to this symbolic link 01067 // has been created but before it is returned to the caller the handle can't 01068 // be closed while we are executing, unless via a random close, 01069 // So no need to hold the type specific mutex while we look at the name. 01070 // 01071 01072 ObjectHeader = OBJECT_TO_OBJECT_HEADER( SymbolicLink ); 01073 NameInfo = OBJECT_HEADER_TO_NAME_INFO( ObjectHeader ); 01074 01075 if ((NameInfo == NULL) || 01076 (NameInfo->Directory == NULL) || 01077 (NameInfo->Directory->DeviceMap == NULL)) { 01078 01079 return; 01080 } 01081 01082 // 01083 // Here if we are creating a symbolic link in an object directory controlled 01084 // by a device map object. See if this is a drive letter definition. If so 01085 // calculate the drive letter index and remember in the symbolic link object. 01086 // 01087 01088 DosDeviceDriveIndex = 0; 01089 01090 if ((NameInfo->Name.Length == (2 * sizeof( WCHAR ))) && 01091 (NameInfo->Name.Buffer[ 1 ] == L':')) { 01092 01093 DosDeviceDriveLetter = RtlUpcaseUnicodeChar( NameInfo->Name.Buffer[ 0 ] ); 01094 01095 if ((DosDeviceDriveLetter >= L'A') && (DosDeviceDriveLetter <= L'Z')) { 01096 01097 DosDeviceDriveIndex = DosDeviceDriveLetter - L'A'; 01098 DosDeviceDriveIndex += 1; 01099 01100 SymbolicLink->DosDeviceDriveIndex = DosDeviceDriveIndex; 01101 } 01102 } 01103 01104 // 01105 // Now traverse the target path seeing if we can snap the link now. 01106 // 01107 01108 ObpProcessDosDeviceSymbolicLink( SymbolicLink, CREATE_SYMBOLIC_LINK ); 01109 01110 return; 01111 }

VOID ObpDeleteSymbolicLink IN PVOID  Object  ) 
 

Definition at line 904 of file oblink.c.

References ExFreePool(), _OBJECT_SYMBOLIC_LINK::LinkTarget, NULL, and PAGED_CODE.

Referenced by ObInitSystem().

00910 : 00911 00912 This routine is called when a reference to a symbolic link goes to zero. 00913 Its job is to clean up the memory used to the symbolic link string 00914 00915 Arguments: 00916 00917 Object - Supplies a pointer to the symbolic link object being deleted 00918 00919 Return Value: 00920 00921 None. 00922 00923 --*/ 00924 00925 { 00926 POBJECT_SYMBOLIC_LINK SymbolicLink = (POBJECT_SYMBOLIC_LINK)Object; 00927 00928 PAGED_CODE(); 00929 00930 // 00931 // The only cleaning up we need to do is to free the link target 00932 // buffer 00933 // 00934 00935 if (SymbolicLink->LinkTarget.Buffer != NULL) { 00936 00937 ExFreePool( SymbolicLink->LinkTarget.Buffer ); 00938 } 00939 00940 SymbolicLink->LinkTarget.Buffer = NULL; 00941 00942 // 00943 // And return to our caller 00944 // 00945 00946 return; 00947 }

VOID ObpDeleteSymbolicLinkName POBJECT_SYMBOLIC_LINK  SymbolicLink  ) 
 

Definition at line 951 of file oblink.c.

References DELETE_SYMBOLIC_LINK, _OBJECT_SYMBOLIC_LINK::LinkTargetObject, NULL, ObDereferenceObject, ObpEnterRootDirectoryMutex, ObpLeaveRootDirectoryMutex, ObpProcessDosDeviceSymbolicLink(), and ObReferenceObject.

Referenced by ObpDeleteNameCheck().

00957 : 00958 00959 This routine delete the symbolic from the system 00960 00961 Arguments: 00962 00963 SymbolicLink - Supplies a pointer to the object body for the symbolic 00964 link object to delete 00965 00966 Return Value: 00967 00968 None. 00969 00970 --*/ 00971 00972 { 00973 PVOID CapturedLinkTargetObject; 00974 00975 CapturedLinkTargetObject = NULL; 00976 00977 // 00978 // Lock the root directory mutex while we look at the target path to 00979 // prevent names from disappearing out from under us. Also protects 00980 // against collisions with NtCreateSymbolicLink 00981 // 00982 00983 ObpEnterRootDirectoryMutex(); 00984 00985 // 00986 // Capture the link target object and referenced one more time 00987 // to avoid destroying while the RootDirectoryMutex is hold 00988 // 00989 00990 CapturedLinkTargetObject = SymbolicLink->LinkTargetObject; 00991 00992 if (CapturedLinkTargetObject != NULL) { 00993 00994 ObReferenceObject(CapturedLinkTargetObject); 00995 } 00996 00997 ObpProcessDosDeviceSymbolicLink( SymbolicLink, DELETE_SYMBOLIC_LINK ); 00998 00999 ObpLeaveRootDirectoryMutex(); 01000 01001 // 01002 // Remove the extra-reference for the link target object 01003 // 01004 01005 if (CapturedLinkTargetObject != NULL) { 01006 01007 ObDereferenceObject(CapturedLinkTargetObject); 01008 } 01009 01010 return; 01011 }

NTSTATUS ObpParseSymbolicLink IN PVOID  ParseObject,
IN PVOID  ObjectType,
IN PACCESS_STATE  AccessState,
IN KPROCESSOR_MODE  AccessMode,
IN ULONG  Attributes,
IN OUT PUNICODE_STRING  CompleteName,
IN OUT PUNICODE_STRING  RemainingName,
IN OUT PVOID Context  OPTIONAL,
IN PSECURITY_QUALITY_OF_SERVICE SecurityQos  OPTIONAL,
OUT PVOID *  Object
 

Definition at line 501 of file oblink.c.

References ExAllocatePoolWithTag, ExFreePool(), _OBJECT_SYMBOLIC_LINK::LinkTarget, _OBJECT_SYMBOLIC_LINK::LinkTargetObject, _OBJECT_SYMBOLIC_LINK::LinkTargetRemaining, NewName, NonPagedPool, NT_SUCCESS, NTSTATUS(), NULL, ObpEnterRootDirectoryMutex, ObpLeaveRootDirectoryMutex, ObReferenceObjectByPointer(), PAGED_CODE, Status, and USHORT.

Referenced by ObInitSystem(), and ObpLookupObjectName().

00516 : 00517 00518 This is the call back routine for parsing symbolic link objects. It is invoked 00519 as part of ObpLookupObjectName 00520 00521 Arguments: 00522 00523 ParseObject - This will actually be a symbolic link object 00524 00525 ObjectType - Specifies the type of the object to lookup 00526 00527 AccessState - Current access state, describing already granted access 00528 types, the privileges used to get them, and any access types yet to 00529 be granted. The access masks may not contain any generic access 00530 types. 00531 00532 AccessMode - Specifies the callers processor mode 00533 00534 Attributes - Specifies the attributes for the lookup (e.g., case 00535 insensitive) 00536 00537 CompleteName - Supplies a pointer to the complete name that we are trying 00538 to open. On return this could be modified to fit the new reparse 00539 buffer 00540 00541 RemainingName - Supplies a pointer to the remaining name that we are 00542 trying to open. On return this will point to what remains after 00543 we processed the symbolic link. 00544 00545 Context - Unused 00546 00547 SecurityQos - Unused 00548 00549 Object - Receives a pointer to the symbolic link object that we 00550 resolve to 00551 00552 Return Value: 00553 00554 STATUS_REPARSE_OBJECT if the parse object is already a snapped 00555 symbolic link meaning we've modified the remaining name and 00556 and have returned the target object of the symbolic link 00557 00558 00559 STATUS_REPARSE if the parse object has not been snapped. In this 00560 case the Complete name has been modified with the link target 00561 name added in front of the remaining name. The parameters 00562 remaining name and object must now be ignored by the caller 00563 00564 An appropriate error value 00565 00566 --*/ 00567 00568 { 00569 ULONG NewLength; 00570 USHORT Length; 00571 USHORT MaximumLength; 00572 PWCHAR NewName, NewRemainingName; 00573 ULONG InsertAmount; 00574 NTSTATUS Status; 00575 POBJECT_SYMBOLIC_LINK SymbolicLink; 00576 PUNICODE_STRING LinkTargetName; 00577 00578 PAGED_CODE(); 00579 00580 // 00581 // This routine needs to be synchonized with the delete symbolic link 00582 // operation. Which uses the root directory mutex. 00583 // 00584 00585 ObpEnterRootDirectoryMutex(); 00586 00587 try { 00588 00589 *Object = NULL; 00590 00591 // 00592 // If there isn't any name remaining and the caller gave us 00593 // an object type then we'll reference the parse object. If 00594 // this is successful then that's the object we return. Otherwise 00595 // if the status is anything but a type mismatch then we'll 00596 // return that error status 00597 // 00598 00599 if (RemainingName->Length == 0) { 00600 00601 if ( ObjectType ) { 00602 00603 Status = ObReferenceObjectByPointer( ParseObject, 00604 0, 00605 ObjectType, 00606 AccessMode ); 00607 00608 if (NT_SUCCESS( Status )) { 00609 00610 *Object = ParseObject; 00611 00612 leave; 00613 00614 } else if (Status != STATUS_OBJECT_TYPE_MISMATCH) { 00615 00616 leave; 00617 } 00618 } 00619 00620 // 00621 // If the remaining name does not start with a "\" then 00622 // its is illformed and we'll call it a type mismatch 00623 // 00624 00625 } else if (*(RemainingName->Buffer) != OBJ_NAME_PATH_SEPARATOR) { 00626 00627 Status = STATUS_OBJECT_TYPE_MISMATCH; 00628 leave; 00629 } 00630 00631 // 00632 // A symbolic link has been encountered. See if this link has been snapped 00633 // to a particular object. 00634 // 00635 00636 SymbolicLink = (POBJECT_SYMBOLIC_LINK)ParseObject; 00637 00638 if (SymbolicLink->LinkTargetObject != NULL) { 00639 00640 // 00641 // This is a snapped link. Get the remaining portion of the 00642 // symbolic link target, if any. 00643 // 00644 00645 LinkTargetName = &SymbolicLink->LinkTargetRemaining; 00646 00647 if (LinkTargetName->Length == 0) { 00648 00649 // 00650 // Remaining link target string is zero, so return to caller 00651 // quickly with snapped object pointer and remaining object name 00652 // which we haven't touched yet. 00653 // 00654 00655 *Object = SymbolicLink->LinkTargetObject; 00656 00657 Status = STATUS_REPARSE_OBJECT; 00658 leave; 00659 } 00660 00661 // 00662 // We have a snapped symbolic link that has additional text. 00663 // Insert that in front of the current remaining name, preserving 00664 // and text between CompleteName and RemainingName 00665 // 00666 00667 InsertAmount = LinkTargetName->Length; 00668 00669 if ((LinkTargetName->Buffer[ (InsertAmount / sizeof( WCHAR )) - 1 ] == OBJ_NAME_PATH_SEPARATOR) 00670 00671 && 00672 00673 (*(RemainingName->Buffer) == OBJ_NAME_PATH_SEPARATOR)) { 00674 00675 // 00676 // Both the link target name ends in a "\" and the remaining 00677 // starts with a "\" but we only need one when we're done 00678 // 00679 00680 InsertAmount -= sizeof( WCHAR ); 00681 } 00682 00683 // 00684 // **** don't see why we need to bias the differnce between two 00685 // pointers with * sizeof(wchar) 00686 // 00687 00688 NewLength = (ULONG)(((RemainingName->Buffer - CompleteName->Buffer) * sizeof( WCHAR )) + 00689 InsertAmount + 00690 RemainingName->Length); 00691 00692 if (NewLength > 0xFFF0) { 00693 00694 Status = STATUS_NAME_TOO_LONG; 00695 leave; 00696 } 00697 00698 Length = (USHORT)NewLength; 00699 00700 // 00701 // Now check if the new computed length is too big for the input 00702 // buffer containing the complete name 00703 // 00704 00705 if (CompleteName->MaximumLength <= Length) { 00706 00707 // 00708 // The new concatentated name is larger than the buffer supplied for 00709 // the complete name. Allocate space for this new string 00710 // 00711 00712 MaximumLength = Length + sizeof( UNICODE_NULL ); 00713 NewName = ExAllocatePoolWithTag( NonPagedPool, MaximumLength, 'mNbO' ); 00714 00715 if (NewName == NULL) { 00716 00717 Status = STATUS_INSUFFICIENT_RESOURCES; 00718 leave; 00719 } 00720 00721 // 00722 // Calculate the pointer within this buffer for the remaining 00723 // name. This value has not been biased by the new link 00724 // target name 00725 // 00726 00727 NewRemainingName = NewName + (RemainingName->Buffer - CompleteName->Buffer); 00728 00729 // 00730 // Copy over all the names that we've processed so far 00731 // 00732 00733 RtlMoveMemory( NewName, 00734 CompleteName->Buffer, 00735 ((RemainingName->Buffer - CompleteName->Buffer) * sizeof( WCHAR ))); 00736 00737 // 00738 // If we have some remaining names then those over at the 00739 // the location offset to hold the link target name 00740 // 00741 00742 if (RemainingName->Length != 0) { 00743 00744 RtlMoveMemory( (PVOID)((PUCHAR)NewRemainingName + InsertAmount), 00745 RemainingName->Buffer, 00746 RemainingName->Length ); 00747 } 00748 00749 // 00750 // Now insert the link target name 00751 // 00752 00753 RtlMoveMemory( NewRemainingName, LinkTargetName->Buffer, InsertAmount ); 00754 00755 // 00756 // Free the old complete name buffer and reset the input 00757 // strings to use the new buffer 00758 // 00759 00760 ExFreePool( CompleteName->Buffer ); 00761 00762 CompleteName->Buffer = NewName; 00763 CompleteName->Length = Length; 00764 CompleteName->MaximumLength = MaximumLength; 00765 00766 RemainingName->Buffer = NewRemainingName; 00767 RemainingName->Length = Length - (USHORT)((PCHAR)NewRemainingName - (PCHAR)NewName); 00768 RemainingName->MaximumLength = RemainingName->Length + sizeof( UNICODE_NULL ); 00769 00770 } else { 00771 00772 // 00773 // Insert extra text associated with this symbolic link name before 00774 // existing remaining name, if any. 00775 // 00776 // First shove over the remaining name to make a hole for the 00777 // link target name 00778 // 00779 00780 if (RemainingName->Length != 0) { 00781 00782 RtlMoveMemory( (PVOID)((PUCHAR)RemainingName->Buffer + InsertAmount), 00783 RemainingName->Buffer, 00784 RemainingName->Length ); 00785 } 00786 00787 // 00788 // Now insert the link target name 00789 // 00790 00791 RtlMoveMemory( RemainingName->Buffer, LinkTargetName->Buffer, InsertAmount ); 00792 00793 // 00794 // Adjust input strings to account for this inserted text 00795 // 00796 00797 CompleteName->Length += LinkTargetName->Length; 00798 00799 RemainingName->Length += LinkTargetName->Length; 00800 RemainingName->MaximumLength += RemainingName->Length + sizeof( UNICODE_NULL ); 00801 00802 CompleteName->Buffer[ CompleteName->Length / sizeof( WCHAR ) ] = UNICODE_NULL; 00803 } 00804 00805 // 00806 // Return the object address associated with snapped symbolic link 00807 // and the reparse object status code. 00808 // 00809 00810 *Object = SymbolicLink->LinkTargetObject; 00811 00812 Status = STATUS_REPARSE_OBJECT; 00813 leave; 00814 } 00815 00816 // 00817 // The symbolic has not yet been snapped 00818 // 00819 // Compute the size of the new name and check if the name will 00820 // fit in the existing complete name buffer. 00821 // 00822 00823 LinkTargetName = &SymbolicLink->LinkTarget; 00824 NewLength = LinkTargetName->Length + RemainingName->Length; 00825 00826 if (NewLength > 0xFFF0) { 00827 00828 Status = STATUS_NAME_TOO_LONG; 00829 leave; 00830 } 00831 00832 Length = (USHORT)NewLength; 00833 00834 if (CompleteName->MaximumLength <= Length) { 00835 00836 // 00837 // The new concatentated name is larger than the buffer supplied for 00838 // the complete name. 00839 // 00840 00841 MaximumLength = Length + sizeof( UNICODE_NULL ); 00842 NewName = ExAllocatePoolWithTag( NonPagedPool, MaximumLength, 'mNbO' ); 00843 00844 if (NewName == NULL) { 00845 00846 Status = STATUS_INSUFFICIENT_RESOURCES; 00847 leave; 00848 } 00849 00850 } else { 00851 00852 MaximumLength = CompleteName->MaximumLength; 00853 NewName = CompleteName->Buffer; 00854 } 00855 00856 // 00857 // Concatenate the symbolic link name with the remaining name, 00858 // if any. What this does is overwrite the front of the complete 00859 // name up to the remaining name with the links target name 00860 // 00861 00862 if (RemainingName->Length != 0) { 00863 00864 RtlMoveMemory( (PVOID)((PUCHAR)NewName + LinkTargetName->Length), 00865 RemainingName->Buffer, 00866 RemainingName->Length ); 00867 } 00868 00869 RtlMoveMemory( NewName, LinkTargetName->Buffer, LinkTargetName->Length ); 00870 00871 NewName[ Length / sizeof( WCHAR ) ] = UNICODE_NULL; 00872 00873 // 00874 // If a new name buffer was allocated, then free the original complete 00875 // name buffer. 00876 // 00877 00878 if (NewName != CompleteName->Buffer) { 00879 00880 ExFreePool( CompleteName->Buffer ); 00881 } 00882 00883 // 00884 // Set the new complete name buffer parameters and return a reparse 00885 // status. 00886 // 00887 00888 CompleteName->Buffer = NewName; 00889 CompleteName->Length = Length; 00890 CompleteName->MaximumLength = MaximumLength; 00891 00892 Status = STATUS_REPARSE; 00893 00894 } finally { 00895 00896 ObpLeaveRootDirectoryMutex(); 00897 } 00898 00899 return Status; 00900 }

VOID ObpProcessDosDeviceSymbolicLink POBJECT_SYMBOLIC_LINK  SymbolicLink,
ULONG  Action
 

Definition at line 1121 of file oblink.c.

References Action, _DEVICE_OBJECT::Characteristics, CREATE_SYMBOLIC_LINK, _OBJECT_DIRECTORY::DeviceMap, _DEVICE_OBJECT::DeviceType, _OBJECT_HEADER_NAME_INFO::Directory, Directory(), _OBJECT_SYMBOLIC_LINK::DosDeviceDriveIndex, _DEVICE_MAP::DosDevicesDirectory, _DEVICE_MAP::DriveMap, _DEVICE_MAP::DriveType, ExFreePool(), FALSE, IoDeviceObjectType, IoRemoteBootClient, _OBJECT_SYMBOLIC_LINK::LinkTarget, _OBJECT_SYMBOLIC_LINK::LinkTargetObject, _OBJECT_SYMBOLIC_LINK::LinkTargetRemaining, MAX_DEPTH, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObGetObjectSecurity(), OBJECT_HEADER_TO_NAME_INFO, OBJECT_TO_OBJECT_HEADER, ObpDirectoryObjectType, ObpDosDevicesShortName, ObpDosDevicesShortNamePrefix, ObpLookupDirectoryEntry(), ObpRootDirectoryObject, ObpSymbolicLinkObjectType, ObReferenceObject, ObReleaseObjectSecurity(), PsGetCurrentProcess, RtlInitUnicodeString(), SeFastTraverseCheck(), Status, TRUE, _OBJECT_HEADER::Type, and UserMode.

Referenced by ObpCreateSymbolicLinkName(), and ObpDeleteSymbolicLinkName().

01128 : 01129 01130 This function is called whenever a symbolic link is created or deleted 01131 in an object directory controlled by a device map object. 01132 01133 For creates, it attempts to snap the symbolic link to a non-object 01134 directory object. It does this by walking the symbolic link target 01135 string, until it sees a non-directory object or a directory object 01136 that does NOT allow World traverse access. It stores a referenced 01137 pointer to this object in the symbolic link object. It also 01138 increments a count in each of the object directory objects that it 01139 walked over. This count is used to disallow any attempt to remove 01140 World traverse access from a directory object after it has 01141 participated in a snapped symbolic link. 01142 01143 For deletes, it repeats the walk of the target string, decrementing 01144 the count associated with each directory object walked over. It also 01145 dereferences the snapped object pointer. 01146 01147 Arguments: 01148 01149 SymbolicLink - pointer to symbolic link object being created or deleted. 01150 01151 Action - describes whether this is a create or a delete action 01152 01153 Return Value: 01154 01155 None. 01156 01157 --*/ 01158 01159 { 01160 NTSTATUS Status; 01161 PVOID Object; 01162 POBJECT_HEADER ObjectHeader; 01163 POBJECT_HEADER_NAME_INFO NameInfo; 01164 PSECURITY_DESCRIPTOR SecurityDescriptor; 01165 BOOLEAN MemoryAllocated; 01166 UNICODE_STRING RemainingName; 01167 UNICODE_STRING ComponentName; 01168 BOOLEAN HaveWorldTraverseAccess; 01169 ULONG Depth; 01170 POBJECT_DIRECTORY Directories[ MAX_DEPTH ], Directory, ParentDirectory; 01171 PDEVICE_OBJECT DeviceObject; 01172 PDEVICE_MAP DeviceMap = NULL; 01173 ULONG DosDeviceDriveType; 01174 BOOLEAN DeviceMapUsed = FALSE; 01175 01176 01177 Object = NULL; 01178 01179 // 01180 // Check if we are creating a symbolic link or if the link has already 01181 // been snapped 01182 // 01183 01184 if ((Action == CREATE_SYMBOLIC_LINK) || 01185 (SymbolicLink->LinkTargetObject != NULL)) { 01186 01187 ParentDirectory = NULL; 01188 Depth = 0; 01189 Directory = ObpRootDirectoryObject; 01190 RemainingName = SymbolicLink->LinkTarget; 01191 01192 DeviceMap = PsGetCurrentProcess()->DeviceMap; 01193 01194 01195 ReCalcDeviceMap: 01196 01197 if (DeviceMap) { 01198 01199 01200 if (!((ULONG_PTR)(RemainingName.Buffer) & (sizeof(ULONGLONG)-1)) 01201 01202 && 01203 01204 (DeviceMap->DosDevicesDirectory != NULL )) { 01205 01206 // 01207 // Check if the object name is actually equal to the 01208 // global dos devices short name prefix "\??\" 01209 // 01210 01211 if ((RemainingName.Length >= ObpDosDevicesShortName.Length) 01212 01213 && 01214 01215 (*(PULONGLONG)(RemainingName.Buffer) == ObpDosDevicesShortNamePrefix.QuadPart)) { 01216 01217 // 01218 // The user gave us the dos short name prefix so we'll 01219 // look down the directory, and start the search at the 01220 // dos device directory 01221 // 01222 01223 Directory = DeviceMap->DosDevicesDirectory; 01224 01225 RemainingName.Buffer += (ObpDosDevicesShortName.Length / sizeof( WCHAR )); 01226 RemainingName.Length -= ObpDosDevicesShortName.Length; 01227 01228 DeviceMapUsed = TRUE; 01229 01230 } 01231 } 01232 } 01233 01234 // 01235 // The following loop will dissect the link target checking 01236 // that each directory exists and that we have access to 01237 // the directory. When we pop out the local directories 01238 // array will contain a list of directories that we need 01239 // to traverse to process this action. 01240 // 01241 01242 while (TRUE) { 01243 01244 // 01245 // Gobble up the "\" in the remaining name 01246 // 01247 01248 if (*(RemainingName.Buffer) == OBJ_NAME_PATH_SEPARATOR) { 01249 01250 RemainingName.Buffer++; 01251 RemainingName.Length -= sizeof( OBJ_NAME_PATH_SEPARATOR ); 01252 } 01253 01254 // 01255 // And dissect the name into its first component and any 01256 // remaining part 01257 // 01258 01259 ComponentName = RemainingName; 01260 01261 while (RemainingName.Length != 0) { 01262 01263 if (*(RemainingName.Buffer) == OBJ_NAME_PATH_SEPARATOR) { 01264 01265 break; 01266 } 01267 01268 RemainingName.Buffer++; 01269 RemainingName.Length -= sizeof( OBJ_NAME_PATH_SEPARATOR ); 01270 } 01271 01272 ComponentName.Length -= RemainingName.Length; 01273 01274 if (ComponentName.Length == 0) { 01275 01276 return; 01277 } 01278 01279 // 01280 // See if we have world traverse access to look this name up 01281 // 01282 01283 if (ParentDirectory != NULL) { 01284 01285 HaveWorldTraverseAccess = FALSE; 01286 01287 // 01288 // Obtain the object's security descriptor 01289 // 01290 01291 Status = ObGetObjectSecurity( ParentDirectory, 01292 &SecurityDescriptor, 01293 &MemoryAllocated ); 01294 01295 if (NT_SUCCESS( Status )) { 01296 01297 // 01298 // Check to see if WORLD has TRAVERSE access and then release 01299 // the security descriptor 01300 // 01301 01302 HaveWorldTraverseAccess = SeFastTraverseCheck( SecurityDescriptor, 01303 DIRECTORY_TRAVERSE, 01304 UserMode ); 01305 01306 ObReleaseObjectSecurity( SecurityDescriptor, 01307 MemoryAllocated ); 01308 } 01309 01310 if (!HaveWorldTraverseAccess) { 01311 01312 Object = NULL; 01313 break; 01314 } 01315 01316 if (Depth >= MAX_DEPTH) { 01317 01318 Object = NULL; 01319 break; 01320 } 01321 01322 Directories[ Depth++ ] = ParentDirectory; 01323 } 01324 01325 // 01326 // Look this component name up in this directory. If not found, then 01327 // bail. 01328 // 01329 01330 Object = ObpLookupDirectoryEntry( Directory, &ComponentName, 0 ); 01331 01332 if (Object == NULL) { 01333 01334 break; 01335 } 01336 01337 // 01338 // See if this is a object directory object. If so, keep going 01339 // 01340 01341 ObjectHeader = OBJECT_TO_OBJECT_HEADER( Object ); 01342 01343 if (ObjectHeader->Type == ObpDirectoryObjectType) { 01344 01345 ParentDirectory = Directory; 01346 Directory = (POBJECT_DIRECTORY)Object; 01347 01348 } else if ((ObjectHeader->Type == ObpSymbolicLinkObjectType) && 01349 (((POBJECT_SYMBOLIC_LINK)Object)->DosDeviceDriveIndex == 0)) { 01350 01351 // 01352 // Found a symbolic link to another symbolic link that is 01353 // not already snapped. So switch to its target string 01354 // so we can chase down the real device object 01355 // 01356 01357 ParentDirectory = NULL; 01358 Depth = 0; 01359 Directory = ObpRootDirectoryObject; 01360 RemainingName = ((POBJECT_SYMBOLIC_LINK)Object)->LinkTarget; 01361 01362 goto ReCalcDeviceMap; 01363 01364 } else { 01365 01366 // 01367 // Not an object directory object, or a symbolic link to an 01368 // unsnapped symbolic link, so all done. Exit the loop 01369 // 01370 01371 break; 01372 } 01373 } 01374 01375 // 01376 // Done walking the target path. Now update the counts associated 01377 // with each directory object walked over. 01378 // 01379 01380 while (Depth--) { 01381 01382 Directory = Directories[ Depth ]; 01383 01384 if (Action == CREATE_SYMBOLIC_LINK) { 01385 01386 if (Object != NULL) { 01387 01388 Directory->SymbolicLinkUsageCount += 1; 01389 } 01390 01391 } else { 01392 01393 Directory->SymbolicLinkUsageCount -= 1; 01394 } 01395 } 01396 } 01397 01398 // 01399 // Done processing symbolic link target path. Update symbolic link 01400 // object as appropriate for passed in reason 01401 // 01402 01403 // 01404 // If this is a drive letter symbolic link, get the address of the device 01405 // map object that is controlling the containing object directory so we 01406 // can update the drive type in the device map. 01407 // 01408 01409 DeviceMap = NULL; 01410 01411 if (SymbolicLink->DosDeviceDriveIndex != 0) { 01412 01413 ObjectHeader = OBJECT_TO_OBJECT_HEADER( SymbolicLink ); 01414 NameInfo = OBJECT_HEADER_TO_NAME_INFO( ObjectHeader ); 01415 01416 if (NameInfo != NULL && NameInfo->Directory) { 01417 01418 DeviceMap = NameInfo->Directory->DeviceMap; 01419 } 01420 } 01421 01422 // 01423 // Check if we are creating a symbolic link 01424 // 01425 01426 if (Action == CREATE_SYMBOLIC_LINK) { 01427 01428 DosDeviceDriveType = DOSDEVICE_DRIVE_CALCULATE; 01429 01430 if (Object != NULL) { 01431 01432 01433 // 01434 // We only want to do snapping for console session. When we create a 01435 // remote session all the symbolic links stored in the console dos devices 01436 // directory (\??) are copied into the per session DosDevices object directory 01437 // (\Session<id>\DosDevices). We don't want to do snapping for the copied 01438 // symbolic links since for each copy we will increment the ref count on the 01439 // target object. All these counts have to go to zero before the device can be 01440 // deleted. 01441 // 01442 if ((PsGetCurrentProcess()->SessionId == 0) || (DeviceMapUsed)) { 01443 // 01444 // Create action. Store a referenced pointer to the snapped object 01445 // along with the description of any remaining name string. Also, 01446 // for Dos drive letters, update the drive type in the appropriate 01447 // device map object. 01448 // 01449 01450 ObReferenceObject( Object ); 01451 01452 SymbolicLink->LinkTargetObject = Object; 01453 01454 if ((*(RemainingName.Buffer) == OBJ_NAME_PATH_SEPARATOR) && 01455 (RemainingName.Length == sizeof( OBJ_NAME_PATH_SEPARATOR))) { 01456 01457 RtlInitUnicodeString( &SymbolicLink->LinkTargetRemaining, NULL ); 01458 01459 } else { 01460 01461 SymbolicLink->LinkTargetRemaining = RemainingName; 01462 } 01463 } 01464 01465 if (SymbolicLink->DosDeviceDriveIndex != 0) { 01466 01467 // 01468 // Default is to calculate the drive type in user mode if we are 01469 // unable to snap the symbolic link or it does not resolve to a 01470 // DEVICE_OBJECT we know about. 01471 // 01472 01473 ObjectHeader = OBJECT_TO_OBJECT_HEADER( Object ); 01474 01475 if (ObjectHeader->Type == IoDeviceObjectType) { 01476 01477 DeviceObject = (PDEVICE_OBJECT)Object; 01478 01479 switch (DeviceObject->DeviceType) { 01480 01481 case FILE_DEVICE_CD_ROM: 01482 case FILE_DEVICE_CD_ROM_FILE_SYSTEM: 01483 01484 DosDeviceDriveType = DOSDEVICE_DRIVE_CDROM; 01485 01486 break; 01487 01488 case FILE_DEVICE_DISK: 01489 case FILE_DEVICE_DISK_FILE_SYSTEM: 01490 case FILE_DEVICE_FILE_SYSTEM: 01491 01492 if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) { 01493 01494 DosDeviceDriveType = DOSDEVICE_DRIVE_REMOVABLE; 01495 01496 } else { 01497 01498 DosDeviceDriveType = DOSDEVICE_DRIVE_FIXED; 01499 } 01500 01501 break; 01502 01503 case FILE_DEVICE_MULTI_UNC_PROVIDER: 01504 case FILE_DEVICE_NETWORK: 01505 case FILE_DEVICE_NETWORK_BROWSER: 01506 case FILE_DEVICE_NETWORK_REDIRECTOR: 01507 01508 DosDeviceDriveType = DOSDEVICE_DRIVE_REMOTE; 01509 01510 break; 01511 01512 case FILE_DEVICE_NETWORK_FILE_SYSTEM: 01513 01514 #if defined(REMOTE_BOOT) 01515 // 01516 // If this is a remote boot workstation, the X: 01517 // drive is a redirected drive, but needs to look 01518 // like a local drive. 01519 // 01520 01521 if (IoRemoteBootClient && 01522 (SymbolicLink->DosDeviceDriveIndex == 24)) { 01523 01524 DosDeviceDriveType = DOSDEVICE_DRIVE_FIXED; 01525 01526 } else 01527 #endif // defined(REMOTE_BOOT) 01528 { 01529 DosDeviceDriveType = DOSDEVICE_DRIVE_REMOTE; 01530 } 01531 01532 break; 01533 01534 case FILE_DEVICE_VIRTUAL_DISK: 01535 01536 DosDeviceDriveType = DOSDEVICE_DRIVE_RAMDISK; 01537 01538 break; 01539 01540 default: 01541 01542 DosDeviceDriveType = DOSDEVICE_DRIVE_UNKNOWN; 01543 01544 break; 01545 } 01546 } 01547 } 01548 } 01549 01550 // 01551 // If this is a drive letter symbolic link, update the drive type and 01552 // and mark as valid drive letter. 01553 // 01554 01555 if (DeviceMap != NULL) { 01556 01557 DeviceMap->DriveType[ SymbolicLink->DosDeviceDriveIndex-1 ] = (UCHAR)DosDeviceDriveType; 01558 DeviceMap->DriveMap |= 1 << (SymbolicLink->DosDeviceDriveIndex-1) ; 01559 } 01560 01561 } else { 01562 01563 // 01564 // Deleting the symbolic link. Dereference the snapped object pointer if any 01565 // and zero out the snapped object fields. 01566 // 01567 01568 RtlInitUnicodeString( &SymbolicLink->LinkTargetRemaining, NULL ); 01569 01570 Object = SymbolicLink->LinkTargetObject; 01571 01572 if (Object != NULL) { 01573 01574 SymbolicLink->LinkTargetObject = NULL; 01575 ObDereferenceObject( Object ); 01576 } 01577 01578 // 01579 // If this is a drive letter symbolic link, set the drive type to 01580 // unknown and clear the bit in the drive letter bit map. 01581 // 01582 01583 if (DeviceMap != NULL) { 01584 01585 DeviceMap->DriveMap &= ~(1 << (SymbolicLink->DosDeviceDriveIndex-1)); 01586 DeviceMap->DriveType[ SymbolicLink->DosDeviceDriveIndex-1 ] = DOSDEVICE_DRIVE_UNKNOWN; 01587 01588 SymbolicLink->DosDeviceDriveIndex = 0; 01589 } 01590 01591 // 01592 // If we allocated a target buffer, free it. 01593 // 01594 01595 if (SymbolicLink->LinkTarget.Buffer != NULL) { 01596 01597 ExFreePool( SymbolicLink->LinkTarget.Buffer ); 01598 01599 RtlInitUnicodeString( &SymbolicLink->LinkTarget, NULL ); 01600 } 01601 } 01602 01603 return; 01604 }


Variable Documentation

POBJECT_TYPE IoDeviceObjectType
 

Definition at line 35 of file oblink.c.

Referenced by IoCreateDevice(), IopCreateObjectTypes(), IovpReexamineAllStacks(), and ObpProcessDosDeviceSymbolicLink().


Generated on Sat May 15 19:44:58 2004 for test by doxygen 1.3.7