📄 shelllink.c
字号:
}
}
return r;
}
static HRESULT WINAPI IPersistFile_fnSaveCompleted(IPersistFile* iface, LPCOLESTR pszFileName)
{
IShellLinkImpl *This = impl_from_IPersistFile(iface);
FIXME("(%p)->(%s)\n",This,debugstr_w(pszFileName));
return NOERROR;
}
static HRESULT WINAPI IPersistFile_fnGetCurFile(IPersistFile* iface, LPOLESTR *ppszFileName)
{
IShellLinkImpl *This = impl_from_IPersistFile(iface);
FIXME("(%p)\n",This);
return NOERROR;
}
static const IPersistFileVtbl pfvt =
{
IPersistFile_fnQueryInterface,
IPersistFile_fnAddRef,
IPersistFile_fnRelease,
IPersistFile_fnGetClassID,
IPersistFile_fnIsDirty,
IPersistFile_fnLoad,
IPersistFile_fnSave,
IPersistFile_fnSaveCompleted,
IPersistFile_fnGetCurFile
};
/************************************************************************
* IPersistStream_QueryInterface
*/
static HRESULT WINAPI IPersistStream_fnQueryInterface(
IPersistStream* iface,
REFIID riid,
VOID** ppvObj)
{
IShellLinkImpl *This = impl_from_IPersistStream(iface);
return ShellLink_QueryInterface( This, riid, ppvObj );
}
/************************************************************************
* IPersistStream_Release
*/
static ULONG WINAPI IPersistStream_fnRelease(
IPersistStream* iface)
{
IShellLinkImpl *This = impl_from_IPersistStream(iface);
return IShellLinkA_Release((IShellLinkA*)This);
}
/************************************************************************
* IPersistStream_AddRef
*/
static ULONG WINAPI IPersistStream_fnAddRef(
IPersistStream* iface)
{
IShellLinkImpl *This = impl_from_IPersistStream(iface);
return ShellLink_AddRef( This );
}
/************************************************************************
* IPersistStream_GetClassID
*
*/
static HRESULT WINAPI IPersistStream_fnGetClassID(
IPersistStream* iface,
CLSID* pClassID)
{
IShellLinkImpl *This = impl_from_IPersistStream(iface);
return ShellLink_GetClassID( This, pClassID );
}
/************************************************************************
* IPersistStream_IsDirty (IPersistStream)
*/
static HRESULT WINAPI IPersistStream_fnIsDirty(
IPersistStream* iface)
{
IShellLinkImpl *This = impl_from_IPersistStream(iface);
TRACE("(%p)\n", This);
return S_OK;
}
static HRESULT Stream_LoadString( IStream* stm, BOOL unicode, LPWSTR *pstr )
{
DWORD count;
USHORT len;
LPVOID temp;
LPWSTR str;
HRESULT r;
TRACE("%p\n", stm);
count = 0;
r = IStream_Read(stm, &len, sizeof(len), &count);
if ( FAILED (r) || ( count != sizeof(len) ) )
return E_FAIL;
if( unicode )
len *= sizeof (WCHAR);
TRACE("reading %d\n", len);
temp = HeapAlloc(GetProcessHeap(), 0, len+sizeof(WCHAR));
if( !temp )
return E_OUTOFMEMORY;
count = 0;
r = IStream_Read(stm, temp, len, &count);
if( FAILED (r) || ( count != len ) )
{
HeapFree( GetProcessHeap(), 0, temp );
return E_FAIL;
}
TRACE("read %s\n", debugstr_an(temp,len));
/* convert to unicode if necessary */
if( !unicode )
{
count = MultiByteToWideChar( CP_ACP, 0, (LPSTR) temp, len, NULL, 0 );
str = HeapAlloc( GetProcessHeap(), 0, (count+1)*sizeof (WCHAR) );
if( str )
MultiByteToWideChar( CP_ACP, 0, (LPSTR) temp, len, str, count );
HeapFree( GetProcessHeap(), 0, temp );
}
else
{
count /= 2;
str = (LPWSTR) temp;
}
str[count] = 0;
*pstr = str;
return S_OK;
}
static HRESULT Stream_ReadChunk( IStream* stm, LPVOID *data )
{
DWORD size;
ULONG count;
HRESULT r;
struct sized_chunk {
DWORD size;
unsigned char data[1];
} *chunk;
TRACE("%p\n",stm);
r = IStream_Read( stm, &size, sizeof(size), &count );
if( FAILED( r ) || count != sizeof(size) )
return E_FAIL;
chunk = HeapAlloc( GetProcessHeap(), 0, size );
if( !chunk )
return E_OUTOFMEMORY;
chunk->size = size;
r = IStream_Read( stm, chunk->data, size - sizeof(size), &count );
if( FAILED( r ) || count != (size - sizeof(size)) )
{
HeapFree( GetProcessHeap(), 0, chunk );
return E_FAIL;
}
TRACE("Read %ld bytes\n",chunk->size);
*data = (LPVOID) chunk;
return S_OK;
}
static BOOL Stream_LoadVolume( LOCAL_VOLUME_INFO *vol, volume_info *volume )
{
const int label_sz = sizeof volume->label/sizeof volume->label[0];
LPSTR label;
int len;
volume->serial = vol->dwVolSerial;
volume->type = vol->dwType;
if( !vol->dwVolLabelOfs )
return FALSE;
if( vol->dwSize <= vol->dwVolLabelOfs )
return FALSE;
len = vol->dwSize - vol->dwVolLabelOfs;
label = (LPSTR) vol;
label += vol->dwVolLabelOfs;
MultiByteToWideChar( CP_ACP, 0, label, len, volume->label, label_sz-1);
return TRUE;
}
static LPWSTR Stream_LoadPath( LPSTR p, DWORD maxlen )
{
int len = 0, wlen;
LPWSTR path;
while( p[len] && (len < maxlen) )
len++;
wlen = MultiByteToWideChar(CP_ACP, 0, p, len, NULL, 0);
path = HeapAlloc(GetProcessHeap(), 0, (wlen+1)*sizeof(WCHAR));
MultiByteToWideChar(CP_ACP, 0, p, len, path, wlen);
path[wlen] = 0;
return path;
}
static HRESULT Stream_LoadLocation( IStream *stm,
volume_info *volume, LPWSTR *path )
{
char *p = NULL;
LOCATION_INFO *loc;
HRESULT r;
int n;
r = Stream_ReadChunk( stm, (LPVOID*) &p );
if( FAILED(r) )
return r;
loc = (LOCATION_INFO*) p;
if (loc->dwTotalSize < sizeof(LOCATION_INFO) - sizeof(DWORD))
{
HeapFree( GetProcessHeap(), 0, p );
return E_FAIL;
}
/* if there's valid local volume information, load it */
if( loc->dwVolTableOfs &&
((loc->dwVolTableOfs + sizeof(LOCAL_VOLUME_INFO)) <= loc->dwTotalSize) )
{
LOCAL_VOLUME_INFO *volume_info;
volume_info = (LOCAL_VOLUME_INFO*) &p[loc->dwVolTableOfs];
Stream_LoadVolume( volume_info, volume );
}
/* if there's a local path, load it */
n = loc->dwLocalPathOfs;
if( n && (n < loc->dwTotalSize) )
*path = Stream_LoadPath( &p[n], loc->dwTotalSize - n );
TRACE("type %ld serial %08lx name %s path %s\n", volume->type,
volume->serial, debugstr_w(volume->label), debugstr_w(*path));
HeapFree( GetProcessHeap(), 0, p );
return S_OK;
}
/*
* The format of the advertised shortcut info seems to be:
*
* Offset Description
* ------ -----------
*
* 0 Length of the block (4 bytes, usually 0x314)
* 4 tag (dword)
* 8 string data in ASCII
* 8+0x104 string data in UNICODE
*
* In the original Win32 implementation the buffers are not initialized
* to zero, so data trailing the string is random garbage.
*/
static HRESULT Stream_LoadAdvertiseInfo( IStream* stm, LPWSTR *str )
{
DWORD size;
ULONG count;
HRESULT r;
EXP_DARWIN_LINK buffer;
TRACE("%p\n",stm);
r = IStream_Read( stm, &buffer.dbh.cbSize, sizeof (DWORD), &count );
if( FAILED( r ) )
return r;
/* make sure that we read the size of the structure even on error */
size = sizeof buffer - sizeof (DWORD);
if( buffer.dbh.cbSize != sizeof buffer )
{
ERR("Ooops. This structure is not as expected...\n");
return E_FAIL;
}
r = IStream_Read( stm, &buffer.dbh.dwSignature, size, &count );
if( FAILED( r ) )
return r;
if( count != size )
return E_FAIL;
TRACE("magic %08lx string = %s\n", buffer.dbh.dwSignature, debugstr_w(buffer.szwDarwinID));
if( (buffer.dbh.dwSignature&0xffff0000) != 0xa0000000 )
{
ERR("Unknown magic number %08lx in advertised shortcut\n", buffer.dbh.dwSignature);
return E_FAIL;
}
*str = HeapAlloc( GetProcessHeap(), 0,
(lstrlenW(buffer.szwDarwinID)+1) * sizeof(WCHAR) );
lstrcpyW( *str, buffer.szwDarwinID );
return S_OK;
}
/************************************************************************
* IPersistStream_Load (IPersistStream)
*/
static HRESULT WINAPI IPersistStream_fnLoad(
IPersistStream* iface,
IStream* stm)
{
LINK_HEADER hdr;
ULONG dwBytesRead;
BOOL unicode;
HRESULT r;
DWORD zero;
IShellLinkImpl *This = impl_from_IPersistStream(iface);
TRACE("%p %p\n", This, stm);
if( !stm )
return STG_E_INVALIDPOINTER;
dwBytesRead = 0;
r = IStream_Read(stm, &hdr, sizeof(hdr), &dwBytesRead);
if( FAILED( r ) )
return r;
if( dwBytesRead != sizeof(hdr))
return E_FAIL;
if( hdr.dwSize != sizeof(hdr))
return E_FAIL;
if( !IsEqualIID(&hdr.MagicGuid, &CLSID_ShellLink) )
return E_FAIL;
/* free all the old stuff */
ILFree(This->pPidl);
This->pPidl = NULL;
memset( &This->volume, 0, sizeof This->volume );
HeapFree(GetProcessHeap(), 0, This->sPath);
This->sPath = NULL;
HeapFree(GetProcessHeap(), 0, This->sDescription);
This->sDescription = NULL;
HeapFree(GetProcessHeap(), 0, This->sPathRel);
This->sPathRel = NULL;
HeapFree(GetProcessHeap(), 0, This->sWorkDir);
This->sWorkDir = NULL;
HeapFree(GetProcessHeap(), 0, This->sArgs);
This->sArgs = NULL;
HeapFree(GetProcessHeap(), 0, This->sIcoPath);
This->sIcoPath = NULL;
HeapFree(GetProcessHeap(), 0, This->sProduct);
This->sProduct = NULL;
HeapFree(GetProcessHeap(), 0, This->sComponent);
This->sComponent = NULL;
This->wHotKey = (WORD)hdr.wHotKey;
This->iIcoNdx = hdr.nIcon;
FileTimeToSystemTime (&hdr.Time1, &This->time1);
FileTimeToSystemTime (&hdr.Time2, &This->time2);
FileTimeToSystemTime (&hdr.Time3, &This->time3);
if (TRACE_ON(shell))
{
WCHAR sTemp[MAX_PATH];
GetDateFormatW(LOCALE_USER_DEFAULT,DATE_SHORTDATE, &This->time1,
NULL, sTemp, sizeof(sTemp)/sizeof(*sTemp));
TRACE("-- time1: %s\n", debugstr_w(sTemp) );
GetDateFormatW(LOCALE_USER_DEFAULT,DATE_SHORTDATE, &This->time2,
NULL, sTemp, sizeof(sTemp)/sizeof(*sTemp));
TRACE("-- time2: %s\n", debugstr_w(sTemp) );
GetDateFormatW(LOCALE_USER_DEFAULT,DATE_SHORTDATE, &This->time3,
NULL, sTemp, sizeof(sTemp)/sizeof(*sTemp));
TRACE("-- time3: %s\n", debugstr_w(sTemp) );
}
/* load all the new stuff */
if( hdr.dwFlags & SLDF_HAS_ID_LIST )
{
r = ILLoadFromStream( stm, &This->pPidl );
if( FAILED( r ) )
return r;
}
pdump(This->pPidl);
/* load the location information */
if( hdr.dwFlags & SLDF_HAS_LINK_INFO )
r = Stream_LoadLocation( stm, &This->volume, &This->sPath );
if( FAILED( r ) )
goto end;
unicode = hdr.dwFlags & SLDF_UNICODE;
if( hdr.dwFlags & SLDF_HAS_NAME )
{
r = Stream_LoadString( stm, unicode, &This->sDescription );
TRACE("Description -> %s\n",debugstr_w(This->sDescription));
}
if( FAILED( r ) )
goto end;
if( hdr.dwFlags & SLDF_HAS_RELPATH )
{
r = Stream_LoadString( stm, unicode, &This->sPathRel );
TRACE("Relative Path-> %s\n",debugstr_w(This->sPathRel));
}
if( FAILED( r ) )
goto end;
if( hdr.dwFlags & SLDF_HAS_WORKINGDIR )
{
r = Stream_LoadString( stm, unicode, &This->sWorkDir );
TRACE("Working Dir -> %s\n",debugstr_w(This->sWorkDir));
}
if( FAILED( r ) )
goto end;
if( hdr.dwFlags & SLDF_HAS_ARGS )
{
r = Stream_LoadString( stm, unicode, &This->sArgs );
TRACE("Working Dir -> %s\n",debugstr_w(This->sArgs));
}
if( FAILED( r ) )
goto end;
if( hdr.dwFlags & SLDF_HAS_ICONLOCATION )
{
r = Stream_LoadString( stm, unicode, &This->sIcoPath );
TRACE("Icon file -> %s\n",debugstr_w(This->sIcoPath));
}
if( FAILED( r ) )
goto end;
if( hdr.dwFlags & SLDF_HAS_LOGO3ID )
{
r = Stream_LoadAdvertiseInfo( stm, &This->sProduct );
TRACE("Product -> %s\n",debugstr_w(This->sProduct));
}
if( FAILED( r ) )
goto end;
if( hdr.dwFlags & SLDF_HAS_DARWINID )
{
r = Stream_LoadAdvertiseInfo( stm, &This->sComponent );
TRACE("Component -> %s\n",debugstr_w(This->sComponent));
}
if( FAILED( r ) )
goto end;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -