Retrieve serial number from USB memory (Windows environment c++) - c++

I would need to retrieve the serial number from my USB memory, namely the hard disk's serial number that the manufacturer assigns. For this reason I cannot use GetVolumeInformation() as suggested in some other threads. I would need to have the "unique" number
I kindly ask you if you can share an example in C++ and Windows environment (Visual c++)
Thanks!

You can check out this article:- http://oroboro.com/usb-serial-number/
#include <WinIOCtl.h>
#include <api/usbioctl.h>
#include <Setupapi.h>
DEFINE_GUID( GUID_DEVINTERFACE_USB_DISK,
0x53f56307L, 0xb6bf, 0x11d0, 0x94, 0xf2,
0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b );
void getDeviceInfo( int vol )
{
UsbDeviceInfo info;
// get the device handle
char devicePath[7] = "\\\\.\\#:";
devicePath[4] = (char)( vol + 'A' );
HANDLE deviceHandle = CreateFile( devicePath, 0,
FILE_SHARE_READ |
FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, 0, NULL );
if ( deviceHandle == INVALID_HANDLE_VALUE )
return;
// to get the device number
DWORD volumeDeviceNumber = getDeviceNumber( deviceHandle );
CloseHandle( deviceHandle );
// Get device interface info set handle
// for all devices attached to the system
HDEVINFO hDevInfo = SetupDiGetClassDevs(
&GUID_DEVINTERFACE_USB_DISK, NULL, NULL,
DIGCF_PRESENT | DIGCF_DEVICEINTERFACE );
if ( hDevInfo == INVALID_HANDLE_VALUE )
return;
// Get a context structure for the device interface
// of a device information set.
BYTE Buf[1024];
PSP_DEVICE_INTERFACE_DETAIL_DATA pspdidd =
(PSP_DEVICE_INTERFACE_DETAIL_DATA)Buf;
SP_DEVICE_INTERFACE_DATA spdid;
SP_DEVINFO_DATA spdd;
spdid.cbSize = sizeof( spdid );
DWORD dwIndex = 0;
while ( true )
{
if ( ! SetupDiEnumDeviceInterfaces( hDevInfo, NULL,
&GUID_DEVINTERFACE_USB_DISK,
dwIndex, &spdid ))
break;
DWORD dwSize = 0;
SetupDiGetDeviceInterfaceDetail( hDevInfo, &spdid, NULL,
0, &dwSize, NULL );
if (( dwSize != 0 ) && ( dwSize <= sizeof( Buf )))
{
pspdidd->cbSize = sizeof( *pspdidd ); // 5 Bytes!
ZeroMemory((PVOID)&spdd, sizeof(spdd));
spdd.cbSize = sizeof(spdd);
long res = SetupDiGetDeviceInterfaceDetail(
hDevInfo, &spdid, pspdidd,
dwSize, &dwSize, &spdd );
if ( res )
{
HANDLE hDrive = CreateFile( pspdidd->DevicePath,0,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL );
if ( hDrive != INVALID_HANDLE_VALUE )
{
DWORD usbDeviceNumber = getDeviceNumber( hDrive );
if ( usbDeviceNumber == volumeDeviceNumber )
{
fprintf( "%s", pspdidd->DevicePath );
}
}
CloseHandle( hDrive );
}
}
dwIndex++;
}
SetupDiDestroyDeviceInfoList(hDevInfo);
return;
}
You get the device number by calling DeviceIOControl() with the handle to your device:
DWORD getDeviceNumber( HANDLE deviceHandle )
{
STORAGE_DEVICE_NUMBER sdn;
sdn.DeviceNumber = -1;
DWORD dwBytesReturned = 0;
if ( !DeviceIoControl( deviceHandle,
IOCTL_STORAGE_GET_DEVICE_NUMBER,
NULL, 0, &sdn, sizeof( sdn ),
&dwBytesReturned, NULL ) )
{
// handle error - like a bad handle.
return U32_MAX;
}
return sdn.DeviceNumber;
}
Next here is a method to recognize if a volume is removable media (e.g. like a usb or firewire disk):
bool isRemovableMedia( s32 vol )
{
char rootPath[5] = "#:\\";
rootPath[0] = (char)( vol + 'A' );
char szDosDeviceName[MAX_PATH];
char dosDevicePath[3] = "#:";
// get the drive type
UINT DriveType = GetDriveType( rootPath );
if ( DriveType != DRIVE_REMOVABLE )
return false;
dosDevicePath[0] = (char)( vol + 'A' );
QueryDosDevice( dosDevicePath, szDosDeviceName, MAX_PATH );
if ( strstr( szDosDeviceName,"\\Floppy") != NULL )
{
// its a floppy
return false;
}
return true;
}

Related

How to get word list using ISpLexicon::GetWords?

I'm developping a Text-To-Speech application using Microsoft SAPI. I found out that it is possible to add customized prononciations of words in a dictionnary (correct me if I'm wrong). I implemented a function which allows to add words into this dictionnary. Here is my code:
int addPrononciation( const char* addPron, const char* phon )
{
hr = cpLexicon.CoCreateInstance( CLSID_SpLexicon );
hr = cpContainerLexicon.CoCreateInstance( CLSID_SpLexicon );
hr = SpEnumTokens( SPCAT_VOICES, NULL, NULL, &cpEnum );
cpEnum->Item( saveVoice, &cpVoiceToken ); //get saveVoice token defined at line 136
cpVoice->SetVoice( cpVoiceToken ); //Initialization of the voice
hr = cpContainerLexicon->AddLexicon( cpLexicon, eLEXTYPE_APP );
langId = MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US );
hr = SpCreatePhoneConverter( langId, NULL, NULL, &cpPhoneConv );
int wchars_num = MultiByteToWideChar( CP_ACP, 0, addPron, -1, NULL, 0 );
wchar_t* pronWstr = new wchar_t[ wchars_num ];
MultiByteToWideChar( CP_ACP, 0, addPron, -1, pronWstr, wchars_num );
int phonWchars_num = MultiByteToWideChar( CP_ACP, 0, phon, -1, NULL, 0 );
wchar_t* phonWstr = new wchar_t[ phonWchars_num ];
MultiByteToWideChar( CP_ACP, 0, phon, -1, phonWstr, phonWchars_num );
if(SUCCEEDED( hr ))
{
hr = cpPhoneConv->PhoneToId( phonWstr, wszId );
hr = cpVoice->Speak( phonWstr, SPF_DEFAULT, NULL );
hr = cpLexicon->AddPronunciation( pronWstr, langId, SPPS_Noun, wszId );
hr = cpVoice->Speak( pronWstr, SPF_DEFAULT, NULL );
if( SUCCEEDED( hr ) )
{
printf( "Success\n" );
}
else
{
printf( "Failed\n" );
}
}
cpEnum.Release();
cpVoiceToken.Release();
cpContainerLexicon.Release();
cpLexicon.Release();
cpPhoneConv.Release();
delete new wchar_t[ wchars_num ];
delete new wchar_t[ phonWchars_num ];
return true;
}
Now I would like to list these words using ISpLexicon::GetWords.
I already read the documentation on the Microsoft website and tried to implement the function, but I can't figure out how to initialize the variable spWordList.
Here is my code:
ZeroMemory( &spWordList, sizeof( spWordList ) );
if( SUCCEEDED( hr ) )
{
hr = cpLexicon->GetWords( eLEXTYPE_APP, &dwGeneration, &dwCookie, &spWordList );
printf( "Words: %ls\n", spWordList ); //print words but the output is null
}
CoTaskMemFree( spWordList.pvBuffer );
I'm triying to print the words, but the output is null. I think the spWordList variable is not initialized. Here is a screenshot of the variable values.
How can I initialize it?
I found out how to initialize spWordList. You have to replace eLEXTYPE_APP with eLEXTYPE_USER. However, you can keep both of them like I did. Below you will find an example on how it lists the words.
ZeroMemory( &spWordList, sizeof( spWordList ) );
hr = S_FALSE;
if( hr == S_FALSE )
{
hr = cpLexicon->GetWords( eLEXTYPE_USER | eLEXTYPE_APP, &dwGeneration, &dwCookie, &spWordList );
for( spWord = spWordList.pFirstWord; spWord != NULL; spWord = spWord->pNextWord )
{
for( spWordPron = spWord->pFirstWordPronunciation; spWordPron != NULL; spWordPron = spWordPron->pNextWordPronunciation )
{
printf( "Words in dictionnary: %i\n", dwGeneration );
printf( "Word: %ls\n", spWord->pszWord );
//you can also display the pronunciation of words if you wish
}
}
}
CoTaskMemFree( spWordList.pvBuffer );
In the code, I loop through the entire dictionnary. Notice that the listed words are displayed randomly. I'll update my answer if I find other important information about ISpLexicon::GetWords

How to determinate if my application is running under SYSTEM account or not?

How could I decide if my application is running under LocalSystem Account or not? Is there an easy way to do that?
Thanks!
Thanks for your help, but I might have found a way. Not the best, I know, but it works.
BOOL CheckIfRunningAsSYSTEM( VOID )
{
DWORD i, dwSize = 0, dwResult = 0;
HANDLE hToken;
PTOKEN_USER Ptoken_User;
// Open a handle to the access token for the calling process.
if ( !OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &hToken ) )
{
printf( "OpenProcessToken Error %u\n", GetLastError() );
return FALSE;
}
// Call GetTokenInformation to get the buffer size.
if ( !GetTokenInformation( hToken, TokenUser, NULL, dwSize, &dwSize ) )
{
dwResult = GetLastError();
if ( dwResult != ERROR_INSUFFICIENT_BUFFER )
{
printf( "GetTokenInformation Error %u\n", dwResult );
return FALSE;
}
}
// Allocate the buffer.
Ptoken_User = ( PTOKEN_USER )GlobalAlloc( GPTR, dwSize );
// Call GetTokenInformation again to get the group information.
if ( !GetTokenInformation( hToken, TokenUser, Ptoken_User, dwSize, &dwSize ) )
{
printf( "GetTokenInformation Error %u\n", GetLastError() );
return FALSE;
}
LPWSTR SID = NULL;
if ( !ConvertSidToStringSidW( Ptoken_User->User.Sid, &SID ) )
{
printf( "\nConvertSidToStringSidW failed. Error = %d", GetLastError() );
return FALSE;
}
else printf( "\nConvertSidToStringSidW succeeded." );
if ( _wcsicmp( L"S-1-5-18", SID ) == 0 ) printf( "\nRunning under SYSTEM" );
else printf( "\nNOT running under SYSTEM" );
if ( Ptoken_User ) GlobalFree( Ptoken_User );
return TRUE;
}//CheckIfRunningAsSYSTEM

How do I find the port name for a bluetooth device with a specific device name?

How do I find the port name for a bluetooth device with a specific device name?
I have this code, which enumerates all bluetooth devices, but doesn't give me their port name:
HBLUETOOTH_DEVICE_FIND founded_device;
BLUETOOTH_DEVICE_INFO device_info;
device_info.dwSize = sizeof(device_info);
BLUETOOTH_DEVICE_SEARCH_PARAMS search_criteria;
search_criteria.dwSize = sizeof(BLUETOOTH_DEVICE_SEARCH_PARAMS);
search_criteria.fReturnAuthenticated = TRUE;
search_criteria.fReturnRemembered = FALSE;
search_criteria.fReturnConnected = FALSE;
search_criteria.fReturnUnknown = FALSE;
search_criteria.fIssueInquiry = FALSE;
search_criteria.cTimeoutMultiplier = 0;
founded_device = BluetoothFindFirstDevice(&search_criteria, &device_info);
if(founded_device == NULL)
return -1;
do {
wstring ws = device_info.szName;
cout << string(ws.begin(), ws.end()) << endl;
} while (BluetoothFindNextDevice(founded_device, &device_info));
And then I have this code, which enumerates all port names but doesn't give me the device name:
DWORD bytesNeeded = 0;
DWORD portCount = 0;
BOOL ret = EnumPorts(nullptr, 2, nullptr, 0, &bytesNeeded, &portCount);
BYTE *ports = new BYTE[bytesNeeded];
if(EnumPorts(nullptr, 2, (LPBYTE)ports, bytesNeeded, &bytesNeeded, &portCount))
{
PORT_INFO_2 *portInfo = (PORT_INFO_2*)ports;
for(DWORD i = 0; i < portCount; ++i)
cout << portInfo[i].pPortName << endl;
}
delete [] ports;
I need to automatically connect to a specific device when my app is started, so I need to either get the port name for the bluetooth device in the first piece of code so I can connect to it, or check each portname in the second piece of code to make sure it's the right device before connecting to it.
How do I do it?
I remember struggling with this in the past.
the only solution i found was to use sockets for communicating with the Bluetooth device using its address, then use the send() and recv() methods for communicating with the device.
// assuming you have the BT device address in blueToothDeviceAddr;
char blueToothDeviceAddr[18];
SOCKET sock;
SOCKADDR_BTH sa = { 0,0,0,0 };
int sa_len = sizeof(sa);
// initialize windows sockets
WORD wVersionRequested;
WSADATA wsaData;
wVersionRequested = MAKEWORD( 2, 0 );
if( WSAStartup( wVersionRequested, &wsaData ) != 0 )
{
ExitProcess(100);
}
// parse the specified Bluetooth address
if( SOCKET_ERROR == WSAStringToAddress( blueToothDeviceAddr, AF_BTH,
NULL, (LPSOCKADDR) &sa, &sa_len ) )
{
ExitProcess(101);
}
// query it for the right port
// create the socket
sock = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM);
if( SOCKET_ERROR == sock )
{
ExitProcess(102);
}
// fill in the rest of the SOCKADDR_BTH struct
GUID pService = (GUID)SerialPortServiceClass_UUID;
SOCKADDR_BTH outSA;
sa.port = SDPGetPort(blueToothDeviceAddr, (LPGUID) &pService,&outSA);
if( sa.port == 0 )
{
ExitProcess(103);
}
// in case you have a pass code you need to register for authetication callback
// look the web for this part
// connect to the device
if( SOCKET_ERROR == connect( sock, (LPSOCKADDR) &outSA, sa_len ) )
{
int lastError = GetLastError();
ExitProcess(105);
}
Under the key:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\BTHENUM
you can find a subkey which has a list of keys containing the device address.
Under this last key, you can find a subkey named Device Parameters which finally has the PortName value.
The code is written in C++ with MFC libraries and is tested under Windows XP, 7 and 10. I hope it helps you !
// Returns the outgoing COM port of a bluetooth device given by address
int GetBluetoothCOM( CString sAddr )
{
int iPort = 0;
HKEY hKey_1;
DWORD KeyNdx_1 = 0;
DWORD MaxKeyLen_1;
char KeyNam_1[ MAX_PATH + 1 ];
LONG RetVal_1;
sAddr.MakeUpper();
sAddr.Replace( ":", "" );
sAddr.Replace( " ", "" );
// Enumerate keys under: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\BTHENUM
RegOpenKeyEx( HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Enum\\BTHENUM", NULL, KEY_READ | KEY_ENUMERATE_SUB_KEYS, &hKey_1 );
while( true )
{
MaxKeyLen_1 = MAX_PATH;
RetVal_1 = RegEnumKeyEx( hKey_1, KeyNdx_1, KeyNam_1, &MaxKeyLen_1, NULL, NULL, NULL, NULL );
if( RetVal_1 == ERROR_NO_MORE_ITEMS )
{
break;
}
if( RetVal_1 == ERROR_SUCCESS )
{
HKEY hKey_2;
DWORD KeyNdx_2 = 0;
DWORD MaxKeyLen_2;
char KeyNam_2[ MAX_PATH + 1 ];
LONG RetVal_2;
// Enumerate subkeys
RegOpenKeyEx( HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Enum\\BTHENUM\\" + CString( KeyNam_1 ), NULL, KEY_READ | KEY_ENUMERATE_SUB_KEYS, &hKey_2 );
while( true )
{
MaxKeyLen_2 = MAX_PATH;
RetVal_2 = RegEnumKeyEx( hKey_2, KeyNdx_2, KeyNam_2, &MaxKeyLen_2, NULL, NULL, NULL, NULL );
if( RetVal_2 == ERROR_NO_MORE_ITEMS )
{
break;
}
if( RetVal_2 == ERROR_SUCCESS )
{
// Find out if the key name contains &ADDRESS_
CString sKey = "SYSTEM\\CurrentControlSet\\Enum\\BTHENUM\\" + CString( KeyNam_1 ) + "\\" + CString( KeyNam_2 );
sKey.MakeUpper();
if( sKey.Find( "&" + sAddr + "_" ) != -1 )
{
HKEY hKey;
char szPort[ 100 + 1 ];
DWORD dwLen = 100;
// I find out the device
RegOpenKeyEx( HKEY_LOCAL_MACHINE, sKey + "\\Device Parameters", 0, KEY_READ, &hKey );
if( RegQueryValueEx( hKey, "PortName", NULL, NULL, ( LPBYTE ) &szPort, &dwLen ) == ERROR_SUCCESS )
{
szPort[ dwLen ] = 0;
CString sPort = CString( szPort );
sPort.MakeUpper();
if( sPort.Find( "COM" ) == -1 )
{
RegCloseKey( hKey );
continue;
}
sPort.Replace( "COM", "" );
sPort.Trim();
iPort = atoi( sPort.GetBuffer() );
if( iPort != 0 )
{
RegCloseKey( hKey );
break;
}
}
RegCloseKey( hKey );
}
}
++KeyNdx_2;
}
RegCloseKey( hKey_2 );
if( iPort != 0 )
{
break;
}
}
++KeyNdx_1;
};
RegCloseKey( hKey_1 );
return iPort;
}

Serial port writes succeed, reads fail

After I run Hyper Terminal or Docklight, my program works (writes and reads OK). But if I never run any of those, all my reads fail.
So I guess I must be missing something in my serial port initialization code, but I can't figure out what. Here it is:
Serial port initialization:
bool CSerialPortDrivenHardware::InitSerialPort(){
m_SerialPort.Config( m_SerialPortConfig );
bool success = ( m_SerialPort.Open( m_SerialPortName ) == TRUE );
if( !success )
Log( LOG_TYPE_ERROR, "CSerialPortDrivenHardware", "InitSerialPort", "Could not establish serial port connection" );
else{
m_SerialPort.SetControlBit( DTR_CONTROL_BIT );
m_SerialPort.SetControlBit( RTS_CONTROL_BIT );
}
return success;
}
Serial port class (relevant code):
BOOL CSerialPort::Config( SConfig sConfig ) {
if( !m_hFile ) return FALSE;
DCB dcb;
if ( !::GetCommState( m_hFile, &dcb ) ) {
m_dwLastError = ::GetLastError();
return FALSE;
}
dcb.BaudRate = sConfig.dwBaudRate;
dcb.Parity = sConfig.bParity;
dcb.StopBits = sConfig.bStopBits;
dcb.ByteSize = sConfig.bDataBits;
if ( !::SetCommState( m_hFile, &dcb ) ) {
m_dwLastError = ::GetLastError();
return FALSE;
}
::Sleep(200);
return TRUE;
}
BOOL CSerialPort::Open( LPCSTR cszCOM ) {
CHAR sPortName[256] = "\\\\.\\";
strcat_s( sPortName, cszCOM );
m_strPortName = sPortName;
if( m_hFile )
return FALSE;
m_hFile = ::CreateFile( m_strPortName.c_str(), GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if( m_hFile == INVALID_HANDLE_VALUE )
m_hFile = NULL;
if( !m_hFile )
return FALSE;
SetFlags( 0 );
return TRUE;
}
void CSerialPort::SetFlags( DWORD dwFlags ) {
if( dwFlags & READMODE_BLOCKING )
SetTimeout( INFINITE );
else
SetTimeout( 0 );
}
void CSerialPort::SetTimeout( DWORD dwTimeout ) {
COMMTIMEOUTS sCommTimeouts;
if( !::GetCommTimeouts( m_hFile, &sCommTimeouts ) ) {
m_dwLastError = ::GetLastError();
return;
}
sCommTimeouts.ReadIntervalTimeout = 0;
sCommTimeouts.ReadTotalTimeoutMultiplier = 0;
sCommTimeouts.ReadTotalTimeoutConstant = dwTimeout;
if ( !::SetCommTimeouts( m_hFile, &sCommTimeouts ) )
m_dwLastError = ::GetLastError();
}
BOOL CSerialPort::SetControlBit( ESerialPortControlBit eControlBit ) {
if( !m_hFile )
return FALSE;
BOOL bResult = FALSE;
switch( eControlBit ) {
case DTR_CONTROL_BIT:
bResult = ::EscapeCommFunction( m_hFile, SETDTR );
break;
case RTS_CONTROL_BIT:
bResult = ::EscapeCommFunction( m_hFile, SETRTS );
break;
}
return bResult;
}
You should first open port, than configure. And your code does it in opposite direction. That's why your configure code does not work and port just opens with default settings.
Just look your code:
BOOL CSerialPort::Config( SConfig sConfig ) {
if( !m_hFile ) return FALSE;
....
And m_hFile is set in CSerialPort::Open
BOOL CSerialPort::Open( LPCSTR cszCOM ) {
CHAR sPortName[256] = "\\\\.\\";
strcat_s( sPortName, cszCOM );
m_strPortName = sPortName;
if( m_hFile )
return FALSE;
m_hFile = ::CreateFile( m_strPortName.c_str(), GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
.....
It seems your hyper terminal program adjust default settings and that's why when you open port after using `hyper terminal it opens with correct settings.

Read Epson Printer Status using C++ and ESC/P

I'm trying to get the status of a PLQ-20 Espon printer, using C++, but with no success.
I tried that using GDI API and Escape function with PASSTHROUGH parameter, but the printer never understands the escape codes with that function.
I tried to use WIN 32 API and the example code found here. That works for sending some escape codes like BEL (to sound the buzzer) or FF (Form Feed, to eject paper from the rear of the printer), but not ESC O (to eject paper from the front of the printer), ESC 0 / ESC 1 (to initialize the printer / reset errors).
So, I tried this way to get the status of the printer with a ESC j escape code but with no success (the ReadPrinter function returns 0). Moreover, the print buffer seems to be not empty nonetheless I only send escape commands.
I don't know if I do a mistake sending escape codes or trying to read the printer status.
If anyone could post examples, it could be fine for everyone because it's hard to find them on the web.
Below is the code I use to send commands and read the result
#include <Windows.h>
#include <StdIO.h>
// **********************************************************************
// PrintError - uses printf() to display error code information
//
// Params:
// dwError - the error code, usually from GetLastError()
// lpString - some caller-defined text to print with the error info
//
// Returns: void
//
void PrintError( DWORD dwError, LPCTSTR lpString )
{
#define MAX_MSG_BUF_SIZE 512
TCHAR *msgBuf;
DWORD cMsgLen;
cMsgLen = FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_ALLOCATE_BUFFER | 40, NULL, dwError,
MAKELANGID(0, SUBLANG_ENGLISH_US), (LPTSTR) &msgBuf,
MAX_MSG_BUF_SIZE, NULL );
printf("%s Error [%d]:: %s\n", lpString, dwError, msgBuf );
LocalFree( msgBuf );
#undef MAX_MSG_BUF_SIZE
}
// end PrintError
// **********************************************************************
// **********************************************************************
// ReadFileWithAlloc - allocates memory for and reads contents of a file
//
// Params:
// szFileName - NULL terminated string specifying file name
// pdwSize - address of variable to receive file bytes size
// ppBytes - address of pointer which will be allocated and contain file bytes
//
// Returns: TRUE for success, FALSE for failure.
//
// Notes: Caller is responsible for freeing the memory using GlobalFree()
//
BOOL ReadFileWithAlloc( LPTSTR szFileName, LPDWORD pdwSize, LPBYTE *ppBytes )
{
HANDLE hFile;
DWORD dwBytes;
BOOL bSuccess = FALSE;
// Validate pointer parameters
if( ( pdwSize == NULL ) || ( ppBytes == NULL ) )
return FALSE;
// Open the file for reading
hFile = CreateFile( szFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
if( hFile == INVALID_HANDLE_VALUE )
{
PrintError( GetLastError(), TEXT("CreateFile()") );
return FALSE;
}
// How big is the file?
*pdwSize = GetFileSize( hFile, NULL );
if( *pdwSize == (DWORD)-1 )
PrintError( GetLastError(), TEXT("GetFileSize()") );
else
{
// Allocate the memory
*ppBytes = (LPBYTE)GlobalAlloc( GPTR, *pdwSize );
if( *ppBytes == NULL )
PrintError( GetLastError(), TEXT("Failed to allocate memory\n") );
else
{
// Read the file into the newly allocated memory
bSuccess = ReadFile( hFile, *ppBytes, *pdwSize, &dwBytes, NULL );
if( ! bSuccess )
PrintError( GetLastError(), TEXT("ReadFile()") );
}
}
// Clean up
CloseHandle( hFile );
return bSuccess;
}
// End ReadFileWithAlloc
// **********************************************************************
// **********************************************************************
// RawDataToPrinter - sends binary data directly to a printer
//
// Params:
// szPrinterName - NULL terminated string specifying printer name
// lpData - Pointer to raw data bytes
// dwCount - Length of lpData in bytes
//
// Returns: TRUE for success, FALSE for failure.
//
BOOL RawDataToPrinter( LPTSTR szPrinterName, LPBYTE lpData, DWORD dwCount )
{
HANDLE hPrinter;
DOC_INFO_1 DocInfo;
DWORD dwJob;
DWORD dwBytesWritten;
// Need a handle to the printer.
if( ! OpenPrinter( szPrinterName, &hPrinter, NULL ) )
{
PrintError( GetLastError(), TEXT("OpenPrinter") );
return FALSE;
}
// Fill in the structure with info about this "document."
DocInfo.pDocName = TEXT("My Document");
DocInfo.pOutputFile = NULL;
DocInfo.pDatatype = TEXT("RAW");
// Inform the spooler the document is beginning.
if( (dwJob = StartDocPrinter( hPrinter, 1, (LPBYTE)&DocInfo )) == 0 )
{
PrintError( GetLastError(), TEXT("StartDocPrinter") );
ClosePrinter( hPrinter );
return FALSE;
}
// Start a page.
if( ! StartPagePrinter( hPrinter ) )
{
PrintError( GetLastError(), TEXT("StartPagePrinter") );
EndDocPrinter( hPrinter );
ClosePrinter( hPrinter );
return FALSE;
}
// Send the data to the printer.
if( ! WritePrinter( hPrinter, lpData, dwCount, &dwBytesWritten ) )
{
PrintError( GetLastError(), TEXT("WritePrinter") );
EndPagePrinter( hPrinter );
EndDocPrinter( hPrinter );
ClosePrinter( hPrinter );
return FALSE;
}
/*********************************/
// CODE USED TO READ THE PRINTER
LPBYTE retData = NULL;
LPDWORD bbr = NULL;
if(ReadPrinter(hPrinter, retData, 1, bbr))
{
printf("OUT : %i", retData);
}
else
{
printf("Failed to read printer");
}
/*********************************/
// End the page.
if( ! EndPagePrinter( hPrinter ) )
{
PrintError( GetLastError(), TEXT("EndPagePrinter") );
EndDocPrinter( hPrinter );
ClosePrinter( hPrinter );
return FALSE;
}
// Inform the spooler that the document is ending.
if( ! EndDocPrinter( hPrinter ) )
{
PrintError( GetLastError(), TEXT("EndDocPrinter") );
ClosePrinter( hPrinter );
return FALSE;
}
// Tidy up the printer handle.
ClosePrinter( hPrinter );
// Check to see if correct number of bytes were written.
if( dwBytesWritten != dwCount )
{
//printf( TEXT("Wrote %d bytes instead of requested %d bytes.\n"), dwBytesWritten, dwCount );
return FALSE;
}
return TRUE;
}
// End RawDataToPrinter
// **********************************************************************
int main( int argc, char* argv[] )
{
LPBYTE pBytes = NULL;
int textSize = 2;
DWORD dwSize = textSize;
pBytes = (LPBYTE) malloc (textSize*sizeof(BYTE));
pBytes[0] = 0x1B;
pBytes[1] = 0x6A;
if( ! RawDataToPrinter(L"EPSON PLQ-20 ESC/P2", pBytes, dwSize) )
printf("Failed to send data to printer.\n" );
else
printf("Data sent to printer.\n" );
free(pBytes);
return 0;
}
// end main
// **********************************************************************
Thanks!
The product brochure for the Epson PLQ-20, states that printer supports Olivetti PR2E, Epson ESC/P2, Wincor 4915, IBM PPDS, IBM 4722 FP emulation.
It looks like you are using ESC/P2 commands, however after a quick search I cannot find any command to read the current status of the printer.
ESC/P2 References
http://www.pcguru.plus.com/escp2.html
Complete Manual
http://gimp-print.sourceforge.net/developer-html/c464.html
Based on the above references, the command that controls how the paper is ejected is ESC EM