Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygendevinst.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
1.7.6.1
|