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

swenum.c
Go to the documentation of this file.
00001 /*
00002  * COPYRIGHT:       See COPYING in the top level directory
00003  * PROJECT:         ReactOS Kernel Streaming
00004  * FILE:            drivers/ksfilter/ks/swenum.c
00005  * PURPOSE:         KS Software BUS functions
00006  * PROGRAMMER:      Johannes Anderwald
00007  */
00008 
00009 
00010 #include "priv.h"
00011 
00012 LONG KsDeviceCount = 0;
00013 
00014 typedef NTSTATUS (NTAPI *PKSP_BUS_ENUM_CALLBACK)(
00015     IN PHANDLE hKey,
00016     IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension,
00017     IN PBUS_DEVICE_ENTRY DummyEntry,
00018     IN LPWSTR RootName,
00019     IN LPWSTR DirectoryName);
00020 
00021 NTSTATUS
00022 KspCreatePDO(
00023     IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension,
00024     IN PBUS_DEVICE_ENTRY DeviceEntry,
00025     OUT PDEVICE_OBJECT * OutDeviceObject)
00026 {
00027     PDEVICE_OBJECT DeviceObject;
00028     WCHAR Buffer[50];
00029     ULONG CurDeviceId;
00030     UNICODE_STRING DeviceName;
00031     NTSTATUS Status;
00032     PCOMMON_DEVICE_EXTENSION DeviceExtension;
00033 
00034     /* increment device count */
00035     CurDeviceId = InterlockedIncrement(&KsDeviceCount);
00036 
00037     /* generate new device id */
00038     swprintf(Buffer, L"\\Device\\KSENUM%08x", CurDeviceId);
00039 
00040     /* initialize new device name */
00041     RtlInitUnicodeString(&DeviceName, Buffer);
00042 
00043     /* create new device object */
00044     Status = IoCreateDevice(BusDeviceExtension->BusDeviceObject->DriverObject, sizeof(PVOID), &DeviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, &DeviceObject);
00045 
00046     /* check for success */
00047     if (!NT_SUCCESS(Status))
00048     {
00049         /* failed to create pdo */
00050         return Status;
00051     }
00052 
00053     /* now allocate device extension */
00054     DeviceExtension = (PCOMMON_DEVICE_EXTENSION)AllocateItem(NonPagedPool, sizeof(COMMON_DEVICE_EXTENSION));
00055     if (!DeviceExtension)
00056     {
00057         /* no memory */
00058         IoDeleteDevice(DeviceObject);
00059         return STATUS_INSUFFICIENT_RESOURCES;
00060     }
00061 
00062     /* store device extension */
00063     *((PVOID*)DeviceObject->DeviceExtension) = DeviceExtension;
00064 
00065     /* initialize device extension */
00066     DeviceExtension->IsBus = FALSE;
00067     DeviceExtension->DeviceObject = DeviceObject;
00068     DeviceExtension->DeviceEntry = DeviceEntry;
00069     DeviceExtension->BusDeviceExtension = BusDeviceExtension;
00070 
00071     /* TODO: update last creation time in bus device extension */
00072 
00073     /* setup flags */
00074     DeviceObject->Flags |= DO_POWER_PAGABLE;
00075     DeviceObject->Flags &= ~ DO_DEVICE_INITIALIZING;
00076     /* TODO: fire time when expired */
00077 
00078     *OutDeviceObject = DeviceObject;
00079 
00080     return STATUS_SUCCESS;
00081 }
00082 
00083 NTSTATUS
00084 KspRegisterDeviceAssociation(
00085     IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension,
00086     IN PBUS_DEVICE_ENTRY DeviceEntry,
00087     IN OUT PBUS_INSTANCE_ENTRY BusInstanceEntry)
00088 {
00089     NTSTATUS Status;
00090     UNICODE_STRING ReferenceString;
00091 
00092     /* initialize reference string */
00093     RtlInitUnicodeString(&ReferenceString, DeviceEntry->DeviceName);
00094 
00095     /* register device interface */
00096     Status = IoRegisterDeviceInterface(BusDeviceExtension->PhysicalDeviceObject, &BusInstanceEntry->InterfaceGuid, &ReferenceString, &BusInstanceEntry->SymbolicLink);
00097 
00098     /* check for success */
00099     if (!NT_SUCCESS(Status))
00100     {
00101         /* failed */
00102         return Status;
00103     }
00104 
00105     /* now enable the interface */
00106     Status = IoSetDeviceInterfaceState(&BusInstanceEntry->SymbolicLink, TRUE);
00107 
00108     /* check for success */
00109     if (!NT_SUCCESS(Status))
00110     {
00111         /* failed, free memory */
00112         FreeItem(BusInstanceEntry->SymbolicLink.Buffer);
00113         return Status;
00114     }
00115 
00116     DPRINT1("Registered DeviceInterface %wZ\n", &BusInstanceEntry->SymbolicLink);
00117 
00118 
00119     /* done */
00120     return Status;
00121 }
00122 
00123 VOID
00124 KspRemoveDeviceAssociations(
00125     IN PBUS_DEVICE_ENTRY DeviceEntry)
00126 {
00127     PLIST_ENTRY Entry;
00128     PBUS_INSTANCE_ENTRY CurEntry;
00129 
00130     /* remove all entries */
00131     Entry = DeviceEntry->DeviceInterfaceList.Flink;
00132 
00133     while(Entry != &DeviceEntry->DeviceInterfaceList)
00134     {
00135          /* get offset */
00136          CurEntry = (PBUS_INSTANCE_ENTRY)CONTAINING_RECORD(Entry, BUS_INSTANCE_ENTRY, Entry);
00137 
00138          /* sanity check */
00139          ASSERT(CurEntry->SymbolicLink.Buffer);
00140 
00141          /* de-register interface */
00142          IoSetDeviceInterfaceState(&CurEntry->SymbolicLink, FALSE);
00143 
00144          /* free symbolic link buffer */
00145          FreeItem(CurEntry->SymbolicLink.Buffer);
00146 
00147          /* remove entry from list */
00148          RemoveEntryList(Entry);
00149 
00150          /* move to next entry */
00151          Entry = Entry->Flink;
00152 
00153          /* free entry */
00154          FreeItem(CurEntry);
00155     }
00156 }
00157 
00158 NTSTATUS
00159 KspEnumerateBusRegistryKeys(
00160     IN HANDLE hKey,
00161     IN LPWSTR ReferenceString,
00162     IN PKSP_BUS_ENUM_CALLBACK Callback,
00163     IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension,
00164     IN PBUS_DEVICE_ENTRY DeviceEntry)
00165 {
00166     UNICODE_STRING String;
00167     OBJECT_ATTRIBUTES ObjectAttributes;
00168     HANDLE hNewKey;
00169     NTSTATUS Status;
00170     ULONG ResultLength, Index, KeyInfoLength;
00171     KEY_FULL_INFORMATION KeyInformation;
00172     PKEY_BASIC_INFORMATION KeyInfo;
00173 
00174     /* initialize key name */
00175     RtlInitUnicodeString(&String, ReferenceString);
00176 
00177     /* initialize object attributes */
00178     InitializeObjectAttributes(&ObjectAttributes, &String, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, hKey, NULL);
00179 
00180     /* open new key */
00181     Status = ZwOpenKey(&hNewKey, GENERIC_READ, &ObjectAttributes);
00182 
00183     /* check for success */
00184     if (!NT_SUCCESS(Status))
00185     {
00186         /* failed to open key */
00187 
00188         return Status;
00189     }
00190 
00191     /* query key stats */
00192     Status = ZwQueryKey(hNewKey, KeyFullInformation, &KeyInformation, sizeof(KeyInformation), &ResultLength);
00193 
00194     if (!NT_SUCCESS(Status))
00195     {
00196         /* close key */
00197         ZwClose(hNewKey);
00198 
00199         /* done */
00200         return Status;
00201     }
00202 
00203     /* calculate key info length */
00204     KeyInfoLength = KeyInformation.MaxNameLen + sizeof(KEY_BASIC_INFORMATION) + 1 * sizeof(WCHAR);
00205 
00206     /* allocate buffer */
00207     KeyInfo = (PKEY_BASIC_INFORMATION)AllocateItem(NonPagedPool, KeyInfoLength);
00208     if (!KeyInfo)
00209     {
00210 
00211         /* no memory */
00212         ZwClose(hNewKey);
00213 
00214         /* done */
00215         return STATUS_INSUFFICIENT_RESOURCES;
00216     }
00217 
00218     /* enumerate all keys */
00219     for(Index = 0; Index < KeyInformation.SubKeys; Index++)
00220     {
00221 
00222         /* query sub key */
00223         Status = ZwEnumerateKey(hNewKey, Index, KeyBasicInformation, (PVOID)KeyInfo, KeyInfoLength, &ResultLength);
00224 
00225         /* check for success */
00226         if (NT_SUCCESS(Status))
00227         {
00228             /* perform callback */
00229             Status = Callback(hNewKey, BusDeviceExtension, DeviceEntry, ReferenceString, KeyInfo->Name);
00230 
00231             /* should enumeration stop */
00232             if (!NT_SUCCESS(Status))
00233                 break;
00234         }
00235     }
00236 
00237     /* free info buffer */
00238     FreeItem(KeyInfo);
00239 
00240     /* close key */
00241     ZwClose(hNewKey);
00242 
00243     /* done */
00244     return Status;
00245 }
00246 
00247 NTSTATUS
00248 NTAPI
00249 KspCreateDeviceAssociation(
00250     IN PHANDLE hKey,
00251     IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension,
00252     IN PBUS_DEVICE_ENTRY DeviceEntry,
00253     IN LPWSTR ReferenceString,
00254     IN LPWSTR InterfaceString)
00255 {
00256     GUID DeviceGuid;
00257     NTSTATUS Status;
00258     PLIST_ENTRY Entry;
00259     PBUS_INSTANCE_ENTRY CurEntry;
00260     UNICODE_STRING DeviceName;
00261 
00262     /* initialize interface string */
00263     RtlInitUnicodeString(&DeviceName, InterfaceString);
00264 
00265     /* first convert device name to guid */
00266     RtlGUIDFromString(&DeviceName, &DeviceGuid);
00267 
00268     /* check if the device is already present */
00269     Entry = DeviceEntry->DeviceInterfaceList.Flink;
00270 
00271     while(Entry != &DeviceEntry->DeviceInterfaceList)
00272     {
00273          /* get offset */
00274          CurEntry = (PBUS_INSTANCE_ENTRY)CONTAINING_RECORD(Entry, BUS_INSTANCE_ENTRY, Entry);
00275 
00276          if (IsEqualGUIDAligned(&CurEntry->InterfaceGuid, &DeviceGuid))
00277          {
00278              /* entry already exists */
00279              return STATUS_SUCCESS;
00280          }
00281 
00282          /* move to next entry */
00283          Entry = Entry->Flink;
00284     }
00285 
00286     /* time to allocate new entry */
00287     CurEntry = (PBUS_INSTANCE_ENTRY)AllocateItem(NonPagedPool, sizeof(BUS_INSTANCE_ENTRY));
00288 
00289     if (!CurEntry)
00290     {
00291         /* no memory */
00292         return STATUS_INSUFFICIENT_RESOURCES;
00293     }
00294 
00295     /* store guid */
00296     RtlMoveMemory(&CurEntry->InterfaceGuid, &DeviceGuid, sizeof(GUID));
00297 
00298     /* now register the association */
00299     Status = KspRegisterDeviceAssociation(BusDeviceExtension, DeviceEntry, CurEntry);
00300 
00301     /* check for success */
00302     if (NT_SUCCESS(Status))
00303     {
00304         /* store entry */
00305         InsertTailList(&DeviceEntry->DeviceInterfaceList, &CurEntry->Entry);
00306     }
00307     else
00308     {
00309         /* failed to associated device */
00310         FreeItem(CurEntry);
00311     }
00312 
00313      /* done */
00314      return Status;
00315 }
00316 
00317 NTSTATUS
00318 NTAPI
00319 KspCreateDeviceReference(
00320     IN PHANDLE hKey,
00321     IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension,
00322     IN PBUS_DEVICE_ENTRY DummyEntry,
00323     IN LPWSTR DeviceCategory,
00324     IN LPWSTR ReferenceString)
00325 {
00326     LPWSTR DeviceName;
00327     ULONG Length;
00328     PLIST_ENTRY Entry;
00329     PBUS_DEVICE_ENTRY DeviceEntry = NULL; /* GCC warning */
00330     BOOLEAN ItemExists = FALSE;
00331     UNICODE_STRING String;
00332     NTSTATUS Status;
00333     KIRQL OldLevel;
00334 
00335     /* first construct device name & reference guid */
00336     Length = wcslen(DeviceCategory) + wcslen(ReferenceString);
00337 
00338     /* append '&' and null byte */
00339     Length += 2;
00340 
00341     /* allocate device name */
00342     DeviceName = AllocateItem(NonPagedPool, Length * sizeof(WCHAR));
00343 
00344     if (!DeviceName)
00345     {
00346         /* not enough memory */
00347         return STATUS_INSUFFICIENT_RESOURCES;
00348     }
00349 
00350     /* construct device name */
00351     swprintf(DeviceName, L"%s&%s", DeviceCategory, ReferenceString);
00352 
00353     /* scan list and check if it is already present */
00354     Entry = BusDeviceExtension->Common.Entry.Flink;
00355 
00356     while(Entry != &BusDeviceExtension->Common.Entry)
00357     {
00358         /* get real offset */
00359         DeviceEntry = (PBUS_DEVICE_ENTRY)CONTAINING_RECORD(Entry, BUS_DEVICE_ENTRY, Entry);
00360 
00361         /* check if name matches */
00362         if (!wcsicmp(DeviceEntry->DeviceName, DeviceName))
00363         {
00364             /* item already exists */
00365             ItemExists = TRUE;
00366             break;
00367         }
00368 
00369         /* move to next entry */
00370         Entry = Entry->Flink;
00371     }
00372 
00373     if (!ItemExists)
00374     {
00375         /* allocate new device entry */
00376         DeviceEntry = AllocateItem(NonPagedPool, sizeof(BUS_DEVICE_ENTRY));
00377         if (!DeviceEntry)
00378         {
00379             /* no memory */
00380             FreeItem(DeviceName);
00381             return STATUS_INSUFFICIENT_RESOURCES;
00382         }
00383 
00384         /* initialize device entry */
00385         InitializeListHead(&DeviceEntry->DeviceInterfaceList);
00386         InitializeListHead(&DeviceEntry->IrpPendingList);
00387 
00388         /* copy device guid */
00389         RtlInitUnicodeString(&String, ReferenceString);
00390         RtlGUIDFromString(&String, &DeviceEntry->DeviceGuid);
00391 
00392         /* copy device names */
00393         DeviceEntry->DeviceName = DeviceName;
00394         DeviceEntry->Instance = (DeviceName + wcslen(DeviceCategory) + 1);
00395 
00396         /* copy name */
00397         DeviceEntry->BusId = AllocateItem(NonPagedPool, (wcslen(DeviceCategory) + 1) * sizeof(WCHAR));
00398         if (!DeviceEntry->BusId)
00399         {
00400             /* no memory */
00401             FreeItem(DeviceName);
00402             FreeItem(DeviceEntry);
00403             return STATUS_INSUFFICIENT_RESOURCES;
00404         }
00405         wcscpy(DeviceEntry->BusId, DeviceCategory);
00406     }
00407 
00408     /* now enumerate the devices */
00409     Status = KspEnumerateBusRegistryKeys(hKey, ReferenceString, KspCreateDeviceAssociation, BusDeviceExtension, DeviceEntry);
00410 
00411     /* check if list is empty */
00412     if (IsListEmpty(&DeviceEntry->DeviceInterfaceList))
00413     {
00414         /* invalid device settings */
00415         FreeItem(DeviceEntry->BusId);
00416         FreeItem(DeviceEntry->DeviceName);
00417         FreeItem(DeviceEntry);
00418 
00419         ASSERT(ItemExists == FALSE);
00420 
00421         return STATUS_INVALID_DEVICE_STATE;
00422     }
00423 
00424     /* check if enumeration failed */
00425     if (!NT_SUCCESS(Status))
00426     {
00427         /* failed */
00428         KspRemoveDeviceAssociations(DeviceEntry);
00429         FreeItem(DeviceEntry->BusId);
00430         FreeItem(DeviceEntry->DeviceName);
00431         FreeItem(DeviceEntry);
00432 
00433         ASSERT(ItemExists == FALSE);
00434 
00435         /* done */
00436         return Status;
00437     }
00438 
00439     if (!ItemExists)
00440     {
00441         /* acquire lock */
00442         KeAcquireSpinLock(&BusDeviceExtension->Lock, &OldLevel);
00443 
00444         /* successfully initialized entry */
00445         InsertTailList(&BusDeviceExtension->Common.Entry, &DeviceEntry->Entry);
00446 
00447         /* release lock */
00448         KeReleaseSpinLock(&BusDeviceExtension->Lock, OldLevel);
00449     }
00450 
00451     /* done */
00452     return Status;
00453 }
00454 
00455 NTSTATUS
00456 NTAPI
00457 KspCreateDeviceReferenceTrampoline(
00458     IN PHANDLE hKey,
00459     IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension,
00460     IN PBUS_DEVICE_ENTRY DummyEntry,
00461     IN LPWSTR DeviceCategory,
00462     IN LPWSTR ReferenceString)
00463 {
00464     return KspEnumerateBusRegistryKeys(hKey, ReferenceString, KspCreateDeviceReference, BusDeviceExtension, DummyEntry);
00465 }
00466 
00467 
00468 NTSTATUS
00469 KspOpenBusRegistryKey(
00470     IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension,
00471     OUT PHANDLE hKey)
00472 {
00473     OBJECT_ATTRIBUTES ObjectAttributes;
00474 
00475     /* initialize object attributes */
00476     InitializeObjectAttributes(&ObjectAttributes, &BusDeviceExtension->ServicePath, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);
00477 
00478     return ZwCreateKey(hKey, GENERIC_READ | GENERIC_WRITE, &ObjectAttributes, 0, NULL, 0, NULL);
00479 }
00480 
00481 NTSTATUS
00482 KspScanBus(
00483     IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension)
00484 {
00485     HANDLE hKey;
00486     NTSTATUS Status;
00487 
00488     /* first open key */
00489     Status = KspOpenBusRegistryKey(BusDeviceExtension, &hKey);
00490 
00491     /* check for success */
00492     if (!NT_SUCCESS(Status))
00493     {
00494         /* no success */
00495 
00496         return Status;
00497     }
00498 
00499     /* TODO clear reference marks */
00500 
00501     /* construct device entries */
00502     Status = KspEnumerateBusRegistryKeys(hKey, NULL, KspCreateDeviceReferenceTrampoline, BusDeviceExtension, NULL);
00503 
00504     /* TODO: delete unreferenced devices */
00505 
00506     /* close handle */
00507     ZwClose(hKey);
00508 
00509     /* done */
00510     return Status;
00511 }
00512 
00513 
00514 NTSTATUS
00515 NTAPI
00516 KspBusQueryReferenceString(
00517     IN PVOID Context,
00518     IN OUT PWCHAR *String)
00519 {
00520     LPWSTR Name;
00521     ULONG Length;
00522     PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION)Context;
00523 
00524     /* sanity checks */
00525     ASSERT(BusDeviceExtension);
00526     ASSERT(BusDeviceExtension->BusIdentifier);
00527 
00528     /* calculate length */
00529     Length = wcslen(BusDeviceExtension->BusIdentifier) + 1;
00530 
00531     /* allocate buffer */
00532     Name = AllocateItem(PagedPool, Length * sizeof(WCHAR));
00533 
00534     if (!Name)
00535     {
00536         /* failed to allocate buffer */
00537         return STATUS_INSUFFICIENT_RESOURCES;
00538     }
00539 
00540     /* copy buffer */
00541     wcscpy(Name, BusDeviceExtension->BusIdentifier);
00542 
00543     /* store result */
00544     *String = Name;
00545 
00546     /* done */
00547     return STATUS_SUCCESS;
00548 }
00549 
00550 VOID
00551 NTAPI
00552 KspBusDeviceReference(
00553     IN PVOID Context)
00554 {
00555     PCOMMON_DEVICE_EXTENSION ChildDeviceExtension = (PCOMMON_DEVICE_EXTENSION)Context;
00556 
00557     /* reference count */
00558     InterlockedIncrement((PLONG)&ChildDeviceExtension->DeviceReferenceCount);
00559 }
00560 
00561 VOID
00562 NTAPI
00563 KspBusDeviceDereference(
00564     IN PVOID Context)
00565 {
00566     PCOMMON_DEVICE_EXTENSION ChildDeviceExtension = (PCOMMON_DEVICE_EXTENSION)Context;
00567 
00568     /* reference count */
00569     InterlockedDecrement((PLONG)&ChildDeviceExtension->DeviceReferenceCount);
00570 }
00571 
00572 VOID
00573 NTAPI
00574 KspBusReferenceDeviceObject(
00575     IN PVOID Context)
00576 {
00577     PCOMMON_DEVICE_EXTENSION ChildDeviceExtension = (PCOMMON_DEVICE_EXTENSION)Context;
00578 
00579     /* reference count */
00580     InterlockedIncrement((PLONG)&ChildDeviceExtension->DeviceObjectReferenceCount);
00581 }
00582 
00583 VOID
00584 NTAPI
00585 KspBusDereferenceDeviceObject(
00586     IN PVOID Context)
00587 {
00588     PCOMMON_DEVICE_EXTENSION ChildDeviceExtension = (PCOMMON_DEVICE_EXTENSION)Context;
00589 
00590     /* reference count */
00591     InterlockedDecrement((PLONG)&ChildDeviceExtension->DeviceObjectReferenceCount);
00592 }
00593 
00594 NTSTATUS
00595 KspQueryBusDeviceInterface(
00596     IN PCOMMON_DEVICE_EXTENSION ChildDeviceExtension,
00597     IN PIRP Irp)
00598 {
00599     PBUS_INTERFACE_SWENUM Interface;
00600     PIO_STACK_LOCATION IoStack;
00601 
00602     /* get current irp stack location */
00603     IoStack = IoGetCurrentIrpStackLocation(Irp);
00604 
00605     /* sanity checks */
00606     ASSERT(IoStack->Parameters.QueryInterface.Size == sizeof(BUS_INTERFACE_SWENUM));
00607     ASSERT(IoStack->Parameters.QueryInterface.Interface);
00608 
00609     /* fill in interface */
00610     Interface = (PBUS_INTERFACE_SWENUM)IoStack->Parameters.QueryInterface.Interface;
00611     Interface->Interface.Size = sizeof(BUS_INTERFACE_SWENUM);
00612     Interface->Interface.Version = BUS_INTERFACE_SWENUM_VERSION;
00613     Interface->Interface.Context = ChildDeviceExtension;
00614     Interface->Interface.InterfaceReference = KspBusDeviceReference;
00615     Interface->Interface.InterfaceDereference = KspBusDeviceDereference;
00616     Interface->ReferenceDeviceObject = KspBusReferenceDeviceObject;
00617     Interface->DereferenceDeviceObject = KspBusDereferenceDeviceObject;
00618     Interface->QueryReferenceString = KspBusQueryReferenceString;
00619 
00620     return STATUS_SUCCESS;
00621 }
00622 
00623 NTSTATUS
00624 KspEnableBusDeviceInterface(
00625     PBUS_DEVICE_ENTRY DeviceEntry,
00626     BOOLEAN bEnable)
00627 {
00628     PLIST_ENTRY Entry;
00629     PBUS_INSTANCE_ENTRY InstanceEntry;
00630     NTSTATUS Status = STATUS_SUCCESS;
00631 
00632     /* enable now all interfaces */
00633     Entry = DeviceEntry->DeviceInterfaceList.Flink;
00634 
00635     while(Entry != &DeviceEntry->DeviceInterfaceList)
00636     {
00637         /* get bus instance entry */
00638         InstanceEntry = (PBUS_INSTANCE_ENTRY)CONTAINING_RECORD(Entry, BUS_INSTANCE_ENTRY, Entry);
00639         DPRINT1("Enabling %u %wZ Irql %u\n", bEnable, &InstanceEntry->SymbolicLink, KeGetCurrentIrql());
00640 
00641         /* set interface state */
00642         Status = IoSetDeviceInterfaceState(&InstanceEntry->SymbolicLink, bEnable);
00643 
00644         if (!NT_SUCCESS(Status))
00645         {
00646             /* failed to set interface */
00647             break;
00648         }
00649 
00650         /* move to next entry */
00651         Entry = Entry->Flink;
00652     }
00653 
00654     /* done */
00655     return Status;
00656 }
00657 
00658 NTSTATUS
00659 KspDoReparseForIrp(
00660     PIRP Irp,
00661     PBUS_DEVICE_ENTRY DeviceEntry)
00662 {
00663     ULONG Length;
00664     LPWSTR Buffer;
00665     PIO_STACK_LOCATION IoStack;
00666 
00667     /* get stack location */
00668     IoStack = IoGetCurrentIrpStackLocation(Irp);
00669 
00670     /* sanity checks */
00671     ASSERT(DeviceEntry->PDODeviceName);
00672     ASSERT(DeviceEntry->Instance);
00673     ASSERT(IoStack->FileObject);
00674     ASSERT(IoStack->FileObject->FileName.Buffer);
00675 
00676     /* calculate length */
00677     Length = wcslen(DeviceEntry->PDODeviceName);
00678     Length += wcslen(DeviceEntry->Instance);
00679 
00680     /* zero byte and '\\' */
00681     Length += 2; 
00682 
00683     /* allocate buffer */
00684     Buffer = AllocateItem(NonPagedPool, Length * sizeof(WCHAR));
00685     if (!Buffer)
00686     {
00687         /* no resources */
00688         return STATUS_INSUFFICIENT_RESOURCES;
00689     }
00690 
00691     /* construct buffer */
00692     swprintf(Buffer, L"%s\\%s", DeviceEntry->PDODeviceName, DeviceEntry->Instance);
00693 
00694     ExFreePool(IoStack->FileObject->FileName.Buffer);
00695 
00696     /* store new file name */
00697     RtlInitUnicodeString(&IoStack->FileObject->FileName, Buffer);
00698 
00699     /* done */
00700     return STATUS_REPARSE;
00701 }
00702 
00703 VOID
00704 KspCompletePendingIrps(
00705     IN PBUS_DEVICE_ENTRY DeviceEntry,
00706     IN OUT NTSTATUS ResultCode)
00707 {
00708     PLIST_ENTRY Entry;
00709     PIRP Irp;
00710     NTSTATUS Status;
00711 
00712     /* go through list */
00713     while(!IsListEmpty(&DeviceEntry->IrpPendingList))
00714     {
00715         /* get first entry */
00716         Entry = RemoveHeadList(&DeviceEntry->IrpPendingList);
00717 
00718         /* get irp */
00719         Irp = (PIRP)CONTAINING_RECORD(Entry, IRP, Tail.Overlay.ListEntry);
00720 
00721         if (ResultCode == STATUS_REPARSE)
00722         {
00723             /* construct reparse information */
00724             Status = KspDoReparseForIrp(Irp, DeviceEntry);
00725         }
00726         else
00727         {
00728             /* use default code */
00729             Status = ResultCode;
00730         }
00731 
00732         /* store result code */
00733         Irp->IoStatus.Status = Status;
00734 
00735         DPRINT1("Completing IRP %p Status %x\n", Irp, Status);
00736 
00737         /* complete the request */
00738         CompleteRequest(Irp, IO_NO_INCREMENT);
00739     }
00740 
00741 }
00742 
00743 
00744 
00745 NTSTATUS
00746 KspStartBusDevice(
00747     IN PDEVICE_OBJECT DeviceObject,
00748     IN PCOMMON_DEVICE_EXTENSION ChildDeviceExtension,
00749     IN PIRP Irp)
00750 {
00751     WCHAR PDOName[256];
00752     NTSTATUS Status;
00753     ULONG ResultLength;
00754     LPWSTR Name;
00755     PBUS_DEVICE_ENTRY DeviceEntry;
00756 
00757     /* FIXME handle pending remove */
00758 
00759     /* get full device name */
00760     Status = IoGetDeviceProperty(DeviceObject, DevicePropertyPhysicalDeviceObjectName, sizeof(PDOName), (PVOID)PDOName, &ResultLength);
00761 
00762     if (!NT_SUCCESS(Status))
00763     {
00764         /* failed to get device name */
00765         return Status;
00766     }
00767 
00768     /* allocate device name buffer */
00769     Name = AllocateItem(NonPagedPool, (ResultLength + 1) * sizeof(WCHAR));
00770     if (!Name)
00771     {
00772         /* no memory */
00773         return STATUS_INSUFFICIENT_RESOURCES;
00774     }
00775 
00776     /* copy name */
00777     wcscpy(Name, PDOName);
00778 
00779     /* TODO: time stamp creation time */
00780 
00781     /* get device entry */
00782     DeviceEntry = (PBUS_DEVICE_ENTRY)ChildDeviceExtension->DeviceEntry;
00783 
00784     /* sanity check */
00785     ASSERT(DeviceEntry);
00786 
00787     /* store device name */
00788     DeviceEntry->PDODeviceName = Name;
00789 
00790     /* mark device as started */
00791     DeviceEntry->DeviceState = Started;
00792 
00793     /* reference start time */
00794     KeQuerySystemTime(&DeviceEntry->TimeCreated);
00795 
00796     DPRINT1("KspStartBusDevice Name %S DeviceName %S Instance %S Started\n", Name, DeviceEntry->DeviceName, DeviceEntry->Instance);
00797 
00798     /* enable device classes */
00799     //KspEnableBusDeviceInterface(DeviceEntry, TRUE);
00800 
00801     /* done */
00802     return STATUS_SUCCESS;
00803 }
00804 
00805 NTSTATUS
00806 KspQueryBusDeviceCapabilities(
00807     IN PCOMMON_DEVICE_EXTENSION ChildDeviceExtension,
00808     IN PIRP Irp)
00809 {
00810     PDEVICE_CAPABILITIES Capabilities;
00811     PIO_STACK_LOCATION IoStack;
00812 
00813     /* get stack location */
00814     IoStack = IoGetCurrentIrpStackLocation(Irp);
00815 
00816     /* get capabilities */
00817     Capabilities = IoStack->Parameters.DeviceCapabilities.Capabilities;
00818 
00819     RtlZeroMemory(Capabilities, sizeof(DEVICE_CAPABILITIES));
00820 
00821     /* setup capabilities */
00822     Capabilities->UniqueID = TRUE;
00823     Capabilities->SilentInstall = TRUE;
00824     Capabilities->SurpriseRemovalOK = TRUE;
00825     Capabilities->Address = 0;
00826     Capabilities->UINumber = 0;
00827     Capabilities->SystemWake = PowerSystemWorking; /* FIXME common device extension */
00828     Capabilities->DeviceWake = PowerDeviceD0;
00829 
00830     /* done */
00831     return STATUS_SUCCESS;
00832 }
00833 
00834 NTSTATUS
00835 KspQueryBusInformation(
00836     IN PCOMMON_DEVICE_EXTENSION ChildDeviceExtension,
00837     IN PIRP Irp)
00838 {
00839     PPNP_BUS_INFORMATION BusInformation;
00840 
00841     /* allocate bus information */
00842     BusInformation = (PPNP_BUS_INFORMATION)AllocateItem(PagedPool, sizeof(PNP_BUS_INFORMATION));
00843 
00844     if (!BusInformation)
00845     {
00846         /* no memory */
00847         return STATUS_INSUFFICIENT_RESOURCES;
00848     }
00849 
00850     /* return info */
00851     BusInformation->BusNumber = 0;
00852     BusInformation->LegacyBusType = InterfaceTypeUndefined;
00853     RtlMoveMemory(&BusInformation->BusTypeGuid, &KSMEDIUMSETID_Standard, sizeof(GUID));
00854 
00855     /* store result */
00856     Irp->IoStatus.Information = (ULONG_PTR)BusInformation;
00857 
00858     /* done */
00859     return STATUS_SUCCESS;
00860 }
00861 
00862 NTSTATUS
00863 KspQueryBusDevicePnpState(
00864     IN PCOMMON_DEVICE_EXTENSION ChildDeviceExtension,
00865     IN PIRP Irp)
00866 {
00867     /* set device flags */
00868     Irp->IoStatus.Information = PNP_DEVICE_DONT_DISPLAY_IN_UI | PNP_DEVICE_NOT_DISABLEABLE;
00869 
00870     /* done */
00871     return STATUS_SUCCESS;
00872 }
00873 
00874 NTSTATUS
00875 KspQueryId(
00876     IN PCOMMON_DEVICE_EXTENSION ChildDeviceExtension,
00877     IN PIRP Irp)
00878 {
00879     PIO_STACK_LOCATION IoStack;
00880     PBUS_DEVICE_ENTRY DeviceEntry;
00881     PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension;
00882     LPWSTR Name;
00883     ULONG Length;
00884 
00885     /* get current irp stack location */
00886     IoStack = IoGetCurrentIrpStackLocation(Irp);
00887 
00888     if (IoStack->Parameters.QueryId.IdType == BusQueryInstanceID)
00889     {
00890         /* get device entry */
00891         DeviceEntry = (PBUS_DEVICE_ENTRY) ChildDeviceExtension->DeviceEntry;
00892 
00893         /* sanity check */
00894         ASSERT(DeviceEntry);
00895         ASSERT(DeviceEntry->Instance);
00896 
00897         /* calculate length */
00898         Length = wcslen(DeviceEntry->Instance) + 1;
00899 
00900         /* allocate buffer */
00901         Name = AllocateItem(PagedPool, Length * sizeof(WCHAR));
00902 
00903         if (!Name)
00904         {
00905             /* failed to allocate buffer */
00906             return STATUS_INSUFFICIENT_RESOURCES;
00907         }
00908 
00909         /* copy buffer */
00910         wcscpy(Name, DeviceEntry->Instance);
00911 
00912         /* store result */
00913         Irp->IoStatus.Information = (ULONG_PTR)Name;
00914 
00915         /* done */
00916         return STATUS_SUCCESS;
00917     }
00918     else if (IoStack->Parameters.QueryId.IdType == BusQueryDeviceID ||
00919              IoStack->Parameters.QueryId.IdType == BusQueryHardwareIDs)
00920     {
00921         /* get device entry */
00922         DeviceEntry = (PBUS_DEVICE_ENTRY) ChildDeviceExtension->DeviceEntry;
00923 
00924         /* get bus device extension */
00925         BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION) ChildDeviceExtension->BusDeviceExtension;
00926 
00927         /* sanity check */
00928         ASSERT(DeviceEntry);
00929         ASSERT(DeviceEntry->BusId);
00930         ASSERT(BusDeviceExtension);
00931         ASSERT(BusDeviceExtension->BusIdentifier);
00932 
00933         /* calculate length */
00934         Length = wcslen(BusDeviceExtension->BusIdentifier);
00935         Length += wcslen(DeviceEntry->BusId);
00936 
00937         /* extra length for '\\' and zero byte */
00938         Length += 2;
00939 
00940         /* allocate buffer */
00941         Name = ExAllocatePool(PagedPool, Length * sizeof(WCHAR));
00942         if (!Name)
00943         {
00944             /* failed to allocate buffer */
00945             return STATUS_INSUFFICIENT_RESOURCES;
00946         }
00947 
00948         /* construct id */
00949         swprintf(Name, L"%s\\%s", BusDeviceExtension->BusIdentifier, DeviceEntry->BusId);
00950 
00951         /* store result */
00952         Irp->IoStatus.Information = (ULONG_PTR)Name;
00953 
00954         /* done */
00955         return STATUS_SUCCESS;
00956     }
00957     else
00958     {
00959         /* other ids are not supported */
00960         //DPRINT1("Not Supported ID Type %x\n", IoStack->Parameters.QueryId.IdType);
00961         return Irp->IoStatus.Status;
00962     }
00963 }
00964 
00965 NTSTATUS
00966 KspInstallInterface(
00967     IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension,
00968     IN PSWENUM_INSTALL_INTERFACE InstallInterface)
00969 {
00970     ULONG Length, Index;
00971     UNICODE_STRING DeviceString, InterfaceString, ReferenceString;
00972     HANDLE hKey, hDeviceKey, hInterfaceKey, hReferenceKey;
00973     NTSTATUS Status;
00974     OBJECT_ATTRIBUTES ObjectAttributes;
00975 
00976     /* sanity check */
00977     ASSERT(InstallInterface);
00978 
00979     /* calculate length */
00980     Length = wcslen(InstallInterface->ReferenceString);
00981 
00982     /* check for invalid characters */
00983     for(Index = 0; Index < Length; Index++)
00984     {
00985         if (InstallInterface->ReferenceString[Index] <= L' ' ||
00986             InstallInterface->ReferenceString[Index] > L'~' ||
00987             InstallInterface->ReferenceString[Index] == L',' ||
00988             InstallInterface->ReferenceString[Index] == L'\\' ||
00989             InstallInterface->ReferenceString[Index] == L'/')
00990         {
00991             /* invalid character */
00992             return STATUS_INVALID_PARAMETER;
00993         }
00994     }
00995 
00996     /* open bus key */
00997     Status = KspOpenBusRegistryKey(BusDeviceExtension, &hKey);
00998     if (NT_SUCCESS(Status))
00999     {
01000         /* convert device guid to string */
01001         Status = RtlStringFromGUID(&InstallInterface->DeviceId, &DeviceString);
01002         if (NT_SUCCESS(Status))
01003         {
01004             /* initialize object attributes */
01005             InitializeObjectAttributes(&ObjectAttributes, &DeviceString, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, hKey, NULL);
01006 
01007             /* construct device key */
01008             Status = ZwCreateKey(&hDeviceKey, GENERIC_WRITE, &ObjectAttributes, 0, NULL, 0, NULL);
01009             if (NT_SUCCESS(Status))
01010             {
01011                 /* initialize reference string */
01012                 RtlInitUnicodeString(&ReferenceString, InstallInterface->ReferenceString);
01013 
01014                 /* initialize object attributes */
01015                 InitializeObjectAttributes(&ObjectAttributes, &ReferenceString, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, hDeviceKey, NULL);
01016 
01017                 /* construct device key */
01018                 Status = ZwCreateKey(&hReferenceKey, GENERIC_WRITE, &ObjectAttributes, 0, NULL, 0, NULL);
01019                 if (NT_SUCCESS(Status))
01020                 {
01021                     /* convert interface guid to string */
01022                     Status = RtlStringFromGUID(&InstallInterface->InterfaceId, &InterfaceString);
01023                     if (NT_SUCCESS(Status))
01024                     {
01025                         /* initialize object attributes */
01026                         InitializeObjectAttributes(&ObjectAttributes, &InterfaceString, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, hReferenceKey, NULL);
01027 
01028                         /* construct device key */
01029                         Status = ZwCreateKey(&hInterfaceKey, GENERIC_WRITE, &ObjectAttributes, 0, NULL, 0, NULL);
01030                         if (NT_SUCCESS(Status))
01031                         {
01032                             /* close key */
01033                             ZwClose(hInterfaceKey);
01034                         }
01035                         /* free interface string */
01036                         RtlFreeUnicodeString(&InterfaceString);
01037                     }
01038                     /* close reference key */
01039                     ZwClose(hReferenceKey);
01040                 }
01041                 /* close device key */
01042                 ZwClose(hDeviceKey);
01043             }
01044             /* free device string */
01045             RtlFreeUnicodeString(&DeviceString);
01046         }
01047         /* close bus key */
01048         ZwClose(hKey);
01049     }
01050 
01051     /* done */
01052     return Status;
01053  }
01054 
01055 VOID
01056 NTAPI
01057 KspInstallBusEnumInterface(
01058     IN PVOID Ctx)
01059 {
01060     PIO_STACK_LOCATION IoStack;
01061     NTSTATUS Status;
01062     PLIST_ENTRY Entry;
01063     PBUS_DEVICE_ENTRY DeviceEntry;
01064     PSWENUM_INSTALL_INTERFACE InstallInterface;
01065     KIRQL OldLevel;
01066     PBUS_INSTALL_ENUM_CONTEXT Context = (PBUS_INSTALL_ENUM_CONTEXT)Ctx;
01067 
01068     /* get current irp stack location */
01069     IoStack = IoGetCurrentIrpStackLocation(Context->Irp);
01070 
01071     /* get install request */
01072     InstallInterface = (PSWENUM_INSTALL_INTERFACE)Context->Irp->AssociatedIrp.SystemBuffer;
01073 
01074     /* sanity check */
01075     ASSERT(InstallInterface);
01076     ASSERT(Context->BusDeviceExtension);
01077 
01078     if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(SWENUM_INSTALL_INTERFACE))
01079     {
01080         /* buffer too small */
01081         Context->Status = STATUS_INVALID_PARAMETER;
01082 
01083         /* signal completion */
01084         KeSetEvent(&Context->Event, 0, FALSE);
01085 
01086         /* done */
01087         return;
01088     }
01089 
01090     /* FIXME locks */
01091 
01092     /* now install the interface */
01093     Status = KspInstallInterface(Context->BusDeviceExtension, InstallInterface);
01094     if (!NT_SUCCESS(Status))
01095     {
01096         /* failed to install interface */
01097         Context->Status = Status;
01098 
01099         /* signal completion */
01100         KeSetEvent(&Context->Event, 0, FALSE);
01101 
01102         /* done */
01103         return;
01104     }
01105 
01106     /* acquire device entry lock */
01107     KeAcquireSpinLock(&Context->BusDeviceExtension->Lock, &OldLevel);
01108 
01109     /* now iterate all device entries */
01110     Entry = Context->BusDeviceExtension->Common.Entry.Flink;
01111     while(Entry != &Context->BusDeviceExtension->Common.Entry)
01112     {
01113         /* get device entry */
01114         DeviceEntry = (PBUS_DEVICE_ENTRY)CONTAINING_RECORD(Entry, BUS_DEVICE_ENTRY, Entry);
01115 
01116         if (IsEqualGUIDAligned(&DeviceEntry->DeviceGuid, &InstallInterface->DeviceId) &&
01117             !wcsicmp(DeviceEntry->Instance, InstallInterface->ReferenceString))
01118         {
01119             if (!DeviceEntry->PDO)
01120             {
01121                 /* create pdo */
01122                 Status = KspCreatePDO(Context->BusDeviceExtension, DeviceEntry, &DeviceEntry->PDO);
01123 
01124                 /* done */
01125                 break;
01126             }
01127         }
01128 
01129         /* move to next entry */
01130         Entry = Entry->Flink;
01131     }
01132 
01133     /* release device entry lock */
01134     KeReleaseSpinLock(&Context->BusDeviceExtension->Lock, OldLevel);
01135 
01136     /* signal that bus driver relations has changed */
01137     IoInvalidateDeviceRelations(Context->BusDeviceExtension->PhysicalDeviceObject, BusRelations);
01138 
01139     /* update status */
01140     Context->Status = Status;
01141 
01142     /* signal completion */
01143     KeSetEvent(&Context->Event, 0, FALSE);
01144 }
01145 
01146 
01147 VOID
01148 NTAPI
01149 KspBusWorkerRoutine(
01150   IN PVOID Parameter)
01151 {
01152     PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension;
01153     PBUS_DEVICE_ENTRY DeviceEntry;
01154     PLIST_ENTRY Entry;
01155     LARGE_INTEGER Time, Diff;
01156     BOOLEAN DoInvalidate = FALSE;
01157     KIRQL OldLevel;
01158 
01159     /* get device extension */
01160     BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION)Parameter;
01161 
01162     /* acquire lock */
01163     KeAcquireSpinLock(&BusDeviceExtension->Lock, &OldLevel);
01164 
01165     /* get current time */
01166     KeQuerySystemTime(&Time);
01167 
01168     /* enumerate all device entries */
01169     Entry = BusDeviceExtension->Common.Entry.Flink;
01170     while(Entry != &BusDeviceExtension->Common.Entry)
01171     {
01172         /* get offset to device entry */
01173         DeviceEntry = (PBUS_DEVICE_ENTRY)CONTAINING_RECORD(Entry, BUS_DEVICE_ENTRY, Entry);
01174 
01175         /* sanity check */
01176         ASSERT(DeviceEntry);
01177 
01178         //DPRINT1("DeviceEntry %p PDO %p State %x\n", DeviceEntry, DeviceEntry->PDO, DeviceEntry->DeviceState);
01179 
01180         if (DeviceEntry->PDO)
01181         {
01182             if (DeviceEntry->DeviceState == NotStarted)
01183             {
01184                 Diff.QuadPart = Time.QuadPart - DeviceEntry->TimeCreated.QuadPart;
01185 
01186                 if (Diff.QuadPart > Int32x32To64(15000, 10000))
01187                 {
01188                      DPRINT1("DeviceID %S  Instance %S TimeCreated %I64u Now %I64u Diff %I64u hung\n", DeviceEntry->DeviceName, DeviceEntry->Instance, DeviceEntry->TimeCreated.QuadPart, Time.QuadPart, Diff.QuadPart);
01189 
01190                      /* release spin lock */
01191                      KeReleaseSpinLock(&BusDeviceExtension->Lock, OldLevel);
01192 
01193                      /* deactivate interfaces */
01194                      //KspEnableBusDeviceInterface(DeviceEntry, FALSE);
01195 
01196                      /* re-acquire lock */
01197                      KeAcquireSpinLock(&BusDeviceExtension->Lock, &OldLevel);
01198 
01199                      /* pending remove device object */
01200                      DeviceEntry->DeviceState = StopPending;
01201 
01202                      /* perform invalidation */
01203                      DoInvalidate = TRUE;
01204                 }
01205             }
01206             else if (DeviceEntry->DeviceState == Started)
01207             {
01208                 /* found pending irps */
01209                 KspCompletePendingIrps(DeviceEntry, STATUS_REPARSE);
01210             }
01211         }
01212 
01213 
01214         /* move to next */
01215         Entry = Entry->Flink;
01216     }
01217 
01218    /* release lock */
01219     KeReleaseSpinLock(&BusDeviceExtension->Lock, OldLevel);
01220 
01221     if (DoInvalidate)
01222     {
01223         /* invalidate device relations */
01224         IoInvalidateDeviceRelations(BusDeviceExtension->PhysicalDeviceObject, BusRelations);
01225     }
01226 
01227     Time.QuadPart = Int32x32To64(5000, -10000);
01228     KeSetTimer(&BusDeviceExtension->Timer, Time, &BusDeviceExtension->Dpc);
01229 }
01230 
01231 VOID
01232 NTAPI
01233 KspBusDpcRoutine(
01234     IN PKDPC Dpc,
01235     IN PVOID DeferredContext OPTIONAL,
01236     IN PVOID SystemArgument1 OPTIONAL,
01237     IN PVOID SystemArgument2 OPTIONAL)
01238 {
01239     /* get device extension */
01240     PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION)DeferredContext;
01241 
01242     /* queue the item */
01243     ExQueueWorkItem(&BusDeviceExtension->WorkItem, DelayedWorkQueue);
01244 }
01245 
01246 VOID
01247 NTAPI
01248 KspRemoveBusInterface(
01249     PVOID Ctx)
01250 {
01251     PBUS_INSTALL_ENUM_CONTEXT Context =(PBUS_INSTALL_ENUM_CONTEXT)Ctx;
01252 
01253     /* TODO
01254      * get SWENUM_INSTALL_INTERFACE struct
01255      * open device key and delete the keys
01256      */
01257 
01258     UNIMPLEMENTED
01259 
01260     /* set status */
01261     Context->Status = STATUS_NOT_IMPLEMENTED;
01262 
01263 
01264     /* signal completion */
01265     KeSetEvent(&Context->Event, IO_NO_INCREMENT, FALSE);
01266 }
01267 
01268 NTSTATUS
01269 KspQueryBusRelations(
01270     IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension,
01271     IN PIRP Irp)
01272 {
01273     PDEVICE_RELATIONS DeviceRelations;
01274     PLIST_ENTRY Entry;
01275     PBUS_DEVICE_ENTRY DeviceEntry;
01276     ULONG Count = 0, Length;
01277     KIRQL OldLevel;
01278 
01279     /* acquire lock */
01280     KeAcquireSpinLock(&BusDeviceExtension->Lock, &OldLevel);
01281 
01282     /* first scan all device entries */
01283     Entry = BusDeviceExtension->Common.Entry.Flink;
01284 
01285     while(Entry != &BusDeviceExtension->Common.Entry)
01286     {
01287         /* get offset to device entry */
01288         DeviceEntry = (PBUS_DEVICE_ENTRY)CONTAINING_RECORD(Entry, BUS_DEVICE_ENTRY, Entry);
01289 
01290         /* is there a pdo yet */
01291         if (DeviceEntry->PDO && (DeviceEntry->DeviceState == NotStarted || DeviceEntry->DeviceState == Started))
01292         {
01293             /* increment count */
01294             Count++;
01295         }
01296 
01297         /* move to next entry */
01298         Entry = Entry->Flink;
01299     }
01300 
01301     /* calculate length */
01302     Length = sizeof(DEVICE_RELATIONS) + (Count > 1 ? sizeof(PDEVICE_OBJECT) * (Count-1) : 0);
01303 
01304     /* allocate device relations */
01305     DeviceRelations = (PDEVICE_RELATIONS)AllocateItem(NonPagedPool, Length);
01306 
01307     if (!DeviceRelations)
01308     {
01309         /* not enough memory */
01310         KeReleaseSpinLock(&BusDeviceExtension->Lock, OldLevel);
01311         return STATUS_INSUFFICIENT_RESOURCES;
01312     }
01313 
01314     /* rescan device entries */
01315     Entry = BusDeviceExtension->Common.Entry.Flink;
01316 
01317     while(Entry != &BusDeviceExtension->Common.Entry)
01318     {
01319         /* get offset to device entry */
01320         DeviceEntry = (PBUS_DEVICE_ENTRY)CONTAINING_RECORD(Entry, BUS_DEVICE_ENTRY, Entry);
01321 
01322         /* is there a pdo yet */
01323         if (DeviceEntry->PDO && (DeviceEntry->DeviceState == NotStarted || DeviceEntry->DeviceState == Started))
01324         {
01325             /* store pdo */
01326             DeviceRelations->Objects[DeviceRelations->Count] = DeviceEntry->PDO;
01327 
01328             /* reference device object */
01329             ObReferenceObject(DeviceEntry->PDO);
01330 
01331             /* increment pdo count */
01332             DeviceRelations->Count++;
01333         }
01334 
01335         /* move to next entry */
01336         Entry = Entry->Flink;
01337     }
01338 
01339     /* release lock */
01340     KeReleaseSpinLock(&BusDeviceExtension->Lock, OldLevel);
01341 
01342     /* FIXME handle existing device relations */
01343     ASSERT(Irp->IoStatus.Information == 0);
01344 
01345     /* store device relations */
01346     Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
01347 
01348     /* done */
01349     return STATUS_SUCCESS;
01350 }
01351 
01352 //------------------------------------------------------------------------------------
01353 
01354 /*
01355     @implemented
01356 */
01357 
01358 KSDDKAPI
01359 NTSTATUS
01360 NTAPI
01361 KsGetBusEnumIdentifier(
01362     IN PIRP Irp)
01363 {
01364     PDEV_EXTENSION DeviceExtension;
01365     PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension;
01366     PIO_STACK_LOCATION IoStack;
01367     ULONG Length;
01368     NTSTATUS Status;
01369     LPWSTR Buffer;
01370 
01371     DPRINT1("KsGetBusEnumIdentifier\n");
01372 
01373     /* get stack location */
01374     IoStack = IoGetCurrentIrpStackLocation(Irp);
01375 
01376     /* sanity checks */
01377     ASSERT(IoStack->DeviceObject);
01378     ASSERT(IoStack->DeviceObject->DeviceExtension);
01379 
01380     /* get device extension */
01381     DeviceExtension = (PDEV_EXTENSION)IoStack->DeviceObject->DeviceExtension;
01382 
01383     /* get bus device extension */
01384     BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION)DeviceExtension->Ext;
01385 
01386     /* sanity checks */
01387     ASSERT(BusDeviceExtension);
01388     ASSERT(BusDeviceExtension->Common.IsBus);
01389 
01390     if (!BusDeviceExtension)
01391     {
01392         /* invalid parameter */
01393         return STATUS_INVALID_PARAMETER;
01394     }
01395 
01396     /* get length */
01397     Length = (wcslen(BusDeviceExtension->BusIdentifier)+1) * sizeof(WCHAR);
01398 
01399     /* is there an output buffer provided */
01400     if (IoStack->Parameters.DeviceIoControl.InputBufferLength)
01401     {
01402         if (Length > IoStack->Parameters.DeviceIoControl.InputBufferLength)
01403         {
01404             /* buffer is too small */
01405             return STATUS_BUFFER_TOO_SMALL;
01406         }
01407 
01408         /* now allocate buffer */
01409         Buffer = AllocateItem(NonPagedPool, Length);
01410         if (!Buffer)
01411         {
01412             /* no memory */
01413             Status = STATUS_INSUFFICIENT_RESOURCES;
01414         }
01415         else
01416         {
01417             /* copy bus identifier */
01418             wcscpy(Buffer, BusDeviceExtension->BusIdentifier);
01419 
01420             /* store buffer */
01421             Irp->AssociatedIrp.SystemBuffer = Buffer;
01422 
01423             /* set flag that buffer gets copied back */
01424             Irp->Flags |= IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER | IRP_INPUT_OPERATION;
01425 
01426             /* done */
01427             Status = STATUS_SUCCESS;
01428         }
01429     }
01430     else
01431     {
01432         /* no buffer provided */
01433         Status = STATUS_BUFFER_OVERFLOW;
01434     }
01435 
01436     /* done */
01437     Irp->IoStatus.Status = Status;
01438     return Status;
01439 }
01440 
01441 /*
01442     @implemented
01443 */
01444 KSDDKAPI
01445 NTSTATUS
01446 NTAPI
01447 KsGetBusEnumParentFDOFromChildPDO(
01448     IN PDEVICE_OBJECT DeviceObject,
01449     OUT PDEVICE_OBJECT *FunctionalDeviceObject)
01450 {
01451     PDEV_EXTENSION DeviceExtension;
01452 
01453     DPRINT1("KsGetBusEnumParentFDOFromChildPDO\n");
01454 
01455     /* get device extension */
01456     DeviceExtension = (PDEV_EXTENSION)DeviceObject->DeviceExtension;
01457 
01458     /* check if this is child pdo */
01459     if (DeviceExtension->Ext->IsBus == FALSE)
01460     {
01461         /* return bus device object */
01462         *FunctionalDeviceObject = DeviceExtension->Ext->BusDeviceExtension->BusDeviceObject;
01463 
01464         /* done */
01465         return STATUS_SUCCESS;
01466     }
01467 
01468     /* invalid parameter */
01469     return STATUS_INVALID_PARAMETER;
01470 }
01471 
01472 
01473 /*
01474     @implemented
01475 */
01476 KSDDKAPI
01477 NTSTATUS
01478 NTAPI
01479 KsCreateBusEnumObject(
01480     IN PWCHAR BusIdentifier,
01481     IN PDEVICE_OBJECT BusDeviceObject,
01482     IN PDEVICE_OBJECT PhysicalDeviceObject,
01483     IN PDEVICE_OBJECT PnpDeviceObject OPTIONAL,
01484     IN REFGUID InterfaceGuid OPTIONAL,
01485     IN PWCHAR ServiceRelativePath OPTIONAL)
01486 {
01487     ULONG Length;
01488     NTSTATUS Status = STATUS_SUCCESS;
01489     UNICODE_STRING ServiceKeyPath = RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Services\\");
01490     PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension;
01491     PDEV_EXTENSION DeviceExtension;
01492 
01493     DPRINT1("KsCreateBusEnumObject %S BusDeviceObject %p\n", ServiceRelativePath, BusDeviceObject);
01494 
01495     /* calculate sizeof bus enum device extension */
01496     Length = wcslen(BusIdentifier) * sizeof(WCHAR);
01497     Length += sizeof(BUS_ENUM_DEVICE_EXTENSION);
01498 
01499     BusDeviceExtension = AllocateItem(NonPagedPool, Length);
01500     if (!BusDeviceExtension)
01501     {
01502         /* not enough memory */
01503 
01504         return STATUS_INSUFFICIENT_RESOURCES;
01505     }
01506 
01507     /* get device extension */
01508     DeviceExtension = (PDEV_EXTENSION)BusDeviceObject->DeviceExtension;
01509 
01510     DPRINT1("DeviceExtension %p BusDeviceExtension %p\n", DeviceExtension, DeviceExtension->Ext);
01511 
01512     /* store bus device extension */
01513     DeviceExtension->Ext = (PCOMMON_DEVICE_EXTENSION)BusDeviceExtension;
01514 
01515     DPRINT1("DeviceExtension %p BusDeviceExtension %p\n", DeviceExtension, DeviceExtension->Ext);
01516 
01517 
01518     /* zero device extension */
01519     RtlZeroMemory(BusDeviceExtension, sizeof(BUS_ENUM_DEVICE_EXTENSION));
01520 
01521     /* initialize bus device extension */
01522     wcscpy(BusDeviceExtension->BusIdentifier, BusIdentifier);
01523 
01524     /* allocate service path string */
01525     Length = ServiceKeyPath.MaximumLength;
01526     Length += BusDeviceObject->DriverObject->DriverExtension->ServiceKeyName.MaximumLength;
01527 
01528     if (ServiceRelativePath)
01529     {
01530         /* relative path for devices */
01531         Length += (wcslen(ServiceRelativePath) + 2) * sizeof(WCHAR);
01532     }
01533 
01534     BusDeviceExtension->ServicePath.Length = 0;
01535     BusDeviceExtension->ServicePath.MaximumLength = Length;
01536     BusDeviceExtension->ServicePath.Buffer = AllocateItem(NonPagedPool, Length);
01537 
01538     if (!BusDeviceExtension->ServicePath.Buffer)
01539     {
01540         /* not enough memory */
01541         FreeItem(BusDeviceExtension);
01542 
01543         return STATUS_INSUFFICIENT_RESOURCES;
01544     }
01545 
01546     RtlAppendUnicodeStringToString(&BusDeviceExtension->ServicePath, &ServiceKeyPath);
01547     RtlAppendUnicodeStringToString(&BusDeviceExtension->ServicePath, &BusDeviceObject->DriverObject->DriverExtension->ServiceKeyName);
01548 
01549     if (ServiceRelativePath)
01550     {
01551         RtlAppendUnicodeToString(&BusDeviceExtension->ServicePath, L"\\");
01552         RtlAppendUnicodeToString(&BusDeviceExtension->ServicePath, ServiceRelativePath);
01553     }
01554 
01555     if (InterfaceGuid)
01556     {
01557         /* register an device interface */
01558         Status = IoRegisterDeviceInterface(PhysicalDeviceObject, InterfaceGuid, NULL, &BusDeviceExtension->DeviceInterfaceLink);
01559 
01560         /* check for success */
01561         if (!NT_SUCCESS(Status))
01562         {
01563 
01564             FreeItem(BusDeviceExtension->ServicePath.Buffer);
01565             FreeItem(BusDeviceExtension);
01566             return Status;
01567         }
01568 
01569         /* now enable device interface */
01570         Status = IoSetDeviceInterfaceState(&BusDeviceExtension->DeviceInterfaceLink, TRUE);
01571 
01572         if (!NT_SUCCESS(Status))
01573         {
01574             FreeItem(BusDeviceExtension->ServicePath.Buffer);
01575             FreeItem(BusDeviceExtension);
01576             return Status;
01577         }
01578     }
01579 
01580     /* initialize common device extension */
01581     BusDeviceExtension->Common.BusDeviceExtension = NULL;
01582     BusDeviceExtension->Common.DeviceObjectReferenceCount = 1;
01583     BusDeviceExtension->Common.DeviceReferenceCount = 1;
01584     BusDeviceExtension->Common.IsBus = TRUE;
01585     InitializeListHead(&BusDeviceExtension->Common.Entry);
01586 
01587     /* store device objects */
01588     BusDeviceExtension->BusDeviceObject = BusDeviceObject;
01589     BusDeviceExtension->PhysicalDeviceObject = PhysicalDeviceObject;
01590 
01591     /* initialize lock */
01592     KeInitializeSpinLock(&BusDeviceExtension->Lock);
01593 
01594     /* initialize timer */
01595     KeInitializeTimer(&BusDeviceExtension->Timer);
01596 
01597     /* initialize dpc */
01598     KeInitializeDpc(&BusDeviceExtension->Dpc, KspBusDpcRoutine, (PVOID)BusDeviceExtension);
01599 
01600     /* initialize event */
01601     KeInitializeEvent(&BusDeviceExtension->Event, SynchronizationEvent, FALSE);
01602 
01603     /* initialize work item */
01604     ExInitializeWorkItem(&BusDeviceExtension->WorkItem, KspBusWorkerRoutine, (PVOID)BusDeviceExtension);
01605 
01606     if (!PnpDeviceObject)
01607     {
01608         /* attach device */
01609         BusDeviceExtension->PnpDeviceObject = IoAttachDeviceToDeviceStack(BusDeviceObject, PhysicalDeviceObject);
01610 
01611         if (!BusDeviceExtension->PnpDeviceObject)
01612         {
01613             /* failed to attach device */
01614             if (BusDeviceExtension->DeviceInterfaceLink.Buffer)
01615             {
01616                 IoSetDeviceInterfaceState(&BusDeviceExtension->DeviceInterfaceLink, FALSE);
01617                 RtlFreeUnicodeString(&BusDeviceExtension->DeviceInterfaceLink);
01618             }
01619 
01620             /* free device extension */
01621             FreeItem(BusDeviceExtension->ServicePath.Buffer);
01622             FreeItem(BusDeviceExtension);
01623 
01624             return STATUS_DEVICE_REMOVED;
01625         }
01626 
01627         /* mark device as attached */
01628         BusDeviceExtension->DeviceAttached = TRUE;
01629     }
01630     else
01631     {
01632         /* directly attach */
01633         BusDeviceExtension->PnpDeviceObject = PnpDeviceObject;
01634     }
01635 
01636     /* now scan the bus */
01637     Status = KspScanBus(BusDeviceExtension);
01638 
01639     /* check for success */
01640     if (!NT_SUCCESS(Status))
01641     {
01642         /* failed to scan bus */
01643         if (BusDeviceExtension->DeviceInterfaceLink.Buffer)
01644         {
01645             IoSetDeviceInterfaceState(&BusDeviceExtension->DeviceInterfaceLink, FALSE);
01646             RtlFreeUnicodeString(&BusDeviceExtension->DeviceInterfaceLink);
01647         }
01648 
01649         if (BusDeviceExtension->DeviceAttached)
01650         {
01651             /* detach device */
01652             IoDetachDevice(BusDeviceExtension->PnpDeviceObject);
01653         }
01654 
01655         /* free device extension */
01656         FreeItem(BusDeviceExtension->ServicePath.Buffer);
01657         FreeItem(BusDeviceExtension);
01658     }
01659 
01660     DPRINT("KsCreateBusEnumObject Status %x\n", Status);
01661     /* done */
01662     return Status;
01663 }
01664 
01665 /*
01666     @implemented
01667 */
01668 KSDDKAPI
01669 NTSTATUS
01670 NTAPI
01671 KsGetBusEnumPnpDeviceObject(
01672     IN PDEVICE_OBJECT DeviceObject,
01673     IN PDEVICE_OBJECT *PnpDeviceObject)
01674 {
01675     PDEV_EXTENSION DeviceExtension;
01676     PCOMMON_DEVICE_EXTENSION CommonDeviceExtension;
01677     PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension;
01678 
01679     DPRINT("KsGetBusEnumPnpDeviceObject\n");
01680 
01681     if (!DeviceObject->DeviceExtension)
01682     {
01683         /* invalid parameter */
01684         return STATUS_INVALID_PARAMETER;
01685     }
01686 
01687     /* get device extension */
01688     DeviceExtension = (PDEV_EXTENSION)DeviceObject->DeviceExtension;
01689 
01690     /* get common device extension */
01691     CommonDeviceExtension = DeviceExtension->Ext;
01692 
01693     if (!CommonDeviceExtension)
01694     {
01695         /* invalid parameter */
01696         return STATUS_INVALID_PARAMETER;
01697     }
01698 
01699     if (!CommonDeviceExtension->IsBus)
01700     {
01701         /* getting pnp device object is only supported for software bus device object */
01702        return STATUS_INVALID_PARAMETER;
01703     }
01704 
01705     /* sanity checks */
01706     ASSERT(CommonDeviceExtension);
01707     ASSERT(CommonDeviceExtension->IsBus);
01708 
01709     /* cast to bus device extension */
01710     BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION)CommonDeviceExtension;
01711 
01712     /* store result */
01713     *PnpDeviceObject = BusDeviceExtension->PnpDeviceObject;
01714 
01715     /* done */
01716     return STATUS_SUCCESS;
01717 }
01718 
01719 /*
01720     @implemented
01721 */
01722 KSDDKAPI
01723 NTSTATUS
01724 NTAPI
01725 KsInstallBusEnumInterface(
01726     PIRP Irp)
01727 {
01728     BUS_INSTALL_ENUM_CONTEXT Context;
01729     KPROCESSOR_MODE Mode;
01730     LUID luid;
01731     PIO_STACK_LOCATION IoStack;
01732     PDEV_EXTENSION DeviceExtension;
01733     PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension;
01734 
01735     DPRINT1("KsInstallBusEnumInterface\n");
01736 
01737     /* get current irp stack location */
01738     IoStack = IoGetCurrentIrpStackLocation(Irp);
01739 
01740     /* get previous mode */
01741     Mode = ExGetPreviousMode();
01742 
01743     /* convert to luid */
01744     luid = RtlConvertUlongToLuid(SE_LOAD_DRIVER_PRIVILEGE);
01745 
01746     /* perform access check */
01747     if (!SeSinglePrivilegeCheck(luid, Mode))
01748     {
01749         /* insufficient privileges */
01750         return STATUS_PRIVILEGE_NOT_HELD;
01751     }
01752 
01753     /* get device extension */
01754     DeviceExtension = (PDEV_EXTENSION)IoStack->DeviceObject->DeviceExtension;
01755 
01756     /* get bus device extension */
01757     BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION)DeviceExtension->Ext;
01758 
01759 
01760     /* initialize context */
01761     Context.Irp = Irp;
01762     KeInitializeEvent(&Context.Event, NotificationEvent, FALSE);
01763     Context.BusDeviceExtension = BusDeviceExtension;
01764     ExInitializeWorkItem(&Context.WorkItem, KspInstallBusEnumInterface, (PVOID)&Context);
01765 
01766     /* queue the work item */
01767     ExQueueWorkItem(&Context.WorkItem, DelayedWorkQueue);
01768     /* wait for completion */
01769     KeWaitForSingleObject(&Context.Event, Executive, KernelMode, FALSE, NULL);
01770 
01771     /* store result */
01772     Irp->IoStatus.Status = Context.Status;
01773 
01774     /* done */
01775     return Context.Status;
01776 }
01777 
01778 /*
01779     @implemented
01780 */
01781 KSDDKAPI
01782 NTSTATUS
01783 NTAPI
01784 KsIsBusEnumChildDevice(
01785     IN PDEVICE_OBJECT DeviceObject,
01786     OUT PBOOLEAN ChildDevice)
01787 {
01788     PDEV_EXTENSION DeviceExtension;
01789     PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension;
01790 
01791     DPRINT("KsIsBusEnumChildDevice %p\n", DeviceObject);
01792 
01793     /* get device extension */
01794     DeviceExtension = (PDEV_EXTENSION)DeviceObject->DeviceExtension;
01795 
01796     /* get bus device extension */
01797     BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION)DeviceExtension->Ext;
01798 
01799     if (!BusDeviceExtension)
01800     {
01801         /* not a bus device */
01802         return STATUS_INVALID_PARAMETER;
01803     }
01804 
01805     /* store result */
01806     *ChildDevice = (BusDeviceExtension->Common.IsBus == FALSE);
01807 
01808     return STATUS_SUCCESS;
01809 }
01810 
01811 /*
01812     @implemented
01813 */
01814 KSDDKAPI
01815 NTSTATUS
01816 NTAPI
01817 KsServiceBusEnumCreateRequest(
01818     IN PDEVICE_OBJECT DeviceObject,
01819     IN OUT PIRP Irp)
01820 {
01821     PLIST_ENTRY Entry;
01822     PBUS_DEVICE_ENTRY DeviceEntry = NULL; /* fix gcc */
01823     PIO_STACK_LOCATION IoStack;
01824     BOOLEAN ItemExists = FALSE;
01825     PDEV_EXTENSION DeviceExtension;
01826     PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension;
01827     //PCOMMON_DEVICE_EXTENSION ChildDeviceExtension;
01828     NTSTATUS Status;
01829     LARGE_INTEGER Time;
01830 
01831     /* FIXME: locks */
01832 
01833     /* get device extension */
01834     DeviceExtension = (PDEV_EXTENSION)DeviceObject->DeviceExtension;
01835 
01836     /* get bus device extension */
01837     BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION)DeviceExtension->Ext;
01838 
01839     /* get current irp stack location */
01840     IoStack = IoGetCurrentIrpStackLocation(Irp);
01841 
01842     /* sanity checks */
01843     ASSERT(IoStack->FileObject);
01844     ASSERT(IoStack->FileObject->FileName.Buffer);
01845 
01846     DPRINT1("KsServiceBusEnumCreateRequest IRP %p Name %wZ\n", Irp, &IoStack->FileObject->FileName);
01847 
01848     /* scan list and check if it is already present */
01849     Entry = BusDeviceExtension->Common.Entry.Flink;
01850 
01851     while(Entry != &BusDeviceExtension->Common.Entry)
01852     {
01853         /* get real offset */
01854         DeviceEntry = (PBUS_DEVICE_ENTRY)CONTAINING_RECORD(Entry, BUS_DEVICE_ENTRY, Entry);
01855 
01856         /* check if name matches */
01857         if (!wcsicmp(DeviceEntry->DeviceName, IoStack->FileObject->FileName.Buffer + 1))
01858         {
01859             /* item already exists */
01860             ItemExists = TRUE;
01861             break;
01862         }
01863 
01864         /* move to next entry */
01865         Entry = Entry->Flink;
01866     }
01867 
01868     if (!ItemExists)
01869     {
01870         /* interface not registered */
01871         DPRINT1("Interface %wZ not registered\n", &IoStack->FileObject->FileName);
01872         return STATUS_OBJECT_NAME_NOT_FOUND;
01873     }
01874 
01875     /*  is there a pdo yet */
01876     if (DeviceEntry->PDO)
01877     {
01878         if (DeviceEntry->DeviceState == Started)
01879         {
01880             /* issue reparse */
01881             Status =  KspDoReparseForIrp(Irp, DeviceEntry);
01882             DPRINT("REPARSE Irp %p '%wZ'\n", Irp, &IoStack->FileObject->FileName);
01883 
01884             Irp->IoStatus.Status = Status;
01885             return Status;
01886         }
01887 
01888         /* delay processing until pnp is finished with enumeration */
01889         IoMarkIrpPending(Irp);
01890 
01891         /* insert into irp pending list */
01892         InsertTailList(&DeviceEntry->IrpPendingList, &Irp->Tail.Overlay.ListEntry);
01893 
01894         Time.QuadPart = Int32x32To64(1500, -10000);
01895         DbgPrint("PENDING Irp %p %wZ\n", Irp, &IoStack->FileObject->FileName);
01896 
01897         /* query current time */
01898         KeQuerySystemTime(&DeviceEntry->TimeCreated);
01899 
01900         /* set timer */
01901         KeSetTimer(&BusDeviceExtension->Timer, Time, &BusDeviceExtension->Dpc);
01902 
01903         /* done for now */
01904         return STATUS_PENDING;
01905 
01906     }
01907     else
01908     {
01909         /* time to create PDO */
01910         Status = KspCreatePDO(BusDeviceExtension, DeviceEntry, &DeviceEntry->PDO);
01911 
01912         if (!NT_SUCCESS(Status))
01913         {
01914             /* failed to create PDO */
01915             DPRINT1("KsServiceBusEnumCreateRequest failed to create PDO with %x\n", Status);
01916             return Status;
01917         }
01918         DPRINT1("PENDING CREATE Irp %p %wZ\n", Irp, &IoStack->FileObject->FileName);
01919 
01920         /* delay processing until pnp is finished with enumeration */
01921         IoMarkIrpPending(Irp);
01922 
01923         /* insert into irp pending list */
01924         InsertTailList(&DeviceEntry->IrpPendingList, &Irp->Tail.Overlay.ListEntry);
01925 
01926         /* get current time */
01927         KeQuerySystemTime(&DeviceEntry->TimeCreated);
01928 
01929         /* invalidate device relations */
01930         IoInvalidateDeviceRelations(BusDeviceExtension->PhysicalDeviceObject, BusRelations);
01931 
01932         /* done for now */
01933         return STATUS_PENDING;
01934     }
01935 }
01936 
01937 /*
01938     @implemented
01939 */
01940 KSDDKAPI
01941 NTSTATUS
01942 NTAPI
01943 KsServiceBusEnumPnpRequest(
01944     IN PDEVICE_OBJECT DeviceObject,
01945     IN OUT PIRP Irp)
01946 {
01947     PDEV_EXTENSION DeviceExtension;
01948     PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension;
01949     PCOMMON_DEVICE_EXTENSION ChildDeviceExtension;
01950     PIO_STACK_LOCATION IoStack;
01951     NTSTATUS Status;
01952     LARGE_INTEGER Time;
01953     PDEVICE_RELATIONS DeviceRelation;
01954     PBUS_DEVICE_ENTRY DeviceEntry;
01955 
01956     /* get device extension */
01957     DeviceExtension = (PDEV_EXTENSION)DeviceObject->DeviceExtension;
01958 
01959     /* get bus device extension */
01960     BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION)DeviceExtension->Ext;
01961 
01962     /* get current irp stack location */
01963     IoStack = IoGetCurrentIrpStackLocation(Irp);
01964 
01965     if (BusDeviceExtension->Common.IsBus)
01966     {
01967         if (IoStack->MinorFunction == IRP_MN_START_DEVICE)
01968         {
01969             /* no op for bus driver */
01970             Status = STATUS_SUCCESS;
01971         }
01972         else if (IoStack->MinorFunction == IRP_MN_QUERY_DEVICE_RELATIONS)
01973         {
01974             /* handle bus device relations */
01975             ASSERT(IoStack->Parameters.QueryDeviceRelations.Type == BusRelations);
01976 
01977             Status = KspQueryBusRelations(BusDeviceExtension, Irp);
01978         }
01979         else
01980         {
01981             /* get default status */
01982             Status = Irp->IoStatus.Status;
01983         }
01984     }
01985     else
01986     {
01987         /* get child device extension */
01988         ChildDeviceExtension = DeviceExtension->Ext;
01989 
01990         /* get bus device extension */
01991         BusDeviceExtension = ChildDeviceExtension->BusDeviceExtension;
01992 
01993         if (IoStack->MinorFunction == IRP_MN_QUERY_ID)
01994         {
01995             /* query id */
01996             Status = KspQueryId(ChildDeviceExtension, Irp);
01997         }
01998         else if (IoStack->MinorFunction == IRP_MN_REMOVE_DEVICE)
01999         {
02000             ASSERT(ChildDeviceExtension->DeviceEntry->DeviceState != Started || ChildDeviceExtension->DeviceEntry->DeviceState == NotStarted);
02001             ASSERT(ChildDeviceExtension->DeviceEntry->PDO == DeviceObject);
02002 
02003             /* backup device entry */
02004             DeviceEntry = ChildDeviceExtension->DeviceEntry;
02005 
02006             /* free device extension */
02007             FreeItem(ChildDeviceExtension);
02008 
02009             /* clear PDO reference */
02010             DeviceEntry->PDO = NULL;
02011 
02012             /* delete the device */
02013             IoDeleteDevice(DeviceObject);
02014 
02015             if (DeviceEntry->PDODeviceName)
02016             {
02017                 /* delete pdo device name */
02018                 FreeItem(DeviceEntry->PDODeviceName);
02019 
02020                 /* set to null */
02021                 DeviceEntry->PDODeviceName = NULL;
02022             }
02023 
02024             /* set state no notstarted */
02025             DeviceEntry->DeviceState = NotStarted;
02026 
02027         /* time to create PDO */
02028         KspCreatePDO(BusDeviceExtension, DeviceEntry, &DeviceEntry->PDO);
02029 
02030         /* invalidate device relations */
02031         IoInvalidateDeviceRelations(BusDeviceExtension->PhysicalDeviceObject, BusRelations);
02032 
02033             /* done */
02034             Status = STATUS_SUCCESS;
02035         }
02036         else if (IoStack->MinorFunction == IRP_MN_QUERY_BUS_INFORMATION)
02037         {
02038             /* query bus information */
02039             Status = KspQueryBusInformation(ChildDeviceExtension, Irp);
02040         }
02041         else if (IoStack->MinorFunction == IRP_MN_QUERY_RESOURCES)
02042         {
02043             /* no op */
02044             Status = STATUS_SUCCESS;
02045         }
02046         else if (IoStack->MinorFunction == IRP_MN_QUERY_RESOURCE_REQUIREMENTS)
02047         {
02048             /* no op */
02049             Status = STATUS_SUCCESS;
02050         }
02051         else if (IoStack->MinorFunction == IRP_MN_START_DEVICE)
02052         {
02053             /* start bus */
02054             Status = KspStartBusDevice(DeviceObject, ChildDeviceExtension, Irp);
02055 
02056             /* set time out */
02057             Time.QuadPart = Int32x32To64(1500, -10000);
02058 
02059             /* sanity check */
02060             ASSERT(BusDeviceExtension);
02061 
02062             /* set timer */
02063             KeSetTimer(&BusDeviceExtension->Timer, Time, &BusDeviceExtension->Dpc);
02064         }
02065         else if (IoStack->MinorFunction == IRP_MN_QUERY_CAPABILITIES)
02066         {
02067             /* query capabilities */
02068             Status = KspQueryBusDeviceCapabilities(ChildDeviceExtension, Irp);
02069         }
02070         else if (IoStack->MinorFunction == IRP_MN_QUERY_PNP_DEVICE_STATE)
02071         {
02072             /* query pnp state */
02073             Status = KspQueryBusDevicePnpState(ChildDeviceExtension, Irp);
02074         }
02075         else if (IoStack->MinorFunction == IRP_MN_QUERY_INTERFACE)
02076         {
02077             /* query interface */
02078             Status = KspQueryBusDeviceInterface(ChildDeviceExtension, Irp);
02079         }
02080         else if (IoStack->MinorFunction == IRP_MN_QUERY_DEVICE_RELATIONS && IoStack->Parameters.QueryDeviceRelations.Type == TargetDeviceRelation)
02081         {
02082             /* handle target device relations */
02083             ASSERT(IoStack->Parameters.QueryDeviceRelations.Type == TargetDeviceRelation);
02084             ASSERT(Irp->IoStatus.Information == 0);
02085 
02086             /* allocate device relation */
02087             DeviceRelation = AllocateItem(PagedPool, sizeof(DEVICE_RELATIONS));
02088             if (DeviceRelation)
02089             {
02090                 DeviceRelation->Count = 1;
02091                 DeviceRelation->Objects[0] = DeviceObject;
02092 
02093                 /* reference self */
02094                 ObReferenceObject(DeviceObject);
02095 
02096                 /* store result */
02097                 Irp->IoStatus.Information = (ULONG_PTR)DeviceRelation;
02098 
02099                 /* done */
02100                 Status = STATUS_SUCCESS;
02101             }
02102             else
02103             {
02104                 /* no memory */
02105                 Status = STATUS_INSUFFICIENT_RESOURCES;
02106             }
02107         }
02108         else
02109         {
02110             /* get default status */
02111             Status = Irp->IoStatus.Status;
02112         }
02113     }
02114 
02115     DPRINT("KsServiceBusEnumPnpRequest %p Bus %u Function %x Status %x\n", DeviceObject, BusDeviceExtension->Common.IsBus, IoStack->MinorFunction, Status);
02116     Irp->IoStatus.Status = Status;
02117     return Status;
02118 }
02119 
02120 /*
02121     @implemented
02122 */
02123 KSDDKAPI 
02124 NTSTATUS
02125 NTAPI
02126 KsRemoveBusEnumInterface(
02127     IN PIRP Irp)
02128 {
02129     KPROCESSOR_MODE Mode;
02130     LUID luid;
02131     BUS_INSTALL_ENUM_CONTEXT Ctx;
02132     PDEV_EXTENSION DeviceExtension;
02133     PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension;
02134     PIO_STACK_LOCATION IoStack;
02135 
02136     DPRINT1("KsRemoveBusEnumInterface\n");
02137 
02138     /* get io stack location */
02139     IoStack = IoGetCurrentIrpStackLocation(Irp);
02140 
02141     /* get device extension */
02142     DeviceExtension = (PDEV_EXTENSION)IoStack->DeviceObject->DeviceExtension;
02143 
02144     /* get bus device extension */
02145     BusDeviceExtension = DeviceExtension->Ext->BusDeviceExtension;
02146 
02147     /* get previous mode */
02148     Mode = ExGetPreviousMode();
02149 
02150     /* convert to luid */
02151     luid = RtlConvertUlongToLuid(SE_LOAD_DRIVER_PRIVILEGE);
02152 
02153     /* perform access check */
02154     if (!SeSinglePrivilegeCheck(luid, Mode))
02155     {
02156         /* insufficient privileges */
02157         return STATUS_PRIVILEGE_NOT_HELD;
02158     }
02159 
02160     /* initialize context */
02161     KeInitializeEvent(&Ctx.Event, NotificationEvent, FALSE);
02162     Ctx.Irp = Irp;
02163     Ctx.BusDeviceExtension = BusDeviceExtension;
02164     ExInitializeWorkItem(&Ctx.WorkItem, KspRemoveBusInterface, (PVOID)&Ctx);
02165 
02166     /* now queue the work item */
02167     ExQueueWorkItem(&Ctx.WorkItem, DelayedWorkQueue);
02168 
02169     /* wait for completion */
02170     KeWaitForSingleObject(&Ctx.Event, Executive, KernelMode, FALSE, NULL);
02171 
02172     /* return result */
02173     return Ctx.Status;
02174 }

Generated on Sun May 27 2012 04:27:58 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.