Windows2000/private/shell/ext/netplwiz/misc.cpp
2020-09-30 17:12:32 +02:00

809 lines
22 KiB
C++

/**
misc.cpp
Utility function implementation
History:
09/23/98: dsheldon created
**/
#include "stdafx.h"
#include "misc.h"
// Miscellanious function implementations
HRESULT ValidateName(LPCTSTR pszName)
{
// We need to use illegal fat chars, says SBurns
TCHAR* pszBadChars = ILLEGAL_FAT_CHARS;
HRESULT hrStringOK = S_OK;
while ((NULL != *pszBadChars) && (hrStringOK == S_OK))
{
if (NULL != StrChr(pszName, *pszBadChars))
{
hrStringOK = E_FAIL;
}
else
{
pszBadChars++;
}
}
if (SUCCEEDED(hrStringOK))
{
// See if the whole string is dots
TCHAR* pszChar = const_cast<TCHAR*>(pszName);
BOOL fAllDots = TRUE;
while (fAllDots && (0 != *pszChar))
{
if (TEXT('.') == *pszChar)
{
pszChar++;
}
else
{
fAllDots = FALSE;
}
}
if (fAllDots)
{
hrStringOK = E_FAIL;
}
}
return hrStringOK;
}
HRESULT ParseDisplayNameHelper(HWND hwnd, LPTSTR szPath, LPITEMIDLIST* ppidl)
{
USES_CONVERSION;
LPSHELLFOLDER psf;
HRESULT hr = SHGetDesktopFolder(&psf);
if (SUCCEEDED(hr))
{
ULONG cchEaten;
hr = psf->ParseDisplayName(hwnd, 0, T2W(szPath), &cchEaten, ppidl, NULL);
psf->Release();
}
return hr;
}
void FetchText(HWND hWndDlg, UINT uID, LPTSTR lpBuffer, DWORD dwMaxSize)
// This routine fetches the text from a control and strips off the leading and trailing whitespace
{
// Trace(TRACE_LEVEL_FLOW, TEXT("Entering FetchText\n"));
TCHAR* pszTemp;
LPTSTR pszString;
*lpBuffer = L'\0';
HWND hwndCtl = GetDlgItem(hWndDlg, uID);
if (hwndCtl)
{
int iSize = GetWindowTextLength(hwndCtl);
pszTemp = new TCHAR[iSize + 1];
if (pszTemp)
{
GetWindowText(hwndCtl, pszTemp, iSize + 1);
for (pszString = pszTemp; *pszString && (*pszString == L' ');)
pszString++;
if (!*pszString)
return;
lstrcpyn(lpBuffer, pszString, dwMaxSize);
pszString = lpBuffer + (lstrlen(lpBuffer) - 1);
while ((pszString > lpBuffer) && (*pszString == L' '))
pszString--;
*++pszString = L'\0';
delete [] pszTemp;
}
}
}
INT FetchTextLength(HWND hWndDlg, UINT uID)
{
TCHAR szBuffer[MAX_PATH];
FetchText(hWndDlg, uID, szBuffer, ARRAYSIZE(szBuffer));
return lstrlen(szBuffer);
}
HRESULT AttemptLookupAccountName(LPCTSTR szUsername, PSID* ppsid, LPTSTR szDomain, DWORD* pcchDomain, SID_NAME_USE* psUse)
{
TraceEnter(TRACE_USR_CORE, "::AttemptLookupAccountName");
HRESULT hr = S_OK;
TraceAssert(*ppsid == NULL);// Attempt to allocate and lookup a SID
// First try to find required size of SID
DWORD cbSid = 0;
DWORD cchDomain = *pcchDomain;
BOOL fSuccess = LookupAccountName(NULL, szUsername, *ppsid, &cbSid, szDomain, pcchDomain, psUse);
TraceAssert(!fSuccess);// Should have failed since we passed 0 as SID buffer size
*ppsid = LocalAlloc(0, cbSid);// Now create the SID buffer and try again
if (*ppsid != NULL)
{
*pcchDomain = cchDomain;
fSuccess = LookupAccountName(NULL, szUsername, *ppsid, &cbSid, szDomain, pcchDomain, psUse);
if (!fSuccess)
{
// Free our allocated SID
LocalFree(*ppsid);
*ppsid = NULL;
hr = E_FAIL;
}
}
else
{
TraceMsg("Couldn't LocalAlloc SID");
hr = E_OUTOFMEMORY;
}
TraceLeaveResult(hr);
}
BOOL FormatMessageString(UINT idTemplate, LPTSTR pszStrOut, DWORD cchSize, ...)
{
BOOL fResult = FALSE;
va_list vaParamList;
TCHAR szFormat[MAX_STATIC + 1];
if (LoadString(g_hInstance, idTemplate, szFormat, ARRAYSIZE(szFormat)))
{
va_start(vaParamList, cchSize);
fResult = FormatMessage(FORMAT_MESSAGE_FROM_STRING, szFormat, 0, 0, pszStrOut, cchSize, &vaParamList);
va_end(vaParamList);
}
return fResult;
}
int DisplayFormatMessage(HWND hwnd, UINT idCaption, UINT idFormatString, UINT uType, ...)
{
TraceEnter(TRACE_USR_CORE, "::DisplayFormatMessage");
int iResult = IDCANCEL;
TCHAR szError[MAX_STATIC + 1]; *szError = 0;
TCHAR szCaption[MAX_CAPTION + 1];
TCHAR szFormat[MAX_STATIC + 1]; *szFormat = 0;
// Load and format the error body
if (LoadString(g_hInstance, idFormatString, szFormat, ARRAYSIZE(szFormat)))
{
va_list arguments;
va_start(arguments, uType);
if (FormatMessage(FORMAT_MESSAGE_FROM_STRING, szFormat, 0, 0, szError, ARRAYSIZE(szError), &arguments))
{
// Load the caption
if (LoadString(g_hInstance, idCaption, szCaption, MAX_CAPTION))
{
iResult = MessageBox(hwnd, szError, szCaption, uType);
}
}
va_end(arguments);
}
TraceLeaveValue(iResult);
}
void EnableControls(HWND hwnd, const UINT* prgIDs, DWORD cIDs, BOOL fEnable)
{
DWORD i;
for (i = 0; i < cIDs; i++)
{
EnableWindow(GetDlgItem(hwnd, prgIDs[i]), fEnable);
}
}
void MakeDomainUserString(LPCTSTR szDomain, LPCTSTR szUsername, LPTSTR szDomainUser, DWORD cchBuffer)
{
*szDomainUser = 0;
if ((!szDomain) || szDomain[0] == TEXT('\0'))
{
// No domain - just use username
lstrcpyn(szDomainUser, szUsername, cchBuffer);
}
else
{
// Otherwise we have to build a DOMAIN\username string
wnsprintf(szDomainUser, cchBuffer, TEXT("%s\\%s"), szDomain, szUsername);
}
}
// From the NT knowledge base
BOOL GetCurrentUserAndDomainName(LPTSTR UserName, LPDWORD cchUserName, LPTSTR DomainName, LPDWORD cchDomainName)
{
TraceEnter(TRACE_USR_CORE, "::GetCurrentUserAndDomainName");
HANDLE hToken;
#define MY_BUFSIZE 512 // highly unlikely to exceed 512 bytes
UCHAR InfoBuffer[MY_BUFSIZE];
DWORD cbInfoBuffer = MY_BUFSIZE;
SID_NAME_USE snu;
BOOL bSuccess;
if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE, &hToken))
{
if (GetLastError() == ERROR_NO_TOKEN)
{
// attempt to open the process token, since no thread token exists
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
TraceLeaveValue(FALSE);
}
else
{
// error trying to get thread token
TraceLeaveValue(FALSE);
}
}
bSuccess = GetTokenInformation(hToken, TokenUser, InfoBuffer, cbInfoBuffer, &cbInfoBuffer);
if (!bSuccess)
{
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
// alloc buffer and try GetTokenInformation() again
CloseHandle(hToken);
TraceLeaveValue(FALSE);
}
else
{
// error getting token info
CloseHandle(hToken);
TraceLeaveValue(FALSE);
}
}
CloseHandle(hToken);
TraceLeaveValue(LookupAccountSid(NULL, ((PTOKEN_USER) InfoBuffer)->User.Sid, UserName, cchUserName, DomainName, cchDomainName, &snu));
}
HRESULT IsUserLocalAdmin(HANDLE TokenHandle, BOOL* pfIsAdmin)
{
// Pass NULL as TokenHandle to see if thread token is admin
TraceEnter(TRACE_USR_CORE, "::IsUserLocalAdmin");
TraceAssert(pfIsAdmin != NULL);
HRESULT hr;
BOOL fSuccess;
// First we must check if the current user is a local administrator; if this is the case, our dialog doesn't even display
// Get the admin localgroup SID
PSID psidAdminGroup = NULL;
SID_IDENTIFIER_AUTHORITY security_nt_authority = SECURITY_NT_AUTHORITY;
fSuccess = ::AllocateAndInitializeSid(&security_nt_authority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &psidAdminGroup);
if (fSuccess)
{
// See if the user for this process is a local admin
fSuccess = CheckTokenMembership(TokenHandle, psidAdminGroup, pfIsAdmin);
if (!fSuccess)
{
TraceMsg("CheckTokenMembership failed");
}
FreeSid(psidAdminGroup);
}
else
{
TraceMsg("AllocateAndInitializeSid failed to get local admin group SID");
}
if (fSuccess)
hr = S_OK;
else
hr = E_FAIL;
TraceLeaveResult(hr);
}
BOOL IsComputerInDomain()
{
TraceEnter(TRACE_USR_CORE, "::IsComputerInDomain");
static BOOL fInDomain = FALSE;
static BOOL fValid = FALSE;
if (!fValid)
{
fValid = TRUE;
DSROLE_PRIMARY_DOMAIN_INFO_BASIC* pdspdinfb = { 0 };
DWORD err = DsRoleGetPrimaryDomainInformation(NULL, DsRolePrimaryDomainInfoBasic, (BYTE**) &pdspdinfb);
if ((err == NO_ERROR) && (pdspdinfb != NULL))
{
if ((pdspdinfb->MachineRole == DsRole_RoleStandaloneWorkstation) || (pdspdinfb->MachineRole == DsRole_RoleStandaloneServer))
{
fInDomain = FALSE;
}
else
{
fInDomain = TRUE;
}
DsRoleFreeMemory(pdspdinfb);
}
else
{
TraceMsg("DsRoleGetPrimaryDomainInformation failed,");
}
}
TraceLeaveValue(fInDomain);
}
void OffsetControls(HWND hwnd, const UINT* prgIDs, DWORD cIDs, int dx, int dy)
{
TraceEnter(TRACE_USR_CORE, "::OffsetControlsEnableControls");
for (DWORD i = 0; i < cIDs; i++)
{
OffsetWindow(GetDlgItem(hwnd, prgIDs[i]), dx, dy);
}
TraceLeaveVoid();
}
void OffsetWindow(HWND hwnd, int dx, int dy)
{
TraceEnter(TRACE_USR_CORE, "::OffsetWindow");
RECT rc;
GetWindowRect(hwnd, &rc);
MapWindowPoints(NULL, GetParent(hwnd), (LPPOINT) &rc, 2);
OffsetRect(&rc, dx, dy);
SetWindowPos(hwnd, NULL, rc.left, rc.top, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
TraceLeaveVoid();
}
BOOL AddPropSheetPageCallback(HPROPSHEETPAGE hpsp, LPARAM lParam)
{
TraceEnter(TRACE_USR_COM, "::AddPropSheetPageCallback");
BOOL fSuccess = FALSE;
// lParam is really a ADDPROPSHEETDATA*
ADDPROPSHEETDATA* ppsd = (ADDPROPSHEETDATA*) lParam;
if (ppsd->nPages < ARRAYSIZE(ppsd->rgPages))
{
ppsd->rgPages[ppsd->nPages++] = hpsp;
fSuccess = TRUE;
}
TraceLeaveValue(fSuccess);
}
// Code to ensure only one instance of a particular window is running
CEnsureSingleInstance::CEnsureSingleInstance(LPCTSTR szCaption)
{
m_hEvent = CreateEvent(NULL, TRUE, FALSE, szCaption);// Create an event
// If any weird errors occur, default to running the instance
m_fShouldExit = FALSE;
if (NULL != m_hEvent)
{
// If our event isn't signaled, we're the first instance
m_fShouldExit = (WAIT_OBJECT_0 == WaitForSingleObject(m_hEvent, 0));
if (m_fShouldExit)
{
// app should exit after calling ShouldExit()
// Find and show the caption'd window
HWND hwndActivate = FindWindow(NULL, szCaption);
if (IsWindow(hwndActivate))
{
SetForegroundWindow(hwndActivate);
}
}
else
{
// Signal that damn event
SetEvent(m_hEvent);
}
}
}
CEnsureSingleInstance::~CEnsureSingleInstance()
{
if (NULL != m_hEvent)
{
CloseHandle(m_hEvent);
}
}
#ifdef WINNT
// Browse for a user
HRESULT BrowseForUser(HWND hwndDlg, TCHAR* pszUser, DWORD cchUser, TCHAR* pszDomain, DWORD cchDomain)
// This routine activates the appropriate Object Picker to allow
// the user to select a user
// uiTextLocation -- The resource ID of the Edit control where the selected object should be printed
{
TraceEnter(TRACE_MND_CORE, "::BrowseForUser");
HRESULT hr;
DSOP_SCOPE_INIT_INFO scopeInfo = { 0 };
scopeInfo.cbSize = sizeof(scopeInfo);
scopeInfo.flType =
DSOP_SCOPE_TYPE_USER_ENTERED_UPLEVEL_SCOPE |
DSOP_SCOPE_TYPE_USER_ENTERED_DOWNLEVEL_SCOPE |
DSOP_SCOPE_TYPE_EXTERNAL_UPLEVEL_DOMAIN |
DSOP_SCOPE_TYPE_EXTERNAL_DOWNLEVEL_DOMAIN |
DSOP_SCOPE_TYPE_ENTERPRISE_DOMAIN |
DSOP_SCOPE_TYPE_GLOBAL_CATALOG;
scopeInfo.flScope = DSOP_SCOPE_FLAG_WANT_PROVIDER_WINNT;
scopeInfo.FilterFlags.flDownlevel = DSOP_DOWNLEVEL_FILTER_USERS;
scopeInfo.FilterFlags.Uplevel.flBothModes = DSOP_FILTER_USERS;
scopeInfo.FilterFlags.Uplevel.flMixedModeOnly = 0;
scopeInfo.FilterFlags.Uplevel.flNativeModeOnly = 0;
scopeInfo.pwzADsPath = NULL;
scopeInfo.pwzDcName = NULL;
scopeInfo.hr = E_FAIL;
DSOP_INIT_INFO initInfo = { 0 };
initInfo.cbSize = sizeof(initInfo);
initInfo.pwzTargetComputer = NULL;
initInfo.cDsScopeInfos = 1;
initInfo.aDsScopeInfos = &scopeInfo;
initInfo.flOptions = 0;
IDsObjectPicker* pPicker;
hr = CoCreateInstance(CLSID_DsObjectPicker, NULL, CLSCTX_INPROC_SERVER, IID_IDsObjectPicker, (LPVOID*) &pPicker);
if (SUCCEEDED(hr))
{
hr = pPicker->Initialize(&initInfo);
if (SUCCEEDED(hr))
{
IDataObject* pdo;
hr = pPicker->InvokeDialog(hwndDlg, &pdo);
// S_FALSE indicates cancel
if ((S_OK == hr) && (NULL != pdo))
{
// Get the DS_SELECTION_LIST out of the data obj
FORMATETC fmt;
fmt.cfFormat = (CLIPFORMAT) RegisterClipboardFormat(CFSTR_DSOP_DS_SELECTION_LIST);
fmt.ptd = NULL;
fmt.dwAspect = DVASPECT_CONTENT;
fmt.lindex = -1;
fmt.tymed = TYMED_HGLOBAL;
STGMEDIUM medium = { 0 };
hr = pdo->GetData(&fmt, &medium);
if (SUCCEEDED(hr))
{
DS_SELECTION_LIST* plist;
plist = (DS_SELECTION_LIST*) GlobalLock(medium.hGlobal);
if (NULL != plist)
{
TraceAssert(1 == plist->cItems);
if (plist->cItems >= 1)
{
WCHAR szWinNTProviderName[MAX_DOMAIN + MAX_USER + 10];
lstrcpyn(szWinNTProviderName, plist->aDsSelection[0].pwzADsPath, ARRAYSIZE(szWinNTProviderName));
// Is the name in the correct format?
if (StrCmpNI(szWinNTProviderName, TEXT("WinNT://"), 8) == 0)
{
// Yes, copy over the user name and password
LPTSTR szDomain = szWinNTProviderName + 8;
LPTSTR szUser = StrChr(szDomain, TEXT('/'));
if (szUser)
{
*szUser++ = 0;
// Just in case, remove the trailing slash
LPTSTR szTrailingSlash = StrChr(szUser, TEXT('/'));
if (szTrailingSlash)
{
*szTrailingSlash = 0;
}
lstrcpyn(pszUser, szUser, cchUser);
lstrcpyn(pszDomain, szDomain, cchDomain);
hr = S_OK;
}
}
}
}
else
{
// No selection list!
hr = E_UNEXPECTED;
}
GlobalUnlock(medium.hGlobal);
}
pdo->Release();
}
}
pPicker->Release();
}
TraceLeaveResult(hr);
}
#endif // WINNT
HFONT GetIntroFont(HWND hwnd)
// create the intro/done large font for wizards
{
static HFONT _hfontIntro;
if (!_hfontIntro)
{
TCHAR szBuffer[64];
NONCLIENTMETRICS ncm = { 0 };
LOGFONT lf;
ncm.cbSize = SIZEOF(ncm);
SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
lf = ncm.lfMessageFont;
LoadString(GLOBAL_HINSTANCE, IDS_TITLEFONTNAME, lf.lfFaceName, ARRAYSIZE(lf.lfFaceName));
lf.lfWeight = FW_BOLD;
LoadString(GLOBAL_HINSTANCE, IDS_TITLEFONTSIZE, szBuffer, ARRAYSIZE(szBuffer));
lf.lfHeight = 0 - (GetDeviceCaps(NULL, LOGPIXELSY) * StrToInt(szBuffer) / 72);
_hfontIntro = CreateFontIndirect(&lf);
}
return _hfontIntro;
}
void DomainUserString_GetParts(LPCTSTR szDomainUser, LPTSTR szUser, DWORD cchUser, LPTSTR szDomain, DWORD cchDomain)
{
// Check for invalid args
if ((!szUser) || (!szDomain) || (!cchUser) || (!cchDomain))
{
return;
}
else
{
*szUser = 0;
*szDomain = 0;
TCHAR szTemp[MAX_USER + MAX_DOMAIN + 2];
lstrcpyn(szTemp, szDomainUser, ARRAYSIZE(szTemp));
LPTSTR szWhack = StrChr(szTemp, TEXT('\\'));
if (!szWhack)
{
// Also check for forward slash to be friendly
szWhack = StrChr(szTemp, TEXT('/'));
}
if (szWhack)
{
LPTSTR szUserPointer = szWhack + 1;
*szWhack = 0;
// Temp now points to domain.
lstrcpyn(szDomain, szTemp, cchDomain);
lstrcpyn(szUser, szUserPointer, cchUser);
}
else
{
// Don't have a domain name - just a username
lstrcpyn(szUser, szTemp, cchUser);
}
}
}
LPITEMIDLIST GetComputerParent()
{
USES_CONVERSION;
LPITEMIDLIST pidl = NULL;
IShellFolder *psfDesktop;
HRESULT hres = SHGetDesktopFolder(&psfDesktop);
if (SUCCEEDED(hres))
{
TCHAR szName[MAX_PATH];
lstrcpy(szName, TEXT("\\\\"));
LPTSTR pszAfterWhacks = szName + 2;
DWORD cchName = MAX_PATH - 2;
if (GetComputerName(pszAfterWhacks, &cchName))
{
hres = psfDesktop->ParseDisplayName(NULL, NULL, T2W(szName), NULL, &pidl, NULL);
if (SUCCEEDED(hres))
{
ILRemoveLastID(pidl);
}
}
else
{
hres = E_FAIL;
}
psfDesktop->Release();
}
if (FAILED(hres))
{
pidl = NULL;
}
return pidl;
}
int CALLBACK ShareBrowseCallback(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
{
TraceEnter(TRACE_MND_CORE, "::ShareBrowseCallback");
switch (uMsg)
{
case BFFM_INITIALIZED:
{
// Try to set the selected item according to the path string passed in lpData
LPTSTR pszPath = (LPTSTR) lpData;
if (pszPath && pszPath[0])
{
int i = lstrlen(pszPath) - 1;
if ((pszPath[i] == TEXT('\\')) || (pszPath[i] == TEXT('/')))
{
pszPath[i] = 0;
}
SendMessage(hwnd, BFFM_SETSELECTION, (WPARAM) TRUE, (LPARAM) (LPTSTR) pszPath);
}
else
{
// Try to get the computer's container folder
LPITEMIDLIST pidl = GetComputerParent();
if (pidl)
{
SendMessage(hwnd, BFFM_SETSELECTION, (WPARAM) FALSE, (LPARAM) (LPTSTR) pidl);
ILFree(pidl);
}
}
}
break;
case BFFM_SELCHANGED:
// Disable OK if this isn't a UNC path type thing
{
TCHAR szPath[MAX_PATH];
LPITEMIDLIST pidl = (LPITEMIDLIST) lParam;
BOOL fEnableOk = FALSE;
if (SHGetPathFromIDList(pidl, szPath))
{
fEnableOk = PathIsUNC(szPath);
}
SendMessage(hwnd, BFFM_ENABLEOK, (WPARAM) 0, (LPARAM) fEnableOk);
}
break;
}
TraceLeaveValue(0);
}
void RemoveControl(HWND hwnd, UINT idControl, UINT idNextControl, const UINT* prgMoveControls, DWORD cControls, BOOL fShrinkParent)
{
HWND hwndControl = GetDlgItem(hwnd, idControl);
HWND hwndNextControl = GetDlgItem(hwnd, idNextControl);
RECT rcControl;
RECT rcNextControl;
if (hwndControl && GetWindowRect(hwndControl, &rcControl) && hwndNextControl && GetWindowRect(hwndNextControl, &rcNextControl))
{
int dx = rcControl.left - rcNextControl.left;
int dy = rcControl.top - rcNextControl.top;
MoveControls(hwnd, prgMoveControls, cControls, dx, dy);
if (fShrinkParent)
{
RECT rcParent;
if (GetWindowRect(hwnd, &rcParent))
{
MapWindowPoints(NULL, GetParent(hwnd), (LPPOINT) &rcParent, 2);
rcParent.right += dx;
rcParent.bottom += dy;
SetWindowPos(hwnd, NULL, 0, 0, RECTWIDTH(rcParent), RECTHEIGHT(rcParent), SWP_NOMOVE | SWP_NOZORDER);
}
}
EnableWindow(hwndControl, FALSE);
ShowWindow(hwndControl, SW_HIDE);
}
}
void MoveControls(HWND hwnd, const UINT* prgControls, DWORD cControls, int dx, int dy)
{
DWORD iControl;
for (iControl = 0; iControl < cControls; iControl++)
{
HWND hwndControl = GetDlgItem(hwnd, prgControls[iControl]);
RECT rcControl;
if (hwndControl && GetWindowRect(hwndControl, &rcControl))
{
MapWindowPoints(NULL, hwnd, (LPPOINT) &rcControl, 2);
SetWindowPos(hwndControl, NULL, rcControl.left + dx, rcControl.top + dy, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
}
}
}
void EnableDomainForUPN(HWND hwndUsername, HWND hwndDomain)
/*
* PURPOSE: Enables or disables the domain text box based on whether or not a UPN-style name is typed into the username box.
* HISTORY:
* 04-17-1998 dsheldon created
*/
{
BOOL fEnable;
// Get the string the user is typing
TCHAR* pszLogonName;
int cchBuffer = (int) SendMessage(hwndUsername, WM_GETTEXTLENGTH, 0, 0) + 1;
pszLogonName = (TCHAR*) LocalAlloc(0, cchBuffer * sizeof(TCHAR));
if (pszLogonName != NULL)
{
SendMessage(hwndUsername, WM_GETTEXT, (WPARAM) cchBuffer, (LPARAM) pszLogonName);
// Disable the domain combo if the user is using a UPN (if there is a "@") - ie foo@microsoft.com
fEnable = (NULL == StrChr(pszLogonName, TEXT('@')));
EnableWindow(hwndDomain, fEnable);
LocalFree(pszLogonName);
}
}