DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Header

Mercurial (c68fe15a81fc)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
/* 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 <windows.h>
#include <windows.h>
#include <wincrypt.h>
#include "pathhash.h"

/**
 * Converts a binary sequence into a hex string
 * Converts a binary sequence into a hex string
 *
 * @param hash      The binary data sequence
 * @param hashSize  The size of the binary data sequence
 * @param hexString A buffer to store the hex string, must be of
 *                  size 2 * @hashSize
 *                  size 2 * @hashSize
 */
static void BinaryDataToHexString(const BYTE* hash, DWORD& hashSize,
                                  LPWSTR hexString) {
  WCHAR* p = hexString;
  for (DWORD i = 0; i < hashSize; ++i) {
  for (DWORD i = 0; i < hashSize; ++i) {
    wsprintfW(p, L"%.2x", hash[i]);
    p += 2;
  }
  }
}

/**
 * Calculates an MD5 hash for the given input binary data
 *
 *
 * @param  data     Any sequence of bytes
 * @param  dataSize The number of bytes inside @data
 * @param  hash     Output buffer to store hash, must be freed by the caller
 * @param  hashSize The number of bytes in the output buffer
 * @return TRUE on success
 * @return TRUE on success
 */
static BOOL CalculateMD5(const char* data, DWORD dataSize, BYTE** hash,
                         DWORD& hashSize) {
  HCRYPTPROV hProv = 0;
  HCRYPTHASH hHash = 0;
  HCRYPTHASH hHash = 0;

  if (!CryptAcquireContext(&hProv, nullptr, nullptr, PROV_RSA_FULL,
                           CRYPT_VERIFYCONTEXT)) {
    if ((DWORD)NTE_BAD_KEYSET != GetLastError()) {
      return FALSE;
    }

    // Maybe it doesn't exist, try to create it.
    if (!CryptAcquireContext(&hProv, nullptr, nullptr, PROV_RSA_FULL,
                             CRYPT_VERIFYCONTEXT | CRYPT_NEWKEYSET)) {
      return FALSE;
    }
    }
  }

  if (!CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash)) {
    return FALSE;
  }
  }

  if (!CryptHashData(hHash, reinterpret_cast<const BYTE*>(data), dataSize, 0)) {
    return FALSE;
  }


  DWORD dwCount = sizeof(DWORD);
  if (!CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE*)&hashSize, &dwCount, 0)) {
    return FALSE;
  }


  *hash = new BYTE[hashSize];
  ZeroMemory(*hash, hashSize);
  if (!CryptGetHashParam(hHash, HP_HASHVAL, *hash, &hashSize, 0)) {
  if (!CryptGetHashParam(hHash, HP_HASHVAL, *hash, &hashSize, 0)) {
    return FALSE;
    return FALSE;
  }

  if (hHash) {
    CryptDestroyHash(hHash);
  }


  if (hProv) {
    CryptReleaseContext(hProv, 0);
  }

  return TRUE;
  return TRUE;
}

/**
 * Converts a file path into a unique registry location for cert storage
 * Converts a file path into a unique registry location for cert storage
 *
 * @param  filePath     The input file path to get a registry path from
 * @param  registryPath A buffer to write the registry path to, must
 *                      be of size in WCHARs MAX_PATH + 1
 * @return TRUE if successful
 * @return TRUE if successful
 */
BOOL CalculateRegistryPathFromFilePath(const LPCWSTR filePath,
                                       LPWSTR registryPath) {
  size_t filePathLen = wcslen(filePath);
  if (!filePathLen) {
  if (!filePathLen) {
    return FALSE;
  }

  // If the file path ends in a slash, ignore that character
  if (filePath[filePathLen - 1] == L'\\' || filePath[filePathLen - 1] == L'/') {
  if (filePath[filePathLen - 1] == L'\\' || filePath[filePathLen - 1] == L'/') {
    filePathLen--;
  }

  // Copy in the full path into our own buffer.
  // Copying in the extra slash is OK because we calculate the hash
  // Copying in the extra slash is OK because we calculate the hash
  // based on the filePathLen which excludes the slash.
  // +2 to account for the possibly trailing slash and the null terminator.
  WCHAR* lowercasePath = new WCHAR[filePathLen + 2];
  memset(lowercasePath, 0, (filePathLen + 2) * sizeof(WCHAR));
  wcsncpy(lowercasePath, filePath, filePathLen + 1);
  wcsncpy(lowercasePath, filePath, filePathLen + 1);
  _wcslwr(lowercasePath);

  BYTE* hash;
  DWORD hashSize = 0;
  if (!CalculateMD5(reinterpret_cast<const char*>(lowercasePath),
  if (!CalculateMD5(reinterpret_cast<const char*>(lowercasePath),
                    filePathLen * 2, &hash, hashSize)) {
    delete[] lowercasePath;
    return FALSE;
  }
  delete[] lowercasePath;
  delete[] lowercasePath;

  LPCWSTR baseRegPath =
      L"SOFTWARE\\Mozilla\\"
      L"MaintenanceService\\";
  wcsncpy(registryPath, baseRegPath, MAX_PATH);
  BinaryDataToHexString(hash, hashSize, registryPath + wcslen(baseRegPath));
  delete[] hash;
  delete[] hash;
  return TRUE;
}