|
|
#include <windows.h>
#include <shlwapi.h>
#include <commctrl.h>
#include "dataitem.h"
#include "resource.h"
#include "autorun.h"
#define ARRAYSIZE(x) (sizeof(x)/sizeof(x[0]))
CDataItem::CDataItem() { m_pszTitle = m_pszMenuName = m_pszDescription = m_pszCmdLine = m_pszArgs = NULL; m_dwFlags = 0; m_chAccel = NULL; }
CDataItem::~CDataItem() { if ( m_pszTitle ) delete [] m_pszTitle; if ( m_pszMenuName ) delete [] m_pszMenuName; if ( m_pszDescription ) delete [] m_pszDescription; if ( m_pszCmdLine ) delete [] m_pszCmdLine; if ( m_pszArgs ) delete [] m_pszArgs; }
BOOL CDataItem::SetData( LPTSTR szTitle, LPTSTR szMenu, LPTSTR szDesc, LPTSTR szCmd, LPTSTR szArgs, DWORD dwFlags, int iImgIndex ) { TCHAR * psz;
// This function should only be called once or else we will leak like a, like a, a thing that leaks a lot.
ASSERT( NULL==m_pszTitle && NULL==m_pszMenuName && NULL==m_pszDescription && NULL==m_pszCmdLine && NULL==m_pszArgs );
m_pszTitle = new TCHAR[lstrlen(szTitle)+1]; if ( m_pszTitle ) lstrcpy( m_pszTitle, szTitle );
if ( szMenu ) { // menuname is allowed to remain NULL. This is only used if you want the
// text on the menu item to be different than the description. This could
// be useful for localization where a shortened name might be required.
m_pszMenuName = new TCHAR[lstrlen(szMenu)+1]; if ( m_pszMenuName ) lstrcpy( m_pszMenuName, szMenu );
psz = StrChr(szMenu, TEXT('&')); if ( psz ) m_chAccel = *(CharNext(psz)); }
m_pszDescription = new TCHAR[lstrlen(szDesc)+1]; if ( m_pszDescription ) lstrcpy( m_pszDescription, szDesc );
m_pszCmdLine = new TCHAR[lstrlen(szCmd)+1]; if ( m_pszCmdLine ) lstrcpy( m_pszCmdLine, szCmd );
if ( szArgs ) { // Some commands don't have any args so this can remain NULL. This is only used
// if the executable requires arguments.
m_pszArgs = new TCHAR[lstrlen(szArgs)+1]; if ( m_pszArgs ) lstrcpy( m_pszArgs, szArgs ); }
m_dwFlags = dwFlags; m_iImage = iImgIndex;
return TRUE; }
BOOL CDataItem::Invoke(HWND hwnd) { BOOL fResult; TCHAR szCmdLine[MAX_PATH*2]; PROCESS_INFORMATION ei; STARTUPINFO si = {0}; si.cb = sizeof(si);
lstrcpy( szCmdLine, m_pszCmdLine ); if ( m_pszArgs ) { strcat( szCmdLine, TEXT(" ") ); strcat( szCmdLine, m_pszArgs ); }
fResult = CreateProcess(NULL, szCmdLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &ei); if (fResult) { if (NULL != ei.hProcess) { DWORD dwObject;
// passing in a NULL HWND is used as a signal not to wait in this inner loop.
while (hwnd) { dwObject = MsgWaitForMultipleObjects(1, &ei.hProcess, FALSE, INFINITE, QS_ALLINPUT); if (WAIT_OBJECT_0 == dwObject) { break; } else if (WAIT_OBJECT_0+1 == dwObject) { MSG msg;
while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) { if ( WM_QUIT == msg.message ) { CloseHandle(ei.hProcess); return fResult; } else { GetMessage(&msg, NULL, 0, 0);
// IsDialogMessage cannot understand the concept of ownerdraw default pushbuttons. It treats
// these attributes as mutually exclusive. As a result, we handle this ourselves. We want
// whatever control has focus to act as the default pushbutton.
if ( (WM_KEYDOWN == msg.message) && (VK_RETURN == msg.wParam) ) { HWND hwndFocus = GetFocus(); if ( hwndFocus ) { SendMessage(hwnd, WM_COMMAND, MAKELONG(GetDlgCtrlID(hwndFocus), BN_CLICKED), (LPARAM)hwndFocus); } continue; }
if ( IsDialogMessage(hwnd, &msg) ) continue;
TranslateMessage(&msg); DispatchMessage(&msg); } } } }
if ( !hwnd ) { // A NULL hwnd means we were called in the mode by which we execute the item and then immediately
// exit. If our process exits before the other process is ready it'll end up in the wrong place
// in the z-order. To prevent this, when we're in "exit when done" mode we need to wait for the
// process we created to be ready. The way to do this is to call WaitForInputIdle. This is really
// only needed on NT5 and above due to the new "rude window activation" stuff, but since this API
// is available all the way back to NT 3.1 we simply call it blindly.
WaitForInputIdle(ei.hProcess, 20*1000); // we wait a maximum of 20 seconds
}
CloseHandle(ei.hProcess); } } else { // do something if we fail to create a process?
}
return fResult; }
|