ReactOS 0.4.15-dev-8344-g0574987
pnp.c
Go to the documentation of this file.
1/* Copyright (c) Mark Harmstone 2016-17
2 *
3 * This file is part of WinBtrfs.
4 *
5 * WinBtrfs is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public Licence as published by
7 * the Free Software Foundation, either version 3 of the Licence, or
8 * (at your option) any later version.
9 *
10 * WinBtrfs is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public Licence for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public Licence
16 * along with WinBtrfs. If not, see <http://www.gnu.org/licenses/>. */
17
18#include "btrfs_drv.h"
19
21extern LIST_ENTRY pdo_list;
22
24 device_extension* Vcb = DeviceObject->DeviceExtension;
26
27 // We might be going away imminently - do a flush so we're not caught out
28
29 ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
30
31 if (Vcb->root_fileref && Vcb->root_fileref->fcb && (Vcb->root_fileref->open_count > 0 || has_open_children(Vcb->root_fileref))) {
32 ExReleaseResourceLite(&Vcb->tree_lock);
34 }
35
36 if (Vcb->need_write && !Vcb->readonly) {
38
40
41 if (!NT_SUCCESS(Status)) {
42 ERR("do_write returned %08lx\n", Status);
43 ExReleaseResourceLite(&Vcb->tree_lock);
44 return Status;
45 }
46 }
47
48 ExReleaseResourceLite(&Vcb->tree_lock);
49
51}
52
54 device_extension* Vcb = DeviceObject->DeviceExtension;
56
57 if (DeviceObject->Vpb->Flags & VPB_MOUNTED) {
59 if (!NT_SUCCESS(Status)) {
60 WARN("FsRtlNotifyVolumeEvent returned %08lx\n", Status);
61 }
62
63 if (Vcb->vde)
64 Vcb->vde->mounted_device = NULL;
65
66 ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
67 Vcb->removing = true;
68 ExReleaseResourceLite(&Vcb->tree_lock);
69
70 if (Vcb->open_files == 0)
71 uninit(Vcb);
72 }
73
74 return STATUS_SUCCESS;
75}
76
78 device_extension* Vcb = DeviceObject->DeviceExtension;
79
80 TRACE("(%p, %p)\n", DeviceObject, Irp);
81
82 UNUSED(Irp);
83
84 if (DeviceObject->Vpb->Flags & VPB_MOUNTED) {
85 ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
86
87 if (Vcb->vde)
88 Vcb->vde->mounted_device = NULL;
89
90 Vcb->removing = true;
91
92 ExReleaseResourceLite(&Vcb->tree_lock);
93
94 if (Vcb->open_files == 0)
95 uninit(Vcb);
96 }
97
98 return STATUS_SUCCESS;
99}
100
104
105 dc->UniqueID = true;
106 dc->SilentInstall = true;
107
108 return STATUS_SUCCESS;
109}
110
113 ULONG num_children;
114 LIST_ENTRY* le;
115 ULONG drsize, i;
117
119
120 num_children = 0;
121
122 le = pdo_list.Flink;
123 while (le != &pdo_list) {
125
126 if (!pdode->dont_report)
127 num_children++;
128
129 le = le->Flink;
130 }
131
132 drsize = offsetof(DEVICE_RELATIONS, Objects[0]) + (num_children * sizeof(PDEVICE_OBJECT));
134
135 if (!dr) {
136 ERR("out of memory\n");
138 goto end;
139 }
140
141 dr->Count = num_children;
142
143 i = 0;
144 le = pdo_list.Flink;
145 while (le != &pdo_list) {
147
148 if (!pdode->dont_report) {
149 ObReferenceObject(pdode->pdo);
150 dr->Objects[i] = pdode->pdo;
151 i++;
152 }
153
154 le = le->Flink;
155 }
156
157 Irp->IoStatus.Information = (ULONG_PTR)dr;
158
160
161end:
163
164 return Status;
165}
166
168 WCHAR* out;
169
170 static const WCHAR ids[] = L"ROOT\\btrfs\0";
171
173 if (!out) {
174 ERR("out of memory\n");
176 }
177
178 RtlCopyMemory(out, ids, sizeof(ids));
179
180 Irp->IoStatus.Information = (ULONG_PTR)out;
181
182 return STATUS_SUCCESS;
183}
184
186 NTSTATUS Status = Irp->IoStatus.Status;
188 bool handled = false;
189
190 switch (IrpSp->MinorFunction) {
196 handled = true;
197 break;
198
201 handled = true;
202 break;
203
206 handled = true;
207 break;
208
211 break;
212
214 handled = true;
215 break;
216
217 case IRP_MN_QUERY_ID:
219 break;
220
222 handled = true;
223 break;
224 }
225
226 if (!NT_SUCCESS(Status) && handled) {
227 Irp->IoStatus.Status = Status;
229
230 return Status;
231 }
232
233 Irp->IoStatus.Status = Status;
234
236 return IoCallDriver(bde->attached_device, Irp);
237}
238
240 WCHAR name[100], *noff, *out;
241 int i;
242
243 static const WCHAR pref[] = L"Btrfs\\";
244
245 RtlCopyMemory(name, pref, sizeof(pref) - sizeof(WCHAR));
246
247 noff = &name[(sizeof(pref) / sizeof(WCHAR)) - 1];
248 for (i = 0; i < 16; i++) {
249 *noff = hex_digit(pdode->uuid.uuid[i] >> 4); noff++;
250 *noff = hex_digit(pdode->uuid.uuid[i] & 0xf); noff++;
251
252 if (i == 3 || i == 5 || i == 7 || i == 9) {
253 *noff = '-';
254 noff++;
255 }
256 }
257 *noff = 0;
258
260 if (!out) {
261 ERR("out of memory\n");
263 }
264
265 RtlCopyMemory(out, name, (wcslen(name) + 1) * sizeof(WCHAR));
266
267 Irp->IoStatus.Information = (ULONG_PTR)out;
268
269 return STATUS_SUCCESS;
270}
271
273 WCHAR* out;
274
275 static const WCHAR ids[] = L"BtrfsVolume\0";
276
278 if (!out) {
279 ERR("out of memory\n");
281 }
282
283 RtlCopyMemory(out, ids, sizeof(ids));
284
285 Irp->IoStatus.Information = (ULONG_PTR)out;
286
287 return STATUS_SUCCESS;
288}
289
292
293 switch (IrpSp->Parameters.QueryId.IdType) {
294 case BusQueryDeviceID:
295 TRACE("BusQueryDeviceID\n");
296 return pdo_query_device_id(pdode, Irp);
297
299 TRACE("BusQueryHardwareIDs\n");
301
302 default:
303 break;
304 }
305
306 return Irp->IoStatus.Status;
307}
308
309typedef struct {
314
315_Function_class_(IO_COMPLETION_ROUTINE)
316static NTSTATUS __stdcall device_usage_completion(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID conptr) {
318
320
321 context->Status = Irp->IoStatus.Status;
322
323 KeSetEvent(&context->Event, 0, false);
324
326}
327
330 LIST_ENTRY* le;
331
332 TRACE("(%p, %p)\n", pdode, Irp);
333
335
336 le = pdode->children.Flink;
337
338 while (le != &pdode->children) {
340
341 if (vc->devobj) {
342 PIRP Irp2;
343 PIO_STACK_LOCATION IrpSp2;
345
346 Irp2 = IoAllocateIrp(vc->devobj->StackSize, false);
347 if (!Irp2) {
348 ERR("out of memory\n");
351 }
352
353 IrpSp2 = IoGetNextIrpStackLocation(Irp2);
354 IrpSp2->MajorFunction = IRP_MJ_PNP;
357 IrpSp2->FileObject = vc->fileobj;
358
359 context.iosb.Status = STATUS_SUCCESS;
360 Irp2->UserIosb = &context.iosb;
361
363 Irp2->UserEvent = &context.Event;
364
365 IoSetCompletionRoutine(Irp2, device_usage_completion, &context, true, true, true);
366
367 context.Status = IoCallDriver(vc->devobj, Irp2);
368
369 if (context.Status == STATUS_PENDING)
371
372 if (!NT_SUCCESS(context.Status)) {
373 ERR("IoCallDriver returned %08lx\n", context.Status);
375 return context.Status;
376 }
377 }
378
379 le = le->Flink;
380 }
381
383
384 return STATUS_SUCCESS;
385}
386
389 PDEVICE_RELATIONS device_relations;
390
392 return Irp->IoStatus.Status;
393
394 device_relations = ExAllocatePoolWithTag(PagedPool, sizeof(DEVICE_RELATIONS), ALLOC_TAG);
395 if (!device_relations) {
396 ERR("out of memory\n");
398 }
399
400 device_relations->Count = 1;
401 device_relations->Objects[0] = pdo;
402
404
405 Irp->IoStatus.Information = (ULONG_PTR)device_relations;
406
407 return STATUS_SUCCESS;
408}
409
413
414 switch (IrpSp->MinorFunction) {
415 case IRP_MN_QUERY_ID:
416 return pdo_query_id(pdode, Irp);
417
422 return STATUS_SUCCESS;
423
425 return STATUS_UNSUCCESSFUL;
426
428 return pdo_device_usage_notification(pdode, Irp);
429
431 return pdo_query_device_relations(pdo, Irp);
432 }
433
434 return Irp->IoStatus.Status;
435}
436
439 device_extension* Vcb = DeviceObject->DeviceExtension;
440
441 if (IrpSp->Parameters.UsageNotification.InPath) {
442 switch (IrpSp->Parameters.UsageNotification.Type) {
447 break;
448
449 default:
450 break;
451 }
452 }
453
455 return IoCallDriver(Vcb->Vpb->RealDevice, Irp);
456}
457
462 device_extension* Vcb = DeviceObject->DeviceExtension;
464 bool top_level;
465
467
468 top_level = is_top_level(Irp);
469
470 if (Vcb && Vcb->type == VCB_TYPE_BUS) {
471 Status = bus_pnp(DeviceObject->DeviceExtension, Irp);
472 goto exit;
473 } else if (Vcb && Vcb->type == VCB_TYPE_VOLUME) {
474 volume_device_extension* vde = DeviceObject->DeviceExtension;
477 goto exit;
478 } else if (Vcb && Vcb->type == VCB_TYPE_PDO) {
480 goto end;
481 } else if (!Vcb || Vcb->type != VCB_TYPE_FS) {
483 goto end;
484 }
485
487
488 switch (IrpSp->MinorFunction) {
491 break;
492
495 break;
496
499 break;
500
503 break;
504
507 goto exit;
508
509 default:
510 TRACE("passing minor function 0x%x on\n", IrpSp->MinorFunction);
511
513 Status = IoCallDriver(Vcb->Vpb->RealDevice, Irp);
514 goto exit;
515 }
516
517end:
518 Irp->IoStatus.Status = Status;
519
521
522exit:
523 TRACE("returning %08lx\n", Status);
524
525 if (top_level)
527
529
530 return Status;
531}
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
LONG NTSTATUS
Definition: precomp.h:26
#define WARN(fmt,...)
Definition: precomp.h:61
#define ERR(fmt,...)
Definition: precomp.h:57
#define VCB_TYPE_VOLUME
Definition: btrfs_drv.h:689
#define _Dispatch_type_(a)
Definition: btrfs_drv.h:204
#define VCB_TYPE_FS
Definition: btrfs_drv.h:687
#define ALLOC_TAG
Definition: btrfs_drv.h:87
#define hex_digit(c)
Definition: btrfs_drv.h:1748
bool has_open_children(file_ref *fileref)
Definition: fileinfo.c:442
#define UNUSED(x)
Definition: btrfs_drv.h:82
NTSTATUS do_write(device_extension *Vcb, PIRP Irp)
Definition: flushthread.c:7877
#define VCB_TYPE_PDO
Definition: btrfs_drv.h:690
#define VCB_TYPE_BUS
Definition: btrfs_drv.h:691
NTSTATUS NTSTATUS bool bool void free_trees(device_extension *Vcb) __attribute__((nonnull(1)))
#define IRP_MJ_PNP
Definition: cdrw_usr.h:52
_In_ PIRP Irp
Definition: csq.h:116
#define NULL
Definition: types.h:112
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
bool is_top_level(_In_ PIRP Irp)
Definition: btrfs.c:278
uint32_t no_pnp
Definition: btrfs.c:87
void uninit(_In_ device_extension *Vcb)
Definition: btrfs.c:2001
static NTSTATUS bus_query_device_relations(PIRP Irp)
Definition: pnp.c:111
static NTSTATUS pdo_query_device_id(pdo_device_extension *pdode, PIRP Irp)
Definition: pnp.c:239
NTSTATUS pnp_surprise_removal(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Definition: pnp.c:77
static NTSTATUS bus_query_hardware_ids(PIRP Irp)
Definition: pnp.c:167
static NTSTATUS pdo_pnp(PDEVICE_OBJECT pdo, PIRP Irp)
Definition: pnp.c:410
static NTSTATUS pdo_device_usage_notification(pdo_device_extension *pdode, PIRP Irp)
Definition: pnp.c:328
static NTSTATUS pdo_query_hardware_ids(PIRP Irp)
Definition: pnp.c:272
static NTSTATUS bus_pnp(bus_device_extension *bde, PIRP Irp)
Definition: pnp.c:185
NTSTATUS pnp_query_remove_device(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Definition: pnp.c:23
LIST_ENTRY pdo_list
Definition: btrfs.c:104
ERESOURCE pdo_list_lock
Definition: btrfs.c:103
static NTSTATUS bus_query_capabilities(PIRP Irp)
Definition: pnp.c:101
static NTSTATUS pdo_query_device_relations(PDEVICE_OBJECT pdo, PIRP Irp)
Definition: pnp.c:387
static NTSTATUS pdo_query_id(pdo_device_extension *pdode, PIRP Irp)
Definition: pnp.c:290
static NTSTATUS pnp_device_usage_notification(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Definition: pnp.c:437
static NTSTATUS pnp_remove_device(PDEVICE_OBJECT DeviceObject)
Definition: pnp.c:53
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4137
#define ULONG_PTR
Definition: config.h:101
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
struct _DEVICE_OBJECT * PDEVICE_OBJECT
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
#define ExAcquireResourceExclusiveLite(res, wait)
Definition: env_spec_w32.h:615
ULONG ERESOURCE
Definition: env_spec_w32.h:594
#define ExAcquireResourceSharedLite(res, wait)
Definition: env_spec_w32.h:621
#define PagedPool
Definition: env_spec_w32.h:308
#define FsRtlEnterFileSystem
#define FsRtlExitFileSystem
Status
Definition: gdiplustypes.h:25
GLuint GLuint end
Definition: gl.h:1545
GLuint * ids
Definition: glext.h:5907
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define IoSetCompletionRoutine(_Irp, _CompletionRoutine, _Context, _InvokeOnSuccess, _InvokeOnError, _InvokeOnCancel)
Definition: irp.cpp:490
static const WCHAR dc[]
#define _Function_class_(x)
Definition: ms_sal.h:2946
#define KernelMode
Definition: asm.h:34
DRIVER_DISPATCH(nfs41_FsdDispatch)
@ NotificationEvent
#define FSRTL_VOLUME_DISMOUNT
Definition: ntifs_ex.h:439
#define IRP_MN_SURPRISE_REMOVAL
Definition: ntifs_ex.h:408
#define IoSkipCurrentIrpStackLocation(Irp)
Definition: ntifs_ex.h:421
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1822
NTSTATUS NTAPI FsRtlNotifyVolumeEvent(IN PFILE_OBJECT FileObject, IN ULONG EventCode)
Definition: pnp.c:38
#define IoCompleteRequest
Definition: irp.c:1240
PIRP NTAPI IoAllocateIrp(IN CCHAR StackSize, IN BOOLEAN ChargeQuota)
Definition: irp.c:615
#define IoCallDriver
Definition: irp.c:1225
VOID NTAPI IoSetTopLevelIrp(IN PIRP Irp)
Definition: irp.c:2000
#define STATUS_PENDING
Definition: ntstatus.h:82
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:239
#define L(x)
Definition: ntvdm.h:50
#define Vcb
Definition: cdprocs.h:1415
static FILE * out
Definition: regtests2xml.c:44
#define offsetof(TYPE, MEMBER)
#define exit(n)
Definition: config.h:202
#define STATUS_MORE_PROCESSING_REQUIRED
Definition: shellext.h:68
#define STATUS_SUCCESS
Definition: shellext.h:65
#define TRACE(s)
Definition: solgame.cpp:4
uint8_t uuid[16]
Definition: btrfs.h:140
PVOID DeviceExtension
Definition: env_spec_w32.h:418
PDEVICE_OBJECT Objects[1]
Definition: iotypes.h:2163
struct _IO_STACK_LOCATION::@3992::@4019 DeviceCapabilities
union _IO_STACK_LOCATION::@1574 Parameters
PFILE_OBJECT FileObject
Definition: iotypes.h:3169
struct _IO_STACK_LOCATION::@3992::@4025 UsageNotification
struct _IO_STACK_LOCATION::@3992::@4023 QueryId
struct _IO_STACK_LOCATION::@3992::@4017 QueryDeviceRelations
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
PDEVICE_OBJECT attached_device
Definition: btrfs_drv.h:880
PDEVICE_OBJECT attached_device
Definition: btrfs_drv.h:849
Definition: http.c:7252
IO_STATUS_BLOCK iosb
Definition: pnp.c:310
KEVENT Event
Definition: pnp.c:311
NTSTATUS Status
Definition: pnp.c:312
Definition: list.h:27
Definition: name.c:39
ERESOURCE child_lock
Definition: btrfs_drv.h:896
PDEVICE_OBJECT pdo
Definition: btrfs_drv.h:890
LIST_ENTRY children
Definition: btrfs_drv.h:897
PFILE_OBJECT fileobj
Definition: btrfs_drv.h:858
PDEVICE_OBJECT devobj
Definition: btrfs_drv.h:857
#define __stdcall
Definition: typedefs.h:25
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2695
#define IoAdjustPagingPathCount(_Count, _Increment)
@ BusRelations
Definition: iotypes.h:2152
@ TargetDeviceRelation
Definition: iotypes.h:2156
#define VPB_MOUNTED
Definition: iotypes.h:1807
#define IO_NO_INCREMENT
Definition: iotypes.h:598
#define IRP_MN_START_DEVICE
#define IRP_MN_DEVICE_USAGE_NOTIFICATION
#define IRP_MN_QUERY_ID
#define IRP_MN_REMOVE_DEVICE
#define IRP_MN_QUERY_DEVICE_RELATIONS
#define IRP_MN_QUERY_CAPABILITIES
* PDEVICE_CAPABILITIES
Definition: iotypes.h:965
#define IRP_MN_CANCEL_REMOVE_DEVICE
@ BusQueryDeviceID
Definition: iotypes.h:2936
@ BusQueryHardwareIDs
Definition: iotypes.h:2937
@ DeviceUsageTypeHibernation
Definition: iotypes.h:1171
@ DeviceUsageTypeDumpFile
Definition: iotypes.h:1172
@ DeviceUsageTypePaging
Definition: iotypes.h:1170
#define IRP_MN_QUERY_REMOVE_DEVICE
@ Executive
Definition: ketypes.h:415
#define ObReferenceObject
Definition: obfuncs.h:204
__wchar_t WCHAR
Definition: xmlstorage.h:180