2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: lib/kernel32/misc/utils.c
5 * PURPOSE: Utility and Support Functions
6 * PROGRAMMER: Alex Ionescu (alex@relsoft.net)
9 /* INCLUDES ****************************************************************/
13 #include "i386/ketypes.h"
14 #elif defined _M_AMD64
15 #include "amd64/ketypes.h"
21 /* GLOBALS ******************************************************************/
23 PRTL_CONVERT_STRING Basep8BitStringToUnicodeString
;
25 /* FUNCTIONS ****************************************************************/
28 * Converts an ANSI or OEM String to the specified Unicode String
32 Basep8BitStringToLiveUnicodeString(OUT PUNICODE_STRING UnicodeString
,
35 ANSI_STRING AnsiString
;
38 DPRINT("Basep8BitStringToLiveUnicodeString\n");
40 /* Create the ANSI String */
41 RtlInitAnsiString(&AnsiString
, String
);
43 /* Convert from OEM or ANSI */
44 Status
= Basep8BitStringToUnicodeString(UnicodeString
, &AnsiString
, FALSE
);
47 if (!NT_SUCCESS(Status
))
49 SetLastErrorByStatus(Status
);
56 * Converts an ANSI or OEM String to the TEB StaticUnicodeString
60 Basep8BitStringToStaticUnicodeString(IN LPCSTR String
)
62 PUNICODE_STRING StaticString
= &(NtCurrentTeb()->StaticUnicodeString
);
63 ANSI_STRING AnsiString
;
66 /* Initialize an ANSI String */
67 if (!NT_SUCCESS(RtlInitAnsiStringEx(&AnsiString
, String
)))
69 SetLastError(ERROR_FILENAME_EXCED_RANGE
);
74 Status
= Basep8BitStringToUnicodeString(StaticString
, &AnsiString
, FALSE
);
75 if (!NT_SUCCESS(Status
))
77 BaseSetLastNTError(Status
);
86 Basep8BitStringToHeapUnicodeString(OUT PUNICODE_STRING UnicodeString
,
89 ANSI_STRING AnsiString
;
92 DPRINT("Basep8BitStringToCachedUnicodeString\n");
94 /* Initialize an ANSI String */
95 RtlInitAnsiString(&AnsiString
, String
);
98 Status
= Basep8BitStringToUnicodeString(UnicodeString
, &AnsiString
, TRUE
);
101 if (!NT_SUCCESS(Status
))
103 SetLastErrorByStatus(Status
);
110 * Allocates space from the Heap and converts an Ansi String into it
114 BasepAnsiStringToHeapUnicodeString(IN LPCSTR AnsiString
,
115 OUT LPWSTR
* UnicodeString
)
117 ANSI_STRING AnsiTemp
;
118 UNICODE_STRING UnicodeTemp
;
120 DPRINT("BasepAnsiStringToHeapUnicodeString\n");
122 /* First create the ANSI_STRING */
123 RtlInitAnsiString(&AnsiTemp
, AnsiString
);
125 if (NT_SUCCESS(RtlAnsiStringToUnicodeString(&UnicodeTemp
,
129 *UnicodeString
= UnicodeTemp
.Buffer
;
133 *UnicodeString
= NULL
;
138 * Converts lpSecurityAttributes + Object Name into ObjectAttributes.
142 BasepConvertObjectAttributes(OUT POBJECT_ATTRIBUTES ObjectAttributes
,
143 IN PSECURITY_ATTRIBUTES SecurityAttributes OPTIONAL
,
144 IN PUNICODE_STRING ObjectName
)
146 ULONG Attributes
= 0;
147 HANDLE RootDirectory
= 0;
148 PVOID SecurityDescriptor
= NULL
;
149 BOOLEAN NeedOba
= FALSE
;
151 DPRINT("BasepConvertObjectAttributes. Security: %p, Name: %p\n",
152 SecurityAttributes
, ObjectName
);
154 /* Get the attributes if present */
155 if (SecurityAttributes
)
157 Attributes
= SecurityAttributes
->bInheritHandle
? OBJ_INHERIT
: 0;
158 SecurityDescriptor
= SecurityAttributes
->lpSecurityDescriptor
;
164 Attributes
|= OBJ_OPENIF
;
165 RootDirectory
= hBaseDir
;
169 DPRINT("Attributes: %lx, RootDirectory: %lx, SecurityDescriptor: %p\n",
170 Attributes
, RootDirectory
, SecurityDescriptor
);
172 /* Create the Object Attributes */
175 InitializeObjectAttributes(ObjectAttributes
,
180 return ObjectAttributes
;
183 /* Nothing to return */
188 * Creates a stack for a thread or fiber
192 BasepCreateStack(HANDLE hProcess
,
195 PINITIAL_TEB InitialTeb
)
198 SYSTEM_BASIC_INFORMATION SystemBasicInfo
;
199 PIMAGE_NT_HEADERS Headers
;
201 BOOLEAN UseGuard
= FALSE
;
203 DPRINT("BasepCreateStack (hProcess: %lx, Max: %lx, Current: %lx)\n",
204 hProcess
, StackReserve
, StackCommit
);
206 /* Get some memory information */
207 Status
= NtQuerySystemInformation(SystemBasicInformation
,
209 sizeof(SYSTEM_BASIC_INFORMATION
),
211 if (!NT_SUCCESS(Status
))
213 DPRINT1("Failure to query system info\n");
217 /* Use the Image Settings if we are dealing with the current Process */
218 if (hProcess
== NtCurrentProcess())
220 /* Get the Image Headers */
221 Headers
= RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress
);
223 /* If we didn't get the parameters, find them ourselves */
224 StackReserve
= (StackReserve
) ?
225 StackReserve
: Headers
->OptionalHeader
.SizeOfStackReserve
;
226 StackCommit
= (StackCommit
) ?
227 StackCommit
: Headers
->OptionalHeader
.SizeOfStackCommit
;
231 /* Use the System Settings if needed */
232 StackReserve
= (StackReserve
) ? StackReserve
:
233 SystemBasicInfo
.AllocationGranularity
;
234 StackCommit
= (StackCommit
) ? StackCommit
: SystemBasicInfo
.PageSize
;
237 /* Align everything to Page Size */
238 StackReserve
= ROUND_UP(StackReserve
, SystemBasicInfo
.AllocationGranularity
);
239 StackCommit
= ROUND_UP(StackCommit
, SystemBasicInfo
.PageSize
);
240 #if 1 // FIXME: Remove once Guard Page support is here
241 StackCommit
= StackReserve
;
243 DPRINT("StackReserve: %lx, StackCommit: %lx\n", StackReserve
, StackCommit
);
245 /* Reserve memory for the stack */
246 Status
= ZwAllocateVirtualMemory(hProcess
,
252 if (!NT_SUCCESS(Status
))
254 DPRINT1("Failure to reserve stack\n");
258 /* Now set up some basic Initial TEB Parameters */
259 InitialTeb
->AllocatedStackBase
= (PVOID
)Stack
;
260 InitialTeb
->StackBase
= (PVOID
)(Stack
+ StackReserve
);
261 InitialTeb
->PreviousStackBase
= NULL
;
262 InitialTeb
->PreviousStackLimit
= NULL
;
264 /* Update the Stack Position */
265 Stack
+= StackReserve
- StackCommit
;
267 /* Check if we will need a guard page */
268 if (StackReserve
> StackCommit
)
270 Stack
-= SystemBasicInfo
.PageSize
;
271 StackCommit
+= SystemBasicInfo
.PageSize
;
275 /* Allocate memory for the stack */
276 Status
= ZwAllocateVirtualMemory(hProcess
,
282 if (!NT_SUCCESS(Status
))
284 DPRINT1("Failure to allocate stack\n");
288 /* Now set the current Stack Limit */
289 InitialTeb
->StackLimit
= (PVOID
)Stack
;
291 /* Create a guard page */
294 SIZE_T GuardPageSize
= SystemBasicInfo
.PageSize
;
297 /* Attempt maximum space possible */
298 Status
= ZwProtectVirtualMemory(hProcess
,
301 PAGE_GUARD
| PAGE_READWRITE
,
303 if (!NT_SUCCESS(Status
))
305 DPRINT1("Failure to create guard page\n");
309 /* Update the Stack Limit keeping in mind the Guard Page */
310 InitialTeb
->StackLimit
= (PVOID
)((ULONG_PTR
)InitialTeb
->StackLimit
- GuardPageSize
);
314 return STATUS_SUCCESS
;
319 BasepFreeStack(HANDLE hProcess
,
320 PINITIAL_TEB InitialTeb
)
325 NtFreeVirtualMemory(hProcess
,
326 &InitialTeb
->AllocatedStackBase
,
332 * Creates the Initial Context for a Thread or Fiber
336 BasepInitializeContext(IN PCONTEXT Context
,
338 IN PVOID StartAddress
,
339 IN PVOID StackAddress
,
340 IN ULONG ContextType
)
343 DPRINT("BasepInitializeContext: %p\n", Context
);
345 /* Setup the Initial Win32 Thread Context */
346 Context
->Eax
= (ULONG
)StartAddress
;
347 Context
->Ebx
= (ULONG
)Parameter
;
348 Context
->Esp
= (ULONG
)StackAddress
;
349 /* The other registers are undefined */
351 /* Setup the Segments */
352 Context
->SegFs
= KGDT_R3_TEB
| RPL_MASK
;
353 Context
->SegEs
= KGDT_R3_DATA
| RPL_MASK
;
354 Context
->SegDs
= KGDT_R3_DATA
| RPL_MASK
;
355 Context
->SegCs
= KGDT_R3_CODE
| RPL_MASK
;
356 Context
->SegSs
= KGDT_R3_DATA
| RPL_MASK
;
360 Context
->EFlags
= 0x3000; /* IOPL 3 */
362 if (ContextType
== 1) /* For Threads */
364 Context
->Eip
= (ULONG
)BaseThreadStartupThunk
;
366 else if (ContextType
== 2) /* For Fibers */
368 Context
->Eip
= (ULONG
)BaseFiberStartup
;
370 else /* For first thread in a Process */
372 Context
->Eip
= (ULONG
)BaseProcessStartThunk
;
375 /* Set the Context Flags */
376 Context
->ContextFlags
= CONTEXT_FULL
;
378 /* Give it some room for the Parameter */
379 Context
->Esp
-= sizeof(PVOID
);
380 #elif defined(_M_AMD64)
381 DPRINT("BasepInitializeContext: %p\n", Context
);
383 /* Setup the Initial Win32 Thread Context */
384 Context
->Rax
= (ULONG_PTR
)StartAddress
;
385 Context
->Rbx
= (ULONG_PTR
)Parameter
;
386 Context
->Rsp
= (ULONG_PTR
)StackAddress
;
387 /* The other registers are undefined */
389 /* Setup the Segments */
390 Context
->SegGs
= KGDT64_R3_DATA
| RPL_MASK
;
391 Context
->SegEs
= KGDT64_R3_DATA
| RPL_MASK
;
392 Context
->SegDs
= KGDT64_R3_DATA
| RPL_MASK
;
393 Context
->SegCs
= KGDT64_R3_CODE
| RPL_MASK
;
394 Context
->SegSs
= KGDT64_R3_DATA
| RPL_MASK
;
395 Context
->SegFs
= KGDT64_R3_CMTEB
| RPL_MASK
;
398 Context
->EFlags
= 0x3000; /* IOPL 3 */
400 if (ContextType
== 1) /* For Threads */
402 Context
->Rip
= (ULONG_PTR
)BaseThreadStartupThunk
;
404 else if (ContextType
== 2) /* For Fibers */
406 Context
->Rip
= (ULONG_PTR
)BaseFiberStartup
;
408 else /* For first thread in a Process */
410 Context
->Rip
= (ULONG_PTR
)BaseProcessStartThunk
;
413 /* Set the Context Flags */
414 Context
->ContextFlags
= CONTEXT_FULL
;
416 /* Give it some room for the Parameter */
417 Context
->Rsp
-= sizeof(PVOID
);
419 #warning Unknown architecture
426 * Checks if the privilege for Real-Time Priority is there
430 BasepCheckRealTimePrivilege(VOID
)
436 * Maps an image file into a section
440 BasepMapFile(IN LPCWSTR lpApplicationName
,
441 OUT PHANDLE hSection
,
442 IN PUNICODE_STRING ApplicationName
)
445 OBJECT_ATTRIBUTES ObjectAttributes
;
448 IO_STATUS_BLOCK IoStatusBlock
;
450 DPRINT("BasepMapFile\n");
452 /* Zero out the Relative Directory */
453 RelativeName
.Handle
= NULL
;
455 /* Find the application name */
456 if (!RtlDosPathNameToNtPathName_U(lpApplicationName
,
461 return STATUS_OBJECT_PATH_NOT_FOUND
;
464 DPRINT("ApplicationName %wZ\n", ApplicationName
);
465 DPRINT("RelativeName %wZ\n", &RelativeName
.DosPath
);
467 /* Did we get a relative name? */
468 if (RelativeName
.DosPath
.Length
)
470 ApplicationName
= &RelativeName
.DosPath
;
473 /* Initialize the Object Attributes */
474 InitializeObjectAttributes(&ObjectAttributes
,
476 OBJ_CASE_INSENSITIVE
,
480 /* Try to open the executable */
481 Status
= NtOpenFile(&hFile
,
482 SYNCHRONIZE
| FILE_EXECUTE
| FILE_READ_DATA
,
485 FILE_SHARE_DELETE
| FILE_SHARE_READ
,
486 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_NON_DIRECTORY_FILE
);
487 if (!NT_SUCCESS(Status
))
489 DPRINT1("Failed to open file\n");
490 SetLastErrorByStatus(Status
);
494 /* Create a section for this file */
495 Status
= NtCreateSection(hSection
,
505 DPRINT("Section: %lx for file: %lx\n", *hSection
, hFile
);