Logo ROOT   6.12/07
Reference Guide
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
TWinNTSystem.cxx
Go to the documentation of this file.
1 // @(#)root/winnt:$Id: db9b3139b1551a1b4e31a17f57866a276d5cd419 $
2 // Author: Fons Rademakers 15/09/95
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 //////////////////////////////////////////////////////////////////////////////////
13 // //
14 // TWinNTSystem //
15 // //
16 // Class providing an interface to the Windows NT/Windows 95 Operating Systems. //
17 // //
18 //////////////////////////////////////////////////////////////////////////////////
19 
20 
21 #ifdef HAVE_CONFIG
22 #include "config.h"
23 #endif
24 
25 #include "Windows4Root.h"
26 #include "TWinNTSystem.h"
27 #include "TROOT.h"
28 #include "TError.h"
29 #include "TOrdCollection.h"
30 #include "TRegexp.h"
31 #include "TException.h"
32 #include "TEnv.h"
33 #include "TSocket.h"
34 #include "TApplication.h"
35 #include "TWin32SplashThread.h"
36 #include "Win32Constants.h"
37 #include "TInterpreter.h"
38 #include "TObjString.h"
39 #include "TVirtualX.h"
40 #include "TUrl.h"
41 
42 #include <sys/utime.h>
43 #include <sys/timeb.h>
44 #include <process.h>
45 #include <io.h>
46 #include <direct.h>
47 #include <ctype.h>
48 #include <float.h>
49 #include <sys/stat.h>
50 #include <signal.h>
51 #include <stdio.h>
52 #include <errno.h>
53 #include <lm.h>
54 #include <dbghelp.h>
55 #include <Tlhelp32.h>
56 #include <sstream>
57 #include <iostream>
58 #include <list>
59 #include <shlobj.h>
60 #include <conio.h>
61 
62 #if defined (_MSC_VER) && (_MSC_VER >= 1400)
63  #include <intrin.h>
64 #elif defined (_M_IX86)
65  static void __cpuid(int* cpuid_data, int info_type)
66  {
67  __asm {
68  push ebx
69  push edi
70  mov edi, cpuid_data
71  mov eax, info_type
72  cpuid
73  mov [edi], eax
74  mov [edi + 4], ebx
75  mov [edi + 8], ecx
76  mov [edi + 12], edx
77  pop edi
78  pop ebx
79  }
80  }
81  __int64 __rdtsc()
82  {
83  LARGE_INTEGER li;
84  __asm {
85  rdtsc
86  mov li.LowPart, eax
87  mov li.HighPart, edx
88  }
89  return li.QuadPart;
90  }
91 #else
92  static void __cpuid(int* cpuid_data, int) {
93  cpuid_data[0] = 0x00000000;
94  cpuid_data[1] = 0x00000000;
95  cpuid_data[2] = 0x00000000;
96  cpuid_data[3] = 0x00000000;
97  }
98  __int64 __rdtsc() { return (__int64)0; }
99 #endif
100 
101 extern "C" {
102  extern void Gl_setwidth(int width);
103  void *_ReturnAddress(void);
104 }
105 
106 //////////////////// Windows TFdSet ////////////////////////////////////////////////
107 class TFdSet {
108 private:
109  fd_set *fds_bits; // file descriptors (according MSDN maximum is 64)
110 public:
111  TFdSet() { fds_bits = new fd_set; fds_bits->fd_count = 0; }
112  virtual ~TFdSet() { delete fds_bits; }
113  void Copy(TFdSet &fd) const { memcpy((void*)fd.fds_bits, fds_bits, sizeof(fd_set)); }
114  TFdSet(const TFdSet& fd) { fd.Copy(*this); }
115  TFdSet& operator=(const TFdSet& fd) { fd.Copy(*this); return *this; }
116  void Zero() { fds_bits->fd_count = 0; }
117  void Set(Int_t fd)
118  {
119  if (fds_bits->fd_count < FD_SETSIZE-1) // protect out of bound access (64)
120  fds_bits->fd_array[fds_bits->fd_count++] = (SOCKET)fd;
121  else
122  ::SysError("TFdSet::Set", "fd_count will exeed FD_SETSIZE");
123  }
124  void Clr(Int_t fd)
125  {
126  int i;
127  for (i=0; i<fds_bits->fd_count; i++) {
128  if (fds_bits->fd_array[i]==(SOCKET)fd) {
129  while (i<fds_bits->fd_count-1) {
130  fds_bits->fd_array[i] = fds_bits->fd_array[i+1];
131  i++;
132  }
133  fds_bits->fd_count--;
134  break;
135  }
136  }
137  }
138  Int_t IsSet(Int_t fd) { return __WSAFDIsSet((SOCKET)fd, fds_bits); }
139  Int_t *GetBits() { return fds_bits && fds_bits->fd_count ? (Int_t*)fds_bits : 0; }
140  UInt_t GetCount() { return (UInt_t)fds_bits->fd_count; }
141  Int_t GetFd(Int_t i) { return i<fds_bits->fd_count ? fds_bits->fd_array[i] : 0; }
142 };
143 
144 namespace {
145  const char *kProtocolName = "tcp";
146  typedef void (*SigHandler_t)(ESignals);
147  static TWinNTSystem::ThreadMsgFunc_t gGUIThreadMsgFunc = 0; // GUI thread message handler func
148 
149  static HANDLE gGlobalEvent;
150  static HANDLE gTimerThreadHandle;
151  typedef NET_API_STATUS (WINAPI *pfn1)(LPVOID);
152  typedef NET_API_STATUS (WINAPI *pfn2)(LPCWSTR, LPCWSTR, DWORD, LPBYTE*);
153  typedef NET_API_STATUS (WINAPI *pfn3)(LPCWSTR, LPCWSTR, DWORD, LPBYTE*,
154  DWORD, LPDWORD, LPDWORD, PDWORD);
155  typedef NET_API_STATUS (WINAPI *pfn4)(LPCWSTR, DWORD, LPBYTE*, DWORD, LPDWORD,
156  LPDWORD, PDWORD);
157  static pfn1 p2NetApiBufferFree;
158  static pfn2 p2NetUserGetInfo;
159  static pfn3 p2NetLocalGroupGetMembers;
160  static pfn4 p2NetLocalGroupEnum;
161 
162  static struct signal_map {
163  int code;
164  SigHandler_t handler;
165  char *signame;
166  } signal_map[kMAXSIGNALS] = { // the order of the signals should be identical
167  -1 /*SIGBUS*/, 0, "bus error", // to the one in SysEvtHandler.h
168  SIGSEGV, 0, "segmentation violation",
169  -1 /*SIGSYS*/, 0, "bad argument to system call",
170  -1 /*SIGPIPE*/, 0, "write on a pipe with no one to read it",
171  SIGILL, 0, "illegal instruction",
172  -1 /*SIGQUIT*/, 0, "quit",
173  SIGINT, 0, "interrupt",
174  -1 /*SIGWINCH*/, 0, "window size change",
175  -1 /*SIGALRM*/, 0, "alarm clock",
176  -1 /*SIGCHLD*/, 0, "death of a child",
177  -1 /*SIGURG*/, 0, "urgent data arrived on an I/O channel",
178  SIGFPE, 0, "floating point exception",
179  SIGTERM, 0, "termination signal",
180  -1 /*SIGUSR1*/, 0, "user-defined signal 1",
181  -1 /*SIGUSR2*/, 0, "user-defined signal 2"
182  };
183 
184  ////// static functions providing interface to raw WinNT ////////////////////
185 
186  //---- RPC -------------------------------------------------------------------
187  //*-* Error codes set by the Windows Sockets implementation are not made available
188  //*-* via the errno variable. Additionally, for the getXbyY class of functions,
189  //*-* error codes are NOT made available via the h_errno variable. Instead, error
190  //*-* codes are accessed by using the WSAGetLastError . This function is provided
191  //*-* in Windows Sockets as a precursor (and eventually an alias) for the Win32
192  //*-* function GetLastError. This is intended to provide a reliable way for a thread
193  //*-* in a multithreaded process to obtain per-thread error information.
194 
195  /////////////////////////////////////////////////////////////////////////////
196  /// Receive exactly length bytes into buffer. Returns number of bytes
197  /// received. Returns -1 in case of error, -2 in case of MSG_OOB
198  /// and errno == EWOULDBLOCK, -3 in case of MSG_OOB and errno == EINVAL
199  /// and -4 in case of kNonBlock and errno == EWOULDBLOCK.
200  /// Returns -5 if pipe broken or reset by peer (EPIPE || ECONNRESET).
201 
202  static int WinNTRecv(int socket, void *buffer, int length, int flag)
203  {
204  if (socket == -1) return -1;
205  SOCKET sock = socket;
206 
207  int once = 0;
208  if (flag == -1) {
209  flag = 0;
210  once = 1;
211  }
212  if (flag == MSG_PEEK) {
213  once = 1;
214  }
215 
216  int nrecv, n;
217  char *buf = (char *)buffer;
218 
219  for (n = 0; n < length; n += nrecv) {
220  if ((nrecv = ::recv(sock, buf+n, length-n, flag)) <= 0) {
221  if (nrecv == 0) {
222  break; // EOF
223  }
224  if (flag == MSG_OOB) {
225  if (::WSAGetLastError() == WSAEWOULDBLOCK) {
226  return -2;
227  } else if (::WSAGetLastError() == WSAEINVAL) {
228  return -3;
229  }
230  }
231  if (::WSAGetLastError() == WSAEWOULDBLOCK) {
232  return -4;
233  } else {
234  if (::WSAGetLastError() != WSAEINTR)
235  ::SysError("TWinNTSystem::WinNTRecv", "recv");
236  if (::WSAGetLastError() == EPIPE ||
237  ::WSAGetLastError() == WSAECONNRESET)
238  return -5;
239  else
240  return -1;
241  }
242  }
243  if (once) {
244  return nrecv;
245  }
246  }
247  return n;
248  }
249 
250  /////////////////////////////////////////////////////////////////////////////
251  /// Send exactly length bytes from buffer. Returns -1 in case of error,
252  /// otherwise number of sent bytes. Returns -4 in case of kNoBlock and
253  /// errno == EWOULDBLOCK. Returns -5 if pipe broken or reset by peer
254  /// (EPIPE || ECONNRESET).
255 
256  static int WinNTSend(int socket, const void *buffer, int length, int flag)
257  {
258  if (socket < 0) return -1;
259  SOCKET sock = socket;
260 
261  int once = 0;
262  if (flag == -1) {
263  flag = 0;
264  once = 1;
265  }
266 
267  int nsent, n;
268  const char *buf = (const char *)buffer;
269 
270  for (n = 0; n < length; n += nsent) {
271  if ((nsent = ::send(sock, buf+n, length-n, flag)) <= 0) {
272  if (nsent == 0) {
273  break;
274  }
275  if (::WSAGetLastError() == WSAEWOULDBLOCK) {
276  return -4;
277  } else {
278  if (::WSAGetLastError() != WSAEINTR)
279  ::SysError("TWinNTSystem::WinNTSend", "send");
280  if (::WSAGetLastError() == EPIPE ||
281  ::WSAGetLastError() == WSAECONNRESET)
282  return -5;
283  else
284  return -1;
285  }
286  }
287  if (once) {
288  return nsent;
289  }
290  }
291  return n;
292  }
293 
294  /////////////////////////////////////////////////////////////////////////////
295  /// Wait for events on the file descriptors specified in the readready and
296  /// writeready masks or for timeout (in milliseconds) to occur.
297 
298  static int WinNTSelect(TFdSet *readready, TFdSet *writeready, Long_t timeout)
299  {
300  int retcode;
301  fd_set* rbits = readready ? (fd_set*)readready->GetBits() : 0;
302  fd_set* wbits = writeready ? (fd_set*)writeready->GetBits() : 0;
303 
304  if (timeout >= 0) {
305  timeval tv;
306  tv.tv_sec = timeout / 1000;
307  tv.tv_usec = (timeout % 1000) * 1000;
308 
309  retcode = ::select(0, rbits, wbits, 0, &tv);
310  } else {
311  retcode = ::select(0, rbits, wbits, 0, 0);
312  }
313 
314  if (retcode == SOCKET_ERROR) {
315  int errcode = ::WSAGetLastError();
316 
317  // if file descriptor is not a socket, assume it is the pipe used
318  // by TXSocket
319  if (errcode == WSAENOTSOCK) {
320  struct __stat64 buf;
321  int result = _fstat64( readready->GetFd(0), &buf );
322  if ( result == 0 ) {
323  if (buf.st_size > 0)
324  return 1;
325  }
326  // yield execution to another thread that is ready to run
327  // if no other thread is ready, sleep 1 ms before to return
328  if (gGlobalEvent) {
329  ::WaitForSingleObject(gGlobalEvent, 1);
330  ::ResetEvent(gGlobalEvent);
331  }
332  return 0;
333  }
334 
335  if ( errcode == WSAEINTR) {
336  TSystem::ResetErrno(); // errno is not self reseting
337  return -2;
338  }
339  if (errcode == EBADF) {
340  return -3;
341  }
342  return -1;
343  }
344  return retcode;
345  }
346 
347  /////////////////////////////////////////////////////////////////////////////
348  /// Get shared library search path.
349 
350  static const char *DynamicPath(const char *newpath = 0, Bool_t reset = kFALSE)
351  {
352  static TString dynpath;
353 
354  if (reset || newpath) {
355  dynpath = "";
356  }
357  if (newpath) {
358 
359  dynpath = newpath;
360 
361  } else if (dynpath == "") {
362  TString rdynpath = gEnv ? gEnv->GetValue("Root.DynamicPath", (char*)0) : "";
363  rdynpath.ReplaceAll("; ", ";"); // in case DynamicPath was extended
364  if (rdynpath == "") {
365  rdynpath = ".;"; rdynpath += TROOT::GetBinDir();
366  }
367  TString path = gSystem->Getenv("PATH");
368  if (path == "")
369  dynpath = rdynpath;
370  else {
371  dynpath = path; dynpath += ";"; dynpath += rdynpath;
372  }
373 
374  }
375 
376  if (!dynpath.Contains(TROOT::GetLibDir())) {
377  dynpath += ";"; dynpath += TROOT::GetLibDir();
378  }
379 
380  return dynpath;
381  }
382 
383  /////////////////////////////////////////////////////////////////////////////
384  /// Call the signal handler associated with the signal.
385 
386  static void sighandler(int sig)
387  {
388  for (int i = 0; i < kMAXSIGNALS; i++) {
389  if (signal_map[i].code == sig) {
390  (*signal_map[i].handler)((ESignals)i);
391  return;
392  }
393  }
394  }
395 
396  /////////////////////////////////////////////////////////////////////////////
397  /// Set a signal handler for a signal.
398 
399  static void WinNTSignal(ESignals sig, SigHandler_t handler)
400  {
401  signal_map[sig].handler = handler;
402  if (signal_map[sig].code != -1)
403  (SigHandler_t)signal(signal_map[sig].code, sighandler);
404  }
405 
406  /////////////////////////////////////////////////////////////////////////////
407  /// Return the signal name associated with a signal.
408 
409  static char *WinNTSigname(ESignals sig)
410  {
411  return signal_map[sig].signame;
412  }
413 
414  /////////////////////////////////////////////////////////////////////////////
415  /// WinNT signal handler.
416 
417  static BOOL ConsoleSigHandler(DWORD sig)
418  {
419  switch (sig) {
420  case CTRL_C_EVENT:
421  if (gSystem) {
422  ((TWinNTSystem*)gSystem)->DispatchSignals(kSigInterrupt);
423  }
424  else {
425  Break("TInterruptHandler::Notify", "keyboard interrupt");
426  if (TROOT::Initialized()) {
427  gInterpreter->RewindDictionary();
428  }
429  }
430  return kTRUE;
431  case CTRL_BREAK_EVENT:
432  case CTRL_LOGOFF_EVENT:
433  case CTRL_SHUTDOWN_EVENT:
434  case CTRL_CLOSE_EVENT:
435  default:
436  printf("\n *** Break *** keyboard interrupt - ROOT is terminated\n");
437  gSystem->Exit(-1);
438  return kTRUE;
439  }
440  }
441 
442  static CONTEXT *fgXcptContext = 0;
443  /////////////////////////////////////////////////////////////////////////////
444 
445  static void SigHandler(ESignals sig)
446  {
447  if (gSystem)
448  ((TWinNTSystem*)gSystem)->DispatchSignals(sig);
449  }
450 
451  /////////////////////////////////////////////////////////////////////////////
452  /// Function that's called when an unhandled exception occurs.
453  /// Produces a stack trace, and lets the system deal with it
454  /// as if it was an unhandled excecption (usually ::abort)
455 
456  LONG WINAPI ExceptionFilter(LPEXCEPTION_POINTERS pXcp)
457  {
458  fgXcptContext = pXcp->ContextRecord;
459  gSystem->StackTrace();
460  return EXCEPTION_CONTINUE_SEARCH;
461  }
462 
463 
464 #pragma intrinsic(_ReturnAddress)
465 #pragma auto_inline(off)
466  DWORD_PTR GetProgramCounter()
467  {
468  // Returns the current program counter.
469  return (DWORD_PTR)_ReturnAddress();
470  }
471 #pragma auto_inline(on)
472 
473  /////////////////////////////////////////////////////////////////////////////
474  /// Message processing loop for the TGWin32 related GUI
475  /// thread for processing windows messages (aka Main/Server thread).
476  /// We need to start the thread outside the TGWin32 / GUI related
477  /// dll, because starting threads at DLL init time does not work.
478  /// Instead, we start an ideling thread at binary startup, and only
479  /// call the "real" message processing function
480  /// TGWin32::GUIThreadMessageFunc() once gVirtualX comes up.
481 
482  static DWORD WINAPI GUIThreadMessageProcessingLoop(void *p)
483  {
484  MSG msg;
485 
486  // force to create message queue
487  ::PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
488 
489  Int_t erret = 0;
490  Bool_t endLoop = kFALSE;
491  while (!endLoop) {
492  if (gGlobalEvent) ::SetEvent(gGlobalEvent);
493  erret = ::GetMessage(&msg, NULL, NULL, NULL);
494  if (erret <= 0) endLoop = kTRUE;
495  if (gGUIThreadMsgFunc)
496  endLoop = (*gGUIThreadMsgFunc)(&msg);
497  }
498 
499  gVirtualX->CloseDisplay();
500 
501  // exit thread
502  if (erret == -1) {
503  erret = ::GetLastError();
504  Error("MsgLoop", "Error in GetMessage");
505  ::ExitThread(-1);
506  } else {
507  ::ExitThread(0);
508  }
509  return 0;
510  }
511 
512  //=========================================================================
513  // Load IMAGEHLP.DLL and get the address of functions in it that we'll use
514  // by Microsoft, from http://www.microsoft.com/msj/0597/hoodtextfigs.htm#fig1
515  //=========================================================================
516  // Make typedefs for some IMAGEHLP.DLL functions so that we can use them
517  // with GetProcAddress
518  typedef BOOL (__stdcall *SYMINITIALIZEPROC)( HANDLE, LPSTR, BOOL );
519  typedef BOOL (__stdcall *SYMCLEANUPPROC)( HANDLE );
520  typedef BOOL (__stdcall *STACKWALK64PROC)
521  ( DWORD, HANDLE, HANDLE, LPSTACKFRAME64, LPVOID,
522  PREAD_PROCESS_MEMORY_ROUTINE,PFUNCTION_TABLE_ACCESS_ROUTINE,
523  PGET_MODULE_BASE_ROUTINE, PTRANSLATE_ADDRESS_ROUTINE );
524  typedef LPVOID (__stdcall *SYMFUNCTIONTABLEACCESS64PROC)( HANDLE, DWORD64 );
525  typedef DWORD (__stdcall *SYMGETMODULEBASE64PROC)( HANDLE, DWORD64 );
526  typedef BOOL (__stdcall *SYMGETMODULEINFO64PROC)(HANDLE, DWORD64, PIMAGEHLP_MODULE64);
527  typedef BOOL (__stdcall *SYMGETSYMFROMADDR64PROC)( HANDLE, DWORD64, PDWORD64, PIMAGEHLP_SYMBOL64);
528  typedef BOOL (__stdcall *SYMGETLINEFROMADDR64PROC)(HANDLE, DWORD64, PDWORD, PIMAGEHLP_LINE64);
529  typedef DWORD (__stdcall *UNDECORATESYMBOLNAMEPROC)(PCSTR, PSTR, DWORD, DWORD);
530 
531 
532  static SYMINITIALIZEPROC _SymInitialize = 0;
533  static SYMCLEANUPPROC _SymCleanup = 0;
534  static STACKWALK64PROC _StackWalk64 = 0;
535  static SYMFUNCTIONTABLEACCESS64PROC _SymFunctionTableAccess64 = 0;
536  static SYMGETMODULEBASE64PROC _SymGetModuleBase64 = 0;
537  static SYMGETMODULEINFO64PROC _SymGetModuleInfo64 = 0;
538  static SYMGETSYMFROMADDR64PROC _SymGetSymFromAddr64 = 0;
539  static SYMGETLINEFROMADDR64PROC _SymGetLineFromAddr64 = 0;
540  static UNDECORATESYMBOLNAMEPROC _UnDecorateSymbolName = 0;
541 
542  BOOL InitImagehlpFunctions()
543  {
544  // Fetches function addresses from IMAGEHLP.DLL at run-time, so we
545  // don't need to link against its import library. These functions
546  // are used in StackTrace; if they cannot be found (e.g. because
547  // IMAGEHLP.DLL doesn't exist or has the wrong version) we cannot
548  // produce a stack trace.
549 
550  HMODULE hModImagehlp = LoadLibrary( "IMAGEHLP.DLL" );
551  if (!hModImagehlp)
552  return FALSE;
553 
554  _SymInitialize = (SYMINITIALIZEPROC) GetProcAddress( hModImagehlp, "SymInitialize" );
555  if (!_SymInitialize)
556  return FALSE;
557 
558  _SymCleanup = (SYMCLEANUPPROC) GetProcAddress( hModImagehlp, "SymCleanup" );
559  if (!_SymCleanup)
560  return FALSE;
561 
562  _StackWalk64 = (STACKWALK64PROC) GetProcAddress( hModImagehlp, "StackWalk64" );
563  if (!_StackWalk64)
564  return FALSE;
565 
566  _SymFunctionTableAccess64 = (SYMFUNCTIONTABLEACCESS64PROC) GetProcAddress(hModImagehlp, "SymFunctionTableAccess64" );
567  if (!_SymFunctionTableAccess64)
568  return FALSE;
569 
570  _SymGetModuleBase64=(SYMGETMODULEBASE64PROC)GetProcAddress(hModImagehlp, "SymGetModuleBase64");
571  if (!_SymGetModuleBase64)
572  return FALSE;
573 
574  _SymGetModuleInfo64=(SYMGETMODULEINFO64PROC)GetProcAddress(hModImagehlp, "SymGetModuleInfo64");
575  if (!_SymGetModuleInfo64)
576  return FALSE;
577 
578  _SymGetSymFromAddr64=(SYMGETSYMFROMADDR64PROC)GetProcAddress(hModImagehlp, "SymGetSymFromAddr64");
579  if (!_SymGetSymFromAddr64)
580  return FALSE;
581 
582  _SymGetLineFromAddr64=(SYMGETLINEFROMADDR64PROC)GetProcAddress(hModImagehlp, "SymGetLineFromAddr64");
583  if (!_SymGetLineFromAddr64)
584  return FALSE;
585 
586  _UnDecorateSymbolName=(UNDECORATESYMBOLNAMEPROC)GetProcAddress(hModImagehlp, "UnDecorateSymbolName");
587  if (!_UnDecorateSymbolName)
588  return FALSE;
589 
590  if (!_SymInitialize(GetCurrentProcess(), 0, TRUE ))
591  return FALSE;
592 
593  return TRUE;
594  }
595 
596  // stack trace helpers getModuleName, getFunctionName by
597  /**************************************************************************
598  * VRS - The Virtual Rendering System
599  * Copyright (C) 2000-2004 Computer Graphics Systems Group at the
600  * Hasso-Plattner-Institute (HPI), Potsdam, Germany.
601  * This library is free software; you can redistribute it and/or modify it
602  * under the terms of the GNU Lesser General Public License as published by
603  * the Free Software Foundation; either version 2.1 of the License, or
604  * (at your option) any later version.
605  ***************************************************************************/
606  std::string GetModuleName(DWORD64 address)
607  {
608  // Return the name of the module that contains the function at address.
609  // Used by StackTrace.
610  std::ostringstream out;
611  HANDLE process = ::GetCurrentProcess();
612 
613  DWORD lineDisplacement = 0;
614  IMAGEHLP_LINE64 line;
615  ::ZeroMemory(&line, sizeof(line));
616  line.SizeOfStruct = sizeof(line);
617  if(_SymGetLineFromAddr64(process, address, &lineDisplacement, &line)) {
618  out << line.FileName << "(" << line.LineNumber << "): ";
619  } else {
620  IMAGEHLP_MODULE64 module;
621  ::ZeroMemory(&module, sizeof(module));
622  module.SizeOfStruct = sizeof(module);
623  if(_SymGetModuleInfo64(process, address, &module)) {
624  out << module.ModuleName << "!";
625  } else {
626  out << "0x" << std::hex << address << std::dec << " ";
627  }
628  }
629 
630  return out.str();
631  }
632 
633  std::string GetFunctionName(DWORD64 address)
634  {
635  // Return the name of the function at address.
636  // Used by StackTrace.
637  DWORD64 symbolDisplacement = 0;
638  HANDLE process = ::GetCurrentProcess();
639 
640  const unsigned int SYMBOL_BUFFER_SIZE = 8192;
641  char symbolBuffer[SYMBOL_BUFFER_SIZE];
642  PIMAGEHLP_SYMBOL64 symbol = reinterpret_cast<PIMAGEHLP_SYMBOL64>(symbolBuffer);
643  ::ZeroMemory(symbol, SYMBOL_BUFFER_SIZE);
644  symbol->SizeOfStruct = SYMBOL_BUFFER_SIZE;
645  symbol->MaxNameLength = SYMBOL_BUFFER_SIZE - sizeof(IMAGEHLP_SYMBOL64);
646 
647  if(_SymGetSymFromAddr64(process, address, &symbolDisplacement, symbol)) {
648  // Make the symbol readable for humans
649  const unsigned int NAME_SIZE = 8192;
650  char name[NAME_SIZE];
651  _UnDecorateSymbolName(
652  symbol->Name,
653  name,
654  NAME_SIZE,
655  UNDNAME_COMPLETE |
656  UNDNAME_NO_THISTYPE |
657  UNDNAME_NO_SPECIAL_SYMS |
658  UNDNAME_NO_MEMBER_TYPE |
659  UNDNAME_NO_MS_KEYWORDS |
660  UNDNAME_NO_ACCESS_SPECIFIERS
661  );
662 
663  std::string result;
664  result += name;
665  result += "()";
666  return result;
667  } else {
668  return "??";
669  }
670  }
671 
672  ////// Shortcuts helper functions IsShortcut and ResolveShortCut ///////////
673 
674  /////////////////////////////////////////////////////////////////////////////
675  /// Validates if a file name has extension '.lnk'. Returns true if file
676  /// name have extension same as Window's shortcut file (.lnk).
677 
678  static BOOL IsShortcut(const char *filename)
679  {
680  //File extension for the Window's shortcuts (.lnk)
681  const char *extLnk = ".lnk";
682  if (filename != NULL) {
683  //Validate extension
684  TString strfilename(filename);
685  if (strfilename.EndsWith(extLnk))
686  return TRUE;
687  }
688  return FALSE;
689  }
690 
691  /////////////////////////////////////////////////////////////////////////////
692  /// Resolve a ShellLink (i.e. c:\path\shortcut.lnk) to a real path.
693 
694  static BOOL ResolveShortCut(LPCSTR pszShortcutFile, char *pszPath, int maxbuf)
695  {
696  HRESULT hres;
697  IShellLink* psl;
698  char szGotPath[MAX_PATH];
699  WIN32_FIND_DATA wfd;
700 
701  *pszPath = 0; // assume failure
702 
703  // Make typedefs for some ole32.dll functions so that we can use them
704  // with GetProcAddress
705  typedef HRESULT (__stdcall *COINITIALIZEPROC)( LPVOID );
706  static COINITIALIZEPROC _CoInitialize = 0;
707  typedef void (__stdcall *COUNINITIALIZEPROC)( void );
708  static COUNINITIALIZEPROC _CoUninitialize = 0;
709  typedef HRESULT (__stdcall *COCREATEINSTANCEPROC)( REFCLSID, LPUNKNOWN,
710  DWORD, REFIID, LPVOID );
711  static COCREATEINSTANCEPROC _CoCreateInstance = 0;
712 
713  HMODULE hModImagehlp = LoadLibrary( "ole32.dll" );
714  if (!hModImagehlp)
715  return FALSE;
716 
717  _CoInitialize = (COINITIALIZEPROC) GetProcAddress( hModImagehlp, "CoInitialize" );
718  if (!_CoInitialize)
719  return FALSE;
720  _CoUninitialize = (COUNINITIALIZEPROC) GetProcAddress( hModImagehlp, "CoUninitialize");
721  if (!_CoUninitialize)
722  return FALSE;
723  _CoCreateInstance = (COCREATEINSTANCEPROC) GetProcAddress( hModImagehlp, "CoCreateInstance" );
724  if (!_CoCreateInstance)
725  return FALSE;
726 
727  _CoInitialize(NULL);
728 
729  hres = _CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
730  IID_IShellLink, (void **) &psl);
731  if (SUCCEEDED(hres)) {
732  IPersistFile* ppf;
733 
734  hres = psl->QueryInterface(IID_IPersistFile, (void **) &ppf);
735  if (SUCCEEDED(hres)) {
736  WCHAR wsz[MAX_PATH];
737  MultiByteToWideChar(CP_ACP, 0, pszShortcutFile, -1, wsz, MAX_PATH);
738 
739  hres = ppf->Load(wsz, STGM_READ);
740  if (SUCCEEDED(hres)) {
741  hres = psl->Resolve(HWND_DESKTOP, SLR_ANY_MATCH | SLR_NO_UI | SLR_UPDATE);
742  if (SUCCEEDED(hres)) {
743  strlcpy(szGotPath, pszShortcutFile,MAX_PATH);
744  hres = psl->GetPath(szGotPath, MAX_PATH, (WIN32_FIND_DATA *)&wfd,
745  SLGP_UNCPRIORITY | SLGP_RAWPATH);
746  strlcpy(pszPath,szGotPath, maxbuf);
747  if (maxbuf) pszPath[maxbuf-1] = 0;
748  }
749  }
750  ppf->Release();
751  }
752  psl->Release();
753  }
754  _CoUninitialize();
755 
756  return SUCCEEDED(hres);
757  }
758 
759  void UpdateRegistry(TWinNTSystem* sys, char* buf /* size of buffer: MAX_MODULE_NAME32 + 1 */) {
760  // register ROOT as the .root file handler:
761  GetModuleFileName(0, buf, MAX_MODULE_NAME32 + 1);
762  if (strcmp(sys->TWinNTSystem::BaseName(buf), "root.exe"))
763  return;
764  HKEY regCUS;
765  if (!::RegOpenKeyEx(HKEY_CURRENT_USER, "Software", 0, KEY_READ, &regCUS) == ERROR_SUCCESS)
766  return;
767  HKEY regCUSC;
768  if (!::RegOpenKeyEx(regCUS, "Classes", 0, KEY_READ, &regCUSC) == ERROR_SUCCESS) {
769  ::RegCloseKey(regCUS);
770  return;
771  }
772 
773  HKEY regROOT;
774  bool regROOTwrite = false;
775  TString iconloc(buf);
776  iconloc += ",-101";
777 
778  if (::RegOpenKeyEx(regCUSC, "ROOTDEV.ROOT", 0, KEY_READ, &regROOT) != ERROR_SUCCESS) {
779  ::RegCloseKey(regCUSC);
780  if (::RegOpenKeyEx(regCUS, "Classes", 0, KEY_READ | KEY_WRITE, &regCUSC) == ERROR_SUCCESS &&
781  ::RegCreateKeyEx(regCUSC, "ROOTDEV.ROOT", 0, NULL, 0, KEY_READ | KEY_WRITE,
782  NULL, &regROOT, NULL) == ERROR_SUCCESS) {
783  regROOTwrite = true;
784  }
785  } else {
786  HKEY regROOTIcon;
787  if (::RegOpenKeyEx(regROOT, "DefaultIcon", 0, KEY_READ, &regROOTIcon) == ERROR_SUCCESS) {
788  char bufIconLoc[1024];
789  DWORD dwType;
790  DWORD dwSize = sizeof(bufIconLoc);
791 
792  if (::RegQueryValueEx(regROOTIcon, NULL, NULL, &dwType, (BYTE*)bufIconLoc, &dwSize) == ERROR_SUCCESS)
793  regROOTwrite = (iconloc != bufIconLoc);
794  else
795  regROOTwrite = true;
796  ::RegCloseKey(regROOTIcon);
797  } else
798  regROOTwrite = true;
799  if (regROOTwrite) {
800  // re-open for writing
801  ::RegCloseKey(regCUSC);
802  ::RegCloseKey(regROOT);
803  if (::RegOpenKeyEx(regCUS, "Classes", 0, KEY_READ | KEY_WRITE, &regCUSC) != ERROR_SUCCESS) {
804  // error opening key for writing:
805  regROOTwrite = false;
806  } else {
807  if (::RegOpenKeyEx(regCUSC, "ROOTDEV.ROOT", 0, KEY_WRITE, &regROOT) != ERROR_SUCCESS) {
808  // error opening key for writing:
809  regROOTwrite = false;
810  ::RegCloseKey(regCUSC);
811  }
812  }
813  }
814  }
815 
816  // determine the fileopen.C file path:
817  TString fileopen = "fileopen.C";
818  TString rootmacrodir = "macros";
819  sys->PrependPathName(getenv("ROOTSYS"), rootmacrodir);
820  sys->PrependPathName(rootmacrodir.Data(), fileopen);
821 
822  if (regROOTwrite) {
823  // only write to registry if fileopen.C is readable
824  regROOTwrite = (::_access(fileopen, kReadPermission) == 0);
825  }
826 
827  if (!regROOTwrite) {
828  ::RegCloseKey(regROOT);
829  ::RegCloseKey(regCUSC);
830  ::RegCloseKey(regCUS);
831  return;
832  }
833 
834  static const char apptitle[] = "ROOT data file";
835  ::RegSetValueEx(regROOT, NULL, 0, REG_SZ, (BYTE*)apptitle, sizeof(apptitle));
836  DWORD editflags = /*FTA_OpenIsSafe*/ 0x00010000; // trust downloaded files
837  ::RegSetValueEx(regROOT, "EditFlags", 0, REG_DWORD, (BYTE*)&editflags, sizeof(editflags));
838 
839  HKEY regROOTIcon;
840  if (::RegCreateKeyEx(regROOT, "DefaultIcon", 0, NULL, 0, KEY_READ | KEY_WRITE,
841  NULL, &regROOTIcon, NULL) == ERROR_SUCCESS) {
842  TString iconloc(buf);
843  iconloc += ",-101";
844  ::RegSetValueEx(regROOTIcon, NULL, 0, REG_SZ, (BYTE*)iconloc.Data(), iconloc.Length() + 1);
845  ::RegCloseKey(regROOTIcon);
846  }
847 
848  // "open" verb
849  HKEY regROOTshell;
850  if (::RegCreateKeyEx(regROOT, "shell", 0, NULL, 0, KEY_READ | KEY_WRITE,
851  NULL, &regROOTshell, NULL) == ERROR_SUCCESS) {
852  HKEY regShellOpen;
853  if (::RegCreateKeyEx(regROOTshell, "open", 0, NULL, 0, KEY_READ | KEY_WRITE,
854  NULL, &regShellOpen, NULL) == ERROR_SUCCESS) {
855  HKEY regShellOpenCmd;
856  if (::RegCreateKeyEx(regShellOpen, "command", 0, NULL, 0, KEY_READ | KEY_WRITE,
857  NULL, &regShellOpenCmd, NULL) == ERROR_SUCCESS) {
858  TString cmd(buf);
859  cmd += " -l \"%1\" \"";
860  cmd += fileopen;
861  cmd += "\"";
862  ::RegSetValueEx(regShellOpenCmd, NULL, 0, REG_SZ, (BYTE*)cmd.Data(), cmd.Length() + 1);
863  ::RegCloseKey(regShellOpenCmd);
864  }
865  ::RegCloseKey(regShellOpen);
866  }
867  ::RegCloseKey(regROOTshell);
868  }
869  ::RegCloseKey(regROOT);
870 
871  if (::RegCreateKeyEx(regCUSC, ".root", 0, NULL, 0, KEY_READ | KEY_WRITE,
872  NULL, &regROOT, NULL) == ERROR_SUCCESS) {
873  static const char appname[] = "ROOTDEV.ROOT";
874  ::RegSetValueEx(regROOT, NULL, 0, REG_SZ, (BYTE*)appname, sizeof(appname));
875  }
876  ::RegCloseKey(regCUSC);
877  ::RegCloseKey(regCUS);
878 
879  // tell Windows that the association was changed
880  ::SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);
881  } // UpdateRegistry()
882 
883  /////////////////////////////////////////////////////////////////////////////
884  /// return kFALSE if option "-l" was specified as main programm command arg
885 
886  bool NeedSplash()
887  {
888  static bool once = true;
889  if (!once || gROOT->IsBatch() || !gApplication) return false;
891  if ((arg != "root") && (arg != "rootn") &&
892  (arg != "root.exe") && (arg != "rootn.exe")) return false;
893  for(int i=1; i<gApplication->Argc(); i++) {
894  arg = gApplication->Argv(i);
895  arg.Strip(TString::kBoth);
896  if ((arg == "-l") || (arg == "-b")) {
897  return false;
898  }
899  }
900  if (once) {
901  once = false;
902  return true;
903  }
904  return false;
905  }
906 
907  /////////////////////////////////////////////////////////////////////////////
908 
909  static void SetConsoleWindowName()
910  {
911  char pszNewWindowTitle[1024]; // contains fabricated WindowTitle
912  char pszOldWindowTitle[1024]; // contains original WindowTitle
913  HANDLE hStdout;
914  CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
915 
916  if (!::GetConsoleTitle(pszOldWindowTitle, 1024))
917  return;
918  // format a "unique" NewWindowTitle
919  wsprintf(pszNewWindowTitle,"%d/%d", ::GetTickCount(), ::GetCurrentProcessId());
920  // change current window title
921  if (!::SetConsoleTitle(pszNewWindowTitle))
922  return;
923  // ensure window title has been updated
924  ::Sleep(40);
925  // look for NewWindowTitle
926  gConsoleWindow = (ULong_t)::FindWindow(0, pszNewWindowTitle);
927  if (gConsoleWindow) {
928  // restore original window title
929  ::ShowWindow((HWND)gConsoleWindow, SW_RESTORE);
930  //::SetForegroundWindow((HWND)gConsoleWindow);
931  ::SetConsoleTitle("ROOT session");
932  }
933  hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
934  ::SetConsoleMode(hStdout, ENABLE_PROCESSED_OUTPUT |
935  ENABLE_WRAP_AT_EOL_OUTPUT);
936  if (!::GetConsoleScreenBufferInfo(hStdout, &csbiInfo))
937  return;
938  Gl_setwidth(csbiInfo.dwMaximumWindowSize.X);
939  }
940 
941 } // end unnamed namespace
942 
943 
944 ///////////////////////////////////////////////////////////////////////////////
946 
948 
949 ////////////////////////////////////////////////////////////////////////////////
950 ///
951 
953 {
954  TSignalHandler *sh;
955  TIter next(fSignalHandler);
956  ESignals s;
957 
958  while (sh = (TSignalHandler*)next()) {
959  s = sh->GetSignal();
960  if (s == kSigInterrupt) {
961  sh->Notify();
962  Throw(SIGINT);
963  return kTRUE;
964  }
965  }
966  return kFALSE;
967 }
968 
969 ////////////////////////////////////////////////////////////////////////////////
970 /// ctor
971 
972 TWinNTSystem::TWinNTSystem() : TSystem("WinNT", "WinNT System"),
973 fGUIThreadHandle(0), fGUIThreadId(0)
974 {
975  fhProcess = ::GetCurrentProcess();
976  fDirNameBuffer = 0;
977 
978  WSADATA WSAData;
979  int initwinsock = 0;
980 
981  if (initwinsock = ::WSAStartup(MAKEWORD(2, 0), &WSAData)) {
982  Error("TWinNTSystem()","Starting sockets failed");
983  }
984 
985  // use ::MessageBeep by default for TWinNTSystem
986  fBeepDuration = 1;
987  fBeepFreq = 0;
988  if (gEnv) {
989  fBeepDuration = gEnv->GetValue("Root.System.BeepDuration", 1);
990  fBeepFreq = gEnv->GetValue("Root.System.BeepFreq", 0);
991  }
992 
993  char *buf = new char[MAX_MODULE_NAME32 + 1];
994 
995 #ifdef ROOTPREFIX
996  if (gSystem->Getenv("ROOTIGNOREPREFIX") {
997 #endif
998  // set ROOTSYS
999  HMODULE hModCore = ::GetModuleHandle("libCore.dll");
1000  if (hModCore) {
1001  ::GetModuleFileName(hModCore, buf, MAX_MODULE_NAME32 + 1);
1002  char *pLibName = strstr(buf, "libCore.dll");
1003  if (pLibName) {
1004  --pLibName; // skip trailing \\ or /
1005  while (--pLibName >= buf && *pLibName != '\\' && *pLibName != '/');
1006  *pLibName = 0; // replace trailing \\ or / with 0
1007  TString check_path = buf;
1008  check_path += "\\etc";
1009  // look for $ROOTSYS (it should contain the "etc" subdirectory)
1010  while (buf[0] && GetFileAttributes(check_path.Data()) == INVALID_FILE_ATTRIBUTES) {
1011  while (--pLibName >= buf && *pLibName != '\\' && *pLibName != '/');
1012  *pLibName = 0;
1013  check_path = buf;
1014  check_path += "\\etc";
1015  }
1016  if (buf[0]) {
1017  Setenv("ROOTSYS", buf);
1018  TString path = buf;
1019  path += "\\bin;";
1020  path += Getenv("PATH");
1021  Setenv("PATH", path.Data());
1022  }
1023  }
1024  }
1025 #ifdef ROOTPREFIX
1026  }
1027 #endif
1028 
1029  UpdateRegistry(this, buf);
1030 
1031  delete [] buf;
1032 }
1033 
1034 ////////////////////////////////////////////////////////////////////////////////
1035 /// dtor
1036 
1038 {
1039  // Revert back the accuracy of Sleep() without needing to link to winmm.lib
1040  typedef UINT (WINAPI* LPTIMEENDPERIOD)( UINT uPeriod );
1041  HINSTANCE hInstWinMM = LoadLibrary( "winmm.dll" );
1042  if( hInstWinMM ) {
1043  LPTIMEENDPERIOD pTimeEndPeriod = (LPTIMEENDPERIOD)GetProcAddress( hInstWinMM, "timeEndPeriod" );
1044  if( NULL != pTimeEndPeriod )
1045  pTimeEndPeriod(1);
1046  FreeLibrary(hInstWinMM);
1047  }
1048  // Clean up the WinSocket connectios
1049  ::WSACleanup();
1050 
1051  if (fDirNameBuffer) {
1052  delete [] fDirNameBuffer;
1053  fDirNameBuffer = 0;
1054  }
1055 
1056  if (gGlobalEvent) {
1057  ::ResetEvent(gGlobalEvent);
1058  ::CloseHandle(gGlobalEvent);
1059  gGlobalEvent = 0;
1060  }
1061  if (gTimerThreadHandle) {
1062  ::TerminateThread(gTimerThreadHandle, 0);
1063  ::CloseHandle(gTimerThreadHandle);
1064  }
1065 }
1066 
1067 ////////////////////////////////////////////////////////////////////////////////
1068 /// Initialize WinNT system interface.
1069 
1071 {
1072  const char *dir = 0;
1073 
1074  if (TSystem::Init()) {
1075  return kTRUE;
1076  }
1077 
1078  fReadmask = new TFdSet;
1079  fWritemask = new TFdSet;
1080  fReadready = new TFdSet;
1081  fWriteready = new TFdSet;
1082  fSignals = new TFdSet;
1083  fNfd = 0;
1084 
1085  //--- install default handlers
1086  // Actually: don't. If we want a stack trace we need a context for the
1087  // signal. Signals don't have one. If we don't handle them, Windows will
1088  // raise an exception, which has a context, and which is handled by
1089  // ExceptionFilter.
1090  /*
1091  WinNTSignal(kSigChild, SigHandler);
1092  WinNTSignal(kSigBus, SigHandler);
1093  WinNTSignal(kSigSegmentationViolation, SigHandler);
1094  WinNTSignal(kSigIllegalInstruction, SigHandler);
1095  WinNTSignal(kSigSystem, SigHandler);
1096  WinNTSignal(kSigPipe, SigHandler);
1097  WinNTSignal(kSigAlarm, SigHandler);
1098  WinNTSignal(kSigFloatingException, SigHandler);
1099  */
1100  ::SetUnhandledExceptionFilter(ExceptionFilter);
1101 
1102  fSigcnt = 0;
1103 
1104  // This is a fallback in case TROOT::GetRootSys() can't determine ROOTSYS
1105  static char lpFilename[MAX_PATH];
1106  if (::GetModuleFileName(
1107  NULL, // handle to module to find filename for
1108  lpFilename, // pointer to buffer to receive module path
1109  sizeof(lpFilename))) { // size of buffer, in characters
1110  const char *dirName = DirName(DirName(lpFilename));
1111  gRootDir = StrDup(dirName);
1112  } else {
1113  gRootDir = 0;
1114  }
1115 
1116  // Increase the accuracy of Sleep() without needing to link to winmm.lib
1117  typedef UINT (WINAPI* LPTIMEBEGINPERIOD)( UINT uPeriod );
1118  HINSTANCE hInstWinMM = LoadLibrary( "winmm.dll" );
1119  if( hInstWinMM ) {
1120  LPTIMEBEGINPERIOD pTimeBeginPeriod = (LPTIMEBEGINPERIOD)GetProcAddress( hInstWinMM, "timeBeginPeriod" );
1121  if( NULL != pTimeBeginPeriod )
1122  pTimeBeginPeriod(1);
1123  FreeLibrary(hInstWinMM);
1124  }
1125  gTimerThreadHandle = ::CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)ThreadStub,
1126  this, NULL, NULL);
1127 
1128  gGlobalEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
1129  fGUIThreadHandle = ::CreateThread( NULL, 0, &GUIThreadMessageProcessingLoop, 0, 0, &fGUIThreadId );
1130 
1131  char *buf = new char[MAX_MODULE_NAME32 + 1];
1132  HMODULE hModCore = ::GetModuleHandle("libCore.dll");
1133  if (hModCore) {
1134  ::GetModuleFileName(hModCore, buf, MAX_MODULE_NAME32 + 1);
1135  char *pLibName = strstr(buf, "libCore.dll");
1136  --pLibName; // remove trailing \\ or /
1137  *pLibName = 0;
1138  // add the directory containing libCore.dll in the dynamic search path
1139  if (buf[0]) AddDynamicPath(buf);
1140  }
1141  delete [] buf;
1142  SetConsoleWindowName();
1144  fFirstFile = kTRUE;
1145 
1146  return kFALSE;
1147 }
1148 
1149 //---- Misc --------------------------------------------------------------------
1150 
1151 ////////////////////////////////////////////////////////////////////////////////
1152 /// Base name of a file name. Base name of /user/root is root.
1153 /// But the base name of '/' is '/'
1154 /// 'c:\' is 'c:\'
1155 
1156 const char *TWinNTSystem::BaseName(const char *name)
1157 {
1158  // BB 28/10/05 : Removed (commented out) StrDup() :
1159  // - To get same behaviour on Windows and on Linux
1160  // - To avoid the need to use #ifdefs
1161  // - Solve memory leaks (mainly in TTF::SetTextFont())
1162  // No need for the calling routine to use free() anymore.
1163 
1164  if (name) {
1165  int idx = 0;
1166  const char *symbol=name;
1167 
1168  // Skip leading blanks
1169  while ( (*symbol == ' ' || *symbol == '\t') && *symbol) symbol++;
1170 
1171  if (*symbol) {
1172  if (isalpha(symbol[idx]) && symbol[idx+1] == ':') idx = 2;
1173  if ( (symbol[idx] == '/' || symbol[idx] == '\\') && symbol[idx+1] == '\0') {
1174  //return StrDup(symbol);
1175  return symbol;
1176  }
1177  } else {
1178  Error("BaseName", "name = 0");
1179  return 0;
1180  }
1181  char *cp;
1182  char *bslash = (char *)strrchr(&symbol[idx],'\\');
1183  char *rslash = (char *)strrchr(&symbol[idx],'/');
1184  if (cp = (std::max)(rslash, bslash)) {
1185  //return StrDup(++cp);
1186  return ++cp;
1187  }
1188  //return StrDup(&symbol[idx]);
1189  return &symbol[idx];
1190  }
1191  Error("BaseName", "name = 0");
1192  return 0;
1193 }
1194 
1195 ////////////////////////////////////////////////////////////////////////////////
1196 /// Set the application name (from command line, argv[0]) and copy it in
1197 /// gProgName. Copy the application pathname in gProgPath.
1198 
1200 {
1201  ULong_t idot = 0;
1202  char *dot = 0;
1203  char *progname;
1204  char *fullname = 0; // the program name with extension
1205 
1206  // On command prompt the progname can be supplied with no extension (under Windows)
1207  ULong_t namelen=name ? strlen(name) : 0;
1208  if (name && namelen > 0) {
1209  // Check whether the name contains "extention"
1210  fullname = new char[namelen+5];
1211  strlcpy(fullname, name,namelen+5);
1212  if ( !strrchr(fullname, '.') )
1213  strlcat(fullname, ".exe",namelen+5);
1214 
1215  progname = StrDup(BaseName(fullname));
1216  dot = strrchr(progname, '.');
1217  idot = dot ? (ULong_t)(dot - progname) : strlen(progname);
1218 
1219  char *which = 0;
1220 
1221  if (IsAbsoluteFileName(fullname) && !AccessPathName(fullname)) {
1222  which = StrDup(fullname);
1223  } else {
1224  which = Which(Form("%s;%s", WorkingDirectory(), Getenv("PATH")), progname);
1225  }
1226 
1227  if (which) {
1228  TString dirname;
1229  char driveletter = DriveName(which);
1230  const char *d = DirName(which);
1231 
1232  if (driveletter) {
1233  dirname.Form("%c:%s", driveletter, d);
1234  } else {
1235  dirname.Form("%s", d);
1236  }
1237 
1238  gProgPath = StrDup(dirname);
1239  } else {
1240  // Do not issue a warning - ROOT is not using gProgPath anyway.
1241  // Warning("SetProgname",
1242  // "Cannot find this program named \"%s\" (Did you create a TApplication? Is this program in your %%PATH%%?)",
1243  // fullname);
1245  }
1246 
1247  // Cut the extension for progname off
1248  progname[idot] = '\0';
1249  gProgName = StrDup(progname);
1250  if (which) delete [] which;
1251  delete[] fullname;
1252  delete[] progname;
1253  }
1254  if (::NeedSplash()) {
1256  }
1257 }
1258 
1259 ////////////////////////////////////////////////////////////////////////////////
1260 /// Return system error string.
1261 
1263 {
1264  Int_t err = GetErrno();
1265  if (err == 0 && GetLastErrorString() != "")
1266  return GetLastErrorString();
1267  if (err < 0 || err >= sys_nerr) {
1268  static TString error_msg;
1269  error_msg.Form("errno out of range %d", err);
1270  return error_msg;
1271  }
1272  return sys_errlist[err];
1273 }
1274 
1275 ////////////////////////////////////////////////////////////////////////////////
1276 /// Return the system's host name.
1277 
1279 {
1280  if (fHostname == "")
1281  fHostname = ::getenv("COMPUTERNAME");
1282  if (fHostname == "") {
1283  // This requires a DNS query - but we need it for fallback
1284  char hn[64];
1285  DWORD il = sizeof(hn);
1286  ::GetComputerName(hn, &il);
1287  fHostname = hn;
1288  }
1289  return fHostname;
1290 }
1291 
1292 ////////////////////////////////////////////////////////////////////////////////
1293 /// Beep. If freq==0 (the default for TWinNTSystem), use ::MessageBeep.
1294 /// Otherwise ::Beep with freq and duration.
1295 
1296 void TWinNTSystem::DoBeep(Int_t freq /*=-1*/, Int_t duration /*=-1*/) const
1297 {
1298  if (freq == 0) {
1299  ::MessageBeep(-1);
1300  return;
1301  }
1302  if (freq < 37) freq = 440;
1303  if (duration < 0) duration = 100;
1304  ::Beep(freq, duration);
1305 }
1306 
1307 ////////////////////////////////////////////////////////////////////////////////
1308 /// Set the (static part of) the event handler func for GUI messages.
1309 
1311 {
1312  gGUIThreadMsgFunc = func;
1313 }
1314 
1315 ////////////////////////////////////////////////////////////////////////////////
1316 /// Hook to tell TSystem that the TApplication object has been created.
1317 
1319 {
1320  // send a dummy message to the GUI thread to kick it into life
1321  ::PostThreadMessage(fGUIThreadId, 0, NULL, 0L);
1322 }
1323 
1324 
1325 //---- EventLoop ---------------------------------------------------------------
1326 
1327 ////////////////////////////////////////////////////////////////////////////////
1328 /// Add a file handler to the list of system file handlers. Only adds
1329 /// the handler if it is not already in the list of file handlers.
1330 
1332 {
1334  if (h) {
1335  int fd = h->GetFd();
1336  if (!fd) return;
1337 
1338  if (h->HasReadInterest()) {
1339  fReadmask->Set(fd);
1340  }
1341  if (h->HasWriteInterest()) {
1342  fWritemask->Set(fd);
1343  }
1344  }
1345 }
1346 
1347 ////////////////////////////////////////////////////////////////////////////////
1348 /// Remove a file handler from the list of file handlers. Returns
1349 /// the handler or 0 if the handler was not in the list of file handlers.
1350 
1352 {
1353  if (!h) return 0;
1354 
1356  if (oh) { // found
1357  fReadmask->Clr(h->GetFd());
1358  fWritemask->Clr(h->GetFd());
1359  }
1360  return oh;
1361 }
1362 
1363 ////////////////////////////////////////////////////////////////////////////////
1364 /// Add a signal handler to list of system signal handlers. Only adds
1365 /// the handler if it is not already in the list of signal handlers.
1366 
1368 {
1369  Bool_t set_console = kFALSE;
1370  ESignals sig = h->GetSignal();
1371 
1372  if (sig == kSigInterrupt) {
1373  set_console = kTRUE;
1374  TSignalHandler *hs;
1375  TIter next(fSignalHandler);
1376 
1377  while ((hs = (TSignalHandler*) next())) {
1378  if (hs->GetSignal() == kSigInterrupt)
1379  set_console = kFALSE;
1380  }
1381  }
1383 
1384  // Add our handler to the list of the console handlers
1385  if (set_console)
1386  ::SetConsoleCtrlHandler((PHANDLER_ROUTINE)ConsoleSigHandler, TRUE);
1387  else
1388  WinNTSignal(h->GetSignal(), SigHandler);
1389 }
1390 
1391 ////////////////////////////////////////////////////////////////////////////////
1392 /// Remove a signal handler from list of signal handlers. Returns
1393 /// the handler or 0 if the handler was not in the list of signal handlers.
1394 
1396 {
1397  if (!h) return 0;
1398 
1399  int sig = h->GetSignal();
1400 
1401  if (sig = kSigInterrupt) {
1402  Bool_t last = kTRUE;
1403  TSignalHandler *hs;
1404  TIter next(fSignalHandler);
1405 
1406  while ((hs = (TSignalHandler*) next())) {
1407  if (hs->GetSignal() == kSigInterrupt)
1408  last = kFALSE;
1409  }
1410  // Remove our handler from the list of the console handlers
1411  if (last)
1412  ::SetConsoleCtrlHandler((PHANDLER_ROUTINE)ConsoleSigHandler, FALSE);
1413  }
1414  return TSystem::RemoveSignalHandler(h);
1415 }
1416 
1417 ////////////////////////////////////////////////////////////////////////////////
1418 /// If reset is true reset the signal handler for the specified signal
1419 /// to the default handler, else restore previous behaviour.
1420 
1422 {
1423  //FIXME!
1424 }
1425 
1426 ////////////////////////////////////////////////////////////////////////////////
1427 /// Reset signals handlers to previous behaviour.
1428 
1430 {
1431  //FIXME!
1432 }
1433 
1434 ////////////////////////////////////////////////////////////////////////////////
1435 /// If ignore is true ignore the specified signal, else restore previous
1436 /// behaviour.
1437 
1439 {
1440  // FIXME!
1441 }
1442 
1443 ////////////////////////////////////////////////////////////////////////////////
1444 /// Print a stack trace, if gEnv entry "Root.Stacktrace" is unset or 1,
1445 /// and if the image helper functions can be found (see InitImagehlpFunctions()).
1446 /// The stack trace is printed for each thread; if fgXcptContext is set (e.g.
1447 /// because there was an exception) use it to define the current thread's context.
1448 /// For each frame in the stack, the frame's module name, the frame's function
1449 /// name, and the frame's line number are printed.
1450 
1452 {
1453  if (!gEnv->GetValue("Root.Stacktrace", 1))
1454  return;
1455 
1456  HANDLE snapshot = ::CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD,::GetCurrentProcessId());
1457 
1458  std::cerr.flush();
1459  fflush (stderr);
1460 
1461  if (!InitImagehlpFunctions()) {
1462  std::cerr << "No stack trace: cannot find (functions in) dbghelp.dll!" << std::endl;
1463  return;
1464  }
1465 
1466  // what system are we on?
1467  SYSTEM_INFO sysInfo;
1468  ::GetSystemInfo(&sysInfo);
1469  DWORD machineType = IMAGE_FILE_MACHINE_I386;
1470  switch (sysInfo.wProcessorArchitecture) {
1471  case PROCESSOR_ARCHITECTURE_AMD64:
1472  machineType = IMAGE_FILE_MACHINE_AMD64;
1473  break;
1474  case PROCESSOR_ARCHITECTURE_IA64:
1475  machineType = IMAGE_FILE_MACHINE_IA64;
1476  break;
1477  }
1478 
1479  DWORD currentThreadID = ::GetCurrentThreadId();
1480  DWORD currentProcessID = ::GetCurrentProcessId();
1481 
1482  if (snapshot == INVALID_HANDLE_VALUE) return;
1483 
1484  THREADENTRY32 threadentry;
1485  threadentry.dwSize = sizeof(THREADENTRY32);
1486  if (!::Thread32First(snapshot, &threadentry)) return;
1487 
1488  std::cerr << std::endl << "==========================================" << std::endl;
1489  std::cerr << "=============== STACKTRACE ===============" << std::endl;
1490  std::cerr << "==========================================" << std::endl << std::endl;
1491  UInt_t iThread = 0;
1492  do {
1493  if (threadentry.th32OwnerProcessID != currentProcessID)
1494  continue;
1495  HANDLE thread = ::OpenThread(THREAD_GET_CONTEXT|THREAD_SUSPEND_RESUME|THREAD_QUERY_INFORMATION,
1496  FALSE, threadentry.th32ThreadID);
1497  CONTEXT context;
1498  memset(&context, 0, sizeof(CONTEXT));
1499 
1500  if (threadentry.th32ThreadID != currentThreadID) {
1501  ::SuspendThread(thread);
1502  context.ContextFlags = CONTEXT_ALL;
1503  ::GetThreadContext(thread, &context);
1504  ::ResumeThread(thread);
1505  } else {
1506  if (fgXcptContext) {
1507  context = *fgXcptContext;
1508  } else {
1509  typedef void (WINAPI *RTLCCTXT)(PCONTEXT);
1510  RTLCCTXT p2RtlCCtxt = (RTLCCTXT) ::GetProcAddress(
1511  GetModuleHandle("kernel32.dll"), "RtlCaptureContext");
1512  if (p2RtlCCtxt) {
1513  context.ContextFlags = CONTEXT_ALL;
1514  p2RtlCCtxt(&context);
1515  }
1516  }
1517  }
1518 
1519  STACKFRAME64 frame;
1520  ::ZeroMemory(&frame, sizeof(frame));
1521 
1522  frame.AddrPC.Mode = AddrModeFlat;
1523  frame.AddrFrame.Mode = AddrModeFlat;
1524  frame.AddrStack.Mode = AddrModeFlat;
1525 #if defined(_M_IX86)
1526  frame.AddrPC.Offset = context.Eip;
1527  frame.AddrFrame.Offset = context.Ebp;
1528  frame.AddrStack.Offset = context.Esp;
1529 #elif defined(_M_X64)
1530  frame.AddrPC.Offset = context.Rip;
1531  frame.AddrFrame.Offset = context.Rsp;
1532  frame.AddrStack.Offset = context.Rsp;
1533 #elif defined(_M_IA64)
1534  frame.AddrPC.Offset = context.StIIP;
1535  frame.AddrFrame.Offset = context.IntSp;
1536  frame.AddrStack.Offset = context.IntSp;
1537  frame.AddrBStore.Offset= context.RsBSP;
1538 #else
1539  std::cerr << "Stack traces not supported on your architecture yet." << std::endl;
1540  return;
1541 #endif
1542 
1543  Bool_t bFirst = kTRUE;
1544  while (_StackWalk64(machineType, (HANDLE)::GetCurrentProcess(), thread, (LPSTACKFRAME64)&frame,
1545  (LPVOID)&context, (PREAD_PROCESS_MEMORY_ROUTINE)NULL, (PFUNCTION_TABLE_ACCESS_ROUTINE)_SymFunctionTableAccess64,
1546  (PGET_MODULE_BASE_ROUTINE)_SymGetModuleBase64, NULL)) {
1547  if (bFirst)
1548  std::cerr << std::endl << "================ Thread " << iThread++ << " ================" << std::endl;
1549  if (!bFirst || threadentry.th32ThreadID != currentThreadID) {
1550  const std::string moduleName = GetModuleName(frame.AddrPC.Offset);
1551  const std::string functionName = GetFunctionName(frame.AddrPC.Offset);
1552  std::cerr << " " << moduleName << functionName << std::endl;
1553  }
1554  bFirst = kFALSE;
1555  }
1556  ::CloseHandle(thread);
1557  } while (::Thread32Next(snapshot, &threadentry));
1558 
1559  std::cerr << std::endl << "==========================================" << std::endl;
1560  std::cerr << "============= END STACKTRACE =============" << std::endl;
1561  std::cerr << "==========================================" << std::endl << std::endl;
1562  ::CloseHandle(snapshot);
1563  _SymCleanup(GetCurrentProcess());
1564 }
1565 
1566 ////////////////////////////////////////////////////////////////////////////////
1567 /// Return the bitmap of conditions that trigger a floating point exception.
1568 
1570 {
1571  Int_t mask = 0;
1572  UInt_t oldmask = _statusfp( );
1573 
1574  if (oldmask & _EM_INVALID ) mask |= kInvalid;
1575  if (oldmask & _EM_ZERODIVIDE) mask |= kDivByZero;
1576  if (oldmask & _EM_OVERFLOW ) mask |= kOverflow;
1577  if (oldmask & _EM_UNDERFLOW) mask |= kUnderflow;
1578  if (oldmask & _EM_INEXACT ) mask |= kInexact;
1579 
1580  return mask;
1581 }
1582 
1583 ////////////////////////////////////////////////////////////////////////////////
1584 /// Set which conditions trigger a floating point exception.
1585 /// Return the previous set of conditions.
1586 
1588 {
1589  Int_t old = GetFPEMask();
1590 
1591  UInt_t newm = 0;
1592  if (mask & kInvalid ) newm |= _EM_INVALID;
1593  if (mask & kDivByZero) newm |= _EM_ZERODIVIDE;
1594  if (mask & kOverflow ) newm |= _EM_OVERFLOW;
1595  if (mask & kUnderflow) newm |= _EM_UNDERFLOW;
1596  if (mask & kInexact ) newm |= _EM_INEXACT;
1597 
1598  UInt_t cm = ::_statusfp();
1599  cm &= ~newm;
1600  ::_controlfp(cm , _MCW_EM);
1601 
1602  return old;
1603 }
1604 
1605 ////////////////////////////////////////////////////////////////////////////////
1606 /// process pending events, i.e. DispatchOneEvent(kTRUE)
1607 
1609 {
1610  return TSystem::ProcessEvents();
1611 }
1612 
1613 ////////////////////////////////////////////////////////////////////////////////
1614 /// Dispatch a single event in TApplication::Run() loop
1615 
1617 {
1618  // check for keyboard events
1619  if (pendingOnly && gGlobalEvent) ::SetEvent(gGlobalEvent);
1620 
1621  Bool_t pollOnce = pendingOnly;
1622 
1623  while (1) {
1624  if (_kbhit()) {
1625  if (gROOT->GetApplication()) {
1627  if (gSplash) { // terminate splash window after first key press
1628  delete gSplash;
1629  gSplash = 0;
1630  }
1631  if (!pendingOnly) {
1632  return;
1633  }
1634  }
1635  }
1636  if (gROOT->IsLineProcessing() && (!gVirtualX || !gVirtualX->IsCmdThread())) {
1637  if (!pendingOnly) {
1638  // yield execution to another thread that is ready to run
1639  // if no other thread is ready, sleep 1 ms before to return
1640  if (gGlobalEvent) {
1641  ::WaitForSingleObject(gGlobalEvent, 1);
1642  ::ResetEvent(gGlobalEvent);
1643  }
1644  return;
1645  }
1646  }
1647  // first handle any GUI events
1648  if (gXDisplay && !gROOT->IsBatch()) {
1649  if (gXDisplay->Notify()) {
1650  if (!pendingOnly) {
1651  return;
1652  }
1653  }
1654  }
1655 
1656  // check for file descriptors ready for reading/writing
1657  if ((fNfd > 0) && fFileHandler && (fFileHandler->GetSize() > 0)) {
1658  if (CheckDescriptors()) {
1659  if (!pendingOnly) {
1660  return;
1661  }
1662  }
1663  }
1664  fNfd = 0;
1665  fReadready->Zero();
1666  fWriteready->Zero();
1667 
1668  if (pendingOnly && !pollOnce)
1669  return;
1670 
1671  // check synchronous signals
1672  if (fSigcnt > 0 && fSignalHandler->GetSize() > 0) {
1673  if (CheckSignals(kTRUE)) {
1674  if (!pendingOnly) {
1675  return;
1676  }
1677  }
1678  }
1679  fSigcnt = 0;
1680  fSignals->Zero();
1681 
1682  // handle past due timers
1683  Long_t nextto;
1684  if (fTimers && fTimers->GetSize() > 0) {
1685  if (DispatchTimers(kTRUE)) {
1686  // prevent timers from blocking the rest types of events
1687  nextto = NextTimeOut(kTRUE);
1688  if (nextto > (kItimerResolution>>1) || nextto == -1) {
1689  return;
1690  }
1691  }
1692  }
1693 
1694  // if in pendingOnly mode poll once file descriptor activity
1695  nextto = NextTimeOut(kTRUE);
1696  if (pendingOnly) {
1697  if (fFileHandler && fFileHandler->GetSize() == 0)
1698  return;
1699  nextto = 0;
1700  pollOnce = kFALSE;
1701  }
1702 
1703  if (fReadmask && !fReadmask->GetBits() &&
1704  fWritemask && !fWritemask->GetBits()) {
1705  // yield execution to another thread that is ready to run
1706  // if no other thread is ready, sleep 1 ms before to return
1707  if (!pendingOnly && gGlobalEvent) {
1708  ::WaitForSingleObject(gGlobalEvent, 1);
1709  ::ResetEvent(gGlobalEvent);
1710  }
1711  return;
1712  }
1713 
1714  *fReadready = *fReadmask;
1715  *fWriteready = *fWritemask;
1716 
1717  fNfd = WinNTSelect(fReadready, fWriteready, nextto);
1718 
1719  // serious error has happened -> reset all file descrptors
1720  if ((fNfd < 0) && (fNfd != -2)) {
1721  int rc, i;
1722 
1723  for (i = 0; i < fReadmask->GetCount(); i++) {
1724  TFdSet t;
1725  Int_t fd = fReadmask->GetFd(i);
1726  t.Set(fd);
1727  if (fReadmask->IsSet(fd)) {
1728  rc = WinNTSelect(&t, 0, 0);
1729  if (rc < 0 && rc != -2) {
1730  ::SysError("DispatchOneEvent", "select: read error on %d\n", fd);
1731  fReadmask->Clr(fd);
1732  }
1733  }
1734  }
1735 
1736  for (i = 0; i < fWritemask->GetCount(); i++) {
1737  TFdSet t;
1738  Int_t fd = fWritemask->GetFd(i);
1739  t.Set(fd);
1740 
1741  if (fWritemask->IsSet(fd)) {
1742  rc = WinNTSelect(0, &t, 0);
1743  if (rc < 0 && rc != -2) {
1744  ::SysError("DispatchOneEvent", "select: write error on %d\n", fd);
1745  fWritemask->Clr(fd);
1746  }
1747  }
1748  t.Clr(fd);
1749  }
1750  }
1751  }
1752 }
1753 
1754 ////////////////////////////////////////////////////////////////////////////////
1755 /// Exit from event loop.
1756 
1758 {
1760 }
1761 
1762 //---- handling of system events -----------------------------------------------
1763 ////////////////////////////////////////////////////////////////////////////////
1764 /// Handle and dispatch signals.
1765 
1767 {
1768  if (sig == kSigInterrupt) {
1769  fSignals->Set(sig);
1770  fSigcnt++;
1771  }
1772  else {
1773  StackTrace();
1774  if (TROOT::Initialized()) {
1775  ::Throw(sig);
1776  }
1777  Abort(-1);
1778  }
1779 
1780  // check a-synchronous signals
1781  if (fSigcnt > 0 && fSignalHandler->GetSize() > 0)
1783 }
1784 
1785 ////////////////////////////////////////////////////////////////////////////////
1786 /// Check if some signals were raised and call their Notify() member.
1787 
1789 {
1790  TSignalHandler *sh;
1791  Int_t sigdone = -1;
1792  {
1793  TIter next(fSignalHandler);
1794 
1795  while (sh = (TSignalHandler*)next()) {
1796  if (sync == sh->IsSync()) {
1797  ESignals sig = sh->GetSignal();
1798  if ((fSignals->IsSet(sig) && sigdone == -1) || sigdone == sig) {
1799  if (sigdone == -1) {
1800  fSignals->Clr(sig);
1801  sigdone = sig;
1802  fSigcnt--;
1803  }
1804  sh->Notify();
1805  }
1806  }
1807  }
1808  }
1809  if (sigdone != -1) return kTRUE;
1810 
1811  return kFALSE;
1812 }
1813 
1814 ////////////////////////////////////////////////////////////////////////////////
1815 /// Check if there is activity on some file descriptors and call their
1816 /// Notify() member.
1817 
1819 {
1820  TFileHandler *fh;
1821  Int_t fddone = -1;
1822  Bool_t read = kFALSE;
1823 
1825 
1826  while ((fh = (TFileHandler*) it.Next())) {
1827  Int_t fd = fh->GetFd();
1828  if (!fd) continue; // ignore TTermInputHandler
1829 
1830  if ((fReadready->IsSet(fd) && fddone == -1) ||
1831  (fddone == fd && read)) {
1832  if (fddone == -1) {
1833  fReadready->Clr(fd);
1834  fddone = fd;
1835  read = kTRUE;
1836  fNfd--;
1837  }
1838  fh->ReadNotify();
1839  }
1840  if ((fWriteready->IsSet(fd) && fddone == -1) ||
1841  (fddone == fd && !read)) {
1842  if (fddone == -1) {
1843  fWriteready->Clr(fd);
1844  fddone = fd;
1845  read = kFALSE;
1846  fNfd--;
1847  }
1848  fh->WriteNotify();
1849  }
1850  }
1851  if (fddone != -1) return kTRUE;
1852 
1853  return kFALSE;
1854 }
1855 
1856 //---- Directories -------------------------------------------------------------
1857 
1858 ////////////////////////////////////////////////////////////////////////////////
1859 /// Make a file system directory. Returns 0 in case of success and
1860 /// -1 if the directory could not be created (either already exists or
1861 /// illegal path name).
1862 /// If 'recursive' is true, makes parent directories as needed.
1863 
1864 int TWinNTSystem::mkdir(const char *name, Bool_t recursive)
1865 {
1866  if (recursive) {
1867  TString dirname = DirName(name);
1868  if (dirname.Length() == 0) {
1869  // well we should not have to make the root of the file system!
1870  // (and this avoid infinite recursions!)
1871  return 0;
1872  }
1873  if (IsAbsoluteFileName(name)) {
1874  // For some good reason DirName strips off the drive letter
1875  // (if present), we need it to make the directory on the
1876  // right disk, so let's put it back!
1877  const char driveletter = DriveName(name);
1878  if (driveletter) {
1879  dirname.Prepend(":");
1880  dirname.Prepend(driveletter);
1881  }
1882  }
1883  if (AccessPathName(dirname, kFileExists)) {
1884  int res = this->mkdir(dirname, kTRUE);
1885  if (res) return res;
1886  }
1887  if (!AccessPathName(name, kFileExists)) {
1888  return -1;
1889  }
1890  }
1891  return MakeDirectory(name);
1892 }
1893 
1894 ////////////////////////////////////////////////////////////////////////////////
1895 /// Make a WinNT file system directory. Returns 0 in case of success and
1896 /// -1 if the directory could not be created (either already exists or
1897 /// illegal path name).
1898 
1900 {
1901  TSystem *helper = FindHelper(name);
1902  if (helper) {
1903  return helper->MakeDirectory(name);
1904  }
1905  const char *proto = (strstr(name, "file:///")) ? "file://" : "file:";
1906 #ifdef WATCOM
1907  // It must be as follows
1908  if (!name) return 0;
1909  return ::mkdir(StripOffProto(name, proto));
1910 #else
1911  // but to be in line with TUnixSystem I did like this
1912  if (!name) return 0;
1913  return ::_mkdir(StripOffProto(name, proto));
1914 #endif
1915 }
1916 
1917 ////////////////////////////////////////////////////////////////////////////////
1918 /// Close a WinNT file system directory.
1919 
1921 {
1922  TSystem *helper = FindHelper(0, dirp);
1923  if (helper) {
1924  helper->FreeDirectory(dirp);
1925  return;
1926  }
1927 
1928  if (dirp) {
1929  ::FindClose(dirp);
1930  }
1931 }
1932 
1933 ////////////////////////////////////////////////////////////////////////////////
1934 /// Returns the next directory entry.
1935 
1936 const char *TWinNTSystem::GetDirEntry(void *dirp)
1937 {
1938  TSystem *helper = FindHelper(0, dirp);
1939  if (helper) {
1940  return helper->GetDirEntry(dirp);
1941  }
1942 
1943  if (dirp) {
1944  HANDLE searchFile = (HANDLE)dirp;
1945  if (fFirstFile) {
1946  // when calling TWinNTSystem::OpenDirectory(), the fFindFileData
1947  // structure is filled by a call to FindFirstFile().
1948  // So first returns this one, before calling FindNextFile()
1949  fFirstFile = kFALSE;
1950  return (const char *)fFindFileData.cFileName;
1951  }
1952  if (::FindNextFile(searchFile, &fFindFileData)) {
1953  return (const char *)fFindFileData.cFileName;
1954  }
1955  }
1956  return 0;
1957 }
1958 
1959 ////////////////////////////////////////////////////////////////////////////////
1960 /// Change directory.
1961 
1963 {
1964  Bool_t ret = (Bool_t) (::chdir(path) == 0);
1965  if (fWdpath != "")
1966  fWdpath = ""; // invalidate path cache
1967  return ret;
1968 }
1969 
1970 ////////////////////////////////////////////////////////////////////////////////
1971 ///
1972 /// Inline function to check for a double-backslash at the
1973 /// beginning of a string
1974 ///
1975 
1976 __inline BOOL DBL_BSLASH(LPCTSTR psz)
1977 {
1978  return (psz[0] == TEXT('\\') && psz[1] == TEXT('\\'));
1979 }
1980 
1981 ////////////////////////////////////////////////////////////////////////////////
1982 /// Returns TRUE if the given string is a UNC path.
1983 ///
1984 /// TRUE
1985 /// "\\foo\bar"
1986 /// "\\foo" <- careful
1987 /// "\\"
1988 /// FALSE
1989 /// "\foo"
1990 /// "foo"
1991 /// "c:\foo"
1992 
1993 BOOL PathIsUNC(LPCTSTR pszPath)
1994 {
1995  return DBL_BSLASH(pszPath);
1996 }
1997 
1998 #pragma data_seg(".text", "CODE")
1999 const TCHAR c_szColonSlash[] = TEXT(":\\");
2000 #pragma data_seg()
2001 
2002 ////////////////////////////////////////////////////////////////////////////////
2003 ///
2004 /// check if a path is a root
2005 ///
2006 /// returns:
2007 /// TRUE for "\" "X:\" "\\foo\asdf" "\\foo\"
2008 /// FALSE for others
2009 ///
2010 
2011 BOOL PathIsRoot(LPCTSTR pPath)
2012 {
2013  if (!IsDBCSLeadByte(*pPath)) {
2014  if (!lstrcmpi(pPath + 1, c_szColonSlash))
2015  // "X:\" case
2016  return TRUE;
2017  }
2018  if ((*pPath == TEXT('\\')) && (*(pPath + 1) == 0))
2019  // "\" case
2020  return TRUE;
2021  if (DBL_BSLASH(pPath)) {
2022  // smells like UNC name
2023  LPCTSTR p;
2024  int cBackslashes = 0;
2025  for (p = pPath + 2; *p; p = CharNext(p)) {
2026  if (*p == TEXT('\\') && (++cBackslashes > 1))
2027  return FALSE; // not a bare UNC name, therefore not a root dir
2028  }
2029  // end of string with only 1 more backslash
2030  // must be a bare UNC, which looks like a root dir
2031  return TRUE;
2032  }
2033  return FALSE;
2034 }
2035 
2036 ////////////////////////////////////////////////////////////////////////////////
2037 /// Open a directory. Returns 0 if directory does not exist.
2038 
2039 void *TWinNTSystem::OpenDirectory(const char *fdir)
2040 {
2041  TSystem *helper = FindHelper(fdir);
2042  if (helper) {
2043  return helper->OpenDirectory(fdir);
2044  }
2045 
2046  const char *proto = (strstr(fdir, "file:///")) ? "file://" : "file:";
2047  const char *sdir = StripOffProto(fdir, proto);
2048 
2049  char *dir = new char[MAX_PATH];
2050  if (IsShortcut(sdir)) {
2051  if (!ResolveShortCut(sdir, dir, MAX_PATH))
2052  strlcpy(dir, sdir,MAX_PATH);
2053  }
2054  else
2055  strlcpy(dir, sdir,MAX_PATH);
2056 
2057  int nche = strlen(dir)+3;
2058  char *entry = new char[nche];
2059  struct _stati64 finfo;
2060 
2061  if(PathIsUNC(dir)) {
2062  strlcpy(entry, dir,nche);
2063  if ((entry[strlen(dir)-1] == '/') || (entry[strlen(dir)-1] == '\\' )) {
2064  entry[strlen(dir)-1] = '\0';
2065  }
2066  if(PathIsRoot(entry)) {
2067  strlcat(entry,"\\",nche);
2068  }
2069  if (_stati64(entry, &finfo) < 0) {
2070  delete [] entry;
2071  delete [] dir;
2072  return 0;
2073  }
2074  }
2075  else {
2076  strlcpy(entry, dir,nche);
2077  if ((entry[strlen(dir)-1] == '/') || (entry[strlen(dir)-1] == '\\' )) {
2078  if(!PathIsRoot(entry))
2079  entry[strlen(dir)-1] = '\0';
2080  }
2081  if (_stati64(entry, &finfo) < 0) {
2082  delete [] entry;
2083  delete [] dir;
2084  return 0;
2085  }
2086  }
2087 
2088  if (finfo.st_mode & S_IFDIR) {
2089  strlcpy(entry, dir,nche);
2090  if (!(entry[strlen(dir)-1] == '/' || entry[strlen(dir)-1] == '\\' )) {
2091  strlcat(entry,"\\",nche);
2092  }
2093  strlcat(entry,"*",nche);
2094 
2095  HANDLE searchFile;
2096  searchFile = ::FindFirstFile(entry, &fFindFileData);
2097  if (searchFile == INVALID_HANDLE_VALUE) {
2098  ((TWinNTSystem *)gSystem)->Error( "Unable to find' for reading:", entry);
2099  delete [] entry;
2100  delete [] dir;
2101  return 0;
2102  }
2103  delete [] entry;
2104  delete [] dir;
2105  fFirstFile = kTRUE;
2106  return searchFile;
2107  } else {
2108  delete [] entry;
2109  delete [] dir;
2110  return 0;
2111  }
2112 }
2113 
2114 ////////////////////////////////////////////////////////////////////////////////
2115 /// Return the working directory for the default drive
2116 
2118 {
2119  return WorkingDirectory('\0');
2120 }
2121 
2122 //////////////////////////////////////////////////////////////////////////////
2123 /// Return the working directory for the default drive
2124 
2126 {
2127  char *wdpath = GetWorkingDirectory('\0');
2128  std::string cwd;
2129  if (wdpath) {
2130  cwd = wdpath;
2131  free(wdpath);
2132  }
2133  return cwd;
2134 }
2135 
2136 ////////////////////////////////////////////////////////////////////////////////
2137 /// Return working directory for the selected drive
2138 /// driveletter == 0 means return the working durectory for the default drive
2139 
2140 const char *TWinNTSystem::WorkingDirectory(char driveletter)
2141 {
2142  char *wdpath = GetWorkingDirectory(driveletter);
2143  if (wdpath) {
2144  fWdpath = wdpath;
2145 
2146  // Make sure the drive letter is upper case
2147  if (fWdpath[1] == ':')
2148  fWdpath[0] = toupper(fWdpath[0]);
2149 
2150  free(wdpath);
2151  }
2152  return fWdpath;
2153 }
2154 
2155 //////////////////////////////////////////////////////////////////////////////
2156 /// Return working directory for the selected drive (helper function).
2157 /// The caller must free the return value.
2158 
2159 char *TWinNTSystem::GetWorkingDirectory(char driveletter) const
2160 {
2161  char *wdpath = 0;
2162  char drive = driveletter ? toupper( driveletter ) - 'A' + 1 : 0;
2163 
2164  // don't use cache as user can call chdir() directly somewhere else
2165  //if (fWdpath != "" )
2166  // return fWdpath;
2167 
2168  if (!(wdpath = ::_getdcwd( (int)drive, wdpath, kMAXPATHLEN))) {
2169  free(wdpath);
2170  Warning("WorkingDirectory", "getcwd() failed");
2171  return 0;
2172  }
2173 
2174  return wdpath;
2175 }
2176 
2177 ////////////////////////////////////////////////////////////////////////////////
2178 /// Return the user's home directory.
2179 
2180 const char *TWinNTSystem::HomeDirectory(const char *userName)
2181 {
2182  static char mydir[kMAXPATHLEN] = "./";
2183  FillWithHomeDirectory(userName, mydir);
2184  return mydir;
2185 }
2186 
2187 //////////////////////////////////////////////////////////////////////////////
2188 /// Return the user's home directory.
2189 
2190 std::string TWinNTSystem::GetHomeDirectory(const char *userName) const
2191 {
2192  char mydir[kMAXPATHLEN] = "./";
2193  FillWithHomeDirectory(userName, mydir);
2194  return std::string(mydir);
2195 }
2196 
2197 //////////////////////////////////////////////////////////////////////////////
2198 /// Fill buffer with user's home directory.
2199 
2200 void TWinNTSystem::FillWithHomeDirectory(const char *userName, char *mydir) const
2201 {
2202  const char *h = 0;
2203  if (!(h = ::getenv("home"))) h = ::getenv("HOME");
2204 
2205  if (h) {
2206  strlcpy(mydir, h,kMAXPATHLEN);
2207  } else {
2208  // for Windows NT HOME might be defined as either $(HOMESHARE)/$(HOMEPATH)
2209  // or $(HOMEDRIVE)/$(HOMEPATH)
2210  h = ::getenv("HOMESHARE");
2211  if (!h) h = ::getenv("HOMEDRIVE");
2212  if (h) {
2213  strlcpy(mydir, h,kMAXPATHLEN);
2214  h = ::getenv("HOMEPATH");
2215  if(h) strlcat(mydir, h,kMAXPATHLEN);
2216  }
2217  // on Windows Vista HOME is usually defined as $(USERPROFILE)
2218  if (!h) {
2219  h = ::getenv("USERPROFILE");
2220  if (h) strlcpy(mydir, h,kMAXPATHLEN);
2221  }
2222  }
2223  // Make sure the drive letter is upper case
2224  if (mydir[1] == ':')
2225  mydir[0] = toupper(mydir[0]);
2226 }
2227 
2228 
2229 ////////////////////////////////////////////////////////////////////////////////
2230 /// Return a user configured or systemwide directory to create
2231 /// temporary files in.
2232 
2233 const char *TWinNTSystem::TempDirectory() const
2234 {
2235  const char *dir = gSystem->Getenv("TEMP");
2236  if (!dir) dir = gSystem->Getenv("TEMPDIR");
2237  if (!dir) dir = gSystem->Getenv("TEMP_DIR");
2238  if (!dir) dir = gSystem->Getenv("TMP");
2239  if (!dir) dir = gSystem->Getenv("TMPDIR");
2240  if (!dir) dir = gSystem->Getenv("TMP_DIR");
2241  if (!dir) dir = "c:\\";
2242 
2243  return dir;
2244 }
2245 
2246 ////////////////////////////////////////////////////////////////////////////////
2247 /// Create a secure temporary file by appending a unique
2248 /// 6 letter string to base. The file will be created in
2249 /// a standard (system) directory or in the directory
2250 /// provided in dir. The full filename is returned in base
2251 /// and a filepointer is returned for safely writing to the file
2252 /// (this avoids certain security problems). Returns 0 in case
2253 /// of error.
2254 
2255 FILE *TWinNTSystem::TempFileName(TString &base, const char *dir)
2256 {
2257  char tmpName[MAX_PATH];
2258 
2259  ::GetTempFileName(dir ? dir : TempDirectory(), base.Data(), 0, tmpName);
2260  base = tmpName;
2261  FILE *fp = fopen(tmpName, "w+");
2262 
2263  if (!fp) ::SysError("TempFileName", "error opening %s", tmpName);
2264 
2265  return fp;
2266 }
2267 
2268 //---- Paths & Files -----------------------------------------------------------
2269 
2270 ////////////////////////////////////////////////////////////////////////////////
2271 /// Get list of volumes (drives) mounted on the system.
2272 /// The returned TList must be deleted by the user using "delete".
2273 
2275 {
2276  Int_t curdrive;
2277  UInt_t type;
2278  TString sDrive, sType;
2279  char szFs[32];
2280 
2281  if (!opt || !opt[0]) {
2282  return 0;
2283  }
2284 
2285  // prevent the system dialog box to pop-up if a drive is empty
2286  UINT nOldErrorMode = ::SetErrorMode(SEM_FAILCRITICALERRORS);
2287  TList *drives = new TList();
2288  drives->SetOwner();
2289  // Save current drive
2290  curdrive = _getdrive();
2291  if (strstr(opt, "cur")) {
2292  *szFs='\0';
2293  sDrive.Form("%c:", (curdrive + 'A' - 1));
2294  sType.Form("Unknown Drive (%s)", sDrive.Data());
2295  ::GetVolumeInformation(Form("%s\\", sDrive.Data()), NULL, 0, NULL, NULL,
2296  NULL, (LPSTR)szFs, 32);
2297  type = ::GetDriveType(sDrive.Data());
2298  switch (type) {
2299  case DRIVE_UNKNOWN:
2300  case DRIVE_NO_ROOT_DIR:
2301  break;
2302  case DRIVE_REMOVABLE:
2303  sType.Form("Removable Disk (%s)", sDrive.Data());
2304  break;
2305  case DRIVE_FIXED:
2306  sType.Form("Local Disk (%s)", sDrive.Data());
2307  break;
2308  case DRIVE_REMOTE:
2309  sType.Form("Network Drive (%s) (%s)", szFs, sDrive.Data());
2310  break;
2311  case DRIVE_CDROM:
2312  sType.Form("CD/DVD Drive (%s)", sDrive.Data());
2313  break;
2314  case DRIVE_RAMDISK:
2315  sType.Form("RAM Disk (%s)", sDrive.Data());
2316  break;
2317  }
2318  drives->Add(new TNamed(sDrive.Data(), sType.Data()));
2319  }
2320  else if (strstr(opt, "all")) {
2321  TCHAR szTemp[512];
2322  szTemp[0] = '\0';
2323  if (::GetLogicalDriveStrings(511, szTemp)) {
2324  TCHAR szDrive[3] = TEXT(" :");
2325  TCHAR* p = szTemp;
2326  do {
2327  // Copy the drive letter to the template string
2328  *szDrive = *p;
2329  *szFs='\0';
2330  sDrive.Form("%s", szDrive);
2331  // skip floppy drives, to avoid accessing them each time...
2332  if ((sDrive == "A:") || (sDrive == "B:")) {
2333  while (*p++);
2334  continue;
2335  }
2336  sType.Form("Unknown Drive (%s)", sDrive.Data());
2337  ::GetVolumeInformation(Form("%s\\", sDrive.Data()), NULL, 0, NULL,
2338  NULL, NULL, (LPSTR)szFs, 32);
2339  type = ::GetDriveType(sDrive.Data());
2340  switch (type) {
2341  case DRIVE_UNKNOWN:
2342  case DRIVE_NO_ROOT_DIR:
2343  break;
2344  case DRIVE_REMOVABLE:
2345  sType.Form("Removable Disk (%s)", sDrive.Data());
2346  break;
2347  case DRIVE_FIXED:
2348  sType.Form("Local Disk (%s)", sDrive.Data());
2349  break;
2350  case DRIVE_REMOTE:
2351  sType.Form("Network Drive (%s) (%s)", szFs, sDrive.Data());
2352  break;
2353  case DRIVE_CDROM:
2354  sType.Form("CD/DVD Drive (%s)", sDrive.Data());
2355  break;
2356  case DRIVE_RAMDISK:
2357  sType.Form("RAM Disk (%s)", sDrive.Data());
2358  break;
2359  }
2360  drives->Add(new TNamed(sDrive.Data(), sType.Data()));
2361  // Go to the next NULL character.
2362  while (*p++);
2363  } while (*p); // end of string
2364  }
2365  }
2366  // restore previous error mode
2367  ::SetErrorMode(nOldErrorMode);
2368  return drives;
2369 }
2370 
2371 ////////////////////////////////////////////////////////////////////////////////
2372 /// Return the directory name in pathname. DirName of c:/user/root is /user.
2373 /// It creates output with 'new char []' operator. Returned string has to
2374 /// be deleted.
2375 
2376 const char *TWinNTSystem::DirName(const char *pathname)
2377 {
2378  // Delete old buffer
2379  if (fDirNameBuffer) {
2380  // delete [] fDirNameBuffer;
2381  fDirNameBuffer = 0;
2382  }
2383 
2384  // Create a buffer to keep the path name
2385  if (pathname) {
2386  if (strchr(pathname, '/') || strchr(pathname, '\\')) {
2387  const char *rslash = strrchr(pathname, '/');
2388  const char *bslash = strrchr(pathname, '\\');
2389  const char *r = (std::max)(rslash, bslash);
2390  const char *ptr = pathname;
2391  while (ptr <= r) {
2392  if (*ptr == ':') {
2393  // Windows path may contain a drive letter
2394  // For NTFS ":" may be a "stream" delimiter as well
2395  pathname = ptr + 1;
2396  break;
2397  }
2398  ptr++;
2399  }
2400  int len = r - pathname;
2401  if (len > 0) {
2402  fDirNameBuffer = new char[len+1];
2403  memcpy(fDirNameBuffer, pathname, len);
2404  fDirNameBuffer[len] = 0;
2405  }
2406  }
2407  }
2408  if (!fDirNameBuffer) {
2409  fDirNameBuffer = new char[1];
2410  *fDirNameBuffer = '\0'; // Set the empty default response
2411  }
2412  return fDirNameBuffer;
2413 }
2414 
2415 ////////////////////////////////////////////////////////////////////////////////
2416 /// Return the drive letter in pathname. DriveName of 'c:/user/root' is 'c'
2417 ///
2418 /// Input:
2419 /// - pathname - the string containing file name
2420 ///
2421 /// Return:
2422 /// - Letter representing the drive letter in the file name
2423 /// - The current drive if the pathname has no drive assigment
2424 /// - 0 if pathname is an empty string or uses UNC syntax
2425 ///
2426 /// Note:
2427 /// It doesn't check whether pathname represents a 'real' filename.
2428 /// This subroutine looks for 'single letter' followed by a ':'.
2429 
2430 const char TWinNTSystem::DriveName(const char *pathname)
2431 {
2432  if (!pathname) return 0;
2433  if (!pathname[0]) return 0;
2434 
2435  const char *lpchar;
2436  lpchar = pathname;
2437 
2438  // Skip blanks
2439  while(*lpchar == ' ') lpchar++;
2440 
2441  if (isalpha((int)*lpchar) && *(lpchar+1) == ':') {
2442  return *lpchar;
2443  }
2444  // Test UNC syntax
2445  if ( (*lpchar == '\\' || *lpchar == '/' ) &&
2446  (*(lpchar+1) == '\\' || *(lpchar+1) == '/') ) return 0;
2447 
2448  // return the current drive
2449  return DriveName(WorkingDirectory());
2450 }
2451 
2452 ////////////////////////////////////////////////////////////////////////////////
2453 /// Return true if dir is an absolute pathname.
2454 
2456 {
2457  if (dir) {
2458  int idx = 0;
2459  if (strchr(dir,':')) idx = 2;
2460  return (dir[idx] == '/' || dir[idx] == '\\');
2461  }
2462  return kFALSE;
2463 }
2464 
2465 ////////////////////////////////////////////////////////////////////////////////
2466 /// Convert a pathname to a unix pathname. E.g. form \user\root to /user/root.
2467 /// General rules for applications creating names for directories and files or
2468 /// processing names supplied by the user include the following:
2469 ///
2470 /// * Use any character in the current code page for a name, but do not use
2471 /// a path separator, a character in the range 0 through 31, or any character
2472 /// explicitly disallowed by the file system. A name can contain characters
2473 /// in the extended character set (128-255).
2474 /// * Use the backslash (\), the forward slash (/), or both to separate
2475 /// components in a path. No other character is acceptable as a path separator.
2476 /// * Use a period (.) as a directory component in a path to represent the
2477 /// current directory.
2478 /// * Use two consecutive periods (..) as a directory component in a path to
2479 /// represent the parent of the current directory.
2480 /// * Use a period (.) to separate components in a directory name or filename.
2481 /// * Do not use the following characters in directory names or filenames, because
2482 /// they are reserved for Windows:
2483 /// < > : " / \ |
2484 /// * Do not use reserved words, such as aux, con, and prn, as filenames or
2485 /// directory names.
2486 /// * Process a path as a null-terminated string. The maximum length for a path
2487 /// is given by MAX_PATH.
2488 /// * Do not assume case sensitivity. Consider names such as OSCAR, Oscar, and
2489 /// oscar to be the same.
2490 
2491 const char *TWinNTSystem::UnixPathName(const char *name)
2492 {
2493  static char temp[1024];
2494  strlcpy(temp, name,1024);
2495  char *currentChar = temp;
2496 
2497  while (*currentChar != '\0') {
2498  if (*currentChar == '\\') *currentChar = '/';
2499  currentChar++;
2500  }
2501  return temp;
2502 }
2503 
2504 ////////////////////////////////////////////////////////////////////////////////
2505 /// Returns FALSE if one can access a file using the specified access mode.
2506 /// Mode is the same as for the WinNT access(2) function.
2507 /// Attention, bizarre convention of return value!!
2508 
2510 {
2511  TSystem *helper = FindHelper(path);
2512  if (helper)
2513  return helper->AccessPathName(path, mode);
2514 
2515  // prevent the system dialog box to pop-up if a drive is empty
2516  UINT nOldErrorMode = ::SetErrorMode(SEM_FAILCRITICALERRORS);
2517  if (mode==kExecutePermission)
2518  // cannot test on exe - use read instead
2519  mode=kReadPermission;
2520  const char *proto = (strstr(path, "file:///")) ? "file://" : "file:";
2521  if (::_access(StripOffProto(path, proto), mode) == 0) {
2522  // restore previous error mode
2523  ::SetErrorMode(nOldErrorMode);
2524  return kFALSE;
2525  }
2527  // restore previous error mode
2528  ::SetErrorMode(nOldErrorMode);
2529  return kTRUE;
2530 }
2531 
2532 ////////////////////////////////////////////////////////////////////////////////
2533 /// Returns TRUE if the url in 'path' points to the local file system.
2534 /// This is used to avoid going through the NIC card for local operations.
2535 
2537 {
2538  TSystem *helper = FindHelper(path);
2539  if (helper)
2540  return helper->IsPathLocal(path);
2541 
2542  return TSystem::IsPathLocal(path);
2543 }
2544 
2545 ////////////////////////////////////////////////////////////////////////////////
2546 /// Concatenate a directory and a file name.
2547 
2548 const char *TWinNTSystem::PrependPathName(const char *dir, TString& name)
2549 {
2550  if (name == ".") name = "";
2551  if (dir && dir[0]) {
2552  // Test whether the last symbol of the directory is a separator
2553  char last = dir[strlen(dir) - 1];
2554  if (last != '/' && last != '\\') {
2555  name.Prepend('\\');
2556  }
2557  name.Prepend(dir);
2558  name.ReplaceAll("/", "\\");
2559  }
2560  return name.Data();
2561 }
2562 
2563 ////////////////////////////////////////////////////////////////////////////////
2564 /// Copy a file. If overwrite is true and file already exists the
2565 /// file will be overwritten. Returns 0 when successful, -1 in case
2566 /// of failure, -2 in case the file already exists and overwrite was false.
2567 
2568 int TWinNTSystem::CopyFile(const char *f, const char *t, Bool_t overwrite)
2569 {
2570  if (AccessPathName(f, kReadPermission)) return -1;
2571  if (!AccessPathName(t) && !overwrite) return -2;
2572 
2573  Bool_t ret = ::CopyFileA(f, t, kFALSE);
2574 
2575  if (!ret) return -1;
2576  return 0;
2577 }
2578 
2579 ////////////////////////////////////////////////////////////////////////////////
2580 /// Rename a file. Returns 0 when successful, -1 in case of failure.
2581 
2582 int TWinNTSystem::Rename(const char *f, const char *t)
2583 {
2584  int ret = ::rename(f, t);
2586  return ret;
2587 }
2588 
2589 ////////////////////////////////////////////////////////////////////////////////
2590 /// Get info about a file. Info is returned in the form of a FileStat_t
2591 /// structure (see TSystem.h).
2592 /// The function returns 0 in case of success and 1 if the file could
2593 /// not be stat'ed.
2594 
2595 int TWinNTSystem::GetPathInfo(const char *path, FileStat_t &buf)
2596 {
2597  TSystem *helper = FindHelper(path);
2598  if (helper)
2599  return helper->GetPathInfo(path, buf);
2600 
2601  struct _stati64 sbuf;
2602 
2603  // Remove trailing backslashes
2604  const char *proto = (strstr(path, "file:///")) ? "file://" : "file:";
2605  char *newpath = StrDup(StripOffProto(path, proto));
2606  int l = strlen(newpath);
2607  while (l > 1) {
2608  if (newpath[--l] != '\\' || newpath[--l] != '/') {
2609  break;
2610  }
2611  newpath[l] = '\0';
2612  }
2613 
2614  if (newpath && ::_stati64(newpath, &sbuf) >= 0) {
2615 
2616  buf.fDev = sbuf.st_dev;
2617  buf.fIno = sbuf.st_ino;
2618  buf.fMode = sbuf.st_mode;
2619  buf.fUid = sbuf.st_uid;
2620  buf.fGid = sbuf.st_gid;
2621  buf.fSize = sbuf.st_size;
2622  buf.fMtime = sbuf.st_mtime;
2623  buf.fIsLink = IsShortcut(newpath); // kFALSE;
2624 
2625  char *lpath = new char[MAX_PATH];
2626  if (IsShortcut(newpath)) {
2627  struct _stati64 sbuf2;
2628  if (ResolveShortCut(newpath, lpath, MAX_PATH)) {
2629  if (::_stati64(lpath, &sbuf2) >= 0) {
2630  buf.fMode = sbuf2.st_mode;
2631  }
2632  }
2633  }
2634  delete [] lpath;
2635 
2636  delete [] newpath;
2637  return 0;
2638  }
2639  delete [] newpath;
2640  return 1;
2641 }
2642 
2643 ////////////////////////////////////////////////////////////////////////////////
2644 /// Get info about a file system: id, bsize, bfree, blocks.
2645 /// Id is file system type (machine dependend, see statfs())
2646 /// Bsize is block size of file system
2647 /// Blocks is total number of blocks in file system
2648 /// Bfree is number of free blocks in file system
2649 /// The function returns 0 in case of success and 1 if the file system could
2650 /// not be stat'ed.
2651 
2652 int TWinNTSystem::GetFsInfo(const char *path, Long_t *id, Long_t *bsize,
2653  Long_t *blocks, Long_t *bfree)
2654 {
2655  // address of root directory of the file system
2656  LPCTSTR lpRootPathName = path;
2657 
2658  // address of name of the volume
2659  LPTSTR lpVolumeNameBuffer = 0;
2660  DWORD nVolumeNameSize = 0;
2661 
2662  DWORD volumeSerialNumber; // volume serial number
2663  DWORD maximumComponentLength; // system's maximum filename length
2664 
2665  // file system flags
2666  DWORD fileSystemFlags;
2667 
2668  // address of name of file system
2669  char fileSystemNameBuffer[512];
2670  DWORD nFileSystemNameSize = sizeof(fileSystemNameBuffer);
2671 
2672  // prevent the system dialog box to pop-up if the drive is empty
2673  UINT nOldErrorMode = ::SetErrorMode(SEM_FAILCRITICALERRORS);
2674  if (!::GetVolumeInformation(lpRootPathName,
2675  lpVolumeNameBuffer, nVolumeNameSize,
2676  &volumeSerialNumber,
2677  &maximumComponentLength,
2678  &fileSystemFlags,
2679  fileSystemNameBuffer, nFileSystemNameSize)) {
2680  // restore previous error mode
2681  ::SetErrorMode(nOldErrorMode);
2682  return 1;
2683  }
2684 
2685  const char *fsNames[] = { "FAT", "NTFS" };
2686  int i;
2687  for (i = 0; i < 2; i++) {
2688  if (!strncmp(fileSystemNameBuffer, fsNames[i], nFileSystemNameSize))
2689  break;
2690  }
2691  *id = i;
2692 
2693  DWORD sectorsPerCluster; // # sectors per cluster
2694  DWORD bytesPerSector; // # bytes per sector
2695  DWORD numberOfFreeClusters; // # free clusters
2696  DWORD totalNumberOfClusters; // # total of clusters
2697 
2698  if (!::GetDiskFreeSpace(lpRootPathName,
2699  &sectorsPerCluster,
2700  &bytesPerSector,
2701  &numberOfFreeClusters,
2702  &totalNumberOfClusters)) {
2703  // restore previous error mode
2704  ::SetErrorMode(nOldErrorMode);
2705  return 1;
2706  }
2707  // restore previous error mode
2708  ::SetErrorMode(nOldErrorMode);
2709 
2710  *bsize = sectorsPerCluster * bytesPerSector;
2711  *blocks = totalNumberOfClusters;
2712  *bfree = numberOfFreeClusters;
2713 
2714  return 0;
2715 }
2716 
2717 ////////////////////////////////////////////////////////////////////////////////
2718 /// Create a link from file1 to file2.
2719 
2720 int TWinNTSystem::Link(const char *from, const char *to)
2721 {
2722  struct _stati64 finfo;
2723  char winDrive[256];
2724  char winDir[256];
2725  char winName[256];
2726  char winExt[256];
2727  char linkname[1024];
2728  LPTSTR lpszFilePart;
2729  TCHAR szPath[MAX_PATH];
2730  DWORD dwRet = 0;
2731 
2732  typedef BOOL (__stdcall *CREATEHARDLINKPROC)( LPCTSTR, LPCTSTR, LPSECURITY_ATTRIBUTES );
2733  static CREATEHARDLINKPROC _CreateHardLink = 0;
2734 
2735  HMODULE hModImagehlp = LoadLibrary( "Kernel32.dll" );
2736  if (!hModImagehlp)
2737  return -1;
2738 
2739 #ifdef _UNICODE
2740  _CreateHardLink = (CREATEHARDLINKPROC) GetProcAddress( hModImagehlp, "CreateHardLinkW" );
2741 #else
2742  _CreateHardLink = (CREATEHARDLINKPROC) GetProcAddress( hModImagehlp, "CreateHardLinkA" );
2743 #endif
2744  if (!_CreateHardLink)
2745  return -1;
2746 
2747  dwRet = GetFullPathName(from, sizeof(szPath) / sizeof(TCHAR),
2748  szPath, &lpszFilePart);
2749 
2750  if (_stati64(szPath, &finfo) < 0)
2751  return -1;
2752 
2753  if (finfo.st_mode & S_IFDIR)
2754  return -1;
2755 
2756  snprintf(linkname,1024,"%s",to);
2757  _splitpath(linkname,winDrive,winDir,winName,winExt);
2758  if ((!winDrive[0] ) &&
2759  (!winDir[0] )) {
2760  _splitpath(szPath,winDrive,winDir,winName,winExt);
2761  snprintf(linkname,1024,"%s\\%s\\%s", winDrive, winDir, to);
2762  }
2763  else if (!winDrive[0]) {
2764  _splitpath(szPath,winDrive,winDir,winName,winExt);
2765  snprintf(linkname,1024,"%s\\%s", winDrive, to);
2766  }
2767 
2768  if (!_CreateHardLink(linkname, szPath, NULL))
2769  return -1;
2770 
2771  return 0;
2772 }
2773 
2774 ////////////////////////////////////////////////////////////////////////////////
2775 /// Create a symlink from file1 to file2. Returns 0 when successful,
2776 /// -1 in case of failure.
2777 
2778 int TWinNTSystem::Symlink(const char *from, const char *to)
2779 {
2780  HRESULT hRes; /* Returned COM result code */
2781  IShellLink* pShellLink; /* IShellLink object pointer */
2782  IPersistFile* pPersistFile; /* IPersistFile object pointer */
2783  WCHAR wszLinkfile[MAX_PATH]; /* pszLinkfile as Unicode string */
2784  int iWideCharsWritten; /* Number of wide characters written */
2785  DWORD dwRet = 0;
2786  LPTSTR lpszFilePart;
2787  TCHAR szPath[MAX_PATH];
2788 
2789  hRes = E_INVALIDARG;
2790  if ((from == NULL) || (!from[0]) || (to == NULL) ||
2791  (!to[0]))
2792  return -1;
2793 
2794  // Make typedefs for some ole32.dll functions so that we can use them
2795  // with GetProcAddress
2796  typedef HRESULT (__stdcall *COINITIALIZEPROC)( LPVOID );
2797  static COINITIALIZEPROC _CoInitialize = 0;
2798  typedef void (__stdcall *COUNINITIALIZEPROC)( void );
2799  static COUNINITIALIZEPROC _CoUninitialize = 0;
2800  typedef HRESULT (__stdcall *COCREATEINSTANCEPROC)( REFCLSID, LPUNKNOWN, DWORD, REFIID, LPVOID );
2801  static COCREATEINSTANCEPROC _CoCreateInstance = 0;
2802 
2803  HMODULE hModImagehlp = LoadLibrary( "ole32.dll" );
2804  if (!hModImagehlp)
2805  return -1;
2806 
2807  _CoInitialize = (COINITIALIZEPROC) GetProcAddress( hModImagehlp, "CoInitialize" );
2808  if (!_CoInitialize)
2809  return -1;
2810  _CoUninitialize = (COUNINITIALIZEPROC) GetProcAddress( hModImagehlp, "CoUninitialize" );
2811  if (!_CoUninitialize)
2812  return -1;
2813  _CoCreateInstance = (COCREATEINSTANCEPROC) GetProcAddress( hModImagehlp, "CoCreateInstance" );
2814  if (!_CoCreateInstance)
2815  return -1;
2816 
2817  TString linkname(to);
2818  if (!linkname.EndsWith(".lnk"))
2819  linkname.Append(".lnk");
2820 
2821  _CoInitialize(NULL);
2822 
2823  // Retrieve the full path and file name of a specified file
2824  dwRet = GetFullPathName(from, sizeof(szPath) / sizeof(TCHAR),
2825  szPath, &lpszFilePart);
2826  hRes = _CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
2827  IID_IShellLink, (LPVOID *)&pShellLink);
2828  if (SUCCEEDED(hRes)) {
2829  // Set the fields in the IShellLink object
2830  hRes = pShellLink->SetPath(szPath);
2831  // Use the IPersistFile object to save the shell link
2832  hRes = pShellLink->QueryInterface(IID_IPersistFile, (void **)&pPersistFile);
2833  if (SUCCEEDED(hRes)){
2834  iWideCharsWritten = MultiByteToWideChar(CP_ACP, 0, linkname.Data(), -1,
2835  wszLinkfile, MAX_PATH);
2836  hRes = pPersistFile->Save(wszLinkfile, TRUE);
2837  pPersistFile->Release();
2838  }
2839  pShellLink->Release();
2840  }
2841  _CoUninitialize();
2842  return 0;
2843 }
2844 
2845 ////////////////////////////////////////////////////////////////////////////////
2846 /// Unlink, i.e. remove, a file or directory.
2847 
2848 int TWinNTSystem::Unlink(const char *name)
2849 {
2850  TSystem *helper = FindHelper(name);
2851  if (helper)
2852  return helper->Unlink(name);
2853 
2854  struct _stati64 finfo;
2855 
2856  if (_stati64(name, &finfo) < 0) {
2857  return -1;
2858  }
2859 
2860  if (finfo.st_mode & S_IFDIR) {
2861  return ::_rmdir(name);
2862  } else {
2863  return ::_unlink(name);
2864  }
2865 }
2866 
2867 ////////////////////////////////////////////////////////////////////////////////
2868 /// Make descriptor fd non-blocking.
2869 
2871 {
2872  if (::ioctlsocket(fd, FIONBIO, (u_long *)1) == SOCKET_ERROR) {
2873  ::SysError("SetNonBlock", "ioctlsocket");
2874  return -1;
2875  }
2876  return 0;
2877 }
2878 
2879 // expand the metacharacters as in the shell
2880 
2881 static char
2882  *shellMeta = "~*[]{}?$%",
2883  *shellStuff = "(){}<>\"'",
2884  shellEscape = '\\';
2885 
2886 ////////////////////////////////////////////////////////////////////////////////
2887 /// Expand a pathname getting rid of special shell characaters like ~.$, etc.
2888 
2890 {
2891  const char *patbuf = (const char *)patbuf0;
2892  const char *p;
2893  char *cmd = 0;
2894  char *q;
2895 
2896  Int_t old_level = gErrorIgnoreLevel;
2897  gErrorIgnoreLevel = kFatal; // Explicitly remove all messages
2898  TUrl urlpath(patbuf0, kTRUE);
2899  TString proto = urlpath.GetProtocol();
2900  gErrorIgnoreLevel = old_level;
2901  if (!proto.EqualTo("file")) // don't expand urls!!!
2902  return kFALSE;
2903 
2904  // skip the "file:" protocol, if any
2905  if (patbuf0.BeginsWith("file:"))
2906  patbuf += 5;
2907 
2908  // skip leading blanks
2909  while (*patbuf == ' ') {
2910  patbuf++;
2911  }
2912 
2913  // skip leading ':'
2914  while (*patbuf == ':') {
2915  patbuf++;
2916  }
2917 
2918  // skip leading ';'
2919  while (*patbuf == ';') {
2920  patbuf++;
2921  }
2922 
2923  // Transform a Unix list of directories into a Windows list
2924  // by changing the separator from ':' into ';'
2925  for (q = (char*)patbuf; *q; q++) {
2926  if ( *q == ':' ) {
2927  // We are avoiding substitution in the case of
2928  // ....;c:.... and of ...;root:/... where root can be any url protocol
2929  if ( (((q-2)>patbuf) && ( (*(q-2)!=';') || !isalpha(*(q-1)) )) &&
2930  *(q+1)!='/' ) {
2931  *q=';';
2932  }
2933  }
2934  }
2935  // any shell meta characters ?
2936  for (p = patbuf; *p; p++) {
2937  if (strchr(shellMeta, *p)) {
2938  goto needshell;
2939  }
2940  }
2941  return kFALSE;
2942 
2943 needshell:
2944 
2945  // Because (problably) we built with cygwin, the path name like:
2946  // LOCALS~1\\Temp
2947  // gets extended to
2948  // LOCALSc:\\Devel
2949  // The most likely cause is that '~' is used with Unix semantic of the
2950  // home directory (and it also cuts the path short after ... who knows why!)
2951  // So we need to detect this case and prevents its expansion :(.
2952 
2953  char replacement[4];
2954 
2955  // intentionally a non visible, unlikely character
2956  for (int k = 0; k<3; k++) replacement[k] = 0x1;
2957 
2958  replacement[3] = 0x0;
2959  Ssiz_t pos = 0;
2960  TRegexp TildaNum = "~[0-9]";
2961 
2962  while ( (pos = patbuf0.Index(TildaNum,pos)) != kNPOS ) {
2963  patbuf0.Replace(pos, 1, replacement);
2964  }
2965 
2966  // escape shell quote characters
2967  // EscChar(patbuf, stuffedPat, sizeof(stuffedPat), shellStuff, shellEscape);
2968  ExpandFileName(patbuf0);
2969  Int_t lbuf = ::ExpandEnvironmentStrings(
2970  patbuf0.Data(), // pointer to string with environment variables
2971  cmd, // pointer to string with expanded environment variables
2972  0 // maximum characters in expanded string
2973  );
2974  if (lbuf > 0) {
2975  cmd = new char[lbuf+1];
2976  ::ExpandEnvironmentStrings(
2977  patbuf0.Data(), // pointer to string with environment variables
2978  cmd, // pointer to string with expanded environment variables
2979  lbuf // maximum characters in expanded string
2980  );
2981  patbuf0 = cmd;
2982  patbuf0.ReplaceAll(replacement, "~");
2983  delete [] cmd;
2984  return kFALSE;
2985  }
2986  return kTRUE;
2987 }
2988 
2989 ////////////////////////////////////////////////////////////////////////////////
2990 /// Expand a pathname getting rid of special shell characaters like ~.$, etc.
2991 /// User must delete returned string.
2992 
2993 char *TWinNTSystem::ExpandPathName(const char *path)
2994 {
2995  char newpath[MAX_PATH];
2996  if (IsShortcut(path)) {
2997  if (!ResolveShortCut(path, newpath, MAX_PATH))
2998  strlcpy(newpath, path, MAX_PATH);
2999  }
3000  else
3001  strlcpy(newpath, path, MAX_PATH);
3002  TString patbuf = newpath;
3003  if (ExpandPathName(patbuf)) return 0;
3004 
3005  return StrDup(patbuf.Data());
3006 }
3007 
3008 ////////////////////////////////////////////////////////////////////////////////
3009 /// Set the file permission bits. Returns -1 in case or error, 0 otherwise.
3010 /// On windows mode can only be a combination of "user read" (0400),
3011 /// "user write" (0200) or "user read | user write" (0600). Any other value
3012 /// for mode are ignored.
3013 
3014 int TWinNTSystem::Chmod(const char *file, UInt_t mode)
3015 {
3016  return ::_chmod(file, mode);
3017 }
3018 
3019 ////////////////////////////////////////////////////////////////////////////////
3020 /// Set the process file creation mode mask.
3021 
3023 {
3024  return ::umask(mask);
3025 }
3026 
3027 ////////////////////////////////////////////////////////////////////////////////
3028 /// Set a files modification and access times. If actime = 0 it will be
3029 /// set to the modtime. Returns 0 on success and -1 in case of error.
3030 
3031 int TWinNTSystem::Utime(const char *file, Long_t modtime, Long_t actime)
3032 {
3033  if (AccessPathName(file, kWritePermission)) {
3034  Error("Utime", "need write permission for %s to change utime", file);
3035  return -1;
3036  }
3037  if (!actime) actime = modtime;
3038 
3039  struct utimbuf t;
3040  t.actime = (time_t)actime;
3041  t.modtime = (time_t)modtime;
3042  return ::utime(file, &t);
3043 }
3044 
3045 ////////////////////////////////////////////////////////////////////////////////
3046 /// Find location of file in a search path.
3047 /// User must delete returned string. Returns 0 in case file is not found.
3048 
3049 const char *TWinNTSystem::FindFile(const char *search, TString& infile, EAccessMode mode)
3050 {
3051  // Windows cannot check on execution mode - all we can do is kReadPermission
3052  if (mode==kExecutePermission)
3053  mode=kReadPermission;
3054 
3055  // Expand parameters
3056 
3057  gSystem->ExpandPathName(infile);
3058  // Check whether this infile has the absolute path first
3059  if (IsAbsoluteFileName(infile.Data()) ) {
3060  if (!AccessPathName(infile.Data(), mode))
3061  return infile.Data();
3062  infile = "";
3063  return 0;
3064  }
3065  TString exsearch(search);
3066  gSystem->ExpandPathName(exsearch);
3067 
3068  // Need to use Windows delimiters
3069  Int_t lastDelim = -1;
3070  for(int i=0; i < exsearch.Length(); ++i) {
3071  switch( exsearch[i] ) {
3072  case ':':
3073  // Replace the ':' unless there are after a disk suffix (aka ;c:\mydirec...)
3074  if (i-lastDelim!=2) exsearch[i] = ';';
3075  lastDelim = i;
3076  break;
3077  case ';': lastDelim = i; break;
3078  }
3079  }
3080 
3081  // Check access
3082  struct stat finfo;
3083  char name[kMAXPATHLEN];
3084  char *lpFilePart = 0;
3085  if (::SearchPath(exsearch.Data(), infile.Data(), NULL, kMAXPATHLEN, name, &lpFilePart) &&
3086  ::access(name, mode) == 0 && stat(name, &finfo) == 0 &&
3087  finfo.st_mode & S_IFREG) {
3088  if (gEnv->GetValue("Root.ShowPath", 0)) {
3089  Printf("Which: %s = %s", infile, name);
3090  }
3091  infile = name;
3092  return infile.Data();
3093  }
3094  infile = "";
3095  return 0;
3096 }
3097 
3098 //---- Users & Groups ----------------------------------------------------------
3099 
3100 ////////////////////////////////////////////////////////////////////////////////
3101 /// Collect local users and groups accounts information
3102 
3104 {
3105  // Net* API functions allowed and OS is Windows NT/2000/XP
3106  if ((gEnv->GetValue("WinNT.UseNetAPI", 0)) && (::GetVersion() < 0x80000000)) {
3107  fActUser = -1;
3108  fNbGroups = fNbUsers = 0;
3109  HINSTANCE netapi = ::LoadLibrary("netapi32.DLL");
3110  if (!netapi) return kFALSE;
3111 
3112  p2NetApiBufferFree = (pfn1)::GetProcAddress(netapi, "NetApiBufferFree");
3113  p2NetUserGetInfo = (pfn2)::GetProcAddress(netapi, "NetUserGetInfo");
3114  p2NetLocalGroupGetMembers = (pfn3)::GetProcAddress(netapi, "NetLocalGroupGetMembers");
3115  p2NetLocalGroupEnum = (pfn4)::GetProcAddress(netapi, "NetLocalGroupEnum");
3116 
3117  if (!p2NetApiBufferFree || !p2NetUserGetInfo ||
3118  !p2NetLocalGroupGetMembers || !p2NetLocalGroupEnum) return kFALSE;
3119 
3120  GetNbGroups();
3121 
3122  fGroups = (struct group *)calloc(fNbGroups, sizeof(struct group));
3123  for(int i=0;i<fNbGroups;i++) {
3124  fGroups[i].gr_mem = (char **)calloc(fNbUsers, sizeof (char*));
3125  }
3126  fPasswords = (struct passwd *)calloc(fNbUsers, sizeof(struct passwd));
3127 
3128  CollectGroups();
3129  ::FreeLibrary(netapi);
3130  }
3132  return kTRUE;
3133 }
3134 
3135 ////////////////////////////////////////////////////////////////////////////////
3136 
3137 Bool_t TWinNTSystem::CountMembers(const char *lpszGroupName)
3138 {
3139  NET_API_STATUS NetStatus = NERR_Success;
3140  LPBYTE Data = NULL;
3141  DWORD Index = 0, ResumeHandle = 0, Total = 0;
3142  LOCALGROUP_MEMBERS_INFO_1 *MemberInfo;
3143  WCHAR wszGroupName[256];
3144  int iRetOp = 0;
3145  DWORD dwLastError = 0;
3146 
3147  iRetOp = MultiByteToWideChar (
3148  (UINT)CP_ACP, // code page
3149  (DWORD)MB_PRECOMPOSED, // character-type options
3150  (LPCSTR)lpszGroupName, // address of string to map
3151  (int)-1, // number of bytes in string
3152  (LPWSTR)wszGroupName, // address of wide-character buffer
3153  (int)sizeof(wszGroupName) ); // size of buffer
3154 
3155  if (iRetOp == 0) {
3156  dwLastError = GetLastError();
3157  if (Data)
3158  p2NetApiBufferFree(Data);
3159  return FALSE;
3160  }
3161 
3162  // The NetLocalGroupGetMembers() API retrieves a list of the members
3163  // of a particular local group.
3164  NetStatus = p2NetLocalGroupGetMembers (NULL, wszGroupName, 1,
3165  &Data, 8192, &Index, &Total, &ResumeHandle );
3166 
3167  if (NetStatus != NERR_Success || Data == NULL) {
3168  dwLastError = GetLastError();
3169 
3170  if (dwLastError == ERROR_ENVVAR_NOT_FOUND) {
3171  // This usually means that the current Group has no members.
3172  // We call NetLocalGroupGetMembers() again.
3173  // This time, we set the level to 0.
3174  // We do this just to confirm that the number of members in
3175  // this group is zero.
3176  NetStatus = p2NetLocalGroupGetMembers ( NULL, wszGroupName, 0,
3177  &Data, 8192, &Index, &Total, &ResumeHandle );
3178  }
3179 
3180  if (Data)
3181  p2NetApiBufferFree(Data);
3182  return FALSE;
3183  }
3184 
3185  fNbUsers += Total;
3186  MemberInfo = (LOCALGROUP_MEMBERS_INFO_1 *)Data;
3187 
3188  if (Data)
3189  p2NetApiBufferFree(Data);
3190 
3191  return TRUE;
3192 }
3193 
3194 ////////////////////////////////////////////////////////////////////////////////
3195 
3197 {
3198  NET_API_STATUS NetStatus = NERR_Success;
3199  LPBYTE Data = NULL;
3200  DWORD Index = 0, ResumeHandle = 0, Total = 0, i;
3201  LOCALGROUP_INFO_0 *GroupInfo;
3202  char szAnsiName[256];
3203  DWORD dwLastError = 0;
3204  int iRetOp = 0;
3205 
3206  NetStatus = p2NetLocalGroupEnum(NULL, 0, &Data, 8192, &Index,
3207  &Total, &ResumeHandle );
3208 
3209  if (NetStatus != NERR_Success || Data == NULL) {
3210  dwLastError = GetLastError();
3211  if (Data)
3212  p2NetApiBufferFree(Data);
3213  return FALSE;
3214  }
3215 
3216  fNbGroups = Total;
3217  GroupInfo = (LOCALGROUP_INFO_0 *)Data;
3218  for (i=0; i < Total; i++) {
3219  // Convert group name from UNICODE to ansi.
3220  iRetOp = WideCharToMultiByte (
3221  (UINT)CP_ACP, // code page
3222  (DWORD)0, // performance and mapping flags
3223  (LPCWSTR)(GroupInfo->lgrpi0_name), // address of wide-char string
3224  (int)-1, // number of characters in string
3225  (LPSTR)szAnsiName, // address of buffer for new string
3226  (int)(sizeof(szAnsiName)), // size of buffer
3227  (LPCSTR)NULL, // address of default for unmappable characters
3228  (LPBOOL)NULL ); // address of flag set when default char used.
3229 
3230  // Now lookup all members of this group and record down their names and
3231  // SIDs into the output file.
3232  CountMembers((LPCTSTR)szAnsiName);
3233 
3234  GroupInfo++;
3235  }
3236 
3237  if (Data)
3238  p2NetApiBufferFree(Data);
3239 
3240  return TRUE;
3241 }
3242 
3243 ////////////////////////////////////////////////////////////////////////////////
3244 ///
3245 /// Take the name and look up a SID so that we can get full
3246 /// domain/user information
3247 ///
3248 
3249 Long_t TWinNTSystem::LookupSID (const char *lpszAccountName, int what,
3250  int &groupIdx, int &memberIdx)
3251 {
3252  BOOL bRetOp = FALSE;
3253  PSID pSid = NULL;
3254  DWORD dwSidSize, dwDomainNameSize;
3255  BYTE bySidBuffer[MAX_SID_SIZE];
3256  char szDomainName[MAX_NAME_STRING];
3257  SID_NAME_USE sidType;
3258  PUCHAR puchar_SubAuthCount = NULL;
3259  SID_IDENTIFIER_AUTHORITY sid_identifier_authority;
3260  PSID_IDENTIFIER_AUTHORITY psid_identifier_authority = NULL;
3261  unsigned char j = 0;
3262  DWORD dwLastError = 0;
3263 
3264  pSid = (PSID)bySidBuffer;
3265  dwSidSize = sizeof(bySidBuffer);
3266  dwDomainNameSize = sizeof(szDomainName);
3267 
3268  bRetOp = LookupAccountName (
3269  (LPCTSTR)NULL, // address of string for system name
3270  (LPCTSTR)lpszAccountName, // address of string for account name
3271  (PSID)pSid, // address of security identifier
3272  (LPDWORD)&dwSidSize, // address of size of security identifier
3273  (LPTSTR)szDomainName, // address of string for referenced domain
3274  (LPDWORD)&dwDomainNameSize,// address of size of domain string
3275  (PSID_NAME_USE)&sidType ); // address of SID-type indicator
3276 
3277  if (bRetOp == FALSE) {
3278  dwLastError = GetLastError();
3279  return -1; // Unable to obtain Account SID.
3280  }
3281 
3282  bRetOp = IsValidSid((PSID)pSid);
3283 
3284  if (bRetOp == FALSE) {
3285  dwLastError = GetLastError();
3286  return -2; // SID returned is invalid.
3287  }
3288 
3289  // Obtain via APIs the identifier authority value.
3290  psid_identifier_authority = GetSidIdentifierAuthority ((PSID)pSid);
3291 
3292  // Make a copy of it.
3293  memcpy (&sid_identifier_authority, psid_identifier_authority,
3294  sizeof(SID_IDENTIFIER_AUTHORITY));
3295 
3296  // Determine how many sub-authority values there are in the current SID.
3297  puchar_SubAuthCount = (PUCHAR)GetSidSubAuthorityCount((PSID)pSid);
3298  // Assign it to a more convenient variable.
3299  j = (unsigned char)(*puchar_SubAuthCount);
3300  // Now obtain all the sub-authority values from the current SID.
3301  DWORD dwSubAuth = 0;
3302  PDWORD pdwSubAuth = NULL;
3303  // Obtain the current sub-authority DWORD (referenced by a pointer)
3304  pdwSubAuth = (PDWORD)GetSidSubAuthority (
3305  (PSID)pSid, // address of security identifier to query
3306  (DWORD)j-1); // index of subauthority to retrieve
3307  dwSubAuth = *pdwSubAuth;
3308  if(what == SID_MEMBER) {
3309  fPasswords[memberIdx].pw_uid = dwSubAuth;
3310  fPasswords[memberIdx].pw_gid = fGroups[groupIdx].gr_gid;
3311  fPasswords[memberIdx].pw_group = strdup(fGroups[groupIdx].gr_name);
3312  }
3313  else if(what == SID_GROUP) {
3314  fGroups[groupIdx].gr_gid = dwSubAuth;
3315  }
3316  return 0;
3317 }
3318 
3319 ////////////////////////////////////////////////////////////////////////////////
3320 ///
3321 
3322 Bool_t TWinNTSystem::CollectMembers(const char *lpszGroupName, int &groupIdx,
3323  int &memberIdx)
3324 {
3325 
3326  NET_API_STATUS NetStatus = NERR_Success;
3327  LPBYTE Data = NULL;
3328  DWORD Index = 0, ResumeHandle = 0, Total = 0, i;
3329  LOCALGROUP_MEMBERS_INFO_1 *MemberInfo;
3330  char szAnsiMemberName[256];
3331  char szFullMemberName[256];
3332  char szMemberHomeDir[256];
3333  WCHAR wszGroupName[256];
3334  int iRetOp = 0;
3335  char act_name[256];
3336  DWORD length = sizeof (act_name);
3337  DWORD dwLastError = 0;
3338  LPUSER_INFO_11 pUI11Buf = NULL;
3339  NET_API_STATUS nStatus;
3340 
3341  iRetOp = MultiByteToWideChar (
3342  (UINT)CP_ACP, // code page
3343  (DWORD)MB_PRECOMPOSED, // character-type options
3344  (LPCSTR)lpszGroupName, // address of string to map
3345  (int)-1, // number of bytes in string
3346  (LPWSTR)wszGroupName, // address of wide-character buffer
3347  (int)sizeof(wszGroupName) ); // size of buffer
3348 
3349  if (iRetOp == 0) {
3350  dwLastError = GetLastError();
3351  if (Data)
3352  p2NetApiBufferFree(Data);
3353  return FALSE;
3354  }
3355 
3356  GetUserName (act_name, &length);
3357 
3358  // The NetLocalGroupGetMembers() API retrieves a list of the members
3359  // of a particular local group.
3360  NetStatus = p2NetLocalGroupGetMembers (NULL, wszGroupName, 1,
3361  &Data, 8192, &Index, &Total, &ResumeHandle );
3362 
3363  if (NetStatus != NERR_Success || Data == NULL) {
3364  dwLastError = GetLastError();
3365 
3366  if (dwLastError == ERROR_ENVVAR_NOT_FOUND) {
3367  // This usually means that the current Group has no members.
3368  // We call NetLocalGroupGetMembers() again.
3369  // This time, we set the level to 0.
3370  // We do this just to confirm that the number of members in
3371  // this group is zero.
3372  NetStatus = p2NetLocalGroupGetMembers ( NULL, wszGroupName, 0,
3373  &Data, 8192, &Index, &Total, &ResumeHandle );
3374  }
3375 
3376  if (Data)
3377  p2NetApiBufferFree(Data);
3378  return FALSE;
3379  }
3380 
3381  MemberInfo = (LOCALGROUP_MEMBERS_INFO_1 *)Data;
3382  for (i=0; i < Total; i++) {
3383  iRetOp = WideCharToMultiByte (
3384  (UINT)CP_ACP, // code page
3385  (DWORD)0, // performance and mapping flags
3386  (LPCWSTR)(MemberInfo->lgrmi1_name), // address of wide-char string
3387  (int)-1, // number of characters in string
3388  (LPSTR)szAnsiMemberName, // address of buffer for new string
3389  (int)(sizeof(szAnsiMemberName)), // size of buffer
3390  (LPCSTR)NULL, // address of default for unmappable characters
3391  (LPBOOL)NULL ); // address of flag set when default char used.
3392 
3393  if (iRetOp == 0) {
3394  dwLastError = GetLastError();
3395  }
3396 
3397  fPasswords[memberIdx].pw_name = strdup(szAnsiMemberName);
3398  fPasswords[memberIdx].pw_passwd = strdup("");
3399  fGroups[groupIdx].gr_mem[i] = strdup(szAnsiMemberName);
3400 
3401  if(fActUser == -1 && !stricmp(fPasswords[memberIdx].pw_name,act_name))
3402  fActUser = memberIdx;
3403 
3404 
3405  TCHAR szUserName[255]=TEXT("");
3406  MultiByteToWideChar(CP_ACP, 0, szAnsiMemberName, -1, (LPWSTR)szUserName, 255);
3407  //
3408  // Call the NetUserGetInfo function; specify level 10.
3409  //
3410  nStatus = p2NetUserGetInfo(NULL, (LPCWSTR)szUserName, 11, (LPBYTE *)&pUI11Buf);
3411  //
3412  // If the call succeeds, print the user information.
3413  //
3414  if (nStatus == NERR_Success) {
3415  if (pUI11Buf != NULL) {
3416  wsprintf(szFullMemberName,"%S",pUI11Buf->usri11_full_name);
3417  fPasswords[memberIdx].pw_gecos = strdup(szFullMemberName);
3418  wsprintf(szMemberHomeDir,"%S",pUI11Buf->usri11_home_dir);
3419  fPasswords[memberIdx].pw_dir = strdup(szMemberHomeDir);
3420  }
3421  }
3422  if((fPasswords[memberIdx].pw_gecos == NULL) || (strlen(fPasswords[memberIdx].pw_gecos) == 0))
3423  fPasswords[memberIdx].pw_gecos = strdup(fPasswords[memberIdx].pw_name);
3424  if((fPasswords[memberIdx].pw_dir == NULL) || (strlen(fPasswords[memberIdx].pw_dir) == 0))
3425  fPasswords[memberIdx].pw_dir = strdup("c:\\");
3426  //
3427  // Free the allocated memory.
3428  //
3429  if (pUI11Buf != NULL) {
3430  p2NetApiBufferFree(pUI11Buf);
3431  pUI11Buf = NULL;
3432  }
3433 
3434  /* Ensure SHELL is defined. */
3435  if (getenv("SHELL") == NULL)
3436  putenv ((GetVersion () & 0x80000000) ? "SHELL=command" : "SHELL=cmd");
3437 
3438  /* Set dir and shell from environment variables. */
3439  fPasswords[memberIdx].pw_shell = getenv("SHELL");
3440 
3441  // Find out the SID of the Member.
3442  LookupSID ((LPCTSTR)szAnsiMemberName, SID_MEMBER, groupIdx, memberIdx);
3443  memberIdx++;
3444  MemberInfo++;
3445  }
3446  if(fActUser == -1) fActUser = 0;
3447 
3448  if (Data)
3449  p2NetApiBufferFree(Data);
3450 
3451  return TRUE;
3452 }
3453 
3454 ////////////////////////////////////////////////////////////////////////////////
3455 ///
3456 
3458 {
3459  NET_API_STATUS NetStatus = NERR_Success;
3460  LPBYTE Data = NULL;
3461  DWORD Index = 0, ResumeHandle = 0, Total = 0, i;
3462  LOCALGROUP_INFO_0 *GroupInfo;
3463  char szAnsiName[256];
3464  DWORD dwLastError = 0;
3465  int iRetOp = 0, iGroupIdx = 0, iMemberIdx = 0;
3466 
3467  NetStatus = p2NetLocalGroupEnum(NULL, 0, &Data, 8192, &Index,
3468  &Total, &ResumeHandle );
3469 
3470  if (NetStatus != NERR_Success || Data == NULL) {
3471  dwLastError = GetLastError();
3472  if (Data)
3473  p2NetApiBufferFree(Data);
3474  return FALSE;
3475  }
3476 
3477  GroupInfo = (LOCALGROUP_INFO_0 *)Data;
3478  for (i=0; i < Total; i++) {
3479  // Convert group name from UNICODE to ansi.
3480  iRetOp = WideCharToMultiByte (
3481  (UINT)CP_ACP, // code page
3482  (DWORD)0, // performance and mapping flags
3483  (LPCWSTR)(GroupInfo->lgrpi0_name), // address of wide-char string
3484  (int)-1, // number of characters in string
3485  (LPSTR)szAnsiName, // address of buffer for new string
3486  (int)(sizeof(szAnsiName)), // size of buffer
3487  (LPCSTR)NULL, // address of default for unmappable characters
3488  (LPBOOL)NULL ); // address of flag set when default char used.
3489 
3490  fGroups[iGroupIdx].gr_name = strdup(szAnsiName);
3491  fGroups[iGroupIdx].gr_passwd = strdup("");
3492 
3493  // Find out the SID of the Group.
3494  LookupSID ((LPCTSTR)szAnsiName, SID_GROUP, iGroupIdx, iMemberIdx);
3495  // Now lookup all members of this group and record down their names and
3496  // SIDs into the output file.
3497  CollectMembers((LPCTSTR)szAnsiName, iGroupIdx, iMemberIdx);
3498 
3499  iGroupIdx++;
3500  GroupInfo++;
3501  }
3502 
3503  if (Data)
3504  p2NetApiBufferFree(Data);
3505 
3506  return TRUE;
3507 }
3508 
3509 ////////////////////////////////////////////////////////////////////////////////
3510 /// Returns the user's id. If user = 0, returns current user's id.
3511 
3512 Int_t TWinNTSystem::GetUid(const char *user)
3513 {
3514  if(!fGroupsInitDone)
3515  InitUsersGroups();
3516 
3517  // Net* API functions not allowed or OS not Windows NT/2000/XP
3518  if ((!gEnv->GetValue("WinNT.UseNetAPI", 0)) || (::GetVersion() >= 0x80000000)) {
3519  int uid;
3520  char name[256];
3521  DWORD length = sizeof (name);
3522  if (::GetUserName (name, &length)) {
3523  if (stricmp ("administrator", name) == 0)
3524  uid = 0;
3525  else
3526  uid = 123;
3527  }
3528  else {
3529  uid = 123;
3530  }
3531  return uid;
3532  }
3533  if (!user || !user[0])
3534  return fPasswords[fActUser].pw_uid;
3535  else {
3536  struct passwd *pwd = 0;
3537  for(int i=0;i<fNbUsers;i++) {
3538  if (!stricmp (user, fPasswords[i].pw_name)) {
3539  pwd = &fPasswords[i];
3540  break;
3541  }
3542  }
3543  if (pwd)
3544  return pwd->pw_uid;
3545  }
3546  return 0;
3547 }
3548 
3549 ////////////////////////////////////////////////////////////////////////////////
3550 /// Returns the effective user id. The effective id corresponds to the
3551 /// set id bit on the file being executed.
3552 
3554 {
3555  if(!fGroupsInitDone)
3556  InitUsersGroups();
3557 
3558  // Net* API functions not allowed or OS not Windows NT/2000/XP
3559  if ((!gEnv->GetValue("WinNT.UseNetAPI", 0)) || (::GetVersion() >= 0x80000000)) {
3560  int uid;
3561  char name[256];
3562  DWORD length = sizeof (name);
3563  if (::GetUserName (name, &length)) {
3564  if (stricmp ("administrator", name) == 0)
3565  uid = 0;
3566  else
3567  uid = 123;
3568  }
3569  else {
3570  uid = 123;
3571  }
3572  return uid;
3573  }
3574  return fPasswords[fActUser].pw_uid;
3575 }
3576 
3577 ////////////////////////////////////////////////////////////////////////////////
3578 /// Returns the group's id. If group = 0, returns current user's group.
3579 
3581 {
3582  if(!fGroupsInitDone)
3583  InitUsersGroups();
3584 
3585  // Net* API functions not allowed or OS not Windows NT/2000/XP
3586  if ((!gEnv->GetValue("WinNT.UseNetAPI", 0)) || (::GetVersion() >= 0x80000000)) {
3587  int gid;
3588  char name[256];
3589  DWORD length = sizeof (name);
3590  if (::GetUserName (name, &length)) {
3591  if (stricmp ("administrator", name) == 0)
3592  gid = 0;
3593  else
3594  gid = 123;
3595  }
3596  else {
3597  gid = 123;
3598  }
3599  return gid;
3600  }
3601  if (!group || !group[0])
3602  return fPasswords[fActUser].pw_gid;
3603  else {
3604  struct group *grp = 0;
3605  for(int i=0;i<fNbGroups;i++) {
3606  if (!stricmp (group, fGroups[i].gr_name)) {
3607  grp = &fGroups[i];
3608  break;
3609  }
3610  }
3611  if (grp)
3612  return grp->gr_gid;
3613  }
3614  return 0;
3615 }
3616 
3617 ////////////////////////////////////////////////////////////////////////////////
3618 /// Returns the effective group id. The effective group id corresponds
3619 /// to the set id bit on the file being executed.
3620 
3622 {
3623  if(!fGroupsInitDone)
3624  InitUsersGroups();
3625 
3626  // Net* API functions not allowed or OS not Windows NT/2000/XP
3627  if ((!gEnv->GetValue("WinNT.UseNetAPI", 0)) || (::GetVersion() >= 0x80000000)) {
3628  int gid;
3629  char name[256];
3630  DWORD length = sizeof (name);
3631  if (::GetUserName (name, &length)) {
3632  if (stricmp ("administrator", name) == 0)
3633  gid = 0;
3634  else
3635  gid = 123;
3636  }
3637  else {
3638  gid = 123;
3639  }
3640  return gid;
3641  }
3642  return fPasswords[fActUser].pw_gid;
3643 }
3644 
3645 ////////////////////////////////////////////////////////////////////////////////
3646 /// Returns all user info in the UserGroup_t structure. The returned
3647 /// structure must be deleted by the user. In case of error 0 is returned.
3648 
3650 {
3651  if(!fGroupsInitDone)
3652  InitUsersGroups();
3653 
3654  // Net* API functions not allowed or OS not Windows NT/2000/XP
3655  if ((!gEnv->GetValue("WinNT.UseNetAPI", 0)) || (::GetVersion() >= 0x80000000)) {
3656  char name[256];
3657  DWORD length = sizeof (name);
3658  UserGroup_t *ug = new UserGroup_t;
3659  if (::GetUserName (name, &length)) {
3660  ug->fUser = name;
3661  if (stricmp ("administrator", name) == 0) {
3662  ug->fUid = 0;
3663  ug->fGroup = "administrators";
3664  }
3665  else {
3666  ug->fUid = 123;
3667  ug->fGroup = "users";
3668  }
3669  ug->fGid = ug->fUid;
3670  }
3671  else {
3672  ug->fUser = "unknown";
3673  ug->fGroup = "unknown";
3674  ug->fUid = ug->fGid = 123;
3675  }
3676  ug->fPasswd = "";
3677  ug->fRealName = ug->fUser;
3678  ug->fShell = "command";
3679  return ug;
3680  }
3681  struct passwd *pwd = 0;
3682  if (uid == 0)
3683  pwd = &fPasswords[fActUser];
3684  else {
3685  for (int i = 0; i < fNbUsers; i++) {
3686  if (uid == fPasswords[i].pw_uid) {
3687  pwd = &fPasswords[i];
3688  break;
3689  }
3690  }
3691  }
3692  if (pwd) {
3693  UserGroup_t *ug = new UserGroup_t;
3694  ug->fUid = pwd->pw_uid;
3695  ug->fGid = pwd->pw_gid;
3696  ug->fUser = pwd->pw_name;
3697  ug->fPasswd = pwd->pw_passwd;
3698  ug->fRealName = pwd->pw_gecos;
3699  ug->fShell = pwd->pw_shell;
3700  ug->fGroup = pwd->pw_group;
3701  return ug;
3702  }
3703  return 0;
3704 }
3705 
3706 ////////////////////////////////////////////////////////////////////////////////
3707 /// Returns all user info in the UserGroup_t structure. If user = 0, returns
3708 /// current user's id info. The returned structure must be deleted by the
3709 /// user. In case of error 0 is returned.
3710 
3712 {
3713  return GetUserInfo(GetUid(user));
3714 }
3715 
3716 ////////////////////////////////////////////////////////////////////////////////
3717 /// Returns all group info in the UserGroup_t structure. The only active
3718 /// fields in the UserGroup_t structure for this call are:
3719 /// fGid and fGroup
3720 /// The returned structure must be deleted by the user. In case of
3721 /// error 0 is returned.
3722 
3724 {
3725  if(!fGroupsInitDone)
3726  InitUsersGroups();
3727 
3728  // Net* API functions not allowed or OS not Windows NT/2000/XP
3729  if ((!gEnv->GetValue("WinNT.UseNetAPI", 0)) || (::GetVersion() >= 0x80000000)) {
3730  char name[256];
3731  DWORD length = sizeof (name);
3732  UserGroup_t *gr = new UserGroup_t;
3733  if (::GetUserName (name, &length)) {
3734  if (stricmp ("administrator", name) == 0) {
3735  gr->fGroup = "administrators";
3736  gr->fGid = 0;
3737  }
3738  else {
3739  gr->fGroup = "users";
3740  gr->fGid = 123;
3741  }
3742  }
3743  else {
3744  gr->fGroup = "unknown";
3745  gr->fGid = 123;
3746  }
3747  gr->fUid = 0;
3748  return gr;
3749  }
3750  struct group *grp = 0;
3751  for(int i=0;i<fNbGroups;i++) {
3752  if (gid == fGroups[i].gr_gid) {
3753  grp = &fGroups[i];
3754  break;
3755  }
3756  }
3757  if (grp) {
3758  UserGroup_t *gr = new UserGroup_t;
3759  gr->fUid = 0;
3760  gr->fGid = grp->gr_gid;
3761  gr->fGroup = grp->gr_name;
3762  return gr;
3763  }
3764  return 0;
3765 
3766 }
3767 
3768 ////////////////////////////////////////////////////////////////////////////////
3769 /// Returns all group info in the UserGroup_t structure. The only active
3770 /// fields in the UserGroup_t structure for this call are:
3771 /// fGid and fGroup
3772 /// If group = 0, returns current user's group. The returned structure
3773 /// must be deleted by the user. In case of error 0 is returned.
3774 
3776 {
3777  return GetGroupInfo(GetGid(group));
3778 }
3779 
3780 //---- environment manipulation ------------------------------------------------
3781 
3782 ////////////////////////////////////////////////////////////////////////////////
3783 /// Set environment variable.
3784 
3785 void TWinNTSystem::Setenv(const char *name, const char *value)
3786 {
3787  ::_putenv(TString::Format("%s=%s", name, value));
3788 }
3789 
3790 ////////////////////////////////////////////////////////////////////////////////
3791 /// Get environment variable.
3792 
3793 const char *TWinNTSystem::Getenv(const char *name)
3794 {
3795  const char *env = ::getenv(name);
3796  if (!env) {
3797  if (::_stricmp(name,"home") == 0 ) {
3798  env = HomeDirectory();
3799  } else if (::_stricmp(name, "rootsys") == 0 ) {
3800  env = gRootDir;
3801  }
3802  }
3803  return env;
3804 }
3805 
3806 //---- Processes ---------------------------------------------------------------
3807 
3808 ////////////////////////////////////////////////////////////////////////////////
3809 /// Execute a command.
3810 
3811 int TWinNTSystem::Exec(const char *shellcmd)
3812 {
3813  return ::system(shellcmd);
3814 }
3815 
3816 ////////////////////////////////////////////////////////////////////////////////
3817 /// Open a pipe.
3818 
3819 FILE *TWinNTSystem::OpenPipe(const char *command, const char *mode)
3820 {
3821  return ::_popen(command, mode);
3822 }
3823 
3824 ////////////////////////////////////////////////////////////////////////////////
3825 /// Close the pipe.
3826 
3828 {
3829  return ::_pclose(pipe);
3830 }
3831 
3832 ////////////////////////////////////////////////////////////////////////////////
3833 /// Get process id.
3834 
3836 {
3837  return ::getpid();
3838 }
3839 
3840 ////////////////////////////////////////////////////////////////////////////////
3841 /// Get current process handle
3842 
3844 {
3845  return fhProcess;
3846 }
3847 
3848 ////////////////////////////////////////////////////////////////////////////////
3849 /// Exit the application.
3850 
3851 void TWinNTSystem::Exit(int code, Bool_t mode)
3852 {
3853  // Insures that the files and sockets are closed before any library is unloaded
3854  // and before emptying CINT.
3855  if (gROOT) {
3856  gROOT->CloseFiles();
3857  if (gROOT->GetListOfBrowsers()) {
3858  // GetListOfBrowsers()->Delete() creates problems when a browser is
3859  // created on the stack, calling CloseWindow() solves the problem
3860  //gROOT->GetListOfBrowsers()->Delete();
3861  TBrowser *b;
3862  TIter next(gROOT->GetListOfBrowsers());
3863  while ((b = (TBrowser*) next()))
3864  gROOT->ProcessLine(TString::Format("((TBrowser*)0x%lx)->GetBrowserImp()->GetMainFrame()->CloseWindow();",
3865  (ULong_t)b));
3866  }
3867  gROOT->EndOfProcessCleanups();
3868  }
3869  if (gInterpreter) {
3870  gInterpreter->ResetGlobals();
3871  }
3872  gVirtualX->CloseDisplay();
3873 
3874  if (mode) {
3875  ::exit(code);
3876  } else {
3877  ::_exit(code);
3878  }
3879 }
3880 
3881 ////////////////////////////////////////////////////////////////////////////////
3882 /// Abort the application.
3883 
3885 {
3886  ::abort();
3887 }
3888 
3889 //---- Standard output redirection ---------------------------------------------
3890 
3891 ////////////////////////////////////////////////////////////////////////////////
3892 /// Redirect standard output (stdout, stderr) to the specified file.
3893 /// If the file argument is 0 the output is set again to stderr, stdout.
3894 /// The second argument specifies whether the output should be added to the
3895 /// file ("a", default) or the file be truncated before ("w").
3896 /// This function saves internally the current state into a static structure.
3897 /// The call can be made reentrant by specifying the opaque structure pointed
3898 /// by 'h', which is filled with the relevant information. The handle 'h'
3899 /// obtained on the first call must then be used in any subsequent call,
3900 /// included ShowOutput, to display the redirected output.
3901 /// Returns 0 on success, -1 in case of error.
3902 
3903 Int_t TWinNTSystem::RedirectOutput(const char *file, const char *mode,
3905 {
3906  FILE *fout, *ferr;
3907  static int fd1=0, fd2=0;
3908  static fpos_t pos1=0, pos2=0;
3909  // Instance to be used if the caller does not passes 'h'
3910  static RedirectHandle_t loch;
3911  Int_t rc = 0;
3912 
3913  // Which handle to use ?
3914  RedirectHandle_t *xh = (h) ? h : &loch;
3915 
3916  if (file) {
3917  // Make sure mode makes sense; default "a"
3918  const char *m = (mode[0] == 'a' || mode[0] == 'w') ? mode : "a";
3919 
3920  // Current file size
3921  xh->fReadOffSet = 0;
3922  if (m[0] == 'a') {
3923  // If the file exists, save the current size
3924  FileStat_t st;
3925  if (!gSystem->GetPathInfo(file, st))
3926  xh->fReadOffSet = (st.fSize > 0) ? st.fSize : xh->fReadOffSet;
3927  }
3928  xh->fFile = file;
3929 
3930  fflush(stdout);
3931  fgetpos(stdout, &pos1);
3932  fd1 = _dup(fileno(stdout));
3933  // redirect stdout & stderr
3934  if ((fout = freopen(file, m, stdout)) == 0) {
3935  SysError("RedirectOutput", "could not freopen stdout");
3936  if (fd1 > 0) {
3937  _dup2(fd1, fileno(stdout));
3938  close(fd1);
3939  }
3940  clearerr(stdout);
3941  fsetpos(stdout, &pos1);
3942  fd1 = fd2 = 0;
3943  return -1;
3944  }
3945  fflush(stderr);
3946  fgetpos(stderr, &pos2);
3947  fd2 = _dup(fileno(stderr));
3948  if ((ferr = freopen(file, m, stderr)) == 0) {
3949  SysError("RedirectOutput", "could not freopen stderr");
3950  if (fd1 > 0) {
3951  _dup2(fd1, fileno(stdout));
3952  close(fd1);
3953  }
3954  clearerr(stdout);
3955  fsetpos(stdout, &pos1);
3956  if (fd2 > 0) {
3957  _dup2(fd2, fileno(stderr));
3958  close(fd2);
3959  }
3960  clearerr(stderr);
3961  fsetpos(stderr, &pos2);
3962  fd1 = fd2 = 0;
3963  return -1;
3964  }
3965  if (m[0] == 'a') {
3966  fseek(fout, 0, SEEK_END);
3967  fseek(ferr, 0, SEEK_END);
3968  }
3969  } else {
3970  // Restore stdout & stderr
3971  fflush(stdout);
3972  if (fd1) {
3973  if (fd1 > 0) {
3974  if (_dup2(fd1, fileno(stdout))) {
3975  SysError("RedirectOutput", "could not restore stdout");
3976  rc = -1;
3977  }
3978  close(fd1);
3979  }
3980  clearerr(stdout);
3981  fsetpos(stdout, &pos1);
3982  fd1 = 0;
3983  }
3984 
3985  fflush(stderr);
3986  if (fd2) {
3987  if (fd2 > 0) {
3988  if (_dup2(fd2, fileno(stderr))) {
3989  SysError("RedirectOutput", "could not restore stderr");
3990  rc = -1;
3991  }
3992  close(fd2);
3993  }
3994  clearerr(stderr);
3995  fsetpos(stderr, &pos2);
3996  fd2 = 0;
3997  }
3998 
3999  // Reset the static instance, if using that
4000  if (xh == &loch)
4001  xh->Reset();
4002  }
4003  return rc;
4004 }
4005 
4006 //---- dynamic loading and linking ---------------------------------------------
4007 
4008 ////////////////////////////////////////////////////////////////////////////////
4009 /// Add a new directory to the dynamic path.
4010 
4011 void TWinNTSystem::AddDynamicPath(const char *dir)
4012 {
4013  if (dir) {
4014  TString oldpath = DynamicPath(0, kFALSE);
4015  oldpath.Append(";");
4016  oldpath.Append(dir);
4017  DynamicPath(oldpath);
4018  }
4019 }
4020 
4021 ////////////////////////////////////////////////////////////////////////////////
4022 /// Return the dynamic path (used to find shared libraries).
4023 
4025 {
4026  return DynamicPath(0, kFALSE);
4027 }
4028 
4029 ////////////////////////////////////////////////////////////////////////////////
4030 /// Set the dynamic path to a new value.
4031 /// If the value of 'path' is zero, the dynamic path is reset to its
4032 /// default value.
4033 
4034 void TWinNTSystem::SetDynamicPath(const char *path)
4035 {
4036  if (!path)
4037  DynamicPath(0, kTRUE);
4038  else
4039  DynamicPath(path);
4040 }
4041 
4042 ////////////////////////////////////////////////////////////////////////////////
4043 /// Returns and updates sLib to the path of a dynamic library
4044 /// (searches for library in the dynamic library search path).
4045 /// If no file name extension is provided it tries .DLL.
4046 
4048 {
4049  int len = sLib.Length();
4050  if (len > 4 && (!stricmp(sLib.Data()+len-4, ".dll"))) {
4052  return sLib;
4053  } else {
4054  TString sLibDll(sLib);
4055  sLibDll += ".dll";
4056  if (gSystem->FindFile(GetDynamicPath(), sLibDll, kReadPermission)) {
4057  sLibDll.Swap(sLib);
4058  return sLib;
4059  }
4060  }
4061 
4062  if (!quiet) {
4063  Error("DynamicPathName",
4064  "%s does not exist in %s,\nor has wrong file extension (.dll)",
4065  sLib.Data(), GetDynamicPath());
4066  }
4067  return 0;
4068 }
4069 
4070 ////////////////////////////////////////////////////////////////////////////////
4071 /// Load a shared library. Returns 0 on successful loading, 1 in
4072 /// case lib was already loaded and -1 in case lib does not exist
4073 /// or in case of error.
4074 
4075 int TWinNTSystem::Load(const char *module, const char *entry, Bool_t system)
4076 {
4077  return TSystem::Load(module, entry, system);
4078 }
4079 
4080 /* nonstandard extension used : zero-sized array in struct/union */
4081 #pragma warning(push)
4082 #pragma warning(disable:4200)
4083 ////////////////////////////////////////////////////////////////////////////////
4084 /// Get list of shared libraries loaded at the start of the executable.
4085 /// Returns 0 in case list cannot be obtained or in case of error.
4086 
4088 {
4089  char winDrive[256];
4090  char winDir[256];
4091  char winName[256];
4092  char winExt[256];
4093 
4094  if (!gApplication) return 0;
4095 
4096  static Bool_t once = kFALSE;
4097  static TString linkedLibs;
4098 
4099  if (!linkedLibs.IsNull())
4100  return linkedLibs;
4101 
4102  if (once)
4103  return 0;
4104 
4105  char *exe = gSystem->Which(Getenv("PATH"), gApplication->Argv(0),
4107  if (!exe) {
4108  once = kTRUE;
4109  return 0;
4110  }
4111 
4112  HANDLE hFile, hMapping;
4113  void *basepointer;
4114 
4115  if((hFile = CreateFile(exe,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_FLAG_SEQUENTIAL_SCAN,0))==INVALID_HANDLE_VALUE) {
4116  delete [] exe;
4117  return 0;
4118  }
4119  if(!(hMapping = CreateFileMapping(hFile,0,PAGE_READONLY|SEC_COMMIT,0,0,0))) {
4120  CloseHandle(hFile);
4121  delete [] exe;
4122  return 0;
4123  }
4124  if(!(basepointer = MapViewOfFile(hMapping,FILE_MAP_READ,0,0,0))) {
4125  CloseHandle(hMapping);
4126  CloseHandle(hFile);
4127  delete [] exe;
4128  return 0;
4129  }
4130 
4131  int sect;
4132  IMAGE_DOS_HEADER *dos_head = (IMAGE_DOS_HEADER *)basepointer;
4133  struct header {
4134  DWORD signature;
4135  IMAGE_FILE_HEADER _head;
4136  IMAGE_OPTIONAL_HEADER opt_head;
4137  IMAGE_SECTION_HEADER section_header[]; // actual number in NumberOfSections
4138  };
4139  struct header *pheader;
4140  const IMAGE_SECTION_HEADER * section_header;
4141 
4142  if(dos_head->e_magic!='ZM') {
4143  delete [] exe;
4144  return 0;
4145  } // verify DOS-EXE-Header
4146  // after end of DOS-EXE-Header: offset to PE-Header
4147  pheader = (struct header *)((char*)dos_head + dos_head->e_lfanew);
4148 
4149  if(IsBadReadPtr(pheader,sizeof(struct header))) { // start of PE-Header
4150  delete [] exe;
4151  return 0;
4152  }
4153  if(pheader->signature!=IMAGE_NT_SIGNATURE) { // verify PE format
4154  switch((unsigned short)pheader->signature) {
4155  case IMAGE_DOS_SIGNATURE:
4156  delete [] exe;
4157  return 0;
4158  case IMAGE_OS2_SIGNATURE:
4159  delete [] exe;
4160  return 0;
4161  case IMAGE_OS2_SIGNATURE_LE:
4162  delete [] exe;
4163  return 0;
4164  default: // unknown signature
4165  delete [] exe;
4166  return 0;
4167  }
4168  }
4169 #define isin(address,start,length) ((address)>=(start) && (address)<(start)+(length))
4170  TString odump;
4171  // walk through sections
4172  for(sect=0,section_header=pheader->section_header;
4173  sect<pheader->_head.NumberOfSections;sect++,section_header++) {
4174  int directory;
4175  const void * const section_data =
4176  (char*)basepointer + section_header->PointerToRawData;
4177  for(directory=0;directory<IMAGE_NUMBEROF_DIRECTORY_ENTRIES;directory++) {
4178  if(isin(pheader->opt_head.DataDirectory[directory].VirtualAddress,
4179  section_header->VirtualAddress,
4180  section_header->SizeOfRawData)) {
4181  const IMAGE_IMPORT_DESCRIPTOR *stuff_start =
4182  (IMAGE_IMPORT_DESCRIPTOR *)((char*)section_data +
4183  (pheader->opt_head.DataDirectory[directory].VirtualAddress -
4184  section_header->VirtualAddress));
4185  // (virtual address of stuff - virtual address of section) =
4186  // offset of stuff in section
4187  const unsigned stuff_length =
4188  pheader->opt_head.DataDirectory[directory].Size;
4189  if(directory == IMAGE_DIRECTORY_ENTRY_IMPORT) {
4190  while(!IsBadReadPtr(stuff_start,sizeof(*stuff_start)) &&
4191  stuff_start->Name) {
4192  TString dll = (char*)section_data +
4193  ((DWORD)(stuff_start->Name)) -
4194  section_header->VirtualAddress;
4195  if (dll.EndsWith(".dll")) {
4196  char *dllPath = DynamicPathName(dll, kTRUE);
4197  if (dllPath) {
4198  char *winPath = getenv("windir");
4199  _splitpath(winPath,winDrive,winDir,winName,winExt);
4200  if(!strstr(dllPath, winDir)) {
4201  if (!linkedLibs.IsNull())
4202  linkedLibs += " ";
4203  linkedLibs += dllPath;
4204  }
4205  }
4206  delete [] dllPath;
4207  }
4208  stuff_start++;
4209  }
4210  }
4211  }
4212  }
4213  }
4214 
4215  UnmapViewOfFile(basepointer);
4216  CloseHandle(hMapping);
4217  CloseHandle(hFile);
4218 
4219  delete [] exe;
4220 
4221  once = kTRUE;
4222 
4223  if (linkedLibs.IsNull())
4224  return 0;
4225 
4226  return linkedLibs;
4227 }
4228 #pragma warning(pop)
4229 
4230 ////////////////////////////////////////////////////////////////////////////////
4231 /// Return a space separated list of loaded shared libraries.
4232 /// This list is of a format suitable for a linker, i.e it may contain
4233 /// -Lpathname and/or -lNameOfLib.
4234 /// Option can be any of:
4235 /// S: shared libraries loaded at the start of the executable, because
4236 /// they were specified on the link line.
4237 /// D: shared libraries dynamically loaded after the start of the program.
4238 /// L: list the .LIB rather than the .DLL (this is intended for linking)
4239 /// [This options is not the default]
4240 
4241 const char *TWinNTSystem::GetLibraries(const char *regexp, const char *options,
4242  Bool_t isRegexp)
4243 {
4244  TString libs(TSystem::GetLibraries(regexp, options, isRegexp));
4245  TString ntlibs;
4246  TString opt = options;
4247 
4248  if ( (opt.First('L')!=kNPOS) ) {
4249  TRegexp separator("[^ \\t\\s]+");
4250  TRegexp user_dll("\\.dll$");
4251  TRegexp user_lib("\\.lib$");
4252  FileStat_t sbuf;
4253  TString s;
4254  Ssiz_t start, index, end;
4255  start = index = end = 0;
4256 
4257  while ((start < libs.Length()) && (index != kNPOS)) {
4258  index = libs.Index(separator, &end, start);
4259  if (index >= 0) {
4260  // Change .dll into .lib and remove the
4261  // path info if it not accessible.
4262  s = libs(index, end);
4263  if (s.Index(user_dll) != kNPOS) {
4264  s.ReplaceAll(".dll",".lib");
4265  if ( GetPathInfo( s, sbuf ) != 0 ) {
4266  s.Replace( 0, s.Last('/')+1, 0, 0);
4267  s.Replace( 0, s.Last('\\')+1, 0, 0);
4268  }
4269  } else if (s.Index(user_lib) != kNPOS) {
4270  if ( GetPathInfo( s, sbuf ) != 0 ) {
4271  s.Replace( 0, s.Last('/')+1, 0, 0);
4272  s.Replace( 0, s.Last('\\')+1, 0, 0);
4273  }
4274  }
4275  if (!ntlibs.IsNull()) ntlibs.Append(" ");
4276  ntlibs.Append(s);
4277  }
4278  start += end+1;
4279  }
4280  } else {
4281  ntlibs = libs;
4282  }
4283 
4284  fListLibs = ntlibs;
4285  fListLibs.ReplaceAll("/","\\");
4286  return fListLibs;
4287 }
4288 
4289 //---- Time & Date -------------------------------------------------------------
4290 
4291 ////////////////////////////////////////////////////////////////////////////////
4292 /// Add timer to list of system timers.
4293 
4295 {
4296  TSystem::AddTimer(ti);
4297 }
4298 
4299 ////////////////////////////////////////////////////////////////////////////////
4300 /// Remove timer from list of system timers.
4301 
4303 {
4304  if (!ti) return 0;
4305 
4306  TTimer *t = TSystem::RemoveTimer(ti);
4307  return t;
4308 }
4309 
4310 ////////////////////////////////////////////////////////////////////////////////
4311 /// Special Thread to check asynchronous timers.
4312 
4314 {
4315  while (1) {
4316  if (!fInsideNotify)
4319  }
4320 }
4321 
4322 ////////////////////////////////////////////////////////////////////////////////
4323 /// Handle and dispatch timers. If mode = kTRUE dispatch synchronous
4324 /// timers else a-synchronous timers.
4325 
4327 {
4328  if (!fTimers) return kFALSE;
4329 
4330  fInsideNotify = kTRUE;
4331 
4333  TTimer *t;
4334  Bool_t timedout = kFALSE;
4335 
4336  while ((t = (TTimer *) it.Next())) {
4337  // NB: the timer resolution is added in TTimer::CheckTimer()
4338  TTime now = Now();
4339  if (mode && t->IsSync()) {
4340  if (t->CheckTimer(now)) {
4341  timedout = kTRUE;
4342  }
4343  } else if (!mode && t->IsAsync()) {
4344  if (t->CheckTimer(now)) {
4345  timedout = kTRUE;
4346  }
4347  }
4348  }
4350 
4351  return timedout;
4352 }
4353 
4354 const Double_t gTicks = 1.0e-7;
4355 ////////////////////////////////////////////////////////////////////////////////
4356 ///
4357 
4359 {
4360  union {
4361  FILETIME ftFileTime;
4362  __int64 ftInt64;
4363  } ftRealTime; // time the process has spent in kernel mode
4364 
4365  ::GetSystemTimeAsFileTime(&ftRealTime.ftFileTime);
4366  return (Double_t)ftRealTime.ftInt64 * gTicks;
4367 }
4368 
4369 ////////////////////////////////////////////////////////////////////////////////
4370 ///
4371 
4373 {
4374  OSVERSIONINFO OsVersionInfo;
4375 
4376 //*-* Value Platform
4377 //*-* ----------------------------------------------------
4378 //*-* VER_PLATFORM_WIN32s Win32s on Windows 3.1
4379 //*-* VER_PLATFORM_WIN32_WINDOWS Win32 on Windows 95
4380 //*-* VER_PLATFORM_WIN32_NT Windows NT
4381 //*-*
4382 
4383  OsVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
4384  GetVersionEx(&OsVersionInfo);
4385  if (OsVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) {
4386  DWORD ret;
4387  FILETIME ftCreate, // when the process was created
4388  ftExit; // when the process exited
4389 
4390  union {
4391  FILETIME ftFileTime;
4392  __int64 ftInt64;
4393  } ftKernel; // time the process has spent in kernel mode
4394 
4395  union {
4396  FILETIME ftFileTime;
4397  __int64 ftInt64;
4398  } ftUser; // time the process has spent in user mode
4399 
4400  HANDLE hThread = GetCurrentThread();
4401  ret = GetThreadTimes (hThread, &ftCreate, &ftExit,
4402  &ftKernel.ftFileTime,
4403  &ftUser.ftFileTime);
4404  if (ret != TRUE){
4405  ret = ::GetLastError();
4406  ::Error("GetCPUTime", " Error on GetProcessTimes 0x%lx", (int)ret);
4407  }
4408 
4409  // Process times are returned in a 64-bit structure, as the number of
4410  // 100 nanosecond ticks since 1 January 1601. User mode and kernel mode
4411  // times for this process are in separate 64-bit structures.
4412  // To convert to floating point seconds, we will:
4413  // Convert sum of high 32-bit quantities to 64-bit int
4414 
4415  return (Double_t) (ftKernel.ftInt64 + ftUser.ftInt64) * gTicks;
4416  } else {
4417  return GetRealTime();
4418  }
4419 }
4420 
4421 ////////////////////////////////////////////////////////////////////////////////
4422 /// Get current time in milliseconds since 0:00 Jan 1 1995.
4423 
4425 {
4426  static time_t jan95 = 0;
4427  if (!jan95) {
4428  struct tm tp;
4429  tp.tm_year = 95;
4430  tp.tm_mon = 0;
4431  tp.tm_mday = 1;
4432  tp.tm_hour = 0;
4433  tp.tm_min = 0;
4434  tp.tm_sec = 0;
4435  tp.tm_isdst = -1;
4436 
4437  jan95 = mktime(&tp);
4438  if ((int)jan95 == -1) {
4439  ::SysError("TWinNTSystem::Now", "error converting 950001 0:00 to time_t");
4440  return 0;
4441  }
4442  }
4443 
4444  _timeb now;
4445  _ftime(&now);
4446  return TTime((now.time-(Long_t)jan95)*1000 + now.millitm);
4447 }
4448 
4449 ////////////////////////////////////////////////////////////////////////////////
4450 /// Sleep milliSec milli seconds.
4451 /// The Sleep function suspends the execution of the CURRENT THREAD for
4452 /// a specified interval.
4453 
4455 {
4456  ::Sleep(milliSec);
4457 }
4458 
4459 ////////////////////////////////////////////////////////////////////////////////
4460 /// Select on file descriptors. The timeout to is in millisec.
4461 
4463 {
4464  Int_t rc = -4;
4465 
4466  TFdSet rd, wr;
4467  Int_t mxfd = -1;
4468  TIter next(act);
4469  TFileHandler *h = 0;
4470  while ((h = (TFileHandler *) next())) {
4471  Int_t fd = h->GetFd();
4472  if (h->HasReadInterest())
4473  rd.Set(fd);
4474  if (h->HasWriteInterest())
4475  wr.Set(fd);
4476  h->ResetReadyMask();
4477  }
4478  rc = WinNTSelect(&rd, &wr, to);
4479 
4480  // Set readiness bits
4481  if (rc > 0) {
4482  next.Reset();
4483  while ((h = (TFileHandler *) next())) {
4484  Int_t fd = h->GetFd();
4485  if (rd.IsSet(fd))
4486  h->SetReadReady();
4487  if (wr.IsSet(fd))
4488  h->SetWriteReady();
4489  }
4490  }
4491 
4492  return rc;
4493 }
4494 
4495 ////////////////////////////////////////////////////////////////////////////////
4496 /// Select on the file descriptor related to file handler h.
4497 /// The timeout to is in millisec.
4498 
4500 {
4501  Int_t rc = -4;
4502 
4503  TFdSet rd, wr;
4504  Int_t fd = -1;
4505  if (h) {
4506  fd = h->GetFd();
4507  if (h->HasReadInterest())
4508  rd.Set(fd);
4509  if (h->HasWriteInterest())
4510  wr.Set(fd);
4511  h->ResetReadyMask();
4512  rc = WinNTSelect(&rd, &wr, to);
4513  }
4514 
4515  // Fill output lists, if required
4516  if (rc > 0) {
4517  if (rd.IsSet(fd))
4518  h->SetReadReady();
4519  if (wr.IsSet(fd))
4520  h->SetWriteReady();
4521  }
4522 
4523  return rc;
4524 }
4525 
4526 //---- RPC ---------------------------------------------------------------------
4527 ////////////////////////////////////////////////////////////////////////////////
4528 /// Get port # of internet service.
4529 
4530 int TWinNTSystem::GetServiceByName(const char *servicename)
4531 {
4532  struct servent *sp;
4533 
4534  if ((sp = ::getservbyname(servicename, kProtocolName)) == 0) {
4535  Error("GetServiceByName", "no service \"%s\" with protocol \"%s\"\n",
4536  servicename, kProtocolName);
4537  return -1;
4538  }
4539  return ::ntohs(sp->s_port);
4540 }
4541 
4542 ////////////////////////////////////////////////////////////////////////////////
4543 
4545 {
4546  // Get name of internet service.
4547 
4548  struct servent *sp;
4549 
4550  if ((sp = ::getservbyport(::htons(port), kProtocolName)) == 0) {
4551  return Form("%d", port);
4552  }
4553  return sp->s_name;
4554 }
4555 
4556 ////////////////////////////////////////////////////////////////////////////////
4557 /// Get Internet Protocol (IP) address of host.
4558 
4560 {
4561  struct hostent *host_ptr;
4562  const char *host;
4563  int type;
4564  UInt_t addr; // good for 4 byte addresses
4565 
4566  if ((addr = ::inet_addr(hostname)) != INADDR_NONE) {
4567  type = AF_INET;
4568  if ((host_ptr = ::gethostbyaddr((const char *)&addr,
4569  sizeof(addr), AF_INET))) {
4570  host = host_ptr->h_name;
4571  TInetAddress a(host, ntohl(addr), type);
4572  UInt_t addr2;
4573  Int_t i;
4574  for (i = 1; host_ptr->h_addr_list[i]; i++) {
4575  memcpy(&addr2, host_ptr->h_addr_list[i], host_ptr->h_length);
4576  a.AddAddress(ntohl(addr2));
4577  }
4578  for (i = 0; host_ptr->h_aliases[i]; i++)
4579  a.AddAlias(host_ptr->h_aliases[i]);
4580  return a;
4581  } else {
4582  host = "UnNamedHost";
4583  }
4584  } else if ((host_ptr = ::gethostbyname(hostname))) {
4585  // Check the address type for an internet host
4586  if (host_ptr->h_addrtype != AF_INET) {
4587  Error("GetHostByName", "%s is not an internet host\n", hostname);
4588  return TInetAddress();
4589  }
4590  memcpy(&addr, host_ptr->h_addr, host_ptr->h_length);
4591  host = host_ptr->h_name;
4592  type = host_ptr->h_addrtype;
4593  TInetAddress a(host, ntohl(addr), type);
4594  UInt_t addr2;
4595  Int_t i;
4596  for (i = 1; host_ptr->h_addr_list[i]; i++) {
4597  memcpy(&addr2, host_ptr->h_addr_list[i], host_ptr->h_length);
4598  a.AddAddress(ntohl(addr2));
4599  }
4600  for (i = 0; host_ptr->h_aliases[i]; i++)
4601  a.AddAlias(host_ptr->h_aliases[i]);
4602  return a;
4603  } else {
4604  if (gDebug > 0) Error("GetHostByName", "unknown host %s", hostname);
4605  return TInetAddress(hostname, 0, -1);
4606  }
4607 
4608  return TInetAddress(host, ::ntohl(addr), type);
4609 }
4610 
4611 ////////////////////////////////////////////////////////////////////////////////
4612 /// Get Internet Protocol (IP) address of remote host and port #.
4613 
4615 {
4616  SOCKET sock = socket;
4617  struct sockaddr_in addr;
4618  int len = sizeof(addr);
4619 
4620  if (::getpeername(sock, (struct sockaddr *)&addr, &len) == SOCKET_ERROR) {
4621  ::SysError("GetPeerName", "getpeername");
4622  return TInetAddress();
4623  }
4624 
4625  struct hostent *host_ptr;
4626  const char *hostname;
4627  int family;
4628  UInt_t iaddr;
4629 
4630  if ((host_ptr = ::gethostbyaddr((const char *)&addr.sin_addr,
4631  sizeof(addr.sin_addr), AF_INET))) {
4632  memcpy(&iaddr, host_ptr->h_addr, host_ptr->h_length);
4633  hostname = host_ptr->h_name;
4634  family = host_ptr->h_addrtype;
4635  } else {
4636  memcpy(&iaddr, &addr.sin_addr, sizeof(addr.sin_addr));
4637  hostname = "????";
4638  family = AF_INET;
4639  }
4640 
4641  return TInetAddress(hostname, ::ntohl(iaddr), family, ::ntohs(addr.sin_port));
4642 }
4643 
4644 ////////////////////////////////////////////////////////////////////////////////
4645 /// Get Internet Protocol (IP) address of host and port #.
4646 
4648 {
4649  SOCKET sock = socket;
4650  struct sockaddr_in addr;
4651  int len = sizeof(addr);
4652 
4653  if (::getsockname(sock, (struct sockaddr *)&addr, &len) == SOCKET_ERROR) {
4654  ::SysError("GetSockName", "getsockname");
4655  return TInetAddress();
4656  }
4657 
4658  struct hostent *host_ptr;
4659  const char *hostname;
4660  int family;
4661  UInt_t iaddr;
4662 
4663  if ((host_ptr = ::gethostbyaddr((const char *)&addr.sin_addr,
4664  sizeof(addr.sin_addr), AF_INET))) {
4665  memcpy(&iaddr, host_ptr->h_addr, host_ptr->h_length);
4666  hostname = host_ptr->h_name;
4667  family = host_ptr->h_addrtype;
4668  } else {
4669  memcpy(&iaddr, &addr.sin_addr, sizeof(addr.sin_addr));
4670  hostname = "????";
4671  family = AF_INET;
4672  }
4673 
4674  return TInetAddress(hostname, ::ntohl(iaddr), family, ::ntohs(addr.sin_port));
4675 }
4676 
4677 ////////////////////////////////////////////////////////////////////////////////
4678 /// Announce unix domain service.
4679 
4680 int TWinNTSystem::AnnounceUnixService(int port, int backlog)
4681 {
4682  SOCKET sock;
4683 
4684  // Create socket
4685  if ((sock = ::socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
4686  ::SysError("TWinNTSystem::AnnounceUnixService", "socket");
4687  return -1;
4688  }
4689 
4690  struct sockaddr_in inserver;
4691  memset(&inserver, 0, sizeof(inserver));
4692  inserver.sin_family = AF_INET;
4693  inserver.sin_addr.s_addr = ::htonl(INADDR_LOOPBACK);
4694  inserver.sin_port = port;
4695 
4696  // Bind socket
4697  if (port > 0) {
4698  if (::bind(sock, (struct sockaddr*) &inserver, sizeof(inserver)) == SOCKET_ERROR) {
4699  ::SysError("TWinNTSystem::AnnounceUnixService", "bind");
4700  return -2;
4701  }
4702  }
4703  // Start accepting connections
4704  if (::listen(sock, backlog)) {
4705  ::SysError("TWinNTSystem::AnnounceUnixService", "listen");
4706  return -1;
4707  }
4708  return (int)sock;
4709 }
4710 
4711 ////////////////////////////////////////////////////////////////////////////////
4712 /// Open a socket on path 'sockpath', bind to it and start listening for Unix
4713 /// domain connections to it. Returns socket fd or -1.
4714 
4715 int TWinNTSystem::AnnounceUnixService(const char *sockpath, int backlog)
4716 {
4717  if (!sockpath || strlen(sockpath) <= 0) {
4718  ::SysError("TWinNTSystem::AnnounceUnixService", "socket path undefined");
4719  return -1;
4720  }
4721 
4722  struct sockaddr_in myaddr;
4723  FILE * fp;
4724  int len = sizeof myaddr;
4725  int rc;
4726  int sock;
4727 
4728  // Create socket
4729  if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
4730  ::SysError("TWinNTSystem::AnnounceUnixService", "socket");
4731  return -1;
4732  }
4733 
4734  memset(&myaddr, 0, sizeof(myaddr));
4735  myaddr.sin_port = 0;
4736  myaddr.sin_family = AF_INET;
4737  myaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
4738 
4739  rc = bind(sock, (struct sockaddr *)&myaddr, len);
4740  if (rc) {
4741  ::SysError("TWinNTSystem::AnnounceUnixService", "bind");
4742  return rc;
4743  }
4744  rc = getsockname(sock, (struct sockaddr *)&myaddr, &len);
4745  if (rc) {
4746  ::SysError("TWinNTSystem::AnnounceUnixService", "getsockname");
4747  return rc;
4748  }
4749  TString socketpath = sockpath;
4750  socketpath.ReplaceAll("/", "\\");
4751  fp = fopen(socketpath, "wb");
4752  if (!fp) {
4753  ::SysError("TWinNTSystem::AnnounceUnixService", "fopen");
4754  return -1;
4755  }
4756  fprintf(fp, "%d", myaddr.sin_port);
4757  fclose(fp);
4758 
4759  // Start accepting connections
4760  if (listen(sock, backlog)) {
4761  ::SysError("TWinNTSystem::AnnounceUnixService", "listen");
4762  return -1;
4763  }
4764 
4765  return sock;
4766 }
4767 
4768 ////////////////////////////////////////////////////////////////////////////////
4769 /// Close socket.
4770 
4771 void TWinNTSystem::CloseConnection(int socket, Bool_t force)
4772 {
4773  if (socket == -1) return;
4774  SOCKET sock = socket;
4775 
4776  if (force) {
4777  ::shutdown(sock, 2);
4778  }
4779  struct linger linger = {0, 0};
4780  ::setsockopt(sock, SOL_SOCKET, SO_LINGER, (char *) &linger, sizeof(linger));
4781  while (::closesocket(sock) == SOCKET_ERROR && WSAGetLastError() == WSAEINTR) {
4783  }
4784 }
4785 
4786 ////////////////////////////////////////////////////////////////////////////////
4787 /// Receive a buffer headed by a length indicator. Length is the size of
4788 /// the buffer. Returns the number of bytes received in buf or -1 in
4789 /// case of error.
4790 
4791 int TWinNTSystem::RecvBuf(int sock, void *buf, int length)
4792 {
4793  Int_t header;
4794 
4795  if (WinNTRecv(sock, &header, sizeof(header), 0) > 0) {
4796  int count = ::ntohl(header);
4797 
4798  if (count > length) {
4799  Error("RecvBuf", "record header exceeds buffer size");
4800  return -1;
4801  } else if (count > 0) {
4802  if (WinNTRecv(sock, buf, count, 0) < 0) {
4803  Error("RecvBuf", "cannot receive buffer");
4804  return -1;
4805  }
4806  }
4807  return count;
4808  }
4809  return -1;
4810 }
4811 
4812 ////////////////////////////////////////////////////////////////////////////////
4813 /// Send a buffer headed by a length indicator. Returns length of sent buffer
4814 /// or -1 in case of error.
4815 
4816 int TWinNTSystem::SendBuf(int sock, const void *buf, int length)
4817 {
4818  Int_t header = ::htonl(length);
4819 
4820  if (WinNTSend(sock, &header, sizeof(header), 0) < 0) {
4821  Error("SendBuf", "cannot send header");
4822  return -1;
4823  }
4824  if (length > 0) {
4825  if (WinNTSend(sock, buf, length, 0) < 0) {
4826  Error("SendBuf", "cannot send buffer");
4827  return -1;
4828  }
4829  }
4830  return length;
4831 }
4832 
4833 ////////////////////////////////////////////////////////////////////////////////
4834 /// Receive exactly length bytes into buffer. Use opt to receive out-of-band
4835 /// data or to have a peek at what is in the buffer (see TSocket). Buffer
4836 /// must be able to store at least length bytes. Returns the number of
4837 /// bytes received (can be 0 if other side of connection was closed) or -1
4838 /// in case of error, -2 in case of MSG_OOB and errno == EWOULDBLOCK, -3
4839 /// in case of MSG_OOB and errno == EINVAL and -4 in case of kNoBlock and
4840 /// errno == EWOULDBLOCK. Returns -5 if pipe broken or reset by peer
4841 /// (EPIPE || ECONNRESET).
4842 
4843 int TWinNTSystem::RecvRaw(int sock, void *buf, int length, int opt)
4844 {
4845  int flag;
4846 
4847  switch (opt) {
4848  case kDefault:
4849  flag = 0;
4850  break;
4851  case kOob:
4852  flag = MSG_OOB;
4853  break;
4854  case kPeek:
4855  flag = MSG_PEEK;
4856  break;
4857  case kDontBlock:
4858  flag = -1;
4859  break;
4860  default:
4861  flag = 0;
4862  break;
4863  }
4864 
4865  int n;
4866  if ((n = WinNTRecv(sock, buf, length, flag)) <= 0) {
4867  if (n == -1) {
4868  Error("RecvRaw", "cannot receive buffer");
4869  }
4870  return n;
4871  }
4872  return n;
4873 }
4874 
4875 ////////////////////////////////////////////////////////////////////////////////
4876 /// Send exactly length bytes from buffer. Use opt to send out-of-band
4877 /// data (see TSocket). Returns the number of bytes sent or -1 in case of
4878 /// error. Returns -4 in case of kNoBlock and errno == EWOULDBLOCK.
4879 /// Returns -5 if pipe broken or reset by peer (EPIPE || ECONNRESET).
4880 
4881 int TWinNTSystem::SendRaw(int sock, const void *buf, int length, int opt)
4882 {
4883  int flag;
4884 
4885  switch (opt) {
4886  case kDefault:
4887  flag = 0;
4888  break;
4889  case kOob:
4890  flag = MSG_OOB;
4891  break;
4892  case kDontBlock:
4893  flag = -1;
4894  break;
4895  case kPeek: // receive only option (see RecvRaw)
4896  default:
4897  flag = 0;
4898  break;
4899  }
4900 
4901  int n;
4902  if ((n = WinNTSend(sock, buf, length, flag)) <= 0) {
4903  if (n == -1 && GetErrno() != EINTR) {
4904  Error("SendRaw", "cannot send buffer");
4905  }
4906  return n;
4907  }
4908  return n;
4909 }
4910 
4911 ////////////////////////////////////////////////////////////////////////////////
4912 /// Set socket option.
4913 
4914 int TWinNTSystem::SetSockOpt(int socket, int opt, int value)
4915 {
4916  u_long val = value;
4917  if (socket == -1) return -1;
4918  SOCKET sock = socket;
4919 
4920  switch (opt) {
4921  case kSendBuffer:
4922  if (::setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char*)&val, sizeof(val)) == SOCKET_ERROR) {
4923  ::SysError("SetSockOpt", "setsockopt(SO_SNDBUF)");
4924  return -1;
4925  }
4926  break;
4927  case kRecvBuffer:
4928  if (::setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*)&val, sizeof(val)) == SOCKET_ERROR) {
4929  ::SysError("SetSockOpt", "setsockopt(SO_RCVBUF)");
4930  return -1;
4931  }
4932  break;
4933  case kOobInline:
4934  if (::setsockopt(sock, SOL_SOCKET, SO_OOBINLINE, (char*)&val, sizeof(val)) == SOCKET_ERROR) {
4935  SysError("SetSockOpt", "setsockopt(SO_OOBINLINE)");
4936  return -1;
4937  }
4938  break;
4939  case kKeepAlive:
4940  if (::setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char*)&val, sizeof(val)) == SOCKET_ERROR) {
4941  ::SysError("SetSockOpt", "setsockopt(SO_KEEPALIVE)");
4942  return -1;
4943  }
4944  break;
4945  case kReuseAddr:
4946  if (::setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&val, sizeof(val)) == SOCKET_ERROR) {
4947  ::SysError("SetSockOpt", "setsockopt(SO_REUSEADDR)");
4948  return -1;
4949  }
4950  break;
4951  case kNoDelay:
4952  if (::setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char*)&val, sizeof(val)) == SOCKET_ERROR) {
4953  ::SysError("SetSockOpt", "setsockopt(TCP_NODELAY)");
4954  return -1;
4955  }
4956  break;
4957  case kNoBlock:
4958  if (::ioctlsocket(sock, FIONBIO, &val) == SOCKET_ERROR) {
4959  ::SysError("SetSockOpt", "ioctl(FIONBIO)");
4960  return -1;
4961  }
4962  break;
4963 #if 0
4964  case kProcessGroup:
4965  if (::ioctl(sock, SIOCSPGRP, &val) == -1) {
4966  ::SysError("SetSockOpt", "ioctl(SIOCSPGRP)");
4967  return -1;
4968  }
4969  break;
4970 #endif
4971  case kAtMark: // read-only option (see GetSockOpt)
4972  case kBytesToRead: // read-only option
4973  default:
4974  Error("SetSockOpt", "illegal option (%d)", opt);
4975  return -1;
4976  break;
4977  }
4978  return 0;
4979 }
4980 
4981 ////////////////////////////////////////////////////////////////////////////////
4982 /// Get socket option.
4983 
4984 int TWinNTSystem::GetSockOpt(int socket, int opt, int *val)
4985 {
4986  if (socket == -1) return -1;
4987  SOCKET sock = socket;
4988 
4989  int optlen = sizeof(*val);
4990 
4991  switch (opt) {
4992  case kSendBuffer:
4993  if (::getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char*)val, &optlen) == SOCKET_ERROR) {
4994  ::SysError("GetSockOpt", "getsockopt(SO_SNDBUF)");
4995  return -1;
4996  }
4997  break;
4998  case kRecvBuffer:
4999  if (::getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*)val, &optlen) == SOCKET_ERROR) {
5000  ::SysError("GetSockOpt", "getsockopt(SO_RCVBUF)");
5001  return -1;
5002  }
5003  break;
5004  case kOobInline:
5005  if (::getsockopt(sock, SOL_SOCKET, SO_OOBINLINE, (char*)val, &optlen) == SOCKET_ERROR) {
5006  ::SysError("GetSockOpt", "getsockopt(SO_OOBINLINE)");
5007  return -1;
5008  }
5009  break;
5010  case kKeepAlive:
5011  if (::getsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char*)val, &optlen) == SOCKET_ERROR) {
5012  ::SysError("GetSockOpt", "getsockopt(SO_KEEPALIVE)");
5013  return -1;
5014  }
5015  break;
5016  case kReuseAddr:
5017  if (::getsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)val, &optlen) == SOCKET_ERROR) {
5018  ::SysError("GetSockOpt", "getsockopt(SO_REUSEADDR)");
5019  return -1;
5020  }
5021  break;
5022  case kNoDelay:
5023  if (::getsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char*)val, &optlen) == SOCKET_ERROR) {
5024  ::SysError("GetSockOpt", "getsockopt(TCP_NODELAY)");
5025  return -1;
5026  }
5027  break;
5028  case kNoBlock:
5029  {
5030  int flg = 0;
5031  if (sock == INVALID_SOCKET) {
5032  ::SysError("GetSockOpt", "INVALID_SOCKET");
5033  }
5034  return -1;
5035  *val = flg; // & O_NDELAY; It is not been defined for WIN32
5036  }
5037  break;
5038 #if 0
5039  case kProcessGroup:
5040  if (::ioctlsocket(sock, SIOCGPGRP, (u_long*)val) == SOCKET_ERROR) {
5041  ::SysError("GetSockOpt", "ioctl(SIOCGPGRP)");
5042  return -1;
5043  }
5044  break;
5045 #endif
5046  case kAtMark:
5047  if (::ioctlsocket(sock, SIOCATMARK, (u_long*)val) == SOCKET_ERROR) {
5048  ::SysError("GetSockOpt", "ioctl(SIOCATMARK)");
5049  return -1;
5050  }
5051  break;
5052  case kBytesToRead:
5053  if (::ioctlsocket(sock, FIONREAD, (u_long*)val) == SOCKET_ERROR) {
5054  ::SysError("GetSockOpt", "ioctl(FIONREAD)");
5055  return -1;
5056  }
5057  break;
5058  default:
5059  Error("GetSockOpt", "illegal option (%d)", opt);
5060  *val = 0;
5061  return -1;
5062  break;
5063  }
5064  return 0;
5065 }
5066 
5067 ////////////////////////////////////////////////////////////////////////////////
5068 /// Connect to service servicename on server servername.
5069 
5070 int TWinNTSystem::ConnectService(const char *servername, int port,
5071  int tcpwindowsize, const char *protocol)
5072 {
5073  short sport;
5074  struct servent *sp;
5075 
5076  if (!strcmp(servername, "unix")) {
5077  return WinNTUnixConnect(port);
5078  }
5079  else if (!gSystem->AccessPathName(servername) || servername[0] == '/' ||
5080  (servername[1] == ':' && servername[2] == '/')) {
5081  return WinNTUnixConnect(servername);
5082  }
5083 
5084  if (!strcmp(protocol, "udp")){
5085  return WinNTUdpConnect(servername, port);
5086  }
5087 
5088  if ((sp = ::getservbyport(::htons(port), kProtocolName))) {
5089  sport = sp->s_port;
5090  } else {
5091  sport = ::htons(port);
5092  }
5093 
5094  TInetAddress addr = gSystem->GetHostByName(servername);
5095  if (!addr.IsValid()) return -1;
5096  UInt_t adr = ::htonl(addr.GetAddress());
5097 
5098  struct sockaddr_in server;
5099  memset(&server, 0, sizeof(server));
5100  memcpy(&server.sin_addr, &adr, sizeof(adr));
5101  server.sin_family = addr.GetFamily();
5102  server.sin_port = sport;
5103 
5104  // Create socket
5105  SOCKET sock;
5106  if ((sock = ::socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
5107  ::SysError("TWinNTSystem::WinNTConnectTcp", "socket");
5108  return -1;
5109  }
5110 
5111  if (tcpwindowsize > 0) {
5112  gSystem->SetSockOpt((int)sock, kRecvBuffer, tcpwindowsize);
5113  gSystem->SetSockOpt((int)sock, kSendBuffer, tcpwindowsize);
5114  }
5115 
5116  if (::connect(sock, (struct sockaddr*) &server, sizeof(server)) == INVALID_SOCKET) {
5117  //::SysError("TWinNTSystem::UnixConnectTcp", "connect");
5118  ::closesocket(sock);
5119  return -1;
5120  }
5121  return (int) sock;
5122 }
5123 
5124 ////////////////////////////////////////////////////////////////////////////////
5125 /// Connect to a Unix domain socket.
5126 
5128 {
5129  struct sockaddr_in myaddr;
5130  int sock;
5131 
5132  memset(&myaddr, 0, sizeof(myaddr));
5133  myaddr.sin_family = AF_INET;
5134  myaddr.sin_port = port;
5135  myaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
5136 
5137  // Open socket
5138  if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
5139  ::SysError("TWinNTSystem::WinNTUnixConnect", "socket");
5140  return -1;
5141  }
5142 
5143  while ((connect(sock, (struct sockaddr *)&myaddr, sizeof myaddr)) == -1) {
5144  if (GetErrno() == EINTR)
5145  ResetErrno();
5146  else {
5147  ::SysError("TWinNTSystem::WinNTUnixConnect", "connect");
5148  close(sock);
5149  return -1;
5150  }
5151  }
5152  return sock;
5153 }
5154 
5155 ////////////////////////////////////////////////////////////////////////////////
5156 /// Connect to a Unix domain socket. Returns -1 in case of error.
5157 
5158 int TWinNTSystem::WinNTUnixConnect(const char *sockpath)
5159 {
5160  FILE *fp;
5161  int port = 0;
5162 
5163  if (!sockpath || strlen(sockpath) <= 0) {
5164  ::SysError("TWinNTSystem::WinNTUnixConnect", "socket path undefined");
5165  return -1;
5166  }
5167  TString socketpath = sockpath;
5168  socketpath.ReplaceAll("/", "\\");
5169  fp = fopen(socketpath.Data(), "rb");
5170  if (!fp) {
5171  ::SysError("TWinNTSystem::WinNTUnixConnect", "fopen");
5172  return -1;
5173  }
5174  fscanf(fp, "%d", &port);
5175  fclose(fp);
5176  /* XXX: set errno in this case */
5177  if (port < 0 || port > 65535) {
5178  ::SysError("TWinNTSystem::WinNTUnixConnect", "invalid port");
5179  return -1;
5180  }
5181  return WinNTUnixConnect(port);
5182 }
5183 
5184 ////////////////////////////////////////////////////////////////////////////////
5185 /// Creates a UDP socket connection
5186 /// Is called via the TSocket constructor. Returns -1 in case of error.
5187 
5188 int TWinNTSystem::WinNTUdpConnect(const char *hostname, int port)
5189 {
5190  short sport;
5191  struct servent *sp;
5192 
5193  if ((sp = getservbyport(htons(port), kProtocolName)))
5194  sport = sp->s_port;
5195  else
5196  sport = htons(port);
5197 
5198  TInetAddress addr = gSystem->GetHostByName(hostname);
5199  if (!addr.IsValid()) return -1;
5200  UInt_t adr = htonl(addr.GetAddress());
5201 
5202  struct sockaddr_in server;
5203  memset(&server, 0, sizeof(server));
5204  memcpy(&server.sin_addr, &adr, sizeof(adr));
5205  server.sin_family = addr.GetFamily();
5206  server.sin_port = sport;
5207 
5208  // Create socket
5209  int sock;
5210  if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
5211  ::SysError("TWinNTSystem::WinNTUdpConnect", "socket (%s:%d)",
5212  hostname, port);
5213  return -1;
5214  }
5215 
5216  while (connect(sock, (struct sockaddr*) &server, sizeof(server)) == -1) {
5217  if (GetErrno() == EINTR)
5218  ResetErrno();
5219  else {
5220  ::SysError("TWinNTSystem::WinNTUdpConnect", "connect (%s:%d)",
5221  hostname, port);
5222  close(sock);
5223  return -1;
5224  }
5225  }
5226  return sock;
5227 }
5228 
5229 ////////////////////////////////////////////////////////////////////////////////
5230 /// Open a connection to a service on a server. Returns -1 in case
5231 /// connection cannot be opened.
5232 /// Use tcpwindowsize to specify the size of the receive buffer, it has
5233 /// to be specified here to make sure the window scale option is set (for
5234 /// tcpwindowsize > 65KB and for platforms supporting window scaling).
5235 /// Is called via the TSocket constructor.
5236 
5237 int TWinNTSystem::OpenConnection(const char *server, int port, int tcpwindowsize,
5238  const char *protocol)
5239 {
5240  return ConnectService(server, port, tcpwindowsize, protocol);
5241 }
5242 
5243 ////////////////////////////////////////////////////////////////////////////////
5244 /// Announce TCP/IP service.
5245 /// Open a socket, bind to it and start listening for TCP/IP connections
5246 /// on the port. If reuse is true reuse the address, backlog specifies
5247 /// how many sockets can be waiting to be accepted.
5248 /// Use tcpwindowsize to specify the size of the receive buffer, it has
5249 /// to be specified here to make sure the window scale option is set (for
5250 /// tcpwindowsize > 65KB and for platforms supporting window scaling).
5251 /// Returns socket fd or -1 if socket() failed, -2 if bind() failed
5252 /// or -3 if listen() failed.
5253 
5254 int TWinNTSystem::AnnounceTcpService(int port, Bool_t reuse, int backlog,
5255  int tcpwindowsize)
5256 {
5257  short sport;
5258  struct servent *sp;
5259  const short kSOCKET_MINPORT = 5000, kSOCKET_MAXPORT = 15000;
5260  short tryport = kSOCKET_MINPORT;
5261 
5262  if ((sp = ::getservbyport(::htons(port), kProtocolName))) {
5263  sport = sp->s_port;
5264  } else {
5265  sport = ::htons(port);
5266  }
5267 
5268  if (port == 0 && reuse) {
5269  ::Error("TWinNTSystem::WinNTTcpService", "cannot do a port scan while reuse is true");
5270  return -1;
5271  }
5272 
5273  if ((sp = ::getservbyport(::htons(port), kProtocolName))) {
5274  sport = sp->s_port;
5275  } else {
5276  sport = ::htons(port);
5277  }
5278 
5279  // Create tcp socket
5280  SOCKET sock;
5281  if ((sock = ::socket(AF_INET, SOCK_STREAM, 0)) < 0) {
5282  ::SysError("TWinNTSystem::WinNTTcpService", "socket");
5283  return -1;
5284  }
5285 
5286  if (reuse) {
5287  gSystem->SetSockOpt((int)sock, kReuseAddr, 1);
5288  }
5289 
5290  if (tcpwindowsize > 0) {
5291  gSystem->SetSockOpt((int)sock, kRecvBuffer, tcpwindowsize);
5292  gSystem->SetSockOpt((int)sock, kSendBuffer, tcpwindowsize);
5293  }
5294 
5295  struct sockaddr_in inserver;
5296  memset(&inserver, 0, sizeof(inserver));
5297  inserver.sin_family = AF_INET;
5298  inserver.sin_addr.s_addr = ::htonl(INADDR_ANY);
5299  inserver.sin_port = sport;
5300 
5301  // Bind socket
5302  if (port > 0) {
5303  if (::bind(sock, (struct sockaddr*) &inserver, sizeof(inserver)) == SOCKET_ERROR) {
5304  ::SysError("TWinNTSystem::WinNTTcpService", "bind");
5305  return -2;
5306  }
5307  } else {
5308  int bret;
5309  do {
5310  inserver.sin_port = ::htons(tryport);
5311  bret = ::bind(sock, (struct sockaddr*) &inserver, sizeof(inserver));
5312  tryport++;
5313  } while (bret == SOCKET_ERROR && WSAGetLastError() == WSAEADDRINUSE &&
5314  tryport < kSOCKET_MAXPORT);
5315  if (bret == SOCKET_ERROR) {
5316  ::SysError("TWinNTSystem::WinNTTcpService", "bind (port scan)");
5317  return -2;
5318  }
5319  }
5320 
5321  // Start accepting connections
5322  if (::listen(sock, backlog) == SOCKET_ERROR) {
5323  ::SysError("TWinNTSystem::WinNTTcpService", "listen");
5324  return -3;
5325  }
5326  return (int)sock;
5327 }
5328 
5329 ////////////////////////////////////////////////////////////////////////////////
5330 /// Announce UDP service.
5331 
5332 int TWinNTSystem::AnnounceUdpService(int port, int backlog)
5333 {
5334  // Open a socket, bind to it and start listening for UDP connections
5335  // on the port. If reuse is true reuse the address, backlog specifies
5336  // how many sockets can be waiting to be accepted. If port is 0 a port
5337  // scan will be done to find a free port. This option is mutual exlusive
5338  // with the reuse option.
5339 
5340  const short kSOCKET_MINPORT = 5000, kSOCKET_MAXPORT = 15000;
5341  short sport, tryport = kSOCKET_MINPORT;
5342  struct servent *sp;
5343 
5344  if ((sp = getservbyport(htons(port), kProtocolName)))
5345  sport = sp->s_port;
5346  else
5347  sport = htons(port);
5348 
5349  // Create udp socket
5350  int sock;
5351  if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
5352  ::SysError("TUnixSystem::UnixUdpService", "socket");
5353  return -1;
5354  }
5355 
5356  struct sockaddr_in inserver;
5357  memset(&inserver, 0, sizeof(inserver));
5358  inserver.sin_family = AF_INET;
5359  inserver.sin_addr.s_addr = htonl(INADDR_ANY);
5360  inserver.sin_port = sport;
5361 
5362  // Bind socket
5363  if (port > 0) {
5364  if (bind(sock, (struct sockaddr*) &inserver, sizeof(inserver))) {
5365  ::SysError("TWinNTSystem::AnnounceUdpService", "bind");
5366  return -2;
5367  }
5368  } else {
5369  int bret;
5370  do {
5371  inserver.sin_port = htons(tryport);
5372  bret = bind(sock, (struct sockaddr*) &inserver, sizeof(inserver));
5373  tryport++;
5374  } while (bret == SOCKET_ERROR && WSAGetLastError() == WSAEADDRINUSE &&
5375  tryport < kSOCKET_MAXPORT);
5376  if (bret < 0) {
5377  ::SysError("TWinNTSystem::AnnounceUdpService", "bind (port scan)");
5378  return -2;
5379  }
5380  }
5381 
5382  // Start accepting connections
5383  if (listen(sock, backlog)) {
5384  ::SysError("TWinNTSystem::AnnounceUdpService", "listen");
5385  return -3;
5386  }
5387 
5388  return sock;
5389 }
5390 
5391 ////////////////////////////////////////////////////////////////////////////////
5392 /// Accept a connection. In case of an error return -1. In case
5393 /// non-blocking I/O is enabled and no connections are available
5394 /// return -2.
5395 
5397 {
5398  int soc = -1;
5399  SOCKET sock = socket;
5400 
5401  while ((soc = ::accept(sock, 0, 0)) == INVALID_SOCKET &&
5402  (::WSAGetLastError() == WSAEINTR)) {
5404  }
5405 
5406  if (soc == -1) {
5407  if (::WSAGetLastError() == WSAEWOULDBLOCK) {
5408  return -2;
5409  } else {
5410  ::SysError("AcceptConnection", "accept");
5411  return -1;
5412  }
5413  }
5414  return soc;
5415 }
5416 
5417 //---- System, CPU and Memory info ---------------------------------------------
5418 
5419 // !!! using undocumented functions and structures !!!
5420 
5421 #define SystemBasicInformation 0
5422 #define SystemPerformanceInformation 2
5423 
5424 typedef struct
5425 {
5426  DWORD dwUnknown1;
5427  ULONG uKeMaximumIncrement;
5428  ULONG uPageSize;
5429  ULONG uMmNumberOfPhysicalPages;
5430  ULONG uMmLowestPhysicalPage;
5431  ULONG UMmHighestPhysicalPage;
5432  ULONG uAllocationGranularity;
5433  PVOID pLowestUserAddress;
5434  PVOID pMmHighestUserAddress;
5435  ULONG uKeActiveProcessors;
5436  BYTE bKeNumberProcessors;
5437  BYTE bUnknown2;
5438  WORD bUnknown3;
5439 } SYSTEM_BASIC_INFORMATION;
5440 
5441 typedef struct
5442 {
5443  LARGE_INTEGER liIdleTime;
5444  DWORD dwSpare[76];
5445 } SYSTEM_PERFORMANCE_INFORMATION;
5446 
5447 typedef struct _PROCESS_MEMORY_COUNTERS {
5448  DWORD cb;
5449  DWORD PageFaultCount;
5450  SIZE_T PeakWorkingSetSize;
5451  SIZE_T WorkingSetSize;
5452  SIZE_T QuotaPeakPagedPoolUsage;
5453  SIZE_T QuotaPagedPoolUsage;
5454  SIZE_T QuotaPeakNonPagedPoolUsage;
5455  SIZE_T QuotaNonPagedPoolUsage;
5456  SIZE_T PagefileUsage;
5457  SIZE_T PeakPagefileUsage;
5459 
5460 typedef LONG (WINAPI *PROCNTQSI) (UINT, PVOID, ULONG, PULONG);
5461 
5462 #define Li2Double(x) ((double)((x).HighPart) * 4.294967296E9 + (double)((x).LowPart))
5463 
5464 ////////////////////////////////////////////////////////////////////////////////
5465 /// Calculate the CPU clock speed using the 'rdtsc' instruction.
5466 /// RDTSC: Read Time Stamp Counter.
5467 
5468 static DWORD GetCPUSpeed()
5469 {
5470  LARGE_INTEGER ulFreq, ulTicks, ulValue, ulStartCounter;
5471 
5472  // Query for high-resolution counter frequency
5473  // (this is not the CPU frequency):
5474  if (QueryPerformanceFrequency(&ulFreq)) {
5475  // Query current value:
5476  QueryPerformanceCounter(&ulTicks);
5477  // Calculate end value (one second interval);
5478  // this is (current + frequency)
5479  ulValue.QuadPart = ulTicks.QuadPart + ulFreq.QuadPart/10;
5480  ulStartCounter.QuadPart = __rdtsc();
5481 
5482  // Loop for one second (measured with the high-resolution counter):
5483  do {
5484  QueryPerformanceCounter(&ulTicks);
5485  } while (ulTicks.QuadPart <= ulValue.QuadPart);
5486  // Now again read CPU time-stamp counter:
5487  return (DWORD)((__rdtsc() - ulStartCounter.QuadPart)/100000);
5488  } else {
5489  // No high-resolution counter present:
5490  return 0;
5491  }
5492 }
5493 
5494 #define BUFSIZE 80
5495 #define SM_SERVERR2 89
5496 typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO);
5497 
5498 ////////////////////////////////////////////////////////////////////////////////
5499 
5500 static char *GetWindowsVersion()
5501 {
5502  OSVERSIONINFOEX osvi;
5503  SYSTEM_INFO si;
5504  PGNSI pGNSI;
5505  BOOL bOsVersionInfoEx;
5506  static char *strReturn = 0;
5507  char temp[512];
5508 
5509  if (strReturn == 0)
5510  strReturn = new char[2048];
5511  else
5512  return strReturn;
5513 
5514  ZeroMemory(&si, sizeof(SYSTEM_INFO));
5515  ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
5516 
5517  // Try calling GetVersionEx using the OSVERSIONINFOEX structure.
5518  // If that fails, try using the OSVERSIONINFO structure.
5519 
5520  osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
5521 
5522  if( !(bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi)) )
5523  {
5524  osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
5525  if (! GetVersionEx ( (OSVERSIONINFO *) &osvi) )
5526  return "";
5527  }
5528 
5529  // Call GetNativeSystemInfo if supported or GetSystemInfo otherwise.
5530  pGNSI = (PGNSI) GetProcAddress( GetModuleHandle("kernel32.dll"),
5531  "GetNativeSystemInfo");
5532  if(NULL != pGNSI)
5533  pGNSI(&si);
5534  else GetSystemInfo(&si);
5535 
5536  switch (osvi.dwPlatformId)
5537  {
5538  // Test for the Windows NT product family.
5539  case VER_PLATFORM_WIN32_NT:
5540 
5541  // Test for the specific product.
5542  if ( osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 0 )
5543  {
5544  if( osvi.wProductType == VER_NT_WORKSTATION )
5545  strlcpy(strReturn, "Microsoft Windows Vista ",2048);
5546  else strlcpy(strReturn, "Windows Server \"Longhorn\" " ,2048);
5547  }
5548  if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2 )
5549  {
5550  if( GetSystemMetrics(SM_SERVERR2) )
5551  strlcpy(strReturn, "Microsoft Windows Server 2003 \"R2\" ",2048);
5552  else if( osvi.wProductType == VER_NT_WORKSTATION &&
5553  si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64)
5554  {
5555  strlcpy(strReturn, "Microsoft Windows XP Professional x64 Edition ",2048);
5556  }
5557  else strlcpy(strReturn, "Microsoft Windows Server 2003, ",2048);
5558  }
5559  if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1 )
5560  strlcpy(strReturn, "Microsoft Windows XP ",2048);
5561 
5562  if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0 )
5563  strlcpy(strReturn, "Microsoft Windows 2000 ",2048);
5564 
5565  if ( osvi.dwMajorVersion <= 4 )
5566  strlcpy(strReturn, "Microsoft Windows NT ",2048);
5567 
5568  // Test for specific product on Windows NT 4.0 SP6 and later.
5569  if( bOsVersionInfoEx )
5570  {
5571  // Test for the workstation type.
5572  if ( osvi.wProductType == VER_NT_WORKSTATION &&
5573  si.wProcessorArchitecture!=PROCESSOR_ARCHITECTURE_AMD64)
5574  {
5575  if( osvi.dwMajorVersion == 4 )
5576  strlcat(strReturn, "Workstation 4.0 ",2048 );
5577  else if( osvi.wSuiteMask & VER_SUITE_PERSONAL )
5578  strlcat(strReturn, "Home Edition " ,2048);
5579  else strlcat(strReturn, "Professional " ,2048);
5580  }
5581  // Test for the server type.
5582  else if ( osvi.wProductType == VER_NT_SERVER ||
5583  osvi.wProductType == VER_NT_DOMAIN_CONTROLLER )
5584  {
5585  if(osvi.dwMajorVersion==5 && osvi.dwMinorVersion==2)
5586  {
5587  if ( si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_IA64 )
5588  {
5589  if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
5590  strlcat(strReturn, "Datacenter Edition for Itanium-based Systems",2048 );
5591  else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
5592  strlcat(strReturn, "Enterprise Edition for Itanium-based Systems" ,2048);
5593  }
5594  else if ( si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64 )
5595  {
5596  if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
5597  strlcat(strReturn, "Datacenter x64 Edition ",2048 );
5598  else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
5599  strlcat(strReturn, "Enterprise x64 Edition ",2048 );
5600  else strlcat(strReturn, "Standard x64 Edition ",2048 );
5601  }
5602  else
5603  {
5604  if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
5605  strlcat(strReturn, "Datacenter Edition ",2048 );
5606  else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
5607  strlcat(strReturn, "Enterprise Edition ",2048 );
5608  else if ( osvi.wSuiteMask == VER_SUITE_BLADE )
5609  strlcat(strReturn, "Web Edition " ,2048);
5610  else strlcat(strReturn, "Standard Edition ",2048 );
5611  }
5612  }
5613  else if(osvi.dwMajorVersion==5 && osvi.dwMinorVersion==0)
5614  {
5615  if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
5616  strlcat(strReturn, "Datacenter Server ",2048 );
5617  else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
5618  strlcat(strReturn, "Advanced Server ",2048 );
5619  else strlcat(strReturn, "Server ",2048 );
5620  }
5621  else // Windows NT 4.0
5622  {
5623  if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
5624  strlcat(strReturn, "Server 4.0, Enterprise Edition " ,2048);
5625  else strlcat(strReturn, "Server 4.0 ",2048 );
5626  }
5627  }
5628  }
5629  // Test for specific product on Windows NT 4.0 SP5 and earlier
5630  else
5631  {
5632  HKEY hKey;
5633  TCHAR szProductType[BUFSIZE];
5634  DWORD dwBufLen=BUFSIZE*sizeof(TCHAR);
5635  LONG lRet;
5636 
5637  lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
5638  "SYSTEM\\CurrentControlSet\\Control\\ProductOptions",
5639  0, KEY_QUERY_VALUE, &hKey );
5640  if( lRet != ERROR_SUCCESS )
5641  return "";
5642 
5643  lRet = RegQueryValueEx( hKey, "ProductType", NULL, NULL,
5644  (LPBYTE) szProductType, &dwBufLen);
5645  RegCloseKey( hKey );
5646 
5647  if( (lRet != ERROR_SUCCESS) || (dwBufLen > BUFSIZE*sizeof(TCHAR)) )
5648  return "";
5649 
5650  if ( lstrcmpi( "WINNT", szProductType) == 0 )
5651  strlcat(strReturn, "Workstation " ,2048);
5652  if ( lstrcmpi( "LANMANNT", szProductType) == 0 )
5653  strlcat(strReturn, "Server " ,2048);
5654  if ( lstrcmpi( "SERVERNT", szProductType) == 0 )
5655  strlcat(strReturn, "Advanced Server " ,2048);
5656  snprintf(temp,512, "%d.%d ", osvi.dwMajorVersion, osvi.dwMinorVersion);
5657  strlcat(strReturn, temp,2048);
5658  }
5659 
5660  // Display service pack (if any) and build number.
5661 
5662  if( osvi.dwMajorVersion == 4 &&
5663  lstrcmpi( osvi.szCSDVersion, "Service Pack 6" ) == 0 )
5664  {
5665  HKEY hKey;
5666  LONG lRet;
5667 
5668  // Test for SP6 versus SP6a.
5669  lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
5670  "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Hotfix\\Q246009",
5671  0, KEY_QUERY_VALUE, &hKey );
5672  if( lRet == ERROR_SUCCESS ) {
5673  snprintf(temp, 512, "Service Pack 6a (Build %d)", osvi.dwBuildNumber & 0xFFFF );
5674  strlcat(strReturn, temp,2048 );
5675  }
5676  else // Windows NT 4.0 prior to SP6a
5677  {
5678  snprintf(temp,512, "%s (Build %d)", osvi.szCSDVersion, osvi.dwBuildNumber & 0xFFFF);
5679  strlcat(strReturn, temp,2048 );
5680  }
5681 
5682  RegCloseKey( hKey );
5683  }
5684  else // not Windows NT 4.0
5685  {
5686  snprintf(temp, 512,"%s (Build %d)", osvi.szCSDVersion, osvi.dwBuildNumber & 0xFFFF);
5687  strlcat(strReturn, temp,2048 );
5688  }
5689 
5690  break;
5691 
5692  // Test for the Windows Me/98/95.
5693  case VER_PLATFORM_WIN32_WINDOWS:
5694 
5695  if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0)
5696  {
5697  strlcpy(strReturn, "Microsoft Windows 95 ",2048);
5698  if (osvi.szCSDVersion[1]=='C' || osvi.szCSDVersion[1]=='B')
5699  strlcat(strReturn, "OSR2 " ,2048);
5700  }
5701 
5702  if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10)
5703  {
5704  strlcpy(strReturn, "Microsoft Windows 98 ",2048);
5705  if ( osvi.szCSDVersion[1]=='A' || osvi.szCSDVersion[1]=='B')
5706  strlcat(strReturn, "SE ",2048 );
5707  }
5708 
5709  if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90)
5710  {
5711  strlcpy(strReturn, "Microsoft Windows Millennium Edition",2048);
5712  }
5713  break;
5714 
5715  case VER_PLATFORM_WIN32s:
5716  strlcpy(strReturn, "Microsoft Win32s",2048);
5717  break;
5718  }
5719  return strReturn;
5720 }
5721 
5722 ////////////////////////////////////////////////////////////////////////////////
5723 /// Use assembly to retrieve the L2 cache information ...
5724 
5725 static int GetL2CacheSize()
5726 {
5727  unsigned nHighestFeatureEx;
5728  int nBuff[4];
5729 
5730  __cpuid(nBuff, 0x80000000);
5731  nHighestFeatureEx = (unsigned)nBuff[0];
5732  // Get cache size
5733  if (nHighestFeatureEx >= 0x80000006) {
5734  __cpuid(nBuff, 0x80000006);
5735  return (((unsigned)nBuff[2])>>16);
5736  }
5737  else return 0;
5738 }
5739 
5740 ////////////////////////////////////////////////////////////////////////////////
5741 /// Get system info for Windows NT.
5742 
5743 static void GetWinNTSysInfo(SysInfo_t *sysinfo)
5744 {
5745  SYSTEM_PERFORMANCE_INFORMATION SysPerfInfo;
5746  SYSTEM_INFO sysInfo;
5747  MEMORYSTATUSEX statex;
5748  OSVERSIONINFO OsVersionInfo;
5749  HKEY hKey;
5750  char szKeyValueString[80];
5751  DWORD szKeyValueDword;
5752  DWORD dwBufLen;
5753  LONG status;
5754  PROCNTQSI NtQuerySystemInformation;
5755 
5756  NtQuerySystemInformation = (PROCNTQSI)GetProcAddress(
5757  GetModuleHandle("ntdll"), "NtQuerySystemInformation");
5758 
5759  if (!NtQuerySystemInformation) {
5760  ::Error("GetWinNTSysInfo",
5761  "Error on GetProcAddress(NtQuerySystemInformation)");
5762  return;
5763  }
5764 
5765  status = NtQuerySystemInformation(SystemPerformanceInformation,
5766  &SysPerfInfo, sizeof(SysPerfInfo),
5767  NULL);
5768  OsVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
5769  GetVersionEx(&OsVersionInfo);
5770  GetSystemInfo(&sysInfo);
5771  statex.dwLength = sizeof(statex);
5772  if (!GlobalMemoryStatusEx(&statex)) {
5773  ::Error("GetWinNTSysInfo", "Error on GlobalMemoryStatusEx()");
5774  return;
5775  }
5776  sysinfo->fCpus = sysInfo.dwNumberOfProcessors;
5777  sysinfo->fPhysRam = (Int_t)(statex.ullTotalPhys >> 20);
5778  sysinfo->fOS = GetWindowsVersion();
5779  sysinfo->fModel = "";
5780  sysinfo->fCpuType = "";
5781  sysinfo->fCpuSpeed = GetCPUSpeed();
5782  sysinfo->fBusSpeed = 0; // bus speed in MHz
5783  sysinfo->fL2Cache = GetL2CacheSize();
5784 
5785  status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System",
5786  0, KEY_QUERY_VALUE, &hKey);
5787  if (status == ERROR_SUCCESS) {
5788  dwBufLen = sizeof(szKeyValueString);
5789  RegQueryValueEx(hKey, "Identifier", NULL, NULL,(LPBYTE)szKeyValueString,
5790  &dwBufLen);
5791  sysinfo->fModel = szKeyValueString;
5792  RegCloseKey (hKey);
5793  }
5794  status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
5795  "Hardware\\Description\\System\\CentralProcessor\\0",
5796  0, KEY_QUERY_VALUE, &hKey);
5797  if (status == ERROR_SUCCESS) {
5798  dwBufLen = sizeof(szKeyValueString);
5799  status = RegQueryValueEx(hKey, "ProcessorNameString", NULL, NULL,
5800  (LPBYTE)szKeyValueString, &dwBufLen);
5801  if (status == ERROR_SUCCESS)
5802  sysinfo->fCpuType = szKeyValueString;
5803  dwBufLen = sizeof(DWORD);
5804  status = RegQueryValueEx(hKey,"~MHz",NULL,NULL,(LPBYTE)&szKeyValueDword,
5805  &dwBufLen);
5806  if ((status == ERROR_SUCCESS) && ((sysinfo->fCpuSpeed <= 0) ||
5807  (sysinfo->fCpuSpeed < (szKeyValueDword >> 1))))
5808  sysinfo->fCpuSpeed = (Int_t)szKeyValueDword;
5809  RegCloseKey (hKey);
5810  }
5811  sysinfo->fCpuType.Remove(TString::kBoth, ' ');
5812  sysinfo->fModel.Remove(TString::kBoth, ' ');
5813 }
5814 
5815 ////////////////////////////////////////////////////////////////////////////////
5816 /// Get CPU stat for Window. Use sampleTime to set the interval over which
5817 /// the CPU load will be measured, in ms (default 1000).
5818 
5819 static void GetWinNTCpuInfo(CpuInfo_t *cpuinfo, Int_t sampleTime)
5820 {
5821  SYSTEM_INFO sysInfo;
5822  Float_t idle_ratio, kernel_ratio, user_ratio, total_ratio;
5823  FILETIME ft_sys_idle, ft_sys_kernel, ft_sys_user, ft_fun_time;
5824  SYSTEMTIME st_fun_time;
5825 
5826  ULARGE_INTEGER ul_sys_idle, ul_sys_kernel, ul_sys_user;
5827  static ULARGE_INTEGER ul_sys_idleold = {0, 0};
5828  static ULARGE_INTEGER ul_sys_kernelold = {0, 0};
5829  static ULARGE_INTEGER ul_sys_userold = {0, 0};
5830  ULARGE_INTEGER ul_sys_idle_diff, ul_sys_kernel_diff, ul_sys_user_diff;
5831 
5832  ULARGE_INTEGER ul_fun_time;
5833  ULARGE_INTEGER ul_fun_timeold = {0, 0};
5834  ULARGE_INTEGER ul_fun_time_diff;
5835 
5836  typedef BOOL (__stdcall *GetSystemTimesProc)( LPFILETIME lpIdleTime,
5837  LPFILETIME lpKernelTime, LPFILETIME lpUserTime );
5838  static GetSystemTimesProc pGetSystemTimes = 0;
5839 
5840  HMODULE hModImagehlp = LoadLibrary( "Kernel32.dll" );
5841  if (!hModImagehlp) {
5842  ::Error("GetWinNTCpuInfo", "Error on LoadLibrary(Kernel32.dll)");
5843  return;
5844  }
5845 
5846  pGetSystemTimes = (GetSystemTimesProc) GetProcAddress( hModImagehlp,
5847  "GetSystemTimes" );
5848  if (!pGetSystemTimes) {
5849  ::Error("GetWinNTCpuInfo", "Error on GetProcAddress(GetSystemTimes)");
5850  return;
5851  }
5852  GetSystemInfo(&sysInfo);
5853 
5854 again:
5855  pGetSystemTimes(&ft_sys_idle,&ft_sys_kernel,&ft_sys_user);
5856  GetSystemTime(&st_fun_time);
5857  SystemTimeToFileTime(&st_fun_time,&ft_fun_time);
5858 
5859  memcpy(&ul_sys_idle, &ft_sys_idle, sizeof(FILETIME));
5860  memcpy(&ul_sys_kernel, &ft_sys_kernel, sizeof(FILETIME));
5861  memcpy(&ul_sys_user, &ft_sys_user, sizeof(FILETIME));
5862  memcpy(&ul_fun_time, &ft_fun_time, sizeof(FILETIME));
5863 
5864  ul_sys_idle_diff.QuadPart = ul_sys_idle.QuadPart -
5865  ul_sys_idleold.QuadPart;
5866  ul_sys_kernel_diff.QuadPart = ul_sys_kernel.QuadPart -
5867  ul_sys_kernelold.QuadPart;
5868  ul_sys_user_diff.QuadPart = ul_sys_user.QuadPart -
5869  ul_sys_userold.QuadPart;
5870 
5871  ul_fun_time_diff.QuadPart = ul_fun_time.QuadPart -
5872  ul_fun_timeold.QuadPart;
5873 
5874  ul_sys_idleold.QuadPart = ul_sys_idle.QuadPart;
5875  ul_sys_kernelold.QuadPart = ul_sys_kernel.QuadPart;
5876  ul_sys_userold.QuadPart = ul_sys_user.QuadPart;
5877 
5878  if (ul_fun_timeold.QuadPart == 0) {
5879  Sleep(sampleTime);
5880  ul_fun_timeold.QuadPart = ul_fun_time.QuadPart;
5881  goto again;
5882  }
5883  ul_fun_timeold.QuadPart = ul_fun_time.QuadPart;
5884 
5885  idle_ratio = (Float_t)(Li2Double(ul_sys_idle_diff)/
5886  Li2Double(ul_fun_time_diff))*100.0;
5887  user_ratio = (Float_t)(Li2Double(ul_sys_user_diff)/
5888  Li2Double(ul_fun_time_diff))*100.0;
5889  kernel_ratio = (Float_t)(Li2Double(ul_sys_kernel_diff)/
5890  Li2Double(ul_fun_time_diff))*100.0;
5891  idle_ratio /= (Float_t)sysInfo.dwNumberOfProcessors;
5892  user_ratio /= (Float_t)sysInfo.dwNumberOfProcessors;
5893  kernel_ratio /= (Float_t)sysInfo.dwNumberOfProcessors;
5894  total_ratio = 100.0 - idle_ratio;
5895 
5896  cpuinfo->fLoad1m = 0; // cpu load average over 1 m
5897  cpuinfo->fLoad5m = 0; // cpu load average over 5 m
5898  cpuinfo->fLoad15m = 0; // cpu load average over 15 m
5899  cpuinfo->fUser = user_ratio; // cpu user load in percentage
5900  cpuinfo->fSys = kernel_ratio; // cpu sys load in percentage
5901  cpuinfo->fTotal = total_ratio; // cpu user+sys load in percentage
5902  cpuinfo->fIdle = idle_ratio; // cpu idle percentage
5903 }
5904 
5905 ////////////////////////////////////////////////////////////////////////////////
5906 /// Get VM stat for Windows NT.
5907 
5908 static void GetWinNTMemInfo(MemInfo_t *meminfo)
5909 {
5910  Long64_t total, used, free, swap_total, swap_used, swap_avail;
5911  MEMORYSTATUSEX statex;
5912  statex.dwLength = sizeof(statex);
5913  if (!GlobalMemoryStatusEx(&statex)) {
5914  ::Error("GetWinNTMemInfo", "Error on GlobalMemoryStatusEx()");
5915  return;
5916  }
5917  used = (Long64_t)(statex.ullTotalPhys - statex.ullAvailPhys);
5918  free = (Long64_t) statex.ullAvailPhys;
5919  total = (Long64_t) statex.ullTotalPhys;
5920 
5921  meminfo->fMemTotal = (Int_t) (total >> 20); // divide by 1024 * 1024
5922  meminfo->fMemUsed = (Int_t) (used >> 20);
5923  meminfo->fMemFree = (Int_t) (free >> 20);
5924 
5925  swap_total = (Long64_t)(statex.ullTotalPageFile - statex.ullTotalPhys);
5926  swap_avail = (Long64_t)(statex.ullAvailPageFile - statex.ullAvailPhys);
5927  swap_used = swap_total - swap_avail;
5928 
5929  meminfo->fSwapTotal = (Int_t) (swap_total >> 20);
5930  meminfo->fSwapUsed = (Int_t) (swap_used >> 20);
5931  meminfo->fSwapFree = (Int_t) (swap_avail >> 20);
5932 }
5933 
5934 ////////////////////////////////////////////////////////////////////////////////
5935 /// Get process info for this process on Windows NT.
5936 
5937 static void GetWinNTProcInfo(ProcInfo_t *procinfo)
5938 {
5940  FILETIME starttime, exittime, kerneltime, usertime;
5941  timeval ru_stime, ru_utime;
5942  ULARGE_INTEGER li;
5943 
5944  typedef BOOL (__stdcall *GetProcessMemoryInfoProc)( HANDLE Process,
5945  PPROCESS_MEMORY_COUNTERS ppsmemCounters, DWORD cb );
5946  static GetProcessMemoryInfoProc pGetProcessMemoryInfo = 0;
5947 
5948  HMODULE hModImagehlp = LoadLibrary( "Psapi.dll" );
5949  if (!hModImagehlp) {
5950  ::Error("GetWinNTProcInfo", "Error on LoadLibrary(Psapi.dll)");
5951  return;
5952  }
5953 
5954  pGetProcessMemoryInfo = (GetProcessMemoryInfoProc) GetProcAddress(
5955  hModImagehlp, "GetProcessMemoryInfo" );
5956  if (!pGetProcessMemoryInfo) {
5957  ::Error("GetWinNTProcInfo",
5958  "Error on GetProcAddress(GetProcessMemoryInfo)");
5959  return;
5960  }
5961 
5962  if ( pGetProcessMemoryInfo( GetCurrentProcess(), &pmc, sizeof(pmc)) ) {
5963  procinfo->fMemResident = pmc.WorkingSetSize / 1024;
5964  procinfo->fMemVirtual = pmc.PagefileUsage / 1024;
5965  }
5966  if ( GetProcessTimes(GetCurrentProcess(), &starttime, &exittime,
5967  &kerneltime, &usertime)) {
5968 
5969  /* Convert FILETIMEs (0.1 us) to struct timeval */
5970  memcpy(&li, &kerneltime, sizeof(FILETIME));
5971  li.QuadPart /= 10L; /* Convert to microseconds */
5972  ru_stime.tv_sec = li.QuadPart / 1000000L;
5973  ru_stime.tv_usec = li.QuadPart % 1000000L;
5974 
5975  memcpy(&li, &usertime, sizeof(FILETIME));
5976  li.QuadPart /= 10L; /* Convert to microseconds */
5977  ru_utime.tv_sec = li.QuadPart / 1000000L;
5978  ru_utime.tv_usec = li.QuadPart % 1000000L;
5979 
5980  procinfo->fCpuUser = (Float_t)(ru_utime.tv_sec) +
5981  ((Float_t)(ru_utime.tv_usec) / 1000000.);
5982  procinfo->fCpuSys = (Float_t)(ru_stime.tv_sec) +
5983  ((Float_t)(ru_stime.tv_usec) / 1000000.);
5984  }
5985 }
5986 
5987 ////////////////////////////////////////////////////////////////////////////////
5988 /// Returns static system info, like OS type, CPU type, number of CPUs
5989 /// RAM size, etc into the SysInfo_t structure. Returns -1 in case of error,
5990 /// 0 otherwise.
5991 
5993 {
5994  if (!info) return -1;
5995  GetWinNTSysInfo(info);
5996  return 0;
5997 }
5998 
5999 ////////////////////////////////////////////////////////////////////////////////
6000 /// Returns cpu load average and load info into the CpuInfo_t structure.
6001 /// Returns -1 in case of error, 0 otherwise. Use sampleTime to set the
6002 /// interval over which the CPU load will be measured, in ms (default 1000).
6003 
6005 {
6006  if (!info) return -1;
6007  GetWinNTCpuInfo(info, sampleTime);
6008  return 0;
6009 }
6010 
6011 ////////////////////////////////////////////////////////////////////////////////
6012 /// Returns ram and swap memory usage info into the MemInfo_t structure.
6013 /// Returns -1 in case of error, 0 otherwise.
6014 
6016 {
6017  if (!info) return -1;
6018  GetWinNTMemInfo(info);
6019  return 0;
6020 }
6021 
6022 ////////////////////////////////////////////////////////////////////////////////
6023 /// Returns cpu and memory used by this process into the ProcInfo_t structure.
6024 /// Returns -1 in case of error, 0 otherwise.
6025 
6027 {
6028  if (!info) return -1;
6029  GetWinNTProcInfo(info);
6030  return 0;
6031 }
Int_t GetGid(const char *group=0)
Returns the group&#39;s id. If group = 0, returns current user&#39;s group.
Int_t fMemFree
Definition: TSystem.h:183
void DispatchOneEvent(Bool_t pendingOnly=kFALSE)
Dispatch a single event in TApplication::Run() loop.
Int_t fGid
Definition: TSystem.h:141
void(* SigHandler_t)(ESignals)
Definition: TUnixSystem.h:28
virtual const char * BaseName(const char *pathname)
Base name of a file name. Base name of /user/root is root.
Definition: TSystem.cxx:932
const TCHAR c_szColonSlash[]
const char * FindFile(const char *search, TString &file, EAccessMode mode=kFileExists)
Find location of file in a search path.
virtual void SysError(const char *method, const char *msgfmt,...) const
Issue system error message.
Definition: TObject.cxx:894
virtual Bool_t AccessPathName(const char *path, EAccessMode mode=kFileExists)
Returns FALSE if one can access a file using the specified access mode.
Definition: TSystem.cxx:1276
int GetSockOpt(int sock, int opt, int *val)
Get socket option.
Bool_t fFirstFile
Definition: TWinNTSystem.h:79
FILE * OpenPipe(const char *shellcmd, const char *mode)
Open a pipe.
Float_t fLoad15m
Definition: TSystem.h:169
static void GetWinNTProcInfo(ProcInfo_t *procinfo)
Get process info for this process on Windows NT.
virtual void SetWriteReady()
Int_t GetEffectiveGid()
Returns the effective group id.
static void __cpuid(int *cpuid_data, int)
UserGroup_t * GetUserInfo(Int_t uid)
Returns all user info in the UserGroup_t structure.
virtual Bool_t ProcessEvents()
Process pending events (GUI, timers, sockets).
Definition: TSystem.cxx:424
const char * HomeDirectory(const char *userName=0)
Return the user&#39;s home directory.
int pw_uid
Definition: TWinNTSystem.h:50
virtual Bool_t Notify()
Notify when event occurred on descriptor associated with this handler.
int RecvRaw(int sock, void *buffer, int length, int flag)
Receive exactly length bytes into buffer.
const char * HostName()
Return the system&#39;s host name.
WIN32_FIND_DATA fFindFileData
Definition: TWinNTSystem.h:85
virtual Bool_t IsPathLocal(const char *path)
Returns TRUE if the url in &#39;path&#39; points to the local file system.
Definition: TSystem.cxx:1285
void SetDynamicPath(const char *path)
Set the dynamic path to a new value.
long long Long64_t
Definition: RtypesCore.h:69
Int_t fBusSpeed
Definition: TSystem.h:157
struct group * fGroups
Definition: TWinNTSystem.h:73
auto * m
Definition: textangle.C:8
const char * TempDirectory() const
Return a user configured or systemwide directory to create temporary files in.
Int_t fPhysRam
Definition: TSystem.h:159
Int_t fSigcnt
Definition: TSystem.h:265
R__EXTERN Int_t gErrorIgnoreLevel
Definition: TError.h:105
#define BUFSIZE
Int_t fReadOffSet
Definition: TSystem.h:210
static DWORD GetCPUSpeed()
Calculate the CPU clock speed using the &#39;rdtsc&#39; instruction.
char * pw_shell
Definition: TWinNTSystem.h:55
int Link(const char *from, const char *to)
Create a link from file1 to file2.
virtual void StackTrace()
Print a stack trace.
Definition: TSystem.cxx:740
const char * GetError()
Return system error string.
Bool_t GetNbGroups()
BOOL PathIsUNC(LPCTSTR pszPath)
Returns TRUE if the given string is a UNC path.
Float_t fSys
Definition: TSystem.h:171
Bool_t EqualTo(const char *cs, ECaseCompare cmp=kExact) const
Definition: TString.h:579
const char * GetLinkedLibraries()
Get list of shared libraries loaded at the start of the executable.
TLine * line
#define INVALID_HANDLE_VALUE
Definition: TMapFile.cxx:84
int Unlink(const char *name)
Unlink, i.e. remove, a file or directory.
HANDLE GetProcess()
Get current process handle.
float Float_t
Definition: RtypesCore.h:53
TTime Now()
Get current time in milliseconds since 0:00 Jan 1 1995.
void CloseConnection(int sock, Bool_t force=kFALSE)
Close socket.
int gr_gid
Definition: TWinNTSystem.h:62
std::string GetWorkingDirectory() const
Return the working directory for the default drive.
int CopyFile(const char *from, const char *to, Bool_t overwrite=kFALSE)
Copy a file.
const char Option_t
Definition: RtypesCore.h:62
void * _ReturnAddress(void)
const char * PrependPathName(const char *dir, TString &name)
Concatenate a directory and a file name.
Int_t fBeepFreq
Definition: TSystem.h:269
TString fOS
Definition: TSystem.h:152
const Ssiz_t kNPOS
Definition: RtypesCore.h:111
This class represents a WWW compatible URL.
Definition: TUrl.h:35
Int_t fUid
Definition: TSystem.h:129
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition: TString.h:638
int GetPathInfo(const char *path, Long_t *id, Long_t *size, Long_t *flags, Long_t *modtime)
Get info about a file: id, size, flags, modification time.
Definition: TSystem.cxx:1374
std::string GetHomeDirectory(const char *userName=0) const
Return the user&#39;s home directory.
#define closesocket(a)
Definition: civetweb.c:453
const char * GetProtocol() const
Definition: TUrl.h:67
static char * GetWindowsVersion()
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
TH1 * h
Definition: legend2.C:5
void AddDynamicPath(const char *dir)
Add a new directory to the dynamic path.
char * gr_name
Definition: TWinNTSystem.h:60
TString fGroup
Definition: TSystem.h:143
TTimer * RemoveTimer(TTimer *ti)
Remove timer from list of system timers.
This class represents an Internet Protocol (IP) address.
Definition: TInetAddress.h:36
virtual int MakeDirectory(const char *name)
Make a directory.
Definition: TSystem.cxx:825
int GetPathInfo(const char *path, FileStat_t &buf)
Get info about a file.
virtual void AddSignalHandler(TSignalHandler *sh)
Add a signal handler to list of system signal handlers.
Definition: TSystem.cxx:540
TString fWdpath
Definition: TSystem.h:266
Regular expression class.
Definition: TRegexp.h:31
int Umask(Int_t mask)
Set the process file creation mode mask.
TString ferr
Definition: pq2main.cxx:38
#define gROOT
Definition: TROOT.h:402
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:585
static constexpr double cm
static char shellEscape
char * GetServiceByPort(int port)
Get name of internet service.
virtual int Load(const char *module, const char *entry="", Bool_t system=kFALSE)
Load a shared library.
Definition: TSystem.cxx:1829
int SendRaw(int sock, const void *buffer, int length, int flag)
Send exactly length bytes from buffer.
Basic string class.
Definition: TString.h:125
TSeqCollection * fSignalHandler
Definition: TSystem.h:277
void(WINAPI * PGNSI)(LPSYSTEM_INFO)
#define MAX_NAME_STRING
Definition: TWinNTSystem.h:42
int Int_t
Definition: RtypesCore.h:41
void IgnoreSignal(ESignals sig, Bool_t ignore=kTRUE)
If ignore is true ignore the specified signal, else restore previous behaviour.
bool Bool_t
Definition: RtypesCore.h:59
virtual TTimer * RemoveTimer(TTimer *t)
Remove timer from list of system timers.
Definition: TSystem.cxx:489
Bool_t IsAbsoluteFileName(const char *dir)
Return true if dir is an absolute pathname.
char * gr_passwd
Definition: TWinNTSystem.h:61
#define gInterpreter
Definition: TInterpreter.h:526
virtual char * Which(const char *search, const char *file, EAccessMode mode=kFileExists)
Find location of file in a search path.
Definition: TSystem.cxx:1522
void Break(const char *location, const char *msgfmt,...)
Long_t fMtime
Definition: TSystem.h:132
Bool_t CheckDescriptors()
Check if there is activity on some file descriptors and call their Notify() member.
const char * DirName(const char *pathname)
Return the directory name in pathname.
static void ThreadStub(void *Parameter)
Definition: TWinNTSystem.h:99
virtual void ResetReadyMask()
TString & Prepend(const char *cs)
Definition: TString.h:607
R__EXTERN TApplication * gApplication
Definition: TApplication.h:165
Basic time type with millisecond precision.
Definition: TTime.h:27
int ClosePipe(FILE *pipe)
Close the pipe.
Bool_t IsPathLocal(const char *path)
Returns TRUE if the url in &#39;path&#39; points to the local file system.
TString fModel
Definition: TSystem.h:153
Bool_t fInsideNotify
Definition: TSystem.h:268
Long64_t fSize
Definition: TSystem.h:131
void * fGUIThreadHandle
Definition: TWinNTSystem.h:82
Int_t fUid
Definition: TSystem.h:140
Int_t GetEffectiveUid()
Returns the effective user id.
HANDLE fhProcess
Definition: TWinNTSystem.h:81
const char * kProtocolName
virtual TFileHandler * RemoveFileHandler(TFileHandler *fh)
Remove a file handler from the list of file handlers.
Definition: TSystem.cxx:572
void Reset()
Definition: TCollection.h:250
TWinNTSystem()
ctor
void NotifyApplicationCreated()
Hook to tell TSystem that the TApplication object has been created.
void SysError(const char *location, const char *msgfmt,...)
virtual Bool_t HandleTermInput()
Definition: TApplication.h:111
virtual const char * FindFile(const char *search, TString &file, EAccessMode mode=kFileExists)
Find location of file in a search path.
Definition: TSystem.cxx:1512
Bool_t DispatchTimers(Bool_t mode)
Handle and dispatch timers.
const Double_t gTicks
TString & Replace(Ssiz_t pos, Ssiz_t n, const char *s)
Definition: TString.h:628
static Int_t GetErrno()
Static function returning system error number.
Definition: TSystem.cxx:268
Int_t fMode
Definition: TSystem.h:128
Int_t GetSysInfo(SysInfo_t *info) const
Returns static system info, like OS type, CPU type, number of CPUs RAM size, etc into the SysInfo_t s...
int SOCKET
Definition: civetweb.c:464
void Abort(int code=0)
Abort the application.
TString fHostname
Definition: TSystem.h:267
static int GetL2CacheSize()
Use assembly to retrieve the L2 cache information ...
void AddSignalHandler(TSignalHandler *sh)
Add a signal handler to list of system signal handlers.
virtual Bool_t Notify()
Notify when signal occurs.
virtual const char * GetDirEntry(void *dirp)
Get a directory entry. Returns 0 if no more entries.
Definition: TSystem.cxx:851
virtual int Unlink(const char *name)
Unlink, i.e. remove, a file.
Definition: TSystem.cxx:1357
Bool_t ChangeDirectory(const char *path)
Change directory.
Int_t GetFamily() const
Definition: TInetAddress.h:72
Int_t GetCpuInfo(CpuInfo_t *info, Int_t sampleTime=1000) const
Returns cpu load average and load info into the CpuInfo_t structure.
static int WinNTUnixConnect(int port)
Connect to a Unix domain socket.
BOOL PathIsRoot(LPCTSTR pPath)
check if a path is a root
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString...
Definition: TString.cxx:2365
TSignalHandler * RemoveSignalHandler(TSignalHandler *sh)
Remove a signal handler from list of signal handlers.
Float_t fUser
Definition: TSystem.h:170
Int_t fSwapFree
Definition: TSystem.h:186
Int_t SetFPEMask(Int_t mask=kDefaultMask)
Set which conditions trigger a floating point exception.
int AcceptConnection(int sock)
Accept a connection.
static Bool_t Initialized()
Return kTRUE if the TROOT object has been initialized.
Definition: TROOT.cxx:2754
static const char * DynamicPath(const char *newpath=0, Bool_t reset=kFALSE)
Get shared library search path. Static utility function.
const char * FindDynamicLibrary(TString &lib, Bool_t quiet=kFALSE)
Returns and updates sLib to the path of a dynamic library (searches for library in the dynamic librar...
int GetPid()
Get process id.
TObject * Next()
Return next object in collection.
const Int_t kFatal
Definition: TError.h:42
R__EXTERN TFileHandler * gXDisplay
Definition: TSystem.h:541
Int_t fNfd
Signals that were trapped.
Definition: TSystem.h:262
TString fShell
Definition: TSystem.h:146
TString fRealName
Definition: TSystem.h:145
static char * shellMeta
void AddTimer(TTimer *ti)
Add timer to list of system timers.
virtual const char * Getenv(const char *env)
Get environment variable.
Definition: TSystem.cxx:1638
TString & Append(const char *cs)
Definition: TString.h:495
Bool_t EndsWith(const char *pat, ECaseCompare cmp=kExact) const
Return true if string ends with the specified string.
Definition: TString.cxx:2231
#define SM_SERVERR2
static constexpr double L
virtual void ExitLoop()
Exit from event loop.
Definition: TSystem.cxx:400
struct _PROCESS_MEMORY_COUNTERS PROCESS_MEMORY_COUNTERS
Ssiz_t First(char c) const
Find first occurrence of a character c.
Definition: TString.cxx:477
char * pw_name
Definition: TWinNTSystem.h:48
const char * WorkingDirectory()
Return the working directory for the default drive.
LONG(WINAPI * PROCNTQSI)(UINT, PVOID, ULONG, PULONG)
int GetServiceByName(const char *service)
Get port # of internet service.
virtual TInetAddress GetHostByName(const char *server)
Get Internet Protocol (IP) address of host.
Definition: TSystem.cxx:2320
int OpenConnection(const char *server, int port, int tcpwindowsize=-1, const char *protocol="tcp")
Open a connection to a service on a server.
void Error(const char *location, const char *msgfmt,...)
Bool_t IsSync() const
Int_t fGid
Definition: TSystem.h:130
#define Li2Double(x)
const char * GetDynamicPath()
Return the dynamic path (used to find shared libraries).
TSeqCollection * fFileHandler
Definition: TSystem.h:278
Bool_t CollectGroups()
A doubly linked list.
Definition: TList.h:44
Float_t fLoad1m
Definition: TSystem.h:167
TString & GetLastErrorString()
Return the thread local storage for the custom last error message.
Definition: TSystem.cxx:2096
struct _PROCESS_MEMORY_COUNTERS * PPROCESS_MEMORY_COUNTERS
const char * pwd()
Definition: TSystem.h:405
Bool_t InitUsersGroups()
Collect local users and groups accounts information.
static void SigHandler(ESignals sig)
Unix signal handler.
Int_t fL2Cache
Definition: TSystem.h:158
virtual ~TWinNTSystem()
dtor
int MakeDirectory(const char *name)
Make a WinNT file system directory.
Using a TBrowser one can browse all ROOT objects.
Definition: TBrowser.h:37
virtual Bool_t WriteNotify()
Notify when something can be written to the descriptor associated with this handler.
const char * GetDirEntry(void *dirp)
Returns the next directory entry.
R__EXTERN const char * gProgName
Definition: TSystem.h:224
#define MAX_SID_SIZE
Definition: TWinNTSystem.h:40
Float_t fCpuUser
Definition: TSystem.h:194
static int WinNTUdpConnect(const char *hostname, int port)
Creates a UDP socket connection Is called via the TSocket constructor.
ESignals
char * pw_gecos
Definition: TWinNTSystem.h:53
TString fUser
Definition: TSystem.h:142
Bool_t Init()
Initialize WinNT system interface.
static void sighandler(int sig)
Call the signal handler associated with the signal.
void Sleep(UInt_t milliSec)
Sleep milliSec milli seconds.
ULong_t fGUIThreadId
Definition: TWinNTSystem.h:83
Int_t fCpus
Definition: TSystem.h:155
virtual Bool_t HasWriteInterest()
True if handler is interested in write events.
const char * BaseName(const char *name)
Base name of a file name.
Bool_t ProcessEvents()
process pending events, i.e. DispatchOneEvent(kTRUE)
ROOT::R::TRInterface & r
Definition: Object.C:4
virtual Bool_t Init()
Initialize the OS interface.
Definition: TSystem.cxx:190
Bool_t fIsLink
Definition: TSystem.h:133
R__EXTERN TSystem * gSystem
Definition: TSystem.h:540
Int_t GetFPEMask()
Return the bitmap of conditions that trigger a floating point exception.
virtual const char * GetLibraries(const char *regexp="", const char *option="", Bool_t isRegexp=kTRUE)
Return a space separated list of loaded shared libraries.
Definition: TSystem.cxx:2132
#define SID_MEMBER
Definition: TWinNTSystem.h:45
auto * a
Definition: textangle.C:12
#define SystemPerformanceInformation
char * pw_group
Definition: TWinNTSystem.h:56
UInt_t GetAddress() const
Definition: TInetAddress.h:68
Int_t fSwapUsed
Definition: TSystem.h:185
int ConnectService(const char *servername, int port, int tcpwindowsize, const char *protocol="tcp")
Connect to service servicename on server servername.
Long_t fMemVirtual
Definition: TSystem.h:197
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition: TString.h:561
static int push(struct mg_context *ctx, FILE *fp, SOCKET sock, SSL *ssl, const char *buf, int len, double timeout)
Definition: civetweb.c:3754
virtual void SetReadReady()
virtual Long_t NextTimeOut(Bool_t mode)
Time when next timer of mode (synchronous=kTRUE or asynchronous=kFALSE) will time-out (in ms)...
Definition: TSystem.cxx:502
Bool_t IsSync() const
Definition: TTimer.h:80
void AddFileHandler(TFileHandler *fh)
Add a file handler to the list of system file handlers.
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition: TString.cxx:2343
unsigned int UInt_t
Definition: RtypesCore.h:42
#define isin(address, start, length)
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:880
char * Form(const char *fmt,...)
void Exit(int code, Bool_t mode=kTRUE)
Exit the application.
int Utime(const char *file, Long_t modtime, Long_t actime)
Set a files modification and access times.
int GetFd() const
Ssiz_t Length() const
Definition: TString.h:386
ESignals GetSignal() const
void ResetSignal(ESignals sig, Bool_t reset=kTRUE)
If reset is true reset the signal handler for the specified signal to the default handler...
static const char * StripOffProto(const char *path, const char *proto)
Definition: TSystem.h:315
#define calloc
Definition: civetweb.c:819
struct passwd * fPasswords
Definition: TWinNTSystem.h:74
const char * UnixPathName(const char *unixpathname)
Convert a pathname to a unix pathname.
Definition: TSocket.h:52
TSubString Strip(EStripType s=kTrailing, char c=' ') const
Return a substring of self stripped at beginning and/or end.
Definition: TString.cxx:1080
static void GetWinNTSysInfo(SysInfo_t *sysinfo)
Get system info for Windows NT.
Handles synchronous and a-synchronous timer events.
Definition: TTimer.h:51
Bool_t CheckTimer(const TTime &now)
Check if timer timed out.
Definition: TTimer.cxx:128
Float_t fLoad5m
Definition: TSystem.h:168
void DoBeep(Int_t freq=-1, Int_t duration=-1) const
Beep.
void ResetSignals()
Reset signals handlers to previous behaviour.
#define SID_GROUP
Definition: TWinNTSystem.h:44
static void GetWinNTCpuInfo(CpuInfo_t *cpuinfo, Int_t sampleTime)
Get CPU stat for Window.
TString fListLibs
Definition: TSystem.h:282
static char * shellStuff
void DispatchSignals(ESignals sig)
Handle and dispatch signals.
void AddAlias(const char *alias)
Add alias to list of aliases.
virtual void FreeDirectory(void *dirp)
Free a directory.
Definition: TSystem.cxx:843
const char * GetLibraries(const char *regexp="", const char *option="", Bool_t isRegexp=kTRUE)
Return a space separated list of loaded shared libraries.
TGraphErrors * gr
Definition: legend1.C:25
#define gVirtualX
Definition: TVirtualX.h:350
const char DriveName(const char *pathname="/")
Return the drive letter in pathname.
#define Printf
Definition: TGeoToOCC.h:18
char * StrDup(const char *str)
Duplicate the string str.
Definition: TString.cxx:2544
void ExitLoop()
Exit from event loop.
const Bool_t kFALSE
Definition: RtypesCore.h:88
virtual int SetSockOpt(int sock, int kind, int val)
Set socket option.
Definition: TSystem.cxx:2465
ULong_t gConsoleWindow
int Exec(const char *shellcmd)
Execute a command.
UserGroup_t * GetGroupInfo(Int_t gid)
Returns all group info in the UserGroup_t structure.
static unsigned int total
TString & Remove(Ssiz_t pos)
Definition: TString.h:619
long Long_t
Definition: RtypesCore.h:50
int Ssiz_t
Definition: RtypesCore.h:63
RooCmdArg Index(RooCategory &icat)
TString fPasswd
Definition: TSystem.h:144
int SendBuf(int sock, const void *buffer, int length)
Send a buffer headed by a length indicator.
virtual TSignalHandler * RemoveSignalHandler(TSignalHandler *sh)
Remove a signal handler from list of signal handlers.
Definition: TSystem.cxx:550
TFdSet * fReadready
Files that should be checked for write events.
Definition: TSystem.h:259
void AddAddress(UInt_t addr)
Add alternative address to list of addresses.
R__EXTERN const char * gProgPath
Definition: TSystem.h:225
void Copy(void *source, void *dest)
static const double x1[5]
TString & Swap(TString &other)
Definition: TString.h:650
Int_t Argc() const
Definition: TApplication.h:135
#define ClassImp(name)
Definition: Rtypes.h:359
Float_t fCpuSys
Definition: TSystem.h:195
int AnnounceTcpService(int port, Bool_t reuse, int backlog, int tcpwindowsize=-1)
Announce TCP/IP service.
R__EXTERN TWin32SplashThread * gSplash
double Double_t
Definition: RtypesCore.h:55
#define INVALID_SOCKET
Definition: civetweb.c:461
Ssiz_t Last(char c) const
Find last occurrence of a character c.
Definition: TString.cxx:875
TFdSet * fReadmask
Definition: TSystem.h:257
char * DynamicPathName(const char *lib, Bool_t quiet=kFALSE)
Find a dynamic library called lib using the system search paths.
Definition: TSystem.cxx:2006
int AnnounceUnixService(int port, int backlog)
Announce unix domain service.
int RecvBuf(int sock, void *buffer, int length)
Receive a buffer headed by a length indicator.
int Chmod(const char *file, UInt_t mode)
Set the file permission bits.
Bool_t fGroupsInitDone
Definition: TWinNTSystem.h:78
int type
Definition: TGX11.cxx:120
#define TRUE
R__EXTERN TEnv * gEnv
Definition: TEnv.h:171
virtual const char * ExpandFileName(const char *fname)
Expand a pathname getting rid of special shell characters like ~.
Definition: TSystem.cxx:1079
TString fCpuType
Definition: TSystem.h:154
TNamed()
Definition: TNamed.h:36
__int64 __rdtsc()
#define free
Definition: civetweb.c:821
unsigned long ULong_t
Definition: RtypesCore.h:51
#define PVOID
Definition: TStorage.cxx:62
char ** Argv() const
Definition: TApplication.h:136
int AnnounceUdpService(int port, int backlog)
Announce UDP service.
void TimerThread()
Special Thread to check asynchronous timers.
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:570
TFdSet * fSignals
Files with writes waiting.
Definition: TSystem.h:261
static constexpr double s
void Beep(Int_t freq=-1, Int_t duration=-1, Bool_t setDefault=kFALSE)
Beep for duration milliseconds with a tone of frequency freq.
Definition: TSystem.cxx:332
Bool_t HandleConsoleEvent()
__inline BOOL DBL_BSLASH(LPCTSTR psz)
Inline function to check for a double-backslash at the beginning of a string.
int Symlink(const char *from, const char *to)
Create a symlink from file1 to file2.
void Gl_setwidth(int width)
void * OpenDirectory(const char *name)
Open a directory. Returns 0 if directory does not exist.
void FillWithHomeDirectory(const char *userName, char *mydir) const
Fill buffer with user&#39;s home directory.
Definition: TSocket.h:51
EAccessMode
Definition: TSystem.h:44
int Load(const char *module, const char *entry="", Bool_t system=kFALSE)
Load a shared library.
void Reset()
Definition: TSystem.h:213
int mkdir(const char *name, Bool_t recursive=kFALSE)
Make a file system directory.
Bool_t IsNull() const
Definition: TString.h:383
TInetAddress GetPeerName(int sock)
Get Internet Protocol (IP) address of remote host and port #.
TFileHandler * RemoveFileHandler(TFileHandler *fh)
Remove a file handler from the list of file handlers.
Bool_t ExpandPathName(TString &patbuf)
Expand a pathname getting rid of special shell characaters like ~.$, etc.
Binding & operator=(OUT(*fun)(void))
Int_t fMemTotal
Definition: TSystem.h:181
int pw_gid
Definition: TWinNTSystem.h:51
void Throw(int code)
If an exception context has been set (using the TRY and RETRY macros) jump back to where it was set...
Definition: TException.cxx:27
void FreeDirectory(void *dirp)
Close a WinNT file system directory.
Int_t Select(TList *active, Long_t timeout)
Select on file descriptors. The timeout to is in millisec.
Double_t GetCPUTime()
int SetSockOpt(int sock, int opt, int val)
Set socket option.
TInetAddress GetSockName(int sock)
Get Internet Protocol (IP) address of host and port #.
Bool_t IsValid() const
Definition: TInetAddress.h:76
typedef void((*Func_t)())
#define FALSE
Bool_t AccessPathName(const char *path, EAccessMode mode=kFileExists)
Returns FALSE if one can access a file using the specified access mode.
TSeqCollection * fTimers
Definition: TSystem.h:276
TInetAddress GetHostByName(const char *server)
Get Internet Protocol (IP) address of host.
Bool_t CountMembers(const char *lpszGroupName)
Bool_t(* ThreadMsgFunc_t)(MSG *)
Definition: TWinNTSystem.h:70
Int_t GetUid(const char *user=0)
Returns the user&#39;s id. If user = 0, returns current user&#39;s id.
virtual void Add(TObject *obj)
Definition: TList.h:87
auto * l
Definition: textangle.C:4
static const TString & GetLibDir()
Get the library directory in the installation. Static utility function.
Definition: TROOT.cxx:2863
virtual void AddTimer(TTimer *t)
Add timer to list of system timers.
Definition: TSystem.cxx:479
Definition: file.py:1
R__EXTERN const char * gRootDir
Definition: TSystem.h:223
Int_t GetProcInfo(ProcInfo_t *info) const
Returns cpu and memory used by this process into the ProcInfo_t structure.
virtual void Exit(int code, Bool_t mode=kTRUE)
Exit the application.
Definition: TSystem.cxx:724
Int_t fMemUsed
Definition: TSystem.h:182
int SetNonBlock(int fd)
Make descriptor fd non-blocking.
int GetFsInfo(const char *path, Long_t *id, Long_t *bsize, Long_t *blocks, Long_t *bfree)
Get info about a file system: id, bsize, bfree, blocks.
you should not use this method at all Int_t Int_t Double_t Double_t Double_t Int_t Double_t Double_t Double_t Double_t b
Definition: TRolke.cxx:630
Int_t fCpuSpeed
Definition: TSystem.h:156
Double_t GetRealTime()
FILE * TempFileName(TString &base, const char *dir=0)
Create a secure temporary file by appending a unique 6 letter string to base.
#define snprintf
Definition: civetweb.c:822
Long_t fIno
Definition: TSystem.h:127
Long_t LookupSID(const char *lpszAccountName, int what, int &groupIdx, int &memberIdx)
Take the name and look up a SID so that we can get full domain/user information.
char * pw_passwd
Definition: TWinNTSystem.h:49
char * pw_dir
Definition: TWinNTSystem.h:54
virtual void * OpenDirectory(const char *name)
Open a directory. Returns 0 if directory does not exist.
Definition: TSystem.cxx:834
const char * proto
Definition: civetweb.c:11652
R__EXTERN Int_t gDebug
Definition: Rtypes.h:86
Iterator of ordered collection.
virtual Bool_t ReadNotify()
Notify when something can be read from the descriptor associated with this handler.
Bool_t CollectMembers(const char *lpszGroupName, int &groupIdx, int &memberIdx)
TSystem * FindHelper(const char *path, void *dirptr=0)
Create helper TSystem to handle file and directory operations that might be special for remote file a...
Definition: TSystem.cxx:752
virtual void AddFileHandler(TFileHandler *fh)
Add a file handler to the list of system file handlers.
Definition: TSystem.cxx:562
static void ResetErrno()
Static function resetting system error number.
Definition: TSystem.cxx:284
static const TString & GetBinDir()
Get the binary directory in the installation. Static utility function.
Definition: TROOT.cxx:2842
void SetProgname(const char *name)
Set the application name (from command line, argv[0]) and copy it in gProgName.
Float_t fTotal
Definition: TSystem.h:172
Bool_t CheckSignals(Bool_t sync)
Check if some signals were raised and call their Notify() member.
virtual Bool_t ExpandPathName(TString &path)
Expand a pathname getting rid of special shell characters like ~.
Definition: TSystem.cxx:1254
void Setenv(const char *name, const char *value)
Set environment variable.
Int_t fBeepDuration
Definition: TSystem.h:270
TFdSet * fWriteready
Files with reads waiting.
Definition: TSystem.h:260
Int_t fSwapTotal
Definition: TSystem.h:184
TList * GetVolumes(Option_t *opt="") const
Get list of volumes (drives) mounted on the system.
Long_t fDev
Definition: TSystem.h:126
static void GetWinNTMemInfo(MemInfo_t *meminfo)
Get VM stat for Windows NT.
virtual Int_t GetSize() const
Definition: TCollection.h:180
Abstract base class defining a generic interface to the underlying Operating System.
Definition: TSystem.h:248
float * q
Definition: THbookFile.cxx:87
Ordered collection.
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
Definition: TEnv.cxx:491
TFdSet * fWritemask
Files that should be checked for read events.
Definition: TSystem.h:258
const Bool_t kTRUE
Definition: RtypesCore.h:87
Bool_t IsAsync() const
Definition: TTimer.h:81
Int_t GetMemInfo(MemInfo_t *info) const
Returns ram and swap memory usage info into the MemInfo_t structure.
Float_t fIdle
Definition: TSystem.h:173
const Int_t n
Definition: legend1.C:16
void StackTrace()
Print a stack trace, if gEnv entry "Root.Stacktrace" is unset or 1, and if the image helper functions...
TString fFile
Definition: TSystem.h:205
char name[80]
Definition: TGX11.cxx:109
Long_t fMemResident
Definition: TSystem.h:196
const char * Getenv(const char *name)
Get environment variable.
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:866
void SetGUIThreadMsgHandler(ThreadMsgFunc_t func)
Set the (static part of) the event handler func for GUI messages.
Int_t RedirectOutput(const char *name, const char *mode="a", RedirectHandle_t *h=0)
Redirect standard output (stdout, stderr) to the specified file.
char * fDirNameBuffer
Definition: TWinNTSystem.h:84
int Rename(const char *from, const char *to)
Rename a file. Returns 0 when successful, -1 in case of failure.
virtual Bool_t HasReadInterest()
True if handler is interested in read events.
const char * Data() const
Definition: TString.h:345
char ** gr_mem
Definition: TWinNTSystem.h:63