1d32377deb56f5787f7f8b016aa8f4fee558cac6
[people/sha0/winvblock.git] / src / httpdisk / bus.c
1 /**
2  * Copyright (C) 2010-2011, Shao Miller <shao.miller@yrdsb.edu.on.ca>.
3  *
4  * This file is part of WinVBlock, originally derived from WinAoE.
5  *
6  * WinVBlock is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * WinVBlock is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with WinVBlock.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 /**
21  * @file
22  *
23  * HTTPDisk bus specifics.
24  */
25
26 #include <ntddk.h>
27
28 #include "portable.h"
29 #include "winvblock.h"
30 #include "debug.h"
31 #include "dummy.h"
32 #include "bus.h"
33 #include "irp.h"
34 #include "httpdisk.h"
35
36 /** From httpdisk.c */
37 extern PDRIVER_OBJECT HttpdiskDriverObj;
38
39 /** Exports. */
40 NTSTATUS STDCALL HttpdiskBusEstablish(void);
41 VOID HttpdiskBusCleanup(void);
42 DRIVER_ADD_DEVICE HttpdiskBusAttach;
43 DRIVER_DISPATCH HttpdiskBusIrp;
44
45 /** Private. */
46 static NTSTATUS STDCALL HttpdiskBusCreateFdo_(void);
47 static NTSTATUS STDCALL HttpdiskBusCreatePdo_(void);
48 static VOID HttpdiskBusDeleteFdo_(void);
49
50 /* The HTTPDisk bus. */
51 static WVL_S_BUS_T HttpdiskBus_ = {0};
52
53 /* Names for the HTTPDisk bus. */
54 #define HTTPDISK_M_BUS_NAME_ (L"\\Device\\HTTPDisk")
55 #define HTTPDISK_M_BUS_DOSNAME_ (L"\\DosDevices\\HTTPDisk")
56 static UNICODE_STRING HttpdiskBusName_ = {
57     sizeof HTTPDISK_M_BUS_NAME_ - sizeof (WCHAR),
58     sizeof HTTPDISK_M_BUS_NAME_ - sizeof (WCHAR),
59     HTTPDISK_M_BUS_NAME_
60   };
61 static UNICODE_STRING HttpdiskBusDosname_ = {
62     sizeof HTTPDISK_M_BUS_DOSNAME_ - sizeof (WCHAR),
63     sizeof HTTPDISK_M_BUS_DOSNAME_ - sizeof (WCHAR),
64     HTTPDISK_M_BUS_DOSNAME_
65   };
66
67 NTSTATUS STDCALL HttpdiskBusEstablish(void) {
68     NTSTATUS status;
69
70     /* Initialize the bus. */
71     WvlBusInit(&HttpdiskBus_);
72     HttpdiskBus_.State = WvlBusStateStarted;
73
74     status = HttpdiskBusCreateFdo_();
75     if (!NT_SUCCESS(status))
76       goto err_fdo;
77
78     status = HttpdiskBusCreatePdo_();
79     if (!NT_SUCCESS(status))
80       goto err_pdo;
81
82     DBG("Bus established.\n");
83     return STATUS_SUCCESS;
84
85     HttpdiskBusDeleteFdo_();
86     err_fdo:
87
88     /* TODO: Remove the PDO. */
89     err_pdo:
90
91     DBG("Bus not established.\n");
92     return status;
93   }
94
95 VOID HttpdiskBusCleanup(void) {
96     /*
97      * The FDO should be deleted by an IRP_MJ_PNP:IRP_MN_REMOVE_DEVICE,
98      * but just in case it isn't...
99      */
100     HttpdiskBusDeleteFdo_();
101     DBG("Cleaned up.\n");
102     return;
103   }
104
105 NTSTATUS HttpdiskBusAttach(
106     IN PDRIVER_OBJECT DriverObj,
107     IN PDEVICE_OBJECT Pdo
108   ) {
109     NTSTATUS status;
110
111     /* Do we already have our bus? */
112     if (HttpdiskBus_.Pdo) {
113         DBG(
114             "Bus PDO %p already established.  Refusing...\n",
115             HttpdiskBus_.Pdo
116           );
117         status = STATUS_NOT_SUPPORTED;
118         goto err_already_established;
119       }
120     /* Associate the bus with the PDO. */
121     HttpdiskBus_.Pdo = Pdo;
122     /* Attach the FDO to the PDO. */
123     HttpdiskBus_.LowerDeviceObject = IoAttachDeviceToDeviceStack(
124         HttpdiskBus_.Fdo,
125         Pdo
126       );
127     if (HttpdiskBus_.LowerDeviceObject == NULL) {
128         status = STATUS_NO_SUCH_DEVICE;
129         DBG("IoAttachDeviceToDeviceStack() failed!\n");
130         goto err_attach;
131       }
132
133     /* Ok! */
134     DBG("Attached bus to PDO %p.\n", Pdo);
135     return STATUS_SUCCESS;
136
137     err_attach:
138
139     err_already_established:
140
141     DBG("PDO %p not attached.\n", Pdo);
142     return status;
143   }
144
145 NTSTATUS HttpdiskBusIrp(IN PDEVICE_OBJECT DevObj, IN PIRP Irp) {
146     PIO_STACK_LOCATION io_stack_loc = IoGetCurrentIrpStackLocation(Irp);
147     UCHAR major = io_stack_loc->MajorFunction;
148     NTSTATUS status;
149
150     switch (major) {
151         case IRP_MJ_PNP:
152           status = WvlBusPnp(&HttpdiskBus_, Irp);
153           /* Is the bus still attached?  If not, it's time to stop. */
154           if (HttpdiskBus_.State == WvlBusStateDeleted)
155             HttpdiskBusDeleteFdo_();
156           return status;
157
158         case IRP_MJ_POWER:
159           return WvlBusPower(&HttpdiskBus_, Irp);
160
161         case IRP_MJ_SYSTEM_CONTROL:
162           return WvlBusSysCtl(&HttpdiskBus_, Irp);
163
164         default:
165           DBG("Unhandled major: %d\n", major);
166           break;
167       }
168     return WvlIrpComplete(Irp, 0, STATUS_NOT_SUPPORTED);
169   }
170
171 static NTSTATUS STDCALL HttpdiskBusCreateFdo_(void) {
172     NTSTATUS status;
173     HTTPDISK_SP_DEV dev;
174
175     status = IoCreateDevice(
176         HttpdiskDriverObj,
177         sizeof *dev,
178         &HttpdiskBusName_,
179         FILE_DEVICE_CONTROLLER,
180         FILE_DEVICE_SECURE_OPEN,
181         FALSE,
182         &HttpdiskBus_.Fdo
183       );
184     if (!NT_SUCCESS(status)) {
185         DBG("FDO not created.\n");
186         return status;
187       }
188
189     /* Initialize device extension. */
190     dev = HttpdiskBus_.Fdo->DeviceExtension;
191     dev->bus = TRUE;
192
193     DBG("FDO created: %p.\n", (PVOID) HttpdiskBus_.Fdo);
194     return STATUS_SUCCESS;
195   }
196
197 static NTSTATUS STDCALL HttpdiskBusCreatePdo_(void) {
198     NTSTATUS status;
199
200     /* Generate dummy IDs for the HTTPDisk bus PDO. */
201     WV_M_DUMMY_ID_GEN(
202         static const,
203         HttpdiskBusDummyIds_,
204         WVL_M_WLIT L"\\HTTPDisk",
205         L"0",
206         WVL_M_WLIT L"\\HTTPDisk\0",
207         WVL_M_WLIT L"\\HTTPDisk\0",
208         FILE_DEVICE_CONTROLLER,
209         FILE_DEVICE_SECURE_OPEN
210       );
211
212     status = WvDummyAdd(&HttpdiskBusDummyIds_.DummyIds);
213     if (!NT_SUCCESS(status)) {
214         DBG("PDO not created.\n");
215         return status;
216       }
217
218     DBG("PDO created.\n");
219     return STATUS_SUCCESS;
220   }
221
222 static VOID HttpdiskBusDeleteFdo_(void) {
223     if (!HttpdiskBus_.Fdo)
224       return;
225     IoDeleteDevice(HttpdiskBus_.Fdo);
226     DBG("FDO %p deleted.\n", (PVOID) HttpdiskBus_.Fdo);
227     HttpdiskBus_.Fdo = NULL;
228     return;
229   }