Ir al contenido



Foto

Número de serie de una unidad de disco USB


  • Por favor identifícate para responder
8 respuestas en este tema

#1 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 3.943 mensajes
  • LocationMadrid - España

Escrito 23 octubre 2016 - 12:19

Obtener el número de serie de una unidad USB es un tema buscado en las redes y muy mal documentado. En principio podríamos suponer que la tarea puede hacerse fácilmente con DeviceIoControl IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER, pero la realidad es que falla para las unidades de disco USB. cHackAll escribió hace unos años un código que se basaba el leer el registro para encontrar esa información, pero en los actuales S.O. no funciona correctamente. Con motivo de una pregunta en CD, me acordé del antiguo código de cHackAll y me propuse revisar el tema. El código que propongo se basa en la lectura del registro y en verificar si la unidad está "pinchada" en nuestro PC.

 

El código está probado en WinXP y Win10.

 

En realidad es una información muy poco útil salvo para aquellos que quieran proteger sus creaciones con una mochila basada en un pendrive.

 

Este es el código:


delphi
  1. var
  2.  Device: ShortString;
  3.  ValueName: array [0..15] of Char = '\DosDevices\\:';
  4.  
  5.  
  6. const
  7.  IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS  = $00560000;
  8.  
  9. // Encuentra el número de disco físico que corresponde a una letra de unidad
  10. function GetPhysicalNumOfDrive(Volume: Char): integer;
  11. var
  12.   hFile: THandle;
  13.   Vde: array [0..56] of BYTE;   // VOLUME_DISK_EXTENTS
  14.   BytesReturned: Cardinal;
  15. begin
  16.   Result:= -1;
  17.   hFile:= CreateFile(PAnsiChar('\\.\' + Volume + ':'),0,0,nil, OPEN_EXISTING, 0, 0);
  18.   if hFile <> INVALID_HANDLE_VALUE then
  19.   begin
  20.     if DeviceIoControl(hFile, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, nil, 0, @Vde, SizeOf(Vde), BytesReturned, nil) then
  21.       Result:= PBYTE(DWORD(@Vde)+8)^;
  22.     CloseHandle(hFile);
  23.   end;
  24. end;
  25.  
  26. // Encuentra el número de serie de una letra de unidad para Win10
  27. function GetUSBSerial10(Drive: Char; var SerialNumber: ShortString): LongBool;
  28. var
  29.   hKey: Windows.HKEY;
  30.   Device: ShortString;
  31.   ValueName: array [0..15] of Char;
  32.   Index: Integer;
  33.   Value: Char;
  34.   Size: DWORD;
  35.   i: integer;
  36.   ValueType: DWORD;
  37. begin
  38.   ValueType:= 3;
  39.   Size:= SizeOf(Device);
  40.   Result := False;
  41.   lstrcpy(ValueName, '\DosDevices\\:');
  42.   ValueName[12] := Drive;
  43.   RegOpenKey(HKEY_LOCAL_MACHINE, 'SYSTEM\MountedDevices', hKey);
  44.   i:= RegQueryValueEx(hKey, @ValueName, nil, @ValueType{REG_BINARY}, @Device, @Size);
  45.   RegCloseKey(hKey);
  46.   if i = 0 then
  47.   begin
  48.     i:= SizeOf(Device);
  49.     repeat  dec(i); until Device[i] = '&';  Device[i]:= #0;
  50.     repeat  dec(i); until Device[i] = '#';
  51.     Index := 1;
  52.     repeat
  53.       Value := Device[i + Index * 2];
  54.       SerialNumber[Index]:= Value;
  55.       inc(Index);
  56.     until Value = #0;
  57.     SerialNumber[0]:= CHAR(lstrlen(@SerialNumber[1]));
  58.     Result:= SerialNumber[1] <> #0;
  59.   end;
  60. end;
  61.  
  62. // Modificado del código de cHackAll
  63. function Search(hParent: HKEY; var SubKey: ShortString): LongBool;
  64. var
  65.  hChild: HKEY;
  66.  Index: Cardinal;
  67.  Data: ShortString;
  68.  Size: DWORD;
  69.  ValueType: DWORD;
  70. begin
  71.  ValueType:= 1; //REG_SZ
  72.  Size:= SizeOf(Device);
  73.  Index := 0;
  74.  RegOpenKey(hParent, @SubKey[1], hChild);
  75.  RegQueryValueEx(hChild, 'ParentIdPrefix', nil, @ValueType, @Data[0], @Size);
  76.  Result := not LongBool(lstrcmp(@Data, @Device));
  77.  while not Result and (RegEnumKey(hChild, Index, @SubKey[1], SizeOf(SubKey) - 1) = ERROR_SUCCESS) do
  78.   begin
  79.    Result := Search(hChild, SubKey);
  80.    Inc(Index);
  81.   end;
  82.  RegCloseKey(hChild);
  83. end;
  84.  
  85. // Modificado del código de cHackAll
  86. function usbGetSerial(Drive: Char; var SerialNumber: ShortString): LongBool;
  87. var
  88.  lpSerialNumber: PChar;
  89.  hKey: Windows.HKEY;
  90.  Index: Integer;
  91.  Value: Char;
  92.  Size: DWORD;
  93.  i: integer;
  94.  ValueType: DWORD;
  95. begin
  96.  ValueType:= 3;
  97.  Size:= SizeOf(Device);
  98.  Result := False;
  99.  ValueName[12] := Drive;
  100.  i:= RegOpenKey(HKEY_LOCAL_MACHINE, 'SYSTEM\MountedDevices', hKey);
  101.  RegQueryValueEx(hKey, @ValueName, nil, @ValueType{REG_BINARY}, @Device, @Size);
  102.  RegCloseKey(hKey);
  103.  
  104.  Index := 0;
  105.  repeat if Device[(Index + 3) * 2 + 54] <> '#' then
  106.   Value := Device[Index * 2 + 54] else Value := #0;
  107.   Device[Index] := Value;
  108.   Inc(Index);
  109.  until Value = #0;
  110.  SerialNumber[0] := #0;
  111.  lstrcpy(@SerialNumber[1], 'SYSTEM\CurrentControlSet\Enum\USBSTOR');
  112.  if (Device[0] <> #0) and Search(HKEY_LOCAL_MACHINE, SerialNumber) then
  113.   begin
  114.    lpSerialNumber := @SerialNumber[1];
  115.    repeat Inc(SerialNumber[0]);
  116.     Inc(lpSerialNumber);
  117.     if lpSerialNumber[0] = '&' then
  118.      lpSerialNumber[0] := #0;
  119.    until lpSerialNumber[0] = #0;
  120.    Result := True;
  121.   end;
  122. end;
  123.  
  124. function GetSOVersion: integer;
  125. var
  126.   VerInfo: TOSVersioninfo;
  127. begin
  128.   VerInfo.dwOSVersionInfoSize:= SizeOf(TOSVersionInfo);
  129.   GetVersionEx(VerInfo);
  130.   Result:= VerInfo.dwMajorVersion; // 5 es XP, mayor vista...
  131. end;
  132.  
  133. function GetUSBSerial(Drive: Char; var SerialNumber: ShortString): LongBool;
  134. begin
  135.   if(GetSOVersion > 5) then
  136.     Result:= GetUSBSerial10(Drive, SerialNumber)
  137.   else
  138.     Result:= usbGetSerial(Drive, SerialNumber);
  139. end;

Y un ejemplo de uso:


delphi
  1. procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
  2. var
  3. SerialNumber: ShortString;
  4. begin
  5. Edit1.Text:='';
  6. Label1.Caption:= '';
  7. if GetPhysicalNumOfDrive(Key) <> -1 then
  8. begin
  9. GetUSBSerial(Key, SerialNumber);
  10. Label1.Caption:= SerialNumber;
  11. end
  12. else MessageBox(Handle, 'Unmounted drive', 'Error', MB_ICONEXCLAMATION);
  13. end;

Subo un proyecto completo con el ejemplo.

 

Saludos.

Archivos adjuntos


  • 5

#2 FerCastro

FerCastro

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 627 mensajes
  • LocationCiudad de México

Escrito 24 octubre 2016 - 10:45

Mi estimado Escafandra, aplausos!! y me paro de pié.

 

Eres un master, muchas gracias por este codigo.


  • 0

#3 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.111 mensajes
  • LocationMéxico

Escrito 24 octubre 2016 - 11:46

Como siempre un código de mucha utilidad, muchas gracias amigo. (y)

 

Saludos


  • 0

#4 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 3.943 mensajes
  • LocationMadrid - España

Escrito 25 octubre 2016 - 05:18

Por si fuera de interés, os muestro otra forma de obtener el número de serie que también trabaja con HD pero que no me convence porque no encuentra los números de serie USB en WinXP en las memorias que he probado y en Win10, al menos en una de ellas, cambia el último dígito del mismo al compararlo con el dato encontrado en el registro de Windows.


delphi
  1. const
  2. IOCTL_STORAGE_QUERY_PROPERTY = $2D1400;
  3.  
  4. type
  5. PSTORAGE_DEVICE_DESCRIPTOR = ^STORAGE_DEVICE_DESCRIPTOR;
  6. STORAGE_DEVICE_DESCRIPTOR = packed record
  7. Version: ULONG;
  8. Size: ULONG;
  9. DeviceType: UCHAR;
  10. DeviceTypeModifier: UCHAR;
  11. RemovableMedia: Boolean;
  12. CommandQueueing: Boolean;
  13. VendorIdOffset: ULONG;
  14. ProductIdOffset: ULONG;
  15. ProductRevisionOffset: ULONG;
  16. SerialNumberOffset: ULONG;
  17. BusType: ULONG;
  18. RawPropertiesLength: ULONG;
  19. RawDeviceProperties: array[0..0] of UCHAR;
  20. end;
  21.  
  22. PSTORAGE_PROPERTY_QUERY = ^STORAGE_PROPERTY_QUERY;
  23. STORAGE_PROPERTY_QUERY = record
  24.   PropertyId: DWORD;     // StorageDeviceProperty = 0
  25.   QueryType: DWORD;      // PropertyStandardQuery = 0
  26. AdditionalParameters: array[0..0] of UCHAR;
  27. end;
  28.  
  29. function GetSerialNumber(Volume: Char; var SerialNumber: string): BOOL;
  30. var
  31. hFile: THANDLE;
  32. SPQ: STORAGE_PROPERTY_QUERY;
  33. SDD: STORAGE_DEVICE_DESCRIPTOR;
  34. PSDD: PSTORAGE_DEVICE_DESCRIPTOR;
  35. Size: DWORD;
  36. begin
  37. Result:= FALSE;
  38. SerialNumber:= '';
  39. hFile:= CreateFile(PAnsiChar('\\.\' + Volume + ':'),0,0,nil, OPEN_EXISTING, 0, 0);
  40. if hFile <> INVALID_HANDLE_VALUE then
  41. begin
  42. ZeroMemory(@SPQ, sizeof(SPQ));
  43. if DeviceIoControl(hFile, IOCTL_STORAGE_QUERY_PROPERTY, @SPQ, sizeof(SPQ), @SDD, sizeof(SDD), Size, nil) then
  44. begin
  45. PSDD:= VirtualAlloc(nil, SDD.Size, MEM_COMMIT, PAGE_READWRITE);
  46. ZeroMemory(PSDD, SDD.Size);
  47. if DeviceIoControl(hFile, IOCTL_STORAGE_QUERY_PROPERTY, @SPQ, sizeof(SPQ), PSDD, SDD.Size, Size, nil) then
  48. begin
  49. if PSDD.SerialNumberOffset <> 0 then
  50. SerialNumber:= String(PCHAR(PSDD) + PSDD.SerialNumberOffset);
  51. end;
  52. VirtualFree(PSDD, 0, MEM_RELEASE);
  53. end;
  54. CloseHandle(hFile);
  55. end;
  56. Result:= Length(SerialNumber) <> 0;
  57. end;

Saludos.


  • 2

#5 cram

cram

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 824 mensajes
  • LocationMisiones, Argentina

Escrito 26 octubre 2016 - 07:25

Muchas gracias por semejante aporte.

 

Es de gran utilidad, tanto para estudio como para aplicación.

 

Saludos Maestro!!


  • 0

#6 jmonfor

jmonfor

    Member

  • Miembros
  • PipPip
  • 20 mensajes

Escrito 06 noviembre 2016 - 03:35

Impresionante. Realmente te das cuenta de cúanto hay por aprender... y en este foro sois todos unos fenómenos!!!

Muchas gracias por el aporte!!!

 

Saludos :ap:


  • 0

#7 monchito_elroro

monchito_elroro

    Advanced Member

  • Miembros
  • PipPipPip
  • 254 mensajes

Escrito 14 noviembre 2016 - 01:24

Muchas gracias amigo Escafranda por compartir un excelente aporte, lo acabo de probar en lazarus y trabaja sin problemas, también quería comentar que le he agreado unos códigos para detectar también los seriales para los disco duros (Fijos y USB mediante la letra de su unidad) acontinuación les comparto el enlace para que lo bajen:

 

http://www.mediafire...ial Lazarus.zip

 

Quisiera también hacer una consulta si se puede al Amigo escafranda:
Lo que pasa es que en el caso del código que agregue para los seriales de los discos duros, si en caso estos discos son formateados los seriales cambian por unos nuevos, al menos eso fue lo que leí por ahí.
Mi pregunta es si en caso el USB lo llevo a otra pc, me dará el mismo serial que me dio al principio ? Pues probe formateando el usb y aún así me da el mismo serial, lo cual es perfecto, pero también quisiera saber si al conectarlo a otra computadora me seguirá dando el mismo serial o me dará uno nuevo.

Esperando su respuesta me despido amigos :)


  • 0

#8 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 3.943 mensajes
  • LocationMadrid - España

Escrito 14 noviembre 2016 - 03:39

El problema es que la API GetVolumeInformation no devuelve el número de serie del fabricante sino el del formateo y varía si vuelves a formatear.

GetVolumeInformation function

lpVolumeSerialNumber [out, optional]

A pointer to a variable that receives the volume serial number.
This parameter can be NULL if the serial number is not required.
This function returns the volume serial number that the operating system assigns when a hard disk is formatted. To programmatically obtain the hard disk's serial number that the manufacturer assigns, use the Windows Management Instrumentation (WMI) Win32_PhysicalMedia property SerialNumber.

 

El código que expuse para USB devuelve en número de serie del fabricante del pendrive y el de este mensaje, sirve para HD y USB aunque falla en bastantes USB, tambien devuelve el número de serie del fabricante. El segundo enlace está más indicado para HD aunque es posible que en algunos falle.


Saludos.


  • 0

#9 monchito_elroro

monchito_elroro

    Advanced Member

  • Miembros
  • PipPipPip
  • 254 mensajes

Escrito 14 noviembre 2016 - 02:32

Muchas gracias amigo escafranda por su respuesta :) siguiendo sus sugerencias he agregado el código que también compartió para los discos duros, en el camino me salió un par de errores, pero pude solucionarlos siguiendo sus consejos de proyectos anteriores, ahora le mando como estoy usando su código amigo: (por favor corregirme si es necesario)

delphi
  1. unit Unit1;
  2.  
  3. interface
  4.  
  5. uses
  6.   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  7.   Dialogs, StdCtrls;
  8.  
  9. type
  10.  
  11.   { TForm1 }
  12.  
  13.   TForm1 = class(TForm)
  14.     Edit2: TEdit;
  15.     Label1: TLabel;
  16.     Edit1: TEdit;
  17.     Label2: TLabel;
  18.     Label3: TLabel;
  19.     procedure Button1Click(Sender: TObject);
  20.     procedure Edit1KeyPress(Sender: TObject; var Key: Char);
  21.     procedure FormCreate(Sender: TObject);
  22.   private
  23.     { Private declarations }
  24.   public
  25.     { Public declarations }
  26.   end;
  27.  
  28. function  StrStrI(s1: PCHAR; s2: PCHAR): PCHAR; stdcall; external 'Shlwapi.dll' name 'StrStrIA';
  29.  
  30. var
  31.   Form1: TForm1;
  32.  
  33. implementation
  34. {$R *.lfm}
  35.  
  36. var
  37.  Device: ShortString;
  38.  ValueName: array [0..15] of Char = '\DosDevices\\:';
  39.  
  40.  
  41. const
  42.  IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS  = $00560000;
  43.  IOCTL_STORAGE_QUERY_PROPERTY = $2D1400;
  44.  
  45.  type
  46. PSTORAGE_DEVICE_DESCRIPTOR = ^STORAGE_DEVICE_DESCRIPTOR;
  47. STORAGE_DEVICE_DESCRIPTOR = packed record
  48.   Version: ULONG;
  49.   Size: ULONG;
  50.   DeviceType: UCHAR;
  51.   DeviceTypeModifier: UCHAR;
  52.   RemovableMedia: Boolean;
  53.   CommandQueueing: Boolean;
  54.   VendorIdOffset: ULONG;
  55.   ProductIdOffset: ULONG;
  56.   ProductRevisionOffset: ULONG;
  57.   SerialNumberOffset: ULONG;
  58.   BusType: ULONG;
  59.   RawPropertiesLength: ULONG;
  60.   RawDeviceProperties: array[0..0] of UCHAR;
  61. end;
  62.  
  63. PSTORAGE_PROPERTY_QUERY = ^STORAGE_PROPERTY_QUERY;
  64. STORAGE_PROPERTY_QUERY = record
  65.   PropertyId: DWORD;     // StorageDeviceProperty = 0
  66.   QueryType: DWORD;      // PropertyStandardQuery = 0
  67.   AdditionalParameters: array[0..0] of UCHAR;
  68. end;
  69.  
  70. // encuentra el serial del disco duro físico
  71. function GetSerialNumber(Volume: Char; var SerialNumber: string): BOOL;
  72. var
  73.   hFile: THANDLE;
  74.   SPQ: STORAGE_PROPERTY_QUERY;
  75.   SDD: STORAGE_DEVICE_DESCRIPTOR;
  76.   PSDD: PSTORAGE_DEVICE_DESCRIPTOR;
  77.   Size: DWORD;
  78. begin
  79.   Result:= FALSE;
  80.   SerialNumber:= '';
  81.   hFile:= CreateFile(PAnsiChar('\\.\' + Volume + ':'),0,0,nil, OPEN_EXISTING, 0, 0);
  82.   if hFile <> INVALID_HANDLE_VALUE then
  83.   begin
  84.     ZeroMemory(@SPQ, sizeof(SPQ));
  85.     if DeviceIoControl(hFile, IOCTL_STORAGE_QUERY_PROPERTY, @SPQ, sizeof(SPQ), @SDD, sizeof(SDD), Size, nil) then
  86.     begin
  87.       PSDD:= VirtualAlloc(nil, SDD.Size, MEM_COMMIT, PAGE_READWRITE);
  88.       ZeroMemory(PSDD, SDD.Size);
  89.       if DeviceIoControl(hFile, IOCTL_STORAGE_QUERY_PROPERTY, @SPQ, sizeof(SPQ), PSDD, SDD.Size, Size, nil) then
  90.       begin
  91.  
  92.         if PSDD^.SerialNumberOffset <> 0 then
  93.           SerialNumber:= String(PCHAR(PSDD) + PSDD^.SerialNumberOffset);
  94.       end;
  95.       VirtualFree(PSDD, 0, MEM_RELEASE);
  96.     end;
  97.     CloseHandle(hFile);
  98.   end;
  99.   Result:= Length(SerialNumber) <> 0;
  100. end;
  101.  
  102. // Encuentra el número de disco físico que corresponde a una letra de unidad
  103. function GetPhysicalNumOfDrive(Volume: Char): integer;
  104. var
  105.   hFile: THandle;
  106.   Vde: array [0..56] of BYTE;   // VOLUME_DISK_EXTENTS
  107.   BytesReturned: Cardinal;
  108. begin
  109.   Result:= -1;
  110.   hFile:= CreateFile(PAnsiChar('\\.\' + Volume + ':'),0,0,nil, OPEN_EXISTING, 0, 0);
  111.   if hFile <> INVALID_HANDLE_VALUE then
  112.   begin
  113.     if DeviceIoControl(hFile, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, nil, 0, @Vde, SizeOf(Vde), BytesReturned, nil) then
  114.       Result:= PBYTE(DWORD(@Vde)+8)^;
  115.     CloseHandle(hFile);
  116.   end;
  117. end;
  118.  
  119. // Encuentra el número de serie de una letra de unidad para Win10
  120. function GetUSBSerial10(Drive: Char; var SerialNumber: ShortString): LongBool;
  121. var
  122.   hKey: Windows.HKEY;
  123.   Device: ShortString;
  124.   ValueName: array [0..15] of Char;
  125.   Index: Integer;
  126.   Value: Char;
  127.   Size: DWORD;
  128.   i: integer;
  129.   ValueType: DWORD;
  130. begin
  131.   ValueType:= 3;
  132.   Size:= SizeOf(Device);
  133.   Result := False;
  134.   lstrcpy(ValueName, '\DosDevices\\:');
  135.   ValueName[12] := Drive;
  136.   RegOpenKey(HKEY_LOCAL_MACHINE, 'SYSTEM\MountedDevices', hKey);
  137.   i:= RegQueryValueEx(hKey, @ValueName, nil, @ValueType{REG_BINARY}, @Device, @Size);
  138.   RegCloseKey(hKey);
  139.   if i = 0 then
  140.   begin
  141.     i:= SizeOf(Device);
  142.     repeat  dec(i); until Device[i] = '&';  Device[i]:= #0;
  143.     repeat  dec(i); until Device[i] = '#';
  144.     Index := 1;
  145.     repeat
  146.       Value := Device[i + Index * 2];
  147.       SerialNumber[Index]:= Value;
  148.       inc(Index);
  149.     until Value = #0;
  150.     SerialNumber[0]:= CHAR(lstrlen(@SerialNumber[1]));
  151.     Result:= SerialNumber[1] <> #0;
  152.     //Result:= Length(SerialNumber) <> 0;
  153.   end;
  154. end;
  155.  
  156. // Modificado del código de cHackAll
  157. function Search(hParent: HKEY; var SubKey: ShortString): LongBool;
  158. var
  159.  hChild: HKEY;
  160.  Index: Cardinal;
  161.  Data: ShortString;
  162.  Size: DWORD;
  163.  ValueType: DWORD;
  164. begin
  165.  ValueType:= 1; //REG_SZ
  166.  Size:= SizeOf(Device);
  167.  Index := 0;
  168.  RegOpenKey(hParent, @SubKey[1], hChild);
  169.  RegQueryValueEx(hChild, 'ParentIdPrefix', nil, @ValueType, @Data[0], @Size);
  170.  Result := not LongBool(lstrcmp(@Data, @Device));
  171.  while not Result and (RegEnumKey(hChild, Index, @SubKey[1], SizeOf(SubKey) - 1) = ERROR_SUCCESS) do
  172.   begin
  173.    Result := Search(hChild, SubKey);
  174.    Inc(Index);
  175.   end;
  176.  RegCloseKey(hChild);
  177. end;
  178.  
  179. // Modificado del código de cHackAll
  180. function usbGetSerial(Drive: Char; var SerialNumber: ShortString): LongBool;
  181. var
  182.  lpSerialNumber: PChar;
  183.  hKey: Windows.HKEY;
  184.  Index: Integer;
  185.  Value: Char;
  186.  Size: DWORD;
  187.  i: integer;
  188.  ValueType: DWORD;
  189. begin
  190.  ValueType:= 3;
  191.  Size:= SizeOf(Device);
  192.  Result := False;
  193.  ValueName[12] := Drive;
  194.  i:= RegOpenKey(HKEY_LOCAL_MACHINE, 'SYSTEM\MountedDevices', hKey);
  195.  RegQueryValueEx(hKey, @ValueName, nil, @ValueType{REG_BINARY}, @Device, @Size);
  196.  RegCloseKey(hKey);
  197.  
  198.  Index := 0;
  199.  repeat if Device[(Index + 3) * 2 + 54] <> '#' then
  200.   Value := Device[Index * 2 + 54] else Value := #0;
  201.   Device[Index] := Value;
  202.   Inc(Index);
  203.  until Value = #0;
  204.  SerialNumber[0] := #0;
  205.  lstrcpy(@SerialNumber[1], 'SYSTEM\CurrentControlSet\Enum\USBSTOR');
  206.  if (Device[0] <> #0) and Search(HKEY_LOCAL_MACHINE, SerialNumber) then
  207.   begin
  208.    lpSerialNumber := @SerialNumber[1];
  209.    repeat Inc(SerialNumber[0]);
  210.     Inc(lpSerialNumber);
  211.     if lpSerialNumber[0] = '&' then
  212.      lpSerialNumber[0] := #0;
  213.    until lpSerialNumber[0] = #0;
  214.    Result := True;
  215.   end;
  216. end;
  217.  
  218. function GetSOVersion: integer;
  219. var
  220.   VerInfo: TOSVersioninfo;
  221. begin
  222.   VerInfo.dwOSVersionInfoSize:= SizeOf(TOSVersionInfo);
  223.   GetVersionEx(VerInfo);
  224.   Result:= VerInfo.dwMajorVersion; // 5 es XP, mayor vista...
  225. end;
  226.  
  227. function GetUSBSerial(Drive: Char; var SerialNumber: ShortString): LongBool;
  228. begin
  229.   if(GetSOVersion > 5) then
  230.     Result:= GetUSBSerial10(Drive, SerialNumber)
  231.   else
  232.     Result:= usbGetSerial(Drive, SerialNumber);
  233. end;
  234.  
  235. function GetHardDiskSerial(const DriveLetter: Char): string;
  236. var
  237.   NotUsed:     DWORD;
  238.   VolumeFlags: DWORD;
  239.   VolumeInfo:  array[0..MAX_PATH] of Char;
  240.   VolumeSerialNumber: DWORD;
  241. begin
  242.   GetVolumeInformation(PChar(DriveLetter + ':\'),
  243.     nil, SizeOf(VolumeInfo), @VolumeSerialNumber, NotUsed,
  244.     VolumeFlags, nil, 0);
  245.   {Result := Format('Label = %s   VolSer = %8.8X',
  246.     [VolumeInfo, VolumeSerialNumber])}
  247.   Result := IntToStr(VolumeSerialNumber);
  248. end;
  249.  
  250. function GetVolumeID(DriveChar: Char): String;
  251. //Para obtener el # de serie de un disco
  252. var
  253.   MaxFileNameLength, VolFlags, SerNum: DWord;
  254.   DrivePath : String;
  255. begin
  256.   DrivePath :=  DriveChar + ':\';
  257.   if GetVolumeInformation(PChar(DrivePath), nil, 0,
  258.      @SerNum, MaxFileNameLength, VolFlags, nil, 0)
  259.   then
  260.   begin
  261.       Result := IntToStr(SerNum);
  262.   end
  263.   else
  264.       Result := '';
  265. End;
  266.  
  267. // EN ESTA PARTE LLAMAMOS A LA FUNCION
  268. procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
  269. var
  270.   SerialNumber: ShortString;
  271.   SerialNumber2: string;
  272. begin
  273.   Edit1.Text:='';
  274.   Label1.Caption:= '';
  275.   if GetPhysicalNumOfDrive(Key) <> -1 then  // si hay una letra escrita hacer
  276.   begin
  277.     case GetDriveType(PChar(Key + ':\')) of
  278.      DRIVE_REMOVABLE:
  279.        begin
  280.        GetUSBSerial(Key, SerialNumber);
  281.        Label1.Caption:= SerialNumber;
  282.        Edit2.Text:=SerialNumber;
  283.        end;
  284.      DRIVE_FIXED:
  285.        begin
  286.        //Label1.Caption:=GetHardDiskSerial(Key);  // obtener serial volumen 1
  287.        //Label1.Caption:=GetVolumeID(Key);  // obtener serial volumen 2
  288.        GetSerialNumber(Key, SerialNumber2);
  289.        Label1.Caption:=SerialNumber2;
  290.        Edit2.Text:=SerialNumber2;
  291.        end;
  292.     end;
  293.   end
  294.   else MessageBox(Handle, 'Unmounted drive', 'Error', MB_ICONEXCLAMATION);
  295. end;
  296.  
  297. procedure TForm1.Button1Click(Sender: TObject);
  298. begin
  299.  
  300. end;
  301.  
  302. procedure TForm1.FormCreate(Sender: TObject);
  303. begin
  304.  
  305. end;
  306.  
  307. end.

Le comento que de momento me esta funcionando excelente :) ahora ya me detecta los números de series del fabricante del disco duro, muchas gracias amigo, también quisiera compartirles mis seriales que en mi caso me detecta:
 
disco duro fijo laptop seagate (500gb):             SBY5DGCY
disco duro usb samgung (500gb):                     00000000011E0E20
memoria usb hp (16gb):                                    0416KK00000066840814
 
Cuando tenga tiempo los probaré en otras pcs, ahorita no tengo otra a la mano.
 
También voy a compartirles el proyecto que estoy usando, miles de gracias de nuevo al amigo Escafranda sus aportes son muy buenos :)
 
http://www.mediafire...USB - HDD 2.zip
 
.
  • 1