Reactos
1/*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS
4 * FILE: lib/nt/entry_point.c
5 * PURPOSE: Native NT Runtime Library
6 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
7 */
8
9/* INCLUDES ******************************************************************/
10
11/* PSDK/NDK Headers */
12#define WIN32_NO_STATUS
13#define NTOS_MODE_USER
14// #include <ndk/psfuncs.h>
15#include <ndk/rtlfuncs.h>
16
17NTSTATUS
18__cdecl
19_main(
20 int argc,
21 char *argv[],
22 char *envp[],
23 ULONG DebugFlag
24);
25
26#define NDEBUG
27#include <debug.h>
28
29/* FUNCTIONS ****************************************************************/
30
31static
32VOID FASTCALL EnvironmentStringToUnicodeString (PWCHAR wsIn, PUNICODE_STRING usOut)
33{
34 if (wsIn)
35 {
36 PWCHAR CurrentChar = wsIn;
37
38 while (*CurrentChar)
39 {
40 while (*CurrentChar++);
41 }
42 /* Double NULL-termination at end */
43 CurrentChar++;
44
45 usOut->Buffer = wsIn;
46 /* FIXME: the last (double) nullterm should perhaps not be included in Length
47 * but only in MaximumLength. -Gunnar */
48 usOut->MaximumLength = usOut->Length = (CurrentChar-wsIn) * sizeof(WCHAR);
49 }
50 else
51 {
52 usOut->Buffer = NULL;
53 usOut->Length = usOut->MaximumLength = 0;
54 }
55}
56
57VOID
58NTAPI
59NtProcessStartup(PPEB Peb)
60{
61 NTSTATUS Status;
62 PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
63 PUNICODE_STRING CmdLineString;
64 ANSI_STRING AnsiCmdLine;
65 UNICODE_STRING UnicodeEnvironment;
66 ANSI_STRING AnsiEnvironment;
67 PCHAR NullPointer = NULL;
68 INT argc = 0;
69 PCHAR *argv;
70 PCHAR *envp;
71 PCHAR *ArgumentList;
72 PCHAR Source, Destination;
73 ULONG Length;
74 ASSERT(Peb);
75
76#ifdef _M_ARM // Huge achievement
77 DPRINT1("%s(%08lx) called\n", __FUNCTION__, Peb);
78 while (TRUE);
79#endif
80
81 /* Normalize and get the Process Parameters */
82 ProcessParameters = RtlNormalizeProcessParams(Peb->ProcessParameters);
83 ASSERT(ProcessParameters);
84
85 /* Allocate memory for the argument list, enough for 512 tokens */
86 // FIXME: what if 512 is not enough????
87 ArgumentList = RtlAllocateHeap(RtlGetProcessHeap(), 0, 512 * sizeof(PCHAR));
88 if (!ArgumentList)
89 {
90 DPRINT1("ERR: no mem!");
91 Status = STATUS_NO_MEMORY;
92 goto fail;
93 }
94
95 /* Use a null pointer as default */
96 argv = &NullPointer;
97 envp = &NullPointer;
98
99 /* Set the first pointer to NULL, and set the argument array to the buffer */
100 *ArgumentList = NULL;
101 argv = ArgumentList;
102
103 /* Get the pointer to the Command Line */
104 CmdLineString = &ProcessParameters->CommandLine;
105
106 /* If we don't have a command line, use the image path instead */
107 if (!CmdLineString->Buffer || !CmdLineString->Length)
108 {
109 CmdLineString = &ProcessParameters->ImagePathName;
110 }
111
112 /* Convert it to an ANSI string */
113 Status = RtlUnicodeStringToAnsiString(&AnsiCmdLine, CmdLineString, TRUE);
114 if (!NT_SUCCESS(Status))
115 {
116 DPRINT1("ERR: no mem(guess)\n");
117 goto fail;
118 }
119
120 /* Save parameters for parsing */
121 Source = AnsiCmdLine.Buffer;
122 Length = AnsiCmdLine.Length;
123
124 /* Ensure it's valid */
125 if (Source)
126 {
127 /* Allocate a buffer for the destination */
128 Destination = RtlAllocateHeap(RtlGetProcessHeap(), 0, Length + sizeof(WCHAR));
129 if (!Destination)
130 {
131 DPRINT1("ERR: no mem!");
132 Status = STATUS_NO_MEMORY;
133 goto fail;
134 }
135
136 /* Start parsing */
137 while (*Source)
138 {
139 /* Skip the white space */
140 while (*Source && *Source <= ' ') Source++;
141
142 /* Copy until the next white space is reached */
143 if (*Source)
144 {
145 /* Save one token pointer */
146 *ArgumentList++ = Destination;
147
148 /* Increase one token count */
149 argc++;
150
151 /* Copy token until white space */
152 while (*Source > ' ') *Destination++ = *Source++;
153
154 /* Null terminate it */
155 *Destination++ = '\0';
156 }
157 }
158 }
159
160 /* Null terminate the token pointer list */
161 *ArgumentList++ = NULL;
162
163 /* Now handle the environment, point the envp at our current list location. */
164 envp = ArgumentList;
165
166 if (ProcessParameters->Environment)
167 {
168 EnvironmentStringToUnicodeString(ProcessParameters->Environment, &UnicodeEnvironment);
169 Status = RtlUnicodeStringToAnsiString (&AnsiEnvironment, &UnicodeEnvironment, TRUE);
170 if (!NT_SUCCESS(Status))
171 {
172 DPRINT1("ERR: no mem(guess)\n");
173 goto fail;
174 }
175
176 ASSERT(AnsiEnvironment.Buffer);
177
178 Source = AnsiEnvironment.Buffer;
179 while (*Source)
180 {
181 /* Save a pointer to this token */
182 *ArgumentList++ = Source;
183
184 /* Keep looking for another variable */
185 while (*Source++);
186 }
187
188 /* Null terminate the list again */
189 *ArgumentList++ = NULL;
190 }
191 /* Breakpoint if we were requested to do so */
192 if (ProcessParameters->DebugFlags) DbgBreakPoint();
193
194 /* Call the Main Function */
195 Status = _main(argc, argv, envp, ProcessParameters->DebugFlags);
196
197fail:
198 /* We're done here */
199 NtTerminateProcess(NtCurrentProcess(), Status);
200}
201
202/* EOF */