RubbeRDucKy 02-13-2008, 08:31 PM I am porting an application from C++ to Visual Basic. Is wchar_t the same as a byte array in Visual Basic?
Sorry if this seems like an easy answer, but for the life of me - I can not find an answer anywhere.
OnErr0r 02-13-2008, 08:38 PM wchar_t is going to be more like an array of integers. Or, you could just use a VB string, which is just an array of integers (shorts) internally.
RubbeRDucKy 02-13-2008, 08:45 PM Here is the problem I am encountering. I am playing around with a driver that does various things to files (kernel level). I have a C++ example of how to pass the file name. I tokHere it is:
_snwprintf( path, sizeofW( path ), L"\\??\\%s", argv[ i + 1 ] );
size = (DWORD)(( wcslen( path ) + 1 ) * 2);
DeviceIoControl(hDevice, ioctl, path, size, NULL, 0, &byteRet, NULL )
Internally, this is how I interpreted the code. It takes the argument passed, for example F:\test.exe, slaps on a prefix (\??\) and then passes it to DeviceIoControl. This works excellent.
So I try the following with Visual Basic
DeviceIoControl (lDevice, IOCTL, sFileName, Len(sFileName), ByVal 0&, 0, lBytesReturned, ByVal 0&)
And the driver either returns ERROR_INVALID_NAME or ERROR_BAD_PATHNAME which makes me assume that I am passing the wrong parameters. I tried copying the file name into a byte array using CopyMemory() and then tried to pass a pointer to the array and the size of the array. It fails as well.
Any ideas?
Rockoon 02-13-2008, 08:49 PM Try 2 * Len(sFileName)
RubbeRDucKy 02-13-2008, 08:51 PM lpInBuffer: \??\F:\test.exe
nInBufferSize: 30
ERROR_BAD_PATHNAME
:(
OnErr0r 02-13-2008, 08:59 PM LenB would be acceptable too. What does your DeviceIoControl declare look like?
OnErr0r 02-13-2008, 09:02 PM If you're using the "standard" declare from the API Viewer, then the string needs to be passed ByVal, as lpInBuffer As Any is ByRef.
RubbeRDucKy 02-13-2008, 09:04 PM Private Declare Function DeviceIoControl Lib "kernel32" (ByVal hDevice As Long, ByVal dwIoControlCode As Long, _
lpInBuffer As Any, ByVal nInBufferSize As Long, lpOutBuffer As Any, ByVal nOutBufferSize As Long, lpBytesReturned As Long, _
lpOverlapped As Any) As Long
And I have tried ByVal as well. Here is my current statement.
If DeviceIoControl(lDevice, IOCTL, ByVal sFileName, LenB(sFileName), ByVal 0&, 0, lBytesReturned, ByVal 0&) = 0 Then
OnErr0r 02-13-2008, 09:12 PM Please provide more of the code. Specifically variable dimensioning and assignment.
RubbeRDucKy 02-13-2008, 09:19 PM Private Sub cmdTestFile_Click()
TestFile "\??\" & txtFile.Text
End Sub
Public Sub TestFile(sFileName$)
Dim lDevice&, lBytesReturned&
'Obtain handle to device
lDevice = CreateFile("\\.\MBAM_FILE_HANDLER", GENERIC_WRITE Or GENERIC_READ, _
FILE_SHARE_READ Or FILE_SHARE_WRITE, ByVal 0&, OPEN_EXISTING, _
FILE_ATTRIBUTE_NORMAL, 0&)
If lDevice > 0 Then
If DeviceIoControl(lDevice, IOCTL, ByVal sFileName, LenB(sFileName), ByVal 0&, 0, lBytesReturned, ByVal 0&) = 0 Then
MsgBox Err.LastDllError
End If
'Close device handle
CloseHandle lDevice
End If
End Sub
This is really the meat of the program. I create a service and delete it, but I have that in other projects and just copied and pasted the code. I use Option Explicit in all modules and forms. I am able to control the driver with all other control codes, for example:
DeviceIoControl(lDevice, IOCTL_VERSION, ByVal 0&, 0, lDeviceVersion, _
Len(lDeviceVersion), lBytesReturned, ByVal 0&)
This control code returns "2" for the internal version of the driver. I am also 100% positive the control code is correct because the C++ example can do this with the lines I stated above.
OnErr0r 02-13-2008, 09:34 PM I wonder if the API wants a null terminator included in the length? Technically, BSTRs are already null terminated. Try this before the call:
sFileName = sFileName & vbNullChar
If that's not it, then supply your definition for IOCTL
RubbeRDucKy 02-13-2008, 09:38 PM I am doing 2 checks for errors now. One with a string buffer, one with a byte array buffer. As soon as I added the null terminator, instead of both being ERROR_BAD_PATHNAME, the byte array turned into ERROR_INVALID_NAME.
My definition for the controls is below.
Private Const IOCTL_VERSION As Long = -1737048060
Private Const IOCTL As Long = -1737047868
I have checked these in C++ the same way, so if the version one works, the other does as well.
OnErr0r 02-13-2008, 10:01 PM Oops, I forgot you want to pass the unicode version of the string. ByVal sFoo is converted to ANSI. Use this instead:
If DeviceIoControl(lDevice, IOCTL, ByVal StrPtr(sFileName), LenB(sFileName), ByVal 0&, 0, lBytesReturned, ByVal 0&) = 0
RubbeRDucKy 02-13-2008, 10:03 PM Wow.
I tried StrPtr() and I tried ByVal, but never put them together. Turns out the null character is not needed. It works great now.
Thanks a lot for your help :)
|