windows-nt/Source/XPSP1/NT/shell/tools/shlexts/pidlcmds.cpp
2020-09-26 16:20:57 +08:00

899 lines
23 KiB
C++

#include "precomp.h"
#pragma hdrstop
#include "shguidp.h"
#include "..\..\shell32\pidl.h"
#include "..\..\shell32\shitemid.h"
// We never want assertions since we are the debugger extension!
#undef DBG
#undef DEBUG
#include "..\..\lib\idhidden.cpp"
extern "C"
{
#include <stdexts.h>
};
UNALIGNED WCHAR * ualstrcpyW(UNALIGNED WCHAR * dst, UNALIGNED const WCHAR * src)
{
UNALIGNED WCHAR * cp = dst;
while( *cp++ = *src++ )
NULL ;
return( dst );
}
///////////////////////////////////////////////////////////////////////////////
// Pidl Cracking function //
// //
// returns fSuccess //
// //
// History: //
// 11/4/97 Created by cdturner //
// //
///////////////////////////////////////////////////////////////////////////////
// NOTE: the options are autovalidate before they are passed to us
typedef enum _PidlTypes
{
PIDL_UNKNOWN,
PIDL_ROOT,
PIDL_FILESYS,
PIDL_DRIVES,
PIDL_NET,
PIDL_INTERNET,
PIDL_FAVORITES
} PIDLTYPE;
#define PIDL_BUFFER_SIZE 400
class CPidlBreaker
{
public:
CPidlBreaker( LPVOID pArg );
~CPidlBreaker( );
void SetVerbose() {_fVerbose = TRUE;};
VOID SetType( PIDLTYPE eType );
BOOL FillBuffer( DWORD cbSize, BOOL fAppend );
VOID ResetBuffer( void );
WORD FetchWord();
DWORD FetchDWORD();
LPBYTE GetBuffer( int iPos = 0);
PIDLTYPE CrackType( BYTE bType );
void PrintType( PIDLTYPE eType );
BOOL PrintPidl();
BOOL PrintRootPidl();
BOOL PrintDrivePidl();
BOOL PrintFileSysPidl();
BOOL PrintInternetPidl();
BOOL PrintNetworkPidl();
BOOL GetSHIDFlags( BYTE bFlags, CHAR * pszBuffer, DWORD cbSize );
void CLSIDToString( CHAR * pszBuffer, DWORD cbSize, REFCLSID rclsid );
BOOL GetCLSIDText( const CHAR * pszCLSID, CHAR * pszBuffer, DWORD cbSize );
private:
PIDLTYPE _eType;
LPVOID _pArg;
BYTE _rgBuffer[PIDL_BUFFER_SIZE];
int _iCurrent;
int _iMax;
BOOL _fVerbose;
// used to display slashes right when we are not in verbose mode...
BOOL _fSlash;
};
extern "C" BOOL Ipidl( DWORD dwOpts,
LPVOID pArg )
{
PIDLTYPE eType = PIDL_UNKNOWN;
CPidlBreaker Breaker( pArg );
if ( dwOpts & OFLAG(r))
{
Breaker.SetType( PIDL_ROOT );
}
else if ( dwOpts & OFLAG(f))
{
Breaker.SetType( PIDL_FILESYS );
}
if (dwOpts & OFLAG(v))
{
Breaker.SetVerbose();
}
BOOL bRes = FALSE;
__try
{
bRes = Breaker.PrintPidl();
}
__except( EXCEPTION_EXECUTE_HANDLER )
{
Print( "Exception caught in !pidl\n");
}
if ( !(dwOpts & OFLAG(v)) )
Print( "\n" );
return bRes;
}
VOID CPidlBreaker::SetType( PIDLTYPE eType )
{
_eType = eType;
}
CPidlBreaker::CPidlBreaker( LPVOID pArg )
{
_pArg = pArg;
_iCurrent = 0;
_iMax = 0;
_eType = PIDL_UNKNOWN;
_fVerbose = FALSE;
_fSlash = FALSE;
}
CPidlBreaker::~CPidlBreaker( )
{
}
BOOL CPidlBreaker::FillBuffer( DWORD cbSize, BOOL fAppend )
{
if ( !fAppend )
{
_iCurrent = 0;
_iMax = 0;
}
int iStart = fAppend ? _iMax : 0;
if ( cbSize + iStart > PIDL_BUFFER_SIZE )
{
return FALSE;
}
#ifdef DEBUG
char szBuffer[50];
sprintf( szBuffer, "****Moving %d from %8X\n", cbSize, _pArg );
Print( szBuffer );
#endif
if ( tryMoveBlock( _rgBuffer + iStart, _pArg, cbSize ))
{
#ifdef DEBUG
for ( int iByte = 0; iByte < (int) cbSize; iByte ++ )
{
sprintf( szBuffer, "Byte %2x\n", _rgBuffer[iByte + iStart] );
Print( szBuffer );
}
#endif
_pArg = (LPBYTE) _pArg + cbSize;
_iMax += cbSize;
return TRUE;
}
else
{
return FALSE;
}
}
WORD CPidlBreaker::FetchWord()
{
// assume that the buffer has been filled...
if ( _iCurrent + 1 >= _iMax )
{
return 0;
}
WORD wRet = MAKEWORD( _rgBuffer[_iCurrent], _rgBuffer[_iCurrent + 1]);
_iCurrent += 2;
#ifdef DEBUG
char szBuffer[200];
sprintf( szBuffer, "FetchWord() == %4X\n", wRet );
Print( szBuffer );
#endif
return wRet;
}
DWORD CPidlBreaker::FetchDWORD()
{
// assume that the buffer has been filled...
if ( _iCurrent + 3 >= _iMax )
{
return 0;
}
DWORD dwRet = MAKELONG( MAKEWORD( _rgBuffer[_iCurrent], _rgBuffer[_iCurrent + 1]),
MAKEWORD( _rgBuffer[_iCurrent + 2], _rgBuffer[_iCurrent + 3] ));
_iCurrent += 4;
#ifdef DEBUG
char szBuffer[200];
sprintf( szBuffer, "FetchDWord() == %8X\n", dwRet );
Print( szBuffer );
#endif
return dwRet;
}
LPBYTE CPidlBreaker::GetBuffer(int iPos)
{
return _rgBuffer + _iCurrent + iPos;
}
VOID CPidlBreaker::ResetBuffer( )
{
_iCurrent = 0;
_iMax = 0;
}
BOOL CPidlBreaker::PrintRootPidl()
{
CHAR szBuffer[200];
if ( !FillBuffer( sizeof( WORD ), FALSE ))
{
Print( "ERROR Unable to get the pidl size\n");
return FALSE;
}
// get the size of the first chunk
WORD wSize = FetchWord();
// root pidls always have the size field as 14
if ( wSize != sizeof( IDREGITEM ))
{
sprintf( szBuffer, "Pidl Size %d seems bogus for a regitem\n", wSize );
Print( szBuffer );
return FALSE;
}
else
{
if ( !FillBuffer( wSize - sizeof(WORD) , TRUE ))
{
sprintf( szBuffer, "Error: unable to access the data for the pidl of size %d\n", wSize );
Print( szBuffer );
return FALSE;
}
LPBYTE pBuf = GetBuffer(- ((int) sizeof(WORD)));
char szBuffer2[200];
if ( pBuf[2] != SHID_ROOT_REGITEM )
{
Print( "Pidl has incorrect flags, should have SHID_ROOT_REGITEM\n");
}
// now map it to a Root structure
LPIDREGITEM pRegItem = (LPIDREGITEM) pBuf;
GetSHIDFlags( pRegItem->bFlags, szBuffer2, ARRAYSIZE( szBuffer2 ));
Print( "RegItem Pidl:\n");
if ( _fVerbose )
{
sprintf( szBuffer, " bFlags = %d (%s)\n", pRegItem->bFlags, szBuffer2 );
Print( szBuffer );
sprintf( szBuffer, " bOrder = %d\n", pRegItem->bOrder );
Print( szBuffer );
}
CHAR szCLSID[40];
CLSIDToString( szCLSID, ARRAYSIZE( szCLSID ), pRegItem->clsid );
sprintf( szBuffer, " CLSID = %s ", szCLSID );
Print( szBuffer );
if ( GetCLSIDText( szCLSID, szBuffer2 + 1, ARRAYSIZE( szBuffer2 ) -2))
{
szBuffer2[0] = '(';
lstrcatA( szBuffer2, ")\n" );
Print( szBuffer2 );
}
if ( _fVerbose )
Print( "\n" );
ResetBuffer();
if ( pRegItem->clsid == CLSID_ShellNetwork )
{
PrintNetworkPidl();
}
else if ( pRegItem->clsid == CLSID_ShellInetRoot )
{
// internet root
PrintInternetPidl();
}
else if ( pRegItem->clsid == CLSID_ShellDrives )
{
// file system pidls ...
PrintDrivePidl();
}
else
{
// unknown pidl type ....
Print( "unknown pidl type, can't crack any further\n");
}
}
return TRUE;
}
void _SprintDosDateTime(LPSTR szBuffer, LPCSTR pszType, WORD wDate, WORD wTime)
{
sprintf( szBuffer, " date/time %s = 0x%04x/%04x = %04d/%02d/%02d %02d:%02d:%02d\n",
pszType,
wDate, wTime,
((wDate & 0xFE00) >> 9)+1980,
(wDate & 0x01E0) >> 5,
(wDate & 0x001F) >> 0,
(wTime & 0xF800) >> 11,
(wTime & 0x07E0) >> 5,
(wTime & 0x001F) << 1 );
}
BOOL CPidlBreaker::PrintFileSysPidl()
{
CHAR szBuffer[200];
CHAR szBuffer2[200];
if ( !FillBuffer( sizeof( WORD ), FALSE ))
{
Print( "ERROR Unable to get the pidl size\n");
return FALSE;
}
// get the size of the first chunk
WORD wSize = FetchWord();
if ( wSize == 0 )
{
// end of the pidl chain....
return TRUE;
}
if ( !FillBuffer( wSize - sizeof(WORD) , TRUE ))
{
sprintf( szBuffer, "Error: unable to access the data for the pidl of size %d\n", wSize );
Print( szBuffer );
return FALSE;
}
LPBYTE pBuf = GetBuffer(- ((int)sizeof(WORD)));
if (( pBuf[2] & SHID_FS ) != SHID_FS )
{
sprintf( szBuffer, "Error, Unknown Pidl flag, use !db %8X\n", (DWORD_PTR) _pArg - wSize);
Print( szBuffer );
return FALSE;
}
if ((( pBuf[2] & SHID_FS_UNICODE ) == SHID_FS_UNICODE ) && wSize > sizeof( IDFOLDER ) )
{
sprintf( szBuffer, "Error, size to big for a UNICODE FileSys Pidl, use !db %8X\n", (DWORD_PTR) _pArg - wSize);
Print( szBuffer );
return FALSE;
}
if ((( pBuf[2] & SHID_FS_UNICODE) != SHID_FS_UNICODE ) && wSize > sizeof( IDFOLDER ))
{
sprintf( szBuffer, "Error, size to big for a ANSI FileSys Pidl, use !db %8X\n", (DWORD_PTR) _pArg - wSize);
Print( szBuffer );
return FALSE;
}
if ( _fVerbose )
Print("FileSystem pidl:\n");
LPIDFOLDER pItem = (LPIDFOLDER) pBuf;
if ( _fVerbose )
{
GetSHIDFlags( pItem->bFlags, szBuffer2, ARRAYSIZE( szBuffer2));
sprintf( szBuffer, " bFlags = %d (%s)\n", pItem->bFlags, szBuffer2 );
Print( szBuffer );
sprintf( szBuffer, " dwSize = %d,\tattrs = 0x%X\n", pItem->dwSize, pItem->wAttrs );
Print( szBuffer );
_SprintDosDateTime(szBuffer, "modified", pItem->dateModified, pItem->timeModified);
Print( szBuffer );
}
BOOL fPathShown = FALSE;
PIDFOLDEREX pidlx = (PIDFOLDEREX)ILFindHiddenIDOn((LPITEMIDLIST)pBuf, IDLHID_IDFOLDEREX, FALSE);
if (pidlx && pidlx->hid.cb >= sizeof(IDFOLDEREX))
{
LPBYTE pbMax = pBuf + wSize;
if (_fVerbose)
{
_SprintDosDateTime(szBuffer, "created", pidlx->dsCreate.wDate, pidlx->dsCreate.wTime);
Print(szBuffer);
_SprintDosDateTime(szBuffer, "accessed", pidlx->dsAccess.wDate, pidlx->dsAccess.wTime);
Print(szBuffer);
if (pidlx->offResourceA)
{
LPSTR pszResourceA = (LPSTR)pidlx + pidlx->offResourceA;
if ((LPBYTE)pszResourceA < pbMax)
{
Print(" MUI = ");
Print(pszResourceA);
Print("\n");
}
}
}
// Do a "cheap" UnicodeToAnsi because
//
// 1. There's really no point in getting it right, since there
// is no guarantee that the debugger is running the same
// codepage as the app, and...
// 2. The string is unaligned so we have to walk it manually anyway.
//
if (pidlx->offNameW)
{
LPBYTE pbName = (LPBYTE)pidlx + pidlx->offNameW;
int i = 0;
while (pbName < pbMax && *pbName && i < ARRAYSIZE(szBuffer2) - 1)
{
szBuffer2[i++] = *pbName;
pbName += 2;
}
szBuffer2[i] = TEXT('\0');
}
if (_fVerbose)
{
Print(" NameW = ");
Print(szBuffer2);
Print("\n");
}
else
{
fPathShown = TRUE;
if ( !_fSlash )
Print( "\\" );
Print( szBuffer2 );
}
}
if (( pItem->bFlags & SHID_FS_UNICODE ) == SHID_FS_UNICODE )
{
WCHAR szTemp[MAX_PATH];
ualstrcpyW( szTemp, (LPCWSTR)pItem->cFileName );
WideCharToMultiByte( CP_ACP, 0, szTemp, -1, szBuffer2, ARRAYSIZE( szBuffer2 ),0 ,0 );
if ( _fVerbose )
{
sprintf( szBuffer, " cFileName = %s\n", szBuffer2 );
Print( szBuffer );
}
else if (!fPathShown)
{
fPathShown = TRUE;
if ( !_fSlash )
Print( "\\" );
Print( szBuffer2 );
}
}
else
{
// assume to be ansi ...
if ( _fVerbose )
{
sprintf( szBuffer, " cFileName = %s\n", pItem->cFileName);
Print( szBuffer );
}
else if (!fPathShown)
{
fPathShown = TRUE;
if ( !_fSlash )
Print( "\\" );
Print( pItem->cFileName );
}
if ( _fVerbose )
{
int cLen = lstrlenA( pItem->cFileName);
sprintf( szBuffer, " cAltName = %s\n", pItem->cFileName + cLen + 1);
Print( szBuffer );
}
}
if ( pItem->bFlags & SHID_JUNCTION )
{
// it is a junction point, so the CLASSID is tagged on the end
/*[TODO]*/
}
_fSlash = FALSE;
ResetBuffer();
PrintFileSysPidl();
return TRUE;
}
BOOL CPidlBreaker::PrintPidl()
{
if ( _eType == PIDL_UNKNOWN )
{
LPVOID pPrevArg = _pArg;
// check the 3rd byte in, it might be a SHID value...
if ( !FillBuffer(3, FALSE ))
{
Print( "Unable to access the memory\n");
return FALSE;
}
LPBYTE pBuf = GetBuffer();
_eType = CrackType( pBuf[2] );
ResetBuffer();
_pArg = pPrevArg;
}
PrintType( _eType );
return TRUE;
}
BOOL CPidlBreaker::PrintInternetPidl()
{
return TRUE;
}
BOOL CPidlBreaker::PrintNetworkPidl()
{
return TRUE;
}
BOOL CPidlBreaker::PrintDrivePidl()
{
CHAR szBuffer[200];
CHAR szBuffer2[200];
if ( !FillBuffer( sizeof( WORD ), FALSE ))
{
Print( "ERROR Unable to get the pidl size\n");
return FALSE;
}
// get the size of the first chunk
WORD wSize = FetchWord();
if ( wSize == 0 )
{
return TRUE;
}
if ( !FillBuffer( wSize - sizeof(WORD) , TRUE ))
{
sprintf( szBuffer, "Error: unable to access the data for the pidl of size %d\n", wSize );
Print( szBuffer );
return FALSE;
}
LPBYTE pBuf = GetBuffer(- ((int)sizeof(WORD)));
// need to check to see if it is an IDDrive structure or a regitem ....
if ( wSize == sizeof( IDDRIVE ) || wSize == FIELD_OFFSET(IDDRIVE, clsid) )
{
// must be a drive structure....
if ( _fVerbose )
Print( "(My Computer) Drives Pidl:\n");
else
Print( "Path = ");
LPIDDRIVE pDriveItem = (LPIDDRIVE) pBuf;
if ( _fVerbose )
{
GetSHIDFlags( pDriveItem->bFlags, szBuffer2, ARRAYSIZE( szBuffer2 ));
sprintf( szBuffer, " bFlags = %d (%s)\n", pDriveItem->bFlags, szBuffer2 );
Print( szBuffer );
sprintf( szBuffer, " cName = %s\n", pDriveItem->cName );
Print( szBuffer );
sprintf( szBuffer, " qwSize = 0x%lX\tqwFree = 0x%lX\n", pDriveItem->qwSize, pDriveItem->qwFree );
Print( szBuffer );
sprintf( szBuffer, " wSig = 0x%X\n\n", pDriveItem->wSig);
Print( szBuffer );
if ( wSize == sizeof( IDDRIVE ) )
{
CHAR szCLSID[40];
CLSIDToString( szCLSID, ARRAYSIZE( szCLSID ), pDriveItem->clsid );
sprintf( szBuffer, " CLSID = %s ", szCLSID );
Print( szBuffer );
}
}
else
Print( pDriveItem->cName );
// coming from a drive, we already have a slash at the start
_fSlash = TRUE;
// assume the next pidl is a standard file-sys one...
PrintFileSysPidl();
}
else if ( wSize == sizeof( IDREGITEM ))
{
// must be a reg item like control panel or printers...
Print( "Drives (My Computer) RegItem Pidl\n");
if ( pBuf[2] != SHID_COMPUTER_REGITEM )
{
Print( "Pidl has incorrect flags, should have SHID_ROOT_REGITEM\n");
}
// now map it to a Root structure
LPIDREGITEM pRegItem = (LPIDREGITEM) pBuf;
GetSHIDFlags( pRegItem->bFlags, szBuffer2, ARRAYSIZE( szBuffer2 ));
Print( "RegItem Pidl:\n");
if ( _fVerbose )
{
sprintf( szBuffer, " bFlags = %d (%s)\n", pRegItem->bFlags, szBuffer2 );
Print( szBuffer );
sprintf( szBuffer, " bOrder = %d\n", pRegItem->bOrder );
Print( szBuffer );
}
CHAR szCLSID[40];
CLSIDToString( szCLSID, ARRAYSIZE( szCLSID ), pRegItem->clsid );
sprintf( szBuffer, " CLSID = %s ", szCLSID );
Print( szBuffer );
if ( GetCLSIDText( szCLSID, szBuffer2 + 1, ARRAYSIZE( szBuffer2 ) -2))
{
szBuffer2[0] = '(';
lstrcatA( szBuffer2, ")\n" );
Print( szBuffer2 );
}
ResetBuffer();
LPVOID _pPrevArg = _pArg;
if ( !FillBuffer( sizeof( WORD ), FALSE ))
{
Print( "Error unable to access next pidl section\n");
}
if ( FetchWord() != 0 )
{
// unknown hierarchy pidl type
sprintf( szBuffer, "Unknown Pidl Type contents, use !db %8X\n", (DWORD_PTR) _pPrevArg );
}
_pArg = _pPrevArg;
}
else
{
Print( "Unknown Drives pidl type\n");
return FALSE;
}
return TRUE;
}
PIDLTYPE CPidlBreaker::CrackType( BYTE bType )
{
PIDLTYPE eType = PIDL_UNKNOWN;
switch( bType & 0xf0 )
{
case SHID_ROOT:
eType = PIDL_ROOT;
break;
case SHID_COMPUTER:
eType = PIDL_DRIVES;
break;
case SHID_FS:
eType = PIDL_FILESYS;
break;
case SHID_NET:
eType = PIDL_NET;
break;
case 0x60: // SHID_INTERNET
eType = PIDL_INTERNET;
break;
}
return eType;
}
void CPidlBreaker::PrintType( PIDLTYPE eType )
{
switch( eType )
{
case PIDL_ROOT:
PrintRootPidl();
break;
case PIDL_FILESYS:
PrintFileSysPidl();
break;
case PIDL_DRIVES:
PrintDrivePidl();
break;
case PIDL_NET:
case PIDL_INTERNET:
default:
Print( "Unknown Pidl Type\n");
break;
}
}
typedef struct _tagSHIDs
{
BYTE bFlag;
LPCSTR pszText;
} SHIDFLAGS;
SHIDFLAGS g_argSHID[] =
{
{SHID_ROOT, "SHID_ROOT" },
{SHID_ROOT_REGITEM, "SHID_ROOT_REGITEM"},
{SHID_COMPUTER, "SHID_COMPUTER"},
{SHID_COMPUTER_1, "SHID_COMPUTER_1"},
{SHID_COMPUTER_REMOVABLE, "SHID_COMPUTER_REMOVABLE"},
{SHID_COMPUTER_FIXED, "SHID_COMPUTER_FIXED"},
{SHID_COMPUTER_REMOTE, "SHID_COMPUTER_REMOTE"},
{SHID_COMPUTER_CDROM, "SHID_COMPUTER_CDROM"},
{SHID_COMPUTER_RAMDISK, "SHID_COMPUTER_RAMDISK"},
{SHID_COMPUTER_7, "SHID_COMPUTER_7"},
{SHID_COMPUTER_DRIVE525, "SHID_COMPUTER_DRIVE525"},
{SHID_COMPUTER_DRIVE35, "SHID_COMPUTER_DRIVE35"},
{SHID_COMPUTER_NETDRIVE, "SHID_COMPUTER_NETDRIVE"},
{SHID_COMPUTER_NETUNAVAIL, "SHID_COMPUTER_NETUNAVAIL"},
{SHID_COMPUTER_C, "SHID_COMPUTER_C"},
{SHID_COMPUTER_D, "SHID_COMPUTER_D"},
{SHID_COMPUTER_REGITEM, "SHID_COMPUTER_REGITEM"},
{SHID_COMPUTER_MISC, "SHID_COMPUTER_MISC"},
{SHID_FS, "SHID_FS"},
{SHID_FS_TYPEMASK, "SHID_FS_TYPEMASK"},
{SHID_FS_DIRECTORY, "SHID_FS_DIRECTORY"},
{SHID_FS_FILE, "SHID_FS_FILE"},
{SHID_FS_UNICODE, "SHID_FS_UNICODE"},
{SHID_FS_DIRUNICODE, "SHID_FS_DIRUNICODE"},
{SHID_FS_FILEUNICODE, "SHID_FS_FILEUNICODE"},
{SHID_NET, "SHID_NET"},
{SHID_NET_DOMAIN, "SHID_NET_DOMAIN"},
{SHID_NET_SERVER, "SHID_NET_SERVER"},
{SHID_NET_SHARE, "SHID_NET_SHARE"},
{SHID_NET_FILE, "SHID_NET_FILE"},
{SHID_NET_GROUP, "SHID_NET_GROUP"},
{SHID_NET_NETWORK, "SHID_NET_NETWORK"},
{SHID_NET_RESTOFNET, "SHID_NET_RESTOFNET"},
{SHID_NET_SHAREADMIN, "SHID_NET_SHAREADMIN"},
{SHID_NET_DIRECTORY, "SHID_NET_DIRECTORY"},
{SHID_NET_TREE, "SHID_NET_TREE"},
{SHID_NET_REGITEM, "SHID_NET_REGITEM"},
{SHID_NET_PRINTER, "SHID_NET_PRINTER"}
};
BOOL CPidlBreaker::GetSHIDFlags( BYTE bFlags, CHAR * pszBuffer, DWORD cbSize )
{
LPCSTR pszText = NULL;
for ( int iFlag = 0; iFlag < ARRAYSIZE( g_argSHID ); iFlag ++ )
{
if ( g_argSHID[iFlag].bFlag == ( bFlags & SHID_TYPEMASK ))
{
pszText = g_argSHID[iFlag].pszText;
break;
}
}
if ( pszText == NULL )
{
sprintf( pszBuffer, "unknown SHID value %2X", bFlags );
return FALSE;
}
else
{
lstrcpyA( pszBuffer, pszText );
}
if (bFlags & SHID_JUNCTION)
{
lstrcatA(pszBuffer, " | SHID_JUNCTION");
}
return TRUE;
}
void CPidlBreaker::CLSIDToString( CHAR * pszBuffer, DWORD cbSize, REFCLSID rclsid )
{
WCHAR szBuffer[40];
StringFromGUID2( rclsid, szBuffer, ARRAYSIZE( szBuffer ));
WideCharToMultiByte( CP_ACP, 0, szBuffer, -1, pszBuffer, cbSize, 0, 0 );
}
//
// Some CLSIDs have "known" names which are used if there is no custom name
// in the registry.
//
typedef struct KNOWNCLSIDS
{
LPCSTR pszCLSID;
LPCSTR pszName;
} KNOWNCLSIDS;
const KNOWNCLSIDS c_kcKnown[] = {
{ "{20D04FE0-3AEA-1069-A2D8-08002B30309D}", "My Computer" },
{ "{21EC2020-3AEA-1069-A2DD-08002B30309D}", "Control Panel" },
{ "{645FF040-5081-101B-9F08-00AA002F954E}", "Recycle Bin" },
{ "{450D8FBA-AD25-11D0-98A8-0800361B1103}", "My Documents" },
{ "{871C5380-42A0-1069-A2EA-08002B30309D}", "The Internet" },
};
BOOL CPidlBreaker::GetCLSIDText( const CHAR * pszCLSID, CHAR * pszBuffer, DWORD cbSize )
{
int i;
for (i = 0; i < ARRAYSIZE(c_kcKnown); i++)
{
if (lstrcmpiA(c_kcKnown[i].pszCLSID, pszCLSID) == 0)
{
lstrcpynA(pszBuffer, c_kcKnown[i].pszName, cbSize);
return TRUE;
}
}
HKEY hKey;
LONG lRes = RegOpenKeyA( HKEY_CLASSES_ROOT, "CLSID", &hKey );
if ( ERROR_SUCCESS == lRes )
{
LONG lSize = cbSize;
lRes = RegQueryValueA( hKey, pszCLSID, pszBuffer, &lSize );
return ( ERROR_SUCCESS == lRes );
}
return FALSE;
}