mirror of https://github.com/lianthony/NT4.0
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.
895 lines
25 KiB
895 lines
25 KiB
//---------------------------------------------------------------------------
|
|
//
|
|
// link.c link management routines (reading, etc.)
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
#define LPITEMIDLIST DWORD
|
|
#define IShellExtInit DWORD
|
|
#define IShellLink DWORD
|
|
#define IPersistStream DWORD
|
|
#define IPersistFile DWORD
|
|
#define IContextMenu DWORD
|
|
#define IContextMenu2 DWORD
|
|
#define IShellLinkA DWORD
|
|
#define IDataObject DWORD
|
|
#define IDropTarget DWORD
|
|
#define PLINKINFO LPVOID
|
|
#ifndef CLSID
|
|
typedef struct _CLSID {
|
|
unsigned long Data1;
|
|
unsigned short Data2;
|
|
unsigned short Data3;
|
|
unsigned char Data4[8];
|
|
} CLSID;
|
|
#endif
|
|
#include "..\..\..\..\windows\shell\shelldll\shlink.h"
|
|
|
|
|
|
NTSTATUS
|
|
MyRegOpenKey(
|
|
IN HANDLE hKey,
|
|
IN LPWSTR lpSubKey,
|
|
OUT PHANDLE phResult
|
|
);
|
|
|
|
NTSTATUS
|
|
MyRegQueryValue(
|
|
IN HANDLE hKey,
|
|
IN LPWSTR lpValueName,
|
|
IN DWORD dwValueLength,
|
|
OUT LPBYTE lpData
|
|
);
|
|
|
|
|
|
LPWSTR
|
|
TranslateConsoleTitle(
|
|
LPWSTR ConsoleTitle
|
|
);
|
|
|
|
|
|
void
|
|
LinkInitRegistryValues( LPLNKPROPNTCONSOLE lpCon )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine allocates a state info structure and fill it in with
|
|
default values.
|
|
|
|
Arguments:
|
|
|
|
none
|
|
|
|
Return Value:
|
|
|
|
pStateInfo - pointer to structure to receive information
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
lpCon->wFillAttribute = 0x07; // white on black
|
|
lpCon->wPopupFillAttribute = 0xf5; // purple on white
|
|
lpCon->bInsertMode = FALSE;
|
|
lpCon->bQuickEdit = FALSE;
|
|
lpCon->bFullScreen = FALSE;
|
|
lpCon->dwScreenBufferSize.X = 80;
|
|
lpCon->dwScreenBufferSize.Y = 25;
|
|
lpCon->dwWindowSize.X = 80;
|
|
lpCon->dwWindowSize.Y = 25;
|
|
lpCon->dwWindowOrigin.X = 0;
|
|
lpCon->dwWindowOrigin.Y = 0;
|
|
lpCon->bAutoPosition = TRUE;
|
|
lpCon->dwFontSize.X = 0;
|
|
lpCon->dwFontSize.Y = 0;
|
|
lpCon->uFontFamily = 0;
|
|
lpCon->uFontWeight = 0;
|
|
FillMemory( lpCon->FaceName, sizeof(lpCon->FaceName), 0 );
|
|
lpCon->uCursorSize = 25;
|
|
lpCon->uHistoryBufferSize = 25;
|
|
lpCon->uNumberOfHistoryBuffers = 4;
|
|
lpCon->bHistoryNoDup = 0;
|
|
lpCon->ColorTable[ 0] = RGB(0, 0, 0 );
|
|
lpCon->ColorTable[ 1] = RGB(0, 0, 0x80);
|
|
lpCon->ColorTable[ 2] = RGB(0, 0x80,0 );
|
|
lpCon->ColorTable[ 3] = RGB(0, 0x80,0x80);
|
|
lpCon->ColorTable[ 4] = RGB(0x80,0, 0 );
|
|
lpCon->ColorTable[ 5] = RGB(0x80,0, 0x80);
|
|
lpCon->ColorTable[ 6] = RGB(0x80,0x80,0 );
|
|
lpCon->ColorTable[ 7] = RGB(0xC0,0xC0,0xC0);
|
|
lpCon->ColorTable[ 8] = RGB(0x80,0x80,0x80);
|
|
lpCon->ColorTable[ 9] = RGB(0, 0, 0xFF);
|
|
lpCon->ColorTable[10] = RGB(0, 0xFF,0 );
|
|
lpCon->ColorTable[11] = RGB(0, 0xFF,0xFF);
|
|
lpCon->ColorTable[12] = RGB(0xFF,0, 0 );
|
|
lpCon->ColorTable[13] = RGB(0xFF,0, 0xFF);
|
|
lpCon->ColorTable[14] = RGB(0xFF,0xFF,0 );
|
|
lpCon->ColorTable[15] = RGB(0xFF,0xFF,0xFF);
|
|
|
|
}
|
|
|
|
|
|
VOID
|
|
LinkGetRegistryValues(
|
|
LPWSTR ConsoleTitle,
|
|
LPLNKPROPNTCONSOLE lpCon
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine reads in values from the registry and places them
|
|
in the supplied structure.
|
|
|
|
Arguments:
|
|
|
|
pStateInfo - optional pointer to structure to receive information
|
|
|
|
Return Value:
|
|
|
|
current page number
|
|
|
|
--*/
|
|
|
|
{
|
|
HKEY hCurrentUserKey;
|
|
HKEY hConsoleKey;
|
|
HKEY hTitleKey;
|
|
NTSTATUS Status;
|
|
LPWSTR TranslatedTitle;
|
|
DWORD dwValue;
|
|
DWORD i;
|
|
WCHAR awchFaceName[LF_FACESIZE];
|
|
WCHAR awchBuffer[ 16 ];
|
|
|
|
//
|
|
// Impersonate the client process
|
|
//
|
|
|
|
if (!CsrImpersonateClient(NULL)) {
|
|
KdPrint(("CONSRV: GetRegistryValues Impersonate failed\n"));
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Open the current user registry key
|
|
//
|
|
|
|
Status = RtlOpenCurrentUser(MAXIMUM_ALLOWED, &hCurrentUserKey);
|
|
if (!NT_SUCCESS(Status)) {
|
|
CsrRevertToSelf();
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Open the console registry key
|
|
//
|
|
|
|
Status = MyRegOpenKey(hCurrentUserKey,
|
|
CONSOLE_REGISTRY_STRING,
|
|
&hConsoleKey);
|
|
if (!NT_SUCCESS(Status)) {
|
|
NtClose(hCurrentUserKey);
|
|
CsrRevertToSelf();
|
|
return;
|
|
}
|
|
|
|
//
|
|
// If there is no structure to fill out, just bail out
|
|
//
|
|
|
|
if (!lpCon)
|
|
goto CloseKeys;
|
|
|
|
//
|
|
// Open the console title subkey, if there is one
|
|
//
|
|
|
|
if (ConsoleTitle && (*ConsoleTitle != L'\0'))
|
|
{
|
|
TranslatedTitle = TranslateConsoleTitle(ConsoleTitle);
|
|
if (TranslatedTitle == NULL)
|
|
goto GetDefaultConsole;
|
|
Status = MyRegOpenKey( hConsoleKey,
|
|
TranslatedTitle,
|
|
&hTitleKey);
|
|
HeapFree(pConHeap,0,TranslatedTitle);
|
|
if (!NT_SUCCESS(Status))
|
|
goto GetDefaultConsole;
|
|
} else {
|
|
|
|
GetDefaultConsole:
|
|
|
|
hTitleKey = hConsoleKey;
|
|
}
|
|
|
|
//
|
|
// Initial screen fill
|
|
//
|
|
|
|
if (NT_SUCCESS(MyRegQueryValue(hTitleKey,
|
|
CONSOLE_REGISTRY_FILLATTR,
|
|
sizeof(dwValue), (PBYTE)&dwValue))) {
|
|
lpCon->wFillAttribute = (WORD)dwValue;
|
|
}
|
|
|
|
//
|
|
// Initial popup fill
|
|
//
|
|
|
|
if (NT_SUCCESS(MyRegQueryValue(hTitleKey,
|
|
CONSOLE_REGISTRY_POPUPATTR,
|
|
sizeof(dwValue), (PBYTE)&dwValue))) {
|
|
lpCon->wPopupFillAttribute = (WORD)dwValue;
|
|
}
|
|
|
|
//
|
|
// Initial insert mode
|
|
//
|
|
|
|
if (NT_SUCCESS(MyRegQueryValue(hTitleKey,
|
|
CONSOLE_REGISTRY_INSERTMODE,
|
|
sizeof(dwValue), (PBYTE)&dwValue))) {
|
|
lpCon->bInsertMode = !!dwValue;
|
|
}
|
|
|
|
//
|
|
// Initial quick edit mode
|
|
//
|
|
|
|
if (NT_SUCCESS(MyRegQueryValue(hTitleKey,
|
|
CONSOLE_REGISTRY_QUICKEDIT,
|
|
sizeof(dwValue), (PBYTE)&dwValue))) {
|
|
lpCon->bQuickEdit = !!dwValue;
|
|
}
|
|
|
|
#ifdef i386
|
|
//
|
|
// Initial full screen mode
|
|
//
|
|
|
|
if (NT_SUCCESS(MyRegQueryValue(hTitleKey,
|
|
CONSOLE_REGISTRY_FULLSCR,
|
|
sizeof(dwValue), (PBYTE)&dwValue))) {
|
|
lpCon->bFullScreen = !!dwValue;
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Initial screen buffer size
|
|
//
|
|
|
|
if (NT_SUCCESS(MyRegQueryValue(hTitleKey,
|
|
CONSOLE_REGISTRY_BUFFERSIZE,
|
|
sizeof(dwValue), (PBYTE)&dwValue))) {
|
|
lpCon->dwScreenBufferSize.X = LOWORD(dwValue);
|
|
lpCon->dwScreenBufferSize.Y = HIWORD(dwValue);
|
|
}
|
|
|
|
//
|
|
// Initial window size
|
|
//
|
|
|
|
if (NT_SUCCESS(MyRegQueryValue(hTitleKey,
|
|
CONSOLE_REGISTRY_WINDOWSIZE,
|
|
sizeof(dwValue), (PBYTE)&dwValue))) {
|
|
lpCon->dwWindowSize.X = LOWORD(dwValue);
|
|
lpCon->dwWindowSize.Y = HIWORD(dwValue);
|
|
}
|
|
|
|
//
|
|
// Initial window position
|
|
//
|
|
|
|
if (NT_SUCCESS(MyRegQueryValue(hTitleKey,
|
|
CONSOLE_REGISTRY_WINDOWPOS,
|
|
sizeof(dwValue), (PBYTE)&dwValue))) {
|
|
lpCon->dwWindowOrigin.X = (SHORT)LOWORD(dwValue);
|
|
lpCon->dwWindowOrigin.Y = (SHORT)HIWORD(dwValue);
|
|
lpCon->bAutoPosition = FALSE;
|
|
}
|
|
|
|
//
|
|
// Initial font size
|
|
//
|
|
|
|
if (NT_SUCCESS(MyRegQueryValue(hTitleKey,
|
|
CONSOLE_REGISTRY_FONTSIZE,
|
|
sizeof(dwValue), (PBYTE)&dwValue))) {
|
|
lpCon->dwFontSize.X = LOWORD(dwValue);
|
|
lpCon->dwFontSize.Y = HIWORD(dwValue);
|
|
}
|
|
|
|
//
|
|
// Initial font family
|
|
//
|
|
|
|
if (NT_SUCCESS(MyRegQueryValue(hTitleKey,
|
|
CONSOLE_REGISTRY_FONTFAMILY,
|
|
sizeof(dwValue), (PBYTE)&dwValue))) {
|
|
lpCon->uFontFamily = dwValue;
|
|
}
|
|
|
|
//
|
|
// Initial font weight
|
|
//
|
|
|
|
if (NT_SUCCESS(MyRegQueryValue(hTitleKey,
|
|
CONSOLE_REGISTRY_FONTWEIGHT,
|
|
sizeof(dwValue), (PBYTE)&dwValue))) {
|
|
lpCon->uFontWeight = dwValue;
|
|
}
|
|
|
|
//
|
|
// Initial font face name
|
|
//
|
|
|
|
if (NT_SUCCESS(MyRegQueryValue(hTitleKey,
|
|
CONSOLE_REGISTRY_FACENAME,
|
|
sizeof(awchFaceName), (PBYTE)awchFaceName))) {
|
|
RtlCopyMemory(lpCon->FaceName, awchFaceName, sizeof(awchFaceName));
|
|
}
|
|
|
|
//
|
|
// Initial cursor size
|
|
//
|
|
|
|
if (NT_SUCCESS(MyRegQueryValue(hTitleKey,
|
|
CONSOLE_REGISTRY_CURSORSIZE,
|
|
sizeof(dwValue), (PBYTE)&dwValue))) {
|
|
lpCon->uCursorSize = dwValue;
|
|
}
|
|
|
|
//
|
|
// Initial history buffer size
|
|
//
|
|
|
|
if (NT_SUCCESS(MyRegQueryValue(hTitleKey,
|
|
CONSOLE_REGISTRY_HISTORYSIZE,
|
|
sizeof(dwValue), (PBYTE)&dwValue))) {
|
|
lpCon->uHistoryBufferSize = dwValue;
|
|
}
|
|
|
|
//
|
|
// Initial number of history buffers
|
|
//
|
|
|
|
if (NT_SUCCESS(MyRegQueryValue(hTitleKey,
|
|
CONSOLE_REGISTRY_HISTORYBUFS,
|
|
sizeof(dwValue), (PBYTE)&dwValue))) {
|
|
lpCon->uNumberOfHistoryBuffers = dwValue;
|
|
}
|
|
|
|
//
|
|
// Initial history duplication mode
|
|
//
|
|
|
|
if (NT_SUCCESS(MyRegQueryValue(hTitleKey,
|
|
CONSOLE_REGISTRY_HISTORYNODUP,
|
|
sizeof(dwValue), (PBYTE)&dwValue))) {
|
|
lpCon->bHistoryNoDup = dwValue;
|
|
}
|
|
|
|
//
|
|
// Initial color table
|
|
//
|
|
|
|
for (i=0; i<16; i++) {
|
|
wsprintf(awchBuffer, CONSOLE_REGISTRY_COLORTABLE, i);
|
|
if (NT_SUCCESS(MyRegQueryValue(hTitleKey, awchBuffer,
|
|
sizeof(dwValue), (PBYTE)&dwValue))) {
|
|
lpCon->ColorTable[i] = dwValue;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Close the registry keys
|
|
//
|
|
|
|
if (hTitleKey != hConsoleKey) {
|
|
NtClose(hTitleKey);
|
|
}
|
|
|
|
CloseKeys:
|
|
NtClose(hConsoleKey);
|
|
NtClose(hCurrentUserKey);
|
|
CsrRevertToSelf();
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
// Error checking
|
|
if (!szLinkName)
|
|
return 0;
|
|
|
|
// 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 = min( ((pDot - pLnk) * sizeof(WCHAR)), MAX_TITLE_LENGTH );
|
|
}
|
|
else
|
|
{
|
|
dwLen = min( (lstrlenW(pLnk) * sizeof(WCHAR)), MAX_TITLE_LENGTH );
|
|
}
|
|
|
|
RtlCopyMemory(szTitle, pLnk, dwLen);
|
|
|
|
return dwLen;
|
|
|
|
}
|
|
|
|
|
|
VOID GetDefaultConsoleProperties( LPTSTR pszLinkName, LPLNKPROPNTCONSOLE lpCon )
|
|
{
|
|
|
|
WCHAR ConsoleTitle[ (MAX_TITLE_LENGTH/2) + 1 ];
|
|
DWORD cbLen;
|
|
|
|
|
|
//
|
|
// Construct window title from link name
|
|
//
|
|
cbLen = GetTitleFromLinkName( pszLinkName, ConsoleTitle );
|
|
if (cbLen> (MAX_TITLE_LENGTH + 2))
|
|
cbLen = MAX_TITLE_LENGTH + 2;
|
|
ConsoleTitle[ cbLen / sizeof(WCHAR) ] = L'\0';
|
|
|
|
//
|
|
// Initialize console settings to some sane values
|
|
//
|
|
LinkInitRegistryValues( lpCon );
|
|
|
|
//
|
|
// Try loading default console settings first
|
|
//
|
|
LinkGetRegistryValues( NULL, lpCon );
|
|
|
|
|
|
//
|
|
// If we have a title, query the registry for settings to overlay on top
|
|
// of the default settings.
|
|
//
|
|
if (ConsoleTitle[0])
|
|
LinkGetRegistryValues( ConsoleTitle, lpCon );
|
|
|
|
}
|
|
|
|
|
|
BOOL ReadString( HANDLE hFile, LPVOID * lpVoid, BOOL bUnicode )
|
|
{
|
|
|
|
USHORT cch;
|
|
DWORD dwBytesRead;
|
|
BOOL fResult = TRUE;
|
|
|
|
if (bUnicode)
|
|
{
|
|
LPWSTR lpWStr = NULL;
|
|
|
|
fResult &= ReadFile( hFile, (LPVOID)&cch, sizeof(cch), &dwBytesRead, NULL );
|
|
lpWStr = (LPWSTR)HeapAlloc( pConHeap, HEAP_ZERO_MEMORY, (cch+1)*sizeof(WCHAR) );
|
|
if (lpWStr) {
|
|
fResult &= ReadFile( hFile, (LPVOID)lpWStr, cch*sizeof(WCHAR), &dwBytesRead, NULL );
|
|
lpWStr[cch] = L'\0';
|
|
}
|
|
*(LPDWORD)lpVoid = (DWORD)lpWStr;
|
|
}
|
|
else
|
|
{
|
|
LPSTR lpStr = NULL;
|
|
|
|
fResult &= ReadFile( hFile, (LPVOID)&cch, sizeof(cch), &dwBytesRead, NULL );
|
|
lpStr = (LPSTR)HeapAlloc( pConHeap, HEAP_ZERO_MEMORY, (cch+1) );
|
|
if (lpStr) {
|
|
fResult &= ReadFile( hFile, (LPVOID)lpStr, cch, &dwBytesRead, NULL );
|
|
lpStr[cch] = '\0';
|
|
}
|
|
*(LPDWORD)lpVoid = (DWORD)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) );
|
|
|
|
// 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
|
|
{
|
|
if (hFile)
|
|
CloseHandle( hFile );
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
// BUGBUG: this part is not unicode ready, talk to daviddi
|
|
|
|
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 *)HeapReAlloc( pConHeap,
|
|
HEAP_ZERO_MEMORY,
|
|
this->pExtraData,
|
|
cbTotal + cbSize + sizeof(DWORD)
|
|
);
|
|
if (pTemp)
|
|
{
|
|
this->pExtraData = pTemp;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
this->pExtraData = pTemp = HeapAlloc( pConHeap, 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;
|
|
|
|
}
|
|
|
|
|
|
if (hFile)
|
|
CloseHandle( hFile );
|
|
|
|
return fResult;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL GetLinkProperties( LPWSTR pszLinkName, DWORD dwPropertySet, LPVOID lpvBuffer, UINT cb )
|
|
{
|
|
CShellLink mld;
|
|
BOOL fResult = FALSE;
|
|
|
|
/*
|
|
{
|
|
TCHAR szRick[ 1024 ];
|
|
STARTUPINFO si;
|
|
PROCESS_INFORMATION pi;
|
|
|
|
// HUGE, HUGE hack-o-rama to get NTSD started on this process!
|
|
wsprintf( szRick, TEXT("ntsd -d -p %d"), GetCurrentProcessId() );
|
|
GetStartupInfo( &si );
|
|
CreateProcess( NULL, szRick, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi );
|
|
CloseHandle( pi.hProcess );
|
|
CloseHandle( pi.hThread );
|
|
Sleep( 5*1000 );
|
|
DebugBreak();
|
|
|
|
}
|
|
*/
|
|
|
|
|
|
|
|
// Zero out structure on the stack
|
|
RtlZeroMemory( &mld, sizeof(mld) );
|
|
|
|
// Load link data
|
|
if (!LoadLink( pszLinkName, &mld ))
|
|
return FALSE;
|
|
|
|
// Now, parse the fields for LINK_PROP_MAIN_HDR
|
|
|
|
if (dwPropertySet==LINK_PROP_MAIN_SIG)
|
|
{
|
|
|
|
// Check return buffer -- is it big enough?
|
|
if ((cb < sizeof( LNKPROPMAIN )) || (!lpvBuffer))
|
|
goto Exit;
|
|
|
|
// Copy data from link into caller's buffer
|
|
lstrcpyW( ((LPLNKPROPMAIN)lpvBuffer)->pszLinkName, mld.pszCurFile );
|
|
if (mld.pszName)
|
|
lstrcpy( ((LPLNKPROPMAIN)lpvBuffer)->pszName, mld.pszName );
|
|
if (mld.pszRelPath)
|
|
lstrcpy( ((LPLNKPROPMAIN)lpvBuffer)->pszRelPath, mld.pszRelPath );
|
|
if (mld.pszWorkingDir)
|
|
lstrcpy( ((LPLNKPROPMAIN)lpvBuffer)->pszWorkingDir, mld.pszWorkingDir );
|
|
if (mld.pszArgs)
|
|
lstrcpy( ((LPLNKPROPMAIN)lpvBuffer)->pszArgs, mld.pszArgs );
|
|
if (mld.pszIconLocation)
|
|
lstrcpy( ((LPLNKPROPMAIN)lpvBuffer)->pszIconLocation, mld.pszIconLocation );
|
|
((LPLNKPROPMAIN)lpvBuffer)->iIcon = mld.sld.iIcon;
|
|
((LPLNKPROPMAIN)lpvBuffer)->iShowCmd = mld.sld.iShowCmd;
|
|
((LPLNKPROPMAIN)lpvBuffer)->wHotKey = mld.sld.wHotkey;
|
|
fResult = TRUE;
|
|
|
|
}
|
|
|
|
|
|
// Now, parse the fields for LINK_PROP_CONSOLE_HDR
|
|
|
|
if (dwPropertySet==LINK_PROP_NT_CONSOLE_SIG)
|
|
{
|
|
|
|
LPNT_CONSOLE_PROPS lpExtraData;
|
|
DWORD dwSize = 0;
|
|
|
|
// Check return buffer -- is it big enough?
|
|
if ((cb < sizeof( LNKPROPNTCONSOLE )) || (!lpvBuffer))
|
|
goto Exit;
|
|
|
|
// 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;
|
|
|
|
// 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)->wFillAttribute,
|
|
&lpExtraData->wFillAttribute,
|
|
sizeof( NT_CONSOLE_PROPS ) - FIELD_OFFSET( NT_CONSOLE_PROPS, wFillAttribute )
|
|
);
|
|
fResult = TRUE;
|
|
goto Exit;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!fResult)
|
|
{
|
|
GetDefaultConsoleProperties( pszLinkName, (LPLNKPROPNTCONSOLE)lpvBuffer );
|
|
fResult = TRUE;
|
|
}
|
|
|
|
|
|
Exit:
|
|
|
|
#if 0
|
|
#define ConsoleInfo ((LPLNKPROPNTCONSOLE)lpvBuffer)
|
|
{
|
|
TCHAR szTemp[ 256 ];
|
|
INT i;
|
|
|
|
wsprintf( szTemp, TEXT("[GetLinkProperties -- Link Properties for %s]\n"), pszLinkName );
|
|
OutputDebugString( szTemp );
|
|
wsprintf( szTemp, TEXT(" wFillAttribute = 0x%04X\n"), ConsoleInfo->wFillAttribute );
|
|
OutputDebugString( szTemp );
|
|
wsprintf( szTemp, TEXT(" wPopupFillAttribute = 0x%04X\n"), ConsoleInfo->wPopupFillAttribute );
|
|
OutputDebugString( szTemp );
|
|
wsprintf( szTemp, TEXT(" dwScreenBufferSize = (%d , %d)\n"), ConsoleInfo->dwScreenBufferSize.X, ConsoleInfo->dwScreenBufferSize.Y );
|
|
OutputDebugString( szTemp );
|
|
wsprintf( szTemp, TEXT(" dwWindowSize = (%d , %d)\n"), ConsoleInfo->dwWindowSize.X, ConsoleInfo->dwWindowSize.Y );
|
|
OutputDebugString( szTemp );
|
|
wsprintf( szTemp, TEXT(" dwWindowOrigin = (%d , %d)\n"), ConsoleInfo->dwWindowOrigin.X, ConsoleInfo->dwWindowOrigin.Y );
|
|
OutputDebugString( szTemp );
|
|
wsprintf( szTemp, TEXT(" nFont = 0x%X\n"), ConsoleInfo->nFont );
|
|
OutputDebugString( szTemp );
|
|
wsprintf( szTemp, TEXT(" nInputBufferSize = 0x%X\n"), ConsoleInfo->nInputBufferSize );
|
|
OutputDebugString( szTemp );
|
|
wsprintf( szTemp, TEXT(" dwFontSize = (%d , %d)\n"), ConsoleInfo->dwFontSize.X, ConsoleInfo->dwFontSize.Y );
|
|
OutputDebugString( szTemp );
|
|
wsprintf( szTemp, TEXT(" uFontFamily = 0x%08X\n"), ConsoleInfo->uFontFamily );
|
|
OutputDebugString( szTemp );
|
|
wsprintf( szTemp, TEXT(" uFontWeight = 0x%08X\n"), ConsoleInfo->uFontWeight );
|
|
OutputDebugString( szTemp );
|
|
wsprintf( szTemp, TEXT(" FaceName = %ws\n"), ConsoleInfo->FaceName );
|
|
OutputDebugString( szTemp );
|
|
wsprintf( szTemp, TEXT(" uCursorSize = %d\n"), ConsoleInfo->uCursorSize );
|
|
OutputDebugString( szTemp );
|
|
wsprintf( szTemp, TEXT(" bFullScreen = %s\n"), ConsoleInfo->bFullScreen ? TEXT("TRUE") : TEXT("FALSE") );
|
|
OutputDebugString( szTemp );
|
|
wsprintf( szTemp, TEXT(" bQuickEdit = %s\n"), ConsoleInfo->bQuickEdit ? TEXT("TRUE") : TEXT("FALSE") );
|
|
OutputDebugString( szTemp );
|
|
wsprintf( szTemp, TEXT(" bInsertMode = %s\n"), ConsoleInfo->bInsertMode ? TEXT("TRUE") : TEXT("FALSE") );
|
|
OutputDebugString( szTemp );
|
|
wsprintf( szTemp, TEXT(" bAutoPosition = %s\n"), ConsoleInfo->bAutoPosition ? TEXT("TRUE") : TEXT("FALSE") );
|
|
OutputDebugString( szTemp );
|
|
wsprintf( szTemp, TEXT(" uHistoryBufferSize = %d\n"), ConsoleInfo->uHistoryBufferSize );
|
|
OutputDebugString( szTemp );
|
|
wsprintf( szTemp, TEXT(" uNumHistoryBuffers = %d\n"), ConsoleInfo->uNumberOfHistoryBuffers );
|
|
OutputDebugString( szTemp );
|
|
wsprintf( szTemp, TEXT(" bHistoryNoDup = %s\n"), ConsoleInfo->bHistoryNoDup ? TEXT("TRUE") : TEXT("FALSE") );
|
|
OutputDebugString( szTemp );
|
|
OutputDebugString( TEXT(" ColorTable = [") );
|
|
i=0;
|
|
while( i < 16 )
|
|
{
|
|
OutputDebugString( TEXT("\n ") );
|
|
wsprintf( szTemp, TEXT("0x%08X "), ConsoleInfo->ColorTable[i++]);
|
|
OutputDebugString( szTemp );
|
|
wsprintf( szTemp, TEXT("0x%08X "), ConsoleInfo->ColorTable[i++]);
|
|
OutputDebugString( szTemp );
|
|
wsprintf( szTemp, TEXT("0x%08X "), ConsoleInfo->ColorTable[i++]);
|
|
OutputDebugString( szTemp );
|
|
wsprintf( szTemp, TEXT("0x%08X "), ConsoleInfo->ColorTable[i++]);
|
|
OutputDebugString( szTemp );
|
|
}
|
|
OutputDebugString( TEXT("]\n\n") );
|
|
}
|
|
#undef ConsoleInfo
|
|
#endif
|
|
|
|
if (mld.pszName)
|
|
HeapFree( pConHeap, 0, mld.pszName );
|
|
if (mld.pszRelPath)
|
|
HeapFree( pConHeap, 0, mld.pszRelPath );
|
|
if (mld.pszWorkingDir)
|
|
HeapFree( pConHeap, 0, mld.pszWorkingDir );
|
|
if (mld.pszArgs)
|
|
HeapFree( pConHeap, 0, mld.pszArgs );
|
|
if (mld.pszIconLocation)
|
|
HeapFree( pConHeap, 0, mld.pszIconLocation );
|
|
if (mld.pExtraData)
|
|
HeapFree( pConHeap, 0, mld.pExtraData );
|
|
|
|
return fResult;
|
|
|
|
}
|
|
|
|
|