Related
I am trying to communicate via SPI in Linux user space using the spidev driver. Physically, this SPI interface is a 4 bus (SCLK, CS, MOSI, MISO).
For this purpose I have attached to my dts the relevant node in the corresponding chip select. Once Linux boots I have the device available.
Using c++ and according to the spi-test example I have treated it as a character device, so I open it, require a full duplex transfer and close it (with the relevant calls to open, ioctl/spi_ioc_transfer and close primitives). The set bus configuration is 8 bits per word, at a maximum frequency of 1.29 MHz and in mode 0 (in other words, CPHA=CPOL=0).
Then, using the oscilloscope I see how my request is present in the MOSI, but I don't see any type of response in the MISO. What am I missing?
In case it helps, I see that the clock signal drops the level immediately after sending the data through the MOSI, so it makes sense that I am not getting any data in the MISO.
In addition, I have checked that the maximum frequency as well as all settings have been set correctly. I also have a baremetal application using the bus correctly, so any HW failure is ruled out.
Spi.hpp
#pragma once
#include <string>
#include <sys/ioctl.h>
#include <cstring>
#include <fcntl.h>
#include <unistd.h>
#include <linux/spi/spidev.h>
#include <drivers/common/literals.hpp>
#include <drivers/common/Utils.hpp>
namespace interfaces
{
namespace spi
{
namespace lnx
{
enum class Mode
{
ZERO = SPI_MODE_0,
ONE = SPI_MODE_1,
TWO = SPI_MODE_2,
THREE = SPI_MODE_3
};
enum class Bpw
{
BITS_8 = 8,
BITS_16 = 16
};
enum class State
{
CLOSED,
OPEN
};
class Spi
{
public:
explicit Spi( const std::string& aDevice )
{
memset( &theFrame, 0, sizeof( struct spi_ioc_transfer ) );
theFileDescriptor = -1;
theState = State::CLOSED;
theFrame[0].delay_usecs = 0;
// Do keep CS activated
theFrame[0].cs_change = 0;
if( setDevice( aDevice ) != ErrorCode::OPERATION_SUCESS )
{
trace( DEBUG_GENERAL, "error setting device\r\n" );
}
if( setMode( Mode::ZERO ) != ErrorCode::OPERATION_SUCESS )
{
trace( DEBUG_GENERAL, "error setting mode\r\n" );
}
if( setBitsPerWord( Bpw::BITS_8 ) != ErrorCode::OPERATION_SUCESS )
{
trace( DEBUG_GENERAL, "error setting bpw\r\n" );
}
// Set the SPI device pre-scaler to divide by 128
// (SPI_CLK_FREQ_HZ = 166 MHz) to transfer below 2MHz clock rate.
if( setMaxSpeedHz( ( 166 / 128.0 ) * 1000000 ) != ErrorCode::OPERATION_SUCESS )
{
trace( DEBUG_GENERAL, "error setting maximum speed\r\n" );
}
}
virtual ~Spi( void )
{
if( theState != State::CLOSED && theFileDescriptor != -1 )
{
if( close() != ErrorCode::OPERATION_SUCESS )
{
trace(
DEBUG_GENERAL,
"error closing device %s\r\n",
theDevice.c_str() );
}
}
}
Spi( const Spi& ) = delete;
Spi& operator=( const Spi& ) = delete;
inline std::string getDevice( void )
{
return this->theDevice;
}
inline ErrorCode setDevice( const std::string& aDevice )
{
ErrorCode anErrorCode = ErrorCode::CANT_CONFIGURE_INTERFACE;
if( theState != State::CLOSED && theFileDescriptor != -1 )
{
if ( close() != ErrorCode::OPERATION_SUCESS )
{
goto exit;
}
}
this->theDevice = aDevice;
anErrorCode = open();
exit:
return std::move( anErrorCode );
}
inline ErrorCode setMode( const Mode& aMode )
{
ErrorCode anErrorCode = ErrorCode::CANT_CONFIGURE_INTERFACE;
if( theState != State::CLOSED && theFileDescriptor != -1 )
{
if( ::ioctl(
theFileDescriptor,
SPI_IOC_WR_MODE32,
&aMode ) != -1 )
{
auto aResult = getMode();
if( aResult.first == ErrorCode::OPERATION_SUCESS &&
aResult.second == aMode )
{
anErrorCode = ErrorCode::OPERATION_SUCESS;
trace(
DEBUG_INFO,
"mode set to %d\r\n",
aMode );
}
else
{
close();
trace(
DEBUG_GENERAL,
"mode incongruence\r\n" );
}
}
else
{
close();
trace(
DEBUG_GENERAL,
"failed setting mode\r\n" );
}
}
return std::move( anErrorCode );
}
inline std::pair<ErrorCode, Mode> getMode( void )
{
Mode aMode;
ErrorCode anErrorCode = ErrorCode::CANT_CONFIGURE_INTERFACE;
if( theState != State::CLOSED && theFileDescriptor != -1 )
{
if( ::ioctl(
theFileDescriptor,
SPI_IOC_RD_MODE32,
&aMode ) != -1 )
{
anErrorCode = ErrorCode::OPERATION_SUCESS;
}
else
{
trace(
DEBUG_GENERAL,
"failed reading mode\r\n" );
}
}
return std::make_pair( anErrorCode, aMode );
}
inline ErrorCode setBitsPerWord( const Bpw& aBitsPerWord )
{
ErrorCode anErrorCode = ErrorCode::CANT_CONFIGURE_INTERFACE;
if( theState != State::CLOSED && theFileDescriptor != -1 )
{
if( ::ioctl(
theFileDescriptor,
SPI_IOC_WR_BITS_PER_WORD,
&aBitsPerWord ) != -1 )
{
auto aResult = getBitsPerWord();
if( aResult.first == ErrorCode::OPERATION_SUCESS &&
aResult.second == aBitsPerWord )
{
anErrorCode = ErrorCode::OPERATION_SUCESS;
theFrame[0].bits_per_word =
static_cast<uint8_t>( aBitsPerWord );
trace(
DEBUG_INFO,
"bpw set to %d\r\n",
aBitsPerWord );
}
else
{
close();
trace(
DEBUG_GENERAL,
"bpw incongruence\r\n" );
}
}
else
{
close();
trace(
DEBUG_GENERAL,
"failed setting bpw\r\n" );
}
}
return std::move( anErrorCode );
}
inline std::pair<ErrorCode, Bpw> getBitsPerWord( void )
{
uint8_t aBitsPerWord;
ErrorCode anErrorCode = ErrorCode::CANT_CONFIGURE_INTERFACE;
if( theState != State::CLOSED && theFileDescriptor != -1 )
{
if( ::ioctl(
theFileDescriptor,
SPI_IOC_RD_BITS_PER_WORD,
&aBitsPerWord ) != -1 )
{
anErrorCode = ErrorCode::OPERATION_SUCESS;
}
else
{
trace(
DEBUG_GENERAL,
"failed reading bpw\r\n" );
}
}
return std::make_pair(
anErrorCode,
static_cast<Bpw>( aBitsPerWord ) );
}
inline ErrorCode setMaxSpeedHz( const uint32_t aSpeed )
{
ErrorCode anErrorCode = ErrorCode::CANT_CONFIGURE_INTERFACE;
if( theState != State::CLOSED && theFileDescriptor != -1 )
{
if( ::ioctl(
theFileDescriptor,
SPI_IOC_WR_MAX_SPEED_HZ,
&aSpeed ) != -1 )
{
auto aResult = getMaxSpeedHz();
if( aResult.first == ErrorCode::OPERATION_SUCESS &&
aResult.second == aSpeed )
{
anErrorCode = ErrorCode::OPERATION_SUCESS;
theFrame[0].speed_hz = aSpeed;
trace(
DEBUG_INFO,
"maximum speed set to %d Hz\r\n",
aSpeed );
}
else
{
close();
trace(
DEBUG_GENERAL,
"maximum speed incongruence\r\n" );
}
}
else
{
close();
trace(
DEBUG_GENERAL,
"failed setting maximum speed\r\n" );
}
}
return std::move( anErrorCode );
}
inline std::pair<ErrorCode, uint32_t> getMaxSpeedHz( void )
{
uint32_t aSpeed;
ErrorCode anErrorCode = ErrorCode::CANT_CONFIGURE_INTERFACE;
if( theState != State::CLOSED && theFileDescriptor != -1 )
{
if( ::ioctl(
theFileDescriptor,
SPI_IOC_RD_MAX_SPEED_HZ,
&aSpeed ) != -1 )
{
anErrorCode = ErrorCode::OPERATION_SUCESS;
}
else
{
trace(
DEBUG_GENERAL,
"failed setting maximum speed\r\n" );
}
}
return std::make_pair( anErrorCode, aSpeed );
}
std::pair<ErrorCode, std::vector<uint8_t>> transfer(
const std::vector<uint8_t>& aBuffer,
uint32_t aLenght );
std::pair<ErrorCode, std::vector<uint8_t>>
read( uint32_t aLenght );
ErrorCode write( const std::vector<uint8_t>& aBuffer );
private:
ErrorCode open( void );
ErrorCode close( void );
int32_t theFileDescriptor;
std::string theDevice;
struct spi_ioc_transfer theFrame[1];
State theState;
};
} // end namespace lnx
} // end namespace spi
} // end namespace interfaces
Spi.cpp
#include <interfaces/lnx/Spi.hpp>
namespace interfaces
{
namespace spi
{
namespace lnx
{
ErrorCode Spi::open( void )
{
ErrorCode anErrorCode = ErrorCode::CANT_OPEN_DEV;
if( !theDevice.empty() )
{
theFileDescriptor = ::open(
theDevice.c_str(), O_SYNC | O_RDWR );
if( theFileDescriptor != -1 )
{
anErrorCode = ErrorCode::OPERATION_SUCESS;
theState = State::OPEN;
trace(
DEBUG_INFO,
"device %s opened\r\n",
theDevice.c_str() );
}
else
{
trace(
DEBUG_GENERAL,
"device %s could not be opened\r\n",
theDevice.c_str() );
}
}
return std::move( anErrorCode );
}
ErrorCode Spi::close( void )
{
ErrorCode anErrorCode = ErrorCode::CANT_CLOSE_DEV;
if( theState != State::CLOSED && theFileDescriptor != -1 )
{
if( ::close( theFileDescriptor ) == 0 )
{
anErrorCode = ErrorCode::OPERATION_SUCESS;
theFileDescriptor = -1;
theState = State::CLOSED;
trace(
DEBUG_INFO,
"device %s closed\r\n",
theDevice.c_str() );
}
}
return std::move( anErrorCode );
}
std::pair<ErrorCode, std::vector<uint8_t>> Spi::transfer(
const std::vector<uint8_t>& aRequest, uint32_t aLenght )
{
std::vector<uint8_t> aBuffer( aLenght, 0xFF );
ErrorCode anErrorCode = ErrorCode::CANT_READ_FROM_INTERFACE;
if( aRequest.empty() || aLenght <= 0 )
{
trace(
DEBUG_GENERAL,
"provided arguments not complains the conditions\r\n" );
goto exit;
}
if( theState != State::CLOSED && theFileDescriptor != -1 )
{
theFrame[0].tx_buf = reinterpret_cast<uintptr_t>( aRequest.data() );
theFrame[0].rx_buf = reinterpret_cast<uintptr_t>( &aBuffer[0] );
// Length of the command to write/read
theFrame[0].len = aLenght;
if( ::ioctl(
theFileDescriptor,
SPI_IOC_MESSAGE( 1 ),
&theFrame ) < 1 )
{
trace(
DEBUG_GENERAL,
"failed doing full duplex transfer\r\n" );
}
else
{
anErrorCode = ErrorCode::OPERATION_SUCESS;
vprint( aBuffer.data(), aBuffer.size() );
}
}
exit:
return std::make_pair( anErrorCode, aBuffer );
}
std::pair<ErrorCode, std::vector<uint8_t>>
Spi::read( uint32_t aLenght )
{
std::vector<uint8_t> aBuffer( aLenght, 0xFF );
ErrorCode anErrorCode = ErrorCode::CANT_READ_FROM_INTERFACE;
if( aLenght <= 0 )
{
trace(
DEBUG_GENERAL,
"provided arguments not complains the conditions\r\n" );
goto exit;
}
if( theState != State::CLOSED && theFileDescriptor != -1 )
{
theFrame[0].tx_buf = static_cast<uintptr_t>( NULL );
theFrame[0].rx_buf = reinterpret_cast<uintptr_t>( &aBuffer[0] );
theFrame[0].len = aLenght;
if( ::ioctl(
theFileDescriptor,
SPI_IOC_MESSAGE( 1 ),
&theFrame ) < 1 )
{
trace(
DEBUG_GENERAL,
"failed receiving message\r\n" );
}
else
{
anErrorCode = ErrorCode::OPERATION_SUCESS;
vprint( aBuffer.data(), aBuffer.size() );
}
}
exit:
return std::make_pair( anErrorCode, aBuffer );
}
ErrorCode Spi::write( const std::vector<uint8_t>& aBuffer )
{
ErrorCode anErrorCode = ErrorCode::CANT_WRITE_TO_INTERFACE;
if( aBuffer.empty() )
{
trace(
DEBUG_GENERAL,
"provided arguments not complains the conditions\r\n" );
goto exit;
}
if( theState != State::CLOSED && theFileDescriptor != -1 )
{
theFrame[0].tx_buf = reinterpret_cast<uintptr_t>( aBuffer.data() );
theFrame[0].rx_buf = static_cast<uintptr_t>( NULL );
theFrame[0].len = aBuffer.size();
if( ::ioctl(
theFileDescriptor,
SPI_IOC_MESSAGE( 1 ),
&theFrame ) < 1 )
{
trace(
DEBUG_GENERAL,
"failed sending message\r\n" );
}
else
{
anErrorCode = ErrorCode::OPERATION_SUCESS;
vprint( aBuffer.data(), aBuffer.size() );
}
}
exit:
return std::move( anErrorCode );
}
} // end namespace lnx
} // end namespace spi
} // end namespace interfaces
myboard.dts
...
&spi0 {
num-cs = <2>;
spi-cpol = <0>;
spi-cpha = <0>;
status = "okay";
spidev#0 {
compatible = "xlnx,spidev";
reg = <0>;
spi-max-frequency = <1296875>;
};
};
...
I use the transfer function to achieve my purpose over lnx-xlnx 4.14
I have some C++ code that I need to use for serial communication between PC and Arduino. The file "Serial.cpp" is including a file called "stdafx.h" that doesn't exist in the project or anywhere on my computer, which obviously causes an error.
Other than that, I also get other errors, such as C2065 'CSerial': undeclared identifier.
Here are the three files that are in the project:
Serial.h
#ifndef __SERIAL_H__
#define __SERIAL_H__
#pragma once
#include <Windows.h>
#include <memory.h>
#define FC_DTRDSR 0x01
#define FC_RTSCTS 0x02
#define FC_XONXOFF 0x04
#define ASCII_BEL 0x07
#define ASCII_BS 0x08
#define ASCII_LF 0x0A
#define ASCII_CR 0x0D
#define ASCII_XON 0x11
#define ASCII_XOFF 0x13
class CSerial
{
public:
CSerial();
~CSerial();
BOOL Open( int nPort = 2, int nBaud = 9600 );
BOOL Close( void );
int ReadData( void *, int );
int SendData( const char *, int );
int ReadDataWaiting( void );
BOOL IsOpened( void ){ return( m_bOpened ); }
protected:
BOOL WriteCommByte( unsigned char );
HANDLE m_hIDComDev;
OVERLAPPED m_OverlappedRead, m_OverlappedWrite;
bool m_bOpened;
};
#endif
Serial.cpp
// Serial.cpp
#include "stdafx.h"
#include "Serial.h"
CSerial::CSerial()
{
memset( &m_OverlappedRead, 0, sizeof( OVERLAPPED ) );
memset( &m_OverlappedWrite, 0, sizeof( OVERLAPPED ) );
m_hIDComDev = NULL;
m_bOpened = false;
}
CSerial::~CSerial()
{
Close();
}
BOOL CSerial::Open( int nPort, int nBaud )
{
if( m_bOpened ) return( TRUE );
wchar_t szPort[15];
wchar_t szComParams[50];
DCB dcb;
wsprintf( szPort, L"COM%d", nPort );
m_hIDComDev = CreateFile( szPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL );
if( m_hIDComDev == NULL ) return( FALSE );
memset( &m_OverlappedRead, 0, sizeof( OVERLAPPED ) );
memset( &m_OverlappedWrite, 0, sizeof( OVERLAPPED ) );
COMMTIMEOUTS CommTimeOuts;
CommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF;
CommTimeOuts.ReadTotalTimeoutMultiplier = 0;
CommTimeOuts.ReadTotalTimeoutConstant = 0;
CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
CommTimeOuts.WriteTotalTimeoutConstant = 5000;
SetCommTimeouts( m_hIDComDev, &CommTimeOuts );
wsprintf( szComParams, L"COM%d:%d,n,8,1", nPort, nBaud );
m_OverlappedRead.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
m_OverlappedWrite.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
dcb.DCBlength = sizeof( DCB );
GetCommState( m_hIDComDev, &dcb );
dcb.BaudRate = nBaud;
dcb.ByteSize = 8;
unsigned char ucSet;
ucSet = (unsigned char) ( ( FC_RTSCTS & FC_DTRDSR ) != 0 );
ucSet = (unsigned char) ( ( FC_RTSCTS & FC_RTSCTS ) != 0 );
ucSet = (unsigned char) ( ( FC_RTSCTS & FC_XONXOFF ) != 0 );
if( !SetCommState( m_hIDComDev, &dcb ) ||
!SetupComm( m_hIDComDev, 10000, 10000 ) ||
m_OverlappedRead.hEvent == NULL ||
m_OverlappedWrite.hEvent == NULL ){
DWORD dwError = GetLastError();
if( m_OverlappedRead.hEvent != NULL ) CloseHandle( m_OverlappedRead.hEvent );
if( m_OverlappedWrite.hEvent != NULL ) CloseHandle( m_OverlappedWrite.hEvent );
CloseHandle( m_hIDComDev );
return( FALSE );
}
m_bOpened = TRUE;
return( m_bOpened );
}
BOOL CSerial::Close( void )
{
if( !m_bOpened || m_hIDComDev == NULL ) return( TRUE );
if( m_OverlappedRead.hEvent != NULL ) CloseHandle( m_OverlappedRead.hEvent );
if( m_OverlappedWrite.hEvent != NULL ) CloseHandle( m_OverlappedWrite.hEvent );
CloseHandle( m_hIDComDev );
m_bOpened = FALSE;
m_hIDComDev = NULL;
return( TRUE );
}
BOOL CSerial::WriteCommByte( unsigned char ucByte )
{
BOOL bWriteStat;
DWORD dwBytesWritten;
bWriteStat = WriteFile( m_hIDComDev, (LPSTR) &ucByte, 1, &dwBytesWritten, &m_OverlappedWrite );
if( !bWriteStat && ( GetLastError() == ERROR_IO_PENDING ) ){
if( WaitForSingleObject( m_OverlappedWrite.hEvent, 1000 ) ) dwBytesWritten = 0;
else{
GetOverlappedResult( m_hIDComDev, &m_OverlappedWrite, &dwBytesWritten, FALSE );
m_OverlappedWrite.Offset += dwBytesWritten;
}
}
return( TRUE );
}
int CSerial::SendData( const char *buffer, int size )
{
if( !m_bOpened || m_hIDComDev == NULL ) return( 0 );
DWORD dwBytesWritten = 0;
int i;
for( i=0; i<size; i++ ){
WriteCommByte( buffer[i] );
dwBytesWritten++;
}
return( (int) dwBytesWritten );
}
int CSerial::ReadDataWaiting( void )
{
if( !m_bOpened || m_hIDComDev == NULL ) return( 0 );
DWORD dwErrorFlags;
COMSTAT ComStat;
ClearCommError( m_hIDComDev, &dwErrorFlags, &ComStat );
return( (int) ComStat.cbInQue );
}
int CSerial::ReadData( void *buffer, int limit )
{
if( !m_bOpened || m_hIDComDev == NULL ) return( 0 );
BOOL bReadStatus;
DWORD dwBytesRead, dwErrorFlags;
COMSTAT ComStat;
ClearCommError( m_hIDComDev, &dwErrorFlags, &ComStat );
if( !ComStat.cbInQue ) return( 0 );
dwBytesRead = (DWORD) ComStat.cbInQue;
if( limit < (int) dwBytesRead ) dwBytesRead = (DWORD) limit;
bReadStatus = ReadFile( m_hIDComDev, buffer, dwBytesRead, &dwBytesRead, &m_OverlappedRead );
if( !bReadStatus ){
if( GetLastError() == ERROR_IO_PENDING ){
WaitForSingleObject( m_OverlappedRead.hEvent, 2000 );
return( (int) dwBytesRead );
}
return( 0 );
}
return( (int) dwBytesRead );
}
SerialExample.cpp
bool sendExample(int port, int baudRate)
{
char data[4];
CSerial* s = new CSerial();
if(!s->Open(port, baudRate))
{
std_out << _T("Could not open COM") << port << endl;
return false;
}
// Sending a string of 4 characters
data[0] = 0x31;
data[1] = 0x32;
data[2] = 0x33;
data[3] = 0x0D; // ASCII CR
s->SendData(data, 4);
s->Close();
delete s;
}
Does anyone know what I have to do?
stdafx.h is a precompiled header for Visual studio. so if you are not working in visual studio, you can just remove it and it should work just fine.
In regard to the compiler not recognizing the CSerial class -
I don't see where you include "CSerial.h" in SerialExample.cpp (i.e: #include "CSerial.h"), but if you do, this may also be a symptom of CSerial.cpp not compiling (less likely though)...
Hope this helps,
Lior
ALL,
I'm getting the Commands were executed in an improper order. trying to execute following code:
std::wstring query6 = L"SELECT( IF( ( SELECT 1 FROM information_schema.statistics WHERE index_name=\'abcattbl_tnam_ownr\' AND table_name=\'abcattbl\' ) > 0, \"SELECT 0\", \"CREATE INDEX abcattbl_tnam_ownr ON abcattbl(abt_tnam ASC, abt_ownr ASC)\"));";
std::wstring query7 = L"SELECT( IF( ( SELECT 1 FROM information_schema.statistics WHERE index_name=\'abcatcol_tnam_ownr_cnam\' AND table_name=\'abcatcol\' ) > 0, \"SELECT 0\", \"CREATE INDEX abcatcol_tnam_ownr_cnam ON abcatcoll(abc_tnam ASC, abc_ownr ASC, abc_cnam ASC)\"));";
res_stmt = mysql_stmt_init( m_db );
if( !res_stmt )
{
std::wstring err = m_pimpl->m_myconv.from_bytes( mysql_stmt_error( res_stmt ) );
errorMsg.push_back( err );
}
else
{
if( mysql_stmt_prepare( res_stmt, m_pimpl->m_myconv.to_bytes( query.c_str() ).c_str(), query.length() ) )
{
std::wstring err = m_pimpl->m_myconv.from_bytes( mysql_stmt_error( res_stmt ) );
errorMsg.push_back( err );
}
else
{
bool index_exist = IsSystemIndexExists( res_stmt, L"abcattbl_tnam_ownr", L"abcattbl", errorMsg );
if( !index_exist )
{
res = mysql_query( m_db, m_pimpl->m_myconv.to_bytes( query6.c_str() ).c_str() );
}
}
bool index_exist = IsSystemIndexExists( res_stmt, L"abcatcol_tnam_ownr_cnam", L"abcatcol", errorMsg );
if( !index_exist )
{
res = mysql_query( m_db, m_pimpl->m_myconv.to_bytes( query7.c_str() ).c_str() );
if( mysql_stmt_close( res_stmt ) )
{
std::wstring err = m_pimpl->m_myconv.from_bytes( mysql_stmt_error( res_stmt ) );
errorMsg.push_back( err );
}
}
}
bool MySQLDatabase::IsSystemIndexExists(MYSQL_STMT *res, const std::wstring &indexName, const std::wstring &tableName, std::vector<std::wstring> &errorMsg)
{
bool exists = false;
char *str_data[2] = { NULL, NULL };
unsigned long *str_length[3];
MYSQL_BIND values[2];
memset( values, 0, sizeof( values ) );
str_data[0] = new char[tableName.length() + 1];
str_data[1] = new char[indexName.length() + 1];
memset( str_data[0], 0, tableName.length() + 1 );
memset( str_data[1], 0, indexName.length() + 1 );
str_length[0] = new unsigned long;
str_length[1] = new unsigned long;
values[0].buffer_type = MYSQL_TYPE_STRING;
values[1].buffer_type = MYSQL_TYPE_STRING;
values[0].buffer = str_data[0];
values[1].buffer = str_data[1];
values[0].buffer_length = tableName.length();
values[1].buffer_length = indexName.length();
values[0].is_null = 0;
values[1].is_null = 0;
values[0].length = str_length[0];
values[1].length = str_length[1];
strncpy( str_data[0], m_pimpl->m_myconv.to_bytes( tableName.c_str() ).c_str(), tableName.length() );
strncpy( str_data[1], m_pimpl->m_myconv.to_bytes( indexName.c_str() ).c_str(), indexName.length() );
*str_length[0] = tableName.length();
*str_length[1] = indexName.length();
if( mysql_stmt_bind_param( res, values ) )
{
std::wstring err = m_pimpl->m_myconv.from_bytes( mysql_stmt_error( res ) );
errorMsg.push_back( err );
}
else
{
if( mysql_stmt_execute( res ) )
{
std::wstring err = m_pimpl->m_myconv.from_bytes( mysql_stmt_error( res ) );
errorMsg.push_back( err );
}
else
{
if( mysql_stmt_fetch( res ) != MYSQL_NO_DATA )
exists = 1;
}
}
}
delete str_data[0];
str_data[0] = NULL;
delete str_data[1];
str_data[1] = NULL;
delete str_length[0];
str_length[0] = NULL;
delete str_length[1];
str_length[1] = NULL;
return exists;
}
The first time function is called everything is executed correctly. However the second time the call fails with the above mentioned error.
What am I missing? Is there maybe a parameters un-bind function that needs to be called?
I feel like I'm missing something really obvious.
TIA!
[EDIT]:
Calling mysql_stmt_reset()/mysql_stmt_free_result() after _fetch() doesn't change the result.
[/EDIT]
My goal is to get the full command line of a 64 bit process programmatically. I have understood and written this code where I do a process walk of all the currently running processes and get each of their details. But the issue is that this code fails to do the same for a 64 bit process (one that is not running under WOW64).
#include <windows.h>
#include <tlhelp32.h>
#include <tchar.h>
#include <iostream>
#include <cstdio>
#include <fstream>
using namespace std;
BOOL GetProcessList( FILE *f);
BOOL ListProcessModules( DWORD dwPID, FILE *f);
BOOL ListProcessThreads( DWORD dwOwnerPID, FILE *f );
void printError( TCHAR* msg, FILE *f );
typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
LPFN_ISWOW64PROCESS fnIsWow64Process;
BOOL IsWow64(HANDLE processHandle)
{
BOOL bIsWow64 = FALSE;
//IsWow64Process is not available on all supported versions of Windows.
//Use GetModuleHandle to get a handle to the DLL that contains the function
//and GetProcAddress to get a pointer to the function if available.
fnIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress(
GetModuleHandle(TEXT("kernel32")),"IsWow64Process");
if(fnIsWow64Process != NULL)
{
if (!fnIsWow64Process(processHandle, &bIsWow64))
{
//handle error
}
}
return bIsWow64;
}
int main( void )
{
FILE *f = fopen("file_.txt", "w");
if (f == NULL)
{
printf("Error opening file!\n");
exit(1);
}
GetProcessList(f);
return 0;
}
BOOL GetProcessList( FILE *f)
{
HANDLE hProcessSnap;
HANDLE hProcess;
PROCESSENTRY32 pe32;
DWORD dwPriorityClass;
fprintf(f, "start writing:\n");
/*
myfile.open ("example.txt");
myfile << "writing starts here..." << endl;
*/
// Take a snapshot of all processes in the system.
hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
if( hProcessSnap == INVALID_HANDLE_VALUE )
{
printError( TEXT("CreateToolhelp32Snapshot (of processes)"), f);
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"), f ); // 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
{
_tprintf( TEXT("\n\n=====================================================" ));
_tprintf( TEXT("\nPROCESS NAME: %s"), pe32.szExeFile );
_tprintf( TEXT("\n-------------------------------------------------------" ));
fprintf(f, "\n\n=====================================================");
fprintf(f, "\nPROCESS NAME: %s", pe32.szExeFile );
fprintf(f, "\n------------------------------------------------------------");
/*
myfile << "\n\n=====================================================";
myfile << "\nPROCESS NAME " << pe32.szExeFile;
myfile << "\n-----------------------------------------------------------";
*/
// Retrieve the priority class.
dwPriorityClass = 0;
hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID );
//is hProcess the handle to the process?
if( hProcess == NULL )
printError( TEXT("OpenProcess"), f );
else
{
if(IsWow64(hProcess)){
_tprintf(TEXT("\nThe process is running under WOW64.\n"));
fprintf(f, "\nThe process is running under WOW64.\n");
//myfile << "\nThe process is running under WOW64.\n";
}
else{
_tprintf(TEXT("\nThe process is not running under WOW64.\n"));
fprintf(f, "\nThe process is not running under WOW64.\n");
//myfile << "\nThe process is not running under WOW64.\n";
}
dwPriorityClass = GetPriorityClass( hProcess );
if( !dwPriorityClass )
printError( TEXT("GetPriorityClass"), f );
CloseHandle( hProcess );
}
_tprintf( TEXT("\n Process ID = 0x%08X"), pe32.th32ProcessID );
_tprintf( TEXT("\n Thread count = %d"), pe32.cntThreads );
_tprintf( TEXT("\n Parent process ID = 0x%08X"), pe32.th32ParentProcessID );
_tprintf( TEXT("\n Priority base = %d"), pe32.pcPriClassBase );
fprintf(f, "\n Process ID = 0x%08X", pe32.th32ProcessID);
fprintf(f, "\n Thread count = %d", pe32.cntThreads );
fprintf(f, "\n Parent process ID = 0x%08X", pe32.th32ParentProcessID );
fprintf(f, "\n Priority base = %d", pe32.pcPriClassBase );
if( dwPriorityClass )
_tprintf( TEXT("\n Priority class = %d"), dwPriorityClass );
// List the modules and threads associated with this process
ListProcessModules( pe32.th32ProcessID,f );
ListProcessThreads( pe32.th32ProcessID,f );
char *cmd_line = NULL;
//get_cmdline_from_pid(pe32.th32ProcessID, cmd_line);
} while( Process32Next( hProcessSnap, &pe32 ) );
CloseHandle( hProcessSnap );
return( TRUE );
}
BOOL ListProcessModules( DWORD dwPID,FILE *f )
{
HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
MODULEENTRY32 me32;
// Take a snapshot of all modules in the specified process.
hModuleSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, dwPID );
if( hModuleSnap == INVALID_HANDLE_VALUE )
{
printError( TEXT("CreateToolhelp32Snapshot (of modules)"), f );
return( FALSE );
}
// Set the size of the structure before using it.
me32.dwSize = sizeof( MODULEENTRY32 );
// Retrieve information about the first module,
// and exit if unsuccessful
if( !Module32First( hModuleSnap, &me32 ) )
{
printError( TEXT("Module32First"), f ); // show cause of failure
CloseHandle( hModuleSnap ); // clean the snapshot object
return( FALSE );
}
// Now walk the module list of the process,
// and display information about each module
do
{
_tprintf( TEXT("\n\n MODULE NAME: %s"), me32.szModule );
_tprintf( TEXT("\n Executable = %s"), me32.szExePath );
_tprintf( TEXT("\n Process ID = 0x%08X"), me32.th32ProcessID );
_tprintf( TEXT("\n Ref count (g) = 0x%04X"), me32.GlblcntUsage );
_tprintf( TEXT("\n Ref count (p) = 0x%04X"), me32.ProccntUsage );
_tprintf( TEXT("\n Base address = 0x%08X"), (DWORD) me32.modBaseAddr );
_tprintf( TEXT("\n Base size = %d"), me32.modBaseSize );
fprintf(f, "\n\n MODULE NAME: %s", me32.szModule );
fprintf(f, "\n Executable = %s", me32.szExePath );
fprintf(f, "\n Process ID = 0x%08X", me32.th32ProcessID );
fprintf(f, "\n Ref count (g) = 0x%04X", me32.GlblcntUsage );
fprintf(f, "\n Ref count (p) = 0x%04X", me32.ProccntUsage );
fprintf(f, "\n Base address = 0x%08X", (DWORD) me32.modBaseAddr );
fprintf(f, "\n Base size = %d", me32.modBaseSize );
} while( Module32Next( hModuleSnap, &me32 ) );
CloseHandle( hModuleSnap );
return( TRUE );
}
BOOL ListProcessThreads( DWORD dwOwnerPID,FILE *f )
{
HANDLE hThreadSnap = INVALID_HANDLE_VALUE;
THREADENTRY32 te32;
// Take a snapshot of all running threads
hThreadSnap = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 );
if( hThreadSnap == INVALID_HANDLE_VALUE )
return( FALSE );
// Fill in the size of the structure before using it.
te32.dwSize = sizeof(THREADENTRY32);
// Retrieve information about the first thread,
// and exit if unsuccessful
if( !Thread32First( hThreadSnap, &te32 ) )
{
printError( TEXT("Thread32First"), f ); // show cause of failure
CloseHandle( hThreadSnap ); // clean the snapshot object
return( FALSE );
}
// Now walk the thread list of the system,
// and display information about each thread
// associated with the specified process
do
{
if( te32.th32OwnerProcessID == dwOwnerPID )
{
_tprintf( TEXT("\n\n THREAD ID = 0x%08X"), te32.th32ThreadID );
_tprintf( TEXT("\n Base priority = %d"), te32.tpBasePri );
_tprintf( TEXT("\n Delta priority = %d"), te32.tpDeltaPri );
_tprintf( TEXT("\n"));
fprintf(f, "\n\n THREAD ID = 0x%08X", te32.th32ThreadID);
fprintf(f, "\n Base priority = %d", te32.tpBasePri );
fprintf(f, "\n Delta priority = %d", te32.tpDeltaPri );
fprintf(f, "\n");
}
} while( Thread32Next(hThreadSnap, &te32 ) );
CloseHandle( hThreadSnap );
return( TRUE );
}
void printError( TCHAR* msg, FILE *f )
{
DWORD eNum;
TCHAR sysMsg[256];
TCHAR* p;
eNum = GetLastError( );
FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, eNum,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
sysMsg, 256, NULL );
// Trim the end of the line and terminate it with a null
p = sysMsg;
while( ( *p > 31 ) || ( *p == 9 ) )
++p;
do { *p-- = 0; } while( ( p >= sysMsg ) &&
( ( *p == '.' ) || ( *p < 33 ) ) );
// Display the message
_tprintf( TEXT("\n WARNING: %s failed with error %d (%s)"), msg, eNum, sysMsg );
fprintf(f, "\n WARNING: %s failed with error %d (%s)", msg, eNum, sysMsg);
}
It gives me the ERROR CODE 299, which indicates that it could not read or write memory from the process, and thus does not provide me the executable command for any 64 bit process.
=====================================================
PROCESS NAME: taskhostex.exe
------------------------------------------------------------
The process is not running under WOW64.
Process ID = 0x00001954
Thread count = 10
Parent process ID = 0x000003BC
Priority base = 8
WARNING: CreateToolhelp32Snapshot (of modules) failed with error 299 (Only part of a ReadProcessMemory or WriteProcessMemory request was completed)
Could anyone please help me out with getting around this issue?
Thanks.
This is not possible. From the documentation:
If the specified process is a 64-bit process and the caller is a
32-bit process, this function fails and the last error code is
ERROR_PARTIAL_COPY (299).
You need to compile your code as 64-bit.
Here more about this issue: How to enum modules in a 64bit process from a 32bit WOW process.
What's wrong? Why do i get 0x0000etc on output?
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
if( !hSnapshot )
return -1;
PROCESSENTRY32W pe32w;
memset( &pe32w, 0, sizeof( pe32w ) );
pe32w.dwSize = sizeof( PROCESSENTRY32W );
Process32First( hSnapshot, &pe32w );
do
{
std::cout << pe32w.szExeFile << std::endl;
} while( Process32Next( hSnapshot, &pe32w ) );
CloseHandle( hSnapshot );
return 0;
}
This is likely because your PROCESSENTRY32W structure is using wchar_t types for szExeFile, and std::cout does not understand how to handle wide characters. In this case it simply prints the pointer value instead.
You may be able to use std::wcout to print wide character values.