Revert "Reland c91b178b07b0d - Delete dead signin code (SigninGlobalError)"
[chromium-blink-merge.git] / rlz / win / lib / machine_id_win.cc
blob3f366fad79144a54a2c63c4c285a2b20f7eb345a
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.
5 #include <windows.h>
6 #include <Sddl.h> // For ConvertSidToStringSidW.
7 #include <string>
9 #include "base/memory/scoped_ptr.h"
10 #include "base/strings/string16.h"
11 #include "rlz/lib/assert.h"
13 namespace rlz_lib {
15 namespace {
17 bool GetSystemVolumeSerialNumber(int* number) {
18 if (!number)
19 return false;
21 *number = 0;
23 // Find the system root path (e.g: C:\).
24 wchar_t system_path[MAX_PATH + 1];
25 if (!GetSystemDirectoryW(system_path, MAX_PATH))
26 return false;
28 wchar_t* first_slash = wcspbrk(system_path, L"\\/");
29 if (first_slash != NULL)
30 *(first_slash + 1) = 0;
32 DWORD number_local = 0;
33 if (!GetVolumeInformationW(system_path, NULL, 0, &number_local, NULL, NULL,
34 NULL, 0))
35 return false;
37 *number = number_local;
38 return true;
41 bool GetComputerSid(const wchar_t* account_name, SID* sid, DWORD sid_size) {
42 static const DWORD kStartDomainLength = 128; // reasonable to start with
44 scoped_ptr<wchar_t[]> domain_buffer(new wchar_t[kStartDomainLength]);
45 DWORD domain_size = kStartDomainLength;
46 DWORD sid_dword_size = sid_size;
47 SID_NAME_USE sid_name_use;
49 BOOL success = ::LookupAccountNameW(NULL, account_name, sid,
50 &sid_dword_size, domain_buffer.get(),
51 &domain_size, &sid_name_use);
52 if (!success && ::GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
53 // We could have gotten the insufficient buffer error because
54 // one or both of sid and szDomain was too small. Check for that
55 // here.
56 if (sid_dword_size > sid_size)
57 return false;
59 if (domain_size > kStartDomainLength)
60 domain_buffer.reset(new wchar_t[domain_size]);
62 success = ::LookupAccountNameW(NULL, account_name, sid, &sid_dword_size,
63 domain_buffer.get(), &domain_size,
64 &sid_name_use);
67 return success != FALSE;
70 std::wstring ConvertSidToString(SID* sid) {
71 std::wstring sid_string;
72 #if _WIN32_WINNT >= 0x500
73 wchar_t* sid_buffer = NULL;
74 if (ConvertSidToStringSidW(sid, &sid_buffer)) {
75 sid_string = sid_buffer;
76 LocalFree(sid_buffer);
78 #else
79 SID_IDENTIFIER_AUTHORITY* sia = ::GetSidIdentifierAuthority(sid);
81 if(sia->Value[0] || sia->Value[1]) {
82 base::SStringPrintf(
83 &sid_string, L"S-%d-0x%02hx%02hx%02hx%02hx%02hx%02hx",
84 SID_REVISION, (USHORT)sia->Value[0], (USHORT)sia->Value[1],
85 (USHORT)sia->Value[2], (USHORT)sia->Value[3], (USHORT)sia->Value[4],
86 (USHORT)sia->Value[5]);
87 } else {
88 ULONG authority = 0;
89 for (int i = 2; i < 6; ++i) {
90 authority <<= 8;
91 authority |= sia->Value[i];
93 base::SStringPrintf(&sid_string, L"S-%d-%lu", SID_REVISION, authority);
96 int sub_auth_count = *::GetSidSubAuthorityCount(sid);
97 for(int i = 0; i < sub_auth_count; ++i)
98 base::StringAppendF(&sid_string, L"-%lu", *::GetSidSubAuthority(sid, i));
99 #endif
101 return sid_string;
104 } // namespace
106 bool GetRawMachineId(base::string16* sid_string, int* volume_id) {
107 // Calculate the Windows SID.
109 wchar_t computer_name[MAX_COMPUTERNAME_LENGTH + 1] = {0};
110 DWORD size = arraysize(computer_name);
112 if (GetComputerNameW(computer_name, &size)) {
113 char sid_buffer[SECURITY_MAX_SID_SIZE];
114 SID* sid = reinterpret_cast<SID*>(sid_buffer);
115 if (GetComputerSid(computer_name, sid, SECURITY_MAX_SID_SIZE)) {
116 *sid_string = ConvertSidToString(sid);
120 // Get the system drive volume serial number.
121 *volume_id = 0;
122 if (!GetSystemVolumeSerialNumber(volume_id)) {
123 ASSERT_STRING("GetMachineId: Failed to retrieve volume serial number");
124 *volume_id = 0;
127 return true;
130 } // namespace rlz_lib