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.

1739 lines
46 KiB

  1. /*++
  2. Copyright (C) 1992-1999 Microsoft Corporation
  3. Module Name:
  4. utils.cpp
  5. Abstract:
  6. This file contains miscellaneous utiltity routines, mostly
  7. low-level windows helpers. These routines are not specific
  8. to the System Monitor control.
  9. --*/
  10. //==========================================================================//
  11. // Includes //
  12. //==========================================================================//
  13. #include "stdafx.h"
  14. #include "unihelpr.h"
  15. #include "strings.h"
  16. #include "utils.h"
  17. //==========================================================================//
  18. // Constants //
  19. //==========================================================================//
  20. #define DEFAULT_MSZ_BUF_LEN ((DWORD)0x01000)
  21. #define MAX_MESSAGE_LENGTH ((DWORD)0x00C00)
  22. #define MESSAGE_RESOURCE_ID_MASK ((DWORD)0x0000ffff)
  23. // Time conversion constants
  24. #define SECONDS_IN_DAY 86400
  25. #define SECONDS_IN_HOUR 3600
  26. #define SECONDS_IN_MINUTE 60
  27. //==========================================================================//
  28. // Local Functions //
  29. //==========================================================================//
  30. static
  31. DWORD _stdcall
  32. ScanHexFormat(
  33. IN LPCWSTR szBuffer,
  34. IN ULONG ulMaximumLength,
  35. IN LPCWSTR szFormat,
  36. ...);
  37. //==========================================================================//
  38. // Exported Functions //
  39. //==========================================================================//
  40. BOOL
  41. TruncateLLTime (
  42. IN LONGLONG llTime,
  43. OUT LONGLONG* pllTime
  44. )
  45. {
  46. SYSTEMTIME SystemTime;
  47. if (!FileTimeToSystemTime((FILETIME*)&llTime, &SystemTime))
  48. return FALSE;
  49. SystemTime.wMilliseconds = 0;
  50. return SystemTimeToFileTime(&SystemTime, (FILETIME*)pllTime);
  51. }
  52. BOOL
  53. LLTimeToVariantDate (
  54. IN LONGLONG llTime,
  55. OUT DATE *pdate
  56. )
  57. {
  58. SYSTEMTIME SystemTime;
  59. if (!FileTimeToSystemTime((FILETIME*)&llTime, &SystemTime))
  60. return FALSE;
  61. return SystemTimeToVariantTime(&SystemTime, pdate);
  62. }
  63. BOOL
  64. VariantDateToLLTime (
  65. IN DATE date,
  66. OUT LONGLONG *pllTime
  67. )
  68. {
  69. SYSTEMTIME SystemTime;
  70. if (!VariantTimeToSystemTime(date, &SystemTime))
  71. return FALSE;
  72. return SystemTimeToFileTime(&SystemTime,(FILETIME*)pllTime);
  73. }
  74. //
  75. // Property bag I/O
  76. //
  77. HRESULT _stdcall
  78. DwordFromPropertyBag (
  79. CPropertyBag* pPropBag,
  80. LPCWSTR szPropName,
  81. DWORD& rdwData )
  82. {
  83. VARIANT vValue;
  84. HRESULT hr;
  85. VariantInit( &vValue );
  86. vValue.vt = VT_I4;
  87. vValue.lVal = 0;
  88. hr = pPropBag->Read ( szPropName, &vValue );
  89. if ( SUCCEEDED ( hr ) ) {
  90. rdwData = vValue.lVal;
  91. }
  92. return hr;
  93. }
  94. HRESULT _stdcall
  95. BOOLFromPropertyBag (
  96. CPropertyBag* pPropBag,
  97. LPCWSTR szPropName,
  98. BOOL& rbData )
  99. {
  100. VARIANT vValue;
  101. HRESULT hr;
  102. VariantInit( &vValue );
  103. vValue.vt = VT_BOOL;
  104. hr = pPropBag->Read ( szPropName, &vValue );
  105. if ( SUCCEEDED ( hr ) ) {
  106. rbData = vValue.boolVal;
  107. }
  108. return hr;
  109. }
  110. HRESULT _stdcall
  111. DoubleFromPropertyBag (
  112. CPropertyBag* pPropBag,
  113. LPCWSTR szPropName,
  114. DOUBLE& rdblData )
  115. {
  116. VARIANT vValue;
  117. HRESULT hr;
  118. VariantInit( &vValue );
  119. vValue.vt = VT_R8;
  120. hr = pPropBag->Read ( szPropName, &vValue );
  121. if ( SUCCEEDED ( hr ) ) {
  122. rdblData = vValue.dblVal;
  123. }
  124. return hr;
  125. }
  126. HRESULT _stdcall
  127. FloatFromPropertyBag (
  128. CPropertyBag* pPropBag,
  129. LPCWSTR szPropName,
  130. FLOAT& rfData )
  131. {
  132. VARIANT vValue;
  133. HRESULT hr;
  134. VariantInit( &vValue );
  135. vValue.vt = VT_R4;
  136. hr = pPropBag->Read ( szPropName, &vValue );
  137. if ( SUCCEEDED ( hr ) ) {
  138. rfData = vValue.fltVal;
  139. }
  140. return hr;
  141. }
  142. HRESULT _stdcall
  143. ShortFromPropertyBag (
  144. CPropertyBag* pPropBag,
  145. LPCWSTR szPropName,
  146. SHORT& riData )
  147. {
  148. VARIANT vValue;
  149. HRESULT hr;
  150. VariantInit( &vValue );
  151. vValue.vt = VT_I2;
  152. hr = pPropBag->Read ( szPropName, &vValue );
  153. if ( SUCCEEDED ( hr ) ) {
  154. riData = vValue.iVal;
  155. }
  156. return hr;
  157. }
  158. HRESULT _stdcall
  159. CyFromPropertyBag (
  160. CPropertyBag* pPropBag,
  161. LPCWSTR szPropName,
  162. CY& rcyData )
  163. {
  164. VARIANT vValue;
  165. HRESULT hr;
  166. VariantInit( &vValue );
  167. vValue.vt = VT_CY;
  168. vValue.cyVal.int64 = 0;
  169. hr = pPropBag->Read ( szPropName, &vValue );
  170. if ( SUCCEEDED( hr ) ) {
  171. hr = VariantChangeType ( &vValue, &vValue, NULL, VT_CY );
  172. if ( SUCCEEDED ( hr ) ) {
  173. rcyData.int64 = vValue.cyVal.int64;
  174. }
  175. }
  176. return hr;
  177. }
  178. HRESULT _stdcall
  179. StringFromPropertyBag (
  180. CPropertyBag* pPropBag,
  181. LPCWSTR szPropName,
  182. LPWSTR szData,
  183. DWORD* pdwBufLen )
  184. {
  185. VARIANT vValue;
  186. HRESULT hr;
  187. VariantInit( &vValue );
  188. vValue.vt = VT_BSTR;
  189. vValue.bstrVal = NULL;
  190. hr = pPropBag->Read(szPropName, &vValue );
  191. // Todo: Return buflen = 1 when no data?
  192. // Todo: Return e_fail if data found, but buffer not big enough?
  193. if ( SUCCEEDED(hr) && vValue.bstrVal ) {
  194. DWORD dwNewBufLen = SysStringLen(vValue.bstrVal) + 1; // 1 for NULL terminator
  195. if ( dwNewBufLen > 1 ) {
  196. if ( *pdwBufLen >= dwNewBufLen && NULL != szData ) {
  197. lstrcpyW ( szData, vValue.bstrVal );
  198. } else {
  199. // Insufficient buffer
  200. hr = HRESULT_FROM_WIN32 ( ERROR_INSUFFICIENT_BUFFER );
  201. }
  202. } else if ( NULL != szData ) {
  203. // Property found, string is NULL
  204. szData[0] = NULL_W;
  205. }
  206. *pdwBufLen = dwNewBufLen;
  207. } else {
  208. *pdwBufLen = 0;
  209. }
  210. return hr;
  211. }
  212. HRESULT _stdcall
  213. LLTimeFromPropertyBag (
  214. CPropertyBag* pPropBag,
  215. LPCWSTR szPropName,
  216. LONGLONG& rllData )
  217. {
  218. VARIANT vValue;
  219. HRESULT hr;
  220. VariantInit( &vValue );
  221. vValue.vt = VT_DATE;
  222. hr = pPropBag->Read ( szPropName, &vValue );
  223. if ( SUCCEEDED(hr) ) {
  224. if ( !VariantDateToLLTime ( vValue.date, &rllData ) ) {
  225. hr = E_FAIL;
  226. }
  227. VariantClear( &vValue );
  228. }
  229. return hr;
  230. }
  231. HRESULT _stdcall
  232. SlqTimeFromPropertyBag (
  233. CPropertyBag* pPropBag,
  234. WORD wFlags,
  235. PSLQ_TIME_INFO pstiDefault,
  236. PSLQ_TIME_INFO pstiData )
  237. {
  238. HRESULT hr = NOERROR;
  239. assert ( NULL != pstiData );
  240. if ( NULL == pstiData ) {
  241. hr = E_POINTER;
  242. } else {
  243. // Todo: Error handling
  244. // This method sets missing fields to default value.
  245. switch (wFlags) {
  246. case SLQ_TT_TTYPE_START:
  247. pstiData->wTimeType = SLQ_TT_TTYPE_START;
  248. pstiData->wDataType = SLQ_TT_DTYPE_DATETIME;
  249. hr = DwordFromPropertyBag (
  250. pPropBag,
  251. cwszHtmlStartMode,
  252. pstiData->dwAutoMode );
  253. if ( SLQ_AUTO_MODE_AT == pstiData->dwAutoMode ) {
  254. hr = LLTimeFromPropertyBag (
  255. pPropBag,
  256. cwszHtmlStartAtTime,
  257. pstiData->llDateTime );
  258. } else {
  259. // Original state is stopped.
  260. assert ( SLQ_AUTO_MODE_NONE == pstiData->dwAutoMode );
  261. pstiData->llDateTime = MAX_TIME_VALUE;
  262. }
  263. break;
  264. case SLQ_TT_TTYPE_STOP:
  265. pstiData->wTimeType = SLQ_TT_TTYPE_STOP;
  266. hr = DwordFromPropertyBag (
  267. pPropBag,
  268. cwszHtmlStopMode,
  269. pstiData->dwAutoMode );
  270. if ( SLQ_AUTO_MODE_AT == pstiData->dwAutoMode ) {
  271. pstiData->wDataType = SLQ_TT_DTYPE_DATETIME;
  272. hr = LLTimeFromPropertyBag (
  273. pPropBag,
  274. cwszHtmlStopAtTime,
  275. pstiData->llDateTime );
  276. } else if ( SLQ_AUTO_MODE_AFTER == pstiData->dwAutoMode ) {
  277. pstiData->wDataType = SLQ_TT_DTYPE_UNITS;
  278. hr = DwordFromPropertyBag (
  279. pPropBag,
  280. cwszHtmlStopAfterUnitType,
  281. pstiData->dwUnitType );
  282. hr = DwordFromPropertyBag (
  283. pPropBag,
  284. cwszHtmlStopAfterValue,
  285. pstiData->dwValue );
  286. } else {
  287. // Original state is stopped.
  288. assert ( SLQ_AUTO_MODE_NONE == pstiData->dwAutoMode );
  289. pstiData->wDataType = SLQ_TT_DTYPE_DATETIME;
  290. pstiData->llDateTime = MIN_TIME_VALUE;
  291. }
  292. break;
  293. case SLQ_TT_TTYPE_SAMPLE:
  294. {
  295. BOOL bUnitTypeMissing = FALSE;
  296. BOOL bUnitValueMissing = FALSE;
  297. pstiData->wTimeType = pstiDefault->wTimeType;
  298. pstiData->dwAutoMode = pstiDefault->dwAutoMode;
  299. pstiData->wDataType = pstiDefault->wDataType;
  300. hr = DwordFromPropertyBag (
  301. pPropBag,
  302. cwszHtmlSampleIntUnitType,
  303. pstiData->dwUnitType );
  304. if ( FAILED ( hr ) ) {
  305. pstiData->dwUnitType = pstiDefault->dwUnitType;
  306. bUnitTypeMissing = TRUE;
  307. }
  308. hr = DwordFromPropertyBag (
  309. pPropBag,
  310. cwszHtmlSampleIntValue,
  311. pstiData->dwValue );
  312. if ( FAILED ( hr ) ) {
  313. pstiData->dwValue = pstiDefault->dwValue;
  314. bUnitValueMissing = TRUE;
  315. }
  316. if ( bUnitTypeMissing || bUnitValueMissing ) {
  317. FLOAT fUpdateInterval;
  318. // If unit type or unit count missing from the property bag,
  319. // look for "UpdateInterval" value, from the Sysmon control object,
  320. // and use it to approximate the sample time.
  321. hr = FloatFromPropertyBag (
  322. pPropBag,
  323. cwszHtmlSysmonUpdateInterval,
  324. fUpdateInterval );
  325. if ( SUCCEEDED ( hr ) ) {
  326. pstiData->dwValue = (DWORD)(fUpdateInterval);
  327. pstiData->dwUnitType = SLQ_TT_UTYPE_SECONDS;
  328. }
  329. }
  330. break;
  331. }
  332. // Restart mode stored as a single DWORD
  333. case SLQ_TT_TTYPE_RESTART:
  334. default:
  335. hr = E_INVALIDARG;
  336. break;
  337. }
  338. }
  339. return hr;
  340. }
  341. //
  342. // Registry I/O
  343. //
  344. LONG _stdcall
  345. WriteRegistryStringValue (
  346. HKEY hKey,
  347. LPCWSTR cwszValueName,
  348. DWORD dwType,
  349. LPCWSTR pszBuffer,
  350. DWORD dwBufLen
  351. )
  352. // writes the contents of pszBuffer to szValue under hKey
  353. {
  354. LONG dwStatus = ERROR_SUCCESS;
  355. DWORD dwBufByteCount;
  356. CONST BYTE *pLclBuffer;
  357. assert ((dwType == REG_SZ) ||
  358. (dwType == REG_MULTI_SZ) ||
  359. (dwType == REG_EXPAND_SZ));
  360. if ( NULL == pszBuffer ) {
  361. // substitute an empty string
  362. pLclBuffer = (CONST BYTE *)cwszNull;
  363. dwBufByteCount = 0;
  364. } else {
  365. // use args passed in
  366. pLclBuffer = (CONST BYTE *)pszBuffer;
  367. dwBufByteCount = dwBufLen * sizeof(WCHAR);
  368. }
  369. dwStatus = RegSetValueExW (hKey,
  370. cwszValueName,
  371. 0L,
  372. dwType,
  373. (CONST BYTE *)pLclBuffer,
  374. dwBufByteCount );
  375. return dwStatus;
  376. }
  377. LONG _stdcall
  378. WriteRegistryDwordValue (
  379. HKEY hKey,
  380. LPCWSTR cwszValueName,
  381. LPDWORD pdwValue,
  382. DWORD dwType
  383. )
  384. {
  385. LONG dwStatus = ERROR_SUCCESS;
  386. DWORD dwValue = sizeof(DWORD);
  387. assert ((dwType == REG_DWORD) ||
  388. (dwType == REG_BINARY));
  389. dwStatus = RegSetValueExW (
  390. hKey,
  391. cwszValueName,
  392. 0L,
  393. dwType,
  394. (CONST BYTE *)pdwValue,
  395. dwValue);
  396. return dwStatus;
  397. }
  398. LONG _stdcall
  399. WriteRegistrySlqTime (
  400. HKEY hKey,
  401. LPCWSTR cwszValueName,
  402. PSLQ_TIME_INFO pstiData
  403. )
  404. {
  405. LONG dwStatus = ERROR_SUCCESS;
  406. DWORD dwValue = sizeof(SLQ_TIME_INFO);
  407. dwStatus = RegSetValueExW (
  408. hKey,
  409. cwszValueName,
  410. 0L,
  411. REG_BINARY,
  412. (CONST BYTE *)pstiData,
  413. dwValue);
  414. return dwStatus;
  415. }
  416. LONG _stdcall
  417. ReadRegistryDwordValue (
  418. HKEY hKey,
  419. LPCWSTR cwszValueName,
  420. LPDWORD pdwValue
  421. )
  422. {
  423. LONG dwStatus = ERROR_SUCCESS;
  424. DWORD dwValue = sizeof(DWORD);
  425. DWORD dwType = 0;
  426. DWORD dwBufferSize = 0;
  427. SLQ_TIME_INFO slqLocal;
  428. assert ( NULL != hKey );
  429. assert ( NULL != pdwValue );
  430. assert ( NULL != cwszValueName );
  431. assert ( NULL_T != cwszValueName[0] );
  432. memset (&slqLocal, 0, sizeof(SLQ_TIME_INFO));
  433. dwStatus = RegQueryValueExW (
  434. hKey,
  435. cwszValueName,
  436. NULL,
  437. &dwType,
  438. NULL,
  439. &dwBufferSize );
  440. if ( ERROR_SUCCESS == dwStatus ) {
  441. if ( ( dwBufferSize == sizeof(DWORD) )
  442. && ( ( REG_DWORD == dwType ) || ( REG_BINARY == dwType ) ) ) {
  443. // then there's something to read
  444. dwType = 0;
  445. dwStatus = RegQueryValueExW (
  446. hKey,
  447. cwszValueName,
  448. NULL,
  449. &dwType,
  450. (LPBYTE)&dwValue,
  451. &dwBufferSize);
  452. } else {
  453. // nothing to read
  454. dwStatus = ERROR_NO_DATA;
  455. }
  456. } // else dwStatus has error.
  457. if ( ERROR_SUCCESS == dwStatus ) {
  458. *pdwValue = dwValue;
  459. }
  460. return dwStatus;
  461. }
  462. LONG _stdcall
  463. ReadRegistrySlqTime (
  464. HKEY hKey,
  465. LPCWSTR cwszValueName,
  466. PSLQ_TIME_INFO pstiData
  467. )
  468. {
  469. LONG dwStatus = ERROR_SUCCESS;
  470. DWORD dwType = 0;
  471. DWORD dwBufferSize = 0;
  472. SLQ_TIME_INFO slqLocal;
  473. assert ( NULL != hKey );
  474. assert ( NULL != pstiData );
  475. assert ( NULL != cwszValueName );
  476. assert ( NULL_T != cwszValueName[0] );
  477. memset (&slqLocal, 0, sizeof(SLQ_TIME_INFO));
  478. dwStatus = RegQueryValueExW (
  479. hKey,
  480. cwszValueName,
  481. NULL,
  482. &dwType,
  483. NULL,
  484. &dwBufferSize );
  485. if ( ERROR_SUCCESS == dwStatus ) {
  486. if ( (dwBufferSize == sizeof(SLQ_TIME_INFO)) && ( REG_BINARY == dwType ) ) {
  487. // then there's something to read
  488. dwType = 0;
  489. dwStatus = RegQueryValueExW (
  490. hKey,
  491. cwszValueName,
  492. NULL,
  493. &dwType,
  494. (LPBYTE)&slqLocal,
  495. &dwBufferSize);
  496. } else {
  497. // nothing to read
  498. dwStatus = ERROR_NO_DATA;
  499. }
  500. }
  501. if ( ERROR_SUCCESS == dwStatus ) {
  502. *pstiData = slqLocal;
  503. }
  504. return dwStatus;
  505. }
  506. //
  507. // Wrapper functions for html to registry
  508. //
  509. HRESULT _stdcall
  510. StringFromPropBagAlloc (
  511. CPropertyBag* pPropBag,
  512. LPCWSTR szPropertyName,
  513. LPWSTR* pszBuffer,
  514. DWORD* pdwBufLen,
  515. DWORD* pdwStringLen )
  516. {
  517. HRESULT hr = NOERROR;
  518. LPWSTR szLocalBuffer = *pszBuffer;
  519. DWORD dwLocalBufLen = *pdwBufLen;
  520. hr = StringFromPropertyBag ( pPropBag, szPropertyName, szLocalBuffer, &dwLocalBufLen );
  521. if ( HRESULT_FROM_WIN32 ( ERROR_INSUFFICIENT_BUFFER ) == hr ) {
  522. assert ( dwLocalBufLen > *pdwBufLen );
  523. if ( NULL != szLocalBuffer ) {
  524. delete szLocalBuffer;
  525. }
  526. szLocalBuffer = new WCHAR[ dwLocalBufLen ];
  527. if ( NULL != szLocalBuffer ) {
  528. *pdwBufLen = dwLocalBufLen;
  529. hr = StringFromPropertyBag ( pPropBag, szPropertyName, szLocalBuffer, &dwLocalBufLen );
  530. } else {
  531. hr = E_OUTOFMEMORY;
  532. }
  533. }
  534. *pszBuffer = szLocalBuffer;
  535. // Length of actual string returned.
  536. if ( NULL != pdwStringLen ) {
  537. *pdwStringLen = dwLocalBufLen - 1; // Buffer length includes space for NULL
  538. }
  539. return hr;
  540. }
  541. DWORD _stdcall
  542. AddStringToMszBuffer (
  543. LPCWSTR szString,
  544. LPWSTR szBuffer,
  545. DWORD* pdwBufLen,
  546. DWORD* pdwBufStringLen )
  547. {
  548. DWORD dwStatus = ERROR_SUCCESS;
  549. assert ( NULL != szString );
  550. if ( NULL == szString ) {
  551. dwStatus = ERROR_INVALID_PARAMETER;
  552. } else {
  553. DWORD dwNewBufStringLen = 0;
  554. DWORD dwStringLen;
  555. DWORD dwLocalBufStringLen;
  556. if ( NULL == szBuffer ) {
  557. dwLocalBufStringLen = 0;
  558. } else {
  559. // Todo: Trust the user? Check in debug mode? If need to check in non-debug mode, then
  560. // just calculate
  561. }
  562. dwStringLen = lstrlenW ( szString );
  563. if ( *pdwBufStringLen > 0 ) {
  564. // Existing buffer length includes double NULL at end
  565. dwLocalBufStringLen = *pdwBufStringLen - 1;
  566. } else {
  567. dwLocalBufStringLen = 0;
  568. }
  569. dwNewBufStringLen = dwStringLen
  570. + 1 // NULL string end
  571. + dwLocalBufStringLen
  572. + 1; // NULL Msz buffer end
  573. if ( dwNewBufStringLen > *pdwBufLen ) {
  574. *pdwBufLen = dwNewBufStringLen;
  575. dwStatus = ERROR_INSUFFICIENT_BUFFER;
  576. } else {
  577. LPWSTR szNextString;
  578. szNextString = szBuffer + dwLocalBufStringLen;
  579. lstrcpyW ( szNextString, szString );
  580. szNextString += dwStringLen + 1; // +1 for string NULL
  581. szNextString[0] = NULL_W; // Msz NULL
  582. *pdwBufStringLen = dwNewBufStringLen;
  583. }
  584. }
  585. return dwStatus;
  586. }
  587. HRESULT _stdcall
  588. AddStringToMszBufferAlloc (
  589. LPCWSTR szString,
  590. LPWSTR* pszBuffer,
  591. DWORD* pdwBufLen,
  592. DWORD* pdwBufStringLen )
  593. {
  594. HRESULT hr = NOERROR;
  595. DWORD dwStatus;
  596. DWORD dwLocalBufLen = *pdwBufLen;
  597. DWORD dwLocalBufStringLen = *pdwBufStringLen;
  598. LPWSTR szLocalBuffer = *pszBuffer;
  599. dwStatus = AddStringToMszBuffer (
  600. szString,
  601. szLocalBuffer,
  602. &dwLocalBufLen,
  603. &dwLocalBufStringLen );
  604. if ( ERROR_INSUFFICIENT_BUFFER == dwStatus ) {
  605. LPWSTR szNewMszBuffer = NULL;
  606. DWORD dwNewBufSize = *pdwBufLen + DEFAULT_MSZ_BUF_LEN;
  607. assert ( dwLocalBufLen < ( *pdwBufLen + dwNewBufSize ) );
  608. if ( dwLocalBufLen < dwNewBufSize ) {
  609. dwLocalBufLen = dwNewBufSize;
  610. }
  611. szNewMszBuffer = new WCHAR[ dwLocalBufLen ];
  612. if ( NULL != szNewMszBuffer ) {
  613. if ( NULL != szLocalBuffer ) {
  614. memcpy (
  615. szNewMszBuffer,
  616. szLocalBuffer,
  617. dwLocalBufStringLen * sizeof(WCHAR) );
  618. delete szLocalBuffer;
  619. }
  620. szLocalBuffer = szNewMszBuffer;
  621. dwStatus = AddStringToMszBuffer (
  622. szString,
  623. szLocalBuffer,
  624. &dwLocalBufLen,
  625. &dwLocalBufStringLen );
  626. } else {
  627. hr = E_OUTOFMEMORY;
  628. dwLocalBufLen = 0;
  629. }
  630. } else {
  631. assert ( ERROR_INSUFFICIENT_BUFFER != dwStatus );
  632. if ( ERROR_SUCCESS != dwStatus ) {
  633. if ( ERROR_INVALID_PARAMETER == dwStatus ) {
  634. hr = E_INVALIDARG;
  635. } else {
  636. hr = E_UNEXPECTED;
  637. }
  638. }
  639. }
  640. *pszBuffer = szLocalBuffer;
  641. *pdwBufLen = dwLocalBufLen;
  642. *pdwBufStringLen = dwLocalBufStringLen;
  643. return hr;
  644. }
  645. HRESULT _stdcall
  646. InitDefaultSlqTimeInfo (
  647. DWORD dwQueryType,
  648. WORD wTimeType,
  649. PSLQ_TIME_INFO pstiData )
  650. {
  651. HRESULT hr = NOERROR;
  652. assert ( NULL != pstiData );
  653. if ( NULL == pstiData ) {
  654. hr = E_POINTER;
  655. } else {
  656. switch ( wTimeType ) {
  657. case SLQ_TT_TTYPE_START:
  658. {
  659. SYSTEMTIME stLocalTime;
  660. FILETIME ftLocalTime;
  661. GetLocalTime (&stLocalTime);
  662. SystemTimeToFileTime (&stLocalTime, &ftLocalTime);
  663. pstiData->wTimeType = SLQ_TT_TTYPE_START;
  664. pstiData->dwAutoMode = SLQ_AUTO_MODE_AFTER;
  665. pstiData->wDataType = SLQ_TT_DTYPE_DATETIME;
  666. pstiData->llDateTime = *(LONGLONG *)&ftLocalTime;
  667. break;
  668. }
  669. case SLQ_TT_TTYPE_STOP:
  670. pstiData->wTimeType = SLQ_TT_TTYPE_STOP;
  671. pstiData->dwAutoMode = SLQ_AUTO_MODE_NONE;
  672. pstiData->wDataType = SLQ_TT_DTYPE_DATETIME;
  673. pstiData->llDateTime = MAX_TIME_VALUE;
  674. break;
  675. case SLQ_TT_TTYPE_SAMPLE:
  676. pstiData->wTimeType = SLQ_TT_TTYPE_SAMPLE;
  677. pstiData->dwAutoMode = SLQ_AUTO_MODE_AFTER;
  678. pstiData->wDataType = SLQ_TT_DTYPE_UNITS;
  679. pstiData->dwUnitType = SLQ_TT_UTYPE_SECONDS;
  680. if ( SLQ_COUNTER_LOG == dwQueryType ) {
  681. pstiData->dwValue = 15;
  682. } else if ( SLQ_ALERT == dwQueryType ) {
  683. pstiData->dwValue = 5;
  684. } else {
  685. hr = E_INVALIDARG;
  686. }
  687. break;
  688. // Restart mode stored as a single DWORD
  689. case SLQ_TT_TTYPE_RESTART:
  690. default:
  691. hr = E_INVALIDARG;
  692. break;
  693. }
  694. }
  695. return hr;
  696. }
  697. /*
  698. HRESULT
  699. ProcessStringProperty (
  700. CPropertyBag* pPropBag,
  701. HKEY hKeyParent,
  702. LPCWSTR szHtmlPropertyName,
  703. LPCWSTR szRegPropertyName,
  704. DWORD dwRegType,
  705. LPWSTR* pszBuffer,
  706. DWORD* pdwBufLen )
  707. {
  708. HRESULT hr;
  709. hr = StringFromPropBagAlloc ( pPropBag, szPropertyName, *pszBuffer, *pdwBufLen );
  710. if ( SUCCEEDED ( hr ) ) {
  711. hr = WriteRegistryStringValue ( hKeyParent, szPropertyName, dwRegType, *pszBuffer );
  712. }
  713. return hr;
  714. }
  715. */
  716. LPWSTR
  717. ResourceString (
  718. UINT uID
  719. )
  720. {
  721. #define STRING_BUF_LEN 256
  722. #define NUM_BUFFERS 16
  723. static WCHAR aszBuffers[NUM_BUFFERS][STRING_BUF_LEN];
  724. static INT iBuffIndex = 0;
  725. static WCHAR szMissingString [8];
  726. // Use next buffer
  727. if (++iBuffIndex >= NUM_BUFFERS)
  728. iBuffIndex = 0;
  729. // Load and return string
  730. if (LoadStringW( NULL, uID, aszBuffers[iBuffIndex], STRING_BUF_LEN)) {
  731. return aszBuffers[iBuffIndex];
  732. } else {
  733. lstrcpyW ( szMissingString, cwszMissingResourceString );
  734. return szMissingString;
  735. }
  736. }
  737. BOOL _stdcall
  738. IsLogManMessage (
  739. DWORD dwMessageId,
  740. DWORD* pdwResourceId )
  741. {
  742. BOOL bIsLogManMsg = FALSE;
  743. DWORD dwLocalId;
  744. dwLocalId = dwMessageId & MESSAGE_RESOURCE_ID_MASK;
  745. if ( 6000 <= dwLocalId && 6040 >= dwLocalId ) {
  746. bIsLogManMsg = TRUE;
  747. }
  748. if ( NULL != pdwResourceId ) {
  749. *pdwResourceId = dwLocalId;
  750. }
  751. return bIsLogManMsg;
  752. }
  753. DWORD _stdcall
  754. FormatResourceString (
  755. DWORD dwResourceId,
  756. LPWSTR szFormatted,
  757. va_list* pargList )
  758. {
  759. DWORD dwStatus = ERROR_SUCCESS;
  760. LPWSTR szUnformatted = NULL;
  761. // Format string into temporary buffer szFormatted
  762. szUnformatted = ResourceString ( dwResourceId );
  763. // Todo: Remove argument count restriction - currently 1 LPWSTR
  764. if ( 0 != lstrcmpiW ( cwszMissingResourceString, szUnformatted ) ) {
  765. LPWSTR p1 = NULL;
  766. LPWSTR p2 = NULL;
  767. LPWSTR p3 = NULL;
  768. LPWSTR p4 = NULL;
  769. LPWSTR p5 = NULL; // Handle up to 5 arguments.
  770. LPWSTR p6 = NULL;
  771. // dwStatus = swprintf ( szFormatted, szUnformatted, pargList );
  772. p1 = va_arg ( *pargList, LPWSTR );
  773. if ( NULL == p1 ) {
  774. dwStatus = swprintf ( szFormatted, szUnformatted );
  775. } else {
  776. p2 = va_arg ( *pargList, LPWSTR );
  777. if ( NULL == p2 ) {
  778. dwStatus = swprintf ( szFormatted, szUnformatted, p1 );
  779. } else {
  780. p3 = va_arg ( *pargList, LPWSTR );
  781. if ( NULL == p3 ) {
  782. dwStatus = swprintf ( szFormatted, szUnformatted, p1, p2 );
  783. } else {
  784. p4 = va_arg ( *pargList, LPWSTR );
  785. if ( NULL == p4 ) {
  786. dwStatus = swprintf ( szFormatted, szUnformatted, p1, p2, p3 );
  787. } else {
  788. p5 = va_arg ( *pargList, LPWSTR );
  789. if ( NULL == p5 ) {
  790. dwStatus = swprintf ( szFormatted, szUnformatted, p1, p2, p3, p4 );
  791. } else {
  792. p6 = va_arg ( *pargList, LPWSTR );\
  793. assert ( NULL == p6 );
  794. dwStatus = swprintf ( szFormatted, szUnformatted, p1, p2, p3, p4, p5 );
  795. }
  796. }
  797. }
  798. }
  799. }
  800. // Swprintf returns length of formatted string
  801. if ( 0 != dwStatus ) {
  802. dwStatus = ERROR_SUCCESS;
  803. } else {
  804. dwStatus = ERROR_GEN_FAILURE;
  805. }
  806. } else {
  807. dwStatus = ERROR_GEN_FAILURE; // No resource string found
  808. }
  809. return dwStatus;
  810. }
  811. void _stdcall
  812. DisplayResourceString (
  813. DWORD dwResourceId,
  814. ... )
  815. {
  816. DWORD dwStatus = ERROR_SUCCESS;
  817. WCHAR szTemp [MAX_MESSAGE_LENGTH]; // Todo: Eliminate length restriction
  818. va_list argList;
  819. va_start(argList, dwResourceId);
  820. dwStatus = FormatResourceString (
  821. dwResourceId,
  822. szTemp,
  823. &argList );
  824. if ( ERROR_SUCCESS == dwStatus ) {
  825. wprintf ( szTemp );
  826. } else {
  827. wprintf ( cwszNoErrorMessage );
  828. }
  829. wprintf ( cwszNewLine );
  830. va_end(argList);
  831. return;
  832. }
  833. void _stdcall
  834. DisplayErrorMessage (
  835. DWORD dwMessageId,
  836. ... )
  837. {
  838. DWORD dwStatus = ERROR_SUCCESS;
  839. WCHAR szTemp [MAX_MESSAGE_LENGTH]; // Todo: Eliminate length restriction
  840. DWORD dwResourceId;
  841. va_list(argList);
  842. va_start(argList, dwMessageId);
  843. if ( IsLogManMessage ( dwMessageId, &dwResourceId ) ) {
  844. dwStatus = FormatResourceString (
  845. dwResourceId,
  846. szTemp,
  847. &argList );
  848. } else {
  849. // Format message into temporary buffer szTemp
  850. dwStatus = FormatSystemMessage (
  851. dwMessageId,
  852. szTemp,
  853. MAX_MESSAGE_LENGTH,
  854. &argList );
  855. }
  856. if ( ERROR_SUCCESS == dwStatus ) {
  857. wprintf ( szTemp );
  858. } else {
  859. wprintf ( cwszNoErrorMessage );
  860. };
  861. wprintf ( cwszNewLine );
  862. va_end(argList);
  863. return;
  864. }
  865. DWORD _stdcall
  866. FormatSystemMessage (
  867. DWORD dwMessageId,
  868. LPWSTR pszSystemMessage,
  869. DWORD dwBufLen,
  870. ... )
  871. {
  872. DWORD dwReturn = 0;
  873. HMODULE hModule = NULL;
  874. LPVOID pMsgBuf = NULL;
  875. DWORD dwFlags;
  876. va_list(argList);
  877. va_start(argList, dwBufLen);
  878. pszSystemMessage[0] = NULL_W;
  879. dwFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM;
  880. hModule = LoadLibraryW ( cwszPdhDll );
  881. if ( NULL != hModule ) {
  882. dwFlags |= FORMAT_MESSAGE_FROM_HMODULE;
  883. }
  884. dwReturn = ::FormatMessageW (
  885. dwFlags,
  886. hModule,
  887. dwMessageId,
  888. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  889. (LPWSTR)&pMsgBuf,
  890. 0,
  891. NULL );
  892. // Todo: dwReturn seems to return failure even on success. Possibly because argList is non-Null?
  893. if ( NULL != hModule ) {
  894. FreeLibrary ( hModule );
  895. }
  896. // TODO: Check buffer length
  897. if ( 0 == lstrlenW ( (LPWSTR)pMsgBuf ) ) {
  898. swprintf ( pszSystemMessage, cwszMessageIdFormatString, dwMessageId );
  899. } else {
  900. swprintf ( pszSystemMessage, cwszSystemError, (LPWSTR)pMsgBuf );
  901. }
  902. LocalFree ( pMsgBuf );
  903. va_end(argList);
  904. return ERROR_SUCCESS;
  905. }
  906. INT
  907. GetNumSeparators (
  908. LPTSTR& rpDecimal,
  909. LPTSTR& rpThousand )
  910. {
  911. #define NUM_BUF_LEN 4
  912. INT iLength;
  913. static TCHAR szDecimal[NUM_BUF_LEN];
  914. static TCHAR szThousand[NUM_BUF_LEN];
  915. rpDecimal = NULL;
  916. rpThousand = NULL;
  917. iLength = GetLocaleInfo (
  918. LOCALE_USER_DEFAULT,
  919. LOCALE_SDECIMAL,
  920. szDecimal,
  921. NUM_BUF_LEN );
  922. if ( 0 != iLength ) {
  923. iLength = GetLocaleInfo (
  924. LOCALE_USER_DEFAULT,
  925. LOCALE_STHOUSAND,
  926. szThousand,
  927. NUM_BUF_LEN );
  928. }
  929. if ( 0 != iLength ) {
  930. rpDecimal = szDecimal;
  931. rpThousand = szThousand;
  932. }
  933. return iLength;
  934. }
  935. BOOL _stdcall
  936. FileRead (
  937. HANDLE hFile,
  938. void* lpMemory,
  939. DWORD nAmtToRead)
  940. {
  941. BOOL bSuccess ;
  942. DWORD nAmtRead ;
  943. bSuccess = ReadFile (hFile, lpMemory, nAmtToRead, &nAmtRead, NULL) ;
  944. return (bSuccess && (nAmtRead == nAmtToRead)) ;
  945. } // FileRead
  946. BOOL _stdcall
  947. FileWrite (
  948. HANDLE hFile,
  949. void* lpMemory,
  950. DWORD nAmtToWrite)
  951. {
  952. BOOL bSuccess = FALSE;
  953. DWORD nAmtWritten = 0;
  954. DWORD dwFileSizeLow, dwFileSizeHigh;
  955. LONGLONG llResultSize;
  956. dwFileSizeLow = GetFileSize (hFile, &dwFileSizeHigh);
  957. // limit file size to 2GB
  958. if (dwFileSizeHigh > 0) {
  959. SetLastError (ERROR_WRITE_FAULT);
  960. bSuccess = FALSE;
  961. } else {
  962. // note that the error return of this function is 0xFFFFFFFF
  963. // since that is > the file size limit, this will be interpreted
  964. // as an error (a size error) so it's accounted for in the following
  965. // test.
  966. llResultSize = dwFileSizeLow + nAmtToWrite;
  967. if (llResultSize >= 0x80000000) {
  968. SetLastError (ERROR_WRITE_FAULT);
  969. bSuccess = FALSE;
  970. } else {
  971. // write buffer to file
  972. bSuccess = WriteFile (hFile, lpMemory, nAmtToWrite, &nAmtWritten, NULL) ;
  973. if (bSuccess)
  974. bSuccess = (nAmtWritten == nAmtToWrite ? TRUE : FALSE);
  975. if ( !bSuccess ) {
  976. SetLastError (ERROR_WRITE_FAULT);
  977. }
  978. }
  979. }
  980. return (bSuccess) ;
  981. } // FileWrite
  982. // This routine extract the filename portion from a given full-path filename
  983. LPTSTR _stdcall
  984. ExtractFileName (LPTSTR pFileSpec)
  985. {
  986. LPTSTR pFileName = NULL ;
  987. TCHAR DIRECTORY_DELIMITER1 = TEXT('\\') ;
  988. TCHAR DIRECTORY_DELIMITER2 = TEXT(':') ;
  989. if (pFileSpec)
  990. {
  991. pFileName = pFileSpec + lstrlen (pFileSpec) ;
  992. while (*pFileName != DIRECTORY_DELIMITER1 &&
  993. *pFileName != DIRECTORY_DELIMITER2)
  994. {
  995. if (pFileName == pFileSpec)
  996. {
  997. // done when no directory delimiter is found
  998. break ;
  999. }
  1000. pFileName-- ;
  1001. }
  1002. if (*pFileName == DIRECTORY_DELIMITER1 ||
  1003. *pFileName == DIRECTORY_DELIMITER2)
  1004. {
  1005. // directory delimiter found, point the
  1006. // filename right after it
  1007. pFileName++ ;
  1008. }
  1009. }
  1010. return pFileName ;
  1011. } // ExtractFileName
  1012. BOOL _stdcall
  1013. LoadDefaultLogFileFolder(
  1014. TCHAR *szFolder
  1015. )
  1016. {
  1017. DWORD nErr;
  1018. HKEY hKey;
  1019. DWORD dwDataType;
  1020. DWORD dwDataSize;
  1021. if (szFolder == NULL)
  1022. return FALSE;
  1023. nErr = RegOpenKey(
  1024. HKEY_LOCAL_MACHINE,
  1025. _T("System\\CurrentControlSet\\Services\\SysmonLog"),
  1026. &hKey
  1027. );
  1028. if (nErr != ERROR_SUCCESS)
  1029. return FALSE;
  1030. *szFolder = 0;
  1031. // NOTE: Assumes szFolder has enough storage for RegQuery to work
  1032. nErr = RegQueryValueEx(
  1033. hKey,
  1034. _T("DefaultLogFileFolder"),
  1035. NULL,
  1036. &dwDataType,
  1037. (LPBYTE) szFolder,
  1038. (LPDWORD) &dwDataSize
  1039. );
  1040. RegCloseKey(hKey);
  1041. return (nErr == ERROR_SUCCESS);
  1042. }
  1043. DWORD _stdcall
  1044. ParseFolderPath(
  1045. LPCTSTR szOrigPath,
  1046. LPTSTR szBuffer,
  1047. INT* piBufLen )
  1048. {
  1049. DWORD dwStatus = ERROR_SUCCESS;
  1050. TCHAR szLocalPath[MAX_PATH];
  1051. TCHAR cPercent = _T('%');
  1052. TCHAR* pBeginSymChar;
  1053. const TCHAR* pNonSymChar;
  1054. TCHAR* pLocalPathNext;
  1055. INT iTempLen;
  1056. // Return error if original buffer isn't large enough.
  1057. pNonSymChar = szOrigPath;
  1058. pLocalPathNext = szLocalPath;
  1059. // Find and parse each symbol, adding to szLocalPath
  1060. while ( NULL != ( pBeginSymChar = _tcschr ( pNonSymChar, cPercent ) ) ) {
  1061. TCHAR* pEndSymChar;
  1062. // Move pre-symbol part of path to szLocalPath
  1063. // lstrcpyn count includes terminating NULL character.
  1064. iTempLen = (INT)( pBeginSymChar - pNonSymChar ) + 1;
  1065. lstrcpyn ( pLocalPathNext, pNonSymChar, iTempLen );
  1066. // Move pointer to NULL terminator
  1067. pLocalPathNext += iTempLen - 1;
  1068. // Find end symbol delimiter
  1069. pEndSymChar = _tcschr ( pBeginSymChar + 1, cPercent );
  1070. if ( NULL != pEndSymChar ) {
  1071. TCHAR szSymbol[MAX_PATH];
  1072. TCHAR* pszTranslated;
  1073. // Parse symbol
  1074. lstrcpyn ( szSymbol,
  1075. pBeginSymChar + 1,
  1076. (int)(pEndSymChar - pBeginSymChar) );
  1077. pszTranslated = _tgetenv ( szSymbol );
  1078. if ( NULL != pszTranslated ) {
  1079. iTempLen = lstrlen (pszTranslated) + 1;
  1080. lstrcpyn ( pLocalPathNext, pszTranslated, iTempLen );
  1081. // Move pointer to NULL terminator
  1082. pLocalPathNext += iTempLen - 1;
  1083. // Set up to find next symbol.
  1084. pNonSymChar = pEndSymChar + 1;
  1085. if ( 0 == lstrlen (pNonSymChar) ) {
  1086. // Done.
  1087. break;
  1088. }
  1089. } else {
  1090. // Path incorrect.
  1091. dwStatus = ERROR_BAD_PATHNAME;
  1092. break;
  1093. }
  1094. } else {
  1095. // Path incorrect.
  1096. dwStatus = ERROR_BAD_PATHNAME;
  1097. break;
  1098. }
  1099. }
  1100. if ( ERROR_SUCCESS == dwStatus ) {
  1101. // Move last part of path to szLocalPath
  1102. iTempLen = lstrlen (pNonSymChar) + 1;
  1103. lstrcpyn ( pLocalPathNext, pNonSymChar, iTempLen );
  1104. // Move string to buffer, checking size.
  1105. // Add room for NULL termination
  1106. iTempLen = lstrlen (szLocalPath ) + 1;
  1107. if ( *piBufLen >= iTempLen ) {
  1108. lstrcpy ( szBuffer, szLocalPath );
  1109. } else {
  1110. dwStatus = ERROR_INSUFFICIENT_BUFFER;
  1111. }
  1112. *piBufLen = iTempLen;
  1113. }
  1114. return dwStatus;
  1115. }
  1116. DWORD
  1117. SlqTimeToMilliseconds (
  1118. SLQ_TIME_INFO* pTimeInfo,
  1119. LONGLONG* pllmsecs)
  1120. {
  1121. BOOL bStatus = TRUE; // Success
  1122. if ( SLQ_TT_DTYPE_UNITS == pTimeInfo->wDataType ) {
  1123. switch (pTimeInfo->dwUnitType) {
  1124. case SLQ_TT_UTYPE_SECONDS:
  1125. *pllmsecs = pTimeInfo->dwValue;
  1126. break;
  1127. case SLQ_TT_UTYPE_MINUTES:
  1128. *pllmsecs = pTimeInfo->dwValue * SECONDS_IN_MINUTE;
  1129. break;
  1130. case SLQ_TT_UTYPE_HOURS:
  1131. *pllmsecs = pTimeInfo->dwValue * SECONDS_IN_HOUR;
  1132. break;
  1133. case SLQ_TT_UTYPE_DAYS:
  1134. *pllmsecs = pTimeInfo->dwValue * SECONDS_IN_DAY;
  1135. break;
  1136. default:
  1137. bStatus = FALSE;
  1138. *pllmsecs = 0;
  1139. }
  1140. *pllmsecs *= 1000;
  1141. } else {
  1142. bStatus = FALSE;
  1143. }
  1144. return bStatus;
  1145. }
  1146. static
  1147. DWORD _stdcall
  1148. ScanHexFormat(
  1149. IN LPCWSTR szBuffer,
  1150. IN ULONG ulMaximumLength,
  1151. IN LPCWSTR szFormat,
  1152. ...)
  1153. /*++
  1154. Routine Description:
  1155. Scans a source szBuffer and places values from that buffer into the parameters
  1156. as specified by szFormat.
  1157. Arguments:
  1158. szBuffer -
  1159. Contains the source buffer which is to be scanned.
  1160. ulMaximumLength -
  1161. Contains the maximum length in characters for which szBuffer is searched.
  1162. This implies that szBuffer need not be UNICODE_NULL terminated.
  1163. szFormat -
  1164. Contains the format string which defines both the acceptable string format
  1165. contained in szBuffer, and the variable parameters which follow.
  1166. NOTE: This code is from \ntos\rtl\guid.c
  1167. Return Value:
  1168. Returns the number of parameters filled if the end of the szBuffer is reached,
  1169. else -1 on an error.
  1170. --*/
  1171. {
  1172. va_list ArgList;
  1173. int iFormatItems;
  1174. va_start(ArgList, szFormat);
  1175. for (iFormatItems = 0;;) {
  1176. switch (*szFormat) {
  1177. case 0:
  1178. return (*szBuffer && ulMaximumLength) ? -1 : iFormatItems;
  1179. case '%':
  1180. szFormat++;
  1181. if (*szFormat != '%') {
  1182. ULONG Number;
  1183. int Width;
  1184. int Long;
  1185. PVOID Pointer;
  1186. for (Long = 0, Width = 0;; szFormat++) {
  1187. if ((*szFormat >= '0') && (*szFormat <= '9')) {
  1188. Width = Width * 10 + *szFormat - '0';
  1189. } else if (*szFormat == 'l') {
  1190. Long++;
  1191. } else if ((*szFormat == 'X') || (*szFormat == 'x')) {
  1192. break;
  1193. }
  1194. }
  1195. szFormat++;
  1196. for (Number = 0; Width--; szBuffer++, ulMaximumLength--) {
  1197. if (!ulMaximumLength)
  1198. return (DWORD)(-1);
  1199. Number *= 16;
  1200. if ((*szBuffer >= '0') && (*szBuffer <= '9')) {
  1201. Number += (*szBuffer - '0');
  1202. } else if ((*szBuffer >= 'a') && (*szBuffer <= 'f')) {
  1203. Number += (*szBuffer - 'a' + 10);
  1204. } else if ((*szBuffer >= 'A') && (*szBuffer <= 'F')) {
  1205. Number += (*szBuffer - 'A' + 10);
  1206. } else {
  1207. return (DWORD)(-1);
  1208. }
  1209. }
  1210. Pointer = va_arg(ArgList, PVOID);
  1211. if (Long) {
  1212. *(PULONG)Pointer = Number;
  1213. } else {
  1214. *(PUSHORT)Pointer = (USHORT)Number;
  1215. }
  1216. iFormatItems++;
  1217. break;
  1218. }
  1219. /* no break */
  1220. default:
  1221. if (!ulMaximumLength || (*szBuffer != *szFormat)) {
  1222. return (DWORD)(-1);
  1223. }
  1224. szBuffer++;
  1225. ulMaximumLength--;
  1226. szFormat++;
  1227. break;
  1228. }
  1229. }
  1230. }
  1231. DWORD _stdcall
  1232. GuidFromString(
  1233. IN PUNICODE_STRING GuidString,
  1234. OUT GUID* Guid
  1235. )
  1236. /*++
  1237. Routine Description:
  1238. Retrieves a the binary format of a textual GUID presented in the standard
  1239. string version of a GUID: "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}".
  1240. Arguments:
  1241. GuidString -
  1242. Place from which to retrieve the textual form of the GUID.
  1243. Guid -
  1244. Place in which to put the binary form of the GUID.
  1245. NOTE: This code is from \ntos\rtl\guid.c
  1246. Return Value:
  1247. Returns ERROR_SUCCESS if the buffer contained a valid GUID, else
  1248. ERROR_INVALID_PARAMETER if the string was invalid.
  1249. --*/
  1250. {
  1251. USHORT Data4[8];
  1252. int Count;
  1253. if (ScanHexFormat(GuidString->Buffer, GuidString->Length / sizeof(WCHAR), cwszGuidFormat, &Guid->Data1, &Guid->Data2, &Guid->Data3, &Data4[0], &Data4[1], &Data4[2], &Data4[3], &Data4[4], &Data4[5], &Data4[6], &Data4[7]) == -1) {
  1254. return (DWORD)(ERROR_INVALID_PARAMETER);
  1255. }
  1256. for (Count = 0; Count < sizeof(Data4)/sizeof(Data4[0]); Count++) {
  1257. Guid->Data4[Count] = (UCHAR)Data4[Count];
  1258. }
  1259. return ERROR_SUCCESS;
  1260. }
  1261. DWORD __stdcall
  1262. IsValidDirPath (
  1263. LPCWSTR cszPath,
  1264. BOOL bLastNameIsDirectory,
  1265. BOOL bCreateMissingDirs,
  1266. BOOL& rbIsValid )
  1267. /*++
  1268. Routine Description:
  1269. Creates the directory specified in szPath and any other "higher"
  1270. directories in the specified path that don't exist.
  1271. Arguments:
  1272. IN LPCWSTR cszPath
  1273. directory path to create (assumed to be a DOS path, not a UNC)
  1274. IN BOOL bLastNameIsDirectory
  1275. TRUE when the last name in the path is a Directory and not a File
  1276. FALSE if the last name is a file
  1277. IN BOOL bCreateMissingDirs
  1278. TRUE will create any dirs in the path that are not found
  1279. FALSE will only test for existence and not create any
  1280. missing dirs.
  1281. OUT BOOL rbIsValid
  1282. TRUE if the directory path now exists
  1283. FALSE if error (GetLastError to find out why)
  1284. Return Value:
  1285. DWSTATUS
  1286. --*/
  1287. {
  1288. WCHAR szLocalPath[MAX_PATH+1];
  1289. LPWSTR szEnd;
  1290. LPSECURITY_ATTRIBUTES lpSA = NULL;
  1291. DWORD dwAttr;
  1292. DWORD dwStatus = ERROR_SUCCESS;
  1293. rbIsValid = FALSE;
  1294. ZeroMemory ( szLocalPath, sizeof ( szLocalPath ) );
  1295. if ( 0 < GetFullPathNameW (
  1296. cszPath,
  1297. MAX_PATH,
  1298. szLocalPath,
  1299. NULL ) ) {
  1300. szEnd = &szLocalPath[3];
  1301. if ( NULL_W != *szEnd ) {
  1302. // then there are sub dirs to create
  1303. while ( NULL_W != *szEnd ) {
  1304. // go to next backslash
  1305. while ( ( BACKSLASH_W != *szEnd ) && ( NULL_W != *szEnd ) ) {
  1306. szEnd++;
  1307. }
  1308. if ( BACKSLASH_W != *szEnd ) {
  1309. // terminate path here and create directory
  1310. *szEnd = NULL_W;
  1311. if (bCreateMissingDirs) {
  1312. if (!CreateDirectoryW (szLocalPath, lpSA)) {
  1313. // see what the error was and "adjust" it if necessary
  1314. dwStatus = GetLastError();
  1315. if ( ERROR_ALREADY_EXISTS == dwStatus ) {
  1316. // this is OK
  1317. dwStatus = ERROR_SUCCESS;
  1318. rbIsValid = TRUE;
  1319. } else {
  1320. rbIsValid = FALSE;
  1321. }
  1322. } else {
  1323. // directory created successfully so update count
  1324. rbIsValid = TRUE;
  1325. }
  1326. } else {
  1327. if ((dwAttr = GetFileAttributesW(szLocalPath)) != 0xFFFFFFFF) {
  1328. // make sure it's a dir
  1329. if ((dwAttr & FILE_ATTRIBUTE_DIRECTORY) ==
  1330. FILE_ATTRIBUTE_DIRECTORY) {
  1331. rbIsValid = TRUE;
  1332. } else {
  1333. // if any dirs fail, then clear the return value
  1334. rbIsValid = FALSE;
  1335. }
  1336. } else {
  1337. // if any dirs fail, then clear the return value
  1338. rbIsValid = FALSE;
  1339. }
  1340. }
  1341. // replace backslash and go to next dir
  1342. *szEnd++ = BACKSLASH_W;
  1343. }
  1344. }
  1345. // create last dir in path now if it's a dir name and not a filename
  1346. if ( bLastNameIsDirectory ) {
  1347. if (bCreateMissingDirs) {
  1348. if (!CreateDirectoryW (szLocalPath, lpSA)) {
  1349. // see what the error was and "adjust" it if necessary
  1350. dwStatus = GetLastError();
  1351. if ( ERROR_ALREADY_EXISTS == dwStatus ) {
  1352. // this is OK
  1353. dwStatus = ERROR_SUCCESS;
  1354. rbIsValid = TRUE;
  1355. } else {
  1356. rbIsValid = FALSE;
  1357. }
  1358. } else {
  1359. // directory created successfully
  1360. rbIsValid = TRUE;
  1361. }
  1362. } else {
  1363. if ((dwAttr = GetFileAttributesW(szLocalPath)) != 0xFFFFFFFF) {
  1364. // make sure it's a dir
  1365. if ((dwAttr & FILE_ATTRIBUTE_DIRECTORY) ==
  1366. FILE_ATTRIBUTE_DIRECTORY) {
  1367. rbIsValid = TRUE;
  1368. } else {
  1369. // if any dirs fail, then clear the return value
  1370. rbIsValid = FALSE;
  1371. }
  1372. } else {
  1373. // if any dirs fail, then clear the return value
  1374. rbIsValid = FALSE;
  1375. }
  1376. }
  1377. }
  1378. } else {
  1379. // else this is a root dir only so return success.
  1380. dwStatus = ERROR_SUCCESS;
  1381. rbIsValid = TRUE;
  1382. }
  1383. } else {
  1384. dwStatus = GetLastError();
  1385. }
  1386. return dwStatus;
  1387. }
  1388. BOOL _stdcall
  1389. IsValidFileName ( LPCWSTR cszFileName )
  1390. {
  1391. LPWSTR szNext;
  1392. BOOL bRetVal = TRUE;
  1393. if ( MAX_PATH < lstrlenW(cszFileName) ) {
  1394. bRetVal = FALSE;
  1395. } else {
  1396. szNext = const_cast<LPWSTR>(cszFileName);
  1397. while(*szNext != '\0'){
  1398. if (*szNext == '?' ||
  1399. *szNext == '\\' ||
  1400. *szNext == '*' ||
  1401. *szNext == '|' ||
  1402. *szNext == '<' ||
  1403. *szNext == '>' ||
  1404. *szNext == '/' ||
  1405. *szNext == ':' ||
  1406. *szNext == '.' ||
  1407. *szNext == '\"'
  1408. ){
  1409. bRetVal = FALSE;
  1410. break;
  1411. }
  1412. szNext++;
  1413. }
  1414. }
  1415. return bRetVal;
  1416. }