Part three of patch...

- Created utils.c for the following new functions:
        * BasepCreateStack - Creates a stack for a Thread or Fiber
        * BasepInitializeContext - Initializes the Context for a Process, a Thread, or a Fiber
        * BasepConvertObjectAttributes - Creates a OBJECT_ATTRIBUTES structure based on Win32
                                         lpSecurityAttributes and name.
        * BasepFreestack - Frees the stack created in case of a failure inside code using it.
        * BasepMapFile - Converts a Win32 Path to NT Path and maps a file into a section.
        * Base 8-bit String conversion functions - Use new, more efficient way to select
          between OEM/ANSI strings, based on MSDN Article by Matt Pietrek. Other code needs
          to be chand to use them.
Also added the new ASM for the startup thunks. All of this is still unused and only being committed to simply the diff output. Credits go to Matt Pietrek and his excellent MSDN article for the 8-bit conversion functions and implementaion details.

svn path=/trunk/; revision=16543
This commit is contained in:
Alex Ionescu 2005-07-12 05:00:33 +00:00
parent e6523bb71e
commit 358a2167ab
5 changed files with 561 additions and 5 deletions

View file

@ -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;
}

View file

@ -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 */

View file

@ -76,6 +76,7 @@
<file>time.c</file>
<file>timerqueue.c</file>
<file>toolhelp.c</file>
<file>utils.c</file>
<file>version.c</file>
</directory>
<directory name="process">
@ -99,6 +100,7 @@
<directory name="thread">
<directory name="i386">
<file>fiber.S</file>
<file>thread.S</file>
</directory>
<file>fiber.c</file>
<file>fls.c</file>

View file

@ -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 <k32.h>
#define NDEBUG
#include <debug.h>
/* 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;
}

View file

@ -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 */