PAL Module/shutdown cleanup.
authorMike McLaughlin <mikem@microsoft.com>
Thu, 10 Dec 2015 03:22:56 +0000 (19:22 -0800)
committerMike McLaughlin <mikem@microsoft.com>
Mon, 14 Dec 2015 22:50:45 +0000 (14:50 -0800)
Added a PAL_Shutdown function that cleans/shutdowns the PAL without exiting/terminating
the process doing exactly what ExitProcess/TerminateProcess before exiting the process.

Removed the PAL_InitializeCoreCLR export. The new coreclr_* hosting apis should be used.

Moved the "is module manager initialized" check (exe_module.prev != NULL) inside the module
lock to prevent races during shutdown in LOADCallDllMain.

Removed LOADFreeModules so we never try to call the DLL_PROCESS_DETACH handlers. Most of this
cleanup happened because I was trying to getting the DLL_PROCESS_DETACH notifications working,
but there were too many opportunities for deadlock. Emulating Windows behavior isn't that
important and in this case will cause more problems that it fixes.

Removed PAL_RegisterLibrary*/PAL_UnregisterLibrary. They were only used in one place to load modules
that don't exist anymore (rotor_palrt and sscoree).

Renamed LOAD_SEH_CallDllMain to LoadCallDllMainSafe (we don't usually use _ in names) and use this
function in all the places we call the DllMain handler. This combines some code in a common place
and protects all DllMain calls from exceptions.

Source code formatting cleanup and moved internal functions around to be next to the rest of the
internal functions.

Initialize pDllMain to NULL in LOADAllocModule.

Get the DllMain function address into LOADAddModule so that it is initialized in the PAL_RegisterModule path.

Changed PAL_UnregisterModule not to call the DllMain function.

12 files changed:
src/dlls/mscoree/mscorwks_unixexports.src
src/dlls/mscoree/unixinterface.cpp
src/pal/inc/pal.h
src/pal/src/include/pal/module.h
src/pal/src/init/pal.cpp
src/pal/src/loader/module.cpp
src/pal/src/thread/process.cpp
src/pal/tests/palsuite/pal_specific/CMakeLists.txt
src/pal/tests/palsuite/paltestlist.txt
src/pal/tests/palsuite/palverify.dat
src/tools/metainfo/metainfo.cpp
src/vm/ceemain.cpp

index 8089dc5..fe4f2a4 100644 (file)
@@ -13,8 +13,7 @@ GetMetaDataPublicInterfaceFromInternal
 ; Obsolete Unix hosting API, to be removed
 ExecuteAssembly
 
-; PAL initialization and module registration
-PAL_InitializeCoreCLR 
+; PAL module registration
 PAL_RegisterModule
 PAL_UnregisterModule
 
index 6a2dbd6..9259590 100644 (file)
@@ -280,13 +280,15 @@ int coreclr_shutdown(
             unsigned int domainId)
 {
     ReleaseHolder<ICLRRuntimeHost2> host(reinterpret_cast<ICLRRuntimeHost2*>(hostHandle));
-    HRESULT hr = host->UnloadAppDomain(domainId,
-                                       true); // Wait until done
+
+    HRESULT hr = host->UnloadAppDomain(domainId, true); // Wait until done
     IfFailRet(hr);
 
     hr = host->Stop();
 
-    // The PAL_Terminate is not called here since it would terminate the current process.
+#ifdef FEATURE_PAL
+    PAL_Shutdown();
+#endif
 
     return hr;
 }
index c0c9ba7..660b408 100644 (file)
@@ -542,6 +542,15 @@ PAL_EntryPoint(
     IN LPVOID lpParameter);
 
 /// <summary>
+/// This function shuts down PAL WITHOUT exiting the current process.
+/// </summary>
+PALIMPORT
+void
+PALAPI
+PAL_Shutdown(
+    void);
+
+/// <summary>
 /// This function shuts down PAL and exits the current process.
 /// </summary>
 PALIMPORT
@@ -579,23 +588,6 @@ PAL_UnregisterModule(
     IN HINSTANCE hInstance);
 
 PALIMPORT
-HMODULE
-PALAPI
-PAL_RegisterLibraryW(
-    IN LPCWSTR lpLibFileName);
-
-PALIMPORT
-BOOL
-PALAPI
-PAL_UnregisterLibraryW(
-    IN HMODULE hLibModule);
-
-#ifdef UNICODE
-#define PAL_RegisterLibrary PAL_RegisterLibraryW
-#define PAL_UnregisterLibrary PAL_UnregisterLibraryW
-#endif
-
-PALIMPORT
 BOOL
 PALAPI
 PAL_GetPALDirectoryW(
@@ -3694,7 +3686,9 @@ Return value:
     A valid base address if successful.
     0 if failure
 --*/
-void * PAL_LOADLoadPEFile(HANDLE hFile);
+void *
+PALAPI
+PAL_LOADLoadPEFile(HANDLE hFile);
 
 /*++
     PAL_LOADUnloadPEFile
@@ -3708,9 +3702,9 @@ Return value:
     TRUE - success
     FALSE - failure (incorrect ptr, etc.)
 --*/
-
-BOOL PAL_LOADUnloadPEFile(void * ptr);
-
+BOOL 
+PALAPI
+PAL_LOADUnloadPEFile(void * ptr);
 
 #ifdef UNICODE
 #define LoadLibrary LoadLibraryW
index 83c977e..077aadf 100644 (file)
@@ -86,19 +86,6 @@ BOOL LOADSetExeName(LPWSTR name);
 
 /*++
 Function :
-    LOADFreeModules
-
-    Release all resources held by the module manager (including dlopen handles)
-
-Parameters:
-    BOOL bTerminateUnconditionally: If TRUE, this will avoid calling any DllMains
-
-    (no return value)
---*/
-void LOADFreeModules(BOOL bTerminateUnconditionally);
-
-/*++
-Function :
     LOADCallDllMain
 
     Call DllMain for all modules (that have one) with the given "fwReason"
index ff7cddd..626f077 100644 (file)
@@ -550,7 +550,6 @@ CLEANUP15:
 CLEANUP13:
     VIRTUALCleanup();
 CLEANUP10:
-    LOADFreeModules(TRUE);
     MAPCleanup();
 CLEANUP6:
     SEHCleanup();
@@ -742,32 +741,17 @@ done:
 
 /*++
 Function:
-  PALCommonCleanup
-
-Utility function to prepare for shutdown.
+  PAL_Shutdown
 
+Abstract:
+  This function shuts down the PAL WITHOUT exiting the current process.
 --*/
-void 
-PALCommonCleanup()
+void
+PALAPI
+PAL_Shutdown(
+    void)
 {
-    static bool cleanupDone = false;
-
-    if (!cleanupDone)
-    {
-        cleanupDone = true;
-
-        PALSetShutdownIntent();
-
-        //
-        // Let the synchronization manager know we're about to shutdown
-        //
-
-        CPalSynchMgrController::PrepareForShutdown();
-
-#ifdef _DEBUG
-        PROCDumpThreadList();
-#endif
-    }
+    TerminateCurrentProcessNoExit(FALSE /* bTerminateUnconditionally */);
 }
 
 /*++
@@ -781,7 +765,7 @@ Abstract:
 void
 PALAPI
 PAL_Terminate(
-          void)
+    void)
 {
     PAL_TerminateEx(0);
 }
@@ -797,7 +781,8 @@ the specified exit code.
 --*/
 void
 PALAPI
-PAL_TerminateEx(int exitCode)
+PAL_TerminateEx(
+    int exitCode)
 {
     ENTRY_EXTERNAL("PAL_TerminateEx()\n");
 
@@ -825,7 +810,7 @@ Abstract:
 void
 PALAPI
 PAL_InitializeDebug(
-          void)
+    void)
 {
     PERF_ENTRY(PAL_InitializeDebug);
     ENTRY("PAL_InitializeDebug()\n");
@@ -842,14 +827,43 @@ Function:
 
 Returns TRUE if startup has reached a point where thread data is available
 --*/
-BOOL
-PALIsThreadDataInitialized()
+BOOL PALIsThreadDataInitialized()
 {
     return g_fThreadDataAvailable;
 }
 
 /*++
 Function:
+  PALCommonCleanup
+
+Utility function to prepare for shutdown.
+
+--*/
+void 
+PALCommonCleanup()
+{
+    static bool cleanupDone = false;
+
+    if (!cleanupDone)
+    {
+        cleanupDone = true;
+
+        PALSetShutdownIntent();
+
+        //
+        // Let the synchronization manager know we're about to shutdown
+        //
+
+        CPalSynchMgrController::PrepareForShutdown();
+
+#ifdef _DEBUG
+        PROCDumpThreadList();
+#endif
+    }
+}
+
+/*++
+Function:
   PALShutdown
 
   sets the PAL's initialization count to zero, so that PALIsInitialized will 
@@ -858,15 +872,12 @@ Function:
   
 (no parameters, no retun vale)
 --*/
-void
-PALShutdown(
-          void)
+void PALShutdown()
 {
     init_count = 0;
 }
 
-BOOL
-PALIsShuttingDown()
+BOOL PALIsShuttingDown()
 {
     /* ROTORTODO: This function may be used to provide a reader/writer-like
        mechanism (or a ref counting one) to prevent PAL APIs that need to access 
@@ -878,8 +889,7 @@ PALIsShuttingDown()
     return shutdown_intent;
 }
 
-void
-PALSetShutdownIntent()
+void PALSetShutdownIntent()
 {
     /* ROTORTODO: See comment in PALIsShuttingDown */
     shutdown_intent = TRUE;
index 04e4b9c..81fc342 100644 (file)
@@ -91,27 +91,28 @@ CRITICAL_SECTION module_critsec;
 
 /* always the first, in the in-load-order list */
 MODSTRUCT exe_module; 
-MODSTRUCT *pal_module = NULL;
+MODSTRUCT *pal_module = nullptr;
 
-char * g_szCoreCLRPath = NULL;
+char * g_szCoreCLRPath = nullptr;
 size_t g_cbszCoreCLRPath = MAX_LONGPATH * sizeof(char);
 
 int MaxWCharToAcpLength = 3;
+
 /* static function declarations ***********************************************/
 
-template<class TChar> bool LOADVerifyLibraryPath(const TChar *libraryPath);
-bool LOADConvertLibraryPathWideStringToMultibyteString(
+template<class TChar> static bool LOADVerifyLibraryPath(const TChar *libraryPath);
+static bool LOADConvertLibraryPathWideStringToMultibyteString(
     LPCWSTR wideLibraryPath,
     LPSTR multibyteLibraryPath,
     INT *multibyteLibraryPathLengthRef);
-
 static BOOL LOADValidateModule(MODSTRUCT *module);
 static LPWSTR LOADGetModuleFileName(MODSTRUCT *module);
 static MODSTRUCT *LOADAddModule(void *dl_handle, LPCSTR libraryNameOrPath);
 static void *LOADLoadLibraryDirect(LPCSTR libraryNameOrPath);
+static BOOL LOADFreeLibrary(MODSTRUCT *module, BOOL fCallDllMain);
 static HMODULE LOADRegisterLibraryDirect(void *dl_handle, LPCSTR libraryNameOrPath, BOOL fDynamic);
 static HMODULE LOADLoadLibrary(LPCSTR shortAsciiName, BOOL fDynamic);
-static void LOAD_SEH_CallDllMain(MODSTRUCT *module, DWORD dwReason, LPVOID lpReserved);
+static BOOL LOADCallDllMainSafe(MODSTRUCT *module, DWORD dwReason, LPVOID lpReserved);
 
 /* API function definitions ***************************************************/
 
@@ -126,7 +127,7 @@ PALAPI
 LoadLibraryA(
     IN LPCSTR lpLibFileName)
 {
-    return LoadLibraryExA(lpLibFileName, NULL, 0);
+    return LoadLibraryExA(lpLibFileName, nullptr, 0);
 }
 
 /*++
@@ -140,7 +141,7 @@ PALAPI
 LoadLibraryW(
     IN LPCWSTR lpLibFileName)
 {
-    return LoadLibraryExW(lpLibFileName, NULL, 0);
+    return LoadLibraryExW(lpLibFileName, nullptr, 0);
 }
 
 /*++
@@ -160,16 +161,16 @@ LoadLibraryExA(
     {
         // UNIXTODO: Implement this!
         ASSERT("Needs Implementation!!!");
-        return NULL;
+        return nullptr;
     }
 
-    LPSTR lpstr = NULL;
-    HMODULE hModule = NULL;
+    LPSTR lpstr = nullptr;
+    HMODULE hModule = nullptr;
 
     PERF_ENTRY(LoadLibraryA);
     ENTRY("LoadLibraryExA (lpLibFileName=%p (%s)) \n",
-          (lpLibFileName)?lpLibFileName:"NULL",
-          (lpLibFileName)?lpLibFileName:"NULL");
+          (lpLibFileName) ? lpLibFileName : "NULL",
+          (lpLibFileName) ? lpLibFileName : "NULL");
 
     if (!LOADVerifyLibraryPath(lpLibFileName))
     {
@@ -190,7 +191,7 @@ LoadLibraryExA(
 
     /* let LOADLoadLibrary call SetLastError */
  Done:
-    if (lpstr != NULL)
+    if (lpstr != nullptr)
     {
         InternalFree(lpstr);
     }
@@ -218,18 +219,18 @@ LoadLibraryExW(
     {
         // UNIXTODO: Implement this!
         ASSERT("Needs Implementation!!!");
-        return NULL;
+        return nullptr;
     }
     
     CHAR * lpstr;
     INT name_length;
     PathCharString pathstr;
-    HMODULE hModule = NULL;
+    HMODULE hModule = nullptr;
 
     PERF_ENTRY(LoadLibraryExW);
     ENTRY("LoadLibraryExW (lpLibFileName=%p (%S)) \n",
-          lpLibFileName?lpLibFileName:W16_NULLSTRING,
-          lpLibFileName?lpLibFileName:W16_NULLSTRING);
+          lpLibFileName ? lpLibFileName : W16_NULLSTRING,
+          lpLibFileName ? lpLibFileName : W16_NULLSTRING);
 
     if (!LOADVerifyLibraryPath(lpLibFileName))
     {
@@ -237,7 +238,7 @@ LoadLibraryExW(
     }
 
     lpstr = pathstr.OpenStringBuffer((PAL_wcslen(lpLibFileName)+1) * MaxWCharToAcpLength);
-    if (NULL == lpstr)
+    if (nullptr == lpstr)
     {
         goto done;
     }
@@ -259,110 +260,6 @@ done:
     return hModule;
 }
 
-/*
-Function:
-LoadLibraryDirect
-
-Loads a library using a system call, without registering the library with the module list.
-
-Returns the system handle to the loaded library, or nullptr upon failure (error is set via SetLastError()).
-*/
-void *
-PALAPI
-PAL_LoadLibraryDirect(
-    IN LPCWSTR lpLibFileName)
-{
-    PathCharString pathstr;
-    CHAR * lpstr = NULL;
-    INT name_length;
-    void *dl_handle = NULL;
-
-    PERF_ENTRY(LoadLibraryDirect);
-    ENTRY("LoadLibraryDirect (lpLibFileName=%p (%S)) \n",
-          lpLibFileName?lpLibFileName:W16_NULLSTRING,
-          lpLibFileName?lpLibFileName:W16_NULLSTRING);
-
-    if (!LOADVerifyLibraryPath(lpLibFileName))
-    {
-        goto done;
-    }
-    
-    lpstr = pathstr.OpenStringBuffer((PAL_wcslen(lpLibFileName)+1) * MaxWCharToAcpLength);
-    if (NULL == lpstr)
-    {
-        goto done;
-    }
-    if (!LOADConvertLibraryPathWideStringToMultibyteString(lpLibFileName, lpstr, &name_length))
-    {
-        goto done;
-    }
-
-    /* do the Dos/Unix conversion on our own copy of the name */
-    FILEDosToUnixPathA(lpstr);
-    pathstr.CloseBuffer(name_length);
-
-    dl_handle = LOADLoadLibraryDirect(lpstr);
-
-done:
-    LOGEXIT("LoadLibraryDirect returns HMODULE %p\n", dl_handle);
-    PERF_EXIT(LoadLibraryDirect);
-    return dl_handle;
-}
-
-/*
-Function:
-RegisterLibraryDirect
-
-Registers a system handle to a loaded library with the module list.
-
-Returns a PAL handle to the loaded library, or nullptr upon failure (error is set via SetLastError()).
-*/
-HMODULE
-PALAPI
-PAL_RegisterLibraryDirect(
-    IN void *dl_handle,
-    IN LPCWSTR lpLibFileName)
-{
-    PathCharString pathstr;
-    CHAR * lpstr = NULL;
-    INT name_length;
-    HMODULE hModule = NULL;
-
-    PERF_ENTRY(RegisterLibraryDirect);
-    ENTRY("RegisterLibraryDirect (lpLibFileName=%p (%S)) \n",
-        lpLibFileName ? lpLibFileName : W16_NULLSTRING,
-        lpLibFileName ? lpLibFileName : W16_NULLSTRING);
-
-    if (!LOADVerifyLibraryPath(lpLibFileName))
-    {
-        goto done;
-    }
-
-    lpstr = pathstr.OpenStringBuffer((PAL_wcslen(lpLibFileName)+1) * MaxWCharToAcpLength);
-    if (NULL == lpstr)
-    {
-        goto done;
-    }
-    if (!LOADConvertLibraryPathWideStringToMultibyteString(lpLibFileName, lpstr, &name_length))
-    {
-        goto done;
-    }
-
-    /* do the Dos/Unix conversion on our own copy of the name */
-    FILEDosToUnixPathA(lpstr);
-    pathstr.CloseBuffer(name_length);
-
-    /* let LOADRegisterLibraryDirect call SetLastError in case of failure */
-    LockModuleList();
-    hModule = LOADRegisterLibraryDirect((void *)dl_handle, lpstr, true /* fDynamic */);
-    UnlockModuleList();
-
-done:
-    LOGEXIT("RegisterLibraryDirect returns HMODULE %p\n", hModule);
-    PERF_EXIT(RegisterLibraryDirect);
-    return hModule;
-}
-
 /*++
 Function:
   GetProcAddress
@@ -376,12 +273,12 @@ GetProcAddress(
     IN LPCSTR lpProcName)
 {
     MODSTRUCT *module;
-    FARPROC ProcAddress = NULL;
+    FARPROC ProcAddress = nullptr;
     LPCSTR symbolName = lpProcName;
 
     PERF_ENTRY(GetProcAddress);
     ENTRY("GetProcAddress (hModule=%p, lpProcName=%p (%s))\n",
-          hModule, lpProcName?lpProcName:"NULL", lpProcName?lpProcName:"NULL");
+          hModule, lpProcName ? lpProcName : "NULL", lpProcName ? lpProcName : "NULL");
 
     LockModuleList();
 
@@ -389,7 +286,7 @@ GetProcAddress(
 
     /* parameter validation */
 
-    if ((lpProcName == NULL) || (*lpProcName == '\0'))
+    if ((lpProcName == nullptr) || (*lpProcName == '\0'))
     {
         TRACE("No function name given\n");
         SetLastError(ERROR_INVALID_PARAMETER);
@@ -443,7 +340,7 @@ GetProcAddress(
 
     // If we aren't looking inside the PAL or we didn't find a PAL_ variant
     // inside the PAL, fall back to a normal search.
-    if (ProcAddress == NULL)
+    if (ProcAddress == nullptr)
     {
         ProcAddress = (FARPROC) dlsym(module->dl_handle, lpProcName);
     }
@@ -460,7 +357,7 @@ GetProcAddress(
             if (libName)
             {
                 module->lib_name = UTIL_MBToWC_Alloc(libName, -1);
-                if (NULL == module->lib_name)
+                if (nullptr == module->lib_name)
                 {
                     ERROR("MBToWC failure; can't save module's full name\n");
                 }
@@ -485,7 +382,6 @@ done:
     return ProcAddress;
 }
 
-
 /*++
 Function:
   FreeLibrary
@@ -497,116 +393,18 @@ PALAPI
 FreeLibrary(
     IN OUT HMODULE hLibModule)
 {
-    MODSTRUCT *module;
     BOOL retval = FALSE;
 
     PERF_ENTRY(FreeLibrary);
     ENTRY("FreeLibrary (hLibModule=%p)\n", hLibModule);
 
-    LockModuleList();
-
-    module = (MODSTRUCT *) hLibModule;
-
-    if (terminator)
-    {
-        /* PAL shutdown is in progress - ignore FreeLibrary calls */
-        retval = TRUE;
-        goto done;
-    }
-
-    if (!LOADValidateModule(module))
-    {
-        TRACE("Can't free invalid module handle %p\n", hLibModule);
-        SetLastError(ERROR_INVALID_HANDLE);
-        goto done;
-    }
-
-    if (module->refcount == -1)
-    {
-        /* special module - never released */
-        retval = TRUE;
-        goto done;
-    }
-
-    module->refcount--;
-    TRACE("Reference count for module %p (named %S) decreases to %d\n",
-            module, MODNAME(module), module->refcount);
-
-    if (module->refcount != 0)
-    {
-        retval = TRUE;
-        goto done;
-    }
-
-    /* Releasing the last reference : call dlclose(), remove module from the
-       process-wide module list */
-
-    TRACE("Reference count for module %p (named %S) now 0; destroying "
-            "module structure.\n", module, MODNAME(module));
-
-    /* unlink the module structure from the list */
-    module->prev->next = module->next;
-    module->next->prev = module->prev;
-
-    /* remove the circular reference so that LOADValidateModule will fail */
-    module->self = NULL;
-
-    /* Call DllMain if the module contains one */
-    if (module->pDllMain)
-    {
-        TRACE("Calling DllMain (%p) for module %S\n",
-                module->pDllMain, 
-                module->lib_name ? module->lib_name : W16_NULLSTRING);
-
-/* reset ENTRY nesting level back to zero while inside the callback... */
-#if _ENABLE_DEBUG_MESSAGES_
-    {
-        int old_level;
-        old_level = DBG_change_entrylevel(0);
-#endif /* _ENABLE_DEBUG_MESSAGES_ */
-    
-        {
-            // This module may be foreign to our PAL, so leave our PAL.
-            // If it depends on us, it will re-enter.
-            PAL_LeaveHolder holder;
-            module->pDllMain(module->hinstance, DLL_PROCESS_DETACH, NULL);
-        }
-
-        if (module->hinstance)
-        {
-            PUNREGISTER_MODULE unregisterModule = (PUNREGISTER_MODULE)dlsym(module->dl_handle, "PAL_UnregisterModule");
-            if (unregisterModule != nullptr)
-            {
-                 unregisterModule(module->hinstance);
-            }
-        }
-/* ...and set nesting level back to what it was */
-#if _ENABLE_DEBUG_MESSAGES_
-        DBG_change_entrylevel(old_level);
-    }
-#endif /* _ENABLE_DEBUG_MESSAGES_ */
-    }
-
-    if (module->dl_handle && 0 != dlclose(module->dl_handle))
-    {
-        /* report dlclose() failure, but proceed anyway. */
-        WARN("dlclose() call failed! error message is \"%s\"\n", dlerror());
-    }
-
-    /* release all memory */
-    InternalFree(module->lib_name);
-    InternalFree(module);
-
-    retval = TRUE;
+    retval = LOADFreeLibrary((MODSTRUCT *)hLibModule, TRUE /* fCallDllMain */);
 
-done:
-    UnlockModuleList();
     LOGEXIT("FreeLibrary returns BOOL %d\n", retval);
     PERF_EXIT(FreeLibrary);
     return retval;
 }
 
-
 /*++
 Function:
   FreeLibraryAndExitThread
@@ -629,7 +427,6 @@ FreeLibraryAndExitThread(
     PERF_EXIT(FreeLibraryAndExitThread);
 }
 
-
 /*++
 Function:
   GetModuleFileNameA
@@ -652,7 +449,7 @@ GetModuleFileNameA(
 {
     INT name_length;
     DWORD retval = 0;
-    LPWSTR wide_name = NULL;
+    LPWSTR wide_name = nullptr;
 
     PERF_ENTRY(GetModuleFileNameA);
     ENTRY("GetModuleFileNameA (hModule=%p, lpFileName=%p, nSize=%u)\n",
@@ -677,7 +474,7 @@ GetModuleFileNameA(
     /* Convert module name to Ascii, place it in the supplied buffer */
 
     name_length = WideCharToMultiByte(CP_ACP, 0, wide_name, -1, lpFileName,
-                                      nSize, NULL, NULL);
+                                      nSize, nullptr, nullptr);
     if (name_length == 0)
     {
         TRACE("Buffer too small to copy module's file name.\n");
@@ -694,7 +491,6 @@ done:
     return retval;
 }
 
-
 /*++
 Function:
   GetModuleFileNameW
@@ -717,7 +513,7 @@ GetModuleFileNameW(
 {
     INT name_length;
     DWORD retval = 0;
-    LPWSTR wide_name = NULL;
+    LPWSTR wide_name = nullptr;
 
     PERF_ENTRY(GetModuleFileNameW);
     ENTRY("GetModuleFileNameW (hModule=%p, lpFileName=%p, nSize=%u)\n",
@@ -763,169 +559,282 @@ done:
     return retval;
 }
 
-
-/*++
+/*
 Function:
-  PAL_RegisterModule
+  PAL_LoadLibraryDirect
 
-  Register the module with the target module and return a module handle in
-  the target module's context. Doesn't call the DllMain because it is used
-  as part of calling DllMain in the calling module.
-
---*/
+  Loads a library using a system call, without registering the library with the module list.
 
-HINSTANCE
+  Returns the system handle to the loaded library, or nullptr upon failure (error is set via SetLastError()).
+*/
+void *
 PALAPI
-PAL_RegisterModule(
-    IN LPCSTR lpLibFileName)
+PAL_LoadLibraryDirect(
+    IN LPCWSTR lpLibFileName)
 {
-    HINSTANCE hinstance = NULL;
-
-    int err = PAL_InitializeDLL();
-    if (err == 0)
-    {
-        PERF_ENTRY(PAL_RegisterModule);
-        ENTRY("PAL_RegisterModule(%s)\n", lpLibFileName ? lpLibFileName : "");
+    PathCharString pathstr;
+    CHAR * lpstr = nullptr;
+    INT name_length;
+    void *dl_handle = nullptr;
 
-        LockModuleList();
+    PERF_ENTRY(LoadLibraryDirect);
+    ENTRY("LoadLibraryDirect (lpLibFileName=%p (%S)) \n",
+          lpLibFileName ? lpLibFileName : W16_NULLSTRING,
+          lpLibFileName ? lpLibFileName : W16_NULLSTRING);
 
-        void *dl_handle = LOADLoadLibraryDirect(lpLibFileName);
-        if (dl_handle)
-        {
-            // This only creates/adds the module handle and doesn't call DllMain
-            hinstance = LOADAddModule(dl_handle, lpLibFileName);
-        }
+    if (!LOADVerifyLibraryPath(lpLibFileName))
+    {
+        goto done;
+    }
+    
+    lpstr = pathstr.OpenStringBuffer((PAL_wcslen(lpLibFileName)+1) * MaxWCharToAcpLength);
+    if (nullptr == lpstr)
+    {
+        goto done;
+    }
+    if (!LOADConvertLibraryPathWideStringToMultibyteString(lpLibFileName, lpstr, &name_length))
+    {
+        goto done;
+    }
 
-        UnlockModuleList();
+    /* do the Dos/Unix conversion on our own copy of the name */
+    FILEDosToUnixPathA(lpstr);
+    pathstr.CloseBuffer(name_length);
 
-        LOGEXIT("PAL_RegisterModule returns HINSTANCE %p\n", hinstance);
-        PERF_EXIT(PAL_RegisterModule);
-    }
+    dl_handle = LOADLoadLibraryDirect(lpstr);
 
-    return hinstance;
+done:
+    LOGEXIT("LoadLibraryDirect returns HMODULE %p\n", dl_handle);
+    PERF_EXIT(LoadLibraryDirect);
+    return dl_handle;
 }
 
-/*++
+/*
 Function:
-  PAL_UnregisterModule
+  PAL_RegisterLibraryDirect
 
-  Used to cleanup the module HINSTANCE from PAL_RegisterModule.
---*/
-VOID
+  Registers a system handle to a loaded library with the module list.
+
+  Returns a PAL handle to the loaded library, or nullptr upon failure (error is set via SetLastError()).
+*/
+HMODULE
 PALAPI
-PAL_UnregisterModule(
-    IN HINSTANCE hInstance)
+PAL_RegisterLibraryDirect(
+    IN void *dl_handle,
+    IN LPCWSTR lpLibFileName)
 {
-    PERF_ENTRY(PAL_UnregisterModule);
-    ENTRY("PAL_UnregisterModule(hInstance=%p)\n", hInstance);
-
-    // DllMain won't be called because PAL_UnregisterModule didn't
-    // query its address and save it.
-    FreeLibrary(hInstance);
+    PathCharString pathstr;
+    CHAR * lpstr = nullptr;
+    INT name_length;
+    HMODULE hModule = nullptr;
 
-    LOGEXIT("PAL_UnregisterModule returns\n");
-    PERF_EXIT(PAL_UnregisterModule);
+    PERF_ENTRY(RegisterLibraryDirect);
+    ENTRY("RegisterLibraryDirect (lpLibFileName=%p (%S)) \n",
+        lpLibFileName ? lpLibFileName : W16_NULLSTRING,
+        lpLibFileName ? lpLibFileName : W16_NULLSTRING);
+
+    if (!LOADVerifyLibraryPath(lpLibFileName))
+    {
+        goto done;
+    }
+
+    lpstr = pathstr.OpenStringBuffer((PAL_wcslen(lpLibFileName)+1) * MaxWCharToAcpLength);
+    if (nullptr == lpstr)
+    {
+        goto done;
+    }
+    if (!LOADConvertLibraryPathWideStringToMultibyteString(lpLibFileName, lpstr, &name_length))
+    {
+        goto done;
+    }
+
+    /* do the Dos/Unix conversion on our own copy of the name */
+    FILEDosToUnixPathA(lpstr);
+    pathstr.CloseBuffer(name_length);
+
+    /* let LOADRegisterLibraryDirect call SetLastError in case of failure */
+    LockModuleList();
+    hModule = LOADRegisterLibraryDirect((void *)dl_handle, lpstr, true /* fDynamic */);
+    UnlockModuleList();
+
+done:
+    LOGEXIT("RegisterLibraryDirect returns HMODULE %p\n", hModule);
+    PERF_EXIT(RegisterLibraryDirect);
+    return hModule;
 }
 
 /*++
 Function:
-  PAL_RegisterLibraryW
+  PAL_RegisterModule
 
-  Same as LoadLibraryW, but with only the base name of
-  the library instead of a full filename.
---*/
+  Register the module with the target module and return a module handle in
+  the target module's context. Doesn't call the DllMain because it is used
+  as part of calling DllMain in the calling module.
 
-HMODULE
+--*/
+HINSTANCE
 PALAPI
-PAL_RegisterLibraryW(
-    IN LPCWSTR lpLibFileName)
+PAL_RegisterModule(
+    IN LPCSTR lpLibFileName)
 {
-    HMODULE hModule = NULL;
-    CHAR    lpstr[_MAX_FNAME];
-    INT     cbMultiByteShortName = 0;
+    HINSTANCE hinstance = nullptr;
 
-    static const char LIB_PREFIX[] = PAL_SHLIB_PREFIX;
-    static const char LIB_SUFFIX[] = PAL_SHLIB_SUFFIX;
-    static const int LIB_PREFIX_LENGTH = sizeof(LIB_PREFIX) - 1;
-    static const int LIB_SUFFIX_LENGTH = sizeof(LIB_SUFFIX) - 1;
+    int err = PAL_InitializeDLL();
+    if (err == 0)
+    {
+        PERF_ENTRY(PAL_RegisterModule);
+        ENTRY("PAL_RegisterModule(%s)\n", lpLibFileName ? lpLibFileName : "");
 
-    PERF_ENTRY(PAL_RegisterLibraryW);
-    ENTRY("PAL_RegisterLibraryW (lpLibFileName=%p (%S)) \n",
-          lpLibFileName?lpLibFileName:W16_NULLSTRING,
-          lpLibFileName?lpLibFileName:W16_NULLSTRING);
+        LockModuleList();
 
-    // First, copy the prefix into the buffer
-    if (strcpy_s(lpstr, sizeof(lpstr), LIB_PREFIX) != SAFECRT_SUCCESS)
-    {
-        ERROR("strcpy_s failed!\n");
-        SetLastError(ERROR_INSUFFICIENT_BUFFER);
-        goto Done;
+        void *dl_handle = LOADLoadLibraryDirect(lpLibFileName);
+        if (dl_handle)
+        {
+            // This only creates/adds the module handle and doesn't call DllMain
+            hinstance = LOADAddModule(dl_handle, lpLibFileName);
+        }
+
+        UnlockModuleList();
+
+        LOGEXIT("PAL_RegisterModule returns HINSTANCE %p\n", hinstance);
+        PERF_EXIT(PAL_RegisterModule);
     }
 
-    // Second, copy the file name, converting to multibyte along the way
-    cbMultiByteShortName = WideCharToMultiByte(CP_ACP, 0, lpLibFileName, -1, 
-                                               lpstr + LIB_PREFIX_LENGTH, 
-                                               _MAX_FNAME - (LIB_PREFIX_LENGTH + LIB_SUFFIX_LENGTH),
-                                               NULL, NULL);
+    return hinstance;
+}
+
+/*++
+Function:
+  PAL_UnregisterModule
+
+  Used to cleanup the module HINSTANCE from PAL_RegisterModule.
+--*/
+VOID
+PALAPI
+PAL_UnregisterModule(
+    IN HINSTANCE hInstance)
+{
+    PERF_ENTRY(PAL_UnregisterModule);
+    ENTRY("PAL_UnregisterModule(hInstance=%p)\n", hInstance);
+
+    LOADFreeLibrary((MODSTRUCT *)hInstance, FALSE /* fCallDllMain */);
+
+    LOGEXIT("PAL_UnregisterModule returns\n");
+    PERF_EXIT(PAL_UnregisterModule);
+}
+
+/*++
+    PAL_LOADLoadPEFile
+
+    Map a PE format file into memory like Windows LoadLibrary() would do.
+    Doesn't apply base relocations if the function is relocated.
+
+Parameters:
+    IN hFile - file to map
+
+Return value:
+    non-NULL - the base address of the mapped image
+    NULL - error, with last error set.
+--*/
+void *
+PALAPI
+PAL_LOADLoadPEFile(HANDLE hFile)
+{
+    ENTRY("PAL_LOADLoadPEFile (hFile=%p)\n", hFile);
+
+    void * loadedBase = MAPMapPEFile(hFile);
 
-    if (cbMultiByteShortName == 0)
+#ifdef _DEBUG
+    if (loadedBase != nullptr)
     {
-        DWORD dwLastError = GetLastError();
-        if (dwLastError == ERROR_INSUFFICIENT_BUFFER)
-        {
-            if (lstrlenW(lpLibFileName) + LIB_PREFIX_LENGTH + LIB_SUFFIX_LENGTH < _MAX_FNAME)
-            {
-                ASSERT("Insufficient buffer error returned incorrectly from WideCharToMultiByte!\n");
-            }
-            ERROR("lpLibFileName is larger than _MAX_FNAME (%d)!\n", _MAX_FNAME);
-        }
-        else
+        char* envVar = getenv("PAL_ForcePEMapFailure");
+        if (envVar && strlen(envVar) > 0)
         {
-            ASSERT("WideCharToMultiByte failure! error is %d\n", dwLastError);
+            TRACE("Forcing failure of PE file map, and retry\n");
+            PAL_LOADUnloadPEFile(loadedBase); // unload it
+            loadedBase = MAPMapPEFile(hFile); // load it again
         }
-        SetLastError(ERROR_INVALID_PARAMETER);
-        goto Done;
     }
+#endif // _DEBUG
 
-    // Last, add the suffix
-    if (strcat_s(lpstr, sizeof(lpstr), LIB_SUFFIX) != SAFECRT_SUCCESS)
-    {
-        ERROR("strcat_s failed!\n");
-        SetLastError(ERROR_INSUFFICIENT_BUFFER);
-        goto Done;
-    }
+    LOGEXIT("PAL_LOADLoadPEFile returns %p\n", loadedBase);
+    return loadedBase;
+}
 
-    FILEDosToUnixPathA(lpstr);
+/*++
+    PAL_LOADUnloadPEFile
 
-    hModule = LOADLoadLibrary(lpstr, FALSE);
+    Unload a PE file that was loaded by PAL_LOADLoadPEFile().
 
-Done:
-    LOGEXIT("PAL_RegisterLibraryW returns HMODULE %p\n", hModule);
-    PERF_EXIT(PAL_RegisterLibraryW);
-    return hModule;
-}
+Parameters:
+    IN ptr - the file pointer returned by PAL_LOADLoadPEFile()
 
+Return value:
+    TRUE - success
+    FALSE - failure (incorrect ptr, etc.)
+--*/
+BOOL 
+PALAPI
+PAL_LOADUnloadPEFile(void * ptr)
+{
+    BOOL retval = FALSE;
+
+    ENTRY("PAL_LOADUnloadPEFile (ptr=%p)\n", ptr);
+
+    if (nullptr == ptr)
+    {
+        ERROR( "Invalid pointer value\n" );
+    }
+    else
+    {
+        retval = MAPUnmapPEFile(ptr);
+    }
+
+    LOGEXIT("PAL_LOADUnloadPEFile returns %d\n", retval);
+    return retval;
+}
 
 /*++
-Function:
-  PAL_UnregisterLibraryW
+    PAL_GetSymbolModuleBase
+
+    Get base address of the module containing a given symbol 
 
-  Same as FreeLibrary.
+Parameters:
+    void *symbol - address of symbol
+
+Return value:
+    module base address
 --*/
-BOOL
+LPCVOID
 PALAPI
-PAL_UnregisterLibraryW(
-    IN OUT HMODULE hLibModule)
+PAL_GetSymbolModuleBase(void *symbol)
 {
-    BOOL retval;
+    LPCVOID retval = nullptr;
 
-    PERF_ENTRY(PAL_UnregisterLibraryW);
-    ENTRY("PAL_UnregisterLibraryW (hLibModule=%p)\n", hLibModule);
+    PERF_ENTRY(PAL_GetPalModuleBase);
+    ENTRY("PAL_GetPalModuleBase\n");
 
-    retval = FreeLibrary(hLibModule);
+    if (symbol == nullptr)
+    {
+        TRACE("Can't get base address. Argument symbol == nullptr\n");
+        SetLastError(ERROR_INVALID_DATA);
+    }
+    else 
+    {
+        Dl_info info;
+        if (dladdr(symbol, &info) != 0)
+        {
+            retval = info.dli_fbase;
+        }
+        else 
+        {
+            TRACE("Can't get base address of the current module\n");
+            SetLastError(ERROR_INVALID_DATA);
+        }        
+    }
 
-    LOGEXIT("PAL_UnregisterLibraryW returns BOOL %d\n", retval);
-    PERF_EXIT(PAL_UnregisterLibraryW);
+    LOGEXIT("PAL_GetPalModuleBase returns %p\n", retval);
+    PERF_EXIT(PAL_GetPalModuleBase);
     return retval;
 }
 
@@ -948,7 +857,7 @@ Return value :
 extern "C"
 BOOL LOADInitializeModules()
 {
-    _ASSERTE(exe_module.prev == NULL);
+    _ASSERTE(exe_module.prev == nullptr);
 
     InternalInitializeCriticalSection(&module_critsec);
 
@@ -956,18 +865,18 @@ BOOL LOADInitializeModules()
     TRACE("Initializing module for main executable\n");
 
     exe_module.self = (HMODULE)&exe_module;
-    exe_module.dl_handle = dlopen(NULL, RTLD_LAZY);
-    if (exe_module.dl_handle == NULL)
+    exe_module.dl_handle = dlopen(nullptr, RTLD_LAZY);
+    if (exe_module.dl_handle == nullptr)
     {
-        ERROR("Executable module will be broken : dlopen(NULL) failed dlerror message is \"%s\" \n", dlerror());
+        ERROR("Executable module will be broken : dlopen(nullptr) failed dlerror message is \"%s\" \n", dlerror());
         return FALSE;
     }
-    exe_module.lib_name = NULL;
+    exe_module.lib_name = nullptr;
     exe_module.refcount = -1;
     exe_module.next = &exe_module;
     exe_module.prev = &exe_module;
-    exe_module.pDllMain = NULL;
-    exe_module.hinstance = NULL;
+    exe_module.pDllMain = nullptr;
+    exe_module.hinstance = nullptr;
     exe_module.threadLibCalls = TRUE;
     return TRUE;
 }
@@ -990,7 +899,7 @@ extern "C"
 BOOL LOADSetExeName(LPWSTR name)
 {
 #if RETURNS_NEW_HANDLES_ON_REPEAT_DLOPEN
-    LPSTR pszExeName = NULL;
+    LPSTR pszExeName = nullptr;
 #endif
     BOOL result = FALSE;
 
@@ -1006,7 +915,7 @@ BOOL LOADSetExeName(LPWSTR name)
     {
         struct stat stat_buf;
         pszExeName = UTIL_WCToMB_Alloc(name, -1);
-        if (NULL == pszExeName)
+        if (nullptr == pszExeName)
         {
             ERROR("WCToMB failure, unable to get full name of exe\n");
             goto exit;
@@ -1037,70 +946,6 @@ exit:
 
 /*++
 Function :
-    LOADFreeModules
-
-    Release all resources held by the module manager (including dlopen handles)
-
-Parameters:
-    BOOL bTerminateUnconditionally: If TRUE, this will avoid calling any DllMains
-
-    (no return value)
---*/
-extern "C"
-void LOADFreeModules(BOOL bTerminateUnconditionally)
-{
-    MODSTRUCT *module;
-
-    if (!exe_module.prev)
-    {
-        ERROR("Module manager not initialized!\n");
-        return;
-    }
-
-    LockModuleList();
-
-    /* Go through the list of modules, release any references we still hold.
-       The list is traversed from newest module to oldest */
-    do
-    {
-        module = exe_module.prev;
-
-        // Call DllMain if the module contains one and if we're supposed
-        // to call DllMains.
-        if (!bTerminateUnconditionally && module->pDllMain)
-        {
-           /* Exception-safe call to DllMain */
-           LOAD_SEH_CallDllMain(module, DLL_PROCESS_DETACH, (LPVOID)-1);
-        }
-
-        /* Remove the current MODSTRUCT from the list, then free its memory */
-        module->prev->next = module->next;
-        module->next->prev = module->prev;
-        module->self = NULL;
-
-        if (module->dl_handle)
-            dlclose( module->dl_handle );
-
-        InternalFree( module->lib_name );
-        module->lib_name = NULL;
-        if (module != &exe_module)
-        {
-            InternalFree( module );
-        }
-    }
-    while (module != &exe_module);
-
-    /* Flag the module manager as uninitialized */
-    exe_module.prev = NULL;
-
-    TRACE("Module manager stopped.\n");
-
-    UnlockModuleList();
-    DeleteCriticalSection(&module_critsec);
-}
-
-/*++
-Function :
     LOADCallDllMain
 
     Call DllMain for all modules (that have one) with the given "fwReason"
@@ -1122,7 +967,7 @@ Notes :
 extern "C"
 void LOADCallDllMain(DWORD dwReason, LPVOID lpReserved)
 {
-    MODSTRUCT *module = NULL;
+    MODSTRUCT *module = nullptr;
     BOOL InLoadOrder = TRUE; /* true if in load order, false for reverse */
     CPalThread *pThread;
     
@@ -1157,7 +1002,9 @@ void LOADCallDllMain(DWORD dwReason, LPVOID lpReserved)
     LockModuleList();
 
     module = &exe_module;
-    do {
+
+    do
+    {
         if (!InLoadOrder)
             module = module->prev;
 
@@ -1165,34 +1012,179 @@ void LOADCallDllMain(DWORD dwReason, LPVOID lpReserved)
         {
             if (module->pDllMain)
             {
-#if _ENABLE_DEBUG_MESSAGES_
-                /* reset ENTRY nesting level back to zero while inside the callback... */
-                int old_level;
-                old_level = DBG_change_entrylevel(0);
-#endif /* _ENABLE_DEBUG_MESSAGES_ */
-
-                {
-                    // This module may be foreign to our PAL, so leave our PAL.
-                    // If it depends on us, it will re-enter.
-                    PAL_LeaveHolder holder;
-                    module->pDllMain(module->hinstance, dwReason, lpReserved);
-                }
-
-#if _ENABLE_DEBUG_MESSAGES_
-                /* ...and set nesting level back to what it was */
-                DBG_change_entrylevel(old_level);
-#endif /* _ENABLE_DEBUG_MESSAGES_ */
+                LOADCallDllMainSafe(module, dwReason, lpReserved);
             }
         }
 
         if (InLoadOrder)
             module = module->next;
+
     } while (module != &exe_module);
 
-    UnlockModuleList();
+    UnlockModuleList();
+}
+
+/*++
+Function:
+  LOADFreeLibrary
+
+Parameters:
+  MODSTRUCT * module - module to free
+  BOOL fCallDllMain - if TRUE, call the DllMain function
+
+Returns:
+  TRUE if successful
+
+--*/
+static BOOL LOADFreeLibrary(MODSTRUCT *module, BOOL fCallDllMain)
+{
+    BOOL retval = FALSE;
+
+    LockModuleList();
+
+    if (terminator)
+    {
+        /* PAL shutdown is in progress - ignore FreeLibrary calls */
+        retval = TRUE;
+        goto done;
+    }
+
+    if (!LOADValidateModule(module))
+    {
+        TRACE("Can't free invalid module %p\n", module);
+        SetLastError(ERROR_INVALID_HANDLE);
+        goto done;
+    }
+
+    if (module->refcount == -1)
+    {
+        /* special module - never released */
+        retval = TRUE;
+        goto done;
+    }
+
+    module->refcount--;
+    TRACE("Reference count for module %p (named %S) decreases to %d\n",
+            module, MODNAME(module), module->refcount);
+
+    if (module->refcount != 0)
+    {
+        retval = TRUE;
+        goto done;
+    }
+
+    /* Releasing the last reference : call dlclose(), remove module from the
+       process-wide module list */
+
+    TRACE("Reference count for module %p (named %S) now 0; destroying module structure\n", 
+        module, MODNAME(module));
+
+    /* unlink the module structure from the list */
+    module->prev->next = module->next;
+    module->next->prev = module->prev;
+
+    /* remove the circular reference so that LOADValidateModule will fail */
+    module->self = nullptr;
+
+    /* Call DllMain if the module contains one */
+    if (fCallDllMain && module->pDllMain)
+    {
+        LOADCallDllMainSafe(module, DLL_PROCESS_DETACH, nullptr);
+    }
+
+    if (module->hinstance)
+    {
+        PUNREGISTER_MODULE unregisterModule = (PUNREGISTER_MODULE)dlsym(module->dl_handle, "PAL_UnregisterModule");
+        if (unregisterModule != nullptr)
+        {
+             unregisterModule(module->hinstance);
+        }
+        module->hinstance = nullptr;
+    }
+
+    if (module->dl_handle && 0 != dlclose(module->dl_handle))
+    {
+        /* report dlclose() failure, but proceed anyway. */
+        WARN("dlclose() call failed! error message is \"%s\"\n", dlerror());
+    }
+
+    /* release all memory */
+    InternalFree(module->lib_name);
+    InternalFree(module);
+
+    retval = TRUE;
+
+done:
+    UnlockModuleList();
+    return retval;
+}
+
+/*++
+Function :
+    LOADCallDllMainSafe
+
+    Exception-safe call to DllMain.
+
+Parameters :
+    MODSTRUCT *module : module whose DllMain must be called
+
+    DWORD dwReason : parameter to pass down to DllMain, one of DLL_PROCESS_ATTACH, DLL_PROCESS_DETACH, 
+        DLL_THREAD_ATTACH, DLL_THREAD_DETACH
+
+    LPVOID lpvReserved : parameter to pass down to DllMain,
+        If dwReason is DLL_PROCESS_ATTACH, lpvReserved is NULL for dynamic loads and non-NULL for static loads. 
+        If dwReason is DLL_PROCESS_DETACH, lpvReserved is NULL if DllMain has been called by using FreeLibrary 
+            and non-NULL if DllMain has been called during process termination. 
+
+Returns:
+    BOOL : DllMain's return value
+*/
+static BOOL LOADCallDllMainSafe(MODSTRUCT *module, DWORD dwReason, LPVOID lpReserved)
+{
+#if _ENABLE_DEBUG_MESSAGES_
+    /* reset ENTRY nesting level back to zero while inside the callback... */
+    int old_level = DBG_change_entrylevel(0);
+#endif /* _ENABLE_DEBUG_MESSAGES_ */
+    
+    struct Param
+    {
+        MODSTRUCT *module;
+        DWORD dwReason;
+        LPVOID lpReserved;
+        BOOL ret;
+    } param;
+    param.module = module;
+    param.dwReason = dwReason;
+    param.lpReserved = lpReserved;
+    param.ret = FALSE;
+
+    PAL_TRY(Param *, pParam, &param)
+    {
+        TRACE("Calling DllMain (%p) for module %S\n",
+              pParam->module->pDllMain, 
+              pParam->module->lib_name ? pParam->module->lib_name : W16_NULLSTRING);
+        
+        {
+            // This module may be foreign to our PAL, so leave our PAL.
+            // If it depends on us, it will re-enter.
+            PAL_LeaveHolder holder;
+            pParam->ret = pParam->module->pDllMain(pParam->module->hinstance, pParam->dwReason, pParam->lpReserved);
+        }
+    }
+    PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        WARN("Call to DllMain (%p) got an unhandled exception; ignoring.\n", module->pDllMain);
+    }
+    PAL_ENDTRY
+
+#if _ENABLE_DEBUG_MESSAGES_
+    /* ...and set nesting level back to what it was */
+    DBG_change_entrylevel(old_level);
+#endif /* _ENABLE_DEBUG_MESSAGES_ */
+
+    return param.ret;
 }
 
-
 /*++
 Function:
     DisableThreadLibraryCalls
@@ -1209,14 +1201,15 @@ DisableThreadLibraryCalls(
     PERF_ENTRY(DisableThreadLibraryCalls);
     ENTRY("DisableThreadLibraryCalls(hLibModule=%p)\n", hLibModule);
 
+    LockModuleList();
+
     if (terminator)
     {
         /* PAL shutdown in progress - ignore DisableThreadLibraryCalls */
         ret = TRUE;
-        goto done_nolock;
+        goto done;
     }
 
-    LockModuleList();
     module = (MODSTRUCT *) hLibModule;
 
     if (!LOADValidateModule(module))
@@ -1234,18 +1227,14 @@ DisableThreadLibraryCalls(
 
 done:
     UnlockModuleList();
-done_nolock:
     LOGEXIT("DisableThreadLibraryCalls returns BOOL %d\n", ret);
     PERF_EXIT(DisableThreadLibraryCalls);
     return ret;
 }
 
-
-/* Static function definitions ************************************************/
-
 // Checks the library path for null or empty string. On error, calls SetLastError() and returns false.
 template<class TChar>
-bool LOADVerifyLibraryPath(const TChar *libraryPath)
+static bool LOADVerifyLibraryPath(const TChar *libraryPath)
 {
     if (libraryPath == nullptr)
     {
@@ -1263,7 +1252,7 @@ bool LOADVerifyLibraryPath(const TChar *libraryPath)
 }
 
 // Converts the wide char library path string into a multibyte-char string. On error, calls SetLastError() and returns false.
-bool LOADConvertLibraryPathWideStringToMultibyteString(
+static bool LOADConvertLibraryPathWideStringToMultibyteString(
     LPCWSTR wideLibraryPath,
     LPSTR multibyteLibraryPath,
     INT *multibyteLibraryPathLengthRef)
@@ -1304,14 +1293,13 @@ Parameters :
 Return value :
     TRUE if module is valid, FALSE otherwise
 
+NOTE :
+    The module lock MUST be owned.
+
 --*/
 static BOOL LOADValidateModule(MODSTRUCT *module)
 {
-    MODSTRUCT *modlist_enum;
-
-    LockModuleList();
-
-    modlist_enum = &exe_module;
+    MODSTRUCT *modlist_enum = &exe_module;
 
     /* enumerate through the list of modules to make sure the given handle is
        really a module (HMODULEs are actually MODSTRUCT pointers) */
@@ -1323,10 +1311,8 @@ static BOOL LOADValidateModule(MODSTRUCT *module)
             if (module->self != module)
             {
                 ERROR("Found corrupt module %p!\n",module);
-                UnlockModuleList();
                 return FALSE;
             }
-            UnlockModuleList();
             TRACE("Module %p is valid (name : %S)\n", module, MODNAME(module));
             return TRUE;
         }
@@ -1335,7 +1321,6 @@ static BOOL LOADValidateModule(MODSTRUCT *module)
     while (modlist_enum != &exe_module);
 
     TRACE("Module %p is NOT valid.\n", module);
-    UnlockModuleList();
     return FALSE;
 }
 
@@ -1431,18 +1416,18 @@ static MODSTRUCT *LOADAllocModule(void *dl_handle, LPCSTR name)
 
     /* no match found : try to create a new module structure */
     module = (MODSTRUCT *)InternalMalloc(sizeof(MODSTRUCT));
-    if (!module)
+    if (nullptr == module)
     {
         ERROR("malloc() failed! errno is %d (%s)\n", errno, strerror(errno));
-        return NULL;
+        return nullptr;
     }
 
     wide_name = UTIL_MBToWC_Alloc(name, -1);
-    if (NULL == wide_name)
+    if (nullptr == wide_name)
     {
         ERROR("couldn't convert name to a wide-character string\n");
         InternalFree(module);
-        return NULL;
+        return nullptr;
     }
 
     module->dl_handle = dl_handle;
@@ -1459,10 +1444,11 @@ static MODSTRUCT *LOADAllocModule(void *dl_handle, LPCSTR name)
     module->refcount = 1;
 #endif  // NEED_DLCOMPAT
     module->self = module;
-    module->hinstance = NULL;
+    module->hinstance = nullptr;
     module->threadLibCalls = TRUE;
-    module->next = NULL;
-    module->prev = NULL;
+    module->pDllMain = nullptr;
+    module->next = nullptr;
+    module->prev = nullptr;
 
     module->lib_name = wide_name;
 
@@ -1514,7 +1500,7 @@ static MODSTRUCT *LOADAddModule(void *dl_handle, LPCSTR libraryNameOrPath)
     TRACE("Module doesn't exist : creating %s.\n", libraryNameOrPath);
 
     module = LOADAllocModule(dl_handle, libraryNameOrPath);
-    if (NULL == module)
+    if (nullptr == module)
     {
         ERROR("couldn't create new module\n");
         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
@@ -1522,6 +1508,9 @@ static MODSTRUCT *LOADAddModule(void *dl_handle, LPCSTR libraryNameOrPath)
         return nullptr;
     }
 
+    /* We now get the address of DllMain if the module contains one. */
+    module->pDllMain = (PDLLMAIN)dlsym(module->dl_handle, "DllMain");
+
     /* Add the new module on to the end of the list */
     module->prev = exe_module.prev;
     module->next = &exe_module;
@@ -1558,17 +1547,14 @@ static HMODULE LOADRegisterLibraryDirect(void *dl_handle, LPCSTR libraryNameOrPa
         return nullptr;
     }
 
-    /* We now get the address of DllMain if the module contains one. */
-    module->pDllMain = (PDLLMAIN)dlsym(module->dl_handle, "DllMain");
-
-    /* If it did contain a DllMain, call it. */
+    /* If the module contains a DllMain, call it. */
     if (module->pDllMain)
     {
         TRACE("Calling DllMain (%p) for module %S\n",
             module->pDllMain,
             module->lib_name ? module->lib_name : W16_NULLSTRING);
 
-        if (NULL == module->hinstance)
+        if (nullptr == module->hinstance)
         {
             PREGISTER_MODULE registerModule = (PREGISTER_MODULE)dlsym(module->dl_handle, "PAL_RegisterModule");
             if (registerModule != nullptr)
@@ -1584,36 +1570,16 @@ static HMODULE LOADRegisterLibraryDirect(void *dl_handle, LPCSTR libraryNameOrPa
             }
         }
 
-        BOOL dllMainRetVal;
-        {
-#if _ENABLE_DEBUG_MESSAGES_
-            /* reset ENTRY nesting level back to zero while inside the callback... */
-            int old_level;
-            old_level = DBG_change_entrylevel(0);
-#endif /* _ENABLE_DEBUG_MESSAGES_ */
-
-            {
-                // This module may be foreign to our PAL, so leave our PAL.
-                // If it depends on us, it will re-enter.
-                PAL_LeaveHolder holder;
-                dllMainRetVal = module->pDllMain(module->hinstance, DLL_PROCESS_ATTACH, fDynamic ? NULL : (LPVOID)-1);
-            }
-
-#if _ENABLE_DEBUG_MESSAGES_
-            /* ...and set nesting level back to what it was */
-            DBG_change_entrylevel(old_level);
-#endif /* _ENABLE_DEBUG_MESSAGES_ */
-        }
+        BOOL dllMainRetVal = LOADCallDllMainSafe(module, DLL_PROCESS_ATTACH, fDynamic ? nullptr : (LPVOID)-1);
 
         // If DlMain(DLL_PROCESS_ATTACH) returns FALSE, we must immediately unload the module
         if (!dllMainRetVal)
         {
             ERROR("DllMain returned FALSE; unloading module.\n");
-            module->pDllMain = NULL;
+            module->pDllMain = nullptr;
             FreeLibrary((HMODULE)module);
             SetLastError(ERROR_DLL_INIT_FAILED);
-            module = NULL;
-            return nullptr;
+            module = nullptr;
         }
     }
     else
@@ -1641,8 +1607,8 @@ Return value :
 --*/
 static HMODULE LOADLoadLibrary(LPCSTR shortAsciiName, BOOL fDynamic)
 {
-    HMODULE module = NULL;
-    void *dl_handle = NULL;
+    HMODULE module = nullptr;
+    void *dl_handle = nullptr;
 
     // Check whether we have been requested to load 'libc'. If that's the case then use the
     // full name of the library that is defined in <gnu/lib-names.h> by the LIBC_SO constant.
@@ -1674,189 +1640,6 @@ static HMODULE LOADLoadLibrary(LPCSTR shortAsciiName, BOOL fDynamic)
 }
 
 /*++
-Function :
-    LOAD_SEH_CallDllMain
-
-    Exception-safe call to DllMain.
-
-Parameters :
-    MODSTRUCT *module : module whose DllMain must be called
-
-    DWORD dwReason : parameter to pass down to DllMain, one of DLL_PROCESS_ATTACH, DLL_PROCESS_DETACH, 
-        DLL_THREAD_ATTACH, DLL_THREAD_DETACH
-
-    LPVOID lpvReserved : parameter to pass down to DllMain,
-        If dwReason is DLL_PROCESS_ATTACH, lpvReserved is NULL for dynamic loads and non-NULL for static loads. 
-        If dwReason is DLL_PROCESS_DETACH, lpvReserved is NULL if DllMain has been called by using FreeLibrary 
-            and non-NULL if DllMain has been called during process termination. 
-
-(no return value)
-
-Notes :
-This function is called from LOADFreeModules. Since we get there from
-PAL_Terminate, we can't let exceptions in DllMain go unhandled :
-TerminateProcess would be called, and would have to abort uncleanly because
-termination was already started. So we catch the exception and ignore it;
-we're terminating anyway.
-*/
-static void LOAD_SEH_CallDllMain(MODSTRUCT *module, DWORD dwReason, LPVOID lpReserved)
-{
-#if _ENABLE_DEBUG_MESSAGES_
-    /* reset ENTRY nesting level back to zero while inside the callback... */
-    int old_level = DBG_change_entrylevel(0);
-#endif /* _ENABLE_DEBUG_MESSAGES_ */
-    
-    struct Param
-    {
-        MODSTRUCT *module;
-        DWORD dwReason;
-        LPVOID lpReserved;
-    } param;
-    param.module = module;
-    param.dwReason = dwReason;
-    param.lpReserved = lpReserved;
-
-    PAL_TRY(Param *, pParam, &param)
-    {
-        TRACE("Calling DllMain (%p) for module %S\n",
-              pParam->module->pDllMain, 
-              pParam->module->lib_name ? pParam->module->lib_name : W16_NULLSTRING);
-        
-        {
-            // This module may be foreign to our PAL, so leave our PAL.
-            // If it depends on us, it will re-enter.
-            PAL_LeaveHolder holder;
-            pParam->module->pDllMain(pParam->module->hinstance, pParam->dwReason, pParam->lpReserved);
-        }
-    }
-    PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-    {
-        WARN("Call to DllMain (%p) got an unhandled exception; "
-              "ignoring.\n", module->pDllMain);
-    }
-    PAL_ENDTRY
-
-#if _ENABLE_DEBUG_MESSAGES_
-    /* ...and set nesting level back to what it was */
-    DBG_change_entrylevel(old_level);
-#endif /* _ENABLE_DEBUG_MESSAGES_ */
-}
-
-/*++
-Function:
-  LockModuleList
-
-Abstract
-  Enter the critical section associated to the module list
-
-Parameter
-  void
-
-Return
-  void
---*/
-extern "C"
-void LockModuleList()
-{
-    CPalThread * pThread = 
-        (PALIsThreadDataInitialized() ? InternalGetCurrentThread() : NULL);
-
-    InternalEnterCriticalSection(pThread , &module_critsec);
-}
-
-/*++
-Function:
-  UnlockModuleList
-
-Abstract
-  Leave the critical section associated to the module list
-
-Parameter
-  void
-
-Return
-  void
---*/
-extern "C"
-void UnlockModuleList()
-{
-    CPalThread * pThread = 
-        (PALIsThreadDataInitialized() ? InternalGetCurrentThread() : NULL);
-
-    InternalLeaveCriticalSection(pThread , &module_critsec);
-}
-
-/*++
-    PAL_LOADLoadPEFile
-
-    Map a PE format file into memory like Windows LoadLibrary() would do.
-    Doesn't apply base relocations if the function is relocated.
-
-Parameters:
-    IN hFile - file to map
-
-Return value:
-    non-NULL - the base address of the mapped image
-    NULL - error, with last error set.
---*/
-
-void * PAL_LOADLoadPEFile(HANDLE hFile)
-{
-    ENTRY("PAL_LOADLoadPEFile (hFile=%p)\n", hFile);
-
-    void * loadedBase = MAPMapPEFile(hFile);
-
-#ifdef _DEBUG
-    if (loadedBase != NULL)
-    {
-        char* envVar = getenv("PAL_ForcePEMapFailure");
-        if (envVar && strlen(envVar) > 0)
-        {
-            TRACE("Forcing failure of PE file map, and retry\n");
-            PAL_LOADUnloadPEFile(loadedBase); // unload it
-            loadedBase = MAPMapPEFile(hFile); // load it again
-        }
-    }
-#endif // _DEBUG
-
-    LOGEXIT("PAL_LOADLoadPEFile returns %p\n", loadedBase);
-    return loadedBase;
-}
-
-
-/*++
-    PAL_LOADUnloadPEFile
-
-    Unload a PE file that was loaded by PAL_LOADLoadPEFile().
-
-Parameters:
-    IN ptr - the file pointer returned by PAL_LOADLoadPEFile()
-
-Return value:
-    TRUE - success
-    FALSE - failure (incorrect ptr, etc.)
---*/
-
-BOOL PAL_LOADUnloadPEFile(void * ptr)
-{
-    BOOL retval = FALSE;
-
-    ENTRY("PAL_LOADUnloadPEFile (ptr=%p)\n", ptr);
-
-    if (NULL == ptr)
-    {
-        ERROR( "Invalid pointer value\n" );
-    }
-    else
-    {
-        retval = MAPUnmapPEFile(ptr);
-    }
-
-    LOGEXIT("PAL_LOADUnloadPEFile returns %d\n", retval);
-    return retval;
-}
-
-/*++
     LOADInitializeCoreCLRModule
 
     Run the initialization methods for CoreCLR module (the module containing this PAL).
@@ -1882,7 +1665,7 @@ BOOL LOADInitializeCoreCLRModule()
         ERROR("Can not find the CoreDllMain entry point\n");
         return FALSE;
     }
-    return pRuntimeDllMain(module->hinstance, DLL_PROCESS_ATTACH, NULL);
+    return pRuntimeDllMain(module->hinstance, DLL_PROCESS_ATTACH, nullptr);
 }
 
 /*++
@@ -1900,7 +1683,7 @@ Return value :
 --*/
 MODSTRUCT *LOADGetPalLibrary()
 {
-    if (pal_module == NULL)
+    if (pal_module == nullptr)
     {
         // Initialize the pal module (the module containing LOADGetPalLibrary). Assumes that 
         // the PAL is linked into the coreclr module because we use the module name containing 
@@ -1915,11 +1698,11 @@ MODSTRUCT *LOADGetPalLibrary()
         }
         // Stash a copy of the CoreCLR installation path in a global variable.
         // Make sure it's terminated with a slash.
-        if (g_szCoreCLRPath == NULL)
+        if (g_szCoreCLRPath == nullptr)
         {
             g_szCoreCLRPath = (char*) InternalMalloc(g_cbszCoreCLRPath);
 
-            if (g_szCoreCLRPath == NULL)
+            if (g_szCoreCLRPath == nullptr)
             {
                 ERROR("LOADGetPalLibrary: InternalMalloc failed!");
                 goto exit;
@@ -1938,37 +1721,46 @@ exit:
     return pal_module;
 }
 
-// Get base address of the module containing a given symbol 
-PALAPI
-LPCVOID
-PAL_GetSymbolModuleBase(void *symbol)
-{
-    LPCVOID retval = NULL;
+/*++
+Function:
+  LockModuleList
 
-    PERF_ENTRY(PAL_GetPalModuleBase);
-    ENTRY("PAL_GetPalModuleBase\n");
+Abstract
+  Enter the critical section associated to the module list
 
-    if (symbol == NULL)
-    {
-        TRACE("Can't get base address. Argument symbol == NULL\n");
-        SetLastError(ERROR_INVALID_DATA);
-    }
-    else 
-    {
-        Dl_info info;
-        if (dladdr(symbol, &info) != 0)
-        {
-            retval = info.dli_fbase;
-        }
-        else 
-        {
-            TRACE("Can't get base address of the current module\n");
-            SetLastError(ERROR_INVALID_DATA);
-        }        
-    }
+Parameter
+  void
 
-    LOGEXIT("PAL_GetPalModuleBase returns %p\n", retval);
-    PERF_EXIT(PAL_GetPalModuleBase);
-    return retval;
+Return
+  void
+--*/
+extern "C"
+void LockModuleList()
+{
+    CPalThread * pThread = 
+        (PALIsThreadDataInitialized() ? InternalGetCurrentThread() : nullptr);
+
+    InternalEnterCriticalSection(pThread, &module_critsec);
 }
 
+/*++
+Function:
+  UnlockModuleList
+
+Abstract
+  Leave the critical section associated to the module list
+
+Parameter
+  void
+
+Return
+  void
+--*/
+extern "C"
+void UnlockModuleList()
+{
+    CPalThread * pThread = 
+        (PALIsThreadDataInitialized() ? InternalGetCurrentThread() : nullptr);
+
+    InternalLeaveCriticalSection(pThread, &module_critsec);
+}
index 88a265b..0953bf0 100644 (file)
@@ -1145,8 +1145,8 @@ See MSDN doc.
 BOOL
 PALAPI
 GetExitCodeProcess(
-           IN HANDLE hProcess,
-           IN LPDWORD lpExitCode)
+    IN HANDLE hProcess,
+    IN LPDWORD lpExitCode)
 {
     CPalThread *pThread;
     PAL_ERROR palError = NO_ERROR;
@@ -1211,17 +1211,16 @@ PAL_NORETURN
 VOID
 PALAPI
 ExitProcess(
-        IN UINT uExitCode)
+    IN UINT uExitCode)
 {
     DWORD old_terminator;
 
     PERF_ENTRY_ONLY(ExitProcess);
     ENTRY("ExitProcess(uExitCode=0x%x)\n", uExitCode );
 
-    old_terminator = InterlockedCompareExchange(&terminator,
-                                                GetCurrentThreadId(),0);
+    old_terminator = InterlockedCompareExchange(&terminator, GetCurrentThreadId(), 0);
 
-    if(GetCurrentThreadId() == old_terminator)
+    if (GetCurrentThreadId() == old_terminator)
     {
         // This thread has already initiated termination. This can happen
         // in two ways:
@@ -1240,7 +1239,7 @@ ExitProcess(
             PROCEndProcess(GetCurrentProcess(), uExitCode, FALSE);
         }
     }
-    else if(0 != old_terminator)
+    else if (0 != old_terminator)
     {
         /* another thread has already initiated the termination process. we 
            could just block on the PALInitLock critical section, but then 
@@ -1250,13 +1249,13 @@ ExitProcess(
            Update: [TODO] PROCSuspendOtherThreads has been removed. Can this 
            code be changed? */
         WARN("termination already started from another thread; blocking.\n");
-        poll(NULL,0,INFTIM);
+        poll(NULL, 0, INFTIM);
     }
 
     /* ExitProcess may be called even if PAL is not initialized.
        Verify if process structure exist
     */
-    if ( PALInitLock() && PALIsInitialized() )
+    if (PALInitLock() && PALIsInitialized())
     {
         PROCEndProcess(GetCurrentProcess(), uExitCode, FALSE);
 
@@ -1276,7 +1275,6 @@ ExitProcess(
     for (;;);
 }
 
-
 /*++
 Function:
   TerminateProcess
@@ -1289,8 +1287,8 @@ See MSDN doc.
 BOOL
 PALAPI
 TerminateProcess(
-         IN HANDLE hProcess,
-         IN UINT uExitCode)
+    IN HANDLE hProcess,
+    IN UINT uExitCode)
 {
     BOOL ret;
 
@@ -1315,8 +1313,7 @@ Function:
   down any DLLs that are loaded.
 
 --*/
-static BOOL PROCEndProcess(HANDLE hProcess, UINT uExitCode,
-                           BOOL bTerminateUnconditionally)
+static BOOL PROCEndProcess(HANDLE hProcess, UINT uExitCode, BOOL bTerminateUnconditionally)
 {
     DWORD dwProcessId;
     BOOL ret = FALSE;
@@ -2767,35 +2764,35 @@ CorUnix::TerminateCurrentProcessNoExit(BOOL bTerminateUnconditionally)
     BOOL locked;
     DWORD old_terminator;
 
-    old_terminator = InterlockedCompareExchange(&terminator,
-                                                    GetCurrentThreadId(),0);
+    old_terminator = InterlockedCompareExchange(&terminator, GetCurrentThreadId(), 0);
 
-    if(0 != old_terminator && GetCurrentThreadId() != old_terminator)
+    if (0 != old_terminator && GetCurrentThreadId() != old_terminator)
     {
-        /* another thread has already initiated the termination process. we
-        could just block on the PALInitLock critical section, but then
-        PROCSuspendOtherThreads would hang... so sleep forever here, we're
-        terminating anyway
-
-        Update: [TODO] PROCSuspendOtherThreads has been removed. Can this 
-           code be changed? */
-
-        /* note that if *this* thread has already started the termination
-        process, we want to proceed. the only way this can happen is if a
-        call to DllMain (from ExitProcess) brought us here (because DllMain
-        called ExitProcess, or TerminateProcess, or ExitThread);
-        TerminateProcess won't call DllMain, so there's no danger to get
-        caught in an infinite loop */
+         /* another thread has already initiated the termination process. we
+            could just block on the PALInitLock critical section, but then
+            PROCSuspendOtherThreads would hang... so sleep forever here, we're
+            terminating anyway
+            Update: [TODO] PROCSuspendOtherThreads has been removed. Can this 
+            code be changed? */
+
+         /* note that if *this* thread has already started the termination
+            process, we want to proceed. the only way this can happen is if a
+            call to DllMain (from ExitProcess) brought us here (because DllMain
+            called ExitProcess, or TerminateProcess, or ExitThread);
+            TerminateProcess won't call DllMain, so there's no danger to get
+            caught in an infinite loop */
          WARN("termination already started from another thread; blocking.\n");
-         poll(NULL,0,INFTIM);
+         poll(NULL, 0, INFTIM);
      }
 
      /* Try to lock the initialization count to prevent multiple threads from
-     terminating/initializing the PAL simultaneously */
+        terminating/initializing the PAL simultaneously */
+
      /* note : it's also important to take this lock before the process lock,
-     because Init/Shutdown take the init lock, and the functions they call
-     may take the process lock. We must do it in the same order to avoid
-     deadlocks */
+        because Init/Shutdown take the init lock, and the functions they call
+        may take the process lock. We must do it in the same order to avoid
+        deadlocks */
      locked = PALInitLock();
      if(locked && PALIsInitialized())
      {
index fdc6661..aaf1f27 100644 (file)
@@ -10,5 +10,4 @@ add_subdirectory(PAL_errno)
 add_subdirectory(PAL_GetPALDirectoryW)
 add_subdirectory(pal_initializedebug)
 add_subdirectory(PAL_Initialize_Terminate)
-add_subdirectory(PAL_RegisterLibraryW_UnregisterLibraryW)
 
index 6bc6022..f8c4ee7 100644 (file)
@@ -719,7 +719,6 @@ pal_specific/PAL_errno/test1/paltest_pal_errno_test1
 pal_specific/pal_initializedebug/test1/paltest_pal_initializedebug_test1
 pal_specific/PAL_Initialize_Terminate/test1/paltest_pal_initialize_terminate_test1
 pal_specific/PAL_Initialize_Terminate/test2/paltest_pal_initialize_terminate_test2
-pal_specific/PAL_RegisterLibraryW_UnregisterLibraryW/test2_neg/paltest_reg_unreg_libraryw_neg
 samples/test1/paltest_samples_test1
 threading/CreateEventA/test1/paltest_createeventa_test1
 threading/CreateEventA/test2/paltest_createeventa_test2
index a997157..b6ae3ef 100644 (file)
@@ -801,8 +801,6 @@ pal_specific/pal_errno/test1,1
 pal_specific/pal_getpaldirectoryw/test1,1
 pal_specific/pal_getuserconfigurationdirectoryw/test1,1
 pal_specific/pal_initialize_terminate/test1,1
-pal_specific/pal_registerlibraryw_unregisterlibraryw/pal_registerlibraryw_unregisterlibraryw_neg,1
-pal_specific/pal_registerlibraryw_unregisterlibraryw/test1,1
 threading/createeventa/test1,1
 threading/createeventa/test2,1
 threading/createeventa/test3,1
index 0ebca52..390cb57 100644 (file)
@@ -77,14 +77,6 @@ extern "C" int _cdecl wmain(int argc, __in_ecount(argc) WCHAR **argv)
     HRESULT hr = 0;
     BOOL    fWantHelp=FALSE;
     
-#if FEATURE_PAL
-    if (!PAL_RegisterLibrary(L"rotor_palrt") ||
-        !PAL_RegisterLibrary(L"sscoree"))
-    {
-        MDInfo::Error("Unable to register libraries", 1);
-    }
-#endif  // FEATURE_PAL
-    
     // Validate incoming arguments
     for (int i=1;  i<argc;  i++)
     {
index 100ee70..1b79d81 100644 (file)
@@ -2451,7 +2451,7 @@ void STDMETHODCALLTYPE EEShutDown(BOOL fIsDllUnloading)
         // Otherwise, this thread calls EEShutDownHelper directly.  First switch to
         // cooperative mode if this is a managed thread
 #endif
-        if (GetThread())
+    if (GetThread())
     {
         GCX_COOP();
         EEShutDownHelper(fIsDllUnloading);