1 /* 2 * ReactOS kernel 3 * Copyright (C) 2008, 2014 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/misc.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 /* FUNCTIONS ****************************************************************/ 35 36 /* 37 * FUNCTION: Used with IRP to set them to TopLevelIrp field 38 * ARGUMENTS: 39 * Irp = The IRP to set 40 * RETURNS: TRUE if top level was null, else FALSE 41 */ 42 BOOLEAN 43 NtfsIsIrpTopLevel(PIRP Irp) 44 { 45 BOOLEAN ReturnCode = FALSE; 46 47 TRACE_(NTFS, "NtfsIsIrpTopLevel()\n"); 48 49 if (IoGetTopLevelIrp() == NULL) 50 { 51 IoSetTopLevelIrp(Irp); 52 ReturnCode = TRUE; 53 } 54 55 return ReturnCode; 56 } 57 58 /* 59 * FUNCTION: Allocate and fill an NTFS_IRP_CONTEXT struct in order to use it for IRP 60 * ARGUMENTS: 61 * DeviceObject = Used to fill in struct 62 * Irp = The IRP that need IRP_CONTEXT struct 63 * RETURNS: NULL or PNTFS_IRP_CONTEXT 64 */ 65 PNTFS_IRP_CONTEXT 66 NtfsAllocateIrpContext(PDEVICE_OBJECT DeviceObject, 67 PIRP Irp) 68 { 69 PNTFS_IRP_CONTEXT IrpContext; 70 71 TRACE_(NTFS, "NtfsAllocateIrpContext()\n"); 72 73 IrpContext = (PNTFS_IRP_CONTEXT)ExAllocateFromNPagedLookasideList(&NtfsGlobalData->IrpContextLookasideList); 74 if (IrpContext == NULL) 75 return NULL; 76 77 RtlZeroMemory(IrpContext, sizeof(NTFS_IRP_CONTEXT)); 78 79 IrpContext->Identifier.Type = NTFS_TYPE_IRP_CONTEXT; 80 IrpContext->Identifier.Size = sizeof(NTFS_IRP_CONTEXT); 81 IrpContext->Irp = Irp; 82 IrpContext->DeviceObject = DeviceObject; 83 IrpContext->Stack = IoGetCurrentIrpStackLocation(Irp); 84 IrpContext->MajorFunction = IrpContext->Stack->MajorFunction; 85 IrpContext->MinorFunction = IrpContext->Stack->MinorFunction; 86 IrpContext->FileObject = IrpContext->Stack->FileObject; 87 IrpContext->IsTopLevel = (IoGetTopLevelIrp() == Irp); 88 IrpContext->PriorityBoost = IO_NO_INCREMENT; 89 IrpContext->Flags = IRPCONTEXT_COMPLETE; 90 91 if (IrpContext->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL || 92 IrpContext->MajorFunction == IRP_MJ_DEVICE_CONTROL || 93 IrpContext->MajorFunction == IRP_MJ_SHUTDOWN || 94 (IrpContext->MajorFunction != IRP_MJ_CLEANUP && 95 IrpContext->MajorFunction != IRP_MJ_CLOSE && 96 IoIsOperationSynchronous(Irp))) 97 { 98 IrpContext->Flags |= IRPCONTEXT_CANWAIT; 99 } 100 101 return IrpContext; 102 } 103 104 VOID 105 NtfsFileFlagsToAttributes(ULONG NtfsAttributes, 106 PULONG FileAttributes) 107 { 108 *FileAttributes = NtfsAttributes; 109 if ((NtfsAttributes & NTFS_FILE_TYPE_DIRECTORY) == NTFS_FILE_TYPE_DIRECTORY) 110 { 111 *FileAttributes = NtfsAttributes & ~NTFS_FILE_TYPE_DIRECTORY; 112 *FileAttributes |= FILE_ATTRIBUTE_DIRECTORY; 113 } 114 115 if (NtfsAttributes == 0) 116 *FileAttributes = FILE_ATTRIBUTE_NORMAL; 117 } 118 119 PVOID 120 NtfsGetUserBuffer(PIRP Irp, 121 BOOLEAN Paging) 122 { 123 if (Irp->MdlAddress != NULL) 124 { 125 return MmGetSystemAddressForMdlSafe(Irp->MdlAddress, (Paging ? HighPagePriority : NormalPagePriority)); 126 } 127 else 128 { 129 return Irp->UserBuffer; 130 } 131 } 132 133 /** 134 * @name NtfsLockUserBuffer 135 * @implemented 136 * 137 * Ensures the IRP has an MDL Address. 138 * 139 * @param Irp 140 * Irp with the UserBuffer that needs locking 141 * 142 * @param Length 143 * Size of the Irp->UserBuffer, in bytes 144 * 145 * @param Operation 146 * What kind of access does the driver need to the buffer. Set to 147 * IoReadAccess, IoWriteAccess, or IoModifyAccess. 148 * 149 * @return 150 * STATUS_SUCCESS in case of success, STATUS_INSUFFICIENT_RESOURCES 151 * or an exception code otherwise. 152 * 153 * @remarks Trevor Thompson shamelessly ripped this from 154 * VfatLockUserBuffer(). Only the name was changed. 155 * 156 */ 157 NTSTATUS 158 NtfsLockUserBuffer(IN PIRP Irp, 159 IN ULONG Length, 160 IN LOCK_OPERATION Operation) 161 { 162 ASSERT(Irp); 163 164 if (Irp->MdlAddress) 165 { 166 return STATUS_SUCCESS; 167 } 168 169 IoAllocateMdl(Irp->UserBuffer, Length, FALSE, FALSE, Irp); 170 171 if (!Irp->MdlAddress) 172 { 173 return STATUS_INSUFFICIENT_RESOURCES; 174 } 175 176 _SEH2_TRY 177 { 178 MmProbeAndLockPages(Irp->MdlAddress, Irp->RequestorMode, Operation); 179 } 180 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 181 { 182 IoFreeMdl(Irp->MdlAddress); 183 Irp->MdlAddress = NULL; 184 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 185 } 186 _SEH2_END; 187 188 return STATUS_SUCCESS; 189 } 190 191 /* EOF */ 192