{"id":5853,"date":"2012-12-12T07:00:00","date_gmt":"2012-12-12T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2012\/12\/12\/how-am-i-supposed-to-free-the-information-returned-by-the-getsecurityinfo-function\/"},"modified":"2012-12-12T07:00:00","modified_gmt":"2012-12-12T07:00:00","slug":"how-am-i-supposed-to-free-the-information-returned-by-the-getsecurityinfo-function","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20121212-00\/?p=5853","title":{"rendered":"How am I supposed to free the information returned by the GetSecurityInfo function?"},"content":{"rendered":"<p>\n<a HREF=\"http:\/\/msdn.microsoft.com\/en-us\/library\/aa446654.aspx\">\nThe <code>Get&shy;Security&shy;Info<\/code> function<\/a>\nreturns a copy of the security descriptor for a kernel object,\nalong with pointers to specific portions you request.\nMore than once, a customer has been confused by the\nguidelines for how to manage the memory returned by the function.\n<\/p>\n<p>\nLet&#8217;s look at what the function says:\n<\/p>\n<blockquote CLASS=\"q\">\n<dl>\n<dt><i>ppsidOwner<\/i> [out, optional]<\/p>\n<dd>A pointer to a variable that receives a pointer to the owner SID\n    in the security descriptor returned in\n    <i>ppSecurity&shy;Descriptor<\/i>.\n    The returned pointer is valid only if you set the\n    <code>OWNER_SECURITY_INFORMATION<\/code>\n    flag.\n    This parameter can be NULL if you do not need the owner SID.\n<\/dl>\n<\/blockquote>\n<p>\nSimilar verbiage can be found for the other subcomponent\nparameters.\nThe final parameter is described as\n<\/p>\n<blockquote CLASS=\"q\">\n<dl>\n<dt><i>ppSecurity&shy;Descriptor<\/i> [out, optional]<\/p>\n<dd>A pointer to a variable that receives a pointer to the security\n    descriptor of the object.\n    When you have finished using the pointer, free the returned\n    buffer by calling the <b>Local&shy;Free<\/b> function.\n<\/dl>\n<\/blockquote>\n<p>\nOkay, so it&#8217;s clear that you need to free the security descriptor\nwith <code>Local&shy;Free<\/code>.\nBut how do you free the owner, group, DACL, and SACL?\n<\/p>\n<p>\nRead the documentation again.\nI&#8217;ve underlined the important part.\n<\/p>\n<blockquote CLASS=\"q\">\n<dl>\n<dt><i>ppsidOwner<\/i> [out, optional]<\/p>\n<dd>A pointer to a variable that receives a pointer to the owner SID\n    <u>in the security descriptor returned in\n    <i>ppSecurity&shy;Descriptor<\/i><\/u>.\n    The returned pointer is valid only if you set the\n    <code>OWNER_SECURITY_INFORMATION<\/code>\n    flag.\n    This parameter can be NULL if you do not need the owner SID.\n<\/dl>\n<\/blockquote>\n<p>\nIn case that wasn&#8217;t clear, the point is reiterated in the remarks.\n<\/p>\n<blockquote CLASS=\"q\"><p>\nIf the <i>ppsidOwner<\/i>,\n<i>ppsidGroup<\/i>,\n<i>ppDacl<\/i>,\nand\n<i>ppSacl<\/i> parameters are non-NULL,\nand the\n<i>Security&shy;Info<\/i> parameter specifies that they be retrieved\nfrom the object,\nthose parameters will point to the corresponding parameters\nin the security descriptor returned in\n<i>ppSecurity&shy;Descriptor<\/i>.\n<\/p><\/blockquote>\n<p>\nIn other words, you are getting a pointer\n<i>into the security descriptor<\/i>.\nNo separate memory allocation is made.\nThe memory for the owner SID is freed when you free the security\ndescriptor.\nIt&#8217;s like the last parameter to <code>Get&shy;Full&shy;Path&shy;Name<\/code>,\nwhich receives a pointer to the file part of the full path.\nThere is no separate memory allocation for that pointer;\nit&#8217;s just a pointer back into the main buffer.\n<\/p>\n<p>\nYou can think of the\n<code>ppsidOwner<\/code> parameter\nas a convenience parameter.\nThe <code>Get&shy;Security&shy;Info<\/code> function\noffers to do the work of calling\n<code>Get&shy;Security&shy;Descriptor&shy;Owner<\/code>\nfor you.\nYou can think of the function as operating like this:\n<\/p>\n<pre>\nDWORD WINAPI GetSecurityInfo(...)\n{\n    ... blah blah get the security info ...\n    \/\/ Just out of courtesy:\n    \/\/ Fetch the owner if the caller requested it\n    if (ppsidOwner != NULL &amp;&amp;\n        (SecurityInfo &amp; OWNER_SECURITY_INFO)) {\n        BOOL fDefaulted;\n        GetSecurityDescriptorOwner(pSecurityDescriptor,\n                                   ppsidOwner,\n                                   &amp;fDefaulted);\n    }\n    ...\n}\n<\/pre>\n<p>\nThat&#8217;s why the documentation says that you need to pass\na non-null\n<code>ppSecurity&shy;Descriptor<\/code>\nif you request any of the pieces of the security descriptor:\nIf you don&#8217;t, then you won&#8217;t be able to free the memory for it.\n<\/p>\n<p>\n<b>Bonus chatter<\/b>:\nIf the\n<code>ppSecurity&shy;Descriptor<\/code>\nis so important,\nwhy is it marked &#8220;optional&#8221;?\n<\/p>\n<p>\nIt really should be a mandatory parameter,\nbut older versions of Windows didn&#8217;t enforce the rule,\nso the parameter is grandfathered in as optional,\neven though no self-respecting program should ever\npass in <code>NULL<\/code>.\nIf you pass <code>NULL<\/code> for the\n<code>ppSecurity&shy;Descriptor<\/code>,\nthe function happily allocates the security descriptor\nand then, &#8220;Oh wait, the caller didn&#8217;t give me a way to\nreceive the pointer to the security descriptor,\nso I guess I won&#8217;t give it to him.&#8221;\n<\/p>\n<pre>\nDWORD WINAPI GetSecurityInfo(...)\n{\n    ... blah blah get the security info ...\n    if (ppSecurityDescriptor != NULL) {\n        *ppSecurityDescriptor = pSecurityDescriptor;\n    }\n    ...\n}\n<\/pre>\n<p>\nResult: Memory leak.\n<\/p>\n<p>\nYou might say that the last parameter was designed by somebody\nwearing\n<a HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2011\/05\/12\/10163578.aspx\">\nkernel-colored glasses<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The Get&shy;Security&shy;Info function returns a copy of the security descriptor for a kernel object, along with pointers to specific portions you request. More than once, a customer has been confused by the guidelines for how to manage the memory returned by the function. Let&#8217;s look at what the function says: ppsidOwner [out, optional] A pointer [&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-5853","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>The Get&shy;Security&shy;Info function returns a copy of the security descriptor for a kernel object, along with pointers to specific portions you request. More than once, a customer has been confused by the guidelines for how to manage the memory returned by the function. Let&#8217;s look at what the function says: ppsidOwner [out, optional] A pointer [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/5853","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=5853"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/5853\/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=5853"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=5853"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=5853"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}