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