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

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

Related

CreateDC() method,while setting up a Printer fails for certain PRINTERs as well as in certain Windows Environment

I have installed a HP Printer and added it to my list of Printer devices.
I am trying to use the following code:
QString printerName = "HP Designjet 500 24+HPGL2 Card";
DWORD infoSize, numBytes;
HANDLE hPrinter;
bool ok = OpenPrinter( ( LPWSTR )printerName.utf16(), ( LPHANDLE )&hPrinter, 0 );
if ( !ok )
{
qErrnoWarning( "QWin32PrintEngine::initialize: OpenPrinter failed" );
return;
}
GetPrinter( hPrinter, 2, NULL, 0, &infoSize );
HGLOBAL hMem;
hMem = GlobalAlloc( GHND, infoSize );
PRINTER_INFO_2 *pInfo;
pInfo = ( PRINTER_INFO_2* )GlobalLock( hMem );
ok = GetPrinter( hPrinter, 2, ( LPBYTE )pInfo, infoSize, &numBytes );
if ( !ok )
{
qErrnoWarning( "QWin32PrintEngine::initialize: GetPrinter failed" );
}
DEVMODE *devMode;
devMode = pInfo->pDevMode;
HDC hdc = NULL;
hdc = CreateDC( NULL, ( LPCWSTR )printerName.utf16(), 0, devMode );
Now,the CreateDC() method fails.I even tried to return the Error using GetLastError() method, and it returned as "203",which corresponds to "ERROR_ENVVAR_NOT_FOUND".
I am completely clueless as of now.
I would be really glad,if someone can help me regarding this.
Thanks in Advance.

c++ - The result of popen is null

I want to run netstat -ano command using popen.
And I want to show the result of executing the command through MFC List Control.
Run the following code from the win32 console project and it will run correctly.
However, if run it on MFC project, popen("netstat -ano *.c","r") result is null.
The development environment is VC6.0.
Please let me know why null is coming. Thank you :)
FILE *fp = NULL;
char line[10240];
char* network[5];
int nIndexNetwork = 0;
if( (fp=popen("netstat -ano *.c","r")) == NULL)
{
printf("[%d:%s]\n", errno, strerror(errno));
CString str;
str.Format("%d",errno);
GetDlgItem(IDC_EDIT1)->SetWindowText(str);
return 1;
}
while(fgets(line, 10240, fp) != NULL)
{
char *word = strtok(line, " ");
while (word != NULL) // 자른 문자열이 나오지 않을 때까지 반복
{
network[nIndexNetwork] = word;
nIndexNetwork++;
printf("%s\n", network[nIndexNetwork-1]); // 자른 문자열 출력
word = strtok(NULL, " "); // 다음 문자열을 잘라서 포인터를 반환
}
nIndexNetwork = 0;
m_ctlList_network.AddItem(network[4],
network[0],
network[1],
network[2],
network[3]);
}
pclose(fp);
return 0;
It does not look like popen will work in a Win32 app. You will have to use, Creating a Child Process with Redirected Input and Output. I have used this example to get the output of a process and display it in MFC. It is not as simple as popen, but it works. I have not worked with this code in years but will post it. This first part just goes in some tool box, it is reusable for any process.
//console_pipe.h
// the console_pipe.cpp declarations .....................................................
//C style use
HRESULT RunProcess( HWND hWnd //Window to 'SendMessage' to
,WORD idPost //ID for message with the data pointer in wparam
,WORD idEnd //ID for message notifying the process has ended
,LPCTSTR psFileExe //Path.File of process to run
,LPCTSTR psCmdLine= NULL //command line
);
//C++
extern HANDLE hGlobalThread;
extern HANDLE hChildProcess;
class RunPipeConsoleProcess
{
HANDLE hProcess;
WORD idPost;
WORD idEnd;
CString strExeFile;
CString strArguments;
public:
void SetMessageIDs( WORD inPost, WORD inEnd ) { idPost= inPost; idEnd= inEnd; }
void SetExecutable( LPCTSTR psExe ) { strExeFile= psExe; }
void SetArguments( LPCTSTR psArg ) { strArguments= psArg; }
bool StartThread( HWND hPostTo ) { hProcess= hChildProcess; return RunProcess( hPostTo, idPost, idEnd, strExeFile, strExeFile + strArguments ) == S_OK; }
bool StopThread( )
{
if( hGlobalThread && hProcess )
TerminateProcess( hProcess, -1 );
// ::PostThreadMessage( (DWORD)hGlobalThread, ID_CONSOLE_THREAD_STOP, 0, 0 );
return true;
}
};
//console_pipe.cpp
#include "stdafx.h"
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <strsafe.h>
#ifndef DWORD
typedef unsigned long DWORD;
#endif
#define CONPIPE_BUF_SIZE 1024
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/*++
Copyright (c) 1998 Microsoft Corporation
Module Name:
Redirect.c
Description:
This sample illustrates how to spawn a child console based
application with redirected standard handles.
The following import libraries are required:
user32.lib
Dave McPherson (davemm) 11-March-98
Modified 6-30-12 for use with MFC, Dan Bloomquist
RunProcess(...)
Creates a process running in its own thread. The process
is expected to use STDOUT to notify the condition of the process.
This call will return after starting the process with
the handle of the process. All you should need to do is
check for NULL, this means the process failed to start.
There will be no input to the process, it is expected
to work on its own after starting. A worker thread will
gather the STDOUT a line at a time and send it back to
the window specified.
TODO: The comments below reflect sending data to the
process input pipe. Here we are only interested in the
output of the process.
--*/
#pragma comment(lib, "User32.lib")
void DisplayError(TCHAR *pszAPI);
void ReadAndHandleOutput(HANDLE hPipeRead);
void PrepAndLaunchRedirectedChild(HANDLE hChildStdOut,
HANDLE hChildStdIn,
HANDLE hChildStdErr,
LPCTSTR psPathFile,
LPCTSTR psCommandLine );
DWORD WINAPI GetAndSendInputThread( LPVOID lpvThreadParam );
HANDLE hChildProcess = NULL;
HANDLE hStdIn = NULL; // Handle to parents std input.
BOOL bRunThread = TRUE;
HWND hPostMessage= NULL;
HANDLE hOutputRead= NULL;
HANDLE hInputRead= NULL;
HANDLE hInputWrite= NULL;
WORD idGlbPost;
WORD idGlbEnd;
HANDLE hGlobalThread;
HRESULT RunProcess( HWND hWnd //Window to 'SendMessage' to
,WORD idPost //ID for message with the data pointer in wparam
,WORD idEnd //ID for message notifying the process has ended
,LPCTSTR psFileExe //Path.File of process to run
,LPCTSTR psCmdLine
)
{
hPostMessage= hWnd;
HANDLE hOutputReadTmp;
HANDLE hOutputWrite;
HANDLE hInputWriteTmp;
HANDLE hErrorWrite;
DWORD ThreadId;
SECURITY_ATTRIBUTES sa;
idGlbPost= idPost;
idGlbEnd= idEnd;
// Set up the security attributes struct.
sa.nLength= sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
// Create the child output pipe.
if (!CreatePipe(&hOutputReadTmp,&hOutputWrite,&sa,0))
DisplayError(_T("CreatePipe"));
// Create a duplicate of the output write handle for the std error
// write handle. This is necessary in case the child application
// closes one of its std output handles.
if (!DuplicateHandle(GetCurrentProcess(),hOutputWrite,
GetCurrentProcess(),&hErrorWrite,0,
TRUE,DUPLICATE_SAME_ACCESS))
DisplayError(_T("DuplicateHandle"));
// Create the child input pipe.
if (!CreatePipe(&hInputRead,&hInputWriteTmp,&sa,0))
DisplayError(_T("CreatePipe"));
// Create new output read handle and the input write handles. Set
// the Properties to FALSE. Otherwise, the child inherits the
// properties and, as a result, non-closeable handles to the pipes
// are created.
if (!DuplicateHandle(GetCurrentProcess(),hOutputReadTmp,
GetCurrentProcess(),
&hOutputRead, // Address of new handle.
0,FALSE, // Make it uninheritable.
DUPLICATE_SAME_ACCESS))
DisplayError(_T("DupliateHandle"));
if (!DuplicateHandle(GetCurrentProcess(),hInputWriteTmp,
GetCurrentProcess(),
&hInputWrite, // Address of new handle.
0,FALSE, // Make it uninheritable.
DUPLICATE_SAME_ACCESS))
DisplayError(_T("DupliateHandle"));
// Close inheritable copies of the handles you do not want to be
// inherited.
if (!CloseHandle(hOutputReadTmp)) DisplayError(_T("CloseHandle hOutputReadTmp"));
if (!CloseHandle(hInputWriteTmp)) DisplayError(_T("CloseHandle hInputWriteTmp"));
// Get std input handle so you can close it and force the ReadFile to
// fail when you want the input thread to exit.
if ( (hStdIn = GetStdHandle(STD_INPUT_HANDLE)) ==
INVALID_HANDLE_VALUE )
DisplayError(_T("GetStdHandle"));
PrepAndLaunchRedirectedChild( hOutputWrite, hInputRead, hErrorWrite, psFileExe, psCmdLine );
// Close pipe handles (do not continue to modify the parent).
// You need to make sure that no handles to the write end of the
// output pipe are maintained in this process or else the pipe will
// not close when the child process exits and the ReadFile will hang.
if (!CloseHandle(hOutputWrite)) DisplayError(_T("CloseHandle hOutputWrite"));
if (!CloseHandle(hInputRead )) DisplayError(_T("CloseHandle hInputRead"));
if (!CloseHandle(hErrorWrite)) DisplayError(_T("CloseHandle hErrorWrite"));
// Launch the thread that gets the input and sends it to the child.
hGlobalThread= CreateThread( NULL, 0, GetAndSendInputThread, (LPVOID)hOutputRead, 0, &ThreadId );
if (hGlobalThread == NULL)
return -1;
return 0;
}
///////////////////////////////////////////////////////////////////////
// PrepAndLaunchRedirectedChild
// Sets up STARTUPINFO structure, and launches redirected child.
///////////////////////////////////////////////////////////////////////
void PrepAndLaunchRedirectedChild(HANDLE hChildStdOut,
HANDLE hChildStdIn,
HANDLE hChildStdErr,
LPCTSTR psPathFile,
LPCTSTR psCommandLine )
{
//static int test= 0;
//ASSERT( ! test++ );
PROCESS_INFORMATION pi;
STARTUPINFO si;
// Set up the start up info struct.
ZeroMemory(&si,sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
si.dwFlags = STARTF_USESTDHANDLES;
si.hStdOutput = hChildStdOut;
si.hStdInput = hChildStdIn;
si.hStdError = hChildStdErr;
// Use this if you want to hide the child:
// si.wShowWindow = SW_HIDE;
// Note that dwFlags must include STARTF_USESHOWWINDOW if you want to
// use the wShowWindow flags.
// Launch the process that you want to redirect (in this case,
// Child.exe). Make sure Child.exe is in the same directory as
// redirect.c launch redirect from a command line to prevent location
// confusion.
BOOL bSuccess = FALSE;
bSuccess = CreateProcess(
psPathFile, // app console
const_cast< LPTSTR >( psCommandLine ), //command line
NULL, // process security attributes
NULL, // primary thread security attributes
TRUE, // handles are inherited
CREATE_NO_WINDOW, // creation flags
NULL, // use parent's environment
NULL, // use parent's current directory
&si, // STARTUPINFO pointer
&pi // receives PROCESS_INFORMATION
);
// If an error occurs, exit the application.
if ( ! bSuccess )
{
DWORD err= GetLastError( );
DisplayError( TEXT( "CreateProcess" ) );
}
//if (!CreateProcess(NULL,psTestFile,NULL,NULL,TRUE,
// CREATE_NEW_CONSOLE,NULL,NULL,&si,&pi))
// DisplayError(_T("CreateProcess");
// Set global child process handle to cause threads to exit.
hChildProcess= pi.hProcess;
// Close any unnecessary handles.
if( ! CloseHandle( pi.hThread ) )
DisplayError( _T("CloseHandle pi.hThread") );
}
///////////////////////////////////////////////////////////////////////
// ReadAndHandleOutput
// Monitors handle for input. Exits when child exits or pipe breaks.
///////////////////////////////////////////////////////////////////////
//#include <boost/iostreams/device/file_descriptor.hpp>
//#include <boost/iostreams/stream.hpp>
void ReadAndHandleOutput( HANDLE hPipeRead )
{
ASSERT( false );
int file_descriptor= _open_osfhandle( (intptr_t)hPipeRead, 0 );
FILE* file= _fdopen( file_descriptor, "r" );
std::ifstream stream( file );
std::string line;
//loop until stream empty
for( ; std::getline( stream, line ); )
{
SendMessage( hPostMessage, idGlbPost, (LPARAM)line.c_str( ), 0 );
TRACE( "line: %s\n", line.c_str( ) );
}
//should be so
ASSERT( GetLastError( ) == ERROR_BROKEN_PIPE );
if (!CloseHandle(hStdIn)) DisplayError(_T("CloseHandle hStdIn"));
if (!CloseHandle(hOutputRead)) DisplayError(_T("CloseHandle hOutputRead"));
if (!CloseHandle(hInputWrite)) DisplayError(_T("CloseHandle hInputWrite"));
}
///////////////////////////////////////////////////////////////////////
// GetAndSendInputThread
// Thread procedure that monitors the console for input and sends input
// to the child process through the input pipe.
// This thread ends when the child application exits.
///////////////////////////////////////////////////////////////////////
DWORD WINAPI GetAndSendInputThread(LPVOID lpvThreadParam)
{
HANDLE hPipeRead= (HANDLE)lpvThreadParam;
int file_descriptor= _open_osfhandle( (intptr_t)hPipeRead, 0 );
FILE* file= _fdopen( file_descriptor, "r" );
std::ifstream stream( file );
std::string line;
//loop until stream empty
for( ; std::getline( stream, line ); )
{
SendMessage( hPostMessage, idGlbPost, (LPARAM)line.c_str( ), 0 );
TRACE( "line: %s\n", line.c_str( ) );
}
//should be so
return 1;
ASSERT( GetLastError( ) == ERROR_BROKEN_PIPE );
//if (!CloseHandle(hStdIn)) DisplayError(_T("CloseHandle"));
if (!CloseHandle(hOutputRead)) DisplayError(_T("CloseHandle hOutputRead"));
if (!CloseHandle(hInputWrite)) DisplayError(_T("CloseHandle hInputWrite"));
SendMessage( hPostMessage, idGlbEnd, 0, 0 );
return 1;
}
///////////////////////////////////////////////////////////////////////
// DisplayError
// Displays the error number and corresponding message.
///////////////////////////////////////////////////////////////////////
void DisplayError(TCHAR *pszAPI)
{
TRACE( "DisplayError: %s\n", pszAPI );
return;
// return;
LPVOID lpvMessageBuffer;
TCHAR szPrintBuffer[CONPIPE_BUF_SIZE];
DWORD nCharsWritten;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
NULL, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpvMessageBuffer, 0, NULL);
StringCbPrintf(szPrintBuffer, CONPIPE_BUF_SIZE,
_T("ERROR: API = %s.\n error code = %d.\n message = %s.\n"),
pszAPI, GetLastError(), (TCHAR *)lpvMessageBuffer);
WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE),szPrintBuffer,
lstrlen(szPrintBuffer),&nCharsWritten,NULL);
LocalFree(lpvMessageBuffer);
//ExitProcess(GetLastError());
}
Now, in your dialog or whatever declaration, add the member:
RunPipeConsoleProcess pipes;
Then when you are ready, do the likes of:
pipes.SetMessageIDs( ID_CONSOLE_OUTPUT_WIN, ID_CONSOLE_OUTPUT_DONE );
pipes.SetExecutable( "netstat" );
pipes.SetArguments( "-ano );
if( ! pipes.StartThread( *this ) )
{
cEditStat.SetSel( -1, -1 );
cEditStat.ReplaceSel( _T("Failed to start JPEG Resize/Move Process\r\n") );
return;
}
The thread running the process will send messages with the IDs:
ID_CONSOLE_OUTPUT_WIN and ID_CONSOLE_OUTPUT_DONE
So add to your message map:
ON_MESSAGE( ID_CONSOLE_OUTPUT_WIN, OnPostConsoleWnd )
ON_MESSAGE( ID_CONSOLE_OUTPUT_DONE, OnPostConsoleWndDone )
OnPostConsoleWnd will get the output from the process in wparam.

WINAPI VirtualQueryEx - invalid handle

I am trying to read some pages of memory of a 32 bit process using VirtualQueryEx using Visual Studio 2012.
However when I run the program I get VirtualQueryEx Error 6: Invalid Handle. However there is no error with the handle itself [hProcess] and I am passing in the appropriate parameters. What could be it?
#include <windows.h>
#include <tlhelp32.h>
#include <tchar.h>
#include <stdio.h>
// Forward declarations:
BOOL GetProcessList( );
BOOL ListProcessModules( DWORD dwPID );
BOOL ListProcessThreads( DWORD dwOwnerPID );
void printError( TCHAR* msg );
int main( void )
{
GetProcessList( );
system("pause");
return 0;
}
BOOL GetProcessList( )
{
HANDLE hProcessSnap;
HANDLE hProcess;
PROCESSENTRY32 pe32;
DWORD dwPriorityClass;
// Take a snapshot of all processes in the system.
hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
if( hProcessSnap == INVALID_HANDLE_VALUE )
{
printError( TEXT("CreateToolhelp32Snapshot (of processes)") );
return( FALSE );
}
// Set the size of the structure before using it.
pe32.dwSize = sizeof( PROCESSENTRY32 );
// Retrieve information about the first process,
// and exit if unsuccessful
if( !Process32First( hProcessSnap, &pe32 ) )
{
printError( TEXT("Process32First") ); // show cause of failure
CloseHandle( hProcessSnap ); // clean the snapshot object
return( FALSE );
}
// Now walk the snapshot of processes, and
// display information about each process in turn
do
{
//If the process name equals foo_process.exe
if (!_tcscmp(pe32.szExeFile, _T("foo_process.exe")))
{
hProcess = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, false, pe32.th32ProcessID );
if( hProcess == NULL )
printError( TEXT("OpenProcess") );
unsigned char *addr = NULL;
MEMORY_BASIC_INFORMATION meminfo;
if (VirtualQueryEx(hProcess, addr, &meminfo, sizeof(meminfo)) == 0){
printError( TEXT("VirtualQueryEx") );
//return FALSE;
}
}
} while( Process32Next( hProcessSnap, &pe32 ) );
CloseHandle( hProcessSnap );
return( TRUE );
}
void printError( TCHAR* msg )
{
...
}
EDIT: Handle has value:
EDIT 2: More Info:
Windows 7 64bit platform.
Visual Studio 2012 (32 bit debugger) ran
as Administrator
Process is *32 (32bit)
unsigned char *addr = NULL;
You're asking VirtualQueryEx to Query address 0 which is not valid, causing the failure.

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

Retrieve serial number from USB memory (Windows environment 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;
}