/* Copyright (c) Microsoft Corporation */ #include "stdinc.h" #include "sxsp.h" #include "windows.h" #include "ntexapi.h" #define HASH_ALGORITHM HASH_STRING_ALGORITHM_X65599 ULONG SxspSetLastNTError( NTSTATUS Status ); BOOL SxspGetAssemblyRootDirectoryHelper( SIZE_T CchBuffer, WCHAR Buffer[], SIZE_T *CchWritten ) { BOOL fSuccess = FALSE; const PCWSTR NtSystemRoot = USER_SHARED_DATA->NtSystemRoot; const SIZE_T cchSystemRoot = wcslen(NtSystemRoot); #define SLASH_WINSXS_SLASH L"\\WinSxS\\" const SIZE_T cch = cchSystemRoot + (NUMBER_OF(SLASH_WINSXS_SLASH) - 1); if ((CchBuffer == 0) && (CchWritten == NULL)) { ::SxspSetLastNTError(STATUS_INVALID_PARAMETER); goto Exit; } if ((CchBuffer != 0) && (Buffer == NULL)) { ::SxspSetLastNTError(STATUS_INVALID_PARAMETER); goto Exit; } if (cch > CchBuffer) { if (CchWritten != NULL) { *CchWritten = cch; } if (Buffer != NULL) { ::SxspSetLastNTError(STATUS_BUFFER_TOO_SMALL); } else { fSuccess = TRUE; } goto Exit; } memcpy(Buffer, NtSystemRoot, cchSystemRoot * sizeof(WCHAR)); memcpy(Buffer + cchSystemRoot, SLASH_WINSXS_SLASH, sizeof(SLASH_WINSXS_SLASH)); fSuccess = TRUE; Exit: return fSuccess; } ULONG SxspSetLastNTError( NTSTATUS Status ) { ULONG dwErrorCode; dwErrorCode = ::FusionpRtlNtStatusToDosError(Status); ::FusionpSetLastWin32Error(dwErrorCode); return dwErrorCode; } BOOL SxspHashString( PCWSTR String, SIZE_T cch, PULONG HashValue, bool CaseInsensitive ) { UNICODE_STRING s; NTSTATUS Status = STATUS_SUCCESS; s.MaximumLength = static_cast(cch * sizeof(WCHAR)); // check for overflow if (s.MaximumLength != (cch * sizeof(WCHAR))) { ::SxspSetLastNTError(STATUS_NAME_TOO_LONG); return FALSE; } s.Length = s.MaximumLength; s.Buffer = const_cast(String); Status = ::FusionpRtlHashUnicodeString(&s, CaseInsensitive, HASH_ALGORITHM, HashValue); if (!NT_SUCCESS(Status)) ::SxspSetLastNTError(Status); return (NT_SUCCESS(Status)); } ULONG SxspGetHashAlgorithm(VOID) { return HASH_ALGORITHM; } BOOL SxspCreateLocallyUniqueId( OUT PSXSP_LOCALLY_UNIQUE_ID psxsLuid ) { FN_PROLOG_WIN32 static WORD s_wMilliseconds = 0; static ULONG s_ulUniquification = 0; SYSTEMTIME stLocalTime; PARAMETER_CHECK(psxsLuid != NULL); GetSystemTime(&stLocalTime); IFW32FALSE_EXIT(SystemTimeToTzSpecificLocalTime(NULL, &stLocalTime, &psxsLuid->stTimeStamp)); if (psxsLuid->stTimeStamp.wMilliseconds == s_wMilliseconds) { s_ulUniquification = ::SxspInterlockedIncrement(&s_ulUniquification); } else { s_wMilliseconds = psxsLuid->stTimeStamp.wMilliseconds; s_ulUniquification = 0; } psxsLuid->ulUniquifier = s_ulUniquification; FN_EPILOG } #define CHARS_IN_TIMESTAMP (4 + (2*5) + 3 + 10) // 8 * 4 + 4 BOOL SxspFormatLocallyUniqueId( IN const SXSP_LOCALLY_UNIQUE_ID &rsxsLuid, OUT CBaseStringBuffer &rbuffUidBuffer ) { FN_PROLOG_WIN32 if (rbuffUidBuffer.GetBufferCb() < CHARS_IN_TIMESTAMP) { IFW32FALSE_EXIT(rbuffUidBuffer.Win32ResizeBuffer( CHARS_IN_TIMESTAMP, eDoNotPreserveBufferContents)); } else { // // The caller may have previously grown the buffer // larger because they are putting in the // unique id followed by additional text. Don't // change the size on them. // } IFW32FALSE_EXIT(rbuffUidBuffer.Win32Format( L"%04u%02u%02u%02u%02u%02u%03u.%u", rsxsLuid.stTimeStamp.wYear, rsxsLuid.stTimeStamp.wMonth, rsxsLuid.stTimeStamp.wDay, rsxsLuid.stTimeStamp.wHour, rsxsLuid.stTimeStamp.wMinute, rsxsLuid.stTimeStamp.wSecond, rsxsLuid.stTimeStamp.wMilliseconds, rsxsLuid.ulUniquifier)); FN_EPILOG }