#pragma optimize("tgy", on)
#endif
-inline COMNlsHashProvider * GetCurrentNlsHashProvider()
-{
- LIMITED_METHOD_CONTRACT;
- return &COMNlsHashProvider::s_NlsHashProvider;
-}
-
-FCIMPL1(INT32, COMString::Marvin32HashString, StringObject* thisRefUNSAFE) {
- FCALL_CONTRACT;
-
- int iReturnHash = 0;
-
- if (thisRefUNSAFE == NULL) {
- FCThrow(kNullReferenceException);
- }
-
- BEGIN_SO_INTOLERANT_CODE_NOTHROW(GetThread(), FCThrow(kStackOverflowException));
- iReturnHash = GetCurrentNlsHashProvider()->HashString(thisRefUNSAFE->GetBuffer(), thisRefUNSAFE->GetStringLength());
- END_SO_INTOLERANT_CODE;
-
- FC_GC_POLL_RET();
-
- return iReturnHash;
-}
-FCIMPLEND
-
/*===============================IsFastSort===============================
**Action: Call the helper to walk the string and see if we have any high chars.
**Returns: void. The appropriate bits are set on the String.
static FCDECL2(FC_BOOL_RET, FCTryGetTrailByte, StringObject* thisRefUNSAFE, UINT8 *pbData);
static FCDECL2(VOID, FCSetTrailByte, StringObject* thisRefUNSAFE, UINT8 bData);
#endif // FEATURE_COMINTEROP
-
- static FCDECL1(INT32, Marvin32HashString, StringObject* thisRefUNSAFE);
-
};
// Revert to command line compilation flags
#include "nls.h"
#include "nlsinfo.h"
-//
-// Constant Declarations.
-//
-
-#define MAX_STRING_VALUE 512
-
-////////////////////////////////////////////////////////////////////////////
-//
-// InternalGetGlobalizedHashCode
-//
-////////////////////////////////////////////////////////////////////////////
-INT32 QCALLTYPE COMNlsInfo::InternalGetGlobalizedHashCode(INT_PTR handle, LPCWSTR localeName, LPCWSTR string, INT32 length, INT32 dwFlagsIn)
-{
- CONTRACTL
- {
- QCALL_CHECK;
- PRECONDITION(CheckPointer(localeName));
- PRECONDITION(CheckPointer(string, NULL_OK));
- } CONTRACTL_END;
-
- INT32 iReturnHash = 0;
- BEGIN_QCALL;
-
- int byteCount = 0;
-
- //
- // Make sure there is a string.
- //
- if (!string) {
- COMPlusThrowArgumentNull(W("string"),W("ArgumentNull_String"));
- }
-
- DWORD dwFlags = (LCMAP_SORTKEY | dwFlagsIn);
-
- //
- // Caller has already verified that the string is not of zero length
- //
- // Assert if we might hit an AV in LCMapStringEx for the invariant culture.
- _ASSERTE(length > 0 || (dwFlags & LCMAP_LINGUISTIC_CASING) == 0);
- {
- byteCount=::LCMapStringEx(handle != NULL ? NULL : localeName, dwFlags, string, length, NULL, 0, NULL, NULL, (LPARAM) handle);
- }
-
- //A count of 0 indicates that we either had an error or had a zero length string originally.
- if (byteCount==0)
- {
- COMPlusThrow(kArgumentException, W("Arg_MustBeString"));
- }
-
- // We used to use a NewArrayHolder here, but it turns out that hurts our large # process
- // scalability in ASP.Net hosting scenarios, using the quick bytes instead mostly stack
- // allocates and ups throughput by 8% in 100 process case, 5% in 1000 process case
- {
- CQuickBytesSpecifySize<MAX_STRING_VALUE * sizeof(WCHAR)> qbBuffer;
- BYTE* pByte = (BYTE*)qbBuffer.AllocThrows(byteCount);
-
- {
- ::LCMapStringEx(handle != NULL ? NULL : localeName, dwFlags, string, length, (LPWSTR)pByte, byteCount, NULL,NULL, (LPARAM) handle);
- }
-
- iReturnHash = COMNlsHashProvider::s_NlsHashProvider.HashSortKey(pByte, byteCount);
- }
- END_QCALL;
- return(iReturnHash);
-}
-
/**
* This function returns a pointer to this table that we use in System.Globalization.EncodingTable.
* No error checking of any sort is performed. Range checking is entirely the responsibility of the managed
+++ /dev/null
-// 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.
-
-#ifndef MARVIN32_INCLUDED
-#define MARVIN32_INCLUDED
-
-
-#include "common.h"
-#include "windows.h"
-
-//
-// Pointer-const typedefs:
-//
-// These definitions are missing from the standard Windows declarations.
-// Should probably be moved to a central typedef file.
-//
-typedef const BYTE * PCBYTE;
-typedef const USHORT * PCUSHORT;
-typedef const ULONG * PCULONG;
-typedef const ULONGLONG * PCULONGLONG;
-typedef const VOID * PCVOID;
-
-
-
-//
-// MARVIN32
-//
-
-#define SYMCRYPT_MARVIN32_RESULT_SIZE (8)
-#define SYMCRYPT_MARVIN32_SEED_SIZE (8)
-#define SYMCRYPT_MARVIN32_INPUT_BLOCK_SIZE (4)
-
-// These macros only support little-endian machines with unaligned access
-#define LOAD_LSBFIRST16( p ) ( *(USHORT *)(p))
-#define LOAD_LSBFIRST32( p ) ( *(ULONG *)(p))
-#define STORE_LSBFIRST32( p, x ) ( *(ULONG *)(p) = (x) )
-
-// Disable the warning about padding the struct on amd64
-#pragma warning(push)
-#pragma warning(disable:4324)
-
-typedef struct _SYMCRYPT_MARVIN32_EXPANDED_SEED
-{
- ULONG s[2];
-} SYMCRYPT_MARVIN32_EXPANDED_SEED, *PSYMCRYPT_MARVIN32_EXPANDED_SEED;
-
-typedef SYMCRYPT_MARVIN32_EXPANDED_SEED SYMCRYPT_MARVIN32_CHAINING_STATE, *PSYMCRYPT_MARVIN32_CHAINING_STATE;
-typedef const SYMCRYPT_MARVIN32_EXPANDED_SEED * PCSYMCRYPT_MARVIN32_EXPANDED_SEED;
-
-typedef struct _SYMCRYPT_MARVIN32_STATE
-{
- BYTE buffer[8]; // 4 bytes of data, 4 more bytes for final padding
- SYMCRYPT_MARVIN32_CHAINING_STATE chain; // chaining state
- PCSYMCRYPT_MARVIN32_EXPANDED_SEED pSeed; //
- ULONG dataLength; // length of the data processed so far, mod 2^32
-} SYMCRYPT_MARVIN32_STATE, *PSYMCRYPT_MARVIN32_STATE;
-typedef const SYMCRYPT_MARVIN32_STATE *PCSYMCRYPT_MARVIN32_STATE;
-#pragma warning(pop)
-
-//
-// Function declarations
-//
-HRESULT SymCryptMarvin32ExpandSeed(
- __out PSYMCRYPT_MARVIN32_EXPANDED_SEED pExpandedSeed,
- __in_ecount(cbSeed) PCBYTE pbSeed,
- SIZE_T cbSeed);
-
-VOID SymCryptMarvin32Init(_Out_ PSYMCRYPT_MARVIN32_STATE pState,
- _In_ PCSYMCRYPT_MARVIN32_EXPANDED_SEED pExpandedSeed);
-
-VOID SymCryptMarvin32Result(
- _Inout_ PSYMCRYPT_MARVIN32_STATE pState,
- _Out_ PBYTE pbResult);
-
-VOID SymCryptMarvin32Append(_Inout_ SYMCRYPT_MARVIN32_STATE * state,
- _In_reads_bytes_(cbData) PCBYTE pbData,
- SIZE_T cbData);
-
-VOID SymCryptMarvin32(
- __in PCSYMCRYPT_MARVIN32_EXPANDED_SEED pExpandedSeed,
- __in_ecount(cbData) PCBYTE pbData,
- SIZE_T cbData,
- __out_ecount(SYMCRYPT_MARVIN32_RESULT_SIZE) PBYTE pbResult);
-#endif // MARVIN32_INCLUDED
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+using System.Buffers;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
fixed (byte* pSortKey = keyData)
{
- Interop.Globalization.GetSortKey(_sortHandle, source, source.Length, pSortKey, sortKeyLength, options);
+ if (Interop.Globalization.GetSortKey(_sortHandle, source, source.Length, pSortKey, sortKeyLength, options) != sortKeyLength)
+ {
+ throw new ArgumentException(SR.Arg_ExternalException);
+ }
}
}
int sortKeyLength = Interop.Globalization.GetSortKey(_sortHandle, source, source.Length, null, 0, options);
- // As an optimization, for small sort keys we allocate the buffer on the stack.
- if (sortKeyLength <= 256)
+ byte[] borrowedArr = null;
+ Span<byte> span = sortKeyLength <= 512 ?
+ stackalloc byte[512] :
+ (borrowedArr = ArrayPool<byte>.Shared.Rent(sortKeyLength));
+
+ fixed (byte* pSortKey = &MemoryMarshal.GetReference(span))
{
- byte* pSortKey = stackalloc byte[sortKeyLength];
- Interop.Globalization.GetSortKey(_sortHandle, source, source.Length, pSortKey, sortKeyLength, options);
- return InternalHashSortKey(pSortKey, sortKeyLength);
+ if (Interop.Globalization.GetSortKey(_sortHandle, source, source.Length, pSortKey, sortKeyLength, options) != sortKeyLength)
+ {
+ throw new ArgumentException(SR.Arg_ExternalException);
+ }
}
- byte[] sortKey = new byte[sortKeyLength];
+ int hash = Marvin.ComputeHash32(span.Slice(0, sortKeyLength), Marvin.DefaultSeed);
- fixed (byte* pSortKey = sortKey)
+ // Return the borrowed array if necessary.
+ if (borrowedArr != null)
{
- Interop.Globalization.GetSortKey(_sortHandle, source, source.Length, pSortKey, sortKeyLength, options);
- return InternalHashSortKey(pSortKey, sortKeyLength);
+ ArrayPool<byte>.Shared.Return(borrowedArr);
}
- }
- [DllImport(JitHelpers.QCall)]
- private static extern unsafe int InternalHashSortKey(byte* sortKey, int sortKeyLength);
+ return hash;
+ }
private static CompareOptions GetOrdinalCompareOptions(CompareOptions options)
{
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System.Security;
+using System.Buffers;
using System.Diagnostics;
-using System.Runtime.InteropServices;
+using System.Security;
using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
namespace System.Globalization
{
return 0;
}
- int flags = GetNativeCompareFlags(options);
- int tmpHash = 0;
-#if CORECLR
- tmpHash = InternalGetGlobalizedHashCode(_sortHandle, _sortName, source, source.Length, flags);
-#else
+ uint flags = LCMAP_SORTKEY | (uint)GetNativeCompareFlags(options);
+
fixed (char* pSource = source)
{
- if (Interop.Kernel32.LCMapStringEx(_sortHandle != IntPtr.Zero ? null : _sortName,
- LCMAP_HASH | (uint)flags,
+ int sortKeyLength = Interop.Kernel32.LCMapStringEx(_sortHandle != IntPtr.Zero ? null : _sortName,
+ flags,
pSource, source.Length,
- &tmpHash, sizeof(int),
- null, null, _sortHandle) == 0)
+ null, 0,
+ null, null, _sortHandle);
+ if (sortKeyLength == 0)
{
- Environment.FailFast("LCMapStringEx failed!");
+ throw new ArgumentException(SR.Arg_ExternalException);
+ }
+
+ byte[] borrowedArr = null;
+ Span<byte> span = sortKeyLength <= 512 ?
+ stackalloc byte[512] :
+ (borrowedArr = ArrayPool<byte>.Shared.Rent(sortKeyLength));
+
+ fixed (byte* pSortKey = &MemoryMarshal.GetReference(span))
+ {
+ if (Interop.Kernel32.LCMapStringEx(_sortHandle != IntPtr.Zero ? null : _sortName,
+ flags,
+ pSource, source.Length,
+ null, 0,
+ null, null, _sortHandle) != sortKeyLength)
+ {
+ throw new ArgumentException(SR.Arg_ExternalException);
+ }
}
+
+ int hash = Marvin.ComputeHash32(span.Slice(0, sortKeyLength), Marvin.DefaultSeed);
+
+ // Return the borrowed array if necessary.
+ if (borrowedArr != null)
+ {
+ ArrayPool<byte>.Shared.Return(borrowedArr);
+ }
+
+ return hash;
}
-#endif
- return tmpHash;
}
private static unsafe int CompareStringOrdinalIgnoreCase(char* string1, int count1, char* string2, int count2)
}
else
{
+ uint flags = LCMAP_SORTKEY | (uint)GetNativeCompareFlags(options);
+
fixed (char *pSource = source)
{
- int result = Interop.Kernel32.LCMapStringEx(_sortHandle != IntPtr.Zero ? null : _sortName,
- LCMAP_SORTKEY | (uint) GetNativeCompareFlags(options),
+ int sortKeyLength = Interop.Kernel32.LCMapStringEx(_sortHandle != IntPtr.Zero ? null : _sortName,
+ flags,
pSource, source.Length,
null, 0,
null, null, _sortHandle);
- if (result == 0)
+ if (sortKeyLength == 0)
{
- throw new ArgumentException(SR.Argument_InvalidFlag, "source");
+ throw new ArgumentException(SR.Arg_ExternalException);
}
- keyData = new byte[result];
+ keyData = new byte[sortKeyLength];
fixed (byte* pBytes = keyData)
{
- result = Interop.Kernel32.LCMapStringEx(_sortHandle != IntPtr.Zero ? null : _sortName,
- LCMAP_SORTKEY | (uint) GetNativeCompareFlags(options),
+ if (Interop.Kernel32.LCMapStringEx(_sortHandle != IntPtr.Zero ? null : _sortName,
+ flags,
pSource, source.Length,
pBytes, keyData.Length,
- null, null, _sortHandle);
+ null, null, _sortHandle) != sortKeyLength)
+ {
+ throw new ArgumentException(SR.Arg_ExternalException);
+ }
}
}
}
nlsVersion.dwEffectiveId == 0 ? LCID : nlsVersion.dwEffectiveId,
nlsVersion.guidCustomVersion);
}
-
-#if CORECLR
- // Get a locale sensitive sort hash code from native code -- COMNlsInfo::InternalGetGlobalizedHashCode
- [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
- private static extern int InternalGetGlobalizedHashCode(IntPtr handle, string localeName, string source, int length, int dwFlags);
-#endif
}
}
return !String.Equals(a, b);
}
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- private static extern int InternalMarvin32HashString(string s);
-
// Gets a hash code for this string. If strings A and B are such that A.Equals(B), then
// they will return the same hash code.
public override int GetHashCode()
{
- return InternalMarvin32HashString(this);
+ return Marvin.ComputeHash32(ref Unsafe.As<char, byte>(ref _firstChar), _stringLength * 2, Marvin.DefaultSeed);
}
- // Gets a hash code for this string and this comparison. If strings A and B and comparition C are such
+ // Gets a hash code for this string and this comparison. If strings A and B and comparison C are such
// that String.Equals(A, B, C), then they will return the same hash code with this comparison C.
public int GetHashCode(StringComparison comparisonType) => StringComparer.FromComparison(comparisonType).GetHashCode(this);
jithelpers.cpp
managedmdimport.cpp
marshalnative.cpp
- marvin32.cpp
mdaassistants.cpp
methodtablebuilder.cpp
mlinfo.cpp
#include "clrprivtypecachewinrt.h"
-
-#pragma warning(push)
-#pragma warning(disable:4324)
-#include "marvin32.h"
-#pragma warning(pop)
-
// this file handles string conversion errors for itself
#undef MAKE_TRANSLATIONFAILED
}
FCIMPLEND
-
-COMNlsHashProvider COMNlsHashProvider::s_NlsHashProvider;
-
-
-COMNlsHashProvider::COMNlsHashProvider()
-{
- LIMITED_METHOD_CONTRACT;
-
- pEntropy = NULL;
- pDefaultSeed = NULL;
-}
-
-INT32 COMNlsHashProvider::HashString(LPCWSTR szStr, SIZE_T strLen)
-{
- CONTRACTL {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- int marvinResult[SYMCRYPT_MARVIN32_RESULT_SIZE / sizeof(int)];
-
- SymCryptMarvin32(GetDefaultSeed(), (PCBYTE) szStr, strLen * sizeof(WCHAR), (PBYTE) &marvinResult);
-
- return marvinResult[0] ^ marvinResult[1];
-}
-
-
-INT32 COMNlsHashProvider::HashSortKey(PCBYTE pSrc, SIZE_T cbSrc)
-{
- CONTRACTL {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- int marvinResult[SYMCRYPT_MARVIN32_RESULT_SIZE / sizeof(int)];
-
- // Sort Keys are terminated with a null byte which we didn't hash using the old algorithm,
- // so we don't have it with Marvin32 either.
- SymCryptMarvin32(GetDefaultSeed(), pSrc, cbSrc - 1, (PBYTE) &marvinResult);
-
- return marvinResult[0] ^ marvinResult[1];
-}
-
-void COMNlsHashProvider::InitializeDefaultSeed()
-{
- CONTRACTL {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- PCBYTE pEntropy = GetEntropy();
- AllocMemHolder<SYMCRYPT_MARVIN32_EXPANDED_SEED> pSeed(GetAppDomain()->GetLowFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(SYMCRYPT_MARVIN32_EXPANDED_SEED))));
- SymCryptMarvin32ExpandSeed(pSeed, pEntropy, SYMCRYPT_MARVIN32_SEED_SIZE);
-
- if(InterlockedCompareExchangeT(&pDefaultSeed, (PCSYMCRYPT_MARVIN32_EXPANDED_SEED) pSeed, NULL) == NULL)
- {
- pSeed.SuppressRelease();
- }
-}
-
-PCSYMCRYPT_MARVIN32_EXPANDED_SEED COMNlsHashProvider::GetDefaultSeed()
-{
- CONTRACTL {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- if(pDefaultSeed == NULL)
- {
- InitializeDefaultSeed();
- }
-
- return pDefaultSeed;
-}
-
-PCBYTE COMNlsHashProvider::GetEntropy()
-{
- CONTRACTL {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- if(pEntropy == NULL)
- {
- AllocMemHolder<BYTE> pNewEntropy(GetAppDomain()->GetLowFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(SYMCRYPT_MARVIN32_SEED_SIZE))));
-
-#ifdef FEATURE_PAL
- PAL_Random(pNewEntropy, SYMCRYPT_MARVIN32_SEED_SIZE);
-#else
- HCRYPTPROV hCryptProv;
- WszCryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
- CryptGenRandom(hCryptProv, SYMCRYPT_MARVIN32_SEED_SIZE, pNewEntropy);
- CryptReleaseContext(hCryptProv, 0);
-#endif
-
- if(InterlockedCompareExchangeT(&pEntropy, (PBYTE) pNewEntropy, NULL) == NULL)
- {
- pNewEntropy.SuppressRelease();
- }
- }
-
- return (PCBYTE) pEntropy;
-}
-
-#ifdef FEATURE_COREFX_GLOBALIZATION
-INT32 QCALLTYPE CoreFxGlobalization::HashSortKey(PCBYTE pSortKey, INT32 cbSortKey)
-{
- QCALL_CONTRACT;
-
- INT32 retVal = 0;
-
- BEGIN_QCALL;
-
- retVal = COMNlsHashProvider::s_NlsHashProvider.HashSortKey(pSortKey, cbSortKey);
-
- END_QCALL;
-
- return retVal;
-}
-#endif //FEATURE_COREFX_GLOBALIZATION
-
static MethodTable * g_pStreamMT;
static WORD g_slotBeginRead, g_slotEndRead;
static WORD g_slotBeginWrite, g_slotEndWrite;
#include "windows.h"
#undef GetCurrentTime
-
-#pragma warning(push)
-#pragma warning(disable:4324)
-#if !defined(CROSS_COMPILE) && defined(_TARGET_ARM_) && !defined(PLATFORM_UNIX)
-#include "arm_neon.h"
-#endif
-#include "marvin32.h"
-#pragma warning(pop)
-
//
//
// EXCEPTION NATIVE
static FCDECL1(INT32, GetHashCodeOfPtr, LPVOID ptr);
};
-
-typedef const BYTE * PCBYTE;
-
-class COMNlsHashProvider {
-public:
- COMNlsHashProvider();
-
- INT32 HashString(LPCWSTR szStr, SIZE_T strLen);
- INT32 HashSortKey(PCBYTE pSrc, SIZE_T cbSrc);
-
- static COMNlsHashProvider s_NlsHashProvider;
-
-private:
- PBYTE pEntropy;
- PCSYMCRYPT_MARVIN32_EXPANDED_SEED pDefaultSeed;
-
- PCBYTE GetEntropy();
- PCSYMCRYPT_MARVIN32_EXPANDED_SEED GetDefaultSeed();
- void InitializeDefaultSeed();
-};
-
-#ifdef FEATURE_COREFX_GLOBALIZATION
-class CoreFxGlobalization {
-public:
- static INT32 QCALLTYPE HashSortKey(PCBYTE pSortKey, INT32 cbSortKey);
-};
-#endif // FEATURE_COREFX_GLOBALIZATION
-
class StreamNative {
public:
static FCDECL1(FC_BOOL_RET, HasOverriddenBeginEndRead, Object *stream);
FCFuncElement("SetTrailByte", COMString::FCSetTrailByte)
FCFuncElement("TryGetTrailByte", COMString::FCTryGetTrailByte)
#endif // FEATURE_COMINTEROP
- FCFuncElement("InternalMarvin32HashString", COMString::Marvin32HashString)
FCFuncEnd()
FCFuncStart(gStringBufferFuncs)
FCFuncEnd()
#if !defined(FEATURE_COREFX_GLOBALIZATION)
-FCFuncStart(gCompareInfoFuncs)
- QCFuncElement("InternalGetGlobalizedHashCode", COMNlsInfo::InternalGetGlobalizedHashCode)
-FCFuncEnd()
-
FCFuncStart(gEncodingTableFuncs)
FCFuncElement("GetNumEncodingItems", COMNlsInfo::nativeGetNumEncodingItems)
FCFuncElement("GetEncodingData", COMNlsInfo::nativeGetEncodingTableDataPointer)
FCFuncEnd()
#endif // !defined(FEATURE_COREFX_GLOBALIZATION)
-#ifdef FEATURE_COREFX_GLOBALIZATION
-FCFuncStart(gCompareInfoFuncs)
- QCFuncElement("InternalHashSortKey", CoreFxGlobalization::HashSortKey)
-FCFuncEnd()
-#endif
-
FCFuncStart(gArrayFuncs)
FCFuncElement("get_Rank", ArrayNative::GetRank)
FCFuncElement("GetLowerBound", ArrayNative::GetLowerBound)
FCClassElement("AssemblyName", "System.Reflection", gAssemblyNameFuncs)
FCClassElement("Buffer", "System", gBufferFuncs)
FCClassElement("CLRConfig", "System", gClrConfig)
-FCClassElement("CompareInfo", "System.Globalization", gCompareInfoFuncs)
FCClassElement("CompatibilitySwitch", "System.Runtime.Versioning", gCompatibilitySwitchFuncs)
FCClassElement("CriticalHandle", "System.Runtime.InteropServices", gCriticalHandleFuncs)
FCClassElement("Currency", "System", gCurrencyFuncs)
+++ /dev/null
-// 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.
-
-//
-// This module contains the routines to implement the Marvin32 checksum function
-//
-//
-
-#include "common.h"
-#include "marvin32.h"
-
-//
-// See the symcrypt.h file for documentation on what the various functions do.
-//
-
-//
-// Round rotation amounts. This array is optimized away by the compiler
-// as we inline all our rotations.
-//
-static const int rotate[4] = {
- 20, 9, 27, 19,
-};
-
-
-#define ROL32( x, n ) _rotl( (x), (n) )
-#define ROR32( x, n ) _rotr( (x), (n) )
-
-#define BLOCK( a, b ) \
-{\
- b ^= a; a = ROL32( a, rotate[0] );\
- a += b; b = ROL32( b, rotate[1] );\
- b ^= a; a = ROL32( a, rotate[2] );\
- a += b; b = ROL32( b, rotate[3] );\
-}
-
-
-
-HRESULT
-SymCryptMarvin32ExpandSeed(
- __out PSYMCRYPT_MARVIN32_EXPANDED_SEED pExpandedSeed,
- __in_ecount(cbSeed) PCBYTE pbSeed,
- SIZE_T cbSeed )
-{
- HRESULT retVal = S_OK;
-
- if( cbSeed != SYMCRYPT_MARVIN32_SEED_SIZE )
- {
- retVal =E_INVALIDARG;
- goto cleanup;
- }
- pExpandedSeed->s[0] = LOAD_LSBFIRST32( pbSeed );
- pExpandedSeed->s[1] = LOAD_LSBFIRST32( pbSeed + 4 );
-
-cleanup:
- return retVal;
-}
-
-
-VOID
-SymCryptMarvin32Init( _Out_ PSYMCRYPT_MARVIN32_STATE pState,
- _In_ PCSYMCRYPT_MARVIN32_EXPANDED_SEED pExpandedSeed)
-{
- pState->chain = *pExpandedSeed;
- pState->dataLength = 0;
- pState->pSeed = pExpandedSeed;
-
- *(ULONG *) &pState->buffer[4] = 0; // wipe the last 4 bytes of the buffer.
-}
-
-VOID
-SymCryptMarvin32AppendBlocks(
- _Inout_ PSYMCRYPT_MARVIN32_CHAINING_STATE pChain,
- _In_reads_( cbData ) PCBYTE pbData,
- SIZE_T cbData )
-{
- ULONG s0 = pChain->s[0];
- ULONG s1 = pChain->s[1];
-
- SIZE_T bytesInFirstBlock = cbData & 0xc; // 0, 4, 8, or 12
-
- pbData += bytesInFirstBlock;
- cbData -= bytesInFirstBlock;
-
- switch( bytesInFirstBlock )
- {
- case 0: // This handles the cbData == 0 case too
- while( cbData > 0 )
- {
- pbData += 16;
- cbData -= 16;
-
- s0 += LOAD_LSBFIRST32( pbData - 16 );
- BLOCK( s0, s1 );
- case 12:
- s0 += LOAD_LSBFIRST32( pbData - 12 );
- BLOCK( s0, s1 );
- case 8:
- s0 += LOAD_LSBFIRST32( pbData - 8 );
- BLOCK( s0, s1 );
- case 4:
- s0 += LOAD_LSBFIRST32( pbData - 4 );
- BLOCK( s0, s1 );
- }
- }
-
- pChain->s[0] = s0;
- pChain->s[1] = s1;
-}
-
-VOID
-SymCryptMarvin32Append(_Inout_ SYMCRYPT_MARVIN32_STATE * state,
-_In_reads_bytes_(cbData) PCBYTE pbData,
-SIZE_T cbData)
-{
- ULONG bytesInBuffer = state->dataLength;
-
- state->dataLength += (ULONG)cbData; // We only keep track of the last 2 bits...
-
- //
- // Truncate bytesInBuffer so that we never have an integer overflow.
- //
- bytesInBuffer &= SYMCRYPT_MARVIN32_INPUT_BLOCK_SIZE - 1;
-
- //
- // If previous data in buffer, buffer new input and transform if possible.
- //
- if (bytesInBuffer > 0)
- {
- SIZE_T freeInBuffer = SYMCRYPT_MARVIN32_INPUT_BLOCK_SIZE - bytesInBuffer;
- if (cbData < freeInBuffer)
- {
- //
- // All the data will fit in the buffer.
- // We don't do anything here.
- // As cbData < INPUT_BLOCK_SIZE the bulk data processing is skipped,
- // and the data will be copied to the buffer at the end
- // of this code.
- }
- else {
- //
- // Enough data to fill the whole buffer & process it
- //
- memcpy(&state->buffer[bytesInBuffer], pbData, freeInBuffer);
- pbData += freeInBuffer;
- cbData -= freeInBuffer;
- SymCryptMarvin32AppendBlocks(&state->chain, state->buffer, SYMCRYPT_MARVIN32_INPUT_BLOCK_SIZE);
-
- //
- // Set bytesInBuffer to zero to ensure that the trailing data in the
- // buffer will be copied to the right location of the buffer below.
- //
- bytesInBuffer = 0;
- }
- }
-
- //
- // Internal buffer is empty; process all remaining whole blocks in the input
- //
- if (cbData >= SYMCRYPT_MARVIN32_INPUT_BLOCK_SIZE)
- {
- SIZE_T cbDataRoundedDown = cbData & ~(SIZE_T)(SYMCRYPT_MARVIN32_INPUT_BLOCK_SIZE - 1);
- SymCryptMarvin32AppendBlocks(&state->chain, pbData, cbDataRoundedDown);
- pbData += cbDataRoundedDown;
- cbData -= cbDataRoundedDown;
- }
-
- //
- // buffer remaining input if necessary.
- //
- if (cbData > 0)
- {
- memcpy(&state->buffer[bytesInBuffer], pbData, cbData);
- }
-
-}
-
-VOID
-SymCryptMarvin32Result(
- _Inout_ PSYMCRYPT_MARVIN32_STATE pState,
- _Out_writes_( SYMCRYPT_MARVIN32_RESULT_SIZE ) PBYTE pbResult )
-{
- SIZE_T bytesInBuffer = ( pState->dataLength) & 0x3;
-
- //
- // Wipe four bytes in the buffer.
- // Doing this first ensures that this write is aligned when the input was of
- // length 0 mod 4.
- // The buffer is 8 bytes long, so we never overwrite anything else.
- //
- *(ULONG *) &pState->buffer[bytesInBuffer] = 0;
-
- //
- // The buffer is never completely full, so we can always put the first
- // padding byte in.
- //
- pState->buffer[bytesInBuffer++] = 0x80;
-
- //
- // Process the final block
- //
- SymCryptMarvin32AppendBlocks( &pState->chain, pState->buffer, 8 );
-
- STORE_LSBFIRST32( pbResult , pState->chain.s[0] );
- STORE_LSBFIRST32( pbResult + 4, pState->chain.s[1] );
-
- //
- // Wipe only those things that we need to wipe.
- //
-
- *(ULONG *) &pState->buffer[0] = 0;
- pState->dataLength = 0;
-
- pState->chain = *pState->pSeed;
-}
-
-
-VOID
-SymCryptMarvin32(
- __in PCSYMCRYPT_MARVIN32_EXPANDED_SEED pExpandedSeed,
- __in_ecount(cbData) PCBYTE pbData,
- SIZE_T cbData,
- __out_ecount(SYMCRYPT_MARVIN32_RESULT_SIZE) PBYTE pbResult)
-//
-// To reduce the per-computation overhead, we have a dedicated code here instead of the whole Init/Append/Result stuff.
-//
-{
- ULONG tmp;
-
- ULONG s0 = pExpandedSeed->s[0];
- ULONG s1 = pExpandedSeed->s[1];
-
- while( cbData > 7 )
- {
- s0 += LOAD_LSBFIRST32( pbData );
- BLOCK( s0, s1 );
- s0 += LOAD_LSBFIRST32( pbData + 4 );
- BLOCK( s0, s1 );
- pbData += 8;
- cbData -= 8;
- }
-
- switch( cbData )
- {
- default:
- case 4: s0 += LOAD_LSBFIRST32( pbData ); BLOCK( s0, s1 ); pbData += 4;
- case 0: tmp = 0x80; break;
-
- case 5: s0 += LOAD_LSBFIRST32( pbData ); BLOCK( s0, s1 ); pbData += 4;
- case 1: tmp = 0x8000 | pbData[0]; break;
-
- case 6: s0 += LOAD_LSBFIRST32( pbData ); BLOCK( s0, s1 ); pbData += 4;
- case 2: tmp = 0x800000 | LOAD_LSBFIRST16( pbData ); break;
-
- case 7: s0 += LOAD_LSBFIRST32( pbData ); BLOCK( s0, s1 ); pbData += 4;
- case 3: tmp = LOAD_LSBFIRST16( pbData ) | (pbData[2] << 16) | 0x80000000; break;
- }
- s0 += tmp;
-
-
- BLOCK( s0, s1 );
- BLOCK( s0, s1 );
-
- STORE_LSBFIRST32( pbResult , s0 );
- STORE_LSBFIRST32( pbResult + 4, s1 );
-}