a900c896f14524211ad82407de3a8f27b73a93f0
[people/sha0/winvblock.git] / src / winvblock / disk / 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  * Disk Device Control IRP handling.
26  */
27
28 #include <ntddk.h>
29 #include <scsi.h>
30 #include <srb.h>
31 #include <ntdddisk.h>
32 #include <ntddscsi.h>
33 #include <ntddstor.h>
34 #include <ntddvol.h>
35 #include <mountdev.h>
36
37 #include "winvblock.h"
38 #include "portable.h"
39 #include "irp.h"
40 #include "driver.h"
41 #include "device.h"
42 #include "disk.h"
43 #include "debug.h"
44
45 static NTSTATUS STDCALL storage_query_prop(
46     IN PDEVICE_OBJECT DeviceObject,
47     IN PIRP Irp,
48     IN PIO_STACK_LOCATION Stack,
49     IN struct device__type * dev_ptr,
50     OUT winvblock__bool_ptr completion_ptr
51   )
52 {
53   NTSTATUS status = STATUS_INVALID_PARAMETER;
54   PSTORAGE_PROPERTY_QUERY storage_prop_query = Irp->AssociatedIrp.SystemBuffer;
55   winvblock__uint32 copy_size;
56   disk__type_ptr disk_ptr;
57   STORAGE_ADAPTER_DESCRIPTOR storage_adapter_desc;
58   STORAGE_DEVICE_DESCRIPTOR storage_dev_desc;
59
60   disk_ptr = disk__get_ptr ( dev_ptr );
61   if ( storage_prop_query->PropertyId == StorageAdapterProperty
62        && storage_prop_query->QueryType == PropertyStandardQuery )
63     {
64       copy_size =
65         ( Stack->Parameters.DeviceIoControl.OutputBufferLength <
66           sizeof ( STORAGE_ADAPTER_DESCRIPTOR ) ? Stack->
67           Parameters.DeviceIoControl.
68           OutputBufferLength : sizeof ( STORAGE_ADAPTER_DESCRIPTOR ) );
69       storage_adapter_desc.Version = sizeof ( STORAGE_ADAPTER_DESCRIPTOR );
70       storage_adapter_desc.Size = sizeof ( STORAGE_ADAPTER_DESCRIPTOR );
71       storage_adapter_desc.MaximumTransferLength =
72         disk__max_xfer_len ( disk_ptr );
73 #if 0
74       storage_adapter_desc.MaximumTransferLength = SECTORSIZE * POOLSIZE;
75 #endif
76       storage_adapter_desc.MaximumPhysicalPages = ( winvblock__uint32 ) - 1;
77       storage_adapter_desc.AlignmentMask = 0;
78       storage_adapter_desc.AdapterUsesPio = TRUE;
79       storage_adapter_desc.AdapterScansDown = FALSE;
80       storage_adapter_desc.CommandQueueing = FALSE;
81       storage_adapter_desc.AcceleratedTransfer = FALSE;
82       storage_adapter_desc.BusType = BusTypeScsi;
83       RtlCopyMemory ( Irp->AssociatedIrp.SystemBuffer, &storage_adapter_desc,
84                       copy_size );
85       Irp->IoStatus.Information = ( ULONG_PTR ) copy_size;
86       status = STATUS_SUCCESS;
87     }
88
89   if ( storage_prop_query->PropertyId == StorageDeviceProperty
90        && storage_prop_query->QueryType == PropertyStandardQuery )
91     {
92       copy_size =
93         ( Stack->Parameters.DeviceIoControl.OutputBufferLength <
94           sizeof ( STORAGE_DEVICE_DESCRIPTOR ) ? Stack->
95           Parameters.DeviceIoControl.
96           OutputBufferLength : sizeof ( STORAGE_DEVICE_DESCRIPTOR ) );
97       storage_dev_desc.Version = sizeof ( STORAGE_DEVICE_DESCRIPTOR );
98       storage_dev_desc.Size = sizeof ( STORAGE_DEVICE_DESCRIPTOR );
99       storage_dev_desc.DeviceType = DIRECT_ACCESS_DEVICE;
100       storage_dev_desc.DeviceTypeModifier = 0;
101       storage_dev_desc.RemovableMedia = disk__removable[disk_ptr->media];
102       storage_dev_desc.CommandQueueing = FALSE;
103       storage_dev_desc.VendorIdOffset = 0;
104       storage_dev_desc.ProductIdOffset = 0;
105       storage_dev_desc.ProductRevisionOffset = 0;
106       storage_dev_desc.SerialNumberOffset = 0;
107       storage_dev_desc.BusType = BusTypeScsi;
108       storage_dev_desc.RawPropertiesLength = 0;
109       RtlCopyMemory ( Irp->AssociatedIrp.SystemBuffer, &storage_dev_desc,
110                       copy_size );
111       Irp->IoStatus.Information = ( ULONG_PTR ) copy_size;
112       status = STATUS_SUCCESS;
113     }
114
115   if ( status == STATUS_INVALID_PARAMETER )
116     {
117       DBG ( "!!Invalid IOCTL_STORAGE_QUERY_PROPERTY "
118             "(PropertyId: %08x / QueryType: %08x)!!\n",
119             storage_prop_query->PropertyId, storage_prop_query->QueryType );
120     }
121   return status;
122 }
123
124 static NTSTATUS STDCALL disk_get_drive_geom(
125     IN PDEVICE_OBJECT DeviceObject,
126     IN PIRP Irp,
127     IN PIO_STACK_LOCATION Stack,
128     IN struct device__type * dev_ptr,
129     OUT winvblock__bool_ptr completion_ptr
130   )
131 {
132   winvblock__uint32 copy_size;
133   DISK_GEOMETRY disk_geom;
134   disk__type_ptr disk_ptr;
135
136   copy_size =
137     ( Stack->Parameters.DeviceIoControl.OutputBufferLength <
138       sizeof ( DISK_GEOMETRY ) ? Stack->Parameters.DeviceIoControl.
139       OutputBufferLength : sizeof ( DISK_GEOMETRY ) );
140   disk_geom.MediaType = FixedMedia;
141   disk_ptr = disk__get_ptr ( dev_ptr );
142   disk_geom.Cylinders.QuadPart = disk_ptr->Cylinders;
143   disk_geom.TracksPerCylinder = disk_ptr->Heads;
144   disk_geom.SectorsPerTrack = disk_ptr->Sectors;
145   disk_geom.BytesPerSector = disk_ptr->SectorSize;
146   RtlCopyMemory ( Irp->AssociatedIrp.SystemBuffer, &disk_geom, copy_size );
147   Irp->IoStatus.Information = ( ULONG_PTR ) copy_size;
148   return STATUS_SUCCESS;
149 }
150
151 static NTSTATUS STDCALL scsi_get_address(
152     IN PDEVICE_OBJECT DeviceObject,
153     IN PIRP Irp,
154     IN PIO_STACK_LOCATION Stack,
155     IN struct device__type * dev_ptr,
156     OUT winvblock__bool_ptr completion_ptr
157   )
158 {
159   winvblock__uint32 copy_size;
160   SCSI_ADDRESS scsi_address;
161   disk__type_ptr disk_ptr;
162
163   copy_size =
164     ( Stack->Parameters.DeviceIoControl.OutputBufferLength <
165       sizeof ( SCSI_ADDRESS ) ? Stack->Parameters.DeviceIoControl.
166       OutputBufferLength : sizeof ( SCSI_ADDRESS ) );
167   scsi_address.Length = sizeof ( SCSI_ADDRESS );
168   scsi_address.PortNumber = 0;
169   scsi_address.PathId = 0;
170   disk_ptr = disk__get_ptr ( dev_ptr );
171   scsi_address.TargetId = ( winvblock__uint8 ) disk_ptr->DiskNumber;
172   scsi_address.Lun = 0;
173   RtlCopyMemory ( Irp->AssociatedIrp.SystemBuffer, &scsi_address, copy_size );
174   Irp->IoStatus.Information = ( ULONG_PTR ) copy_size;
175   return STATUS_SUCCESS;
176 }
177
178 NTSTATUS STDCALL disk_dev_ctl__dispatch(
179     IN PDEVICE_OBJECT DeviceObject,
180     IN PIRP Irp,
181     IN PIO_STACK_LOCATION Stack,
182     IN struct device__type * dev_ptr,
183     OUT winvblock__bool_ptr completion_ptr
184   )
185 {
186   NTSTATUS status;
187
188   switch ( Stack->Parameters.DeviceIoControl.IoControlCode )
189     {
190       case IOCTL_STORAGE_QUERY_PROPERTY:
191         status =
192           storage_query_prop ( DeviceObject, Irp, Stack, dev_ptr,
193                                completion_ptr );
194         break;
195       case IOCTL_DISK_GET_DRIVE_GEOMETRY:
196         status =
197           disk_get_drive_geom ( DeviceObject, Irp, Stack, dev_ptr,
198                                 completion_ptr );
199         break;
200       case IOCTL_SCSI_GET_ADDRESS:
201         status =
202           scsi_get_address ( DeviceObject, Irp, Stack, dev_ptr,
203                              completion_ptr );
204         break;
205         /*
206          * Some cases that pop up on Windows Server 2003 
207          */
208 #if 0
209       case IOCTL_MOUNTDEV_UNIQUE_ID_CHANGE_NOTIFY:
210       case IOCTL_MOUNTDEV_LINK_CREATED:
211       case IOCTL_MOUNTDEV_QUERY_STABLE_GUID:
212       case IOCTL_VOLUME_ONLINE:
213         Irp->IoStatus.Information = 0;
214         status = STATUS_SUCCESS;
215         break;
216 #endif
217       default:
218         Irp->IoStatus.Information = 0;
219         status = STATUS_INVALID_PARAMETER;
220     }
221
222   Irp->IoStatus.Status = status;
223   IoCompleteRequest ( Irp, IO_NO_INCREMENT );
224   *completion_ptr = TRUE;
225   return status;
226 }