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.
 
 
 
 
 
 

965 lines
26 KiB

/*++
Microsoft Windows
Copyright (C) Microsoft Corporation, 1981 - 1999
Module Name:
utils.cpp
Abstract:
Author:
Rahul Thombre (RahulTh) 4/30/1998
Revision History:
4/30/1998 RahulTh
Created this module.
10/12/98 RahulTh
Better error handling capabilities added : CError etc.
--*/
#include "precomp.hxx"
#include <irmonftp.h>
LONG g_lLinkOnDesktop = 0;
//the path of the desktop folder.
TCHAR g_lpszDesktopFolder[MAX_PATH];
//the path to the send to folder;
TCHAR g_lpszSendToFolder[MAX_PATH];
BOOL GetShortcutInfo (
LPTSTR lpszShortcutName,
ULONG ShortCutNameLength,
LPTSTR lpszFullExeName,
ULONG ExeNameLength
);
BOOL GetSendToInfo (
LPTSTR lpszSendToName,
ULONG SendToNameLength,
LPTSTR lpszFullExeName,
ULONG FullExeNameLength
);
#define VALIDATE_SEND_COOKIE(cookie) \
{ \
__try \
{ \
*pStatus = ERROR_INVALID_DATA; \
if (MAGIC_ID != ((CSendProgress *)cookie)->m_dwMagicID) \
return; \
*pStatus = ERROR_SUCCESS; \
} \
__except (EXCEPTION_EXECUTE_HANDLER) \
{ \
return; \
} \
}
//
// wireless link specific errors
//
ERROR_TO_STRING_ID g_ErrorToStringId[] =
{
{ERROR_IRTRANP_OUT_OF_MEMORY, IDS_ERROR_NO_MEMORY},
{ERROR_IRTRANP_DISK_FULL, IDS_ERROR_DISK_FULL},
{ERROR_SCEP_CANT_CREATE_FILE, IDS_ERROR_DISK_FULL},
{ERROR_SCEP_ABORT, IDS_ERROR_ABORTED},
{ERROR_SCEP_INVALID_PROTOCOL, IDS_ERROR_PROTOCOL},
{ERROR_SCEP_PDU_TOO_LARGE, IDS_ERROR_PROTOCOL},
{ERROR_BFTP_INVALID_PROTOCOL, IDS_ERROR_PROTOCOL},
{ERROR_BFTP_NO_MORE_FRAGMENTS, IDS_ERROR_PROTOCOL},
{ERROR_SUCCESS, -1}
};
////////////////////////////////////////////////////////////////////
//
//Miscellaneous useful functions
//
///////////////////////////////////////////////////////////////////
int ParseFileNames (TCHAR* pszInString, TCHAR* pszFilesList, int& iCharCount)
{
ASSERT(pszFilesList != NULL);
ASSERT(pszInString != NULL);
BOOL fInQuotes = FALSE;
BOOL fIgnoreSpaces = FALSE;
TCHAR* pszSource = pszInString;
TCHAR* pszTarget = pszFilesList;
int iFileCount = 0;
TCHAR curr;
//ignore leading whitespaces
while(' ' == *pszSource || '\t' == *pszSource)
pszSource++;
iCharCount = 0;
*pszTarget = '\0'; //precautionary measures
if ('\0' == *pszSource) //special case : if this was an empty string, return 0
return iFileCount;
//parse the string to get filenames
while(curr = *pszSource)
{
if('\"' == curr)
{
fInQuotes = fInQuotes?FALSE:TRUE;
}
else if(' ' == curr && !fInQuotes)
{
if(!fIgnoreSpaces)
{
*pszTarget++ = 0;
iFileCount++;
iCharCount++;
fIgnoreSpaces = TRUE;
}
}
else
{
*pszTarget++ = curr;
iCharCount++;
fIgnoreSpaces = FALSE;
}
pszSource++;
}
if(' ' != *(pszSource-1)) //if there was no trailing space
{
*pszTarget++ = '\0'; //then the last file was not accounted for.
iCharCount++; //so we do it here
iFileCount++;
}
*pszTarget++ = '\0'; //should have 2 terminating nulls
iCharCount++;
return iFileCount;
}
//+--------------------------------------------------------------------------
//
// Function: GetIRRegVal
//
// Synopsis: gets the specified registry value from the IR subtree in HKCU
//
// Arguments: [in] szValName : the name of the value.
// [in] dwDefVal : the default value to be returned if the read
// from the registry fails or if the value is
// missing.
//
// Returns: the actual value stored in the registry or the default value
// if the read fails.
//
// History: 10/27/1999 RahulTh created
//
// Notes:
//
//---------------------------------------------------------------------------
DWORD GetIRRegVal (LPCTSTR szValName, DWORD dwDefVal)
{
HKEY hftKey = NULL;
DWORD iSize = sizeof(DWORD);
DWORD data = 0;
DWORD Status;
RegOpenKeyEx (HKEY_CURRENT_USER, TEXT("Control Panel\\Infrared\\File Transfer"),
0, KEY_READ, &hftKey);
if (!hftKey)
return dwDefVal;
Status = RegQueryValueEx (hftKey, szValName, NULL, NULL,
(LPBYTE)&data, &iSize);
if (ERROR_SUCCESS != Status)
data = dwDefVal;
RegCloseKey (hftKey);
return data;
}
TCHAR* GetFullPathnames (TCHAR* pszPath, //directory in which the files are located
const TCHAR* pszFilesList, //NULL separated list of filenames
int iFileCount, //number of files in pszFilesList
int& iCharCount //number of characters in pszFilesList. also returns the number of chars in the return string
)
{
int iChars;
int iPathLen = lstrlen(pszPath);
if (pszPath[iPathLen - 1] != '\\') //append a '\' character to the path if not already present
{
pszPath[iPathLen++] = '\\';
pszPath[iPathLen] = '\0';
}
int iSize = (iChars = iFileCount*iPathLen + iCharCount);
TCHAR* pszFilePathList = new TCHAR[iSize];
TCHAR* pszTemp = pszFilePathList;
int iLen;
while(*pszFilesList)
{
//
// start with the path
//
StringCchCopy(pszTemp, iSize ,pszPath);
//
// add on the file name
//
StringCchCat(pszTemp, iSize, pszFilesList);
//
// move the next files name
//
iLen = lstrlen(pszFilesList);
pszFilesList += iLen + 1;
//
// move past the current path and file name
//
iLen = lstrlen(pszTemp);
pszTemp += iLen + 1;
iSize-=iLen;
}
*pszTemp = '\0'; //should be terminated by 2 null characters
iCharCount = (int)(pszTemp - pszFilePathList) + 1; //return the actual char count of this string
return pszFilePathList;
}
TCHAR* ProcessOneFile (TCHAR* pszPath, //directory in which the files are located
const TCHAR* pszFilesList, //NULL separated list of filenames
int iFileCount, //number of files in pszFilesList
int& iCharCount //number of characters in pszFilesList. also returns the number of characters in the return string
)
{
int iFileLen, iPathLen;
TCHAR* pszFullFileName;
iFileLen = lstrlen (pszFilesList);
iPathLen = lstrlen (pszPath);
ASSERT (iFileLen);
ASSERT (iPathLen);
if(':' == pszFilesList[1] //this is an absolute path starting with the drive letter;
|| ('\\' == pszFilesList[0] && '\\' == pszFilesList[1]) //UNC path
)
{
pszFullFileName = new TCHAR [iFileLen + 2];
StringCchCopy(pszFullFileName, iFileLen + 2, pszFilesList);
pszFullFileName[iFileLen + 1] = '\0'; //we need to have 2 terminating nulls
iCharCount = iFileLen + 2;
}
else if('\\' == pszFilesList[0]) //path relative to the root
{
iCharCount = iFileLen + 2 /*drive letter and colon*/ + 2 /*terminating nulls*/;
pszFullFileName = new TCHAR [iCharCount];
pszFullFileName[0] = pszPath[0];
pszFullFileName[1] = pszPath[1];
StringCchCopy(pszFullFileName + 2, iCharCount-2, pszFilesList);
pszFullFileName[iCharCount - 1] = '\0'; //we need to have 2 terminating nulls
}
else //ordinary file name
{
iCharCount = iPathLen + iFileLen + 2; //2 terminating nulls
//
// sometimes the path does not have a \ at the end, so we need to add these ourselves
//
iCharCount += ('\\' == pszPath[iPathLen - 1])?0:1;
pszFullFileName = new TCHAR [iCharCount];
//
// put in the path
//
StringCchCopy(pszFullFileName,iCharCount, pszPath);
if ('\\' != pszPath[iPathLen - 1]) {
//
// we need to add the \ ourselves
//
StringCchCat(pszFullFileName,iCharCount,TEXT("\\"));
}
//
// add on the file name
//
StringCchCat(pszFullFileName,iCharCount,pszFilesList);
pszFullFileName[iCharCount - 1] = '\0'; //2 terminating nulls
}
return pszFullFileName;
}
//+--------------------------------------------------------------------------
//
// Function: GetPrimaryAppWindow
//
// Synopsis: gets the handle to the main window of an existing instance of
// irftp
//
// Arguments: none.
//
// Returns: handle to the window if it finds one. otherwise NULL.
//
// History: 6/30/1999 RahulTh created
//
// Notes:
//
//---------------------------------------------------------------------------
HWND GetPrimaryAppWindow (void)
{
HWND hwnd = NULL;
int i = 1;
//try to find the window for 5 seconds.
do
{
hwnd = FindWindow (L"#32770", //the dialog class
MAIN_WINDOW_TITLE);
if (hwnd)
break;
Sleep (500);
} while ( i++ <= 10 );
return hwnd;
}
///////////////////////////////////////////////////////////////////////////////////////
// RPC Server functions
//////////////////////////////////////////////////////////////////////////////////////
void _PopupUI (handle_t Binding)
{
int nResponse;
appController->PostMessage(WM_APP_TRIGGER_UI);
return;
}
void _InitiateFileTransfer (handle_t Binding, ULONG lSize, wchar_t __RPC_FAR lpszFilesList[])
{
COPYDATASTRUCT cStruct;
cStruct.dwData = lSize;
cStruct.cbData = lSize * sizeof(wchar_t);
cStruct.lpData = (LPVOID)(lpszFilesList);
appController->SendMessage(WM_COPYDATA, (WPARAM)NULL, (LPARAM)(&cStruct));
}
void _DisplaySettings (handle_t Binding)
{
appController->PostMessage(WM_APP_TRIGGER_SETTINGS);
}
void _UpdateSendProgress (
handle_t RpcBinding,
COOKIE Cookie,
wchar_t CurrentFile[],
__int64 BytesInTransfer,
__int64 BytesTransferred,
error_status_t* pStatus
)
{
VALIDATE_SEND_COOKIE (Cookie)
CSendProgress* progressDlg = (CSendProgress*)Cookie;
int percentComplete;
if (BytesInTransfer)
{
percentComplete = (int)((BytesTransferred*100.0)/BytesInTransfer);
}
else
{
percentComplete = 100;
}
progressDlg->PostMessage(WM_APP_UPDATE_PROGRESS, (WPARAM) 0, (LPARAM) percentComplete);
if (100 > percentComplete)
{
progressDlg->SetCurrentFileName (CurrentFile);
}
*pStatus = 0;
}
void _OneSendFileFailed(
handle_t RpcBinding,
COOKIE Cookie,
wchar_t FileName[],
error_status_t ErrorCode,
int Location,
error_status_t * pStatus
)
{
VALIDATE_SEND_COOKIE (Cookie)
struct SEND_FAILURE_DATA Data;
COPYDATASTRUCT cStruct;
CWnd* progressDlg = (CWnd*)Cookie;
StringCbCopy(Data.FileName,sizeof(Data.FileName), FileName);
Data.Location = (FAILURE_LOCATION)Location;
Data.Error = ErrorCode;
cStruct.cbData = sizeof(SEND_FAILURE_DATA);
cStruct.lpData = &Data;
progressDlg->SendMessage(WM_COPYDATA, (WPARAM) 0, (LPARAM)(&cStruct));
*pStatus = 0;
}
void _SendComplete(
handle_t RpcBinding,
COOKIE Cookie,
__int64 BytesTransferred,
error_status_t* pStatus
)
{
VALIDATE_SEND_COOKIE (Cookie)
CWnd* progressDlg = (CWnd*)Cookie;
progressDlg->PostMessage(WM_APP_SEND_COMPLETE);
*pStatus = 0;
}
error_status_t
_ReceiveInProgress(
handle_t RpcBinding,
wchar_t MachineName[],
COOKIE * pCookie,
boolean bSuppressRecvConf
)
{
struct MSG_RECEIVE_IN_PROGRESS msg;
msg.MachineName = MachineName;
msg.pCookie = pCookie;
msg.bSuppressRecvConf = bSuppressRecvConf;
msg.status = ~0UL;
appController->SendMessage( WM_APP_RECV_IN_PROGRESS, (WPARAM) &msg );
return msg.status;
}
error_status_t
_GetPermission(
handle_t RpcBinding,
COOKIE Cookie,
wchar_t Name[],
boolean fDirectory
)
{
struct MSG_GET_PERMISSION msg;
msg.Cookie = Cookie;
msg.Name = Name;
msg.fDirectory = fDirectory;
msg.status = ~0UL;
appController->SendMessage( WM_APP_GET_PERMISSION, (WPARAM) &msg );
return msg.status;
}
error_status_t
_ReceiveFinished(
handle_t RpcBinding,
COOKIE Cookie,
error_status_t Status
)
{
struct MSG_RECEIVE_FINISHED msg;
msg.Cookie = Cookie;
msg.ReceiveStatus = Status;
msg.status = ~0UL;
appController->SendMessage( WM_APP_RECV_FINISHED, (WPARAM) &msg );
return msg.status;
}
void _DeviceInRange(
handle_t RpcBinding,
POBEX_DEVICE_LIST device,
error_status_t* pStatus
)
{
appController->PostMessage (WM_APP_KILL_TIMER);
LONG NewLinkCount = InterlockedIncrement(&g_lLinkOnDesktop);
BOOL Result;
if (NewLinkCount == 1) {
//
// the link count went from zero to 1, create the links now
//
Result=CreateLinks();
if (!Result) {
//
// could not create the links
//
InterlockedExchange(&g_lLinkOnDesktop,0);
}
}
g_deviceList= device;
*pStatus = 0;
}
void _NoDeviceInRange(
handle_t RpcBinding,
error_status_t* pStatus
)
{
InterlockedExchange(&g_lLinkOnDesktop,0);
RemoveLinks();
g_deviceList = NULL;
if (0 == g_lUIComponentCount) {
//
// nothing displayed, start timer to shutdown app if no device comeback some.
//
appController->PostMessage (WM_APP_START_TIMER);
}
*pStatus = 0;
}
VOID
CloseDownUI(
VOID
)
{
if (0 == g_lUIComponentCount) {
if (appController != NULL) {
appController->PostMessage (WM_CLOSE);
}
} else {
if (appController != NULL) {
appController->SessionOver();
}
}
return;
}
void _Message(
handle_t RpcBinding,
wchar_t String[]
)
{
AFX_MANAGE_STATE (AfxGetStaticModuleState());
CString szTitle;
szTitle.LoadString (IDS_CAPTION);
InterlockedIncrement (&g_lUIComponentCount);
::MessageBox (NULL, String, (LPCTSTR) szTitle, MB_OK);
BOOL fNoUIComponents = (0 == InterlockedDecrement (&g_lUIComponentCount));
if (appController && fNoUIComponents && ! g_deviceList.GetDeviceCount())
{
//there are no UI components displayed and there are no devices in
//range. Start the timer. If the timer expires, the app. will quit.
appController->PostMessage (WM_APP_START_TIMER);
}
}
error_status_t
_ShutdownUi(handle_t RpcBinding)
{
appController->PostMessage( WM_CLOSE );
return 0;
}
error_status_t
_ShutdownRequested(
handle_t RpcBinding,
boolean * pAnswer
)
{
WCHAR pwszCaption [50];
WCHAR pwszMessage [MAX_PATH];
*pAnswer = TRUE;
if (appController)
{
appController->PostMessage (WM_APP_KILL_TIMER);
}
if (! ::LoadString ( g_hInstance, IDS_CAPTION, pwszCaption, 50))
{
return ERROR_NOT_ENOUGH_MEMORY;
}
if (! ::LoadString ( g_hInstance, IDS_SHUTDOWN_MESSAGE, pwszMessage, MAX_PATH))
{
return ERROR_NOT_ENOUGH_MEMORY;
}
//display a message box with YES / NO buttons
if (IDYES == ::MessageBox (appController->m_hWnd, pwszMessage, pwszCaption,
MB_ICONEXCLAMATION | MB_YESNO | MB_SYSTEMMODAL | MB_SETFOREGROUND))
{
*pAnswer = TRUE;
}
else
{
*pAnswer = FALSE;
}
return 0;
}
//////////////////////////////////////////////////////////////////////////////
//Create links on the desktop and in the Send To menu to this executable file
BOOL
CreateLinks(
VOID
)
{
AFX_MANAGE_STATE (AfxGetStaticModuleState());
HRESULT Result=E_FAIL;
LONG i;
TCHAR lpszFullExeName [2*MAX_PATH];
TCHAR lpszShortcutName[2*MAX_PATH];
CString szDesc;
szDesc.LoadString (IDS_SHTCUT_DESC);
//
// create the desktop link
//
if (GetShortcutInfo(lpszShortcutName,sizeof(lpszShortcutName)/sizeof(TCHAR), lpszFullExeName,sizeof(lpszFullExeName)/sizeof(TCHAR))) {
#if 0
OutputDebugString(lpszShortcutName);
OutputDebugStringA("\n");
#endif
Result=CreateShortcut (lpszFullExeName, lpszShortcutName, (LPCTSTR) szDesc);
if (SUCCEEDED(Result)) {
} else {
#if DB
OutputDebugStringA("Could not create desktop link\n");
#endif
}
} else {
#if DBG
OutputDebugStringA("Could not get desktop path\n");
#endif
}
if (!SUCCEEDED(Result)) {
return FALSE;
}
//
// create the send to link
//
if (GetSendToInfo(lpszShortcutName,sizeof(lpszShortcutName)/sizeof(TCHAR) ,lpszFullExeName,sizeof(lpszFullExeName)/sizeof(TCHAR))) {
Result=CreateShortcut (lpszFullExeName, lpszShortcutName, (LPCTSTR) szDesc);
if (SUCCEEDED(Result)) {
} else {
#if DBG
OutputDebugStringA("Could not create desktop link\n");
#endif
}
} else {
#if DBG
OutputDebugStringA("Could get sendto path\n");
#endif
}
return SUCCEEDED(Result);
}
//////////////////////////////////////////////////////////////////////////////
// CreateShortcut - uses the shell's IShellLink and IPersistFile interfaces
// to create and store a shortcut to the specified object.
HRESULT CreateShortcut (LPCTSTR lpszExe, LPCTSTR lpszLink, LPCTSTR lpszDesc)
{
HRESULT hres;
IShellLink* psl;
hres = CoInitialize(NULL);
if (FAILED(hres))
return hres;
// Get a pointer to the IShellLink interface.
hres = CoCreateInstance(CLSID_ShellLink, NULL,
CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl);
if (SUCCEEDED(hres)) {
IPersistFile* ppf;
// Set the path to the shortcut target and add the
// description.
psl->SetPath(lpszExe);
psl->SetDescription(lpszDesc);
// Query IShellLink for the IPersistFile interface for saving the
// shortcut in persistent storage.
hres = psl->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf);
if (SUCCEEDED(hres)) {
// Save the link by calling IPersistFile::Save.
hres = ppf->Save(lpszLink, TRUE);
ppf->Release();
}
psl->Release();
}
return SUCCEEDED(hres)?S_OK:E_FAIL;
}
void RemoveLinks (void)
{
TCHAR lpszShortcutName[2 * MAX_PATH];
TCHAR lpszFullExeName[2 * MAX_PATH];
//delete the desktop shortcut
if (GetShortcutInfo (lpszShortcutName,sizeof(lpszShortcutName)/sizeof(TCHAR), lpszFullExeName,sizeof(lpszFullExeName)/sizeof(TCHAR))) {
DeleteFile (lpszShortcutName);
}
//delete the send to shortcut
//
if (GetSendToInfo (lpszShortcutName,sizeof(lpszShortcutName)/sizeof(TCHAR), lpszFullExeName,sizeof(lpszFullExeName)/sizeof(TCHAR))) {
DeleteFile (lpszShortcutName);
}
}
BOOL GetShortcutInfo (
LPTSTR lpszShortcutName,
ULONG ShortCutNameLength,
LPTSTR lpszFullExeName,
ULONG ExeNameLength
)
{
AFX_MANAGE_STATE (AfxGetStaticModuleState());
*lpszShortcutName = '\0'; //precautionary measures
*lpszFullExeName = '\0';
CString szExe;
CString szShtCut;
int len;
szExe.LoadString (IDS_EXE);
szShtCut.LoadString (IDS_DESKTOP_SHTCUT);
len = GetSystemDirectory (lpszFullExeName, ExeNameLength);
if (0 == len) {
return FALSE;
}
StringCchCat(lpszFullExeName,ExeNameLength,LPCTSTR (szExe));
if('\0' == g_lpszDesktopFolder[0]) //try once again if we had failed before, or maybe this is the first time
{
if (!SHGetSpecialFolderPath(NULL, g_lpszDesktopFolder,
CSIDL_DESKTOPDIRECTORY, 0))
{
g_lpszDesktopFolder[0] = '\0'; //we failed so give up.
return FALSE;
}
}
StringCchCopy(lpszShortcutName,ShortCutNameLength, g_lpszDesktopFolder);
StringCchCat(lpszShortcutName,ShortCutNameLength, (LPCTSTR) szShtCut);
return TRUE;
}
BOOL GetSendToInfo (
LPTSTR lpszSendToName,
ULONG SendToNameLength,
LPTSTR lpszFullExeName,
ULONG FullExeNameLength
)
{
AFX_MANAGE_STATE (AfxGetStaticModuleState());
*lpszSendToName = TEXT('\0'); //precautionary measures
*lpszFullExeName = TEXT('\0');
CString szExe;
CString szSendTo;
int len;
szExe.LoadString (IDS_EXE);
szSendTo.LoadString (IDS_SENDTO_SHTCUT);
len = GetSystemDirectory (lpszFullExeName, FullExeNameLength);
if (0 == len) {
return FALSE;
}
StringCchCat(lpszFullExeName,FullExeNameLength, (LPCTSTR) szExe);
if ('\0' == g_lpszSendToFolder[0]) //try once again if we had failed before, or maybe this is the first time
{
if (!SHGetSpecialFolderPath(NULL, g_lpszSendToFolder,
CSIDL_SENDTO, 0))
{
g_lpszSendToFolder[0] = TEXT('\0');
return FALSE;
}
}
StringCchCopy(lpszSendToName,SendToNameLength, g_lpszSendToFolder);
StringCchCat(lpszSendToName, SendToNameLength,(LPCTSTR) szSendTo);
return TRUE;
}
//+--------------------------------------------------------------------------
//
// Member: CError::ConstructMessage
//
// Synopsis: this is an internal helper function that constructs a message
// from the available error codes it is called by both ShowMessage
//
// Arguments: [in] argList : the va_list of arguments
// [out] szErrMsg : the formatted error message
//
// Returns: nothing
//
// History: 10/2/1998 RahulTh created
//
// Notes:
//
//---------------------------------------------------------------------------
void CError::ConstructMessage (va_list argList, CString& szErrMsg)
{
AFX_MANAGE_STATE (AfxGetStaticModuleState());
TCHAR lpszMessage[2048];
szErrMsg.LoadString (m_msgID);
StringCbVPrintf(lpszMessage, sizeof(lpszMessage),(LPCTSTR) szErrMsg, argList);
szErrMsg = lpszMessage;
if (ERROR_SUCCESS != m_winErr)
{
LPVOID lpMsgBuf;
DWORD dwRet;
dwRet = ::FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
m_winErr,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0,
NULL
);
if (dwRet)
{
szErrMsg += TEXT("\n\n");
szErrMsg += (LPCTSTR) lpMsgBuf;
LocalFree (lpMsgBuf);
}
}
}
//+--------------------------------------------------------------------------
//
// Member: CError::ShowMessage
//
// Synopsis: displays an error message in a message box based on the
// members of the object
//
// Arguments: message id for the error + more
//
// Returns: the return value of the message box
//
// History: 10/1/1998 RahulTh created
//
// Notes: if the resultant message is longer than 2048 characters
// then result is unpredictable and may also cause AVs.
// but this is a limitation of wvsprintf. However, this is not
// so bad since we can make sure that we do not have any error
// message that exceed this self imposed limit
//
//---------------------------------------------------------------------------
int CError::ShowMessage (UINT errID, ...)
{
AFX_MANAGE_STATE (AfxGetStaticModuleState());
va_list argList;
CString szErrMsg;
CString szTitle;
m_msgID = errID; //update the message ID with the new one
szTitle.LoadString (m_titleID);
va_start (argList, errID);
ConstructMessage (argList, szErrMsg);
va_end (argList);
return ::MessageBox (m_hWndParent, (LPCTSTR)szErrMsg,
(LPCTSTR) szTitle, m_nStyle);
}