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.

538 lines
12 KiB

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