{"id":25363,"date":"2007-08-29T10:00:00","date_gmt":"2007-08-29T10:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2007\/08\/29\/kernel-handles-are-not-reference-counted\/"},"modified":"2007-08-29T10:00:00","modified_gmt":"2007-08-29T10:00:00","slug":"kernel-handles-are-not-reference-counted","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20070829-00\/?p=25363","title":{"rendered":"Kernel handles are not reference-counted"},"content":{"rendered":"<p>\nHere&#8217;s a question that floated past some time ago:\n<\/p>\n<blockquote CLASS=\"q\"><p>\nIn my code, I have multiple objects that want to talk to the\nsame handle (via <code>DeviceIoControl<\/code>).\nEach time I create an object, I use <code>DuplicateHandle<\/code>\nto increment the reference count on the handle.\nThat way, when each object calls <code>CloseHandle<\/code>,\nonly the last one actually closes the handle.\nHowever, when I run the code, I find as soon as the first object\ncalls <code>CloseHandle<\/code>, the handle is no longer valid\nand nobody else can use it.\nWhat flags do I need to pass to <code>CreateFile<\/code> to get\nthis to work?\n<\/p><\/blockquote>\n<p>\nIn other words, the code went something like this:\n<\/p>\n<pre>\n<i>\/\/ h is the handle that we want to share with a new CFred object\nCFred *MakeFred(HANDLE h)\n{\n \/\/ \"Duplicate the handle to bump the reference count\"\n \/\/ This code is wrong - see discussion\n \/\/ All error checking removed for expository purposes\n HANDLE hDup;\n DuplicateHandle(GetCurrentProcess(), h,\n                 GetCurrentProcess(), &amp;hDup,\n                 0, FALSE, DUPLICATE_SAME_ACCESS);\n return new CFred(h);\n}<\/i>\n<\/pre>\n<p>\nKernel handles aren&#8217;t reference-counted.\nWhen you call <code>CloseHandle<\/code>,\nthat closes the handle, end of story.\n<\/p>\n<p>\nFrom the original problem statement, we know that\nthe <code>CFred<\/code> object closes the handle when it\nis destroyed.\nJust for argument&#8217;s sake, let&#8217;s say that the caller goes\nsomething like this:\n<\/p>\n<pre>\nCFred *pfred1 = MakeFred(h);\nCFred *pfred2 = MakeFred(h);\ndelete pfred1;\ndelete pfred2;\n<\/pre>\n<p>\nWhat actually happens when you run this fragment?\n<\/p>\n<p>\nThe first time we call <code>MakeFred<\/code> we take\nthe original handle <code>h<\/code> and duplicate it,\nbut we give the original handle to the <code>CFred<\/code>\nconstructor and leak the <code>hDup<\/code>!\nThe original poster assumed that duplicating a handle merely\nincremented the handle&#8217;s imaginary reference count,\nso that <code>h == hDup<\/code>.\n(Which would also have made the original poster wonder why\nwe even bother having a <code>lpTargetHandle<\/code> parameter\nin the first place.)\n<\/p>\n<p>\nWhen <code>pfred1<\/code> is deleted, it closes its handle,\nwhich is <code>h<\/code>.\nThis closes the <code>h<\/code> handle and renders it invalid\nand available to be recycled for another <code>CreateFile<\/code>\nor other operation that creates a handle.\n<\/p>\n<p>\nWhen <code>pfred2<\/code> is deleted, it also closes its handle,\nwhich is still <code>h<\/code>.\nThis is now closing an already-close handle,\nwhich is an error.\nIf we had bothered calling a method on <code>pfred2<\/code> that\nused the handle, it would have gotten failures from those operations\nas well, since the handle is no longer valid.\n(Well, if we&#8217;re lucky, we would have gotten a failure.\nIf we were unlucky, the handle would have been recycled and\nwe ended up performing a <code>DeviceIoControl<\/code> on somebody\nelse&#8217;s handle!)\n<\/p>\n<p>\nMeanwhile, the calling code&#8217;s copy of <code>h<\/code> is also bad,\nsince <code>pfred1<\/code> closed it when it was deleted.\n<\/p>\n<p>\nWhat we really want to do here is duplicate the handle\nand pass the <strong>duplicate<\/strong> to each object.\nThe <code>DuplicateHandle<\/code> function creates a new\nhandle that refers to the same object as the original handle.\nThat new handle can be closed without affecting the original handle.\n<\/p>\n<pre>\n\/\/ h is the handle that we want to share with a new CFred object\nCFred *MakeFred(HANDLE h)\n{\n \/\/ Create another handle that refers to the same object as \"h\"\n \/\/ All error checking removed for expository purposes\n HANDLE hDup;\n DuplicateHandle(GetCurrentProcess(), h,\n                 GetCurrentProcess(), &amp;hDup,\n                 0, FALSE, DUPLICATE_SAME_ACCESS);\n return new CFred(<font COLOR=\"blue\">hDup<\/font>);\n}\n<\/pre>\n<p>\nThe fix is one word, highlighted in blue.\nWe give the duplicated handle to the <code>CFred<\/code> object.\nThat way, it gets its own handle which it is free to close\nany time it wants, and it won&#8217;t affect anybody else&#8217;s handle.\n<\/p>\n<p>\nYou can think of <code>DuplicateHandle<\/code> as a sort of\n<code>AddRef<\/code> for kernel objects.\nEach time you duplicate a handle, the reference count on the\nkernel object goes up by one, and you gain a new reference\n(the new handle).\nEach time you close a handle, the reference count on the kernel\nobject drops by one.\n<\/p>\n<p>\nIn summary, a handle is not a reference-counted object.\nWhen you close a handle, it&#8217;s gone.\nWhen you duplicate a handle, you gain a new obligation to\nclose the duplicate, in addition to the existing obligation\nto close the original handle.\nThe duplicate handle refers to the same object as the original handle,\nand it is the underlying object that is reference-counted.\n(Note that kernel objects can have reference from things\nthat aren&#8217;t handles.\nFor example, an executing thread maintains a reference to the underlying\nthread object.\nClosing the last handle to a thread will not destroy the thread object\nbecause the thread keeps a reference to itself as long as it&#8217;s running.)<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Here&#8217;s a question that floated past some time ago: In my code, I have multiple objects that want to talk to the same handle (via DeviceIoControl). Each time I create an object, I use DuplicateHandle to increment the reference count on the handle. That way, when each object calls CloseHandle, only the last one actually [&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":[25],"class_list":["post-25363","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Here&#8217;s a question that floated past some time ago: In my code, I have multiple objects that want to talk to the same handle (via DeviceIoControl). Each time I create an object, I use DuplicateHandle to increment the reference count on the handle. That way, when each object calls CloseHandle, only the last one actually [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/25363","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=25363"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/25363\/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=25363"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=25363"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=25363"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}