Leaked source code of windows server 2003
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.
 
 
 
 
 
 

638 lines
17 KiB

// util.cpp - miscelaneous helper functions
#include "stdafx.h"
#include "util.h"
// Net API stuffs
#include <dsgetdc.h>
#include <wtsapi32.h>
#include <rassapi.h>
#include <shlobj.h>
#include <lmaccess.h>
#include <lmapibuf.h>
#include <lmshare.h>
#include <lmserver.h>
// ldap/adsi includes
#include <iads.h>
#include <adshlp.h>
#include <adsiid.h>
extern HWND g_hwndMain;
LRESULT CALLBACK EventCBWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
// Event callback window class object
CMsgWindowClass EventCBWndClass(L"OnEventCB", EventCBWndProc);
HBITMAP GetBitmapFromStrip(HBITMAP hbmStrip, int nPos, int cSize)
{
HBITMAP hbmNew = NULL;
// Create src & dest DC
HDC hdc = GetDC(NULL);
if( hdc == NULL ) return NULL;
HDC hdcSrc = CreateCompatibleDC(hdc);
HDC hdcDst = CreateCompatibleDC(hdc);
if( hdcSrc && hdcDst )
{
hbmNew= CreateCompatibleBitmap (hdc, cSize, cSize);
if( hbmNew )
{
// Select src & dest bitmaps into DCs
HBITMAP hbmSrcOld = (HBITMAP)SelectObject(hdcSrc, (HGDIOBJ)hbmStrip);
HBITMAP hbmDstOld = (HBITMAP)SelectObject(hdcDst, (HGDIOBJ)hbmNew);
// Copy selected image from source
BitBlt(hdcDst, 0, 0, cSize, cSize, hdcSrc, cSize * nPos, 0, SRCCOPY);
// Restore selections
if( hbmSrcOld ) SelectObject(hdcSrc, (HGDIOBJ)hbmSrcOld);
if( hbmDstOld ) SelectObject(hdcDst, (HGDIOBJ)hbmDstOld);
}
DeleteDC(hdcSrc);
DeleteDC(hdcDst);
}
ReleaseDC(NULL, hdc);
return hbmNew;
}
void ConfigSingleColumnListView(HWND hwndListView)
{
if( !hwndListView || !::IsWindow(hwndListView) ) return;
RECT rc;
BOOL bStat = GetClientRect(hwndListView, &rc);
ASSERT(bStat);
LV_COLUMN lvc;
lvc.mask = LVCF_WIDTH | LVCF_SUBITEM;
lvc.cx = rc.right - rc.left - GetSystemMetrics(SM_CXVSCROLL);
lvc.iSubItem = 0;
int iCol = ListView_InsertColumn(hwndListView, 0, &lvc);
ASSERT(iCol == 0);
ListView_SetExtendedListViewStyleEx(hwndListView, LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT);
}
//--------------------------------------------------------------------------
// EnableDlgItem
//
// Enables or disables a dialog control. If the control has the focus when
// it is disabled, the focus is moved to the next control
//--------------------------------------------------------------------------
void EnableDlgItem(HWND hwndDialog, int iCtrlID, BOOL bEnable)
{
if( !hwndDialog || !::IsWindow(hwndDialog) ) return;
HWND hWndCtrl = ::GetDlgItem(hwndDialog, iCtrlID);
if( !hWndCtrl || !::IsWindow(hWndCtrl) ) return;
if( !bEnable && ::GetFocus() == hWndCtrl )
{
HWND hWndNextCtrl = ::GetNextDlgTabItem(hwndDialog, hWndCtrl, FALSE);
if( hWndNextCtrl != NULL && hWndNextCtrl != hWndCtrl )
{
::SetFocus(hWndNextCtrl);
}
}
::EnableWindow(hWndCtrl, bEnable);
}
//--------------------------------------------------------------------------
// GetItemText
//
// Read text from a control and return it in a string
//---------------------------------------------------------------------------
void GetItemText(HWND hwnd, tstring& strText)
{
strText = _T("");
if( !hwnd || !::IsWindow(hwnd) ) return;
int nLen = ::GetWindowTextLength(hwnd);
if( nLen == 0 ) return;
LPWSTR pszTemp = new WCHAR[nLen + 1];
if( !pszTemp ) return;
int nLen1 = ::GetWindowText( hwnd, pszTemp, (nLen + 1) );
ASSERT(nLen == nLen1);
strText = pszTemp;
delete [] pszTemp;
}
//------------------------------------------------------------------------
// RemoveSpaces
//
// Remove spaces from null-terminated string
//-------------------------------------------------------------------------
void RemoveSpaces(LPWSTR pszBuf)
{
if( !pszBuf ) return;
WCHAR* pszDest = pszBuf;
do
{
if( *pszBuf != L' ' ) *(pszDest++) = *pszBuf;
}
while( *(pszBuf++) );
}
//-------------------------------------------------------------------------
// EscapeSlashes
//
// Add escape char '\' in front of each forward slash '/'
//-------------------------------------------------------------------------
void EscapeSlashes(LPCWSTR pszIn, tstring& strOut)
{
strOut = _T("");
if( !pszIn ) return;
strOut.reserve( wcslen(pszIn) + 8 );
while( *pszIn != 0 )
{
if( *pszIn == L'/' )
strOut += L'\\';
strOut += *(pszIn++);
}
}
HRESULT ReplaceParameters( tstring& str, CParamLookup& lookup, BOOL bRetainMarkers )
{
// Do for each parameter $<param name>
int posParam = 0;
while( (posParam = str.find(L"$<", posParam)) != tstring::npos )
{
// skip over the '$<'
posParam += 2;
// find terminating ">"
int posParamEnd = str.find(L">", posParam);
if( posParamEnd == tstring::npos )
return E_FAIL;
// Get replacement string from lookup function
tstring strValue;
if( !lookup(str.substr(posParam, posParamEnd - posParam), strValue) )
return E_FAIL;
// replace either paramter or parameter and markers
// and advance pointer to first char after substitution
if( bRetainMarkers )
{
str.replace(posParam, posParamEnd - posParam, strValue);
posParam += strValue.size();
}
else
{
str.replace(posParam - 2, posParamEnd - posParam + 3, strValue);
posParam += strValue.size() - 2;
}
}
return S_OK;
}
VARIANT GetDomainPath( LPCTSTR lpServer )
{
VARIANT vDomain;
::VariantInit(&vDomain);
if( !lpServer ) return vDomain;
// get the domain information
TCHAR pString[MAX_PATH*2];
_sntprintf( pString, (MAX_PATH*2)-1, L"LDAP://%s/rootDSE", lpServer );
CComPtr<IADs> pDS = NULL;
HRESULT hr = ::ADsGetObject(pString, IID_IADs, (void**)&pDS);
ASSERT(hr == S_OK);
if( hr != S_OK ) return vDomain;
CComBSTR bstrProp = L"defaultNamingContext";
hr = pDS->Get( bstrProp, &vDomain );
ASSERT(hr == S_OK);
return vDomain;
}
HRESULT ExpandDCWildCard( tstring& str )
{
int posParam = 0;
const tstring strKey = _T("DC=*");
if( (posParam = str.find(strKey.c_str(), posParam)) != tstring::npos )
{
CComVariant vDomain;
HRESULT hr = S_OK;
CString csDns = L"";
PDOMAIN_CONTROLLER_INFO pDCI = NULL;
hr = DsGetDcName(NULL, NULL, NULL, NULL, DS_DIRECTORY_SERVICE_REQUIRED | DS_RETURN_DNS_NAME, &pDCI);
if( (hr == S_OK) && (pDCI != NULL) )
{
csDns = pDCI->DomainName;
NetApiBufferFree (pDCI);
pDCI = NULL;
}
vDomain = GetDomainPath((LPCTSTR)csDns);
if( vDomain.vt == VT_BSTR )
{
// Get replacement string from lookup function
tstring strValue = vDomain.bstrVal;
// We replace the whole DC=* with the full DC=XYZ,DC=COM
str.replace(posParam, strKey.size(), strValue);
}
else
{
return E_FAIL;
}
}
return S_OK;
}
HRESULT ExpandEnvironmentParams( tstring& strIn, tstring& strOut )
{
// if no % then just return inout string
if( strIn.find(L"%") == tstring::npos )
{
strOut = strIn;
return S_OK;
}
DWORD dwSize = strIn.size() * 2;
while( TRUE )
{
WCHAR* pszBuf = new WCHAR [dwSize];
if( !pszBuf ) return E_OUTOFMEMORY;
ZeroMemory( pszBuf, (dwSize * sizeof(WCHAR)) );
DWORD dwReqSize = ExpandEnvironmentStrings(strIn.c_str(), pszBuf, dwSize);
if( dwReqSize <= dwSize )
{
strOut = pszBuf;
delete [] pszBuf;
return S_OK;
}
delete [] pszBuf;
dwSize = dwReqSize;
}
}
tstring StrLoadString( UINT uID )
{
tstring strRet = _T("");
HINSTANCE hInst = _Module.GetResourceInstance();
INT iSize = MAX_PATH;
TCHAR* psz = new TCHAR[iSize];
if( !psz ) return strRet;
while( LoadString(hInst, uID, psz, iSize) == (iSize - 1) )
{
iSize += MAX_PATH;
delete[] psz;
psz = NULL;
psz = new TCHAR[iSize];
if( !psz ) return strRet;
}
strRet = psz;
delete[] psz;
return strRet;
}
HRESULT StringTableWrite(IStringTable* pStringTable, LPCWSTR psz, MMC_STRING_ID* pID)
{
VALIDATE_POINTER(pStringTable);
VALIDATE_POINTER(psz);
VALIDATE_POINTER(pID);
MMC_STRING_ID newID = 0;
// if non-null string store it and get the new ID
if( psz[0] != 0 )
{
HRESULT hr = pStringTable->AddString(psz, &newID);
ASSERT(SUCCEEDED(hr) && newID != 0);
RETURN_ON_FAILURE(hr);
}
// If had an old string ID, free it
if( *pID != 0 )
{
HRESULT hr = pStringTable->DeleteString(*pID);
ASSERT(SUCCEEDED(hr));
}
*pID = newID;
return S_OK;
}
HRESULT StringTableRead(IStringTable* pStringTable, MMC_STRING_ID ID, tstring& str)
{
VALIDATE_POINTER(pStringTable);
ASSERT(ID != 0);
// get the length of the string from the string table
DWORD cb = 0;
HRESULT hr = pStringTable->GetStringLength(ID, &cb);
RETURN_ON_FAILURE(hr);
// alloc stack buffer (+1 for terminating null)
cb++;
LPWSTR pszBuf = new WCHAR[cb + 1];
if( !pszBuf ) return E_OUTOFMEMORY;
// read the string
DWORD cbRead = 0;
hr = pStringTable->GetString(ID, cb, pszBuf, &cbRead);
RETURN_ON_FAILURE(hr);
ASSERT(cb == cbRead + 1);
str = pszBuf;
delete [] pszBuf;
return S_OK;
}
int DisplayMessageBox(HWND hWnd, UINT uTitleID, UINT uMsgID, UINT uStyle, LPCWSTR pvParam1, LPCWSTR pvParam2)
{
ASSERT(hWnd != NULL || g_hwndMain != NULL);
if( hWnd == NULL && g_hwndMain == NULL )
return 0;
// Display error message
CString strTitle;
strTitle.LoadString(uTitleID);
CString strMsgFmt;
strMsgFmt.LoadString(uMsgID);
CString strMsg;
strMsg.Format(strMsgFmt, pvParam1, pvParam2);
return MessageBox(hWnd ? hWnd : g_hwndMain, strMsg, strTitle, uStyle);
}
HRESULT ValidateFile( tstring& strFilePath )
{
if( strFilePath.empty() ) return E_INVALIDARG;
tstring strTmp;
ExpandEnvironmentParams(strFilePath, strTmp);
// if file path includes a directory or drive specifier then check the specific file
// then look for that specific file
if( strFilePath.find_first_of(L"\\:") != tstring::npos )
{
DWORD dwAttr = GetFileAttributes(strTmp.c_str());
if( (dwAttr != INVALID_FILE_ATTRIBUTES) && !(dwAttr & FILE_ATTRIBUTE_DIRECTORY) )
return S_OK;
}
else
{
// else search for file in standard locations
DWORD dwLen = SearchPath(NULL, strTmp.c_str(), NULL, 0, NULL, NULL);
if( dwLen > 0 )
return S_OK;
}
return E_FAIL;
}
HRESULT ValidateDirectory( tstring& strDir )
{
if( strDir.empty() ) return E_INVALIDARG;
tstring strTmp;
ExpandEnvironmentParams(strDir, strTmp);
DWORD dwAttr = GetFileAttributes( strTmp.c_str() );
if( (dwAttr != INVALID_FILE_ATTRIBUTES) && (dwAttr & FILE_ATTRIBUTE_DIRECTORY) )
return S_OK;
else
return E_FAIL;
}
/////////////////////////////////////////////////////////////////////////
// Event-triggered callbacks
//
// The main thread can request that a callback be made when an object
// is signaled by calling function CallbackOnEvent. The function starts
// a monitor thread which does a wait on the object. When the object is
// signaled, the thread posts a message to a callback window and exits.
// The callback window, which is owned by the main thread, then executes
// the callback function.
//
// the callback window
static HWND hwndCallback = NULL; // callback window
#define MSG_EVENTCALLBACK (WM_USER+100) // callback message
struct EVENTCB_INFO // callback info struct
{
CEventCallback* pCallback; // callback object to execute
HANDLE hWaitObj; // object that triggers the callback
HANDLE hThread; // monitoring thread
};
//---------------------------------------------------------------------------
// EventCBThdProc
//
// This is the monitoring thread procedure. It just does a wait for the object
// signal, then posts a callback message to the callback window.
//
// Inputs: pVoid ptr to EVENTCB_INFO struct (cast to void*)
//----------------------------------------------------------------------------
static DWORD WINAPI EventCBThdProc(void* pVoid )
{
if( !pVoid ) return 0;
EVENTCB_INFO* pInfo = reinterpret_cast<EVENTCB_INFO*>(pVoid);
ASSERT(pInfo->hWaitObj != NULL && pInfo->pCallback != NULL);
DWORD dwStat = WaitForSingleObject(pInfo->hWaitObj, INFINITE);
ASSERT(dwStat == WAIT_OBJECT_0);
ASSERT(hwndCallback != NULL);
::PostMessage(hwndCallback, MSG_EVENTCALLBACK, reinterpret_cast<WPARAM>(pInfo), NULL);
return 0;
}
//----------------------------------------------------------------------------------
// EventCBWndProc
//
// This is the callback window's WndProc. When it gets a callback message it
// executes the callback function then destroys the callback function object and
// the callback info struct.
//----------------------------------------------------------------------------------
static LRESULT CALLBACK EventCBWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if( uMsg == MSG_EVENTCALLBACK )
{
EVENTCB_INFO* pInfo = reinterpret_cast<EVENTCB_INFO*>(wParam);
if( !pInfo ) return 0;
if( pInfo->pCallback )
{
pInfo->pCallback->Execute();
delete pInfo->pCallback;
pInfo->pCallback = NULL;
}
delete pInfo;
pInfo = NULL;
return 0;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
//-----------------------------------------------------------------------------------
// CallbackOnEvent
//
// This function accepts an event-triggered callback request. It starts a monitoring
// thread which will cause the callback when the specified object signals.
//
// Inputs: HANDLE hWaitObj Handle of object to wait on
// CEventCallback Callback function object (with single Execute method)
//
// Outputs: HRESULT Result of event trigger setup
//
// Note: The CEventCallback object is destroyed after the callback is executed.
//-----------------------------------------------------------------------------------
HRESULT CallbackOnEvent(HANDLE hWaitObj, CEventCallback* pCallback)
{
ASSERT(pCallback != NULL);
// Create callback window the first time
if( hwndCallback == NULL )
{
hwndCallback = EventCBWndClass.Window();
if( hwndCallback == NULL )
return E_FAIL;
}
// Create a callback info object
EVENTCB_INFO* pInfo = new EVENTCB_INFO;
if( pInfo == NULL )
return E_OUTOFMEMORY;
pInfo->hWaitObj = hWaitObj;
pInfo->pCallback = pCallback;
// Start monitor thread passing it the callback info
pInfo->hThread = CreateThread(NULL, NULL, EventCBThdProc, pInfo, 0, NULL);
if( pInfo->hThread == NULL )
{
delete pInfo;
return E_FAIL;
}
return S_OK;
}
BOOL ModifyStyleEx(HWND hWnd, DWORD dwRemove, DWORD dwAdd, UINT nFlags)
{
if( !hWnd || !::IsWindow(hWnd) ) return FALSE;
DWORD dwStyle = ::GetWindowLong(hWnd, GWL_EXSTYLE);
DWORD dwNewStyle = (dwStyle & ~dwRemove) | dwAdd;
if( dwStyle == dwNewStyle )
return FALSE;
::SetWindowLong(hWnd, GWL_EXSTYLE, dwNewStyle);
if( nFlags != 0 )
{
::SetWindowPos(hWnd, NULL, 0, 0, 0, 0,
SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | nFlags);
}
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////////////
// CMsgWindowClass
HWND CMsgWindowClass::Window()
{
ASSERT(m_pszName != NULL && m_pWndProc != NULL);
if( m_hWnd != NULL )
return m_hWnd;
// Create callback window the first time (m_hwndCB is static)
if( m_atom == NULL )
{
// first register window class
WNDCLASS wc;
memset(&wc, 0, sizeof(WNDCLASS));
wc.lpfnWndProc = m_pWndProc;
wc.hInstance = _Module.GetModuleInstance();
wc.lpszClassName = m_pszName;
m_atom = RegisterClass(&wc);
DWORD dwError = GetLastError();
ASSERT(m_atom);
}
if( m_atom )
{
m_hWnd = ::CreateWindow(MAKEINTATOM(m_atom), L"", WS_DISABLED, 0,0,0,0,
NULL, NULL, _Module.GetModuleInstance(), NULL);
ASSERT(m_hWnd);
}
return m_hWnd;
}