[bus] Remove WvBusFree_ and WvBusThreadFree_
[people/sha0/winvblock.git] / src / winvblock / bus / dev_ctl.c
1 /**
2  * Copyright (C) 2009-2010, Shao Miller <shao.miller@yrdsb.edu.on.ca>.
3  * Copyright 2006-2008, V.
4  * For WinAoE contact information, see http://winaoe.org/
5  *
6  * This file is part of WinVBlock, derived from WinAoE.
7  *
8  * WinVBlock is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * WinVBlock is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with WinVBlock.  If not, see <http://www.gnu.org/licenses/>.
20  */
21
22 /**
23  * @file
24  *
25  * Bus Device Control IRP handling.
26  */
27
28 #include <ntddk.h>
29
30 #include "winvblock.h"
31 #include "portable.h"
32 #include "driver.h"
33 #include "device.h"
34 #include "disk.h"
35 #include "mount.h"
36 #include "bus.h"
37 #include "debug.h"
38 #include "filedisk.h"
39
40 /* Forward declarations. */
41 static WV_F_DEV_DISPATCH WvBusDevCtlDiskDetach_;
42
43 static NTSTATUS STDCALL WvBusDevCtlDiskDetach_(
44     IN WV_SP_DEV_T dev,
45     IN PIRP irp
46   ) {
47     winvblock__uint8_ptr buffer = irp->AssociatedIrp.SystemBuffer;
48     winvblock__uint32 disk_num = *(winvblock__uint32_ptr) buffer;
49     WV_SP_DEV_T dev_walker;
50     WV_SP_DISK_T disk_walker = NULL, prev_disk_walker;
51     WV_SP_BUS_T bus;
52
53     DBG("Request to detach disk: %d\n", disk_num);
54     bus = WvBusFromDev(dev);
55     dev_walker = bus->first_child;
56     if (dev_walker != NULL)
57       disk_walker = disk__get_ptr(dev_walker);
58     prev_disk_walker = disk_walker;
59     while ((disk_walker != NULL) && (dev_walker->DevNum != disk_num)) {
60         prev_disk_walker = disk_walker;
61         dev_walker = dev_walker->next_sibling_ptr;
62         if (dev_walker != NULL)
63           disk_walker = disk__get_ptr(dev_walker);
64       }
65     if (disk_walker != NULL) {
66         if (disk_walker->BootDrive) {
67             DBG("Cannot unmount a boot drive.\n");
68             irp->IoStatus.Information = 0;
69             return STATUS_INVALID_DEVICE_REQUEST;
70           }
71         DBG("Deleting disk %d\n", dev_walker->DevNum);
72         if (disk_walker == disk__get_ptr(bus->first_child))
73           bus->first_child = dev_walker->next_sibling_ptr;
74           else {
75             prev_disk_walker->Dev->next_sibling_ptr =
76               dev_walker->next_sibling_ptr;
77           }
78         disk_walker->Unmount = TRUE;
79         dev_walker->next_sibling_ptr = NULL;
80         if (bus->PhysicalDeviceObject != NULL)
81           IoInvalidateDeviceRelations(bus->PhysicalDeviceObject, BusRelations);
82       }
83     bus->Children--;
84     irp->IoStatus.Information = 0;
85     return STATUS_SUCCESS;
86   }
87
88 NTSTATUS STDCALL WvBusDevCtlDispatch(
89     IN WV_SP_DEV_T dev,
90     IN PIRP irp,
91     IN ULONG POINTER_ALIGNMENT code
92   ) {
93     NTSTATUS status;
94
95     switch (code) {
96         case IOCTL_FILE_ATTACH:
97           status = filedisk__attach(dev, irp);
98           break;
99
100         case IOCTL_FILE_DETACH:
101           status = WvBusDevCtlDiskDetach_(dev, irp);
102           break;
103
104         default:
105           irp->IoStatus.Information = 0;
106           status = STATUS_INVALID_DEVICE_REQUEST;
107       }
108
109     irp->IoStatus.Status = status;
110     IoCompleteRequest(irp, IO_NO_INCREMENT);
111     return status;
112   }