Серийный номер жесткого диска перевернулся каждые 2 байта в Windows XP, Vista и 7, но не в Windows 8
Мне нужно получить серийный номер жесткого диска, чтобы использовать его в качестве ключа для лицензирования программного обеспечения.
Я использовал diskid32 код в этом URL: http://www.winsim.com/diskid32/diskid32.html
Он использовал DeviceIoControl Win32 API с кодом управления IO IOCTL_STORAGE_QUERY_PROPERTY.
Это сработало. Однако, когда я дважды проверяю фактический серийный номер, напечатанный на самом жестком диске, я обнаружил, что каждые 2 байта числа были перевернуты.
Простым решением может быть просто перевернуть байты назад. Он работал в Windows XP, Vista и 7, но в Windows 8 не нужно переворачиваться!
Я хочу знать точную причину, по которой байты были перевернуты в Windows XP, Vista и 7, и почему бы не перевернуть в Windows 8. Что относительно следующей Windows?
Часть кода с незначительными изменениями:
int drive = 0;
HANDLE hPhysicalDriveIOCTL = 0;
char driveName [256];
sprintf (driveName, "\\\\.\\PhysicalDrive%d", drive);
// Windows NT, Windows 2000, Windows XP - admin rights not required
hPhysicalDriveIOCTL = CreateFile (driveName, 0,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, 0, NULL);
if (hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
{
_STORAGE_PROPERTY_QUERY query;
DWORD cbBytesReturned = 0;
char buffer [10000];
memset ((void *) & query, 0, sizeof (query));
query.PropertyId = StorageDeviceProperty;
query.QueryType = PropertyStandardQuery;
memset (buffer, 0, sizeof (buffer));
if ( DeviceIoControl (hPhysicalDriveIOCTL, IOCTL_STORAGE_QUERY_PROPERTY,
& query,
sizeof (query),
& buffer,
sizeof (buffer),
& cbBytesReturned, NULL) )
{
_STORAGE_DEVICE_DESCRIPTOR * descrip = (_STORAGE_DEVICE_DESCRIPTOR *) & buffer;
char serialNumber [1000];
char modelNumber [1000];
char vendorId [1000];
char productRevision [1000];
flipAndCodeBytes (buffer,
descrip -> SerialNumberOffset,
1, serialNumber );
...
}
Ответы
Ответ 1
Я использую тот же подход (и тот же код) в моем лицензировании программного обеспечения. Да, Windows 8 по какой-то причине возвращает измененные значения для этого метода, я не могу сказать, почему (поэтому я не могу ответить на ваш вопрос).
Мое решение - это тот, который вы указали: снова переверните значения.
Итак, после вызова "flipAndCodeBytes" вы можете проверить, есть ли ОС Windows 8, и перевернуть значения.
В моем случае он работает сейчас (я получил те же значения для Windows XP/Vista/7 и Windows 8).
Удачи!
Ответ 2
Просто выключите флип, используя флаг "flip" функции flibAndCodeBytes, когда Windows 8 или больше.
bool shoulFlipBytes = true;
if(IsWin8OrLater()) shouldFlipBytes = false;
flipAndCodeBytes(buffer,
descrip->SerialNumberOffset,
shouldFlipBytes,
serialNumber);
Вы можете использовать это для проверки версии Windows:
#include <windows.h>
bool IsWin8OrLater() {
DWORD version = GetVersion();
DWORD major = (DWORD) (LOBYTE(LOWORD(version)));
DWORD minor = (DWORD) (HIBYTE(LOWORD(version)));
return (major > 6) || ((major == 6) && (minor >= 2));
}
Согласно http://msdn.microsoft.com/en-us/library/ms724832%28VS.85%29.aspx
(Благодаря ChrisV Определите, является ли O/S Windows 7)
Ответ 3
В основном вы полагаетесь на данные, которые не являются строго надежными для начала. Приводы могут меняться в течение всего срока службы компьютера; все время получая точно правильный серийный номер, даже не важно для вашего продукта.
Один простой хак, о котором я могу думать, это нормализовать серийный номер, например. путем сортировки цифр; это заставит больше дисков выглядеть одинаково, но я сомневаюсь, что это станет проблемой.
Другой способ взглянуть на проблему заключается в том, что приложение должно предусматривать изменения серийного номера; пользователь может быть проинформирован о проблеме лицензирования (по каким-либо причинам) и попросил связаться с отделом поддержки с помощью сгенерированного кода (не обязательно самого серийного номера). Учитывая этот код, поддержка может затем создать новую лицензию для клиента.
Ответ 4
Кажется, вам нужно проверить версию Windows через API и добавить if() в ваш код, если версия достаточно высока
Мои разработчики нашли другую проблему с этим методом - такой код IOCtl полагается на программу, которая запускается с правами администратора на Win7\Win8+. В связи с нашим программным обеспечением это сервис, который запускается с правами системы и клиентским программным обеспечением, которое строго выполняется с правами пользователя
Ответ 5
Для целей проверки лицензий вам все равно. Все, что вам нужно знать, это то, что некоторые конфигурации приводят к перевороту, некоторые - нет, и это может измениться в течение срока действия лицензии.
Так что принимайте оба варианта:
string serial = get_serial();
if (license_check(serial)) {
licensed = true;
return;
}
serial = swap_bytes(serial);
if (license_check(serial)) {
licensed = true;
return;
}
(Я вижу, что Раймонд предложил это в комментарии)
Отсутствует хрупкая проверка ОС, не стоит беспокоиться о том, не удалось ли она щелкнуть, когда пользователь подал заявку на получение лицензии. Просто счастливые пользователи.