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