00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
#include "obp.h"
00022
00023
#if defined(ALLOC_PRAGMA)
00024
#pragma alloc_text(PAGE,NtCreateSymbolicLinkObject)
00025
#pragma alloc_text(PAGE,NtOpenSymbolicLinkObject)
00026
#pragma alloc_text(PAGE,NtQuerySymbolicLinkObject)
00027
#pragma alloc_text(PAGE,ObpParseSymbolicLink)
00028
#pragma alloc_text(PAGE,ObpDeleteSymbolicLink)
00029
#endif
00030
00031
00032
00033
00034
00035 extern POBJECT_TYPE IoDeviceObjectType;
00036
00037
00038
00039
00040
00041 #define CREATE_SYMBOLIC_LINK 0
00042 #define DELETE_SYMBOLIC_LINK 1
00043
00044
VOID
00045
ObpProcessDosDeviceSymbolicLink (
00046
POBJECT_SYMBOLIC_LINK SymbolicLink,
00047 ULONG Action
00048 );
00049
00050
00051
NTSTATUS
00052 NtCreateSymbolicLinkObject (
00053 OUT PHANDLE LinkHandle,
00054 IN ACCESS_MASK DesiredAccess,
00055 IN POBJECT_ATTRIBUTES ObjectAttributes,
00056 IN PUNICODE_STRING LinkTarget
00057 )
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
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
00097
00098
00099 PreviousMode = KeGetPreviousMode();
00100
00101
if (PreviousMode !=
KernelMode) {
00102
00103
try {
00104
00105
00106
00107
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
00138
00139
00140
if (CapturedLinkTarget.MaximumLength %
sizeof( WCHAR )) {
00141
00142
00143
00144
00145
00146 CapturedLinkTarget.MaximumLength = (CapturedLinkTarget.MaximumLength /
sizeof( WCHAR )) *
sizeof( WCHAR );
00147 }
00148
00149
00150
00151
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
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
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
00221
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
00239
00240 }
00241
00242
return(
Status );
00243 }
00244
00245
00246
NTSTATUS
00247 NtOpenSymbolicLinkObject (
00248 OUT PHANDLE LinkHandle,
00249 IN ACCESS_MASK DesiredAccess,
00250 IN POBJECT_ATTRIBUTES ObjectAttributes
00251 )
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276 {
00277
KPROCESSOR_MODE PreviousMode;
00278
NTSTATUS Status;
00279 HANDLE
Handle;
00280
00281
PAGED_CODE();
00282
00283
00284
00285
00286
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
00305
00306
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
00325
00326 }
00327
00328
return(
Status );
00329 }
00330
00331
00332
NTSTATUS
00333 NtQuerySymbolicLinkObject (
00334 IN HANDLE LinkHandle,
00335 IN OUT PUNICODE_STRING LinkTarget,
00336 OUT PULONG ReturnedLength OPTIONAL
00337 )
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363 {
00364
KPROCESSOR_MODE PreviousMode;
00365
NTSTATUS Status;
00366
POBJECT_SYMBOLIC_LINK SymbolicLink;
00367 UNICODE_STRING CapturedLinkTarget;
00368
00369
00370
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
00412
00413
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
00429
00430
00431
00432
00433
00434
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
00463
00464 }
00465
00466 }
else {
00467
00468
00469
00470
00471
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
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 }
00498
00499
00500
NTSTATUS
00501 ObpParseSymbolicLink (
00502 IN PVOID ParseObject,
00503 IN PVOID ObjectType,
00504 IN
PACCESS_STATE AccessState,
00505 IN KPROCESSOR_MODE AccessMode,
00506 IN ULONG Attributes,
00507 IN OUT PUNICODE_STRING CompleteName,
00508 IN OUT PUNICODE_STRING RemainingName,
00509 IN OUT PVOID Context OPTIONAL,
00510 IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL,
00511 OUT PVOID *Object
00512 )
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
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
00582
00583
00584
00585
ObpEnterRootDirectoryMutex();
00586
00587
try {
00588
00589 *Object =
NULL;
00590
00591
00592
00593
00594
00595
00596
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
00622
00623
00624
00625 }
else if (*(RemainingName->Buffer) != OBJ_NAME_PATH_SEPARATOR) {
00626
00627
Status = STATUS_OBJECT_TYPE_MISMATCH;
00628 leave;
00629 }
00630
00631
00632
00633
00634
00635
00636 SymbolicLink = (
POBJECT_SYMBOLIC_LINK)ParseObject;
00637
00638
if (SymbolicLink->
LinkTargetObject !=
NULL) {
00639
00640
00641
00642
00643
00644
00645 LinkTargetName = &SymbolicLink->
LinkTargetRemaining;
00646
00647
if (LinkTargetName->Length == 0) {
00648
00649
00650
00651
00652
00653
00654
00655 *Object = SymbolicLink->
LinkTargetObject;
00656
00657
Status = STATUS_REPARSE_OBJECT;
00658 leave;
00659 }
00660
00661
00662
00663
00664
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
00677
00678
00679
00680 InsertAmount -=
sizeof( WCHAR );
00681 }
00682
00683
00684
00685
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
00702
00703
00704
00705
if (CompleteName->MaximumLength <= Length) {
00706
00707
00708
00709
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
00723
00724
00725
00726
00727 NewRemainingName =
NewName + (RemainingName->Buffer - CompleteName->Buffer);
00728
00729
00730
00731
00732
00733 RtlMoveMemory(
NewName,
00734 CompleteName->Buffer,
00735 ((RemainingName->Buffer - CompleteName->Buffer) *
sizeof( WCHAR )));
00736
00737
00738
00739
00740
00741
00742
if (RemainingName->Length != 0) {
00743
00744 RtlMoveMemory( (PVOID)((PUCHAR)NewRemainingName + InsertAmount),
00745 RemainingName->Buffer,
00746 RemainingName->Length );
00747 }
00748
00749
00750
00751
00752
00753 RtlMoveMemory( NewRemainingName, LinkTargetName->Buffer, InsertAmount );
00754
00755
00756
00757
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
00774
00775
00776
00777
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
00789
00790
00791 RtlMoveMemory( RemainingName->Buffer, LinkTargetName->Buffer, InsertAmount );
00792
00793
00794
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
00807
00808
00809
00810 *Object = SymbolicLink->
LinkTargetObject;
00811
00812
Status = STATUS_REPARSE_OBJECT;
00813 leave;
00814 }
00815
00816
00817
00818
00819
00820
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
00838
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
00858
00859
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
00875
00876
00877
00878
if (
NewName != CompleteName->Buffer) {
00879
00880
ExFreePool( CompleteName->Buffer );
00881 }
00882
00883
00884
00885
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 }
00901
00902
00903
VOID
00904 ObpDeleteSymbolicLink (
00905 IN PVOID Object
00906 )
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925 {
00926
POBJECT_SYMBOLIC_LINK SymbolicLink = (
POBJECT_SYMBOLIC_LINK)Object;
00927
00928
PAGED_CODE();
00929
00930
00931
00932
00933
00934
00935
if (SymbolicLink->
LinkTarget.Buffer !=
NULL) {
00936
00937
ExFreePool( SymbolicLink->
LinkTarget.Buffer );
00938 }
00939
00940 SymbolicLink->
LinkTarget.Buffer =
NULL;
00941
00942
00943
00944
00945
00946
return;
00947 }
00948
00949
00950
VOID
00951 ObpDeleteSymbolicLinkName (
00952
POBJECT_SYMBOLIC_LINK SymbolicLink
00953 )
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972 {
00973 PVOID CapturedLinkTargetObject;
00974
00975 CapturedLinkTargetObject =
NULL;
00976
00977
00978
00979
00980
00981
00982
00983
ObpEnterRootDirectoryMutex();
00984
00985
00986
00987
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
01003
01004
01005
if (CapturedLinkTargetObject !=
NULL) {
01006
01007
ObDereferenceObject(CapturedLinkTargetObject);
01008 }
01009
01010
return;
01011 }
01012
01013
01014
VOID
01015 ObpCreateSymbolicLinkName (
01016
POBJECT_SYMBOLIC_LINK SymbolicLink
01017 )
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057 {
01058
POBJECT_HEADER ObjectHeader;
01059
POBJECT_HEADER_NAME_INFO NameInfo;
01060 WCHAR DosDeviceDriveLetter;
01061 ULONG DosDeviceDriveIndex;
01062
01063
01064
01065
01066
01067
01068
01069
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
01084
01085
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
01106
01107
01108
ObpProcessDosDeviceSymbolicLink( SymbolicLink,
CREATE_SYMBOLIC_LINK );
01109
01110
return;
01111 }
01112
01113
01114
01115
01116
01117
01118 #define MAX_DEPTH 16
01119
01120
VOID
01121 ObpProcessDosDeviceSymbolicLink (
01122
POBJECT_SYMBOLIC_LINK SymbolicLink,
01123 ULONG Action
01124 )
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155
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
01181
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
01208
01209
01210
01211
if ((RemainingName.Length >=
ObpDosDevicesShortName.Length)
01212
01213 &&
01214
01215 (*(PULONGLONG)(RemainingName.Buffer) ==
ObpDosDevicesShortNamePrefix.QuadPart)) {
01216
01217
01218
01219
01220
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
01236
01237
01238
01239
01240
01241
01242
while (
TRUE) {
01243
01244
01245
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
01256
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
01281
01282
01283
if (ParentDirectory !=
NULL) {
01284
01285 HaveWorldTraverseAccess =
FALSE;
01286
01287
01288
01289
01290
01291
Status =
ObGetObjectSecurity( ParentDirectory,
01292 &SecurityDescriptor,
01293 &MemoryAllocated );
01294
01295
if (
NT_SUCCESS(
Status )) {
01296
01297
01298
01299
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
01327
01328
01329
01330 Object =
ObpLookupDirectoryEntry(
Directory, &ComponentName, 0 );
01331
01332
if (Object ==
NULL) {
01333
01334
break;
01335 }
01336
01337
01338
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
01353
01354
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
01368
01369
01370
01371
break;
01372 }
01373 }
01374
01375
01376
01377
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
01400
01401
01402
01403
01404
01405
01406
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
01424
01425
01426
if (
Action ==
CREATE_SYMBOLIC_LINK) {
01427
01428 DosDeviceDriveType = DOSDEVICE_DRIVE_CALCULATE;
01429
01430
if (Object !=
NULL) {
01431
01432
01433
01434
01435
01436
01437
01438
01439
01440
01441
01442
if ((
PsGetCurrentProcess()->SessionId == 0) || (DeviceMapUsed)) {
01443
01444
01445
01446
01447
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
01469
01470
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
01517
01518
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
01552
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
01565
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
01580
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
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 }
01605