rlz_value_store_registry.cc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "rlz/win/lib/rlz_value_store_registry.h"
  5. #include "base/strings/stringprintf.h"
  6. #include "base/strings/utf_string_conversions.h"
  7. #include "base/win/registry.h"
  8. #include "rlz/lib/assert.h"
  9. #include "rlz/lib/lib_values.h"
  10. #include "rlz/lib/string_utils.h"
  11. #include "rlz/lib/supplementary_branding.h"
  12. #include "rlz/win/lib/registry_util.h"
  13. namespace rlz_lib {
  14. namespace {
  15. //
  16. // Registry keys:
  17. //
  18. // RLZ's are stored as:
  19. // <AccessPointName> = <RLZ value> @ kRootKey\kLibKeyName\kRlzsSubkeyName.
  20. //
  21. // Events are stored as:
  22. // <AccessPointName><EventName> = 1 @
  23. // HKCU\kLibKeyName\kEventsSubkeyName\GetProductName(product).
  24. //
  25. // The OEM Deal Confirmation Code (DCC) is stored as
  26. // kDccValueName = <DCC value> @ HKLM\kLibKeyName
  27. //
  28. // The last ping time, per product is stored as:
  29. // GetProductName(product) = <last ping time> @
  30. // HKCU\kLibKeyName\kPingTimesSubkeyName.
  31. //
  32. // The server does not care about any of these constants.
  33. //
  34. const char kLibKeyName[] = "Software\\Google\\Common\\Rlz";
  35. const wchar_t kGoogleKeyName[] = L"Software\\Google";
  36. const wchar_t kGoogleCommonKeyName[] = L"Software\\Google\\Common";
  37. const char kRlzsSubkeyName[] = "RLZs";
  38. const char kEventsSubkeyName[] = "Events";
  39. const char kStatefulEventsSubkeyName[] = "StatefulEvents";
  40. const char kPingTimesSubkeyName[] = "PTimes";
  41. std::wstring GetWideProductName(Product product) {
  42. return base::ASCIIToWide(GetProductName(product));
  43. }
  44. void AppendBrandToString(std::string* str) {
  45. std::string brand(SupplementaryBranding::GetBrand());
  46. if (!brand.empty())
  47. base::StringAppendF(str, "\\_%s", brand.c_str());
  48. }
  49. // Function to get the specific registry keys.
  50. bool GetRegKey(const char* name, REGSAM access, base::win::RegKey* key) {
  51. std::string key_location;
  52. base::StringAppendF(&key_location, "%s\\%s", kLibKeyName, name);
  53. AppendBrandToString(&key_location);
  54. std::wstring key_locationw = base::ASCIIToWide(key_location);
  55. LONG ret;
  56. if (access & (KEY_SET_VALUE | KEY_CREATE_SUB_KEY | KEY_CREATE_LINK))
  57. ret = key->Create(HKEY_CURRENT_USER, key_locationw.c_str(), access);
  58. else
  59. ret = key->Open(HKEY_CURRENT_USER, key_locationw.c_str(), access);
  60. return ret == ERROR_SUCCESS;
  61. }
  62. bool GetPingTimesRegKey(REGSAM access, base::win::RegKey* key) {
  63. return GetRegKey(kPingTimesSubkeyName, access, key);
  64. }
  65. bool GetEventsRegKey(const char* event_type,
  66. const rlz_lib::Product* product,
  67. REGSAM access, base::win::RegKey* key) {
  68. std::string key_location;
  69. base::StringAppendF(&key_location, "%s\\%s", kLibKeyName,
  70. event_type);
  71. AppendBrandToString(&key_location);
  72. if (product != NULL) {
  73. std::string product_name = GetProductName(*product);
  74. if (product_name.empty())
  75. return false;
  76. base::StringAppendF(&key_location, "\\%s", product_name.c_str());
  77. }
  78. std::wstring key_locationw = base::ASCIIToWide(key_location);
  79. LONG ret;
  80. if (access & (KEY_SET_VALUE | KEY_CREATE_SUB_KEY | KEY_CREATE_LINK))
  81. ret = key->Create(HKEY_CURRENT_USER, key_locationw.c_str(), access);
  82. else
  83. ret = key->Open(HKEY_CURRENT_USER, key_locationw.c_str(), access);
  84. return ret == ERROR_SUCCESS;
  85. }
  86. bool GetAccessPointRlzsRegKey(REGSAM access, base::win::RegKey* key) {
  87. return GetRegKey(kRlzsSubkeyName, access, key);
  88. }
  89. bool ClearAllProductEventValues(rlz_lib::Product product, const char* key) {
  90. std::wstring product_name = GetWideProductName(product);
  91. if (product_name.empty())
  92. return false;
  93. base::win::RegKey reg_key;
  94. GetEventsRegKey(key, NULL, KEY_WRITE, &reg_key);
  95. reg_key.DeleteKey(product_name.c_str());
  96. // Verify that the value no longer exists.
  97. base::win::RegKey product_events(
  98. reg_key.Handle(), product_name.c_str(), KEY_READ);
  99. if (product_events.Valid()) {
  100. ASSERT_STRING("ClearAllProductEvents: Key deletion failed");
  101. return false;
  102. }
  103. return true;
  104. }
  105. // Deletes a registry key if it exists and has no subkeys or values.
  106. // TODO: Move this to a registry_utils file and add unittest.
  107. bool DeleteKeyIfEmpty(HKEY root_key, const wchar_t* key_name) {
  108. if (!key_name) {
  109. ASSERT_STRING("DeleteKeyIfEmpty: key_name is NULL");
  110. return false;
  111. } else { // Scope needed for RegKey
  112. base::win::RegKey key(root_key, key_name, KEY_READ);
  113. if (!key.Valid())
  114. return true; // Key does not exist - nothing to do.
  115. base::win::RegistryKeyIterator key_iter(root_key, key_name);
  116. if (key_iter.SubkeyCount() > 0)
  117. return true; // Not empty, so nothing to do
  118. base::win::RegistryValueIterator value_iter(root_key, key_name);
  119. if (value_iter.ValueCount() > 0)
  120. return true; // Not empty, so nothing to do
  121. }
  122. // The key is empty - delete it now.
  123. base::win::RegKey key(root_key, L"", KEY_WRITE);
  124. return key.DeleteKey(key_name) == ERROR_SUCCESS;
  125. }
  126. } // namespace
  127. // static
  128. std::wstring RlzValueStoreRegistry::GetWideLibKeyName() {
  129. return base::ASCIIToWide(kLibKeyName);
  130. }
  131. bool RlzValueStoreRegistry::HasAccess(AccessType type) {
  132. return HasUserKeyAccess(type == kWriteAccess);
  133. }
  134. bool RlzValueStoreRegistry::WritePingTime(Product product, int64_t time) {
  135. base::win::RegKey key;
  136. std::wstring product_name = GetWideProductName(product);
  137. return GetPingTimesRegKey(KEY_WRITE, &key) &&
  138. key.WriteValue(product_name.c_str(), &time, sizeof(time),
  139. REG_QWORD) == ERROR_SUCCESS;
  140. }
  141. bool RlzValueStoreRegistry::ReadPingTime(Product product, int64_t* time) {
  142. base::win::RegKey key;
  143. std::wstring product_name = GetWideProductName(product);
  144. return GetPingTimesRegKey(KEY_READ, &key) &&
  145. key.ReadInt64(product_name.c_str(), time) == ERROR_SUCCESS;
  146. }
  147. bool RlzValueStoreRegistry::ClearPingTime(Product product) {
  148. base::win::RegKey key;
  149. GetPingTimesRegKey(KEY_WRITE, &key);
  150. std::wstring product_name = GetWideProductName(product);
  151. key.DeleteValue(product_name.c_str());
  152. // Verify deletion.
  153. uint64_t value;
  154. DWORD size = sizeof(value);
  155. if (key.ReadValue(
  156. product_name.c_str(), &value, &size, NULL) == ERROR_SUCCESS) {
  157. ASSERT_STRING("RlzValueStoreRegistry::ClearPingTime: Failed to delete.");
  158. return false;
  159. }
  160. return true;
  161. }
  162. bool RlzValueStoreRegistry::WriteAccessPointRlz(AccessPoint access_point,
  163. const char* new_rlz) {
  164. const char* access_point_name = GetAccessPointName(access_point);
  165. if (!access_point_name)
  166. return false;
  167. std::wstring access_point_namew(base::ASCIIToWide(access_point_name));
  168. base::win::RegKey key;
  169. GetAccessPointRlzsRegKey(KEY_WRITE, &key);
  170. if (!RegKeyWriteValue(&key, access_point_namew.c_str(), new_rlz)) {
  171. ASSERT_STRING("SetAccessPointRlz: Could not write the new RLZ value");
  172. return false;
  173. }
  174. return true;
  175. }
  176. bool RlzValueStoreRegistry::ReadAccessPointRlz(AccessPoint access_point,
  177. char* rlz,
  178. size_t rlz_size) {
  179. const char* access_point_name = GetAccessPointName(access_point);
  180. if (!access_point_name)
  181. return false;
  182. size_t size = rlz_size;
  183. base::win::RegKey key;
  184. GetAccessPointRlzsRegKey(KEY_READ, &key);
  185. std::wstring access_point_namew = base::ASCIIToWide(access_point_name);
  186. if (!RegKeyReadValue(key, access_point_namew.c_str(), rlz, &size)) {
  187. rlz[0] = 0;
  188. if (size > rlz_size) {
  189. ASSERT_STRING("GetAccessPointRlz: Insufficient buffer size");
  190. return false;
  191. }
  192. }
  193. return true;
  194. }
  195. bool RlzValueStoreRegistry::ClearAccessPointRlz(AccessPoint access_point) {
  196. const char* access_point_name = GetAccessPointName(access_point);
  197. if (!access_point_name)
  198. return false;
  199. std::wstring access_point_namew(base::ASCIIToWide(access_point_name));
  200. base::win::RegKey key;
  201. GetAccessPointRlzsRegKey(KEY_WRITE, &key);
  202. key.DeleteValue(access_point_namew.c_str());
  203. // Verify deletion.
  204. DWORD value;
  205. if (key.ReadValueDW(access_point_namew.c_str(), &value) == ERROR_SUCCESS) {
  206. ASSERT_STRING("SetAccessPointRlz: Could not clear the RLZ value.");
  207. return false;
  208. }
  209. return true;
  210. }
  211. bool RlzValueStoreRegistry::UpdateExistingAccessPointRlz(
  212. const std::string& brand) {
  213. return false;
  214. }
  215. bool RlzValueStoreRegistry::AddProductEvent(Product product,
  216. const char* event_rlz) {
  217. std::wstring event_rlzw(base::ASCIIToWide(event_rlz));
  218. base::win::RegKey reg_key;
  219. GetEventsRegKey(kEventsSubkeyName, &product, KEY_WRITE, &reg_key);
  220. if (reg_key.WriteValue(event_rlzw.c_str(), 1) != ERROR_SUCCESS) {
  221. ASSERT_STRING("AddProductEvent: Could not write the new event value");
  222. return false;
  223. }
  224. return true;
  225. }
  226. bool RlzValueStoreRegistry::ReadProductEvents(Product product,
  227. std::vector<std::string>* events) {
  228. // Open the events key.
  229. base::win::RegKey events_key;
  230. GetEventsRegKey(kEventsSubkeyName, &product, KEY_READ, &events_key);
  231. if (!events_key.Valid())
  232. return false;
  233. // Append the events to the buffer.
  234. int num_values = 0;
  235. LONG result = ERROR_SUCCESS;
  236. for (num_values = 0; result == ERROR_SUCCESS; ++num_values) {
  237. // Max 32767 bytes according to MSDN, but we never use that much.
  238. const size_t kMaxValueNameLength = 2048;
  239. char buffer[kMaxValueNameLength];
  240. DWORD size = std::size(buffer);
  241. result = RegEnumValueA(events_key.Handle(), num_values, buffer, &size,
  242. NULL, NULL, NULL, NULL);
  243. if (result == ERROR_SUCCESS)
  244. events->push_back(std::string(buffer));
  245. }
  246. return result == ERROR_NO_MORE_ITEMS;
  247. }
  248. bool RlzValueStoreRegistry::ClearProductEvent(Product product,
  249. const char* event_rlz) {
  250. std::wstring event_rlzw(base::ASCIIToWide(event_rlz));
  251. base::win::RegKey key;
  252. GetEventsRegKey(kEventsSubkeyName, &product, KEY_WRITE, &key);
  253. key.DeleteValue(event_rlzw.c_str());
  254. // Verify deletion.
  255. DWORD value;
  256. if (key.ReadValueDW(event_rlzw.c_str(), &value) == ERROR_SUCCESS) {
  257. ASSERT_STRING("ClearProductEvent: Could not delete the event value.");
  258. return false;
  259. }
  260. return true;
  261. }
  262. bool RlzValueStoreRegistry::ClearAllProductEvents(Product product) {
  263. return ClearAllProductEventValues(product, kEventsSubkeyName);
  264. }
  265. bool RlzValueStoreRegistry::AddStatefulEvent(Product product,
  266. const char* event_rlz) {
  267. base::win::RegKey key;
  268. std::wstring event_rlzw(base::ASCIIToWide(event_rlz));
  269. if (!GetEventsRegKey(kStatefulEventsSubkeyName, &product, KEY_WRITE, &key) ||
  270. key.WriteValue(event_rlzw.c_str(), 1) != ERROR_SUCCESS) {
  271. ASSERT_STRING(
  272. "AddStatefulEvent: Could not write the new stateful event");
  273. return false;
  274. }
  275. return true;
  276. }
  277. bool RlzValueStoreRegistry::IsStatefulEvent(Product product,
  278. const char* event_rlz) {
  279. DWORD value;
  280. base::win::RegKey key;
  281. GetEventsRegKey(kStatefulEventsSubkeyName, &product, KEY_READ, &key);
  282. std::wstring event_rlzw(base::ASCIIToWide(event_rlz));
  283. return key.ReadValueDW(event_rlzw.c_str(), &value) == ERROR_SUCCESS;
  284. }
  285. bool RlzValueStoreRegistry::ClearAllStatefulEvents(Product product) {
  286. return ClearAllProductEventValues(product, kStatefulEventsSubkeyName);
  287. }
  288. void RlzValueStoreRegistry::CollectGarbage() {
  289. // Delete each of the known subkeys if empty.
  290. const char* const subkeys[] = {
  291. kRlzsSubkeyName,
  292. kEventsSubkeyName,
  293. kStatefulEventsSubkeyName,
  294. kPingTimesSubkeyName
  295. };
  296. for (size_t i = 0; i < std::size(subkeys); i++) {
  297. std::string subkey_name;
  298. base::StringAppendF(&subkey_name, "%s\\%s", kLibKeyName, subkeys[i]);
  299. AppendBrandToString(&subkey_name);
  300. std::wstring subkey_namew = base::ASCIIToWide(subkey_name);
  301. VERIFY(DeleteKeyIfEmpty(HKEY_CURRENT_USER, subkey_namew.c_str()));
  302. }
  303. // Delete the library key and its parents too now if empty.
  304. VERIFY(DeleteKeyIfEmpty(HKEY_CURRENT_USER, GetWideLibKeyName().c_str()));
  305. VERIFY(DeleteKeyIfEmpty(HKEY_CURRENT_USER, kGoogleCommonKeyName));
  306. VERIFY(DeleteKeyIfEmpty(HKEY_CURRENT_USER, kGoogleKeyName));
  307. }
  308. ScopedRlzValueStoreLock::ScopedRlzValueStoreLock() {
  309. if (!lock_.failed())
  310. store_.reset(new RlzValueStoreRegistry);
  311. }
  312. ScopedRlzValueStoreLock::~ScopedRlzValueStoreLock() {
  313. }
  314. RlzValueStore* ScopedRlzValueStoreLock::GetStore() {
  315. return store_.get();
  316. }
  317. } // namespace rlz_lib