使用 GetFileInformationByHandle 检查文件是否有硬链接
typedef struct _BY_HANDLE_FILE_INFORMATION {
DWORD dwFileAttributes;
FILETIME ftCreationTime;
FILETIME ftLastAccessTime;
FILETIME ftLastWriteTime;
DWORD dwVolumeSerialNumber;
DWORD nFileSizeHigh;
DWORD nFileSizeLow;
DWORD nNumberOfLinks; <--- if this value is more than 1, then we have hard links
DWORD nFileIndexHigh;
DWORD nFileIndexLow;
} BY_HANDLE_FILE_INFORMATION, *PBY_HANDLE_FILE_INFORMATION, *LPBY_HANDLE_FILE_INFORMATION;
然后对于 vista 或更高版本,使用 FindFirstFileName/FindNextFileName 来获取目标。
对于较早的系统版本,遍历整个卷并比较nFileIndexHigh和nFileIndexLow,一旦找到,--nNumberOfLinks,打印目标名称,直到nNumberofLinks==1,然后退出。
这是我通过反转二进制文件在 FindLinks.exe 中找到的方式。
if ( _wcsicmp(dword_422154, lpFileName) )
{
sub_402580(v4, (DWORD *)&v8, (int)&fileindexlow, (int)&v11);
if ( fileindexlow == a3 && fileindexhigh == a4 )
{
wprintf(L"\r \r%s\n", v4);
if ( --*v5 == 1 ) //numoflinks
exit(0);
}
}
char __usercall sub_402580@<al>(LPCWSTR lpFileName@<ecx>, DWORD *a2@<edx>, int a3, int a4)
{
DWORD *v4; // edi
DWORD v5; // eax
HANDLE v6; // esi
DWORD v7; // ecx
const WCHAR *lpFileNamea; // [esp+Ch] [ebp-40h]
struct _BY_HANDLE_FILE_INFORMATION FileInformation; // [esp+14h] [ebp-38h]
v4 = a2;
lpFileNamea = lpFileName;
v5 = GetFileAttributesW(lpFileName);
if ( v5 == -1 )
return 0;
*v4 = 0;
v4[1] = 0;
*(_DWORD *)a3 = 0;
*(_DWORD *)(a3 + 4) = 0;
*(_DWORD *)a4 = 0;
v6 = CreateFileW(lpFileNamea, 0x80u, 7u, 0, 3u, (v5 & 0x10) << 21, 0);
if ( v6 == (HANDLE)-1 )
return 0;
if ( GetFileInformationByHandle(v6, &FileInformation) )
{
*(_DWORD *)a4 = FileInformation.nNumberOfLinks;
v7 = FileInformation.nFileSizeHigh;
*v4 = FileInformation.nFileSizeLow;
v4[1] = v7;
LOWORD(v7) = FileInformation.nFileIndexHigh;
*(_DWORD *)a3 = FileInformation.nFileIndexLow;
*(_DWORD *)(a3 + 4) = (unsigned __int16)v7;
}
CloseHandle(v6);
return 1;
}