#include "pch.h"
#include "..\Inc\TCLib.h"
#if _MSC_VER >= 1310
class __declspec(uuid("0002e005-0000-0000-c000-000000000046")) StdComponentCategoriesMgr;
#endif
#ifdef _DEBUG
void _cdecl TCTrace(LPCTSTR lpszFormat, ...)
{
va_list args;
va_start(args, lpszFormat);
int nBuf;
TCHAR szBuffer[512];
nBuf = _vstprintf(szBuffer, lpszFormat, args);
assert(nBuf < sizeof(szBuffer));
USES_CONVERSION;
ZDebugOutputImpl(T2CA(szBuffer));
va_end(args);
}
#endif HRESULT RegisterComponentCategory(REFGUID catid, LPCOLESTR pszDesc)
{
ICatRegisterPtr pcr;
HRESULT hr = pcr.CreateInstance(__uuidof(StdComponentCategoriesMgr));
if (FAILED(hr))
{
return S_OK;
}
const LANGID langid = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
const LCID lcid = MAKELCID(langid, SORT_DEFAULT);
CATEGORYINFO catinfo;
catinfo.catid = catid;
catinfo.lcid = lcid;
wcscpy(catinfo.szDescription, pszDesc);
return pcr->RegisterCategories(1, &catinfo);
}
HRESULT RegisterComponentCategory(LPCOLESTR pszCLSID, LPCOLESTR pszDesc)
{
GUID catid;
HRESULT hr = CLSIDFromString(const_cast<LPOLESTR>(pszCLSID), &catid);
return SUCCEEDED(hr) ? RegisterComponentCategory(catid, pszDesc) : hr;
}
HRESULT UnregisterComponentCategory(REFGUID catid)
{
ICatRegisterPtr pcr;
HRESULT hr = pcr.CreateInstance(__uuidof(StdComponentCategoriesMgr));
if (FAILED(hr))
{
return S_OK;
}
const LANGID langid = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
const LCID lcid = MAKELCID(langid, SORT_DEFAULT);
CATID catids[1];
catids[0] = catid;
return pcr->UnRegisterCategories(1, catids);
}
HRESULT UnregisterComponentCategory(LPCOLESTR pszCLSID)
{
GUID catid;
HRESULT hr = CLSIDFromString(const_cast<LPOLESTR>(pszCLSID), &catid);
return SUCCEEDED(hr) ? UnregisterComponentCategory(catid) : hr;
}
DATE GetVariantDateTime()
{
SYSTEMTIME st;
GetSystemTime(&st);
DATE time = 0;
_VERIFYE(SystemTimeToVariantTime(&st, &time));
return time;
}
DATE GetVariantDate()
{
SYSTEMTIME st;
GetSystemTime(&st);
st.wHour = 0;
st.wMinute = 0;
st.wSecond = 0;
st.wMilliseconds = 0;
DATE time = 0;
_VERIFYE(SystemTimeToVariantTime(&st, &time));
return time;
}
DATE GetVariantTime()
{
SYSTEMTIME st;
GetSystemTime(&st);
st.wYear = 1899;
st.wMonth = 12;
st.wDay = 30;
DATE time = 0;
_VERIFYE(SystemTimeToVariantTime(&st, &time));
return time;
}
DATE GetLocalVariantDateTime()
{
SYSTEMTIME st;
GetLocalTime(&st);
DATE time = 0;
_VERIFYE(SystemTimeToVariantTime(&st, &time));
return time;
}
DATE GetLocalVariantDate()
{
SYSTEMTIME st;
GetLocalTime(&st);
st.wHour = 0;
st.wMinute = 0;
st.wSecond = 0;
st.wMilliseconds = 0;
DATE time = 0;
_VERIFYE(SystemTimeToVariantTime(&st, &time));
return time;
}
DATE GetLocalVariantTime()
{
SYSTEMTIME st;
GetLocalTime(&st);
st.wYear = 1899;
st.wMonth = 12;
st.wDay = 30;
DATE time = 0;
_VERIFYE(SystemTimeToVariantTime(&st, &time));
return time;
}
bool TCSystemTimeToTzSpecificLocalTime(TIME_ZONE_INFORMATION* pTimeZone,
SYSTEMTIME* pUniversalTime, SYSTEMTIME* pLocalTime)
{
if (!::SystemTimeToTzSpecificLocalTime(NULL, pUniversalTime, pLocalTime))
{
TIME_ZONE_INFORMATION tz;
DWORD zone = GetTimeZoneInformation(&tz);
if (zone != TIME_ZONE_ID_UNKNOWN)
{
LONG lBias = tz.Bias;
if (zone == TIME_ZONE_ID_STANDARD)
lBias += tz.StandardBias;
else lBias += tz.DaylightBias;
FILETIME ft;
_VERIFYE(::SystemTimeToFileTime(pUniversalTime, &ft));
__int64 time64 = ((__int64)ft.dwHighDateTime << 32) | ft.dwLowDateTime;
__int64 bias = (__int64)lBias * (__int64)600000000;
time64 -= bias;
ft.dwHighDateTime = (DWORD)(time64 >> 32);
ft.dwLowDateTime = (DWORD)time64;
_VERIFYE(::FileTimeToSystemTime(&ft, pLocalTime));
}
}
return true;
}
bool VariantTimeToLocalTime(DATE date, SYSTEMTIME* psystime)
{
SYSTEMTIME systimeUTC, systime;
if (!VariantTimeToSystemTime(date, &systimeUTC))
return false;
_VERIFYE(TCSystemTimeToTzSpecificLocalTime(NULL, &systimeUTC, &systime));
__try
{
CopyMemory(psystime, &systime, sizeof(*psystime));
return true;
}
__except(1)
{
return false;
}
}
bool FileTimeToVariantTime(FILETIME* pft, DATE* pdate)
{
SYSTEMTIME systime;
if (!FileTimeToSystemTime(pft, &systime))
return false;
return !!SystemTimeToVariantTime(&systime, pdate);
}
int FormatDateTime(SYSTEMTIME* psystime, LPTSTR psz, int nLength)
{
__try
{
LCID lcid = GetThreadLocale();
int cchDate, cchTime;
cchDate = GetDateFormat(lcid, DATE_SHORTDATE, psystime, NULL, NULL, 0);
cchTime = GetTimeFormat(lcid, 0, psystime, NULL, NULL, 0);
int cchTotal = cchDate + cchTime;
if (!nLength)
return cchTotal;
LPTSTR pszFmt = LPTSTR(_alloca(cchTotal * sizeof(TCHAR)));
GetDateFormat(lcid, DATE_SHORTDATE, psystime, NULL, pszFmt, cchDate);
GetTimeFormat(lcid, 0, psystime, NULL, pszFmt + cchDate, cchTime);
pszFmt[cchDate - 1] = TEXT(' ');
lstrcpyn(psz, pszFmt, nLength);
return cchTotal;
}
__except(1)
{
_TRACE0("FormatDateTime(): Caught an unknown exception\n");
return 0;
}
}
int FormatVariantDateTimeAsLocal(DATE date, LPTSTR psz, int nLength)
{
SYSTEMTIME systime;
if (!VariantTimeToLocalTime(date, &systime))
return 0;
return FormatDateTime(&systime, psz, nLength);
}
int FormatDate(SYSTEMTIME* psystime, LPTSTR psz, int nLength)
{
__try
{
LCID lcid = GetThreadLocale();
int cchDate;
cchDate = GetDateFormat(lcid, DATE_SHORTDATE, psystime, NULL, NULL, 0);
if (!nLength)
return cchDate;
LPTSTR pszFmt = LPTSTR(_alloca(cchDate * sizeof(TCHAR)));
GetDateFormat(lcid, DATE_SHORTDATE, psystime, NULL, pszFmt, cchDate);
lstrcpyn(psz, pszFmt, nLength);
return cchDate;
}
__except(1)
{
_TRACE0("FormatDate(): Caught an unknown exception\n");
return 0;
}
}
int FormatVariantDateAsLocal(DATE date, LPTSTR psz, int nLength)
{
SYSTEMTIME systime;
if (!VariantTimeToLocalTime(date, &systime))
return 0;
return FormatDate(&systime, psz, nLength);
}
int FormatTime(SYSTEMTIME* psystime, LPTSTR psz, int nLength)
{
__try
{
LCID lcid = GetThreadLocale();
int cchTime;
cchTime = GetTimeFormat(lcid, 0, psystime, NULL, NULL, 0);
if (!nLength)
return cchTime;
LPTSTR pszFmt = LPTSTR(_alloca(cchTime * sizeof(TCHAR)));
GetTimeFormat(lcid, 0, psystime, NULL, pszFmt, cchTime);
lstrcpyn(psz, pszFmt, nLength);
return cchTime;
}
__except(1)
{
_TRACE0("FormatTime(): Caught an unknown exception\n");
return 0;
}
}
int FormatVariantTimeAsLocal(DATE date, LPTSTR psz, int nLength)
{
SYSTEMTIME systime;
if (!VariantTimeToLocalTime(date, &systime))
return 0;
return FormatTime(&systime, psz, nLength);
}
int FormatTimeSpan(SYSTEMTIME* psystime, LPTSTR psz, int nLength)
{
__try
{
LCID lcid = GetThreadLocale();
int cchTime;
DWORD dwFlags = TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT;
cchTime = GetTimeFormat(lcid, dwFlags, psystime, NULL, NULL, 0);
if (!nLength)
return cchTime;
LPTSTR pszFmt = LPTSTR(_alloca(cchTime * sizeof(TCHAR)));
GetTimeFormat(lcid, dwFlags, psystime, NULL, pszFmt, cchTime);
lstrcpyn(psz, pszFmt, nLength);
return cchTime;
}
__except(1)
{
_TRACE0("FormatTimeSpan(): Caught an unknown exception\n");
return 0;
}
}
int FormatVariantTimeSpan(DATE date, LPTSTR psz, int nLength)
{
SYSTEMTIME systime;
if (!VariantTimeToSystemTime(date, &systime))
return 0;
int nDays = int(date);
int nNegative = (nDays < 0) ? -1 : 1;
int nHoursExtra = (nDays * nNegative) * 24;
if ((nHoursExtra + systime.wHour) > USHRT_MAX)
return 0;
systime.wHour += nHoursExtra;
return FormatTimeSpan(&systime, psz, nLength);
}
#ifdef _AFX
CString FormatDateTime(SYSTEMTIME* psystime)
{
CString str;
FormatDateTime(psystime, str);
return str;
}
BOOL FormatDateTime(SYSTEMTIME* psystime, CString& str)
{
str.Empty();
int cch = FormatDateTime(psystime, NULL, 0);
int cchFmt = FormatDateTime(psystime, str.GetBuffer(cch), cch);
str.ReleaseBuffer();
return 0 != cchFmt;
}
CString FormatVariantDateTimeAsLocal(DATE date)
{
CString str;
FormatVariantDateTimeAsLocal(date, str);
return str;
}
BOOL FormatVariantDateTimeAsLocal(DATE date, CString& str)
{
SYSTEMTIME systime;
if (!VariantTimeToLocalTime(date, &systime))
return FALSE;
return FormatDateTime(&systime, str);
}
CString FormatDate(SYSTEMTIME* psystime)
{
CString str;
FormatDate(psystime, str);
return str;
}
BOOL FormatDate(SYSTEMTIME* psystime, CString& str)
{
str.Empty();
int cch = FormatDate(psystime, NULL, 0);
int cchFmt = FormatDate(psystime, str.GetBuffer(cch), cch);
str.ReleaseBuffer();
return 0 != cchFmt;
}
CString FormatVariantDateAsLocal(DATE date)
{
CString str;
FormatVariantDateAsLocal(date, str);
return str;
}
BOOL FormatVariantDateAsLocal(DATE date, CString& str)
{
SYSTEMTIME systime;
if (!VariantTimeToLocalTime(date, &systime))
return FALSE;
return FormatDate(&systime, str);
}
CString FormatTime(SYSTEMTIME* psystime)
{
CString str;
FormatTime(psystime, str);
return str;
}
BOOL FormatTime(SYSTEMTIME* psystime, CString& str)
{
str.Empty();
int cch = FormatTime(psystime, NULL, 0);
int cchFmt = FormatTime(psystime, str.GetBuffer(cch), cch);
str.ReleaseBuffer();
return 0 != cchFmt;
}
CString FormatVariantTimeAsLocal(DATE date)
{
CString str;
FormatVariantTimeAsLocal(date, str);
return str;
}
BOOL FormatVariantTimeAsLocal(DATE date, CString& str)
{
SYSTEMTIME systime;
if (!VariantTimeToLocalTime(date, &systime))
return FALSE;
return FormatTime(&systime, str);
}
CString FormatTimeSpan(SYSTEMTIME* psystime)
{
CString str;
FormatTimeSpan(psystime, str);
return str;
}
BOOL FormatTimeSpan(SYSTEMTIME* psystime, CString& str)
{
str.Empty();
int cch = FormatTimeSpan(psystime, NULL, 0);
int cchFmt = FormatTimeSpan(psystime, str.GetBuffer(cch), cch);
str.ReleaseBuffer();
return 0 != cchFmt;
}
CString FormatVariantTimeSpan(DATE date)
{
CString str;
FormatVariantTimeSpan(date, str);
return str;
}
BOOL FormatVariantTimeSpan(DATE date, CString& str)
{
str.Empty();
int cch = FormatVariantTimeSpan(date, NULL, 0);
int cchFmt = FormatVariantTimeSpan(date, str.GetBuffer(cch), cch);
str.ReleaseBuffer();
return 0 != cchFmt;
}
#endif HRESULT SaveObjectToNewStream(IUnknown* punk, IStream** ppStream)
{
CLEAROUT(ppStream, (IStream*)NULL);
if (!punk)
return E_POINTER;
IPersistStreamPtr sppstm;
HRESULT hr = TCSafeQI(punk, &sppstm);
if (E_NOINTERFACE == hr)
hr = punk->QueryInterface(IID_IPersistStreamInit, (void**)&sppstm);
RETURN_FAILED(hr);
IStreamPtr spstm;
RETURN_FAILED(CreateStreamOnHGlobal(NULL, TRUE, &spstm));
ULARGE_INTEGER cbSize = {0, 0};
if (SUCCEEDED(sppstm->GetSizeMax(&cbSize)))
spstm->SetSize(cbSize);
RETURN_FAILED(sppstm->Save(spstm, FALSE))
*ppStream = spstm;
spstm.Detach();
return S_OK;
}
HRESULT LoadObjectFromStream(IUnknown* punk, IStream* pStream)
{
if (!punk)
return E_POINTER;
IPersistStreamPtr sppstm;
HRESULT hr = TCSafeQI(punk, &sppstm);
if (E_NOINTERFACE == hr)
hr = punk->QueryInterface(IID_IPersistStreamInit, (void**)&sppstm);
RETURN_FAILED(hr);
IStreamPtr spStream;
RETURN_FAILED(TCSafeQI(pStream, &spStream));
LARGE_INTEGER lSeek = {0, 0};
RETURN_FAILED(spStream->Seek(lSeek, STREAM_SEEK_SET, NULL));
return sppstm->Load(spStream);
}
HRESULT CopyObjectThruStream(IUnknown* punkDest, IUnknown* punkSrc)
{
if (!punkDest || !punkSrc)
return E_POINTER;
IStreamPtr pstm;
RETURN_FAILED(SaveObjectToNewStream(punkSrc, &pstm));
return LoadObjectFromStream(punkDest, pstm);
}
HRESULT CreateCopyObjectThruStream(IUnknown* punk, REFIID riid, void** ppv)
{
CLEAROUT(ppv, (void*)NULL);
if (!punk)
return S_OK;
IPersistPtr spPersist;
RETURN_FAILED(TCSafeQI(punk, &spPersist));
CLSID clsid;
RETURN_FAILED(spPersist->GetClassID(&clsid));
if (CLSID_NULL == clsid)
return REGDB_E_CLASSNOTREG;
IStreamPtr spstm;
RETURN_FAILED(SaveObjectToNewStream(punk, &spstm));
IUnknownPtr spunkDest;
RETURN_FAILED(spunkDest.CreateInstance(clsid));
RETURN_FAILED(LoadObjectFromStream(spunkDest, spstm));
return spunkDest->QueryInterface(riid, ppv);
}
HRESULT CompareObjectsThruStream(IUnknown* punk1, IUnknown* punk2)
{
if (!punk1 && !punk2)
return S_OK;
HRESULT hr = CompareObjectCLSIDs(punk1, punk2);
if (S_OK != hr)
return hr;
IStreamPtr spstm1;
RETURN_FAILED(SaveObjectToNewStream(punk1, &spstm1));
return CompareObjectsThruThisStream(spstm1, punk2);
}
HRESULT CompareObjectsThruThisStream(IStream* pstm1, IUnknown* punk2)
{
if (!pstm1 && !punk2)
return S_OK;
if (!pstm1 || !punk2)
return S_FALSE;
IStreamPtr spstm2;
RETURN_FAILED(SaveObjectToNewStream(punk2, &spstm2));
LARGE_INTEGER liMove = {0, 0};
ULARGE_INTEGER uliPos1 = {0, 0}, uliPos2 = {0, 0};
RETURN_FAILED(pstm1->Seek(liMove, STREAM_SEEK_END, &uliPos1));
RETURN_FAILED(spstm2->Seek(liMove, STREAM_SEEK_END, &uliPos2));
assert(!uliPos1.HighPart && !uliPos2.HighPart);
if (uliPos1.LowPart != uliPos2.LowPart)
return S_FALSE;
RETURN_FAILED(pstm1->Seek(liMove, STREAM_SEEK_SET, NULL));
RETURN_FAILED(spstm2->Seek(liMove, STREAM_SEEK_SET, NULL));
const int cbBuffer = 4096;
BYTE pBuffer1[cbBuffer], pBuffer2[cbBuffer];
ULONG nRemaining = uliPos1.LowPart;
for (; nRemaining > cbBuffer; nRemaining -= cbBuffer)
{
RETURN_FAILED(pstm1->Read(pBuffer1, cbBuffer, NULL));
RETURN_FAILED(spstm2->Read(pBuffer2, cbBuffer, NULL));
if (0 != memcmp(pBuffer1, pBuffer2, cbBuffer))
return S_FALSE;
}
RETURN_FAILED(pstm1->Read(pBuffer1, nRemaining, NULL));
RETURN_FAILED(spstm2->Read(pBuffer2, nRemaining, NULL));
return (0 != memcmp(pBuffer1, pBuffer2, nRemaining)) ? S_FALSE : S_OK;
}
HRESULT CompareObjectCLSIDs(IUnknown* punk1, IUnknown* punk2)
{
if (!punk1 && !punk2)
return S_OK;
if (!punk1 || !punk2)
return S_FALSE;
IPersistPtr spPersist1, spPersist2;
RETURN_FAILED(TCSafeQI(punk1, &spPersist1));
RETURN_FAILED(TCSafeQI(punk2, &spPersist2));
CLSID clsid1, clsid2;
RETURN_FAILED(spPersist1->GetClassID(&clsid1));
RETURN_FAILED(spPersist2->GetClassID(&clsid2));
return (clsid1 == clsid2) ? S_OK : S_FALSE;
}
bool FixSliderThumbSize(HWND hwndSlider)
{
DWORD dwStyle = ::GetWindowLong(hwndSlider, GWL_STYLE);
long nDefault = ::SendMessage(hwndSlider, TBM_GETTHUMBLENGTH, 0, 0);
if (!(dwStyle & TBS_FIXEDLENGTH))
::SetWindowLong(hwndSlider, GWL_STYLE, dwStyle | TBS_FIXEDLENGTH);
RECT rc;
::GetClientRect(hwndSlider, &rc);
const long nFocus = 1;
long nThumb = ((dwStyle & TBS_VERT) ?
(rc.right - rc.left) : (rc.bottom - rc.top)) - nFocus * 2;
long nTickSides = (dwStyle & TBS_BOTH) ? 2 : 1;
nTickSides = (dwStyle & TBS_NOTICKS) ? 0 : nTickSides;
if (2 == nTickSides || (1 == nTickSides && (dwStyle & TBS_TOP)))
--nThumb;
const long nTicks = 3 + 4;
nThumb -= nTickSides * nTicks;
nThumb = max(nThumb, 6L);
nThumb = min(nThumb, nDefault);
if (nThumb == nDefault)
return true;
::SendMessage(hwndSlider, TBM_SETTHUMBLENGTH, nThumb, 0);
return ::SendMessage(hwndSlider, TBM_GETTHUMBLENGTH, 0, 0) == nThumb;
}
#ifdef _AFX
bool FixSliderThumbSize(CWnd* pwndSlider)
{
HWND hwndSlider = pwndSlider->GetSafeHwnd();
return hwndSlider ? FixSliderThumbSize(hwndSlider) : false;
}
#endif HRESULT LockAndLoadResource(HINSTANCE hinst, LPCTSTR pszType,
LPCTSTR pszName, void** ppvData, DWORD* pcbData)
{
CLEAROUT_ALLOW_NULL(ppvData, (void*)NULL);
CLEAROUT_ALLOW_NULL(pcbData, (DWORD)0);
HRSRC hrsrc = ::FindResource(hinst, pszName, pszType);
if (!hrsrc)
return HRESULT_FROM_WIN32(::GetLastError());
DWORD cb = ::SizeofResource(hinst, hrsrc);
HGLOBAL hData = ::LoadResource(hinst, hrsrc);
if (!hData)
return HRESULT_FROM_WIN32(::GetLastError());
void* pvData = LockResource(hData);
if (!pvData)
return HRESULT_FROM_WIN32(::GetLastError());
*ppvData = pvData;
*pcbData = cb;
return S_OK;
}
bool IsInteractiveDesktop()
{
if (IsWin9x())
return true;
HWINSTA hWinSta = ::GetProcessWindowStation();
if (!hWinSta)
return false;
DWORD cbNeeded = 0;
TCHAR szName[_MAX_PATH] = TEXT("");
::GetUserObjectInformation(hWinSta, UOI_NAME, szName, sizeof(szName),
&cbNeeded);
if (lstrcmp(TEXT("WinSta0"), szName))
return false;
HDESK hDesk = ::GetThreadDesktop(::GetCurrentThreadId());
if (!hDesk)
return false;
::GetUserObjectInformation(hDesk, UOI_NAME, szName, sizeof(szName),
&cbNeeded);
return !lstrcmp(TEXT("Default"), szName);
}
int TCLoadStringW(HINSTANCE hInstance, UINT wID, LPWSTR wzBuf, int cchBuf)
{
if (wzBuf && cchBuf)
wzBuf[0] = L'\0';
UINT block = (wID >> 4) + 1; UINT num = wID & 0xf; HRSRC hRC = FindResourceEx(hInstance, RT_STRING,
MAKEINTRESOURCE(block), MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL));
HGLOBAL hgl = LoadResource(hInstance, hRC);
LPWSTR str = (LPWSTR)LockResource(hgl);
if (!str)
return 0;
for (UINT i = 0; i < num; i++)
str += *str + 1;
if (wzBuf && cchBuf)
{
wcsncpy(wzBuf, str + 1, min(cchBuf - 1, *str));
wzBuf[min(cchBuf-1, *str) ] = '\0';
}
return *str;
}
HRESULT TCLoadBSTR(HINSTANCE hInstance, UINT wID, BSTR* pbstrOut)
{
int cch = TCLoadStringW(hInstance, wID, NULL, 0);
if (!cch)
return S_FALSE;
*pbstrOut = SysAllocStringLen(NULL, cch);
if (!*pbstrOut)
return E_OUTOFMEMORY;
return TCLoadStringW(hInstance, wID, *pbstrOut, cch + 1) ? S_OK : S_FALSE;
}
void _cdecl TCErrLog(LPCTSTR lpszFormat, ...)
{
va_list args;
va_start(args, lpszFormat);
int nBuf;
TCHAR szBuffer[512];
nBuf = _vstprintf(szBuffer, lpszFormat, args);
assert(nBuf < sizeof(szBuffer));
#ifdef _DEBUG
ZDebugOutputImpl(szBuffer);
#else OutputDebugString(szBuffer);
#endif va_end(args);
}