1 /*** 2 *wincmdln.c - process command line for WinMain 3 * 4 * Copyright (c) Microsoft Corporation. All rights reserved. 5 * 6 *Purpose: 7 * Prepare command line to be passed to [w]WinMain. 8 * 9 *******************************************************************************/ 10 11 #include <corecrt_internal.h> 12 #include <mbstring.h> 13 14 15 16 // In the function below, we need to ensure that we've initialized the mbc table 17 // before we start performing character transformations. 18 static void do_locale_initialization(unsigned char) throw() { __acrt_initialize_multibyte(); } 19 static void do_locale_initialization(wchar_t) throw() { /* no-op */ } 20 21 static unsigned char* get_command_line(unsigned char) throw() 22 { 23 return reinterpret_cast<unsigned char *>(_acmdln); 24 } 25 26 static wchar_t* get_command_line(wchar_t) throw() { return _wcmdln; } 27 28 29 // should_copy_another_character is *ONLY* checking for DBCS lead bytes to see if there 30 // might be a following trail byte. This works because the callers are only concerned 31 // about escaped quote sequences and other codepages aren't using those quotes. 32 static bool __cdecl should_copy_another_character(unsigned char const c) throw() 33 { 34 // This is OK for UTF-8 as a quote is never a trail byte. 35 return _ismbblead(c) != 0; 36 } 37 38 static bool __cdecl should_copy_another_character(wchar_t) throw() 39 { 40 // This is OK for UTF-16 as a quote is never part of a surrogate pair. 41 return false; 42 } 43 44 45 46 /*** 47 *_[w]wincmdln 48 * 49 *Purpose: 50 * Extract the command line tail to be passed to WinMain. 51 * 52 * Be warned! This code was originally implemented by the NT group and 53 * has remained pretty much unchanged since 12-91. It should be changed 54 * only with extreme care since there are undoubtedly many apps which 55 * depend on its historical behavior. 56 * 57 *Entry: 58 * The global variable _[a|w]cmdln is set to point at the complete 59 * command line. 60 * 61 *Exit: 62 * Returns a pointer to the command line tail. 63 * 64 *Exceptions: 65 * 66 *******************************************************************************/ 67 template <typename Character> 68 static Character* __cdecl common_wincmdln() throw() 69 { 70 do_locale_initialization(Character()); 71 72 static Character empty_string[] = { '\0' }; 73 74 Character* command_line = get_command_line(Character()) == nullptr 75 ? empty_string 76 : get_command_line(Character()); 77 78 // Skip past the program name (the first token in the command line) and 79 // check for and handle a quoted program name: 80 bool in_double_quotes = false; 81 while (*command_line > ' ' || (*command_line != '\0' && in_double_quotes)) 82 { 83 // Toggle the in_double_quotes flag if the current character is '"' 84 if (*command_line == '"') 85 in_double_quotes = !in_double_quotes; 86 87 if (should_copy_another_character(*command_line)) 88 ++command_line; 89 90 ++command_line; 91 } 92 93 // Skip past any whitespace preceding the next token: 94 while (*command_line != '\0' && *command_line <= ' ') 95 ++command_line; 96 97 return command_line; 98 } 99 100 101 102 extern "C" char* __cdecl _get_narrow_winmain_command_line() 103 { // Need to use unsigned char so that we correctly handle ASCII characters 104 // above 127, in particular the comparison to ' ' (space - 0x20). 105 return reinterpret_cast<char *>(common_wincmdln<unsigned char>()); 106 } 107 108 extern "C" wchar_t* __cdecl _get_wide_winmain_command_line() 109 { 110 return common_wincmdln<wchar_t>(); 111 } 112