xref: /reactos/drivers/filesystems/ntfs/misc.c (revision 50cf16b3)
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