ROOT  6.07/01
Reference Guide
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
TWinNTSystem.cxx
Go to the documentation of this file.
1 // @(#)root/winnt:$Id: db9b3139b1551a1b4e31a17f57866a276d5cd419 $
2 // Author: Fons Rademakers 15/09/95
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 //////////////////////////////////////////////////////////////////////////////////
13 // //
14 // TWinNTSystem //
15 // //
16 // Class providing an interface to the Windows NT/Windows 95 Operating Systems. //
17 // //
18 //////////////////////////////////////////////////////////////////////////////////
19 
20 
21 #ifdef HAVE_CONFIG
22 #include "config.h"
23 #endif
24 
25 #include "Windows4Root.h"
26 #include "TWinNTSystem.h"
27 #include "TROOT.h"
28 #include "TError.h"
29 #include "TOrdCollection.h"
30 #include "TRegexp.h"
31 #include "TException.h"
32 #include "TEnv.h"
33 #include "TSocket.h"
34 #include "TApplication.h"
35 #include "TWin32SplashThread.h"
36 #include "Win32Constants.h"
37 #include "TInterpreter.h"
38 #include "TObjString.h"
39 #include "TVirtualX.h"
40 #include "TUrl.h"
41 
42 #include <sys/utime.h>
43 #include <sys/timeb.h>
44 #include <process.h>
45 #include <io.h>
46 #include <direct.h>
47 #include <ctype.h>
48 #include <float.h>
49 #include <sys/stat.h>
50 #include <signal.h>
51 #include <stdio.h>
52 #include <errno.h>
53 #include <lm.h>
54 #include <dbghelp.h>
55 #include <Tlhelp32.h>
56 #include <sstream>
57 #include <iostream>
58 #include <list>
59 #include <shlobj.h>
60 #include <conio.h>
61 
62 #if defined (_MSC_VER) && (_MSC_VER >= 1400)
63  #include <intrin.h>
64 #elif defined (_M_IX86)
65  static void __cpuid(int* cpuid_data, int info_type)
66  {
67  __asm {
68  push ebx
69  push edi
70  mov edi, cpuid_data
71  mov eax, info_type
72  cpuid
73  mov [edi], eax
74  mov [edi + 4], ebx
75  mov [edi + 8], ecx
76  mov [edi + 12], edx
77  pop edi
78  pop ebx
79  }
80  }
81  __int64 __rdtsc()
82  {
83  LARGE_INTEGER li;
84  __asm {
85  rdtsc
86  mov li.LowPart, eax
87  mov li.HighPart, edx
88  }
89  return li.QuadPart;
90  }
91 #else
92  static void __cpuid(int* cpuid_data, int) {
93  cpuid_data[0] = 0x00000000;
94  cpuid_data[1] = 0x00000000;
95  cpuid_data[2] = 0x00000000;
96  cpuid_data[3] = 0x00000000;
97  }
98  __int64 __rdtsc() { return (__int64)0; }
99 #endif
100 
101 extern "C" {
102  extern void Gl_setwidth(int width);
103  void *_ReturnAddress(void);
104 }
105 
106 //////////////////// Windows TFdSet ////////////////////////////////////////////////
107 class TFdSet {
108 private:
109  fd_set *fds_bits; // file descriptors (according MSDN maximum is 64)
110 public:
111  TFdSet() { fds_bits = new fd_set; fds_bits->fd_count = 0; }
112  virtual ~TFdSet() { delete fds_bits; }
113  void Copy(TFdSet &fd) const { memcpy((void*)fd.fds_bits, fds_bits, sizeof(fd_set)); }
114  TFdSet(const TFdSet& fd) { fd.Copy(*this); }
115  TFdSet& operator=(const TFdSet& fd) { fd.Copy(*this); return *this; }
116  void Zero() { fds_bits->fd_count = 0; }
117  void Set(Int_t fd)
118  {
119  if (fds_bits->fd_count < FD_SETSIZE-1) // protect out of bound access (64)
120  fds_bits->fd_array[fds_bits->fd_count++] = (SOCKET)fd;
121  else
122  ::SysError("TFdSet::Set", "fd_count will exeed FD_SETSIZE");
123  }
124  void Clr(Int_t fd)
125  {
126  int i;
127  for (i=0; i<fds_bits->fd_count; i++) {
128  if (fds_bits->fd_array[i]==(SOCKET)fd) {
129  while (i<fds_bits->fd_count-1) {
130  fds_bits->fd_array[i] = fds_bits->fd_array[i+1];
131  i++;
132  }
133  fds_bits->fd_count--;
134  break;
135  }
136  }
137  }
138  Int_t IsSet(Int_t fd) { return __WSAFDIsSet((SOCKET)fd, fds_bits); }
139  Int_t *GetBits() { return fds_bits && fds_bits->fd_count ? (Int_t*)fds_bits : 0; }
140  UInt_t GetCount() { return (UInt_t)fds_bits->fd_count; }
141  Int_t GetFd(Int_t i) { return i<fds_bits->fd_count ? fds_bits->fd_array[i] : 0; }
142 };
143 
144 namespace {
145  const char *kProtocolName = "tcp";
146  typedef void (*SigHandler_t)(ESignals);
147  static TWinNTSystem::ThreadMsgFunc_t gGUIThreadMsgFunc = 0; // GUI thread message handler func
148 
149  static HANDLE gGlobalEvent;
150  static HANDLE gTimerThreadHandle;
151  typedef NET_API_STATUS (WINAPI *pfn1)(LPVOID);
152  typedef NET_API_STATUS (WINAPI *pfn2)(LPCWSTR, LPCWSTR, DWORD, LPBYTE*);
153  typedef NET_API_STATUS (WINAPI *pfn3)(LPCWSTR, LPCWSTR, DWORD, LPBYTE*,
154  DWORD, LPDWORD, LPDWORD, PDWORD);
155  typedef NET_API_STATUS (WINAPI *pfn4)(LPCWSTR, DWORD, LPBYTE*, DWORD, LPDWORD,
156  LPDWORD, PDWORD);
157  static pfn1 p2NetApiBufferFree;
158  static pfn2 p2NetUserGetInfo;
159  static pfn3 p2NetLocalGroupGetMembers;
160  static pfn4 p2NetLocalGroupEnum;
161 
162  static struct signal_map {
163  int code;
164  SigHandler_t handler;
165  char *signame;
166  } signal_map[kMAXSIGNALS] = { // the order of the signals should be identical
167  -1 /*SIGBUS*/, 0, "bus error", // to the one in SysEvtHandler.h
168  SIGSEGV, 0, "segmentation violation",
169  -1 /*SIGSYS*/, 0, "bad argument to system call",
170  -1 /*SIGPIPE*/, 0, "write on a pipe with no one to read it",
171  SIGILL, 0, "illegal instruction",
172  -1 /*SIGQUIT*/, 0, "quit",
173  SIGINT, 0, "interrupt",
174  -1 /*SIGWINCH*/, 0, "window size change",
175  -1 /*SIGALRM*/, 0, "alarm clock",
176  -1 /*SIGCHLD*/, 0, "death of a child",
177  -1 /*SIGURG*/, 0, "urgent data arrived on an I/O channel",
178  SIGFPE, 0, "floating point exception",
179  SIGTERM, 0, "termination signal",
180  -1 /*SIGUSR1*/, 0, "user-defined signal 1",
181  -1 /*SIGUSR2*/, 0, "user-defined signal 2"
182  };
183 
184  ////// static functions providing interface to raw WinNT ////////////////////
185 
186  //---- RPC -------------------------------------------------------------------
187  //*-* Error codes set by the Windows Sockets implementation are not made available
188  //*-* via the errno variable. Additionally, for the getXbyY class of functions,
189  //*-* error codes are NOT made available via the h_errno variable. Instead, error
190  //*-* codes are accessed by using the WSAGetLastError . This function is provided
191  //*-* in Windows Sockets as a precursor (and eventually an alias) for the Win32
192  //*-* function GetLastError. This is intended to provide a reliable way for a thread
193  //*-* in a multithreaded process to obtain per-thread error information.
194 
195  /////////////////////////////////////////////////////////////////////////////
196  /// Receive exactly length bytes into buffer. Returns number of bytes
197  /// received. Returns -1 in case of error, -2 in case of MSG_OOB
198  /// and errno == EWOULDBLOCK, -3 in case of MSG_OOB and errno == EINVAL
199  /// and -4 in case of kNonBlock and errno == EWOULDBLOCK.
200  /// Returns -5 if pipe broken or reset by peer (EPIPE || ECONNRESET).
201 
202  static int WinNTRecv(int socket, void *buffer, int length, int flag)
203  {
204  if (socket == -1) return -1;
205  SOCKET sock = socket;
206 
207  int once = 0;
208  if (flag == -1) {
209  flag = 0;
210  once = 1;
211  }
212  if (flag == MSG_PEEK) {
213  once = 1;
214  }
215 
216  int nrecv, n;
217  char *buf = (char *)buffer;
218 
219  for (n = 0; n < length; n += nrecv) {
220  if ((nrecv = ::recv(sock, buf+n, length-n, flag)) <= 0) {
221  if (nrecv == 0) {
222  break; // EOF
223  }
224  if (flag == MSG_OOB) {
225  if (::WSAGetLastError() == WSAEWOULDBLOCK) {
226  return -2;
227  } else if (::WSAGetLastError() == WSAEINVAL) {
228  return -3;
229  }
230  }
231  if (::WSAGetLastError() == WSAEWOULDBLOCK) {
232  return -4;
233  } else {
234  if (::WSAGetLastError() != WSAEINTR)
235  ::SysError("TWinNTSystem::WinNTRecv", "recv");
236  if (::WSAGetLastError() == EPIPE ||
237  ::WSAGetLastError() == WSAECONNRESET)
238  return -5;
239  else
240  return -1;
241  }
242  }
243  if (once) {
244  return nrecv;
245  }
246  }
247  return n;
248  }
249 
250  /////////////////////////////////////////////////////////////////////////////
251  /// Send exactly length bytes from buffer. Returns -1 in case of error,
252  /// otherwise number of sent bytes. Returns -4 in case of kNoBlock and
253  /// errno == EWOULDBLOCK. Returns -5 if pipe broken or reset by peer
254  /// (EPIPE || ECONNRESET).
255 
256  static int WinNTSend(int socket, const void *buffer, int length, int flag)
257  {
258  if (socket < 0) return -1;
259  SOCKET sock = socket;
260 
261  int once = 0;
262  if (flag == -1) {
263  flag = 0;
264  once = 1;
265  }
266 
267  int nsent, n;
268  const char *buf = (const char *)buffer;
269 
270  for (n = 0; n < length; n += nsent) {
271  if ((nsent = ::send(sock, buf+n, length-n, flag)) <= 0) {
272  if (nsent == 0) {
273  break;
274  }
275  if (::WSAGetLastError() == WSAEWOULDBLOCK) {
276  return -4;
277  } else {
278  if (::WSAGetLastError() != WSAEINTR)
279  ::SysError("TWinNTSystem::WinNTSend", "send");
280  if (::WSAGetLastError() == EPIPE ||
281  ::WSAGetLastError() == WSAECONNRESET)
282  return -5;
283  else
284  return -1;
285  }
286  }
287  if (once) {
288  return nsent;
289  }
290  }
291  return n;
292  }
293 
294  /////////////////////////////////////////////////////////////////////////////
295  /// Wait for events on the file descriptors specified in the readready and
296  /// writeready masks or for timeout (in milliseconds) to occur.
297 
298  static int WinNTSelect(TFdSet *readready, TFdSet *writeready, Long_t timeout)
299  {
300  int retcode;
301  fd_set* rbits = readready ? (fd_set*)readready->GetBits() : 0;
302  fd_set* wbits = writeready ? (fd_set*)writeready->GetBits() : 0;
303 
304  if (timeout >= 0) {
305  timeval tv;
306  tv.tv_sec = timeout / 1000;
307  tv.tv_usec = (timeout % 1000) * 1000;
308 
309  retcode = ::select(0, rbits, wbits, 0, &tv);
310  } else {
311  retcode = ::select(0, rbits, wbits, 0, 0);
312  }
313 
314  if (retcode == SOCKET_ERROR) {
315  int errcode = ::WSAGetLastError();
316 
317  // if file descriptor is not a socket, assume it is the pipe used
318  // by TXSocket
319  if (errcode == WSAENOTSOCK) {
320  struct __stat64 buf;
321  int result = _fstat64( readready->GetFd(0), &buf );
322  if ( result == 0 ) {
323  if (buf.st_size > 0)
324  return 1;
325  }
326  // yield execution to another thread that is ready to run
327  // if no other thread is ready, sleep 1 ms before to return
328  if (gGlobalEvent) {
329  ::WaitForSingleObject(gGlobalEvent, 1);
330  ::ResetEvent(gGlobalEvent);
331  }
332  return 0;
333  }
334 
335  if ( errcode == WSAEINTR) {
336  TSystem::ResetErrno(); // errno is not self reseting
337  return -2;
338  }
339  if (errcode == EBADF) {
340  return -3;
341  }
342  return -1;
343  }
344  return retcode;
345  }
346 
347  /////////////////////////////////////////////////////////////////////////////
348  /// Get shared library search path.
349 
350  static const char *DynamicPath(const char *newpath = 0, Bool_t reset = kFALSE)
351  {
352  static TString dynpath;
353 
354  if (reset || newpath) {
355  dynpath = "";
356  }
357  if (newpath) {
358 
359  dynpath = newpath;
360 
361  } else if (dynpath == "") {
362  TString rdynpath = gEnv ? gEnv->GetValue("Root.DynamicPath", (char*)0) : "";
363  rdynpath.ReplaceAll("; ", ";"); // in case DynamicPath was extended
364  if (rdynpath == "") {
365 #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 working directory for the selected drive
2141 /// driveletter == 0 means return the working durectory for the default drive
2142 
2143 const char *TWinNTSystem::WorkingDirectory(char driveletter)
2144 {
2145  char *wdpath = 0;
2146  char drive = driveletter ? toupper( driveletter ) - 'A' + 1 : 0;
2147 
2148  // don't use cache as user can call chdir() directly somewhere else
2149  //if (fWdpath != "" )
2150  // return fWdpath;
2151 
2152  if (!(wdpath = ::_getdcwd( (int)drive, wdpath, kMAXPATHLEN))) {
2153  free(wdpath);
2154  Warning("WorkingDirectory", "getcwd() failed");
2155  return 0;
2156  }
2157  fWdpath = wdpath;
2158  // Make sure the drive letter is upper case
2159  if (fWdpath[1] == ':')
2160  fWdpath[0] = toupper(fWdpath[0]);
2161  free(wdpath);
2162  return fWdpath;
2163 }
2164 
2165 ////////////////////////////////////////////////////////////////////////////////
2166 /// Return the user's home directory.
2167 
2168 const char *TWinNTSystem::HomeDirectory(const char *userName)
2169 {
2170  static char mydir[kMAXPATHLEN] = "./";
2171  const char *h = 0;
2172  if (!(h = ::getenv("home"))) h = ::getenv("HOME");
2173 
2174  if (h) {
2175  strlcpy(mydir, h,kMAXPATHLEN);
2176  } else {
2177  // for Windows NT HOME might be defined as either $(HOMESHARE)/$(HOMEPATH)
2178  // or $(HOMEDRIVE)/$(HOMEPATH)
2179  h = ::getenv("HOMESHARE");
2180  if (!h) h = ::getenv("HOMEDRIVE");
2181  if (h) {
2182  strlcpy(mydir, h,kMAXPATHLEN);
2183  h = ::getenv("HOMEPATH");
2184  if(h) strlcat(mydir, h,kMAXPATHLEN);
2185  }
2186  // on Windows Vista HOME is usually defined as $(USERPROFILE)
2187  if (!h) {
2188  h = ::getenv("USERPROFILE");
2189  if (h) strlcpy(mydir, h,kMAXPATHLEN);
2190  }
2191  }
2192  // Make sure the drive letter is upper case
2193  if (mydir[1] == ':')
2194  mydir[0] = toupper(mydir[0]);
2195  return mydir;
2196 }
2197 
2198 ////////////////////////////////////////////////////////////////////////////////
2199 /// Return a user configured or systemwide directory to create
2200 /// temporary files in.
2201 
2202 const char *TWinNTSystem::TempDirectory() const
2203 {
2204  const char *dir = gSystem->Getenv("TEMP");
2205  if (!dir) dir = gSystem->Getenv("TEMPDIR");
2206  if (!dir) dir = gSystem->Getenv("TEMP_DIR");
2207  if (!dir) dir = gSystem->Getenv("TMP");
2208  if (!dir) dir = gSystem->Getenv("TMPDIR");
2209  if (!dir) dir = gSystem->Getenv("TMP_DIR");
2210  if (!dir) dir = "c:\\";
2211 
2212  return dir;
2213 }
2214 
2215 ////////////////////////////////////////////////////////////////////////////////
2216 /// Create a secure temporary file by appending a unique
2217 /// 6 letter string to base. The file will be created in
2218 /// a standard (system) directory or in the directory
2219 /// provided in dir. The full filename is returned in base
2220 /// and a filepointer is returned for safely writing to the file
2221 /// (this avoids certain security problems). Returns 0 in case
2222 /// of error.
2223 
2224 FILE *TWinNTSystem::TempFileName(TString &base, const char *dir)
2225 {
2226  char tmpName[MAX_PATH];
2227 
2228  ::GetTempFileName(dir ? dir : TempDirectory(), base.Data(), 0, tmpName);
2229  base = tmpName;
2230  FILE *fp = fopen(tmpName, "w+");
2231 
2232  if (!fp) ::SysError("TempFileName", "error opening %s", tmpName);
2233 
2234  return fp;
2235 }
2236 
2237 //---- Paths & Files -----------------------------------------------------------
2238 
2239 ////////////////////////////////////////////////////////////////////////////////
2240 /// Get list of volumes (drives) mounted on the system.
2241 /// The returned TList must be deleted by the user using "delete".
2242 
2244 {
2245  Int_t curdrive;
2246  UInt_t type;
2247  TString sDrive, sType;
2248  char szFs[32];
2249 
2250  if (!opt || !opt[0]) {
2251  return 0;
2252  }
2253 
2254  // prevent the system dialog box to pop-up if a drive is empty
2255  UINT nOldErrorMode = ::SetErrorMode(SEM_FAILCRITICALERRORS);
2256  TList *drives = new TList();
2257  drives->SetOwner();
2258  // Save current drive
2259  curdrive = _getdrive();
2260  if (strstr(opt, "cur")) {
2261  *szFs='\0';
2262  sDrive.Form("%c:", (curdrive + 'A' - 1));
2263  sType.Form("Unknown Drive (%s)", sDrive.Data());
2264  ::GetVolumeInformation(Form("%s\\", sDrive.Data()), NULL, 0, NULL, NULL,
2265  NULL, (LPSTR)szFs, 32);
2266  type = ::GetDriveType(sDrive.Data());
2267  switch (type) {
2268  case DRIVE_UNKNOWN:
2269  case DRIVE_NO_ROOT_DIR:
2270  break;
2271  case DRIVE_REMOVABLE:
2272  sType.Form("Removable Disk (%s)", sDrive.Data());
2273  break;
2274  case DRIVE_FIXED:
2275  sType.Form("Local Disk (%s)", sDrive.Data());
2276  break;
2277  case DRIVE_REMOTE:
2278  sType.Form("Network Drive (%s) (%s)", szFs, sDrive.Data());
2279  break;
2280  case DRIVE_CDROM:
2281  sType.Form("CD/DVD Drive (%s)", sDrive.Data());
2282  break;
2283  case DRIVE_RAMDISK:
2284  sType.Form("RAM Disk (%s)", sDrive.Data());
2285  break;
2286  }
2287  drives->Add(new TNamed(sDrive.Data(), sType.Data()));
2288  }
2289  else if (strstr(opt, "all")) {
2290  TCHAR szTemp[512];
2291  szTemp[0] = '\0';
2292  if (::GetLogicalDriveStrings(511, szTemp)) {
2293  TCHAR szDrive[3] = TEXT(" :");
2294  TCHAR* p = szTemp;
2295  do {
2296  // Copy the drive letter to the template string
2297  *szDrive = *p;
2298  *szFs='\0';
2299  sDrive.Form("%s", szDrive);
2300  // skip floppy drives, to avoid accessing them each time...
2301  if ((sDrive == "A:") || (sDrive == "B:")) {
2302  while (*p++);
2303  continue;
2304  }
2305  sType.Form("Unknown Drive (%s)", sDrive.Data());
2306  ::GetVolumeInformation(Form("%s\\", sDrive.Data()), NULL, 0, NULL,
2307  NULL, NULL, (LPSTR)szFs, 32);
2308  type = ::GetDriveType(sDrive.Data());
2309  switch (type) {
2310  case DRIVE_UNKNOWN:
2311  case DRIVE_NO_ROOT_DIR:
2312  break;
2313  case DRIVE_REMOVABLE:
2314  sType.Form("Removable Disk (%s)", sDrive.Data());
2315  break;
2316  case DRIVE_FIXED:
2317  sType.Form("Local Disk (%s)", sDrive.Data());
2318  break;
2319  case DRIVE_REMOTE:
2320  sType.Form("Network Drive (%s) (%s)", szFs, sDrive.Data());
2321  break;
2322  case DRIVE_CDROM:
2323  sType.Form("CD/DVD Drive (%s)", sDrive.Data());
2324  break;
2325  case DRIVE_RAMDISK:
2326  sType.Form("RAM Disk (%s)", sDrive.Data());
2327  break;
2328  }
2329  drives->Add(new TNamed(sDrive.Data(), sType.Data()));
2330  // Go to the next NULL character.
2331  while (*p++);
2332  } while (*p); // end of string
2333  }
2334  }
2335  // restore previous error mode
2336  ::SetErrorMode(nOldErrorMode);
2337  return drives;
2338 }
2339 
2340 ////////////////////////////////////////////////////////////////////////////////
2341 /// Return the directory name in pathname. DirName of c:/user/root is /user.
2342 /// It creates output with 'new char []' operator. Returned string has to
2343 /// be deleted.
2344 
2345 const char *TWinNTSystem::DirName(const char *pathname)
2346 {
2347  // Delete old buffer
2348  if (fDirNameBuffer) {
2349  // delete [] fDirNameBuffer;
2350  fDirNameBuffer = 0;
2351  }
2352 
2353  // Create a buffer to keep the path name
2354  if (pathname) {
2355  if (strchr(pathname, '/') || strchr(pathname, '\\')) {
2356  const char *rslash = strrchr(pathname, '/');
2357  const char *bslash = strrchr(pathname, '\\');
2358  const char *r = std::max(rslash, bslash);
2359  const char *ptr = pathname;
2360  while (ptr <= r) {
2361  if (*ptr == ':') {
2362  // Windows path may contain a drive letter
2363  // For NTFS ":" may be a "stream" delimiter as well
2364  pathname = ptr + 1;
2365  break;
2366  }
2367  ptr++;
2368  }
2369  int len = r - pathname;
2370  if (len > 0) {
2371  fDirNameBuffer = new char[len+1];
2372  memcpy(fDirNameBuffer, pathname, len);
2373  fDirNameBuffer[len] = 0;
2374  }
2375  }
2376  }
2377  if (!fDirNameBuffer) {
2378  fDirNameBuffer = new char[1];
2379  *fDirNameBuffer = '\0'; // Set the empty default response
2380  }
2381  return fDirNameBuffer;
2382 }
2383 
2384 ////////////////////////////////////////////////////////////////////////////////
2385 /////////////////////////////////////////////////////////////////////////////
2386 /// Return the drive letter in pathname. DriveName of 'c:/user/root' is 'c'//
2387 /// Input: //
2388 /// pathname - the string containing file name //
2389 /// Return: //
2390 /// = Letter presenting the drive letter in the file name //
2391 /// = The current drive if the pathname has no drive assigment //
2392 /// = 0 if pathname is an empty string or uses UNC syntax //
2393 /// Note: //
2394 /// It doesn't chech whether pathname presents the 'real filename //
2395 /// This subroutine looks for 'single letter' is follows with a ':' //
2396 /////////////////////////////////////////////////////////////////////////////
2397 
2398 const char TWinNTSystem::DriveName(const char *pathname)
2399 {
2400  if (!pathname) return 0;
2401  if (!pathname[0]) return 0;
2402 
2403  const char *lpchar;
2404  lpchar = pathname;
2405 
2406  // Skip blanks
2407  while(*lpchar == ' ') lpchar++;
2408 
2409  if (isalpha((int)*lpchar) && *(lpchar+1) == ':') {
2410  return *lpchar;
2411  }
2412  // Test UNC syntax
2413  if ( (*lpchar == '\\' || *lpchar == '/' ) &&
2414  (*(lpchar+1) == '\\' || *(lpchar+1) == '/') ) return 0;
2415 
2416  // return the current drive
2417  return DriveName(WorkingDirectory());
2418 }
2419 
2420 ////////////////////////////////////////////////////////////////////////////////
2421 /// Return true if dir is an absolute pathname.
2422 
2424 {
2425  if (dir) {
2426  int idx = 0;
2427  if (strchr(dir,':')) idx = 2;
2428  return (dir[idx] == '/' || dir[idx] == '\\');
2429  }
2430  return kFALSE;
2431 }
2432 
2433 ////////////////////////////////////////////////////////////////////////////////
2434 /// Convert a pathname to a unix pathname. E.g. form \user\root to /user/root.
2435 /// General rules for applications creating names for directories and files or
2436 /// processing names supplied by the user include the following:
2437 ///
2438 /// * Use any character in the current code page for a name, but do not use
2439 /// a path separator, a character in the range 0 through 31, or any character
2440 /// explicitly disallowed by the file system. A name can contain characters
2441 /// in the extended character set (128-255).
2442 /// * Use the backslash (\), the forward slash (/), or both to separate
2443 /// components in a path. No other character is acceptable as a path separator.
2444 /// * Use a period (.) as a directory component in a path to represent the
2445 /// current directory.
2446 /// * Use two consecutive periods (..) as a directory component in a path to
2447 /// represent the parent of the current directory.
2448 /// * Use a period (.) to separate components in a directory name or filename.
2449 /// * Do not use the following characters in directory names or filenames, because
2450 /// they are reserved for Windows:
2451 /// < > : " / \ |
2452 /// * Do not use reserved words, such as aux, con, and prn, as filenames or
2453 /// directory names.
2454 /// * Process a path as a null-terminated string. The maximum length for a path
2455 /// is given by MAX_PATH.
2456 /// * Do not assume case sensitivity. Consider names such as OSCAR, Oscar, and
2457 /// oscar to be the same.
2458 
2459 const char *TWinNTSystem::UnixPathName(const char *name)
2460 {
2461  static char temp[1024];
2462  strlcpy(temp, name,1024);
2463  char *currentChar = temp;
2464 
2465  while (*currentChar != '\0') {
2466  if (*currentChar == '\\') *currentChar = '/';
2467  currentChar++;
2468  }
2469  return temp;
2470 }
2471 
2472 ////////////////////////////////////////////////////////////////////////////////
2473 /// Returns FALSE if one can access a file using the specified access mode.
2474 /// Mode is the same as for the WinNT access(2) function.
2475 /// Attention, bizarre convention of return value!!
2476 
2478 {
2479  TSystem *helper = FindHelper(path);
2480  if (helper)
2481  return helper->AccessPathName(path, mode);
2482 
2483  // prevent the system dialog box to pop-up if a drive is empty
2484  UINT nOldErrorMode = ::SetErrorMode(SEM_FAILCRITICALERRORS);
2485  if (mode==kExecutePermission)
2486  // cannot test on exe - use read instead
2487  mode=kReadPermission;
2488  const char *proto = (strstr(path, "file:///")) ? "file://" : "file:";
2489  if (::_access(StripOffProto(path, proto), mode) == 0) {
2490  // restore previous error mode
2491  ::SetErrorMode(nOldErrorMode);
2492  return kFALSE;
2493  }
2495  // restore previous error mode
2496  ::SetErrorMode(nOldErrorMode);
2497  return kTRUE;
2498 }
2499 
2500 ////////////////////////////////////////////////////////////////////////////////
2501 /// Returns TRUE if the url in 'path' points to the local file system.
2502 /// This is used to avoid going through the NIC card for local operations.
2503 
2505 {
2506  TSystem *helper = FindHelper(path);
2507  if (helper)
2508  return helper->IsPathLocal(path);
2509 
2510  return TSystem::IsPathLocal(path);
2511 }
2512 
2513 ////////////////////////////////////////////////////////////////////////////////
2514 /// Concatenate a directory and a file name.
2515 
2516 const char *TWinNTSystem::PrependPathName(const char *dir, TString& name)
2517 {
2518  if (name == ".") name = "";
2519  if (dir && dir[0]) {
2520  // Test whether the last symbol of the directory is a separator
2521  char last = dir[strlen(dir) - 1];
2522  if (last != '/' && last != '\\') {
2523  name.Prepend('\\');
2524  }
2525  name.Prepend(dir);
2526  name.ReplaceAll("/", "\\");
2527  }
2528  return name.Data();
2529 }
2530 
2531 ////////////////////////////////////////////////////////////////////////////////
2532 /// Copy a file. If overwrite is true and file already exists the
2533 /// file will be overwritten. Returns 0 when successful, -1 in case
2534 /// of failure, -2 in case the file already exists and overwrite was false.
2535 
2536 int TWinNTSystem::CopyFile(const char *f, const char *t, Bool_t overwrite)
2537 {
2538  if (AccessPathName(f, kReadPermission)) return -1;
2539  if (!AccessPathName(t) && !overwrite) return -2;
2540 
2541  Bool_t ret = ::CopyFileA(f, t, kFALSE);
2542 
2543  if (!ret) return -1;
2544  return 0;
2545 }
2546 
2547 ////////////////////////////////////////////////////////////////////////////////
2548 /// Rename a file. Returns 0 when successful, -1 in case of failure.
2549 
2550 int TWinNTSystem::Rename(const char *f, const char *t)
2551 {
2552  int ret = ::rename(f, t);
2554  return ret;
2555 }
2556 
2557 ////////////////////////////////////////////////////////////////////////////////
2558 /// Get info about a file. Info is returned in the form of a FileStat_t
2559 /// structure (see TSystem.h).
2560 /// The function returns 0 in case of success and 1 if the file could
2561 /// not be stat'ed.
2562 
2563 int TWinNTSystem::GetPathInfo(const char *path, FileStat_t &buf)
2564 {
2565  TSystem *helper = FindHelper(path);
2566  if (helper)
2567  return helper->GetPathInfo(path, buf);
2568 
2569  struct _stati64 sbuf;
2570 
2571  // Remove trailing backslashes
2572  const char *proto = (strstr(path, "file:///")) ? "file://" : "file:";
2573  char *newpath = StrDup(StripOffProto(path, proto));
2574  int l = strlen(newpath);
2575  while (l > 1) {
2576  if (newpath[--l] != '\\' || newpath[--l] != '/') {
2577  break;
2578  }
2579  newpath[l] = '\0';
2580  }
2581 
2582  if (newpath && ::_stati64(newpath, &sbuf) >= 0) {
2583 
2584  buf.fDev = sbuf.st_dev;
2585  buf.fIno = sbuf.st_ino;
2586  buf.fMode = sbuf.st_mode;
2587  buf.fUid = sbuf.st_uid;
2588  buf.fGid = sbuf.st_gid;
2589  buf.fSize = sbuf.st_size;
2590  buf.fMtime = sbuf.st_mtime;
2591  buf.fIsLink = IsShortcut(newpath); // kFALSE;
2592 
2593  char *lpath = new char[MAX_PATH];
2594  if (IsShortcut(newpath)) {
2595  struct _stati64 sbuf2;
2596  if (ResolveShortCut(newpath, lpath, MAX_PATH)) {
2597  if (::_stati64(lpath, &sbuf2) >= 0) {
2598  buf.fMode = sbuf2.st_mode;
2599  }
2600  }
2601  }
2602  delete [] lpath;
2603 
2604  delete [] newpath;
2605  return 0;
2606  }
2607  delete [] newpath;
2608  return 1;
2609 }
2610 
2611 ////////////////////////////////////////////////////////////////////////////////
2612 /// Get info about a file system: id, bsize, bfree, blocks.
2613 /// Id is file system type (machine dependend, see statfs())
2614 /// Bsize is block size of file system
2615 /// Blocks is total number of blocks in file system
2616 /// Bfree is number of free blocks in file system
2617 /// The function returns 0 in case of success and 1 if the file system could
2618 /// not be stat'ed.
2619 
2620 int TWinNTSystem::GetFsInfo(const char *path, Long_t *id, Long_t *bsize,
2621  Long_t *blocks, Long_t *bfree)
2622 {
2623  // address of root directory of the file system
2624  LPCTSTR lpRootPathName = path;
2625 
2626  // address of name of the volume
2627  LPTSTR lpVolumeNameBuffer = 0;
2628  DWORD nVolumeNameSize = 0;
2629 
2630  DWORD volumeSerialNumber; // volume serial number
2631  DWORD maximumComponentLength; // system's maximum filename length
2632 
2633  // file system flags
2634  DWORD fileSystemFlags;
2635 
2636  // address of name of file system
2637  char fileSystemNameBuffer[512];
2638  DWORD nFileSystemNameSize = sizeof(fileSystemNameBuffer);
2639 
2640  // prevent the system dialog box to pop-up if the drive is empty
2641  UINT nOldErrorMode = ::SetErrorMode(SEM_FAILCRITICALERRORS);
2642  if (!::GetVolumeInformation(lpRootPathName,
2643  lpVolumeNameBuffer, nVolumeNameSize,
2644  &volumeSerialNumber,
2645  &maximumComponentLength,
2646  &fileSystemFlags,
2647  fileSystemNameBuffer, nFileSystemNameSize)) {
2648  // restore previous error mode
2649  ::SetErrorMode(nOldErrorMode);
2650  return 1;
2651  }
2652 
2653  const char *fsNames[] = { "FAT", "NTFS" };
2654  int i;
2655  for (i = 0; i < 2; i++) {
2656  if (!strncmp(fileSystemNameBuffer, fsNames[i], nFileSystemNameSize))
2657  break;
2658  }
2659  *id = i;
2660 
2661  DWORD sectorsPerCluster; // # sectors per cluster
2662  DWORD bytesPerSector; // # bytes per sector
2663  DWORD numberOfFreeClusters; // # free clusters
2664  DWORD totalNumberOfClusters; // # total of clusters
2665 
2666  if (!::GetDiskFreeSpace(lpRootPathName,
2667  &sectorsPerCluster,
2668  &bytesPerSector,
2669  &numberOfFreeClusters,
2670  &totalNumberOfClusters)) {
2671  // restore previous error mode
2672  ::SetErrorMode(nOldErrorMode);
2673  return 1;
2674  }
2675  // restore previous error mode
2676  ::SetErrorMode(nOldErrorMode);
2677 
2678  *bsize = sectorsPerCluster * bytesPerSector;
2679  *blocks = totalNumberOfClusters;
2680  *bfree = numberOfFreeClusters;
2681 
2682  return 0;
2683 }
2684 
2685 ////////////////////////////////////////////////////////////////////////////////
2686 /// Create a link from file1 to file2.
2687 
2688 int TWinNTSystem::Link(const char *from, const char *to)
2689 {
2690  struct _stati64 finfo;
2691  char winDrive[256];
2692  char winDir[256];
2693  char winName[256];
2694  char winExt[256];
2695  char linkname[1024];
2696  LPTSTR lpszFilePart;
2697  TCHAR szPath[MAX_PATH];
2698  DWORD dwRet = 0;
2699 
2700  typedef BOOL (__stdcall *CREATEHARDLINKPROC)( LPCTSTR, LPCTSTR, LPSECURITY_ATTRIBUTES );
2701  static CREATEHARDLINKPROC _CreateHardLink = 0;
2702 
2703  HMODULE hModImagehlp = LoadLibrary( "Kernel32.dll" );
2704  if (!hModImagehlp)
2705  return -1;
2706 
2707 #ifdef _UNICODE
2708  _CreateHardLink = (CREATEHARDLINKPROC) GetProcAddress( hModImagehlp, "CreateHardLinkW" );
2709 #else
2710  _CreateHardLink = (CREATEHARDLINKPROC) GetProcAddress( hModImagehlp, "CreateHardLinkA" );
2711 #endif
2712  if (!_CreateHardLink)
2713  return -1;
2714 
2715  dwRet = GetFullPathName(from, sizeof(szPath) / sizeof(TCHAR),
2716  szPath, &lpszFilePart);
2717 
2718  if (_stati64(szPath, &finfo) < 0)
2719  return -1;
2720 
2721  if (finfo.st_mode & S_IFDIR)
2722  return -1;
2723 
2724  snprintf(linkname,1024,"%s",to);
2725  _splitpath(linkname,winDrive,winDir,winName,winExt);
2726  if ((!winDrive[0] ) &&
2727  (!winDir[0] )) {
2728  _splitpath(szPath,winDrive,winDir,winName,winExt);
2729  snprintf(linkname,1024,"%s\\%s\\%s", winDrive, winDir, to);
2730  }
2731  else if (!winDrive[0]) {
2732  _splitpath(szPath,winDrive,winDir,winName,winExt);
2733  snprintf(linkname,1024,"%s\\%s", winDrive, to);
2734  }
2735 
2736  if (!_CreateHardLink(linkname, szPath, NULL))
2737  return -1;
2738 
2739  return 0;
2740 }
2741 
2742 ////////////////////////////////////////////////////////////////////////////////
2743 /// Create a symlink from file1 to file2. Returns 0 when successful,
2744 /// -1 in case of failure.
2745 
2746 int TWinNTSystem::Symlink(const char *from, const char *to)
2747 {
2748  HRESULT hRes; /* Returned COM result code */
2749  IShellLink* pShellLink; /* IShellLink object pointer */
2750  IPersistFile* pPersistFile; /* IPersistFile object pointer */
2751  WCHAR wszLinkfile[MAX_PATH]; /* pszLinkfile as Unicode string */
2752  int iWideCharsWritten; /* Number of wide characters written */
2753  DWORD dwRet = 0;
2754  LPTSTR lpszFilePart;
2755  TCHAR szPath[MAX_PATH];
2756 
2757  hRes = E_INVALIDARG;
2758  if ((from == NULL) || (!from[0]) || (to == NULL) ||
2759  (!to[0]))
2760  return -1;
2761 
2762  // Make typedefs for some ole32.dll functions so that we can use them
2763  // with GetProcAddress
2764  typedef HRESULT (__stdcall *COINITIALIZEPROC)( LPVOID );
2765  static COINITIALIZEPROC _CoInitialize = 0;
2766  typedef void (__stdcall *COUNINITIALIZEPROC)( void );
2767  static COUNINITIALIZEPROC _CoUninitialize = 0;
2768  typedef HRESULT (__stdcall *COCREATEINSTANCEPROC)( REFCLSID, LPUNKNOWN, DWORD, REFIID, LPVOID );
2769  static COCREATEINSTANCEPROC _CoCreateInstance = 0;
2770 
2771  HMODULE hModImagehlp = LoadLibrary( "ole32.dll" );
2772  if (!hModImagehlp)
2773  return -1;
2774 
2775  _CoInitialize = (COINITIALIZEPROC) GetProcAddress( hModImagehlp, "CoInitialize" );
2776  if (!_CoInitialize)
2777  return -1;
2778  _CoUninitialize = (COUNINITIALIZEPROC) GetProcAddress( hModImagehlp, "CoUninitialize" );
2779  if (!_CoUninitialize)
2780  return -1;
2781  _CoCreateInstance = (COCREATEINSTANCEPROC) GetProcAddress( hModImagehlp, "CoCreateInstance" );
2782  if (!_CoCreateInstance)
2783  return -1;
2784 
2785  TString linkname(to);
2786  if (!linkname.EndsWith(".lnk"))
2787  linkname.Append(".lnk");
2788 
2789  _CoInitialize(NULL);
2790 
2791  // Retrieve the full path and file name of a specified file
2792  dwRet = GetFullPathName(from, sizeof(szPath) / sizeof(TCHAR),
2793  szPath, &lpszFilePart);
2794  hRes = _CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
2795  IID_IShellLink, (LPVOID *)&pShellLink);
2796  if (SUCCEEDED(hRes)) {
2797  // Set the fields in the IShellLink object
2798  hRes = pShellLink->SetPath(szPath);
2799  // Use the IPersistFile object to save the shell link
2800  hRes = pShellLink->QueryInterface(IID_IPersistFile, (void **)&pPersistFile);
2801  if (SUCCEEDED(hRes)){
2802  iWideCharsWritten = MultiByteToWideChar(CP_ACP, 0, linkname.Data(), -1,
2803  wszLinkfile, MAX_PATH);
2804  hRes = pPersistFile->Save(wszLinkfile, TRUE);
2805  pPersistFile->Release();
2806  }
2807  pShellLink->Release();
2808  }
2809  _CoUninitialize();
2810  return 0;
2811 }
2812 
2813 ////////////////////////////////////////////////////////////////////////////////
2814 /// Unlink, i.e. remove, a file or directory.
2815 
2816 int TWinNTSystem::Unlink(const char *name)
2817 {
2818  TSystem *helper = FindHelper(name);
2819  if (helper)
2820  return helper->Unlink(name);
2821 
2822  struct _stati64 finfo;
2823 
2824  if (_stati64(name, &finfo) < 0) {
2825  return -1;
2826  }
2827 
2828  if (finfo.st_mode & S_IFDIR) {
2829  return ::_rmdir(name);
2830  } else {
2831  return ::_unlink(name);
2832  }
2833 }
2834 
2835 ////////////////////////////////////////////////////////////////////////////////
2836 /// Make descriptor fd non-blocking.
2837 
2839 {
2840  if (::ioctlsocket(fd, FIONBIO, (u_long *)1) == SOCKET_ERROR) {
2841  ::SysError("SetNonBlock", "ioctlsocket");
2842  return -1;
2843  }
2844  return 0;
2845 }
2846 
2847 // expand the metacharacters as in the shell
2848 
2849 static char
2850  *shellMeta = "~*[]{}?$%",
2851  *shellStuff = "(){}<>\"'",
2852  shellEscape = '\\';
2853 
2854 ////////////////////////////////////////////////////////////////////////////////
2855 /// Expand a pathname getting rid of special shell characaters like ~.$, etc.
2856 
2858 {
2859  const char *patbuf = (const char *)patbuf0;
2860  const char *p;
2861  char *cmd = 0;
2862  char *q;
2863 
2864  Int_t old_level = gErrorIgnoreLevel;
2865  gErrorIgnoreLevel = kFatal; // Explicitly remove all messages
2866  TUrl urlpath(patbuf0, kTRUE);
2867  TString proto = urlpath.GetProtocol();
2868  gErrorIgnoreLevel = old_level;
2869  if (!proto.EqualTo("file")) // don't expand urls!!!
2870  return kFALSE;
2871 
2872  // skip the "file:" protocol, if any
2873  if (patbuf0.BeginsWith("file:"))
2874  patbuf += 5;
2875 
2876  // skip leading blanks
2877  while (*patbuf == ' ') {
2878  patbuf++;
2879  }
2880 
2881  // skip leading ':'
2882  while (*patbuf == ':') {
2883  patbuf++;
2884  }
2885 
2886  // skip leading ';'
2887  while (*patbuf == ';') {
2888  patbuf++;
2889  }
2890 
2891  // Transform a Unix list of directories into a Windows list
2892  // by changing the separator from ':' into ';'
2893  for (q = (char*)patbuf; *q; q++) {
2894  if ( *q == ':' ) {
2895  // We are avoiding substitution in the case of
2896  // ....;c:.... and of ...;root:/... where root can be any url protocol
2897  if ( (((q-2)>patbuf) && ( (*(q-2)!=';') || !isalpha(*(q-1)) )) &&
2898  *(q+1)!='/' ) {
2899  *q=';';
2900  }
2901  }
2902  }
2903  // any shell meta characters ?
2904  for (p = patbuf; *p; p++) {
2905  if (strchr(shellMeta, *p)) {
2906  goto needshell;
2907  }
2908  }
2909  return kFALSE;
2910 
2911 needshell:
2912 
2913  // Because (problably) we built with cygwin, the path name like:
2914  // LOCALS~1\\Temp
2915  // gets extended to
2916  // LOCALSc:\\Devel
2917  // The most likely cause is that '~' is used with Unix semantic of the
2918  // home directory (and it also cuts the path short after ... who knows why!)
2919  // So we need to detect this case and prevents its expansion :(.
2920 
2921  char replacement[4];
2922 
2923  // intentionally a non visible, unlikely character
2924  for (int k = 0; k<3; k++) replacement[k] = 0x1;
2925 
2926  replacement[3] = 0x0;
2927  Ssiz_t pos = 0;
2928  TRegexp TildaNum = "~[0-9]";
2929 
2930  while ( (pos = patbuf0.Index(TildaNum,pos)) != kNPOS ) {
2931  patbuf0.Replace(pos, 1, replacement);
2932  }
2933 
2934  // escape shell quote characters
2935  // EscChar(patbuf, stuffedPat, sizeof(stuffedPat), shellStuff, shellEscape);
2936  patbuf0 = ExpandFileName(patbuf0.Data());
2937  Int_t lbuf = ::ExpandEnvironmentStrings(
2938  patbuf0.Data(), // pointer to string with environment variables
2939  cmd, // pointer to string with expanded environment variables
2940  0 // maximum characters in expanded string
2941  );
2942  if (lbuf > 0) {
2943  cmd = new char[lbuf+1];
2944  ::ExpandEnvironmentStrings(
2945  patbuf0.Data(), // pointer to string with environment variables
2946  cmd, // pointer to string with expanded environment variables
2947  lbuf // maximum characters in expanded string
2948  );
2949  patbuf0 = cmd;
2950  patbuf0.ReplaceAll(replacement, "~");
2951  delete [] cmd;
2952  return kFALSE;
2953  }
2954  return kTRUE;
2955 }
2956 
2957 ////////////////////////////////////////////////////////////////////////////////
2958 /// Expand a pathname getting rid of special shell characaters like ~.$, etc.
2959 /// User must delete returned string.
2960 
2961 char *TWinNTSystem::ExpandPathName(const char *path)
2962 {
2963  char newpath[MAX_PATH];
2964  if (IsShortcut(path)) {
2965  if (!ResolveShortCut(path, newpath, MAX_PATH))
2966  strlcpy(newpath, path, MAX_PATH);
2967  }
2968  else
2969  strlcpy(newpath, path, MAX_PATH);
2970  TString patbuf = newpath;
2971  if (ExpandPathName(patbuf)) return 0;
2972 
2973  return StrDup(patbuf.Data());
2974 }
2975 
2976 ////////////////////////////////////////////////////////////////////////////////
2977 /// Set the file permission bits. Returns -1 in case or error, 0 otherwise.
2978 /// On windows mode can only be a combination of "user read" (0400),
2979 /// "user write" (0200) or "user read | user write" (0600). Any other value
2980 /// for mode are ignored.
2981 
2982 int TWinNTSystem::Chmod(const char *file, UInt_t mode)
2983 {
2984  return ::_chmod(file, mode);
2985 }
2986 
2987 ////////////////////////////////////////////////////////////////////////////////
2988 /// Set the process file creation mode mask.
2989 
2991 {
2992  return ::umask(mask);
2993 }
2994 
2995 ////////////////////////////////////////////////////////////////////////////////
2996 /// Set a files modification and access times. If actime = 0 it will be
2997 /// set to the modtime. Returns 0 on success and -1 in case of error.
2998 
2999 int TWinNTSystem::Utime(const char *file, Long_t modtime, Long_t actime)
3000 {
3001  if (AccessPathName(file, kWritePermission)) {
3002  Error("Utime", "need write permission for %s to change utime", file);
3003  return -1;
3004  }
3005  if (!actime) actime = modtime;
3006 
3007  struct utimbuf t;
3008  t.actime = (time_t)actime;
3009  t.modtime = (time_t)modtime;
3010  return ::utime(file, &t);
3011 }
3012 
3013 ////////////////////////////////////////////////////////////////////////////////
3014 /// Find location of file in a search path.
3015 /// User must delete returned string. Returns 0 in case file is not found.
3016 
3017 const char *TWinNTSystem::FindFile(const char *search, TString& infile, EAccessMode mode)
3018 {
3019  // Windows cannot check on execution mode - all we can do is kReadPermission
3020  if (mode==kExecutePermission)
3021  mode=kReadPermission;
3022 
3023  // Expand parameters
3024 
3025  gSystem->ExpandPathName(infile);
3026  // Check whether this infile has the absolute path first
3027  if (IsAbsoluteFileName(infile.Data()) ) {
3028  if (!AccessPathName(infile.Data(), mode))
3029  return infile.Data();
3030  infile = "";
3031  return 0;
3032  }
3033  TString exsearch(search);
3034  gSystem->ExpandPathName(exsearch);
3035 
3036  // Need to use Windows delimiters
3037  Int_t lastDelim = -1;
3038  for(int i=0; i < exsearch.Length(); ++i) {
3039  switch( exsearch[i] ) {
3040  case ':':
3041  // Replace the ':' unless there are after a disk suffix (aka ;c:\mydirec...)
3042  if (i-lastDelim!=2) exsearch[i] = ';';
3043  lastDelim = i;
3044  break;
3045  case ';': lastDelim = i; break;
3046  }
3047  }
3048 
3049  // Check access
3050  struct stat finfo;
3051  char name[kMAXPATHLEN];
3052  char *lpFilePart = 0;
3053  if (::SearchPath(exsearch.Data(), infile.Data(), NULL, kMAXPATHLEN, name, &lpFilePart) &&
3054  ::access(name, mode) == 0 && stat(name, &finfo) == 0 &&
3055  finfo.st_mode & S_IFREG) {
3056  if (gEnv->GetValue("Root.ShowPath", 0)) {
3057  Printf("Which: %s = %s", infile, name);
3058  }
3059  infile = name;
3060  return infile.Data();
3061  }
3062  infile = "";
3063  return 0;
3064 }
3065 
3066 //---- Users & Groups ----------------------------------------------------------
3067 
3068 ////////////////////////////////////////////////////////////////////////////////
3069 /// Collect local users and groups accounts information
3070 
3072 {
3073  // Net* API functions allowed and OS is Windows NT/2000/XP
3074  if ((gEnv->GetValue("WinNT.UseNetAPI", 0)) && (::GetVersion() < 0x80000000)) {
3075  fActUser = -1;
3076  fNbGroups = fNbUsers = 0;
3077  HINSTANCE netapi = ::LoadLibrary("netapi32.DLL");
3078  if (!netapi) return kFALSE;
3079 
3080  p2NetApiBufferFree = (pfn1)::GetProcAddress(netapi, "NetApiBufferFree");
3081  p2NetUserGetInfo = (pfn2)::GetProcAddress(netapi, "NetUserGetInfo");
3082  p2NetLocalGroupGetMembers = (pfn3)::GetProcAddress(netapi, "NetLocalGroupGetMembers");
3083  p2NetLocalGroupEnum = (pfn4)::GetProcAddress(netapi, "NetLocalGroupEnum");
3084 
3085  if (!p2NetApiBufferFree || !p2NetUserGetInfo ||
3086  !p2NetLocalGroupGetMembers || !p2NetLocalGroupEnum) return kFALSE;
3087 
3088  GetNbGroups();
3089 
3090  fGroups = (struct group *)calloc(fNbGroups, sizeof(struct group));
3091  for(int i=0;i<fNbGroups;i++) {
3092  fGroups[i].gr_mem = (char **)calloc(fNbUsers, sizeof (char*));
3093  }
3094  fPasswords = (struct passwd *)calloc(fNbUsers, sizeof(struct passwd));
3095 
3096  CollectGroups();
3097  ::FreeLibrary(netapi);
3098  }
3100  return kTRUE;
3101 }
3102 
3103 ////////////////////////////////////////////////////////////////////////////////
3104 
3105 Bool_t TWinNTSystem::CountMembers(const char *lpszGroupName)
3106 {
3107  NET_API_STATUS NetStatus = NERR_Success;
3108  LPBYTE Data = NULL;
3109  DWORD Index = 0, ResumeHandle = 0, Total = 0;
3110  LOCALGROUP_MEMBERS_INFO_1 *MemberInfo;
3111  WCHAR wszGroupName[256];
3112  int iRetOp = 0;
3113  DWORD dwLastError = 0;
3114 
3115  iRetOp = MultiByteToWideChar (
3116  (UINT)CP_ACP, // code page
3117  (DWORD)MB_PRECOMPOSED, // character-type options
3118  (LPCSTR)lpszGroupName, // address of string to map
3119  (int)-1, // number of bytes in string
3120  (LPWSTR)wszGroupName, // address of wide-character buffer
3121  (int)sizeof(wszGroupName) ); // size of buffer
3122 
3123  if (iRetOp == 0) {
3124  dwLastError = GetLastError();
3125  if (Data)
3126  p2NetApiBufferFree(Data);
3127  return FALSE;
3128  }
3129 
3130  // The NetLocalGroupGetMembers() API retrieves a list of the members
3131  // of a particular local group.
3132  NetStatus = p2NetLocalGroupGetMembers (NULL, wszGroupName, 1,
3133  &Data, 8192, &Index, &Total, &ResumeHandle );
3134 
3135  if (NetStatus != NERR_Success || Data == NULL) {
3136  dwLastError = GetLastError();
3137 
3138  if (dwLastError == ERROR_ENVVAR_NOT_FOUND) {
3139  // This usually means that the current Group has no members.
3140  // We call NetLocalGroupGetMembers() again.
3141  // This time, we set the level to 0.
3142  // We do this just to confirm that the number of members in
3143  // this group is zero.
3144  NetStatus = p2NetLocalGroupGetMembers ( NULL, wszGroupName, 0,
3145  &Data, 8192, &Index, &Total, &ResumeHandle );
3146  }
3147 
3148  if (Data)
3149  p2NetApiBufferFree(Data);
3150  return FALSE;
3151  }
3152 
3153  fNbUsers += Total;
3154  MemberInfo = (LOCALGROUP_MEMBERS_INFO_1 *)Data;
3155 
3156  if (Data)
3157  p2NetApiBufferFree(Data);
3158 
3159  return TRUE;
3160 }
3161 
3162 ////////////////////////////////////////////////////////////////////////////////
3163 
3165 {
3166  NET_API_STATUS NetStatus = NERR_Success;
3167  LPBYTE Data = NULL;
3168  DWORD Index = 0, ResumeHandle = 0, Total = 0, i;
3169  LOCALGROUP_INFO_0 *GroupInfo;
3170  char szAnsiName[256];
3171  DWORD dwLastError = 0;
3172  int iRetOp = 0;
3173 
3174  NetStatus = p2NetLocalGroupEnum(NULL, 0, &Data, 8192, &Index,
3175  &Total, &ResumeHandle );
3176 
3177  if (NetStatus != NERR_Success || Data == NULL) {
3178  dwLastError = GetLastError();
3179  if (Data)
3180  p2NetApiBufferFree(Data);
3181  return FALSE;
3182  }
3183 
3184  fNbGroups = Total;
3185  GroupInfo = (LOCALGROUP_INFO_0 *)Data;
3186  for (i=0; i < Total; i++) {
3187  // Convert group name from UNICODE to ansi.
3188  iRetOp = WideCharToMultiByte (
3189  (UINT)CP_ACP, // code page
3190  (DWORD)0, // performance and mapping flags
3191  (LPCWSTR)(GroupInfo->lgrpi0_name), // address of wide-char string
3192  (int)-1, // number of characters in string
3193  (LPSTR)szAnsiName, // address of buffer for new string
3194  (int)(sizeof(szAnsiName)), // size of buffer
3195  (LPCSTR)NULL, // address of default for unmappable characters
3196  (LPBOOL)NULL ); // address of flag set when default char used.
3197 
3198  // Now lookup all members of this group and record down their names and
3199  // SIDs into the output file.
3200  CountMembers((LPCTSTR)szAnsiName);
3201 
3202  GroupInfo++;
3203  }
3204 
3205  if (Data)
3206  p2NetApiBufferFree(Data);
3207 
3208  return TRUE;
3209 }
3210 
3211 ////////////////////////////////////////////////////////////////////////////////
3212 ///
3213 /// Take the name and look up a SID so that we can get full
3214 /// domain/user information
3215 ///
3216 
3217 Long_t TWinNTSystem::LookupSID (const char *lpszAccountName, int what,
3218  int &groupIdx, int &memberIdx)
3219 {
3220  BOOL bRetOp = FALSE;
3221  PSID pSid = NULL;
3222  DWORD dwSidSize, dwDomainNameSize;
3223  BYTE bySidBuffer[MAX_SID_SIZE];
3224  char szDomainName[MAX_NAME_STRING];
3225  SID_NAME_USE sidType;
3226  PUCHAR puchar_SubAuthCount = NULL;
3227  SID_IDENTIFIER_AUTHORITY sid_identifier_authority;
3228  PSID_IDENTIFIER_AUTHORITY psid_identifier_authority = NULL;
3229  unsigned char j = 0;
3230  DWORD dwLastError = 0;
3231 
3232  pSid = (PSID)bySidBuffer;
3233  dwSidSize = sizeof(bySidBuffer);
3234  dwDomainNameSize = sizeof(szDomainName);
3235 
3236  bRetOp = LookupAccountName (
3237  (LPCTSTR)NULL, // address of string for system name
3238  (LPCTSTR)lpszAccountName, // address of string for account name
3239  (PSID)pSid, // address of security identifier
3240  (LPDWORD)&dwSidSize, // address of size of security identifier
3241  (LPTSTR)szDomainName, // address of string for referenced domain
3242  (LPDWORD)&dwDomainNameSize,// address of size of domain string
3243  (PSID_NAME_USE)&sidType ); // address of SID-type indicator
3244 
3245  if (bRetOp == FALSE) {
3246  dwLastError = GetLastError();
3247  return -1; // Unable to obtain Account SID.
3248  }
3249 
3250  bRetOp = IsValidSid((PSID)pSid);
3251 
3252  if (bRetOp == FALSE) {
3253  dwLastError = GetLastError();
3254  return -2; // SID returned is invalid.
3255  }
3256 
3257  // Obtain via APIs the identifier authority value.
3258  psid_identifier_authority = GetSidIdentifierAuthority ((PSID)pSid);
3259 
3260  // Make a copy of it.
3261  memcpy (&sid_identifier_authority, psid_identifier_authority,
3262  sizeof(SID_IDENTIFIER_AUTHORITY));
3263 
3264  // Determine how many sub-authority values there are in the current SID.
3265  puchar_SubAuthCount = (PUCHAR)GetSidSubAuthorityCount((PSID)pSid);
3266  // Assign it to a more convenient variable.
3267  j = (unsigned char)(*puchar_SubAuthCount);
3268  // Now obtain all the sub-authority values from the current SID.
3269  DWORD dwSubAuth = 0;
3270  PDWORD pdwSubAuth = NULL;
3271  // Obtain the current sub-authority DWORD (referenced by a pointer)
3272  pdwSubAuth = (PDWORD)GetSidSubAuthority (
3273  (PSID)pSid, // address of security identifier to query
3274  (DWORD)j-1); // index of subauthority to retrieve
3275  dwSubAuth = *pdwSubAuth;
3276  if(what == SID_MEMBER) {
3277  fPasswords[memberIdx].pw_uid = dwSubAuth;
3278  fPasswords[memberIdx].pw_gid = fGroups[groupIdx].gr_gid;
3279  fPasswords[memberIdx].pw_group = strdup(fGroups[groupIdx].gr_name);
3280  }
3281  else if(what == SID_GROUP) {
3282  fGroups[groupIdx].gr_gid = dwSubAuth;
3283  }
3284  return 0;
3285 }
3286 
3287 ////////////////////////////////////////////////////////////////////////////////
3288 ///
3289 
3290 Bool_t TWinNTSystem::CollectMembers(const char *lpszGroupName, int &groupIdx,
3291  int &memberIdx)
3292 {
3293 
3294  NET_API_STATUS NetStatus = NERR_Success;
3295  LPBYTE Data = NULL;
3296  DWORD Index = 0, ResumeHandle = 0, Total = 0, i;
3297  LOCALGROUP_MEMBERS_INFO_1 *MemberInfo;
3298  char szAnsiMemberName[256];
3299  char szFullMemberName[256];
3300  char szMemberHomeDir[256];
3301  WCHAR wszGroupName[256];
3302  int iRetOp = 0;
3303  char act_name[256];
3304  DWORD length = sizeof (act_name);
3305  DWORD dwLastError = 0;
3306  LPUSER_INFO_11 pUI11Buf = NULL;
3307  NET_API_STATUS nStatus;
3308 
3309  iRetOp = MultiByteToWideChar (
3310  (UINT)CP_ACP, // code page
3311  (DWORD)MB_PRECOMPOSED, // character-type options
3312  (LPCSTR)lpszGroupName, // address of string to map
3313  (int)-1, // number of bytes in string
3314  (LPWSTR)wszGroupName, // address of wide-character buffer
3315  (int)sizeof(wszGroupName) ); // size of buffer
3316 
3317  if (iRetOp == 0) {
3318  dwLastError = GetLastError();
3319  if (Data)
3320  p2NetApiBufferFree(Data);
3321  return FALSE;
3322  }
3323 
3324  GetUserName (act_name, &length);
3325 
3326  // The NetLocalGroupGetMembers() API retrieves a list of the members
3327  // of a particular local group.
3328  NetStatus = p2NetLocalGroupGetMembers (NULL, wszGroupName, 1,
3329  &Data, 8192, &Index, &Total, &ResumeHandle );
3330 
3331  if (NetStatus != NERR_Success || Data == NULL) {
3332  dwLastError = GetLastError();
3333 
3334  if (dwLastError == ERROR_ENVVAR_NOT_FOUND) {
3335  // This usually means that the current Group has no members.
3336  // We call NetLocalGroupGetMembers() again.
3337  // This time, we set the level to 0.
3338  // We do this just to confirm that the number of members in
3339  // this group is zero.
3340  NetStatus = p2NetLocalGroupGetMembers ( NULL, wszGroupName, 0,
3341  &Data, 8192, &Index, &Total, &ResumeHandle );
3342  }
3343 
3344  if (Data)
3345  p2NetApiBufferFree(Data);
3346  return FALSE;
3347  }
3348 
3349  MemberInfo = (LOCALGROUP_MEMBERS_INFO_1 *)Data;
3350  for (i=0; i < Total; i++) {
3351  iRetOp = WideCharToMultiByte (
3352  (UINT)CP_ACP, // code page
3353  (DWORD)0, // performance and mapping flags
3354  (LPCWSTR)(MemberInfo->lgrmi1_name), // address of wide-char string
3355  (int)-1, // number of characters in string
3356  (LPSTR)szAnsiMemberName, // address of buffer for new string
3357  (int)(sizeof(szAnsiMemberName)), // size of buffer
3358  (LPCSTR)NULL, // address of default for unmappable characters
3359  (LPBOOL)NULL ); // address of flag set when default char used.
3360 
3361  if (iRetOp == 0) {
3362  dwLastError = GetLastError();
3363  }
3364 
3365  fPasswords[memberIdx].pw_name = strdup(szAnsiMemberName);
3366  fPasswords[memberIdx].pw_passwd = strdup("");
3367  fGroups[groupIdx].gr_mem[i] = strdup(szAnsiMemberName);
3368 
3369  if(fActUser == -1 && !stricmp(fPasswords[memberIdx].pw_name,act_name))
3370  fActUser = memberIdx;
3371 
3372 
3373  TCHAR szUserName[255]=TEXT("");
3374  MultiByteToWideChar(CP_ACP, 0, szAnsiMemberName, -1, (LPWSTR)szUserName, 255);
3375  //
3376  // Call the NetUserGetInfo function; specify level 10.
3377  //
3378  nStatus = p2NetUserGetInfo(NULL, (LPCWSTR)szUserName, 11, (LPBYTE *)&pUI11Buf);
3379  //
3380  // If the call succeeds, print the user information.
3381  //
3382  if (nStatus == NERR_Success) {
3383  if (pUI11Buf != NULL) {
3384  wsprintf(szFullMemberName,"%S",pUI11Buf->usri11_full_name);
3385  fPasswords[memberIdx].pw_gecos = strdup(szFullMemberName);
3386  wsprintf(szMemberHomeDir,"%S",pUI11Buf->usri11_home_dir);
3387  fPasswords[memberIdx].pw_dir = strdup(szMemberHomeDir);
3388  }
3389  }
3390  if((fPasswords[memberIdx].pw_gecos == NULL) || (strlen(fPasswords[memberIdx].pw_gecos) == 0))
3391  fPasswords[memberIdx].pw_gecos = strdup(fPasswords[memberIdx].pw_name);
3392  if((fPasswords[memberIdx].pw_dir == NULL) || (strlen(fPasswords[memberIdx].pw_dir) == 0))
3393  fPasswords[memberIdx].pw_dir = strdup("c:\\");
3394  //
3395  // Free the allocated memory.
3396  //
3397  if (pUI11Buf != NULL) {
3398  p2NetApiBufferFree(pUI11Buf);
3399  pUI11Buf = NULL;
3400  }
3401 
3402  /* Ensure SHELL is defined. */
3403  if (getenv("SHELL") == NULL)
3404  putenv ((GetVersion () & 0x80000000) ? "SHELL=command" : "SHELL=cmd");
3405 
3406  /* Set dir and shell from environment variables. */
3407  fPasswords[memberIdx].pw_shell = getenv("SHELL");
3408 
3409  // Find out the SID of the Member.
3410  LookupSID ((LPCTSTR)szAnsiMemberName, SID_MEMBER, groupIdx, memberIdx);
3411  memberIdx++;
3412  MemberInfo++;
3413  }
3414  if(fActUser == -1) fActUser = 0;
3415 
3416  if (Data)
3417  p2NetApiBufferFree(Data);
3418 
3419  return TRUE;
3420 }
3421 
3422 ////////////////////////////////////////////////////////////////////////////////
3423 ///
3424 
3426 {
3427  NET_API_STATUS NetStatus = NERR_Success;
3428  LPBYTE Data = NULL;
3429  DWORD Index = 0, ResumeHandle = 0, Total = 0, i;
3430  LOCALGROUP_INFO_0 *GroupInfo;
3431  char szAnsiName[256];
3432  DWORD dwLastError = 0;
3433  int iRetOp = 0, iGroupIdx = 0, iMemberIdx = 0;
3434 
3435  NetStatus = p2NetLocalGroupEnum(NULL, 0, &Data, 8192, &Index,
3436  &Total, &ResumeHandle );
3437 
3438  if (NetStatus != NERR_Success || Data == NULL) {
3439  dwLastError = GetLastError();
3440  if (Data)
3441  p2NetApiBufferFree(Data);
3442  return FALSE;
3443  }
3444 
3445  GroupInfo = (LOCALGROUP_INFO_0 *)Data;
3446  for (i=0; i < Total; i++) {
3447  // Convert group name from UNICODE to ansi.
3448  iRetOp = WideCharToMultiByte (
3449  (UINT)CP_ACP, // code page
3450  (DWORD)0, // performance and mapping flags
3451  (LPCWSTR)(GroupInfo->lgrpi0_name), // address of wide-char string
3452  (int)-1, // number of characters in string
3453  (LPSTR)szAnsiName, // address of buffer for new string
3454  (int)(sizeof(szAnsiName)), // size of buffer
3455  (LPCSTR)NULL, // address of default for unmappable characters
3456  (LPBOOL)NULL ); // address of flag set when default char used.
3457 
3458  fGroups[iGroupIdx].gr_name = strdup(szAnsiName);
3459  fGroups[iGroupIdx].gr_passwd = strdup("");
3460 
3461  // Find out the SID of the Group.
3462  LookupSID ((LPCTSTR)szAnsiName, SID_GROUP, iGroupIdx, iMemberIdx);
3463  // Now lookup all members of this group and record down their names and
3464  // SIDs into the output file.
3465  CollectMembers((LPCTSTR)szAnsiName, iGroupIdx, iMemberIdx);
3466 
3467  iGroupIdx++;
3468  GroupInfo++;
3469  }
3470 
3471  if (Data)
3472  p2NetApiBufferFree(Data);
3473 
3474  return TRUE;
3475 }
3476 
3477 ////////////////////////////////////////////////////////////////////////////////
3478 /// Returns the user's id. If user = 0, returns current user's id.
3479 
3480 Int_t TWinNTSystem::GetUid(const char *user)
3481 {
3482  if(!fGroupsInitDone)
3483  InitUsersGroups();
3484 
3485  // Net* API functions not allowed or OS not Windows NT/2000/XP
3486  if ((!gEnv->GetValue("WinNT.UseNetAPI", 0)) || (::GetVersion() >= 0x80000000)) {
3487  int uid;
3488  char name[256];
3489  DWORD length = sizeof (name);
3490  if (::GetUserName (name, &length)) {
3491  if (stricmp ("administrator", name) == 0)
3492  uid = 0;
3493  else
3494  uid = 123;
3495  }
3496  else {
3497  uid = 123;
3498  }
3499  return uid;
3500  }
3501  if (!user || !user[0])
3502  return fPasswords[fActUser].pw_uid;
3503  else {
3504  struct passwd *pwd = 0;
3505  for(int i=0;i<fNbUsers;i++) {
3506  if (!stricmp (user, fPasswords[i].pw_name)) {
3507  pwd = &fPasswords[i];
3508  break;
3509  }
3510  }
3511  if (pwd)
3512  return pwd->pw_uid;
3513  }
3514  return 0;
3515 }
3516 
3517 ////////////////////////////////////////////////////////////////////////////////
3518 /// Returns the effective user id. The effective id corresponds to the
3519 /// set id bit on the file being executed.
3520 
3522 {
3523  if(!fGroupsInitDone)
3524  InitUsersGroups();
3525 
3526  // Net* API functions not allowed or OS not Windows NT/2000/XP
3527  if ((!gEnv->GetValue("WinNT.UseNetAPI", 0)) || (::GetVersion() >= 0x80000000)) {
3528  int uid;
3529  char name[256];
3530  DWORD length = sizeof (name);
3531  if (::GetUserName (name, &length)) {
3532  if (stricmp ("administrator", name) == 0)
3533  uid = 0;
3534  else
3535  uid = 123;
3536  }
3537  else {
3538  uid = 123;
3539  }
3540  return uid;
3541  }
3542  return fPasswords[fActUser].pw_uid;
3543 }
3544 
3545 ////////////////////////////////////////////////////////////////////////////////
3546 /// Returns the group's id. If group = 0, returns current user's group.
3547 
3549 {
3550  if(!fGroupsInitDone)
3551  InitUsersGroups();
3552 
3553  // Net* API functions not allowed or OS not Windows NT/2000/XP
3554  if ((!gEnv->GetValue("WinNT.UseNetAPI", 0)) || (::GetVersion() >= 0x80000000)) {
3555  int gid;
3556  char name[256];
3557  DWORD length = sizeof (name);
3558  if (::GetUserName (name, &length)) {
3559  if (stricmp ("administrator", name) == 0)
3560  gid = 0;
3561  else
3562  gid = 123;
3563  }
3564  else {
3565  gid = 123;
3566  }
3567  return gid;
3568  }
3569  if (!group || !group[0])
3570  return fPasswords[fActUser].pw_gid;
3571  else {
3572  struct group *grp = 0;
3573  for(int i=0;i<fNbGroups;i++) {
3574  if (!stricmp (group, fGroups[i].gr_name)) {
3575  grp = &fGroups[i];
3576  break;
3577  }
3578  }
3579  if (grp)
3580  return grp->gr_gid;
3581  }
3582  return 0;
3583 }
3584 
3585 ////////////////////////////////////////////////////////////////////////////////
3586 /// Returns the effective group id. The effective group id corresponds
3587 /// to the set id bit on the file being executed.
3588 
3590 {
3591  if(!fGroupsInitDone)
3592  InitUsersGroups();
3593 
3594  // Net* API functions not allowed or OS not Windows NT/2000/XP
3595  if ((!gEnv->GetValue("WinNT.UseNetAPI", 0)) || (::GetVersion() >= 0x80000000)) {
3596  int gid;
3597  char name[256];
3598  DWORD length = sizeof (name);
3599  if (::GetUserName (name, &length)) {
3600  if (stricmp ("administrator", name) == 0)
3601  gid = 0;
3602  else
3603  gid = 123;
3604  }
3605  else {
3606  gid = 123;
3607  }
3608  return gid;
3609  }
3610  return fPasswords[fActUser].pw_gid;
3611 }
3612 
3613 ////////////////////////////////////////////////////////////////////////////////
3614 /// Returns all user info in the UserGroup_t structure. The returned
3615 /// structure must be deleted by the user. In case of error 0 is returned.
3616 
3618 {
3619  if(!fGroupsInitDone)
3620  InitUsersGroups();
3621 
3622  // Net* API functions not allowed or OS not Windows NT/2000/XP
3623  if ((!gEnv->GetValue("WinNT.UseNetAPI", 0)) || (::GetVersion() >= 0x80000000)) {
3624  char name[256];
3625  DWORD length = sizeof (name);
3626  UserGroup_t *ug = new UserGroup_t;
3627  if (::GetUserName (name, &length)) {
3628  ug->fUser = name;
3629  if (stricmp ("administrator", name) == 0) {
3630  ug->fUid = 0;
3631  ug->fGroup = "administrators";
3632  }
3633  else {
3634  ug->fUid = 123;
3635  ug->fGroup = "users";
3636  }
3637  ug->fGid = ug->fUid;
3638  }
3639  else {
3640  ug->fUser = "unknown";
3641  ug->fGroup = "unknown";
3642  ug->fUid = ug->fGid = 123;
3643  }
3644  ug->fPasswd = "";
3645  ug->fRealName = ug->fUser;
3646  ug->fShell = "command";
3647  return ug;
3648  }
3649  struct passwd *pwd = 0;
3650  if (uid == 0)
3651  pwd = &fPasswords[fActUser];
3652  else {
3653  for (int i = 0; i < fNbUsers; i++) {
3654  if (uid == fPasswords[i].pw_uid) {
3655  pwd = &fPasswords[i];
3656  break;
3657  }
3658  }
3659  }
3660  if (pwd) {
3661  UserGroup_t *ug = new UserGroup_t;
3662  ug->fUid = pwd->pw_uid;
3663  ug->fGid = pwd->pw_gid;
3664  ug->fUser = pwd->pw_name;
3665  ug->fPasswd = pwd->pw_passwd;
3666  ug->fRealName = pwd->pw_gecos;
3667  ug->fShell = pwd->pw_shell;
3668  ug->fGroup = pwd->pw_group;
3669  return ug;
3670  }
3671  return 0;
3672 }
3673 
3674 ////////////////////////////////////////////////////////////////////////////////
3675 /// Returns all user info in the UserGroup_t structure. If user = 0, returns
3676 /// current user's id info. The returned structure must be deleted by the
3677 /// user. In case of error 0 is returned.
3678 
3680 {
3681  return GetUserInfo(GetUid(user));
3682 }
3683 
3684 ////////////////////////////////////////////////////////////////////////////////
3685 /// Returns all group info in the UserGroup_t structure. The only active
3686 /// fields in the UserGroup_t structure for this call are:
3687 /// fGid and fGroup
3688 /// The returned structure must be deleted by the user. In case of
3689 /// error 0 is returned.
3690 
3692 {
3693  if(!fGroupsInitDone)
3694  InitUsersGroups();
3695 
3696  // Net* API functions not allowed or OS not Windows NT/2000/XP
3697  if ((!gEnv->GetValue("WinNT.UseNetAPI", 0)) || (::GetVersion() >= 0x80000000)) {
3698  char name[256];
3699  DWORD length = sizeof (name);
3700  UserGroup_t *gr = new UserGroup_t;
3701  if (::GetUserName (name, &length)) {
3702  if (stricmp ("administrator", name) == 0) {
3703  gr->fGroup = "administrators";
3704  gr->fGid = 0;
3705  }
3706  else {
3707  gr->fGroup = "users";
3708  gr->fGid = 123;
3709  }
3710  }
3711  else {
3712  gr->fGroup = "unknown";
3713  gr->fGid = 123;
3714  }
3715  gr->fUid = 0;
3716  return gr;
3717  }
3718  struct group *grp = 0;
3719  for(int i=0;i<fNbGroups;i++) {
3720  if (gid == fGroups[i].gr_gid) {
3721  grp = &fGroups[i];
3722  break;
3723  }
3724  }
3725  if (grp) {
3726  UserGroup_t *gr = new UserGroup_t;
3727  gr->fUid = 0;
3728  gr->fGid = grp->gr_gid;
3729  gr->fGroup = grp->gr_name;
3730  return gr;
3731  }
3732  return 0;
3733 
3734 }
3735 
3736 ////////////////////////////////////////////////////////////////////////////////
3737 /// Returns all group info in the UserGroup_t structure. The only active
3738 /// fields in the UserGroup_t structure for this call are:
3739 /// fGid and fGroup
3740 /// If group = 0, returns current user's group. The returned structure
3741 /// must be deleted by the user. In case of error 0 is returned.
3742 
3744 {
3745  return GetGroupInfo(GetGid(group));
3746 }
3747 
3748 //---- environment manipulation ------------------------------------------------
3749 
3750 ////////////////////////////////////////////////////////////////////////////////
3751 /// Set environment variable.
3752 
3753 void TWinNTSystem::Setenv(const char *name, const char *value)
3754 {
3755  ::_putenv(TString::Format("%s=%s", name, value));
3756 }
3757 
3758 ////////////////////////////////////////////////////////////////////////////////
3759 /// Get environment variable.
3760 
3761 const char *TWinNTSystem::Getenv(const char *name)
3762 {
3763  const char *env = ::getenv(name);
3764  if (!env) {
3765  if (::_stricmp(name,"home") == 0 ) {
3766  env = HomeDirectory();
3767  } else if (::_stricmp(name, "rootsys") == 0 ) {
3768  env = gRootDir;
3769  }
3770  }
3771  return env;
3772 }
3773 
3774 //---- Processes ---------------------------------------------------------------
3775 
3776 ////////////////////////////////////////////////////////////////////////////////
3777 /// Execute a command.
3778 
3779 int TWinNTSystem::Exec(const char *shellcmd)
3780 {
3781  return ::system(shellcmd);
3782 }
3783 
3784 ////////////////////////////////////////////////////////////////////////////////
3785 /// Open a pipe.
3786 
3787 FILE *TWinNTSystem::OpenPipe(const char *command, const char *mode)
3788 {
3789  return ::_popen(command, mode);
3790 }
3791 
3792 ////////////////////////////////////////////////////////////////////////////////
3793 /// Close the pipe.
3794 
3796 {
3797  return ::_pclose(pipe);
3798 }
3799 
3800 ////////////////////////////////////////////////////////////////////////////////
3801 /// Get process id.
3802 
3804 {
3805  return ::getpid();
3806 }
3807 
3808 ////////////////////////////////////////////////////////////////////////////////
3809 /// Get current process handle
3810 
3812 {
3813  return fhProcess;
3814 }
3815 
3816 ////////////////////////////////////////////////////////////////////////////////
3817 /// Exit the application.
3818 
3819 void TWinNTSystem::Exit(int code, Bool_t mode)
3820 {
3821  // Insures that the files and sockets are closed before any library is unloaded
3822  // and before emptying CINT.
3823  if (gROOT) {
3824  gROOT->CloseFiles();
3825  if (gROOT->GetListOfBrowsers()) {
3826  // GetListOfBrowsers()->Delete() creates problems when a browser is
3827  // created on the stack, calling CloseWindow() solves the problem
3828  //gROOT->GetListOfBrowsers()->Delete();
3829  TBrowser *b;
3830  TIter next(gROOT->GetListOfBrowsers());
3831  while ((b = (TBrowser*) next()))
3832  gROOT->ProcessLine(TString::Format("((TBrowser*)0x%lx)->GetBrowserImp()->GetMainFrame()->CloseWindow();",
3833  (ULong_t)b));
3834  }
3835  }
3836  if (gInterpreter) {
3837  gInterpreter->ResetGlobals();
3838  }
3839  gVirtualX->CloseDisplay();
3840 
3841  if (mode) {
3842  ::exit(code);
3843  } else {
3844  ::_exit(code);
3845  }
3846 }
3847 
3848 ////////////////////////////////////////////////////////////////////////////////
3849 /// Abort the application.
3850 
3852 {
3853  ::abort();
3854 }
3855 
3856 //---- Standard output redirection ---------------------------------------------
3857 
3858 ////////////////////////////////////////////////////////////////////////////////
3859 /// Redirect standard output (stdout, stderr) to the specified file.
3860 /// If the file argument is 0 the output is set again to stderr, stdout.
3861 /// The second argument specifies whether the output should be added to the
3862 /// file ("a", default) or the file be truncated before ("w").
3863 /// This function saves internally the current state into a static structure.
3864 /// The call can be made reentrant by specifying the opaque structure pointed
3865 /// by 'h', which is filled with the relevant information. The handle 'h'
3866 /// obtained on the first call must then be used in any subsequent call,
3867 /// included ShowOutput, to display the redirected output.
3868 /// Returns 0 on success, -1 in case of error.
3869 
3870 Int_t TWinNTSystem::RedirectOutput(const char *file, const char *mode,
3872 {
3873  FILE *fout, *ferr;
3874  static int fd1=0, fd2=0;
3875  static fpos_t pos1=0, pos2=0;
3876  // Instance to be used if the caller does not passes 'h'
3877  static RedirectHandle_t loch;
3878  Int_t rc = 0;
3879 
3880  // Which handle to use ?
3881  RedirectHandle_t *xh = (h) ? h : &loch;
3882 
3883  if (file) {
3884  // Make sure mode makes sense; default "a"
3885  const char *m = (mode[0] == 'a' || mode[0] == 'w') ? mode : "a";
3886 
3887  // Current file size
3888  xh->fReadOffSet = 0;
3889  if (m[0] == 'a') {
3890  // If the file exists, save the current size
3891  FileStat_t st;
3892  if (!gSystem->GetPathInfo(file, st))
3893  xh->fReadOffSet = (st.fSize > 0) ? st.fSize : xh->fReadOffSet;
3894  }
3895  xh->fFile = file;
3896 
3897  fflush(stdout);
3898  fgetpos(stdout, &pos1);
3899  fd1 = _dup(fileno(stdout));
3900  // redirect stdout & stderr
3901  if ((fout = freopen(file, m, stdout)) == 0) {
3902  SysError("RedirectOutput", "could not freopen stdout");
3903  if (fd1 > 0) {
3904  _dup2(fd1, fileno(stdout));
3905  close(fd1);
3906  }
3907  clearerr(stdout);
3908  fsetpos(stdout, &pos1);
3909  fd1 = fd2 = 0;
3910  return -1;
3911  }
3912  fflush(stderr);
3913  fgetpos(stderr, &pos2);
3914  fd2 = _dup(fileno(stderr));
3915  if ((ferr = freopen(file, m, stderr)) == 0) {
3916  SysError("RedirectOutput", "could not freopen stderr");
3917  if (fd1 > 0) {
3918  _dup2(fd1, fileno(stdout));
3919  close(fd1);
3920  }
3921  clearerr(stdout);
3922  fsetpos(stdout, &pos1);
3923  if (fd2 > 0) {
3924  _dup2(fd2, fileno(stderr));
3925  close(fd2);
3926  }
3927  clearerr(stderr);
3928  fsetpos(stderr, &pos2);
3929  fd1 = fd2 = 0;
3930  return -1;
3931  }
3932  if (m[0] == 'a') {
3933  fseek(fout, 0, SEEK_END);
3934  fseek(ferr, 0, SEEK_END);
3935  }
3936  } else {
3937  // Restore stdout & stderr
3938  fflush(stdout);
3939  if (fd1) {
3940  if (fd1 > 0) {
3941  if (_dup2(fd1, fileno(stdout))) {
3942  SysError("RedirectOutput", "could not restore stdout");
3943  rc = -1;
3944  }
3945  close(fd1);
3946  }
3947  clearerr(stdout);
3948  fsetpos(stdout, &pos1);
3949  fd1 = 0;
3950  }
3951 
3952  fflush(stderr);
3953  if (fd2) {
3954  if (fd2 > 0) {
3955  if (_dup2(fd2, fileno(stderr))) {
3956  SysError("RedirectOutput", "could not restore stderr");
3957  rc = -1;
3958  }
3959  close(fd2);
3960  }
3961  clearerr(stderr);
3962  fsetpos(stderr, &pos2);
3963  fd2 = 0;
3964  }
3965 
3966  // Reset the static instance, if using that
3967  if (xh == &loch)
3968  xh->Reset();
3969  }
3970  return rc;
3971 }
3972 
3973 //---- dynamic loading and linking ---------------------------------------------
3974 
3975 ////////////////////////////////////////////////////////////////////////////////
3976 /// Add a new directory to the dynamic path.
3977 
3979 {
3980  if (dir) {
3981  TString oldpath = DynamicPath(0, kFALSE);
3982  oldpath.Append(";");
3983  oldpath.Append(dir);
3984  DynamicPath(oldpath);
3985  }
3986 }
3987 
3988 ////////////////////////////////////////////////////////////////////////////////
3989 /// Return the dynamic path (used to find shared libraries).
3990 
3992 {
3993  return DynamicPath(0, kFALSE);
3994 }
3995 
3996 ////////////////////////////////////////////////////////////////////////////////
3997 /// Set the dynamic path to a new value.
3998 /// If the value of 'path' is zero, the dynamic path is reset to its
3999 /// default value.
4000 
4001 void TWinNTSystem::SetDynamicPath(const char *path)
4002 {
4003  if (!path)
4004  DynamicPath(0, kTRUE);
4005  else
4006  DynamicPath(path);
4007 }
4008 
4009 ////////////////////////////////////////////////////////////////////////////////
4010 /// Returns and updates sLib to the path of a dynamic library
4011 /// (searches for library in the dynamic library search path).
4012 /// If no file name extension is provided it tries .DLL.
4013 
4015 {
4016  int len = sLib.Length();
4017  if (len > 4 && (!stricmp(sLib.Data()+len-4, ".dll"))) {
4018  if (gSystem->FindFile(GetDynamicPath(), sLib, kReadPermission))
4019  return sLib;
4020  } else {
4021  TString sLibDll(sLib);
4022  sLibDll += ".dll";
4023  if (gSystem->FindFile(GetDynamicPath(), sLibDll, kReadPermission)) {
4024  sLibDll.Swap(sLib);
4025  return sLib;
4026  }
4027  }
4028 
4029  if (!quiet) {
4030  Error("DynamicPathName",
4031  "%s does not exist in %s,\nor has wrong file extension (.dll)",
4032  sLib.Data(), GetDynamicPath());
4033  }
4034  return 0;
4035 }
4036 
4037 ////////////////////////////////////////////////////////////////////////////////
4038 /// Load a shared library. Returns 0 on successful loading, 1 in
4039 /// case lib was already loaded and -1 in case lib does not exist
4040 /// or in case of error.
4041 
4042 int TWinNTSystem::Load(const char *module, const char *entry, Bool_t system)
4043 {
4044  return TSystem::Load(module, entry, system);
4045 }
4046 
4047 /* nonstandard extension used : zero-sized array in struct/union */
4048 #pragma warning(push)
4049 #pragma warning(disable:4200)
4050 ////////////////////////////////////////////////////////////////////////////////
4051 /// Get list of shared libraries loaded at the start of the executable.
4052 /// Returns 0 in case list cannot be obtained or in case of error.
4053 
4055 {
4056  char winDrive[256];
4057  char winDir[256];
4058  char winName[256];
4059  char winExt[256];
4060 
4061  if (!gApplication) return 0;
4062 
4063  static Bool_t once = kFALSE;
4064  static TString linkedLibs;
4065 
4066  if (!linkedLibs.IsNull())
4067  return linkedLibs;
4068 
4069  if (once)
4070  return 0;
4071 
4072  char *exe = gSystem->Which(Getenv("PATH"), gApplication->Argv(0),
4074  if (!exe) {
4075  once = kTRUE;
4076  return 0;
4077  }
4078 
4079  HANDLE hFile, hMapping;
4080  void *basepointer;
4081 
4082  if((hFile = CreateFile(exe,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_FLAG_SEQUENTIAL_SCAN,0))==INVALID_HANDLE_VALUE) {
4083  delete [] exe;
4084  return 0;
4085  }
4086  if(!(hMapping = CreateFileMapping(hFile,0,PAGE_READONLY|SEC_COMMIT,0,0,0))) {
4087  CloseHandle(hFile);
4088  delete [] exe;
4089  return 0;
4090  }
4091  if(!(basepointer = MapViewOfFile(hMapping,FILE_MAP_READ,0,0,0))) {
4092  CloseHandle(hMapping);
4093  CloseHandle(hFile);
4094  delete [] exe;
4095  return 0;
4096  }
4097 
4098  int sect;
4099  IMAGE_DOS_HEADER *dos_head = (IMAGE_DOS_HEADER *)basepointer;
4100  struct header {
4101  DWORD signature;
4102  IMAGE_FILE_HEADER _head;
4103  IMAGE_OPTIONAL_HEADER opt_head;
4104  IMAGE_SECTION_HEADER section_header[]; // actual number in NumberOfSections
4105  };
4106  struct header *pheader;
4107  const IMAGE_SECTION_HEADER * section_header;
4108 
4109  if(dos_head->e_magic!='ZM') {
4110  delete [] exe;
4111  return 0;
4112  } // verify DOS-EXE-Header
4113  // after end of DOS-EXE-Header: offset to PE-Header
4114  pheader = (struct header *)((char*)dos_head + dos_head->e_lfanew);
4115 
4116  if(IsBadReadPtr(pheader,sizeof(struct header))) { // start of PE-Header
4117  delete [] exe;
4118  return 0;
4119  }
4120  if(pheader->signature!=IMAGE_NT_SIGNATURE) { // verify PE format
4121  switch((unsigned short)pheader->signature) {
4122  case IMAGE_DOS_SIGNATURE:
4123  delete [] exe;
4124  return 0;
4125  case IMAGE_OS2_SIGNATURE:
4126  delete [] exe;
4127  return 0;
4128  case IMAGE_OS2_SIGNATURE_LE:
4129  delete [] exe;
4130  return 0;
4131  default: // unknown signature
4132  delete [] exe;
4133  return 0;
4134  }
4135  }
4136 #define isin(address,start,length) ((address)>=(start) && (address)<(start)+(length))
4137  TString odump;
4138  // walk through sections
4139  for(sect=0,section_header=pheader->section_header;
4140  sect<pheader->_head.NumberOfSections;sect++,section_header++) {
4141  int directory;
4142  const void * const section_data =
4143  (char*)basepointer + section_header->PointerToRawData;
4144  for(directory=0;directory<IMAGE_NUMBEROF_DIRECTORY_ENTRIES;directory++) {
4145  if(isin(pheader->opt_head.DataDirectory[directory].VirtualAddress,
4146  section_header->VirtualAddress,
4147  section_header->SizeOfRawData)) {
4148  const IMAGE_IMPORT_DESCRIPTOR *stuff_start =
4149  (IMAGE_IMPORT_DESCRIPTOR *)((char*)section_data +
4150  (pheader->opt_head.DataDirectory[directory].VirtualAddress -
4151  section_header->VirtualAddress));
4152  // (virtual address of stuff - virtual address of section) =
4153  // offset of stuff in section
4154  const unsigned stuff_length =
4155  pheader->opt_head.DataDirectory[directory].Size;
4156  if(directory == IMAGE_DIRECTORY_ENTRY_IMPORT) {
4157  while(!IsBadReadPtr(stuff_start,sizeof(*stuff_start)) &&
4158  stuff_start->Name) {
4159  TString dll = (char*)section_data +
4160  ((DWORD)(stuff_start->Name)) -
4161  section_header->VirtualAddress;
4162  if (dll.EndsWith(".dll")) {
4163  char *dllPath = DynamicPathName(dll, kTRUE);
4164  if (dllPath) {
4165  char *winPath = getenv("windir");
4166  _splitpath(winPath,winDrive,winDir,winName,winExt);
4167  if(!strstr(dllPath, winDir)) {
4168  if (!linkedLibs.IsNull())
4169  linkedLibs += " ";
4170  linkedLibs += dllPath;
4171  }
4172  }
4173  delete [] dllPath;
4174  }
4175  stuff_start++;
4176  }
4177  }
4178  }
4179  }
4180  }
4181 
4182  UnmapViewOfFile(basepointer);
4183  CloseHandle(hMapping);
4184  CloseHandle(hFile);
4185 
4186  delete [] exe;
4187 
4188  once = kTRUE;
4189 
4190  if (linkedLibs.IsNull())
4191  return 0;
4192 
4193  return linkedLibs;
4194 }
4195 #pragma warning(pop)
4196 
4197 ////////////////////////////////////////////////////////////////////////////////
4198 /// Return a space separated list of loaded shared libraries.
4199 /// This list is of a format suitable for a linker, i.e it may contain
4200 /// -Lpathname and/or -lNameOfLib.
4201 /// Option can be any of:
4202 /// S: shared libraries loaded at the start of the executable, because
4203 /// they were specified on the link line.
4204 /// D: shared libraries dynamically loaded after the start of the program.
4205 /// L: list the .LIB rather than the .DLL (this is intended for linking)
4206 /// [This options is not the default]
4207 
4208 const char *TWinNTSystem::GetLibraries(const char *regexp, const char *options,
4209  Bool_t isRegexp)
4210 {
4211  TString libs(TSystem::GetLibraries(regexp, options, isRegexp));
4212  TString ntlibs;
4213  TString opt = options;
4214 
4215  if ( (opt.First('L')!=kNPOS) ) {
4216  TRegexp separator("[^ \\t\\s]+");
4217  TRegexp user_dll("\\.dll$");
4218  TRegexp user_lib("\\.lib$");
4219  FileStat_t sbuf;
4220  TString s;
4221  Ssiz_t start, index, end;
4222  start = index = end = 0;
4223 
4224  while ((start < libs.Length()) && (index != kNPOS)) {
4225  index = libs.Index(separator, &end, start);
4226  if (index >= 0) {
4227  // Change .dll into .lib and remove the
4228  // path info if it not accessible.
4229  s = libs(index, end);
4230  if (s.Index(user_dll) != kNPOS) {
4231  s.ReplaceAll(".dll",".lib");
4232  if ( GetPathInfo( s, sbuf ) != 0 ) {
4233  s.Replace( 0, s.Last('/')+1, 0, 0);
4234  s.Replace( 0, s.Last('\\')+1, 0, 0);
4235  }
4236  } else if (s.Index(user_lib) != kNPOS) {
4237  if ( GetPathInfo( s, sbuf ) != 0 ) {
4238  s.Replace( 0, s.Last('/')+1, 0, 0);
4239  s.Replace( 0, s.Last('\\')+1, 0, 0);
4240  }
4241  }
4242  if (!ntlibs.IsNull()) ntlibs.Append(" ");
4243  ntlibs.Append(s);
4244  }
4245  start += end+1;
4246  }
4247  } else {
4248  ntlibs = libs;
4249  }
4250 
4251  fListLibs = ntlibs;
4252  fListLibs.ReplaceAll("/","\\");
4253  return fListLibs;
4254 }
4255 
4256 //---- Time & Date -------------------------------------------------------------
4257 
4258 ////////////////////////////////////////////////////////////////////////////////
4259 /// Add timer to list of system timers.
4260 
4262 {
4263  TSystem::AddTimer(ti);
4264 }
4265 
4266 ////////////////////////////////////////////////////////////////////////////////
4267 /// Remove timer from list of system timers.
4268 
4270 {
4271  if (!ti) return 0;
4272 
4273  TTimer *t = TSystem::RemoveTimer(ti);
4274  return t;
4275 }
4276 
4277 ////////////////////////////////////////////////////////////////////////////////
4278 /// Special Thread to check asynchronous timers.
4279 
4281 {
4282  while (1) {
4283  if (!fInsideNotify)
4286  }
4287 }
4288 
4289 ////////////////////////////////////////////////////////////////////////////////
4290 /// Handle and dispatch timers. If mode = kTRUE dispatch synchronous
4291 /// timers else a-synchronous timers.
4292 
4294 {
4295  if (!fTimers) return kFALSE;
4296 
4297  fInsideNotify = kTRUE;
4298 
4300  TTimer *t;
4301  Bool_t timedout = kFALSE;
4302 
4303  while ((t = (TTimer *) it.Next())) {
4304  // NB: the timer resolution is added in TTimer::CheckTimer()
4305  TTime now = Now();
4306  if (mode && t->IsSync()) {
4307  if (t->CheckTimer(now)) {
4308  timedout = kTRUE;
4309  }
4310  } else if (!mode && t->IsAsync()) {
4311  if (t->CheckTimer(now)) {
4312  timedout = kTRUE;
4313  }
4314  }
4315  }
4317 
4318  return timedout;
4319 }
4320 
4321 const Double_t gTicks = 1.0e-7;
4322 ////////////////////////////////////////////////////////////////////////////////
4323 ///
4324 
4326 {
4327  union {
4328  FILETIME ftFileTime;
4329  __int64 ftInt64;
4330  } ftRealTime; // time the process has spent in kernel mode
4331 
4332  ::GetSystemTimeAsFileTime(&ftRealTime.ftFileTime);
4333  return (Double_t)ftRealTime.ftInt64 * gTicks;
4334 }
4335 
4336 ////////////////////////////////////////////////////////////////////////////////
4337 ///
4338 
4340 {
4341  OSVERSIONINFO OsVersionInfo;
4342 
4343 //*-* Value Platform
4344 //*-* ----------------------------------------------------
4345 //*-* VER_PLATFORM_WIN32s Win32s on Windows 3.1
4346 //*-* VER_PLATFORM_WIN32_WINDOWS Win32 on Windows 95
4347 //*-* VER_PLATFORM_WIN32_NT Windows NT
4348 //*-*
4349 
4350  OsVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
4351  GetVersionEx(&OsVersionInfo);
4352  if (OsVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) {
4353  DWORD ret;
4354  FILETIME ftCreate, // when the process was created
4355  ftExit; // when the process exited
4356 
4357  union {
4358  FILETIME ftFileTime;
4359  __int64 ftInt64;
4360  } ftKernel; // time the process has spent in kernel mode
4361 
4362  union {
4363  FILETIME ftFileTime;
4364  __int64 ftInt64;
4365  } ftUser; // time the process has spent in user mode
4366 
4367  HANDLE hThread = GetCurrentThread();
4368  ret = GetThreadTimes (hThread, &ftCreate, &ftExit,
4369  &ftKernel.ftFileTime,
4370  &ftUser.ftFileTime);
4371  if (ret != TRUE){
4372  ret = ::GetLastError();
4373  ::Error("GetCPUTime", " Error on GetProcessTimes 0x%lx", (int)ret);
4374  }
4375 
4376  // Process times are returned in a 64-bit structure, as the number of
4377  // 100 nanosecond ticks since 1 January 1601. User mode and kernel mode
4378  // times for this process are in separate 64-bit structures.
4379  // To convert to floating point seconds, we will:
4380  // Convert sum of high 32-bit quantities to 64-bit int
4381 
4382  return (Double_t) (ftKernel.ftInt64 + ftUser.ftInt64) * gTicks;
4383  } else {
4384  return GetRealTime();
4385  }
4386 }
4387 
4388 ////////////////////////////////////////////////////////////////////////////////
4389 /// Get current time in milliseconds since 0:00 Jan 1 1995.
4390 
4392 {
4393  static time_t jan95 = 0;
4394  if (!jan95) {
4395  struct tm tp;
4396  tp.tm_year = 95;
4397  tp.tm_mon = 0;
4398  tp.tm_mday = 1;
4399  tp.tm_hour = 0;
4400  tp.tm_min = 0;
4401  tp.tm_sec = 0;
4402  tp.tm_isdst = -1;
4403 
4404  jan95 = mktime(&tp);
4405  if ((int)jan95 == -1) {
4406  ::SysError("TWinNTSystem::Now", "error converting 950001 0:00 to time_t");
4407  return 0;
4408  }
4409  }
4410 
4411  _timeb now;
4412  _ftime(&now);
4413  return TTime((now.time-(Long_t)jan95)*1000 + now.millitm);
4414 }
4415 
4416 ////////////////////////////////////////////////////////////////////////////////
4417 /// Sleep milliSec milli seconds.
4418 /// The Sleep function suspends the execution of the CURRENT THREAD for
4419 /// a specified interval.
4420 
4422 {
4423  ::Sleep(milliSec);
4424 }
4425 
4426 ////////////////////////////////////////////////////////////////////////////////
4427 /// Select on file descriptors. The timeout to is in millisec.
4428 
4430 {
4431  Int_t rc = -4;
4432 
4433  TFdSet rd, wr;
4434  Int_t mxfd = -1;
4435  TIter next(act);
4436  TFileHandler *h = 0;
4437  while ((h = (TFileHandler *) next())) {
4438  Int_t fd = h->GetFd();
4439  if (h->HasReadInterest())
4440  rd.Set(fd);
4441  if (h->HasWriteInterest())
4442  wr.Set(fd);
4443  h->ResetReadyMask();
4444  }
4445  rc = WinNTSelect(&rd, &wr, to);
4446 
4447  // Set readiness bits
4448  if (rc > 0) {
4449  next.Reset();
4450  while ((h = (TFileHandler *) next())) {
4451  Int_t fd = h->GetFd();
4452  if (rd.IsSet(fd))
4453  h->SetReadReady();
4454  if (wr.IsSet(fd))
4455  h->SetWriteReady();
4456  }
4457  }
4458 
4459  return rc;
4460 }
4461 
4462 ////////////////////////////////////////////////////////////////////////////////
4463 /// Select on the file descriptor related to file handler h.
4464 /// The timeout to is in millisec.
4465 
4467 {
4468  Int_t rc = -4;
4469 
4470  TFdSet rd, wr;
4471  Int_t fd = -1;
4472  if (h) {
4473  fd = h->GetFd();
4474  if (h->HasReadInterest())
4475  rd.Set(fd);
4476  if (h->HasWriteInterest())
4477  wr.Set(fd);
4478  h->ResetReadyMask();
4479  rc = WinNTSelect(&rd, &wr, to);
4480  }
4481 
4482  // Fill output lists, if required
4483  if (rc > 0) {
4484  if (rd.IsSet(fd))
4485  h->SetReadReady();
4486  if (wr.IsSet(fd))
4487  h->SetWriteReady();
4488  }
4489 
4490  return rc;
4491 }
4492 
4493 //---- RPC ---------------------------------------------------------------------
4494 ////////////////////////////////////////////////////////////////////////////////
4495 /// Get port # of internet service.
4496 
4497 int TWinNTSystem::GetServiceByName(const char *servicename)
4498 {
4499  struct servent *sp;
4500 
4501  if ((sp = ::getservbyname(servicename, kProtocolName)) == 0) {
4502  Error("GetServiceByName", "no service \"%s\" with protocol \"%s\"\n",
4503  servicename, kProtocolName);
4504  return -1;
4505  }
4506  return ::ntohs(sp->s_port);
4507 }
4508 
4509 ////////////////////////////////////////////////////////////////////////////////
4510 
4512 {
4513  // Get name of internet service.
4514 
4515  struct servent *sp;
4516 
4517  if ((sp = ::getservbyport(::htons(port), kProtocolName)) == 0) {
4518  return Form("%d", port);
4519  }
4520  return sp->s_name;
4521 }
4522 
4523 ////////////////////////////////////////////////////////////////////////////////
4524 /// Get Internet Protocol (IP) address of host.
4525 
4527 {
4528  struct hostent *host_ptr;
4529  const char *host;
4530  int type;
4531  UInt_t addr; // good for 4 byte addresses
4532 
4533  if ((addr = ::inet_addr(hostname)) != INADDR_NONE) {
4534  type = AF_INET;
4535  if ((host_ptr = ::gethostbyaddr((const char *)&addr,
4536  sizeof(addr), AF_INET))) {
4537  host = host_ptr->h_name;
4538  TInetAddress a(host, ntohl(addr), type);
4539  UInt_t addr2;
4540  Int_t i;
4541  for (i = 1; host_ptr->h_addr_list[i]; i++) {
4542  memcpy(&addr2, host_ptr->h_addr_list[i], host_ptr->h_length);
4543  a.AddAddress(ntohl(addr2));
4544  }
4545  for (i = 0; host_ptr->h_aliases[i]; i++)
4546  a.AddAlias(host_ptr->h_aliases[i]);
4547  return a;
4548  } else {
4549  host = "UnNamedHost";
4550  }
4551  } else if ((host_ptr = ::gethostbyname(hostname))) {
4552  // Check the address type for an internet host
4553  if (host_ptr->h_addrtype != AF_INET) {
4554  Error("GetHostByName", "%s is not an internet host\n", hostname);
4555  return TInetAddress();
4556  }
4557  memcpy(&addr, host_ptr->h_addr, host_ptr->h_length);
4558  host = host_ptr->h_name;
4559  type = host_ptr->h_addrtype;
4560  TInetAddress a(host, ntohl(addr), type);
4561  UInt_t addr2;
4562  Int_t i;
4563  for (i = 1; host_ptr->h_addr_list[i]; i++) {
4564  memcpy(&addr2, host_ptr->h_addr_list[i], host_ptr->h_length);
4565  a.AddAddress(ntohl(addr2));
4566  }
4567  for (i = 0; host_ptr->h_aliases[i]; i++)
4568  a.AddAlias(host_ptr->h_aliases[i]);
4569  return a;
4570  } else {
4571  if (gDebug > 0) Error("GetHostByName", "unknown host %s", hostname);
4572  return TInetAddress(hostname, 0, -1);
4573  }
4574 
4575  return TInetAddress(host, ::ntohl(addr), type);
4576 }
4577 
4578 ////////////////////////////////////////////////////////////////////////////////
4579 /// Get Internet Protocol (IP) address of remote host and port #.
4580 
4582 {
4583  SOCKET sock = socket;
4584  struct sockaddr_in addr;
4585  int len = sizeof(addr);
4586 
4587  if (::getpeername(sock, (struct sockaddr *)&addr, &len) == SOCKET_ERROR) {
4588  ::SysError("GetPeerName", "getpeername");
4589  return TInetAddress();
4590  }
4591 
4592  struct hostent *host_ptr;
4593  const char *hostname;
4594  int family;
4595  UInt_t iaddr;
4596 
4597  if ((host_ptr = ::gethostbyaddr((const char *)&addr.sin_addr,
4598  sizeof(addr.sin_addr), AF_INET))) {
4599  memcpy(&iaddr, host_ptr->h_addr, host_ptr->h_length);
4600  hostname = host_ptr->h_name;
4601  family = host_ptr->h_addrtype;
4602  } else {
4603  memcpy(&iaddr, &addr.sin_addr, sizeof(addr.sin_addr));
4604  hostname = "????";
4605  family = AF_INET;
4606  }
4607 
4608  return TInetAddress(hostname, ::ntohl(iaddr), family, ::ntohs(addr.sin_port));
4609 }
4610 
4611 ////////////////////////////////////////////////////////////////////////////////
4612 /// Get Internet Protocol (IP) address of host and port #.
4613 
4615 {
4616  SOCKET sock = socket;
4617  struct sockaddr_in addr;
4618  int len = sizeof(addr);
4619 
4620  if (::getsockname(sock, (struct sockaddr *)&addr, &len) == SOCKET_ERROR) {
4621  ::SysError("GetSockName", "getsockname");
4622  return TInetAddress();
4623  }
4624 
4625  struct hostent *host_ptr;
4626  const char *hostname;
4627  int family;
4628  UInt_t iaddr;
4629 
4630  if ((host_ptr = ::gethostbyaddr((const char *)&addr.sin_addr,
4631  sizeof(addr.sin_addr), AF_INET))) {
4632  memcpy(&iaddr, host_ptr->h_addr, host_ptr->h_length);
4633  hostname = host_ptr->h_name;
4634  family = host_ptr->h_addrtype;
4635  } else {
4636  memcpy(&iaddr, &addr.sin_addr, sizeof(addr.sin_addr));
4637  hostname = "????";
4638  family = AF_INET;
4639  }
4640 
4641  return TInetAddress(hostname, ::ntohl(iaddr), family, ::ntohs(addr.sin_port));
4642 }
4643 
4644 ////////////////////////////////////////////////////////////////////////////////
4645 /// Announce unix domain service.
4646 
4647 int TWinNTSystem::AnnounceUnixService(int port, int backlog)
4648 {
4649  SOCKET sock;
4650 
4651  // Create socket
4652  if ((sock = ::socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
4653  ::SysError("TWinNTSystem::AnnounceUnixService", "socket");
4654  return -1;
4655  }
4656 
4657  struct sockaddr_in inserver;
4658  memset(&inserver, 0, sizeof(inserver));
4659  inserver.sin_family = AF_INET;
4660  inserver.sin_addr.s_addr = ::htonl(INADDR_LOOPBACK);
4661  inserver.sin_port = port;
4662 
4663  // Bind socket
4664  if (port > 0) {
4665  if (::bind(sock, (struct sockaddr*) &inserver, sizeof(inserver)) == SOCKET_ERROR) {
4666  ::SysError("TWinNTSystem::AnnounceUnixService", "bind");
4667  return -2;
4668  }
4669  }
4670  // Start accepting connections
4671  if (::listen(sock, backlog)) {
4672  ::SysError("TWinNTSystem::AnnounceUnixService", "listen");
4673  return -1;
4674  }
4675  return (int)sock;
4676 }
4677 
4678 ////////////////////////////////////////////////////////////////////////////////
4679 /// Open a socket on path 'sockpath', bind to it and start listening for Unix
4680 /// domain connections to it. Returns socket fd or -1.
4681 
4682 int TWinNTSystem::AnnounceUnixService(const char *sockpath, int backlog)
4683 {
4684  if (!sockpath || strlen(sockpath) <= 0) {
4685  ::SysError("TWinNTSystem::AnnounceUnixService", "socket path undefined");
4686  return -1;
4687  }
4688 
4689  struct sockaddr_in myaddr;
4690  FILE * fp;
4691  int len = sizeof myaddr;
4692  int rc;
4693  int sock;
4694 
4695  // Create socket
4696  if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
4697  ::SysError("TWinNTSystem::AnnounceUnixService", "socket");
4698  return -1;
4699  }
4700 
4701  memset(&myaddr, 0, sizeof(myaddr));
4702  myaddr.sin_port = 0;
4703  myaddr.sin_family = AF_INET;
4704  myaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
4705 
4706  rc = bind(sock, (struct sockaddr *)&myaddr, len);
4707  if (rc) {
4708  ::SysError("TWinNTSystem::AnnounceUnixService", "bind");
4709  return rc;
4710  }
4711  rc = getsockname(sock, (struct sockaddr *)&myaddr, &len);
4712  if (rc) {
4713  ::SysError("TWinNTSystem::AnnounceUnixService", "getsockname");
4714  return rc;
4715  }
4716  TString socketpath = sockpath;
4717  socketpath.ReplaceAll("/", "\\");
4718  fp = fopen(socketpath, "wb");
4719  if (!fp) {
4720  ::SysError("TWinNTSystem::AnnounceUnixService", "fopen");
4721  return -1;
4722  }
4723  fprintf(fp, "%d", myaddr.sin_port);
4724  fclose(fp);
4725 
4726  // Start accepting connections
4727  if (listen(sock, backlog)) {
4728  ::SysError("TWinNTSystem::AnnounceUnixService", "listen");
4729  return -1;
4730  }
4731 
4732  return sock;
4733 }
4734 
4735 ////////////////////////////////////////////////////////////////////////////////
4736 /// Close socket.
4737 
4738 void TWinNTSystem::CloseConnection(int socket, Bool_t force)
4739 {
4740  if (socket == -1) return;
4741  SOCKET sock = socket;
4742 
4743  if (force) {
4744  ::shutdown(sock, 2);
4745  }
4746  struct linger linger = {0, 0};
4747  ::setsockopt(sock, SOL_SOCKET, SO_LINGER, (char *) &linger, sizeof(linger));
4748  while (::closesocket(sock) == SOCKET_ERROR && WSAGetLastError() == WSAEINTR) {
4750  }
4751 }
4752 
4753 ////////////////////////////////////////////////////////////////////////////////
4754 /// Receive a buffer headed by a length indicator. Length is the size of
4755 /// the buffer. Returns the number of bytes received in buf or -1 in
4756 /// case of error.
4757 
4758 int TWinNTSystem::RecvBuf(int sock, void *buf, int length)
4759 {
4760  Int_t header;
4761 
4762  if (WinNTRecv(sock, &header, sizeof(header), 0) > 0) {
4763  int count = ::ntohl(header);
4764 
4765  if (count > length) {
4766  Error("RecvBuf", "record header exceeds buffer size");
4767  return -1;
4768  } else if (count > 0) {
4769  if (WinNTRecv(sock, buf, count, 0) < 0) {
4770  Error("RecvBuf", "cannot receive buffer");
4771  return -1;
4772  }
4773  }
4774  return count;
4775  }
4776  return -1;
4777 }
4778 
4779 ////////////////////////////////////////////////////////////////////////////////
4780 /// Send a buffer headed by a length indicator. Returns length of sent buffer
4781 /// or -1 in case of error.
4782 
4783 int TWinNTSystem::SendBuf(int sock, const void *buf, int length)
4784 {
4785  Int_t header = ::htonl(length);
4786 
4787  if (WinNTSend(sock, &header, sizeof(header), 0) < 0) {
4788  Error("SendBuf", "cannot send header");
4789  return -1;
4790  }
4791  if (length > 0) {
4792  if (WinNTSend(sock, buf, length, 0) < 0) {
4793  Error("SendBuf", "cannot send buffer");
4794  return -1;
4795  }
4796  }
4797  return length;
4798 }
4799 
4800 ////////////////////////////////////////////////////////////////////////////////
4801 /// Receive exactly length bytes into buffer. Use opt to receive out-of-band
4802 /// data or to have a peek at what is in the buffer (see TSocket). Buffer
4803 /// must be able to store at least length bytes. Returns the number of
4804 /// bytes received (can be 0 if other side of connection was closed) or -1
4805 /// in case of error, -2 in case of MSG_OOB and errno == EWOULDBLOCK, -3
4806 /// in case of MSG_OOB and errno == EINVAL and -4 in case of kNoBlock and
4807 /// errno == EWOULDBLOCK. Returns -5 if pipe broken or reset by peer
4808 /// (EPIPE || ECONNRESET).
4809 
4810 int TWinNTSystem::RecvRaw(int sock, void *buf, int length, int opt)
4811 {
4812  int flag;
4813 
4814  switch (opt) {
4815  case kDefault:
4816  flag = 0;
4817  break;
4818  case kOob:
4819  flag = MSG_OOB;
4820  break;
4821  case kPeek:
4822  flag = MSG_PEEK;
4823  break;
4824  case kDontBlock:
4825  flag = -1;
4826  break;
4827  default:
4828  flag = 0;
4829  break;
4830  }
4831 
4832  int n;
4833  if ((n = WinNTRecv(sock, buf, length, flag)) <= 0) {
4834  if (n == -1) {
4835  Error("RecvRaw", "cannot receive buffer");
4836  }
4837  return n;
4838  }
4839  return n;
4840 }
4841 
4842 ////////////////////////////////////////////////////////////////////////////////
4843 /// Send exactly length bytes from buffer. Use opt to send out-of-band
4844 /// data (see TSocket). Returns the number of bytes sent or -1 in case of
4845 /// error. Returns -4 in case of kNoBlock and errno == EWOULDBLOCK.
4846 /// Returns -5 if pipe broken or reset by peer (EPIPE || ECONNRESET).
4847 
4848 int TWinNTSystem::SendRaw(int sock, const void *buf, int length, int opt)
4849 {
4850  int flag;
4851 
4852  switch (opt) {
4853  case kDefault:
4854  flag = 0;
4855  break;
4856  case kOob:
4857  flag = MSG_OOB;
4858  break;
4859  case kDontBlock:
4860  flag = -1;
4861  break;
4862  case kPeek: // receive only option (see RecvRaw)
4863  default:
4864  flag = 0;
4865  break;
4866  }
4867 
4868  int n;
4869  if ((n = WinNTSend(sock, buf, length, flag)) <= 0) {
4870  if (n == -1 && GetErrno() != EINTR) {
4871  Error("SendRaw", "cannot send buffer");
4872  }
4873  return n;
4874  }
4875  return n;
4876 }
4877 
4878 ////////////////////////////////////////////////////////////////////////////////
4879 /// Set socket option.
4880 
4881 int TWinNTSystem::SetSockOpt(int socket, int opt, int value)
4882 {
4883  u_long val = value;
4884  if (socket == -1) return -1;
4885  SOCKET sock = socket;
4886 
4887  switch (opt) {
4888  case kSendBuffer:
4889  if (::setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char*)&val, sizeof(val)) == SOCKET_ERROR) {
4890  ::SysError("SetSockOpt", "setsockopt(SO_SNDBUF)");
4891  return -1;
4892  }
4893  break;
4894  case kRecvBuffer:
4895  if (::setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*)&val, sizeof(val)) == SOCKET_ERROR) {
4896  ::SysError("SetSockOpt", "setsockopt(SO_RCVBUF)");
4897  return -1;
4898  }
4899  break;
4900  case kOobInline:
4901  if (::setsockopt(sock, SOL_SOCKET, SO_OOBINLINE, (char*)&val, sizeof(val)) == SOCKET_ERROR) {
4902  SysError("SetSockOpt", "setsockopt(SO_OOBINLINE)");
4903  return -1;
4904  }
4905  break;
4906  case kKeepAlive:
4907  if (::setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char*)&val, sizeof(val)) == SOCKET_ERROR) {
4908  ::SysError("SetSockOpt", "setsockopt(SO_KEEPALIVE)");
4909  return -1;
4910  }
4911  break;
4912  case kReuseAddr:
4913  if (::setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&val, sizeof(val)) == SOCKET_ERROR) {
4914  ::SysError("SetSockOpt", "setsockopt(SO_REUSEADDR)");
4915  return -1;
4916  }
4917  break;
4918  case kNoDelay:
4919  if (::setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char*)&val, sizeof(val)) == SOCKET_ERROR) {
4920  ::SysError("SetSockOpt", "setsockopt(TCP_NODELAY)");
4921  return -1;
4922  }
4923  break;
4924  case kNoBlock:
4925  if (::ioctlsocket(sock, FIONBIO, &val) == SOCKET_ERROR) {
4926  ::SysError("SetSockOpt", "ioctl(FIONBIO)");
4927  return -1;
4928  }
4929  break;
4930 #if 0
4931  case kProcessGroup:
4932  if (::ioctl(sock, SIOCSPGRP, &val) == -1) {
4933  ::SysError("SetSockOpt", "ioctl(SIOCSPGRP)");
4934  return -1;
4935  }
4936  break;
4937 #endif
4938  case kAtMark: // read-only option (see GetSockOpt)
4939  case kBytesToRead: // read-only option
4940  default:
4941  Error("SetSockOpt", "illegal option (%d)", opt);
4942  return -1;
4943  break;
4944  }
4945  return 0;
4946 }
4947 
4948 ////////////////////////////////////////////////////////////////////////////////
4949 /// Get socket option.
4950 
4951 int TWinNTSystem::GetSockOpt(int socket, int opt, int *val)
4952 {
4953  if (socket == -1) return -1;
4954  SOCKET sock = socket;
4955 
4956  int optlen = sizeof(*val);
4957 
4958  switch (opt) {
4959  case kSendBuffer:
4960  if (::getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char*)val, &optlen) == SOCKET_ERROR) {
4961  ::SysError("GetSockOpt", "getsockopt(SO_SNDBUF)");
4962  return -1;
4963  }
4964  break;
4965  case kRecvBuffer:
4966  if (::getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*)val, &optlen) == SOCKET_ERROR) {
4967  ::SysError("GetSockOpt", "getsockopt(SO_RCVBUF)");
4968  return -1;
4969  }
4970  break;
4971  case kOobInline:
4972  if (::getsockopt(sock, SOL_SOCKET, SO_OOBINLINE, (char*)val, &optlen) == SOCKET_ERROR) {
4973  ::SysError("GetSockOpt", "getsockopt(SO_OOBINLINE)");
4974  return -1;
4975  }
4976  break;
4977  case kKeepAlive:
4978  if (::getsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char*)val, &optlen) == SOCKET_ERROR) {
4979  ::SysError("GetSockOpt", "getsockopt(SO_KEEPALIVE)");
4980  return -1;
4981  }
4982  break;
4983  case kReuseAddr:
4984  if (::getsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)val, &optlen) == SOCKET_ERROR) {
4985  ::SysError("GetSockOpt", "getsockopt(SO_REUSEADDR)");
4986  return -1;
4987  }
4988  break;
4989  case kNoDelay:
4990  if (::getsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char*)val, &optlen) == SOCKET_ERROR) {
4991  ::SysError("GetSockOpt", "getsockopt(TCP_NODELAY)");
4992  return -1;
4993  }
4994  break;
4995  case kNoBlock:
4996  {
4997  int flg = 0;
4998  if (sock == INVALID_SOCKET) {
4999  ::SysError("GetSockOpt", "INVALID_SOCKET");
5000  }
5001  return -1;
5002  *val = flg; // & O_NDELAY; It is not been defined for WIN32
5003  }
5004  break;
5005 #if 0
5006  case kProcessGroup:
5007  if (::ioctlsocket(sock, SIOCGPGRP, (u_long*)val) == SOCKET_ERROR) {
5008  ::SysError("GetSockOpt", "ioctl(SIOCGPGRP)");
5009  return -1;
5010  }
5011  break;
5012 #endif
5013  case kAtMark:
5014  if (::ioctlsocket(sock, SIOCATMARK, (u_long*)val) == SOCKET_ERROR) {
5015  ::SysError("GetSockOpt", "ioctl(SIOCATMARK)");
5016  return -1;
5017  }
5018  break;
5019  case kBytesToRead:
5020  if (::ioctlsocket(sock, FIONREAD, (u_long*)val) == SOCKET_ERROR) {
5021  ::SysError("GetSockOpt", "ioctl(FIONREAD)");
5022  return -1;
5023  }
5024  break;
5025  default:
5026  Error("GetSockOpt", "illegal option (%d)", opt);
5027  *val = 0;
5028  return -1;
5029  break;
5030  }
5031  return 0;
5032 }
5033 
5034 ////////////////////////////////////////////////////////////////////////////////
5035 /// Connect to service servicename on server servername.
5036 
5037 int TWinNTSystem::ConnectService(const char *servername, int port,
5038  int tcpwindowsize, const char *protocol)
5039 {
5040  short sport;
5041  struct servent *sp;
5042 
5043  if (!strcmp(servername, "unix")) {
5044  return WinNTUnixConnect(port);
5045  }
5046  else if (!gSystem->AccessPathName(servername) || servername[0] == '/' ||
5047  (servername[1] == ':' && servername[2] == '/')) {
5048  return WinNTUnixConnect(servername);
5049  }
5050 
5051  if (!strcmp(protocol, "udp")){
5052  return WinNTUdpConnect(servername, port);
5053  }
5054 
5055  if ((sp = ::getservbyport(::htons(port), kProtocolName))) {
5056  sport = sp->s_port;
5057  } else {
5058  sport = ::htons(port);
5059  }
5060 
5061  TInetAddress addr = gSystem->GetHostByName(servername);
5062  if (!addr.IsValid()) return -1;
5063  UInt_t adr = ::htonl(addr.GetAddress());
5064 
5065  struct sockaddr_in server;
5066  memset(&server, 0, sizeof(server));
5067  memcpy(&server.sin_addr, &adr, sizeof(adr));
5068  server.sin_family = addr.GetFamily();
5069  server.sin_port = sport;
5070 
5071  // Create socket
5072  SOCKET sock;
5073  if ((sock = ::socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
5074  ::SysError("TWinNTSystem::WinNTConnectTcp", "socket");
5075  return -1;
5076  }
5077 
5078  if (tcpwindowsize > 0) {
5079  gSystem->SetSockOpt((int)sock, kRecvBuffer, tcpwindowsize);
5080  gSystem->SetSockOpt((int)sock, kSendBuffer, tcpwindowsize);
5081  }
5082 
5083  if (::connect(sock, (struct sockaddr*) &server, sizeof(server)) == INVALID_SOCKET) {
5084  //::SysError("TWinNTSystem::UnixConnectTcp", "connect");
5085  ::closesocket(sock);
5086  return -1;
5087  }
5088  return (int) sock;
5089 }
5090 
5091 ////////////////////////////////////////////////////////////////////////////////
5092 /// Connect to a Unix domain socket.
5093 
5095 {
5096  struct sockaddr_in myaddr;
5097  int sock;
5098 
5099  memset(&myaddr, 0, sizeof(myaddr));
5100  myaddr.sin_family = AF_INET;
5101  myaddr.sin_port = port;
5102  myaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
5103 
5104  // Open socket
5105  if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
5106  ::SysError("TWinNTSystem::WinNTUnixConnect", "socket");
5107  return -1;
5108  }
5109 
5110  while ((connect(sock, (struct sockaddr *)&myaddr, sizeof myaddr)) == -1) {
5111  if (GetErrno() == EINTR)
5112  ResetErrno();
5113  else {
5114  ::SysError("TWinNTSystem::WinNTUnixConnect", "connect");
5115  close(sock);
5116  return -1;
5117  }
5118  }
5119  return sock;
5120 }
5121 
5122 ////////////////////////////////////////////////////////////////////////////////
5123 /// Connect to a Unix domain socket. Returns -1 in case of error.
5124 
5125 int TWinNTSystem::WinNTUnixConnect(const char *sockpath)
5126 {
5127  FILE *fp;
5128  int port = 0;
5129 
5130  if (!sockpath || strlen(sockpath) <= 0) {
5131  ::SysError("TWinNTSystem::WinNTUnixConnect", "socket path undefined");
5132  return -1;
5133  }
5134  TString socketpath = sockpath;
5135  socketpath.ReplaceAll("/", "\\");
5136  fp = fopen(socketpath.Data(), "rb");
5137  if (!fp) {
5138  ::SysError("TWinNTSystem::WinNTUnixConnect", "fopen");
5139  return -1;
5140  }
5141  fscanf(fp, "%d", &port);
5142  fclose(fp);
5143  /* XXX: set errno in this case */
5144  if (port < 0 || port > 65535) {
5145  ::SysError("TWinNTSystem::WinNTUnixConnect", "invalid port");
5146  return -1;
5147  }
5148  return WinNTUnixConnect(port);
5149 }
5150 
5151 ////////////////////////////////////////////////////////////////////////////////
5152 /// Creates a UDP socket connection
5153 /// Is called via the TSocket constructor. Returns -1 in case of error.
5154 
5155 int TWinNTSystem::WinNTUdpConnect(const char *hostname, int port)
5156 {
5157  short sport;
5158  struct servent *sp;
5159 
5160  if ((sp = getservbyport(htons(port), kProtocolName)))
5161  sport = sp->s_port;
5162  else
5163  sport = htons(port);
5164 
5165  TInetAddress addr = gSystem->GetHostByName(hostname);
5166  if (!addr.IsValid()) return -1;
5167  UInt_t adr = htonl(addr.GetAddress());
5168 
5169  struct sockaddr_in server;
5170  memset(&server, 0, sizeof(server));
5171  memcpy(&server.sin_addr, &adr, sizeof(adr));
5172  server.sin_family = addr.GetFamily();
5173  server.sin_port = sport;
5174 
5175  // Create socket
5176  int sock;
5177  if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
5178  ::SysError("TWinNTSystem::WinNTUdpConnect", "socket (%s:%d)",
5179  hostname, port);
5180  return -1;
5181  }
5182 
5183  while (connect(sock, (struct sockaddr*) &server, sizeof(server)) == -1) {
5184  if (GetErrno() == EINTR)
5185  ResetErrno();
5186  else {
5187  ::SysError("TWinNTSystem::WinNTUdpConnect", "connect (%s:%d)",
5188  hostname, port);
5189  close(sock);
5190  return -1;
5191  }
5192  }
5193  return sock;
5194 }
5195 
5196 ////////////////////////////////////////////////////////////////////////////////
5197 /// Open a connection to a service on a server. Returns -1 in case
5198 /// connection cannot be opened.
5199 /// Use tcpwindowsize to specify the size of the receive buffer, it has
5200 /// to be specified here to make sure the window scale option is set (for
5201 /// tcpwindowsize > 65KB and for platforms supporting window scaling).
5202 /// Is called via the TSocket constructor.
5203 
5204 int TWinNTSystem::OpenConnection(const char *server, int port, int tcpwindowsize,
5205  const char *protocol)
5206 {
5207  return ConnectService(server, port, tcpwindowsize, protocol);
5208 }
5209 
5210 ////////////////////////////////////////////////////////////////////////////////
5211 /// Announce TCP/IP service.
5212 /// Open a socket, bind to it and start listening for TCP/IP connections
5213 /// on the port. If reuse is true reuse the address, backlog specifies
5214 /// how many sockets can be waiting to be accepted.
5215 /// Use tcpwindowsize to specify the size of the receive buffer, it has
5216 /// to be specified here to make sure the window scale option is set (for
5217 /// tcpwindowsize > 65KB and for platforms supporting window scaling).
5218 /// Returns socket fd or -1 if socket() failed, -2 if bind() failed
5219 /// or -3 if listen() failed.
5220 
5221 int TWinNTSystem::AnnounceTcpService(int port, Bool_t reuse, int backlog,
5222  int tcpwindowsize)
5223 {
5224  short sport;
5225  struct servent *sp;
5226  const short kSOCKET_MINPORT = 5000, kSOCKET_MAXPORT = 15000;
5227  short tryport = kSOCKET_MINPORT;
5228 
5229  if ((sp = ::getservbyport(::htons(port), kProtocolName))) {
5230  sport = sp->s_port;
5231  } else {
5232  sport = ::htons(port);
5233  }
5234 
5235  if (port == 0 && reuse) {
5236  ::Error("TWinNTSystem::WinNTTcpService", "cannot do a port scan while reuse is true");
5237  return -1;
5238  }
5239 
5240  if ((sp = ::getservbyport(::htons(port), kProtocolName))) {
5241  sport = sp->s_port;
5242  } else {
5243  sport = ::htons(port);
5244  }
5245 
5246  // Create tcp socket
5247  SOCKET sock;
5248  if ((sock = ::socket(AF_INET, SOCK_STREAM, 0)) < 0) {
5249  ::SysError("TWinNTSystem::WinNTTcpService", "socket");
5250  return -1;
5251  }
5252 
5253  if (reuse) {
5254  gSystem->SetSockOpt((int)sock, kReuseAddr, 1);
5255  }
5256 
5257  if (tcpwindowsize > 0) {
5258  gSystem->SetSockOpt((int)sock, kRecvBuffer, tcpwindowsize);
5259  gSystem->SetSockOpt((int)sock, kSendBuffer, tcpwindowsize);
5260  }
5261 
5262  struct sockaddr_in inserver;
5263  memset(&inserver, 0, sizeof(inserver));
5264  inserver.sin_family = AF_INET;
5265  inserver.sin_addr.s_addr = ::htonl(INADDR_ANY);
5266  inserver.sin_port = sport;
5267 
5268  // Bind socket
5269  if (port > 0) {
5270  if (::bind(sock, (struct sockaddr*) &inserver, sizeof(inserver)) == SOCKET_ERROR) {
5271  ::SysError("TWinNTSystem::WinNTTcpService", "bind");
5272  return -2;
5273  }
5274  } else {
5275  int bret;
5276  do {
5277  inserver.sin_port = ::htons(tryport++);
5278  bret = ::bind(sock, (struct sockaddr*) &inserver, sizeof(inserver));
5279  } while (bret == SOCKET_ERROR && WSAGetLastError() == WSAEADDRINUSE &&
5280  tryport < kSOCKET_MAXPORT);
5281  if (bret == SOCKET_ERROR) {
5282  ::SysError("TWinNTSystem::WinNTTcpService", "bind (port scan)");
5283  return -2;
5284  }
5285  }
5286 
5287  // Start accepting connections
5288  if (::listen(sock, backlog) == SOCKET_ERROR) {
5289  ::SysError("TWinNTSystem::WinNTTcpService", "listen");
5290  return -3;
5291  }
5292  return (int)sock;
5293 }
5294 
5295 ////////////////////////////////////////////////////////////////////////////////
5296 /// Announce UDP service.
5297 
5298 int TWinNTSystem::AnnounceUdpService(int port, int backlog)
5299 {
5300  // Open a socket, bind to it and start listening for UDP connections
5301  // on the port. If reuse is true reuse the address, backlog specifies
5302  // how many sockets can be waiting to be accepted. If port is 0 a port
5303  // scan will be done to find a free port. This option is mutual exlusive
5304  // with the reuse option.
5305 
5306  const short kSOCKET_MINPORT = 5000, kSOCKET_MAXPORT = 15000;
5307  short sport, tryport = kSOCKET_MINPORT;
5308  struct servent *sp;
5309 
5310  if ((sp = getservbyport(htons(port), kProtocolName)))
5311  sport = sp->s_port;
5312  else
5313  sport = htons(port);
5314 
5315  // Create udp socket
5316  int sock;
5317  if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
5318  ::SysError("TUnixSystem::UnixUdpService", "socket");
5319  return -1;
5320  }
5321 
5322  struct sockaddr_in inserver;
5323  memset(&inserver, 0, sizeof(inserver));
5324  inserver.sin_family = AF_INET;
5325  inserver.sin_addr.s_addr = htonl(INADDR_ANY);
5326  inserver.sin_port = sport;
5327 
5328  // Bind socket
5329  if (port > 0) {
5330  if (bind(sock, (struct sockaddr*) &inserver, sizeof(inserver))) {
5331  ::SysError("TWinNTSystem::AnnounceUdpService", "bind");
5332  return -2;
5333  }
5334  } else {
5335  int bret;
5336  do {
5337  inserver.sin_port = htons(tryport++);
5338  bret = bind(sock, (struct sockaddr*) &inserver, sizeof(inserver));
5339  } while (bret == SOCKET_ERROR && WSAGetLastError() == WSAEADDRINUSE &&
5340  tryport < kSOCKET_MAXPORT);
5341  if (bret < 0) {
5342  ::SysError("TWinNTSystem::AnnounceUdpService", "bind (port scan)");
5343  return -2;
5344  }
5345  }
5346 
5347  // Start accepting connections
5348  if (listen(sock, backlog)) {
5349  ::SysError("TWinNTSystem::AnnounceUdpService", "listen");
5350  return -3;
5351  }
5352 
5353  return sock;
5354 }
5355 
5356 ////////////////////////////////////////////////////////////////////////////////
5357 /// Accept a connection. In case of an error return -1. In case
5358 /// non-blocking I/O is enabled and no connections are available
5359 /// return -2.
5360 
5362 {
5363  int soc = -1;
5364  SOCKET sock = socket;
5365 
5366  while ((soc = ::accept(sock, 0, 0)) == INVALID_SOCKET &&
5367  (::WSAGetLastError() == WSAEINTR)) {
5369  }
5370 
5371  if (soc == -1) {
5372  if (::WSAGetLastError() == WSAEWOULDBLOCK) {
5373  return -2;
5374  } else {
5375  ::SysError("AcceptConnection", "accept");
5376  return -1;
5377  }
5378  }
5379  return soc;
5380 }
5381 
5382 //---- System, CPU and Memory info ---------------------------------------------
5383 
5384 // !!! using undocumented functions and structures !!!
5385 
5386 #define SystemBasicInformation 0
5387 #define SystemPerformanceInformation 2
5388 
5389 typedef struct
5390 {
5391  DWORD dwUnknown1;
5392  ULONG uKeMaximumIncrement;
5393  ULONG uPageSize;
5394  ULONG uMmNumberOfPhysicalPages;
5395  ULONG uMmLowestPhysicalPage;
5396  ULONG UMmHighestPhysicalPage;
5397  ULONG uAllocationGranularity;
5398  PVOID pLowestUserAddress;
5399  PVOID pMmHighestUserAddress;
5400  ULONG uKeActiveProcessors;
5401  BYTE bKeNumberProcessors;
5402  BYTE bUnknown2;
5403  WORD bUnknown3;
5404 } SYSTEM_BASIC_INFORMATION;
5405 
5406 typedef struct
5407 {
5408  LARGE_INTEGER liIdleTime;
5409  DWORD dwSpare[76];
5410 } SYSTEM_PERFORMANCE_INFORMATION;
5411 
5412 typedef struct _PROCESS_MEMORY_COUNTERS {
5413  DWORD cb;
5414  DWORD PageFaultCount;
5415  SIZE_T PeakWorkingSetSize;
5416  SIZE_T WorkingSetSize;
5417  SIZE_T QuotaPeakPagedPoolUsage;
5418  SIZE_T QuotaPagedPoolUsage;
5419  SIZE_T QuotaPeakNonPagedPoolUsage;
5420  SIZE_T QuotaNonPagedPoolUsage;
5421  SIZE_T PagefileUsage;
5422  SIZE_T PeakPagefileUsage;
5424 
5425 typedef LONG (WINAPI *PROCNTQSI) (UINT, PVOID, ULONG, PULONG);
5426 
5427 #define Li2Double(x) ((double)((x).HighPart) * 4.294967296E9 + (double)((x).LowPart))
5428 
5429 ////////////////////////////////////////////////////////////////////////////////
5430 /// Calculate the CPU clock speed using the 'rdtsc' instruction.
5431 /// RDTSC: Read Time Stamp Counter.
5432 
5433 static DWORD GetCPUSpeed()
5434 {
5435  LARGE_INTEGER ulFreq, ulTicks, ulValue, ulStartCounter;
5436 
5437  // Query for high-resolution counter frequency
5438  // (this is not the CPU frequency):
5439  if (QueryPerformanceFrequency(&ulFreq)) {
5440  // Query current value:
5441  QueryPerformanceCounter(&ulTicks);
5442  // Calculate end value (one second interval);
5443  // this is (current + frequency)
5444  ulValue.QuadPart = ulTicks.QuadPart + ulFreq.QuadPart/10;
5445  ulStartCounter.QuadPart = __rdtsc();
5446 
5447  // Loop for one second (measured with the high-resolution counter):
5448  do {
5449  QueryPerformanceCounter(&ulTicks);
5450  } while (ulTicks.QuadPart <= ulValue.QuadPart);
5451  // Now again read CPU time-stamp counter:
5452  return (DWORD)((__rdtsc() - ulStartCounter.QuadPart)/100000);
5453  } else {
5454  // No high-resolution counter present:
5455  return 0;
5456  }
5457 }
5458 
5459 #define BUFSIZE 80
5460 #define SM_SERVERR2 89
5461 typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO);
5462 
5463 ////////////////////////////////////////////////////////////////////////////////
5464 
5465 static char *GetWindowsVersion()
5466 {
5467  OSVERSIONINFOEX osvi;
5468  SYSTEM_INFO si;
5469  PGNSI pGNSI;
5470  BOOL bOsVersionInfoEx;
5471  static char *strReturn = 0;
5472  char temp[512];
5473 
5474  if (strReturn == 0)
5475  strReturn = new char[2048];
5476  else
5477  return strReturn;
5478 
5479  ZeroMemory(&si, sizeof(SYSTEM_INFO));
5480  ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
5481 
5482  // Try calling GetVersionEx using the OSVERSIONINFOEX structure.
5483  // If that fails, try using the OSVERSIONINFO structure.
5484 
5485  osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
5486 
5487  if( !(bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi)) )
5488  {
5489  osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
5490  if (! GetVersionEx ( (OSVERSIONINFO *) &osvi) )
5491  return "";
5492  }
5493 
5494  // Call GetNativeSystemInfo if supported or GetSystemInfo otherwise.
5495  pGNSI = (PGNSI) GetProcAddress( GetModuleHandle("kernel32.dll"),
5496  "GetNativeSystemInfo");
5497  if(NULL != pGNSI)
5498  pGNSI(&si);
5499  else GetSystemInfo(&si);
5500 
5501  switch (osvi.dwPlatformId)
5502  {
5503  // Test for the Windows NT product family.
5504  case VER_PLATFORM_WIN32_NT:
5505 
5506  // Test for the specific product.
5507  if ( osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 0 )
5508  {
5509  if( osvi.wProductType == VER_NT_WORKSTATION )
5510  strlcpy(strReturn, "Microsoft Windows Vista ",2048);
5511  else strlcpy(strReturn, "Windows Server \"Longhorn\" " ,2048);
5512  }
5513  if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2 )
5514  {
5515  if( GetSystemMetrics(SM_SERVERR2) )
5516  strlcpy(strReturn, "Microsoft Windows Server 2003 \"R2\" ",2048);
5517  else if( osvi.wProductType == VER_NT_WORKSTATION &&
5518  si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64)
5519  {
5520  strlcpy(strReturn, "Microsoft Windows XP Professional x64 Edition ",2048);
5521  }
5522  else strlcpy(strReturn, "Microsoft Windows Server 2003, ",2048);
5523  }
5524  if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1 )
5525  strlcpy(strReturn, "Microsoft Windows XP ",2048);
5526 
5527  if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0 )
5528  strlcpy(strReturn, "Microsoft Windows 2000 ",2048);
5529 
5530  if ( osvi.dwMajorVersion <= 4 )
5531  strlcpy(strReturn, "Microsoft Windows NT ",2048);
5532 
5533  // Test for specific product on Windows NT 4.0 SP6 and later.
5534  if( bOsVersionInfoEx )
5535  {
5536  // Test for the workstation type.
5537  if ( osvi.wProductType == VER_NT_WORKSTATION &&
5538  si.wProcessorArchitecture!=PROCESSOR_ARCHITECTURE_AMD64)
5539  {
5540  if( osvi.dwMajorVersion == 4 )
5541  strlcat(strReturn, "Workstation 4.0 ",2048 );
5542  else if( osvi.wSuiteMask & VER_SUITE_PERSONAL )
5543  strlcat(strReturn, "Home Edition " ,2048);
5544  else strlcat(strReturn, "Professional " ,2048);
5545  }
5546  // Test for the server type.
5547  else if ( osvi.wProductType == VER_NT_SERVER ||
5548  osvi.wProductType == VER_NT_DOMAIN_CONTROLLER )
5549  {
5550  if(osvi.dwMajorVersion==5 && osvi.dwMinorVersion==2)
5551  {
5552  if ( si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_IA64 )
5553  {
5554  if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
5555  strlcat(strReturn, "Datacenter Edition for Itanium-based Systems",2048 );
5556  else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
5557  strlcat(strReturn, "Enterprise Edition for Itanium-based Systems" ,2048);
5558  }
5559  else if ( si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64 )
5560  {
5561  if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
5562  strlcat(strReturn, "Datacenter x64 Edition ",2048 );
5563  else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
5564  strlcat(strReturn, "Enterprise x64 Edition ",2048 );
5565  else strlcat(strReturn, "Standard x64 Edition ",2048 );
5566  }
5567  else
5568  {
5569  if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
5570  strlcat(strReturn, "Datacenter Edition ",2048 );
5571  else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
5572  strlcat(strReturn, "Enterprise Edition ",2048 );
5573  else if ( osvi.wSuiteMask == VER_SUITE_BLADE )
5574  strlcat(strReturn, "Web Edition " ,2048);
5575  else strlcat(strReturn, "Standard Edition ",2048 );
5576  }
5577  }
5578  else if(osvi.dwMajorVersion==5 && osvi.dwMinorVersion==0)
5579  {
5580  if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
5581  strlcat(strReturn, "Datacenter Server ",2048 );
5582  else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
5583  strlcat(strReturn, "Advanced Server ",2048 );
5584  else strlcat(strReturn, "Server ",2048 );
5585  }
5586  else // Windows NT 4.0
5587  {
5588  if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
5589  strlcat(strReturn, "Server 4.0, Enterprise Edition " ,2048);
5590  else strlcat(strReturn, "Server 4.0 ",2048 );
5591  }
5592  }
5593  }
5594  // Test for specific product on Windows NT 4.0 SP5 and earlier
5595  else
5596  {
5597  HKEY hKey;
5598  TCHAR szProductType[BUFSIZE];
5599  DWORD dwBufLen=BUFSIZE*sizeof(TCHAR);
5600  LONG lRet;
5601 
5602  lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
5603  "SYSTEM\\CurrentControlSet\\Control\\ProductOptions",
5604  0, KEY_QUERY_VALUE, &hKey );
5605  if( lRet != ERROR_SUCCESS )
5606  return "";
5607 
5608  lRet = RegQueryValueEx( hKey, "ProductType", NULL, NULL,
5609  (LPBYTE) szProductType, &dwBufLen);
5610  RegCloseKey( hKey );
5611 
5612  if( (lRet != ERROR_SUCCESS) || (dwBufLen > BUFSIZE*sizeof(TCHAR)) )
5613  return "";
5614 
5615  if ( lstrcmpi( "WINNT", szProductType) == 0 )
5616  strlcat(strReturn, "Workstation " ,2048);
5617  if ( lstrcmpi( "LANMANNT", szProductType) == 0 )
5618  strlcat(strReturn, "Server " ,2048);
5619  if ( lstrcmpi( "SERVERNT", szProductType) == 0 )
5620  strlcat(strReturn, "Advanced Server " ,2048);
5621  snprintf(temp,512, "%d.%d ", osvi.dwMajorVersion, osvi.dwMinorVersion);
5622  strlcat(strReturn, temp,2048);
5623  }
5624 
5625  // Display service pack (if any) and build number.
5626 
5627  if( osvi.dwMajorVersion == 4 &&
5628  lstrcmpi( osvi.szCSDVersion, "Service Pack 6" ) == 0 )
5629  {
5630  HKEY hKey;
5631  LONG lRet;
5632 
5633  // Test for SP6 versus SP6a.
5634  lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
5635  "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Hotfix\\Q246009",
5636  0, KEY_QUERY_VALUE, &hKey );
5637  if( lRet == ERROR_SUCCESS ) {
5638  snprintf(temp, 512, "Service Pack 6a (Build %d)", osvi.dwBuildNumber & 0xFFFF );
5639  strlcat(strReturn, temp,2048 );
5640  }
5641  else // Windows NT 4.0 prior to SP6a
5642  {
5643  snprintf(temp,512, "%s (Build %d)", osvi.szCSDVersion, osvi.dwBuildNumber & 0xFFFF);
5644  strlcat(strReturn, temp,2048 );
5645  }
5646 
5647  RegCloseKey( hKey );
5648  }
5649  else // not Windows NT 4.0
5650  {
5651  snprintf(temp, 512,"%s (Build %d)", osvi.szCSDVersion, osvi.dwBuildNumber & 0xFFFF);
5652  strlcat(strReturn, temp,2048 );
5653  }
5654 
5655  break;
5656 
5657  // Test for the Windows Me/98/95.
5658  case VER_PLATFORM_WIN32_WINDOWS:
5659 
5660  if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0)
5661  {
5662  strlcpy(strReturn, "Microsoft Windows 95 ",2048);
5663  if (osvi.szCSDVersion[1]=='C' || osvi.szCSDVersion[1]=='B')
5664  strlcat(strReturn, "OSR2 " ,2048);
5665  }
5666 
5667  if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10)
5668  {
5669  strlcpy(strReturn, "Microsoft Windows 98 ",2048);
5670  if ( osvi.szCSDVersion[1]=='A' || osvi.szCSDVersion[1]=='B')
5671  strlcat(strReturn, "SE ",2048 );
5672  }
5673 
5674  if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90)
5675  {
5676  strlcpy(strReturn, "Microsoft Windows Millennium Edition",2048);
5677  }
5678  break;
5679 
5680  case VER_PLATFORM_WIN32s:
5681  strlcpy(strReturn, "Microsoft Win32s",2048);
5682  break;
5683  }
5684  return strReturn;
5685 }
5686 
5687 ////////////////////////////////////////////////////////////////////////////////
5688 /// Use assembly to retrieve the L2 cache information ...
5689 
5690 static int GetL2CacheSize()
5691 {
5692  unsigned nHighestFeatureEx;
5693  int nBuff[4];
5694 
5695  __cpuid(nBuff, 0x80000000);
5696  nHighestFeatureEx = (unsigned)nBuff[0];
5697  // Get cache size
5698  if (nHighestFeatureEx >= 0x80000006) {
5699  __cpuid(nBuff, 0x80000006);
5700  return (((unsigned)nBuff[2])>>16);
5701  }
5702  else return 0;
5703 }
5704 
5705 ////////////////////////////////////////////////////////////////////////////////
5706 /// Get system info for Windows NT.
5707 
5708 static void GetWinNTSysInfo(SysInfo_t *sysinfo)
5709 {
5710  SYSTEM_PERFORMANCE_INFORMATION SysPerfInfo;
5711  SYSTEM_INFO sysInfo;
5712  MEMORYSTATUSEX statex;
5713  OSVERSIONINFO OsVersionInfo;
5714  HKEY hKey;
5715  char szKeyValueString[80];
5716  DWORD szKeyValueDword;
5717  DWORD dwBufLen;
5718  LONG status;
5719  PROCNTQSI NtQuerySystemInformation;
5720 
5721  NtQuerySystemInformation = (PROCNTQSI)GetProcAddress(
5722  GetModuleHandle("ntdll"), "NtQuerySystemInformation");
5723 
5724  if (!NtQuerySystemInformation) {
5725  ::Error("GetWinNTSysInfo",
5726  "Error on GetProcAddress(NtQuerySystemInformation)");
5727  return;
5728  }
5729 
5730  status = NtQuerySystemInformation(SystemPerformanceInformation,
5731  &SysPerfInfo, sizeof(SysPerfInfo),
5732  NULL);
5733  OsVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
5734  GetVersionEx(&OsVersionInfo);
5735  GetSystemInfo(&sysInfo);
5736  statex.dwLength = sizeof(statex);
5737  if (!GlobalMemoryStatusEx(&statex)) {
5738  ::Error("GetWinNTSysInfo", "Error on GlobalMemoryStatusEx()");
5739  return;
5740  }
5741  sysinfo->fCpus = sysInfo.dwNumberOfProcessors;
5742  sysinfo->fPhysRam = (Int_t)(statex.ullTotalPhys >> 20);
5743  sysinfo->fOS = GetWindowsVersion();
5744  sysinfo->fModel = "";
5745  sysinfo->fCpuType = "";
5746  sysinfo->fCpuSpeed = GetCPUSpeed();
5747  sysinfo->fBusSpeed = 0; // bus speed in MHz
5748  sysinfo->fL2Cache = GetL2CacheSize();
5749 
5750  status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System",
5751  0, KEY_QUERY_VALUE, &hKey);
5752  if (status == ERROR_SUCCESS) {
5753  dwBufLen = sizeof(szKeyValueString);
5754  RegQueryValueEx(hKey, "Identifier", NULL, NULL,(LPBYTE)szKeyValueString,
5755  &dwBufLen);
5756  sysinfo->fModel = szKeyValueString;
5757  RegCloseKey (hKey);
5758  }
5759  status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
5760  "Hardware\\Description\\System\\CentralProcessor\\0",
5761  0, KEY_QUERY_VALUE, &hKey);
5762  if (status == ERROR_SUCCESS) {
5763  dwBufLen = sizeof(szKeyValueString);
5764  status = RegQueryValueEx(hKey, "ProcessorNameString", NULL, NULL,
5765  (LPBYTE)szKeyValueString, &dwBufLen);
5766  if (status == ERROR_SUCCESS)
5767  sysinfo->fCpuType = szKeyValueString;
5768  dwBufLen = sizeof(DWORD);
5769  status = RegQueryValueEx(hKey,"~MHz",NULL,NULL,(LPBYTE)&szKeyValueDword,
5770  &dwBufLen);
5771  if ((status == ERROR_SUCCESS) && ((sysinfo->fCpuSpeed <= 0) ||
5772  (sysinfo->fCpuSpeed < (szKeyValueDword >> 1))))
5773  sysinfo->fCpuSpeed = (Int_t)szKeyValueDword;
5774  RegCloseKey (hKey);
5775  }
5776  sysinfo->fCpuType.Remove(TString::kBoth, ' ');
5777  sysinfo->fModel.Remove(TString::kBoth, ' ');
5778 }
5779 
5780 ////////////////////////////////////////////////////////////////////////////////
5781 /// Get CPU stat for Window. Use sampleTime to set the interval over which
5782 /// the CPU load will be measured, in ms (default 1000).
5783 
5784 static void GetWinNTCpuInfo(CpuInfo_t *cpuinfo, Int_t sampleTime)
5785 {
5786  SYSTEM_INFO sysInfo;
5787  Float_t idle_ratio, kernel_ratio, user_ratio, total_ratio;
5788  FILETIME ft_sys_idle, ft_sys_kernel, ft_sys_user, ft_fun_time;
5789  SYSTEMTIME st_fun_time;
5790 
5791  ULARGE_INTEGER ul_sys_idle, ul_sys_kernel, ul_sys_user;
5792  static ULARGE_INTEGER ul_sys_idleold = {0, 0};
5793  static ULARGE_INTEGER ul_sys_kernelold = {0, 0};
5794  static ULARGE_INTEGER ul_sys_userold = {0, 0};
5795  ULARGE_INTEGER ul_sys_idle_diff, ul_sys_kernel_diff, ul_sys_user_diff;
5796 
5797  ULARGE_INTEGER ul_fun_time;
5798  ULARGE_INTEGER ul_fun_timeold = {0, 0};
5799  ULARGE_INTEGER ul_fun_time_diff;
5800 
5801  typedef BOOL (__stdcall *GetSystemTimesProc)( LPFILETIME lpIdleTime,
5802  LPFILETIME lpKernelTime, LPFILETIME lpUserTime );
5803  static GetSystemTimesProc pGetSystemTimes = 0;
5804 
5805  HMODULE hModImagehlp = LoadLibrary( "Kernel32.dll" );
5806  if (!hModImagehlp) {
5807  ::Error("GetWinNTCpuInfo", "Error on LoadLibrary(Kernel32.dll)");
5808  return;
5809  }
5810 
5811  pGetSystemTimes = (GetSystemTimesProc) GetProcAddress( hModImagehlp,
5812  "GetSystemTimes" );
5813  if (!pGetSystemTimes) {
5814  ::Error("GetWinNTCpuInfo", "Error on GetProcAddress(GetSystemTimes)");
5815  return;
5816  }
5817  GetSystemInfo(&sysInfo);
5818 
5819 again:
5820  pGetSystemTimes(&ft_sys_idle,&ft_sys_kernel,&ft_sys_user);
5821  GetSystemTime(&st_fun_time);
5822  SystemTimeToFileTime(&st_fun_time,&ft_fun_time);
5823 
5824  memcpy(&ul_sys_idle, &ft_sys_idle, sizeof(FILETIME));
5825  memcpy(&ul_sys_kernel, &ft_sys_kernel, sizeof(FILETIME));
5826  memcpy(&ul_sys_user, &ft_sys_user, sizeof(FILETIME));
5827  memcpy(&ul_fun_time, &ft_fun_time, sizeof(FILETIME));
5828 
5829  ul_sys_idle_diff.QuadPart = ul_sys_idle.QuadPart -
5830  ul_sys_idleold.QuadPart;
5831  ul_sys_kernel_diff.QuadPart = ul_sys_kernel.QuadPart -
5832  ul_sys_kernelold.QuadPart;
5833  ul_sys_user_diff.QuadPart = ul_sys_user.QuadPart -
5834  ul_sys_userold.QuadPart;
5835 
5836  ul_fun_time_diff.QuadPart = ul_fun_time.QuadPart -
5837  ul_fun_timeold.QuadPart;
5838 
5839  ul_sys_idleold.QuadPart = ul_sys_idle.QuadPart;
5840  ul_sys_kernelold.QuadPart = ul_sys_kernel.QuadPart;
5841  ul_sys_userold.QuadPart = ul_sys_user.QuadPart;
5842 
5843  if (ul_fun_timeold.QuadPart == 0) {
5844  Sleep(sampleTime);
5845  ul_fun_timeold.QuadPart = ul_fun_time.QuadPart;
5846  goto again;
5847  }
5848  ul_fun_timeold.QuadPart = ul_fun_time.QuadPart;
5849 
5850  idle_ratio = (Float_t)(Li2Double(ul_sys_idle_diff)/
5851  Li2Double(ul_fun_time_diff))*100.0;
5852  user_ratio = (Float_t)(Li2Double(ul_sys_user_diff)/
5853  Li2Double(ul_fun_time_diff))*100.0;
5854  kernel_ratio = (Float_t)(Li2Double(ul_sys_kernel_diff)/
5855  Li2Double(ul_fun_time_diff))*100.0;
5856  idle_ratio /= (Float_t)sysInfo.dwNumberOfProcessors;
5857  user_ratio /= (Float_t)sysInfo.dwNumberOfProcessors;
5858  kernel_ratio /= (Float_t)sysInfo.dwNumberOfProcessors;
5859  total_ratio = 100.0 - idle_ratio;
5860 
5861  cpuinfo->fLoad1m = 0; // cpu load average over 1 m
5862  cpuinfo->fLoad5m = 0; // cpu load average over 5 m
5863  cpuinfo->fLoad15m = 0; // cpu load average over 15 m
5864  cpuinfo->fUser = user_ratio; // cpu user load in percentage
5865  cpuinfo->fSys = kernel_ratio; // cpu sys load in percentage
5866  cpuinfo->fTotal = total_ratio; // cpu user+sys load in percentage
5867  cpuinfo->fIdle = idle_ratio; // cpu idle percentage
5868 }
5869 
5870 ////////////////////////////////////////////////////////////////////////////////
5871 /// Get VM stat for Windows NT.
5872 
5873 static void GetWinNTMemInfo(MemInfo_t *meminfo)
5874 {
5875  Long64_t total, used, free, swap_total, swap_used, swap_avail;
5876  MEMORYSTATUSEX statex;
5877  statex.dwLength = sizeof(statex);
5878  if (!GlobalMemoryStatusEx(&statex)) {
5879  ::Error("GetWinNTMemInfo", "Error on GlobalMemoryStatusEx()");
5880  return;
5881  }
5882  used = (Long64_t)(statex.ullTotalPhys - statex.ullAvailPhys);
5883  free = (Long64_t) statex.ullAvailPhys;
5884  total = (Long64_t) statex.ullTotalPhys;
5885 
5886  meminfo->fMemTotal = (Int_t) (total >> 20); // divide by 1024 * 1024
5887  meminfo->fMemUsed = (Int_t) (used >> 20);
5888  meminfo->fMemFree = (Int_t) (free >> 20);
5889 
5890  swap_total = (Long64_t)(statex.ullTotalPageFile - statex.ullTotalPhys);
5891  swap_avail = (Long64_t)(statex.ullAvailPageFile - statex.ullAvailPhys);
5892  swap_used = swap_total - swap_avail;
5893 
5894  meminfo->fSwapTotal = (Int_t) (swap_total >> 20);
5895  meminfo->fSwapUsed = (Int_t) (swap_used >> 20);
5896  meminfo->fSwapFree = (Int_t) (swap_avail >> 20);
5897 }
5898 
5899 ////////////////////////////////////////////////////////////////////////////////
5900 /// Get process info for this process on Windows NT.
5901 
5902 static void GetWinNTProcInfo(ProcInfo_t *procinfo)
5903 {
5905  FILETIME starttime, exittime, kerneltime, usertime;
5906  timeval ru_stime, ru_utime;
5907  ULARGE_INTEGER li;
5908 
5909  typedef BOOL (__stdcall *GetProcessMemoryInfoProc)( HANDLE Process,
5910  PPROCESS_MEMORY_COUNTERS ppsmemCounters, DWORD cb );
5911  static GetProcessMemoryInfoProc pGetProcessMemoryInfo = 0;
5912 
5913  HMODULE hModImagehlp = LoadLibrary( "Psapi.dll" );
5914  if (!hModImagehlp) {
5915  ::Error("GetWinNTProcInfo", "Error on LoadLibrary(Psapi.dll)");
5916  return;
5917  }
5918 
5919  pGetProcessMemoryInfo = (GetProcessMemoryInfoProc) GetProcAddress(
5920  hModImagehlp, "GetProcessMemoryInfo" );
5921  if (!pGetProcessMemoryInfo) {
5922  ::Error("GetWinNTProcInfo",
5923  "Error on GetProcAddress(GetProcessMemoryInfo)");
5924  return;
5925  }
5926 
5927  if ( pGetProcessMemoryInfo( GetCurrentProcess(), &pmc, sizeof(pmc)) ) {
5928  procinfo->fMemResident = pmc.WorkingSetSize / 1024;
5929  procinfo->fMemVirtual = pmc.PagefileUsage / 1024;
5930  }
5931  if ( GetProcessTimes(GetCurrentProcess(), &starttime, &exittime,
5932  &kerneltime, &usertime)) {
5933 
5934  /* Convert FILETIMEs (0.1 us) to struct timeval */
5935  memcpy(&li, &kerneltime, sizeof(FILETIME));
5936  li.QuadPart /= 10L; /* Convert to microseconds */
5937  ru_stime.tv_sec = li.QuadPart / 1000000L;
5938  ru_stime.tv_usec = li.QuadPart % 1000000L;
5939 
5940  memcpy(&li, &usertime, sizeof(FILETIME));
5941  li.QuadPart /= 10L; /* Convert to microseconds */
5942  ru_utime.tv_sec = li.QuadPart / 1000000L;
5943  ru_utime.tv_usec = li.QuadPart % 1000000L;
5944 
5945  procinfo->fCpuUser = (Float_t)(ru_utime.tv_sec) +
5946  ((Float_t)(ru_utime.tv_usec) / 1000000.);
5947  procinfo->fCpuSys = (Float_t)(ru_stime.tv_sec) +
5948  ((Float_t)(ru_stime.tv_usec) / 1000000.);
5949  }
5950 }
5951 
5952 ////////////////////////////////////////////////////////////////////////////////
5953 /// Returns static system info, like OS type, CPU type, number of CPUs
5954 /// RAM size, etc into the SysInfo_t structure. Returns -1 in case of error,
5955 /// 0 otherwise.
5956 
5958 {
5959  if (!info) return -1;
5960  GetWinNTSysInfo(info);
5961  return 0;
5962 }
5963 
5964 ////////////////////////////////////////////////////////////////////////////////
5965 /// Returns cpu load average and load info into the CpuInfo_t structure.
5966 /// Returns -1 in case of error, 0 otherwise. Use sampleTime to set the
5967 /// interval over which the CPU load will be measured, in ms (default 1000).
5968 
5970 {
5971  if (!info) return -1;
5972  GetWinNTCpuInfo(info, sampleTime);
5973  return 0;
5974 }
5975 
5976 ////////////////////////////////////////////////////////////////////////////////
5977 /// Returns ram and swap memory usage info into the MemInfo_t structure.
5978 /// Returns -1 in case of error, 0 otherwise.
5979 
5981 {
5982  if (!info) return -1;
5983  GetWinNTMemInfo(info);
5984  return 0;
5985 }
5986 
5987 ////////////////////////////////////////////////////////////////////////////////
5988 /// Returns cpu and memory used by this process into the ProcInfo_t structure.
5989 /// Returns -1 in case of error, 0 otherwise.
5990 
5992 {
5993  if (!info) return -1;
5994  GetWinNTProcInfo(info);
5995  return 0;
5996 }
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
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:1213
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:851
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:1222
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:1311
#define closesocket(a)
Definition: civetweb.c:275
static char * GetWindowsVersion()
void regexp()
Definition: regexp.C:34
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:344
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:1766
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.
#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:1459
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
TFile * f
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:1294
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:2321
TSignalHandler * RemoveSignalHandler(TSignalHandler *sh)
Remove a signal handler from list of signal handlers.
Float_t fUser
Definition: TSystem.h:180
Bool_t IsValid() const
Definition: TInetAddress.h:80
Int_t fSwapFree
Definition: TSystem.h:196
TPaveText exe(6, 5.5, 12, 8)
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:2509
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
int d
Definition: tornado.py:11
R__EXTERN TFileHandler * gXDisplay
Definition: TSystem.h:546
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:262
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:1996
static const char * what
Definition: stlLoader.cc:6
tuple infile
Definition: mrt.py:15
struct _PROCESS_MEMORY_COUNTERS * PPROCESS_MEMORY_COUNTERS
const char * pwd()
Definition: TSystem.h:411
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
TThread * t[5]
Definition: threadsh1.C:13
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:2207
TString dirName
Definition: demos.C:9
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:2032
#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.
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition: TString.cxx:2308
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:324
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:1056
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.
tuple free
Definition: fildir.py:30
#define Printf
Definition: TGeoToOCC.h:18
TH1F * total
Definition: threadsh2.C:15
char * StrDup(const char *str)
Duplicate the string str.
Definition: TString.cxx:2500
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.
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
void(* SigHandler_t)(ESignals)
Definition: TUnixSystem.h:34
Float_t fCpuSys
Definition: TSystem.h:205
tuple file
Definition: fildir.py:20
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
void select(Int_t replica=1, Int_t color=kGreen)
Definition: runplugin.C:24
#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:1906
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:1055
ClassImp(TMCParticle) void TMCParticle printf(": p=(%7.3f,%7.3f,%9.3f) ;", fPx, fPy, fPz)
void dir(char *path=0)
Definition: rootalias.C:30
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)
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:183
Bool_t(* ThreadMsgFunc_t)(MSG *)
Definition: TWinNTSystem.h:72
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
void(WINAPI * PGNSI)(LPSYSTEM_INFO)
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:453
Long_t fMemResident
Definition: TSystem.h:206
const char * Getenv(const char *name)
Get environment variable.
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