{"id":42,"date":"2007-03-14T18:35:38","date_gmt":"2007-03-14T17:35:38","guid":{"rendered":"http:\/\/blog.m-ri.de\/index.php\/2007\/03\/14\/grunde-fur-den-r6034-bei-der-vc-80-dll-crt\/"},"modified":"2007-03-14T18:38:12","modified_gmt":"2007-03-14T17:38:12","slug":"grunde-fur-den-r6034-bei-der-vc-80-dll-crt","status":"publish","type":"post","link":"http:\/\/blog.m-ri.de\/index.php\/2007\/03\/14\/grunde-fur-den-r6034-bei-der-vc-80-dll-crt\/","title":{"rendered":"Gr\u00fcnde f\u00fcr den R6034 bei der VC 8.0 DLL CRT"},"content":{"rendered":"<p>Warum l\u00e4sst sich die neue VC 8.0 CRT eigentlich nicht ohne Manifest verwenden?<br \/>\nSchauen wir uns also mal an was passiert wenn eine Applikation oder eine DLL geladen wird, die die VC 8.0 CRT als DLL verwendet:<\/p>\n<p>Die DllMain der CRT wird aufgerufen. Bei der C-Runtime DLL ist dies die Funktion _CRTDLL_INIT die sofort die Funktion __CRTDLL_INIT aufruft.<\/p>\n<p>Diese Funktion sorgt nun der Reihe nach daf\u00fcr, dass:<\/p>\n<ul>\n<li>die aktuelle Windows Version bestimmt wird<\/li>\n<li>der Heap initialisiert wird<\/li>\n<li>die TLS Bereiche f\u00fcr multithreading angelegt werden<\/li>\n<li>das Environment und die Befehlszeile bestimmt werden<\/li>\n<li>die MBCS Umwandlungstabellen angelegt werden<\/li>\n<li>alles was mit atexit, floating-point math etc. initialisiert wird<\/li>\n<li>und&#8230; jetzt wird es spannend&#8230; die Funktion <em>_check_manifest<\/em> aufgerufen wird.<\/li>\n<\/ul>\n<p>In der Funktion _check_manifest wird der Code ausgef\u00fchrt der zum Runtime Fehler R6034 <em>&#8222;The application has attempted to load the runtime library incorrectly. Contact support for more information&#8220; <\/em>f\u00fchren kann, n\u00e4mlich genau dann, wenn diese Funktion FALSE zur\u00fcck gibt.<\/p>\n<p>Was macht diese Funktion nun?<br \/>\nIm Source-Code der CRT ist dies wunderbar dokumentiert:<\/p>\n<ol>\n<li><strong><em>if (pre-fusion OS)<br \/>\n\u00a0 return TRUE; [no need to check]<\/em><br \/>\n<\/strong>Das bedeutet nichts anderes, als das die nachfolgenden Tests nur auf XP\/Vista\/2003 und folgenden OS durchgef\u00fchrt werden. Also im Klartext unter Windows 2000 kann dieser Runtime Error nicht auftreten.<\/li>\n<li><em><strong>if dll is being loaded by instrumented-mscoree.dll.<br \/>\n\u00a0 return TRUE;<br \/>\n<\/strong><\/em>OK. Ein Speziallfall. Im Kontext der .NET CLR und des Profilers ist auch ales erlaubt. Also wenn sich <em>MSCoree.dll<\/em> (Microsoft .NET Runtime Execution Engine) und <em>PGORT80.dll<\/em> (Profile Guided Optimization Instrumentation Runtime) im Speicher befinden ist auch alles paletti.<\/li>\n<li><em><strong>if (dll is loaded from system32)<br \/>\n\u00a0 return FALSE;<br \/>\n<\/strong><\/em>Dies ist interessant. In keinem Fall darf diese DLL im <em>Windows\\System32<\/em> stehen! Oder wenn Sie von dort geladen wird fielgt einem der R6045 um die Ohren.<\/li>\n<li><em><strong>if (!(loaded through a manifest))<br \/>\n\u00a0 return FALSE;<\/strong><br \/>\n<\/em>Hier wird \u00fcber die Funktion <em>FindActCtxSectionStringW<\/em> gepr\u00fcft ob diese DLL \u00fcber ein Manifest geladen wird. <em>ActCtx<\/em> ist die Abk\u00fcrzung f\u00fcr Activation Context.<br \/>\nWurde kein solcher Activation Context gefunden (also kein Manifest), dass f\u00fcr diese DLL verantwortlich ist, dann hei\u00dft das auch R6045.<\/li>\n<li><em><strong>if (loaded from %SystemRoot%\\WinSxS)<br \/>\n\u00a0 return TRUE; [loaded from the WinSxS cache]<\/strong><br \/>\n<\/em>Wird die DLL aus den Side by Side Verzeichnissen geladen ist schon alles gut.<br \/>\nAber auch das geht nur mit g\u00fcltigem Manifest.<\/li>\n<li><em><strong>if (manifest is in the same folder as the dll)<br \/>\n\u00a0 return TRUE;<br \/>\n<\/strong><\/em>Auch das ist interessant. Das Manifest muss zwingend im selben Verzeichnis wie diese DLL liegen, denn sonst sind wir fertig<\/li>\n<li><em><strong>return FALSE; [loaded with another manifest]<\/strong><br \/>\n<\/em>und nun schl\u00e4gt das Laden fehl, da das Manifest offensichtlich nicht im DLL Verzeichnis liegt. Auch hier ein R6045.<\/li>\n<\/ol>\n<p>Zur\u00fcck noch mal zum Fall 2. Was macht dieser Test &#8222;<em>if dll is being loaded by instrumented-mscoree.dll&#8220;<\/em>? Er macht nichts anderes als zu pr\u00fcfen ob die beiden DLLs im Speicher sind.<\/p>\n<p>BTW: Man k\u00f6nnte nun ganz frech zwei <em>leere<\/em> DLLs mit diesen Namen erzeugen und diese in ein Projekt implizit laden lassen&#8230; und siehe da, die Applikation ben\u00f6tigt auf einmal kein Manifest mehr&#8230;<br \/>\nAber warum sich das ganze verbietet ist auch klar. DLLs mit den oben genannten Namen zu erzeugen, kann ganz sch\u00f6n verwirrend und problematisch werden.<br \/>\nUnd warum zwei leere DLLs in einen Prozess laden, wenn es reicht ein Manifest zu erg\u00e4nzen? \ud83d\ude09<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Warum l\u00e4sst sich die neue VC 8.0 CRT eigentlich nicht ohne Manifest verwenden? Schauen wir uns also mal an was passiert wenn eine Applikation oder eine DLL geladen wird, die die VC 8.0 CRT als DLL verwendet: Die DllMain der CRT wird aufgerufen. Bei der C-Runtime DLL ist dies die Funktion _CRTDLL_INIT die sofort die &hellip; <a href=\"http:\/\/blog.m-ri.de\/index.php\/2007\/03\/14\/grunde-fur-den-r6034-bei-der-vc-80-dll-crt\/\" class=\"more-link\"><span class=\"screen-reader-text\">\u201eGr\u00fcnde f\u00fcr den R6034 bei der VC 8.0 DLL CRT\u201c <\/span>weiterlesen<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[19,3],"tags":[69,58,36],"class_list":["post-42","post","type-post","status-publish","format-standard","hentry","category-crt","category-programmieren","tag-manifest","tag-uac","tag-vs-2005"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/posts\/42","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/comments?post=42"}],"version-history":[{"count":0,"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/posts\/42\/revisions"}],"wp:attachment":[{"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/media?parent=42"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/categories?post=42"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/tags?post=42"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}