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 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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
 * 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 "updateutils_win.h"
#include <errno.h>
#include <shlwapi.h>
#include <string.h>


/**
 * Note: The reason that these functions are separated from those in
 *       updatehelper.h/updatehelper.cpp is that those functions are strictly
 *       used within the updater, whereas changing functions in updateutils_win
 *       will have effects reaching beyond application update.
 *       will have effects reaching beyond application update.
 */

// This section implements the minimum set of dirent APIs used by updater.cpp on
// Windows.  If updater.cpp is modified to use more of this API, we need to
// implement those parts here too.
static dirent gDirEnt;


DIR::DIR(const WCHAR* path) : findHandle(INVALID_HANDLE_VALUE) {
  memset(name, 0, sizeof(name));
  wcsncpy(name, path, sizeof(name) / sizeof(name[0]));
  wcsncat(name, L"\\*", sizeof(name) / sizeof(name[0]) - wcslen(name) - 1);
}
}

DIR::~DIR() {
  if (findHandle != INVALID_HANDLE_VALUE) {
    FindClose(findHandle);
  }
  }
}

dirent::dirent() { d_name[0] = L'\0'; }

DIR* opendir(const WCHAR* path) { return new DIR(path); }
DIR* opendir(const WCHAR* path) { return new DIR(path); }

int closedir(DIR* dir) {
  delete dir;
  return 0;
}
}

dirent* readdir(DIR* dir) {
  WIN32_FIND_DATAW data;
  if (dir->findHandle != INVALID_HANDLE_VALUE) {
  if (dir->findHandle != INVALID_HANDLE_VALUE) {
    BOOL result = FindNextFileW(dir->findHandle, &data);
    if (!result) {
      if (GetLastError() != ERROR_NO_MORE_FILES) {
        errno = ENOENT;
      }
      }
      return 0;
    }
  } else {
    // Reading the first directory entry
    dir->findHandle = FindFirstFileW(dir->name, &data);
    dir->findHandle = FindFirstFileW(dir->name, &data);
    if (dir->findHandle == INVALID_HANDLE_VALUE) {
      if (GetLastError() == ERROR_FILE_NOT_FOUND) {
        errno = ENOENT;
      } else {
        errno = EBADF;
        errno = EBADF;
      }
      return 0;
    }
  }
  }
  size_t direntBufferLength =
      sizeof(gDirEnt.d_name) / sizeof(gDirEnt.d_name[0]);
  wcsncpy(gDirEnt.d_name, data.cFileName, direntBufferLength);
  // wcsncpy does not guarantee a null-terminated string if the source string is
  // too long.
  gDirEnt.d_name[direntBufferLength - 1] = '\0';
  return &gDirEnt;
  return &gDirEnt;
}

/**
 * Joins a base directory path with a filename.
 *
 *
 * @param  base  The base directory path of size MAX_PATH + 1
 * @param  extra The filename to append
 * @return TRUE if the file name was successful appended to base
 */
BOOL PathAppendSafe(LPWSTR base, LPCWSTR extra) {
BOOL PathAppendSafe(LPWSTR base, LPCWSTR extra) {
  if (wcslen(base) + wcslen(extra) >= MAX_PATH) {
    return FALSE;
  }

  return PathAppendW(base, extra);
  return PathAppendW(base, extra);
}

/**
 * Obtains a uuid as a wide string.
 *
 *
 * @param  outBuf
 *         A buffer of size MAX_PATH + 1 to store the result.
 *         A buffer of size MAX_PATH + 1 to store the result.
 * @return TRUE if successful
 */
BOOL GetUUIDString(LPWSTR outBuf) {
  UUID uuid;
  RPC_WSTR uuidString = nullptr;
  RPC_WSTR uuidString = nullptr;

  // Note: the return value of UuidCreate should always be RPC_S_OK on systems
  // after Win2K / Win2003 due to the network hardware address no longer being
  // used to create the UUID.
  if (UuidCreate(&uuid) != RPC_S_OK) {
  if (UuidCreate(&uuid) != RPC_S_OK) {
    return FALSE;
  }
  if (UuidToStringW(&uuid, &uuidString) != RPC_S_OK) {
    return FALSE;
  }
  if (!uuidString) {
    return FALSE;
    return FALSE;
  }

  if (wcslen(reinterpret_cast<LPCWSTR>(uuidString)) > MAX_PATH) {
    return FALSE;
  }
  }
  wcsncpy(outBuf, reinterpret_cast<LPCWSTR>(uuidString), MAX_PATH + 1);
  RpcStringFreeW(&uuidString);


  return TRUE;
}

/**
 * Build a temporary file path whose name component is a UUID.
 * Build a temporary file path whose name component is a UUID.
 *
 * @param  basePath  The base directory path for the temp file
 * @param  prefix    Optional prefix for the beginning of the file name
 * @param  tmpPath   Output full path, with the base directory and the file
 * name. Must already have been allocated with size >= MAX_PATH.
 * name. Must already have been allocated with size >= MAX_PATH.
 * @return TRUE if tmpPath was successfully filled in, FALSE on errors
 */
BOOL GetUUIDTempFilePath(LPCWSTR basePath, LPCWSTR prefix, LPWSTR tmpPath) {
  WCHAR filename[MAX_PATH + 1] = {L"\0"};
  if (prefix) {
  if (prefix) {
    if (wcslen(prefix) > MAX_PATH) {
      return FALSE;
    }
    wcsncpy(filename, prefix, MAX_PATH + 1);
  }
  }

  WCHAR tmpFileNameString[MAX_PATH + 1] = {L"\0"};
  if (!GetUUIDString(tmpFileNameString)) {
    return FALSE;
  }


  size_t tmpFileNameStringLen = wcslen(tmpFileNameString);
  if (wcslen(filename) + tmpFileNameStringLen > MAX_PATH) {
    return FALSE;
  }
  wcsncat(filename, tmpFileNameString, tmpFileNameStringLen);
  wcsncat(filename, tmpFileNameString, tmpFileNameStringLen);

  size_t basePathLen = wcslen(basePath);
  if (basePathLen > MAX_PATH) {
    return FALSE;
  }
  }
  // Use basePathLen + 1 so wcsncpy will add null termination and if a caller
  // doesn't allocate MAX_PATH + 1 for tmpPath this won't fail when there is
  // actually enough space allocated.
  wcsncpy(tmpPath, basePath, basePathLen + 1);
  if (!PathAppendSafe(tmpPath, filename)) {
  if (!PathAppendSafe(tmpPath, filename)) {
    return FALSE;
  }

  return TRUE;
}
}