1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4 //*****************************************************************************
9 // This file contains wrapper functions for Win32 API's that take strings.
11 // COM+ internally uses UNICODE as the internal state and string format. This
12 // file will undef the mapping macros so that one cannot mistakingly call a
13 // method that isn't going to work. Instead, you have to call the correct
16 //*****************************************************************************
18 #include "stdafx.h" // Precompiled header key.
19 #include "winwrap.h" // Header for macros and functions.
22 #include "ndpversion.h"
23 #include "pedecoder.h"
26 // ====== READ BEFORE ADDING CONTRACTS ==================================================
27 // The functions in this file propagate SetLastError codes to their callers.
28 // Contracts are not guaranteed to preserve these codes (and no, we're not taking
29 // the overhead hit to make them do so. Don't bother asking.)
31 // Most of the wrappers have a contract of the form:
36 // For such functions, use the special purpose construct:
38 // WINWRAPPER_NO_CONTRACT(xxx);
40 // For everything else, use STATIC_CONTRACT.
43 #define CONTRACT $$$$$$$$READ_COMMENT_IN_WINFIX_CPP$$$$$$$$$$
46 #define CONTRACTL $$$$$$$$READ_COMMENT_IN_WINFIX_CPP$$$$$$$$$$
48 #ifdef ENABLE_CONTRACTS_IMPL
49 static BOOL gWinWrapperContractRecursionBreak = FALSE;
52 class WinWrapperContract
55 WinWrapperContract(const char *szFunction, const char *szFile, int lineNum)
59 m_pClrDebugState = NULL;
61 if (gWinWrapperContractRecursionBreak)
66 m_pClrDebugState = GetClrDebugState();
68 // Save old debug state
69 m_IncomingClrDebugState = *m_pClrDebugState;
72 m_pClrDebugState->ViolationMaskReset( ThrowsViolation );
74 if (m_pClrDebugState->IsFaultForbid() && !(m_pClrDebugState->ViolationMask() & (FaultViolation|FaultNotFatal|BadDebugState)))
76 gWinWrapperContractRecursionBreak = TRUE;
78 CONTRACT_ASSERT("INJECT_FAULT called in a FAULTFORBID region.",
79 Contract::FAULT_Forbid,
94 //!!!!!! THIS DESTRUCTOR MUST NOT CHANGE THE GETLASTERROR VALUE !!!!!!
96 // Backout all changes to debug state.
97 if (m_pClrDebugState != NULL)
99 *m_pClrDebugState = m_IncomingClrDebugState;
103 ClrDebugState *m_pClrDebugState;
104 ClrDebugState m_IncomingClrDebugState;
112 #ifdef ENABLE_CONTRACTS_IMPL
113 #define WINWRAPPER_NO_CONTRACT(stmt) \
114 STATIC_CONTRACT_NOTHROW; \
115 STATIC_CONTRACT_FAULT; \
116 STATIC_CONTRACT_CANNOT_TAKE_LOCK; \
117 WinWrapperContract __wcontract(__FUNCTION__, __FILE__, __LINE__); \
120 #define STATIC_WINWRAPPER_NO_CONTRACT(stmt) \
121 STATIC_CONTRACT_NOTHROW; \
122 STATIC_CONTRACT_CANNOT_TAKE_LOCK; \
123 STATIC_CONTRACT_FAULT; \
128 #define WINWRAPPER_NO_CONTRACT(stmt)
129 #define STATIC_WINWRAPPER_NO_CONTRACT(stmt)
132 ULONG g_dwMaxDBCSCharByteSize = 0;
134 // The only purpose of this function is to make a local copy of lpCommandLine.
135 // Because windows implementation of CreateProcessW can actually change lpCommandLine,
136 // but we'd like to keep it const.
139 LPCWSTR lpApplicationName,
140 LPCWSTR lpCommandLine,
141 LPSECURITY_ATTRIBUTES lpProcessAttributes,
142 LPSECURITY_ATTRIBUTES lpThreadAttributes,
143 BOOL bInheritHandles,
144 DWORD dwCreationFlags,
145 LPVOID lpEnvironment,
146 LPCWSTR lpCurrentDirectory,
147 LPSTARTUPINFOW lpStartupInfo,
148 LPPROCESS_INFORMATION lpProcessInformation
151 WINWRAPPER_NO_CONTRACT(SetLastError(ERROR_OUTOFMEMORY); return 0;);
156 size_t commandLineLength = wcslen(lpCommandLine) + 1;
157 NewArrayHolder<WCHAR> nonConstCommandLine(new (nothrow) WCHAR[commandLineLength]);
158 if (nonConstCommandLine == NULL)
160 SetLastError(ERROR_OUTOFMEMORY);
164 memcpy(nonConstCommandLine, lpCommandLine, commandLineLength * sizeof(WCHAR));
166 fResult = CreateProcessW(lpApplicationName,
173 (LPWSTR)lpCurrentDirectory,
175 lpProcessInformation);
177 // At the end of the current scope, the last error code will be overwritten by the destructor of
178 // NewArrayHolder. So we save the error code here, and restore it after the end of the current scope.
179 err = GetLastError();
190 #include "tlhelp32.h"
193 //********** Globals. *********************************************************
194 bool g_fEnsureCharSetInfoInitialized = FALSE; // true if we've detected the platform's character set characteristics
196 // Detect Unicode support of the operating system, and initialize globals
197 void EnsureCharSetInfoInitialized()
199 STATIC_CONTRACT_NOTHROW;
200 STATIC_CONTRACT_FORBID_FAULT;
201 STATIC_CONTRACT_CANNOT_TAKE_LOCK;
203 if (!g_fEnsureCharSetInfoInitialized)
205 // NOTE: Do not use any of the Wsz* wrapper functions right now. They will have
208 // Per Shupak, you're supposed to get the maximum size of a DBCS char
209 // dynamically to work properly on all locales (bug 2757).
211 if (GetCPInfo(CP_ACP, &cpInfo))
212 g_dwMaxDBCSCharByteSize = cpInfo.MaxCharSize;
214 g_dwMaxDBCSCharByteSize = 2;
216 VolatileStore(&g_fEnsureCharSetInfoInitialized, true);
223 // Running with an interactive workstation.
224 BOOL RunningInteractive()
226 STATIC_CONTRACT_NOTHROW;
227 STATIC_CONTRACT_FORBID_FAULT;
229 static int fInteractive = -1;
230 if (fInteractive != -1)
231 return fInteractive != 0;
233 #if !defined(FEATURE_CORESYSTEM)
234 HWINSTA hwinsta = NULL;
236 if ((hwinsta = GetProcessWindowStation() ) != NULL)
239 USEROBJECTFLAGS flags;
241 if (GetUserObjectInformationW (hwinsta, UOI_FLAGS, &flags, sizeof(flags), &lengthNeeded))
243 if ((flags.dwFlags & WSF_VISIBLE) == 0)
247 #endif // !FEATURE_CORESYSTEM
249 if (fInteractive != 0)
252 return fInteractive != 0;
255 typedef HRESULT(WINAPI *pfnSetThreadDescription)(HANDLE hThread, PCWSTR lpThreadDescription);
256 extern pfnSetThreadDescription g_pfnSetThreadDescription;
258 // Dummy method if windows version does not support it
259 HRESULT SetThreadDescriptionDummy(HANDLE hThread, PCWSTR lpThreadDescription)
264 HRESULT WINAPI InitializeSetThreadDescription(HANDLE hThread, PCWSTR lpThreadDescription)
266 HMODULE hKernel32 = WszLoadLibrary(W("kernel32.dll"));
268 pfnSetThreadDescription pLocal = NULL;
269 if (hKernel32 != NULL)
271 // store to thread local variable to prevent data race
272 pLocal = (pfnSetThreadDescription)GetProcAddress(hKernel32, "SetThreadDescription");
275 if (pLocal == NULL) // method is only available with Windows 10 Creators Update or later
277 g_pfnSetThreadDescription = SetThreadDescriptionDummy;
281 g_pfnSetThreadDescription = pLocal;
284 return g_pfnSetThreadDescription(hThread, lpThreadDescription);
287 pfnSetThreadDescription g_pfnSetThreadDescription = &InitializeSetThreadDescription;
289 // Set unmanaged thread name which will show up in ETW and Debuggers which know how to read this data.
290 HRESULT SetThreadName(HANDLE hThread, PCWSTR lpThreadDescription)
292 return g_pfnSetThreadDescription(hThread, lpThreadDescription);
295 #endif //!FEATURE_PAL