{"id":102299,"date":"2004-07-05T07:00:00","date_gmt":"2004-07-05T14:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2004\/07\/05\/whats-the-difference-between-shgetmalloc-shalloc-cogetmalloc-and-cotaskmemalloc\/"},"modified":"2004-07-05T07:00:00","modified_gmt":"2004-07-05T14:00:00","slug":"whats-the-difference-between-shgetmalloc-shalloc-cogetmalloc-and-cotaskmemalloc-2","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20040705-00\/?p=102299","title":{"rendered":"What&#8217;s the difference between SHGetMalloc, SHAlloc, CoGetMalloc, and CoTaskMemAlloc"},"content":{"rendered":"<p>\nLet&#8217;s get the easy ones out of the way.\n<\/p>\n<p>\nFirst,\n<a HREF=\"http:\/\/msdn.microsoft.com\/library\/en-us\/com\/htm\/cmf_a2c_9bj7.asp\">\nCoTaskMemAlloc<\/a> is exactly the same as\n<a HREF=\"http:\/\/msdn.microsoft.com\/library\/en-us\/com\/htm\/cmf_a2c_2qlf.asp\">\nCoGetMalloc<\/a>(MEMCTX_TASK) +\n<a HREF=\"http:\/\/msdn.microsoft.com\/library\/en-us\/com\/htm\/cmi_m_3twj.asp\">\nIMalloc::Alloc<\/a>,\nand\n<a HREF=\"http:\/\/msdn.microsoft.com\/library\/en-us\/com\/htm\/cmf_a2c_63l1.asp\">\nCoTaskMemFree<\/a> is the same as\nCoGetMalloc(MEMCTX_TASK) +\n<a HREF=\"http:\/\/msdn.microsoft.com\/library\/en-us\/com\/htm\/cmi_m_1smd.asp\">\nIMalloc::Free<\/a>.\nCoTaskMemAlloc and CoTaskMemFree (and the less-used\n<a HREF=\"http:\/\/msdn.microsoft.com\/library\/en-us\/com\/htm\/cmf_a2c_3lpf.asp\">\nCoTaskMemRealloc<\/a>)\nare just convenience functions that save you the trouble of having to\nmess with CoGetMalloc yourself.\nConsequently, you can safely allocate memory via\nCoGetMalloc(MEMCTX_TASK) + IMalloc::Alloc, and then free it with\nCoTaskMemFree, and vice versa.  It&#8217;s all the same allocator.\n<\/p>\n<p>\nSimilarly,\n<a HREF=\"http:\/\/msdn.microsoft.com\/library\/en-us\/shellcc\/platform\/shell\/reference\/functions\/shalloc.asp\">SHAlloc<\/a>\nand\n<a HREF=\"http:\/\/msdn.microsoft.com\/library\/en-us\/shellcc\/platform\/shell\/reference\/functions\/SHFree.asp\">\nSHFree<\/a>\nare just wrappers around\n<a HREF=\"http:\/\/msdn.microsoft.com\/library\/en-us\/shellcc\/platform\/shell\/reference\/functions\/shgetmalloc.asp\">\nSHGetMalloc<\/a>\nwhich allocate\/free the memory via the shell task allocator.\nMemory you allocated via SHGetMalloc + IMalloc::Alloc can be freed\nwith SHFree.\n<\/p>\n<p>\nSo far, we have this diagram.\n<\/p>\n<table BORDER=\"0\">\n<tr>\n<td ALIGN=\"center\" COLSPAN=\"3\" STYLE=\"border-top: solid .75pt black;border-left: solid .75pt black;border-right: solid .75pt black\">Shell task allocator\n    <\/td>\n<td><\/td>\n<td ALIGN=\"center\" COLSPAN=\"3\" STYLE=\"border-top: solid .75pt black;border-left: solid .75pt black;border-right: solid .75pt black\">OLE task allocator\n    <\/td>\n<\/tr>\n<tr>\n<td COLSPAN=\"7\" HEIGHT=\"3\"><\/td>\n<\/tr>\n<tr>\n<td STYLE=\"border: solid .75pt black\">SHAlloc\/<br \/>SHFree<\/td>\n<td>=<\/td>\n<td STYLE=\"border: solid .75pt black\">SHGetMalloc<\/td>\n<td>&nbsp;<font SIZE=\"+3\">??<\/font>&nbsp;<\/td>\n<td STYLE=\"border: solid .75pt black\">CoGetMalloc<\/td>\n<td>=<\/td>\n<td STYLE=\"border: solid .75pt black\">CoTaskMemAlloc\/<br \/>CoTaskMemFree<\/td>\n<\/tr>\n<\/table>\n<p>\nNow what about those question marks?\n<\/p>\n<p>\nIf you read the comments in shlobj.h, you may get a bit of a hint:\n<\/p>\n<pre>\n\/\/===========================================================================\n\/\/\n\/\/ Task allocator API\n\/\/\n\/\/  All the shell extensions MUST use the task allocator (see OLE 2.0\n\/\/ programming guild for its definition) when they allocate or free\n\/\/ memory objects (mostly ITEMIDLIST) that are returned across any\n\/\/ shell interfaces. There are two ways to access the task allocator\n\/\/ from a shell extension depending on whether or not it is linked with\n\/\/ OLE32.DLL or not (purely for efficiency).\n\/\/\n\/\/ (1) A shell extension which calls any OLE API (i.e., linked with\n\/\/  OLE32.DLL) should call OLE's task allocator (by retrieving\n\/\/  the task allocator by calling CoGetMalloc API).\n\/\/\n\/\/ (2) A shell extension which does not call any OLE API (i.e., not linked\n\/\/  with OLE32.DLL) should call the shell task allocator API (defined\n\/\/  below), so that the shell can quickly loads it when OLE32.DLL is not\n\/\/  loaded by any application at that point.\n\/\/\n\/\/ Notes:\n\/\/  In next version of Windowso release, SHGetMalloc will be replaced by\n\/\/ the following macro.\n\/\/\n\/\/ #define SHGetMalloc(ppmem)   CoGetMalloc(MEMCTX_TASK, ppmem)\n\/\/\n\/\/===========================================================================\n<\/pre>\n<p>\n(Yes, those typos &#8220;guild&#8221; and &#8220;Windowso&#8221; have been there since 1995.)\n<\/p>\n<p>\nThis discussion strongly hints at what&#8217;s going on.\n<\/p>\n<p>\nWhen Windows&nbsp;95 was being developed, computers typically had\njust 4MB of memory.  (The cool people got 8MB.)\nBut Explorer was also heavily reliant upon COM for its shell extension\narchitecture, and loading OLE32.DLL into memory was a significant kick\nin the teeth.  Under such tight memory conditions,\n<a HREF=\"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/archive\/2003\/10\/10\/55256.aspx\">\neven the loss of 4K of memory was noticeable<\/a>.\n<\/p>\n<p>\nThe solution: Play &#8220;OLE Chicken&#8221;.\n<\/p>\n<p>\nThe shell, it turns out, didn&#8217;t use very much of COM:\nThe only objects it supported were in-process apartment-threaded\nobjects with no marshalling.\nSo the shell team wrote a &#8220;mini-COM&#8221; that supported only those operations\nand use it instead of the real thing.\n(It helped that one of the high-ranking members of\nthe shell team was a COM super-expert.)\nThe shell had\n<a HREF=\"http:\/\/msdn.microsoft.com\/library\/en-us\/shellcc\/platform\/shell\/reference\/functions\/shgetmalloc.asp\">\nits own miniature task allocator<\/a>,\n<a HREF=\"http:\/\/msdn.microsoft.com\/library\/en-us\/shellcc\/platform\/shell\/reference\/functions\/shcocreateinstance.asp\">\nits own miniature binder<\/a>,\n<a HREF=\"http:\/\/msdn.microsoft.com\/library\/en-us\/shellcc\/platform\/shell\/reference\/functions\/shdodragdrop.asp\">\nits own miniature drag-drop loop<\/a>,\neverything it needed <strong>provided<\/strong>\nyou didn&#8217;t run any other programs that used OLE32.\n<\/p>\n<p>\nOnce some other program that used OLE32 started running, you\nhad a problem: There were now two separate versions of OLE in the system:\nthe real thing and the fake version inside the shell.\nUnless something was done, you wouldn&#8217;t be able to interoperate\nbetween real-COM and fake-shell-COM.\nFor example, you wouldn&#8217;t be able to drag\/drop data between Explorer\n(using fake-shell-COM)\nand a window that was using real-COM.\n<\/p>\n<p>\nThe solution: With the help of other parts of the system, the shell detected\nthat &#8220;COM is now in the building&#8221; once anybody loaded OLE32.DLL,\nand it and transferred all the information\nit had been managing on its own into the world of real COM.\nOnce it did this, all the shell pseudo-COM functions switched to\nreal-COM as well.\nFor example, once OLE32.DLL got loaded, calls to the shell&#8217;s\nfake-task-allocator just went to the real task allocator.\n<\/p>\n<p>\nBut what is &#8220;OLE Chicken&#8221;?\nThis is another variation of the various\n&#8220;chicken&#8221;-type games, perhaps the most famous of which is\n<a HREF=\"https:\/\/web.archive.org\/web\/20040729081330\/http:\/\/msdn.microsoft.com\/library\/en-us\/dnstone\/html\/stone041999.asp\">\nSchedule Chicken<\/a>.\nIn &#8220;OLE Chicken&#8221;, each program would avoid loading OLE32.DLL\nas long as possible, so that it wouldn&#8217;t be the one blamed for\nthe long pause\nas OLE32.DLL got itself off the ground and ready for action.\n(Remember, we&#8217;re talking 1995-era machines where allocating 32K would\nbring the wrath of the performance team upon your head.)\n<\/p>\n<p>\nOkay, so let&#8217;s look at that comment block again.\n<\/p>\n<p>\nThe opening paragraph mentions the possibility that a shell extension\ndoes not itself link with OLE32.DLL.\nOption&nbsp;(1) discusses a shell extension that does use OLE32,\nin which case it should use the official OLE functions like\nCoGetMalloc.\nBut Option&nbsp;(2) discusses a shell extension that does not use OLE32.\nThose shell extensions are directed to use the shell&#8217;s fake-COM functions\nlike SHGetMalloc, instead of the real-COM functions, so that no new\ndependency on OLE32 is created.\nTherefore, if OLE32 is not yet loaded, loading these\nshell extensions will also not cause OLE32 to be loaded,\nthereby saving the cost of loading and initializing OLE32.DLL.\n<\/p>\n<p>\nSo the completion of our diagram for 1995-era programs would be\nsomething like this:\n<\/p>\n<div STYLE=\"padding-left: 3em\">\n<p>\nBefore OLE32.DLL is loaded:\n<\/p>\n<table BORDER=\"0\">\n<tr>\n<td ALIGN=\"center\" COLSPAN=\"3\" STYLE=\"border-top: solid .75pt black;border-left: solid .75pt black;border-right: solid .75pt black\">Shell task allocator\n    <\/td>\n<td><\/td>\n<td ALIGN=\"center\" COLSPAN=\"3\" STYLE=\"border-top: solid .75pt black;border-left: solid .75pt black;border-right: solid .75pt black\">OLE task allocator\n    <\/td>\n<\/tr>\n<tr>\n<td COLSPAN=\"7\" HEIGHT=\"3\"><\/td>\n<\/tr>\n<tr>\n<td STYLE=\"border: solid .75pt black\">SHAlloc\/<br \/>SHFree<\/td>\n<td>=<\/td>\n<td STYLE=\"border: solid .75pt black\">SHGetMalloc<\/td>\n<td>&nbsp;<font SIZE=\"+3\">&ne;<\/font>&nbsp;<\/td>\n<td STYLE=\"border: solid .75pt black\">CoGetMalloc<\/td>\n<td>=<\/td>\n<td STYLE=\"border: solid .75pt black\">CoTaskMemAlloc\/<br \/>CoTaskMemFree<\/td>\n<\/tr>\n<\/table>\n<p>\nAfter OLE32.DLL is loaded:\n<\/p>\n<table BORDER=\"0\">\n<tr>\n<td ALIGN=\"center\" COLSPAN=\"3\" STYLE=\"border-top: solid .75pt black;border-left: solid .75pt black;border-right: solid .75pt black\">Shell task allocator\n    <\/td>\n<td><\/td>\n<td ALIGN=\"center\" COLSPAN=\"3\" STYLE=\"border-top: solid .75pt black;border-left: solid .75pt black;border-right: solid .75pt black\">OLE task allocator\n    <\/td>\n<\/tr>\n<tr>\n<td COLSPAN=\"7\" HEIGHT=\"3\"><\/td>\n<\/tr>\n<tr>\n<td STYLE=\"border: solid .75pt black\">SHAlloc\/<br \/>SHFree<\/td>\n<td>=<\/td>\n<td STYLE=\"border: solid .75pt black\">SHGetMalloc<\/td>\n<td>&nbsp;<font SIZE=\"+3\">=<\/font>&nbsp;<\/td>\n<td STYLE=\"border: solid .75pt black\">CoGetMalloc<\/td>\n<td>=<\/td>\n<td STYLE=\"border: solid .75pt black\">CoTaskMemAlloc\/<br \/>CoTaskMemFree<\/td>\n<\/tr>\n<\/table>\n<\/div>\n<p>\nThe final &#8220;Note&#8221; hints at the direction the shell intended to go.\nEventually, loading OLE32.DLL would not be as painful as it was\nin Windows&nbsp;95, and the shell can abandon its fake-COM and just\nuse the real thing.  At this point, asking for the shell task allocator\nwould become the same as asking for the COM task allocator.\n<\/p>\n<p>\nThat time actually arrived a long time ago.\nThe days of 4MB machines are now the stuff of legend.\nThe shell has ditched its fake-COM and now just uses real-COM everywhere.\n<\/p>\n<p>\nTherefore,\n<strong>the diagram today is the one with the equals-sign<\/strong>.\nAll four functions are interchangeable in Windows XP and beyond.\n<\/p>\n<p>\nWhat if you want to run on older systems?  Well, it is always\nacceptable to use CoTaskMemAlloc\/CoTaskMemFree.  Why?  You can\npuzzle this out logically.\nSince those functions are exported from OLE32.DLL, the fact that\nyou are using them means that OLE32.DLL is loaded, at which point\nthe &#8220;After&#8221; diagram above with the equals sign kicks in, and everything\nis all one big happy family.\n<\/p>\n<p>\nThe case where you need to be careful is if your DLL does\n<strong>not<\/strong>\nlink to OLE32.DLL.\nIn that case, you don&#8217;t know whether you are in the\n&#8220;Before&#8221; or &#8220;After&#8221; case, and you have to play it safe and\nuse the shell task allocator for the things that are documented\nas using the shell task allocator.\n<\/p>\n<p>\nI hope this discussion also provides the historical background\nof the function\n<a HREF=\"http:\/\/msdn.microsoft.com\/library\/en-us\/shellcc\/platform\/shell\/reference\/functions\/shloadole.asp\">\nSHLoadOLE<\/a>, which today doesn&#8217;t do anything\nbecause OLE is already always loaded.\nBut in the old days, this signalled to the shell,\n&#8220;Okay, now is the time to\n<a HREF=\"http:\/\/catb.org\/~esr\/jargon\/html\/B\/brain-dump.html\">\nbrain-dump<\/a> your fake-COM into the real-COM.&#8221;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>There isn&#8217;t any difference any more.<\/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":[2],"class_list":["post-102299","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-history"],"acf":[],"blog_post_summary":"<p>There isn&#8217;t any difference any more.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/102299","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=102299"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/102299\/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=102299"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=102299"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=102299"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}