.386
LOCALS

.MODEL	FLAT


L			EQU	<LARGE>


OPEN_EXISTING		EQU	3
FILE_SHARE_READ		EQU	1
FILE_SHARE_WRITE	EQU	2
GENERIC_READ		EQU	80000000h
GENERIC_WRITE		EQU	40000000h

SMART_GET_VERSION		EQU	74080h
SMART_SEND_DRIVE_COMMAND	EQU	7C084h
SMART_RCV_DRIVE_DATA		EQU	7C088h

GETVERSIONINPARAMS	STRUC
	gvip_bVersion		DB	?
	gvip_bRevision		DB	?
	gvip_bReserved		DB	?
	gvip_bIDEDeviceMap	DB	?
	gvip_dwCapabilities	DD	?
	gvip_dwReserved		DD	4 DUP(?)
GETVERSIONINPARAMS	ENDS

;Биты gvip_dwCapabilities
CAP_ATA_ID_CMD		EQU	1
CAP_ATAPI_ID_CMD	EQU	2
CAP_SMART_CMD		EQU	4

IDEREGS		STRUC
	ir_bFeaturesReg		DB	?
	ir_bSectorCountReg	DB	?
	ir_bSectorNumberReg	DB	?
	ir_bCylLowReg		DB	?
	ir_bCylHighReg		DB	?
	ir_bDriveHeadReg	DB	?
	ir_bCommandReg		DB	?
	ir_bReserved		DB	?
IDEREGS		ENDS

;Значения ir_bCommandReg
ATAPI_ID_CMD		EQU	0A1h
ID_CMD			EQU	0ECh
SMART_CMD		EQU	0B0h

;Значения ir_bCylLowReg и ir_bCylHighReg для команд SMART
SMART_CYL_LOW		EQU	4Fh
SMART_CYL_HI		EQU	0C2h

SENDCMDINPARAMS	STRUC
	scip_dwBufferSize	DD	?
	scip_irDriveRegs	IDEREGS	<>
	scip_bDriveNumber	DB	?
	scip_bReserved		DB	3 DUP(?)
	scip_dwReserved		DD	4 DUP(?)
	scip_bBuffer		DB	?
SENDCMDINPARAMS	ENDS

DRIVERSTATUS	STRUC
	ds_bDriverError		DB	?
	ds_bIDEError		DB	?
	ds_bReserved		DB	2 DUP(?)
	ds_dwReserved		DD	2 DUP(?)
DRIVERSTATUS	ENDS

;Значения ds_bDriverError
DRVERR_NO_ERROR		EQU	0
DRVERR_IDE_ERROR	EQU	1
DRVERR_INVALID_FLAG	EQU	2
DRVERR_INVALID_COMMAND	EQU	3
DRVERR_INVALID_BUFFER	EQU	4
DRVERR_INVALID_DRIVE	EQU	5
DRVERR_INVALID_IOCTL	EQU	6
DRVERR_ERROR_NO_MEM	EQU	7
DRVERR_INVALID_REGISTER	EQU	8
DRVERR_NOT_SUPPORTED	EQU	9
DRVERR_NO_IDE_DEVICE	EQU	10

SENDCMDOUTPARAMS	STRUC
	scop_dwBufferSize	DD		?
	scop_dsDriverStatus	DRIVERSTATUS	<>
	scop_bBuffer		DB		?
SENDCMDOUTPARAMS	ENDS


EXTRN	CreateFileA:PROC
EXTRN	CloseHandle:PROC
EXTRN	DeviceIoControl:PROC


.DATA

szDeviceName	DB	"\\.\PhysicalDrive0", 0


.CODE

PUBLIC	NT_GetDevInfo

EXTRN	CorrectDevInfo:PROC

;*******************************************************************************
;NT_GetDevInfo	получает информацию об устройстве IDE/ATAPI
;		(WinNT с правами администратора)
;*******************************************************************************
;Использует:	CreateFileA, CloseHandle, DeviceIoControl
;
;Вызов:		AL = номер устройства
;		EDI -> буфер для информации об устройстве
;
;Возврат:	EAX = флаг успешного/неудачного завершения
;
;Изменяемые
;  регистры:	EAX,ECX,EDX,Flags
;*******************************************************************************
NT_GetDevInfo	PROC
		LOCAL	@@gvip:GETVERSIONINPARAMS, \
			@@scip:BYTE:SIZE SENDCMDINPARAMS -1, \
			@@scop:BYTE:SIZE SENDCMDOUTPARAMS -1+512, \
			@@dwBytesReturned:DWORD = LOCAL_SIZE

		push	ebx

;Получаем описатель устройства
		and	al,7
		mov	bl,al			;BL = номер устройства
		or	al,'0'
		mov	BYTE PTR [szDeviceName+17],al

		xor	eax,eax
		push	eax
		push	eax
		push	L OPEN_EXISTING
		push	eax
		push	L (FILE_SHARE_READ OR FILE_SHARE_WRITE)
		push	L (GENERIC_READ OR GENERIC_WRITE)
		push	L OFFSET szDeviceName
		call	CreateFileA		;EAX = описатель устройства
		inc	eax
		jz	@@Exit
		dec	eax

		enter	LOCAL_SIZE,0
		push	esi

		mov	esi,eax			;ESI = описатель устройства

;Обнуляем локальные переменные
		lea	edx,[ebp-LOCAL_SIZE]
		mov	ecx,LOCAL_SIZE
		call	MemZero

;Получаем информацию о версии драйвера
		xor	eax,eax
		push	eax
		lea	ecx,[@@dwBytesReturned]
		push	ecx
		push	L SIZE GETVERSIONINPARAMS
		lea	ecx,[@@gvip]
		push	ecx
		push	eax
		push	eax
		push	L SMART_GET_VERSION
		push	esi
		call	DeviceIoControl
		or	eax,eax
		jz	@@Error

;Получаем информацию об устройстве
		mov	al,[@@gvip.gvip_bIDEDeviceMap]
		mov	cl,bl
		shr	al,cl
		test	al,1
		mov	ah,ID_CMD		;AH=0ECh (команда идентификации
						;устройства IDE)
		jnz	@@GetDeviceInfo

		mov	ah,ATAPI_ID_CMD		;AH=0A1h (команда идентификации
						;устройства ATAPI)

@@GetDeviceInfo:
		mov	[@@scip.scip_dwBufferSize],512
		mov	[@@scip.scip_bDriveNumber],bl
		mov	[@@scip.scip_irDriveRegs.ir_bSectorCountReg],1
		mov	[@@scip.scip_irDriveRegs.ir_bSectorNumberReg],1
		and	bl,1
		shl	bl,4
		or	bl,0A0h
		mov	[@@scip.scip_irDriveRegs.ir_bDriveHeadReg],bl
		mov	[@@scip.scip_irDriveRegs.ir_bCommandReg],ah

		push	L 0
		lea	eax,@@dwBytesReturned
		push	eax
		push	L (SIZE SENDCMDOUTPARAMS -1+512)
		lea	eax,@@scop
		push	eax
		push	L (SIZE SENDCMDINPARAMS -1)
		lea	eax,@@scip
		push	eax
		push	L SMART_RCV_DRIVE_DATA
		push	esi
		call	DeviceIoControl
		or	eax,eax
		jz	@@Error
		cmp	[@@scop.scop_dsDriverStatus.ds_bDriverError],DRVERR_NO_ERROR
		je	@@Ok

@@Error:	xor	ebx,ebx
		jmp	@@Done

@@Ok:
;Копируем информацию в буфер
		push	esi
		push	edi

		lea	esi,[@@scop.scop_bBuffer]
		mov	ecx,512 SHR 2
		rep	movsd

		pop	edi
		pop	esi

		call	CorrectDevInfo		;коррекция информации

		xor	ebx,ebx
		inc	ebx

@@Done:
;Освобождаем описатель устройства
		push	esi
		call	CloseHandle

		mov	eax,ebx

		pop	esi
		leave

@@Exit:
		pop	ebx

		ret

NT_GetDevInfo	ENDP


;*******************************************************************************
;MemZero	заполняет блок памяти нулями
;*******************************************************************************
;Использует:	нет
;
;Вызов:		EDX -> блок
;		ECX = размер блока в байтах
;
;Возврат:	нет
;
;Изменяемые
;  регистры:	EAX,ECX,EDX,Flags
;*******************************************************************************
MemZero		PROC

		push	edi

		mov	edi,edx
		xor	eax,eax		;EAX=0
		mov	edx,ecx
		shr	ecx,2		;ECX = число двойных слов в блоке
		rep	stosd
		mov	ecx,edx
		and	ecx,3		;ECX = число оставшихся байт
		rep	stosb

		pop	edi

		ret

MemZero		ENDP


END
