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 ****************************************************************/
14 #include "../include/debug.h"
16 /* GLOBALS ******************************************************************/
18 /* GCC s^H can't handle static initializers to APIs, so we have to hack this */
21 RtlAnsiStringToUnicodeString(
22 PUNICODE_STRING DestinationString
,
23 PCANSI_STRING SourceString
,
24 BOOLEAN AllocateDestinationString
27 PRTL_CONVERT_STRING Basep8BitStringToUnicodeString
= RtlAnsiStringToUnicodeString
;
29 /* FUNCTIONS ****************************************************************/
32 * Converts an ANSI or OEM String to the specified Unicode String
36 Basep8BitStringToLiveUnicodeString(OUT PUNICODE_STRING UnicodeString
,
39 ANSI_STRING AnsiString
;
42 DPRINT("Basep8BitStringToLiveUnicodeString\n");
44 /* Create the ANSI String */
45 RtlInitAnsiString(&AnsiString
, String
);
47 /* Convert from OEM or ANSI */
48 Status
= Basep8BitStringToUnicodeString(UnicodeString
, &AnsiString
, FALSE
);
51 if (!NT_SUCCESS(Status
))
53 SetLastErrorByStatus(Status
);
60 * Converts an ANSI or OEM String to the TEB StaticUnicodeString
64 Basep8BitStringToCachedUnicodeString(IN LPCSTR String
)
66 PUNICODE_STRING StaticString
= &NtCurrentTeb()->StaticUnicodeString
;
67 ANSI_STRING AnsiString
;
70 DPRINT("Basep8BitStringToCachedUnicodeString\n");
72 /* Initialize an ANSI String */
73 RtlInitAnsiString(&AnsiString
, String
);
76 Status
= Basep8BitStringToUnicodeString(StaticString
, &AnsiString
, FALSE
);
79 if (!NT_SUCCESS(Status
))
81 SetLastErrorByStatus(Status
);
85 /* Return pointer to the string */
91 Basep8BitStringToHeapUnicodeString(OUT PUNICODE_STRING UnicodeString
,
94 ANSI_STRING AnsiString
;
97 DPRINT("Basep8BitStringToCachedUnicodeString\n");
99 /* Initialize an ANSI String */
100 RtlInitAnsiString(&AnsiString
, String
);
103 Status
= Basep8BitStringToUnicodeString(UnicodeString
, &AnsiString
, TRUE
);
106 if (!NT_SUCCESS(Status
))
108 SetLastErrorByStatus(Status
);
115 * Allocates space from the Heap and converts an Ansi String into it
119 BasepAnsiStringToHeapUnicodeString(IN LPCSTR AnsiString
,
120 OUT LPWSTR
* UnicodeString
)
122 ANSI_STRING AnsiTemp
;
123 UNICODE_STRING UnicodeTemp
;
125 DPRINT("BasepAnsiStringToHeapUnicodeString\n");
127 /* First create the ANSI_STRING */
128 RtlInitAnsiString(&AnsiTemp
, AnsiString
);
130 if (NT_SUCCESS(RtlAnsiStringToUnicodeString(&UnicodeTemp
,
134 *UnicodeString
= UnicodeTemp
.Buffer
;
138 *UnicodeString
= NULL
;
143 * Converts lpSecurityAttributes + Object Name into ObjectAttributes.
147 BasepConvertObjectAttributes(OUT POBJECT_ATTRIBUTES ObjectAttributes
,
148 IN PSECURITY_ATTRIBUTES SecurityAttributes OPTIONAL
,
149 IN PUNICODE_STRING ObjectName
)
151 ULONG Attributes
= 0;
152 HANDLE RootDirectory
= 0;
153 PVOID SecurityDescriptor
= NULL
;
154 BOOLEAN NeedOba
= FALSE
;
156 DPRINT("BasepConvertObjectAttributes. Security: %p, Name: %p\n",
157 SecurityAttributes
, ObjectName
);
159 /* Get the attributes if present */
160 if (SecurityAttributes
)
162 Attributes
= SecurityAttributes
->bInheritHandle
? OBJ_INHERIT
: 0;
163 SecurityDescriptor
= SecurityAttributes
->lpSecurityDescriptor
;
169 Attributes
|= OBJ_OPENIF
;
170 RootDirectory
= hBaseDir
;
174 DPRINT("Attributes: %lx, RootDirectory: %lx, SecurityDescriptor: %p\n",
175 Attributes
, RootDirectory
, SecurityDescriptor
);
177 /* Create the Object Attributes */
180 InitializeObjectAttributes(ObjectAttributes
,
185 return ObjectAttributes
;
188 /* Nothing to return */
193 * Creates a stack for a thread or fiber
197 BasepCreateStack(HANDLE hProcess
,
200 PINITIAL_TEB InitialTeb
)
203 SYSTEM_BASIC_INFORMATION SystemBasicInfo
;
204 PIMAGE_NT_HEADERS Headers
;
206 BOOLEAN UseGuard
= FALSE
;
208 DPRINT("BasepCreateStack (hProcess: %lx, Max: %lx, Current: %lx)\n",
209 hProcess
, StackReserve
, StackCommit
);
211 /* Get some memory information */
212 Status
= NtQuerySystemInformation(SystemBasicInformation
,
214 sizeof(SYSTEM_BASIC_INFORMATION
),
216 if (!NT_SUCCESS(Status
))
218 DPRINT1("Failure to query system info\n");
222 /* Use the Image Settings if we are dealing with the current Process */
223 if (hProcess
== NtCurrentProcess())
225 /* Get the Image Headers */
226 Headers
= RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress
);
228 /* If we didn't get the parameters, find them ourselves */
229 StackReserve
= (StackReserve
) ?
230 StackReserve
: Headers
->OptionalHeader
.SizeOfStackReserve
;
231 StackCommit
= (StackCommit
) ?
232 StackCommit
: Headers
->OptionalHeader
.SizeOfStackCommit
;
236 /* Use the System Settings if needed */
237 StackReserve
= (StackReserve
) ? StackReserve
:
238 SystemBasicInfo
.AllocationGranularity
;
239 StackCommit
= (StackCommit
) ? StackCommit
: SystemBasicInfo
.PageSize
;
242 /* Align everything to Page Size */
243 StackReserve
= ROUND_UP(StackReserve
, SystemBasicInfo
.AllocationGranularity
);
244 StackCommit
= ROUND_UP(StackCommit
, SystemBasicInfo
.PageSize
);
245 #if 1 // FIXME: Remove once Guard Page support is here
246 StackCommit
= StackReserve
;
248 DPRINT("StackReserve: %lx, StackCommit: %lx\n", StackReserve
, StackCommit
);
250 /* Reserve memory for the stack */
251 Status
= ZwAllocateVirtualMemory(hProcess
,
257 if (!NT_SUCCESS(Status
))
259 DPRINT1("Failure to reserve stack\n");
263 /* Now set up some basic Initial TEB Parameters */
264 InitialTeb
->AllocatedStackBase
= (PVOID
)Stack
;
265 InitialTeb
->StackBase
= (PVOID
)(Stack
+ StackReserve
);
267 /* Update the Stack Position */
268 Stack
+= StackReserve
- StackCommit
;
270 /* Check if we will need a guard page */
271 if (StackReserve
> StackCommit
)
273 Stack
-= SystemBasicInfo
.PageSize
;
274 StackCommit
+= SystemBasicInfo
.PageSize
;
278 /* Allocate memory for the stack */
279 Status
= ZwAllocateVirtualMemory(hProcess
,
285 if (!NT_SUCCESS(Status
))
287 DPRINT1("Failure to allocate stack\n");
291 /* Now set the current Stack Limit */
292 InitialTeb
->StackLimit
= (PVOID
)Stack
;
294 /* Create a guard page */
297 ULONG GuardPageSize
= SystemBasicInfo
.PageSize
;
300 /* Attempt maximum space possible */
301 Status
= ZwProtectVirtualMemory(hProcess
,
304 PAGE_GUARD
| PAGE_READWRITE
,
306 if (!NT_SUCCESS(Status
))
308 DPRINT1("Failure to create guard page\n");
312 /* Update the Stack Limit keeping in mind the Guard Page */
313 InitialTeb
->StackLimit
= (PVOID
)((ULONG_PTR
)InitialTeb
->StackLimit
- GuardPageSize
);
317 return STATUS_SUCCESS
;
322 BasepFreeStack(HANDLE hProcess
,
323 PINITIAL_TEB InitialTeb
)
328 NtFreeVirtualMemory(hProcess
,
329 &InitialTeb
->AllocatedStackBase
,
335 * Creates the Initial Context for a Thread or Fiber
339 BasepInitializeContext(IN PCONTEXT Context
,
341 IN PVOID StartAddress
,
342 IN PVOID StackAddress
,
343 IN ULONG ContextType
)
345 DPRINT("BasepInitializeContext: %p\n", Context
);
347 /* Setup the Initial Win32 Thread Context */
348 Context
->Eax
= (ULONG
)StartAddress
;
349 Context
->Ebx
= (ULONG
)Parameter
;
350 Context
->Esp
= (ULONG
)StackAddress
;
351 /* The other registers are undefined */
353 /* Setup the Segments */
354 Context
->SegFs
= KGDT_R3_TEB
| RPL_MASK
;
355 Context
->SegEs
= KGDT_R3_DATA
| RPL_MASK
;
356 Context
->SegDs
= KGDT_R3_DATA
| RPL_MASK
;
357 Context
->SegCs
= KGDT_R3_CODE
| RPL_MASK
;
358 Context
->SegSs
= KGDT_R3_DATA
| RPL_MASK
;
362 Context
->EFlags
= 0x3000; /* IOPL 3 */
364 if (ContextType
== 1) /* For Threads */
366 Context
->Eip
= (ULONG
)BaseThreadStartupThunk
;
368 else if (ContextType
== 2) /* For Fibers */
370 //Context->Eip = (ULONG)BaseFiberStartup;
372 else /* For first thread in a Process */
374 Context
->Eip
= (ULONG
)BaseProcessStartThunk
;
377 /* Set the Context Flags */
378 Context
->ContextFlags
= CONTEXT_FULL
;
380 /* Give it some room for the Parameter */
381 Context
->Esp
-= sizeof(PVOID
);
385 * Checks if the privilege for Real-Time Priority is there
389 BasepCheckRealTimePrivilege(VOID
)
395 * Maps an image file into a section
399 BasepMapFile(IN LPCWSTR lpApplicationName
,
400 OUT PHANDLE hSection
,
401 IN PUNICODE_STRING ApplicationName
)
404 OBJECT_ATTRIBUTES ObjectAttributes
;
407 IO_STATUS_BLOCK IoStatusBlock
;
409 DPRINT("BasepMapFile\n");
411 /* Zero out the Relative Directory */
412 RelativeName
.Handle
= NULL
;
414 /* Find the application name */
415 RtlDosPathNameToNtPathName_U(lpApplicationName
,
419 DPRINT("ApplicationName %wZ\n", ApplicationName
);
420 DPRINT("RelativeName %wZ\n", &RelativeName
.DosPath
);
422 /* Did we get a relative name? */
423 if (RelativeName
.DosPath
.Length
)
425 ApplicationName
= &RelativeName
.DosPath
;
428 /* Initialize the Object Attributes */
429 InitializeObjectAttributes(&ObjectAttributes
,
431 OBJ_CASE_INSENSITIVE
,
435 /* Try to open the executable */
436 Status
= NtOpenFile(&hFile
,
437 SYNCHRONIZE
| FILE_EXECUTE
| FILE_READ_DATA
,
440 FILE_SHARE_DELETE
| FILE_SHARE_READ
,
441 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_NON_DIRECTORY_FILE
);
442 if (!NT_SUCCESS(Status
))
444 DPRINT1("Failed to open file\n");
445 SetLastErrorByStatus (Status
);
449 /* Create a section for this file */
450 Status
= NtCreateSection(hSection
,
460 DPRINT("Section: %lx for file: %lx\n", *hSection
, hFile
);