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