Friday, October 19, 2007

OpenFileById

A while back,

I was trying to determine the file name for a given file ID, and had initially found the new win32 API to do this: OpenFileById.

However, I never got it to work, and soon used some kernel code in usermode to get it.

Recently, I've had to revisit this code to make an easier win32 app that can find a file's name.

I was always getting an invalid parameter every time I called the function, so I finally traced in assembly...

And behold! The function was checking my parameters, and the size of the structure I was passing (the dwSize parameter), which I had set to the sizeof(structure).

When looking at the given size, it did not match what they were looking for. (I had 16)

So I just changed my code to set the size to the value they were expecting (24), and made sure I allocated my structure inside a pointer that had at least that size as a backing (even if the structure really only is 16 bytes).

All of a sudden it worked!

Here is a tidbit:


wsprintf(szVolumePath, TEXT("\\\\.\\%c:"), cDriveLetter[0]);
hDisk=CreateFile(szVolumePath,
GENERIC_READ,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL);

if(hDisk!=INVALID_HANDLE_VALUE)
{
// This value was determined by looking at the assembly code
// and has no actual corresponance to the structure size which
// is 16. Might be related to 64bit version?
fileIDDesc.dwSize = 24;
fileIDDesc.FileId.QuadPart = index;
fileIDDesc.Type = FileIdType;

hFile = OpenFileById ( hDisk,
&fileIDDesc,
SYNCHRONIZE | FILE_READ_ATTRIBUTES,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,
0 );

if (hFile != INVALID_HANDLE_VALUE)
{
PFILE_NAME_INFO pFileNameInfo = NULL;
pFileNameInfo = (PFILE_NAME_INFO)malloc(sizeof(FILE_NAME_INFO)+1000);
if (pFileNameInfo != NULL)
{
RtlZeroMemory(pFileNameInfo, sizeof(FILE_NAME_INFO) + 1000);
GetFileInformationByHandleEx(hFile, FileNameInfo, pFileNameInfo, sizeof(FILE_NAME_INFO) + 1000);

if (pFileNameInfo->FileNameLength > 0)
{
if (*pLength >= pFileNameInfo->FileNameLength)
{
// copy your file, and return it!

That's how simple it is, if you figure out that OpenFileById needs a 24bytes size structure :p

2 comments:

eugenez said...

I'd assume they us declspec(align(24)) on the struct, to make sure it is aligned on 24 bit boundary.
Why that is not documented, that's another issue :)

Ivan Borisenko said...

Hey guys, do you ever seen that FILE_ID_DESCRIPTOR has 16-byte GUID in its body union-ed with 8-byte FileID?