Каков наилучший способ разыменования ссылки на оболочку Windows (ярлык) в коде C ++?
Я использовал функцию DeReferenceShellLink (), написанную Бретом Пёрсоном для Windows Developer Journal, но этот код, вероятно,10-20 лет сейчас. Я хотел бы заменить его новейшими технологиями, так как этот код становится проблематичным для поддержки
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// DerefLnk.cpp
// Bret S. Pehrson for Windows Developer's Journal
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//DeReferenceShellLink
// Parameters:
// lpszLinkName - link name to dereference
// lpszDest - destination to store dereferenced name
// cchDest - size of destination buffer, in characters
// Return:
// Number of characters ( including NULL ) for complete
// dereferenced name
// Notes:
// lpszLinkName and lpszDest can point to the same buffer.
// If NULL is specified for lpszDest, the dereferenced name
// is not copied to the destination, but the return value is
// still computed.
//
// Requires link library : ole32.dll
//
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
UINT DeReferenceShellLink(
LPCTSTR lpszLinkName,
LPTSTR lpszDest,
UINT cchDest )
{
// STACK variables
const LPCTSTR lpszExt = _tcsrchr( lpszLinkName, '.' );
WIN32_FIND_DATA fd;
IPersistFile * pPersistFile = NULL;
IShellLink * pShellLink = NULL;
LPCOLESTR lpOleStrLinkName;
HRESULT hResult;
TCHAR szPath[_MAX_PATH+1];
UINT cchDeref = 0;
#ifndef UNICODE
UINT cbAlloc;
#endif //!UNICODE
// Initialization
fd.cFileName[0] = NULL;
szPath[0] = NULL;
// Dereference as necessary
if ( ( lpszExt!=NULL ) && ( lstrcmpi( lpszExt, TEXT( ".lnk" ) )==0 ) )
{
// Initialize COM
hResult = CoInitialize( NULL );
if ( SUCCEEDED( hResult ) )
{
// Create an instance of shell link interface
hResult = CoCreateInstance(
CLSID_ShellLink,
NULL,
CLSCTX_INPROC_SERVER,
IID_IShellLink,
( LPVOID * )&pShellLink );
if ( SUCCEEDED( hResult ) )
{
// Get the persist file interface
hResult = pShellLink->QueryInterface(
IID_IPersistFile,
( LPVOID * )&pPersistFile );
if ( SUCCEEDED( hResult ) )
{
// Convert the link name to unicode as necessary
#ifdef UNICODE
lpOleStrLinkName = lpszLinkName;
#else //!UNICODE
int cchString = lstrlen( lpszLinkName ) + 1;
cbAlloc = cchString * sizeof( OLECHAR );
lpOleStrLinkName = ( LPOLESTR )_alloca( cbAlloc );
MultiByteToWideChar(
CP_ACP,
MB_PRECOMPOSED,
lpszLinkName,
cchString,
( LPOLESTR )lpOleStrLinkName,
cchString );
#endif //!UNICODE
// Load the persist file with the link
hResult = pPersistFile->Load(
lpOleStrLinkName,
0 );
if ( SUCCEEDED( hResult ) )
{
// Resolve the link
hResult = pShellLink->Resolve(
NULL,
SLR_NO_UI );
if ( SUCCEEDED( hResult ) )
{
// Get the path from the link
hResult = pShellLink->GetPath(
szPath,
sizeof( szPath )/sizeof( szPath[0] ),
&fd,
0 );
if ( hResult == S_OK )
{
// Copy to destination
cchDeref = lstrlen( szPath ) + 1;
if ( lpszDest != NULL )
{
lstrcpyn(
lpszDest,
szPath,
cchDest );
}
}
}
}
pPersistFile->Release();
//pPersistFile = NULL; CppCheck flags this as unused assignment
}
pShellLink->Release();
// pShellLink = NULL; CppCheck flags this as unused assignment
}
CoUninitialize();
}
}
else
{
// Not a shell link, simply copy source to destination
if ( ( lpszLinkName!=lpszDest ) && ( lpszDest!= NULL ) )
{
lstrcpyn( lpszDest, lpszLinkName, cchDest );
}
cchDeref = lstrlen( lpszLinkName ) + 1;
}
// Done
return cchDeref;
}