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