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.
521 lines
12 KiB
521 lines
12 KiB
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1997.
|
|
//
|
|
// File: P I D L . C P P
|
|
//
|
|
// Contents: PIDL utility routines. This stuff is mainly copied from the
|
|
// existing Namespace extension samples and real code, since
|
|
// everyone and their gramma uses this stuff.
|
|
//
|
|
// Notes:
|
|
//
|
|
// Author: jeffspr 1 Oct 1997
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include "pch.h"
|
|
#pragma hdrstop
|
|
|
|
#include "shlobj.h"
|
|
#include "shlobjp.h"
|
|
|
|
#include "pidlutil.h"
|
|
|
|
#if DBG
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ILNext
|
|
//
|
|
// Purpose: Return the next PIDL in the list
|
|
//
|
|
// Arguments:
|
|
// pidl []
|
|
//
|
|
// Returns:
|
|
//
|
|
// Author: jeffspr 1 Oct 1997 (from brianwen)
|
|
//
|
|
// Notes:
|
|
//
|
|
LPITEMIDLIST ILNext(LPCITEMIDLIST pidl)
|
|
{
|
|
if (pidl)
|
|
{
|
|
pidl = (LPITEMIDLIST) ((BYTE *)pidl + pidl->mkid.cb);
|
|
}
|
|
|
|
return (LPITEMIDLIST)pidl;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ILIsEmpty
|
|
//
|
|
// Purpose: Is this PIDL empty
|
|
//
|
|
// Arguments:
|
|
// pidl []
|
|
//
|
|
// Returns:
|
|
//
|
|
// Author: jeffspr 1 Oct 1997 (from brianwen)
|
|
//
|
|
// Notes:
|
|
//
|
|
BOOL ILIsEmpty(LPCITEMIDLIST pidl)
|
|
{
|
|
return (!pidl || !pidl->mkid.cb);
|
|
|
|
}
|
|
#endif // #if DBG
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ILCreate
|
|
//
|
|
// Purpose: Create a PIDL
|
|
//
|
|
// Arguments:
|
|
// cbSize []
|
|
//
|
|
// Returns:
|
|
//
|
|
// Author: jeffspr 1 Oct 1997 (from brianwen)
|
|
//
|
|
// Notes:
|
|
//
|
|
LPITEMIDLIST ILCreate(DWORD dwSize)
|
|
{
|
|
LPITEMIDLIST pidl = (LPITEMIDLIST) SHAlloc(dwSize);
|
|
|
|
return pidl;
|
|
}
|
|
|
|
VOID FreeIDL(LPITEMIDLIST pidl)
|
|
{
|
|
Assert(pidl);
|
|
|
|
SHFree(pidl);
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ILIsSingleID
|
|
//
|
|
// Purpose: Returns TRUE if the idlist has just one ID in it.
|
|
//
|
|
// Arguments:
|
|
// pidl []
|
|
//
|
|
// Returns:
|
|
//
|
|
// Author: jeffspr 1 Oct 1997 (from brianwen)
|
|
//
|
|
// Notes:
|
|
//
|
|
BOOL ILIsSingleID(LPCITEMIDLIST pidl)
|
|
{
|
|
if (pidl == NULL)
|
|
return FALSE;
|
|
|
|
return (pidl->mkid.cb == 0 || ILNext(pidl)->mkid.cb == 0);
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ILGetCID
|
|
//
|
|
// Purpose: Returns the number of ID's in the list.
|
|
//
|
|
// Arguments:
|
|
// pidl []
|
|
//
|
|
// Returns:
|
|
//
|
|
// Author: jeffspr 1 Oct 1997 (from brianwen)
|
|
//
|
|
// Notes:
|
|
//
|
|
UINT ILGetCID(LPCITEMIDLIST pidl)
|
|
{
|
|
UINT cid = 0;
|
|
|
|
while (!ILIsEmpty(pidl))
|
|
{
|
|
++ cid;
|
|
pidl = ILNext(pidl);
|
|
}
|
|
|
|
return cid;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ILGetSizeCID
|
|
//
|
|
// Purpose: Get the length of the first cid items in a pidl.
|
|
//
|
|
// Arguments:
|
|
// pidl []
|
|
// cid []
|
|
//
|
|
// Returns:
|
|
//
|
|
// Author: jeffspr 1 Oct 1997 (from brianwen)
|
|
//
|
|
// Notes:
|
|
//
|
|
UINT ILGetSizeCID(LPCITEMIDLIST pidl, UINT cid)
|
|
{
|
|
UINT cbTotal = 0;
|
|
|
|
if (pidl)
|
|
{
|
|
cbTotal += sizeof(pidl->mkid.cb); // Null terminator
|
|
|
|
while (cid && !ILIsEmpty(pidl))
|
|
{
|
|
cbTotal += pidl->mkid.cb;
|
|
pidl = ILNext(pidl);
|
|
-- cid;
|
|
}
|
|
}
|
|
|
|
return cbTotal;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: CloneIDLFirstCID
|
|
//
|
|
// Purpose: Make a new list consisting of only the first cid items on
|
|
// an existing list.
|
|
//
|
|
// Arguments:
|
|
// pidl []
|
|
// cid []
|
|
//
|
|
// Returns:
|
|
//
|
|
// Author: jeffspr 1 Oct 1997 (from brianwen)
|
|
//
|
|
// Notes:
|
|
//
|
|
LPITEMIDLIST CloneIDLFirstCID(LPCITEMIDLIST pidl, UINT cid)
|
|
{
|
|
Assert((INT)cid >= 0);
|
|
|
|
UINT cb = ILGetSizeCID(pidl, cid);
|
|
LPITEMIDLIST pidlRet = (LPITEMIDLIST) SHAlloc(cb);
|
|
|
|
if (pidlRet)
|
|
{
|
|
// Notes: no need to zero-init.
|
|
// Also, do not copy the NULL terminator.
|
|
memcpy (pidlRet, pidl, cb - sizeof(pidl->mkid.cb));
|
|
|
|
LPITEMIDLIST pidlTerm = pidlRet;
|
|
|
|
// Cannot test for NULL terminator, we have not terminated
|
|
// the list yet.
|
|
//
|
|
while (cid)
|
|
{
|
|
pidlTerm = ILNext(pidlTerm);
|
|
-- cid;
|
|
}
|
|
|
|
pidlTerm->mkid.cb = 0;
|
|
}
|
|
|
|
return pidlRet;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ILSkipCID
|
|
//
|
|
// Purpose: Skips the first cid items in a pidl.
|
|
//
|
|
// Arguments:
|
|
// pidl []
|
|
// cid []
|
|
//
|
|
// Returns:
|
|
//
|
|
// Author: jeffspr 1 Oct 1997 (from brianwen)
|
|
//
|
|
// Notes:
|
|
//
|
|
LPITEMIDLIST ILSkipCID(LPCITEMIDLIST pidl, UINT cid)
|
|
{
|
|
Assert((INT)cid >= 0);
|
|
|
|
while (cid && !ILIsEmpty(pidl))
|
|
{
|
|
pidl = ILNext(pidl);
|
|
-- cid;
|
|
}
|
|
|
|
return (LPITEMIDLIST)pidl;
|
|
}
|
|
|
|
|
|
#if 0
|
|
BOOL ILIsEqual(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
|
|
{
|
|
if (FSetupGlobalShellFolders())
|
|
{
|
|
LPSHELLFOLDER psfDesktop = (LPSHELLFOLDER) PvGlobGet (ipsfDesktop);
|
|
if (psfDesktop)
|
|
{
|
|
VERIFYPTR(pidl1, FALSE);
|
|
VERIFYPTR(pidl2, FALSE);
|
|
|
|
return psfDesktop->CompareIDs(0, pidl1, pidl2) == ResultFromShort(0);
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
#endif
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: CloneIDL
|
|
//
|
|
// Purpose: Clone an IDL (return a duplicate)
|
|
//
|
|
// Arguments:
|
|
// pidl []
|
|
//
|
|
// Returns:
|
|
//
|
|
// Author: jeffspr 1 Oct 1997 (from brianwen)
|
|
//
|
|
// Notes:
|
|
//
|
|
LPITEMIDLIST CloneIDL(LPCITEMIDLIST pidl)
|
|
{
|
|
UINT cb = 0;
|
|
LPITEMIDLIST pidlRet = NULL;
|
|
|
|
if (pidl)
|
|
{
|
|
cb = ILGetSize(pidl);
|
|
|
|
pidlRet = (LPITEMIDLIST) SHAlloc(cb);
|
|
if (pidlRet)
|
|
{
|
|
memcpy(pidlRet, pidl, cb);
|
|
}
|
|
}
|
|
|
|
return pidlRet;
|
|
}
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: CloneRgIDL
|
|
//
|
|
// Purpose: Clone a pidl array
|
|
//
|
|
// Arguments:
|
|
// rgpidl [in] PIDL array to clone
|
|
// cidl [in] Count of the pidl array
|
|
// fUseCache [in] If TRUE, generate the returned IDL from the cache
|
|
// fAllowNonCacheItems [in] Use old version of pidl if cached version non available
|
|
// pppidl [out] Return pointer for pidl array
|
|
//
|
|
// Returns:
|
|
//
|
|
// Author: jeffspr 22 Oct 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
/*
|
|
HRESULT HrCloneRgIDL(
|
|
LPCITEMIDLIST * rgpidl,
|
|
ULONG cidl,
|
|
BOOL fUseCache,
|
|
BOOL fAllowNonCacheItems,
|
|
LPITEMIDLIST ** pppidl,
|
|
ULONG * pcidl)
|
|
{
|
|
HRESULT hr = NOERROR;
|
|
LPITEMIDLIST * rgpidlReturn = NULL;
|
|
ULONG irg = 0;
|
|
ULONG cidlCopied = 0;
|
|
|
|
Assert(pppidl);
|
|
Assert(pcidl);
|
|
Assert(rgpidl);
|
|
|
|
if (!rgpidl || !cidl)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto Exit;
|
|
}
|
|
else
|
|
{
|
|
// Alloc the return buffer
|
|
//
|
|
rgpidlReturn = (LPITEMIDLIST *) SHAlloc(cidl * sizeof(LPITEMIDLIST));
|
|
if (!rgpidlReturn)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Exit;
|
|
}
|
|
else
|
|
{
|
|
// Clone all elements within the passed in PIDL array
|
|
//
|
|
for (irg = 0; irg < cidl; irg++)
|
|
{
|
|
if (rgpidl[irg])
|
|
{
|
|
if (fUseCache)
|
|
{
|
|
PCONNLISTENTRY pcle = NULL;
|
|
PCONFOLDPIDL pcfp = (PCONFOLDPIDL) rgpidl[irg];
|
|
|
|
hr = g_ccl.HrFindConnectionByGuid(&(pcfp->guidId), &pcle);
|
|
if (hr == S_OK)
|
|
{
|
|
Assert(pcle);
|
|
Assert(pcle->pccfe);
|
|
|
|
// Copy to the return pidl array.
|
|
hr = HrConFoldEntryToPidl(pcle->pccfe, &(rgpidlReturn[cidlCopied++]));
|
|
if (FAILED(hr))
|
|
goto Exit;
|
|
}
|
|
else
|
|
{
|
|
TraceTag(ttidShellFolder, "HrCloneRgIDL: Connection find returned: 0x%08x", hr);
|
|
|
|
if (hr == S_FALSE)
|
|
{
|
|
if (fAllowNonCacheItems)
|
|
{
|
|
TraceTag(ttidShellFolder, "HrCloneRgIDL: Connection not found in cache, "
|
|
"using non-cache item");
|
|
|
|
rgpidlReturn[cidlCopied++] = CloneIDL((LPITEMIDLIST)rgpidl[irg]);
|
|
if (!rgpidlReturn[irg])
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Exit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TraceTag(ttidShellFolder, "HrCloneRgIDL: Connection not found in cache. "
|
|
"Dropping item from array");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
AssertSz(FALSE, "HrCloneRgIDL: Connection find HR_FAILED");
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Clone this element in the PIDL array
|
|
//
|
|
rgpidlReturn[cidlCopied++] = CloneIDL ((LPITEMIDLIST) rgpidl[irg]);
|
|
if (!rgpidlReturn[irg])
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Exit;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Make sure that we don't try to delete bogus data later.
|
|
//
|
|
rgpidlReturn[cidlCopied++] = NULL;
|
|
|
|
AssertSz(FALSE, "Bogus element in the rgpidl in HrCloneRgIDL");
|
|
hr = E_INVALIDARG;
|
|
goto Exit;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Exit:
|
|
if (FAILED(hr))
|
|
{
|
|
// Free the already-allocated IDLISTs
|
|
//
|
|
ULONG irgT = 0;
|
|
|
|
for (irgT = 0; irgT < irg; irgT++)
|
|
{
|
|
if (rgpidlReturn[irgT])
|
|
{
|
|
FreeIDL(rgpidlReturn[irgT]);
|
|
}
|
|
}
|
|
|
|
SHFree(rgpidlReturn);
|
|
*pppidl = NULL;
|
|
}
|
|
else
|
|
{
|
|
// Fill in the return var.
|
|
//
|
|
*pppidl = rgpidlReturn;
|
|
*pcidl = cidlCopied;
|
|
}
|
|
|
|
TraceHr(ttidError, FAL, hr, FALSE, "HrCloneRgIDL");
|
|
return hr;
|
|
|
|
} // CloneRgIDL
|
|
*/
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: FreeRgIDL
|
|
//
|
|
// Purpose: Free a PIDL array
|
|
//
|
|
// Arguments:
|
|
// cidl [in] Size of PIDL array
|
|
// apidl [in] Pointer to the array itself.
|
|
//
|
|
// Returns:
|
|
//
|
|
// Author: jeffspr 27 Oct 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
VOID FreeRgIDL(
|
|
UINT cidl,
|
|
LPITEMIDLIST * apidl)
|
|
{
|
|
if (apidl)
|
|
{
|
|
for (UINT i = 0; i < cidl; i++)
|
|
{
|
|
FreeIDL(apidl[i]);
|
|
}
|
|
|
|
SHFree(apidl);
|
|
}
|
|
}
|