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.

931 lines
25 KiB

  1. //---------------------------------------------------------------------------
  2. //
  3. // Copyright (c) Microsoft Corporation 1993-1994
  4. //
  5. // File: status.c
  6. //
  7. // This file contains the dialog code for the Status property sheet
  8. //
  9. // History:
  10. // 08-06-93 ScottH Transferred from twin code
  11. //
  12. //---------------------------------------------------------------------------
  13. #include "brfprv.h" // common headers
  14. #include <brfcasep.h>
  15. #include "res.h"
  16. #include "recact.h"
  17. #include <help.h>
  18. typedef struct tagSTAT
  19. {
  20. HWND hwnd; // dialog handle
  21. PPAGEDATA ppagedata;
  22. FileInfo * pfi;
  23. TCHAR szFolder[MAX_PATH];
  24. BOOL bInit;
  25. } STAT, * PSTAT;
  26. #define Stat_Pcbs(this) ((this)->ppagedata->pcbs)
  27. #define Stat_AtomBrf(this) ((this)->ppagedata->pcbs->atomBrf)
  28. #define Stat_GetPtr(hwnd) (PSTAT)GetWindowLongPtr(hwnd, DWLP_USER)
  29. #define Stat_SetPtr(hwnd, lp) (PSTAT)SetWindowLongPtr(hwnd, DWLP_USER, (LRESULT)(lp))
  30. #define LNKM_ACTIVATEOTHER (WM_USER + 0)
  31. /*----------------------------------------------------------
  32. Purpose: Disable all the controls in the property page
  33. Returns: --
  34. Cond: --
  35. */
  36. void PRIVATE Stat_DisableAll(
  37. PSTAT this)
  38. {
  39. HWND hwnd = this->hwnd;
  40. HWND hwndFocus = GetFocus();
  41. RecAct_DeleteAllItems(GetDlgItem(hwnd, IDC_UPDATEACTIONS));
  42. RecAct_Enable(GetDlgItem(hwnd, IDC_UPDATEACTIONS), FALSE);
  43. Button_Enable(GetDlgItem(hwnd, IDC_PBTSRECON), FALSE);
  44. Button_Enable(GetDlgItem(hwnd, IDC_PBTSFIND), FALSE);
  45. Button_Enable(GetDlgItem(hwnd, IDC_PBTSSPLIT), FALSE);
  46. if ( !hwndFocus || !IsWindowEnabled(hwndFocus) )
  47. {
  48. SetFocus(GetDlgItem(GetParent(hwnd), IDOK));
  49. SendMessage(GetParent(hwnd), DM_SETDEFID, IDOK, 0);
  50. }
  51. }
  52. /*----------------------------------------------------------
  53. Purpose: Set the directions static text
  54. Returns: --
  55. Cond: --
  56. */
  57. void PRIVATE Stat_SetDirections(
  58. PSTAT this)
  59. {
  60. HWND hwnd = this->hwnd;
  61. HWND hwndRA = GetDlgItem(this->hwnd, IDC_UPDATEACTIONS);
  62. RA_ITEM item;
  63. TCHAR sz[MAXBUFLEN];
  64. *sz = 0;
  65. // This function shouldn't be called if this is an orphan
  66. ASSERT(S_OK == PageData_Query(this->ppagedata, hwnd, NULL, NULL));
  67. item.mask = RAIF_INSIDE | RAIF_OUTSIDE | RAIF_ACTION;
  68. item.iItem = 0;
  69. ASSERT(RecAct_GetItemCount(hwndRA) == 1);
  70. if (RecAct_GetItem(hwndRA, &item))
  71. {
  72. UINT ids;
  73. ASSERT(IsFlagSet(item.mask, RAIF_INSIDE | RAIF_OUTSIDE));
  74. switch (item.uAction)
  75. {
  76. case RAIA_TOIN:
  77. case RAIA_TOOUT:
  78. case RAIA_DELETEOUT:
  79. case RAIA_DELETEIN:
  80. case RAIA_MERGE:
  81. case RAIA_SOMETHING:
  82. // Instructions to update
  83. if (this->ppagedata->bFolder)
  84. ids = IDS_STATPROP_PressButton;
  85. else
  86. ids = IDS_STATPROP_Update;
  87. break;
  88. case RAIA_CONFLICT:
  89. ids = IDS_STATPROP_Conflict;
  90. break;
  91. default:
  92. if (SI_UNAVAILABLE == item.siOutside.uState)
  93. {
  94. // The original file is unavailable. We don't know if
  95. // everything is up-to-date.
  96. ids = IDS_STATPROP_Unavailable;
  97. }
  98. else
  99. {
  100. // They are up-to-date
  101. ids = IDS_STATPROP_Uptodate;
  102. }
  103. break;
  104. }
  105. SzFromIDS(ids, sz, ARRAYSIZE(sz));
  106. }
  107. Static_SetText(GetDlgItem(hwnd, IDC_STTSDIRECT), sz);
  108. }
  109. /*----------------------------------------------------------
  110. Purpose: Sets the reconciliation action control
  111. Returns: standard result
  112. S_OK if the item is still a twin
  113. S_FALSE if the item is an orphan
  114. Cond: --
  115. */
  116. HRESULT PRIVATE Stat_SetRecAct(
  117. PSTAT this,
  118. PRECLIST prl,
  119. PFOLDERTWINLIST pftl)
  120. {
  121. HRESULT hres;
  122. HWND hwnd = this->hwnd;
  123. HWND hwndRA = GetDlgItem(hwnd, IDC_UPDATEACTIONS);
  124. LPCTSTR pszPath = Atom_GetName(this->ppagedata->atomPath);
  125. RA_ITEM * pitem;
  126. // This function shouldn't be called if this is an orphan
  127. ASSERT(S_OK == PageData_Query(this->ppagedata, hwnd, NULL, NULL));
  128. hres = RAI_Create(&pitem, Atom_GetName(Stat_AtomBrf(this)), pszPath,
  129. prl, pftl);
  130. if (SUCCEEDED(hres))
  131. {
  132. if (RAIA_ORPHAN == pitem->uAction)
  133. {
  134. // This is a pending orphan
  135. PageData_Orphanize(this->ppagedata);
  136. hres = S_FALSE;
  137. }
  138. else if ( !this->ppagedata->bFolder )
  139. {
  140. pitem->mask |= RAIF_LPARAM;
  141. pitem->lParam = (LPARAM)prl->priFirst;
  142. }
  143. if (S_OK == hres)
  144. {
  145. BOOL bEnable;
  146. HWND hwndFocus = GetFocus();
  147. // Add the item to the recact control.
  148. RecAct_InsertItem(hwndRA, pitem);
  149. // Determine the state of the buttons
  150. bEnable = !(pitem->uAction == RAIA_SKIP ||
  151. pitem->uAction == RAIA_CONFLICT ||
  152. pitem->uAction == RAIA_NOTHING);
  153. Button_Enable(GetDlgItem(hwnd, IDC_PBTSRECON), bEnable);
  154. bEnable = (SI_UNAVAILABLE != pitem->siOutside.uState);
  155. Button_Enable(GetDlgItem(hwnd, IDC_PBTSFIND), bEnable);
  156. if ( !hwndFocus || !IsWindowEnabled(hwndFocus) )
  157. {
  158. SetFocus(GetDlgItem(hwnd, IDC_PBTSSPLIT));
  159. SendMessage(hwnd, DM_SETDEFID, IDC_PBTSSPLIT, 0);
  160. }
  161. }
  162. RAI_Free(pitem);
  163. }
  164. return hres;
  165. }
  166. /*----------------------------------------------------------
  167. Purpose: Sets the controls in the status property page.
  168. Returns: --
  169. Cond: --
  170. */
  171. void PRIVATE Stat_SetControls(
  172. PSTAT this)
  173. {
  174. HWND hwnd = this->hwnd;
  175. HRESULT hres;
  176. PRECLIST prl;
  177. PFOLDERTWINLIST pftl;
  178. // Is this a twin?
  179. hres = PageData_Query(this->ppagedata, hwnd, &prl, &pftl);
  180. if (S_OK == hres)
  181. {
  182. // Yes
  183. RecAct_DeleteAllItems(GetDlgItem(hwnd, IDC_UPDATEACTIONS));
  184. // Is it still a twin?
  185. hres = Stat_SetRecAct(this, prl, pftl);
  186. if (S_OK == hres)
  187. {
  188. // Yes
  189. Stat_SetDirections(this);
  190. }
  191. else if (S_FALSE == hres)
  192. {
  193. // No
  194. goto WipeOut;
  195. }
  196. }
  197. else if (S_FALSE == hres)
  198. {
  199. // No; disable the controls
  200. TCHAR sz[MAXBUFLEN];
  201. WipeOut:
  202. Stat_DisableAll(this);
  203. // Is this a subfolder twin?
  204. if (IsSubfolderTwin(PageData_GetHbrf(this->ppagedata),
  205. Atom_GetName(this->ppagedata->atomPath)))
  206. {
  207. // Yes; use subfolder twin message.
  208. SzFromIDS(IDS_STATPROP_SubfolderTwin, sz, ARRAYSIZE(sz));
  209. }
  210. else
  211. {
  212. // No; use orphan message.
  213. if (this->ppagedata->bFolder)
  214. SzFromIDS(IDS_STATPROP_OrphanFolder, sz, ARRAYSIZE(sz));
  215. else
  216. SzFromIDS(IDS_STATPROP_OrphanFile, sz, ARRAYSIZE(sz));
  217. }
  218. Static_SetText(GetDlgItem(hwnd, IDC_STTSDIRECT), sz);
  219. }
  220. }
  221. /*----------------------------------------------------------
  222. Purpose: Gets the icon of the file
  223. Returns: HICON
  224. Cond: --
  225. */
  226. HICON PRIVATE GetIconHelper(
  227. LPCTSTR pszPath)
  228. {
  229. SHFILEINFO sfi;
  230. if (SHGetFileInfo(pszPath, 0, &sfi, sizeof(sfi), SHGFI_ICON))
  231. {
  232. return sfi.hIcon;
  233. }
  234. return NULL;
  235. }
  236. /*----------------------------------------------------------
  237. Purpose: Stat WM_INITDIALOG Handler
  238. Returns: FALSE when we assign the control focus
  239. Cond: --
  240. */
  241. BOOL PRIVATE Stat_OnInitDialog(
  242. PSTAT this,
  243. HWND hwndFocus,
  244. LPARAM lParam) // expected to be LPPROPSHEETPAGE
  245. {
  246. HWND hwnd = this->hwnd;
  247. LPCTSTR pszPath;
  248. this->ppagedata = (PPAGEDATA)((LPPROPSHEETPAGE)lParam)->lParam;
  249. // Set up the display of the dialog
  250. pszPath = Atom_GetName(this->ppagedata->atomPath);
  251. if (SUCCEEDED(FICreate(pszPath, &this->pfi, FIF_ICON)))
  252. {
  253. Static_SetIcon(GetDlgItem(hwnd, IDC_ICTSMAIN), this->pfi->hicon);
  254. Static_SetText(GetDlgItem(hwnd, IDC_NAME), FIGetDisplayName(this->pfi));
  255. }
  256. // Save the folder of the twin away.
  257. if (pszPath)
  258. {
  259. lstrcpy(this->szFolder, pszPath);
  260. }
  261. else
  262. {
  263. this->szFolder[0] = 0;
  264. }
  265. if (!this->ppagedata->bFolder)
  266. PathRemoveFileSpec(this->szFolder);
  267. this->bInit = TRUE;
  268. return FALSE; // we set the initial focus
  269. }
  270. /*----------------------------------------------------------
  271. Purpose: PSN_SETACTIVE handler
  272. Returns: --
  273. Cond: --
  274. */
  275. void PRIVATE Stat_OnSetActive(
  276. PSTAT this)
  277. {
  278. HWND hwnd = this->hwnd;
  279. // Cause the page to be painted right away
  280. HideCaret(NULL);
  281. SetWindowRedraw(hwnd, TRUE);
  282. InvalidateRect(hwnd, NULL, TRUE);
  283. UpdateWindow(hwnd);
  284. if (this->bInit)
  285. {
  286. PageData_Init(this->ppagedata, GetParent(this->hwnd));
  287. this->bInit = FALSE;
  288. }
  289. ShowCaret(NULL);
  290. Stat_SetControls(this);
  291. }
  292. /*----------------------------------------------------------
  293. Purpose: Reconcile the twins in this property sheet.
  294. For folder twins, we invoke the Update dialog.
  295. For object twins, we reconcile from here.
  296. Returns: --
  297. Cond: --
  298. */
  299. void PRIVATE Stat_OnUpdate(
  300. PSTAT this,
  301. PRECLIST prl)
  302. {
  303. HWND hwnd = this->hwnd;
  304. HWND hwndRA = GetDlgItem(hwnd, IDC_UPDATEACTIONS);
  305. LPCTSTR pszPath = Atom_GetName(this->ppagedata->atomPath);
  306. if (0 == RecAct_GetItemCount(hwndRA))
  307. return;
  308. ASSERT(S_OK == PageData_Query(this->ppagedata, hwnd, NULL, NULL));
  309. // Is this a folder?
  310. if (this->ppagedata->bFolder)
  311. {
  312. // Yes; let the Update dialog do the work
  313. Upd_DoModal(hwnd, Stat_Pcbs(this), pszPath, 1, UF_SELECTION);
  314. }
  315. else
  316. {
  317. // No; we do the work.
  318. HWND hwndProgress;
  319. hwndProgress = UpdBar_Show(hwnd, UB_UPDATING, 0);
  320. Sync_ReconcileRecList(prl, Atom_GetName(Stat_AtomBrf(this)),
  321. hwndProgress, RF_DEFAULT);
  322. UpdBar_Kill(hwndProgress);
  323. }
  324. this->ppagedata->bRecalc = TRUE;
  325. PropSheet_CancelToClose(GetParent(hwnd));
  326. }
  327. /*----------------------------------------------------------
  328. Purpose: Separate the twins.
  329. Returns: --
  330. Cond: --
  331. */
  332. void PRIVATE Stat_OnSplit(PSTAT this)
  333. {
  334. HWND hwnd = this->hwnd;
  335. HWND hwndRA = GetDlgItem(hwnd, IDC_UPDATEACTIONS);
  336. LPCTSTR pszPath = Atom_GetName(this->ppagedata->atomPath);
  337. if (0 == RecAct_GetItemCount(hwndRA))
  338. return;
  339. ASSERT(S_OK == PageData_Query(this->ppagedata, hwnd, NULL, NULL));
  340. // Was the twin successfully deleted?
  341. if (S_OK == Sync_Split(PageData_GetHbrf(this->ppagedata), pszPath, 1, hwnd, 0))
  342. {
  343. // Yes; remove the cache references
  344. CRL_Nuke(this->ppagedata->atomPath);
  345. Stat_DisableAll(this);
  346. PropSheet_CancelToClose(GetParent(hwnd));
  347. // Notify the shell of the change
  348. PathNotifyShell(pszPath, NSE_UPDATEITEM, FALSE);
  349. }
  350. }
  351. /*----------------------------------------------------------
  352. Purpose: Attempt to bind to an object to see if it exists.
  353. Returns: TRUE if the object exists
  354. Cond: --
  355. */
  356. BOOL PRIVATE VerifyExists(LPCITEMIDLIST pidlParent, LPCITEMIDLIST pidl)
  357. {
  358. BOOL bRet = FALSE;
  359. IShellFolder *psfDesktop;
  360. ASSERT(pidlParent);
  361. ASSERT(pidl);
  362. if (SUCCEEDED(SHGetDesktopFolder(&psfDesktop)))
  363. {
  364. IShellFolder *psf;
  365. HRESULT hres = psfDesktop->lpVtbl->BindToObject(psfDesktop, pidlParent, NULL, &IID_IShellFolder, &psf);
  366. if (SUCCEEDED(hres))
  367. {
  368. ULONG rgfAttr = SFGAO_VALIDATE;
  369. bRet = SUCCEEDED(psf->lpVtbl->GetAttributesOf(psf, 1, &pidl, &rgfAttr));
  370. psf->lpVtbl->Release(psf);
  371. }
  372. psfDesktop->lpVtbl->Release(psfDesktop);
  373. }
  374. return bRet;
  375. }
  376. /*----------------------------------------------------------
  377. Purpose: Open a file (taken from ShellExecFile)
  378. Returns: value of ShellExecuteEx
  379. Cond: --
  380. */
  381. BOOL PUBLIC ExecFile(HWND hwnd,
  382. LPCTSTR pszVerb,
  383. LPCTSTR pszFile, // Fully qualified and fully resolved path to the file
  384. LPCTSTR pszParams,
  385. LPCTSTR pszDir, // If NULL then working dir is derived from lpszFile (except for UNC's)
  386. LPCITEMIDLIST pidl,
  387. int nShow)
  388. {
  389. SHELLEXECUTEINFO execinfo = {0};
  390. execinfo.cbSize = sizeof(execinfo);
  391. execinfo.hwnd = hwnd;
  392. execinfo.lpVerb = pszVerb;
  393. execinfo.lpFile = pszFile;
  394. execinfo.lpParameters = pszParams;
  395. execinfo.lpDirectory = pszDir;
  396. execinfo.nShow = nShow;
  397. execinfo.lpIDList = (LPITEMIDLIST)pidl;
  398. if (pidl)
  399. {
  400. execinfo.fMask |= SEE_MASK_IDLIST;
  401. }
  402. return ShellExecuteEx(&execinfo);
  403. }
  404. /*----------------------------------------------------------
  405. Purpose: Selects an item in the given cabinet window. Optionally
  406. sets it to be renamed.
  407. This function does not verify if the window is really
  408. a cabinet window.
  409. Returns: --
  410. Cond: --
  411. */
  412. void PUBLIC SelectItemInCabinet(
  413. HWND hwndCabinet,
  414. LPCITEMIDLIST pidl,
  415. BOOL bEdit)
  416. {
  417. if (IsWindow(hwndCabinet))
  418. {
  419. if (pidl)
  420. {
  421. LPITEMIDLIST pidlItem;
  422. // we need to global clone this because hwndCabinet might be
  423. // in a different process... could happen with common dialog
  424. pidlItem = ILGlobalClone(pidl);
  425. if (pidlItem)
  426. {
  427. UINT uFlagsEx;
  428. if (bEdit)
  429. uFlagsEx = SVSI_EDIT;
  430. else
  431. uFlagsEx = 0;
  432. SendMessage(hwndCabinet, CWM_SELECTITEM,
  433. uFlagsEx | SVSI_SELECT | SVSI_ENSUREVISIBLE |
  434. SVSI_FOCUSED | SVSI_DESELECTOTHERS,
  435. (LPARAM)pidlItem);
  436. ILGlobalFree(pidlItem);
  437. }
  438. }
  439. }
  440. }
  441. /*----------------------------------------------------------
  442. Purpose: Open a cabinet window and set the focus on the object.
  443. Returns: --
  444. Cond: --
  445. */
  446. void PUBLIC OpenCabinet(
  447. HWND hwnd,
  448. LPCITEMIDLIST pidlFolder,
  449. LPCITEMIDLIST pidl,
  450. BOOL bEdit) // TRUE: set the focus to edit the label
  451. {
  452. if (!VerifyExists(pidlFolder, pidl))
  453. {
  454. MsgBox(hwnd, MAKEINTRESOURCE(IDS_MSG_CantFindOriginal), MAKEINTRESOURCE(IDS_CAP_STATUS),
  455. NULL, MB_INFO);
  456. }
  457. else
  458. {
  459. HWND hwndCabinet;
  460. SHWaitForFileToOpen(pidlFolder, WFFO_ADD, 0L);
  461. if (ExecFile(hwnd, c_szOpen, NULL, NULL, NULL, pidlFolder, SW_NORMAL))
  462. {
  463. // This will wait for the window to open or time out
  464. // We need to disable the dialog box while we are waiting.
  465. DECLAREHOURGLASS;
  466. SetHourglass();
  467. EnableWindow(hwnd, FALSE);
  468. SHWaitForFileToOpen(pidlFolder, WFFO_REMOVE | WFFO_WAIT, WFFO_WAITTIME);
  469. EnableWindow(hwnd, TRUE);
  470. ResetHourglass();
  471. hwndCabinet = FindWindow(c_szCabinetClass, NULL);
  472. }
  473. else
  474. {
  475. // If it failed clear out our wait
  476. hwndCabinet = NULL;
  477. SHWaitForFileToOpen(pidlFolder, WFFO_REMOVE, 0L);
  478. }
  479. if (hwndCabinet)
  480. {
  481. SelectItemInCabinet(hwndCabinet, pidl, bEdit);
  482. // we need to post to the other because we can't activate another
  483. // thread from within a button's callback
  484. PostMessage(hwnd, LNKM_ACTIVATEOTHER, 0, (LPARAM)hwndCabinet);
  485. }
  486. }
  487. }
  488. /*----------------------------------------------------------
  489. Purpose: Opens the cabinet with the item pointed to by the twin.
  490. (copied and modified from link.c in shelldll)
  491. Returns: --
  492. Cond: --
  493. */
  494. void PRIVATE Stat_OnFind(
  495. PSTAT this)
  496. {
  497. HWND hwnd = this->hwnd;
  498. HWND hwndRA = GetDlgItem(hwnd, IDC_UPDATEACTIONS);
  499. RA_ITEM item;
  500. if (0 == RecAct_GetItemCount(hwndRA))
  501. return;
  502. ASSERT(S_OK == PageData_Query(this->ppagedata, hwnd, NULL, NULL));
  503. item.mask = RAIF_OUTSIDE | RAIF_NAME;
  504. item.iItem = 0;
  505. if (RecAct_GetItem(hwndRA, &item))
  506. {
  507. TCHAR szCanon[MAX_PATH];
  508. LPITEMIDLIST pidlFolder;
  509. LPITEMIDLIST pidl;
  510. // Use UNC name to find it on the net
  511. BrfPathCanonicalize(item.siOutside.pszDir, szCanon);
  512. pidlFolder = ILCreateFromPath(szCanon);
  513. if (pidlFolder)
  514. {
  515. pidl = ILCreateFromPath(item.pszName);
  516. if (pidl)
  517. {
  518. OpenCabinet(hwnd, pidlFolder, ILFindLastID(pidl), FALSE);
  519. ILFree(pidl);
  520. }
  521. ILFree(pidlFolder);
  522. }
  523. }
  524. }
  525. /*----------------------------------------------------------
  526. Purpose: Stat WM_COMMAND Handler
  527. Returns: --
  528. Cond: --
  529. */
  530. void PRIVATE Stat_OnCommand(
  531. PSTAT this,
  532. int id,
  533. HWND hwndCtl,
  534. UINT uNotifyCode)
  535. {
  536. PRECLIST prl;
  537. HRESULT hres;
  538. switch (id)
  539. {
  540. case IDC_PBTSRECON:
  541. case IDC_PBTSFIND:
  542. case IDC_PBTSSPLIT:
  543. RETRY_BEGIN(FALSE)
  544. {
  545. hres = PageData_Query(this->ppagedata, this->hwnd, &prl, NULL);
  546. if (FAILED(hres))
  547. {
  548. // Error
  549. // Unavailable disk?
  550. if (E_TR_UNAVAILABLE_VOLUME == hres)
  551. {
  552. // Yes; ask user to retry/cancel
  553. int id = MsgBox(this->hwnd, MAKEINTRESOURCE(IDS_ERR_UNAVAIL_VOL),
  554. MAKEINTRESOURCE(IDS_CAP_STATUS), NULL, MB_RETRYCANCEL | MB_ICONWARNING);
  555. if (IDRETRY == id)
  556. RETRY_SET(); // Try again
  557. }
  558. }
  559. }
  560. RETRY_END()
  561. // Is this a twin?
  562. if (S_OK == hres)
  563. {
  564. // Yes; do the operation
  565. switch (id)
  566. {
  567. case IDC_PBTSRECON:
  568. Stat_OnUpdate(this, prl);
  569. break;
  570. case IDC_PBTSFIND:
  571. Stat_OnFind(this);
  572. break;
  573. case IDC_PBTSSPLIT:
  574. Stat_OnSplit(this);
  575. break;
  576. }
  577. Stat_SetControls(this);
  578. }
  579. else if (S_FALSE == hres)
  580. {
  581. Stat_SetControls(this);
  582. }
  583. break;
  584. }
  585. }
  586. /*----------------------------------------------------------
  587. Purpose: Handle RN_ITEMCHANGED
  588. Returns: --
  589. Cond: --
  590. */
  591. void PRIVATE Stat_HandleItemChange(
  592. PSTAT this,
  593. NM_RECACT * lpnm)
  594. {
  595. PRECITEM pri;
  596. ASSERT((lpnm->mask & RAIF_LPARAM) != 0);
  597. pri = (PRECITEM)lpnm->lParam;
  598. // The action has changed, update the recnode accordingly
  599. //
  600. if (lpnm->mask & RAIF_ACTION)
  601. {
  602. BOOL bEnable;
  603. HWND hwndFocus = GetFocus();
  604. Sync_ChangeRecItemAction(pri, Atom_GetName(Stat_AtomBrf(this)),
  605. this->szFolder, lpnm->uAction);
  606. bEnable = (RAIA_SKIP != lpnm->uAction && RAIA_CONFLICT != lpnm->uAction);
  607. Button_Enable(GetDlgItem(this->hwnd, IDC_PBTSRECON), bEnable);
  608. if ( !hwndFocus || !IsWindowEnabled(hwndFocus) )
  609. {
  610. SetFocus(GetDlgItem(this->hwnd, IDC_PBTSSPLIT));
  611. SendMessage(this->hwnd, DM_SETDEFID, IDC_PBTSSPLIT, 0);
  612. }
  613. }
  614. }
  615. /*----------------------------------------------------------
  616. Purpose: WM_NOTIFY handler
  617. Returns: varies
  618. Cond: --
  619. */
  620. LRESULT PRIVATE Stat_OnNotify(
  621. PSTAT this,
  622. int idFrom,
  623. NMHDR * lpnmhdr)
  624. {
  625. LRESULT lRet = PSNRET_NOERROR;
  626. switch (lpnmhdr->code)
  627. {
  628. case RN_ITEMCHANGED:
  629. Stat_HandleItemChange(this, (NM_RECACT *)lpnmhdr);
  630. break;
  631. case PSN_SETACTIVE:
  632. Stat_OnSetActive(this);
  633. break;
  634. case PSN_KILLACTIVE:
  635. // N.b. This message is not sent if user clicks Cancel!
  636. // N.b. This message is sent prior to PSN_APPLY
  637. //
  638. break;
  639. case PSN_APPLY:
  640. break;
  641. default:
  642. break;
  643. }
  644. return lRet;
  645. }
  646. /*----------------------------------------------------------
  647. Purpose: WM_DESTROY handler
  648. Returns: --
  649. Cond: --
  650. */
  651. void PRIVATE Stat_OnDestroy(
  652. PSTAT this)
  653. {
  654. FIFree(this->pfi);
  655. }
  656. ///////////////////////////////////////////////////// EXPORTED FUNCTIONS
  657. static BOOL s_bStatRecurse = FALSE;
  658. LRESULT INLINE Stat_DefProc(
  659. HWND hDlg,
  660. UINT msg,
  661. WPARAM wParam,
  662. LPARAM lParam)
  663. {
  664. ENTEREXCLUSIVE();
  665. {
  666. s_bStatRecurse = TRUE;
  667. }
  668. LEAVEEXCLUSIVE();
  669. return DefDlgProc(hDlg, msg, wParam, lParam);
  670. }
  671. /*----------------------------------------------------------
  672. Purpose: Real Create Folder Twin dialog proc
  673. Returns: varies
  674. Cond: --
  675. */
  676. LRESULT Stat_DlgProc(
  677. PSTAT this,
  678. UINT message,
  679. WPARAM wParam,
  680. LPARAM lParam)
  681. {
  682. const static DWORD rgHelpIDs[] = {
  683. IDC_ICTSMAIN, IDH_BFC_PROP_FILEICON,
  684. IDC_NAME, IDH_BFC_PROP_FILEICON,
  685. IDC_STTSDIRECT, IDH_BFC_UPDATE_SCREEN,
  686. IDC_UPDATEACTIONS, IDH_BFC_UPDATE_SCREEN, // different
  687. IDC_PBTSRECON, IDH_BFC_UPDATE_BUTTON,
  688. IDC_PBTSSPLIT, IDH_BFC_PROP_SPLIT_BUTTON,
  689. IDC_PBTSFIND, IDH_BFC_PROP_FINDORIG_BUTTON,
  690. 0, 0 };
  691. DWORD_PTR dw;
  692. switch (message)
  693. {
  694. HANDLE_MSG(this, WM_INITDIALOG, Stat_OnInitDialog);
  695. HANDLE_MSG(this, WM_COMMAND, Stat_OnCommand);
  696. HANDLE_MSG(this, WM_NOTIFY, Stat_OnNotify);
  697. HANDLE_MSG(this, WM_DESTROY, Stat_OnDestroy);
  698. case WM_HELP:
  699. dw = (DWORD_PTR)rgHelpIDs;
  700. if ( IDC_STATIC != ((LPHELPINFO)lParam)->iCtrlId )
  701. WinHelp(((LPHELPINFO)lParam)->hItemHandle, c_szWinHelpFile, HELP_WM_HELP, dw);
  702. return 0;
  703. case WM_CONTEXTMENU:
  704. dw = (DWORD_PTR)rgHelpIDs;
  705. WinHelp((HWND)wParam, c_szWinHelpFile, HELP_CONTEXTMENU, dw);
  706. return 0;
  707. case LNKM_ACTIVATEOTHER:
  708. SwitchToThisWindow(GetLastActivePopup((HWND)lParam), TRUE);
  709. SetForegroundWindow((HWND)lParam);
  710. return 0;
  711. default:
  712. return Stat_DefProc(this->hwnd, message, wParam, lParam);
  713. }
  714. return 0;
  715. }
  716. /*----------------------------------------------------------
  717. Purpose: Create Folder Twin Dialog Wrapper
  718. Returns: varies
  719. Cond: --
  720. */
  721. INT_PTR CALLBACK Stat_WrapperProc(
  722. HWND hDlg, // std params
  723. UINT message,
  724. WPARAM wParam,
  725. LPARAM lParam)
  726. {
  727. PSTAT this;
  728. // Cool windowsx.h dialog technique. For full explanation, see
  729. // WINDOWSX.TXT. This supports multiple-instancing of dialogs.
  730. //
  731. ENTEREXCLUSIVE();
  732. {
  733. if (s_bStatRecurse)
  734. {
  735. s_bStatRecurse = FALSE;
  736. LEAVEEXCLUSIVE();
  737. return FALSE;
  738. }
  739. }
  740. LEAVEEXCLUSIVE();
  741. this = Stat_GetPtr(hDlg);
  742. if (this == NULL)
  743. {
  744. if (message == WM_INITDIALOG)
  745. {
  746. this = GAlloc(sizeof(*this));
  747. if (!this)
  748. {
  749. MsgBox(hDlg, MAKEINTRESOURCE(IDS_OOM_STATUS), MAKEINTRESOURCE(IDS_CAP_STATUS),
  750. NULL, MB_ERROR);
  751. EndDialog(hDlg, IDCANCEL);
  752. return Stat_DefProc(hDlg, message, wParam, lParam);
  753. }
  754. this->hwnd = hDlg;
  755. Stat_SetPtr(hDlg, this);
  756. }
  757. else
  758. {
  759. return Stat_DefProc(hDlg, message, wParam, lParam);
  760. }
  761. }
  762. if (message == WM_DESTROY)
  763. {
  764. Stat_DlgProc(this, message, wParam, lParam);
  765. GFree(this);
  766. Stat_SetPtr(hDlg, NULL);
  767. return 0;
  768. }
  769. return SetDlgMsgResult(hDlg, message, Stat_DlgProc(this, message, wParam, lParam));
  770. }