Leaked source code of windows server 2003
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.

725 lines
19 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 <sddl.h>
  48. #include <assert.h>
  49. #include <stdlib.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 <strsafe.h>
  61. #include "common.h"
  62. // Time conversion constants
  63. #define SECONDS_IN_DAY 86400
  64. #define SECONDS_IN_HOUR 3600
  65. #define SECONDS_IN_MINUTE 60
  66. #define INDIRECT_STRING_LEN 9
  67. LPCWSTR cszFormatIndirect = L"%s Indirect";
  68. // Forward definitions - to be moved to pdhpla
  69. PDH_FUNCTION
  70. PlaReadRegistryIndirectStringValue (
  71. HKEY hKey,
  72. LPCWSTR cwszValueName,
  73. LPWSTR *pszBuffer,
  74. UINT* pcchBufLen
  75. );
  76. BOOL __stdcall
  77. GetLocalFileTime (
  78. LONGLONG *pFileTime
  79. )
  80. {
  81. BOOL bResult;
  82. SYSTEMTIME st;
  83. assert ( NULL != pFileTime );
  84. GetLocalTime ( &st );
  85. //
  86. // The only error for SystemTimeToFileTime is STATUS_INVALID_PARAMETER.
  87. //
  88. bResult = SystemTimeToFileTime (&st, (LPFILETIME)pFileTime);
  89. return bResult;
  90. }
  91. BOOL __stdcall
  92. MakeStringFromInfo (
  93. PALERT_INFO_BLOCK pInfo,
  94. LPWSTR szBuffer,
  95. LPDWORD pcchBufferLength
  96. )
  97. {
  98. HRESULT hr = S_OK;
  99. BOOL bStatus = FALSE;
  100. DWORD dwLenReqd;
  101. size_t cchMaxLocalBufLen = 0;
  102. size_t cchLocalBufLen = 0;
  103. dwLenReqd = lstrlen ( pInfo->szCounterPath );
  104. dwLenReqd += 1; // sizeof inequality char
  105. dwLenReqd += SLQ_MAX_VALUE_LEN; // max size of value in chars
  106. dwLenReqd += 1; // term NULL
  107. if (dwLenReqd <= *pcchBufferLength) {
  108. //
  109. // Copy info block contents to a string buffer
  110. //
  111. cchMaxLocalBufLen = *pcchBufferLength;
  112. hr = StringCchPrintf (
  113. szBuffer,
  114. cchMaxLocalBufLen,
  115. L"%s%s%0.23g",
  116. pInfo->szCounterPath,
  117. (((pInfo->dwFlags & AIBF_OVER) == AIBF_OVER) ? L">" : L"<"),
  118. pInfo->dLimit );
  119. // Returned buffer length does not include final NULL character.
  120. if ( SUCCEEDED (hr) ) {
  121. hr = StringCchLength ( szBuffer, cchMaxLocalBufLen, &cchLocalBufLen );
  122. if ( SUCCEEDED (hr) ) {
  123. *pcchBufferLength = (DWORD)cchLocalBufLen + 1;
  124. bStatus = TRUE;
  125. }
  126. }
  127. }
  128. return bStatus;
  129. }
  130. BOOL __stdcall
  131. MakeInfoFromString (
  132. LPCWSTR szBuffer,
  133. PALERT_INFO_BLOCK pInfo,
  134. LPDWORD pdwBufferSize
  135. )
  136. {
  137. LPCWSTR szSrc;
  138. LPWSTR szDst;
  139. DWORD dwSizeUsed;
  140. DWORD dwSizeLimit = *pdwBufferSize - sizeof(WCHAR);
  141. dwSizeUsed = sizeof(ALERT_INFO_BLOCK);
  142. szSrc = szBuffer;
  143. szDst = (LPWSTR)&pInfo[1];
  144. pInfo->szCounterPath = szDst;
  145. // copy the string
  146. while (dwSizeUsed < dwSizeLimit) {
  147. if ((*szSrc == L'<') || (*szSrc == L'>')) break;
  148. *szDst++ = *szSrc++;
  149. dwSizeUsed += sizeof(WCHAR);
  150. }
  151. if (dwSizeUsed < dwSizeLimit) {
  152. *szDst++ = 0; // NULL term the string
  153. dwSizeUsed += sizeof(WCHAR);
  154. }
  155. pInfo->dwFlags = ((*szSrc == L'>') ? AIBF_OVER : AIBF_UNDER);
  156. szSrc++;
  157. //
  158. // Get limit value
  159. //
  160. pInfo->dLimit = _wtof(szSrc);
  161. // write size of buffer used
  162. pInfo->dwSize = dwSizeUsed;
  163. if (dwSizeUsed <= *pdwBufferSize) {
  164. return TRUE;
  165. }
  166. else {
  167. return FALSE;
  168. }
  169. }
  170. void _stdcall
  171. ReplaceBlanksWithUnderscores(
  172. LPWSTR szName )
  173. {
  174. PdhiPlaFormatBlanksW( NULL, szName );
  175. }
  176. void _stdcall
  177. TimeInfoToMilliseconds (
  178. SLQ_TIME_INFO* pTimeInfo,
  179. LONGLONG* pllmsecs)
  180. {
  181. assert ( SLQ_TT_DTYPE_UNITS == pTimeInfo->wDataType );
  182. //
  183. // Trusted caller, no check for NULL pointers.
  184. //
  185. TimeInfoToTics ( pTimeInfo, pllmsecs );
  186. *pllmsecs /= FILETIME_TICS_PER_MILLISECOND;
  187. return;
  188. }
  189. void _stdcall
  190. TimeInfoToTics (
  191. SLQ_TIME_INFO* pTimeInfo,
  192. LONGLONG* pllTics)
  193. {
  194. assert ( SLQ_TT_DTYPE_UNITS == pTimeInfo->wDataType );
  195. //
  196. // Trusted caller, no check for NULL pointers.
  197. //
  198. switch (pTimeInfo->dwUnitType) {
  199. case SLQ_TT_UTYPE_SECONDS:
  200. *pllTics = pTimeInfo->dwValue;
  201. break;
  202. case SLQ_TT_UTYPE_MINUTES:
  203. *pllTics = pTimeInfo->dwValue * SECONDS_IN_MINUTE;
  204. break;
  205. case SLQ_TT_UTYPE_HOURS:
  206. *pllTics = pTimeInfo->dwValue * SECONDS_IN_HOUR;
  207. break;
  208. case SLQ_TT_UTYPE_DAYS:
  209. *pllTics = pTimeInfo->dwValue * SECONDS_IN_DAY;
  210. break;
  211. default:
  212. *pllTics = 0;
  213. }
  214. *pllTics *= FILETIME_TICS_PER_SECOND;
  215. return;
  216. }
  217. PDH_FUNCTION
  218. PlaReadRegistryIndirectStringValue (
  219. HKEY hKey,
  220. LPCWSTR pcszValueName,
  221. LPWSTR* pszBuffer,
  222. UINT* pcchBufLen
  223. )
  224. {
  225. //
  226. // Reads the indirect string value from under hKey and
  227. // frees any existing buffer referenced by pszBuffer,
  228. // then allocates a new buffer returning it with the
  229. // string value read from the registry and the length
  230. // of the buffer in characters (string length including
  231. // NULL terminator)
  232. //
  233. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  234. HRESULT hr = NOERROR;
  235. LPWSTR szNewStringBuffer = NULL;
  236. UINT cchLocalBufLen = 0;
  237. const UINT cchLocalBufLenGrow = MAX_PATH;
  238. assert ( NULL != hKey );
  239. assert ( NULL != pcszValueName );
  240. assert ( NULL != pszBuffer );
  241. assert ( NULL != pcchBufLen );
  242. if ( NULL != hKey ) {
  243. if ( ( NULL != pcszValueName )
  244. && ( NULL != pszBuffer )
  245. && ( NULL != pcchBufLen ) ) {
  246. // find out the size of the required buffer
  247. do {
  248. /*
  249. * allocate a large(r) buffer for the string
  250. */
  251. if ( NULL != szNewStringBuffer ) {
  252. G_FREE ( szNewStringBuffer );
  253. szNewStringBuffer = NULL;
  254. }
  255. cchLocalBufLen += cchLocalBufLenGrow;
  256. szNewStringBuffer = (LPWSTR)G_ALLOC( cchLocalBufLen*sizeof(WCHAR));
  257. if ( NULL != szNewStringBuffer ) {
  258. hr = SHLoadRegUIStringW (
  259. hKey,
  260. pcszValueName,
  261. szNewStringBuffer,
  262. cchLocalBufLen);
  263. //
  264. // Called method might not have set the terminating NULL.
  265. //
  266. szNewStringBuffer[cchLocalBufLen - 1] = L'\0';
  267. /*
  268. * If we filled up the buffer, we'll pessimistically assume that
  269. * there's more data available. We'll loop around, grow the buffer,
  270. * and try again.
  271. */
  272. } else {
  273. pdhStatus = ERROR_OUTOFMEMORY;
  274. break;
  275. }
  276. } while ( (ULONG)lstrlen( szNewStringBuffer ) == cchLocalBufLen-1
  277. && SUCCEEDED ( hr ) );
  278. if ( NULL != szNewStringBuffer ) {
  279. if ( 0 == lstrlen (szNewStringBuffer) ) {
  280. // nothing to read
  281. pdhStatus = ERROR_NO_DATA;
  282. } else {
  283. if ( FAILED ( hr ) ) {
  284. // Unable to read buffer
  285. // Translate hr to pdhStatus
  286. assert ( E_INVALIDARG != hr );
  287. if ( E_OUTOFMEMORY == hr ) {
  288. pdhStatus = ERROR_OUTOFMEMORY;
  289. } else {
  290. pdhStatus = ERROR_NO_DATA;
  291. }
  292. }
  293. }
  294. }
  295. } else {
  296. pdhStatus = ERROR_INVALID_PARAMETER;
  297. }
  298. } else {
  299. // null key
  300. pdhStatus = ERROR_BADKEY;
  301. }
  302. if ( ERROR_SUCCESS != pdhStatus ) {
  303. if ( NULL != szNewStringBuffer ) {
  304. G_FREE (szNewStringBuffer);
  305. szNewStringBuffer = NULL;
  306. cchLocalBufLen = 0;
  307. }
  308. } else {
  309. // then delete the old buffer and replace it with
  310. // the new one
  311. if ( NULL != *pszBuffer ) {
  312. G_FREE (*pszBuffer );
  313. }
  314. *pszBuffer = szNewStringBuffer;
  315. *pcchBufLen = cchLocalBufLen;
  316. }
  317. return pdhStatus;
  318. }
  319. DWORD
  320. SmReadRegistryIndirectStringValue (
  321. HKEY hKey,
  322. LPCWSTR szValueName,
  323. LPCWSTR szDefault,
  324. LPWSTR* pszBuffer,
  325. UINT* pcchBufLen
  326. )
  327. //
  328. // reads the string value "szValueName" from under hKey and
  329. // frees any existing buffer referenced by pszBuffer,
  330. // then allocates a new buffer returning it with the
  331. // string value read from the registry and the size of the
  332. // buffer in characters, including the terminating null.
  333. //
  334. {
  335. DWORD dwStatus = ERROR_SUCCESS;
  336. HRESULT hr = S_OK;
  337. LPWSTR szNewStringBuffer = NULL;
  338. UINT cchLocalBufLen = 0;
  339. LPWSTR szIndirectValueName = NULL;
  340. UINT uiValueNameLen = 0;
  341. DWORD dwType;
  342. DWORD dwBufferSize = 0;
  343. if ( NULL == hKey ) {
  344. assert ( FALSE );
  345. dwStatus = ERROR_BADKEY;
  346. }
  347. else if ( ( NULL == pcchBufLen ) ||
  348. ( NULL == pszBuffer ) ||
  349. ( NULL == szValueName ) ) {
  350. assert ( FALSE );
  351. dwStatus = ERROR_INVALID_PARAMETER;
  352. }
  353. if (dwStatus == ERROR_SUCCESS) {
  354. uiValueNameLen = lstrlen ( szValueName ) + INDIRECT_STRING_LEN + 1;
  355. szIndirectValueName = G_ALLOC ( uiValueNameLen * sizeof(WCHAR) );
  356. if ( NULL != szIndirectValueName ) {
  357. StringCchPrintf (
  358. szIndirectValueName,
  359. uiValueNameLen,
  360. cszFormatIndirect,
  361. szValueName );
  362. //
  363. // PlaReadxxx guarantees NULL terminated return string.
  364. //
  365. dwStatus = PlaReadRegistryIndirectStringValue (
  366. hKey,
  367. szIndirectValueName,
  368. &szNewStringBuffer,
  369. &cchLocalBufLen );
  370. if ( ERROR_SUCCESS == dwStatus) {
  371. if ( 0 == lstrlen( szNewStringBuffer ) ) {
  372. // nothing to read
  373. dwStatus = ERROR_NO_DATA;
  374. }
  375. } // else dwStatus has error
  376. G_FREE ( szIndirectValueName );
  377. } else {
  378. dwStatus = ERROR_NOT_ENOUGH_MEMORY;
  379. }
  380. if ( ERROR_NO_DATA == dwStatus ) {
  381. //
  382. // There might be something to read under the non-indirect field.
  383. // Find out the size of the required buffer.
  384. //
  385. dwStatus = RegQueryValueExW (
  386. hKey,
  387. szValueName,
  388. NULL,
  389. &dwType,
  390. NULL,
  391. &dwBufferSize);
  392. if (dwStatus == ERROR_SUCCESS) {
  393. // NULL character size is 2 bytes
  394. if (dwBufferSize > 2) {
  395. // then there's something to read
  396. szNewStringBuffer = (WCHAR*) G_ALLOC ( dwBufferSize );
  397. if (szNewStringBuffer != NULL) {
  398. dwType = 0;
  399. dwStatus = RegQueryValueExW (
  400. hKey,
  401. szValueName,
  402. NULL,
  403. &dwType,
  404. (LPBYTE)szNewStringBuffer,
  405. &dwBufferSize);
  406. cchLocalBufLen = dwBufferSize/sizeof(WCHAR);
  407. szNewStringBuffer[cchLocalBufLen - 1] = L'\0';
  408. cchLocalBufLen = lstrlenW ( szNewStringBuffer ) + 1;
  409. if ( 1 == cchLocalBufLen ) {
  410. dwStatus = ERROR_NO_DATA;
  411. }
  412. } else {
  413. // Todo: Report event for this case.
  414. dwStatus = ERROR_OUTOFMEMORY;
  415. }
  416. } else {
  417. // nothing to read
  418. dwStatus = ERROR_NO_DATA;
  419. }
  420. }
  421. }
  422. if ( ERROR_SUCCESS != dwStatus ) {
  423. if ( NULL != szNewStringBuffer ) {
  424. G_FREE ( szNewStringBuffer );
  425. szNewStringBuffer = NULL;
  426. cchLocalBufLen = 0;
  427. }
  428. // apply default
  429. if ( NULL != szDefault ) {
  430. cchLocalBufLen = lstrlen(szDefault) + 1;
  431. if ( 1 < cchLocalBufLen ) {
  432. szNewStringBuffer = (WCHAR*) G_ALLOC ( cchLocalBufLen * sizeof (WCHAR) );
  433. if ( NULL != szNewStringBuffer ) {
  434. hr = StringCchCopy ( szNewStringBuffer, cchLocalBufLen, szDefault );
  435. dwStatus = HRESULT_CODE( hr );
  436. } else {
  437. dwStatus = ERROR_OUTOFMEMORY;
  438. }
  439. }
  440. } // else no default so no data returned
  441. }
  442. if ( ERROR_SUCCESS == dwStatus ) {
  443. // Delete the old buffer and replace it with
  444. // the new one.
  445. if ( NULL != *pszBuffer ) {
  446. G_FREE (*pszBuffer );
  447. }
  448. *pszBuffer = szNewStringBuffer;
  449. *pcchBufLen = cchLocalBufLen;
  450. } else {
  451. //
  452. // If error then delete the buffer
  453. // Leave the original buffer pointer as is.
  454. //
  455. if ( NULL != szNewStringBuffer ) {
  456. G_FREE ( szNewStringBuffer );
  457. *pcchBufLen = 0;
  458. }
  459. }
  460. }
  461. return dwStatus;
  462. }
  463. DWORD
  464. RegisterCurrentFile( HKEY hkeyQuery, LPWSTR szFileName, DWORD dwSubIndex )
  465. {
  466. DWORD dwStatus = ERROR_SUCCESS;
  467. LPWSTR szLocalFileName = NULL;
  468. BOOL bLocalAlloc = FALSE;
  469. DWORD dwSize = 0;
  470. size_t cchLocalBufLen = 0;
  471. if( szFileName != NULL ){
  472. if( dwSubIndex == (-1) ){
  473. //
  474. // The only time this will get called with a (-1) is the first time
  475. // trace is building the file name.
  476. //
  477. dwSize = (DWORD)((BYTE*)&szFileName[wcslen( szFileName )] -
  478. (BYTE*)&szFileName[0]);
  479. // 32 is the max size of all formatting and extention characters.
  480. dwSize += 32 * sizeof(WCHAR);
  481. szLocalFileName = (LPWSTR)G_ALLOC( dwSize );
  482. if( NULL != szLocalFileName ) {
  483. bLocalAlloc = TRUE;
  484. cchLocalBufLen = dwSize/(sizeof(WCHAR));
  485. //
  486. // No file name length restriction.
  487. //
  488. StringCchPrintf (
  489. szLocalFileName,
  490. cchLocalBufLen,
  491. szFileName,
  492. 1 );
  493. } else {
  494. dwStatus = ERROR_OUTOFMEMORY;
  495. }
  496. } else {
  497. szLocalFileName = szFileName;
  498. //
  499. // No file name length restriction.
  500. //
  501. if ( SUCCEEDED ( StringCchLength ( szLocalFileName, STRSAFE_MAX_CCH, &cchLocalBufLen ) ) ) {
  502. dwSize = (cchLocalBufLen + 1) * sizeof(WCHAR);
  503. } else {
  504. dwStatus = ERROR_INVALID_NAME;
  505. }
  506. }
  507. // dwSize = (DWORD)((BYTE*)&szLocalFileName[wcslen( szLocalFileName )] -
  508. // (BYTE*)&szLocalFileName[0]);
  509. if ( ERROR_SUCCESS == dwStatus ) {
  510. dwStatus = RegSetValueExW (
  511. hkeyQuery,
  512. L"Current Log File Name",
  513. 0L,
  514. REG_SZ,
  515. (CONST BYTE *)szLocalFileName,
  516. dwSize );
  517. }
  518. } else {
  519. dwStatus = ERROR_INVALID_PARAMETER;
  520. }
  521. if( bLocalAlloc && NULL != szLocalFileName ){
  522. G_FREE( szLocalFileName );
  523. }
  524. return dwStatus;
  525. }
  526. ULONG
  527. __stdcall
  528. ahextoi( LPWSTR s )
  529. {
  530. long len;
  531. ULONG num, base, hex;
  532. len = (long) wcslen(s);
  533. if (len == 0) {
  534. return 0;
  535. }
  536. hex = 0;
  537. base = 1;
  538. num = 0;
  539. while (-- len >= 0) {
  540. if (s[len] >= L'0' && s[len] <= L'9'){
  541. num = s[len] - L'0';
  542. }else if (s[len] >= L'a' && s[len] <= L'f'){
  543. num = (s[len] - L'a') + 10;
  544. }else if (s[len] >= L'A' && s[len] <= L'F'){
  545. num = (s[len] - L'A') + 10;
  546. }else if( s[len] == L'x' || s[len] == L'X'){
  547. break;
  548. }else{
  549. continue;
  550. }
  551. hex += num * base;
  552. base = base * 16;
  553. }
  554. return hex;
  555. }
  556. BOOL
  557. PerfCreateDirectory(LPWSTR szDirectory)
  558. /*++
  559. Routine Description:
  560. The function create a SECURITY_ATTRIBUTES structure used by
  561. "Performance Logs and Alerts" when creating a directory to
  562. hold log files.
  563. The security policy is as following:
  564. Admin - Full control
  565. System - Full control
  566. Performance Logging -
  567. Performance Monitoring - Read & Execute, List folder contents
  568. Network
  569. Arguments:
  570. None
  571. Return Value:
  572. Return the newly created SECURITY_ATTRIBUTES if success,
  573. otherwise return NULL
  574. --*/
  575. {
  576. SECURITY_ATTRIBUTES sa;
  577. WCHAR* szSD = L"D:"
  578. L"(A;OICI;GA;;;SY)(A;OICI;GA;;;BA)"
  579. L"(A;OICI;FRFWFXSDRC;;;NS)"
  580. L"(A;OICI;FRFWFXSDRC;;;LU)"
  581. L"(A;OICI;FRFX;;;MU)";
  582. sa.nLength = sizeof(SECURITY_ATTRIBUTES);
  583. sa.bInheritHandle = FALSE;
  584. if (ConvertStringSecurityDescriptorToSecurityDescriptor(
  585. szSD,
  586. SDDL_REVISION_1,
  587. &(sa.lpSecurityDescriptor),
  588. NULL)) {
  589. if (CreateDirectory(szDirectory, &sa)) {
  590. return TRUE;
  591. }
  592. }
  593. return FALSE;
  594. }