Initialized Basep8BitStringToUnicodeString
[reactos.git] / reactos / lib / kernel32 / misc / utils.c
1 /*
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 */
8
9 /* INCLUDES ****************************************************************/
10
11 #include <k32.h>
12
13 #define NDEBUG
14 #include "../include/debug.h"
15
16 /* GLOBALS ******************************************************************/
17
18 PRTL_CONVERT_STRING Basep8BitStringToUnicodeString = RtlAnsiStringToUnicodeString;
19
20 /* FUNCTIONS ****************************************************************/
21
22 /*
23 * Converts an ANSI or OEM String to the specified Unicode String
24 */
25 NTSTATUS
26 STDCALL
27 Basep8BitStringToLiveUnicodeString(OUT PUNICODE_STRING UnicodeString,
28 IN LPCSTR String)
29 {
30 ANSI_STRING AnsiString;
31 NTSTATUS Status;
32
33 DPRINT("Basep8BitStringToLiveUnicodeString\n");
34
35 /* Create the ANSI String */
36 RtlInitAnsiString(&AnsiString, String);
37
38 /* Convert from OEM or ANSI */
39 Status = Basep8BitStringToUnicodeString(UnicodeString, &AnsiString, FALSE);
40
41 /* Return Status */
42 if (!NT_SUCCESS(Status))
43 {
44 SetLastErrorByStatus(Status);
45 }
46 return Status;
47 }
48
49
50 /*
51 * Converts an ANSI or OEM String to the TEB StaticUnicodeString
52 */
53 PUNICODE_STRING
54 STDCALL
55 Basep8BitStringToCachedUnicodeString(IN LPCSTR String)
56 {
57 PUNICODE_STRING StaticString = &NtCurrentTeb()->StaticUnicodeString;
58 ANSI_STRING AnsiString;
59 NTSTATUS Status;
60
61 DPRINT("Basep8BitStringToCachedUnicodeString\n");
62
63 /* Initialize an ANSI String */
64 RtlInitAnsiString(&AnsiString, String);
65
66 /* Convert it */
67 Status = Basep8BitStringToUnicodeString(StaticString, &AnsiString, FALSE);
68
69 /* Handle failure */
70 if (!NT_SUCCESS(Status))
71 {
72 SetLastErrorByStatus(Status);
73 return NULL;
74 }
75
76 /* Return pointer to the string */
77 return StaticString;
78 }
79
80 NTSTATUS
81 STDCALL
82 Basep8BitStringToHeapUnicodeString(OUT PUNICODE_STRING UnicodeString,
83 IN LPCSTR String)
84 {
85 ANSI_STRING AnsiString;
86 NTSTATUS Status;
87
88 DPRINT("Basep8BitStringToCachedUnicodeString\n");
89
90 /* Initialize an ANSI String */
91 RtlInitAnsiString(&AnsiString, String);
92
93 /* Convert it */
94 Status = Basep8BitStringToUnicodeString(UnicodeString, &AnsiString, TRUE);
95
96 /* Handle failure */
97 if (!NT_SUCCESS(Status))
98 {
99 SetLastErrorByStatus(Status);
100 }
101 /* Return Status */
102 return Status;
103 }
104
105 /*
106 * Allocates space from the Heap and converts an Ansi String into it
107 */
108 VOID
109 STDCALL
110 BasepAnsiStringToHeapUnicodeString(IN LPCSTR AnsiString,
111 OUT LPWSTR* UnicodeString)
112 {
113 ANSI_STRING AnsiTemp;
114 UNICODE_STRING UnicodeTemp;
115
116 DPRINT("BasepAnsiStringToHeapUnicodeString\n");
117
118 /* First create the ANSI_STRING */
119 RtlInitAnsiString(&AnsiTemp, AnsiString);
120
121 if (NT_SUCCESS(RtlAnsiStringToUnicodeString(&UnicodeTemp,
122 &AnsiTemp,
123 TRUE)))
124 {
125 *UnicodeString = UnicodeTemp.Buffer;
126 }
127 else
128 {
129 *UnicodeString = NULL;
130 }
131 }
132
133 /*
134 * Converts lpSecurityAttributes + Object Name into ObjectAttributes.
135 */
136 POBJECT_ATTRIBUTES
137 STDCALL
138 BasepConvertObjectAttributes(OUT POBJECT_ATTRIBUTES ObjectAttributes,
139 IN PSECURITY_ATTRIBUTES SecurityAttributes OPTIONAL,
140 IN PUNICODE_STRING ObjectName)
141 {
142 ULONG Attributes = 0;
143 HANDLE RootDirectory = 0;
144 PVOID SecurityDescriptor = NULL;
145 BOOLEAN NeedOba = FALSE;
146
147 DPRINT("BasepConvertObjectAttributes. Security: %p, Name: %p\n",
148 SecurityAttributes, ObjectName);
149
150 /* Get the attributes if present */
151 if (SecurityAttributes)
152 {
153 Attributes = SecurityAttributes->bInheritHandle ? OBJ_INHERIT : 0;
154 SecurityDescriptor = SecurityAttributes->lpSecurityDescriptor;
155 NeedOba = TRUE;
156 }
157
158 if (ObjectName)
159 {
160 Attributes |= OBJ_OPENIF;
161 RootDirectory = hBaseDir;
162 NeedOba = TRUE;
163 }
164
165 DPRINT("Attributes: %lx, RootDirectory: %lx, SecurityDescriptor: %p\n",
166 Attributes, RootDirectory, SecurityDescriptor);
167
168 /* Create the Object Attributes */
169 if (NeedOba)
170 {
171 InitializeObjectAttributes(ObjectAttributes,
172 ObjectName,
173 Attributes,
174 RootDirectory,
175 SecurityDescriptor);
176 return ObjectAttributes;
177 }
178
179 /* Nothing to return */
180 return NULL;
181 }
182
183 /*
184 * Creates a stack for a thread or fiber
185 */
186 NTSTATUS
187 STDCALL
188 BasepCreateStack(HANDLE hProcess,
189 ULONG StackReserve,
190 ULONG StackCommit,
191 PINITIAL_TEB InitialTeb)
192 {
193 NTSTATUS Status;
194 SYSTEM_BASIC_INFORMATION SystemBasicInfo;
195 PIMAGE_NT_HEADERS Headers;
196 ULONG_PTR Stack = 0;
197 BOOLEAN UseGuard = FALSE;
198
199 DPRINT("BasepCreateStack (hProcess: %lx, Max: %lx, Current: %lx)\n",
200 hProcess, StackReserve, StackCommit);
201
202 /* Get some memory information */
203 Status = NtQuerySystemInformation(SystemBasicInformation,
204 &SystemBasicInfo,
205 sizeof(SYSTEM_BASIC_INFORMATION),
206 NULL);
207 if (!NT_SUCCESS(Status))
208 {
209 DPRINT1("Failure to query system info\n");
210 return Status;
211 }
212
213 /* Use the Image Settings if we are dealing with the current Process */
214 if (hProcess == NtCurrentProcess())
215 {
216 /* Get the Image Headers */
217 Headers = RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress);
218
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;
224 }
225 else
226 {
227 /* Use the System Settings if needed */
228 StackReserve = (StackReserve) ? StackReserve :
229 SystemBasicInfo.AllocationGranularity;
230 StackCommit = (StackCommit) ? StackCommit : SystemBasicInfo.PageSize;
231 }
232
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;
238 #endif
239 DPRINT("StackReserve: %lx, StackCommit: %lx\n", StackReserve, StackCommit);
240
241 /* Reserve memory for the stack */
242 Status = ZwAllocateVirtualMemory(hProcess,
243 (PVOID*)&Stack,
244 0,
245 &StackReserve,
246 MEM_RESERVE,
247 PAGE_READWRITE);
248 if (!NT_SUCCESS(Status))
249 {
250 DPRINT1("Failure to reserve stack\n");
251 return Status;
252 }
253
254 /* Now set up some basic Initial TEB Parameters */
255 InitialTeb->AllocatedStackBase = (PVOID)Stack;
256 InitialTeb->StackBase = (PVOID)(Stack + StackReserve);
257
258 /* Update the Stack Position */
259 Stack += StackReserve - StackCommit;
260
261 /* Check if we will need a guard page */
262 if (StackReserve > StackCommit)
263 {
264 Stack -= SystemBasicInfo.PageSize;
265 StackCommit += SystemBasicInfo.PageSize;
266 UseGuard = TRUE;
267 }
268
269 /* Allocate memory for the stack */
270 Status = ZwAllocateVirtualMemory(hProcess,
271 (PVOID*)&Stack,
272 0,
273 &StackCommit,
274 MEM_COMMIT,
275 PAGE_READWRITE);
276 if (!NT_SUCCESS(Status))
277 {
278 DPRINT1("Failure to allocate stack\n");
279 return Status;
280 }
281
282 /* Now set the current Stack Limit */
283 InitialTeb->StackLimit = (PVOID)Stack;
284
285 /* Create a guard page */
286 if (UseGuard)
287 {
288 ULONG GuardPageSize = SystemBasicInfo.PageSize;
289 ULONG Dummy;
290
291 /* Attempt maximum space possible */
292 Status = ZwProtectVirtualMemory(hProcess,
293 (PVOID*)&Stack,
294 &GuardPageSize,
295 PAGE_GUARD | PAGE_READWRITE,
296 &Dummy);
297 if (!NT_SUCCESS(Status))
298 {
299 DPRINT1("Failure to create guard page\n");
300 return Status;
301 }
302
303 /* Update the Stack Limit keeping in mind the Guard Page */
304 InitialTeb->StackLimit = (PVOID)((ULONG_PTR)InitialTeb->StackLimit - GuardPageSize);
305 }
306
307 /* We are done! */
308 return STATUS_SUCCESS;
309 }
310
311 VOID
312 STDCALL
313 BasepFreeStack(HANDLE hProcess,
314 PINITIAL_TEB InitialTeb)
315 {
316 ULONG Dummy = 0;
317
318 /* Free the Stack */
319 NtFreeVirtualMemory(hProcess,
320 &InitialTeb->AllocatedStackBase,
321 &Dummy,
322 MEM_RELEASE);
323 }
324
325 /*
326 * Creates the Initial Context for a Thread or Fiber
327 */
328 VOID
329 STDCALL
330 BasepInitializeContext(IN PCONTEXT Context,
331 IN PVOID Parameter,
332 IN PVOID StartAddress,
333 IN PVOID StackAddress,
334 IN ULONG ContextType)
335 {
336 DPRINT("BasepInitializeContext: %p\n", Context);
337
338 /* Setup the Initial Win32 Thread Context */
339 Context->Eax = (ULONG)StartAddress;
340 Context->Ebx = (ULONG)Parameter;
341 Context->Esp = (ULONG)StackAddress;
342 /* The other registers are undefined */
343
344 /* Setup the Segments */
345 Context->SegCs = USER_CS;
346 Context->SegDs = USER_DS;
347 Context->SegEs = USER_DS;
348 Context->SegFs = TEB_SELECTOR;
349 Context->SegSs = USER_DS;
350 Context->SegGs = 0;
351
352 /* Set the EFLAGS */
353 Context->EFlags = 0x3000; /* IOPL 3 */
354
355 if (ContextType == 1) /* For Threads */
356 {
357 Context->Eip = (ULONG)BaseThreadStartupThunk;
358 }
359 else if (ContextType == 2) /* For Fibers */
360 {
361 //Context->Eip = (ULONG)BaseFiberStartup;
362 }
363 else /* For first thread in a Process */
364 {
365 Context->Eip = (ULONG)BaseProcessStartThunk;
366 }
367
368 /* Set the Context Flags */
369 Context->ContextFlags = CONTEXT_FULL;
370
371 /* Give it some room for the Parameter */
372 Context->Esp -= sizeof(PVOID);
373 }
374
375 /*
376 * Checks if the privilege for Real-Time Priority is there
377 */
378 BOOLEAN
379 STDCALL
380 BasepCheckRealTimePrivilege(VOID)
381 {
382 return TRUE;
383 }
384
385 /*
386 * Maps an image file into a section
387 */
388 NTSTATUS
389 STDCALL
390 BasepMapFile(IN LPCWSTR lpApplicationName,
391 OUT PHANDLE hSection,
392 IN PUNICODE_STRING ApplicationName)
393 {
394 CURDIR RelativeName;
395 OBJECT_ATTRIBUTES ObjectAttributes;
396 NTSTATUS Status;
397 HANDLE hFile = NULL;
398 IO_STATUS_BLOCK IoStatusBlock;
399
400 DPRINT("BasepMapFile\n");
401
402 /* Zero out the Relative Directory */
403 RelativeName.Handle = NULL;
404
405 /* Find the application name */
406 RtlDosPathNameToNtPathName_U((LPWSTR)lpApplicationName,
407 ApplicationName,
408 NULL,
409 &RelativeName);
410 DPRINT("ApplicationName %wZ\n", ApplicationName);
411 DPRINT("RelativeName %wZ\n", &RelativeName.DosPath);
412
413 /* Did we get a relative name? */
414 if (RelativeName.DosPath.Length)
415 {
416 ApplicationName = &RelativeName.DosPath;
417 }
418
419 /* Initialize the Object Attributes */
420 InitializeObjectAttributes(&ObjectAttributes,
421 ApplicationName,
422 OBJ_CASE_INSENSITIVE,
423 RelativeName.Handle,
424 NULL);
425
426 /* Try to open the executable */
427 Status = NtOpenFile(&hFile,
428 SYNCHRONIZE | FILE_EXECUTE | FILE_READ_DATA,
429 &ObjectAttributes,
430 &IoStatusBlock,
431 FILE_SHARE_DELETE | FILE_SHARE_READ,
432 FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE);
433 if (!NT_SUCCESS(Status))
434 {
435 DPRINT1("Failed to open file\n");
436 SetLastErrorByStatus (Status);
437 return Status;
438 }
439
440 /* Create a section for this file */
441 Status = NtCreateSection(hSection,
442 SECTION_ALL_ACCESS,
443 NULL,
444 NULL,
445 PAGE_EXECUTE,
446 SEC_IMAGE,
447 hFile);
448 NtClose(hFile);
449
450 /* Return status */
451 DPRINT("Section: %lx for file: %lx\n", *hSection, hFile);
452 return Status;
453 }