NT4/private/windows/rover/filesync/syncui/status.c

952 lines
24 KiB
C
Raw Normal View History

2001-01-01 00:00:00 +01:00
//---------------------------------------------------------------------------
//
// 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));
}