SMART_RCV_DRIVE_DATA
et SMART_SEND_DRIVE_COMMAND
sont des un codes de contrôle (dwIoControlCode
) utilisé dans l'appel a l'API DeviceIoControl
BOOL DeviceIoControl( HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped );
Exemple d'appel en Pascal (parce que moi j'aime bien le Pascal)
var vSCIP: TSendCmdInParams; vSCOP: TSendCmdOutParams; vOutSize: dword; begin ... DeviceIoControl(AHandle, SMART_RCV_DRIVE_DATA, @vSCIP, sizeof(TSendCmdInParams), @vSCOP, sizeof(TSendCmdOutParams)+BufferSize, vOutSize, nil); // Ou... DeviceIoControl(AHandle, SMART_SEND_DRIVE_COMMAND, @vSCIP, sizeof(TSendCmdInParams), @vSCOP, sizeof(TSendCmdOutParams), vOutSize, nil);
Source : SENDCMDOUTPARAMS chez Microsoft
La Structure SENDCMDOUTPARAMS contient la réponse fournie par l'API.
Cette structure est remplie par l'API pas besoin de la pré-remplir.
typedef struct _SENDCMDOUTPARAMS { ULONG cBufferSize; DRIVERSTATUS DriverStatus; UCHAR bBuffer[1]; } SENDCMDOUTPARAMS, *PSENDCMDOUTPARAMS, *LPSENDCMDOUTPARAMS;
Source : SENDCMDINPARAMS chez Microsoft
typedef struct _SENDCMDINPARAMS { ULONG cBufferSize; // Taille du buffer de sortie BufferSize dans le tableau ci-dessous IDEREGS irDriveRegs; // Strucutre IDEREGS contenant les paramètres d'appel (voir ci-dessous) UCHAR bDriveNumber; // Numero du disk (exemple: avec \\.\PhysicalDrive5, le numéro du disque est 5) UCHAR bReserved[3]; ULONG dwReserved[4]; UCHAR bBuffer[1]; } SENDCMDINPARAMS, *PSENDCMDINPARAMS, *LPSENDCMDINPARAMS;
Source : IDEREGS chez Microsoft
La Structure IDEREGS est une sous structure de SENDCMDINPARAMS (voir ci-dessus) contenant les paramètres utiles a l'appel de l'API.
typedef struct _IDEREGS { UCHAR bFeaturesReg; // La fonction qu'on appel, Features dans le tableau ci-dessous UCHAR bSectorCountReg; // SectorCount dans tableau : Nombre de secteur (je pense...) UCHAR bSectorNumberReg; // Sectornumber dans tableau : Numéro du premier secteur (je pense...) UCHAR bCylLowReg; // CylLow dans tableau : Cylindre Bas ??? UCHAR bCylHighReg; // CylHigh dans tableau : Cylindre Haut ??? UCHAR bDriveHeadReg; // $A0 or ((DriveNumber and 1) shl 4); en Pascal. Pourquoi ??? je ne sais pas.. UCHAR bCommandReg; // toujours SMART_CMD ( $B0) avec SMART_RVC_DRIVE_DATA UCHAR bReserved; } IDEREGS, *PIDEREGS, *LPIDEREGS;
SMART_RCV_DRIVE_DATA | ||||||||
---|---|---|---|---|---|---|---|---|
IDEREGS Features | Rôle | SENDCMDINPARAMS BufferSize | IDEREGS SectorCount | IDEREGS SectorNumber | IDEREGS CylLow | IDEREGS CylHigh | ||
READ_ATTRIBUTES $D0 | Récupérer les attributs SMART | READ_ATTRIBUTE_BUFFER_SIZE (512) | 1 | 1 | SMART_CYL_LOW ($4F) | SMART_CYL_HI ($C2) | ||
READ_THRESHOLDS $D1 | Récupérer les valeurs de seuil qui indiquent quand un disque est sur le point de tomber en panne. | READ_THRESHOLD_BUFFER_SIZE (512) | 1 | 1 | SMART_CYL_LOW ($4F) | SMART_CYL_HI ($C2) | ||
ENABLE_DISABLE_AUTOSAVE $D2 | Active l'attribut optionnel autosave du périphérique lorsqu'il est défini à 1. Désactive cette fonction lorsqu'elle est définie à 0… | |||||||
SAVE_ATTRIBUTE_VALUES $D3 | Demande à l'appareil de sauvegarder ses valeurs d'attribut dans la mémoire non volatile de l'appareil. | |||||||
EXECUTE_OFFLINE_DIAGS $D4 | Permet à l'appareil de commencer à collecter des données SMART en mode hors ligne ou d'exécuter une routine de test d'autodiagnostic en mode captif ou hors ligne. | |||||||
SMART_READ_LOG $D5 | Récupère les Logs. | |||||||
SMART_WRITE_LOG $D6 | Écrit le nombre indiqué de secteurs de données de 512 octets dans les logs | |||||||
RETURN_SMART_STATUS $DA | Récupère l'état de fiabilité de l'appareil. | |||||||
ENABLE_DISABLE_AUTO_OFFLINE $DB | Active ou Désactive le mode hors ligne | |||||||
SMART_SEND_DRIVE_COMMAND | ||||||||
IDEREGS Features | Rôle | SENDCMDINPARAMS BufferSize | IDEREGS SectorCount | IDEREGS SectorNumber | IDEREGS CylLow | IDEREGS CylHigh | ||
ENABLE_SMART $D8 | Active SMART | 0 | 1 | 1 | SMART_CYL_LOW ($4F) | SMART_CYL_HI ($C2) | ||
DISABLE_SMART $D9 | Désactive SMART |
Le type TicSendCmdOutParams
est une variante du type TSendCmdOutParams
présent dans l'unité jwaWinIoCtl.pas
(Ici on parle Pascal et Lazarus plus précisément)
auquel j'ai enlevé le dernier membre (bBuffer: array [0..0] of BYTE
) pour qu'il puisse être inclus dans un type TSCOP_XXXXXXX.
Bon, je ne sais pas si c'est une bonne idée, mais c'est la mienne a l'instant T.
Et ça fonctionne en plus !
TTicSendCmdOutParams = packed record cBufferSize: DWORD; // Size of bBuffer in bytes DriverStatus: TDriverStatus; // Driver status structure. end;
le SCOP (SendCmdOutParams) est suivi de deux Byte A et B dont je ne connais pas l'utilité.
Puis un tableau de 30 attributs SMART (TSmartAttrs)
Et de quelques byte, ici pour combler l'espace.
TSCOP_SmartAttrs = packed record SCOP: TTicSendCmdOutParams; (voir ci-dessus) A, B: byte; // ??? Results: TSmartAttrs; //array[0..29] of TSmartAttr; Reserved: array[1..150] of byte; // pour arriver a 512 end;
Avec les types suivants
TSmartAttr = packed record ID: byte; Flags: word; Current, Worst: byte; Raw: array[0..5] of byte; //[01 23 45 67 89 AB] correspond a $AB8967452301 Reserved: byte; end; TSmartAttrs = array[0..29] of TSmartAttr; // max of 30 attributes
D’après ce que je constate il peut y avoir au maximum 30 attributs
le SCOP (SendCmdOutParams)
suivi d'un Word (2oct) indiquant la numéro de révision.
Puis un tableau de 30 Thresholds SMART (TSmartThresholds
)
Et de quelques byte, ici pour combler l'espace.
TSCOP_SmartThresholds = packed record SCOP : TTicSendCmdOutParams; RevNumber : word; // 2 oct Results : TSmartThresholds; // 360 oct Reserved : array[0..148] of byte; // 149 oct Chksum: byte; // 1 oct // total 512 = READ_THRESHOLD_BUFFER_SIZE end;
Avec les types suivants
TSmartThreshold = packed record ID: byte; //1 oct Threshold : byte; //1 oct Reserved : array[0..9] of byte; //10 oct // Total = 12 oct end; TSmartThresholds = array[0..C_SMART_MAX_ATTRS] of TSmartThreshold; //12x30 = 360 oct
30 max comme le nombre d'attributs
ID de l'attribut auquel correspond ce Threshold
Valeur sur 1 octet, seuil indiquant quand un disque est sur le point de tomber en panne.
Pour l'instant, je ne sais pas trop.
Dés que j'ai plus d'infos je les mettrai ici !
On peut estimer que si la commande DeviceIOControl renvoi True
alors le SMART est activé.