Loop streaming .ogg audio - OpenAL - c++

I have problem looping a streamed ogg vorbis file.
This is the code :
fslStream_OGG::fslStream_OGG()
{
className = "fslSound";
iMemSize = 0;
iLength = 0;
bSourceRelative = false;
bIsLooping = false;
bForceStop = false;
bActive = false;
source = buffer = 0;
current_gain = 1.0f;
outer_gain = 0;
snd_info.uiChannels = snd_info.uiFrequency = snd_info.uiSampling = 0;
}
fslStream_OGG::~fslStream_OGG()
{
if (bStreamCreated)
{
alSourceStop(source);
Empty();
alDeleteSources(1,&source);
alDeleteBuffers(2,buffers);
ov_clear(&oggStream);
}
}
bool fslStream_OGG::Update()
{
ALenum state;
alGetSourcei(source,AL_SOURCE_STATE,&state);
if (state == AL_PAUSED || !bActive) return false;
int processed;
alGetSourcei(source,AL_BUFFERS_PROCESSED,&processed);
while (processed--)
{
ALuint bufferI;
alSourceUnqueueBuffers(source,1,&bufferI);
Stream(bufferI);
if (bActive) alSourceQueueBuffers(source,1,&bufferI);
}
if (state == AL_STOPPED || !bActive)
{
bActive = false;
StreamSetPos(0.0f);
if (bForceStop) return false;
if (bIsLooping)
{
alSourceStop(source); // <- *** note these ***
Empty(); // <- *** 2 lines of code ***
StreamPlay();
alSourcePlay(source);
}
else
{
return true;
}
}
return false;
}
void fslStream_OGG::StreamPlay()
{
if (!bActive)
{
bActive = true;
bForceStop = false;
Stream(buffers[0]);
Stream(buffers[1]);
alSourceQueueBuffers(source,2,buffers);
}
}
bool fslStream_OGG::Open(const char* strFile)
{
bStreamCreated = false;
vorbis_info* vorbisInfo;
oggFile = fopen(strFile,"rb");
if (!oggFile) return false;
if (ov_open_callbacks(oggFile,&oggStream,NULL,0,OV_CALLBACKS_DEFAULT) != 0)
{
fclose(oggFile);
return false;
}
vorbisInfo = ov_info(&oggStream,-1);
if (vorbisInfo->channels == 1)
format = AL_FORMAT_MONO16;
else format = AL_FORMAT_STEREO16;
alGenBuffers(2,buffers);
alGenSources(1,&source);
iLength = (long)(ov_time_total(&oggStream,-1) * 1000.0);
snd_info.uiChannels = (format == AL_FORMAT_MONO8 || format == AL_FORMAT_MONO16)? 1:2;
snd_info.uiSampling = (format == AL_FORMAT_MONO8 || format == AL_FORMAT_STEREO8)? 8:16;
snd_info.uiFrequency = vorbisInfo->rate;
bStreamCreated = true;
bIsStream = true;
return true;
}
void fslStream_OGG::Stream(ALuint bufferI)
{
int size = 0;
int section;
int result;
bActive = true;
while (size < OGG_STREAM_BUFFER_SIZE)
{
result = ov_read(&oggStream,data + size,OGG_STREAM_BUFFER_SIZE - size,0,2,1,&section);
if (result > 0)
{
size += result;
}
else
{
if (result < 0) return; else break;
}
}
if (size == 0) { bActive = false; return; }
alBufferData(bufferI,format,data,size,snd_info.uiFrequency);
}
void fslStream_OGG::Empty()
{
int queued;
alGetSourcei(source,AL_BUFFERS_QUEUED,&queued);
while (queued--)
{
ALuint bufferI;
alSourceUnqueueBuffers(source,1,&bufferI);
}
}
void fslStream_OGG::StreamSetPos(float p)
{
ov_time_seek(&oggStream,p);
}
float fslStream_OGG::StreamGetPos()
{
return (float)ov_time_tell(&oggStream);
}
Note the 2 lines of code I have marked with ***.
In all cases, the file starts playing fine and rewinds when it ends. However :
Without those 2 lines of code, when repeated the file sounds "corrupted". If let to repeat again, it sounds even more "corrupted". I believe this is because OpenAl and the Vorbis decoder get "unsynchronized" writing/reading the buffer when the stream is repeated.
If I add those 2 lines of code, the file repeats without sounding corrupted. However, the file isn't repeated seamlessly; it rewinds a few centiseconds before it ends. I suspect this is because the buffers are not played to the end before rewinding to start.
I would be obliged if anyone could lend a helping hand.
Many thanks in advance,
Bill

It seems that I have fixed the problem (I won't be sure without extensive testing).
I have fixed the Update method as follows :
bool fslStream_OGG::Update()
{
ALenum state;
alGetSourcei(source,AL_SOURCE_STATE,&state);
//if (state == AL_PAUSED || !bActive) return false; // <- WRONG
if (state == AL_PAUSED) return false;
int processed;
alGetSourcei(source,AL_BUFFERS_PROCESSED,&processed);
while (processed--)
{
ALuint bufferI;
alSourceUnqueueBuffers(source,1,&bufferI);
Stream(bufferI);
if (bActive) alSourceQueueBuffers(source,1,&bufferI);
}
//if (state == AL_STOPPED || !bActive) /// <- WRONG
if (state == AL_STOPPED)
{
bActive = false;
StreamSetPos(0.0f);
if (bForceStop) return false;
if (bIsLooping)
{
//alSourceStop(source); // <- I have added these
//Empty(); // <- 2 lines of code
StreamPlay();
alSourcePlay(source);
}
else
{
return true;
}
}
return false;
}
Those 2 lines of code seem not to be necessary now. Will have to test it with different OSes, hardware etc...

Related

Memory change detection function in C++ isn't detecting properly some malwares

I'm having an anti cheat system for my private online game platformed for Windows.
One of the most popular functions I have is memory change detection.
Source code for memory change detections:
bool MEMORY_PROTECTION_INIT() // OK
{
bool ClearFileMapping = 0;
if((FileMappingHandle=CreateFileMapping(INVALID_HANDLE_VALUE,0,PAGE_READWRITE,0,sizeof(HACK_VERIFY_FILE_MAPPING),"Local\\HACK_VERIFY_FILE_MAPPING")) == 0)
{
return 0;
}
if(GetLastError() == ERROR_ALREADY_EXISTS)
{
ClearFileMapping = 0;
}
else
{
ClearFileMapping = 1;
}
if((lpHackVerifyFileMapping=(HACK_VERIFY_FILE_MAPPING*)MapViewOfFile(FileMappingHandle,FILE_MAP_ALL_ACCESS,0,0,sizeof(HACK_VERIFY_FILE_MAPPING))) == 0)
{
return 0;
}
if(ClearFileMapping != 0)
{
lpHackVerifyFileMapping->Clear();
}
MemoryProtectionTime = GetTickCount();
return 1;
}
bool MEMORY_PROTECTION_SCAN() // OK
{
if(gMemoryGuardSwitch == 0 || (gMemoryGuardNumber & MEMORY_GUARD_NUMBER_INJECT) == 0)
{
return 1;
}
for(DWORD n=0;n < lpHackVerifyFileMapping->WriteVirtualMemoryCount;n++)
{
HACK_VERIFY_FILE* lpHackVerifyFile = &lpHackVerifyFileMapping->WriteVirtualMemoryTable[n];
if(lpHackVerifyFile->time >= MemoryProtectionTime)
{
if(lpHackVerifyFile->spid != GetCurrentProcessId())
{
if(lpHackVerifyFile->tpid == GetCurrentProcessId())
{
CHClientDisconnectSend(CLIENT_DISCONNECT_MEMORY_DETECTION,0,lpHackVerifyFile->spid);
return 1;
}
}
}
}
return 1;
}
bool HANDLE_PROTECTION_INIT() // OK
{
CProcessQuery ProcessQuery;
HANDLE HandleValue = OpenProcess(PROCESS_VM_READ,0,GetCurrentProcessId());
if(ProcessQuery.Fetch(SystemExtendedHandleInformation,sizeof(SYSTEM_HANDLE_INFO_EX)) != 0)
{
SYSTEM_HANDLE_INFO_EX* lpSystemHandleInfo = ProcessQuery.GetExtendedHandleInfo();
if(lpSystemHandleInfo != 0)
{
SYSTEM_HANDLE_ENTRY_INFO_EX* lpSystemHandleEntryInfo = lpSystemHandleInfo->Handles;
if(lpSystemHandleEntryInfo != 0)
{
for(DWORD n=0;n < lpSystemHandleInfo->NumberOfHandles;n++,lpSystemHandleEntryInfo++)
{
if(lpSystemHandleEntryInfo->UniqueProcessId == GetCurrentProcessId() && lpSystemHandleEntryInfo->HandleValue == ((DWORD)HandleValue))
{
HandleProtectionNumber = (DWORD)lpSystemHandleEntryInfo->ObjectTypeIndex;
HandleProtectionObject = (DWORD)lpSystemHandleEntryInfo->Object;
ProcessQuery.Close();
return 1;
}
}
}
}
}
ProcessQuery.Close();
return 0;
}
bool HANDLE_PROTECTION_SCAN() // OK
{
if(gMemoryGuardSwitch == 0 || (gMemoryGuardNumber & MEMORY_GUARD_NUMBER_HANDLE) == 0)
{
return 1;
}
static CProcessQuery ProcessQuery;
std::map<DWORD,std::vector<DWORD>> HandleProtectionTable;
if(ProcessQuery.Fetch(SystemExtendedHandleInformation,sizeof(SYSTEM_HANDLE_INFO_EX)) != 0)
{
SYSTEM_HANDLE_INFO_EX* lpSystemHandleInfo = ProcessQuery.GetExtendedHandleInfo();
if(lpSystemHandleInfo != 0)
{
SYSTEM_HANDLE_ENTRY_INFO_EX* lpSystemHandleEntryInfo = lpSystemHandleInfo->Handles;
if(lpSystemHandleEntryInfo != 0)
{
for(DWORD n=0;n < lpSystemHandleInfo->NumberOfHandles;n++,lpSystemHandleEntryInfo++)
{
if(lpSystemHandleEntryInfo->UniqueProcessId != GetCurrentProcessId() && lpSystemHandleEntryInfo->ObjectTypeIndex == HandleProtectionNumber && lpSystemHandleEntryInfo->Object == ((LPVOID)HandleProtectionObject) && (lpSystemHandleEntryInfo->GrantedAccess & PROCESS_VM_WRITE) != 0)
{
std::map<DWORD,std::vector<DWORD>>::iterator it = HandleProtectionTable.find(lpSystemHandleEntryInfo->UniqueProcessId);
if(it == HandleProtectionTable.end())
{
HandleProtectionTable.insert(std::pair<DWORD,std::vector<DWORD>>(lpSystemHandleEntryInfo->UniqueProcessId,std::vector<DWORD>(1,lpSystemHandleEntryInfo->HandleValue)));
continue;
}
else
{
if(it->second.size() >= 10)
{
CHClientDisconnectSend(CLIENT_DISCONNECT_MEMORY_DETECTION,0,lpSystemHandleEntryInfo->UniqueProcessId);
return 0;
}
else
{
it->second.push_back(lpSystemHandleEntryInfo->HandleValue);
continue;
}
}
}
}
}
}
}
return 1;
}
bool MEMORY_CHECK_ATTACH() // OK
{
CCRC32 CRC32;
MODULEINFO ModuleInfo;
memset(&ModuleInfo,0,sizeof(ModuleInfo));
if(GetModuleInformation(GetCurrentProcess(),GetModuleHandle(0),&ModuleInfo,sizeof(ModuleInfo)) == 0)
{
return 0;
}
IMAGE_NT_HEADERS32* lpNtHeader = (IMAGE_NT_HEADERS32*)((DWORD)ModuleInfo.lpBaseOfDll+((IMAGE_DOS_HEADER*)ModuleInfo.lpBaseOfDll)->e_lfanew);
IMAGE_SECTION_HEADER* lpSectionHeader = (IMAGE_SECTION_HEADER*)((DWORD)lpNtHeader+sizeof(IMAGE_NT_HEADERS32));
for(int n=0;n < lpNtHeader->FileHeader.NumberOfSections;n++)
{
MEMORY_CHECK_SOURCE data;
data.VirtualAddress = (DWORD)ModuleInfo.lpBaseOfDll+lpSectionHeader[n].VirtualAddress;
data.VirtualSize = lpSectionHeader[n].Misc.VirtualSize;
data.VirtualChecksum = CRC32.FullCRC((BYTE*)data.VirtualAddress,data.VirtualSize);
MemoryCheckSource.insert(std::pair<DWORD,MEMORY_CHECK_SOURCE>(data.VirtualAddress,data));
break;
}
return 1;
}
bool MEMORY_CHECK_DETACH() // OK
{
CCRC32 CRC32;
for(std::map<DWORD,MEMORY_CHECK_SOURCE>::iterator it=MemoryCheckSource.begin();it != MemoryCheckSource.end();it++)
{
if(it->second.VirtualChecksum != CRC32.FullCRC((BYTE*)it->second.VirtualAddress,it->second.VirtualSize))
{
return 0;
}
}
return 1;
}
For some reasons it works fine on some malwares, but some software (that are doing memory changes too) aren't detected by the function.
After few checks I realized that the difference between both types of cheats is the memory base address.
For those that are detected by the function- the base address that is calling to Heap(id2) is 0x30000. Although the software that aren't detected by the function- the base address that is calling to heap(id2) (- same use) is 0x10000 (the first one).
any ideas what changes should I make to make sure that these cheats are blocked?

Error in Xcode: Thread 1: EXC_BAD_ACCESS (code=1, address=0xe8)

This is supposed to be a c++ game which works by reading in files. How ever, I am not really sure what is the problem in the code below. When I enter the file name it gives me this error (code is below, problematic line is also shown). If you can't fix it can you at least tell me why this seems to work fine in another computer, but when I try to compile in Xcode it goes wrong?
#include "AdvRoom.h"
AdvRoom::AdvRoom()
{
}
bool AdvRoom::readRoom(ifstream &roomFile)
{
bool success = true;
char data[64];
int pointer;
while ((roomFile.get(data[0])) && data[0] == '\n') {}
roomFile.unget();
if (success && !roomFile.eof() && roomFile.good()) {
roomFile.get(data, 64);
this->number = atoi(data);
roomFile.get(data[0]);
}
else success = false;
if (success && !roomFile.eof() && roomFile.good()) {
roomFile.get(data, 64);
this->name = data;
roomFile.get(data[0]);
}
else success = false;
if (success && !roomFile.eof() && roomFile.good()) {
roomFile.get(data, 64);
while (data[0] != '-' && success) {
this->description.push_back(data);
if (success && !roomFile.eof() && roomFile.good()) {
roomFile.get(data[0]);
roomFile.get(data, 64);
}
else success = false;
}
roomFile.get(data[0]);
}
else success = false;
if (success && !roomFile.eof() && roomFile.good()) {
// Check for \n
string direction;
int destination = 0;
string key;
while (roomFile.peek() != '\n' && success) {
if (success && !roomFile.eof() && roomFile.good()) {
roomFile.get(data, 64, ' ');
direction = data;
while ((roomFile.get(data[0])) && data[0] == ' ') {}
roomFile.unget();
int i = 0;
while ((roomFile.get(data[i])) && data[i] != '\n' && data[i] != ' ') {
++i;
}
if (data[i] == ' ') {
data[i] = '\0';
destination = atoi(data);
roomFile.get(data, 64, '\n');
key = data;
roomFile.get(data[0]);
}
else if (data[i] == '\n') {
data[i] = '\0';
destination = atoi(data);
key = "";
//roomFile.get(data[0]);
}
AdvMotionTableEntry entry(direction, destination, key);
this->motionTable.push_back(entry);
}
else success = false;
}
}
else success = false;
return success;
}
vector<string> AdvRoom::getDescription()
{
vector<string> copyDesc = this->description;
return copyDesc;
}
string AdvRoom::getName()
{
string copyName = this->name;
return copyName;
}
void AdvRoom::addObject(AdvObject obj)
{
// This function should add the obj to the room.
// It however, should not add the object to the room
// if the room already contains the object.
this->objects.push_back(obj);
}
AdvObject AdvRoom::removeObject(string objName)
{
AdvObject deletedObj;
// This function should remove the object with objName.
for (int i = 0; i < this->objects.size(); ++i) {
if (this->objects[i].getName() == objName) {
deletedObj = this->objects[i];
this->objects.erase(this->objects.begin() + i);
}
}
return deletedObj;
}
bool AdvRoom::containsObject(string objName)
{
// Returns true if object with objName is in the room.
bool success = false;
for (int i = 0; i < this->objects.size(); ++i) {
if (this->objects[i].getName() == objName) {
success = true;
}
}
return success;
}
int AdvRoom::objectCount()
{
return this->objects.size();
}
AdvObject AdvRoom::getObject(int index)
{
return this->objects.at(index);
}
bool AdvRoom::hasBeenVisited()
{
bool truth = this->isVisited;
return truth;
}
void AdvRoom::setVisited(bool flag)
{
this->isVisited = flag;
}
vector<AdvMotionTableEntry> AdvRoom::getMotionTable()
{
vector<AdvMotionTableEntry> copyMotionTable = this->motionTable;
return copyMotionTable;
}
int AdvRoom::getRoomNumber()
{
int copyNumber = this->number;
return copyNumber;
}

Verification code doesn't work in Arduino

I am new to Arduino and I'm trying to make a program that receives IR codes from a TV remote, uses them as a 4 number pass code lighting up a LED as you press each button. And then comparing the code to a hard-coded one. In this case 1234.
I made a function to verify that the value entered is equal to the pass. If so, light up a green LED and else, light up a red one.
However, even if I input the correct code, only the red led lights up.
Here is my whole code as I'm not sure which part of it is the one causing problems:
const int pass[4] = {1, 2, 3, 4};
int value[4] = {};
int digitNum = 0;
int input;
void loop()
{
value[digitNum] = input; //where input is a number between 0 and 9
digitNum++;
if(digitNum == 1){
lightFirstLed();
}
else if(digitNum == 2){
lightSecondLed();
}
else if(digitNum == 3){
lightThirdLed();
}
else if(digitNum == 4){
lightFourthLed();
verify();
}
}
void verify()
{
bool falseCharacter = false;
for(int i = 0; i <= 4; i++){
if(value[i] != pass[i]){
falseCharacter = true;
}
}
if(!falseCharacter){
lightGreenLed();
}
else{
lightRedLed();
}
}
Functions in the form of light*Led actually do what they're supposed to do.
I tried changing the verify function around, that ended up making the green LED the one that always shone. I've been doing this for hours and I'm starting to feel disparate.
I would really appreciate any help. And please tell me if anything I'm doing does not comply with best practices even if it's out of the scope of this question.
For full code and design, here's a link to autodesk's simulator: https://www.tinkercad.com/things/0keqmlhVqNp-mighty-leelo/editel?tenant=circuits?sharecode=vVUD2_4774Lj4PYXh6doFcOqWUMY2URIfW8VXGxutRE=
EDIT: Now reset doesn't work
Your for loop in verify is accessing outside the array:
const int pass[4] = {1, 2, 3, 4};
int value[4] = {};
for(int i = 0; i <= 4; i++){
if(value[i] != pass[i]){
falseCharacter = true;
}
}
Change i <= 4 to i < 4. Also, when falseCharacter is set to true, break from the loop:
for(int i = 0; i < 4; i++)
{
if(value[i] != pass[i])
{
falseCharacter = true;
break;
}
}
Update
You need an else statement in loop:
void loop(void)
{
if(irrecv.decode(&results))
{
if (results.value == powBtn)
{
reset();
}
else if (results.value == zeroBtn)
{
input = 0;
}
else if (results.value == oneBtn)
{
input = 1;
}
else if (results.value == twoBtn)
{
input = 2;
}
else if (results.value == threeBtn)
{
input = 3;
}
else if (results.value == fourBtn)
{
input = 4;
}
else if (results.value == fiveBtn)
{
input = 5;
}
else if (results.value == sixBtn)
{
input = 6;
}
else if (results.value == sevenBtn)
{
input = 7;
}
else if (results.value == eightBtn)
{
input = 8;
}
else if (results.value == nineBtn)
{
input = 9;
}
else
{
return; /*** !!! Unrecognized Value !!! ***/
}
value[digitNum] = input;
digitNum++;
if(digitNum == 1)
{
digitalWrite(LED1, HIGH);
}
else if(digitNum == 2)
{
digitalWrite(LED2, HIGH);
}
else if(digitNum == 3)
{
digitalWrite(LED3, HIGH);
}
else if(digitNum == 4)
{
digitalWrite(LED4, HIGH);
verify();
}
else
{
if (results.value == powBtn)
{
reset();
}
}
// Receive the next value
irrecv.resume();
}
}

C++ [Microsoft][ODBC SQL Server Driver]String data, right truncation

I need help with ODBC prepared queries. I working on Windows 10(x64). My VPS server is Windows Server 2012(x64). My compiled aplication is 32 bit. I need prepared queries to make SQL Injection not possible. But have one big problem.
Error:
[QueryManager] State (22001), Diagnostic: [Microsoft][ODBC SQL Server Driver]String data, right truncation
Code:
gQueryManager.BindParameterAsString(1,Name,sizeof(Name));
gQueryManager.ExecQuery("SELECT Value FROM Table WHERE Name=?");
gQueryManager.Fetch();
...
gQueryManager.Close();
This is source code of Query Manager I using:
// QueryManager.cpp: implementation of the CQueryManager class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "QueryManager.h"
#include "Util.h"
CQueryManager gQueryManager;
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CQueryManager::CQueryManager() // OK
{
this->m_SQLEnvironment = SQL_NULL_HANDLE;
this->m_SQLConnection = SQL_NULL_HANDLE;
this->m_STMT = SQL_NULL_HANDLE;
this->m_RowCount = -1;
this->m_ColCount = -1;
memset(this->m_SQLColName,0,sizeof(this->m_SQLColName));
memset(this->m_SQLData,0,sizeof(this->m_SQLData));
SQLAllocHandle(SQL_HANDLE_ENV,SQL_NULL_HANDLE,&this->m_SQLEnvironment);
SQLSetEnvAttr(this->m_SQLEnvironment,SQL_ATTR_ODBC_VERSION,(SQLPOINTER)SQL_OV_ODBC3,SQL_IS_INTEGER);
}
CQueryManager::~CQueryManager() // OK
{
this->Disconnect();
}
bool CQueryManager::Connect(char* odbc,char* user,char* pass) // OK
{
strcpy_s(this->m_odbc,odbc);
strcpy_s(this->m_user,user);
strcpy_s(this->m_pass,pass);
if(SQL_SUCCEEDED(SQLAllocHandle(SQL_HANDLE_DBC,this->m_SQLEnvironment,&this->m_SQLConnection)) == 0)
{
return 0;
}
if(SQL_SUCCEEDED(SQLConnect(this->m_SQLConnection,(SQLCHAR*)this->m_odbc,SQL_NTS,(SQLCHAR*)this->m_user,SQL_NTS,(SQLCHAR*)this->m_pass,SQL_NTS)) == 0)
{
return 0;
}
if(SQL_SUCCEEDED(SQLAllocHandle(SQL_HANDLE_STMT,this->m_SQLConnection,&this->m_STMT)) == 0)
{
return 0;
}
else
{
return 1;
}
}
void CQueryManager::Disconnect() // OK
{
if(this->m_STMT != SQL_NULL_HANDLE)
{
SQLFreeHandle(SQL_HANDLE_STMT,this->m_STMT);
this->m_STMT = SQL_NULL_HANDLE;
}
if(this->m_SQLConnection != SQL_NULL_HANDLE)
{
SQLFreeHandle(SQL_HANDLE_DBC,this->m_SQLConnection);
this->m_SQLConnection = SQL_NULL_HANDLE;
}
if(this->m_SQLEnvironment != SQL_NULL_HANDLE)
{
SQLFreeHandle(SQL_HANDLE_ENV,this->m_SQLEnvironment);
this->m_SQLEnvironment = SQL_NULL_HANDLE;
}
}
void CQueryManager::Diagnostic(char* query) // OK
{
LogAdd(LOG_BLACK,"%s",query);
SQLINTEGER NativeError;
SQLSMALLINT RecNumber=1,BufferLength;
SQLCHAR SqlState[6],MessageText[SQL_MAX_MESSAGE_LENGTH];
while(SQLGetDiagRec(SQL_HANDLE_STMT,this->m_STMT,(RecNumber++),SqlState,&NativeError,MessageText,sizeof(MessageText),&BufferLength) != SQL_NO_DATA)
{
LogAdd(LOG_RED,"[QueryManager] State (%s), Diagnostic: %s",SqlState,MessageText);
}
if(strcmp((char*)SqlState,"08S01") == 0)
{
this->Connect(this->m_odbc,this->m_user,this->m_pass);
}
}
bool CQueryManager::ExecQuery(char* query,...) // OK
{
char buff[4096];
va_list arg;
va_start(arg,query);
vsprintf_s(buff,query,arg);
va_end(arg);
SQLRETURN result;
if(SQL_SUCCEEDED((result=SQLExecDirect(this->m_STMT,(SQLCHAR*)buff,SQL_NTS))) == 0 && result != SQL_NO_DATA)
{
this->Diagnostic(buff);
return 0;
}
SQLRowCount(this->m_STMT,&this->m_RowCount);
if(this->m_RowCount == 0){return 1;}
SQLNumResultCols(this->m_STMT,&this->m_ColCount);
if(this->m_ColCount == 0){return 1;}
if(this->m_ColCount > MAX_COLUMNS){return 0;}
memset(this->m_SQLColName,0,sizeof(this->m_SQLColName));
memset(this->m_SQLData,0,sizeof(this->m_SQLData));
for(int n=0;n < this->m_ColCount;n++)
{
SQLDescribeCol(this->m_STMT,(n+1),this->m_SQLColName[n],sizeof(this->m_SQLColName[n]),0,0,0,0,0);
SQLBindCol(this->m_STMT,(n+1),SQL_C_CHAR,this->m_SQLData[n],sizeof(this->m_SQLData[n]),&this->m_SQLDataLen[n]);
}
return 1;
}
void CQueryManager::Close() // OK
{
SQLCloseCursor(this->m_STMT);
SQLFreeStmt(this->m_STMT,SQL_UNBIND);
}
SQLRETURN CQueryManager::Fetch() // OK
{
return SQLFetch(this->m_STMT);
}
int CQueryManager::FindIndex(char* ColName) // OK
{
for(int n=0;n < this->m_ColCount;n++)
{
if(_stricmp(ColName,(char*)this->m_SQLColName[n]) == 0)
{
return n;
}
}
return -1;
}
int CQueryManager::GetResult(int index) // OK
{
return atoi(this->m_SQLData[index]);
}
int CQueryManager::GetAsInteger(char* ColName) // OK
{
int index = this->FindIndex(ColName);
if(index == -1)
{
return index;
}
else
{
return atoi(this->m_SQLData[index]);
}
}
float CQueryManager::GetAsFloat(char* ColName) // OK
{
int index = this->FindIndex(ColName);
if(index == -1)
{
return (float)index;
}
else
{
return (float)atof(this->m_SQLData[index]);
}
}
__int64 CQueryManager::GetAsInteger64(char* ColName) // OK
{
int index = this->FindIndex(ColName);
if(index == -1)
{
return index;
}
else
{
return _atoi64(this->m_SQLData[index]);
}
}
void CQueryManager::GetAsString(char* ColName,char* OutBuffer,int OutBufferSize) // OK
{
int index = this->FindIndex(ColName);
if(index == -1)
{
memset(OutBuffer,0,OutBufferSize);
}
else
{
strncpy_s(OutBuffer,OutBufferSize,this->m_SQLData[index],(OutBufferSize-1));
}
}
void CQueryManager::GetAsBinary(char* ColName,BYTE* OutBuffer,int OutBufferSize) // OK
{
int index = this->FindIndex(ColName);
if(index == -1)
{
memset(OutBuffer,0,OutBufferSize);
}
else
{
this->ConvertStringToBinary(this->m_SQLData[index],sizeof(this->m_SQLData[index]),OutBuffer,OutBufferSize);
}
}
void CQueryManager::BindParameterAsString(int ParamNumber,void* InBuffer,int ColumnSize) // OK
{
this->m_SQLBindValue[(ParamNumber-1)] = SQL_NTS;
SQLBindParameter(this->m_STMT,ParamNumber,SQL_PARAM_INPUT,SQL_C_CHAR,SQL_VARCHAR,ColumnSize,0,InBuffer,0,&this->m_SQLBindValue[(ParamNumber-1)]);
}
void CQueryManager::BindParameterAsBinary(int ParamNumber,void* InBuffer,int ColumnSize) // OK
{
this->m_SQLBindValue[(ParamNumber-1)] = ColumnSize;
SQLBindParameter(this->m_STMT,ParamNumber,SQL_PARAM_INPUT,SQL_C_BINARY,SQL_VARBINARY,ColumnSize,0,InBuffer,0,&this->m_SQLBindValue[(ParamNumber-1)]);
}
void CQueryManager::ConvertStringToBinary(char* InBuff,int InSize,BYTE* OutBuff,int OutSize) // OK
{
int size = 0;
memset(OutBuff,0,OutSize);
for(int n=0;n < InSize,size < OutSize;n++)
{
if(InBuff[n] == 0)
{
break;
}
if((n%2) == 0)
{
OutBuff[size] = ((InBuff[n]>='A')?((InBuff[n]-'A')+10):(InBuff[n]-'0'))*16;
size = size+0;
}
else
{
OutBuff[size] = OutBuff[size] | ((InBuff[n]>='A')?((InBuff[n]-'A')+10):(InBuff[n]-'0'));
size = size+1;
}
}
}
void CQueryManager::ConvertBinaryToString(BYTE* InBuff,int InSize,char* OutBuff,int OutSize) // OK
{
int size = 0;
memset(OutBuff,0,OutSize);
for(int n=0;n < OutSize,size < InSize;n++)
{
if((n%2) == 0)
{
OutBuff[n] = (((InBuff[size]/16)>=10)?('A'+((InBuff[size]/16)-10)):('0'+(InBuff[size]/16)));
size = size+0;
}
else
{
OutBuff[n] = (((InBuff[size]%16)>=10)?('A'+((InBuff[size]%16)-10)):('0'+(InBuff[size]%16)));
size = size+1;
}
}
}

could not determine size if fclose not done twice

I'm made a File class that is a sort of wrapper of the FILE type and added some methods.
This is the code of my file class :
#include <Fs/File.h>
File::File(Path& p):
m_path(p),
m_openned(false)
{
}
int File::open(const string& mode)
{
m_f = new FILE;
fopen(m_path, mode.c_str());
if (m_f == NULL)
{
m_openned = false;
return -1;
}
m_openned = true;
return 0;
}
bool File::exists()
{
FILE* file;
if (file = fopen(m_path, "r"))
{
fclose(file);
return true;
}
fclose(file);
return false;
}
int File::flush(){
return fflush(m_f);
}
int File::remove()
{
return ::remove(m_path);
}
int File::close()
{
if (isOpenned())
{
m_openned = false;
return fclose(m_f);
}
return 0;
}
long File::getSize()
{
struct stat file_status;
if(!this->exists())
return -1;
if (stat(m_path, &file_status) < 0)
{
return -1;
}
return file_status.st_size;
}
FileMode File::getMode()
{
struct stat file_status;
if (stat(m_path, &file_status) < 0)
{
return FileMode(-1);
}
return FileMode(file_status.st_mode);
}
Path File::getPath()
{
return m_path;
}
bool File::isOpenned()
{
return m_openned;
}
int File::setMode(FileMode& mode)
{
return chmod(m_path, mode);
}
int File::renameTo(File& f)
{
if (f.exists() || !this->exists())
return -1;
return rename( m_path , f.getPath());
}
int File::copyTo(File& to)
{
char ch;
this->close();
this->open(FileTypes::READ);
to.close();
to.open(FileTypes::WRITE);
while (!this->eof())
{
ch = this->readc();
if (ch == -1)
return 0;
if (!to.eof())
to.writec(ch);
}
if (this->close() < 0)
{
return -1;
}
if (to.close() < 0)
{
return -1;
}
return 0;
}
int File::readc()
{
if (!isOpenned())
return FileTypes::ENDOFFILE;
char c = fgetc(m_f);
if (ferror(m_f))
{
return FileTypes::ENDOFFILE;
}
return c;
}
int File::writec(char c)
{
if (!isOpenned())
return -1;
fputc(c, m_f);
if (ferror(m_f))
{
return FileTypes::ENDOFFILE;
}
return 0;
}
bool File::eof()
{
if (!isOpenned())
return true;
return feof(m_f);
}
I made some tests and I have a kind of problem
Path p1("test.txt");
Path p2("temp.txt");
File f1(p1);
File f2(p2);
assert(f1.open(FileTypes::READ) == 0);
assert(f1.exists() == true);
assert(f1.close() == 0);
cout<<"Mode of f1 "<<f1.getMode().getStringMode()<<endl;
cout<<"Path of f1 "<<f1.getPath().getAbsolutePath()<<endl;
cout<<"Size of f1 "<<f1.getSize()<<endl;
assert(f2.exists() == false);
assert(f1.copyTo(f2) == 0);
//#####################################
// If I comment f2.close() the
// assert(f1.getSize() == f2.getSize()) test fails and
// f2.getSize() == 0
##########################################
f2.close();
assert(f2.exists() == true);
assert(f1.getSize() == f2.getSize());
I couldn't figure why this f2.close is needed because I did a close in the copyTo method.
Can someone help me ?
Thank you in advance.
Ben
In File::copyTo:
if (ch == -1)
return 0;
you are jumping out of the function without properly closing the files. When the target file is not closed, it's contents is probably not sent to the OS, which later reports bogus filesize.
fclose flushes the stream. My guess is, is that without closing the file, the stream has not been fully written, so the sizes are different. Consider adding fflush(to); at the end of your copyTo method to ensure everything has been written.
You have multiple exits from the copyTo function which doesn't ensure that you actually close the file. It looks to me that you may be exiting early from the copyTo function and that the intended close isn't executing
while (!this->eof())
{
ch = this->readc();
if (ch == -1)
return 0;
if (!to.eof())
to.writec(ch);
}
when you hit the end of the file you will get EOF which in my os (windows) it is -1, which would cause you to return 0 here, and skip the close call.