{"id":11363,"date":"2011-02-28T07:00:00","date_gmt":"2011-02-28T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2011\/02\/28\/if-you-want-to-use-guids-to-identify-your-files-then-nobodys-stopping-you\/"},"modified":"2011-02-28T07:00:00","modified_gmt":"2011-02-28T07:00:00","slug":"if-you-want-to-use-guids-to-identify-your-files-then-nobodys-stopping-you","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20110228-00\/?p=11363","title":{"rendered":"If you want to use GUIDs to identify your files, then nobody&#039;s stopping you"},"content":{"rendered":"<p>\nIgor Levicki proposes solving the problem of file extensions by\n<a HREF=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2007\/12\/17\/6785519.aspx#6793266\">\nusing a GUID instead of a file name to identify a file<\/a>.\n<\/p>\n<p>\nYou can do this already.\nEvery file on an NTFS volume has an <i>object identifier<\/i>\nwhich is formally 16-byte buffer, but let&#8217;s just call it a GUID.\nBy default a file doesn&#8217;t have an object identifier,\nbut you can ask for one to be created with\n<code>FSCTL_CREATE_OR_GET_OBJECT_ID<\/code>,\nwhich will retrieve the existing object identifier associated with\na file, or create one if there isn&#8217;t one already.\nIf you are a control freak, you can use\n<code>FSCTL_SET_OBJECT_ID<\/code> to specify the GUID you want to use\nas the object identifier.\n(The call fails if the file already has an object identifier.)\nAnd of course there is\n<code>FSCTL_GET_OBJECT_ID<\/code> to retrieve the object identifier, if any.\n<\/p>\n<pre>\n#define UNICODE\n#define _UNICODE\n#include &lt;windows.h&gt;\n#include &lt;stdio.h&gt;\n#include &lt;tchar.h&gt;\n#include &lt;ole2.h&gt;\n#include &lt;winioctl.h&gt;\nint __cdecl _tmain(int argc, PTSTR *argv)\n{\n HANDLE h = CreateFile(argv[1], 0,\n                 FILE_SHARE_READ | FILE_SHARE_WRITE |\n                 FILE_SHARE_DELETE, NULL,\n                 OPEN_EXISTING, 0, NULL);\n if (h != INVALID_HANDLE_VALUE) {\n  FILE_OBJECTID_BUFFER buf;\n  DWORD cbOut;\n  if (DeviceIoControl(h, FSCTL_CREATE_OR_GET_OBJECT_ID,\n                 NULL, 0, &amp;buf, sizeof(buf),\n                 &amp;cbOut, NULL)) {\n    GUID guid;\n    CopyMemory(&amp;guid, &amp;buf.ObjectId, sizeof(GUID));\n    WCHAR szGuid[39];\n    StringFromGUID2(guid, szGuid, 39);\n    _tprintf(_T(\"GUID is %ws\\n\"), szGuid);\n  }\n  CloseHandle(h);\n }\n return 0;\n}\n<\/pre>\n<p>\nThis program takes a file or directory name\nas its sole parameter and prints the associated object identifier.\n<\/p>\n<p>\nBig deal, now we have a GUID associated with each file.\n<\/p>\n<p>\nThe other half is, of course, using this GUID to open the file:\n<\/p>\n<pre>\n#define UNICODE\n#define _UNICODE\n#include &lt;windows.h&gt;\n#include &lt;stdio.h&gt;\n#include &lt;tchar.h&gt;\n#include &lt;ole2.h&gt;\nint __cdecl _tmain(int argc, PTSTR *argv)\n{\n HANDLE hRoot = CreateFile(_T(\"C:\\\\\"), 0,\n                 FILE_SHARE_READ | FILE_SHARE_WRITE |\n                 FILE_SHARE_DELETE, NULL,\n                 OPEN_EXISTING,\n                 FILE_FLAG_BACKUP_SEMANTICS, NULL);\n if (hRoot != INVALID_HANDLE_VALUE) {\n  FILE_ID_DESCRIPTOR desc;\n  desc.dwSize = sizeof(desc);\n  desc.Type = ObjectIdType;\n  if (SUCCEEDED(CLSIDFromString(argv[1], &amp;desc.ObjectId))) {\n   HANDLE h = OpenFileById(hRoot, &amp;desc, GENERIC_READ,\n                 FILE_SHARE_READ | FILE_SHARE_WRITE |\n                 FILE_SHARE_DELETE, NULL, 0);\n   if (h != INVALID_HANDLE_VALUE) {\n    BYTE b;\n    DWORD cb;\n    if (ReadFile(h, &amp;b, 1, &amp;cb, NULL)) {\n     _tprintf(_T(\"First byte of file is 0x%02x\\n\"), b);\n    }\n    CloseHandle(h);\n   }\n  }\n  CloseHandle(hRoot);\n }\n return 0;\n}\n<\/pre>\n<p>\nTo open a file by its GUID, you first need to open\nsomething&mdash;anything&mdash;on the volume the file resides on.\nDoesn&#8217;t matter what you open;\nthe only reason for having this handle is so that\n<code>OpenFileById<\/code> knows which volume you&#8217;re talking about.\nIn our little test program, we use the C: drive,\nwhich means that the file search will take place on the\nC: drive.\n<\/p>\n<p>\nNext, you fill in the <code>FILE_ID_DESCRIPTOR<\/code>,\nsaying that you want to open the file by its object identifier,\nand then it&#8217;s off to the races with <code>OpenFileById<\/code>.\nJust as a proof of concept, we read and print the first byte\nof the file that was opened as a result.\n<\/p>\n<p>\nNotice that the file you open by its object identifier does not\nhave to be in the current directory.\nIt can be <i>anywhere on the C: drive<\/i>.\nAs long as you have the GUID for a file, you can open it\nno matter where it is on the drive.\n<\/p>\n<p>\nYou can run these two programs just to enjoy the thrill of\nopening a file by its GUID.\nNotice that once you get the GUID for a file, you can move\nit anywhere on the drive, and <code>OpenFileById<\/code>\nwill still open it.\n<\/p>\n<p>\n(And if you want to get rid of those pesky drive letters,\nyou can use the volume GUID instead.\nNow every file is identified by a pair of GUIDs:\nthe volume GUID and the object identifier.)\n<\/p>\n<p>\nSo Igor&#8217;s dream world where all files are referenced by GUID\nalready exists.\nWhy isn&#8217;t everybody switching over to this utopia of GUID-based\nfile identification?\n<\/p>\n<p>\nYou probably know the answer already:\nBecause people prefer to name things with something mnemonic\nrather than a GUID.\nImagine a file open dialog in this dream world.\n&#8220;Enter the GUID of the file you wish to open, or click Browse\nto see the GUIDs of all the files on this volume so you can pick\nfrom a list.&#8221;\nHow long would this dialog survive?\n<\/p>\n<p>\nFor today, you don&#8217;t have to call me Raymond.\nYou can call me\n<a HREF=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2004\/03\/15\/89753.aspx\">\n{7ecf65a0-4b78-5f9b-e77c-8770091c0100}<\/a>,\nor &#8220;91c&#8221; for short.\n<\/p>\n<p>\n(And I&#8217;ve totally ignored the fact that\nusing GUIDs to identify files does nothing\nto solve the problem of trying to figure out what program should be\nused to open a particular file.)\n<\/p>\n<p><p>\n<b>Bonus chatter<\/b>:\nYou can also open files by their file identifer, which is a\nvolume-specific 64-bit value.\nBut I chose to use the GUID both for the extra challenge,\nand just to show that Igor&#8217;s dream world already exists.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>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&#8217;s just call it a GUID. By default a file doesn&#8217;t have [&hellip;]<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[26],"class_list":["post-11363","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-other"],"acf":[],"blog_post_summary":"<p>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&#8217;s just call it a GUID. By default a file doesn&#8217;t have [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/11363","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=11363"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/11363\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=11363"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=11363"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=11363"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}