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.

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