15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h> 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <Sddl.h> // For ConvertSidToStringSidW. 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string16.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "rlz/lib/assert.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace rlz_lib { 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetSystemVolumeSerialNumber(int* number) { 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!number) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *number = 0; 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Find the system root path (e.g: C:\). 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wchar_t system_path[MAX_PATH + 1]; 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetSystemDirectoryW(system_path, MAX_PATH)) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wchar_t* first_slash = wcspbrk(system_path, L"\\/"); 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (first_slash != NULL) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *(first_slash + 1) = 0; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD number_local = 0; 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetVolumeInformationW(system_path, NULL, 0, &number_local, NULL, NULL, 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, 0)) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *number = number_local; 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetComputerSid(const wchar_t* account_name, SID* sid, DWORD sid_size) { 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const DWORD kStartDomainLength = 128; // reasonable to start with 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<wchar_t[]> domain_buffer(new wchar_t[kStartDomainLength]); 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD domain_size = kStartDomainLength; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD sid_dword_size = sid_size; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SID_NAME_USE sid_name_use; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BOOL success = ::LookupAccountNameW(NULL, account_name, sid, 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &sid_dword_size, domain_buffer.get(), 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &domain_size, &sid_name_use); 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!success && ::GetLastError() == ERROR_INSUFFICIENT_BUFFER) { 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We could have gotten the insufficient buffer error because 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // one or both of sid and szDomain was too small. Check for that 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // here. 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sid_dword_size > sid_size) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (domain_size > kStartDomainLength) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) domain_buffer.reset(new wchar_t[domain_size]); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) success = ::LookupAccountNameW(NULL, account_name, sid, &sid_dword_size, 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) domain_buffer.get(), &domain_size, 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &sid_name_use); 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return success != FALSE; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::wstring ConvertSidToString(SID* sid) { 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::wstring sid_string; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if _WIN32_WINNT >= 0x500 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wchar_t* sid_buffer = NULL; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ConvertSidToStringSidW(sid, &sid_buffer)) { 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sid_string = sid_buffer; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LocalFree(sid_buffer); 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SID_IDENTIFIER_AUTHORITY* sia = ::GetSidIdentifierAuthority(sid); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if(sia->Value[0] || sia->Value[1]) { 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::SStringPrintf( 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &sid_string, L"S-%d-0x%02hx%02hx%02hx%02hx%02hx%02hx", 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SID_REVISION, (USHORT)sia->Value[0], (USHORT)sia->Value[1], 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (USHORT)sia->Value[2], (USHORT)sia->Value[3], (USHORT)sia->Value[4], 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (USHORT)sia->Value[5]); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ULONG authority = 0; 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 2; i < 6; ++i) { 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) authority <<= 8; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) authority |= sia->Value[i]; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::SStringPrintf(&sid_string, L"S-%d-%lu", SID_REVISION, authority); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int sub_auth_count = *::GetSidSubAuthorityCount(sid); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for(int i = 0; i < sub_auth_count; ++i) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StringAppendF(&sid_string, L"-%lu", *::GetSidSubAuthority(sid, i)); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return sid_string; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool GetRawMachineId(base::string16* sid_string, int* volume_id) { 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Calculate the Windows SID. 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wchar_t computer_name[MAX_COMPUTERNAME_LENGTH + 1] = {0}; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD size = arraysize(computer_name); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (GetComputerNameW(computer_name, &size)) { 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char sid_buffer[SECURITY_MAX_SID_SIZE]; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SID* sid = reinterpret_cast<SID*>(sid_buffer); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (GetComputerSid(computer_name, sid, SECURITY_MAX_SID_SIZE)) { 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *sid_string = ConvertSidToString(sid); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the system drive volume serial number. 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *volume_id = 0; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetSystemVolumeSerialNumber(volume_id)) { 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_STRING("GetMachineId: Failed to retrieve volume serial number"); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *volume_id = 0; 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace rlz_lib 131