#include #pragma hdrstop void ReadString( HANDLE hFile, LPVOID * lpVoid, BOOL bUnicode ) { USHORT cch; DWORD dwBytesRead; *lpVoid = NULL; if (bUnicode) { LPWSTR lpWStr = NULL; if (ReadFile( hFile, (LPVOID)&cch, sizeof(cch), &dwBytesRead, NULL )) { lpWStr = (LPWSTR)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, (cch+1)*sizeof(WCHAR) ); if (lpWStr) { if (ReadFile( hFile, (LPVOID)lpWStr, cch*sizeof(WCHAR), &dwBytesRead, NULL )) { lpWStr[cch] = L'\0'; *lpVoid = lpWStr; } } } } else { LPSTR lpStr = NULL; if (ReadFile( hFile, (LPVOID)&cch, sizeof(cch), &dwBytesRead, NULL )) { lpStr = (LPSTR)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, (cch+1) ); if (lpStr) { if (ReadFile( hFile, (LPVOID)lpStr, cch, &dwBytesRead, NULL )) { lpStr[cch] = '\0'; *lpVoid = lpStr; } } } } } int __cdecl main( int argc, char *argv[]) { HANDLE hFile; CShellLink csl; CShellLink * this = &csl; DWORD cbSize, cbTotal, cbToRead, dwBytesRead; SYSTEMTIME st; LPSTR pTemp = NULL; this->pidl = 0; this->pli = NULL; memset( this, 0, sizeof(CShellLink) ); if (argc!=2) { printf("usage: lnkdump filename.lnk\n" ); return(1); } // Try to open the file hFile = CreateFile( argv[1], GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if (hFile == INVALID_HANDLE_VALUE) { printf( "lnkdump: unable to open file %s, err %d\n", argv[1], GetLastError() ); return(1); } // Now, read out data... if (!ReadFile( hFile, (LPVOID)&this->sld, sizeof(this->sld), &dwBytesRead, NULL )) return (1); // 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 if (!ReadFile( hFile, (LPVOID)&cbSize, sizeof(USHORT), &dwBytesRead, NULL )) return (1); if (cbSize) { SetFilePointer(hFile,cbSize,NULL,FILE_CURRENT); } else { printf( "Error readling PIDL out of link!\n" ); return( 1 ); } } // REARCHITECT: this part is not unicode ready, talk to daviddi if (this->sld.dwFlags & (SLDF_HAS_LINK_INFO)) { LPVOID pli; if (!ReadFile( hFile, (LPVOID)&cbSize, sizeof(cbSize), &dwBytesRead, NULL )) return (1); if (cbSize >= sizeof(cbSize)) { cbSize -= sizeof(cbSize); SetFilePointer(hFile,cbSize,NULL,FILE_CURRENT); } } if (this->sld.dwFlags & SLDF_HAS_NAME) ReadString( hFile, &this->pszName, this->sld.dwFlags & SLDF_UNICODE); if (this->sld.dwFlags & SLDF_HAS_RELPATH) ReadString( hFile, &this->pszRelPath, this->sld.dwFlags & SLDF_UNICODE); if (this->sld.dwFlags & SLDF_HAS_WORKINGDIR) ReadString( hFile, &this->pszWorkingDir, this->sld.dwFlags & SLDF_UNICODE); if (this->sld.dwFlags & SLDF_HAS_ARGS) ReadString( hFile, &this->pszArgs, this->sld.dwFlags & SLDF_UNICODE); if (this->sld.dwFlags & SLDF_HAS_ICONLOCATION) 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; if (!ReadFile( hFile, (LPVOID)&cbSize, sizeof(cbSize), &dwBytesRead, NULL )) return (1); if (cbSize < sizeof(cbSize)) break; if (pTemp) { pTemp = (void *)HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, this->pExtraData, cbTotal + cbSize + sizeof(DWORD) ); if (pTemp) { this->pExtraData = (LPDBLIST)pTemp; } } else { (LPVOID)this->pExtraData = pTemp = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, cbTotal + cbSize + sizeof(DWORD) ); } if (!pTemp) break; cbToRead = cbSize - sizeof(cbSize); pReadData = pTemp + cbTotal; if (!ReadFile( hFile, (LPVOID)(pReadData + sizeof(cbSize)), cbToRead, &dwBytesRead, NULL )) return (1); if (dwBytesRead==cbToRead) { // got all of the extra data, comit it *((UNALIGNED DWORD *)pReadData) = cbSize; cbTotal += cbSize; } else break; } printf( "\n===== Dump of link file (%s) =====\n\n", argv[1] ); printf( "[Shell Link Data (sld)]\n" ); printf( " cbSize = 0x%08X\n", this->sld.cbSize ); printf( " GUID = {%08lX-%04X-%04X-%02X%02X-%02X%02X%02x%02x%02x%02x}\n", this->sld.clsid.Data1, this->sld.clsid.Data2, this->sld.clsid.Data3, this->sld.clsid.Data4[0], this->sld.clsid.Data4[1], this->sld.clsid.Data4[2], this->sld.clsid.Data4[3], this->sld.clsid.Data4[4], this->sld.clsid.Data4[5], this->sld.clsid.Data4[6], this->sld.clsid.Data4[7] ); printf( " dwFlags = 0x%08X\n", this->sld.dwFlags ); if (this->sld.dwFlags & SLDF_HAS_ID_LIST) printf( " SLDF_HAS_ID_LIST is set.\n" ); if (this->sld.dwFlags & SLDF_HAS_LINK_INFO) printf( " SLDF_HAS_LINK_INFO is set.\n" ); if (this->sld.dwFlags & SLDF_HAS_NAME) printf( " SLDF_HAS_NAME is set.\n" ); if (this->sld.dwFlags & SLDF_HAS_RELPATH) printf( " SLDF_HAS_RELPATH is set.\n" ); if (this->sld.dwFlags & SLDF_HAS_WORKINGDIR) printf( " SLDF_HAS_WORKINGDIR is set.\n" ); if (this->sld.dwFlags & SLDF_HAS_ARGS) printf( " SLDF_HAS_ARGS is set.\n" ); if (this->sld.dwFlags & SLDF_HAS_ICONLOCATION) printf( " SLDF_HAS_ICONLOCATION is set.\n" ); if (this->sld.dwFlags & SLDF_HAS_EXP_SZ) printf( " SLDF_HAS_EXP_SZ is set.\n" ); if (this->sld.dwFlags & SLDF_RUN_IN_SEPARATE) printf( " SLDF_RUN_IN_SEPARATE is set.\n" ); if (this->sld.dwFlags & SLDF_UNICODE) printf( " SLDF_HAS_UNICODE is set.\n" ); if (this->sld.dwFlags & SLDF_FORCE_NO_LINKINFO) printf( " SLDF_FORCE_NO_LINKINFO is set.\n" ); printf( " dwFileAttributes = 0x%08X\n", this->sld.dwFileAttributes ); if (this->sld.dwFileAttributes & FILE_ATTRIBUTE_READONLY) printf( " FILE_ATTRIBUTE_READONLY is set.\n" ); if (this->sld.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) printf( " FILE_ATTRIBUTE_HIDDEN is set.\n" ); if (this->sld.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) printf( " FILE_ATTRIBUTE_SYSTEM is set.\n" ); if (this->sld.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) printf( " FILE_ATTRIBUTE_DIRECTORY is set.\n" ); if (this->sld.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) printf( " FILE_ATTRIBUTE_ARCHIVE is set.\n" ); if (this->sld.dwFileAttributes & FILE_ATTRIBUTE_NORMAL) printf( " FILE_ATTRIBUTE_NORMAL is set.\n" ); if (this->sld.dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY) printf( " FILE_ATTRIBUTE_TEMPORARY is set.\n" ); if (this->sld.dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED) printf( " FILE_ATTRIBUTE_COMPRESSED is set.\n" ); FileTimeToSystemTime( &this->sld.ftCreationTime, &st ); printf(" ftCreationTime = %02d:%02d:%02d, %02d/%02d/%04d\n", st.wHour, st.wMinute, st.wSecond, st.wMonth, st.wDay, st.wYear ); FileTimeToSystemTime( &this->sld.ftLastAccessTime, &st ); printf(" ftLastAccessTime = %02d:%02d:%02d, %02d/%02d/%04d\n", st.wHour, st.wMinute, st.wSecond, st.wMonth, st.wDay, st.wYear ); FileTimeToSystemTime( &this->sld.ftLastWriteTime, &st ); printf(" ftLastWriteTime = %02d:%02d:%02d, %02d/%02d/%04d\n", st.wHour, st.wMinute, st.wSecond, st.wMonth, st.wDay, st.wYear ); printf(" nFileSizeLow = %d bytes\n", this->sld.nFileSizeLow ); printf(" iIcon = %d\n", this->sld.iIcon ); printf(" wHotkey = 0x08%X\n", this->sld.wHotkey ); printf(" dwRes1 = 0x08%X\n", this->sld.dwRes1 ); printf(" dwRes2 = 0x08%X\n", this->sld.dwRes2 ); printf("\n[Strings]\n"); if (this->pszName) { printf( " pszName = " ); if (this->sld.dwFlags & SLDF_UNICODE) { CHAR szTemp[ 256 ]; WideCharToMultiByte( CP_ACP, 0, (LPWSTR)this->pszName, -1, szTemp, 256, NULL, NULL ); printf( "(UNICODE) %s\n", szTemp ); } else printf( "%s\n", (LPSTR)this->pszName ); } if (this->pszRelPath) { printf( " pszRelPath = " ); if (this->sld.dwFlags & SLDF_UNICODE) { CHAR szTemp[ 256 ]; WideCharToMultiByte( CP_ACP, 0, (LPWSTR)this->pszRelPath, -1, szTemp, 256, NULL, NULL ); printf( "(UNICODE) %s\n", szTemp ); } else printf( "%s\n", (LPSTR)this->pszRelPath ); } if (this->pszWorkingDir) { printf( " pszWorkingDir = " ); if (this->sld.dwFlags & SLDF_UNICODE) { CHAR szTemp[ 256 ]; WideCharToMultiByte( CP_ACP, 0, (LPWSTR)this->pszWorkingDir, -1, szTemp, 256, NULL, NULL ); printf( "(UNICODE) %s\n", szTemp ); } else printf( "%s\n", (LPSTR)this->pszWorkingDir ); } if (this->pszArgs) { printf( " pszArgs = " ); if (this->sld.dwFlags & SLDF_UNICODE) { CHAR szTemp[ 256 ]; WideCharToMultiByte( CP_ACP, 0, (LPWSTR)this->pszArgs, -1, szTemp, 256, NULL, NULL ); printf( "(UNICODE) %s\n", szTemp ); } else printf( "%s\n", (LPSTR)this->pszArgs ); } if (this->pszIconLocation) { printf( " pszIconLocation = " ); if (this->sld.dwFlags & SLDF_UNICODE) { CHAR szTemp[ 256 ]; WideCharToMultiByte( CP_ACP, 0, (LPWSTR)this->pszIconLocation, -1, szTemp, 256, NULL, NULL ); printf( "(UNICODE) %s\n", szTemp ); } else printf( "%s\n", (LPSTR)this->pszIconLocation ); } if (this->pExtraData) { LPEXP_SZ_LINK lpData = (LPEXP_SZ_LINK)this->pExtraData; while( lpData && lpData->cbSize!=0 ) { switch( lpData->dwSignature ) { case EXP_SZ_LINK_SIG: { CHAR szTemp[ 256 ]; printf("\n[Extra Data -- EXP_SZ_LINK_SIG info]\n"); printf(" cbSize = 0x%X bytes\n", lpData->cbSize ); printf(" dwSignature = 0x%X\n", lpData->dwSignature ); printf(" szTarget = %s\n", lpData->szTarget ); WideCharToMultiByte( CP_ACP, 0, lpData->swzTarget, -1, szTemp, 256, NULL, NULL ); printf(" swzTarget = (UNICODE) %s\n\n", szTemp ); } break; case NT_CONSOLE_PROPS_SIG: { CHAR szTemp[ 256 ]; INT i; LPNT_CONSOLE_PROPS lpConData = (LPNT_CONSOLE_PROPS)lpData; printf("\n[Extra Data -- NT_CONSOLE_PROPS_SIG info]\n"); printf(" cbSize = 0x%X bytes\n", lpConData->cbSize ); printf(" dwSignature = 0x%X\n", lpConData->dwSignature ); printf(" wFillAttribute = 0x%04X\n", lpConData->wFillAttribute ); printf(" wPopupFillAttribute = 0x%04X\n", lpConData->wPopupFillAttribute ); printf(" dwScreenBufferSize = (%d , %d)\n", lpConData->dwScreenBufferSize.X, lpConData->dwScreenBufferSize.Y ); printf(" dwWindowSize = (%d , %d)\n", lpConData->dwWindowSize.X, lpConData->dwWindowSize.Y ); printf(" dwWindowOrigin = (%d , %d)\n", lpConData->dwWindowOrigin.X, lpConData->dwWindowOrigin.Y ); printf(" nFont = %d\n", lpConData->nFont ); printf(" nInputBufferSize = %d\n", lpConData->nInputBufferSize ); printf(" dwFontSize = (%d , %d)\n", lpConData->dwFontSize.X, lpConData->dwFontSize.Y ); printf(" uFontFamily = 0x%08X\n", lpConData->uFontFamily ); printf(" uFontWeight = 0x%08X\n", lpConData->uFontWeight ); WideCharToMultiByte( CP_ACP, 0, lpConData->FaceName, LF_FACESIZE, szTemp, LF_FACESIZE, NULL, NULL ); szTemp[ LF_FACESIZE ] = (CHAR)0; printf(" FaceName = %s\n", szTemp ); printf(" uCursorSize = %d\n", lpConData->uCursorSize ); printf(" bFullScreen = %s\n", lpConData->bFullScreen ? "TRUE" : "FALSE" ); printf(" bQuickEdit = %s\n", lpConData->bQuickEdit ? "TRUE" : "FALSE" ); printf(" bInsertMode = %s\n", lpConData->bInsertMode ? "TRUE" : "FALSE" ); printf(" bAutoPosition = %s\n", lpConData->bAutoPosition ? "TRUE" : "FALSE" ); printf(" uHistoryBufferSize = %d\n", lpConData->uHistoryBufferSize ); printf(" uNumHistoryBuffers = %d\n", lpConData->uNumberOfHistoryBuffers ); printf(" bHistoryNoDup = %s\n", lpConData->bHistoryNoDup ? "TRUE" : "FALSE" ); printf(" ColorTable = [" ); i=0; while( i < 16 ) { printf("\n "); printf("0x%08X ", lpConData->ColorTable[i++]); printf("0x%08X ", lpConData->ColorTable[i++]); printf("0x%08X ", lpConData->ColorTable[i++]); printf("0x%08X ", lpConData->ColorTable[i++]); } printf( "]\n\n" ); } break; case NT_FE_CONSOLE_PROPS_SIG: { LPNT_FE_CONSOLE_PROPS lpFEConData = (LPNT_FE_CONSOLE_PROPS)lpData; printf("\n[Extra Data -- NT_FE_CONSOLE_PROPS_SIG info]\n"); printf(" cbSize = 0x%X bytes\n", lpFEConData->cbSize ); printf(" dwSignature = 0x%X\n", lpFEConData->dwSignature ); printf(" CodePage = %d\n\n", lpFEConData->uCodePage ); } break; case EXP_DARWIN_ID_SIG: { CHAR szTemp[ 256 ]; LPEXP_DARWIN_LINK lpDarwin = (LPEXP_DARWIN_LINK)lpData; printf("\n[Extra Data -- EXP_DARWIN_ID_SIG info]\n"); printf(" szDarwinID = %s\n", lpDarwin->szDarwinID ); WideCharToMultiByte( CP_ACP, 0, lpDarwin->szwDarwinID, -1, szTemp, 256, NULL, NULL ); printf(" szwDarwinID = (UNICODE) %s\n\n", szTemp ); } break; case EXP_SPECIAL_FOLDER_SIG: { LPEXP_SPECIAL_FOLDER lpFolder = (LPEXP_SPECIAL_FOLDER)lpData; printf("\n[Extra Data -- EXP_SPECIAL_FOLDER_SIG info]\n"); printf(" idSpecialFolder = 0x%X\n", lpFolder->idSpecialFolder ); printf(" cbOffset = 0x%X\n\n", lpFolder->cbOffset ); } break; #ifdef WINNT case EXP_TRACKER_SIG: { LPEXP_TRACKER lpTracker = (LPEXP_TRACKER)lpData; WCHAR wszGUID[ MAX_PATH ]; printf("\n[Extra Data -- EXP_TRACKER_SIG info]\n"); #if 0 // (reinerf) - traker info looks like a byte-array, how do we dump it? printf(" abTracker = 0x%X\n", lpTracker->abTracker); #endif } #endif break; case EXP_SZ_ICON_SIG: { CHAR szTemp[256]; LPEXP_SZ_LINK lpExpIcon = (LPEXP_SZ_LINK)lpData; printf("\n[Extra Data -- EXP_SZ_ICON_SIG info]\n"); printf(" szTarget = %s\n", lpExpIcon->szTarget ); WideCharToMultiByte( CP_ACP, 0, lpExpIcon->swzTarget, -1, szTemp, 256, NULL, NULL ); printf(" wszTarget = (UNICODE) %s\n\n", szTemp ); } break; } // end swtich (LPBYTE)lpData += lpData->cbSize; } LocalFree( this->pExtraData ); } if (this->pidl) LocalFree( (HLOCAL)this->pidl ); if (this->pli) LocalFree( this->pli ); if (this->pszName) HeapFree( GetProcessHeap(), 0, this->pszName ); if (this->pszRelPath) HeapFree( GetProcessHeap(), 0, this->pszRelPath ); if (this->pszWorkingDir) HeapFree( GetProcessHeap(), 0, this->pszWorkingDir ); if (this->pszArgs) HeapFree( GetProcessHeap(), 0, this->pszArgs ); if (this->pszIconLocation) HeapFree( GetProcessHeap(), 0, this->pszIconLocation ); return(0); }