Tanveer,

I'm sorry, but porting to VB doesn't change anything: I don't think the
DllImportAttribute or GC was your problem. You still use "Long" (64 bit) all
over the place, although "Integer" (32 bit) and "IntPtr"
(processor-specific) should be used.

What's that:
Declare Unicode Function CreateFile Lib "kernel32" Alias "CreateFileA"
You are declaring a function to be Unicode, but use the ANSI version?

This declaration works:
Public Declare Unicode Function CreateFile Lib "kernel32" Alias
"CreateFileW" ( _
  ByVal lpFileName As String, ByVal dwDesiredAccess As Integer, ByVal
dwShareMode As Integer, _
  ByVal lpSecurityAttributes As IntPtr, ByVal dwCreationDisposition As
Integer, _
  ByVal dwFlagsAndAttributes As Integer, ByVal hTemplateFile As IntPtr) As
IntPtr

When you use it, you write: CreateFile("\\\\.\\Scsi0:", ...). Now this is
wrong in VB, since VB does not use \ as a meta-character. Write "\\.\Scsi0"
instead (I believe it mustn't have a trailing :, but I am not sure about
that).

When you had CreateFile ... As Long, it returned &HFFFFFFFF as a return
value, which corresponds to -1 in 32 bits (signed). In 64 bits, however, it
means 4294967295; so when you compared it with -1, the comparison yielded
that they were different (although they weren't). Use an IntPtr instead (as
in the above declaration). Also, to know what has gone wrong, in your else
branch (if hFile is -1), throw a Win32Exception, so you can see what went
wrong.

Then you declare a buffer: Dim buffer() As Byte, ReDim buffer(560). Just Dim
buffer(560) As Byte, which gets the same result. And if you make it (560),
the array will be from 0..560, i.e. 561 bytes long. Make it Dim buffer(559)
As Byte instead.

For x = 0 To 559
  buffer(x) = CType(0, Byte)
End For
This isn't needed, arrays are 0-initialized automatically. (Why casting 0 to
Byte anyway?)

I also don't think that the 42 lines of array initialization are nice, but I
won't change that now.

Let's go to DeviceIoControl. I would declare it as follows:
Public Declare Ansi Function DeviceIoControl Lib "kernel32" ( _
  ByVal hDevice As IntPtr, ByVal dwIoControlCode As Integer, ByVal
lpInBuffer As IntPtr, _
  ByVal nInBufferSize As Integer, ByVal lpOutBuffer As IntPtr, ByVal
nOutBufferSize As Integer, _
  ByRef lpBytesReturned As Integer, ByVal lpOverlapped As IntPtr) As Boolean

Now, I am not sure if you are allowed to pass the same pointer as InBuffer
and OutBuffer, but I assume you know what you are doing, so let's keep that.
The call now looks like this:
Dim success As Boolean = _
  DeviceIoControl(hFile, 315400, sb, 63, sb, 560, outBufferLength,
IntPtr.Zero)

At the end of this message, I have appended the whole source code again.
Alas, I don't have a SCSI disk, so I can't really try it out. And, you know,
VB.NET didn't buy you anything, I would've sticked with C# (the handle
created by CreateFile is never GCed by .NET).

Hope this helps
Fabian

Code:
Imports System

Imports System.Text

Imports System.Runtime.InteropServices

Imports System.ComponentModel

Module VBHDD

Public Class clsHDD

Public Const GENERIC_READ As Integer = &H80000000

Public Const GENERIC_WRITE As Integer = &H40000000

Public Const FILE_SHARE_READ As Integer = &H1

Public Const FILE_SHARE_WRITE As Integer = &H2

Public Const OPEN_EXISTING As Integer = 3

Public Declare Unicode Function CreateFile Lib "kernel32" Alias
"CreateFileW" ( _

ByVal lpFileName As String, ByVal dwDesiredAccess As Integer, ByVal
dwShareMode As Integer, _

ByVal lpSecurityAttributes As IntPtr, ByVal dwCreationDisposition As
Integer, _

ByVal dwFlagsAndAttributes As Integer, ByVal hTemplateFile As IntPtr) As
IntPtr

Public Declare Unicode Function CloseHandle Lib "kernel32" Alias
"CloseHandle" ( _

ByVal hObject As IntPtr) As Boolean

Public Declare Ansi Function DeviceIoControl Lib "kernel32" ( _

ByVal hDevice As IntPtr, ByVal dwIoControlCode As Integer, ByVal lpInBuffer
As IntPtr, _

ByVal nInBufferSize As Integer, ByVal lpOutBuffer As IntPtr, ByVal
nOutBufferSize As Integer, _

ByRef lpBytesReturned As Integer, ByVal lpOverlapped As IntPtr) As Boolean

Public Shared Function SCSI() As Long

Dim hFile As IntPtr = CreateFile("\\.\Scsi0", GENERIC_READ Or GENERIC_WRITE,
_

FILE_SHARE_READ Or FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0,
IntPtr.Zero)

Console.WriteLine("File Pointer ...{0}", hFile)

If (hFile.ToInt32() = -1) Then

Throw New Win32Exception

Else

Dim buffer(559) As Byte

Dim x As Integer = 0

buffer(x) = CType(28, Byte) : x += 1

buffer(x) = CType(0, Byte) : x += 1

buffer(x) = CType(0, Byte) : x += 1

buffer(x) = CType(0, Byte) : x += 1

buffer(x) = CType(83, Byte) : x += 1

buffer(x) = CType(67, Byte) : x += 1

buffer(x) = CType(83, Byte) : x += 1

buffer(x) = CType(73, Byte) : x += 1

buffer(x) = CType(68, Byte) : x += 1

buffer(x) = CType(73, Byte) : x += 1

buffer(x) = CType(83, Byte) : x += 1

buffer(x) = CType(75, Byte) : x += 1

'Timeout

buffer(x) = CType(16, Byte) : x += 1

buffer(x) = CType(39, Byte) : x += 1

buffer(x) = CType(0, Byte) : x += 1

buffer(x) = CType(0, Byte) : x += 1

'Control Code

buffer(x) = CType(1, Byte) : x += 1

buffer(x) = CType(5, Byte) : x += 1

buffer(x) = CType(27, Byte) : x += 1

buffer(x) = CType(0, Byte) : x += 1

buffer(x) = CType(0, Byte) : x += 1

buffer(x) = CType(0, Byte) : x += 1

buffer(x) = CType(0, Byte) : x += 1

buffer(x) = CType(0, Byte) : x += 1

buffer(x) = CType(20, Byte) : x += 1

buffer(x) = CType(2, Byte) : x += 1

buffer(x) = CType(0, Byte) : x += 1

buffer(x) = CType(0, Byte) : x += 1

buffer(x) = CType(0, Byte) : x += 1

buffer(x) = CType(0, Byte) : x += 1

buffer(x) = CType(0, Byte) : x += 1

buffer(x) = CType(0, Byte) : x += 1

buffer(x) = CType(0, Byte) : x += 1

buffer(x) = CType(0, Byte) : x += 1

buffer(x) = CType(0, Byte) : x += 1

buffer(x) = CType(0, Byte) : x += 1

buffer(x) = CType(0, Byte) : x += 1

buffer(x) = CType(0, Byte) : x += 1

buffer(x) = CType(&HEC, Byte) : x += 1

buffer(x) = CType(0, Byte) : x += 1

For x = 0 To 63

Console.Write("{0}", Chr(buffer(x)))

Next

Dim sb As IntPtr = Marshal.AllocCoTaskMem(560)

Marshal.Copy(buffer, 0, sb, 560)

Dim outBufferLength As Integer = 0

Dim success As Boolean = _

DeviceIoControl(hFile, 315400, sb, 63, sb, 560, outBufferLength,
IntPtr.Zero)

If (success) Then

Console.WriteLine("Passed ")

Console.WriteLine("Returned sb: {0}", Marshal.PtrToStringAnsi(sb,
outBufferLength))

Else

Throw New Win32Exception

Console.WriteLine("Failed outBufferLength: {0}", outBufferLength)

Console.WriteLine("Input: {0}", Marshal.PtrToStringAnsi(sb, 560))

Console.ReadLine()

End If

Marshal.FreeHGlobal(sb)

End If

Return CloseHandle(hFile)

End Function

End Class

Public Sub Main()

Console.WriteLine("Exit Code ...{0}", clsHDD.SCSI)

Console.ReadLine()

End Sub

End Module

----- Original Message -----
From: "Tanveer" <[EMAIL PROTECTED]>
To: <[EMAIL PROTECTED]>
Sent: Wednesday, September 03, 2003 7:06 AM
Subject: Re: [ADVANCED-DOTNET] Interop with DeviceIoControl


> Dear Fabian,
>
> I have converted this to VB.NET and removed the DllImport attribute...this
> seems to solve the GC-ed pointer problem...but still the return buffer is
> not as desired.
>
> The complete code is:
>
> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>
> [...] see
http://discuss.develop.com/archives/wa.exe?A2=ind0308e&L=advanced-dotnet&T=0&F=&S=&P=1797
> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>
> Any ideas...?
>
> -Tanveer

===================================
This list is hosted by DevelopMentorŪ  http://www.develop.com
NEW! ASP.NET courses you may be interested in:

2 Days of ASP.NET, 29 Sept 2003, in Redmond
http://www.develop.com/courses/2daspdotnet

Guerrilla ASP.NET, 13 Oct 2003, in Boston
http://www.develop.com/courses/gaspdotnet

View archives and manage your subscription(s) at http://discuss.develop.com

Reply via email to