[Tizen] Unify dnetmemoryenumlib terms to match the codebase (#291)
[platform/upstream/coreclr.git] / src / utilcode / winfix.cpp
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 //*****************************************************************************
5 // WinWrap.cpp
6 //
7
8 //
9 // This file contains wrapper functions for Win32 API's that take strings.
10 //
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
14 // wrapper API.
15 //
16 //*****************************************************************************
17
18 #include "stdafx.h"                     // Precompiled header key.
19 #include "winwrap.h"                    // Header for macros and functions.
20 #include "utilcode.h"
21 #include "holder.h"
22 #include "ndpversion.h"
23 #include "pedecoder.h"
24
25
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.)
30 //
31 // Most of the wrappers have a contract of the form:
32 //
33 //     NOTHROW;
34 //     INJECT_FAULT(xxx);
35 //
36 // For such functions, use the special purpose construct:
37 //
38 //     WINWRAPPER_NO_CONTRACT(xxx);
39 //
40 // For everything else, use STATIC_CONTRACT.
41 //     
42 #undef CONTRACT
43 #define CONTRACT $$$$$$$$READ_COMMENT_IN_WINFIX_CPP$$$$$$$$$$
44
45 #undef CONTRACTL
46 #define CONTRACTL $$$$$$$$READ_COMMENT_IN_WINFIX_CPP$$$$$$$$$$
47
48 #ifdef ENABLE_CONTRACTS_IMPL
49 static BOOL gWinWrapperContractRecursionBreak = FALSE;
50
51
52 class WinWrapperContract
53 {
54     public:
55         WinWrapperContract(const char *szFunction, const char *szFile, int lineNum)
56         {
57             CANNOT_HAVE_CONTRACT;
58
59             m_pClrDebugState = NULL;
60             
61             if (gWinWrapperContractRecursionBreak)
62             {
63                 return;
64             }
65
66             m_pClrDebugState = GetClrDebugState();
67
68             // Save old debug state
69             m_IncomingClrDebugState = *m_pClrDebugState;
70
71
72             m_pClrDebugState->ViolationMaskReset( ThrowsViolation );
73
74             if (m_pClrDebugState->IsFaultForbid() && !(m_pClrDebugState->ViolationMask() & (FaultViolation|FaultNotFatal|BadDebugState)))
75             {
76                 gWinWrapperContractRecursionBreak = TRUE;
77
78                 CONTRACT_ASSERT("INJECT_FAULT called in a FAULTFORBID region.",
79                                 Contract::FAULT_Forbid,
80                                 Contract::FAULT_Mask,
81                                 szFunction,
82                                 szFile,
83                                 lineNum
84                                 );
85             }
86
87             
88         };
89
90         ~WinWrapperContract()
91         {
92             CANNOT_HAVE_CONTRACT;
93
94             //!!!!!! THIS DESTRUCTOR MUST NOT CHANGE THE GETLASTERROR VALUE !!!!!!
95
96             // Backout all changes to debug state.
97             if (m_pClrDebugState != NULL)
98             {
99                 *m_pClrDebugState = m_IncomingClrDebugState;
100             }
101         }
102     private:
103         ClrDebugState *m_pClrDebugState;
104         ClrDebugState  m_IncomingClrDebugState;
105
106 };
107
108
109
110 #endif
111
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__); \
118     if (0) {stmt}  \
119         
120 #define STATIC_WINWRAPPER_NO_CONTRACT(stmt) \
121     STATIC_CONTRACT_NOTHROW;      \
122     STATIC_CONTRACT_CANNOT_TAKE_LOCK;  \
123     STATIC_CONTRACT_FAULT;        \
124     if (0) {stmt}  \
125         
126         
127 #else
128 #define WINWRAPPER_NO_CONTRACT(stmt)
129 #define STATIC_WINWRAPPER_NO_CONTRACT(stmt) 
130 #endif
131
132 ULONG g_dwMaxDBCSCharByteSize = 0;
133
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.
137 BOOL
138 WszCreateProcess(
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
149     )
150 {
151     WINWRAPPER_NO_CONTRACT(SetLastError(ERROR_OUTOFMEMORY); return 0;);
152
153     BOOL fResult;
154     DWORD err;
155     {
156         size_t commandLineLength = wcslen(lpCommandLine) + 1;
157         NewArrayHolder<WCHAR> nonConstCommandLine(new (nothrow) WCHAR[commandLineLength]);
158         if (nonConstCommandLine == NULL)
159         {
160             SetLastError(ERROR_OUTOFMEMORY);
161             return 0;
162         }
163             
164         memcpy(nonConstCommandLine, lpCommandLine, commandLineLength * sizeof(WCHAR));
165             
166         fResult = CreateProcessW(lpApplicationName,
167                                    nonConstCommandLine,
168                                    lpProcessAttributes,
169                                    lpThreadAttributes,
170                                    bInheritHandles,
171                                    dwCreationFlags,
172                                    lpEnvironment,
173                                    (LPWSTR)lpCurrentDirectory,
174                                    lpStartupInfo,
175                                    lpProcessInformation);
176
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();
180     }
181
182     SetLastError(err);
183     return fResult;
184 }
185
186 #ifndef FEATURE_PAL
187
188
189 #include "psapi.h"
190 #include "tlhelp32.h"
191 #include "winnls.h"
192
193 //********** Globals. *********************************************************
194 bool            g_fEnsureCharSetInfoInitialized = FALSE; // true if we've detected the platform's character set characteristics
195
196 // Detect Unicode support of the operating system, and initialize globals
197 void EnsureCharSetInfoInitialized()
198 {
199     STATIC_CONTRACT_NOTHROW;
200     STATIC_CONTRACT_FORBID_FAULT;
201     STATIC_CONTRACT_CANNOT_TAKE_LOCK;
202
203     if (!g_fEnsureCharSetInfoInitialized)
204     {
205         // NOTE: Do not use any of the Wsz* wrapper functions right now. They will have
206         // problems.
207
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).
210         CPINFO cpInfo;
211         if (GetCPInfo(CP_ACP, &cpInfo))
212             g_dwMaxDBCSCharByteSize = cpInfo.MaxCharSize;
213         else
214             g_dwMaxDBCSCharByteSize = 2;
215
216         VolatileStore(&g_fEnsureCharSetInfoInitialized, true);
217     }
218
219     return;
220 }
221
222
223 // Running with an interactive workstation.
224 BOOL RunningInteractive()
225 {
226     STATIC_CONTRACT_NOTHROW;
227     STATIC_CONTRACT_FORBID_FAULT;
228
229     static int fInteractive = -1;
230     if (fInteractive != -1)
231         return fInteractive != 0;
232
233 #if !defined(FEATURE_CORESYSTEM)
234         HWINSTA hwinsta = NULL;
235
236         if ((hwinsta = GetProcessWindowStation() ) != NULL)
237         {
238             DWORD lengthNeeded;
239             USEROBJECTFLAGS flags;
240
241             if (GetUserObjectInformationW (hwinsta, UOI_FLAGS, &flags, sizeof(flags), &lengthNeeded))
242            {
243                     if ((flags.dwFlags & WSF_VISIBLE) == 0)
244                         fInteractive = 0;
245             }
246         }
247 #endif // !FEATURE_CORESYSTEM
248
249     if (fInteractive != 0)
250         fInteractive = 1;
251
252     return fInteractive != 0;
253 }
254
255 typedef HRESULT(WINAPI *pfnSetThreadDescription)(HANDLE hThread, PCWSTR lpThreadDescription);
256 extern pfnSetThreadDescription g_pfnSetThreadDescription;
257
258 // Dummy method if windows version does not support it
259 HRESULT SetThreadDescriptionDummy(HANDLE hThread, PCWSTR lpThreadDescription)
260 {
261     return NOERROR;
262 }
263
264 HRESULT WINAPI InitializeSetThreadDescription(HANDLE hThread, PCWSTR lpThreadDescription)
265 {
266     HMODULE hKernel32 = WszLoadLibrary(W("kernel32.dll"));
267
268     pfnSetThreadDescription pLocal = NULL; 
269     if (hKernel32 != NULL)
270     {
271         // store to thread local variable to prevent data race
272         pLocal = (pfnSetThreadDescription)GetProcAddress(hKernel32, "SetThreadDescription");
273     }
274
275     if (pLocal == NULL) // method is only available with Windows 10 Creators Update or later
276     {
277         g_pfnSetThreadDescription = SetThreadDescriptionDummy;
278     }
279     else
280     {
281         g_pfnSetThreadDescription = pLocal;
282     }
283
284     return g_pfnSetThreadDescription(hThread, lpThreadDescription);
285 }
286
287 pfnSetThreadDescription g_pfnSetThreadDescription = &InitializeSetThreadDescription;
288
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)
291 {
292     return g_pfnSetThreadDescription(hThread, lpThreadDescription);
293 }
294
295 #endif //!FEATURE_PAL