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 /* FUNCTIONS ****************************************************************/
19 * Converts an ANSI or OEM String to the specified Unicode String
23 Basep8BitStringToLiveUnicodeString(OUT PUNICODE_STRING UnicodeString
,
26 ANSI_STRING AnsiString
;
29 DPRINT("Basep8BitStringToLiveUnicodeString\n");
31 /* Create the ANSI String */
32 RtlInitAnsiString(&AnsiString
, String
);
34 /* Convert from OEM or ANSI */
35 Status
= Basep8BitStringToUnicodeString(UnicodeString
, &AnsiString
, FALSE
);
38 if (!NT_SUCCESS(Status
))
40 SetLastErrorByStatus(Status
);
47 * Converts an ANSI or OEM String to the TEB StaticUnicodeString
51 Basep8BitStringToCachedUnicodeString(IN LPCSTR String
)
53 PUNICODE_STRING StaticString
= &NtCurrentTeb()->StaticUnicodeString
;
54 ANSI_STRING AnsiString
;
57 DPRINT("Basep8BitStringToCachedUnicodeString\n");
59 /* Initialize an ANSI String */
60 RtlInitAnsiString(&AnsiString
, String
);
63 Status
= Basep8BitStringToUnicodeString(StaticString
, &AnsiString
, FALSE
);
66 if (!NT_SUCCESS(Status
))
68 SetLastErrorByStatus(Status
);
72 /* Return pointer to the string */
77 * Allocates space from the Heap and converts an Ansi String into it
81 BasepAnsiStringToHeapUnicodeString(IN LPCSTR AnsiString
,
82 IN PVOID UnicodeString
)
85 UNICODE_STRING UnicodeTemp
;
87 DPRINT("BasepAnsiStringToHeapUnicodeString\n");
89 /* First create the ANSI_STRING */
90 RtlInitAnsiString(&AnsiTemp
, AnsiString
);
92 /* Now get the size needed */
93 UnicodeTemp
.MaximumLength
= RtlAnsiStringToUnicodeSize(&AnsiTemp
);
95 /* Allocate space from the Heap for the string */
96 UnicodeString
= RtlAllocateHeap(GetProcessHeap(),
98 UnicodeTemp
.MaximumLength
);
100 /* Save the buffer and convert */
101 UnicodeTemp
.Buffer
= UnicodeString
;
102 RtlAnsiStringToUnicodeString(&UnicodeTemp
, &AnsiTemp
, FALSE
);
106 * Converts lpSecurityAttributes + Object Name into ObjectAttributes.
110 BasepConvertObjectAttributes(OUT POBJECT_ATTRIBUTES ObjectAttributes
,
111 IN PSECURITY_ATTRIBUTES SecurityAttributes OPTIONAL
,
112 IN PUNICODE_STRING ObjectName
)
114 ULONG Attributes
= 0;
115 HANDLE RootDirectory
= 0;
116 PVOID SecurityDescriptor
= NULL
;
117 BOOLEAN NeedOba
= FALSE
;
119 DPRINT("BasepConvertObjectAttributes. Security: %p, Name: %p\n",
120 SecurityAttributes
, ObjectName
);
122 /* Get the attributes if present */
123 if (SecurityAttributes
)
125 Attributes
= SecurityAttributes
->bInheritHandle
? OBJ_INHERIT
: 0;
126 SecurityDescriptor
= SecurityAttributes
->lpSecurityDescriptor
;
132 Attributes
|= OBJ_OPENIF
;
133 RootDirectory
= hBaseDir
;
137 DPRINT("Attributes: %lx, RootDirectory: %lx, SecurityDescriptor: %p\n",
138 Attributes
, RootDirectory
, SecurityDescriptor
);
140 /* Create the Object Attributes */
143 InitializeObjectAttributes(ObjectAttributes
,
148 return ObjectAttributes
;
151 /* Nothing to return */
156 * Creates a stack for a thread or fiber
160 BasepCreateStack(HANDLE hProcess
,
163 PINITIAL_TEB InitialTeb
)
166 SYSTEM_BASIC_INFORMATION SystemBasicInfo
;
167 PIMAGE_NT_HEADERS Headers
;
169 BOOLEAN UseGuard
= FALSE
;
171 DPRINT("BasepCreateStack (hProcess: %lx, Max: %lx, Current: %lx)\n",
172 hProcess
, StackReserve
, StackCommit
);
174 /* Get some memory information */
175 Status
= NtQuerySystemInformation(SystemBasicInformation
,
177 sizeof(SYSTEM_BASIC_INFORMATION
),
179 if (!NT_SUCCESS(Status
))
181 DPRINT1("Failure to query system info\n");
185 /* Use the Image Settings if we are dealing with the current Process */
186 if (hProcess
== NtCurrentProcess())
188 /* Get the Image Headers */
189 Headers
= RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress
);
191 /* If we didn't get the parameters, find them ourselves */
192 StackReserve
= (StackReserve
) ?
193 StackReserve
: Headers
->OptionalHeader
.SizeOfStackReserve
;
194 StackCommit
= (StackCommit
) ?
195 StackCommit
: Headers
->OptionalHeader
.SizeOfStackCommit
;
199 /* Use the System Settings if needed */
200 StackReserve
= (StackReserve
) ? StackReserve
:
201 SystemBasicInfo
.AllocationGranularity
;
202 StackCommit
= (StackCommit
) ? StackCommit
: SystemBasicInfo
.PageSize
;
205 /* Align everything to Page Size */
206 StackReserve
= ROUND_UP(StackReserve
, SystemBasicInfo
.AllocationGranularity
);
207 StackCommit
= ROUND_UP(StackCommit
, SystemBasicInfo
.PageSize
);
208 #if 1 // FIXME: Remove once Guard Page support is here
209 StackCommit
= StackReserve
;
211 DPRINT("StackReserve: %lx, StackCommit: %lx\n", StackReserve
, StackCommit
);
213 /* Reserve memory for the stack */
214 Status
= ZwAllocateVirtualMemory(hProcess
,
220 if (!NT_SUCCESS(Status
))
222 DPRINT1("Failure to reserve stack\n");
226 /* Now set up some basic Initial TEB Parameters */
227 InitialTeb
->AllocatedStackBase
= (PVOID
)Stack
;
228 InitialTeb
->StackBase
= (PVOID
)(Stack
+ StackReserve
);
230 /* Update the Stack Position */
231 Stack
+= StackReserve
- StackCommit
;
233 /* Check if we will need a guard page */
234 if (StackReserve
> StackCommit
)
236 Stack
-= SystemBasicInfo
.PageSize
;
237 StackCommit
+= SystemBasicInfo
.PageSize
;
241 /* Allocate memory for the stack */
242 Status
= ZwAllocateVirtualMemory(hProcess
,
248 if (!NT_SUCCESS(Status
))
250 DPRINT1("Failure to allocate stack\n");
254 /* Now set the current Stack Limit */
255 InitialTeb
->StackLimit
= (PVOID
)Stack
;
257 /* Create a guard page */
260 ULONG GuardPageSize
= SystemBasicInfo
.PageSize
;
263 /* Attempt maximum space possible */
264 Status
= ZwProtectVirtualMemory(hProcess
,
267 PAGE_GUARD
| PAGE_READWRITE
,
269 if (!NT_SUCCESS(Status
))
271 DPRINT1("Failure to create guard page\n");
275 /* Update the Stack Limit keeping in mind the Guard Page */
276 InitialTeb
->StackLimit
= (PVOID
)((ULONG_PTR
)InitialTeb
->StackLimit
- GuardPageSize
);
280 return STATUS_SUCCESS
;
285 BasepFreeStack(HANDLE hProcess
,
286 PINITIAL_TEB InitialTeb
)
291 NtFreeVirtualMemory(hProcess
,
292 &InitialTeb
->AllocatedStackBase
,
298 * Creates the Initial Context for a Thread or Fiber
302 BasepInitializeContext(IN PCONTEXT Context
,
304 IN PVOID StartAddress
,
305 IN PVOID StackAddress
,
306 IN ULONG ContextType
)
308 DPRINT("BasepInitializeContext: %p\n", Context
);
310 /* Setup the Initial Win32 Thread Context */
311 Context
->Eax
= (ULONG
)StartAddress
;
312 Context
->Ebx
= (ULONG
)Parameter
;
313 Context
->Esp
= (ULONG
)StackAddress
;
314 /* The other registers are undefined */
316 /* Setup the Segments */
317 Context
->SegCs
= USER_CS
;
318 Context
->SegDs
= USER_DS
;
319 Context
->SegEs
= USER_DS
;
320 Context
->SegFs
= TEB_SELECTOR
;
321 Context
->SegSs
= USER_DS
;
325 Context
->EFlags
= 0x3000; /* IOPL 3 */
327 if (ContextType
== 1) /* For Threads */
329 Context
->Eip
= (ULONG
)BaseThreadStartupThunk
;
331 else if (ContextType
== 2) /* For Fibers */
333 //Context->Eip = (ULONG)BaseFiberStartup;
335 else /* For first thread in a Process */
337 Context
->Eip
= (ULONG
)BaseProcessStartThunk
;
340 /* Set the Context Flags */
341 Context
->ContextFlags
= CONTEXT_FULL
;
343 /* Give it some room for the Parameter */
344 Context
->Esp
-= sizeof(PVOID
);
348 * Checks if the privilege for Real-Time Priority is there
352 BasepCheckRealTimePrivilege(VOID
)
358 * Maps an image file into a section
362 BasepMapFile(IN LPCWSTR lpApplicationName
,
363 OUT PHANDLE hSection
,
364 IN PUNICODE_STRING ApplicationName
)
367 OBJECT_ATTRIBUTES ObjectAttributes
;
370 IO_STATUS_BLOCK IoStatusBlock
;
372 DPRINT("BasepMapFile\n");
374 /* Zero out the Relative Directory */
375 RelativeName
.Handle
= NULL
;
377 /* Find the application name */
378 RtlDosPathNameToNtPathName_U((LPWSTR
)lpApplicationName
,
382 DPRINT("ApplicationName %wZ\n", ApplicationName
);
383 DPRINT("RelativeName %wZ\n", &RelativeName
.DosPath
);
385 /* Did we get a relative name? */
386 if (RelativeName
.DosPath
.Length
)
388 ApplicationName
= &RelativeName
.DosPath
;
391 /* Initialize the Object Attributes */
392 InitializeObjectAttributes(&ObjectAttributes
,
394 OBJ_CASE_INSENSITIVE
,
398 /* Try to open the executable */
399 Status
= NtOpenFile(&hFile
,
400 SYNCHRONIZE
| FILE_EXECUTE
| FILE_READ_DATA
,
403 FILE_SHARE_DELETE
| FILE_SHARE_READ
,
404 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_NON_DIRECTORY_FILE
);
405 if (!NT_SUCCESS(Status
))
407 DPRINT1("Failed to open file\n");
408 SetLastErrorByStatus (Status
);
412 /* Create a section for this file */
413 Status
= NtCreateSection(hSection
,
423 DPRINT("Section: %lx for file: %lx\n", *hSection
, hFile
);