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
2370 lines
61 KiB
/*++
|
|
|
|
Copyright (C) 1992-1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
utils.cpp
|
|
|
|
Abstract:
|
|
|
|
This file contains miscellaneous utiltity routines, mostly
|
|
low-level windows helpers. These routines are not specific
|
|
to the System Monitor control.
|
|
|
|
--*/
|
|
|
|
//==========================================================================//
|
|
// Includes //
|
|
//==========================================================================//
|
|
|
|
#include <windows.h>
|
|
#include <assert.h>
|
|
#include <math.h>
|
|
#include <winperf.h>
|
|
#include "utils.h"
|
|
#include "unihelpr.h"
|
|
#include "globals.h"
|
|
#include "winhelpr.h"
|
|
#include "polyline.h" // For eDataSourceType
|
|
#include <strsafe.h>
|
|
#include "smonmsg.h" // For error string IDs.
|
|
|
|
#define NUM_RESOURCE_STRING_BUFFERS 16
|
|
#define MISSING_RESOURCE_STRING L"????"
|
|
|
|
#define szHexFormat L"0x%08lX"
|
|
#define szLargeHexFormat L"0x%08lX%08lX"
|
|
|
|
LPCWSTR cszSqlDataSourceFormat = L"SQL:%s!%s";
|
|
|
|
//==========================================================================//
|
|
// Exported Functions //
|
|
//==========================================================================//
|
|
|
|
|
|
VOID
|
|
Line (
|
|
IN HDC hDC,
|
|
IN HPEN hPen,
|
|
IN INT x1,
|
|
IN INT y1,
|
|
IN INT x2,
|
|
IN INT y2
|
|
)
|
|
{
|
|
HPEN hPenPrevious = NULL;
|
|
|
|
assert ( NULL != hDC );
|
|
|
|
if ( NULL != hDC ) {
|
|
if ( NULL != hPen ) {
|
|
hPenPrevious = (HPEN)SelectObject (hDC, hPen) ;
|
|
}
|
|
|
|
MoveToEx (hDC, x1, y1, NULL) ;
|
|
LineTo (hDC, x2, y2) ;
|
|
|
|
if ( NULL != hPen ) {
|
|
SelectObject (hDC, hPenPrevious);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
Fill (
|
|
IN HDC hDC,
|
|
IN DWORD rgbColor,
|
|
IN LPRECT lpRect
|
|
)
|
|
{
|
|
HBRUSH hBrush = NULL;
|
|
|
|
assert ( NULL != hDC && NULL != lpRect );
|
|
|
|
if ( NULL != hDC && NULL != lpRect ) {
|
|
|
|
hBrush = CreateSolidBrush (rgbColor) ;
|
|
|
|
if ( NULL != hBrush ) {
|
|
FillRect (hDC, lpRect, hBrush) ;
|
|
DeleteObject (hBrush) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
INT
|
|
TextWidth (
|
|
IN HDC hDC,
|
|
IN LPCWSTR lpszText
|
|
)
|
|
{
|
|
SIZE size ;
|
|
INT iReturn;
|
|
|
|
iReturn = 0;
|
|
|
|
assert ( NULL != hDC && NULL != lpszText );
|
|
|
|
if ( NULL != lpszText && NULL != hDC) {
|
|
if ( GetTextExtentPoint (hDC, lpszText, lstrlen (lpszText), &size) ) {
|
|
iReturn = size.cx;
|
|
}
|
|
}
|
|
return iReturn;
|
|
}
|
|
|
|
|
|
INT
|
|
FontHeight (
|
|
IN HDC hDC,
|
|
IN BOOL bIncludeLeading
|
|
)
|
|
{
|
|
TEXTMETRIC tm ;
|
|
INT iReturn = 0;
|
|
|
|
assert ( NULL != hDC );
|
|
|
|
if ( NULL != hDC ) {
|
|
GetTextMetrics (hDC, &tm) ;
|
|
if (bIncludeLeading) {
|
|
iReturn = tm.tmHeight + tm.tmExternalLeading;
|
|
} else {
|
|
iReturn = tm.tmHeight;
|
|
}
|
|
}
|
|
return iReturn;
|
|
}
|
|
|
|
|
|
INT
|
|
TextAvgWidth (
|
|
IN HDC hDC,
|
|
IN INT iNumChars
|
|
)
|
|
{
|
|
TEXTMETRIC tm ;
|
|
INT xAvgWidth ;
|
|
INT iReturn = 0;
|
|
|
|
assert ( NULL != hDC );
|
|
|
|
if ( NULL != hDC ) {
|
|
GetTextMetrics (hDC, &tm) ;
|
|
|
|
xAvgWidth = iNumChars * tm.tmAveCharWidth ;
|
|
|
|
// add 10% slop
|
|
iReturn = MulDiv (xAvgWidth, 11, 10);
|
|
}
|
|
return iReturn;
|
|
}
|
|
|
|
|
|
BOOL
|
|
DialogEnable (
|
|
IN HWND hDlg,
|
|
IN WORD wID,
|
|
IN BOOL bEnable
|
|
)
|
|
/*
|
|
Effect: Enable or disable (based on bEnable) the control
|
|
identified by wID in dialog hDlg.
|
|
|
|
See Also: DialogShow.
|
|
*/
|
|
{
|
|
BOOL bStatus = TRUE; // Success
|
|
DWORD dwStatus = ERROR_SUCCESS;
|
|
HWND hControl ;
|
|
|
|
assert ( NULL != hDlg );
|
|
|
|
if ( NULL != hDlg ) {
|
|
hControl = GetDlgItem (hDlg, wID) ;
|
|
|
|
if (hControl) {
|
|
if ( 0 == EnableWindow (hControl, bEnable) ) {
|
|
dwStatus = GetLastError();
|
|
if ( ERROR_SUCCESS != dwStatus ) {
|
|
bStatus = FALSE;
|
|
}
|
|
}
|
|
} else {
|
|
bStatus = FALSE;
|
|
}
|
|
} else {
|
|
bStatus = FALSE;
|
|
}
|
|
return bStatus;
|
|
}
|
|
|
|
|
|
VOID
|
|
DialogShow (
|
|
IN HWND hDlg,
|
|
IN WORD wID,
|
|
IN BOOL bShow
|
|
)
|
|
{
|
|
HWND hControl ;
|
|
|
|
assert ( NULL != hDlg );
|
|
|
|
if ( NULL != hDlg ) {
|
|
|
|
hControl = GetDlgItem (hDlg, wID) ;
|
|
|
|
if (hControl) {
|
|
ShowWindow (hControl, bShow ? SW_SHOW : SW_HIDE) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
FLOAT
|
|
DialogFloat (
|
|
IN HWND hDlg,
|
|
IN WORD wControlID,
|
|
OUT BOOL *pbOK)
|
|
/*
|
|
Effect: Return a floating point representation of the string
|
|
value found in the control wControlID of hDlg.
|
|
|
|
Internals: We use sscanf instead of atof becuase atof returns a
|
|
double. This may or may not be the right thing to do.
|
|
*/
|
|
{
|
|
WCHAR szValue [MAX_VALUE_LEN] ;
|
|
FLOAT eValue = 0.0;
|
|
UINT uiCharCount = 0;
|
|
INT iNumScanned = 0 ;
|
|
|
|
assert ( NULL != hDlg );
|
|
assert ( NULL != pbOK );
|
|
|
|
//
|
|
// If any errors, iNumScanned remains 0 and *pbOK = FALSE
|
|
//
|
|
if ( NULL != hDlg ) {
|
|
|
|
uiCharCount = DialogText (hDlg, wControlID, szValue) ;
|
|
if ( 0 < uiCharCount ) {
|
|
iNumScanned = swscanf (szValue, L"%e", &eValue) ;
|
|
}
|
|
}
|
|
if (pbOK) {
|
|
*pbOK = ( 1 == iNumScanned ) ;
|
|
}
|
|
return (eValue) ;
|
|
}
|
|
|
|
|
|
BOOL NeedEllipses (
|
|
IN HDC hAttribDC,
|
|
IN LPCWSTR pszText,
|
|
IN INT nTextLen,
|
|
IN INT xMaxExtent,
|
|
IN INT xEllipses,
|
|
OUT INT *pnChars
|
|
)
|
|
{
|
|
|
|
SIZE size;
|
|
|
|
*pnChars = 0;
|
|
// If no space or no chars, just return
|
|
if (xMaxExtent <= 0 || nTextLen == 0) {
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
assert ( NULL != hAttribDC
|
|
&& NULL != pszText
|
|
&& NULL != pnChars );
|
|
|
|
if ( NULL == hAttribDC
|
|
|| NULL == pszText
|
|
|| NULL == pnChars ) {
|
|
return FALSE;
|
|
}
|
|
|
|
// Find out how many characters will fit
|
|
GetTextExtentExPoint(hAttribDC, pszText, nTextLen, xMaxExtent, pnChars, NULL, &size);
|
|
|
|
// If all or none fit, we're done
|
|
if (*pnChars == nTextLen || *pnChars == 0) {
|
|
return FALSE;
|
|
}
|
|
|
|
// How many chars will fit with ellipses?
|
|
if (xMaxExtent > xEllipses) {
|
|
GetTextExtentExPoint(hAttribDC, pszText, *pnChars, (xMaxExtent - xEllipses),
|
|
pnChars, NULL, &size);
|
|
} else {
|
|
*pnChars = 0;
|
|
}
|
|
|
|
// Better to show one char than just ellipses
|
|
if ( 0 == *pnChars ) {
|
|
*pnChars = 1;
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
VOID
|
|
FitTextOut (
|
|
IN HDC hDC,
|
|
IN HDC hAttribDC,
|
|
IN UINT fuOptions,
|
|
IN CONST RECT *lprc,
|
|
IN LPCWSTR lpString,
|
|
IN INT cchCount,
|
|
IN INT iAlign,
|
|
IN BOOL fVertical
|
|
)
|
|
{
|
|
LPWSTR szOutput = NULL;
|
|
LPWSTR szDisplay = NULL;
|
|
INT iExtent;
|
|
INT nOutCnt = 0;
|
|
SIZE size;
|
|
INT x,y;
|
|
|
|
assert ( NULL != hAttribDC
|
|
&& NULL != lprc
|
|
&& NULL != lpString );
|
|
|
|
if ( NULL != hAttribDC
|
|
&& NULL != lprc
|
|
&& NULL != lpString ) {
|
|
|
|
szDisplay = const_cast<LPWSTR>(lpString);
|
|
|
|
//
|
|
// Add one for NULL
|
|
//
|
|
szOutput = new WCHAR [ cchCount + ELLIPSES_CNT + 1 ];
|
|
|
|
if ( NULL != szOutput ) {
|
|
|
|
iExtent = fVertical ? (lprc->bottom - lprc->top) : (lprc->right - lprc->left);
|
|
|
|
GetTextExtentPoint (hAttribDC, ELLIPSES, ELLIPSES_CNT, &size) ;
|
|
|
|
if (NeedEllipses(hAttribDC, lpString, cchCount, iExtent, size.cx, &nOutCnt)) {
|
|
|
|
ZeroMemory ( szOutput, (cchCount + ELLIPSES_CNT + 1) * sizeof(WCHAR) );
|
|
|
|
StringCchCopyN ( szOutput, cchCount + ELLIPSES_CNT + 1, lpString, cchCount );
|
|
|
|
StringCchCopy(
|
|
&szOutput[nOutCnt],
|
|
(cchCount + ELLIPSES_CNT + 1) - nOutCnt,
|
|
ELLIPSES );
|
|
|
|
nOutCnt += ELLIPSES_CNT;
|
|
szDisplay = szOutput;
|
|
}
|
|
}
|
|
|
|
if (fVertical) {
|
|
switch (iAlign) {
|
|
|
|
case TA_CENTER:
|
|
y = (lprc->top + lprc->bottom) / 2;
|
|
break;
|
|
|
|
case TA_RIGHT:
|
|
y = lprc->top;
|
|
break;
|
|
|
|
default:
|
|
y = lprc->bottom;
|
|
break;
|
|
}
|
|
|
|
x = lprc->left;
|
|
}
|
|
else {
|
|
switch (iAlign) {
|
|
|
|
case TA_CENTER:
|
|
x = (lprc->left + lprc->right) / 2;
|
|
break;
|
|
|
|
case TA_RIGHT:
|
|
x = lprc->right;
|
|
break;
|
|
|
|
default:
|
|
x = lprc->left;
|
|
break;
|
|
}
|
|
|
|
y = lprc->top;
|
|
}
|
|
|
|
ExtTextOut(hDC, x, y, fuOptions, lprc, szDisplay, nOutCnt, NULL);
|
|
}
|
|
if ( NULL != szOutput ) {
|
|
delete [] szOutput;
|
|
}
|
|
}
|
|
|
|
BOOL
|
|
TruncateLLTime (
|
|
IN LONGLONG llTime,
|
|
OUT LONGLONG* pllTime
|
|
)
|
|
{
|
|
SYSTEMTIME SystemTime;
|
|
BOOL bReturn = FALSE;
|
|
|
|
assert ( NULL != pllTime );
|
|
|
|
if ( NULL != pllTime ) {
|
|
if ( FileTimeToSystemTime((FILETIME*)&llTime, &SystemTime) ) {
|
|
SystemTime.wMilliseconds = 0;
|
|
bReturn = SystemTimeToFileTime(&SystemTime, (FILETIME*)pllTime);
|
|
}
|
|
}
|
|
return bReturn;
|
|
}
|
|
|
|
|
|
BOOL
|
|
LLTimeToVariantDate (
|
|
IN LONGLONG llTime,
|
|
OUT DATE *pdate
|
|
)
|
|
{
|
|
BOOL bReturn = FALSE;
|
|
SYSTEMTIME SystemTime;
|
|
|
|
assert ( NULL != pdate );
|
|
|
|
if ( NULL != pdate ) {
|
|
if ( FileTimeToSystemTime((FILETIME*)&llTime, &SystemTime) ) {
|
|
bReturn = SystemTimeToVariantTime(&SystemTime, pdate);
|
|
}
|
|
}
|
|
return bReturn;
|
|
}
|
|
|
|
|
|
BOOL
|
|
VariantDateToLLTime (
|
|
IN DATE date,
|
|
OUT LONGLONG *pllTime
|
|
)
|
|
{
|
|
BOOL bReturn = FALSE;
|
|
SYSTEMTIME SystemTime;
|
|
|
|
|
|
assert ( NULL != pllTime );
|
|
|
|
if ( NULL != pllTime ) {
|
|
if ( VariantTimeToSystemTime(date, &SystemTime) ) {
|
|
bReturn = SystemTimeToFileTime(&SystemTime,(FILETIME*)pllTime);
|
|
}
|
|
}
|
|
return bReturn;
|
|
}
|
|
|
|
//
|
|
// WideStringFromStream also supports multi-sz
|
|
//
|
|
HRESULT
|
|
WideStringFromStream (
|
|
LPSTREAM pIStream,
|
|
LPWSTR *ppsz,
|
|
INT nLen
|
|
)
|
|
{
|
|
ULONG bc = 0;
|
|
LPWSTR pszWide = NULL;
|
|
HRESULT hr = E_POINTER;
|
|
|
|
assert ( NULL != pIStream && NULL != ppsz );
|
|
|
|
// This method does not perform conversion from W to T.
|
|
assert ( sizeof(WCHAR) == sizeof(WCHAR) );
|
|
|
|
if ( NULL != pIStream
|
|
&& NULL != ppsz ) {
|
|
|
|
*ppsz = NULL;
|
|
|
|
if (nLen == 0) {
|
|
hr = S_OK;
|
|
} else {
|
|
pszWide = new WCHAR[nLen + 1];
|
|
if (pszWide == NULL) {
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
else {
|
|
hr = pIStream->Read(pszWide, nLen*sizeof(WCHAR), &bc);
|
|
}
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
if (bc != (ULONG)nLen*sizeof(WCHAR)) {
|
|
hr = E_FAIL;
|
|
}
|
|
}
|
|
if (SUCCEEDED(hr)) {
|
|
// Write ending NULL for non-multisz strings.
|
|
pszWide[nLen] = L'\0';
|
|
|
|
*ppsz = new WCHAR [nLen + 1];
|
|
if ( NULL != *ppsz ) {
|
|
memcpy(*ppsz, pszWide, (nLen+1)*sizeof(WCHAR) );
|
|
} else {
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
if (pszWide != NULL) {
|
|
delete [] pszWide;
|
|
}
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Property bag I/O - only include if user knows about IStream
|
|
//
|
|
#ifdef __IPropertyBag_INTERFACE_DEFINED__
|
|
|
|
HRESULT
|
|
IntegerToPropertyBag (
|
|
IPropertyBag* pIPropBag,
|
|
LPCWSTR szPropName,
|
|
INT intData )
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
VARIANT vValue;
|
|
|
|
assert ( NULL != pIPropBag );
|
|
|
|
if ( NULL != pIPropBag ) {
|
|
|
|
VariantInit( &vValue );
|
|
vValue.vt = VT_I4;
|
|
vValue.lVal = intData;
|
|
|
|
hr = pIPropBag->Write(szPropName, &vValue );
|
|
|
|
VariantClear ( &vValue );
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
OleColorToPropertyBag (
|
|
IPropertyBag* pIPropBag,
|
|
LPCWSTR szPropName,
|
|
OLE_COLOR& clrData )
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
VARIANT vValue;
|
|
|
|
assert ( NULL != pIPropBag );
|
|
|
|
if ( NULL != pIPropBag ) {
|
|
|
|
VariantInit( &vValue );
|
|
vValue.vt = VT_COLOR; // VT_COLOR = VT_I4
|
|
vValue.lVal = clrData;
|
|
|
|
hr = pIPropBag->Write(szPropName, &vValue );
|
|
|
|
VariantClear ( &vValue );
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
ShortToPropertyBag (
|
|
IPropertyBag* pIPropBag,
|
|
LPCWSTR szPropName,
|
|
SHORT iData )
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
VARIANT vValue;
|
|
|
|
assert ( NULL != pIPropBag );
|
|
|
|
if ( NULL != pIPropBag ) {
|
|
|
|
VariantInit( &vValue );
|
|
vValue.vt = VT_I2;
|
|
vValue.iVal = iData;
|
|
|
|
hr = pIPropBag->Write(szPropName, &vValue );
|
|
|
|
VariantClear ( &vValue );
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
BOOLToPropertyBag (
|
|
IPropertyBag* pIPropBag,
|
|
LPCWSTR szPropName,
|
|
BOOL bData )
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
VARIANT vValue;
|
|
|
|
assert ( NULL != pIPropBag );
|
|
|
|
if ( NULL != pIPropBag ) {
|
|
|
|
VariantInit( &vValue );
|
|
vValue.vt = VT_BOOL;
|
|
vValue.boolVal = (SHORT)bData;
|
|
|
|
hr = pIPropBag->Write(szPropName, &vValue );
|
|
|
|
VariantClear ( &vValue );
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
DoubleToPropertyBag (
|
|
IPropertyBag* pIPropBag,
|
|
LPCWSTR szPropName,
|
|
DOUBLE dblData )
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
VARIANT vValue;
|
|
|
|
assert ( NULL != pIPropBag );
|
|
|
|
if ( NULL != pIPropBag ) {
|
|
|
|
VariantInit( &vValue );
|
|
vValue.vt = VT_R8;
|
|
vValue.dblVal = dblData;
|
|
|
|
hr = pIPropBag->Write(szPropName, &vValue );
|
|
|
|
VariantClear ( &vValue );
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
FloatToPropertyBag (
|
|
IPropertyBag* pIPropBag,
|
|
LPCWSTR szPropName,
|
|
FLOAT fData )
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
VARIANT vValue;
|
|
|
|
assert ( NULL != pIPropBag );
|
|
|
|
if ( NULL != pIPropBag ) {
|
|
|
|
VariantInit( &vValue );
|
|
vValue.vt = VT_R4;
|
|
vValue.fltVal = fData;
|
|
|
|
hr = pIPropBag->Write(szPropName, &vValue );
|
|
|
|
VariantClear ( &vValue );
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
CyToPropertyBag (
|
|
IPropertyBag* pIPropBag,
|
|
LPCWSTR szPropName,
|
|
CY& cyData )
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
VARIANT vValue;
|
|
|
|
assert ( NULL != pIPropBag );
|
|
|
|
if ( NULL != pIPropBag ) {
|
|
|
|
VariantInit( &vValue );
|
|
vValue.vt = VT_CY;
|
|
vValue.cyVal.int64 = cyData.int64;
|
|
|
|
hr = VariantChangeType ( &vValue, &vValue, NULL, VT_BSTR );
|
|
|
|
if ( SUCCEEDED ( hr ) )
|
|
hr = pIPropBag->Write(szPropName, &vValue );
|
|
|
|
VariantClear ( &vValue );
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
typedef struct _HTML_ENTITIES {
|
|
LPWSTR szHTML;
|
|
LPWSTR szEntity;
|
|
} HTML_ENTITIES;
|
|
|
|
HTML_ENTITIES g_htmlentities[] = {
|
|
L"&", L"&",
|
|
L"\"", L""",
|
|
L"<", L"<",
|
|
L">", L">",
|
|
NULL, NULL
|
|
};
|
|
|
|
HRESULT
|
|
StringToPropertyBag (
|
|
IPropertyBag* pIPropBag,
|
|
LPCWSTR szPropName,
|
|
LPCWSTR szData )
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
VARIANT vValue;
|
|
LPWSTR szTrans = NULL;
|
|
BOOL bAllocated = FALSE;
|
|
size_t cchTrans = 0;
|
|
LPWSTR szScan = NULL;
|
|
int i;
|
|
|
|
assert ( NULL != pIPropBag );
|
|
|
|
if ( NULL != pIPropBag ) {
|
|
|
|
VariantInit( &vValue );
|
|
vValue.vt = VT_BSTR;
|
|
vValue.bstrVal = NULL;
|
|
|
|
if ( NULL != szData ) {
|
|
|
|
//
|
|
// Max length of szHTML is 6. Add 5 because 1 will be added
|
|
// when add original data length below.
|
|
//
|
|
for( i=0 ;g_htmlentities[i].szHTML != NULL; i++ ){
|
|
szScan = (LPWSTR)szData;
|
|
while( *szScan != L'\0' ) {
|
|
if( *szScan == *g_htmlentities[i].szHTML ){
|
|
cchTrans += 5;
|
|
}
|
|
szScan++;
|
|
}
|
|
}
|
|
|
|
if( cchTrans > 0 ){
|
|
//
|
|
// Add 1 for null.
|
|
//
|
|
cchTrans += lstrlen (szData) + 1;
|
|
|
|
szTrans = new WCHAR [ cchTrans ];
|
|
if( szTrans != NULL ){
|
|
bAllocated = TRUE;
|
|
ZeroMemory( szTrans, cchTrans * sizeof(WCHAR) );
|
|
szScan = (LPWSTR)szData;
|
|
while( *szScan != L'\0' ){
|
|
BOOL bEntity = FALSE;
|
|
|
|
for( i=0; g_htmlentities[i].szHTML != NULL; i++ ){
|
|
if( *szScan == *g_htmlentities[i].szHTML ){
|
|
bEntity = TRUE;
|
|
StringCchCat(szTrans, cchTrans, g_htmlentities[i].szEntity);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( !bEntity ){
|
|
StringCchCatN ( szTrans, cchTrans, szScan, 1 );
|
|
}
|
|
szScan++;
|
|
}
|
|
} else {
|
|
szTrans = (LPWSTR)szData;
|
|
}
|
|
} else {
|
|
szTrans = (LPWSTR)szData;
|
|
}
|
|
|
|
vValue.bstrVal = SysAllocString ( szTrans );
|
|
|
|
if ( NULL != vValue.bstrVal ) {
|
|
hr = pIPropBag->Write(szPropName, &vValue );
|
|
VariantClear ( &vValue );
|
|
} else {
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
} else {
|
|
hr = pIPropBag->Write(szPropName, &vValue );
|
|
}
|
|
}
|
|
|
|
if( NULL != szTrans && bAllocated ){
|
|
delete [] szTrans;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
LLTimeToPropertyBag (
|
|
IPropertyBag* pIPropBag,
|
|
LPCWSTR szPropName,
|
|
LONGLONG& rllData )
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
VARIANT vValue;
|
|
BOOL bStatus;
|
|
|
|
assert ( NULL != pIPropBag );
|
|
|
|
if ( NULL != pIPropBag ) {
|
|
|
|
VariantInit( &vValue );
|
|
vValue.vt = VT_DATE;
|
|
|
|
bStatus = LLTimeToVariantDate ( rllData, &vValue.date );
|
|
|
|
if ( bStatus ) {
|
|
|
|
hr = pIPropBag->Write(szPropName, &vValue );
|
|
|
|
VariantClear ( &vValue );
|
|
|
|
} else {
|
|
hr = E_FAIL;
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
IntegerFromPropertyBag (
|
|
IPropertyBag* pIPropBag,
|
|
IErrorLog* pIErrorLog,
|
|
LPCWSTR szPropName,
|
|
INT& rintData )
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
VARIANT vValue;
|
|
|
|
assert ( NULL != pIPropBag );
|
|
|
|
if ( NULL != pIPropBag ) {
|
|
|
|
VariantInit( &vValue );
|
|
vValue.vt = VT_I4;
|
|
vValue.lVal = 0;
|
|
|
|
hr = pIPropBag->Read(szPropName, &vValue, pIErrorLog );
|
|
|
|
if ( SUCCEEDED ( hr ) ) {
|
|
rintData = vValue.lVal;
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
OleColorFromPropertyBag (
|
|
IPropertyBag* pIPropBag,
|
|
IErrorLog* pIErrorLog,
|
|
LPCWSTR szPropName,
|
|
OLE_COLOR& rintData )
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
VARIANT vValue;
|
|
|
|
assert ( NULL != pIPropBag );
|
|
|
|
if ( NULL != pIPropBag ) {
|
|
|
|
VariantInit( &vValue );
|
|
vValue.vt = VT_COLOR; // VT_COLOR == VT_I4;
|
|
|
|
hr = pIPropBag->Read(szPropName, &vValue, pIErrorLog );
|
|
|
|
if ( SUCCEEDED ( hr ) ) {
|
|
rintData = vValue.lVal;
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
BOOLFromPropertyBag (
|
|
IPropertyBag* pIPropBag,
|
|
IErrorLog* pIErrorLog,
|
|
LPCWSTR szPropName,
|
|
BOOL& rbData )
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
VARIANT vValue;
|
|
|
|
assert ( NULL != pIPropBag );
|
|
|
|
if ( NULL != pIPropBag ) {
|
|
|
|
VariantInit( &vValue );
|
|
vValue.vt = VT_BOOL;
|
|
|
|
hr = pIPropBag->Read(szPropName, &vValue, pIErrorLog );
|
|
|
|
if ( SUCCEEDED ( hr ) ) {
|
|
rbData = vValue.boolVal;
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
DoubleFromPropertyBag (
|
|
IPropertyBag* pIPropBag,
|
|
IErrorLog* pIErrorLog,
|
|
LPCWSTR szPropName,
|
|
DOUBLE& rdblData )
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
VARIANT vValue;
|
|
|
|
assert ( NULL != pIPropBag );
|
|
|
|
if ( NULL != pIPropBag ) {
|
|
|
|
VariantInit( &vValue );
|
|
vValue.vt = VT_R8;
|
|
|
|
hr = pIPropBag->Read(szPropName, &vValue, pIErrorLog );
|
|
|
|
if ( SUCCEEDED ( hr ) ) {
|
|
rdblData = vValue.dblVal;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
FloatFromPropertyBag (
|
|
IPropertyBag* pIPropBag,
|
|
IErrorLog* pIErrorLog,
|
|
LPCWSTR szPropName,
|
|
FLOAT& rfData )
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
VARIANT vValue;
|
|
|
|
assert ( NULL != pIPropBag );
|
|
|
|
if ( NULL != pIPropBag ) {
|
|
|
|
VariantInit( &vValue );
|
|
vValue.vt = VT_R4;
|
|
|
|
hr = pIPropBag->Read(szPropName, &vValue, pIErrorLog );
|
|
|
|
if ( SUCCEEDED ( hr ) ) {
|
|
rfData = vValue.fltVal;
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
ShortFromPropertyBag (
|
|
IPropertyBag* pIPropBag,
|
|
IErrorLog* pIErrorLog,
|
|
LPCWSTR szPropName,
|
|
SHORT& riData )
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
VARIANT vValue;
|
|
|
|
assert ( NULL != pIPropBag );
|
|
|
|
if ( NULL != pIPropBag ) {
|
|
|
|
VariantInit( &vValue );
|
|
vValue.vt = VT_I2;
|
|
|
|
hr = pIPropBag->Read(szPropName, &vValue, pIErrorLog );
|
|
|
|
if ( SUCCEEDED ( hr ) ) {
|
|
riData = vValue.iVal;
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
CyFromPropertyBag (
|
|
IPropertyBag* pIPropBag,
|
|
IErrorLog* pIErrorLog,
|
|
LPCWSTR szPropName,
|
|
CY& rcyData )
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
VARIANT vValue;
|
|
|
|
assert ( NULL != pIPropBag );
|
|
|
|
if ( NULL != pIPropBag ) {
|
|
|
|
VariantInit( &vValue );
|
|
vValue.vt = VT_CY;
|
|
vValue.cyVal.int64 = 0;
|
|
|
|
hr = pIPropBag->Read(szPropName, &vValue, pIErrorLog );
|
|
|
|
if ( SUCCEEDED( hr ) ) {
|
|
hr = VariantChangeType ( &vValue, &vValue, NULL, VT_CY );
|
|
|
|
if ( SUCCEEDED ( hr ) ) {
|
|
rcyData.int64 = vValue.cyVal.int64;
|
|
}
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
StringFromPropertyBag (
|
|
IPropertyBag* pIPropBag,
|
|
IErrorLog* pIErrorLog,
|
|
LPCWSTR szPropName,
|
|
LPWSTR szData,
|
|
INT& riCchBufLen )
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
VARIANT vValue;
|
|
INT iCchNewBufLen = 0;
|
|
LPWSTR szLocalData = NULL;
|
|
LPWSTR szTrans = NULL;
|
|
LPWSTR szScan = NULL;
|
|
|
|
assert ( NULL != pIPropBag );
|
|
|
|
if ( NULL != pIPropBag ) {
|
|
|
|
if ( NULL != szData ) {
|
|
*szData = L'\0';
|
|
}
|
|
|
|
VariantInit( &vValue );
|
|
vValue.vt = VT_BSTR;
|
|
vValue.bstrVal = NULL;
|
|
|
|
hr = pIPropBag->Read(szPropName, &vValue, pIErrorLog );
|
|
|
|
if ( SUCCEEDED(hr) && vValue.bstrVal ) {
|
|
|
|
iCchNewBufLen = SysStringLen(vValue.bstrVal) + 1;
|
|
|
|
if ( iCchNewBufLen > 1 ) {
|
|
|
|
if ( riCchBufLen >= iCchNewBufLen && NULL != szData ) {
|
|
|
|
//
|
|
// Translate HTML entities back to single characters.
|
|
//
|
|
szTrans = new WCHAR [iCchNewBufLen];
|
|
szLocalData = new WCHAR [iCchNewBufLen];
|
|
if ( NULL != szTrans && NULL != szLocalData ) {
|
|
|
|
StringCchCopy(szLocalData, riCchBufLen, vValue.bstrVal);
|
|
|
|
for( int i=0;g_htmlentities[i].szHTML != NULL;i++ ){
|
|
szScan = NULL;
|
|
|
|
while( szScan = wcsstr( szLocalData, g_htmlentities[i].szEntity ) ){
|
|
//
|
|
// Null the character at szScan, so that the string
|
|
// at the beginning of szLocalData will copied to szTrans.
|
|
// Then the NULL character is overwritten with the character
|
|
// represented by the specified HTML entity.
|
|
//
|
|
*szScan = L'\0';
|
|
|
|
StringCchCopy(szTrans, iCchNewBufLen, szLocalData);
|
|
StringCchCat(szTrans, iCchNewBufLen, g_htmlentities[i].szHTML);
|
|
|
|
//
|
|
// szScan is then set to one character past the HTML entity.
|
|
//
|
|
szScan += lstrlenW( g_htmlentities[i].szEntity);
|
|
//
|
|
// The rest of the original string is concatenated onto
|
|
// szTrans, and szLocalData replaced by the string at szTrans,
|
|
// so the next loop will start again at the beginning
|
|
// of the string.
|
|
//
|
|
StringCchCat(szTrans, iCchNewBufLen, szScan);
|
|
StringCchCopy(szLocalData, riCchBufLen, szTrans);
|
|
}
|
|
}
|
|
StringCchCopy(szData, riCchBufLen, szLocalData);
|
|
} else {
|
|
StringCchCopy(szData, riCchBufLen, vValue.bstrVal);
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
if ( NULL != szLocalData ) {
|
|
delete [] szLocalData;
|
|
}
|
|
|
|
if ( NULL != szTrans ) {
|
|
delete [] szTrans;
|
|
}
|
|
}
|
|
riCchBufLen = iCchNewBufLen;
|
|
} else {
|
|
riCchBufLen = 0;
|
|
}
|
|
}
|
|
VariantClear ( &vValue );
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
LLTimeFromPropertyBag (
|
|
IPropertyBag* pIPropBag,
|
|
IErrorLog* pIErrorLog,
|
|
LPCWSTR szPropName,
|
|
LONGLONG& rllData )
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
VARIANT vValue;
|
|
|
|
assert ( NULL != pIPropBag );
|
|
|
|
if ( NULL != pIPropBag ) {
|
|
|
|
VariantInit( &vValue );
|
|
vValue.vt = VT_DATE;
|
|
|
|
hr = pIPropBag->Read(szPropName, &vValue, pIErrorLog );
|
|
|
|
if ( SUCCEEDED(hr) ) {
|
|
if ( !VariantDateToLLTime ( vValue.date, &rllData ) ) {
|
|
hr = E_FAIL;
|
|
}
|
|
VariantClear( &vValue );
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
#endif // Property bag
|
|
|
|
LPWSTR
|
|
ResourceString (
|
|
UINT uID
|
|
)
|
|
{
|
|
|
|
static WCHAR aszBuffers[NUM_RESOURCE_STRING_BUFFERS][RESOURCE_STRING_BUF_LEN];
|
|
static INT iBuffIndex = 0;
|
|
|
|
// Use next buffer
|
|
if (++iBuffIndex >= NUM_RESOURCE_STRING_BUFFERS)
|
|
iBuffIndex = 0;
|
|
|
|
// Load and return string
|
|
if (LoadString(g_hInstance, uID, aszBuffers[iBuffIndex], RESOURCE_STRING_BUF_LEN))
|
|
return aszBuffers[iBuffIndex];
|
|
else
|
|
return MISSING_RESOURCE_STRING;
|
|
}
|
|
|
|
DWORD
|
|
FormatSystemMessage (
|
|
DWORD dwMessageId,
|
|
LPWSTR pszSystemMessage,
|
|
DWORD dwBufSize )
|
|
{
|
|
DWORD dwReturn = 0;
|
|
HINSTANCE hPdh = NULL;
|
|
DWORD dwFlags = FORMAT_MESSAGE_FROM_SYSTEM;
|
|
|
|
assert ( NULL != pszSystemMessage );
|
|
|
|
if ( NULL != pszSystemMessage ) {
|
|
pszSystemMessage[0] = L'\0';
|
|
|
|
hPdh = LoadLibrary( L"PDH.DLL") ;
|
|
|
|
if ( NULL != hPdh ) {
|
|
dwFlags |= FORMAT_MESSAGE_FROM_HMODULE;
|
|
}
|
|
|
|
dwReturn = ::FormatMessage (
|
|
dwFlags,
|
|
hPdh,
|
|
dwMessageId,
|
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
|
pszSystemMessage,
|
|
dwBufSize,
|
|
NULL );
|
|
|
|
if ( NULL != hPdh ) {
|
|
FreeLibrary( hPdh );
|
|
}
|
|
|
|
if ( L'\0' == pszSystemMessage[0] ) {
|
|
StringCchPrintf(pszSystemMessage, dwBufSize, L"0x%08lX", dwMessageId );
|
|
}
|
|
}
|
|
return dwReturn;
|
|
}
|
|
|
|
INT
|
|
GetNumSeparators (
|
|
LPWSTR& rpDecimal,
|
|
LPWSTR& rpThousand )
|
|
{
|
|
#define NUM_BUF_LEN 4
|
|
INT iLength;
|
|
|
|
static WCHAR szDecimal[NUM_BUF_LEN] = L".";
|
|
static WCHAR szThousand[NUM_BUF_LEN] = L",";
|
|
|
|
iLength = GetLocaleInfo (
|
|
LOCALE_USER_DEFAULT,
|
|
LOCALE_SDECIMAL,
|
|
szDecimal,
|
|
NUM_BUF_LEN );
|
|
|
|
if ( 0 != iLength ) {
|
|
iLength = GetLocaleInfo (
|
|
LOCALE_USER_DEFAULT,
|
|
LOCALE_STHOUSAND,
|
|
szThousand,
|
|
NUM_BUF_LEN );
|
|
|
|
}
|
|
|
|
rpDecimal = szDecimal;
|
|
rpThousand = szThousand;
|
|
|
|
return iLength;
|
|
}
|
|
|
|
LPWSTR
|
|
GetTimeSeparator ( void )
|
|
{
|
|
#define TIME_MARK_BUF_LEN 5
|
|
static INT iInitialized; // Initialized to 0
|
|
static WCHAR szTimeSeparator[TIME_MARK_BUF_LEN];
|
|
|
|
if ( 0 == iInitialized ) {
|
|
INT iLength;
|
|
|
|
iLength = GetLocaleInfo (
|
|
LOCALE_USER_DEFAULT,
|
|
LOCALE_STIME,
|
|
szTimeSeparator,
|
|
TIME_MARK_BUF_LEN );
|
|
|
|
// Default to colon for time separator
|
|
if ( '\0' == szTimeSeparator[0] ) {
|
|
StringCchCopy(szTimeSeparator, TIME_MARK_BUF_LEN, L":" );
|
|
}
|
|
|
|
iInitialized = 1;
|
|
}
|
|
|
|
assert ( L'\0' != szTimeSeparator[0] );
|
|
|
|
return szTimeSeparator;
|
|
}
|
|
|
|
BOOL
|
|
DisplayThousandsSeparator ( void )
|
|
{
|
|
long nErr;
|
|
HKEY hKey = NULL;
|
|
DWORD dwRegValue;
|
|
DWORD dwDataType;
|
|
DWORD dwDataSize;
|
|
DWORD dwDisposition;
|
|
|
|
static INT siInitialized; // Initialized to 0
|
|
static BOOL sbUseSeparator; // Initialized to 0 ( FALSE )
|
|
|
|
// check registry setting to see if thousands separator is enabled
|
|
if ( 0 == siInitialized ) {
|
|
nErr = RegOpenKey(
|
|
HKEY_CURRENT_USER,
|
|
L"Software\\Microsoft\\SystemMonitor",
|
|
&hKey );
|
|
|
|
if( ERROR_SUCCESS != nErr ) {
|
|
nErr = RegCreateKeyEx(
|
|
HKEY_CURRENT_USER,
|
|
L"Software\\Microsoft\\SystemMonitor",
|
|
0,
|
|
L"REG_DWORD",
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_ALL_ACCESS,
|
|
NULL,
|
|
&hKey,
|
|
&dwDisposition );
|
|
}
|
|
|
|
dwRegValue = 0;
|
|
if ( ERROR_SUCCESS == nErr ) {
|
|
|
|
dwDataSize = sizeof(DWORD);
|
|
nErr = RegQueryValueExW (
|
|
hKey,
|
|
L"DisplayThousandsSeparator",
|
|
NULL,
|
|
&dwDataType,
|
|
(LPBYTE) &dwRegValue,
|
|
(LPDWORD) &dwDataSize );
|
|
|
|
if ( ERROR_SUCCESS == nErr
|
|
&& REG_DWORD == dwDataType
|
|
&& sizeof(DWORD) == dwDataSize )
|
|
{
|
|
if ( 0 != dwRegValue ) {
|
|
sbUseSeparator = TRUE;
|
|
}
|
|
}
|
|
siInitialized = 1;
|
|
}
|
|
|
|
if ( NULL != hKey ) {
|
|
nErr = RegCloseKey( hKey );
|
|
}
|
|
}
|
|
|
|
return sbUseSeparator;
|
|
}
|
|
|
|
|
|
INT
|
|
FormatNumberInternal (
|
|
LPWSTR pNumOrig,
|
|
LPWSTR pNumFormatted,
|
|
INT cchars,
|
|
UINT uiPrecision,
|
|
UINT uiLeadingZero,
|
|
UINT uiGrouping,
|
|
UINT uiNegativeMode )
|
|
{
|
|
INT iLength = 0;
|
|
WCHAR* pszSrc;
|
|
|
|
static INT siInitialized; // Initialized to 0
|
|
static NUMBERFMT NumberFormat;
|
|
|
|
assert ( NULL != pNumOrig && NULL != pNumFormatted );
|
|
|
|
if ( NULL != pNumOrig && NULL != pNumFormatted ) {
|
|
|
|
iLength = 2;
|
|
|
|
NumberFormat.NumDigits = uiPrecision;
|
|
NumberFormat.LeadingZero = uiLeadingZero;
|
|
NumberFormat.NegativeOrder = uiNegativeMode;
|
|
|
|
if ( DisplayThousandsSeparator() ) {
|
|
NumberFormat.Grouping = uiGrouping;
|
|
} else {
|
|
NumberFormat.Grouping = 0;
|
|
}
|
|
|
|
if ( 0 == siInitialized ) {
|
|
GetNumSeparators (
|
|
NumberFormat.lpDecimalSep,
|
|
NumberFormat.lpThousandSep );
|
|
|
|
siInitialized = 1;
|
|
}
|
|
|
|
// Programming error if either pointer is NULL.
|
|
assert ( NULL != NumberFormat.lpDecimalSep );
|
|
assert ( NULL != NumberFormat.lpThousandSep );
|
|
|
|
// GetNumberFormat requires "." for decimal point.
|
|
if ( NumberFormat.lpDecimalSep != NULL) {
|
|
if (0 != lstrcmpi(NumberFormat.lpDecimalSep, L".") ) {
|
|
for ( pszSrc = pNumOrig; *pszSrc != L'\0'; pszSrc++) {
|
|
if ( *pszSrc == NumberFormat.lpDecimalSep[0] ) {
|
|
*pszSrc = L'.';
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
iLength = GetNumberFormat (
|
|
LOCALE_USER_DEFAULT,
|
|
0,
|
|
pNumOrig,
|
|
&NumberFormat,
|
|
pNumFormatted,
|
|
cchars );
|
|
}
|
|
}
|
|
// Return 0 on failure, number of chars on success.
|
|
// GetNumberFormat includes the null terminator in the length.
|
|
return iLength;
|
|
}
|
|
|
|
INT
|
|
FormatHex (
|
|
double dValue,
|
|
LPWSTR pNumFormatted,
|
|
BOOL bLargeFormat
|
|
)
|
|
{
|
|
INT iLength = 0;
|
|
WCHAR szPreFormat[24];
|
|
|
|
assert ( NULL != pNumFormatted );
|
|
|
|
if ( NULL != pNumFormatted ) {
|
|
iLength = 8;
|
|
// Localization doesn't handle padding blanks.
|
|
StringCchPrintf( szPreFormat,
|
|
24,
|
|
(bLargeFormat ? szLargeHexFormat : szHexFormat ),
|
|
(ULONG)dValue );
|
|
|
|
StringCchCopy(pNumFormatted, MAX_VALUE_LEN, szPreFormat);
|
|
}
|
|
|
|
return iLength;
|
|
}
|
|
|
|
INT
|
|
FormatNumber (
|
|
double dValue,
|
|
LPWSTR pNumFormatted,
|
|
INT ccharsFormatted,
|
|
UINT /* uiMinimumWidth */,
|
|
UINT uiPrecision )
|
|
{
|
|
INT iLength = 0;
|
|
INT iLeadingZero = FALSE;
|
|
WCHAR szPreFormat[MAX_VALUE_LEN];
|
|
|
|
assert ( NULL != pNumFormatted );
|
|
// This method enforces number format commonality
|
|
if ( NULL != pNumFormatted ) {
|
|
|
|
assert ( 8 > uiPrecision );
|
|
|
|
// Localization doesn't handle padding blanks.
|
|
StringCchPrintf( szPreFormat,
|
|
MAX_VALUE_LEN,
|
|
L"%0.7f", // assumes 7 >= uiPrecision
|
|
dValue );
|
|
|
|
if ( 1 > dValue )
|
|
iLeadingZero = TRUE;
|
|
|
|
iLength = FormatNumberInternal (
|
|
szPreFormat,
|
|
pNumFormatted,
|
|
ccharsFormatted,
|
|
uiPrecision,
|
|
iLeadingZero, // Leading 0
|
|
3, // Grouping
|
|
1 ); // Negative format
|
|
}
|
|
|
|
// Return 0 on failure, number of chars on success.
|
|
// GetNumberFormat includes the null terminator in the length.
|
|
return iLength;
|
|
}
|
|
|
|
INT
|
|
FormatScientific (
|
|
double dValue,
|
|
LPWSTR pszNumFormatted,
|
|
INT ccharsFormatted,
|
|
UINT /* uiMinimumWidth */,
|
|
UINT uiPrecision )
|
|
{
|
|
INT iLength = 0;
|
|
WCHAR szPreFormat[24];
|
|
WCHAR szPreFormNumber[24];
|
|
WCHAR *pche;
|
|
INT iPreLen;
|
|
INT iPostLen;
|
|
INT iLeadingZero = FALSE;
|
|
|
|
assert ( NULL != pszNumFormatted );
|
|
// This method enforces number format commonality
|
|
if ( NULL != pszNumFormatted ) {
|
|
|
|
assert ( 8 > uiPrecision );
|
|
assert ( 32 > ccharsFormatted );
|
|
|
|
// Localization doesn't handle padding blanks.
|
|
StringCchPrintf( szPreFormat,
|
|
24,
|
|
L"%0.8e", // assumes 8 >= uiPrecision
|
|
dValue );
|
|
|
|
pche = wcsrchr(szPreFormat, L'e');
|
|
if (pche != NULL) {
|
|
iPreLen = (INT)((UINT_PTR)pche - (UINT_PTR)szPreFormat); // Number of bytes
|
|
iPreLen /= sizeof (WCHAR); // Number of characters
|
|
iPostLen = lstrlen(pche) + 1;
|
|
|
|
StringCchCopyN ( szPreFormNumber, 24, szPreFormat, iPreLen );
|
|
|
|
if ( 1 > dValue ) {
|
|
iLeadingZero = TRUE;
|
|
}
|
|
|
|
iLength = FormatNumberInternal (
|
|
szPreFormNumber,
|
|
pszNumFormatted,
|
|
ccharsFormatted,
|
|
uiPrecision,
|
|
iLeadingZero, // Leading 0
|
|
0, // Grouping
|
|
1 ); // Negative format
|
|
|
|
if( ( iLength + iPostLen ) < ccharsFormatted ) {
|
|
StringCchCopy(pszNumFormatted, ccharsFormatted, pche );
|
|
iLength += iPostLen;
|
|
}
|
|
}
|
|
}
|
|
// Return 0 on failure, number of chars on success.
|
|
// GetNumberFormat includes the null terminator in the length.
|
|
return iLength;
|
|
}
|
|
|
|
void
|
|
FormatDateTime (
|
|
LONGLONG llTime,
|
|
LPWSTR pszDate,
|
|
LPWSTR pszTime )
|
|
{
|
|
SYSTEMTIME SystemTime;
|
|
|
|
assert ( NULL != pszDate && NULL != pszTime );
|
|
if ( NULL != pszDate
|
|
&& NULL != pszTime ) {
|
|
|
|
FileTimeToSystemTime((FILETIME*)&llTime, &SystemTime);
|
|
GetTimeFormat (LOCALE_USER_DEFAULT, 0, &SystemTime, NULL, pszTime, MAX_TIME_CHARS) ;
|
|
GetDateFormat (LOCALE_USER_DEFAULT, DATE_SHORTDATE, &SystemTime, NULL, pszDate, MAX_DATE_CHARS) ;
|
|
}
|
|
}
|
|
|
|
// CreateTargetDC is based on AtlCreateTargetDC.
|
|
HDC
|
|
CreateTargetDC(HDC hdc, DVTARGETDEVICE* ptd)
|
|
{
|
|
USES_CONVERSION
|
|
|
|
// cases hdc, ptd, hdc is metafile, hic
|
|
// NULL, NULL, n/a, Display
|
|
// NULL, !NULL, n/a, ptd
|
|
// !NULL, NULL, FALSE, hdc
|
|
// !NULL, NULL, TRUE, display
|
|
// !NULL, !NULL, FALSE, ptd
|
|
// !NULL, !NULL, TRUE, ptd
|
|
|
|
if ( NULL != ptd ) {
|
|
LPDEVMODE lpDevMode;
|
|
LPOLESTR lpszDriverName;
|
|
LPOLESTR lpszDeviceName;
|
|
LPOLESTR lpszPortName;
|
|
|
|
if (ptd->tdExtDevmodeOffset == 0)
|
|
lpDevMode = NULL;
|
|
else
|
|
lpDevMode = (LPDEVMODE) ((LPSTR)ptd + ptd->tdExtDevmodeOffset);
|
|
|
|
lpszDriverName = (LPOLESTR)((BYTE*)ptd + ptd->tdDriverNameOffset);
|
|
lpszDeviceName = (LPOLESTR)((BYTE*)ptd + ptd->tdDeviceNameOffset);
|
|
lpszPortName = (LPOLESTR)((BYTE*)ptd + ptd->tdPortNameOffset);
|
|
|
|
return ::CreateDC(lpszDriverName, lpszDeviceName,
|
|
lpszPortName, lpDevMode);
|
|
} else if ( NULL == hdc ) {
|
|
return ::CreateDC(L"DISPLAY", NULL, NULL, NULL);
|
|
} else if ( GetDeviceCaps(hdc, TECHNOLOGY) == DT_METAFILE ) {
|
|
return ::CreateDC(L"DISPLAY", NULL, NULL, NULL);
|
|
} else
|
|
return hdc;
|
|
}
|
|
|
|
/***********************************************************************
|
|
|
|
FUNCTION : HitTestLine
|
|
|
|
PARAMETERS : POINT pt0 - endpoint for line segment
|
|
POINT pt1 - endpoint for line segment
|
|
POINTS ptMouse - mouse coordinates of hit
|
|
INT nWidth - width of pen
|
|
|
|
PURPOSE : test if mouse click occurred on line segment while
|
|
adjusting for the width of line
|
|
|
|
CALLS : GetDC
|
|
ReleaseDC
|
|
SetGraphicsMode
|
|
SetWorldTransform
|
|
|
|
MESSAGES : none
|
|
|
|
RETURNS : BOOL - TRUE if the point was within the width of the
|
|
pen about the line
|
|
FALSE if the point lies outside of the width
|
|
of the pen about the line
|
|
|
|
COMMENTS : uses VECTOR2D.DLL
|
|
|
|
HISTORY : 9/20/93 - created - denniscr
|
|
|
|
************************************************************************/
|
|
|
|
BOOL HitTestLine( POINT pt0, POINT pt1, POINTS ptMouse, INT nWidth )
|
|
{
|
|
POINT PtM;
|
|
VECTOR2D tt0, tt1;
|
|
double dist;
|
|
INT nHalfWidth;
|
|
|
|
nHalfWidth = (nWidth/2 < 1) ? 1 : nWidth/2;
|
|
|
|
//
|
|
//convert the line into a vector
|
|
//
|
|
|
|
POINTS2VECTOR2D(pt0, pt1, tt0);
|
|
//
|
|
//convert the mouse points (short) into POINT (long)
|
|
//
|
|
|
|
MPOINT2POINT(ptMouse ,PtM);
|
|
POINTS2VECTOR2D(pt0, PtM, tt1);
|
|
|
|
//
|
|
//if the mouse click is past the endpoints of
|
|
//a line segment return FALSE
|
|
//
|
|
|
|
if (pt0.x <= pt1.x)
|
|
{
|
|
if (PtM.x < pt0.x || PtM.x > pt1.x)
|
|
return (FALSE);
|
|
}
|
|
else
|
|
{
|
|
if (PtM.x > pt0.x || PtM.x < pt1.x)
|
|
return (FALSE);
|
|
}
|
|
//
|
|
//this is the call to the function that does the work
|
|
//of obtaining the distance of the point to the line
|
|
//
|
|
dist = vDistFromPointToLine(&pt0, &pt1, &PtM);
|
|
|
|
//
|
|
//TRUE if the distance is within the width of the pen about the
|
|
//line otherwise FALSE
|
|
//
|
|
return (dist >= -nHalfWidth && dist <= nHalfWidth);
|
|
}
|
|
|
|
/***********************************************************************
|
|
|
|
vSubtractVectors
|
|
|
|
The vSubtractVectors function subtracts the components of a two
|
|
dimensional vector from another. The resultant vector
|
|
c = (a1 - b1, a2 - b2).
|
|
|
|
Parameters
|
|
|
|
v0 A pointer to a VECTOR2D structure containing the components
|
|
of the first two dimensional vector.
|
|
v1 A pointer to a VECTOR2D structure containing the components
|
|
of the second two dimensional vector.
|
|
vt A pointer to a VECTOR2D structure in which the components
|
|
of the two dimensional vector obtained from the subtraction of
|
|
the first two are placed.
|
|
|
|
Return value
|
|
|
|
A pointer to a VECTOR2D structure containing the new vector obtained
|
|
from the subtraction of the first two parameters.
|
|
|
|
HISTORY : - created - denniscr
|
|
|
|
************************************************************************/
|
|
|
|
PVECTOR2D vSubtractVectors(PVECTOR2D v0, PVECTOR2D v1, PVECTOR2D v)
|
|
{
|
|
if (v0 == NULL || v1 == NULL)
|
|
v = (PVECTOR2D)NULL;
|
|
else
|
|
{
|
|
v->x = v0->x - v1->x;
|
|
v->y = v0->y - v1->y;
|
|
}
|
|
return(v);
|
|
}
|
|
|
|
/***********************************************************************
|
|
|
|
vVectorSquared
|
|
|
|
The vVectorSquared function squares each of the components of the
|
|
vector and adds then together to produce the squared value of the
|
|
vector. SquaredValue = a.x * a.x + a.y * a.y.
|
|
|
|
Parameters
|
|
|
|
v0 A pointer to a VECTOR2D structure containing the vector upon which
|
|
to determine the squared value.
|
|
|
|
Return value
|
|
|
|
A double value which is the squared value of the vector.
|
|
|
|
HISTORY : - created - denniscr
|
|
|
|
************************************************************************/
|
|
|
|
double vVectorSquared(PVECTOR2D v0)
|
|
{
|
|
double dSqLen;
|
|
|
|
if (v0 == NULL)
|
|
dSqLen = 0.0;
|
|
else
|
|
dSqLen = (double)(v0->x * v0->x) + (double)(v0->y * v0->y);
|
|
return (dSqLen);
|
|
}
|
|
|
|
/***********************************************************************
|
|
|
|
vVectorMagnitude
|
|
|
|
The vVectorMagnitude function determines the length of a vector by
|
|
summing the squares of each of the components of the vector. The
|
|
magnitude is equal to a.x * a.x + a.y * a.y.
|
|
|
|
Parameters
|
|
|
|
v0 A pointer to a VECTOR2D structure containing the vector upon
|
|
which to determine the magnitude.
|
|
|
|
Return value
|
|
|
|
A double value which is the magnitude of the vector.
|
|
|
|
HISTORY : - created - denniscr
|
|
|
|
************************************************************************/
|
|
|
|
double vVectorMagnitude(PVECTOR2D v0)
|
|
{
|
|
double dMagnitude;
|
|
|
|
if (v0 == NULL)
|
|
dMagnitude = 0.0;
|
|
else
|
|
dMagnitude = sqrt(vVectorSquared(v0));
|
|
return (dMagnitude);
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
vDotProduct
|
|
|
|
The function vDotProduct computes the dot product of two vectors. The
|
|
dot product of two vectors is the sum of the products of the components
|
|
of the vectors ie: for the vectors a and b, dotprod = a1 * a2 + b1 * b2.
|
|
|
|
Parameters
|
|
|
|
v0 A pointer to a VECTOR2D structure containing the first vector used
|
|
for obtaining a dot product.
|
|
v1 A pointer to a VECTOR2D structure containing the second vector used
|
|
for obtaining a dot product.
|
|
|
|
Return value
|
|
|
|
A double value containing the scalar dot product value.
|
|
|
|
HISTORY : - created - denniscr
|
|
|
|
************************************************************************/
|
|
|
|
double vDotProduct(PVECTOR2D v0, PVECTOR2D v1)
|
|
{
|
|
return ((v0 == NULL || v1 == NULL) ? 0.0
|
|
: (v0->x * v1->x) + (v0->y * v1->y));
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
vProjectAndResolve
|
|
|
|
The function vProjectAndResolve resolves a vector into two vector
|
|
components. The first is a vector obtained by projecting vector v0 onto
|
|
v1. The second is a vector that is perpendicular (normal) to the
|
|
projected vector. It extends from the head of the projected vector
|
|
v1 to the head of the original vector v0.
|
|
|
|
Parameters
|
|
|
|
v0 A pointer to a VECTOR2D structure containing the first vector
|
|
v1 A pointer to a VECTOR2D structure containing the second vector
|
|
ppProj A pointer to a PROJECTION structure containing the resolved
|
|
vectors and their lengths.
|
|
|
|
Return value
|
|
|
|
void.
|
|
|
|
HISTORY : - created - denniscr
|
|
|
|
************************************************************************/
|
|
|
|
void vProjectAndResolve(PVECTOR2D v0, PVECTOR2D v1, PPROJECTION ppProj)
|
|
{
|
|
VECTOR2D ttProjection, ttOrthogonal;
|
|
double vDotProd;
|
|
double proj1 = 0.0;
|
|
//
|
|
//obtain projection vector
|
|
//
|
|
//c = a * b
|
|
// ----- b
|
|
// |b|^2
|
|
//
|
|
|
|
ttOrthogonal.x = 0.0;
|
|
ttOrthogonal.y = 0.0;
|
|
vDotProd = vDotProduct(v1, v1);
|
|
|
|
if ( 0.0 != vDotProd ) {
|
|
proj1 = vDotProduct(v0, v1)/vDotProd;
|
|
}
|
|
|
|
ttProjection.x = v1->x * proj1;
|
|
ttProjection.y = v1->y * proj1;
|
|
//
|
|
//obtain perpendicular projection : e = a - c
|
|
//
|
|
vSubtractVectors(v0, &ttProjection, &ttOrthogonal);
|
|
//
|
|
//fill PROJECTION structure with appropriate values
|
|
//
|
|
ppProj->LenProjection = vVectorMagnitude(&ttProjection);
|
|
ppProj->LenPerpProjection = vVectorMagnitude(&ttOrthogonal);
|
|
|
|
ppProj->ttProjection.x = ttProjection.x;
|
|
ppProj->ttProjection.y = ttProjection.y;
|
|
ppProj->ttPerpProjection.x = ttOrthogonal.x;
|
|
ppProj->ttPerpProjection.y = ttOrthogonal.y;
|
|
}
|
|
|
|
/***********************************************************************
|
|
|
|
vDistFromPointToLine
|
|
|
|
The function vDistFromPointToLine computes the distance from the point
|
|
ptTest to the line defined by endpoints pt0 and pt1. This is done by
|
|
resolving the the vector from pt0 to ptTest into its components. The
|
|
length of the component vector that is attached to the head of the
|
|
vector from pt0 to ptTest is the distance of ptTest from the line.
|
|
|
|
Parameters
|
|
|
|
pt0 A pointer to a POINT structure containing the first endpoint of the
|
|
line.
|
|
pt1 A pointer to a POINT structure containing the second endpoint of the
|
|
line.
|
|
ptTest A pointer to a POINT structure containing the point for which the
|
|
distance from the line is to be computed.
|
|
|
|
Return value
|
|
|
|
A double value that contains the distance of ptTest to the line defined
|
|
by the endpoints pt0 and pt1.
|
|
|
|
HISTORY : - created - denniscr
|
|
************************************************************************/
|
|
|
|
double vDistFromPointToLine(LPPOINT pt0, LPPOINT pt1, LPPOINT ptTest)
|
|
{
|
|
VECTOR2D ttLine, ttTest;
|
|
PROJECTION pProjection;
|
|
|
|
POINTS2VECTOR2D(*pt0, *pt1, ttLine);
|
|
POINTS2VECTOR2D(*pt0, *ptTest, ttTest);
|
|
|
|
vProjectAndResolve(&ttTest, &ttLine, &pProjection);
|
|
|
|
return(pProjection.LenPerpProjection);
|
|
}
|
|
|
|
|
|
BOOL
|
|
FileRead (
|
|
HANDLE hFile,
|
|
void* lpMemory,
|
|
DWORD nAmtToRead)
|
|
{
|
|
BOOL bSuccess = FALSE;
|
|
DWORD nAmtRead = 0;
|
|
|
|
assert ( NULL != hFile );
|
|
assert ( NULL != lpMemory );
|
|
|
|
if ( NULL != hFile
|
|
&& NULL != lpMemory ) {
|
|
bSuccess = ReadFile (hFile, lpMemory, nAmtToRead, &nAmtRead, NULL) ;
|
|
}
|
|
return (bSuccess && (nAmtRead == nAmtToRead)) ;
|
|
} // FileRead
|
|
|
|
|
|
BOOL
|
|
FileWrite (
|
|
HANDLE hFile,
|
|
void* lpMemory,
|
|
DWORD nAmtToWrite)
|
|
{
|
|
BOOL bSuccess = FALSE;
|
|
DWORD nAmtWritten = 0;
|
|
DWORD dwFileSizeLow, dwFileSizeHigh;
|
|
LONGLONG llResultSize;
|
|
|
|
if ( NULL != hFile
|
|
&& NULL != lpMemory ) {
|
|
|
|
dwFileSizeLow = GetFileSize (hFile, &dwFileSizeHigh);
|
|
// limit file size to 2GB
|
|
|
|
if (dwFileSizeHigh > 0) {
|
|
SetLastError (ERROR_WRITE_FAULT);
|
|
bSuccess = FALSE;
|
|
} else {
|
|
// note that the error return of this function is 0xFFFFFFFF
|
|
// since that is > the file size limit, this will be interpreted
|
|
// as an error (a size error) so it's accounted for in the following
|
|
// test.
|
|
llResultSize = dwFileSizeLow + nAmtToWrite;
|
|
if (llResultSize >= 0x80000000) {
|
|
SetLastError (ERROR_WRITE_FAULT);
|
|
bSuccess = FALSE;
|
|
} else {
|
|
// write buffer to file
|
|
bSuccess = WriteFile (hFile, lpMemory, nAmtToWrite, &nAmtWritten, NULL) ;
|
|
if (bSuccess)
|
|
bSuccess = (nAmtWritten == nAmtToWrite ? TRUE : FALSE);
|
|
if ( !bSuccess ) {
|
|
SetLastError (ERROR_WRITE_FAULT);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
assert ( FALSE );
|
|
SetLastError (ERROR_INVALID_PARAMETER);
|
|
}
|
|
|
|
return (bSuccess) ;
|
|
|
|
} // FileWrite
|
|
|
|
// This routine extract the filename portion from a given full-path filename
|
|
LPWSTR
|
|
ExtractFileName ( LPWSTR pFileSpec )
|
|
{
|
|
LPWSTR pFileName = NULL ;
|
|
WCHAR DIRECTORY_DELIMITER1 = TEXT('\\') ;
|
|
WCHAR DIRECTORY_DELIMITER2 = TEXT(':') ;
|
|
|
|
assert ( NULL != pFileSpec );
|
|
if ( pFileSpec ) {
|
|
pFileName = pFileSpec + lstrlen (pFileSpec) ;
|
|
|
|
while (*pFileName != DIRECTORY_DELIMITER1 &&
|
|
*pFileName != DIRECTORY_DELIMITER2) {
|
|
if (pFileName == pFileSpec) {
|
|
// done when no directory delimiter is found
|
|
break ;
|
|
}
|
|
pFileName-- ;
|
|
}
|
|
|
|
if (*pFileName == DIRECTORY_DELIMITER1
|
|
|| *pFileName == DIRECTORY_DELIMITER2) {
|
|
|
|
// directory delimiter found, point the
|
|
// filename right after it
|
|
pFileName++ ;
|
|
}
|
|
}
|
|
return pFileName ;
|
|
} // ExtractFileName
|
|
|
|
// CWaitCursor class
|
|
|
|
CWaitCursor::CWaitCursor()
|
|
: m_hcurWaitCursorRestore ( NULL )
|
|
{
|
|
DoWaitCursor(1);
|
|
}
|
|
|
|
CWaitCursor::~CWaitCursor()
|
|
{
|
|
DoWaitCursor(-1);
|
|
}
|
|
|
|
void
|
|
CWaitCursor::DoWaitCursor(INT nCode)
|
|
{
|
|
// 1=> begin, -1=> end
|
|
assert(nCode == 1 || nCode == -1);
|
|
|
|
if ( 1 == nCode )
|
|
{
|
|
m_hcurWaitCursorRestore = SetHourglassCursor();
|
|
} else {
|
|
if ( NULL != m_hcurWaitCursorRestore ) {
|
|
SetCursor(m_hcurWaitCursorRestore);
|
|
} else {
|
|
SetArrowCursor();
|
|
}
|
|
}
|
|
}
|
|
|
|
DWORD
|
|
LoadDefaultLogFileFolder(
|
|
LPWSTR szFolder,
|
|
INT* piBufLen )
|
|
{
|
|
DWORD dwStatus = ERROR_SUCCESS;
|
|
HKEY hKey = NULL;
|
|
DWORD dwDataType;
|
|
DWORD dwBufferSize = 0;
|
|
WCHAR* szNewStringBuffer = NULL;
|
|
|
|
assert ( NULL != szFolder );
|
|
assert ( NULL != piBufLen );
|
|
|
|
if ( NULL != szFolder
|
|
&& NULL != piBufLen ) {
|
|
|
|
dwStatus = RegOpenKey (
|
|
HKEY_LOCAL_MACHINE,
|
|
L"System\\CurrentControlSet\\Services\\SysmonLog",
|
|
&hKey );
|
|
|
|
if ( ERROR_SUCCESS == dwStatus ) {
|
|
|
|
dwDataType = 0;
|
|
|
|
// Determine the size of the required buffer.
|
|
dwStatus = RegQueryValueExW (
|
|
hKey,
|
|
L"DefaultLogFileFolder",
|
|
NULL,
|
|
&dwDataType,
|
|
NULL,
|
|
&dwBufferSize);
|
|
|
|
if (dwStatus == ERROR_SUCCESS) {
|
|
if (dwBufferSize > 0) {
|
|
|
|
szNewStringBuffer = new WCHAR[dwBufferSize / sizeof(WCHAR) ];
|
|
if ( NULL != szNewStringBuffer ) {
|
|
*szNewStringBuffer = L'\0';
|
|
|
|
dwStatus = RegQueryValueEx(
|
|
hKey,
|
|
L"DefaultLogFileFolder",
|
|
NULL,
|
|
&dwDataType,
|
|
(LPBYTE) szNewStringBuffer,
|
|
(LPDWORD) &dwBufferSize );
|
|
|
|
} else {
|
|
dwStatus = ERROR_OUTOFMEMORY;
|
|
}
|
|
} else {
|
|
dwStatus = ERROR_NO_DATA;
|
|
}
|
|
}
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
if (dwStatus == ERROR_SUCCESS) {
|
|
if ( *piBufLen >= (INT)(dwBufferSize / sizeof(WCHAR)) ) {
|
|
StringCchCopy(szFolder, *piBufLen, szNewStringBuffer );
|
|
} else {
|
|
dwStatus = ERROR_INSUFFICIENT_BUFFER;
|
|
}
|
|
*piBufLen = dwBufferSize / sizeof(WCHAR);
|
|
}
|
|
if ( NULL != szNewStringBuffer )
|
|
delete [] szNewStringBuffer;
|
|
} else {
|
|
dwStatus = ERROR_INVALID_PARAMETER;
|
|
}
|
|
return dwStatus;
|
|
}
|
|
|
|
|
|
BOOL
|
|
AreSameCounterPath (
|
|
PPDH_COUNTER_PATH_ELEMENTS pFirst,
|
|
PPDH_COUNTER_PATH_ELEMENTS pSecond )
|
|
{
|
|
BOOL bSame = FALSE;
|
|
|
|
assert ( NULL != pFirst && NULL != pSecond );
|
|
|
|
if ( NULL != pFirst && NULL != pSecond ) {
|
|
|
|
if ( 0 == lstrcmpi ( pFirst->szMachineName, pSecond->szMachineName ) ) {
|
|
if ( 0 == lstrcmpi ( pFirst->szObjectName, pSecond->szObjectName ) ) {
|
|
if ( 0 == lstrcmpi ( pFirst->szInstanceName, pSecond->szInstanceName ) ) {
|
|
if ( 0 == lstrcmpi ( pFirst->szParentInstance, pSecond->szParentInstance ) ) {
|
|
if ( pFirst->dwInstanceIndex == pSecond->dwInstanceIndex ) {
|
|
if ( 0 == lstrcmpi ( pFirst->szCounterName, pSecond->szCounterName ) ) {
|
|
bSame = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return bSame;
|
|
};
|
|
|
|
BOOL
|
|
DisplaySingleLogSampleValue ( void )
|
|
{
|
|
long nErr;
|
|
HKEY hKey = NULL;
|
|
DWORD dwRegValue;
|
|
DWORD dwDataType;
|
|
DWORD dwDataSize;
|
|
DWORD dwDisposition;
|
|
|
|
static INT siInitialized; // Initialized to 0
|
|
static BOOL sbSingleValue; // Initialized to 0 ( FALSE )
|
|
|
|
// check registry setting to see if thousands separator is enabled
|
|
if ( 0 == siInitialized ) {
|
|
nErr = RegOpenKey(
|
|
HKEY_CURRENT_USER,
|
|
L"Software\\Microsoft\\SystemMonitor",
|
|
&hKey );
|
|
|
|
if( ERROR_SUCCESS != nErr ) {
|
|
nErr = RegCreateKeyEx(
|
|
HKEY_CURRENT_USER,
|
|
L"Software\\Microsoft\\SystemMonitor",
|
|
0,
|
|
L"REG_DWORD",
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_ALL_ACCESS,
|
|
NULL,
|
|
&hKey,
|
|
&dwDisposition );
|
|
}
|
|
|
|
dwRegValue = 0;
|
|
if ( ERROR_SUCCESS == nErr ) {
|
|
|
|
dwDataSize = sizeof(DWORD);
|
|
nErr = RegQueryValueExW (
|
|
hKey,
|
|
L"DisplaySingleLogSampleValue",
|
|
NULL,
|
|
&dwDataType,
|
|
(LPBYTE) &dwRegValue,
|
|
(LPDWORD) &dwDataSize );
|
|
|
|
if ( ERROR_SUCCESS == nErr
|
|
&& REG_DWORD == dwDataType
|
|
&& sizeof(DWORD) == dwDataSize )
|
|
{
|
|
if ( 0 != dwRegValue ) {
|
|
sbSingleValue = TRUE;
|
|
}
|
|
}
|
|
siInitialized = 1;
|
|
}
|
|
|
|
if ( NULL != hKey ) {
|
|
nErr = RegCloseKey( hKey );
|
|
}
|
|
}
|
|
|
|
return sbSingleValue;
|
|
}
|
|
|
|
DWORD
|
|
FormatSqlDataSourceName (
|
|
LPCWSTR szSqlDsn,
|
|
LPCWSTR szSqlLogSetName,
|
|
LPWSTR szSqlDataSourceName,
|
|
ULONG* pulBufLen )
|
|
{
|
|
|
|
DWORD dwStatus = ERROR_SUCCESS;
|
|
ULONG ulNameLen;
|
|
|
|
if ( NULL != pulBufLen ) {
|
|
ulNameLen = lstrlen (szSqlDsn)
|
|
+ lstrlen(szSqlLogSetName)
|
|
+ 5 // SQL:<DSN>!<LOGSET>
|
|
+ 2; // 2 NULL characters at the end;
|
|
|
|
if ( ulNameLen <= *pulBufLen ) {
|
|
if ( NULL != szSqlDataSourceName ) {
|
|
StringCchPrintf( szSqlDataSourceName,
|
|
*pulBufLen,
|
|
cszSqlDataSourceFormat,
|
|
szSqlDsn,
|
|
szSqlLogSetName );
|
|
}
|
|
} else if ( NULL != szSqlDataSourceName ) {
|
|
dwStatus = ERROR_MORE_DATA;
|
|
}
|
|
*pulBufLen = ulNameLen;
|
|
} else {
|
|
dwStatus = ERROR_INVALID_PARAMETER;
|
|
assert ( FALSE );
|
|
}
|
|
return dwStatus;
|
|
}
|
|
|
|
|
|
DWORD
|
|
DisplayDataSourceError (
|
|
HWND hwndOwner,
|
|
DWORD dwErrorStatus,
|
|
INT iDataSourceType,
|
|
LPCWSTR szLogFileName,
|
|
LPCWSTR szSqlDsn,
|
|
LPCWSTR szSqlLogSetName )
|
|
{
|
|
DWORD dwStatus = ERROR_SUCCESS;
|
|
|
|
LPWSTR szMessage = NULL;
|
|
LPWSTR szDataSource = NULL;
|
|
ULONG ulMsgBufLen = 0;
|
|
WCHAR szSystemMessage[MAX_PATH];
|
|
|
|
// todo: Alloc message buffers
|
|
|
|
if ( sysmonLogFiles == iDataSourceType ) {
|
|
if ( NULL != szLogFileName ) {
|
|
ulMsgBufLen = lstrlen ( szLogFileName ) +1;
|
|
szDataSource = new WCHAR [ulMsgBufLen];
|
|
if ( NULL != szDataSource ) {
|
|
StringCchCopy(szDataSource, ulMsgBufLen, szLogFileName );
|
|
} else {
|
|
dwStatus = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
} else {
|
|
assert ( FALSE );
|
|
dwStatus = ERROR_INVALID_PARAMETER;
|
|
}
|
|
} else if ( sysmonSqlLog == iDataSourceType ){
|
|
if ( NULL != szSqlDsn && NULL != szSqlLogSetName ) {
|
|
|
|
FormatSqlDataSourceName (
|
|
szSqlDsn,
|
|
szSqlLogSetName,
|
|
NULL,
|
|
&ulMsgBufLen );
|
|
szDataSource = new WCHAR [ulMsgBufLen];
|
|
if ( NULL != szDataSource ) {
|
|
FormatSqlDataSourceName (
|
|
szSqlDsn,
|
|
szSqlLogSetName,
|
|
(LPWSTR)szDataSource,
|
|
&ulMsgBufLen );
|
|
|
|
// todo: check status
|
|
} else {
|
|
dwStatus = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
} else {
|
|
assert ( FALSE );
|
|
dwStatus = ERROR_INVALID_PARAMETER;
|
|
}
|
|
} else {
|
|
assert ( FALSE );
|
|
dwStatus = ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
if ( ERROR_SUCCESS == dwStatus ) {
|
|
ulMsgBufLen += RESOURCE_STRING_BUF_LEN;
|
|
ulMsgBufLen += MAX_PATH;
|
|
szMessage = new WCHAR [ulMsgBufLen];
|
|
if ( NULL != szMessage ) {
|
|
if ( SMON_STATUS_TOO_FEW_SAMPLES == dwErrorStatus ) {
|
|
StringCchPrintf(szMessage,
|
|
ulMsgBufLen,
|
|
ResourceString(IDS_TOO_FEW_SAMPLES_ERR),
|
|
szDataSource );
|
|
} else if ( SMON_STATUS_LOG_FILE_SIZE_LIMIT == dwErrorStatus ) {
|
|
StringCchPrintf(szMessage,
|
|
ulMsgBufLen,
|
|
ResourceString(IDS_LOG_FILE_TOO_LARGE_ERR),
|
|
szDataSource );
|
|
} else {
|
|
StringCchPrintf(szMessage,
|
|
ulMsgBufLen,
|
|
ResourceString(IDS_BADDATASOURCE_ERR),
|
|
szDataSource );
|
|
FormatSystemMessage ( dwErrorStatus, szSystemMessage, MAX_PATH - 1 );
|
|
StringCchCat(szMessage, ulMsgBufLen, szSystemMessage );
|
|
}
|
|
|
|
MessageBox(
|
|
hwndOwner,
|
|
szMessage,
|
|
ResourceString(IDS_APP_NAME),
|
|
MB_OK | MB_ICONEXCLAMATION);
|
|
}
|
|
}
|
|
|
|
if ( NULL != szDataSource ) {
|
|
delete [] szDataSource;
|
|
}
|
|
|
|
if ( NULL != szMessage ) {
|
|
delete [] szMessage;
|
|
}
|
|
|
|
return dwStatus;
|
|
}
|