xref: /reactos/dll/win32/kernel32/client/file/lock.c (revision 40462c92)
1 /*
2  * COPYRIGHT:       See COPYING in the top level directory
3  * PROJECT:         ReactOS system libraries
4  * FILE:            dll/win32/kernel32/client/file/lock.c
5  * PURPOSE:         Directory functions
6  * PROGRAMMER:      Ariadne ( ariadne@xs4all.nl)
7  * UPDATE HISTORY:
8  *                  Created 01/11/98
9  */
10 
11 
12 /* INCLUDES ****************************************************************/
13 
14 #include <k32.h>
15 #define NDEBUG
16 #include <debug.h>
17 
18 /* FUNCTIONS ****************************************************************/
19 
20 /*
21  * @implemented
22  */
23 BOOL
24 WINAPI
25 LockFile(IN HANDLE hFile,
26          IN DWORD dwFileOffsetLow,
27          IN DWORD dwFileOffsetHigh,
28          IN DWORD nNumberOfBytesToLockLow,
29          IN DWORD nNumberOfBytesToLockHigh)
30 {
31     IO_STATUS_BLOCK IoStatusBlock;
32     NTSTATUS Status;
33     LARGE_INTEGER BytesToLock, Offset;
34 
35     /* Is this a console handle? */
36     if (IsConsoleHandle(hFile))
37     {
38         /* Can't "lock" a console! */
39         BaseSetLastNTError(STATUS_INVALID_HANDLE);
40         return FALSE;
41     }
42 
43     /* Setup the parameters in NT style and call the native API */
44     BytesToLock.u.LowPart = nNumberOfBytesToLockLow;
45     BytesToLock.u.HighPart = nNumberOfBytesToLockHigh;
46     Offset.u.LowPart = dwFileOffsetLow;
47     Offset.u.HighPart = dwFileOffsetHigh;
48     Status = NtLockFile(hFile,
49                         NULL,
50                         NULL,
51                         NULL,
52                         &IoStatusBlock,
53                         &Offset,
54                         &BytesToLock,
55                         0,
56                         TRUE,
57                         TRUE);
58     if (Status == STATUS_PENDING)
59     {
60         /* Wait for completion if needed */
61         Status = NtWaitForSingleObject(hFile, FALSE, NULL);
62         if (NT_SUCCESS(Status)) Status = IoStatusBlock.Status;
63     }
64 
65     /* Check if we failed */
66     if (!NT_SUCCESS(Status))
67     {
68         /* Convert the error code and fail */
69         BaseSetLastNTError(Status);
70         return FALSE;
71     }
72 
73     /* Success! */
74     return TRUE;
75 }
76 
77 /*
78  * @implemented
79  */
80 BOOL
81 WINAPI
82 LockFileEx(IN HANDLE hFile,
83            IN DWORD dwFlags,
84            IN DWORD dwReserved,
85            IN DWORD nNumberOfBytesToLockLow,
86            IN DWORD nNumberOfBytesToLockHigh,
87            IN LPOVERLAPPED lpOverlapped)
88 {
89     LARGE_INTEGER BytesToLock, Offset;
90     NTSTATUS Status;
91 
92     /* Is this a console handle? */
93     if (IsConsoleHandle(hFile))
94     {
95         /* Can't "lock" a console! */
96         BaseSetLastNTError(STATUS_INVALID_HANDLE);
97         return FALSE;
98     }
99 
100     /* This parameter should be zero */
101     if (dwReserved)
102     {
103         /* Fail since it isn't */
104         SetLastError(ERROR_INVALID_PARAMETER);
105         return FALSE;
106     }
107 
108     /* Set the initial status in the IO_STATUS_BLOCK to pending... */
109     lpOverlapped->Internal = STATUS_PENDING;
110 
111     /* Convert the parameters to NT format and call the native API */
112     Offset.u.LowPart = lpOverlapped->Offset;
113     Offset.u.HighPart = lpOverlapped->OffsetHigh;
114     BytesToLock.u.LowPart = nNumberOfBytesToLockLow;
115     BytesToLock.u.HighPart = nNumberOfBytesToLockHigh;
116     Status = NtLockFile(hFile,
117                         lpOverlapped->hEvent,
118                         NULL,
119                         NULL,
120                         (PIO_STATUS_BLOCK)lpOverlapped,
121                         &Offset,
122                         &BytesToLock,
123                         0,
124                         dwFlags & LOCKFILE_FAIL_IMMEDIATELY ? TRUE : FALSE,
125                         dwFlags & LOCKFILE_EXCLUSIVE_LOCK ? TRUE: FALSE);
126     if ((NT_SUCCESS(Status)) && (Status != STATUS_PENDING))
127     {
128         /* Pending status is *not* allowed in the Ex API */
129         return TRUE;
130     }
131 
132     /* Convert the error code and fail */
133     BaseSetLastNTError(Status);
134     return FALSE;
135 }
136 
137 /*
138  * @implemented
139  */
140 BOOL
141 WINAPI
142 UnlockFile(IN HANDLE hFile,
143            IN DWORD dwFileOffsetLow,
144            IN DWORD dwFileOffsetHigh,
145            IN DWORD nNumberOfBytesToUnlockLow,
146            IN DWORD nNumberOfBytesToUnlockHigh)
147 {
148     OVERLAPPED Overlapped;
149     NTSTATUS Status;
150     BOOLEAN Result;
151 
152     /* Convert parameters to Ex format and call the new API */
153     Overlapped.Offset = dwFileOffsetLow;
154     Overlapped.OffsetHigh = dwFileOffsetHigh;
155     Result = UnlockFileEx(hFile,
156                           0,
157                           nNumberOfBytesToUnlockLow,
158                           nNumberOfBytesToUnlockHigh,
159                           &Overlapped);
160     if (!(Result) && (GetLastError() == ERROR_IO_PENDING))
161     {
162         /* Ex fails during STATUS_PENDING, handle that here by waiting */
163         Status = NtWaitForSingleObject(hFile, FALSE, NULL);
164         if (NT_SUCCESS(Status)) Status = Overlapped.Internal;
165 
166         /* Now if the status is successful, return */
167         if (!NT_SUCCESS(Status)) return TRUE;
168 
169         /* Otherwise the asynchronous operation had a failure, so fail */
170         BaseSetLastNTError(Status);
171         return FALSE;
172     }
173 
174     /* Success or error case -- Ex took care of the rest, just return */
175     return Result;
176 }
177 
178 /*
179  * @implemented
180  */
181 BOOL
182 WINAPI
183 UnlockFileEx(IN HANDLE hFile,
184              IN DWORD dwReserved,
185              IN DWORD nNumberOfBytesToUnLockLow,
186              IN DWORD nNumberOfBytesToUnLockHigh,
187              IN LPOVERLAPPED lpOverlapped)
188 {
189     LARGE_INTEGER BytesToUnLock, StartAddress;
190     NTSTATUS Status;
191 
192     /* Is this a console handle? */
193     if (IsConsoleHandle(hFile))
194     {
195         /* Can't "unlock" a console! */
196         BaseSetLastNTError(STATUS_INVALID_HANDLE);
197         return FALSE;
198     }
199 
200     /* This parameter should be zero */
201     if (dwReserved)
202     {
203         /* Fail since it isn't */
204         SetLastError(ERROR_INVALID_PARAMETER);
205         return FALSE;
206     }
207 
208     /* Convert to NT format and call the native function */
209     BytesToUnLock.u.LowPart = nNumberOfBytesToUnLockLow;
210     BytesToUnLock.u.HighPart = nNumberOfBytesToUnLockHigh;
211     StartAddress.u.LowPart = lpOverlapped->Offset;
212     StartAddress.u.HighPart = lpOverlapped->OffsetHigh;
213     Status = NtUnlockFile(hFile,
214                           (PIO_STATUS_BLOCK)lpOverlapped,
215                           &StartAddress,
216                           &BytesToUnLock,
217                           0);
218     if (!NT_SUCCESS(Status))
219     {
220         /* Convert the error and fail */
221         BaseSetLastNTError(Status);
222         return FALSE;
223     }
224 
225     /* All good */
226     return TRUE;
227 }
228 
229 /* EOF */
230