C++ How to make that a function runs only one - c++

I use a C++\CLR project in Visual Studio 2017.At the time i try to manipulate the memory so i create a hack for a no name game and try to manipulate the game.
My problem is that I try to create a random integer and for that i use the function rand() in combination with firstSetRand srand().
using namespace System;
int * randomName()
{
srand((unsigned)time(0));
int i = 1;
static int name[5];
for (int i = 1; i < 5; i++)
{
name[i] = 97 + rand() % 122;
}
std::cout << name << std::endl;
return name;
}
This is my function for the random counts and here i call it:
int main(array<System::String ^> ^args)
{
while (true)
{
switch (inputCheat) //check which case match with the user input
{
case 4:
Console::WriteLine("test: ");
random:: randomName(firstSetRand);
//WriteProcessMemory(handle, (LPVOID)localName, &inputNumber, sizeof(), NULL); //Write to the local adress memory and change the value
Console::WriteLine("\nWhat did you want to cheat up: ");
break;
}
}
Sleep(200);
}
The problem is because that´s a while(true) loop and I call the function multiple times. And I don't know how to make that srand() function is only called once time i get always the same random number.
I am coming from Java. In Java i would do the whole code in a class and than i would write the variable in the constructor but i think that's not possible in C++. Because when i do the whole code in a class i get the error:
Severity Code Description Project File Line Suppression State
Error LNK2019 unresolved external symbol _main referenced in function "int __cdecl invoke_main(void)" (?invoke_main##YAHXZ) AssaultCubeHack C:\Users\schup\source\repos\AssaultCubeHack\AssaultCubeHack\MSVCRTD.lib(exe_main.obj) 1
Here is the full code of my project:
// AssaultCubeWithClr.cpp: Hauptprojektdatei.
#include "stdafx.h"
using namespace System;
struct InitRandHelper
{
InitRandHelper() { srand((unsigned)time(0)); }
};
int * randomName()
{
static InitRandHelper init;
int i = 1;
static int name[5];
for (int i = 1; i < 5; i++)
{
name[i] = 97 + rand() % 122;
}
std::cout << name << std::endl;
return name;
}
void StartText()
{
//Text to See in the Console
Console::ForegroundColor = System::ConsoleColor::Green;
Console::WriteLine("Welcome to my Cheat for AssaultCube!");
Console::WriteLine("------------------------------------");
Console::WriteLine("1. For More Health type in: 1.");
Console::WriteLine("2. For More Ammo type in: 2");
Console::WriteLine("3. For More Armor type in: 3");
Console::WriteLine("4. For Turn on Name changer: 4");
}
int main(array<System::String ^> ^args)
{
DWORD playerBaseAdress = 0x00509b74;
DWORD offsePrimaryAmmo = 0x128;
DWORD offsetPistolAmmo = 0x13C;
DWORD offsetArmor = 0xFC;
DWORD offsetHealth = 0xF8;
DWORD offsetRoll = 0x0080;
DWORD baseforName = 0x005028FC;
static bool firstSetRand = true;
int inputCheat;
int inputNumber;
DWORD processId;
DWORD localPlayer;
DWORD localName;
DWORD primaryAmmo;
DWORD pistolAmmo;
DWORD health;
DWORD armor;
DWORD roll;
bool firstExecute = true;
HWND hwnd = FindWindowA(NULL, "AssaultCube"); //Find Window with Name AssaultCube
StartText(); //function call
while (true)
{
if (hwnd == NULL) //Check if the game exists
{
if (firstExecute == true)
{
Console::ForegroundColor = System::ConsoleColor::Red;
Console::WriteLine("ERROR: The Game couldn´t found!");
firstExecute = false;
}
}
else
{
GetWindowThreadProcessId(hwnd, &processId); //Get Process id from the Window
HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, false, processId);
if (handle == NULL) //check if process id exsits
{
Console::ForegroundColor = System::ConsoleColor::Red;
Console::WriteLine("ERROR: Wrong Process Id!");
Console::ForegroundColor = System::ConsoleColor::Green;
}
else
{
ReadProcessMemory(handle, (LPCVOID)playerBaseAdress, &localPlayer, sizeof(playerBaseAdress), NULL); //Read the local adresse and save it in localPlayer
ReadProcessMemory(handle, (LPCVOID)baseforName, &localName, sizeof(playerBaseAdress), NULL);
primaryAmmo = localPlayer + offsePrimaryAmmo;
pistolAmmo = localPlayer + offsetPistolAmmo;
health = localPlayer + offsetHealth;
armor = localPlayer + offsetArmor;
roll = localPlayer + offsetRoll;
std::cin >> inputCheat; //wait for user input
switch (inputCheat) //check which case match with the user input
{
case 1:
Console::WriteLine("Write how much Health you want: ");
std::cin >> inputNumber;
WriteProcessMemory(handle, (LPVOID)health, &inputNumber, sizeof(inputNumber), NULL); //Write to the local adress memory and change the value
Console::WriteLine("\nWhat did you want to cheat up: ");
break;
case 2:
Console::WriteLine("Write how much Ammo you want: ");
std::cin >> inputNumber;
WriteProcessMemory(handle, (LPVOID)primaryAmmo, &inputNumber, sizeof(inputNumber), NULL); //Write to the local adress memory and change the value
Console::WriteLine("\nWhat did you want to cheat up: ");
break;
case 3:
Console::WriteLine("Write how much Armor you want: ");
std::cin >> inputNumber;
WriteProcessMemory(handle, (LPVOID)armor, &inputNumber, sizeof(inputNumber), NULL); //Write to the local adress memory and change the value
Console::WriteLine("\nWhat did you want to cheat up: ");
break;
case 4:
Console::WriteLine("Random Number: ");
randomName();
//WriteProcessMemory(handle, (LPVOID)localName, &inputNumber, sizeof(), NULL); //Write to the local adress memory and change the value
Console::WriteLine("\nWhat did you want to cheat up: ");
break;
case 5:
Console::WriteLine("test: ");
std::cin >> inputNumber;
WriteProcessMemory(handle, (LPVOID)roll, &inputNumber, sizeof(inputNumber), NULL); //Write to the local adress memory and change the value
Console::WriteLine("\nWhat did you want to cheat up: ");
break;
default:
Console::ForegroundColor = System::ConsoleColor::Red;
Console::WriteLine("ERROR: Wrong Entry!");
Console::WriteLine("Try a other input :D");
Console::ForegroundColor = System::ConsoleColor::Green;
break;
}
}
}
Sleep(200);
}
return 0;
}
Here you can see it doesn't work.

Solution 1
You can use a function static variable for that.
static bool firstTime = true;
if ( firstTime )
{
srand((unsigned)time(0));
firstTime = false;
}
Solution 2
If you don't want to pay the price of the check for each call of the function, you can use a helper class/struct.
struct InitRandHelper
{
InitRandHelper() { srand((unsigned)time(0)); }
};
int* randomName()
{
// Initialize the random number generator.
static InitRandHelper init;
int i = 1;
static int name[5];
for (int i = 1; i < 5; i++)
{
name[i] = 97 + rand() % 122;
}
std::cout << name << std::endl;
return name;
}
Solution 3
Call srand in main before the while loop begins.
int main(array<System::String ^> ^args)
{
srand((unsigned)time(0));
while (true)
{
switch (inputCheat) //check which case match with the user input
{
case 4:
Console::WriteLine("test: ");
random:: randomName(firstSetRand);
//WriteProcessMemory(handle, (LPVOID)localName, &inputNumber, sizeof(), NULL); //Write to the local adress memory and change the value
Console::WriteLine("\nWhat did you want to cheat up: ");
break;
}
}
Sleep(200);
}
and remove the call from random::randomName.

okay here the answer i found. Ther problem is this line:
std::cout << name << std::endl;
The Ouput in the console is not the value rather its the adress from the array. To do it proper i have to it so:
int i = 1;
static int name[5];
for (int i = 1; i < 5; i++)
{
name[i] = 97 + rand() % 122;
std::cout << name[i] << std::endl; //this line is the right thing to do it
}
return name;

Related

How to read EventViewer logs of remote machine using c++?

It is about to collect logs of event viewer from the remote machine.I have tried Event Logging api so far. Though,It works well by reading logs from the localhost,was failed to read from remote machine.
HANDLE OpenEventLogA(
[in] LPCSTR lpUNCServerName,
[in] LPCSTR lpSourceName
);
Using this,I have tried to open event logs by mentioning ipaddress of remote machine in the place of UNCServerName.But,it doesn't work.Below is the code,I've tried so far.
#include <windows.h>
#include <stdio.h>
#include <bits/stdc++.h>
#include <winbase.h>
#include<string.h>
#include <iostream>
#include<vector>
#define BUFFER_SIZE 1024*200
#define MAX_TIMESTAMP_LEN 23 + 1
#define MAX_WORD_LEN 1000
using namespace std;
struct SearchRecord {
string type;
string time;
string source;
string eid;
};
void FillEventRecordDetails(std::vector<SearchRecord*> *searchRecordResult)
{
HANDLE h;
int i=1,j=0;
EVENTLOGRECORD *pevlr;
BYTE bBuffer[BUFFER_SIZE];
DWORD dwRead, dwNeeded, dwRecord,dwThisRecord;
// Open the Application event log.
h = OpenEventLog(//ip address//,
"Application");
if (h == NULL)
{
cout<<GetLastError();
}
cout<<"HANDLE:"<<h;
pevlr = (EVENTLOGRECORD *) &bBuffer;
GetOldestEventLogRecord(h, &dwThisRecord);
cout<<"Record Number:"<<dwThisRecord;
GetNumberOfEventLogRecords(h, &dwRecord);
cout<<"\n New:"<<dwRecord+dwThisRecord;
while (ReadEventLog(h, EVENTLOG_SEEK_READ|
EVENTLOG_FORWARDS_READ ,
dwThisRecord,
pevlr,
BUFFER_SIZE,
&dwRead,
&dwNeeded))
{
while (dwRead > 0 )
{
//TYPE
string type;
switch(pevlr->EventType)
{
case EVENTLOG_ERROR_TYPE:
type = "ERROR";
break;
case EVENTLOG_WARNING_TYPE:
type = "WARNING";
break;
case EVENTLOG_INFORMATION_TYPE:
type = "INFORMATION";
break;
case EVENTLOG_AUDIT_SUCCESS:
type = "AUDIT_SUCCESS";
break;
case EVENTLOG_AUDIT_FAILURE:
type = "AUDIT_FAILURE";
break;
default:
type = "Unknown";
break;
}
//TIME
DWORD Time = ((PEVENTLOGRECORD)pevlr)->TimeGenerated ;
ULONGLONG ullTimeStamp = 0;
ULONGLONG SecsTo1970 = 116444736000000000;
SYSTEMTIME st;
FILETIME ft, ftLocal;
ullTimeStamp = Int32x32To64(Time, 10000000) + SecsTo1970;
ft.dwHighDateTime = (DWORD)((ullTimeStamp >> 32) & 0xFFFFFFFF);
ft.dwLowDateTime = (DWORD)(ullTimeStamp & 0xFFFFFFFF);
FileTimeToLocalFileTime(&ft, &ftLocal);
FileTimeToSystemTime(&ftLocal, &st);
ostringstream mon1 , day1 ,year1,hour1,min1,sec1,mil1;
mon1 << st.wMonth ;day1 << st.wDay ;year1 << st.wYear ;hour1 << st.wHour ;min1 << st.wMinute ;sec1 << st.wSecond ;mil1 <<st.wMilliseconds;
string mon = mon1.str();string day = day1.str();string year = year1.str();string hour = hour1.str();string min = min1.str();string sec = sec1.str();
string mil=mil1.str();
string time = day+"-"+mon+"-"+year+" "+hour+":"+min+":"+sec+":"+mil;
int id = ((PEVENTLOGRECORD)pevlr)->EventID & 0xFFFF;
ostringstream temp;
temp << id;
string eid = temp.str();
string source = (LPSTR) ((LPBYTE) pevlr + sizeof(EVENTLOGRECORD));
SearchRecord *pRecord = new SearchRecord();
pRecord->type = type;
pRecord->time = time;
pRecord->eid = eid;
pRecord->source = source;
searchRecordResult->push_back(pRecord);
cout<<i;
cout<<" Type:"<<type;
cout<<" Time:"<<time;
cout<<" Event Id:"<<id;
cout<<" source:"<<source;
cout<<"\n";
i++;
dwRead -= pevlr->Length;
pevlr = (EVENTLOGRECORD *)
((LPBYTE) pevlr + pevlr->Length);
}
dwThisRecord+=i;
pevlr = (EVENTLOGRECORD *) &bBuffer;
}
CloseEventLog(h);
}
int main()
{
vector<SearchRecord*> searchRecordResult ;
FillEventRecordDetails(&searchRecordResult);
}
Is there any way to read logs from remote machine using c++ code?
Thanks in advance.

How to find if espeak ended the speech?

I want to use espeak in my program. I'd like to know when espeak stops speaking. Are there any flags or functions to check?
Let's consider this is my program:
Line 1
espeak
Line 2
When I execute this code, espeak starts to say "hello, this is espeak" but before it ends, Line 2 of code is executed, and I don't like this. I am looking for a way to pause the program until espeak ends the speaking!
EDIT:
This is my complete code, I use pocketsphinx to recognize what the user say, then save it inside char* hyp and pass it through espeak by speech function.
static ps_decoder_t *ps;
static cmd_ln_t *config;
static FILE *rawfd;
espeak_POSITION_TYPE position_type;
espeak_AUDIO_OUTPUT output;
char *path=NULL;
int Buflength = 1000, Options=0;
void* user_data;
char Voice[] = {"English"};
char text2[30] = {"this is a english test"};
unsigned int Size,position=0, end_position=0, flags=espeakCHARS_AUTO, *unique_identifier;
t_espeak_callback *SynthCallback;
espeak_PARAMETER Parm;
//char* text;
static void initFuncs()
{
output = AUDIO_OUTPUT_PLAYBACK;
espeak_Initialize(output, Buflength, path, Options );
espeak_SetVoiceByName(Voice);
const char *langNativeString = "en";
espeak_VOICE voice;
memset(&voice, 0, sizeof(espeak_VOICE));
voice.languages = langNativeString;
voice.name = "US";
voice.variant = 2;
voice.gender = 1;
espeak_SetVoiceByProperties(&voice);
}
static void sleep_msec(int32 ms)
{
struct timeval tmo;
tmo.tv_sec = 0;
tmo.tv_usec = ms * 1000;
select(0, NULL, NULL, NULL, &tmo);
}
static void speech(char* hyp)
{
Size = strlen(hyp)+1;
espeak_Synth( hyp, Size, position, position_type, end_position, flags,unique_identifier, user_data );
espeak_Synchronize( );
}
static void recognize_from_microphone()
{
ad_rec_t *ad;
int16 adbuf[2048];
uint8 utt_started, in_speech;
int32 k;
char *hyp;
if ((ad = ad_open_dev(cmd_ln_str_r(config, "-adcdev"),(int) cmd_ln_float32_r(config,"-samprate"))) == NULL)
E_FATAL("Failed to open audio device\n");
if (ad_start_rec(ad) < 0)
E_FATAL("Failed to start recording\n");
if (ps_start_utt(ps) < 0)
E_FATAL("Failed to start utterance\n");
utt_started = FALSE;
E_INFO("Ready....\n");
for (;;) {
ad_start_rec(ad);
if ((k = ad_read(ad, adbuf, 2048)) < 0)
E_FATAL("Failed to read audio\n");
ps_process_raw(ps, adbuf, k, FALSE, FALSE);
in_speech = ps_get_in_speech(ps);
if (in_speech && !utt_started) {
utt_started = TRUE;
E_INFO("Listening...\n");
}
if (!in_speech && utt_started) {
ps_end_utt(ps);
hyp = (char*)ps_get_hyp(ps, NULL );
if (hyp != NULL) {
ad_stop_rec(ad);
speech(hyp);
printf("%s\n", hyp);
fflush(stdout);
}
if (ps_start_utt(ps) < 0)
E_FATAL("Failed to start utterance\n");
utt_started = FALSE;
E_INFO("Ready....\n");
}
}//for loop
ad_close(ad);
}
int main(int argc, char *argv[])
{
initFuncs();
config = cmd_ln_init(NULL, ps_args(), TRUE,
"-hmm", MODELDIR "/en-us/en-us",
"-lm", MODELDIR "/en-us/en-us.lm.bin",
"-dict", MODELDIR "/en-us/cmudict-en-us.dict",
NULL);
ps = ps_init(config);
recognize_from_microphone();
ps_free(ps);
cmd_ln_free_r(config);
return 0;
}
I adapted the espeak part of your code. In this code espeak is finished before Line 2 begins. Also the callback functionality is implemented. You are setting a voice by name and a voice by property. Maybe this is a problem. You are working with c-style strings and not with std::string. Maybe you are calculating the wrong string length. I don't know where the problem in your code is but the following code has fixed it:
#include <string>
#include <iostream>
#include <espeak/speak_lib.h>
espeak_POSITION_TYPE position_type(POS_CHARACTER);
espeak_AUDIO_OUTPUT output(AUDIO_OUTPUT_PLAYBACK);
void* user_data;
std::string voice("English");
std::string text("this is a english test");
unsigned int Size(0);
unsigned int position(0);
unsigned int end_position(0);
unsigned int flags(espeakCHARS_AUTO);
unsigned int* unique_identifier;
static void initFuncs() {
espeak_Initialize(output, 0, 0, 0);
espeak_SetVoiceByName(voice.c_str());
}
int SynthCallback(short *wav, int numsamples, espeak_EVENT *events) {
std::cout << "Callback: ";
for (unsigned int i(0); events[i].type != espeakEVENT_LIST_TERMINATED; i++) {
if (i != 0) {
std::cout << ", ";
}
switch (events[i].type) {
case espeakEVENT_LIST_TERMINATED:
std::cout << "espeakEVENT_LIST_TERMINATED";
break;
case espeakEVENT_WORD:
std::cout << "espeakEVENT_WORD";
break;
case espeakEVENT_SENTENCE:
std::cout << "espeakEVENT_SENTENCE";
break;
case espeakEVENT_MARK:
std::cout << "espeakEVENT_MARK";
break;
case espeakEVENT_PLAY:
std::cout << "espeakEVENT_PLAY";
break;
case espeakEVENT_END:
std::cout << "espeakEVENT_END";
break;
case espeakEVENT_MSG_TERMINATED:
std::cout << "espeakEVENT_MSG_TERMINATED";
break;
case espeakEVENT_PHONEME:
std::cout << "espeakEVENT_PHONEME";
break;
case espeakEVENT_SAMPLERATE:
std::cout << "espeakEVENT_SAMPLERATE";
break;
default:
break;
}
}
std::cout << std::endl;
return 0;
}
static void speech(std::string hyp) {
Size = hyp.length();
espeak_SetSynthCallback(SynthCallback);
espeak_Synth(hyp.c_str(), Size, position, position_type, end_position, flags,unique_identifier, user_data );
espeak_Synchronize( );
}
int main() {
initFuncs();
std::cout << "Start" << std::endl;
speech(text.c_str());
std::cout << "End" << std::endl;
return 0;
}
The out put is
Start
Callback: espeakEVENT_SENTENCE
Callback: espeakEVENT_WORD
Callback: espeakEVENT_WORD
Callback: espeakEVENT_WORD
Callback: espeakEVENT_WORD
Callback: espeakEVENT_WORD
Callback: espeakEVENT_END
Callback: espeakEVENT_MSG_TERMINATED
End
The timing of the console outout fits to the audio output. When you are working with C++, then you should use its tools and features like strings, cout instead of printf and smart pointers to avoid problems like this.

How send a structure through fifo

HI!
I am trying to pass whole structure from one program and read it in another using fifo.
I'm using read and write functions. I had a problem with putting my structure into this functions. When I did it and tried to send and receive I get an error (core dump) or I recived some trash. I dont know exactly, where my problem take place (in receiver or sender). How can I send/receive my structure, or what i have wrong in my code.Here is my code...Receiver
struct data
{
char* message;
int size;
vector <times> prog;
};
int if_fifo(char* name)
{
struct stat info;
int score = stat(name,&info);
if(S_ISFIFO(info.st_mode))
{
return 1;
}
else
{
return 0;
}
}
int fifo_in(char* name)
{
data msg;
int pip;
pip = open(name, O_RDONLY | O_NONBLOCK);
while(1)
{
int hr = read(pip,&msg,sizeof(msg));
if(hr != 0)
{
cout << "Message: " << msg.message << endl;
}
}
cout << "O.K." << endl;
return 0;
}
int main(int argc, char** argv) {
int c, status_in, status_out;
char* input;
char* output;
float del;
if(argc < 5)
{
cout << "Za malo podanych parametrow" << endl;
return 1;
}
else
{
while ((c = getopt(argc, argv, "iod:")) != -1)
{
switch (c)
{
case 'i':
input = argv[2];
status_in = if_fifo(input);
break;
case 'o':
output = argv[3];
status_out = if_fifo(output);
break;
case 'd':
del = atof(argv[4]);
break;
case '?':
printf("UKNOWN");
}
}
}
if(status_in == 1)
{
return fifo_in(input);
}
else
{
cout << "It isnt fifo!!" << endl;
}
return 0;
}
And sender:
struct data
{
char* message;
int size;
vector <times> prog;
}msg;
int if_fifo(char* name)
{
struct stat info;
int score = stat(name,&info);
if(S_ISFIFO(info.st_mode))
{
return 1;
}
else
{
return 0;
}
}
int fifo_out(char* name)
{
msg.message = "To jest to!!";
msg.size = sizeof(msg.message);
int pip;
pip = open(name, O_WRONLY);
if( pip == -1 )
{
perror("Error: open( ): ");
return 1;
}
write(pip,&msg,sizeof(msg));
return 0;
}
int main(int argc, char** argv) {
int c, status_out;
char* output;
if(argc < 3)
{
cout << "Za malo podanych parametrow" << endl;
return 1;
}
else
{
while ((c = getopt(argc, argv, "o:")) != -1)
{
switch (c)
{
case 'o':
output = argv[2];
status_out = if_fifo(output);
break;
case '?':
printf("UKNOWN");
}
}
}
if(status_out == 1)
{
return fifo_out(output);
}
return 0;
}
you cannot just send memory structures from one program to another. You have to do whats called 'serialization' ie convert the struct into a byte stream that represents the structure. There are many, many serialization techniques: ASN1/ Ber, XML, JSON, Google protocol buffs, roll your own.
Just so you know why this is. The field message in your struct is actually a pointer, when you send this pointer to another program it points to the same address but in the receiver prgram not the sender. That address likely doesnt exist and certainly does not contain the string you had in the sender program.

GetLogicalDriveStrings() and char - Where am I doing wrongly

I want to search a file which may be present in any drives such as C:\, D:\ etc. Using GetLogicalDriveStrings I can able to get the list of drives but when I add anything extra for the output, I am getting a null in the output prompt. Here is my code:
#include "StdAfx.h"
#include <windows.h>
#include <stdio.h>
#include <conio.h>
// Buffer length
DWORD mydrives = 100;
// Buffer for drive string storage
char lpBuffer[100];
const char *extFile = "text.ext";
// You may want to try the wmain() version
int main(void)
{
DWORD test;
int i;
test = GetLogicalDriveStrings(mydrives, (LPWSTR)lpBuffer);
if(test != 0)
{
printf("GetLogicalDriveStrings() return value: %d, Error (if any): %d \n", test, GetLastError());
printf("The logical drives of this machine are:\n");
// Check up to 100 drives...
for(i = 0; i<100; i++)
printf("%c%s", lpBuffer[i],extFile);
printf("\n");
}
else
printf("GetLogicalDriveStrings() is failed lor!!! Error code: %d\n", GetLastError());
_getch();
return 0;
}
I want above output as C:\text.ext D:\text.ext ... rather I am getting text.ext only. I am using Microsoft Visual C++ 2010 Express
GetLogicalDriveStrings() returns a double-null terminated list of null-terminated strings. E.g., say you had drives A, B and C in your machine. The returned string would look like this:
A:\<nul>B:\<nul>C:\<nul><nul>
You can use the following code to iterate through the strings in the returned buffer and print each one in turn:
DWORD dwSize = MAX_PATH;
char szLogicalDrives[MAX_PATH] = {0};
DWORD dwResult = GetLogicalDriveStrings(dwSize,szLogicalDrives);
if (dwResult > 0 && dwResult <= MAX_PATH)
{
char* szSingleDrive = szLogicalDrives;
while(*szSingleDrive)
{
printf("Drive: %s\n", szSingleDrive);
// get the next drive
szSingleDrive += strlen(szSingleDrive) + 1;
}
}
Note that the details of how the function works, including the example code that I shamelessly copied and pasted, can be found by reading the docs.
Did you mean to put the printf in the loop?
Currently, you set extFile 100 times (just to be sure?!)
for(i = 0; i<100; i++)
extFile = "text.ext";
You meant to show all the drive letters in a loop:
for(i = 0; i<100; i++)
{
extFile = "text.ext";
printf("%c%s", lpBuffer[i], extFile); //I guess you mean extFile here?
}
DWORD dwSize = MAX_PATH;
WCHAR szLogicalDrives[MAX_PATH] = { 0 };
DWORD dwResult = GetLogicalDriveStrings(dwSize, szLogicalDrives);
CStringArray m_Drives;
m_Drives.RemoveAll();
if (dwResult > 0 && dwResult <= MAX_PATH)
{
WCHAR* szSingleDrive = szLogicalDrives;
while (*szSingleDrive)
{
UINT nDriveType = GetDriveType(szSingleDrive);
m_Drives.Add(CString(szSingleDrive, 2));
// get the next drive
szSingleDrive += wcslen(szSingleDrive) + 1;
}
}
return m_Drives;
class DriveList {
protected:
LPTSTR m_driveList;
DWORD m_driveCount;
DWORD m_bufSize = 32 * sizeof(TCHAR);
public:
virtual ~DriveList() {
free(m_driveList);
}
DriveList() {
m_driveList = (LPTSTR)malloc(m_bufSize);
}
int getDriveCount() const {
return m_driveCount;
}
TCHAR operator[] (const int index) const {
return m_driveList[index];
}
void loadDriveList() {
DWORD mask;
if((mask = GetLogicalDrives()) == 0) {
throw;
}
m_driveCount = 0;
for(int x = 0; x <= 25; x++ ) {
if(mask & 1) {
m_driveList[m_driveCount] = TCHAR(65 + x);
m_driveCount += 1;
}
mask >>= 1;
}
}
};

How can I find the size of all files located inside a folder?

Is there any API in c++ for getting the size of a specified folder?
If not, how can I get the total size of a folder including all subfolders and files?
How about letting OS do it for you:
long long int getFolderSize(string path)
{
// command to be executed
std::string cmd("du -sb ");
cmd.append(path);
cmd.append(" | cut -f1 2>&1");
// execute above command and get the output
FILE *stream = popen(cmd.c_str(), "r");
if (stream) {
const int max_size = 256;
char readbuf[max_size];
if (fgets(readbuf, max_size, stream) != NULL) {
return atoll(readbuf);
}
pclose(stream);
}
// return error val
return -1;
}
Actually I don't want to use any third party library. Just want to
implement in pure c++.
If you use MSVC++ you have <filesystem> "as standard C++".
But using boost or MSVC - both are "pure C++".
If you don’t want to use boost, and only the C++ std:: library this answer is somewhat close. As you can see here, there is a Filesystem Library Proposal (Revision 4). Here you can read:
The Boost version of the library has been in widespread use for ten
years. The Dinkumware version of the library, based on N1975
(equivalent to version 2 of the Boost library), ships with Microsoft
Visual C++ 2012.
To illustrate the use, I adapted the answer of #Nayana Adassuriya , with very minor modifications (OK, he forgot to initialize one variable, and I use unsigned long long, and most important was to use: path filePath(complete (dirIte->path(), folderPath)); to restore the complete path before the call to other functions). I have tested and it work well in windows 7.
#include <iostream>
#include <string>
#include <filesystem>
using namespace std;
using namespace std::tr2::sys;
void getFoldersize(string rootFolder,unsigned long long & f_size)
{
path folderPath(rootFolder);
if (exists(folderPath))
{
directory_iterator end_itr;
for (directory_iterator dirIte(rootFolder); dirIte != end_itr; ++dirIte )
{
path filePath(complete (dirIte->path(), folderPath));
try{
if (!is_directory(dirIte->status()) )
{
f_size = f_size + file_size(filePath);
}else
{
getFoldersize(filePath,f_size);
}
}catch(exception& e){ cout << e.what() << endl; }
}
}
}
int main()
{
unsigned long long f_size=0;
getFoldersize("C:\\Silvio",f_size);
cout << f_size << endl;
system("pause");
return 0;
}
You may use boost in this way. You can try to optimize it some deeper.
#include <iostream>
#include <string>
#include <boost/filesystem.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/algorithm/string.hpp>
using namespace std;
namespace bsfs = boost::filesystem;
void getFoldersize(string rootFolder,long & file_size){
boost::replace_all(rootFolder, "\\\\", "\\");
bsfs::path folderPath(rootFolder);
if (bsfs::exists(folderPath)){
bsfs::directory_iterator end_itr;
for (bsfs::directory_iterator dirIte(rootFolder); dirIte != end_itr; ++dirIte )
{
bsfs::path filePath(dirIte->path());
try{
if (!bsfs::is_directory(dirIte->status()) )
{
file_size = file_size + bsfs::file_size(filePath);
}else{
getFoldersize(filePath.string(),file_size);
}
}catch(exception& e){
cout << e.what() << endl;
}
}
}
}
int main(){
long file_size =0;
getFoldersize("C:\\logs",file_size);
cout << file_size << endl;
system("pause");
return 0;
}
Something like this would be better to avoid adding symbolic(soft) links:
std::uintmax_t directorySize(const std::filesystem::path& directory)
{
std::uintmax_t size{ 0 };
for (const auto& entry : std::filesystem::recursive_directory_iterator(directory))
{
if (entry.is_regular_file() && !entry.is_symlink())
{
size += entry.file_size();
}
}
return size;
}
Size of files in a folder
Please have a look at this link
#include <iostream>
#include <windows.h>
#include <string>
using namespace std;
__int64 TransverseDirectory(string path)
{
WIN32_FIND_DATA data;
__int64 size = 0;
string fname = path + "\\*.*";
HANDLE h = FindFirstFile(fname.c_str(),&data);
if(h != INVALID_HANDLE_VALUE)
{
do {
if( (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
{
// make sure we skip "." and "..". Have to use strcmp here because
// some file names can start with a dot, so just testing for the
// first dot is not suffient.
if( strcmp(data.cFileName,".") != 0 &&strcmp(data.cFileName,"..") != 0)
{
// We found a sub-directory, so get the files in it too
fname = path + "\\" + data.cFileName;
// recurrsion here!
size += TransverseDirectory(fname);
}
}
else
{
LARGE_INTEGER sz;
// All we want here is the file size. Since file sizes can be larger
// than 2 gig, the size is reported as two DWORD objects. Below we
// combine them to make one 64-bit integer.
sz.LowPart = data.nFileSizeLow;
sz.HighPart = data.nFileSizeHigh;
size += sz.QuadPart;
}
}while( FindNextFile(h,&data) != 0);
FindClose(h);
}
return size;
}
int main(int argc, char* argv[])
{
__int64 size = 0;
string path;
size = TransverseDirectory("c:\\dvlp");
cout << "\n\nDirectory Size = " << size << "\n";
cin.ignore();
return 0;
}
For more detail PLease CLick Here
The file system functions are integral part of each operative system, written mostly in C and assembler, not C++, each C++ library implementation for this are in one way or another a wrapper of this functions. Taking on count the effort and if you will not use your implementation in different OS, maybe is a good idea to use this functions directly and save some overhead and time.
Best regards.
I have my types definition file with:
typedef std::wstring String;
typedef std::vector<String> StringVector;
typedef unsigned long long uint64_t;
and code is:
uint64_t CalculateDirSize(const String &path, StringVector *errVect = NULL, uint64_t size = 0)
{
WIN32_FIND_DATA data;
HANDLE sh = NULL;
sh = FindFirstFile((path + L"\\*").c_str(), &data);
if (sh == INVALID_HANDLE_VALUE )
{
//if we want, store all happened error
if (errVect != NULL)
errVect ->push_back(path);
return size;
}
do
{
// skip current and parent
if (!IsBrowsePath(data.cFileName))
{
// if found object is ...
if ((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY)
// directory, then search it recursievly
size = CalculateDirSize(path + L"\\" + data.cFileName, NULL, size);
else
// otherwise get object size and add it to directory size
size += (uint64_t) (data.nFileSizeHigh * (MAXDWORD ) + data.nFileSizeLow);
}
} while (FindNextFile(sh, &data)); // do
FindClose(sh);
return size;
}
bool IsBrowsePath(const String& path)
{
return (path == _T(".") || path == _T(".."));
}
This uses UNICODE and returns failed dirs if you want that.
To call use:
StringVector vect;
CalculateDirSize(L"C:\\boost_1_52_0", &vect);
CalculateDirSize(L"C:\\boost_1_52_0");
But never pass size
//use FAT32
#undef UNICODE // to flag window deactive unicode
#include<Windows.h> //to use windows api
#include<iostream>
#include<iomanip>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
#pragma pack(1) //tell compiler do'nt do prag
struct BPB
{
BYTE JMP[3];
BYTE OEM[8];
WORD NumberOfBytesPerSector;
BYTE NumberOfSectorsPerCluster;
WORD NumberOfReservedSectors;
BYTE NumberOfFATs;
WORD NumberOfRootEntries16;
WORD LowNumbferOfSectors;
BYTE MediaDescriptor;
WORD NumberOfSectorsPerFAT16;
WORD NumberOfSectorsPerTrack;
WORD NumberOfHeads;
DWORD NumberOfHiddenSectors;
DWORD HighNumberOfSectors;
DWORD NumberOfSectorsPerFAT32;
WORD Flags;
WORD FATVersionNumber;
DWORD RootDirectoryClusterNumber;
WORD FSInfoSector;
WORD BackupSector;
BYTE Reserver[12];
BYTE BiosDrive;
BYTE WindowsNTFlag;
BYTE Signature;
DWORD VolumeSerial;
BYTE VolumeLabel[11];
BYTE SystemID[8];
BYTE CODE[420];
WORD BPBSignature;
};
//-----------------------------------------------------------
struct DirectoryEntry
{
BYTE Name[11];
BYTE Attributes;
BYTE Reserved;
BYTE CreationTimeTenth;
WORD CreationTime;
WORD CreationDate;
WORD LastAccessTime;
WORD HiClusterNumber;
WORD WriteTime;
WORD WriteDate;
WORD LowClusterNumber;
DWORD FileSize; //acual size of file
};
//---------------------------------------------------
void dirFunction(string s){
string path = "\\\\.\\" + s + ":";
HANDLE hFile = CreateFile(path.c_str(), GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);//open partition
BPB bootSector;//var from bootSector structure
DWORD readBytes = 0;
if (hFile == INVALID_HANDLE_VALUE)
{
cout << "Error " << GetLastError()<<endl;
return;
}
ReadFile(hFile, (BYTE*)&bootSector, sizeof(bootSector), &readBytes, 0);//read partition and load bootSector information inside our structure
LONG t = 0;
ULONG distance = bootSector.NumberOfReservedSectors +
bootSector.NumberOfFATs*bootSector.NumberOfSectorsPerFAT32;//distance from begine until Root Directory or content of partetion
distance *= bootSector.NumberOfBytesPerSector;//convert distance number to bytes value
SetFilePointer(hFile, distance, &t, FILE_BEGIN);//set pointer to root directory begine or begine of data
int clusterSize = bootSector.NumberOfBytesPerSector*bootSector.NumberOfSectorsPerCluster; //cluster size
int NumberOfEntries = clusterSize / sizeof(DirectoryEntry); //number of record inside cluster
DirectoryEntry* root = new DirectoryEntry[NumberOfEntries];//descripe the partetion
ReadFile(hFile, (BYTE*)root, clusterSize, &readBytes, 0);
DWORD clusterNumber;
for (int i = 0; i < NumberOfEntries; i++)
{
if (root[i].Name[0] == 0)//there no entery after this
break;
if (root[i].Name[0] == 0xE5)
continue;
if ((root[i].Attributes & 0xF) == 0xF)
continue;
for (int j = 0; j < 8; j++)
cout << root[i].Name[j];
if((root[i].Attributes & 0x10) != 0x10){
cout<<".";
for (int j = 8; j < 11; j++)
cout << root[i].Name[j];
}
if ((root[i].Attributes & 0x10) == 0x10){
cout << "\t<Folder>" ;
}else{
cout<<"\t<File>" ;
}
clusterNumber = root[i].HiClusterNumber << 16;
clusterNumber |= root[i].LowClusterNumber;
cout <<"\t"<<root[i].FileSize<<"bytes" << "\t" << clusterNumber<<"cluster" << endl;
}
CloseHandle(hFile);
}
//---------------------------------------------------------------
string convertLowerToUpper(string f){
string temp = "";
for (int i = 0; i < f.size(); i++){
temp += toupper(f[i]);
}
return temp;
}
//---------------------------------------------------------------
string getFileName(BYTE filename[11]){
string name = "";
for (int i = 0; i < 8; i++){
if (filename[i] != ' ')
name += filename[i];
}
return (name);
}
//------------------------------------------------------------------
int findEntryNumber(DirectoryEntry* root, int NumberOfEntries, string required){
string n;
int j = 0;
for (int i = 0; i < NumberOfEntries; i++){
if (strcmp((getFileName(root[i].Name).c_str()), convertLowerToUpper(required).c_str()) == 0){
return i;
}
}
return -1;
}
//---------------------------------------------------------------
void typeFunction(string fileName, string s){
string path = "\\\\.\\" + s + ":";
HANDLE hFile = CreateFile(path.c_str(), GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);//open partition
BPB bootSector;//var from bootSector structure
DWORD readBytes = 0;
if (hFile == INVALID_HANDLE_VALUE)
{
cout << "Error " << GetLastError()<<endl;
return;
}
ReadFile(hFile, (BYTE*)&bootSector, sizeof(bootSector), &readBytes, 0);//read partition and load bootSector information inside our structure
LONG t = 0;
ULONG distance = bootSector.NumberOfReservedSectors +
bootSector.NumberOfFATs*bootSector.NumberOfSectorsPerFAT32;//distance from begine until Root Directory or content of partetion
distance *= bootSector.NumberOfBytesPerSector;//convert distance number to bytes value
SetFilePointer(hFile, distance, &t, FILE_BEGIN);//set pointer to root directory begine or begine of data
int clusterSize = bootSector.NumberOfBytesPerSector*bootSector.NumberOfSectorsPerCluster; //cluster size
int NumberOfEntries = clusterSize / sizeof(DirectoryEntry); //number of record inside cluster
DirectoryEntry* root = new DirectoryEntry[NumberOfEntries];//descripe the partetion
ReadFile(hFile, (BYTE*)root, clusterSize, &readBytes, 0);
DWORD clusterNumber;
int index = findEntryNumber(root, NumberOfEntries, fileName);
if (index == -1){
cout << "File is not found" << endl;
return;
}
if (((root[index].Attributes & 0x10) == 0x10) ){
cout << "Is not file name" << endl;
return;
}
clusterNumber = root[index].HiClusterNumber << 16;
clusterNumber |= root[index].LowClusterNumber;
ULONG temp = (clusterNumber - 2) * clusterSize;
distance += temp;
t = 0;
SetFilePointer(hFile, distance, &t, FILE_BEGIN);
BYTE* buffer = new BYTE[clusterSize];
readBytes = 0;
ReadFile(hFile, (BYTE*)buffer, clusterSize, &readBytes, 0);
for (int i = 0; i < root[index].FileSize; i++){
cout << buffer[i];
}
cout << endl;
CloseHandle(hFile);
}
//----------------------------------------------------------------------
void delFunction(string filename, string s){
string path = "\\\\.\\" + s + ":";
HANDLE hFile = CreateFile(path.c_str(), GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);//open partition
BPB bootSector;//var from bootSector structure
DWORD readBytes = 0;
if (hFile == INVALID_HANDLE_VALUE)
{
cout << "Error " << GetLastError()<<endl;
return;
}
ReadFile(hFile, (BYTE*)&bootSector, sizeof(bootSector), &readBytes, 0);//read partition and load bootSector information inside our structure
LONG t = 0;
ULONG distance = bootSector.NumberOfReservedSectors +
bootSector.NumberOfFATs*bootSector.NumberOfSectorsPerFAT32;//distance from begine until Root Directory or content of partetion
distance *= bootSector.NumberOfBytesPerSector;//convert distance number to bytes value
SetFilePointer(hFile, distance, &t, FILE_BEGIN);//set pointer to root directory begine or begine of data
int clusterSize = bootSector.NumberOfBytesPerSector*bootSector.NumberOfSectorsPerCluster; //cluster size
int NumberOfEntries = clusterSize / sizeof(DirectoryEntry); //number of record inside cluster
DirectoryEntry* root = new DirectoryEntry[NumberOfEntries];//descripe the partetion
ReadFile(hFile, (BYTE*)root, clusterSize, &readBytes, 0);
DWORD clusterNumber;
readBytes = 0;
t = 0;
int index = findEntryNumber(root, NumberOfEntries, filename);
if (index == -1){
cout << "FIle is not found" << endl;
return;
}
if ((root[index].Attributes & 0x10) == 0x10){
cout << "Is not file name" << endl;
return;
}
//delete file
root[index].Name[0] = 0xE5;
SetFilePointer(hFile, distance, &t, FILE_BEGIN);
WriteFile(hFile, (BYTE*)root, clusterSize, &readBytes, 0);
cout<<filename<<" is deleted\n";
CloseHandle(hFile);
}
//----------------------------------------------------------------------
string removeExtention(string s){
string t = "";
for (int i = 0; i < s.size(); i++){
if (s[i] == '.')break;
t += s[i];
}
return t;
}
//-------------------------------------------------------------------
void main()
{
string swich_value;
string directory;
string file_name;
//dirFunction("G");
cout<<"plz, Enter single Partition character ------> example E or G\n\n";
cin>>directory;
string path = "\\\\.\\" + directory + ":";
cout<<"current directory is "<<path<<endl;
cout<<"Enter Options: \n1- dir \n2- type file_name.extention \n3- del file_name.extention\n\n";
again:
cin>>swich_value;
if(swich_value.at(1)!='i')
cin>>file_name;
string answer;
switch(swich_value.at(1)){
case 'i':
dirFunction(directory);
cout<<"\nare you want to do another process: y or n?";
cin>>answer;
if (answer.at(0)=='y')
goto again;
break;
case 'y':
typeFunction(removeExtention(file_name), directory);
cout<<"\nare you want to do another process: y or n?";
cin>>answer;
if (answer.at(0)=='y')
goto again;
break;
case 'e':
delFunction(removeExtention(file_name), directory);
cout<<"\nare you want to do another process: y or n?";
cin>>answer;
if (answer.at(0)=='y')
goto again;
break;
}
}
You can use "boost::filesystem"
#include <boost/filesystem.hpp>
namespace fs = boost::filesystem;
unsigned long long int get_directory_size(const fs::path& directory){
if (!fs::exists(directory)) return 0;
if (fs::is_directory(directory)){
unsigned long long int ret_size = 0;
fs::directory_iterator m_dir_itr(directory);
for (m_dir_itr = fs::begin(m_dir_itr); m_dir_itr != fs::end(m_dir_itr); ++m_dir_itr){
fs::directory_entry m_dir_entry = *m_dir_itr;
if (fs::is_regular_file(m_dir_entry.path())){
ret_size += fs::file_size(m_dir_entry.path());
}else if (fs::is_directory(m_dir_entry.path())){
ret_size += get_directory_size(m_dir_entry.path());
}
}
return ret_size;
} else if (fs::is_regular_file(directory)){
return fs::file_size(directory);
}
return 0;
}
#include <stdio.h>
int main(int /*argc*/, char** /*argv*/) {
// Assuming 'C:/Folder' be any directory then its size can be found using
auto folder_size = get_directory_size("C:/Folder");
printf("Size of 'C:/Folder' is %d\n",folder_size);
return 0;
}
With the introduction of std::filesystem, you no more have to use any system APIs or any external libraries.
#include <filesystem>
namespace n_fs = ::std::filesystem;
double archive::getFolderSize(std::string path)
{
double r = 0.0;
try{
if (!n_fs::is_directory(path))
{
r += (double)n_fs::file_size(path);
}
else
{
for(auto entry: n_fs::directory_iterator(path))
getFolderSize(entry.path().string());
}
}
catch(exception& e)
{
std::cout << e.what() << std::endl();
}
return r;
}
int main(){
double folderSize = getFolderSize("~/dev/"); //Replace with your path
std::cout << "Size of Folder: " << folderSize;
}
Try using GetFileSizeEx function. Following is some sample code for this. You need to get the size from the LARGE_INTEGER union though.
#include <iostream>
#include <windows.h>
#include <stdio.h>
#include <io.h>
using namespace std;
int main()
{
FILE *fp;
fp = fopen("C:\test.txt","r");
int fileNo = _fileno(fp);
HANDLE cLibHandle = (HANDLE)_get_osfhandle(fileNo);
long int fileSize = 0;
LARGE_INTEGER fileSizeL;
GetFileSizeEx(cLibHandle, &fileSizeL);
return 0;
}
5 years and not a simple solution with standard C++, that's why I would like to contribute my solution to this question:
uint64_t GetDirSize(const std::string &path)
{
uint64_t size = 0;
for (const auto & entry : std::experimental::filesystem::directory_iterator(path))
{
if(entry.status().type() == std::experimental::filesystem::file_type::regular)
size += std::experimental::filesystem::file_size(entry.path());
if (entry.status().type() == std::experimental::filesystem::file_type::directory)
size += GetDirSize(entry.path().generic_string());
}
return size;
}
Use it for example by calling
GetDirSize("C:\\dir_name")
if you're using Windows.
Calculating a folder size in bytes on Windows.
size_t GetFolderSizeInBytes(std::wstring path)
{
size_t result = 0;
WIN32_FIND_DATA findData;
HANDLE hFileHandle;
std::wstring sourcePath(path);
if (GetFileAttributes(sourcePath.c_str()) & FILE_ATTRIBUTE_DIRECTORY)
sourcePath.push_back(L'\\');
std::wstring fileName(sourcePath);
fileName.append(L"*");
hFileHandle = FindFirstFileEx(
fileName.data(),
FindExInfoStandard,
&findData,
FindExSearchNameMatch,
NULL,
FIND_FIRST_EX_ON_DISK_ENTRIES_ONLY);
if (hFileHandle != INVALID_HANDLE_VALUE)
{
do
{
if (!wcscmp(findData.cFileName, L".") || !wcscmp(findData.cFileName, L".."))
continue;
if ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
{
// Folder
std::wstring newPath = path + L"\\" + findData.cFileName;
result += GetFolderSizeInBytes(newPath);
}
else
{
// File
unsigned long high = findData.nFileSizeHigh;
unsigned long low = findData.nFileSizeLow;
size_t size = size_t(high * (MAXWORD + 1)) + low;
result += size;
}
} while (FindNextFile(hFileHandle, &findData));
FindClose(hFileHandle);
}
return result;
}