627195eb44404dc1e6412af4ba79b0f094797755
[openafs.git] / src / WINNT / afsrdr / kernel / lib / AFSDevControl.cpp
1 /*
2  * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
3  * Copyright (c) 2009, 2010, 2011 Your File System, Inc.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * - Redistributions of source code must retain the above copyright notice,
11  *   this list of conditions and the following disclaimer.
12  * - Redistributions in binary form must reproduce the above copyright
13  *   notice,
14  *   this list of conditions and the following disclaimer in the
15  *   documentation
16  *   and/or other materials provided with the distribution.
17  * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
18  *   nor the names of their contributors may be used to endorse or promote
19  *   products derived from this software without specific prior written
20  *   permission from Kernel Drivers, LLC and Your File System, Inc.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
26  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34
35 //
36 // File: AFSDevControl.cpp
37 //
38
39 #include "AFSCommon.h"
40
41 //
42 // Function: AFSDevControl
43 //
44 // Description:
45 //
46 //      This is the dipatch handler for the IRP_MJ_DEVICE_CONTROL requests.
47 //
48 // Return:
49 //
50 //      A status is returned for the function
51 //
52
53 NTSTATUS
54 AFSDevControl( IN PDEVICE_OBJECT LibDeviceObject,
55                IN PIRP Irp)
56 {
57
58     NTSTATUS ntStatus = STATUS_SUCCESS;
59     IO_STACK_LOCATION *pIrpSp;
60     ULONG               ulIoControlCode;
61
62     __try
63     {
64
65         pIrpSp = IoGetCurrentIrpStackLocation( Irp);
66
67         ulIoControlCode = pIrpSp->Parameters.DeviceIoControl.IoControlCode;
68
69         switch( ulIoControlCode)
70         {
71
72             case IOCTL_AFS_INITIALIZE_LIBRARY_DEVICE:
73             {
74
75                 AFSLibraryInitCB *pLibInitCB = (AFSLibraryInitCB *)Irp->AssociatedIrp.SystemBuffer;
76
77                 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSLibraryInitCB))
78                 {
79
80                     ntStatus = STATUS_INVALID_PARAMETER;
81
82                     break;
83                 }
84
85                 ntStatus = AFSInitializeLibrary( pLibInitCB);
86
87                 if( !NT_SUCCESS( ntStatus))
88                 {
89
90                     AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
91                                   AFS_TRACE_LEVEL_ERROR,
92                                   "AFSDevControl AFSInitializeLibrary failure %08lX\n",
93                                   ntStatus);
94
95                     break;
96                 }
97
98                 //
99                 // Initialize our global entries
100                 //
101
102                 ntStatus = AFSInitializeGlobalDirectoryEntries();
103
104                 if( !NT_SUCCESS( ntStatus))
105                 {
106
107                     AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
108                                   AFS_TRACE_LEVEL_ERROR,
109                                   "AFSDevControl AFSInitializeGlobalDirectoryEntries failure %08lX\n",
110                                   ntStatus);
111
112                     break;
113                 }
114
115                 ntStatus = AFSInitializeSpecialShareNameList();
116
117                 if( !NT_SUCCESS( ntStatus))
118                 {
119
120                     AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
121                                   AFS_TRACE_LEVEL_ERROR,
122                                   "AFSDevControl AFSInitializeSpecialShareNameList failure %08lX\n",
123                                   ntStatus);
124
125                     break;
126                 }
127
128                 break;
129             }
130
131             case IOCTL_AFS_ADD_CONNECTION:
132             {
133
134                 AFSNetworkProviderConnectionCB *pConnectCB = (AFSNetworkProviderConnectionCB *)Irp->AssociatedIrp.SystemBuffer;
135
136                 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSNetworkProviderConnectionCB) ||
137                     pIrpSp->Parameters.DeviceIoControl.InputBufferLength < (ULONG)FIELD_OFFSET( AFSNetworkProviderConnectionCB, RemoteName) +
138                                                                                                             pConnectCB->RemoteNameLength ||
139                     pIrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof( ULONG))
140                 {
141
142                     ntStatus = STATUS_INVALID_PARAMETER;
143
144                     break;
145                 }
146
147                 ntStatus = AFSAddConnection( pConnectCB,
148                                              (PULONG)Irp->AssociatedIrp.SystemBuffer,
149                                              &Irp->IoStatus.Information);
150
151                 break;
152             }
153
154             case IOCTL_AFS_CANCEL_CONNECTION:
155             {
156
157                 AFSNetworkProviderConnectionCB *pConnectCB = (AFSNetworkProviderConnectionCB *)Irp->AssociatedIrp.SystemBuffer;
158
159                 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSNetworkProviderConnectionCB))
160                 {
161
162                     ntStatus = STATUS_INVALID_PARAMETER;
163
164                     break;
165                 }
166
167                 ntStatus = AFSCancelConnection( pConnectCB,
168                                                 (AFSCancelConnectionResultCB *)Irp->AssociatedIrp.SystemBuffer,
169                                                 &Irp->IoStatus.Information);
170
171                 break;
172             }
173
174             case IOCTL_AFS_GET_CONNECTION:
175             {
176
177                 AFSNetworkProviderConnectionCB *pConnectCB = (AFSNetworkProviderConnectionCB *)Irp->AssociatedIrp.SystemBuffer;
178
179                 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSNetworkProviderConnectionCB) ||
180                     pIrpSp->Parameters.DeviceIoControl.OutputBufferLength == 0)
181                 {
182
183                     ntStatus = STATUS_INVALID_PARAMETER;
184
185                     break;
186                 }
187
188                 ntStatus = AFSGetConnection( pConnectCB,
189                                              (WCHAR *)Irp->AssociatedIrp.SystemBuffer,
190                                              pIrpSp->Parameters.DeviceIoControl.OutputBufferLength,
191                                              &Irp->IoStatus.Information);
192
193                 break;
194             }
195
196             case IOCTL_AFS_LIST_CONNECTIONS:
197             {
198
199                 if( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength == 0)
200                 {
201
202                     ntStatus = STATUS_INVALID_PARAMETER;
203
204                     break;
205                 }
206
207                 ntStatus = AFSListConnections( (AFSNetworkProviderConnectionCB *)Irp->AssociatedIrp.SystemBuffer,
208                                                 pIrpSp->Parameters.DeviceIoControl.OutputBufferLength,
209                                                 &Irp->IoStatus.Information);
210
211                 break;
212             }
213
214             case IOCTL_AFS_GET_CONNECTION_INFORMATION:
215             {
216
217                 AFSNetworkProviderConnectionCB *pConnectCB = (AFSNetworkProviderConnectionCB *)Irp->AssociatedIrp.SystemBuffer;
218
219                 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSNetworkProviderConnectionCB) ||
220                     pIrpSp->Parameters.DeviceIoControl.OutputBufferLength == 0)
221                 {
222
223                     ntStatus = STATUS_INVALID_PARAMETER;
224
225                     break;
226                 }
227
228                 ntStatus = AFSGetConnectionInfo( pConnectCB,
229                                                  pIrpSp->Parameters.DeviceIoControl.OutputBufferLength,
230                                                  &Irp->IoStatus.Information);
231
232                 break;
233             }
234
235             case IOCTL_AFS_SET_FILE_EXTENTS:
236             {
237
238                 AFSSetFileExtentsCB *pExtents = (AFSSetFileExtentsCB*) Irp->AssociatedIrp.SystemBuffer;
239
240                 //
241                 // Check lengths twice so that if the buffer makes the
242                 // count invalid we will not Accvio
243                 //
244
245                 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
246                     ( FIELD_OFFSET( AFSSetFileExtentsCB, ExtentCount) + sizeof(ULONG)) ||
247                     pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
248                     ( FIELD_OFFSET( AFSSetFileExtentsCB, ExtentCount) + sizeof(ULONG) +
249                       sizeof (AFSFileExtentCB) * pExtents->ExtentCount))
250                 {
251
252                     ntStatus = STATUS_INVALID_PARAMETER;
253
254                     break;
255                 }
256
257                 ntStatus = AFSProcessSetFileExtents( pExtents );
258
259                 Irp->IoStatus.Information = 0;
260                 Irp->IoStatus.Status = ntStatus;
261
262                 break;
263             }
264
265             case IOCTL_AFS_RELEASE_FILE_EXTENTS:
266             {
267                 ntStatus = AFSProcessReleaseFileExtents( Irp);
268                 break;
269             }
270
271             case IOCTL_AFS_SET_FILE_EXTENT_FAILURE:
272             {
273
274                 ntStatus = AFSProcessExtentFailure( Irp);
275
276                 break;
277             }
278
279             case IOCTL_AFS_INVALIDATE_CACHE:
280             {
281
282                 AFSInvalidateCacheCB *pInvalidate = (AFSInvalidateCacheCB*)Irp->AssociatedIrp.SystemBuffer;
283
284                 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSInvalidateCacheCB))
285                 {
286
287                     ntStatus = STATUS_INVALID_PARAMETER;
288
289                     break;
290                 }
291
292                 ntStatus = AFSInvalidateCache( pInvalidate);
293
294                 Irp->IoStatus.Information = 0;
295                 Irp->IoStatus.Status = ntStatus;
296
297                 break;
298             }
299
300             case IOCTL_AFS_NETWORK_STATUS:
301             {
302
303                 AFSNetworkStatusCB *pNetworkStatus = (AFSNetworkStatusCB *)Irp->AssociatedIrp.SystemBuffer;
304
305                 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSNetworkStatusCB))
306                 {
307
308                     ntStatus = STATUS_INVALID_PARAMETER;
309
310                     break;
311                 }
312
313                 //
314                 // Set the network status
315                 //
316
317                 ntStatus = AFSSetNetworkState( pNetworkStatus);
318
319                 Irp->IoStatus.Information = 0;
320                 Irp->IoStatus.Status = ntStatus;
321
322                 break;
323             }
324
325             case IOCTL_AFS_VOLUME_STATUS:
326             {
327
328                 AFSVolumeStatusCB *pVolumeStatus = (AFSVolumeStatusCB *)Irp->AssociatedIrp.SystemBuffer;
329
330                 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSVolumeStatusCB))
331                 {
332
333                     ntStatus = STATUS_INVALID_PARAMETER;
334
335                     break;
336                 }
337
338                 ntStatus = AFSSetVolumeState( pVolumeStatus);
339
340                 Irp->IoStatus.Information = 0;
341                 Irp->IoStatus.Status = ntStatus;
342
343                 break;
344             }
345
346             case IOCTL_AFS_STATUS_REQUEST:
347             {
348
349                 if( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof( AFSDriverStatusRespCB))
350                 {
351
352                     ntStatus = STATUS_INVALID_PARAMETER;
353
354                     break;
355                 }
356
357                 ntStatus = AFSGetDriverStatus( (AFSDriverStatusRespCB *)Irp->AssociatedIrp.SystemBuffer);
358
359                 Irp->IoStatus.Information = sizeof( AFSDriverStatusRespCB);
360
361                 break;
362             }
363
364             case IOCTL_AFS_GET_OBJECT_INFORMATION:
365             {
366
367
368                 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSGetStatusInfoCB) ||
369                     pIrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof( AFSStatusInfoCB))
370
371                 {
372
373                     ntStatus = STATUS_INVALID_PARAMETER;
374
375                     break;
376                 }
377
378                 ntStatus = AFSGetObjectStatus( (AFSGetStatusInfoCB *)Irp->AssociatedIrp.SystemBuffer,
379                                                pIrpSp->Parameters.DeviceIoControl.InputBufferLength,
380                                                (AFSStatusInfoCB *)Irp->AssociatedIrp.SystemBuffer,
381                                                (ULONG *)&Irp->IoStatus.Information);
382
383                 break;
384             }
385
386             case 0x140390:      // IOCTL_LMR_DISABLE_LOCAL_BUFFERING
387             {
388                 //
389                 // See http://msdn.microsoft.com/en-us/library/ee210753%28v=vs.85%29.aspx
390                 //
391                 // The IOCTL_LMR_DISABLE_LOCAL_BUFFERING control code is defined internally by
392                 // the system as 0x140390 and not in a public header file. It is used by
393                 // special-purpose applications to disable local client-side in-memory
394                 // caching of data when reading data from or writing data to a remote file.
395                 // After local buffering is disabled, the setting remains in effect until all
396                 // open handles to the file are closed and the redirector cleans up its internal
397                 // data structures.
398                 //
399                 // General-purpose applications should not use IOCTL_LMR_DISABLE_LOCAL_BUFFERING,
400                 // because it can result in excessive network traffic and associated loss of
401                 // performance. The IOCTL_LMR_DISABLE_LOCAL_BUFFERING control code should be used
402                 // only in specialized applications moving large amounts of data over the network
403                 // while attempting to maximize use of network bandwidth. For example, the CopyFile
404                 // and CopyFileEx functions use IOCTL_LMR_DISABLE_LOCAL_BUFFERING to improve large
405                 // file copy performance.
406                 //
407                 // IOCTL_LMR_DISABLE_LOCAL_BUFFERING is not implemented by local file systems and
408                 // will fail with the error ERROR_INVALID_FUNCTION. Issuing the
409                 // IOCTL_LMR_DISABLE_LOCAL_BUFFERING control code on remote directory handles will
410                 // fail with the error ERROR_NOT_SUPPORTED.
411                 //
412
413                 ntStatus = STATUS_NOT_SUPPORTED;
414
415                 break;
416             }
417
418          default:
419             {
420
421                 ntStatus = STATUS_NOT_IMPLEMENTED;
422
423                 break;
424             }
425         }
426
427 //try_exit:
428
429     }
430     __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()))
431     {
432
433         ntStatus = STATUS_UNSUCCESSFUL;
434
435         AFSDumpTraceFilesFnc();
436     }
437
438     Irp->IoStatus.Status = ntStatus;
439
440     AFSCompleteRequest( Irp,
441                         ntStatus);
442
443     return ntStatus;
444 }