1843 lines
47 KiB
C++
1843 lines
47 KiB
C++
//+--------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1994 - 1998.
|
|
//
|
|
// File: util.cxx
|
|
//
|
|
// Contents: utility functions
|
|
//
|
|
//
|
|
// History: 12-05-1997 SusiA
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
#include "lib.h"
|
|
#ifndef SECURITY_WIN32
|
|
#define SECURITY_WIN32
|
|
#endif
|
|
#include "security.h"
|
|
|
|
extern "C" CRITICAL_SECTION g_CritSectCommonLib; // initialized by InitCommonLib
|
|
extern OSVERSIONINFOA g_OSVersionInfo; // osVersionInfo.
|
|
|
|
typedef BOOLEAN (APIENTRY *PFNGETUSERNAMEEX) (EXTENDED_NAME_FORMAT NameFormat,
|
|
LPWSTR lpNameBuffer, PULONG nSize );
|
|
|
|
STRING_FILENAME(szSecur32Dll, "SECUR32.DLL");
|
|
STRING_INTERFACE(szGetUserNameEx,"GetUserNameExW");
|
|
BOOL g_fLoadedSecur32 = FALSE;
|
|
HINSTANCE g_hinstSecur32 = NULL;
|
|
PFNGETUSERNAMEEX g_pfGetUserNameEx = NULL;
|
|
|
|
|
|
//--------------------------------------------------------------------------------
|
|
//
|
|
// FUNCTION: RegGetCurrentUser(LPTSTR pszName, LPDWORD pdwCount)
|
|
//
|
|
// PURPOSE: Gets the currently logged on user name from the Reg
|
|
//
|
|
//--------------------------------------------------------------------------------
|
|
|
|
BOOL RegGetCurrentUser(LPTSTR pszName, LPDWORD pdwCount)
|
|
{
|
|
HRESULT hr = ERROR_SUCCESS;
|
|
HKEY hkeyUser;
|
|
DWORD dwDataSize = *pdwCount * sizeof(TCHAR);
|
|
DWORD dwType = REG_SZ;
|
|
|
|
|
|
// Get the current user name from the reg
|
|
if (ERROR_SUCCESS == (hr = RegOpenKeyExXp(HKEY_CURRENT_USER,
|
|
TOPLEVEL_REGKEY,0,KEY_QUERY_VALUE,&hkeyUser,FALSE /*fSetSecurity*/)))
|
|
{
|
|
|
|
hr = RegQueryValueEx(hkeyUser,TEXT("CurrentUserName"),
|
|
NULL, &dwType ,
|
|
(LPBYTE) pszName,
|
|
&dwDataSize);
|
|
|
|
*pdwCount = dwDataSize;
|
|
RegCloseKey(hkeyUser);
|
|
}
|
|
|
|
if (ERROR_SUCCESS == hr)
|
|
{
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------
|
|
//
|
|
// FUNCTION: RegSetCurrentUser(LPTSTR pszName)
|
|
//
|
|
// PURPOSE: sets the current user name in the reg
|
|
//
|
|
//--------------------------------------------------------------------------------
|
|
|
|
BOOL RegSetCurrentUser(LPTSTR pszName)
|
|
{
|
|
HRESULT hr = ERROR_SUCCESS;
|
|
HKEY hkeyUser;
|
|
|
|
// write out the Handler to the Registry.
|
|
if (ERROR_SUCCESS == (hr = RegCreateKeyEx(HKEY_CURRENT_USER,
|
|
TOPLEVEL_REGKEY,0,NULL, REG_OPTION_NON_VOLATILE,
|
|
KEY_READ | KEY_WRITE | KEY_CREATE_SUB_KEY,
|
|
NULL,&hkeyUser, NULL)))
|
|
{
|
|
|
|
hr = RegSetValueEx(hkeyUser,TEXT("CurrentUserName"),
|
|
NULL, REG_SZ ,
|
|
(LPBYTE) pszName,
|
|
UNLEN + 1);
|
|
|
|
RegCloseKey(hkeyUser);
|
|
}
|
|
|
|
if (ERROR_SUCCESS == hr)
|
|
{
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: CenterDialog
|
|
//
|
|
// Synopsis: Helper to center a dialog on screen.
|
|
//
|
|
// Arguments: [hDlg] -- Dialog handle.
|
|
//
|
|
// Returns: None.
|
|
//
|
|
// Notes: None.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
void
|
|
CenterDialog(HWND hDlg)
|
|
{
|
|
RECT rc;
|
|
GetWindowRect(hDlg, &rc);
|
|
|
|
SetWindowPos(hDlg,
|
|
NULL,
|
|
((GetSystemMetrics(SM_CXSCREEN) - (rc.right - rc.left)) / 2),
|
|
((GetSystemMetrics(SM_CYSCREEN) - (rc.bottom - rc.top)) / 2),
|
|
0,
|
|
0,
|
|
SWP_NOSIZE | SWP_NOACTIVATE);
|
|
}
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Function: GetDomainAndMachineName
|
|
//
|
|
// Synopsis: Fill [ptszDomainAndMachineName] with "domain\machine" string
|
|
//
|
|
// Arguments: [ptszDomainAndMachineName] - buffer to receive string
|
|
// [cchBuf] - should be at least UNLEN
|
|
//
|
|
// Modifies: *[ptszDomainAndMachineName].
|
|
//
|
|
// History: 01-12-1998 SusiA Created
|
|
//
|
|
// Notes: If an error occurs while retrieving the domain name, only
|
|
// the machine name is returned. If even that cannot be
|
|
// retrieved, the buffer is set to an empty string.
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
VOID
|
|
GetDomainAndMachineName(
|
|
LPTSTR ptszDomainAndMachineName,
|
|
ULONG cchBuf)
|
|
{
|
|
|
|
HRESULT hr = E_FAIL;
|
|
LONG lr;
|
|
HKEY hkWinlogon = NULL;
|
|
ULONG cchRemain = cchBuf;
|
|
|
|
do
|
|
{
|
|
//
|
|
// Get the domain name of the currently logged on user. Open the
|
|
// winlogon key.
|
|
//
|
|
|
|
lr = RegOpenKeyExXp(HKEY_LOCAL_MACHINE,
|
|
REGSTR_WINLOGON,
|
|
0,
|
|
KEY_QUERY_VALUE,
|
|
&hkWinlogon,FALSE /*fSetSecurity*/);
|
|
|
|
if (lr != ERROR_SUCCESS)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Query for the default domain, which is what the user logged on to.
|
|
//
|
|
|
|
ULONG cbBuf = cchBuf * sizeof(TCHAR);
|
|
DWORD dwType;
|
|
|
|
lr = RegQueryValueEx(hkWinlogon,
|
|
REGSTR_DEFAULT_DOMAIN,
|
|
NULL,
|
|
&dwType,
|
|
(LPBYTE) ptszDomainAndMachineName,
|
|
&cbBuf);
|
|
|
|
if (lr != ERROR_SUCCESS)
|
|
{
|
|
break;
|
|
}
|
|
|
|
Assert(dwType == REG_SZ);
|
|
|
|
//
|
|
// Account for the characters used up by the domain name, but
|
|
// don't count the trailing NULL.
|
|
//
|
|
|
|
cchRemain -= (cbBuf / sizeof(TCHAR)) - 1;
|
|
|
|
if (cchRemain < 2)
|
|
{
|
|
break;
|
|
}
|
|
|
|
lstrcat(ptszDomainAndMachineName, TEXT("/"));
|
|
cchRemain--;
|
|
|
|
hr = S_OK;
|
|
} while (0);
|
|
|
|
//
|
|
// If there was any problem with the domain name, put only the user name
|
|
// in the buffer.
|
|
//
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
*ptszDomainAndMachineName = TEXT('\0');
|
|
cchRemain = cchBuf;
|
|
}
|
|
|
|
//
|
|
// Get the machine name, which is going either at the start of the buffer
|
|
// or just after the backslash appended to the domain name.
|
|
//
|
|
|
|
lr = GetComputerName(&ptszDomainAndMachineName[cchBuf - cchRemain], &cchRemain);
|
|
|
|
if (!lr)
|
|
{
|
|
*ptszDomainAndMachineName = TEXT('\0');
|
|
}
|
|
|
|
if (hkWinlogon)
|
|
{
|
|
RegCloseKey(hkWinlogon);
|
|
}
|
|
}
|
|
|
|
void LoadSecur32Dll()
|
|
{
|
|
if (g_fLoadedSecur32)
|
|
return;
|
|
|
|
CCriticalSection cCritSect(&g_CritSectCommonLib,GetCurrentThreadId());
|
|
|
|
cCritSect.Enter();
|
|
|
|
// make sure not loaded again in case someone took lock first
|
|
if (!g_fLoadedSecur32)
|
|
{
|
|
g_hinstSecur32 = LoadLibrary(szSecur32Dll);
|
|
|
|
if (g_hinstSecur32)
|
|
{
|
|
g_pfGetUserNameEx = (PFNGETUSERNAMEEX) GetProcAddress(g_hinstSecur32, szGetUserNameEx);
|
|
|
|
// won't get the export on NT 4.0
|
|
}
|
|
|
|
g_fLoadedSecur32 = TRUE;
|
|
}
|
|
|
|
cCritSect.Leave();
|
|
|
|
}
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Function: GetNT4UserDomainName
|
|
//
|
|
// Synopsis: Fill [ptszDomainAndUserName] with "domain\user" string
|
|
//
|
|
// Arguments: [ptszDomainAndUserName] - buffer to receive string
|
|
// [cchBuf] - should be at least UNLEN
|
|
//
|
|
// Modifies: *[ptszDomainAndUserName].
|
|
//
|
|
// History: 06-03-1997 DavidMun Created
|
|
//
|
|
// Notes: If an error occurs while retrieving the domain name, only
|
|
// the user name is returned. If even that cannot be
|
|
// retrieved, the buffer is set to an empty string.
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
BOOL GetNT4UserDomainName(LPTSTR ptszDomainAndUserName,
|
|
LPTSTR ptszSeparator,
|
|
ULONG cchBuf)
|
|
{
|
|
HKEY hkWinlogon = NULL;
|
|
ULONG cchRemain = cchBuf;
|
|
HRESULT hr = E_FAIL;
|
|
LONG lr;
|
|
ULONG cchTemp = UNLEN + DNLEN + 1;
|
|
|
|
do
|
|
{
|
|
//
|
|
// Get the domain name of the currently logged on user. Open the
|
|
// winlogon key.
|
|
//
|
|
|
|
lr = RegOpenKeyExXp(HKEY_LOCAL_MACHINE,
|
|
REGSTR_WINLOGON,
|
|
0,
|
|
KEY_QUERY_VALUE,
|
|
&hkWinlogon,FALSE /*fSetSecurity*/);
|
|
|
|
if (lr != ERROR_SUCCESS)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Query for the default domain, which is what the user logged on to.
|
|
//
|
|
|
|
ULONG cbBuf = cchBuf * sizeof(TCHAR);
|
|
DWORD dwType;
|
|
|
|
lr = RegQueryValueEx(hkWinlogon,
|
|
REGSTR_DEFAULT_DOMAIN,
|
|
NULL,
|
|
&dwType,
|
|
(LPBYTE) ptszDomainAndUserName,
|
|
&cbBuf);
|
|
|
|
if (lr != ERROR_SUCCESS)
|
|
{
|
|
break;
|
|
}
|
|
|
|
Assert(dwType == REG_SZ);
|
|
|
|
//
|
|
// Account for the characters used up by the domain name, but
|
|
// don't count the trailing NULL.
|
|
//
|
|
|
|
cchRemain -= (cbBuf / sizeof(TCHAR)) - 1;
|
|
|
|
if (cchRemain < 2)
|
|
{
|
|
break;
|
|
}
|
|
|
|
lstrcat(ptszDomainAndUserName, ptszSeparator);
|
|
cchRemain--;
|
|
|
|
hr = S_OK;
|
|
} while (0);
|
|
|
|
//
|
|
// If there was any problem with the domain name, put only the user name
|
|
// in the buffer.
|
|
//
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
*ptszDomainAndUserName = TEXT('\0');
|
|
cchRemain = cchBuf;
|
|
}
|
|
|
|
//
|
|
// Get the user name, which is going either at the start of the buffer
|
|
// or just after the backslash appended to the domain name.
|
|
//
|
|
|
|
cchTemp = cchRemain;
|
|
|
|
lr = GetUserName(&ptszDomainAndUserName[cchBuf - cchTemp], &cchTemp);
|
|
if (hkWinlogon)
|
|
{
|
|
RegCloseKey(hkWinlogon);
|
|
}
|
|
|
|
|
|
return (S_OK == hr) ? TRUE: FALSE;
|
|
}
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Function: GetDefaultDomainAndUserName
|
|
//
|
|
// Synopsis: Fill [ptszDomainAndUserName] with "domain\user" string
|
|
//
|
|
// Arguments: [ptszDomainAndUserName] - buffer to receive string
|
|
// [cchBuf] - should be at least UNLEN
|
|
//
|
|
// Modifies: *[ptszDomainAndUserName].
|
|
//
|
|
// History: 06-03-1997 DavidMun Created
|
|
//
|
|
// Notes: If an error occurs while retrieving the domain name, only
|
|
// the user name is returned. If even that cannot be
|
|
// retrieved, the buffer is set to an empty string.
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
// if output buffer is too small it gets truncated.
|
|
|
|
VOID
|
|
GetDefaultDomainAndUserName(
|
|
LPTSTR ptszDomainAndUserName,
|
|
LPTSTR ptszSeparator,
|
|
ULONG cchBuf)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
LONG lr = 0;
|
|
ULONG cchTemp = UNLEN + DNLEN + 1;
|
|
BOOL fIsNT = (g_OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT);
|
|
|
|
if (fIsNT)
|
|
{
|
|
LoadSecur32Dll();
|
|
|
|
if (g_pfGetUserNameEx)
|
|
{
|
|
lr = g_pfGetUserNameEx(NameSamCompatible,ptszDomainAndUserName, &cchTemp);
|
|
|
|
if (lr)
|
|
{
|
|
LPTSTR ptszWorker = ptszDomainAndUserName;
|
|
|
|
while ( (TEXT('\0') != *ptszWorker) && *ptszWorker != TEXT('\\'))
|
|
{
|
|
ptszWorker++;
|
|
}
|
|
|
|
if ( TEXT('\0') != *ptszWorker)
|
|
{
|
|
*ptszWorker = ptszSeparator[0];
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if ((NULL == g_pfGetUserNameEx) || (0 == lr))
|
|
{
|
|
GetNT4UserDomainName(ptszDomainAndUserName,ptszSeparator,cchBuf);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
// Win9x Stuff.
|
|
|
|
cchTemp = cchBuf;
|
|
|
|
if (!(lr = RegGetCurrentUser(ptszDomainAndUserName, &cchTemp)))
|
|
{
|
|
cchTemp = cchBuf;
|
|
|
|
lr = GetUserName(ptszDomainAndUserName,&cchTemp);
|
|
|
|
if (!lr || (*ptszDomainAndUserName == NULL))
|
|
{
|
|
// on Win9x user can work without a user Name in this case
|
|
// or any other GetUserName file the user is forced
|
|
// to be called Default
|
|
|
|
Assert(lstrlen(SZ_DEFAULTDOMAINANDUSERNAME) < cchBuf);
|
|
|
|
lstrcpy(ptszDomainAndUserName,SZ_DEFAULTDOMAINANDUSERNAME);
|
|
}
|
|
|
|
// write out currentUser setting so can use next time.
|
|
RegSetCurrentUser(ptszDomainAndUserName);
|
|
}
|
|
|
|
}
|
|
|
|
Assert(NULL != *ptszDomainAndUserName);
|
|
return;
|
|
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------------
|
|
//
|
|
// FUNCTION: BOOL ConvertString(LPTSTR pszOut, LPWSTR pwszIn, DWORD dwSize)
|
|
//
|
|
// PURPOSE: utility function for ANSI/UNICODE conversion
|
|
//
|
|
// RETURN VALUE: return TRUE if we process it ok.
|
|
//
|
|
//+-------------------------------------------------------------------------------
|
|
BOOL ConvertString(char * pszOut, LPWSTR pwszIn, DWORD dwSize)
|
|
{
|
|
|
|
if(WideCharToMultiByte( CP_ACP,0,pwszIn,-1,pszOut,dwSize,NULL,NULL))
|
|
{
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------------
|
|
//
|
|
// FUNCTION: BOOL ConvertString(LPWSTR pwszOut, LPTSTR pszIn, DWORD dwSize)
|
|
//
|
|
// PURPOSE: utility function for ANSI/UNICODE conversion
|
|
//
|
|
// RETURN VALUE: return TRUE if we process it ok.
|
|
//
|
|
//+-------------------------------------------------------------------------------
|
|
BOOL ConvertString(LPWSTR pwszOut,char * pszIn, DWORD dwSize)
|
|
{
|
|
|
|
if(MultiByteToWideChar( CP_ACP,0,pszIn,-1,pwszOut,dwSize))
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//+-------------------------------------------------------------------------------
|
|
//
|
|
// FUNCTION: Bogus function temporary until get transitioned to unicode
|
|
// so I don't have to fix up every existing converstring call.
|
|
//
|
|
// PURPOSE: utility function for ANSI/UNICODE conversion
|
|
//
|
|
// RETURN VALUE: return TRUE if we process it ok.
|
|
//
|
|
//+-------------------------------------------------------------------------------
|
|
|
|
BOOL ConvertString(LPWSTR pszOut, LPWSTR pwszIn, DWORD dwSize)
|
|
{
|
|
#ifdef _UNICODE
|
|
lstrcpy(pszOut,pwszIn);
|
|
#else
|
|
AssertSz(0,"Shouldn't be called in ASCII mode");
|
|
#endif // _UNICODE
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------------
|
|
//
|
|
// Function: ConvertMultiByteToWideChar
|
|
//
|
|
// Synopsis: Converts multibyte strings to Unicode
|
|
//
|
|
/// Arguments: [pszBufIn] -- Input multibyte string
|
|
// [cbBufIn] -- Count of chars/bytes in input buffer
|
|
// [xwszBufOut] -- Smart pointer to output Unicode string
|
|
// [fOem] -- If true use CP_OEMCP
|
|
//
|
|
// Returns: TRUE if we process it ok
|
|
//
|
|
// History: 14-Jul-98 SitaramR Created
|
|
//
|
|
//+-------------------------------------------------------------------------------
|
|
|
|
BOOL ConvertMultiByteToWideChar( const char *pszBufIn,
|
|
ULONG cbBufIn,
|
|
XArray<WCHAR>& xwszBufOut,
|
|
BOOL fOem )
|
|
{
|
|
Assert( pszBufIn != 0 );
|
|
|
|
if ( 0 == cbBufIn )
|
|
{
|
|
xwszBufOut[0] = 0;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL fOk;
|
|
if ( xwszBufOut.Get() == 0 )
|
|
{
|
|
ULONG cbBufOut;
|
|
|
|
cbBufOut = (-1 == cbBufIn) ? lstrlenA(pszBufIn) + 1: cbBufIn;
|
|
cbBufOut += 6; // give it a little extra room
|
|
|
|
fOk = xwszBufOut.Init(cbBufOut);
|
|
if ( !fOk )
|
|
return FALSE;
|
|
}
|
|
|
|
UINT codePage = CP_ACP;
|
|
if ( fOem && !AreFileApisANSI() )
|
|
codePage = CP_OEMCP;
|
|
|
|
ULONG cwcBufOut = (ULONG)xwszBufOut.Count();
|
|
ULONG cwcConvert = 0;
|
|
|
|
do
|
|
{
|
|
cwcConvert = MultiByteToWideChar( codePage,
|
|
MB_PRECOMPOSED,
|
|
pszBufIn,
|
|
cbBufIn,
|
|
xwszBufOut.Get(),
|
|
cwcBufOut - 1 );
|
|
if ( 0 == cwcConvert )
|
|
{
|
|
if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER )
|
|
{
|
|
//
|
|
// Double buffer size and then retry
|
|
//
|
|
delete xwszBufOut.Acquire();
|
|
|
|
cwcBufOut *= 2;
|
|
fOk = xwszBufOut.Init( cwcBufOut );
|
|
if ( !fOk )
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Error during conversion
|
|
//
|
|
Assert( FALSE );
|
|
return FALSE;
|
|
}
|
|
}
|
|
else
|
|
xwszBufOut[cwcConvert] = 0;
|
|
|
|
} while ( 0 == cwcConvert );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
//+-------------------------------------------------------------------------------
|
|
//
|
|
// Function: ConvertMultiByteToWideChar
|
|
//
|
|
// Synopsis: Converts multibyte strings to Unicode
|
|
//
|
|
/// Arguments: [pszBufIn] -- Input to null terminated multibyte string
|
|
// [xwszBufOut] -- Smart pointer to output Unicode string
|
|
// [fOem] -- If true use CP_OEMCP
|
|
//
|
|
// Returns: TRUE if we process it ok
|
|
//
|
|
// History: 14-Jul-98 SitaramR Created
|
|
//
|
|
//+-------------------------------------------------------------------------------
|
|
|
|
BOOL ConvertMultiByteToWideChar( const char *pszBufIn,
|
|
XArray<WCHAR>& xwszBufOut,
|
|
BOOL fOem )
|
|
{
|
|
if ( pszBufIn == 0)
|
|
{
|
|
void *pBuf;
|
|
|
|
if (pBuf = xwszBufOut.Acquire())
|
|
{
|
|
delete pBuf;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL fRet = ConvertMultiByteToWideChar( pszBufIn,
|
|
-1 /* lstrlenA(pszBufIn) + 1 */,
|
|
xwszBufOut,
|
|
fOem );
|
|
|
|
return fRet;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------------
|
|
//
|
|
// Function: ConvertWideCharToMultiByte
|
|
//
|
|
// Synopsis: Converts Unicode to multibyte strings
|
|
//
|
|
/// Arguments: [pwszBufIn] -- Input Unicode string
|
|
// [cwcBufIn] -- Count of wide chars in input buffer
|
|
// [xwszBufOut] -- Smart pointer to output multibyte string
|
|
// [fOem] -- If true use CP_OEMCP
|
|
//
|
|
// Returns: TRUE if we process it ok
|
|
//
|
|
// History: 14-Jul-98 SitaramR Created
|
|
//
|
|
//+-------------------------------------------------------------------------------
|
|
|
|
BOOL ConvertWideCharToMultiByte( const WCHAR *pwszBufIn,
|
|
ULONG cwcBufIn,
|
|
XArray<char>& xszBufOut,
|
|
BOOL fOem )
|
|
{
|
|
Assert( pwszBufIn != 0 );
|
|
|
|
if ( 0 == cwcBufIn )
|
|
{
|
|
xszBufOut[0] = 0;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL fOk;
|
|
if ( xszBufOut.Get() == 0 )
|
|
{
|
|
ULONG cbBufOut;
|
|
|
|
cbBufOut = (-1 == cwcBufIn) ? lstrlenX(pwszBufIn) + 1: cwcBufIn;
|
|
cbBufOut += 6; // give it a little extra room.
|
|
|
|
fOk = xszBufOut.Init(cbBufOut);
|
|
if ( !fOk )
|
|
return FALSE;
|
|
}
|
|
|
|
UINT codePage = CP_ACP;
|
|
if ( fOem && !AreFileApisANSI() )
|
|
codePage = CP_OEMCP;
|
|
|
|
ULONG cbConvert;
|
|
ULONG cbBufOut = (ULONG)xszBufOut.Count();
|
|
|
|
do
|
|
{
|
|
cbConvert = WideCharToMultiByte( codePage,
|
|
WC_COMPOSITECHECK,
|
|
pwszBufIn,
|
|
cwcBufIn,
|
|
xszBufOut.Get(),
|
|
cbBufOut - 1,
|
|
NULL,
|
|
NULL );
|
|
|
|
if ( 0 == cbConvert )
|
|
{
|
|
if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER )
|
|
{
|
|
//
|
|
// Double buffer size and then retry
|
|
//
|
|
delete xszBufOut.Acquire();
|
|
|
|
cbBufOut *= 2;
|
|
fOk = xszBufOut.Init( cbBufOut );
|
|
if ( !fOk )
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Error during conversion
|
|
//
|
|
Assert( FALSE );
|
|
return FALSE;
|
|
}
|
|
}
|
|
else
|
|
xszBufOut[cbConvert] = 0;
|
|
} while ( 0 == cbConvert );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
//+-------------------------------------------------------------------------------
|
|
//
|
|
// Function: ConvertWideCharToMultiByte
|
|
//
|
|
// Synopsis: Converts Unicode to multibyte strings
|
|
//
|
|
/// Arguments: [pwszBufIn] -- Input to null terminated Unicode string
|
|
// [xwszBufOut] -- Smart pointer to output multibyte string
|
|
// [fOem] -- If true use CP_OEMCP
|
|
//
|
|
// Returns: TRUE if we process it ok
|
|
//
|
|
// History: 14-Jul-98 SitaramR Created
|
|
//
|
|
//+-------------------------------------------------------------------------------
|
|
|
|
BOOL ConvertWideCharToMultiByte( const WCHAR *pwszBufIn,
|
|
XArray<char>& xszBufOut,
|
|
BOOL fOem )
|
|
{
|
|
if ( pwszBufIn == 0)
|
|
{
|
|
void *pBuf;
|
|
|
|
if (pBuf = xszBufOut.Acquire())
|
|
{
|
|
delete pBuf;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL fRet = ConvertWideCharToMultiByte( pwszBufIn,
|
|
lstrlenX(pwszBufIn) + 1,
|
|
xszBufOut,
|
|
fOem );
|
|
|
|
return fRet;
|
|
}
|
|
|
|
|
|
//
|
|
// Local constants
|
|
//
|
|
// DEFAULT_TIME_FORMAT - what to use if there's a problem getting format
|
|
// from system.
|
|
//
|
|
#define ARRAYLEN(a) (sizeof(a) / sizeof((a)[0]))
|
|
#define DEFAULT_TIME_FORMAT TEXT("hh:mm tt")
|
|
#define GET_LOCALE_INFO(lcid) \
|
|
{ \
|
|
cch = GetLocaleInfo(LOCALE_USER_DEFAULT, \
|
|
(lcid), \
|
|
tszScratch, \
|
|
ARRAYLEN(tszScratch)); \
|
|
if (!cch) \
|
|
{ \
|
|
break; \
|
|
} \
|
|
}
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Function: UpdateTimeFormat
|
|
//
|
|
// Synopsis: Construct a time format containing hour and minute for use
|
|
// with the date picker control.
|
|
//
|
|
// Arguments: [tszTimeFormat] - buffer to fill with time format
|
|
// [cchTimeFormat] - size in chars of buffer
|
|
//
|
|
// Modifies: *[tszTimeFormat]
|
|
//
|
|
// History: 11-18-1996 DavidMun Created
|
|
//
|
|
// Notes: This is called on initialization and for wininichange
|
|
// processing.
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
void
|
|
UpdateTimeFormat(
|
|
LPTSTR tszTimeFormat,
|
|
ULONG cchTimeFormat)
|
|
{
|
|
ULONG cch;
|
|
TCHAR tszScratch[80];
|
|
BOOL fAmPm;
|
|
BOOL fAmPmPrefixes;
|
|
BOOL fLeadingZero;
|
|
|
|
do
|
|
{
|
|
GET_LOCALE_INFO(LOCALE_ITIME);
|
|
fAmPm = (*tszScratch == TEXT('0'));
|
|
|
|
if (fAmPm)
|
|
{
|
|
GET_LOCALE_INFO(LOCALE_ITIMEMARKPOSN);
|
|
fAmPmPrefixes = (*tszScratch == TEXT('1'));
|
|
}
|
|
|
|
GET_LOCALE_INFO(LOCALE_ITLZERO);
|
|
fLeadingZero = (*tszScratch == TEXT('1'));
|
|
|
|
GET_LOCALE_INFO(LOCALE_STIME);
|
|
|
|
//
|
|
// See if there's enough room in destination string
|
|
//
|
|
|
|
cch = 1 + // terminating nul
|
|
1 + // first hour digit specifier "h"
|
|
2 + // minutes specifier "mm"
|
|
(fLeadingZero != 0) + // leading hour digit specifier "h"
|
|
lstrlen(tszScratch) + // separator string
|
|
(fAmPm ? 3 : 0); // space and "tt" for AM/PM
|
|
|
|
if (cch > cchTimeFormat)
|
|
{
|
|
cch = 0; // signal error
|
|
}
|
|
} while (0);
|
|
|
|
//
|
|
// If there was a problem in getting locale info for building time string
|
|
// just use the default and bail.
|
|
//
|
|
|
|
if (!cch)
|
|
{
|
|
lstrcpy(tszTimeFormat, DEFAULT_TIME_FORMAT);
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Build a time string that has hours and minutes but no seconds.
|
|
//
|
|
|
|
tszTimeFormat[0] = TEXT('\0');
|
|
|
|
if (fAmPm)
|
|
{
|
|
if (fAmPmPrefixes)
|
|
{
|
|
lstrcpy(tszTimeFormat, TEXT("tt "));
|
|
}
|
|
|
|
lstrcat(tszTimeFormat, TEXT("h"));
|
|
|
|
if (fLeadingZero)
|
|
{
|
|
lstrcat(tszTimeFormat, TEXT("h"));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lstrcat(tszTimeFormat, TEXT("H"));
|
|
|
|
if (fLeadingZero)
|
|
{
|
|
lstrcat(tszTimeFormat, TEXT("H"));
|
|
}
|
|
}
|
|
|
|
lstrcat(tszTimeFormat, tszScratch); // separator
|
|
lstrcat(tszTimeFormat, TEXT("mm"));
|
|
|
|
if (fAmPm && !fAmPmPrefixes)
|
|
{
|
|
lstrcat(tszTimeFormat, TEXT(" tt"));
|
|
}
|
|
}
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Function: FillInStartDateTime
|
|
//
|
|
// Synopsis: Fill [pTrigger]'s starting date and time values from the
|
|
// values in the date/time picker controls.
|
|
//
|
|
// Arguments: [hwndDatePick] - handle to control with start date
|
|
// [hwndTimePick] - handle to control with start time
|
|
// [pTrigger] - trigger to init
|
|
//
|
|
// Modifies: *[pTrigger]
|
|
//
|
|
// History: 12-08-1997 SusiA Stole from task scheduler
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
VOID FillInStartDateTime( HWND hwndDatePick, HWND hwndTimePick,TASK_TRIGGER *pTrigger)
|
|
{
|
|
SYSTEMTIME st;
|
|
|
|
DateTime_GetSystemtime(hwndDatePick, &st);
|
|
|
|
pTrigger->wBeginYear = st.wYear;
|
|
pTrigger->wBeginMonth = st.wMonth;
|
|
pTrigger->wBeginDay = st.wDay;
|
|
|
|
DateTime_GetSystemtime(hwndTimePick, &st);
|
|
|
|
pTrigger->wStartHour = st.wHour;
|
|
pTrigger->wStartMinute = st.wMinute;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// function: InsertListViewColumn, private
|
|
//
|
|
// Synopsis: Inserts a column into the ListView..
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 30-Jul-98 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
|
|
BOOL InsertListViewColumn(CListView *pListView,int iColumnId,LPWSTR pszText,int fmt,int cx)
|
|
{
|
|
LV_COLUMN columnInfo;
|
|
|
|
columnInfo.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;
|
|
columnInfo.fmt = fmt;
|
|
columnInfo.cx = cx;
|
|
columnInfo.pszText = pszText;
|
|
columnInfo.iSubItem = 0;
|
|
|
|
|
|
return pListView->InsertColumn(iColumnId,&columnInfo);
|
|
}
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Function: InitResizeItem
|
|
//
|
|
// Synopsis: Setups the ResizeInfo Structure.
|
|
//
|
|
// !!Can either pass in a ParentScreenRect or
|
|
// function will calculate. If passing in
|
|
// make sure you don't include the NC area
|
|
// of the window. See code below GetClientRect on parent
|
|
// then ClientToScreen.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 30-07-1998 rogerg
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
BOOL InitResizeItem(int iCtrlId,DWORD dlgResizeFlags,HWND hwndParent,
|
|
LPRECT pParentClientRect,DLGRESIZEINFO *pDlgResizeInfo)
|
|
{
|
|
RECT rectCtrl;
|
|
RECT rectLocalParentScreenRect;
|
|
|
|
Assert(pDlgResizeInfo);
|
|
|
|
Assert(0 == pParentClientRect->left); // catch any case not handing in ClientRect.
|
|
|
|
pDlgResizeInfo->iCtrlId = -1; // set ctrlId to -1 so GetDlgItem will fail in resize
|
|
|
|
|
|
// if dont' have parentScreenRect get it ourselves
|
|
if (!pParentClientRect)
|
|
{
|
|
pParentClientRect = &rectLocalParentScreenRect;
|
|
|
|
if (!GetClientRect(hwndParent,&rectLocalParentScreenRect))
|
|
{
|
|
AssertSz(0,"Unable to get Parent Rects");
|
|
return FALSE;
|
|
}
|
|
|
|
}
|
|
|
|
Assert(pParentClientRect);
|
|
|
|
if (!GetWindowRect(GetDlgItem(hwndParent,iCtrlId),&rectCtrl))
|
|
{
|
|
AssertSz(0,"Failed to GetWindowRect");
|
|
return FALSE;
|
|
}
|
|
|
|
MapWindowPoints(NULL,hwndParent,(LPPOINT) &rectCtrl,2);
|
|
|
|
pDlgResizeInfo->iCtrlId = iCtrlId;
|
|
pDlgResizeInfo->hwndParent = hwndParent;
|
|
pDlgResizeInfo->dlgResizeFlags = dlgResizeFlags;
|
|
|
|
// calc the offsets
|
|
|
|
pDlgResizeInfo->rectParentOffsets.left = rectCtrl.left - pParentClientRect->left;
|
|
pDlgResizeInfo->rectParentOffsets.top = rectCtrl.top - pParentClientRect->top;
|
|
|
|
pDlgResizeInfo->rectParentOffsets.right = pParentClientRect->right - rectCtrl.right;
|
|
pDlgResizeInfo->rectParentOffsets.bottom = pParentClientRect->bottom - rectCtrl.bottom;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Function: ResizeItems
|
|
//
|
|
// Synopsis: Resizes the Item.
|
|
//
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 30-07-1998 rogerg
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void ResizeItems(ULONG cbNumItems,DLGRESIZEINFO *pDlgResizeInfo)
|
|
{
|
|
RECT rectLocalParentClientCoord; // used if caller doesn't pass in parent coords.
|
|
DWORD dlgResizeFlags;
|
|
LPRECT prectOffsets;
|
|
RECT rectClient;
|
|
HWND hwndCtrl;
|
|
HWND hwndLastParent = NULL;
|
|
LPRECT prectParentClientCoords = NULL;
|
|
ULONG ulCount;
|
|
DLGRESIZEINFO *pCurDlgResizeInfo;
|
|
int x,y,cx,cy;
|
|
|
|
|
|
if (!pDlgResizeInfo)
|
|
{
|
|
Assert(pDlgResizeInfo);
|
|
}
|
|
|
|
|
|
for (ulCount = 0; ulCount < cbNumItems; ulCount++)
|
|
{
|
|
|
|
pCurDlgResizeInfo = &(pDlgResizeInfo[ulCount]);
|
|
|
|
dlgResizeFlags = pCurDlgResizeInfo->dlgResizeFlags;
|
|
prectOffsets = &(pCurDlgResizeInfo->rectParentOffsets);
|
|
|
|
// if not pinright or pin bottom there is nothing
|
|
// to do.
|
|
if (!(dlgResizeFlags & DLGRESIZEFLAG_PINRIGHT) &&
|
|
!(dlgResizeFlags & DLGRESIZEFLAG_PINBOTTOM) )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (NULL == prectParentClientCoords || (hwndLastParent != pCurDlgResizeInfo->hwndParent))
|
|
{
|
|
prectParentClientCoords = &rectLocalParentClientCoord;
|
|
|
|
if (!GetClientRect(pCurDlgResizeInfo->hwndParent,&rectLocalParentClientCoord))
|
|
{
|
|
prectParentClientCoords = NULL; // if GetClientRect failed for a recalc on next item
|
|
continue;
|
|
}
|
|
|
|
hwndLastParent = pCurDlgResizeInfo->hwndParent; // set lastparent now that we calc'd the rect.
|
|
}
|
|
|
|
Assert(prectParentClientCoords);
|
|
|
|
hwndCtrl = GetDlgItem(pCurDlgResizeInfo->hwndParent,pCurDlgResizeInfo->iCtrlId);
|
|
|
|
if ( (NULL == hwndCtrl) || !(GetWindowRect(hwndCtrl,&rectClient)) )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// get current values
|
|
x = (prectParentClientCoords->left + prectOffsets->left);
|
|
y = (prectParentClientCoords->top + prectOffsets->top);
|
|
|
|
cx = WIDTH(rectClient);
|
|
cy = HEIGHT(rectClient);
|
|
|
|
// if pinned both right and left adjust the width
|
|
if ((dlgResizeFlags & DLGRESIZEFLAG_PINLEFT)
|
|
&& (dlgResizeFlags & DLGRESIZEFLAG_PINRIGHT))
|
|
{
|
|
cx = prectParentClientCoords->right - (prectOffsets->right + prectOffsets->left);
|
|
}
|
|
|
|
// if pinned both top and bottom adjust height
|
|
if ((dlgResizeFlags & DLGRESIZEFLAG_PINTOP)
|
|
&& (dlgResizeFlags & DLGRESIZEFLAG_PINBOTTOM))
|
|
{
|
|
cy = prectParentClientCoords->bottom - (prectOffsets->bottom + prectOffsets->top);
|
|
}
|
|
|
|
// adjust the x position if pin right
|
|
if (dlgResizeFlags & DLGRESIZEFLAG_PINRIGHT)
|
|
{
|
|
x = (prectParentClientCoords->right - prectOffsets->right) - cx;
|
|
}
|
|
|
|
// adjust the y position if pin bottom
|
|
if (dlgResizeFlags & DLGRESIZEFLAG_PINBOTTOM)
|
|
{
|
|
y = (prectParentClientCoords->bottom - prectOffsets->bottom) - cy;
|
|
}
|
|
|
|
SetWindowPos(hwndCtrl, 0,x,y,cx,cy,SWP_NOZORDER | SWP_NOACTIVATE);
|
|
}
|
|
|
|
// now that the items are moved, loop through them again invalidating
|
|
// any items with the nocopy bits flag set
|
|
|
|
for (ulCount = 0; ulCount < cbNumItems; ulCount++)
|
|
{
|
|
pCurDlgResizeInfo = &(pDlgResizeInfo[ulCount]);
|
|
|
|
if (pCurDlgResizeInfo->dlgResizeFlags & DLGRESIZEFLAG_NOCOPYBITS)
|
|
{
|
|
hwndCtrl = GetDlgItem(pCurDlgResizeInfo->hwndParent,pCurDlgResizeInfo->iCtrlId);
|
|
|
|
if (hwndCtrl && GetClientRect(hwndCtrl,&rectClient))
|
|
{
|
|
InvalidateRect(hwndCtrl,&rectClient,FALSE);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Function: CalcListViewWidth
|
|
//
|
|
// Synopsis: Calcs width of listview - scroll bars
|
|
//
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 30-07-1998 rogerg
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
int CalcListViewWidth(HWND hwndList,int iDefault)
|
|
{
|
|
NONCLIENTMETRICSA metrics;
|
|
RECT rcClientRect;
|
|
|
|
|
|
metrics.cbSize = sizeof(metrics);
|
|
|
|
// explicitly ask for ANSI version of SystemParametersInfo since we just
|
|
// care about the ScrollWidth and don't want to conver the LOGFONT info.
|
|
if (GetClientRect(hwndList,&rcClientRect)
|
|
&& SystemParametersInfoA(SPI_GETNONCLIENTMETRICS,sizeof(metrics),(PVOID) &metrics,0))
|
|
{
|
|
// subtract off scroll bar distance
|
|
rcClientRect.right -= (metrics.iScrollWidth);
|
|
}
|
|
else
|
|
{
|
|
rcClientRect.right = iDefault; // if fail, use default
|
|
}
|
|
|
|
|
|
return rcClientRect.right;
|
|
}
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Function: SetCtrlFont
|
|
//
|
|
// Synopsis: Sets the appropriate font on the hwnd
|
|
// based on the platform and langID passed in.
|
|
//
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 25-09-1998 rogerg
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
// Example: SetCtrlFont(hwndList,g_OSVersionInfo.dwPlatformId,g_LangIdSystem);
|
|
|
|
void SetCtrlFont(HWND hwnd,DWORD dwPlatformID,LANGID langId)
|
|
{
|
|
|
|
// IE is in the process of cleaning up their controls as
|
|
// of 8/27/98 the controls we would need to set the font on are
|
|
// Edit,Static and ListBox (listView is okay). Haven't tested the Combo Box
|
|
|
|
// If want to turn this on need to make sure all the proper controls
|
|
// are wrapped for now we don't do anything
|
|
|
|
#if _SETFONTOURSELF
|
|
|
|
// if on Win95J platform need to do font substitution ourselfs.
|
|
// Review what we do on Win98
|
|
if ((VER_PLATFORM_WIN32_WINDOWS == dwPlatformID)
|
|
&& (LANG_JAPANESE == PRIMARYLANGID(langId)) )
|
|
{
|
|
SendMessage(hwnd,WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT),0);
|
|
}
|
|
|
|
#endif // _SETFONTOURSELF
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Function: IsHwndRightToLeft
|
|
//
|
|
// Synopsis: determine if hwnd is right to left.
|
|
//
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 04-02-1999 rogerg
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
BOOL IsHwndRightToLeft(HWND hwnd)
|
|
{
|
|
LONG_PTR ExStyles;
|
|
|
|
if (NULL == hwnd)
|
|
{
|
|
Assert(hwnd);
|
|
return FALSE;
|
|
}
|
|
|
|
ExStyles = GetWindowLongPtr(hwnd,GWL_EXSTYLE);
|
|
|
|
if (WS_EX_LAYOUTRTL & ExStyles)
|
|
{
|
|
// this is righ to left
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Function: GetDateFormatReadingFlags
|
|
//
|
|
// Synopsis: returns necessary flags settings for passing proper
|
|
// Reading order flags to GetDateFormat()
|
|
//
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 09-07-1999 rogerg
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
DWORD GetDateFormatReadingFlags(HWND hwnd)
|
|
{
|
|
DWORD dwDateReadingFlags = 0;
|
|
LCID locale = GetUserDefaultLCID();
|
|
|
|
// only set on NT 5.0 or higher.
|
|
if ( (VER_PLATFORM_WIN32_NT == g_OSVersionInfo.dwPlatformId)
|
|
&& ( 5 <= g_OSVersionInfo.dwMajorVersion) )
|
|
{
|
|
if ((PRIMARYLANGID(LANGIDFROMLCID(locale)) == LANG_ARABIC)
|
|
|| (PRIMARYLANGID(LANGIDFROMLCID(locale)) == LANG_HEBREW))
|
|
{
|
|
LONG_PTR dwExStyle = GetWindowLongPtr(hwnd, GWL_EXSTYLE);
|
|
|
|
if ((!!(dwExStyle & WS_EX_RTLREADING)) != (!!(dwExStyle & WS_EX_LAYOUTRTL)))
|
|
{
|
|
dwDateReadingFlags = DATE_RTLREADING;
|
|
}
|
|
else
|
|
{
|
|
dwDateReadingFlags = DATE_LTRREADING;
|
|
}
|
|
}
|
|
}
|
|
|
|
return dwDateReadingFlags;
|
|
}
|
|
|
|
#ifdef _SETSECURITY
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Function: SetRegKeySecurityEveryone
|
|
//
|
|
// Synopsis: Gives Everyone all access to the specified RegKey.
|
|
//
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 01-19-1999 rogerg
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
BOOL SetRegKeySecurityEveryone(HKEY hKeyParent,LPCWSTR lpSubKey)
|
|
{
|
|
BOOL fResult = FALSE;
|
|
HKEY hKey = NULL;
|
|
|
|
|
|
if (VER_PLATFORM_WIN32_NT != g_OSVersionInfo.dwPlatformId)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
// key must be openned with WRITE_DAC
|
|
|
|
if (ERROR_SUCCESS != RegOpenKeyExXp(hKeyParent,
|
|
lpSubKey,
|
|
REG_OPTION_OPEN_LINK, WRITE_DAC,&hKey,FALSE /*fSetSecurity*/) )
|
|
{
|
|
hKey = NULL;
|
|
}
|
|
|
|
if (hKey)
|
|
{
|
|
SECURITY_DESCRIPTOR SecurityDescriptor;
|
|
|
|
// Initialize an empty security descriptor and use this to set DACL. Since
|
|
// no DACL list in new Security Descriptor everyone will get access to the Key.
|
|
if (InitializeSecurityDescriptor(&SecurityDescriptor,SECURITY_DESCRIPTOR_REVISION))
|
|
{
|
|
if (ERROR_SUCCESS == RegSetKeySecurity(hKey,
|
|
(SECURITY_INFORMATION) DACL_SECURITY_INFORMATION,
|
|
&SecurityDescriptor) )
|
|
{
|
|
fResult = TRUE;
|
|
}
|
|
}
|
|
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
Assert(TRUE == fResult); // debugging lets find out when this fails.
|
|
return fResult;
|
|
}
|
|
|
|
#endif // _SETSECURITY
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Function: QueryHandleException
|
|
//
|
|
// Synopsis: in debug prompts user how to handle the exception
|
|
// return always handle.
|
|
//
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 01-04-1999 rogerg
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
extern DWORD g_dwDebugLogAsserts; // conform to logAsserts
|
|
|
|
BOOL QueryHandleException(void)
|
|
{
|
|
#ifndef _DEBUG
|
|
return EXCEPTION_EXECUTE_HANDLER;
|
|
#else // _DEBUG
|
|
|
|
int iMsgResult = 0;
|
|
BOOL fQueryResult = EXCEPTION_EXECUTE_HANDLER;
|
|
|
|
// if logging asserts just execute the handler
|
|
if (g_dwDebugLogAsserts)
|
|
{
|
|
return EXCEPTION_EXECUTE_HANDLER;
|
|
}
|
|
|
|
iMsgResult = MessageBoxA(NULL,
|
|
"An Exception Occured.\nWould you like to Debug this Exception?",
|
|
"Exception Failure.",
|
|
MB_YESNO | MB_SYSTEMMODAL);
|
|
|
|
if (iMsgResult == IDYES)
|
|
{
|
|
fQueryResult = EXCEPTION_CONTINUE_SEARCH;
|
|
}
|
|
|
|
// ask the User what they want to do
|
|
return fQueryResult;
|
|
|
|
#endif // _DEBUG
|
|
}
|
|
|
|
|
|
|
|
|
|
// convert a hex char to an int - used by str to guid conversion
|
|
// we wrote our own, since the ole one is slow, and requires ole32.dll
|
|
// we use ansi strings here, since guids won't get internationalized
|
|
int GetDigit(LPSTR lpstr)
|
|
{
|
|
char ch = *lpstr;
|
|
|
|
if (ch >= '0' && ch <= '9')
|
|
return(ch - '0');
|
|
if (ch >= 'a' && ch <= 'f')
|
|
return(ch - 'a' + 10);
|
|
if (ch >= 'A' && ch <= 'F')
|
|
return(ch - 'A' + 10);
|
|
return(0);
|
|
}
|
|
// walk the string, writing pairs of bytes into the byte stream (guid)
|
|
// we need to write the bytes into the byte stream from right to left
|
|
// or left to right as indicated by fRightToLeft
|
|
void ConvertField(LPBYTE lpByte,LPSTR * ppStr,int iFieldSize,BOOL fRightToLeft)
|
|
{
|
|
int i;
|
|
|
|
for (i=0;i<iFieldSize ;i++ )
|
|
{
|
|
// don't barf on the field separators
|
|
if ('-' == **ppStr) (*ppStr)++;
|
|
if (fRightToLeft == TRUE)
|
|
{
|
|
// work from right to left within the byte stream
|
|
*(lpByte + iFieldSize - (i+1)) = 16*GetDigit(*ppStr) + GetDigit((*ppStr)+1);
|
|
}
|
|
else
|
|
{
|
|
// work from left to right within the byte stream
|
|
*(lpByte + i) = 16*GetDigit(*ppStr) + GetDigit((*ppStr)+1);
|
|
}
|
|
*ppStr+=2; // get next two digit pair
|
|
}
|
|
} // ConvertField
|
|
|
|
int WideToAnsi(LPSTR lpStr,LPWSTR lpWStr,int cchStr)
|
|
{
|
|
|
|
int rval;
|
|
BOOL bDefault;
|
|
|
|
// use the default code page (CP_ACP)
|
|
// -1 indicates WStr must be null terminated
|
|
rval = WideCharToMultiByte(CP_ACP,0,lpWStr,-1,lpStr,cchStr,"-",&bDefault);
|
|
|
|
return rval;
|
|
|
|
} // WideToAnsi
|
|
int AnsiToWide(LPWSTR lpWStr,LPSTR lpStr,int cchWStr)
|
|
{
|
|
int rval;
|
|
|
|
rval = MultiByteToWideChar(CP_ACP,0,lpStr,-1,lpWStr,cchWStr);
|
|
|
|
return rval;
|
|
} // AnsiToWide
|
|
|
|
|
|
// convert the passed in string to a real GUID
|
|
// walk the guid, setting each byte in the guid to the two digit hex pair in the
|
|
// passed string
|
|
HRESULT GUIDFromString(LPWSTR lpWStr, GUID * pGuid)
|
|
{
|
|
BYTE * lpByte; // byte index into guid
|
|
int iFieldSize; // size of current field we're converting
|
|
// since its a guid, we can do a "brute force" conversion
|
|
char lpTemp[GUID_STRING_SIZE];
|
|
char *lpStr = lpTemp;
|
|
|
|
WideToAnsi(lpStr,lpWStr,GUID_STRING_SIZE);
|
|
|
|
// make sure we have a {xxxx-...} type guid
|
|
if ('{' != *lpStr) return E_FAIL;
|
|
lpStr++;
|
|
|
|
lpByte = (BYTE *)pGuid;
|
|
// data 1
|
|
iFieldSize = sizeof(unsigned long);
|
|
ConvertField(lpByte,&lpStr,iFieldSize,TRUE);
|
|
lpByte += iFieldSize;
|
|
|
|
// data 2
|
|
iFieldSize = sizeof(unsigned short);
|
|
ConvertField(lpByte,&lpStr,iFieldSize,TRUE);
|
|
lpByte += iFieldSize;
|
|
|
|
// data 3
|
|
iFieldSize = sizeof(unsigned short);
|
|
ConvertField(lpByte,&lpStr,iFieldSize,TRUE);
|
|
lpByte += iFieldSize;
|
|
|
|
// data 4
|
|
iFieldSize = 8*sizeof(unsigned char);
|
|
ConvertField(lpByte,&lpStr,iFieldSize,FALSE);
|
|
lpByte += iFieldSize;
|
|
|
|
// make sure we ended in the right place
|
|
if ('}' != *lpStr)
|
|
{
|
|
memset(pGuid,0,sizeof(GUID));
|
|
return E_FAIL;
|
|
}
|
|
|
|
return S_OK;
|
|
}// GUIDFromString
|
|
|
|
|
|
// following are routines for calling sens service directly to write HKLM data
|
|
// for us on a locked down machine
|
|
|
|
#define _SENSCALLS
|
|
#define _SENSINTERNAL
|
|
|
|
#ifdef _SENSCALLS
|
|
|
|
#include "notify.h"
|
|
|
|
// may or may not need depending on if in sensapip.h
|
|
|
|
DWORD SyncMgrExecCmd(DWORD nCmdID, DWORD nCmdOpt);
|
|
|
|
typedef enum SYNCMGRCMDEXECID
|
|
{
|
|
SYNCMGRCMDEXECID_UPDATERUNKEY = 1,
|
|
SYNCMGRCMDEXECID_RESETREGSECURITY = 2,
|
|
} SYNCMGRCMDEXECID;
|
|
|
|
|
|
#ifdef _SENSINTERNAL
|
|
// functions for if want to call sens internal without
|
|
// dependency on sensapip.lib
|
|
|
|
// these defines are from Sens common.h
|
|
#define SENS_PROTSEQ TEXT("ncalrpc")
|
|
#define SENS_ENDPOINT TEXT("senssvc")
|
|
|
|
|
|
RPC_STATUS GetSensNotifyBindHandle(RPC_BINDING_HANDLE *phSensNotify)
|
|
{
|
|
RPC_STATUS status = RPC_S_OK;
|
|
WCHAR * BindingString = NULL;
|
|
|
|
status = RpcStringBindingCompose(
|
|
NULL, // NULL ObjUuid
|
|
SENS_PROTSEQ,
|
|
NULL, // Local machine
|
|
SENS_ENDPOINT,
|
|
NULL, // No Options
|
|
&BindingString
|
|
);
|
|
|
|
if (BindingString != NULL)
|
|
{
|
|
*phSensNotify = NULL;
|
|
|
|
status = RpcBindingFromStringBinding(BindingString,phSensNotify);
|
|
|
|
if (status == RPC_S_OK)
|
|
{
|
|
RPC_SECURITY_QOS RpcSecQos;
|
|
|
|
RpcSecQos.Version= RPC_C_SECURITY_QOS_VERSION_1;
|
|
RpcSecQos.ImpersonationType= RPC_C_IMP_LEVEL_IMPERSONATE;
|
|
RpcSecQos.IdentityTracking= RPC_C_QOS_IDENTITY_DYNAMIC;
|
|
RpcSecQos.Capabilities= RPC_C_QOS_CAPABILITIES_MUTUAL_AUTH;
|
|
|
|
status= RpcBindingSetAuthInfoEx(*phSensNotify,
|
|
L"NT Authority\\System",
|
|
RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
|
|
RPC_C_AUTHN_WINNT,
|
|
NULL,
|
|
RPC_C_AUTHZ_NONE,
|
|
(RPC_SECURITY_QOS *)&RpcSecQos);
|
|
|
|
if (RPC_S_OK != status)
|
|
{
|
|
RpcBindingFree(phSensNotify);
|
|
*phSensNotify = NULL;
|
|
}
|
|
}
|
|
RpcStringFree(&BindingString);
|
|
}
|
|
|
|
return (status);
|
|
}
|
|
|
|
|
|
|
|
RPC_STATUS SyncMgrExecCmdInternal(DWORD nCmdID, DWORD nCmdOpt)
|
|
{
|
|
RPC_STATUS status;
|
|
RPC_BINDING_HANDLE hSensNotify;
|
|
|
|
status = GetSensNotifyBindHandle(&hSensNotify);
|
|
|
|
if (RPC_S_OK != status)
|
|
{
|
|
return status;
|
|
}
|
|
|
|
status = RPC_SyncMgrExecCmd(hSensNotify,nCmdID,nCmdOpt);
|
|
|
|
RpcBindingFree(&hSensNotify);
|
|
|
|
return status;
|
|
}
|
|
|
|
#endif // _SENSINTERNAL
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Function: SyncMgrExecCmdp
|
|
//
|
|
// Synopsis: helper function that actually calls into sensapip.lib
|
|
//
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 03-11-99 rogerg created
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
BOOL SyncMgrExecCmdp(DWORD nCmdID, DWORD nCmdOpt)
|
|
{
|
|
RPC_STATUS RpcStatus;
|
|
HRESULT hr;
|
|
BOOL fReturn = FALSE;
|
|
|
|
__try
|
|
{
|
|
|
|
#ifdef _SENSINTERNAL
|
|
RpcStatus = SyncMgrExecCmdInternal(nCmdID,nCmdOpt);
|
|
#else
|
|
RpcStatus = SyncMgrExecCmd(nCmdID,nCmdOpt);
|
|
#endif // _SENSINTERNAL
|
|
fReturn = (RPC_S_OK == RpcStatus ) ? TRUE: FALSE;
|
|
|
|
}
|
|
__except(QueryHandleException())
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetExceptionCode());
|
|
AssertSz(0,"Exception Calling SensApip_SyncMgrExecCmd");
|
|
}
|
|
|
|
return fReturn;
|
|
}
|
|
|
|
|
|
#endif // _SENSCALLS
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Function: SyncMgrExecCmd_UpdateRunKey
|
|
//
|
|
// Synopsis: Calls SENS Service to write or remove the run Key
|
|
//
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 03-11-99 rogerg created
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
BOOL SyncMgrExecCmd_UpdateRunKey(BOOL fSet)
|
|
{
|
|
BOOL fReturn = FALSE;
|
|
CCriticalSection cCritSect(&g_CritSectCommonLib,GetCurrentThreadId());
|
|
|
|
// IF NOT NT 5.0 or higher just return
|
|
if ( (g_OSVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT)
|
|
|| (g_OSVersionInfo.dwMajorVersion < 5))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
cCritSect.Enter(); // DoRpcSetup in Sensapip is not thread safe.
|
|
#ifdef _SENSCALLS
|
|
fReturn = SyncMgrExecCmdp(
|
|
SYNCMGRCMDEXECID_UPDATERUNKEY,fSet ? 1 : 0);
|
|
#endif // _SENSCALLS
|
|
cCritSect.Leave();
|
|
|
|
|
|
return fReturn;
|
|
}
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Function: SyncMgrExecCmd_ResetRegSecurity
|
|
//
|
|
// Synopsis: Calls SENS Service to reset the security on regkeys
|
|
// to everyone.
|
|
//
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 03-11-99 rogerg created
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
BOOL SyncMgrExecCmd_ResetRegSecurity(void)
|
|
{
|
|
BOOL fReturn = FALSE;
|
|
CCriticalSection cCritSect(&g_CritSectCommonLib,GetCurrentThreadId());
|
|
|
|
// IF NOT NT 5.0 or higher just return
|
|
if ( (g_OSVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT)
|
|
|| (g_OSVersionInfo.dwMajorVersion < 5))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
cCritSect.Enter(); // DoRpcSetup in Sensapip is not thread safe.
|
|
#ifdef _SENSCALLS
|
|
fReturn = SyncMgrExecCmdp(SYNCMGRCMDEXECID_RESETREGSECURITY,0);
|
|
#endif // _SENSCALLS
|
|
cCritSect.Leave();
|
|
|
|
return fReturn;
|
|
}
|