|
|
/*++
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"
#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; \ } \ }
////////////////////////////////////////////////////////////////////////
//
//RPC Functions
//
///////////////////////////////////////////////////////////////////////
void __RPC_FAR * __RPC_USER MIDL_user_allocate(size_t Size) { return new char[Size]; }
void __RPC_USER MIDL_user_free( void __RPC_FAR * buf) { delete [] buf; }
//
// 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) { lstrcpy(pszTemp, pszPath); pszTemp += iPathLen; lstrcpy(pszTemp, pszFilesList); iLen = lstrlen(pszFilesList); pszFilesList += iLen + 1; pszTemp += iLen + 1; } *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]; lstrcpy (pszFullFileName, 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]; lstrcpy (pszFullFileName + 2, pszFilesList); pszFullFileName[iCharCount - 1] = '\0'; //we need to have 2 terminating nulls
} else //ordinary file name
{ iCharCount = iPathLen + iFileLen + 2; //2 terminating nulls
iCharCount += ('\\' == pszPath[iPathLen - 1])?0:1; //sometimes the path does not have a \ at the end, so we need to add these ourselves
pszFullFileName = new TCHAR [iCharCount]; lstrcpy (pszFullFileName, pszPath); if('\\' != pszPath[iPathLen - 1]) //we need to add the \ ourselves
{ pszFullFileName[iPathLen] = '\\'; lstrcpy(pszFullFileName + iPathLen + 1, pszFilesList); } else lstrcpy (pszFullFileName + iPathLen, 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; }
/////////////////////////////////////////////////////////////////////////
// Initialize the RPC server
////////////////////////////////////////////////////////////////////////
BOOL InitRPCServer (void) { DWORD Status;
Status = RpcServerRegisterIf( _IrNotifications_v1_0_s_ifspec, 0, 0); if (Status) { return FALSE; }
Status = RpcServerUseAllProtseqsIf( RPC_C_PROTSEQ_MAX_REQS_DEFAULT, _IrNotifications_v1_0_s_ifspec, 0); if (Status) { return FALSE; }
Status = RpcServerListen( 1, RPC_C_LISTEN_MAX_CALLS_DEFAULT, TRUE); if (Status) { return FALSE; }
return TRUE; }
//////////////////////////////////////////////////////////////////////////////////
//Connect to the RPC server running on the first instance of the app
//this function is called only if this is not the first instance of the app
//////////////////////////////////////////////////////////////////////////////////
RPC_BINDING_HANDLE GetRpcHandle (void) { DWORD Status; RPC_BINDING_HANDLE Binding;
Status = RpcBindingFromStringBinding(L"ncalrpc:", &Binding);
if (Status) return NULL; else return Binding;
}
///////////////////////////////////////////////////////////////////////////////////////
// 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, FAILURE_LOCATION Location, error_status_t * pStatus ) { VALIDATE_SEND_COOKIE (Cookie)
struct SEND_FAILURE_DATA Data;
COPYDATASTRUCT cStruct; CWnd* progressDlg = (CWnd*)Cookie;
lstrcpy(Data.FileName, FileName); Data.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); BOOL fLinkOnDesktop = (0 != InterlockedIncrement(&g_lLinkOnDesktop)); if(!fLinkOnDesktop) CreateLinks(); else InterlockedDecrement(&g_lLinkOnDesktop); //don't allow the value to exceed 0
g_deviceList = device; *pStatus = 0; }
void _NoDeviceInRange( handle_t RpcBinding, error_status_t* pStatus ) { RemoveLinks(); InterlockedDecrement(&g_lLinkOnDesktop); g_deviceList = NULL; if (0 == g_lUIComponentCount) appController->PostMessage (WM_APP_START_TIMER); *pStatus = 0; }
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
void CreateLinks(void) { AFX_MANAGE_STATE (AfxGetStaticModuleState());
TCHAR lpszFullExeName [MAX_PATH]; TCHAR lpszShortcutName[MAX_PATH]; CString szDesc;
szDesc.LoadString (IDS_SHTCUT_DESC);
//create the desktop link
if (GetShortcutInfo(lpszShortcutName, lpszFullExeName)) CreateShortcut (lpszFullExeName, lpszShortcutName, (LPCTSTR) szDesc);
//create the send to link
if (GetSendToInfo(lpszShortcutName, lpszFullExeName)) CreateShortcut (lpszFullExeName, lpszShortcutName, (LPCTSTR) szDesc); }
//////////////////////////////////////////////////////////////////////////////
// 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, lpszFullExeName)) DeleteFile (lpszShortcutName);
//delete the send to shortcut
if (GetSendToInfo (lpszShortcutName, lpszFullExeName)) DeleteFile (lpszShortcutName); }
BOOL GetShortcutInfo (LPTSTR lpszShortcutName, LPTSTR lpszFullExeName) { 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, MAX_PATH); if(0 == len) return FALSE; lstrcat(lpszFullExeName, LPCTSTR (szExe));
if('\0' == g_lpszDesktopFolder[0]) //try once again if we had failed before, or maybe this is the first time
{ if (FAILED(SHGetSpecialFolderPath(NULL, g_lpszDesktopFolder, CSIDL_DESKTOPDIRECTORY, 0))) { g_lpszDesktopFolder[0] = '\0'; //we failed so give up.
return FALSE; } }
lstrcpy (lpszShortcutName, g_lpszDesktopFolder); lstrcat (lpszShortcutName, (LPCTSTR) szShtCut);
return TRUE; }
BOOL GetSendToInfo (LPTSTR lpszSendToName, LPTSTR lpszFullExeName) { AFX_MANAGE_STATE (AfxGetStaticModuleState());
*lpszSendToName = '\0'; //precautionary measures
*lpszFullExeName = '\0'; CString szExe; CString szSendTo; int len;
szExe.LoadString (IDS_EXE); szSendTo.LoadString (IDS_SENDTO_SHTCUT);
len = GetSystemDirectory (lpszFullExeName, MAX_PATH); if (0 == len) return FALSE; lstrcat (lpszFullExeName, (LPCTSTR) szExe);
if ('\0' == g_lpszSendToFolder[0]) //try once again if we had failed before, or maybe this is the first time
{ if (FAILED(SHGetSpecialFolderPath(NULL, g_lpszSendToFolder, CSIDL_SENDTO, 0))) { g_lpszSendToFolder[0] = '\0'; return FALSE; } }
lstrcpy (lpszSendToName, g_lpszSendToFolder); lstrcat (lpszSendToName, (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);
wvsprintf (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); }
|