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.
566 lines
14 KiB
566 lines
14 KiB
// ProgView.cpp : Implementation of CProgView
|
|
#include "stdafx.h"
|
|
#include <commctrl.h>
|
|
#include "ProgView.h"
|
|
#include <strsafe.h>
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CProgView
|
|
|
|
|
|
LRESULT
|
|
CProgView::OnNotifyListView(
|
|
int idCtrl,
|
|
LPNMHDR pnmh,
|
|
BOOL& bHandled
|
|
)
|
|
{
|
|
|
|
if (idCtrl != IDC_FILE_LIST) {
|
|
bHandled = FALSE;
|
|
return 0;
|
|
}
|
|
|
|
if (pnmh->code == NM_DBLCLK)
|
|
{
|
|
return OnDblclkListprograms(idCtrl, pnmh, bHandled);
|
|
}
|
|
// see that we get the notification to fill-in the details
|
|
return NotifyProgramList(m_pProgramList, pnmh, bHandled);
|
|
}
|
|
|
|
LRESULT
|
|
CProgView::OnDblclkListprograms(
|
|
int idCtrl,
|
|
LPNMHDR pnmh,
|
|
BOOL& bHandled)
|
|
{
|
|
LPNMITEMACTIVATE lpnmh;
|
|
LRESULT SelFile;
|
|
WCHAR FileName[MAX_PATH];
|
|
|
|
if (idCtrl != IDC_FILE_LIST) {
|
|
bHandled = FALSE;
|
|
return 0;
|
|
}
|
|
|
|
lpnmh = (LPNMITEMACTIVATE) pnmh;
|
|
|
|
// we have a double-click !
|
|
|
|
SelFile = SendDlgItemMessage(m_hwnd, IDC_FILE_LIST,
|
|
LVM_GETSELECTIONMARK,
|
|
0, 0);
|
|
if (SelFile >= 0)
|
|
{
|
|
GetSelectedItem();
|
|
GetSelectionInformation(PROGLIST_EXENAME, FileName, sizeof(FileName));
|
|
StringCchCopyW(m_wszRetFileName, MAX_PATH, FileName);
|
|
|
|
|
|
if (lpnmh->iSubItem == 0 &&
|
|
lpnmh->iItem == SelFile)
|
|
{
|
|
// A file is selected, we can end the dialog
|
|
m_nCmdPopulate = CMD_EXIT;
|
|
EndDialog(m_hwnd, IDOK);
|
|
SetEvent(m_hEventCmd);
|
|
}
|
|
}
|
|
bHandled = TRUE;
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
STDMETHODIMP CProgView::GetSelectedItem()
|
|
{
|
|
|
|
GetProgramListSelection(m_pProgramList);
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CProgView::get_SelectionName(LPWSTR pBuffer, ULONG Size)
|
|
{
|
|
if (!m_Safe) {
|
|
return HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED);
|
|
}
|
|
|
|
|
|
GetProgramListSelectionDetails(m_pProgramList, 0, pBuffer, Size);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
STDMETHODIMP CProgView::GetSelectionInformation(LONG lInformationClass, LPWSTR pBuffer, ULONG Size)
|
|
{
|
|
if (!m_Safe) {
|
|
return HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED);
|
|
}
|
|
|
|
GetProgramListSelectionDetails(m_pProgramList, lInformationClass, pBuffer, Size);
|
|
return S_OK;
|
|
}
|
|
|
|
VOID
|
|
CProgView::ShowProgressWindows(BOOL bProgress)
|
|
{
|
|
HDWP hDefer = ::BeginDeferWindowPos(4);
|
|
DWORD dwProgressFlag = bProgress ? SWP_SHOWWINDOW : SWP_HIDEWINDOW;
|
|
DWORD dwListFlag = bProgress ? SWP_HIDEWINDOW : SWP_SHOWWINDOW;
|
|
|
|
hDefer = ::DeferWindowPos(hDefer, GetDlgItem(m_hwnd, IDC_ANIMATE), NULL,
|
|
0, 0, 0, 0,
|
|
SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|dwProgressFlag);
|
|
|
|
hDefer = ::DeferWindowPos(hDefer, GetDlgItem(m_hwnd, IDC_SEARCH_STATUS), NULL,
|
|
0, 0, 0, 0,
|
|
SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|dwProgressFlag);
|
|
|
|
hDefer = ::DeferWindowPos(hDefer, GetDlgItem(m_hwnd, IDC_SEARCH_STATUS2), NULL,
|
|
0, 0, 0, 0,
|
|
SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|dwProgressFlag);
|
|
|
|
hDefer = ::DeferWindowPos(hDefer, GetDlgItem(m_hwnd, IDC_SEARCH_STATUS3), NULL,
|
|
0, 0, 0, 0,
|
|
SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|dwProgressFlag);
|
|
|
|
hDefer = ::DeferWindowPos(hDefer, GetDlgItem(m_hwnd, IDC_SEARCH_FINISHED), NULL,
|
|
0, 0, 0, 0,
|
|
SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|dwListFlag);
|
|
hDefer = ::DeferWindowPos(hDefer, GetDlgItem(m_hwnd, IDC_FILE_LIST), NULL,
|
|
0, 0, 0, 0,
|
|
SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|dwListFlag);
|
|
|
|
|
|
EndDeferWindowPos(hDefer);
|
|
|
|
}
|
|
|
|
STDMETHODIMP CProgView::PopulateList()
|
|
{
|
|
HANDLE hThread;
|
|
|
|
ResetEvent(m_hEventCancel);
|
|
ResetEvent(m_hEventCmd);
|
|
|
|
// if (!m_bInPlaceActive) {
|
|
// InPlaceActivate(OLEIVERB_INPLACEACTIVATE);
|
|
// }
|
|
if (m_hThreadPopulate == NULL) {
|
|
m_hThreadPopulate = CreateThread(NULL, 0, _PopulateThreadProc, (LPVOID)this, 0, NULL);
|
|
}
|
|
|
|
if (m_hThreadPopulate != NULL && !IsScanInProgress()) {
|
|
m_nCmdPopulate = CMD_SCAN;
|
|
SetEvent(m_hEventCmd);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
BOOL CProgView::PopulateListInternal()
|
|
{
|
|
|
|
if (InterlockedCompareExchange(&m_PopulateInProgress, TRUE, FALSE) == TRUE) {
|
|
//
|
|
// populate in progress -- quit
|
|
//
|
|
return FALSE;
|
|
}
|
|
|
|
if (m_pProgramList != NULL) {
|
|
CleanupProgramList(m_pProgramList);
|
|
m_pProgramList = NULL;
|
|
|
|
}
|
|
|
|
ShowProgressWindows(TRUE);
|
|
Animate_OpenEx(GetDlgItem(m_hwnd, IDC_ANIMATE), _Module.GetModuleInstance(), MAKEINTRESOURCE(IDA_FINDANIM));
|
|
Animate_Play(GetDlgItem(m_hwnd, IDC_ANIMATE), 0, -1, -1);
|
|
|
|
PostMessage(m_hwnd, WM_VIEW_CHANGED, 0, 0);
|
|
|
|
// FireViewChange();
|
|
|
|
// if (m_bInPlaceActive) {
|
|
/* HCURSOR hcWait = (HCURSOR)::LoadImage(NULL,
|
|
MAKEINTRESOURCE(IDC_WAIT),
|
|
IMAGE_CURSOR,
|
|
0, 0,
|
|
LR_DEFAULTSIZE|LR_SHARED);
|
|
|
|
// HCURSOR hcWait = ::LoadCursor(_Module.GetResourceInstance(),
|
|
// MAKEINTRESOURCE(IDC_WAIT));
|
|
|
|
|
|
HCURSOR hcSave = SetCursor(hcWait);
|
|
*/
|
|
|
|
//
|
|
// malloc used on this thread should NOT be used on UI thread
|
|
//
|
|
|
|
InitializeProgramList(&m_pProgramList, GetDlgItem(m_hwnd, IDC_FILE_LIST));
|
|
PopulateProgramList(m_pProgramList, this, m_hEventCancel);
|
|
|
|
// SetCursor(hcSave);
|
|
|
|
Animate_Stop(GetDlgItem(m_hwnd, IDC_ANIMATE));
|
|
Animate_Close(GetDlgItem(m_hwnd, IDC_ANIMATE));
|
|
ShowProgressWindows();
|
|
|
|
InterlockedCompareExchange(&m_PopulateInProgress, FALSE, TRUE);
|
|
|
|
PostMessage(m_hwnd, WM_VIEW_CHANGED, 0, 0);
|
|
PostMessage(m_hwnd, WM_LIST_POPULATED, 0, 0); // we are done, signal to the main thread
|
|
|
|
|
|
// FireViewChange();
|
|
|
|
// } else {
|
|
// m_bPendingPopulate = TRUE;
|
|
// }
|
|
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
DWORD WINAPI
|
|
CProgView::_PopulateThreadProc(
|
|
LPVOID lpvParam
|
|
)
|
|
{
|
|
CProgView* pProgView = (CProgView*)lpvParam;
|
|
DWORD dwWait;
|
|
BOOL bExit = FALSE;
|
|
HRESULT hr = CoInitialize(NULL);
|
|
if (!SUCCEEDED(hr)) {
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// keep this thread alive, block it on a command event
|
|
//
|
|
while(!bExit) {
|
|
dwWait = WaitForSingleObject(pProgView->m_hEventCmd, INFINITE);
|
|
if (dwWait != WAIT_OBJECT_0) {
|
|
break; // get out, we are being killed
|
|
}
|
|
//
|
|
// get the command
|
|
//
|
|
switch(pProgView->m_nCmdPopulate) {
|
|
case CMD_NONE:
|
|
break;
|
|
|
|
case CMD_EXIT:
|
|
bExit = TRUE;
|
|
//
|
|
// intentional fall-through
|
|
//
|
|
|
|
case CMD_CLEANUP:
|
|
if (pProgView->m_pProgramList) {
|
|
CleanupProgramList(pProgView->m_pProgramList);
|
|
pProgView->m_pProgramList = NULL;
|
|
}
|
|
break;
|
|
|
|
case CMD_SCAN:
|
|
pProgView->PopulateListInternal();
|
|
break;
|
|
}
|
|
|
|
pProgView->m_nCmdPopulate = CMD_NONE;
|
|
}
|
|
CoUninitialize();
|
|
return TRUE;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CProgView::UpdateListItem(
|
|
BSTR pTarget,
|
|
VARIANT *pKeys,
|
|
BOOL *pResult
|
|
)
|
|
{
|
|
VARIANT vKeys;
|
|
VariantInit(&vKeys);
|
|
CComBSTR bstrKeys;
|
|
HRESULT hr;
|
|
|
|
if (!m_pProgramList) {
|
|
return S_OK;
|
|
}
|
|
|
|
if (!m_Safe) {
|
|
return HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED);
|
|
}
|
|
|
|
|
|
if (pKeys->vt == VT_NULL || pKeys->vt == VT_EMPTY) {
|
|
*pResult = UpdateProgramListItem(m_pProgramList, pTarget, NULL);
|
|
return S_OK;
|
|
}
|
|
|
|
hr = VariantChangeType(&vKeys, pKeys, 0, VT_BSTR);
|
|
if (SUCCEEDED(hr)) {
|
|
bstrKeys = vKeys.bstrVal;
|
|
|
|
if (bstrKeys.Length()) {
|
|
*pResult = UpdateProgramListItem(m_pProgramList, pTarget, bstrKeys);
|
|
} else {
|
|
*pResult = FALSE;
|
|
}
|
|
}
|
|
|
|
VariantClear(&vKeys);
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CProgView::CancelPopulateList()
|
|
{
|
|
if (m_hEventCancel && InterlockedCompareExchange(&m_PopulateInProgress, TRUE, TRUE) == TRUE) {
|
|
SetEvent(m_hEventCancel);
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CProgView::get_ItemCount(VARIANT* pVal)
|
|
{
|
|
if (!m_Safe) {
|
|
return HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED);
|
|
}
|
|
|
|
pVal->vt = VT_I4;
|
|
pVal->intVal = (int)ListView_GetItemCount(GetDlgItem(m_hwnd, IDC_FILE_LIST));
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//
|
|
// expand env -- lives in util.cpp
|
|
// we have a bit differing implementation here
|
|
//
|
|
|
|
LPWSTR
|
|
ExpandEnvironmentVars(
|
|
LPWSTR lpszCmd
|
|
)
|
|
{
|
|
DWORD dwLength;
|
|
LPTSTR lpBuffer = NULL;
|
|
BOOL bExpanded = FALSE;
|
|
LPWSTR strCmd;
|
|
TCHAR szBuffer[MAX_PATH];
|
|
|
|
if (_tcschr(lpszCmd, TEXT('%')) == NULL) {
|
|
goto out;
|
|
}
|
|
|
|
dwLength = ExpandEnvironmentStrings(lpszCmd, NULL, 0);
|
|
if (!dwLength) {
|
|
goto out;
|
|
}
|
|
|
|
if (dwLength < CHARCOUNT(szBuffer)) {
|
|
lpBuffer = szBuffer;
|
|
} else {
|
|
lpBuffer = new TCHAR[dwLength];
|
|
if (NULL == lpBuffer) {
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
dwLength = ExpandEnvironmentStrings(lpszCmd, lpBuffer, dwLength);
|
|
if (!dwLength) {
|
|
goto out;
|
|
}
|
|
|
|
strCmd = lpBuffer;
|
|
bExpanded = TRUE;
|
|
|
|
out:
|
|
if (!bExpanded) {
|
|
strCmd = lpszCmd;
|
|
}
|
|
if (lpBuffer && lpBuffer != szBuffer) {
|
|
delete[] lpBuffer;
|
|
}
|
|
return strCmd;
|
|
}
|
|
|
|
#if 0
|
|
STDMETHODIMP CProgView::put_ExcludeFiles(BSTR newVal)
|
|
{
|
|
// parse exclude files, put them into our blacklist
|
|
wstring strFile;
|
|
LPCWSTR pch = newVal;
|
|
LPCWSTR pend;
|
|
|
|
m_ExcludedFiles.clear();
|
|
|
|
while (pch != NULL && *pch != TEXT('\0')) {
|
|
|
|
pch += _tcsspn(pch, TEXT(" \t"));
|
|
// begining
|
|
// find the ;
|
|
pend = _tcschr(pch, TEXT(';'));
|
|
if (pend == NULL) {
|
|
// from pch to the end
|
|
strFile = pch;
|
|
pch = NULL; // will bail out
|
|
} else {
|
|
strFile = wstring(pch, (wstring::size_type)(pend - pch));
|
|
pch = pend + 1; // one past ;
|
|
}
|
|
|
|
// add
|
|
if (strFile.length()) {
|
|
strFile = ExpandEnvironmentVars(strFile.c_str());
|
|
m_ExcludedFiles.insert(StrUpCase(strFile));
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CProgView::get_ExcludeFiles(BSTR* pVal)
|
|
{
|
|
// parse exclude files, put them into our blacklist
|
|
STRSET::iterator iter;
|
|
CComBSTR bstrFiles;
|
|
|
|
for (iter = m_ExcludedFiles.begin(); iter != m_ExcludedFiles.end(); ++iter) {
|
|
if (bstrFiles.Length()) {
|
|
bstrFiles += TEXT(';');
|
|
}
|
|
bstrFiles += (*iter).c_str();
|
|
}
|
|
|
|
*pVal = bstrFiles.Copy();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
BOOL CProgView::IsFileExcluded(LPCTSTR pszFile)
|
|
{
|
|
wstring strFile = pszFile;
|
|
STRSET::iterator iter;
|
|
|
|
iter = m_ExcludedFiles.find(StrUpCase(strFile));
|
|
return iter != m_ExcludedFiles.end();
|
|
}
|
|
#endif // 0
|
|
|
|
LRESULT
|
|
CProgView::OnCommand(WPARAM wParam, LPARAM lParam)
|
|
{
|
|
WORD wCode = HIWORD(wParam);
|
|
WORD wId = LOWORD(wParam);
|
|
LRESULT SelFile;
|
|
WCHAR FileName[MAX_PATH];
|
|
|
|
switch(wId)
|
|
{
|
|
|
|
case IDOK:
|
|
SelFile = SendDlgItemMessage(m_hwnd, IDC_FILE_LIST,
|
|
LVM_GETSELECTIONMARK,
|
|
0, 0);
|
|
if (SelFile >= 0)
|
|
{
|
|
GetSelectedItem();
|
|
GetSelectionInformation(PROGLIST_EXENAME, FileName, sizeof(FileName));
|
|
StringCchCopyW(m_wszRetFileName, MAX_PATH, FileName);
|
|
}
|
|
// Fall through
|
|
case IDCANCEL:
|
|
m_nCmdPopulate = CMD_EXIT;
|
|
EndDialog(m_hwnd, wId);
|
|
SetEvent(m_hEventCmd);
|
|
return 0;
|
|
|
|
default:
|
|
return 1; // not handled
|
|
|
|
}
|
|
return 1; // not handled
|
|
}
|
|
|
|
LRESULT
|
|
CProgView::OnNotify(WPARAM wParam, LPARAM lParam)
|
|
{
|
|
WORD wId = LOWORD(wParam);
|
|
BOOL bVal;
|
|
BOOL& bHandled = bVal;
|
|
|
|
switch(wId)
|
|
{
|
|
default:
|
|
break;
|
|
case IDC_FILE_LIST:
|
|
return OnNotifyListView((int) wParam, (LPNMHDR) lParam, bHandled);
|
|
break;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
INT_PTR CALLBACK
|
|
Dialog_GetProgFromList(
|
|
HWND hwnd,
|
|
UINT Message,
|
|
WPARAM wparam,
|
|
LPARAM lparam
|
|
)
|
|
{
|
|
BOOL bHandled;
|
|
CProgView* pProgWinData;
|
|
|
|
pProgWinData = (CProgView *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
|
|
|
if (Message != WM_INITDIALOG && pProgWinData == NULL)
|
|
{
|
|
return FALSE;
|
|
}
|
|
switch (Message)
|
|
{
|
|
case WM_INITDIALOG:
|
|
// Assert(pProgWinData == NULL);
|
|
|
|
pProgWinData = new CProgView();
|
|
if (!pProgWinData)
|
|
{
|
|
return -1;
|
|
}
|
|
pProgWinData->m_hwnd = hwnd;
|
|
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) pProgWinData);
|
|
|
|
SetFocus(hwnd);
|
|
pProgWinData->OnInitDialog(Message, wparam, lparam, &bHandled);
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
if (pProgWinData->OnCommand(wparam, lparam) == 0)
|
|
{
|
|
return TRUE;
|
|
}
|
|
break;
|
|
case WM_NOTIFY:
|
|
if (pProgWinData->OnNotify(wparam, lparam) == 0)
|
|
{
|
|
return TRUE;
|
|
}
|
|
break;
|
|
|
|
case WM_DESTROY:
|
|
delete pProgWinData;
|
|
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) NULL);
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|