Alexandre Julliard | fe08568 | 2000-03-18 21:56:10 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Option parsing |
| 3 | * |
| 4 | * Copyright 2000 Alexandre Julliard |
| 5 | */ |
| 6 | |
| 7 | #include "config.h" |
| 8 | #include <string.h> |
Alexandre Julliard | eeaae3c | 2000-05-30 17:51:44 +0000 | [diff] [blame] | 9 | #include <stdlib.h> |
Alexandre Julliard | fe08568 | 2000-03-18 21:56:10 +0000 | [diff] [blame] | 10 | |
| 11 | #include "winbase.h" |
Alexandre Julliard | 909eff9 | 2000-12-15 03:38:11 +0000 | [diff] [blame] | 12 | #include "winnls.h" |
Guy L. Albertelli | 8d91b50 | 2001-01-04 19:37:37 +0000 | [diff] [blame] | 13 | #include "ntddk.h" |
Alexandre Julliard | 85423c6 | 2000-11-08 04:28:54 +0000 | [diff] [blame] | 14 | #include "wine/library.h" |
Alexandre Julliard | fe08568 | 2000-03-18 21:56:10 +0000 | [diff] [blame] | 15 | #include "options.h" |
Alexandre Julliard | b9c9cdc | 2001-03-20 02:11:08 +0000 | [diff] [blame] | 16 | #include "loadorder.h" |
Alexandre Julliard | fe08568 | 2000-03-18 21:56:10 +0000 | [diff] [blame] | 17 | #include "version.h" |
| 18 | #include "debugtools.h" |
| 19 | |
Alexandre Julliard | ca43a64 | 2001-01-10 23:56:59 +0000 | [diff] [blame] | 20 | struct option_descr |
Alexandre Julliard | fe08568 | 2000-03-18 21:56:10 +0000 | [diff] [blame] | 21 | { |
| 22 | const char *longname; |
| 23 | char shortname; |
| 24 | int has_arg; |
Alexandre Julliard | eeaae3c | 2000-05-30 17:51:44 +0000 | [diff] [blame] | 25 | int inherit; |
Alexandre Julliard | fe08568 | 2000-03-18 21:56:10 +0000 | [diff] [blame] | 26 | void (*func)( const char *arg ); |
| 27 | const char *usage; |
| 28 | }; |
| 29 | |
Alexandre Julliard | c192ba2 | 2000-05-29 21:25:10 +0000 | [diff] [blame] | 30 | /* default options */ |
| 31 | struct options Options = |
| 32 | { |
Alexandre Julliard | ca43a64 | 2001-01-10 23:56:59 +0000 | [diff] [blame] | 33 | FALSE /* Managed windows */ |
Alexandre Julliard | c192ba2 | 2000-05-29 21:25:10 +0000 | [diff] [blame] | 34 | }; |
| 35 | |
Alexandre Julliard | a3e0cfc | 2000-07-16 18:21:34 +0000 | [diff] [blame] | 36 | const char *argv0; /* the original argv[0] */ |
| 37 | const char *full_argv0; /* the full path of argv[0] (if known) */ |
Alexandre Julliard | c192ba2 | 2000-05-29 21:25:10 +0000 | [diff] [blame] | 38 | |
Alexandre Julliard | eeaae3c | 2000-05-30 17:51:44 +0000 | [diff] [blame] | 39 | static char *inherit_str; /* options to pass to child processes */ |
| 40 | |
Alexandre Julliard | b1e7028 | 2000-11-09 20:29:42 +0000 | [diff] [blame] | 41 | static int app_argc; /* argc/argv to pass to application */ |
| 42 | static char **app_argv; |
Alexandre Julliard | 909eff9 | 2000-12-15 03:38:11 +0000 | [diff] [blame] | 43 | static WCHAR **app_wargv; |
Alexandre Julliard | b1e7028 | 2000-11-09 20:29:42 +0000 | [diff] [blame] | 44 | |
Alexandre Julliard | eeaae3c | 2000-05-30 17:51:44 +0000 | [diff] [blame] | 45 | static void out_of_memory(void) WINE_NORETURN; |
| 46 | static void out_of_memory(void) |
| 47 | { |
| 48 | MESSAGE( "Virtual memory exhausted\n" ); |
| 49 | ExitProcess(1); |
| 50 | } |
| 51 | |
Alexandre Julliard | 94613ab | 2000-11-05 04:51:34 +0000 | [diff] [blame] | 52 | static void do_debugmsg( const char *arg ); |
Alexandre Julliard | fe08568 | 2000-03-18 21:56:10 +0000 | [diff] [blame] | 53 | static void do_help( const char *arg ); |
| 54 | static void do_managed( const char *arg ); |
Alexandre Julliard | fe08568 | 2000-03-18 21:56:10 +0000 | [diff] [blame] | 55 | static void do_version( const char *arg ); |
| 56 | |
Alexandre Julliard | ca43a64 | 2001-01-10 23:56:59 +0000 | [diff] [blame] | 57 | static const struct option_descr option_table[] = |
Alexandre Julliard | fe08568 | 2000-03-18 21:56:10 +0000 | [diff] [blame] | 58 | { |
Alexandre Julliard | 94613ab | 2000-11-05 04:51:34 +0000 | [diff] [blame] | 59 | { "debugmsg", 0, 1, 1, do_debugmsg, |
Alexandre Julliard | fe08568 | 2000-03-18 21:56:10 +0000 | [diff] [blame] | 60 | "--debugmsg name Turn debugging-messages on or off" }, |
Alexandre Julliard | b9c9cdc | 2001-03-20 02:11:08 +0000 | [diff] [blame] | 61 | { "dll", 0, 1, 1, MODULE_AddLoadOrderOption, |
Alexandre Julliard | fe08568 | 2000-03-18 21:56:10 +0000 | [diff] [blame] | 62 | "--dll name Enable or disable built-in DLLs" }, |
Alexandre Julliard | eeaae3c | 2000-05-30 17:51:44 +0000 | [diff] [blame] | 63 | { "dosver", 0, 1, 1, VERSION_ParseDosVersion, |
Andreas Mohr | cb45438 | 2000-11-27 01:39:05 +0000 | [diff] [blame] | 64 | "--dosver x.xx DOS version to imitate (e.g. 6.22)\n" |
| 65 | " Only valid with --winver win31" }, |
Alexandre Julliard | eeaae3c | 2000-05-30 17:51:44 +0000 | [diff] [blame] | 66 | { "help", 'h', 0, 0, do_help, |
Alexandre Julliard | fe08568 | 2000-03-18 21:56:10 +0000 | [diff] [blame] | 67 | "--help,-h Show this help message" }, |
Alexandre Julliard | eeaae3c | 2000-05-30 17:51:44 +0000 | [diff] [blame] | 68 | { "managed", 0, 0, 0, do_managed, |
Alexandre Julliard | fe08568 | 2000-03-18 21:56:10 +0000 | [diff] [blame] | 69 | "--managed Allow the window manager to manage created windows" }, |
Alexandre Julliard | eeaae3c | 2000-05-30 17:51:44 +0000 | [diff] [blame] | 70 | { "version", 'v', 0, 0, do_version, |
Alexandre Julliard | fe08568 | 2000-03-18 21:56:10 +0000 | [diff] [blame] | 71 | "--version,-v Display the Wine version" }, |
Alexandre Julliard | eeaae3c | 2000-05-30 17:51:44 +0000 | [diff] [blame] | 72 | { "winver", 0, 1, 1, VERSION_ParseWinVersion, |
Andreas Mohr | cb45438 | 2000-11-27 01:39:05 +0000 | [diff] [blame] | 73 | "--winver Version to imitate (win95,nt40,win31,nt2k,win98,nt351,win30,win20)" }, |
Patrik Stridvall | a9f6a9d | 2000-10-24 02:22:16 +0000 | [diff] [blame] | 74 | { NULL, 0, 0, 0, NULL, NULL } /* terminator */ |
Alexandre Julliard | fe08568 | 2000-03-18 21:56:10 +0000 | [diff] [blame] | 75 | }; |
| 76 | |
| 77 | |
| 78 | static void do_help( const char *arg ) |
| 79 | { |
| 80 | OPTIONS_Usage(); |
| 81 | } |
| 82 | |
| 83 | static void do_version( const char *arg ) |
| 84 | { |
| 85 | MESSAGE( "%s\n", WINE_RELEASE_INFO ); |
| 86 | ExitProcess(0); |
| 87 | } |
| 88 | |
Alexandre Julliard | fe08568 | 2000-03-18 21:56:10 +0000 | [diff] [blame] | 89 | static void do_managed( const char *arg ) |
| 90 | { |
| 91 | Options.managed = TRUE; |
| 92 | } |
| 93 | |
Alexandre Julliard | 94613ab | 2000-11-05 04:51:34 +0000 | [diff] [blame] | 94 | static void do_debugmsg( const char *arg ) |
| 95 | { |
Alexandre Julliard | 94613ab | 2000-11-05 04:51:34 +0000 | [diff] [blame] | 96 | static const char * const debug_class_names[__DBCL_COUNT] = { "fixme", "err", "warn", "trace" }; |
| 97 | |
| 98 | char *opt, *options = strdup(arg); |
| 99 | int i; |
Guy L. Albertelli | 8d91b50 | 2001-01-04 19:37:37 +0000 | [diff] [blame] | 100 | /* defined in relay32/relay386.c */ |
| 101 | extern char **debug_relay_includelist; |
| 102 | extern char **debug_relay_excludelist; |
| 103 | /* defined in relay32/snoop.c */ |
| 104 | extern char **debug_snoop_includelist; |
| 105 | extern char **debug_snoop_excludelist; |
Alexandre Julliard | 94613ab | 2000-11-05 04:51:34 +0000 | [diff] [blame] | 106 | |
| 107 | if (!(opt = strtok( options, "," ))) goto error; |
| 108 | do |
| 109 | { |
| 110 | unsigned char set = 0, clear = 0; |
| 111 | char *p = strchr( opt, '+' ); |
| 112 | if (!p) p = strchr( opt, '-' ); |
| 113 | if (!p || !p[1]) goto error; |
| 114 | if (p > opt) |
| 115 | { |
| 116 | for (i = 0; i < __DBCL_COUNT; i++) |
| 117 | { |
| 118 | int len = strlen(debug_class_names[i]); |
| 119 | if (len != (p - opt)) continue; |
| 120 | if (!memcmp( opt, debug_class_names[i], len )) /* found it */ |
| 121 | { |
| 122 | if (*p == '+') set |= 1 << i; |
| 123 | else clear |= 1 << i; |
| 124 | break; |
| 125 | } |
| 126 | } |
| 127 | if (i == __DBCL_COUNT) goto error; /* class name not found */ |
| 128 | } |
| 129 | else |
| 130 | { |
| 131 | if (*p == '+') set = ~0; |
| 132 | else clear = ~0; |
Guy L. Albertelli | 8d91b50 | 2001-01-04 19:37:37 +0000 | [diff] [blame] | 133 | if (!strncasecmp(p+1, "relay=", 6) || |
| 134 | !strncasecmp(p+1, "snoop=", 6)) |
| 135 | { |
| 136 | int i, l; |
| 137 | char *s, *s2, ***output, c; |
| 138 | |
| 139 | if (strchr(p,',')) |
| 140 | l=strchr(p,',')-p; |
| 141 | else |
| 142 | l=strlen(p); |
| 143 | set = ~0; |
| 144 | clear = 0; |
| 145 | output = (*p == '+') ? |
| 146 | ((*(p+1) == 'r') ? |
| 147 | &debug_relay_includelist : |
| 148 | &debug_snoop_includelist) : |
| 149 | ((*(p+1) == 'r') ? |
| 150 | &debug_relay_excludelist : |
| 151 | &debug_snoop_excludelist); |
| 152 | s = p + 7; |
| 153 | /* if there are n ':', there are n+1 modules, and we need |
| 154 | n+2 slots, last one being for the sentinel (NULL) */ |
| 155 | i = 2; |
| 156 | while((s = strchr(s, ':'))) i++, s++; |
| 157 | *output = malloc(sizeof(char **) * i); |
| 158 | i = 0; |
| 159 | s = p + 7; |
| 160 | while((s2 = strchr(s, ':'))) { |
| 161 | c = *s2; |
| 162 | *s2 = '\0'; |
| 163 | *((*output)+i) = _strupr(strdup(s)); |
| 164 | *s2 = c; |
| 165 | s = s2 + 1; |
| 166 | i++; |
| 167 | } |
| 168 | c = *(p + l); |
| 169 | *(p + l) = '\0'; |
| 170 | *((*output)+i) = _strupr(strdup(s)); |
| 171 | *(p + l) = c; |
| 172 | *((*output)+i+1) = NULL; |
| 173 | *(p + 6) = '\0'; |
| 174 | } |
Alexandre Julliard | 94613ab | 2000-11-05 04:51:34 +0000 | [diff] [blame] | 175 | } |
| 176 | p++; |
| 177 | if (!strcmp( p, "all" )) p = ""; /* empty string means all */ |
| 178 | wine_dbg_add_option( p, set, clear ); |
| 179 | opt = strtok( NULL, "," ); |
| 180 | } while(opt); |
| 181 | |
| 182 | free( options ); |
| 183 | return; |
| 184 | |
| 185 | error: |
| 186 | MESSAGE("wine: Syntax: --debugmsg [class]+xxx,... or " |
| 187 | "-debugmsg [class]-xxx,...\n"); |
| 188 | MESSAGE("Example: --debugmsg +all,warn-heap\n" |
| 189 | " turn on all messages except warning heap messages\n"); |
| 190 | MESSAGE("Available message classes:\n"); |
| 191 | for( i = 0; i < __DBCL_COUNT; i++) MESSAGE( "%-9s", debug_class_names[i] ); |
| 192 | MESSAGE("\n\n"); |
| 193 | ExitProcess(1); |
| 194 | } |
| 195 | |
| 196 | |
Alexandre Julliard | eeaae3c | 2000-05-30 17:51:44 +0000 | [diff] [blame] | 197 | static void remove_options( char *argv[], int pos, int count, int inherit ) |
Alexandre Julliard | fe08568 | 2000-03-18 21:56:10 +0000 | [diff] [blame] | 198 | { |
Alexandre Julliard | eeaae3c | 2000-05-30 17:51:44 +0000 | [diff] [blame] | 199 | if (inherit) |
| 200 | { |
| 201 | int i, len = 0; |
| 202 | for (i = 0; i < count; i++) len += strlen(argv[pos+i]) + 1; |
| 203 | if (inherit_str) |
| 204 | { |
Alexandre Julliard | 45fccb8 | 2000-06-07 02:03:54 +0000 | [diff] [blame] | 205 | if (!(inherit_str = realloc( inherit_str, strlen(inherit_str) + 1 + len ))) |
Alexandre Julliard | eeaae3c | 2000-05-30 17:51:44 +0000 | [diff] [blame] | 206 | out_of_memory(); |
| 207 | strcat( inherit_str, " " ); |
| 208 | } |
| 209 | else |
| 210 | { |
| 211 | if (!(inherit_str = malloc( len ))) out_of_memory(); |
| 212 | inherit_str[0] = 0; |
| 213 | } |
| 214 | for (i = 0; i < count; i++) |
| 215 | { |
| 216 | strcat( inherit_str, argv[pos+i] ); |
| 217 | if (i < count-1) strcat( inherit_str, " " ); |
| 218 | } |
| 219 | } |
Alexandre Julliard | fe08568 | 2000-03-18 21:56:10 +0000 | [diff] [blame] | 220 | while ((argv[pos] = argv[pos+count])) pos++; |
Alexandre Julliard | fe08568 | 2000-03-18 21:56:10 +0000 | [diff] [blame] | 221 | } |
| 222 | |
Alexandre Julliard | eeaae3c | 2000-05-30 17:51:44 +0000 | [diff] [blame] | 223 | /* parse options from the argv array and remove all the recognized ones */ |
| 224 | static void parse_options( char *argv[] ) |
Alexandre Julliard | fe08568 | 2000-03-18 21:56:10 +0000 | [diff] [blame] | 225 | { |
Alexandre Julliard | ca43a64 | 2001-01-10 23:56:59 +0000 | [diff] [blame] | 226 | const struct option_descr *opt; |
Alexandre Julliard | fe08568 | 2000-03-18 21:56:10 +0000 | [diff] [blame] | 227 | int i; |
| 228 | |
Alexandre Julliard | eeaae3c | 2000-05-30 17:51:44 +0000 | [diff] [blame] | 229 | for (i = 0; argv[i]; i++) |
Alexandre Julliard | fe08568 | 2000-03-18 21:56:10 +0000 | [diff] [blame] | 230 | { |
Morten Welinder | 87093f5 | 2000-12-18 03:49:49 +0000 | [diff] [blame] | 231 | const char *equalarg = NULL; |
Alexandre Julliard | fe08568 | 2000-03-18 21:56:10 +0000 | [diff] [blame] | 232 | char *p = argv[i]; |
| 233 | if (*p++ != '-') continue; /* not an option */ |
| 234 | if (*p && !p[1]) /* short name */ |
| 235 | { |
| 236 | if (*p == '-') break; /* "--" option */ |
| 237 | for (opt = option_table; opt->longname; opt++) if (opt->shortname == *p) break; |
| 238 | } |
| 239 | else /* long name */ |
| 240 | { |
Morten Welinder | 87093f5 | 2000-12-18 03:49:49 +0000 | [diff] [blame] | 241 | const char *equal = strchr (p, '='); |
Alexandre Julliard | fe08568 | 2000-03-18 21:56:10 +0000 | [diff] [blame] | 242 | if (*p == '-') p++; |
| 243 | /* check for the long name */ |
Morten Welinder | 87093f5 | 2000-12-18 03:49:49 +0000 | [diff] [blame] | 244 | for (opt = option_table; opt->longname; opt++) { |
| 245 | /* Plain --option */ |
Alexandre Julliard | fe08568 | 2000-03-18 21:56:10 +0000 | [diff] [blame] | 246 | if (!strcmp( p, opt->longname )) break; |
Morten Welinder | 87093f5 | 2000-12-18 03:49:49 +0000 | [diff] [blame] | 247 | |
| 248 | /* --option=value */ |
| 249 | if (opt->has_arg && |
| 250 | equal && |
| 251 | strlen (opt->longname) == equal - p && |
| 252 | !strncmp (p, opt->longname, equal - p)) { |
| 253 | equalarg = equal + 1; |
| 254 | break; |
| 255 | } |
| 256 | } |
Alexandre Julliard | fe08568 | 2000-03-18 21:56:10 +0000 | [diff] [blame] | 257 | } |
| 258 | if (!opt->longname) continue; |
| 259 | |
Morten Welinder | 87093f5 | 2000-12-18 03:49:49 +0000 | [diff] [blame] | 260 | if (equalarg) |
| 261 | { |
| 262 | opt->func( equalarg ); |
| 263 | remove_options( argv, i, 1, opt->inherit ); |
| 264 | } |
| 265 | else if (opt->has_arg && argv[i+1]) |
Alexandre Julliard | fe08568 | 2000-03-18 21:56:10 +0000 | [diff] [blame] | 266 | { |
| 267 | opt->func( argv[i+1] ); |
Alexandre Julliard | eeaae3c | 2000-05-30 17:51:44 +0000 | [diff] [blame] | 268 | remove_options( argv, i, 2, opt->inherit ); |
Alexandre Julliard | fe08568 | 2000-03-18 21:56:10 +0000 | [diff] [blame] | 269 | } |
| 270 | else |
| 271 | { |
| 272 | opt->func( "" ); |
Alexandre Julliard | eeaae3c | 2000-05-30 17:51:44 +0000 | [diff] [blame] | 273 | remove_options( argv, i, 1, opt->inherit ); |
Alexandre Julliard | fe08568 | 2000-03-18 21:56:10 +0000 | [diff] [blame] | 274 | } |
| 275 | i--; |
| 276 | } |
Alexandre Julliard | eeaae3c | 2000-05-30 17:51:44 +0000 | [diff] [blame] | 277 | } |
| 278 | |
| 279 | /* inherit options from WINEOPTIONS variable */ |
| 280 | static void inherit_options( char *buffer ) |
| 281 | { |
| 282 | char *argv[256]; |
Alexandre Julliard | 908464d | 2000-11-01 03:11:12 +0000 | [diff] [blame] | 283 | unsigned int n; |
Alexandre Julliard | eeaae3c | 2000-05-30 17:51:44 +0000 | [diff] [blame] | 284 | |
| 285 | char *p = strtok( buffer, " \t" ); |
Alexandre Julliard | 908464d | 2000-11-01 03:11:12 +0000 | [diff] [blame] | 286 | for (n = 0; n < sizeof(argv)/sizeof(argv[0])-1 && p; n++) |
Alexandre Julliard | eeaae3c | 2000-05-30 17:51:44 +0000 | [diff] [blame] | 287 | { |
Alexandre Julliard | 908464d | 2000-11-01 03:11:12 +0000 | [diff] [blame] | 288 | argv[n] = p; |
Alexandre Julliard | eeaae3c | 2000-05-30 17:51:44 +0000 | [diff] [blame] | 289 | p = strtok( NULL, " \t" ); |
| 290 | } |
Alexandre Julliard | 908464d | 2000-11-01 03:11:12 +0000 | [diff] [blame] | 291 | argv[n] = NULL; |
Alexandre Julliard | eeaae3c | 2000-05-30 17:51:44 +0000 | [diff] [blame] | 292 | parse_options( argv ); |
| 293 | if (argv[0]) /* an option remains */ |
| 294 | { |
| 295 | MESSAGE( "Unknown option '%s' in WINEOPTIONS variable\n\n", argv[0] ); |
| 296 | OPTIONS_Usage(); |
| 297 | } |
| 298 | } |
| 299 | |
| 300 | /*********************************************************************** |
| 301 | * OPTIONS_Usage |
| 302 | */ |
| 303 | void OPTIONS_Usage(void) |
| 304 | { |
Alexandre Julliard | ca43a64 | 2001-01-10 23:56:59 +0000 | [diff] [blame] | 305 | const struct option_descr *opt; |
Alexandre Julliard | 26320d1 | 2001-03-23 23:45:45 +0000 | [diff] [blame] | 306 | MESSAGE( "%s\n\n", WINE_RELEASE_INFO ); |
Andreas Mohr | 1f192c1 | 2000-12-15 21:28:47 +0000 | [diff] [blame] | 307 | MESSAGE( "Usage: %s [options] [--] program_name [arguments]\n", argv0 ); |
| 308 | MESSAGE("The -- has to be used if you specify arguments (of the program)\n\n"); |
Alexandre Julliard | eeaae3c | 2000-05-30 17:51:44 +0000 | [diff] [blame] | 309 | MESSAGE( "Options:\n" ); |
| 310 | for (opt = option_table; opt->longname; opt++) MESSAGE( " %s\n", opt->usage ); |
| 311 | ExitProcess(0); |
| 312 | } |
| 313 | |
| 314 | /*********************************************************************** |
| 315 | * OPTIONS_ParseOptions |
| 316 | */ |
| 317 | void OPTIONS_ParseOptions( char *argv[] ) |
| 318 | { |
| 319 | char buffer[1024]; |
| 320 | int i; |
| 321 | |
| 322 | if (GetEnvironmentVariableA( "WINEOPTIONS", buffer, sizeof(buffer) ) && buffer[0]) |
| 323 | inherit_options( buffer ); |
| 324 | |
| 325 | parse_options( argv + 1 ); |
| 326 | |
| 327 | SetEnvironmentVariableA( "WINEOPTIONS", inherit_str ); |
Alexandre Julliard | fe08568 | 2000-03-18 21:56:10 +0000 | [diff] [blame] | 328 | |
| 329 | /* check if any option remains */ |
| 330 | for (i = 1; argv[i]; i++) |
| 331 | { |
| 332 | if (!strcmp( argv[i], "--" )) |
| 333 | { |
Alexandre Julliard | eeaae3c | 2000-05-30 17:51:44 +0000 | [diff] [blame] | 334 | remove_options( argv, i, 1, 0 ); |
Alexandre Julliard | fe08568 | 2000-03-18 21:56:10 +0000 | [diff] [blame] | 335 | break; |
| 336 | } |
| 337 | if (argv[i][0] == '-') |
| 338 | { |
Alexandre Julliard | eeaae3c | 2000-05-30 17:51:44 +0000 | [diff] [blame] | 339 | MESSAGE( "Unknown option '%s'\n\n", argv[i] ); |
Alexandre Julliard | fe08568 | 2000-03-18 21:56:10 +0000 | [diff] [blame] | 340 | OPTIONS_Usage(); |
| 341 | } |
| 342 | } |
Alexandre Julliard | c192ba2 | 2000-05-29 21:25:10 +0000 | [diff] [blame] | 343 | |
| 344 | /* count the resulting arguments */ |
Alexandre Julliard | b1e7028 | 2000-11-09 20:29:42 +0000 | [diff] [blame] | 345 | app_argv = argv; |
| 346 | app_argc = 0; |
| 347 | while (argv[app_argc]) app_argc++; |
Alexandre Julliard | fe08568 | 2000-03-18 21:56:10 +0000 | [diff] [blame] | 348 | } |
Alexandre Julliard | b1e7028 | 2000-11-09 20:29:42 +0000 | [diff] [blame] | 349 | |
| 350 | |
| 351 | /*********************************************************************** |
Patrik Stridvall | 3ca9823 | 2001-06-20 23:03:14 +0000 | [diff] [blame] | 352 | * __wine_get_main_args (NTDLL.@) |
Alexandre Julliard | b1e7028 | 2000-11-09 20:29:42 +0000 | [diff] [blame] | 353 | * |
| 354 | * Return the argc/argv that the application should see. |
| 355 | * Used by the startup code generated in the .spec.c file. |
| 356 | */ |
| 357 | int __wine_get_main_args( char ***argv ) |
| 358 | { |
| 359 | *argv = app_argv; |
| 360 | return app_argc; |
| 361 | } |
| 362 | |
Alexandre Julliard | 909eff9 | 2000-12-15 03:38:11 +0000 | [diff] [blame] | 363 | |
| 364 | /*********************************************************************** |
Patrik Stridvall | 3ca9823 | 2001-06-20 23:03:14 +0000 | [diff] [blame] | 365 | * __wine_get_wmain_args (NTDLL.@) |
Alexandre Julliard | 909eff9 | 2000-12-15 03:38:11 +0000 | [diff] [blame] | 366 | * |
| 367 | * Same as __wine_get_main_args but for Unicode. |
| 368 | */ |
| 369 | int __wine_get_wmain_args( WCHAR ***argv ) |
| 370 | { |
| 371 | if (!app_wargv) |
| 372 | { |
| 373 | int i; |
| 374 | WCHAR *p; |
| 375 | DWORD total = 0; |
| 376 | |
| 377 | for (i = 0; i < app_argc; i++) |
| 378 | total += MultiByteToWideChar( CP_ACP, 0, app_argv[i], -1, NULL, 0 ); |
| 379 | |
| 380 | app_wargv = HeapAlloc( GetProcessHeap(), 0, |
| 381 | total * sizeof(WCHAR) + (app_argc + 1) * sizeof(*app_wargv) ); |
| 382 | p = (WCHAR *)(app_wargv + app_argc + 1); |
| 383 | for (i = 0; i < app_argc; i++) |
| 384 | { |
| 385 | DWORD len = MultiByteToWideChar( CP_ACP, 0, app_argv[i], -1, p, total ); |
| 386 | app_wargv[i] = p; |
| 387 | p += len; |
| 388 | total -= len; |
| 389 | } |
| 390 | app_wargv[app_argc] = NULL; |
| 391 | } |
| 392 | *argv = app_wargv; |
| 393 | return app_argc; |
| 394 | } |