SystemTools.cxx 122 KB
Newer Older
1
2
3
/*============================================================================
  KWSys - Kitware System Library
  Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
4

5
6
  Distributed under the OSI-approved BSD License (the "License");
  see accompanying file Copyright.txt for details.
7

8
9
10
11
  This software is distributed WITHOUT ANY WARRANTY; without even the
  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  See the License for more information.
============================================================================*/
12
13
14
15
16
17
18

#ifdef __osf__
#  define _OSF_SOURCE
#  define _POSIX_C_SOURCE 199506L
#  define _XOPEN_SOURCE_EXTENDED
#endif

19
#include "kwsysPrivate.h"
20
#include KWSYS_HEADER(RegularExpression.hxx)
21
#include KWSYS_HEADER(SystemTools.hxx)
22
#include KWSYS_HEADER(Directory.hxx)
23
24
#include KWSYS_HEADER(FStream.hxx)
#include KWSYS_HEADER(Encoding.hxx)
25

26
27
#include KWSYS_HEADER(ios/iostream)
#include KWSYS_HEADER(ios/fstream)
28
#include KWSYS_HEADER(ios/sstream)
29

30
31
#include KWSYS_HEADER(stl/set)

32
33
34
35
36
// Work-around CMake dependency scanning limitation.  This must
// duplicate the above list of headers.
#if 0
# include "SystemTools.hxx.in"
# include "Directory.hxx.in"
37
38
# include "FStream.hxx.in"
# include "Encoding.hxx.in"
39
40
41
42
43
# include "kwsys_ios_iostream.h.in"
# include "kwsys_ios_fstream.h.in"
# include "kwsys_ios_sstream.h.in"
#endif

44
45
46
47
#ifdef _MSC_VER
# pragma warning (disable: 4786)
#endif

48
49
50
#if defined(__sgi) && !defined(__GNUC__)
# pragma set woff 1375 /* base class destructor not virtual */
#endif
51

52
53
#include <ctype.h>
#include <errno.h>
54
55
#ifdef __QNX__
# include <malloc.h> /* for malloc/free on QNX */
56
#endif
57
58
59
60
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
61
62
63
64
#include <time.h>

// support for realpath call
#ifndef _WIN32
65
#include <sys/time.h>
66
#include <utime.h>
67
68
#include <limits.h>
#include <sys/wait.h>
69
70
#include <sys/ioctl.h>
#include <unistd.h>
71
#include <pwd.h>
72
73
#ifndef __VMS
#include <sys/param.h>
Andy Cedilnik's avatar
Andy Cedilnik committed
74
#include <termios.h>
75
#endif
76
#include <signal.h>    /* sigprocmask */
77
78
#endif

79
80
// Windows API.
#if defined(_WIN32)
81
# include <windows.h>
82
83
84
# ifndef INVALID_FILE_ATTRIBUTES
#  define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
# endif
85
86
87
#elif defined (__CYGWIN__)
# include <windows.h>
# undef _WIN32
88
89
#endif

90
91
92
93
#if !KWSYS_CXX_HAS_ENVIRON_IN_STDLIB_H
extern char **environ;
#endif

94
95
96
97
#ifdef __CYGWIN__
extern "C" void cygwin_conv_to_win32_path(const char *path, char *win32_path);
#endif

Alexander Neundorf's avatar
   
Alexander Neundorf committed
98
// getpwnam doesn't exist on Windows and Cray Xt3/Catamount
Alexander Neundorf's avatar
   
Alexander Neundorf committed
99
// same for TIOCGWINSZ
Alexander Neundorf's avatar
   
Alexander Neundorf committed
100
101
#if defined(_WIN32) || defined (__LIBCATAMOUNT__)
# undef HAVE_GETPWNAM
Alexander Neundorf's avatar
   
Alexander Neundorf committed
102
# undef HAVE_TTY_INFO
Alexander Neundorf's avatar
   
Alexander Neundorf committed
103
104
#else
# define HAVE_GETPWNAM 1
Alexander Neundorf's avatar
   
Alexander Neundorf committed
105
# define HAVE_TTY_INFO 1
Alexander Neundorf's avatar
   
Alexander Neundorf committed
106
107
#endif

108
#define VTK_URL_PROTOCOL_REGEX "([a-zA-Z0-9]*)://(.*)"
109
#define VTK_URL_REGEX "([a-zA-Z0-9]*)://(([A-Za-z0-9]+)(:([^:@]+))?@)?([^:@/]+)(:([0-9]+))?/(.+)?"
110

111
112
113
114
115
#ifdef _MSC_VER
#include <sys/utime.h>
#else
#include <utime.h>
#endif
Alexander Neundorf's avatar
   
Alexander Neundorf committed
116

117

118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
// This is a hack to prevent warnings about these functions being
// declared but not referenced.
#if defined(__sgi) && !defined(__GNUC__)
# include <sys/termios.h>
namespace KWSYS_NAMESPACE
{
class SystemToolsHack
{
public:
  enum
  {
    Ref1 = sizeof(cfgetospeed(0)),
    Ref2 = sizeof(cfgetispeed(0)),
    Ref3 = sizeof(tcgetattr(0, 0)),
    Ref4 = sizeof(tcsetattr(0, 0, 0)),
    Ref5 = sizeof(cfsetospeed(0,0)),
    Ref6 = sizeof(cfsetispeed(0,0))
  };
};
}
#endif
139

140
#if defined(_WIN32) && (defined(_MSC_VER) || defined(__WATCOMC__) ||defined(__BORLANDC__) || defined(__MINGW32__))
141
#include <io.h>
142
143
#include <direct.h>
#define _unlink unlink
144
#endif
145
146
147
148
149
150
151
152
153

/* The maximum length of a file name.  */
#if defined(PATH_MAX)
# define KWSYS_SYSTEMTOOLS_MAXPATH PATH_MAX
#elif defined(MAXPATHLEN)
# define KWSYS_SYSTEMTOOLS_MAXPATH MAXPATHLEN
#else
# define KWSYS_SYSTEMTOOLS_MAXPATH 16384
#endif
154
155
156
157
158
159
160
#if defined(__WATCOMC__)
#include <direct.h>
#define _mkdir mkdir
#define _rmdir rmdir
#define _getcwd getcwd
#define _chdir chdir
#endif
161

162
#if defined(__BEOS__) && !defined(__ZETA__)
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
#include <be/kernel/OS.h>
#include <be/storage/Path.h>

// BeOS 5 doesn't have usleep(), but it has snooze(), which is identical.
static inline void usleep(unsigned int msec)
{
  ::snooze(msec);
}

// BeOS 5 also doesn't have realpath(), but its C++ API offers something close.
static inline char *realpath(const char *path, char *resolved_path)
{
  const size_t maxlen = KWSYS_SYSTEMTOOLS_MAXPATH;
  snprintf(resolved_path, maxlen, "%s", path);
  BPath normalized(resolved_path, NULL, true);
  const char *resolved = normalized.Path();
179
  if (resolved != NULL)   // NULL == No such file.
180
    {
181
    if (snprintf(resolved_path, maxlen, "%s", resolved) < maxlen)
182
183
184
185
186
187
188
189
      {
      return resolved_path;
      }
    }
  return NULL;   // something went wrong.
}
#endif

190
#if defined(_WIN32) && (defined(_MSC_VER) || defined(__WATCOMC__) || defined(__BORLANDC__) || defined(__MINGW32__))
191
192
193

#include <wctype.h>

194
195
inline int Mkdir(const char* dir)
{
196
  return _wmkdir(KWSYS_NAMESPACE::Encoding::ToWide(dir).c_str());
197
}
198
199
inline int Rmdir(const char* dir)
{
200
  return _wrmdir(KWSYS_NAMESPACE::Encoding::ToWide(dir).c_str());
201
}
202
203
inline const char* Getcwd(char* buf, unsigned int len)
{
204
205
  std::vector<wchar_t> w_buf(len);
  if(const wchar_t* ret = _wgetcwd(&w_buf[0], len))
206
    {
207
    // make sure the drive letter is capital
208
    if(wcslen(&w_buf[0]) > 1 && w_buf[1] == L':')
209
      {
210
      w_buf[0] = towupper(w_buf[0]);
211
      }
212
213
214
    std::string tmp = KWSYS_NAMESPACE::Encoding::ToNarrow(&w_buf[0]);
    strcpy(buf, tmp.c_str());
    return buf;
215
    }
216
  return 0;
217
218
219
220
221
222
}
inline int Chdir(const char* dir)
{
  #if defined(__BORLANDC__)
  return chdir(dir);
  #else
223
  return _wchdir(KWSYS_NAMESPACE::Encoding::ToWide(dir).c_str());
224
225
  #endif
}
226
inline void Realpath(const char *path, kwsys_stl::string & resolved_path)
227
{
228
229
230
231
232
  kwsys_stl::wstring tmp = KWSYS_NAMESPACE::Encoding::ToWide(path);
  wchar_t *ptemp;
  wchar_t fullpath[MAX_PATH];
  if( GetFullPathNameW(tmp.c_str(), sizeof(fullpath)/sizeof(fullpath[0]),
                       fullpath, &ptemp) )
233
    {
234
    resolved_path = KWSYS_NAMESPACE::Encoding::ToNarrow(fullpath);
235
    KWSYS_NAMESPACE::SystemTools::ConvertToUnixSlashes(resolved_path);
236
    }
237
238
239
240
  else
    {
    resolved_path = path;
    }
241
}
242
243
244
245
246
247
248
249
#else
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
inline int Mkdir(const char* dir)
{
  return mkdir(dir, 00777);
}
250
251
252
253
inline int Rmdir(const char* dir)
{
  return rmdir(dir);
}
254
255
inline const char* Getcwd(char* buf, unsigned int len)
{
256
  return getcwd(buf, len);
257
}
258

259
260
261
262
inline int Chdir(const char* dir)
{
  return chdir(dir);
}
263
inline void Realpath(const char *path, kwsys_stl::string & resolved_path)
264
{
265
  char resolved_name[KWSYS_SYSTEMTOOLS_MAXPATH];
266

267
268
269
270
271
272
273
274
275
276
  char *ret = realpath(path, resolved_name);
  if(ret)
    {
    resolved_path = ret;
    }
  else
    {
    // if path resolution fails, return what was passed in
    resolved_path = path;
    }
277
}
278
279
#endif

280
281
282
283
284
285
286
287
288
289
290
291
#if !defined(_WIN32) && defined(__COMO__)
// Hack for como strict mode to avoid defining _SVID_SOURCE or _BSD_SOURCE.
extern "C"
{
extern FILE *popen (__const char *__command, __const char *__modes) __THROW;
extern int pclose (FILE *__stream) __THROW;
extern char *realpath (__const char *__restrict __name,
                       char *__restrict __resolved) __THROW;
extern char *strdup (__const char *__s) __THROW;
extern int putenv (char *__string) __THROW;
}
#endif
292
293
294
295

namespace KWSYS_NAMESPACE
{

296
297
298
299
300
301
302
303
304
305
306
double SystemTools::GetTime(void)
{
#if defined(_WIN32) && !defined(__CYGWIN__)
  FILETIME ft;
  GetSystemTimeAsFileTime(&ft);
  return (429.4967296*ft.dwHighDateTime
          + 0.0000001*ft.dwLowDateTime
          - 11644473600.0);
#else
  struct timeval t;
  gettimeofday(&t, 0);
307
  return 1.0*double(t.tv_sec) + 0.000001*double(t.tv_usec);
308
309
310
#endif
}

311
class SystemToolsTranslationMap :
312
313
314
315
    public kwsys_stl::map<kwsys_stl::string,kwsys_stl::string>
{
};

316
// adds the elements of the env variable path to the arg passed in
317
void SystemTools::GetPath(kwsys_stl::vector<kwsys_stl::string>& path, const char* env)
318
319
320
321
322
323
{
#if defined(_WIN32) && !defined(__CYGWIN__)
  const char* pathSep = ";";
#else
  const char* pathSep = ":";
#endif
324
325
326
327
  if(!env)
    {
    env = "PATH";
    }
328
329
330
331
332
333
334
  const char* cpathEnv = SystemTools::GetEnv(env);
  if ( !cpathEnv )
    {
    return;
    }

  kwsys_stl::string pathEnv = cpathEnv;
335
336

  // A hack to make the below algorithm work.
337
  if(!pathEnv.empty() && pathEnv[pathEnv.length()-1] != pathSep[0])
338
339
340
    {
    pathEnv += pathSep;
    }
341
  kwsys_stl::string::size_type start =0;
342
343
344
  bool done = false;
  while(!done)
    {
345
346
    kwsys_stl::string::size_type endpos = pathEnv.find(pathSep, start);
    if(endpos != kwsys_stl::string::npos)
347
      {
348
      path.push_back(pathEnv.substr(start, endpos-start));
349
350
351
352
353
354
355
      start = endpos+1;
      }
    else
      {
      done = true;
      }
    }
356
  for(kwsys_stl::vector<kwsys_stl::string>::iterator i = path.begin();
357
358
359
360
361
362
      i != path.end(); ++i)
    {
    SystemTools::ConvertToUnixSlashes(*i);
    }
}

Brad King's avatar
Brad King committed
363
364
365
366
367
const char* SystemTools::GetEnv(const char* key)
{
  return getenv(key);
}

368
bool SystemTools::GetEnv(const char* key, kwsys_stl::string& result)
Brad King's avatar
Brad King committed
369
370
371
372
373
374
375
376
377
378
379
380
{
  const char* v = getenv(key);
  if(v)
    {
    result = v;
    return true;
    }
  else
    {
    return false;
    }
}
381

382
383
384
385
386
387
//----------------------------------------------------------------------------

#if defined(__CYGWIN__) || defined(__GLIBC__)
# define KWSYS_PUTENV_NAME  /* putenv("A")  removes A.  */
#elif defined(_WIN32)
# define KWSYS_PUTENV_EMPTY /* putenv("A=") removes A. */
388
389
#endif

390
391
392
393
#if KWSYS_CXX_HAS_UNSETENV
/* unsetenv("A") removes A from the environment.
   On older platforms it returns void instead of int.  */
static int kwsysUnPutEnv(const char* env)
Bill Hoffman's avatar
Bill Hoffman committed
394
{
395
396
397
398
399
400
401
402
403
404
405
  if(const char* eq = strchr(env, '='))
    {
    std::string name(env, eq-env);
    unsetenv(name.c_str());
    }
  else
    {
    unsetenv(env);
    }
  return 0;
}
Bill Hoffman's avatar
Bill Hoffman committed
406

407
408
409
#elif defined(KWSYS_PUTENV_EMPTY) || defined(KWSYS_PUTENV_NAME)
/* putenv("A=") or putenv("A") removes A from the environment.  */
static int kwsysUnPutEnv(const char* env)
Bill Hoffman's avatar
Bill Hoffman committed
410
{
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
  int err = 0;
  const char* eq = strchr(env, '=');
  size_t const len = eq? (size_t)(eq-env) : strlen(env);
# ifdef KWSYS_PUTENV_EMPTY
  size_t const sz = len + 2;
# else
  size_t const sz = len + 1;
# endif
  char local_buf[256];
  char* buf = sz > sizeof(local_buf) ? (char*)malloc(sz) : local_buf;
  if(!buf)
    {
    return -1;
    }
  strncpy(buf, env, len);
# ifdef KWSYS_PUTENV_EMPTY
  buf[len] = '=';
  buf[len+1] = 0;
  if(putenv(buf) < 0)
Bill Hoffman's avatar
Bill Hoffman committed
430
    {
431
    err = errno;
Bill Hoffman's avatar
Bill Hoffman committed
432
    }
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
# else
  buf[len] = 0;
  if(putenv(buf) < 0 && errno != EINVAL)
    {
    err = errno;
    }
# endif
  if(buf != local_buf)
    {
    free(buf);
    }
  if(err)
    {
    errno = err;
    return -1;
    }
  return 0;
}

#else
/* Manipulate the "environ" global directly.  */
static int kwsysUnPutEnv(const char* env)
{
  const char* eq = strchr(env, '=');
  size_t const len = eq? (size_t)(eq-env) : strlen(env);
  int in = 0;
  int out = 0;
  while(environ[in])
    {
    if(strlen(environ[in]) > len &&
       environ[in][len] == '=' &&
       strncmp(env, environ[in], len) == 0)
      {
      ++in;
      }
    else
      {
      environ[out++] = environ[in++];
      }
    }
  while(out < in)
    {
    environ[out++] = 0;
    }
  return 0;
}
479
#endif
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497

//----------------------------------------------------------------------------

#if KWSYS_CXX_HAS_SETENV

/* setenv("A", "B", 1) will set A=B in the environment and makes its
   own copies of the strings.  */
bool SystemTools::PutEnv(const char* env)
{
  if(const char* eq = strchr(env, '='))
    {
    std::string name(env, eq-env);
    return setenv(name.c_str(), eq+1, 1) == 0;
    }
  else
    {
    return kwsysUnPutEnv(env) == 0;
    }
Bill Hoffman's avatar
Bill Hoffman committed
498
}
499
500

bool SystemTools::UnPutEnv(const char* env)
501
{
502
  return kwsysUnPutEnv(env) == 0;
Bill Hoffman's avatar
Bill Hoffman committed
503
504
}

505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
#else

/* putenv("A=B") will set A=B in the environment.  Most putenv implementations
   put their argument directly in the environment.  They never free the memory
   on program exit.  Keep an active set of pointers to memory we allocate and
   pass to putenv, one per environment key.  At program exit remove any
   environment values that may still reference memory we allocated.  Then free
   the memory.  This will not affect any environment values we never set.  */

# ifdef __INTEL_COMPILER
#  pragma warning disable 444 /* base has non-virtual destructor */
# endif

/* Order by environment key only (VAR from VAR=VALUE).  */
struct kwsysEnvCompare
{
  bool operator() (const char* l, const char* r) const
    {
    const char* leq = strchr(l, '=');
    const char* req = strchr(r, '=');
    size_t llen = leq? (leq-l) : strlen(l);
    size_t rlen = req? (req-r) : strlen(r);
    if(llen == rlen)
      {
      return strncmp(l,r,llen) < 0;
      }
    else
      {
      return strcmp(l,r) < 0;
      }
    }
};

class kwsysEnv: public kwsys_stl::set<const char*, kwsysEnvCompare>
{
  class Free
  {
    const char* Env;
  public:
    Free(const char* env): Env(env) {}
    ~Free() { free(const_cast<char*>(this->Env)); }
  };
public:
  typedef kwsys_stl::set<const char*, kwsysEnvCompare> derived;
  ~kwsysEnv()
    {
    for(derived::iterator i = this->begin(); i != this->end(); ++i)
      {
      kwsysUnPutEnv(*i);
      free(const_cast<char*>(*i));
      }
    }
  const char* Release(const char* env)
    {
    const char* old = 0;
    derived::iterator i = this->find(env);
    if(i != this->end())
      {
      old = *i;
      this->erase(i);
      }
    return old;
    }
  bool Put(const char* env)
    {
    Free oldEnv(this->Release(env));
    static_cast<void>(oldEnv);
    char* newEnv = strdup(env);
    this->insert(newEnv);
    return putenv(newEnv) == 0;
    }
  bool UnPut(const char* env)
    {
    Free oldEnv(this->Release(env));
    static_cast<void>(oldEnv);
    return kwsysUnPutEnv(env) == 0;
    }
};

static kwsysEnv kwsysEnvInstance;

bool SystemTools::PutEnv(const char* env)
{
  return kwsysEnvInstance.Put(env);
}

bool SystemTools::UnPutEnv(const char* env)
{
  return kwsysEnvInstance.UnPut(env);
}

#endif

//----------------------------------------------------------------------------

600
601
const char* SystemTools::GetExecutableExtension()
{
Bill Hoffman's avatar
Bill Hoffman committed
602
#if defined(_WIN32) || defined(__CYGWIN__) || defined(__VMS)
603
604
605
  return ".exe";
#else
  return "";
606
#endif
607
608
}

609
610
611
612
613
614
615
616
617
FILE* SystemTools::Fopen(const char* file, const char* mode)
{
#ifdef _WIN32
  return _wfopen(Encoding::ToWide(file).c_str(),
                 Encoding::ToWide(mode).c_str());
#else
  return fopen(file, mode);
#endif
}
618
619
620

bool SystemTools::MakeDirectory(const char* path)
{
Bill Hoffman's avatar
Bill Hoffman committed
621
622
623
624
  if(!path)
    {
    return false;
    }
625
626
  if(SystemTools::FileExists(path))
    {
627
    return SystemTools::FileIsDirectory(path);
628
    }
629
  kwsys_stl::string dir = path;
630
  if(dir.empty())
631
632
633
634
635
    {
    return false;
    }
  SystemTools::ConvertToUnixSlashes(dir);

636
  kwsys_stl::string::size_type pos = 0;
637
638
  kwsys_stl::string topdir;
  while((pos = dir.find('/', pos)) != kwsys_stl::string::npos)
639
640
641
642
643
    {
    topdir = dir.substr(0, pos);
    Mkdir(topdir.c_str());
    pos++;
    }
644
  topdir = dir;
645
646
647
648
649
650
  if(Mkdir(topdir.c_str()) != 0)
    {
    // There is a bug in the Borland Run time library which makes MKDIR
    // return EACCES when it should return EEXISTS
    // if it is some other error besides directory exists
    // then return false
651
    if( (errno != EEXIST)
652
#ifdef __BORLANDC__
653
654
        && (errno != EACCES)
#endif
655
656
657
658
659
660
661
662
663
664
665
      )
      {
      return false;
      }
    }
  return true;
}


// replace replace with with as many times as it shows up in source.
// write the result into source.
666
void SystemTools::ReplaceString(kwsys_stl::string& source,
667
668
669
                                   const char* replace,
                                   const char* with)
{
Ken Martin's avatar
Ken Martin committed
670
  const char *src = source.c_str();
Bill Lorensen's avatar
Bill Lorensen committed
671
  char *searchPos = const_cast<char *>(strstr(src,replace));
672

673
  // get out quick if string is not found
Ken Martin's avatar
Ken Martin committed
674
  if (!searchPos)
675
676
677
    {
    return;
    }
Ken Martin's avatar
Ken Martin committed
678
679
680

  // perform replacements until done
  size_t replaceSize = strlen(replace);
681
682
683
684
685
  // do while hangs if replaceSize is 0
  if(replaceSize == 0)
    {
    return;
    }
Ken Martin's avatar
Ken Martin committed
686
687
688
  char *orig = strdup(src);
  char *currentPos = orig;
  searchPos = searchPos - src + orig;
689

Ken Martin's avatar
Ken Martin committed
690
  // initialize the result
Ken Martin's avatar
Ken Martin committed
691
  source.erase(source.begin(),source.end());
Ken Martin's avatar
Ken Martin committed
692
  do
693
    {
Ken Martin's avatar
Ken Martin committed
694
695
696
697
    *searchPos = '\0';
    source += currentPos;
    currentPos = searchPos + replaceSize;
    // replace
698
    source += with;
Ken Martin's avatar
Ken Martin committed
699
    searchPos = strstr(currentPos,replace);
700
    }
Ken Martin's avatar
Ken Martin committed
701
702
703
704
705
  while (searchPos);

  // copy any trailing text
  source += currentPos;
  free(orig);
706
707
}

708
709
710
711
712
713
714
715
716
#if defined(KEY_WOW64_32KEY) && defined(KEY_WOW64_64KEY)
# define KWSYS_ST_KEY_WOW64_32KEY KEY_WOW64_32KEY
# define KWSYS_ST_KEY_WOW64_64KEY KEY_WOW64_64KEY
#else
# define KWSYS_ST_KEY_WOW64_32KEY 0x0200
# define KWSYS_ST_KEY_WOW64_64KEY 0x0100
#endif

#if defined(_WIN32) && !defined(__CYGWIN__)
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
static bool SystemToolsParseRegistryKey(const char* key,
                                        HKEY& primaryKey,
                                        kwsys_stl::string& second,
                                        kwsys_stl::string& valuename)
{
  kwsys_stl::string primary = key;

  size_t start = primary.find("\\");
  if (start == kwsys_stl::string::npos)
    {
    return false;
    }

  size_t valuenamepos = primary.find(";");
  if (valuenamepos != kwsys_stl::string::npos)
    {
    valuename = primary.substr(valuenamepos+1);
    }

  second = primary.substr(start+1, valuenamepos-start-1);
  primary = primary.substr(0, start);

  if (primary == "HKEY_CURRENT_USER")
    {
    primaryKey = HKEY_CURRENT_USER;
    }
  if (primary == "HKEY_CURRENT_CONFIG")
    {
    primaryKey = HKEY_CURRENT_CONFIG;
    }
  if (primary == "HKEY_CLASSES_ROOT")
    {
    primaryKey = HKEY_CLASSES_ROOT;
    }
  if (primary == "HKEY_LOCAL_MACHINE")
    {
    primaryKey = HKEY_LOCAL_MACHINE;
    }
  if (primary == "HKEY_USERS")
    {
    primaryKey = HKEY_USERS;
    }

  return true;
}

763
764
765
static DWORD SystemToolsMakeRegistryMode(DWORD mode,
                                         SystemTools::KeyWOW64 view)
{
766
  // only add the modes when on a system that supports Wow64.
767
  static FARPROC wow64p = GetProcAddress(GetModuleHandleW(L"kernel32"),
768
                                         "IsWow64Process");
769
770
771
772
773
  if(wow64p == NULL)
    {
    return mode;
    }

774
775
776
777
778
779
780
781
782
783
784
785
  if(view == SystemTools::KeyWOW64_32)
    {
    return mode | KWSYS_ST_KEY_WOW64_32KEY;
    }
  else if(view == SystemTools::KeyWOW64_64)
    {
    return mode | KWSYS_ST_KEY_WOW64_64KEY;
    }
  return mode;
}
#endif

786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
#if defined(_WIN32) && !defined(__CYGWIN__)
bool
SystemTools::GetRegistrySubKeys(const char *key,
                                kwsys_stl::vector<kwsys_stl::string>& subkeys,
                                KeyWOW64 view)
{
  HKEY primaryKey = HKEY_CURRENT_USER;
  kwsys_stl::string second;
  kwsys_stl::string valuename;
  if (!SystemToolsParseRegistryKey(key, primaryKey, second, valuename))
    {
    return false;
    }

  HKEY hKey;
801
802
  if(RegOpenKeyExW(primaryKey,
                  Encoding::ToWide(second).c_str(),
803
804
805
806
807
808
809
810
                  0,
                  SystemToolsMakeRegistryMode(KEY_READ, view),
                  &hKey) != ERROR_SUCCESS)
    {
    return false;
    }
  else
    {
811
    wchar_t name[1024];
812
813
814
    DWORD dwNameSize = sizeof(name)/sizeof(name[0]);

    DWORD i = 0;
815
    while (RegEnumKeyW(hKey, i, name, dwNameSize) == ERROR_SUCCESS)
816
      {
817
      subkeys.push_back(Encoding::ToNarrow(name));
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
      ++i;
      }

    RegCloseKey(hKey);
    }

  return true;
}
#else
bool SystemTools::GetRegistrySubKeys(const char *,
                                     kwsys_stl::vector<kwsys_stl::string>&,
                                     KeyWOW64)
{
  return false;
}
#endif

835
// Read a registry value.
836
// Example :
837
838
839
840
841
842
//      HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath
//      =>  will return the data of the "default" value of the key
//      HKEY_LOCAL_MACHINE\SOFTWARE\Scriptics\Tcl\8.4;Root
//      =>  will return the data of the "Root" value of the key

#if defined(_WIN32) && !defined(__CYGWIN__)
843
844
bool SystemTools::ReadRegistryValue(const char *key, kwsys_stl::string &value,
                                    KeyWOW64 view)
845
{
846
  bool valueset = false;
847
  HKEY primaryKey = HKEY_CURRENT_USER;
848
849
  kwsys_stl::string second;
  kwsys_stl::string valuename;
850
  if (!SystemToolsParseRegistryKey(key, primaryKey, second, valuename))
851
852
853
854
855
    {
    return false;
    }

  HKEY hKey;
856
857
  if(RegOpenKeyExW(primaryKey,
                  Encoding::ToWide(second).c_str(),
858
                  0,
859
                  SystemToolsMakeRegistryMode(KEY_READ, view),
860
861
862
863
864
865
866
867
                  &hKey) != ERROR_SUCCESS)
    {
    return false;
    }
  else
    {
    DWORD dwType, dwSize;
    dwSize = 1023;
868
869
870
    wchar_t data[1024];
    if(RegQueryValueExW(hKey,
                       Encoding::ToWide(valuename).c_str(),
871
872
873
                       NULL,
                       &dwType,
                       (BYTE *)data,
874
875
876
877
                       &dwSize) == ERROR_SUCCESS)
      {
      if (dwType == REG_SZ)
        {
878
        value = Encoding::ToNarrow(data);
879
880
881
882
        valueset = true;
        }
      else if (dwType == REG_EXPAND_SZ)
        {
883
        wchar_t expanded[1024];
884
        DWORD dwExpandedSize = sizeof(expanded)/sizeof(expanded[0]);
885
886
        if(ExpandEnvironmentStringsW(data, expanded,
            dwExpandedSize))
887
          {
888
          value = Encoding::ToNarrow(expanded);
889
890
          valueset = true;
          }
891
892
        }
      }
893
894

    RegCloseKey(hKey);
895
    }
896
897

  return valueset;
898
899
}
#else
900
901
bool SystemTools::ReadRegistryValue(const char *, kwsys_stl::string &,
                                    KeyWOW64)
902
903
904
905
906
907
908
{
  return false;
}
#endif


// Write a registry value.
909
// Example :
910
911
912
913
914
915
//      HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath
//      =>  will set the data of the "default" value of the key
//      HKEY_LOCAL_MACHINE\SOFTWARE\Scriptics\Tcl\8.4;Root
//      =>  will set the data of the "Root" value of the key

#if defined(_WIN32) && !defined(__CYGWIN__)
916
917
bool SystemTools::WriteRegistryValue(const char *key, const char *value,
                                     KeyWOW64 view)
918
{
919
  HKEY primaryKey = HKEY_CURRENT_USER;
920
921
  kwsys_stl::string second;
  kwsys_stl::string valuename;
922
  if (!SystemToolsParseRegistryKey(key, primaryKey, second, valuename))
923
924
925
926
927
928
    {
    return false;
    }

  HKEY hKey;
  DWORD dwDummy;
929
930
931
  wchar_t lpClass[] = L"";
  if(RegCreateKeyExW(primaryKey,
                    Encoding::ToWide(second).c_str(),
932
                    0,
933
                    lpClass,
934
                    REG_OPTION_NON_VOLATILE,
935
                    SystemToolsMakeRegistryMode(KEY_WRITE, view),
936
937
938
939
940
941
942
                    NULL,
                    &hKey,
                    &dwDummy) != ERROR_SUCCESS)
    {
    return false;
    }

943
944
945
  std::wstring wvalue = Encoding::ToWide(value);
  if(RegSetValueExW(hKey,
                   Encoding::ToWide(valuename).c_str(),
946
947
                   0,
                   REG_SZ,
948
949
                   (CONST BYTE *)wvalue.c_str(),
                   (DWORD)(sizeof(wchar_t) * (wvalue.size() + 1))) == ERROR_SUCCESS)
950
951
952
953
954
955
    {
    return true;
    }
  return false;
}
#else
956
bool SystemTools::WriteRegistryValue(const char *, const char *, KeyWOW64)
957
958
959
960
961
962
{
  return false;
}
#endif

// Delete a registry value.
963
// Example :
964
965
966
967
968
969
//      HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath
//      =>  will delete the data of the "default" value of the key
//      HKEY_LOCAL_MACHINE\SOFTWARE\Scriptics\Tcl\8.4;Root
//      =>  will delete  the data of the "Root" value of the key

#if defined(_WIN32) && !defined(__CYGWIN__)
970
bool SystemTools::DeleteRegistryValue(const char *key, KeyWOW64 view)
971
{
972
  HKEY primaryKey = HKEY_CURRENT_USER;
973
974
  kwsys_stl::string second;
  kwsys_stl::string valuename;
975
  if (!SystemToolsParseRegistryKey(key, primaryKey, second, valuename))
976
977
978
979
980
    {
    return false;
    }

  HKEY hKey;
981
982
  if(RegOpenKeyExW(primaryKey,
                  Encoding::ToWide(second).c_str(),
983
                  0,
984
                  SystemToolsMakeRegistryMode(KEY_WRITE, view),
985
986
987
988
989
990
                  &hKey) != ERROR_SUCCESS)
    {
    return false;
    }
  else
    {
991
    if(RegDeleteValue(hKey,
992
993
                      (LPTSTR)valuename.c_str()) == ERROR_SUCCESS)
      {
994
      RegCloseKey(hKey);
995
996
997
998
999
1000
      return true;
      }
    }
  return false;
}
#else
For faster browsing, not all history is shown. View entire blame