Leaked source code of windows server 2003
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.
 
 
 
 
 
 

336 lines
9.6 KiB

//---------------------------------------------------------------------------
//
// link.c link management routines (reading, etc.)
//
// Copyright (c) 1985 - 1999, Microsoft Corporation
//
//---------------------------------------------------------------------------
#include "precomp.h"
#pragma hdrstop
DWORD
GetTitleFromLinkName(
IN LPWSTR szLinkName,
OUT LPWSTR szTitle
)
/*++
Routine Description:
This routine returns the title (i.e., display name of the link) in szTitle,
and the number of bytes (not chars) in szTitle.
Arguments:
szLinkName - fully qualified path to link file
szTitle - pointer to buffer to contain title (display name) of the link
i.e.:
"C:\nt\desktop\A Link File Name.lnk" --> "A Link File Name"
Return Value:
number of bytes copied to szTitle
--*/
{
DWORD dwLen;
LPWSTR pLnk, pDot;
LPWSTR pPath = szLinkName;
ASSERT(szLinkName);
// find filename at end of fully qualified link name and point pLnk to it
for (pLnk = pPath; *pPath; pPath++)
{
if ( (pPath[0] == L'\\' || pPath[0] == L':') &&
pPath[1] &&
(pPath[1] != L'\\')
)
pLnk = pPath + 1;
}
// find extension (.lnk)
pPath = pLnk;
for (pDot = NULL; *pPath; pPath++)
{
switch (*pPath) {
case L'.':
pDot = pPath; // remember the last dot
break;
case L'\\':
case L' ': // extensions can't have spaces
pDot = NULL; // forget last dot, it was in a directory
break;
}
}
// if we found the extension, pDot points to it, if not, pDot
// is NULL.
if (pDot)
{
dwLen = (ULONG)((pDot - pLnk) * sizeof(WCHAR));
}
else
{
dwLen = lstrlenW(pLnk) * sizeof(WCHAR);
}
dwLen = min(dwLen, MAX_TITLE_LENGTH);
RtlCopyMemory(szTitle, pLnk, dwLen);
return dwLen;
}
BOOL ReadString( HANDLE hFile, LPVOID * lpVoid, BOOL bUnicode )
{
USHORT cch;
DWORD dwBytesRead;
BOOL fResult = TRUE;
if (bUnicode)
{
LPWSTR lpWStr;
fResult &= ReadFile( hFile, (LPVOID)&cch, sizeof(cch), &dwBytesRead, NULL );
lpWStr = ConsoleHeapAlloc(HEAP_ZERO_MEMORY, (cch + 1) * sizeof(WCHAR));
if (lpWStr) {
fResult &= ReadFile( hFile, (LPVOID)lpWStr, cch*sizeof(WCHAR), &dwBytesRead, NULL );
lpWStr[cch] = L'\0';
}
*(LPWSTR *)lpVoid = lpWStr;
} else {
LPSTR lpStr;
fResult &= ReadFile( hFile, (LPVOID)&cch, sizeof(cch), &dwBytesRead, NULL );
lpStr = ConsoleHeapAlloc(HEAP_ZERO_MEMORY, cch + 1);
if (lpStr) {
fResult &= ReadFile( hFile, (LPVOID)lpStr, cch, &dwBytesRead, NULL );
lpStr[cch] = '\0';
}
*(LPSTR *)lpVoid = lpStr;
}
return fResult;
}
BOOL LoadLink( LPWSTR pszLinkName, CShellLink * this )
{
HANDLE hFile;
DWORD dwBytesRead, cbSize, cbTotal, cbToRead;
BOOL fResult = TRUE;
LPSTR pTemp = NULL;
// Try to open the file
hFile = CreateFile(pszLinkName,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hFile == INVALID_HANDLE_VALUE) {
return FALSE;
}
// Now, read out data...
fResult = ReadFile( hFile, (LPVOID)&this->sld, sizeof(this->sld), &dwBytesRead, NULL );
fResult &= ((dwBytesRead == sizeof(this->sld)) && (this->sld.cbSize == sizeof(this->sld)));
if (!fResult) {
// This is a bad .lnk file. Bail.
goto ErrorExit;
}
// read all of the members
if (this->sld.dwFlags & SLDF_HAS_ID_LIST)
{
// Read the size of the IDLIST
cbSize = 0; // need to zero out to get HIWORD 0 'cause USHORT is only 2 bytes
fResult &= ReadFile( hFile, (LPVOID)&cbSize, sizeof(USHORT), &dwBytesRead, NULL );
fResult &= (dwBytesRead == sizeof(USHORT));
if (cbSize)
{
fResult &=
(SetFilePointer(hFile,cbSize,NULL,FILE_CURRENT)!=0xFFFFFFFF);
}
else
{
goto ErrorExit;
}
}
if (this->sld.dwFlags & (SLDF_HAS_LINK_INFO))
{
fResult &= ReadFile( hFile, (LPVOID)&cbSize, sizeof(cbSize), &dwBytesRead, NULL );
fResult &= (dwBytesRead == sizeof(cbSize));
if (cbSize >= sizeof(cbSize))
{
cbSize -= sizeof(cbSize);
fResult &=
(SetFilePointer(hFile,cbSize,NULL,FILE_CURRENT)!=0xFFFFFFFF);
}
}
if (this->sld.dwFlags & SLDF_HAS_NAME)
fResult &= ReadString( hFile, &this->pszName, this->sld.dwFlags & SLDF_UNICODE);
if (this->sld.dwFlags & SLDF_HAS_RELPATH)
fResult &= ReadString( hFile, &this->pszRelPath, this->sld.dwFlags & SLDF_UNICODE);
if (this->sld.dwFlags & SLDF_HAS_WORKINGDIR)
fResult &= ReadString( hFile, &this->pszWorkingDir, this->sld.dwFlags & SLDF_UNICODE);
if (this->sld.dwFlags & SLDF_HAS_ARGS)
fResult &= ReadString( hFile, &this->pszArgs, this->sld.dwFlags & SLDF_UNICODE);
if (this->sld.dwFlags & SLDF_HAS_ICONLOCATION)
fResult &= ReadString( hFile, &this->pszIconLocation, this->sld.dwFlags & SLDF_UNICODE);
// Read in extra data sections
this->pExtraData = NULL;
cbTotal = 0;
while (TRUE)
{
LPSTR pReadData = NULL;
cbSize = 0;
fResult &= ReadFile( hFile, (LPVOID)&cbSize, sizeof(cbSize), &dwBytesRead, NULL );
if (cbSize < sizeof(cbSize))
break;
if (pTemp)
{
pTemp = (void *)ConsoleHeapReAlloc(
HEAP_ZERO_MEMORY,
this->pExtraData,
cbTotal + cbSize + sizeof(DWORD)
);
if (pTemp)
{
this->pExtraData = pTemp;
}
}
else
{
this->pExtraData = pTemp = ConsoleHeapAlloc( HEAP_ZERO_MEMORY, cbTotal + cbSize + sizeof(DWORD) );
}
if (!pTemp)
break;
cbToRead = cbSize - sizeof(cbSize);
pReadData = pTemp + cbTotal;
fResult &= ReadFile( hFile, (LPVOID)(pReadData + sizeof(cbSize)), cbToRead, &dwBytesRead, NULL );
if (dwBytesRead == cbToRead) {
// got all of the extra data, comit it
*((UNALIGNED DWORD *)pReadData) = cbSize;
cbTotal += cbSize;
} else {
break;
}
}
ErrorExit:
CloseHandle( hFile );
return fResult;
}
DWORD GetLinkProperties( LPWSTR pszLinkName, LPVOID lpvBuffer, UINT cb )
{
CShellLink mld;
DWORD fResult;
LPNT_CONSOLE_PROPS lpExtraData;
DWORD dwSize = 0;
// Zero out structure on the stack
RtlZeroMemory( &mld, sizeof(mld) );
// Load link data
if (!LoadLink( pszLinkName, &mld )) {
RIPMSG1(RIP_WARNING, "LoadLink %ws failed", pszLinkName);
fResult = LINK_NOINFO;
goto Cleanup;
}
// Check return buffer -- is it big enough?
ASSERT(cb >= sizeof( LNKPROPNTCONSOLE));
// Zero out callers buffer
RtlZeroMemory( lpvBuffer, cb );
// Copy relevant shell link data into caller's buffer
if (mld.pszName)
lstrcpy( ((LPLNKPROPNTCONSOLE)lpvBuffer)->pszName, mld.pszName );
if (mld.pszIconLocation)
lstrcpy( ((LPLNKPROPNTCONSOLE)lpvBuffer)->pszIconLocation, mld.pszIconLocation );
((LPLNKPROPNTCONSOLE)lpvBuffer)->uIcon = mld.sld.iIcon;
((LPLNKPROPNTCONSOLE)lpvBuffer)->uShowCmd = mld.sld.iShowCmd;
((LPLNKPROPNTCONSOLE)lpvBuffer)->uHotKey = mld.sld.wHotkey;
fResult = LINK_SIMPLEINFO;
// Find console properties in extra data section
for( lpExtraData = (LPNT_CONSOLE_PROPS)mld.pExtraData;
lpExtraData && lpExtraData->cbSize;
(LPBYTE)lpExtraData += dwSize
)
{
dwSize = lpExtraData->cbSize;
if (dwSize)
{
if (lpExtraData->dwSignature == NT_CONSOLE_PROPS_SIG)
{
RtlCopyMemory( &((LPLNKPROPNTCONSOLE)lpvBuffer)->console_props,
lpExtraData,
sizeof( NT_CONSOLE_PROPS )
);
fResult = LINK_FULLINFO;
#if !defined(FE_SB)
break;
#endif
}
#if defined(FE_SB)
if (lpExtraData->dwSignature == NT_FE_CONSOLE_PROPS_SIG)
{
LPNT_FE_CONSOLE_PROPS lpFEExtraData = (LPNT_FE_CONSOLE_PROPS)lpExtraData;
RtlCopyMemory( &((LPLNKPROPNTCONSOLE)lpvBuffer)->fe_console_props,
lpFEExtraData,
sizeof( NT_FE_CONSOLE_PROPS )
);
}
#endif
}
}
Cleanup:
if (mld.pszName)
ConsoleHeapFree( mld.pszName );
if (mld.pszRelPath)
ConsoleHeapFree( mld.pszRelPath );
if (mld.pszWorkingDir)
ConsoleHeapFree( mld.pszWorkingDir );
if (mld.pszArgs)
ConsoleHeapFree( mld.pszArgs );
if (mld.pszIconLocation)
ConsoleHeapFree( mld.pszIconLocation );
if (mld.pExtraData)
ConsoleHeapFree( mld.pExtraData );
return fResult;
}