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.

566 lines
14 KiB

  1. // ProgView.cpp : Implementation of CProgView
  2. #include "stdafx.h"
  3. #include <commctrl.h>
  4. #include "ProgView.h"
  5. #include <strsafe.h>
  6. /////////////////////////////////////////////////////////////////////////////
  7. // CProgView
  8. LRESULT
  9. CProgView::OnNotifyListView(
  10. int idCtrl,
  11. LPNMHDR pnmh,
  12. BOOL& bHandled
  13. )
  14. {
  15. if (idCtrl != IDC_FILE_LIST) {
  16. bHandled = FALSE;
  17. return 0;
  18. }
  19. if (pnmh->code == NM_DBLCLK)
  20. {
  21. return OnDblclkListprograms(idCtrl, pnmh, bHandled);
  22. }
  23. // see that we get the notification to fill-in the details
  24. return NotifyProgramList(m_pProgramList, pnmh, bHandled);
  25. }
  26. LRESULT
  27. CProgView::OnDblclkListprograms(
  28. int idCtrl,
  29. LPNMHDR pnmh,
  30. BOOL& bHandled)
  31. {
  32. LPNMITEMACTIVATE lpnmh;
  33. LRESULT SelFile;
  34. WCHAR FileName[MAX_PATH];
  35. if (idCtrl != IDC_FILE_LIST) {
  36. bHandled = FALSE;
  37. return 0;
  38. }
  39. lpnmh = (LPNMITEMACTIVATE) pnmh;
  40. // we have a double-click !
  41. SelFile = SendDlgItemMessage(m_hwnd, IDC_FILE_LIST,
  42. LVM_GETSELECTIONMARK,
  43. 0, 0);
  44. if (SelFile >= 0)
  45. {
  46. GetSelectedItem();
  47. GetSelectionInformation(PROGLIST_EXENAME, FileName, sizeof(FileName));
  48. StringCchCopyW(m_wszRetFileName, MAX_PATH, FileName);
  49. if (lpnmh->iSubItem == 0 &&
  50. lpnmh->iItem == SelFile)
  51. {
  52. // A file is selected, we can end the dialog
  53. m_nCmdPopulate = CMD_EXIT;
  54. EndDialog(m_hwnd, IDOK);
  55. SetEvent(m_hEventCmd);
  56. }
  57. }
  58. bHandled = TRUE;
  59. return 0;
  60. }
  61. STDMETHODIMP CProgView::GetSelectedItem()
  62. {
  63. GetProgramListSelection(m_pProgramList);
  64. return S_OK;
  65. }
  66. STDMETHODIMP CProgView::get_SelectionName(LPWSTR pBuffer, ULONG Size)
  67. {
  68. if (!m_Safe) {
  69. return HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED);
  70. }
  71. GetProgramListSelectionDetails(m_pProgramList, 0, pBuffer, Size);
  72. return S_OK;
  73. }
  74. STDMETHODIMP CProgView::GetSelectionInformation(LONG lInformationClass, LPWSTR pBuffer, ULONG Size)
  75. {
  76. if (!m_Safe) {
  77. return HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED);
  78. }
  79. GetProgramListSelectionDetails(m_pProgramList, lInformationClass, pBuffer, Size);
  80. return S_OK;
  81. }
  82. VOID
  83. CProgView::ShowProgressWindows(BOOL bProgress)
  84. {
  85. HDWP hDefer = ::BeginDeferWindowPos(4);
  86. DWORD dwProgressFlag = bProgress ? SWP_SHOWWINDOW : SWP_HIDEWINDOW;
  87. DWORD dwListFlag = bProgress ? SWP_HIDEWINDOW : SWP_SHOWWINDOW;
  88. hDefer = ::DeferWindowPos(hDefer, GetDlgItem(m_hwnd, IDC_ANIMATE), NULL,
  89. 0, 0, 0, 0,
  90. SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|dwProgressFlag);
  91. hDefer = ::DeferWindowPos(hDefer, GetDlgItem(m_hwnd, IDC_SEARCH_STATUS), NULL,
  92. 0, 0, 0, 0,
  93. SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|dwProgressFlag);
  94. hDefer = ::DeferWindowPos(hDefer, GetDlgItem(m_hwnd, IDC_SEARCH_STATUS2), NULL,
  95. 0, 0, 0, 0,
  96. SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|dwProgressFlag);
  97. hDefer = ::DeferWindowPos(hDefer, GetDlgItem(m_hwnd, IDC_SEARCH_STATUS3), NULL,
  98. 0, 0, 0, 0,
  99. SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|dwProgressFlag);
  100. hDefer = ::DeferWindowPos(hDefer, GetDlgItem(m_hwnd, IDC_SEARCH_FINISHED), NULL,
  101. 0, 0, 0, 0,
  102. SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|dwListFlag);
  103. hDefer = ::DeferWindowPos(hDefer, GetDlgItem(m_hwnd, IDC_FILE_LIST), NULL,
  104. 0, 0, 0, 0,
  105. SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|dwListFlag);
  106. EndDeferWindowPos(hDefer);
  107. }
  108. STDMETHODIMP CProgView::PopulateList()
  109. {
  110. HANDLE hThread;
  111. ResetEvent(m_hEventCancel);
  112. ResetEvent(m_hEventCmd);
  113. // if (!m_bInPlaceActive) {
  114. // InPlaceActivate(OLEIVERB_INPLACEACTIVATE);
  115. // }
  116. if (m_hThreadPopulate == NULL) {
  117. m_hThreadPopulate = CreateThread(NULL, 0, _PopulateThreadProc, (LPVOID)this, 0, NULL);
  118. }
  119. if (m_hThreadPopulate != NULL && !IsScanInProgress()) {
  120. m_nCmdPopulate = CMD_SCAN;
  121. SetEvent(m_hEventCmd);
  122. }
  123. return S_OK;
  124. }
  125. BOOL CProgView::PopulateListInternal()
  126. {
  127. if (InterlockedCompareExchange(&m_PopulateInProgress, TRUE, FALSE) == TRUE) {
  128. //
  129. // populate in progress -- quit
  130. //
  131. return FALSE;
  132. }
  133. if (m_pProgramList != NULL) {
  134. CleanupProgramList(m_pProgramList);
  135. m_pProgramList = NULL;
  136. }
  137. ShowProgressWindows(TRUE);
  138. Animate_OpenEx(GetDlgItem(m_hwnd, IDC_ANIMATE), _Module.GetModuleInstance(), MAKEINTRESOURCE(IDA_FINDANIM));
  139. Animate_Play(GetDlgItem(m_hwnd, IDC_ANIMATE), 0, -1, -1);
  140. PostMessage(m_hwnd, WM_VIEW_CHANGED, 0, 0);
  141. // FireViewChange();
  142. // if (m_bInPlaceActive) {
  143. /* HCURSOR hcWait = (HCURSOR)::LoadImage(NULL,
  144. MAKEINTRESOURCE(IDC_WAIT),
  145. IMAGE_CURSOR,
  146. 0, 0,
  147. LR_DEFAULTSIZE|LR_SHARED);
  148. // HCURSOR hcWait = ::LoadCursor(_Module.GetResourceInstance(),
  149. // MAKEINTRESOURCE(IDC_WAIT));
  150. HCURSOR hcSave = SetCursor(hcWait);
  151. */
  152. //
  153. // malloc used on this thread should NOT be used on UI thread
  154. //
  155. InitializeProgramList(&m_pProgramList, GetDlgItem(m_hwnd, IDC_FILE_LIST));
  156. PopulateProgramList(m_pProgramList, this, m_hEventCancel);
  157. // SetCursor(hcSave);
  158. Animate_Stop(GetDlgItem(m_hwnd, IDC_ANIMATE));
  159. Animate_Close(GetDlgItem(m_hwnd, IDC_ANIMATE));
  160. ShowProgressWindows();
  161. InterlockedCompareExchange(&m_PopulateInProgress, FALSE, TRUE);
  162. PostMessage(m_hwnd, WM_VIEW_CHANGED, 0, 0);
  163. PostMessage(m_hwnd, WM_LIST_POPULATED, 0, 0); // we are done, signal to the main thread
  164. // FireViewChange();
  165. // } else {
  166. // m_bPendingPopulate = TRUE;
  167. // }
  168. return TRUE;
  169. }
  170. DWORD WINAPI
  171. CProgView::_PopulateThreadProc(
  172. LPVOID lpvParam
  173. )
  174. {
  175. CProgView* pProgView = (CProgView*)lpvParam;
  176. DWORD dwWait;
  177. BOOL bExit = FALSE;
  178. HRESULT hr = CoInitialize(NULL);
  179. if (!SUCCEEDED(hr)) {
  180. return FALSE;
  181. }
  182. //
  183. // keep this thread alive, block it on a command event
  184. //
  185. while(!bExit) {
  186. dwWait = WaitForSingleObject(pProgView->m_hEventCmd, INFINITE);
  187. if (dwWait != WAIT_OBJECT_0) {
  188. break; // get out, we are being killed
  189. }
  190. //
  191. // get the command
  192. //
  193. switch(pProgView->m_nCmdPopulate) {
  194. case CMD_NONE:
  195. break;
  196. case CMD_EXIT:
  197. bExit = TRUE;
  198. //
  199. // intentional fall-through
  200. //
  201. case CMD_CLEANUP:
  202. if (pProgView->m_pProgramList) {
  203. CleanupProgramList(pProgView->m_pProgramList);
  204. pProgView->m_pProgramList = NULL;
  205. }
  206. break;
  207. case CMD_SCAN:
  208. pProgView->PopulateListInternal();
  209. break;
  210. }
  211. pProgView->m_nCmdPopulate = CMD_NONE;
  212. }
  213. CoUninitialize();
  214. return TRUE;
  215. }
  216. STDMETHODIMP
  217. CProgView::UpdateListItem(
  218. BSTR pTarget,
  219. VARIANT *pKeys,
  220. BOOL *pResult
  221. )
  222. {
  223. VARIANT vKeys;
  224. VariantInit(&vKeys);
  225. CComBSTR bstrKeys;
  226. HRESULT hr;
  227. if (!m_pProgramList) {
  228. return S_OK;
  229. }
  230. if (!m_Safe) {
  231. return HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED);
  232. }
  233. if (pKeys->vt == VT_NULL || pKeys->vt == VT_EMPTY) {
  234. *pResult = UpdateProgramListItem(m_pProgramList, pTarget, NULL);
  235. return S_OK;
  236. }
  237. hr = VariantChangeType(&vKeys, pKeys, 0, VT_BSTR);
  238. if (SUCCEEDED(hr)) {
  239. bstrKeys = vKeys.bstrVal;
  240. if (bstrKeys.Length()) {
  241. *pResult = UpdateProgramListItem(m_pProgramList, pTarget, bstrKeys);
  242. } else {
  243. *pResult = FALSE;
  244. }
  245. }
  246. VariantClear(&vKeys);
  247. return S_OK;
  248. }
  249. STDMETHODIMP CProgView::CancelPopulateList()
  250. {
  251. if (m_hEventCancel && InterlockedCompareExchange(&m_PopulateInProgress, TRUE, TRUE) == TRUE) {
  252. SetEvent(m_hEventCancel);
  253. }
  254. return S_OK;
  255. }
  256. STDMETHODIMP CProgView::get_ItemCount(VARIANT* pVal)
  257. {
  258. if (!m_Safe) {
  259. return HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED);
  260. }
  261. pVal->vt = VT_I4;
  262. pVal->intVal = (int)ListView_GetItemCount(GetDlgItem(m_hwnd, IDC_FILE_LIST));
  263. return S_OK;
  264. }
  265. //
  266. // expand env -- lives in util.cpp
  267. // we have a bit differing implementation here
  268. //
  269. LPWSTR
  270. ExpandEnvironmentVars(
  271. LPWSTR lpszCmd
  272. )
  273. {
  274. DWORD dwLength;
  275. LPTSTR lpBuffer = NULL;
  276. BOOL bExpanded = FALSE;
  277. LPWSTR strCmd;
  278. TCHAR szBuffer[MAX_PATH];
  279. if (_tcschr(lpszCmd, TEXT('%')) == NULL) {
  280. goto out;
  281. }
  282. dwLength = ExpandEnvironmentStrings(lpszCmd, NULL, 0);
  283. if (!dwLength) {
  284. goto out;
  285. }
  286. if (dwLength < CHARCOUNT(szBuffer)) {
  287. lpBuffer = szBuffer;
  288. } else {
  289. lpBuffer = new TCHAR[dwLength];
  290. if (NULL == lpBuffer) {
  291. goto out;
  292. }
  293. }
  294. dwLength = ExpandEnvironmentStrings(lpszCmd, lpBuffer, dwLength);
  295. if (!dwLength) {
  296. goto out;
  297. }
  298. strCmd = lpBuffer;
  299. bExpanded = TRUE;
  300. out:
  301. if (!bExpanded) {
  302. strCmd = lpszCmd;
  303. }
  304. if (lpBuffer && lpBuffer != szBuffer) {
  305. delete[] lpBuffer;
  306. }
  307. return strCmd;
  308. }
  309. #if 0
  310. STDMETHODIMP CProgView::put_ExcludeFiles(BSTR newVal)
  311. {
  312. // parse exclude files, put them into our blacklist
  313. wstring strFile;
  314. LPCWSTR pch = newVal;
  315. LPCWSTR pend;
  316. m_ExcludedFiles.clear();
  317. while (pch != NULL && *pch != TEXT('\0')) {
  318. pch += _tcsspn(pch, TEXT(" \t"));
  319. // begining
  320. // find the ;
  321. pend = _tcschr(pch, TEXT(';'));
  322. if (pend == NULL) {
  323. // from pch to the end
  324. strFile = pch;
  325. pch = NULL; // will bail out
  326. } else {
  327. strFile = wstring(pch, (wstring::size_type)(pend - pch));
  328. pch = pend + 1; // one past ;
  329. }
  330. // add
  331. if (strFile.length()) {
  332. strFile = ExpandEnvironmentVars(strFile.c_str());
  333. m_ExcludedFiles.insert(StrUpCase(strFile));
  334. }
  335. }
  336. return S_OK;
  337. }
  338. STDMETHODIMP CProgView::get_ExcludeFiles(BSTR* pVal)
  339. {
  340. // parse exclude files, put them into our blacklist
  341. STRSET::iterator iter;
  342. CComBSTR bstrFiles;
  343. for (iter = m_ExcludedFiles.begin(); iter != m_ExcludedFiles.end(); ++iter) {
  344. if (bstrFiles.Length()) {
  345. bstrFiles += TEXT(';');
  346. }
  347. bstrFiles += (*iter).c_str();
  348. }
  349. *pVal = bstrFiles.Copy();
  350. return S_OK;
  351. }
  352. BOOL CProgView::IsFileExcluded(LPCTSTR pszFile)
  353. {
  354. wstring strFile = pszFile;
  355. STRSET::iterator iter;
  356. iter = m_ExcludedFiles.find(StrUpCase(strFile));
  357. return iter != m_ExcludedFiles.end();
  358. }
  359. #endif // 0
  360. LRESULT
  361. CProgView::OnCommand(WPARAM wParam, LPARAM lParam)
  362. {
  363. WORD wCode = HIWORD(wParam);
  364. WORD wId = LOWORD(wParam);
  365. LRESULT SelFile;
  366. WCHAR FileName[MAX_PATH];
  367. switch(wId)
  368. {
  369. case IDOK:
  370. SelFile = SendDlgItemMessage(m_hwnd, IDC_FILE_LIST,
  371. LVM_GETSELECTIONMARK,
  372. 0, 0);
  373. if (SelFile >= 0)
  374. {
  375. GetSelectedItem();
  376. GetSelectionInformation(PROGLIST_EXENAME, FileName, sizeof(FileName));
  377. StringCchCopyW(m_wszRetFileName, MAX_PATH, FileName);
  378. }
  379. // Fall through
  380. case IDCANCEL:
  381. m_nCmdPopulate = CMD_EXIT;
  382. EndDialog(m_hwnd, wId);
  383. SetEvent(m_hEventCmd);
  384. return 0;
  385. default:
  386. return 1; // not handled
  387. }
  388. return 1; // not handled
  389. }
  390. LRESULT
  391. CProgView::OnNotify(WPARAM wParam, LPARAM lParam)
  392. {
  393. WORD wId = LOWORD(wParam);
  394. BOOL bVal;
  395. BOOL& bHandled = bVal;
  396. switch(wId)
  397. {
  398. default:
  399. break;
  400. case IDC_FILE_LIST:
  401. return OnNotifyListView((int) wParam, (LPNMHDR) lParam, bHandled);
  402. break;
  403. }
  404. return 1;
  405. }
  406. INT_PTR CALLBACK
  407. Dialog_GetProgFromList(
  408. HWND hwnd,
  409. UINT Message,
  410. WPARAM wparam,
  411. LPARAM lparam
  412. )
  413. {
  414. BOOL bHandled;
  415. CProgView* pProgWinData;
  416. pProgWinData = (CProgView *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
  417. if (Message != WM_INITDIALOG && pProgWinData == NULL)
  418. {
  419. return FALSE;
  420. }
  421. switch (Message)
  422. {
  423. case WM_INITDIALOG:
  424. // Assert(pProgWinData == NULL);
  425. pProgWinData = new CProgView();
  426. if (!pProgWinData)
  427. {
  428. return -1;
  429. }
  430. pProgWinData->m_hwnd = hwnd;
  431. SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) pProgWinData);
  432. SetFocus(hwnd);
  433. pProgWinData->OnInitDialog(Message, wparam, lparam, &bHandled);
  434. break;
  435. case WM_COMMAND:
  436. if (pProgWinData->OnCommand(wparam, lparam) == 0)
  437. {
  438. return TRUE;
  439. }
  440. break;
  441. case WM_NOTIFY:
  442. if (pProgWinData->OnNotify(wparam, lparam) == 0)
  443. {
  444. return TRUE;
  445. }
  446. break;
  447. case WM_DESTROY:
  448. delete pProgWinData;
  449. SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) NULL);
  450. break;
  451. }
  452. return FALSE;
  453. }