OLD | NEW |
| (Empty) |
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 | |
5 #include <windows.h> | |
6 #include <Sddl.h> // For ConvertSidToStringSidW. | |
7 #include <string> | |
8 | |
9 #include "base/memory/scoped_ptr.h" | |
10 #include "base/string16.h" | |
11 #include "rlz/lib/assert.h" | |
12 | |
13 namespace rlz_lib { | |
14 | |
15 namespace { | |
16 | |
17 bool GetSystemVolumeSerialNumber(int* number) { | |
18 if (!number) | |
19 return false; | |
20 | |
21 *number = 0; | |
22 | |
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; | |
27 | |
28 wchar_t* first_slash = wcspbrk(system_path, L"\\/"); | |
29 if (first_slash != NULL) | |
30 *(first_slash + 1) = 0; | |
31 | |
32 DWORD number_local = 0; | |
33 if (!GetVolumeInformationW(system_path, NULL, 0, &number_local, NULL, NULL, | |
34 NULL, 0)) | |
35 return false; | |
36 | |
37 *number = number_local; | |
38 return true; | |
39 } | |
40 | |
41 bool GetComputerSid(const wchar_t* account_name, SID* sid, DWORD sid_size) { | |
42 static const DWORD kStartDomainLength = 128; // reasonable to start with | |
43 | |
44 scoped_array<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; | |
48 | |
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; | |
58 | |
59 if (domain_size > kStartDomainLength) | |
60 domain_buffer.reset(new wchar_t[domain_size]); | |
61 | |
62 success = ::LookupAccountNameW(NULL, account_name, sid, &sid_dword_size, | |
63 domain_buffer.get(), &domain_size, | |
64 &sid_name_use); | |
65 } | |
66 | |
67 return success != FALSE; | |
68 } | |
69 | |
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); | |
77 } | |
78 #else | |
79 SID_IDENTIFIER_AUTHORITY* sia = ::GetSidIdentifierAuthority(sid); | |
80 | |
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]; | |
92 } | |
93 base::SStringPrintf(&sid_string, L"S-%d-%lu", SID_REVISION, authority); | |
94 } | |
95 | |
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 | |
100 | |
101 return sid_string; | |
102 } | |
103 | |
104 } // namespace | |
105 | |
106 bool GetRawMachineId(string16* sid_string, int* volume_id) { | |
107 // Calculate the Windows SID. | |
108 | |
109 wchar_t computer_name[MAX_COMPUTERNAME_LENGTH + 1] = {0}; | |
110 DWORD size = arraysize(computer_name); | |
111 | |
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); | |
117 } | |
118 } | |
119 | |
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; | |
125 } | |
126 | |
127 return true; | |
128 } | |
129 | |
130 } // namespace rlz_lib | |
OLD | NEW |