Windows: Runtime RDR Trace Toggle
[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     UNREFERENCED_PARAMETER(LibDeviceObject);
58     NTSTATUS ntStatus = STATUS_SUCCESS;
59     IO_STACK_LOCATION *pIrpSp;
60     ULONG               ulIoControlCode = 0;
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 ( Irp->RequestorMode != KernelMode)
78                 {
79
80                     ntStatus = STATUS_ACCESS_DENIED;
81
82                     break;
83                 }
84
85                 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSLibraryInitCB))
86                 {
87
88                     ntStatus = STATUS_INVALID_PARAMETER;
89
90                     break;
91                 }
92
93                 ntStatus = AFSInitializeLibrary( pLibInitCB);
94
95                 if( !NT_SUCCESS( ntStatus))
96                 {
97
98                     AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
99                                   AFS_TRACE_LEVEL_ERROR,
100                                   "AFSDevControl AFSInitializeLibrary failure %08lX\n",
101                                   ntStatus));
102
103                     break;
104                 }
105
106                 //
107                 // Initialize the worker pool.
108                 //
109
110                 ntStatus = AFSInitializeWorkerPool();
111
112                 if( !NT_SUCCESS( ntStatus))
113                 {
114
115                     AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
116                                   AFS_TRACE_LEVEL_ERROR,
117                                   "AFSDevControl AFSInitializeWorkerPool failure %08lX\n",
118                                   ntStatus));
119
120                     break;
121                 }
122
123                 //
124                 // Initialize our global entries
125                 //
126
127                 ntStatus = AFSInitializeGlobalDirectoryEntries();
128
129                 if( !NT_SUCCESS( ntStatus))
130                 {
131
132                     AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
133                                   AFS_TRACE_LEVEL_ERROR,
134                                   "AFSDevControl AFSInitializeGlobalDirectoryEntries failure %08lX\n",
135                                   ntStatus));
136
137                     break;
138                 }
139
140                 ntStatus = AFSInitializeSpecialShareNameList();
141
142                 if( !NT_SUCCESS( ntStatus))
143                 {
144
145                     AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
146                                   AFS_TRACE_LEVEL_ERROR,
147                                   "AFSDevControl AFSInitializeSpecialShareNameList failure %08lX\n",
148                                   ntStatus));
149
150                     break;
151                 }
152
153                 break;
154             }
155
156             case IOCTL_AFS_ADD_CONNECTION:
157             {
158
159                 AFSNetworkProviderConnectionCB *pConnectCB = (AFSNetworkProviderConnectionCB *)Irp->AssociatedIrp.SystemBuffer;
160
161                 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSNetworkProviderConnectionCB) ||
162                     pIrpSp->Parameters.DeviceIoControl.InputBufferLength < (ULONG)FIELD_OFFSET( AFSNetworkProviderConnectionCB, RemoteName) +
163                                                                                                             pConnectCB->RemoteNameLength ||
164                     pIrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof( ULONG))
165                 {
166
167                     ntStatus = STATUS_INVALID_PARAMETER;
168
169                     break;
170                 }
171
172                 ntStatus = AFSAddConnection( pConnectCB,
173                                              (PULONG)Irp->AssociatedIrp.SystemBuffer,
174                                              &Irp->IoStatus.Information);
175
176                 break;
177             }
178
179             case IOCTL_AFS_CANCEL_CONNECTION:
180             {
181
182                 AFSNetworkProviderConnectionCB *pConnectCB = (AFSNetworkProviderConnectionCB *)Irp->AssociatedIrp.SystemBuffer;
183
184                 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSNetworkProviderConnectionCB))
185                 {
186
187                     ntStatus = STATUS_INVALID_PARAMETER;
188
189                     break;
190                 }
191
192                 ntStatus = AFSCancelConnection( pConnectCB,
193                                                 (AFSCancelConnectionResultCB *)Irp->AssociatedIrp.SystemBuffer,
194                                                 &Irp->IoStatus.Information);
195
196                 break;
197             }
198
199             case IOCTL_AFS_GET_CONNECTION:
200             {
201
202                 AFSNetworkProviderConnectionCB *pConnectCB = (AFSNetworkProviderConnectionCB *)Irp->AssociatedIrp.SystemBuffer;
203
204                 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSNetworkProviderConnectionCB) ||
205                     pIrpSp->Parameters.DeviceIoControl.OutputBufferLength == 0)
206                 {
207
208                     ntStatus = STATUS_INVALID_PARAMETER;
209
210                     break;
211                 }
212
213                 ntStatus = AFSGetConnection( pConnectCB,
214                                              (WCHAR *)Irp->AssociatedIrp.SystemBuffer,
215                                              pIrpSp->Parameters.DeviceIoControl.OutputBufferLength,
216                                              &Irp->IoStatus.Information);
217
218                 break;
219             }
220
221             case IOCTL_AFS_LIST_CONNECTIONS:
222             {
223
224                 if( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength == 0)
225                 {
226
227                     ntStatus = STATUS_INVALID_PARAMETER;
228
229                     break;
230                 }
231
232                 ntStatus = AFSListConnections( (AFSNetworkProviderConnectionCB *)Irp->AssociatedIrp.SystemBuffer,
233                                                 pIrpSp->Parameters.DeviceIoControl.OutputBufferLength,
234                                                 &Irp->IoStatus.Information);
235
236                 break;
237             }
238
239             case IOCTL_AFS_GET_CONNECTION_INFORMATION:
240             {
241
242                 AFSNetworkProviderConnectionCB *pConnectCB = (AFSNetworkProviderConnectionCB *)Irp->AssociatedIrp.SystemBuffer;
243
244                 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSNetworkProviderConnectionCB) ||
245                     pIrpSp->Parameters.DeviceIoControl.OutputBufferLength == 0)
246                 {
247
248                     ntStatus = STATUS_INVALID_PARAMETER;
249
250                     break;
251                 }
252
253                 ntStatus = AFSGetConnectionInfo( pConnectCB,
254                                                  pIrpSp->Parameters.DeviceIoControl.OutputBufferLength,
255                                                  &Irp->IoStatus.Information);
256
257                 break;
258             }
259
260             case IOCTL_AFS_SET_FILE_EXTENTS:
261             {
262
263                 AFSSetFileExtentsCB *pExtents = (AFSSetFileExtentsCB*) Irp->AssociatedIrp.SystemBuffer;
264
265                 //
266                 // Check lengths twice so that if the buffer makes the
267                 // count invalid we will not Accvio
268                 //
269
270                 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
271                     ( FIELD_OFFSET( AFSSetFileExtentsCB, ExtentCount) + sizeof(ULONG)) ||
272                     pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
273                     ( FIELD_OFFSET( AFSSetFileExtentsCB, ExtentCount) + sizeof(ULONG) +
274                       sizeof (AFSFileExtentCB) * pExtents->ExtentCount))
275                 {
276
277                     ntStatus = STATUS_INVALID_PARAMETER;
278
279                     break;
280                 }
281
282                 ntStatus = AFSProcessSetFileExtents( pExtents );
283
284                 Irp->IoStatus.Information = 0;
285                 Irp->IoStatus.Status = ntStatus;
286
287                 break;
288             }
289
290             case IOCTL_AFS_RELEASE_FILE_EXTENTS:
291             {
292                 ntStatus = AFSProcessReleaseFileExtents( Irp);
293                 break;
294             }
295
296             case IOCTL_AFS_SET_FILE_EXTENT_FAILURE:
297             {
298
299                 ntStatus = AFSProcessExtentFailure( Irp);
300
301                 break;
302             }
303
304             case IOCTL_AFS_INVALIDATE_CACHE:
305             {
306
307                 AFSInvalidateCacheCB *pInvalidate = (AFSInvalidateCacheCB*)Irp->AssociatedIrp.SystemBuffer;
308
309                 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSInvalidateCacheCB))
310                 {
311
312                     ntStatus = STATUS_INVALID_PARAMETER;
313
314                     break;
315                 }
316
317                 ntStatus = AFSInvalidateCache( pInvalidate);
318
319                 Irp->IoStatus.Information = 0;
320                 Irp->IoStatus.Status = ntStatus;
321
322                 break;
323             }
324
325             case IOCTL_AFS_NETWORK_STATUS:
326             {
327
328                 AFSNetworkStatusCB *pNetworkStatus = (AFSNetworkStatusCB *)Irp->AssociatedIrp.SystemBuffer;
329
330                 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSNetworkStatusCB))
331                 {
332
333                     ntStatus = STATUS_INVALID_PARAMETER;
334
335                     break;
336                 }
337
338                 //
339                 // Set the network status
340                 //
341
342                 ntStatus = AFSSetNetworkState( pNetworkStatus);
343
344                 Irp->IoStatus.Information = 0;
345                 Irp->IoStatus.Status = ntStatus;
346
347                 break;
348             }
349
350             case IOCTL_AFS_VOLUME_STATUS:
351             {
352
353                 AFSVolumeStatusCB *pVolumeStatus = (AFSVolumeStatusCB *)Irp->AssociatedIrp.SystemBuffer;
354
355                 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSVolumeStatusCB))
356                 {
357
358                     ntStatus = STATUS_INVALID_PARAMETER;
359
360                     break;
361                 }
362
363                 ntStatus = AFSSetVolumeState( pVolumeStatus);
364
365                 Irp->IoStatus.Information = 0;
366                 Irp->IoStatus.Status = ntStatus;
367
368                 break;
369             }
370
371             case IOCTL_AFS_STATUS_REQUEST:
372             {
373
374                 if( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof( AFSDriverStatusRespCB))
375                 {
376
377                     ntStatus = STATUS_INVALID_PARAMETER;
378
379                     break;
380                 }
381
382                 ntStatus = AFSGetDriverStatus( (AFSDriverStatusRespCB *)Irp->AssociatedIrp.SystemBuffer);
383
384                 Irp->IoStatus.Information = sizeof( AFSDriverStatusRespCB);
385
386                 break;
387             }
388
389             case IOCTL_AFS_GET_OBJECT_INFORMATION:
390             {
391
392
393                 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSGetStatusInfoCB) ||
394                     pIrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof( AFSStatusInfoCB))
395
396                 {
397
398                     ntStatus = STATUS_INVALID_PARAMETER;
399
400                     break;
401                 }
402
403                 ntStatus = AFSGetObjectStatus( (AFSGetStatusInfoCB *)Irp->AssociatedIrp.SystemBuffer,
404                                                pIrpSp->Parameters.DeviceIoControl.InputBufferLength,
405                                                (AFSStatusInfoCB *)Irp->AssociatedIrp.SystemBuffer,
406                                                (ULONG *)&Irp->IoStatus.Information);
407
408                 break;
409             }
410
411             case 0x140390:      // IOCTL_LMR_DISABLE_LOCAL_BUFFERING
412             {
413                 //
414                 // See http://msdn.microsoft.com/en-us/library/ee210753%28v=vs.85%29.aspx
415                 //
416                 // The IOCTL_LMR_DISABLE_LOCAL_BUFFERING control code is defined internally by
417                 // the system as 0x140390 and not in a public header file. It is used by
418                 // special-purpose applications to disable local client-side in-memory
419                 // caching of data when reading data from or writing data to a remote file.
420                 // After local buffering is disabled, the setting remains in effect until all
421                 // open handles to the file are closed and the redirector cleans up its internal
422                 // data structures.
423                 //
424                 // General-purpose applications should not use IOCTL_LMR_DISABLE_LOCAL_BUFFERING,
425                 // because it can result in excessive network traffic and associated loss of
426                 // performance. The IOCTL_LMR_DISABLE_LOCAL_BUFFERING control code should be used
427                 // only in specialized applications moving large amounts of data over the network
428                 // while attempting to maximize use of network bandwidth. For example, the CopyFile
429                 // and CopyFileEx functions use IOCTL_LMR_DISABLE_LOCAL_BUFFERING to improve large
430                 // file copy performance.
431                 //
432                 // IOCTL_LMR_DISABLE_LOCAL_BUFFERING is not implemented by local file systems and
433                 // will fail with the error ERROR_INVALID_FUNCTION. Issuing the
434                 // IOCTL_LMR_DISABLE_LOCAL_BUFFERING control code on remote directory handles will
435                 // fail with the error ERROR_NOT_SUPPORTED.
436                 //
437
438                 ntStatus = STATUS_NOT_SUPPORTED;
439
440                 break;
441             }
442
443             case IOCTL_AFS_CONFIG_LIBRARY_TRACE:
444             {
445                 AFSDebugTraceConfigCB *pConfigLib;
446
447                 if ( pIrpSp->Parameters.DeviceIoControl.InputBufferLength != sizeof( AFSDebugTraceConfigCB))
448                 {
449
450                     ntStatus = STATUS_INVALID_PARAMETER;
451
452                     break;
453                 }
454
455                 pConfigLib = (AFSDebugTraceConfigCB *)Irp->AssociatedIrp.SystemBuffer;
456
457                 InterlockedCompareExchangePointer( (PVOID *)&AFSDebugTraceFnc,
458                                                    pConfigLib->AFSDbgLogMsg,
459                                                    (void *)pConfigLib->AFSDbgLogMsg);
460
461                 break;
462             }
463
464          default:
465             {
466                 //
467                 // Note that this code path is never executed - default behavior is caught in the
468                 // security checks in lib.  New Ioctl functions therefore have to be added here and
469                 // in ..\fs\AFSCommSupport.cpp
470                 //
471
472                 ntStatus = STATUS_NOT_IMPLEMENTED;
473
474                 break;
475             }
476         }
477
478 //try_exit:
479
480     }
481     __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()))
482     {
483
484         ntStatus = STATUS_UNSUCCESSFUL;
485
486         AFSDbgTrace(( 0,
487                       0,
488                       "EXCEPTION - AFSDevControl %08lX\n",
489                       ulIoControlCode));
490
491         AFSDumpTraceFilesFnc();
492     }
493
494     Irp->IoStatus.Status = ntStatus;
495
496     AFSCompleteRequest( Irp,
497                         ntStatus);
498
499     return ntStatus;
500 }