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

driver.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/io/iomgr/driver.c
00005  * PURPOSE:         Driver Object Management
00006  * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
00007  *                  Filip Navara (navaraf@reactos.org)
00008  *                  Hervé Poussineau (hpoussin@reactos.org)
00009  */
00010 
00011 /* INCLUDES *******************************************************************/
00012 
00013 #include <ntoskrnl.h>
00014 #define NDEBUG
00015 #include <debug.h>
00016 
00017 /* GLOBALS ********************************************************************/
00018 
00019 LIST_ENTRY DriverReinitListHead;
00020 KSPIN_LOCK DriverReinitListLock;
00021 PLIST_ENTRY DriverReinitTailEntry;
00022 
00023 PLIST_ENTRY DriverBootReinitTailEntry;
00024 LIST_ENTRY DriverBootReinitListHead;
00025 KSPIN_LOCK DriverBootReinitListLock;
00026 
00027 UNICODE_STRING IopHardwareDatabaseKey =
00028    RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\HARDWARE\\DESCRIPTION\\SYSTEM");
00029 
00030 POBJECT_TYPE IoDriverObjectType = NULL;
00031 
00032 #define TAG_RTLREGISTRY 'vrqR'
00033 
00034 extern BOOLEAN ExpInTextModeSetup;
00035 extern BOOLEAN PnpSystemInit;
00036 
00037 USHORT IopGroupIndex;
00038 PLIST_ENTRY IopGroupTable;
00039 
00040 /* PRIVATE FUNCTIONS **********************************************************/
00041 
00042 NTSTATUS NTAPI
00043 IopInvalidDeviceRequest(
00044    PDEVICE_OBJECT DeviceObject,
00045    PIRP Irp)
00046 {
00047    Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
00048    Irp->IoStatus.Information = 0;
00049    IoCompleteRequest(Irp, IO_NO_INCREMENT);
00050    return STATUS_INVALID_DEVICE_REQUEST;
00051 }
00052 
00053 VOID
00054 NTAPI
00055 IopDeleteDriver(IN PVOID ObjectBody)
00056 {
00057     PDRIVER_OBJECT DriverObject = ObjectBody;
00058     PIO_CLIENT_EXTENSION DriverExtension, NextDriverExtension;
00059     PAGED_CODE();
00060 
00061     DPRINT1("Deleting driver object '%wZ'\n", &DriverObject->DriverName);
00062 
00063     /* There must be no device objects remaining at this point */
00064     ASSERT(!DriverObject->DeviceObject);
00065 
00066     /* Get the extension and loop them */
00067     DriverExtension = IoGetDrvObjExtension(DriverObject)->
00068                       ClientDriverExtension;
00069     while (DriverExtension)
00070     {
00071         /* Get the next one */
00072         NextDriverExtension = DriverExtension->NextExtension;
00073         ExFreePoolWithTag(DriverExtension, TAG_DRIVER_EXTENSION);
00074 
00075         /* Move on */
00076         DriverExtension = NextDriverExtension;
00077     }
00078 
00079 #if 0
00080     /* Check if the driver image is still loaded */
00081     if (DriverObject->DriverSection)
00082     {
00083         /* Unload it */
00084         MmUnloadSystemImage(DriverObject->DriverSection);
00085     }
00086 #else
00087     DPRINT1("HACK: Not unloading the driver image due to critical bugs!\n");
00088 #endif
00089 
00090     /* Check if it has a name */
00091     if (DriverObject->DriverName.Buffer)
00092     {
00093         /* Free it */
00094         ExFreePool(DriverObject->DriverName.Buffer);
00095     }
00096 
00097 #if 0 /* See a bit of hack in IopCreateDriver */
00098     /* Check if it has a service key name */
00099     if (DriverObject->DriverExtension->ServiceKeyName.Buffer)
00100     {
00101         /* Free it */
00102         ExFreePool(DriverObject->DriverExtension->ServiceKeyName.Buffer);
00103     }
00104 #endif
00105 }
00106 
00107 NTSTATUS FASTCALL
00108 IopGetDriverObject(
00109    PDRIVER_OBJECT *DriverObject,
00110    PUNICODE_STRING ServiceName,
00111    BOOLEAN FileSystem)
00112 {
00113    PDRIVER_OBJECT Object;
00114    WCHAR NameBuffer[MAX_PATH];
00115    UNICODE_STRING DriverName;
00116    NTSTATUS Status;
00117 
00118    DPRINT("IopGetDriverObject(%p '%wZ' %x)\n",
00119       DriverObject, ServiceName, FileSystem);
00120 
00121    *DriverObject = NULL;
00122 
00123    /* Create ModuleName string */
00124    if (ServiceName == NULL || ServiceName->Buffer == NULL)
00125       /* We don't know which DriverObject we have to open */
00126       return STATUS_INVALID_PARAMETER_2;
00127 
00128    DriverName.Buffer = NameBuffer;
00129    DriverName.Length = 0;
00130    DriverName.MaximumLength = sizeof(NameBuffer);
00131 
00132    if (FileSystem == TRUE)
00133       RtlAppendUnicodeToString(&DriverName, FILESYSTEM_ROOT_NAME);
00134    else
00135       RtlAppendUnicodeToString(&DriverName, DRIVER_ROOT_NAME);
00136    RtlAppendUnicodeStringToString(&DriverName, ServiceName);
00137 
00138    DPRINT("Driver name: '%wZ'\n", &DriverName);
00139 
00140    /* Open driver object */
00141    Status = ObReferenceObjectByName(
00142       &DriverName,
00143       OBJ_OPENIF | OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, /* Attributes */
00144       NULL, /* PassedAccessState */
00145       0, /* DesiredAccess */
00146       IoDriverObjectType,
00147       KernelMode,
00148       NULL, /* ParseContext */
00149       (PVOID*)&Object);
00150 
00151    if (!NT_SUCCESS(Status))
00152    {
00153       DPRINT("Failed to reference driver object, status=0x%08x\n", Status);
00154       return Status;
00155    }
00156 
00157    *DriverObject = Object;
00158 
00159    DPRINT("Driver Object: %p\n", Object);
00160 
00161    return STATUS_SUCCESS;
00162 }
00163 
00164 /*
00165  * RETURNS
00166  *  TRUE if String2 contains String1 as a suffix.
00167  */
00168 BOOLEAN
00169 NTAPI
00170 IopSuffixUnicodeString(
00171     IN PCUNICODE_STRING String1,
00172     IN PCUNICODE_STRING String2)
00173 {
00174     PWCHAR pc1;
00175     PWCHAR pc2;
00176     ULONG Length;
00177 
00178     if (String2->Length < String1->Length)
00179         return FALSE;
00180 
00181     Length = String1->Length / 2;
00182     pc1 = String1->Buffer;
00183     pc2 = &String2->Buffer[String2->Length / sizeof(WCHAR) - Length];
00184 
00185     if (pc1 && pc2)
00186     {
00187         while (Length--)
00188         {
00189             if( *pc1++ != *pc2++ )
00190                 return FALSE;
00191         }
00192         return TRUE;
00193     }
00194     return FALSE;
00195 }
00196 
00197 /*
00198  * IopDisplayLoadingMessage
00199  *
00200  * Display 'Loading XXX...' message.
00201  */
00202 
00203 VOID
00204 FASTCALL
00205 INIT_FUNCTION
00206 IopDisplayLoadingMessage(PUNICODE_STRING ServiceName)
00207 {
00208     CHAR TextBuffer[256];
00209     UNICODE_STRING DotSys = RTL_CONSTANT_STRING(L".SYS");
00210 
00211     if (ExpInTextModeSetup) return;
00212     if (!KeLoaderBlock) return;
00213     RtlUpcaseUnicodeString(ServiceName, ServiceName, FALSE);
00214     snprintf(TextBuffer, sizeof(TextBuffer),
00215             "%s%sSystem32\\Drivers\\%wZ%s\n",
00216             KeLoaderBlock->ArcBootDeviceName,
00217             KeLoaderBlock->NtBootPathName,
00218             ServiceName,
00219             IopSuffixUnicodeString(&DotSys, ServiceName) ? "" : ".SYS");
00220     HalDisplayString(TextBuffer);
00221 }
00222 
00223 /*
00224  * IopNormalizeImagePath
00225  *
00226  * Normalize an image path to contain complete path.
00227  *
00228  * Parameters
00229  *    ImagePath
00230  *       The input path and on exit the result path. ImagePath.Buffer
00231  *       must be allocated by ExAllocatePool on input. Caller is responsible
00232  *       for freeing the buffer when it's no longer needed.
00233  *
00234  *    ServiceName
00235  *       Name of the service that ImagePath belongs to.
00236  *
00237  * Return Value
00238  *    Status
00239  *
00240  * Remarks
00241  *    The input image path isn't freed on error.
00242  */
00243 
00244 NTSTATUS FASTCALL
00245 IopNormalizeImagePath(
00246    IN OUT PUNICODE_STRING ImagePath,
00247    IN PUNICODE_STRING ServiceName)
00248 {
00249    UNICODE_STRING InputImagePath;
00250 
00251    DPRINT("Normalizing image path '%wZ' for service '%wZ'\n", ImagePath, ServiceName);
00252 
00253    RtlCopyMemory(
00254       &InputImagePath,
00255       ImagePath,
00256       sizeof(UNICODE_STRING));
00257 
00258    if (InputImagePath.Length == 0)
00259    {
00260       ImagePath->Length = 0;
00261       ImagePath->MaximumLength =
00262           (33 * sizeof(WCHAR)) + ServiceName->Length + sizeof(UNICODE_NULL);
00263       ImagePath->Buffer = ExAllocatePool(NonPagedPool, ImagePath->MaximumLength);
00264       if (ImagePath->Buffer == NULL)
00265          return STATUS_NO_MEMORY;
00266 
00267       RtlAppendUnicodeToString(ImagePath, L"\\SystemRoot\\system32\\drivers\\");
00268       RtlAppendUnicodeStringToString(ImagePath, ServiceName);
00269       RtlAppendUnicodeToString(ImagePath, L".sys");
00270    } else
00271    if (InputImagePath.Buffer[0] != L'\\')
00272    {
00273       ImagePath->Length = 0;
00274       ImagePath->MaximumLength =
00275           12 * sizeof(WCHAR) + InputImagePath.Length + sizeof(UNICODE_NULL);
00276       ImagePath->Buffer = ExAllocatePool(NonPagedPool, ImagePath->MaximumLength);
00277       if (ImagePath->Buffer == NULL)
00278          return STATUS_NO_MEMORY;
00279 
00280       RtlAppendUnicodeToString(ImagePath, L"\\SystemRoot\\");
00281       RtlAppendUnicodeStringToString(ImagePath, &InputImagePath);
00282 
00283       /* Free caller's string */
00284       ExFreePoolWithTag(InputImagePath.Buffer, TAG_RTLREGISTRY);
00285    }
00286  
00287    DPRINT("Normalized image path is '%wZ' for service '%wZ'\n", ImagePath, ServiceName);
00288 
00289    return STATUS_SUCCESS;
00290 }
00291 
00292 /*
00293  * IopLoadServiceModule
00294  *
00295  * Load a module specified by registry settings for service.
00296  *
00297  * Parameters
00298  *    ServiceName
00299  *       Name of the service to load.
00300  *
00301  * Return Value
00302  *    Status
00303  */
00304 
00305 NTSTATUS FASTCALL
00306 IopLoadServiceModule(
00307    IN PUNICODE_STRING ServiceName,
00308    OUT PLDR_DATA_TABLE_ENTRY *ModuleObject)
00309 {
00310    RTL_QUERY_REGISTRY_TABLE QueryTable[3];
00311    ULONG ServiceStart;
00312    UNICODE_STRING ServiceImagePath, CCSName;
00313    NTSTATUS Status;
00314    HANDLE CCSKey, ServiceKey;
00315    PVOID BaseAddress;
00316 
00317    DPRINT("IopLoadServiceModule(%wZ, 0x%p)\n", ServiceName, ModuleObject);
00318 
00319    /* FIXME: This check may be removed once the bug is fixed */
00320    if (ServiceName->Buffer == NULL)
00321    {
00322        DPRINT1("If you see this, please report to Fireball or hpoussin!\n");
00323       return STATUS_UNSUCCESSFUL;
00324    }
00325 
00326    if (ExpInTextModeSetup)
00327    {
00328        /* We have no registry, but luckily we know where all the drivers are */
00329 
00330        /* ServiceStart < 4 is all that matters */
00331        ServiceStart = 0;
00332 
00333        /* IopNormalizeImagePath will do all of the work for us if we give it an empty string */
00334        ServiceImagePath.Length = ServiceImagePath.MaximumLength = 0;
00335        ServiceImagePath.Buffer = NULL;
00336    }
00337    else
00338    {
00339        /* Open CurrentControlSet */
00340        RtlInitUnicodeString(&CCSName,
00341                             L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services");
00342        Status = IopOpenRegistryKeyEx(&CCSKey, NULL, &CCSName, KEY_READ);
00343        if (!NT_SUCCESS(Status))
00344        {
00345            DPRINT1("ZwOpenKey() failed with Status %08X\n", Status);
00346            return Status;
00347        }
00348 
00349        /* Open service key */
00350        Status = IopOpenRegistryKeyEx(&ServiceKey, CCSKey, ServiceName, KEY_READ);
00351        if (!NT_SUCCESS(Status))
00352        {
00353            DPRINT1("ZwOpenKey() failed with Status %08X\n", Status);
00354            ZwClose(CCSKey);
00355            return Status;
00356        }
00357 
00358        /*
00359         * Get information about the service.
00360         */
00361 
00362        RtlZeroMemory(QueryTable, sizeof(QueryTable));
00363 
00364        RtlInitUnicodeString(&ServiceImagePath, NULL);
00365 
00366        QueryTable[0].Name = L"Start";
00367        QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
00368        QueryTable[0].EntryContext = &ServiceStart;
00369 
00370        QueryTable[1].Name = L"ImagePath";
00371        QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
00372        QueryTable[1].EntryContext = &ServiceImagePath;
00373 
00374        Status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE,
00375           (PWSTR)ServiceKey, QueryTable, NULL, NULL);
00376 
00377        ZwClose(ServiceKey);
00378        ZwClose(CCSKey);
00379 
00380        if (!NT_SUCCESS(Status))
00381        {
00382           DPRINT1("RtlQueryRegistryValues() failed (Status %x)\n", Status);
00383           return Status;
00384        }
00385    }
00386 
00387    /*
00388     * Normalize the image path for all later processing.
00389     */
00390 
00391    Status = IopNormalizeImagePath(&ServiceImagePath, ServiceName);
00392 
00393    if (!NT_SUCCESS(Status))
00394    {
00395       DPRINT("IopNormalizeImagePath() failed (Status %x)\n", Status);
00396       return Status;
00397    }
00398 
00399    /*
00400     * Case for disabled drivers
00401     */
00402 
00403    if (ServiceStart >= 4)
00404    {
00405       /* We can't load this */
00406       Status = STATUS_DRIVER_UNABLE_TO_LOAD;
00407    }
00408    else
00409    {
00410       DPRINT("Loading module from %wZ\n", &ServiceImagePath);
00411       Status = MmLoadSystemImage(&ServiceImagePath, NULL, NULL, 0, (PVOID)ModuleObject, &BaseAddress);
00412       if (NT_SUCCESS(Status))
00413       {
00414           IopDisplayLoadingMessage(ServiceName);
00415       }
00416    }
00417 
00418    ExFreePool(ServiceImagePath.Buffer);
00419 
00420    /*
00421     * Now check if the module was loaded successfully.
00422     */
00423 
00424    if (!NT_SUCCESS(Status))
00425    {
00426       DPRINT("Module loading failed (Status %x)\n", Status);
00427    }
00428 
00429    DPRINT("Module loading (Status %x)\n", Status);
00430 
00431    return Status;
00432 }
00433 
00434 VOID
00435 NTAPI
00436 MmFreeDriverInitialization(IN PLDR_DATA_TABLE_ENTRY LdrEntry);
00437 
00438 /*
00439  * IopInitializeDriverModule
00440  *
00441  * Initalize a loaded driver.
00442  *
00443  * Parameters
00444  *    DeviceNode
00445  *       Pointer to device node.
00446  *
00447  *    ModuleObject
00448  *       Module object representing the driver. It can be retrieve by
00449  *       IopLoadServiceModule.
00450  *
00451  *    ServiceName
00452  *       Name of the service (as in registry).
00453  *
00454  *    FileSystemDriver
00455  *       Set to TRUE for file system drivers.
00456  *
00457  *    DriverObject
00458  *       On successful return this contains the driver object representing
00459  *       the loaded driver.
00460  */
00461 
00462 NTSTATUS FASTCALL
00463 IopInitializeDriverModule(
00464    IN PDEVICE_NODE DeviceNode,
00465    IN PLDR_DATA_TABLE_ENTRY ModuleObject,
00466    IN PUNICODE_STRING ServiceName,
00467    IN BOOLEAN FileSystemDriver,
00468    OUT PDRIVER_OBJECT *DriverObject)
00469 {
00470    const WCHAR ServicesKeyName[] = L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\";
00471    WCHAR NameBuffer[MAX_PATH];
00472    UNICODE_STRING DriverName;
00473    UNICODE_STRING RegistryKey;
00474    PDRIVER_INITIALIZE DriverEntry;
00475    PDRIVER_OBJECT Driver;
00476    NTSTATUS Status;
00477 
00478    DriverEntry = ModuleObject->EntryPoint;
00479 
00480    if (ServiceName != NULL && ServiceName->Length != 0)
00481    {
00482       RegistryKey.Length = 0;
00483       RegistryKey.MaximumLength = sizeof(ServicesKeyName) + ServiceName->Length;
00484       RegistryKey.Buffer = ExAllocatePool(PagedPool, RegistryKey.MaximumLength);
00485       if (RegistryKey.Buffer == NULL)
00486       {
00487          return STATUS_INSUFFICIENT_RESOURCES;
00488       }
00489       RtlAppendUnicodeToString(&RegistryKey, ServicesKeyName);
00490       RtlAppendUnicodeStringToString(&RegistryKey, ServiceName);
00491    }
00492    else
00493    {
00494       RtlInitUnicodeString(&RegistryKey, NULL);
00495    }
00496 
00497    /* Create ModuleName string */
00498    if (ServiceName && ServiceName->Length > 0)
00499    {
00500       if (FileSystemDriver == TRUE)
00501          wcscpy(NameBuffer, FILESYSTEM_ROOT_NAME);
00502       else
00503          wcscpy(NameBuffer, DRIVER_ROOT_NAME);
00504 
00505       RtlInitUnicodeString(&DriverName, NameBuffer);
00506       DriverName.MaximumLength = sizeof(NameBuffer);
00507 
00508       RtlAppendUnicodeStringToString(&DriverName, ServiceName);
00509 
00510       DPRINT("Driver name: '%wZ'\n", &DriverName);
00511    }
00512    else
00513       DriverName.Length = 0;
00514 
00515    Status = IopCreateDriver(
00516        DriverName.Length > 0 ? &DriverName : NULL,
00517        DriverEntry,
00518        &RegistryKey,
00519        ModuleObject,
00520        &Driver);
00521    RtlFreeUnicodeString(&RegistryKey);
00522 
00523    *DriverObject = Driver;
00524    if (!NT_SUCCESS(Status))
00525    {
00526       DPRINT("IopCreateDriver() failed (Status 0x%08lx)\n", Status);
00527       return Status;
00528    }
00529    
00530    MmFreeDriverInitialization((PLDR_DATA_TABLE_ENTRY)Driver->DriverSection);
00531 
00532    /* Set the driver as initialized */
00533    IopReadyDeviceObjects(Driver);
00534 
00535    if (PnpSystemInit) IopReinitializeDrivers();
00536 
00537    return STATUS_SUCCESS;
00538 }
00539 
00540 /*
00541  * IopAttachFilterDriversCallback
00542  *
00543  * Internal routine used by IopAttachFilterDrivers.
00544  */
00545 
00546 NTSTATUS NTAPI
00547 IopAttachFilterDriversCallback(
00548    PWSTR ValueName,
00549    ULONG ValueType,
00550    PVOID ValueData,
00551    ULONG ValueLength,
00552    PVOID Context,
00553    PVOID EntryContext)
00554 {
00555    PDEVICE_NODE DeviceNode = Context;
00556    UNICODE_STRING ServiceName;
00557    PWCHAR Filters;
00558    PLDR_DATA_TABLE_ENTRY ModuleObject;
00559    PDRIVER_OBJECT DriverObject;
00560    NTSTATUS Status;
00561 
00562    for (Filters = ValueData;
00563         ((ULONG_PTR)Filters - (ULONG_PTR)ValueData) < ValueLength &&
00564         *Filters != 0;
00565         Filters += (ServiceName.Length / sizeof(WCHAR)) + 1)
00566    {
00567       DPRINT("Filter Driver: %S (%wZ)\n", Filters, &DeviceNode->InstancePath);
00568 
00569       ServiceName.Buffer = Filters;
00570       ServiceName.MaximumLength =
00571       ServiceName.Length = (USHORT)wcslen(Filters) * sizeof(WCHAR);
00572 
00573        Status = IopGetDriverObject(&DriverObject,
00574                                    &ServiceName,
00575                                    FALSE);
00576        if (!NT_SUCCESS(Status))
00577        {
00578            /* Load and initialize the filter driver */
00579            Status = IopLoadServiceModule(&ServiceName, &ModuleObject);
00580            if (!NT_SUCCESS(Status))
00581                continue;
00582 
00583            Status = IopInitializeDriverModule(DeviceNode, ModuleObject, &ServiceName,
00584                                               FALSE, &DriverObject);
00585            if (!NT_SUCCESS(Status))
00586                continue;
00587        }
00588 
00589        Status = IopInitializeDevice(DeviceNode, DriverObject);
00590 
00591        /* Remove extra reference */
00592        ObDereferenceObject(DriverObject);
00593    }
00594 
00595    return STATUS_SUCCESS;
00596 }
00597 
00598 /*
00599  * IopAttachFilterDrivers
00600  *
00601  * Load filter drivers for specified device node.
00602  *
00603  * Parameters
00604  *    Lower
00605  *       Set to TRUE for loading lower level filters or FALSE for upper
00606  *       level filters.
00607  */
00608 
00609 NTSTATUS FASTCALL
00610 IopAttachFilterDrivers(
00611    PDEVICE_NODE DeviceNode,
00612    BOOLEAN Lower)
00613 {
00614    RTL_QUERY_REGISTRY_TABLE QueryTable[2] = { { NULL, 0, NULL, NULL, 0, NULL, 0 }, };
00615    UNICODE_STRING Class;
00616    WCHAR ClassBuffer[40];
00617    UNICODE_STRING EnumRoot = RTL_CONSTANT_STRING(ENUM_ROOT);
00618    HANDLE EnumRootKey, SubKey;
00619    NTSTATUS Status;
00620 
00621    /* Open enumeration root key */
00622    Status = IopOpenRegistryKeyEx(&EnumRootKey, NULL,
00623        &EnumRoot, KEY_READ);
00624    if (!NT_SUCCESS(Status))
00625    {
00626        DPRINT1("ZwOpenKey() failed with Status %08X\n", Status);
00627        return Status;
00628    }
00629 
00630    /* Open subkey */
00631    Status = IopOpenRegistryKeyEx(&SubKey, EnumRootKey,
00632        &DeviceNode->InstancePath, KEY_READ);
00633    if (!NT_SUCCESS(Status))
00634    {
00635        DPRINT1("ZwOpenKey() failed with Status %08X\n", Status);
00636        ZwClose(EnumRootKey);
00637        return Status;
00638    }
00639 
00640    /*
00641     * First load the device filters
00642     */
00643    QueryTable[0].QueryRoutine = IopAttachFilterDriversCallback;
00644    if (Lower)
00645      QueryTable[0].Name = L"LowerFilters";
00646    else
00647      QueryTable[0].Name = L"UpperFilters";
00648    QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED;
00649 
00650    RtlQueryRegistryValues(
00651       RTL_REGISTRY_HANDLE,
00652       (PWSTR)SubKey,
00653       QueryTable,
00654       DeviceNode,
00655       NULL);
00656 
00657    /*
00658     * Now get the class GUID
00659     */
00660    Class.Length = 0;
00661    Class.MaximumLength = 40 * sizeof(WCHAR);
00662    Class.Buffer = ClassBuffer;
00663    QueryTable[0].QueryRoutine = NULL;
00664    QueryTable[0].Name = L"ClassGUID";
00665    QueryTable[0].EntryContext = &Class;
00666    QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_DIRECT;
00667 
00668    Status = RtlQueryRegistryValues(
00669       RTL_REGISTRY_HANDLE,
00670       (PWSTR)SubKey,
00671       QueryTable,
00672       DeviceNode,
00673       NULL);
00674 
00675    /* Close handles */
00676    ZwClose(SubKey);
00677    ZwClose(EnumRootKey);
00678 
00679    /*
00680     * Load the class filter driver
00681     */
00682    if (NT_SUCCESS(Status))
00683    {
00684        UNICODE_STRING ControlClass = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class");
00685 
00686        Status = IopOpenRegistryKeyEx(&EnumRootKey, NULL,
00687            &ControlClass, KEY_READ);
00688        if (!NT_SUCCESS(Status))
00689        {
00690            DPRINT1("ZwOpenKey() failed with Status %08X\n", Status);
00691            return Status;
00692        }
00693 
00694        /* Open subkey */
00695        Status = IopOpenRegistryKeyEx(&SubKey, EnumRootKey,
00696            &Class, KEY_READ);
00697        if (!NT_SUCCESS(Status))
00698        {
00699            DPRINT1("ZwOpenKey() failed with Status %08X\n", Status);
00700            ZwClose(EnumRootKey);
00701            return Status;
00702        }
00703 
00704       QueryTable[0].QueryRoutine = IopAttachFilterDriversCallback;
00705       if (Lower)
00706          QueryTable[0].Name = L"LowerFilters";
00707       else
00708          QueryTable[0].Name = L"UpperFilters";
00709       QueryTable[0].EntryContext = NULL;
00710       QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED;
00711 
00712       RtlQueryRegistryValues(
00713          RTL_REGISTRY_HANDLE,
00714          (PWSTR)SubKey,
00715          QueryTable,
00716          DeviceNode,
00717          NULL);
00718 
00719       /* Clean up */
00720       ZwClose(SubKey);
00721       ZwClose(EnumRootKey);
00722    }
00723 
00724    return STATUS_SUCCESS;
00725 }
00726 
00727 NTSTATUS
00728 NTAPI
00729 MiResolveImageReferences(IN PVOID ImageBase,
00730                          IN PUNICODE_STRING ImageFileDirectory,
00731                          IN PUNICODE_STRING NamePrefix OPTIONAL,
00732                          OUT PCHAR *MissingApi,
00733                          OUT PWCHAR *MissingDriver,
00734                          OUT PLOAD_IMPORTS *LoadImports);
00735 
00736 //
00737 // Used for images already loaded (boot drivers)
00738 //
00739 NTSTATUS
00740 NTAPI
00741 INIT_FUNCTION
00742 LdrProcessDriverModule(PLDR_DATA_TABLE_ENTRY LdrEntry,
00743                        PUNICODE_STRING FileName,
00744                        PLDR_DATA_TABLE_ENTRY *ModuleObject)
00745 {
00746     NTSTATUS Status;
00747     UNICODE_STRING BaseName, BaseDirectory;
00748     PLOAD_IMPORTS LoadedImports = (PVOID)-2;
00749     PCHAR MissingApiName, Buffer;
00750     PWCHAR MissingDriverName;
00751     PVOID DriverBase = LdrEntry->DllBase;
00752 
00753     /* Allocate a buffer we'll use for names */
00754     Buffer = ExAllocatePoolWithTag(NonPagedPool, MAX_PATH, TAG_LDR_WSTR);
00755     if (!Buffer)
00756     {
00757         /* Fail */
00758         return STATUS_INSUFFICIENT_RESOURCES;
00759     }
00760 
00761     /* Check for a separator */
00762     if (FileName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR)
00763     {
00764         PWCHAR p;
00765         ULONG BaseLength;
00766 
00767         /* Loop the path until we get to the base name */
00768         p = &FileName->Buffer[FileName->Length / sizeof(WCHAR)];
00769         while (*(p - 1) != OBJ_NAME_PATH_SEPARATOR) p--;
00770 
00771         /* Get the length */
00772         BaseLength = (ULONG)(&FileName->Buffer[FileName->Length / sizeof(WCHAR)] - p);
00773         BaseLength *= sizeof(WCHAR);
00774 
00775         /* Setup the string */
00776         BaseName.Length = (USHORT)BaseLength;
00777         BaseName.Buffer = p;
00778     }
00779     else
00780     {
00781         /* Otherwise, we already have a base name */
00782         BaseName.Length = FileName->Length;
00783         BaseName.Buffer = FileName->Buffer;
00784     }
00785 
00786     /* Setup the maximum length */
00787     BaseName.MaximumLength = BaseName.Length;
00788 
00789     /* Now compute the base directory */
00790     BaseDirectory = *FileName;
00791     BaseDirectory.Length -= BaseName.Length;
00792     BaseDirectory.MaximumLength = BaseDirectory.Length;
00793 
00794     /* Resolve imports */
00795     MissingApiName = Buffer;
00796     Status = MiResolveImageReferences(DriverBase,
00797                                       &BaseDirectory,
00798                                       NULL,
00799                                       &MissingApiName,
00800                                       &MissingDriverName,
00801                                       &LoadedImports);
00802     if (!NT_SUCCESS(Status)) return Status;
00803 
00804     /* Return */
00805     *ModuleObject = LdrEntry;
00806     return STATUS_SUCCESS;
00807 }
00808 
00809 /*
00810  * IopInitializeBuiltinDriver
00811  *
00812  * Initialize a driver that is already loaded in memory.
00813  */
00814 
00815 NTSTATUS
00816 NTAPI
00817 INIT_FUNCTION
00818 IopInitializeBuiltinDriver(IN PLDR_DATA_TABLE_ENTRY LdrEntry)
00819 {
00820     PDEVICE_NODE DeviceNode;
00821     PDRIVER_OBJECT DriverObject;
00822     NTSTATUS Status;
00823     PWCHAR FileNameWithoutPath;
00824     LPWSTR FileExtension;
00825     PUNICODE_STRING ModuleName = &LdrEntry->BaseDllName;
00826     UNICODE_STRING ServiceName;
00827 
00828    /*
00829     * Display 'Loading XXX...' message
00830     */
00831    IopDisplayLoadingMessage(ModuleName);
00832    InbvIndicateProgress();
00833 
00834    /*
00835     * Generate filename without path (not needed by freeldr)
00836     */
00837    FileNameWithoutPath = wcsrchr(ModuleName->Buffer, L'\\');
00838    if (FileNameWithoutPath == NULL)
00839    {
00840       FileNameWithoutPath = ModuleName->Buffer;
00841    }
00842    else
00843    {
00844       FileNameWithoutPath++;
00845    }
00846 
00847    /*
00848     * Strip the file extension from ServiceName
00849     */
00850    RtlCreateUnicodeString(&ServiceName, FileNameWithoutPath);
00851    FileExtension = wcsrchr(ServiceName.Buffer, '.');
00852    if (FileExtension != NULL)
00853    {
00854       ServiceName.Length -= (USHORT)wcslen(FileExtension) * sizeof(WCHAR);
00855       FileExtension[0] = 0;
00856    }
00857 
00858    /*
00859     * Determine the right device object
00860     */
00861    /* Use IopRootDeviceNode for now */
00862    Status = IopCreateDeviceNode(IopRootDeviceNode, NULL, &ServiceName, &DeviceNode);
00863    if (!NT_SUCCESS(Status))
00864    {
00865       DPRINT1("Driver '%wZ' load failed, status (%x)\n", ModuleName, Status);
00866       return(Status);
00867    }
00868 
00869    /*
00870     * Initialize the driver
00871     */
00872    Status = IopInitializeDriverModule(DeviceNode, LdrEntry,
00873       &DeviceNode->ServiceName, FALSE, &DriverObject);
00874 
00875    if (!NT_SUCCESS(Status))
00876    {
00877       IopFreeDeviceNode(DeviceNode);
00878       return Status;
00879    }
00880 
00881    Status = IopInitializeDevice(DeviceNode, DriverObject);
00882    if (NT_SUCCESS(Status))
00883    {
00884       Status = IopStartDevice(DeviceNode);
00885    }
00886 
00887    /* Remove extra reference from IopInitializeDriverModule */
00888    ObDereferenceObject(DriverObject);
00889 
00890    return Status;
00891 }
00892 
00893 /*
00894  * IopInitializeBootDrivers
00895  *
00896  * Initialize boot drivers and free memory for boot files.
00897  *
00898  * Parameters
00899  *    None
00900  *
00901  * Return Value
00902  *    None
00903  */
00904 VOID
00905 FASTCALL
00906 INIT_FUNCTION
00907 IopInitializeBootDrivers(VOID)
00908 {
00909     PLIST_ENTRY ListHead, NextEntry, NextEntry2;
00910     PLDR_DATA_TABLE_ENTRY LdrEntry;
00911     PDEVICE_NODE DeviceNode;
00912     PDRIVER_OBJECT DriverObject;
00913     LDR_DATA_TABLE_ENTRY ModuleObject;
00914     NTSTATUS Status;
00915     UNICODE_STRING DriverName;
00916     ULONG i, Index;
00917     PDRIVER_INFORMATION DriverInfo, DriverInfoTag;
00918     HANDLE KeyHandle;
00919     PBOOT_DRIVER_LIST_ENTRY BootEntry;
00920     DPRINT("IopInitializeBootDrivers()\n");
00921 
00922     /* Use IopRootDeviceNode for now */
00923     Status = IopCreateDeviceNode(IopRootDeviceNode, NULL, NULL, &DeviceNode);
00924     if (!NT_SUCCESS(Status)) return;
00925 
00926     /* Setup the module object for the RAW FS Driver */
00927     ModuleObject.DllBase = NULL;
00928     ModuleObject.SizeOfImage = 0;
00929     ModuleObject.EntryPoint = RawFsDriverEntry;
00930     RtlInitUnicodeString(&DriverName, L"RAW");
00931 
00932     /* Initialize it */
00933     Status = IopInitializeDriverModule(DeviceNode,
00934                                        &ModuleObject,
00935                                        &DriverName,
00936                                        TRUE,
00937                                        &DriverObject);
00938     if (!NT_SUCCESS(Status))
00939     {
00940         /* Fail */
00941         IopFreeDeviceNode(DeviceNode);
00942         return;
00943     }
00944 
00945     /* Now initialize the associated device */
00946     Status = IopInitializeDevice(DeviceNode, DriverObject);
00947     if (!NT_SUCCESS(Status))
00948     {
00949         /* Fail */
00950         IopFreeDeviceNode(DeviceNode);
00951         ObDereferenceObject(DriverObject);
00952         return;
00953     }
00954 
00955     /* Start it up */
00956     Status = IopStartDevice(DeviceNode);
00957     if (!NT_SUCCESS(Status))
00958     {
00959         /* Fail */
00960         IopFreeDeviceNode(DeviceNode);
00961         ObDereferenceObject(DriverObject);
00962         return;
00963     }
00964 
00965     /* Get highest group order index */
00966     IopGroupIndex = PpInitGetGroupOrderIndex(NULL);
00967     if (IopGroupIndex == 0xFFFF) ASSERT(FALSE);
00968 
00969     /* Allocate the group table */
00970     IopGroupTable = ExAllocatePoolWithTag(PagedPool,
00971                                           IopGroupIndex * sizeof(LIST_ENTRY),
00972                                           TAG_IO);
00973     if (IopGroupTable == NULL) ASSERT(FALSE);
00974 
00975     /* Initialize the group table lists */
00976     for (i = 0; i < IopGroupIndex; i++) InitializeListHead(&IopGroupTable[i]);
00977 
00978     /* Loop the boot modules */
00979     ListHead = &KeLoaderBlock->LoadOrderListHead;
00980     NextEntry = ListHead->Flink;
00981     while (ListHead != NextEntry)
00982     {
00983         /* Get the entry */
00984         LdrEntry = CONTAINING_RECORD(NextEntry,
00985                                      LDR_DATA_TABLE_ENTRY,
00986                                      InLoadOrderLinks);
00987 
00988         /* Check if the DLL needs to be initialized */
00989         if (LdrEntry->Flags & LDRP_DRIVER_DEPENDENT_DLL)
00990         {
00991             /* Call its entrypoint */
00992             MmCallDllInitialize(LdrEntry, NULL);
00993         }
00994 
00995         /* Go to the next driver */
00996         NextEntry = NextEntry->Flink;
00997     }
00998 
00999     /* Loop the boot drivers */
01000     ListHead = &KeLoaderBlock->BootDriverListHead;
01001     NextEntry = ListHead->Flink;
01002     while (ListHead != NextEntry)
01003     {
01004         /* Get the entry */
01005         BootEntry = CONTAINING_RECORD(NextEntry,
01006                                       BOOT_DRIVER_LIST_ENTRY,
01007                                       Link);
01008 
01009         /* Get the driver loader entry */
01010         LdrEntry = BootEntry->LdrEntry;
01011 
01012         /* Allocate our internal accounting structure */
01013         DriverInfo = ExAllocatePoolWithTag(PagedPool,
01014                                            sizeof(DRIVER_INFORMATION),
01015                                            TAG_IO);
01016         if (DriverInfo)
01017         {
01018             /* Zero it and initialize it */
01019             RtlZeroMemory(DriverInfo, sizeof(DRIVER_INFORMATION));
01020             InitializeListHead(&DriverInfo->Link);
01021             DriverInfo->DataTableEntry = BootEntry;
01022 
01023             /* Open the registry key */
01024             Status = IopOpenRegistryKeyEx(&KeyHandle,
01025                                           NULL,
01026                                           &BootEntry->RegistryPath,
01027                                           KEY_READ);
01028             if ((NT_SUCCESS(Status)) || /* ReactOS HACK for SETUPLDR */
01029                 ((KeLoaderBlock->SetupLdrBlock) && ((KeyHandle = (PVOID)1)))) // yes, it's an assignment!
01030             {
01031                 /* Save the handle */
01032                 DriverInfo->ServiceHandle = KeyHandle;
01033 
01034                 /* Get the group oder index */
01035                 Index = PpInitGetGroupOrderIndex(KeyHandle);
01036 
01037                 /* Get the tag position */
01038                 DriverInfo->TagPosition = PipGetDriverTagPriority(KeyHandle);
01039 
01040                 /* Insert it into the list, at the right place */
01041                 ASSERT(Index < IopGroupIndex);
01042                 NextEntry2 = IopGroupTable[Index].Flink;
01043                 while (NextEntry2 != &IopGroupTable[Index])
01044                 {
01045                     /* Get the driver info */
01046                     DriverInfoTag = CONTAINING_RECORD(NextEntry2,
01047                                                       DRIVER_INFORMATION,
01048                                                       Link);
01049 
01050                     /* Check if we found the right tag position */
01051                     if (DriverInfoTag->TagPosition > DriverInfo->TagPosition)
01052                     {
01053                         /* We're done */
01054                         break;
01055                     }
01056 
01057                     /* Next entry */
01058                     NextEntry2 = NextEntry2->Flink;
01059                 }
01060 
01061                 /* Insert us right before the next entry */
01062                 NextEntry2 = NextEntry2->Blink;
01063                 InsertHeadList(NextEntry2, &DriverInfo->Link);
01064             }
01065         }
01066 
01067         /* Go to the next driver */
01068         NextEntry = NextEntry->Flink;
01069     }
01070 
01071     /* Loop each group index */
01072     for (i = 0; i < IopGroupIndex; i++)
01073     {
01074         /* Loop each group table */
01075         NextEntry = IopGroupTable[i].Flink;
01076         while (NextEntry != &IopGroupTable[i])
01077         {
01078             /* Get the entry */
01079             DriverInfo = CONTAINING_RECORD(NextEntry,
01080                                            DRIVER_INFORMATION,
01081                                            Link);
01082 
01083             /* Get the driver loader entry */
01084             LdrEntry = DriverInfo->DataTableEntry->LdrEntry;
01085 
01086             /* Initialize it */
01087             IopInitializeBuiltinDriver(LdrEntry);
01088 
01089             /* Next entry */
01090             NextEntry = NextEntry->Flink;
01091         }
01092     }
01093 
01094     /* In old ROS, the loader list became empty after this point. Simulate. */
01095     InitializeListHead(&KeLoaderBlock->LoadOrderListHead);
01096 }
01097 
01098 VOID
01099 FASTCALL
01100 INIT_FUNCTION
01101 IopInitializeSystemDrivers(VOID)
01102 {
01103     PUNICODE_STRING *DriverList, *SavedList;
01104 
01105     /* No system drivers on the boot cd */
01106     if (KeLoaderBlock->SetupLdrBlock) return;
01107 
01108     /* Get the driver list */
01109     SavedList = DriverList = CmGetSystemDriverList();
01110     ASSERT(DriverList);
01111 
01112     /* Loop it */
01113     while (*DriverList)
01114     {
01115         /* Load the driver */
01116         ZwLoadDriver(*DriverList);
01117 
01118         /* Free the entry */
01119         RtlFreeUnicodeString(*DriverList);
01120         ExFreePool(*DriverList);
01121 
01122         /* Next entry */
01123         InbvIndicateProgress();
01124         DriverList++;
01125     }
01126 
01127     /* Free the list */
01128     ExFreePool(SavedList);
01129 }
01130 
01131 /*
01132  * IopUnloadDriver
01133  *
01134  * Unloads a device driver.
01135  *
01136  * Parameters
01137  *    DriverServiceName
01138  *       Name of the service to unload (registry key).
01139  *
01140  *    UnloadPnpDrivers
01141  *       Whether to unload Plug & Plug or only legacy drivers. If this
01142  *       parameter is set to FALSE, the routine will unload only legacy
01143  *       drivers.
01144  *
01145  * Return Value
01146  *    Status
01147  *
01148  * To do
01149  *    Guard the whole function by SEH.
01150  */
01151 
01152 NTSTATUS NTAPI
01153 IopUnloadDriver(PUNICODE_STRING DriverServiceName, BOOLEAN UnloadPnpDrivers)
01154 {
01155    RTL_QUERY_REGISTRY_TABLE QueryTable[2];
01156    UNICODE_STRING ImagePath;
01157    UNICODE_STRING ServiceName;
01158    UNICODE_STRING ObjectName;
01159    PDRIVER_OBJECT DriverObject;
01160    PDEVICE_OBJECT DeviceObject;
01161    PEXTENDED_DEVOBJ_EXTENSION DeviceExtension;
01162    LOAD_UNLOAD_PARAMS LoadParams;
01163    NTSTATUS Status;
01164    LPWSTR Start;
01165    BOOLEAN SafeToUnload = TRUE;
01166 
01167    DPRINT("IopUnloadDriver('%wZ', %d)\n", DriverServiceName, UnloadPnpDrivers);
01168 
01169    PAGED_CODE();
01170 
01171    /*
01172     * Get the service name from the registry key name
01173     */
01174 
01175    Start = wcsrchr(DriverServiceName->Buffer, L'\\');
01176    if (Start == NULL)
01177       Start = DriverServiceName->Buffer;
01178    else
01179       Start++;
01180 
01181    RtlInitUnicodeString(&ServiceName, Start);
01182 
01183    /*
01184     * Construct the driver object name
01185     */
01186 
01187    ObjectName.Length = ((USHORT)wcslen(Start) + 8) * sizeof(WCHAR);
01188    ObjectName.MaximumLength = ObjectName.Length + sizeof(WCHAR);
01189    ObjectName.Buffer = ExAllocatePool(PagedPool, ObjectName.MaximumLength);
01190    if (!ObjectName.Buffer) return STATUS_INSUFFICIENT_RESOURCES;
01191    wcscpy(ObjectName.Buffer, L"\\Driver\\");
01192    memcpy(ObjectName.Buffer + 8, Start, ObjectName.Length - 8 * sizeof(WCHAR));
01193    ObjectName.Buffer[ObjectName.Length/sizeof(WCHAR)] = 0;
01194 
01195    /*
01196     * Find the driver object
01197     */
01198    Status = ObReferenceObjectByName(&ObjectName,
01199                                     0,
01200                                     0,
01201                                     0,
01202                                     IoDriverObjectType,
01203                                     KernelMode,
01204                                     0,
01205                                     (PVOID*)&DriverObject);
01206 
01207    if (!NT_SUCCESS(Status))
01208    {
01209       DPRINT1("Can't locate driver object for %wZ\n", &ObjectName);
01210       ExFreePool(ObjectName.Buffer);
01211       return Status;
01212    }
01213 
01214    /*
01215     * Free the buffer for driver object name
01216     */
01217    ExFreePool(ObjectName.Buffer);
01218 
01219    /* Check that driver is not already unloading */
01220    if (DriverObject->Flags & DRVO_UNLOAD_INVOKED)
01221    {
01222        DPRINT1("Driver deletion pending\n");
01223        ObDereferenceObject(DriverObject);
01224        return STATUS_DELETE_PENDING;
01225    }
01226 
01227    /*
01228     * Get path of service...
01229     */
01230 
01231    RtlZeroMemory(QueryTable, sizeof(QueryTable));
01232 
01233    RtlInitUnicodeString(&ImagePath, NULL);
01234 
01235    QueryTable[0].Name = L"ImagePath";
01236    QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
01237    QueryTable[0].EntryContext = &ImagePath;
01238 
01239    Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
01240        DriverServiceName->Buffer, QueryTable, NULL, NULL);
01241 
01242    if (!NT_SUCCESS(Status))
01243    {
01244       DPRINT1("RtlQueryRegistryValues() failed (Status %x)\n", Status);
01245       ObDereferenceObject(DriverObject);
01246       return Status;
01247    }
01248 
01249    /*
01250     * Normalize the image path for all later processing.
01251     */
01252 
01253    Status = IopNormalizeImagePath(&ImagePath, &ServiceName);
01254 
01255    if (!NT_SUCCESS(Status))
01256    {
01257       DPRINT1("IopNormalizeImagePath() failed (Status %x)\n", Status);
01258       ObDereferenceObject(DriverObject);
01259       return Status;
01260    }
01261 
01262    /*
01263     * Free the service path
01264     */
01265 
01266    ExFreePool(ImagePath.Buffer);
01267 
01268    /*
01269     * Unload the module and release the references to the device object
01270     */
01271 
01272     /* Call the load/unload routine, depending on current process */
01273    if (DriverObject->DriverUnload && DriverObject->DriverSection &&
01274        (UnloadPnpDrivers || (DriverObject->Flags & DRVO_LEGACY_DRIVER)))
01275    {
01276       /* Loop through each device object of the driver
01277          and set DOE_UNLOAD_PENDING flag */
01278       DeviceObject = DriverObject->DeviceObject;
01279       while (DeviceObject)
01280       {
01281          /* Set the unload pending flag for the device */
01282          DeviceExtension = IoGetDevObjExtension(DeviceObject);
01283          DeviceExtension->ExtensionFlags |= DOE_UNLOAD_PENDING;
01284 
01285          /* Make sure there are no attached devices or no reference counts */
01286          if ((DeviceObject->ReferenceCount) || (DeviceObject->AttachedDevice))
01287          {
01288             /* Not safe to unload */
01289             DPRINT1("Drivers device object is referenced or has attached devices\n");
01290 
01291             SafeToUnload = FALSE;
01292          }
01293 
01294          DeviceObject = DeviceObject->NextDevice;
01295       }
01296 
01297       /* If not safe to unload, then return success */
01298       if (!SafeToUnload)
01299       {
01300          ObDereferenceObject(DriverObject);
01301          return STATUS_SUCCESS;
01302       }
01303 
01304       DPRINT1("Unloading driver '%wZ' (manual)\n", &DriverObject->DriverName);
01305 
01306       /* Set the unload invoked flag */
01307       DriverObject->Flags |= DRVO_UNLOAD_INVOKED;
01308 
01309       if (PsGetCurrentProcess() == PsInitialSystemProcess)
01310       {
01311          /* Just call right away */
01312          (*DriverObject->DriverUnload)(DriverObject);
01313       }
01314       else
01315       {
01316          /* Load/Unload must be called from system process */
01317 
01318          /* Prepare parameters block */
01319          LoadParams.DriverObject = DriverObject;
01320          KeInitializeEvent(&LoadParams.Event, NotificationEvent, FALSE);
01321 
01322          ExInitializeWorkItem(&LoadParams.WorkItem,
01323              (PWORKER_THREAD_ROUTINE)IopLoadUnloadDriver,
01324              (PVOID)&LoadParams);
01325 
01326          /* Queue it */
01327          ExQueueWorkItem(&LoadParams.WorkItem, DelayedWorkQueue);
01328 
01329          /* And wait when it completes */
01330          KeWaitForSingleObject(&LoadParams.Event, UserRequest, KernelMode,
01331              FALSE, NULL);
01332       }
01333 
01334       /* Mark the driver object temporary, so it could be deleted later */
01335       ObMakeTemporaryObject(DriverObject);
01336 
01337       /* Dereference it 2 times */
01338       ObDereferenceObject(DriverObject);
01339       ObDereferenceObject(DriverObject);
01340 
01341       return STATUS_SUCCESS;
01342    }
01343    else
01344    {
01345       DPRINT1("No DriverUnload function! '%wZ' will not be unloaded!\n", &DriverObject->DriverName);
01346 
01347       /* Dereference one time (refd inside this function) */
01348       ObDereferenceObject(DriverObject);
01349 
01350       /* Return unloading failure */
01351       return STATUS_INVALID_DEVICE_REQUEST;
01352    }
01353 }
01354 
01355 VOID
01356 NTAPI
01357 IopReinitializeDrivers(VOID)
01358 {
01359     PDRIVER_REINIT_ITEM ReinitItem;
01360     PLIST_ENTRY Entry;
01361 
01362     /* Get the first entry and start looping */
01363     Entry = ExInterlockedRemoveHeadList(&DriverReinitListHead,
01364                                         &DriverReinitListLock);
01365     while (Entry)
01366     {
01367         /* Get the item*/
01368         ReinitItem = CONTAINING_RECORD(Entry, DRIVER_REINIT_ITEM, ItemEntry);
01369 
01370         /* Increment reinitialization counter */
01371         ReinitItem->DriverObject->DriverExtension->Count++;
01372 
01373         /* Remove the device object flag */
01374         ReinitItem->DriverObject->Flags &= ~DRVO_REINIT_REGISTERED;
01375 
01376         /* Call the routine */
01377         ReinitItem->ReinitRoutine(ReinitItem->DriverObject,
01378                                   ReinitItem->Context,
01379                                   ReinitItem->DriverObject->
01380                                   DriverExtension->Count);
01381 
01382         /* Free the entry */
01383         ExFreePool(Entry);
01384 
01385         /* Move to the next one */
01386         Entry = ExInterlockedRemoveHeadList(&DriverReinitListHead,
01387                                             &DriverReinitListLock);
01388     }
01389 }
01390 
01391 VOID
01392 NTAPI
01393 IopReinitializeBootDrivers(VOID)
01394 {
01395     PDRIVER_REINIT_ITEM ReinitItem;
01396     PLIST_ENTRY Entry;
01397 
01398     /* Get the first entry and start looping */
01399     Entry = ExInterlockedRemoveHeadList(&DriverBootReinitListHead,
01400                                         &DriverBootReinitListLock);
01401     while (Entry)
01402     {
01403         /* Get the item*/
01404         ReinitItem = CONTAINING_RECORD(Entry, DRIVER_REINIT_ITEM, ItemEntry);
01405 
01406         /* Increment reinitialization counter */
01407         ReinitItem->DriverObject->DriverExtension->Count++;
01408 
01409         /* Remove the device object flag */
01410         ReinitItem->DriverObject->Flags &= ~DRVO_BOOTREINIT_REGISTERED;
01411 
01412         /* Call the routine */
01413         ReinitItem->ReinitRoutine(ReinitItem->DriverObject,
01414                                   ReinitItem->Context,
01415                                   ReinitItem->DriverObject->
01416                                   DriverExtension->Count);
01417 
01418         /* Free the entry */
01419         ExFreePool(Entry);
01420 
01421         /* Move to the next one */
01422         Entry = ExInterlockedRemoveHeadList(&DriverBootReinitListHead,
01423                                             &DriverBootReinitListLock);
01424     }
01425 }
01426 
01427 NTSTATUS
01428 NTAPI
01429 IopCreateDriver(IN PUNICODE_STRING DriverName OPTIONAL,
01430                 IN PDRIVER_INITIALIZE InitializationFunction,
01431                 IN PUNICODE_STRING RegistryPath,
01432                 PLDR_DATA_TABLE_ENTRY ModuleObject,
01433                 OUT PDRIVER_OBJECT *pDriverObject)
01434 {
01435     WCHAR NameBuffer[100];
01436     USHORT NameLength;
01437     UNICODE_STRING LocalDriverName;
01438     NTSTATUS Status;
01439     OBJECT_ATTRIBUTES ObjectAttributes;
01440     ULONG ObjectSize;
01441     PDRIVER_OBJECT DriverObject;
01442     UNICODE_STRING ServiceKeyName;
01443     HANDLE hDriver;
01444     ULONG i, RetryCount = 0;
01445 
01446 try_again:
01447     /* First, create a unique name for the driver if we don't have one */
01448     if (!DriverName)
01449     {
01450         /* Create a random name and set up the string*/
01451         NameLength = (USHORT)swprintf(NameBuffer,
01452                                       L"\\Driver\\%08u",
01453                                       KeTickCount);
01454         LocalDriverName.Length = NameLength * sizeof(WCHAR);
01455         LocalDriverName.MaximumLength = LocalDriverName.Length + sizeof(UNICODE_NULL);
01456         LocalDriverName.Buffer = NameBuffer;
01457     }
01458     else
01459     {
01460         /* So we can avoid another code path, use a local var */
01461         LocalDriverName = *DriverName;
01462     }
01463 
01464     /* Initialize the Attributes */
01465     ObjectSize = sizeof(DRIVER_OBJECT) + sizeof(EXTENDED_DRIVER_EXTENSION);
01466     InitializeObjectAttributes(&ObjectAttributes,
01467                                &LocalDriverName,
01468                                OBJ_PERMANENT | OBJ_CASE_INSENSITIVE,
01469                                NULL,
01470                                NULL);
01471 
01472     /* Create the Object */
01473     Status = ObCreateObject(KernelMode,
01474                             IoDriverObjectType,
01475                             &ObjectAttributes,
01476                             KernelMode,
01477                             NULL,
01478                             ObjectSize,
01479                             0,
01480                             0,
01481                             (PVOID*)&DriverObject);
01482     if (!NT_SUCCESS(Status)) return Status;
01483 
01484     DPRINT("IopCreateDriver(): created DO %p\n", DriverObject);
01485 
01486     /* Set up the Object */
01487     RtlZeroMemory(DriverObject, ObjectSize);
01488     DriverObject->Type = IO_TYPE_DRIVER;
01489     DriverObject->Size = sizeof(DRIVER_OBJECT);
01490     DriverObject->Flags = DRVO_LEGACY_DRIVER;
01491     DriverObject->DriverExtension = (PDRIVER_EXTENSION)(DriverObject + 1);
01492     DriverObject->DriverExtension->DriverObject = DriverObject;
01493     DriverObject->DriverInit = InitializationFunction;
01494     DriverObject->DriverSection = ModuleObject;
01495     /* Loop all Major Functions */
01496     for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
01497     {
01498         /* Invalidate each function */
01499         DriverObject->MajorFunction[i] = IopInvalidDeviceRequest;
01500     }
01501 
01502     /* Set up the service key name buffer */
01503     ServiceKeyName.Buffer = ExAllocatePoolWithTag(PagedPool,
01504                                                   LocalDriverName.Length +
01505                                                   sizeof(WCHAR),
01506                                                   TAG_IO);
01507     if (!ServiceKeyName.Buffer)
01508     {
01509         /* Fail */
01510         ObMakeTemporaryObject(DriverObject);
01511         ObDereferenceObject(DriverObject);
01512         return STATUS_INSUFFICIENT_RESOURCES;
01513     }
01514 
01515     /* Fill out the key data and copy the buffer */
01516     ServiceKeyName.Length = LocalDriverName.Length;
01517     ServiceKeyName.MaximumLength = LocalDriverName.MaximumLength;
01518     RtlCopyMemory(ServiceKeyName.Buffer,
01519                   LocalDriverName.Buffer,
01520                   LocalDriverName.Length);
01521 
01522     /* Null-terminate it and set it */
01523     ServiceKeyName.Buffer[ServiceKeyName.Length / sizeof(WCHAR)] = UNICODE_NULL;
01524     DriverObject->DriverExtension->ServiceKeyName = ServiceKeyName;
01525 
01526     /* Also store it in the Driver Object. This is a bit of a hack. */
01527     RtlCopyMemory(&DriverObject->DriverName,
01528                   &ServiceKeyName,
01529                   sizeof(UNICODE_STRING));
01530 
01531     /* Add the Object and get its handle */
01532     Status = ObInsertObject(DriverObject,
01533                             NULL,
01534                             FILE_READ_DATA,
01535                             0,
01536                             NULL,
01537                             &hDriver);
01538 
01539     /* Eliminate small possibility when this function is called more than
01540        once in a row, and KeTickCount doesn't get enough time to change */
01541     if (!DriverName && (Status == STATUS_OBJECT_NAME_COLLISION) && (RetryCount < 100))
01542     {
01543         RetryCount++;
01544         goto try_again;
01545     }
01546 
01547     if (!NT_SUCCESS(Status)) return Status;
01548 
01549     /* Now reference it */
01550     Status = ObReferenceObjectByHandle(hDriver,
01551                                        0,
01552                                        IoDriverObjectType,
01553                                        KernelMode,
01554                                        (PVOID*)&DriverObject,
01555                                        NULL);
01556 
01557     /* Close the extra handle */
01558     ZwClose(hDriver);
01559 
01560     if (!NT_SUCCESS(Status))
01561     {
01562         /* Fail */
01563         ObMakeTemporaryObject(DriverObject);
01564         ObDereferenceObject(DriverObject);
01565         return Status;
01566     }
01567 
01568     DriverObject->HardwareDatabase = &IopHardwareDatabaseKey;
01569     DriverObject->DriverStart = ModuleObject ? ModuleObject->DllBase : 0;
01570     DriverObject->DriverSize = ModuleObject ? ModuleObject->SizeOfImage : 0;
01571 
01572     /* Finally, call its init function */
01573     DPRINT("RegistryKey: %wZ\n", RegistryPath);
01574     DPRINT("Calling driver entrypoint at %p\n", InitializationFunction);
01575     Status = (*InitializationFunction)(DriverObject, RegistryPath);
01576     if (!NT_SUCCESS(Status))
01577     {
01578         /* If it didn't work, then kill the object */
01579         DPRINT1("'%wZ' initialization failed, status (0x%08lx)\n", DriverName, Status);
01580         DriverObject->DriverSection = NULL;
01581         ObMakeTemporaryObject(DriverObject);
01582         ObDereferenceObject(DriverObject);
01583         return Status;
01584     }
01585     else
01586     {
01587         /* Returns to caller the object */
01588         *pDriverObject = DriverObject;
01589     }
01590 
01591     /* We're going to say if we don't have any DOs from DriverEntry, then we're not legacy.
01592      * Other parts of the I/O manager depend on this behavior */
01593     if (!DriverObject->DeviceObject) DriverObject->Flags &= ~DRVO_LEGACY_DRIVER;
01594 
01595     /* Loop all Major Functions */
01596     for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
01597     {
01598         /*
01599          * Make sure the driver didn't set any dispatch entry point to NULL!
01600          * Doing so is illegal; drivers shouldn't touch entry points they
01601          * do not implement.
01602          */
01603 
01604         /* Check if it did so anyway */
01605         if (!DriverObject->MajorFunction[i])
01606         {
01607             /* Print a warning in the debug log */
01608             DPRINT1("Driver <%wZ> set DriverObject->MajorFunction[%d] to NULL!\n",
01609                     &DriverObject->DriverName, i);
01610 
01611             /* Fix it up */
01612             DriverObject->MajorFunction[i] = IopInvalidDeviceRequest;
01613         }
01614     }
01615 
01616     /* Return the Status */
01617     return Status;
01618 }
01619 
01620 /* PUBLIC FUNCTIONS ***********************************************************/
01621 
01622 /*
01623  * @implemented
01624  */
01625 NTSTATUS
01626 NTAPI
01627 IoCreateDriver(IN PUNICODE_STRING DriverName OPTIONAL,
01628                IN PDRIVER_INITIALIZE InitializationFunction)
01629 {
01630    PDRIVER_OBJECT DriverObject;
01631    return IopCreateDriver(DriverName, InitializationFunction, NULL, NULL, &DriverObject);
01632 }
01633 
01634 /*
01635  * @implemented
01636  */
01637 VOID
01638 NTAPI
01639 IoDeleteDriver(IN PDRIVER_OBJECT DriverObject)
01640 {
01641     /* Simply dereference the Object */
01642     ObDereferenceObject(DriverObject);
01643 }
01644 
01645 /*
01646  * @implemented
01647  */
01648 VOID
01649 NTAPI
01650 IoRegisterBootDriverReinitialization(IN PDRIVER_OBJECT DriverObject,
01651                                      IN PDRIVER_REINITIALIZE ReinitRoutine,
01652                                      IN PVOID Context)
01653 {
01654     PDRIVER_REINIT_ITEM ReinitItem;
01655 
01656     /* Allocate the entry */
01657     ReinitItem = ExAllocatePoolWithTag(NonPagedPool,
01658                                        sizeof(DRIVER_REINIT_ITEM),
01659                                        TAG_REINIT);
01660     if (!ReinitItem) return;
01661 
01662     /* Fill it out */
01663     ReinitItem->DriverObject = DriverObject;
01664     ReinitItem->ReinitRoutine = ReinitRoutine;
01665     ReinitItem->Context = Context;
01666 
01667     /* Set the Driver Object flag and insert the entry into the list */
01668     DriverObject->Flags |= DRVO_BOOTREINIT_REGISTERED;
01669     ExInterlockedInsertTailList(&DriverBootReinitListHead,
01670                                 &ReinitItem->ItemEntry,
01671                                 &DriverBootReinitListLock);
01672 }
01673 
01674 /*
01675  * @implemented
01676  */
01677 VOID
01678 NTAPI
01679 IoRegisterDriverReinitialization(IN PDRIVER_OBJECT DriverObject,
01680                                  IN PDRIVER_REINITIALIZE ReinitRoutine,
01681                                  IN PVOID Context)
01682 {
01683     PDRIVER_REINIT_ITEM ReinitItem;
01684 
01685     /* Allocate the entry */
01686     ReinitItem = ExAllocatePoolWithTag(NonPagedPool,
01687                                        sizeof(DRIVER_REINIT_ITEM),
01688                                        TAG_REINIT);
01689     if (!ReinitItem) return;
01690 
01691     /* Fill it out */
01692     ReinitItem->DriverObject = DriverObject;
01693     ReinitItem->ReinitRoutine = ReinitRoutine;
01694     ReinitItem->Context = Context;
01695 
01696     /* Set the Driver Object flag and insert the entry into the list */
01697     DriverObject->Flags |= DRVO_REINIT_REGISTERED;
01698     ExInterlockedInsertTailList(&DriverReinitListHead,
01699                                 &ReinitItem->ItemEntry,
01700                                 &DriverReinitListLock);
01701 }
01702 
01703 /*
01704  * @implemented
01705  */
01706 NTSTATUS
01707 NTAPI
01708 IoAllocateDriverObjectExtension(IN PDRIVER_OBJECT DriverObject,
01709                                 IN PVOID ClientIdentificationAddress,
01710                                 IN ULONG DriverObjectExtensionSize,
01711                                 OUT PVOID *DriverObjectExtension)
01712 {
01713     KIRQL OldIrql;
01714     PIO_CLIENT_EXTENSION DriverExtensions, NewDriverExtension;
01715     BOOLEAN Inserted = FALSE;
01716 
01717     /* Assume failure */
01718     *DriverObjectExtension = NULL;
01719 
01720     /* Allocate the extension */
01721     NewDriverExtension = ExAllocatePoolWithTag(NonPagedPool,
01722                                                sizeof(IO_CLIENT_EXTENSION) +
01723                                                DriverObjectExtensionSize,
01724                                                TAG_DRIVER_EXTENSION);
01725     if (!NewDriverExtension) return STATUS_INSUFFICIENT_RESOURCES;
01726 
01727     /* Clear the extension for teh caller */
01728     RtlZeroMemory(NewDriverExtension,
01729                   sizeof(IO_CLIENT_EXTENSION) + DriverObjectExtensionSize);
01730 
01731     /* Acqure lock */
01732     OldIrql = KeRaiseIrqlToDpcLevel();
01733 
01734     /* Fill out the extension */
01735     NewDriverExtension->ClientIdentificationAddress = ClientIdentificationAddress;
01736 
01737     /* Loop the current extensions */
01738     DriverExtensions = IoGetDrvObjExtension(DriverObject)->
01739                        ClientDriverExtension;
01740     while (DriverExtensions)
01741     {
01742         /* Check if the identifier matches */
01743         if (DriverExtensions->ClientIdentificationAddress ==
01744             ClientIdentificationAddress)
01745         {
01746             /* We have a collision, break out */
01747             break;
01748         }
01749 
01750         /* Go to the next one */
01751         DriverExtensions = DriverExtensions->NextExtension;
01752     }
01753 
01754     /* Check if we didn't collide */
01755     if (!DriverExtensions)
01756     {
01757         /* Link this one in */
01758         NewDriverExtension->NextExtension =
01759             IoGetDrvObjExtension(DriverObject)->ClientDriverExtension;
01760         IoGetDrvObjExtension(DriverObject)->ClientDriverExtension =
01761             NewDriverExtension;
01762         Inserted = TRUE;
01763     }
01764 
01765     /* Release the lock */
01766     KeLowerIrql(OldIrql);
01767 
01768     /* Check if insertion failed */
01769     if (!Inserted)
01770     {
01771         /* Free the entry and fail */
01772         ExFreePool(NewDriverExtension);
01773         return STATUS_OBJECT_NAME_COLLISION;
01774     }
01775 
01776     /* Otherwise, return the pointer */
01777     *DriverObjectExtension = NewDriverExtension + 1;
01778     return STATUS_SUCCESS;
01779 }
01780 
01781 /*
01782  * @implemented
01783  */
01784 PVOID
01785 NTAPI
01786 IoGetDriverObjectExtension(IN PDRIVER_OBJECT DriverObject,
01787                            IN PVOID ClientIdentificationAddress)
01788 {
01789     KIRQL OldIrql;
01790     PIO_CLIENT_EXTENSION DriverExtensions;
01791 
01792     /* Acquire lock */
01793     OldIrql = KeRaiseIrqlToDpcLevel();
01794 
01795     /* Loop the list until we find the right one */
01796     DriverExtensions = IoGetDrvObjExtension(DriverObject)->ClientDriverExtension;
01797     while (DriverExtensions)
01798     {
01799         /* Check for a match */
01800         if (DriverExtensions->ClientIdentificationAddress ==
01801             ClientIdentificationAddress)
01802         {
01803             /* Break out */
01804             break;
01805         }
01806 
01807         /* Keep looping */
01808         DriverExtensions = DriverExtensions->NextExtension;
01809     }
01810 
01811     /* Release lock */
01812     KeLowerIrql(OldIrql);
01813 
01814     /* Return nothing or the extension */
01815     if (!DriverExtensions) return NULL;
01816     return DriverExtensions + 1;
01817 }
01818 
01819 VOID NTAPI
01820 IopLoadUnloadDriver(PLOAD_UNLOAD_PARAMS LoadParams)
01821 {
01822    RTL_QUERY_REGISTRY_TABLE QueryTable[3];
01823    UNICODE_STRING ImagePath;
01824    UNICODE_STRING ServiceName;
01825    NTSTATUS Status;
01826    ULONG Type;
01827    PDEVICE_NODE DeviceNode;
01828    PDRIVER_OBJECT DriverObject;
01829    PLDR_DATA_TABLE_ENTRY ModuleObject;
01830    PVOID BaseAddress;
01831    WCHAR *cur;
01832 
01833    /* Check if it's an unload request */
01834    if (LoadParams->DriverObject)
01835    {
01836        (*LoadParams->DriverObject->DriverUnload)(LoadParams->DriverObject);
01837 
01838        /* Return success and signal the event */
01839        LoadParams->Status = STATUS_SUCCESS;
01840       (VOID)KeSetEvent(&LoadParams->Event, 0, FALSE);
01841        return;
01842    }
01843 
01844    RtlInitUnicodeString(&ImagePath, NULL);
01845 
01846    /*
01847     * Get the service name from the registry key name.
01848     */
01849    ASSERT(LoadParams->ServiceName->Length >= sizeof(WCHAR));
01850 
01851    ServiceName = *LoadParams->ServiceName;
01852    cur = LoadParams->ServiceName->Buffer +
01853        (LoadParams->ServiceName->Length / sizeof(WCHAR)) - 1;
01854    while (LoadParams->ServiceName->Buffer != cur)
01855    {
01856       if(*cur == L'\\')
01857       {
01858          ServiceName.Buffer = cur + 1;
01859          ServiceName.Length = LoadParams->ServiceName->Length -
01860                               (USHORT)((ULONG_PTR)ServiceName.Buffer -
01861                                        (ULONG_PTR)LoadParams->ServiceName->Buffer);
01862          break;
01863       }
01864       cur--;
01865    }
01866 
01867    /*
01868     * Get service type.
01869     */
01870 
01871    RtlZeroMemory(&QueryTable, sizeof(QueryTable));
01872 
01873    RtlInitUnicodeString(&ImagePath, NULL);
01874 
01875    QueryTable[0].Name = L"Type";
01876    QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
01877    QueryTable[0].EntryContext = &Type;
01878 
01879    QueryTable[1].Name = L"ImagePath";
01880    QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
01881    QueryTable[1].EntryContext = &ImagePath;
01882 
01883    Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
01884       LoadParams->ServiceName->Buffer, QueryTable, NULL, NULL);
01885 
01886    if (!NT_SUCCESS(Status))
01887    {
01888       DPRINT("RtlQueryRegistryValues() failed (Status %lx)\n", Status);
01889       if (ImagePath.Buffer)
01890          ExFreePool(ImagePath.Buffer);
01891       LoadParams->Status = Status;
01892       (VOID)KeSetEvent(&LoadParams->Event, 0, FALSE);
01893       return;
01894    }
01895 
01896    /*
01897     * Normalize the image path for all later processing.
01898     */
01899 
01900    Status = IopNormalizeImagePath(&ImagePath, &ServiceName);
01901 
01902    if (!NT_SUCCESS(Status))
01903    {
01904       DPRINT("IopNormalizeImagePath() failed (Status %x)\n", Status);
01905       LoadParams->Status = Status;
01906       (VOID)KeSetEvent(&LoadParams->Event, 0, FALSE);
01907       return;
01908    }
01909 
01910    DPRINT("FullImagePath: '%wZ'\n", &ImagePath);
01911    DPRINT("Type: %lx\n", Type);
01912 
01913    /* Get existing DriverObject pointer (in case the driver has
01914       already been loaded and initialized) */
01915    Status = IopGetDriverObject(
01916        &DriverObject,
01917        &ServiceName,
01918        (Type == 2 /* SERVICE_FILE_SYSTEM_DRIVER */ ||
01919         Type == 8 /* SERVICE_RECOGNIZER_DRIVER */));
01920 
01921    if (!NT_SUCCESS(Status))
01922    {
01923        /*
01924         * Load the driver module
01925         */
01926 
01927        DPRINT("Loading module from %wZ\n", &ImagePath);
01928        Status = MmLoadSystemImage(&ImagePath, NULL, NULL, 0, (PVOID)&ModuleObject, &BaseAddress);
01929 
01930        if (!NT_SUCCESS(Status))
01931        {
01932            DPRINT("MmLoadSystemImage() failed (Status %lx)\n", Status);
01933            LoadParams->Status = Status;
01934            (VOID)KeSetEvent(&LoadParams->Event, 0, FALSE);
01935            return;
01936        }
01937 
01938        /*
01939         * Initialize the driver module if it's loaded for the first time
01940         */
01941        Status = IopCreateDeviceNode(IopRootDeviceNode, NULL, &ServiceName, &DeviceNode);
01942        if (!NT_SUCCESS(Status))
01943        {
01944            DPRINT1("IopCreateDeviceNode() failed (Status %lx)\n", Status);
01945            MmUnloadSystemImage(ModuleObject);
01946            LoadParams->Status = Status;
01947            (VOID)KeSetEvent(&LoadParams->Event, 0, FALSE);
01948            return;
01949        }
01950 
01951        IopDisplayLoadingMessage(&DeviceNode->ServiceName);
01952 
01953        Status = IopInitializeDriverModule(DeviceNode,
01954                                           ModuleObject,
01955                                           &DeviceNode->ServiceName,
01956                                           (Type == 2 /* SERVICE_FILE_SYSTEM_DRIVER */ ||
01957                                            Type == 8 /* SERVICE_RECOGNIZER_DRIVER */),
01958                                           &DriverObject);
01959        if (!NT_SUCCESS(Status))
01960        {
01961            DPRINT1("IopInitializeDriver() failed (Status %lx)\n", Status);
01962            MmUnloadSystemImage(ModuleObject);
01963            IopFreeDeviceNode(DeviceNode);
01964            LoadParams->Status = Status;
01965            (VOID)KeSetEvent(&LoadParams->Event, 0, FALSE);
01966            return;
01967        }
01968 
01969        /* Initialize and start device */
01970        IopInitializeDevice(DeviceNode, DriverObject);
01971        Status = IopStartDevice(DeviceNode);
01972    }
01973    else
01974    {
01975       DPRINT("DriverObject already exist in ObjectManager\n");
01976       Status = STATUS_IMAGE_ALREADY_LOADED;
01977 
01978       /* IopGetDriverObject references the DriverObject, so dereference it */
01979       ObDereferenceObject(DriverObject);
01980    }
01981 
01982    /* Pass status to the caller and signal the event */
01983    LoadParams->Status = Status;
01984    (VOID)KeSetEvent(&LoadParams->Event, 0, FALSE);
01985 }
01986 
01987 /*
01988  * NtLoadDriver
01989  *
01990  * Loads a device driver.
01991  *
01992  * Parameters
01993  *    DriverServiceName
01994  *       Name of the service to load (registry key).
01995  *
01996  * Return Value
01997  *    Status
01998  *
01999  * Status
02000  *    implemented
02001  */
02002 NTSTATUS NTAPI
02003 NtLoadDriver(IN PUNICODE_STRING DriverServiceName)
02004 {
02005     UNICODE_STRING CapturedDriverServiceName = { 0, 0, NULL };
02006     KPROCESSOR_MODE PreviousMode;
02007     LOAD_UNLOAD_PARAMS LoadParams;
02008     NTSTATUS Status;
02009 
02010     PAGED_CODE();
02011 
02012     PreviousMode = KeGetPreviousMode();
02013 
02014     /*
02015     * Check security privileges
02016     */
02017 
02018     /* FIXME: Uncomment when privileges will be correctly implemented. */
02019 #if 0
02020     if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege, PreviousMode))
02021     {
02022         DPRINT("Privilege not held\n");
02023         return STATUS_PRIVILEGE_NOT_HELD;
02024     }
02025 #endif
02026 
02027     Status = ProbeAndCaptureUnicodeString(&CapturedDriverServiceName,
02028                                           PreviousMode,
02029                                           DriverServiceName);
02030     if (!NT_SUCCESS(Status))
02031     {
02032         return Status;
02033     }
02034 
02035     DPRINT("NtLoadDriver('%wZ')\n", &CapturedDriverServiceName);
02036 
02037     LoadParams.ServiceName = &CapturedDriverServiceName;
02038     LoadParams.DriverObject = NULL;
02039     KeInitializeEvent(&LoadParams.Event, NotificationEvent, FALSE);
02040 
02041     /* Call the load/unload routine, depending on current process */
02042     if (PsGetCurrentProcess() == PsInitialSystemProcess)
02043     {
02044         /* Just call right away */
02045         IopLoadUnloadDriver(&LoadParams);
02046     }
02047     else
02048     {
02049         /* Load/Unload must be called from system process */
02050         ExInitializeWorkItem(&LoadParams.WorkItem,
02051                              (PWORKER_THREAD_ROUTINE)IopLoadUnloadDriver,
02052                              (PVOID)&LoadParams);
02053 
02054         /* Queue it */
02055         ExQueueWorkItem(&LoadParams.WorkItem, DelayedWorkQueue);
02056 
02057         /* And wait when it completes */
02058         KeWaitForSingleObject(&LoadParams.Event, UserRequest, KernelMode,
02059             FALSE, NULL);
02060     }
02061 
02062     ReleaseCapturedUnicodeString(&CapturedDriverServiceName,
02063                                  PreviousMode);
02064 
02065     return LoadParams.Status;
02066 }
02067 
02068 /*
02069  * NtUnloadDriver
02070  *
02071  * Unloads a legacy device driver.
02072  *
02073  * Parameters
02074  *    DriverServiceName
02075  *       Name of the service to unload (registry key).
02076  *
02077  * Return Value
02078  *    Status
02079  *
02080  * Status
02081  *    implemented
02082  */
02083 
02084 NTSTATUS NTAPI
02085 NtUnloadDriver(IN PUNICODE_STRING DriverServiceName)
02086 {
02087    return IopUnloadDriver(DriverServiceName, FALSE);
02088 }
02089 
02090 /* EOF */

Generated on Sat May 26 2012 04:17:43 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.