DllMain からの LoadLibrary の呼び出しが完全に安全な単純な状況があり、それほど単純ではない状況もあります。ただし、設計上、DllMain は読み込まれたモジュールのリストを変更しないと信頼されています。
ローダー ロックの所有は、DllMain で実行できることを実際に制限しますが、それは LoadLibrary ルールに間接的に関連するだけです。ローダー ロックの関連する目的は、ロードされたモジュールのリストへのアクセスをシリアル化することです。NTDLL は 1 つのスレッドでこのリストを操作しますが、ローダー ロックを所有することで、別のスレッドで実行されている NTDLL コードによってリストが変更されないようにします。ただし、ローダーロックは重要なセクションです。同じスレッドがローダーロックを再取得してリストを変更するのを止めることは何もしません。
これは、リストの処理中に NTDLL が完全にそれ自体を保持している場合は問題になりません。ただし、NTDLL では、新しく読み込まれた DLL を初期化するときなど、この作業に他のコードを含めることができます。リストの処理中に NTDLL が自身の外部を呼び出すたびに、設計を行うための選択肢があります。大きく分けて、2 つのオプションがあります。1 つは、リストを安定させてローダー ロックを解放し、外部を呼び出してからローダー ロックを取得し、リストの作業を最初から再開することです。もう 1 つは、ローダーのロックを維持し、呼び出されたコードがリストを変更するようなことをしないことを信頼することです。したがって、LoadLibrary は DllMain で立ち入り禁止になります。
ローダー ロックが DllMain による LoadLibrary の呼び出しを停止するということではなく、ローダー ロック自体がそのような呼び出しを安全でなくするということでもありません。代わりに、ローダー ロックを保持することにより、NTDLLはDllMain が LoadLibrary を呼び出さないことを信頼します。
対照的に、同期オブジェクトを待機しないという DllMain ルールについて考えてみましょう。ここでは、ローダーロックがこれを危険にする直接的な役割を果たしています。DllMain で同期オブジェクトを待機すると、デッドロックの可能性が設定されます。必要なのは、待機しているオブジェクトを別のスレッドが既に保持していて、この別のスレッドが、ローダー ロックで待機する関数 (たとえば、LoadLibrary だけでなく、一見無害な GetModuleHandle などの関数) を呼び出すことだけです。
DllMain の規則を拡張したり破ったりすることは、いたずらであるか、完全に愚かでさえあるかもしれません。ただし、Microsoft は、これらの規則がどれほど強力で意味があるかを尋ねる人々に対して、少なくとも部分的に責任があることを指摘しなければなりません。結局のところ、いくつかは常に明確かつ強制的に文書化されているわけではなく、最後に調べたとき、それらが確実に必要とされるすべての状況でまだ文書化されていませんでした。(私が念頭に置いている例外は、少なくとも Visual Studio 2005 までは、DLL を作成する MFC プログラマーは初期化コードを CWinApp::InitInstance に配置するように言われていましたが、このコードが DllMain 規則に従うことは知らされていませんでした。)
さらに、DllMain の規則に疑問の余地なく従うべきであるかのように Microsoft の誰もが発言するのは、少し金持ちになるでしょう。Microsoft 自身のプログラマーが規則を破る例が存在し、規則を破った後も引き続き、重大な現実世界の問題を引き起こしていることが確認されています。