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.

2370 lines
61 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 <windows.h>
  14. #include <assert.h>
  15. #include <math.h>
  16. #include <winperf.h>
  17. #include "utils.h"
  18. #include "unihelpr.h"
  19. #include "globals.h"
  20. #include "winhelpr.h"
  21. #include "polyline.h" // For eDataSourceType
  22. #include <strsafe.h>
  23. #include "smonmsg.h" // For error string IDs.
  24. #define NUM_RESOURCE_STRING_BUFFERS 16
  25. #define MISSING_RESOURCE_STRING L"????"
  26. #define szHexFormat L"0x%08lX"
  27. #define szLargeHexFormat L"0x%08lX%08lX"
  28. LPCWSTR cszSqlDataSourceFormat = L"SQL:%s!%s";
  29. //==========================================================================//
  30. // Exported Functions //
  31. //==========================================================================//
  32. VOID
  33. Line (
  34. IN HDC hDC,
  35. IN HPEN hPen,
  36. IN INT x1,
  37. IN INT y1,
  38. IN INT x2,
  39. IN INT y2
  40. )
  41. {
  42. HPEN hPenPrevious = NULL;
  43. assert ( NULL != hDC );
  44. if ( NULL != hDC ) {
  45. if ( NULL != hPen ) {
  46. hPenPrevious = (HPEN)SelectObject (hDC, hPen) ;
  47. }
  48. MoveToEx (hDC, x1, y1, NULL) ;
  49. LineTo (hDC, x2, y2) ;
  50. if ( NULL != hPen ) {
  51. SelectObject (hDC, hPenPrevious);
  52. }
  53. }
  54. }
  55. VOID
  56. Fill (
  57. IN HDC hDC,
  58. IN DWORD rgbColor,
  59. IN LPRECT lpRect
  60. )
  61. {
  62. HBRUSH hBrush = NULL;
  63. assert ( NULL != hDC && NULL != lpRect );
  64. if ( NULL != hDC && NULL != lpRect ) {
  65. hBrush = CreateSolidBrush (rgbColor) ;
  66. if ( NULL != hBrush ) {
  67. FillRect (hDC, lpRect, hBrush) ;
  68. DeleteObject (hBrush) ;
  69. }
  70. }
  71. }
  72. INT
  73. TextWidth (
  74. IN HDC hDC,
  75. IN LPCWSTR lpszText
  76. )
  77. {
  78. SIZE size ;
  79. INT iReturn;
  80. iReturn = 0;
  81. assert ( NULL != hDC && NULL != lpszText );
  82. if ( NULL != lpszText && NULL != hDC) {
  83. if ( GetTextExtentPoint (hDC, lpszText, lstrlen (lpszText), &size) ) {
  84. iReturn = size.cx;
  85. }
  86. }
  87. return iReturn;
  88. }
  89. INT
  90. FontHeight (
  91. IN HDC hDC,
  92. IN BOOL bIncludeLeading
  93. )
  94. {
  95. TEXTMETRIC tm ;
  96. INT iReturn = 0;
  97. assert ( NULL != hDC );
  98. if ( NULL != hDC ) {
  99. GetTextMetrics (hDC, &tm) ;
  100. if (bIncludeLeading) {
  101. iReturn = tm.tmHeight + tm.tmExternalLeading;
  102. } else {
  103. iReturn = tm.tmHeight;
  104. }
  105. }
  106. return iReturn;
  107. }
  108. INT
  109. TextAvgWidth (
  110. IN HDC hDC,
  111. IN INT iNumChars
  112. )
  113. {
  114. TEXTMETRIC tm ;
  115. INT xAvgWidth ;
  116. INT iReturn = 0;
  117. assert ( NULL != hDC );
  118. if ( NULL != hDC ) {
  119. GetTextMetrics (hDC, &tm) ;
  120. xAvgWidth = iNumChars * tm.tmAveCharWidth ;
  121. // add 10% slop
  122. iReturn = MulDiv (xAvgWidth, 11, 10);
  123. }
  124. return iReturn;
  125. }
  126. BOOL
  127. DialogEnable (
  128. IN HWND hDlg,
  129. IN WORD wID,
  130. IN BOOL bEnable
  131. )
  132. /*
  133. Effect: Enable or disable (based on bEnable) the control
  134. identified by wID in dialog hDlg.
  135. See Also: DialogShow.
  136. */
  137. {
  138. BOOL bStatus = TRUE; // Success
  139. DWORD dwStatus = ERROR_SUCCESS;
  140. HWND hControl ;
  141. assert ( NULL != hDlg );
  142. if ( NULL != hDlg ) {
  143. hControl = GetDlgItem (hDlg, wID) ;
  144. if (hControl) {
  145. if ( 0 == EnableWindow (hControl, bEnable) ) {
  146. dwStatus = GetLastError();
  147. if ( ERROR_SUCCESS != dwStatus ) {
  148. bStatus = FALSE;
  149. }
  150. }
  151. } else {
  152. bStatus = FALSE;
  153. }
  154. } else {
  155. bStatus = FALSE;
  156. }
  157. return bStatus;
  158. }
  159. VOID
  160. DialogShow (
  161. IN HWND hDlg,
  162. IN WORD wID,
  163. IN BOOL bShow
  164. )
  165. {
  166. HWND hControl ;
  167. assert ( NULL != hDlg );
  168. if ( NULL != hDlg ) {
  169. hControl = GetDlgItem (hDlg, wID) ;
  170. if (hControl) {
  171. ShowWindow (hControl, bShow ? SW_SHOW : SW_HIDE) ;
  172. }
  173. }
  174. }
  175. FLOAT
  176. DialogFloat (
  177. IN HWND hDlg,
  178. IN WORD wControlID,
  179. OUT BOOL *pbOK)
  180. /*
  181. Effect: Return a floating point representation of the string
  182. value found in the control wControlID of hDlg.
  183. Internals: We use sscanf instead of atof becuase atof returns a
  184. double. This may or may not be the right thing to do.
  185. */
  186. {
  187. WCHAR szValue [MAX_VALUE_LEN] ;
  188. FLOAT eValue = 0.0;
  189. UINT uiCharCount = 0;
  190. INT iNumScanned = 0 ;
  191. assert ( NULL != hDlg );
  192. assert ( NULL != pbOK );
  193. //
  194. // If any errors, iNumScanned remains 0 and *pbOK = FALSE
  195. //
  196. if ( NULL != hDlg ) {
  197. uiCharCount = DialogText (hDlg, wControlID, szValue) ;
  198. if ( 0 < uiCharCount ) {
  199. iNumScanned = swscanf (szValue, L"%e", &eValue) ;
  200. }
  201. }
  202. if (pbOK) {
  203. *pbOK = ( 1 == iNumScanned ) ;
  204. }
  205. return (eValue) ;
  206. }
  207. BOOL NeedEllipses (
  208. IN HDC hAttribDC,
  209. IN LPCWSTR pszText,
  210. IN INT nTextLen,
  211. IN INT xMaxExtent,
  212. IN INT xEllipses,
  213. OUT INT *pnChars
  214. )
  215. {
  216. SIZE size;
  217. *pnChars = 0;
  218. // If no space or no chars, just return
  219. if (xMaxExtent <= 0 || nTextLen == 0) {
  220. return FALSE;
  221. }
  222. assert ( NULL != hAttribDC
  223. && NULL != pszText
  224. && NULL != pnChars );
  225. if ( NULL == hAttribDC
  226. || NULL == pszText
  227. || NULL == pnChars ) {
  228. return FALSE;
  229. }
  230. // Find out how many characters will fit
  231. GetTextExtentExPoint(hAttribDC, pszText, nTextLen, xMaxExtent, pnChars, NULL, &size);
  232. // If all or none fit, we're done
  233. if (*pnChars == nTextLen || *pnChars == 0) {
  234. return FALSE;
  235. }
  236. // How many chars will fit with ellipses?
  237. if (xMaxExtent > xEllipses) {
  238. GetTextExtentExPoint(hAttribDC, pszText, *pnChars, (xMaxExtent - xEllipses),
  239. pnChars, NULL, &size);
  240. } else {
  241. *pnChars = 0;
  242. }
  243. // Better to show one char than just ellipses
  244. if ( 0 == *pnChars ) {
  245. *pnChars = 1;
  246. return FALSE;
  247. }
  248. return TRUE;
  249. }
  250. VOID
  251. FitTextOut (
  252. IN HDC hDC,
  253. IN HDC hAttribDC,
  254. IN UINT fuOptions,
  255. IN CONST RECT *lprc,
  256. IN LPCWSTR lpString,
  257. IN INT cchCount,
  258. IN INT iAlign,
  259. IN BOOL fVertical
  260. )
  261. {
  262. LPWSTR szOutput = NULL;
  263. LPWSTR szDisplay = NULL;
  264. INT iExtent;
  265. INT nOutCnt = 0;
  266. SIZE size;
  267. INT x,y;
  268. assert ( NULL != hAttribDC
  269. && NULL != lprc
  270. && NULL != lpString );
  271. if ( NULL != hAttribDC
  272. && NULL != lprc
  273. && NULL != lpString ) {
  274. szDisplay = const_cast<LPWSTR>(lpString);
  275. //
  276. // Add one for NULL
  277. //
  278. szOutput = new WCHAR [ cchCount + ELLIPSES_CNT + 1 ];
  279. if ( NULL != szOutput ) {
  280. iExtent = fVertical ? (lprc->bottom - lprc->top) : (lprc->right - lprc->left);
  281. GetTextExtentPoint (hAttribDC, ELLIPSES, ELLIPSES_CNT, &size) ;
  282. if (NeedEllipses(hAttribDC, lpString, cchCount, iExtent, size.cx, &nOutCnt)) {
  283. ZeroMemory ( szOutput, (cchCount + ELLIPSES_CNT + 1) * sizeof(WCHAR) );
  284. StringCchCopyN ( szOutput, cchCount + ELLIPSES_CNT + 1, lpString, cchCount );
  285. StringCchCopy(
  286. &szOutput[nOutCnt],
  287. (cchCount + ELLIPSES_CNT + 1) - nOutCnt,
  288. ELLIPSES );
  289. nOutCnt += ELLIPSES_CNT;
  290. szDisplay = szOutput;
  291. }
  292. }
  293. if (fVertical) {
  294. switch (iAlign) {
  295. case TA_CENTER:
  296. y = (lprc->top + lprc->bottom) / 2;
  297. break;
  298. case TA_RIGHT:
  299. y = lprc->top;
  300. break;
  301. default:
  302. y = lprc->bottom;
  303. break;
  304. }
  305. x = lprc->left;
  306. }
  307. else {
  308. switch (iAlign) {
  309. case TA_CENTER:
  310. x = (lprc->left + lprc->right) / 2;
  311. break;
  312. case TA_RIGHT:
  313. x = lprc->right;
  314. break;
  315. default:
  316. x = lprc->left;
  317. break;
  318. }
  319. y = lprc->top;
  320. }
  321. ExtTextOut(hDC, x, y, fuOptions, lprc, szDisplay, nOutCnt, NULL);
  322. }
  323. if ( NULL != szOutput ) {
  324. delete [] szOutput;
  325. }
  326. }
  327. BOOL
  328. TruncateLLTime (
  329. IN LONGLONG llTime,
  330. OUT LONGLONG* pllTime
  331. )
  332. {
  333. SYSTEMTIME SystemTime;
  334. BOOL bReturn = FALSE;
  335. assert ( NULL != pllTime );
  336. if ( NULL != pllTime ) {
  337. if ( FileTimeToSystemTime((FILETIME*)&llTime, &SystemTime) ) {
  338. SystemTime.wMilliseconds = 0;
  339. bReturn = SystemTimeToFileTime(&SystemTime, (FILETIME*)pllTime);
  340. }
  341. }
  342. return bReturn;
  343. }
  344. BOOL
  345. LLTimeToVariantDate (
  346. IN LONGLONG llTime,
  347. OUT DATE *pdate
  348. )
  349. {
  350. BOOL bReturn = FALSE;
  351. SYSTEMTIME SystemTime;
  352. assert ( NULL != pdate );
  353. if ( NULL != pdate ) {
  354. if ( FileTimeToSystemTime((FILETIME*)&llTime, &SystemTime) ) {
  355. bReturn = SystemTimeToVariantTime(&SystemTime, pdate);
  356. }
  357. }
  358. return bReturn;
  359. }
  360. BOOL
  361. VariantDateToLLTime (
  362. IN DATE date,
  363. OUT LONGLONG *pllTime
  364. )
  365. {
  366. BOOL bReturn = FALSE;
  367. SYSTEMTIME SystemTime;
  368. assert ( NULL != pllTime );
  369. if ( NULL != pllTime ) {
  370. if ( VariantTimeToSystemTime(date, &SystemTime) ) {
  371. bReturn = SystemTimeToFileTime(&SystemTime,(FILETIME*)pllTime);
  372. }
  373. }
  374. return bReturn;
  375. }
  376. //
  377. // WideStringFromStream also supports multi-sz
  378. //
  379. HRESULT
  380. WideStringFromStream (
  381. LPSTREAM pIStream,
  382. LPWSTR *ppsz,
  383. INT nLen
  384. )
  385. {
  386. ULONG bc = 0;
  387. LPWSTR pszWide = NULL;
  388. HRESULT hr = E_POINTER;
  389. assert ( NULL != pIStream && NULL != ppsz );
  390. // This method does not perform conversion from W to T.
  391. assert ( sizeof(WCHAR) == sizeof(WCHAR) );
  392. if ( NULL != pIStream
  393. && NULL != ppsz ) {
  394. *ppsz = NULL;
  395. if (nLen == 0) {
  396. hr = S_OK;
  397. } else {
  398. pszWide = new WCHAR[nLen + 1];
  399. if (pszWide == NULL) {
  400. hr = E_OUTOFMEMORY;
  401. }
  402. else {
  403. hr = pIStream->Read(pszWide, nLen*sizeof(WCHAR), &bc);
  404. }
  405. if (SUCCEEDED(hr)) {
  406. if (bc != (ULONG)nLen*sizeof(WCHAR)) {
  407. hr = E_FAIL;
  408. }
  409. }
  410. if (SUCCEEDED(hr)) {
  411. // Write ending NULL for non-multisz strings.
  412. pszWide[nLen] = L'\0';
  413. *ppsz = new WCHAR [nLen + 1];
  414. if ( NULL != *ppsz ) {
  415. memcpy(*ppsz, pszWide, (nLen+1)*sizeof(WCHAR) );
  416. } else {
  417. hr = E_OUTOFMEMORY;
  418. }
  419. }
  420. if (pszWide != NULL) {
  421. delete [] pszWide;
  422. }
  423. }
  424. }
  425. return hr;
  426. }
  427. //
  428. // Property bag I/O - only include if user knows about IStream
  429. //
  430. #ifdef __IPropertyBag_INTERFACE_DEFINED__
  431. HRESULT
  432. IntegerToPropertyBag (
  433. IPropertyBag* pIPropBag,
  434. LPCWSTR szPropName,
  435. INT intData )
  436. {
  437. HRESULT hr = E_INVALIDARG;
  438. VARIANT vValue;
  439. assert ( NULL != pIPropBag );
  440. if ( NULL != pIPropBag ) {
  441. VariantInit( &vValue );
  442. vValue.vt = VT_I4;
  443. vValue.lVal = intData;
  444. hr = pIPropBag->Write(szPropName, &vValue );
  445. VariantClear ( &vValue );
  446. }
  447. return hr;
  448. }
  449. HRESULT
  450. OleColorToPropertyBag (
  451. IPropertyBag* pIPropBag,
  452. LPCWSTR szPropName,
  453. OLE_COLOR& clrData )
  454. {
  455. HRESULT hr = E_INVALIDARG;
  456. VARIANT vValue;
  457. assert ( NULL != pIPropBag );
  458. if ( NULL != pIPropBag ) {
  459. VariantInit( &vValue );
  460. vValue.vt = VT_COLOR; // VT_COLOR = VT_I4
  461. vValue.lVal = clrData;
  462. hr = pIPropBag->Write(szPropName, &vValue );
  463. VariantClear ( &vValue );
  464. }
  465. return hr;
  466. }
  467. HRESULT
  468. ShortToPropertyBag (
  469. IPropertyBag* pIPropBag,
  470. LPCWSTR szPropName,
  471. SHORT iData )
  472. {
  473. HRESULT hr = E_INVALIDARG;
  474. VARIANT vValue;
  475. assert ( NULL != pIPropBag );
  476. if ( NULL != pIPropBag ) {
  477. VariantInit( &vValue );
  478. vValue.vt = VT_I2;
  479. vValue.iVal = iData;
  480. hr = pIPropBag->Write(szPropName, &vValue );
  481. VariantClear ( &vValue );
  482. }
  483. return hr;
  484. }
  485. HRESULT
  486. BOOLToPropertyBag (
  487. IPropertyBag* pIPropBag,
  488. LPCWSTR szPropName,
  489. BOOL bData )
  490. {
  491. HRESULT hr = E_INVALIDARG;
  492. VARIANT vValue;
  493. assert ( NULL != pIPropBag );
  494. if ( NULL != pIPropBag ) {
  495. VariantInit( &vValue );
  496. vValue.vt = VT_BOOL;
  497. vValue.boolVal = (SHORT)bData;
  498. hr = pIPropBag->Write(szPropName, &vValue );
  499. VariantClear ( &vValue );
  500. }
  501. return hr;
  502. }
  503. HRESULT
  504. DoubleToPropertyBag (
  505. IPropertyBag* pIPropBag,
  506. LPCWSTR szPropName,
  507. DOUBLE dblData )
  508. {
  509. HRESULT hr = E_INVALIDARG;
  510. VARIANT vValue;
  511. assert ( NULL != pIPropBag );
  512. if ( NULL != pIPropBag ) {
  513. VariantInit( &vValue );
  514. vValue.vt = VT_R8;
  515. vValue.dblVal = dblData;
  516. hr = pIPropBag->Write(szPropName, &vValue );
  517. VariantClear ( &vValue );
  518. }
  519. return hr;
  520. }
  521. HRESULT
  522. FloatToPropertyBag (
  523. IPropertyBag* pIPropBag,
  524. LPCWSTR szPropName,
  525. FLOAT fData )
  526. {
  527. HRESULT hr = E_INVALIDARG;
  528. VARIANT vValue;
  529. assert ( NULL != pIPropBag );
  530. if ( NULL != pIPropBag ) {
  531. VariantInit( &vValue );
  532. vValue.vt = VT_R4;
  533. vValue.fltVal = fData;
  534. hr = pIPropBag->Write(szPropName, &vValue );
  535. VariantClear ( &vValue );
  536. }
  537. return hr;
  538. }
  539. HRESULT
  540. CyToPropertyBag (
  541. IPropertyBag* pIPropBag,
  542. LPCWSTR szPropName,
  543. CY& cyData )
  544. {
  545. HRESULT hr = E_INVALIDARG;
  546. VARIANT vValue;
  547. assert ( NULL != pIPropBag );
  548. if ( NULL != pIPropBag ) {
  549. VariantInit( &vValue );
  550. vValue.vt = VT_CY;
  551. vValue.cyVal.int64 = cyData.int64;
  552. hr = VariantChangeType ( &vValue, &vValue, NULL, VT_BSTR );
  553. if ( SUCCEEDED ( hr ) )
  554. hr = pIPropBag->Write(szPropName, &vValue );
  555. VariantClear ( &vValue );
  556. }
  557. return hr;
  558. }
  559. typedef struct _HTML_ENTITIES {
  560. LPWSTR szHTML;
  561. LPWSTR szEntity;
  562. } HTML_ENTITIES;
  563. HTML_ENTITIES g_htmlentities[] = {
  564. L"&", L"&amp;",
  565. L"\"", L"&quot;",
  566. L"<", L"&lt;",
  567. L">", L"&gt;",
  568. NULL, NULL
  569. };
  570. HRESULT
  571. StringToPropertyBag (
  572. IPropertyBag* pIPropBag,
  573. LPCWSTR szPropName,
  574. LPCWSTR szData )
  575. {
  576. HRESULT hr = E_INVALIDARG;
  577. VARIANT vValue;
  578. LPWSTR szTrans = NULL;
  579. BOOL bAllocated = FALSE;
  580. size_t cchTrans = 0;
  581. LPWSTR szScan = NULL;
  582. int i;
  583. assert ( NULL != pIPropBag );
  584. if ( NULL != pIPropBag ) {
  585. VariantInit( &vValue );
  586. vValue.vt = VT_BSTR;
  587. vValue.bstrVal = NULL;
  588. if ( NULL != szData ) {
  589. //
  590. // Max length of szHTML is 6. Add 5 because 1 will be added
  591. // when add original data length below.
  592. //
  593. for( i=0 ;g_htmlentities[i].szHTML != NULL; i++ ){
  594. szScan = (LPWSTR)szData;
  595. while( *szScan != L'\0' ) {
  596. if( *szScan == *g_htmlentities[i].szHTML ){
  597. cchTrans += 5;
  598. }
  599. szScan++;
  600. }
  601. }
  602. if( cchTrans > 0 ){
  603. //
  604. // Add 1 for null.
  605. //
  606. cchTrans += lstrlen (szData) + 1;
  607. szTrans = new WCHAR [ cchTrans ];
  608. if( szTrans != NULL ){
  609. bAllocated = TRUE;
  610. ZeroMemory( szTrans, cchTrans * sizeof(WCHAR) );
  611. szScan = (LPWSTR)szData;
  612. while( *szScan != L'\0' ){
  613. BOOL bEntity = FALSE;
  614. for( i=0; g_htmlentities[i].szHTML != NULL; i++ ){
  615. if( *szScan == *g_htmlentities[i].szHTML ){
  616. bEntity = TRUE;
  617. StringCchCat(szTrans, cchTrans, g_htmlentities[i].szEntity);
  618. break;
  619. }
  620. }
  621. if( !bEntity ){
  622. StringCchCatN ( szTrans, cchTrans, szScan, 1 );
  623. }
  624. szScan++;
  625. }
  626. } else {
  627. szTrans = (LPWSTR)szData;
  628. }
  629. } else {
  630. szTrans = (LPWSTR)szData;
  631. }
  632. vValue.bstrVal = SysAllocString ( szTrans );
  633. if ( NULL != vValue.bstrVal ) {
  634. hr = pIPropBag->Write(szPropName, &vValue );
  635. VariantClear ( &vValue );
  636. } else {
  637. hr = E_OUTOFMEMORY;
  638. }
  639. } else {
  640. hr = pIPropBag->Write(szPropName, &vValue );
  641. }
  642. }
  643. if( NULL != szTrans && bAllocated ){
  644. delete [] szTrans;
  645. }
  646. return hr;
  647. }
  648. HRESULT
  649. LLTimeToPropertyBag (
  650. IPropertyBag* pIPropBag,
  651. LPCWSTR szPropName,
  652. LONGLONG& rllData )
  653. {
  654. HRESULT hr = E_INVALIDARG;
  655. VARIANT vValue;
  656. BOOL bStatus;
  657. assert ( NULL != pIPropBag );
  658. if ( NULL != pIPropBag ) {
  659. VariantInit( &vValue );
  660. vValue.vt = VT_DATE;
  661. bStatus = LLTimeToVariantDate ( rllData, &vValue.date );
  662. if ( bStatus ) {
  663. hr = pIPropBag->Write(szPropName, &vValue );
  664. VariantClear ( &vValue );
  665. } else {
  666. hr = E_FAIL;
  667. }
  668. }
  669. return hr;
  670. }
  671. HRESULT
  672. IntegerFromPropertyBag (
  673. IPropertyBag* pIPropBag,
  674. IErrorLog* pIErrorLog,
  675. LPCWSTR szPropName,
  676. INT& rintData )
  677. {
  678. HRESULT hr = E_INVALIDARG;
  679. VARIANT vValue;
  680. assert ( NULL != pIPropBag );
  681. if ( NULL != pIPropBag ) {
  682. VariantInit( &vValue );
  683. vValue.vt = VT_I4;
  684. vValue.lVal = 0;
  685. hr = pIPropBag->Read(szPropName, &vValue, pIErrorLog );
  686. if ( SUCCEEDED ( hr ) ) {
  687. rintData = vValue.lVal;
  688. }
  689. }
  690. return hr;
  691. }
  692. HRESULT
  693. OleColorFromPropertyBag (
  694. IPropertyBag* pIPropBag,
  695. IErrorLog* pIErrorLog,
  696. LPCWSTR szPropName,
  697. OLE_COLOR& rintData )
  698. {
  699. HRESULT hr = E_INVALIDARG;
  700. VARIANT vValue;
  701. assert ( NULL != pIPropBag );
  702. if ( NULL != pIPropBag ) {
  703. VariantInit( &vValue );
  704. vValue.vt = VT_COLOR; // VT_COLOR == VT_I4;
  705. hr = pIPropBag->Read(szPropName, &vValue, pIErrorLog );
  706. if ( SUCCEEDED ( hr ) ) {
  707. rintData = vValue.lVal;
  708. }
  709. }
  710. return hr;
  711. }
  712. HRESULT
  713. BOOLFromPropertyBag (
  714. IPropertyBag* pIPropBag,
  715. IErrorLog* pIErrorLog,
  716. LPCWSTR szPropName,
  717. BOOL& rbData )
  718. {
  719. HRESULT hr = E_INVALIDARG;
  720. VARIANT vValue;
  721. assert ( NULL != pIPropBag );
  722. if ( NULL != pIPropBag ) {
  723. VariantInit( &vValue );
  724. vValue.vt = VT_BOOL;
  725. hr = pIPropBag->Read(szPropName, &vValue, pIErrorLog );
  726. if ( SUCCEEDED ( hr ) ) {
  727. rbData = vValue.boolVal;
  728. }
  729. }
  730. return hr;
  731. }
  732. HRESULT
  733. DoubleFromPropertyBag (
  734. IPropertyBag* pIPropBag,
  735. IErrorLog* pIErrorLog,
  736. LPCWSTR szPropName,
  737. DOUBLE& rdblData )
  738. {
  739. HRESULT hr = E_INVALIDARG;
  740. VARIANT vValue;
  741. assert ( NULL != pIPropBag );
  742. if ( NULL != pIPropBag ) {
  743. VariantInit( &vValue );
  744. vValue.vt = VT_R8;
  745. hr = pIPropBag->Read(szPropName, &vValue, pIErrorLog );
  746. if ( SUCCEEDED ( hr ) ) {
  747. rdblData = vValue.dblVal;
  748. }
  749. }
  750. return hr;
  751. }
  752. HRESULT
  753. FloatFromPropertyBag (
  754. IPropertyBag* pIPropBag,
  755. IErrorLog* pIErrorLog,
  756. LPCWSTR szPropName,
  757. FLOAT& rfData )
  758. {
  759. HRESULT hr = E_INVALIDARG;
  760. VARIANT vValue;
  761. assert ( NULL != pIPropBag );
  762. if ( NULL != pIPropBag ) {
  763. VariantInit( &vValue );
  764. vValue.vt = VT_R4;
  765. hr = pIPropBag->Read(szPropName, &vValue, pIErrorLog );
  766. if ( SUCCEEDED ( hr ) ) {
  767. rfData = vValue.fltVal;
  768. }
  769. }
  770. return hr;
  771. }
  772. HRESULT
  773. ShortFromPropertyBag (
  774. IPropertyBag* pIPropBag,
  775. IErrorLog* pIErrorLog,
  776. LPCWSTR szPropName,
  777. SHORT& riData )
  778. {
  779. HRESULT hr = E_INVALIDARG;
  780. VARIANT vValue;
  781. assert ( NULL != pIPropBag );
  782. if ( NULL != pIPropBag ) {
  783. VariantInit( &vValue );
  784. vValue.vt = VT_I2;
  785. hr = pIPropBag->Read(szPropName, &vValue, pIErrorLog );
  786. if ( SUCCEEDED ( hr ) ) {
  787. riData = vValue.iVal;
  788. }
  789. }
  790. return hr;
  791. }
  792. HRESULT
  793. CyFromPropertyBag (
  794. IPropertyBag* pIPropBag,
  795. IErrorLog* pIErrorLog,
  796. LPCWSTR szPropName,
  797. CY& rcyData )
  798. {
  799. HRESULT hr = E_INVALIDARG;
  800. VARIANT vValue;
  801. assert ( NULL != pIPropBag );
  802. if ( NULL != pIPropBag ) {
  803. VariantInit( &vValue );
  804. vValue.vt = VT_CY;
  805. vValue.cyVal.int64 = 0;
  806. hr = pIPropBag->Read(szPropName, &vValue, pIErrorLog );
  807. if ( SUCCEEDED( hr ) ) {
  808. hr = VariantChangeType ( &vValue, &vValue, NULL, VT_CY );
  809. if ( SUCCEEDED ( hr ) ) {
  810. rcyData.int64 = vValue.cyVal.int64;
  811. }
  812. }
  813. }
  814. return hr;
  815. }
  816. HRESULT
  817. StringFromPropertyBag (
  818. IPropertyBag* pIPropBag,
  819. IErrorLog* pIErrorLog,
  820. LPCWSTR szPropName,
  821. LPWSTR szData,
  822. INT& riCchBufLen )
  823. {
  824. HRESULT hr = E_INVALIDARG;
  825. VARIANT vValue;
  826. INT iCchNewBufLen = 0;
  827. LPWSTR szLocalData = NULL;
  828. LPWSTR szTrans = NULL;
  829. LPWSTR szScan = NULL;
  830. assert ( NULL != pIPropBag );
  831. if ( NULL != pIPropBag ) {
  832. if ( NULL != szData ) {
  833. *szData = L'\0';
  834. }
  835. VariantInit( &vValue );
  836. vValue.vt = VT_BSTR;
  837. vValue.bstrVal = NULL;
  838. hr = pIPropBag->Read(szPropName, &vValue, pIErrorLog );
  839. if ( SUCCEEDED(hr) && vValue.bstrVal ) {
  840. iCchNewBufLen = SysStringLen(vValue.bstrVal) + 1;
  841. if ( iCchNewBufLen > 1 ) {
  842. if ( riCchBufLen >= iCchNewBufLen && NULL != szData ) {
  843. //
  844. // Translate HTML entities back to single characters.
  845. //
  846. szTrans = new WCHAR [iCchNewBufLen];
  847. szLocalData = new WCHAR [iCchNewBufLen];
  848. if ( NULL != szTrans && NULL != szLocalData ) {
  849. StringCchCopy(szLocalData, riCchBufLen, vValue.bstrVal);
  850. for( int i=0;g_htmlentities[i].szHTML != NULL;i++ ){
  851. szScan = NULL;
  852. while( szScan = wcsstr( szLocalData, g_htmlentities[i].szEntity ) ){
  853. //
  854. // Null the character at szScan, so that the string
  855. // at the beginning of szLocalData will copied to szTrans.
  856. // Then the NULL character is overwritten with the character
  857. // represented by the specified HTML entity.
  858. //
  859. *szScan = L'\0';
  860. StringCchCopy(szTrans, iCchNewBufLen, szLocalData);
  861. StringCchCat(szTrans, iCchNewBufLen, g_htmlentities[i].szHTML);
  862. //
  863. // szScan is then set to one character past the HTML entity.
  864. //
  865. szScan += lstrlenW( g_htmlentities[i].szEntity);
  866. //
  867. // The rest of the original string is concatenated onto
  868. // szTrans, and szLocalData replaced by the string at szTrans,
  869. // so the next loop will start again at the beginning
  870. // of the string.
  871. //
  872. StringCchCat(szTrans, iCchNewBufLen, szScan);
  873. StringCchCopy(szLocalData, riCchBufLen, szTrans);
  874. }
  875. }
  876. StringCchCopy(szData, riCchBufLen, szLocalData);
  877. } else {
  878. StringCchCopy(szData, riCchBufLen, vValue.bstrVal);
  879. hr = E_OUTOFMEMORY;
  880. }
  881. if ( NULL != szLocalData ) {
  882. delete [] szLocalData;
  883. }
  884. if ( NULL != szTrans ) {
  885. delete [] szTrans;
  886. }
  887. }
  888. riCchBufLen = iCchNewBufLen;
  889. } else {
  890. riCchBufLen = 0;
  891. }
  892. }
  893. VariantClear ( &vValue );
  894. }
  895. return hr;
  896. }
  897. HRESULT
  898. LLTimeFromPropertyBag (
  899. IPropertyBag* pIPropBag,
  900. IErrorLog* pIErrorLog,
  901. LPCWSTR szPropName,
  902. LONGLONG& rllData )
  903. {
  904. HRESULT hr = E_INVALIDARG;
  905. VARIANT vValue;
  906. assert ( NULL != pIPropBag );
  907. if ( NULL != pIPropBag ) {
  908. VariantInit( &vValue );
  909. vValue.vt = VT_DATE;
  910. hr = pIPropBag->Read(szPropName, &vValue, pIErrorLog );
  911. if ( SUCCEEDED(hr) ) {
  912. if ( !VariantDateToLLTime ( vValue.date, &rllData ) ) {
  913. hr = E_FAIL;
  914. }
  915. VariantClear( &vValue );
  916. }
  917. }
  918. return hr;
  919. }
  920. #endif // Property bag
  921. LPWSTR
  922. ResourceString (
  923. UINT uID
  924. )
  925. {
  926. static WCHAR aszBuffers[NUM_RESOURCE_STRING_BUFFERS][RESOURCE_STRING_BUF_LEN];
  927. static INT iBuffIndex = 0;
  928. // Use next buffer
  929. if (++iBuffIndex >= NUM_RESOURCE_STRING_BUFFERS)
  930. iBuffIndex = 0;
  931. // Load and return string
  932. if (LoadString(g_hInstance, uID, aszBuffers[iBuffIndex], RESOURCE_STRING_BUF_LEN))
  933. return aszBuffers[iBuffIndex];
  934. else
  935. return MISSING_RESOURCE_STRING;
  936. }
  937. DWORD
  938. FormatSystemMessage (
  939. DWORD dwMessageId,
  940. LPWSTR pszSystemMessage,
  941. DWORD dwBufSize )
  942. {
  943. DWORD dwReturn = 0;
  944. HINSTANCE hPdh = NULL;
  945. DWORD dwFlags = FORMAT_MESSAGE_FROM_SYSTEM;
  946. assert ( NULL != pszSystemMessage );
  947. if ( NULL != pszSystemMessage ) {
  948. pszSystemMessage[0] = L'\0';
  949. hPdh = LoadLibrary( L"PDH.DLL") ;
  950. if ( NULL != hPdh ) {
  951. dwFlags |= FORMAT_MESSAGE_FROM_HMODULE;
  952. }
  953. dwReturn = ::FormatMessage (
  954. dwFlags,
  955. hPdh,
  956. dwMessageId,
  957. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  958. pszSystemMessage,
  959. dwBufSize,
  960. NULL );
  961. if ( NULL != hPdh ) {
  962. FreeLibrary( hPdh );
  963. }
  964. if ( L'\0' == pszSystemMessage[0] ) {
  965. StringCchPrintf(pszSystemMessage, dwBufSize, L"0x%08lX", dwMessageId );
  966. }
  967. }
  968. return dwReturn;
  969. }
  970. INT
  971. GetNumSeparators (
  972. LPWSTR& rpDecimal,
  973. LPWSTR& rpThousand )
  974. {
  975. #define NUM_BUF_LEN 4
  976. INT iLength;
  977. static WCHAR szDecimal[NUM_BUF_LEN] = L".";
  978. static WCHAR szThousand[NUM_BUF_LEN] = L",";
  979. iLength = GetLocaleInfo (
  980. LOCALE_USER_DEFAULT,
  981. LOCALE_SDECIMAL,
  982. szDecimal,
  983. NUM_BUF_LEN );
  984. if ( 0 != iLength ) {
  985. iLength = GetLocaleInfo (
  986. LOCALE_USER_DEFAULT,
  987. LOCALE_STHOUSAND,
  988. szThousand,
  989. NUM_BUF_LEN );
  990. }
  991. rpDecimal = szDecimal;
  992. rpThousand = szThousand;
  993. return iLength;
  994. }
  995. LPWSTR
  996. GetTimeSeparator ( void )
  997. {
  998. #define TIME_MARK_BUF_LEN 5
  999. static INT iInitialized; // Initialized to 0
  1000. static WCHAR szTimeSeparator[TIME_MARK_BUF_LEN];
  1001. if ( 0 == iInitialized ) {
  1002. INT iLength;
  1003. iLength = GetLocaleInfo (
  1004. LOCALE_USER_DEFAULT,
  1005. LOCALE_STIME,
  1006. szTimeSeparator,
  1007. TIME_MARK_BUF_LEN );
  1008. // Default to colon for time separator
  1009. if ( '\0' == szTimeSeparator[0] ) {
  1010. StringCchCopy(szTimeSeparator, TIME_MARK_BUF_LEN, L":" );
  1011. }
  1012. iInitialized = 1;
  1013. }
  1014. assert ( L'\0' != szTimeSeparator[0] );
  1015. return szTimeSeparator;
  1016. }
  1017. BOOL
  1018. DisplayThousandsSeparator ( void )
  1019. {
  1020. long nErr;
  1021. HKEY hKey = NULL;
  1022. DWORD dwRegValue;
  1023. DWORD dwDataType;
  1024. DWORD dwDataSize;
  1025. DWORD dwDisposition;
  1026. static INT siInitialized; // Initialized to 0
  1027. static BOOL sbUseSeparator; // Initialized to 0 ( FALSE )
  1028. // check registry setting to see if thousands separator is enabled
  1029. if ( 0 == siInitialized ) {
  1030. nErr = RegOpenKey(
  1031. HKEY_CURRENT_USER,
  1032. L"Software\\Microsoft\\SystemMonitor",
  1033. &hKey );
  1034. if( ERROR_SUCCESS != nErr ) {
  1035. nErr = RegCreateKeyEx(
  1036. HKEY_CURRENT_USER,
  1037. L"Software\\Microsoft\\SystemMonitor",
  1038. 0,
  1039. L"REG_DWORD",
  1040. REG_OPTION_NON_VOLATILE,
  1041. KEY_ALL_ACCESS,
  1042. NULL,
  1043. &hKey,
  1044. &dwDisposition );
  1045. }
  1046. dwRegValue = 0;
  1047. if ( ERROR_SUCCESS == nErr ) {
  1048. dwDataSize = sizeof(DWORD);
  1049. nErr = RegQueryValueExW (
  1050. hKey,
  1051. L"DisplayThousandsSeparator",
  1052. NULL,
  1053. &dwDataType,
  1054. (LPBYTE) &dwRegValue,
  1055. (LPDWORD) &dwDataSize );
  1056. if ( ERROR_SUCCESS == nErr
  1057. && REG_DWORD == dwDataType
  1058. && sizeof(DWORD) == dwDataSize )
  1059. {
  1060. if ( 0 != dwRegValue ) {
  1061. sbUseSeparator = TRUE;
  1062. }
  1063. }
  1064. siInitialized = 1;
  1065. }
  1066. if ( NULL != hKey ) {
  1067. nErr = RegCloseKey( hKey );
  1068. }
  1069. }
  1070. return sbUseSeparator;
  1071. }
  1072. INT
  1073. FormatNumberInternal (
  1074. LPWSTR pNumOrig,
  1075. LPWSTR pNumFormatted,
  1076. INT cchars,
  1077. UINT uiPrecision,
  1078. UINT uiLeadingZero,
  1079. UINT uiGrouping,
  1080. UINT uiNegativeMode )
  1081. {
  1082. INT iLength = 0;
  1083. WCHAR* pszSrc;
  1084. static INT siInitialized; // Initialized to 0
  1085. static NUMBERFMT NumberFormat;
  1086. assert ( NULL != pNumOrig && NULL != pNumFormatted );
  1087. if ( NULL != pNumOrig && NULL != pNumFormatted ) {
  1088. iLength = 2;
  1089. NumberFormat.NumDigits = uiPrecision;
  1090. NumberFormat.LeadingZero = uiLeadingZero;
  1091. NumberFormat.NegativeOrder = uiNegativeMode;
  1092. if ( DisplayThousandsSeparator() ) {
  1093. NumberFormat.Grouping = uiGrouping;
  1094. } else {
  1095. NumberFormat.Grouping = 0;
  1096. }
  1097. if ( 0 == siInitialized ) {
  1098. GetNumSeparators (
  1099. NumberFormat.lpDecimalSep,
  1100. NumberFormat.lpThousandSep );
  1101. siInitialized = 1;
  1102. }
  1103. // Programming error if either pointer is NULL.
  1104. assert ( NULL != NumberFormat.lpDecimalSep );
  1105. assert ( NULL != NumberFormat.lpThousandSep );
  1106. // GetNumberFormat requires "." for decimal point.
  1107. if ( NumberFormat.lpDecimalSep != NULL) {
  1108. if (0 != lstrcmpi(NumberFormat.lpDecimalSep, L".") ) {
  1109. for ( pszSrc = pNumOrig; *pszSrc != L'\0'; pszSrc++) {
  1110. if ( *pszSrc == NumberFormat.lpDecimalSep[0] ) {
  1111. *pszSrc = L'.';
  1112. break;
  1113. }
  1114. }
  1115. }
  1116. iLength = GetNumberFormat (
  1117. LOCALE_USER_DEFAULT,
  1118. 0,
  1119. pNumOrig,
  1120. &NumberFormat,
  1121. pNumFormatted,
  1122. cchars );
  1123. }
  1124. }
  1125. // Return 0 on failure, number of chars on success.
  1126. // GetNumberFormat includes the null terminator in the length.
  1127. return iLength;
  1128. }
  1129. INT
  1130. FormatHex (
  1131. double dValue,
  1132. LPWSTR pNumFormatted,
  1133. BOOL bLargeFormat
  1134. )
  1135. {
  1136. INT iLength = 0;
  1137. WCHAR szPreFormat[24];
  1138. assert ( NULL != pNumFormatted );
  1139. if ( NULL != pNumFormatted ) {
  1140. iLength = 8;
  1141. // Localization doesn't handle padding blanks.
  1142. StringCchPrintf( szPreFormat,
  1143. 24,
  1144. (bLargeFormat ? szLargeHexFormat : szHexFormat ),
  1145. (ULONG)dValue );
  1146. StringCchCopy(pNumFormatted, MAX_VALUE_LEN, szPreFormat);
  1147. }
  1148. return iLength;
  1149. }
  1150. INT
  1151. FormatNumber (
  1152. double dValue,
  1153. LPWSTR pNumFormatted,
  1154. INT ccharsFormatted,
  1155. UINT /* uiMinimumWidth */,
  1156. UINT uiPrecision )
  1157. {
  1158. INT iLength = 0;
  1159. INT iLeadingZero = FALSE;
  1160. WCHAR szPreFormat[MAX_VALUE_LEN];
  1161. assert ( NULL != pNumFormatted );
  1162. // This method enforces number format commonality
  1163. if ( NULL != pNumFormatted ) {
  1164. assert ( 8 > uiPrecision );
  1165. // Localization doesn't handle padding blanks.
  1166. StringCchPrintf( szPreFormat,
  1167. MAX_VALUE_LEN,
  1168. L"%0.7f", // assumes 7 >= uiPrecision
  1169. dValue );
  1170. if ( 1 > dValue )
  1171. iLeadingZero = TRUE;
  1172. iLength = FormatNumberInternal (
  1173. szPreFormat,
  1174. pNumFormatted,
  1175. ccharsFormatted,
  1176. uiPrecision,
  1177. iLeadingZero, // Leading 0
  1178. 3, // Grouping
  1179. 1 ); // Negative format
  1180. }
  1181. // Return 0 on failure, number of chars on success.
  1182. // GetNumberFormat includes the null terminator in the length.
  1183. return iLength;
  1184. }
  1185. INT
  1186. FormatScientific (
  1187. double dValue,
  1188. LPWSTR pszNumFormatted,
  1189. INT ccharsFormatted,
  1190. UINT /* uiMinimumWidth */,
  1191. UINT uiPrecision )
  1192. {
  1193. INT iLength = 0;
  1194. WCHAR szPreFormat[24];
  1195. WCHAR szPreFormNumber[24];
  1196. WCHAR *pche;
  1197. INT iPreLen;
  1198. INT iPostLen;
  1199. INT iLeadingZero = FALSE;
  1200. assert ( NULL != pszNumFormatted );
  1201. // This method enforces number format commonality
  1202. if ( NULL != pszNumFormatted ) {
  1203. assert ( 8 > uiPrecision );
  1204. assert ( 32 > ccharsFormatted );
  1205. // Localization doesn't handle padding blanks.
  1206. StringCchPrintf( szPreFormat,
  1207. 24,
  1208. L"%0.8e", // assumes 8 >= uiPrecision
  1209. dValue );
  1210. pche = wcsrchr(szPreFormat, L'e');
  1211. if (pche != NULL) {
  1212. iPreLen = (INT)((UINT_PTR)pche - (UINT_PTR)szPreFormat); // Number of bytes
  1213. iPreLen /= sizeof (WCHAR); // Number of characters
  1214. iPostLen = lstrlen(pche) + 1;
  1215. StringCchCopyN ( szPreFormNumber, 24, szPreFormat, iPreLen );
  1216. if ( 1 > dValue ) {
  1217. iLeadingZero = TRUE;
  1218. }
  1219. iLength = FormatNumberInternal (
  1220. szPreFormNumber,
  1221. pszNumFormatted,
  1222. ccharsFormatted,
  1223. uiPrecision,
  1224. iLeadingZero, // Leading 0
  1225. 0, // Grouping
  1226. 1 ); // Negative format
  1227. if( ( iLength + iPostLen ) < ccharsFormatted ) {
  1228. StringCchCopy(pszNumFormatted, ccharsFormatted, pche );
  1229. iLength += iPostLen;
  1230. }
  1231. }
  1232. }
  1233. // Return 0 on failure, number of chars on success.
  1234. // GetNumberFormat includes the null terminator in the length.
  1235. return iLength;
  1236. }
  1237. void
  1238. FormatDateTime (
  1239. LONGLONG llTime,
  1240. LPWSTR pszDate,
  1241. LPWSTR pszTime )
  1242. {
  1243. SYSTEMTIME SystemTime;
  1244. assert ( NULL != pszDate && NULL != pszTime );
  1245. if ( NULL != pszDate
  1246. && NULL != pszTime ) {
  1247. FileTimeToSystemTime((FILETIME*)&llTime, &SystemTime);
  1248. GetTimeFormat (LOCALE_USER_DEFAULT, 0, &SystemTime, NULL, pszTime, MAX_TIME_CHARS) ;
  1249. GetDateFormat (LOCALE_USER_DEFAULT, DATE_SHORTDATE, &SystemTime, NULL, pszDate, MAX_DATE_CHARS) ;
  1250. }
  1251. }
  1252. // CreateTargetDC is based on AtlCreateTargetDC.
  1253. HDC
  1254. CreateTargetDC(HDC hdc, DVTARGETDEVICE* ptd)
  1255. {
  1256. USES_CONVERSION
  1257. // cases hdc, ptd, hdc is metafile, hic
  1258. // NULL, NULL, n/a, Display
  1259. // NULL, !NULL, n/a, ptd
  1260. // !NULL, NULL, FALSE, hdc
  1261. // !NULL, NULL, TRUE, display
  1262. // !NULL, !NULL, FALSE, ptd
  1263. // !NULL, !NULL, TRUE, ptd
  1264. if ( NULL != ptd ) {
  1265. LPDEVMODE lpDevMode;
  1266. LPOLESTR lpszDriverName;
  1267. LPOLESTR lpszDeviceName;
  1268. LPOLESTR lpszPortName;
  1269. if (ptd->tdExtDevmodeOffset == 0)
  1270. lpDevMode = NULL;
  1271. else
  1272. lpDevMode = (LPDEVMODE) ((LPSTR)ptd + ptd->tdExtDevmodeOffset);
  1273. lpszDriverName = (LPOLESTR)((BYTE*)ptd + ptd->tdDriverNameOffset);
  1274. lpszDeviceName = (LPOLESTR)((BYTE*)ptd + ptd->tdDeviceNameOffset);
  1275. lpszPortName = (LPOLESTR)((BYTE*)ptd + ptd->tdPortNameOffset);
  1276. return ::CreateDC(lpszDriverName, lpszDeviceName,
  1277. lpszPortName, lpDevMode);
  1278. } else if ( NULL == hdc ) {
  1279. return ::CreateDC(L"DISPLAY", NULL, NULL, NULL);
  1280. } else if ( GetDeviceCaps(hdc, TECHNOLOGY) == DT_METAFILE ) {
  1281. return ::CreateDC(L"DISPLAY", NULL, NULL, NULL);
  1282. } else
  1283. return hdc;
  1284. }
  1285. /***********************************************************************
  1286. FUNCTION : HitTestLine
  1287. PARAMETERS : POINT pt0 - endpoint for line segment
  1288. POINT pt1 - endpoint for line segment
  1289. POINTS ptMouse - mouse coordinates of hit
  1290. INT nWidth - width of pen
  1291. PURPOSE : test if mouse click occurred on line segment while
  1292. adjusting for the width of line
  1293. CALLS : GetDC
  1294. ReleaseDC
  1295. SetGraphicsMode
  1296. SetWorldTransform
  1297. MESSAGES : none
  1298. RETURNS : BOOL - TRUE if the point was within the width of the
  1299. pen about the line
  1300. FALSE if the point lies outside of the width
  1301. of the pen about the line
  1302. COMMENTS : uses VECTOR2D.DLL
  1303. HISTORY : 9/20/93 - created - denniscr
  1304. ************************************************************************/
  1305. BOOL HitTestLine( POINT pt0, POINT pt1, POINTS ptMouse, INT nWidth )
  1306. {
  1307. POINT PtM;
  1308. VECTOR2D tt0, tt1;
  1309. double dist;
  1310. INT nHalfWidth;
  1311. nHalfWidth = (nWidth/2 < 1) ? 1 : nWidth/2;
  1312. //
  1313. //convert the line into a vector
  1314. //
  1315. POINTS2VECTOR2D(pt0, pt1, tt0);
  1316. //
  1317. //convert the mouse points (short) into POINT (long)
  1318. //
  1319. MPOINT2POINT(ptMouse ,PtM);
  1320. POINTS2VECTOR2D(pt0, PtM, tt1);
  1321. //
  1322. //if the mouse click is past the endpoints of
  1323. //a line segment return FALSE
  1324. //
  1325. if (pt0.x <= pt1.x)
  1326. {
  1327. if (PtM.x < pt0.x || PtM.x > pt1.x)
  1328. return (FALSE);
  1329. }
  1330. else
  1331. {
  1332. if (PtM.x > pt0.x || PtM.x < pt1.x)
  1333. return (FALSE);
  1334. }
  1335. //
  1336. //this is the call to the function that does the work
  1337. //of obtaining the distance of the point to the line
  1338. //
  1339. dist = vDistFromPointToLine(&pt0, &pt1, &PtM);
  1340. //
  1341. //TRUE if the distance is within the width of the pen about the
  1342. //line otherwise FALSE
  1343. //
  1344. return (dist >= -nHalfWidth && dist <= nHalfWidth);
  1345. }
  1346. /***********************************************************************
  1347. vSubtractVectors
  1348. The vSubtractVectors function subtracts the components of a two
  1349. dimensional vector from another. The resultant vector
  1350. c = (a1 - b1, a2 - b2).
  1351. Parameters
  1352. v0 A pointer to a VECTOR2D structure containing the components
  1353. of the first two dimensional vector.
  1354. v1 A pointer to a VECTOR2D structure containing the components
  1355. of the second two dimensional vector.
  1356. vt A pointer to a VECTOR2D structure in which the components
  1357. of the two dimensional vector obtained from the subtraction of
  1358. the first two are placed.
  1359. Return value
  1360. A pointer to a VECTOR2D structure containing the new vector obtained
  1361. from the subtraction of the first two parameters.
  1362. HISTORY : - created - denniscr
  1363. ************************************************************************/
  1364. PVECTOR2D vSubtractVectors(PVECTOR2D v0, PVECTOR2D v1, PVECTOR2D v)
  1365. {
  1366. if (v0 == NULL || v1 == NULL)
  1367. v = (PVECTOR2D)NULL;
  1368. else
  1369. {
  1370. v->x = v0->x - v1->x;
  1371. v->y = v0->y - v1->y;
  1372. }
  1373. return(v);
  1374. }
  1375. /***********************************************************************
  1376. vVectorSquared
  1377. The vVectorSquared function squares each of the components of the
  1378. vector and adds then together to produce the squared value of the
  1379. vector. SquaredValue = a.x * a.x + a.y * a.y.
  1380. Parameters
  1381. v0 A pointer to a VECTOR2D structure containing the vector upon which
  1382. to determine the squared value.
  1383. Return value
  1384. A double value which is the squared value of the vector.
  1385. HISTORY : - created - denniscr
  1386. ************************************************************************/
  1387. double vVectorSquared(PVECTOR2D v0)
  1388. {
  1389. double dSqLen;
  1390. if (v0 == NULL)
  1391. dSqLen = 0.0;
  1392. else
  1393. dSqLen = (double)(v0->x * v0->x) + (double)(v0->y * v0->y);
  1394. return (dSqLen);
  1395. }
  1396. /***********************************************************************
  1397. vVectorMagnitude
  1398. The vVectorMagnitude function determines the length of a vector by
  1399. summing the squares of each of the components of the vector. The
  1400. magnitude is equal to a.x * a.x + a.y * a.y.
  1401. Parameters
  1402. v0 A pointer to a VECTOR2D structure containing the vector upon
  1403. which to determine the magnitude.
  1404. Return value
  1405. A double value which is the magnitude of the vector.
  1406. HISTORY : - created - denniscr
  1407. ************************************************************************/
  1408. double vVectorMagnitude(PVECTOR2D v0)
  1409. {
  1410. double dMagnitude;
  1411. if (v0 == NULL)
  1412. dMagnitude = 0.0;
  1413. else
  1414. dMagnitude = sqrt(vVectorSquared(v0));
  1415. return (dMagnitude);
  1416. }
  1417. /***********************************************************************
  1418. vDotProduct
  1419. The function vDotProduct computes the dot product of two vectors. The
  1420. dot product of two vectors is the sum of the products of the components
  1421. of the vectors ie: for the vectors a and b, dotprod = a1 * a2 + b1 * b2.
  1422. Parameters
  1423. v0 A pointer to a VECTOR2D structure containing the first vector used
  1424. for obtaining a dot product.
  1425. v1 A pointer to a VECTOR2D structure containing the second vector used
  1426. for obtaining a dot product.
  1427. Return value
  1428. A double value containing the scalar dot product value.
  1429. HISTORY : - created - denniscr
  1430. ************************************************************************/
  1431. double vDotProduct(PVECTOR2D v0, PVECTOR2D v1)
  1432. {
  1433. return ((v0 == NULL || v1 == NULL) ? 0.0
  1434. : (v0->x * v1->x) + (v0->y * v1->y));
  1435. }
  1436. /***********************************************************************
  1437. vProjectAndResolve
  1438. The function vProjectAndResolve resolves a vector into two vector
  1439. components. The first is a vector obtained by projecting vector v0 onto
  1440. v1. The second is a vector that is perpendicular (normal) to the
  1441. projected vector. It extends from the head of the projected vector
  1442. v1 to the head of the original vector v0.
  1443. Parameters
  1444. v0 A pointer to a VECTOR2D structure containing the first vector
  1445. v1 A pointer to a VECTOR2D structure containing the second vector
  1446. ppProj A pointer to a PROJECTION structure containing the resolved
  1447. vectors and their lengths.
  1448. Return value
  1449. void.
  1450. HISTORY : - created - denniscr
  1451. ************************************************************************/
  1452. void vProjectAndResolve(PVECTOR2D v0, PVECTOR2D v1, PPROJECTION ppProj)
  1453. {
  1454. VECTOR2D ttProjection, ttOrthogonal;
  1455. double vDotProd;
  1456. double proj1 = 0.0;
  1457. //
  1458. //obtain projection vector
  1459. //
  1460. //c = a * b
  1461. // ----- b
  1462. // |b|^2
  1463. //
  1464. ttOrthogonal.x = 0.0;
  1465. ttOrthogonal.y = 0.0;
  1466. vDotProd = vDotProduct(v1, v1);
  1467. if ( 0.0 != vDotProd ) {
  1468. proj1 = vDotProduct(v0, v1)/vDotProd;
  1469. }
  1470. ttProjection.x = v1->x * proj1;
  1471. ttProjection.y = v1->y * proj1;
  1472. //
  1473. //obtain perpendicular projection : e = a - c
  1474. //
  1475. vSubtractVectors(v0, &ttProjection, &ttOrthogonal);
  1476. //
  1477. //fill PROJECTION structure with appropriate values
  1478. //
  1479. ppProj->LenProjection = vVectorMagnitude(&ttProjection);
  1480. ppProj->LenPerpProjection = vVectorMagnitude(&ttOrthogonal);
  1481. ppProj->ttProjection.x = ttProjection.x;
  1482. ppProj->ttProjection.y = ttProjection.y;
  1483. ppProj->ttPerpProjection.x = ttOrthogonal.x;
  1484. ppProj->ttPerpProjection.y = ttOrthogonal.y;
  1485. }
  1486. /***********************************************************************
  1487. vDistFromPointToLine
  1488. The function vDistFromPointToLine computes the distance from the point
  1489. ptTest to the line defined by endpoints pt0 and pt1. This is done by
  1490. resolving the the vector from pt0 to ptTest into its components. The
  1491. length of the component vector that is attached to the head of the
  1492. vector from pt0 to ptTest is the distance of ptTest from the line.
  1493. Parameters
  1494. pt0 A pointer to a POINT structure containing the first endpoint of the
  1495. line.
  1496. pt1 A pointer to a POINT structure containing the second endpoint of the
  1497. line.
  1498. ptTest A pointer to a POINT structure containing the point for which the
  1499. distance from the line is to be computed.
  1500. Return value
  1501. A double value that contains the distance of ptTest to the line defined
  1502. by the endpoints pt0 and pt1.
  1503. HISTORY : - created - denniscr
  1504. ************************************************************************/
  1505. double vDistFromPointToLine(LPPOINT pt0, LPPOINT pt1, LPPOINT ptTest)
  1506. {
  1507. VECTOR2D ttLine, ttTest;
  1508. PROJECTION pProjection;
  1509. POINTS2VECTOR2D(*pt0, *pt1, ttLine);
  1510. POINTS2VECTOR2D(*pt0, *ptTest, ttTest);
  1511. vProjectAndResolve(&ttTest, &ttLine, &pProjection);
  1512. return(pProjection.LenPerpProjection);
  1513. }
  1514. BOOL
  1515. FileRead (
  1516. HANDLE hFile,
  1517. void* lpMemory,
  1518. DWORD nAmtToRead)
  1519. {
  1520. BOOL bSuccess = FALSE;
  1521. DWORD nAmtRead = 0;
  1522. assert ( NULL != hFile );
  1523. assert ( NULL != lpMemory );
  1524. if ( NULL != hFile
  1525. && NULL != lpMemory ) {
  1526. bSuccess = ReadFile (hFile, lpMemory, nAmtToRead, &nAmtRead, NULL) ;
  1527. }
  1528. return (bSuccess && (nAmtRead == nAmtToRead)) ;
  1529. } // FileRead
  1530. BOOL
  1531. FileWrite (
  1532. HANDLE hFile,
  1533. void* lpMemory,
  1534. DWORD nAmtToWrite)
  1535. {
  1536. BOOL bSuccess = FALSE;
  1537. DWORD nAmtWritten = 0;
  1538. DWORD dwFileSizeLow, dwFileSizeHigh;
  1539. LONGLONG llResultSize;
  1540. if ( NULL != hFile
  1541. && NULL != lpMemory ) {
  1542. dwFileSizeLow = GetFileSize (hFile, &dwFileSizeHigh);
  1543. // limit file size to 2GB
  1544. if (dwFileSizeHigh > 0) {
  1545. SetLastError (ERROR_WRITE_FAULT);
  1546. bSuccess = FALSE;
  1547. } else {
  1548. // note that the error return of this function is 0xFFFFFFFF
  1549. // since that is > the file size limit, this will be interpreted
  1550. // as an error (a size error) so it's accounted for in the following
  1551. // test.
  1552. llResultSize = dwFileSizeLow + nAmtToWrite;
  1553. if (llResultSize >= 0x80000000) {
  1554. SetLastError (ERROR_WRITE_FAULT);
  1555. bSuccess = FALSE;
  1556. } else {
  1557. // write buffer to file
  1558. bSuccess = WriteFile (hFile, lpMemory, nAmtToWrite, &nAmtWritten, NULL) ;
  1559. if (bSuccess)
  1560. bSuccess = (nAmtWritten == nAmtToWrite ? TRUE : FALSE);
  1561. if ( !bSuccess ) {
  1562. SetLastError (ERROR_WRITE_FAULT);
  1563. }
  1564. }
  1565. }
  1566. } else {
  1567. assert ( FALSE );
  1568. SetLastError (ERROR_INVALID_PARAMETER);
  1569. }
  1570. return (bSuccess) ;
  1571. } // FileWrite
  1572. // This routine extract the filename portion from a given full-path filename
  1573. LPWSTR
  1574. ExtractFileName ( LPWSTR pFileSpec )
  1575. {
  1576. LPWSTR pFileName = NULL ;
  1577. WCHAR DIRECTORY_DELIMITER1 = TEXT('\\') ;
  1578. WCHAR DIRECTORY_DELIMITER2 = TEXT(':') ;
  1579. assert ( NULL != pFileSpec );
  1580. if ( pFileSpec ) {
  1581. pFileName = pFileSpec + lstrlen (pFileSpec) ;
  1582. while (*pFileName != DIRECTORY_DELIMITER1 &&
  1583. *pFileName != DIRECTORY_DELIMITER2) {
  1584. if (pFileName == pFileSpec) {
  1585. // done when no directory delimiter is found
  1586. break ;
  1587. }
  1588. pFileName-- ;
  1589. }
  1590. if (*pFileName == DIRECTORY_DELIMITER1
  1591. || *pFileName == DIRECTORY_DELIMITER2) {
  1592. // directory delimiter found, point the
  1593. // filename right after it
  1594. pFileName++ ;
  1595. }
  1596. }
  1597. return pFileName ;
  1598. } // ExtractFileName
  1599. // CWaitCursor class
  1600. CWaitCursor::CWaitCursor()
  1601. : m_hcurWaitCursorRestore ( NULL )
  1602. {
  1603. DoWaitCursor(1);
  1604. }
  1605. CWaitCursor::~CWaitCursor()
  1606. {
  1607. DoWaitCursor(-1);
  1608. }
  1609. void
  1610. CWaitCursor::DoWaitCursor(INT nCode)
  1611. {
  1612. // 1=> begin, -1=> end
  1613. assert(nCode == 1 || nCode == -1);
  1614. if ( 1 == nCode )
  1615. {
  1616. m_hcurWaitCursorRestore = SetHourglassCursor();
  1617. } else {
  1618. if ( NULL != m_hcurWaitCursorRestore ) {
  1619. SetCursor(m_hcurWaitCursorRestore);
  1620. } else {
  1621. SetArrowCursor();
  1622. }
  1623. }
  1624. }
  1625. DWORD
  1626. LoadDefaultLogFileFolder(
  1627. LPWSTR szFolder,
  1628. INT* piBufLen )
  1629. {
  1630. DWORD dwStatus = ERROR_SUCCESS;
  1631. HKEY hKey = NULL;
  1632. DWORD dwDataType;
  1633. DWORD dwBufferSize = 0;
  1634. WCHAR* szNewStringBuffer = NULL;
  1635. assert ( NULL != szFolder );
  1636. assert ( NULL != piBufLen );
  1637. if ( NULL != szFolder
  1638. && NULL != piBufLen ) {
  1639. dwStatus = RegOpenKey (
  1640. HKEY_LOCAL_MACHINE,
  1641. L"System\\CurrentControlSet\\Services\\SysmonLog",
  1642. &hKey );
  1643. if ( ERROR_SUCCESS == dwStatus ) {
  1644. dwDataType = 0;
  1645. // Determine the size of the required buffer.
  1646. dwStatus = RegQueryValueExW (
  1647. hKey,
  1648. L"DefaultLogFileFolder",
  1649. NULL,
  1650. &dwDataType,
  1651. NULL,
  1652. &dwBufferSize);
  1653. if (dwStatus == ERROR_SUCCESS) {
  1654. if (dwBufferSize > 0) {
  1655. szNewStringBuffer = new WCHAR[dwBufferSize / sizeof(WCHAR) ];
  1656. if ( NULL != szNewStringBuffer ) {
  1657. *szNewStringBuffer = L'\0';
  1658. dwStatus = RegQueryValueEx(
  1659. hKey,
  1660. L"DefaultLogFileFolder",
  1661. NULL,
  1662. &dwDataType,
  1663. (LPBYTE) szNewStringBuffer,
  1664. (LPDWORD) &dwBufferSize );
  1665. } else {
  1666. dwStatus = ERROR_OUTOFMEMORY;
  1667. }
  1668. } else {
  1669. dwStatus = ERROR_NO_DATA;
  1670. }
  1671. }
  1672. RegCloseKey(hKey);
  1673. }
  1674. if (dwStatus == ERROR_SUCCESS) {
  1675. if ( *piBufLen >= (INT)(dwBufferSize / sizeof(WCHAR)) ) {
  1676. StringCchCopy(szFolder, *piBufLen, szNewStringBuffer );
  1677. } else {
  1678. dwStatus = ERROR_INSUFFICIENT_BUFFER;
  1679. }
  1680. *piBufLen = dwBufferSize / sizeof(WCHAR);
  1681. }
  1682. if ( NULL != szNewStringBuffer )
  1683. delete [] szNewStringBuffer;
  1684. } else {
  1685. dwStatus = ERROR_INVALID_PARAMETER;
  1686. }
  1687. return dwStatus;
  1688. }
  1689. BOOL
  1690. AreSameCounterPath (
  1691. PPDH_COUNTER_PATH_ELEMENTS pFirst,
  1692. PPDH_COUNTER_PATH_ELEMENTS pSecond )
  1693. {
  1694. BOOL bSame = FALSE;
  1695. assert ( NULL != pFirst && NULL != pSecond );
  1696. if ( NULL != pFirst && NULL != pSecond ) {
  1697. if ( 0 == lstrcmpi ( pFirst->szMachineName, pSecond->szMachineName ) ) {
  1698. if ( 0 == lstrcmpi ( pFirst->szObjectName, pSecond->szObjectName ) ) {
  1699. if ( 0 == lstrcmpi ( pFirst->szInstanceName, pSecond->szInstanceName ) ) {
  1700. if ( 0 == lstrcmpi ( pFirst->szParentInstance, pSecond->szParentInstance ) ) {
  1701. if ( pFirst->dwInstanceIndex == pSecond->dwInstanceIndex ) {
  1702. if ( 0 == lstrcmpi ( pFirst->szCounterName, pSecond->szCounterName ) ) {
  1703. bSame = TRUE;
  1704. }
  1705. }
  1706. }
  1707. }
  1708. }
  1709. }
  1710. }
  1711. return bSame;
  1712. };
  1713. BOOL
  1714. DisplaySingleLogSampleValue ( void )
  1715. {
  1716. long nErr;
  1717. HKEY hKey = NULL;
  1718. DWORD dwRegValue;
  1719. DWORD dwDataType;
  1720. DWORD dwDataSize;
  1721. DWORD dwDisposition;
  1722. static INT siInitialized; // Initialized to 0
  1723. static BOOL sbSingleValue; // Initialized to 0 ( FALSE )
  1724. // check registry setting to see if thousands separator is enabled
  1725. if ( 0 == siInitialized ) {
  1726. nErr = RegOpenKey(
  1727. HKEY_CURRENT_USER,
  1728. L"Software\\Microsoft\\SystemMonitor",
  1729. &hKey );
  1730. if( ERROR_SUCCESS != nErr ) {
  1731. nErr = RegCreateKeyEx(
  1732. HKEY_CURRENT_USER,
  1733. L"Software\\Microsoft\\SystemMonitor",
  1734. 0,
  1735. L"REG_DWORD",
  1736. REG_OPTION_NON_VOLATILE,
  1737. KEY_ALL_ACCESS,
  1738. NULL,
  1739. &hKey,
  1740. &dwDisposition );
  1741. }
  1742. dwRegValue = 0;
  1743. if ( ERROR_SUCCESS == nErr ) {
  1744. dwDataSize = sizeof(DWORD);
  1745. nErr = RegQueryValueExW (
  1746. hKey,
  1747. L"DisplaySingleLogSampleValue",
  1748. NULL,
  1749. &dwDataType,
  1750. (LPBYTE) &dwRegValue,
  1751. (LPDWORD) &dwDataSize );
  1752. if ( ERROR_SUCCESS == nErr
  1753. && REG_DWORD == dwDataType
  1754. && sizeof(DWORD) == dwDataSize )
  1755. {
  1756. if ( 0 != dwRegValue ) {
  1757. sbSingleValue = TRUE;
  1758. }
  1759. }
  1760. siInitialized = 1;
  1761. }
  1762. if ( NULL != hKey ) {
  1763. nErr = RegCloseKey( hKey );
  1764. }
  1765. }
  1766. return sbSingleValue;
  1767. }
  1768. DWORD
  1769. FormatSqlDataSourceName (
  1770. LPCWSTR szSqlDsn,
  1771. LPCWSTR szSqlLogSetName,
  1772. LPWSTR szSqlDataSourceName,
  1773. ULONG* pulBufLen )
  1774. {
  1775. DWORD dwStatus = ERROR_SUCCESS;
  1776. ULONG ulNameLen;
  1777. if ( NULL != pulBufLen ) {
  1778. ulNameLen = lstrlen (szSqlDsn)
  1779. + lstrlen(szSqlLogSetName)
  1780. + 5 // SQL:<DSN>!<LOGSET>
  1781. + 2; // 2 NULL characters at the end;
  1782. if ( ulNameLen <= *pulBufLen ) {
  1783. if ( NULL != szSqlDataSourceName ) {
  1784. StringCchPrintf( szSqlDataSourceName,
  1785. *pulBufLen,
  1786. cszSqlDataSourceFormat,
  1787. szSqlDsn,
  1788. szSqlLogSetName );
  1789. }
  1790. } else if ( NULL != szSqlDataSourceName ) {
  1791. dwStatus = ERROR_MORE_DATA;
  1792. }
  1793. *pulBufLen = ulNameLen;
  1794. } else {
  1795. dwStatus = ERROR_INVALID_PARAMETER;
  1796. assert ( FALSE );
  1797. }
  1798. return dwStatus;
  1799. }
  1800. DWORD
  1801. DisplayDataSourceError (
  1802. HWND hwndOwner,
  1803. DWORD dwErrorStatus,
  1804. INT iDataSourceType,
  1805. LPCWSTR szLogFileName,
  1806. LPCWSTR szSqlDsn,
  1807. LPCWSTR szSqlLogSetName )
  1808. {
  1809. DWORD dwStatus = ERROR_SUCCESS;
  1810. LPWSTR szMessage = NULL;
  1811. LPWSTR szDataSource = NULL;
  1812. ULONG ulMsgBufLen = 0;
  1813. WCHAR szSystemMessage[MAX_PATH];
  1814. // todo: Alloc message buffers
  1815. if ( sysmonLogFiles == iDataSourceType ) {
  1816. if ( NULL != szLogFileName ) {
  1817. ulMsgBufLen = lstrlen ( szLogFileName ) +1;
  1818. szDataSource = new WCHAR [ulMsgBufLen];
  1819. if ( NULL != szDataSource ) {
  1820. StringCchCopy(szDataSource, ulMsgBufLen, szLogFileName );
  1821. } else {
  1822. dwStatus = ERROR_NOT_ENOUGH_MEMORY;
  1823. }
  1824. } else {
  1825. assert ( FALSE );
  1826. dwStatus = ERROR_INVALID_PARAMETER;
  1827. }
  1828. } else if ( sysmonSqlLog == iDataSourceType ){
  1829. if ( NULL != szSqlDsn && NULL != szSqlLogSetName ) {
  1830. FormatSqlDataSourceName (
  1831. szSqlDsn,
  1832. szSqlLogSetName,
  1833. NULL,
  1834. &ulMsgBufLen );
  1835. szDataSource = new WCHAR [ulMsgBufLen];
  1836. if ( NULL != szDataSource ) {
  1837. FormatSqlDataSourceName (
  1838. szSqlDsn,
  1839. szSqlLogSetName,
  1840. (LPWSTR)szDataSource,
  1841. &ulMsgBufLen );
  1842. // todo: check status
  1843. } else {
  1844. dwStatus = ERROR_NOT_ENOUGH_MEMORY;
  1845. }
  1846. } else {
  1847. assert ( FALSE );
  1848. dwStatus = ERROR_INVALID_PARAMETER;
  1849. }
  1850. } else {
  1851. assert ( FALSE );
  1852. dwStatus = ERROR_INVALID_PARAMETER;
  1853. }
  1854. if ( ERROR_SUCCESS == dwStatus ) {
  1855. ulMsgBufLen += RESOURCE_STRING_BUF_LEN;
  1856. ulMsgBufLen += MAX_PATH;
  1857. szMessage = new WCHAR [ulMsgBufLen];
  1858. if ( NULL != szMessage ) {
  1859. if ( SMON_STATUS_TOO_FEW_SAMPLES == dwErrorStatus ) {
  1860. StringCchPrintf(szMessage,
  1861. ulMsgBufLen,
  1862. ResourceString(IDS_TOO_FEW_SAMPLES_ERR),
  1863. szDataSource );
  1864. } else if ( SMON_STATUS_LOG_FILE_SIZE_LIMIT == dwErrorStatus ) {
  1865. StringCchPrintf(szMessage,
  1866. ulMsgBufLen,
  1867. ResourceString(IDS_LOG_FILE_TOO_LARGE_ERR),
  1868. szDataSource );
  1869. } else {
  1870. StringCchPrintf(szMessage,
  1871. ulMsgBufLen,
  1872. ResourceString(IDS_BADDATASOURCE_ERR),
  1873. szDataSource );
  1874. FormatSystemMessage ( dwErrorStatus, szSystemMessage, MAX_PATH - 1 );
  1875. StringCchCat(szMessage, ulMsgBufLen, szSystemMessage );
  1876. }
  1877. MessageBox(
  1878. hwndOwner,
  1879. szMessage,
  1880. ResourceString(IDS_APP_NAME),
  1881. MB_OK | MB_ICONEXCLAMATION);
  1882. }
  1883. }
  1884. if ( NULL != szDataSource ) {
  1885. delete [] szDataSource;
  1886. }
  1887. if ( NULL != szMessage ) {
  1888. delete [] szMessage;
  1889. }
  1890. return dwStatus;
  1891. }