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