From 29cd838eab01ed7110f3ccb2e8c6a35c8a31dbcc Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 11 Apr 2024 10:21:29 +0200 Subject: Adding upstream version 1:0.1.9998svn3589+dfsg. Signed-off-by: Daniel Baumann --- src/lib/nt/nthlpcore.c | 481 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 481 insertions(+) create mode 100644 src/lib/nt/nthlpcore.c (limited to 'src/lib/nt/nthlpcore.c') 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 + * + * 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 +#include "nthlp.h" +#ifndef NDEBUG +# include +#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; +} + -- cgit v1.2.3