machine_id_win.cc 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  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. #include <windows.h>
  5. #include <Sddl.h> // For ConvertSidToStringSidW.
  6. #include <memory>
  7. #include <string>
  8. #include "base/strings/utf_string_conversions.h"
  9. #include "rlz/lib/assert.h"
  10. namespace rlz_lib {
  11. namespace {
  12. bool GetSystemVolumeSerialNumber(int* number) {
  13. if (!number)
  14. return false;
  15. *number = 0;
  16. // Find the system root path (e.g: C:\).
  17. wchar_t system_path[MAX_PATH + 1];
  18. if (!GetSystemDirectoryW(system_path, MAX_PATH))
  19. return false;
  20. wchar_t* first_slash = wcspbrk(system_path, L"\\/");
  21. if (first_slash != NULL)
  22. *(first_slash + 1) = 0;
  23. DWORD number_local = 0;
  24. if (!GetVolumeInformationW(system_path, NULL, 0, &number_local, NULL, NULL,
  25. NULL, 0))
  26. return false;
  27. *number = number_local;
  28. return true;
  29. }
  30. bool GetComputerSid(const wchar_t* account_name, SID* sid, DWORD sid_size) {
  31. static const DWORD kStartDomainLength = 128; // reasonable to start with
  32. std::unique_ptr<wchar_t[]> domain_buffer(new wchar_t[kStartDomainLength]);
  33. DWORD domain_size = kStartDomainLength;
  34. DWORD sid_dword_size = sid_size;
  35. SID_NAME_USE sid_name_use;
  36. BOOL success = ::LookupAccountNameW(NULL, account_name, sid,
  37. &sid_dword_size, domain_buffer.get(),
  38. &domain_size, &sid_name_use);
  39. if (!success && ::GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
  40. // We could have gotten the insufficient buffer error because
  41. // one or both of sid and szDomain was too small. Check for that
  42. // here.
  43. if (sid_dword_size > sid_size)
  44. return false;
  45. if (domain_size > kStartDomainLength)
  46. domain_buffer.reset(new wchar_t[domain_size]);
  47. success = ::LookupAccountNameW(NULL, account_name, sid, &sid_dword_size,
  48. domain_buffer.get(), &domain_size,
  49. &sid_name_use);
  50. }
  51. return success != FALSE;
  52. }
  53. std::u16string ConvertSidToString(SID* sid) {
  54. std::wstring sid_string;
  55. wchar_t* sid_buffer = NULL;
  56. if (ConvertSidToStringSidW(sid, &sid_buffer)) {
  57. sid_string = sid_buffer;
  58. LocalFree(sid_buffer);
  59. }
  60. return base::WideToUTF16(sid_string);
  61. }
  62. } // namespace
  63. bool GetRawMachineId(std::u16string* sid_string, int* volume_id) {
  64. // Calculate the Windows SID.
  65. wchar_t computer_name[MAX_COMPUTERNAME_LENGTH + 1] = {0};
  66. DWORD size = std::size(computer_name);
  67. if (GetComputerNameW(computer_name, &size)) {
  68. char sid_buffer[SECURITY_MAX_SID_SIZE];
  69. SID* sid = reinterpret_cast<SID*>(sid_buffer);
  70. if (GetComputerSid(computer_name, sid, SECURITY_MAX_SID_SIZE)) {
  71. *sid_string = ConvertSidToString(sid);
  72. }
  73. }
  74. // Get the system drive volume serial number.
  75. *volume_id = 0;
  76. if (!GetSystemVolumeSerialNumber(volume_id)) {
  77. ASSERT_STRING("GetMachineId: Failed to retrieve volume serial number");
  78. *volume_id = 0;
  79. }
  80. return true;
  81. }
  82. } // namespace rlz_lib