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.

3914 lines
129 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997.
  5. //
  6. // File: Progress.cpp
  7. //
  8. // Contents: Progress Dialog
  9. //
  10. // Classes:
  11. //
  12. // Notes:
  13. //
  14. // History: 05-Nov-97 Susia Created.
  15. //
  16. //--------------------------------------------------------------------------
  17. #include "precomp.h"
  18. #define TIMERID_TRAYANIMATION 3
  19. #define TRAYANIMATION_SPEED 500 // speed in milliseconds
  20. #define TIMERID_NOIDLEHANGUP 4 // inform wininet that connection isn't idle.
  21. #define NOIDLEHANGUP_REFRESHRATE (1000*30) // inform of idle every 30 seconds.
  22. #define TIMERID_KILLHANDLERS 5
  23. #define TIMERID_KILLHANDLERSMINTIME (1000*15) // minimum timeout for kill handlers that are hung after cancel.
  24. #define TIMERID_KILLHANDLERSWIN9XTIME (1000*60) // Timeout for for kill handlers other than NT 5.0
  25. const TCHAR c_szTrayWindow[] = TEXT("Shell_TrayWnd");
  26. const TCHAR c_szTrayNotifyWindow[] = TEXT("TrayNotifyWnd");
  27. #ifndef IDANI_CAPTION
  28. #define IDANI_CAPTION 3
  29. #endif // IDANI_CAPTION
  30. // list collapsed items first so only have to loop
  31. // though first item to cbNumDlgResizeItemsCollapsed when
  32. // not expanded.
  33. const DlgResizeList g_ProgressResizeList[] = {
  34. IDSTOP,DLGRESIZEFLAG_PINRIGHT,
  35. IDC_DETAILS,DLGRESIZEFLAG_PINRIGHT,
  36. IDC_RESULTTEXT,DLGRESIZEFLAG_PINRIGHT | DLGRESIZEFLAG_PINLEFT,
  37. IDC_STATIC_WHATS_UPDATING,DLGRESIZEFLAG_PINRIGHT | DLGRESIZEFLAG_PINLEFT,
  38. IDC_STATIC_WHATS_UPDATING_INFO,DLGRESIZEFLAG_PINRIGHT | DLGRESIZEFLAG_PINLEFT,
  39. IDC_STATIC_HOW_MANY_COMPLETE,DLGRESIZEFLAG_PINRIGHT | DLGRESIZEFLAG_PINLEFT,
  40. IDC_SP_SEPARATOR,DLGRESIZEFLAG_PINRIGHT | DLGRESIZEFLAG_PINLEFT,
  41. // expanded items
  42. IDC_TOOLBAR, DLGRESIZEFLAG_PINRIGHT,
  43. IDC_PROGRESS_TABS,DLGRESIZEFLAG_PINRIGHT | DLGRESIZEFLAG_PINLEFT | DLGRESIZEFLAG_PINBOTTOM | DLGRESIZEFLAG_PINTOP,
  44. IDC_UPDATE_LIST,DLGRESIZEFLAG_PINRIGHT | DLGRESIZEFLAG_PINLEFT | DLGRESIZEFLAG_PINBOTTOM | DLGRESIZEFLAG_PINTOP,
  45. IDC_SKIP_BUTTON_MAIN,DLGRESIZEFLAG_PINBOTTOM | DLGRESIZEFLAG_PINLEFT,
  46. IDC_STATIC_SKIP_TEXT,DLGRESIZEFLAG_PINBOTTOM | DLGRESIZEFLAG_PINLEFT,
  47. IDC_PROGRESS_OPTIONS_BUTTON_MAIN,DLGRESIZEFLAG_PINRIGHT | DLGRESIZEFLAG_PINBOTTOM,
  48. IDC_LISTBOXERROR,DLGRESIZEFLAG_PINRIGHT | DLGRESIZEFLAG_PINLEFT | DLGRESIZEFLAG_PINBOTTOM | DLGRESIZEFLAG_PINTOP,
  49. IDC_PROGRESSRESIZESCROLLBAR,DLGRESIZEFLAG_PINRIGHT | DLGRESIZEFLAG_PINBOTTOM,
  50. };
  51. extern HINSTANCE g_hInst; // current instance
  52. extern TCHAR g_szSyncMgrHelp[];
  53. extern ULONG g_aContextHelpIds[];
  54. extern LANGID g_LangIdSystem; // langID of system we are running on.
  55. extern DWORD g_WMTaskbarCreated; // TaskBar Created WindowMessage;
  56. INT_PTR CALLBACK ProgressWndProc(HWND hwnd, UINT uMsg,WPARAM wParam,LPARAM lParam);
  57. //defined in progtab.cpp
  58. extern INT_PTR CALLBACK UpdateProgressWndProc(HWND hwnd, UINT uMsg,WPARAM wParam,LPARAM lParam);
  59. extern INT_PTR CALLBACK ResultsProgressWndProc(HWND hwnd, UINT uMsg,WPARAM wParam,LPARAM lParam);
  60. extern BOOL OnProgressResultsMeasureItem(HWND hwnd,CProgressDlg *pProgress, UINT *horizExtent, UINT idCtl, MEASUREITEMSTRUCT *pMeasureItem);
  61. extern BOOL OnProgressResultsDeleteItem(HWND hwnd, UINT idCtl, const DELETEITEMSTRUCT * lpDeleteItem);
  62. extern void OnProgressResultsSize(HWND hwnd,CProgressDlg *pProgress,UINT uMsg,WPARAM wParam,LPARAM lParam);
  63. //--------------------------------------------------------------------------------
  64. //
  65. // FUNCTION: CProgressDlg::CProgressDlg()
  66. //
  67. // PURPOSE: Constructor
  68. //
  69. // COMMENTS: Constructor for progress dialog
  70. //
  71. //
  72. //--------------------------------------------------------------------------------
  73. CProgressDlg::CProgressDlg(REFCLSID rclsid)
  74. {
  75. m_clsid = rclsid;
  76. m_cInternalcRefs = 0;
  77. m_hwnd = NULL;
  78. m_hwndTabs = NULL;
  79. m_errorimage = NULL;
  80. m_HndlrQueue = NULL;
  81. m_iProgressSelectedItem = -1;
  82. m_iItem = -1; // index to any new item to the list box.
  83. m_iResultCount = -1; // Number of logged results
  84. m_iErrorCount = 0; // Number of logged errors
  85. m_iWarningCount = 0; // Number of logged warnings
  86. m_iInfoCount = 0; // Number of logged info
  87. m_dwThreadID = -1;
  88. m_nCmdShow = SW_SHOWNORMAL;
  89. // m_hRasConn = NULL;
  90. m_pSyncMgrIdle = NULL;
  91. m_fHasShellTrayIcon = FALSE;
  92. m_fAddedIconToTray = FALSE;
  93. m_fnResultsListBox = NULL;
  94. m_ulIdleRetryMinutes = 0;
  95. m_ulDelayIdleShutDownTime = 0;
  96. m_fHwndRightToLeft = FALSE;
  97. m_iLastItem = -1;
  98. m_dwLastStatusType = -1;
  99. m_dwHandleThreadNestcount = 0;
  100. m_dwShowErrorRefCount = 0;
  101. m_dwSetItemStateRefCount = 0;
  102. m_dwHandlerOutCallCount = 0;
  103. m_dwPrepareForSyncOutCallCount = 0;
  104. m_dwSynchronizeOutCallCount = 0;
  105. m_dwQueueTransferCount = 0;
  106. m_clsidHandlerInSync = GUID_NULL;
  107. m_fForceClose = FALSE;
  108. m_nKillHandlerTimeoutValue = TIMERID_KILLHANDLERSMINTIME;
  109. m_dwProgressFlags = PROGRESSFLAG_NEWDIALOG;
  110. m_pItemListView = NULL;
  111. m_iTrayAniFrame = IDI_SYSTRAYANI6; // initialize to end.
  112. LoadString(g_hInst, IDS_STOPPED, m_pszStatusText[0], MAX_STRING_RES);
  113. LoadString(g_hInst, IDS_SKIPPED, m_pszStatusText[1], MAX_STRING_RES);
  114. LoadString(g_hInst, IDS_PENDING, m_pszStatusText[2], MAX_STRING_RES);
  115. LoadString(g_hInst, IDS_SYNCHRONIZING, m_pszStatusText[3], MAX_STRING_RES);
  116. LoadString(g_hInst, IDS_SUCCEEDED, m_pszStatusText[4], MAX_STRING_RES);
  117. LoadString(g_hInst, IDS_FAILED, m_pszStatusText[5], MAX_STRING_RES);
  118. LoadString(g_hInst, IDS_PAUSED, m_pszStatusText[6], MAX_STRING_RES);
  119. LoadString(g_hInst, IDS_RESUMING, m_pszStatusText[7], MAX_STRING_RES);
  120. // Determine if SENS is installed
  121. LPNETAPI pNetApi;
  122. m_fSensInstalled = FALSE;
  123. if (pNetApi = gSingleNetApiObj.GetNetApiObj())
  124. {
  125. m_fSensInstalled = pNetApi->IsSensInstalled();
  126. pNetApi->Release();
  127. }
  128. m_CurrentListEntry = NULL;
  129. }
  130. //+---------------------------------------------------------------------------
  131. //
  132. // Member: CProgressDlg::AddRefProgressDialog, private
  133. //
  134. // Synopsis: Called to Addref ourselves
  135. //
  136. // Arguments:
  137. //
  138. // Returns:
  139. //
  140. // Modifies:
  141. //
  142. // History: 26-Aug-98 rogerg Created.
  143. //
  144. //----------------------------------------------------------------------------
  145. STDMETHODIMP_(ULONG) CProgressDlg::AddRefProgressDialog()
  146. {
  147. ULONG cRefs;
  148. cRefs = ::AddRefProgressDialog(m_clsid,this); // addref GlobalRef
  149. Assert(0 <= m_cInternalcRefs);
  150. ++m_cInternalcRefs;
  151. return cRefs;
  152. }
  153. //+---------------------------------------------------------------------------
  154. //
  155. // Member: CProgressDlg::ReleaseProgressDialog, private
  156. //
  157. // Synopsis: Called to Release ourselves
  158. //
  159. // Arguments:
  160. //
  161. // Returns:
  162. //
  163. // Modifies:
  164. //
  165. // History: 26-Aug-98 rogerg Created.
  166. //
  167. //----------------------------------------------------------------------------
  168. STDMETHODIMP_(ULONG) CProgressDlg::ReleaseProgressDialog(BOOL fForce)
  169. {
  170. ULONG cRefs;
  171. Assert(0 < m_cInternalcRefs);
  172. --m_cInternalcRefs;
  173. cRefs = ::ReleaseProgressDialog(m_clsid,this,fForce); // release global ref.
  174. return cRefs;
  175. }
  176. //--------------------------------------------------------------------------------
  177. //
  178. // FUNCTION: CProgressDlg::Initialize()
  179. //
  180. // PURPOSE: Initialize the Progress Dialog
  181. //
  182. // COMMENTS: Implemented on main thread.
  183. //
  184. //
  185. //--------------------------------------------------------------------------------
  186. BOOL CProgressDlg::Initialize(DWORD dwThreadID,int nCmdShow)
  187. {
  188. BOOL fCreated = FALSE;
  189. Assert(NULL == m_hwnd);
  190. m_nCmdShow = nCmdShow;
  191. if (NULL == m_hwnd)
  192. {
  193. m_dwThreadID = dwThreadID;
  194. m_hwnd = CreateDialogParam(g_hInst,MAKEINTRESOURCE(IDD_PROGRESS),NULL, ProgressWndProc,
  195. (LPARAM) this);
  196. if (!m_hwnd)
  197. return FALSE;
  198. // expand/collapse dialog base on use settings.
  199. RegGetProgressDetailsState(m_clsid,&m_fPushpin, &m_fExpanded);
  200. ExpandCollapse(m_fExpanded, TRUE);
  201. // Set the state of the thumbtack
  202. if (m_fPushpin)
  203. {
  204. SendDlgItemMessage(m_hwnd, IDC_TOOLBAR, TB_SETSTATE, IDC_PUSHPIN,
  205. MAKELONG(TBSTATE_CHECKED | TBSTATE_ENABLED, 0));
  206. SendMessage(m_hwnd, WM_COMMAND, IDC_PUSHPIN, 0);
  207. }
  208. m_HndlrQueue = new CHndlrQueue(QUEUETYPE_PROGRESS,this); // reivew, queueu should be created and passed in initialize??
  209. // if this is the idle progress then need to load up msidle and
  210. // set up the callback
  211. if (m_clsid == GUID_PROGRESSDLGIDLE)
  212. {
  213. BOOL fIdleSupport = FALSE;
  214. m_pSyncMgrIdle = new CSyncMgrIdle();
  215. if (m_pSyncMgrIdle)
  216. {
  217. fIdleSupport = m_pSyncMgrIdle->Initialize();
  218. if (FALSE == fIdleSupport)
  219. {
  220. delete m_pSyncMgrIdle;
  221. m_pSyncMgrIdle = NULL;
  222. }
  223. }
  224. // if couldn't load idle, then return a failure
  225. if (FALSE == fIdleSupport)
  226. {
  227. return FALSE;
  228. }
  229. }
  230. fCreated = TRUE;
  231. // When Window is first created show with specified nCmdShow.
  232. // Review if want to wait to show window until transfer comes in.
  233. UpdateWndPosition(nCmdShow,TRUE /* fForce */);
  234. }
  235. Assert(m_hwnd);
  236. UpdateWindow(m_hwnd);
  237. return TRUE;
  238. }
  239. //--------------------------------------------------------------------------------
  240. //
  241. // FUNCTION: CProgressDlg::OnSize(UINT uMsg,WPARAM wParam,LPARAM lParam)
  242. //
  243. // PURPOSE: moves and resizes dialog items based on current window size.
  244. //
  245. //--------------------------------------------------------------------------------
  246. void CProgressDlg::OnSize(UINT uMsg,WPARAM wParam,LPARAM lParam)
  247. {
  248. ULONG cbNumResizeItems;
  249. HWND hwndSizeGrip;
  250. cbNumResizeItems = m_fExpanded ? m_cbNumDlgResizeItemsExpanded : m_cbNumDlgResizeItemsCollapsed;
  251. ResizeItems(cbNumResizeItems,m_dlgResizeInfo);
  252. // if expanded and not maximized show the resize, else hide it.
  253. hwndSizeGrip = GetDlgItem(m_hwnd,IDC_PROGRESSRESIZESCROLLBAR);
  254. if (hwndSizeGrip)
  255. {
  256. int nCmdShow = (m_fMaximized || !m_fExpanded) ? SW_HIDE : SW_NORMAL;
  257. // temporarily always hide if right to left
  258. if (m_fHwndRightToLeft)
  259. {
  260. nCmdShow = SW_HIDE;
  261. }
  262. ShowWindow(hwndSizeGrip,nCmdShow);
  263. }
  264. // tell the error listbox it needs to recalc its items heights
  265. OnProgressResultsSize(m_hwnd,this,WM_SIZE,0,0);
  266. }
  267. //--------------------------------------------------------------------------------
  268. //
  269. // FUNCTION: CProgressDlg::OffIdle()
  270. //
  271. // PURPOSE: Informs progress dialog that the machine is no longer Idle.
  272. //
  273. // Scenarios
  274. //
  275. // dialog is maximized, just keep processing.
  276. // dialog is minimized or in tray - Set our wait timer for a specified time
  277. // if dialog is still minimized, go away
  278. // if dialog is now maximized just keep processing.
  279. //
  280. //--------------------------------------------------------------------------------
  281. void CProgressDlg::OffIdle()
  282. {
  283. Assert(!(PROGRESSFLAG_DEAD & m_dwProgressFlags)); // make sure not notified after dialog gone.
  284. m_dwProgressFlags |= PROGRESSFLAG_INOFFIDLE;
  285. // set flag that we received the OffIdle
  286. m_dwProgressFlags |= PROGRESSFLAG_RECEIVEDOFFIDLE;
  287. // reset Flag so know that no longer registered for Idle.
  288. m_dwProgressFlags &= ~PROGRESSFLAG_REGISTEREDFOROFFIDLE;
  289. // make sure in all cases we release the idle reference.
  290. // if in shutdownmode or cancel has already been pressed
  291. // by the user or if window is visible but not in the Tray.
  292. // then don't bother with the wait.
  293. if ( !IsWindowVisible(m_hwnd) && m_fHasShellTrayIcon
  294. && !(m_dwProgressFlags & PROGRESSFLAG_SHUTTINGDOWNLOOP)
  295. && !(m_dwProgressFlags & PROGRESSFLAG_CANCELPRESSED)
  296. && (m_dwProgressFlags & PROGRESSFLAG_SYNCINGITEMS) )
  297. {
  298. HANDLE hTimer = CreateEvent(NULL, TRUE, FALSE, NULL);
  299. // should use Create/SetWaitable timer to accomplish this but these
  300. // functions aren't available on Win9x yet.
  301. if (hTimer)
  302. {
  303. UINT uTimeOutValue = m_ulDelayIdleShutDownTime;
  304. Assert(sizeof(UINT) >= sizeof(HANDLE));
  305. DoModalLoop(hTimer,NULL,m_hwnd,TRUE,uTimeOutValue);
  306. CloseHandle(hTimer);
  307. }
  308. }
  309. // now after our wait, check the window placement again
  310. // if window is not visible or is in the tray
  311. // then do a cancel on behalf of the User,
  312. if ( (!IsWindowVisible(m_hwnd) || m_fHasShellTrayIcon)
  313. && !(m_dwProgressFlags & PROGRESSFLAG_SHUTTINGDOWNLOOP)
  314. && !(m_dwProgressFlags & PROGRESSFLAG_CANCELPRESSED) )
  315. {
  316. OnCancel(TRUE);
  317. }
  318. // now if we aren't syncing any items and no items
  319. // waiting in the queue release our idle lock
  320. // !!! warning. don't release until after wait above to
  321. // don't have to worry about next idle firing before
  322. // this method is complete.
  323. if (!(m_dwProgressFlags & PROGRESSFLAG_SYNCINGITEMS)
  324. || !(m_dwQueueTransferCount) )
  325. {
  326. ReleaseIdleLock();
  327. }
  328. m_dwProgressFlags &= ~PROGRESSFLAG_INOFFIDLE;
  329. ReleaseProgressDialog(m_fForceClose); // release our addref.
  330. }
  331. //--------------------------------------------------------------------------------
  332. //
  333. // FUNCTION: CProgressDlg::OnIdle()
  334. //
  335. // PURPOSE: Informs progress dialog that the machine is still
  336. // Idle after a set amount of time.
  337. //
  338. //
  339. //--------------------------------------------------------------------------------
  340. void CProgressDlg::OnIdle()
  341. {
  342. CSynchronizeInvoke *pSyncMgrInvoke;
  343. Assert(!(m_dwProgressFlags & PROGRESSFLAG_DEAD)); // make sure not notified after dialog gone.
  344. // if received and offIdle then ignore this idle until next ::transfer
  345. if (!(m_dwProgressFlags & PROGRESSFLAG_RECEIVEDOFFIDLE)
  346. && !(m_dwProgressFlags & PROGRESSFLAG_INOFFIDLE) )
  347. {
  348. AddRefProgressDialog(); // hold alive until next items are queued.
  349. pSyncMgrInvoke = new CSynchronizeInvoke;
  350. if (pSyncMgrInvoke)
  351. {
  352. pSyncMgrInvoke->RunIdle();
  353. pSyncMgrInvoke->Release();
  354. }
  355. ReleaseProgressDialog(m_fForceClose);
  356. }
  357. }
  358. //--------------------------------------------------------------------------------
  359. //
  360. // FUNCTION: CProgressDlg::SetIdleParams()
  361. //
  362. // PURPOSE: Sets the IdleInformation, last writer wins.
  363. //
  364. //
  365. //--------------------------------------------------------------------------------
  366. void CProgressDlg::SetIdleParams( ULONG ulIdleRetryMinutes,ULONG ulDelayIdleShutDownTime
  367. ,BOOL fRetryEnabled)
  368. {
  369. Assert(m_clsid == GUID_PROGRESSDLGIDLE);
  370. m_ulIdleRetryMinutes = ulIdleRetryMinutes;
  371. m_ulDelayIdleShutDownTime = ulDelayIdleShutDownTime;
  372. if (fRetryEnabled)
  373. {
  374. m_dwProgressFlags |= PROGRESSFLAG_IDLERETRYENABLED;
  375. }
  376. }
  377. //--------------------------------------------------------------------------------
  378. //
  379. // FUNCTION: BOOL CProgressDlg::InitializeToolbar(HWND hwnd)
  380. //
  381. // PURPOSE: What dialog would be complete without a toolbar, eh?
  382. //
  383. // RETURN VALUE:
  384. // TRUE if everything succeeded, FALSE otherwise.
  385. //
  386. //--------------------------------------------------------------------------------
  387. BOOL CProgressDlg::InitializeToolbar(HWND hwnd)
  388. {
  389. HWND hwndTool;
  390. HIMAGELIST himlImages = ImageList_LoadBitmap(g_hInst,
  391. MAKEINTRESOURCE(IDB_PUSHPIN), 16, 0,
  392. RGB(255, 0, 255));
  393. hwndTool = GetDlgItem(hwnd,IDC_TOOLBAR);
  394. //If we can't create the pushpin window
  395. //the user just won't get a pushpin.
  396. if (hwndTool)
  397. {
  398. TBBUTTON tb = { IMAGE_TACK_OUT, IDC_PUSHPIN, TBSTATE_ENABLED, TBSTYLE_CHECK, 0, 0 };
  399. SendMessage(hwndTool, TB_SETIMAGELIST, 0, (LPARAM) himlImages);
  400. SendMessage(hwndTool, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
  401. SendMessage(hwndTool, TB_SETBUTTONSIZE, 0, MAKELONG(14, 14));
  402. SendMessage(hwndTool, TB_SETBITMAPSIZE, 0, MAKELONG(14, 14));
  403. SendMessage(hwndTool, TB_ADDBUTTONS, 1, (LPARAM) &tb);
  404. }
  405. return (0);
  406. }
  407. //--------------------------------------------------------------------------------
  408. //
  409. // FUNCTION: CProgressDlg::InitializeTabs(HWND hwnd)
  410. //
  411. // PURPOSE: Initializes the tab control on the dialog.
  412. //
  413. // RETURN VALUE:
  414. // TRUE if everything succeeded, FALSE otherwise.
  415. //
  416. //--------------------------------------------------------------------------------
  417. BOOL CProgressDlg::InitializeTabs(HWND hwnd)
  418. {
  419. m_hwndTabs = GetDlgItem(hwnd, IDC_PROGRESS_TABS);
  420. TC_ITEM tci;
  421. TCHAR szRes[MAX_STRING_RES];
  422. if (!m_hwndTabs )
  423. return FALSE;
  424. // "Updates"
  425. tci.mask = TCIF_TEXT;
  426. LoadString(g_hInst, IDS_UPDATETAB, szRes, ARRAYSIZE(szRes));
  427. tci.pszText = szRes;
  428. TabCtrl_InsertItem(m_hwndTabs,PROGRESS_TAB_UPDATE, &tci);
  429. // "Results"
  430. LoadString(g_hInst, IDS_ERRORSTAB, szRes, ARRAYSIZE(szRes));
  431. tci.pszText = szRes;
  432. TabCtrl_InsertItem(m_hwndTabs, PROGRESS_TAB_ERRORS, &tci);
  433. //Set the tab to the Update page to begin with
  434. m_iTab = PROGRESS_TAB_UPDATE;
  435. if (-1 != TabCtrl_SetCurSel(m_hwndTabs, PROGRESS_TAB_UPDATE))
  436. {
  437. m_iTab = PROGRESS_TAB_UPDATE;
  438. ShowWindow(GetDlgItem(hwnd, IDC_LISTBOXERROR), SW_HIDE);
  439. }
  440. else //ToDo: What do we do if the set tab fails?
  441. {
  442. m_iTab = -1;
  443. return FALSE;
  444. }
  445. return (TRUE);
  446. }
  447. //--------------------------------------------------------------------------------
  448. //
  449. // FUNCTION: CProgressDlg::InitializeUpdateList(HWND hwnd)
  450. //
  451. // PURPOSE: Initializes the update list view control on the progress dialog.
  452. //
  453. // RETURN VALUE:
  454. // TRUE if everything succeeded, FALSE otherwise.
  455. //
  456. //--------------------------------------------------------------------------------
  457. BOOL CProgressDlg::InitializeUpdateList(HWND hwnd)
  458. {
  459. HWND hwndList = GetDlgItem(hwnd,IDC_UPDATE_LIST);
  460. HIMAGELIST hImageList;
  461. TCHAR pszProgressColumn[MAX_STRING_RES + 1];
  462. int iListViewWidth;
  463. if (hwndList)
  464. {
  465. m_pItemListView = new CListView(hwndList,hwnd,IDC_UPDATE_LIST,WM_BASEDLG_NOTIFYLISTVIEWEX);
  466. }
  467. if (!m_pItemListView)
  468. {
  469. return FALSE;
  470. }
  471. if (m_pItemListView)
  472. {
  473. UINT ImageListflags;
  474. ImageListflags = ILC_COLOR | ILC_MASK;
  475. if (IsHwndRightToLeft(hwnd))
  476. {
  477. ImageListflags |= ILC_MIRROR;
  478. }
  479. // create an imagelist
  480. hImageList = ImageList_Create( GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), ImageListflags, 5, 20);
  481. if (hImageList)
  482. {
  483. m_pItemListView->SetImageList(hImageList, LVSIL_SMALL);
  484. }
  485. // for column widths go 35%, 20%, 45%
  486. iListViewWidth = CalcListViewWidth(hwndList,410);
  487. //set up the columns
  488. LoadString(g_hInst, IDS_PROGRESS_DLG_COLUMN_NAME, pszProgressColumn, MAX_STRING_RES);
  489. InsertListViewColumn(m_pItemListView,PROGRESSLIST_NAMECOLUMN,pszProgressColumn,
  490. LVCFMT_LEFT,(iListViewWidth*7)/20 /* cx */);
  491. LoadString(g_hInst, IDS_PROGRESS_DLG_COLUMN_STATUS, pszProgressColumn, MAX_STRING_RES);
  492. InsertListViewColumn(m_pItemListView,PROGRESSLIST_STATUSCOLUMN,pszProgressColumn,
  493. LVCFMT_LEFT,(iListViewWidth/5) /* cx */);
  494. LoadString(g_hInst, IDS_PROGRESS_DLG_COLUMN_INFO, pszProgressColumn, MAX_STRING_RES);
  495. InsertListViewColumn(m_pItemListView,PROGRESSLIST_INFOCOLUMN,pszProgressColumn,
  496. LVCFMT_LEFT,(iListViewWidth*9)/20 /* cx */);
  497. }
  498. return (TRUE);
  499. }
  500. //--------------------------------------------------------------------------------
  501. //
  502. // FUNCTION: CProgressDlg::InitializeResultsList(HWND hwnd)
  503. //
  504. // PURPOSE: Initializes the results list view control on the progress dialog.
  505. //
  506. // RETURN VALUE:
  507. // TRUE if everything succeeded, FALSE otherwise.
  508. //
  509. //--------------------------------------------------------------------------------
  510. BOOL CProgressDlg::InitializeResultsList(HWND hwnd)
  511. {
  512. HWND hwndList = GetDlgItem(hwnd,IDC_LISTBOXERROR);
  513. LBDATA *pData = NULL;
  514. ULONG cbData = 0; // Allocated length of pData
  515. ULONG cchDataText = 0; // Allocated length of pData->pszText
  516. TCHAR pszError[MAX_STRING_RES];
  517. UINT ImageListflags;
  518. LoadString(g_hInst, IDS_NOERRORSREPORTED, pszError, ARRAYSIZE(pszError));
  519. if (!hwndList)
  520. return FALSE;
  521. // Allocate a struct for the item data
  522. cchDataText = ARRAYSIZE(pszError);
  523. cbData = sizeof(LBDATA) + cchDataText * sizeof(TCHAR);
  524. pData = (LBDATA *) ALLOC(cbData);
  525. if (!pData)
  526. {
  527. return FALSE;
  528. }
  529. pData->fIsJump = FALSE;
  530. pData->fTextRectValid = FALSE;
  531. pData->fHasBeenClicked = FALSE;
  532. pData->fAddLineSpacingAtEnd = FALSE;
  533. pData->ErrorID = GUID_NULL;
  534. pData->dwErrorLevel = SYNCMGRLOGLEVEL_INFORMATION;
  535. pData->pHandlerID = 0;
  536. StringCchCopy(pData->pszText, cchDataText, pszError);
  537. // create the error image list based on the current System
  538. // metrics
  539. m_iIconMetricX = GetSystemMetrics(SM_CXSMICON);
  540. m_iIconMetricY = GetSystemMetrics(SM_CYSMICON);
  541. ImageListflags = ILC_COLOR | ILC_MASK;
  542. if (IsHwndRightToLeft(hwnd))
  543. {
  544. ImageListflags |= ILC_MIRROR;
  545. }
  546. m_errorimage = ImageList_Create(m_iIconMetricX,m_iIconMetricY,ImageListflags, 0, MAX_ERR0R_ICONS);
  547. // load up the Error Images, if fail then just won't be an image next to the text
  548. if (m_errorimage)
  549. {
  550. m_ErrorImages[ErrorImage_Information] = ImageList_AddIcon(m_errorimage,LoadIcon(NULL,IDI_INFORMATION));
  551. m_ErrorImages[ErrorImage_Warning] = ImageList_AddIcon(m_errorimage,LoadIcon(NULL,IDI_WARNING));
  552. m_ErrorImages[ErrorImage_Error] = ImageList_AddIcon(m_errorimage,LoadIcon(NULL,IDI_ERROR));
  553. }
  554. else
  555. {
  556. m_ErrorImages[ErrorImage_Information] = m_ErrorImages[ErrorImage_Warning] =
  557. m_ErrorImages[ErrorImage_Error] = -1;
  558. }
  559. //Add a default Icon
  560. pData->IconIndex = m_ErrorImages[ErrorImage_Information];
  561. // Add the item data
  562. AddListData(pData, sizeof(pszError), hwndList);
  563. return TRUE;
  564. }
  565. void CProgressDlg::ReleaseDlg(WORD wCommandID)
  566. {
  567. // put into dead state so know not
  568. // addref/release
  569. PostMessage(m_hwnd,WM_PROGRESS_RELEASEDLGCMD,wCommandID,0);
  570. }
  571. // notifies choice dialog when it is actually released.
  572. void CProgressDlg::PrivReleaseDlg(WORD wCommandID)
  573. {
  574. m_dwProgressFlags |= PROGRESSFLAG_DEAD; // put us in the dead state.
  575. Assert(0 == m_dwQueueTransferCount); // shouldn't be going away if transfer is in progress!!
  576. RegSetProgressDetailsState(m_clsid,m_fPushpin, m_fExpanded);
  577. ShowWindow(m_hwnd,SW_HIDE);
  578. // if the tray is around hide it now.
  579. if (m_fHasShellTrayIcon)
  580. {
  581. RegisterShellTrayIcon(FALSE);
  582. m_fHasShellTrayIcon = FALSE;
  583. }
  584. switch (wCommandID)
  585. {
  586. case RELEASEDLGCMDID_OK: // on an okay sleep a little, then fall through to cancel.
  587. case RELEASEDLGCMDID_CANCEL:
  588. Assert(m_HndlrQueue);
  589. //
  590. // Fall through..
  591. //
  592. case RELEASEDLGCMDID_DESTROY: // called in Thread creation or initialize failed
  593. case RELEASEDLGCMDID_DEFAULT:
  594. if (m_HndlrQueue)
  595. {
  596. m_HndlrQueue->FreeAllHandlers();
  597. m_HndlrQueue->Release();
  598. m_HndlrQueue = NULL;
  599. }
  600. break;
  601. default:
  602. AssertSz(0,"Unknown Command");
  603. break;
  604. }
  605. Assert(m_hwnd);
  606. if (m_fHasShellTrayIcon)
  607. {
  608. RegisterShellTrayIcon(FALSE);
  609. }
  610. if (m_pSyncMgrIdle)
  611. {
  612. delete m_pSyncMgrIdle;
  613. }
  614. // if this is an idle progress then release our lock on the idle
  615. if (m_clsid == GUID_PROGRESSDLGIDLE)
  616. {
  617. ReleaseIdleLock();
  618. }
  619. if (m_pItemListView)
  620. {
  621. delete m_pItemListView;
  622. m_pItemListView = NULL;
  623. }
  624. if (m_hwnd)
  625. DestroyWindow(m_hwnd);
  626. delete this;
  627. return;
  628. }
  629. // updates window Z-Order and min/max state.
  630. void CProgressDlg::UpdateWndPosition(int nCmdShow,BOOL fForce)
  631. {
  632. BOOL fRemoveTrayIcon = FALSE;
  633. BOOL fWindowVisible = IsWindowVisible(m_hwnd);
  634. BOOL fTrayRequest = ((nCmdShow == SW_MINIMIZE)|| (nCmdShow == SW_SHOWMINIMIZED) || (nCmdShow == SW_HIDE));
  635. BOOL fHandledUpdate = FALSE;
  636. // only time we go to the tray is if the request is a minimize and
  637. // either the window is invisible or it is a force. note Hide for
  638. // now is treated as going to the tray.
  639. //
  640. // other cases or on tray failure we can just do a setforeground and show window.
  641. if (fTrayRequest && (fForce || !fWindowVisible))
  642. {
  643. if (m_fHasShellTrayIcon || RegisterShellTrayIcon(TRUE))
  644. {
  645. // if window was visible hide it and animiate
  646. if (fWindowVisible)
  647. {
  648. AnimateTray(TRUE);
  649. ShowWindow(m_hwnd,SW_HIDE);
  650. }
  651. fHandledUpdate = TRUE;
  652. }
  653. }
  654. if (!fHandledUpdate)
  655. {
  656. // if haven't handled then make sure window is shown and bring to
  657. // front
  658. if (m_fHasShellTrayIcon)
  659. {
  660. AnimateTray(FALSE);
  661. }
  662. ShowWindow(m_hwnd,SW_SHOW);
  663. SetForegroundWindow(m_hwnd);
  664. // if currently have a tray then lets animate
  665. // fAnimate = m_fHasShellTrayIcon ? TRUE : FALSE;
  666. // if the tray is around but we didn't register it this time through then it should
  667. // be removed
  668. if (m_fHasShellTrayIcon)
  669. {
  670. RegisterShellTrayIcon(FALSE);
  671. }
  672. }
  673. }
  674. //--------------------------------------------------------------------------------
  675. //
  676. // Member: CProgressDlg::AnimateTray
  677. //
  678. // PURPOSE: does animation to the tray
  679. //
  680. // COMMENTS: true means we are animating to the tray, false means back to the hwnd.
  681. //
  682. //
  683. //--------------------------------------------------------------------------------
  684. BOOL CProgressDlg::AnimateTray(BOOL fTrayAdded)
  685. {
  686. BOOL fAnimate;
  687. HWND hwndTray,hWndST;
  688. RECT rcDlg;
  689. RECT rcST;
  690. fAnimate = FALSE;
  691. // get rectangles for animation
  692. if (hwndTray = FindWindow(c_szTrayWindow, NULL))
  693. {
  694. if (hWndST = FindWindowEx(hwndTray, NULL, c_szTrayNotifyWindow, NULL))
  695. {
  696. GetWindowRect(m_hwnd, &rcDlg);
  697. GetWindowRect(hWndST, &rcST);
  698. fAnimate = TRUE;
  699. }
  700. }
  701. if (fAnimate)
  702. {
  703. if (fTrayAdded)
  704. {
  705. DrawAnimatedRects(m_hwnd, IDANI_CAPTION,&rcDlg,&rcST);
  706. }
  707. else
  708. {
  709. DrawAnimatedRects(m_hwnd, IDANI_CAPTION,&rcST,&rcDlg);
  710. }
  711. }
  712. return fAnimate;
  713. }
  714. //--------------------------------------------------------------------------------
  715. //
  716. // Member: CProgressDlg::RegisterShellTrayIcon
  717. //
  718. // PURPOSE: Registers/Unregisters the dialog in the Tray.
  719. //
  720. // COMMENTS: Up to Caller to do the proper thing with the main hwnd.
  721. //
  722. //
  723. //--------------------------------------------------------------------------------
  724. BOOL CProgressDlg::RegisterShellTrayIcon(BOOL fRegister)
  725. {
  726. NOTIFYICONDATA icondata;
  727. if (fRegister)
  728. {
  729. BOOL fResult;
  730. m_fHasShellTrayIcon = TRUE;
  731. fResult = UpdateTrayIcon();
  732. if (!fResult) // if couldn't ad then say its not added.
  733. {
  734. m_fHasShellTrayIcon = FALSE;
  735. }
  736. return fResult;
  737. }
  738. else // remove ouselves from the tray.
  739. {
  740. Assert(TRUE == m_fHasShellTrayIcon);
  741. icondata.cbSize = sizeof(NOTIFYICONDATA);
  742. icondata.hWnd = m_hwnd;
  743. icondata.uID = 1;
  744. m_fHasShellTrayIcon = FALSE;
  745. m_fAddedIconToTray = FALSE;
  746. // ShellNotifyIcon Yields
  747. Shell_NotifyIcon(NIM_DELETE,&icondata);
  748. }
  749. return TRUE;
  750. }
  751. // called to Update the TrayIcon, Keeps track of highest warning state
  752. // and sets the appropriate Icon in the tray. If the item is not already
  753. // in the tray UpdateTrayIcon will not do a thing.
  754. BOOL CProgressDlg::UpdateTrayIcon()
  755. {
  756. NOTIFYICONDATA icondata;
  757. DWORD dwReturn = 0;
  758. if (m_fHasShellTrayIcon)
  759. {
  760. icondata.cbSize = sizeof(NOTIFYICONDATA);
  761. icondata.hWnd = m_hwnd;
  762. icondata.uID = 1;
  763. icondata.uFlags = NIF_ICON | NIF_MESSAGE;
  764. icondata.uCallbackMessage = WM_PROGRESS_SHELLTRAYNOTIFICATION;
  765. // if progress animation is turned on then also animate
  766. // the tray.
  767. if (m_dwProgressFlags & PROGRESSFLAG_PROGRESSANIMATION)
  768. {
  769. // update the frame
  770. m_iTrayAniFrame++;
  771. if (m_iTrayAniFrame > IDI_SYSTRAYANI6)
  772. m_iTrayAniFrame = IDI_SYSTRAYANI1;
  773. icondata.hIcon = LoadIcon(g_hInst, MAKEINTRESOURCE(m_iTrayAniFrame));
  774. }
  775. else
  776. {
  777. // update the Icon and tip text based on the current state .
  778. // Review - Currently don't have different Icons.
  779. if (m_iErrorCount > 0)
  780. {
  781. icondata.hIcon = LoadIcon(g_hInst, MAKEINTRESOURCE(IDI_SYSTRAYERROR));
  782. }
  783. else if (m_iWarningCount > 0)
  784. {
  785. icondata.hIcon = LoadIcon(g_hInst, MAKEINTRESOURCE(IDI_SYSTRAYWARNING));
  786. }
  787. else
  788. {
  789. icondata.hIcon = LoadIcon(g_hInst, MAKEINTRESOURCE(IDI_SYSTRAYANI1));
  790. }
  791. }
  792. Assert(icondata.hIcon);
  793. TCHAR szBuf[MAX_STRING_RES];
  794. icondata.uFlags |= NIF_TIP;
  795. LoadString(g_hInst, IDS_SYNCMGRNAME, szBuf, ARRAYSIZE(szBuf));
  796. StringCchCopy(icondata.szTip, ARRAYSIZE(icondata.szTip), szBuf);
  797. dwReturn = Shell_NotifyIcon(m_fAddedIconToTray ? NIM_MODIFY : NIM_ADD ,&icondata);
  798. if (dwReturn)
  799. {
  800. // possible for Shell_NotifyIcon(NIM_DELETE) to come in while still
  801. // in shell notify call so only set m_fAddedIconTray to true
  802. // if still have a shell tray icon after the call.
  803. if (m_fHasShellTrayIcon)
  804. {
  805. m_fAddedIconToTray = TRUE;
  806. }
  807. return TRUE;
  808. }
  809. else
  810. {
  811. // possible this failed becuase a Shell_DeleteIcon was in progress
  812. // which yields check if really have a Shell Tray and if not
  813. // reset the AddedIcon Flag
  814. if (!m_fHasShellTrayIcon)
  815. {
  816. m_fAddedIconToTray = FALSE;
  817. }
  818. return FALSE;
  819. }
  820. }
  821. return FALSE;
  822. }
  823. // given an ID sets the appropriate state.
  824. BOOL CProgressDlg::SetButtonState(int nIDDlgItem,BOOL fEnabled)
  825. {
  826. BOOL fResult = FALSE;
  827. HWND hwndCtrl = GetDlgItem(m_hwnd,nIDDlgItem);
  828. HWND hwndFocus = NULL;
  829. if (hwndCtrl)
  830. {
  831. if (!fEnabled) // don't bother getting focus if not disabling.
  832. {
  833. hwndFocus = GetFocus();
  834. }
  835. fResult = EnableWindow(GetDlgItem(m_hwnd,nIDDlgItem),fEnabled);
  836. // if control had the focus. and now it doesn't then tab to the
  837. // next control
  838. if ( (hwndFocus == hwndCtrl) && !fEnabled)
  839. {
  840. SetFocus(GetDlgItem(m_hwnd,IDC_DETAILS));
  841. }
  842. }
  843. return fResult;
  844. }
  845. //+---------------------------------------------------------------------------
  846. //
  847. // Member: CProgressDlg::InitializeHwnd, private
  848. //
  849. // Synopsis: Called by WM_INIT.
  850. // m_hwnd member is not setup yet so refer to hwnd.
  851. //
  852. // Sets up items specific to the UI
  853. //
  854. // Arguments:
  855. //
  856. // Returns:
  857. //
  858. // Modifies:
  859. //
  860. // History: 30-Jul-98 rogerg Created.
  861. //
  862. //----------------------------------------------------------------------------
  863. BOOL CProgressDlg::InitializeHwnd(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
  864. {
  865. HWND hwndList = GetDlgItem(hwnd,IDC_LISTBOXERROR);
  866. m_hwnd = hwnd; // setup the hwnd.
  867. m_fHwndRightToLeft = IsHwndRightToLeft(m_hwnd);
  868. // IF THE HWND IS RIGHT TO LEFT HIDE
  869. // SIZE CONTROL UNTIL RESIZE WORKS.
  870. if (m_fHwndRightToLeft)
  871. {
  872. ShowWindow(GetDlgItem(m_hwnd,IDC_PROGRESSRESIZESCROLLBAR),SW_HIDE);
  873. }
  874. InterlockedExchange(&m_lTimerSet, 0);
  875. if (m_fnResultsListBox = (WNDPROC) GetWindowLongPtr(hwndList,GWLP_WNDPROC))
  876. {
  877. SetWindowLongPtr(hwndList, GWLP_WNDPROC, (LONG_PTR) ResultsListBoxWndProc);
  878. }
  879. m_cbNumDlgResizeItemsCollapsed = 0; // if fail then we don't resize anything.
  880. m_cbNumDlgResizeItemsExpanded = 0;
  881. // init resize items, be default nothing will move.
  882. m_ptMinimumDlgExpandedSize.x = 0;
  883. m_ptMinimumDlgExpandedSize.y = 0;
  884. m_cyCollapsed = 0;
  885. m_fExpanded = FALSE;
  886. m_fMaximized = FALSE;
  887. RECT rectParent;
  888. //Setup the toolbar pushpin
  889. InitializeToolbar(hwnd);
  890. if (GetClientRect(hwnd,&rectParent))
  891. {
  892. ULONG itemCount;
  893. DlgResizeList *pResizeList;
  894. // loop through resize list
  895. Assert(NUM_DLGRESIZEINFO_PROGRESS == (sizeof(g_ProgressResizeList)/sizeof(DlgResizeList)) );
  896. pResizeList = (DlgResizeList *) &g_ProgressResizeList;
  897. // loop through collapsed items
  898. for (itemCount = 0; itemCount < NUM_DLGRESIZEINFO_PROGRESS_COLLAPSED; ++itemCount)
  899. {
  900. if(InitResizeItem(pResizeList->iCtrlId,
  901. pResizeList->dwDlgResizeFlags,hwnd,&rectParent,&(m_dlgResizeInfo[m_cbNumDlgResizeItemsCollapsed])))
  902. {
  903. ++m_cbNumDlgResizeItemsCollapsed; // if fail then we don't resize anything.
  904. ++m_cbNumDlgResizeItemsExpanded;
  905. }
  906. ++pResizeList;
  907. }
  908. // loop through expanded items
  909. for (itemCount = NUM_DLGRESIZEINFO_PROGRESS_COLLAPSED;
  910. itemCount < NUM_DLGRESIZEINFO_PROGRESS; ++itemCount)
  911. {
  912. if(InitResizeItem(pResizeList->iCtrlId,
  913. pResizeList->dwDlgResizeFlags,hwnd,&rectParent,&(m_dlgResizeInfo[m_cbNumDlgResizeItemsExpanded])))
  914. {
  915. ++m_cbNumDlgResizeItemsExpanded;
  916. }
  917. ++pResizeList;
  918. }
  919. }
  920. // store the current width and height as the
  921. // the min for expanded and as the current expanded height
  922. // if GetWindowRect fails not much we can do.
  923. if (GetWindowRect(hwnd,&m_rcDlg))
  924. {
  925. RECT rcSep;
  926. m_ptMinimumDlgExpandedSize.x = m_rcDlg.right - m_rcDlg.left;
  927. m_ptMinimumDlgExpandedSize.y = m_rcDlg.bottom - m_rcDlg.top;
  928. // use the separator position as the max height when collapsed
  929. if (GetWindowRect(GetDlgItem(hwnd, IDC_SP_SEPARATOR), &rcSep))
  930. {
  931. m_cyCollapsed = rcSep.top - m_rcDlg.top;
  932. }
  933. }
  934. if (InitializeTabs(hwnd)) // If these fail user just won't see probress..
  935. {
  936. InitializeUpdateList(hwnd);
  937. InitializeResultsList(hwnd);
  938. }
  939. Animate_Open(GetDlgItem(hwnd,IDC_UPDATEAVI),MAKEINTRESOURCE(IDA_UPDATE));
  940. return TRUE; // return true if want to use default focus.
  941. }
  942. //--------------------------------------------------------------------------------
  943. //
  944. // FUNCTION: CProgressDlg::OnPaint()
  945. //
  946. // PURPOSE: Handle the WM_PAINT message dispatched from the dialog
  947. //
  948. //--------------------------------------------------------------------------------
  949. void CProgressDlg::OnPaint(UINT uMsg,WPARAM wParam,LPARAM lParam)
  950. {
  951. // if not currently animating and
  952. // have already added things to the dialog then draw the icons
  953. if (!(m_dwProgressFlags & PROGRESSFLAG_PROGRESSANIMATION)
  954. && !(m_dwProgressFlags & PROGRESSFLAG_NEWDIALOG) )
  955. {
  956. PAINTSTRUCT ps;
  957. HDC hDC = BeginPaint(m_hwnd, &ps);
  958. if (hDC)
  959. {
  960. HICON hIcon;
  961. if (m_iErrorCount > 0)
  962. {
  963. hIcon = LoadIcon(NULL,IDI_ERROR);
  964. }
  965. else if (m_iWarningCount > 0)
  966. {
  967. hIcon = LoadIcon(NULL,IDI_WARNING);
  968. }
  969. else
  970. {
  971. hIcon = LoadIcon(NULL,IDI_INFORMATION);
  972. }
  973. if (hIcon)
  974. {
  975. DrawIcon(hDC, 7, 10,hIcon);
  976. }
  977. EndPaint(m_hwnd, &ps);
  978. }
  979. }
  980. }
  981. //--------------------------------------------------------------------------------
  982. //
  983. // FUNCTION: CProgressDlg::RedrawIcon()
  984. //
  985. // PURPOSE: Clear/Draw the completed icon
  986. //
  987. //--------------------------------------------------------------------------------
  988. BOOL CProgressDlg::RedrawIcon()
  989. {
  990. RECT rc = {0, 0, 37, 40};
  991. InvalidateRect(m_hwnd, &rc, TRUE);
  992. return TRUE;
  993. }
  994. //+---------------------------------------------------------------------------
  995. //
  996. // Member: CProgressDlg::OnShowError, private
  997. //
  998. // Synopsis: Calls appropriate handlers ShowError method.
  999. //
  1000. // Arguments: [wHandlerId] - Id of handler to call.
  1001. // [hwndParent]- hwnd to use as the parent.
  1002. // [ErrorId] - Identifies the Error.
  1003. //
  1004. // Returns: S_OK - If ShowError was called
  1005. // S_FALSE - if already in ShowErrorCall
  1006. // appropriate error codes.
  1007. //
  1008. // Modifies:
  1009. //
  1010. // History: 04-Jun-98 rogerg Created.
  1011. //
  1012. //----------------------------------------------------------------------------
  1013. STDMETHODIMP CProgressDlg::OnShowError(HANDLERINFO *pHandlerId,HWND hwndParent,REFSYNCMGRERRORID ErrorID)
  1014. {
  1015. HRESULT hr = S_FALSE; // if don't call ShowError should return S_FALSE
  1016. // only allow one ShowError Call at a time.
  1017. if (!(m_dwProgressFlags & PROGRESSFLAG_INSHOWERRORSCALL) && !(m_dwProgressFlags & PROGRESSFLAG_DEAD))
  1018. {
  1019. Assert(!(m_dwProgressFlags & PROGRESSFLAG_SHOWERRORSCALLBACKCALLED));
  1020. m_dwProgressFlags |= PROGRESSFLAG_INSHOWERRORSCALL;
  1021. // hold alive - stick two references so we can always just release
  1022. // at end of ShowError and ShowErrorCompleted methods.
  1023. m_dwShowErrorRefCount += 2;
  1024. AddRefProgressDialog();
  1025. AddRefProgressDialog();
  1026. hr = m_HndlrQueue->ShowError(pHandlerId,hwndParent,ErrorID);
  1027. m_dwProgressFlags &= ~PROGRESSFLAG_INSHOWERRORSCALL;
  1028. // if callback with an hresult or retry came in while we were
  1029. // in our out call then post the transfer
  1030. if (m_dwProgressFlags & PROGRESSFLAG_SHOWERRORSCALLBACKCALLED)
  1031. {
  1032. m_dwProgressFlags &= ~PROGRESSFLAG_SHOWERRORSCALLBACKCALLED;
  1033. // need to sendmessage so queued up before release.
  1034. SendMessage(m_hwnd,WM_PROGRESS_TRANSFERQUEUEDATA,(WPARAM) 0, (LPARAM) NULL);
  1035. }
  1036. --m_dwShowErrorRefCount;
  1037. // count can go negative if handler calls completion routine on an error. if
  1038. // this is the case just set it to zero
  1039. if ( ((LONG) m_dwShowErrorRefCount) < 0)
  1040. {
  1041. AssertSz(0,"Negative ErrorCount");
  1042. m_dwShowErrorRefCount = 0;
  1043. }
  1044. else
  1045. {
  1046. ReleaseProgressDialog(m_fForceClose);
  1047. }
  1048. }
  1049. return hr;
  1050. }
  1051. //+---------------------------------------------------------------------------
  1052. //
  1053. // Member: CProgressDlg::OnResetKillHandlersTimers, private
  1054. //
  1055. // Synopsis: Called to reset the Kill Handlers
  1056. // Timer. Called as a SendMessage From the handlrqueue
  1057. // Cancel Call.
  1058. //
  1059. // !!!This funciton won't create the Timer if it doesn't
  1060. // already exist by design since queue could be in a cancel
  1061. // in a state we don't want to force kill as in the case
  1062. // of an offIdle
  1063. //
  1064. // Arguments:
  1065. //
  1066. // Returns:
  1067. //
  1068. // Modifies:
  1069. //
  1070. // History: 19-Nov-1998 rogerg Created.
  1071. //
  1072. //----------------------------------------------------------------------------
  1073. void CProgressDlg::OnResetKillHandlersTimers(void)
  1074. {
  1075. if (m_lTimerSet && !(m_dwProgressFlags & PROGRESSFLAG_INTERMINATE))
  1076. {
  1077. // SetTimer with the same hwnd and Id will replace the existing.
  1078. Assert(m_nKillHandlerTimeoutValue >= TIMERID_KILLHANDLERSMINTIME);
  1079. SetTimer(m_hwnd,TIMERID_KILLHANDLERS,m_nKillHandlerTimeoutValue,NULL);
  1080. }
  1081. }
  1082. //--------------------------------------------------------------------------------
  1083. //
  1084. // FUNCTION: CProgressDlg::OnCancel()
  1085. //
  1086. // PURPOSE: handles cancelling of the dialog
  1087. //
  1088. //--------------------------------------------------------------------------------
  1089. void CProgressDlg::OnCancel(BOOL fOffIdle)
  1090. {
  1091. // if dialog isn't dead and not in a showerrorcall then
  1092. // already in a cancel
  1093. // addref/release. if no more refs we will go away.
  1094. if (!fOffIdle)
  1095. {
  1096. // set cancelpressed flag if the user invoked the cancel.
  1097. m_dwProgressFlags |= PROGRESSFLAG_CANCELPRESSED;
  1098. if (!m_lTimerSet)
  1099. {
  1100. InterlockedExchange(&m_lTimerSet, 1);
  1101. Assert(m_nKillHandlerTimeoutValue >= TIMERID_KILLHANDLERSMINTIME);
  1102. SetTimer(m_hwnd,TIMERID_KILLHANDLERS,m_nKillHandlerTimeoutValue,NULL);
  1103. }
  1104. if ( (m_dwProgressFlags & PROGRESSFLAG_REGISTEREDFOROFFIDLE)
  1105. && !(m_dwProgressFlags & PROGRESSFLAG_RECEIVEDOFFIDLE) )
  1106. {
  1107. IdleCallback(STATE_USER_IDLE_END); // make sure offidle gets set if user presses cancel
  1108. }
  1109. }
  1110. if (!(m_dwProgressFlags & PROGRESSFLAG_DEAD) && !m_dwShowErrorRefCount
  1111. && !(m_dwProgressFlags & PROGRESSFLAG_INCANCELCALL)
  1112. && !(m_dwProgressFlags & PROGRESSFLAG_INTERMINATE))
  1113. {
  1114. // just cancel the queue, when items
  1115. // come though cancel
  1116. // it is possible that the dialog has already been removed from the
  1117. // object list and the User hit stop again.
  1118. SetProgressReleaseDlgCmdId(m_clsid,this,RELEASEDLGCMDID_CANCEL); // set so cleanup knows it was stopped by user..
  1119. // if handlethread is in shutdown then just fall through
  1120. if (!(m_dwProgressFlags & PROGRESSFLAG_SHUTTINGDOWNLOOP))
  1121. {
  1122. AddRefProgressDialog(); // hold dialog alive until cancel is complete
  1123. // Get the state of the stop button before the call
  1124. // because it could transition to close during the Canel
  1125. BOOL fForceShutdown = !(m_dwProgressFlags & PROGRESSFLAG_SYNCINGITEMS);
  1126. m_dwProgressFlags |= PROGRESSFLAG_INCANCELCALL;
  1127. if (m_dwProgressFlags & PROGRESSFLAG_SYNCINGITEMS)
  1128. {
  1129. //
  1130. // Replace the STOP button text with "Stopping" and
  1131. // disable the button. This gives the user positive feedback
  1132. // that the operation is being stopped. We'll re-enable
  1133. // the button whenever it's text is changed.
  1134. //
  1135. const HWND hwndStop = GetDlgItem(m_hwnd, IDSTOP);
  1136. TCHAR szText[80];
  1137. if (0 < LoadString(g_hInst, IDS_STOPPING, szText, ARRAYSIZE(szText)))
  1138. {
  1139. SetWindowText(hwndStop, szText);
  1140. }
  1141. EnableWindow(hwndStop, FALSE);
  1142. }
  1143. m_HndlrQueue->Cancel();
  1144. m_dwProgressFlags &= ~PROGRESSFLAG_INCANCELCALL;
  1145. // addref/release lifetime in case locked open.
  1146. // OffIdle case: then do a soft release so dialog doesn't
  1147. // go away.
  1148. // Non Idle case: Set the fForceClose After the call
  1149. // incase the pushpin change or errors came in during the Cancel
  1150. ReleaseProgressDialog(fOffIdle ? m_fForceClose : fForceShutdown );
  1151. }
  1152. else
  1153. {
  1154. // set flag so shutdown knows a cancel was pressed
  1155. m_dwProgressFlags |= PROGRESSFLAG_CANCELWHILESHUTTINGDOWN;
  1156. }
  1157. }
  1158. }
  1159. //--------------------------------------------------------------------------------
  1160. //
  1161. // FUNCTION: CProgressDlg::OnCommand()
  1162. //
  1163. // PURPOSE: Handle the various command messages dispatched from the dialog
  1164. //
  1165. //--------------------------------------------------------------------------------
  1166. void CProgressDlg::OnCommand(UINT uMsg,WPARAM wParam,LPARAM lParam)
  1167. {
  1168. WORD wID = LOWORD(wParam); // item, control, or accelerator identifier
  1169. WORD wNotifyCode HIWORD(wParam);
  1170. switch (wID)
  1171. {
  1172. case IDC_SKIP_BUTTON_MAIN:
  1173. {
  1174. if (m_pItemListView)
  1175. {
  1176. if (m_iProgressSelectedItem != -1)
  1177. {
  1178. //Skip this item:
  1179. if (!(m_dwProgressFlags & PROGRESSFLAG_DEAD))
  1180. {
  1181. LVHANDLERITEMBLOB lvHandlerItemBlob;
  1182. lvHandlerItemBlob.cbSize = sizeof(LVHANDLERITEMBLOB);
  1183. if (m_pItemListView->GetItemBlob(m_iProgressSelectedItem,
  1184. (LPLVBLOB) &lvHandlerItemBlob,lvHandlerItemBlob.cbSize))
  1185. {
  1186. ++m_dwSetItemStateRefCount;
  1187. AddRefProgressDialog();
  1188. m_HndlrQueue->SkipItem(lvHandlerItemBlob.clsidServer, lvHandlerItemBlob.ItemID);
  1189. --m_dwSetItemStateRefCount;
  1190. ReleaseProgressDialog(m_fForceClose);
  1191. }
  1192. }
  1193. //Disable the Skip button for this item
  1194. SetButtonState(IDC_SKIP_BUTTON_MAIN,FALSE);
  1195. }
  1196. }
  1197. }
  1198. break;
  1199. case IDC_PROGRESS_OPTIONS_BUTTON_MAIN:
  1200. {
  1201. // !!! if skip has the focus set it to settings since while the
  1202. // settings dialog is open the skip could go disabled.
  1203. if (GetFocus() == GetDlgItem(m_hwnd,IDC_SKIP_BUTTON_MAIN))
  1204. {
  1205. SetFocus(GetDlgItem(m_hwnd,IDC_PROGRESS_OPTIONS_BUTTON_MAIN));
  1206. }
  1207. ShowOptionsDialog(m_hwnd);
  1208. }
  1209. break;
  1210. case IDCANCEL:
  1211. wNotifyCode = BN_CLICKED; // make sure notify code is clicked and fall through
  1212. //
  1213. // Fall through..
  1214. //
  1215. case IDSTOP:
  1216. {
  1217. if (BN_CLICKED == wNotifyCode)
  1218. {
  1219. OnCancel(FALSE);
  1220. }
  1221. }
  1222. break;
  1223. case IDC_PUSHPIN:
  1224. {
  1225. UINT state = (UINT)SendDlgItemMessage(m_hwnd, IDC_TOOLBAR, TB_GETSTATE, IDC_PUSHPIN, 0);
  1226. m_fPushpin = state & TBSTATE_CHECKED;
  1227. SendDlgItemMessage(m_hwnd, IDC_TOOLBAR, TB_CHANGEBITMAP,
  1228. IDC_PUSHPIN,
  1229. MAKELPARAM(m_fPushpin ? IMAGE_TACK_IN : IMAGE_TACK_OUT, 0));
  1230. }
  1231. break;
  1232. case IDC_DETAILS:
  1233. ExpandCollapse(!m_fExpanded, FALSE);
  1234. break;
  1235. default:
  1236. break;
  1237. }
  1238. }
  1239. //--------------------------------------------------------------------------------
  1240. //
  1241. // FUNCTION: CProgressDlg::ShowProgressTab(int iTab)
  1242. //
  1243. // PURPOSE:
  1244. //
  1245. //--------------------------------------------------------------------------------
  1246. void CProgressDlg::ShowProgressTab(int iTab)
  1247. {
  1248. int nCmdUpdateTab;
  1249. int nCmdErrorTab;
  1250. int nCmdSettingsButton;
  1251. BOOL fIsItemWorking = FALSE;
  1252. m_iTab = iTab;
  1253. EnableWindow(GetDlgItem(m_hwnd, IDC_PROGRESS_TABS), m_fExpanded); // enable/disable tabs based on if dialog is expanded.
  1254. EnableWindow(GetDlgItem(m_hwnd, IDC_TOOLBAR), m_fExpanded); // enable/disable pushpin based on if dialog is expanded.
  1255. nCmdUpdateTab = ((iTab == PROGRESS_TAB_UPDATE) && (m_fExpanded)) ? SW_SHOW: SW_HIDE;
  1256. nCmdErrorTab = ((iTab == PROGRESS_TAB_ERRORS) && (m_fExpanded)) ? SW_SHOW: SW_HIDE;
  1257. nCmdSettingsButton = ((iTab == PROGRESS_TAB_UPDATE) && (m_fExpanded) && m_fSensInstalled) ? SW_SHOW: SW_HIDE;
  1258. switch (iTab)
  1259. {
  1260. case PROGRESS_TAB_UPDATE:
  1261. // Hide the error listview, show the tasks list
  1262. ShowWindow(GetDlgItem(m_hwnd,IDC_LISTBOXERROR), nCmdErrorTab);
  1263. TabCtrl_SetCurSel(m_hwndTabs, iTab);
  1264. EnableWindow(GetDlgItem(m_hwnd,IDC_UPDATE_LIST),m_fExpanded);
  1265. // only enable the skip button if there is a selection
  1266. // and IsItemWorking()
  1267. if (-1 != m_iProgressSelectedItem)
  1268. {
  1269. fIsItemWorking = IsItemWorking(m_iProgressSelectedItem);
  1270. }
  1271. EnableWindow(GetDlgItem(m_hwnd,IDC_SKIP_BUTTON_MAIN),m_fExpanded && fIsItemWorking);
  1272. EnableWindow(GetDlgItem(m_hwnd,IDC_PROGRESS_OPTIONS_BUTTON_MAIN),m_fExpanded && m_fSensInstalled);
  1273. EnableWindow(GetDlgItem(m_hwnd,IDC_LISTBOXERROR), FALSE);
  1274. ShowWindow(GetDlgItem(m_hwnd,IDC_STATIC_SKIP_TEXT),nCmdUpdateTab);
  1275. ShowWindow(GetDlgItem(m_hwnd,IDC_SKIP_BUTTON_MAIN),nCmdUpdateTab);
  1276. ShowWindow(GetDlgItem(m_hwnd,IDC_PROGRESS_OPTIONS_BUTTON_MAIN),nCmdSettingsButton);
  1277. ShowWindow(GetDlgItem(m_hwnd,IDC_UPDATE_LIST),nCmdUpdateTab);
  1278. break;
  1279. case PROGRESS_TAB_ERRORS:
  1280. // Hide the update listview, show the error list
  1281. ShowWindow(GetDlgItem(m_hwnd,IDC_UPDATE_LIST),nCmdUpdateTab);
  1282. ShowWindow(GetDlgItem(m_hwnd,IDC_STATIC_SKIP_TEXT),nCmdUpdateTab);
  1283. ShowWindow(GetDlgItem(m_hwnd,IDC_SKIP_BUTTON_MAIN),nCmdUpdateTab);
  1284. ShowWindow(GetDlgItem(m_hwnd,IDC_PROGRESS_OPTIONS_BUTTON_MAIN),nCmdSettingsButton);
  1285. TabCtrl_SetCurSel(m_hwndTabs, iTab);
  1286. EnableWindow(GetDlgItem(m_hwnd,IDC_UPDATE_LIST),FALSE);
  1287. EnableWindow(GetDlgItem(m_hwnd,IDC_SKIP_BUTTON_MAIN),FALSE);
  1288. EnableWindow(GetDlgItem(m_hwnd,IDC_PROGRESS_OPTIONS_BUTTON_MAIN),FALSE);
  1289. EnableWindow(GetDlgItem(m_hwnd,IDC_LISTBOXERROR), m_fExpanded);
  1290. ShowWindow(GetDlgItem(m_hwnd,IDC_LISTBOXERROR), nCmdErrorTab);
  1291. break;
  1292. default:
  1293. AssertSz(0,"Unknown Tab");
  1294. break;
  1295. }
  1296. }
  1297. //+---------------------------------------------------------------------------
  1298. //
  1299. // Member: CProgressDlg::IsItemWorking, private
  1300. //
  1301. // Synopsis: Determines if Skip should be enabled
  1302. // for the listViewItem;
  1303. //
  1304. // Arguments:
  1305. //
  1306. // Returns:
  1307. //
  1308. // Modifies:
  1309. //
  1310. // History: 12-Aug-98 rogerg Created.
  1311. //
  1312. //----------------------------------------------------------------------------
  1313. BOOL CProgressDlg::IsItemWorking(int iListViewItem)
  1314. {
  1315. BOOL fItemWorking;
  1316. LPARAM ItemStatus;
  1317. // lastest status is stored in the lParam of the ListBoxItem.
  1318. if (!(m_pItemListView->GetItemlParam(iListViewItem,&ItemStatus)))
  1319. {
  1320. ItemStatus = SYNCMGRSTATUS_STOPPED;
  1321. }
  1322. fItemWorking = ( ItemStatus == SYNCMGRSTATUS_PENDING ||
  1323. ItemStatus == SYNCMGRSTATUS_UPDATING ||
  1324. ItemStatus == SYNCMGRSTATUS_PAUSED ||
  1325. ItemStatus == SYNCMGRSTATUS_RESUMING );
  1326. return fItemWorking;
  1327. }
  1328. //+---------------------------------------------------------------------------
  1329. //
  1330. // Member: CProgressDlg::OnNotifyListViewEx, private
  1331. //
  1332. // Synopsis: Handles ListView Notifications
  1333. //
  1334. // Arguments:
  1335. //
  1336. // Returns:
  1337. //
  1338. // Modifies:
  1339. //
  1340. // History: 17-Jun-98 rogerg Created.
  1341. //
  1342. //----------------------------------------------------------------------------
  1343. LRESULT CProgressDlg::OnNotifyListViewEx(UINT uMsg,WPARAM wParam,LPARAM lParam)
  1344. {
  1345. int idCtrl = (int) wParam;
  1346. LPNMHDR pnmhdr = (LPNMHDR) lParam;
  1347. if ( (IDC_UPDATE_LIST != idCtrl) || (NULL == m_pItemListView))
  1348. {
  1349. Assert(IDC_UPDATE_LIST == idCtrl);
  1350. Assert(m_pItemListView);
  1351. return 0;
  1352. }
  1353. switch (pnmhdr->code)
  1354. {
  1355. case LVN_ITEMCHANGED:
  1356. {
  1357. NM_LISTVIEW *pnmv = (NM_LISTVIEW FAR *) pnmhdr;
  1358. if (pnmv->uChanged == LVIF_STATE)
  1359. {
  1360. if (pnmv->uNewState & LVIS_SELECTED)
  1361. {
  1362. m_iProgressSelectedItem = ((LPNMLISTVIEW) pnmhdr)->iItem;
  1363. // see if an item is selected and set the properties
  1364. // button accordingly
  1365. SetButtonState(IDC_SKIP_BUTTON_MAIN,IsItemWorking(m_iProgressSelectedItem));
  1366. }
  1367. else if (pnmv->uOldState & LVIS_SELECTED)
  1368. {
  1369. // on deselect see if any other selected items and if not
  1370. // set skip to false.
  1371. if (0 == m_pItemListView->GetSelectedCount())
  1372. {
  1373. m_iProgressSelectedItem = -1;
  1374. SetButtonState(IDC_SKIP_BUTTON_MAIN,FALSE);
  1375. }
  1376. }
  1377. }
  1378. break;
  1379. }
  1380. default:
  1381. break;
  1382. }
  1383. return 0;
  1384. }
  1385. //--------------------------------------------------------------------------------
  1386. //
  1387. // FUNCTION: CProgressDlg::OnNotify(HWND hwnd, int idFrom, LPNMHDR pnmhdr)
  1388. //
  1389. // PURPOSE: Handle the various notification messages dispatched from the dialog
  1390. //
  1391. //--------------------------------------------------------------------------------
  1392. LRESULT CProgressDlg::OnNotify(UINT uMsg,WPARAM wParam,LPARAM lParam)
  1393. {
  1394. int idFrom = (int) wParam;
  1395. LPNMHDR pnmhdr = (LPNMHDR) lParam;
  1396. // if notification for UpdateListPass it on.
  1397. if ((IDC_UPDATE_LIST == idFrom) && m_pItemListView)
  1398. {
  1399. return m_pItemListView->OnNotify(pnmhdr);
  1400. }
  1401. else if (IDC_TOOLBAR == idFrom)
  1402. {
  1403. if (pnmhdr->code == NM_KEYDOWN)
  1404. {
  1405. if (((LPNMKEY) lParam)->nVKey == TEXT(' ') )
  1406. {
  1407. UINT state = (UINT)SendDlgItemMessage(m_hwnd, IDC_TOOLBAR, TB_GETSTATE, IDC_PUSHPIN, 0);
  1408. state = state^TBSTATE_CHECKED;
  1409. SendDlgItemMessage(m_hwnd, IDC_TOOLBAR, TB_SETSTATE, IDC_PUSHPIN, state);
  1410. m_fPushpin = state & TBSTATE_CHECKED;
  1411. SendDlgItemMessage(m_hwnd, IDC_TOOLBAR, TB_CHANGEBITMAP, IDC_PUSHPIN,
  1412. MAKELPARAM(m_fPushpin ? IMAGE_TACK_IN : IMAGE_TACK_OUT, 0));
  1413. }
  1414. }
  1415. }
  1416. else if (IDC_PROGRESS_TABS == idFrom)
  1417. {
  1418. switch (pnmhdr->code)
  1419. {
  1420. case TCN_SELCHANGE:
  1421. {
  1422. // Find out which tab is currently active
  1423. m_iTab = TabCtrl_GetCurSel(GetDlgItem(m_hwnd, IDC_PROGRESS_TABS));
  1424. if (-1 == m_iTab)
  1425. {
  1426. break;
  1427. }
  1428. ShowProgressTab(m_iTab);
  1429. break;
  1430. }
  1431. default:
  1432. break;
  1433. }
  1434. }
  1435. return 0;
  1436. }
  1437. //--------------------------------------------------------------------------------
  1438. //
  1439. // FUNCTION: CProgressDlg::UpdateProgressValues()
  1440. //
  1441. // PURPOSE: Updates the value of the ProgressBar
  1442. //
  1443. //--------------------------------------------------------------------------------
  1444. void CProgressDlg::UpdateProgressValues()
  1445. {
  1446. int iProgValue;
  1447. int iMaxValue;
  1448. int iNumItemsComplete;
  1449. int iNumItemsTotal;
  1450. TCHAR pszComplete[MAX_STRING_RES];
  1451. if (!m_pItemListView || !m_HndlrQueue)
  1452. {
  1453. return;
  1454. }
  1455. LoadString(g_hInst, IDS_NUM_ITEMS_COMPLETE, pszComplete, ARRAYSIZE(pszComplete));
  1456. if (S_OK == m_HndlrQueue->GetProgressInfo(&iProgValue, &iMaxValue, &iNumItemsComplete, &iNumItemsTotal) )
  1457. {
  1458. HWND hwndProgress = GetDlgItem(m_hwnd,IDC_PROGRESSBAR);
  1459. TCHAR szHowManBuf[50];
  1460. if (hwndProgress)
  1461. {
  1462. SendMessage(hwndProgress,PBM_SETRANGE,0,MAKELPARAM(0, iMaxValue));
  1463. SendMessage(hwndProgress,PBM_SETPOS,(WPARAM) iProgValue,0);
  1464. }
  1465. StringCchPrintf(szHowManBuf, ARRAYSIZE(szHowManBuf), pszComplete, iNumItemsComplete, iNumItemsTotal);
  1466. Static_SetText(GetDlgItem(m_hwnd,IDC_STATIC_HOW_MANY_COMPLETE), szHowManBuf);
  1467. }
  1468. }
  1469. //--------------------------------------------------------------------------------
  1470. //
  1471. // FUNCTION: CProgressDlg::UpdateDetailsInfo(DWORD dwStatusType, HWND hwndList,
  1472. // int iItem, TCHAR *pszItemInfo)
  1473. //
  1474. // PURPOSE: provide info in the non-details progress view.
  1475. //
  1476. //--------------------------------------------------------------------------------
  1477. void CProgressDlg::UpdateDetailsInfo(DWORD dwStatusType,int iItem, TCHAR *pszItemInfo)
  1478. {
  1479. BOOL fNewNameField = TRUE;
  1480. BOOL fInfoField = FALSE;
  1481. TCHAR pszItemName[MAX_SYNCMGRITEMNAME + 1];
  1482. TCHAR pszFormatString[MAX_PATH + 1];
  1483. TCHAR pszNameString[MAX_PATH + 1];
  1484. if ((m_dwLastStatusType == dwStatusType) && (m_iLastItem == iItem))
  1485. {
  1486. fNewNameField = FALSE;
  1487. }
  1488. //Strip the item info of white space
  1489. if (pszItemInfo)
  1490. {
  1491. int i = lstrlen(pszItemInfo) - 1;
  1492. while (i >=0 &&
  1493. (pszItemInfo[i] == TEXT(' ') || pszItemInfo[i] == TEXT('\n')
  1494. || pszItemInfo[i] == TEXT('\t')))
  1495. {
  1496. pszItemInfo[i] = NULL;
  1497. i--;
  1498. }
  1499. if (i >= 0)
  1500. {
  1501. fInfoField = TRUE;
  1502. }
  1503. }
  1504. // If Called Callback for an Item in Pending mode
  1505. // but no item text don't bother updating the top display.
  1506. if ((SYNCMGRSTATUS_PENDING == dwStatusType) && (FALSE == fInfoField))
  1507. {
  1508. return;
  1509. }
  1510. m_dwLastStatusType = dwStatusType;
  1511. m_iLastItem = iItem;
  1512. if (fNewNameField && m_pItemListView)
  1513. {
  1514. //Get the item name
  1515. *pszItemName = NULL;
  1516. m_pItemListView->GetItemText(iItem, PROGRESSLIST_NAMECOLUMN, pszItemName, MAX_SYNCMGRITEMNAME);
  1517. switch (dwStatusType)
  1518. {
  1519. case SYNCMGRSTATUS_STOPPED:
  1520. {
  1521. LoadString(g_hInst, IDS_STOPPED_ITEM, pszFormatString, ARRAYSIZE(pszFormatString));
  1522. }
  1523. break;
  1524. case SYNCMGRSTATUS_SKIPPED:
  1525. {
  1526. LoadString(g_hInst, IDS_SKIPPED_ITEM, pszFormatString, ARRAYSIZE(pszFormatString));
  1527. }
  1528. break;
  1529. case SYNCMGRSTATUS_PENDING:
  1530. {
  1531. LoadString(g_hInst, IDS_PENDING_ITEM, pszFormatString, ARRAYSIZE(pszFormatString));
  1532. }
  1533. break;
  1534. case SYNCMGRSTATUS_UPDATING:
  1535. {
  1536. LoadString(g_hInst, IDS_SYNCHRONIZING_ITEM,pszFormatString, ARRAYSIZE(pszFormatString));
  1537. }
  1538. break;
  1539. case SYNCMGRSTATUS_SUCCEEDED:
  1540. {
  1541. LoadString(g_hInst, IDS_SUCCEEDED_ITEM,pszFormatString, ARRAYSIZE(pszFormatString));
  1542. }
  1543. break;
  1544. case SYNCMGRSTATUS_FAILED:
  1545. {
  1546. LoadString(g_hInst, IDS_FAILED_ITEM,pszFormatString, ARRAYSIZE(pszFormatString));
  1547. }
  1548. break;
  1549. case SYNCMGRSTATUS_PAUSED:
  1550. {
  1551. LoadString(g_hInst, IDS_PAUSED_ITEM,pszFormatString, ARRAYSIZE(pszFormatString));
  1552. }
  1553. break;
  1554. case SYNCMGRSTATUS_RESUMING:
  1555. {
  1556. LoadString(g_hInst, IDS_RESUMING_ITEM,pszFormatString, ARRAYSIZE(pszFormatString));
  1557. }
  1558. break;
  1559. default:
  1560. {
  1561. AssertSz(0,"Unknown Status Type");
  1562. StringCchCopy(pszFormatString, ARRAYSIZE(pszFormatString), TEXT("%ws"));
  1563. }
  1564. break;
  1565. }
  1566. StringCchPrintf(pszNameString, ARRAYSIZE(pszNameString), pszFormatString, pszItemName);
  1567. Static_SetText(GetDlgItem(m_hwnd,IDC_STATIC_WHATS_UPDATING), pszNameString);
  1568. }
  1569. // if don't have an info field but did update the name then set the info field
  1570. // to blank
  1571. if (fInfoField)
  1572. {
  1573. Static_SetText(GetDlgItem(m_hwnd,IDC_STATIC_WHATS_UPDATING_INFO), pszItemInfo);
  1574. }
  1575. else if (fNewNameField)
  1576. {
  1577. Static_SetText(GetDlgItem(m_hwnd,IDC_STATIC_WHATS_UPDATING_INFO), L"");
  1578. }
  1579. }
  1580. //--------------------------------------------------------------------------------
  1581. //
  1582. // FUNCTION: CProgressDlg::HandleProgressUpdate(HWND hwnd, WPARAM wParam,LPARAM lParam)
  1583. //
  1584. // PURPOSE: Handle the progress bar update for the progress dialog
  1585. //
  1586. //--------------------------------------------------------------------------------
  1587. void CProgressDlg::HandleProgressUpdate(HWND hwnd, WPARAM wParam,LPARAM lParam)
  1588. {
  1589. PROGRESSUPDATEDATA *progressData = (PROGRESSUPDATEDATA *) wParam;
  1590. SYNCMGRPROGRESSITEM *lpSyncProgressItem = (SYNCMGRPROGRESSITEM *) lParam;
  1591. LVHANDLERITEMBLOB lvHandlerItemBlob;
  1592. int iItem = -1;
  1593. BOOL fProgressItemChanged = FALSE;
  1594. if (!m_pItemListView)
  1595. {
  1596. return;
  1597. }
  1598. // if emptyItem is in list View delete it.
  1599. lvHandlerItemBlob.cbSize = sizeof(LVHANDLERITEMBLOB);
  1600. lvHandlerItemBlob.clsidServer = (progressData->clsidHandler);
  1601. lvHandlerItemBlob.ItemID = (progressData->ItemID);
  1602. iItem = m_pItemListView->FindItemFromBlob((LPLVBLOB) &lvHandlerItemBlob);
  1603. if (-1 == iItem)
  1604. {
  1605. AssertSz(0,"Progress Update on Item not in ListView");
  1606. return;
  1607. }
  1608. if (SYNCMGRPROGRESSITEM_STATUSTYPE & lpSyncProgressItem->mask)
  1609. {
  1610. if (lpSyncProgressItem->dwStatusType <= SYNCMGRSTATUS_RESUMING)
  1611. {
  1612. // update the listview items lParam
  1613. m_pItemListView->SetItemlParam(iItem,lpSyncProgressItem->dwStatusType);
  1614. m_pItemListView->SetItemText(iItem,PROGRESSLIST_STATUSCOLUMN,
  1615. m_pszStatusText[lpSyncProgressItem->dwStatusType]);
  1616. //Update Skip button if this item is selected
  1617. if (m_iProgressSelectedItem == iItem)
  1618. {
  1619. BOOL fItemComplete = ( (lpSyncProgressItem->dwStatusType == SYNCMGRSTATUS_SUCCEEDED) ||
  1620. (lpSyncProgressItem->dwStatusType == SYNCMGRSTATUS_FAILED) ||
  1621. (lpSyncProgressItem->dwStatusType == SYNCMGRSTATUS_SKIPPED) ||
  1622. (lpSyncProgressItem->dwStatusType == SYNCMGRSTATUS_STOPPED) );
  1623. EnableWindow(GetDlgItem(m_hwnd,IDC_SKIP_BUTTON_MAIN),!fItemComplete);
  1624. }
  1625. }
  1626. }
  1627. if (SYNCMGRPROGRESSITEM_STATUSTEXT & lpSyncProgressItem->mask )
  1628. {
  1629. #define MAXDISPLAYBUF 256
  1630. TCHAR displaybuf[MAXDISPLAYBUF]; // make a local copy of ths display buf
  1631. *displaybuf = NULL;
  1632. if (lpSyncProgressItem->lpcStatusText)
  1633. {
  1634. StringCchCopy(displaybuf, ARRAYSIZE(displaybuf), lpSyncProgressItem->lpcStatusText);
  1635. TCHAR *pEndBuf = displaybuf + MAXDISPLAYBUF -1;
  1636. *pEndBuf = NULL;
  1637. }
  1638. m_pItemListView->SetItemText(iItem,PROGRESSLIST_INFOCOLUMN,displaybuf);
  1639. LPARAM ItemStatus;
  1640. if (!(SYNCMGRPROGRESSITEM_STATUSTYPE & lpSyncProgressItem->mask))
  1641. {
  1642. if (!(m_pItemListView->GetItemlParam(iItem,&ItemStatus)))
  1643. {
  1644. AssertSz(0,"failed to get item lParam");
  1645. ItemStatus = SYNCMGRSTATUS_STOPPED;
  1646. }
  1647. }
  1648. else
  1649. {
  1650. ItemStatus = lpSyncProgressItem->dwStatusType;
  1651. }
  1652. Assert(ItemStatus == ((LPARAM) (DWORD) ItemStatus));
  1653. UpdateDetailsInfo( (DWORD) ItemStatus,iItem, displaybuf);
  1654. }
  1655. // now update the items progress value information
  1656. if (S_OK == m_HndlrQueue->SetItemProgressInfo( progressData->pHandlerID,
  1657. progressData->wItemId,
  1658. lpSyncProgressItem,
  1659. &fProgressItemChanged))
  1660. {
  1661. // recalcing the progress bar and numItems completed values
  1662. // can become expensive with a large amount of items so it callback
  1663. // was called but didn't change status or min/max of the item
  1664. // don't bother updating the progress values.
  1665. if (fProgressItemChanged)
  1666. {
  1667. UpdateProgressValues();
  1668. }
  1669. }
  1670. }
  1671. //--------------------------------------------------------------------------------
  1672. //
  1673. // FUNCTION: CProgressDlg::AddListData(LBDATA *pData,int iNumChars, HWND hwndList)
  1674. //
  1675. // PURPOSE: Handle the adding item data to the list for the results pane
  1676. //
  1677. //--------------------------------------------------------------------------------
  1678. void CProgressDlg::AddListData(LBDATA *pData, int iNumChars, HWND hwndList)
  1679. {
  1680. // Save current item in global for use by MeasureItem handler
  1681. Assert(NULL == m_CurrentListEntry); // catch any recursion case.
  1682. m_CurrentListEntry = pData;
  1683. // ... add the string first...
  1684. //the text is freed by the list box
  1685. int iItem = ListBox_AddString( hwndList, pData->pszText);
  1686. // (Note that the WM_MEASUREITEM is sent at this point)
  1687. // ...now attach the data.
  1688. ListBox_SetItemData( hwndList, iItem, pData);
  1689. m_CurrentListEntry = NULL;
  1690. // pData is freed by the list box
  1691. }
  1692. //--------------------------------------------------------------------------------
  1693. //
  1694. // FUNCTION: CProgressDlg::HandleLogError(HWND hwnd, WORD pHandlerID,MSGLogErrors *msgLogErrors)
  1695. //
  1696. // PURPOSE: Handle the error logging tab for the progress dialog
  1697. //
  1698. //--------------------------------------------------------------------------------
  1699. void CProgressDlg::HandleLogError(HWND hwnd, HANDLERINFO *pHandlerID,MSGLogErrors *lpmsgLogErrors)
  1700. {
  1701. LBDATA *pData = NULL;
  1702. INT iNumChars;
  1703. TCHAR szBuffer[MAX_STRING_RES]; // buffer used for loading string resources
  1704. HWND hwndList;
  1705. hwndList = GetDlgItem(m_hwnd,IDC_LISTBOXERROR);
  1706. if (!hwndList)
  1707. {
  1708. return;
  1709. }
  1710. //Remove the "No Errors" when the first error is encountered
  1711. if (++m_iResultCount == 0)
  1712. {
  1713. ListBox_ResetContent(hwndList);
  1714. }
  1715. // determine if handlerId and ItemId are valid.ItemID
  1716. // if handlerId isn't valid we don't bother with the ItemId
  1717. SYNCMGRHANDLERINFO SyncMgrHandlerInfo;
  1718. SYNCMGRITEM offlineItem;
  1719. DWORD cchItemLen = 0;
  1720. DWORD cchHandlerLen = 0;
  1721. UINT uIDResource;
  1722. // preset both to NULL
  1723. *(SyncMgrHandlerInfo.wszHandlerName) = NULL;
  1724. *(offlineItem.wszItemName) = NULL;
  1725. // if can't get the ParentInfo then don't add the Item
  1726. // pHandlerId can be NULL if we logged the Error Ourselves.
  1727. if (pHandlerID && m_HndlrQueue
  1728. && (S_OK == m_HndlrQueue->GetHandlerInfo(pHandlerID,&SyncMgrHandlerInfo)))
  1729. {
  1730. cchHandlerLen = lstrlen(SyncMgrHandlerInfo.wszHandlerName);
  1731. // now see if we can get the itemName.
  1732. if (lpmsgLogErrors->mask & SYNCMGRLOGERROR_ITEMID)
  1733. {
  1734. BOOL fHiddenItem;
  1735. CLSID clsidDataHandler;
  1736. if (S_OK == m_HndlrQueue->GetItemDataAtIndex(pHandlerID, lpmsgLogErrors->ItemID,
  1737. &clsidDataHandler,&offlineItem,&fHiddenItem) )
  1738. {
  1739. cchItemLen = lstrlen(offlineItem.wszItemName);
  1740. }
  1741. }
  1742. }
  1743. // note: handlerName can be an empty string even if GetHandlerInfo did not fail and we
  1744. // can still have an Item so need to do the right thing.
  1745. // cases
  1746. // valid handler and ItemID in LogError
  1747. // 1) <icon> <handler name> <(item name)>: <message> (valid handler and ItemID in LogError)
  1748. // 2) <icon> <(item name)>: <message> handler name NULL .
  1749. // 3) <icon> <handler name>: <message> only valid handler in LogError
  1750. // 4) <icon> <message> (handler invalid or mobsync error in LogError)
  1751. // => three different format strings
  1752. // 1,2 - "%ws (%ws): %ws" // valid item
  1753. // 3 - "%ws: %ws" // only valid handler.
  1754. // 4 - "%ws" // no handler or item
  1755. if (cchItemLen)
  1756. {
  1757. uIDResource = IDS_LOGERRORWITHITEMID;
  1758. }
  1759. else if (cchHandlerLen)
  1760. {
  1761. uIDResource = IDS_LOGERRORNOITEMID;
  1762. }
  1763. else
  1764. {
  1765. uIDResource = IDS_LOGERRORNOHANDLER;
  1766. }
  1767. if (0 == LoadString(g_hInst, uIDResource, szBuffer, ARRAYSIZE(szBuffer)))
  1768. {
  1769. // if couldn't loadstring then set to empty string so an empty string
  1770. // gets logged. If string is truncated will just print the trucated string.
  1771. *szBuffer = NULL;
  1772. }
  1773. // get the number of characters we need to allocate for
  1774. iNumChars = lstrlen(lpmsgLogErrors->lpcErrorText)
  1775. + cchHandlerLen
  1776. + cchItemLen
  1777. + lstrlen(szBuffer);
  1778. // Allocate a struct for the item data
  1779. if ( !(pData = (LBDATA *) ALLOC(sizeof(LBDATA) + ( (iNumChars+1) *sizeof(TCHAR)))) )
  1780. {
  1781. return;
  1782. }
  1783. // now format the string using the same logic as used to load
  1784. // the proper resource
  1785. if (cchItemLen)
  1786. {
  1787. StringCchPrintf(pData->pszText, iNumChars+1, szBuffer, SyncMgrHandlerInfo.wszHandlerName,
  1788. offlineItem.wszItemName, lpmsgLogErrors->lpcErrorText);
  1789. }
  1790. else if (cchHandlerLen)
  1791. {
  1792. StringCchPrintf(pData->pszText, iNumChars+1, szBuffer, SyncMgrHandlerInfo.wszHandlerName,
  1793. lpmsgLogErrors->lpcErrorText);
  1794. }
  1795. else
  1796. {
  1797. StringCchPrintf(pData->pszText, iNumChars+1, szBuffer, lpmsgLogErrors->lpcErrorText);
  1798. }
  1799. // error text is not a jump but has same ErrorID
  1800. pData->fIsJump = FALSE;
  1801. pData->fTextRectValid = FALSE;
  1802. pData->ErrorID = lpmsgLogErrors->ErrorID;
  1803. pData->dwErrorLevel = lpmsgLogErrors->dwErrorLevel;
  1804. pData->pHandlerID = pHandlerID;
  1805. pData->fHasBeenClicked = FALSE;
  1806. pData->fAddLineSpacingAtEnd = FALSE;
  1807. // insert the icon
  1808. // ToDo: Add client customizable icons?
  1809. switch (lpmsgLogErrors->dwErrorLevel)
  1810. {
  1811. case SYNCMGRLOGLEVEL_INFORMATION:
  1812. pData->IconIndex = m_ErrorImages[ErrorImage_Information];
  1813. break;
  1814. case SYNCMGRLOGLEVEL_WARNING:
  1815. ++m_iWarningCount;
  1816. pData->IconIndex = m_ErrorImages[ErrorImage_Warning];
  1817. break;
  1818. case SYNCMGRLOGLEVEL_ERROR:
  1819. default:
  1820. // if an error occurs we want to keep the dialog alive
  1821. ++m_iErrorCount;
  1822. pData->IconIndex = m_ErrorImages[ErrorImage_Error];
  1823. break;
  1824. }
  1825. if (!lpmsgLogErrors->fHasErrorJumps)
  1826. {
  1827. pData->fAddLineSpacingAtEnd = TRUE;
  1828. }
  1829. // Add the item data
  1830. AddListData(pData, (iNumChars)*sizeof(TCHAR), hwndList);
  1831. if (lpmsgLogErrors->fHasErrorJumps)
  1832. {
  1833. //This is make the "For more info" apprear closer,
  1834. //More associated with the item it corresponds to
  1835. // Allocate a struct for the item data
  1836. LoadString(g_hInst, IDS_JUMPTEXT, szBuffer, ARRAYSIZE(szBuffer));
  1837. // Review, why not strlen instead of total size of szBuffer.
  1838. iNumChars = ARRAYSIZE(szBuffer);
  1839. pData = (LBDATA *) ALLOC(sizeof(LBDATA) + iNumChars * sizeof(TCHAR));
  1840. if (!pData)
  1841. {
  1842. return;
  1843. }
  1844. pData->IconIndex = -1;
  1845. // we always set ErrorID to GUID_NULL if one wasn't given
  1846. // and fHasErrorJumps to false.
  1847. pData->fIsJump = lpmsgLogErrors->fHasErrorJumps;
  1848. pData->fTextRectValid = FALSE;
  1849. pData->ErrorID = lpmsgLogErrors->ErrorID;
  1850. pData->dwErrorLevel = lpmsgLogErrors->dwErrorLevel;
  1851. pData->pHandlerID = pHandlerID;
  1852. pData->fHasBeenClicked = FALSE;
  1853. pData->fAddLineSpacingAtEnd = TRUE; // always put space after
  1854. StringCchCopy(pData->pszText, iNumChars, szBuffer);
  1855. AddListData(pData, sizeof(szBuffer), hwndList);
  1856. }
  1857. // new item could have caused the Scrollbar to be drawn. Need to
  1858. // recalc listbox
  1859. OnProgressResultsSize(m_hwnd,this,WM_SIZE,0,0);
  1860. // if tray icon is shown and not currently syncing any items
  1861. // make sure it has the most up to date info. if syncing just
  1862. // let the timer.
  1863. if (!(m_dwProgressFlags & PROGRESSFLAG_SYNCINGITEMS))
  1864. {
  1865. UpdateTrayIcon();
  1866. }
  1867. return;
  1868. }
  1869. //--------------------------------------------------------------------------------
  1870. //
  1871. // FUNCTION: CProgressDlg::HandleDeleteLogError(HWND hwnds)
  1872. //
  1873. // PURPOSE: Deletes matching errors that have been logged.
  1874. //
  1875. //--------------------------------------------------------------------------------
  1876. void CProgressDlg::HandleDeleteLogError(HWND hwnd,MSGDeleteLogErrors *pDeleteLogError)
  1877. {
  1878. HWND hwndList = GetDlgItem(m_hwnd,IDC_LISTBOXERROR);
  1879. int iItemCount;
  1880. LBDATA *pData = NULL;
  1881. if (NULL == hwndList)
  1882. return;
  1883. iItemCount = ListBox_GetCount(hwndList);
  1884. // loop through the logged errors finding any matches.
  1885. // if the passed in ErrorID is GUID_NULL then delete all errors associated with this
  1886. // handler.
  1887. while(iItemCount--)
  1888. {
  1889. if (pData = (LBDATA *) ListBox_GetItemData(hwndList,iItemCount))
  1890. {
  1891. if ((pData->pHandlerID == pDeleteLogError->pHandlerId)
  1892. && ( (pData->ErrorID == pDeleteLogError->ErrorID)
  1893. || (GUID_NULL == pDeleteLogError->ErrorID) )
  1894. )
  1895. {
  1896. if ( !pData->fIsJump )
  1897. {
  1898. //
  1899. // Decrement count for non-jump items only to avoid
  1900. // double decrements.
  1901. //
  1902. m_iResultCount--;
  1903. if ( pData->dwErrorLevel == SYNCMGRLOGLEVEL_WARNING )
  1904. {
  1905. Assert( m_iWarningCount > 0 );
  1906. m_iWarningCount--;
  1907. }
  1908. else if ( pData->dwErrorLevel == SYNCMGRLOGLEVEL_ERROR )
  1909. {
  1910. Assert( m_iErrorCount > 0 );
  1911. m_iErrorCount--;
  1912. }
  1913. }
  1914. ListBox_DeleteString(hwndList,iItemCount);
  1915. }
  1916. }
  1917. }
  1918. //
  1919. // If all items have been removed, add default no-error item
  1920. //
  1921. iItemCount = ListBox_GetCount(hwndList);
  1922. if ( iItemCount == 0 )
  1923. {
  1924. m_iResultCount = -1;
  1925. TCHAR pszError[MAX_STRING_RES];
  1926. LoadString(g_hInst, IDS_NOERRORSREPORTED, pszError, ARRAYSIZE(pszError));
  1927. //
  1928. // Allocate a struct for the item data
  1929. //
  1930. DWORD cchDataText = 0;
  1931. cchDataText = ARRAYSIZE(pszError);
  1932. pData = (LBDATA *) ALLOC(sizeof(LBDATA) + ARRAYSIZE(pszError)*sizeof(TCHAR));
  1933. if (!pData)
  1934. return;
  1935. pData->fIsJump = FALSE;
  1936. pData->fTextRectValid = FALSE;
  1937. pData->fHasBeenClicked = FALSE;
  1938. pData->fAddLineSpacingAtEnd = FALSE;
  1939. pData->ErrorID = GUID_NULL;
  1940. pData->dwErrorLevel = SYNCMGRLOGLEVEL_INFORMATION;
  1941. pData->pHandlerID = 0;
  1942. StringCchCopy(pData->pszText, cchDataText, pszError);
  1943. pData->IconIndex = m_ErrorImages[ErrorImage_Information];
  1944. AddListData(pData, sizeof(pszError), hwndList);
  1945. }
  1946. // recalc listbox heights to accomodate the new value.
  1947. OnProgressResultsSize(m_hwnd,this,WM_SIZE,0,0);
  1948. // if tray icon is shown and not currently syncing any items
  1949. // make sure it has the most up to date info. if syncing just
  1950. // let the timer.
  1951. if (!(m_dwProgressFlags & PROGRESSFLAG_SYNCINGITEMS))
  1952. UpdateTrayIcon();
  1953. }
  1954. //--------------------------------------------------------------------------------
  1955. //
  1956. // FUNCTION: BOOL CProgressDlg::ShowCompletedProgress(BOOL fComplete)
  1957. //
  1958. // PURPOSE: Show the dialog in the completed state
  1959. //
  1960. //--------------------------------------------------------------------------------
  1961. BOOL CProgressDlg::ShowCompletedProgress(BOOL fComplete,BOOL fDialogIsLocked)
  1962. {
  1963. TCHAR szBuf[MAX_STRING_RES];
  1964. LoadString( g_hInst,
  1965. fComplete? IDS_PROGRESSCOMPLETETITLE : IDS_PROGRESSWORKINGTITLE,
  1966. szBuf,
  1967. ARRAYSIZE(szBuf));
  1968. SetWindowText(m_hwnd, szBuf);
  1969. if (fComplete)
  1970. {
  1971. ShowWindow(GetDlgItem(m_hwnd,IDC_UPDATEAVI), SW_HIDE);
  1972. ShowWindow(GetDlgItem(m_hwnd,IDC_FOLDER1), SW_HIDE);
  1973. ShowWindow(GetDlgItem(m_hwnd,IDC_FOLDER2), SW_HIDE);
  1974. ShowWindow(GetDlgItem(m_hwnd,IDC_STATIC_WHATS_UPDATING), SW_HIDE);
  1975. ShowWindow(GetDlgItem(m_hwnd,IDC_STATIC_WHATS_UPDATING_INFO), SW_HIDE);
  1976. ShowWindow(GetDlgItem(m_hwnd,IDC_PROGRESSBAR), SW_HIDE);
  1977. ShowWindow(GetDlgItem(m_hwnd,IDC_STATIC_HOW_MANY_COMPLETE), SW_HIDE);
  1978. if (m_iErrorCount > 0 )
  1979. {
  1980. LoadString(g_hInst, IDS_PROGRESSCOMPLETEERROR, szBuf, ARRAYSIZE(szBuf));
  1981. }
  1982. else if (m_iWarningCount > 0 )
  1983. {
  1984. LoadString(g_hInst, IDS_PROGRESSCOMPLETEWARNING, szBuf, ARRAYSIZE(szBuf));
  1985. }
  1986. else
  1987. {
  1988. LoadString(g_hInst, IDS_PROGRESSCOMPLETEOK, szBuf, ARRAYSIZE(szBuf));
  1989. }
  1990. SetDlgItemText(m_hwnd, IDC_RESULTTEXT, szBuf);
  1991. ShowWindow(GetDlgItem(m_hwnd,IDC_RESULTTEXT), SW_SHOW);
  1992. //Change the Stop to "Close" if the dialog is going to be remained open
  1993. if (fDialogIsLocked)
  1994. {
  1995. LoadString(g_hInst, IDS_CLOSE, szBuf, ARRAYSIZE(szBuf));
  1996. SetWindowText(GetDlgItem(m_hwnd,IDSTOP), szBuf);
  1997. EnableWindow(GetDlgItem(m_hwnd,IDSTOP), TRUE);
  1998. }
  1999. }
  2000. else
  2001. {
  2002. ShowWindow(GetDlgItem(m_hwnd,IDC_RESULTTEXT), SW_HIDE);
  2003. ShowWindow(GetDlgItem(m_hwnd,IDC_UPDATEAVI), SW_SHOW);
  2004. ShowWindow(GetDlgItem(m_hwnd,IDC_FOLDER1), SW_SHOW);
  2005. ShowWindow(GetDlgItem(m_hwnd,IDC_FOLDER2), SW_SHOW);
  2006. ShowWindow(GetDlgItem(m_hwnd,IDC_STATIC_WHATS_UPDATING), SW_SHOW);
  2007. ShowWindow(GetDlgItem(m_hwnd,IDC_STATIC_WHATS_UPDATING_INFO), SW_SHOW);
  2008. ShowWindow(GetDlgItem(m_hwnd,IDC_PROGRESSBAR), SW_SHOW);
  2009. ShowWindow(GetDlgItem(m_hwnd,IDC_STATIC_HOW_MANY_COMPLETE), SW_SHOW);
  2010. //Change the "Close" to "Stop"
  2011. LoadString(g_hInst, IDS_STOP, szBuf, ARRAYSIZE(szBuf));
  2012. SetWindowText(GetDlgItem(m_hwnd,IDSTOP), szBuf);
  2013. EnableWindow(GetDlgItem(m_hwnd,IDSTOP), TRUE);
  2014. }
  2015. RedrawIcon();
  2016. return TRUE;
  2017. }
  2018. //--------------------------------------------------------------------------------
  2019. //
  2020. // Function: DoSyncTask
  2021. //
  2022. // Synopsis: Drives the handlers actual synchronization routines
  2023. //
  2024. //--------------------------------------------------------------------------------
  2025. void CProgressDlg::DoSyncTask(HWND hwnd)
  2026. {
  2027. HANDLERINFO *pHandlerID;
  2028. ULONG cDlgRefs;
  2029. BOOL fRepostedStart = FALSE; // set if posted message to ourselves.
  2030. CLSID pHandlerClsid;
  2031. Assert(!(m_dwProgressFlags & PROGRESSFLAG_DEAD));
  2032. ++m_dwHandleThreadNestcount;
  2033. // if handlerNestCount is > 1 which it can on a transfer
  2034. // or when multiple items are going even on an error
  2035. // if this is the case then just return
  2036. if (m_dwHandleThreadNestcount > 1)
  2037. {
  2038. Assert(1 == m_dwHandleThreadNestcount);
  2039. m_dwHandleThreadNestcount--;
  2040. return;
  2041. }
  2042. // review - order should be set inhandleroutcall
  2043. // an then reset flags for completion and transfers.
  2044. // reset callback flag so receive another one if
  2045. // message comes in
  2046. m_dwProgressFlags &= ~PROGRESSFLAG_CALLBACKPOSTED;
  2047. // first thing through make sure all our state is setup.
  2048. // set the syncing flag
  2049. m_dwProgressFlags |= PROGRESSFLAG_SYNCINGITEMS;
  2050. // set our Call flag so callback knows not to post to us
  2051. // if we are handling call
  2052. Assert(!(m_dwProgressFlags & PROGRESSFLAG_INHANDLEROUTCALL));
  2053. m_dwProgressFlags |= PROGRESSFLAG_INHANDLEROUTCALL;
  2054. m_dwProgressFlags &= ~PROGRESSFLAG_COMPLETIONROUTINEWHILEINOUTCALL; // reset completion routine
  2055. m_dwProgressFlags &= ~PROGRESSFLAG_NEWITEMSINQUEUE; // reset new items in queue flag
  2056. m_dwProgressFlags &= ~PROGRESSFLAG_STARTPROGRESSPOSTED; // reset post flag.
  2057. if (!(m_dwProgressFlags & PROGRESSFLAG_IDLENETWORKTIMER))
  2058. {
  2059. m_dwProgressFlags |= PROGRESSFLAG_IDLENETWORKTIMER;
  2060. // reset network idle initially to keep hangup from happening and setup a timer
  2061. // to keep resetting the idle until the sync is complete.
  2062. ResetNetworkIdle();
  2063. SetTimer(m_hwnd,TIMERID_NOIDLEHANGUP,NOIDLEHANGUP_REFRESHRATE,NULL);
  2064. }
  2065. UpdateProgressValues();
  2066. if (m_clsid != GUID_PROGRESSDLGIDLE)
  2067. {
  2068. // if there is a server we are currently synchronizing but out count
  2069. // is zero then reset to GUID_NULL else use our clsidHandlerInSync
  2070. // so next handler matches the one we are currently syncing.
  2071. if (0 == m_dwHandlerOutCallCount) // if no outcalls we don't care what handler gets matched.
  2072. {
  2073. m_clsidHandlerInSync = GUID_NULL;
  2074. }
  2075. // find the next set of items that match our criteria by seeing
  2076. // if there is any handler that matches out guid (if guid_null just
  2077. // matches first item in state
  2078. // then loop through all handlers matching the guid
  2079. // in the same state.
  2080. // see if there are any items that need PrepareForSyncCalled on them
  2081. if (S_OK == m_HndlrQueue->FindFirstHandlerInState(
  2082. HANDLERSTATE_PREPAREFORSYNC,m_clsidHandlerInSync,
  2083. &pHandlerID,&m_clsidHandlerInSync))
  2084. {
  2085. ++m_dwHandlerOutCallCount;
  2086. ++m_dwPrepareForSyncOutCallCount;
  2087. m_HndlrQueue->PrepareForSync(pHandlerID,hwnd);
  2088. // see if any other handlers that match the clsid and also call their
  2089. // PrepareForSync methods.
  2090. while (S_OK == m_HndlrQueue->FindFirstHandlerInState(
  2091. HANDLERSTATE_PREPAREFORSYNC,m_clsidHandlerInSync,
  2092. &pHandlerID,&m_clsidHandlerInSync))
  2093. {
  2094. ++m_dwHandlerOutCallCount;
  2095. ++m_dwPrepareForSyncOutCallCount;
  2096. m_HndlrQueue->PrepareForSync(pHandlerID,hwnd);
  2097. }
  2098. }
  2099. else if ( (0 == m_dwPrepareForSyncOutCallCount)
  2100. && (S_OK == m_HndlrQueue->FindFirstHandlerInState(
  2101. HANDLERSTATE_SYNCHRONIZE,m_clsidHandlerInSync,&pHandlerID,
  2102. &m_clsidHandlerInSync)) )
  2103. {
  2104. // no prepareforsync so if there aren't any more handlers in prerpareforsync
  2105. // calls kick off someones synchronize. see if any synchronize methods.
  2106. ++m_dwHandlerOutCallCount;
  2107. ++m_dwSynchronizeOutCallCount;
  2108. m_HndlrQueue->Synchronize(pHandlerID,hwnd);
  2109. // see if any other handlers that match the clsid and also call their
  2110. // synchronize methods.
  2111. while (S_OK == m_HndlrQueue->FindFirstHandlerInState(
  2112. HANDLERSTATE_SYNCHRONIZE,m_clsidHandlerInSync,
  2113. &pHandlerID,&m_clsidHandlerInSync))
  2114. {
  2115. ++m_dwHandlerOutCallCount;
  2116. ++m_dwSynchronizeOutCallCount;
  2117. m_HndlrQueue->Synchronize(pHandlerID,hwnd);
  2118. }
  2119. }
  2120. // set noMoreItemsToSync flag if
  2121. }
  2122. else
  2123. {
  2124. // for idle queue synchronize any items first since
  2125. // no need to call prepareforsync until we have too and don't kick off more than
  2126. // one at a time.
  2127. // a transfer can come in while processing an out call should be the only time
  2128. // this should happen. This can happen on Idle if in a Retry Error when the next
  2129. // idle fires.
  2130. // Assert(0 == m_dwHandlerOutCallCount);
  2131. // not doing anything while still in an out call emulates the old behavior of
  2132. // only ever doing one handler at a time.
  2133. if (0 == m_dwHandlerOutCallCount)
  2134. {
  2135. if (S_OK == m_HndlrQueue->FindFirstHandlerInState(
  2136. HANDLERSTATE_SYNCHRONIZE,GUID_NULL,&pHandlerID,&pHandlerClsid))
  2137. {
  2138. ++m_dwHandlerOutCallCount;
  2139. ++m_dwSynchronizeOutCallCount;
  2140. m_HndlrQueue->Synchronize(pHandlerID,hwnd);
  2141. }
  2142. else if (S_OK == m_HndlrQueue->FindFirstHandlerInState(
  2143. HANDLERSTATE_PREPAREFORSYNC,GUID_NULL,&pHandlerID,&pHandlerClsid))
  2144. {
  2145. // msidle only allows one idle registration at a time.
  2146. // reset idle in case last handler we called took it away from us
  2147. if (m_pSyncMgrIdle && (m_dwProgressFlags & PROGRESSFLAG_REGISTEREDFOROFFIDLE))
  2148. {
  2149. // !!!don't reset the registered if idle flag will do this
  2150. // when all handlers are completed.
  2151. if (!(m_dwProgressFlags & PROGRESSFLAG_RECEIVEDOFFIDLE))
  2152. {
  2153. m_pSyncMgrIdle->ReRegisterIdleDetection(this); // reregisterIdle in case handle overrode it.
  2154. m_pSyncMgrIdle->CheckForIdle();
  2155. }
  2156. }
  2157. ++m_dwHandlerOutCallCount;
  2158. ++m_dwPrepareForSyncOutCallCount;
  2159. m_HndlrQueue->PrepareForSync(pHandlerID,hwnd);
  2160. }
  2161. else
  2162. {
  2163. // even if nothing to do need to call
  2164. // reset idle hack
  2165. if (m_pSyncMgrIdle && !(m_dwProgressFlags & PROGRESSFLAG_RECEIVEDOFFIDLE)
  2166. && (m_dwProgressFlags & PROGRESSFLAG_REGISTEREDFOROFFIDLE))
  2167. {
  2168. m_pSyncMgrIdle->ReRegisterIdleDetection(this); // reregisterIdle in case handle overrode it.
  2169. m_pSyncMgrIdle->CheckForIdle();
  2170. }
  2171. }
  2172. }
  2173. }
  2174. UpdateProgressValues(); // update progress values when come out of calls.
  2175. // no longer in any out calls, reset our flag and see if a completion
  2176. // routine came in or items were added to the queue during our out call
  2177. m_dwProgressFlags &= ~PROGRESSFLAG_INHANDLEROUTCALL;
  2178. if ((PROGRESSFLAG_COMPLETIONROUTINEWHILEINOUTCALL & m_dwProgressFlags)
  2179. || (PROGRESSFLAG_NEWITEMSINQUEUE & m_dwProgressFlags) )
  2180. {
  2181. Assert(!(m_dwProgressFlags & PROGRESSFLAG_SHUTTINGDOWNLOOP)); // shouldn't get here if shutting down.
  2182. fRepostedStart = TRUE;
  2183. if (!(m_dwProgressFlags & PROGRESSFLAG_STARTPROGRESSPOSTED))
  2184. {
  2185. m_dwProgressFlags |= PROGRESSFLAG_STARTPROGRESSPOSTED;
  2186. PostMessage(m_hwnd,WM_PROGRESS_STARTPROGRESS,0,0);
  2187. }
  2188. }
  2189. // if no more items to synchronize and all synchronizations
  2190. // are done and we are currently syncing items then shut things down.
  2191. // if user is currently in a cancel call then don't start shutting
  2192. Assert(!(m_dwProgressFlags & PROGRESSFLAG_SHUTTINGDOWNLOOP)); // assert if in shutdown this loop shouldn't get called.
  2193. if (!(m_dwProgressFlags & PROGRESSFLAG_SHUTTINGDOWNLOOP)
  2194. && (0 == m_dwHandlerOutCallCount) && !(fRepostedStart)
  2195. && (m_dwProgressFlags & PROGRESSFLAG_SYNCINGITEMS))
  2196. {
  2197. BOOL fTransferAddRef;
  2198. BOOL fOffIdleBeforeShutDown = (m_dwProgressFlags & PROGRESSFLAG_RECEIVEDOFFIDLE);
  2199. BOOL fKeepDialogAlive;
  2200. // if no out calls shouldn't be any call specific out calls either
  2201. Assert(0 == m_dwPrepareForSyncOutCallCount);
  2202. Assert(0 == m_dwSynchronizeOutCallCount);
  2203. m_dwProgressFlags |= PROGRESSFLAG_SHUTTINGDOWNLOOP;
  2204. // reset newItemsInQueue so know for sure it got set while we
  2205. // yielded in cleanup calls.
  2206. m_dwProgressFlags &= ~PROGRESSFLAG_NEWITEMSINQUEUE;
  2207. // treat progress as one long out call
  2208. Assert(!(m_dwProgressFlags & PROGRESSFLAG_INHANDLEROUTCALL));
  2209. m_dwProgressFlags |= PROGRESSFLAG_INHANDLEROUTCALL;
  2210. m_dwProgressFlags &= ~PROGRESSFLAG_COMPLETIONROUTINEWHILEINOUTCALL; // reset completion routine.
  2211. // reset PROGRESSFLAG_TRANSFERADDREF flag but don't release
  2212. // if another transfer happens during this shutdown then the transfer
  2213. // will reset the flag and put and addref on. need to store state
  2214. // in case get this shutdown routine called twice without another
  2215. // transfer we don't call too many releases.
  2216. fTransferAddRef = m_dwProgressFlags & PROGRESSFLAG_TRANSFERADDREF;
  2217. Assert(fTransferAddRef); // should always have a transfer at this statge.
  2218. m_dwProgressFlags &= ~PROGRESSFLAG_TRANSFERADDREF;
  2219. SetProgressReleaseDlgCmdId(m_clsid,this,RELEASEDLGCMDID_OK);
  2220. UpdateProgressValues();
  2221. m_HndlrQueue->RemoveFinishedProgressItems(); // let the queue know to reset the progress bar
  2222. // if not in a cancel or setIetmstatus go ahead and release handlers
  2223. // and kill the terminate timer.
  2224. // review if there is a better opportunity to do cleanup.
  2225. if (!(m_dwProgressFlags & PROGRESSFLAG_INCANCELCALL)
  2226. && !(m_dwProgressFlags & PROGRESSFLAG_INTERMINATE)
  2227. && (0 == m_dwSetItemStateRefCount) )
  2228. {
  2229. if (m_lTimerSet)
  2230. {
  2231. InterlockedExchange(&m_lTimerSet, 0);
  2232. KillTimer(m_hwnd,TIMERID_KILLHANDLERS);
  2233. }
  2234. m_HndlrQueue->ReleaseCompletedHandlers(); // munge the queue.
  2235. }
  2236. fKeepDialogAlive = KeepProgressAlive(); // determine if progress should stick around
  2237. if ((m_dwProgressFlags & PROGRESSFLAG_PROGRESSANIMATION))
  2238. {
  2239. m_dwProgressFlags &= ~PROGRESSFLAG_PROGRESSANIMATION;
  2240. KillTimer(m_hwnd,TIMERID_TRAYANIMATION);
  2241. Animate_Stop(GetDlgItem(m_hwnd,IDC_UPDATEAVI));
  2242. ShowWindow(GetDlgItem(m_hwnd,IDC_UPDATEAVI),SW_HIDE);
  2243. ShowCompletedProgress(TRUE /* fComplete */ ,fKeepDialogAlive /* fDialogIsLocked */);
  2244. }
  2245. UpdateTrayIcon(); // if Icon is showing make sure we have the uptodate one.
  2246. ConnectObj_CloseConnections(); // Close any connections we held open during the Sync.
  2247. if (m_dwProgressFlags & PROGRESSFLAG_IDLENETWORKTIMER)
  2248. {
  2249. m_dwProgressFlags &= ~PROGRESSFLAG_IDLENETWORKTIMER;
  2250. KillTimer(m_hwnd,TIMERID_NOIDLEHANGUP); // don't need to keep connection open.
  2251. }
  2252. // make sure any previous locks on dialog are removed
  2253. // before going into wait logic. This can happen in the case of a retry.
  2254. LockProgressDialog(m_clsid,this,FALSE);
  2255. // if there are no items to lock the progress open and the
  2256. // force close flag isn't set wait in a loop
  2257. // for two seconds
  2258. if (!(fKeepDialogAlive) && (FALSE == m_fForceClose))
  2259. {
  2260. HANDLE hTimer = CreateEvent(NULL, TRUE, FALSE, NULL);
  2261. // should use Create/SetWaitable timer to accomplish this but these
  2262. // functions aren't available on Win9x yet.
  2263. if (hTimer)
  2264. {
  2265. // sit in loop until timer event sets it.
  2266. DoModalLoop(hTimer,NULL,m_hwnd,TRUE,1000*2);
  2267. CloseHandle(hTimer);
  2268. }
  2269. }
  2270. else
  2271. {
  2272. LockProgressDialog(m_clsid,this,TRUE);
  2273. ExpandCollapse(TRUE,FALSE); // make sure the dialog is expanded.
  2274. ShowProgressTab(PROGRESS_TAB_ERRORS);
  2275. }
  2276. //if the user hit the pushpin after we started the 2 second delay
  2277. if ((m_fPushpin) && !(fKeepDialogAlive))
  2278. {
  2279. ShowCompletedProgress(TRUE /* fComplete */,TRUE /* fDialogIsLocked */);
  2280. LockProgressDialog(m_clsid,this,TRUE);
  2281. }
  2282. // if this is an idle dialog handle the logic for
  2283. // either releasing the IdleLock or reregistering.
  2284. if (m_pSyncMgrIdle)
  2285. {
  2286. // if we have already received an OffIdle and not
  2287. // still handling the offidle then release the Idle Lock.
  2288. if ( (m_dwProgressFlags & PROGRESSFLAG_RECEIVEDOFFIDLE)
  2289. && !(m_dwProgressFlags & PROGRESSFLAG_INOFFIDLE))
  2290. {
  2291. // Release our IdleLock so TS can fire use again even if progress
  2292. // sticks around.
  2293. ReleaseIdleLock();
  2294. }
  2295. else if ( (m_dwProgressFlags & PROGRESSFLAG_REGISTEREDFOROFFIDLE)
  2296. && !(m_dwProgressFlags & PROGRESSFLAG_RECEIVEDOFFIDLE) )
  2297. {
  2298. // if have registered for idle but haven't seen it yet then
  2299. // we want to stay alive.
  2300. // if we aren't suppose to repeat idle or
  2301. // user has maximized the window then just call idle as if
  2302. // an OffIdle occured. Mostly done as a safety precaution
  2303. // in case someone has registered for Idle with MSIdle in
  2304. // our process space so we fail to receive the true offidle
  2305. if (!(m_dwProgressFlags & PROGRESSFLAG_IDLERETRYENABLED) || !m_fHasShellTrayIcon)
  2306. {
  2307. IdleCallback(STATE_USER_IDLE_END);
  2308. // release idle lock since OffIdle won't since we are still
  2309. // in the syncing Item state.
  2310. ReleaseIdleLock();
  2311. }
  2312. else
  2313. {
  2314. // if haven't yet received an offidle reregister
  2315. m_pSyncMgrIdle->ReRegisterIdleDetection(this); // reregisterIdle in case handle overrode it.
  2316. m_pSyncMgrIdle->CheckForIdle();
  2317. // first thing hide our window. Only hide if we are in the shelltray
  2318. // and no errors have occured.
  2319. if (m_fHasShellTrayIcon && !(KeepProgressAlive()))
  2320. {
  2321. RegisterShellTrayIcon(FALSE);
  2322. }
  2323. m_pSyncMgrIdle->ResetIdle(m_ulIdleRetryMinutes);
  2324. }
  2325. }
  2326. }
  2327. // if no new items in the queue no longer need the connection.
  2328. // do this before releasing dialog ref
  2329. if (!(m_dwProgressFlags & PROGRESSFLAG_NEWITEMSINQUEUE))
  2330. {
  2331. m_HndlrQueue->EndSyncSession();
  2332. }
  2333. // see if Release takes care or our progress, if not,
  2334. // there are more things to synchronize.
  2335. if (fTransferAddRef)
  2336. {
  2337. cDlgRefs = ReleaseProgressDialog(m_fForceClose); // release transfer addref.
  2338. }
  2339. else
  2340. {
  2341. Assert(fTransferAddRef); // this shouldn't happen but if it does addref/release.
  2342. AddRefProgressDialog();
  2343. cDlgRefs = ReleaseProgressDialog(m_fForceClose);
  2344. }
  2345. // !!!! warning - no longer hold onto a reference to
  2346. // this dialog. Do not do anything to allow this thread
  2347. // to be reentrant.
  2348. // its possible that items got placed in the queue why we were in our
  2349. // sleep loop, if so then restart the loop
  2350. m_dwProgressFlags &= ~PROGRESSFLAG_INHANDLEROUTCALL;
  2351. // if there are new items in the queue need to kick off another loop
  2352. if (m_dwProgressFlags & PROGRESSFLAG_NEWITEMSINQUEUE)
  2353. {
  2354. // m_dwProgressFlags &= ~PROGRESSFLAG_NEWITEMSINQUEUE;
  2355. Assert(m_cInternalcRefs);
  2356. // reset the user cancel flag if new items comein
  2357. m_dwProgressFlags &= ~PROGRESSFLAG_CANCELPRESSED;
  2358. if (!(m_dwProgressFlags & PROGRESSFLAG_STARTPROGRESSPOSTED))
  2359. {
  2360. m_dwProgressFlags |= PROGRESSFLAG_STARTPROGRESSPOSTED;
  2361. PostMessage(hwnd,WM_PROGRESS_STARTPROGRESS,0,0); // restart the sync.
  2362. }
  2363. }
  2364. else
  2365. {
  2366. if (m_dwShowErrorRefCount || m_dwSetItemStateRefCount
  2367. || (m_dwProgressFlags & PROGRESSFLAG_INCANCELCALL)
  2368. || (m_dwProgressFlags & PROGRESSFLAG_INTERMINATE) )
  2369. {
  2370. // cases that crefs should not be zero caused by out calls
  2371. Assert(m_cInternalcRefs);
  2372. }
  2373. else
  2374. {
  2375. // if get here refs should be zero, be an idle or a queue transfer is in
  2376. // progress.ADD
  2377. Assert(0 == m_cInternalcRefs
  2378. || (m_dwProgressFlags & PROGRESSFLAG_INOFFIDLE)
  2379. || (m_dwProgressFlags & PROGRESSFLAG_REGISTEREDFOROFFIDLE)
  2380. || (m_dwQueueTransferCount));
  2381. }
  2382. m_dwProgressFlags &= ~PROGRESSFLAG_SYNCINGITEMS; // no longer syncing items.
  2383. }
  2384. m_dwProgressFlags &= ~PROGRESSFLAG_CANCELWHILESHUTTINGDOWN; // if cancel came in during shutdown reset flag now.
  2385. m_dwProgressFlags &= ~PROGRESSFLAG_SHUTTINGDOWNLOOP;
  2386. }
  2387. --m_dwHandleThreadNestcount;
  2388. }
  2389. //+---------------------------------------------------------------------------
  2390. //
  2391. // Member: CProgressDlg::KeepProgressAlive, private
  2392. //
  2393. // Synopsis: returns true if progress dialog shouln't go away
  2394. // when the sync is complete
  2395. // Arguments:
  2396. //
  2397. // Returns:
  2398. //
  2399. // Modifies:
  2400. //
  2401. // History: 17-Jun-98 rogerg Created.
  2402. //
  2403. //----------------------------------------------------------------------------
  2404. BOOL CProgressDlg::KeepProgressAlive()
  2405. {
  2406. HKEY hkKeepProgress;
  2407. // Default behavior is to stick around on warnings and errors only.
  2408. DWORD dwKeepProgressSetting = PROGRESS_STICKY_WARNINGS | PROGRESS_STICKY_ERRORS;
  2409. DWORD dwErrorsFlag = 0;
  2410. DWORD dwType = REG_DWORD;
  2411. DWORD dwDataSize = sizeof(DWORD);
  2412. if (m_fPushpin)
  2413. {
  2414. return TRUE;
  2415. }
  2416. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, TOPLEVEL_REGKEY, 0, KEY_READ, &hkKeepProgress))
  2417. {
  2418. RegQueryValueEx(hkKeepProgress,TEXT("KeepProgressLevel"),NULL, &dwType,
  2419. (LPBYTE) &(dwKeepProgressSetting),
  2420. &dwDataSize);
  2421. RegCloseKey(hkKeepProgress);
  2422. }
  2423. if (m_iInfoCount)
  2424. {
  2425. dwErrorsFlag |= PROGRESS_STICKY_INFO;
  2426. }
  2427. if (m_iWarningCount)
  2428. {
  2429. dwErrorsFlag |= PROGRESS_STICKY_WARNINGS;
  2430. }
  2431. if (m_iErrorCount)
  2432. {
  2433. dwErrorsFlag |= PROGRESS_STICKY_ERRORS;
  2434. }
  2435. if (dwKeepProgressSetting & dwErrorsFlag)
  2436. {
  2437. return TRUE;
  2438. }
  2439. return FALSE;
  2440. }
  2441. //--------------------------------------------------------------------------------
  2442. //
  2443. // FUNCTION: CProgressDlg::TransferQueueData(CHndlrQueue *HndlrQueue)
  2444. //
  2445. // PURPOSE: Get the queue date
  2446. //
  2447. // COMMENTS: transfer items from the specified queue into our queue
  2448. // It is legal fo the HndlrQueue arg to be NULL in the case that
  2449. // the queue is being restarted from a retry. Review - May want
  2450. // to break this function to make the bottom part for the
  2451. // retry a separate function so can assert if someone tries
  2452. // to transfer a NULL queue.
  2453. //
  2454. //--------------------------------------------------------------------------------
  2455. STDMETHODIMP CProgressDlg::TransferQueueData(CHndlrQueue *pHndlrQueue)
  2456. {
  2457. HRESULT hr = E_UNEXPECTED;
  2458. SendMessage(m_hwnd, WM_PROGRESS_TRANSFERQUEUEDATA,(WPARAM) &hr, (LPARAM) pHndlrQueue);
  2459. return hr;
  2460. }
  2461. //--------------------------------------------------------------------------------
  2462. //
  2463. // FUNCTION: CProgressDlg::TransferQueueData(CHndlrQueue *HndlrQueue)
  2464. //
  2465. // PURPOSE: Get the queue date
  2466. //
  2467. // COMMENTS: transfer items from the specified queue into our queue
  2468. // It is legal fo the HndlrQueue arg to be NULL in the case that
  2469. // the queue is being restarted from a retry. Review - May want
  2470. // to break this function to make the bottom part for the
  2471. // retry a separate function so can assert if someone tries
  2472. // to transfer a NULL queue.
  2473. //
  2474. //--------------------------------------------------------------------------------
  2475. STDMETHODIMP CProgressDlg::PrivTransferQueueData(CHndlrQueue *HndlrQueue)
  2476. {
  2477. HRESULT hr = S_OK;
  2478. Assert(!(m_dwProgressFlags & PROGRESSFLAG_DEAD));
  2479. Assert(m_HndlrQueue);
  2480. if (NULL == m_HndlrQueue)
  2481. {
  2482. return E_UNEXPECTED;
  2483. }
  2484. ++m_dwQueueTransferCount;
  2485. if (HndlrQueue && m_HndlrQueue)
  2486. {
  2487. // set the transfer flag so main loop knows there are new items to look at
  2488. m_HndlrQueue->TransferQueueData(HndlrQueue);
  2489. // fill in the list box right away so
  2490. // a) better visual UI
  2491. // b) don't have to worry about race conditions with PrepareForSync.
  2492. // since adding UI won't make an outgoing call.
  2493. if (m_pItemListView)
  2494. {
  2495. AddItemsFromQueueToListView(m_pItemListView,m_HndlrQueue,
  2496. LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP ,SYNCMGRSTATUS_PENDING,
  2497. -1 /* iDateColumn */ ,PROGRESSLIST_STATUSCOLUMN /*status column */
  2498. ,FALSE /* fUseHandlerAsParent */,TRUE /* fAddOnlyCheckedItems */);
  2499. // set the selection to the first item
  2500. m_pItemListView->SetItemState(0, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED );
  2501. }
  2502. UpdateProgressValues();
  2503. UpdateWindow(m_hwnd);
  2504. // now check if there is already a transfer in progress and if
  2505. // there isn't post the message, else Addref the progress dialog as appropriate.
  2506. }
  2507. m_dwProgressFlags &= ~PROGRESSFLAG_NEWDIALOG; // no longer a new dialog once something is in the queue.
  2508. ShowCompletedProgress(FALSE,FALSE);
  2509. // if the animation isn't going then start it up.
  2510. if (!(m_dwProgressFlags & PROGRESSFLAG_PROGRESSANIMATION))
  2511. {
  2512. m_dwProgressFlags |= PROGRESSFLAG_PROGRESSANIMATION;
  2513. RedrawIcon();
  2514. ShowProgressTab(PROGRESS_TAB_UPDATE);
  2515. Animate_Play(GetDlgItem(m_hwnd,IDC_UPDATEAVI),0,-1,-1);
  2516. ShowWindow(GetDlgItem(m_hwnd,IDC_UPDATEAVI),SW_SHOW );
  2517. SetTimer(m_hwnd,TIMERID_TRAYANIMATION,TRAYANIMATION_SPEED,NULL);
  2518. }
  2519. // if we are an idle set up our callback
  2520. // successfully loaded msIdle, then set up the callback
  2521. // review - make these progress flags
  2522. if (m_pSyncMgrIdle && !(PROGRESSFLAG_REGISTEREDFOROFFIDLE & m_dwProgressFlags))
  2523. {
  2524. m_dwProgressFlags &= ~PROGRESSFLAG_RECEIVEDOFFIDLE; // reset offidle flag
  2525. // read in the defaults to use for Idle shutdown delay and
  2526. // wait until retryIdle based on the first Job in the queue.
  2527. if (0 == m_pSyncMgrIdle->BeginIdleDetection(this,1,0))
  2528. {
  2529. m_dwProgressFlags |= PROGRESSFLAG_REGISTEREDFOROFFIDLE;
  2530. AddRefProgressDialog(); // put an addref on to keep alive, will be released in OffIdle.
  2531. }
  2532. else
  2533. {
  2534. m_dwProgressFlags &= ~PROGRESSFLAG_REGISTEREDFOROFFIDLE;
  2535. }
  2536. }
  2537. // if don't have a transfer addref then add one and make sure idle is setup
  2538. if (!(PROGRESSFLAG_TRANSFERADDREF & m_dwProgressFlags))
  2539. {
  2540. m_dwProgressFlags |= PROGRESSFLAG_TRANSFERADDREF;
  2541. AddRefProgressDialog(); // put an addref on to keep alive.
  2542. }
  2543. --m_dwQueueTransferCount;
  2544. // don't post message if we are in an out call or in the shutdown
  2545. // loop or if newitemsqueue is already set.
  2546. if (!(m_dwProgressFlags & PROGRESSFLAG_INHANDLEROUTCALL)
  2547. && !(m_dwProgressFlags & PROGRESSFLAG_SHUTTINGDOWNLOOP)
  2548. && !(m_dwProgressFlags & PROGRESSFLAG_NEWITEMSINQUEUE)
  2549. && !(m_dwProgressFlags & PROGRESSFLAG_STARTPROGRESSPOSTED) )
  2550. {
  2551. if ( !(m_dwProgressFlags & PROGRESSFLAG_SYNCINGITEMS) )
  2552. {
  2553. // set here even though main loop does in case power managment or another transfer
  2554. // occurs between here and the postMessage being processed.
  2555. m_dwProgressFlags |= PROGRESSFLAG_SYNCINGITEMS;
  2556. m_HndlrQueue->BeginSyncSession();
  2557. }
  2558. m_dwProgressFlags |= PROGRESSFLAG_STARTPROGRESSPOSTED;
  2559. PostMessage(m_hwnd,WM_PROGRESS_STARTPROGRESS,0,0);
  2560. }
  2561. // set newitems flag event if don't post the message so when handler comes out of
  2562. // state can check the flag.
  2563. m_dwProgressFlags |= PROGRESSFLAG_NEWITEMSINQUEUE;
  2564. // reset the user cancel flag if new items comein
  2565. m_dwProgressFlags &= ~PROGRESSFLAG_CANCELPRESSED;
  2566. if (m_lTimerSet)
  2567. {
  2568. InterlockedExchange(&m_lTimerSet, 0);
  2569. // if we are in a terminate no need to kill the Timer
  2570. if (!(m_dwProgressFlags & PROGRESSFLAG_INTERMINATE))
  2571. {
  2572. KillTimer(m_hwnd,TIMERID_KILLHANDLERS);
  2573. }
  2574. }
  2575. return hr;
  2576. }
  2577. //+---------------------------------------------------------------------------
  2578. //
  2579. // Member: CProgressDlg::CallCompletionRoutine, private
  2580. //
  2581. // Synopsis: method called when a call has been completed.
  2582. //
  2583. // Arguments:
  2584. //
  2585. // Returns:
  2586. //
  2587. // Modifies:
  2588. //
  2589. // History: 02-Jun-98 rogerg Created.
  2590. //
  2591. //----------------------------------------------------------------------------
  2592. void CProgressDlg::CallCompletionRoutine(DWORD dwThreadMsg,LPCALLCOMPLETIONMSGLPARAM lpCallCompletelParam)
  2593. {
  2594. // !!!warning: This code assumes that the completion routine is only called
  2595. // after the original out call has returned. This code is currently handled
  2596. // by the queue and proxy. If switch to com need to make sure don't start winding
  2597. // up the stack if handlers are calling comletion routines before the original
  2598. // call comes back
  2599. // for anything but ShowErrors can just kick off a progress.
  2600. // for ShowErrors we need to pretend a transfer happened if a retry should occur
  2601. // else don't do anything.
  2602. switch(dwThreadMsg)
  2603. {
  2604. case ThreadMsg_ShowError:
  2605. if (lpCallCompletelParam && (S_SYNCMGR_RETRYSYNC == lpCallCompletelParam->hCallResult))
  2606. {
  2607. // if still in original ShowError Call let ShowEror post the message
  2608. // when done, else treat it like a transfer occured.
  2609. if (m_dwProgressFlags & PROGRESSFLAG_INSHOWERRORSCALL)
  2610. {
  2611. Assert(!(m_dwProgressFlags & PROGRESSFLAG_SHOWERRORSCALLBACKCALLED)); // only support one.
  2612. m_dwProgressFlags |= PROGRESSFLAG_SHOWERRORSCALLBACKCALLED;
  2613. }
  2614. else
  2615. {
  2616. // sendmessage so it is queued up before release
  2617. SendMessage(m_hwnd,WM_PROGRESS_TRANSFERQUEUEDATA,(WPARAM) 0, (LPARAM) NULL);
  2618. }
  2619. }
  2620. --m_dwShowErrorRefCount;
  2621. // count can go negative if handler calls completion routine on an error. if
  2622. // this is the case just set it to zero
  2623. if ( ((LONG) m_dwShowErrorRefCount) < 0)
  2624. {
  2625. AssertSz(0,"Negative ErrorRefCount");
  2626. m_dwShowErrorRefCount = 0;
  2627. }
  2628. else
  2629. {
  2630. ReleaseProgressDialog(m_fForceClose);
  2631. }
  2632. break;
  2633. case ThreadMsg_PrepareForSync:
  2634. case ThreadMsg_Synchronize:
  2635. {
  2636. DWORD *pdwMsgOutCallCount = (ThreadMsg_PrepareForSync == dwThreadMsg) ?
  2637. &m_dwPrepareForSyncOutCallCount : &m_dwSynchronizeOutCallCount;
  2638. if (m_dwProgressFlags & PROGRESSFLAG_INHANDLEROUTCALL)
  2639. {
  2640. m_dwProgressFlags |=PROGRESSFLAG_COMPLETIONROUTINEWHILEINOUTCALL;
  2641. }
  2642. else
  2643. {
  2644. if (!(m_dwProgressFlags & PROGRESSFLAG_STARTPROGRESSPOSTED))
  2645. {
  2646. Assert(!(m_dwProgressFlags & PROGRESSFLAG_SHUTTINGDOWNLOOP));
  2647. m_dwProgressFlags |= PROGRESSFLAG_CALLBACKPOSTED;
  2648. m_dwProgressFlags |= PROGRESSFLAG_STARTPROGRESSPOSTED;
  2649. PostMessage(m_hwnd,WM_PROGRESS_STARTPROGRESS,0,0);
  2650. }
  2651. }
  2652. // fix up call count.
  2653. --(*pdwMsgOutCallCount);
  2654. if ( ((LONG) *pdwMsgOutCallCount) < 0)
  2655. {
  2656. AssertSz(0,"Negative Message Specific OutCall");
  2657. *pdwMsgOutCallCount = 0;
  2658. }
  2659. --m_dwHandlerOutCallCount; // decrement the handler outcall.
  2660. if ( ((LONG) m_dwHandlerOutCallCount) < 0)
  2661. {
  2662. AssertSz(0,"NegativeHandlerOutCallCount");
  2663. m_dwHandlerOutCallCount = 0;
  2664. }
  2665. }
  2666. break;
  2667. default:
  2668. AssertSz(0,"Unknown Callback method");
  2669. break;
  2670. }
  2671. // if have an lparam free it now
  2672. if (lpCallCompletelParam)
  2673. {
  2674. FREE(lpCallCompletelParam);
  2675. }
  2676. }
  2677. //+---------------------------------------------------------------------------
  2678. //
  2679. // Member: CProgressDlg::QueryCanSystemShutdown, private
  2680. //
  2681. // Synopsis: called by object manager to determine if can shutdown.
  2682. //
  2683. // !!!Warning - can be called on any thread. make sure this is
  2684. // readonly.
  2685. //
  2686. // !!!Warning - Do not yield in the function;
  2687. //
  2688. // Arguments:
  2689. //
  2690. // Returns: S_OK - if can shutdown
  2691. // S_FALSE - system should not shutdown, must fill in out params.
  2692. //
  2693. // Modifies:
  2694. //
  2695. // History: 17-Jun-98 rogerg Created.
  2696. //
  2697. //----------------------------------------------------------------------------
  2698. HRESULT CProgressDlg::QueryCanSystemShutdown(/* [out] */ HWND *phwnd, /* [out] */ UINT *puMessageId,
  2699. /* [out] */ BOOL *pfLetUserDecide)
  2700. {
  2701. HRESULT hr = S_OK;
  2702. if (m_dwShowErrorRefCount > 0)
  2703. {
  2704. *puMessageId = IDS_HANDLERSHOWERRORQUERYENDSESSION ;
  2705. *phwnd = NULL; // don't know showError parent so keep NULL
  2706. *pfLetUserDecide = FALSE;
  2707. hr = S_FALSE;
  2708. }
  2709. else if (m_clsid != GUID_PROGRESSDLGIDLE) // idle should allow shutdown even if syncing.
  2710. {
  2711. // if a sync is in progress prompt user to if they want to cancel.
  2712. if (PROGRESSFLAG_SYNCINGITEMS & m_dwProgressFlags)
  2713. {
  2714. *puMessageId = IDS_PROGRESSQUERYENDSESSION;
  2715. *phwnd = m_hwnd;
  2716. *pfLetUserDecide = TRUE;
  2717. hr = S_FALSE;
  2718. }
  2719. }
  2720. return hr;
  2721. }
  2722. //--------------------------------------------------------------------------------
  2723. //
  2724. // FUNCTION: CProgressDlg::ExpandCollapse()
  2725. //
  2726. // PURPOSE: Takes care of showing and hiding the "details" part of the
  2727. // dialog.
  2728. //
  2729. // PARAMETERS:
  2730. // <in> fExpand - TRUE if we should be expanding the dialog.
  2731. // <in> fSetFocus - TRUE forces a recalc.
  2732. //
  2733. //--------------------------------------------------------------------------------
  2734. void CProgressDlg::ExpandCollapse(BOOL fExpand, BOOL fForce)
  2735. {
  2736. RECT rcSep;
  2737. TCHAR szBuf[MAX_STRING_RES];
  2738. RECT rcCurDlgRect;
  2739. BOOL fSetWindowPos = FALSE;
  2740. BOOL fOrigExpanded = m_fExpanded;
  2741. if ( (m_fExpanded == fExpand) && !fForce) // no need to do anything if already in requested state
  2742. return;
  2743. m_fExpanded = fExpand;
  2744. GetWindowRect(GetDlgItem(m_hwnd, IDC_SP_SEPARATOR), &rcSep);
  2745. GetWindowRect(m_hwnd,&rcCurDlgRect);
  2746. if (!m_fExpanded)
  2747. {
  2748. // update or rcDlg rect so can reset to proper height next time.
  2749. if (GetWindowRect(m_hwnd,&m_rcDlg))
  2750. {
  2751. fSetWindowPos = SetWindowPos(m_hwnd, HWND_NOTOPMOST, 0, 0, rcCurDlgRect.right - rcCurDlgRect.left,
  2752. m_cyCollapsed, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
  2753. }
  2754. }
  2755. else
  2756. {
  2757. fSetWindowPos = SetWindowPos(m_hwnd, HWND_NOTOPMOST, 0, 0, rcCurDlgRect.right - rcCurDlgRect.left,
  2758. m_rcDlg.bottom - m_rcDlg.top, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
  2759. }
  2760. // if couldn't change window, leave as is
  2761. if (!fSetWindowPos)
  2762. {
  2763. m_fExpanded = fOrigExpanded;
  2764. return;
  2765. }
  2766. // Make sure the entire dialog is visible on the screen. If not,
  2767. // then push it up
  2768. RECT rc;
  2769. RECT rcWorkArea;
  2770. GetWindowRect(m_hwnd, &rc);
  2771. SystemParametersInfo(SPI_GETWORKAREA, 0, (LPVOID) &rcWorkArea, 0);
  2772. if (rc.bottom > rcWorkArea.bottom)
  2773. {
  2774. rc.top = max(0, (int) rc.top - (rc.bottom - rcWorkArea.bottom));
  2775. SetWindowPos(m_hwnd, HWND_NOTOPMOST, rc.left, rc.top, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
  2776. }
  2777. LoadString(g_hInst, m_fExpanded ? IDS_HIDE_DETAILS : IDS_SHOW_DETAILS, szBuf, ARRAYSIZE(szBuf));
  2778. SetDlgItemText(m_hwnd, IDC_DETAILS, szBuf);
  2779. // Make sure the proper tab is up to date shown.
  2780. ShowProgressTab(m_iTab);
  2781. // Raid-34387: Spooler: Closing details with ALT-D while focus is on a task disables keyboard input
  2782. // if any control other than the cancel button has the focus set the focus to details.
  2783. if (!fExpand)
  2784. {
  2785. HWND hwndFocus = GetFocus();
  2786. if (hwndFocus != GetDlgItem(m_hwnd, IDSTOP))
  2787. {
  2788. SetFocus(GetDlgItem(m_hwnd, IDC_DETAILS));
  2789. }
  2790. }
  2791. }
  2792. //+---------------------------------------------------------------------------
  2793. //
  2794. // Member: CProgressDlg::OnTimer, private
  2795. //
  2796. // Synopsis:
  2797. //
  2798. // Arguments:
  2799. //
  2800. // Returns:
  2801. //
  2802. // Modifies:
  2803. //
  2804. // History: 17-Jun-98 rogerg Created.
  2805. //
  2806. //----------------------------------------------------------------------------
  2807. void CProgressDlg::OnTimer(UINT uMsg,WPARAM wParam,LPARAM lParam)
  2808. {
  2809. WORD wTimerID = (WORD) wParam;
  2810. if (wTimerID == TIMERID_TRAYANIMATION)
  2811. {
  2812. UpdateTrayIcon();
  2813. }
  2814. else if (TIMERID_NOIDLEHANGUP == wTimerID)
  2815. {
  2816. ResetNetworkIdle();
  2817. }
  2818. else if (TIMERID_KILLHANDLERS == wTimerID)
  2819. {
  2820. if (m_lTimerSet)
  2821. {
  2822. if (!(m_dwProgressFlags & PROGRESSFLAG_DEAD)
  2823. && !(m_dwProgressFlags & PROGRESSFLAG_SHUTTINGDOWNLOOP)
  2824. && !(m_dwProgressFlags & PROGRESSFLAG_INTERMINATE))
  2825. {
  2826. BOOL fItemToKill;
  2827. m_dwProgressFlags |= PROGRESSFLAG_INTERMINATE;
  2828. // Even though KillTimer,
  2829. // don't reset m_lTimerSet timer until done with ForceKill
  2830. // in case cancel is pressed again.
  2831. KillTimer(m_hwnd,TIMERID_KILLHANDLERS);
  2832. SetProgressReleaseDlgCmdId(m_clsid,this,RELEASEDLGCMDID_CANCEL); // set so cleanup knows it was stopped by user..
  2833. AddRefProgressDialog(); // hold dialog alive until cancel is complete
  2834. m_HndlrQueue->ForceKillHandlers(&fItemToKill);
  2835. // reset the timer if TimerSet is still set, i.e. if was
  2836. // set to zero because of a transfer or actually done don't reset.
  2837. if (m_lTimerSet)
  2838. {
  2839. // only settimer if actually killed anything. if looped through
  2840. // and found nothing then can turn off timer.
  2841. if (fItemToKill)
  2842. {
  2843. Assert(m_nKillHandlerTimeoutValue >= TIMERID_KILLHANDLERSMINTIME);
  2844. SetTimer(m_hwnd,TIMERID_KILLHANDLERS,m_nKillHandlerTimeoutValue,NULL);
  2845. }
  2846. else
  2847. {
  2848. m_lTimerSet = 0;
  2849. }
  2850. }
  2851. m_dwProgressFlags &= ~PROGRESSFLAG_INTERMINATE;
  2852. ReleaseProgressDialog(FALSE);
  2853. }
  2854. }
  2855. }
  2856. }
  2857. //+---------------------------------------------------------------------------
  2858. //
  2859. // Member: CProgressDlg::OnTaskBarCreated, private
  2860. //
  2861. // Synopsis: Receive this when the Tray has been restarted.
  2862. // Need to put back our tray icon.
  2863. //
  2864. // Arguments:
  2865. //
  2866. // Returns:
  2867. //
  2868. // Modifies:
  2869. //
  2870. // History: 31-Aug-98 rogerg Created.
  2871. //
  2872. //----------------------------------------------------------------------------
  2873. void CProgressDlg::OnTaskBarCreated(UINT uMsg,WPARAM wParam,LPARAM lParam)
  2874. {
  2875. if (m_fHasShellTrayIcon)
  2876. {
  2877. m_fAddedIconToTray = FALSE; // set added to false to force update to add again.
  2878. UpdateTrayIcon();
  2879. }
  2880. }
  2881. //+---------------------------------------------------------------------------
  2882. //
  2883. // Member: CProgressDlg::OnSysCommand, private
  2884. //
  2885. // Synopsis:
  2886. //
  2887. // Arguments:
  2888. //
  2889. // Returns:
  2890. //
  2891. // Modifies:
  2892. //
  2893. // History: 17-Jun-98 rogerg Created.
  2894. //
  2895. //----------------------------------------------------------------------------
  2896. BOOL CProgressDlg::OnSysCommand(UINT uMsg,WPARAM wParam,LPARAM lParam)
  2897. {
  2898. UINT uCmdType = (UINT) wParam; // type of system command requested
  2899. WORD xPos = LOWORD(lParam); // horizontal postion, in screen coordinates
  2900. WORD yPos = HIWORD(lParam); // vertical postion, in screen coordinates
  2901. //
  2902. // WARNING: USER uses low four bits for some undocumented feature
  2903. // (only for SC_*). We need to mask those bits to make this case
  2904. // statement work.
  2905. uCmdType &= 0xFFF0;
  2906. switch(uCmdType)
  2907. {
  2908. case SC_MINIMIZE:
  2909. // if already in the tray do nothing
  2910. if (!m_fHasShellTrayIcon)
  2911. {
  2912. if (RegisterShellTrayIcon(TRUE))
  2913. {
  2914. AnimateTray(TRUE);
  2915. ShowWindow(m_hwnd,SW_HIDE);
  2916. // AnimateTray(TRUE);
  2917. return -1;
  2918. }
  2919. }
  2920. else
  2921. {
  2922. return -1; // if already in the tray we handled.
  2923. }
  2924. break;
  2925. case SC_MAXIMIZE:
  2926. case SC_RESTORE:
  2927. {
  2928. // if we are being maximized or restored from a maximize
  2929. // make sure details is open
  2930. if ( (uCmdType == SC_RESTORE && m_fMaximized)
  2931. || (uCmdType == SC_MAXIMIZE) )
  2932. {
  2933. if (!m_fExpanded)
  2934. {
  2935. ExpandCollapse(TRUE,FALSE);
  2936. }
  2937. }
  2938. m_fMaximized = (uCmdType == SC_MAXIMIZE) ? TRUE : FALSE;
  2939. }
  2940. break;
  2941. default:
  2942. break;
  2943. }
  2944. return FALSE; // fall through to defWndProc
  2945. }
  2946. //+---------------------------------------------------------------------------
  2947. //
  2948. // Member: CProgressDlg::OnShellTrayNotification, private
  2949. //
  2950. // Synopsis:
  2951. //
  2952. // Arguments:
  2953. //
  2954. // Returns:
  2955. //
  2956. // Modifies:
  2957. //
  2958. // History: 17-Jun-98 rogerg Created.
  2959. //
  2960. //----------------------------------------------------------------------------
  2961. void CProgressDlg::OnShellTrayNotification(UINT uMsg,WPARAM wParam,LPARAM lParam)
  2962. {
  2963. DWORD dwMsg = (DWORD) lParam;
  2964. switch (dwMsg)
  2965. {
  2966. case WM_LBUTTONUP:
  2967. {
  2968. UpdateWndPosition(SW_SHOWNORMAL,TRUE /* fForce */);
  2969. }
  2970. break;
  2971. default:
  2972. break;
  2973. }
  2974. }
  2975. //+---------------------------------------------------------------------------
  2976. //
  2977. // Member: CProgressDlg::OnClose, private
  2978. //
  2979. // Synopsis:
  2980. //
  2981. // Arguments:
  2982. //
  2983. // Returns:
  2984. //
  2985. // Modifies:
  2986. //
  2987. // History: 17-Jun-98 rogerg Created.
  2988. //
  2989. //----------------------------------------------------------------------------
  2990. void CProgressDlg::OnClose(UINT uMsg,WPARAM wParam,LPARAM lParam)
  2991. {
  2992. OnCancel(FALSE /* fOffIdle */); // treat close as a cancel.
  2993. }
  2994. //+---------------------------------------------------------------------------
  2995. //
  2996. // Member: CProgressDlg::OnGetMinMaxInfo, private
  2997. //
  2998. // Synopsis:
  2999. //
  3000. // Arguments:
  3001. //
  3002. // Returns:
  3003. //
  3004. // Modifies:
  3005. //
  3006. // History: 17-Jun-98 rogerg Created.
  3007. //
  3008. //----------------------------------------------------------------------------
  3009. void CProgressDlg::OnGetMinMaxInfo(UINT uMsg,WPARAM wParam,LPARAM lParam)
  3010. {
  3011. MINMAXINFO *pMinMax = (MINMAXINFO *) lParam ;
  3012. // minimum width is a constant but minimum height depends on
  3013. // if dialog is collapsed or expanded.
  3014. if (!m_fExpanded)
  3015. {
  3016. pMinMax->ptMinTrackSize.y = m_cyCollapsed;
  3017. pMinMax->ptMaxTrackSize.y = m_cyCollapsed; // maximum is also the collapsed height
  3018. }
  3019. else
  3020. {
  3021. pMinMax->ptMinTrackSize.y = m_ptMinimumDlgExpandedSize.y;
  3022. }
  3023. pMinMax->ptMinTrackSize.x = m_ptMinimumDlgExpandedSize.x;
  3024. }
  3025. //+---------------------------------------------------------------------------
  3026. //
  3027. // Member: CProgressDlg::OnMoving, private
  3028. //
  3029. // Synopsis:
  3030. //
  3031. // Arguments:
  3032. //
  3033. // Returns:
  3034. //
  3035. // Modifies:
  3036. //
  3037. // History: 17-Jun-98 rogerg Created.
  3038. //
  3039. //----------------------------------------------------------------------------
  3040. void CProgressDlg::OnMoving(UINT uMsg,WPARAM wParam,LPARAM lParam)
  3041. {
  3042. LPRECT lprc = (LPRECT) lParam; // screen coordinates of drag rectangle
  3043. // if we are maxmized don't allow moving
  3044. if (m_fMaximized)
  3045. {
  3046. GetWindowRect(m_hwnd,lprc);
  3047. }
  3048. }
  3049. //+---------------------------------------------------------------------------
  3050. //
  3051. // Member: CProgressDlg::OnContextMenu, private
  3052. //
  3053. // Synopsis:
  3054. //
  3055. // Arguments:
  3056. //
  3057. // Returns:
  3058. //
  3059. // Modifies:
  3060. //
  3061. // History: 17-Jun-98 rogerg Created.
  3062. //
  3063. //----------------------------------------------------------------------------
  3064. BOOL CProgressDlg::OnContextMenu(UINT uMsg,WPARAM wParam,LPARAM lParam)
  3065. {
  3066. WinHelp ((HWND)wParam, g_szSyncMgrHelp, HELP_CONTEXTMENU, (ULONG_PTR)g_aContextHelpIds);
  3067. return TRUE;
  3068. }
  3069. //+---------------------------------------------------------------------------
  3070. //
  3071. // Member: CProgressDlg::OnPowerBroadcast, private
  3072. //
  3073. // Synopsis:
  3074. //
  3075. // Arguments:
  3076. //
  3077. // Returns:
  3078. //
  3079. // Modifies:
  3080. //
  3081. // History: 17-Jun-98 rogerg Created.
  3082. //
  3083. //----------------------------------------------------------------------------
  3084. BOOL CProgressDlg::OnPowerBroadcast(UINT uMsg,WPARAM wParam,LPARAM lParam)
  3085. {
  3086. if (wParam == PBT_APMQUERYSUSPEND)
  3087. {
  3088. // if just created or syncing don't suspend
  3089. if (m_dwProgressFlags & PROGRESSFLAG_NEWDIALOG
  3090. || m_dwProgressFlags & PROGRESSFLAG_SYNCINGITEMS)
  3091. {
  3092. SetWindowLongPtr(m_hwnd,DWLP_MSGRESULT,BROADCAST_QUERY_DENY);
  3093. return TRUE;
  3094. }
  3095. }
  3096. return TRUE;
  3097. }
  3098. //--------------------------------------------------------------------------------
  3099. //
  3100. // FUNCTION: ProgressWndProc(HWND hwnd, UINT uMsg,WPARAM wParam,LPARAM lParam)
  3101. //
  3102. // PURPOSE: Callback for Progress Dialog
  3103. //
  3104. // COMMENTS: Implemented on main thread.
  3105. //
  3106. //
  3107. //--------------------------------------------------------------------------------
  3108. INT_PTR CALLBACK ProgressWndProc(HWND hwnd, UINT uMsg,WPARAM wParam,LPARAM lParam)
  3109. {
  3110. CProgressDlg *pThis = (CProgressDlg *) GetWindowLongPtr(hwnd, DWLP_USER);
  3111. UINT horizExtent = 0;
  3112. BOOL bResult;
  3113. // spcial case destroy and init.
  3114. switch (uMsg)
  3115. {
  3116. case WM_DESTROY:
  3117. PostQuitMessage(0); // done with this thread.
  3118. break;
  3119. case WM_INITDIALOG:
  3120. {
  3121. SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR)lParam);
  3122. pThis = (CProgressDlg *) lParam;
  3123. if (pThis)
  3124. {
  3125. pThis->InitializeHwnd(hwnd,uMsg,wParam,lParam);
  3126. }
  3127. return FALSE; // return FALSE so system doesn't give us the focus
  3128. }
  3129. break;
  3130. default:
  3131. {
  3132. if (pThis)
  3133. {
  3134. switch (uMsg)
  3135. {
  3136. case WM_POWERBROADCAST:
  3137. return pThis->OnPowerBroadcast(uMsg,wParam,lParam);
  3138. break;
  3139. case WM_CONTEXTMENU:
  3140. return pThis->OnContextMenu(uMsg,wParam,lParam);
  3141. break;
  3142. case WM_DRAWITEM:
  3143. return OnProgressResultsDrawItem(hwnd,pThis,(UINT)wParam,(const DRAWITEMSTRUCT*)lParam);
  3144. break;
  3145. case WM_MEASUREITEM:
  3146. bResult = OnProgressResultsMeasureItem(hwnd,pThis, &horizExtent,(UINT)wParam,(MEASUREITEMSTRUCT *)lParam);
  3147. if (horizExtent)
  3148. {
  3149. //make sure there is a horizontal scroll bar if needed
  3150. SendMessage(GetDlgItem(hwnd,IDC_LISTBOXERROR), LB_SETHORIZONTALEXTENT, horizExtent, 0L);
  3151. }
  3152. return bResult;
  3153. break;
  3154. case WM_DELETEITEM:
  3155. return OnProgressResultsDeleteItem(hwnd,(UINT)wParam,(const DELETEITEMSTRUCT *)lParam);
  3156. break;
  3157. case WM_NOTIFY:
  3158. pThis->OnNotify(uMsg,wParam,lParam);
  3159. break;
  3160. case WM_COMMAND:
  3161. pThis->OnCommand(uMsg,wParam,lParam);
  3162. break;
  3163. case WM_MOVING:
  3164. pThis->OnMoving(uMsg,wParam,lParam);
  3165. break;
  3166. case WM_SIZE:
  3167. pThis->OnSize(uMsg,wParam,lParam);
  3168. break;
  3169. case WM_GETMINMAXINFO:
  3170. pThis->OnGetMinMaxInfo(uMsg,wParam,lParam);
  3171. break;
  3172. case WM_PAINT:
  3173. pThis->OnPaint(uMsg,wParam,lParam);
  3174. return 0;
  3175. break;
  3176. case WM_BASEDLG_SHOWWINDOW:
  3177. pThis->UpdateWndPosition((int)wParam,FALSE); // nCmdShow is stored in the wParam
  3178. break;
  3179. case WM_BASEDLG_NOTIFYLISTVIEWEX:
  3180. pThis->OnNotifyListViewEx(uMsg,wParam,lParam);
  3181. break;
  3182. case WM_BASEDLG_COMPLETIONROUTINE:
  3183. pThis->CallCompletionRoutine((DWORD)wParam /*dwThreadMsg */ ,(LPCALLCOMPLETIONMSGLPARAM) lParam);
  3184. break;
  3185. case WM_BASEDLG_HANDLESYSSHUTDOWN:
  3186. // set the force shutdown member then treat as a close
  3187. pThis->m_fForceClose = TRUE;
  3188. PostMessage(hwnd,WM_CLOSE,0,0);
  3189. break;
  3190. case WM_TIMER: // timer message for delat when sync is done.
  3191. pThis->OnTimer(uMsg,wParam,lParam);
  3192. break;
  3193. case WM_PROGRESS_UPDATE:
  3194. pThis->HandleProgressUpdate(hwnd,wParam,lParam);
  3195. break;
  3196. case WM_PROGRESS_LOGERROR:
  3197. pThis->HandleLogError(hwnd,(HANDLERINFO *) wParam,(MSGLogErrors *) lParam);
  3198. break;
  3199. case WM_PROGRESS_DELETELOGERROR:
  3200. pThis->HandleDeleteLogError(hwnd,(MSGDeleteLogErrors *) lParam);
  3201. break;
  3202. case WM_PROGRESS_STARTPROGRESS:
  3203. pThis->DoSyncTask(hwnd);
  3204. break;
  3205. case WM_PROGRESS_RESETKILLHANDLERSTIMER:
  3206. pThis->OnResetKillHandlersTimers();
  3207. break;
  3208. case WM_CLOSE:
  3209. pThis->OnClose(uMsg,wParam,lParam);
  3210. break;
  3211. case WM_PROGRESS_SHELLTRAYNOTIFICATION:
  3212. pThis->OnShellTrayNotification(uMsg,wParam,lParam);
  3213. break;
  3214. case WM_SYSCOMMAND:
  3215. return pThis->OnSysCommand(uMsg,wParam,lParam);
  3216. break;
  3217. case WM_PROGRESS_TRANSFERQUEUEDATA:
  3218. {
  3219. HRESULT *phr = (HRESULT *) wParam;
  3220. HRESULT hr;
  3221. hr = pThis->PrivTransferQueueData( (CHndlrQueue *) lParam);
  3222. // phr is only valid on a SendMessage.
  3223. if (phr)
  3224. {
  3225. *phr = hr;
  3226. }
  3227. return TRUE;
  3228. }
  3229. break;
  3230. case WM_PROGRESS_RELEASEDLGCMD:
  3231. pThis->PrivReleaseDlg((WORD)wParam);
  3232. break;
  3233. default:
  3234. if (uMsg == g_WMTaskbarCreated)
  3235. {
  3236. pThis->OnTaskBarCreated(uMsg,wParam,lParam);
  3237. }
  3238. break;
  3239. }
  3240. }
  3241. }
  3242. break;
  3243. }
  3244. return FALSE;
  3245. }