/reporting/crashrpt/Utility.cpp

http://crashrpt.googlecode.com/ · C++ · 607 lines · 466 code · 107 blank · 34 comment · 53 complexity · d04c35f91afcb92ad1f6f5911454ecd0 MD5 · raw file

  1. /*************************************************************************************
  2. This file is a part of CrashRpt library.
  3. Copyright (c) 2003-2013 The CrashRpt project authors. All Rights Reserved.
  4. Use of this source code is governed by a BSD-style license
  5. that can be found in the License.txt file in the root of the source
  6. tree. All contributing project authors may
  7. be found in the Authors.txt file in the root of the source tree.
  8. ***************************************************************************************/
  9. // File: Utility.cpp
  10. // Description: Miscellaneous helper functions
  11. // Authors: mikecarruth, zexspectrum
  12. // Date:
  13. #include "stdafx.h"
  14. #include "Utility.h"
  15. #include "resource.h"
  16. #include "strconv.h"
  17. CString Utility::getAppName()
  18. {
  19. TCHAR szFileName[_MAX_PATH];
  20. GetModuleFileName(NULL, szFileName, _MAX_FNAME);
  21. CString sAppName; // Extract from last '\' to '.'
  22. sAppName = szFileName;
  23. sAppName = sAppName.Mid(sAppName.ReverseFind(_T('\\')) + 1)
  24. .SpanExcluding(_T("."));
  25. return sAppName;
  26. }
  27. CString Utility::GetModuleName(HMODULE hModule)
  28. {
  29. CString string;
  30. LPTSTR buf = string.GetBuffer(_MAX_PATH);
  31. GetModuleFileName(hModule, buf, _MAX_PATH);
  32. string.ReleaseBuffer();
  33. return string;
  34. }
  35. CString Utility::GetModulePath(HMODULE hModule)
  36. {
  37. CString string;
  38. LPTSTR buf = string.GetBuffer(_MAX_PATH);
  39. GetModuleFileName(hModule, buf, _MAX_PATH);
  40. TCHAR* ptr = _tcsrchr(buf,'\\');
  41. if(ptr!=NULL)
  42. *(ptr)=0; // remove executable name
  43. string.ReleaseBuffer();
  44. return string;
  45. }
  46. int Utility::getTempDirectory(CString& strTemp)
  47. {
  48. TCHAR* pszTempVar = NULL;
  49. #if _MSC_VER<1400
  50. pszTempVar = _tgetenv(_T("TEMP"));
  51. strTemp = CString(pszTempVar);
  52. #else
  53. size_t len = 0;
  54. errno_t err = _tdupenv_s(&pszTempVar, &len, _T("TEMP"));
  55. if(err!=0)
  56. {
  57. // Couldn't get environment variable TEMP
  58. return 1;
  59. }
  60. strTemp = CString(pszTempVar);
  61. free(pszTempVar);
  62. #endif
  63. return 0;
  64. }
  65. CString Utility::getTempFileName()
  66. {
  67. TCHAR szTempDir[MAX_PATH - 14] = _T("");
  68. TCHAR szTempFile[MAX_PATH] = _T("");
  69. if (GetTempPath(MAX_PATH - 14, szTempDir))
  70. GetTempFileName(szTempDir, getAppName(), 0, szTempFile);
  71. return szTempFile;
  72. }
  73. int Utility::GetSystemTimeUTC(CString& sTime)
  74. {
  75. sTime.Empty();
  76. // Get system time in UTC format
  77. time_t cur_time;
  78. time(&cur_time);
  79. char szDateTime[64];
  80. #if _MSC_VER<1400
  81. struct tm* timeinfo = gmtime(&cur_time);
  82. strftime(szDateTime, 64, "%Y-%m-%dT%H:%M:%SZ", timeinfo);
  83. #else
  84. struct tm timeinfo;
  85. gmtime_s(&timeinfo, &cur_time);
  86. strftime(szDateTime, 64, "%Y-%m-%dT%H:%M:%SZ", &timeinfo);
  87. #endif
  88. sTime = szDateTime;
  89. return 0;
  90. }
  91. void Utility::UTC2SystemTime(CString sUTC, SYSTEMTIME& st)
  92. {
  93. CString sYear = sUTC.Mid(0, 4);
  94. CString sMonth = sUTC.Mid(5, 2);
  95. CString sDay = sUTC.Mid(8, 2);
  96. CString sHour = sUTC.Mid(11, 2);
  97. CString sMin = sUTC.Mid(14, 2);
  98. CString sSec = sUTC.Mid(17, 2);
  99. SYSTEMTIME UtcTime;
  100. memset(&UtcTime, 0, sizeof(SYSTEMTIME));
  101. UtcTime.wYear = (WORD)_ttoi(sYear);
  102. UtcTime.wMonth = (WORD)_ttoi(sMonth);
  103. UtcTime.wDay = (WORD)_ttoi(sDay);
  104. UtcTime.wHour = (WORD)_ttoi(sHour);
  105. UtcTime.wMinute = (WORD)_ttoi(sMin);
  106. UtcTime.wSecond = (WORD)_ttoi(sSec);
  107. // Convert to local time
  108. SystemTimeToTzSpecificLocalTime(NULL, &UtcTime, &st);
  109. }
  110. int Utility::GenerateGUID(CString& sGUID)
  111. {
  112. int status = 1;
  113. sGUID.Empty();
  114. strconv_t strconv;
  115. // Create GUID
  116. UCHAR *pszUuid = 0;
  117. GUID *pguid = NULL;
  118. pguid = new GUID;
  119. if(pguid!=NULL)
  120. {
  121. HRESULT hr = CoCreateGuid(pguid);
  122. if(SUCCEEDED(hr))
  123. {
  124. // Convert the GUID to a string
  125. hr = UuidToStringA(pguid, &pszUuid);
  126. if(SUCCEEDED(hr) && pszUuid!=NULL)
  127. {
  128. status = 0;
  129. sGUID = strconv.a2t((char*)pszUuid);
  130. RpcStringFreeA(&pszUuid);
  131. }
  132. }
  133. delete pguid;
  134. }
  135. return status;
  136. }
  137. int Utility::GetOSFriendlyName(CString& sOSName)
  138. {
  139. sOSName.Empty();
  140. CRegKey regKey;
  141. LONG lResult = regKey.Open(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"), KEY_READ);
  142. if(lResult==ERROR_SUCCESS)
  143. {
  144. TCHAR buf[1024];
  145. ULONG buf_size = 0;
  146. TCHAR* PRODUCT_NAME = _T("ProductName");
  147. TCHAR* CURRENT_BUILD_NUMBER = _T("CurrentBuildNumber");
  148. TCHAR* CSD_VERSION = _T("CSDVersion");
  149. #pragma warning(disable:4996)
  150. buf_size = 1023;
  151. if(ERROR_SUCCESS == regKey.QueryValue(buf, PRODUCT_NAME, &buf_size))
  152. {
  153. sOSName += buf;
  154. }
  155. buf_size = 1023;
  156. if(ERROR_SUCCESS == regKey.QueryValue(buf, CURRENT_BUILD_NUMBER, &buf_size))
  157. {
  158. sOSName += _T(" Build ");
  159. sOSName += buf;
  160. }
  161. buf_size = 1023;
  162. if(ERROR_SUCCESS == regKey.QueryValue(buf, CSD_VERSION, &buf_size))
  163. {
  164. sOSName += _T(" ");
  165. sOSName += buf;
  166. }
  167. #pragma warning(default:4996)
  168. regKey.Close();
  169. return 0;
  170. }
  171. return 1;
  172. }
  173. BOOL Utility::IsOS64Bit()
  174. {
  175. BOOL b64Bit = FALSE;
  176. #ifdef _WIN64
  177. // 64-bit applications always run under 64-bit Windows
  178. return TRUE;
  179. #endif
  180. // Check for 32-bit applications
  181. typedef BOOL (WINAPI *PFNISWOW64PROCESS)(HANDLE, PBOOL);
  182. HMODULE hKernel32 = LoadLibrary(_T("kernel32.dll"));
  183. if(hKernel32!=NULL)
  184. {
  185. PFNISWOW64PROCESS pfnIsWow64Process =
  186. (PFNISWOW64PROCESS)GetProcAddress(hKernel32, "IsWow64Process");
  187. if(pfnIsWow64Process==NULL)
  188. {
  189. // If there is no IsWow64Process() API, than Windows is 32-bit for sure
  190. FreeLibrary(hKernel32);
  191. return FALSE;
  192. }
  193. pfnIsWow64Process(GetCurrentProcess(), &b64Bit);
  194. FreeLibrary(hKernel32);
  195. }
  196. return b64Bit;
  197. }
  198. int Utility::GetGeoLocation(CString& sGeoLocation)
  199. {
  200. sGeoLocation = _T("");
  201. typedef GEOID (WINAPI *PFNGETUSERGEOID)(GEOCLASS);
  202. typedef int (WINAPI *PFNGETGEOINFOW)(GEOID, GEOTYPE, LPWSTR, int, LANGID);
  203. HMODULE hKernel32 = LoadLibrary(_T("kernel32.dll"));
  204. if(hKernel32!=NULL)
  205. {
  206. PFNGETUSERGEOID pfnGetUserGeoID =
  207. (PFNGETUSERGEOID)GetProcAddress(hKernel32, "GetUserGeoID");
  208. PFNGETGEOINFOW pfnGetGeoInfoW =
  209. (PFNGETGEOINFOW)GetProcAddress(hKernel32, "GetGeoInfoW");
  210. if(pfnGetUserGeoID==NULL ||
  211. pfnGetGeoInfoW==NULL)
  212. return -1;
  213. GEOID GeoLocation = pfnGetUserGeoID(GEOCLASS_NATION);
  214. if(GeoLocation!=GEOID_NOT_AVAILABLE)
  215. {
  216. WCHAR szGeoInfo[1024] = _T("");
  217. int n = pfnGetGeoInfoW(GeoLocation, GEO_RFC1766, szGeoInfo, 1024, 0);
  218. if(n!=0)
  219. {
  220. sGeoLocation = szGeoInfo;
  221. FreeLibrary(hKernel32);
  222. return 0;
  223. }
  224. }
  225. FreeLibrary(hKernel32);
  226. }
  227. return -1;
  228. }
  229. int Utility::GetSpecialFolder(int csidl, CString& sFolderPath)
  230. {
  231. sFolderPath.Empty();
  232. TCHAR szPath[_MAX_PATH];
  233. BOOL bResult = SHGetSpecialFolderPath(NULL, szPath, csidl, TRUE);
  234. if(!bResult)
  235. return 1;
  236. sFolderPath = CString(szPath);
  237. return 0;
  238. }
  239. CString Utility::ReplaceInvalidCharsInFileName(CString sFileName)
  240. {
  241. sFileName.Replace(_T("*"),_T("_"));
  242. sFileName.Replace(_T("|"),_T("_"));
  243. sFileName.Replace(_T("/"),_T("_"));
  244. sFileName.Replace(_T("?"),_T("_"));
  245. sFileName.Replace(_T("<"),_T("_"));
  246. sFileName.Replace(_T(">"),_T("_"));
  247. return sFileName;
  248. }
  249. int Utility::RecycleFile(CString sFilePath, bool bPermanentDelete)
  250. {
  251. SHFILEOPSTRUCT fop;
  252. memset(&fop, 0, sizeof(SHFILEOPSTRUCT));
  253. TCHAR szFrom[_MAX_PATH];
  254. memset(szFrom, 0, sizeof(TCHAR)*(_MAX_PATH));
  255. _TCSCPY_S(szFrom, _MAX_PATH, sFilePath.GetBuffer(0));
  256. szFrom[sFilePath.GetLength()+1] = 0;
  257. fop.fFlags |= FOF_SILENT; // don't report progress
  258. fop.fFlags |= FOF_NOERRORUI; // don't report errors
  259. fop.fFlags |= FOF_NOCONFIRMATION; // don't confirm delete
  260. fop.wFunc = FO_DELETE; // REQUIRED: delete operation
  261. fop.pFrom = szFrom; // REQUIRED: which file(s)
  262. fop.pTo = NULL; // MUST be NULL
  263. if (bPermanentDelete)
  264. {
  265. // if delete requested..
  266. fop.fFlags &= ~FOF_ALLOWUNDO; // ..don't use Recycle Bin
  267. }
  268. else
  269. { // otherwise..
  270. fop.fFlags |= FOF_ALLOWUNDO; // ..send to Recycle Bin
  271. }
  272. return SHFileOperation(&fop); // do it!
  273. }
  274. CString Utility::GetINIString(LPCTSTR pszFile, LPCTSTR pszSection, LPCTSTR pszName)
  275. {
  276. TCHAR szBuffer[1024] = _T("");
  277. GetPrivateProfileString(pszSection, pszName, _T(""), szBuffer, 1024, pszFile);
  278. CString sResult = szBuffer;
  279. sResult.Replace(_T("\\n"), _T("\n"));
  280. return sResult;
  281. }
  282. void Utility::SetINIString(LPCTSTR pszFile, LPCTSTR pszSection, LPCTSTR pszName, LPCTSTR pszValue)
  283. {
  284. WritePrivateProfileString(pszSection, pszName, pszValue, pszFile);
  285. }
  286. void Utility::SetLayoutRTL(HWND hWnd)
  287. {
  288. DWORD dwExStyle = GetWindowLong(hWnd, GWL_EXSTYLE);
  289. dwExStyle |= WS_EX_LAYOUTRTL;
  290. SetWindowLong(hWnd, GWL_EXSTYLE, dwExStyle);
  291. SetLayout(GetDC(hWnd), LAYOUT_RTL);
  292. CRect rcWnd;
  293. ::GetClientRect(hWnd, &rcWnd);
  294. HWND hWndChild = GetWindow(hWnd, GW_CHILD);
  295. while(hWndChild!=NULL)
  296. {
  297. SetLayoutRTL(hWndChild);
  298. CRect rc;
  299. ::GetWindowRect(hWndChild, &rc);
  300. ::MapWindowPoints(0, hWnd, (LPPOINT)&rc, 2);
  301. ::MoveWindow(hWndChild, rcWnd.Width()-rc.right, rc.top, rc.Width(), rc.Height(), TRUE);
  302. SetLayout(GetDC(hWndChild), LAYOUT_RTL);
  303. hWndChild = GetWindow(hWndChild, GW_HWNDNEXT);
  304. }
  305. }
  306. CString Utility::FormatErrorMsg(DWORD dwErrorCode)
  307. {
  308. LPTSTR msg = 0;
  309. FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_ALLOCATE_BUFFER,
  310. NULL, dwErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  311. (LPTSTR)&msg, 0, NULL);
  312. CString str = msg;
  313. str.Replace(_T("\r\n"), _T(""));
  314. GlobalFree(msg);
  315. return str;
  316. }
  317. // GetBaseFileName
  318. // This helper function returns file name without extension
  319. CString Utility::GetFileName(CString sPath)
  320. {
  321. CString sBase = sPath;
  322. int pos1 = sPath.ReverseFind('\\');
  323. if(pos1>=0)
  324. sBase = sBase.Mid(pos1+1);
  325. return sBase;
  326. }
  327. // GetBaseFileName
  328. // This helper function returns file name without extension
  329. CString Utility::GetBaseFileName(CString sFileName)
  330. {
  331. CString sBase = sFileName;
  332. int pos1 = sFileName.ReverseFind('\\');
  333. if(pos1>=0)
  334. sBase = sBase.Mid(pos1+1);
  335. int pos2 = sBase.ReverseFind('.');
  336. if(pos2>=0)
  337. {
  338. sBase = sFileName.Mid(0, pos2);
  339. }
  340. return sBase;
  341. }
  342. // GetFileExtension
  343. // This helper function returns file extension by file name
  344. CString Utility::GetFileExtension(CString sFileName)
  345. {
  346. CString sExt;
  347. int pos = sFileName.ReverseFind('.');
  348. if(pos>=0)
  349. {
  350. sExt = sFileName.Mid(pos+1);
  351. }
  352. return sExt;
  353. }
  354. CString Utility::GetProductVersion(CString sModuleName)
  355. {
  356. CString sProductVer;
  357. DWORD dwBuffSize = GetFileVersionInfoSize(sModuleName, 0);
  358. LPBYTE pBuff = (LPBYTE)GlobalAlloc(GPTR, dwBuffSize);
  359. if(NULL!=pBuff && 0!=GetFileVersionInfo(sModuleName, 0, dwBuffSize, pBuff))
  360. {
  361. VS_FIXEDFILEINFO* fi = NULL;
  362. UINT uLen = 0;
  363. VerQueryValue(pBuff, _T("\\"), (LPVOID*)&fi, &uLen);
  364. WORD dwVerMajor = HIWORD(fi->dwProductVersionMS);
  365. WORD dwVerMinor = LOWORD(fi->dwProductVersionMS);
  366. WORD dwPatchLevel = HIWORD(fi->dwProductVersionLS);
  367. WORD dwVerBuild = LOWORD(fi->dwProductVersionLS);
  368. sProductVer.Format(_T("%u.%u.%u.%u"),
  369. dwVerMajor, dwVerMinor, dwPatchLevel, dwVerBuild);
  370. }
  371. GlobalFree((HGLOBAL)pBuff);
  372. return sProductVer;
  373. }
  374. // Creates a folder. If some intermediate folders in the path do not exist,
  375. // it creates them.
  376. BOOL Utility::CreateFolder(CString sFolderName)
  377. {
  378. CString sIntermediateFolder;
  379. // Skip disc drive name "X:\" if presents
  380. int start = sFolderName.Find(':', 0);
  381. if(start>=0)
  382. start+=2;
  383. int pos = start;
  384. for(;;)
  385. {
  386. pos = sFolderName.Find('\\', pos);
  387. if(pos<0)
  388. {
  389. sIntermediateFolder = sFolderName;
  390. }
  391. else
  392. {
  393. sIntermediateFolder = sFolderName.Left(pos);
  394. }
  395. BOOL bCreate = CreateDirectory(sIntermediateFolder, NULL);
  396. if(!bCreate && GetLastError()!=ERROR_ALREADY_EXISTS)
  397. return FALSE;
  398. DWORD dwAttrs = GetFileAttributes(sIntermediateFolder);
  399. if((dwAttrs&FILE_ATTRIBUTE_DIRECTORY)==0)
  400. return FALSE;
  401. if(pos==-1)
  402. break;
  403. pos++;
  404. }
  405. return TRUE;
  406. }
  407. ULONG64 Utility::SystemTimeToULONG64( const SYSTEMTIME& st )
  408. {
  409. FILETIME ft ;
  410. SystemTimeToFileTime( &st, &ft ) ;
  411. ULARGE_INTEGER integer ;
  412. integer.LowPart = ft.dwLowDateTime ;
  413. integer.HighPart = ft.dwHighDateTime ;
  414. return integer.QuadPart ;
  415. }
  416. CString Utility::FileSizeToStr(ULONG64 uFileSize)
  417. {
  418. CString sFileSize;
  419. if(uFileSize==0)
  420. {
  421. sFileSize = _T("0 KB");
  422. }
  423. else if(uFileSize<1024)
  424. {
  425. float fSizeKbytes = (float)uFileSize/(float)1024;
  426. TCHAR szStr[64];
  427. #if _MSC_VER<1400
  428. _stprintf(szStr, _T("%0.1f KB"), fSizeKbytes);
  429. #else
  430. _stprintf_s(szStr, 64, _T("%0.1f KB"), fSizeKbytes);
  431. #endif
  432. sFileSize = szStr;
  433. }
  434. else if(uFileSize<1024*1024)
  435. {
  436. sFileSize.Format(_T("%I64u KB"), uFileSize/1024);
  437. }
  438. else
  439. {
  440. float fSizeMbytes = (float)uFileSize/(float)(1024*1024);
  441. TCHAR szStr[64];
  442. #if _MSC_VER<1400
  443. _stprintf(szStr, _T("%0.1f MB"), fSizeMbytes);
  444. #else
  445. _stprintf_s(szStr, 64, _T("%0.1f MB"), fSizeMbytes);
  446. #endif
  447. sFileSize = szStr;
  448. }
  449. return sFileSize;
  450. }
  451. CString Utility::AddEllipsis(LPCTSTR szString, int nMaxLength)
  452. {
  453. if(szString==NULL)
  454. return CString("");
  455. CString sResult = szString;
  456. if(sResult.GetLength()>nMaxLength)
  457. {
  458. if(nMaxLength>=3)
  459. sResult = sResult.Mid(0, nMaxLength-3)+_T("...");
  460. }
  461. return sResult;
  462. }
  463. std::vector<CString> Utility::ExplodeStr(LPCTSTR szString, LPCTSTR szSeparators)
  464. {
  465. std::vector<CString> aTokens;
  466. CString copy = szString;
  467. TCHAR *context = 0;
  468. TCHAR *token = _tcstok_s(const_cast<LPTSTR>((LPCTSTR)copy), szSeparators, &context);
  469. while (token != 0)
  470. {
  471. aTokens.push_back(token);
  472. token=_tcstok_s(NULL, szSeparators, &context);
  473. };
  474. return aTokens;
  475. }
  476. long Utility::GetFileSize(const TCHAR *fileName)
  477. {
  478. BOOL fOk;
  479. WIN32_FILE_ATTRIBUTE_DATA fileInfo;
  480. if (NULL == fileName)
  481. return -1;
  482. fOk = GetFileAttributesEx(fileName, GetFileExInfoStandard, (void*)&fileInfo);
  483. if (!fOk)
  484. return -1;
  485. //assert(0 == fileInfo.nFileSizeHigh);
  486. return (long)fileInfo.nFileSizeLow;
  487. }
  488. BOOL Utility::IsFileSearchPattern(CString sFileName)
  489. {
  490. // Remove the "\\?\" prefix in case of a long path name
  491. if(sFileName.Left(4).Compare(_T("\\\\?\\"))==0)
  492. sFileName = sFileName.Mid(4);
  493. // Check if the file name is a search template.
  494. BOOL bSearchPattern = FALSE;
  495. int nPos = sFileName.FindOneOf(_T("*?"));
  496. if(nPos>=0)
  497. bSearchPattern = true;
  498. return bSearchPattern;
  499. }