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

devinst.c
Go to the documentation of this file.
00001 /*
00002  * COPYRIGHT:       See COPYING in the top level directory
00003  * PROJECT:         ReactOS text-mode setup
00004  * FILE:            subsys/system/usetup/interface/devinst.c
00005  * PURPOSE:         Device installation
00006  * PROGRAMMER:      Hervé Poussineau (hpoussin@reactos.org)
00007  */
00008 
00009 #include "usetup.h"
00010 
00011 #define NDEBUG
00012 #include <debug.h>
00013 
00014 BOOLEAN
00015 ResetDevice(
00016     IN LPCWSTR DeviceId)
00017 {
00018     PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData;
00019     NTSTATUS Status;
00020 
00021     RtlInitUnicodeString(&ResetDeviceData.DeviceInstance, DeviceId);
00022     Status = NtPlugPlayControl(PlugPlayControlResetDevice, &ResetDeviceData, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA));
00023     if (!NT_SUCCESS(Status))
00024     {
00025         DPRINT1("NtPlugPlayControl() failed with status 0x%08x\n", Status);
00026         return FALSE;
00027     }
00028     return TRUE;
00029 }
00030 
00031 BOOLEAN
00032 InstallDriver(
00033     IN HINF hInf,
00034     IN HANDLE hServices,
00035     IN HANDLE hDeviceKey,
00036     IN LPCWSTR DeviceId,
00037     IN LPCWSTR HardwareId)
00038 {
00039     UNICODE_STRING PathPrefix = RTL_CONSTANT_STRING(L"System32\\DRIVERS\\");
00040     UNICODE_STRING ServiceU = RTL_CONSTANT_STRING(L"Service");
00041     UNICODE_STRING ErrorControlU = RTL_CONSTANT_STRING(L"ErrorControl");
00042     UNICODE_STRING ImagePathU = RTL_CONSTANT_STRING(L"ImagePath");
00043     UNICODE_STRING StartU = RTL_CONSTANT_STRING(L"Start");
00044     UNICODE_STRING TypeU = RTL_CONSTANT_STRING(L"Type");
00045     UNICODE_STRING StringU;
00046     OBJECT_ATTRIBUTES ObjectAttributes;
00047     HANDLE hService;
00048     INFCONTEXT Context;
00049     LPWSTR Driver, ImagePath, FullImagePath;
00050     ULONG dwValue;
00051     ULONG Disposition;
00052     NTSTATUS Status;
00053     BOOLEAN deviceInstalled = FALSE;
00054     UNICODE_STRING UpperFiltersU = RTL_CONSTANT_STRING(L"UpperFilters");
00055     LPWSTR keyboardClass = L"kbdclass\0";
00056     BOOLEAN keyboardDevice = FALSE;
00057 
00058     /* Check if we know the hardware */
00059     if (!SetupFindFirstLineW(hInf, L"HardwareIdsDatabase", HardwareId, &Context))
00060         return FALSE;
00061     if (!INF_GetDataField(&Context, 1, &Driver))
00062         return FALSE;
00063 
00064     /* Find associated driver name */
00065     /* FIXME: check in other sections too! */
00066     if (!SetupFindFirstLineW(hInf, L"BootBusExtenders.Load", Driver, &Context)
00067      && !SetupFindFirstLineW(hInf, L"BusExtenders.Load", Driver, &Context)
00068      && !SetupFindFirstLineW(hInf, L"SCSI.Load", Driver, &Context)
00069      && !SetupFindFirstLineW(hInf, L"InputDevicesSupport.Load", Driver, &Context))
00070     {
00071         if (!SetupFindFirstLineW(hInf, L"Keyboard.Load", Driver, &Context))
00072             return FALSE;
00073 
00074         keyboardDevice = TRUE;
00075     }
00076 
00077     if (!INF_GetDataField(&Context, 1, &ImagePath))
00078         return FALSE;
00079 
00080     /* Prepare full driver path */
00081     dwValue = PathPrefix.MaximumLength + wcslen(ImagePath) * sizeof(WCHAR);
00082     FullImagePath = (LPWSTR)RtlAllocateHeap(ProcessHeap, 0, dwValue);
00083     if (!FullImagePath)
00084     {
00085         DPRINT1("RtlAllocateHeap() failed\n");
00086         return FALSE;
00087     }
00088     RtlCopyMemory(FullImagePath, PathPrefix.Buffer, PathPrefix.MaximumLength);
00089     wcscat(FullImagePath, ImagePath);
00090 
00091     DPRINT1("Using driver '%S' for device '%S'\n", ImagePath, DeviceId);
00092 
00093     /* Create service key */
00094     RtlInitUnicodeString(&StringU, Driver);
00095     InitializeObjectAttributes(&ObjectAttributes, &StringU, 0, hServices, NULL);
00096     Status = NtCreateKey(&hService, KEY_SET_VALUE, &ObjectAttributes, 0, NULL, 0, &Disposition);
00097     if (!NT_SUCCESS(Status))
00098     {
00099         DPRINT1("NtCreateKey('%wZ') failed with status 0x%08x\n", &StringU, Status);
00100         RtlFreeHeap(ProcessHeap, 0, FullImagePath);
00101         return FALSE;
00102     }
00103 
00104     /* Fill service key */
00105     if (Disposition == REG_CREATED_NEW_KEY)
00106     {
00107         dwValue = 0;
00108         NtSetValueKey(
00109             hService,
00110             &ErrorControlU,
00111             0,
00112             REG_DWORD,
00113             &dwValue,
00114             sizeof(dwValue));
00115         dwValue = 0;
00116         NtSetValueKey(
00117             hService,
00118             &StartU,
00119             0,
00120             REG_DWORD,
00121             &dwValue,
00122             sizeof(dwValue));
00123         dwValue = SERVICE_KERNEL_DRIVER;
00124         NtSetValueKey(
00125             hService,
00126             &TypeU,
00127             0,
00128             REG_DWORD,
00129             &dwValue,
00130             sizeof(dwValue));
00131     }
00132     /* HACK: don't put any path in registry */
00133     NtSetValueKey(
00134         hService,
00135         &ImagePathU,
00136         0,
00137         REG_SZ,
00138         ImagePath,
00139         (wcslen(ImagePath) + 1) * sizeof(WCHAR));
00140 
00141     if (keyboardDevice)
00142     {
00143         DPRINT1("Installing keyboard class driver for '%S'\n", DeviceId);
00144         NtSetValueKey(hDeviceKey,
00145                       &UpperFiltersU,
00146                       0,
00147                       REG_MULTI_SZ,
00148                       keyboardClass,
00149                       (wcslen(keyboardClass) + 2) * sizeof(WCHAR));
00150     }
00151 
00152     /* Associate device with the service we just filled */
00153     Status = NtSetValueKey(
00154         hDeviceKey,
00155         &ServiceU,
00156         0,
00157         REG_SZ,
00158         Driver,
00159         (wcslen(Driver) + 1) * sizeof(WCHAR));
00160     if (NT_SUCCESS(Status))
00161     {
00162         /* Restart the device, so it will use the driver we registred */
00163         deviceInstalled = ResetDevice(DeviceId);
00164     }
00165 
00166     /* HACK: Update driver path */
00167     NtSetValueKey(
00168         hService,
00169         &ImagePathU,
00170         0,
00171         REG_SZ,
00172         FullImagePath,
00173         (wcslen(FullImagePath) + 1) * sizeof(WCHAR));
00174     RtlFreeHeap(ProcessHeap, 0, FullImagePath);
00175     NtClose(hService);
00176 
00177     return deviceInstalled;
00178 }
00179 
00180 VOID
00181 InstallDevice(
00182     IN HINF hInf,
00183     IN HANDLE hEnum,
00184     IN HANDLE hServices,
00185     IN LPCWSTR DeviceId)
00186 {
00187     UNICODE_STRING HardwareIDU = RTL_CONSTANT_STRING(L"HardwareID");
00188     UNICODE_STRING CompatibleIDsU = RTL_CONSTANT_STRING(L"CompatibleIDs");
00189     UNICODE_STRING DeviceIdU;
00190     OBJECT_ATTRIBUTES ObjectAttributes;
00191     LPCWSTR HardwareID;
00192     PKEY_VALUE_PARTIAL_INFORMATION pPartialInformation = NULL;
00193     HANDLE hDeviceKey;
00194     ULONG ulRequired;
00195     BOOLEAN bDriverInstalled = FALSE;
00196     NTSTATUS Status;
00197 
00198     RtlInitUnicodeString(&DeviceIdU, DeviceId);
00199     InitializeObjectAttributes(&ObjectAttributes, &DeviceIdU, 0, hEnum, NULL);
00200     Status = NtOpenKey(&hDeviceKey, KEY_QUERY_VALUE | KEY_SET_VALUE, &ObjectAttributes);
00201     if (!NT_SUCCESS(Status))
00202     {
00203         DPRINT("Unable to open subkey '%S'\n", DeviceId);
00204         return;
00205     }
00206 
00207     Status = NtQueryValueKey(
00208         hDeviceKey,
00209         &HardwareIDU,
00210         KeyValuePartialInformation,
00211         NULL,
00212         0,
00213         &ulRequired);
00214     if (Status == STATUS_BUFFER_TOO_SMALL)
00215     {
00216         pPartialInformation = (PKEY_VALUE_PARTIAL_INFORMATION)RtlAllocateHeap(ProcessHeap, 0, ulRequired);
00217         if (!pPartialInformation)
00218         {
00219             DPRINT1("RtlAllocateHeap() failed\n");
00220             NtClose(hDeviceKey);
00221             return;
00222         }
00223         Status = NtQueryValueKey(
00224             hDeviceKey,
00225             &HardwareIDU,
00226             KeyValuePartialInformation,
00227             pPartialInformation,
00228             ulRequired,
00229             &ulRequired);
00230     }
00231     if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
00232     {
00233         /* Nothing to do */
00234     }
00235     else if (!NT_SUCCESS(Status))
00236     {
00237         DPRINT1("NtQueryValueKey() failed with status 0x%08x\n", Status);
00238         if (pPartialInformation)
00239             RtlFreeHeap(ProcessHeap, 0, pPartialInformation);
00240         NtClose(hDeviceKey);
00241         return;
00242     }
00243     else if (pPartialInformation)
00244     {
00245         for (HardwareID = (LPCWSTR)pPartialInformation->Data;
00246              (PUCHAR)HardwareID < pPartialInformation->Data + pPartialInformation->DataLength
00247                  && *HardwareID
00248                  && !bDriverInstalled;
00249             HardwareID += wcslen(HardwareID) + 1)
00250         {
00251             bDriverInstalled = InstallDriver(hInf, hServices,hDeviceKey, DeviceId, HardwareID);
00252         }
00253     }
00254 
00255     if (!bDriverInstalled)
00256     {
00257         if (pPartialInformation)
00258         {
00259             RtlFreeHeap(ProcessHeap, 0, pPartialInformation);
00260             pPartialInformation = NULL;
00261         }
00262         Status = NtQueryValueKey(
00263             hDeviceKey,
00264             &CompatibleIDsU,
00265             KeyValuePartialInformation,
00266             NULL,
00267             0,
00268             &ulRequired);
00269         if (Status == STATUS_BUFFER_TOO_SMALL)
00270         {
00271             pPartialInformation = (PKEY_VALUE_PARTIAL_INFORMATION)RtlAllocateHeap(ProcessHeap, 0, ulRequired);
00272             if (!pPartialInformation)
00273             {
00274                 DPRINT("RtlAllocateHeap() failed\n");
00275                 NtClose(hDeviceKey);
00276                 return;
00277             }
00278             Status = NtQueryValueKey(
00279                 hDeviceKey,
00280                 &CompatibleIDsU,
00281                 KeyValuePartialInformation,
00282                 pPartialInformation,
00283                 ulRequired,
00284                 &ulRequired);
00285         }
00286         if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
00287         {
00288             /* Nothing to do */
00289         }
00290         else if (!NT_SUCCESS(Status))
00291         {
00292             if (pPartialInformation)
00293                 RtlFreeHeap(ProcessHeap, 0, pPartialInformation);
00294             NtClose(hDeviceKey);
00295             DPRINT1("NtQueryValueKey() failed with status 0x%08x\n", Status);
00296             return;
00297         }
00298         else if (pPartialInformation)
00299         {
00300             for (HardwareID = (LPCWSTR)pPartialInformation->Data;
00301                  (PUCHAR)HardwareID < pPartialInformation->Data + pPartialInformation->DataLength
00302                      && *HardwareID
00303                      && !bDriverInstalled;
00304                 HardwareID += wcslen(HardwareID) + 1)
00305             {
00306                 bDriverInstalled = InstallDriver(hInf, hServices,hDeviceKey, DeviceId, HardwareID);
00307             }
00308         }
00309     }
00310     if (!bDriverInstalled)
00311         DPRINT("No driver available for %S\n", DeviceId);
00312 
00313     RtlFreeHeap(ProcessHeap, 0, pPartialInformation);
00314     NtClose(hDeviceKey);
00315 }
00316 
00317 NTSTATUS
00318 EventThread(IN LPVOID lpParameter)
00319 {
00320     UNICODE_STRING EnumU = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Enum");
00321     UNICODE_STRING ServicesU = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services");
00322     PPLUGPLAY_EVENT_BLOCK PnpEvent;
00323     OBJECT_ATTRIBUTES ObjectAttributes;
00324     ULONG PnpEventSize;
00325     HINF hInf;
00326     HANDLE hEnum, hServices;
00327     NTSTATUS Status;
00328 
00329     hInf = *(HINF *)lpParameter;
00330 
00331     InitializeObjectAttributes(&ObjectAttributes, &EnumU, OBJ_CASE_INSENSITIVE, NULL, NULL);
00332     Status = NtOpenKey(&hEnum, KEY_QUERY_VALUE, &ObjectAttributes);
00333     if (!NT_SUCCESS(Status))
00334     {
00335         DPRINT1("NtOpenKey('%wZ') failed with status 0x%08lx\n", &EnumU, Status);
00336         return Status;
00337     }
00338 
00339     InitializeObjectAttributes(&ObjectAttributes, &ServicesU, OBJ_CASE_INSENSITIVE, NULL, NULL);
00340     Status = NtCreateKey(&hServices, 0, &ObjectAttributes, 0, NULL, 0, NULL);
00341     if (!NT_SUCCESS(Status))
00342     {
00343         DPRINT1("NtCreateKey('%wZ') failed with status 0x%08lx\n", &ServicesU, Status);
00344         NtClose(hEnum);
00345         return Status;
00346     }
00347 
00348     PnpEventSize = 0x1000;
00349     PnpEvent = (PPLUGPLAY_EVENT_BLOCK)RtlAllocateHeap(ProcessHeap, 0, PnpEventSize);
00350     if (PnpEvent == NULL)
00351     {
00352         NtClose(hEnum);
00353         NtClose(hServices);
00354         return STATUS_NO_MEMORY;
00355     }
00356 
00357     for (;;)
00358     {
00359         DPRINT("Calling NtGetPlugPlayEvent()\n");
00360 
00361         /* Wait for the next pnp event */
00362         Status = NtGetPlugPlayEvent(0, 0, PnpEvent, PnpEventSize);
00363 
00364         /* Resize the buffer for the PnP event if it's too small. */
00365         if (Status == STATUS_BUFFER_TOO_SMALL)
00366         {
00367             PnpEventSize += 0x400;
00368             RtlFreeHeap(ProcessHeap, 0, PnpEvent);
00369             PnpEvent = (PPLUGPLAY_EVENT_BLOCK)RtlAllocateHeap(ProcessHeap, 0, PnpEventSize);
00370             if (PnpEvent == NULL)
00371             {
00372                 NtClose(hEnum);
00373                 NtClose(hServices);
00374                 return STATUS_NO_MEMORY;
00375             }
00376             continue;
00377         }
00378 
00379         if (!NT_SUCCESS(Status))
00380         {
00381             DPRINT("NtPlugPlayEvent() failed (Status %lx)\n", Status);
00382             break;
00383         }
00384 
00385         /* Process the pnp event */
00386         DPRINT("Received PnP Event\n");
00387         if (IsEqualIID(&PnpEvent->EventGuid, (REFGUID)&GUID_DEVICE_ENUMERATED))
00388         {
00389             DPRINT("Device arrival event: %S\n", PnpEvent->TargetDevice.DeviceIds);
00390             InstallDevice(hInf, hEnum, hServices, PnpEvent->TargetDevice.DeviceIds);
00391         }
00392         else
00393         {
00394             DPRINT("Unknown event\n");
00395         }
00396 
00397         /* Dequeue the current pnp event and signal the next one */
00398         NtPlugPlayControl(PlugPlayControlUserResponse, NULL, 0);
00399     }
00400 
00401     RtlFreeHeap(ProcessHeap, 0, PnpEvent);
00402     NtClose(hEnum);
00403     NtClose(hServices);
00404 
00405     return STATUS_SUCCESS;
00406 }
00407 
00408 DWORD WINAPI
00409 PnpEventThread(IN LPVOID lpParameter)
00410 {
00411     NTSTATUS Status;
00412     Status = EventThread(lpParameter);
00413     NtTerminateThread(NtCurrentThread(), Status);
00414     return 0;
00415 }

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