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)
7 * Pierre Schweitzer (pierre.schweitzer@reactos.org)
10 /* INCLUDES ****************************************************************/
14 #include "i386/ketypes.h"
15 #elif defined _M_AMD64
16 #include "amd64/ketypes.h"
22 /* GLOBALS ******************************************************************/
24 PRTL_CONVERT_STRING Basep8BitStringToUnicodeString
;
26 /* FUNCTIONS ****************************************************************/
30 * Converts an ANSI or OEM String to the TEB StaticUnicodeString
34 Basep8BitStringToStaticUnicodeString(IN LPCSTR String
)
36 PUNICODE_STRING StaticString
= &(NtCurrentTeb()->StaticUnicodeString
);
37 ANSI_STRING AnsiString
;
40 /* Initialize an ANSI String */
41 if (!NT_SUCCESS(RtlInitAnsiStringEx(&AnsiString
, String
)))
43 SetLastError(ERROR_FILENAME_EXCED_RANGE
);
48 Status
= Basep8BitStringToUnicodeString(StaticString
, &AnsiString
, FALSE
);
49 if (!NT_SUCCESS(Status
))
51 BaseSetLastNTError(Status
);
59 * Allocates space from the Heap and converts an Unicode String into it
63 Basep8BitStringToDynamicUnicodeString(OUT PUNICODE_STRING UnicodeString
,
66 ANSI_STRING AnsiString
;
69 DPRINT("Basep8BitStringToDynamicUnicodeString\n");
71 /* Initialize an ANSI String */
72 if (!NT_SUCCESS(RtlInitAnsiStringEx(&AnsiString
, String
)))
74 SetLastError(ERROR_BUFFER_OVERFLOW
);
79 Status
= Basep8BitStringToUnicodeString(UnicodeString
, &AnsiString
, TRUE
);
82 if (!NT_SUCCESS(Status
))
84 BaseSetLastNTError(Status
);
93 * Allocates space from the Heap and converts an Ansi String into it
97 BasepAnsiStringToHeapUnicodeString(IN LPCSTR AnsiString
,
98 OUT LPWSTR
* UnicodeString
)
100 ANSI_STRING AnsiTemp
;
101 UNICODE_STRING UnicodeTemp
;
103 DPRINT("BasepAnsiStringToHeapUnicodeString\n");
105 /* First create the ANSI_STRING */
106 RtlInitAnsiString(&AnsiTemp
, AnsiString
);
108 if (NT_SUCCESS(RtlAnsiStringToUnicodeString(&UnicodeTemp
,
112 *UnicodeString
= UnicodeTemp
.Buffer
;
116 *UnicodeString
= NULL
;
122 BaseFormatTimeOut(OUT PLARGE_INTEGER Timeout
,
123 IN DWORD dwMilliseconds
)
125 /* Check if this is an infinite wait, which means no timeout argument */
126 if (dwMilliseconds
== INFINITE
) return NULL
;
128 /* Otherwise, convert the time to NT Format */
129 Timeout
->QuadPart
= UInt32x32To64(dwMilliseconds
, -10000);
134 * Converts lpSecurityAttributes + Object Name into ObjectAttributes.
138 BasepConvertObjectAttributes(OUT POBJECT_ATTRIBUTES ObjectAttributes
,
139 IN PSECURITY_ATTRIBUTES SecurityAttributes OPTIONAL
,
140 IN PUNICODE_STRING ObjectName
)
142 ULONG Attributes
= 0;
143 HANDLE RootDirectory
= 0;
144 PVOID SecurityDescriptor
= NULL
;
145 BOOLEAN NeedOba
= FALSE
;
147 DPRINT("BasepConvertObjectAttributes. Security: %p, Name: %p\n",
148 SecurityAttributes
, ObjectName
);
150 /* Get the attributes if present */
151 if (SecurityAttributes
)
153 Attributes
= SecurityAttributes
->bInheritHandle
? OBJ_INHERIT
: 0;
154 SecurityDescriptor
= SecurityAttributes
->lpSecurityDescriptor
;
160 Attributes
|= OBJ_OPENIF
;
161 RootDirectory
= hBaseDir
;
165 DPRINT("Attributes: %lx, RootDirectory: %lx, SecurityDescriptor: %p\n",
166 Attributes
, RootDirectory
, SecurityDescriptor
);
168 /* Create the Object Attributes */
171 InitializeObjectAttributes(ObjectAttributes
,
176 return ObjectAttributes
;
179 /* Nothing to return */
184 * Creates a stack for a thread or fiber
188 BasepCreateStack(HANDLE hProcess
,
191 PINITIAL_TEB InitialTeb
)
194 SYSTEM_BASIC_INFORMATION SystemBasicInfo
;
195 PIMAGE_NT_HEADERS Headers
;
197 BOOLEAN UseGuard
= FALSE
;
199 DPRINT("BasepCreateStack (hProcess: %lx, Max: %lx, Current: %lx)\n",
200 hProcess
, StackReserve
, StackCommit
);
202 /* Get some memory information */
203 Status
= NtQuerySystemInformation(SystemBasicInformation
,
205 sizeof(SYSTEM_BASIC_INFORMATION
),
207 if (!NT_SUCCESS(Status
))
209 DPRINT1("Failure to query system info\n");
213 /* Use the Image Settings if we are dealing with the current Process */
214 if (hProcess
== NtCurrentProcess())
216 /* Get the Image Headers */
217 Headers
= RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress
);
219 /* If we didn't get the parameters, find them ourselves */
220 StackReserve
= (StackReserve
) ?
221 StackReserve
: Headers
->OptionalHeader
.SizeOfStackReserve
;
222 StackCommit
= (StackCommit
) ?
223 StackCommit
: Headers
->OptionalHeader
.SizeOfStackCommit
;
227 /* Use the System Settings if needed */
228 StackReserve
= (StackReserve
) ? StackReserve
:
229 SystemBasicInfo
.AllocationGranularity
;
230 StackCommit
= (StackCommit
) ? StackCommit
: SystemBasicInfo
.PageSize
;
233 /* Align everything to Page Size */
234 StackReserve
= ROUND_UP(StackReserve
, SystemBasicInfo
.AllocationGranularity
);
235 StackCommit
= ROUND_UP(StackCommit
, SystemBasicInfo
.PageSize
);
236 #if 1 // FIXME: Remove once Guard Page support is here
237 StackCommit
= StackReserve
;
239 DPRINT("StackReserve: %lx, StackCommit: %lx\n", StackReserve
, StackCommit
);
241 /* Reserve memory for the stack */
242 Status
= ZwAllocateVirtualMemory(hProcess
,
248 if (!NT_SUCCESS(Status
))
250 DPRINT1("Failure to reserve stack\n");
254 /* Now set up some basic Initial TEB Parameters */
255 InitialTeb
->AllocatedStackBase
= (PVOID
)Stack
;
256 InitialTeb
->StackBase
= (PVOID
)(Stack
+ StackReserve
);
257 InitialTeb
->PreviousStackBase
= NULL
;
258 InitialTeb
->PreviousStackLimit
= NULL
;
260 /* Update the Stack Position */
261 Stack
+= StackReserve
- StackCommit
;
263 /* Check if we will need a guard page */
264 if (StackReserve
> StackCommit
)
266 Stack
-= SystemBasicInfo
.PageSize
;
267 StackCommit
+= SystemBasicInfo
.PageSize
;
271 /* Allocate memory for the stack */
272 Status
= ZwAllocateVirtualMemory(hProcess
,
278 if (!NT_SUCCESS(Status
))
280 DPRINT1("Failure to allocate stack\n");
284 /* Now set the current Stack Limit */
285 InitialTeb
->StackLimit
= (PVOID
)Stack
;
287 /* Create a guard page */
290 SIZE_T GuardPageSize
= SystemBasicInfo
.PageSize
;
293 /* Attempt maximum space possible */
294 Status
= ZwProtectVirtualMemory(hProcess
,
297 PAGE_GUARD
| PAGE_READWRITE
,
299 if (!NT_SUCCESS(Status
))
301 DPRINT1("Failure to create guard page\n");
305 /* Update the Stack Limit keeping in mind the Guard Page */
306 InitialTeb
->StackLimit
= (PVOID
)((ULONG_PTR
)InitialTeb
->StackLimit
- GuardPageSize
);
310 return STATUS_SUCCESS
;
315 BasepFreeStack(HANDLE hProcess
,
316 PINITIAL_TEB InitialTeb
)
321 NtFreeVirtualMemory(hProcess
,
322 &InitialTeb
->AllocatedStackBase
,
328 * Creates the Initial Context for a Thread or Fiber
332 BasepInitializeContext(IN PCONTEXT Context
,
334 IN PVOID StartAddress
,
335 IN PVOID StackAddress
,
336 IN ULONG ContextType
)
340 DPRINT("BasepInitializeContext: %p\n", Context
);
342 /* Setup the Initial Win32 Thread Context */
343 Context
->Eax
= (ULONG
)StartAddress
;
344 Context
->Ebx
= (ULONG
)Parameter
;
345 Context
->Esp
= (ULONG
)StackAddress
;
346 /* The other registers are undefined */
348 /* Setup the Segments */
349 Context
->SegFs
= KGDT_R3_TEB
| RPL_MASK
;
350 Context
->SegEs
= KGDT_R3_DATA
| RPL_MASK
;
351 Context
->SegDs
= KGDT_R3_DATA
| RPL_MASK
;
352 Context
->SegCs
= KGDT_R3_CODE
| RPL_MASK
;
353 Context
->SegSs
= KGDT_R3_DATA
| RPL_MASK
;
356 /* Set the Context Flags */
357 ContextFlags
= Context
->ContextFlags
;
358 Context
->ContextFlags
= CONTEXT_FULL
;
360 /* Give it some room for the Parameter */
361 Context
->Esp
-= sizeof(PVOID
);
364 Context
->EFlags
= 0x3000; /* IOPL 3 */
366 /* What kind of context is being created? */
367 if (ContextType
== 1)
370 Context
->Eip
= (ULONG
)BaseThreadStartupThunk
;
372 else if (ContextType
== 2)
374 /* This is a fiber: make space for the return address */
375 Context
->Esp
-= sizeof(PVOID
);
376 *((PVOID
*)Context
->Esp
) = BaseFiberStartup
;
378 /* Is FPU state required? */
379 Context
->ContextFlags
|= ContextFlags
;
380 if (ContextFlags
== CONTEXT_FLOATING_POINT
)
382 /* Set an initial state */
383 Context
->FloatSave
.ControlWord
= 0x27F;
384 Context
->FloatSave
.StatusWord
= 0;
385 Context
->FloatSave
.TagWord
= 0xFFFF;
386 Context
->FloatSave
.ErrorOffset
= 0;
387 Context
->FloatSave
.ErrorSelector
= 0;
388 Context
->FloatSave
.DataOffset
= 0;
389 Context
->FloatSave
.DataSelector
= 0;
390 if (SharedUserData
->ProcessorFeatures
[PF_XMMI_INSTRUCTIONS_AVAILABLE
])
391 Context
->Dr6
= 0x1F80;
396 /* For first thread in a Process */
397 Context
->Eip
= (ULONG
)BaseProcessStartThunk
;
400 #elif defined(_M_AMD64)
401 DPRINT("BasepInitializeContext: %p\n", Context
);
403 /* Setup the Initial Win32 Thread Context */
404 Context
->Rax
= (ULONG_PTR
)StartAddress
;
405 Context
->Rbx
= (ULONG_PTR
)Parameter
;
406 Context
->Rsp
= (ULONG_PTR
)StackAddress
;
407 /* The other registers are undefined */
409 /* Setup the Segments */
410 Context
->SegGs
= KGDT64_R3_DATA
| RPL_MASK
;
411 Context
->SegEs
= KGDT64_R3_DATA
| RPL_MASK
;
412 Context
->SegDs
= KGDT64_R3_DATA
| RPL_MASK
;
413 Context
->SegCs
= KGDT64_R3_CODE
| RPL_MASK
;
414 Context
->SegSs
= KGDT64_R3_DATA
| RPL_MASK
;
415 Context
->SegFs
= KGDT64_R3_CMTEB
| RPL_MASK
;
418 Context
->EFlags
= 0x3000; /* IOPL 3 */
420 if (ContextType
== 1) /* For Threads */
422 Context
->Rip
= (ULONG_PTR
)BaseThreadStartupThunk
;
424 else if (ContextType
== 2) /* For Fibers */
426 Context
->Rip
= (ULONG_PTR
)BaseFiberStartup
;
428 else /* For first thread in a Process */
430 Context
->Rip
= (ULONG_PTR
)BaseProcessStartThunk
;
433 /* Set the Context Flags */
434 Context
->ContextFlags
= CONTEXT_FULL
;
436 /* Give it some room for the Parameter */
437 Context
->Rsp
-= sizeof(PVOID
);
439 #warning Unknown architecture
446 * Checks if the privilege for Real-Time Priority is there
450 BasepCheckRealTimePrivilege(VOID
)
456 * Maps an image file into a section
460 BasepMapFile(IN LPCWSTR lpApplicationName
,
461 OUT PHANDLE hSection
,
462 IN PUNICODE_STRING ApplicationName
)
464 RTL_RELATIVE_NAME_U RelativeName
;
465 OBJECT_ATTRIBUTES ObjectAttributes
;
468 IO_STATUS_BLOCK IoStatusBlock
;
470 DPRINT("BasepMapFile\n");
472 /* Zero out the Relative Directory */
473 RelativeName
.ContainingDirectory
= NULL
;
475 /* Find the application name */
476 if (!RtlDosPathNameToNtPathName_U(lpApplicationName
,
481 return STATUS_OBJECT_PATH_NOT_FOUND
;
484 DPRINT("ApplicationName %wZ\n", ApplicationName
);
485 DPRINT("RelativeName %wZ\n", &RelativeName
.RelativeName
);
487 /* Did we get a relative name? */
488 if (RelativeName
.RelativeName
.Length
)
490 ApplicationName
= &RelativeName
.RelativeName
;
493 /* Initialize the Object Attributes */
494 InitializeObjectAttributes(&ObjectAttributes
,
496 OBJ_CASE_INSENSITIVE
,
497 RelativeName
.ContainingDirectory
,
500 /* Try to open the executable */
501 Status
= NtOpenFile(&hFile
,
502 SYNCHRONIZE
| FILE_EXECUTE
| FILE_READ_DATA
,
505 FILE_SHARE_DELETE
| FILE_SHARE_READ
,
506 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_NON_DIRECTORY_FILE
);
507 if (!NT_SUCCESS(Status
))
509 DPRINT1("Failed to open file\n");
510 BaseSetLastNTError(Status
);
514 /* Create a section for this file */
515 Status
= NtCreateSection(hSection
,
525 DPRINT("Section: %lx for file: %lx\n", *hSection
, hFile
);
534 BaseCheckRunApp(IN DWORD Unknown1
,
554 BasepCheckWinSaferRestrictions(IN DWORD Unknown1
,