Safe file name comparison
Posted
by Jvrg Koenig
on February 2nd, 1999
Since Microsoft provides UNC paths, every file may have two valid names: a short (traditional) and a long file name. OK - one could convert the long file name into a short one and compare these two names; but that will lead to two problems:
o How does one determine which of the two names is the short
one and which is the long ?
o There is no API-function that will convert a long file name into
a short one. There are (of course) some descriptions of how one can do
this, but that's it.
Fortunataly there is another solution. The Win95/NT shell deals
with PIDLs (pointers to item identifier lists)
instead. Every file in the filesystem has one unique PIDL, so the idea
of comparing to file names is to compare their PIDLs.
The bad point is, that this requires some knowledge of the (sucking)
COM interface mechanism...
Here is the way it does:
#include "stdafx.h"
#include <shlobj.h>
// this function compares the PIDLs of two file names.
// NOTE that you cannot compare the names directly (strcmp() for
// instance), because one of the names might appear in
// long file name format and the other in short file name
// format.
// The function returns TRUE, if <pszPath1> and <pszPath2>
// name the same file in the filesystem, otherwise FALSE.
//
// <pszPath1> and <pszPath2> shall be absolute pathnames ...
BOOL CompareFilenames( LPCSTR pszPath1, LPCSTR pszPath2 ) {
VERIFY(pszPath1 != 0);
VERIFY(pszPath2 != 0);
CoInitialize(0) ;
BOOL bRet = FALSE;
LPSHELLFOLDER pDesktopFolder;
if( SUCCEEDED( SHGetDesktopFolder(&pDesktopFolder)) ) {
// COM-interface always needs unicode strings ...
OLECHAR olePath1[MAX_PATH], olePath2[MAX_PATH];
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pszPath1, -1, olePath1, MAX_PATH);
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pszPath2, -1, olePath2, MAX_PATH);
// retrieve PIDLs
LPITEMIDLIST pidl1, pidl2;
DWORD dwAttr;
DWORD dummy;
if( SUCCEEDED(pDesktopFolder->ParseDisplayName(0, 0, olePath1, &dummy, &pidl1, &dwAttr)) &&
SUCCEEDED(pDesktopFolder->ParseDisplayName(0, 0, olePath2, &dummy, &pidl2, &dwAttr)) ) {
// now we can compare the PIDLs
HRESULT hRes = pDesktopFolder->CompareIDs(0, pidl1, pidl2);
if( HRESULT_CODE(hRes) == 0 )
bRet = TRUE;
// free the PIDLs (do not forget this !) ...
LPMALLOC pMalloc;
SHGetMalloc(&pMalloc);
pMalloc->Free((void *)pidl1);
pMalloc->Free((void *)pidl2);
pMalloc->Release();
}
pDesktopFolder->Release();
}
CoUninitialize();
return bRet;
}

Comments
Yet another (easier?) way...
Posted by Legacy on 11/17/1998 12:00amOriginally posted by: Ken Sutherland
ReplyAnother way to distinguish files on Win32
Posted by Legacy on 11/11/1998 12:00amOriginally posted by: Josh Baudhuin
Reply