Windows NT 4.0 source code leak
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

//
// 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;
}