1 // Copyright 2018 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 
5 #include "chrome/credential_provider/gaiacp/reg_utils.h"
6 
7 #include <atlbase.h>
8 
9 #include "base/base64.h"
10 #include "base/stl_util.h"
11 #include "base/strings/stringprintf.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "base/win/registry.h"
14 #include "base/win/win_util.h"
15 #include "build/branding_buildflags.h"
16 #include "chrome/credential_provider/common/gcp_strings.h"
17 #include "chrome/credential_provider/gaiacp/gaia_credential_provider_i.h"
18 #include "chrome/credential_provider/gaiacp/logging.h"
19 
20 namespace credential_provider {
21 
22 // Root registry key for GCPW configuration and state.
23 #if BUILDFLAG(GOOGLE_CHROME_BRANDING)
24 #define CREDENTIAL_PROVIDER_REGISTRY_KEY L"Software\\Google\\GCPW"
25 #else
26 #define CREDENTIAL_PROVIDER_REGISTRY_KEY L"Software\\Chromium\\GCPW"
27 #endif  // BUILDFLAG(GOOGLE_CHROME_BRANDING)
28 
29 const wchar_t kGcpRootKeyName[] = CREDENTIAL_PROVIDER_REGISTRY_KEY;
30 
31 const wchar_t kGcpUsersRootKeyName[] =
32     CREDENTIAL_PROVIDER_REGISTRY_KEY L"\\Users";
33 
34 const wchar_t kWinlogonUserListRegKey[] =
35     L"SOFTWARE\\Microsoft\\Windows NT"
36     L"\\CurrentVersion\\Winlogon\\SpecialAccounts\\UserList";
37 
38 const wchar_t kLogonUiUserTileRegKey[] =
39     L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Authentication\\LogonUI"
40     L"\\UserTile";
41 
42 const wchar_t kMicrosoftCryptographyRegKey[] =
43     L"SOFTWARE\\Microsoft\\Cryptography";
44 const wchar_t kMicrosoftCryptographyMachineGuidRegKey[] = L"MachineGuid";
45 
46 constexpr wchar_t kRegUserDeviceResourceId[] = L"device_resource_id";
47 constexpr wchar_t kRegGlsPath[] = L"gls_path";
48 constexpr wchar_t kRegEnableVerboseLogging[] = L"enable_verbose_logging";
49 constexpr wchar_t kRegInitializeCrashReporting[] = L"enable_crash_reporting";
50 constexpr wchar_t kRegMdmUrl[] = L"mdm";
51 constexpr wchar_t kRegEnableDmEnrollment[] = L"enable_dm_enrollment";
52 constexpr wchar_t kRegDisablePasswordSync[] = L"disable_password_sync";
53 constexpr wchar_t kRegMdmSupportsMultiUser[] = L"enable_multi_user_login";
54 constexpr wchar_t kRegMdmAllowConsumerAccounts[] = L"enable_consumer_accounts ";
55 constexpr wchar_t kRegMdmEnableForcePasswordReset[] =
56     L"enable_force_reset_password_option";
57 constexpr wchar_t kRegDeviceDetailsUploadStatus[] =
58     L"device_details_upload_status";
59 constexpr wchar_t kRegDeviceDetailsUploadFailures[] =
60     L"device_details_upload_failures";
61 constexpr wchar_t kRegDeveloperMode[] = L"developer_mode";
62 constexpr wchar_t kRegUpdateCredentialsOnChange[] =
63     L"update_credentials_on_change";
64 constexpr wchar_t kRegUseShorterAccountName[] = L"use_shorter_account_name";
65 constexpr wchar_t kEmailDomainsKey[] = L"ed";  // deprecated.
66 constexpr wchar_t kEmailDomainsKeyNew[] = L"domains_allowed_to_login";
67 
68 namespace {
69 
70 constexpr wchar_t kAccountPicturesRootRegKey[] =
71     L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AccountPicture\\Users";
72 constexpr wchar_t kImageRegKey[] = L"Image";
73 
74 // Registry entry that controls whether GCPW is the default
75 // Credential Provider or not.
76 constexpr wchar_t kMakeGcpwDefaultCredProvider[] = L"set_gcpw_as_default_cp";
77 // Windows OS defined registry entry used to configure the
78 // default credential provider CLSID.
79 constexpr wchar_t kDefaultCredProviderPath[] =
80     L"Software\\Policies\\Microsoft\\Windows\\System";
81 constexpr wchar_t kDefaultCredProviderKey[] = L"DefaultCredentialProvider";
82 
83 constexpr wchar_t kEnrollmentRegKey[] = L"SOFTWARE\\Google\\Enrollment";
84 constexpr wchar_t kDmTokenRegKey[] = L"dmtoken";
85 
SetMachineRegDWORD(const base::string16 & key_name,const base::string16 & name,DWORD value)86 HRESULT SetMachineRegDWORD(const base::string16& key_name,
87                            const base::string16& name,
88                            DWORD value) {
89   base::win::RegKey key;
90   LONG sts = key.Create(HKEY_LOCAL_MACHINE, key_name.c_str(), KEY_WRITE);
91   if (sts != ERROR_SUCCESS)
92     return HRESULT_FROM_WIN32(sts);
93 
94   sts = key.WriteValue(name.c_str(), value);
95   if (sts != ERROR_SUCCESS)
96     return HRESULT_FROM_WIN32(sts);
97 
98   return S_OK;
99 }
100 
SetMachineRegString(const base::string16 & key_name,const base::string16 & name,const base::string16 & value)101 HRESULT SetMachineRegString(const base::string16& key_name,
102                             const base::string16& name,
103                             const base::string16& value) {
104   base::win::RegKey key;
105   LONG sts = key.Create(HKEY_LOCAL_MACHINE, key_name.c_str(), KEY_WRITE);
106   if (sts != ERROR_SUCCESS)
107     return HRESULT_FROM_WIN32(sts);
108 
109   if (value.empty()) {
110     sts = key.DeleteValue(name.c_str());
111     if (sts == ERROR_FILE_NOT_FOUND)
112       sts = ERROR_SUCCESS;
113   } else {
114     sts = key.WriteValue(name.c_str(), value.c_str());
115   }
116 
117   if (sts != ERROR_SUCCESS)
118     return HRESULT_FROM_WIN32(sts);
119 
120   return S_OK;
121 }
122 
SetMachineRegBinaryInternal(const base::string16 & key_name,const base::string16 & name,const std::string & value,REGSAM sam_desired)123 HRESULT SetMachineRegBinaryInternal(const base::string16& key_name,
124                                     const base::string16& name,
125                                     const std::string& value,
126                                     REGSAM sam_desired) {
127   base::win::RegKey key;
128   LONG sts = key.Create(HKEY_LOCAL_MACHINE, key_name.c_str(), sam_desired);
129   if (sts != ERROR_SUCCESS)
130     return HRESULT_FROM_WIN32(sts);
131 
132   if (value.empty()) {
133     sts = key.DeleteValue(name.c_str());
134     if (sts == ERROR_FILE_NOT_FOUND)
135       sts = ERROR_SUCCESS;
136   } else {
137     sts =
138         key.WriteValue(name.c_str(), value.c_str(), value.length(), REG_BINARY);
139   }
140 
141   if (sts != ERROR_SUCCESS)
142     return HRESULT_FROM_WIN32(sts);
143 
144   return S_OK;
145 }
146 
GetImageRegKeyForSpecificSize(int image_size)147 base::string16 GetImageRegKeyForSpecificSize(int image_size) {
148   return base::StringPrintf(L"%ls%i", kImageRegKey, image_size);
149 }
150 
GetAccountPictureRegPathForUSer(const base::string16 & user_sid)151 base::string16 GetAccountPictureRegPathForUSer(const base::string16& user_sid) {
152   return base::StringPrintf(L"%ls\\%ls", kAccountPicturesRootRegKey,
153                             user_sid.c_str());
154 }
155 
156 }  // namespace
157 
MakeGcpwDefaultCP()158 HRESULT MakeGcpwDefaultCP() {
159   if (GetGlobalFlagOrDefault(kMakeGcpwDefaultCredProvider, 1))
160     return SetMachineRegString(
161         kDefaultCredProviderPath, kDefaultCredProviderKey,
162         base::win::WStringFromGUID(CLSID_GaiaCredentialProvider));
163 
164   return S_OK;
165 }
166 
GetMachineRegDWORD(const base::string16 & key_name,const base::string16 & name,DWORD * value)167 HRESULT GetMachineRegDWORD(const base::string16& key_name,
168                            const base::string16& name,
169                            DWORD* value) {
170   base::win::RegKey key;
171   LONG sts = key.Open(HKEY_LOCAL_MACHINE, key_name.c_str(), KEY_READ);
172   if (sts != ERROR_SUCCESS)
173     return HRESULT_FROM_WIN32(sts);
174 
175   sts = key.ReadValueDW(name.c_str(), value);
176   if (sts != ERROR_SUCCESS)
177     return HRESULT_FROM_WIN32(sts);
178 
179   return S_OK;
180 }
181 
GetMachineRegString(const base::string16 & key_name,const base::string16 & name,wchar_t * value,ULONG * length)182 HRESULT GetMachineRegString(const base::string16& key_name,
183                             const base::string16& name,
184                             wchar_t* value,
185                             ULONG* length) {
186   DCHECK(value);
187   DCHECK(length);
188   DCHECK_GT(*length, 0u);
189 
190   base::win::RegKey key;
191   LONG sts = key.Open(HKEY_LOCAL_MACHINE, key_name.c_str(), KEY_READ);
192   if (sts != ERROR_SUCCESS)
193     return HRESULT_FROM_WIN32(sts);
194 
195   // read one less character that specified in |length| so that the returned
196   // string can always be null terminated.  Note that string registry values
197   // are not guaranteed to be null terminated.
198   DWORD type;
199   ULONG local_length = (*length - 1) * sizeof(decltype(value[0]));
200   sts = key.ReadValue(name.c_str(), value, &local_length, &type);
201   if (type != REG_SZ)
202     return HRESULT_FROM_WIN32(ERROR_CANTREAD);
203 
204   // When using this overload of the ReadValue() method, the returned length
205   // is in bytes.  The caller expects the length in characters.
206   local_length /= sizeof(decltype(value[0]));
207 
208   if (sts != ERROR_SUCCESS) {
209     if (sts == ERROR_MORE_DATA)
210       *length = local_length;
211     return HRESULT_FROM_WIN32(sts);
212   }
213 
214   value[local_length] = 0;
215   *length = local_length;
216   return S_OK;
217 }
218 
GetMachineRegBinaryInternal(const base::string16 & key_name,const base::string16 & name,std::string * val,REGSAM sam_desired)219 HRESULT GetMachineRegBinaryInternal(const base::string16& key_name,
220                                     const base::string16& name,
221                                     std::string* val,
222                                     REGSAM sam_desired) {
223   DCHECK(val);
224 
225   base::win::RegKey key;
226   LONG sts = key.Open(HKEY_LOCAL_MACHINE, key_name.c_str(), sam_desired);
227   if (sts != ERROR_SUCCESS)
228     return HRESULT_FROM_WIN32(sts);
229 
230   DWORD type;
231   DWORD size = 0;
232 
233   sts = key.ReadValue(name.c_str(), nullptr, &size, &type);
234   if (sts != ERROR_SUCCESS)
235     return HRESULT_FROM_WIN32(sts);
236 
237   if (type != REG_BINARY)
238     return HRESULT_FROM_WIN32(ERROR_CANTREAD);
239 
240   std::vector<char> buffer(size);
241 
242   sts = key.ReadValue(name.c_str(), const_cast<char*>(buffer.data()), &size,
243                       &type);
244   if (sts != ERROR_SUCCESS) {
245     if (sts == ERROR_MORE_DATA)
246       return HRESULT_FROM_WIN32(sts);
247   }
248 
249   val->assign(buffer.data(), buffer.size());
250 
251   return S_OK;
252 }
253 
GetAccountPictureRegString(const base::string16 & user_sid,int image_size,wchar_t * value,ULONG * length)254 HRESULT GetAccountPictureRegString(const base::string16& user_sid,
255                                    int image_size,
256                                    wchar_t* value,
257                                    ULONG* length) {
258   return GetMachineRegString(GetAccountPictureRegPathForUSer(user_sid),
259                              GetImageRegKeyForSpecificSize(image_size), value,
260                              length);
261 }
262 
263 // Sets a specific account picture registry key in HKEY_LOCAL_MACHINE
SetAccountPictureRegString(const base::string16 & user_sid,int image_size,const base::string16 & value)264 HRESULT SetAccountPictureRegString(const base::string16& user_sid,
265                                    int image_size,
266                                    const base::string16& value) {
267   return SetMachineRegString(GetAccountPictureRegPathForUSer(user_sid),
268                              GetImageRegKeyForSpecificSize(image_size), value);
269 }
270 
GetGlobalFlag(const base::string16 & name,DWORD * value)271 HRESULT GetGlobalFlag(const base::string16& name, DWORD* value) {
272   return GetMachineRegDWORD(kGcpRootKeyName, name, value);
273 }
274 
GetGlobalFlag(const base::string16 & name,wchar_t * value,ULONG * length)275 HRESULT GetGlobalFlag(const base::string16& name,
276                       wchar_t* value,
277                       ULONG* length) {
278   return GetMachineRegString(kGcpRootKeyName, name, value, length);
279 }
280 
GetGlobalFlagOrDefault(const base::string16 & reg_key,const base::string16 & default_value)281 base::string16 GetGlobalFlagOrDefault(const base::string16& reg_key,
282                                       const base::string16& default_value) {
283   wchar_t reg_value_buffer[256];
284   ULONG length = base::size(reg_value_buffer);
285   HRESULT hr = GetGlobalFlag(reg_key, reg_value_buffer, &length);
286   if (FAILED(hr))
287     return default_value;
288 
289   return reg_value_buffer;
290 }
291 
GetGlobalFlagOrDefault(const base::string16 & reg_key,const DWORD & default_value)292 DWORD GetGlobalFlagOrDefault(const base::string16& reg_key,
293                              const DWORD& default_value) {
294   DWORD value;
295   HRESULT hr = GetGlobalFlag(reg_key, &value);
296   return SUCCEEDED(hr) ? value : default_value;
297 }
298 
SetGlobalFlag(const base::string16 & name,DWORD value)299 HRESULT SetGlobalFlag(const base::string16& name, DWORD value) {
300   return SetMachineRegDWORD(kGcpRootKeyName, name, value);
301 }
302 
SetGlobalFlag(const base::string16 & name,const base::string16 & value)303 HRESULT SetGlobalFlag(const base::string16& name, const base::string16& value) {
304   return SetMachineRegString(kGcpRootKeyName, name, value);
305 }
306 
SetGlobalFlagForTesting(const base::string16 & name,const base::string16 & value)307 HRESULT SetGlobalFlagForTesting(const base::string16& name,
308                                 const base::string16& value) {
309   return SetMachineRegString(kGcpRootKeyName, name, value);
310 }
311 
SetGlobalFlagForTesting(const base::string16 & name,DWORD value)312 HRESULT SetGlobalFlagForTesting(const base::string16& name, DWORD value) {
313   return SetMachineRegDWORD(kGcpRootKeyName, name, value);
314 }
315 
SetUpdaterClientsAppPathFlag(const base::string16 & name,DWORD value)316 HRESULT SetUpdaterClientsAppPathFlag(const base::string16& name, DWORD value) {
317   base::win::RegKey key;
318   LONG sts = key.Create(HKEY_LOCAL_MACHINE, kRegUpdaterClientsAppPath,
319                         KEY_WRITE | KEY_WOW64_32KEY);
320   if (sts != ERROR_SUCCESS)
321     return HRESULT_FROM_WIN32(sts);
322 
323   sts = key.WriteValue(name.c_str(), value);
324   if (sts != ERROR_SUCCESS)
325     return HRESULT_FROM_WIN32(sts);
326 
327   return S_OK;
328 }
329 
GetUpdaterClientsAppPathFlag(const base::string16 & name,DWORD * value)330 HRESULT GetUpdaterClientsAppPathFlag(const base::string16& name, DWORD* value) {
331   base::win::RegKey key;
332   LONG sts = key.Open(HKEY_LOCAL_MACHINE, kRegUpdaterClientsAppPath,
333                       KEY_READ | KEY_WOW64_32KEY);
334   if (sts != ERROR_SUCCESS)
335     return HRESULT_FROM_WIN32(sts);
336 
337   sts = key.ReadValueDW(name.c_str(), value);
338   if (sts != ERROR_SUCCESS)
339     return HRESULT_FROM_WIN32(sts);
340 
341   return S_OK;
342 }
343 
GetUpdaterClientsAppPathFlagOrDefault(const base::string16 & reg_key,const DWORD & default_value)344 DWORD GetUpdaterClientsAppPathFlagOrDefault(const base::string16& reg_key,
345                                             const DWORD& default_value) {
346   DWORD value;
347   HRESULT hr = GetUpdaterClientsAppPathFlag(reg_key, &value);
348   return SUCCEEDED(hr) ? value : default_value;
349 }
350 
GetUserProperty(const base::string16 & sid,const base::string16 & name,DWORD * value)351 HRESULT GetUserProperty(const base::string16& sid,
352                         const base::string16& name,
353                         DWORD* value) {
354   wchar_t key_name[128];
355   swprintf_s(key_name, base::size(key_name), L"%s\\%s", kGcpUsersRootKeyName,
356              sid.c_str());
357   return GetMachineRegDWORD(key_name, name, value);
358 }
359 
GetUserProperty(const base::string16 & sid,const base::string16 & name,wchar_t * value,ULONG * length)360 HRESULT GetUserProperty(const base::string16& sid,
361                         const base::string16& name,
362                         wchar_t* value,
363                         ULONG* length) {
364   wchar_t key_name[128];
365   swprintf_s(key_name, base::size(key_name), L"%s\\%s", kGcpUsersRootKeyName,
366              sid.c_str());
367   return GetMachineRegString(key_name, name, value, length);
368 }
369 
SetUserProperty(const base::string16 & sid,const base::string16 & name,DWORD value)370 HRESULT SetUserProperty(const base::string16& sid,
371                         const base::string16& name,
372                         DWORD value) {
373   wchar_t key_name[128];
374   swprintf_s(key_name, base::size(key_name), L"%s\\%s", kGcpUsersRootKeyName,
375              sid.c_str());
376   return SetMachineRegDWORD(key_name, name, value);
377 }
378 
SetUserProperty(const base::string16 & sid,const base::string16 & name,const base::string16 & value)379 HRESULT SetUserProperty(const base::string16& sid,
380                         const base::string16& name,
381                         const base::string16& value) {
382   wchar_t key_name[128];
383   swprintf_s(key_name, base::size(key_name), L"%s\\%s", kGcpUsersRootKeyName,
384              sid.c_str());
385   return SetMachineRegString(key_name, name, value);
386 }
387 
RemoveAllUserProperties(const base::string16 & sid)388 HRESULT RemoveAllUserProperties(const base::string16& sid) {
389   base::win::RegKey key;
390   LONG sts = key.Open(HKEY_LOCAL_MACHINE, kGcpUsersRootKeyName, KEY_WRITE);
391   if (sts != ERROR_SUCCESS)
392     return HRESULT_FROM_WIN32(sts);
393 
394   sts = key.DeleteKey(sid.c_str());
395   return sts != ERROR_SUCCESS ? HRESULT_FROM_WIN32(sts) : S_OK;
396 }
397 
GetUserTokenHandles(std::map<base::string16,UserTokenHandleInfo> * sid_to_handle_info)398 HRESULT GetUserTokenHandles(
399     std::map<base::string16, UserTokenHandleInfo>* sid_to_handle_info) {
400   DCHECK(sid_to_handle_info);
401   sid_to_handle_info->clear();
402 
403   base::win::RegistryKeyIterator iter(HKEY_LOCAL_MACHINE, kGcpUsersRootKeyName);
404   for (; iter.Valid(); ++iter) {
405     const wchar_t* sid = iter.Name();
406     wchar_t gaia_id[256];
407     ULONG length = base::size(gaia_id);
408     HRESULT gaia_id_hr = GetUserProperty(sid, kUserId, gaia_id, &length);
409     wchar_t token_handle[256];
410     length = base::size(token_handle);
411     HRESULT token_handle_hr =
412         GetUserProperty(sid, kUserTokenHandle, token_handle, &length);
413     wchar_t email_address[256];
414     length = base::size(email_address);
415     HRESULT email_address_hr =
416         GetUserProperty(sid, kUserEmail, email_address, &length);
417     sid_to_handle_info->emplace(
418         sid,
419         UserTokenHandleInfo{SUCCEEDED(gaia_id_hr) ? gaia_id : L"",
420                             SUCCEEDED(email_address_hr) ? email_address : L"",
421                             SUCCEEDED(token_handle_hr) ? token_handle : L""});
422   }
423   return S_OK;
424 }
425 
GetSidFromKey(const wchar_t * key,const base::string16 & value,wchar_t * sid,ULONG length)426 HRESULT GetSidFromKey(const wchar_t* key,
427                       const base::string16& value,
428                       wchar_t* sid,
429                       ULONG length) {
430   DCHECK(sid);
431   bool result_found = false;
432   base::win::RegistryKeyIterator iter(HKEY_LOCAL_MACHINE, kGcpUsersRootKeyName);
433   for (; iter.Valid(); ++iter) {
434     const wchar_t* user_sid = iter.Name();
435     wchar_t result[256];
436     ULONG result_length = base::size(result);
437     HRESULT hr = GetUserProperty(user_sid, key, result, &result_length);
438     if (SUCCEEDED(hr) && value == result) {
439       // Make sure there are not 2 users with the same SID.
440       if (result_found)
441         return HRESULT_FROM_WIN32(ERROR_USER_EXISTS);
442 
443       wcsncpy_s(sid, length, user_sid, wcslen(user_sid));
444       result_found = true;
445     }
446   }
447 
448   return result_found ? S_OK : HRESULT_FROM_WIN32(ERROR_NONE_MAPPED);
449 }
450 
GetSidFromEmail(const base::string16 & email,wchar_t * sid,ULONG length)451 HRESULT GetSidFromEmail(const base::string16& email,
452                         wchar_t* sid,
453                         ULONG length) {
454   return GetSidFromKey(kUserEmail, email, sid, length);
455 }
456 
GetSidFromId(const base::string16 & id,wchar_t * sid,ULONG length)457 HRESULT GetSidFromId(const base::string16& id, wchar_t* sid, ULONG length) {
458   return GetSidFromKey(kUserId, id, sid, length);
459 }
460 
GetIdFromSid(const wchar_t * sid,base::string16 * id)461 HRESULT GetIdFromSid(const wchar_t* sid, base::string16* id) {
462   DCHECK(id);
463 
464   base::win::RegistryKeyIterator iter(HKEY_LOCAL_MACHINE, kGcpUsersRootKeyName);
465   for (; iter.Valid(); ++iter) {
466     const wchar_t* user_sid = iter.Name();
467 
468     if (wcscmp(sid, user_sid) == 0) {
469       wchar_t user_id[256];
470       ULONG user_length = base::size(user_id);
471       HRESULT hr = GetUserProperty(user_sid, kUserId, user_id, &user_length);
472       if (SUCCEEDED(hr)) {
473         *id = user_id;
474         return S_OK;
475       }
476     }
477   }
478   return HRESULT_FROM_WIN32(ERROR_NONE_MAPPED);
479 }
480 
GetUserEmailFromSid(const base::string16 & sid)481 std::string GetUserEmailFromSid(const base::string16& sid) {
482   wchar_t email_id[512];
483   ULONG email_id_size = base::size(email_id);
484   HRESULT hr = GetUserProperty(sid, kUserEmail, email_id, &email_id_size);
485 
486   base::string16 email_id_str;
487   if (SUCCEEDED(hr) && email_id_size > 0)
488     email_id_str = base::string16(email_id, email_id_size - 1);
489 
490   return base::UTF16ToUTF8(email_id_str);
491 }
492 
SetUserWinlogonUserListEntry(const base::string16 & username,DWORD visible)493 HRESULT SetUserWinlogonUserListEntry(const base::string16& username,
494                                      DWORD visible) {
495   // Sets the value of the key that will hide the user from all credential
496   // providers.
497   base::win::RegKey key;
498   LONG sts = key.Create(HKEY_LOCAL_MACHINE, kWinlogonUserListRegKey, KEY_WRITE);
499   if (sts != ERROR_SUCCESS)
500     return HRESULT_FROM_WIN32(sts);
501 
502   // The key is only set if we want to make a user invisible. The default
503   // behavior is for the user to be visible so delete the key in this case.
504   if (!visible) {
505     sts = key.WriteValue(username.c_str(), visible);
506   } else {
507     sts = key.DeleteValue(username.c_str());
508     if (sts == ERROR_FILE_NOT_FOUND)
509       sts = ERROR_SUCCESS;
510   }
511 
512   if (sts != ERROR_SUCCESS)
513     return HRESULT_FROM_WIN32(sts);
514 
515   return S_OK;
516 }
517 
SetLogonUiUserTileEntry(const base::string16 & sid,CLSID cp_guid)518 HRESULT SetLogonUiUserTileEntry(const base::string16& sid, CLSID cp_guid) {
519   return SetMachineRegString(kLogonUiUserTileRegKey, sid,
520                              base::win::WStringFromGUID(cp_guid));
521 }
522 
GetMachineGuid(base::string16 * machine_guid)523 HRESULT GetMachineGuid(base::string16* machine_guid) {
524   // The machine guid is a unique identifier assigned to a computer on every
525   // install of Windows. This guid can be used to uniquely identify this device
526   // to various management services. The same guid is used to identify the
527   // device to Chrome Browser Cloud Management. It is fetched in this file:
528   // chrome/browser/policy/browser_dm_token_storage_win.cc:InitClientId.
529   DCHECK(machine_guid);
530   wchar_t machine_guid_buffer[64];
531   ULONG guid_length = base::size(machine_guid_buffer);
532   HRESULT hr = GetMachineRegString(kMicrosoftCryptographyRegKey,
533                                    kMicrosoftCryptographyMachineGuidRegKey,
534                                    machine_guid_buffer, &guid_length);
535 
536   if (SUCCEEDED(hr))
537     *machine_guid = machine_guid_buffer;
538 
539   return hr;
540 }
541 
SetMachineGuidForTesting(const base::string16 & machine_guid)542 HRESULT SetMachineGuidForTesting(const base::string16& machine_guid) {
543   // Set a debug guid for the machine so that unit tests that override the
544   // registry can run properly.
545   return SetMachineRegString(kMicrosoftCryptographyRegKey,
546                              kMicrosoftCryptographyMachineGuidRegKey,
547                              machine_guid);
548 }
549 
GetUserDeviceResourceId(const base::string16 & sid)550 base::string16 GetUserDeviceResourceId(const base::string16& sid) {
551   wchar_t known_resource_id[512];
552   ULONG known_resource_id_size = base::size(known_resource_id);
553   HRESULT hr = GetUserProperty(sid, kRegUserDeviceResourceId, known_resource_id,
554                                &known_resource_id_size);
555 
556   if (SUCCEEDED(hr) && known_resource_id_size > 0)
557     return base::string16(known_resource_id, known_resource_id_size - 1);
558 
559   return base::string16();
560 }
561 
GetDmToken(std::string * dm_token)562 HRESULT GetDmToken(std::string* dm_token) {
563   DCHECK(dm_token);
564 
565   std::string binary_dm_token;
566   HRESULT hr =
567       GetMachineRegBinaryInternal(kEnrollmentRegKey, kDmTokenRegKey,
568                                   &binary_dm_token, KEY_READ | KEY_WOW64_32KEY);
569   if (SUCCEEDED(hr)) {
570     base::Base64Encode(binary_dm_token, dm_token);
571   }
572   return hr;
573 }
574 
SetDmTokenForTesting(const std::string & dm_token)575 HRESULT SetDmTokenForTesting(const std::string& dm_token) {
576   // Set a debug dm token for the machine so that unit tests that override the
577   // registry can run properly.
578   return SetMachineRegBinaryInternal(kEnrollmentRegKey, kDmTokenRegKey,
579                                      dm_token, KEY_WRITE | KEY_WOW64_32KEY);
580 }
581 
582 }  // namespace credential_provider
583