<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
	<title type="html"><![CDATA[Серый форум &mdash; LangMF 9/11: Узнать состояние лотка CD-ROM]]></title>
	<link rel="self" href="http://forum.script-coding.com/extern.php?action=feed&amp;tid=3251&amp;type=atom" />
	<updated>2009-06-03T16:27:01Z</updated>
	<generator>PunBB</generator>
	<id>http://forum.script-coding.com/viewtopic.php?id=3251</id>
		<entry>
			<title type="html"><![CDATA[LangMF 9/11: Узнать состояние лотка CD-ROM]]></title>
			<link rel="alternate" href="http://forum.script-coding.com/viewtopic.php?pid=24218#p24218" />
			<content type="html"><![CDATA[<p><em>Без гарантий. Используете на свой страх и риск.</em></p><p>Узнать состояние лотка CD-ROM(открыт/закрыт) можно с помощью функции DeviceIoControl (control code IOCTL_SCSI_PASS_THROUGH).</p><p>Для <a href="http://langmf.ru/ftp/archive/LangMF_9.0.exe">LangMF 9</a>, <strong>cd_rom_9.mf</strong>:<br /></p><div class="codebox"><pre><code>
&#039;
&#039; Переключатель лотка CDROM. Сценарий опрашивает состояние лотка CDROM(открыт/закрыт) с помощью DeviceIoControl. 
&#039; Если лоток закрыт, сценарий открывает его и наоборот.
&#039;
&#039; Lang LangMF9
&#039; OC Win7
&#039;
&#039;
&lt;#Module=CDROM&gt;

&#039;Private Type SCSI_PASS_THROUGH
&#039;Length As Integer
&#039;ScsiStatus As Byte
&#039;PathId As Byte
&#039;TargetId As Byte
&#039;Lun As Byte 
&#039;CdbLength As Byte
&#039;SenseInfoLength As Byte
&#039;DataIn As Long
&#039;DataTransferLength As Long
&#039;TimeOutValue As Long
&#039;DataBufferOffset As Long
&#039;SenseInfoOffset As Long
&#039;Cdb(16) As Byte
&#039;End Type

&#039;Private Type SCSI_PASS_THROUGH_BUFFER
&#039;Header As SCSI_PASS_THROUGH
&#039;SenseBuffer(32) As Byte
&#039;DataBuffer(192) As Byte
&#039;End Type


 Private Const SCSI_IOCTL_DATA_IN = 1
 Private Const SCSIOP_MECHANISM_STATUS = &amp;HBD
 Private Const IOCTL_SCSI_PASS_THROUGH = &amp;H4D004

 Private Const GENERIC_READ = &amp;H80000000
 Private Const GENERIC_WRITE = &amp;H40000000
 Private Const GENERIC_EXECUTE = &amp;H20000000
 Private Const GENERIC_ALL = &amp;H10000000
 Private Const FILE_SHARE_READ = 1
 Private Const FILE_SHARE_WRITE = 2
 Private Const FILE_ATTRIBUTE_NORMAL = &amp;H80
 Private Const FILE_ATTRIBUTE_DEVICE = &amp;H40
 Private Const FILE_FLAG_DELETE_ON_CLOSE = &amp;H4000000
 Private Const FILE_FLAG_OVERLAPPED = &amp;H40000000
 Private Const OPEN_EXISTING = 3

 Private Const IOCTL_DISK_EJECT_MEDIA = &amp;H74808
 Private Const IOCTL_DISK_LOAD_MEDIA  = &amp;H7480C

 Private Const INVALID_HANDLE_VALUE = -1

 Private Const SCSI_PASS_THROUGH_LEN = 44
 Private Const SENSE_BUF_LEN = 32
 Private Const DATA_BUF_LEN = 192



&#039; ///Буква диска///
&#039;---------------------------------------------------
 Private Const sDiskLtr = &quot;D&quot;
 Private Const CDROM_TYPE = 4

&#039; Общие переменные
&#039;---------------------------------------------------
 Private BUF_LEN, b1, hDev, DATA_BUF, sDiskLetter



&#039;---------------------------------------------------
Sub Load(cmdstr)

	Dim oScr
	Dim SENSE_BUF, p1
	
	sDiskLetter = sDiskLtr
	
	sDiskLetter = InputBox(&quot;Укажите букву диска:&quot;, &quot;Буква диска&quot;, sDiskLetter)
	If Len(sDiskLetter) = 0 Then EndMF: Exit Sub
	sDiskLetter = Trim(sDiskLetter &amp; &quot;:&quot;)


	&#039; Проверить наличие и тип устройства
	&#039;--------------------------------------------
	Set oScr = CreateObject(&quot;Scripting.FileSystemObject&quot;)

	If Not oScr.DriveExists(sDiskLetter) Then
		MsgBox &quot;Диск [&quot; &amp; sDiskLetter &amp; &quot;] не существует.&quot;,vbSystemModal + vbExclamation, &quot;Error&quot;	
		EndMF: Exit Sub
	End If

	If oScr.GetDrive(sDiskLetter).DriveType&lt;&gt;CDROM_TYPE Then
		MsgBox &quot;Диск [&quot; &amp; sDiskLetter &amp; &quot;] не является CDROM.&quot;,vbSystemModal + vbExclamation, &quot;Error&quot;	
		EndMF: Exit Sub
	End If


	&#039; Подготовить и заполнить структуру SCSI_PASS_THROUGH_BUFFER, 
	&#039; которая содержит вложенную структуру SCSI_PASS_THROUGH.
	&#039; Использован Sys.DynAPI.CurBuf т.к. в таком случае 
	&#039; легче осуществить выравнивание структуры.	
	&#039;--------------------------------------------
	BUF_LEN = SCSI_PASS_THROUGH_LEN + SENSE_BUF_LEN + DATA_BUF_LEN
	Sys.DynAPI.CurBuf = 1
	Sys.DynAPI.ReBuf(BUF_LEN)
	p1 = Sys.DynAPI.PtrBuf(1)
	b1 = p1

	&#039;--------------------------------------------
	&#039;/SCSI_PASS_THROUGH.Length
	Sys.MemoryWord(p1)=SCSI_PASS_THROUGH_LEN		
	p1=p1+6
	
	&#039;/SCSI_PASS_THROUGH.CdbLength
	Sys.MemoryByte(p1)=12
	p1=p1+1

	&#039;/SCSI_PASS_THROUGH.SenseInfoLength
	Sys.MemoryByte(p1)=SENSE_BUF_LEN
	p1=p1+1

	&#039;/SCSI_PASS_THROUGH.DataIn
	Sys.MemoryByte(p1)=SCSI_IOCTL_DATA_IN
	p1=p1+4

	&#039;/SCSI_PASS_THROUGH.DataTransferLength
	Sys.MemoryLong(p1)=DATA_BUF_LEN
	p1=p1+4

	&#039;/SCSI_PASS_THROUGH.TimeOutValue
	Sys.MemoryLong(p1)=10
	p1=p1+4

	&#039;/SCSI_PASS_THROUGH.DataBufferOffset
	Sys.MemoryLong(p1)=SCSI_PASS_THROUGH_LEN + SENSE_BUF_LEN
	p1=p1+4

	&#039;/SCSI_PASS_THROUGH.SenseInfoOffset
	Sys.MemoryLong(p1)=SCSI_PASS_THROUGH_LEN
	p1=p1+4


	&#039;/SCSI_PASS_THROUGH.Cdb(0)
	Sys.MemoryByte(p1)=SCSIOP_MECHANISM_STATUS
	p1=p1+9

	&#039;/SCSI_PASS_THROUGH.Cdb(8)
	Sys.MemoryByte(p1)=8
	p1=p1+7

	SENSE_BUF = p1	
	DATA_BUF = SENSE_BUF+32

	&#039; Открыть диск как файл
	&#039;--------------------------------------------
	hDev = Sys.DynApi.CallFunction( _	
			&quot;KERNEL32.DLL&quot;,&quot;CreateFileA&quot;, _	
					CStr(&quot;\\.\&quot; &amp; sDiskLetter), _	
					GENERIC_READ + GENERIC_WRITE, _		
					FILE_SHARE_READ + FILE_SHARE_WRITE, _
					0, _			
					OPEN_EXISTING, _	
					0, _
					0)	

	If hDev = INVALID_HANDLE_VALUE Then 
		MsgBox &quot;Не удалось открыть устройство [&quot; &amp; sDiskLetter &amp; &quot;]&quot; ,vbSystemModal + vbExclamation, &quot;Error&quot;		
		EndMF: Exit Sub
	End If

	
	&#039; Опросить состояние устройства и переключить лоток CD-ROM
	&#039;--------------------------------------------
	SwitchCDROM()

	&#039;--------------------------------------------
	Sys.DynApi.CallFunction &quot;KERNEL32.DLL&quot;,&quot;CloseHandle&quot;, hDev

	EndMF

End Sub

&#039;
&#039; Опросить состояние устройства и переключить лоток CD-ROM
&#039;
&#039;---------------------------------------------------
Sub SwitchCDROM()

	Dim val1, n1, x, OPERATION, sStr, hRes, iAnsw

	&#039; Опросить состояние устройства
	&#039;--------------------------------------------	
	val1 = CLng(0)
	n1 = VarPtr(val1) + 8
	
	hRes = Sys.DynApi.CallFunction( _	
		&quot;KERNEL32.DLL&quot;,&quot;DeviceIoControl&quot;, _	
				hDev, _
				IOCTL_SCSI_PASS_THROUGH, _
				b1, _
				BUF_LEN, _
				b1, _
				BUF_LEN, _
				n1, _
				0)

	If hRes = 0 Then 
		MsgBox &quot;Не удалось опросить устройство [&quot; &amp; sDiskLetter &amp; &quot;]&quot;, vbSystemModal + vbExclamation, &quot;Error&quot;		
		Exit Sub
	End If

	&#039; Второй байт буфера данных содержит искомый флаг
	&#039; (000[1]0000-лоток открыт, 000[0]0000-лоток закрыт)
	&#039;--------------------------------------------
	x = Sys.MemoryByte(DATA_BUF+1) And &amp;H10
	
	&#039; Переключить лоток CD-ROM с помощью DeviceIoControl
	&#039;--------------------------------------------
	If x = &amp;H10 Then 
		sStr = &quot;Лоток CDROM открыт. Закрыть лоток?&quot;
		OPERATION = IOCTL_DISK_LOAD_MEDIA

	ElseIf x = 0 Then
		sStr = &quot;Лоток CDROM закрыт. Открыть лоток?&quot;
		OPERATION = IOCTL_DISK_EJECT_MEDIA

	End If

	&#039;--------------------------------------------
	iAnsw = MsgBox(&quot;Диск [&quot; &amp; sDiskLetter &amp; &quot;] &quot; &amp; sStr,vbSystemModal + vbExclamation + vbOKCancel, &quot;Состояние&quot;)	
	If iAnsw = vbCancel Then Exit Sub

	hRes = Sys.DynApi.CallFunction( _	
		&quot;KERNEL32.DLL&quot;,&quot;DeviceIoControl&quot;, _	
				hDev, _
				OPERATION, _
				0, _
				0, _
				0, _
				0, _
				n1, _
				0)


	

End Sub	
&lt;#Module&gt;
</code></pre></div><p>Аналогично для&nbsp; <a href="http://forum.langmf.ru/viewtopic.php?f=4&amp;t=6107">LangMF 11</a>, <strong>cd_rom_11.mf</strong>:<br /></p><div class="codebox"><pre><code>
&#039;
&#039; Переключатель лотка CDROM. Сценарий опрашивает состояние лотка CDROM(открыт/закрыт) с помощью DeviceIoControl. 
&#039; Если лоток закрыт, сценарий открывает его и наоборот.
&#039;
&#039; Lang LangMF11
&#039; OC Win7
&#039;
&#039;
&lt;#Module=CDROM&gt;

&#039;Private Type SCSI_PASS_THROUGH
&#039;Length As Integer
&#039;ScsiStatus As Byte
&#039;PathId As Byte
&#039;TargetId As Byte
&#039;Lun As Byte 
&#039;CdbLength As Byte
&#039;SenseInfoLength As Byte
&#039;DataIn As Long
&#039;DataTransferLength As Long
&#039;TimeOutValue As Long
&#039;DataBufferOffset As Long
&#039;SenseInfoOffset As Long
&#039;Cdb(16) As Byte
&#039;End Type

&#039;Private Type SCSI_PASS_THROUGH_BUFFER
&#039;Header As SCSI_PASS_THROUGH
&#039;SenseBuffer(32) As Byte
&#039;DataBuffer(192) As Byte
&#039;End Type


 Private Const SCSI_IOCTL_DATA_IN = 1
 Private Const SCSIOP_MECHANISM_STATUS = &amp;HBD
 Private Const IOCTL_SCSI_PASS_THROUGH = &amp;H4D004

 Private Const GENERIC_READ = &amp;H80000000
 Private Const GENERIC_WRITE = &amp;H40000000
 Private Const GENERIC_EXECUTE = &amp;H20000000
 Private Const GENERIC_ALL = &amp;H10000000
 Private Const FILE_SHARE_READ = 1
 Private Const FILE_SHARE_WRITE = 2
 Private Const FILE_ATTRIBUTE_NORMAL = &amp;H80
 Private Const FILE_ATTRIBUTE_DEVICE = &amp;H40
 Private Const FILE_FLAG_DELETE_ON_CLOSE = &amp;H4000000
 Private Const FILE_FLAG_OVERLAPPED = &amp;H40000000
 Private Const OPEN_EXISTING = 3

 Private Const IOCTL_DISK_EJECT_MEDIA = &amp;H74808
 Private Const IOCTL_DISK_LOAD_MEDIA  = &amp;H7480C

 Private Const INVALID_HANDLE_VALUE = -1

 Private Const SCSI_PASS_THROUGH_LEN = 44
 Private Const SENSE_BUF_LEN = 32
 Private Const DATA_BUF_LEN = 192



&#039; ///Буква диска///
&#039;---------------------------------------------------
 Private Const sDiskLtr = &quot;D&quot;
 Private Const CDROM_TYPE = 4

&#039; Общие переменные
&#039;---------------------------------------------------
 Private BUF_LEN, cBUF, hDev, DATA_BUF, sDiskLetter


&#039;---------------------------------------------------
Sub Load(cmdstr)

	Dim oScr
	Dim offs, SENSE_BUF
	Dim arr()

	sDiskLetter = sDiskLtr
	
	sDiskLetter = InputBox(&quot;Укажите букву диска:&quot;, &quot;Буква диска&quot;, sDiskLetter)
	If Len(sDiskLetter) = 0 Then EndMF: Exit Sub
	sDiskLetter = Trim(sDiskLetter &amp; &quot;:&quot;)
	
	&#039; Проверить наличие и тип устройства
	&#039;--------------------------------------------
	Set oScr = CreateObject(&quot;Scripting.FileSystemObject&quot;)

	If Not oScr.DriveExists(sDiskLetter) Then
		MsgBox &quot;Диск [&quot; &amp; sDiskLetter &amp; &quot;] не существует.&quot;,vbSystemModal + vbExclamation, &quot;Error&quot;	
		EndMF: Exit Sub
	End If

	If oScr.GetDrive(sDiskLetter).DriveType&lt;&gt;CDROM_TYPE Then
		MsgBox &quot;Диск [&quot; &amp; sDiskLetter &amp; &quot;] не является CDROM.&quot;,vbSystemModal + vbExclamation, &quot;Error&quot;	
		EndMF: Exit Sub
	End If


	&#039; Подготовить и заполнить структуру SCSI_PASS_THROUGH_BUFFER,
	&#039; которая содержит вложенную структуру SCSI_PASS_THROUGH.
	&#039; Использован Sys.NewBuf() т.к. в таком случае 
	&#039; легче осуществить выравнивание структуры.	
	&#039;--------------------------------------------
	BUF_LEN = SCSI_PASS_THROUGH_LEN + SENSE_BUF_LEN + DATA_BUF_LEN

	ReDim arr(BUF_LEN)
	Set cBUF = Sys.NewBuf(arr)
	
	offs=0

	&#039;/SCSI_PASS_THROUGH.Length
	cBUF.PWord(offs)=SCSI_PASS_THROUGH_LEN
	offs=offs+6
	
	&#039;/SCSI_PASS_THROUGH.CdbLength
	cBUF.PByte(offs)=12
	offs=offs+1

	&#039;/SCSI_PASS_THROUGH.SenseInfoLength
	cBUF.PByte(offs)=SENSE_BUF_LEN
	offs=offs+1

	&#039;/SCSI_PASS_THROUGH.DataIn
	cBUF.PByte(offs)=SCSI_IOCTL_DATA_IN
	offs=offs+4

	&#039;/SCSI_PASS_THROUGH.DataTransferLength
	cBUF.PLong(offs)=DATA_BUF_LEN
	offs=offs+4

	&#039;/SCSI_PASS_THROUGH.TimeOutValue
	cBUF.PLong(offs)=10
	offs=offs+4

	&#039;/SCSI_PASS_THROUGH.DataBufferOffset
	cBUF.PLong(offs)=SCSI_PASS_THROUGH_LEN + SENSE_BUF_LEN
	offs=offs+4

	&#039;/SCSI_PASS_THROUGH.SenseInfoOffset
	cBUF.PLong(offs)=SCSI_PASS_THROUGH_LEN
	offs=offs+4

	&#039;/SCSI_PASS_THROUGH.Cdb(0)
	cBUF.PByte(offs)=SCSIOP_MECHANISM_STATUS
	offs=offs+9

	&#039;/SCSI_PASS_THROUGH.Cdb(8)
	cBUF.PByte(offs)=8
	offs=offs+7


	SENSE_BUF = offs	
	DATA_BUF = SENSE_BUF+32

	&#039; Открыть диск как файл
	&#039;--------------------------------------------
	hDev = DllCall( &quot;KERNEL32.DLL&quot;,&quot;CreateFileA&quot;, _	
					CStr(&quot;\\.\&quot; &amp; sDiskLetter), _	
					GENERIC_READ + GENERIC_WRITE, _		
					FILE_SHARE_READ + FILE_SHARE_WRITE, _
					0, _			
					OPEN_EXISTING, _	
					0, _
					0)	

	If hDev = INVALID_HANDLE_VALUE Then 
		MsgBox &quot;Не удалось открыть устройство [&quot; &amp; sDiskLetter &amp; &quot;]&quot;, vbSystemModal + vbExclamation, &quot;Error&quot;		
		EndMF: Exit Sub
	End If

	&#039; Опросить состояние устройства и переключить лоток CD-ROM
	&#039;--------------------------------------------
	SwitchCDROM()
	
	&#039;--------------------------------------------
	DllCall &quot;KERNEL32.DLL&quot;,&quot;CloseHandle&quot;, hDev

	EndMF


End Sub

&#039;
&#039; Опросить состояние устройства и переключить лоток CD-ROM
&#039;
&#039;---------------------------------------------------
Sub SwitchCDROM()

	
	Dim b1, val1, n1, x, OPERATION, sStr, hRes, iAnsw

	val1 = CLng(0)
	n1 = VarPtr(val1) + 8
	
	&#039; Опросить состояние устройства
	&#039;--------------------------------------------	
	b1 = cBUF.Ptr
	hRes = DllCall( &quot;KERNEL32.DLL&quot;,&quot;DeviceIoControl&quot;, _	
				hDev, _
				IOCTL_SCSI_PASS_THROUGH, _
				b1, _
				BUF_LEN, _
				b1, _
				BUF_LEN, _
				n1, _
				0)

	If hRes = 0 Then 
		MsgBox &quot;Не удалось опросить устройство [&quot; &amp; sDiskLetter &amp; &quot;]&quot; ,vbSystemModal + vbExclamation, &quot;Error&quot;		
		Exit Sub
	End If

	&#039; Второй байт буфера данных содержит искомый флаг
	&#039; (000[1]0000-лоток открыт, 000[0]0000-лоток закрыт)
	&#039;--------------------------------------------
	x = cBUF.PByte(DATA_BUF+1) And &amp;H10
	
	&#039; Переключить лоток CD-ROM с помощью DeviceIoControl
	&#039;--------------------------------------------
	If x = &amp;H10 Then 
		sStr = &quot;Лоток CDROM открыт. Закрыть лоток?&quot;
		OPERATION = IOCTL_DISK_LOAD_MEDIA

	ElseIf x = 0 Then
		sStr = &quot;Лоток CDROM закрыт. Открыть лоток?&quot;
		OPERATION = IOCTL_DISK_EJECT_MEDIA

	End If

	&#039;--------------------------------------------
	iAnsw = MsgBox(&quot;Диск [&quot; &amp; sDiskLetter &amp; &quot;] &quot; &amp; sStr,vbSystemModal + vbExclamation + vbOKCancel, &quot;Состояние&quot;)	
	If iAnsw = vbCancel Then Exit Sub

	hRes = DllCall( &quot;KERNEL32.DLL&quot;,&quot;DeviceIoControl&quot;, _	
				hDev, _
				OPERATION, _
				0, _
				0, _
				0, _
				0, _
				n1, _
				0)

End Sub
&lt;#Module&gt;
</code></pre></div>]]></content>
			<author>
				<name><![CDATA[Poltergeyst]]></name>
				<uri>http://forum.script-coding.com/profile.php?id=83</uri>
			</author>
			<updated>2009-06-03T16:27:01Z</updated>
			<id>http://forum.script-coding.com/viewtopic.php?pid=24218#p24218</id>
		</entry>
</feed>
