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 the system's host name.
1270
1272{
1273 if (fHostname == "")
1274 fHostname = std::getenv("COMPUTERNAME");
1275 if (fHostname == "") {
1276 // This requires a DNS query - but we need it for fallback
1277 char hn[64];
1278 DWORD il = sizeof(hn);
1280 fHostname = hn;
1281 }
1282 return fHostname;
1283}
1284
1285////////////////////////////////////////////////////////////////////////////////
1286/// Beep. If freq==0 (the default for TWinNTSystem), use ::MessageBeep.
1287/// Otherwise ::Beep with freq and duration.
1288
1289void TWinNTSystem::DoBeep(Int_t freq /*=-1*/, Int_t duration /*=-1*/) const
1290{
1291 if (freq == 0) {
1292 ::MessageBeep(-1);
1293 return;
1294 }
1295 if (freq < 37) freq = 440;
1296 if (duration < 0) duration = 100;
1298}
1299
1300////////////////////////////////////////////////////////////////////////////////
1301/// Set the (static part of) the event handler func for GUI messages.
1302
1304{
1305 gGUIThreadMsgFunc = func;
1306}
1307
1308////////////////////////////////////////////////////////////////////////////////
1309/// Hook to tell TSystem that the TApplication object has been created.
1310
1312{
1313 // send a dummy message to the GUI thread to kick it into life
1315}
1316
1317
1318//---- EventLoop ---------------------------------------------------------------
1319
1320////////////////////////////////////////////////////////////////////////////////
1321/// Add a file handler to the list of system file handlers. Only adds
1322/// the handler if it is not already in the list of file handlers.
1323
1325{
1327 if (h) {
1328 int fd = h->GetFd();
1329 if (!fd) return;
1330
1331 if (h->HasReadInterest()) {
1332 fReadmask->Set(fd);
1333 }
1334 if (h->HasWriteInterest()) {
1335 fWritemask->Set(fd);
1336 }
1337 }
1338}
1339
1340////////////////////////////////////////////////////////////////////////////////
1341/// Remove a file handler from the list of file handlers. Returns
1342/// the handler or 0 if the handler was not in the list of file handlers.
1343
1345{
1346 if (!h) return nullptr;
1347
1349 if (oh) { // found
1350 fReadmask->Clr(h->GetFd());
1351 fWritemask->Clr(h->GetFd());
1352 }
1353 return oh;
1354}
1355
1356////////////////////////////////////////////////////////////////////////////////
1357/// Add a signal handler to list of system signal handlers. Only adds
1358/// the handler if it is not already in the list of signal handlers.
1359
1361{
1363 ESignals sig = h->GetSignal();
1364
1365 if (sig == kSigInterrupt) {
1368 TIter next(fSignalHandler);
1369
1370 while ((hs = (TSignalHandler*) next())) {
1371 if (hs->GetSignal() == kSigInterrupt)
1373 }
1374 }
1376
1377 // Add our handler to the list of the console handlers
1378 if (set_console)
1380 else
1381 WinNTSignal(h->GetSignal(), SigHandler);
1382}
1383
1384////////////////////////////////////////////////////////////////////////////////
1385/// Remove a signal handler from list of signal handlers. Returns
1386/// the handler or 0 if the handler was not in the list of signal handlers.
1387
1389{
1390 if (!h) return nullptr;
1391
1392 int sig = h->GetSignal();
1393
1394 if (sig = kSigInterrupt) {
1395 Bool_t last = kTRUE;
1397 TIter next(fSignalHandler);
1398
1399 while ((hs = (TSignalHandler*) next())) {
1400 if (hs->GetSignal() == kSigInterrupt)
1401 last = kFALSE;
1402 }
1403 // Remove our handler from the list of the console handlers
1404 if (last)
1406 }
1408}
1409
1410////////////////////////////////////////////////////////////////////////////////
1411/// If reset is true reset the signal handler for the specified signal
1412/// to the default handler, else restore previous behaviour.
1413
1415{
1416 //FIXME!
1417}
1418
1419////////////////////////////////////////////////////////////////////////////////
1420/// Reset signals handlers to previous behaviour.
1421
1423{
1424 //FIXME!
1425}
1426
1427////////////////////////////////////////////////////////////////////////////////
1428/// If ignore is true ignore the specified signal, else restore previous
1429/// behaviour.
1430
1432{
1433 // FIXME!
1434}
1435
1436////////////////////////////////////////////////////////////////////////////////
1437/// Print a stack trace, if gEnv entry "Root.Stacktrace" is unset or 1,
1438/// and if the image helper functions can be found (see InitImagehlpFunctions()).
1439/// The stack trace is printed for each thread; if fgXcptContext is set (e.g.
1440/// because there was an exception) use it to define the current thread's context.
1441/// For each frame in the stack, the frame's module name, the frame's function
1442/// name, and the frame's line number are printed.
1443
1445{
1446 if (!gEnv->GetValue("Root.Stacktrace", 1))
1447 return;
1448
1450
1451 std::cerr.flush();
1452 fflush (stderr);
1453
1454 if (!InitImagehlpFunctions()) {
1455 std::cerr << "No stack trace: cannot find (functions in) dbghelp.dll!" << std::endl;
1456 return;
1457 }
1458
1459 // what system are we on?
1463 switch (sysInfo.wProcessorArchitecture) {
1466 break;
1469 break;
1470 }
1471
1474
1475 if (snapshot == INVALID_HANDLE_VALUE) return;
1476
1478 threadentry.dwSize = sizeof(THREADENTRY32);
1479 if (!::Thread32First(snapshot, &threadentry)) return;
1480
1481 std::cerr << std::endl << "==========================================" << std::endl;
1482 std::cerr << "=============== STACKTRACE ===============" << std::endl;
1483 std::cerr << "==========================================" << std::endl << std::endl;
1484 UInt_t iThread = 0;
1485 do {
1486 if (threadentry.th32OwnerProcessID != currentProcessID)
1487 continue;
1489 FALSE, threadentry.th32ThreadID);
1490 CONTEXT context;
1491 memset(&context, 0, sizeof(CONTEXT));
1492
1493 if (threadentry.th32ThreadID != currentThreadID) {
1494 ::SuspendThread(thread);
1495 context.ContextFlags = CONTEXT_ALL;
1496 ::GetThreadContext(thread, &context);
1497 ::ResumeThread(thread);
1498 } else {
1499 if (fgXcptContext) {
1500 context = *fgXcptContext;
1501 } else {
1502 typedef void (WINAPI *RTLCCTXT)(PCONTEXT);
1504 GetModuleHandle("kernel32.dll"), "RtlCaptureContext");
1505 if (p2RtlCCtxt) {
1506 context.ContextFlags = CONTEXT_ALL;
1507 p2RtlCCtxt(&context);
1508 }
1509 }
1510 }
1511
1512 STACKFRAME64 frame;
1513 ::ZeroMemory(&frame, sizeof(frame));
1514
1515 frame.AddrPC.Mode = AddrModeFlat;
1516 frame.AddrFrame.Mode = AddrModeFlat;
1517 frame.AddrStack.Mode = AddrModeFlat;
1518#if defined(_M_IX86)
1519 frame.AddrPC.Offset = context.Eip;
1520 frame.AddrFrame.Offset = context.Ebp;
1521 frame.AddrStack.Offset = context.Esp;
1522#elif defined(_M_X64)
1523 frame.AddrPC.Offset = context.Rip;
1524 frame.AddrFrame.Offset = context.Rsp;
1525 frame.AddrStack.Offset = context.Rsp;
1526#elif defined(_M_IA64)
1527 frame.AddrPC.Offset = context.StIIP;
1528 frame.AddrFrame.Offset = context.IntSp;
1529 frame.AddrStack.Offset = context.IntSp;
1530 frame.AddrBStore.Offset= context.RsBSP;
1531#else
1532 std::cerr << "Stack traces not supported on your architecture yet." << std::endl;
1533 return;
1534#endif
1535
1537 while (_StackWalk64(machineType, (HANDLE)::GetCurrentProcess(), thread, (LPSTACKFRAME64)&frame,
1540 if (bFirst)
1541 std::cerr << std::endl << "================ Thread " << iThread++ << " ================" << std::endl;
1542 if (!bFirst || threadentry.th32ThreadID != currentThreadID) {
1543 const std::string moduleName = GetModuleName(frame.AddrPC.Offset);
1544 const std::string functionName = GetFunctionName(frame.AddrPC.Offset);
1545 std::cerr << " " << moduleName << functionName << std::endl;
1546 }
1547 bFirst = kFALSE;
1548 }
1549 ::CloseHandle(thread);
1550 } while (::Thread32Next(snapshot, &threadentry));
1551
1552 std::cerr << std::endl << "==========================================" << std::endl;
1553 std::cerr << "============= END STACKTRACE =============" << std::endl;
1554 std::cerr << "==========================================" << std::endl << std::endl;
1555 ::CloseHandle(snapshot);
1557}
1558
1559////////////////////////////////////////////////////////////////////////////////
1560/// Return the bitmap of conditions that trigger a floating point exception.
1561
1563{
1564 Int_t mask = 0;
1566
1567 if (oldmask & _EM_INVALID ) mask |= kInvalid;
1571 if (oldmask & _EM_INEXACT ) mask |= kInexact;
1572
1573 return mask;
1574}
1575
1576////////////////////////////////////////////////////////////////////////////////
1577/// Set which conditions trigger a floating point exception.
1578/// Return the previous set of conditions.
1579
1581{
1582 Int_t old = GetFPEMask();
1583
1584 UInt_t newm = 0;
1585 if (mask & kInvalid ) newm |= _EM_INVALID;
1587 if (mask & kOverflow ) newm |= _EM_OVERFLOW;
1589 if (mask & kInexact ) newm |= _EM_INEXACT;
1590
1591 UInt_t cm = ::_statusfp();
1592 cm &= ~newm;
1593 ::_controlfp(cm , _MCW_EM);
1594
1595 return old;
1596}
1597
1598////////////////////////////////////////////////////////////////////////////////
1599/// process pending events, i.e. DispatchOneEvent(kTRUE)
1600
1605
1606////////////////////////////////////////////////////////////////////////////////
1607/// Dispatch a single event in TApplication::Run() loop
1608
1610{
1611 // check for keyboard events
1612 if (pendingOnly && gGlobalEvent) ::SetEvent(gGlobalEvent);
1613
1615
1616 while (1) {
1617 if (_kbhit()) {
1618 if (gROOT->GetApplication()) {
1620 if (gSplash) { // terminate splash window after first key press
1621 delete gSplash;
1622 gSplash = 0;
1623 }
1624 if (!pendingOnly) {
1625 return;
1626 }
1627 }
1628 }
1629 if (gROOT->IsLineProcessing() && (!gVirtualX || !gVirtualX->IsCmdThread())) {
1630 if (!pendingOnly) {
1631 // yield execution to another thread that is ready to run
1632 // if no other thread is ready, sleep 1 ms before to return
1633 if (gGlobalEvent) {
1636 }
1637 return;
1638 }
1639 }
1640 // first handle any GUI events
1641 if (gXDisplay && !gROOT->IsBatch()) {
1642 if (gXDisplay->Notify()) {
1643 if (!pendingOnly) {
1644 return;
1645 }
1646 }
1647 }
1648
1649 // check for file descriptors ready for reading/writing
1650 if ((fNfd > 0) && fFileHandler && (fFileHandler->GetSize() > 0)) {
1651 if (CheckDescriptors()) {
1652 if (!pendingOnly) {
1653 return;
1654 }
1655 }
1656 }
1657 fNfd = 0;
1658 fReadready->Zero();
1659 fWriteready->Zero();
1660
1661 if (pendingOnly && !pollOnce)
1662 return;
1663
1664 // check synchronous signals
1665 if (fSigcnt > 0 && fSignalHandler->GetSize() > 0) {
1666 if (CheckSignals(kTRUE)) {
1667 if (!pendingOnly) {
1668 return;
1669 }
1670 }
1671 }
1672 fSigcnt = 0;
1673 fSignals->Zero();
1674
1675 // handle past due timers
1676 Long_t nextto;
1677 if (fTimers && fTimers->GetSize() > 0) {
1678 if (DispatchTimers(kTRUE)) {
1679 // prevent timers from blocking the rest types of events
1681 if (nextto > (kItimerResolution>>1) || nextto == -1) {
1682 return;
1683 }
1684 }
1685 }
1686
1687 // if in pendingOnly mode poll once file descriptor activity
1689 if (pendingOnly) {
1690 if (fFileHandler && fFileHandler->GetSize() == 0)
1691 return;
1692 nextto = 0;
1693 pollOnce = kFALSE;
1694 }
1695
1696 if (fReadmask && !fReadmask->GetBits() &&
1697 fWritemask && !fWritemask->GetBits()) {
1698 // yield execution to another thread that is ready to run
1699 // if no other thread is ready, sleep 1 ms before to return
1700 if (!pendingOnly && gGlobalEvent) {
1703 }
1704 return;
1705 }
1706
1709
1711
1712 // serious error has happened -> reset all file descrptors
1713 if ((fNfd < 0) && (fNfd != -2)) {
1714 int rc, i;
1715
1716 for (i = 0; i < fReadmask->GetCount(); i++) {
1717 TFdSet t;
1718 Int_t fd = fReadmask->GetFd(i);
1719 t.Set(fd);
1720 if (fReadmask->IsSet(fd)) {
1721 rc = WinNTSelect(&t, 0, 0);
1722 if (rc < 0 && rc != -2) {
1723 ::SysError("DispatchOneEvent", "select: read error on %d\n", fd);
1724 fReadmask->Clr(fd);
1725 }
1726 }
1727 }
1728
1729 for (i = 0; i < fWritemask->GetCount(); i++) {
1730 TFdSet t;
1731 Int_t fd = fWritemask->GetFd(i);
1732 t.Set(fd);
1733
1734 if (fWritemask->IsSet(fd)) {
1735 rc = WinNTSelect(0, &t, 0);
1736 if (rc < 0 && rc != -2) {
1737 ::SysError("DispatchOneEvent", "select: write error on %d\n", fd);
1738 fWritemask->Clr(fd);
1739 }
1740 }
1741 t.Clr(fd);
1742 }
1743 }
1744 }
1745}
1746
1747////////////////////////////////////////////////////////////////////////////////
1748/// Exit from event loop.
1749
1754
1755//---- handling of system events -----------------------------------------------
1756////////////////////////////////////////////////////////////////////////////////
1757/// Handle and dispatch signals.
1758
1760{
1761 if (sig == kSigInterrupt) {
1762 fSignals->Set(sig);
1763 fSigcnt++;
1764 }
1765 else {
1766 if (gExceptionHandler) {
1767 //sig is ESignal, should it be mapped to the correct signal number?
1768 if (sig == kSigFloatingException) _fpreset();
1770 } else {
1771 if (sig == kSigAbort)
1772 return;
1773 //map to the real signal code + set the
1774 //high order bit to indicate a signal (?)
1775 StackTrace();
1776 if (TROOT::Initialized()) {
1777 ::Throw(sig);
1778 }
1779 }
1780 Abort(-1);
1781 }
1782
1783 // check a-synchronous signals
1784 if (fSigcnt > 0 && fSignalHandler->GetSize() > 0)
1786}
1787
1788////////////////////////////////////////////////////////////////////////////////
1789/// Check if some signals were raised and call their Notify() member.
1790
1792{
1794 Int_t sigdone = -1;
1795 {
1796 TIter next(fSignalHandler);
1797
1798 while (sh = (TSignalHandler*)next()) {
1799 if (sync == sh->IsSync()) {
1800 ESignals sig = sh->GetSignal();
1801 if ((fSignals->IsSet(sig) && sigdone == -1) || sigdone == sig) {
1802 if (sigdone == -1) {
1803 fSignals->Clr(sig);
1804 sigdone = sig;
1805 fSigcnt--;
1806 }
1807 sh->Notify();
1808 }
1809 }
1810 }
1811 }
1812 if (sigdone != -1) return kTRUE;
1813
1814 return kFALSE;
1815}
1816
1817////////////////////////////////////////////////////////////////////////////////
1818/// Check if there is activity on some file descriptors and call their
1819/// Notify() member.
1820
1822{
1823 TFileHandler *fh;
1824 Int_t fddone = -1;
1825 Bool_t read = kFALSE;
1826
1828
1829 while ((fh = (TFileHandler*) it.Next())) {
1830 Int_t fd = fh->GetFd();
1831 if (!fd) continue; // ignore TTermInputHandler
1832
1833 if ((fReadready->IsSet(fd) && fddone == -1) ||
1834 (fddone == fd && read)) {
1835 if (fddone == -1) {
1836 fReadready->Clr(fd);
1837 fddone = fd;
1838 read = kTRUE;
1839 fNfd--;
1840 }
1841 fh->ReadNotify();
1842 }
1843 if ((fWriteready->IsSet(fd) && fddone == -1) ||
1844 (fddone == fd && !read)) {
1845 if (fddone == -1) {
1846 fWriteready->Clr(fd);
1847 fddone = fd;
1848 read = kFALSE;
1849 fNfd--;
1850 }
1851 fh->WriteNotify();
1852 }
1853 }
1854 if (fddone != -1) return kTRUE;
1855
1856 return kFALSE;
1857}
1858
1859//---- Directories -------------------------------------------------------------
1860
1861////////////////////////////////////////////////////////////////////////////////
1862/// Make a file system directory. Returns 0 in case of success and
1863/// -1 if the directory could not be created (either already exists or
1864/// illegal path name).
1865/// If 'recursive' is true, makes parent directories as needed.
1866
1868{
1869 if (recursive) {
1871 if (dirname.Length() == 0) {
1872 // well we should not have to make the root of the file system!
1873 // (and this avoid infinite recursions!)
1874 return 0;
1875 }
1876 if (IsAbsoluteFileName(name)) {
1877 // For some good reason DirName strips off the drive letter
1878 // (if present), we need it to make the directory on the
1879 // right disk, so let's put it back!
1880 const char driveletter = DriveName(name);
1881 if (driveletter) {
1882 dirname.Prepend(":");
1883 dirname.Prepend(driveletter);
1884 }
1885 }
1887 int res = this->mkdir(dirname, kTRUE);
1888 if (res) return res;
1889 }
1891 return -1;
1892 }
1893 }
1894 return MakeDirectory(name);
1895}
1896
1897////////////////////////////////////////////////////////////////////////////////
1898/// Make a WinNT file system directory. Returns 0 in case of success and
1899/// -1 if the directory could not be created (either already exists or
1900/// illegal path name).
1901
1903{
1905 if (helper) {
1906 return helper->MakeDirectory(name);
1907 }
1908 const char *proto = (strstr(name, "file:///")) ? "file://" : "file:";
1909#ifdef WATCOM
1910 // It must be as follows
1911 if (!name) return 0;
1912 return ::mkdir(StripOffProto(name, proto));
1913#else
1914 // but to be in line with TUnixSystem I did like this
1915 if (!name) return 0;
1916 return ::_mkdir(StripOffProto(name, proto));
1917#endif
1918}
1919
1920////////////////////////////////////////////////////////////////////////////////
1921/// Struct used to pass information between OpenDirectory and GetDirEntry in a
1922/// thread safe way (each thread creates a new instance of it).
1923
1925 HANDLE fSearchFile; // HANDLE returned by FindFirstFile and used by FindNextFile
1926 WIN32_FIND_DATA fFindFileData; // Structure to look for files (aka OpenDir under UNIX)
1927 Bool_t fFirstFile{kFALSE}; // Flag used by OpenDirectory/GetDirEntry
1928};
1929
1930////////////////////////////////////////////////////////////////////////////////
1931/// Close a WinNT file system directory.
1932
1934{
1935 if (!dirp)
1936 return;
1937 if (TSystem *helper = FindHelper(0, dirp)) {
1938 helper->FreeDirectory(dirp);
1939 return;
1940 }
1941 auto tsfd = static_cast<FindFileData_t *>(dirp);
1942 ::FindClose(tsfd->fSearchFile);
1943 delete dirp;
1944}
1945
1946////////////////////////////////////////////////////////////////////////////////
1947/// Returns the next directory entry.
1948
1950{
1951 if (!dirp)
1952 return nullptr;
1953 if (TSystem *helper = FindHelper(0, dirp)) {
1954 return helper->GetDirEntry(dirp);
1955 }
1956 auto tsfd = static_cast<FindFileData_t *>(dirp);
1957 if (tsfd->fFirstFile) {
1958 // when calling TWinNTSystem::OpenDirectory(), the fFindFileData
1959 // structure is filled by a call to FindFirstFile().
1960 // So first returns this one, before calling FindNextFile()
1961 tsfd->fFirstFile = kFALSE;
1962 return (const char *)tsfd->fFindFileData.cFileName;
1963 }
1964 if (::FindNextFile(tsfd->fSearchFile, &tsfd->fFindFileData)) {
1965 return (const char *)tsfd->fFindFileData.cFileName;
1966 }
1967 return nullptr;
1968}
1969
1970////////////////////////////////////////////////////////////////////////////////
1971/// Change directory.
1972
1974{
1975 Bool_t ret = (Bool_t) (::chdir(path) == 0);
1976 if (fWdpath != "")
1977 fWdpath = ""; // invalidate path cache
1978 return ret;
1979}
1980
1981////////////////////////////////////////////////////////////////////////////////
1982///
1983/// Inline function to check for a double-backslash at the
1984/// beginning of a string
1985///
1986
1988{
1989 return (psz[0] == TEXT('\\') && psz[1] == TEXT('\\'));
1990}
1991
1992////////////////////////////////////////////////////////////////////////////////
1993/// Returns TRUE if the given string is a UNC path.
1994///
1995/// TRUE
1996/// `\\foo\bar`
1997/// `\\foo` <- careful
1998/// `\\`
1999/// FALSE
2000/// `\foo`
2001/// `foo"`
2002/// `c:\foo`
2003
2005{
2006 return DBL_BSLASH(pszPath);
2007}
2008
2009#pragma data_seg(".text", "CODE")
2010const TCHAR c_szColonSlash[] = TEXT(":\\");
2011#pragma data_seg()
2012
2013////////////////////////////////////////////////////////////////////////////////
2014///
2015/// check if a path is a root
2016///
2017/// returns:
2018/// TRUE for "\" "X:\" "\\foo\asdf" "\\foo\"
2019/// FALSE for others
2020///
2021
2023{
2024 if (!IsDBCSLeadByte(*pPath)) {
2025 if (!lstrcmpi(pPath + 1, c_szColonSlash))
2026 // "X:\" case
2027 return TRUE;
2028 }
2029 if ((*pPath == TEXT('\\')) && (*(pPath + 1) == 0))
2030 // "\" case
2031 return TRUE;
2032 if (DBL_BSLASH(pPath)) {
2033 // smells like UNC name
2034 LPCTSTR p;
2035 int cBackslashes = 0;
2036 for (p = pPath + 2; *p; p = CharNext(p)) {
2037 if (*p == TEXT('\\') && (++cBackslashes > 1))
2038 return FALSE; // not a bare UNC name, therefore not a root dir
2039 }
2040 // end of string with only 1 more backslash
2041 // must be a bare UNC, which looks like a root dir
2042 return TRUE;
2043 }
2044 return FALSE;
2045}
2046
2047////////////////////////////////////////////////////////////////////////////////
2048/// Open a directory. Returns 0 if directory does not exist.
2049
2050void *TWinNTSystem::OpenDirectory(const char *fdir)
2051{
2052 TSystem *helper = FindHelper(fdir);
2053 if (helper) {
2054 return helper->OpenDirectory(fdir);
2055 }
2056
2057 const char *proto = (strstr(fdir, "file:///")) ? "file://" : "file:";
2058 const char *sdir = StripOffProto(fdir, proto);
2059
2060 char *dir = new char[MAX_PATH];
2061 if (IsShortcut(sdir)) {
2062 if (!ResolveShortCut(sdir, dir, MAX_PATH))
2063 strlcpy(dir, sdir,MAX_PATH);
2064 }
2065 else
2066 strlcpy(dir, sdir,MAX_PATH);
2067
2068 size_t nche = strlen(dir)+3;
2069 char *entry = new char[nche];
2070 struct _stati64 finfo;
2071
2072 if(PathIsUNC(dir)) {
2073 strlcpy(entry, dir,nche);
2074 if ((entry[strlen(dir)-1] == '/') || (entry[strlen(dir)-1] == '\\' )) {
2075 entry[strlen(dir)-1] = '\0';
2076 }
2077 if(PathIsRoot(entry)) {
2078 strlcat(entry,"\\",nche);
2079 }
2080 if (_stati64(entry, &finfo) < 0) {
2081 delete [] entry;
2082 delete [] dir;
2083 return nullptr;
2084 }
2085 } else {
2086 strlcpy(entry, dir,nche);
2087 if ((entry[strlen(dir)-1] == '/') || (entry[strlen(dir)-1] == '\\' )) {
2088 if(!PathIsRoot(entry))
2089 entry[strlen(dir)-1] = '\0';
2090 }
2091 if (_stati64(entry, &finfo) < 0) {
2092 delete [] entry;
2093 delete [] dir;
2094 return nullptr;
2095 }
2096 }
2097
2098 if (finfo.st_mode & S_IFDIR) {
2099 strlcpy(entry, dir,nche);
2100 if (!(entry[strlen(dir)-1] == '/' || entry[strlen(dir)-1] == '\\' )) {
2101 strlcat(entry,"\\",nche);
2102 }
2103 if (entry[strlen(dir)-1] == ' ')
2104 entry[strlen(dir)-1] = '\0';
2105 strlcat(entry,"*",nche);
2106
2108 dirp->fSearchFile = ::FindFirstFile(entry, &dirp->fFindFileData);
2109 if (dirp->fSearchFile == INVALID_HANDLE_VALUE) {
2110 delete dirp;
2111 ((TWinNTSystem *)gSystem)->Error( "Unable to find' for reading:", entry);
2112 delete [] entry;
2113 delete [] dir;
2114 return nullptr;
2115 }
2116 dirp->fFirstFile = kTRUE;
2117 delete [] entry;
2118 delete [] dir;
2119 return dirp;
2120 }
2121
2122 delete [] entry;
2123 delete [] dir;
2124 return nullptr;
2125}
2126
2127////////////////////////////////////////////////////////////////////////////////
2128/// Return the working directory for the default drive
2129
2131{
2132 return WorkingDirectory('\0');
2133}
2134
2135//////////////////////////////////////////////////////////////////////////////
2136/// Return the working directory for the default drive
2137
2139{
2140 char *wdpath = GetWorkingDirectory('\0');
2141 std::string cwd;
2142 if (wdpath) {
2143 cwd = wdpath;
2144 free(wdpath);
2145 }
2146 return cwd;
2147}
2148
2149////////////////////////////////////////////////////////////////////////////////
2150/// Return working directory for the selected drive
2151/// driveletter == 0 means return the working durectory for the default drive
2152
2154{
2156 if (wdpath) {
2157 fWdpath = wdpath;
2158
2159 // Make sure the drive letter is upper case
2160 if (fWdpath[1] == ':')
2161 fWdpath[0] = toupper(fWdpath[0]);
2162
2163 free(wdpath);
2164 }
2165 return fWdpath;
2166}
2167
2168//////////////////////////////////////////////////////////////////////////////
2169/// Return working directory for the selected drive (helper function).
2170/// The caller must free the return value.
2171
2173{
2174 char *wdpath = nullptr;
2175 char drive = driveletter ? toupper( driveletter ) - 'A' + 1 : 0;
2176
2177 // don't use cache as user can call chdir() directly somewhere else
2178 //if (fWdpath != "" )
2179 // return fWdpath;
2180
2181 if (!(wdpath = ::_getdcwd( (int)drive, wdpath, kMAXPATHLEN))) {
2182 free(wdpath);
2183 Warning("WorkingDirectory", "getcwd() failed");
2184 return nullptr;
2185 }
2186
2187 return wdpath;
2188}
2189
2190////////////////////////////////////////////////////////////////////////////////
2191/// Return the user's home directory.
2192
2194{
2195 static char mydir[kMAXPATHLEN] = "./";
2197 return mydir;
2198}
2199
2200//////////////////////////////////////////////////////////////////////////////
2201/// Return the user's home directory.
2202
2203std::string TWinNTSystem::GetHomeDirectory(const char *userName) const
2204{
2205 char mydir[kMAXPATHLEN] = "./";
2207 return std::string(mydir);
2208}
2209
2210//////////////////////////////////////////////////////////////////////////////
2211/// Fill buffer with user's home directory.
2212
2214{
2215 const char *h = nullptr;
2216 if (!(h = std::getenv("home"))) h = std::getenv("HOME");
2217
2218 if (h) {
2220 } else {
2221 // for Windows NT HOME might be defined as either $(HOMESHARE)/$(HOMEPATH)
2222 // or $(HOMEDRIVE)/$(HOMEPATH)
2223 h = std::getenv("HOMESHARE");
2224 if (!h) h = std::getenv("HOMEDRIVE");
2225 if (h) {
2227 h = std::getenv("HOMEPATH");
2228 if(h) strlcat(mydir, h,kMAXPATHLEN);
2229 }
2230 // on Windows Vista HOME is usually defined as $(USERPROFILE)
2231 if (!h) {
2232 h = std::getenv("USERPROFILE");
2233 if (h) strlcpy(mydir, h,kMAXPATHLEN);
2234 }
2235 }
2236 // Make sure the drive letter is upper case
2237 if (mydir[1] == ':')
2238 mydir[0] = toupper(mydir[0]);
2239}
2240
2241
2242////////////////////////////////////////////////////////////////////////////////
2243/// Return a user configured or systemwide directory to create
2244/// temporary files in.
2245
2247{
2248 const char *dir = gSystem->Getenv("TEMP");
2249 if (!dir) dir = gSystem->Getenv("TEMPDIR");
2250 if (!dir) dir = gSystem->Getenv("TEMP_DIR");
2251 if (!dir) dir = gSystem->Getenv("TMP");
2252 if (!dir) dir = gSystem->Getenv("TMPDIR");
2253 if (!dir) dir = gSystem->Getenv("TMP_DIR");
2254 if (!dir) dir = "c:\\";
2255
2256 return dir;
2257}
2258
2259////////////////////////////////////////////////////////////////////////////////
2260/// Create a secure temporary file by appending a unique
2261/// 6 letter string to base. The file will be created in
2262/// a standard (system) directory or in the directory
2263/// provided in dir. Optionally one can provide suffix
2264/// append to the final name - like extension ".txt" or ".html".
2265/// The full filename is returned in base
2266/// and a filepointer is returned for safely writing to the file
2267/// (this avoids certain security problems). Returns 0 in case
2268/// of error.
2269
2270FILE *TWinNTSystem::TempFileName(TString &base, const char *dir, const char *suffix)
2271{
2272 char tmpName[MAX_PATH];
2273
2274 auto res = ::GetTempFileName(dir ? dir : TempDirectory(), base.Data(), 0, tmpName);
2275 if (res == 0) {
2276 ::SysError("TempFileName", "Fail to generate temporary file name");
2277 return nullptr;
2278 }
2279
2280 base = tmpName;
2281 if (suffix && *suffix) {
2282 base.Append(suffix);
2283
2284 if (!AccessPathName(base, kFileExists)) {
2285 ::SysError("TempFileName", "Temporary file %s already exists", base.Data());
2286 Unlink(tmpName);
2287 return nullptr;
2288 }
2289
2290 auto res2 = Rename(tmpName, base.Data());
2291 if (res2 != 0) {
2292 ::SysError("TempFileName", "Fail to rename temporary file to %s", base.Data());
2293 Unlink(tmpName);
2294 return nullptr;
2295 }
2296 }
2297
2298 FILE *fp = fopen(base.Data(), "w+");
2299
2300 if (!fp) ::SysError("TempFileName", "error opening %s", base.Data());
2301
2302 return fp;
2303}
2304
2305//---- Paths & Files -----------------------------------------------------------
2306
2307////////////////////////////////////////////////////////////////////////////////
2308/// Get list of volumes (drives) mounted on the system.
2309/// The returned TList must be deleted by the user using "delete".
2310
2312{
2314 UInt_t type;
2316 char szFs[32];
2317
2318 if (!opt || !opt[0]) {
2319 return 0;
2320 }
2321
2322 // prevent the system dialog box to pop-up if a drive is empty
2324 TList *drives = new TList();
2325 drives->SetOwner();
2326 // Save current drive
2327 curdrive = _getdrive();
2328 if (strstr(opt, "cur")) {
2329 *szFs='\0';
2330 sDrive.Form("%c:", (curdrive + 'A' - 1));
2331 sType.Form("Unknown Drive (%s)", sDrive.Data());
2332 ::GetVolumeInformation(Form("%s\\", sDrive.Data()), NULL, 0, NULL, NULL,
2333 NULL, (LPSTR)szFs, 32);
2334 type = ::GetDriveType(sDrive.Data());
2335 switch (type) {
2336 case DRIVE_UNKNOWN:
2337 case DRIVE_NO_ROOT_DIR:
2338 break;
2339 case DRIVE_REMOVABLE:
2340 sType.Form("Removable Disk (%s)", sDrive.Data());
2341 break;
2342 case DRIVE_FIXED:
2343 sType.Form("Local Disk (%s)", sDrive.Data());
2344 break;
2345 case DRIVE_REMOTE:
2346 sType.Form("Network Drive (%s) (%s)", szFs, sDrive.Data());
2347 break;
2348 case DRIVE_CDROM:
2349 sType.Form("CD/DVD Drive (%s)", sDrive.Data());
2350 break;
2351 case DRIVE_RAMDISK:
2352 sType.Form("RAM Disk (%s)", sDrive.Data());
2353 break;
2354 }
2355 drives->Add(new TNamed(sDrive.Data(), sType.Data()));
2356 }
2357 else if (strstr(opt, "all")) {
2358 TCHAR szTemp[512];
2359 szTemp[0] = '\0';
2360 if (::GetLogicalDriveStrings(511, szTemp)) {
2361 TCHAR szDrive[3] = TEXT(" :");
2362 TCHAR* p = szTemp;
2363 do {
2364 // Copy the drive letter to the template string
2365 *szDrive = *p;
2366 *szFs='\0';
2367 sDrive.Form("%s", szDrive);
2368 // skip floppy drives, to avoid accessing them each time...
2369 if ((sDrive == "A:") || (sDrive == "B:")) {
2370 while (*p++);
2371 continue;
2372 }
2373 sType.Form("Unknown Drive (%s)", sDrive.Data());
2374 ::GetVolumeInformation(Form("%s\\", sDrive.Data()), NULL, 0, NULL,
2375 NULL, NULL, (LPSTR)szFs, 32);
2376 type = ::GetDriveType(sDrive.Data());
2377 switch (type) {
2378 case DRIVE_UNKNOWN:
2379 case DRIVE_NO_ROOT_DIR:
2380 break;
2381 case DRIVE_REMOVABLE:
2382 sType.Form("Removable Disk (%s)", sDrive.Data());
2383 break;
2384 case DRIVE_FIXED:
2385 sType.Form("Local Disk (%s)", sDrive.Data());
2386 break;
2387 case DRIVE_REMOTE:
2388 sType.Form("Network Drive (%s) (%s)", szFs, sDrive.Data());
2389 break;
2390 case DRIVE_CDROM:
2391 sType.Form("CD/DVD Drive (%s)", sDrive.Data());
2392 break;
2393 case DRIVE_RAMDISK:
2394 sType.Form("RAM Disk (%s)", sDrive.Data());
2395 break;
2396 }
2397 drives->Add(new TNamed(sDrive.Data(), sType.Data()));
2398 // Go to the next NULL character.
2399 while (*p++);
2400 } while (*p); // end of string
2401 }
2402 }
2403 // restore previous error mode
2405 return drives;
2406}
2407
2408////////////////////////////////////////////////////////////////////////////////
2409/// Return the directory name in pathname. DirName of c:/user/root is /user.
2410/// It creates output with 'new char []' operator. Returned string has to
2411/// be deleted.
2412
2413const char *TWinNTSystem::DirName(const char *pathname)
2414{
2416 return fDirNameBuffer.c_str();
2417}
2418
2419////////////////////////////////////////////////////////////////////////////////
2420/// Return the directory name in pathname. DirName of c:/user/root is /user.
2421/// DirName of c:/user/root/ is /user/root.
2422
2424{
2425 // Create a buffer to keep the path name
2426 if (pathname) {
2427 if (strchr(pathname, '/') || strchr(pathname, '\\')) {
2428 const char *rslash = strrchr(pathname, '/');
2429 const char *bslash = strrchr(pathname, '\\');
2430 const char *r = std::max(rslash, bslash);
2431 const char *ptr = pathname;
2432 while (ptr <= r) {
2433 if (*ptr == ':') {
2434 // Windows path may contain a drive letter
2435 // For NTFS ":" may be a "stream" delimiter as well
2436 pathname = ptr + 1;
2437 break;
2438 }
2439 ptr++;
2440 }
2441 int len = r - pathname;
2442 if (len > 0)
2443 return TString(pathname, len);
2444 }
2445 }
2446 return "";
2447}
2448
2449////////////////////////////////////////////////////////////////////////////////
2450/// Return the drive letter in pathname. DriveName of 'c:/user/root' is 'c'
2451///
2452/// Input:
2453/// - pathname - the string containing file name
2454///
2455/// Return:
2456/// - Letter representing the drive letter in the file name
2457/// - The current drive if the pathname has no drive assigment
2458/// - 0 if pathname is an empty string or uses UNC syntax
2459///
2460/// Note:
2461/// It doesn't check whether pathname represents a 'real' filename.
2462/// This subroutine looks for 'single letter' followed by a ':'.
2463
2464const char TWinNTSystem::DriveName(const char *pathname)
2465{
2466 if (!pathname) return 0;
2467 if (!pathname[0]) return 0;
2468
2469 const char *lpchar;
2470 lpchar = pathname;
2471
2472 // Skip blanks
2473 while(*lpchar == ' ') lpchar++;
2474
2475 if (isalpha((int)*lpchar) && *(lpchar+1) == ':') {
2476 return *lpchar;
2477 }
2478 // Test UNC syntax
2479 if ( (*lpchar == '\\' || *lpchar == '/' ) &&
2480 (*(lpchar+1) == '\\' || *(lpchar+1) == '/') ) return 0;
2481
2482 // return the current drive
2483 return DriveName(WorkingDirectory());
2484}
2485
2486////////////////////////////////////////////////////////////////////////////////
2487/// Return true if dir is an absolute pathname.
2488
2490{
2491 if (dir) {
2492 int idx = 0;
2493 if (strchr(dir,':')) idx = 2;
2494 return (dir[idx] == '/' || dir[idx] == '\\');
2495 }
2496 return kFALSE;
2497}
2498
2499////////////////////////////////////////////////////////////////////////////////
2500/// Convert a pathname to a unix pathname. E.g. from `\user\root` to `/user/root`.
2501/// General rules for applications creating names for directories and files or
2502/// processing names supplied by the user include the following:
2503///
2504/// * Use any character in the current code page for a name, but do not use
2505/// a path separator, a character in the range 0 through 31, or any character
2506/// explicitly disallowed by the file system. A name can contain characters
2507/// in the extended character set (128-255).
2508/// * Use the backslash (\‍), the forward slash (/), or both to separate
2509/// components in a path. No other character is acceptable as a path separator.
2510/// * Use a period (.) as a directory component in a path to represent the
2511/// current directory.
2512/// * Use two consecutive periods (..) as a directory component in a path to
2513/// represent the parent of the current directory.
2514/// * Use a period (.) to separate components in a directory name or filename.
2515/// * Do not use the following characters in directory names or filenames, because
2516/// they are reserved for Windows:
2517/// < > : " / \ |
2518/// * Do not use reserved words, such as aux, con, and prn, as filenames or
2519/// directory names.
2520/// * Process a path as a null-terminated string. The maximum length for a path
2521/// is given by MAX_PATH.
2522/// * Do not assume case sensitivity. Consider names such as OSCAR, Oscar, and
2523/// oscar to be the same.
2524
2525const char *TWinNTSystem::UnixPathName(const char *name)
2526{
2527 const int kBufSize = 1024;
2528 TTHREAD_TLS_ARRAY(char, kBufSize, temp);
2529
2530 strlcpy(temp, name, kBufSize);
2531 char *currentChar = temp;
2532
2533 // This can not change the size of the string.
2534 while (*currentChar != '\0') {
2535 if (*currentChar == '\\') *currentChar = '/';
2536 currentChar++;
2537 }
2538 return temp;
2539}
2540
2541////////////////////////////////////////////////////////////////////////////////
2542/// Returns FALSE if one can access a file using the specified access mode.
2543/// Mode is the same as for the WinNT access(2) function.
2544/// Attention, bizarre convention of return value!!
2545
2547{
2548 TSystem *helper = FindHelper(path);
2549 if (helper)
2550 return helper->AccessPathName(path, mode);
2551
2552 // prevent the system dialog box to pop-up if a drive is empty
2555 // cannot test on exe - use read instead
2557 const char *proto = (strstr(path, "file:///")) ? "file://" : "file:";
2558 if (::_access(StripOffProto(path, proto), mode) == 0) {
2559 // restore previous error mode
2561 return kFALSE;
2562 }
2564 // restore previous error mode
2566 return kTRUE;
2567}
2568
2569////////////////////////////////////////////////////////////////////////////////
2570/// Returns TRUE if the url in 'path' points to the local file system.
2571/// This is used to avoid going through the NIC card for local operations.
2572
2574{
2575 TSystem *helper = FindHelper(path);
2576 if (helper)
2577 return helper->IsPathLocal(path);
2578
2579 return TSystem::IsPathLocal(path);
2580}
2581
2582////////////////////////////////////////////////////////////////////////////////
2583/// Concatenate a directory and a file name.
2584
2585const char *TWinNTSystem::PrependPathName(const char *dir, TString& name)
2586{
2587 if (name == ".") name = "";
2588 if (dir && dir[0]) {
2589 // Test whether the last symbol of the directory is a separator
2590 char last = dir[strlen(dir) - 1];
2591 if (last != '/' && last != '\\') {
2592 name.Prepend('\\');
2593 }
2594 name.Prepend(dir);
2595 name.ReplaceAll("/", "\\");
2596 }
2597 return name.Data();
2598}
2599
2600////////////////////////////////////////////////////////////////////////////////
2601/// Copy a file. If overwrite is true and file already exists the
2602/// file will be overwritten. Returns 0 when successful, -1 in case
2603/// of failure, -2 in case the file already exists and overwrite was false.
2604
2605int TWinNTSystem::CopyFile(const char *f, const char *t, Bool_t overwrite)
2606{
2607 if (AccessPathName(f, kReadPermission)) return -1;
2608 if (!AccessPathName(t) && !overwrite) return -2;
2609
2610 Bool_t ret = ::CopyFileA(f, t, kFALSE);
2611
2612 if (!ret) return -1;
2613 return 0;
2614}
2615
2616////////////////////////////////////////////////////////////////////////////////
2617/// Rename a file. Returns 0 when successful, -1 in case of failure.
2618
2619int TWinNTSystem::Rename(const char *f, const char *t)
2620{
2621 int ret = std::rename(f, t);
2623 return ret;
2624}
2625
2626////////////////////////////////////////////////////////////////////////////////
2627/// Get info about a file. Info is returned in the form of a FileStat_t
2628/// structure (see TSystem.h).
2629/// The function returns 0 in case of success and 1 if the file could
2630/// not be stat'ed.
2631
2632int TWinNTSystem::GetPathInfo(const char *path, FileStat_t &buf)
2633{
2634 TSystem *helper = FindHelper(path);
2635 if (helper)
2636 return helper->GetPathInfo(path, buf);
2637
2638 struct _stati64 sbuf;
2639
2640 // Remove trailing backslashes
2641 const char *proto = (strstr(path, "file:///")) ? "file://" : "file:";
2642 char *newpath = StrDup(StripOffProto(path, proto));
2643 size_t l = strlen(newpath);
2644 while (l > 1) {
2645 if (newpath[--l] != '\\' || newpath[--l] != '/') {
2646 break;
2647 }
2648 newpath[l] = '\0';
2649 }
2650
2651 if (newpath && ::_stati64(newpath, &sbuf) >= 0) {
2652
2653 buf.fDev = sbuf.st_dev;
2654 buf.fIno = sbuf.st_ino;
2655 buf.fMode = sbuf.st_mode;
2656 buf.fUid = sbuf.st_uid;
2657 buf.fGid = sbuf.st_gid;
2658 buf.fSize = sbuf.st_size;
2659 buf.fMtime = sbuf.st_mtime;
2660 buf.fIsLink = IsShortcut(newpath); // kFALSE;
2661
2662 char *lpath = new char[MAX_PATH];
2663 if (IsShortcut(newpath)) {
2664 struct _stati64 sbuf2;
2666 if (::_stati64(lpath, &sbuf2) >= 0) {
2667 buf.fMode = sbuf2.st_mode;
2668 }
2669 }
2670 }
2671 delete [] lpath;
2672
2673 delete [] newpath;
2674 return 0;
2675 }
2676 delete [] newpath;
2677 return 1;
2678}
2679
2680////////////////////////////////////////////////////////////////////////////////
2681/// Get info about a file system: id, bsize, bfree, blocks.
2682/// Id is file system type (machine dependend, see statfs())
2683/// Bsize is block size of file system
2684/// Blocks is total number of blocks in file system
2685/// Bfree is number of free blocks in file system
2686/// The function returns 0 in case of success and 1 if the file system could
2687/// not be stat'ed.
2688
2689int TWinNTSystem::GetFsInfo(const char *path, Long_t *id, Long_t *bsize,
2691{
2692 // address of root directory of the file system
2693 LPCTSTR lpRootPathName = path;
2694
2695 // address of name of the volume
2697 DWORD nVolumeNameSize = 0;
2698
2699 DWORD volumeSerialNumber; // volume serial number
2700 DWORD maximumComponentLength; // system's maximum filename length
2701
2702 // file system flags
2703 DWORD fileSystemFlags;
2704
2705 // address of name of file system
2706 char fileSystemNameBuffer[512];
2708
2709 // prevent the system dialog box to pop-up if the drive is empty
2717 // restore previous error mode
2719 return 1;
2720 }
2721
2722 const char *fsNames[] = { "FAT", "NTFS" };
2723 int i;
2724 for (i = 0; i < 2; i++) {
2726 break;
2727 }
2728 *id = i;
2729
2730 DWORD sectorsPerCluster; // # sectors per cluster
2731 DWORD bytesPerSector; // # bytes per sector
2732 DWORD numberOfFreeClusters; // # free clusters
2733 DWORD totalNumberOfClusters; // # total of clusters
2734
2740 // restore previous error mode
2742 return 1;
2743 }
2744 // restore previous error mode
2746
2750
2751 return 0;
2752}
2753
2754////////////////////////////////////////////////////////////////////////////////
2755/// Create a link from file1 to file2.
2756
2757int TWinNTSystem::Link(const char *from, const char *to)
2758{
2759 struct _stati64 finfo;
2760 char winDrive[256];
2761 char winDir[256];
2762 char winName[256];
2763 char winExt[256];
2764 char linkname[1024];
2767 DWORD dwRet = 0;
2768
2771
2772 HMODULE hModImagehlp = LoadLibrary( "Kernel32.dll" );
2773 if (!hModImagehlp)
2774 return -1;
2775
2776#ifdef _UNICODE
2778#else
2780#endif
2781 if (!_CreateHardLink)
2782 return -1;
2783
2784 dwRet = GetFullPathName(from, sizeof(szPath) / sizeof(TCHAR),
2786
2787 if (_stati64(szPath, &finfo) < 0)
2788 return -1;
2789
2790 if (finfo.st_mode & S_IFDIR)
2791 return -1;
2792
2793 snprintf(linkname,1024,"%s",to);
2795 if ((!winDrive[0] ) &&
2796 (!winDir[0] )) {
2798 snprintf(linkname,1024,"%s\\%s\\%s", winDrive, winDir, to);
2799 }
2800 else if (!winDrive[0]) {
2802 snprintf(linkname,1024,"%s\\%s", winDrive, to);
2803 }
2804
2806 return -1;
2807
2808 return 0;
2809}
2810
2811////////////////////////////////////////////////////////////////////////////////
2812/// Create a symlink from file1 to file2. Returns 0 when successful,
2813/// -1 in case of failure.
2814
2815int TWinNTSystem::Symlink(const char *from, const char *to)
2816{
2817 HRESULT hRes; /* Returned COM result code */
2818 IShellLink* pShellLink; /* IShellLink object pointer */
2819 IPersistFile* pPersistFile; /* IPersistFile object pointer */
2820 WCHAR wszLinkfile[MAX_PATH]; /* pszLinkfile as Unicode string */
2821 int iWideCharsWritten; /* Number of wide characters written */
2822 DWORD dwRet = 0;
2825
2827 if ((from == NULL) || (!from[0]) || (to == NULL) ||
2828 (!to[0]))
2829 return -1;
2830
2831 // Make typedefs for some ole32.dll functions so that we can use them
2832 // with GetProcAddress
2835 typedef void (__stdcall *COUNINITIALIZEPROC)( void );
2839
2840 HMODULE hModImagehlp = LoadLibrary( "ole32.dll" );
2841 if (!hModImagehlp)
2842 return -1;
2843
2845 if (!_CoInitialize)
2846 return -1;
2848 if (!_CoUninitialize)
2849 return -1;
2851 if (!_CoCreateInstance)
2852 return -1;
2853
2854 TString linkname(to);
2855 if (!linkname.EndsWith(".lnk"))
2856 linkname.Append(".lnk");
2857
2859
2860 // Retrieve the full path and file name of a specified file
2861 dwRet = GetFullPathName(from, sizeof(szPath) / sizeof(TCHAR),
2865 if (SUCCEEDED(hRes)) {
2866 // Set the fields in the IShellLink object
2867 hRes = pShellLink->SetPath(szPath);
2868 // Use the IPersistFile object to save the shell link
2869 hRes = pShellLink->QueryInterface(IID_IPersistFile, (void **)&pPersistFile);
2870 if (SUCCEEDED(hRes)){
2874 pPersistFile->Release();
2875 }
2876 pShellLink->Release();
2877 }
2879 return 0;
2880}
2881
2882////////////////////////////////////////////////////////////////////////////////
2883/// Unlink, i.e. remove, a file or directory.
2884///
2885/// If the file is currently open by the current or another process Windows does not allow the file to be deleted and
2886/// the operation is a no-op.
2887
2889{
2891 if (helper)
2892 return helper->Unlink(name);
2893
2894 struct _stati64 finfo;
2895
2896 if (_stati64(name, &finfo) < 0) {
2897 return -1;
2898 }
2899
2900 if (finfo.st_mode & S_IFDIR) {
2901 return ::_rmdir(name);
2902 } else {
2903 return ::_unlink(name);
2904 }
2905}
2906
2907////////////////////////////////////////////////////////////////////////////////
2908/// Make descriptor fd non-blocking.
2909
2911{
2912 if (::ioctlsocket(fd, FIONBIO, (u_long *)1) == SOCKET_ERROR) {
2913 ::SysError("SetNonBlock", "ioctlsocket");
2914 return -1;
2915 }
2916 return 0;
2917}
2918
2919// expand the metacharacters as in the shell
2920
2921static const char
2922 *shellMeta = "~*[]{}?$%",
2923 *shellStuff = "(){}<>\"'",
2925
2926////////////////////////////////////////////////////////////////////////////////
2927/// Expand a pathname getting rid of special shell characaters like ~.$, etc.
2928
2930{
2931 const char *patbuf = (const char *)patbuf0;
2932 const char *p;
2933 char *cmd = nullptr;
2934 char *q;
2935
2936 // We do want the messages from the gROOT initialization
2937 // So let's force it rather than having as a side effect of the
2938 // TUrl construction.
2940 (void)gROOT;
2941
2943 gErrorIgnoreLevel = kFatal; // Explicitly remove all messages
2944 if (patbuf0.BeginsWith("\\")) {
2945 const char driveletter = DriveName(patbuf);
2946 if (driveletter) {
2947 patbuf0.Prepend(":");
2948 patbuf0.Prepend(driveletter);
2949 }
2950 }
2952 TString proto = urlpath.GetProtocol();
2954 if (!proto.EqualTo("file")) // don't expand urls!!!
2955 return kFALSE;
2956
2957 // skip the "file:" protocol, if any
2958 if (patbuf0.BeginsWith("file:"))
2959 patbuf += 5;
2960
2961 // skip leading blanks
2962 while (*patbuf == ' ') {
2963 patbuf++;
2964 }
2965
2966 // skip leading ':'
2967 while (*patbuf == ':') {
2968 patbuf++;
2969 }
2970
2971 // skip leading ';'
2972 while (*patbuf == ';') {
2973 patbuf++;
2974 }
2975
2976 // Transform a Unix list of directories into a Windows list
2977 // by changing the separator from ':' into ';'
2978 for (q = (char*)patbuf; *q; q++) {
2979 if ( *q == ':' ) {
2980 // We are avoiding substitution in the case of
2981 // ....;c:.... and of ...;root:/... where root can be any url protocol
2982 if ( (((q-2)>patbuf) && ( (*(q-2)!=';') || !isalpha(*(q-1)) )) &&
2983 *(q+1)!='/' ) {
2984 *q=';';
2985 }
2986 }
2987 }
2988 // any shell meta characters ?
2989 for (p = patbuf; *p; p++) {
2990 if (strchr(shellMeta, *p)) {
2991 goto needshell;
2992 }
2993 }
2994 return kFALSE;
2995
2996needshell:
2997
2998 // Because (problably) we built with cygwin, the path name like:
2999 // LOCALS~1\\Temp
3000 // gets extended to
3001 // LOCALSc:\\Devel
3002 // The most likely cause is that '~' is used with Unix semantic of the
3003 // home directory (and it also cuts the path short after ... who knows why!)
3004 // So we need to detect this case and prevents its expansion :(.
3005
3006 char replacement[4];
3007
3008 // intentionally a non visible, unlikely character
3009 for (int k = 0; k<3; k++) replacement[k] = 0x1;
3010
3011 replacement[3] = 0x0;
3012 Ssiz_t pos = 0;
3013 TRegexp TildaNum = "~[0-9]";
3014
3015 while ( (pos = patbuf0.Index(TildaNum,pos)) != kNPOS ) {
3016 patbuf0.Replace(pos, 1, replacement);
3017 }
3018
3019 // escape shell quote characters
3020 // EscChar(patbuf, stuffedPat, sizeof(stuffedPat), shellStuff, shellEscape);
3023 patbuf0.Data(), // pointer to string with environment variables
3024 cmd, // pointer to string with expanded environment variables
3025 0 // maximum characters in expanded string
3026 );
3027 if (lbuf > 0) {
3028 cmd = new char[lbuf+1];
3030 patbuf0.Data(), // pointer to string with environment variables
3031 cmd, // pointer to string with expanded environment variables
3032 lbuf // maximum characters in expanded string
3033 );
3034 patbuf0 = cmd;
3035 patbuf0.ReplaceAll(replacement, "~");
3036 delete [] cmd;
3037 return kFALSE;
3038 }
3039 return kTRUE;
3040}
3041
3042////////////////////////////////////////////////////////////////////////////////
3043/// Expand a pathname getting rid of special shell characaters like ~.$, etc.
3044/// User must delete returned string.
3045
3046char *TWinNTSystem::ExpandPathName(const char *path)
3047{
3048 char newpath[MAX_PATH];
3049 if (IsShortcut(path)) {
3050 if (!ResolveShortCut(path, newpath, MAX_PATH))
3051 strlcpy(newpath, path, MAX_PATH);
3052 }
3053 else
3054 strlcpy(newpath, path, MAX_PATH);
3057 return nullptr;
3058
3059 return StrDup(patbuf.Data());
3060}
3061
3062////////////////////////////////////////////////////////////////////////////////
3063/// Set the file permission bits. Returns -1 in case or error, 0 otherwise.
3064/// On windows mode can only be a combination of "user read" (0400),
3065/// "user write" (0200) or "user read | user write" (0600). Any other value
3066/// for mode are ignored.
3067
3068int TWinNTSystem::Chmod(const char *file, UInt_t mode)
3069{
3070 return ::_chmod(file, mode);
3071}
3072
3073////////////////////////////////////////////////////////////////////////////////
3074/// Set the process file creation mode mask.
3075
3077{
3078 return ::umask(mask);
3079}
3080
3081////////////////////////////////////////////////////////////////////////////////
3082/// Set a files modification and access times. If actime = 0 it will be
3083/// set to the modtime. Returns 0 on success and -1 in case of error.
3084
3085int TWinNTSystem::Utime(const char *file, Long_t modtime, Long_t actime)
3086{
3087 if (AccessPathName(file, kWritePermission)) {
3088 Error("Utime", "need write permission for %s to change utime", file);
3089 return -1;
3090 }
3091 if (!actime) actime = modtime;
3092
3093 struct utimbuf t;
3094 t.actime = (time_t)actime;
3095 t.modtime = (time_t)modtime;
3096 return ::utime(file, &t);
3097}
3098
3099////////////////////////////////////////////////////////////////////////////////
3100/// Find location of file in a search path.
3101/// User must delete returned string. Returns 0 in case file is not found.
3102
3104{
3105 // Windows cannot check on execution mode - all we can do is kReadPermission
3108
3109 // Expand parameters
3110
3112 // Check whether this infile has the absolute path first
3113 if (IsAbsoluteFileName(infile.Data()) ) {
3114 if (!AccessPathName(infile.Data(), mode))
3115 return infile.Data();
3116 infile = "";
3117 return nullptr;
3118 }
3121
3122 // Need to use Windows delimiters
3123 Int_t lastDelim = -1;
3124 for(int i=0; i < exsearch.Length(); ++i) {
3125 switch( exsearch[i] ) {
3126 case ':':
3127 // Replace the ':' unless there are after a disk suffix (aka ;c:\mydirec...)
3128 if (i-lastDelim!=2) exsearch[i] = ';';
3129 lastDelim = i;
3130 break;
3131 case ';': lastDelim = i; break;
3132 }
3133 }
3134
3135 // Check access
3136 struct stat finfo;
3137 char name[kMAXPATHLEN];
3138 char *lpFilePart = nullptr;
3139 if (::SearchPath(exsearch.Data(), infile.Data(), NULL, kMAXPATHLEN, name, &lpFilePart) &&
3140 ::access(name, mode) == 0 && stat(name, &finfo) == 0 &&
3141 finfo.st_mode & S_IFREG) {
3142 if (gEnv->GetValue("Root.ShowPath", 0)) {
3143 Printf("Which: %s = %s", infile, name);
3144 }
3145 infile = name;
3146 return infile.Data();
3147 }
3148 infile = "";
3149 return nullptr;
3150}
3151
3152//---- Users & Groups ----------------------------------------------------------
3153
3154////////////////////////////////////////////////////////////////////////////////
3155/// Collect local users and groups accounts information
3156
3158{
3159 // Net* API functions allowed and OS is Windows NT/2000/XP
3160 if ((gEnv->GetValue("WinNT.UseNetAPI", 0)) && (::GetVersion() < 0x80000000)) {
3161 fActUser = -1;
3162 fNbGroups = fNbUsers = 0;
3163 HINSTANCE netapi = ::LoadLibrary("netapi32.DLL");
3164 if (!netapi) return kFALSE;
3165
3166 p2NetApiBufferFree = (pfn1)::GetProcAddress(netapi, "NetApiBufferFree");
3167 p2NetUserGetInfo = (pfn2)::GetProcAddress(netapi, "NetUserGetInfo");
3168 p2NetLocalGroupGetMembers = (pfn3)::GetProcAddress(netapi, "NetLocalGroupGetMembers");
3169 p2NetLocalGroupEnum = (pfn4)::GetProcAddress(netapi, "NetLocalGroupEnum");
3170
3173
3174 GetNbGroups();
3175
3176 fGroups = (struct group *)calloc(fNbGroups, sizeof(struct group));
3177 for(int i=0;i<fNbGroups;i++) {
3178 fGroups[i].gr_mem = (char **)calloc(fNbUsers, sizeof (char*));
3179 }
3180 fPasswords = (struct passwd *)calloc(fNbUsers, sizeof(struct passwd));
3181
3182 CollectGroups();
3184 }
3186 return kTRUE;
3187}
3188
3189////////////////////////////////////////////////////////////////////////////////
3190
3192{
3194 LPBYTE Data = NULL;
3195 DWORD Index = 0, Total = 0;
3198 WCHAR wszGroupName[256];
3199 int iRetOp = 0;
3200 DWORD dwLastError = 0;
3201
3203 (UINT)CP_ACP, // code page
3204 (DWORD)MB_PRECOMPOSED, // character-type options
3205 (LPCSTR)lpszGroupName, // address of string to map
3206 (int)-1, // number of bytes in string
3207 (LPWSTR)wszGroupName, // address of wide-character buffer
3208 (int)sizeof(wszGroupName) ); // size of buffer
3209
3210 if (iRetOp == 0) {
3212 if (Data)
3213 p2NetApiBufferFree(Data);
3214 return FALSE;
3215 }
3216
3217 // The NetLocalGroupGetMembers() API retrieves a list of the members
3218 // of a particular local group.
3220 &Data, 8192, &Index, &Total, &ResumeHandle );
3221
3222 if (NetStatus != NERR_Success || Data == NULL) {
3224
3226 // This usually means that the current Group has no members.
3227 // We call NetLocalGroupGetMembers() again.
3228 // This time, we set the level to 0.
3229 // We do this just to confirm that the number of members in
3230 // this group is zero.
3232 &Data, 8192, &Index, &Total, &ResumeHandle );
3233 }
3234
3235 if (Data)
3236 p2NetApiBufferFree(Data);
3237 return FALSE;
3238 }
3239
3240 fNbUsers += Total;
3242
3243 if (Data)
3244 p2NetApiBufferFree(Data);
3245
3246 return TRUE;
3247}
3248
3249////////////////////////////////////////////////////////////////////////////////
3250
3252{
3254 LPBYTE Data = NULL;
3255 DWORD Index = 0, Total = 0, i;
3258 char szAnsiName[256];
3259 DWORD dwLastError = 0;
3260 int iRetOp = 0;
3261
3262 NetStatus = p2NetLocalGroupEnum(NULL, 0, &Data, 8192, &Index,
3263 &Total, &ResumeHandle );
3264
3265 if (NetStatus != NERR_Success || Data == NULL) {
3267 if (Data)
3268 p2NetApiBufferFree(Data);
3269 return FALSE;
3270 }
3271
3272 fNbGroups = Total;
3273 GroupInfo = (LOCALGROUP_INFO_0 *)Data;
3274 for (i=0; i < Total; i++) {
3275 // Convert group name from UNICODE to ansi.
3277 (UINT)CP_ACP, // code page
3278 (DWORD)0, // performance and mapping flags
3279 (LPCWSTR)(GroupInfo->lgrpi0_name), // address of wide-char string
3280 (int)-1, // number of characters in string
3281 (LPSTR)szAnsiName, // address of buffer for new string
3282 (int)(sizeof(szAnsiName)), // size of buffer
3283 (LPCSTR)NULL, // address of default for unmappable characters
3284 (LPBOOL)NULL ); // address of flag set when default char used.
3285
3286 // Now lookup all members of this group and record down their names and
3287 // SIDs into the output file.
3289
3290 GroupInfo++;
3291 }
3292
3293 if (Data)
3294 p2NetApiBufferFree(Data);
3295
3296 return TRUE;
3297}
3298
3299////////////////////////////////////////////////////////////////////////////////
3300///
3301/// Take the name and look up a SID so that we can get full
3302/// domain/user information
3303///
3304
3306 int &groupIdx, int &memberIdx)
3307{
3308 BOOL bRetOp = FALSE;
3309 PSID pSid = NULL;
3317 unsigned char j = 0;
3318 DWORD dwLastError = 0;
3319
3321 dwSidSize = sizeof(bySidBuffer);
3323
3325 (LPCTSTR)NULL, // address of string for system name
3326 (LPCTSTR)lpszAccountName, // address of string for account name
3327 (PSID)pSid, // address of security identifier
3328 (LPDWORD)&dwSidSize, // address of size of security identifier
3329 (LPTSTR)szDomainName, // address of string for referenced domain
3330 (LPDWORD)&dwDomainNameSize,// address of size of domain string
3331 (PSID_NAME_USE)&sidType ); // address of SID-type indicator
3332
3333 if (bRetOp == FALSE) {
3335 return -1; // Unable to obtain Account SID.
3336 }
3337
3339
3340 if (bRetOp == FALSE) {
3342 return -2; // SID returned is invalid.
3343 }
3344
3345 // Obtain via APIs the identifier authority value.
3347
3348 // Make a copy of it.
3350 sizeof(SID_IDENTIFIER_AUTHORITY));
3351
3352 // Determine how many sub-authority values there are in the current SID.
3354 // Assign it to a more convenient variable.
3355 j = (unsigned char)(*puchar_SubAuthCount);
3356 // Now obtain all the sub-authority values from the current SID.
3357 DWORD dwSubAuth = 0;
3359 // Obtain the current sub-authority DWORD (referenced by a pointer)
3361 (PSID)pSid, // address of security identifier to query
3362 (DWORD)j-1); // index of subauthority to retrieve
3364 if(what == SID_MEMBER) {
3365 fPasswords[memberIdx].pw_uid = dwSubAuth;
3366 fPasswords[memberIdx].pw_gid = fGroups[groupIdx].gr_gid;
3367 fPasswords[memberIdx].pw_group = strdup(fGroups[groupIdx].gr_name);
3368 }
3369 else if(what == SID_GROUP) {
3370 fGroups[groupIdx].gr_gid = dwSubAuth;
3371 }
3372 return 0;
3373}
3374
3375////////////////////////////////////////////////////////////////////////////////
3376///
3377
3379 int &memberIdx)
3380{
3381
3383 LPBYTE Data = NULL;
3384 DWORD Index = 0, Total = 0, i;
3387 char szAnsiMemberName[256];
3388 char szFullMemberName[256];
3389 char szMemberHomeDir[256];
3390 WCHAR wszGroupName[256];
3391 int iRetOp = 0;
3392 char act_name[256];
3393 DWORD length = sizeof (act_name);
3394 DWORD dwLastError = 0;
3397
3399 (UINT)CP_ACP, // code page
3400 (DWORD)MB_PRECOMPOSED, // character-type options
3401 (LPCSTR)lpszGroupName, // address of string to map
3402 (int)-1, // number of bytes in string
3403 (LPWSTR)wszGroupName, // address of wide-character buffer
3404 (int)sizeof(wszGroupName) ); // size of buffer
3405
3406 if (iRetOp == 0) {
3408 if (Data)
3409 p2NetApiBufferFree(Data);
3410 return FALSE;
3411 }
3412
3413 GetUserName (act_name, &length);
3414
3415 // The NetLocalGroupGetMembers() API retrieves a list of the members
3416 // of a particular local group.
3418 &Data, 8192, &Index, &Total, &ResumeHandle );
3419
3420 if (NetStatus != NERR_Success || Data == NULL) {
3422
3424 // This usually means that the current Group has no members.
3425 // We call NetLocalGroupGetMembers() again.
3426 // This time, we set the level to 0.
3427 // We do this just to confirm that the number of members in
3428 // this group is zero.
3430 &Data, 8192, &Index, &Total, &ResumeHandle );
3431 }
3432
3433 if (Data)
3434 p2NetApiBufferFree(Data);
3435 return FALSE;
3436 }
3437
3439 for (i=0; i < Total; i++) {
3441 (UINT)CP_ACP, // code page
3442 (DWORD)0, // performance and mapping flags
3443 (LPCWSTR)(MemberInfo->lgrmi1_name), // address of wide-char string
3444 (int)-1, // number of characters in string
3445 (LPSTR)szAnsiMemberName, // address of buffer for new string
3446 (int)(sizeof(szAnsiMemberName)), // size of buffer
3447 (LPCSTR)NULL, // address of default for unmappable characters
3448 (LPBOOL)NULL ); // address of flag set when default char used.
3449
3450 if (iRetOp == 0) {
3452 }
3453
3455 fPasswords[memberIdx].pw_passwd = strdup("");
3457
3458 if(fActUser == -1 && !stricmp(fPasswords[memberIdx].pw_name,act_name))
3460
3461
3462 TCHAR szUserName[255]=TEXT("");
3464 //
3465 // Call the NetUserGetInfo function; specify level 10.
3466 //
3468 //
3469 // If the call succeeds, print the user information.
3470 //
3471 if (nStatus == NERR_Success) {
3472 if (pUI11Buf != NULL) {
3473 wsprintf(szFullMemberName,"%S",pUI11Buf->usri11_full_name);
3475 wsprintf(szMemberHomeDir,"%S",pUI11Buf->usri11_home_dir);
3477 }
3478 }
3479 if((fPasswords[memberIdx].pw_gecos == NULL) || (strlen(fPasswords[memberIdx].pw_gecos) == 0))
3480 fPasswords[memberIdx].pw_gecos = strdup(fPasswords[memberIdx].pw_name);
3481 if((fPasswords[memberIdx].pw_dir == NULL) || (strlen(fPasswords[memberIdx].pw_dir) == 0))
3482 fPasswords[memberIdx].pw_dir = strdup("c:\\");
3483 //
3484 // Free the allocated memory.
3485 //
3486 if (pUI11Buf != NULL) {
3488 pUI11Buf = NULL;
3489 }
3490
3491 /* Ensure SHELL is defined. */
3492 if (getenv("SHELL") == NULL)
3493 putenv ((GetVersion () & 0x80000000) ? "SHELL=command" : "SHELL=cmd");
3494
3495 /* Set dir and shell from environment variables. */
3496 fPasswords[memberIdx].pw_shell = getenv("SHELL");
3497
3498 // Find out the SID of the Member.
3500 memberIdx++;
3501 MemberInfo++;
3502 }
3503 if(fActUser == -1) fActUser = 0;
3504
3505 if (Data)
3506 p2NetApiBufferFree(Data);
3507
3508 return TRUE;
3509}
3510
3511////////////////////////////////////////////////////////////////////////////////
3512///
3513
3515{
3517 LPBYTE Data = NULL;
3518 DWORD Index = 0, Total = 0, i;
3521 char szAnsiName[256];
3522 DWORD dwLastError = 0;
3523 int iRetOp = 0, iGroupIdx = 0, iMemberIdx = 0;
3524
3525 NetStatus = p2NetLocalGroupEnum(NULL, 0, &Data, 8192, &Index,
3526 &Total, &ResumeHandle );
3527
3528 if (NetStatus != NERR_Success || Data == NULL) {
3530 if (Data)
3531 p2NetApiBufferFree(Data);
3532 return FALSE;
3533 }
3534
3535 GroupInfo = (LOCALGROUP_INFO_0 *)Data;
3536 for (i=0; i < Total; i++) {
3537 // Convert group name from UNICODE to ansi.
3539 (UINT)CP_ACP, // code page
3540 (DWORD)0, // performance and mapping flags
3541 (LPCWSTR)(GroupInfo->lgrpi0_name), // address of wide-char string
3542 (int)-1, // number of characters in string
3543 (LPSTR)szAnsiName, // address of buffer for new string
3544 (int)(sizeof(szAnsiName)), // size of buffer
3545 (LPCSTR)NULL, // address of default for unmappable characters
3546 (LPBOOL)NULL ); // address of flag set when default char used.
3547
3548 fGroups[iGroupIdx].gr_name = strdup(szAnsiName);
3549 fGroups[iGroupIdx].gr_passwd = strdup("");
3550
3551 // Find out the SID of the Group.
3553 // Now lookup all members of this group and record down their names and
3554 // SIDs into the output file.
3556
3557 iGroupIdx++;
3558 GroupInfo++;
3559 }
3560
3561 if (Data)
3562 p2NetApiBufferFree(Data);
3563
3564 return TRUE;
3565}
3566
3567////////////////////////////////////////////////////////////////////////////////
3568/// Returns the user's id. If user = 0, returns current user's id.
3569
3571{
3572 if(!fGroupsInitDone)
3574
3575 // Net* API functions not allowed or OS not Windows NT/2000/XP
3576 if ((!gEnv->GetValue("WinNT.UseNetAPI", 0)) || (::GetVersion() >= 0x80000000)) {
3577 int uid;
3578 char name[256];
3579 DWORD length = sizeof (name);
3580 if (::GetUserName (name, &length)) {
3581 if (stricmp ("administrator", name) == 0)
3582 uid = 0;
3583 else
3584 uid = 123;
3585 }
3586 else {
3587 uid = 123;
3588 }
3589 return uid;
3590 }
3591 if (!user || !user[0])
3592 return fPasswords[fActUser].pw_uid;
3593 else {
3594 struct passwd *pwd = nullptr;
3595 for(int i=0;i<fNbUsers;i++) {
3596 if (!stricmp (user, fPasswords[i].pw_name)) {
3597 pwd = &fPasswords[i];
3598 break;
3599 }
3600 }
3601 if (pwd)
3602 return pwd->pw_uid;
3603 }
3604 return 0;
3605}
3606
3607////////////////////////////////////////////////////////////////////////////////
3608/// Returns the effective user id. The effective id corresponds to the
3609/// set id bit on the file being executed.
3610
3612{
3613 if(!fGroupsInitDone)
3615
3616 // Net* API functions not allowed or OS not Windows NT/2000/XP
3617 if ((!gEnv->GetValue("WinNT.UseNetAPI", 0)) || (::GetVersion() >= 0x80000000)) {
3618 int uid;
3619 char name[256];
3620 DWORD length = sizeof (name);
3621 if (::GetUserName (name, &length)) {
3622 if (stricmp ("administrator", name) == 0)
3623 uid = 0;
3624 else
3625 uid = 123;
3626 }
3627 else {
3628 uid = 123;
3629 }
3630 return uid;
3631 }
3632 return fPasswords[fActUser].pw_uid;
3633}
3634
3635////////////////////////////////////////////////////////////////////////////////
3636/// Returns the group's id. If group = 0, returns current user's group.
3637
3639{
3640 if(!fGroupsInitDone)
3642
3643 // Net* API functions not allowed or OS not Windows NT/2000/XP
3644 if ((!gEnv->GetValue("WinNT.UseNetAPI", 0)) || (::GetVersion() >= 0x80000000)) {
3645 int gid;
3646 char name[256];
3647 DWORD length = sizeof (name);
3648 if (::GetUserName (name, &length)) {
3649 if (stricmp ("administrator", name) == 0)
3650 gid = 0;
3651 else
3652 gid = 123;
3653 }
3654 else {
3655 gid = 123;
3656 }
3657 return gid;
3658 }
3659 if (!group || !group[0])
3660 return fPasswords[fActUser].pw_gid;
3661 else {
3662 struct group *grp = nullptr;
3663 for(int i=0;i<fNbGroups;i++) {
3664 if (!stricmp (group, fGroups[i].gr_name)) {
3665 grp = &fGroups[i];
3666 break;
3667 }
3668 }
3669 if (grp)
3670 return grp->gr_gid;
3671 }
3672 return 0;
3673}
3674
3675////////////////////////////////////////////////////////////////////////////////
3676/// Returns the effective group id. The effective group id corresponds
3677/// to the set id bit on the file being executed.
3678
3680{
3681 if(!fGroupsInitDone)
3683
3684 // Net* API functions not allowed or OS not Windows NT/2000/XP
3685 if ((!gEnv->GetValue("WinNT.UseNetAPI", 0)) || (::GetVersion() >= 0x80000000)) {
3686 int gid;
3687 char name[256];
3688 DWORD length = sizeof (name);
3689 if (::GetUserName (name, &length)) {
3690 if (stricmp ("administrator", name) == 0)
3691 gid = 0;
3692 else
3693 gid = 123;
3694 }
3695 else {
3696 gid = 123;
3697 }
3698 return gid;
3699 }
3700 return fPasswords[fActUser].pw_gid;
3701}
3702
3703////////////////////////////////////////////////////////////////////////////////
3704/// Returns all user info in the UserGroup_t structure. The returned
3705/// structure must be deleted by the user. In case of error 0 is returned.
3706
3708{
3709 if(!fGroupsInitDone)
3711
3712 // Net* API functions not allowed or OS not Windows NT/2000/XP
3713 if ((!gEnv->GetValue("WinNT.UseNetAPI", 0)) || (::GetVersion() >= 0x80000000)) {
3714 char name[256];
3715 DWORD length = sizeof (name);
3716 UserGroup_t *ug = new UserGroup_t;
3717 if (::GetUserName (name, &length)) {
3718 ug->fUser = name;
3719 if (stricmp ("administrator", name) == 0) {
3720 ug->fUid = 0;
3721 ug->fGroup = "administrators";
3722 }
3723 else {
3724 ug->fUid = 123;
3725 ug->fGroup = "users";
3726 }
3727 ug->fGid = ug->fUid;
3728 }
3729 else {
3730 ug->fUser = "unknown";
3731 ug->fGroup = "unknown";
3732 ug->fUid = ug->fGid = 123;
3733 }
3734 ug->fPasswd = "";
3735 ug->fRealName = ug->fUser;
3736 ug->fShell = "command";
3737 return ug;
3738 }
3739 struct passwd *pwd = 0;
3740 if (uid == 0)
3742 else {
3743 for (int i = 0; i < fNbUsers; i++) {
3744 if (uid == fPasswords[i].pw_uid) {
3745 pwd = &fPasswords[i];
3746 break;
3747 }
3748 }
3749 }
3750 if (pwd) {
3751 UserGroup_t *ug = new UserGroup_t;
3752 ug->fUid = pwd->pw_uid;
3753 ug->fGid = pwd->pw_gid;
3754 ug->fUser = pwd->pw_name;
3755 ug->fPasswd = pwd->pw_passwd;
3756 ug->fRealName = pwd->pw_gecos;
3757 ug->fShell = pwd->pw_shell;
3758 ug->fGroup = pwd->pw_group;
3759 return ug;
3760 }
3761 return nullptr;
3762}
3763
3764////////////////////////////////////////////////////////////////////////////////
3765/// Returns all user info in the UserGroup_t structure. If user = 0, returns
3766/// current user's id info. The returned structure must be deleted by the
3767/// user. In case of error 0 is returned.
3768
3770{
3771 return GetUserInfo(GetUid(user));
3772}
3773
3774////////////////////////////////////////////////////////////////////////////////
3775/// Returns all group info in the UserGroup_t structure. The only active
3776/// fields in the UserGroup_t structure for this call are:
3777/// fGid and fGroup
3778/// The returned structure must be deleted by the user. In case of
3779/// error 0 is returned.
3780
3782{
3783 if(!fGroupsInitDone)
3785
3786 // Net* API functions not allowed or OS not Windows NT/2000/XP
3787 if ((!gEnv->GetValue("WinNT.UseNetAPI", 0)) || (::GetVersion() >= 0x80000000)) {
3788 char name[256];
3789 DWORD length = sizeof (name);
3790 UserGroup_t *gr = new UserGroup_t;
3791 if (::GetUserName (name, &length)) {
3792 if (stricmp ("administrator", name) == 0) {
3793 gr->fGroup = "administrators";
3794 gr->fGid = 0;
3795 }
3796 else {
3797 gr->fGroup = "users";
3798 gr->fGid = 123;
3799 }
3800 }
3801 else {
3802 gr->fGroup = "unknown";
3803 gr->fGid = 123;
3804 }
3805 gr->fUid = 0;
3806 return gr;
3807 }
3808 struct group *grp = nullptr;
3809 for(int i=0;i<fNbGroups;i++) {
3810 if (gid == fGroups[i].gr_gid) {
3811 grp = &fGroups[i];
3812 break;
3813 }
3814 }
3815 if (grp) {
3816 UserGroup_t *gr = new UserGroup_t;
3817 gr->fUid = 0;
3818 gr->fGid = grp->gr_gid;
3819 gr->fGroup = grp->gr_name;
3820 return gr;
3821 }
3822 return nullptr;
3823}
3824
3825////////////////////////////////////////////////////////////////////////////////
3826/// Returns all group info in the UserGroup_t structure. The only active
3827/// fields in the UserGroup_t structure for this call are:
3828/// fGid and fGroup
3829/// If group = 0, returns current user's group. The returned structure
3830/// must be deleted by the user. In case of error 0 is returned.
3831
3833{
3834 return GetGroupInfo(GetGid(group));
3835}
3836
3837//---- environment manipulation ------------------------------------------------
3838
3839////////////////////////////////////////////////////////////////////////////////
3840/// Set environment variable.
3841
3842void TWinNTSystem::Setenv(const char *name, const char *value)
3843{
3844 ::_putenv(TString::Format("%s=%s", name, value));
3845}
3846
3847////////////////////////////////////////////////////////////////////////////////
3848/// Get environment variable.
3849
3850const char *TWinNTSystem::Getenv(const char *name)
3851{
3852 const char *env = std::getenv(name);
3853 if (!env) {
3854 if (::_stricmp(name,"home") == 0 ) {
3855 env = HomeDirectory();
3856 } else if (::_stricmp(name, "rootsys") == 0 ) {
3857 env = gRootDir;
3858 }
3859 }
3860 return env;
3861}
3862
3863//---- Processes ---------------------------------------------------------------
3864
3865////////////////////////////////////////////////////////////////////////////////
3866/// Execute a command.
3867
3869{
3870 return ::system(shellcmd);
3871}
3872
3873////////////////////////////////////////////////////////////////////////////////
3874/// Open a pipe.
3875
3876FILE *TWinNTSystem::OpenPipe(const char *command, const char *mode)
3877{
3878 return ::_popen(command, mode);
3879}
3880
3881////////////////////////////////////////////////////////////////////////////////
3882/// Close the pipe.
3883
3885{
3886 return ::_pclose(pipe);
3887}
3888
3889////////////////////////////////////////////////////////////////////////////////
3890/// Get process id.
3891
3893{
3894 return ::getpid();
3895}
3896
3897////////////////////////////////////////////////////////////////////////////////
3898/// Get current process handle
3899
3901{
3902 return fhProcess;
3903}
3904
3905////////////////////////////////////////////////////////////////////////////////
3906/// Exit the application.
3907
3909{
3910 // Insures that the files and sockets are closed before any library is unloaded
3911 // and before emptying CINT.
3912 // FIXME: Unify with TROOT::ShutDown.
3913 if (gROOT) {
3914 gROOT->CloseFiles();
3915 if (gROOT->GetListOfBrowsers()) {
3916 // GetListOfBrowsers()->Delete() creates problems when a browser is
3917 // created on the stack, calling CloseWindow() solves the problem
3918 if (gROOT->IsBatch())
3919 gROOT->GetListOfBrowsers()->Delete();
3920 else {
3921 TBrowser *b;
3922 TIter next(gROOT->GetListOfBrowsers());
3923 while ((b = (TBrowser*) next()))
3924 if (b->GetBrowserImp() && b->GetBrowserImp()->GetMainFrame())
3925 gROOT->ProcessLine(TString::Format("\
3926 (((TBrowser*)0x%zx)->GetBrowserImp()->GetMainFrame()->CloseWindow();",
3927 (intptr_t)b));
3928 }
3929 }
3930 }
3932 gVirtualX->CloseDisplay();
3933
3934 if (mode) {
3935 ::exit(code);
3936 } else {
3937 ::_exit(code);
3938 }
3939}
3940
3941////////////////////////////////////////////////////////////////////////////////
3942/// Abort the application.
3943
3945{
3947 ::abort();
3948}
3949
3950//---- Standard output redirection ---------------------------------------------
3951
3952////////////////////////////////////////////////////////////////////////////////
3953/// Redirect standard output (stdout, stderr) to the specified file.
3954/// If the file argument is 0 the output is set again to stderr, stdout.
3955/// The second argument specifies whether the output should be added to the
3956/// file ("a", default) or the file be truncated before ("w").
3957/// This function saves internally the current state into a static structure.
3958/// The call can be made reentrant by specifying the opaque structure pointed
3959/// by 'h', which is filled with the relevant information. The handle 'h'
3960/// obtained on the first call must then be used in any subsequent call,
3961/// included ShowOutput, to display the redirected output.
3962/// Returns 0 on success, -1 in case of error.
3963
3964Int_t TWinNTSystem::RedirectOutput(const char *file, const char *mode,
3966{
3967 FILE *fout, *ferr;
3968 static int fd1=0, fd2=0;
3969 static fpos_t pos1=0, pos2=0;
3970 // Instance to be used if the caller does not passes 'h'
3971 static RedirectHandle_t loch;
3972 Int_t rc = 0;
3973
3974 // Which handle to use ?
3975 RedirectHandle_t *xh = (h) ? h : &loch;
3976
3977 if (file) {
3978 // Make sure mode makes sense; default "a"
3979 const char *m = (mode[0] == 'a' || mode[0] == 'w') ? mode : "a";
3980
3981 // Current file size
3982 xh->fReadOffSet = 0;
3983 if (m[0] == 'a') {
3984 // If the file exists, save the current size
3985 FileStat_t st;
3986 if (!gSystem->GetPathInfo(file, st))
3987 xh->fReadOffSet = (st.fSize > 0) ? st.fSize : xh->fReadOffSet;
3988 }
3989 xh->fFile = file;
3990
3991 fflush(stdout);
3992 fgetpos(stdout, &pos1);
3993 fd1 = _dup(fileno(stdout));
3994 // redirect stdout & stderr
3995 if ((fout = freopen(file, m, stdout)) == 0) {
3996 SysError("RedirectOutput", "could not freopen stdout");
3997 if (fd1 > 0) {
3999 close(fd1);
4000 }
4002 fsetpos(stdout, &pos1);
4003 fd1 = fd2 = 0;
4004 return -1;
4005 }
4006 fflush(stderr);
4007 fgetpos(stderr, &pos2);
4008 fd2 = _dup(fileno(stderr));
4009 if ((ferr = freopen(file, m, stderr)) == 0) {
4010 SysError("RedirectOutput", "could not freopen stderr");
4011 if (fd1 > 0) {
4013 close(fd1);
4014 }
4016 fsetpos(stdout, &pos1);
4017 if (fd2 > 0) {
4019 close(fd2);
4020 }
4022 fsetpos(stderr, &pos2);
4023 fd1 = fd2 = 0;
4024 return -1;
4025 }
4026 if (m[0] == 'a') {
4027 fseek(fout, 0, SEEK_END);
4028 fseek(ferr, 0, SEEK_END);
4029 }
4030 } else {
4031 // Restore stdout & stderr
4032 fflush(stdout);
4033 if (fd1) {
4034 if (fd1 > 0) {
4035 if (_dup2(fd1, fileno(stdout))) {
4036 SysError("RedirectOutput", "could not restore stdout");
4037 rc = -1;
4038 }
4039 close(fd1);
4040 }
4042 fsetpos(stdout, &pos1);
4043 fd1 = 0;
4044 }
4045
4046 fflush(stderr);
4047 if (fd2) {
4048 if (fd2 > 0) {
4049 if (_dup2(fd2, fileno(stderr))) {
4050 SysError("RedirectOutput", "could not restore stderr");
4051 rc = -1;
4052 }
4053 close(fd2);
4054 }
4056 fsetpos(stderr, &pos2);
4057 fd2 = 0;
4058 }
4059
4060 // Reset the static instance, if using that
4061 if (xh == &loch)
4062 xh->Reset();
4063 }
4064 return rc;
4065}
4066
4067//---- dynamic loading and linking ---------------------------------------------
4068
4069////////////////////////////////////////////////////////////////////////////////
4070/// Add a new directory to the dynamic path.
4071
4072void TWinNTSystem::AddDynamicPath(const char *dir)
4073{
4074 if (dir) {
4076 oldpath.Append(";");
4077 oldpath.Append(dir);
4079 }
4080}
4081
4082////////////////////////////////////////////////////////////////////////////////
4083/// Return the dynamic path (used to find shared libraries).
4084
4086{
4087 return DynamicPath(0, kFALSE);
4088}
4089
4090////////////////////////////////////////////////////////////////////////////////
4091/// Set the dynamic path to a new value.
4092/// If the value of 'path' is zero, the dynamic path is reset to its
4093/// default value.
4094
4095void TWinNTSystem::SetDynamicPath(const char *path)
4096{
4097 if (!path)
4098 DynamicPath(0, kTRUE);
4099 else
4100 DynamicPath(path);
4101}
4102
4103////////////////////////////////////////////////////////////////////////////////
4104/// Returns and updates sLib to the path of a dynamic library
4105/// (searches for library in the dynamic library search path).
4106/// If no file name extension is provided it tries .DLL.
4107
4109{
4110 int len = sLib.Length();
4111 if (len > 4 && (!stricmp(sLib.Data()+len-4, ".dll"))) {
4113 return sLib.Data();
4114 } else {
4116 sLibDll += ".dll";
4118 sLibDll.Swap(sLib);
4119 return sLib.Data();
4120 }
4121 }
4122
4123 if (!quiet) {
4124 Error("DynamicPathName",
4125 "%s does not exist in %s,\nor has wrong file extension (.dll)",
4126 sLib.Data(), GetDynamicPath());
4127 }
4128 return nullptr;
4129}
4130
4131////////////////////////////////////////////////////////////////////////////////
4132/// Load a shared library. Returns 0 on successful loading, 1 in
4133/// case lib was already loaded and -1 in case lib does not exist
4134/// or in case of error.
4135
4136int TWinNTSystem::Load(const char *module, const char *entry, Bool_t system)
4137{
4138 return TSystem::Load(module, entry, system);
4139}
4140
4141/* nonstandard extension used : zero-sized array in struct/union */
4142#pragma warning(push)
4143#pragma warning(disable:4200)
4144////////////////////////////////////////////////////////////////////////////////
4145/// Get list of shared libraries loaded at the start of the executable.
4146/// Returns 0 in case list cannot be obtained or in case of error.
4147
4149{
4150 char winDrive[256];
4151 char winDir[256];
4152 char winName[256];
4153 char winExt[256];
4154
4155 if (!gApplication) return nullptr;
4156
4157 static Bool_t once = kFALSE;
4158 static TString linkedLibs;
4159
4160 if (!linkedLibs.IsNull())
4161 return linkedLibs;
4162
4163 if (once)
4164 return nullptr;
4165
4166 char *exe = gSystem->Which(Getenv("PATH"), gApplication->Argv(0),
4168 if (!exe) {
4169 once = kTRUE;
4170 return nullptr;
4171 }
4172
4173 HANDLE hFile, hMapping;
4174 void *basepointer;
4175
4177 delete [] exe;
4178 return nullptr;
4179 }
4182 delete [] exe;
4183 return nullptr;
4184 }
4188 delete [] exe;
4189 return nullptr;
4190 }
4191
4192 int sect;
4194 struct header {
4195 DWORD signature;
4198 IMAGE_SECTION_HEADER section_header[]; // actual number in NumberOfSections
4199 };
4200 struct header *pheader;
4202
4203 if(dos_head->e_magic!='ZM') {
4204 delete [] exe;
4205 return nullptr;
4206 } // verify DOS-EXE-Header
4207 // after end of DOS-EXE-Header: offset to PE-Header
4208 pheader = (struct header *)((char*)dos_head + dos_head->e_lfanew);
4209
4210 if(IsBadReadPtr(pheader,sizeof(struct header))) { // start of PE-Header
4211 delete [] exe;
4212 return nullptr;
4213 }
4214 if(pheader->signature!=IMAGE_NT_SIGNATURE) { // verify PE format
4215 switch((unsigned short)pheader->signature) {
4217 delete [] exe;
4218 return nullptr;
4220 delete [] exe;
4221 return nullptr;
4223 delete [] exe;
4224 return nullptr;
4225 default: // unknown signature
4226 delete [] exe;
4227 return nullptr;
4228 }
4229 }
4230#define isin(address,start,length) ((address)>=(start) && (address)<(start)+(length))
4231 TString odump;
4232 // walk through sections
4233 for(sect=0,section_header=pheader->section_header;
4234 sect<pheader->_head.NumberOfSections;sect++,section_header++) {
4235 int directory;
4236 const void * const section_data =
4237 (char*)basepointer + section_header->PointerToRawData;
4239 if(isin(pheader->opt_head.DataDirectory[directory].VirtualAddress,
4240 section_header->VirtualAddress,
4241 section_header->SizeOfRawData)) {
4244 (pheader->opt_head.DataDirectory[directory].VirtualAddress -
4245 section_header->VirtualAddress));
4246 // (virtual address of stuff - virtual address of section) =
4247 // offset of stuff in section
4248 const unsigned stuff_length =
4249 pheader->opt_head.DataDirectory[directory].Size;
4251 while(!IsBadReadPtr(stuff_start,sizeof(*stuff_start)) &&
4252 stuff_start->Name) {
4253 TString dll = (char*)section_data +
4254 ((DWORD)(stuff_start->Name)) -
4255 section_header->VirtualAddress;
4256 if (dll.EndsWith(".dll")) {
4257 char *dllPath = DynamicPathName(dll, kTRUE);
4258 if (dllPath) {
4259 char *winPath = getenv("windir");
4261 if(!strstr(dllPath, winDir)) {
4262 if (!linkedLibs.IsNull())
4263 linkedLibs += " ";
4265 }
4266 }
4267 delete [] dllPath;
4268 }
4269 stuff_start++;
4270 }
4271 }
4272 }
4273 }
4274 }
4275
4279
4280 delete [] exe;
4281
4282 once = kTRUE;
4283
4284 if (linkedLibs.IsNull())
4285 return nullptr;
4286
4287 return linkedLibs;
4288}
4289#pragma warning(pop)
4290
4291////////////////////////////////////////////////////////////////////////////////
4292/// Return a space separated list of loaded shared libraries.
4293/// This list is of a format suitable for a linker, i.e it may contain
4294/// -Lpathname and/or -lNameOfLib.
4295/// Option can be any of:
4296/// S: shared libraries loaded at the start of the executable, because
4297/// they were specified on the link line.
4298/// D: shared libraries dynamically loaded after the start of the program.
4299/// L: list the .LIB rather than the .DLL (this is intended for linking)
4300/// [This options is not the default]
4301
4302const char *TWinNTSystem::GetLibraries(const char *regexp, const char *options,
4304{
4306 struct _stat buf;
4307 std::string str;
4309 TString libs(TSystem::GetLibraries(regexp, options, isRegexp));
4310 TString opt = options;
4311 std::vector<std::string> all_libs, libpaths;
4312
4313 if ( (opt.First('L')!=kNPOS) ) {
4314 libs.ReplaceAll("/","\\");
4315 // get the %LIB% environment path list
4316 std::stringstream libenv(gSystem->Getenv("LIB"));
4317 while (getline(libenv, str, ';')) {
4318 libpaths.push_back(str);
4319 }
4320 // now get the list of libraries
4321 std::stringstream libraries(libs.Data());
4322 while (getline(libraries, str, ' ')) {
4323 std::string::size_type first, last;
4324 // if the line begins with "-L", it's a linker option
4325 // (e.g. -LIBPATH:%ROOTSYS%\\lib), so add it to the path list
4326 if (str.rfind("-L", 0) == 0) {
4327 first = str.find_first_of('%');
4328 last = str.find_last_of('%');
4329 if ((first != std::string::npos) && (last != std::string::npos) &&
4330 (first != last)) {
4331 // if there is a string between %%, this is an environment
4332 // variable (e.g. %ROOTSYS%), so let's try to resolve it
4333 // and replace it with the real path
4334 std::string var = str.substr(first+1, last-first-1);
4335 std::string env(gSystem->Getenv(var.c_str()));
4336 if (!env.empty()) {
4337 // the environment variable exist and properly resolved
4338 // so add the last part of the path and add it to the list
4339 env += str.substr(last+1);
4340 libpaths.push_back(env);
4341 }
4342 }
4343 // keep the linker instuction in the final list
4344 ntlibs.Append(str.c_str());
4345 ntlibs += " ";
4346 continue;
4347 }
4348 // replace the '.dll' or '.DLL' extension by '.lib'
4349 last = str.rfind(".dll");
4350 if (last != std::string::npos)
4351 str.replace(last, 4, ".lib");
4352 last = str.rfind(".DLL");
4353 if (last != std::string::npos)
4354 str.replace(last, 4, ".lib");
4355 if (str.rfind(".lib") != std::string::npos ||
4356 str.rfind(".LIB") != std::string::npos) {
4357 // check if the .lib with its full path exists
4358 if (_stat( str.c_str(), &buf ) == 0) {
4359 // file exists, so keep it with full path in our final list
4360 ntlibs.Append(str.c_str());
4361 ntlibs += " ";
4362 continue;
4363 }
4364 }
4365 // full path not found, so split it to extract the library name
4366 // only, set its extension to '.lib' and add it to the list of
4367 // libraries to search, but only if not a system DLL for which
4368 // we might not have the proper import library
4369 char *windir;
4370 size_t requiredSize;
4371 getenv_s( &requiredSize, NULL, 0, "WinDir");
4372 if (requiredSize == 0) {
4373 windir = strdup(":\\WINDOWS");
4374 } else {
4375 windir = (char*) malloc(requiredSize * sizeof(char));
4376 if (!windir) {
4377 windir = strdup(":\\WINDOWS");
4378 } else {
4379 getenv_s( &requiredSize, windir, requiredSize, "WinDir" );
4380 }
4381 }
4382 if (str.find(windir) == std::string::npos) {
4383 _splitpath(str.c_str(), drive, dir, fname, ext);
4384 std::string libname(fname);
4385 libname += ".lib";
4386 all_libs.push_back(libname);
4387 }
4388 free(windir);
4389 }
4390 for (auto lib : all_libs) {
4391 // loop over all libraries to check which one exists
4392 for (auto libpath : libpaths) {
4393 // check in each path of the %LIB% environment
4394 std::string path_lib(libpath);
4395 path_lib += "\\";
4396 path_lib += lib;
4397 if (_stat( path_lib.c_str(), &buf ) == 0) {
4398 // file exists, add it to the final list of libraries
4399 ntlibs.Append(lib.c_str());
4400 ntlibs += " ";
4401 }
4402 }
4403 }
4404 } else {
4405 ntlibs = libs;
4406 }
4407
4408 fListLibs = ntlibs;
4409 fListLibs.ReplaceAll("/","\\");
4410 return fListLibs;
4411}
4412
4413//---- Time & Date -------------------------------------------------------------
4414
4415////////////////////////////////////////////////////////////////////////////////
4416/// Add timer to list of system timers.
4417
4422
4423////////////////////////////////////////////////////////////////////////////////
4424/// Remove timer from list of system timers.
4425
4427{
4428 if (!ti) return nullptr;
4429
4431 return t;
4432}
4433
4434////////////////////////////////////////////////////////////////////////////////
4435/// Special Thread to check asynchronous timers.
4436
4438{
4439 while (1) {
4440 if (!fInsideNotify)
4443 }
4444}
4445
4446////////////////////////////////////////////////////////////////////////////////
4447/// Handle and dispatch timers. If mode = kTRUE dispatch synchronous
4448/// timers else a-synchronous timers.
4449
4451{
4452 if (!fTimers) return kFALSE;
4453
4455
4456 TListIter it(fTimers);
4457 TTimer *t;
4459
4460 while ((t = (TTimer *) it.Next())) {
4461 // NB: the timer resolution is added in TTimer::CheckTimer()
4462 TTime now = Now();
4463 if (mode && t->IsSync()) {
4464 if (t->CheckTimer(now)) {
4465 timedout = kTRUE;
4466 }
4467 } else if (!mode && t->IsAsync()) {
4468 if (t->CheckTimer(now)) {
4469 timedout = kTRUE;
4470 }
4471 }
4472 }
4474
4475 return timedout;
4476}
4477
4478const Double_t gTicks = 1.0e-7;
4479////////////////////////////////////////////////////////////////////////////////
4480///
4481
4483{
4484 union {
4487 } ftRealTime; // time the process has spent in kernel mode
4488
4490 return (Double_t)ftRealTime.ftInt64 * gTicks;
4491}
4492
4493////////////////////////////////////////////////////////////////////////////////
4494///
4495
4497{
4499
4500//*-* Value Platform
4501//*-* ----------------------------------------------------
4502//*-* VER_PLATFORM_WIN32s Win32s on Windows 3.1
4503//*-* VER_PLATFORM_WIN32_WINDOWS Win32 on Windows 95
4504//*-* VER_PLATFORM_WIN32_NT Windows NT
4505//*-*
4506
4507 OsVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
4509 if (OsVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) {
4510 DWORD ret;
4511 FILETIME ftCreate, // when the process was created
4512 ftExit; // when the process exited
4513
4514 union {
4517 } ftKernel; // time the process has spent in kernel mode
4518
4519 union {
4522 } ftUser; // time the process has spent in user mode
4523
4524 HANDLE hThread = GetCurrentThread();
4526 &ftKernel.ftFileTime,
4527 &ftUser.ftFileTime);
4528 if (ret != TRUE){
4529 ret = ::GetLastError();
4530 ::Error("GetCPUTime", " Error on GetProcessTimes 0x%lx", (int)ret);
4531 }
4532
4533 // Process times are returned in a 64-bit structure, as the number of
4534 // 100 nanosecond ticks since 1 January 1601. User mode and kernel mode
4535 // times for this process are in separate 64-bit structures.
4536 // To convert to floating point seconds, we will:
4537 // Convert sum of high 32-bit quantities to 64-bit int
4538
4539 return (Double_t) (ftKernel.ftInt64 + ftUser.ftInt64) * gTicks;
4540 } else {
4541 return GetRealTime();
4542 }
4543}
4544
4545////////////////////////////////////////////////////////////////////////////////
4546/// Get current time in milliseconds since 0:00 Jan 1 1995.
4547
4549{
4550 static time_t jan95 = 0;
4551 if (!jan95) {
4552 struct tm tp;
4553 tp.tm_year = 95;
4554 tp.tm_mon = 0;
4555 tp.tm_mday = 1;
4556 tp.tm_hour = 0;
4557 tp.tm_min = 0;
4558 tp.tm_sec = 0;
4559 tp.tm_isdst = -1;
4560
4561 jan95 = mktime(&tp);
4562 if ((int)jan95 == -1) {
4563 ::SysError("TWinNTSystem::Now", "error converting 950001 0:00 to time_t");
4564 return 0;
4565 }
4566 }
4567
4568 _timeb now;
4569 _ftime(&now);
4570 return TTime((now.time-(Long_t)jan95)*1000 + now.millitm);
4571}
4572
4573////////////////////////////////////////////////////////////////////////////////
4574/// Sleep milliSec milli seconds.
4575/// The Sleep function suspends the execution of the CURRENT THREAD for
4576/// a specified interval.
4577
4579{
4580 std::this_thread::sleep_for(std::chrono::milliseconds(milliSec));
4581}
4582
4583////////////////////////////////////////////////////////////////////////////////
4584/// Select on file descriptors. The timeout to is in millisec.
4585
4587{
4588 Int_t rc = -4;
4589
4590 TFdSet rd, wr;
4591 Int_t mxfd = -1;
4592 TIter next(act);
4593 TFileHandler *h = nullptr;
4594 while ((h = (TFileHandler *) next())) {
4595 Int_t fd = h->GetFd();
4596 if (h->HasReadInterest())
4597 rd.Set(fd);
4598 if (h->HasWriteInterest())
4599 wr.Set(fd);
4600 h->ResetReadyMask();
4601 }
4602 rc = WinNTSelect(&rd, &wr, to);
4603
4604 // Set readiness bits
4605 if (rc > 0) {
4606 next.Reset();
4607 while ((h = (TFileHandler *) next())) {
4608 Int_t fd = h->GetFd();
4609 if (rd.IsSet(fd))
4610 h->SetReadReady();
4611 if (wr.IsSet(fd))
4612 h->SetWriteReady();
4613 }
4614 }
4615
4616 return rc;
4617}
4618
4619////////////////////////////////////////////////////////////////////////////////
4620/// Select on the file descriptor related to file handler h.
4621/// The timeout to is in millisec.
4622
4624{
4625 Int_t rc = -4;
4626
4627 TFdSet rd, wr;
4628 Int_t fd = -1;
4629 if (h) {
4630 fd = h->GetFd();
4631 if (h->HasReadInterest())
4632 rd.Set(fd);
4633 if (h->HasWriteInterest())
4634 wr.Set(fd);
4635 h->ResetReadyMask();
4636 rc = WinNTSelect(&rd, &wr, to);
4637 }
4638
4639 // Fill output lists, if required
4640 if (rc > 0) {
4641 if (rd.IsSet(fd))
4642 h->SetReadReady();
4643 if (wr.IsSet(fd))
4644 h->SetWriteReady();
4645 }
4646
4647 return rc;
4648}
4649
4650//---- RPC ---------------------------------------------------------------------
4651////////////////////////////////////////////////////////////////////////////////
4652/// Get port # of internet service.
4653
4655{
4656 struct servent *sp;
4657
4659 Error("GetServiceByName", "no service \"%s\" with protocol \"%s\"\n",
4661 return -1;
4662 }
4663 return ::ntohs(sp->s_port);
4664}
4665
4666////////////////////////////////////////////////////////////////////////////////
4667
4669{
4670 // Get name of internet service.
4671
4672 struct servent *sp;
4673
4674 if ((sp = ::getservbyport(::htons(port), kProtocolName)) == 0) {
4675 return Form("%d", port);
4676 }
4677 return sp->s_name;
4678}
4679
4680////////////////////////////////////////////////////////////////////////////////
4681/// Get Internet Protocol (IP) address of host.
4682
4684{
4685 struct hostent *host_ptr;
4686 const char *host;
4687 int type;
4688 UInt_t addr; // good for 4 byte addresses
4689
4690 if ((addr = ::inet_addr(hostname)) != INADDR_NONE) {
4691 type = AF_INET;
4692 if ((host_ptr = ::gethostbyaddr((const char *)&addr,
4693 sizeof(addr), AF_INET))) {
4694 host = host_ptr->h_name;
4695 TInetAddress a(host, ntohl(addr), type);
4696 UInt_t addr2;
4697 Int_t i;
4698 for (i = 1; host_ptr->h_addr_list[i]; i++) {
4699 memcpy(&addr2, host_ptr->h_addr_list[i], host_ptr->h_length);
4700 a.AddAddress(ntohl(addr2));
4701 }
4702 for (i = 0; host_ptr->h_aliases[i]; i++)
4703 a.AddAlias(host_ptr->h_aliases[i]);
4704 return a;
4705 } else {
4706 host = "UnNamedHost";
4707 }
4708 } else if ((host_ptr = ::gethostbyname(hostname))) {
4709 // Check the address type for an internet host
4710 if (host_ptr->h_addrtype != AF_INET) {
4711 Error("GetHostByName", "%s is not an internet host\n", hostname);
4712 return TInetAddress();
4713 }
4714 memcpy(&addr, host_ptr->h_addr, host_ptr->h_length);
4715 host = host_ptr->h_name;
4716 type = host_ptr->h_addrtype;
4717 TInetAddress a(host, ntohl(addr), type);
4718 UInt_t addr2;
4719 Int_t i;
4720 for (i = 1; host_ptr->h_addr_list[i]; i++) {
4721 memcpy(&addr2, host_ptr->h_addr_list[i], host_ptr->h_length);
4722 a.AddAddress(ntohl(addr2));
4723 }
4724 for (i = 0; host_ptr->h_aliases[i]; i++)
4725 a.AddAlias(host_ptr->h_aliases[i]);
4726 return a;
4727 } else {
4728 if (gDebug > 0) Error("GetHostByName", "unknown host %s", hostname);
4729 return TInetAddress(hostname, 0, -1);
4730 }
4731
4732 return TInetAddress(host, ::ntohl(addr), type);
4733}
4734
4735////////////////////////////////////////////////////////////////////////////////
4736/// Get Internet Protocol (IP) address of remote host and port #.
4737
4739{
4740 SOCKET sock = socket;
4741 struct sockaddr_in addr;
4742 int len = sizeof(addr);
4743
4744 if (::getpeername(sock, (struct sockaddr *)&addr, &len) == SOCKET_ERROR) {
4745 ::SysError("GetPeerName", "getpeername");
4746 return TInetAddress();
4747 }
4748
4749 struct hostent *host_ptr;
4750 const char *hostname;
4751 int family;
4752 UInt_t iaddr;
4753
4754 if ((host_ptr = ::gethostbyaddr((const char *)&addr.sin_addr,
4755 sizeof(addr.sin_addr), AF_INET))) {
4756 memcpy(&iaddr, host_ptr->h_addr, host_ptr->h_length);
4757 hostname = host_ptr->h_name;
4758 family = host_ptr->h_addrtype;
4759 } else {
4760 memcpy(&iaddr, &addr.sin_addr, sizeof(addr.sin_addr));
4761 hostname = "????";
4762 family = AF_INET;
4763 }
4764
4765 return TInetAddress(hostname, ::ntohl(iaddr), family, ::ntohs(addr.sin_port));
4766}
4767
4768////////////////////////////////////////////////////////////////////////////////
4769/// Get Internet Protocol (IP) address of host and port #.
4770
4772{
4773 SOCKET sock = socket;
4774 struct sockaddr_in addr;
4775 int len = sizeof(addr);
4776
4777 if (::getsockname(sock, (struct sockaddr *)&addr, &len) == SOCKET_ERROR) {
4778 ::SysError("GetSockName", "getsockname");
4779 return TInetAddress();
4780 }
4781
4782 struct hostent *host_ptr;
4783 const char *hostname;
4784 int family;
4785 UInt_t iaddr;
4786
4787 if ((host_ptr = ::gethostbyaddr((const char *)&addr.sin_addr,
4788 sizeof(addr.sin_addr), AF_INET))) {
4789 memcpy(&iaddr, host_ptr->h_addr, host_ptr->h_length);
4790 hostname = host_ptr->h_name;
4791 family = host_ptr->h_addrtype;
4792 } else {
4793 memcpy(&iaddr, &addr.sin_addr, sizeof(addr.sin_addr));
4794 hostname = "????";
4795 family = AF_INET;
4796 }
4797
4798 return TInetAddress(hostname, ::ntohl(iaddr), family, ::ntohs(addr.sin_port));
4799}
4800
4801////////////////////////////////////////////////////////////////////////////////
4802/// Announce unix domain service.
4803
4805{
4806 SOCKET sock;
4807
4808 // Create socket
4809 if ((sock = ::socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
4810 ::SysError("TWinNTSystem::AnnounceUnixService", "socket");
4811 return -1;
4812 }
4813
4814 struct sockaddr_in inserver;
4815 memset(&inserver, 0, sizeof(inserver));
4816 inserver.sin_family = AF_INET;
4817 inserver.sin_addr.s_addr = ::htonl(INADDR_LOOPBACK);
4818 inserver.sin_port = port;
4819
4820 // Bind socket
4821 if (port > 0) {
4822 if (::bind(sock, (struct sockaddr*) &inserver, sizeof(inserver)) == SOCKET_ERROR) {
4823 ::SysError("TWinNTSystem::AnnounceUnixService", "bind");
4824 return -2;
4825 }
4826 }
4827 // Start accepting connections
4828 if (::listen(sock, backlog)) {
4829 ::SysError("TWinNTSystem::AnnounceUnixService", "listen");
4830 return -1;
4831 }
4832 return (int)sock;
4833}
4834
4835////////////////////////////////////////////////////////////////////////////////
4836/// Open a socket on path 'sockpath', bind to it and start listening for Unix
4837/// domain connections to it. Returns socket fd or -1.
4838
4840{
4841 if (!sockpath || strlen(sockpath) <= 0) {
4842 ::SysError("TWinNTSystem::AnnounceUnixService", "socket path undefined");
4843 return -1;
4844 }
4845
4846 struct sockaddr_in myaddr;
4847 FILE * fp;
4848 int len = sizeof myaddr;
4849 int rc;
4850 int sock;
4851
4852 // Create socket
4853 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
4854 ::SysError("TWinNTSystem::AnnounceUnixService", "socket");
4855 return -1;
4856 }
4857
4858 memset(&myaddr, 0, sizeof(myaddr));
4859 myaddr.sin_port = 0;
4860 myaddr.sin_family = AF_INET;
4861 myaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
4862
4863 rc = bind(sock, (struct sockaddr *)&myaddr, len);
4864 if (rc) {
4865 ::SysError("TWinNTSystem::AnnounceUnixService", "bind");
4866 return rc;
4867 }
4868 rc = getsockname(sock, (struct sockaddr *)&myaddr, &len);
4869 if (rc) {
4870 ::SysError("TWinNTSystem::AnnounceUnixService", "getsockname");
4871 return rc;
4872 }
4874 socketpath.ReplaceAll("/", "\\");
4875 fp = fopen(socketpath, "wb");
4876 if (!fp) {
4877 ::SysError("TWinNTSystem::AnnounceUnixService", "fopen");
4878 return -1;
4879 }
4880 fprintf(fp, "%d", myaddr.sin_port);
4881 fclose(fp);
4882
4883 // Start accepting connections
4884 if (listen(sock, backlog)) {
4885 ::SysError("TWinNTSystem::AnnounceUnixService", "listen");
4886 return -1;
4887 }
4888
4889 return sock;
4890}
4891
4892////////////////////////////////////////////////////////////////////////////////
4893/// Close socket.
4894
4896{
4897 if (socket == -1) return;
4898 SOCKET sock = socket;
4899
4900 if (force) {
4901 ::shutdown(sock, 2);
4902 }
4903 struct linger linger = {0, 0};
4904 ::setsockopt(sock, SOL_SOCKET, SO_LINGER, (char *) &linger, sizeof(linger));
4905 while (::closesocket(sock) == SOCKET_ERROR && WSAGetLastError() == WSAEINTR) {
4907 }
4908}
4909
4910////////////////////////////////////////////////////////////////////////////////
4911/// Receive a buffer headed by a length indicator. Length is the size of
4912/// the buffer. Returns the number of bytes received in buf or -1 in
4913/// case of error.
4914
4915int TWinNTSystem::RecvBuf(int sock, void *buf, int length)
4916{
4917 Int_t header;
4918
4919 if (WinNTRecv(sock, &header, sizeof(header), 0) > 0) {
4920 int count = ::ntohl(header);
4921
4922 if (count > length) {
4923 Error("RecvBuf", "record header exceeds buffer size");
4924 return -1;
4925 } else if (count > 0) {
4926 if (WinNTRecv(sock, buf, count, 0) < 0) {
4927 Error("RecvBuf", "cannot receive buffer");
4928 return -1;
4929 }
4930 }
4931 return count;
4932 }
4933 return -1;
4934}
4935
4936////////////////////////////////////////////////////////////////////////////////
4937/// Send a buffer headed by a length indicator. Returns length of sent buffer
4938/// or -1 in case of error.
4939
4940int TWinNTSystem::SendBuf(int sock, const void *buf, int length)
4941{
4942 Int_t header = ::htonl(length);
4943
4944 if (WinNTSend(sock, &header, sizeof(header), 0) < 0) {
4945 Error("SendBuf", "cannot send header");
4946 return -1;
4947 }
4948 if (length > 0) {
4949 if (WinNTSend(sock, buf, length, 0) < 0) {
4950 Error("SendBuf", "cannot send buffer");
4951 return -1;
4952 }
4953 }
4954 return length;
4955}
4956
4957////////////////////////////////////////////////////////////////////////////////
4958/// Receive exactly length bytes into buffer. Use opt to receive out-of-band
4959/// data or to have a peek at what is in the buffer (see TSocket). Buffer
4960/// must be able to store at least length bytes. Returns the number of
4961/// bytes received (can be 0 if other side of connection was closed) or -1
4962/// in case of error, -2 in case of MSG_OOB and errno == EWOULDBLOCK, -3
4963/// in case of MSG_OOB and errno == EINVAL and -4 in case of kNoBlock and
4964/// errno == EWOULDBLOCK. Returns -5 if pipe broken or reset by peer
4965/// (EPIPE || ECONNRESET).
4966
4967int TWinNTSystem::RecvRaw(int sock, void *buf, int length, int opt)
4968{
4969 int flag;
4970
4971 switch (opt) {
4972 case kDefault:
4973 flag = 0;
4974 break;
4975 case kOob:
4976 flag = MSG_OOB;
4977 break;
4978 case kPeek:
4979 flag = MSG_PEEK;
4980 break;
4981 case kDontBlock:
4982 flag = -1;
4983 break;
4984 default:
4985 flag = 0;
4986 break;
4987 }
4988
4989 int n;
4990 if ((n = WinNTRecv(sock, buf, length, flag)) <= 0) {
4991 if (n == -1) {
4992 Error("RecvRaw", "cannot receive buffer");
4993 }
4994 return n;
4995 }
4996 return n;
4997}
4998
4999////////////////////////////////////////////////////////////////////////////////
5000/// Send exactly length bytes from buffer. Use opt to send out-of-band
5001/// data (see TSocket). Returns the number of bytes sent or -1 in case of
5002/// error. Returns -4 in case of kNoBlock and errno == EWOULDBLOCK.
5003/// Returns -5 if pipe broken or reset by peer (EPIPE || ECONNRESET).
5004
5005int TWinNTSystem::SendRaw(int sock, const void *buf, int length, int opt)
5006{
5007 int flag;
5008
5009 switch (opt) {
5010 case kDefault:
5011 flag = 0;
5012 break;
5013 case kOob:
5014 flag = MSG_OOB;
5015 break;
5016 case kDontBlock:
5017 flag = -1;
5018 break;
5019 case kPeek: // receive only option (see RecvRaw)
5020 default:
5021 flag = 0;
5022 break;
5023 }
5024
5025 int n;
5026 if ((n = WinNTSend(sock, buf, length, flag)) <= 0) {
5027 if (n == -1 && GetErrno() != EINTR) {
5028 Error("SendRaw", "cannot send buffer");
5029 }
5030 return n;
5031 }
5032 return n;
5033}
5034
5035////////////////////////////////////////////////////////////////////////////////
5036/// Set socket option.
5037
5039{
5040 u_long val = value;
5041 if (socket == -1) return -1;
5042 SOCKET sock = socket;
5043
5044 switch (opt) {
5045 case kSendBuffer:
5046 if (::setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char*)&val, sizeof(val)) == SOCKET_ERROR) {
5047 ::SysError("SetSockOpt", "setsockopt(SO_SNDBUF)");
5048 return -1;
5049 }
5050 break;
5051 case kRecvBuffer:
5052 if (::setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*)&val, sizeof(val)) == SOCKET_ERROR) {
5053 ::SysError("SetSockOpt", "setsockopt(SO_RCVBUF)");
5054 return -1;
5055 }
5056 break;
5057 case kOobInline:
5058 if (::setsockopt(sock, SOL_SOCKET, SO_OOBINLINE, (char*)&val, sizeof(val)) == SOCKET_ERROR) {
5059 SysError("SetSockOpt", "setsockopt(SO_OOBINLINE)");
5060 return -1;
5061 }
5062 break;
5063 case kKeepAlive:
5064 if (::setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char*)&val, sizeof(val)) == SOCKET_ERROR) {
5065 ::SysError("SetSockOpt", "setsockopt(SO_KEEPALIVE)");
5066 return -1;
5067 }
5068 break;
5069 case kReuseAddr:
5070 if (::setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&val, sizeof(val)) == SOCKET_ERROR) {
5071 ::SysError("SetSockOpt", "setsockopt(SO_REUSEADDR)");
5072 return -1;
5073 }
5074 break;
5075 case kNoDelay:
5076 if (::setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char*)&val, sizeof(val)) == SOCKET_ERROR) {
5077 ::SysError("SetSockOpt", "setsockopt(TCP_NODELAY)");
5078 return -1;
5079 }
5080 break;
5081 case kNoBlock:
5082 if (::ioctlsocket(sock, FIONBIO, &val) == SOCKET_ERROR) {
5083 ::SysError("SetSockOpt", "ioctl(FIONBIO)");
5084 return -1;
5085 }
5086 break;
5087#if 0
5088 case kProcessGroup:
5089 if (::ioctl(sock, SIOCSPGRP, &val) == -1) {
5090 ::SysError("SetSockOpt", "ioctl(SIOCSPGRP)");
5091 return -1;
5092 }
5093 break;
5094#endif
5095 case kAtMark: // read-only option (see GetSockOpt)
5096 case kBytesToRead: // read-only option
5097 default:
5098 Error("SetSockOpt", "illegal option (%d)", opt);
5099 return -1;
5100 break;
5101 }
5102 return 0;
5103}
5104
5105////////////////////////////////////////////////////////////////////////////////
5106/// Get socket option.
5107
5108int TWinNTSystem::GetSockOpt(int socket, int opt, int *val)
5109{
5110 if (socket == -1) return -1;
5111 SOCKET sock = socket;
5112
5113 int optlen = sizeof(*val);
5114
5115 switch (opt) {
5116 case kSendBuffer:
5117 if (::getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char*)val, &optlen) == SOCKET_ERROR) {
5118 ::SysError("GetSockOpt", "getsockopt(SO_SNDBUF)");
5119 return -1;
5120 }
5121 break;
5122 case kRecvBuffer:
5123 if (::getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*)val, &optlen) == SOCKET_ERROR) {
5124 ::SysError("GetSockOpt", "getsockopt(SO_RCVBUF)");
5125 return -1;
5126 }
5127 break;
5128 case kOobInline:
5129 if (::getsockopt(sock, SOL_SOCKET, SO_OOBINLINE, (char*)val, &optlen) == SOCKET_ERROR) {
5130 ::SysError("GetSockOpt", "getsockopt(SO_OOBINLINE)");
5131 return -1;
5132 }
5133 break;
5134 case kKeepAlive:
5135 if (::getsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char*)val, &optlen) == SOCKET_ERROR) {
5136 ::SysError("GetSockOpt", "getsockopt(SO_KEEPALIVE)");
5137 return -1;
5138 }
5139 break;
5140 case kReuseAddr:
5141 if (::getsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)val, &optlen) == SOCKET_ERROR) {
5142 ::SysError("GetSockOpt", "getsockopt(SO_REUSEADDR)");
5143 return -1;
5144 }
5145 break;
5146 case kNoDelay:
5147 if (::getsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char*)val, &optlen) == SOCKET_ERROR) {
5148 ::SysError("GetSockOpt", "getsockopt(TCP_NODELAY)");
5149 return -1;
5150 }
5151 break;
5152 case kNoBlock:
5153 {
5154 int flg = 0;
5155 if (sock == INVALID_SOCKET) {
5156 ::SysError("GetSockOpt", "INVALID_SOCKET");
5157 }
5158 *val = flg; // & O_NDELAY; It is not been defined for WIN32
5159 return -1;
5160 }
5161 break;
5162#if 0
5163 case kProcessGroup:
5164 if (::ioctlsocket(sock, SIOCGPGRP, (u_long*)val) == SOCKET_ERROR) {
5165 ::SysError("GetSockOpt", "ioctl(SIOCGPGRP)");
5166 return -1;
5167 }
5168 break;
5169#endif
5170 case kAtMark:
5171 if (::ioctlsocket(sock, SIOCATMARK, (u_long*)val) == SOCKET_ERROR) {
5172 ::SysError("GetSockOpt", "ioctl(SIOCATMARK)");
5173 return -1;
5174 }
5175 break;
5176 case kBytesToRead:
5177 if (::ioctlsocket(sock, FIONREAD, (u_long*)val) == SOCKET_ERROR) {
5178 ::SysError("GetSockOpt", "ioctl(FIONREAD)");
5179 return -1;
5180 }
5181 break;
5182 default:
5183 Error("GetSockOpt", "illegal option (%d)", opt);
5184 *val = 0;
5185 return -1;
5186 break;
5187 }
5188 return 0;
5189}
5190
5191////////////////////////////////////////////////////////////////////////////////
5192/// Connect to service servicename on server servername.
5193
5195 int tcpwindowsize, const char *protocol)
5196{
5197 short sport;
5198 struct servent *sp;
5199
5200 if (!strcmp(servername, "unix")) {
5201 return WinNTUnixConnect(port);
5202 }
5203 else if (!gSystem->AccessPathName(servername) || servername[0] == '/' ||
5204 (servername[1] == ':' && servername[2] == '/')) {
5206 }
5207
5208 if (!strcmp(protocol, "udp")){
5209 return WinNTUdpConnect(servername, port);
5210 }
5211
5212 if ((sp = ::getservbyport(::htons(port), kProtocolName))) {
5213 sport = sp->s_port;
5214 } else {
5215 sport = ::htons(port);
5216 }
5217
5219 if (!addr.IsValid()) return -1;
5220 UInt_t adr = ::htonl(addr.GetAddress());
5221
5222 struct sockaddr_in server;
5223 memset(&server, 0, sizeof(server));
5224 memcpy(&server.sin_addr, &adr, sizeof(adr));
5225 server.sin_family = addr.GetFamily();
5226 server.sin_port = sport;
5227
5228 // Create socket
5229 SOCKET sock;
5230 if ((sock = ::socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
5231 ::SysError("TWinNTSystem::WinNTConnectTcp", "socket");
5232 return -1;
5233 }
5234
5235 if (tcpwindowsize > 0) {
5238 }
5239
5240 if (::connect(sock, (struct sockaddr*) &server, sizeof(server)) == INVALID_SOCKET) {
5241 //::SysError("TWinNTSystem::UnixConnectTcp", "connect");
5242 ::closesocket(sock);
5243 return -1;
5244 }
5245 return (int) sock;
5246}
5247
5248////////////////////////////////////////////////////////////////////////////////
5249/// Connect to a Unix domain socket.
5250
5252{
5253 struct sockaddr_in myaddr;
5254 int sock;
5255
5256 memset(&myaddr, 0, sizeof(myaddr));
5257 myaddr.sin_family = AF_INET;
5258 myaddr.sin_port = port;
5259 myaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
5260
5261 // Open socket
5262 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
5263 ::SysError("TWinNTSystem::WinNTUnixConnect", "socket");
5264 return -1;
5265 }
5266
5267 while ((connect(sock, (struct sockaddr *)&myaddr, sizeof myaddr)) == -1) {
5268 if (GetErrno() == EINTR)
5269 ResetErrno();
5270 else {
5271 ::SysError("TWinNTSystem::WinNTUnixConnect", "connect");
5272 close(sock);
5273 return -1;
5274 }
5275 }
5276 return sock;
5277}
5278
5279////////////////////////////////////////////////////////////////////////////////
5280/// Connect to a Unix domain socket. Returns -1 in case of error.
5281
5283{
5284 FILE *fp;
5285 int port = 0;
5286
5287 if (!sockpath || strlen(sockpath) <= 0) {
5288 ::SysError("TWinNTSystem::WinNTUnixConnect", "socket path undefined");
5289 return -1;
5290 }
5292 socketpath.ReplaceAll("/", "\\");
5293 fp = fopen(socketpath.Data(), "rb");
5294 if (!fp) {
5295 ::SysError("TWinNTSystem::WinNTUnixConnect", "fopen");
5296 return -1;
5297 }
5298 fscanf(fp, "%d", &port);
5299 fclose(fp);
5300 /* XXX: set errno in this case */
5301 if (port < 0 || port > 65535) {
5302 ::SysError("TWinNTSystem::WinNTUnixConnect", "invalid port");
5303 return -1;
5304 }
5305 return WinNTUnixConnect(port);
5306}
5307
5308////////////////////////////////////////////////////////////////////////////////
5309/// Creates a UDP socket connection
5310/// Is called via the TSocket constructor. Returns -1 in case of error.
5311
5312int TWinNTSystem::WinNTUdpConnect(const char *hostname, int port)
5313{
5314 short sport;
5315 struct servent *sp;
5316
5317 if ((sp = getservbyport(htons(port), kProtocolName)))
5318 sport = sp->s_port;
5319 else
5320 sport = htons(port);
5321
5323 if (!addr.IsValid()) return -1;
5324 UInt_t adr = htonl(addr.GetAddress());
5325
5326 struct sockaddr_in server;
5327 memset(&server, 0, sizeof(server));
5328 memcpy(&server.sin_addr, &adr, sizeof(adr));
5329 server.sin_family = addr.GetFamily();
5330 server.sin_port = sport;
5331
5332 // Create socket
5333 int sock;
5334 if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
5335 ::SysError("TWinNTSystem::WinNTUdpConnect", "socket (%s:%d)",
5336 hostname, port);
5337 return -1;
5338 }
5339
5340 while (connect(sock, (struct sockaddr*) &server, sizeof(server)) == -1) {
5341 if (GetErrno() == EINTR)
5342 ResetErrno();
5343 else {
5344 ::SysError("TWinNTSystem::WinNTUdpConnect", "connect (%s:%d)",
5345 hostname, port);
5346 close(sock);
5347 return -1;
5348 }
5349 }
5350 return sock;
5351}
5352
5353////////////////////////////////////////////////////////////////////////////////
5354/// Open a connection to a service on a server. Returns -1 in case
5355/// connection cannot be opened.
5356/// Use tcpwindowsize to specify the size of the receive buffer, it has
5357/// to be specified here to make sure the window scale option is set (for
5358/// tcpwindowsize > 65KB and for platforms supporting window scaling).
5359/// Is called via the TSocket constructor.
5360
5362 const char *protocol)
5363{
5364 return ConnectService(server, port, tcpwindowsize, protocol);
5365}
5366
5367////////////////////////////////////////////////////////////////////////////////
5368/// Announce TCP/IP service.
5369/// Open a socket, bind to it and start listening for TCP/IP connections
5370/// on the port. If reuse is true reuse the address, backlog specifies
5371/// how many sockets can be waiting to be accepted.
5372/// Use tcpwindowsize to specify the size of the receive buffer, it has
5373/// to be specified here to make sure the window scale option is set (for
5374/// tcpwindowsize > 65KB and for platforms supporting window scaling).
5375/// The socketBindOption parameter allows to specify how the socket will be
5376/// bound. See the documentation of ESocketBindOption for the details.
5377/// Returns socket fd or -1 if socket() failed, -2 if bind() failed
5378/// or -3 if listen() failed.
5379
5382{
5383 short sport;
5384 struct servent *sp;
5385 const short kSOCKET_MINPORT = 5000, kSOCKET_MAXPORT = 15000;
5386 short tryport = kSOCKET_MINPORT;
5387
5388 if ((sp = ::getservbyport(::htons(port), kProtocolName))) {
5389 sport = sp->s_port;
5390 } else {
5391 sport = ::htons(port);
5392 }
5393
5394 if (port == 0 && reuse) {
5395 ::Error("TWinNTSystem::WinNTTcpService", "cannot do a port scan while reuse is true");
5396 return -1;
5397 }
5398
5399 if ((sp = ::getservbyport(::htons(port), kProtocolName))) {
5400 sport = sp->s_port;
5401 } else {
5402 sport = ::htons(port);
5403 }
5404
5405 // Create tcp socket
5406 SOCKET sock;
5407 if ((sock = ::socket(AF_INET, SOCK_STREAM, 0)) < 0) {
5408 ::SysError("TWinNTSystem::WinNTTcpService", "socket");
5409 return -1;
5410 }
5411
5412 if (reuse) {
5413 gSystem->SetSockOpt((int)sock, kReuseAddr, 1);
5414 }
5415
5416 if (tcpwindowsize > 0) {
5419 }
5420
5421 struct sockaddr_in inserver;
5422 memset(&inserver, 0, sizeof(inserver));
5423 inserver.sin_family = AF_INET;
5425 inserver.sin_port = sport;
5426
5427 // Bind socket
5428 if (port > 0) {
5429 if (::bind(sock, (struct sockaddr*) &inserver, sizeof(inserver)) == SOCKET_ERROR) {
5430 ::SysError("TWinNTSystem::WinNTTcpService", "bind");
5431 return -2;
5432 }
5433 } else {
5434 int bret;
5435 do {
5436 inserver.sin_port = ::htons(tryport);
5437 bret = ::bind(sock, (struct sockaddr*) &inserver, sizeof(inserver));
5438 tryport++;
5439 } while (bret == SOCKET_ERROR && WSAGetLastError() == WSAEADDRINUSE &&
5441 if (bret == SOCKET_ERROR) {
5442 ::SysError("TWinNTSystem::WinNTTcpService", "bind (port scan)");
5443 return -2;
5444 }
5445 }
5446
5447 // Start accepting connections
5448 if (::listen(sock, backlog) == SOCKET_ERROR) {
5449 ::SysError("TWinNTSystem::WinNTTcpService", "listen");
5450 return -3;
5451 }
5452 return (int)sock;
5453}
5454
5455////////////////////////////////////////////////////////////////////////////////
5456/// Announce UDP service.
5457
5459{
5460 // Open a socket, bind to it and start listening for UDP connections
5461 // on the port. If reuse is true reuse the address, backlog specifies
5462 // how many sockets can be waiting to be accepted. If port is 0 a port
5463 // scan will be done to find a free port. This option is mutual exlusive
5464 // with the reuse option.
5465 // The socketBindOption parameter allows to specify how the socket will be
5466 // bound. See the documentation of ESocketBindOption for the details.
5467
5468 const short kSOCKET_MINPORT = 5000, kSOCKET_MAXPORT = 15000;
5469 short sport, tryport = kSOCKET_MINPORT;
5470 struct servent *sp;
5471
5472 if ((sp = getservbyport(htons(port), kProtocolName)))
5473 sport = sp->s_port;
5474 else
5475 sport = htons(port);
5476
5477 // Create udp socket
5478 int sock;
5479 if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
5480 ::SysError("TUnixSystem::UnixUdpService", "socket");
5481 return -1;
5482 }
5483
5484 struct sockaddr_in inserver;
5485 memset(&inserver, 0, sizeof(inserver));
5486 inserver.sin_family = AF_INET;
5488 inserver.sin_port = sport;
5489
5490 // Bind socket
5491 if (port > 0) {
5492 if (bind(sock, (struct sockaddr*) &inserver, sizeof(inserver))) {
5493 ::SysError("TWinNTSystem::AnnounceUdpService", "bind");
5494 return -2;
5495 }
5496 } else {
5497 int bret;
5498 do {
5499 inserver.sin_port = htons(tryport);
5500 bret = bind(sock, (struct sockaddr*) &inserver, sizeof(inserver));
5501 tryport++;
5502 } while (bret == SOCKET_ERROR && WSAGetLastError() == WSAEADDRINUSE &&
5504 if (bret < 0) {
5505 ::SysError("TWinNTSystem::AnnounceUdpService", "bind (port scan)");
5506 return -2;
5507 }
5508 }
5509
5510 // Start accepting connections
5511 if (listen(sock, backlog)) {
5512 ::SysError("TWinNTSystem::AnnounceUdpService", "listen");
5513 return -3;
5514 }
5515
5516 return sock;
5517}
5518
5519////////////////////////////////////////////////////////////////////////////////
5520/// Accept a connection. In case of an error return -1. In case
5521/// non-blocking I/O is enabled and no connections are available
5522/// return -2.
5523
5525{
5526 int soc = -1;
5527 SOCKET sock = socket;
5528
5529 while ((soc = ::accept(sock, 0, 0)) == INVALID_SOCKET &&
5530 (::WSAGetLastError() == WSAEINTR)) {
5532 }
5533
5534 if (soc == -1) {
5536 return -2;
5537 } else {
5538 ::SysError("AcceptConnection", "accept");
5539 return -1;
5540 }
5541 }
5542 return soc;
5543}
5544
5545//---- System, CPU and Memory info ---------------------------------------------
5546
5547// !!! using undocumented functions and structures !!!
5548
5549#define SystemBasicInformation 0
5550#define SystemPerformanceInformation 2
5551
5568
5569typedef struct
5570{
5571 LARGE_INTEGER liIdleTime;
5572 DWORD dwSpare[76];
5574
5587
5588typedef LONG (WINAPI *PROCNTQSI) (UINT, PVOID, ULONG, PULONG);
5589
5590#define Li2Double(x) ((double)((x).HighPart) * 4.294967296E9 + (double)((x).LowPart))
5591
5592////////////////////////////////////////////////////////////////////////////////
5593/// Calculate the CPU clock speed using the 'rdtsc' instruction.
5594/// RDTSC: Read Time Stamp Counter.
5595
5596static DWORD GetCPUSpeed()
5597{
5598 LARGE_INTEGER ulFreq, ulTicks, ulValue, ulStartCounter;
5599
5600 // Query for high-resolution counter frequency
5601 // (this is not the CPU frequency):
5603 // Query current value:
5605 // Calculate end value (one second interval);
5606 // this is (current + frequency)
5607 ulValue.QuadPart = ulTicks.QuadPart + ulFreq.QuadPart/10;
5608 ulStartCounter.QuadPart = __rdtsc();
5609
5610 // Loop for one second (measured with the high-resolution counter):
5611 do {
5613 } while (ulTicks.QuadPart <= ulValue.QuadPart);
5614 // Now again read CPU time-stamp counter:
5615 return (DWORD)((__rdtsc() - ulStartCounter.QuadPart)/100000);
5616 } else {
5617 // No high-resolution counter present:
5618 return 0;
5619 }
5620}
5621
5622#define BUFSIZE 80
5623#define SM_SERVERR2 89
5624typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO);
5625
5626////////////////////////////////////////////////////////////////////////////////
5627
5628static const char *GetWindowsVersion()
5629{
5632 PGNSI pGNSI;
5633 BOOL bOsVersionInfoEx;
5634 static char *strReturn = nullptr;
5635 char temp[512];
5636
5637 if (!strReturn)
5638 strReturn = new char[2048];
5639 else
5640 return strReturn;
5641
5642 ZeroMemory(&si, sizeof(SYSTEM_INFO));
5643 ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
5644
5645 // Try calling GetVersionEx using the OSVERSIONINFOEX structure.
5646 // If that fails, try using the OSVERSIONINFO structure.
5647
5648 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
5649
5651 {
5652 osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
5653 if (! GetVersionEx ( (OSVERSIONINFO *) &osvi) )
5654 return "";
5655 }
5656
5657 // Call GetNativeSystemInfo if supported or GetSystemInfo otherwise.
5658 pGNSI = (PGNSI) GetProcAddress( GetModuleHandle("kernel32.dll"),
5659 "GetNativeSystemInfo");
5660 if(NULL != pGNSI)
5661 pGNSI(&si);
5662 else GetSystemInfo(&si);
5663
5664 switch (osvi.dwPlatformId)
5665 {
5666 // Test for the Windows NT product family.
5668
5669 // Test for the specific product.
5670 if ( osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 0 )
5671 {
5672 if( osvi.wProductType == VER_NT_WORKSTATION )
5673 strlcpy(strReturn, "Microsoft Windows Vista ",2048);
5674 else strlcpy(strReturn, "Windows Server \"Longhorn\" " ,2048);
5675 }
5676 if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2 )
5677 {
5679 strlcpy(strReturn, "Microsoft Windows Server 2003 \"R2\" ",2048);
5680 else if( osvi.wProductType == VER_NT_WORKSTATION &&
5681 si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64)
5682 {
5683 strlcpy(strReturn, "Microsoft Windows XP Professional x64 Edition ",2048);
5684 }
5685 else strlcpy(strReturn, "Microsoft Windows Server 2003, ",2048);
5686 }
5687 if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1 )
5688 strlcpy(strReturn, "Microsoft Windows XP ",2048);
5689
5690 if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0 )
5691 strlcpy(strReturn, "Microsoft Windows 2000 ",2048);
5692
5693 if ( osvi.dwMajorVersion <= 4 )
5694 strlcpy(strReturn, "Microsoft Windows NT ",2048);
5695
5696 // Test for specific product on Windows NT 4.0 SP6 and later.
5697 if( bOsVersionInfoEx )
5698 {
5699 // Test for the workstation type.
5700 if ( osvi.wProductType == VER_NT_WORKSTATION &&
5701 si.wProcessorArchitecture!=PROCESSOR_ARCHITECTURE_AMD64)
5702 {
5703 if( osvi.dwMajorVersion == 4 )
5704 strlcat(strReturn, "Workstation 4.0 ",2048 );
5705 else if( osvi.wSuiteMask & VER_SUITE_PERSONAL )
5706 strlcat(strReturn, "Home Edition " ,2048);
5707 else strlcat(strReturn, "Professional " ,2048);
5708 }
5709 // Test for the server type.
5710 else if ( osvi.wProductType == VER_NT_SERVER ||
5711 osvi.wProductType == VER_NT_DOMAIN_CONTROLLER )
5712 {
5713 if(osvi.dwMajorVersion==5 && osvi.dwMinorVersion==2)
5714 {
5715 if ( si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_IA64 )
5716 {
5717 if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
5718 strlcat(strReturn, "Datacenter Edition for Itanium-based Systems",2048 );
5719 else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
5720 strlcat(strReturn, "Enterprise Edition for Itanium-based Systems" ,2048);
5721 }
5722 else if ( si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64 )
5723 {
5724 if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
5725 strlcat(strReturn, "Datacenter x64 Edition ",2048 );
5726 else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
5727 strlcat(strReturn, "Enterprise x64 Edition ",2048 );
5728 else strlcat(strReturn, "Standard x64 Edition ",2048 );
5729 }
5730 else
5731 {
5732 if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
5733 strlcat(strReturn, "Datacenter Edition ",2048 );
5734 else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
5735 strlcat(strReturn, "Enterprise Edition ",2048 );
5736 else if ( osvi.wSuiteMask == VER_SUITE_BLADE )
5737 strlcat(strReturn, "Web Edition " ,2048);
5738 else strlcat(strReturn, "Standard Edition ",2048 );
5739 }
5740 }
5741 else if(osvi.dwMajorVersion==5 && osvi.dwMinorVersion==0)
5742 {
5743 if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
5744 strlcat(strReturn, "Datacenter Server ",2048 );
5745 else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
5746 strlcat(strReturn, "Advanced Server ",2048 );
5747 else strlcat(strReturn, "Server ",2048 );
5748 }
5749 else // Windows NT 4.0
5750 {
5751 if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
5752 strlcat(strReturn, "Server 4.0, Enterprise Edition " ,2048);
5753 else strlcat(strReturn, "Server 4.0 ",2048 );
5754 }
5755 }
5756 }
5757 // Test for specific product on Windows NT 4.0 SP5 and earlier
5758 else
5759 {
5760 HKEY hKey;
5762 DWORD dwBufLen=BUFSIZE*sizeof(TCHAR);
5763 LONG lRet;
5764
5766 "SYSTEM\\CurrentControlSet\\Control\\ProductOptions",
5767 0, KEY_QUERY_VALUE, &hKey );
5768 if( lRet != ERROR_SUCCESS )
5769 return "";
5770
5771 lRet = RegQueryValueEx( hKey, "ProductType", NULL, NULL,
5773 RegCloseKey( hKey );
5774
5775 if( (lRet != ERROR_SUCCESS) || (dwBufLen > BUFSIZE*sizeof(TCHAR)) )
5776 return "";
5777
5778 if ( lstrcmpi( "WINNT", szProductType) == 0 )
5779 strlcat(strReturn, "Workstation " ,2048);
5780 if ( lstrcmpi( "LANMANNT", szProductType) == 0 )
5781 strlcat(strReturn, "Server " ,2048);
5782 if ( lstrcmpi( "SERVERNT", szProductType) == 0 )
5783 strlcat(strReturn, "Advanced Server " ,2048);
5784 snprintf(temp,512, "%d.%d ", osvi.dwMajorVersion, osvi.dwMinorVersion);
5785 strlcat(strReturn, temp,2048);
5786 }
5787
5788 // Display service pack (if any) and build number.
5789
5790 if( osvi.dwMajorVersion == 4 &&
5791 lstrcmpi( osvi.szCSDVersion, "Service Pack 6" ) == 0 )
5792 {
5793 HKEY hKey;
5794 LONG lRet;
5795
5796 // Test for SP6 versus SP6a.
5798 "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Hotfix\\Q246009",
5799 0, KEY_QUERY_VALUE, &hKey );
5800 if( lRet == ERROR_SUCCESS ) {
5801 snprintf(temp, 512, "Service Pack 6a (Build %d)", osvi.dwBuildNumber & 0xFFFF );
5802 strlcat(strReturn, temp,2048 );
5803 }
5804 else // Windows NT 4.0 prior to SP6a
5805 {
5806 snprintf(temp,512, "%s (Build %d)", osvi.szCSDVersion, osvi.dwBuildNumber & 0xFFFF);
5807 strlcat(strReturn, temp,2048 );
5808 }
5809
5810 RegCloseKey( hKey );
5811 }
5812 else // not Windows NT 4.0
5813 {
5814 snprintf(temp, 512,"%s (Build %d)", osvi.szCSDVersion, osvi.dwBuildNumber & 0xFFFF);
5815 strlcat(strReturn, temp,2048 );
5816 }
5817
5818 break;
5819
5820 // Test for the Windows Me/98/95.
5822
5823 if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0)
5824 {
5825 strlcpy(strReturn, "Microsoft Windows 95 ",2048);
5826 if (osvi.szCSDVersion[1]=='C' || osvi.szCSDVersion[1]=='B')
5827 strlcat(strReturn, "OSR2 " ,2048);
5828 }
5829
5830 if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10)
5831 {
5832 strlcpy(strReturn, "Microsoft Windows 98 ",2048);
5833 if ( osvi.szCSDVersion[1]=='A' || osvi.szCSDVersion[1]=='B')
5834 strlcat(strReturn, "SE ",2048 );
5835 }
5836
5837 if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90)
5838 {
5839 strlcpy(strReturn, "Microsoft Windows Millennium Edition",2048);
5840 }
5841 break;
5842
5844 strlcpy(strReturn, "Microsoft Win32s",2048);
5845 break;
5846 }
5847 return strReturn;
5848}
5849
5850////////////////////////////////////////////////////////////////////////////////
5851/// Use assembly to retrieve the L2 cache information ...
5852
5853static int GetL2CacheSize()
5854{
5855 unsigned nHighestFeatureEx;
5856 int nBuff[4];
5857
5858 __cpuid(nBuff, 0x80000000);
5859 nHighestFeatureEx = (unsigned)nBuff[0];
5860 // Get cache size
5861 if (nHighestFeatureEx >= 0x80000006) {
5862 __cpuid(nBuff, 0x80000006);
5863 return (((unsigned)nBuff[2])>>16);
5864 }
5865 else return 0;
5866}
5867
5868////////////////////////////////////////////////////////////////////////////////
5869/// Get system info for Windows NT.
5870
5872{
5877 HKEY hKey;
5878 char szKeyValueString[80];
5879 DWORD szKeyValueDword;
5880 DWORD dwBufLen;
5881 LONG status;
5883
5885 GetModuleHandle("ntdll"), "NtQuerySystemInformation");
5886
5888 ::Error("GetWinNTSysInfo",
5889 "Error on GetProcAddress(NtQuerySystemInformation)");
5890 return;
5891 }
5892
5894 &SysPerfInfo, sizeof(SysPerfInfo),
5895 NULL);
5896 OsVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
5899 statex.dwLength = sizeof(statex);
5901 ::Error("GetWinNTSysInfo", "Error on GlobalMemoryStatusEx()");
5902 return;
5903 }
5904 sysinfo->fCpus = sysInfo.dwNumberOfProcessors;
5905 sysinfo->fPhysRam = (Int_t)(statex.ullTotalPhys >> 20);
5906 sysinfo->fOS = GetWindowsVersion();
5907 sysinfo->fModel = "";
5908 sysinfo->fCpuType = "";
5909 sysinfo->fCpuSpeed = GetCPUSpeed();
5910 sysinfo->fBusSpeed = 0; // bus speed in MHz
5911 sysinfo->fL2Cache = GetL2CacheSize();
5912
5913 status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System",
5914 0, KEY_QUERY_VALUE, &hKey);
5915 if (status == ERROR_SUCCESS) {
5916 dwBufLen = sizeof(szKeyValueString);
5918 &dwBufLen);
5919 sysinfo->fModel = szKeyValueString;
5920 RegCloseKey (hKey);
5921 }
5923 "Hardware\\Description\\System\\CentralProcessor\\0",
5924 0, KEY_QUERY_VALUE, &hKey);
5925 if (status == ERROR_SUCCESS) {
5926 dwBufLen = sizeof(szKeyValueString);
5927 status = RegQueryValueEx(hKey, "ProcessorNameString", NULL, NULL,
5929 if (status == ERROR_SUCCESS)
5930 sysinfo->fCpuType = szKeyValueString;
5931 dwBufLen = sizeof(DWORD);
5933 &dwBufLen);
5934 if ((status == ERROR_SUCCESS) && ((sysinfo->fCpuSpeed <= 0) ||
5935 (sysinfo->fCpuSpeed < (szKeyValueDword >> 1))))
5936 sysinfo->fCpuSpeed = (Int_t)szKeyValueDword;
5937 RegCloseKey (hKey);
5938 }
5939 sysinfo->fCpuType.Remove(TString::kBoth, ' ');
5940 sysinfo->fModel.Remove(TString::kBoth, ' ');
5941}
5942
5943////////////////////////////////////////////////////////////////////////////////
5944/// Get CPU stat for Window. Use sampleTime to set the interval over which
5945/// the CPU load will be measured, in ms (default 1000).
5946
5948{
5953
5955 static ULARGE_INTEGER ul_sys_idleold = {0, 0};
5956 static ULARGE_INTEGER ul_sys_kernelold = {0, 0};
5957 static ULARGE_INTEGER ul_sys_userold = {0, 0};
5959
5963
5967
5968 HMODULE hModImagehlp = LoadLibrary( "Kernel32.dll" );
5969 if (!hModImagehlp) {
5970 ::Error("GetWinNTCpuInfo", "Error on LoadLibrary(Kernel32.dll)");
5971 return;
5972 }
5973
5975 "GetSystemTimes" );
5976 if (!pGetSystemTimes) {
5977 ::Error("GetWinNTCpuInfo", "Error on GetProcAddress(GetSystemTimes)");
5978 return;
5979 }
5981
5982again:
5984 GetSystemTime(&st_fun_time);
5986
5991
5992 ul_sys_idle_diff.QuadPart = ul_sys_idle.QuadPart -
5993 ul_sys_idleold.QuadPart;
5994 ul_sys_kernel_diff.QuadPart = ul_sys_kernel.QuadPart -
5995 ul_sys_kernelold.QuadPart;
5996 ul_sys_user_diff.QuadPart = ul_sys_user.QuadPart -
5997 ul_sys_userold.QuadPart;
5998
5999 ul_fun_time_diff.QuadPart = ul_fun_time.QuadPart -
6000 ul_fun_timeold.QuadPart;
6001
6002 ul_sys_idleold.QuadPart = ul_sys_idle.QuadPart;
6003 ul_sys_kernelold.QuadPart = ul_sys_kernel.QuadPart;
6004 ul_sys_userold.QuadPart = ul_sys_user.QuadPart;
6005
6006 if (ul_fun_timeold.QuadPart == 0) {
6007 Sleep(sampleTime);
6008 ul_fun_timeold.QuadPart = ul_fun_time.QuadPart;
6009 goto again;
6010 }
6011 ul_fun_timeold.QuadPart = ul_fun_time.QuadPart;
6012
6019 idle_ratio /= (Float_t)sysInfo.dwNumberOfProcessors;
6020 user_ratio /= (Float_t)sysInfo.dwNumberOfProcessors;
6021 kernel_ratio /= (Float_t)sysInfo.dwNumberOfProcessors;
6022 total_ratio = 100.0 - idle_ratio;
6023
6024 cpuinfo->fLoad1m = 0; // cpu load average over 1 m
6025 cpuinfo->fLoad5m = 0; // cpu load average over 5 m
6026 cpuinfo->fLoad15m = 0; // cpu load average over 15 m
6027 cpuinfo->fUser = user_ratio; // cpu user load in percentage
6028 cpuinfo->fSys = kernel_ratio; // cpu sys load in percentage
6029 cpuinfo->fTotal = total_ratio; // cpu user+sys load in percentage
6030 cpuinfo->fIdle = idle_ratio; // cpu idle percentage
6031}
6032
6033////////////////////////////////////////////////////////////////////////////////
6034/// Get VM stat for Windows NT.
6035
6037{
6040 statex.dwLength = sizeof(statex);
6042 ::Error("GetWinNTMemInfo", "Error on GlobalMemoryStatusEx()");
6043 return;
6044 }
6045 used = (Long64_t)(statex.ullTotalPhys - statex.ullAvailPhys);
6046 free = (Long64_t) statex.ullAvailPhys;
6047 total = (Long64_t) statex.ullTotalPhys;
6048
6049 meminfo->fMemTotal = (Int_t) (total >> 20); // divide by 1024 * 1024
6050 meminfo->fMemUsed = (Int_t) (used >> 20);
6051 meminfo->fMemFree = (Int_t) (free >> 20);
6052
6053 swap_total = (Long64_t)(statex.ullTotalPageFile - statex.ullTotalPhys);
6054 swap_avail = (Long64_t)(statex.ullAvailPageFile - statex.ullAvailPhys);
6056
6057 meminfo->fSwapTotal = (Int_t) (swap_total >> 20);
6058 meminfo->fSwapUsed = (Int_t) (swap_used >> 20);
6059 meminfo->fSwapFree = (Int_t) (swap_avail >> 20);
6060}
6061
6062////////////////////////////////////////////////////////////////////////////////
6063/// Get process info for this process on Windows NT.
6064
6066{
6071
6072 typedef BOOL (__stdcall *GetProcessMemoryInfoProc)( HANDLE Process,
6075
6076 HMODULE hModImagehlp = LoadLibrary( "Psapi.dll" );
6077 if (!hModImagehlp) {
6078 ::Error("GetWinNTProcInfo", "Error on LoadLibrary(Psapi.dll)");
6079 return;
6080 }
6081
6083 hModImagehlp, "GetProcessMemoryInfo" );
6084 if (!pGetProcessMemoryInfo) {
6085 ::Error("GetWinNTProcInfo",
6086 "Error on GetProcAddress(GetProcessMemoryInfo)");
6087 return;
6088 }
6089
6090 if ( pGetProcessMemoryInfo( GetCurrentProcess(), &pmc, sizeof(pmc)) ) {
6091 procinfo->fMemResident = pmc.WorkingSetSize / 1024;
6092 procinfo->fMemVirtual = pmc.PagefileUsage / 1024;
6093 }
6095 &kerneltime, &usertime)) {
6096
6097 /* Convert FILETIMEs (0.1 us) to struct timeval */
6098 memcpy(&li, &kerneltime, sizeof(FILETIME));
6099 li.QuadPart /= 10L; /* Convert to microseconds */
6100 ru_stime.tv_sec = li.QuadPart / 1000000L;
6101 ru_stime.tv_usec = li.QuadPart % 1000000L;
6102
6103 memcpy(&li, &usertime, sizeof(FILETIME));
6104 li.QuadPart /= 10L; /* Convert to microseconds */
6105 ru_utime.tv_sec = li.QuadPart / 1000000L;
6106 ru_utime.tv_usec = li.QuadPart % 1000000L;
6107
6108 procinfo->fCpuUser = (Float_t)(ru_utime.tv_sec) +
6109 ((Float_t)(ru_utime.tv_usec) / 1000000.);
6110 procinfo->fCpuSys = (Float_t)(ru_stime.tv_sec) +
6111 ((Float_t)(ru_stime.tv_usec) / 1000000.);
6112 }
6113}
6114
6115////////////////////////////////////////////////////////////////////////////////
6116/// Returns static system info, like OS type, CPU type, number of CPUs
6117/// RAM size, etc into the SysInfo_t structure. Returns -1 in case of error,
6118/// 0 otherwise.
6119
6121{
6122 if (!info) return -1;
6124 return 0;
6125}
6126
6127////////////////////////////////////////////////////////////////////////////////
6128/// Returns cpu load average and load info into the CpuInfo_t structure.
6129/// Returns -1 in case of error, 0 otherwise. Use sampleTime to set the
6130/// interval over which the CPU load will be measured, in ms (default 1000).
6131
6133{
6134 if (!info) return -1;
6136 return 0;
6137}
6138
6139////////////////////////////////////////////////////////////////////////////////
6140/// Returns ram and swap memory usage info into the MemInfo_t structure.
6141/// Returns -1 in case of error, 0 otherwise.
6142
6144{
6145 if (!info) return -1;
6147 return 0;
6148}
6149
6150////////////////////////////////////////////////////////////////////////////////
6151/// Returns cpu and memory used by this process into the ProcInfo_t structure.
6152/// Returns -1 in case of error, 0 otherwise.
6153
6155{
6156 if (!info) return -1;
6158 return 0;
6159}
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 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:505
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:2998
static void ShutDown()
Shut down ROOT.
Definition TROOT.cxx:3291
static Bool_t Initialized()
Return kTRUE if the TROOT object has been initialized.
Definition TROOT.cxx:2915
static const TString & GetLibDir()
Get the library directory in the installation.
Definition TROOT.cxx:3026
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:713
@ kBoth
Definition TString.h:284
Bool_t IsNull() const
Definition TString.h:422
TString & Append(const char *cs)
Definition TString.h:581
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:556
TString & GetLastErrorString()
Return the thread local storage for the custom last error message.
Definition TSystem.cxx:2117
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:326
Int_t fBeepDuration
Definition TSystem.h:298
static void ResetErrno()
Static function resetting system error number.
Definition TSystem.cxx:286
virtual Bool_t ExpandPathName(TString &path)
Expand a pathname getting rid of special shell characters like ~.
Definition TSystem.cxx:1289
const char * pwd()
Definition TSystem.h:434
static Int_t GetErrno()
Static function returning system error number.
Definition TSystem.cxx:278
@ 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:496
virtual int SetSockOpt(int sock, int kind, int val)
Set socket option.
Definition TSystem.cxx:2451
virtual const char * Getenv(const char *env)
Get environment variable.
Definition TSystem.cxx:1680
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:1320
virtual const char * FindFile(const char *search, TString &file, EAccessMode mode=kFileExists)
Find location of file in a search path.
Definition TSystem.cxx:1553
virtual const char * ExpandFileName(const char *fname)
Expand a pathname getting rid of special shell characters like ~.
Definition TSystem.cxx:1113
virtual TFileHandler * RemoveFileHandler(TFileHandler *fh)
Remove a file handler from the list of file handlers.
Definition TSystem.cxx:566
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:1872
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:1413
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:1311
virtual void ExitLoop()
Exit from event loop.
Definition TSystem.cxx:394
virtual Bool_t Init()
Initialize the OS interface.
Definition TSystem.cxx:182
virtual void AddTimer(TTimer *t)
Add timer to list of system timers.
Definition TSystem.cxx:473
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:534
TSeqCollection * fSignalHandler
Definition TSystem.h:305
virtual void Exit(int code, Bool_t mode=kTRUE)
Exit the application.
Definition TSystem.cxx:729
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:759
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:1563
virtual TInetAddress GetHostByName(const char *server)
Get Internet Protocol (IP) address of host.
Definition TSystem.cxx:2306
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:2151
virtual TSignalHandler * RemoveSignalHandler(TSignalHandler *sh)
Remove a signal handler from list of signal handlers.
Definition TSystem.cxx:544
static const char * StripOffProto(const char *path, const char *proto)
Strip off protocol string from specified path.
Definition TSystem.cxx:116
virtual Bool_t ProcessEvents()
Process pending events (GUI, timers, sockets).
Definition TSystem.cxx:418
virtual TTimer * RemoveTimer(TTimer *t)
Remove timer from list of system timers.
Definition TSystem.cxx:483
virtual void StackTrace()
Print a stack trace.
Definition TSystem.cxx:747
char * DynamicPathName(const char *lib, Bool_t quiet=kFALSE)
Find a dynamic library called lib using the system search paths.
Definition TSystem.cxx:2035
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.
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