Friday, March 04, 2011

If you want to use GUIDs to identify your files, then nobody's stopping you

Igor Levicki proposes solving the problem of file extensions by using a GUID instead of a file name to identify a file.

You can do this already. Every file on an NTFS volume has an object identifier which is formally 16-byte buffer, but let's just call it a GUID. By default a file doesn't have an object identifier, but you can ask for one to be created with FSCTL_CREATE_OR_GET_OBJECT_ID, which will retrieve the existing object identifier associated with a file, or create one if there isn't one already. If you are a control freak, you can use FSCTL_SET_OBJECT_ID to specify the GUID you want to use as the object identifier. (The call fails if the file already has an object identifier.) And of course there is FSCTL_GET_OBJECT_ID to retrieve the object identifier, if any.

#define UNICODE
#define _UNICODE
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <ole2.h>
#include <winioctl.h>
int __cdecl _tmain(int argc, PTSTR *argv)
{
HANDLE h = CreateFile(argv[1], 0,
                FILE_SHARE_READ | FILE_SHARE_WRITE |
                FILE_SHARE_DELETE, NULL,
                OPEN_EXISTING, 0, NULL);
if (h != INVALID_HANDLE_VALUE) {
 FILE_OBJECTID_BUFFER buf;
 DWORD cbOut;
 if (DeviceIoControl(h, FSCTL_CREATE_OR_GET_OBJECT_ID,
                NULL, 0, &buf, sizeof(buf),
                &cbOut, NULL)) {
   GUID guid;
   CopyMemory(&guid, &buf.ObjectId, sizeof(GUID));
   WCHAR szGuid[39];
   StringFromGUID2(guid, szGuid, 39);
   _tprintf(_T("GUID is %ws\n"), szGuid);
 }
 CloseHandle(h);
}
return 0;
}

This program takes a file or directory name as its sole parameter and prints the associated object identifier.
Big deal, now we have a GUID associated with each file.
The other half is, of course, using this GUID to open the file:

#define UNICODE
#define _UNICODE
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <ole2.h>
int __cdecl _tmain(int argc, PTSTR *argv)
{
HANDLE hRoot = CreateFile(_T("C:\\"), 0,
                FILE_SHARE_READ | FILE_SHARE_WRITE |
                FILE_SHARE_DELETE, NULL,
                OPEN_EXISTING,
                FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (hRoot != INVALID_HANDLE_VALUE) {
 FILE_ID_DESCRIPTOR desc;
 desc.dwSize = sizeof(desc);
 desc.Type = ObjectIdType;

Read more: The old new thing