00051 {
00052 PLIST_ENTRY link;
00053
PPO_DEVICE_NOTIFY notify;
00054
PDEVICE_NODE node;
00055
PDEVICE_NODE parent;
00056 ULONG noLists, listIndex;
00057 PLIST_ENTRY notifyLists;
00058 LONG maxLevel, level;
00059 UCHAR orderLevel;
00060
PDEVICE_OBJECT nonPaged;
00061
00062
00063
00064
00065
00066
IopAcquireDeviceTreeLock();
00067 RtlZeroMemory (Order,
sizeof (*Order));
00068 Order->DevNodeSequence =
IoDeviceNodeTreeSequence;
00069 InitializeListHead (&Order->Partial);
00070 InitializeListHead (&Order->Rebase);
00071
00072
00073
00074
00075
00076
00077 level = -1;
00078 node =
IopRootDeviceNode;
00079
while (node->
Child) {
00080 node = node->
Child;
00081 level += 1;
00082 }
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100 maxLevel = level;
00101
while (node !=
IopRootDeviceNode) {
00102 notify =
ExAllocatePoolWithTag (
00103 NonPagedPool,
00104
sizeof(
PO_DEVICE_NOTIFY),
00105 IOP_DPWR_TAG
00106 );
00107
00108
if (!notify) {
00109
return STATUS_INSUFFICIENT_RESOURCES;
00110 }
00111
00112 RtlZeroMemory (notify,
sizeof(
PO_DEVICE_NOTIFY));
00113
ASSERT(node->
Notify == NULL) ;
00114 node->
Notify = notify;
00115 notify->
Node = node;
00116 notify->
DeviceObject = node->
PhysicalDeviceObject;
00117 notify->
TargetDevice =
IoGetAttachedDevice(node->
PhysicalDeviceObject);
00118 notify->
DriverName =
IopCaptureObjectName(notify->
TargetDevice->
DriverObject);
00119 notify->
DeviceName =
IopCaptureObjectName(notify->
TargetDevice);
00120
ObReferenceObject (notify->
DeviceObject);
00121
ObReferenceObject (notify->
TargetDevice);
00122
00123 orderLevel = 0;
00124
00125
if (notify->
TargetDevice->
DeviceType != FILE_DEVICE_SCREEN &&
00126 notify->
TargetDevice->
DeviceType != FILE_DEVICE_VIDEO) {
00127 orderLevel |=
PO_ORDER_NOT_VIDEO;
00128 }
00129
00130
if (notify->
TargetDevice->
Flags &
DO_POWER_PAGABLE) {
00131 orderLevel |=
PO_ORDER_PAGABLE;
00132 }
00133
00134 notify->
OrderLevel = orderLevel;
00135 notify->
NodeLevel = level;
00136
00137
00138
00139
00140
00141
00142
00143
if (level == 0 &&
00144 node->
InterfaceType != Internal &&
00145 !(node->
Flags &
DNF_HAL_NODE)) {
00146
00147 InsertTailList (&Order->Rebase, ¬ify->
Link);
00148 }
else {
00149 InsertTailList (&Order->Partial, ¬ify->
Link);
00150 }
00151
00152
00153
00154
00155
00156
if (node->
Sibling) {
00157 node = node->
Sibling;
00158
while (node->
Child) {
00159 node = node->
Child;
00160 level += 1;
00161
if (level > maxLevel) {
00162 maxLevel = level;
00163 }
00164 }
00165
00166 }
else {
00167 node = node->
Parent;
00168 level -= 1;
00169 }
00170 }
00171
00172
00173
00174
00175
00176
while (!IsListEmpty(&Order->Rebase)) {
00177 link = Order->Rebase.Flink;
00178 notify = CONTAINING_RECORD (link,
PO_DEVICE_NOTIFY, Link);
00179 RemoveEntryList (¬ify->
Link);
00180 InsertTailList (&Order->Partial, ¬ify->
Link);
00181
00182
00183
00184
00185
00186 node = notify->
Node;
00187 notify->
OrderLevel |=
PO_ORDER_ROOT_ENUM;
00188
00189
00190
00191
00192
00193 parent = node;
00194
while (node->Child) {
00195 node = node->
Child;
00196 }
00197
00198
while (node != parent) {
00199 notify = node->Notify;
00200
if (notify) {
00201 notify->
OrderLevel |=
PO_ORDER_ROOT_ENUM;
00202 }
00203
00204
00205
if (node->Sibling) {
00206 node = node->Sibling;
00207
while (node->Child) {
00208 node = node->Child;
00209 }
00210 }
else {
00211 node = node->Parent;
00212 }
00213 }
00214 }
00215
00216
00217
00218
00219
00220 maxLevel = maxLevel + 1;
00221 noLists = maxLevel * (
PO_ORDER_MAXIMUM + 1);
00222 notifyLists =
ExAllocatePoolWithTag (
00223 NonPagedPool,
00224
sizeof(LIST_ENTRY) * noLists,
00225 IOP_DPWR_TAG
00226 );
00227
00228
if (!notifyLists) {
00229
return STATUS_INSUFFICIENT_RESOURCES;
00230 }
00231
00232
for (listIndex=0; listIndex < noLists; listIndex++) {
00233 InitializeListHead (¬ifyLists[listIndex]);
00234 }
00235
00236 Order->Notify = notifyLists;
00237 Order->MaxLevel = maxLevel;
00238 Order->NoLists = noLists;
00239
00240
00241
00242
00243
00244
while (!IsListEmpty(&Order->Partial)) {
00245 link = Order->Partial.Flink;
00246 notify = CONTAINING_RECORD (link,
PO_DEVICE_NOTIFY, Link);
00247 RemoveEntryList (¬ify->
Link);
00248
00249 orderLevel = notify->
OrderLevel;
00250 listIndex = orderLevel * maxLevel + notify->
NodeLevel;
00251 InsertTailList (¬ifyLists[listIndex], ¬ify->
Link);
00252
00253
00254
00255
00256
00257
00258 nonPaged =
NULL;
00259
if (!(notify->
TargetDevice->
Flags &
DO_POWER_PAGABLE)) {
00260 nonPaged = notify->
TargetDevice;
00261 }
00262
00263
if (nonPaged && (notify->
DeviceObject->
Flags &
DO_POWER_PAGABLE)) {
00264
KeBugCheckEx (
00265 DRIVER_POWER_STATE_FAILURE,
00266 0x100,
00267 (ULONG_PTR) nonPaged,
00268 (ULONG_PTR) notify->
TargetDevice,
00269 (ULONG_PTR) notify->
DeviceObject
00270 );
00271 }
00272
00273
00274
00275
00276
00277
00278
00279 node = notify->
Node;
00280
for (parent = node->
Parent;
00281 parent !=
IopRootDeviceNode;
00282 parent = parent->
Parent) {
00283
00284 notify = parent->
Notify;
00285
ASSERT (notify != NULL);
00286
if (notify->
OrderLevel <= orderLevel) {
00287
break;
00288 }
00289
00290
if (nonPaged && (
00291 (notify->
DeviceObject->
Flags &
DO_POWER_PAGABLE) ||
00292 (notify->
TargetDevice->
Flags &
DO_POWER_PAGABLE) )) {
00293
00294
KeBugCheckEx (
00295 DRIVER_POWER_STATE_FAILURE,
00296 0x100,
00297 (ULONG_PTR) nonPaged,
00298 (ULONG_PTR) notify->
TargetDevice,
00299 (ULONG_PTR) notify->
DeviceObject
00300 );
00301 }
00302
00303 RemoveEntryList (¬ify->
Link);
00304
00305 notify->
OrderLevel = orderLevel;
00306 listIndex = orderLevel * maxLevel + notify->
NodeLevel;
00307 InsertTailList (¬ifyLists[listIndex], ¬ify->
Link);
00308 }
00309 }
00310
00311 Order->WarmEjectPdoPointer = &
IopWarmEjectPdo;
00312
00313
00314
00315
00316
00317
return STATUS_SUCCESS;
00318 }