Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set ExactSpelling=true on P/Invokes in System.Private.CoreLib that already specify the unicode W suffix #36257

Merged
merged 2 commits into from
May 13, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 35 additions & 30 deletions src/coreclr/src/vm/method.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5307,6 +5307,23 @@ FARPROC NDirectMethodDesc::FindEntryPointWithMangling(NATIVE_LIBRARY_HANDLE hMod

return pFunc;
}

FARPROC NDirectMethodDesc::FindEntryPointWithSuffix(NATIVE_LIBRARY_HANDLE hMod, PTR_CUTF8 entryPointName, char suffix) const
{
// Allocate space for a copy of the entry point name.
DWORD entryPointWithSuffixLen = (DWORD)(strlen(entryPointName) + 1); // +1 for charset decorations
int dstbufsize = (int)(sizeof(char) * (entryPointWithSuffixLen + 1)); // +1 for the null terminator
LPSTR entryPointWithSuffix = ((LPSTR)_alloca(dstbufsize));

// Copy the name so we can mangle it.
strcpy_s(entryPointWithSuffix, dstbufsize, entryPointName);
entryPointWithSuffix[entryPointWithSuffixLen] = '\0'; // Null terminator
entryPointWithSuffix[entryPointWithSuffixLen - 1] = suffix; // Charset suffix

// Look for entry point with the suffix based on charset
return FindEntryPointWithMangling(hMod, entryPointWithSuffix);
}

#endif

//*******************************************************************************
Expand All @@ -5332,39 +5349,27 @@ LPVOID NDirectMethodDesc::FindEntryPoint(NATIVE_LIBRARY_HANDLE hMod) const
return reinterpret_cast<LPVOID>(GetProcAddress(hMod, (LPCSTR)(size_t)((UINT16)ordinal)));
}

// Just look for the user-provided name without charset suffixes.
// If it is unicode fcn, we are going
// to need to check for the 'W' API because it takes precedence over the
// unmangled one (on NT some APIs have unmangled ANSI exports).
FARPROC pFunc = FindEntryPointWithMangling(hMod, funcName);
if ((pFunc != NULL && IsNativeAnsi()) || IsNativeNoMangled())
FARPROC pFunc = NULL;
if (IsNativeNoMangled())
{
return reinterpret_cast<LPVOID>(pFunc);
// Look for the user-provided entry point name only
pFunc = FindEntryPointWithMangling(hMod, funcName);
}

DWORD probedEntrypointNameLength = (DWORD)(strlen(funcName) + 1); // +1 for charset decorations

// Allocate space for a copy of the entry point name.
int dstbufsize = (int)(sizeof(char) * (probedEntrypointNameLength + 1)); // +1 for the null terminator

LPSTR szProbedEntrypointName = ((LPSTR)_alloca(dstbufsize));

// Copy the name so we can mangle it.
strcpy_s(szProbedEntrypointName, dstbufsize, funcName);
szProbedEntrypointName[probedEntrypointNameLength] = '\0'; // Add an extra '\0'.

if(!IsNativeNoMangled())
jkotas marked this conversation as resolved.
Show resolved Hide resolved
else if (IsNativeAnsi())
{
szProbedEntrypointName[probedEntrypointNameLength - 1] = IsNativeAnsi() ? 'A' : 'W';

FARPROC pProbedFunc = FindEntryPointWithMangling(hMod, szProbedEntrypointName);

if(pProbedFunc != NULL)
{
pFunc = pProbedFunc;
}

probedEntrypointNameLength++;
// For ANSI, look for the user-provided entry point name first.
// If that does not exist, try the charset suffix.
pFunc = FindEntryPointWithMangling(hMod, funcName);
if (pFunc == NULL)
pFunc = FindEntryPointWithSuffix(hMod, funcName, 'A');
}
else
{
// For Unicode, look for the entry point name with the charset suffix first.
// The 'W' API takes precedence over the undecorated one.
pFunc = FindEntryPointWithSuffix(hMod, funcName, 'W');
if (pFunc == NULL)
pFunc = FindEntryPointWithMangling(hMod, funcName);
}

return reinterpret_cast<LPVOID>(pFunc);
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/src/vm/method.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3150,6 +3150,7 @@ class NDirectMethodDesc : public MethodDesc
#ifdef TARGET_WINDOWS
private:
FARPROC FindEntryPointWithMangling(NATIVE_LIBRARY_HANDLE mod, PTR_CUTF8 entryPointName) const;
FARPROC FindEntryPointWithSuffix(NATIVE_LIBRARY_HANDLE mod, PTR_CUTF8 entryPointName, char suffix) const;
#endif
public:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ internal static partial class Advapi32
{
// Note: RegCreateKeyEx won't set the last error on failure - it returns
// an error code if it fails.
[DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegCreateKeyExW")]
[DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegCreateKeyExW", ExactSpelling = true)]
internal static extern int RegCreateKeyEx(
Copy link
Member

@stephentoub stephentoub May 12, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not for this PR, but we might want to subsequently rename all of the methods to use the exact entrypoint name; doing that would make it more clear at the call site exactly which method was being used, would remove the need to specify EntryPoint as well, would increase our consistency (sometimes we use W in the name and sometimes we don't), and also fits with the goal of minimizing magic. Not a big deal, though.

SafeRegistryHandle hKey,
string lpSubKey,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ internal static partial class Interop
{
internal static partial class Advapi32
{
[DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegDeleteKeyExW")]
[DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegDeleteKeyExW", ExactSpelling = true)]
internal static extern int RegDeleteKeyEx(SafeRegistryHandle hKey, string lpSubKey, int samDesired, int Reserved);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ internal static partial class Interop
{
internal static partial class Advapi32
{
[DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegDeleteValueW")]
[DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegDeleteValueW", ExactSpelling = true)]
internal static extern int RegDeleteValue(SafeRegistryHandle hKey, string? lpValueName);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ internal static partial class Interop
{
internal static partial class Advapi32
{
[DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegEnumKeyExW")]
[DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegEnumKeyExW", ExactSpelling = true)]
internal static extern unsafe int RegEnumKeyEx(
SafeRegistryHandle hKey,
int dwIndex,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ internal static partial class Interop
{
internal static partial class Advapi32
{
[DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegEnumValueW")]
[DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegEnumValueW", ExactSpelling = true)]
internal static extern unsafe int RegEnumValue(
SafeRegistryHandle hKey,
int dwIndex,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ internal static partial class Interop
{
internal static partial class Advapi32
{
[DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegOpenKeyExW")]
[DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegOpenKeyExW", ExactSpelling = true)]
internal static extern int RegOpenKeyEx(
SafeRegistryHandle hKey,
string? lpSubKey,
Expand All @@ -24,7 +24,7 @@ internal static extern int RegOpenKeyEx(
out SafeRegistryHandle hkResult);


[DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegOpenKeyExW")]
[DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegOpenKeyExW", ExactSpelling = true)]
internal static extern int RegOpenKeyEx(
IntPtr hKey,
string? lpSubKey,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ internal static partial class Interop
{
internal static partial class Advapi32
{
[DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegQueryValueExW")]
[DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegQueryValueExW", ExactSpelling = true)]
internal static extern int RegQueryValueEx(
SafeRegistryHandle hKey,
string? lpValueName,
Expand All @@ -23,7 +23,7 @@ internal static extern int RegQueryValueEx(
[Out] byte[]? lpData,
ref int lpcbData);

[DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegQueryValueExW")]
[DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegQueryValueExW", ExactSpelling = true)]
internal static extern int RegQueryValueEx(
SafeRegistryHandle hKey,
string? lpValueName,
Expand All @@ -32,7 +32,7 @@ internal static extern int RegQueryValueEx(
ref int lpData,
ref int lpcbData);

[DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegQueryValueExW")]
[DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegQueryValueExW", ExactSpelling = true)]
internal static extern int RegQueryValueEx(
SafeRegistryHandle hKey,
string? lpValueName,
Expand All @@ -41,7 +41,7 @@ internal static extern int RegQueryValueEx(
ref long lpData,
ref int lpcbData);

[DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegQueryValueExW")]
[DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegQueryValueExW", ExactSpelling = true)]
internal static extern int RegQueryValueEx(
SafeRegistryHandle hKey,
string? lpValueName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ internal static partial class Interop
{
internal static partial class Advapi32
{
[DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegSetValueExW")]
[DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegSetValueExW", ExactSpelling = true)]
internal static extern int RegSetValueEx(
SafeRegistryHandle hKey,
string? lpValueName,
Expand All @@ -23,7 +23,7 @@ internal static extern int RegSetValueEx(
byte[]? lpData,
int cbData);

[DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegSetValueExW")]
[DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegSetValueExW", ExactSpelling = true)]
internal static extern int RegSetValueEx(
SafeRegistryHandle hKey,
string? lpValueName,
Expand All @@ -32,7 +32,7 @@ internal static extern int RegSetValueEx(
char[]? lpData,
int cbData);

[DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegSetValueExW")]
[DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegSetValueExW", ExactSpelling = true)]
internal static extern int RegSetValueEx(
SafeRegistryHandle hKey,
string? lpValueName,
Expand All @@ -41,7 +41,7 @@ internal static extern int RegSetValueEx(
ref int lpData,
int cbData);

[DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegSetValueExW")]
[DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegSetValueExW", ExactSpelling = true)]
internal static extern int RegSetValueEx(
SafeRegistryHandle hKey,
string? lpValueName,
Expand All @@ -50,7 +50,7 @@ internal static extern int RegSetValueEx(
ref long lpData,
int cbData);

[DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegSetValueExW")]
[DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegSetValueExW", ExactSpelling = true)]
internal static extern int RegSetValueEx(
SafeRegistryHandle hKey,
string? lpValueName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ internal static partial class Kernel32
[DllImport(Libraries.Kernel32, SetLastError = true)]
internal static extern bool ResetEvent(SafeWaitHandle handle);

[DllImport(Libraries.Kernel32, EntryPoint = "CreateEventExW", SetLastError = true, CharSet = CharSet.Unicode)]
[DllImport(Libraries.Kernel32, EntryPoint = "CreateEventExW", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true)]
internal static extern SafeWaitHandle CreateEventEx(IntPtr lpSecurityAttributes, string? name, uint flags, uint desiredAccess);

[DllImport(Libraries.Kernel32, EntryPoint = "OpenEventW", SetLastError = true, CharSet = CharSet.Unicode)]
[DllImport(Libraries.Kernel32, EntryPoint = "OpenEventW", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true)]
internal static extern SafeWaitHandle OpenEvent(uint desiredAccess, bool inheritHandle, string name);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ internal static partial class Interop
{
internal static partial class Kernel32
{
[DllImport(Libraries.Kernel32, EntryPoint = "ExpandEnvironmentStringsW", CharSet = CharSet.Unicode, SetLastError = true)]
[DllImport(Libraries.Kernel32, EntryPoint = "ExpandEnvironmentStringsW", CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)]
internal static extern uint ExpandEnvironmentStrings(string lpSrc, ref char lpDst, uint nSize);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ internal static partial class Kernel32
/// <summary>
/// WARNING: This method does not implicitly handle long paths. Use FindFirstFile.
/// </summary>
[DllImport(Libraries.Kernel32, EntryPoint = "FindFirstFileExW", SetLastError = true, CharSet = CharSet.Unicode)]
[DllImport(Libraries.Kernel32, EntryPoint = "FindFirstFileExW", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true)]
private static extern SafeFindHandle FindFirstFileExPrivate(string lpFileName, FINDEX_INFO_LEVELS fInfoLevelId, ref WIN32_FIND_DATA lpFindFileData, FINDEX_SEARCH_OPS fSearchOp, IntPtr lpSearchFilter, int dwAdditionalFlags);

internal static SafeFindHandle FindFirstFile(string fileName, ref WIN32_FIND_DATA data)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ internal static partial class Kernel32
private const int FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100;
private const int ERROR_INSUFFICIENT_BUFFER = 0x7A;

[DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, EntryPoint = "FormatMessageW", SetLastError = true, BestFitMapping = true)]
[DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, EntryPoint = "FormatMessageW", SetLastError = true, BestFitMapping = true, ExactSpelling = true)]
private static extern unsafe int FormatMessage(
int dwFlags,
IntPtr lpSource,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ internal static partial class Interop
{
internal static partial class Kernel32
{
[DllImport(Libraries.Kernel32, EntryPoint = "FreeEnvironmentStringsW", SetLastError = true, CharSet = CharSet.Unicode, BestFitMapping = false)]
[DllImport(Libraries.Kernel32, EntryPoint = "FreeEnvironmentStringsW", SetLastError = true, CharSet = CharSet.Unicode, BestFitMapping = false, ExactSpelling = true)]
internal static extern unsafe bool FreeEnvironmentStrings(char* lpszEnvironmentBlock);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ internal static partial class Interop
{
internal static partial class Kernel32
{
[DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, EntryPoint = "GetComputerNameW")]
[DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, EntryPoint = "GetComputerNameW", ExactSpelling = true)]
private static extern unsafe int GetComputerName(ref char lpBuffer, ref uint nSize);

// maximum length of the NETBIOS name (not including NULL)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ internal static partial class Interop
{
internal static partial class Kernel32
{
[DllImport(Libraries.Kernel32, EntryPoint = "GetCurrentDirectoryW", SetLastError = true, CharSet = CharSet.Unicode, BestFitMapping = false)]
[DllImport(Libraries.Kernel32, EntryPoint = "GetCurrentDirectoryW", SetLastError = true, CharSet = CharSet.Unicode, BestFitMapping = false, ExactSpelling = true)]
internal static extern uint GetCurrentDirectory(uint nBufferLength, ref char lpBuffer);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ internal static partial class Interop
{
internal static partial class Kernel32
{
[DllImport(Libraries.Kernel32, EntryPoint = "GetEnvironmentStringsW", SetLastError = true, CharSet = CharSet.Unicode, BestFitMapping = false)]
[DllImport(Libraries.Kernel32, EntryPoint = "GetEnvironmentStringsW", SetLastError = true, CharSet = CharSet.Unicode, BestFitMapping = false, ExactSpelling = true)]
internal static extern unsafe char* GetEnvironmentStrings();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ internal static unsafe int GetEnvironmentVariable(string lpName, Span<char> buff
}
}

[DllImport(Libraries.Kernel32, EntryPoint = "GetEnvironmentVariableW", SetLastError = true, CharSet = CharSet.Unicode)]
[DllImport(Libraries.Kernel32, EntryPoint = "GetEnvironmentVariableW", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true)]
private static extern unsafe int GetEnvironmentVariable(string lpName, char* lpBuffer, int nSize);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ internal static partial class Kernel32
/// <summary>
/// WARNING: This method does not implicitly handle long paths. Use GetFileAttributesEx.
/// </summary>
[DllImport(Libraries.Kernel32, EntryPoint = "GetFileAttributesExW", SetLastError = true, CharSet = CharSet.Unicode)]
[DllImport(Libraries.Kernel32, EntryPoint = "GetFileAttributesExW", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true)]
private static extern bool GetFileAttributesExPrivate(string? name, GET_FILEEX_INFO_LEVELS fileInfoLevel, ref WIN32_FILE_ATTRIBUTE_DATA lpFileInformation);

internal static bool GetFileAttributesEx(string? name, GET_FILEEX_INFO_LEVELS fileInfoLevel, ref WIN32_FILE_ATTRIBUTE_DATA lpFileInformation)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ internal static partial class Interop
{
internal static partial class Kernel32
{
[DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true)]
[DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)]
internal static extern uint GetSystemDirectoryW(ref char lpBuffer, uint uSize);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ internal static partial class Interop
{
internal static partial class Kernel32
{
[DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true, BestFitMapping = false)]
[DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true, BestFitMapping = false, ExactSpelling = true)]
internal static extern uint GetTempFileNameW(ref char lpPathName, string lpPrefixString, uint uUnique, ref char lpTempFileName);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ internal static partial class Interop
{
internal static partial class Kernel32
{
[DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, BestFitMapping = false)]
[DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, BestFitMapping = false, ExactSpelling = true)]
internal static extern uint GetTempPathW(int bufferLen, ref char buffer);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ internal static partial class Kernel32
internal const int LOAD_LIBRARY_AS_DATAFILE = 0x00000002;
internal const int LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800;

[DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, EntryPoint = "LoadLibraryExW", SetLastError = true)]
[DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, EntryPoint = "LoadLibraryExW", SetLastError = true, ExactSpelling = true)]
internal static extern IntPtr LoadLibraryEx(string libFilename, IntPtr reserved, int flags);
}
}
Loading