01561 :
01562
01563 PnP device drivers call
this API to report any device detected. This routine
01564 creates a
Physical Device object, reference
the Physical Device object and
01565 returns back to
the callers. Once
the detected device
is reported,
the Pnp manager
01566 considers
the device has been fully controlled by
the reporting drivers. Thus
it
01567 will not invoke AddDevice entry and send
StartDevice irp to
the driver.
01568
01569 The driver needs to report
the resources
it used to detect
this device such that
01570 pnp manager can perform duplicates detection on
this device.
01571
01572 The caller must dereference
the DeviceObject once
it no longer needs
it.
01573
01574 Parameters:
01575
01576 DriverObject - Supplies
the driver object of
the driver who detected
01577
this device.
01578
01579 ResourceList - Supplies a pointer to
the resource list which
the driver used
01580 to detect
the device.
01581
01582 ResourceRequirements - supplies a pointer to
the resource requirements list
01583
for the detected device. This
is optional.
01584
01585 ResourceAssigned -
if TRUE,
the driver already called
IoReportResourceUsage or
01586 IoAssignResource to get
the ownership of
the resources. Otherwise,
01587
the PnP manager will call
IoReportResourceUsage to allocate
the
01588 resources
for the driver.
01589
01590 DeviceObject -
if NULL,
this routine will create a PDO and
return it thru
this variable.
01591 Otherwise, a PDO
is already created and
this routine will simply use
the supplied
01592 PDO.
01593
01594 Return Value:
01595
01596
Status code that indicates whether or not
the function was successful.
01597
01598
01599 --*/
01600
01601 {
01602 WCHAR buffer[60];
01603
NTSTATUS status;
01604 UNICODE_STRING deviceName, instanceName, unicodeName, *serviceName, driverName;
01605
PDEVICE_NODE deviceNode;
01606 ULONG length, i = 0, disposition, tmpValue, listSize = 0;
01607 HANDLE handle, handle1, logConfHandle, controlHandle, hTreeHandle, enumHandle;
01608 PCM_RESOURCE_LIST cmResource;
01609 PWSTR p;
01610 LARGE_INTEGER tickCount;
01611
PDEVICE_OBJECT deviceObject;
01612 BOOLEAN newlyCreated =
FALSE;
01613
01614
PAGED_CODE();
01615
01616
if (*DeviceObject) {
01617
01618 deviceObject = *DeviceObject;
01619
01620
01621
01622
01623
01624 deviceNode = (
PDEVICE_NODE)(*DeviceObject)->DeviceObjectExtension->DeviceNode;
01625
if (!deviceNode) {
01626
return STATUS_NO_SUCH_DEVICE;
01627 }
01628
01629
KeEnterCriticalRegion();
01630
ExAcquireResourceShared(&PpRegistryDeviceResource, TRUE);
01631
01632
01633
01634
01635
01636 status =
IopDeviceObjectToDeviceInstance (*DeviceObject,
01637 &handle,
01638 KEY_ALL_ACCESS
01639 );
01640
if (!
NT_SUCCESS(status)) {
01641
ExReleaseResource(&PpRegistryDeviceResource);
01642
KeLeaveCriticalRegion();
01643
return status;
01644 }
01645
if (ResourceAssigned) {
01646
RtlInitUnicodeString(&unicodeName, REGSTR_VALUE_NO_RESOURCE_AT_INIT);
01647 tmpValue = 1;
01648 ZwSetValueKey(handle,
01649 &unicodeName,
01650 TITLE_INDEX_VALUE,
01651 REG_DWORD,
01652 &tmpValue,
01653
sizeof(tmpValue)
01654 );
01655 }
01656
RtlInitUnicodeString(&unicodeName, REGSTR_KEY_LOG_CONF);
01657 status =
IopCreateRegistryKeyEx( &logConfHandle,
01658 handle,
01659 &unicodeName,
01660 KEY_ALL_ACCESS,
01661 REG_OPTION_NON_VOLATILE,
01662 NULL
01663 );
01664 ZwClose(handle);
01665
if (
NT_SUCCESS(status)) {
01666
01667
01668
01669
01670
01671
01672
if (ResourceList) {
01673
RtlInitUnicodeString(&unicodeName, REGSTR_VAL_BOOTCONFIG);
01674 ZwSetValueKey(
01675 logConfHandle,
01676 &unicodeName,
01677 TITLE_INDEX_VALUE,
01678 REG_RESOURCE_LIST,
01679 ResourceList,
01680 listSize =
IopDetermineResourceListSize(ResourceList)
01681 );
01682 }
01683
if (ResourceRequirements) {
01684
RtlInitUnicodeString(&unicodeName, REGSTR_VALUE_BASIC_CONFIG_VECTOR);
01685 ZwSetValueKey(
01686 logConfHandle,
01687 &unicodeName,
01688 TITLE_INDEX_VALUE,
01689 REG_RESOURCE_REQUIREMENTS_LIST,
01690 ResourceRequirements,
01691 ResourceRequirements->ListSize
01692 );
01693 }
01694 ZwClose(logConfHandle);
01695 }
01696
ExReleaseResource(&PpRegistryDeviceResource);
01697
KeLeaveCriticalRegion();
01698
if (
NT_SUCCESS(status)) {
01699
goto checkResource;
01700 }
else {
01701
return status;
01702 }
01703 }
01704
01705
01706
01707
01708
01709 *DeviceObject =
NULL;
01710 serviceName = &DriverObject->DriverExtension->ServiceKeyName;
01711
01712
01713
01714
01715
01716
01717
01718
01719
if (DriverObject->Flags &
DRVO_BUILTIN_DRIVER) {
01720 p = serviceName->Buffer + (serviceName->Length /
sizeof(WCHAR)) - 1;
01721 driverName.Length = 0;
01722
while (*p !=
'\\' && (p != serviceName->Buffer)) {
01723 p--;
01724 driverName.Length +=
sizeof(WCHAR);
01725 }
01726
if (p == serviceName->Buffer) {
01727
return STATUS_UNSUCCESSFUL;
01728 }
else {
01729 p++;
01730 driverName.Buffer = p;
01731 driverName.MaximumLength = driverName.Length +
sizeof(WCHAR);
01732 }
01733 }
else {
01734
01735
01736
01737
01738
01739 status =
IopDuplicateDetection(
01740 LegacyBusType,
01741 BusNumber,
01742 SlotNumber,
01743 &deviceNode
01744 );
01745
01746
if (
NT_SUCCESS(status) && deviceNode) {
01747 deviceObject = deviceNode->
PhysicalDeviceObject;
01748
if ((deviceNode->
Flags &
DNF_ADDED) ||
01749 (
IopDoesDevNodeHaveProblem(deviceNode) &&
01750 deviceNode->
Problem != CM_PROB_NOT_CONFIGURED &&
01751 deviceNode->
Problem != CM_PROB_REINSTALL &&
01752 deviceNode->
Problem != CM_PROB_FAILED_INSTALL)) {
01753
01754
01755
01756
01757
01758
ObDereferenceObject(deviceObject);
01759
01760
return STATUS_NO_SUCH_DEVICE;
01761 }
01762
01763 deviceNode->
Flags &= ~
DNF_HAS_PROBLEM;
01764 deviceNode->
Problem = 0;
01765
01766
IopDeleteLegacyKey(DriverObject);
01767
goto checkResource;
01768 }
01769
01770 }
01771
01772
01773
01774
01775
01776
01777
01778
01779
01780
KeQueryTickCount(&tickCount);
01781 length = _snwprintf(buffer,
sizeof(buffer) /
sizeof(WCHAR), L
"\\Device\\%04u%x", IopNumberDeviceNodes, tickCount.LowPart);
01782 deviceName.MaximumLength =
sizeof(buffer);
01783 deviceName.Length = (
USHORT)(length *
sizeof(WCHAR));
01784 deviceName.Buffer = buffer; \
01785
01786 status =
IoCreateDevice( IoPnpDriverObject,
01787
sizeof(
IOPNP_DEVICE_EXTENSION),
01788 &deviceName,
01789 FILE_DEVICE_CONTROLLER,
01790 0,
01791 FALSE,
01792 &deviceObject );
01793
01794
if (
NT_SUCCESS(status)) {
01795 deviceObject->
Flags |=
DO_BUS_ENUMERATED_DEVICE;
01796 deviceNode =
IopAllocateDeviceNode(deviceObject);
01797
if (deviceNode) {
01798
01799
01800
01801
01802
01803
if (!(DriverObject->Flags &
DRVO_BUILTIN_DRIVER)) {
01804
IopDeleteLegacyKey(DriverObject);
01805 }
01806
01807
01808
01809
01810
01811 status =
PpCreateLegacyDeviceIds(
01812 deviceObject,
01813 ((DriverObject->Flags & DRVO_BUILTIN_DRIVER) ?
01814 &driverName : serviceName),
01815 ResourceList);
01816
01817
if(!
NT_SUCCESS(status)) {
01818
goto exit;
01819 }
01820
01821
01822
01823
01824
01825
01826
if (DriverObject->Flags &
DRVO_BUILTIN_DRIVER) {
01827 length = _snwprintf(buffer,
sizeof(buffer) /
sizeof(WCHAR), L
"ROOT\\%s", driverName.Buffer);
01828 }
else {
01829 length = _snwprintf(buffer,
sizeof(buffer) /
sizeof(WCHAR), L
"ROOT\\%s", serviceName->Buffer);
01830 }
01831 deviceName.MaximumLength =
sizeof(buffer);
01832
ASSERT(length <=
sizeof(buffer) - 10);
01833 deviceName.Length = (
USHORT)(length *
sizeof(WCHAR));
01834 deviceName.Buffer = buffer;
01835
01836
KeEnterCriticalRegion();
01837
ExAcquireResourceShared(&PpRegistryDeviceResource, TRUE);
01838
01839 status =
IopOpenRegistryKeyEx( &enumHandle,
01840 NULL,
01841 &CmRegistryMachineSystemCurrentControlSetEnumName,
01842 KEY_ALL_ACCESS
01843 );
01844
if (!
NT_SUCCESS(status)) {
01845
goto exit;
01846 }
01847
01848 status =
IopCreateRegistryKeyEx( &handle1,
01849 enumHandle,
01850 &deviceName,
01851 KEY_ALL_ACCESS,
01852 REG_OPTION_NON_VOLATILE,
01853 &disposition
01854 );
01855
01856
if (
NT_SUCCESS(status)) {
01857 deviceName.Buffer[deviceName.Length /
sizeof(WCHAR)] =
01858 OBJ_NAME_PATH_SEPARATOR;
01859 deviceName.Length +=
sizeof(WCHAR);
01860
if (disposition != REG_CREATED_NEW_KEY) {
01861
while (
TRUE) {
01862 PiUlongToInstanceKeyUnicodeString(&instanceName,
01863 buffer + deviceName.Length /
sizeof(WCHAR),
01864
sizeof(buffer) - deviceName.Length,
01865 i
01866 );
01867 status =
IopCreateRegistryKeyEx( &handle,
01868 handle1,
01869 &instanceName,
01870 KEY_ALL_ACCESS,
01871 REG_OPTION_NON_VOLATILE,
01872 &disposition
01873 );
01874
if (
NT_SUCCESS(status)) {
01875
if (disposition == REG_CREATED_NEW_KEY) {
01876 ZwClose(handle1);
01877
break;
01878 }
else {
01879
if (
IopIsReportedAlready(handle, serviceName, ResourceList)) {
01880
01881
01882
01883
01884
01885
RtlInitUnicodeString(&unicodeName, REGSTR_KEY_LOG_CONF);
01886 status =
IopCreateRegistryKeyEx( &logConfHandle,
01887 handle,
01888 &unicodeName,
01889 KEY_ALL_ACCESS,
01890 REG_OPTION_NON_VOLATILE,
01891 NULL
01892 );
01893
if (
NT_SUCCESS(status)) {
01894
01895
01896
01897
01898
01899
if (ResourceList) {
01900
RtlInitUnicodeString(&unicodeName, REGSTR_VAL_BOOTCONFIG);
01901 ZwSetValueKey(
01902 logConfHandle,
01903 &unicodeName,
01904 TITLE_INDEX_VALUE,
01905 REG_RESOURCE_LIST,
01906 ResourceList,
01907 listSize =
IopDetermineResourceListSize(ResourceList)
01908 );
01909 }
01910
if (ResourceRequirements) {
01911
RtlInitUnicodeString(&unicodeName, REGSTR_VALUE_BASIC_CONFIG_VECTOR);
01912 ZwSetValueKey(
01913 logConfHandle,
01914 &unicodeName,
01915 TITLE_INDEX_VALUE,
01916 REG_RESOURCE_REQUIREMENTS_LIST,
01917 ResourceRequirements,
01918 ResourceRequirements->ListSize
01919 );
01920 }
01921 ZwClose(logConfHandle);
01922 }
01923
01924
ExReleaseResource(&PpRegistryDeviceResource);
01925
KeLeaveCriticalRegion();
01926
IoDeleteDevice(deviceObject);
01927 ZwClose(handle1);
01928 deviceObject =
IopDeviceObjectFromDeviceInstance (
01929 handle, NULL);
01930 ZwClose(handle);
01931 ZwClose(enumHandle);
01932
ASSERT(deviceObject);
01933
if (deviceObject ==
NULL) {
01934 status = STATUS_UNSUCCESSFUL;
01935
return status;
01936 }
01937 deviceNode = (
PDEVICE_NODE)
01938 deviceObject->
DeviceObjectExtension->
DeviceNode;
01939
goto checkResource;
01940 }
else {
01941 i++;
01942 ZwClose(handle);
01943
continue;
01944 }
01945 }
01946 }
else {
01947 ZwClose(handle1);
01948 ZwClose(enumHandle);
01949
goto exit;
01950 }
01951 }
01952 }
else {
01953
01954
01955
01956
01957
01958 PiUlongToInstanceKeyUnicodeString(&instanceName,
01959 buffer + deviceName.Length /
sizeof(WCHAR),
01960
sizeof(buffer) - deviceName.Length,
01961 i
01962 );
01963 status =
IopCreateRegistryKeyEx( &handle,
01964 handle1,
01965 &instanceName,
01966 KEY_ALL_ACCESS,
01967 REG_OPTION_NON_VOLATILE,
01968 &disposition
01969 );
01970 ZwClose(handle1);
01971
if (!
NT_SUCCESS(status)) {
01972 ZwClose(enumHandle);
01973
goto exit;
01974 }
01975
ASSERT(disposition == REG_CREATED_NEW_KEY);
01976 }
01977 }
else {
01978 ZwClose(enumHandle);
01979
goto exit;
01980 }
01981
01982 deviceName.Length += instanceName.Length;
01983
ASSERT(disposition == REG_CREATED_NEW_KEY);
01984 newlyCreated =
TRUE;
01985
01986
01987
01988
01989
01990
if (ResourceAssigned) {
01991
RtlInitUnicodeString(&unicodeName, REGSTR_VALUE_NO_RESOURCE_AT_INIT);
01992 tmpValue = 1;
01993 ZwSetValueKey(handle,
01994 &unicodeName,
01995 TITLE_INDEX_VALUE,
01996 REG_DWORD,
01997 &tmpValue,
01998
sizeof(tmpValue)
01999 );
02000 }
02001
RtlInitUnicodeString(&unicodeName, REGSTR_KEY_LOG_CONF);
02002 logConfHandle =
NULL;
02003 status =
IopCreateRegistryKeyEx( &logConfHandle,
02004 handle,
02005 &unicodeName,
02006 KEY_ALL_ACCESS,
02007 REG_OPTION_NON_VOLATILE,
02008 NULL
02009 );
02010
02011
ASSERT(status == STATUS_SUCCESS);
02012
02013
if (
NT_SUCCESS(status)) {
02014
02015
02016
02017
02018
02019
02020
if (ResourceList) {
02021
RtlInitUnicodeString(&unicodeName, REGSTR_VAL_BOOTCONFIG);
02022 ZwSetValueKey(
02023 logConfHandle,
02024 &unicodeName,
02025 TITLE_INDEX_VALUE,
02026 REG_RESOURCE_LIST,
02027 ResourceList,
02028 listSize =
IopDetermineResourceListSize(ResourceList)
02029 );
02030 }
02031
if (ResourceRequirements) {
02032
RtlInitUnicodeString(&unicodeName, REGSTR_VALUE_BASIC_CONFIG_VECTOR);
02033 ZwSetValueKey(
02034 logConfHandle,
02035 &unicodeName,
02036 TITLE_INDEX_VALUE,
02037 REG_RESOURCE_REQUIREMENTS_LIST,
02038 ResourceRequirements,
02039 ResourceRequirements->ListSize
02040 );
02041 }
02042
02043 }
02044
02045
RtlInitUnicodeString(&unicodeName, REGSTR_VALUE_CONFIG_FLAGS);
02046 tmpValue = CONFIGFLAG_FINISH_INSTALL;
02047 ZwSetValueKey(handle,
02048 &unicodeName,
02049 TITLE_INDEX_VALUE,
02050 REG_DWORD,
02051 &tmpValue,
02052
sizeof(tmpValue)
02053 );
02054
02055 PiWstrToUnicodeString(&unicodeName, REGSTR_VALUE_LEGACY);
02056 tmpValue = 0;
02057 ZwSetValueKey(
02058 handle,
02059 &unicodeName,
02060 TITLE_INDEX_VALUE,
02061 REG_DWORD,
02062 &tmpValue,
02063
sizeof(ULONG)
02064 );
02065
02066
RtlInitUnicodeString(&unicodeName, REGSTR_KEY_CONTROL);
02067 controlHandle =
NULL;
02068
IopCreateRegistryKeyEx( &controlHandle,
02069 handle,
02070 &unicodeName,
02071 KEY_ALL_ACCESS,
02072 REG_OPTION_VOLATILE,
02073 NULL
02074 );
02075
02076
ASSERT(status == STATUS_SUCCESS);
02077
02078
if (
NT_SUCCESS(status)) {
02079
02080
02081
02082
02083
02084 PiWstrToUnicodeString(&unicodeName, REGSTR_VALUE_DEVICE_REFERENCE);
02085 status = ZwSetValueKey(controlHandle,
02086 &unicodeName,
02087 TITLE_INDEX_VALUE,
02088 REG_DWORD,
02089 (PULONG_PTR)&deviceObject,
02090
sizeof(ULONG_PTR)
02091 );
02092 PiWstrToUnicodeString(&unicodeName, REGSTR_VALUE_DEVICE_REPORTED);
02093 tmpValue = 1;
02094 status = ZwSetValueKey(controlHandle,
02095 &unicodeName,
02096 TITLE_INDEX_VALUE,
02097 REG_DWORD,
02098 &tmpValue,
02099
sizeof(ULONG)
02100 );
02101 status = ZwSetValueKey(handle,
02102 &unicodeName,
02103 TITLE_INDEX_VALUE,
02104 REG_DWORD,
02105 &tmpValue,
02106
sizeof(ULONG)
02107 );
02108
02109
02110 }
02111
02112 ZwClose(enumHandle);
02113
02114
02115
02116
02117
02118
02119 PiWstrToUnicodeString(&unicodeName, REGSTR_VALUE_SERVICE);
02120 p = (PWSTR)
ExAllocatePool(PagedPool, serviceName->Length +
sizeof(UNICODE_NULL));
02121
if (!p) {
02122
goto CleanupRegistry;
02123 }
02124 RtlMoveMemory(p, serviceName->Buffer, serviceName->Length);
02125 p[serviceName->Length /
sizeof (WCHAR)] = UNICODE_NULL;
02126 ZwSetValueKey(
02127 handle,
02128 &unicodeName,
02129 TITLE_INDEX_VALUE,
02130 REG_SZ,
02131 p,
02132 serviceName->Length +
sizeof(UNICODE_NULL)
02133 );
02134
if (DriverObject->Flags &
DRVO_BUILTIN_DRIVER) {
02135 deviceNode->
ServiceName = *serviceName;
02136 }
else {
02137
ExFreePool(p);
02138 }
02139
02140
ExReleaseResource(&PpRegistryDeviceResource);
02141
KeLeaveCriticalRegion();
02142
02143
02144
02145
02146
02147
02148
02149
02150
02151
if (!(DriverObject->Flags &
DRVO_BUILTIN_DRIVER)) {
02152
PpDeviceRegistration( &deviceName,
02153 TRUE,
02154 &deviceNode->
ServiceName
02155 );
02156 }
02157
02158
IopConcatenateUnicodeStrings(&deviceNode->
InstancePath, &deviceName, NULL);
02159
02160 deviceNode->
Flags =
DNF_MADEUP +
DNF_ENUMERATED +
DNF_PROCESSED;
02161
02162
IopInsertTreeDeviceNode(IopRootDeviceNode, deviceNode);
02163
02164
02165
02166
02167
02168
ObReferenceObject(deviceObject);
02169
02170
IopNotifySetupDeviceArrival(deviceObject, NULL, FALSE);
02171
02172
goto checkResource;
02173 }
else {
02174
IoDeleteDevice(deviceObject);
02175 status = STATUS_INSUFFICIENT_RESOURCES;
02176 }
02177 }
02178
return status;
02179 checkResource:
02180
02181
02182
02183
02184
02185
02186
02187
if (ResourceAssigned) {
02188
02189
02190
02191
02192
02193
02194
02195
02196 deviceNode->
Flags |=
DNF_NO_RESOURCE_REQUIRED;
02197
if (ResourceList) {
02198
02199
02200
02201
02202
02203 listSize =
IopDetermineResourceListSize(ResourceList);
02204
IopWriteAllocatedResourcesToRegistry (deviceNode, ResourceList, listSize);
02205 }
02206 }
else {
02207 BOOLEAN conflict;
02208
02209
if (ResourceList && ResourceList->Count && ResourceList->List[0].PartialResourceList.Count) {
02210
if (listSize == 0) {
02211 listSize =
IopDetermineResourceListSize(ResourceList);
02212 }
02213 cmResource = (PCM_RESOURCE_LIST)
ExAllocatePool(PagedPool, listSize);
02214
if (cmResource) {
02215 RtlCopyMemory(cmResource, ResourceList, listSize);
02216
RtlInitUnicodeString(&unicodeName, PNPMGR_STR_PNP_MANAGER);
02217 status =
IoReportResourceUsageInternal(
02218 ArbiterRequestLegacyReported,
02219 &unicodeName,
02220 IoPnpDriverObject,
02221 NULL,
02222 0,
02223 deviceNode->
PhysicalDeviceObject,
02224
02225 cmResource,
02226 listSize,
02227 FALSE,
02228 &conflict
02229 );
02230
ExFreePool(cmResource);
02231
if (!
NT_SUCCESS(status) || conflict) {
02232 status = STATUS_CONFLICTING_ADDRESSES;
02233
IopSetDevNodeProblem(deviceNode, CM_PROB_NORMAL_CONFLICT);
02234 }
02235 }
else {
02236 status = STATUS_INSUFFICIENT_RESOURCES;
02237
IopSetDevNodeProblem(deviceNode, CM_PROB_OUT_OF_MEMORY);
02238 }
02239 }
else {
02240
ASSERT(ResourceRequirements == NULL);
02241 deviceNode->
Flags |=
DNF_NO_RESOURCE_REQUIRED;
02242 }
02243 }
02244
02245
if (
NT_SUCCESS(status)) {
02246
02247
IopDoDeferredSetInterfaceState(deviceNode);
02248
02249 deviceNode->
Flags |=
DNF_STARTED |
DNF_ADDED |
DNF_NEED_ENUMERATION_ONLY |
DNF_NEED_QUERY_IDS;
02250 *DeviceObject = deviceObject;
02251
if (newlyCreated) {
02252
if (controlHandle) {
02253 ZwClose(controlHandle);
02254 }
02255
if (logConfHandle) {
02256 ZwClose(logConfHandle);
02257 }
02258 ZwClose(handle);
02259 }
02260
return status;
02261
02262 }
02263 CleanupRegistry:
02264
IopReleaseDeviceResources(deviceNode, FALSE);
02265
if (newlyCreated) {
02266
IoDeleteDevice(deviceObject);
02267
if (controlHandle) {
02268 ZwDeleteKey(controlHandle);
02269 }
02270
if (logConfHandle) {
02271 ZwDeleteKey(logConfHandle);
02272 }
02273
if (handle) {
02274 ZwDeleteKey(handle);
02275 }
02276 }
02277
return status;
02278
exit:
02279
ExReleaseResource(&PpRegistryDeviceResource);
02280
KeLeaveCriticalRegion();
02281
IoDeleteDevice(*DeviceObject);
02282
return status;
02283 }