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