00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifdef HAVE_CONFIG
00022 #include "config.h"
00023 #endif
00024
00025 #include "Windows4Root.h"
00026 #include "TWinNTSystem.h"
00027 #include "TROOT.h"
00028 #include "TError.h"
00029 #include "TOrdCollection.h"
00030 #include "TRegexp.h"
00031 #include "TException.h"
00032 #include "TEnv.h"
00033 #include "TSocket.h"
00034 #include "TApplication.h"
00035 #include "TWin32SplashThread.h"
00036 #include "Win32Constants.h"
00037 #include "TInterpreter.h"
00038 #include "TObjString.h"
00039 #include "TVirtualX.h"
00040
00041 #include <sys/utime.h>
00042 #include <sys/timeb.h>
00043 #include <process.h>
00044 #include <io.h>
00045 #include <direct.h>
00046 #include <ctype.h>
00047 #include <float.h>
00048 #include <sys/stat.h>
00049 #include <signal.h>
00050 #include <stdio.h>
00051 #include <errno.h>
00052 #include <lm.h>
00053 #include <dbghelp.h>
00054 #include <Tlhelp32.h>
00055 #include <sstream>
00056 #include <iostream>
00057 #include <list>
00058 #include <shlobj.h>
00059 #include <conio.h>
00060
00061 extern "C" {
00062 extern void Gl_setwidth(int width);
00063 extern int G__get_security_error();
00064 extern int G__genericerror(const char* msg);
00065 void *_ReturnAddress(void);
00066 }
00067
00068
00069 class TFdSet {
00070 private:
00071 fd_set *fds_bits;
00072 public:
00073 TFdSet() { fds_bits = new fd_set; fds_bits->fd_count = 0; }
00074 virtual ~TFdSet() { delete fds_bits; }
00075 void Copy(TFdSet &fd) const { memcpy((void*)fd.fds_bits, fds_bits, sizeof(fd_set)); }
00076 TFdSet(const TFdSet& fd) { fd.Copy(*this); }
00077 TFdSet& operator=(const TFdSet& fd) { fd.Copy(*this); return *this; }
00078 void Zero() { fds_bits->fd_count = 0; }
00079 void Set(Int_t fd)
00080 {
00081 if (fds_bits->fd_count < FD_SETSIZE-1)
00082 fds_bits->fd_array[fds_bits->fd_count++] = (SOCKET)fd;
00083 else
00084 ::SysError("TFdSet::Set", "fd_count will exeed FD_SETSIZE");
00085 }
00086 void Clr(Int_t fd)
00087 {
00088 int i;
00089 for (i=0; i<fds_bits->fd_count; i++) {
00090 if (fds_bits->fd_array[i]==(SOCKET)fd) {
00091 while (i<fds_bits->fd_count-1) {
00092 fds_bits->fd_array[i] = fds_bits->fd_array[i+1];
00093 i++;
00094 }
00095 fds_bits->fd_count--;
00096 break;
00097 }
00098 }
00099 }
00100 Int_t IsSet(Int_t fd) { return __WSAFDIsSet((SOCKET)fd, fds_bits); }
00101 Int_t *GetBits() { return fds_bits && fds_bits->fd_count ? (Int_t*)fds_bits : 0; }
00102 UInt_t GetCount() { return (UInt_t)fds_bits->fd_count; }
00103 Int_t GetFd(Int_t i) { return i<fds_bits->fd_count ? fds_bits->fd_array[i] : 0; }
00104 };
00105
00106 namespace {
00107 const char *kProtocolName = "tcp";
00108 typedef void (*SigHandler_t)(ESignals);
00109 static TWinNTSystem::ThreadMsgFunc_t gGUIThreadMsgFunc = 0;
00110
00111 static HANDLE gGlobalEvent;
00112 static HANDLE gTimerThreadHandle;
00113 typedef NET_API_STATUS (WINAPI *pfn1)(LPVOID);
00114 typedef NET_API_STATUS (WINAPI *pfn2)(LPCWSTR, LPCWSTR, DWORD, LPBYTE*);
00115 typedef NET_API_STATUS (WINAPI *pfn3)(LPCWSTR, LPCWSTR, DWORD, LPBYTE*,
00116 DWORD, LPDWORD, LPDWORD, PDWORD);
00117 typedef NET_API_STATUS (WINAPI *pfn4)(LPCWSTR, DWORD, LPBYTE*, DWORD, LPDWORD,
00118 LPDWORD, PDWORD);
00119 static pfn1 p2NetApiBufferFree;
00120 static pfn2 p2NetUserGetInfo;
00121 static pfn3 p2NetLocalGroupGetMembers;
00122 static pfn4 p2NetLocalGroupEnum;
00123
00124 static struct signal_map {
00125 int code;
00126 SigHandler_t handler;
00127 char *signame;
00128 } signal_map[kMAXSIGNALS] = {
00129 -1 , 0, "bus error",
00130 SIGSEGV, 0, "segmentation violation",
00131 -1 , 0, "bad argument to system call",
00132 -1 , 0, "write on a pipe with no one to read it",
00133 SIGILL, 0, "illegal instruction",
00134 -1 , 0, "quit",
00135 SIGINT, 0, "interrupt",
00136 -1 , 0, "window size change",
00137 -1 , 0, "alarm clock",
00138 -1 , 0, "death of a child",
00139 -1 , 0, "urgent data arrived on an I/O channel",
00140 SIGFPE, 0, "floating point exception",
00141 SIGTERM, 0, "termination signal",
00142 -1 , 0, "user-defined signal 1",
00143 -1 , 0, "user-defined signal 2"
00144 };
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158 static int WinNTRecv(int socket, void *buffer, int length, int flag)
00159 {
00160
00161
00162
00163
00164
00165
00166 if (socket == -1) return -1;
00167 SOCKET sock = socket;
00168
00169 int once = 0;
00170 if (flag == -1) {
00171 flag = 0;
00172 once = 1;
00173 }
00174 if (flag == MSG_PEEK) {
00175 once = 1;
00176 }
00177
00178 int nrecv, n;
00179 char *buf = (char *)buffer;
00180
00181 for (n = 0; n < length; n += nrecv) {
00182 if ((nrecv = ::recv(sock, buf+n, length-n, flag)) <= 0) {
00183 if (nrecv == 0) {
00184 break;
00185 }
00186 if (flag == MSG_OOB) {
00187 if (::WSAGetLastError() == WSAEWOULDBLOCK) {
00188 return -2;
00189 } else if (::WSAGetLastError() == WSAEINVAL) {
00190 return -3;
00191 }
00192 }
00193 if (::WSAGetLastError() == WSAEWOULDBLOCK) {
00194 return -4;
00195 } else {
00196 if (::WSAGetLastError() != WSAEINTR)
00197 ::SysError("TWinNTSystem::WinNTRecv", "recv");
00198 if (::WSAGetLastError() == EPIPE ||
00199 ::WSAGetLastError() == WSAECONNRESET)
00200 return -5;
00201 else
00202 return -1;
00203 }
00204 }
00205 if (once) {
00206 return nrecv;
00207 }
00208 }
00209 return n;
00210 }
00211
00212
00213 static int WinNTSend(int socket, const void *buffer, int length, int flag)
00214 {
00215
00216
00217
00218
00219
00220 if (socket < 0) return -1;
00221 SOCKET sock = socket;
00222
00223 int once = 0;
00224 if (flag == -1) {
00225 flag = 0;
00226 once = 1;
00227 }
00228
00229 int nsent, n;
00230 const char *buf = (const char *)buffer;
00231
00232 for (n = 0; n < length; n += nsent) {
00233 if ((nsent = ::send(sock, buf+n, length-n, flag)) <= 0) {
00234 if (nsent == 0) {
00235 break;
00236 }
00237 if (::WSAGetLastError() == WSAEWOULDBLOCK) {
00238 return -4;
00239 } else {
00240 if (::WSAGetLastError() != WSAEINTR)
00241 ::SysError("TWinNTSystem::WinNTSend", "send");
00242 if (::WSAGetLastError() == EPIPE ||
00243 ::WSAGetLastError() == WSAECONNRESET)
00244 return -5;
00245 else
00246 return -1;
00247 }
00248 }
00249 if (once) {
00250 return nsent;
00251 }
00252 }
00253 return n;
00254 }
00255
00256
00257 static int WinNTSelect(TFdSet *readready, TFdSet *writeready, Long_t timeout)
00258 {
00259
00260
00261
00262 int retcode;
00263 fd_set* rbits = readready ? (fd_set*)readready->GetBits() : 0;
00264 fd_set* wbits = writeready ? (fd_set*)writeready->GetBits() : 0;
00265
00266 if (timeout >= 0) {
00267 timeval tv;
00268 tv.tv_sec = timeout / 1000;
00269 tv.tv_usec = (timeout % 1000) * 1000;
00270
00271 retcode = ::select(0, rbits, wbits, 0, &tv);
00272 } else {
00273 retcode = ::select(0, rbits, wbits, 0, 0);
00274 }
00275
00276 if (retcode == SOCKET_ERROR) {
00277 int errcode = ::WSAGetLastError();
00278
00279
00280
00281 if (errcode == WSAENOTSOCK) {
00282 struct __stat64 buf;
00283 int result = _fstat64( readready->GetFd(0), &buf );
00284 if ( result == 0 ) {
00285 if (buf.st_size > 0)
00286 return 1;
00287 }
00288
00289
00290 if (gGlobalEvent) {
00291 ::WaitForSingleObject(gGlobalEvent, 1);
00292 ::ResetEvent(gGlobalEvent);
00293 }
00294 return 0;
00295 }
00296
00297 if ( errcode == WSAEINTR) {
00298 TSystem::ResetErrno();
00299 return -2;
00300 }
00301 if (errcode == EBADF) {
00302 return -3;
00303 }
00304 return -1;
00305 }
00306 return retcode;
00307 }
00308
00309
00310 static const char *DynamicPath(const char *newpath = 0, Bool_t reset = kFALSE)
00311 {
00312
00313
00314 static TString dynpath;
00315
00316 if (reset || newpath) {
00317 dynpath = "";
00318 }
00319 if (newpath) {
00320
00321 dynpath = newpath;
00322
00323 } else if (dynpath == "") {
00324 TString rdynpath = gEnv->GetValue("Root.DynamicPath", (char*)0);
00325 rdynpath.ReplaceAll("; ", ";");
00326 if (rdynpath == "") {
00327 #ifdef ROOTBINDIR
00328 rdynpath = ".;"; rdynpath += ROOTBINDIR;
00329 #else
00330 rdynpath = ".;"; rdynpath += gRootDir; rdynpath += "/bin";
00331 #endif
00332 }
00333 TString path = gSystem->Getenv("PATH");
00334 if (path == "")
00335 dynpath = rdynpath;
00336 else {
00337 dynpath = path; dynpath += ";"; dynpath += rdynpath;
00338 }
00339
00340 }
00341 #ifdef ROOTLIBDIR
00342 if (!dynpath.Contains(ROOTLIBDIR)) {
00343 dynpath += ";"; dynpath += ROOTLIBDIR;
00344 }
00345 #else
00346 if (!dynpath.Contains(TString::Format("%s/lib", gRootDir))) {
00347 dynpath += ";"; dynpath += gRootDir; dynpath += "/lib";
00348 }
00349 #endif
00350
00351 #ifdef CINTINCDIR
00352 TString cintinc(TString::Format("%s/cint/stl",CINTINCDIR));
00353 #else
00354 TString cintinc(TString::Format("%s/cint/cint/stl",gRootDir));
00355 #endif
00356 if (!dynpath.Contains( cintinc)) {
00357 dynpath += ";"; dynpath += cintinc;
00358 }
00359 return dynpath;
00360 }
00361
00362
00363 static void sighandler(int sig)
00364 {
00365
00366
00367 for (int i = 0; i < kMAXSIGNALS; i++) {
00368 if (signal_map[i].code == sig) {
00369 (*signal_map[i].handler)((ESignals)i);
00370 return;
00371 }
00372 }
00373 }
00374
00375
00376 static void WinNTSignal(ESignals sig, SigHandler_t handler)
00377 {
00378
00379 signal_map[sig].handler = handler;
00380 if (signal_map[sig].code != -1)
00381 (SigHandler_t)signal(signal_map[sig].code, sighandler);
00382 }
00383
00384
00385 static char *WinNTSigname(ESignals sig)
00386 {
00387
00388
00389 return signal_map[sig].signame;
00390 }
00391
00392
00393 static BOOL ConsoleSigHandler(DWORD sig)
00394 {
00395
00396
00397 switch (sig) {
00398 case CTRL_C_EVENT:
00399 if (!G__get_security_error()) {
00400 G__genericerror("\n *** Break *** keyboard interrupt");
00401 } else {
00402 Break("TInterruptHandler::Notify", "keyboard interrupt");
00403 if (TROOT::Initialized()) {
00404 gInterpreter->RewindDictionary();
00405 }
00406 }
00407 return kTRUE;
00408 case CTRL_BREAK_EVENT:
00409 case CTRL_LOGOFF_EVENT:
00410 case CTRL_SHUTDOWN_EVENT:
00411 case CTRL_CLOSE_EVENT:
00412 default:
00413 printf("\n *** Break *** keyboard interrupt - ROOT is terminated\n");
00414 gSystem->Exit(-1);
00415 return kTRUE;
00416 }
00417 }
00418
00419 static CONTEXT *fgXcptContext = 0;
00420
00421 static void SigHandler(ESignals sig)
00422 {
00423 if (gSystem) {
00424 gSystem->StackTrace();
00425 if (TROOT::Initialized()) {
00426 ::Throw(sig);
00427 }
00428 gSystem->Abort(-1);
00429 }
00430 }
00431
00432
00433 LONG WINAPI ExceptionFilter(LPEXCEPTION_POINTERS pXcp)
00434 {
00435
00436
00437
00438 fgXcptContext = pXcp->ContextRecord;
00439 gSystem->StackTrace();
00440 return EXCEPTION_CONTINUE_SEARCH;
00441 }
00442
00443
00444 #pragma intrinsic(_ReturnAddress)
00445 #pragma auto_inline(off)
00446 DWORD_PTR GetProgramCounter()
00447 {
00448
00449 return (DWORD_PTR)_ReturnAddress();
00450 }
00451 #pragma auto_inline(on)
00452
00453
00454 static DWORD WINAPI GUIThreadMessageProcessingLoop(void *p)
00455 {
00456
00457
00458
00459
00460
00461
00462
00463
00464 MSG msg;
00465
00466
00467 ::PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
00468
00469 Int_t erret = 0;
00470 Bool_t endLoop = kFALSE;
00471 while (!endLoop) {
00472 if (gGlobalEvent) ::SetEvent(gGlobalEvent);
00473 erret = ::GetMessage(&msg, NULL, NULL, NULL);
00474 if (erret <= 0) endLoop = kTRUE;
00475 if (gGUIThreadMsgFunc)
00476 endLoop = (*gGUIThreadMsgFunc)(&msg);
00477 }
00478
00479 gVirtualX->CloseDisplay();
00480
00481
00482 if (erret == -1) {
00483 erret = ::GetLastError();
00484 Error("MsgLoop", "Error in GetMessage");
00485 ::ExitThread(-1);
00486 } else {
00487 ::ExitThread(0);
00488 }
00489 return 0;
00490 }
00491
00492
00493
00494
00495
00496
00497
00498 typedef BOOL (__stdcall *SYMINITIALIZEPROC)( HANDLE, LPSTR, BOOL );
00499 typedef BOOL (__stdcall *SYMCLEANUPPROC)( HANDLE );
00500 typedef BOOL (__stdcall *STACKWALK64PROC)
00501 ( DWORD, HANDLE, HANDLE, LPSTACKFRAME64, LPVOID,
00502 PREAD_PROCESS_MEMORY_ROUTINE,PFUNCTION_TABLE_ACCESS_ROUTINE,
00503 PGET_MODULE_BASE_ROUTINE, PTRANSLATE_ADDRESS_ROUTINE );
00504 typedef LPVOID (__stdcall *SYMFUNCTIONTABLEACCESS64PROC)( HANDLE, DWORD64 );
00505 typedef DWORD (__stdcall *SYMGETMODULEBASE64PROC)( HANDLE, DWORD64 );
00506 typedef BOOL (__stdcall *SYMGETMODULEINFO64PROC)(HANDLE, DWORD64, PIMAGEHLP_MODULE64);
00507 typedef BOOL (__stdcall *SYMGETSYMFROMADDR64PROC)( HANDLE, DWORD64, PDWORD64, PIMAGEHLP_SYMBOL64);
00508 typedef BOOL (__stdcall *SYMGETLINEFROMADDR64PROC)(HANDLE, DWORD64, PDWORD, PIMAGEHLP_LINE64);
00509 typedef DWORD (__stdcall *UNDECORATESYMBOLNAMEPROC)(PCSTR, PSTR, DWORD, DWORD);
00510
00511
00512 static SYMINITIALIZEPROC _SymInitialize = 0;
00513 static SYMCLEANUPPROC _SymCleanup = 0;
00514 static STACKWALK64PROC _StackWalk64 = 0;
00515 static SYMFUNCTIONTABLEACCESS64PROC _SymFunctionTableAccess64 = 0;
00516 static SYMGETMODULEBASE64PROC _SymGetModuleBase64 = 0;
00517 static SYMGETMODULEINFO64PROC _SymGetModuleInfo64 = 0;
00518 static SYMGETSYMFROMADDR64PROC _SymGetSymFromAddr64 = 0;
00519 static SYMGETLINEFROMADDR64PROC _SymGetLineFromAddr64 = 0;
00520 static UNDECORATESYMBOLNAMEPROC _UnDecorateSymbolName = 0;
00521
00522 BOOL InitImagehlpFunctions()
00523 {
00524
00525
00526
00527
00528
00529
00530 HMODULE hModImagehlp = LoadLibrary( "IMAGEHLP.DLL" );
00531 if (!hModImagehlp)
00532 return FALSE;
00533
00534 _SymInitialize = (SYMINITIALIZEPROC) GetProcAddress( hModImagehlp, "SymInitialize" );
00535 if (!_SymInitialize)
00536 return FALSE;
00537
00538 _SymCleanup = (SYMCLEANUPPROC) GetProcAddress( hModImagehlp, "SymCleanup" );
00539 if (!_SymCleanup)
00540 return FALSE;
00541
00542 _StackWalk64 = (STACKWALK64PROC) GetProcAddress( hModImagehlp, "StackWalk64" );
00543 if (!_StackWalk64)
00544 return FALSE;
00545
00546 _SymFunctionTableAccess64 = (SYMFUNCTIONTABLEACCESS64PROC) GetProcAddress(hModImagehlp, "SymFunctionTableAccess64" );
00547 if (!_SymFunctionTableAccess64)
00548 return FALSE;
00549
00550 _SymGetModuleBase64=(SYMGETMODULEBASE64PROC)GetProcAddress(hModImagehlp, "SymGetModuleBase64");
00551 if (!_SymGetModuleBase64)
00552 return FALSE;
00553
00554 _SymGetModuleInfo64=(SYMGETMODULEINFO64PROC)GetProcAddress(hModImagehlp, "SymGetModuleInfo64");
00555 if (!_SymGetModuleInfo64)
00556 return FALSE;
00557
00558 _SymGetSymFromAddr64=(SYMGETSYMFROMADDR64PROC)GetProcAddress(hModImagehlp, "SymGetSymFromAddr64");
00559 if (!_SymGetSymFromAddr64)
00560 return FALSE;
00561
00562 _SymGetLineFromAddr64=(SYMGETLINEFROMADDR64PROC)GetProcAddress(hModImagehlp, "SymGetLineFromAddr64");
00563 if (!_SymGetLineFromAddr64)
00564 return FALSE;
00565
00566 _UnDecorateSymbolName=(UNDECORATESYMBOLNAMEPROC)GetProcAddress(hModImagehlp, "UnDecorateSymbolName");
00567 if (!_UnDecorateSymbolName)
00568 return FALSE;
00569
00570 if (!_SymInitialize(GetCurrentProcess(), 0, TRUE ))
00571 return FALSE;
00572
00573 return TRUE;
00574 }
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586 std::string GetModuleName(DWORD64 address)
00587 {
00588
00589
00590 std::ostringstream out;
00591 HANDLE process = ::GetCurrentProcess();
00592
00593 DWORD lineDisplacement = 0;
00594 IMAGEHLP_LINE64 line;
00595 ::ZeroMemory(&line, sizeof(line));
00596 line.SizeOfStruct = sizeof(line);
00597 if(_SymGetLineFromAddr64(process, address, &lineDisplacement, &line)) {
00598 out << line.FileName << "(" << line.LineNumber << "): ";
00599 } else {
00600 IMAGEHLP_MODULE64 module;
00601 ::ZeroMemory(&module, sizeof(module));
00602 module.SizeOfStruct = sizeof(module);
00603 if(_SymGetModuleInfo64(process, address, &module)) {
00604 out << module.ModuleName << "!";
00605 } else {
00606 out << "0x" << std::hex << address << std::dec << " ";
00607 }
00608 }
00609
00610 return out.str();
00611 }
00612
00613 std::string GetFunctionName(DWORD64 address)
00614 {
00615
00616
00617 DWORD64 symbolDisplacement = 0;
00618 HANDLE process = ::GetCurrentProcess();
00619
00620 const unsigned int SYMBOL_BUFFER_SIZE = 8192;
00621 char symbolBuffer[SYMBOL_BUFFER_SIZE];
00622 PIMAGEHLP_SYMBOL64 symbol = reinterpret_cast<PIMAGEHLP_SYMBOL64>(symbolBuffer);
00623 ::ZeroMemory(symbol, SYMBOL_BUFFER_SIZE);
00624 symbol->SizeOfStruct = SYMBOL_BUFFER_SIZE;
00625 symbol->MaxNameLength = SYMBOL_BUFFER_SIZE - sizeof(IMAGEHLP_SYMBOL64);
00626
00627 if(_SymGetSymFromAddr64(process, address, &symbolDisplacement, symbol)) {
00628
00629 const unsigned int NAME_SIZE = 8192;
00630 char name[NAME_SIZE];
00631 _UnDecorateSymbolName(
00632 symbol->Name,
00633 name,
00634 NAME_SIZE,
00635 UNDNAME_COMPLETE |
00636 UNDNAME_NO_THISTYPE |
00637 UNDNAME_NO_SPECIAL_SYMS |
00638 UNDNAME_NO_MEMBER_TYPE |
00639 UNDNAME_NO_MS_KEYWORDS |
00640 UNDNAME_NO_ACCESS_SPECIFIERS
00641 );
00642
00643 std::string result;
00644 result += name;
00645 result += "()";
00646 return result;
00647 } else {
00648 return "??";
00649 }
00650 }
00651
00652
00653
00654
00655 static BOOL IsShortcut(const char *filename)
00656 {
00657
00658
00659
00660
00661 const char *extLnk = ".lnk";
00662 if (filename != NULL) {
00663
00664 TString strfilename(filename);
00665 if (strfilename.EndsWith(extLnk))
00666 return TRUE;
00667 }
00668 return FALSE;
00669 }
00670
00671
00672 static BOOL ResolveShortCut(LPCSTR pszShortcutFile, char *pszPath, int maxbuf)
00673 {
00674
00675
00676 HRESULT hres;
00677 IShellLink* psl;
00678 char szGotPath[MAX_PATH];
00679 WIN32_FIND_DATA wfd;
00680
00681 *pszPath = 0;
00682
00683
00684
00685 typedef HRESULT (__stdcall *COINITIALIZEPROC)( LPVOID );
00686 static COINITIALIZEPROC _CoInitialize = 0;
00687 typedef void (__stdcall *COUNINITIALIZEPROC)( void );
00688 static COUNINITIALIZEPROC _CoUninitialize = 0;
00689 typedef HRESULT (__stdcall *COCREATEINSTANCEPROC)( REFCLSID, LPUNKNOWN,
00690 DWORD, REFIID, LPVOID );
00691 static COCREATEINSTANCEPROC _CoCreateInstance = 0;
00692
00693 HMODULE hModImagehlp = LoadLibrary( "ole32.dll" );
00694 if (!hModImagehlp)
00695 return FALSE;
00696
00697 _CoInitialize = (COINITIALIZEPROC) GetProcAddress( hModImagehlp, "CoInitialize" );
00698 if (!_CoInitialize)
00699 return FALSE;
00700 _CoUninitialize = (COUNINITIALIZEPROC) GetProcAddress( hModImagehlp, "CoUninitialize");
00701 if (!_CoUninitialize)
00702 return FALSE;
00703 _CoCreateInstance = (COCREATEINSTANCEPROC) GetProcAddress( hModImagehlp, "CoCreateInstance" );
00704 if (!_CoCreateInstance)
00705 return FALSE;
00706
00707 _CoInitialize(NULL);
00708
00709 hres = _CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
00710 IID_IShellLink, (void **) &psl);
00711 if (SUCCEEDED(hres)) {
00712 IPersistFile* ppf;
00713
00714 hres = psl->QueryInterface(IID_IPersistFile, (void **) &ppf);
00715 if (SUCCEEDED(hres)) {
00716 WCHAR wsz[MAX_PATH];
00717 MultiByteToWideChar(CP_ACP, 0, pszShortcutFile, -1, wsz, MAX_PATH);
00718
00719 hres = ppf->Load(wsz, STGM_READ);
00720 if (SUCCEEDED(hres)) {
00721 hres = psl->Resolve(HWND_DESKTOP, SLR_ANY_MATCH);
00722 if (SUCCEEDED(hres)) {
00723 strlcpy(szGotPath, pszShortcutFile,MAX_PATH);
00724 hres = psl->GetPath(szGotPath, MAX_PATH, (WIN32_FIND_DATA *)&wfd,
00725 SLGP_UNCPRIORITY | SLGP_RAWPATH);
00726 strlcpy(pszPath,szGotPath, maxbuf);
00727 if (maxbuf) pszPath[maxbuf-1] = 0;
00728 }
00729 }
00730 ppf->Release();
00731 }
00732 psl->Release();
00733 }
00734 _CoUninitialize();
00735
00736 return SUCCEEDED(hres);
00737 }
00738
00739 void UpdateRegistry(TWinNTSystem* sys, char* buf ) {
00740
00741 GetModuleFileName(0, buf, MAX_MODULE_NAME32 + 1);
00742 if (strcmp(sys->TWinNTSystem::BaseName(buf), "root.exe"))
00743 return;
00744 HKEY regCUS;
00745 if (!::RegOpenKeyEx(HKEY_CURRENT_USER, "Software", 0, KEY_READ, ®CUS) == ERROR_SUCCESS)
00746 return;
00747 HKEY regCUSC;
00748 if (!::RegOpenKeyEx(regCUS, "Classes", 0, KEY_READ, ®CUSC) == ERROR_SUCCESS) {
00749 ::RegCloseKey(regCUS);
00750 return;
00751 }
00752
00753 HKEY regROOT;
00754 bool regROOTwrite = false;
00755 TString iconloc(buf);
00756 iconloc += ",-101";
00757
00758 if (::RegOpenKeyEx(regCUSC, "ROOTDEV.ROOT", 0, KEY_READ, ®ROOT) != ERROR_SUCCESS) {
00759 ::RegCloseKey(regCUSC);
00760 if (::RegOpenKeyEx(regCUS, "Classes", 0, KEY_READ | KEY_WRITE, ®CUSC) == ERROR_SUCCESS &&
00761 ::RegCreateKeyEx(regCUSC, "ROOTDEV.ROOT", 0, NULL, 0, KEY_READ | KEY_WRITE,
00762 NULL, ®ROOT, NULL) == ERROR_SUCCESS) {
00763 regROOTwrite = true;
00764 }
00765 } else {
00766 HKEY regROOTIcon;
00767 if (::RegOpenKeyEx(regROOT, "DefaultIcon", 0, KEY_READ, ®ROOTIcon) == ERROR_SUCCESS) {
00768 char bufIconLoc[1024];
00769 DWORD dwType;
00770 DWORD dwSize = sizeof(bufIconLoc);
00771
00772 if (::RegQueryValueEx(regROOTIcon, NULL, NULL, &dwType, (BYTE*)bufIconLoc, &dwSize) == ERROR_SUCCESS)
00773 regROOTwrite = (iconloc != bufIconLoc);
00774 else
00775 regROOTwrite = true;
00776 ::RegCloseKey(regROOTIcon);
00777 } else
00778 regROOTwrite = true;
00779 if (regROOTwrite) {
00780
00781 ::RegCloseKey(regCUSC);
00782 ::RegCloseKey(regROOT);
00783 if (::RegOpenKeyEx(regCUS, "Classes", 0, KEY_READ | KEY_WRITE, ®CUSC) != ERROR_SUCCESS) {
00784
00785 regROOTwrite = false;
00786 } else {
00787 if (::RegOpenKeyEx(regCUSC, "ROOTDEV.ROOT", 0, KEY_WRITE, ®ROOT) != ERROR_SUCCESS) {
00788
00789 regROOTwrite = false;
00790 ::RegCloseKey(regCUSC);
00791 }
00792 }
00793 }
00794 }
00795
00796
00797 TString fileopen;
00798 #ifndef ROOT_PREFIX
00799 fileopen += sys->TWinNTSystem::DriveName(buf);
00800 fileopen += ":";
00801 fileopen += sys->TWinNTSystem::DirName(sys->TWinNTSystem::DirName(buf));
00802 fileopen += "\\macros";
00803 #else
00804 fileopen += ROOTMACRODIR;
00805 #endif
00806 fileopen += "\\fileopen.C";
00807
00808 if (regROOTwrite) {
00809
00810 regROOTwrite = (::_access(fileopen, kReadPermission) == 0);
00811 }
00812
00813 if (!regROOTwrite) {
00814 ::RegCloseKey(regROOT);
00815 ::RegCloseKey(regCUSC);
00816 ::RegCloseKey(regCUS);
00817 return;
00818 }
00819
00820 static const char apptitle[] = "ROOT data file";
00821 ::RegSetValueEx(regROOT, NULL, 0, REG_SZ, (BYTE*)apptitle, sizeof(apptitle));
00822 DWORD editflags = 0x00010000;
00823 ::RegSetValueEx(regROOT, "EditFlags", 0, REG_DWORD, (BYTE*)&editflags, sizeof(editflags));
00824
00825 HKEY regROOTIcon;
00826 if (::RegCreateKeyEx(regROOT, "DefaultIcon", 0, NULL, 0, KEY_READ | KEY_WRITE,
00827 NULL, ®ROOTIcon, NULL) == ERROR_SUCCESS) {
00828 TString iconloc(buf);
00829 iconloc += ",-101";
00830 ::RegSetValueEx(regROOTIcon, NULL, 0, REG_SZ, (BYTE*)iconloc.Data(), iconloc.Length() + 1);
00831 ::RegCloseKey(regROOTIcon);
00832 }
00833
00834
00835 HKEY regROOTshell;
00836 if (::RegCreateKeyEx(regROOT, "shell", 0, NULL, 0, KEY_READ | KEY_WRITE,
00837 NULL, ®ROOTshell, NULL) == ERROR_SUCCESS) {
00838 HKEY regShellOpen;
00839 if (::RegCreateKeyEx(regROOTshell, "open", 0, NULL, 0, KEY_READ | KEY_WRITE,
00840 NULL, ®ShellOpen, NULL) == ERROR_SUCCESS) {
00841 HKEY regShellOpenCmd;
00842 if (::RegCreateKeyEx(regShellOpen, "command", 0, NULL, 0, KEY_READ | KEY_WRITE,
00843 NULL, ®ShellOpenCmd, NULL) == ERROR_SUCCESS) {
00844 TString cmd(buf);
00845 cmd += " -l \"%1\" \"";
00846 cmd += fileopen;
00847 cmd += "\"";
00848 ::RegSetValueEx(regShellOpenCmd, NULL, 0, REG_SZ, (BYTE*)cmd.Data(), cmd.Length() + 1);
00849 ::RegCloseKey(regShellOpenCmd);
00850 }
00851 ::RegCloseKey(regShellOpen);
00852 }
00853 ::RegCloseKey(regROOTshell);
00854 }
00855 ::RegCloseKey(regROOT);
00856
00857 if (::RegCreateKeyEx(regCUSC, ".root", 0, NULL, 0, KEY_READ | KEY_WRITE,
00858 NULL, ®ROOT, NULL) == ERROR_SUCCESS) {
00859 static const char appname[] = "ROOTDEV.ROOT";
00860 ::RegSetValueEx(regROOT, NULL, 0, REG_SZ, (BYTE*)appname, sizeof(appname));
00861 }
00862 ::RegCloseKey(regCUSC);
00863 ::RegCloseKey(regCUS);
00864
00865
00866 ::SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);
00867 }
00868
00869
00870 bool NeedSplash()
00871 {
00872
00873
00874 static bool once = true;
00875 if (!once || gROOT->IsBatch() || !gApplication) return false;
00876 TString arg = gSystem->BaseName(gApplication->Argv(0));
00877 if ((arg != "root") && (arg != "rootn") &&
00878 (arg != "root.exe") && (arg != "rootn.exe")) return false;
00879 for(int i=1; i<gApplication->Argc(); i++) {
00880 arg = gApplication->Argv(i);
00881 arg.Strip(TString::kBoth);
00882 if ((arg == "-l") || (arg == "-b")) {
00883 return false;
00884 }
00885 }
00886 if (once) {
00887 once = false;
00888 return true;
00889 }
00890 return false;
00891 }
00892
00893
00894 static void SetConsoleWindowName()
00895 {
00896
00897 char pszNewWindowTitle[1024];
00898 char pszOldWindowTitle[1024];
00899 HANDLE hStdout;
00900 CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
00901
00902 if (!::GetConsoleTitle(pszOldWindowTitle, 1024))
00903 return;
00904
00905 wsprintf(pszNewWindowTitle,"%d/%d", ::GetTickCount(), ::GetCurrentProcessId());
00906
00907 if (!::SetConsoleTitle(pszNewWindowTitle))
00908 return;
00909
00910 ::Sleep(40);
00911
00912 gConsoleWindow = (ULong_t)::FindWindow(0, pszNewWindowTitle);
00913 if (gConsoleWindow) {
00914
00915 ::ShowWindow((HWND)gConsoleWindow, SW_RESTORE);
00916
00917 ::SetConsoleTitle("ROOT session");
00918 }
00919 hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
00920 ::SetConsoleMode(hStdout, ENABLE_PROCESSED_OUTPUT |
00921 ENABLE_WRAP_AT_EOL_OUTPUT);
00922 if (!::GetConsoleScreenBufferInfo(hStdout, &csbiInfo))
00923 return;
00924 Gl_setwidth(csbiInfo.dwMaximumWindowSize.X);
00925 }
00926
00927 }
00928
00929
00930
00931 ClassImp(TWinNTSystem)
00932
00933 ULong_t gConsoleWindow = 0;
00934
00935
00936 Bool_t TWinNTSystem::HandleConsoleEvent()
00937 {
00938
00939
00940 TSignalHandler *sh;
00941 TIter next(fSignalHandler);
00942 ESignals s;
00943
00944 while (sh = (TSignalHandler*)next()) {
00945 s = sh->GetSignal();
00946 if (s == kSigInterrupt) {
00947 sh->Notify();
00948 Throw(SIGINT);
00949 return kTRUE;
00950 }
00951 }
00952 return kFALSE;
00953 }
00954
00955
00956 TWinNTSystem::TWinNTSystem() : TSystem("WinNT", "WinNT System"),
00957 fGUIThreadHandle(0), fGUIThreadId(0)
00958 {
00959
00960
00961 fhProcess = ::GetCurrentProcess();
00962 fDirNameBuffer = 0;
00963
00964 WSADATA WSAData;
00965 int initwinsock = 0;
00966
00967 if (initwinsock = ::WSAStartup(MAKEWORD(2, 0), &WSAData)) {
00968 Error("TWinNTSystem()","Starting sockets failed");
00969 }
00970
00971
00972 fBeepDuration = 1;
00973 fBeepFreq = 0;
00974 if (gEnv) {
00975 fBeepDuration = gEnv->GetValue("Root.System.BeepDuration", 1);
00976 fBeepFreq = gEnv->GetValue("Root.System.BeepFreq", 0);
00977 }
00978
00979 char *buf = new char[MAX_MODULE_NAME32 + 1];
00980
00981 #ifndef ROOTPREFIX
00982
00983 HMODULE hModCore = ::GetModuleHandle("libCore.dll");
00984 if (hModCore) {
00985 ::GetModuleFileName(hModCore, buf, MAX_MODULE_NAME32 + 1);
00986 char* pLibName = strstr(buf, "libCore.dll");
00987 if (pLibName) {
00988 --pLibName;
00989 while (--pLibName >= buf && *pLibName != '\\' && *pLibName != '/');
00990 *pLibName = 0;
00991 if (buf[0])
00992 Setenv("ROOTSYS", buf);
00993 }
00994 }
00995 #endif
00996
00997 UpdateRegistry(this, buf);
00998
00999 delete [] buf;
01000 }
01001
01002
01003 TWinNTSystem::~TWinNTSystem()
01004 {
01005
01006
01007
01008 typedef UINT (WINAPI* LPTIMEENDPERIOD)( UINT uPeriod );
01009 HINSTANCE hInstWinMM = LoadLibrary( "winmm.dll" );
01010 if( hInstWinMM ) {
01011 LPTIMEENDPERIOD pTimeEndPeriod = (LPTIMEENDPERIOD)GetProcAddress( hInstWinMM, "timeEndPeriod" );
01012 if( NULL != pTimeEndPeriod )
01013 pTimeEndPeriod(1);
01014 FreeLibrary(hInstWinMM);
01015 }
01016
01017 ::WSACleanup();
01018
01019 if (fDirNameBuffer) {
01020 delete [] fDirNameBuffer;
01021 fDirNameBuffer = 0;
01022 }
01023
01024 if (gGlobalEvent) {
01025 ::ResetEvent(gGlobalEvent);
01026 ::CloseHandle(gGlobalEvent);
01027 gGlobalEvent = 0;
01028 }
01029 if (gTimerThreadHandle) {
01030 ::TerminateThread(gTimerThreadHandle, 0);
01031 ::CloseHandle(gTimerThreadHandle);
01032 }
01033 }
01034
01035
01036 Bool_t TWinNTSystem::Init()
01037 {
01038
01039
01040 const char *dir = 0;
01041
01042 if (TSystem::Init()) {
01043 return kTRUE;
01044 }
01045
01046 fReadmask = new TFdSet;
01047 fWritemask = new TFdSet;
01048 fReadready = new TFdSet;
01049 fWriteready = new TFdSet;
01050 fSignals = new TFdSet;
01051 fNfd = 0;
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068 ::SetUnhandledExceptionFilter(ExceptionFilter);
01069
01070 fSigcnt = 0;
01071
01072 #ifndef ROOTPREFIX
01073 gRootDir = Getenv("ROOTSYS");
01074 if (gRootDir == 0) {
01075 static char lpFilename[MAX_PATH];
01076 if (::GetModuleFileName(NULL,
01077 lpFilename,
01078 sizeof(lpFilename)))
01079 {
01080 const char *dirName = DirName(DirName(lpFilename));
01081 gRootDir = StrDup(dirName);
01082 } else {
01083 gRootDir = 0;
01084 }
01085 }
01086 #else
01087 gRootDir= ROOTPREFIX;
01088 #endif
01089
01090
01091 typedef UINT (WINAPI* LPTIMEBEGINPERIOD)( UINT uPeriod );
01092 HINSTANCE hInstWinMM = LoadLibrary( "winmm.dll" );
01093 if( hInstWinMM ) {
01094 LPTIMEBEGINPERIOD pTimeBeginPeriod = (LPTIMEBEGINPERIOD)GetProcAddress( hInstWinMM, "timeBeginPeriod" );
01095 if( NULL != pTimeBeginPeriod )
01096 pTimeBeginPeriod(1);
01097 FreeLibrary(hInstWinMM);
01098 }
01099 gTimerThreadHandle = ::CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)ThreadStub,
01100 this, NULL, NULL);
01101
01102 gGlobalEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
01103 fGUIThreadHandle = ::CreateThread( NULL, 0, &GUIThreadMessageProcessingLoop, 0, 0, &fGUIThreadId );
01104
01105 SetConsoleWindowName();
01106 fGroupsInitDone = kFALSE;
01107 fFirstFile = kTRUE;
01108
01109 return kFALSE;
01110 }
01111
01112
01113
01114
01115 const char *TWinNTSystem::BaseName(const char *name)
01116 {
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127 if (name) {
01128 int idx = 0;
01129 const char *symbol=name;
01130
01131
01132 while ( (*symbol == ' ' || *symbol == '\t') && *symbol) symbol++;
01133
01134 if (*symbol) {
01135 if (isalpha(symbol[idx]) && symbol[idx+1] == ':') idx = 2;
01136 if ( (symbol[idx] == '/' || symbol[idx] == '\\') && symbol[idx+1] == '\0') {
01137
01138 return symbol;
01139 }
01140 } else {
01141 Error("BaseName", "name = 0");
01142 return 0;
01143 }
01144 char *cp;
01145 char *bslash = (char *)strrchr(&symbol[idx],'\\');
01146 char *rslash = (char *)strrchr(&symbol[idx],'/');
01147 if (cp = max(rslash, bslash)) {
01148
01149 return ++cp;
01150 }
01151
01152 return &symbol[idx];
01153 }
01154 Error("BaseName", "name = 0");
01155 return 0;
01156 }
01157
01158
01159 void TWinNTSystem::SetProgname(const char *name)
01160 {
01161
01162
01163
01164 ULong_t idot = 0;
01165 char *dot = 0;
01166 char *progname;
01167 char *fullname = 0;
01168
01169
01170 ULong_t namelen=name ? strlen(name) : 0;
01171 if (name && namelen > 0) {
01172
01173 fullname = new char[namelen+5];
01174 strlcpy(fullname, name,namelen+5);
01175 if ( !strrchr(fullname, '.') )
01176 strlcat(fullname, ".exe",namelen+5);
01177
01178 progname = StrDup(BaseName(fullname));
01179 dot = strrchr(progname, '.');
01180 idot = dot ? (ULong_t)(dot - progname) : strlen(progname);
01181
01182 char *which = 0;
01183
01184 if (IsAbsoluteFileName(fullname) && !AccessPathName(fullname)) {
01185 which = StrDup(fullname);
01186 } else {
01187 which = Which(Form("%s;%s", WorkingDirectory(), Getenv("PATH")), progname);
01188 }
01189
01190 if (which) {
01191 const char *dirname;
01192 char driveletter = DriveName(which);
01193 const char *d = DirName(which);
01194
01195 if (driveletter) {
01196 dirname = Form("%c:%s", driveletter, d);
01197 } else {
01198 dirname = Form("%s", d);
01199 }
01200
01201 gProgPath = StrDup(dirname);
01202 } else {
01203
01204
01205
01206
01207 gProgPath = WorkingDirectory();
01208 }
01209
01210
01211 progname[idot] = '\0';
01212 gProgName = StrDup(progname);
01213 if (which) delete [] which;
01214 delete[] fullname;
01215 delete[] progname;
01216 }
01217 if (::NeedSplash()) {
01218 new TWin32SplashThread(FALSE);
01219 }
01220 }
01221
01222
01223 const char *TWinNTSystem::GetError()
01224 {
01225
01226
01227 Int_t err = GetErrno();
01228 if (err == 0 && fLastErrorString != "")
01229 return fLastErrorString;
01230 if (err < 0 || err >= sys_nerr) {
01231 return Form("errno out of range %d", err);
01232 }
01233 return sys_errlist[err];
01234 }
01235
01236
01237 const char *TWinNTSystem::HostName()
01238 {
01239
01240
01241 if (fHostname == "")
01242 fHostname = ::getenv("COMPUTERNAME");
01243 if (fHostname == "") {
01244
01245 char hn[64];
01246 DWORD il = sizeof(hn);
01247 ::GetComputerName(hn, &il);
01248 fHostname = hn;
01249 }
01250 return fHostname;
01251 }
01252
01253
01254 void TWinNTSystem::DoBeep(Int_t freq , Int_t duration ) const
01255 {
01256
01257
01258
01259 if (freq == 0) {
01260 ::MessageBeep(-1);
01261 return;
01262 }
01263 if (freq < 37) freq = 440;
01264 if (duration < 0) duration = 100;
01265 ::Beep(freq, duration);
01266 }
01267
01268
01269 void TWinNTSystem::SetGUIThreadMsgHandler(ThreadMsgFunc_t func)
01270 {
01271
01272
01273 gGUIThreadMsgFunc = func;
01274 }
01275
01276
01277 void TWinNTSystem::NotifyApplicationCreated()
01278 {
01279
01280
01281
01282 ::PostThreadMessage(fGUIThreadId, 0, NULL, 0L);
01283 }
01284
01285
01286
01287
01288
01289 void TWinNTSystem::AddFileHandler(TFileHandler *h)
01290 {
01291
01292
01293
01294 TSystem::AddFileHandler(h);
01295 if (h) {
01296 int fd = h->GetFd();
01297 if (!fd) return;
01298
01299 if (h->HasReadInterest()) {
01300 fReadmask->Set(fd);
01301 }
01302 if (h->HasWriteInterest()) {
01303 fWritemask->Set(fd);
01304 }
01305 }
01306 }
01307
01308
01309 TFileHandler *TWinNTSystem::RemoveFileHandler(TFileHandler *h)
01310 {
01311
01312
01313
01314 if (!h) return 0;
01315
01316 TFileHandler *oh = TSystem::RemoveFileHandler(h);
01317 if (oh) {
01318 fReadmask->Clr(h->GetFd());
01319 fWritemask->Clr(h->GetFd());
01320 }
01321 return oh;
01322 }
01323
01324
01325 void TWinNTSystem::AddSignalHandler(TSignalHandler *h)
01326 {
01327
01328
01329
01330 TSystem::AddSignalHandler(h);
01331 ESignals sig = h->GetSignal();
01332
01333
01334 if (sig == kSigInterrupt) {
01335 ::SetConsoleCtrlHandler((PHANDLER_ROUTINE)ConsoleSigHandler, TRUE);
01336 } else
01337 WinNTSignal(h->GetSignal(), SigHandler);
01338 }
01339
01340
01341 TSignalHandler *TWinNTSystem::RemoveSignalHandler(TSignalHandler *h)
01342 {
01343
01344
01345
01346 if (!h) return 0;
01347
01348 int sig = h->GetSignal();
01349
01350 if (sig = kSigInterrupt) {
01351
01352 ::SetConsoleCtrlHandler((PHANDLER_ROUTINE)ConsoleSigHandler, FALSE);
01353 }
01354 return TSystem::RemoveSignalHandler(h);
01355 }
01356
01357
01358 void TWinNTSystem::ResetSignal(ESignals sig, Bool_t reset)
01359 {
01360
01361
01362
01363
01364 }
01365
01366
01367 void TWinNTSystem::IgnoreSignal(ESignals sig, Bool_t ignore)
01368 {
01369
01370
01371
01372
01373 }
01374
01375
01376 void TWinNTSystem::StackTrace()
01377 {
01378
01379
01380
01381
01382
01383
01384
01385 if (!gEnv->GetValue("Root.Stacktrace", 1))
01386 return;
01387
01388 HANDLE snapshot = ::CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD,::GetCurrentProcessId());
01389
01390 std::cerr.flush();
01391 fflush (stderr);
01392
01393 if (!InitImagehlpFunctions()) {
01394 std::cerr << "No stack trace: cannot find (functions in) dbghelp.dll!" << std::endl;
01395 return;
01396 }
01397
01398
01399 SYSTEM_INFO sysInfo;
01400 ::GetSystemInfo(&sysInfo);
01401 DWORD machineType = IMAGE_FILE_MACHINE_I386;
01402 switch (sysInfo.wProcessorArchitecture) {
01403 case PROCESSOR_ARCHITECTURE_AMD64:
01404 machineType = IMAGE_FILE_MACHINE_AMD64;
01405 break;
01406 case PROCESSOR_ARCHITECTURE_IA64:
01407 machineType = IMAGE_FILE_MACHINE_IA64;
01408 break;
01409 }
01410
01411 DWORD currentThreadID = ::GetCurrentThreadId();
01412 DWORD currentProcessID = ::GetCurrentProcessId();
01413
01414 if (snapshot == INVALID_HANDLE_VALUE) return;
01415
01416 THREADENTRY32 threadentry;
01417 threadentry.dwSize = sizeof(THREADENTRY32);
01418 if (!::Thread32First(snapshot, &threadentry)) return;
01419
01420 std::cerr << std::endl << "==========================================" << std::endl;
01421 std::cerr << "=============== STACKTRACE ===============" << std::endl;
01422 std::cerr << "==========================================" << std::endl << std::endl;
01423 UInt_t iThread = 0;
01424 do {
01425 if (threadentry.th32OwnerProcessID != currentProcessID)
01426 continue;
01427 HANDLE thread = ::OpenThread(THREAD_GET_CONTEXT|THREAD_SUSPEND_RESUME|THREAD_QUERY_INFORMATION,
01428 FALSE, threadentry.th32ThreadID);
01429 CONTEXT context;
01430 memset(&context, 0, sizeof(CONTEXT));
01431
01432 if (threadentry.th32ThreadID != currentThreadID) {
01433 ::SuspendThread(thread);
01434 context.ContextFlags = CONTEXT_ALL;
01435 ::GetThreadContext(thread, &context);
01436 ::ResumeThread(thread);
01437 } else {
01438 if (fgXcptContext) {
01439 context = *fgXcptContext;
01440 } else {
01441 typedef void (WINAPI *RTLCCTXT)(PCONTEXT);
01442 RTLCCTXT p2RtlCCtxt = (RTLCCTXT) ::GetProcAddress(
01443 GetModuleHandle("kernel32.dll"), "RtlCaptureContext");
01444 if (p2RtlCCtxt) {
01445 context.ContextFlags = CONTEXT_ALL;
01446 p2RtlCCtxt(&context);
01447 }
01448 }
01449 }
01450
01451 STACKFRAME64 frame;
01452 ::ZeroMemory(&frame, sizeof(frame));
01453
01454 frame.AddrPC.Mode = AddrModeFlat;
01455 frame.AddrFrame.Mode = AddrModeFlat;
01456 frame.AddrStack.Mode = AddrModeFlat;
01457 #if defined(_M_IX86)
01458 frame.AddrPC.Offset = context.Eip;
01459 frame.AddrFrame.Offset = context.Ebp;
01460 frame.AddrStack.Offset = context.Esp;
01461 #elif defined(_M_X64)
01462 frame.AddrPC.Offset = context.Rip;
01463 frame.AddrFrame.Offset = context.Rsp;
01464 frame.AddrStack.Offset = context.Rsp;
01465 #elif defined(_M_IA64)
01466 frame.AddrPC.Offset = context.StIIP;
01467 frame.AddrFrame.Offset = context.IntSp;
01468 frame.AddrStack.Offset = context.IntSp;
01469 frame.AddrBStore.Offset= context.RsBSP;
01470 #else
01471 std::cerr << "Stack traces not supported on your architecture yet." << std::endl;
01472 return;
01473 #endif
01474
01475 Bool_t bFirst = kTRUE;
01476 while (_StackWalk64(machineType, (HANDLE)::GetCurrentProcess(), thread, (LPSTACKFRAME64)&frame,
01477 (LPVOID)&context, (PREAD_PROCESS_MEMORY_ROUTINE)NULL, (PFUNCTION_TABLE_ACCESS_ROUTINE)_SymFunctionTableAccess64,
01478 (PGET_MODULE_BASE_ROUTINE)_SymGetModuleBase64, NULL)) {
01479 if (bFirst)
01480 std::cerr << std::endl << "================ Thread " << iThread++ << " ================" << std::endl;
01481 if (!bFirst || threadentry.th32ThreadID != currentThreadID) {
01482 const std::string moduleName = GetModuleName(frame.AddrPC.Offset);
01483 const std::string functionName = GetFunctionName(frame.AddrPC.Offset);
01484 std::cerr << " " << moduleName << functionName << std::endl;
01485 }
01486 bFirst = kFALSE;
01487 }
01488 ::CloseHandle(thread);
01489 } while (::Thread32Next(snapshot, &threadentry));
01490
01491 std::cerr << std::endl << "==========================================" << std::endl;
01492 std::cerr << "============= END STACKTRACE =============" << std::endl;
01493 std::cerr << "==========================================" << std::endl << std::endl;
01494 ::CloseHandle(snapshot);
01495 _SymCleanup(GetCurrentProcess());
01496 }
01497
01498
01499 Int_t TWinNTSystem::GetFPEMask()
01500 {
01501
01502
01503 Int_t mask = 0;
01504 UInt_t oldmask = _statusfp( );
01505
01506 if (oldmask & _EM_INVALID ) mask |= kInvalid;
01507 if (oldmask & _EM_ZERODIVIDE) mask |= kDivByZero;
01508 if (oldmask & _EM_OVERFLOW ) mask |= kOverflow;
01509 if (oldmask & _EM_UNDERFLOW) mask |= kUnderflow;
01510 if (oldmask & _EM_INEXACT ) mask |= kInexact;
01511
01512 return mask;
01513 }
01514
01515
01516 Int_t TWinNTSystem::SetFPEMask(Int_t mask)
01517 {
01518
01519
01520
01521 Int_t old = GetFPEMask();
01522
01523 UInt_t newm = 0;
01524 if (mask & kInvalid ) newm |= _EM_INVALID;
01525 if (mask & kDivByZero) newm |= _EM_ZERODIVIDE;
01526 if (mask & kOverflow ) newm |= _EM_OVERFLOW;
01527 if (mask & kUnderflow) newm |= _EM_UNDERFLOW;
01528 if (mask & kInexact ) newm |= _EM_INEXACT;
01529
01530 UInt_t cm = ::_statusfp();
01531 cm &= ~newm;
01532 ::_controlfp(cm , _MCW_EM);
01533
01534 return old;
01535 }
01536
01537
01538 Bool_t TWinNTSystem::ProcessEvents()
01539 {
01540
01541
01542 return TSystem::ProcessEvents();
01543 }
01544
01545
01546 void TWinNTSystem::DispatchOneEvent(Bool_t pendingOnly)
01547 {
01548
01549
01550
01551 if (pendingOnly && gGlobalEvent) ::SetEvent(gGlobalEvent);
01552
01553 Bool_t pollOnce = pendingOnly;
01554
01555 while (1) {
01556 if (_kbhit()) {
01557 if (gROOT->GetApplication()) {
01558 gApplication->HandleTermInput();
01559 if (gSplash) {
01560 delete gSplash;
01561 gSplash = 0;
01562 }
01563 if (!pendingOnly) {
01564 return;
01565 }
01566 }
01567 }
01568 if (gROOT->IsLineProcessing() && (!gVirtualX || !gVirtualX->IsCmdThread())) {
01569 if (!pendingOnly) {
01570
01571
01572 if (gGlobalEvent) {
01573 ::WaitForSingleObject(gGlobalEvent, 1);
01574 ::ResetEvent(gGlobalEvent);
01575 }
01576 return;
01577 }
01578 }
01579
01580 if (gXDisplay && !gROOT->IsBatch()) {
01581 if (gXDisplay->Notify()) {
01582 if (!pendingOnly) {
01583 return;
01584 }
01585 }
01586 }
01587
01588
01589 if ((fNfd > 0) && fFileHandler && (fFileHandler->GetSize() > 0)) {
01590 if (CheckDescriptors()) {
01591 if (!pendingOnly) {
01592 return;
01593 }
01594 }
01595 }
01596 fNfd = 0;
01597 fReadready->Zero();
01598 fWriteready->Zero();
01599
01600 if (pendingOnly && !pollOnce)
01601 return;
01602
01603
01604 if (fSigcnt > 0 && fSignalHandler->GetSize() > 0) {
01605 if (CheckSignals(kTRUE)) {
01606 if (!pendingOnly) {
01607 return;
01608 }
01609 }
01610 }
01611 fSigcnt = 0;
01612 fSignals->Zero();
01613
01614
01615 Long_t nextto;
01616 if (fTimers && fTimers->GetSize() > 0) {
01617 if (DispatchTimers(kTRUE)) {
01618
01619 nextto = NextTimeOut(kTRUE);
01620 if (nextto > kItimerResolution || nextto == -1) {
01621 return;
01622 }
01623 }
01624 }
01625
01626
01627 nextto = NextTimeOut(kTRUE);
01628 if (pendingOnly) {
01629 if (fFileHandler && fFileHandler->GetSize() == 0)
01630 return;
01631 nextto = 0;
01632 pollOnce = kFALSE;
01633 }
01634
01635 if (fReadmask && !fReadmask->GetBits() &&
01636 fWritemask && !fWritemask->GetBits()) {
01637
01638
01639 if (!pendingOnly && gGlobalEvent) {
01640 ::WaitForSingleObject(gGlobalEvent, 1);
01641 ::ResetEvent(gGlobalEvent);
01642 }
01643 return;
01644 }
01645
01646 *fReadready = *fReadmask;
01647 *fWriteready = *fWritemask;
01648
01649 fNfd = WinNTSelect(fReadready, fWriteready, nextto);
01650
01651
01652 if ((fNfd < 0) && (fNfd != -2)) {
01653 int rc, i;
01654
01655 for (i = 0; i < fReadmask->GetCount(); i++) {
01656 TFdSet t;
01657 Int_t fd = fReadmask->GetFd(i);
01658 t.Set(fd);
01659 if (fReadmask->IsSet(fd)) {
01660 rc = WinNTSelect(&t, 0, 0);
01661 if (rc < 0 && rc != -2) {
01662 ::SysError("DispatchOneEvent", "select: read error on %d\n", fd);
01663 fReadmask->Clr(fd);
01664 }
01665 }
01666 }
01667
01668 for (i = 0; i < fWritemask->GetCount(); i++) {
01669 TFdSet t;
01670 Int_t fd = fWritemask->GetFd(i);
01671 t.Set(fd);
01672
01673 if (fWritemask->IsSet(fd)) {
01674 rc = WinNTSelect(0, &t, 0);
01675 if (rc < 0 && rc != -2) {
01676 ::SysError("DispatchOneEvent", "select: write error on %d\n", fd);
01677 fWritemask->Clr(fd);
01678 }
01679 }
01680 t.Clr(fd);
01681 }
01682 }
01683 }
01684 }
01685
01686
01687 void TWinNTSystem::ExitLoop()
01688 {
01689
01690
01691 TSystem::ExitLoop();
01692 }
01693
01694
01695
01696 Bool_t TWinNTSystem::CheckSignals(Bool_t sync)
01697 {
01698
01699
01700 TSignalHandler *sh;
01701 Int_t sigdone = -1;
01702 {
01703 TIter next(fSignalHandler);
01704
01705 while (sh = (TSignalHandler*)next()) {
01706 if (sync == sh->IsSync()) {
01707 ESignals sig = sh->GetSignal();
01708 if ((fSignals->IsSet(sig) && sigdone == -1) || sigdone == sig) {
01709 if (sigdone == -1) {
01710 fSignals->Clr(sig);
01711 sigdone = sig;
01712 fSigcnt--;
01713 }
01714 sh->Notify();
01715 }
01716 }
01717 }
01718 }
01719 if (sigdone != -1) return kTRUE;
01720
01721 return kFALSE;
01722 }
01723
01724
01725 Bool_t TWinNTSystem::CheckDescriptors()
01726 {
01727
01728
01729
01730 TFileHandler *fh;
01731 Int_t fddone = -1;
01732 Bool_t read = kFALSE;
01733
01734 TOrdCollectionIter it((TOrdCollection*)fFileHandler);
01735
01736 while ((fh = (TFileHandler*) it.Next())) {
01737 Int_t fd = fh->GetFd();
01738 if (!fd) continue;
01739
01740 if ((fReadready->IsSet(fd) && fddone == -1) ||
01741 (fddone == fd && read)) {
01742 if (fddone == -1) {
01743 fReadready->Clr(fd);
01744 fddone = fd;
01745 read = kTRUE;
01746 fNfd--;
01747 }
01748 fh->ReadNotify();
01749 }
01750 if ((fWriteready->IsSet(fd) && fddone == -1) ||
01751 (fddone == fd && !read)) {
01752 if (fddone == -1) {
01753 fWriteready->Clr(fd);
01754 fddone = fd;
01755 read = kFALSE;
01756 fNfd--;
01757 }
01758 fh->WriteNotify();
01759 }
01760 }
01761 if (fddone != -1) return kTRUE;
01762
01763 return kFALSE;
01764 }
01765
01766
01767
01768
01769 int TWinNTSystem::mkdir(const char *name, Bool_t recursive)
01770 {
01771
01772
01773
01774
01775
01776 if (recursive) {
01777 TString dirname = DirName(name);
01778 if (dirname.Length() == 0) {
01779
01780
01781 return 0;
01782 }
01783 if (IsAbsoluteFileName(name)) {
01784
01785
01786
01787 const char driveletter = DriveName(name);
01788 if (driveletter) {
01789 dirname.Prepend(":");
01790 dirname.Prepend(driveletter);
01791 }
01792 }
01793 if (AccessPathName(dirname, kFileExists)) {
01794 int res = this->mkdir(dirname, kTRUE);
01795 if (res) return res;
01796 }
01797 if (!AccessPathName(name, kFileExists)) {
01798 return -1;
01799 }
01800 }
01801 return MakeDirectory(name);
01802 }
01803
01804
01805 int TWinNTSystem::MakeDirectory(const char *name)
01806 {
01807
01808
01809
01810
01811 TSystem *helper = FindHelper(name);
01812 if (helper) {
01813 return helper->MakeDirectory(name);
01814 }
01815 const char *proto = (strstr(name, "file:///")) ? "file://" : "file:";
01816 #ifdef WATCOM
01817
01818 if (!name) return 0;
01819 return ::mkdir(StripOffProto(name, proto));
01820 #else
01821
01822 if (!name) return 0;
01823 return ::_mkdir(StripOffProto(name, proto));
01824 #endif
01825 }
01826
01827
01828 void TWinNTSystem::FreeDirectory(void *dirp)
01829 {
01830
01831
01832 TSystem *helper = FindHelper(0, dirp);
01833 if (helper) {
01834 helper->FreeDirectory(dirp);
01835 return;
01836 }
01837
01838 if (dirp) {
01839 ::FindClose(dirp);
01840 }
01841 }
01842
01843
01844 const char *TWinNTSystem::GetDirEntry(void *dirp)
01845 {
01846
01847
01848 TSystem *helper = FindHelper(0, dirp);
01849 if (helper) {
01850 return helper->GetDirEntry(dirp);
01851 }
01852
01853 if (dirp) {
01854 HANDLE searchFile = (HANDLE)dirp;
01855 if (fFirstFile) {
01856
01857
01858
01859 fFirstFile = kFALSE;
01860 return (const char *)fFindFileData.cFileName;
01861 }
01862 if (::FindNextFile(searchFile, &fFindFileData)) {
01863 return (const char *)fFindFileData.cFileName;
01864 }
01865 }
01866 return 0;
01867 }
01868
01869
01870 Bool_t TWinNTSystem::ChangeDirectory(const char *path)
01871 {
01872
01873
01874 Bool_t ret = (Bool_t) (::chdir(path) == 0);
01875 if (fWdpath != "") {
01876 fWdpath = "";
01877 }
01878 return ret;
01879 }
01880
01881
01882 __inline BOOL DBL_BSLASH(LPCTSTR psz)
01883 {
01884
01885
01886
01887
01888 return (psz[0] == TEXT('\\') && psz[1] == TEXT('\\'));
01889 }
01890
01891
01892 BOOL PathIsUNC(LPCTSTR pszPath)
01893 {
01894
01895
01896
01897
01898
01899
01900
01901
01902
01903
01904 return DBL_BSLASH(pszPath);
01905 }
01906
01907 #pragma data_seg(".text", "CODE")
01908 const TCHAR c_szColonSlash[] = TEXT(":\\");
01909 #pragma data_seg()
01910
01911
01912 BOOL PathIsRoot(LPCTSTR pPath)
01913 {
01914
01915
01916
01917
01918
01919
01920
01921 if (!IsDBCSLeadByte(*pPath)) {
01922 if (!lstrcmpi(pPath + 1, c_szColonSlash))
01923
01924 return TRUE;
01925 }
01926 if ((*pPath == TEXT('\\')) && (*(pPath + 1) == 0))
01927
01928 return TRUE;
01929 if (DBL_BSLASH(pPath)) {
01930
01931 LPCTSTR p;
01932 int cBackslashes = 0;
01933 for (p = pPath + 2; *p; p = CharNext(p)) {
01934 if (*p == TEXT('\\') && (++cBackslashes > 1))
01935 return FALSE;
01936 }
01937
01938
01939 return TRUE;
01940 }
01941 return FALSE;
01942 }
01943
01944
01945 void *TWinNTSystem::OpenDirectory(const char *fdir)
01946 {
01947
01948
01949 TSystem *helper = FindHelper(fdir);
01950 if (helper) {
01951 return helper->OpenDirectory(fdir);
01952 }
01953
01954 const char *proto = (strstr(fdir, "file:///")) ? "file://" : "file:";
01955 const char *sdir = StripOffProto(fdir, proto);
01956
01957 char *dir = new char[MAX_PATH];
01958 if (IsShortcut(sdir)) {
01959 if (!ResolveShortCut(sdir, dir, MAX_PATH))
01960 strlcpy(dir, sdir,MAX_PATH);
01961 }
01962 else
01963 strlcpy(dir, sdir,MAX_PATH);
01964
01965 int nche = strlen(dir)+3;
01966 char *entry = new char[nche];
01967 struct _stati64 finfo;
01968
01969 if(PathIsUNC(dir)) {
01970 strlcpy(entry, dir,nche);
01971 if ((entry[strlen(dir)-1] == '/') || (entry[strlen(dir)-1] == '\\' )) {
01972 entry[strlen(dir)-1] = '\0';
01973 }
01974 if(PathIsRoot(entry)) {
01975 strlcat(entry,"\\",nche);
01976 }
01977 if (_stati64(entry, &finfo) < 0) {
01978 delete [] entry;
01979 delete [] dir;
01980 return 0;
01981 }
01982 }
01983 else {
01984 strlcpy(entry, dir,nche);
01985 if ((entry[strlen(dir)-1] == '/') || (entry[strlen(dir)-1] == '\\' )) {
01986 if(!PathIsRoot(entry))
01987 entry[strlen(dir)-1] = '\0';
01988 }
01989 if (_stati64(entry, &finfo) < 0) {
01990 delete [] entry;
01991 delete [] dir;
01992 return 0;
01993 }
01994 }
01995
01996 if (finfo.st_mode & S_IFDIR) {
01997 strlcpy(entry, dir,nche);
01998 if (!(entry[strlen(dir)-1] == '/' || entry[strlen(dir)-1] == '\\' )) {
01999 strlcat(entry,"\\",nche);
02000 }
02001 strlcat(entry,"*",nche);
02002
02003 HANDLE searchFile;
02004 searchFile = ::FindFirstFile(entry, &fFindFileData);
02005 if (searchFile == INVALID_HANDLE_VALUE) {
02006 ((TWinNTSystem *)gSystem)->Error( "Unable to find' for reading:", entry);
02007 delete [] entry;
02008 delete [] dir;
02009 return 0;
02010 }
02011 delete [] entry;
02012 delete [] dir;
02013 fFirstFile = kTRUE;
02014 return searchFile;
02015 } else {
02016 delete [] entry;
02017 delete [] dir;
02018 return 0;
02019 }
02020 }
02021
02022
02023 const char *TWinNTSystem::WorkingDirectory()
02024 {
02025
02026
02027 return WorkingDirectory('\0');
02028 }
02029
02030
02031 const char *TWinNTSystem::WorkingDirectory(char driveletter)
02032 {
02033
02034
02035
02036 char *wdpath = 0;
02037 char drive = driveletter ? toupper( driveletter ) - 'A' + 1 : 0;
02038
02039 if (fWdpath != "" ) {
02040 return fWdpath;
02041 }
02042
02043 if (!(wdpath = ::_getdcwd( (int)drive, wdpath, kMAXPATHLEN))) {
02044 free(wdpath);
02045 Warning("WorkingDirectory", "getcwd() failed");
02046 return 0;
02047 }
02048 fWdpath = wdpath;
02049
02050 if (fWdpath[1] == ':')
02051 fWdpath[0] = toupper(fWdpath[0]);
02052 free(wdpath);
02053 return fWdpath;
02054 }
02055
02056
02057 const char *TWinNTSystem::HomeDirectory(const char *userName)
02058 {
02059
02060
02061 static char mydir[kMAXPATHLEN] = "./";
02062 const char *h = 0;
02063 if (!(h = ::getenv("home"))) h = ::getenv("HOME");
02064
02065 if (h) {
02066 strlcpy(mydir, h,kMAXPATHLEN);
02067 } else {
02068
02069
02070 h = ::getenv("HOMESHARE");
02071 if (!h) h = ::getenv("HOMEDRIVE");
02072 if (h) {
02073 strlcpy(mydir, h,kMAXPATHLEN);
02074 h = ::getenv("HOMEPATH");
02075 if(h) strlcat(mydir, h,kMAXPATHLEN);
02076 }
02077
02078 if (!h) {
02079 h = ::getenv("USERPROFILE");
02080 if (h) strlcpy(mydir, h,kMAXPATHLEN);
02081 }
02082 }
02083
02084 if (mydir[1] == ':')
02085 mydir[0] = toupper(mydir[0]);
02086 return mydir;
02087 }
02088
02089
02090 const char *TWinNTSystem::TempDirectory() const
02091 {
02092
02093
02094
02095 const char *dir = gSystem->Getenv("TEMP");
02096 if (!dir) dir = gSystem->Getenv("TEMPDIR");
02097 if (!dir) dir = gSystem->Getenv("TEMP_DIR");
02098 if (!dir) dir = gSystem->Getenv("TMP");
02099 if (!dir) dir = gSystem->Getenv("TMPDIR");
02100 if (!dir) dir = gSystem->Getenv("TMP_DIR");
02101 if (!dir) dir = "c:\\";
02102
02103 return dir;
02104 }
02105
02106
02107 FILE *TWinNTSystem::TempFileName(TString &base, const char *dir)
02108 {
02109
02110
02111
02112
02113
02114
02115
02116
02117 char tmpName[MAX_PATH];
02118
02119 ::GetTempFileName(dir ? dir : TempDirectory(), base.Data(), 0, tmpName);
02120 base = tmpName;
02121 FILE *fp = fopen(tmpName, "w+");
02122
02123 if (!fp) ::SysError("TempFileName", "error opening %s", tmpName);
02124
02125 return fp;
02126 }
02127
02128
02129
02130
02131 TList *TWinNTSystem::GetVolumes(Option_t *opt) const
02132 {
02133
02134
02135
02136 Int_t curdrive;
02137 UInt_t type;
02138 TString sDrive, sType;
02139 char szFs[32];
02140
02141 if (!opt || !strlen(opt)) {
02142 return 0;
02143 }
02144
02145
02146 UINT nOldErrorMode = ::SetErrorMode(SEM_FAILCRITICALERRORS);
02147 TList *drives = new TList();
02148 drives->SetOwner();
02149
02150 curdrive = _getdrive();
02151 if (strstr(opt, "cur")) {
02152 *szFs='\0';
02153 sDrive.Form("%c:", (curdrive + 'A' - 1));
02154 sType.Form("Unknown Drive (%s)", sDrive.Data());
02155 ::GetVolumeInformation(Form("%s\\", sDrive.Data()), NULL, 0, NULL, NULL,
02156 NULL, (LPSTR)szFs, 32);
02157 type = ::GetDriveType(sDrive.Data());
02158 switch (type) {
02159 case DRIVE_UNKNOWN:
02160 case DRIVE_NO_ROOT_DIR:
02161 break;
02162 case DRIVE_REMOVABLE:
02163 sType.Form("Removable Disk (%s)", sDrive.Data());
02164 break;
02165 case DRIVE_FIXED:
02166 sType.Form("Local Disk (%s)", sDrive.Data());
02167 break;
02168 case DRIVE_REMOTE:
02169 sType.Form("Network Drive (%s) (%s)", szFs, sDrive.Data());
02170 break;
02171 case DRIVE_CDROM:
02172 sType.Form("CD/DVD Drive (%s)", sDrive.Data());
02173 break;
02174 case DRIVE_RAMDISK:
02175 sType.Form("RAM Disk (%s)", sDrive.Data());
02176 break;
02177 }
02178 drives->Add(new TNamed(sDrive.Data(), sType.Data()));
02179 }
02180 else if (strstr(opt, "all")) {
02181 TCHAR szTemp[512];
02182 szTemp[0] = '\0';
02183 if (::GetLogicalDriveStrings(511, szTemp)) {
02184 TCHAR szDrive[3] = TEXT(" :");
02185 TCHAR* p = szTemp;
02186 do {
02187
02188 *szDrive = *p;
02189 *szFs='\0';
02190 sDrive.Form("%s", szDrive);
02191
02192 if ((sDrive == "A:") || (sDrive == "B:")) {
02193 while (*p++);
02194 continue;
02195 }
02196 sType.Form("Unknown Drive (%s)", sDrive.Data());
02197 ::GetVolumeInformation(Form("%s\\", sDrive.Data()), NULL, 0, NULL,
02198 NULL, NULL, (LPSTR)szFs, 32);
02199 type = ::GetDriveType(sDrive.Data());
02200 switch (type) {
02201 case DRIVE_UNKNOWN:
02202 case DRIVE_NO_ROOT_DIR:
02203 break;
02204 case DRIVE_REMOVABLE:
02205 sType.Form("Removable Disk (%s)", sDrive.Data());
02206 break;
02207 case DRIVE_FIXED:
02208 sType.Form("Local Disk (%s)", sDrive.Data());
02209 break;
02210 case DRIVE_REMOTE:
02211 sType.Form("Network Drive (%s) (%s)", szFs, sDrive.Data());
02212 break;
02213 case DRIVE_CDROM:
02214 sType.Form("CD/DVD Drive (%s)", sDrive.Data());
02215 break;
02216 case DRIVE_RAMDISK:
02217 sType.Form("RAM Disk (%s)", sDrive.Data());
02218 break;
02219 }
02220 drives->Add(new TNamed(sDrive.Data(), sType.Data()));
02221
02222 while (*p++);
02223 } while (*p);
02224 }
02225 }
02226
02227 ::SetErrorMode(nOldErrorMode);
02228 return drives;
02229 }
02230
02231
02232 const char *TWinNTSystem::DirName(const char *pathname)
02233 {
02234
02235
02236
02237
02238
02239 if (fDirNameBuffer) {
02240
02241 fDirNameBuffer = 0;
02242 }
02243
02244
02245 if (pathname) {
02246 if (strchr(pathname, '/') || strchr(pathname, '\\')) {
02247 const char *rslash = strrchr(pathname, '/');
02248 const char *bslash = strrchr(pathname, '\\');
02249 const char *r = max(rslash, bslash);
02250 const char *ptr = pathname;
02251 while (ptr <= r) {
02252 if (*ptr == ':') {
02253
02254
02255 pathname = ptr + 1;
02256 break;
02257 }
02258 ptr++;
02259 }
02260 int len = r - pathname;
02261 if (len > 0) {
02262 fDirNameBuffer = new char[len+1];
02263 memcpy(fDirNameBuffer, pathname, len);
02264 fDirNameBuffer[len] = 0;
02265 }
02266 }
02267 }
02268 if (!fDirNameBuffer) {
02269 fDirNameBuffer = new char[1];
02270 *fDirNameBuffer = '\0';
02271 }
02272 return fDirNameBuffer;
02273 }
02274
02275
02276 const char TWinNTSystem::DriveName(const char *pathname)
02277 {
02278
02279
02280
02281
02282
02283
02284
02285
02286
02287
02288
02289
02290
02291 if (!pathname) return 0;
02292 if (!pathname[0]) return 0;
02293
02294 const char *lpchar;
02295 lpchar = pathname;
02296
02297
02298 while(*lpchar == ' ') lpchar++;
02299
02300 if (isalpha((int)*lpchar) && *(lpchar+1) == ':') {
02301 return *lpchar;
02302 }
02303
02304 if ( (*lpchar == '\\' || *lpchar == '/' ) &&
02305 (*(lpchar+1) == '\\' || *(lpchar+1) == '/') ) return 0;
02306
02307
02308 return DriveName(WorkingDirectory());
02309 }
02310
02311
02312 Bool_t TWinNTSystem::IsAbsoluteFileName(const char *dir)
02313 {
02314
02315
02316 if (dir) {
02317 int idx = 0;
02318 if (strchr(dir,':')) idx = 2;
02319 return (dir[idx] == '/' || dir[idx] == '\\');
02320 }
02321 return kFALSE;
02322 }
02323
02324
02325 const char *TWinNTSystem::UnixPathName(const char *name)
02326 {
02327
02328
02329
02330
02331
02332
02333
02334
02335
02336
02337
02338
02339
02340
02341
02342
02343
02344
02345
02346
02347
02348
02349
02350
02351
02352 static char temp[1024];
02353 strlcpy(temp, name,1024);
02354 char *currentChar = temp;
02355
02356 while (*currentChar != '\0') {
02357 if (*currentChar == '\\') *currentChar = '/';
02358 currentChar++;
02359 }
02360 return temp;
02361 }
02362
02363
02364 Bool_t TWinNTSystem::AccessPathName(const char *path, EAccessMode mode)
02365 {
02366
02367
02368
02369
02370 TSystem *helper = FindHelper(path);
02371 if (helper)
02372 return helper->AccessPathName(path, mode);
02373
02374 if (mode==kExecutePermission)
02375
02376 mode=kReadPermission;
02377 const char *proto = (strstr(path, "file:///")) ? "file://" : "file:";
02378 if (::_access(StripOffProto(path, proto), mode) == 0)
02379 return kFALSE;
02380 fLastErrorString = GetError();
02381 return kTRUE;
02382 }
02383
02384
02385 Bool_t TWinNTSystem::IsPathLocal(const char *path)
02386 {
02387
02388
02389
02390 TSystem *helper = FindHelper(path);
02391 if (helper)
02392 return helper->IsPathLocal(path);
02393
02394 return TSystem::IsPathLocal(path);
02395 }
02396
02397
02398 const char *TWinNTSystem::PrependPathName(const char *dir, TString& name)
02399 {
02400
02401
02402 if (name == ".") name = "";
02403 if (dir && dir[0]) {
02404
02405 char last = dir[strlen(dir) - 1];
02406 if (last != '/' && last != '\\') {
02407 name.Prepend('\\');
02408 }
02409 name.Prepend(dir);
02410 name.ReplaceAll("/", "\\");
02411 }
02412 return name.Data();
02413 }
02414
02415
02416 int TWinNTSystem::CopyFile(const char *f, const char *t, Bool_t overwrite)
02417 {
02418
02419
02420
02421
02422 if (AccessPathName(f, kReadPermission)) return -1;
02423 if (!AccessPathName(t) && !overwrite) return -2;
02424
02425 Bool_t ret = ::CopyFileA(f, t, kFALSE);
02426
02427 if (!ret) return -1;
02428 return 0;
02429 }
02430
02431
02432 int TWinNTSystem::Rename(const char *f, const char *t)
02433 {
02434
02435
02436 int ret = ::rename(f, t);
02437 fLastErrorString = GetError();
02438 return ret;
02439 }
02440
02441
02442 int TWinNTSystem::GetPathInfo(const char *path, FileStat_t &buf)
02443 {
02444
02445
02446
02447
02448
02449 TSystem *helper = FindHelper(path);
02450 if (helper)
02451 return helper->GetPathInfo(path, buf);
02452
02453 struct _stati64 sbuf;
02454
02455
02456 const char *proto = (strstr(path, "file:///")) ? "file://" : "file:";
02457 char *newpath = StrDup(StripOffProto(path, proto));
02458 int l = strlen(newpath);
02459 while (l > 1) {
02460 if (newpath[--l] != '\\' || newpath[--l] != '/') {
02461 break;
02462 }
02463 newpath[l] = '\0';
02464 }
02465
02466 if (newpath && ::_stati64(newpath, &sbuf) >= 0) {
02467
02468 buf.fDev = sbuf.st_dev;
02469 buf.fIno = sbuf.st_ino;
02470 buf.fMode = sbuf.st_mode;
02471 buf.fUid = sbuf.st_uid;
02472 buf.fGid = sbuf.st_gid;
02473 buf.fSize = sbuf.st_size;
02474 buf.fMtime = sbuf.st_mtime;
02475 buf.fIsLink = IsShortcut(newpath);
02476
02477
02478
02479
02480
02481
02482
02483
02484
02485
02486
02487 delete [] newpath;
02488 return 0;
02489 }
02490 delete [] newpath;
02491 return 1;
02492 }
02493
02494
02495 int TWinNTSystem::GetFsInfo(const char *path, Long_t *id, Long_t *bsize,
02496 Long_t *blocks, Long_t *bfree)
02497 {
02498
02499
02500
02501
02502
02503
02504
02505
02506
02507 LPCTSTR lpRootPathName = path;
02508
02509
02510 LPTSTR lpVolumeNameBuffer = 0;
02511 DWORD nVolumeNameSize = 0;
02512
02513 DWORD volumeSerialNumber;
02514 DWORD maximumComponentLength;
02515
02516
02517 DWORD fileSystemFlags;
02518
02519
02520 char fileSystemNameBuffer[512];
02521 DWORD nFileSystemNameSize = sizeof(fileSystemNameBuffer);
02522
02523
02524 UINT nOldErrorMode = ::SetErrorMode(SEM_FAILCRITICALERRORS);
02525 if (!::GetVolumeInformation(lpRootPathName,
02526 lpVolumeNameBuffer, nVolumeNameSize,
02527 &volumeSerialNumber,
02528 &maximumComponentLength,
02529 &fileSystemFlags,
02530 fileSystemNameBuffer, nFileSystemNameSize)) {
02531
02532 ::SetErrorMode(nOldErrorMode);
02533 return 1;
02534 }
02535
02536 const char *fsNames[] = { "FAT", "NTFS" };
02537 int i;
02538 for (i = 0; i < 2; i++) {
02539 if (!strncmp(fileSystemNameBuffer, fsNames[i], nFileSystemNameSize))
02540 break;
02541 }
02542 *id = i;
02543
02544 DWORD sectorsPerCluster;
02545 DWORD bytesPerSector;
02546 DWORD numberOfFreeClusters;
02547 DWORD totalNumberOfClusters;
02548
02549 if (!::GetDiskFreeSpace(lpRootPathName,
02550 §orsPerCluster,
02551 &bytesPerSector,
02552 &numberOfFreeClusters,
02553 &totalNumberOfClusters)) {
02554
02555 ::SetErrorMode(nOldErrorMode);
02556 return 1;
02557 }
02558
02559 ::SetErrorMode(nOldErrorMode);
02560
02561 *bsize = sectorsPerCluster * bytesPerSector;
02562 *blocks = totalNumberOfClusters;
02563 *bfree = numberOfFreeClusters;
02564
02565 return 0;
02566 }
02567
02568
02569 int TWinNTSystem::Link(const char *from, const char *to)
02570 {
02571
02572
02573 struct _stati64 finfo;
02574 char winDrive[256];
02575 char winDir[256];
02576 char winName[256];
02577 char winExt[256];
02578 char linkname[1024];
02579 LPTSTR lpszFilePart;
02580 TCHAR szPath[MAX_PATH];
02581 DWORD dwRet = 0;
02582
02583 typedef BOOL (__stdcall *CREATEHARDLINKPROC)( LPCTSTR, LPCTSTR, LPSECURITY_ATTRIBUTES );
02584 static CREATEHARDLINKPROC _CreateHardLink = 0;
02585
02586 HMODULE hModImagehlp = LoadLibrary( "Kernel32.dll" );
02587 if (!hModImagehlp)
02588 return -1;
02589
02590 #ifdef _UNICODE
02591 _CreateHardLink = (CREATEHARDLINKPROC) GetProcAddress( hModImagehlp, "CreateHardLinkW" );
02592 #else
02593 _CreateHardLink = (CREATEHARDLINKPROC) GetProcAddress( hModImagehlp, "CreateHardLinkA" );
02594 #endif
02595 if (!_CreateHardLink)
02596 return -1;
02597
02598 dwRet = GetFullPathName(from, sizeof(szPath) / sizeof(TCHAR),
02599 szPath, &lpszFilePart);
02600
02601 if (_stati64(szPath, &finfo) < 0)
02602 return -1;
02603
02604 if (finfo.st_mode & S_IFDIR)
02605 return -1;
02606
02607 snprintf(linkname,1024,"%s",to);
02608 _splitpath(linkname,winDrive,winDir,winName,winExt);
02609 if ((strlen(winDrive) == 0 ) &&
02610 (strlen(winDir) == 0 )) {
02611 _splitpath(szPath,winDrive,winDir,winName,winExt);
02612 snprintf(linkname,1024,"%s\\%s\\%s", winDrive, winDir, to);
02613 }
02614 else if (strlen(winDrive) == 0) {
02615 _splitpath(szPath,winDrive,winDir,winName,winExt);
02616 snprintf(linkname,1024,"%s\\%s", winDrive, to);
02617 }
02618
02619 if (!_CreateHardLink(linkname, szPath, NULL))
02620 return -1;
02621
02622 return 0;
02623 }
02624
02625
02626 int TWinNTSystem::Symlink(const char *from, const char *to)
02627 {
02628
02629
02630
02631 HRESULT hRes;
02632 IShellLink* pShellLink;
02633 IPersistFile* pPersistFile;
02634 WCHAR wszLinkfile[MAX_PATH];
02635 int iWideCharsWritten;
02636 DWORD dwRet = 0;
02637 LPTSTR lpszFilePart;
02638 TCHAR szPath[MAX_PATH];
02639
02640 hRes = E_INVALIDARG;
02641 if ((from == NULL) || (strlen(from) == 0) || (to == NULL) ||
02642 (strlen(to) == 0))
02643 return -1;
02644
02645
02646
02647 typedef HRESULT (__stdcall *COINITIALIZEPROC)( LPVOID );
02648 static COINITIALIZEPROC _CoInitialize = 0;
02649 typedef void (__stdcall *COUNINITIALIZEPROC)( void );
02650 static COUNINITIALIZEPROC _CoUninitialize = 0;
02651 typedef HRESULT (__stdcall *COCREATEINSTANCEPROC)( REFCLSID, LPUNKNOWN, DWORD, REFIID, LPVOID );
02652 static COCREATEINSTANCEPROC _CoCreateInstance = 0;
02653
02654 HMODULE hModImagehlp = LoadLibrary( "ole32.dll" );
02655 if (!hModImagehlp)
02656 return -1;
02657
02658 _CoInitialize = (COINITIALIZEPROC) GetProcAddress( hModImagehlp, "CoInitialize" );
02659 if (!_CoInitialize)
02660 return -1;
02661 _CoUninitialize = (COUNINITIALIZEPROC) GetProcAddress( hModImagehlp, "CoUninitialize" );
02662 if (!_CoUninitialize)
02663 return -1;
02664 _CoCreateInstance = (COCREATEINSTANCEPROC) GetProcAddress( hModImagehlp, "CoCreateInstance" );
02665 if (!_CoCreateInstance)
02666 return -1;
02667
02668 TString linkname(to);
02669 if (!linkname.EndsWith(".lnk"))
02670 linkname.Append(".lnk");
02671
02672 _CoInitialize(NULL);
02673
02674
02675 dwRet = GetFullPathName(from, sizeof(szPath) / sizeof(TCHAR),
02676 szPath, &lpszFilePart);
02677 hRes = _CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
02678 IID_IShellLink, (LPVOID *)&pShellLink);
02679 if (SUCCEEDED(hRes)) {
02680
02681 hRes = pShellLink->SetPath(szPath);
02682
02683 hRes = pShellLink->QueryInterface(IID_IPersistFile, (void **)&pPersistFile);
02684 if (SUCCEEDED(hRes)){
02685 iWideCharsWritten = MultiByteToWideChar(CP_ACP, 0, linkname.Data(), -1,
02686 wszLinkfile, MAX_PATH);
02687 hRes = pPersistFile->Save(wszLinkfile, TRUE);
02688 pPersistFile->Release();
02689 }
02690 pShellLink->Release();
02691 }
02692 _CoUninitialize();
02693 return 0;
02694 }
02695
02696
02697 int TWinNTSystem::Unlink(const char *name)
02698 {
02699
02700
02701 TSystem *helper = FindHelper(name);
02702 if (helper)
02703 return helper->Unlink(name);
02704
02705 struct _stati64 finfo;
02706
02707 if (_stati64(name, &finfo) < 0) {
02708 return -1;
02709 }
02710
02711 if (finfo.st_mode & S_IFDIR) {
02712 return ::_rmdir(name);
02713 } else {
02714 return ::_unlink(name);
02715 }
02716 }
02717
02718
02719 int TWinNTSystem::SetNonBlock(int fd)
02720 {
02721
02722
02723 if (::ioctlsocket(fd, FIONBIO, (u_long *)1) == SOCKET_ERROR) {
02724 ::SysError("SetNonBlock", "ioctlsocket");
02725 return -1;
02726 }
02727 return 0;
02728 }
02729
02730
02731
02732 static char
02733 *shellMeta = "~*[]{}?$%",
02734 *shellStuff = "(){}<>\"'",
02735 shellEscape = '\\';
02736
02737
02738 Bool_t TWinNTSystem::ExpandPathName(TString &patbuf0)
02739 {
02740
02741
02742 const char *patbuf = (const char *)patbuf0;
02743 const char *p;
02744 char *cmd = 0;
02745 char *q;
02746
02747
02748 while (*patbuf == ' ') {
02749 patbuf++;
02750 }
02751
02752
02753 while (*patbuf == ':') {
02754 patbuf++;
02755 }
02756
02757
02758 while (*patbuf == ';') {
02759 patbuf++;
02760 }
02761
02762
02763
02764 for (q = (char*)patbuf; *q; q++) {
02765 if ( *q == ':' ) {
02766
02767
02768 if ( (((q-2)>patbuf) && ( (*(q-2)!=';') || !isalpha(*(q-1)) )) &&
02769 *(q+1)!='/' ) {
02770 *q=';';
02771 }
02772 }
02773 }
02774
02775 for (p = patbuf; *p; p++) {
02776 if (strchr(shellMeta, *p)) {
02777 goto needshell;
02778 }
02779 }
02780 return kFALSE;
02781
02782 needshell:
02783
02784
02785
02786
02787
02788
02789
02790
02791
02792 char replacement[4];
02793
02794
02795 for (int k = 0; k<3; k++) replacement[k] = 0x1;
02796
02797 replacement[3] = 0x0;
02798 Ssiz_t pos = 0;
02799 TRegexp TildaNum = "~[0-9]";
02800
02801 while ( (pos = patbuf0.Index(TildaNum,pos)) != kNPOS ) {
02802 patbuf0.Replace(pos, 1, replacement);
02803 }
02804
02805
02806
02807 patbuf0 = ExpandFileName(patbuf0.Data());
02808 Int_t lbuf = ::ExpandEnvironmentStrings(
02809 patbuf0.Data(),
02810 cmd,
02811 0
02812 );
02813 if (lbuf > 0) {
02814 cmd = new char[lbuf+1];
02815 ::ExpandEnvironmentStrings(
02816 patbuf0.Data(),
02817 cmd,
02818 lbuf
02819 );
02820 patbuf0 = cmd;
02821 patbuf0.ReplaceAll(replacement, "~");
02822 delete [] cmd;
02823 return kFALSE;
02824 }
02825 return kTRUE;
02826 }
02827
02828
02829 char *TWinNTSystem::ExpandPathName(const char *path)
02830 {
02831
02832
02833
02834 char newpath[MAX_PATH];
02835 if (IsShortcut(path)) {
02836 if (!ResolveShortCut(path, newpath, MAX_PATH))
02837 strlcpy(newpath, path,MAX_PATH);
02838 }
02839 else
02840 strlcpy(newpath, path,MAX_PATH);
02841 TString patbuf = newpath;
02842 if (ExpandPathName(patbuf)) return 0;
02843
02844 return StrDup(patbuf.Data());
02845 }
02846
02847
02848 int TWinNTSystem::Chmod(const char *file, UInt_t mode)
02849 {
02850
02851
02852
02853
02854
02855 return ::_chmod(file, mode);
02856 }
02857
02858
02859 int TWinNTSystem::Umask(Int_t mask)
02860 {
02861
02862
02863 return ::umask(mask);
02864 }
02865
02866
02867 int TWinNTSystem::Utime(const char *file, Long_t modtime, Long_t actime)
02868 {
02869
02870
02871
02872 if (AccessPathName(file, kWritePermission)) {
02873 Error("Utime", "need write permission for %s to change utime", file);
02874 return -1;
02875 }
02876 if (!actime) actime = modtime;
02877
02878 struct utimbuf t;
02879 t.actime = (time_t)actime;
02880 t.modtime = (time_t)modtime;
02881 return ::utime(file, &t);
02882 }
02883
02884
02885 const char *TWinNTSystem::FindFile(const char *search, TString& infile, EAccessMode mode)
02886 {
02887
02888
02889
02890
02891 if (mode==kExecutePermission)
02892 mode=kReadPermission;
02893
02894
02895
02896 gSystem->ExpandPathName(infile);
02897
02898 if (IsAbsoluteFileName(infile.Data()) ) {
02899 if (!AccessPathName(infile.Data(), mode))
02900 return infile.Data();
02901 infile = "";
02902 return 0;
02903 }
02904 TString exsearch(search);
02905 gSystem->ExpandPathName(exsearch);
02906
02907
02908 Int_t lastDelim = -1;
02909 for(int i=0; i < exsearch.Length(); ++i) {
02910 switch( exsearch[i] ) {
02911 case ':':
02912
02913 if (i-lastDelim!=2) exsearch[i] = ';';
02914 lastDelim = i;
02915 break;
02916 case ';': lastDelim = i; break;
02917 }
02918 }
02919
02920
02921 struct stat finfo;
02922 char name[kMAXPATHLEN];
02923 char *lpFilePart = 0;
02924 if (::SearchPath(exsearch.Data(), infile.Data(), NULL, kMAXPATHLEN, name, &lpFilePart) &&
02925 ::access(name, mode) == 0 && stat(name, &finfo) == 0 &&
02926 finfo.st_mode & S_IFREG) {
02927 if (gEnv->GetValue("Root.ShowPath", 0)) {
02928 Printf("Which: %s = %s", infile, name);
02929 }
02930 infile = name;
02931 return infile.Data();
02932 }
02933 infile = "";
02934 return 0;
02935 }
02936
02937
02938
02939
02940 Bool_t TWinNTSystem::InitUsersGroups()
02941 {
02942
02943
02944
02945 if ((gEnv->GetValue("WinNT.UseNetAPI", 0)) && (::GetVersion() < 0x80000000)) {
02946 fActUser = -1;
02947 fNbGroups = fNbUsers = 0;
02948 HINSTANCE netapi = ::LoadLibrary("netapi32.DLL");
02949 if (!netapi) return kFALSE;
02950
02951 p2NetApiBufferFree = (pfn1)::GetProcAddress(netapi, "NetApiBufferFree");
02952 p2NetUserGetInfo = (pfn2)::GetProcAddress(netapi, "NetUserGetInfo");
02953 p2NetLocalGroupGetMembers = (pfn3)::GetProcAddress(netapi, "NetLocalGroupGetMembers");
02954 p2NetLocalGroupEnum = (pfn4)::GetProcAddress(netapi, "NetLocalGroupEnum");
02955
02956 if (!p2NetApiBufferFree || !p2NetUserGetInfo ||
02957 !p2NetLocalGroupGetMembers || !p2NetLocalGroupEnum) return kFALSE;
02958
02959 GetNbGroups();
02960
02961 fGroups = (struct group *)calloc(fNbGroups, sizeof(struct group));
02962 for(int i=0;i<fNbGroups;i++) {
02963 fGroups[i].gr_mem = (char **)calloc(fNbUsers, sizeof (char*));
02964 }
02965 fPasswords = (struct passwd *)calloc(fNbUsers, sizeof(struct passwd));
02966
02967 CollectGroups();
02968 ::FreeLibrary(netapi);
02969 }
02970 fGroupsInitDone = kTRUE;
02971 return kTRUE;
02972 }
02973
02974
02975 Bool_t TWinNTSystem::CountMembers(const char *lpszGroupName)
02976 {
02977 NET_API_STATUS NetStatus = NERR_Success;
02978 LPBYTE Data = NULL;
02979 DWORD Index = 0, ResumeHandle = 0, Total = 0;
02980 LOCALGROUP_MEMBERS_INFO_1 *MemberInfo;
02981 WCHAR wszGroupName[256];
02982 int iRetOp = 0;
02983 DWORD dwLastError = 0;
02984
02985 iRetOp = MultiByteToWideChar (
02986 (UINT)CP_ACP,
02987 (DWORD)MB_PRECOMPOSED,
02988 (LPCSTR)lpszGroupName,
02989 (int)-1,
02990 (LPWSTR)wszGroupName,
02991 (int)sizeof(wszGroupName) );
02992
02993 if (iRetOp == 0) {
02994 dwLastError = GetLastError();
02995 if (Data)
02996 p2NetApiBufferFree(Data);
02997 return FALSE;
02998 }
02999
03000
03001
03002 NetStatus = p2NetLocalGroupGetMembers (NULL, wszGroupName, 1,
03003 &Data, 8192, &Index, &Total, &ResumeHandle );
03004
03005 if (NetStatus != NERR_Success || Data == NULL) {
03006 dwLastError = GetLastError();
03007
03008 if (dwLastError == ERROR_ENVVAR_NOT_FOUND) {
03009
03010
03011
03012
03013
03014 NetStatus = p2NetLocalGroupGetMembers ( NULL, wszGroupName, 0,
03015 &Data, 8192, &Index, &Total, &ResumeHandle );
03016 }
03017
03018 if (Data)
03019 p2NetApiBufferFree(Data);
03020 return FALSE;
03021 }
03022
03023 fNbUsers += Total;
03024 MemberInfo = (LOCALGROUP_MEMBERS_INFO_1 *)Data;
03025
03026 if (Data)
03027 p2NetApiBufferFree(Data);
03028
03029 return TRUE;
03030 }
03031
03032
03033 Bool_t TWinNTSystem::GetNbGroups()
03034 {
03035 NET_API_STATUS NetStatus = NERR_Success;
03036 LPBYTE Data = NULL;
03037 DWORD Index = 0, ResumeHandle = 0, Total = 0, i;
03038 LOCALGROUP_INFO_0 *GroupInfo;
03039 char szAnsiName[256];
03040 DWORD dwLastError = 0;
03041 int iRetOp = 0;
03042
03043 NetStatus = p2NetLocalGroupEnum(NULL, 0, &Data, 8192, &Index,
03044 &Total, &ResumeHandle );
03045
03046 if (NetStatus != NERR_Success || Data == NULL) {
03047 dwLastError = GetLastError();
03048 if (Data)
03049 p2NetApiBufferFree(Data);
03050 return FALSE;
03051 }
03052
03053 fNbGroups = Total;
03054 GroupInfo = (LOCALGROUP_INFO_0 *)Data;
03055 for (i=0; i < Total; i++) {
03056
03057 iRetOp = WideCharToMultiByte (
03058 (UINT)CP_ACP,
03059 (DWORD)0,
03060 (LPCWSTR)(GroupInfo->lgrpi0_name),
03061 (int)-1,
03062 (LPSTR)szAnsiName,
03063 (int)(sizeof(szAnsiName)),
03064 (LPCSTR)NULL,
03065 (LPBOOL)NULL );
03066
03067
03068
03069 CountMembers((LPCTSTR)szAnsiName);
03070
03071 GroupInfo++;
03072 }
03073
03074 if (Data)
03075 p2NetApiBufferFree(Data);
03076
03077 return TRUE;
03078 }
03079
03080
03081 Long_t TWinNTSystem::LookupSID (const char *lpszAccountName, int what,
03082 int &groupIdx, int &memberIdx)
03083 {
03084
03085
03086
03087
03088 BOOL bRetOp = FALSE;
03089 PSID pSid = NULL;
03090 DWORD dwSidSize, dwDomainNameSize;
03091 BYTE bySidBuffer[MAX_SID_SIZE];
03092 char szDomainName[MAX_NAME_STRING];
03093 SID_NAME_USE sidType;
03094 PUCHAR puchar_SubAuthCount = NULL;
03095 SID_IDENTIFIER_AUTHORITY sid_identifier_authority;
03096 PSID_IDENTIFIER_AUTHORITY psid_identifier_authority = NULL;
03097 unsigned char j = 0;
03098 DWORD dwLastError = 0;
03099
03100 pSid = (PSID)bySidBuffer;
03101 dwSidSize = sizeof(bySidBuffer);
03102 dwDomainNameSize = sizeof(szDomainName);
03103
03104 bRetOp = LookupAccountName (
03105 (LPCTSTR)NULL,
03106 (LPCTSTR)lpszAccountName,
03107 (PSID)pSid,
03108 (LPDWORD)&dwSidSize,
03109 (LPTSTR)szDomainName,
03110 (LPDWORD)&dwDomainNameSize,
03111 (PSID_NAME_USE)&sidType );
03112
03113 if (bRetOp == FALSE) {
03114 dwLastError = GetLastError();
03115 return -1;
03116 }
03117
03118 bRetOp = IsValidSid((PSID)pSid);
03119
03120 if (bRetOp == FALSE) {
03121 dwLastError = GetLastError();
03122 return -2;
03123 }
03124
03125
03126 psid_identifier_authority = GetSidIdentifierAuthority ((PSID)pSid);
03127
03128
03129 memcpy (&sid_identifier_authority, psid_identifier_authority,
03130 sizeof(SID_IDENTIFIER_AUTHORITY));
03131
03132
03133 puchar_SubAuthCount = (PUCHAR)GetSidSubAuthorityCount((PSID)pSid);
03134
03135 j = (unsigned char)(*puchar_SubAuthCount);
03136
03137 DWORD dwSubAuth = 0;
03138 PDWORD pdwSubAuth = NULL;
03139
03140 pdwSubAuth = (PDWORD)GetSidSubAuthority (
03141 (PSID)pSid,
03142 (DWORD)j-1);
03143 dwSubAuth = *pdwSubAuth;
03144 if(what == SID_MEMBER) {
03145 fPasswords[memberIdx].pw_uid = dwSubAuth;
03146 fPasswords[memberIdx].pw_gid = fGroups[groupIdx].gr_gid;
03147 fPasswords[memberIdx].pw_group = strdup(fGroups[groupIdx].gr_name);
03148 }
03149 else if(what == SID_GROUP) {
03150 fGroups[groupIdx].gr_gid = dwSubAuth;
03151 }
03152 return 0;
03153 }
03154
03155
03156 Bool_t TWinNTSystem::CollectMembers(const char *lpszGroupName, int &groupIdx,
03157 int &memberIdx)
03158 {
03159
03160
03161
03162 NET_API_STATUS NetStatus = NERR_Success;
03163 LPBYTE Data = NULL;
03164 DWORD Index = 0, ResumeHandle = 0, Total = 0, i;
03165 LOCALGROUP_MEMBERS_INFO_1 *MemberInfo;
03166 char szAnsiMemberName[256];
03167 char szFullMemberName[256];
03168 char szMemberHomeDir[256];
03169 WCHAR wszGroupName[256];
03170 int iRetOp = 0;
03171 char act_name[256];
03172 DWORD length = sizeof (act_name);
03173 DWORD dwLastError = 0;
03174 LPUSER_INFO_11 pUI11Buf = NULL;
03175 NET_API_STATUS nStatus;
03176
03177 iRetOp = MultiByteToWideChar (
03178 (UINT)CP_ACP,
03179 (DWORD)MB_PRECOMPOSED,
03180 (LPCSTR)lpszGroupName,
03181 (int)-1,
03182 (LPWSTR)wszGroupName,
03183 (int)sizeof(wszGroupName) );
03184
03185 if (iRetOp == 0) {
03186 dwLastError = GetLastError();
03187 if (Data)
03188 p2NetApiBufferFree(Data);
03189 return FALSE;
03190 }
03191
03192 GetUserName (act_name, &length);
03193
03194
03195
03196 NetStatus = p2NetLocalGroupGetMembers (NULL, wszGroupName, 1,
03197 &Data, 8192, &Index, &Total, &ResumeHandle );
03198
03199 if (NetStatus != NERR_Success || Data == NULL) {
03200 dwLastError = GetLastError();
03201
03202 if (dwLastError == ERROR_ENVVAR_NOT_FOUND) {
03203
03204
03205
03206
03207
03208 NetStatus = p2NetLocalGroupGetMembers ( NULL, wszGroupName, 0,
03209 &Data, 8192, &Index, &Total, &ResumeHandle );
03210 }
03211
03212 if (Data)
03213 p2NetApiBufferFree(Data);
03214 return FALSE;
03215 }
03216
03217 MemberInfo = (LOCALGROUP_MEMBERS_INFO_1 *)Data;
03218 for (i=0; i < Total; i++) {
03219 iRetOp = WideCharToMultiByte (
03220 (UINT)CP_ACP,
03221 (DWORD)0,
03222 (LPCWSTR)(MemberInfo->lgrmi1_name),
03223 (int)-1,
03224 (LPSTR)szAnsiMemberName,
03225 (int)(sizeof(szAnsiMemberName)),
03226 (LPCSTR)NULL,
03227 (LPBOOL)NULL );
03228
03229 if (iRetOp == 0) {
03230 dwLastError = GetLastError();
03231 }
03232
03233 fPasswords[memberIdx].pw_name = strdup(szAnsiMemberName);
03234 fPasswords[memberIdx].pw_passwd = strdup("");
03235 fGroups[groupIdx].gr_mem[i] = strdup(szAnsiMemberName);
03236
03237 if(fActUser == -1 && !stricmp(fPasswords[memberIdx].pw_name,act_name))
03238 fActUser = memberIdx;
03239
03240
03241 TCHAR szUserName[255]=TEXT("");
03242 MultiByteToWideChar(CP_ACP, 0, szAnsiMemberName, -1, (LPWSTR)szUserName, 255);
03243
03244
03245
03246 nStatus = p2NetUserGetInfo(NULL, (LPCWSTR)szUserName, 11, (LPBYTE *)&pUI11Buf);
03247
03248
03249
03250 if (nStatus == NERR_Success) {
03251 if (pUI11Buf != NULL) {
03252 wsprintf(szFullMemberName,"%S",pUI11Buf->usri11_full_name);
03253 fPasswords[memberIdx].pw_gecos = strdup(szFullMemberName);
03254 wsprintf(szMemberHomeDir,"%S",pUI11Buf->usri11_home_dir);
03255 fPasswords[memberIdx].pw_dir = strdup(szMemberHomeDir);
03256 }
03257 }
03258 if((fPasswords[memberIdx].pw_gecos == NULL) || (strlen(fPasswords[memberIdx].pw_gecos) == 0))
03259 fPasswords[memberIdx].pw_gecos = strdup(fPasswords[memberIdx].pw_name);
03260 if((fPasswords[memberIdx].pw_dir == NULL) || (strlen(fPasswords[memberIdx].pw_dir) == 0))
03261 fPasswords[memberIdx].pw_dir = strdup("c:\\");
03262
03263
03264
03265 if (pUI11Buf != NULL) {
03266 p2NetApiBufferFree(pUI11Buf);
03267 pUI11Buf = NULL;
03268 }
03269
03270
03271 if (getenv("SHELL") == NULL)
03272 putenv ((GetVersion () & 0x80000000) ? "SHELL=command" : "SHELL=cmd");
03273
03274
03275 fPasswords[memberIdx].pw_shell = getenv("SHELL");
03276
03277
03278 LookupSID ((LPCTSTR)szAnsiMemberName, SID_MEMBER, groupIdx, memberIdx);
03279 memberIdx++;
03280 MemberInfo++;
03281 }
03282 if(fActUser == -1) fActUser = 0;
03283
03284 if (Data)
03285 p2NetApiBufferFree(Data);
03286
03287 return TRUE;
03288 }
03289
03290
03291 Bool_t TWinNTSystem::CollectGroups()
03292 {
03293
03294
03295 NET_API_STATUS NetStatus = NERR_Success;
03296 LPBYTE Data = NULL;
03297 DWORD Index = 0, ResumeHandle = 0, Total = 0, i;
03298 LOCALGROUP_INFO_0 *GroupInfo;
03299 char szAnsiName[256];
03300 DWORD dwLastError = 0;
03301 int iRetOp = 0, iGroupIdx = 0, iMemberIdx = 0;
03302
03303 NetStatus = p2NetLocalGroupEnum(NULL, 0, &Data, 8192, &Index,
03304 &Total, &ResumeHandle );
03305
03306 if (NetStatus != NERR_Success || Data == NULL) {
03307 dwLastError = GetLastError();
03308 if (Data)
03309 p2NetApiBufferFree(Data);
03310 return FALSE;
03311 }
03312
03313 GroupInfo = (LOCALGROUP_INFO_0 *)Data;
03314 for (i=0; i < Total; i++) {
03315
03316 iRetOp = WideCharToMultiByte (
03317 (UINT)CP_ACP,
03318 (DWORD)0,
03319 (LPCWSTR)(GroupInfo->lgrpi0_name),
03320 (int)-1,
03321 (LPSTR)szAnsiName,
03322 (int)(sizeof(szAnsiName)),
03323 (LPCSTR)NULL,
03324 (LPBOOL)NULL );
03325
03326 fGroups[iGroupIdx].gr_name = strdup(szAnsiName);
03327 fGroups[iGroupIdx].gr_passwd = strdup("");
03328
03329
03330 LookupSID ((LPCTSTR)szAnsiName, SID_GROUP, iGroupIdx, iMemberIdx);
03331
03332
03333 CollectMembers((LPCTSTR)szAnsiName, iGroupIdx, iMemberIdx);
03334
03335 iGroupIdx++;
03336 GroupInfo++;
03337 }
03338
03339 if (Data)
03340 p2NetApiBufferFree(Data);
03341
03342 return TRUE;
03343 }
03344
03345
03346 Int_t TWinNTSystem::GetUid(const char *user)
03347 {
03348
03349
03350 if(!fGroupsInitDone)
03351 InitUsersGroups();
03352
03353
03354 if ((!gEnv->GetValue("WinNT.UseNetAPI", 0)) || (::GetVersion() >= 0x80000000)) {
03355 int uid;
03356 char name[256];
03357 DWORD length = sizeof (name);
03358 if (::GetUserName (name, &length)) {
03359 if (stricmp ("administrator", name) == 0)
03360 uid = 0;
03361 else
03362 uid = 123;
03363 }
03364 else {
03365 uid = 123;
03366 }
03367 return uid;
03368 }
03369 if (!user || !user[0])
03370 return fPasswords[fActUser].pw_uid;
03371 else {
03372 struct passwd *pwd = 0;
03373 for(int i=0;i<fNbUsers;i++) {
03374 if (!stricmp (user, fPasswords[i].pw_name)) {
03375 pwd = &fPasswords[i];
03376 break;
03377 }
03378 }
03379 if (pwd)
03380 return pwd->pw_uid;
03381 }
03382 return 0;
03383 }
03384
03385
03386 Int_t TWinNTSystem::GetEffectiveUid()
03387 {
03388
03389
03390
03391 if(!fGroupsInitDone)
03392 InitUsersGroups();
03393
03394
03395 if ((!gEnv->GetValue("WinNT.UseNetAPI", 0)) || (::GetVersion() >= 0x80000000)) {
03396 int uid;
03397 char name[256];
03398 DWORD length = sizeof (name);
03399 if (::GetUserName (name, &length)) {
03400 if (stricmp ("administrator", name) == 0)
03401 uid = 0;
03402 else
03403 uid = 123;
03404 }
03405 else {
03406 uid = 123;
03407 }
03408 return uid;
03409 }
03410 return fPasswords[fActUser].pw_uid;
03411 }
03412
03413
03414 Int_t TWinNTSystem::GetGid(const char *group)
03415 {
03416
03417
03418 if(!fGroupsInitDone)
03419 InitUsersGroups();
03420
03421
03422 if ((!gEnv->GetValue("WinNT.UseNetAPI", 0)) || (::GetVersion() >= 0x80000000)) {
03423 int gid;
03424 char name[256];
03425 DWORD length = sizeof (name);
03426 if (::GetUserName (name, &length)) {
03427 if (stricmp ("administrator", name) == 0)
03428 gid = 0;
03429 else
03430 gid = 123;
03431 }
03432 else {
03433 gid = 123;
03434 }
03435 return gid;
03436 }
03437 if (!group || !group[0])
03438 return fPasswords[fActUser].pw_gid;
03439 else {
03440 struct group *grp = 0;
03441 for(int i=0;i<fNbGroups;i++) {
03442 if (!stricmp (group, fGroups[i].gr_name)) {
03443 grp = &fGroups[i];
03444 break;
03445 }
03446 }
03447 if (grp)
03448 return grp->gr_gid;
03449 }
03450 return 0;
03451 }
03452
03453
03454 Int_t TWinNTSystem::GetEffectiveGid()
03455 {
03456
03457
03458
03459 if(!fGroupsInitDone)
03460 InitUsersGroups();
03461
03462
03463 if ((!gEnv->GetValue("WinNT.UseNetAPI", 0)) || (::GetVersion() >= 0x80000000)) {
03464 int gid;
03465 char name[256];
03466 DWORD length = sizeof (name);
03467 if (::GetUserName (name, &length)) {
03468 if (stricmp ("administrator", name) == 0)
03469 gid = 0;
03470 else
03471 gid = 123;
03472 }
03473 else {
03474 gid = 123;
03475 }
03476 return gid;
03477 }
03478 return fPasswords[fActUser].pw_gid;
03479 }
03480
03481
03482 UserGroup_t *TWinNTSystem::GetUserInfo(Int_t uid)
03483 {
03484
03485
03486
03487 if(!fGroupsInitDone)
03488 InitUsersGroups();
03489
03490
03491 if ((!gEnv->GetValue("WinNT.UseNetAPI", 0)) || (::GetVersion() >= 0x80000000)) {
03492 char name[256];
03493 DWORD length = sizeof (name);
03494 UserGroup_t *ug = new UserGroup_t;
03495 if (::GetUserName (name, &length)) {
03496 ug->fUser = name;
03497 if (stricmp ("administrator", name) == 0) {
03498 ug->fUid = 0;
03499 ug->fGroup = "administrators";
03500 }
03501 else {
03502 ug->fUid = 123;
03503 ug->fGroup = "users";
03504 }
03505 ug->fGid = ug->fUid;
03506 }
03507 else {
03508 ug->fUser = "unknown";
03509 ug->fGroup = "unknown";
03510 ug->fUid = ug->fGid = 123;
03511 }
03512 ug->fPasswd = "";
03513 ug->fRealName = ug->fUser;
03514 ug->fShell = "command";
03515 return ug;
03516 }
03517 struct passwd *pwd = 0;
03518 if (uid == 0)
03519 pwd = &fPasswords[fActUser];
03520 else {
03521 for (int i = 0; i < fNbUsers; i++) {
03522 if (uid == fPasswords[i].pw_uid) {
03523 pwd = &fPasswords[i];
03524 break;
03525 }
03526 }
03527 }
03528 if (pwd) {
03529 UserGroup_t *ug = new UserGroup_t;
03530 ug->fUid = pwd->pw_uid;
03531 ug->fGid = pwd->pw_gid;
03532 ug->fUser = pwd->pw_name;
03533 ug->fPasswd = pwd->pw_passwd;
03534 ug->fRealName = pwd->pw_gecos;
03535 ug->fShell = pwd->pw_shell;
03536 ug->fGroup = pwd->pw_group;
03537 return ug;
03538 }
03539 return 0;
03540 }
03541
03542
03543 UserGroup_t *TWinNTSystem::GetUserInfo(const char *user)
03544 {
03545
03546
03547
03548
03549 return GetUserInfo(GetUid(user));
03550 }
03551
03552
03553 UserGroup_t *TWinNTSystem::GetGroupInfo(Int_t gid)
03554 {
03555
03556
03557
03558
03559
03560
03561 if(!fGroupsInitDone)
03562 InitUsersGroups();
03563
03564
03565 if ((!gEnv->GetValue("WinNT.UseNetAPI", 0)) || (::GetVersion() >= 0x80000000)) {
03566 char name[256];
03567 DWORD length = sizeof (name);
03568 UserGroup_t *gr = new UserGroup_t;
03569 if (::GetUserName (name, &length)) {
03570 if (stricmp ("administrator", name) == 0) {
03571 gr->fGroup = "administrators";
03572 gr->fGid = 0;
03573 }
03574 else {
03575 gr->fGroup = "users";
03576 gr->fGid = 123;
03577 }
03578 }
03579 else {
03580 gr->fGroup = "unknown";
03581 gr->fGid = 123;
03582 }
03583 gr->fUid = 0;
03584 return gr;
03585 }
03586 struct group *grp = 0;
03587 for(int i=0;i<fNbGroups;i++) {
03588 if (gid == fGroups[i].gr_gid) {
03589 grp = &fGroups[i];
03590 break;
03591 }
03592 }
03593 if (grp) {
03594 UserGroup_t *gr = new UserGroup_t;
03595 gr->fUid = 0;
03596 gr->fGid = grp->gr_gid;
03597 gr->fGroup = grp->gr_name;
03598 return gr;
03599 }
03600 return 0;
03601
03602 }
03603
03604
03605 UserGroup_t *TWinNTSystem::GetGroupInfo(const char *group)
03606 {
03607
03608
03609
03610
03611
03612
03613 return GetGroupInfo(GetGid(group));
03614 }
03615
03616
03617
03618
03619 void TWinNTSystem::Setenv(const char *name, const char *value)
03620 {
03621
03622
03623 ::_putenv(Form("%s=%s", name, value));
03624 }
03625
03626
03627 const char *TWinNTSystem::Getenv(const char *name)
03628 {
03629
03630
03631 const char *env = ::getenv(name);
03632 if (!env) {
03633 if (::_stricmp(name,"home") == 0 ) {
03634 env = HomeDirectory();
03635 } else if (::_stricmp(name, "rootsys") == 0 ) {
03636 env = gRootDir;
03637 }
03638 }
03639 return env;
03640 }
03641
03642
03643
03644
03645 int TWinNTSystem::Exec(const char *shellcmd)
03646 {
03647
03648
03649 return ::system(shellcmd);
03650 }
03651
03652
03653 FILE *TWinNTSystem::OpenPipe(const char *command, const char *mode)
03654 {
03655
03656
03657 return ::_popen(command, mode);
03658 }
03659
03660
03661 int TWinNTSystem::ClosePipe(FILE *pipe)
03662 {
03663
03664
03665 return ::_pclose(pipe);
03666 }
03667
03668
03669 int TWinNTSystem::GetPid()
03670 {
03671
03672
03673 return ::getpid();
03674 }
03675
03676
03677 HANDLE TWinNTSystem::GetProcess()
03678 {
03679
03680
03681 return fhProcess;
03682 }
03683
03684
03685 void TWinNTSystem::Exit(int code, Bool_t mode)
03686 {
03687
03688
03689
03690 if (gROOT) {
03691 if (gROOT->GetListOfFiles()) gROOT->GetListOfFiles()->Delete("slow");
03692 if (gROOT->GetListOfSockets()) gROOT->GetListOfSockets()->Delete();
03693 if (gROOT->GetListOfMappedFiles()) gROOT->GetListOfMappedFiles()->Delete("slow");
03694 if (gROOT->GetListOfBrowsers()) gROOT->GetListOfBrowsers()->Delete();
03695 }
03696 gVirtualX->CloseDisplay();
03697
03698 if (mode) {
03699 ::exit(code);
03700 } else {
03701 ::_exit(code);
03702 }
03703 }
03704
03705
03706 void TWinNTSystem::Abort(int)
03707 {
03708
03709
03710 ::abort();
03711 }
03712
03713
03714
03715
03716 Int_t TWinNTSystem::RedirectOutput(const char *file, const char *mode,
03717 RedirectHandle_t *h)
03718 {
03719
03720
03721
03722
03723
03724
03725
03726
03727
03728
03729
03730
03731 static RedirectHandle_t loch;
03732 Int_t rc = 0;
03733
03734
03735 RedirectHandle_t *xh = (h) ? h : &loch;
03736
03737 if (file) {
03738
03739 const char *m = (mode[0] == 'a' || mode[0] == 'w') ? mode : "a";
03740
03741
03742 xh->fReadOffSet = 0;
03743 if (m[0] == 'a') {
03744
03745 FileStat_t st;
03746 if (!gSystem->GetPathInfo(file, st))
03747 xh->fReadOffSet = (st.fSize > 0) ? st.fSize : xh->fReadOffSet;
03748 }
03749 xh->fFile = file;
03750
03751
03752 if (freopen(file, m, stdout) == 0) {
03753 SysError("RedirectOutput", "could not freopen stdout");
03754 return -1;
03755 }
03756 if (freopen(file, m, stderr) == 0) {
03757 SysError("RedirectOutput", "could not freopen stderr");
03758 freopen("CONOUT$", "a", stdout);
03759 return -1;
03760 }
03761 } else {
03762
03763 fflush(stdout);
03764 if (freopen("CONOUT$", "a", stdout) == 0) {
03765 SysError("RedirectOutput", "could not restore stdout");
03766 rc = -1;
03767 }
03768 fflush(stderr);
03769 if (freopen("CONOUT$", "a", stderr) == 0) {
03770 SysError("RedirectOutput", "could not restore stderr");
03771 rc = -1;
03772 }
03773
03774 if (xh == &loch)
03775 xh->Reset();
03776 }
03777 return rc;
03778 }
03779
03780
03781
03782
03783 void TWinNTSystem::AddDynamicPath(const char *dir)
03784 {
03785
03786
03787 if (dir) {
03788 TString oldpath = DynamicPath(0, kFALSE);
03789 oldpath.Append(";");
03790 oldpath.Append(dir);
03791 DynamicPath(oldpath);
03792 }
03793 }
03794
03795
03796 const char* TWinNTSystem::GetDynamicPath()
03797 {
03798
03799
03800 return DynamicPath(0, kFALSE);
03801 }
03802
03803
03804 void TWinNTSystem::SetDynamicPath(const char *path)
03805 {
03806
03807
03808
03809
03810 if (!path)
03811 DynamicPath(0, kTRUE);
03812 else
03813 DynamicPath(path);
03814 }
03815
03816
03817 char *TWinNTSystem::DynamicPathName(const char *lib, Bool_t quiet)
03818 {
03819
03820
03821
03822
03823 char *name;
03824
03825 int len = strlen(lib);
03826 if (len > 4 && (!stricmp(lib+len-4, ".dll"))) {
03827 name = gSystem->Which(GetDynamicPath(), lib, kReadPermission);
03828 } else {
03829 name = Form("%s.dll", lib);
03830 name = gSystem->Which(GetDynamicPath(), name, kReadPermission);
03831 }
03832
03833 if (!name && !quiet) {
03834 Error("DynamicPathName",
03835 "%s does not exist in %s,\nor has wrong file extension (.dll)", lib,
03836 GetDynamicPath());
03837 }
03838 return name;
03839 }
03840
03841
03842 int TWinNTSystem::Load(const char *module, const char *entry, Bool_t system)
03843 {
03844
03845
03846
03847 return TSystem::Load(module, entry, system);
03848 }
03849
03850
03851 #pragma warning(push)
03852 #pragma warning(disable:4200)
03853
03854 const char *TWinNTSystem::GetLinkedLibraries()
03855 {
03856
03857
03858 char winDrive[256];
03859 char winDir[256];
03860 char winName[256];
03861 char winExt[256];
03862
03863 if (!gApplication) return 0;
03864
03865 static Bool_t once = kFALSE;
03866 static TString linkedLibs;
03867
03868 if (!linkedLibs.IsNull())
03869 return linkedLibs;
03870
03871 if (once)
03872 return 0;
03873
03874 char *exe = gSystem->Which(Getenv("PATH"), gApplication->Argv(0),
03875 kExecutePermission);
03876 if (!exe) {
03877 once = kTRUE;
03878 return 0;
03879 }
03880
03881 HANDLE hFile, hMapping;
03882 void *basepointer;
03883
03884 if((hFile = CreateFile(exe,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_FLAG_SEQUENTIAL_SCAN,0))==INVALID_HANDLE_VALUE) {
03885 delete [] exe;
03886 return 0;
03887 }
03888 if(!(hMapping = CreateFileMapping(hFile,0,PAGE_READONLY|SEC_COMMIT,0,0,0))) {
03889 CloseHandle(hFile);
03890 delete [] exe;
03891 return 0;
03892 }
03893 if(!(basepointer = MapViewOfFile(hMapping,FILE_MAP_READ,0,0,0))) {
03894 CloseHandle(hMapping);
03895 CloseHandle(hFile);
03896 delete [] exe;
03897 return 0;
03898 }
03899
03900 int sect;
03901 IMAGE_DOS_HEADER *dos_head = (IMAGE_DOS_HEADER *)basepointer;
03902 struct header {
03903 DWORD signature;
03904 IMAGE_FILE_HEADER _head;
03905 IMAGE_OPTIONAL_HEADER opt_head;
03906 IMAGE_SECTION_HEADER section_header[];
03907 };
03908 struct header *pheader;
03909 const IMAGE_SECTION_HEADER * section_header;
03910
03911 if(dos_head->e_magic!='ZM') {
03912 delete [] exe;
03913 return 0;
03914 }
03915
03916 pheader = (struct header *)((char*)dos_head + dos_head->e_lfanew);
03917
03918 if(IsBadReadPtr(pheader,sizeof(struct header))) {
03919 delete [] exe;
03920 return 0;
03921 }
03922 if(pheader->signature!=IMAGE_NT_SIGNATURE) {
03923 switch((unsigned short)pheader->signature) {
03924 case IMAGE_DOS_SIGNATURE:
03925 delete [] exe;
03926 return 0;
03927 case IMAGE_OS2_SIGNATURE:
03928 delete [] exe;
03929 return 0;
03930 case IMAGE_OS2_SIGNATURE_LE:
03931 delete [] exe;
03932 return 0;
03933 default:
03934 delete [] exe;
03935 return 0;
03936 }
03937 }
03938 #define isin(address,start,length) ((address)>=(start) && (address)<(start)+(length))
03939 TString odump;
03940
03941 for(sect=0,section_header=pheader->section_header;
03942 sect<pheader->_head.NumberOfSections;sect++,section_header++) {
03943 int directory;
03944 const void * const section_data =
03945 (char*)basepointer + section_header->PointerToRawData;
03946 for(directory=0;directory<IMAGE_NUMBEROF_DIRECTORY_ENTRIES;directory++) {
03947 if(isin(pheader->opt_head.DataDirectory[directory].VirtualAddress,
03948 section_header->VirtualAddress,
03949 section_header->SizeOfRawData)) {
03950 const IMAGE_IMPORT_DESCRIPTOR *stuff_start =
03951 (IMAGE_IMPORT_DESCRIPTOR *)((char*)section_data +
03952 (pheader->opt_head.DataDirectory[directory].VirtualAddress -
03953 section_header->VirtualAddress));
03954
03955
03956 const unsigned stuff_length =
03957 pheader->opt_head.DataDirectory[directory].Size;
03958 if(directory == IMAGE_DIRECTORY_ENTRY_IMPORT) {
03959 while(!IsBadReadPtr(stuff_start,sizeof(*stuff_start)) &&
03960 stuff_start->Name) {
03961 TString dll = (char*)section_data +
03962 ((DWORD)(stuff_start->Name)) -
03963 section_header->VirtualAddress;
03964 if (dll.EndsWith(".dll")) {
03965 char *dllPath = DynamicPathName(dll, kTRUE);
03966 if (dllPath) {
03967 char *winPath = getenv("windir");
03968 _splitpath(winPath,winDrive,winDir,winName,winExt);
03969 if(!strstr(dllPath, winDir)) {
03970 if (!linkedLibs.IsNull())
03971 linkedLibs += " ";
03972 linkedLibs += dllPath;
03973 }
03974 }
03975 delete [] dllPath;
03976 }
03977 stuff_start++;
03978 }
03979 }
03980 }
03981 }
03982 }
03983
03984 UnmapViewOfFile(basepointer);
03985 CloseHandle(hMapping);
03986 CloseHandle(hFile);
03987
03988 delete [] exe;
03989
03990 once = kTRUE;
03991
03992 if (linkedLibs.IsNull())
03993 return 0;
03994
03995 return linkedLibs;
03996 }
03997 #pragma warning(pop)
03998
03999
04000 const char *TWinNTSystem::GetLibraries(const char *regexp, const char *options,
04001 Bool_t isRegexp)
04002 {
04003
04004
04005
04006
04007
04008
04009
04010
04011
04012
04013 TString libs(TSystem::GetLibraries(regexp, options, isRegexp));
04014 TString ntlibs;
04015 TString opt = options;
04016
04017 if ( (opt.First('L')!=kNPOS) ) {
04018 TRegexp separator("[^ \\t\\s]+");
04019 TRegexp user_dll("\\.dll$");
04020 TRegexp user_lib("\\.lib$");
04021 FileStat_t sbuf;
04022 TString s;
04023 Ssiz_t start, index, end;
04024 start = index = end = 0;
04025
04026 while ((start < libs.Length()) && (index != kNPOS)) {
04027 index = libs.Index(separator, &end, start);
04028 if (index >= 0) {
04029
04030
04031 s = libs(index, end);
04032 if (s.Index(user_dll) != kNPOS) {
04033 s.ReplaceAll(".dll",".lib");
04034 if ( GetPathInfo( s, sbuf ) != 0 ) {
04035 s.Replace( 0, s.Last('/')+1, 0, 0);
04036 s.Replace( 0, s.Last('\\')+1, 0, 0);
04037 }
04038 } else if (s.Index(user_lib) != kNPOS) {
04039 if ( GetPathInfo( s, sbuf ) != 0 ) {
04040 s.Replace( 0, s.Last('/')+1, 0, 0);
04041 s.Replace( 0, s.Last('\\')+1, 0, 0);
04042 }
04043 }
04044 if (!ntlibs.IsNull()) ntlibs.Append(" ");
04045 ntlibs.Append(s);
04046 }
04047 start += end+1;
04048 }
04049 } else {
04050 ntlibs = libs;
04051 }
04052
04053 fListLibs = ntlibs;
04054 fListLibs.ReplaceAll("/","\\");
04055 return fListLibs;
04056 }
04057
04058
04059
04060
04061 void TWinNTSystem::AddTimer(TTimer *ti)
04062 {
04063
04064
04065 TSystem::AddTimer(ti);
04066 }
04067
04068
04069 TTimer *TWinNTSystem::RemoveTimer(TTimer *ti)
04070 {
04071
04072
04073 if (!ti) return 0;
04074
04075 TTimer *t = TSystem::RemoveTimer(ti);
04076 return t;
04077 }
04078
04079
04080 void TWinNTSystem::TimerThread()
04081 {
04082
04083
04084 while (1) {
04085 if (!fInsideNotify)
04086 DispatchTimers(kFALSE);
04087 ::Sleep(kItimerResolution/2);
04088 }
04089 }
04090
04091
04092 Bool_t TWinNTSystem::DispatchTimers(Bool_t mode)
04093 {
04094
04095
04096
04097 if (!fTimers) return kFALSE;
04098
04099 fInsideNotify = kTRUE;
04100
04101 TOrdCollectionIter it((TOrdCollection*)fTimers);
04102 TTimer *t;
04103 Bool_t timedout = kFALSE;
04104
04105 while ((t = (TTimer *) it.Next())) {
04106
04107 TTime now = Now();
04108 if (mode && t->IsSync()) {
04109 if (t->CheckTimer(now)) {
04110 timedout = kTRUE;
04111 }
04112 } else if (!mode && t->IsAsync()) {
04113 if (t->CheckTimer(now)) {
04114 timedout = kTRUE;
04115 }
04116 }
04117 }
04118 fInsideNotify = kFALSE;
04119
04120 return timedout;
04121 }
04122
04123 const Double_t gTicks = 1.0e-7;
04124
04125 Double_t TWinNTSystem::GetRealTime()
04126 {
04127
04128
04129 union {
04130 FILETIME ftFileTime;
04131 __int64 ftInt64;
04132 } ftRealTime;
04133
04134 ::GetSystemTimeAsFileTime(&ftRealTime.ftFileTime);
04135 return (Double_t)ftRealTime.ftInt64 * gTicks;
04136 }
04137
04138
04139 Double_t TWinNTSystem::GetCPUTime()
04140 {
04141
04142
04143 OSVERSIONINFO OsVersionInfo;
04144
04145
04146
04147
04148
04149
04150
04151
04152 OsVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
04153 GetVersionEx(&OsVersionInfo);
04154 if (OsVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) {
04155 DWORD ret;
04156 FILETIME ftCreate,
04157 ftExit;
04158
04159 union {
04160 FILETIME ftFileTime;
04161 __int64 ftInt64;
04162 } ftKernel;
04163
04164 union {
04165 FILETIME ftFileTime;
04166 __int64 ftInt64;
04167 } ftUser;
04168
04169 HANDLE hThread = GetCurrentThread();
04170 ret = GetThreadTimes (hThread, &ftCreate, &ftExit,
04171 &ftKernel.ftFileTime,
04172 &ftUser.ftFileTime);
04173 if (ret != TRUE){
04174 ret = ::GetLastError();
04175 ::Error("GetCPUTime", " Error on GetProcessTimes 0x%lx", (int)ret);
04176 }
04177
04178
04179
04180
04181
04182
04183
04184 return (Double_t) (ftKernel.ftInt64 + ftUser.ftInt64) * gTicks;
04185 } else {
04186 return GetRealTime();
04187 }
04188 }
04189
04190
04191 TTime TWinNTSystem::Now()
04192 {
04193
04194
04195 static time_t jan95 = 0;
04196 if (!jan95) {
04197 struct tm tp;
04198 tp.tm_year = 95;
04199 tp.tm_mon = 0;
04200 tp.tm_mday = 1;
04201 tp.tm_hour = 0;
04202 tp.tm_min = 0;
04203 tp.tm_sec = 0;
04204 tp.tm_isdst = -1;
04205
04206 jan95 = mktime(&tp);
04207 if ((int)jan95 == -1) {
04208 ::SysError("TWinNTSystem::Now", "error converting 950001 0:00 to time_t");
04209 return 0;
04210 }
04211 }
04212
04213 _timeb now;
04214 _ftime(&now);
04215 return TTime((now.time-(Long_t)jan95)*1000 + now.millitm);
04216 }
04217
04218
04219 void TWinNTSystem::Sleep(UInt_t milliSec)
04220 {
04221
04222
04223
04224
04225 ::Sleep(milliSec);
04226 }
04227
04228
04229 Int_t TWinNTSystem::Select(TList *act, Long_t to)
04230 {
04231
04232 Int_t rc = -4;
04233
04234 TFdSet rd, wr;
04235 Int_t mxfd = -1;
04236 TIter next(act);
04237 TFileHandler *h = 0;
04238 while ((h = (TFileHandler *) next())) {
04239 Int_t fd = h->GetFd();
04240 if (h->HasReadInterest())
04241 rd.Set(fd);
04242 if (h->HasWriteInterest())
04243 wr.Set(fd);
04244 h->ResetReadyMask();
04245 }
04246 rc = WinNTSelect(&rd, &wr, to);
04247
04248
04249 if (rc > 0) {
04250 next.Reset();
04251 while ((h = (TFileHandler *) next())) {
04252 Int_t fd = h->GetFd();
04253 if (rd.IsSet(fd))
04254 h->SetReadReady();
04255 if (wr.IsSet(fd))
04256 h->SetWriteReady();
04257 }
04258 }
04259
04260 return rc;
04261 }
04262
04263
04264 Int_t TWinNTSystem::Select(TFileHandler *h, Long_t to)
04265 {
04266
04267
04268 Int_t rc = -4;
04269
04270 TFdSet rd, wr;
04271 Int_t fd = -1;
04272 if (h) {
04273 fd = h->GetFd();
04274 if (h->HasReadInterest())
04275 rd.Set(fd);
04276 if (h->HasWriteInterest())
04277 wr.Set(fd);
04278 h->ResetReadyMask();
04279 rc = WinNTSelect(&rd, &wr, to);
04280 }
04281
04282
04283 if (rc > 0) {
04284 if (rd.IsSet(fd))
04285 h->SetReadReady();
04286 if (wr.IsSet(fd))
04287 h->SetWriteReady();
04288 }
04289
04290 return rc;
04291 }
04292
04293
04294
04295 int TWinNTSystem::GetServiceByName(const char *servicename)
04296 {
04297
04298
04299 struct servent *sp;
04300
04301 if ((sp = ::getservbyname(servicename, kProtocolName)) == 0) {
04302 Error("GetServiceByName", "no service \"%s\" with protocol \"%s\"\n",
04303 servicename, kProtocolName);
04304 return -1;
04305 }
04306 return ::ntohs(sp->s_port);
04307 }
04308
04309
04310 char *TWinNTSystem::GetServiceByPort(int port)
04311 {
04312
04313
04314
04315 struct servent *sp;
04316
04317 if ((sp = ::getservbyport(::htons(port), kProtocolName)) == 0) {
04318 return Form("%d", port);
04319 }
04320 return sp->s_name;
04321 }
04322
04323
04324 TInetAddress TWinNTSystem::GetHostByName(const char *hostname)
04325 {
04326
04327
04328 struct hostent *host_ptr;
04329 const char *host;
04330 int type;
04331 UInt_t addr;
04332
04333 if ((addr = ::inet_addr(hostname)) != INADDR_NONE) {
04334 type = AF_INET;
04335 if ((host_ptr = ::gethostbyaddr((const char *)&addr,
04336 sizeof(addr), AF_INET))) {
04337 host = host_ptr->h_name;
04338 TInetAddress a(host, ntohl(addr), type);
04339 UInt_t addr2;
04340 Int_t i;
04341 for (i = 1; host_ptr->h_addr_list[i]; i++) {
04342 memcpy(&addr2, host_ptr->h_addr_list[i], host_ptr->h_length);
04343 a.AddAddress(ntohl(addr2));
04344 }
04345 for (i = 0; host_ptr->h_aliases[i]; i++)
04346 a.AddAlias(host_ptr->h_aliases[i]);
04347 return a;
04348 } else {
04349 host = "UnNamedHost";
04350 }
04351 } else if ((host_ptr = ::gethostbyname(hostname))) {
04352
04353 if (host_ptr->h_addrtype != AF_INET) {
04354 Error("GetHostByName", "%s is not an internet host\n", hostname);
04355 return TInetAddress();
04356 }
04357 memcpy(&addr, host_ptr->h_addr, host_ptr->h_length);
04358 host = host_ptr->h_name;
04359 type = host_ptr->h_addrtype;
04360 TInetAddress a(host, ntohl(addr), type);
04361 UInt_t addr2;
04362 Int_t i;
04363 for (i = 1; host_ptr->h_addr_list[i]; i++) {
04364 memcpy(&addr2, host_ptr->h_addr_list[i], host_ptr->h_length);
04365 a.AddAddress(ntohl(addr2));
04366 }
04367 for (i = 0; host_ptr->h_aliases[i]; i++)
04368 a.AddAlias(host_ptr->h_aliases[i]);
04369 return a;
04370 } else {
04371 if (gDebug > 0) Error("GetHostByName", "unknown host %s", hostname);
04372 return TInetAddress(hostname, 0, -1);
04373 }
04374
04375 return TInetAddress(host, ::ntohl(addr), type);
04376 }
04377
04378
04379 TInetAddress TWinNTSystem::GetPeerName(int socket)
04380 {
04381
04382
04383 SOCKET sock = socket;
04384 struct sockaddr_in addr;
04385 int len = sizeof(addr);
04386
04387 if (::getpeername(sock, (struct sockaddr *)&addr, &len) == SOCKET_ERROR) {
04388 ::SysError("GetPeerName", "getpeername");
04389 return TInetAddress();
04390 }
04391
04392 struct hostent *host_ptr;
04393 const char *hostname;
04394 int family;
04395 UInt_t iaddr;
04396
04397 if ((host_ptr = ::gethostbyaddr((const char *)&addr.sin_addr,
04398 sizeof(addr.sin_addr), AF_INET))) {
04399 memcpy(&iaddr, host_ptr->h_addr, host_ptr->h_length);
04400 hostname = host_ptr->h_name;
04401 family = host_ptr->h_addrtype;
04402 } else {
04403 memcpy(&iaddr, &addr.sin_addr, sizeof(addr.sin_addr));
04404 hostname = "????";
04405 family = AF_INET;
04406 }
04407
04408 return TInetAddress(hostname, ::ntohl(iaddr), family, ::ntohs(addr.sin_port));
04409 }
04410
04411
04412 TInetAddress TWinNTSystem::GetSockName(int socket)
04413 {
04414
04415
04416 SOCKET sock = socket;
04417 struct sockaddr_in addr;
04418 int len = sizeof(addr);
04419
04420 if (::getsockname(sock, (struct sockaddr *)&addr, &len) == SOCKET_ERROR) {
04421 ::SysError("GetSockName", "getsockname");
04422 return TInetAddress();
04423 }
04424
04425 struct hostent *host_ptr;
04426 const char *hostname;
04427 int family;
04428 UInt_t iaddr;
04429
04430 if ((host_ptr = ::gethostbyaddr((const char *)&addr.sin_addr,
04431 sizeof(addr.sin_addr), AF_INET))) {
04432 memcpy(&iaddr, host_ptr->h_addr, host_ptr->h_length);
04433 hostname = host_ptr->h_name;
04434 family = host_ptr->h_addrtype;
04435 } else {
04436 memcpy(&iaddr, &addr.sin_addr, sizeof(addr.sin_addr));
04437 hostname = "????";
04438 family = AF_INET;
04439 }
04440
04441 return TInetAddress(hostname, ::ntohl(iaddr), family, ::ntohs(addr.sin_port));
04442 }
04443
04444
04445 int TWinNTSystem::AnnounceUnixService(int port, int backlog)
04446 {
04447
04448
04449 SOCKET sock;
04450
04451
04452 if ((sock = ::socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
04453 ::SysError("TWinNTSystem::AnnounceUnixService", "socket");
04454 return -1;
04455 }
04456
04457 struct sockaddr_in inserver;
04458 memset(&inserver, 0, sizeof(inserver));
04459 inserver.sin_family = AF_INET;
04460 inserver.sin_addr.s_addr = ::htonl(INADDR_LOOPBACK);
04461 inserver.sin_port = port;
04462
04463
04464 if (port > 0) {
04465 if (::bind(sock, (struct sockaddr*) &inserver, sizeof(inserver)) == SOCKET_ERROR) {
04466 ::SysError("TWinNTSystem::AnnounceUnixService", "bind");
04467 return -2;
04468 }
04469 }
04470
04471 if (::listen(sock, backlog)) {
04472 ::SysError("TWinNTSystem::AnnounceUnixService", "listen");
04473 return -1;
04474 }
04475 return (int)sock;
04476 }
04477
04478
04479 int TWinNTSystem::AnnounceUnixService(const char *sockpath, int backlog)
04480 {
04481
04482
04483
04484 if (!sockpath || strlen(sockpath) <= 0) {
04485 ::SysError("TWinNTSystem::AnnounceUnixService", "socket path undefined");
04486 return -1;
04487 }
04488
04489 struct sockaddr_in myaddr;
04490 FILE * fp;
04491 int len = sizeof myaddr;
04492 int rc;
04493 int sock;
04494
04495
04496 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
04497 ::SysError("TWinNTSystem::AnnounceUnixService", "socket");
04498 return -1;
04499 }
04500
04501 memset(&myaddr, 0, sizeof(myaddr));
04502 myaddr.sin_port = 0;
04503 myaddr.sin_family = AF_INET;
04504 myaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
04505
04506 rc = bind(sock, (struct sockaddr *)&myaddr, len);
04507 if (rc) {
04508 ::SysError("TWinNTSystem::AnnounceUnixService", "bind");
04509 return rc;
04510 }
04511 rc = getsockname(sock, (struct sockaddr *)&myaddr, &len);
04512 if (rc) {
04513 ::SysError("TWinNTSystem::AnnounceUnixService", "getsockname");
04514 return rc;
04515 }
04516 TString socketpath = sockpath;
04517 socketpath.ReplaceAll("/", "\\");
04518 fp = fopen(socketpath, "wb");
04519 if (!fp) {
04520 ::SysError("TWinNTSystem::AnnounceUnixService", "fopen");
04521 return -1;
04522 }
04523 fprintf(fp, "%d", myaddr.sin_port);
04524 fclose(fp);
04525
04526
04527 if (listen(sock, backlog)) {
04528 ::SysError("TWinNTSystem::AnnounceUnixService", "listen");
04529 return -1;
04530 }
04531
04532 return sock;
04533 }
04534
04535
04536 void TWinNTSystem::CloseConnection(int socket, Bool_t force)
04537 {
04538
04539
04540 if (socket == -1) return;
04541 SOCKET sock = socket;
04542
04543 if (force) {
04544 ::shutdown(sock, 2);
04545 }
04546 struct linger linger = {0, 0};
04547 ::setsockopt(sock, SOL_SOCKET, SO_LINGER, (char *) &linger, sizeof(linger));
04548 while (::closesocket(sock) == SOCKET_ERROR && WSAGetLastError() == WSAEINTR) {
04549 TSystem::ResetErrno();
04550 }
04551 }
04552
04553
04554 int TWinNTSystem::RecvBuf(int sock, void *buf, int length)
04555 {
04556
04557
04558
04559
04560 Int_t header;
04561
04562 if (WinNTRecv(sock, &header, sizeof(header), 0) > 0) {
04563 int count = ::ntohl(header);
04564
04565 if (count > length) {
04566 Error("RecvBuf", "record header exceeds buffer size");
04567 return -1;
04568 } else if (count > 0) {
04569 if (WinNTRecv(sock, buf, count, 0) < 0) {
04570 Error("RecvBuf", "cannot receive buffer");
04571 return -1;
04572 }
04573 }
04574 return count;
04575 }
04576 return -1;
04577 }
04578
04579
04580 int TWinNTSystem::SendBuf(int sock, const void *buf, int length)
04581 {
04582
04583
04584
04585 Int_t header = ::htonl(length);
04586
04587 if (WinNTSend(sock, &header, sizeof(header), 0) < 0) {
04588 Error("SendBuf", "cannot send header");
04589 return -1;
04590 }
04591 if (length > 0) {
04592 if (WinNTSend(sock, buf, length, 0) < 0) {
04593 Error("SendBuf", "cannot send buffer");
04594 return -1;
04595 }
04596 }
04597 return length;
04598 }
04599
04600
04601 int TWinNTSystem::RecvRaw(int sock, void *buf, int length, int opt)
04602 {
04603
04604
04605
04606
04607
04608
04609
04610
04611
04612 int flag;
04613
04614 switch (opt) {
04615 case kDefault:
04616 flag = 0;
04617 break;
04618 case kOob:
04619 flag = MSG_OOB;
04620 break;
04621 case kPeek:
04622 flag = MSG_PEEK;
04623 break;
04624 case kDontBlock:
04625 flag = -1;
04626 break;
04627 default:
04628 flag = 0;
04629 break;
04630 }
04631
04632 int n;
04633 if ((n = WinNTRecv(sock, buf, length, flag)) <= 0) {
04634 if (n == -1) {
04635 Error("RecvRaw", "cannot receive buffer");
04636 }
04637 return n;
04638 }
04639 return n;
04640 }
04641
04642
04643 int TWinNTSystem::SendRaw(int sock, const void *buf, int length, int opt)
04644 {
04645
04646
04647
04648
04649
04650 int flag;
04651
04652 switch (opt) {
04653 case kDefault:
04654 flag = 0;
04655 break;
04656 case kOob:
04657 flag = MSG_OOB;
04658 break;
04659 case kDontBlock:
04660 flag = -1;
04661 break;
04662 case kPeek:
04663 default:
04664 flag = 0;
04665 break;
04666 }
04667
04668 int n;
04669 if ((n = WinNTSend(sock, buf, length, flag)) <= 0) {
04670 if (n == -1 && GetErrno() != EINTR) {
04671 Error("SendRaw", "cannot send buffer");
04672 }
04673 return n;
04674 }
04675 return n;
04676 }
04677
04678
04679 int TWinNTSystem::SetSockOpt(int socket, int opt, int value)
04680 {
04681
04682
04683 u_long val = value;
04684 if (socket == -1) return -1;
04685 SOCKET sock = socket;
04686
04687 switch (opt) {
04688 case kSendBuffer:
04689 if (::setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char*)&val, sizeof(val)) == SOCKET_ERROR) {
04690 ::SysError("SetSockOpt", "setsockopt(SO_SNDBUF)");
04691 return -1;
04692 }
04693 break;
04694 case kRecvBuffer:
04695 if (::setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*)&val, sizeof(val)) == SOCKET_ERROR) {
04696 ::SysError("SetSockOpt", "setsockopt(SO_RCVBUF)");
04697 return -1;
04698 }
04699 break;
04700 case kOobInline:
04701 if (::setsockopt(sock, SOL_SOCKET, SO_OOBINLINE, (char*)&val, sizeof(val)) == SOCKET_ERROR) {
04702 SysError("SetSockOpt", "setsockopt(SO_OOBINLINE)");
04703 return -1;
04704 }
04705 break;
04706 case kKeepAlive:
04707 if (::setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char*)&val, sizeof(val)) == SOCKET_ERROR) {
04708 ::SysError("SetSockOpt", "setsockopt(SO_KEEPALIVE)");
04709 return -1;
04710 }
04711 break;
04712 case kReuseAddr:
04713 if (::setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&val, sizeof(val)) == SOCKET_ERROR) {
04714 ::SysError("SetSockOpt", "setsockopt(SO_REUSEADDR)");
04715 return -1;
04716 }
04717 break;
04718 case kNoDelay:
04719 if (::setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char*)&val, sizeof(val)) == SOCKET_ERROR) {
04720 ::SysError("SetSockOpt", "setsockopt(TCP_NODELAY)");
04721 return -1;
04722 }
04723 break;
04724 case kNoBlock:
04725 if (::ioctlsocket(sock, FIONBIO, &val) == SOCKET_ERROR) {
04726 ::SysError("SetSockOpt", "ioctl(FIONBIO)");
04727 return -1;
04728 }
04729 break;
04730 #if 0
04731 case kProcessGroup:
04732 if (::ioctl(sock, SIOCSPGRP, &val) == -1) {
04733 ::SysError("SetSockOpt", "ioctl(SIOCSPGRP)");
04734 return -1;
04735 }
04736 break;
04737 #endif
04738 case kAtMark:
04739 case kBytesToRead:
04740 default:
04741 Error("SetSockOpt", "illegal option (%d)", opt);
04742 return -1;
04743 break;
04744 }
04745 return 0;
04746 }
04747
04748
04749 int TWinNTSystem::GetSockOpt(int socket, int opt, int *val)
04750 {
04751
04752
04753 if (socket == -1) return -1;
04754 SOCKET sock = socket;
04755
04756 int optlen = sizeof(*val);
04757
04758 switch (opt) {
04759 case kSendBuffer:
04760 if (::getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char*)val, &optlen) == SOCKET_ERROR) {
04761 ::SysError("GetSockOpt", "getsockopt(SO_SNDBUF)");
04762 return -1;
04763 }
04764 break;
04765 case kRecvBuffer:
04766 if (::getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*)val, &optlen) == SOCKET_ERROR) {
04767 ::SysError("GetSockOpt", "getsockopt(SO_RCVBUF)");
04768 return -1;
04769 }
04770 break;
04771 case kOobInline:
04772 if (::getsockopt(sock, SOL_SOCKET, SO_OOBINLINE, (char*)val, &optlen) == SOCKET_ERROR) {
04773 ::SysError("GetSockOpt", "getsockopt(SO_OOBINLINE)");
04774 return -1;
04775 }
04776 break;
04777 case kKeepAlive:
04778 if (::getsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char*)val, &optlen) == SOCKET_ERROR) {
04779 ::SysError("GetSockOpt", "getsockopt(SO_KEEPALIVE)");
04780 return -1;
04781 }
04782 break;
04783 case kReuseAddr:
04784 if (::getsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)val, &optlen) == SOCKET_ERROR) {
04785 ::SysError("GetSockOpt", "getsockopt(SO_REUSEADDR)");
04786 return -1;
04787 }
04788 break;
04789 case kNoDelay:
04790 if (::getsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char*)val, &optlen) == SOCKET_ERROR) {
04791 ::SysError("GetSockOpt", "getsockopt(TCP_NODELAY)");
04792 return -1;
04793 }
04794 break;
04795 case kNoBlock:
04796 {
04797 int flg = 0;
04798 if (sock == INVALID_SOCKET) {
04799 ::SysError("GetSockOpt", "INVALID_SOCKET");
04800 }
04801 return -1;
04802 *val = flg;
04803 }
04804 break;
04805 #if 0
04806 case kProcessGroup:
04807 if (::ioctlsocket(sock, SIOCGPGRP, (u_long*)val) == SOCKET_ERROR) {
04808 ::SysError("GetSockOpt", "ioctl(SIOCGPGRP)");
04809 return -1;
04810 }
04811 break;
04812 #endif
04813 case kAtMark:
04814 if (::ioctlsocket(sock, SIOCATMARK, (u_long*)val) == SOCKET_ERROR) {
04815 ::SysError("GetSockOpt", "ioctl(SIOCATMARK)");
04816 return -1;
04817 }
04818 break;
04819 case kBytesToRead:
04820 if (::ioctlsocket(sock, FIONREAD, (u_long*)val) == SOCKET_ERROR) {
04821 ::SysError("GetSockOpt", "ioctl(FIONREAD)");
04822 return -1;
04823 }
04824 break;
04825 default:
04826 Error("GetSockOpt", "illegal option (%d)", opt);
04827 *val = 0;
04828 return -1;
04829 break;
04830 }
04831 return 0;
04832 }
04833
04834
04835 int TWinNTSystem::ConnectService(const char *servername, int port,
04836 int tcpwindowsize)
04837 {
04838
04839
04840 short sport;
04841 struct servent *sp;
04842
04843 if (!strcmp(servername, "unix")) {
04844 return WinNTUnixConnect(port);
04845 }
04846 else if (!gSystem->AccessPathName(servername) || servername[0] == '/' ||
04847 (servername[1] == ':' && servername[2] == '/')) {
04848 return WinNTUnixConnect(servername);
04849 }
04850
04851 if ((sp = ::getservbyport(::htons(port), kProtocolName))) {
04852 sport = sp->s_port;
04853 } else {
04854 sport = ::htons(port);
04855 }
04856
04857 TInetAddress addr = gSystem->GetHostByName(servername);
04858 if (!addr.IsValid()) return -1;
04859 UInt_t adr = ::htonl(addr.GetAddress());
04860
04861 struct sockaddr_in server;
04862 memset(&server, 0, sizeof(server));
04863 memcpy(&server.sin_addr, &adr, sizeof(adr));
04864 server.sin_family = addr.GetFamily();
04865 server.sin_port = sport;
04866
04867
04868 SOCKET sock;
04869 if ((sock = ::socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
04870 ::SysError("TWinNTSystem::WinNTConnectTcp", "socket");
04871 return -1;
04872 }
04873
04874 if (tcpwindowsize > 0) {
04875 gSystem->SetSockOpt((int)sock, kRecvBuffer, tcpwindowsize);
04876 gSystem->SetSockOpt((int)sock, kSendBuffer, tcpwindowsize);
04877 }
04878
04879 if (::connect(sock, (struct sockaddr*) &server, sizeof(server)) == INVALID_SOCKET) {
04880
04881 ::closesocket(sock);
04882 return -1;
04883 }
04884 return (int) sock;
04885 }
04886
04887
04888 int TWinNTSystem::WinNTUnixConnect(int port)
04889 {
04890
04891
04892 struct sockaddr_in myaddr;
04893 int sock;
04894
04895 memset(&myaddr, 0, sizeof(myaddr));
04896 myaddr.sin_family = AF_INET;
04897 myaddr.sin_port = port;
04898 myaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
04899
04900
04901 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
04902 ::SysError("TWinNTSystem::WinNTUnixConnect", "socket");
04903 return -1;
04904 }
04905
04906 while ((connect(sock, (struct sockaddr *)&myaddr, sizeof myaddr)) == -1) {
04907 if (GetErrno() == EINTR)
04908 ResetErrno();
04909 else {
04910 ::SysError("TWinNTSystem::WinNTUnixConnect", "connect");
04911 close(sock);
04912 return -1;
04913 }
04914 }
04915 return sock;
04916 }
04917
04918
04919 int TWinNTSystem::WinNTUnixConnect(const char *sockpath)
04920 {
04921
04922
04923 FILE *fp;
04924 int port = 0;
04925
04926 if (!sockpath || strlen(sockpath) <= 0) {
04927 ::SysError("TWinNTSystem::WinNTUnixConnect", "socket path undefined");
04928 return -1;
04929 }
04930 TString socketpath = sockpath;
04931 socketpath.ReplaceAll("/", "\\");
04932 fp = fopen(socketpath.Data(), "rb");
04933 if (!fp) {
04934 ::SysError("TWinNTSystem::WinNTUnixConnect", "fopen");
04935 return -1;
04936 }
04937 fscanf(fp, "%d", &port);
04938 fclose(fp);
04939
04940 if (port < 0 || port > 65535) {
04941 ::SysError("TWinNTSystem::WinNTUnixConnect", "invalid port");
04942 return -1;
04943 }
04944 return WinNTUnixConnect(port);
04945 }
04946
04947
04948
04949 int TWinNTSystem::OpenConnection(const char *server, int port, int tcpwindowsize)
04950 {
04951
04952
04953
04954
04955
04956
04957
04958 return ConnectService(server, port, tcpwindowsize);
04959 }
04960
04961
04962 int TWinNTSystem::AnnounceTcpService(int port, Bool_t reuse, int backlog,
04963 int tcpwindowsize)
04964 {
04965
04966
04967
04968
04969
04970
04971
04972
04973
04974
04975 short sport;
04976 struct servent *sp;
04977 const short kSOCKET_MINPORT = 5000, kSOCKET_MAXPORT = 15000;
04978 short tryport = kSOCKET_MINPORT;
04979
04980 if ((sp = ::getservbyport(::htons(port), kProtocolName))) {
04981 sport = sp->s_port;
04982 } else {
04983 sport = ::htons(port);
04984 }
04985
04986 if (port == 0 && reuse) {
04987 ::Error("TWinNTSystem::WinNTTcpService", "cannot do a port scan while reuse is true");
04988 return -1;
04989 }
04990
04991 if ((sp = ::getservbyport(::htons(port), kProtocolName))) {
04992 sport = sp->s_port;
04993 } else {
04994 sport = ::htons(port);
04995 }
04996
04997
04998 SOCKET sock;
04999 if ((sock = ::socket(AF_INET, SOCK_STREAM, 0)) < 0) {
05000 ::SysError("TWinNTSystem::WinNTTcpService", "socket");
05001 return -1;
05002 }
05003
05004 if (reuse) {
05005 gSystem->SetSockOpt((int)sock, kReuseAddr, 1);
05006 }
05007
05008 if (tcpwindowsize > 0) {
05009 gSystem->SetSockOpt((int)sock, kRecvBuffer, tcpwindowsize);
05010 gSystem->SetSockOpt((int)sock, kSendBuffer, tcpwindowsize);
05011 }
05012
05013 struct sockaddr_in inserver;
05014 memset(&inserver, 0, sizeof(inserver));
05015 inserver.sin_family = AF_INET;
05016 inserver.sin_addr.s_addr = ::htonl(INADDR_ANY);
05017 inserver.sin_port = sport;
05018
05019
05020 if (port > 0) {
05021 if (::bind(sock, (struct sockaddr*) &inserver, sizeof(inserver)) == SOCKET_ERROR) {
05022 ::SysError("TWinNTSystem::WinNTTcpService", "bind");
05023 return -2;
05024 }
05025 } else {
05026 int bret;
05027 do {
05028 inserver.sin_port = ::htons(tryport++);
05029 bret = ::bind(sock, (struct sockaddr*) &inserver, sizeof(inserver));
05030 } while (bret == SOCKET_ERROR && WSAGetLastError() == WSAEADDRINUSE &&
05031 tryport < kSOCKET_MAXPORT);
05032 if (bret == SOCKET_ERROR) {
05033 ::SysError("TWinNTSystem::WinNTTcpService", "bind (port scan)");
05034 return -2;
05035 }
05036 }
05037
05038
05039 if (::listen(sock, backlog) == SOCKET_ERROR) {
05040 ::SysError("TWinNTSystem::WinNTTcpService", "listen");
05041 return -3;
05042 }
05043 return (int)sock;
05044 }
05045
05046
05047 int TWinNTSystem::AcceptConnection(int socket)
05048 {
05049
05050
05051
05052
05053 int soc = -1;
05054 SOCKET sock = socket;
05055
05056 while ((soc = ::accept(sock, 0, 0)) == INVALID_SOCKET &&
05057 (::WSAGetLastError() == WSAEINTR)) {
05058 TSystem::ResetErrno();
05059 }
05060
05061 if (soc == -1) {
05062 if (::WSAGetLastError() == WSAEWOULDBLOCK) {
05063 return -2;
05064 } else {
05065 ::SysError("AcceptConnection", "accept");
05066 return -1;
05067 }
05068 }
05069 return soc;
05070 }
05071
05072
05073
05074
05075
05076 #define SystemBasicInformation 0
05077 #define SystemPerformanceInformation 2
05078
05079 typedef struct
05080 {
05081 DWORD dwUnknown1;
05082 ULONG uKeMaximumIncrement;
05083 ULONG uPageSize;
05084 ULONG uMmNumberOfPhysicalPages;
05085 ULONG uMmLowestPhysicalPage;
05086 ULONG UMmHighestPhysicalPage;
05087 ULONG uAllocationGranularity;
05088 PVOID pLowestUserAddress;
05089 PVOID pMmHighestUserAddress;
05090 ULONG uKeActiveProcessors;
05091 BYTE bKeNumberProcessors;
05092 BYTE bUnknown2;
05093 WORD bUnknown3;
05094 } SYSTEM_BASIC_INFORMATION;
05095
05096 typedef struct
05097 {
05098 LARGE_INTEGER liIdleTime;
05099 DWORD dwSpare[76];
05100 } SYSTEM_PERFORMANCE_INFORMATION;
05101
05102 typedef struct _PROCESS_MEMORY_COUNTERS {
05103 DWORD cb;
05104 DWORD PageFaultCount;
05105 SIZE_T PeakWorkingSetSize;
05106 SIZE_T WorkingSetSize;
05107 SIZE_T QuotaPeakPagedPoolUsage;
05108 SIZE_T QuotaPagedPoolUsage;
05109 SIZE_T QuotaPeakNonPagedPoolUsage;
05110 SIZE_T QuotaNonPagedPoolUsage;
05111 SIZE_T PagefileUsage;
05112 SIZE_T PeakPagefileUsage;
05113 } PROCESS_MEMORY_COUNTERS, *PPROCESS_MEMORY_COUNTERS;
05114
05115 typedef LONG (WINAPI *PROCNTQSI) (UINT, PVOID, ULONG, PULONG);
05116
05117 #define Li2Double(x) ((double)((x).HighPart) * 4.294967296E9 + (double)((x).LowPart))
05118
05119
05120 static DWORD GetCPUSpeed()
05121 {
05122
05123
05124
05125 LARGE_INTEGER ulFreq, ulTicks, ulValue, ulStartCounter, ulEAX_EDX;
05126
05127
05128
05129 if (QueryPerformanceFrequency(&ulFreq)) {
05130
05131 QueryPerformanceCounter(&ulTicks);
05132
05133
05134 ulValue.QuadPart = ulTicks.QuadPart + ulFreq.QuadPart/10;
05135
05136 __asm RDTSC
05137
05138 __asm mov ulEAX_EDX.LowPart, EAX
05139 __asm mov ulEAX_EDX.HighPart, EDX
05140
05141 ulStartCounter.QuadPart = ulEAX_EDX.QuadPart;
05142
05143 do {
05144 QueryPerformanceCounter(&ulTicks);
05145 } while (ulTicks.QuadPart <= ulValue.QuadPart);
05146
05147 __asm RDTSC
05148
05149 __asm mov ulEAX_EDX.LowPart, EAX
05150 __asm mov ulEAX_EDX.HighPart, EDX
05151
05152 return (DWORD)((ulEAX_EDX.QuadPart - ulStartCounter.QuadPart)/100000);
05153 } else {
05154
05155 return 0;
05156 }
05157 }
05158
05159 #define BUFSIZE 80
05160 #define SM_SERVERR2 89
05161 typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO);
05162
05163
05164 static char *GetWindowsVersion()
05165 {
05166 OSVERSIONINFOEX osvi;
05167 SYSTEM_INFO si;
05168 PGNSI pGNSI;
05169 BOOL bOsVersionInfoEx;
05170 static char *strReturn = 0;
05171 char temp[512];
05172
05173 if (strReturn == 0)
05174 strReturn = new char[2048];
05175 else
05176 return strReturn;
05177
05178 ZeroMemory(&si, sizeof(SYSTEM_INFO));
05179 ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
05180
05181
05182
05183
05184 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
05185
05186 if( !(bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi)) )
05187 {
05188 osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
05189 if (! GetVersionEx ( (OSVERSIONINFO *) &osvi) )
05190 return "";
05191 }
05192
05193
05194 pGNSI = (PGNSI) GetProcAddress( GetModuleHandle("kernel32.dll"),
05195 "GetNativeSystemInfo");
05196 if(NULL != pGNSI)
05197 pGNSI(&si);
05198 else GetSystemInfo(&si);
05199
05200 switch (osvi.dwPlatformId)
05201 {
05202
05203 case VER_PLATFORM_WIN32_NT:
05204
05205
05206 if ( osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 0 )
05207 {
05208 if( osvi.wProductType == VER_NT_WORKSTATION )
05209 strlcpy(strReturn, "Microsoft Windows Vista ",2048);
05210 else strlcpy(strReturn, "Windows Server \"Longhorn\" " ,2048);
05211 }
05212 if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2 )
05213 {
05214 if( GetSystemMetrics(SM_SERVERR2) )
05215 strlcpy(strReturn, "Microsoft Windows Server 2003 \"R2\" ",2048);
05216 else if( osvi.wProductType == VER_NT_WORKSTATION &&
05217 si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64)
05218 {
05219 strlcpy(strReturn, "Microsoft Windows XP Professional x64 Edition ",2048);
05220 }
05221 else strlcpy(strReturn, "Microsoft Windows Server 2003, ",2048);
05222 }
05223 if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1 )
05224 strlcpy(strReturn, "Microsoft Windows XP ",2048);
05225
05226 if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0 )
05227 strlcpy(strReturn, "Microsoft Windows 2000 ",2048);
05228
05229 if ( osvi.dwMajorVersion <= 4 )
05230 strlcpy(strReturn, "Microsoft Windows NT ",2048);
05231
05232
05233 if( bOsVersionInfoEx )
05234 {
05235
05236 if ( osvi.wProductType == VER_NT_WORKSTATION &&
05237 si.wProcessorArchitecture!=PROCESSOR_ARCHITECTURE_AMD64)
05238 {
05239 if( osvi.dwMajorVersion == 4 )
05240 strlcat(strReturn, "Workstation 4.0 ",2048 );
05241 else if( osvi.wSuiteMask & VER_SUITE_PERSONAL )
05242 strlcat(strReturn, "Home Edition " ,2048);
05243 else strlcat(strReturn, "Professional " ,2048);
05244 }
05245
05246 else if ( osvi.wProductType == VER_NT_SERVER ||
05247 osvi.wProductType == VER_NT_DOMAIN_CONTROLLER )
05248 {
05249 if(osvi.dwMajorVersion==5 && osvi.dwMinorVersion==2)
05250 {
05251 if ( si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_IA64 )
05252 {
05253 if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
05254 strlcat(strReturn, "Datacenter Edition for Itanium-based Systems",2048 );
05255 else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
05256 strlcat(strReturn, "Enterprise Edition for Itanium-based Systems" ,2048);
05257 }
05258 else if ( si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64 )
05259 {
05260 if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
05261 strlcat(strReturn, "Datacenter x64 Edition ",2048 );
05262 else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
05263 strlcat(strReturn, "Enterprise x64 Edition ",2048 );
05264 else strlcat(strReturn, "Standard x64 Edition ",2048 );
05265 }
05266 else
05267 {
05268 if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
05269 strlcat(strReturn, "Datacenter Edition ",2048 );
05270 else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
05271 strlcat(strReturn, "Enterprise Edition ",2048 );
05272 else if ( osvi.wSuiteMask == VER_SUITE_BLADE )
05273 strlcat(strReturn, "Web Edition " ,2048);
05274 else strlcat(strReturn, "Standard Edition ",2048 );
05275 }
05276 }
05277 else if(osvi.dwMajorVersion==5 && osvi.dwMinorVersion==0)
05278 {
05279 if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
05280 strlcat(strReturn, "Datacenter Server ",2048 );
05281 else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
05282 strlcat(strReturn, "Advanced Server ",2048 );
05283 else strlcat(strReturn, "Server ",2048 );
05284 }
05285 else
05286 {
05287 if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
05288 strlcat(strReturn, "Server 4.0, Enterprise Edition " ,2048);
05289 else strlcat(strReturn, "Server 4.0 ",2048 );
05290 }
05291 }
05292 }
05293
05294 else
05295 {
05296 HKEY hKey;
05297 TCHAR szProductType[BUFSIZE];
05298 DWORD dwBufLen=BUFSIZE*sizeof(TCHAR);
05299 LONG lRet;
05300
05301 lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
05302 "SYSTEM\\CurrentControlSet\\Control\\ProductOptions",
05303 0, KEY_QUERY_VALUE, &hKey );
05304 if( lRet != ERROR_SUCCESS )
05305 return "";
05306
05307 lRet = RegQueryValueEx( hKey, "ProductType", NULL, NULL,
05308 (LPBYTE) szProductType, &dwBufLen);
05309 RegCloseKey( hKey );
05310
05311 if( (lRet != ERROR_SUCCESS) || (dwBufLen > BUFSIZE*sizeof(TCHAR)) )
05312 return "";
05313
05314 if ( lstrcmpi( "WINNT", szProductType) == 0 )
05315 strlcat(strReturn, "Workstation " ,2048);
05316 if ( lstrcmpi( "LANMANNT", szProductType) == 0 )
05317 strlcat(strReturn, "Server " ,2048);
05318 if ( lstrcmpi( "SERVERNT", szProductType) == 0 )
05319 strlcat(strReturn, "Advanced Server " ,2048);
05320 snprintf(temp,512, "%d.%d ", osvi.dwMajorVersion, osvi.dwMinorVersion);
05321 strlcat(strReturn, temp,2048);
05322 }
05323
05324
05325
05326 if( osvi.dwMajorVersion == 4 &&
05327 lstrcmpi( osvi.szCSDVersion, "Service Pack 6" ) == 0 )
05328 {
05329 HKEY hKey;
05330 LONG lRet;
05331
05332
05333 lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
05334 "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Hotfix\\Q246009",
05335 0, KEY_QUERY_VALUE, &hKey );
05336 if( lRet == ERROR_SUCCESS ) {
05337 snprintf(temp, 512, "Service Pack 6a (Build %d)", osvi.dwBuildNumber & 0xFFFF );
05338 strlcat(strReturn, temp,2048 );
05339 }
05340 else
05341 {
05342 snprintf(temp,512, "%s (Build %d)", osvi.szCSDVersion, osvi.dwBuildNumber & 0xFFFF);
05343 strlcat(strReturn, temp,2048 );
05344 }
05345
05346 RegCloseKey( hKey );
05347 }
05348 else
05349 {
05350 snprintf(temp, 512,"%s (Build %d)", osvi.szCSDVersion, osvi.dwBuildNumber & 0xFFFF);
05351 strlcat(strReturn, temp,2048 );
05352 }
05353
05354 break;
05355
05356
05357 case VER_PLATFORM_WIN32_WINDOWS:
05358
05359 if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0)
05360 {
05361 strlcpy(strReturn, "Microsoft Windows 95 ",2048);
05362 if (osvi.szCSDVersion[1]=='C' || osvi.szCSDVersion[1]=='B')
05363 strlcat(strReturn, "OSR2 " ,2048);
05364 }
05365
05366 if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10)
05367 {
05368 strlcpy(strReturn, "Microsoft Windows 98 ",2048);
05369 if ( osvi.szCSDVersion[1]=='A' || osvi.szCSDVersion[1]=='B')
05370 strlcat(strReturn, "SE ",2048 );
05371 }
05372
05373 if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90)
05374 {
05375 strlcpy(strReturn, "Microsoft Windows Millennium Edition",2048);
05376 }
05377 break;
05378
05379 case VER_PLATFORM_WIN32s:
05380 strlcpy(strReturn, "Microsoft Win32s",2048);
05381 break;
05382 }
05383 return strReturn;
05384 }
05385
05386
05387 static int GetL2CacheSize()
05388 {
05389
05390
05391 unsigned long eaxreg, ebxreg, ecxreg, edxreg;;
05392
05393 __try {
05394 _asm {
05395 push eax
05396 push ebx
05397 push ecx
05398 push edx
05399 ; eax = 0x80000006 --> eax: L2 cache information.
05400 mov eax, 0x80000006
05401 cpuid
05402 mov eaxreg, eax
05403 mov ebxreg, ebx
05404 mov ecxreg, ecx
05405 mov edxreg, edx
05406 pop edx
05407 pop ecx
05408 pop ebx
05409 pop eax
05410 }
05411 }
05412 __except (1) {
05413 return 0;
05414 }
05415
05416 return ((ecxreg & 0xFFFF0000) >> 16);
05417 }
05418
05419
05420 static void GetWinNTSysInfo(SysInfo_t *sysinfo)
05421 {
05422
05423
05424 SYSTEM_PERFORMANCE_INFORMATION SysPerfInfo;
05425 SYSTEM_INFO sysInfo;
05426 MEMORYSTATUSEX statex;
05427 OSVERSIONINFO OsVersionInfo;
05428 HKEY hKey;
05429 char szKeyValueString[80];
05430 DWORD szKeyValueDword;
05431 DWORD dwBufLen;
05432 LONG status;
05433 PROCNTQSI NtQuerySystemInformation;
05434
05435 NtQuerySystemInformation = (PROCNTQSI)GetProcAddress(
05436 GetModuleHandle("ntdll"), "NtQuerySystemInformation");
05437
05438 if (!NtQuerySystemInformation) {
05439 ::Error("GetWinNTSysInfo",
05440 "Error on GetProcAddress(NtQuerySystemInformation)");
05441 return;
05442 }
05443
05444 status = NtQuerySystemInformation(SystemPerformanceInformation,
05445 &SysPerfInfo, sizeof(SysPerfInfo),
05446 NULL);
05447 OsVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
05448 GetVersionEx(&OsVersionInfo);
05449 GetSystemInfo(&sysInfo);
05450 statex.dwLength = sizeof(statex);
05451 if (!GlobalMemoryStatusEx(&statex)) {
05452 ::Error("GetWinNTSysInfo", "Error on GlobalMemoryStatusEx()");
05453 return;
05454 }
05455 sysinfo->fCpus = sysInfo.dwNumberOfProcessors;
05456 sysinfo->fPhysRam = (Int_t)(statex.ullTotalPhys >> 20);
05457 sysinfo->fOS = GetWindowsVersion();
05458 sysinfo->fModel = "";
05459 sysinfo->fCpuType = "";
05460 sysinfo->fCpuSpeed = GetCPUSpeed();
05461 sysinfo->fBusSpeed = 0;
05462 sysinfo->fL2Cache = GetL2CacheSize();
05463
05464 status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System",
05465 0, KEY_QUERY_VALUE, &hKey);
05466 if (status == ERROR_SUCCESS) {
05467 dwBufLen = sizeof(szKeyValueString);
05468 RegQueryValueEx(hKey, "Identifier", NULL, NULL,(LPBYTE)szKeyValueString,
05469 &dwBufLen);
05470 sysinfo->fModel = szKeyValueString;
05471 RegCloseKey (hKey);
05472 }
05473 status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
05474 "Hardware\\Description\\System\\CentralProcessor\\0",
05475 0, KEY_QUERY_VALUE, &hKey);
05476 if (status == ERROR_SUCCESS) {
05477 dwBufLen = sizeof(szKeyValueString);
05478 status = RegQueryValueEx(hKey, "ProcessorNameString", NULL, NULL,
05479 (LPBYTE)szKeyValueString, &dwBufLen);
05480 if (status == ERROR_SUCCESS)
05481 sysinfo->fCpuType = szKeyValueString;
05482 dwBufLen = sizeof(DWORD);
05483 status = RegQueryValueEx(hKey,"~MHz",NULL,NULL,(LPBYTE)&szKeyValueDword,
05484 &dwBufLen);
05485 if ((status == ERROR_SUCCESS) && ((sysinfo->fCpuSpeed <= 0) ||
05486 (sysinfo->fCpuSpeed < (szKeyValueDword >> 1))))
05487 sysinfo->fCpuSpeed = (Int_t)szKeyValueDword;
05488 RegCloseKey (hKey);
05489 }
05490 sysinfo->fCpuType.Remove(TString::kBoth, ' ');
05491 sysinfo->fModel.Remove(TString::kBoth, ' ');
05492 }
05493
05494
05495 static void GetWinNTCpuInfo(CpuInfo_t *cpuinfo, Int_t sampleTime)
05496 {
05497
05498
05499
05500 SYSTEM_INFO sysInfo;
05501 Float_t idle_ratio, kernel_ratio, user_ratio, total_ratio;
05502 FILETIME ft_sys_idle, ft_sys_kernel, ft_sys_user, ft_fun_time;
05503 SYSTEMTIME st_fun_time;
05504
05505 ULARGE_INTEGER ul_sys_idle, ul_sys_kernel, ul_sys_user;
05506 static ULARGE_INTEGER ul_sys_idleold = {0, 0};
05507 static ULARGE_INTEGER ul_sys_kernelold = {0, 0};
05508 static ULARGE_INTEGER ul_sys_userold = {0, 0};
05509 ULARGE_INTEGER ul_sys_idle_diff, ul_sys_kernel_diff, ul_sys_user_diff;
05510
05511 ULARGE_INTEGER ul_fun_time;
05512 ULARGE_INTEGER ul_fun_timeold = {0, 0};
05513 ULARGE_INTEGER ul_fun_time_diff;
05514
05515 typedef BOOL (__stdcall *GetSystemTimesProc)( LPFILETIME lpIdleTime,
05516 LPFILETIME lpKernelTime, LPFILETIME lpUserTime );
05517 static GetSystemTimesProc pGetSystemTimes = 0;
05518
05519 HMODULE hModImagehlp = LoadLibrary( "Kernel32.dll" );
05520 if (!hModImagehlp) {
05521 ::Error("GetWinNTCpuInfo", "Error on LoadLibrary(Kernel32.dll)");
05522 return;
05523 }
05524
05525 pGetSystemTimes = (GetSystemTimesProc) GetProcAddress( hModImagehlp,
05526 "GetSystemTimes" );
05527 if (!pGetSystemTimes) {
05528 ::Error("GetWinNTCpuInfo", "Error on GetProcAddress(GetSystemTimes)");
05529 return;
05530 }
05531 GetSystemInfo(&sysInfo);
05532
05533 again:
05534 pGetSystemTimes(&ft_sys_idle,&ft_sys_kernel,&ft_sys_user);
05535 GetSystemTime(&st_fun_time);
05536 SystemTimeToFileTime(&st_fun_time,&ft_fun_time);
05537
05538 memcpy(&ul_sys_idle, &ft_sys_idle, sizeof(FILETIME));
05539 memcpy(&ul_sys_kernel, &ft_sys_kernel, sizeof(FILETIME));
05540 memcpy(&ul_sys_user, &ft_sys_user, sizeof(FILETIME));
05541 memcpy(&ul_fun_time, &ft_fun_time, sizeof(FILETIME));
05542
05543 ul_sys_idle_diff.QuadPart = ul_sys_idle.QuadPart -
05544 ul_sys_idleold.QuadPart;
05545 ul_sys_kernel_diff.QuadPart = ul_sys_kernel.QuadPart -
05546 ul_sys_kernelold.QuadPart;
05547 ul_sys_user_diff.QuadPart = ul_sys_user.QuadPart -
05548 ul_sys_userold.QuadPart;
05549
05550 ul_fun_time_diff.QuadPart = ul_fun_time.QuadPart -
05551 ul_fun_timeold.QuadPart;
05552
05553 ul_sys_idleold.QuadPart = ul_sys_idle.QuadPart;
05554 ul_sys_kernelold.QuadPart = ul_sys_kernel.QuadPart;
05555 ul_sys_userold.QuadPart = ul_sys_user.QuadPart;
05556
05557 if (ul_fun_timeold.QuadPart == 0) {
05558 Sleep(sampleTime);
05559 ul_fun_timeold.QuadPart = ul_fun_time.QuadPart;
05560 goto again;
05561 }
05562 ul_fun_timeold.QuadPart = ul_fun_time.QuadPart;
05563
05564 idle_ratio = (Float_t)(Li2Double(ul_sys_idle_diff)/
05565 Li2Double(ul_fun_time_diff))*100.0;
05566 user_ratio = (Float_t)(Li2Double(ul_sys_user_diff)/
05567 Li2Double(ul_fun_time_diff))*100.0;
05568 kernel_ratio = (Float_t)(Li2Double(ul_sys_kernel_diff)/
05569 Li2Double(ul_fun_time_diff))*100.0;
05570 idle_ratio /= (Float_t)sysInfo.dwNumberOfProcessors;
05571 user_ratio /= (Float_t)sysInfo.dwNumberOfProcessors;
05572 kernel_ratio /= (Float_t)sysInfo.dwNumberOfProcessors;
05573 total_ratio = 100.0 - idle_ratio;
05574
05575 cpuinfo->fLoad1m = 0;
05576 cpuinfo->fLoad5m = 0;
05577 cpuinfo->fLoad15m = 0;
05578 cpuinfo->fUser = user_ratio;
05579 cpuinfo->fSys = kernel_ratio;
05580 cpuinfo->fTotal = total_ratio;
05581 cpuinfo->fIdle = idle_ratio;
05582 }
05583
05584
05585 static void GetWinNTMemInfo(MemInfo_t *meminfo)
05586 {
05587
05588
05589 Long64_t total, used, free, swap_total, swap_used, swap_avail;
05590 MEMORYSTATUSEX statex;
05591 statex.dwLength = sizeof(statex);
05592 if (!GlobalMemoryStatusEx(&statex)) {
05593 ::Error("GetWinNTMemInfo", "Error on GlobalMemoryStatusEx()");
05594 return;
05595 }
05596 used = (Long64_t)(statex.ullTotalPhys - statex.ullAvailPhys);
05597 free = (Long64_t) statex.ullAvailPhys;
05598 total = (Long64_t) statex.ullTotalPhys;
05599
05600 meminfo->fMemTotal = (Int_t) (total >> 20);
05601 meminfo->fMemUsed = (Int_t) (used >> 20);
05602 meminfo->fMemFree = (Int_t) (free >> 20);
05603
05604 swap_total = (Long64_t)(statex.ullTotalPageFile - statex.ullTotalPhys);
05605 swap_avail = (Long64_t)(statex.ullAvailPageFile - statex.ullAvailPhys);
05606 swap_used = swap_total - swap_avail;
05607
05608 meminfo->fSwapTotal = (Int_t) (swap_total >> 20);
05609 meminfo->fSwapUsed = (Int_t) (swap_used >> 20);
05610 meminfo->fSwapFree = (Int_t) (swap_avail >> 20);
05611 }
05612
05613
05614 static void GetWinNTProcInfo(ProcInfo_t *procinfo)
05615 {
05616
05617
05618 PROCESS_MEMORY_COUNTERS pmc;
05619 FILETIME starttime, exittime, kerneltime, usertime;
05620 timeval ru_stime, ru_utime;
05621 ULARGE_INTEGER li;
05622
05623 typedef BOOL (__stdcall *GetProcessMemoryInfoProc)( HANDLE Process,
05624 PPROCESS_MEMORY_COUNTERS ppsmemCounters, DWORD cb );
05625 static GetProcessMemoryInfoProc pGetProcessMemoryInfo = 0;
05626
05627 HMODULE hModImagehlp = LoadLibrary( "Psapi.dll" );
05628 if (!hModImagehlp) {
05629 ::Error("GetWinNTProcInfo", "Error on LoadLibrary(Psapi.dll)");
05630 return;
05631 }
05632
05633 pGetProcessMemoryInfo = (GetProcessMemoryInfoProc) GetProcAddress(
05634 hModImagehlp, "GetProcessMemoryInfo" );
05635 if (!pGetProcessMemoryInfo) {
05636 ::Error("GetWinNTProcInfo",
05637 "Error on GetProcAddress(GetProcessMemoryInfo)");
05638 return;
05639 }
05640
05641 if ( pGetProcessMemoryInfo( GetCurrentProcess(), &pmc, sizeof(pmc)) ) {
05642 procinfo->fMemResident = pmc.WorkingSetSize / 1024;
05643 procinfo->fMemVirtual = pmc.PagefileUsage / 1024;
05644 }
05645 if ( GetProcessTimes(GetCurrentProcess(), &starttime, &exittime,
05646 &kerneltime, &usertime)) {
05647
05648
05649 memcpy(&li, &kerneltime, sizeof(FILETIME));
05650 li.QuadPart /= 10L;
05651 ru_stime.tv_sec = li.QuadPart / 1000000L;
05652 ru_stime.tv_usec = li.QuadPart % 1000000L;
05653
05654 memcpy(&li, &usertime, sizeof(FILETIME));
05655 li.QuadPart /= 10L;
05656 ru_utime.tv_sec = li.QuadPart / 1000000L;
05657 ru_utime.tv_usec = li.QuadPart % 1000000L;
05658
05659 procinfo->fCpuUser = (Float_t)(ru_utime.tv_sec) +
05660 ((Float_t)(ru_utime.tv_usec) / 1000000.);
05661 procinfo->fCpuSys = (Float_t)(ru_stime.tv_sec) +
05662 ((Float_t)(ru_stime.tv_usec) / 1000000.);
05663 }
05664 }
05665
05666
05667 Int_t TWinNTSystem::GetSysInfo(SysInfo_t *info) const
05668 {
05669
05670
05671
05672
05673 if (!info) return -1;
05674 GetWinNTSysInfo(info);
05675 return 0;
05676 }
05677
05678
05679 Int_t TWinNTSystem::GetCpuInfo(CpuInfo_t *info, Int_t sampleTime) const
05680 {
05681
05682
05683
05684
05685 if (!info) return -1;
05686 GetWinNTCpuInfo(info, sampleTime);
05687 return 0;
05688 }
05689
05690
05691 Int_t TWinNTSystem::GetMemInfo(MemInfo_t *info) const
05692 {
05693
05694
05695
05696 if (!info) return -1;
05697 GetWinNTMemInfo(info);
05698 return 0;
05699 }
05700
05701
05702 Int_t TWinNTSystem::GetProcInfo(ProcInfo_t *info) const
05703 {
05704
05705
05706
05707 if (!info) return -1;
05708 GetWinNTProcInfo(info);
05709 return 0;
05710 }