xref: /reactos/sdk/lib/nt/entry_point.c (revision 8a978a17)
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 
17 NTSTATUS
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 
31 static
32 VOID 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 
57 VOID
58 NTAPI
59 NtProcessStartup(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 
197 fail:
198     /* We're done here */
199     NtTerminateProcess(NtCurrentProcess(), Status);
200 }
201 
202 /* EOF */
203