mirror of https://github.com/lianthony/NT4.0
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.
270 lines
7.0 KiB
270 lines
7.0 KiB
//
|
|
// This file contains some shell specific property sheet related code,
|
|
// which includes:
|
|
// 1. The logic which lets shell extensions add pages.
|
|
// 2. The callback function to be called by those shell extensions.
|
|
// but does not include:
|
|
// 1. The property sheet UI code (should be in COMMCTRL).
|
|
// 2. The file system specific property sheet pages.
|
|
//
|
|
#include "shellprv.h"
|
|
#pragma hdrstop
|
|
|
|
#ifdef CAIRO_DS
|
|
#include "dsdata.h"
|
|
#endif
|
|
|
|
//
|
|
// This function is a callback function from property sheet page extensions.
|
|
//
|
|
BOOL CALLBACK _AddPropSheetPage(HPROPSHEETPAGE hpage, LPARAM lParam)
|
|
{
|
|
PROPSHEETHEADER * ppsh = (PROPSHEETHEADER *)lParam;
|
|
|
|
if (ppsh->nPages < MAX_FILE_PROP_PAGES)
|
|
{
|
|
ppsh->phpage[ppsh->nPages++] = hpage;
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//
|
|
// This function enumerates all the property sheet page extensions for
|
|
// specified class and let them add pages.
|
|
//
|
|
VOID DCA_AppendClassSheetInfo(HDCA hdca, HKEY hkeyProgID, LPPROPSHEETHEADER ppsh, LPDATAOBJECT pdtobj)
|
|
{
|
|
int i;
|
|
for (i = 0; i < DCA_GetItemCount(hdca); i++)
|
|
{
|
|
LPSHELLEXTINIT psei;
|
|
HRESULT hres = DCA_CreateInstance(hdca, i, &IID_IShellExtInit, &psei);
|
|
|
|
if (hres==NOERROR)
|
|
{
|
|
IShellPropSheetExt * pspse;
|
|
if (SUCCEEDED(psei->lpVtbl->Initialize(psei, NULL, pdtobj, hkeyProgID))
|
|
&& SUCCEEDED(psei->lpVtbl->QueryInterface(psei, &IID_IShellPropSheetExt, &pspse)))
|
|
{
|
|
pspse->lpVtbl->AddPages(pspse, _AddPropSheetPage, (LPARAM)ppsh);
|
|
pspse->lpVtbl->Release(pspse);
|
|
}
|
|
psei->lpVtbl->Release(psei);
|
|
}
|
|
}
|
|
}
|
|
|
|
HWND FindStubForPidl(LPCITEMIDLIST pidl)
|
|
{
|
|
HWND hwnd;
|
|
|
|
for (hwnd = FindWindow(c_szStubWindowClass, NULL); hwnd; hwnd = GetWindow(hwnd, GW_HWNDNEXT))
|
|
{
|
|
TCHAR szClass[80];
|
|
|
|
// find stub windows only
|
|
GetClassName(hwnd, szClass, ARRAYSIZE(szClass));
|
|
if (lstrcmpi(szClass, c_szStubWindowClass) == 0)
|
|
{
|
|
int iClass;
|
|
HANDLE hClassPidl;
|
|
DWORD dwProcId;
|
|
|
|
GetWindowThreadProcessId(hwnd, &dwProcId);
|
|
|
|
hClassPidl = (HANDLE)SendMessage(hwnd, STUBM_GETDATA, 0, 0);
|
|
if (hClassPidl)
|
|
{
|
|
LPBYTE lpb;
|
|
|
|
lpb = (LPBYTE)SHLockShared(hClassPidl, dwProcId);
|
|
|
|
if (lpb)
|
|
{
|
|
iClass = *(int *)lpb;
|
|
|
|
if (iClass == SHELL_PROPSHEET_STUB_CLASS &&
|
|
ILIsEqual(pidl, (LPITEMIDLIST)(lpb+SIZEOF(int))) )
|
|
{
|
|
SHUnlockShared(lpb);
|
|
return hwnd;
|
|
}
|
|
SHUnlockShared(lpb);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
HWND FindOtherStub(HIDA hida)
|
|
{
|
|
LPITEMIDLIST pidl;
|
|
HWND hwnd = NULL;
|
|
|
|
if (hida && (HIDA_GetCount(hida) == 1) && (NULL != (pidl = HIDA_ILClone(hida, 0)))) {
|
|
hwnd = FindStubForPidl(pidl);
|
|
ILFree(pidl);
|
|
}
|
|
|
|
return hwnd;
|
|
}
|
|
|
|
HANDLE StuffStubWindowWithPidl(HWND hwnd, LPITEMIDLIST pidlT)
|
|
{
|
|
DWORD dwProcId;
|
|
HANDLE hSharedClassPidl;
|
|
UINT uidlSize;
|
|
|
|
uidlSize = ILGetSize(pidlT);
|
|
GetWindowThreadProcessId(hwnd, &dwProcId);
|
|
|
|
hSharedClassPidl = SHAllocShared(NULL, SIZEOF(int)+uidlSize, dwProcId);
|
|
if (hSharedClassPidl)
|
|
{
|
|
LPBYTE lpb = SHLockShared(hSharedClassPidl, dwProcId);
|
|
if (lpb)
|
|
{
|
|
*(int *)lpb = SHELL_PROPSHEET_STUB_CLASS;
|
|
memcpy(lpb+SIZEOF(int),pidlT, uidlSize);
|
|
SHUnlockShared(lpb);
|
|
SendMessage(hwnd, STUBM_SETDATA, (WPARAM)hSharedClassPidl, 0);
|
|
return hSharedClassPidl;
|
|
}
|
|
SHFreeShared(hSharedClassPidl, dwProcId);
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
HANDLE StuffStubWindow(HWND hwnd, HIDA hida)
|
|
{
|
|
LPITEMIDLIST pidlT = NULL;
|
|
HANDLE hClassPidl = NULL;
|
|
|
|
if (hida && (HIDA_GetCount(hida) == 1) && (NULL != (pidlT = HIDA_ILClone(hida, 0)))) {
|
|
hClassPidl = StuffStubWindowWithPidl(hwnd, pidlT);
|
|
ILFree(pidlT);
|
|
}
|
|
return hClassPidl;
|
|
}
|
|
|
|
BOOL _IsAnyDuplicatedKey(HKEY ahkeys[], UINT ckeys, HKEY hkey)
|
|
{
|
|
UINT ikey;
|
|
for (ikey=0; ikey<ckeys; ikey++)
|
|
{
|
|
if (ahkeys[ikey]==hkey) {
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL SHOpenPropSheet(LPCTSTR pszCaption,
|
|
HKEY ahkeys[], UINT ckeys,
|
|
const CLSID * pclsidDef,
|
|
LPDATAOBJECT pdtobj, IShellBrowser * psb,
|
|
LPCTSTR pStartPage)
|
|
{
|
|
BOOL fSuccess = FALSE;
|
|
PROPSHEETHEADER psh;
|
|
HPROPSHEETPAGE ahpage[MAX_FILE_PROP_PAGES];
|
|
HWND hwnd;
|
|
STGMEDIUM medium;
|
|
HANDLE hClassPidl = NULL;
|
|
HDCA hdca = NULL;
|
|
|
|
DataObj_GetHIDA(pdtobj, &medium);
|
|
#ifdef CAIRO_DS
|
|
if (!medium.hGlobal)
|
|
{
|
|
DataObj_GetDS_HIDA (pdtobj, &medium);
|
|
}
|
|
#endif
|
|
if (medium.hGlobal)
|
|
{
|
|
if (NULL != (hwnd = FindOtherStub(medium.hGlobal)))
|
|
{
|
|
SHReleaseStgMedium(&medium);
|
|
SwitchToThisWindow(GetLastActivePopup(hwnd), TRUE);
|
|
return TRUE;
|
|
}
|
|
else if (NULL != (hwnd = _CreateStubWindow()))
|
|
{
|
|
hClassPidl = StuffStubWindow(hwnd, medium.hGlobal);
|
|
}
|
|
HIDA_ReleaseStgMedium(NULL, &medium);
|
|
}
|
|
|
|
psh.hwndParent = hwnd;
|
|
psh.dwSize = SIZEOF(psh);
|
|
psh.dwFlags = PSH_PROPTITLE;
|
|
psh.hInstance = HINST_THISDLL;
|
|
psh.pszCaption = pszCaption;
|
|
psh.nPages = 0; // incremented in callback
|
|
psh.nStartPage = 0;
|
|
psh.phpage = ahpage;
|
|
if (pStartPage)
|
|
{
|
|
psh.dwFlags |= PSH_USEPSTARTPAGE;
|
|
psh.pStartPage = pStartPage;
|
|
}
|
|
|
|
hdca = DCA_Create();
|
|
if (hdca)
|
|
{
|
|
UINT ikey;
|
|
//
|
|
// Always add this default extention at the top, if any.
|
|
//
|
|
if (pclsidDef)
|
|
{
|
|
DCA_AddItem(hdca, pclsidDef);
|
|
}
|
|
|
|
for (ikey=0; ikey<ckeys; ikey++)
|
|
{
|
|
if (ahkeys[ikey] && !_IsAnyDuplicatedKey(ahkeys, ikey, ahkeys[ikey]))
|
|
{
|
|
DCA_AddItemsFromKey(hdca, ahkeys[ikey], c_szPropSheet);
|
|
}
|
|
}
|
|
|
|
// Notes: ahkeys[ckeys-1] as hkeyProgID
|
|
Assert(ckeys);
|
|
DCA_AppendClassSheetInfo(hdca, ahkeys[ckeys-1], &psh, pdtobj);
|
|
DCA_Destroy(hdca);
|
|
}
|
|
|
|
// Open the property sheet, only if we have some pages.
|
|
if (psh.nPages > 0)
|
|
{
|
|
_try
|
|
{
|
|
if (PropertySheet(&psh) >= 0) // IDOK or IDCANCEL (< 0 is error)
|
|
fSuccess = TRUE;
|
|
}
|
|
_except(UnhandledExceptionFilter(GetExceptionInformation()))
|
|
{
|
|
DebugMsg(DM_ERROR, TEXT("PRSHT: Fault in property sheet"));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ShellMessageBox(HINST_THISDLL, NULL,
|
|
MAKEINTRESOURCE(IDS_NOPAGE),
|
|
MAKEINTRESOURCE(IDS_DESKTOP),
|
|
MB_OK|MB_ICONHAND);
|
|
}
|
|
|
|
// clean up the stub window and data
|
|
SHFreeShared(hClassPidl,GetCurrentProcessId());
|
|
if (psh.hwndParent)
|
|
DestroyWindow(psh.hwndParent);
|
|
|
|
return fSuccess;
|
|
}
|