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 |