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.
299 lines
7.7 KiB
299 lines
7.7 KiB
//---------------------------------------------------------------------------
|
|
//
|
|
// Copyright (c) Microsoft Corporation 1991-1995
|
|
//
|
|
// File: fldrlist.c
|
|
//
|
|
// BUGBUG - We could speed up this stuff by having the rest of the shell just
|
|
// call through to here and let us loop over the hwnd's, instead of letting
|
|
// the shell loop over the hwnd's and then call us to do the comparison.
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
#include "cabinet.h"
|
|
|
|
HDPA s_hdpaFolders = NULL;
|
|
|
|
extern COMPAREROOT *g_psCR; // To get the current desktop's root info
|
|
|
|
int CALLBACK _CompareRootHwnd(LPVOID lpcr1, LPVOID lpcr2, LPARAM lparam)
|
|
{
|
|
HWND hwnd1 = NULL;
|
|
HWND hwnd2 = NULL;
|
|
|
|
if (lpcr1)
|
|
hwnd1 = ((LPCOMPAREROOT)lpcr1)->hwnd;
|
|
if (lpcr2)
|
|
hwnd2 = ((LPCOMPAREROOT)lpcr2)->hwnd;
|
|
|
|
if (hwnd1 > hwnd2)
|
|
return 1;
|
|
else if (hwnd1 < hwnd2)
|
|
return -1;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
void FolderList_AddCompare(LPCOMPAREROOT lpcr)
|
|
{
|
|
INT iIndex;
|
|
|
|
if (!s_hdpaFolders)
|
|
s_hdpaFolders = DPA_Create(0);
|
|
|
|
iIndex = DPA_Search(s_hdpaFolders, lpcr, 0, _CompareRootHwnd,
|
|
0, DPAS_SORTED|DPAS_INSERTBEFORE);
|
|
|
|
if (iIndex != -1)
|
|
{
|
|
LPCOMPAREROOT lpcrOther = DPA_GetPtr(s_hdpaFolders,iIndex);
|
|
|
|
if (lpcrOther && _CompareRootHwnd(lpcr,lpcrOther,(LPARAM)NULL) == 0)
|
|
{
|
|
LocalFree(lpcrOther);
|
|
DPA_SetPtr(s_hdpaFolders,iIndex,lpcr);
|
|
}
|
|
else
|
|
{
|
|
DPA_InsertPtr(s_hdpaFolders,iIndex,lpcr);
|
|
}
|
|
}
|
|
}
|
|
|
|
void FolderList_RemoveCompare(LPCOMPAREROOT lpcr)
|
|
{
|
|
INT iIndex;
|
|
|
|
if (!s_hdpaFolders)
|
|
return;
|
|
|
|
iIndex = DPA_Search(s_hdpaFolders, lpcr, 0, _CompareRootHwnd,
|
|
0, DPAS_SORTED);
|
|
|
|
if (iIndex != -1)
|
|
{
|
|
LPCOMPAREROOT lpcrOther = DPA_FastGetPtr(s_hdpaFolders,iIndex);
|
|
|
|
LocalFree(lpcrOther);
|
|
DPA_DeletePtr(s_hdpaFolders, iIndex);
|
|
}
|
|
}
|
|
|
|
BOOL _CompareRoots(LPCOMPAREROOT lpcr1, LPCOMPAREROOT lpcr2)
|
|
{
|
|
CR_MASK mask1;
|
|
CR_MASK mask2;
|
|
|
|
mask1 = lpcr1 ? lpcr1->mask : 0;
|
|
mask2 = lpcr2 ? lpcr2->mask : 0;
|
|
|
|
// Must have the same mask to be equal
|
|
if (((mask1^mask2) & (CR_CLSID|CR_IDLROOT)) == 0)
|
|
{
|
|
// It's up to the class to handle being called with different roots
|
|
if (mask1 & CR_CLSID)
|
|
{
|
|
if (!IsEqualGUID(&lpcr1->clsid, &lpcr2->clsid))
|
|
return FALSE;
|
|
}
|
|
|
|
// I should probably compare IDList's so I will recognize an object
|
|
// that has several "names", but this really should not be a problem
|
|
if (mask1 & CR_IDLROOT)
|
|
{
|
|
if (!ILIsEqual(&lpcr1->idlRoot, &lpcr2->idlRoot))
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL _CompareFolder(LPCOMPAREROOT lpcr1, LPCOMPAREROOT lpcr2)
|
|
{
|
|
CR_MASK mask1;
|
|
CR_MASK mask2;
|
|
|
|
mask1 = lpcr1 ? lpcr1->mask : 0;
|
|
mask2 = lpcr2 ? lpcr2->mask : 0;
|
|
|
|
// Must have the same mask to be equal
|
|
if (((mask1^mask2) & (CR_IDLFOLDER)) == 0)
|
|
{
|
|
// I should probably compare IDList's so I will recognize an object
|
|
// that has several "names", but this really should not be a problem
|
|
if (mask1 & CR_IDLFOLDER)
|
|
{
|
|
LPCITEMIDLIST pidl1;
|
|
LPCITEMIDLIST pidl2;
|
|
|
|
pidl1 = (LPCITEMIDLIST)((LPBYTE)&lpcr1->idlRoot
|
|
+ ((mask1 & CR_IDLROOT) ? ILGetSize(&lpcr1->idlRoot) : 0));
|
|
pidl2 = (LPCITEMIDLIST)((LPBYTE)&lpcr2->idlRoot
|
|
+ ((mask2 & CR_IDLROOT) ? ILGetSize(&lpcr2->idlRoot) : 0));
|
|
|
|
if (!ILIsEqual(pidl1, pidl2))
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL FolderList_PerformCompare( LPCOMPAREROOT lpcr )
|
|
{
|
|
INT iIndex;
|
|
|
|
// Find the root we have for the window and see if it matches.
|
|
|
|
if (!s_hdpaFolders)
|
|
return FALSE;
|
|
|
|
iIndex = DPA_Search(s_hdpaFolders, lpcr, 0, _CompareRootHwnd,
|
|
0, DPAS_SORTED);
|
|
if (iIndex == -1)
|
|
return FALSE;
|
|
|
|
if ((lpcr->mask & CR_IDLFOLDERONLY) == 0) // Need to compare idlroots?
|
|
if (!_CompareRoots(lpcr,(LPCOMPAREROOT)DPA_FastGetPtr(s_hdpaFolders,iIndex)))
|
|
return FALSE;
|
|
|
|
if ((lpcr->mask & CR_IDLFOLDER))
|
|
return _CompareFolder(lpcr,
|
|
(LPCOMPAREROOT)DPA_FastGetPtr(s_hdpaFolders,iIndex));
|
|
else
|
|
return TRUE;
|
|
}
|
|
|
|
LPCOMPAREROOT FolderList_BuildCompare( HWND hwnd, const CLSID *pclsid, LPCITEMIDLIST pidlRoot, LPCITEMIDLIST pidlFolder)
|
|
{
|
|
LPCOMPAREROOT lpcr = NULL;
|
|
UINT uLenRoot;
|
|
UINT uLenFolder;
|
|
UINT uSize;
|
|
|
|
uLenRoot = pidlRoot ? ILGetSize(pidlRoot) : 0;
|
|
uLenFolder = pidlFolder ? ILGetSize(pidlFolder) : 0;
|
|
|
|
uSize = SIZEOF(COMPAREROOT)+uLenRoot+uLenFolder;
|
|
|
|
lpcr = (LPCOMPAREROOT)LocalAlloc(LPTR,uSize);
|
|
if (!lpcr)
|
|
return NULL;
|
|
|
|
lpcr->uSize = uSize;
|
|
lpcr->mask = 0;
|
|
lpcr->hwnd = hwnd;
|
|
|
|
if (pclsid)
|
|
{
|
|
lpcr->clsid = *pclsid;
|
|
lpcr->mask |= CR_CLSID;
|
|
}
|
|
if (pidlRoot)
|
|
{
|
|
hmemcpy(&lpcr->idlRoot, pidlRoot, uLenRoot);
|
|
lpcr->mask |= CR_IDLROOT;
|
|
}
|
|
|
|
if (pidlFolder)
|
|
{
|
|
if (!pclsid && !pidlRoot) // Neither spec means compare only fldr
|
|
lpcr->mask |= CR_IDLFOLDERONLY;
|
|
|
|
hmemcpy((LPBYTE)(&lpcr->idlRoot)+uLenRoot, pidlFolder, uLenFolder);
|
|
lpcr->mask |= CR_IDLFOLDER;
|
|
}
|
|
return lpcr;
|
|
}
|
|
|
|
void FolderList_Register(HWND hwnd,const CLSID *pclsid,LPCITEMIDLIST pidlRoot,LPCITEMIDLIST pidlFolder)
|
|
{
|
|
LPCOMPAREROOT lpcr = FolderList_BuildCompare(hwnd,pclsid,pidlRoot,pidlFolder);
|
|
HWND hwndDesktop = GetShellWindow();
|
|
|
|
if (!lpcr)
|
|
return;
|
|
|
|
if (hwndDesktop)
|
|
{
|
|
DWORD dwProcId;
|
|
HANDLE hcr;
|
|
|
|
GetWindowThreadProcessId(hwndDesktop,&dwProcId);
|
|
hcr = SHAllocShared(lpcr,lpcr->uSize,dwProcId);
|
|
LocalFree(lpcr);
|
|
if (!hcr)
|
|
{
|
|
return; // If this fails, something else will soon enough
|
|
}
|
|
// REVIEW: BobDay - This could be a sendmessage to prevent
|
|
// synchronization problems. If so, allocate the data in this
|
|
// process (via this proc-id) instead of the desktop window.
|
|
PostMessage(hwndDesktop, CWM_SPECIFYCOMPARE, 0, (LPARAM)hcr);
|
|
}
|
|
else
|
|
{
|
|
FolderList_AddCompare(lpcr);
|
|
LocalFree(lpcr);
|
|
}
|
|
}
|
|
|
|
void FolderList_RegisterWindow(HWND hwnd, LPCITEMIDLIST pidlFolder)
|
|
{
|
|
LPCLSID pclsid;
|
|
LPCITEMIDLIST pidlRoot;
|
|
|
|
if (g_psCR)
|
|
{
|
|
pclsid = (g_psCR->mask & CR_CLSID) ? &g_psCR->clsid : NULL;
|
|
pidlRoot = (g_psCR->mask & CR_IDLROOT) ? &g_psCR->idlRoot : NULL;
|
|
}
|
|
else
|
|
{
|
|
pclsid = NULL;
|
|
pidlRoot = NULL;
|
|
}
|
|
|
|
FolderList_Register(hwnd, pclsid, pidlRoot, pidlFolder);
|
|
}
|
|
|
|
void FolderList_Unregister(HWND hwnd)
|
|
{
|
|
HWND hwndDesktop = GetShellWindow();
|
|
COMPAREROOT cr;
|
|
|
|
cr.uSize = SIZEOF(COMPAREROOT);
|
|
cr.hwnd = hwnd;
|
|
cr.mask = CR_REMOVE;
|
|
|
|
if (hwndDesktop)
|
|
{
|
|
DWORD dwProcId;
|
|
HANDLE hcr;
|
|
|
|
GetWindowThreadProcessId(hwndDesktop,&dwProcId);
|
|
hcr = SHAllocShared(&cr,cr.uSize,dwProcId);
|
|
if (!hcr)
|
|
{
|
|
return; // If this fails, something else will soon enough
|
|
}
|
|
// REVIEW: BobDay - This could be a sendmessage to prevent
|
|
// synchronization problems. If so, allocate the data in this
|
|
// process (via this proc-id) instead of the desktop window.
|
|
PostMessage(hwndDesktop, CWM_SPECIFYCOMPARE, 0, (LPARAM)hcr);
|
|
}
|
|
else
|
|
{
|
|
FolderList_RemoveCompare(&cr);
|
|
}
|
|
}
|
|
|
|
void FolderList_UnregisterWindow(HWND hwnd)
|
|
{
|
|
FolderList_Unregister(hwnd);
|
|
}
|
|
|
|
void FolderList_Terminate()
|
|
{
|
|
// BUGBUG - BobDay - We need to clean this up at some point
|
|
}
|