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"
19 /* GLOBALS ******************************************************************/
21 PRTL_CONVERT_STRING Basep8BitStringToUnicodeString
;
23 /* FUNCTIONS ****************************************************************/
26 * Converts an ANSI or OEM String to the specified Unicode String
30 Basep8BitStringToLiveUnicodeString(OUT PUNICODE_STRING UnicodeString
,
33 ANSI_STRING AnsiString
;
36 DPRINT("Basep8BitStringToLiveUnicodeString\n");
38 /* Create the ANSI String */
39 RtlInitAnsiString(&AnsiString
, String
);
41 /* Convert from OEM or ANSI */
42 Status
= Basep8BitStringToUnicodeString(UnicodeString
, &AnsiString
, FALSE
);
45 if (!NT_SUCCESS(Status
))
47 SetLastErrorByStatus(Status
);
54 * Converts an ANSI or OEM String to the TEB StaticUnicodeString
58 Basep8BitStringToCachedUnicodeString(IN LPCSTR String
)
60 PUNICODE_STRING StaticString
= &NtCurrentTeb()->StaticUnicodeString
;
61 ANSI_STRING AnsiString
;
64 DPRINT("Basep8BitStringToCachedUnicodeString\n");
66 /* Initialize an ANSI String */
67 RtlInitAnsiString(&AnsiString
, String
);
70 Status
= Basep8BitStringToUnicodeString(StaticString
, &AnsiString
, FALSE
);
73 if (!NT_SUCCESS(Status
))
75 SetLastErrorByStatus(Status
);
79 /* Return pointer to the string */
85 Basep8BitStringToHeapUnicodeString(OUT PUNICODE_STRING UnicodeString
,
88 ANSI_STRING AnsiString
;
91 DPRINT("Basep8BitStringToCachedUnicodeString\n");
93 /* Initialize an ANSI String */
94 RtlInitAnsiString(&AnsiString
, String
);
97 Status
= Basep8BitStringToUnicodeString(UnicodeString
, &AnsiString
, TRUE
);
100 if (!NT_SUCCESS(Status
))
102 SetLastErrorByStatus(Status
);
109 * Allocates space from the Heap and converts an Ansi String into it
113 BasepAnsiStringToHeapUnicodeString(IN LPCSTR AnsiString
,
114 OUT LPWSTR
* UnicodeString
)
116 ANSI_STRING AnsiTemp
;
117 UNICODE_STRING UnicodeTemp
;
119 DPRINT("BasepAnsiStringToHeapUnicodeString\n");
121 /* First create the ANSI_STRING */
122 RtlInitAnsiString(&AnsiTemp
, AnsiString
);
124 if (NT_SUCCESS(RtlAnsiStringToUnicodeString(&UnicodeTemp
,
128 *UnicodeString
= UnicodeTemp
.Buffer
;
132 *UnicodeString
= NULL
;
137 * Converts lpSecurityAttributes + Object Name into ObjectAttributes.
141 BasepConvertObjectAttributes(OUT POBJECT_ATTRIBUTES ObjectAttributes
,
142 IN PSECURITY_ATTRIBUTES SecurityAttributes OPTIONAL
,
143 IN PUNICODE_STRING ObjectName
)
145 ULONG Attributes
= 0;
146 HANDLE RootDirectory
= 0;
147 PVOID SecurityDescriptor
= NULL
;
148 BOOLEAN NeedOba
= FALSE
;
150 DPRINT("BasepConvertObjectAttributes. Security: %p, Name: %p\n",
151 SecurityAttributes
, ObjectName
);
153 /* Get the attributes if present */
154 if (SecurityAttributes
)
156 Attributes
= SecurityAttributes
->bInheritHandle
? OBJ_INHERIT
: 0;
157 SecurityDescriptor
= SecurityAttributes
->lpSecurityDescriptor
;
163 Attributes
|= OBJ_OPENIF
;
164 RootDirectory
= hBaseDir
;
168 DPRINT("Attributes: %lx, RootDirectory: %lx, SecurityDescriptor: %p\n",
169 Attributes
, RootDirectory
, SecurityDescriptor
);
171 /* Create the Object Attributes */
174 InitializeObjectAttributes(ObjectAttributes
,
179 return ObjectAttributes
;
182 /* Nothing to return */
187 * Creates a stack for a thread or fiber
191 BasepCreateStack(HANDLE hProcess
,
194 PINITIAL_TEB InitialTeb
)
197 SYSTEM_BASIC_INFORMATION SystemBasicInfo
;
198 PIMAGE_NT_HEADERS Headers
;
200 BOOLEAN UseGuard
= FALSE
;
202 DPRINT("BasepCreateStack (hProcess: %lx, Max: %lx, Current: %lx)\n",
203 hProcess
, StackReserve
, StackCommit
);
205 /* Get some memory information */
206 Status
= NtQuerySystemInformation(SystemBasicInformation
,
208 sizeof(SYSTEM_BASIC_INFORMATION
),
210 if (!NT_SUCCESS(Status
))
212 DPRINT1("Failure to query system info\n");
216 /* Use the Image Settings if we are dealing with the current Process */
217 if (hProcess
== NtCurrentProcess())
219 /* Get the Image Headers */
220 Headers
= RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress
);
222 /* If we didn't get the parameters, find them ourselves */
223 StackReserve
= (StackReserve
) ?
224 StackReserve
: Headers
->OptionalHeader
.SizeOfStackReserve
;
225 StackCommit
= (StackCommit
) ?
226 StackCommit
: Headers
->OptionalHeader
.SizeOfStackCommit
;
230 /* Use the System Settings if needed */
231 StackReserve
= (StackReserve
) ? StackReserve
:
232 SystemBasicInfo
.AllocationGranularity
;
233 StackCommit
= (StackCommit
) ? StackCommit
: SystemBasicInfo
.PageSize
;
236 /* Align everything to Page Size */
237 StackReserve
= ROUND_UP(StackReserve
, SystemBasicInfo
.AllocationGranularity
);
238 StackCommit
= ROUND_UP(StackCommit
, SystemBasicInfo
.PageSize
);
239 #if 1 // FIXME: Remove once Guard Page support is here
240 StackCommit
= StackReserve
;
242 DPRINT("StackReserve: %lx, StackCommit: %lx\n", StackReserve
, StackCommit
);
244 /* Reserve memory for the stack */
245 Status
= ZwAllocateVirtualMemory(hProcess
,
251 if (!NT_SUCCESS(Status
))
253 DPRINT1("Failure to reserve stack\n");
257 /* Now set up some basic Initial TEB Parameters */
258 InitialTeb
->AllocatedStackBase
= (PVOID
)Stack
;
259 InitialTeb
->StackBase
= (PVOID
)(Stack
+ StackReserve
);
260 InitialTeb
->PreviousStackBase
= NULL
;
261 InitialTeb
->PreviousStackLimit
= NULL
;
263 /* Update the Stack Position */
264 Stack
+= StackReserve
- StackCommit
;
266 /* Check if we will need a guard page */
267 if (StackReserve
> StackCommit
)
269 Stack
-= SystemBasicInfo
.PageSize
;
270 StackCommit
+= SystemBasicInfo
.PageSize
;
274 /* Allocate memory for the stack */
275 Status
= ZwAllocateVirtualMemory(hProcess
,
281 if (!NT_SUCCESS(Status
))
283 DPRINT1("Failure to allocate stack\n");
287 /* Now set the current Stack Limit */
288 InitialTeb
->StackLimit
= (PVOID
)Stack
;
290 /* Create a guard page */
293 ULONG GuardPageSize
= SystemBasicInfo
.PageSize
;
296 /* Attempt maximum space possible */
297 Status
= ZwProtectVirtualMemory(hProcess
,
300 PAGE_GUARD
| PAGE_READWRITE
,
302 if (!NT_SUCCESS(Status
))
304 DPRINT1("Failure to create guard page\n");
308 /* Update the Stack Limit keeping in mind the Guard Page */
309 InitialTeb
->StackLimit
= (PVOID
)((ULONG_PTR
)InitialTeb
->StackLimit
- GuardPageSize
);
313 return STATUS_SUCCESS
;
318 BasepFreeStack(HANDLE hProcess
,
319 PINITIAL_TEB InitialTeb
)
324 NtFreeVirtualMemory(hProcess
,
325 &InitialTeb
->AllocatedStackBase
,
331 * Creates the Initial Context for a Thread or Fiber
335 BasepInitializeContext(IN PCONTEXT Context
,
337 IN PVOID StartAddress
,
338 IN PVOID StackAddress
,
339 IN ULONG ContextType
)
342 DPRINT("BasepInitializeContext: %p\n", Context
);
344 /* Setup the Initial Win32 Thread Context */
345 Context
->Eax
= (ULONG
)StartAddress
;
346 Context
->Ebx
= (ULONG
)Parameter
;
347 Context
->Esp
= (ULONG
)StackAddress
;
348 /* The other registers are undefined */
350 /* Setup the Segments */
351 Context
->SegFs
= KGDT_R3_TEB
| RPL_MASK
;
352 Context
->SegEs
= KGDT_R3_DATA
| RPL_MASK
;
353 Context
->SegDs
= KGDT_R3_DATA
| RPL_MASK
;
354 Context
->SegCs
= KGDT_R3_CODE
| RPL_MASK
;
355 Context
->SegSs
= KGDT_R3_DATA
| RPL_MASK
;
359 Context
->EFlags
= 0x3000; /* IOPL 3 */
361 if (ContextType
== 1) /* For Threads */
363 Context
->Eip
= (ULONG
)BaseThreadStartupThunk
;
365 else if (ContextType
== 2) /* For Fibers */
367 //Context->Eip = (ULONG)BaseFiberStartup;
369 else /* For first thread in a Process */
371 Context
->Eip
= (ULONG
)BaseProcessStartThunk
;
374 /* Set the Context Flags */
375 Context
->ContextFlags
= CONTEXT_FULL
;
377 /* Give it some room for the Parameter */
378 Context
->Esp
-= sizeof(PVOID
);
380 #warning Unknown architecture
387 * Checks if the privilege for Real-Time Priority is there
391 BasepCheckRealTimePrivilege(VOID
)
397 * Maps an image file into a section
401 BasepMapFile(IN LPCWSTR lpApplicationName
,
402 OUT PHANDLE hSection
,
403 IN PUNICODE_STRING ApplicationName
)
406 OBJECT_ATTRIBUTES ObjectAttributes
;
409 IO_STATUS_BLOCK IoStatusBlock
;
411 DPRINT("BasepMapFile\n");
413 /* Zero out the Relative Directory */
414 RelativeName
.Handle
= NULL
;
416 /* Find the application name */
417 if (!RtlDosPathNameToNtPathName_U(lpApplicationName
,
422 return STATUS_OBJECT_PATH_NOT_FOUND
;
425 DPRINT("ApplicationName %wZ\n", ApplicationName
);
426 DPRINT("RelativeName %wZ\n", &RelativeName
.DosPath
);
428 /* Did we get a relative name? */
429 if (RelativeName
.DosPath
.Length
)
431 ApplicationName
= &RelativeName
.DosPath
;
434 /* Initialize the Object Attributes */
435 InitializeObjectAttributes(&ObjectAttributes
,
437 OBJ_CASE_INSENSITIVE
,
441 /* Try to open the executable */
442 Status
= NtOpenFile(&hFile
,
443 SYNCHRONIZE
| FILE_EXECUTE
| FILE_READ_DATA
,
446 FILE_SHARE_DELETE
| FILE_SHARE_READ
,
447 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_NON_DIRECTORY_FILE
);
448 if (!NT_SUCCESS(Status
))
450 DPRINT1("Failed to open file\n");
451 SetLastErrorByStatus(Status
);
455 /* Create a section for this file */
456 Status
= NtCreateSection(hSection
,
466 DPRINT("Section: %lx for file: %lx\n", *hSection
, hFile
);