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.h
6//
7// This file contains wrapper functions for Win32 API's that take strings.
8//
9// The Common Language Runtime internally uses UNICODE as the internal state
10// and string format. This file will undef the mapping macros so that one
11// cannot mistakingly call a method that isn't going to work. Instead, you
12// have to call the correct wrapper API.
13//
14//*****************************************************************************
15
16#ifndef __WIN_WRAP_H__
17#define __WIN_WRAP_H__
18
19//********** Macros. **********************************************************
20#if !defined(WIN32_LEAN_AND_MEAN)
21#define WIN32_LEAN_AND_MEAN
22#endif
23
24//
25// WinCE uniformly uses cdecl calling convention on x86. __stdcall is defined as __cdecl in SDK.
26// STDCALL macro is meant to be used where we have hard dependency on __stdcall calling convention
27// - the unification with __cdecl does not apply to STDCALL.
28//
29#define STDCALL _stdcall
30
31//********** Includes. ********************************************************
32
33#include <crtwrap.h>
34#include <windows.h>
35#include <wincrypt.h>
36#include <specstrings.h>
37
38#include "registrywrapper.h"
39#include "longfilepathwrappers.h"
40
41#if defined(_PREFAST_) || defined(SOURCE_FORMATTING)
42//
43// For PREFAST we don't want the C_ASSERT to be expanded since it always
44// involves the comparison of two constants which causes PREfast warning 326
45//
46#undef C_ASSERT
47#define C_ASSERT(expr)
48#endif
49
50#include "palclr.h"
51
52#if !defined(__TODO_PORT_TO_WRAPPERS__)
53//*****************************************************************************
54// Undefine all of the windows wrappers so you can't use them.
55//*****************************************************************************
56
57// wincrypt.h
58#undef CryptAcquireContext
59#undef CryptSignHash
60#undef CryptVerifySignature
61
62// winbase.h
63#undef GetBinaryType
64#undef GetShortPathName
65#undef GetLongPathName
66#undef GetEnvironmentStrings
67#undef FreeEnvironmentStrings
68#undef FormatMessage
69#undef lstrcmp
70#undef lstrcmpi
71#undef lstrcpyn
72#undef lstrlen
73#undef CreateMutex
74#undef OpenMutex
75#undef CreateEvent
76#undef OpenEvent
77#undef CreateSemaphore
78#undef OpenSemaphore
79#undef CreateWaitableTimer
80#undef CreateFileMapping
81#undef OpenFileMapping
82#undef LoadLibrary
83#undef LoadLibraryEx
84#undef GetModuleFileName
85#undef GetModuleHandle
86#undef GetModuleHandleEx
87#undef CreateProcess
88#undef GetCommandLine
89#undef GetEnvironmentVariable
90#undef SetEnvironmentVariable
91#undef ExpandEnvironmentStrings
92#undef OutputDebugString
93#undef FindResource
94#undef FindResourceEx
95#undef BeginUpdateResource
96#undef UpdateResource
97#undef EndUpdateResource
98#undef GetPrivateProfileInt
99#undef GetSystemDirectory
100#undef GetTempPath
101#undef GetTempFileName
102#undef SetCurrentDirectory
103#undef GetCurrentDirectory
104#undef CreateDirectory
105#undef RemoveDirectory
106#undef GetFullPathName
107#undef CreateFile
108#undef SetFileAttributes
109#undef GetFileAttributes
110#undef GetFileAttributesEx
111#undef DeleteFile
112#undef FindFirstFileEx
113#undef FindFirstFile
114#undef FindNextFile
115#undef SearchPath
116#undef CopyFile
117#undef CopyFileEx
118#undef MoveFile
119#undef MoveFileEx
120#undef CreateHardLink
121#undef CreateNamedPipe
122#undef WaitNamedPipe
123#undef LookupPrivilegeValue
124#undef GetVersionEx
125
126// winuser.h
127#undef MAKEINTRESOURCE
128#undef GetUserObjectInformation
129#undef GetMessage
130
131#undef SendMessage
132#undef CharLower
133#undef CharNext
134#undef MessageBox
135#undef GetClassName
136#undef LoadString
137#undef GetCalendarInfo
138#undef GetDateFormat
139#undef GetTimeFormat
140#undef LCMapString
141
142// winnetwk.h
143#undef WNetGetConnection
144
145// Win32 Fusion API's
146#undef QueryActCtxW
147
148#endif // !defined(__TODO_PORT_TO_WRAPPERS__)
149
150//
151// NT supports the wide entry points. So we redefine the wrappers right back
152// to the *W entry points as macros. This way no client code needs a wrapper on NT.
153//
154
155// wincrypt.h
156#define WszCryptAcquireContext CryptAcquireContextW
157#define WszCryptSignHash CryptSignHashW
158#define WszCryptVerifySignature CryptVerifySignatureW
159
160// winbase.h
161#define WszGetEnvironmentStrings GetEnvironmentStringsW
162#define WszFreeEnvironmentStrings FreeEnvironmentStringsW
163#ifndef USE_FORMATMESSAGE_WRAPPER
164#define WszFormatMessage FormatMessageW
165#else
166#define WszFormatMessage CCompRC::FormatMessage
167#endif
168#define Wszlstrcmp lstrcmpW
169#define Wszlstrcmpi lstrcmpiW
170#define WszCreateMutex CreateMutexW
171#define WszOpenMutex OpenMutexW
172#define WszCreateEvent CreateEventW
173#define WszOpenEvent OpenEventW
174#define WszCreateWaitableTimer CreateWaitableTimerW
175#define WszCreateFileMapping CreateFileMappingW
176#define WszOpenFileMapping OpenFileMappingW
177#define WszGetModuleHandle GetModuleHandleW
178#define WszGetModuleHandleEx GetModuleHandleExW
179#define WszGetCommandLine GetCommandLineW
180#define WszSetEnvironmentVariable SetEnvironmentVariableW
181#define WszExpandEnvironmentStrings ExpandEnvironmentStringsW
182#define WszOutputDebugString OutputDebugStringW
183#define WszFindResource FindResourceW
184#define WszFindResourceEx FindResourceExW
185#define WszBeginUpdateResource BeginUpdateResourceW
186#define WszUpdateResource UpdateResourceW
187#define WszEndUpdateResource EndUpdateResourceW
188#define WszGetPrivateProfileInt GetPrivateProfileIntW
189#define WszGetSystemDirectory GetSystemDirectoryW
190#define WszCreateNamedPipe CreateNamedPipeW
191#define WszWaitNamedPipe WaitNamedPipeW
192#define WszLookupPrivilegeValue LookupPrivilegeValueW
193
194// winuser.h
195#define WszMAKEINTRESOURCE MAKEINTRESOURCEW
196#define WszGetUserObjectInformation GetUserObjectInformationW
197#define WszGetMessage GetMessageW
198#define WszSendMessage SendMessageW
199#define WszCharLower CharLowerW
200#define WszCharNext CharNextW
201#define WszMessageBox LateboundMessageBoxW
202#define WszGetClassName GetClassNameW
203#define WszLoadString LoadStringW
204#define WszRegOpenKeyEx ClrRegOpenKeyEx
205#define WszRegOpenKey(hKey, wszSubKey, phkRes) ClrRegOpenKeyEx(hKey, wszSubKey, 0, KEY_ALL_ACCESS, phkRes)
206#define WszRegQueryValue RegQueryValueW
207#define WszRegQueryValueEx RegQueryValueExW
208#define WszRegQueryValueExTrue RegQueryValueExW
209#define WszRegQueryStringValueEx RegQueryValueExW
210
211
212#define WszRegQueryInfoKey RegQueryInfoKeyW
213#define WszRegEnumValue RegEnumValueW
214#define WszRegEnumKeyEx RegEnumKeyExW
215#define WszGetCalendarInfo GetCalendarInfoW
216#define WszGetDateFormat GetDateFormatW
217#define WszGetTimeFormat GetTimeFormatW
218#define WszLCMapString LCMapStringW
219#define WszMultiByteToWideChar MultiByteToWideChar
220#define WszWideCharToMultiByte WideCharToMultiByte
221#define WszCreateSemaphore CreateSemaphoreW
222#define WszQueryActCtxW QueryActCtxW
223
224
225#ifdef FEATURE_CORESYSTEM
226
227// CoreSystem has CreateSemaphoreExW but not CreateSemaphoreW.
228#undef WszCreateSemaphore
229#define WszCreateSemaphore(_secattr, _count, _maxcount, _name) CreateSemaphoreExW((_secattr), (_count), (_maxcount), (_name), 0, MAXIMUM_ALLOWED | SYNCHRONIZE | SEMAPHORE_MODIFY_STATE)
230
231// Same deal as above for GetFileVersionInfo/GetFileVersionInfoSize.
232#undef GetFileVersionInfo
233#define GetFileVersionInfo(_filename, _handle, _len, _data) GetFileVersionInfoEx(0, (_filename), (_handle), (_len), (_data))
234#undef GetFileVersionInfoSize
235#define GetFileVersionInfoSize(_filename, _handle) GetFileVersionInfoSizeEx(0, (_filename), (_handle))
236
237#endif // FEATURE_CORESYSTEM
238
239#ifndef _T
240#define _T(str) W(str)
241#endif
242
243//File and Directory Functions which need special handling for LongFile Names
244//Note only the functions which are currently used are defined
245#define WszLoadLibrary LoadLibraryExWrapper
246#define WszLoadLibraryEx LoadLibraryExWrapper
247#define WszCreateFile CreateFileWrapper
248#define WszSetFileAttributes SetFileAttributesWrapper
249#define WszGetFileAttributes GetFileAttributesWrapper
250#define WszGetFileAttributesEx GetFileAttributesExWrapper
251#define WszDeleteFile DeleteFileWrapper
252#define WszFindFirstFileEx FindFirstFileExWrapper
253#define WszFindNextFile FindNextFileW
254#define WszCopyFile CopyFileWrapper
255#define WszCopyFileEx CopyFileExWrapper
256#define WszMoveFileEx MoveFileExWrapper
257#define WszMoveFile(lpExistingFileName, lpNewFileName) WszMoveFileEx(lpExistingFileName, lpNewFileName, 0)
258#define WszCreateDirectory CreateDirectoryWrapper
259#define WszRemoveDirectory RemoveDirectoryWrapper
260#define WszCreateHardLink CreateHardLinkWrapper
261
262//Can not use extended syntax
263#define WszGetFullPathName GetFullPathNameW
264
265//Long Files will not work on these till redstone
266#define WszGetCurrentDirectory GetCurrentDirectoryWrapper
267#define WszGetTempFileName GetTempFileNameWrapper
268#define WszGetTempPath GetTempPathWrapper
269
270//APIS which have a buffer as an out parameter
271#define WszGetEnvironmentVariable GetEnvironmentVariableWrapper
272#define WszSearchPath SearchPathWrapper
273#define WszGetShortPathName GetShortPathNameWrapper
274#define WszGetLongPathName GetLongPathNameWrapper
275#define WszGetModuleFileName GetModuleFileNameWrapper
276
277//NOTE: IF the following API's are enabled ensure that they can work with LongFile Names
278//See the usage and implementation of above API's
279//
280//#define WszSetCurrentDirectory SetCurrentDirectoryW
281//#define WszGetBinaryType GetBinaryTypeWrapper //Coresys does not seem to have this API
282
283#if FEATURE_PAL
284#define WszFindFirstFile FindFirstFileW
285#else
286#define WszFindFirstFile(_lpFileName_, _lpFindData_) FindFirstFileExWrapper(_lpFileName_, FindExInfoStandard, _lpFindData_, FindExSearchNameMatch, NULL, 0)
287#endif //FEATURE_PAL
288//*****************************************************************************
289// Prototypes for API's.
290//*****************************************************************************
291
292extern DWORD g_dwMaxDBCSCharByteSize;
293
294void EnsureCharSetInfoInitialized();
295
296inline DWORD GetMaxDBCSCharByteSize()
297{
298 // contract.h not visible here
299 __annotation(W("WRAPPER ") W("GetMaxDBCSCharByteSize"));
300#ifndef FEATURE_PAL
301 EnsureCharSetInfoInitialized();
302
303 _ASSERTE(g_dwMaxDBCSCharByteSize != 0);
304 return (g_dwMaxDBCSCharByteSize);
305#else // FEATURE_PAL
306 return 3;
307#endif // FEATURE_PAL
308}
309
310#ifndef FEATURE_PAL
311BOOL RunningInteractive();
312#else // !FEATURE_PAL
313#define RunningInteractive() FALSE
314#endif // !FEATURE_PAL
315
316// Determines if the process is running as Local System or as a service. Note that this function uses the
317// process' identity and not the thread's (if the thread is impersonating).
318//
319// If the function succeeds, it returns ERROR_SUCCESS, else it returns the error code returned by GetLastError()
320DWORD RunningAsLocalSystemOrService(OUT BOOL& fIsLocalSystemOrService);
321
322#ifndef Wsz_mbstowcs
323#define Wsz_mbstowcs(szOut, szIn, iSize) WszMultiByteToWideChar(CP_ACP, 0, szIn, -1, szOut, iSize)
324#endif
325
326#ifndef Wsz_wcstombs
327#define Wsz_wcstombs(szOut, szIn, iSize) WszWideCharToMultiByte(CP_ACP, 0, szIn, -1, szOut, iSize, 0, 0)
328#endif
329
330// For all platforms:
331
332BOOL
333WszCreateProcess(
334 LPCWSTR lpApplicationName,
335 LPCWSTR lpCommandLine,
336 LPSECURITY_ATTRIBUTES lpProcessAttributes,
337 LPSECURITY_ATTRIBUTES lpThreadAttributes,
338 BOOL bInheritHandles,
339 DWORD dwCreationFlags,
340 LPVOID lpEnvironment,
341 LPCWSTR lpCurrentDirectory,
342 LPSTARTUPINFOW lpStartupInfo,
343 LPPROCESS_INFORMATION lpProcessInformation
344 );
345
346#if defined(_X86_) && defined(_MSC_VER)
347
348//
349// Windows SDK does not use intrinsics on x86. Redefine the interlocked operations to use intrinsics.
350//
351
352#include "intrin.h"
353
354#define InterlockedIncrement _InterlockedIncrement
355#define InterlockedDecrement _InterlockedDecrement
356#define InterlockedExchange _InterlockedExchange
357#define InterlockedCompareExchange _InterlockedCompareExchange
358#define InterlockedExchangeAdd _InterlockedExchangeAdd
359#define InterlockedCompareExchange64 _InterlockedCompareExchange64
360#define InterlockedAnd _InterlockedAnd
361#define InterlockedOr _InterlockedOr
362
363//
364// There is no _InterlockedCompareExchangePointer intrinsic in VC++ for x86.
365// winbase.h #defines InterlockedCompareExchangePointer as __InlineInterlockedCompareExchangePointer,
366// which calls the Win32 InterlockedCompareExchange, not the intrinsic _InterlockedCompareExchange.
367// We want the intrinsic, so we #undef the Windows version of this API, and define our own.
368//
369#ifdef InterlockedCompareExchangePointer
370#undef InterlockedCompareExchangePointer
371#endif
372
373FORCEINLINE
374PVOID
375InterlockedCompareExchangePointer (
376 __inout PVOID volatile *Destination,
377 __in_opt PVOID ExChange,
378 __in_opt PVOID Comperand
379 )
380{
381 return((PVOID)(LONG_PTR)_InterlockedCompareExchange((LONG volatile *)Destination, (LONG)(LONG_PTR)ExChange, (LONG)(LONG_PTR)Comperand));
382}
383
384#endif // _X86_ && _MSC_VER
385
386#if defined(_ARM_) & !defined(FEATURE_PAL)
387//
388// InterlockedCompareExchangeAcquire/InterlockedCompareExchangeRelease is not mapped in SDK to the correct intrinsics. Remove once
389// the SDK definition is fixed (OS Bug #516255)
390//
391#undef InterlockedCompareExchangeAcquire
392#define InterlockedCompareExchangeAcquire _InterlockedCompareExchange_acq
393#undef InterlockedCompareExchangeRelease
394#define InterlockedCompareExchangeRelease _InterlockedCompareExchange_rel
395#endif
396
397#if defined(_X86_) & !defined(InterlockedIncrement64)
398
399// Interlockedxxx64 that do not have intrinsics are only supported on Windows Server 2003
400// or higher for X86 so define our own portable implementation
401
402#undef InterlockedIncrement64
403#define InterlockedIncrement64 __InterlockedIncrement64
404#undef InterlockedDecrement64
405#define InterlockedDecrement64 __InterlockedDecrement64
406#undef InterlockedExchange64
407#define InterlockedExchange64 __InterlockedExchange64
408#undef InterlockedExchangeAdd64
409#define InterlockedExchangeAdd64 __InterlockedExchangeAdd64
410
411__forceinline LONGLONG __InterlockedIncrement64(LONGLONG volatile *Addend)
412{
413 LONGLONG Old;
414
415 do {
416 Old = *Addend;
417 } while (InterlockedCompareExchange64(Addend,
418 Old + 1,
419 Old) != Old);
420
421 return Old + 1;
422}
423
424__forceinline LONGLONG __InterlockedDecrement64(LONGLONG volatile *Addend)
425{
426 LONGLONG Old;
427
428 do {
429 Old = *Addend;
430 } while (InterlockedCompareExchange64(Addend,
431 Old - 1,
432 Old) != Old);
433
434 return Old - 1;
435}
436
437__forceinline LONGLONG __InterlockedExchange64(LONGLONG volatile * Target, LONGLONG Value)
438{
439 LONGLONG Old;
440
441 do {
442 Old = *Target;
443 } while (InterlockedCompareExchange64(Target,
444 Value,
445 Old) != Old);
446
447 return Old;
448}
449
450__forceinline LONGLONG __InterlockedExchangeAdd64(LONGLONG volatile * Addend, LONGLONG Value)
451{
452 LONGLONG Old;
453
454 do {
455 Old = *Addend;
456 } while (InterlockedCompareExchange64(Addend,
457 Old + Value,
458 Old) != Old);
459
460 return Old;
461}
462
463#endif // _X86_
464
465// Output printf-style formatted text to the debugger if it's present or stdout otherwise.
466inline void DbgWPrintf(const LPCWSTR wszFormat, ...)
467{
468 WCHAR wszBuffer[4096];
469
470 va_list args;
471 va_start(args, wszFormat);
472
473 _vsnwprintf_s(wszBuffer, sizeof(wszBuffer) / sizeof(WCHAR), _TRUNCATE, wszFormat, args);
474
475 va_end(args);
476
477 if (IsDebuggerPresent())
478 {
479 OutputDebugStringW(wszBuffer);
480 }
481 else
482 {
483 fwprintf(stdout, W("%s"), wszBuffer);
484 fflush(stdout);
485 }
486}
487
488typedef int (*MessageBoxWFnPtr)(HWND hWnd,
489 LPCWSTR lpText,
490 LPCWSTR lpCaption,
491 UINT uType);
492
493inline int LateboundMessageBoxW(HWND hWnd,
494 LPCWSTR lpText,
495 LPCWSTR lpCaption,
496 UINT uType)
497{
498#ifndef FEATURE_PAL
499 // User32 should exist on all systems where displaying a message box makes sense.
500 HMODULE hGuiExtModule = WszLoadLibrary(W("user32"));
501 if (hGuiExtModule)
502 {
503 int result = IDCANCEL;
504 MessageBoxWFnPtr fnptr = (MessageBoxWFnPtr)GetProcAddress(hGuiExtModule, "MessageBoxW");
505 if (fnptr)
506 result = fnptr(hWnd, lpText, lpCaption, uType);
507
508 FreeLibrary(hGuiExtModule);
509 return result;
510 }
511#endif // !FEATURE_PAL
512
513 // No luck. Output the caption and text to the debugger if present or stdout otherwise.
514 if (lpText == NULL)
515 lpText = W("<null>");
516 if (lpCaption == NULL)
517 lpCaption = W("<null>");
518 DbgWPrintf(W("**** MessageBox invoked, title '%s' ****\n"), lpCaption);
519 DbgWPrintf(W(" %s\n"), lpText);
520 DbgWPrintf(W("********\n"));
521 DbgWPrintf(W("\n"));
522
523 // Indicate to the caller that message box was not actually displayed
524 SetLastError(ERROR_NOT_SUPPORTED);
525 return 0;
526}
527
528inline int LateboundMessageBoxA(HWND hWnd,
529 LPCSTR lpText,
530 LPCSTR lpCaption,
531 UINT uType)
532{
533 if (lpText == NULL)
534 lpText = "<null>";
535 if (lpCaption == NULL)
536 lpCaption = "<null>";
537
538 SIZE_T cchText = strlen(lpText) + 1;
539 LPWSTR wszText = (LPWSTR)_alloca(cchText * sizeof(WCHAR));
540 swprintf_s(wszText, cchText, W("%S"), lpText);
541
542 SIZE_T cchCaption = strlen(lpCaption) + 1;
543 LPWSTR wszCaption = (LPWSTR)_alloca(cchCaption * sizeof(WCHAR));
544 swprintf_s(wszCaption, cchCaption, W("%S"), lpCaption);
545
546 return LateboundMessageBoxW(hWnd, wszText, wszCaption, uType);
547}
548
549#if defined(FEATURE_CORESYSTEM) && !defined(CROSSGEN_COMPILE)
550
551#define MessageBoxW LateboundMessageBoxW
552#define MessageBoxA LateboundMessageBoxA
553
554#endif // FEATURE_CORESYSTEM
555
556#endif // __WIN_WRAP_H__
557