952 lines
24 KiB
C
952 lines
24 KiB
C
|
//---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Copyright (c) Microsoft Corporation 1993-1994
|
||
|
//
|
||
|
// File: status.c
|
||
|
//
|
||
|
// This file contains the dialog code for the Status property sheet
|
||
|
//
|
||
|
// History:
|
||
|
// 08-06-93 ScottH Transferred from twin code
|
||
|
//
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
|
||
|
#include "brfprv.h" // common headers
|
||
|
#include <brfcasep.h>
|
||
|
|
||
|
#include "res.h"
|
||
|
#include "recact.h"
|
||
|
#ifdef WINNT
|
||
|
#include <help.h>
|
||
|
#else
|
||
|
#include "..\..\..\win\core\inc\help.h" // help IDs
|
||
|
#endif
|
||
|
|
||
|
|
||
|
typedef struct tagSTAT
|
||
|
{
|
||
|
HWND hwnd; // dialog handle
|
||
|
PPAGEDATA ppagedata;
|
||
|
FileInfo * pfi;
|
||
|
TCHAR szFolder[MAX_PATH];
|
||
|
BOOL bInit;
|
||
|
} STAT, * PSTAT;
|
||
|
|
||
|
#define Stat_Pcbs(this) ((this)->ppagedata->pcbs)
|
||
|
#define Stat_AtomBrf(this) ((this)->ppagedata->pcbs->atomBrf)
|
||
|
#define Stat_GetPtr(hwnd) (PSTAT)GetWindowLong(hwnd, DWL_USER)
|
||
|
#define Stat_SetPtr(hwnd, lp) (PSTAT)SetWindowLong(hwnd, DWL_USER, (LONG)(lp))
|
||
|
|
||
|
#define LNKM_ACTIVATEOTHER (WM_USER + 0)
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: Disable all the controls in the property page
|
||
|
Returns: --
|
||
|
Cond: --
|
||
|
*/
|
||
|
void PRIVATE Stat_DisableAll(
|
||
|
PSTAT this)
|
||
|
{
|
||
|
HWND hwnd = this->hwnd;
|
||
|
HWND hwndFocus = GetFocus();
|
||
|
|
||
|
RecAct_DeleteAllItems(GetDlgItem(hwnd, IDC_UPDATEACTIONS));
|
||
|
RecAct_Enable(GetDlgItem(hwnd, IDC_UPDATEACTIONS), FALSE);
|
||
|
|
||
|
Button_Enable(GetDlgItem(hwnd, IDC_PBTSRECON), FALSE);
|
||
|
Button_Enable(GetDlgItem(hwnd, IDC_PBTSFIND), FALSE);
|
||
|
Button_Enable(GetDlgItem(hwnd, IDC_PBTSSPLIT), FALSE);
|
||
|
|
||
|
if ( !hwndFocus || !IsWindowEnabled(hwndFocus) )
|
||
|
{
|
||
|
SetFocus(GetDlgItem(GetParent(hwnd), IDOK));
|
||
|
SendMessage(GetParent(hwnd), DM_SETDEFID, IDOK, 0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: Set the directions static text
|
||
|
Returns: --
|
||
|
Cond: --
|
||
|
*/
|
||
|
void PRIVATE Stat_SetDirections(
|
||
|
PSTAT this)
|
||
|
{
|
||
|
HWND hwnd = this->hwnd;
|
||
|
HWND hwndRA = GetDlgItem(this->hwnd, IDC_UPDATEACTIONS);
|
||
|
RA_ITEM item;
|
||
|
TCHAR sz[MAXBUFLEN];
|
||
|
|
||
|
*sz = 0;
|
||
|
|
||
|
// This function shouldn't be called if this is an orphan
|
||
|
ASSERT(S_OK == PageData_Query(this->ppagedata, hwnd, NULL, NULL));
|
||
|
|
||
|
item.mask = RAIF_INSIDE | RAIF_OUTSIDE | RAIF_ACTION;
|
||
|
item.iItem = 0;
|
||
|
|
||
|
ASSERT(RecAct_GetItemCount(hwndRA) == 1);
|
||
|
|
||
|
if (RecAct_GetItem(hwndRA, &item))
|
||
|
{
|
||
|
UINT ids;
|
||
|
|
||
|
ASSERT(IsFlagSet(item.mask, RAIF_INSIDE | RAIF_OUTSIDE));
|
||
|
|
||
|
switch (item.uAction)
|
||
|
{
|
||
|
case RAIA_TOIN:
|
||
|
case RAIA_TOOUT:
|
||
|
case RAIA_DELETEOUT:
|
||
|
case RAIA_DELETEIN:
|
||
|
case RAIA_MERGE:
|
||
|
case RAIA_SOMETHING:
|
||
|
// Instructions to update
|
||
|
if (this->ppagedata->bFolder)
|
||
|
ids = IDS_STATPROP_PressButton;
|
||
|
else
|
||
|
ids = IDS_STATPROP_Update;
|
||
|
break;
|
||
|
|
||
|
case RAIA_CONFLICT:
|
||
|
ids = IDS_STATPROP_Conflict;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
if (SI_UNAVAILABLE == item.siOutside.uState)
|
||
|
{
|
||
|
// The original file is unavailable. We don't know if
|
||
|
// everything is up-to-date.
|
||
|
ids = IDS_STATPROP_Unavailable;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// They are up-to-date
|
||
|
ids = IDS_STATPROP_Uptodate;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
SzFromIDS(ids, sz, ARRAYSIZE(sz));
|
||
|
}
|
||
|
Static_SetText(GetDlgItem(hwnd, IDC_STTSDIRECT), sz);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: Sets the reconciliation action control
|
||
|
|
||
|
Returns: standard result
|
||
|
S_OK if the item is still a twin
|
||
|
S_FALSE if the item is an orphan
|
||
|
|
||
|
Cond: --
|
||
|
*/
|
||
|
HRESULT PRIVATE Stat_SetRecAct(
|
||
|
PSTAT this,
|
||
|
PRECLIST prl,
|
||
|
PFOLDERTWINLIST pftl)
|
||
|
{
|
||
|
HRESULT hres;
|
||
|
HWND hwnd = this->hwnd;
|
||
|
HWND hwndRA = GetDlgItem(hwnd, IDC_UPDATEACTIONS);
|
||
|
LPCTSTR pszPath = Atom_GetName(this->ppagedata->atomPath);
|
||
|
RA_ITEM * pitem;
|
||
|
|
||
|
// This function shouldn't be called if this is an orphan
|
||
|
ASSERT(S_OK == PageData_Query(this->ppagedata, hwnd, NULL, NULL));
|
||
|
|
||
|
hres = RAI_Create(&pitem, Atom_GetName(Stat_AtomBrf(this)), pszPath,
|
||
|
prl, pftl);
|
||
|
|
||
|
if (SUCCEEDED(hres))
|
||
|
{
|
||
|
if (RAIA_ORPHAN == pitem->uAction)
|
||
|
{
|
||
|
// This is a pending orphan
|
||
|
PageData_Orphanize(this->ppagedata);
|
||
|
hres = S_FALSE;
|
||
|
}
|
||
|
else if ( !this->ppagedata->bFolder )
|
||
|
{
|
||
|
pitem->mask |= RAIF_LPARAM;
|
||
|
pitem->lParam = (DWORD)(LPVOID)prl->priFirst;
|
||
|
}
|
||
|
|
||
|
if (S_OK == hres)
|
||
|
{
|
||
|
BOOL bEnable;
|
||
|
HWND hwndFocus = GetFocus();
|
||
|
|
||
|
// Add the item to the recact control.
|
||
|
RecAct_InsertItem(hwndRA, pitem);
|
||
|
|
||
|
// Determine the state of the buttons
|
||
|
bEnable = !(pitem->uAction == RAIA_SKIP ||
|
||
|
pitem->uAction == RAIA_CONFLICT ||
|
||
|
pitem->uAction == RAIA_NOTHING);
|
||
|
Button_Enable(GetDlgItem(hwnd, IDC_PBTSRECON), bEnable);
|
||
|
|
||
|
bEnable = (SI_UNAVAILABLE != pitem->siOutside.uState);
|
||
|
Button_Enable(GetDlgItem(hwnd, IDC_PBTSFIND), bEnable);
|
||
|
|
||
|
if ( !hwndFocus || !IsWindowEnabled(hwndFocus) )
|
||
|
{
|
||
|
SetFocus(GetDlgItem(hwnd, IDC_PBTSSPLIT));
|
||
|
SendMessage(hwnd, DM_SETDEFID, IDC_PBTSSPLIT, 0);
|
||
|
}
|
||
|
}
|
||
|
RAI_Free(pitem);
|
||
|
}
|
||
|
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: Sets the controls in the status property page.
|
||
|
|
||
|
Returns: --
|
||
|
Cond: --
|
||
|
*/
|
||
|
void PRIVATE Stat_SetControls(
|
||
|
PSTAT this)
|
||
|
{
|
||
|
HWND hwnd = this->hwnd;
|
||
|
HRESULT hres;
|
||
|
PRECLIST prl;
|
||
|
PFOLDERTWINLIST pftl;
|
||
|
|
||
|
// Is this a twin?
|
||
|
hres = PageData_Query(this->ppagedata, hwnd, &prl, &pftl);
|
||
|
if (S_OK == hres)
|
||
|
{
|
||
|
// Yes
|
||
|
RecAct_DeleteAllItems(GetDlgItem(hwnd, IDC_UPDATEACTIONS));
|
||
|
|
||
|
// Is it still a twin?
|
||
|
hres = Stat_SetRecAct(this, prl, pftl);
|
||
|
if (S_OK == hres)
|
||
|
{
|
||
|
// Yes
|
||
|
Stat_SetDirections(this);
|
||
|
}
|
||
|
else if (S_FALSE == hres)
|
||
|
{
|
||
|
// No
|
||
|
goto WipeOut;
|
||
|
}
|
||
|
}
|
||
|
else if (S_FALSE == hres)
|
||
|
{
|
||
|
// No; disable the controls
|
||
|
TCHAR sz[MAXBUFLEN];
|
||
|
WipeOut:
|
||
|
|
||
|
Stat_DisableAll(this);
|
||
|
|
||
|
// Is this a subfolder twin?
|
||
|
if (IsSubfolderTwin(PageData_GetHbrf(this->ppagedata),
|
||
|
Atom_GetName(this->ppagedata->atomPath)))
|
||
|
{
|
||
|
// Yes; use subfolder twin message.
|
||
|
SzFromIDS(IDS_STATPROP_SubfolderTwin, sz, ARRAYSIZE(sz));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// No; use orphan message.
|
||
|
if (this->ppagedata->bFolder)
|
||
|
SzFromIDS(IDS_STATPROP_OrphanFolder, sz, ARRAYSIZE(sz));
|
||
|
else
|
||
|
SzFromIDS(IDS_STATPROP_OrphanFile, sz, ARRAYSIZE(sz));
|
||
|
}
|
||
|
Static_SetText(GetDlgItem(hwnd, IDC_STTSDIRECT), sz);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: Gets the icon of the file
|
||
|
|
||
|
Returns: HICON
|
||
|
Cond: --
|
||
|
*/
|
||
|
HICON PRIVATE GetIconHelper(
|
||
|
LPCTSTR pszPath)
|
||
|
{
|
||
|
SHFILEINFO sfi;
|
||
|
|
||
|
if (SHGetFileInfo(pszPath, 0, &sfi, sizeof(sfi), SHGFI_ICON))
|
||
|
{
|
||
|
return sfi.hIcon;
|
||
|
}
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: Stat WM_INITDIALOG Handler
|
||
|
|
||
|
Returns: FALSE when we assign the control focus
|
||
|
Cond: --
|
||
|
*/
|
||
|
BOOL PRIVATE Stat_OnInitDialog(
|
||
|
PSTAT this,
|
||
|
HWND hwndFocus,
|
||
|
LPARAM lParam) // expected to be LPPROPSHEETPAGE
|
||
|
{
|
||
|
HWND hwnd = this->hwnd;
|
||
|
LPCTSTR pszPath;
|
||
|
|
||
|
this->ppagedata = (PPAGEDATA)((LPPROPSHEETPAGE)lParam)->lParam;
|
||
|
|
||
|
// Set up the display of the dialog
|
||
|
pszPath = Atom_GetName(this->ppagedata->atomPath);
|
||
|
|
||
|
if (SUCCEEDED(FICreate(pszPath, &this->pfi, FIF_ICON)))
|
||
|
{
|
||
|
Static_SetIcon(GetDlgItem(hwnd, IDC_ICTSMAIN), this->pfi->hicon);
|
||
|
Static_SetText(GetDlgItem(hwnd, IDC_NAME), FIGetDisplayName(this->pfi));
|
||
|
}
|
||
|
|
||
|
// Save the folder of the twin away.
|
||
|
lstrcpy(this->szFolder, pszPath);
|
||
|
if (!this->ppagedata->bFolder)
|
||
|
PathRemoveFileSpec(this->szFolder);
|
||
|
|
||
|
this->bInit = TRUE;
|
||
|
|
||
|
return FALSE; // we set the initial focus
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: PSN_SETACTIVE handler
|
||
|
Returns: --
|
||
|
Cond: --
|
||
|
*/
|
||
|
void PRIVATE Stat_OnSetActive(
|
||
|
PSTAT this)
|
||
|
{
|
||
|
HWND hwnd = this->hwnd;
|
||
|
|
||
|
// Cause the page to be painted right away
|
||
|
HideCaret(NULL);
|
||
|
SetWindowRedraw(hwnd, TRUE);
|
||
|
InvalidateRect(hwnd, NULL, TRUE);
|
||
|
UpdateWindow(hwnd);
|
||
|
|
||
|
if (this->bInit)
|
||
|
{
|
||
|
PageData_Init(this->ppagedata, GetParent(this->hwnd));
|
||
|
this->bInit = FALSE;
|
||
|
}
|
||
|
|
||
|
ShowCaret(NULL);
|
||
|
|
||
|
Stat_SetControls(this);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: Reconcile the twins in this property sheet.
|
||
|
For folder twins, we invoke the Update dialog.
|
||
|
For object twins, we reconcile from here.
|
||
|
|
||
|
Returns: --
|
||
|
Cond: --
|
||
|
*/
|
||
|
void PRIVATE Stat_OnUpdate(
|
||
|
PSTAT this,
|
||
|
PRECLIST prl)
|
||
|
{
|
||
|
HWND hwnd = this->hwnd;
|
||
|
HWND hwndRA = GetDlgItem(hwnd, IDC_UPDATEACTIONS);
|
||
|
LPCTSTR pszPath = Atom_GetName(this->ppagedata->atomPath);
|
||
|
|
||
|
if (0 == RecAct_GetItemCount(hwndRA))
|
||
|
return;
|
||
|
|
||
|
ASSERT(S_OK == PageData_Query(this->ppagedata, hwnd, NULL, NULL));
|
||
|
|
||
|
// Is this a folder?
|
||
|
if (this->ppagedata->bFolder)
|
||
|
{
|
||
|
// Yes; let the Update dialog do the work
|
||
|
Upd_DoModal(hwnd, Stat_Pcbs(this), pszPath, 1, UF_SELECTION);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// No; we do the work.
|
||
|
HWND hwndProgress;
|
||
|
|
||
|
hwndProgress = UpdBar_Show(hwnd, UB_UPDATING, 0);
|
||
|
|
||
|
Sync_ReconcileRecList(prl, Atom_GetName(Stat_AtomBrf(this)),
|
||
|
hwndProgress, RF_DEFAULT);
|
||
|
|
||
|
UpdBar_Kill(hwndProgress);
|
||
|
}
|
||
|
|
||
|
this->ppagedata->bRecalc = TRUE;
|
||
|
|
||
|
PropSheet_CancelToClose(GetParent(hwnd));
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: Separate the twins.
|
||
|
Returns: --
|
||
|
Cond: --
|
||
|
*/
|
||
|
void PRIVATE Stat_OnSplit(
|
||
|
PSTAT this)
|
||
|
{
|
||
|
HWND hwnd = this->hwnd;
|
||
|
HWND hwndRA = GetDlgItem(hwnd, IDC_UPDATEACTIONS);
|
||
|
LPCTSTR pszPath = Atom_GetName(this->ppagedata->atomPath);
|
||
|
|
||
|
if (0 == RecAct_GetItemCount(hwndRA))
|
||
|
return;
|
||
|
|
||
|
ASSERT(S_OK == PageData_Query(this->ppagedata, hwnd, NULL, NULL));
|
||
|
|
||
|
// Was the twin successfully deleted?
|
||
|
if (S_OK == Sync_Split(PageData_GetHbrf(this->ppagedata), pszPath, 1, hwnd, 0))
|
||
|
{
|
||
|
// Yes; remove the cache references
|
||
|
CRL_Nuke(this->ppagedata->atomPath);
|
||
|
Stat_DisableAll(this);
|
||
|
|
||
|
PropSheet_CancelToClose(GetParent(hwnd));
|
||
|
|
||
|
// Notify the shell of the change
|
||
|
PathNotifyShell(pszPath, NSE_UPDATEITEM, FALSE);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: Attempt to bind to an object to see if it exists.
|
||
|
|
||
|
Returns: TRUE if the object exists
|
||
|
Cond: --
|
||
|
*/
|
||
|
BOOL PRIVATE VerifyExists(
|
||
|
LPCITEMIDLIST pidlParent,
|
||
|
LPCITEMIDLIST pidl)
|
||
|
{
|
||
|
BOOL bRet = FALSE;
|
||
|
LPSHELLFOLDER psfDesktop;
|
||
|
|
||
|
ASSERT(pidlParent);
|
||
|
ASSERT(pidl);
|
||
|
|
||
|
psfDesktop = GetDesktopShellFolder();
|
||
|
if (psfDesktop)
|
||
|
{
|
||
|
LPSHELLFOLDER psf;
|
||
|
HRESULT hres;
|
||
|
|
||
|
hres = psfDesktop->lpVtbl->BindToObject(psfDesktop, pidlParent, NULL, &IID_IShellFolder, &psf);
|
||
|
if (SUCCEEDED(hres))
|
||
|
{
|
||
|
ULONG rgfAttr = SFGAO_VALIDATE;
|
||
|
bRet = SUCCEEDED(psf->lpVtbl->GetAttributesOf(psf, 1, &pidl, &rgfAttr));
|
||
|
psf->lpVtbl->Release(psf);
|
||
|
}
|
||
|
}
|
||
|
return bRet;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: Open a file (taken from ShellExecFile)
|
||
|
|
||
|
Returns: value of ShellExecuteEx
|
||
|
|
||
|
Cond: --
|
||
|
*/
|
||
|
BOOL PUBLIC ExecFile(
|
||
|
HWND hwnd,
|
||
|
LPCTSTR pszVerb,
|
||
|
LPCTSTR pszFile, // Fully qualified and fully resolved path to the file
|
||
|
LPCTSTR pszParams,
|
||
|
LPCTSTR pszDir, // If NULL then working dir is derived from lpszFile (except for UNC's)
|
||
|
LPCITEMIDLIST pidl,
|
||
|
int nShow)
|
||
|
{
|
||
|
SHELLEXECUTEINFO execinfo;
|
||
|
|
||
|
execinfo.cbSize = sizeof(execinfo);
|
||
|
execinfo.hwnd = hwnd;
|
||
|
execinfo.lpVerb = pszVerb;
|
||
|
execinfo.lpFile = pszFile;
|
||
|
execinfo.lpParameters = pszParams;
|
||
|
execinfo.lpDirectory = pszDir;
|
||
|
execinfo.nShow = nShow;
|
||
|
execinfo.fMask = 0;
|
||
|
execinfo.lpIDList = (LPITEMIDLIST)pidl;
|
||
|
|
||
|
if (pidl)
|
||
|
{
|
||
|
execinfo.fMask |= SEE_MASK_IDLIST;
|
||
|
}
|
||
|
|
||
|
return ShellExecuteEx(&execinfo);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: Selects an item in the given cabinet window. Optionally
|
||
|
sets it to be renamed.
|
||
|
|
||
|
This function does not verify if the window is really
|
||
|
a cabinet window.
|
||
|
|
||
|
Returns: --
|
||
|
Cond: --
|
||
|
*/
|
||
|
void PUBLIC SelectItemInCabinet(
|
||
|
HWND hwndCabinet,
|
||
|
LPCITEMIDLIST pidl,
|
||
|
BOOL bEdit)
|
||
|
{
|
||
|
if (IsWindow(hwndCabinet))
|
||
|
{
|
||
|
if (pidl)
|
||
|
{
|
||
|
LPITEMIDLIST pidlItem;
|
||
|
|
||
|
// we need to global clone this because hwndCabinet might be
|
||
|
// in a different process... could happen with common dialog
|
||
|
pidlItem = ILGlobalClone(pidl);
|
||
|
if (pidlItem)
|
||
|
{
|
||
|
UINT uFlagsEx;
|
||
|
|
||
|
if (bEdit)
|
||
|
uFlagsEx = SVSI_EDIT;
|
||
|
else
|
||
|
uFlagsEx = 0;
|
||
|
|
||
|
SendMessage(hwndCabinet, CWM_SELECTITEM,
|
||
|
uFlagsEx | SVSI_SELECT | SVSI_ENSUREVISIBLE |
|
||
|
SVSI_FOCUSED | SVSI_DESELECTOTHERS,
|
||
|
(LPARAM)pidlItem);
|
||
|
ILGlobalFree(pidlItem);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: Open a cabinet window and set the focus on the object.
|
||
|
|
||
|
Returns: --
|
||
|
Cond: --
|
||
|
*/
|
||
|
void PUBLIC OpenCabinet(
|
||
|
HWND hwnd,
|
||
|
LPCITEMIDLIST pidlFolder,
|
||
|
LPCITEMIDLIST pidl,
|
||
|
BOOL bEdit) // TRUE: set the focus to edit the label
|
||
|
{
|
||
|
if (!VerifyExists(pidlFolder, pidl))
|
||
|
{
|
||
|
MsgBox(hwnd, MAKEINTRESOURCE(IDS_MSG_CantFindOriginal), MAKEINTRESOURCE(IDS_CAP_STATUS),
|
||
|
NULL, MB_INFO);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
HWND hwndCabinet;
|
||
|
|
||
|
SHWaitForFileToOpen(pidlFolder, WFFO_ADD, 0L);
|
||
|
if (ExecFile(hwnd, c_szOpen, NULL, NULL, NULL, pidlFolder, SW_NORMAL))
|
||
|
{
|
||
|
// This will wait for the window to open or time out
|
||
|
// We need to disable the dialog box while we are waiting.
|
||
|
DECLAREHOURGLASS;
|
||
|
|
||
|
SetHourglass();
|
||
|
EnableWindow(hwnd, FALSE);
|
||
|
SHWaitForFileToOpen(pidlFolder, WFFO_REMOVE | WFFO_WAIT, WFFO_WAITTIME);
|
||
|
EnableWindow(hwnd, TRUE);
|
||
|
ResetHourglass();
|
||
|
|
||
|
hwndCabinet = FindWindow(c_szCabinetClass, NULL);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// If it failed clear out our wait
|
||
|
hwndCabinet = NULL;
|
||
|
SHWaitForFileToOpen(pidlFolder, WFFO_REMOVE, 0L);
|
||
|
}
|
||
|
|
||
|
if (hwndCabinet)
|
||
|
{
|
||
|
SelectItemInCabinet(hwndCabinet, pidl, bEdit);
|
||
|
|
||
|
// we need to post to the other because we can't activate another
|
||
|
// thread from within a button's callback
|
||
|
PostMessage(hwnd, LNKM_ACTIVATEOTHER, 0, (LPARAM)hwndCabinet);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: Opens the cabinet with the item pointed to by the twin.
|
||
|
(copied and modified from link.c in shelldll)
|
||
|
Returns: --
|
||
|
Cond: --
|
||
|
*/
|
||
|
void PRIVATE Stat_OnFind(
|
||
|
PSTAT this)
|
||
|
{
|
||
|
HWND hwnd = this->hwnd;
|
||
|
HWND hwndRA = GetDlgItem(hwnd, IDC_UPDATEACTIONS);
|
||
|
RA_ITEM item;
|
||
|
|
||
|
if (0 == RecAct_GetItemCount(hwndRA))
|
||
|
return;
|
||
|
|
||
|
ASSERT(S_OK == PageData_Query(this->ppagedata, hwnd, NULL, NULL));
|
||
|
|
||
|
item.mask = RAIF_OUTSIDE | RAIF_NAME;
|
||
|
item.iItem = 0;
|
||
|
|
||
|
if (RecAct_GetItem(hwndRA, &item))
|
||
|
{
|
||
|
TCHAR szCanon[MAX_PATH];
|
||
|
LPITEMIDLIST pidlFolder;
|
||
|
LPITEMIDLIST pidl;
|
||
|
|
||
|
// Use UNC name to find it on the net
|
||
|
PathCanonicalize(item.siOutside.pszDir, szCanon);
|
||
|
pidlFolder = ILCreateFromPath(szCanon);
|
||
|
if (pidlFolder)
|
||
|
{
|
||
|
pidl = ILCreateFromPath(item.pszName);
|
||
|
if (pidl)
|
||
|
{
|
||
|
OpenCabinet(hwnd, pidlFolder, ILFindLastID(pidl), FALSE);
|
||
|
ILFree(pidl);
|
||
|
}
|
||
|
ILFree(pidlFolder);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: Stat WM_COMMAND Handler
|
||
|
Returns: --
|
||
|
Cond: --
|
||
|
*/
|
||
|
void PRIVATE Stat_OnCommand(
|
||
|
PSTAT this,
|
||
|
int id,
|
||
|
HWND hwndCtl,
|
||
|
UINT uNotifyCode)
|
||
|
{
|
||
|
PRECLIST prl;
|
||
|
HRESULT hres;
|
||
|
|
||
|
switch (id)
|
||
|
{
|
||
|
case IDC_PBTSRECON:
|
||
|
case IDC_PBTSFIND:
|
||
|
case IDC_PBTSSPLIT:
|
||
|
RETRY_BEGIN(FALSE)
|
||
|
{
|
||
|
hres = PageData_Query(this->ppagedata, this->hwnd, &prl, NULL);
|
||
|
if (FAILED(hres))
|
||
|
{
|
||
|
// Error
|
||
|
|
||
|
// Unavailable disk?
|
||
|
if (E_TR_UNAVAILABLE_VOLUME == hres)
|
||
|
{
|
||
|
// Yes; ask user to retry/cancel
|
||
|
int id = MsgBox(this->hwnd, MAKEINTRESOURCE(IDS_ERR_UNAVAIL_VOL),
|
||
|
MAKEINTRESOURCE(IDS_CAP_STATUS), NULL, MB_RETRYCANCEL | MB_ICONWARNING);
|
||
|
|
||
|
if (IDRETRY == id)
|
||
|
RETRY_SET(); // Try again
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
RETRY_END()
|
||
|
|
||
|
// Is this a twin?
|
||
|
if (S_OK == hres)
|
||
|
{
|
||
|
// Yes; do the operation
|
||
|
switch (id)
|
||
|
{
|
||
|
case IDC_PBTSRECON:
|
||
|
Stat_OnUpdate(this, prl);
|
||
|
break;
|
||
|
|
||
|
case IDC_PBTSFIND:
|
||
|
Stat_OnFind(this);
|
||
|
break;
|
||
|
|
||
|
case IDC_PBTSSPLIT:
|
||
|
Stat_OnSplit(this);
|
||
|
break;
|
||
|
}
|
||
|
Stat_SetControls(this);
|
||
|
}
|
||
|
else if (S_FALSE == hres)
|
||
|
{
|
||
|
Stat_SetControls(this);
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: Handle RN_ITEMCHANGED
|
||
|
Returns: --
|
||
|
Cond: --
|
||
|
*/
|
||
|
void PRIVATE Stat_HandleItemChange(
|
||
|
PSTAT this,
|
||
|
NM_RECACT * lpnm)
|
||
|
{
|
||
|
PRECITEM pri;
|
||
|
|
||
|
ASSERT((lpnm->mask & RAIF_LPARAM) != 0);
|
||
|
|
||
|
pri = (PRECITEM)lpnm->lParam;
|
||
|
|
||
|
// The action has changed, update the recnode accordingly
|
||
|
//
|
||
|
if (lpnm->mask & RAIF_ACTION)
|
||
|
{
|
||
|
BOOL bEnable;
|
||
|
HWND hwndFocus = GetFocus();
|
||
|
|
||
|
Sync_ChangeRecItemAction(pri, Atom_GetName(Stat_AtomBrf(this)),
|
||
|
this->szFolder, lpnm->uAction);
|
||
|
|
||
|
bEnable = (RAIA_SKIP != lpnm->uAction && RAIA_CONFLICT != lpnm->uAction);
|
||
|
Button_Enable(GetDlgItem(this->hwnd, IDC_PBTSRECON), bEnable);
|
||
|
|
||
|
if ( !hwndFocus || !IsWindowEnabled(hwndFocus) )
|
||
|
{
|
||
|
SetFocus(GetDlgItem(this->hwnd, IDC_PBTSSPLIT));
|
||
|
SendMessage(this->hwnd, DM_SETDEFID, IDC_PBTSSPLIT, 0);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: WM_NOTIFY handler
|
||
|
Returns: varies
|
||
|
Cond: --
|
||
|
*/
|
||
|
LRESULT PRIVATE Stat_OnNotify(
|
||
|
PSTAT this,
|
||
|
int idFrom,
|
||
|
NMHDR * lpnmhdr)
|
||
|
{
|
||
|
LRESULT lRet = PSNRET_NOERROR;
|
||
|
|
||
|
switch (lpnmhdr->code)
|
||
|
{
|
||
|
case RN_ITEMCHANGED:
|
||
|
Stat_HandleItemChange(this, (NM_RECACT *)lpnmhdr);
|
||
|
break;
|
||
|
|
||
|
case PSN_SETACTIVE:
|
||
|
Stat_OnSetActive(this);
|
||
|
break;
|
||
|
|
||
|
case PSN_KILLACTIVE:
|
||
|
// N.b. This message is not sent if user clicks Cancel!
|
||
|
// N.b. This message is sent prior to PSN_APPLY
|
||
|
//
|
||
|
break;
|
||
|
|
||
|
case PSN_APPLY:
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return lRet;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: WM_DESTROY handler
|
||
|
Returns: --
|
||
|
Cond: --
|
||
|
*/
|
||
|
void PRIVATE Stat_OnDestroy(
|
||
|
PSTAT this)
|
||
|
{
|
||
|
FIFree(this->pfi);
|
||
|
}
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////// EXPORTED FUNCTIONS
|
||
|
|
||
|
static BOOL s_bStatRecurse = FALSE;
|
||
|
|
||
|
LRESULT INLINE Stat_DefProc(
|
||
|
HWND hDlg,
|
||
|
UINT msg,
|
||
|
WPARAM wParam,
|
||
|
LPARAM lParam)
|
||
|
{
|
||
|
ENTEREXCLUSIVE()
|
||
|
{
|
||
|
s_bStatRecurse = TRUE;
|
||
|
}
|
||
|
LEAVEEXCLUSIVE()
|
||
|
|
||
|
return DefDlgProc(hDlg, msg, wParam, lParam);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: Real Create Folder Twin dialog proc
|
||
|
Returns: varies
|
||
|
Cond: --
|
||
|
*/
|
||
|
LRESULT Stat_DlgProc(
|
||
|
PSTAT this,
|
||
|
UINT message,
|
||
|
WPARAM wParam,
|
||
|
LPARAM lParam)
|
||
|
{
|
||
|
#pragma data_seg(DATASEG_READONLY)
|
||
|
const static DWORD rgHelpIDs_File[] = {
|
||
|
IDC_ICTSMAIN, IDH_BFC_PROP_FILEICON,
|
||
|
IDC_NAME, IDH_BFC_PROP_FILEICON,
|
||
|
IDC_UPDATEACTIONS, IDH_BFC_UPDATE_SCREEN, // different
|
||
|
IDC_PBTSRECON, IDH_BFC_UPDATE_BUTTON,
|
||
|
IDC_PBTSSPLIT, IDH_BFC_PROP_SPLIT_BUTTON,
|
||
|
IDC_PBTSFIND, IDH_BFC_PROP_FINDORIG_BUTTON,
|
||
|
0, 0 };
|
||
|
|
||
|
const static DWORD rgHelpIDs_Folder[] = {
|
||
|
IDC_ICTSMAIN, IDH_BFC_PROP_FILEICON,
|
||
|
IDC_NAME, IDH_BFC_PROP_FILEICON,
|
||
|
IDC_UPDATEACTIONS, IDH_BFC_UPDATE_SCREEN, // different
|
||
|
IDC_PBTSRECON, IDH_BFC_UPDATE_BUTTON,
|
||
|
IDC_PBTSSPLIT, IDH_BFC_PROP_SPLIT_BUTTON,
|
||
|
IDC_PBTSFIND, IDH_BFC_PROP_FINDORIG_BUTTON,
|
||
|
0, 0 };
|
||
|
#pragma data_seg()
|
||
|
DWORD dw;
|
||
|
|
||
|
switch (message)
|
||
|
{
|
||
|
HANDLE_MSG(this, WM_INITDIALOG, Stat_OnInitDialog);
|
||
|
HANDLE_MSG(this, WM_COMMAND, Stat_OnCommand);
|
||
|
HANDLE_MSG(this, WM_NOTIFY, Stat_OnNotify);
|
||
|
HANDLE_MSG(this, WM_DESTROY, Stat_OnDestroy);
|
||
|
|
||
|
case WM_HELP:
|
||
|
dw = this->ppagedata->bFolder ? (DWORD)(LPVOID)rgHelpIDs_Folder :
|
||
|
(DWORD)(LPVOID)rgHelpIDs_File;
|
||
|
|
||
|
WinHelp(((LPHELPINFO)lParam)->hItemHandle, c_szWinHelpFile, HELP_WM_HELP, dw);
|
||
|
return 0;
|
||
|
|
||
|
case WM_CONTEXTMENU:
|
||
|
dw = this->ppagedata->bFolder ? (DWORD)(LPVOID)rgHelpIDs_Folder :
|
||
|
(DWORD)(LPVOID)rgHelpIDs_File;
|
||
|
|
||
|
WinHelp((HWND)wParam, c_szWinHelpFile, HELP_CONTEXTMENU, dw);
|
||
|
return 0;
|
||
|
|
||
|
case LNKM_ACTIVATEOTHER:
|
||
|
SwitchToThisWindow(GetLastActivePopup((HWND)lParam), TRUE);
|
||
|
SetForegroundWindow((HWND)lParam);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
return Stat_DefProc(this->hwnd, message, wParam, lParam);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: Create Folder Twin Dialog Wrapper
|
||
|
Returns: varies
|
||
|
Cond: --
|
||
|
*/
|
||
|
BOOL CALLBACK Stat_WrapperProc(
|
||
|
HWND hDlg, // std params
|
||
|
UINT message,
|
||
|
WPARAM wParam,
|
||
|
LPARAM lParam)
|
||
|
{
|
||
|
PSTAT this;
|
||
|
|
||
|
// Cool windowsx.h dialog technique. For full explanation, see
|
||
|
// WINDOWSX.TXT. This supports multiple-instancing of dialogs.
|
||
|
//
|
||
|
ENTEREXCLUSIVE()
|
||
|
{
|
||
|
if (s_bStatRecurse)
|
||
|
{
|
||
|
s_bStatRecurse = FALSE;
|
||
|
LEAVEEXCLUSIVE()
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
LEAVEEXCLUSIVE()
|
||
|
|
||
|
this = Stat_GetPtr(hDlg);
|
||
|
if (this == NULL)
|
||
|
{
|
||
|
if (message == WM_INITDIALOG)
|
||
|
{
|
||
|
this = GAlloc(sizeof(*this));
|
||
|
if (!this)
|
||
|
{
|
||
|
MsgBox(hDlg, MAKEINTRESOURCE(IDS_OOM_STATUS), MAKEINTRESOURCE(IDS_CAP_STATUS),
|
||
|
NULL, MB_ERROR);
|
||
|
EndDialog(hDlg, IDCANCEL);
|
||
|
return (BOOL)Stat_DefProc(hDlg, message, wParam, lParam);
|
||
|
}
|
||
|
this->hwnd = hDlg;
|
||
|
Stat_SetPtr(hDlg, this);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return (BOOL)Stat_DefProc(hDlg, message, wParam, lParam);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (message == WM_DESTROY)
|
||
|
{
|
||
|
Stat_DlgProc(this, message, wParam, lParam);
|
||
|
GFree(this);
|
||
|
Stat_SetPtr(hDlg, NULL);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
return SetDlgMsgResult(hDlg, message, Stat_DlgProc(this, message, wParam, lParam));
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|