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