ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

obname.c
Go to the documentation of this file.
00001 /*
00002  * PROJECT:         ReactOS Kernel
00003  * LICENSE:         GPL - See COPYING in the top level directory
00004  * FILE:            ntoskrnl/ob/obname.c
00005  * PURPOSE:         Manages all functions related to the Object Manager name-
00006  *                  space, such as finding objects or querying their names.
00007  * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
00008  *                  Eric Kohl
00009  *                  Thomas Weidenmueller (w3seek@reactos.org)
00010  */
00011 
00012 /* INCLUDES ******************************************************************/
00013 
00014 #include <ntoskrnl.h>
00015 #define NDEBUG
00016 #include <debug.h>
00017 
00018 BOOLEAN ObpCaseInsensitive = TRUE;
00019 POBJECT_DIRECTORY ObpRootDirectoryObject;
00020 POBJECT_DIRECTORY ObpTypeDirectoryObject;
00021 
00022 /* DOS Device Prefix \??\ and \?? */
00023 ALIGNEDNAME ObpDosDevicesShortNamePrefix = {{L'\\',L'?',L'?',L'\\'}};
00024 ALIGNEDNAME ObpDosDevicesShortNameRoot = {{L'\\',L'?',L'?',L'\0'}};
00025 UNICODE_STRING ObpDosDevicesShortName =
00026 {
00027     sizeof(ObpDosDevicesShortNamePrefix),
00028     sizeof(ObpDosDevicesShortNamePrefix),
00029     (PWSTR)&ObpDosDevicesShortNamePrefix
00030 };
00031 
00032 /* PRIVATE FUNCTIONS *********************************************************/
00033 
00034 NTSTATUS
00035 NTAPI
00036 INIT_FUNCTION
00037 ObpCreateDosDevicesDirectory(VOID)
00038 {
00039     OBJECT_ATTRIBUTES ObjectAttributes;
00040     UNICODE_STRING Name, LinkName;
00041     HANDLE Handle, SymHandle;
00042     NTSTATUS Status;
00043 
00044     /* Create the '\??' directory */
00045     RtlInitUnicodeString(&Name, L"\\??");
00046     InitializeObjectAttributes(&ObjectAttributes,
00047                                &Name,
00048                                OBJ_PERMANENT,
00049                                NULL,
00050                                NULL);
00051     Status = NtCreateDirectoryObject(&Handle,
00052                                      DIRECTORY_ALL_ACCESS,
00053                                      &ObjectAttributes);
00054     if (!NT_SUCCESS(Status)) return FALSE;
00055 
00056     /* Initialize the GLOBALROOT path */
00057     RtlInitUnicodeString(&LinkName, L"GLOBALROOT");
00058     RtlInitUnicodeString(&Name, L"");
00059     InitializeObjectAttributes(&ObjectAttributes,
00060                                &LinkName,
00061                                OBJ_PERMANENT,
00062                                Handle,
00063                                NULL);
00064     Status = NtCreateSymbolicLinkObject(&SymHandle,
00065                                         SYMBOLIC_LINK_ALL_ACCESS,
00066                                         &ObjectAttributes,
00067                                         &Name);
00068     if (NT_SUCCESS(Status)) NtClose(SymHandle);
00069 
00070     /* Link \??\Global to \?? */
00071     RtlInitUnicodeString(&LinkName, L"Global");
00072     RtlInitUnicodeString(&Name, L"\\??");
00073     InitializeObjectAttributes(&ObjectAttributes,
00074                                &LinkName,
00075                                OBJ_PERMANENT,
00076                                Handle,
00077                                NULL);
00078     Status = NtCreateSymbolicLinkObject(&SymHandle,
00079                                         SYMBOLIC_LINK_ALL_ACCESS,
00080                                         &ObjectAttributes,
00081                                         &Name);
00082     if (NT_SUCCESS(Status)) NtClose(SymHandle);
00083 
00084     /* Close the directory handle */
00085     NtClose(Handle);
00086     if (!NT_SUCCESS(Status)) return Status;
00087 
00088     /* Create link from '\DosDevices' to '\??' directory */
00089     RtlCreateUnicodeString(&LinkName, L"\\DosDevices");
00090     InitializeObjectAttributes(&ObjectAttributes,
00091                                &LinkName,
00092                                OBJ_PERMANENT,
00093                                NULL,
00094                                NULL);
00095     Status = NtCreateSymbolicLinkObject(&SymHandle,
00096                                         SYMBOLIC_LINK_ALL_ACCESS,
00097                                         &ObjectAttributes,
00098                                         &Name);
00099     if (NT_SUCCESS(Status)) NtClose(SymHandle);
00100 
00101     /* FIXME: Hack Hack! */
00102     ObSystemDeviceMap = ExAllocatePoolWithTag(NonPagedPool,
00103                                               sizeof(*ObSystemDeviceMap),
00104                                               'mDbO');
00105     if (!ObSystemDeviceMap) return STATUS_INSUFFICIENT_RESOURCES;
00106     RtlZeroMemory(ObSystemDeviceMap, sizeof(*ObSystemDeviceMap));
00107 
00108     /* Return status */
00109     return Status;
00110 }
00111 
00112 VOID
00113 NTAPI
00114 ObDereferenceDeviceMap(IN PEPROCESS Process)
00115 {
00116     PDEVICE_MAP DeviceMap;
00117 
00118     /* Get the pointer to this process devicemap and reset it
00119        holding devicemap lock */
00120     KeAcquireGuardedMutex(&ObpDeviceMapLock);
00121     DeviceMap = Process->DeviceMap;
00122     Process->DeviceMap = NULL;
00123     KeReleaseGuardedMutex(&ObpDeviceMapLock);
00124 
00125     /* Continue only if there is a devicemap to dereference */
00126     if (DeviceMap)
00127     {
00128         KeAcquireGuardedMutex(&ObpDeviceMapLock);
00129 
00130         /* Delete the device map link and dereference it */
00131         if (--DeviceMap->ReferenceCount)
00132         {
00133             /* Nobody is referencing it anymore, unlink the DOS directory */
00134             DeviceMap->DosDevicesDirectory->DeviceMap = NULL;
00135 
00136             /* Release the devicemap lock */
00137             KeReleaseGuardedMutex(&ObpDeviceMapLock);
00138 
00139             /* Dereference the DOS Devices Directory and free the Device Map */
00140             ObDereferenceObject(DeviceMap->DosDevicesDirectory);
00141             ExFreePool(DeviceMap);
00142         }
00143         else
00144         {
00145             /* Release the devicemap lock */
00146             KeReleaseGuardedMutex(&ObpDeviceMapLock);
00147         }
00148     }
00149 }
00150 
00151 VOID
00152 NTAPI
00153 ObInheritDeviceMap(IN PEPROCESS Parent,
00154                    IN PEPROCESS Process)
00155 {
00156     /* FIXME: Devicemap Support */
00157 }
00158 
00159 /*++
00160 * @name ObpDeleteNameCheck
00161 *
00162 *     The ObpDeleteNameCheck routine checks if a named object should be
00163 *     removed from the object directory namespace.
00164 *
00165 * @param Object
00166 *        Pointer to the object to check for possible removal.
00167 *
00168 * @return None.
00169 *
00170 * @remarks An object is removed if the following 4 criteria are met:
00171 *          1) The object has 0 handles open
00172 *          2) The object is in the directory namespace and has a name
00173 *          3) The object is not permanent
00174 *
00175 *--*/
00176 VOID
00177 NTAPI
00178 ObpDeleteNameCheck(IN PVOID Object)
00179 {
00180     POBJECT_HEADER ObjectHeader;
00181     OBP_LOOKUP_CONTEXT Context;
00182     POBJECT_HEADER_NAME_INFO ObjectNameInfo;
00183     POBJECT_TYPE ObjectType;
00184     PVOID Directory = NULL;
00185 
00186     /* Get object structures */
00187     ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
00188     ObjectNameInfo = ObpReferenceNameInfo(ObjectHeader);
00189     ObjectType = ObjectHeader->Type;
00190 
00191     /*
00192      * Check if the handle count is 0, if the object is named,
00193      * and if the object isn't a permanent object.
00194      */
00195     if (!(ObjectHeader->HandleCount) &&
00196          (ObjectNameInfo) &&
00197          (ObjectNameInfo->Name.Length) &&
00198          (ObjectNameInfo->Directory) &&
00199          !(ObjectHeader->Flags & OB_FLAG_PERMANENT))
00200     {
00201         /* Setup a lookup context */
00202         ObpInitializeLookupContext(&Context);
00203 
00204         /* Lock the directory */
00205         ObpAcquireDirectoryLockExclusive(ObjectNameInfo->Directory, &Context);
00206 
00207         /* Do the lookup */
00208         Object = ObpLookupEntryDirectory(ObjectNameInfo->Directory,
00209                                          &ObjectNameInfo->Name,
00210                                          0,
00211                                          FALSE,
00212                                          &Context);
00213         if (Object)
00214         {
00215             /* Lock the object */
00216             ObpAcquireObjectLock(ObjectHeader);
00217 
00218             /* Make sure we can still delete the object */
00219             if (!(ObjectHeader->HandleCount) &&
00220                 !(ObjectHeader->Flags & OB_FLAG_PERMANENT))
00221             {
00222                 /* First delete it from the directory */
00223                 ObpDeleteEntryDirectory(&Context);
00224 
00225                 /* Check if this is a symbolic link */
00226                 if (ObjectType == ObSymbolicLinkType)
00227                 {
00228                     /* Remove internal name */
00229                     ObpDeleteSymbolicLinkName(Object);
00230                 }
00231 
00232                 /* Check if the magic protection flag is set */
00233                 ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
00234                 if ((ObjectNameInfo) &&
00235                     (ObjectNameInfo->QueryReferences & 0x40000000))
00236                 {
00237                     /* Remove protection flag */
00238                     InterlockedExchangeAdd((PLONG)&ObjectNameInfo->QueryReferences,
00239                                            -0x40000000);
00240                 }
00241 
00242                 /* Get the directory */
00243                 Directory = ObjectNameInfo->Directory;
00244             }
00245 
00246             /* Release the lock */
00247             ObpReleaseObjectLock(ObjectHeader);
00248         }
00249 
00250         /* Cleanup after lookup */
00251         ObpReleaseLookupContext(&Context);
00252 
00253         /* Remove another query reference since we added one on top */
00254         ObpDereferenceNameInfo(ObjectNameInfo);
00255 
00256         /* Check if we were inserted in a directory */
00257         if (Directory)
00258         {
00259             /* We were, so first remove the extra reference we had added */
00260             ObpDereferenceNameInfo(ObjectNameInfo);
00261 
00262             /* Now dereference the object as well */
00263             ObDereferenceObject(Object);
00264         }
00265     }
00266     else
00267     {
00268         /* Remove the reference we added */
00269         ObpDereferenceNameInfo(ObjectNameInfo);
00270     }
00271 }
00272 
00273 NTSTATUS
00274 NTAPI
00275 ObpLookupObjectName(IN HANDLE RootHandle OPTIONAL,
00276                     IN PUNICODE_STRING ObjectName,
00277                     IN ULONG Attributes,
00278                     IN POBJECT_TYPE ObjectType,
00279                     IN KPROCESSOR_MODE AccessMode,
00280                     IN OUT PVOID ParseContext,
00281                     IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL,
00282                     IN PVOID InsertObject OPTIONAL,
00283                     IN OUT PACCESS_STATE AccessState,
00284                     OUT POBP_LOOKUP_CONTEXT LookupContext,
00285                     OUT PVOID *FoundObject)
00286 {
00287     PVOID Object;
00288     POBJECT_HEADER ObjectHeader;
00289     UNICODE_STRING ComponentName, RemainingName;
00290     BOOLEAN Reparse = FALSE, SymLink = FALSE;
00291     POBJECT_DIRECTORY Directory = NULL, ParentDirectory = NULL, RootDirectory;
00292     POBJECT_DIRECTORY ReferencedDirectory = NULL, ReferencedParentDirectory = NULL;
00293     KIRQL CalloutIrql;
00294     OB_PARSE_METHOD ParseRoutine;
00295     NTSTATUS Status;
00296     KPROCESSOR_MODE AccessCheckMode;
00297     PWCHAR NewName;
00298     POBJECT_HEADER_NAME_INFO ObjectNameInfo;
00299     ULONG MaxReparse = 30;
00300     PAGED_CODE();
00301     OBTRACE(OB_NAMESPACE_DEBUG,
00302             "%s - Finding Object: %wZ. Expecting: %p\n",
00303             __FUNCTION__,
00304             ObjectName,
00305             InsertObject);
00306 
00307     /* Initialize starting state */
00308     ObpInitializeLookupContext(LookupContext);
00309     *FoundObject = NULL;
00310     Status = STATUS_SUCCESS;
00311     Object = NULL;
00312 
00313     /* Check if case-insensitivity is checked */
00314     if (ObpCaseInsensitive)
00315     {
00316         /* Check if the object type requests this */
00317         if (!(ObjectType) || (ObjectType->TypeInfo.CaseInsensitive))
00318         {
00319             /* Add the flag to disable case sensitivity */
00320             Attributes |= OBJ_CASE_INSENSITIVE;
00321         }
00322     }
00323 
00324     /* Check if this is a access checks are being forced */
00325     AccessCheckMode = (Attributes & OBJ_FORCE_ACCESS_CHECK) ?
00326                        UserMode : AccessMode;
00327 
00328     /* Check if we got a Root Directory */
00329     if (RootHandle)
00330     {
00331         /* We did. Reference it */
00332         Status = ObReferenceObjectByHandle(RootHandle,
00333                                            0,
00334                                            NULL,
00335                                            AccessMode,
00336                                            (PVOID*)&RootDirectory,
00337                                            NULL);
00338         if (!NT_SUCCESS(Status)) return Status;
00339 
00340         /* Get the header */
00341         ObjectHeader = OBJECT_TO_OBJECT_HEADER(RootDirectory);
00342 
00343         /* The name cannot start with a separator, unless this is a file */
00344         if ((ObjectName->Buffer) &&
00345             (ObjectName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR) &&
00346             (ObjectHeader->Type != IoFileObjectType))
00347         {
00348             /* The syntax is bad, so fail this request */
00349             ObDereferenceObject(RootDirectory);
00350             return STATUS_OBJECT_PATH_SYNTAX_BAD;
00351         }
00352 
00353         /* Don't parse a Directory */
00354         if (ObjectHeader->Type != ObDirectoryType)
00355         {
00356             /* Make sure the Object Type has a parse routine */
00357             ParseRoutine = ObjectHeader->Type->TypeInfo.ParseProcedure;
00358             if (!ParseRoutine)
00359             {
00360                 /* We can't parse a name if we don't have a parse routine */
00361                 ObDereferenceObject(RootDirectory);
00362                 return STATUS_INVALID_HANDLE;
00363             }
00364 
00365             /* Set default parse count */
00366             MaxReparse = 30;
00367 
00368             /* Now parse */
00369             while (TRUE)
00370             {
00371                 /* Start with the full name */
00372                 RemainingName = *ObjectName;
00373 
00374                 /* Call the Parse Procedure */
00375                 ObpCalloutStart(&CalloutIrql);
00376                 Status = ParseRoutine(RootDirectory,
00377                                       ObjectType,
00378                                       AccessState,
00379                                       AccessCheckMode,
00380                                       Attributes,
00381                                       ObjectName,
00382                                       &RemainingName,
00383                                       ParseContext,
00384                                       SecurityQos,
00385                                       &Object);
00386                 ObpCalloutEnd(CalloutIrql, "Parse", ObjectHeader->Type, Object);
00387 
00388                 /* Check for success or failure, so not reparse */
00389                 if ((Status != STATUS_REPARSE) &&
00390                     (Status != STATUS_REPARSE_OBJECT))
00391                 {
00392                     /* Check for failure */
00393                     if (!NT_SUCCESS(Status))
00394                     {
00395                         /* Parse routine might not have cleared this, do it */
00396                         Object = NULL;
00397                     }
00398                     else if (!Object)
00399                     {
00400                         /* Modify status to reflect failure inside Ob */
00401                         Status = STATUS_OBJECT_NAME_NOT_FOUND;
00402                     }
00403 
00404                     /* We're done, return the status and object */
00405                     *FoundObject = Object;
00406                     ObDereferenceObject(RootDirectory);
00407                     return Status;
00408                 }
00409                 else if ((!ObjectName->Length) ||
00410                          (!ObjectName->Buffer) ||
00411                          (ObjectName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR))
00412                 {
00413                     /* Reparsed to the root directory, so start over */
00414                     ObDereferenceObject(RootDirectory);
00415                     RootDirectory = ObpRootDirectoryObject;
00416 
00417                     /* Don't use this anymore, since we're starting at root */
00418                     RootHandle = NULL;
00419                     goto ParseFromRoot;
00420                 }
00421                 else if (--MaxReparse)
00422                 {
00423                     /* Try reparsing again */
00424                     continue;
00425                 }
00426                 else
00427                 {
00428                     /* Reparsed too many times */
00429                     ObDereferenceObject(RootDirectory);
00430 
00431                     /* Return the object and normalized status */
00432                     *FoundObject = Object;
00433                     if (!Object) Status = STATUS_OBJECT_NAME_NOT_FOUND;
00434                     return Status;
00435                 }
00436             }
00437         }
00438         else if (!(ObjectName->Length) || !(ObjectName->Buffer))
00439         {
00440             /* Just return the Root Directory if we didn't get a name*/
00441             Status = ObReferenceObjectByPointer(RootDirectory,
00442                                                 0,
00443                                                 ObjectType,
00444                                                 AccessMode);
00445             if (NT_SUCCESS(Status)) Object = RootDirectory;
00446 
00447             /* Remove the first reference we added and return the object */
00448             ObDereferenceObject(RootDirectory);
00449             *FoundObject = Object;
00450             return Status;
00451         }
00452     }
00453     else
00454     {
00455         /* We did not get a Root Directory, so use the root */
00456         RootDirectory = ObpRootDirectoryObject;
00457 
00458         /* It must start with a path separator */
00459         if (!(ObjectName->Length) ||
00460             !(ObjectName->Buffer) ||
00461             (ObjectName->Buffer[0] != OBJ_NAME_PATH_SEPARATOR))
00462         {
00463             /* This name is invalid, so fail */
00464             return STATUS_OBJECT_PATH_SYNTAX_BAD;
00465         }
00466 
00467         /* Check if the name is only the path separator */
00468         if (ObjectName->Length == sizeof(OBJ_NAME_PATH_SEPARATOR))
00469         {
00470             /* So the caller only wants the root directory; do we have one? */
00471             if (!RootDirectory)
00472             {
00473                 /* This must be the first time we're creating it... right? */
00474                 if (InsertObject)
00475                 {
00476                     /* Yes, so return it to ObInsert so that it can create it */
00477                     Status = ObReferenceObjectByPointer(InsertObject,
00478                                                         0,
00479                                                         ObjectType,
00480                                                         AccessMode);
00481                     if (NT_SUCCESS(Status)) *FoundObject = InsertObject;
00482                     return Status;
00483                 }
00484                 else
00485                 {
00486                     /* This should never really happen */
00487                     ASSERT(FALSE);
00488                     return STATUS_INVALID_PARAMETER;
00489                 }
00490             }
00491             else
00492             {
00493                 /* We do have the root directory, so just return it */
00494                 Status = ObReferenceObjectByPointer(RootDirectory,
00495                                                     0,
00496                                                     ObjectType,
00497                                                     AccessMode);
00498                 if (NT_SUCCESS(Status)) *FoundObject = RootDirectory;
00499                 return Status;
00500             }
00501         }
00502         else
00503         {
00504 ParseFromRoot:
00505             /* FIXME: Check if we have a device map */
00506 
00507             /* Check if this is a possible DOS name */
00508             if (!((ULONG_PTR)(ObjectName->Buffer) & 7))
00509             {
00510                 /*
00511                  * This could be one. Does it match the prefix?
00512                  * Note that as an optimization, the match is done as 64-bit
00513                  * compare since the prefix is "\??\" which is exactly 8 bytes.
00514                  *
00515                  * In the second branch, we test for "\??" which is also valid.
00516                  * This time, we use a 32-bit compare followed by a Unicode
00517                  * character compare (16-bit), since the sum is 6 bytes.
00518                  */
00519                 if ((ObjectName->Length >= ObpDosDevicesShortName.Length) &&
00520                     (*(PULONGLONG)(ObjectName->Buffer) ==
00521                      ObpDosDevicesShortNamePrefix.Alignment.QuadPart))
00522                 {
00523                     /* FIXME! */
00524                 }
00525                 else if ((ObjectName->Length == ObpDosDevicesShortName.Length -
00526                                                 sizeof(WCHAR)) &&
00527                          (*(PULONG)(ObjectName->Buffer) ==
00528                           ObpDosDevicesShortNameRoot.Alignment.LowPart) &&
00529                          (*((PWCHAR)(ObjectName->Buffer) + 2) ==
00530                           (WCHAR)(ObpDosDevicesShortNameRoot.Alignment.HighPart)))
00531                 {
00532                     /* FIXME! */
00533                 }
00534             }
00535         }
00536     }
00537 
00538     /* Check if we were reparsing a symbolic link */
00539     if (!SymLink)
00540     {
00541         /* Allow reparse */
00542         Reparse = TRUE;
00543         MaxReparse = 30;
00544     }
00545 
00546     /* Reparse */
00547     while (Reparse && MaxReparse)
00548     {
00549         /* Get the name */
00550         RemainingName = *ObjectName;
00551 
00552         /* Disable reparsing again */
00553         Reparse = FALSE;
00554 
00555         /* Start parse loop */
00556         while (TRUE)
00557         {
00558             /* Clear object */
00559             Object = NULL;
00560 
00561             /* Check if the name starts with a path separator */
00562             if ((RemainingName.Length) &&
00563                 (RemainingName.Buffer[0] == OBJ_NAME_PATH_SEPARATOR))
00564             {
00565                 /* Skip the path separator */
00566                 RemainingName.Buffer++;
00567                 RemainingName.Length -= sizeof(OBJ_NAME_PATH_SEPARATOR);
00568             }
00569 
00570             /* Find the next Part Name */
00571             ComponentName = RemainingName;
00572             while (RemainingName.Length)
00573             {
00574                 /* Break if we found the \ ending */
00575                 if (RemainingName.Buffer[0] == OBJ_NAME_PATH_SEPARATOR) break;
00576 
00577                 /* Move on */
00578                 RemainingName.Buffer++;
00579                 RemainingName.Length -= sizeof(OBJ_NAME_PATH_SEPARATOR);
00580             }
00581 
00582             /* Get its size and make sure it's valid */
00583             ComponentName.Length -= RemainingName.Length;
00584             if (!ComponentName.Length)
00585             {
00586                 /* Invalid size, fail */
00587                 Status = STATUS_OBJECT_NAME_INVALID;
00588                 break;
00589             }
00590 
00591             /* Check if we're in the root */
00592             if (!Directory) Directory = RootDirectory;
00593 
00594             /* Check if this is a user-mode call that needs to traverse */
00595             if ((AccessCheckMode != KernelMode) &&
00596                 !(AccessState->Flags & TOKEN_HAS_TRAVERSE_PRIVILEGE))
00597             {
00598                 /* We shouldn't have referenced a directory yet */
00599                 ASSERT(ReferencedDirectory == NULL);
00600 
00601                 /* Reference the directory */
00602                 ObReferenceObject(Directory);
00603                 ReferencedDirectory = Directory;
00604 
00605                 /* Check if we have a parent directory */
00606                 if (ParentDirectory)
00607                 {
00608                     /* Check for traverse access */
00609                     if (!ObpCheckTraverseAccess(ParentDirectory,
00610                                                 DIRECTORY_TRAVERSE,
00611                                                 AccessState,
00612                                                 FALSE,
00613                                                 AccessCheckMode,
00614                                                 &Status))
00615                     {
00616                         /* We don't have it, fail */
00617                         break;
00618                     }
00619                 }
00620             }
00621 
00622             /* Check if we don't have a remaining name yet */
00623             if (!RemainingName.Length)
00624             {
00625                 /* Check if we don't have a referenced directory yet */
00626                 if (!ReferencedDirectory)
00627                 {
00628                     /* Reference it */
00629                     ObReferenceObject(Directory);
00630                     ReferencedDirectory = Directory;
00631                 }
00632 
00633                 /* Check if we are inserting an object */
00634                 if (InsertObject)
00635                 {
00636                     /* Lock the directory */
00637                     ObpAcquireDirectoryLockExclusive(Directory, LookupContext);
00638                 }
00639             }
00640 
00641             /* Do the lookup */
00642             Object = ObpLookupEntryDirectory(Directory,
00643                                              &ComponentName,
00644                                              Attributes,
00645                                              InsertObject ? FALSE : TRUE,
00646                                              LookupContext);
00647             if (!Object)
00648             {
00649                 /* We didn't find it... do we still have a path? */
00650                 if (RemainingName.Length)
00651                 {
00652                     /* Then tell the caller the path wasn't found */
00653                     Status = STATUS_OBJECT_PATH_NOT_FOUND;
00654                     break;
00655                 }
00656                 else if (!InsertObject)
00657                 {
00658                     /* Otherwise, we have a path, but the name isn't valid */
00659                     Status = STATUS_OBJECT_NAME_NOT_FOUND;
00660                     break;
00661                 }
00662 
00663                 /* Check create access for the object */
00664                 if (!ObCheckCreateObjectAccess(Directory,
00665                                                ObjectType == ObDirectoryType ?
00666                                                DIRECTORY_CREATE_SUBDIRECTORY :
00667                                                DIRECTORY_CREATE_OBJECT,
00668                                                AccessState,
00669                                                &ComponentName,
00670                                                FALSE,
00671                                                AccessCheckMode,
00672                                                &Status))
00673                 {
00674                     /* We don't have create access, fail */
00675                     break;
00676                 }
00677 
00678                 /* Get the object header */
00679                 ObjectHeader = OBJECT_TO_OBJECT_HEADER(InsertObject);
00680 
00681                 /* FIXME: Check if this is a Section Object or Sym Link */
00682                 /* FIXME: If it is, then check if this isn't session 0 */
00683                 /* FIXME: If it isn't, check for SeCreateGlobalPrivilege */
00684                 /* FIXME: If privilege isn't there, check for unsecure name */
00685                 /* FIXME: If it isn't a known unsecure name, then fail */
00686 
00687                 /* Create Object Name */
00688                 NewName = ExAllocatePoolWithTag(PagedPool,
00689                                                 ComponentName.Length,
00690                                                 OB_NAME_TAG);
00691                 if (!(NewName) ||
00692                     !(ObpInsertEntryDirectory(Directory,
00693                                               LookupContext,
00694                                               ObjectHeader)))
00695                 {
00696                     /* Either couldn't allocate the name, or insert failed */
00697                     if (NewName) ExFreePoolWithTag(NewName, OB_NAME_TAG);
00698 
00699                     /* Fail due to memory reasons */
00700                     Status = STATUS_INSUFFICIENT_RESOURCES;
00701                     break;
00702                 }
00703 
00704                 /* Reference newly to be inserted object */
00705                 ObReferenceObject(InsertObject);
00706 
00707                 /* Get the name information */
00708                 ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
00709 
00710                 /* Reference the directory */
00711                 ObReferenceObject(Directory);
00712 
00713                 /* Copy the Name */
00714                 RtlCopyMemory(NewName,
00715                               ComponentName.Buffer,
00716                               ComponentName.Length);
00717 
00718                 /* Check if we had an old name */
00719                 if (ObjectNameInfo->Name.Buffer)
00720                 {
00721                     /* Free it */
00722                     ExFreePoolWithTag(ObjectNameInfo->Name.Buffer, OB_NAME_TAG );
00723                 }
00724 
00725                 /* Write new one */
00726                 ObjectNameInfo->Name.Buffer = NewName;
00727                 ObjectNameInfo->Name.Length = ComponentName.Length;
00728                 ObjectNameInfo->Name.MaximumLength = ComponentName.Length;
00729 
00730                 /* Return Status and the Expected Object */
00731                 Status = STATUS_SUCCESS;
00732                 Object = InsertObject;
00733 
00734                 /* Get out of here */
00735                 break;
00736             }
00737 
00738 ReparseObject:
00739             /* We found it, so now get its header */
00740             ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
00741 
00742             /*
00743              * Check for a parse Procedure, but don't bother to parse for an insert
00744              * unless it's a Symbolic Link, in which case we MUST parse
00745              */
00746             ParseRoutine = ObjectHeader->Type->TypeInfo.ParseProcedure;
00747             if ((ParseRoutine) &&
00748                 (!(InsertObject) || (ParseRoutine == ObpParseSymbolicLink)))
00749             {
00750                 /* Use the Root Directory next time */
00751                 Directory = NULL;
00752 
00753                 /* Increment the pointer count */
00754                 InterlockedExchangeAdd(&ObjectHeader->PointerCount, 1);
00755 
00756                 /* Cleanup from the first lookup */
00757                 ObpReleaseLookupContext(LookupContext);
00758 
00759                 /* Check if we have a referenced directory */
00760                 if (ReferencedDirectory)
00761                 {
00762                     /* We do, dereference it */
00763                     ObDereferenceObject(ReferencedDirectory);
00764                     ReferencedDirectory = NULL;
00765                 }
00766 
00767                 /* Check if we have a referenced parent directory */
00768                 if (ReferencedParentDirectory)
00769                 {
00770                     /* We do, dereference it */
00771                     ObDereferenceObject(ReferencedParentDirectory);
00772                     ReferencedParentDirectory = NULL;
00773                 }
00774 
00775                 /* Call the Parse Procedure */
00776                 ObpCalloutStart(&CalloutIrql);
00777                 Status = ParseRoutine(Object,
00778                                       ObjectType,
00779                                       AccessState,
00780                                       AccessCheckMode,
00781                                       Attributes,
00782                                       ObjectName,
00783                                       &RemainingName,
00784                                       ParseContext,
00785                                       SecurityQos,
00786                                       &Object);
00787                 ObpCalloutEnd(CalloutIrql, "Parse", ObjectHeader->Type, Object);
00788 
00789                 /* Remove our extra reference */
00790                 ObDereferenceObject(&ObjectHeader->Body);
00791 
00792                 /* Check if we have to reparse */
00793                 if ((Status == STATUS_REPARSE) ||
00794                     (Status == STATUS_REPARSE_OBJECT))
00795                 {
00796                     /* Reparse again */
00797                     Reparse = TRUE;
00798                     --MaxReparse;
00799 
00800                     /* Start over from root if we got sent back there */
00801                     if ((Status == STATUS_REPARSE_OBJECT) ||
00802                         (ObjectName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR))
00803                     {
00804                         /* Check if we got a root directory */
00805                         if (RootHandle)
00806                         {
00807                             /* Stop using it, because we have a new directory now */
00808                             ObDereferenceObject(RootDirectory);
00809                             RootHandle = NULL;
00810                         }
00811 
00812                         /* Start at Root */
00813                         ParentDirectory = NULL;
00814                         RootDirectory = ObpRootDirectoryObject;
00815 
00816                         /* Check for reparse status */
00817                         if (Status == STATUS_REPARSE_OBJECT)
00818                         {
00819                             /* Don't reparse again */
00820                             Reparse = FALSE;
00821 
00822                             /* Did we actually get an object to which to reparse? */
00823                             if (!Object)
00824                             {
00825                                 /* We didn't, so set a failure status */
00826                                 Status = STATUS_OBJECT_NAME_NOT_FOUND;
00827                             }
00828                             else
00829                             {
00830                                 /* We did, so we're free to parse the new object */
00831                                 goto ReparseObject;
00832                             }
00833                         }
00834                         else
00835                         {
00836                             /* This is a symbolic link */
00837                             SymLink = TRUE;
00838                             goto ParseFromRoot;
00839                         }
00840                     }
00841                     else if (RootDirectory == ObpRootDirectoryObject)
00842                     {
00843                         /* We got STATUS_REPARSE but are at the Root Directory */
00844                         Object = NULL;
00845                         Status = STATUS_OBJECT_NAME_NOT_FOUND;
00846                         Reparse = FALSE;
00847                     }
00848                 }
00849                 else if (!NT_SUCCESS(Status))
00850                 {
00851                     /* Total failure */
00852                     Object = NULL;
00853                 }
00854                 else if (!Object)
00855                 {
00856                     /* We didn't reparse but we didn't find the Object Either */
00857                     Status = STATUS_OBJECT_NAME_NOT_FOUND;
00858                 }
00859 
00860                 /* Break out of the loop */
00861                 break;
00862             }
00863             else
00864             {
00865                 /* No parse routine...do we still have a remaining name? */
00866                 if (!RemainingName.Length)
00867                 {
00868                     /* Are we creating an object? */
00869                     if (!InsertObject)
00870                     {
00871                         /* Check if this is a user-mode call that needs to traverse */
00872                         if ((AccessCheckMode != KernelMode) &&
00873                             !(AccessState->Flags & TOKEN_HAS_TRAVERSE_PRIVILEGE))
00874                         {
00875                             /* Check if we can get it */
00876                             if (!ObpCheckTraverseAccess(Directory,
00877                                                         DIRECTORY_TRAVERSE,
00878                                                         AccessState,
00879                                                         FALSE,
00880                                                         AccessCheckMode,
00881                                                         &Status))
00882                             {
00883                                 /* We don't have access, fail */
00884                                 Object = NULL;
00885                                 break;
00886                             }
00887                         }
00888 
00889                         /* Reference the Object */
00890                         Status = ObReferenceObjectByPointer(Object,
00891                                                             0,
00892                                                             ObjectType,
00893                                                             AccessMode);
00894                         if (!NT_SUCCESS(Status)) Object = NULL;
00895                     }
00896 
00897                     /* And get out of the reparse loop */
00898                     break;
00899                 }
00900                 else
00901                 {
00902                     /* We still have a name; check if this is a directory object */
00903                     if (ObjectHeader->Type == ObDirectoryType)
00904                     {
00905                         /* Check if we have a referenced parent directory */
00906                         if (ReferencedParentDirectory)
00907                         {
00908                             /* Dereference it */
00909                             ObDereferenceObject(ReferencedParentDirectory);
00910                         }
00911 
00912                         /* Restart the lookup from this directory */
00913                         ReferencedParentDirectory = ReferencedDirectory;
00914                         ParentDirectory = Directory;
00915                         Directory = Object;
00916                         ReferencedDirectory = NULL;
00917                     }
00918                     else
00919                     {
00920                         /* We still have a name, but no parse routine for it */
00921                         Status = STATUS_OBJECT_TYPE_MISMATCH;
00922                         Object = NULL;
00923                         break;
00924                     }
00925                 }
00926             }
00927         }
00928     }
00929 
00930     /* Check if we failed */
00931     if (!NT_SUCCESS(Status))
00932     {
00933         /* Cleanup after lookup */
00934         ObpReleaseLookupContext(LookupContext);
00935     }
00936 
00937     /* Check if we have a device map and dereference it if so */
00938     //if (DeviceMap) ObfDereferenceDeviceMap(DeviceMap);
00939 
00940     /* Check if we have a referenced directory and dereference it if so */
00941     if (ReferencedDirectory) ObDereferenceObject(ReferencedDirectory);
00942 
00943     /* Check if we have a referenced parent directory */
00944     if (ReferencedParentDirectory)
00945     {
00946         /* We do, dereference it */
00947         ObDereferenceObject(ReferencedParentDirectory);
00948     }
00949 
00950     /* Set the found object and check if we got one */
00951     *FoundObject = Object;
00952     if (!Object)
00953     {
00954         /* Nothing was found. Did we reparse or get success? */
00955         if ((Status == STATUS_REPARSE) || (NT_SUCCESS(Status)))
00956         {
00957             /* Set correct failure */
00958             Status = STATUS_OBJECT_NAME_NOT_FOUND;
00959         }
00960     }
00961 
00962     /* Check if we had a root directory */
00963     if (RootHandle) ObDereferenceObject(RootDirectory);
00964 
00965     /* Return status to caller */
00966     OBTRACE(OB_NAMESPACE_DEBUG,
00967             "%s - Found Object: %p. Expected: %p\n",
00968             __FUNCTION__,
00969             *FoundObject,
00970             InsertObject);
00971     return Status;
00972 }
00973 
00974 /* PUBLIC FUNCTIONS *********************************************************/
00975 
00976 NTSTATUS
00977 NTAPI
00978 ObQueryNameString(IN PVOID Object,
00979                   OUT POBJECT_NAME_INFORMATION ObjectNameInfo,
00980                   IN ULONG Length,
00981                   OUT PULONG ReturnLength)
00982 {
00983     POBJECT_HEADER_NAME_INFO LocalInfo;
00984     POBJECT_HEADER ObjectHeader;
00985     POBJECT_DIRECTORY ParentDirectory;
00986     ULONG NameSize;
00987     PWCH ObjectName;
00988     BOOLEAN ObjectIsNamed;
00989     NTSTATUS Status = STATUS_SUCCESS;
00990 
00991     /* Get the Kernel Meta-Structures */
00992     ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
00993     LocalInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
00994 
00995     /* Check if a Query Name Procedure is available */
00996     if (ObjectHeader->Type->TypeInfo.QueryNameProcedure)
00997     {
00998         /* Call the procedure inside SEH */
00999         ObjectIsNamed = ((LocalInfo) && (LocalInfo->Name.Length > 0));
01000 
01001         _SEH2_TRY
01002         {
01003             Status = ObjectHeader->Type->TypeInfo.QueryNameProcedure(Object,
01004                                                                ObjectIsNamed,
01005                                                                ObjectNameInfo,
01006                                                                Length,
01007                                                                ReturnLength,
01008                                                                KernelMode);
01009         }
01010         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
01011         {
01012             /* Return the exception code */
01013             Status = _SEH2_GetExceptionCode();
01014         }
01015         _SEH2_END;
01016 
01017         return Status;
01018     }
01019 
01020     /* Check if the object doesn't even have a name */
01021     if (!(LocalInfo) || !(LocalInfo->Name.Buffer))
01022     {
01023         Status = STATUS_SUCCESS;
01024 
01025         _SEH2_TRY
01026         {
01027             /* We're returning the name structure */
01028             *ReturnLength = sizeof(OBJECT_NAME_INFORMATION);
01029 
01030             /* Check if we were given enough space */
01031             if (*ReturnLength > Length)
01032             {
01033                 Status = STATUS_INFO_LENGTH_MISMATCH;
01034             }
01035             else
01036             {
01037                 /* Return an empty buffer */
01038                 RtlInitEmptyUnicodeString(&ObjectNameInfo->Name, NULL, 0);
01039             }
01040         }
01041         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
01042         {
01043             /* Return the exception code */
01044             Status = _SEH2_GetExceptionCode();
01045         }
01046         _SEH2_END;
01047 
01048         return Status;
01049     }
01050 
01051     /*
01052      * Find the size needed for the name. We won't do
01053      * this during the Name Creation loop because we want
01054      * to let the caller know that the buffer isn't big
01055      * enough right at the beginning, not work our way through
01056      * and find out at the end
01057      */
01058     _SEH2_TRY
01059     {
01060         if (Object == ObpRootDirectoryObject)
01061         {
01062             /* Size of the '\' string */
01063             NameSize = sizeof(OBJ_NAME_PATH_SEPARATOR);
01064         }
01065         else
01066         {
01067             /* Get the Object Directory and add name of Object */
01068             ParentDirectory = LocalInfo->Directory;
01069             NameSize = sizeof(OBJ_NAME_PATH_SEPARATOR) + LocalInfo->Name.Length;
01070 
01071             /* Loop inside the directory to get the top-most one (meaning root) */
01072             while ((ParentDirectory != ObpRootDirectoryObject) && (ParentDirectory))
01073             {
01074                 /* Get the Name Information */
01075                 LocalInfo = OBJECT_HEADER_TO_NAME_INFO(
01076                     OBJECT_TO_OBJECT_HEADER(ParentDirectory));
01077 
01078                 /* Add the size of the Directory Name */
01079                 if (LocalInfo && LocalInfo->Directory)
01080                 {
01081                     /* Size of the '\' string + Directory Name */
01082                     NameSize += sizeof(OBJ_NAME_PATH_SEPARATOR) +
01083                                 LocalInfo->Name.Length;
01084 
01085                     /* Move to next parent Directory */
01086                     ParentDirectory = LocalInfo->Directory;
01087                 }
01088                 else
01089                 {
01090                     /* Directory with no name. We append "...\" */
01091                     NameSize += sizeof(L"...") + sizeof(OBJ_NAME_PATH_SEPARATOR);
01092                     break;
01093                 }
01094             }
01095         }
01096 
01097         /* Finally, add the name of the structure and the null char */
01098         *ReturnLength = NameSize +
01099                         sizeof(OBJECT_NAME_INFORMATION) +
01100                         sizeof(UNICODE_NULL);
01101 
01102         /* Check if we were given enough space */
01103         if (*ReturnLength > Length) _SEH2_YIELD(return STATUS_INFO_LENGTH_MISMATCH);
01104 
01105         /*
01106         * Now we will actually create the name. We work backwards because
01107         * it's easier to start off from the Name we have and walk up the
01108         * parent directories. We use the same logic as Name Length calculation.
01109         */
01110         LocalInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
01111         ObjectName = (PWCH)((ULONG_PTR)ObjectNameInfo + *ReturnLength);
01112         *--ObjectName = UNICODE_NULL;
01113 
01114         /* Check if the object is actually the Root directory */
01115         if (Object == ObpRootDirectoryObject)
01116         {
01117             /* This is already the Root Directory, return "\\" */
01118             *--ObjectName = OBJ_NAME_PATH_SEPARATOR;
01119             ObjectNameInfo->Name.Length = (USHORT)NameSize;
01120             ObjectNameInfo->Name.MaximumLength = (USHORT)(NameSize +
01121                                                           sizeof(UNICODE_NULL));
01122             ObjectNameInfo->Name.Buffer = ObjectName;
01123             Status = STATUS_SUCCESS;
01124         }
01125         else
01126         {
01127             /* Start by adding the Object's Name */
01128             ObjectName = (PWCH)((ULONG_PTR)ObjectName -
01129                                            LocalInfo->Name.Length);
01130             RtlCopyMemory(ObjectName,
01131                           LocalInfo->Name.Buffer,
01132                           LocalInfo->Name.Length);
01133 
01134             /* Now parse the Parent directories until we reach the top */
01135             ParentDirectory = LocalInfo->Directory;
01136             while ((ParentDirectory != ObpRootDirectoryObject) && (ParentDirectory))
01137             {
01138                 /* Get the name information */
01139                 LocalInfo = OBJECT_HEADER_TO_NAME_INFO(
01140                     OBJECT_TO_OBJECT_HEADER(ParentDirectory));
01141 
01142                 /* Add the "\" */
01143                 *(--ObjectName) = OBJ_NAME_PATH_SEPARATOR;
01144 
01145                 /* Add the Parent Directory's Name */
01146                 if (LocalInfo && LocalInfo->Name.Buffer)
01147                 {
01148                     /* Add the name */
01149                     ObjectName = (PWCH)((ULONG_PTR)ObjectName -
01150                                                    LocalInfo->Name.Length);
01151                     RtlCopyMemory(ObjectName,
01152                                   LocalInfo->Name.Buffer,
01153                                   LocalInfo->Name.Length);
01154 
01155                     /* Move to next parent */
01156                     ParentDirectory = LocalInfo->Directory;
01157                 }
01158                 else
01159                 {
01160                     /* Directory without a name, we add "..." */
01161                     ObjectName = (PWCH)((ULONG_PTR)ObjectName -
01162                                                    sizeof(L"...") +
01163                                                    sizeof(UNICODE_NULL));
01164                     RtlCopyMemory(ObjectName,
01165                                   L"...",
01166                                   sizeof(L"...") + sizeof(UNICODE_NULL));
01167                     break;
01168                 }
01169             }
01170 
01171             /* Add Root Directory Name */
01172             *(--ObjectName) = OBJ_NAME_PATH_SEPARATOR;
01173             ObjectNameInfo->Name.Length = (USHORT)NameSize;
01174             ObjectNameInfo->Name.MaximumLength =
01175                 (USHORT)(NameSize + sizeof(UNICODE_NULL));
01176             ObjectNameInfo->Name.Buffer = ObjectName;
01177         }
01178     }
01179     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
01180     {
01181         /* Return the exception code */
01182         Status = _SEH2_GetExceptionCode();
01183     }
01184     _SEH2_END;
01185 
01186     /* Return success */
01187     return Status;
01188 }
01189 
01190 VOID
01191 NTAPI
01192 ObQueryDeviceMapInformation(IN PEPROCESS Process,
01193                             IN PPROCESS_DEVICEMAP_INFORMATION DeviceMapInfo)
01194 {
01195     /*
01196     * FIXME: This is an ugly hack for now, to always return the System Device Map
01197     * instead of returning the Process Device Map. Not important yet since we don't use it
01198     */
01199 
01200     KeAcquireGuardedMutex(&ObpDeviceMapLock);
01201 
01202     /* Make a copy */
01203     DeviceMapInfo->Query.DriveMap = ObSystemDeviceMap->DriveMap;
01204     RtlCopyMemory(DeviceMapInfo->Query.DriveType,
01205                   ObSystemDeviceMap->DriveType,
01206                   sizeof(ObSystemDeviceMap->DriveType));
01207 
01208     KeReleaseGuardedMutex(&ObpDeviceMapLock);
01209 }
01210 
01211 NTSTATUS
01212 NTAPI
01213 ObIsDosDeviceLocallyMapped(
01214     IN ULONG Index,
01215     OUT PUCHAR DosDeviceState)
01216 {
01217     /* check parameters */
01218     if (Index < 1 || Index > 26)
01219     {
01220         /* invalid index */
01221         return STATUS_INVALID_PARAMETER;
01222     }
01223 
01224     /* acquire lock */
01225     KeAcquireGuardedMutex(&ObpDeviceMapLock);
01226 
01227     /* get drive mapping status */
01228     *DosDeviceState = (ObSystemDeviceMap->DriveMap & (1 << Index)) != 0;
01229 
01230     /* release lock */
01231     KeReleaseGuardedMutex(&ObpDeviceMapLock);
01232 
01233     /* done */
01234     return STATUS_SUCCESS;
01235 }
01236 
01237 /* EOF */

Generated on Fri May 25 2012 04:36:05 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.