summaryrefslogtreecommitdiffstats
path: root/src/lib/nt/nthlpcore.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/nt/nthlpcore.c')
-rw-r--r--src/lib/nt/nthlpcore.c481
1 files changed, 481 insertions, 0 deletions
diff --git a/src/lib/nt/nthlpcore.c b/src/lib/nt/nthlpcore.c
new file mode 100644
index 0000000..fe40c5e
--- /dev/null
+++ b/src/lib/nt/nthlpcore.c
@@ -0,0 +1,481 @@
+/* $Id: nthlpcore.c 3534 2021-12-20 23:31:55Z bird $ */
+/** @file
+ * MSC + NT core helpers functions and globals.
+ */
+
+/*
+ * Copyright (c) 2005-2013 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Alternatively, the content of this file may be used under the terms of the
+ * GPL version 2 or later, or LGPL version 2.1 or later.
+ */
+
+/*******************************************************************************
+* Header Files *
+*******************************************************************************/
+#include <errno.h>
+#include "nthlp.h"
+#ifndef NDEBUG
+# include <stdio.h>
+#endif
+
+
+/*******************************************************************************
+* Global Variables *
+*******************************************************************************/
+MY_NTSTATUS (WINAPI *g_pfnNtClose)(HANDLE);
+MY_NTSTATUS (WINAPI *g_pfnNtCreateFile)(PHANDLE, MY_ACCESS_MASK, MY_OBJECT_ATTRIBUTES *, MY_IO_STATUS_BLOCK *,
+ PLARGE_INTEGER, ULONG, ULONG, ULONG, ULONG, PVOID, ULONG);
+MY_NTSTATUS (WINAPI *g_pfnNtDeleteFile)(MY_OBJECT_ATTRIBUTES *);
+MY_NTSTATUS (WINAPI *g_pfnNtDuplicateObject)(HANDLE hSrcProc, HANDLE hSrc, HANDLE hDstProc, HANDLE *phRet,
+ MY_ACCESS_MASK fDesiredAccess, ULONG fAttribs, ULONG fOptions);
+MY_NTSTATUS (WINAPI *g_pfnNtReadFile)(HANDLE hFile, HANDLE hEvent, MY_IO_APC_ROUTINE *pfnApc, PVOID pvApcCtx,
+ MY_IO_STATUS_BLOCK *, PVOID pvBuf, ULONG cbToRead, PLARGE_INTEGER poffFile,
+ PULONG puKey);
+MY_NTSTATUS (WINAPI *g_pfnNtQueryInformationFile)(HANDLE, MY_IO_STATUS_BLOCK *, PVOID, LONG, MY_FILE_INFORMATION_CLASS);
+MY_NTSTATUS (WINAPI *g_pfnNtQueryVolumeInformationFile)(HANDLE, MY_IO_STATUS_BLOCK *, PVOID, LONG, MY_FS_INFORMATION_CLASS);
+MY_NTSTATUS (WINAPI *g_pfnNtQueryDirectoryFile)(HANDLE, HANDLE, MY_IO_APC_ROUTINE *, PVOID, MY_IO_STATUS_BLOCK *,
+ PVOID, ULONG, MY_FILE_INFORMATION_CLASS, BOOLEAN,
+ MY_UNICODE_STRING *, BOOLEAN);
+MY_NTSTATUS (WINAPI *g_pfnNtQueryAttributesFile)(MY_OBJECT_ATTRIBUTES *, MY_FILE_BASIC_INFORMATION *);
+MY_NTSTATUS (WINAPI *g_pfnNtQueryFullAttributesFile)(MY_OBJECT_ATTRIBUTES *, MY_FILE_NETWORK_OPEN_INFORMATION *);
+MY_NTSTATUS (WINAPI *g_pfnNtSetInformationFile)(HANDLE, MY_IO_STATUS_BLOCK *, PVOID, LONG, MY_FILE_INFORMATION_CLASS);
+BOOLEAN (WINAPI *g_pfnRtlDosPathNameToNtPathName_U)(PCWSTR, MY_UNICODE_STRING *, PCWSTR *, MY_RTL_RELATIVE_NAME_U *);
+MY_NTSTATUS (WINAPI *g_pfnRtlAnsiStringToUnicodeString)(MY_UNICODE_STRING *, MY_ANSI_STRING const *, BOOLEAN);
+MY_NTSTATUS (WINAPI *g_pfnRtlUnicodeStringToAnsiString)(MY_ANSI_STRING *, MY_UNICODE_STRING *, BOOLEAN);
+BOOLEAN (WINAPI *g_pfnRtlEqualUnicodeString)(MY_UNICODE_STRING const *, MY_UNICODE_STRING const *, BOOLEAN);
+BOOLEAN (WINAPI *g_pfnRtlEqualString)(MY_ANSI_STRING const *, MY_ANSI_STRING const *, BOOLEAN);
+UCHAR (WINAPI *g_pfnRtlUpperChar)(UCHAR uch);
+ULONG (WINAPI *g_pfnRtlNtStatusToDosError)(MY_NTSTATUS rcNt);
+VOID (WINAPI *g_pfnRtlAcquirePebLock)(VOID);
+VOID (WINAPI *g_pfnRtlReleasePebLock)(VOID);
+
+static struct
+{
+ FARPROC *ppfn;
+ const char *pszName;
+} const g_apfnDynamicNtdll[] =
+{
+ { (FARPROC *)&g_pfnNtClose, "NtClose" },
+ { (FARPROC *)&g_pfnNtCreateFile, "NtCreateFile" },
+ { (FARPROC *)&g_pfnNtDeleteFile, "NtDeleteFile" },
+ { (FARPROC *)&g_pfnNtDuplicateObject, "NtDuplicateObject" },
+ { (FARPROC *)&g_pfnNtReadFile, "NtReadFile" },
+ { (FARPROC *)&g_pfnNtQueryInformationFile, "NtQueryInformationFile" },
+ { (FARPROC *)&g_pfnNtQueryVolumeInformationFile, "NtQueryVolumeInformationFile" },
+ { (FARPROC *)&g_pfnNtQueryDirectoryFile, "NtQueryDirectoryFile" },
+ { (FARPROC *)&g_pfnNtQueryAttributesFile, "NtQueryAttributesFile" },
+ { (FARPROC *)&g_pfnNtQueryFullAttributesFile, "NtQueryFullAttributesFile" },
+ { (FARPROC *)&g_pfnNtSetInformationFile, "NtSetInformationFile" },
+ { (FARPROC *)&g_pfnRtlDosPathNameToNtPathName_U, "RtlDosPathNameToNtPathName_U" },
+ { (FARPROC *)&g_pfnRtlAnsiStringToUnicodeString, "RtlAnsiStringToUnicodeString" },
+ { (FARPROC *)&g_pfnRtlUnicodeStringToAnsiString, "RtlUnicodeStringToAnsiString" },
+ { (FARPROC *)&g_pfnRtlEqualUnicodeString, "RtlEqualUnicodeString" },
+ { (FARPROC *)&g_pfnRtlEqualString, "RtlEqualString" },
+ { (FARPROC *)&g_pfnRtlUpperChar, "RtlUpperChar" },
+ { (FARPROC *)&g_pfnRtlNtStatusToDosError, "RtlNtStatusToDosError" },
+ { (FARPROC *)&g_pfnRtlAcquirePebLock, "RtlAcquirePebLock" },
+ { (FARPROC *)&g_pfnRtlReleasePebLock, "RtlReleasePebLock" },
+};
+/** Set to 1 if we've successfully resolved the imports, otherwise 0. */
+int g_fResolvedNtImports = 0;
+
+
+
+void birdResolveImportsWorker(void)
+{
+ HMODULE hMod = LoadLibraryW(L"ntdll.dll");
+ int i = sizeof(g_apfnDynamicNtdll) / sizeof(g_apfnDynamicNtdll[0]);
+ while (i-- > 0)
+ {
+ const char *pszSym = g_apfnDynamicNtdll[i].pszName;
+ FARPROC pfn;
+ *g_apfnDynamicNtdll[i].ppfn = pfn = GetProcAddress(hMod, pszSym);
+ if (!pfn)
+ {
+ /* Write short message and die. */
+ static const char s_szMsg[] = "\r\nFatal error resolving NTDLL.DLL symbols!\r\nSymbol: ";
+ DWORD cbWritten;
+ if ( !WriteFile(GetStdHandle(STD_ERROR_HANDLE), s_szMsg, sizeof(s_szMsg) - 1, &cbWritten, NULL)
+ || !WriteFile(GetStdHandle(STD_ERROR_HANDLE), pszSym, (DWORD)strlen(pszSym), &cbWritten, NULL)
+ || !WriteFile(GetStdHandle(STD_ERROR_HANDLE), "\r\n", sizeof("\r\n") - 1, &cbWritten, NULL)
+ )
+ *(void **)(size_t)i = NULL;
+ ExitProcess(127);
+ }
+ }
+
+ g_fResolvedNtImports = 1;
+}
+
+
+void *birdTmpAlloc(size_t cb)
+{
+ return malloc(cb);
+}
+
+
+void birdTmpFree(void *pv)
+{
+ if (pv)
+ free(pv);
+}
+
+
+void *birdMemAlloc(size_t cb)
+{
+ return malloc(cb);
+}
+
+
+void *birdMemAllocZ(size_t cb)
+{
+ return calloc(cb, 1);
+}
+
+
+void birdMemFree(void *pv)
+{
+ if (pv)
+ free(pv);
+}
+
+
+int birdErrnoFromNtStatus(MY_NTSTATUS rcNt)
+{
+ switch (rcNt)
+ {
+ /* EPERM = 1 */
+ case STATUS_CANNOT_DELETE:
+ return EPERM;
+ /* ENOENT = 2 */
+ case STATUS_NOT_FOUND:
+ case STATUS_OBJECT_NAME_NOT_FOUND:
+ case STATUS_OBJECT_PATH_NOT_FOUND:
+ case STATUS_OBJECT_NAME_INVALID:
+ case STATUS_INVALID_COMPUTER_NAME:
+ case STATUS_VARIABLE_NOT_FOUND:
+ case STATUS_MESSAGE_NOT_FOUND:
+ case STATUS_DLL_NOT_FOUND:
+ case STATUS_ORDINAL_NOT_FOUND:
+ case STATUS_ENTRYPOINT_NOT_FOUND:
+ case STATUS_PATH_NOT_COVERED:
+ case STATUS_BAD_NETWORK_PATH:
+ case STATUS_DFS_EXIT_PATH_FOUND:
+ case RPC_NT_OBJECT_NOT_FOUND:
+ case STATUS_DELETE_PENDING:
+ return ENOENT;
+ /* ESRCH = 3 */
+ case STATUS_PROCESS_NOT_IN_JOB:
+ return ESRCH;
+ /* EINTR = 4 */
+ case STATUS_ALERTED:
+ case STATUS_USER_APC:
+ return EINTR;
+ /* EIO = 5 */
+ /* ENXIO = 6 */
+ /* E2BIG = 7 */
+ /* ENOEXEC = 8 */
+ case STATUS_INVALID_IMAGE_FORMAT:
+ case STATUS_INVALID_IMAGE_NE_FORMAT:
+ case STATUS_INVALID_IMAGE_LE_FORMAT:
+ case STATUS_INVALID_IMAGE_NOT_MZ:
+ case STATUS_INVALID_IMAGE_PROTECT:
+ case STATUS_INVALID_IMAGE_WIN_16:
+ case STATUS_IMAGE_SUBSYSTEM_NOT_PRESENT:
+ case STATUS_IMAGE_CHECKSUM_MISMATCH:
+ case STATUS_IMAGE_MP_UP_MISMATCH:
+ case STATUS_IMAGE_MACHINE_TYPE_MISMATCH:
+ case STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE:
+ case STATUS_SYSTEM_IMAGE_BAD_SIGNATURE:
+ case STATUS_SECTION_NOT_IMAGE:
+ case STATUS_INVALID_IMAGE_WIN_32:
+ case STATUS_INVALID_IMAGE_WIN_64:
+ case STATUS_INVALID_IMAGE_HASH:
+ case STATUS_IMAGE_CERT_REVOKED:
+ return ENOEXEC;
+ /* EBADF = 9 */
+ case STATUS_INVALID_HANDLE:
+ case STATUS_PORT_CLOSED:
+ case STATUS_OPLOCK_HANDLE_CLOSED:
+ case STATUS_HANDLES_CLOSED:
+ case STATUS_FILE_FORCED_CLOSED:
+ return EBADF;
+ /* ECHILD = 10 */
+ /* EAGAIN = 11 */
+ case STATUS_WMI_TRY_AGAIN:
+ case STATUS_GRAPHICS_TRY_AGAIN_LATER:
+ case STATUS_GRAPHICS_TRY_AGAIN_NOW:
+ return EAGAIN;
+ /* ENOMEM = 12 */
+ case STATUS_NO_MEMORY:
+ case STATUS_HV_INSUFFICIENT_MEMORY:
+ case STATUS_INSUFFICIENT_RESOURCES:
+ case STATUS_REMOTE_RESOURCES:
+ case STATUS_INSUFF_SERVER_RESOURCES:
+ return ENOMEM;
+ /* EACCES = 13 */
+ case STATUS_ACCESS_DENIED:
+ case STATUS_NETWORK_ACCESS_DENIED:
+ case RPC_NT_PROXY_ACCESS_DENIED:
+ case STATUS_CTX_SHADOW_DENIED:
+ case STATUS_CTX_WINSTATION_ACCESS_DENIED:
+ return EACCES;
+ /* EFAULT = 14 */
+ case STATUS_ACCESS_VIOLATION:
+ case STATUS_HARDWARE_MEMORY_ERROR:
+ return EFAULT;
+ /* EBUSY = 16 */
+ case STATUS_PIPE_BUSY:
+ case STATUS_RESOURCE_IN_USE:
+ return EBUSY;
+ /* EEXIST = 17 */
+ case STATUS_OBJECT_NAME_EXISTS:
+ case STATUS_OBJECT_NAME_COLLISION:
+ case STATUS_DUPLICATE_NAME:
+ return EEXIST;
+ /* EXDEV = 18 */
+ case STATUS_NOT_SAME_DEVICE:
+ return EXDEV;
+ /* ENODEV = 19 */
+ /* ENOTDIR = 20 */
+ case STATUS_NOT_A_DIRECTORY:
+ case STATUS_DIRECTORY_IS_A_REPARSE_POINT:
+ case STATUS_OBJECT_PATH_SYNTAX_BAD:
+ case STATUS_OBJECT_PATH_INVALID:
+ case STATUS_OBJECT_TYPE_MISMATCH:
+ return ENOTDIR;
+ /* EISDIR = 21 */
+ case STATUS_FILE_IS_A_DIRECTORY:
+ return EISDIR;
+ /* EINVAL = 22 */
+ case STATUS_INVALID_PARAMETER:
+ case STATUS_INVALID_PARAMETER_1:
+ case STATUS_INVALID_PARAMETER_2:
+ case STATUS_INVALID_PARAMETER_3:
+ case STATUS_INVALID_PARAMETER_4:
+ case STATUS_INVALID_PARAMETER_5:
+ case STATUS_INVALID_PARAMETER_6:
+ case STATUS_INVALID_PARAMETER_7:
+ case STATUS_INVALID_PARAMETER_8:
+ case STATUS_INVALID_PARAMETER_9:
+ case STATUS_INVALID_PARAMETER_10:
+ case STATUS_INVALID_PARAMETER_11:
+ case STATUS_INVALID_PARAMETER_12:
+ case STATUS_INVALID_PARAMETER_MIX:
+ return EINVAL;
+ /* ENFILE = 23 */
+ /* EMFILE = 24 */
+ case STATUS_TOO_MANY_OPENED_FILES:
+ return EMFILE;
+ /* ENOTTY = 25 */
+ /* EFBIG = 27 */
+ /* ENOSPC = 28 */
+ case STATUS_DISK_FULL:
+ return ENOSPC;
+ /* ESPIPE = 29 */
+ /* EROFS = 30 */
+ /* EMLINK = 31 */
+ /* EPIPE = 32 */
+ case STATUS_PIPE_BROKEN:
+ case RPC_NT_PIPE_CLOSED:
+ return EPIPE;
+ /* EDOM = 33 */
+ /* ERANGE = 34 */
+ /* EDEADLK = 36 */
+ case STATUS_POSSIBLE_DEADLOCK:
+ return EDEADLK;
+ /* ENAMETOOLONG = 38 */
+ case STATUS_NAME_TOO_LONG:
+ return ENAMETOOLONG;
+ /* ENOLCK = 39 */
+ /* ENOSYS = 40 */
+ case STATUS_NOT_SUPPORTED:
+ return ENOSYS;
+ /* ENOTEMPTY = 41 */
+ case STATUS_DIRECTORY_NOT_EMPTY:
+ return ENOTEMPTY;
+ /* EILSEQ = 42 */
+ /* EADDRINUSE = 100 */
+ /* EADDRNOTAVAIL = 101 */
+ /* EAFNOSUPPORT = 102 */
+ /* EALREADY = 103 */
+ case STATUS_INTERRUPT_VECTOR_ALREADY_CONNECTED:
+ case STATUS_DEVICE_ALREADY_ATTACHED:
+ case STATUS_PORT_ALREADY_SET:
+ case STATUS_IMAGE_ALREADY_LOADED:
+ case STATUS_TOKEN_ALREADY_IN_USE:
+ case STATUS_IMAGE_ALREADY_LOADED_AS_DLL:
+ case STATUS_ADDRESS_ALREADY_EXISTS:
+ case STATUS_ADDRESS_ALREADY_ASSOCIATED:
+ return EALREADY;
+ /* EBADMSG = 104 */
+ /* ECANCELED = 105 */
+ /* ECONNABORTED = 106 */
+ /* ECONNREFUSED = 107 */
+ /* ECONNRESET = 108 */
+ /* EDESTADDRREQ = 109 */
+ /* EHOSTUNREACH = 110 */
+ case STATUS_HOST_UNREACHABLE:
+ return EHOSTUNREACH;
+ /* EIDRM = 111 */
+ /* EINPROGRESS = 112 */
+ /* EISCONN = 113 */
+ /* ELOOP = 114 */
+ /* EMSGSIZE = 115 */
+ /* ENETDOWN = 116 */
+ /* ENETRESET = 117 */
+ /* ENETUNREACH = 118 */
+ case STATUS_NETWORK_UNREACHABLE:
+ return ENETUNREACH;
+ /* ENOBUFS = 119 */
+ /* ENODATA = 120 */
+ /* ENOLINK = 121 */
+ /* ENOMSG = 122 */
+ /* ENOPROTOOPT = 123 */
+ /* ENOSR = 124 */
+ /* ENOSTR = 125 */
+ /* ENOTCONN = 126 */
+ /* ENOTRECOVERABLE = 127 */
+ /* ENOTSOCK = 128 */
+ /* ENOTSUP = 129 */
+ /* EOPNOTSUPP = 130 */
+ /* EOTHER = 131 */
+ /* EOVERFLOW = 132 */
+ /* EOWNERDEAD = 133 */
+ /* EPROTO = 134 */
+ /* EPROTONOSUPPORT = 135 */
+ /* EPROTOTYPE = 136 */
+ /* ETIME = 137 */
+ /* ETIMEDOUT = 138 */
+ case STATUS_VIRTUAL_CIRCUIT_CLOSED:
+ case STATUS_TIMEOUT:
+ return ETIMEDOUT;
+
+ /* ETXTBSY = 139 */
+ case STATUS_SHARING_VIOLATION:
+ return ETXTBSY;
+ /* EWOULDBLOCK = 140 */
+ }
+
+#ifndef NDEBUG
+ __debugbreak();
+ fprintf(stderr, "rcNt=%#x (%d)\n", rcNt, rcNt);
+#endif
+ return EINVAL;
+}
+
+
+int birdSetErrnoFromNt(MY_NTSTATUS rcNt)
+{
+ errno = birdErrnoFromNtStatus(rcNt);
+#if 0
+ {
+ ULONG rcWin32;
+ _doserrno = rcWin32 = g_pfnRtlNtStatusToDosError(rcNt);
+ SetLastError(rcWin32);
+ }
+#endif
+ return -1;
+}
+
+
+int birdSetErrnoFromWin32(DWORD dwErr)
+{
+ switch (dwErr)
+ {
+ default:
+ case ERROR_INVALID_FUNCTION: errno = EINVAL; break;
+ case ERROR_FILE_NOT_FOUND: errno = ENOENT; break;
+ case ERROR_PATH_NOT_FOUND: errno = ENOENT; break;
+ case ERROR_TOO_MANY_OPEN_FILES: errno = EMFILE; break;
+ case ERROR_ACCESS_DENIED: errno = EACCES; break;
+ case ERROR_INVALID_HANDLE: errno = EBADF; break;
+ case ERROR_ARENA_TRASHED: errno = ENOMEM; break;
+ case ERROR_NOT_ENOUGH_MEMORY: errno = ENOMEM; break;
+ case ERROR_INVALID_BLOCK: errno = ENOMEM; break;
+ case ERROR_BAD_ENVIRONMENT: errno = E2BIG; break;
+ case ERROR_BAD_FORMAT: errno = ENOEXEC; break;
+ case ERROR_INVALID_ACCESS: errno = EINVAL; break;
+ case ERROR_INVALID_DATA: errno = EINVAL; break;
+ case ERROR_INVALID_DRIVE: errno = ENOENT; break;
+ case ERROR_CURRENT_DIRECTORY: errno = EACCES; break;
+ case ERROR_NOT_SAME_DEVICE: errno = EXDEV; break;
+ case ERROR_NO_MORE_FILES: errno = ENOENT; break;
+ case ERROR_LOCK_VIOLATION: errno = EACCES; break;
+ case ERROR_BAD_NETPATH: errno = ENOENT; break;
+ case ERROR_NETWORK_ACCESS_DENIED: errno = EACCES; break;
+ case ERROR_BAD_NET_NAME: errno = ENOENT; break;
+ case ERROR_FILE_EXISTS: errno = EEXIST; break;
+ case ERROR_CANNOT_MAKE: errno = EACCES; break;
+ case ERROR_FAIL_I24: errno = EACCES; break;
+ case ERROR_INVALID_PARAMETER: errno = EINVAL; break;
+ case ERROR_NO_PROC_SLOTS: errno = EAGAIN; break;
+ case ERROR_DRIVE_LOCKED: errno = EACCES; break;
+ case ERROR_BROKEN_PIPE: errno = EPIPE; break;
+ case ERROR_DISK_FULL: errno = ENOSPC; break;
+ case ERROR_INVALID_TARGET_HANDLE: errno = EBADF; break;
+ case ERROR_WAIT_NO_CHILDREN: errno = ECHILD; break;
+ case ERROR_CHILD_NOT_COMPLETE: errno = ECHILD; break;
+ case ERROR_DIRECT_ACCESS_HANDLE: errno = EBADF; break;
+ case ERROR_NEGATIVE_SEEK: errno = EINVAL; break;
+ case ERROR_SEEK_ON_DEVICE: errno = EACCES; break;
+ case ERROR_DIR_NOT_EMPTY: errno = ENOTEMPTY; break;
+ case ERROR_NOT_LOCKED: errno = EACCES; break;
+ case ERROR_BAD_PATHNAME: errno = ENOENT; break;
+ case ERROR_MAX_THRDS_REACHED: errno = EAGAIN; break;
+ case ERROR_LOCK_FAILED: errno = EACCES; break;
+ case ERROR_ALREADY_EXISTS: errno = EEXIST; break;
+ case ERROR_FILENAME_EXCED_RANGE: errno = ENOENT; break;
+ case ERROR_NESTING_NOT_ALLOWED: errno = EAGAIN; break;
+#ifdef EMLINK
+ case ERROR_TOO_MANY_LINKS: errno = EMLINK; break;
+#endif
+
+ case ERROR_SHARING_VIOLATION:
+ errno = ETXTBSY;
+ break;
+ }
+
+ return -1;
+}
+
+
+int birdSetErrnoToNoMem(void)
+{
+ errno = ENOMEM;
+ return -1;
+}
+
+
+int birdSetErrnoToInvalidArg(void)
+{
+ errno = EINVAL;
+ return -1;
+}
+
+
+int birdSetErrnoToBadFileNo(void)
+{
+ errno = EBADF;
+ return -1;
+}
+