{"id":92701,"date":"2015-12-23T07:00:00","date_gmt":"2015-12-23T22:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/?p=92701"},"modified":"2019-03-13T12:23:09","modified_gmt":"2019-03-13T19:23:09","slug":"20151223-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20151223-00\/?p=92701","title":{"rendered":"Confusing gotcha: PSECURITY_DESCRIPTOR is not a pointer to a SECURITY_DESCRIPTOR"},"content":{"rendered":"<p>There is a structure called a <code>SECURITY_DESCRIPTOR<\/code>. It describes the layout of an absolute security descriptor. <\/p>\n<p>There is also a structure called a <code>SECURITY_DESCRIPTOR_RELATIVE<\/code>. It describes the layout of a relative security descriptor. <\/p>\n<p>And then there is a type called <code>PSECURITY_DESCRIPTOR<\/code>. You might think based on its name that it is a pointer to a <code>SECURITY_DESCRIPTOR<\/code>. But it&#8217;s not. It is defined as <\/p>\n<pre>\ntypedef PVOID PSECURITY_DESCRIPTOR;\n\/\/ equivalent to\n\/\/ typedef void *PSECURITY_DESCRIPTOR;\n<\/pre>\n<\/p>\n<p>Most code that accept security descriptors don&#8217;t care whether the security descriptor is absolute or relative. They just pass the security descriptor through to functions like <code>Access&shy;Check<\/code>. And the name for a generic &#8220;pointer to some type of security descriptor, maybe relative, maybe absolute&#8221; is <code>PSECURITY_DESCRIPTOR<\/code>. <\/p>\n<p>You rarely notice this switcheroo because code that deals with security descriptors typically use helper functions to do the heavy lifting. You notice this problem if you try to use something like <code>std::unique_ptr<\/code> to manage the lifetime of a security descriptor. <\/p>\n<pre>\ntemplate&lt;typename T&gt;\nstruct LocalAlloc_delete\n{\n LocalAlloc_delete() { }\n void operator()(T* p) throw() { LocalFree(p); }\n};\n\ntemplate&lt;typename T&gt;\nusing unique_localptr = std::unique_ptr&lt;T, LocalAlloc_delete&lt;T&gt;&gt;;\n\nvoid some_function()\n{\n PSECURITY_DESCRIPTOR result;\n ConvertStringSecurityDescriptorToSecurityDescriptorW(\n  L\"O:AOG:DAD:(A;;RPWPCCDCLCSWRCWDWOGA;;;S-1-0-0)\",\n  SDDL_REVISION_1, &amp;result, nullptr);\n\n <font COLOR=\"blue\">\/\/ compiler error here\n unique_localptr&lt;SECURITY_DESCRIPTOR&gt; sd(result);<\/font>\n\n .. do stuff with sd ...\n}\n<\/pre>\n<p>The compiler complains because <code>result<\/code> is a <code>PSECURITY_DESCRIPTOR<\/code>, but it expects a <code>SECURITY_DESCRIPTOR*<\/code>. <\/p>\n<p>I can&#8217;t think of a clean way out of this. Here are some ugly ways out: <\/p>\n<pre>\n\/\/ ugly option 1 - cast it away\nunique_localptr&lt;SECURITY_DESCRIPTOR&gt;\n    sd(reinterpret_cast&lt;SECURITY_DESCRIPTOR*&gt;(result));\n\n\/\/ ugly option 2 - special knowledge about PSECURITY_DESCRIPTOR\nunique_localptr&lt;void&gt; sd(result);\n\n\/\/ ugly option 3 - general, but an awful lot of typing\n unique_localptr&lt;\n    std::remove_pointer&lt;PSECURITY_DESCRIPTOR&gt;::type&gt; sd(result);\n<\/pre>\n<p>In retrospect, the structure for an absolute security descriptor should have been named <code>SECURITY_DESCRIPTOR_ABSOLUTE<\/code>. My guess is that the name is historical: Initially, the only kind of security descriptor was absolute. Later, relative security descriptors were invented, and the easiest way to retrofit them into the existing interfaces was to make <code>PSECURITY_DESCRIPTOR<\/code> the generic security descriptor pointer. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>It&#8217;s just an untyped pointer.<\/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-92701","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>It&#8217;s just an untyped pointer.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/92701","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=92701"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/92701\/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=92701"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=92701"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=92701"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}