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,NtCreateDirectoryObject)
00025
#pragma alloc_text(PAGE,NtOpenDirectoryObject)
00026
#pragma alloc_text(PAGE,NtQueryDirectoryObject)
00027
#pragma alloc_text(PAGE,ObpLookupDirectoryEntry)
00028
#endif
00029
00030
00031
NTSTATUS
00032 NtCreateDirectoryObject (
00033 OUT PHANDLE DirectoryHandle,
00034 IN ACCESS_MASK DesiredAccess,
00035 IN POBJECT_ATTRIBUTES ObjectAttributes
00036 )
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062 {
00063
POBJECT_DIRECTORY Directory;
00064 HANDLE
Handle;
00065
KPROCESSOR_MODE PreviousMode;
00066
NTSTATUS Status;
00067
00068
PAGED_CODE();
00069
00070
ObpValidateIrql(
"NtCreateDirectoryObject" );
00071
00072
00073
00074
00075
00076 PreviousMode = KeGetPreviousMode();
00077
00078
if (PreviousMode !=
KernelMode) {
00079
00080
try {
00081
00082
ProbeForWriteHandle(
DirectoryHandle );
00083
00084 } except(
EXCEPTION_EXECUTE_HANDLER ) {
00085
00086
return( GetExceptionCode() );
00087 }
00088 }
00089
00090
00091
00092
00093
00094
00095
00096
00097
Status =
ObCreateObject( PreviousMode,
00098
ObpDirectoryObjectType,
00099
ObjectAttributes,
00100 PreviousMode,
00101
NULL,
00102
sizeof( *
Directory ),
00103 0,
00104 0,
00105 (PVOID *)&
Directory );
00106
00107
if (!
NT_SUCCESS(
Status )) {
00108
00109
return(
Status );
00110 }
00111
00112 RtlZeroMemory(
Directory,
sizeof( *
Directory ) );
00113
00114
00115
00116
00117
00118
00119
00120
00121
Status =
ObInsertObject(
Directory,
00122
NULL,
00123 DesiredAccess,
00124 0,
00125 (PVOID *)
NULL,
00126 &
Handle );
00127
00128
try {
00129
00130 *
DirectoryHandle =
Handle;
00131
00132 } except(
EXCEPTION_EXECUTE_HANDLER ) {
00133
00134
00135
00136
00137 }
00138
00139
return(
Status );
00140 }
00141
00142
00143
NTSTATUS
00144 NtOpenDirectoryObject (
00145 OUT PHANDLE DirectoryHandle,
00146 IN ACCESS_MASK DesiredAccess,
00147 IN POBJECT_ATTRIBUTES ObjectAttributes
00148 )
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173 {
00174
KPROCESSOR_MODE PreviousMode;
00175
NTSTATUS Status;
00176 HANDLE
Handle;
00177
00178
PAGED_CODE();
00179
00180
ObpValidateIrql(
"NtOpenDirectoryObject" );
00181
00182
00183
00184
00185
00186 PreviousMode = KeGetPreviousMode();
00187
00188
if (PreviousMode !=
KernelMode) {
00189
00190
try {
00191
00192
ProbeForWriteHandle(
DirectoryHandle );
00193
00194 } except(
EXCEPTION_EXECUTE_HANDLER ) {
00195
00196
return( GetExceptionCode() );
00197 }
00198 }
00199
00200
00201
00202
00203
00204
00205
Status =
ObOpenObjectByName(
ObjectAttributes,
00206
ObpDirectoryObjectType,
00207 PreviousMode,
00208
NULL,
00209 DesiredAccess,
00210
NULL,
00211 &
Handle );
00212
00213
try {
00214
00215 *
DirectoryHandle =
Handle;
00216
00217 } except(
EXCEPTION_EXECUTE_HANDLER ) {
00218
00219
00220
00221
00222 }
00223
00224
return Status;
00225 }
00226
00227
00228
NTSTATUS
00229 NtQueryDirectoryObject (
00230 IN HANDLE DirectoryHandle,
00231 OUT PVOID Buffer,
00232 IN ULONG Length,
00233 IN BOOLEAN ReturnSingleEntry,
00234 IN BOOLEAN RestartScan,
00235 IN OUT PULONG Context,
00236 OUT PULONG ReturnLength OPTIONAL
00237 )
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
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
00278 {
00279
POBJECT_DIRECTORY Directory;
00280
POBJECT_DIRECTORY_ENTRY DirectoryEntry;
00281
POBJECT_HEADER ObjectHeader;
00282
POBJECT_HEADER_NAME_INFO NameInfo;
00283 UNICODE_STRING ObjectName;
00284 POBJECT_DIRECTORY_INFORMATION DirInfo;
00285 PWCH NameBuffer;
00286
KPROCESSOR_MODE PreviousMode;
00287
NTSTATUS Status;
00288 ULONG Bucket, EntryNumber, CapturedContext;
00289 ULONG TotalLengthNeeded, LengthNeeded, EntriesFound;
00290 PCHAR TempBuffer;
00291
00292
PAGED_CODE();
00293
00294
ObpValidateIrql(
"NtQueryDirectoryObject" );
00295
00296
00297
00298
00299
00300 PreviousMode = KeGetPreviousMode();
00301
00302
if (PreviousMode !=
KernelMode) {
00303
00304
try {
00305
00306
ProbeForWrite(
Buffer, Length,
sizeof( WCHAR ) );
00307
ProbeForWriteUlong( Context );
00308
00309
if (ARGUMENT_PRESENT( ReturnLength )) {
00310
00311
ProbeForWriteUlong( ReturnLength );
00312 }
00313
00314
if (RestartScan) {
00315
00316 CapturedContext = 0;
00317
00318 }
else {
00319
00320 CapturedContext = *Context;
00321 }
00322
00323 } except(
EXCEPTION_EXECUTE_HANDLER ) {
00324
00325
return( GetExceptionCode() );
00326 }
00327
00328 }
else {
00329
00330
if (RestartScan) {
00331
00332 CapturedContext = 0;
00333
00334 }
else {
00335
00336 CapturedContext = *Context;
00337 }
00338 }
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
if (
ObpIsOverflow( Length,
sizeof( OBJECT_DIRECTORY_INFORMATION ))) {
00354
00355
return( STATUS_INVALID_PARAMETER );
00356 }
00357
00358 TempBuffer =
ExAllocatePoolWithTag(
PagedPool,
00359 Length +
sizeof( OBJECT_DIRECTORY_INFORMATION ),
00360 'mNbO' );
00361
00362
if (TempBuffer ==
NULL) {
00363
00364
return( STATUS_INSUFFICIENT_RESOURCES );
00365 }
00366
00367 RtlZeroMemory( TempBuffer, Length );
00368
00369
00370
00371
00372
00373
Status =
ObReferenceObjectByHandle(
DirectoryHandle,
00374 DIRECTORY_QUERY,
00375
ObpDirectoryObjectType,
00376 PreviousMode,
00377 (PVOID *)&
Directory,
00378
NULL );
00379
00380
if (!
NT_SUCCESS(
Status )) {
00381
00382
ExFreePool( TempBuffer );
00383
00384
return(
Status );
00385 }
00386
00387
00388
00389
00390
00391
00392
ObpEnterRootDirectoryMutex();
00393
00394
00395
00396
00397
00398
00399
00400 DirInfo = (POBJECT_DIRECTORY_INFORMATION)TempBuffer;
00401
00402 TotalLengthNeeded =
sizeof( *DirInfo );
00403
00404
00405
00406
00407
00408
00409 EntryNumber = 0;
00410 EntriesFound = 0;
00411
00412
00413
00414
00415
00416
00417
Status = STATUS_NO_MORE_ENTRIES;
00418
00419
00420
00421
00422
00423
for (Bucket=0; Bucket<
NUMBER_HASH_BUCKETS; Bucket++) {
00424
00425 DirectoryEntry =
Directory->HashBuckets[ Bucket ];
00426
00427
00428
00429
00430
00431
00432
00433
while (DirectoryEntry) {
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
if (CapturedContext == EntryNumber++) {
00445
00446
00447
00448
00449
00450
00451
00452 ObjectHeader =
OBJECT_TO_OBJECT_HEADER( DirectoryEntry->
Object );
00453 NameInfo =
OBJECT_HEADER_TO_NAME_INFO( ObjectHeader );
00454
00455
if (NameInfo !=
NULL) {
00456
00457 ObjectName = NameInfo->
Name;
00458
00459 }
else {
00460
00461
RtlInitUnicodeString( &ObjectName,
NULL );
00462 }
00463
00464
00465
00466
00467
00468
00469
00470
00471 LengthNeeded =
sizeof( *DirInfo ) +
00472 ObjectName.Length +
sizeof( UNICODE_NULL ) +
00473 ObjectHeader->
Type->
Name.Length +
sizeof( UNICODE_NULL );
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
if ((TotalLengthNeeded + LengthNeeded) > Length) {
00486
00487
if (ReturnSingleEntry) {
00488
00489 TotalLengthNeeded += LengthNeeded;
00490
00491
Status = STATUS_BUFFER_TOO_SMALL;
00492
00493 }
else {
00494
00495
Status = STATUS_MORE_ENTRIES;
00496 }
00497
00498 EntryNumber -= 1;
00499
goto querydone;
00500 }
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
try {
00511
00512 DirInfo->Name.Length = ObjectName.Length;
00513 DirInfo->Name.MaximumLength = (
USHORT)(ObjectName.Length+
sizeof( UNICODE_NULL ));
00514 DirInfo->Name.Buffer = ObjectName.Buffer;
00515
00516 DirInfo->TypeName.Length = ObjectHeader->
Type->
Name.Length;
00517 DirInfo->TypeName.MaximumLength = (
USHORT)(ObjectHeader->
Type->
Name.Length+
sizeof( UNICODE_NULL ));
00518 DirInfo->TypeName.Buffer = ObjectHeader->
Type->
Name.Buffer;
00519
00520
Status = STATUS_SUCCESS;
00521
00522 } except(
EXCEPTION_EXECUTE_HANDLER ) {
00523
00524
Status = GetExceptionCode();
00525 }
00526
00527
if (!
NT_SUCCESS(
Status )) {
00528
00529
goto querydone;
00530 }
00531
00532
00533
00534
00535
00536
00537
00538
00539 TotalLengthNeeded += LengthNeeded;
00540
00541 DirInfo++;
00542 EntriesFound++;
00543
00544
00545
00546
00547
00548
00549
00550
00551
if (ReturnSingleEntry) {
00552
00553
goto querydone;
00554
00555 }
else {
00556
00557
00558
00559
00560
00561 CapturedContext++;
00562 }
00563 }
00564
00565
00566
00567
00568
00569
00570 DirectoryEntry = DirectoryEntry->
ChainLink;
00571 }
00572 }
00573
00574
00575
00576
00577
00578
00579
00580
00581 querydone:
00582
00583
try {
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
if (
NT_SUCCESS(
Status )) {
00596
00597
00598
00599
00600
00601
00602 RtlZeroMemory( DirInfo,
sizeof( *DirInfo ));
00603
00604 DirInfo++;
00605
00606 NameBuffer = (PWCH)DirInfo;
00607
00608
00609
00610
00611
00612
00613
00614
00615 DirInfo = (POBJECT_DIRECTORY_INFORMATION)TempBuffer;
00616
00617
while (EntriesFound--) {
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627 RtlMoveMemory( NameBuffer,
00628 DirInfo->Name.Buffer,
00629 DirInfo->Name.Length );
00630
00631 DirInfo->Name.Buffer = (PVOID)((ULONG_PTR)
Buffer + ((ULONG_PTR)NameBuffer - (ULONG_PTR)TempBuffer));
00632 NameBuffer = (PWCH)((ULONG_PTR)NameBuffer + DirInfo->Name.Length);
00633 *NameBuffer++ = UNICODE_NULL;
00634
00635
00636
00637
00638
00639 RtlMoveMemory( NameBuffer,
00640 DirInfo->TypeName.Buffer,
00641 DirInfo->TypeName.Length );
00642
00643 DirInfo->TypeName.Buffer = (PVOID)((ULONG_PTR)
Buffer + ((ULONG_PTR)NameBuffer - (ULONG_PTR)TempBuffer));
00644 NameBuffer = (PWCH)((ULONG_PTR)NameBuffer + DirInfo->TypeName.Length);
00645 *NameBuffer++ = UNICODE_NULL;
00646
00647
00648
00649
00650
00651 DirInfo++;
00652 }
00653
00654
00655
00656
00657
00658
00659 *Context = EntryNumber;
00660 }
00661
00662
00663
00664
00665
00666
00667
00668 RtlMoveMemory(
Buffer,
00669 TempBuffer,
00670 (TotalLengthNeeded <= Length ? TotalLengthNeeded : Length) );
00671
00672
00673
00674
00675
00676
00677
if (ARGUMENT_PRESENT( ReturnLength )) {
00678
00679 *ReturnLength = TotalLengthNeeded;
00680 }
00681
00682 } except(
EXCEPTION_EXECUTE_HANDLER ) {
00683
00684
00685
00686
00687 }
00688
00689
00690
00691
00692
00693
00694
ObpLeaveRootDirectoryMutex();
00695
00696
ObDereferenceObject(
Directory );
00697
00698
ExFreePool( TempBuffer );
00699
00700
return(
Status );
00701 }
00702
00703
00704 PVOID
00705 ObpLookupDirectoryEntry (
00706 IN
POBJECT_DIRECTORY Directory,
00707 IN PUNICODE_STRING Name,
00708 IN ULONG Attributes
00709 )
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738 {
00739
POBJECT_DIRECTORY_ENTRY *HeadDirectoryEntry;
00740
POBJECT_DIRECTORY_ENTRY DirectoryEntry;
00741
POBJECT_HEADER ObjectHeader;
00742
POBJECT_HEADER_NAME_INFO NameInfo;
00743 PWCH
Buffer;
00744 WCHAR Wchar;
00745 ULONG HashIndex;
00746 ULONG WcharLength;
00747 BOOLEAN CaseInSensitive;
00748
00749
PAGED_CODE();
00750
00751
00752
00753
00754
00755
00756
if (!
Directory || !
Name) {
00757
00758
return(
NULL );
00759 }
00760
00761
00762
00763
00764
00765
if (Attributes & OBJ_CASE_INSENSITIVE) {
00766
00767 CaseInSensitive =
TRUE;
00768
00769 }
else {
00770
00771 CaseInSensitive =
FALSE;
00772 }
00773
00774
00775
00776
00777
00778
00779
00780
Buffer =
Name->Buffer;
00781 WcharLength =
Name->Length /
sizeof( *Buffer );
00782
00783
if (!WcharLength || !
Buffer) {
00784
00785
return(
NULL );
00786 }
00787
00788
00789
00790
00791
00792 HashIndex = 0;
00793
while (WcharLength--) {
00794
00795 Wchar = *
Buffer++;
00796 HashIndex += (HashIndex << 1) + (HashIndex >> 1);
00797
00798
if (Wchar <
'a') {
00799
00800 HashIndex += Wchar;
00801
00802 }
else if (Wchar >
'z') {
00803
00804 HashIndex +=
RtlUpcaseUnicodeChar( Wchar );
00805
00806 }
else {
00807
00808 HashIndex += (Wchar - (
'a'-
'A'));
00809 }
00810 }
00811
00812 HashIndex %=
NUMBER_HASH_BUCKETS;
00813
00814 HeadDirectoryEntry = (
POBJECT_DIRECTORY_ENTRY *)&
Directory->HashBuckets[ HashIndex ];
00815
00816
Directory->LookupBucket = HeadDirectoryEntry;
00817
00818
00819
00820
00821
00822
00823
while ((DirectoryEntry = *HeadDirectoryEntry) !=
NULL) {
00824
00825
00826
00827
00828
00829
00830
00831
00832 ObjectHeader =
OBJECT_TO_OBJECT_HEADER( DirectoryEntry->
Object );
00833 NameInfo =
OBJECT_HEADER_TO_NAME_INFO( ObjectHeader );
00834
00835
00836
00837
00838
00839
if ((
Name->Length == NameInfo->
Name.Length) &&
00840
RtlEqualUnicodeString(
Name,
00841 &NameInfo->
Name,
00842 CaseInSensitive )) {
00843
00844
00845
00846
00847
00848
00849
break;
00850 }
00851
00852 HeadDirectoryEntry = &DirectoryEntry->
ChainLink;
00853 }
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
if (DirectoryEntry) {
00868
00869
Directory->LookupFound =
TRUE;
00870
00871
00872
00873
00874
00875
00876
if (HeadDirectoryEntry !=
Directory->LookupBucket) {
00877
00878 *HeadDirectoryEntry = DirectoryEntry->
ChainLink;
00879 DirectoryEntry->
ChainLink = *(
Directory->LookupBucket);
00880 *(
Directory->LookupBucket) = DirectoryEntry;
00881 }
00882
00883
00884
00885
00886
00887
return( DirectoryEntry->
Object );
00888
00889 }
else {
00890
00891
00892
00893
00894
00895
Directory->LookupFound =
FALSE;
00896
00897
return(
NULL );
00898 }
00899 }
00900
00901
00902 BOOLEAN
00903 ObpInsertDirectoryEntry (
00904 IN
POBJECT_DIRECTORY Directory,
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
00927
00928
00929
00930 {
00931
POBJECT_DIRECTORY_ENTRY *HeadDirectoryEntry;
00932
POBJECT_DIRECTORY_ENTRY NewDirectoryEntry;
00933
POBJECT_HEADER_NAME_INFO NameInfo;
00934
00935
00936
00937
00938
00939
00940
if (!
Directory ||
Directory->LookupFound) {
00941
00942
return(
FALSE );
00943 }
00944
00945
00946
00947
00948
00949 HeadDirectoryEntry =
Directory->LookupBucket;
00950
00951
if (!HeadDirectoryEntry) {
00952
00953
return(
FALSE );
00954 }
00955
00956
00957
00958
00959
00960
00961 NameInfo =
OBJECT_HEADER_TO_NAME_INFO(
OBJECT_TO_OBJECT_HEADER( Object ) );
00962
00963
if (NameInfo ==
NULL) {
00964
00965
return FALSE;
00966 }
00967
00968
00969
00970
00971
00972 NewDirectoryEntry = (
POBJECT_DIRECTORY_ENTRY)
ExAllocatePoolWithTag(
PagedPool,
00973
sizeof(
OBJECT_DIRECTORY_ENTRY ),
00974 'iDbO' );
00975
00976
if (NewDirectoryEntry ==
NULL) {
00977
00978
return(
FALSE );
00979 }
00980
00981
00982
00983
00984
00985
00986
00987 NewDirectoryEntry->
ChainLink = *HeadDirectoryEntry;
00988 *HeadDirectoryEntry = NewDirectoryEntry;
00989 NewDirectoryEntry->
Object = Object;
00990
00991
00992
00993
00994
00995
00996 NameInfo->
Directory =
Directory;
00997
00998
00999
01000
01001
01002
Directory->LookupFound =
TRUE;
01003
01004
return(
TRUE );
01005 }
01006
01007
01008 BOOLEAN
01009 ObpDeleteDirectoryEntry (
01010 IN
POBJECT_DIRECTORY Directory
01011 )
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031 {
01032
POBJECT_DIRECTORY_ENTRY *HeadDirectoryEntry;
01033
POBJECT_DIRECTORY_ENTRY DirectoryEntry;
01034
01035
01036
01037
01038
01039
if (!
Directory || !
Directory->LookupFound) {
01040
01041
return(
FALSE );
01042 }
01043
01044
01045
01046
01047
01048 HeadDirectoryEntry =
Directory->LookupBucket;
01049
01050
if (!HeadDirectoryEntry) {
01051
01052
return(
FALSE );
01053 }
01054
01055 DirectoryEntry = *HeadDirectoryEntry;
01056
01057
if (!DirectoryEntry) {
01058
01059
return(
FALSE );
01060 }
01061
01062
01063
01064
01065
01066
01067 *HeadDirectoryEntry = DirectoryEntry->
ChainLink;
01068 DirectoryEntry->
ChainLink =
NULL;
01069
01070
ExFreePool( DirectoryEntry );
01071
01072
01073
01074
01075
01076
return(
TRUE );
01077 }
01078
01079
01080
NTSTATUS
01081 ObpLookupObjectName (
01082 IN HANDLE RootDirectoryHandle OPTIONAL,
01083 IN PUNICODE_STRING ObjectName,
01084 IN ULONG Attributes,
01085 IN
POBJECT_TYPE ObjectType,
01086 IN KPROCESSOR_MODE AccessMode,
01087 IN PVOID ParseContext OPTIONAL,
01088 IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL,
01089 IN PVOID InsertObject OPTIONAL,
01090 IN OUT
PACCESS_STATE AccessState,
01091 OUT PBOOLEAN DirectoryLocked,
01092 OUT PVOID *FoundObject
01093 )
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
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
POBJECT_DIRECTORY RootDirectory;
01149
POBJECT_DIRECTORY Directory;
01150
POBJECT_DIRECTORY ParentDirectory =
NULL;
01151
POBJECT_HEADER ObjectHeader;
01152
POBJECT_HEADER_NAME_INFO NameInfo;
01153
PDEVICE_MAP DeviceMap =
NULL;
01154 PVOID Object;
01155 UNICODE_STRING RemainingName;
01156 UNICODE_STRING ComponentName;
01157 PWCH
NewName;
01158
NTSTATUS Status;
01159 BOOLEAN Reparse;
01160 ULONG MaxReparse = OBJ_MAX_REPARSE_ATTEMPTS;
01161
OB_PARSE_METHOD ParseProcedure;
01162
extern POBJECT_TYPE IoFileObjectType;
01163
01164
ObpValidateIrql(
"ObpLookupObjectName" );
01165
01166
01167
01168
01169
01170
01171 *DirectoryLocked =
FALSE;
01172 *FoundObject =
NULL;
01173
Status = STATUS_SUCCESS;
01174
01175 Object =
NULL;
01176
01177
01178
01179
01180
01181
01182
if (ARGUMENT_PRESENT( RootDirectoryHandle )) {
01183
01184
01185
01186
01187
01188
01189
Status =
ObReferenceObjectByHandle( RootDirectoryHandle,
01190 0,
01191
NULL,
01192 AccessMode,
01193 (PVOID *)&RootDirectory,
01194
NULL );
01195
01196
if (!
NT_SUCCESS(
Status )) {
01197
01198
return(
Status );
01199 }
01200
01201
01202
01203
01204
01205 ObjectHeader =
OBJECT_TO_OBJECT_HEADER( RootDirectory );
01206
01207
01208
01209
01210
01211
01212
if ((ObjectName->Buffer !=
NULL) &&
01213 (*(ObjectName->Buffer) == OBJ_NAME_PATH_SEPARATOR) &&
01214 (ObjectHeader->
Type !=
IoFileObjectType)) {
01215
01216
ObDereferenceObject( RootDirectory );
01217
01218
return( STATUS_OBJECT_PATH_SYNTAX_BAD );
01219 }
01220
01221
01222
01223
01224
01225
01226
if (ObjectHeader->
Type !=
ObpDirectoryObjectType) {
01227
01228
01229
01230
01231
01232
01233
01234
if (ObjectHeader->
Type->
TypeInfo.
ParseProcedure ==
NULL) {
01235
01236
ObDereferenceObject( RootDirectory );
01237
01238
return( STATUS_INVALID_HANDLE );
01239
01240 }
else {
01241
01242 MaxReparse = OBJ_MAX_REPARSE_ATTEMPTS;
01243
01244
01245
01246
01247
01248
01249
01250
while (
TRUE) {
01251
01252 KIRQL SaveIrql;
01253
01254 RemainingName = *ObjectName;
01255
01256
01257
01258
01259
01260
01261
ObpBeginTypeSpecificCallOut( SaveIrql );
01262
01263
Status = (*ObjectHeader->
Type->
TypeInfo.
ParseProcedure)( RootDirectory,
01264 ObjectType,
01265 AccessState,
01266 AccessMode,
01267 Attributes,
01268 ObjectName,
01269 &RemainingName,
01270 ParseContext,
01271
SecurityQos,
01272 &Object );
01273
01274
ObpEndTypeSpecificCallOut( SaveIrql,
"Parse", ObjectHeader->
Type, Object );
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
if ( (
Status != STATUS_REPARSE ) &&
01288 (
Status != STATUS_REPARSE_OBJECT )) {
01289
01290
if (!
NT_SUCCESS(
Status )) {
01291
01292 Object =
NULL;
01293
01294 }
else if (Object ==
NULL) {
01295
01296
Status = STATUS_OBJECT_NAME_NOT_FOUND;
01297 }
01298
01299
ObDereferenceObject( RootDirectory );
01300
01301 *FoundObject = Object;
01302
01303
return(
Status );
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313 }
else if ((ObjectName->Length == 0) ||
01314 (ObjectName->Buffer ==
NULL) ||
01315 (*(ObjectName->Buffer) == OBJ_NAME_PATH_SEPARATOR)) {
01316
01317
01318
01319
01320
01321
ObDereferenceObject( RootDirectory );
01322
01323 RootDirectory =
ObpRootDirectoryObject;
01324 RootDirectoryHandle =
NULL;
01325
01326
break;
01327
01328
01329
01330
01331
01332
01333
01334 }
else if (--MaxReparse) {
01335
01336
continue;
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346 }
else {
01347
01348
ObDereferenceObject( RootDirectory );
01349
01350 *FoundObject = Object;
01351
01352
01353
01354
01355
01356
01357
01358
if (Object ==
NULL) {
01359
01360
Status = STATUS_OBJECT_NAME_NOT_FOUND;
01361 }
01362
01363
return(
Status );
01364 }
01365 }
01366 }
01367
01368
01369
01370
01371
01372
01373
01374 }
else if ((ObjectName->Length == 0) ||
01375 (ObjectName->Buffer ==
NULL)) {
01376
01377
Status =
ObReferenceObjectByPointer( RootDirectory,
01378 0,
01379 ObjectType,
01380 AccessMode );
01381
01382
if (
NT_SUCCESS(
Status )) {
01383
01384 Object = RootDirectory;
01385 }
01386
01387
ObDereferenceObject( RootDirectory );
01388
01389 *FoundObject = Object;
01390
01391
return(
Status );
01392 }
01393
01394
01395
01396
01397
01398
01399 }
else {
01400
01401 RootDirectory =
ObpRootDirectoryObject;
01402
01403
01404
01405
01406
01407
01408
if ((ObjectName->Length == 0) ||
01409 (ObjectName->Buffer ==
NULL) ||
01410 (*(ObjectName->Buffer) != OBJ_NAME_PATH_SEPARATOR)) {
01411
01412
return( STATUS_OBJECT_PATH_SYNTAX_BAD );
01413 }
01414
01415
01416
01417
01418
01419
01420
01421
if (ObjectName->Length ==
sizeof( OBJ_NAME_PATH_SEPARATOR )) {
01422
01423
01424
01425
01426
01427
01428
01429
01430
if (!RootDirectory) {
01431
01432
if (InsertObject) {
01433
01434
Status =
ObReferenceObjectByPointer( InsertObject,
01435 0,
01436 ObjectType,
01437 AccessMode );
01438
01439
if (
NT_SUCCESS(
Status )) {
01440
01441 *FoundObject = InsertObject;
01442 }
01443
01444
return(
Status );
01445
01446 }
else {
01447
01448
return( STATUS_INVALID_PARAMETER );
01449 }
01450
01451
01452
01453
01454
01455
01456
01457 }
else {
01458
01459
Status =
ObReferenceObjectByPointer( RootDirectory,
01460 0,
01461 ObjectType,
01462 AccessMode );
01463
01464
if (
NT_SUCCESS(
Status )) {
01465
01466 *FoundObject = RootDirectory;
01467 }
01468
01469
return(
Status );
01470 }
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483 }
else {
01484
01485 KIRQL OldIrql;
01486
01487 ExAcquireSpinLock( &
ObpDeviceMapLock, &OldIrql );
01488
01489
if ((DeviceMap =
PsGetCurrentProcess()->DeviceMap) !=
NULL) {
01490
01491 DeviceMap->
ReferenceCount++;
01492 ExReleaseSpinLock( &
ObpDeviceMapLock, OldIrql );
01493
01494
if (!((ULONG_PTR)(ObjectName->Buffer) & (
sizeof(ULONGLONG)-1))
01495
01496 &&
01497
01498 (DeviceMap->
DosDevicesDirectory !=
NULL )) {
01499
01500
01501
01502
01503
01504
01505
if ((ObjectName->Length >=
ObpDosDevicesShortName.Length)
01506
01507 &&
01508
01509 (*(PULONGLONG)(ObjectName->Buffer) ==
ObpDosDevicesShortNamePrefix.QuadPart)) {
01510
01511
01512
01513
01514
01515
01516
01517 *DirectoryLocked =
TRUE;
01518
01519
ObpEnterRootDirectoryMutex();
01520
01521 ParentDirectory = RootDirectory;
01522
01523
Directory = DeviceMap->
DosDevicesDirectory;
01524
01525 RemainingName = *ObjectName;
01526 RemainingName.Buffer += (
ObpDosDevicesShortName.Length /
sizeof( WCHAR ));
01527 RemainingName.Length -=
ObpDosDevicesShortName.Length;
01528
01529
goto quickStart;
01530
01531
01532
01533
01534
01535
01536 }
else if ((ObjectName->Length ==
ObpDosDevicesShortName.Length -
sizeof( WCHAR ))
01537
01538 &&
01539
01540 (*(PULONG)(ObjectName->Buffer) ==
ObpDosDevicesShortNameRoot.LowPart)
01541
01542 &&
01543
01544 (*((PWCHAR)(ObjectName->Buffer)+2) == (WCHAR)(
ObpDosDevicesShortNameRoot.HighPart))) {
01545
01546
01547
01548
01549
01550
01551
Status =
ObReferenceObjectByPointer( DeviceMap->
DosDevicesDirectory,
01552 0,
01553 ObjectType,
01554 AccessMode );
01555
01556
if (
NT_SUCCESS(
Status )) {
01557
01558 *FoundObject = DeviceMap->
DosDevicesDirectory;
01559 }
01560
01561
01562
01563
01564
01565 {
01566 KIRQL OldIrql;
01567
01568 ExAcquireSpinLock( &
ObpDeviceMapLock, &OldIrql );
01569
01570 DeviceMap->
ReferenceCount--;
01571
01572
if (DeviceMap->
ReferenceCount == 0) {
01573
01574 ExReleaseSpinLock( &
ObpDeviceMapLock, OldIrql );
01575
01576 DeviceMap->
DosDevicesDirectory->
DeviceMap =
NULL;
01577
ObDereferenceObject( DeviceMap->
DosDevicesDirectory );
01578
01579
ExFreePool( DeviceMap );
01580
01581 }
else {
01582
01583 ExReleaseSpinLock( &
ObpDeviceMapLock, OldIrql );
01584 }
01585 }
01586
01587
return(
Status );
01588 }
01589 }
01590
01591 }
else {
01592
01593 ExReleaseSpinLock( &
ObpDeviceMapLock, OldIrql );
01594 }
01595 }
01596 }
01597
01598
01599
01600
01601
01602
01603
01604
01605
01606
01607
01608
01609
01610
01611
01612
01613 Reparse =
TRUE;
01614 MaxReparse = OBJ_MAX_REPARSE_ATTEMPTS;
01615
01616
while (Reparse) {
01617
01618 RemainingName = *ObjectName;
01619
01620 quickStart:
01621
01622 Reparse =
FALSE;
01623
01624
while (
TRUE) {
01625
01626 Object =
NULL;
01627
01628
01629
01630
01631
01632
01633
01634
01635
01636
01637
01638
if ( (RemainingName.Length != 0) &&
01639 (*(RemainingName.Buffer) == OBJ_NAME_PATH_SEPARATOR) ) {
01640
01641 RemainingName.Buffer++;
01642 RemainingName.Length -=
sizeof( OBJ_NAME_PATH_SEPARATOR );
01643 }
01644
01645
01646
01647
01648
01649
01650
01651 ComponentName = RemainingName;
01652
01653
while (RemainingName.Length != 0) {
01654
01655
if (*(RemainingName.Buffer) == OBJ_NAME_PATH_SEPARATOR) {
01656
01657
break;
01658 }
01659
01660 RemainingName.Buffer++;
01661 RemainingName.Length -=
sizeof( OBJ_NAME_PATH_SEPARATOR );
01662 }
01663
01664 ComponentName.Length -= RemainingName.Length;
01665
01666
if (ComponentName.Length == 0) {
01667
01668
Status = STATUS_OBJECT_NAME_INVALID;
01669
break;
01670 }
01671
01672
01673
01674
01675
01676
01677
if (!*DirectoryLocked) {
01678
01679 *DirectoryLocked =
TRUE;
01680
ObpEnterRootDirectoryMutex();
01681
Directory = RootDirectory;
01682 }
01683
01684
01685
01686
01687
01688
01689
01690
01691
01692
if ( !(AccessState->Flags &
TOKEN_HAS_TRAVERSE_PRIVILEGE) && (ParentDirectory !=
NULL) ) {
01693
01694
if (!
ObpCheckTraverseAccess( ParentDirectory,
01695 DIRECTORY_TRAVERSE,
01696 AccessState,
01697
FALSE,
01698 AccessMode,
01699 &
Status )) {
01700
01701
break;
01702 }
01703 }
01704
01705
01706
01707
01708
01709
01710 Object =
ObpLookupDirectoryEntry(
Directory, &ComponentName, Attributes );
01711
01712
if (!Object) {
01713
01714
01715
01716
01717
01718
01719
01720
01721
01722
if (RemainingName.Length != 0) {
01723
01724
Status = STATUS_OBJECT_PATH_NOT_FOUND;
01725
break;
01726 }
01727
01728
if (!InsertObject) {
01729
01730
Status = STATUS_OBJECT_NAME_NOT_FOUND;
01731
break;
01732 }
01733
01734
01735
01736
01737
01738
01739
01740
01741
01742
if (!
ObCheckCreateObjectAccess(
Directory,
01743 ObjectType ==
ObpDirectoryObjectType ?
01744 DIRECTORY_CREATE_SUBDIRECTORY :
01745 DIRECTORY_CREATE_OBJECT,
01746 AccessState,
01747 &ComponentName,
01748
FALSE,
01749 AccessMode,
01750 &
Status )) {
01751
01752
break;
01753 }
01754
01755
01756
01757
01758
01759
01760
01761
NewName =
ExAllocatePoolWithTag(
PagedPool, ComponentName.Length, 'mNbO' );
01762
01763
if ((
NewName ==
NULL) ||
01764 !
ObpInsertDirectoryEntry(
Directory, InsertObject )) {
01765
01766
if (
NewName !=
NULL) {
01767
01768
ExFreePool(
NewName );
01769 }
01770
01771
Status = STATUS_INSUFFICIENT_RESOURCES;
01772
break;
01773 }
01774
01775
01776
01777
01778
01779
01780
01781
ObReferenceObject( InsertObject );
01782
01783 ObjectHeader =
OBJECT_TO_OBJECT_HEADER( InsertObject );
01784
01785 NameInfo =
OBJECT_HEADER_TO_NAME_INFO( ObjectHeader );
01786
01787
ObReferenceObject(
Directory );
01788
01789 RtlMoveMemory(
NewName,
01790 ComponentName.Buffer,
01791 ComponentName.Length );
01792
01793
if (NameInfo->
Name.Buffer) {
01794
01795
ExFreePool( NameInfo->
Name.Buffer );
01796 }
01797
01798 NameInfo->
Name.Buffer =
NewName;
01799 NameInfo->
Name.Length = ComponentName.Length;
01800 NameInfo->
Name.MaximumLength = ComponentName.Length;
01801
01802 Object = InsertObject;
01803
01804
Status = STATUS_SUCCESS;
01805
01806
break;
01807 }
01808
01809
01810
01811
01812
01813
01814
01815 ReparseObject:
01816
01817 ObjectHeader =
OBJECT_TO_OBJECT_HEADER( Object );
01818 ParseProcedure = ObjectHeader->
Type->
TypeInfo.
ParseProcedure;
01819
01820
01821
01822
01823
01824
01825
01826
if (ParseProcedure && (!InsertObject || (ParseProcedure ==
ObpParseSymbolicLink))) {
01827
01828 KIRQL SaveIrql;
01829
01830
01831
01832
01833
01834
01835
01836
ObpIncrPointerCount( ObjectHeader );
01837
01838
ASSERT(*DirectoryLocked);
01839
01840
ObpLeaveRootDirectoryMutex();
01841
01842 *DirectoryLocked =
FALSE;
01843
01844
ObpBeginTypeSpecificCallOut( SaveIrql );
01845
01846
01847
01848
01849
01850
Status = (*ParseProcedure)( Object,
01851 (PVOID)ObjectType,
01852 AccessState,
01853 AccessMode,
01854 Attributes,
01855 ObjectName,
01856 &RemainingName,
01857 ParseContext,
01858
SecurityQos,
01859 &Object );
01860
01861
ObpEndTypeSpecificCallOut( SaveIrql,
"Parse", ObjectHeader->
Type, Object );
01862
01863
01864
01865
01866
01867
ObDereferenceObject( &ObjectHeader->
Body );
01868
01869
01870
01871
01872
01873
if ((
Status == STATUS_REPARSE) || (
Status == STATUS_REPARSE_OBJECT)) {
01874
01875
01876
01877
01878
01879
01880
if (--MaxReparse) {
01881
01882
01883
01884
01885
01886 Reparse =
TRUE;
01887
01888
01889
01890
01891
01892
01893
if ((
Status == STATUS_REPARSE_OBJECT) ||
01894 (*(ObjectName->Buffer) == OBJ_NAME_PATH_SEPARATOR)) {
01895
01896
01897
01898
01899
01900
01901
01902
if (ARGUMENT_PRESENT( RootDirectoryHandle )) {
01903
01904
ObDereferenceObject( RootDirectory );
01905 RootDirectoryHandle =
NULL;
01906 }
01907
01908
01909
01910
01911
01912
01913 ParentDirectory =
NULL;
01914 RootDirectory =
ObpRootDirectoryObject;
01915
01916
01917
01918
01919
01920
01921
01922
01923
01924
01925
if (
Status == STATUS_REPARSE_OBJECT) {
01926
01927 Reparse =
FALSE;
01928
01929
if (Object ==
NULL) {
01930
01931
Status = STATUS_OBJECT_NAME_NOT_FOUND;
01932
01933 }
else {
01934
01935
01936
01937
01938
01939
01940
01941 *DirectoryLocked =
TRUE;
01942
ObpEnterRootDirectoryMutex();
01943
01944
goto ReparseObject;
01945 }
01946 }
01947
01948
01949
01950
01951
01952
01953
01954
01955
01956
01957
01958 }
else if (RootDirectory ==
ObpRootDirectoryObject) {
01959
01960 Object =
NULL;
01961
Status = STATUS_OBJECT_NAME_NOT_FOUND;
01962
01963 Reparse =
FALSE;
01964 }
01965
01966 }
else {
01967
01968
01969
01970
01971
01972
01973 Object =
NULL;
01974
Status = STATUS_OBJECT_NAME_NOT_FOUND;
01975 }
01976
01977
01978
01979
01980
01981
01982 }
else if (!
NT_SUCCESS(
Status )) {
01983
01984 Object =
NULL;
01985
01986
01987
01988
01989
01990
01991
01992
01993
01994
01995 }
else if (Object ==
NULL) {
01996
01997
Status = STATUS_OBJECT_NAME_NOT_FOUND;
01998 }
01999
02000
break;
02001
02002 }
else {
02003
02004
02005
02006
02007
02008
02009
02010
02011
02012
if (RemainingName.Length == 0) {
02013
02014
02015
02016
02017
02018
02019
02020
if (!InsertObject) {
02021
02022
02023
02024
02025
02026
02027
02028
02029
if ( !(AccessState->Flags &
TOKEN_HAS_TRAVERSE_PRIVILEGE) ) {
02030
02031
if (!
ObpCheckTraverseAccess(
Directory,
02032 DIRECTORY_TRAVERSE,
02033 AccessState,
02034
FALSE,
02035 AccessMode,
02036 &
Status )) {
02037
02038 Object =
NULL;
02039
break;
02040 }
02041 }
02042
02043
Status =
ObReferenceObjectByPointer( Object,
02044 0,
02045 ObjectType,
02046 AccessMode );
02047
02048
if (!
NT_SUCCESS(
Status )) {
02049
02050 Object =
NULL;
02051 }
02052 }
02053
02054
break;
02055
02056 }
else {
02057
02058
02059
02060
02061
02062
02063
02064
02065
if (ObjectHeader->
Type ==
ObpDirectoryObjectType) {
02066
02067 ParentDirectory =
Directory;
02068
Directory = (
POBJECT_DIRECTORY)Object;
02069
02070 }
else {
02071
02072
02073
02074
02075
02076
02077
02078
Status = STATUS_OBJECT_TYPE_MISMATCH;
02079 Object =
NULL;
02080
02081
break;
02082 }
02083 }
02084 }
02085 }
02086 }
02087
02088
02089
02090
02091
02092
if (DeviceMap !=
NULL) {
02093
02094 KIRQL OldIrql;
02095
02096 ExAcquireSpinLock( &
ObpDeviceMapLock, &OldIrql );
02097
02098 DeviceMap->
ReferenceCount--;
02099
02100
if (DeviceMap->
ReferenceCount == 0) {
02101
02102 ExReleaseSpinLock( &
ObpDeviceMapLock, OldIrql );
02103
02104 DeviceMap->
DosDevicesDirectory->
DeviceMap =
NULL;
02105
ObDereferenceObject( DeviceMap->
DosDevicesDirectory );
02106
02107
ExFreePool( DeviceMap );
02108
02109 }
else {
02110
02111 ExReleaseSpinLock( &
ObpDeviceMapLock, OldIrql );
02112 }
02113 }
02114
02115
02116
02117
02118
02119
02120
02121
02122
02123
02124
if (!(*FoundObject = Object)) {
02125
02126
if (
Status == STATUS_REPARSE) {
02127
02128
Status = STATUS_OBJECT_NAME_NOT_FOUND;
02129
02130 }
else if (
NT_SUCCESS(
Status )) {
02131
02132
Status = STATUS_OBJECT_NAME_NOT_FOUND;
02133 }
02134 }
02135
02136
02137
02138
02139
02140
02141
if (ARGUMENT_PRESENT( RootDirectoryHandle )) {
02142
02143
ObDereferenceObject( RootDirectory );
02144 RootDirectoryHandle =
NULL;
02145 }
02146
02147
02148
02149
02150
02151
return(
Status );
02152 }
02153
02154