Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

577 lines
15 KiB

  1. /*++
  2. Copyright (c) 1997-1999 Microsoft Corporation
  3. Module Name:
  4. Utils.c
  5. Abstract:
  6. Contains utility methods which are used throughout the project.
  7. --*/
  8. #ifndef UNICODE
  9. #define UNICODE 1
  10. #endif
  11. #ifndef _UNICODE
  12. #define _UNICODE 1
  13. #endif
  14. // Define the following to use the minimum of shlwapip.h
  15. #ifndef NO_SHLWAPI_PATH
  16. #define NO_SHLWAPI_PATH
  17. #endif
  18. #ifndef NO_SHLWAPI_REG
  19. #define NO_SHLWAPI_REG
  20. #endif
  21. #ifndef NO_SHLWAPI_UALSTR
  22. #define NO_SHLWAPI_UALSTR
  23. #endif
  24. #ifndef NO_SHLWAPI_STREAM
  25. #define NO_SHLWAPI_STREAM
  26. #endif
  27. #ifndef NO_SHLWAPI_HTTP
  28. #define NO_SHLWAPI_HTTP
  29. #endif
  30. #ifndef NO_SHLWAPI_INTERNAL
  31. #define NO_SHLWAPI_INTERNAL
  32. #endif
  33. #ifndef NO_SHLWAPI_GDI
  34. #define NO_SHLWAPI_GDI
  35. #endif
  36. #ifndef NO_SHLWAPI_UNITHUNK
  37. #define NO_SHLWAPI_UNITHUNK
  38. #endif
  39. #ifndef NO_SHLWAPI_TPS
  40. #define NO_SHLWAPI_TPS
  41. #endif
  42. #ifndef NO_SHLWAPI_MLUI
  43. #define NO_SHLWAPI_MLUI
  44. #endif
  45. #include <shlwapi.h> // For PlaReadRegistryIndirectStringValue
  46. #include <shlwapip.h> // For PlaReadRegistryIndirectStringValue
  47. #include <assert.h>
  48. #include <stdlib.h>
  49. #include <tchar.h>
  50. #include <pdhp.h>
  51. // Disable 64-bit warnings in math.h
  52. #if _MSC_VER >= 1200
  53. #pragma warning(push)
  54. #endif
  55. #pragma warning ( disable : 4032 )
  56. #include <math.h>
  57. #if _MSC_VER >= 1200
  58. #pragma warning(pop)
  59. #endif
  60. #include "common.h"
  61. // Time conversion constants
  62. #define SECONDS_IN_DAY 86400
  63. #define SECONDS_IN_HOUR 3600
  64. #define SECONDS_IN_MINUTE 60
  65. #define INDIRECT_STRING_LEN 9
  66. LPCWSTR cszFormatIndirect = L"%s Indirect";
  67. // Forward definitions - to be moved to pdhpla
  68. PDH_FUNCTION
  69. PlaReadRegistryIndirectStringValue (
  70. HKEY hKey,
  71. LPCWSTR cwszValueName,
  72. LPWSTR *pszBuffer,
  73. UINT* puiLength
  74. );
  75. BOOL __stdcall
  76. GetLocalFileTime (
  77. LONGLONG *pFileTime
  78. )
  79. {
  80. BOOL bResult;
  81. SYSTEMTIME st;
  82. assert ( NULL != pFileTime );
  83. GetLocalTime ( &st );
  84. bResult = SystemTimeToFileTime (&st, (LPFILETIME)pFileTime);
  85. return bResult;
  86. }
  87. BOOL __stdcall
  88. MakeStringFromInfo (
  89. PALERT_INFO_BLOCK pInfo,
  90. LPTSTR szBuffer,
  91. LPDWORD pcchBufferLength
  92. )
  93. {
  94. DWORD dwSizeReqd;
  95. dwSizeReqd = pInfo->dwSize - sizeof(ALERT_INFO_BLOCK);
  96. dwSizeReqd /= sizeof(LPTSTR); // size of counter path in chars
  97. dwSizeReqd += 1; // sizeof inequality char
  98. dwSizeReqd += 20; // size of value in chars
  99. dwSizeReqd += 1; // term NULL
  100. if (dwSizeReqd <= *pcchBufferLength) {
  101. // copy info block contents to a string buffer
  102. *pcchBufferLength = _stprintf (szBuffer, L"%s%s%0.23g",
  103. pInfo->szCounterPath,
  104. (((pInfo->dwFlags & AIBF_OVER) == AIBF_OVER) ? L">" : L"<"),
  105. pInfo->dLimit);
  106. return TRUE;
  107. } else {
  108. return FALSE;
  109. }
  110. }
  111. BOOL __stdcall
  112. MakeInfoFromString (
  113. LPCTSTR szBuffer,
  114. PALERT_INFO_BLOCK pInfo,
  115. LPDWORD pdwBufferSize
  116. )
  117. {
  118. LPCTSTR szSrc;
  119. LPTSTR szDst;
  120. CHAR szAnsiVal[64];
  121. DWORD dwSizeUsed;
  122. DWORD dwSizeLimit = *pdwBufferSize - sizeof(TCHAR);
  123. szAnsiVal[0] = '\0';
  124. dwSizeUsed = sizeof(ALERT_INFO_BLOCK);
  125. szSrc = szBuffer;
  126. szDst = (LPTSTR)&pInfo[1];
  127. pInfo->szCounterPath = szDst;
  128. // copy the string
  129. while (dwSizeUsed < dwSizeLimit) {
  130. if ((*szSrc == L'<') || (*szSrc == L'>')) break;
  131. *szDst++ = *szSrc++;
  132. dwSizeUsed += sizeof(TCHAR);
  133. }
  134. if (dwSizeUsed < dwSizeLimit) {
  135. *szDst++ = 0; // NULL term the string
  136. dwSizeUsed += sizeof(TCHAR);
  137. }
  138. pInfo->dwFlags = ((*szSrc == L'>') ? AIBF_OVER : AIBF_UNDER);
  139. szSrc++;
  140. // get limit value
  141. wcstombs (szAnsiVal, szSrc, sizeof(szAnsiVal));
  142. pInfo->dLimit = atof(szAnsiVal);
  143. // write size of buffer used
  144. pInfo->dwSize = dwSizeUsed;
  145. if (dwSizeUsed <= *pdwBufferSize) {
  146. return TRUE;
  147. }
  148. else {
  149. return FALSE;
  150. }
  151. }
  152. void _stdcall
  153. ReplaceBlanksWithUnderscores(
  154. LPWSTR szName )
  155. {
  156. PdhiPlaFormatBlanksW( NULL, szName );
  157. }
  158. void _stdcall
  159. TimeInfoToMilliseconds (
  160. SLQ_TIME_INFO* pTimeInfo,
  161. LONGLONG* pllmsecs)
  162. {
  163. assert ( SLQ_TT_DTYPE_UNITS == pTimeInfo->wDataType );
  164. TimeInfoToTics ( pTimeInfo, pllmsecs );
  165. *pllmsecs /= FILETIME_TICS_PER_MILLISECOND;
  166. return;
  167. }
  168. void _stdcall
  169. TimeInfoToTics (
  170. SLQ_TIME_INFO* pTimeInfo,
  171. LONGLONG* pllTics)
  172. {
  173. assert ( SLQ_TT_DTYPE_UNITS == pTimeInfo->wDataType );
  174. switch (pTimeInfo->dwUnitType) {
  175. case SLQ_TT_UTYPE_SECONDS:
  176. *pllTics = pTimeInfo->dwValue;
  177. break;
  178. case SLQ_TT_UTYPE_MINUTES:
  179. *pllTics = pTimeInfo->dwValue * SECONDS_IN_MINUTE;
  180. break;
  181. case SLQ_TT_UTYPE_HOURS:
  182. *pllTics = pTimeInfo->dwValue * SECONDS_IN_HOUR;
  183. break;
  184. case SLQ_TT_UTYPE_DAYS:
  185. *pllTics = pTimeInfo->dwValue * SECONDS_IN_DAY;
  186. break;
  187. default:
  188. *pllTics = 0;
  189. }
  190. *pllTics *= FILETIME_TICS_PER_SECOND;
  191. return;
  192. }
  193. PDH_FUNCTION
  194. PlaReadRegistryIndirectStringValue (
  195. HKEY hKey,
  196. LPCWSTR pcszValueName,
  197. LPWSTR* pszBuffer,
  198. UINT* puiLength
  199. )
  200. {
  201. //
  202. // reads the indirect string value from under hKey and
  203. // frees any existing buffer referenced by pszBuffer,
  204. // then allocates a new buffer returning it with the
  205. // string value read from the registry and the length
  206. // of the buffer (string length including NULL terminator)
  207. //
  208. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  209. HRESULT hr = NOERROR;
  210. LPTSTR szNewStringBuffer = NULL;
  211. UINT uiBufferLen = 0;
  212. const UINT uiBufferLenGrow = 256;
  213. assert ( NULL != hKey );
  214. assert ( NULL != pcszValueName );
  215. assert ( NULL != pszBuffer );
  216. assert ( NULL != puiLength );
  217. if ( NULL != hKey ) {
  218. if ( ( NULL != pcszValueName )
  219. && ( NULL != pszBuffer )
  220. && ( NULL != puiLength ) ) {
  221. // find out the size of the required buffer
  222. do {
  223. /*
  224. * allocate a large(r) buffer for the string
  225. */
  226. if ( NULL != szNewStringBuffer ) {
  227. G_FREE ( szNewStringBuffer );
  228. szNewStringBuffer = NULL;
  229. }
  230. uiBufferLen += uiBufferLenGrow;
  231. szNewStringBuffer = (LPWSTR)G_ALLOC( uiBufferLen*sizeof(WCHAR));
  232. if ( NULL != szNewStringBuffer ) {
  233. hr = SHLoadRegUIStringW (
  234. hKey,
  235. pcszValueName,
  236. szNewStringBuffer,
  237. uiBufferLen);
  238. /*
  239. * If we filled up the buffer, we'll pessimistically assume that
  240. * there's more data available. We'll loop around, grow the buffer,
  241. * and try again.
  242. */
  243. } else {
  244. pdhStatus = ERROR_OUTOFMEMORY;
  245. break;
  246. }
  247. } while ( (ULONG)lstrlen( szNewStringBuffer ) == uiBufferLen-1
  248. && SUCCEEDED ( hr ) );
  249. if ( NULL != szNewStringBuffer ) {
  250. if ( 0 == lstrlen (szNewStringBuffer) ) {
  251. // nothing to read
  252. pdhStatus = ERROR_NO_DATA;
  253. } else {
  254. if ( FAILED ( hr ) ) {
  255. // Unable to read buffer
  256. // Translate hr to pdhStatus
  257. assert ( E_INVALIDARG != hr );
  258. if ( E_OUTOFMEMORY == hr ) {
  259. // Todo: Return pdh memory code?
  260. pdhStatus = ERROR_OUTOFMEMORY;
  261. } else {
  262. pdhStatus = ERROR_NO_DATA;
  263. }
  264. }
  265. }
  266. }
  267. } else {
  268. pdhStatus = ERROR_INVALID_PARAMETER;
  269. }
  270. } else {
  271. // null key
  272. pdhStatus = ERROR_BADKEY;
  273. }
  274. if ( ERROR_SUCCESS != pdhStatus ) {
  275. if ( NULL != szNewStringBuffer ) {
  276. G_FREE (szNewStringBuffer);
  277. szNewStringBuffer = NULL;
  278. uiBufferLen = 0;
  279. }
  280. } else {
  281. // then delete the old buffer and replace it with
  282. // the new one
  283. if ( NULL != *pszBuffer ) {
  284. G_FREE (*pszBuffer );
  285. }
  286. *pszBuffer = szNewStringBuffer;
  287. *puiLength = uiBufferLen;
  288. }
  289. return pdhStatus;
  290. }
  291. DWORD
  292. SmReadRegistryIndirectStringValue (
  293. HKEY hKey,
  294. LPCWSTR szValueName,
  295. LPCWSTR szDefault,
  296. LPWSTR* pszBuffer,
  297. UINT* puiLength
  298. )
  299. //
  300. // reads the string value "szValueName" from under hKey and
  301. // frees any existing buffer referenced by pszBuffer,
  302. // then allocates a new buffer returning it with the
  303. // string value read from the registry and the size of the
  304. // buffer (in bytes)
  305. //
  306. {
  307. DWORD dwStatus = ERROR_SUCCESS;
  308. LPWSTR szNewStringBuffer = NULL;
  309. UINT uiBufferLen = 0;
  310. LPWSTR szIndirectValueName = NULL;
  311. UINT uiValueNameLen = 0;
  312. DWORD dwType;
  313. DWORD dwBufferSize = 0;
  314. if ( NULL == hKey ) {
  315. assert ( FALSE );
  316. dwStatus = ERROR_BADKEY;
  317. }
  318. else if ( ( NULL == puiLength ) ||
  319. ( NULL == pszBuffer ) ||
  320. ( NULL == szValueName ) ) {
  321. assert ( FALSE );
  322. dwStatus = ERROR_INVALID_PARAMETER;
  323. }
  324. if (dwStatus == ERROR_SUCCESS) {
  325. uiValueNameLen = lstrlen ( szValueName ) + INDIRECT_STRING_LEN + 1;
  326. szIndirectValueName = G_ALLOC ( uiValueNameLen * sizeof(WCHAR) );
  327. if ( NULL != szIndirectValueName ) {
  328. swprintf ( szIndirectValueName, cszFormatIndirect, szValueName );
  329. dwStatus = PlaReadRegistryIndirectStringValue (
  330. hKey,
  331. szIndirectValueName,
  332. &szNewStringBuffer,
  333. &uiBufferLen );
  334. if ( ERROR_SUCCESS == dwStatus) {
  335. if ( 0 == lstrlen( szNewStringBuffer ) ) {
  336. // nothing to read
  337. dwStatus = ERROR_NO_DATA;
  338. }
  339. } // else dwStatus has error
  340. G_FREE ( szIndirectValueName );
  341. } else {
  342. dwStatus = ERROR_NOT_ENOUGH_MEMORY;
  343. }
  344. if ( ERROR_NO_DATA == dwStatus ) {
  345. // There might be something to read under the non-indirect field.
  346. // Find out the size of the required buffer.
  347. dwStatus = RegQueryValueExW (
  348. hKey,
  349. szValueName,
  350. NULL,
  351. &dwType,
  352. NULL,
  353. &dwBufferSize);
  354. if (dwStatus == ERROR_SUCCESS) {
  355. // NULL character size is 2 bytes
  356. if (dwBufferSize > 2) {
  357. // then there's something to read
  358. szNewStringBuffer = (WCHAR*) G_ALLOC ( dwBufferSize );
  359. if (szNewStringBuffer != NULL) {
  360. dwType = 0;
  361. dwStatus = RegQueryValueExW (
  362. hKey,
  363. szValueName,
  364. NULL,
  365. &dwType,
  366. (LPBYTE)szNewStringBuffer,
  367. &dwBufferSize);
  368. if ( 0 == lstrlenW ( szNewStringBuffer ) ) {
  369. dwStatus = ERROR_NO_DATA;
  370. }
  371. } else {
  372. // Todo: Report event for this case.
  373. dwStatus = ERROR_OUTOFMEMORY;
  374. }
  375. } else {
  376. // nothing to read
  377. dwStatus = ERROR_NO_DATA;
  378. }
  379. }
  380. }
  381. if ( ERROR_SUCCESS != dwStatus ) {
  382. if ( NULL != szNewStringBuffer ) {
  383. G_FREE ( szNewStringBuffer );
  384. szNewStringBuffer = NULL;
  385. uiBufferLen = 0;
  386. }
  387. // apply default
  388. if ( NULL != szDefault ) {
  389. uiBufferLen = lstrlen(szDefault) + 1;
  390. if ( 1 < uiBufferLen ) {
  391. szNewStringBuffer = (WCHAR*) G_ALLOC ( uiBufferLen *= sizeof (WCHAR) );
  392. if ( NULL != szNewStringBuffer ) {
  393. lstrcpyW ( szNewStringBuffer, szDefault);
  394. dwStatus = ERROR_SUCCESS;
  395. } else {
  396. dwStatus = ERROR_OUTOFMEMORY;
  397. }
  398. }
  399. } // else no default so no data returned
  400. }
  401. if ( ERROR_SUCCESS == dwStatus ) {
  402. // Delete the old buffer and replace it with
  403. // the new one.
  404. if ( NULL != *pszBuffer ) {
  405. G_FREE (*pszBuffer ); //delete (*pszBuffer );
  406. }
  407. *pszBuffer = szNewStringBuffer;
  408. *puiLength = uiBufferLen;
  409. } else {
  410. // if error then delete the buffer
  411. if ( NULL != szNewStringBuffer ) {
  412. G_FREE ( szNewStringBuffer ); //delete (szNewStringBuffer);
  413. *puiLength = 0;
  414. }
  415. }
  416. }
  417. return dwStatus;
  418. }
  419. HRESULT
  420. RegisterCurrentFile( HKEY hkeyQuery, LPWSTR strFileName, DWORD dwSubIndex )
  421. {
  422. HRESULT hr = ERROR_SUCCESS;
  423. LPWSTR strLocalFileName = NULL;
  424. BOOL bLocalAlloc = FALSE;
  425. DWORD dwSize;
  426. if( strFileName == NULL ){
  427. return hr;
  428. }
  429. __try{
  430. if( dwSubIndex == (-1) ){
  431. // The only time this will get called with a (-1) is the first time
  432. // trace is building the file name.
  433. dwSize = (DWORD)((BYTE*)&strFileName[wcslen( strFileName )] -
  434. (BYTE*)&strFileName[0]);
  435. dwSize += 32 * sizeof(WCHAR);
  436. strLocalFileName = (LPWSTR)G_ALLOC( dwSize );
  437. if( NULL == strLocalFileName ){
  438. return ERROR_OUTOFMEMORY;
  439. }
  440. bLocalAlloc = TRUE;
  441. swprintf( strLocalFileName, strFileName, 1 /* Sub index starts at 1 */ );
  442. }else{
  443. strLocalFileName = strFileName;
  444. }
  445. dwSize = (DWORD)((BYTE*)&strLocalFileName[wcslen( strLocalFileName )] -
  446. (BYTE*)&strLocalFileName[0]);
  447. hr = RegSetValueExW (hkeyQuery,
  448. L"Current Log File Name",
  449. 0L,
  450. REG_SZ,
  451. (CONST BYTE *)strLocalFileName,
  452. dwSize
  453. );
  454. if( bLocalAlloc ){
  455. G_FREE( strLocalFileName );
  456. }
  457. } __except (EXCEPTION_EXECUTE_HANDLER) {
  458. return ERROR_ARENA_TRASHED;
  459. }
  460. return hr;
  461. }
  462. #if 0
  463. void
  464. StringFromGuid (
  465. REFGUID rguid,
  466. CString& rstrGuid )
  467. {
  468. rstrGuid.Format (
  469. TEXT("{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}"),
  470. rguid.Data1, rguid.Data2, rguid.Data3, rguid.Data4[0], rguid.Data4[1],
  471. rguid.Data4[2], rguid.Data4[3], rguid.Data4[4], rguid.Data4[5],
  472. rguid.Data4[6], rguid.Data4[7]);
  473. return;
  474. }
  475. #endif