/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <optional>
#include <rpc.h>
#include <string>
#include <windows.h>

static const size_t BUFFER_LEN = MAX_PATH + 1;

/**
 * Create a unique tempfile name in a temp directory appropriate
 * for this user.
 * @return The temp filename, or std::nullopt on failure
 */
std::optional<std::wstring> get_tempfile_name() {
  wchar_t pathBuffer[BUFFER_LEN];
  wchar_t filenameBuffer[BUFFER_LEN];
  UUID uuid;
  DWORD pathLen = GetTempPathW(BUFFER_LEN, pathBuffer);
  if (pathLen > BUFFER_LEN || pathLen == 0) {
    // Error getting path
    return std::nullopt;
  }
  // Use a UUID as a convenient source of random bits
  RPC_STATUS uuidStatus = UuidCreate(&uuid);
  if (uuidStatus != RPC_S_OK && uuidStatus != RPC_S_UUID_LOCAL_ONLY) {
    // Error creating a unique UUID for the filename
    return std::nullopt;
  }

  // Since we're only using the UUID data structure as a source of random bits,
  // rather than as something that we need to serialize and deserialize as a
  // UUID, it's best not to leak the internal implementation details out of the
  // abstraction of the filename.
  // With that in mind, the following code converts the UUID data structure into
  // a sequence of hexadecimal digits.
  ULONG data4msb =
      *((ULONG*)uuid.Data4);  // First 4 bytes of the 8-byte Data4 char array
  ULONG data4lsb =
      *((ULONG*)(uuid.Data4 +
                 4));  // Second 4 bytes of the 8-byte Data4 char array
  if (swprintf_s(filenameBuffer, BUFFER_LEN, L"%sfx%X%X%X%X%X.exe", pathBuffer,
                 uuid.Data1, uuid.Data2, uuid.Data3, data4msb, data4lsb) < 0) {
    return std::nullopt;
  }

  return std::wstring(filenameBuffer);
}
