diff --git a/reactos/lib/kernel32/file/file.c b/reactos/lib/kernel32/file/file.c index d3c1c2237ce..ea5f1c3ae4b 100644 --- a/reactos/lib/kernel32/file/file.c +++ b/reactos/lib/kernel32/file/file.c @@ -22,7 +22,6 @@ BOOL bIsFileApiAnsi = TRUE; // set the file api to ansi or oem - /* FUNCTIONS ****************************************************************/ @@ -178,20 +177,30 @@ FilenameW2A_N( /* * @implemented */ -VOID STDCALL +VOID +STDCALL SetFileApisToOEM(VOID) { - bIsFileApiAnsi = FALSE; + /* Set the correct Base Api */ + Basep8BitStringToUnicodeString = RtlOemStringToUnicodeString; + + /* FIXME: Old, deprecated way */ + bIsFileApiAnsi = FALSE; } /* * @implemented */ -VOID STDCALL +VOID +STDCALL SetFileApisToANSI(VOID) { - bIsFileApiAnsi = TRUE; + /* Set the correct Base Api */ + Basep8BitStringToUnicodeString = RtlAnsiStringToUnicodeString; + + /* FIXME: Old, deprecated way */ + bIsFileApiAnsi = TRUE; } diff --git a/reactos/lib/kernel32/include/kernel32.h b/reactos/lib/kernel32/include/kernel32.h index bc5dfb2ec3f..885c1a3d0db 100755 --- a/reactos/lib/kernel32/include/kernel32.h +++ b/reactos/lib/kernel32/include/kernel32.h @@ -26,6 +26,13 @@ #define IsConsoleHandle(h) \ ((((ULONG)h) & 0x10000003) == 0x3) ? TRUE : FALSE +#define HANDLE_DETACHED_PROCESS (HANDLE)-1 +#define HANDLE_CREATE_NEW_CONSOLE (HANDLE)-2 +#define HANDLE_CREATE_NO_WINDOW (HANDLE)-3 + +/* Undocumented CreateProcess flag */ +#define STARTF_SHELLPRIVATE 0x400 + #define SetLastErrorByStatus(__S__) \ ((void)SetLastError(RtlNtStatusToDosError(__S__))) @@ -69,5 +76,86 @@ DWORD FilenameU2A_FitOrFail(LPSTR DestA, INT destLen, PUNICODE_STRING SourceU); #define HeapAlloc RtlAllocateHeap #define HeapFree RtlFreeHeap +POBJECT_ATTRIBUTES +STDCALL +BasepConvertObjectAttributes(OUT POBJECT_ATTRIBUTES ObjectAttributes, + IN PSECURITY_ATTRIBUTES SecurityAttributes OPTIONAL, + IN PUNICODE_STRING ObjectName); + +NTSTATUS +STDCALL +BasepCreateStack(HANDLE hProcess, + ULONG StackReserve, + ULONG StackCommit, + PINITIAL_TEB InitialTeb); + +VOID +STDCALL +BasepInitializeContext(IN PCONTEXT Context, + IN PVOID Parameter, + IN PVOID StartAddress, + IN PVOID StackAddress, + IN ULONG ContextType); + +VOID +STDCALL +BaseThreadStartupThunk(); + +VOID +STDCALL +BaseProcessStartThunk(); + +__declspec(noreturn) +VOID +STDCALL +BaseThreadStartup(LPTHREAD_START_ROUTINE lpStartAddress, + LPVOID lpParameter); + +VOID +STDCALL +BasepFreeStack(HANDLE hProcess, + PINITIAL_TEB InitialTeb); + +__declspec(noreturn) +VOID +WINAPI +BaseFiberStartup(VOID); + +typedef UINT (STDCALL *PPROCESS_START_ROUTINE)(VOID); + +VOID +STDCALL +BaseProcessStartup(PPROCESS_START_ROUTINE lpStartAddress); + +BOOLEAN +STDCALL +BasepCheckRealTimePrivilege(VOID); + +VOID +STDCALL +BasepAnsiStringToHeapUnicodeString(IN LPCSTR AnsiString, + IN PVOID UnicodeString); + +PUNICODE_STRING +STDCALL +Basep8BitStringToCachedUnicodeString(IN LPCSTR String); + +NTSTATUS +STDCALL +Basep8BitStringToLiveUnicodeString(OUT PUNICODE_STRING UnicodeString, + IN LPCSTR String); + +typedef NTSTATUS (STDCALL *PRTL_CONVERT_STRING)(IN PUNICODE_STRING UnicodeString, + IN PANSI_STRING AnsiString, + IN BOOLEAN AllocateMemory); + +PRTL_CONVERT_STRING Basep8BitStringToUnicodeString; + +NTSTATUS +STDCALL +BasepMapFile(IN LPCWSTR lpApplicationName, + OUT PHANDLE hSection, + IN PUNICODE_STRING ApplicationName); + #endif /* ndef _KERNEL32_INCLUDE_KERNEL32_H */ diff --git a/reactos/lib/kernel32/kernel32.xml b/reactos/lib/kernel32/kernel32.xml index 51b36e49d54..38226e2cb26 100644 --- a/reactos/lib/kernel32/kernel32.xml +++ b/reactos/lib/kernel32/kernel32.xml @@ -76,6 +76,7 @@ time.c timerqueue.c toolhelp.c + utils.c version.c @@ -99,6 +100,7 @@ fiber.S + thread.S fiber.c fls.c diff --git a/reactos/lib/kernel32/misc/utils.c b/reactos/lib/kernel32/misc/utils.c new file mode 100644 index 00000000000..eb7b7d2068d --- /dev/null +++ b/reactos/lib/kernel32/misc/utils.c @@ -0,0 +1,425 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/misc/utils.c + * PURPOSE: Utility and Support Functions + * PROGRAMMER: Alex Ionescu (alex@relsoft.net) + */ + +/* INCLUDES ****************************************************************/ + +#include + +#define NDEBUG +#include + +/* FUNCTIONS ****************************************************************/ + +/* + * Converts an ANSI or OEM String to the specified Unicode String + */ +NTSTATUS +STDCALL +Basep8BitStringToLiveUnicodeString(OUT PUNICODE_STRING UnicodeString, + IN LPCSTR String) +{ + ANSI_STRING AnsiString; + NTSTATUS Status; + + DPRINT("Basep8BitStringToLiveUnicodeString\n"); + + /* Create the ANSI String */ + RtlInitAnsiString(&AnsiString, String); + + /* Convert from OEM or ANSI */ + Status = Basep8BitStringToUnicodeString(UnicodeString, &AnsiString, FALSE); + + /* Return Status */ + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + } + return Status; +} + + +/* + * Converts an ANSI or OEM String to the TEB StaticUnicodeString + */ +PUNICODE_STRING +STDCALL +Basep8BitStringToCachedUnicodeString(IN LPCSTR String) +{ + PUNICODE_STRING StaticString = &NtCurrentTeb()->StaticUnicodeString; + ANSI_STRING AnsiString; + NTSTATUS Status; + + DPRINT("Basep8BitStringToCachedUnicodeString\n"); + + /* Initialize an ANSI String */ + RtlInitAnsiString(&AnsiString, String); + + /* Convert it */ + Status = Basep8BitStringToUnicodeString(StaticString, &AnsiString, FALSE); + + /* Handle failure */ + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return NULL; + } + + /* Return pointer to the string */ + return StaticString; +} + +/* + * Allocates space from the Heap and converts an Ansi String into it + */ +VOID +STDCALL +BasepAnsiStringToHeapUnicodeString(IN LPCSTR AnsiString, + IN PVOID UnicodeString) +{ + ANSI_STRING AnsiTemp; + UNICODE_STRING UnicodeTemp; + + DPRINT("BasepAnsiStringToHeapUnicodeString\n"); + + /* First create the ANSI_STRING */ + RtlInitAnsiString(&AnsiTemp, AnsiString); + + /* Now get the size needed */ + UnicodeTemp.MaximumLength = RtlAnsiStringToUnicodeSize(&AnsiTemp); + + /* Allocate space from the Heap for the string */ + UnicodeString = RtlAllocateHeap(GetProcessHeap(), + 0, + UnicodeTemp.MaximumLength); + + /* Save the buffer and convert */ + UnicodeTemp.Buffer = UnicodeString; + RtlAnsiStringToUnicodeString(&UnicodeTemp, &AnsiTemp, FALSE); +} + +/* + * Converts lpSecurityAttributes + Object Name into ObjectAttributes. + */ +POBJECT_ATTRIBUTES +STDCALL +BasepConvertObjectAttributes(OUT POBJECT_ATTRIBUTES ObjectAttributes, + IN PSECURITY_ATTRIBUTES SecurityAttributes OPTIONAL, + IN PUNICODE_STRING ObjectName) +{ + ULONG Attributes = 0; + HANDLE RootDirectory = 0; + PVOID SecurityDescriptor = NULL; + BOOLEAN NeedOba = FALSE; + + DPRINT("BasepConvertObjectAttributes. Security: %p, Name: %p\n", + SecurityAttributes, ObjectName); + + /* Get the attributes if present */ + if (SecurityAttributes) + { + Attributes = SecurityAttributes->bInheritHandle ? OBJ_INHERIT : 0; + SecurityDescriptor = SecurityAttributes->lpSecurityDescriptor; + NeedOba = TRUE; + } + + if (ObjectName) + { + Attributes |= OBJ_OPENIF; + RootDirectory = hBaseDir; + NeedOba = TRUE; + } + + DPRINT("Attributes: %lx, RootDirectory: %lx, SecurityDescriptor: %p\n", + Attributes, RootDirectory, SecurityDescriptor); + + /* Create the Object Attributes */ + if (NeedOba) + { + InitializeObjectAttributes(ObjectAttributes, + ObjectName, + Attributes, + RootDirectory, + SecurityDescriptor); + return ObjectAttributes; + } + + /* Nothing to return */ + return NULL; +} + +/* + * Creates a stack for a thread or fiber + */ +NTSTATUS +STDCALL +BasepCreateStack(HANDLE hProcess, + ULONG StackReserve, + ULONG StackCommit, + PINITIAL_TEB InitialTeb) +{ + NTSTATUS Status; + SYSTEM_BASIC_INFORMATION SystemBasicInfo; + PIMAGE_NT_HEADERS Headers; + ULONG_PTR Stack = 0; + BOOLEAN UseGuard = FALSE; + + DPRINT("BasepCreateStack (hProcess: %lx, Max: %lx, Current: %lx)\n", + hProcess, StackReserve, StackCommit); + + /* Get some memory information */ + Status = NtQuerySystemInformation(SystemBasicInformation, + &SystemBasicInfo, + sizeof(SYSTEM_BASIC_INFORMATION), + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failure to query system info\n"); + return Status; + } + + /* Use the Image Settings if we are dealing with the current Process */ + if (hProcess == NtCurrentProcess()) + { + /* Get the Image Headers */ + Headers = RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress); + + /* If we didn't get the parameters, find them ourselves */ + StackReserve = (StackReserve) ? + StackReserve : Headers->OptionalHeader.SizeOfStackReserve; + StackCommit = (StackCommit) ? + StackCommit : Headers->OptionalHeader.SizeOfStackCommit; + } + else + { + /* Use the System Settings if needed */ + StackReserve = (StackReserve) ? StackReserve : + SystemBasicInfo.AllocationGranularity; + StackCommit = (StackCommit) ? StackCommit : SystemBasicInfo.PageSize; + } + + /* Align everything to Page Size */ + StackReserve = ROUND_UP(StackReserve, SystemBasicInfo.AllocationGranularity); + StackCommit = ROUND_UP(StackCommit, SystemBasicInfo.PageSize); + #if 1 // FIXME: Remove once Guard Page support is here + StackCommit = StackReserve; + #endif + DPRINT("StackReserve: %lx, StackCommit: %lx\n", StackReserve, StackCommit); + + /* Reserve memory for the stack */ + Status = ZwAllocateVirtualMemory(hProcess, + (PVOID*)&Stack, + 0, + &StackReserve, + MEM_RESERVE, + PAGE_READWRITE); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failure to reserve stack\n"); + return Status; + } + + /* Now set up some basic Initial TEB Parameters */ + InitialTeb->AllocatedStackBase = (PVOID)Stack; + InitialTeb->StackBase = (PVOID)(Stack + StackReserve); + + /* Update the Stack Position */ + Stack += StackReserve - StackCommit; + + /* Check if we will need a guard page */ + if (StackReserve > StackCommit) + { + Stack -= SystemBasicInfo.PageSize; + StackCommit += SystemBasicInfo.PageSize; + UseGuard = TRUE; + } + + /* Allocate memory for the stack */ + Status = ZwAllocateVirtualMemory(hProcess, + (PVOID*)&Stack, + 0, + &StackCommit, + MEM_COMMIT, + PAGE_READWRITE); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failure to allocate stack\n"); + return Status; + } + + /* Now set the current Stack Limit */ + InitialTeb->StackLimit = (PVOID)Stack; + + /* Create a guard page */ + if (UseGuard) + { + ULONG GuardPageSize = SystemBasicInfo.PageSize; + ULONG Dummy; + + /* Attempt maximum space possible */ + Status = ZwProtectVirtualMemory(hProcess, + (PVOID*)&Stack, + &GuardPageSize, + PAGE_GUARD | PAGE_READWRITE, + &Dummy); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failure to create guard page\n"); + return Status; + } + + /* Update the Stack Limit keeping in mind the Guard Page */ + InitialTeb->StackLimit = (PVOID)((ULONG_PTR)InitialTeb->StackLimit - GuardPageSize); + } + + /* We are done! */ + return STATUS_SUCCESS; +} + +VOID +STDCALL +BasepFreeStack(HANDLE hProcess, + PINITIAL_TEB InitialTeb) +{ + ULONG Dummy = 0; + + /* Free the Stack */ + NtFreeVirtualMemory(hProcess, + &InitialTeb->AllocatedStackBase, + &Dummy, + MEM_RELEASE); +} + +/* + * Creates the Initial Context for a Thread or Fiber + */ +VOID +STDCALL +BasepInitializeContext(IN PCONTEXT Context, + IN PVOID Parameter, + IN PVOID StartAddress, + IN PVOID StackAddress, + IN ULONG ContextType) +{ + DPRINT("BasepInitializeContext: %p\n", Context); + + /* Setup the Initial Win32 Thread Context */ + Context->Eax = (ULONG)StartAddress; + Context->Ebx = (ULONG)Parameter; + Context->Esp = (ULONG)StackAddress; + /* The other registers are undefined */ + + /* Setup the Segments */ + Context->SegCs = USER_CS; + Context->SegDs = USER_DS; + Context->SegEs = USER_DS; + Context->SegFs = TEB_SELECTOR; + Context->SegSs = USER_DS; + Context->SegGs = 0; + + /* Set the EFLAGS */ + Context->EFlags = 0x3000; /* IOPL 3 */ + + if (ContextType == 1) /* For Threads */ + { + Context->Eip = (ULONG)BaseThreadStartupThunk; + } + else if (ContextType == 2) /* For Fibers */ + { + //Context->Eip = (ULONG)BaseFiberStartup; + } + else /* For first thread in a Process */ + { + Context->Eip = (ULONG)BaseProcessStartThunk; + } + + /* Set the Context Flags */ + Context->ContextFlags = CONTEXT_FULL; + + /* Give it some room for the Parameter */ + Context->Esp -= sizeof(PVOID); +} + +/* + * Checks if the privilege for Real-Time Priority is there + */ +BOOLEAN +STDCALL +BasepCheckRealTimePrivilege(VOID) +{ + return TRUE; +} + +/* + * Maps an image file into a section + */ +NTSTATUS +STDCALL +BasepMapFile(IN LPCWSTR lpApplicationName, + OUT PHANDLE hSection, + IN PUNICODE_STRING ApplicationName) +{ + CURDIR RelativeName; + OBJECT_ATTRIBUTES ObjectAttributes; + NTSTATUS Status; + HANDLE hFile = NULL; + IO_STATUS_BLOCK IoStatusBlock; + + DPRINT("BasepMapFile\n"); + + /* Zero out the Relative Directory */ + RelativeName.Handle = NULL; + + /* Find the application name */ + RtlDosPathNameToNtPathName_U((LPWSTR)lpApplicationName, + ApplicationName, + NULL, + &RelativeName); + DPRINT("ApplicationName %wZ\n", ApplicationName); + DPRINT("RelativeName %wZ\n", &RelativeName.DosPath); + + /* Did we get a relative name? */ + if (RelativeName.DosPath.Length) + { + ApplicationName = &RelativeName.DosPath; + } + + /* Initialize the Object Attributes */ + InitializeObjectAttributes(&ObjectAttributes, + ApplicationName, + OBJ_CASE_INSENSITIVE, + RelativeName.Handle, + NULL); + + /* Try to open the executable */ + Status = NtOpenFile(&hFile, + SYNCHRONIZE | FILE_EXECUTE | FILE_READ_DATA, + &ObjectAttributes, + &IoStatusBlock, + FILE_SHARE_DELETE | FILE_SHARE_READ, + FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to open file\n"); + SetLastErrorByStatus (Status); + return Status; + } + + /* Create a section for this file */ + Status = NtCreateSection(hSection, + SECTION_ALL_ACCESS, + NULL, + NULL, + PAGE_EXECUTE, + SEC_IMAGE, + hFile); + NtClose(hFile); + + /* Return status */ + DPRINT("Section: %lx for file: %lx\n", *hSection, hFile); + return Status; +} diff --git a/reactos/lib/kernel32/thread/i386/thread.S b/reactos/lib/kernel32/thread/i386/thread.S new file mode 100644 index 00000000000..e789f4d9b5f --- /dev/null +++ b/reactos/lib/kernel32/thread/i386/thread.S @@ -0,0 +1,32 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/thread/i386/thread.S + * PURPOSE: Thread Start Thunks + * PROGRAMMER: Alex Ionescu (alex@relsoft.net) + */ + +.globl _BaseThreadStartupThunk@0 +.globl _BaseProcessStartThunk@0 +.intel_syntax noprefix + +_BaseThreadStartupThunk@0: + + /* Start out fresh */ + xor ebp, ebp + + push ebx /* lpParameter */ + push eax /* lpStartAddress */ + push 0 /* Return EIP */ + //jmp _BaseThreadStartup@8 + +_BaseProcessStartThunk@0: + + /* Start out fresh */ + xor ebp, ebp + + push eax /* lpStartAddress */ + push 0 /* Return EIP */ + //jmp _BaseProcessStartup@4 + +/* EOF */