Porting from C++

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 :)

EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum