source: trunk/src/lib/nt/nthlpfs.c@ 3682

Last change on this file since 3682 was 3682, checked in by bird, 4 weeks ago

lib/nt,kmk: Fixed around rm/unlink semantics and general support for long file names in lib/nt.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 20.5 KB
Line 
1/* $Id: nthlpfs.c 3682 2025-08-12 23:34:19Z 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#include <stddef.h>
37#include <string.h>
38#include <wchar.h>
39#include <errno.h>
40
41
42/*******************************************************************************
43* Global Variables *
44*******************************************************************************/
45static int g_fHaveOpenReparsePoint = -1;
46
47
48
49static int birdHasTrailingSlash(const char *pszPath)
50{
51 char ch, ch2;
52
53 /* Skip leading slashes. */
54 while ((ch = *pszPath) == '/' || ch == '\\')
55 pszPath++;
56 if (ch == '\0')
57 return 0;
58
59 /* Find the last char. */
60 while ((ch2 = *++pszPath) != '\0')
61 ch = ch2;
62
63 return ch == '/' || ch == '\\' || ch == ':';
64}
65
66
67static int birdHasTrailingSlashW(const wchar_t *pwszPath)
68{
69 wchar_t wc, wc2;
70
71 /* Skip leading slashes. */
72 while ((wc = *pwszPath) == '/' || wc == '\\')
73 pwszPath++;
74 if (wc == '\0')
75 return 0;
76
77 /* Find the last char. */
78 while ((wc2 = *++pwszPath) != '\0')
79 wc = wc2;
80
81 return wc == '/' || wc == '\\' || wc == ':';
82}
83
84
85int birdIsPathDirSpec(const char *pszPath)
86{
87 char ch, ch2;
88
89 /* Check for empty string. */
90 ch = *pszPath;
91 if (ch == '\0')
92 return 0;
93
94 /* Find the last char. */
95 while ((ch2 = *++pszPath) != '\0')
96 ch = ch2;
97
98 return ch == '/' || ch == '\\' || ch == ':';
99}
100
101
102static int birdIsPathDirSpecW(const wchar_t *pwszPath)
103{
104 wchar_t wc, wc2;
105
106 /* Check for empty string. */
107 wc = *pwszPath;
108 if (wc == '\0')
109 return 0;
110
111 /* Find the last char. */
112 while ((wc2 = *++pwszPath) != '\0')
113 wc = wc2;
114
115 return wc == '/' || wc == '\\' || wc == ':';
116}
117
118
119int birdDosToNtPath(const char *pszPath, MY_UNICODE_STRING *pNtPath)
120{
121 MY_NTSTATUS rcNt;
122 WCHAR wszTmp[4096];
123 MY_UNICODE_STRING TmpUniStr;
124 MY_ANSI_STRING Src;
125
126 birdResolveImports();
127
128 pNtPath->Length = pNtPath->MaximumLength = 0;
129 pNtPath->Buffer = NULL;
130
131 /*
132 * Convert the input to wide char.
133 */
134 Src.Buffer = (PCHAR)pszPath;
135 Src.MaximumLength = Src.Length = (USHORT)strlen(pszPath);
136
137 TmpUniStr.Length = 0;
138 TmpUniStr.MaximumLength = sizeof(wszTmp) - sizeof(WCHAR);
139 TmpUniStr.Buffer = wszTmp;
140
141 rcNt = g_pfnRtlAnsiStringToUnicodeString(&TmpUniStr, &Src, FALSE);
142 if (MY_NT_SUCCESS(rcNt))
143 {
144 if (TmpUniStr.Length > 0 && !(TmpUniStr.Length & 1))
145 {
146 wszTmp[TmpUniStr.Length / sizeof(WCHAR)] = '\0';
147
148 /*
149 * Convert the wide DOS path to an NT path.
150 */
151 if (g_pfnRtlDosLongPathNameToNtPathName_U_WithStatus)
152 {
153 rcNt = g_pfnRtlDosLongPathNameToNtPathName_U_WithStatus(wszTmp, pNtPath, NULL, NULL);
154 if (MY_NT_SUCCESS(rcNt))
155 return 0;
156 }
157 else if (g_pfnRtlDosPathNameToNtPathName_U(wszTmp, pNtPath, NULL, NULL))
158 return 0;
159 else
160 rcNt = -1;
161 }
162 else
163 rcNt = -1;
164 }
165 return birdSetErrnoFromNt(rcNt);
166}
167
168
169int birdDosToNtPathW(const wchar_t *pwszPath, MY_UNICODE_STRING *pNtPath)
170{
171 birdResolveImports();
172
173 pNtPath->Length = pNtPath->MaximumLength = 0;
174 pNtPath->Buffer = NULL;
175
176 /*
177 * Convert the wide DOS path to an NT path.
178 */
179 if (g_pfnRtlDosLongPathNameToNtPathName_U_WithStatus)
180 {
181 MY_NTSTATUS rcNt = g_pfnRtlDosLongPathNameToNtPathName_U_WithStatus(pwszPath, pNtPath, NULL, NULL);
182 if (MY_NT_SUCCESS(rcNt))
183 return 0;
184 return birdSetErrnoFromNt(rcNt);
185 }
186 if (g_pfnRtlDosPathNameToNtPathName_U(pwszPath, pNtPath, NULL, NULL))
187 return 0;
188 return birdSetErrnoFromNt(STATUS_NO_MEMORY);
189}
190
191
192/**
193 * Converts UNIX slashes to DOS ones.
194 *
195 * @returns 0
196 * @param pNtPath The relative NT path to fix up.
197 */
198static int birdFixRelativeNtPathSlashesAndReturn0(MY_UNICODE_STRING *pNtPath)
199{
200 size_t cwcLeft = pNtPath->Length / sizeof(wchar_t);
201 wchar_t *pwcStart = pNtPath->Buffer;
202 wchar_t *pwcHit;
203
204 /* Convert slashes. */
205 while ((pwcHit = wmemchr(pwcStart, '/', cwcLeft)) != NULL)
206 {
207 *pwcHit = '\\';
208 cwcLeft -= pwcHit - pwcStart;
209 pwcHit = pwcStart;
210 }
211
212#if 0
213 /* Strip trailing slashes (NT doesn't like them). */
214 while ( pNtPath->Length >= sizeof(wchar_t)
215 && pNtPath->Buffer[(pNtPath->Length - sizeof(wchar_t)) / sizeof(wchar_t)] == '\\')
216 {
217 pNtPath->Length -= sizeof(wchar_t);
218 pNtPath->Buffer[pNtPath->Length / sizeof(wchar_t)] = '\0';
219 }
220
221 /* If it was all trailing slashes we convert it to a dot path. */
222 if ( pNtPath->Length == 0
223 && pNtPath->MaximumLength >= sizeof(wchar_t) * 2)
224 {
225 pNtPath->Length = sizeof(wchar_t);
226 pNtPath->Buffer[0] = '.';
227 pNtPath->Buffer[1] = '\0';
228 }
229#endif
230
231 return 0;
232}
233
234
235/**
236 * Similar to birdDosToNtPath, but it does call RtlDosPathNameToNtPathName_U.
237 *
238 * @returns 0 on success, -1 + errno on failure.
239 * @param pszPath The relative path.
240 * @param pNtPath Where to return the NT path. Call birdFreeNtPath when done.
241 */
242int birdDosToRelativeNtPath(const char *pszPath, MY_UNICODE_STRING *pNtPath)
243{
244 MY_NTSTATUS rcNt;
245 MY_ANSI_STRING Src;
246
247 birdResolveImports();
248
249 /*
250 * Just convert to wide char.
251 */
252 pNtPath->Length = pNtPath->MaximumLength = 0;
253 pNtPath->Buffer = NULL;
254
255 Src.Buffer = (PCHAR)pszPath;
256 Src.MaximumLength = Src.Length = (USHORT)strlen(pszPath);
257
258 rcNt = g_pfnRtlAnsiStringToUnicodeString(pNtPath, &Src, TRUE /* Allocate */);
259 if (MY_NT_SUCCESS(rcNt))
260 return birdFixRelativeNtPathSlashesAndReturn0(pNtPath);
261 return birdSetErrnoFromNt(rcNt);
262}
263
264
265/**
266 * Similar to birdDosToNtPathW, but it does call RtlDosPathNameToNtPathName_U.
267 *
268 * @returns 0 on success, -1 + errno on failure.
269 * @param pwszPath The relative path.
270 * @param pNtPath Where to return the NT path. Call birdFreeNtPath when done.
271 */
272int birdDosToRelativeNtPathW(const wchar_t *pwszPath, MY_UNICODE_STRING *pNtPath)
273{
274 size_t cwcPath = wcslen(pwszPath);
275 if (cwcPath < 0xfffe)
276 {
277 pNtPath->Length = (USHORT)(cwcPath * sizeof(wchar_t));
278 pNtPath->MaximumLength = pNtPath->Length + sizeof(wchar_t);
279 pNtPath->Buffer = HeapAlloc(GetProcessHeap(), 0, pNtPath->MaximumLength);
280 if (pNtPath->Buffer)
281 {
282 memcpy(pNtPath->Buffer, pwszPath, pNtPath->MaximumLength);
283 return birdFixRelativeNtPathSlashesAndReturn0(pNtPath);
284 }
285 errno = ENOMEM;
286 }
287 else
288 errno = ENAMETOOLONG;
289 return -1;
290}
291
292
293/**
294 * Frees a string returned by birdDosToNtPath, birdDosToNtPathW or
295 * birdDosToRelativeNtPath.
296 *
297 * @param pNtPath The the NT path to free.
298 */
299void birdFreeNtPath(MY_UNICODE_STRING *pNtPath)
300{
301 HeapFree(GetProcessHeap(), 0, pNtPath->Buffer);
302 pNtPath->Buffer = NULL;
303 pNtPath->Length = 0;
304 pNtPath->MaximumLength = 0;
305}
306
307
308MY_NTSTATUS birdOpenFileUniStr(HANDLE hRoot, MY_UNICODE_STRING *pNtPath, ACCESS_MASK fDesiredAccess, ULONG fFileAttribs,
309 ULONG fShareAccess, ULONG fCreateDisposition, ULONG fCreateOptions, ULONG fObjAttribs,
310 HANDLE *phFile)
311{
312 MY_IO_STATUS_BLOCK Ios;
313 MY_OBJECT_ATTRIBUTES ObjAttr;
314 MY_NTSTATUS rcNt;
315
316 birdResolveImports();
317
318 if ( (fCreateOptions & FILE_OPEN_REPARSE_POINT)
319 && g_fHaveOpenReparsePoint == 0)
320 fCreateOptions &= ~FILE_OPEN_REPARSE_POINT;
321
322 Ios.Information = -1;
323 Ios.u.Status = 0;
324 MyInitializeObjectAttributes(&ObjAttr, pNtPath, fObjAttribs, hRoot, NULL /*pSecAttr*/);
325
326 rcNt = g_pfnNtCreateFile(phFile,
327 fDesiredAccess,
328 &ObjAttr,
329 &Ios,
330 NULL, /* cbFileInitialAlloc */
331 fFileAttribs,
332 fShareAccess,
333 fCreateDisposition,
334 fCreateOptions,
335 NULL, /* pEaBuffer */
336 0); /* cbEaBuffer*/
337 if ( rcNt == STATUS_INVALID_PARAMETER
338 && g_fHaveOpenReparsePoint < 0
339 && (fCreateOptions & FILE_OPEN_REPARSE_POINT))
340 {
341 fCreateOptions &= ~FILE_OPEN_REPARSE_POINT;
342
343 Ios.Information = -1;
344 Ios.u.Status = 0;
345 MyInitializeObjectAttributes(&ObjAttr, pNtPath, fObjAttribs, NULL /*hRoot*/, NULL /*pSecAttr*/);
346
347 rcNt = g_pfnNtCreateFile(phFile,
348 fDesiredAccess,
349 &ObjAttr,
350 &Ios,
351 NULL, /* cbFileInitialAlloc */
352 fFileAttribs,
353 fShareAccess,
354 fCreateDisposition,
355 fCreateOptions,
356 NULL, /* pEaBuffer */
357 0); /* cbEaBuffer*/
358 if (rcNt != STATUS_INVALID_PARAMETER)
359 g_fHaveOpenReparsePoint = 0;
360 }
361 return rcNt;
362}
363
364
365HANDLE birdOpenFile(const char *pszPath, ACCESS_MASK fDesiredAccess, ULONG fFileAttribs,
366 ULONG fShareAccess, ULONG fCreateDisposition, ULONG fCreateOptions, ULONG fObjAttribs)
367{
368 MY_UNICODE_STRING NtPath;
369 MY_NTSTATUS rcNt;
370
371 /*
372 * Adjust inputs.
373 */
374 if (birdIsPathDirSpec(pszPath))
375 fCreateOptions |= FILE_DIRECTORY_FILE;
376
377 /*
378 * Convert the path and call birdOpenFileUniStr to do the real work.
379 */
380 if (birdDosToNtPath(pszPath, &NtPath) == 0)
381 {
382 HANDLE hFile;
383 rcNt = birdOpenFileUniStr(NULL /*hRoot*/, &NtPath, fDesiredAccess, fFileAttribs, fShareAccess,
384 fCreateDisposition, fCreateOptions, fObjAttribs, &hFile);
385 birdFreeNtPath(&NtPath);
386 if (MY_NT_SUCCESS(rcNt))
387 return hFile;
388 birdSetErrnoFromNt(rcNt);
389 }
390
391 return INVALID_HANDLE_VALUE;
392}
393
394
395HANDLE birdOpenFileW(const wchar_t *pwszPath, ACCESS_MASK fDesiredAccess, ULONG fFileAttribs,
396 ULONG fShareAccess, ULONG fCreateDisposition, ULONG fCreateOptions, ULONG fObjAttribs)
397{
398 MY_UNICODE_STRING NtPath;
399 MY_NTSTATUS rcNt;
400
401 /*
402 * Adjust inputs.
403 */
404 if (birdIsPathDirSpecW(pwszPath))
405 fCreateOptions |= FILE_DIRECTORY_FILE;
406
407 /*
408 * Convert the path and call birdOpenFileUniStr to do the real work.
409 */
410 if (birdDosToNtPathW(pwszPath, &NtPath) == 0)
411 {
412 HANDLE hFile;
413 rcNt = birdOpenFileUniStr(NULL /*hRoot*/, &NtPath, fDesiredAccess, fFileAttribs, fShareAccess,
414 fCreateDisposition, fCreateOptions, fObjAttribs, &hFile);
415 birdFreeNtPath(&NtPath);
416 if (MY_NT_SUCCESS(rcNt))
417 return hFile;
418 birdSetErrnoFromNt(rcNt);
419 }
420
421 return INVALID_HANDLE_VALUE;
422}
423
424
425HANDLE birdOpenFileEx(HANDLE hRoot, const char *pszPath, ACCESS_MASK fDesiredAccess, ULONG fFileAttribs,
426 ULONG fShareAccess, ULONG fCreateDisposition, ULONG fCreateOptions, ULONG fObjAttribs)
427{
428 MY_UNICODE_STRING NtPath;
429 MY_NTSTATUS rcNt;
430
431 /*
432 * Adjust inputs.
433 */
434 if (birdIsPathDirSpec(pszPath))
435 fCreateOptions |= FILE_DIRECTORY_FILE;
436
437 /*
438 * Convert the path and call birdOpenFileUniStr to do the real work.
439 */
440 if (hRoot == INVALID_HANDLE_VALUE)
441 hRoot = NULL;
442 if ((hRoot != NULL ? birdDosToRelativeNtPath(pszPath, &NtPath) : birdDosToNtPath(pszPath, &NtPath)) == 0)
443 {
444 HANDLE hFile;
445 rcNt = birdOpenFileUniStr(hRoot, &NtPath, fDesiredAccess, fFileAttribs, fShareAccess,
446 fCreateDisposition, fCreateOptions, fObjAttribs, &hFile);
447 birdFreeNtPath(&NtPath);
448 if (MY_NT_SUCCESS(rcNt))
449 return hFile;
450 birdSetErrnoFromNt(rcNt);
451 }
452
453 return INVALID_HANDLE_VALUE;
454}
455
456
457HANDLE birdOpenFileExW(HANDLE hRoot, const wchar_t *pwszPath, ACCESS_MASK fDesiredAccess, ULONG fFileAttribs,
458 ULONG fShareAccess, ULONG fCreateDisposition, ULONG fCreateOptions, ULONG fObjAttribs)
459{
460 MY_UNICODE_STRING NtPath;
461 MY_NTSTATUS rcNt;
462
463 /*
464 * Adjust inputs.
465 */
466 if (birdIsPathDirSpecW(pwszPath))
467 fCreateOptions |= FILE_DIRECTORY_FILE;
468
469 /*
470 * Convert the path (could save ourselves this if pwszPath is perfect) and
471 * call birdOpenFileUniStr to do the real work.
472 */
473 if (hRoot == INVALID_HANDLE_VALUE)
474 hRoot = NULL;
475 if ((hRoot != NULL ? birdDosToRelativeNtPathW(pwszPath, &NtPath) : birdDosToNtPathW(pwszPath, &NtPath)) == 0)
476 {
477 HANDLE hFile;
478 rcNt = birdOpenFileUniStr(hRoot, &NtPath, fDesiredAccess, fFileAttribs, fShareAccess,
479 fCreateDisposition, fCreateOptions, fObjAttribs, &hFile);
480 birdFreeNtPath(&NtPath);
481 if (MY_NT_SUCCESS(rcNt))
482 return hFile;
483 birdSetErrnoFromNt(rcNt);
484 }
485
486 return INVALID_HANDLE_VALUE;
487}
488
489
490static HANDLE birdOpenParentDirCommon(HANDLE hRoot, MY_UNICODE_STRING *pNtPath, ACCESS_MASK fDesiredAccess, ULONG fFileAttribs,
491 ULONG fShareAccess, ULONG fCreateDisposition, ULONG fCreateOptions, ULONG fObjAttribs,
492 MY_UNICODE_STRING *pNameUniStr)
493{
494 MY_NTSTATUS rcNt;
495
496 /*
497 * Strip the path down to the directory.
498 */
499 USHORT offName = pNtPath->Length / sizeof(WCHAR);
500 USHORT cwcName = offName;
501 WCHAR wc = 0;
502 while ( offName > 0
503 && (wc = pNtPath->Buffer[offName - 1]) != '\\'
504 && wc != '/'
505 && wc != ':')
506 offName--;
507 if ( offName > 0
508 || (hRoot != NULL && cwcName > 0))
509 {
510 cwcName -= offName;
511
512 /* Make a copy of the file name, if requested. */
513 rcNt = STATUS_SUCCESS;
514 if (pNameUniStr)
515 {
516 pNameUniStr->Length = cwcName * sizeof(WCHAR);
517 pNameUniStr->MaximumLength = pNameUniStr->Length + sizeof(WCHAR);
518 pNameUniStr->Buffer = (WCHAR *)HeapAlloc(GetProcessHeap(), 0, pNameUniStr->MaximumLength);
519 if (pNameUniStr->Buffer)
520 {
521 memcpy(pNameUniStr->Buffer, &pNtPath->Buffer[offName], pNameUniStr->Length);
522 pNameUniStr->Buffer[cwcName] = '\0';
523 }
524 else
525 rcNt = STATUS_NO_MEMORY;
526 }
527
528 /* Chop, chop. */
529 // Bad idea, breaks \\?\c:\pagefile.sys. //while ( offName > 0
530 // Bad idea, breaks \\?\c:\pagefile.sys. // && ( (wc = pNtPath->Buffer[offName - 1]) == '\\'
531 // Bad idea, breaks \\?\c:\pagefile.sys. // || wc == '/'))
532 // Bad idea, breaks \\?\c:\pagefile.sys. // offName--;
533 if (offName == 0)
534 pNtPath->Buffer[offName++] = '.'; /* Hack for dir handle + dir entry name. */
535 pNtPath->Length = offName * sizeof(WCHAR);
536 pNtPath->Buffer[offName] = '\0';
537 if (MY_NT_SUCCESS(rcNt))
538 {
539 /*
540 * Finally, try open the directory.
541 */
542 HANDLE hFile;
543 fCreateOptions |= FILE_DIRECTORY_FILE;
544 rcNt = birdOpenFileUniStr(hRoot, pNtPath, fDesiredAccess, fFileAttribs, fShareAccess,
545 fCreateDisposition, fCreateOptions, fObjAttribs, &hFile);
546 if (MY_NT_SUCCESS(rcNt))
547 {
548 birdFreeNtPath(pNtPath);
549 return hFile;
550 }
551 }
552
553 if (pNameUniStr)
554 birdFreeNtPath(pNameUniStr);
555 }
556 else
557 rcNt = STATUS_INVALID_PARAMETER;
558
559 birdFreeNtPath(pNtPath);
560 birdSetErrnoFromNt(rcNt);
561 return INVALID_HANDLE_VALUE;
562}
563
564
565HANDLE birdOpenParentDir(HANDLE hRoot, const char *pszPath, ACCESS_MASK fDesiredAccess, ULONG fFileAttribs,
566 ULONG fShareAccess, ULONG fCreateDisposition, ULONG fCreateOptions, ULONG fObjAttribs,
567 MY_UNICODE_STRING *pNameUniStr)
568{
569 /*
570 * Convert the path and join up with the UTF-16 version (it'll free NtPath).
571 */
572 MY_UNICODE_STRING NtPath;
573 if (hRoot == INVALID_HANDLE_VALUE)
574 hRoot = NULL;
575 if ( hRoot == NULL
576 ? birdDosToNtPath(pszPath, &NtPath) == 0
577 : birdDosToRelativeNtPath(pszPath, &NtPath) == 0)
578 return birdOpenParentDirCommon(hRoot, &NtPath, fDesiredAccess, fFileAttribs, fShareAccess,
579 fCreateDisposition, fCreateOptions, fObjAttribs, pNameUniStr);
580 return INVALID_HANDLE_VALUE;
581}
582
583
584HANDLE birdOpenParentDirW(HANDLE hRoot, const wchar_t *pwszPath, ACCESS_MASK fDesiredAccess, ULONG fFileAttribs,
585 ULONG fShareAccess, ULONG fCreateDisposition, ULONG fCreateOptions, ULONG fObjAttribs,
586 MY_UNICODE_STRING *pNameUniStr)
587{
588 /*
589 * Convert the path and join up with the ansi version (it'll free NtPath).
590 */
591 MY_UNICODE_STRING NtPath;
592 if (hRoot == INVALID_HANDLE_VALUE)
593 hRoot = NULL;
594 if ( hRoot == NULL
595 ? birdDosToNtPathW(pwszPath, &NtPath) == 0
596 : birdDosToRelativeNtPathW(pwszPath, &NtPath) == 0)
597 return birdOpenParentDirCommon(hRoot, &NtPath, fDesiredAccess, fFileAttribs, fShareAccess,
598 fCreateDisposition, fCreateOptions, fObjAttribs, pNameUniStr);
599 return INVALID_HANDLE_VALUE;
600}
601
602
603/**
604 * Returns a handle to the current working directory of the process.
605 *
606 * @returns CWD handle with FILE_TRAVERSE and SYNCHRONIZE access. May return
607 * INVALID_HANDLE_VALUE w/ errno for invalid CWD.
608 */
609HANDLE birdOpenCurrentDirectory(void)
610{
611 PMY_RTL_USER_PROCESS_PARAMETERS pProcParams;
612 MY_NTSTATUS rcNt;
613 HANDLE hRet = INVALID_HANDLE_VALUE;
614
615 birdResolveImports();
616
617 /*
618 * We'll try get this from the PEB.
619 */
620 g_pfnRtlAcquirePebLock();
621 pProcParams = (PMY_RTL_USER_PROCESS_PARAMETERS)MY_NT_CURRENT_PEB()->ProcessParameters;
622 if (pProcParams != NULL)
623 rcNt = g_pfnNtDuplicateObject(MY_NT_CURRENT_PROCESS, pProcParams->CurrentDirectory.Handle,
624 MY_NT_CURRENT_PROCESS, &hRet,
625 FILE_TRAVERSE | SYNCHRONIZE,
626 0 /*fAttribs*/,
627 0 /*fOptions*/);
628 else
629 rcNt = STATUS_INVALID_PARAMETER;
630 g_pfnRtlReleasePebLock();
631 if (MY_NT_SUCCESS(rcNt))
632 return hRet;
633
634 /*
635 * Fallback goes thru birdOpenFileW.
636 */
637 return birdOpenFileW(L".",
638 FILE_TRAVERSE | SYNCHRONIZE,
639 FILE_ATTRIBUTE_NORMAL,
640 FILE_SHARE_READ | FILE_SHARE_WRITE,
641 FILE_OPEN,
642 FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT,
643 OBJ_CASE_INSENSITIVE);
644}
645
646
647void birdCloseFile(HANDLE hFile)
648{
649 birdResolveImports();
650 g_pfnNtClose(hFile);
651}
652
Note: See TracBrowser for help on using the repository browser.