From: Udo on
Dear All!

Is it possible to convert the following C++ Code to VB6?


/* Code to find the device path for a usbprint.sys controlled
* usb printer and print to it
*/

#include <usb.h>
#include <usbiodef.h>
#include <usbioctl.h>
#include <usbprint.h>
#include <setupapi.h>
#include <devguid.h>
#include <wdmguid.h>


/* This define is required so that the GUID_DEVINTERFACE_USBPRINT variable is
* declared an initialised as a static locally, since windows does not
include it in any
* of its libraries
*/

#define SS_DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
static const GUID DECLSPEC_SELECTANY name \
= { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }

SS_DEFINE_GUID(GUID_DEVINTERFACE_USBPRINT, 0x28d78fad, 0x5a12, 0x11D1, 0xae,
0x5b, 0x00, 0x00, 0xf8, 0x03, 0xa8, 0xc2);

void SomeFunctionToWriteToUSB()
{
HDEVINFO devs;
DWORD devcount;
SP_DEVINFO_DATA devinfo;
SP_DEVICE_INTERFACE_DATA devinterface;
DWORD size;
GUID intfce;
PSP_DEVICE_INTERFACE_DETAIL_DATA interface_detail;

intfce = GUID_DEVINTERFACE_USBPRINT;
devs = SetupDiGetClassDevs(&intfce, 0, 0, DIGCF_PRESENT |
DIGCF_DEVICEINTERFACE);
if (devs == INVALID_HANDLE_VALUE) {
return;
}
devcount = 0;
devinterface.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
while (SetupDiEnumDeviceInterfaces(devs, 0, &intfce, devcount,
&devinterface)) {
/* The following buffers would normally be malloced to he correct size
* but here we just declare them as large stack variables
* to make the code more readable
*/
char driverkey[2048];
char interfacename[2048];
char location[2048];
char description[2048];

/* If this is not the device we want, we would normally continue onto
the next one
* so something like if (!required_device) continue; would be added here
*/
devcount++;
size = 0;
/* See how large a buffer we require for the device interface details */
SetupDiGetDeviceInterfaceDetail(devs, &devinterface, 0, 0, &size, 0);
devinfo.cbSize = sizeof(SP_DEVINFO_DATA);
interface_detail = calloc(1, size);
if (interface_detail) {
interface_detail->cbSize = sizeof (SP_DEVICE_INTERFACE_DETAIL_DATA);
devinfo.cbSize = sizeof(SP_DEVINFO_DATA);
if (!SetupDiGetDeviceInterfaceDetail(devs, &devinterface,
interface_detail, size, 0, &devinfo)) {
free(interface_detail);
SetupDiDestroyDeviceInfoList(devs);
return;
}
/* Make a copy of the device path for later use */
strcpy(interfacename, interface_detail->DevicePath);
free(interface_detail);
/* And now fetch some useful registry entries */
size = sizeof(driverkey);
driverkey[0] = 0;
if (!SetupDiGetDeviceRegistryProperty(devs, &devinfo, SPDRP_DRIVER,
&dataType, (LPBYTE)driverkey, size, 0)) {
SetupDiDestroyDeviceInfoList(devs);
return;
}
size = sizeof(location);
location[0] = 0;
if (!SetupDiGetDeviceRegistryProperty(devs, &devinfo,
SPDRP_LOCATION_INFORMATION, &dataType, (LPBYTE)location, size, 0)) {
SetupDiDestroyDeviceInfoList(devs);
return;
}
usbHandle = CreateFile(interfacename, GENERIC_WRITE, FILE_SHARE_READ,
NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL |
FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (usbHandle != INVALID_HANDLE_VALUE) {
/* Now perform all the writing to the device ie.
* while (some condition) WriteFile(usbHandle, buf, size, &bytes_written);
*/
CloseHandle(usbHandle);
}
}
}
SetupDiDestroyDeviceInfoList(devs);
}
From: Mike Williams on
"Udo" <Udo(a)discussions.microsoft.com> wrote in message
news:8FBB2BC4-2CB3-408D-9326-4A187649002D(a)microsoft.com...

> Is it possible to convert the following C++ Code to VB6?

What actual task are you trying to perform? Do you want to allow your user
to select a printer and to then print something to that printer? If so then
there are lots of different ways to do it. At the very simplest you can just
place a standard CommonDialog Control on your Form and use
CommonDialog1.ShowPrinter and then use Printer.Print "Some Text" followed by
Printer.EndDoc to print a page to whatever printer the user selected in the
dialog, whether it is USB connected or not. Or is there something else you
are trying to do?

Mike



From: Udo on
Hello Mike!

I want to send special PCL commands to the USB printer. After that I want to
receive the reply from the printer.

For sending data direct to the printer I used:
Declare Function WritePrinter Lib "winspool.drv" (ByVal hPrinter As Long,
pBuf As Any, ByVal cdBuf As Long, pcWritten As Long) As Long
This works fine!

For receiving data from the printer I used the following function but
without success:
Declare Function ReadPrinter Lib "winspool.drv" Alias "ReadPrinter" (ByVal
hPrinter As Long, ByRef pBuf As Any, ByVal cbBuf As Long, ByRef pNoBytesRead
As Long) As Long

In the web I don't found any solution for ReadPrinter. According to the C++
forum my problem can only be solved with the attached solution!?


"Mike Williams" wrote:

> "Udo" <Udo(a)discussions.microsoft.com> wrote in message
> news:8FBB2BC4-2CB3-408D-9326-4A187649002D(a)microsoft.com...
>
> > Is it possible to convert the following C++ Code to VB6?
>
> What actual task are you trying to perform? Do you want to allow your user
> to select a printer and to then print something to that printer? If so then
> there are lots of different ways to do it. At the very simplest you can just
> place a standard CommonDialog Control on your Form and use
> CommonDialog1.ShowPrinter and then use Printer.Print "Some Text" followed by
> Printer.EndDoc to print a page to whatever printer the user selected in the
> dialog, whether it is USB connected or not. Or is there something else you
> are trying to do?
>
> Mike

From: Mike Williams on
"Udo" <Udo(a)discussions.microsoft.com> wrote in message
news:CF6AB872-F13C-4806-99E5-F8A6DE4C5FDB(a)microsoft.com...

> Hello Mike! I want to send special PCL commands to the USB printer.
> After that I want to receive the reply from the printer.
> For sending data direct to the printer I used:
> Declare Function WritePrinter Lib "winspool.drv" (ByVal hPrinter
> As Long, pBuf As Any, ByVal cdBuf As Long, pcWritten As Long)
> As Long. This works fine!
> For receiving data from the printer I used the following function but
> without success:
> Declare Function ReadPrinter Lib "winspool.drv" Alias "ReadPrinter"
> (ByVal hPrinter As Long, ByRef pBuf As Any, ByVal cbBuf As Long,
> ByRef pNoBytesRead As Long) As Long

Oh right. Well I could have helped you with writing raw data to the USB
printer, in fact I would have suggested exactly the method you have just
posted, but I'm afraid I can't help you with reading data from it because
I've never actually had the need to do so myself. I might have a look at it
one day if I get time, but at the moment I'm afraid I can't help you with
it.

Mike



From: expvb on
You can get the API declaration from here(See the download link to the
right):

http://www.activevb.de/rubriken/apiviewer/index-apiviewer.html

The declaration seems to be correct, except the first parameter for each
function, which is the handle, this needs to be passed ByVal, not ByRef.
Also, SetupDiGetClassDevs is incorrectly declared as Sub. It needs to a
function returning a Long.

Finally, it seems that all the purpose of using SetupDi functions is to get
SymbolicName value from the registry then use it with CreateFile. If this is
an in-house application, then you could get the SymbolicName value from the
registry and use it with VB's built-in Open statement. SymbolicName can be
found here:

HKLM\SYSTEM\CurrentControlSet\Enum\USB\Vid_<SomeNumber>&Pid_<SomeNumber>\<SomeSubkey>\Device
Parameters

Under <SomeSubkey> above, there are several values with GUID, make sure that
they match the one in the source code and device that you are talking to.
Once you get SymbolicName, you can use VB to talk to it. Example:

Private Sub Form_Load()
Dim f As Integer
Dim SymbolicName As String
Dim b As Byte

SymbolicName = "\??\USB#....."
f = FreeFile
Open SymbolicName For Binary Access Read Write Shared As f
b = 27
Put f, , b
Get f, , b
Close f
End Sub