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