From: danmosemsft Date: Sat, 11 Feb 2017 15:20:12 +0000 (-0800) Subject: Revert "Remove always defined FEATURE_CORESYSTEM" X-Git-Tag: accepted/tizen/base/20180629.140029~2270^2~5 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=56d4ba8a9338c3ff7378d18378f38ad847f130f2;p=platform%2Fupstream%2Fcoreclr.git Revert "Remove always defined FEATURE_CORESYSTEM" This reverts commit 751771a8976f909af772e35c167bd7e3ffbe44c8. --- diff --git a/src/ToolBox/SOS/Strike/util.cpp b/src/ToolBox/SOS/Strike/util.cpp index 90574fc..b6336fb 100644 --- a/src/ToolBox/SOS/Strike/util.cpp +++ b/src/ToolBox/SOS/Strike/util.cpp @@ -4791,7 +4791,13 @@ HRESULT InitCorDebugInterface() // SOS now has a statically linked version of the loader code that is normally found in mscoree/mscoreei.dll // Its not much code and takes a big step towards 0 install dependencies // Need to pick the appropriate SKU of CLR to detect +#if defined(FEATURE_CORESYSTEM) GUID skuId = CLR_ID_ONECORE_CLR; +#elif defined(FEATURE_CORECLR) + GUID skuId = CLR_ID_CORECLR; +#else + GUID skuId = CLR_ID_V4_DESKTOP; +#endif CLRDebuggingImpl* pDebuggingImpl = new CLRDebuggingImpl(skuId); hr = pDebuggingImpl->QueryInterface(IID_ICLRDebugging, (LPVOID *)&pClrDebugging); if (FAILED(hr)) diff --git a/src/binder/applicationcontext.cpp b/src/binder/applicationcontext.cpp index 2d41dc6..e5c3025 100644 --- a/src/binder/applicationcontext.cpp +++ b/src/binder/applicationcontext.cpp @@ -12,6 +12,9 @@ // // ============================================================ +#ifndef FEATURE_CORESYSTEM +#define DISABLE_BINDER_DEBUG_LOGGING +#endif #include "applicationcontext.hpp" #include "stringarraylist.h" diff --git a/src/classlibnative/nls/nlsinfo.cpp b/src/classlibnative/nls/nlsinfo.cpp index 4a4c294..44ed542 100644 --- a/src/classlibnative/nls/nlsinfo.cpp +++ b/src/classlibnative/nls/nlsinfo.cpp @@ -2065,6 +2065,26 @@ BOOL QCALLTYPE COMNlsInfo::InternalTryFindStringOrdinalIgnoreCase( lpSearchStart = &lpStringSource[sourceIndex]; } { +#ifndef FEATURE_CORESYSTEM + // kernel function pointer + typedef int (WINAPI *PFNFindStringOrdinal)(DWORD, LPCWSTR, INT, LPCWSTR, INT, BOOL); + static PFNFindStringOrdinal FindStringOrdinal = NULL; + + // initizalize kernel32!FindStringOrdinal + if (FindStringOrdinal == NULL) + { + PFNFindStringOrdinal result = NULL; + + HMODULE hMod=WszGetModuleHandle(WINDOWS_KERNEL32_DLLNAME_W); + if(hMod != NULL) + result=(PFNFindStringOrdinal)GetProcAddress(hMod,"FindStringOrdinal"); + + FindStringOrdinal = (result != NULL) ? result : (PFNFindStringOrdinal)-1; + } + + // call into the kernel + if (FindStringOrdinal != (PFNFindStringOrdinal)-1) +#endif { *foundIndex = FindStringOrdinal( dwFindNLSStringFlags, diff --git a/src/debug/daccess/daccess.cpp b/src/debug/daccess/daccess.cpp index c5781ae..69167ab 100644 --- a/src/debug/daccess/daccess.cpp +++ b/src/debug/daccess/daccess.cpp @@ -6573,6 +6573,7 @@ bool ClrDataAccess::GetILImageInfoFromNgenPEFile(PEFile *peFile, return true; } +#if defined(FEATURE_CORESYSTEM) /* static */ // We extract "ni.dll or .ni.winmd" from the NGEM image name to obtain the IL image name. // In the end we add given ilExtension. @@ -6631,6 +6632,7 @@ bool ClrDataAccess::GetILImageNameFromNgenImage( LPCWSTR ilExtension, return false; } +#endif // FEATURE_CORESYSTEM void * ClrDataAccess::GetMetaDataFromHost(PEFile* peFile, @@ -6740,6 +6742,7 @@ ClrDataAccess::GetMetaDataFromHost(PEFile* peFile, goto ErrExit; } +#if defined(FEATURE_CORESYSTEM) const WCHAR* ilExtension[] = {W("dll"), W("winmd")}; WCHAR ngenImageName[MAX_LONGPATH] = {0}; if (wcscpy_s(ngenImageName, NumItems(ngenImageName), uniPath) != 0) @@ -6757,6 +6760,7 @@ ClrDataAccess::GetMetaDataFromHost(PEFile* peFile, { goto ErrExit; } +#endif//FEATURE_CORESYSTEM // RVA size in ngen image and IL image is the same. Because the only // different is in RVA. That is 4 bytes column fixed. @@ -6789,11 +6793,13 @@ ClrDataAccess::GetMetaDataFromHost(PEFile* peFile, (BYTE*)buffer, NULL); } +#if defined(FEATURE_CORESYSTEM) if (SUCCEEDED(hr)) { break; } } +#endif // FEATURE_CORESYSTEM } if (FAILED(hr)) @@ -6983,8 +6989,10 @@ bool ClrDataAccess::TargetConsistencyAssertsEnabled() return m_fEnableTargetConsistencyAsserts; } +#ifdef FEATURE_CORESYSTEM #define ctime_s _ctime32_s #define time_t __time32_t +#endif // // VerifyDlls - Validate that the mscorwks in the target matches this version of mscordacwks @@ -7524,7 +7532,11 @@ BOOL OutOfProcessExceptionEventGetProcessIdAndThreadId(HANDLE hProcess, HANDLE h *pPId = (DWORD)hProcess; *pThreadId = (DWORD)hThread; #else +#if !defined(FEATURE_CORESYSTEM) + HMODULE hKernel32 = WszGetModuleHandle(W("kernel32.dll")); +#else HMODULE hKernel32 = WszGetModuleHandle(W("api-ms-win-core-processthreads-l1-1-1.dll")); +#endif if (hKernel32 == NULL) { return FALSE; diff --git a/src/debug/daccess/dacimpl.h b/src/debug/daccess/dacimpl.h index 91722f5..635be80 100644 --- a/src/debug/daccess/dacimpl.h +++ b/src/debug/daccess/dacimpl.h @@ -14,11 +14,14 @@ #ifndef __DACIMPL_H__ #define __DACIMPL_H__ +#if defined(_TARGET_ARM_) || defined(FEATURE_CORESYSTEM) // @ARMTODO: STL breaks the build with current VC headers //--------------------------------------------------------------------------------------- // Setting DAC_HASHTABLE tells the DAC to use the hand rolled hashtable for // storing code:DAC_INSTANCE . Otherwise, the DAC uses the STL unordered_map to. #define DAC_HASHTABLE +#endif // _TARGET_ARM_|| FEATURE_CORESYSTEM + #ifndef DAC_HASHTABLE #pragma push_macro("return") #undef return @@ -1479,9 +1482,11 @@ public: DWORD &dwSize, __out_ecount(cchPath) LPWSTR wszPath, const DWORD cchPath); +#if defined(FEATURE_CORESYSTEM) static bool GetILImageNameFromNgenImage(LPCWSTR ilExtension, __out_ecount(cchFilePath) LPWSTR wszFilePath, const DWORD cchFilePath); +#endif // FEATURE_CORESYSTEM }; extern ClrDataAccess* g_dacImpl; diff --git a/src/debug/daccess/nidump.cpp b/src/debug/daccess/nidump.cpp index 3818c4f..9eb761b 100644 --- a/src/debug/daccess/nidump.cpp +++ b/src/debug/daccess/nidump.cpp @@ -15,6 +15,9 @@ #include #include +#if !defined(FEATURE_CORESYSTEM) +#include +#endif #include @@ -28,6 +31,11 @@ #include +#if !defined(FEATURE_CORESYSTEM) +#include +#undef _ASSERTE +#define _ASSERTE(x) assert(x) +#endif #include @@ -6042,6 +6050,16 @@ void NativeImageDumper::DumpTypes(PTR_Module module) //there may be duplicates in the list. Remove them before moving on. COUNT_T mtCount = m_discoveredMTs.GetCount(); +#if !defined(FEATURE_CORESYSTEM) // no STL right now + std::sort(&*m_discoveredMTs.Begin(), + (&*m_discoveredMTs.Begin()) + + (m_discoveredMTs.End() - m_discoveredMTs.Begin())); + PTR_MethodTable* newEnd = std::unique(&*m_discoveredMTs.Begin(), + (&*m_discoveredMTs.Begin()) + + (m_discoveredMTs.End() + - m_discoveredMTs.Begin())); + mtCount = (COUNT_T)(newEnd - &*m_discoveredMTs.Begin()); +#endif DisplayStartArray( "MethodTables", NULL, METHODTABLES ); for(COUNT_T i = 0; i < mtCount; ++i ) @@ -6057,6 +6075,15 @@ void NativeImageDumper::DumpTypes(PTR_Module module) DisplayStartArray( "MethodTableSlotChunks", NULL, METHODTABLES ); { COUNT_T slotChunkCount = m_discoveredSlotChunks.GetCount(); +#if !defined(FEATURE_CORESYSTEM) // no STL right now + std::sort(&*m_discoveredSlotChunks.Begin(), + (&*m_discoveredSlotChunks.Begin()) + + (m_discoveredSlotChunks.End() - m_discoveredSlotChunks.Begin())); + SlotChunk *newEndChunks = std::unique(&*m_discoveredSlotChunks.Begin(), + (&*m_discoveredSlotChunks.Begin()) + + (m_discoveredSlotChunks.End() - m_discoveredSlotChunks.Begin())); + slotChunkCount = (COUNT_T)(newEndChunks - &*m_discoveredSlotChunks.Begin()); +#endif for (COUNT_T i = 0; i < slotChunkCount; ++i) { @@ -6071,6 +6098,16 @@ void NativeImageDumper::DumpTypes(PTR_Module module) //there may be duplicates in the list. Remove them before moving on. COUNT_T clazzCount = m_discoveredClasses.GetCount(); +#if !defined(FEATURE_CORESYSTEM) // no STL right now + std::sort(&*m_discoveredClasses.Begin(), + (&*m_discoveredClasses.Begin()) + + (m_discoveredClasses.End() - m_discoveredClasses.Begin())); + PTR_MethodTable * newEndClazz = std::unique(&*m_discoveredClasses.Begin(), + (&*m_discoveredClasses.Begin()) + +(m_discoveredClasses.End() + -m_discoveredClasses.Begin())); + clazzCount = (COUNT_T)(newEndClazz - &*m_discoveredClasses.Begin()); +#endif for(COUNT_T i = 0; i < clazzCount; ++i ) { @@ -6089,6 +6126,17 @@ void NativeImageDumper::DumpTypes(PTR_Module module) //there may be duplicates in the list. Remove them before moving on. COUNT_T tdCount = m_discoveredTypeDescs.GetCount(); +#if !defined(FEATURE_CORESYSTEM) // no STL right now + std::sort(&*m_discoveredTypeDescs.Begin(), + (&*m_discoveredTypeDescs.Begin()) + + (m_discoveredTypeDescs.End() + - m_discoveredTypeDescs.Begin())); + PTR_TypeDesc* newEndTD = std::unique(&*m_discoveredTypeDescs.Begin(), + (&*m_discoveredTypeDescs.Begin()) + +(m_discoveredTypeDescs.End() + -m_discoveredTypeDescs.Begin())); + tdCount = (COUNT_T)(newEndTD - &*m_discoveredTypeDescs.Begin()); +#endif for(COUNT_T i = 0; i < tdCount; ++i ) { diff --git a/src/debug/di/cordb.cpp b/src/debug/di/cordb.cpp index 3cb9375..c993fa0 100644 --- a/src/debug/di/cordb.cpp +++ b/src/debug/di/cordb.cpp @@ -86,6 +86,15 @@ HINSTANCE g_hInst; // Instance handle to this piece of code //***************************************************************************** STDAPI CreateCordbObject(int iDebuggerVersion, IUnknown ** ppCordb) { +#if defined(FEATURE_CORECLR) && !defined(FEATURE_DBGIPC_TRANSPORT_DI) && !defined(FEATURE_CORESYSTEM) + // This API should not be called for Windows CoreCLR unless we are doing interop-debugging + // (which is only supported internally). Use code:CoreCLRCreateCordbObject instead. + if (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_DbgEnableMixedModeDebugging) == 0) + { + _ASSERTE(!"Deprecated entry point CreateCordbObject() is called on Windows CoreCLR\n"); + return E_NOTIMPL; + } +#endif // FEATURE_CORECLR && !FEATURE_DBGIPC_TRANSPORT_DI if (ppCordb == NULL) { diff --git a/src/debug/di/module.cpp b/src/debug/di/module.cpp index 46487b9..36cc6f5 100644 --- a/src/debug/di/module.cpp +++ b/src/debug/di/module.cpp @@ -5153,7 +5153,7 @@ HRESULT CordbNativeCode::GetReturnValueLiveOffsetImpl(Instantiation *currentInst int skipBytes = 0; -#if defined(DBG_TARGET_X86) +#if defined(DBG_TARGET_X86) && defined(FEATURE_CORESYSTEM) // Skip nop sleds on x86 coresystem. The JIT adds these instructions as a security measure, // and incorrectly reports to us the wrong offset of the call instruction. const BYTE nop_opcode = 0x90; diff --git a/src/debug/di/process.cpp b/src/debug/di/process.cpp index 2d73c3a..927b438 100644 --- a/src/debug/di/process.cpp +++ b/src/debug/di/process.cpp @@ -381,6 +381,7 @@ IMDInternalImport * CordbProcess::LookupMetaDataFromDebugger( WCHAR *mutableFilePath = (WCHAR *)filePath; +#if defined(FEATURE_CORESYSTEM) size_t pathLen = wcslen(mutableFilePath); const wchar_t *nidll = W(".ni.dll"); @@ -402,6 +403,7 @@ IMDInternalImport * CordbProcess::LookupMetaDataFromDebugger( { wcscpy_s(mutableFilePath+pathLen-winmdLen, winmdLen, W(".winmd")); } +#endif//FEATURE_CORESYSTEM ALLOW_DATATARGET_MISSING_MEMORY( pMDII = LookupMetaDataFromDebuggerForSingleFile(pModule, mutableFilePath, dwImageTimeStamp, dwImageSize); @@ -7565,7 +7567,27 @@ HRESULT CordbProcess::GetRuntimeOffsets() { -#if FEATURE_PAL +#if !defined FEATURE_CORESYSTEM + // kernel32!OpenThread does not exist on all platforms (missing on Win98). + // So we need to delay load it. + typedef HANDLE (WINAPI *FPOPENTHREAD)(DWORD dwDesiredAccess, + BOOL bInheritHandle, + DWORD dwThreadId); + + + + HMODULE mod = WszGetModuleHandle(W("kernel32.dll")); + + _ASSERTE(mod != NULL); // can't fail since Kernel32.dll is already loaded. + + const FPOPENTHREAD pfnOpenThread = (FPOPENTHREAD)GetProcAddress(mod, "OpenThread"); + + if (pfnOpenThread != NULL) + { + m_hHelperThread = pfnOpenThread(SYNCHRONIZE, FALSE, dwHelperTid); + CONSISTENCY_CHECK_MSGF(m_hHelperThread != NULL, ("Failed to get helper-thread handle. tid=0x%x\n", dwHelperTid)); + } +#elif FEATURE_PAL m_hHelperThread = NULL; //RS is supposed to be able to live without a helper thread handle. #else m_hHelperThread = OpenThread(SYNCHRONIZE, FALSE, dwHelperTid); @@ -9738,11 +9760,13 @@ HRESULT CordbProcess::EnsureClrInstanceIdSet() if (m_clrInstanceId == 0) { +#ifdef FEATURE_CORESYSTEM if(m_cordb->GetTargetCLR() != 0) { m_clrInstanceId = PTR_TO_CORDB_ADDRESS(m_cordb->GetTargetCLR()); return S_OK; } +#endif // The only case in which we're allowed to request the "default" CLR instance // ID is when we're running in V2 mode. In V3, the client is required to pass @@ -14885,6 +14909,17 @@ HRESULT CordbProcess::IsReadyForDetach() // and hard detach failures (after which the process object is neutered). if (m_pShim != NULL) { +#if !defined(FEATURE_CORESYSTEM) // CORESYSTEM TODO + HModuleHolder hKernel32; + hKernel32 = WszLoadLibrary(W("kernel32")); + if (hKernel32 == NULL) + return HRESULT_FROM_GetLastError(); + typedef BOOL (*DebugActiveProcessStopSig) (DWORD); + DebugActiveProcessStopSig pDebugActiveProcessStop = + reinterpret_cast(GetProcAddress(hKernel32, "DebugActiveProcessStop")); + if (pDebugActiveProcessStop == NULL) + return COR_E_PLATFORMNOTSUPPORTED; +#endif } return S_OK; diff --git a/src/debug/di/publish.cpp b/src/debug/di/publish.cpp index a7e2ebb..888988a 100644 --- a/src/debug/di/publish.cpp +++ b/src/debug/di/publish.cpp @@ -44,6 +44,19 @@ BOOL GetAllProcessesInSystem(DWORD *ProcessId, { HandleHolder hSnapshotHolder; +#if !defined(FEATURE_CORESYSTEM) + // Load the dll "kernel32.dll". + HModuleHolder hDll = WszLoadLibrary(W("kernel32")); + _ASSERTE(hDll != NULL); + + if (hDll == NULL) + { + LOG((LF_CORDB, LL_INFO1000, + "Unable to load the dll for enumerating processes. " + "LoadLibrary (kernel32.dll) failed.\n")); + return FALSE; + } +#else // Load the dll "api-ms-win-obsolete-kernel32-l1-1-0.dll". HModuleHolder hDll = WszLoadLibrary(W("api-ms-win-obsolete-kernel32-l1-1-0.dll")); _ASSERTE(hDll != NULL); @@ -55,6 +68,7 @@ BOOL GetAllProcessesInSystem(DWORD *ProcessId, "LoadLibrary (api-ms-win-obsolete-kernel32-l1-1-0.dll) failed.\n")); return FALSE; } +#endif // Create the Process' Snapshot @@ -169,7 +183,11 @@ CorpubPublish::CorpubPublish() { // Try to get psapi!GetModuleFileNameExW once, and then every process object can use it. // If we can't get it, then we'll fallback to getting information from the IPC block. +#if !defined(FEATURE_CORESYSTEM) + m_hPSAPIdll = WszLoadLibrary(W("psapi.dll")); +#else m_hPSAPIdll = WszLoadLibrary(W("api-ms-win-obsolete-psapi-l1-1-0.dll")); +#endif if (m_hPSAPIdll != NULL) { diff --git a/src/debug/di/rsmain.cpp b/src/debug/di/rsmain.cpp index 5428725..cd2063a 100644 --- a/src/debug/di/rsmain.cpp +++ b/src/debug/di/rsmain.cpp @@ -864,8 +864,10 @@ Cordb::Cordb(CorDebugInterfaceVersion iDebuggerVersion) m_processes(11), m_initialized(false), m_debuggerSpecifiedVersion(iDebuggerVersion) +#ifdef FEATURE_CORESYSTEM , m_targetCLR(0) +#endif { g_pRSDebuggingInfo->m_Cordb = this; @@ -1311,7 +1313,9 @@ HRESULT Cordb::SetTargetCLR(HMODULE hmodTargetCLR) if (m_initialized) return E_FAIL; +#ifdef FEATURE_CORESYSTEM m_targetCLR = hmodTargetCLR; +#endif // @REVIEW: are we happy with this workaround? It allows us to use the existing // infrastructure for instance name decoration, but it really doesn't fit @@ -1419,6 +1423,14 @@ bool Cordb::IsInteropDebuggingSupported() // ICorDebug::SetUnmanagedHandler for details. #ifdef FEATURE_INTEROP_DEBUGGING +#if defined(FEATURE_CORECLR) && !defined(FEATURE_CORESYSTEM) + // Interop debugging is only supported internally on CoreCLR. + // Check if the special reg key is set. If not, then we don't allow interop debugging. + if (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_DbgEnableMixedModeDebugging) == 0) + { + return false; + } +#endif // FEATURE_CORECLR return true; #else diff --git a/src/debug/di/rspriv.h b/src/debug/di/rspriv.h index 5b832c7..d714517 100644 --- a/src/debug/di/rspriv.h +++ b/src/debug/di/rspriv.h @@ -2315,7 +2315,9 @@ public: CorDebugInterfaceVersion GetDebuggerVersion() const; +#ifdef FEATURE_CORESYSTEM HMODULE GetTargetCLR() { return m_targetCLR; } +#endif private: bool IsCreateProcessSupported(); @@ -2335,7 +2337,9 @@ private: //Note - this code could be useful outside coresystem, but keeping the change localized // because we are late in the win8 release +#ifdef FEATURE_CORESYSTEM HMODULE m_targetCLR; +#endif }; diff --git a/src/debug/di/shimprocess.cpp b/src/debug/di/shimprocess.cpp index 6572f2a..a6fc154 100644 --- a/src/debug/di/shimprocess.cpp +++ b/src/debug/di/shimprocess.cpp @@ -18,6 +18,9 @@ #include #include "shimpriv.h" +#if !defined(FEATURE_CORESYSTEM) +#include +#endif //--------------------------------------------------------------------------------------- // @@ -1079,8 +1082,114 @@ HRESULT ShimProcess::QueueFakeThreadAttachEventsNoOrder() // sends the threads in an arbitrary order. HRESULT ShimProcess::QueueFakeThreadAttachEventsNativeOrder() { +#ifdef FEATURE_CORESYSTEM _ASSERTE("NYI"); return E_FAIL; +#else + ICorDebugProcess * pProcess = GetProcess(); + + DWORD dwProcessId; + HRESULT hr = pProcess->GetID(&dwProcessId); + SIMPLIFYING_ASSUMPTION_SUCCEEDED(hr); + if (FAILED(hr)) + { + return hr; + } + + HANDLE hThreadSnap = INVALID_HANDLE_VALUE; + THREADENTRY32 te32; + + // Take a snapshot of all running threads + hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); + if (hThreadSnap == INVALID_HANDLE_VALUE) + { + hr = HRESULT_FROM_GetLastError(); + SIMPLIFYING_ASSUMPTION_SUCCEEDED(hr); + return hr; + } + // HandleHolder doesn't deal with INVALID_HANDLE_VALUE, so we only assign if we have a legal value. + HandleHolder hSnapshotHolder(hThreadSnap); + + // Fill in the size of the structure before using it. + te32.dwSize = sizeof(THREADENTRY32); + + // Retrieve information about the first thread, and exit if unsuccessful + if (!Thread32First(hThreadSnap, &te32)) + { + hr = HRESULT_FROM_GetLastError(); + return hr; + } + + // Now walk the thread list of the system, + // and display information about each thread + // associated with the specified process + do + { + if (te32.th32OwnerProcessID == dwProcessId) + { + RSExtSmartPtr pThread; + pProcess->GetThread(te32.th32ThreadID, &pThread); + if (pThread != NULL) + { + // If we fail to get the appdomain for some reason, then then + // we can't dispatch this thread callback. But we can still + // finish enumerating. + RSExtSmartPtr pAppDomain; + HRESULT hrGetAppDomain = pThread->GetAppDomain(&pAppDomain); + SIMPLIFYING_ASSUMPTION_SUCCEEDED(hrGetAppDomain); + if (pAppDomain != NULL) + { + GetShimCallback()->CreateThread(pAppDomain, pThread); + AddDuplicateCreationEvent(pThread); + + //fix for issue DevDiv2\DevDiv 77523 - threads are switched out in SQL don't get thread create notifications + // mark that this thread has queued a create event + CordbThread* pThreadInternal = static_cast(pThread.GetValue()); + pThreadInternal->SetCreateEventQueued(); + } + } + } + } while(Thread32Next(hThreadSnap, &te32)); + + + //fix for issue DevDiv2\DevDiv 77523 - threads are switched out in SQL don't get thread create notifications + // + + + // Threads which were switched out won't be present in the native thread order enumeration above. + // In order to not miss them we will enumerate all the managed thread objects and for any that we haven't + // already queued a notification for, we will queue a notification now. + RSExtSmartPtr pThreadEnum; + RSExtSmartPtr pThread; + hr = pProcess->EnumerateThreads(&pThreadEnum); + if (FAILED(hr)) + { + return hr; + } + + ULONG cDummy; + + while(SUCCEEDED(pThreadEnum->Next(1, &pThread, &cDummy)) && (pThread != NULL)) + { + RSExtSmartPtr pAppDomain; + hr = pThread->GetAppDomain(&pAppDomain); + CordbThread* pThreadInternal = static_cast(pThread.GetValue()); + + // Getting the appdomain shouldn't fail. If it does, we can't dispatch + // this callback, but we can still dispatch the other thread creates. + SIMPLIFYING_ASSUMPTION_SUCCEEDED(hr); + if (pAppDomain != NULL && !pThreadInternal->CreateEventWasQueued()) + { + GetShimCallback()->CreateThread(pAppDomain, pThread); + AddDuplicateCreationEvent(pThread); + pThreadInternal->SetCreateEventQueued(); + } + pThread.Clear(); + } + + + return S_OK; +#endif } //--------------------------------------------------------------------------------------- @@ -1368,9 +1477,15 @@ void ShimProcess::QueueFakeAttachEvents() // // Third, Queue all Threads // +#if !defined(FEATURE_DBGIPC_TRANSPORT_DI) && !defined(FEATURE_CORESYSTEM) + // Use OS thread enumeration facilities to ensure that the managed thread + // thread order is the same as the corresponding native thread order. + QueueFakeThreadAttachEventsNativeOrder(); +#else // Use ICorDebug to enumerate threads. The order of managed threads may // not match the order the threads were created in. QueueFakeThreadAttachEventsNoOrder(); +#endif // Forth, Queue all Connections. // Enumerate connections is not exposed through ICorDebug, so we need to go use a private hook on CordbProcess. @@ -1627,8 +1742,42 @@ CORDB_ADDRESS ShimProcess::GetCLRInstanceBaseAddress() CORDB_ADDRESS baseAddress = CORDB_ADDRESS(NULL); DWORD dwPid = m_pLiveDataTarget->GetPid(); +#if defined(FEATURE_CORESYSTEM) // Debugger attaching to CoreCLR via CoreCLRCreateCordbObject should have already specified CLR module address. // Code that help to find it now lives in dbgshim. +#else + // get a "snapshot" of all modules in the target + HandleHolder hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPid); + MODULEENTRY32 moduleEntry = { 0 }; + + if (hSnapshot == INVALID_HANDLE_VALUE) + { + // we haven't got a loaded CLR yet + baseAddress = CORDB_ADDRESS(NULL); + } + else + { + // we need to loop through the modules until we find mscorwks.dll + moduleEntry.dwSize = sizeof(MODULEENTRY32); + + if (!Module32First(hSnapshot, &moduleEntry)) + { + baseAddress = CORDB_ADDRESS(NULL); + } + else + { + + do + { + if (!_wcsicmp(moduleEntry.szModule, MAKEDLLNAME_W(MAIN_CLR_MODULE_NAME_W))) + { + // we found it, so save the base address + baseAddress = PTR_TO_CORDB_ADDRESS(moduleEntry.modBaseAddr); + } + } while (Module32Next(hSnapshot, &moduleEntry)); + } + } +#endif return baseAddress; } // ShimProcess::GetCLRInstanceBaseAddress diff --git a/src/debug/di/windowspipeline.cpp b/src/debug/di/windowspipeline.cpp index 073a412..c3050e3 100644 --- a/src/debug/di/windowspipeline.cpp +++ b/src/debug/di/windowspipeline.cpp @@ -134,8 +134,36 @@ BOOL WindowsNativePipeline::DebugSetProcessKillOnExit(bool fKillOnExit) // Enforces the bit set in code:WindowsNativePipeline::DebugSetProcessKillOnExit void WindowsNativePipeline::UpdateDebugSetProcessKillOnExit() { +#if !defined(FEATURE_CORESYSTEM) + // Late bind to DebugSetProcessKillOnExit - WinXP and above only + HModuleHolder hKernel32; + hKernel32 = WszLoadLibrary(W("kernel32")); + SIMPLIFYING_ASSUMPTION(hKernel32 != NULL); + if (hKernel32 == NULL) + return; + + typedef BOOL (*DebugSetProcessKillOnExitSig) (BOOL); + DebugSetProcessKillOnExitSig pDebugSetProcessKillOnExit = + reinterpret_cast(GetProcAddress(hKernel32, "DebugSetProcessKillOnExit")); + + // If the API doesn't exist (eg. Win2k) - there isn't anything we can do, just + // silently ignore the request. + if (pDebugSetProcessKillOnExit == NULL) + return; + + BOOL ret = pDebugSetProcessKillOnExit(m_fKillOnExit); + + // Not a good failure path here. + // 1) This shouldn't fail. + // 2) Even if it does, this is likely called after the debuggee + // has already been created, and if this API fails, most scenarios will + // be unaffected, so we don't want to fail the overall debugging session. + SIMPLIFYING_ASSUMPTION(ret); + +#else // The API doesn't exit on CoreSystem, just return return; +#endif } // Create an process under the debugger. @@ -221,20 +249,69 @@ HRESULT WindowsNativePipeline::DebugActiveProcess(MachineInfo machineInfo, DWORD // Determine (if possible) whether a debugger is attached to the target process HRESULT WindowsNativePipeline::IsRemoteDebuggerPresent(DWORD processId, BOOL* pfDebuggerPresent) { +#if !defined(FEATURE_CORESYSTEM) + + // Get a process handle for the process ID. + HandleHolder hProc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, processId); + if (hProc == NULL) + return HRESULT_FROM_GetLastError(); + + // Delay-bind to CheckRemoteDebuggerPresent - WinXP SP1 and above only + HModuleHolder hKernel32; + hKernel32 = WszLoadLibrary(W("kernel32")); + if (hKernel32 == NULL) + return HRESULT_FROM_GetLastError(); + + typedef BOOL (*CheckRemoteDebuggerPresentSig) (HANDLE, PBOOL); + CheckRemoteDebuggerPresentSig pCheckRemoteDebuggerPresent = + reinterpret_cast(GetProcAddress(hKernel32, "CheckRemoteDebuggerPresent")); + if (pCheckRemoteDebuggerPresent == NULL) + return HRESULT_FROM_GetLastError(); + + // API exists - call it + if (!pCheckRemoteDebuggerPresent(hProc, pfDebuggerPresent)) + return HRESULT_FROM_GetLastError(); + + return S_OK; +#else //CoreSystem doesn't have this API return E_FAIL; +#endif } // Detach HRESULT WindowsNativePipeline::DebugActiveProcessStop(DWORD processId) { +#if !defined(FEATURE_CORESYSTEM) + // Late-bind to DebugActiveProcessStop since it's WinXP and above only + HModuleHolder hKernel32; + hKernel32 = WszLoadLibrary(W("kernel32")); + if (hKernel32 == NULL) + return HRESULT_FROM_GetLastError(); + + typedef BOOL (*DebugActiveProcessStopSig) (DWORD); + DebugActiveProcessStopSig pDebugActiveProcessStop = + reinterpret_cast(GetProcAddress(hKernel32, "DebugActiveProcessStop")); + + // Win2K will fail here - can't find DebugActiveProcessStop + if (pDebugActiveProcessStop == NULL) + return HRESULT_FROM_GetLastError(); + + // Ok, the API exists, call it + if (!pDebugActiveProcessStop(processId)) + { + // Detach itself failed + return HRESULT_FROM_GetLastError(); + } +#else // The API exists, call it if (!::DebugActiveProcessStop(processId)) { // Detach itself failed return HRESULT_FROM_GetLastError(); } +#endif return S_OK; } @@ -287,6 +364,56 @@ BOOL WindowsNativePipeline::TerminateProcess(UINT32 exitCode) // Resume any suspended threads (but just once) HRESULT WindowsNativePipeline::EnsureThreadsRunning() { +#ifdef FEATURE_CORESYSTEM _ASSERTE("NYI"); return E_FAIL; +#else + _ASSERTE(m_dwProcessId != 0); + + // Take a snapshot of all running threads (similar to ShimProcess::QueueFakeThreadAttachEventsNativeOrder) + // Alternately we could return thread creation/exit in WaitForDebugEvent. But we expect this to be used + // very rarely, so no need to complicate more common codepaths. + HANDLE hThreadSnap = INVALID_HANDLE_VALUE; + THREADENTRY32 te32; + + hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); + if (hThreadSnap == INVALID_HANDLE_VALUE) + return HRESULT_FROM_GetLastError(); + + // HandleHolder doesn't deal with INVALID_HANDLE_VALUE, so we only assign if we have a legal value. + HandleHolder hSnapshotHolder(hThreadSnap); + + // Fill in the size of the structure before using it. + te32.dwSize = sizeof(THREADENTRY32); + + // Retrieve information about the first thread, and exit if unsuccessful + if (!Thread32First(hThreadSnap, &te32)) + return HRESULT_FROM_GetLastError(); + + // Now walk the thread list of the system and attempt to resume any that are part of this process + // Ignore errors - this is a best effort (but ASSERT in CHK builds since we don't expect errors + // in practice - we expect the process to be frozen at a debug event, so no races etc.) + + HRESULT hr = S_FALSE; // no thread was resumed + do + { + if (te32.th32OwnerProcessID == m_dwProcessId) + { + HandleHolder hThread = ::OpenThread(THREAD_SUSPEND_RESUME, FALSE, te32.th32ThreadID); + _ASSERTE(hThread != NULL); + if (hThread != NULL) + { + // Resume each thread exactly once (if they were suspended multiple times, + // then EnsureThreadsRunning would need to be called multiple times until it + // returned S_FALSE. + DWORD prevCount = ::ResumeThread(hThread); + _ASSERTE(prevCount >= 0); + if (prevCount >= 1) + hr = S_OK; // some thread was resumed + } + } + } while(Thread32Next(hThreadSnap, &te32)); + + return hr; +#endif } diff --git a/src/debug/ee/rcthread.cpp b/src/debug/ee/rcthread.cpp index 2244766..d4e707d 100644 --- a/src/debug/ee/rcthread.cpp +++ b/src/debug/ee/rcthread.cpp @@ -734,7 +734,18 @@ HRESULT DebuggerRCThread::SetupRuntimeOffsets(DebuggerIPCControlBlock * pDebugge pDebuggerRuntimeOffsets->m_excepNotForRuntimeBPAddr = (void*) ExceptionNotForRuntimeFlare; pDebuggerRuntimeOffsets->m_notifyRSOfSyncCompleteBPAddr = (void*) NotifyRightSideOfSyncCompleteFlare; +#if !defined(FEATURE_CORESYSTEM) + // Grab the address of RaiseException in kernel32 because we have to play some games with exceptions + // that are generated there (just another reason why mixed mode debugging is shady). See bug 476768. + HMODULE hModule = WszGetModuleHandle(W("kernel32.dll")); + _ASSERTE(hModule != NULL); + PREFAST_ASSUME(hModule != NULL); + pDebuggerRuntimeOffsets->m_raiseExceptionAddr = GetProcAddress(hModule, "RaiseException"); + _ASSERTE(pDebuggerRuntimeOffsets->m_raiseExceptionAddr != NULL); + hModule = NULL; +#else pDebuggerRuntimeOffsets->m_raiseExceptionAddr = NULL; +#endif #endif // FEATURE_INTEROP_DEBUGGING pDebuggerRuntimeOffsets->m_pPatches = DebuggerController::GetPatchTable(); @@ -790,7 +801,7 @@ static LONG _debugFilter(LPEXCEPTION_POINTERS ep, PVOID pv) SUPPRESS_ALLOCATION_ASSERTS_IN_THIS_SCOPE; -#if defined(_DEBUG) +#if defined(_DEBUG) || !defined(FEATURE_CORESYSTEM) DebuggerIPCEvent *event = ((DebugFilterParam *)pv)->event; DWORD pid = GetCurrentProcessId(); @@ -829,6 +840,16 @@ static LONG _debugFilter(LPEXCEPTION_POINTERS ep, PVOID pv) #endif // this message box doesn't work well on coresystem... we actually get in a recursive exception handling loop +#ifndef FEATURE_CORESYSTEM + // We took an AV on the helper thread. This is a catastrophic situation so we can + // simply call the EE's catastrophic message box to display the error. + EEMessageBoxCatastrophic( + IDS_DEBUG_UNHANDLEDEXCEPTION_IPC, IDS_DEBUG_SERVICE_CAPTION, + type, + ep->ExceptionRecord->ExceptionCode, + GetIP(ep->ContextRecord), + pid, pid, tid, tid); +#endif // For debugging, we can change the behavior by manually setting eax. // EXCEPTION_EXECUTE_HANDLER=1, EXCEPTION_CONTINUE_SEARCH=0, EXCEPTION_CONTINUE_EXECUTION=-1 diff --git a/src/debug/inc/dbgipcevents.h b/src/debug/inc/dbgipcevents.h index 8ab7971..1b4dec7 100644 --- a/src/debug/inc/dbgipcevents.h +++ b/src/debug/inc/dbgipcevents.h @@ -364,6 +364,29 @@ struct MSLAYOUT DebuggerIPCControlBlockTransport #include "dbgtransportsession.h" #endif // defined(FEATURE_DBGIPC_TRANSPORT_VM) || defined(FEATURE_DBGIPC_TRANSPORT_DI) +#if defined(DBG_TARGET_X86) && !defined(FEATURE_CORESYSTEM) +// We have an versioning requirement. +// Certain portions of the v1.0 and v1.1 IPC block are shared. This is b/c a v1.1 debugger needs to be able +// to look at a v2.0 app enough to recognize the version mismatch. +// This check is only necessary for platforms that ran on v1.1 (Win32-x86) + +// Just to catch any potential illegal change in the IPC block, we assert the offsets against the offsets from v1.1. +// The constants here are pulled from v1.1. +// The RS will look at these versioning fields, so they absolutely must line up. +static_assert_no_msg(offsetof(DebuggerIPCControlBlock, m_leftSideProtocolCurrent) == 0x10); +static_assert_no_msg(offsetof(DebuggerIPCControlBlock, m_leftSideProtocolMinSupported) == 0x14); +static_assert_no_msg(offsetof(DebuggerIPCControlBlock, m_rightSideProtocolCurrent) == 0x18); +static_assert_no_msg(offsetof(DebuggerIPCControlBlock, m_rightSideProtocolMinSupported) == 0x1c); + +// Unfortunately, on detecting such failure, v1.1 will also null out LSEA, LSER and RSPH. +// If these get adjusted, a version-mismatch attach will effectively null out random fields. +static_assert_no_msg(offsetof(DebuggerIPCControlBlock, m_paddingObsoleteLSEA) == 0x30); +static_assert_no_msg(offsetof(DebuggerIPCControlBlock, m_paddingObsoleteLSER) == 0x34); +static_assert_no_msg(offsetof(DebuggerIPCControlBlock, m_rightSideProcessHandle) == 0x38); + + + +#endif #define INITIAL_APP_DOMAIN_INFO_LIST_SIZE 16 diff --git a/src/debug/shared/dbgtransportsession.cpp b/src/debug/shared/dbgtransportsession.cpp index 6369feb..95fdf25 100644 --- a/src/debug/shared/dbgtransportsession.cpp +++ b/src/debug/shared/dbgtransportsession.cpp @@ -2688,7 +2688,11 @@ bool DbgTransportSession::DbgTransportShouldInjectFault(DbgTransportFaultOp eOp, if (dwChance < (s_dwFaultInjection & DBG_TRANSPORT_FAULT_RATE_MASK)) { DbgTransportLog(LC_FaultInject, "Injected fault for %s operation", szOpName); +#if defined(FEATURE_CORESYSTEM) // not supported +#else + WSASetLastError(WSAEFAULT); +#endif // defined(FEATURE_CORESYSTEM) return true; } } diff --git a/src/dlls/dbgshim/dbgshim.cpp b/src/dlls/dbgshim/dbgshim.cpp index 9013101..5f15cab 100644 --- a/src/dlls/dbgshim/dbgshim.cpp +++ b/src/dlls/dbgshim/dbgshim.cpp @@ -1787,7 +1787,9 @@ GetContinueStartupEvent( #endif // !FEATURE_PAL +#if defined(FEATURE_CORESYSTEM) #include "debugshim.h" +#endif //----------------------------------------------------------------------------- // Public API. @@ -1806,6 +1808,7 @@ CLRCreateInstance( REFIID riid, LPVOID *ppInterface) { +#if defined(FEATURE_CORESYSTEM) if (ppInterface == NULL) return E_POINTER; @@ -1813,8 +1816,17 @@ CLRCreateInstance( if (clsid != CLSID_CLRDebugging || riid != IID_ICLRDebugging) return E_NOINTERFACE; +#if defined(FEATURE_CORESYSTEM) GUID skuId = CLR_ID_ONECORE_CLR; +#elif defined(FEATURE_CORECLR) + GUID skuId = CLR_ID_CORECLR; +#else + GUID skuId = CLR_ID_V4_DESKTOP; +#endif CLRDebuggingImpl *pDebuggingImpl = new CLRDebuggingImpl(skuId); return pDebuggingImpl->QueryInterface(riid, ppInterface); +#else + return E_NOTIMPL; +#endif } \ No newline at end of file diff --git a/src/inc/bbsweep.h b/src/inc/bbsweep.h index 5787110..d5526d8 100644 --- a/src/inc/bbsweep.h +++ b/src/inc/bbsweep.h @@ -186,6 +186,95 @@ private: { SECURITY_ATTRIBUTES * pSecurityAttributes = NULL; +#ifndef FEATURE_CORESYSTEM // @CORESYSTEMTODO + PSECURITY_DESCRIPTOR pSD = NULL; + PSID pAdminSid = NULL; + HANDLE hToken = NULL; + PACL pACL = NULL; + LPVOID buffer = NULL; + + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) + goto cleanup; + + // don't set pSecurityAttributes for Metro processes + if(!IsAppContainerProcess(hToken)) + { + SECURITY_ATTRIBUTES securityAttributes; + PSID pUserSid = NULL; + SID_IDENTIFIER_AUTHORITY SIDAuthNT = SECURITY_NT_AUTHORITY; + DWORD retLength; + +#ifdef _PREFAST_ +#pragma warning(push) +#pragma warning(disable:6211) // PREfast warning: Leaking memory 'pSD' due to an exception. +#endif /*_PREFAST_ */ + pSD = (PSECURITY_DESCRIPTOR) new char[SECURITY_DESCRIPTOR_MIN_LENGTH]; + if (!pSD) + goto cleanup; + + if (GetTokenInformation(hToken, TokenOwner, NULL, 0, &retLength)) + goto cleanup; + + buffer = (LPVOID) new char[retLength]; + if (!buffer) + goto cleanup; +#ifdef _PREFAST_ +#pragma warning(pop) +#endif /*_PREFAST_*/ + + // Get the SID for the current user + if (!GetTokenInformation(hToken, TokenOwner, (LPVOID) buffer, retLength, &retLength)) + goto cleanup; + + pUserSid = ((TOKEN_OWNER *) buffer)->Owner; + + // Get the SID for the admin group + // Create a SID for the BUILTIN\Administrators group. + if(! AllocateAndInitializeSid(&SIDAuthNT, 2, + SECURITY_BUILTIN_DOMAIN_RID, + DOMAIN_ALIAS_RID_ADMINS, + 0, 0, 0, 0, 0, 0, + &pAdminSid)) + goto cleanup; + + EXPLICIT_ACCESS ea[2]; + ZeroMemory(ea, 2 * sizeof(EXPLICIT_ACCESS)); + + // Initialize an EXPLICIT_ACCESS structure for an ACE. + // The ACE will allow the current user full access + ea[0].grfAccessPermissions = STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL; // KEY_ALL_ACCESS; + ea[0].grfAccessMode = SET_ACCESS; + ea[0].grfInheritance= NO_INHERITANCE; + ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID; + ea[0].Trustee.TrusteeType = TRUSTEE_IS_USER; + ea[0].Trustee.ptstrName = (LPTSTR) pUserSid; + + // Initialize an EXPLICIT_ACCESS structure for an ACE. + // The ACE will allow admins full access + ea[1].grfAccessPermissions = STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL; //KEY_ALL_ACCESS; + ea[1].grfAccessMode = SET_ACCESS; + ea[1].grfInheritance= NO_INHERITANCE; + ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID; + ea[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP; + ea[1].Trustee.ptstrName = (LPTSTR) pAdminSid; + + if (SetEntriesInAcl(2, ea, NULL, &pACL) != ERROR_SUCCESS) + goto cleanup; + + if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION)) + goto cleanup; + + if (!SetSecurityDescriptorDacl(pSD, TRUE, pACL, FALSE)) + goto cleanup; + + memset((void *) &securityAttributes, 0, sizeof(SECURITY_ATTRIBUTES)); + securityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES); + securityAttributes.lpSecurityDescriptor = pSD; + securityAttributes.bInheritHandle = FALSE; + + pSecurityAttributes = &securityAttributes; + } +#endif // !FEATURE_CORESYSTEM WCHAR objectName[MAX_LONGPATH] = {0}; WCHAR objectNamePrefix[MAX_LONGPATH] = {0}; @@ -206,6 +295,14 @@ private: swprintf_s(objectName, MAX_LONGPATH, W("%sBBSweep_hProfWriterSemaphore"), objectNamePrefix); hProfWriterSemaphore = ::WszCreateSemaphore(pSecurityAttributes, MAX_COUNT, MAX_COUNT, objectName); +#ifndef FEATURE_CORESYSTEM // @CORESYSTEMTODO +cleanup: + if (pSD) delete [] ((char *) pSD); + if (pAdminSid) FreeSid(pAdminSid); + if (hToken) CloseHandle(hToken); + if (pACL) LocalFree(pACL); + if (buffer) delete [] ((char *) buffer); +#endif } bInitialized = hSweepMutex && @@ -285,7 +382,7 @@ private: } else { -#if !defined(CROSSGEN_COMPILE) && !defined(DACCESS_COMPILE) +#if defined (FEATURE_CORESYSTEM) && !defined(CROSSGEN_COMPILE) && !defined(DACCESS_COMPILE) #define MODULE_NAME W("api-ms-win-security-appcontainer-l1-1-0.dll") #else #define MODULE_NAME W("kernel32.dll") diff --git a/src/inc/clrtypes.h b/src/inc/clrtypes.h index 3b38bb3..5f9de0c 100644 --- a/src/inc/clrtypes.h +++ b/src/inc/clrtypes.h @@ -12,7 +12,7 @@ #ifndef CLRTYPES_H_ #define CLRTYPES_H_ -#if defined(_MSC_VER) && !defined(SOURCE_FORMATTING) +#if defined(_MSC_VER) && !defined(SOURCE_FORMATTING) && (!defined(FEATURE_CORECLR) || defined(FEATURE_CORESYSTEM)) // Prefer intsafe.h when available, which defines many of the MAX/MIN // values below (which is why they are in #ifndef blocks). #include diff --git a/src/inc/legacyactivationshim.h b/src/inc/legacyactivationshim.h index 564ac95..4d8eaa5 100644 --- a/src/inc/legacyactivationshim.h +++ b/src/inc/legacyactivationshim.h @@ -819,6 +819,46 @@ namespace LegacyActivationShim #endif //LoadStringRC // Define this method only if it is not yet defined as macro (see ndp\clr\src\inc\UtilCode.h). +#if !defined(LoadStringRCEx) && !defined(FEATURE_CORESYSTEM) + // -------------------------------------------------------------------------------------------- + inline + HRESULT LoadStringRCEx( + LCID lcid, + UINT nResourceID, + __out_ecount(nMax) LPWSTR szBuffer, + int nMax, + int fQuiet, + int *pcwchUsed) + { + HRESULT hr = S_OK; + + if (Util::HasNewActivationAPIs()) + { + GET_CLRINFO(pInfo); + DWORD cchUsed = static_cast(nMax); + IfHrFailRet(pInfo->LoadErrorString(nResourceID, szBuffer, &cchUsed, lcid)); + *pcwchUsed = cchUsed; + } + else + { + CALL_LEGACY_API(LoadStringRCEx, + (LCID lcid, + UINT nResourceID, + LPWSTR szBuffer, + int nMax, + int fQuiet, + int *pcwchUsed), + (lcid, + nResourceID, + szBuffer, + nMax, + fQuiet, + pcwchUsed)); + } + + return hr; + } +#endif //LoadStringRCEx // -------------------------------------------------------------------------------------------- inline diff --git a/src/inc/newapis.h b/src/inc/newapis.h index cdde784..dfe77a5 100644 --- a/src/inc/newapis.h +++ b/src/inc/newapis.h @@ -150,6 +150,7 @@ typedef BOOL (CALLBACK* LOCALE_ENUMPROCEX)(LPWSTR, DWORD, LPARAM); namespace NewApis { +#if defined(FEATURE_CORESYSTEM) __inline bool IsWindows7Platform() { return true; @@ -165,6 +166,94 @@ namespace NewApis return false; } +#else + // Return true if we're on Windows 7 or up (ie: if we have neutral native support and sorting knows about versions) + __inline bool IsWindows7Platform() + { + static int isRunningOnWindows7 = -1; // -1 notinitialized, 0 not running on Windows 7, other value means running on Windows 7 + + if (isRunningOnWindows7 == -1) + { + OSVERSIONINFOEX sVer; + ZeroMemory(&sVer, sizeof(OSVERSIONINFOEX)); + sVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + sVer.dwMajorVersion = 6; + sVer.dwMinorVersion = 1; + sVer.dwPlatformId = VER_PLATFORM_WIN32_NT; + + DWORDLONG dwlConditionMask = 0; + VER_SET_CONDITION(dwlConditionMask, CLR_VER_MAJORVERSION, VER_GREATER_EQUAL); + VER_SET_CONDITION(dwlConditionMask, CLR_VER_MINORVERSION, VER_GREATER_EQUAL); + VER_SET_CONDITION(dwlConditionMask, CLR_VER_PLATFORMID, VER_EQUAL); + + if(VerifyVersionInfo(&sVer, CLR_VER_MAJORVERSION|CLR_VER_MINORVERSION|CLR_VER_PLATFORMID, dwlConditionMask)) + { + isRunningOnWindows7 = 1; + } + else + { + isRunningOnWindows7 = 0; + } + } + + return isRunningOnWindows7 == 1; + } + + // + // IsVistaPlatform return true if running on Vista and false if running on pre or post Vista + // + __inline BOOL IsVistaPlatform() + { + static int isRunningOnVista = -1; // -1 notinitialized, 0 not running on Vista, other value meanse running on Vista + + if (isRunningOnVista == -1) + { + OSVERSIONINFOEX sVer; + ZeroMemory(&sVer, sizeof(OSVERSIONINFOEX)); + sVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + sVer.dwMajorVersion = 6; + sVer.dwMinorVersion = 0; + sVer.dwPlatformId = VER_PLATFORM_WIN32_NT; + + DWORDLONG dwlConditionMask = 0; + VER_SET_CONDITION(dwlConditionMask, CLR_VER_MAJORVERSION, VER_EQUAL); + VER_SET_CONDITION(dwlConditionMask, CLR_VER_MINORVERSION, VER_EQUAL); + VER_SET_CONDITION(dwlConditionMask, CLR_VER_PLATFORMID, VER_EQUAL); + + if(VerifyVersionInfo(&sVer, CLR_VER_MAJORVERSION|CLR_VER_MINORVERSION|CLR_VER_PLATFORMID, dwlConditionMask)) + { + isRunningOnVista = 1; + } + else + { + isRunningOnVista = 0; + } + } + + return isRunningOnVista == 1; + } + + + __inline BOOL IsZhTwSku() + { + const INT32 LANGID_ZH_TW = 0x0404; + LPCWSTR DEFAULT_REGION_NAME_0404 = W("\x53f0\x7063"); + + if(::GetSystemDefaultUILanguage() == LANGID_ZH_TW) + { + WCHAR wszBuffer[32]; + int result = ::GetLocaleInfoW(LANGID_ZH_TW, LOCALE_SNATIVECTRYNAME, wszBuffer, 32); + if (result) + { + if (wcsncmp(wszBuffer, DEFAULT_REGION_NAME_0404, 3) != 0) + { + return true; + } + } + } + return false; + } +#endif // FEATURE_CORESYSTEM __inline BOOL NotLeakingFrameworkOnlyCultures(__in LPCWSTR lpLocaleName) { diff --git a/src/inc/ostype.h b/src/inc/ostype.h index 91a0e77..c18d05a 100644 --- a/src/inc/ostype.h +++ b/src/inc/ostype.h @@ -38,6 +38,19 @@ extern BOOL gExInfoIsServer; void InitRunningOnVersionStatus(); +#if defined(FEATURE_COMINTEROP) && !defined(FEATURE_CORESYSTEM) +typedef enum +{ + WINRT_STATUS_UNINITED = 0, + WINRT_STATUS_UNSUPPORTED, + WINRT_STATUS_SUPPORTED +} +WinRTStatusEnum; + +extern WinRTStatusEnum gWinRTStatus; + +void InitWinRTStatus(); +#endif // FEATURE_COMINTEROP && !FEATURE_CORESYSTEM //***************************************************************************** // @@ -58,7 +71,16 @@ void InitRunningOnVersionStatus(); inline BOOL RunningOnWin7() { WRAPPER_NO_CONTRACT; +#if defined(_ARM_) || defined(FEATURE_CORESYSTEM) return TRUE; +#else + if (gRunningOnStatus == RUNNING_ON_STATUS_UNINITED) + { + InitRunningOnVersionStatus(); + } + + return (gRunningOnStatus >= RUNNING_ON_WIN7) ? TRUE : FALSE; +#endif } //***************************************************************************** @@ -115,11 +137,32 @@ inline BOOL ExOSInfoRunningOnServer() #ifdef FEATURE_COMINTEROP +#ifdef FEATURE_CORESYSTEM inline BOOL WinRTSupported() { return RunningOnWin8(); } +#else +inline BOOL WinRTSupported() +{ + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + STATIC_CONTRACT_CANNOT_TAKE_LOCK; + STATIC_CONTRACT_SO_TOLERANT; + +#ifdef CROSSGEN_COMPILE + return TRUE; +#endif + + if (gWinRTStatus == WINRT_STATUS_UNINITED) + { + InitWinRTStatus(); + } + + return gWinRTStatus == WINRT_STATUS_SUPPORTED; +} +#endif // FEATURE_CORESYSTEM #endif // FEATURE_COMINTEROP diff --git a/src/inc/switches.h b/src/inc/switches.h index daf1751..5db6641 100644 --- a/src/inc/switches.h +++ b/src/inc/switches.h @@ -217,9 +217,11 @@ #define FEATURE_DOUBLE_ALIGNMENT_HINT #endif +#if defined(FEATURE_CORESYSTEM) #define FEATURE_MINIMETADATA_IN_TRIAGEDUMPS +#endif // defined(FEATURE_CORESYSTEM) -#if defined(FEATURE_PREJIT) +#if defined(FEATURE_PREJIT) && defined(FEATURE_CORESYSTEM) // Desktop CLR allows profilers and debuggers to opt out of loading NGENd images, and to // JIT everything instead. "FEATURE_TREAT_NI_AS_MSIL_DURING_DIAGNOSTICS" is roughly the // equivalent for Apollo, where MSIL images may not be available at all. diff --git a/src/inc/winwrap.h b/src/inc/winwrap.h index 6c4dfe8..be09815 100644 --- a/src/inc/winwrap.h +++ b/src/inc/winwrap.h @@ -466,7 +466,7 @@ #define WszObjectDeleteAuditAlarm ObjectDeleteAuditAlarmW #define WszPrivilegedServiceAuditAlarm PrivilegedServiceAuditAlarmW #define WszIsBadStringPtr __DO_NOT_USE__WszIsBadStringPtr__ -#if defined(CROSSGEN_COMPILE) +#if !defined(FEATURE_CORESYSTEM) || defined(CROSSGEN_COMPILE) #define WszLookupAccountSid LookupAccountSidW #endif #define WszLookupAccountName LookupAccountNameW @@ -649,6 +649,7 @@ // winnetwk.h #define WszWNetGetConnection WNetGetConnectionW +#ifdef FEATURE_CORESYSTEM // CoreSystem has CreateSemaphoreExW but not CreateSemaphoreW. #undef WszCreateSemaphore @@ -660,6 +661,7 @@ #undef GetFileVersionInfoSize #define GetFileVersionInfoSize(_filename, _handle) GetFileVersionInfoSizeEx(0, (_filename), (_handle)) +#endif // FEATURE_CORESYSTEM #ifndef _T #define _T(str) W(str) @@ -1009,7 +1011,7 @@ inline int LateboundMessageBoxA(HWND hWnd, return LateboundMessageBoxW(hWnd, wszText, wszCaption, uType); } -#if !defined(CROSSGEN_COMPILE) +#if defined(FEATURE_CORESYSTEM) && !defined(CROSSGEN_COMPILE) #define MessageBoxW LateboundMessageBoxW #define MessageBoxA LateboundMessageBoxA diff --git a/src/pal/prebuilt/inc/asm_version.h b/src/pal/prebuilt/inc/asm_version.h index a9a9fed..44e09c0 100644 --- a/src/pal/prebuilt/inc/asm_version.h +++ b/src/pal/prebuilt/inc/asm_version.h @@ -1,8 +1,22 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#if defined(SILVERLIGHT) +#if defined(FEATURE_CORESYSTEM) #define asm_rmj 4 #define asm_rmm 0 #define asm_rup 0 #define asm_rpt 0 +#else +#define asm_rmj 5 +#define asm_rmm 0 +#define asm_rup 5 +#define asm_rpt 0 +#endif +#else +#define asm_rmj 4 +#define asm_rmm 0 +#define asm_rup 0 +#define asm_rpt 0 +#endif diff --git a/src/strongname/api/strongname.cpp b/src/strongname/api/strongname.cpp index 2562f4c..00b1156 100644 --- a/src/strongname/api/strongname.cpp +++ b/src/strongname/api/strongname.cpp @@ -906,8 +906,14 @@ SNAPI StrongNameGetPublicKeyEx (LPCWSTR wszKeyContainer, // [in] desired ke 0, 0, &hKey)) goto Error; } else { +#if !defined(FEATURE_CORESYSTEM) + // Else fetch the signature key pair from the container. + if (!CryptGetUserKey(hProv, g_uKeySpec, &hKey)) + goto Error; +#else // FEATURE_CORESYSTEM SetLastError(E_NOTIMPL); goto Error; +#endif // !FEATURE_CORESYSTEM } // Determine the length of the public key part as a blob. diff --git a/src/utilcode/securitywrapper.cpp b/src/utilcode/securitywrapper.cpp index c357ab6..0f146ab 100644 --- a/src/utilcode/securitywrapper.cpp +++ b/src/utilcode/securitywrapper.cpp @@ -207,6 +207,116 @@ exit: return hr; } +#ifndef FEATURE_CORESYSTEM +//----------------------------------------------------------------------------- +// get the sid of a given process id using WTSEnumerateProcesses +// @todo: Make this function fail when WTSEnumerateProcesses is not available +// Or is it always available on all of our platform? +// +// Caller remember to call delete on *ppSid +//----------------------------------------------------------------------------- +HRESULT GetSidFromProcessEXWorker(DWORD dwProcessId, PSID *ppSid) +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + PRECONDITION(CheckPointer(ppSid)); + } + CONTRACTL_END; + + HRESULT hr = S_OK; + PWTS_PROCESS_INFOW rgProcessInfo = NULL; + DWORD dwNumProcesses; + DWORD iProc; + DWORD cbSid; + PSID pSid = NULL; + + LOG((LF_CORDB, LL_INFO10000, + "SecurityUtil::GetSidFromProcessEx: 0x%08x\n", + dwProcessId)); + + + *ppSid = NULL; + if (!WTSEnumerateProcessesW(WTS_CURRENT_SERVER_HANDLE, // use local server + 0, // Reserved must be zero + 1, // version must be 1 + &rgProcessInfo, // Receives pointer to process list + &dwNumProcesses)) + { + hr = HRESULT_FROM_GetLastError(); + goto exit; + } + + for (iProc = 0; iProc < dwNumProcesses; iProc++) + { + + if (rgProcessInfo[iProc].ProcessId == dwProcessId) + { + if (rgProcessInfo[iProc].pUserSid == NULL) + { + LOG((LF_CORDB, LL_INFO10000, + "SecurityUtil::GetSidFromProcessEx is not able to retreive SID\n")); + + // if there is no Sid for the user, don't call GetLengthSid. + // It will crash! It is ok to return E_FAIL as caller will ignore it. + hr = E_FAIL; + goto exit; + } + cbSid = GetLengthSid(rgProcessInfo[iProc].pUserSid); + pSid = new (nothrow) BYTE[cbSid]; + if (pSid == NULL) + { + hr = E_OUTOFMEMORY; + } + else + { + if (!CopySid(cbSid, pSid, rgProcessInfo[iProc].pUserSid)) + { + hr = HRESULT_FROM_GetLastError(); + } + else + { + // We are done. Go to exit + hr = S_OK; + } + } + + // we already find a match. Even if we fail from memory allocation of CopySid, still + // goto exit. + goto exit; + } + } + + // Walk the whole list and cannot find the matching PID + // Find a better error code. + hr = E_FAIL; + +exit: + + if (rgProcessInfo) + { + WTSFreeMemory(rgProcessInfo); + } + + if (FAILED(hr) && pSid) + { + delete [] (reinterpret_cast(pSid)); + } + + if (SUCCEEDED(hr)) + { + _ASSERTE(pSid); + *ppSid = pSid; + } + LOG((LF_CORDB, LL_INFO10000, + "SecurityUtil::GetSidFromProcessEx return hr : 0x%08x\n", + hr)); + + + return hr; +} +#endif // !FEATURE_CORESYSTEM //----------------------------------------------------------------------------- // The functions below initialize this SidBuffer instance with a Sid from @@ -252,6 +362,12 @@ HRESULT SidBuffer::InitFromProcessNoThrow(DWORD pid) _ASSERTE(m_pBuffer == NULL); HRESULT hr = GetSidFromProcessWorker(pid, kOwnerSid, (PSID *) &m_pBuffer); +#ifndef FEATURE_CORESYSTEM + if (FAILED(hr)) + { + hr = GetSidFromProcessEXWorker(pid, (PSID *) &m_pBuffer); + } +#endif // !FEATURE_CORESYSTEM if (FAILED(hr)) { return hr; @@ -411,6 +527,12 @@ HRESULT SidBuffer::InitFromProcessUserNoThrow(DWORD pid) _ASSERTE(m_pBuffer == NULL); HRESULT hr = GetSidFromProcessWorker(pid, kUserSid, (PSID *) &m_pBuffer); +#ifndef FEATURE_CORESYSTEM + if (FAILED(hr)) + { + hr = GetSidFromProcessEXWorker(pid, (PSID *) &m_pBuffer); + } +#endif // !FEATURE_CORESYSTEM if (FAILED(hr)) { return hr; diff --git a/src/utilcode/sstring.cpp b/src/utilcode/sstring.cpp index cf495cc..7c332e0 100644 --- a/src/utilcode/sstring.cpp +++ b/src/utilcode/sstring.cpp @@ -2237,7 +2237,11 @@ void SString::PVPrintf(const WCHAR *format, va_list args) { // First, try to use the existing buffer va_copy(ap, args); +#if defined(FEATURE_CORESYSTEM) int result = _vsnwprintf_s(GetRawUnicode(), GetRawCount()+1, _TRUNCATE, format, ap); +#else + int result = _vswprintf_p(GetRawUnicode(), GetRawCount()+1, format, ap); +#endif va_end(ap); if (result >= 0) { @@ -2267,7 +2271,11 @@ void SString::PVPrintf(const WCHAR *format, va_list args) errno = 0; va_copy(ap, args); +#if defined(FEATURE_CORESYSTEM) int result = _vsnwprintf_s(GetRawUnicode(), GetRawCount()+1, _TRUNCATE, format, ap); +#else + int result = _vswprintf_p(GetRawUnicode(), GetRawCount()+1, format, ap); +#endif va_end(ap); if (result >= 0) diff --git a/src/utilcode/util.cpp b/src/utilcode/util.cpp index 67e353b..b9ca380 100644 --- a/src/utilcode/util.cpp +++ b/src/utilcode/util.cpp @@ -28,7 +28,60 @@ UINT32 g_nClrInstanceId = 0; //********** Code. ************************************************************ +#if defined(FEATURE_COMINTEROP) && !defined(FEATURE_CORESYSTEM) +extern WinRTStatusEnum gWinRTStatus = WINRT_STATUS_UNINITED; +#endif // FEATURE_COMINTEROP && !FEATURE_CORESYSTEM +#if defined(FEATURE_COMINTEROP) && !defined(FEATURE_CORESYSTEM) +//------------------------------------------------------------------------------ +// +// Attempt to detect the presense of Windows Runtime support on the current OS. +// Our algorithm to do this is to ensure that: +// 1. combase.dll exists +// 2. combase.dll contains a RoInitialize export +// + +void InitWinRTStatus() +{ + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + STATIC_CONTRACT_CANNOT_TAKE_LOCK; + STATIC_CONTRACT_SO_TOLERANT; + + WinRTStatusEnum winRTStatus = WINRT_STATUS_UNSUPPORTED; + + const WCHAR wszComBaseDll[] = W("\\combase.dll"); + const SIZE_T cchComBaseDll = _countof(wszComBaseDll); + + WCHAR wszComBasePath[MAX_LONGPATH + 1]; + const SIZE_T cchComBasePath = _countof(wszComBasePath); + + ZeroMemory(wszComBasePath, cchComBasePath * sizeof(wszComBasePath[0])); + + UINT cchSystemDirectory = WszGetSystemDirectory(wszComBasePath, MAX_LONGPATH); + + // Make sure that we're only probing in the system directory. If we can't find the system directory, or + // we find it but combase.dll doesn't fit into it, we'll fall back to a safe default of saying that WinRT + // is simply not present. + if (cchSystemDirectory > 0 && cchComBasePath - cchSystemDirectory >= cchComBaseDll) + { + if (wcscat_s(wszComBasePath, wszComBaseDll) == 0) + { + HModuleHolder hComBase(WszLoadLibrary(wszComBasePath)); + if (hComBase != NULL) + { + FARPROC activateInstace = GetProcAddress(hComBase, "RoInitialize"); + if (activateInstace != NULL) + { + winRTStatus = WINRT_STATUS_SUPPORTED; + } + } + } + } + + gWinRTStatus = winRTStatus; +} +#endif // FEATURE_COMINTEROP && !FEATURE_CORESYSTEM //***************************************************************************** // Convert a string of hex digits into a hex value of the specified # of bytes. //***************************************************************************** diff --git a/src/utilcode/utilmessagebox.cpp b/src/utilcode/utilmessagebox.cpp index 899b120..5ceb390 100644 --- a/src/utilcode/utilmessagebox.cpp +++ b/src/utilcode/utilmessagebox.cpp @@ -18,6 +18,11 @@ #include "ndpversion.h" #include "../dlls/mscorrc/resource.h" #include "ex.h" +#if !defined(FEATURE_CORESYSTEM) +#undef NTDDI_VERSION +#define NTDDI_VERSION NTDDI_WIN7 +#include "commctrl.h" +#endif BOOL ShouldDisplayMsgBoxOnCriticalFailure() @@ -44,6 +49,16 @@ BOOL ShouldDisplayMsgBoxOnCriticalFailure() } +#if !defined(FEATURE_CORESYSTEM) && !defined(FEATURE_CORECLR) +enum ProbedTaskDialogIndirectState +{ + ProbedTaskDialogIndirectState_NotProbed = 0, + ProbedTaskDialogIndirectState_NotAvailable = 1, + ProbedTaskDialogIndirectState_Available = 2 +}; + +static ProbedTaskDialogIndirectState siProbedTaskDialogIndirect = ProbedTaskDialogIndirectState_NotProbed; +#endif // !FEATURE_CORESYSTEM && !FEATURE_CORECLR // We'd like to use TaskDialogIndirect for asserts coming from managed code in particular @@ -71,7 +86,157 @@ int MessageBoxImpl( } CONTRACTL_END; +#if defined(FEATURE_CORESYSTEM) || defined (FEATURE_CORECLR) return WszMessageBox(hWnd, message, title, uType); +#else + bool mustUseMessageBox = false; // Mac, Silverlight, pre-Vista? Do we support this type of message box? + decltype(TaskDialogIndirect)* pfnTaskDialogIndirect = NULL; + ULONG_PTR cookie = NULL; // For activation context. + bool activatedActivationContext = false; + HModuleHolder hmodComctl32; + HANDLE hActCtx = INVALID_HANDLE_VALUE; + + // Note: TaskDialogIndirect is only in the v6 and above versions of comctl32. Windows + // stores that library in the WinSxS directory in a directory with + // "Microsoft.Windows.Common-Controls" in the name. Your application can only see + // this library if the linker has added a manifest dependency on the V6 common controls + // to your application. Or, you can create an activation context to make this work, + // if your library also has the appropriate manifest dependency. + // Also, I'm not going to leave comctl32.dll mapped, to ensure it can't somehow + // interfere with older versions. Therefore, re-load comctl32.dll every time through + // this method. We will record whether TaskDialogIndirect is available though, so + // we can fall back to MessageBox faster. + + // We don't yet have a perfect mapping from all MessageBox behavior to TaskDialogIndirect behavior. + // Use MessageBox to avoid most of this complexity. + if (((uType & MB_ICONMASK) != MB_ICONWARNING) && (uType & MB_ICONMASK) != MB_ICONERROR || + (uType & MB_TYPEMASK) != MB_ABORTRETRYIGNORE || + (uType & MB_DEFMASK) != 0 || + (uType & MB_MODEMASK) != 0 || + (uType & MB_MISCMASK) != 0) + mustUseMessageBox = true; + else if (mustUseMessageBox || siProbedTaskDialogIndirect == ProbedTaskDialogIndirectState_NotAvailable) + mustUseMessageBox = true; + else { + // Replace our application's ActivationContext temporarily, load comctl32 + // & look for TaskDialogIndirect. Don't cache pointer. + // The following code was suggested by some Windows experts. We do not want + // to add a manifest to our library saying we use comctl32 v6, because that + // will mean loading a lot of extra libraries on startup (a significant perf hit). + // We could either store the manifest as a resource, or more creatively since + // we are effectively a Windows component, rely on %windir%\WindowsShell.manifest. + ACTCTX ctx = { sizeof(ACTCTX) }; + ctx.dwFlags = 0; + StackSString manifestPath; // Point this at %windir%\WindowsShell.manifest, for comctl32 version 6. + UINT numChars = WszGetWindowsDirectory(manifestPath.OpenUnicodeBuffer(MAX_PATH_FNAME), MAX_PATH_FNAME); + if (numChars == 0 || numChars >= MAX_PATH_FNAME) + { + _ASSERTE(0); // How did this fail? + } + else { + manifestPath.CloseBuffer(numChars); + if (manifestPath[manifestPath.GetCount() - 1] != W('\\')) + manifestPath.Append(W('\\')); + manifestPath.Append(W("WindowsShell.manifest")); // Other Windows components have already loaded this. + ctx.lpSource = manifestPath.GetUnicode(); + hActCtx = CreateActCtx(&ctx); + if (hActCtx != INVALID_HANDLE_VALUE) + { + if (!ActivateActCtx(hActCtx, &cookie)) + { + cookie = NULL; + _ASSERTE(0); // Why did ActivateActCtx fail? (We'll continue executing & cope with the failure.) + } + else { + activatedActivationContext = true; + // Activation context was replaced - now we can load comctl32 version 6. + hmodComctl32 = WszLoadLibrary(W("comctl32.dll")); + + if (hmodComctl32 != INVALID_HANDLE_VALUE) { + pfnTaskDialogIndirect = (decltype(TaskDialogIndirect)*)GetProcAddress(hmodComctl32, "TaskDialogIndirect"); + if (pfnTaskDialogIndirect == NULL) { + hmodComctl32.Release(); + } + } + } + } + } + + siProbedTaskDialogIndirect = (pfnTaskDialogIndirect == NULL) ? ProbedTaskDialogIndirectState_NotAvailable : ProbedTaskDialogIndirectState_Available; + mustUseMessageBox = (pfnTaskDialogIndirect == NULL); + } + + int result = MB_OK; + if (mustUseMessageBox) { + result = WszMessageBox(hWnd, message, title, uType); + } + else { + _ASSERTE(pfnTaskDialogIndirect != NULL); + int nButtonPressed = 0; + TASKDIALOGCONFIG config = {0}; + config.cbSize = sizeof(config); + config.hwndParent = hWnd; + config.dwCommonButtons = 0; + config.pszWindowTitle = title; + config.dwFlags = (uType & MB_RTLREADING) ? TDF_RTL_LAYOUT : 0; + + // Set the user-visible icon in the window. + _ASSERTE(((uType & MB_ICONMASK) == MB_ICONWARNING) || ((uType & MB_ICONMASK) == MB_ICONERROR)); + config.pszMainIcon = ((uType & MB_ICONMASK) == MB_ICONWARNING) ? TD_WARNING_ICON : TD_ERROR_ICON; + + config.pszMainInstruction = title; + config.pszContent = message; + config.pszExpandedInformation = detailedText; + + // Set up the buttons + // Note about button hot keys: Windows keeps track of of where the last input came from + // (ie, mouse or keyboard). If you use the mouse to interact w/ one dialog box and then use + // the keyboard, the next dialog will not include hot keys. This is a Windows feature to + // minimize clutter on the screen for mouse users. + _ASSERTE((uType & MB_TYPEMASK) == MB_ABORTRETRYIGNORE); + StackSString abortLabel, debugLabel, ignoreLabel; + const WCHAR *pAbortLabel, *pDebugLabel, *pIgnoreLabel; + + if (abortLabel.LoadResource(CCompRC::Optional, IDS_DIALOG_BOX_ABORT_BUTTON)) + pAbortLabel = abortLabel.GetUnicode(); + else + pAbortLabel = W("&Abort"); + if (debugLabel.LoadResource(CCompRC::Optional, IDS_DIALOG_BOX_DEBUG_BUTTON)) + pDebugLabel = debugLabel.GetUnicode(); + else + pDebugLabel = W("&Debug"); + if (ignoreLabel.LoadResource(CCompRC::Optional, IDS_DIALOG_BOX_IGNORE_BUTTON)) + pIgnoreLabel = ignoreLabel.GetUnicode(); + else + pIgnoreLabel = W("&Ignore"); + + const TASKDIALOG_BUTTON abortDebugIgnoreButtons[] = { + { IDOK, pAbortLabel }, + { IDRETRY, pDebugLabel }, + { IDIGNORE, pIgnoreLabel } + }; + config.pButtons = abortDebugIgnoreButtons; + config.cButtons = 3; + + HRESULT hr = pfnTaskDialogIndirect(&config, &nButtonPressed, NULL, NULL); + _ASSERTE(hr == S_OK); + if (hr == S_OK) { + result = nButtonPressed; + } + else { + result = IDOK; + } + + _ASSERTE(result == IDOK || result == IDRETRY || result == IDIGNORE); + } + + if (activatedActivationContext) { + DeactivateActCtx(0, cookie); + ReleaseActCtx(hActCtx); // perf isn't important so we won't bother caching the actctx + } + + return result; +#endif } int UtilMessageBoxVA( diff --git a/src/utilcode/winfix.cpp b/src/utilcode/winfix.cpp index d6bd59c..3a04486 100644 --- a/src/utilcode/winfix.cpp +++ b/src/utilcode/winfix.cpp @@ -231,6 +231,21 @@ BOOL RunningInteractive() if (fInteractive != -1) return fInteractive != 0; +#if !defined(FEATURE_CORESYSTEM) + HWINSTA hwinsta = NULL; + + if ((hwinsta = GetProcessWindowStation() ) != NULL) + { + DWORD lengthNeeded; + USEROBJECTFLAGS flags; + + if (GetUserObjectInformationW (hwinsta, UOI_FLAGS, &flags, sizeof(flags), &lengthNeeded)) + { + if ((flags.dwFlags & WSF_VISIBLE) == 0) + fInteractive = 0; + } + } +#endif // !FEATURE_CORESYSTEM if (fInteractive != 0) fInteractive = 1; diff --git a/src/vm/assembly.cpp b/src/vm/assembly.cpp index e71fffc..cc24ec7 100644 --- a/src/vm/assembly.cpp +++ b/src/vm/assembly.cpp @@ -3286,6 +3286,7 @@ BOOL Assembly::CanBeShared(DomainAssembly *pDomainAssembly) #endif // FEATURE_LOADER_OPTIMIZATION +#if defined(FEATURE_APTCA) || defined(FEATURE_CORESYSTEM) BOOL Assembly::AllowUntrustedCaller() { CONTRACTL @@ -3298,6 +3299,7 @@ BOOL Assembly::AllowUntrustedCaller() return ModuleSecurityDescriptor::GetModuleSecurityDescriptor(this)->IsAPTCA(); } +#endif // defined(FEATURE_APTCA) || defined(FEATURE_CORESYSTEM) void DECLSPEC_NORETURN Assembly::ThrowTypeLoadException(LPCUTF8 pszFullName, UINT resIDWhy) { diff --git a/src/vm/classnames.h b/src/vm/classnames.h index 7664158..455924c 100644 --- a/src/vm/classnames.h +++ b/src/vm/classnames.h @@ -161,9 +161,11 @@ #define g_SecuritySafeCriticalAttribute "System.Security.SecuritySafeCriticalAttribute" +#if defined(FEATURE_APTCA) || defined(FEATURE_CORESYSTEM) #define g_SecurityAPTCA "System.Security.AllowPartiallyTrustedCallersAttribute" #define g_SecurityPartialTrustVisibilityLevel "System.Security.PartialTrustVisibilityLevel" #define g_PartialTrustVisibilityLevel "PartialTrustVisibilityLevel" +#endif // defined(FEATURE_APTCA) || defined(FEATURE_CORESYSTEM) #define g_ReferenceAssemblyAttribute "System.Runtime.CompilerServices.ReferenceAssemblyAttribute" diff --git a/src/vm/comutilnative.cpp b/src/vm/comutilnative.cpp index 04ad7a8..1c9703a 100644 --- a/src/vm/comutilnative.cpp +++ b/src/vm/comutilnative.cpp @@ -1500,6 +1500,12 @@ void QCALLTYPE Buffer::MemMove(void *dst, void *src, size_t length) { QCALL_CONTRACT; +#if defined(FEATURE_CORECLR) && !defined(FEATURE_CORESYSTEM) + // Callers of memcpy do expect and handle access violations in some scenarios. + // Access violations in the runtime dll are turned into fail fast by the vector exception handler by default. + // We need to supress this behavior for CoreCLR using AVInRuntimeImplOkayHolder because of memcpy is statically linked in. + AVInRuntimeImplOkayHolder avOk; +#endif memmove(dst, src, length); } diff --git a/src/vm/dllimport.cpp b/src/vm/dllimport.cpp index 98e58c6..15d964a 100644 --- a/src/vm/dllimport.cpp +++ b/src/vm/dllimport.cpp @@ -6129,6 +6129,9 @@ static HMODULE LocalLoadLibraryHelper( LPCWSTR name, DWORD flags, LoadLibErrorTr #ifndef FEATURE_PAL if ((flags & 0xFFFFFF00) != 0 +#ifndef FEATURE_CORESYSTEM + && NDirect::SecureLoadLibrarySupported() +#endif // !FEATURE_CORESYSTEM ) { hmod = CLRLoadLibraryEx(name, NULL, flags & 0xFFFFFF00); @@ -6181,6 +6184,62 @@ static HMODULE LocalLoadLibraryDirectHelper(LPCWSTR name, DWORD flags, LoadLibEr } +#if !defined(FEATURE_CORESYSTEM) + +#define NATIVE_DLL(d) L#d, L#d W(".dll") + +const LPCWSTR wellKnownModules[] = +{ + NATIVE_DLL(advapi32), + NATIVE_DLL(gdi32), + NATIVE_DLL(gdiplus), + NATIVE_DLL(kernel32), + NATIVE_DLL(mscoree), + NATIVE_DLL(ole32), + NATIVE_DLL(shfolder), + NATIVE_DLL(user32), + NATIVE_DLL(version) +}; + +BOOL CompareLibNames (UPTR val1, UPTR val2) +{ + CONTRACTL { + MODE_ANY; + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + LPCWSTR wszStr1 = (LPCWSTR)(val1 << 1); + LPCWSTR wszStr2 = (LPCWSTR)val2; + + if (SString::_wcsicmp(wszStr1, wszStr2) == 0) + return TRUE; + + return FALSE; +} + +PtrHashMap * NDirect::s_pWellKnownNativeModules = NULL; +bool NDirect::s_fSecureLoadLibrarySupported = false; + +HINSTANCE NDirect::CheckForWellKnownModules(LPCWSTR wszLibName, LoadLibErrorTracker *pErrorTracker) +{ + STANDARD_VM_CONTRACT; + + ModuleHandleHolder hMod; + ULONG hash = HashiString(wszLibName); + LPCWSTR wszName = NULL; + wszName = (LPCWSTR) s_pWellKnownNativeModules->LookupValue((UPTR) hash, (LPVOID)wszLibName); + + if (wszName != (LPCWSTR)INVALIDENTRY) + { + hMod = LocalLoadLibraryHelper(wszLibName, 0, pErrorTracker); + } + + return hMod.Extract(); +} + +#endif // !FEATURE_CORESYSTEM #define TOLOWER(a) (((a) >= W('A') && (a) <= W('Z')) ? (W('a') + (a - W('A'))) : (a)) #define TOHEX(a) ((a)>=10 ? W('a')+(a)-10 : W('0')+(a)) @@ -6395,6 +6454,9 @@ HINSTANCE NDirect::LoadLibraryModule(NDirectMethodDesc * pMD, LoadLibErrorTracke return hmod.Extract(); } +#if !defined(FEATURE_CORESYSTEM) + hmod = CheckForWellKnownModules(wszLibName, pErrorTracker); +#endif #ifdef FEATURE_PAL // In the PAL version of CoreCLR, the CLR module itself exports the functionality @@ -6406,7 +6468,7 @@ HINSTANCE NDirect::LoadLibraryModule(NDirectMethodDesc * pMD, LoadLibErrorTracke hmod = GetCLRModule(); #endif // FEATURE_PAL -#if !defined(PLATFORM_UNIX) +#if defined(FEATURE_CORESYSTEM) && !defined(PLATFORM_UNIX) if (hmod == NULL) { // Try to go straight to System32 for Windows API sets. This is replicating quick check from diff --git a/src/vm/dllimport.h b/src/vm/dllimport.h index ca04661..ab5b212 100644 --- a/src/vm/dllimport.h +++ b/src/vm/dllimport.h @@ -133,6 +133,20 @@ private: static HMODULE LoadLibraryModuleViaHost(NDirectMethodDesc * pMD, AppDomain* pDomain, const wchar_t* wszLibName); #endif //defined(FEATURE_HOST_ASSEMBLY_RESOLVER) +#if !defined(FEATURE_CORESYSTEM) + static HINSTANCE CheckForWellKnownModules(LPCWSTR wszLibName, LoadLibErrorTracker *pErrorTracker); + static PtrHashMap *s_pWellKnownNativeModules; + + // Indicates if the OS supports the new secure LoadLibraryEx flags introduced in KB2533623 + static bool s_fSecureLoadLibrarySupported; + +public: + static bool SecureLoadLibrarySupported() + { + LIMITED_METHOD_CONTRACT; + return s_fSecureLoadLibrarySupported; + } +#endif // !FEATURE_CORESYSTEM }; //---------------------------------------------------------------- diff --git a/src/vm/domainfile.cpp b/src/vm/domainfile.cpp index e66ebae..bf7fc57 100644 --- a/src/vm/domainfile.cpp +++ b/src/vm/domainfile.cpp @@ -3373,7 +3373,113 @@ bool DomainAssembly::GetDebuggingOverrides(DWORD *pdwFlags) } CONTRACTL_END; +#if defined(DEBUGGING_SUPPORTED) && !defined(FEATURE_CORESYSTEM) + // TODO FIX in V5.0 + // Any touch of the file system is relatively expensive even in the warm case. + // + // Ideally we remove the .INI feature completely (if we need something put it in the .exe.config file) + // + // However because of compatibility concerns, we won't do this until the next side-by-side release + // In the mean time don't check in the case where we have already loaded the NGEN image, as the + // JIT overrides don't mean anything in that case as we won't be jitting anyway. + // This avoids doing these probes for framework DLLs right away. + if (GetFile()->HasNativeImage()) + return false; + + _ASSERTE(pdwFlags); + + bool fHasBits = false; + WCHAR *pFileName = NULL; + HRESULT hr = S_OK; + UINT cbExtOrValue = 4; + WCHAR *pTail = NULL; + size_t len = 0; + WCHAR *lpFileName = NULL; + + const WCHAR *wszFileName = GetFile()->GetPath(); + + if (wszFileName == NULL) + { + return false; + } + + // lpFileName is a copy of the original, and will be edited. + CQuickBytes qb; + len = wcslen(wszFileName); + size_t cchlpFileName = (len + 1); + lpFileName = (WCHAR*)qb.AllocThrows(cchlpFileName * sizeof(WCHAR)); + wcscpy_s(lpFileName, cchlpFileName, wszFileName); + + pFileName = wcsrchr(lpFileName, W('\\')); + + if (pFileName == NULL) + { + pFileName = lpFileName; + } + + if (*pFileName == W('\\')) + { + pFileName++; //move the pointer past the last '\' + } + + _ASSERTE(wcslen(W(".INI")) == cbExtOrValue); + + if (pFileName == NULL || (pTail=wcsrchr(pFileName, W('.'))) == NULL || (wcslen(pTail) WerModuleHolder; +#else #define WER_MODULE_NAME_W W("api-ms-win-core-windowserrorreporting-l1-1-0.dll") typedef SimpleModuleHolder WerModuleHolder; +#endif //------------------------------------------------------------------------------ // Description @@ -211,11 +216,13 @@ BOOL RegisterOutOfProcessWatsonCallbacks() WCHAR wszDACName[] = MAIN_DAC_MODULE_NAME_W W(".dll"); WerModuleHolder hWerModule(WER_MODULE_NAME_W); +#ifdef FEATURE_CORESYSTEM if ((hWerModule == NULL) && !RunningOnWin8()) { // If we are built for CoreSystemServer, but are running on Windows 7, we need to look elsewhere hWerModule = WerModuleHolder(W("Kernel32.dll")); } +#endif if (hWerModule == NULL) { @@ -257,10 +264,15 @@ BOOL RegisterOutOfProcessWatsonCallbacks() LL_ERROR, "WATSON support: failed to register DAC dll with WerRegisterRuntimeExceptionModule"); +#ifdef FEATURE_CORESYSTEM // For CoreSys we *could* be running on a platform that doesn't have Watson proper // (the APIs might exist but they just fail). // WerRegisterRuntimeExceptionModule may return E_NOIMPL. return TRUE; +#else // FEATURE_CORESYSTEM + _ASSERTE(! "WATSON support: failed to register DAC dll with WerRegisterRuntimeExceptionModule"); + return FALSE; +#endif // FEATURE_CORESYSTEM } STRESS_LOG0(LF_STARTUP, diff --git a/src/vm/ecalllist.h b/src/vm/ecalllist.h index b427d63..fba50a7 100644 --- a/src/vm/ecalllist.h +++ b/src/vm/ecalllist.h @@ -266,6 +266,9 @@ FCFuncStart(gEnvironmentFuncs) FCFuncElement("GetCommandLineArgsNative", SystemNative::GetCommandLineArgs) FCFuncElement("get_CurrentProcessorNumber", SystemNative::GetCurrentProcessorNumber) +#if defined(FEATURE_COMINTEROP) && !defined(FEATURE_CORESYSTEM) + QCFuncElement("WinRTSupported", SystemNative::WinRTSupported) +#endif // FEATURE_COMINTEROP FCFuncElementSig("FailFast", &gsig_SM_Str_RetVoid, SystemNative::FailFast) FCFuncElementSig("FailFast", &gsig_SM_Str_Exception_RetVoid, SystemNative::FailFastWithException) FCFuncEnd() diff --git a/src/vm/eventreporter.cpp b/src/vm/eventreporter.cpp index e10aed9..a96c525 100644 --- a/src/vm/eventreporter.cpp +++ b/src/vm/eventreporter.cpp @@ -448,8 +448,33 @@ BOOL ShouldLogInEventLog() } CONTRACTL_END; +#ifndef FEATURE_CORESYSTEM + // If the process is being debugged, don't log + if ((CORDebuggerAttached() || IsDebuggerPresent()) +#ifdef _DEBUG + // Allow debug to be able to break in + && + CLRConfig::GetConfigValue(CLRConfig::INTERNAL_BreakOnUncaughtException) == 0 +#endif + ) + { + return FALSE; + } + + static LONG fOnce = 0; + if (fOnce == 1 || FastInterlockExchange(&fOnce, 1) == 1) + { + return FALSE; + } + + if (CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_logFatalError) == 0) + return FALSE; + else + return TRUE; +#else // no event log on Apollo return FALSE; +#endif //!FEATURE_CORESYSTEM } //--------------------------------------------------------------------------------------- diff --git a/src/vm/eventtrace.cpp b/src/vm/eventtrace.cpp index 4285f6e..ba2f3da 100644 --- a/src/vm/eventtrace.cpp +++ b/src/vm/eventtrace.cpp @@ -4310,6 +4310,26 @@ HRESULT ETW::CEtwTracer::Register() { WRAPPER_NO_CONTRACT; +#ifndef FEATURE_CORESYSTEM + OSVERSIONINFO osVer; + osVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + + if (GetOSVersion(&osVer) == FALSE) { + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + else if (osVer.dwMajorVersion < ETW_SUPPORTED_MAJORVER) { + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + // if running on OS < Longhorn, skip registration unless reg key is set + // since ETW reg is expensive (in both time and working set) on older OSes + if (osVer.dwMajorVersion < ETW_ENABLED_MAJORVER && !g_fEnableETW && !CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_PreVistaETWEnabled)) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + + // If running on OS >= Longhorn, skip registration if ETW is not enabled + if (osVer.dwMajorVersion >= ETW_ENABLED_MAJORVER && !g_fEnableETW && !CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_VistaAndAboveETWEnabled)) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); +#endif EventRegisterMicrosoft_Windows_DotNETRuntime(); EventRegisterMicrosoft_Windows_DotNETRuntimePrivate(); diff --git a/src/vm/excep.cpp b/src/vm/excep.cpp index 3a4685e..277a9d9 100644 --- a/src/vm/excep.cpp +++ b/src/vm/excep.cpp @@ -4149,6 +4149,18 @@ void RaiseFailFastExceptionOnWin7(PEXCEPTION_RECORD pExceptionRecord, PCONTEXT p LIMITED_METHOD_CONTRACT; _ASSERTE(RunningOnWin7()); +#ifndef FEATURE_CORESYSTEM + typedef void (WINAPI * RaiseFailFastExceptionFnPtr)(PEXCEPTION_RECORD, PCONTEXT, DWORD); + RaiseFailFastExceptionFnPtr RaiseFailFastException; + + HINSTANCE hKernel32 = WszGetModuleHandle(WINDOWS_KERNEL32_DLLNAME_W); + if (hKernel32 == NULL) + return; + + RaiseFailFastException = (RaiseFailFastExceptionFnPtr)GetProcAddress(hKernel32, "RaiseFailFastException"); + if (RaiseFailFastException == NULL) + return; +#endif // enable preemptive mode before call into OS to allow runtime suspend to finish GCX_PREEMP(); diff --git a/src/vm/gcenv.os.cpp b/src/vm/gcenv.os.cpp index 29f912c..7849844 100644 --- a/src/vm/gcenv.os.cpp +++ b/src/vm/gcenv.os.cpp @@ -71,7 +71,9 @@ bool GCToOSInterface::SetCurrentThreadIdealAffinity(GCThreadAffinity* affinity) bool success = true; -#if !defined(FEATURE_PAL) +#if !defined(FEATURE_CORESYSTEM) + SetThreadIdealProcessor(GetCurrentThread(), (DWORD)affinity->Processor); +#elif !defined(FEATURE_PAL) PROCESSOR_NUMBER proc; if (affinity->Group != -1) diff --git a/src/vm/i386/cgenx86.cpp b/src/vm/i386/cgenx86.cpp index 1c6737b..528629c 100644 --- a/src/vm/i386/cgenx86.cpp +++ b/src/vm/i386/cgenx86.cpp @@ -94,7 +94,65 @@ void ClearRegDisplayArgumentAndScratchRegisters(REGDISPLAY * pRD) // BOOL Runtime_Test_For_SSE2() { +#ifdef FEATURE_CORESYSTEM return TRUE; +#else + + BOOL result = IsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE); + + if (result == FALSE) + return FALSE; + + // ********************************************************************** + // *** *** + // *** IMPORTANT NOTE: *** + // *** *** + // *** All of these RunningOnXXX APIs return true when *** + // *** the OS that you are running on is that OS or later. *** + // *** For example RunningOnWin2003() will return true *** + // *** when you are running on Win2k3, Vista, Win7 or later. *** + // *** *** + // ********************************************************************** + + + // Windows 7 and later should alwys be using SSE2 instructions + // this is true for both for native and Wow64 + // + if (RunningOnWin7()) + return TRUE; + + if (RunningInWow64()) + { + // There is an issue with saving/restoring the SSE2 registers under wow64 + // So we figure out if we are running on an impacted OS and Service Pack level + // See DevDiv Bugs 89587 for the wow64 bug. + // + + _ASSERTE(ExOSInfoAvailable()); // This is always available on Vista and later + + // + // The issue is fixed in Windows Server 2008 or Vista/SP1 + // + // It is not fixed in Vista/RTM, so check for that case + // + if ((ExOSInfoRunningOnServer() == FALSE)) + { + OSVERSIONINFOEX osvi; + + ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + osvi.wServicePackMajor = 0; + + DWORDLONG dwlConditionMask = 0; + VER_SET_CONDITION( dwlConditionMask, CLR_VER_SERVICEPACKMAJOR, VER_EQUAL); + + if (VerifyVersionInfo(&osvi, CLR_VER_SERVICEPACKMAJOR, dwlConditionMask)) + result = FALSE; + } + } + + return result; +#endif } //--------------------------------------------------------------- diff --git a/src/vm/i386/stublinkerx86.cpp b/src/vm/i386/stublinkerx86.cpp index 6157746..63b9e87 100644 --- a/src/vm/i386/stublinkerx86.cpp +++ b/src/vm/i386/stublinkerx86.cpp @@ -3871,6 +3871,48 @@ VOID StubLinkerCPU::EmitDisable(CodeLabel *pForwardRef, BOOL fCallIn, X86Reg Thr // jnz RarePath X86EmitCondJump(pForwardRef, X86CondCode::kJNZ); +#if defined(FEATURE_COMINTEROP) && !defined(FEATURE_CORESYSTEM) + // If we are checking whether the current thread holds the loader lock, vector + // such cases to the rare disable pathway, where we can check again. + if (fCallIn && ShouldCheckLoaderLock()) + { + X86EmitPushReg(kEAX); + X86EmitPushReg(kEDX); + + if (ThreadReg == kECX) + X86EmitPushReg(kECX); + + // BOOL AuxUlibIsDLLSynchronizationHeld(BOOL *IsHeld) + // + // So we need to be sure that both the return value and the passed BOOL are both TRUE. + // If either is FALSE, then the call failed or the lock is not held. Either way, the + // probe should not fire. + + X86EmitPushReg(kEDX); // BOOL temp + Emit8(0x54); // push ESP because arg is &temp + X86EmitCall(NewExternalCodeLabel((LPVOID) AuxUlibIsDLLSynchronizationHeld), 0); + + // callee has popped. + X86EmitPopReg(kEDX); // recover temp + + CodeLabel *pPopLabel = NewCodeLabel(); + + Emit16(0xc085); // test eax, eax + X86EmitCondJump(pPopLabel, X86CondCode::kJZ); + + Emit16(0xd285); // test edx, edx + + EmitLabel(pPopLabel); // retain the conditional flags across the pops + + if (ThreadReg == kECX) + X86EmitPopReg(kECX); + + X86EmitPopReg(kEDX); + X86EmitPopReg(kEAX); + + X86EmitCondJump(pForwardRef, X86CondCode::kJNZ); + } +#endif #ifdef _DEBUG if (ThreadReg != kECX) diff --git a/src/vm/interoputil.cpp b/src/vm/interoputil.cpp index f4dc236..ffd54d0 100644 --- a/src/vm/interoputil.cpp +++ b/src/vm/interoputil.cpp @@ -2520,12 +2520,20 @@ HRESULT GetCLSIDFromProgID(__in_z WCHAR *strProgId, GUID *pGuid) HRESULT hr = S_OK; +#ifdef FEATURE_CORESYSTEM LeaveRuntimeHolderNoThrow lrh((size_t)CLSIDFromProgID); +#else + LeaveRuntimeHolderNoThrow lrh((size_t)CLSIDFromProgIDEx); +#endif hr = lrh.GetHR(); if (FAILED(hr)) return hr; +#ifdef FEATURE_CORESYSTEM return CLSIDFromProgID(strProgId, pGuid); +#else + return CLSIDFromProgIDEx(strProgId, pGuid); +#endif } #endif // FEATURE_CLASSIC_COMINTEROP diff --git a/src/vm/jithelpers.cpp b/src/vm/jithelpers.cpp index 6d4fd89..c8c4ba6 100644 --- a/src/vm/jithelpers.cpp +++ b/src/vm/jithelpers.cpp @@ -538,7 +538,7 @@ ftype BankersRound(ftype value) if ((value -(integerPart +0.5)) == 0.0) { // round to even -#if defined(_TARGET_ARM_) +#if defined(_TARGET_ARM_) && defined(FEATURE_CORESYSTEM) // @ARMTODO: On ARM when building on CoreSystem (where we link against the system CRT) an attempt to // use fmod(float, float) fails to link (apparently this is converted to a reference to fmodf, which // is not included in the system CRT). Use the double version instead. diff --git a/src/vm/jitinterface.cpp b/src/vm/jitinterface.cpp index 8ea9016..5411b96 100644 --- a/src/vm/jitinterface.cpp +++ b/src/vm/jitinterface.cpp @@ -12769,6 +12769,7 @@ PCODE UnsafeJitFunction(MethodDesc* ftn, COR_ILMETHOD_DECODER* ILHeader, CORJIT_ "Jitted Entry at" FMT_ADDR "method %s::%s %s\n", DBG_ADDR(nativeEntry), ftn->m_pszDebugClassName, ftn->m_pszDebugMethodName, ftn->m_pszDebugMethodSignature)); +#if defined(FEATURE_CORESYSTEM) #ifdef _DEBUG LPCUTF8 pszDebugClassName = ftn->m_pszDebugClassName; @@ -12783,6 +12784,7 @@ PCODE UnsafeJitFunction(MethodDesc* ftn, COR_ILMETHOD_DECODER* ILHeader, CORJIT_ //DbgPrintf("Jitted Entry at" FMT_ADDR "method %s::%s %s size %08x\n", DBG_ADDR(nativeEntry), // pszDebugClassName, pszDebugMethodName, pszDebugMethodSignature, sizeOfCode); +#endif ClrFlushInstructionCache(nativeEntry, sizeOfCode); ret = (PCODE)nativeEntry; diff --git a/src/vm/methodtablebuilder.cpp b/src/vm/methodtablebuilder.cpp index 68148d7..303edc4 100644 --- a/src/vm/methodtablebuilder.cpp +++ b/src/vm/methodtablebuilder.cpp @@ -5172,6 +5172,7 @@ void MethodTableBuilder::SetSecurityFlagsOnMethod(bmtRTMethod* pParentMethod, pNewMD->SetRequiresLinktimeCheck(); } +#if defined(FEATURE_APTCA) || defined(FEATURE_CORESYSTEM) // All public methods on public types will do a link demand of // full trust, unless AllowUntrustedCaller attribute is set if ( @@ -5199,6 +5200,7 @@ void MethodTableBuilder::SetSecurityFlagsOnMethod(bmtRTMethod* pParentMethod, pNewMD->SetRequiresLinktimeCheck(); } } +#endif // defined(FEATURE_APTCA) || defined(FEATURE_CORESYSTEM) // If it's a delegate BeginInvoke, we need to do a HostProtection check for synchronization if(!pNewMD->RequiresLinktimeCheck() && IsDelegate()) diff --git a/src/vm/notifyexternals.cpp b/src/vm/notifyexternals.cpp index 1d69edf..df1cce4 100644 --- a/src/vm/notifyexternals.cpp +++ b/src/vm/notifyexternals.cpp @@ -30,6 +30,32 @@ BOOL ShouldCheckLoaderLock(BOOL fForMDA /*= TRUE*/) } CONTRACTL_END; +#ifdef FEATURE_CORESYSTEM // CoreSystem does not support this. return FALSE; +#else + // Because of how C++ generates code, we must use default initialization to + // 0 here. Any explicit initialization will result in thread-safety problems. + static BOOL fInited; + static BOOL fShouldCheck; + static BOOL fShouldCheck_ForMDA; + + if (VolatileLoad(&fInited) == FALSE) + { + fShouldCheck_ForMDA = FALSE; + + fShouldCheck = AuxUlibInitialize(); // may fail + +#ifdef MDA_SUPPORTED + if (fShouldCheck) + { + MdaLoaderLock* pProbe = MDA_GET_ASSISTANT(LoaderLock); + if (pProbe) + fShouldCheck_ForMDA = TRUE; + } +#endif // MDA_SUPPORTED + VolatileStore(&fInited, TRUE); + } + return (fForMDA ? fShouldCheck_ForMDA : fShouldCheck); +#endif // FEATURE_CORESYSTEM } diff --git a/src/vm/runtimecallablewrapper.cpp b/src/vm/runtimecallablewrapper.cpp index dace892..a3f7127 100644 --- a/src/vm/runtimecallablewrapper.cpp +++ b/src/vm/runtimecallablewrapper.cpp @@ -702,6 +702,7 @@ IUnknown *AppXComClassFactory::CreateInstanceInternal(IUnknown *pOuter, BOOL *pf HRESULT hr; +#ifdef FEATURE_CORESYSTEM // This works around a bug in the Windows 7 loader that prevents us from loading the // forwarder for this function typedef HRESULT (*CoCreateInstanceFromAppFnPtr) (REFCLSID rclsid, IUnknown *punkOuter, DWORD dwClsCtx, @@ -722,6 +723,7 @@ IUnknown *AppXComClassFactory::CreateInstanceInternal(IUnknown *pOuter, BOOL *pf _ASSERTE(false); IfFailThrow(E_FAIL); } +#endif LeaveRuntimeHolder lrh((size_t)CoCreateInstanceFromApp); diff --git a/src/vm/securitydeclarative.cpp b/src/vm/securitydeclarative.cpp index 1d0f5c3..a21bdb0 100644 --- a/src/vm/securitydeclarative.cpp +++ b/src/vm/securitydeclarative.cpp @@ -642,6 +642,7 @@ LinktimeCheckReason SecurityDeclarative::GetLinktimeCheckReason(MethodDesc *pMD, LinktimeCheckReason reason = LinktimeCheckReason_None; +#if defined(FEATURE_APTCA) || defined(FEATURE_CORESYSTEM) ModuleSecurityDescriptor *pMSD = ModuleSecurityDescriptor::GetModuleSecurityDescriptor(pMD->GetAssembly()); // If the method does not allow partially trusted callers, then the check is because we need to ensure all @@ -650,6 +651,7 @@ LinktimeCheckReason SecurityDeclarative::GetLinktimeCheckReason(MethodDesc *pMD, { reason |= LinktimeCheckReason_AptcaCheck; } +#endif // defined(FEATURE_APTCA) || defined(FEATURE_CORESYSTEM) // // If the method has a LinkDemand on it for either CAS or non-CAS permissions, get those and set the diff --git a/src/vm/securitymeta.cpp b/src/vm/securitymeta.cpp index 8bff148..008a408 100644 --- a/src/vm/securitymeta.cpp +++ b/src/vm/securitymeta.cpp @@ -1468,6 +1468,7 @@ VOID ModuleSecurityDescriptor::Fixup(DataImage *image) } #endif +#if defined(FEATURE_APTCA) || defined(FEATURE_CORESYSTEM) //--------------------------------------------------------------------------------------- // @@ -1510,6 +1511,7 @@ TokenSecurityDescriptorFlags ParseAptcaAttribute(const BYTE *pbAptcaBlob, DWORD return aptcaFlags; } +#endif // defined(FEATURE_APTCA) || defined(FEATURE_CORESYSTEM) //--------------------------------------------------------------------------------------- // @@ -1615,6 +1617,7 @@ TokenSecurityDescriptorFlags TokenSecurityDescriptor::ReadSecurityAttributes(IMD szAttributeNamespace != NULL && strcmp(g_SecurityNS, szAttributeNamespace) == 0) { +#if defined(FEATURE_APTCA) || defined(FEATURE_CORESYSTEM) if (strcmp(g_SecurityAPTCA + sizeof(g_SecurityNS), szAttributeName) == 0) { // Check the visibility parameter @@ -1630,6 +1633,7 @@ TokenSecurityDescriptorFlags TokenSecurityDescriptor::ReadSecurityAttributes(IMD flags |= aptcaFlags; } else +#endif // defined(FEATURE_APTCA) || defined(FEATURE_CORESYSTEM) if (strcmp(g_SecurityCriticalAttribute + sizeof(g_SecurityNS), szAttributeName) == 0) { flags |= TokenSecurityDescriptorFlags_Critical; diff --git a/src/vm/securitymeta.h b/src/vm/securitymeta.h index 403133c..00ff923 100644 --- a/src/vm/securitymeta.h +++ b/src/vm/securitymeta.h @@ -630,8 +630,10 @@ public: inline SecurityRuleSet GetSecurityRuleSet(); +#if defined(FEATURE_APTCA) || defined(FEATURE_CORESYSTEM) // Does the assembly allow partially trusted callers inline BOOL IsAPTCA(); +#endif // defined(FEATURE_APTCA) || defined(FEATURE_CORESYSTEM) private: diff --git a/src/vm/securitytransparentassembly.cpp b/src/vm/securitytransparentassembly.cpp index f9ac18c..7488dd5 100644 --- a/src/vm/securitytransparentassembly.cpp +++ b/src/vm/securitytransparentassembly.cpp @@ -1238,10 +1238,12 @@ public: ModuleSecurityDescriptorFlags moduleFlags = ModuleSecurityDescriptorFlags_None; +#if defined(FEATURE_APTCA) || defined(FEATURE_CORESYSTEM) if (tokenFlags & TokenSecurityDescriptorFlags_APTCA) { moduleFlags |= ModuleSecurityDescriptorFlags_IsAPTCA; } +#endif // defined(FEATURE_APTCA) || defined(FEATURE_CORESYSTEM) if (tokenFlags & TokenSecurityDescriptorFlags_Critical) { @@ -1324,7 +1326,6 @@ public: } }; - // // Shared transparency behavior objects // diff --git a/src/vm/util.cpp b/src/vm/util.cpp index ac0da8d..cc52b91 100644 --- a/src/vm/util.cpp +++ b/src/vm/util.cpp @@ -369,6 +369,20 @@ void NPrintToHandleA(HANDLE Handle, const char *pszString, size_t BytesToWrite) DWORD dwChunkToWrite = (DWORD) min(BytesToWrite, maxWriteFileSize); // No CharNextExA on CoreSystem, we just assume no multi-byte characters (this code path shouldn't be // used in the production codepath for currently supported CoreSystem based products anyway). +#ifndef FEATURE_CORESYSTEM + if (dwChunkToWrite < BytesToWrite) { + break; + // must go by char to find biggest string that will fit, taking DBCS chars into account + //dwChunkToWrite = 0; + //const char *charNext = pszString; + //while (dwChunkToWrite < maxWriteFileSize-2 && charNext) { + // charNext = CharNextExA(0, pszString+dwChunkToWrite, 0); + // dwChunkToWrite = (DWORD)(charNext - pszString); + //} + //if (dwChunkToWrite == 0) + // break; + } +#endif // !FEATURE_CORESYSTEM // Try to write to handle. If this is not a CUI app, then this is probably // not going to work unless the dev took special pains to set their own console @@ -2229,11 +2243,78 @@ DWORD GetLogicalCpuCountFallback() if(LogicalNum > 1) { +#ifdef FEATURE_CORESYSTEM // CoreSystem doesn't expose GetProcessAffinityMask or SetProcessAffinityMask or anything // functionally equivalent. Just assume 1:1 mapping if we get here (in reality we shouldn't since // all CoreSystems support GetLogicalProcessorInformation so GetLogicalCpuCountFromOS should have // taken care of everything. goto fDone; +#else // FEATURE_CORESYSTEM + HANDLE hCurrentProcessHandle; + DWORD_PTR dwProcessAffinity; + DWORD_PTR dwSystemAffinity; + DWORD_PTR dwAffinityMask; + + // Calculate the appropriate shifts and mask based on the + // number of logical processors. + + BYTE i = 1, PHY_ID_MASK = 0xFF, PHY_ID_SHIFT = 0; + while (i < LogicalNum) + { + i *= 2; + PHY_ID_MASK <<= 1; + PHY_ID_SHIFT++; + } + hCurrentProcessHandle = GetCurrentProcess(); + + GetProcessAffinityMask(hCurrentProcessHandle, &dwProcessAffinity, &dwSystemAffinity); + + // Check if available process affinity mask is equal to the available system affinity mask + // If the masks are equal, then all the processors the OS utilizes are available to the + // application. + + if (dwProcessAffinity != dwSystemAffinity) + { + retVal = 0; + goto fDone; + } + + dwAffinityMask = 1; + + // loop over all processors, running APIC ID retrieval code starting + // with the first one by setting process affinity. + while (dwAffinityMask != 0 && dwAffinityMask <= dwProcessAffinity) + { + // Check if this CPU is available + if (dwAffinityMask & dwProcessAffinity) + { + if (SetProcessAffinityMask(hCurrentProcessHandle, dwAffinityMask)) + { + BYTE APIC_ID, LOG_ID, PHY_ID; + __SwitchToThread(0, CALLER_LIMITS_SPINNING); // Give OS time to switch CPU + + getextcpuid(0,1, buffer); //call cpuid with EAX=1 + + APIC_ID = (dwBuffer[1] & INITIAL_APIC_ID_BITS) >> 24; + LOG_ID = APIC_ID & ~PHY_ID_MASK; + PHY_ID = APIC_ID >> PHY_ID_SHIFT; + if (LOG_ID != 0) + lProcCounter++; + } + } + dwAffinityMask = dwAffinityMask << 1; + } + // Reset the processor affinity + + SetProcessAffinityMask(hCurrentProcessHandle, dwProcessAffinity); + + // Check if HT is enabled on all the processors + if(lProcCounter > 0 && (lProcCounter == (DWORD)(PhysicalNum / LogicalNum))) + { + retVal = lProcCounter; + goto fDone; + } +#endif // FEATURE_CORESYSTEM } } fDone: diff --git a/src/vm/win32threadpool.cpp b/src/vm/win32threadpool.cpp index 90be10a..e8a05c3 100644 --- a/src/vm/win32threadpool.cpp +++ b/src/vm/win32threadpool.cpp @@ -495,7 +495,11 @@ void ThreadpoolMgr::InitPlatformVariables() CONTRACT_VIOLATION(GCViolation|FaultViolation); hNtDll = CLRLoadLibrary(W("ntdll.dll")); _ASSERTE(hNtDll); +#ifdef FEATURE_CORESYSTEM hCoreSynch = CLRLoadLibrary(W("api-ms-win-core-synch-l1-1-0.dll")); +#else + hCoreSynch = CLRLoadLibrary(W("kernel32.dll")); +#endif _ASSERTE(hCoreSynch); } diff --git a/src/zap/zapimage.cpp b/src/zap/zapimage.cpp index f285b97..2fbeb03 100644 --- a/src/zap/zapimage.cpp +++ b/src/zap/zapimage.cpp @@ -1632,7 +1632,7 @@ void ZapImage::OutputTables() #if defined(FEATURE_PAL) // PAL library requires native image sections to align to page bounaries. SetFileAlignment(0x1000); -#elif defined(_TARGET_ARM_) +#elif defined(_TARGET_ARM_) && defined(FEATURE_CORESYSTEM) if (!IsReadyToRunCompilation()) { // On ARM CoreSys builds, crossgen will use 4k file alignment, as requested by Phone perf team