/** * WinPR: Windows Portable Runtime * Windows Native System Services * * Copyright 2013 Marc-Andre Moreau * Copyright 2013 Thincast Technologies GmbH * Copyright 2013 Norbert Federa * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include "../log.h" #define TAG WINPR_TAG("nt") /** * NtXxx Routines: * http://msdn.microsoft.com/en-us/library/windows/hardware/ff557720/ */ /** * InitializeObjectAttributes macro * http://msdn.microsoft.com/en-us/library/windows/hardware/ff547804/ */ VOID _InitializeObjectAttributes(POBJECT_ATTRIBUTES InitializedAttributes, PUNICODE_STRING ObjectName, ULONG Attributes, HANDLE RootDirectory, PSECURITY_DESCRIPTOR SecurityDescriptor) { #if defined(_WIN32) && !defined(_UWP) InitializeObjectAttributes(InitializedAttributes, ObjectName, Attributes, RootDirectory, SecurityDescriptor); #else InitializedAttributes->Length = sizeof(OBJECT_ATTRIBUTES); InitializedAttributes->ObjectName = ObjectName; InitializedAttributes->Attributes = Attributes; InitializedAttributes->RootDirectory = RootDirectory; InitializedAttributes->SecurityDescriptor = SecurityDescriptor; InitializedAttributes->SecurityQualityOfService = NULL; #endif } #ifndef _WIN32 #include #include #include "../handle/handle.h" struct winpr_nt_file { WINPR_HANDLE_DEF(); ACCESS_MASK DesiredAccess; OBJECT_ATTRIBUTES ObjectAttributes; ULONG FileAttributes; ULONG ShareAccess; ULONG CreateDisposition; ULONG CreateOptions; }; typedef struct winpr_nt_file WINPR_NT_FILE; static pthread_once_t _TebOnceControl = PTHREAD_ONCE_INIT; static pthread_key_t _TebKey; static void _TebDestruct(void* teb) { free(teb); } static void _TebInitOnce(void) { pthread_key_create(&_TebKey, _TebDestruct); } PTEB NtCurrentTeb(void) { PTEB teb = NULL; if (pthread_once(&_TebOnceControl, _TebInitOnce) == 0) { if ((teb = pthread_getspecific(_TebKey)) == NULL) { teb = calloc(1, sizeof(TEB)); if (teb) pthread_setspecific(_TebKey, teb); } } return teb; } /** * RtlInitAnsiString routine: * http://msdn.microsoft.com/en-us/library/windows/hardware/ff561918/ */ VOID _RtlInitAnsiString(PANSI_STRING DestinationString, PCSZ SourceString) { DestinationString->Buffer = (PCHAR)SourceString; if (!SourceString) { DestinationString->Length = 0; DestinationString->MaximumLength = 0; } else { USHORT length = (USHORT)strlen(SourceString); DestinationString->Length = length; DestinationString->MaximumLength = length + 1; } } /** * RtlInitUnicodeString routine: * http://msdn.microsoft.com/en-us/library/windows/hardware/ff561934/ */ VOID _RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString) { DestinationString->Buffer = (PWSTR)SourceString; if (!SourceString) { DestinationString->Length = 0; DestinationString->MaximumLength = 0; } else { USHORT length = (USHORT)_wcslen(SourceString); DestinationString->Length = length * 2; DestinationString->MaximumLength = (length + 1) * 2; } } /** * RtlAnsiStringToUnicodeString function: * http://msdn.microsoft.com/en-us/library/ms648413/ */ NTSTATUS _RtlAnsiStringToUnicodeString(PUNICODE_STRING DestinationString, PCANSI_STRING SourceString, BOOLEAN AllocateDestinationString) { int index; if (!SourceString) return STATUS_INVALID_PARAMETER; if (AllocateDestinationString) { PWSTR wbuf = NULL; if (SourceString->MaximumLength) { if (!(wbuf = (PWSTR)calloc(SourceString->MaximumLength, 2))) return STATUS_NO_MEMORY; } DestinationString->MaximumLength = SourceString->MaximumLength * 2; DestinationString->Buffer = wbuf; } else { if (DestinationString->MaximumLength < SourceString->MaximumLength * 2) return STATUS_BUFFER_OVERFLOW; } for (index = 0; index < SourceString->MaximumLength; index++) { Data_Write_UINT16(&DestinationString->Buffer[index], SourceString->Buffer[index]); } DestinationString->Length = SourceString->Length * 2; return STATUS_SUCCESS; } /** * RtlFreeUnicodeString function: * http://msdn.microsoft.com/en-us/library/ms648418/ */ VOID _RtlFreeUnicodeString(PUNICODE_STRING UnicodeString) { if (UnicodeString) { free(UnicodeString->Buffer); UnicodeString->Length = 0; UnicodeString->MaximumLength = 0; } } /** * RtlNtStatusToDosError function: * http://msdn.microsoft.com/en-us/library/windows/desktop/ms680600/ */ ULONG _RtlNtStatusToDosError(NTSTATUS status) { return status; } /** * NtCreateFile function: * http://msdn.microsoft.com/en-us/library/bb432380/ */ NTSTATUS _NtCreateFile(PHANDLE FileHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PIO_STATUS_BLOCK IoStatusBlock, PLARGE_INTEGER AllocationSize, ULONG FileAttributes, ULONG ShareAccess, ULONG CreateDisposition, ULONG CreateOptions, PVOID EaBuffer, ULONG EaLength) { #if 1 WLog_ERR(TAG, "%s: Not implemented", __FUNCTION__); return STATUS_NOT_SUPPORTED; #else WINPR_NT_FILE* pFileHandle; pFileHandle = (WINPR_NT_FILE*)calloc(1, sizeof(WINPR_NT_FILE)); if (!pFileHandle) return STATUS_NO_MEMORY; pFileHandle->DesiredAccess = DesiredAccess; pFileHandle->FileAttributes = FileAttributes; pFileHandle->ShareAccess = ShareAccess; pFileHandle->CreateDisposition = CreateDisposition; pFileHandle->CreateOptions = CreateOptions; *((PULONG_PTR)FileHandle) = (ULONG_PTR)pFileHandle; // STATUS_ACCESS_DENIED // STATUS_OBJECT_NAME_INVALID // STATUS_OBJECT_PATH_NOT_FOUND // STATUS_OBJECT_NAME_NOT_FOUND return STATUS_SUCCESS; #endif } /** * NtOpenFile function: * http://msdn.microsoft.com/en-us/library/bb432381/ */ NTSTATUS _NtOpenFile(PHANDLE FileHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PIO_STATUS_BLOCK IoStatusBlock, ULONG ShareAccess, ULONG OpenOptions) { #if 1 WLog_ERR(TAG, "%s: Not implemented", __FUNCTION__); return STATUS_NOT_SUPPORTED; #else WINPR_NT_FILE* pFileHandle; pFileHandle = (WINPR_NT_FILE*)calloc(1, sizeof(WINPR_NT_FILE)); if (!pFileHandle) return STATUS_NO_MEMORY; pFileHandle->DesiredAccess = DesiredAccess; pFileHandle->ShareAccess = ShareAccess; *((PULONG_PTR)FileHandle) = (ULONG_PTR)pFileHandle; return STATUS_SUCCESS; #endif } /** * NtReadFile function: * http://msdn.microsoft.com/en-us/library/windows/hardware/ff567072/ */ NTSTATUS _NtReadFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, PVOID Buffer, ULONG Length, PLARGE_INTEGER ByteOffset, PULONG Key) { #if 1 WLog_ERR(TAG, "%s: Not implemented", __FUNCTION__); return STATUS_NOT_SUPPORTED; #else return STATUS_SUCCESS; #endif } /** * NtWriteFile function: * http://msdn.microsoft.com/en-us/library/windows/hardware/ff567121/ */ NTSTATUS _NtWriteFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, PVOID Buffer, ULONG Length, PLARGE_INTEGER ByteOffset, PULONG Key) { #if 1 WLog_ERR(TAG, "%s: Not implemented", __FUNCTION__); return STATUS_NOT_SUPPORTED; #else return STATUS_SUCCESS; #endif } /** * NtDeviceIoControlFile function: * http://msdn.microsoft.com/en-us/library/ms648411/ */ NTSTATUS _NtDeviceIoControlFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, ULONG IoControlCode, PVOID InputBuffer, ULONG InputBufferLength, PVOID OutputBuffer, ULONG OutputBufferLength) { #if 1 WLog_ERR(TAG, "%s: Not implemented", __FUNCTION__); return STATUS_NOT_SUPPORTED; #else return STATUS_SUCCESS; #endif } /** * NtClose function: * http://msdn.microsoft.com/en-us/library/ms648410/ */ NTSTATUS _NtClose(HANDLE Handle) { #if 1 WLog_ERR(TAG, "%s: Not implemented", __FUNCTION__); return STATUS_NOT_SUPPORTED; #else WINPR_NT_FILE* pFileHandle; if (!Handle) return STATUS_SUCCESS; pFileHandle = (WINPR_NT_FILE*)Handle; free(pFileHandle); return STATUS_SUCCESS; #endif } /** * NtWaitForSingleObject function: * http://msdn.microsoft.com/en-us/library/ms648412/ */ NTSTATUS _NtWaitForSingleObject(HANDLE Handle, BOOLEAN Alertable, PLARGE_INTEGER Timeout) { #if 1 WLog_ERR(TAG, "%s: Not implemented", __FUNCTION__); return STATUS_NOT_SUPPORTED; #else return STATUS_SUCCESS; #endif } #else #include typedef VOID(WINAPI* RTL_INIT_ANSI_STRING_FN)(PANSI_STRING DestinationString, PCSZ SourceString); typedef VOID(WINAPI* RTL_INIT_UNICODE_STRING_FN)(PUNICODE_STRING DestinationString, PCWSTR SourceString); typedef NTSTATUS(WINAPI* RTL_ANSI_STRING_TO_UNICODE_STRING_FN)(PUNICODE_STRING DestinationString, PCANSI_STRING SourceString, BOOLEAN AllocateDestinationString); typedef VOID(WINAPI* RTL_FREE_UNICODE_STRING_FN)(PUNICODE_STRING UnicodeString); typedef ULONG(WINAPI* RTL_NT_STATUS_TO_DOS_ERROR_FN)(NTSTATUS status); typedef NTSTATUS(WINAPI* NT_CREATE_FILE_FN)(PHANDLE FileHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PIO_STATUS_BLOCK IoStatusBlock, PLARGE_INTEGER AllocationSize, ULONG FileAttributes, ULONG ShareAccess, ULONG CreateDisposition, ULONG CreateOptions, PVOID EaBuffer, ULONG EaLength); typedef NTSTATUS(WINAPI* NT_OPEN_FILE_FN)(PHANDLE FileHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PIO_STATUS_BLOCK IoStatusBlock, ULONG ShareAccess, ULONG OpenOptions); typedef NTSTATUS(WINAPI* NT_READ_FILE_FN)(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, PVOID Buffer, ULONG Length, PLARGE_INTEGER ByteOffset, PULONG Key); typedef NTSTATUS(WINAPI* NT_WRITE_FILE_FN)(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, PVOID Buffer, ULONG Length, PLARGE_INTEGER ByteOffset, PULONG Key); typedef NTSTATUS(WINAPI* NT_DEVICE_IO_CONTROL_FILE_FN)(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, ULONG IoControlCode, PVOID InputBuffer, ULONG InputBufferLength, PVOID OutputBuffer, ULONG OutputBufferLength); typedef NTSTATUS(WINAPI* NT_CLOSE_FN)(HANDLE Handle); typedef NTSTATUS(WINAPI* NT_WAIT_FOR_SINGLE_OBJECT_FN)(HANDLE Handle, BOOLEAN Alertable, PLARGE_INTEGER Timeout); static RTL_INIT_ANSI_STRING_FN pRtlInitAnsiString = NULL; static RTL_INIT_UNICODE_STRING_FN pRtlInitUnicodeString = NULL; static RTL_ANSI_STRING_TO_UNICODE_STRING_FN pRtlAnsiStringToUnicodeString = NULL; static RTL_FREE_UNICODE_STRING_FN pRtlFreeUnicodeString = NULL; static RTL_NT_STATUS_TO_DOS_ERROR_FN pRtlNtStatusToDosError = NULL; static NT_CREATE_FILE_FN pNtCreateFile = NULL; static NT_OPEN_FILE_FN pNtOpenFile = NULL; static NT_READ_FILE_FN pNtReadFile = NULL; static NT_WRITE_FILE_FN pNtWriteFile = NULL; static NT_DEVICE_IO_CONTROL_FILE_FN pNtDeviceIoControlFile = NULL; static NT_CLOSE_FN pNtClose = NULL; static NT_WAIT_FOR_SINGLE_OBJECT_FN pNtWaitForSingleObject = NULL; static INIT_ONCE ntdllInitOnce = INIT_ONCE_STATIC_INIT; static BOOL CALLBACK NtdllModuleInit(PINIT_ONCE once, PVOID param, PVOID* context) { HMODULE NtdllModule = LoadLibraryA("ntdll.dll"); if (NtdllModule) { pRtlInitAnsiString = (RTL_INIT_ANSI_STRING_FN)GetProcAddress(NtdllModule, "RtlInitAnsiString"); pRtlInitUnicodeString = (RTL_INIT_UNICODE_STRING_FN)GetProcAddress(NtdllModule, "RtlInitUnicodeString"); pRtlAnsiStringToUnicodeString = (RTL_ANSI_STRING_TO_UNICODE_STRING_FN)GetProcAddress( NtdllModule, "RtlAnsiStringToUnicodeString"); pRtlFreeUnicodeString = (RTL_FREE_UNICODE_STRING_FN)GetProcAddress(NtdllModule, "RtlFreeUnicodeString"); pRtlNtStatusToDosError = (RTL_NT_STATUS_TO_DOS_ERROR_FN)GetProcAddress(NtdllModule, "RtlNtStatusToDosError"); pNtCreateFile = (NT_CREATE_FILE_FN)GetProcAddress(NtdllModule, "NtCreateFile"); pNtOpenFile = (NT_OPEN_FILE_FN)GetProcAddress(NtdllModule, "NtOpenFile"); pNtReadFile = (NT_READ_FILE_FN)GetProcAddress(NtdllModule, "NtReadFile"); pNtWriteFile = (NT_WRITE_FILE_FN)GetProcAddress(NtdllModule, "NtWriteFile"); pNtDeviceIoControlFile = (NT_DEVICE_IO_CONTROL_FILE_FN)GetProcAddress(NtdllModule, "NtDeviceIoControlFile"); pNtClose = (NT_CLOSE_FN)GetProcAddress(NtdllModule, "NtClose"); pNtWaitForSingleObject = (NT_WAIT_FOR_SINGLE_OBJECT_FN)GetProcAddress(NtdllModule, "NtWaitForSingleObject"); } return TRUE; } VOID _RtlInitAnsiString(PANSI_STRING DestinationString, PCSZ SourceString) { InitOnceExecuteOnce(&ntdllInitOnce, NtdllModuleInit, NULL, NULL); if (!pRtlInitAnsiString) return; pRtlInitAnsiString(DestinationString, SourceString); } VOID _RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString) { InitOnceExecuteOnce(&ntdllInitOnce, NtdllModuleInit, NULL, NULL); if (!pRtlInitUnicodeString) return; pRtlInitUnicodeString(DestinationString, SourceString); } NTSTATUS _RtlAnsiStringToUnicodeString(PUNICODE_STRING DestinationString, PCANSI_STRING SourceString, BOOLEAN AllocateDestinationString) { InitOnceExecuteOnce(&ntdllInitOnce, NtdllModuleInit, NULL, NULL); if (!pRtlAnsiStringToUnicodeString) return STATUS_INTERNAL_ERROR; return pRtlAnsiStringToUnicodeString(DestinationString, SourceString, AllocateDestinationString); } VOID _RtlFreeUnicodeString(PUNICODE_STRING UnicodeString) { InitOnceExecuteOnce(&ntdllInitOnce, NtdllModuleInit, NULL, NULL); if (!pRtlFreeUnicodeString) return; pRtlFreeUnicodeString(UnicodeString); } ULONG _RtlNtStatusToDosError(NTSTATUS status) { InitOnceExecuteOnce(&ntdllInitOnce, NtdllModuleInit, NULL, NULL); if (!pRtlNtStatusToDosError) return status; return pRtlNtStatusToDosError(status); } NTSTATUS _NtCreateFile(PHANDLE FileHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PIO_STATUS_BLOCK IoStatusBlock, PLARGE_INTEGER AllocationSize, ULONG FileAttributes, ULONG ShareAccess, ULONG CreateDisposition, ULONG CreateOptions, PVOID EaBuffer, ULONG EaLength) { InitOnceExecuteOnce(&ntdllInitOnce, NtdllModuleInit, NULL, NULL); if (!pNtCreateFile) return STATUS_INTERNAL_ERROR; return pNtCreateFile(FileHandle, DesiredAccess, ObjectAttributes, IoStatusBlock, AllocationSize, FileAttributes, ShareAccess, CreateDisposition, CreateOptions, EaBuffer, EaLength); } NTSTATUS _NtOpenFile(PHANDLE FileHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PIO_STATUS_BLOCK IoStatusBlock, ULONG ShareAccess, ULONG OpenOptions) { InitOnceExecuteOnce(&ntdllInitOnce, NtdllModuleInit, NULL, NULL); if (!pNtOpenFile) return STATUS_INTERNAL_ERROR; return pNtOpenFile(FileHandle, DesiredAccess, ObjectAttributes, IoStatusBlock, ShareAccess, OpenOptions); } NTSTATUS _NtReadFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, PVOID Buffer, ULONG Length, PLARGE_INTEGER ByteOffset, PULONG Key) { InitOnceExecuteOnce(&ntdllInitOnce, NtdllModuleInit, NULL, NULL); if (!pNtReadFile) return STATUS_INTERNAL_ERROR; return pNtReadFile(FileHandle, Event, ApcRoutine, ApcContext, IoStatusBlock, Buffer, Length, ByteOffset, Key); } NTSTATUS _NtWriteFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, PVOID Buffer, ULONG Length, PLARGE_INTEGER ByteOffset, PULONG Key) { InitOnceExecuteOnce(&ntdllInitOnce, NtdllModuleInit, NULL, NULL); if (!pNtWriteFile) return STATUS_INTERNAL_ERROR; return pNtWriteFile(FileHandle, Event, ApcRoutine, ApcContext, IoStatusBlock, Buffer, Length, ByteOffset, Key); } NTSTATUS _NtDeviceIoControlFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, ULONG IoControlCode, PVOID InputBuffer, ULONG InputBufferLength, PVOID OutputBuffer, ULONG OutputBufferLength) { InitOnceExecuteOnce(&ntdllInitOnce, NtdllModuleInit, NULL, NULL); if (!pNtDeviceIoControlFile) return STATUS_INTERNAL_ERROR; return pNtDeviceIoControlFile(FileHandle, Event, ApcRoutine, ApcContext, IoStatusBlock, IoControlCode, InputBuffer, InputBufferLength, OutputBuffer, OutputBufferLength); } NTSTATUS _NtClose(HANDLE Handle) { InitOnceExecuteOnce(&ntdllInitOnce, NtdllModuleInit, NULL, NULL); if (!pNtClose) return STATUS_INTERNAL_ERROR; return pNtClose(Handle); } NTSTATUS _NtWaitForSingleObject(HANDLE Handle, BOOLEAN Alertable, PLARGE_INTEGER Timeout) { InitOnceExecuteOnce(&ntdllInitOnce, NtdllModuleInit, NULL, NULL); if (!pNtWaitForSingleObject) return STATUS_INTERNAL_ERROR; return pNtWaitForSingleObject(Handle, Alertable, Timeout); } #endif