VirtualBox

source: kBuild/trunk/src/lib/nt/nthlpfs.c@ 2704

Last change on this file since 2704 was 2704, checked in by bird, 12 years ago

Drop the w32 createfile option, implemented sharing-violation fallback for stat() and lstat().

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 9.7 KB
Line 
1/* $Id: nthlpfs.c 2704 2013-11-21 01:26:52Z bird $ */
2/** @file
3 * MSC + NT helpers for file system related functions.
4 */
5
6/*
7 * Copyright (c) 2005-2013 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
25 * IN THE SOFTWARE.
26 *
27 * Alternatively, the content of this file may be used under the terms of the
28 * GPL version 2 or later, or LGPL version 2.1 or later.
29 */
30
31
32/*******************************************************************************
33* Header Files *
34*******************************************************************************/
35#include "nthlp.h"
36
37
38/*******************************************************************************
39* Global Variables *
40*******************************************************************************/
41static int g_fHaveOpenReparsePoint = -1;
42
43
44
45static int birdHasTrailingSlash(const char *pszPath)
46{
47 char ch, ch2;
48
49 /* Skip leading slashes. */
50 while ((ch = *pszPath) == '/' || ch == '\\')
51 pszPath++;
52 if (ch == '\0')
53 return 0;
54
55 /* Find the last char. */
56 while ((ch2 = *++pszPath) != '\0')
57 ch = ch2;
58
59 return ch == '/' || ch == '\\' || ch == ':';
60}
61
62
63static int birdIsPathDirSpec(const char *pszPath)
64{
65 char ch, ch2;
66
67 /* Check for empty string. */
68 ch = *pszPath;
69 if (ch == '\0')
70 return 0;
71
72 /* Find the last char. */
73 while ((ch2 = *++pszPath) != '\0')
74 ch = ch2;
75
76 return ch == '/' || ch == '\\' || ch == ':';
77}
78
79
80static int birdDosToNtPath(const char *pszPath, MY_UNICODE_STRING *pNtPath)
81{
82 MY_NTSTATUS rcNt;
83 WCHAR wszTmp[4096];
84 MY_UNICODE_STRING TmpUniStr;
85 MY_ANSI_STRING Src;
86
87 pNtPath->Length = pNtPath->MaximumLength = 0;
88 pNtPath->Buffer = NULL;
89
90 /*
91 * Convert the input to wide char.
92 */
93 Src.Buffer = (PCHAR)pszPath;
94 Src.MaximumLength = Src.Length = (USHORT)strlen(pszPath);
95
96 TmpUniStr.Length = 0;
97 TmpUniStr.MaximumLength = sizeof(wszTmp) - sizeof(WCHAR);
98 TmpUniStr.Buffer = wszTmp;
99
100 rcNt = g_pfnRtlAnsiStringToUnicodeString(&TmpUniStr, &Src, FALSE);
101 if (MY_NT_SUCCESS(rcNt))
102 {
103 if (TmpUniStr.Length > 0 && !(TmpUniStr.Length & 1))
104 {
105 wszTmp[TmpUniStr.Length / sizeof(WCHAR)] = '\0';
106
107 /*
108 * Convert the wide DOS path to an NT path.
109 */
110 if (g_pfnRtlDosPathNameToNtPathName_U(wszTmp, pNtPath, NULL, FALSE))
111 return 0;
112 }
113 rcNt = -1;
114 }
115 return birdSetErrnoFromNt(rcNt);
116}
117
118
119void birdFreeNtPath(MY_UNICODE_STRING *pNtPath)
120{
121 HeapFree(GetProcessHeap(), 0, pNtPath->Buffer);
122 pNtPath->Buffer = NULL;
123 pNtPath->Length = 0;
124 pNtPath->MaximumLength = 0;
125}
126
127
128static MY_NTSTATUS birdOpenFileInternal(MY_UNICODE_STRING *pNtPath, ACCESS_MASK fDesiredAccess, ULONG fFileAttribs,
129 ULONG fShareAccess, ULONG fCreateDisposition, ULONG fCreateOptions, ULONG fObjAttribs,
130 HANDLE *phFile)
131{
132 MY_IO_STATUS_BLOCK Ios;
133 MY_OBJECT_ATTRIBUTES ObjAttr;
134 MY_NTSTATUS rcNt;
135
136 if ( (fCreateOptions & FILE_OPEN_REPARSE_POINT)
137 && g_fHaveOpenReparsePoint == 0)
138 fCreateOptions &= ~FILE_OPEN_REPARSE_POINT;
139
140 Ios.Information = -1;
141 Ios.u.Status = 0;
142 MyInitializeObjectAttributes(&ObjAttr, pNtPath, fObjAttribs, NULL /*hRoot*/, NULL /*pSecAttr*/);
143
144 rcNt = g_pfnNtCreateFile(phFile,
145 fDesiredAccess,
146 &ObjAttr,
147 &Ios,
148 NULL, /* cbFileInitialAlloc */
149 fFileAttribs,
150 fShareAccess,
151 fCreateDisposition,
152 fCreateOptions,
153 NULL, /* pEaBuffer */
154 0); /* cbEaBuffer*/
155 if ( rcNt == STATUS_INVALID_PARAMETER
156 && g_fHaveOpenReparsePoint < 0
157 && (fCreateOptions & FILE_OPEN_REPARSE_POINT))
158 {
159 fCreateOptions &= ~FILE_OPEN_REPARSE_POINT;
160
161 Ios.Information = -1;
162 Ios.u.Status = 0;
163 MyInitializeObjectAttributes(&ObjAttr, pNtPath, fObjAttribs, NULL /*hRoot*/, NULL /*pSecAttr*/);
164
165 rcNt = g_pfnNtCreateFile(phFile,
166 fDesiredAccess,
167 &ObjAttr,
168 &Ios,
169 NULL, /* cbFileInitialAlloc */
170 fFileAttribs,
171 fShareAccess,
172 fCreateDisposition,
173 fCreateOptions,
174 NULL, /* pEaBuffer */
175 0); /* cbEaBuffer*/
176 if (rcNt != STATUS_INVALID_PARAMETER)
177 g_fHaveOpenReparsePoint = 0;
178 }
179 return rcNt;
180}
181
182
183HANDLE birdOpenFile(const char *pszPath, ACCESS_MASK fDesiredAccess, ULONG fFileAttribs, ULONG fShareAccess,
184 ULONG fCreateDisposition, ULONG fCreateOptions, ULONG fObjAttribs)
185{
186 MY_UNICODE_STRING NtPath;
187 MY_NTSTATUS rcNt;
188
189 birdResolveImports();
190
191 /*
192 * Adjust inputs.
193 */
194 if (birdIsPathDirSpec(pszPath))
195 fCreateOptions |= FILE_DIRECTORY_FILE;
196
197 /*
198 * Call the NT API directly.
199 */
200 if (birdDosToNtPath(pszPath, &NtPath) == 0)
201 {
202 HANDLE hFile;
203 rcNt = birdOpenFileInternal(&NtPath, fDesiredAccess, fFileAttribs, fShareAccess,
204 fCreateDisposition, fCreateOptions, fObjAttribs, &hFile);
205 if (MY_NT_SUCCESS(rcNt))
206 {
207 birdFreeNtPath(&NtPath);
208 return hFile;
209 }
210
211 birdFreeNtPath(&NtPath);
212 birdSetErrnoFromNt(rcNt);
213 }
214
215 return INVALID_HANDLE_VALUE;
216}
217
218
219HANDLE birdOpenParentDir(const char *pszPath, ACCESS_MASK fDesiredAccess, ULONG fFileAttribs, ULONG fShareAccess,
220 ULONG fCreateDisposition, ULONG fCreateOptions, ULONG fObjAttribs,
221 MY_UNICODE_STRING *pNameUniStr)
222{
223 MY_UNICODE_STRING NtPath;
224 MY_NTSTATUS rcNt;
225
226 birdResolveImports();
227
228 /*
229 * Adjust inputs.
230 */
231 fCreateOptions |= FILE_DIRECTORY_FILE;
232
233 /*
234 * Convert the path and split off the filename.
235 */
236 if (birdDosToNtPath(pszPath, &NtPath) == 0)
237 {
238 USHORT offName = NtPath.Length / sizeof(WCHAR);
239 USHORT cwcName = offName;
240 WCHAR wc = 0;
241
242 while ( offName > 0
243 && (wc = NtPath.Buffer[offName - 1]) != '\\'
244 && wc != '/'
245 && wc != ':')
246 offName--;
247 if (offName > 0)
248 {
249 cwcName -= offName;
250
251 /* Make a copy of the file name, if requested. */
252 rcNt = STATUS_SUCCESS;
253 if (pNameUniStr)
254 {
255 pNameUniStr->Length = cwcName * sizeof(WCHAR);
256 pNameUniStr->MaximumLength = pNameUniStr->Length + sizeof(WCHAR);
257 pNameUniStr->Buffer = (WCHAR *)HeapAlloc(GetProcessHeap(), 0, pNameUniStr->MaximumLength);
258 if (pNameUniStr->Buffer)
259 {
260 memcpy(pNameUniStr->Buffer, &NtPath.Buffer[offName],pNameUniStr->Length);
261 pNameUniStr->Buffer[cwcName] = '\0';
262 }
263 else
264 rcNt = STATUS_NO_MEMORY;
265 }
266
267 /* Chop, chop. */
268 // Bad idea, breaks \\?\c:\pagefile.sys. //while ( offName > 0
269 // Bad idea, breaks \\?\c:\pagefile.sys. // && ( (wc = NtPath.Buffer[offName - 1]) == '\\'
270 // Bad idea, breaks \\?\c:\pagefile.sys. // || wc == '/'))
271 // Bad idea, breaks \\?\c:\pagefile.sys. // offName--;
272 NtPath.Length = offName * sizeof(WCHAR);
273 NtPath.Buffer[offName] = '\0';
274 if (MY_NT_SUCCESS(rcNt))
275 {
276 /*
277 * Finally, try open the directory.
278 */
279 HANDLE hFile;
280 rcNt = birdOpenFileInternal(&NtPath, fDesiredAccess, fFileAttribs, fShareAccess,
281 fCreateDisposition, fCreateOptions, fObjAttribs, &hFile);
282 if (MY_NT_SUCCESS(rcNt))
283 {
284 birdFreeNtPath(&NtPath);
285 return hFile;
286 }
287 }
288
289 if (pNameUniStr)
290 birdFreeNtPath(pNameUniStr);
291 }
292
293 birdFreeNtPath(&NtPath);
294 birdSetErrnoFromNt(rcNt);
295 }
296
297 return INVALID_HANDLE_VALUE;
298}
299
300
301void birdCloseFile(HANDLE hFile)
302{
303 birdResolveImports();
304 g_pfnNtClose(hFile);
305}
306
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette