1 /* 2 * ReactOS kernel 3 * Copyright (C) 2008 ReactOS Team 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. 18 * 19 * COPYRIGHT: See COPYING in the top level directory 20 * PROJECT: ReactOS kernel 21 * FILE: drivers/filesystem/ntfs/dispatch.c 22 * PURPOSE: NTFS filesystem driver 23 * PROGRAMMER: Pierre Schweitzer 24 * UPDATE HISTORY: 25 */ 26 27 /* INCLUDES *****************************************************************/ 28 29 #include "ntfs.h" 30 31 #define NDEBUG 32 #include <debug.h> 33 34 static LONG QueueCount = 0; 35 36 /* FUNCTIONS ****************************************************************/ 37 38 static WORKER_THREAD_ROUTINE NtfsDoRequest; 39 40 static 41 NTSTATUS 42 NtfsQueueRequest(PNTFS_IRP_CONTEXT IrpContext) 43 { 44 InterlockedIncrement(&QueueCount); 45 DPRINT("NtfsQueueRequest(IrpContext %p), %d\n", IrpContext, QueueCount); 46 47 ASSERT(!(IrpContext->Flags & IRPCONTEXT_QUEUE) && 48 (IrpContext->Flags & IRPCONTEXT_COMPLETE)); 49 IrpContext->Flags |= IRPCONTEXT_CANWAIT; 50 IoMarkIrpPending(IrpContext->Irp); 51 ExInitializeWorkItem(&IrpContext->WorkQueueItem, NtfsDoRequest, IrpContext); 52 ExQueueWorkItem(&IrpContext->WorkQueueItem, CriticalWorkQueue); 53 54 return STATUS_PENDING; 55 } 56 57 static 58 NTSTATUS 59 NtfsDispatch(PNTFS_IRP_CONTEXT IrpContext) 60 { 61 PIRP Irp = IrpContext->Irp; 62 NTSTATUS Status = STATUS_UNSUCCESSFUL; 63 64 TRACE_(NTFS, "NtfsDispatch()\n"); 65 66 FsRtlEnterFileSystem(); 67 68 NtfsIsIrpTopLevel(Irp); 69 70 switch (IrpContext->MajorFunction) 71 { 72 case IRP_MJ_QUERY_VOLUME_INFORMATION: 73 Status = NtfsQueryVolumeInformation(IrpContext); 74 break; 75 76 case IRP_MJ_SET_VOLUME_INFORMATION: 77 Status = NtfsSetVolumeInformation(IrpContext); 78 break; 79 80 case IRP_MJ_QUERY_INFORMATION: 81 Status = NtfsQueryInformation(IrpContext); 82 break; 83 84 case IRP_MJ_SET_INFORMATION: 85 if (!NtfsGlobalData->EnableWriteSupport) 86 { 87 DPRINT1("NTFS write-support is EXPERIMENTAL and is disabled by default!\n"); 88 Status = STATUS_ACCESS_DENIED; 89 } 90 else 91 { 92 Status = NtfsSetInformation(IrpContext); 93 } 94 break; 95 96 case IRP_MJ_DIRECTORY_CONTROL: 97 Status = NtfsDirectoryControl(IrpContext); 98 break; 99 100 case IRP_MJ_READ: 101 Status = NtfsRead(IrpContext); 102 break; 103 104 case IRP_MJ_DEVICE_CONTROL: 105 Status = NtfsDeviceControl(IrpContext); 106 break; 107 108 case IRP_MJ_WRITE: 109 if (!NtfsGlobalData->EnableWriteSupport) 110 { 111 DPRINT1("NTFS write-support is EXPERIMENTAL and is disabled by default!\n"); 112 Status = STATUS_ACCESS_DENIED; 113 } 114 else 115 { 116 Status = NtfsWrite(IrpContext); 117 } 118 break; 119 120 case IRP_MJ_CLOSE: 121 Status = NtfsClose(IrpContext); 122 break; 123 124 case IRP_MJ_CLEANUP: 125 Status = NtfsCleanup(IrpContext); 126 break; 127 128 case IRP_MJ_CREATE: 129 Status = NtfsCreate(IrpContext); 130 break; 131 132 case IRP_MJ_FILE_SYSTEM_CONTROL: 133 Status = NtfsFileSystemControl(IrpContext); 134 break; 135 } 136 137 ASSERT((!(IrpContext->Flags & IRPCONTEXT_COMPLETE) && !(IrpContext->Flags & IRPCONTEXT_QUEUE)) || 138 ((IrpContext->Flags & IRPCONTEXT_COMPLETE) && !(IrpContext->Flags & IRPCONTEXT_QUEUE)) || 139 (!(IrpContext->Flags & IRPCONTEXT_COMPLETE) && (IrpContext->Flags & IRPCONTEXT_QUEUE))); 140 141 if (IrpContext->Flags & IRPCONTEXT_COMPLETE) 142 { 143 Irp->IoStatus.Status = Status; 144 IoCompleteRequest(Irp, IrpContext->PriorityBoost); 145 } 146 147 if (IrpContext->Flags & IRPCONTEXT_QUEUE) 148 { 149 /* Reset our status flags before queueing the IRP */ 150 IrpContext->Flags |= IRPCONTEXT_COMPLETE; 151 IrpContext->Flags &= ~IRPCONTEXT_QUEUE; 152 Status = NtfsQueueRequest(IrpContext); 153 } 154 else 155 { 156 ExFreeToNPagedLookasideList(&NtfsGlobalData->IrpContextLookasideList, IrpContext); 157 } 158 159 IoSetTopLevelIrp(NULL); 160 FsRtlExitFileSystem(); 161 162 return Status; 163 } 164 165 static 166 VOID 167 NTAPI 168 NtfsDoRequest(PVOID IrpContext) 169 { 170 InterlockedDecrement(&QueueCount); 171 DPRINT("NtfsDoRequest(IrpContext %p), MajorFunction %x, %d\n", 172 IrpContext, ((PNTFS_IRP_CONTEXT)IrpContext)->MajorFunction, QueueCount); 173 NtfsDispatch((PNTFS_IRP_CONTEXT)IrpContext); 174 } 175 176 /* 177 * FUNCTION: This function manages IRP for various major functions 178 * ARGUMENTS: 179 * DriverObject = object describing this driver 180 * Irp = IRP to be passed to internal functions 181 * RETURNS: Status of I/O Request 182 */ 183 NTSTATUS 184 NTAPI 185 NtfsFsdDispatch(PDEVICE_OBJECT DeviceObject, 186 PIRP Irp) 187 { 188 PNTFS_IRP_CONTEXT IrpContext = NULL; 189 NTSTATUS Status; 190 191 TRACE_(NTFS, "NtfsFsdDispatch()\n"); 192 193 IrpContext = NtfsAllocateIrpContext(DeviceObject, Irp); 194 if (IrpContext == NULL) 195 { 196 Status = STATUS_INSUFFICIENT_RESOURCES; 197 Irp->IoStatus.Status = Status; 198 IoCompleteRequest(Irp, IO_NO_INCREMENT); 199 } 200 else 201 { 202 Status = NtfsDispatch(IrpContext); 203 } 204 205 return Status; 206 } 207