Source code of Windows XP (NT5)
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.

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