15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Library functions related to the OEM Deal Confirmation Code.
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "rlz/win/lib/machine_deal.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_split.h"
15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/registry.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "rlz/lib/assert.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "rlz/lib/lib_values.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "rlz/win/lib/lib_mutex.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "rlz/win/lib/registry_util.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "rlz/win/lib/rlz_value_store_registry.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kDccValueName[]             = L"DCC";
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Current DCC can only uses [a-zA-Z0-9_-!@$*();.<>,:]
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We will be more liberal and allow some additional chars, but not url meta
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// chars.
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsGoodDccChar(char ch) {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsAsciiAlpha(ch) || IsAsciiDigit(ch))
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (ch) {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case '_':
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case '-':
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case '!':
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case '@':
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case '$':
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case '*':
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case '(':
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ')':
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ';':
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case '.':
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case '<':
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case '>':
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ',':
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ':':
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This function will remove bad rlz chars and also limit the max rlz to some
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// reasonable size. It also assumes that normalized_dcc is at least
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// kMaxDccLength+1 long.
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NormalizeDcc(const char* raw_dcc, char* normalized_dcc) {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int index = 0;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (; raw_dcc[index] != 0 && index < rlz_lib::kMaxDccLength; ++index) {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char current = raw_dcc[index];
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (IsGoodDccChar(current)) {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      normalized_dcc[index] = current;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      normalized_dcc[index] = '.';
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  normalized_dcc[index] = 0;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetResponseLine(const char* response_text, int response_length,
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     int* search_index, std::string* response_line) {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!response_line || !search_index || *search_index > response_length)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  response_line->clear();
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (*search_index < 0)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int line_begin = *search_index;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* line_end = strchr(response_text + line_begin, '\n');
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (line_end == NULL || line_end - response_text > response_length) {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    line_end = response_text + response_length;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *search_index = -1;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *search_index = line_end - response_text + 1;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  response_line->assign(response_text + line_begin,
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        line_end - response_text - line_begin);
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetResponseValue(const std::string& response_line,
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      const std::string& response_key,
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      std::string* value) {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!value)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  value->clear();
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!StartsWithASCII(response_line, response_key, true))
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string> tokens;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::SplitString(response_line, ':', &tokens);
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (tokens.size() != 2)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The first token is the key, the second is the value.  The value is already
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // trimmed for whitespace.
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *value = tokens[1];
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace anonymous
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace rlz_lib {
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MachineDealCode::Set(const char* dcc) {
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LibMutex lock;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (lock.failed())
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO: if (!ProcessInfo::CanWriteMachineKey()) return false;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Validate the new dcc value.
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t length = strlen(dcc);
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (length >  kMaxDccLength) {
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_STRING("MachineDealCode::Set: DCC length is exceeds max allowed.");
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::win::RegKey hklm_key(HKEY_LOCAL_MACHINE,
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             RlzValueStoreRegistry::GetWideLibKeyName().c_str(),
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             KEY_READ | KEY_WRITE | KEY_WOW64_32KEY);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!hklm_key.Valid()) {
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_STRING("MachineDealCode::Set: Unable to create / open machine key."
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  " Did you call rlz_lib::CreateMachineState()?");
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char normalized_dcc[kMaxDccLength + 1];
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NormalizeDcc(dcc, normalized_dcc);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VERIFY(length == strlen(normalized_dcc));
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Write the DCC to HKLM.  Note that we need to include the null character
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // when writing the string.
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!RegKeyWriteValue(hklm_key, kDccValueName, normalized_dcc)) {
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_STRING("MachineDealCode::Set: Could not write the DCC value");
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MachineDealCode::GetNewCodeFromPingResponse(const char* response,
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool* has_new_dcc, char* new_dcc, int new_dcc_size) {
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!has_new_dcc || !new_dcc || !new_dcc_size)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *has_new_dcc = false;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  new_dcc[0] = 0;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int response_length = -1;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsPingResponseValid(response, &response_length))
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get the current DCC value to compare to later)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char stored_dcc[kMaxDccLength + 1];
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!Get(stored_dcc, arraysize(stored_dcc)))
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    stored_dcc[0] = 0;
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int search_index = 0;
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string response_line;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string new_dcc_value;
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool old_dcc_confirmed = false;
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string dcc_cgi(kDccCgiVariable);
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string dcc_cgi_response(kSetDccResponseVariable);
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (GetResponseLine(response, response_length, &search_index,
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         &response_line)) {
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string value;
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!old_dcc_confirmed &&
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetResponseValue(response_line, dcc_cgi, &value)) {
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // This is the old DCC confirmation - should match value in registry.
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (value != stored_dcc)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;  // Corrupted DCC - ignore this response.
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        old_dcc_confirmed = true;
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!(*has_new_dcc) &&
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetResponseValue(response_line, dcc_cgi_response, &value)) {
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // This is the new DCC.
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (value.size() > kMaxDccLength) continue;  // Too long
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *has_new_dcc = true;
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new_dcc_value = value;
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  old_dcc_confirmed |= (NULL == stored_dcc[0]);
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::strlcpy(new_dcc, new_dcc_value.c_str(), new_dcc_size);
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return old_dcc_confirmed;
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MachineDealCode::SetFromPingResponse(const char* response) {
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool has_new_dcc = false;
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char new_dcc[kMaxDccLength + 1];
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool response_valid = GetNewCodeFromPingResponse(
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      response, &has_new_dcc, new_dcc, arraysize(new_dcc));
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (response_valid && has_new_dcc)
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return Set(new_dcc);
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return response_valid;
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MachineDealCode::GetAsCgi(char* cgi, int cgi_size) {
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!cgi || cgi_size <= 0) {
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_STRING("MachineDealCode::GetAsCgi: Invalid buffer");
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cgi[0] = 0;
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string cgi_arg;
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::StringAppendF(&cgi_arg, "%s=", kDccCgiVariable);
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int cgi_arg_length = cgi_arg.size();
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cgi_arg_length >= cgi_size) {
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_STRING("MachineDealCode::GetAsCgi: Insufficient buffer size");
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::strlcpy(cgi, cgi_arg.c_str(), cgi_size);
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!Get(cgi + cgi_arg_length, cgi_size - cgi_arg_length)) {
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cgi[0] = 0;
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MachineDealCode::Get(char* dcc, int dcc_size) {
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LibMutex lock;
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (lock.failed())
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!dcc || dcc_size <= 0) {
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_STRING("MachineDealCode::Get: Invalid buffer");
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dcc[0] = 0;
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::win::RegKey dcc_key(HKEY_LOCAL_MACHINE,
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            RlzValueStoreRegistry::GetWideLibKeyName().c_str(),
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            KEY_READ | KEY_WOW64_32KEY);
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!dcc_key.Valid())
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;  // no DCC key.
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t size = dcc_size;
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!RegKeyReadValue(dcc_key, kDccValueName, dcc, &size)) {
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_STRING("MachineDealCode::Get: Insufficient buffer size");
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dcc[0] = 0;
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MachineDealCode::Clear() {
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::win::RegKey dcc_key(HKEY_LOCAL_MACHINE,
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            RlzValueStoreRegistry::GetWideLibKeyName().c_str(),
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            KEY_READ | KEY_WRITE | KEY_WOW64_32KEY);
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!dcc_key.Valid())
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;  // no DCC key.
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dcc_key.DeleteValue(kDccValueName);
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify deletion.
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wchar_t dcc[kMaxDccLength + 1];
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD dcc_size = arraysize(dcc);
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (dcc_key.ReadValue(kDccValueName, dcc, &dcc_size, NULL) == ERROR_SUCCESS) {
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_STRING("MachineDealCode::Clear: Could not delete the DCC value.");
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace rlz_lib
301