//#ifndef UTILITIES_HPP_INCLUDED #include "StdAfx.h" // trying to resolve #include "utilities.hpp" //#endif #ifndef UTILITIES_HPP_INCLUDED #error "You forgot to #include \"utilities.hpp\" in StdAfx.h" #endif #define UTILITIES_HPP_INCLUDED #include #pragma comment(lib, "Ws2_32.lib") #pragma comment(lib, "version.lib") #pragma comment(lib, "Wininet.lib") ////////////////////////////////////////////////////////////////////////////////// // // Implementation part // UTILITIES // // //////////////////////////////////////////////////////////////////////////////// critical_section_variable general_critical_section::m_cs; //////////////////////////////////////////////////////////////////////////////// // // CTextOfError_Formatter // CTextOfError_Formatter::CTextOfError_Formatter(const char _prfx[]/*=0*/) : prfx(_prfx) { s << std::hex << std::boolalpha;; if(prfx && *prfx) s << prfx << "
"; } CTextOfError_Formatter::CTextOfError_Formatter(const std::string& _prfx) : prfx(_prfx.c_str()) { s << std::hex << std::boolalpha;; if(prfx && *prfx) s << prfx << "
"; } std::string CTextOfError_Formatter::getText(const char *er) { s << "Runtime Error
Description: " << er << ""; return s.str(); } #if defined _MFC_VER std::string CTextOfError_Formatter::getText(CException* e) { char er[512]; e->GetErrorMessage(er, sizeof er); s << "MFC Error
Description: " << er << ""; return s.str(); } #endif std::string CTextOfError_Formatter::getText(DWORD er) { s << "Last System Error=0x" << er << "
Description: " << textOfWin32Error(er) <<""; return s.str(); } std::string CTextOfError_Formatter::getText(HRESULT hr) { s << "Type: HRESULT = 0x" << (unsigned long) hr << " "; if (hr==S_OK) s << "Success OK"; else if(hr==S_FALSE) s << "General failure (success with FALSE return)"; else { s << (IS_ERROR(hr)? "Severe error.":"Success with code return") << " Code 0x" << SCODE_CODE(hr) << "
"; #define FACILITY_R_BIT 0x8000000 if(bool bR = ((hr & FACILITY_R_BIT) !=0)) s << "The value of this HRESULT is a message ID to display a string
"; if(int fac= HRESULT_FACILITY(hr) >0) { fac =HRESULT_FACILITY(hr &(~(FACILITY_R_BIT|FACILITY_NT_BIT))); const char* pszFac ="Unknown or new type"; switch(fac) { case FACILITY_NULL :pszFac = "Null" ;break; case FACILITY_RPC :pszFac = "RPC -- Remote Procedure Call";break; case FACILITY_DISPATCH :pszFac = "DISPATCH" ;break; case FACILITY_STORAGE :pszFac = "STORAGE" ;break; case FACILITY_ITF :pszFac = "ITF - interface"; // // NOTE: PSI AppStrg.dll makes up the 0x800-0x802 HRESULTs // switch(SCODE_CODE(hr)) { case REGDB_E_CLASSNOTREG: s << "Description: Class is not registered
"; break; case 0x800: s <<"Source: SessionObject
Description: " "Error of encrypting of SESSIONPARAM. B3000 Key Set or crypt.dll " "might be missed or corrupted or SESSIONPARAM contains not valid data"; break; case 0x801: s <<"Source: SessionObject
Description: " "Invalid key has been passed to APPSTRG's session object"; break; case 0x802: s <<"Source: SessionObject
Description: " "Unable to decrypt session parameter (SessionID cookie is missing)"; break; } break; case FACILITY_WIN32 :pszFac = "WIN32"; s << "Description: " << textOfWin32Error(SCODE_CODE(hr)) << "
"; break; case FACILITY_WINDOWS :pszFac = "WINDOWS" ;break; case FACILITY_SSPI :pszFac = "SSPI -- Security Support Provider Interface" ;break; case FACILITY_CONTROL :pszFac = "CONTROL"; if(hr = HRESULT_CODE(CTL_E_PATHNOTFOUND)) s << "Description: Path not found
"; break; case FACILITY_CERT :pszFac = "CERT -- certificate" ;break; case FACILITY_INTERNET :pszFac = "INTERNET" ;break; case FACILITY_MEDIASERVER :pszFac = "MEDIASERVER" ;break; case FACILITY_MSMQ :pszFac = "MSMQ" ;break; case FACILITY_SETUPAPI :pszFac = "SETUPAPI" ;break; case 16 :pszFac = "SCARD" ;break; case 17 :pszFac = "MTS (id exist but not documented)" ;break; case 109 :pszFac = "VISUALCPP"; ;break; case 119 :pszFac = "VDI (id exist but not documented)"; ;break; case 769 :pszFac = "IC (id exist but not documented)"; ;break; case 2047 :pszFac = "BACKUP"; ;break; case 2048 :pszFac = "EDB"; ;break; case 2304 :pszFac = "MDSI"; ;break; } s << "Source (facility=0x" << fac << (0 != (hr & FACILITY_NT_BIT)? ", mapped NT status value":"") << "): " << pszFac << " facility" "
Possible COM interpretation of the result:
"; textOfCOMError(_com_error(hr)); } } return s.str(); } std::string CTextOfError_Formatter::getText(const _com_error& er) { s << "Type: COM error
"; textOfCOMError(er); return s.str(); } std::string CTextOfError_Formatter::getText(const URL& url) { s << "URL Source: " << (std::string)url << ""; return s.str(); } std::string CTextOfError_Formatter::getText(const std::exception& e) { s << "Source: C++ standard std::exception
Description: " << e.what() << " "; return s.str(); } std::string CTextOfError_Formatter::textOfWin32Error(DWORD error_code/*=-1*/) { if(error_code ==-1) error_code = ::GetLastError(); char *pBuf=0; DWORD dwSym = ::FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER, 0, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR) &pBuf,0, 0); if(pBuf ==0) return "Unknown System error"; std::string ret(pBuf); ::LocalFree(HLOCAL(pBuf)); return trim(ret); } void CTextOfError_Formatter::textOfCOMError(const _com_error& er) throw() { try { const char *pszMsg = er.ErrorMessage(); _bstr_t bstrDsc = er.Description(); _bstr_t bstrSrc = er.Source(); char *pszDsc = (char*) bstrDsc; char *pszSrc = (char*) bstrSrc; if(pszMsg !=0 && pszMsg[0] !=0) s << "Error Message: " << pszMsg << "
"; if(pszDsc !=0 && pszDsc[0] !=0) s << "Description: " << pszDsc << ""; if(pszSrc !=0 && pszSrc[0] !=0) s << "
Source: " << pszSrc << ""; } catch(...) { } } ////////////////////////////////////////////////////////////////////////////////// // CRuntime_error // std::string CRuntime_error::extract(const char* sectionname) const { std::string strResult; std::string open_tag("<"); open_tag.append(sectionname).append(">"); // opening tag std::string close_tag(""); // closing tag for(size_t pfb=0 , pfe=0 ; (pfb=_strText.find(open_tag,pfe)) !=std::string::npos ; pfe+=close_tag.length()) { if(strResult.length() !=0) strResult +="\n
\n"; pfb +=open_tag.length(); if((pfe =_strText.find(close_tag, pfb)) ==std::string::npos) { strResult.append(_strText, pfb, std::string::npos); break; } strResult.append(_strText, pfb, pfe-pfb); } return strResult; } std::string CRuntime_error::text() const // removes tags { std::string strResult = _strText; return replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(strResult, "
", "\n"), ""), ""), ""), ""), ""), ""), ""), ""), ""), ""), ""), ""); } std::string CRuntime_error::getContentAsHtml(const TraceStream* pts) const { std::string strDesc = extract("DESCRIPTION"); if(strDesc.empty()) strDesc = "No description's been given. Click here for more information"; std::string res; res .append("
") .append(strDesc) .append("
" "

") .append(_strText); if(pts!=0) { std::string sTraceNote=pts->str(); if(!sTraceNote.empty()) res .append("
Trace Notes:
") .append(sTraceNote) .append("
"); } res.append("
"); return res; } std::string CRuntime_error::getContentAsHtml(const TraceStream& ts) const { return getContentAsHtml(&ts); } ///////////////////////////////////////////////////////////////////////////////////////// // // CSeExceptionsTranslator // void __cdecl CSeExceptionsTranslator::SeTranslator(UINT nSeCode, _EXCEPTION_POINTERS* pExcPointers) throw(CRuntime_error) { const char *pszName ="???"; switch(nSeCode) { case EXCEPTION_ACCESS_VIOLATION: pszName="access violation"; break; case EXCEPTION_DATATYPE_MISALIGNMENT: pszName="datatype misalignment"; break; case EXCEPTION_BREAKPOINT: #if 0 // defined(_DEBUG) se_translator_processor(nSeCode, pExcPointers); #endif pszName="breakpoint"; break; case EXCEPTION_SINGLE_STEP: #if 0 // defined(_DEBUG) se_translator_processor(nSeCode, pExcPointers); #endif pszName="single step"; break; case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: pszName="array bounds exceeded"; break; case EXCEPTION_FLT_DENORMAL_OPERAND: pszName="flt denormal operand"; break; case EXCEPTION_FLT_DIVIDE_BY_ZERO: pszName="flt divide by zero"; break; case EXCEPTION_FLT_INEXACT_RESULT: pszName="flt inexact result"; break; case EXCEPTION_FLT_INVALID_OPERATION: pszName="flt invalid operation"; break; case EXCEPTION_FLT_OVERFLOW: pszName="flt overflow"; break; case EXCEPTION_FLT_STACK_CHECK: pszName="flt stack check"; break; case EXCEPTION_FLT_UNDERFLOW: pszName="flt underflow"; break; case EXCEPTION_INT_DIVIDE_BY_ZERO: pszName="int divide by zero"; break; case EXCEPTION_INT_OVERFLOW: pszName="int overflow"; break; case EXCEPTION_PRIV_INSTRUCTION: pszName="privilege instruction"; break; case EXCEPTION_IN_PAGE_ERROR: pszName="in page error"; break; case EXCEPTION_ILLEGAL_INSTRUCTION: pszName="illegal instruction"; break; case EXCEPTION_NONCONTINUABLE_EXCEPTION: pszName="noncontinuable exception"; break; case EXCEPTION_STACK_OVERFLOW: pszName="stack overflow"; break; case EXCEPTION_INVALID_DISPOSITION: pszName="invalid disposition"; break; case EXCEPTION_GUARD_PAGE: pszName="guard page"; break; case EXCEPTION_INVALID_HANDLE: pszName="invalid handle"; break; } std::ostringstream str; str << "" "Source: Unknown
Description: " "SE Exception 0x" << std::hex << nSeCode << " (" << pszName << ") at address 0x" << pExcPointers->ExceptionRecord->ExceptionAddress << "
"; throw CRuntime_error(str.str()); } void CSeExceptionsTranslator::se_translator_processor(unsigned int nSeCode, struct _EXCEPTION_POINTERS* pExcPointers) { static _se_translator_function pOldSeFn=0; if(pOldSeFn ==0 && nSeCode ==1) pOldSeFn = _set_se_translator(SeTranslator); else if(pExcPointers !=0 && pOldSeFn !=0) pOldSeFn(nSeCode, pExcPointers); // execute original se chain (aparantly on debugging interrupts) else if(nSeCode ==0 && pOldSeFn !=0) { _set_se_translator(pOldSeFn); // restore old chain pOldSeFn =0; } } ///////////////////////////////////////////////////////////////////////////////////////// // // dump // dump::dump(const void* pb, const void *pe, const int line_len, const bool bAscii) : terminator_(0) , pbeg_(reinterpret_cast(pb)) , pend_(reinterpret_cast(pe)) , line_len_(line_len) , bAscii_(bAscii) {;} dump::dump(const void* p, const int len, const int line_len, const bool bAscii) : terminator_(0) , pbeg_(reinterpret_cast(p)) , pend_(len >=0 ? reinterpret_cast(p)+len:0) , line_len_(line_len) , bAscii_(bAscii) {;} dump::dump(const char* p, const int line_len, const bool bAscii) : terminator_(0) , pbeg_(reinterpret_cast(p)) , pend_(0) , line_len_(line_len) , bAscii_(bAscii) {;} dump::dump(const unsigned char* p, const int line_len, const bool bAscii) : terminator_(0) , pbeg_(reinterpret_cast(p)) , pend_(0) , line_len_(line_len) , bAscii_(bAscii) {;} dump::dump(const std::string& s, const int line_len, const bool bAscii) : terminator_(0) , pbeg_(reinterpret_cast(s.c_str())) , pend_(0) , line_len_(line_len) , bAscii_(bAscii) {;} std::ostream& dump::operator() (std::ostream& s) { using namespace std; ios_base::fmtflags original_flags = s.flags(ios_base::hex); for(const unsigned char *pcur_ = pbeg_ ; doit(pcur_) ; ) { string ascii; s << uppercase << setfill('0') << setw(8) << (void *) (pcur_) << ":"; for(int j = 0 ; j 0) ascii.insert(size_t(0), j, ' '); s << nouppercase << " " << ascii; } s << '\n'; } s.flags(original_flags); return s; } std::ostream& dump::dump_hex(std::ostream& os, const unsigned char* b, int len) { for(int j = 0 ; j 0) { ::OutputDebugString(strBuf.c_str()); #if defined(_DEBUG) OutputDebugStringToFileLog(strBuf.c_str(), strBuf.length()); #endif } return true; } bool& OutputDebug::disabled() { // the C++ language guarantees to initialize a static variable once on the first use of it #if defined(_DEBUG) static bool bDisabled= false; #else // // allow only 6 hours maximum of continuing debugging in production version // static CTimer timer; static bool bDisabled= true; if(bDisabled) timer.start(); else if(timer() > (6L *60L* 1000L)) bDisabled = true; #endif return bDisabled; } std::string OutputDebug::getHtmlFormOfDisabled(std::string strName, std::string strInclude) { return ""; } bool OutputDebug::OutputDebugStringToFileLog(const char *pszBuf, int dwLen, const char* pszFileName) { if(pszBuf ==0 || dwLen <=0) return true; HANDLE hFile = ::CreateFile(pszFileName, GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_DELETE, 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, 0); if(hFile == INVALID_HANDLE_VALUE) return false; OVERLAPPED overlapped = { 0, 0, ::GetFileSize(hFile,NULL), 0, 0 }; DWORD dwSize = 0; ::WriteFile(hFile, pszBuf, dwLen, &dwSize, &overlapped); ::CloseHandle(hFile); return true; } ///////////////////////////////////////////////////////////////////////////////////////// // // OutputDebugStream // int OutputDebugStream::buf::output_buffer() { int n = pptr() - pbase(); // how many symbols to write out if(n >0) // && !OutputDebugStream::disabled()) { _buffer[n] = _buffer[n+1] = '\0'; // we reserved enough space for two more symbols if(_buffer[n-1] != '\n') _buffer[n] = '\n'; OutputDebug::OutputDebugString(static_cast(_buffer)); } pbump(-n); return n; } ///////////////////////////////////////////////////////////////////////////////////////// // // TraceStream // TraceStream::TraceStream(const char* p) : std::basic_ostream(_buf=make_buf()) { if(_buf!=0) *this << CTimer::strCurrentTime("vvvvvvvvvvvvv Begin trace %X ") << (p==0?"":p) << ". Thread " << ::GetCurrentThreadId() << " vvvvvvvvvvvvvvv\n"; } TraceStream::~TraceStream() { if(_buf!=0) { *this << CTimer::strCurrentTime("^^^^^^^^^^^^^ End trace %X ^^^^^^^^^^^^^\n\n"); OutputDebug::OutputDebugString(_buf->str()); delete _buf; } } std::string TraceStream::getHtmlFormOfNumberOfTracingHistory(const std::string& strName, const std::string& strInclude) { return ""; } int TraceStream::size_of_history_list(int n) { if(n >=0) get_History_container().resize(size_t(n)); return (int) get_History_container().max_size(); } TraceStream::buf::~buf() { std::string s =str(); if(!OutputDebug::disabled()) OutputDebug::OutputDebugString(s); if(size_of_history_list() >0) TraceStream::put_into_history_list(s); } /*history_container& TraceStream::get_History_container() { static history_container hs; return hs; }*/ ///////////////////////////////////////////////////////////////////////////////////////// // // EventStream // int EventStream::buf::output_buffer() { int n = pptr() - pbase(); // how many symbols to write out if(n >0 && _h) { _buffer[n] = _buffer[n+1] = '\0'; // we reserved enough space for two more symbols const char* rgsz[] = { _buffer }; ::ReportEvent(_h, _type,0,0,0,1,0,rgsz,0); } // // also copy out the event to the debug window and into history list // bool bOutputDebug=!OutputDebug::disabled(); bool bTrace=TraceStream::size_of_history_list() >0?true:false; if(bOutputDebug || bTrace) { if(_buffer[n-1] == '\n') _buffer[n-1] = 0; std::string s(_pName); s.append(": ******** Event type ").append(EventTypeName(_type)).append(CTimer::strCurrentTime("%X\n")) .append(_buffer).append(" *******\n"); if(bOutputDebug) OutputDebug::OutputDebugString(s); if(bTrace) TraceStream::put_into_history_list(s); } pbump(-n); // bump down the buffer to 0-length resetting one return n; } const char* EventStream::EventTypeName(long type, const char* const* names) { static const char * const defaultNames[] = { "OK", "Error", "Warning", "Inform", "Audit OK", "Audit fail", "UNKNOWN"}; if(names ==0) names = defaultNames; switch(type) { case EVENTLOG_SUCCESS: return names[0]; case EVENTLOG_ERROR_TYPE: return names[1]; case EVENTLOG_WARNING_TYPE: return names[2]; case EVENTLOG_INFORMATION_TYPE: return names[3]; case EVENTLOG_AUDIT_SUCCESS: return names[4]; case EVENTLOG_AUDIT_FAILURE: return names[5]; default: return names[6]; } } ///////////////////////////////////////////////////////////////////////////////////////// // // URL // bool URL::crack() { // // I dont check if there has been any change to THIS string since last cracking and do the crack // again. If InternetCrackUrl will prove to be unefficient it's possible to keep a copy last // cracked string and make a comparison with THIS string prior to cracking // trim(*this); _urlComponents.dwStructSize = sizeof _urlComponents; _urlComponents.lpszScheme = 0; _urlComponents.lpszHostName = 0; _urlComponents.lpszUserName = 0; _urlComponents.lpszPassword = 0; _urlComponents.lpszUrlPath = 0; _urlComponents.lpszExtraInfo = 0; _urlComponents.nPort = 0; // preset port to invalid value _urlComponents.dwSchemeLength = 1; // these lines set which components should be cracked out _urlComponents.dwHostNameLength = 1; _urlComponents.dwUserNameLength = 1; _urlComponents.dwPasswordLength = 1; _urlComponents.dwUrlPathLength = 1; _urlComponents.dwExtraInfoLength = 1; return ::InternetCrackUrl(data(), length(), 0, &_urlComponents) !=0? true : false; // if(!InternetCrackUrl(data(), length(), 0, &_urlComponents) !=0) dothrow(); // return true; } std::string URL::escape(const std::string& s) { std::ostringstream str; str << std::hex << std::uppercase << std::setfill('0'); for(int i = 0 ; i < s.length() ; ++i) { static const std::string strCharSet="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" "'=:;@$-_.+!*()/"; if(strCharSet.find(s[i]) ==std::string::npos) str << "%" << std::setw(2) << (s[i] & 0xff); else str << s[i]; } return str.str(); } std::string URL::canonicalize(const std::string& s, DWORD flags) { DWORD dwSize = s.length() + (flags&ICU_DECODE? 0 : s.length()/4) ; std::string res(dwSize, 0); if(!::InternetCanonicalizeUrl(s.c_str(), const_cast(res.c_str()), &dwSize, flags)) { if(::GetLastError() != ERROR_INSUFFICIENT_BUFFER) return std::string(); res.resize(dwSize); if(!::InternetCanonicalizeUrl(s.c_str(), const_cast(res.c_str()), &dwSize, flags)) return std::string(); } res.resize(dwSize); return res; } std::string URL::combine(std::string sUrl_1, std::string sUrl_2, DWORD dwFlags) throw(CRuntime_error) { std::string sFullUrl(sUrl_1.length() + sUrl_2.length() + 128, 0); DWORD lnFullUrl = sFullUrl.length(); if(!::InternetCombineUrl(sUrl_1.c_str(), sUrl_2.c_str(), const_cast(sFullUrl.data()), &lnFullUrl, dwFlags)) { DWORD err=::GetLastError(); if(err !=ERROR_INSUFFICIENT_BUFFER) throw CRuntime_error("Note: InternetCombineUrl failed", err); sFullUrl.resize(lnFullUrl); if(!::InternetCombineUrl(sUrl_1.c_str(), sUrl_2.c_str(), const_cast(sFullUrl.data()), &lnFullUrl, dwFlags)) throw CRuntime_error("Note: InternetCombineUrl failed", ::GetLastError()); } sFullUrl.resize(lnFullUrl); return sFullUrl; } std::string URL::getDomainFromHost(const std::string& strHost, int nLevel) throw(CRuntime_error) { for(int pos = -1 ; (pos = strHost.rfind('.', pos)) >0 && (--nLevel) >0 ; --pos) ; if(pos == npos) throw CRuntime_error(std::string("Host name: ") +strHost+"", "Invalid domain name for host"); return strHost.substr(pos); } int URL::getPortNumber() { if(!crack()) return 0; return _urlComponents.nPort; } bool URL::putPortNumber(int port) { _urlComponents.nPort = port; return createUrl(length()+10); } std::string URL::getString(LPTSTR* buf, DWORD* len) { return !crack() || *len ==0 ? std::string() : std::string(*buf, *len); } bool URL::putString(std::string s, LPTSTR* buf, DWORD* len) { if(!crack()) // before adding info in url crack it down to the pieces ?? return false; *len = s.length(); *buf = const_cast(s.data()); return createUrl(length() + s.length() +1); } bool URL::createUrl(DWORD dwSize) { std::string res(dwSize, 0); if(!::InternetCreateUrl(&_urlComponents, 0, const_cast(res.data()), &dwSize)) { if(::GetLastError() !=ERROR_INSUFFICIENT_BUFFER) return false; // dothrow(); res.resize(dwSize, 0); if(!::InternetCreateUrl(&_urlComponents, 0, const_cast(res.data()), &dwSize)) return false; // dothrow } res.resize(dwSize); assign(res); return crack(); } ///////////////////////////////////////////////////////////////////////////////////////// // // clsid // clsid& clsid::operator= (const clsid& n) { ::memcpy(static_cast(this), static_cast(&n), sizeof CLSID); _hr = n._hr; _sname = n._sname; return *this; } clsid& clsid::operator= (const char *name) { _hr = CO_E_CLASSSTRING; // pre-reset it to wrong state ::memset(static_cast(this), 0, sizeof CLSID); if(name==0 || name[0] !='{') _sname.erase() , *this; if(name[0]==0) // no name given -> create_new GUID return create_new(); _sname = name; _bstr_t n(name); _hr = ::CLSIDFromString((wchar_t*)n, static_cast(this)); return *this; } clsid& clsid::operator= (const CLSID& id) throw(CRuntime_error) { BSTR olestr = ::SysAllocStringLen(0, 39); if(olestr == 0) throw CRuntime_error("Source: clsid", "No memory"); _hr = S_OK; ::memcpy(static_cast(this), &id, sizeof CLSID); ::StringFromGUID2(static_cast(*this), olestr, 39); _sname = _bstr_t(olestr, false).operator const char * (); return *this; } clsid& clsid::create_new() { GUID guid; ::memset(&guid, 0, sizeof GUID); ::CoCreateGuid(&guid); return operator=(guid); } clsid& clsid::reset() { _hr = S_OK; _sname ="{00000000-0000-0000-0000-000000000000}"; ::memset(static_cast(this),0,sizeof CLSID); return *this; } bool clsid::valid(const std::string& n) { return n.length() ==38 && n[0]=='{' && n[37]=='}' && n[9]=='-' && n[14] =='-' && n[19]=='-' && n[24]=='-' && n.find_first_not_of("0123456789ABCDEFabcdef", 1, 8) !=n.npos && n.find_first_not_of("0123456789ABCDEFabcdef", 10, 4) !=n.npos && n.find_first_not_of("0123456789ABCDEFabcdef", 15, 4) !=n.npos && n.find_first_not_of("0123456789ABCDEFabcdef", 20, 4) !=n.npos && n.find_first_not_of("0123456789ABCDEFabcdef", 25, 8) !=n.npos; } std::ostream& clsid::getInformationOnCOMAsHtml(std::ostream& os, bool bShowInfoOnFile) const throw(CRuntime_error) { // static const char bol[] = "", del[] = "", eol[] = ""; RegistryKey reg (HKEY_CLASSES_ROOT, ("AppID\\"+_sname).c_str(), KEY_READ); //KEY_QUERY_VALUE|KEY_ENUMERATE_SUB_KEYS); RegistryKey reg2(HKEY_CLASSES_ROOT, ("CLSID\\"+_sname).c_str(), KEY_READ); //KEY_QUERY_VALUE|KEY_ENUMERATE_SUB_KEYS); os<<"" ""; if(!reg.Valid() && !reg2.Valid()) return os << "
" << _sname << "
COM " << _sname << " is not registered
"; if(reg.Valid()) reg.getInformationAsHtml(os << "", "1 HKEY_CLASSES_ROOT\\") << ""; if(reg2.Valid()) { reg2.getInformationAsHtml(os << "", "1 HKEY_CLASSES_ROOT\\") << ""; if(bShowInfoOnFile) { std::string server; if((server=RegistryKey::GetStringValue(HKEY_CLASSES_ROOT, "CLSID\\"+_sname+"\\LocalServer32")).empty()) if((server=RegistryKey::GetStringValue(HKEY_CLASSES_ROOT, "CLSID\\"+_sname+"\\InprocServer32")).empty()) if((server=RegistryKey::GetStringValue(HKEY_CLASSES_ROOT, "CLSID\\"+_sname+"\\LocalServer")).empty()) server=RegistryKey::GetStringValue(HKEY_CLASSES_ROOT, "CLSID\\"+_sname+"\\InprocServer"); os << "Information on COM server"; if(server.empty()) os << "The COM object is not local or inproc server"; else { FileInformation(server) .getFileInformationAsHtml(os<<"") << ""; FileVersion(server) .getFileVersionAsHtml (os<<"") << ""; } } } os << ""; return os; } ///////////////////////////////////////////////////////////////////////////////////////// // // progid // progid::progid(const char *n1, const char* n2, ...) // multiple attempts to init { va_list args; va_start(args, n1); for(const char *n = n1 ; n !=0 && n[0] !=0 ; n = va_arg(args, const char*)) if(init(n)) break; va_end(args); } progid& progid::operator= (const progid& n) { ::memcpy(static_cast(this), static_cast(&n), sizeof CLSID); // _hr = n._hr; _sname = n._sname; _bRegistered = n._bRegistered; return *this; } progid& progid::operator= (const CLSID& id) throw(CRuntime_error) { reset(); BSTR bstrID; if(::ProgIDFromCLSID(id, &bstrID) ==S_OK) { _sname = _bstr_t(bstrID, false).operator const char * (); ::memcpy(static_cast(this), &id, sizeof CLSID); _bRegistered = true; } return *this; } progid& progid::create_new() { GUID guid; ::memset(&guid, 0, sizeof GUID); ::CoCreateGuid(&guid); return operator=(guid); } progid& progid::reset() { // _hr = CO_E_CLASSSTRING; // pre-reset it to wrong state _sname.erase(); ::memset(static_cast(this),0,sizeof CLSID); _bRegistered =false; return *this; } bool progid::valid(const std::string& n) { return n.length() !=0 && n.length() <=39 && !::isdigit(n[0]) && n.find_first_not_of(".0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")!=n.npos; } bool progid::init(const char *name) { reset(); if(name==0 || name[0]==0) return false; _sname = name; std::string strCLSID; if(clsid::valid(_sname)) strCLSID = _sname; else { RegistryKey reg(HKEY_LOCAL_MACHINE, ("SOFTWARE\\Classes\\"+_sname+"\\CLSID").c_str(), KEY_QUERY_VALUE); if(!reg.Valid()) return false; strCLSID = reg.GetStringValue(""); } clsid cls(strCLSID.c_str()); if(!cls.valid()) return false; ::memcpy(static_cast(this), &cls, sizeof CLSID); return _bRegistered = true; } std::ostream& progid::getInformationOnCOMAsHtml(std::ostream& os, bool bShowInfoOnFile) const { os<<"" ""; if(!registered()) return os << "
" << _sname << "
COM object is not registered: " << RegistryKey(HKEY_LOCAL_MACHINE, ("SOFTWARE\\Classes\\"+_sname+"\\CLSID").c_str(), KEY_QUERY_VALUE).LastError() << "
"; RegistryKey reg(HKEY_LOCAL_MACHINE, ("SOFTWARE\\Classes\\"+_sname).c_str(), KEY_READ); if(reg.Valid()) reg.getInformationAsHtml(os << "", "1 HKEY_LOCAL_MACHINE\\") << ""; else os << "Error of openning HKEY_LOCAL_MACHINE\\SOFTWARE\\Classes\\" << _sname << ". " << reg.LastError() << ""; return clsid(*this).getInformationOnCOMAsHtml(os<<"", bShowInfoOnFile) << ""; } ///////////////////////////////////////////////////////////////////////////////////////// // // HTML // std::string HTML::escape(const std::string& s) { std::ostringstream str; //str << std::hex << std::uppercase << std::setfill('0'); for(int i = 0 ; i < s.length() ; ++i) { static const std::string strCharSet= "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$-_.+!*'()/"; if(strCharSet.find(s[i]) ==std::string::npos) str << "&#" << /*std::setw(2) << */(s[i] & 0xff) <<";"; else str << s[i]; } return str.str(); } std::string HTML::str() // closes BODY and HTML if they are not there { static const char BODY_tag [] = ""; static const char HTML_tag [] = ""; std::string r = static_cast(*this).str(); if(std::find_first_of(r.begin(), r.end(),BODY_tag,BODY_tag+lengthof(BODY_tag), char_less_than_ignore_case::compare_symbols) !=r.end()) r +=""; if(std::find_first_of(r.begin(), r.end(), HTML_tag, HTML_tag+lengthof(HTML_tag), char_less_than_ignore_case::compare_symbols) !=r.end()) r +=""; return r; } // // convert 'this' content into invisile SPAN with 'id'; the content will popup in modal HTML browser // std::string HTML::makeModalDialogSPAN(std::string id) { return "" "" ; } void HTML::Init(const std::string& style, const std::string& script) { if(!_strTitle.empty() || !style.empty() || !script.empty()) *this << strHTMLBegin() << style << script << "" +_strTitle + ""; } std::string HTML::strRedirect(URL& url) { return "top.location.href='" + static_cast(url) + "';"; } std::string HTML::strHTMLBegin() { static const std::string r("\r\n\r\n"); return r; } std::string HTML::strHTMLEnd() { static const std::string r(""); return r; } std::string HTML::strHTMLPasswordSubmitButtons(std::string name) { return "" "" "
"; } HTML& HTML::FloatingAdvertisement(HTML& s, const char* content, const char* title) { s << "
" "
" << title << "
" << content << "
"; return s; } std::string HTML::strAHREF(const std::string& href, const std::string& label) { return ""+(label.empty()? href:label) + ""; } const std::string& HTML::strSTYLE() { static const std::string r( ""); return r; } const std::string& HTML::strSCRIPT() { static const std::string r( // //document.onreadystatechange=new Function("if(document.readyState=='complete')InitOnmouseover('H1,DL',DoCollapsableHeader);"); // "" ); return r; } ///////////////////////////////////////////////////////////////////////////////////////// // // CStatistics // CStatistics::CStatistics() : _disabled(false) { ::time(&_start_time); disable(0); } std::string CStatistics::getHtmlFormOfDisabled(std::string strName, std::string strInclude) { return ""; } std::string CStatistics::getHtmlFormOfResetAll(std::string strName, std::string strInclude) { return ""; } long CStatistics::disable(long d) { static const std::string key("Statistics disabled (1-disabled)"); critical_section guard(_cs); (void) guard; if(d>=0) _map[key] =(_disabled = (d>0))? 1:0; return (long) _map[key]; } statistics CStatistics::assign(const char *key, long value) { if(_disabled) return long_statistics_invalid(); critical_section guard(_cs); (void) guard; return _map[key] =value; } void CStatistics::minmax(std::string key, long value) { if(_disabled) return; critical_section guard(_cs); (void) guard; _map[key+". Minimum value"].less_equal(value); _map[key+". Maximum value"].greater_equal(value); } // // sets key+last_fixed, key+minimum, key+maximum, key+integral, key+average, key+number_of_occurences // void CStatistics::full(const std::string& key, long value) { if(_disabled) return; critical_section guard(_cs); (void) guard; _map[key+". Last fixed value"].assign(value); _map[key+". Minimum value"].less_equal(value); _map[key+". Maximum value"].greater_equal(value); _map[key+". Integral value"] +=value; _map[key+". Number of requests"] +=1; _map[key+". Average value"] =_map[key+". Integral value"] / _map[key+". Number of requests"]; } // // counts +-value of key+last_fixed_value, and key+maximum_value. Cannot go down of zerro // void CStatistics::count(const std::string& key, long value=+1) { if(_disabled) return; critical_section guard(_cs); (void) guard; long_statistics& last = _map[key+". Last fixed value"]; last +=value; if(value >0) _map[key+". Maximum value"].greater_equal(long(last)); else if(long(last) <0) last =0; } statistics CStatistics::greater_equal(const char *key, long value) { if(_disabled) return long_statistics_invalid(); critical_section guard(_cs); (void) guard; return _map[key].greater_equal(value); } statistics CStatistics::less_or_equal(const char *key, long value) { if(_disabled) return long_statistics_invalid(); critical_section guard(_cs); (void) guard; return _map[key].less_equal(value); } statistics CStatistics::maximum(const char *key, long value) { if(_disabled) return long_statistics_invalid(); critical_section guard(_cs); (void) guard; return _map[key].maximum(value); } statistics CStatistics::minimum(const char *key, long value) { if(_disabled) return long_statistics_invalid(); critical_section guard(_cs); (void) guard; return _map[key].minimum(value); } statistics CStatistics::increment(const char *key) { if(_disabled) return long_statistics_invalid(); critical_section guard(_cs); (void) guard; return ++(_map[key]); } statistics CStatistics::decrement(const char *key) { if(_disabled) return long_statistics_invalid(); critical_section guard(_cs); (void) guard; return --(_map[key]); } // // read-only acccess to statistics // void CStatistics::reset() { critical_section guard(_cs); (void) guard; long num_resets = (long) _map["Number (and time of last) statistics resets"]; for(TMap::iterator iter=_map.begin() ; iter != _map.end() ; ++iter) iter->second.reset(); assign("Number (and time of last) statistics resets", num_resets+1); } statistics CStatistics::reset(const char *key) { critical_section guard(_cs); (void) guard; return _map[key].reset(); } statistics CStatistics::operator[](const char *key) { critical_section guard(_cs); (void) guard; return _map[key]; } // // stream/string outputs // std::ostream& CStatistics::getStatistics(std::ostream&os, const char*pszBOL,const char*pszDelim1, const char*pszDelim2, const char*pszEOL) { critical_section guard(_cs); (void) guard; for(TMap::iterator iter =_map.begin() ; iter != _map.end() ; ++iter) { TMap::value_type& val = *iter; os << pszBOL << val.first << pszDelim1; if(val.second.is_valid()) os << (long) val.second << pszDelim2 << time_to_string(val.second.changed_on()) << pszEOL; else os << "reset value" << pszDelim2 << "value has not been changed yet" << pszEOL; } return os; } std::ostream& CStatistics::getTimeInformation(std::ostream& os, const char* pszBOL, const char* pszDelim, const char* pszEOL) { time_t loctime; ::time(&loctime); long secs = loctime - _start_time; // total long totalmins = secs /60L; // total long totalhours = secs/ (60L * 60L); // total long days = secs / (24L *60L *60L); // total long hours = totalhours - days*24L; long mins = totalmins - totalhours*60L; secs -= totalmins *60L; os << pszBOL << "Time of starting " << pszDelim << time_to_string(_start_time) << pszEOL << pszBOL << "Current Time " << pszDelim << time_to_string(loctime) << pszEOL << pszBOL << "Since start elapsed " << pszDelim << days << " days, " << hours << " hours, " << mins << " minutes, and " << secs << " seconds" << pszEOL; return os; } std::ostream& CStatistics::getStatisticsAsPartOfHtmlTable(std::ostream& os) { getStatistics(os, "", "", "", ""); return os; } std::ostream& CStatistics::getStatisticsAsHtml(std::ostream& os) { getTimeInformation(os, "", "", "
"); os << ""; getStatisticsAsPartOfHtmlTable(os); os << "
NameValueTime of last fixation
" "

NOTE: Whereas the Windows ® operating system is a preemptive " "one, timing values may include the time the process itself or a working thread of the process had been " "waiting for processor time, and thereupon should be considered as real-world real-time values

"; return os; } std::ostream& CStatistics::getStatistics(std::ostream& os) { return getStatistics(getTimeInformation(os), ""," = ",", time of last fixation: ", "\r\n"); } std::string CStatistics::getStatistics(const char*pszBOL,const char*pszDelim1,const char*pszDelim2,const char*pszEOL) { std::ostringstream s; getStatistics(s, pszBOL, pszDelim1, pszDelim2, pszEOL); return s.str(); } std::string CStatistics::getTimeInformation(const char* pszBOL, const char* pszDelim, const char* pszEOL) { std::ostringstream s; getTimeInformation(s, pszBOL, pszDelim, pszEOL); return s.str(); } std::string CStatistics::getStatisticsAsHtml() { HTML s; return (std::string) getStatistics(s); } std::string CStatistics::time_to_string(time_t t, const char* pszFormat) { return t==0? std::string("value has not been changed yet") : CTimer::strLocalTime(t, pszFormat); } ///////////////////////////////////////////////////////////////////////////////////////// // // RegistryKey // RegistryKey::RegistryKey(const RegistryKey& copy, const char *szSubFolderName, REGSAM sAccess, DWORD option, LPSECURITY_ATTRIBUTES psSecur) { Init(); operator= (copy); if(szSubFolderName != NULL) Open(NULL, szSubFolderName, sAccess, option, psSecur); } RegistryKey::RegistryKey(HKEY hParentKey, const char *szSubFolderName, REGSAM sAccess, DWORD option, LPSECURITY_ATTRIBUTES psSecur) { Init(); Open(hParentKey, szSubFolderName, sAccess, option, psSecur); } bool RegistryKey::Open(HKEY hParentKey, const char *szSubFolderName, REGSAM sAccess, DWORD dwOption, LPSECURITY_ATTRIBUTES psSecur) { if((m_hParentKey = hParentKey) ==0) m_hParentKey = m_hKey; else Close(); // reusing this class m_sAccess = sAccess; if(ERROR_SUCCESS != (m_err = ::RegCreateKeyEx(m_hParentKey, szSubFolderName, 0, NULL, // "", // class name ?? is it subkey name in hParentKey\szSubFolderName ?? dwOption, sAccess, psSecur, // *security &m_hKey, &m_dwDisp))) return false; ::RegQueryInfoKey(m_hKey, 0, 0, 0, &iNumSubKeys, &iMaxSubKeyLen, &iMaxClassLen, &iValues, &iMaxValueNameLen, &iMaxValueLen,&iSecurityDescriptor, &LastWriteTime); Init(szSubFolderName, dwOption, sAccess, psSecur); return true; } void RegistryKey::Close() { if(m_hKey != 0) ::RegCloseKey(m_hKey); Init(); } RegistryKey& RegistryKey::operator= (const RegistryKey& from) { Close(); m_hKey = from.m_hKey; m_hParentKey = from.m_hParentKey; m_dwDisp = from.m_dwDisp; m_err = from .m_err; Init(from.m_strSubFolderName.c_str(), from.m_dwOption, from.m_sAccess, from.m_psSecur); return *this; } // deletes this key and all the data it contens bool RegistryKey::Delete() { DeleteAllKeys(); DeleteAllValues(); if(ERROR_SUCCESS != ::RegDeleteKey(m_hParentKey, m_strSubFolderName.c_str())) return false; Init(); return true; } // deletes all the values or this key bool RegistryKey::DeleteAllValues() { char szValue[MAX_PATH]; // MAX_VALUE_NAME]; DWORD cValue = MAX_PATH; //MAX_VALUE_NAME; for(bool res = true ; ERROR_SUCCESS ==::RegEnumValue(m_hKey, 0, szValue, &cValue, 0,0,0,0) ; ) res &= (ERROR_SUCCESS == ::RegDeleteValue(m_hKey, szValue)); return res; // all of the values were deleted successfuly? } // deletes the subkey(s) (including underlaying data) bool RegistryKey::DeleteAllKeys() { char chKey[MAX_PATH]; for(bool res=true ; ERROR_SUCCESS == ::RegEnumKey(m_hKey, 0, chKey, MAX_PATH) ; ) { RegistryKey subKey(*this, chKey); res &= subKey.Delete(); } return res; // all of the keys were deleted successfuly? } // // get/set/delete value suit // bool RegistryKey::SetValue(const char* szValName, int iValue) { return SetValue(szValName, reinterpret_cast(&iValue), sizeof(iValue), REG_DWORD); } bool RegistryKey::SetValue(const char* szValName, const char* pValue) { return SetValue(szValName, reinterpret_cast(pValue), strlen(pValue), REG_SZ); } bool RegistryKey::SetValue(const char* szValName, const BYTE* pValue, int iValueLen, DWORD dwValType) { if(m_hKey == NULL || ERROR_SUCCESS != (m_err = ::RegSetValueEx(m_hKey, szValName, 0, dwValType, pValue, iValueLen))) return false; //throw m_err; return true; } // // // RegistryKey::Value::Value(DWORD tp, const std::vector& buf, int len) : type_(tp) , value(buf) { if(len >=0) value.resize(len, char()); } RegistryKey::Value& RegistryKey::Value::operator=(const RegistryKey::Value& x) { type_ = x.type(); value.assign(x.value.begin(), x.value.end()); return *this; } std::ostream& RegistryKey::Value::output(std::ostream& os, DWORD dwType, const unsigned char* bVal, int lenVal) { if(bVal ==0 || lenVal ==0) return os; std::ios_base::fmtflags oldfl = os.flags(); switch(dwType) { case REG_BINARY: case REG_DWORD_BIG_ENDIAN: dump::dump_hex(os, &bVal[0], lenVal); break; case REG_DWORD: // case REG_DWORD_LITTLE_ENDIAN: //A 32-bit number. os << std::hex << *(DWORD*)(&bVal[0]); break; // case REG_QWORD: case REG_QWORD_LITTLE_ENDIAN: // os << std::hex << *(__int64*)(&bVal[0]); break; case REG_RESOURCE_LIST: os << "Resource list: "; dump::dump_hex(os, &bVal[0], lenVal); break; case REG_LINK: os << "A Unicode symbolic link: "; dump::dump_hex(os, &bVal[0], lenVal); break; case REG_EXPAND_SZ: { std::vector val(::ExpandEnvironmentStrings((const char*)bVal, 0, 0)); ::ExpandEnvironmentStrings((const char*)bVal, &val[0], val.size()); os << &val[0]; } break; case REG_SZ: os << bVal; break; case REG_MULTI_SZ: // An array of null-terminated strings, terminated by two null characters. vector for(const unsigned char* bEnd = bVal +lenVal ; bVal > ret; return ret; } bool RegistryKey::GetValue(const char* szValName, Value& val) const { if(m_hKey == 0) return val.clear() , false; val.type_= REG_NONE; DWORD dwType = REG_NONE; val.value.resize(iMaxValueLen); DWORD dwSize = val.value.size(); if(::RegQueryValueEx(m_hKey, szValName, 0, &dwType, &val.value[0], &dwSize) !=ERROR_SUCCESS) return false; val.type_= dwType; val.value.resize(dwSize); return true; } DWORD RegistryKey::GetDWORDValue(const char* szValName) const { DWORD dwVal=0xBADBAD; DWORD dwSize = sizeof dwVal; DWORD dwValType =REG_NONE; if(m_hKey != 0) ::RegQueryValueEx(m_hKey, szValName, 0, &dwValType, (unsigned char*)&dwVal, &dwSize); return dwValType == REG_DWORD ? dwVal : -1; } void RegistryKey::EnumerateKeys(std::vector& subkeys) const { if(m_hKey ==0) return; std::vector sName(iMaxSubKeyLen +MAX_PATH); for(DWORD dwIndex=0 ; dwIndex < iNumSubKeys ; ++dwIndex) { DWORD lenName = sName.size(); // size of value name buffer FILETIME ft; if(ERROR_SUCCESS !=::RegEnumKeyEx( m_hKey, // handle to key to enumerate dwIndex, // subkey index &sName[0], // subkey name &lenName, // size of subkey buffer 0, // reserved 0, // class string buffer 0, // size of class string buffer &ft)) // last write time continue; subkeys.push_back(std::string(&sName[0], lenName)); } } std::ostream& RegistryKey::getInformationAsHtml(std::ostream& os, const char* pszNamePrefix) const { os << "" ""; EnumerateValuesAsHtmlTBODY(os); std::vector subkeys; EnumerateKeys(subkeys); for(int i = 0 ; i < subkeys.size() ; ++i) { RegistryKey reg(m_hKey, subkeys[i].c_str(), m_sAccess); os << ""; } os << "
" << pszNamePrefix << m_strSubFolderName << "Modified: " << CTimer::FileTimeAsHtml(LastWriteTime) << "
"; if(reg.Valid()) reg.getInformationAsHtml(os, "1 "); else os << "Error openning registry key " << subkeys[i] << ". " << reg.LastError(); os << "
"; return os; } // // helper to read a value at once // std::string RegistryKey::GetStringValue(HKEY hParentKey, const std::string& strSubFolderName, const char *szValName) { RegistryKey rk(hParentKey, strSubFolderName.c_str(), KEY_QUERY_VALUE, REG_OPTION_NON_VOLATILE, 0); return (std::string) rk.GetValue(szValName); } /* typedef std::map Values; void EnumerateValues(Values& m) const { if(m_hKey ==0) return; std::vector sName(iMaxValueNameLen); std::vector bVal(iMaxValueLen); for(DWORD dwIndex=0 ; dwIndex < iValues ; ++dwIndex) { DWORD lenName = sName.size(); // size of value name buffer DWORD lenVal = bVal.size(); // size of value name buffer DWORD dwType = REG_NONE; if(ERROR_SUCCESS !=::RegEnumValue(m_hKey, dwIndex, &sName[0], &lenName, 0, &dwType, &bVal[0], &lenVal)) continue; m.insert(std::pair(std::string(&sName[0], lenName), Value(dwType, bVal, lenVal))); } } std::ostream& EnumerateValues(std::ostream& os, const char* bol, const char *del, const char* eol) const { Values v; EnumerateValues(v); for(Values::const_iterator it = v.begin() ; it != v.end() ; ++it) { os << bol << it->first << del ; it->second.output(os) << eol; } return os; } */ void RegistryKey::Init() { m_hKey = NULL; m_dwDisp = 0; m_err = ERROR_SUCCESS; iNumSubKeys=0; iMaxSubKeyLen=0; iMaxClassLen=0; iValues=0; iMaxValueNameLen=0; iMaxValueLen=0; iSecurityDescriptor =0; } void RegistryKey::Init(const char *szSubFolderName, DWORD dwOption, REGSAM sAccess, LPSECURITY_ATTRIBUTES psSecur) { m_strSubFolderName = szSubFolderName; m_dwOption = dwOption; m_sAccess = sAccess; m_psSecur = psSecur; } ///////////////////////////////////////////////////////////////////////////////////////// // // ThisComputer // std::ostream& ThisComputer::OSInfo(std::ostream& s, const char*bol, const char*dm1, const char*dm2, const char*eol) { #if(WINVER < 0x0500) //!defined(VER_NT_WORKSTATION) #define VER_NT_WORKSTATION 0x0000001 #define VER_NT_DOMAIN_CONTROLLER 0x0000002 #define VER_NT_SERVER 0x0000003 #define VER_SERVER_NT 0x80000000 #define VER_WORKSTATION_NT 0x40000000 #define VER_SUITE_SMALLBUSINESS 0x00000001 #define VER_SUITE_ENTERPRISE 0x00000002 #define VER_SUITE_BACKOFFICE 0x00000004 #define VER_SUITE_COMMUNICATIONS 0x00000008 #define VER_SUITE_TERMINAL 0x00000010 #define VER_SUITE_SMALLBUSINESS_RESTRICTED 0x00000020 #define VER_SUITE_EMBEDDEDNT 0x00000040 #define VER_SUITE_DATACENTER 0x00000080 #define VER_SUITE_SINGLEUSERTS 0x00000100 #define VER_SUITE_PERSONAL 0x00000200 #define VER_SUITE_SERVERAPPLIANCE 0x00000400 typedef struct _OSVERSIONINFOEX { DWORD dwOSVersionInfoSize; DWORD dwMajorVersion; DWORD dwMinorVersion; DWORD dwBuildNumber; DWORD dwPlatformId; char szCSDVersion[ 128 ]; WORD wServicePackMajor; WORD wServicePackMinor; WORD wSuiteMask; BYTE wProductType; BYTE wReserved; } OSVERSIONINFOEX; OSVERSIONINFOEX vi; #endif ::ZeroMemory(&vi, sizeof OSVERSIONINFOEX); vi.dwOSVersionInfoSize = sizeof OSVERSIONINFOEX; if(!::GetVersionEx((OSVERSIONINFO *)&vi)) // GetVersionEx using the OSVERSIONINFOEX { vi.dwOSVersionInfoSize = sizeof OSVERSIONINFO; // ditto using OSVERSIONINFO if(!::GetVersionEx ( (OSVERSIONINFO *) &vi)) throw CRuntime_error("Source: GetVersion of OS", ::GetLastError()); } s << bol << "OS Platform" << dm1; if (vi.dwPlatformId == VER_PLATFORM_WIN32_NT) { if(vi.dwOSVersionInfoSize ==sizeof OSVERSIONINFOEX) { s << "Windows " << (vi.dwMajorVersion <= 4? "NT":(vi.dwMajorVersion == 5 && vi.dwMinorVersion > 0)? "XP":"2000") << ( vi.wProductType==VER_NT_WORKSTATION? " Professional": vi.wProductType==VER_NT_DOMAIN_CONTROLLER? " Domain Controller": vi.wProductType==VER_NT_SERVER? " Server": "") << dm2 << eol << bol << "Suite" << dm1 ; if(vi.wSuiteMask & VER_SUITE_DATACENTER) s << "Data Center. "; if(vi.wSuiteMask & VER_SUITE_ENTERPRISE) s << "Advanced Server. "; if(vi.wSuiteMask & VER_SUITE_BACKOFFICE) s << "Microsoft Backoffice. "; if(vi.wSuiteMask & VER_SUITE_SMALLBUSINESS) s << "Microsoft Small Business Server. "; if(vi.wSuiteMask & VER_SUITE_SMALLBUSINESS_RESTRICTED) s << "Microsoft Small Business Server - Restrictive Client License. "; if(vi.wSuiteMask & VER_SUITE_TERMINAL) s << "Terminal Server. "; if(vi.wSuiteMask & VER_SUITE_PERSONAL) s << "Workstation Personal. "; s << dm2 << eol; } else // there is no direct way of telling is it workstation or server version. There we need to check in the registry. { if(vi.dwMajorVersion <= 4) s << "Windows NT"; else if(vi.dwMajorVersion == 5 && vi.dwMinorVersion == 0) s << "Windows 2000"; else if (vi.dwMajorVersion == 5 && vi.dwMinorVersion > 0) s << "Windows XP (Whistler)"; s << " - " << RegistryKey::GetStringValue(HKEY_LOCAL_MACHINE, "System\\CurrentControlSet\\Control\\ProductOptions", "ProductType") << eol; } s << bol << "Version" << dm1 << vi.dwMajorVersion << "." << vi.dwMinorVersion << dm2 << eol << bol << "Build" << dm1 << vi.dwBuildNumber << dm2 << eol ; } else if (vi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) { if ((vi.dwMajorVersion > 4) || ((vi.dwMajorVersion == 4) && (vi.dwMinorVersion > 0))) { s << (vi.dwMinorVersion < 90? "Windows 98":"Windows ME"); } else s << "Windows 95"; s << dm2 << eol << bol << "Version" << dm1 << vi.dwMajorVersion << "." << vi.dwMinorVersion << dm2 << eol << bol << "Build" << dm1 << (DWORD)(LOBYTE(LOWORD(vi.dwBuildNumber))) << dm2 << eol ; } else if (vi.dwPlatformId == VER_PLATFORM_WIN32s) s << "Windows 32s or Windows 3.1" << dm2 << eol; else s << "??? " << vi.dwPlatformId << dm2 << eol; if(vi.szCSDVersion[0] !='\0') s << bol << "Service Pack" << dm1 << vi.szCSDVersion << dm2 << "vers." << vi.wServicePackMajor << "." << vi.wServicePackMinor << eol; return s; } std::ostream& ThisComputer::CPUFromRegistryInfo(std::ostream& s, const char*bol, const char*dm1, const char*dm2, const char*eol, const char*separator) { RegistryKey regCPUs(HKEY_LOCAL_MACHINE, "Hardware\\Description\\System\\CentralProcessor\\", KEY_READ); std::vector vecCPUs; regCPUs.EnumerateKeys(vecCPUs); for(int i = 0 ; i < vecCPUs.size() ; ++i) { RegistryKey regCPU(regCPUs, vecCPUs[i].c_str(), KEY_QUERY_VALUE); if(!regCPU.Valid()) continue; s << separator << bol << "CPU Identifier" << dm1 << regCPU.GetStringValue("Identifier") << dm2 << "CPU " < path(MAX_PATH *2, 0); if(::EnumProcessModules(hProc, &hMod, sizeof HMODULE, &cbMods)) ::GetModuleBaseName(hProc, hMod, &path[0], path.size()); s < vecMods(cbMods /= sizeof HMODULE); if(::EnumProcessModules(hProc, &hMod, sizeof HMODULE, &cbMods)) { s <0) s << bol << std::hex << "0x" < ids(4000); // reserv for 4000 processes DWORD cb; ::EnumProcesses(&ids[0], ids.size(), &cb); cb /=sizeof DWORD; for(int i = 0 ; i < cb ; ++i) ProcessInfo(s, ids[i], bol, dm1, dm2, eol); } #endif std::ostream& ThisComputer::MisceleniousInfo(std::ostream& s, const char*bol, const char*dm1, const char*dm2, const char*eol) throw(CRuntime_error) { char szBuffer[MAX_COMPUTERNAME_LENGTH + 1]; DWORD dwSize = sizeof szBuffer; // // TODO use GetComputerNameEx for Windows 2000 // if(::GetComputerName (szBuffer, &dwSize)) s << bol << "Computer Name" << dm1 << szBuffer << dm2 << "The NetBIOS name of the computer" << eol; char *pszDomainName = ::getenv("USERDOMAIN"); if(pszDomainName !=0) s << bol << "Domain Name" << dm1 << pszDomainName << dm2 << "The Domain name (taking from environment)" << eol; //"HKLM\\SOFTWARE\\Microsoft\Windows NT\\CurrentVersion\\Winlogon\\CachePrimaryDomain" char *pszLogonServer = ::getenv("LOGONSERVER"); if(pszLogonServer !=0) s << bol << "Logon Server Name" << dm1 << pszLogonServer << dm2 << "DNS server name (taking from environment)" << eol; dwSize = sizeof szBuffer; if(::GetUserName(szBuffer, &dwSize)) s << bol << "User Name" << dm1 << szBuffer << dm2 << "The name of the user currently logged onto the system" << eol; char szVal[MAX_PATH]; if((DWORD)::GetLocaleInfo (LOCALE_SYSTEM_DEFAULT, LOCALE_SENGCOUNTRY, szVal, sizeof szVal) <= sizeof szVal) s << bol << "Country" << dm1 << szVal << dm2 << "The country/region set for the system" << eol; if((DWORD)::GetLocaleInfo (LOCALE_SYSTEM_DEFAULT, LOCALE_SENGLANGUAGE, szVal, sizeof szVal) <= sizeof szVal) s << bol << "Language" << dm1 << szVal << dm2 << "The language set for the system" << eol; TIME_ZONE_INFORMATION info; if(TIME_ZONE_ID_INVALID != ::GetTimeZoneInformation(&info)) s << bol << "Time Zone" << dm1 << (char*)_bstr_t(info.StandardName) << dm2 << eol; return s; } std::ostream& ThisComputer::NetworkInfo(std::ostream& s, const char*bol, const char*dm1, const char*dm2, const char*eol, const char* separator) throw(CRuntime_error) { // // IP addresses // char szHostName[MAX_PATH]; if(::gethostname(szHostName, sizeof szHostName) == 0) { s << bol << "Host name" << dm1 << szHostName << dm2 << "The computer may have more than IP addresses. See gethostname for more information" << eol; struct hostent *pHost = ::gethostbyname(szHostName); // Get host adresses if(pHost !=0) { s << bol << pHost->h_name << dm1; for(int i = 0 ; pHost->h_addr_list[i] !=0 ; ++i) { s << (i >0? "
" : ""); for(int j = 0 ; j < pHost->h_length ; ++j) s << (j >0? "." : "") << (unsigned int)((unsigned char*)pHost->h_addr_list[i])[j]; s << ""; } s << dm2; for(i = 0 ; pHost->h_aliases[i] !=0 ; ++i) s << (i >0? "
" : "") << "Alias " << pHost->h_aliases[i] <<""; s << eol; } } RegistryKey regNetworkCards(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards\\", KEY_READ); std::vector cards; regNetworkCards.EnumerateKeys(cards); for(int i = 0 ; i < cards.size() ; ++i) { RegistryKey regNetworkCard(regNetworkCards, cards[i].c_str(), KEY_QUERY_VALUE); if(!regNetworkCard.Valid()) continue; s << separator << bol << "Network card" << dm1 << regNetworkCard.GetStringValue("Description") << dm2 << "Card " << cards[i]; std::string strServiceName = regNetworkCard.GetStringValue("ServiceName"); if(strServiceName.empty()) { s << ". The card is not in use" << eol; continue; } RegistryKey reg(HKEY_LOCAL_MACHINE, ("SYSTEM\\CurrentControlSet\\Services\\"+strServiceName+"\\Parameters\\TcpIp").c_str(), KEY_QUERY_VALUE); s << eol << bol << "DHCP IP address" << dm1 << reg.GetStringValue("DhcpIPAddress") << dm2 << "Taken from registry for aforementioned network card" << eol << bol << "IP address" << dm1 << reg.GetStringValue("IPAddress") << dm2 << "..ditto" << eol << bol << "Enable DHCP" << dm1 << reg.GetDWORDValue("EnableDHCP") << dm2 << "..ditto" << eol << bol << "DHCP server" << dm1 << reg.GetStringValue("DhcpServer") << dm2 << "..ditto" << eol << bol << "DHCP Default Gateway" << dm1 << reg.GetStringValue("DhcpDefaultGateway") << dm2 << "..ditto" << eol << bol << "Subnet mask" << dm1 << reg.GetStringValue("DhcpSubnetMask") << dm2 << "..ditto" << eol ; } return s; } std::ostream& ThisComputer::Information(std::ostream& s) { s << "" ""; MisceleniousInfo(s, ""); s << ""; OSInfo(s, ""); s << ""; CPUInfo(s, ""); CPUFromRegistryInfo(s, "", ""); s << ""; MemoryInfo(s, ""); #ifdef _PSAPI_H_ // PSAPI is not a part of WINDOWS but a SDK dll s << ""; ProcessesInfo(s, "", ""); #endif s << ""; NetworkInfo(s, "", ""); s << ""; VolumesInfo(s, "", "", "v", " "); s<< "" ""; return s << "
Computer:
", "", "", "
Operating System:
", "", "", "
CPU(s):
", "", "", "
", "", "", "
Memory:
", "", "", "
Processes:
", "", "", "
Network:
", "", "", "
Volumes:
", "", "", "
Internet explorer:
"; InternetExplorer::getFullInformationAsHtml(s); s << "
"; } ///////////////////////////////////////////////////////////////////////////////////////// // // FileInformation // /* FileInformation& FileInformation::operator=(const FileInformation& x) { ::memcpy(static_cast(this), static_cast(&x), sizeof FILE_INFORMATION_STRUCTURE); return *this; } bool FileInformation::operator==(const FILE_INFORMATION_STRUCTURE& x) const { return ::memcmp(static_cast(this), &x, sizeof FILE_INFORMATION_STRUCTURE) ==0; } */ bool FileInformation::init(HMODULE hFile) { char filename[_MAX_PATH]; // get module file name return ::GetModuleFileName(hFile, filename, _MAX_PATH) <= 0? false : init(filename); } bool FileInformation::init(const char *pszFilename) { zerroing(); HANDLE h=::FindFirstFile(pszFilename, static_cast(this)); return h==INVALID_HANDLE_VALUE? false : (::FindClose(h) !=0); } std::ostream& FileInformation::getFileInformationAsHtml(std::ostream& os) { os<<""; if(!exist()) return os << "
" << HTML::escape(cFileName) << "
Information on file is not available
"; os<<"NameValueComment" "Created" << CTimer::FileTimeAsHtml(ftCreationTime) << "Not all file systems can record these values and not all file systems record them in the same manner. F.e., " "on Windows NT FAT, create time has a resolution of 10 milliseconds, write time has a resolution of 2 seconds, and access time has a resolution of 1 day " "(really, the access date). On NTFS, access time has a resolution of 1 hour. FAT records times on disk in local time, while NTFS records times on disk in UTC, " "so it is not affected by changes in time zone or daylight saving time" "Modified" << CTimer::FileTimeAsHtml(ftLastWriteTime) << "" "Accessed" << CTimer::FileTimeAsHtml(ftLastAccessTime) << "" ; if(nFileSizeHigh !=0) { long double fileSize = double(nFileSizeHigh)*(double(ULONG_MAX)+1) +double(nFileSizeLow); os << "Size" << fileSize << "bytes"; } else { std::locale old_locale(os.imbue(std::locale("American_USA.1252"))); // change locale to the USA one to set thousands separator to ',' os << std::fixed << "Size" << nFileSizeLow << "bytes"; os.imbue(old_locale); // restore locale } os<<"Alternate name" << (cAlternateFileName[0]==0?" ":cAlternateFileName) << "short 8.3 (filename.ext) file name format (MS-DOS name)" // "Volume Serial Number" << dwVolumeSerialNumber << "volume where this file resides in" // "Number of links" << nNumberOfLinks << "number of links to this file. For the FAT file system this member is always 1" // "System Index" << std::hex << nFileIndexHigh << std::setfill('0') << std::setw(8) << nFileIndexLow << " (hex) unique ID the system assigned to this file on opening" "Attributes:" "Archive" "" << attribute(FILE_ATTRIBUTE_ARCHIVE) << "marked by an application for backup or removal" "Readonly" "" << attribute(FILE_ATTRIBUTE_READONLY) << "applications can read the file but cannot write to or delete it" "System" "" << attribute(FILE_ATTRIBUTE_SYSTEM) << "part of (or is used exclusively by) the operating system" "Compressed" "" << attribute(FILE_ATTRIBUTE_COMPRESSED) << "data in file or directory is compressed" "Directory" "" << attribute(FILE_ATTRIBUTE_DIRECTORY) << " " "Encrypted" "" << attribute(FILE_ATTRIBUTE_ENCRYPTED) << "data in the file or directory is encrypted" "Hidden" "" << attribute(FILE_ATTRIBUTE_HIDDEN) << "not visible in an ordinary directory listing" "Normal" "" << attribute(FILE_ATTRIBUTE_NORMAL) << "file has no other attributes. This attribute is valid only if used alone" "Offline" "" << attribute(FILE_ATTRIBUTE_OFFLINE) << "data is not immediately available (the file data has been physically moved to offline storage)" "Reparse point""" << attribute(FILE_ATTRIBUTE_REPARSE_POINT) << "file has an associated reparse point" "Sparse file" "" << attribute(FILE_ATTRIBUTE_SPARSE_FILE) << "file is a sparse file" "Temporary" "" << attribute(FILE_ATTRIBUTE_TEMPORARY) << "file is being used for temporary storage" "" ; return os; } std::ostream& FileInformation::getFileInformation(std::ostream& os) { os <<"File name: " << cFileName << "\r\n"; if(!exist()) { os << "File does not exist\r\n"; return os; } long double fileSize = double(nFileSizeHigh)*(double(ULONG_MAX)+1) +double(nFileSizeLow); os<<"Modified: " << CTimer::FileTimeAsHtml(ftLastWriteTime) << "\r\n" "Accessed: " << CTimer::FileTimeAsHtml(ftLastAccessTime) << "\r\n" ; os<<"Size (bytes): " << std::setprecision(0) << fileSize << "\r\n" "Alternate name: " << (cAlternateFileName[0]==0?"":cAlternateFileName) << "; short 8.3 (filename.ext) file name format (MS-DOS name)\r\n" // "Volume Serial Number: " << dwVolumeSerialNumber << "; volume where this file resides in\r\n" // "Number of links: " << nNumberOfLinks << "; number of links to this file. For the FAT file system this member is always 1\r\n" // "System Index (hex): " << nFileIndexHigh << std::setfill('0') << std::setw(8) << nFileIndexLow << "; unique ID the system assigned to this file on opening\r\n" "Attributes:\r\n" " Archive " << attribute(FILE_ATTRIBUTE_ARCHIVE) << "; marked by an application for backup or removal\r\n" " Readonly " << attribute(FILE_ATTRIBUTE_READONLY) << "; applications can read the file but cannot write to or delete it\r\n" " System " << attribute(FILE_ATTRIBUTE_SYSTEM) << "; part of (or is used exclusively by) the operating system\r\n" " Compressed " << attribute(FILE_ATTRIBUTE_COMPRESSED) << "; data in file or directory is compressed\r\n" " Directory " << attribute(FILE_ATTRIBUTE_DIRECTORY) << "\r\n" " Encrypted " << attribute(FILE_ATTRIBUTE_ENCRYPTED) << "; data in the file or directory is encrypted\r\n" " Hidden " << attribute(FILE_ATTRIBUTE_HIDDEN) << "; not visible in an ordinary directory listing\r\n" " Normal " << attribute(FILE_ATTRIBUTE_NORMAL) << "; file has no other attributes. This attribute is valid only if used alone\r\n" " Offline " << attribute(FILE_ATTRIBUTE_OFFLINE) << "; data is not immediately available (the file data has been physically moved to offline storage)\r\n" " Reparse point " << attribute(FILE_ATTRIBUTE_REPARSE_POINT) << "; file has an associated reparse point\r\n" " Sparse file " << attribute(FILE_ATTRIBUTE_SPARSE_FILE) << "; file is a sparse file\r\n" " Temporary " << attribute(FILE_ATTRIBUTE_TEMPORARY) << "; file is being used for temporary storage\r\n" ; return os; } ///////////////////////////////////////////////////////////////////////////////////////// // // FileVersion // bool FileVersion::init(HMODULE lib) { m_strFileName = ""; char filename[_MAX_PATH]; // get module file name return ::GetModuleFileName(lib, filename, _MAX_PATH) <= 0? false : init(filename); } bool FileVersion::init(const char* modulename) { zerroing(); m_strFileName = modulename; m_translation.charset = 1252; // default = ANSI code page DWORD dwDummyHandle; // will always be set to zero DWORD len = ::GetFileVersionInfoSize(const_cast(modulename), &dwDummyHandle); if(len <= 0) return false; delete [] m_pVersionInfo; m_pVersionInfo = new BYTE[len]; // allocate version info if(!::GetFileVersionInfo(const_cast(modulename), 0, len, m_pVersionInfo)) return false; LPVOID lpvi; UINT iLen; if(!::VerQueryValue(m_pVersionInfo, "\\", &lpvi, &iLen)) return false; ::memcpy(static_cast(this), lpvi, sizeof VS_FIXEDFILEINFO); // // Get translation info. Note: VerQueryValue could return a value > 4, in which case // mulitple languages are supported and VerQueryValue returns an array of langID/codepage // pairs and you have to decide which to use. // if(::VerQueryValue(m_pVersionInfo, "\\VarFileInfo\\Translation", &lpvi, &iLen) && iLen >= 4) m_translation = *(TRANSLATION*)lpvi; return dwSignature == VS_FFI_SIGNATURE; } std::string FileVersion::value(const char* lpKeyName) const { std::string sVal; if(m_pVersionInfo==0) return sVal; // To get a string value must pass query in the form // "\StringFileInfo\\keyname" std::ostringstream query; query << "\\StringFileInfo\\" << std::setfill('0') << std::hex << std::setw(4) << m_translation.langID << std::setw(4) << m_translation.charset << "\\" << lpKeyName; char *pVal; UINT iLenVal; if(::VerQueryValue(m_pVersionInfo, const_cast(query.str().c_str()), (LPVOID*)&pVal, &iLenVal)) sVal = pVal; return sVal; } std::string FileVersion::getValueAsHtml(const char* lpKeyName) const { std::string sVal(value(lpKeyName)); return sVal.empty() ? std::string(" ") : HTML::escape(sVal); } std::string FileVersion::getCreatedTimeAsHtml() const { // ft.dwLowDateTime = dwFileDateLS; // ft.dwHighDateTime = dwFileDateMS; return FileTime(dwFileDateLS, dwFileDateMS).AsHtml(); } std::string FileVersion::getCreatedTimeAsString() const { FILETIME ft={ dwFileDateLS, dwFileDateMS }; return CTimer::FileTimeAsString(ft); } std::string FileVersion::getFlagsInfoAsHtml() const { DWORD f = dwFileFlagsMask & dwFileFlags; std::string s("
    "); if(f & VS_FF_DEBUG) s += "
  • The file contains debugging information or is compiled with debugging features enabled
  • "; if(f & VS_FF_INFOINFERRED) s += "
  • The file's version structure was created dynamically (some of the version information may be incorrect)
  • "; if(f & VS_FF_PATCHED) s +="
  • The file has been modified and is not identical to the original shipping file of the same version number
  • "; if(f & VS_FF_PRERELEASE) s +="
  • The file is a development version, not a commercially released product
  • "; if(f & VS_FF_PRIVATEBUILD) s +="
  • The file was not built using standard release procedures. See Private Build for more info
  • "; if(f & VS_FF_SPECIALBUILD) s +="
  • The file was built by the original company using standard release procedures but is a variation " "of the normal file of the same version number. See Special Build for more info
  • "; return s +="
"; } std::ostream& FileVersion::getFlagsInfoAsHtml(std::ostream& s) const { DWORD f = dwFileFlagsMask & dwFileFlags; s << "
    "; if(f & VS_FF_DEBUG) s << "
  • The file contains debugging information or is compiled with debugging features enabled
  • "; if(f & VS_FF_INFOINFERRED) s << "
  • The file's version structure was created dynamically (some of the version information may be incorrect)
  • "; if(f & VS_FF_PATCHED) s <<"
  • The file has been modified and is not identical to the original shipping file of the same version number
  • "; if(f & VS_FF_PRERELEASE) s <<"
  • The file is a development version, not a commercially released product
  • "; if(f & VS_FF_PRIVATEBUILD) s <<"
  • The file was not built using standard release procedures. See Private Build for more info
  • "; if(f & VS_FF_SPECIALBUILD) s <<"
  • The file was built by the original company using standard release procedures but is a variation " "of the normal file of the same version number. See Special Build for more info
  • "; return s << "
"; } // // stream/string output // std::ostream& FileVersion::getFileVersionAsHtml(std::ostream& os) const { DWORD f = dwFileFlagsMask & dwFileFlags; os<<"" ""; if(!valid()) return os << "
" << m_strFileName << "
Version information is not available
"; os<<"NameValue" "Created" "" << getCreatedTimeAsString() << "" "Flags" "" << getFlagsInfoAsHtml() << "" "File Description" << getValueAsHtml("FileDescription")<< "" "Original Filename" << getValueAsHtml("OriginalFilename")<< "" "Production Name" << getValueAsHtml("ProductName") << "" "Production Version" << getValueAsHtml("ProductVersion") << "" "File Version" << getValueAsHtml("FileVersion") << "" "Internal Name" << getValueAsHtml("InternalName") << "" "Company Name" << getValueAsHtml("CompanyName") << "" "Comments" << getValueAsHtml("Comments") << "" "Legal Copyright" << getValueAsHtml("LegalCopyright") << "" "Legal Trademarks" << getValueAsHtml("LegalTrademarks")<< ""; if(f & VS_FF_PRIVATEBUILD) os << "Private Build" << getValueAsHtml("PrivateBuild") << ""; if(f & VS_FF_SPECIALBUILD) os << "Special Build" << getValueAsHtml("SpecialBuild") << ""; return os << ""; } std::ostream& FileVersion::getFileVersion(std::ostream& os) const { DWORD f = dwFileFlagsMask & dwFileFlags; os << "File name: " << m_strFileName << "\r\n" "Created: " << getCreatedTimeAsHtml() << "\r\n" "Flags: " << (dwFileFlagsMask & dwFileFlags) << "\r\n" "File Description: " << value("FileDescription") << "\r\n" "Original Filename: " << value("OriginalFilename") << "\r\n" "Production Name: " << value("ProductName") << "\r\n" "Production Version: " << value("ProductVersion") << "\r\n" "File Version: " << value("FileVersion") << "\r\n" "Internal Name: " << value("InternalName") << "\r\n" "Company Name: " << value("CompanyName") << "\r\n" "Comments: " << value("Comments") << "\r\n" "Legal Copyright: " << value("LegalCopyright") << "\r\n" "Legal Trademarks: " << value("LegalTrademarks") << "\r\n"; if(f&VS_FF_PRIVATEBUILD) os << "Private Build: " << value("PrivateBuild") << "\r\n"; if(f&VS_FF_SPECIALBUILD) os << "Special Build: " << value("SpecialBuild") << "\r\n"; return os; } ////////////////////////////////////////////////////////////////////////////////////////////// // /* // // starting Internet explorer // IDispatch* InternetExplorer::OnStartIE() { // // Create an instance of Internet Explorer 4.0 // HRESULT hr = ::CoCreateInstance(CLSID_InternetExplorer, NULL, CLSCTX_LOCAL_SERVER, IID_IWebBrowser2, (void**)&m_pIE); if(FAILED(hr)) return; // // Set up the event sink // BOOL bAdvised = AfxConnectionAdvise(m_pIE, DIID_DWebBrowserEvents2, m_pIE4Events->GetInterface(&IID_IUnknown), TRUE, &m_dwCookie); TRACE("Advise for DWebBrowserEvents2 %s\n", bAdvised ? "succeeded" : "failed"); m_pIE->put_Visible(VARIANT_TRUE); // Make IE4 visible _variant_t vtEmpty; m_pIE->Navigate(url.c_str(), &vtEmpty, &vtEmpty, &vtEmpty, &vtEmpty); } */ std::string InternetExplorer::PathToExecutable() { std::string str= RegistryKey::GetStringValue(HKEY_CLASSES_ROOT, "http\\shell\\open\\command"); if(!str.empty()) { if(str[0] =='\"') str.erase(0,1), str.erase(str.find('\"')); else str.erase(str.find(' ')); } return str; } std::ostream& InternetExplorer::getFullInformationAsHtml(std::ostream& os) { RegistryKey reg (HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Internet Explorer", KEY_QUERY_VALUE); RegistryKey reg2(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", KEY_QUERY_VALUE); os << "

Internet explorer (info from registry)

" "" // "" ""; reg.EnumerateValuesAsHtmlTBODY(os); os << ""; reg2.EnumerateValuesAsHtmlTBODY(os); os << "
Version" << HTML::escape(reg.GetStringValue("Version")) << " " // << HTML::escape(reg.GetStringValue("CustomizedVersion"))<< " " // << HTML::escape(reg2.GetStringValue("MinorVersion")) << "
HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Internet Explorer
HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings
"; std::string str = PathToExecutable(); FileInformation (str).getFileInformationAsHtml(os); FileVersion (str).getFileVersionAsHtml(os); return os; } #pragma comment(lib, "Version.lib") #pragma comment(lib, "WinInet.lib") #pragma comment(lib, "Shell32.lib") HINSTANCE InternetExplorer::ShellExecute(const URL& url) { return ::ShellExecute(0, "open", PathToExecutable().c_str(), url.c_str(), 0, SW_SHOWNORMAL); } void InternetExplorer::Open(const URL& url) throw(CRuntime_error) { HINSTANCE hinst = ShellExecute(url); DWORD err = (DWORD)hinst; if(err <=32) throw CRuntime_error("Description: Failed to launch Internet Explorer", err); } ///////////////////////////////////////////////////////////////////////////////////////// // // text_files_cache // void text_files_cache::clear() { critical_section mapGuard(s_csTextFiles); s_mapTextFiles.clear(); s_mapTextFilesInformation.clear(); } std::string text_files_cache::get_contents(const std::string& filename) { critical_section mapGuard(s_csTextFiles); // CS to guard map TmapTextFiles::iterator it = s_mapTextFiles.find(filename); if(it != s_mapTextFiles.end()) return it->second.c_str(); // make a copy of the string since it might be thread-crossing // mapGuard.unlock(); // release the map while preparing the file std::string strError = "File: " + filename + ""; FileInformation info(get_information(filename)); if(!info.exist()) throw CRuntime_error(strError.c_str(), "File does not exist"); HANDLE hFileRaw = ::CreateFile( filename.c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, (LPSECURITY_ATTRIBUTES) 0, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, (HANDLE) 0); strError += "
Notes: Error on reading"; DWORD dwSize, dwRead; handle hFile; if(hFileRaw ==INVALID_HANDLE_VALUE || !(hFile=hFileRaw).valid() || (dwSize = ::GetFileSize((HANDLE) hFile, 0)) == INVALID_FILE_SIZE) throw CRuntime_error(strError.c_str(), ::GetLastError()); // // TODO: implement read-out data chunk by chunk and pending input // std::string strData(dwSize, ' '); if(!::ReadFile((HANDLE) hFile, const_cast(strData.data()), dwSize, &dwRead, 0)) throw CRuntime_error(strError.c_str(), ::GetLastError()); // mapGuard.lock(); // hold up the map to cache.. s_mapTextFiles[filename] = strData; return std::string(strData.c_str()); } FileInformation text_files_cache::get_information(const std::string& filename) { critical_section mapGuard(s_csTextFiles); // CS to guard map TmapTextFilesInformation::iterator it = s_mapTextFilesInformation.find(filename); if(it != s_mapTextFilesInformation.end()) return it->second; FileInformation info(filename); if(info.exist()) s_mapTextFilesInformation[filename] = info; return info; } HTML& text_files_cache::getFileInformation(HTML& os, std::string filename) { TmapTextFilesInformation::iterator it; critical_section mapGuard(s_csTextFiles); // CS to guard map if(!filename.empty()) { if((it = s_mapTextFilesInformation.find(filename)) != s_mapTextFilesInformation.end()) it->second.getFileInformation(os) << "

Keyed as " << it->first << "

"; } else // dump all the info into stream { for(it=s_mapTextFilesInformation.begin() ; it != s_mapTextFilesInformation.end() ; ++it) it->second.getFileInformation(os) << "

Keyed as " << it->first << "

"; } return os; } std::string text_files_cache::getHtmlFormClearCache(std::string strName, std::string strInclude) { return ""; } ///////////////////////////////////////////////////////////////////////////////////////// // // text_file // text_file& text_file::replace(const std::string& f, const std::string& r, int n) { for(size_type pos =0 ; n-- >0 && (pos =find(f, pos)) != npos ; pos +=r.length()) static_cast(this)->replace(pos, f.length(), r); return *this; } text_file& text_file::replace_or_append(const std::string& f, const std::string& r) { size_type pos(find(f)); if(pos !=npos) static_cast(*this).replace(pos, f.length(), r); else static_cast(*this).append("
") .append(r); return *this; } text_file& text_file::insert(const std::string& f, const std::string& r, int n) { for(size_type pos =0 ; n-- >0 && (pos =find(f, pos)) != npos ; pos +=f.length() +r.length()) static_cast(this)->insert(pos +f.length(), r); return *this; } text_files_cache& text_file::get_cache() { static text_files_cache s_cache; return s_cache; } std::string text_file::text(const std::string& filename) throw(CRuntime_error) { return get_cache().get_contents(filename); } HTML& text_file::information(HTML& os, const std::string& filename) throw(CRuntime_error) { return get_cache().getFileInformation(os, filename); } ///////////////////////////////////////////////////////////////////////////////////////// // // CSV_parser // CSV_parser& CSV_parser::set_max_size(size_t m) throw(CRuntime_error) { if((_max_size = min(static_cast(*this).max_size(), m)) ==0) throw CRuntime_error("Source: CSV_parser", "set_max_size to zerro"); return *this; } CSV_parser& CSV_parser::add(const std::string& str) { // // if(_parsed >=max_size) // TODO: ?throw on _parsed == max_size? // for(unsigned p=0 , p0=0 ; (p = str.find(pszDelim, p0)) !=str.npos ; p0 =p +1) if(_parsed++ < _max_size) push_back(str.substr(p0, p - p0)); else { push_back(str.substr(p +1)); return *this; } // // there is no delimiters anymore in the string, so add the rest of string to CVS // if(p ==str.npos && _parsed < _max_size) { ++_parsed; push_back(str.substr(p0)); } return *this; } std::string CSV_parser::getAsString(unsigned beg, unsigned end) const { std::string s; for(end = min(end, size()) ; beg < end ; ++beg) { if(!s.empty()) s +=pszDelim; s +=value_of(beg); } return s; } ///////////////////////////////////////////////////////////////////////////////////////// // // implementation of WIN32_thread // WIN32_thread::~WIN32_thread() { terminate(3000); } DWORD WINAPI WIN32_thread_starter(LPVOID pthread_t) { WIN32_thread * p = reinterpret_cast(pthread_t); DWORD res = p->thread_body(); ::CloseHandle(p->m_hThread); p->m_hThread = 0; p->m_ThreadID = 0; return res; } void WIN32_thread::start(bool bYield) { if(m_hThread ==0) { m_hThread = ::CreateThread( NULL, // security attributes 0, // stack size (default value) reinterpret_cast (WIN32_thread_starter), // start point of thread this, // parameters (this pointer) 0, // flags &m_ThreadID); //#pragma message(MESSAGE_ANCHOR "Uncomment the following") if(bYield) ::Sleep(50); //::SwitchToThread(); } } void WIN32_thread::terminate(int mls_timeout) { if(m_ThreadID ==0) // restart the thread if it has not had been started yet return; ::PostThreadMessage(m_ThreadID, // thread identifier WM_QUIT, // message 0, // first message parameter 0); // second message parameter if(::WaitForSingleObject(m_hThread, mls_timeout) ==WAIT_TIMEOUT) ::TerminateThread(m_hThread, -01); // -1 exit code ::CloseHandle(m_hThread); m_hThread = 0; m_ThreadID = 0; } void WIN32_thread::post_WIN32_message(UINT msg, WPARAM wpar, LPARAM lpar) { if(m_ThreadID ==0) // restart the thread if it has not had been started yet start(true); // .. yield this thread to let posted thread run ::PostThreadMessage(m_ThreadID, msg, wpar, lpar); } UINT WIN32_thread::get_WIN32_message(MSG& msg, UINT first_message, UINT last_message) { ::memset(&msg, 0, sizeof msg); ::GetMessage(&msg, // message information 0, // handle to window (thread itself) first_message, last_message); return msg.message; }