Coverage Report

Created: 2022-03-21 07:20

/src/xpdf-4.03/goo/gfile.cc
Line
Count
Source (jump to first uncovered line)
1
//========================================================================
2
//
3
// gfile.cc
4
//
5
// Miscellaneous file and directory name manipulation.
6
//
7
// Copyright 1996-2003 Glyph & Cog, LLC
8
//
9
//========================================================================
10
11
#include <aconf.h>
12
13
#ifdef _WIN32
14
#  undef WIN32_LEAN_AND_MEAN
15
#  include <windows.h>
16
#  include <time.h>
17
#  include <direct.h>
18
#  include <shobjidl.h>
19
#  include <shlguid.h>
20
#else
21
#  if !defined(ACORN)
22
#    include <sys/types.h>
23
#    include <sys/stat.h>
24
#    include <fcntl.h>
25
#  endif
26
#  include <time.h>
27
#  include <limits.h>
28
#  include <string.h>
29
#  if !defined(VMS) && !defined(ACORN)
30
#    include <pwd.h>
31
#  endif
32
#  if defined(VMS) && (__DECCXX_VER < 50200000)
33
#    include <unixlib.h>
34
#  endif
35
#endif // _WIN32
36
#include "gmem.h"
37
#include "gmempp.h"
38
#include "GString.h"
39
#include "gfile.h"
40
41
// Some systems don't define this, so just make it something reasonably
42
// large.
43
#ifndef PATH_MAX
44
#define PATH_MAX 1024
45
#endif
46
47
//------------------------------------------------------------------------
48
49
108
GString *getHomeDir() {
50
#ifdef VMS
51
  //---------- VMS ----------
52
  return new GString("SYS$LOGIN:");
53
54
#elif defined(__EMX__) || defined(_WIN32)
55
  //---------- OS/2+EMX and Win32 ----------
56
  char *s;
57
  GString *ret;
58
59
  if ((s = getenv("HOME")))
60
    ret = new GString(s);
61
  else
62
    ret = new GString(".");
63
  return ret;
64
65
#elif defined(ACORN)
66
  //---------- RISCOS ----------
67
  return new GString("@");
68
69
#else
70
  //---------- Unix ----------
71
108
  char *s;
72
108
  struct passwd *pw;
73
108
  GString *ret;
74
75
108
  if ((s = getenv("HOME"))) {
76
108
    ret = new GString(s);
77
108
  } else {
78
0
    if ((s = getenv("USER")))
79
0
      pw = getpwnam(s);
80
0
    else
81
0
      pw = getpwuid(getuid());
82
0
    if (pw)
83
0
      ret = new GString(pw->pw_dir);
84
0
    else
85
0
      ret = new GString(".");
86
0
  }
87
108
  return ret;
88
108
#endif
89
108
}
90
91
0
GString *getCurrentDir() {
92
0
  char buf[PATH_MAX+1];
93
94
#if defined(__EMX__)
95
  if (_getcwd2(buf, sizeof(buf)))
96
#elif defined(_WIN32)
97
  if (GetCurrentDirectoryA(sizeof(buf), buf))
98
#elif defined(ACORN)
99
  if (strcpy(buf, "@"))
100
#else
101
0
  if (getcwd(buf, sizeof(buf)))
102
0
#endif
103
0
    return new GString(buf);
104
0
  return new GString();
105
0
}
106
107
2.62k
GString *appendToPath(GString *path, const char *fileName) {
108
#if defined(VMS)
109
  //---------- VMS ----------
110
  //~ this should handle everything necessary for file
111
  //~ requesters, but it's certainly not complete
112
  char *p0, *p1, *p2;
113
  char *q1;
114
115
  p0 = path->getCString();
116
  p1 = p0 + path->getLength() - 1;
117
  if (!strcmp(fileName, "-")) {
118
    if (*p1 == ']') {
119
      for (p2 = p1; p2 > p0 && *p2 != '.' && *p2 != '['; --p2) ;
120
      if (*p2 == '[')
121
  ++p2;
122
      path->del(p2 - p0, p1 - p2);
123
    } else if (*p1 == ':') {
124
      path->append("[-]");
125
    } else {
126
      path->clear();
127
      path->append("[-]");
128
    }
129
  } else if ((q1 = strrchr(fileName, '.')) && !strncmp(q1, ".DIR;", 5)) {
130
    if (*p1 == ']') {
131
      path->insert(p1 - p0, '.');
132
      path->insert(p1 - p0 + 1, fileName, q1 - fileName);
133
    } else if (*p1 == ':') {
134
      path->append('[');
135
      path->append(']');
136
      path->append(fileName, q1 - fileName);
137
    } else {
138
      path->clear();
139
      path->append(fileName, q1 - fileName);
140
    }
141
  } else {
142
    if (*p1 != ']' && *p1 != ':')
143
      path->clear();
144
    path->append(fileName);
145
  }
146
  return path;
147
148
#elif defined(_WIN32)
149
  //---------- Win32 ----------
150
  GString *tmp;
151
  char buf[256];
152
  char *fp;
153
154
  tmp = new GString(path);
155
  tmp->append('/');
156
  tmp->append(fileName);
157
  GetFullPathNameA(tmp->getCString(), sizeof(buf), buf, &fp);
158
  delete tmp;
159
  path->clear();
160
  path->append(buf);
161
  return path;
162
163
#elif defined(ACORN)
164
  //---------- RISCOS ----------
165
  char *p;
166
  int i;
167
168
  path->append(".");
169
  i = path->getLength();
170
  path->append(fileName);
171
  for (p = path->getCString() + i; *p; ++p) {
172
    if (*p == '/') {
173
      *p = '.';
174
    } else if (*p == '.') {
175
      *p = '/';
176
    }
177
  }
178
  return path;
179
180
#elif defined(__EMX__)
181
  //---------- OS/2+EMX ----------
182
  int i;
183
184
  // appending "." does nothing
185
  if (!strcmp(fileName, "."))
186
    return path;
187
188
  // appending ".." goes up one directory
189
  if (!strcmp(fileName, "..")) {
190
    for (i = path->getLength() - 2; i >= 0; --i) {
191
      if (path->getChar(i) == '/' || path->getChar(i) == '\\' ||
192
    path->getChar(i) == ':')
193
  break;
194
    }
195
    if (i <= 0) {
196
      if (path->getChar(0) == '/' || path->getChar(0) == '\\') {
197
  path->del(1, path->getLength() - 1);
198
      } else if (path->getLength() >= 2 && path->getChar(1) == ':') {
199
  path->del(2, path->getLength() - 2);
200
      } else {
201
  path->clear();
202
  path->append("..");
203
      }
204
    } else {
205
      if (path->getChar(i-1) == ':')
206
  ++i;
207
      path->del(i, path->getLength() - i);
208
    }
209
    return path;
210
  }
211
212
  // otherwise, append "/" and new path component
213
  if (path->getLength() > 0 &&
214
      path->getChar(path->getLength() - 1) != '/' &&
215
      path->getChar(path->getLength() - 1) != '\\')
216
    path->append('/');
217
  path->append(fileName);
218
  return path;
219
220
#else
221
  //---------- Unix ----------
222
2.62k
  int i;
223
224
  // appending "." does nothing
225
2.62k
  if (!strcmp(fileName, "."))
226
0
    return path;
227
228
  // appending ".." goes up one directory
229
2.62k
  if (!strcmp(fileName, "..")) {
230
0
    for (i = path->getLength() - 2; i >= 0; --i) {
231
0
      if (path->getChar(i) == '/')
232
0
  break;
233
0
    }
234
0
    if (i <= 0) {
235
0
      if (path->getChar(0) == '/') {
236
0
  path->del(1, path->getLength() - 1);
237
0
      } else {
238
0
  path->clear();
239
0
  path->append("..");
240
0
      }
241
0
    } else {
242
0
      path->del(i, path->getLength() - i);
243
0
    }
244
0
    return path;
245
0
  }
246
247
  // otherwise, append "/" and new path component
248
2.62k
  if (path->getLength() > 0 &&
249
2.62k
      path->getChar(path->getLength() - 1) != '/')
250
2.62k
    path->append('/');
251
2.62k
  path->append(fileName);
252
2.62k
  return path;
253
2.62k
#endif
254
2.62k
}
255
256
0
GString *grabPath(char *fileName) {
257
#ifdef VMS
258
  //---------- VMS ----------
259
  char *p;
260
261
  if ((p = strrchr(fileName, ']')))
262
    return new GString(fileName, p + 1 - fileName);
263
  if ((p = strrchr(fileName, ':')))
264
    return new GString(fileName, p + 1 - fileName);
265
  return new GString();
266
267
#elif defined(__EMX__) || defined(_WIN32)
268
  //---------- OS/2+EMX and Win32 ----------
269
  char *p;
270
271
  if ((p = strrchr(fileName, '/')))
272
    return new GString(fileName, (int)(p - fileName));
273
  if ((p = strrchr(fileName, '\\')))
274
    return new GString(fileName, (int)(p - fileName));
275
  if ((p = strrchr(fileName, ':')))
276
    return new GString(fileName, (int)(p + 1 - fileName));
277
  return new GString();
278
279
#elif defined(ACORN)
280
  //---------- RISCOS ----------
281
  char *p;
282
283
  if ((p = strrchr(fileName, '.')))
284
    return new GString(fileName, p - fileName);
285
  return new GString();
286
287
#else
288
  //---------- Unix ----------
289
0
  char *p;
290
291
0
  if ((p = strrchr(fileName, '/')))
292
0
    return new GString(fileName, (int)(p - fileName));
293
0
  return new GString();
294
0
#endif
295
0
}
296
297
0
GBool isAbsolutePath(char *path) {
298
#ifdef VMS
299
  //---------- VMS ----------
300
  return strchr(path, ':') ||
301
   (path[0] == '[' && path[1] != '.' && path[1] != '-');
302
303
#elif defined(__EMX__) || defined(_WIN32)
304
  //---------- OS/2+EMX and Win32 ----------
305
  return path[0] == '/' || path[0] == '\\' || path[1] == ':';
306
307
#elif defined(ACORN)
308
  //---------- RISCOS ----------
309
  return path[0] == '$';
310
311
#else
312
  //---------- Unix ----------
313
0
  return path[0] == '/';
314
0
#endif
315
0
}
316
317
0
GString *makePathAbsolute(GString *path) {
318
#ifdef VMS
319
  //---------- VMS ----------
320
  char buf[PATH_MAX+1];
321
322
  if (!isAbsolutePath(path->getCString())) {
323
    if (getcwd(buf, sizeof(buf))) {
324
      path->insert(0, buf);
325
    }
326
  }
327
  return path;
328
329
#elif defined(_WIN32)
330
  //---------- Win32 ----------
331
  char buf[_MAX_PATH];
332
  char *fp;
333
334
  buf[0] = '\0';
335
  if (!GetFullPathNameA(path->getCString(), _MAX_PATH, buf, &fp)) {
336
    path->clear();
337
    return path;
338
  }
339
  path->clear();
340
  path->append(buf);
341
  return path;
342
343
#elif defined(ACORN)
344
  //---------- RISCOS ----------
345
  path->insert(0, '@');
346
  return path;
347
348
#else
349
  //---------- Unix and OS/2+EMX ----------
350
0
  struct passwd *pw;
351
0
  char buf[PATH_MAX+1];
352
0
  GString *s;
353
0
  char *p1, *p2;
354
0
  int n;
355
356
0
  if (path->getChar(0) == '~') {
357
0
    if (path->getChar(1) == '/' ||
358
#ifdef __EMX__
359
  path->getChar(1) == '\\' ||
360
#endif
361
0
  path->getLength() == 1) {
362
0
      path->del(0, 1);
363
0
      s = getHomeDir();
364
0
      path->insert(0, s);
365
0
      delete s;
366
0
    } else {
367
0
      p1 = path->getCString() + 1;
368
#ifdef __EMX__
369
      for (p2 = p1; *p2 && *p2 != '/' && *p2 != '\\'; ++p2) ;
370
#else
371
0
      for (p2 = p1; *p2 && *p2 != '/'; ++p2) ;
372
0
#endif
373
0
      if ((n = (int)(p2 - p1)) > PATH_MAX)
374
0
  n = PATH_MAX;
375
0
      strncpy(buf, p1, n);
376
0
      buf[n] = '\0';
377
0
      if ((pw = getpwnam(buf))) {
378
0
  path->del(0, (int)(p2 - p1 + 1));
379
0
  path->insert(0, pw->pw_dir);
380
0
      }
381
0
    }
382
0
  } else if (!isAbsolutePath(path->getCString())) {
383
0
    if (getcwd(buf, sizeof(buf))) {
384
0
#ifndef __EMX__
385
0
      path->insert(0, '/');
386
0
#endif
387
0
      path->insert(0, buf);
388
0
    }
389
0
  }
390
0
  return path;
391
0
#endif
392
0
}
393
394
0
time_t getModTime(char *fileName) {
395
#ifdef _WIN32
396
  //~ should implement this, but it's (currently) only used in xpdf
397
  return 0;
398
#else
399
0
  struct stat statBuf;
400
401
0
  if (stat(fileName, &statBuf)) {
402
0
    return 0;
403
0
  }
404
0
  return statBuf.st_mtime;
405
0
#endif
406
0
}
407
408
GBool openTempFile(GString **name, FILE **f,
409
0
       const char *mode, const char *ext) {
410
#if defined(_WIN32)
411
  //---------- Win32 ----------
412
  char tempPath[MAX_PATH + 1];
413
  GString *s, *s2;
414
  FILE *f2;
415
  DWORD n;
416
  int t, i;
417
418
  // this has the standard race condition problem, but I haven't found
419
  // a better way to generate temp file names with extensions on
420
  // Windows
421
  n = GetTempPathA(sizeof(tempPath), tempPath);
422
  if (n > 0 && n <= sizeof(tempPath)) {
423
    s = new GString(tempPath);
424
    if (tempPath[n-1] != '\\') {
425
      s->append('\\');
426
    }
427
  } else {
428
    s = new GString(".\\");
429
  }
430
  s->appendf("xpdf_{0:d}_{1:d}_",
431
       (int)GetCurrentProcessId(), (int)GetCurrentThreadId());
432
  t = (int)time(NULL);
433
  for (i = 0; i < 1000; ++i) {
434
    s2 = GString::format("{0:t}{1:d}", s, t + i);
435
    if (ext) {
436
      s2->append(ext);
437
    }
438
    if (!(f2 = fopen(s2->getCString(), "r"))) {
439
      if (!(f2 = fopen(s2->getCString(), mode))) {
440
  delete s2;
441
  delete s;
442
  return gFalse;
443
      }
444
      *name = s2;
445
      *f = f2;
446
      delete s;
447
      return gTrue;
448
    }
449
    fclose(f2);
450
    delete s2;
451
  }
452
  delete s;
453
  return gFalse;
454
#elif defined(VMS) || defined(__EMX__) || defined(ACORN)
455
  //---------- non-Unix ----------
456
  char *s;
457
458
  // There is a security hole here: an attacker can create a symlink
459
  // with this file name after the tmpnam call and before the fopen
460
  // call.  I will happily accept fixes to this function for non-Unix
461
  // OSs.
462
  if (!(s = tmpnam(NULL))) {
463
    return gFalse;
464
  }
465
  *name = new GString(s);
466
  if (ext) {
467
    (*name)->append(ext);
468
  }
469
  if (!(*f = fopen((*name)->getCString(), mode))) {
470
    delete (*name);
471
    *name = NULL;
472
    return gFalse;
473
  }
474
  return gTrue;
475
#else
476
  //---------- Unix ----------
477
0
  char *s;
478
0
  int fd;
479
480
0
  if (ext) {
481
0
#if HAVE_MKSTEMPS
482
0
    if ((s = getenv("TMPDIR"))) {
483
0
      *name = new GString(s);
484
0
    } else {
485
0
      *name = new GString("/tmp");
486
0
    }
487
0
    (*name)->append("/XXXXXX")->append(ext);
488
0
    fd = mkstemps((*name)->getCString(), (int)strlen(ext));
489
#else
490
    if (!(s = tmpnam(NULL))) {
491
      return gFalse;
492
    }
493
    *name = new GString(s);
494
    (*name)->append(ext);
495
    fd = open((*name)->getCString(), O_WRONLY | O_CREAT | O_EXCL, 0600);
496
#endif
497
0
  } else {
498
0
#if HAVE_MKSTEMP
499
0
    if ((s = getenv("TMPDIR"))) {
500
0
      *name = new GString(s);
501
0
    } else {
502
0
      *name = new GString("/tmp");
503
0
    }
504
0
    (*name)->append("/XXXXXX");
505
0
    fd = mkstemp((*name)->getCString());
506
#else // HAVE_MKSTEMP
507
    if (!(s = tmpnam(NULL))) {
508
      return gFalse;
509
    }
510
    *name = new GString(s);
511
    fd = open((*name)->getCString(), O_WRONLY | O_CREAT | O_EXCL, 0600);
512
#endif // HAVE_MKSTEMP
513
0
  }
514
0
  if (fd < 0 || !(*f = fdopen(fd, mode))) {
515
0
    delete *name;
516
0
    *name = NULL;
517
0
    return gFalse;
518
0
  }
519
0
  return gTrue;
520
0
#endif
521
0
}
522
523
0
GBool createDir(char *path, int mode) {
524
#ifdef _WIN32
525
  return !mkdir(path);
526
#else
527
0
  return !mkdir(path, mode);
528
0
#endif
529
0
}
530
531
0
GBool executeCommand(char *cmd) {
532
#ifdef VMS
533
  return system(cmd) ? gTrue : gFalse;
534
#else
535
0
  return system(cmd) ? gFalse : gTrue;
536
0
#endif
537
0
}
538
539
#ifdef _WIN32
540
GString *fileNameToUTF8(char *path) {
541
  GString *s;
542
  char *p;
543
544
  s = new GString();
545
  for (p = path; *p; ++p) {
546
    if (*p & 0x80) {
547
      s->append((char)(0xc0 | ((*p >> 6) & 0x03)));
548
      s->append((char)(0x80 | (*p & 0x3f)));
549
    } else {
550
      s->append(*p);
551
    }
552
  }
553
  return s;
554
}
555
556
GString *fileNameToUTF8(wchar_t *path) {
557
  GString *s;
558
  wchar_t *p;
559
560
  s = new GString();
561
  for (p = path; *p; ++p) {
562
    if (*p < 0x80) {
563
      s->append((char)*p);
564
    } else if (*p < 0x800) {
565
      s->append((char)(0xc0 | ((*p >> 6) & 0x1f)));
566
      s->append((char)(0x80 | (*p & 0x3f)));
567
    } else {
568
      s->append((char)(0xe0 | ((*p >> 12) & 0x0f)));
569
      s->append((char)(0x80 | ((*p >> 6) & 0x3f)));
570
      s->append((char)(0x80 | (*p & 0x3f)));
571
    }
572
  }
573
  return s;
574
}
575
576
wchar_t *fileNameToUCS2(const char *path, wchar_t *out, size_t outSize) {
577
  const char *p;
578
  size_t i;
579
580
  for (p = path, i = 0; *p && i < outSize - 1; ++i) {
581
    if ((p[0] & 0xe0) == 0xc0 &&
582
  p[1] && (p[1] & 0xc0) == 0x80) {
583
      out[i] = (wchar_t)(((p[0] & 0x1f) << 6) |
584
        (p[1] & 0x3f));
585
      p += 2;
586
    } else if ((p[0] & 0xf0) == 0xe0 &&
587
         (p[1] & 0xc0) == 0x80 &&
588
         (p[2] & 0xc0) == 0x80) {
589
      out[i] = (wchar_t)(((p[0] & 0x0f) << 12) |
590
       ((p[1] & 0x3f) << 6) |
591
        (p[2] & 0x3f));
592
      p += 3;
593
    } else {
594
      out[i] = (wchar_t)(p[0] & 0xff);
595
      p += 1;
596
    }
597
  }
598
  out[i] = (wchar_t)0;
599
  return out;
600
}
601
#endif
602
603
0
FILE *openFile(const char *path, const char *mode) {
604
#if defined(_WIN32)
605
  wchar_t wPath[_MAX_PATH + 1];
606
  wchar_t wMode[8];
607
  int i;
608
609
  fileNameToUCS2(path, wPath, sizeof(wPath) / sizeof(wchar_t));
610
  for (i = 0; mode[i] && i < sizeof(wMode)/sizeof(wchar_t) - 1; ++i) {
611
    wMode[i] = (wchar_t)(mode[i] & 0xff);
612
  }
613
  wMode[i] = (wchar_t)0;
614
  readWindowsShortcut(wPath, _MAX_PATH + 1);
615
  return _wfopen(wPath, wMode);
616
#elif defined(VMS)
617
  return fopen(path, mode, "ctx=stm");
618
#else
619
0
  return fopen(path, mode);
620
0
#endif
621
0
}
622
623
#ifdef _WIN32
624
void readWindowsShortcut(wchar_t *wPath, size_t wPathSize) {
625
  size_t n = wcslen(wPath);
626
  if (n < 4 || wcscmp(wPath + n - 4, L".lnk")) {
627
    return;
628
  }
629
  IShellLinkW *shellLink;
630
  HRESULT hres;
631
  hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
632
        IID_IShellLinkW, (LPVOID *)&shellLink);
633
  bool needCoUninit = false;
634
  if (hres == CO_E_NOTINITIALIZED) {
635
    CoInitialize(NULL);
636
    needCoUninit = true;
637
    hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
638
          IID_IShellLinkW, (LPVOID *)&shellLink);
639
  }
640
  if (FAILED(hres)) {
641
    return;
642
  }
643
  IPersistFile *persistFile;
644
  hres = shellLink->QueryInterface(IID_IPersistFile, (LPVOID *)&persistFile);
645
  if (FAILED(hres)) {
646
    return;
647
  }
648
  hres = persistFile->Load(wPath, STGM_READ);
649
  if (FAILED(hres)) {
650
    fprintf(stderr, "IPersistFile.Load failed: 0x%08x\n", hres);
651
    exit(1);
652
  }
653
  wchar_t target[_MAX_PATH + 1];
654
  hres = shellLink->GetPath(target, _MAX_PATH + 1, NULL, 0);
655
  if (FAILED(hres)) {
656
    return;
657
  }
658
  shellLink->Release();
659
  if (needCoUninit) {
660
    CoUninitialize();
661
  }
662
  if (wcslen(target) > wPathSize - 1) {
663
    return;
664
  }
665
  wcscpy(wPath, target);
666
}
667
#endif
668
669
0
int makeDir(const char *path, int mode) {
670
#ifdef _WIN32
671
  wchar_t wPath[_MAX_PATH + 1];
672
  return _wmkdir(fileNameToUCS2(path, wPath, sizeof(wPath) / sizeof(wchar_t)));
673
#else
674
0
  return mkdir(path, (mode_t)mode);
675
0
#endif
676
0
}
677
678
0
char *getLine(char *buf, int size, FILE *f) {
679
0
  int c, i;
680
681
0
  i = 0;
682
0
  while (i < size - 1) {
683
0
    if ((c = fgetc(f)) == EOF) {
684
0
      break;
685
0
    }
686
0
    buf[i++] = (char)c;
687
0
    if (c == '\x0a') {
688
0
      break;
689
0
    }
690
0
    if (c == '\x0d') {
691
0
      c = fgetc(f);
692
0
      if (c == '\x0a' && i < size - 1) {
693
0
  buf[i++] = (char)c;
694
0
      } else if (c != EOF) {
695
0
  ungetc(c, f);
696
0
      }
697
0
      break;
698
0
    }
699
0
  }
700
0
  buf[i] = '\0';
701
0
  if (i == 0) {
702
0
    return NULL;
703
0
  }
704
0
  return buf;
705
0
}
706
707
0
int gfseek(FILE *f, GFileOffset offset, int whence) {
708
0
#if HAVE_FSEEKO
709
0
  return fseeko(f, offset, whence);
710
#elif HAVE_FSEEK64
711
  return fseek64(f, offset, whence);
712
#elif HAVE_FSEEKI64
713
  return _fseeki64(f, offset, whence);
714
#else
715
  return fseek(f, offset, whence);
716
#endif
717
0
}
718
719
0
GFileOffset gftell(FILE *f) {
720
0
#if HAVE_FSEEKO
721
0
  return ftello(f);
722
#elif HAVE_FSEEK64
723
  return ftell64(f);
724
#elif HAVE_FSEEKI64
725
  return _ftelli64(f);
726
#else
727
  return ftell(f);
728
#endif
729
0
}
730
731
0
void fixCommandLine(int *argc, char **argv[]) {
732
#ifdef _WIN32
733
  int argcw;
734
  wchar_t **argvw;
735
  GString *arg;
736
  int i;
737
738
  argvw = CommandLineToArgvW(GetCommandLineW(), &argcw);
739
  if (!argvw || argcw < 0) {
740
    return;
741
  }
742
743
  *argc = argcw;
744
745
  *argv = (char **)gmallocn(argcw + 1, sizeof(char *));
746
  for (i = 0; i < argcw; ++i) {
747
    arg = fileNameToUTF8(argvw[i]);
748
    (*argv)[i] = copyString(arg->getCString());
749
    delete arg;
750
  }
751
  (*argv)[argcw] = NULL;
752
753
  LocalFree(argvw);
754
#endif
755
0
}