Why Am I Writing 0 bytes with WriteFile? - c++

I'm trying to make a program that finds the next .exe file in a user-defined directory and writes a flag to it (for a computer security class).
It's currently writing 0 bytes, and I'm not sure why.
Here is my code so far:
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <Windows.h>
#include <fstream>
using namespace std;
typedef wchar_t wchar;
struct thePlague{
long int origBytes;
wchar_t flag[6];
};
void main() {
WIN32_FIND_DATA findFileData; //Windows structure that receives info about a found file or directory
HANDLE hFind = INVALID_HANDLE_VALUE; //Handle that holds whether or not a file was successfully found with FindNextFile
LARGE_INTEGER fileSize;
wchar szDir[MAX_PATH];
DWORD dwError = 0;
wchar directory[MAX_PATH];
wcout<<L"Please enter a directory: ";
wcin>>directory;
// Check that the input path plus 7 is not longer than MAX_PATH.
// 7 characters are for the "\*.exe" plus NULL appended below.
if (wcslen(directory) > (MAX_PATH - 7)) {
wcout<<L"\nDirectory is too long\n";
return;
}
wcout<<L"Target directory is: "<<directory<<endl;
// Prepare string for use with FindFile functions. First, copy the
// string to a buffer, then append '\*' to the directory name.
wcscpy(szDir, directory);
wcscat(szDir, L"\\*.exe");
//Find the first file in the directory
hFind = FindFirstFile(szDir, &findFileData);
if (hFind == INVALID_HANDLE_VALUE) {
wcout<<L"FindFirstFile Failed"<<GetLastError()<<endl;
return;
}
do {
fileSize.LowPart = findFileData.nFileSizeLow;
fileSize.HighPart = findFileData.nFileSizeHigh;
wcout<<findFileData.cFileName<<L" "<<fileSize.QuadPart<<L" bytes\n";
DWORD dwBytesWritten = 0; //# of bytes written by WriteFile
wchar_t *buffer = (wchar *)malloc(sizeof(thePlague)); //A buffer the size of our struct (infection flag)
wofstream writeToBuffer(buffer, ios::binary); //Open the buffer for writing
thePlague newVictim; //New infection flag
writeToBuffer.write((const wchar_t*)&newVictim, sizeof(thePlague));
writeToBuffer.close();
DWORD dwErrorFlag;
dwErrorFlag = WriteFile(hFind, //The handle holding the file we are writing to
buffer, //The buffer holding what we want to write to the file, in this case a struct
sizeof(thePlague), //How many bytes to write to the file
&dwBytesWritten, //Where to store the # of bytes successfully written
NULL //Where to write to incase of overlap
);
if (dwErrorFlag == false)
wcout<<L"Error was: "<<GetLastError()<<endl;
wcout<<L"# of bytes written: "<<dwBytesWritten<<endl;
} while(FindNextFile(hFind, &findFileData) != 0);
FindClose(hFind);
return;
}
When I run this, I get:
Please enter a directory: C:\Infect
Target directory is: C:\Infect
hello.exe 65536 bytes
Error was: 6
# of bytes written: 0
Press any key to continue . . .
I know this is an ERROR_INVALID_HANDLE, but how do I fix this?

You need to open the file before writing to it. Your HANDLE hFind is just a handle to iterate over directories/files, not an open handle to a file.
Use CreateFile() to open the file

FindFirstFile returns a search handle, but WriteFile requires an open file handle. Use CreateFile to open the file before writing to it with WriteFile.

Related

Why do I get special characters when getting the source code of a website? c++

I am trying to get the source code of Barack Obama's Wikipedia page and save it to a file.
Everything works well until I open the file and see some weird characters in it:
As you can see, EOT1024 appears in the file, but it does not appear in the website's actual source code, which I checked using Google Chrome. I would like to know why this is happening, and how I can stop it from happening.
My code:
#include <iostream>
#include <windows.h>
#include <wininet.h>
#include <fstream>
int main(){
std::string textLink = "https://en.wikipedia.org/wiki/Barack_Obama";
std::ofstream file;
HINTERNET hInternet, hFile;
char buf[1024];
DWORD bytes_read;
int finished = 0;
bool e=false;
std::string waste;
file.open("data.txt",std::ios::out);
hInternet = InternetOpenW(L"Whatever", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
if (hInternet == NULL) {
printf("InternetOpen failed\n");
}
hFile = InternetOpenUrl(hInternet, textLink.c_str(), NULL, 0L, 0, 0);
if (hFile == NULL) {
printf("InternetOpenUrl failed\n");
}
while (!finished) {
if (InternetReadFile(hFile, buf, sizeof(buf), &bytes_read)) {
if (bytes_read > 0) {
file << bytes_read << buf;
}
else {
finished = 1;
}
}
else {
printf("InternetReadFile failed\n");
finished = 1;
}
}
InternetCloseHandle(hInternet);
InternetCloseHandle(hFile);
file.close();
}
I have the text file as I view it in Notepad++ right here:
https://drive.google.com/open?id=1Ty-a1o29RWSQiO1zTLym6XH4dJvUjpTO
I don't understand why I would get those characters in the data.txt file that I write to.
NOTE: occasionally, instead of seeing EOT1024, I even get EOT21, EOT1016, and other seemingly random characters.
You're literally writing the integer bytes_read to the file:
file << bytes_read << buf;
There's your "1024" (on the occasions that 1024 bytes were read).
Don't do that.
Furthermore, it looks like you're assuming buf is null-terminated. Instead, stream the first bytes_read of buf; that's why you have that integer.
So:
file.write(&buf[0], bytes_read);
Consult the documentation:
A normal read retrieves the specified dwNumberOfBytesToRead for each call to InternetReadFile until the end of the file is reached. To ensure all data is retrieved, an application must continue to call the InternetReadFile function until the function returns TRUE and the lpdwNumberOfBytesRead parameter equals zero.

save recursion output to text file

I am trying to recursively list the files in a directory. However when I save the output to a text file, it works, but the file contents keep being reset. So the file size will be 2Kb, and then it is reset to 1Kb, 30Kb reset to 1Kb, and so on. The code is not saving all the output to the text file and only some of the last lines are saved to output.txt.
#include "stdafx.h"
#include <Windows.h>
#include <iostream>
#include <Psapi.h>
#include <fstream>
using namespace std;
void listDir(wchar_t * szCurrentDirectory);
int main()
{
// return current directory where app run
DWORD nBufferLength = MAX_PATH;
wchar_t szCurrentDirectory[MAX_PATH];
GetCurrentDirectory(nBufferLength, szCurrentDirectory);
listDir(szCurrentDirectory);
system("pause");
return 0;
}
void listDir(wchar_t * szCurrentDirectory)
{
wchar_t addPath[MAX_PATH] = L"\\*";
WIN32_FIND_DATA FindFileData;
wchar_t buf[MAX_PATH];
swprintf(buf, MAX_PATH,L"%s%s", szCurrentDirectory, addPath);
HANDLE hFind;
hFind = FindFirstFile(buf, &FindFileData);
wofstream myfile("c:/output.txt");
if (myfile.is_open())
{
if (hFind != INVALID_HANDLE_VALUE)
{
do
{
// Check if is a folder or not.
if (FindFileData.dwFileAttributes != FILE_ATTRIBUTE_REPARSE_POINT)
{
// Ignore current folder and parent folder.
if (wcscmp(FindFileData.cFileName, L".") && wcscmp(FindFileData.cFileName, L"..") != 0)
{
if (wcscmp(FindFileData.cFileName, L"$RECYCLE.BIN") != 0)
{
// return current directory where app run
wchar_t filepath[10000];
// Append slash to current directory.
swprintf(filepath, 10000, L"%s%s%s", szCurrentDirectory, L"\\", FindFileData.cFileName);
// Output the file.
myfile << filepath << endl;
if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
// Recursive
listDir(filepath);
} // if directory
} // if not recycle bin
} // if not . or ..
} if not reparse point
} while (FindNextFile(hFind, &FindFileData) != 0);
FindClose(hFind);
myfile.close();
}
}
}
try to run the app in c: drive and look the output in output.txt. the output keep reset.
Pass the open file as a parameter instead.
Change
void listDir(wchar_t * szCurrentDirectory)
to
void listDir(wofstream & myfile,wchar_t * szCurrentDirectory)
then remove the file opening code from listDir().
Delete this line:
wofstream myfile("c:/output.txt");
And then call it in main() like this:
wofstream myfile("c:/output.txt");
listDir(myfile,szCurrentDirectory);
And finally in listDir() change
listDir(filepath);
to
listDir(myfile,filepath);
The right answer is definitely to open the file once (in the main program), and then pass the stream into into the listdir function.
However ... there is an alternative. It is not appropriate in this case, it might be in similar cases. You can open the file in append mode, so the contents is never overwritten. You just need to change the line where you open the file to:
std::wofstream myfile("c:/output.txt", std::ios_base::app);
The output will be written to the end of the file, preserving the existing contents.
Open the file in main and pass the handle as a second parameter to the listDir function.
Don't open it in listDir

C++ using 7zip.dll

I'm developing an app which will need to work with different types of archives. As many of the archive types as possible is good. I have choosen a 7zip.dll as an engine of archive-worker. But there is a problem, does anyone knows how to uncompress a file from archive to memory buffer? As I see, 7zip.dll supports only uncompressing to hard disk. Also, it would be nice to load archive from memory buffer. Has anyone tried to do something like that?
Not sure if I completely understand your needs (for example, don't you need the decompressed file on disk?).
I was looking at LZMA SDK 9.20 and its lzma.txt readme file, and there are plenty of hints that decompression to memory is possible - you may just need to use the C API rather than the C++ interface. Check out, for example, the section called Single-call Decompressing:
When to use: RAM->RAM decompressing
Compile files: LzmaDec.h + LzmaDec.c + Types.h
Compile defines: no defines
Memory Requirements:
- Input buffer: compressed size
- Output buffer: uncompressed size
- LZMA Internal Structures: state_size (16 KB for default settings)
Also, there is this function:
SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen,
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
You can utilize these by memory-mapping the archive file. To the best of my knowledge, if your process creates a memory-mapped file with exclusive access (so no other process can access it) and does no explicit flushing, all changes to the file will be kept in memory until the mapping is destroyed or the file closed. Alternatively, you could just load the archive contents in memory.
For the sake of completeness, I hacked together several examples into a demo of using memory mapping in Windows.
#include <stdio.h>
#include <time.h>
#include <Windows.h>
#include <WinNT.h>
// This demo will limit the file to 4KiB
#define FILE_SIZE_MAX_LOWER_DW 4096
#define FILE_SIZE_MAX_UPPER_DW 0
#define MAP_OFFSET_LOWER_DW 0
#define MAP_OFFSET_UPPER_DW 0
#define TEST_ITERATIONS 1000
#define INT16_SIZE 2
typedef short int int16;
// NOTE: This will not work for Windows less than XP or 2003 Server!
int main()
{
HANDLE hFile, hFileMapping;
PBYTE mapViewStartAddress;
// Note: with no explicit security attributes, the process needs to have
// the necessary rights (e.g. read, write) to this location.
LPCSTR path = "C:\\Users\\mcmlxxxvi\\Desktop\\test.dat";
// First, open a file handle.
hFile = CreateFile(path,
GENERIC_READ | GENERIC_WRITE, // The file is created with Read/Write permissions
FILE_SHARE_READ, // Set this to 0 for exclusive access
NULL, // Optional security attributes
CREATE_ALWAYS, // File is created if not found, overwritten otherwise
FILE_ATTRIBUTE_TEMPORARY, // This affects the caching behaviour
0); // Attributes template, can be left NULL
if ((hFile) == INVALID_HANDLE_VALUE)
{
fprintf(stderr, "Unable to open file");
return 1;
}
// Then, create a memory mapping for the opened file.
hFileMapping = CreateFileMapping(hFile, // Handle for an opened file
NULL, // Optional security attributes
PAGE_READWRITE, // File can be mapped for Read/Write access
FILE_SIZE_MAX_UPPER_DW, // Maximum file size split in DWORDs.
FILE_SIZE_MAX_LOWER_DW, // NOTE: I may have these two mixed up!
NULL); // Optional name
if (hFileMapping == 0)
{
CloseHandle(hFile);
fprintf(stderr, "Unable to open file for mapping.");
return 1;
}
// Next, map a view (a continuous portion of the file) to a memory region
// The view must start and end at an offset that is a multiple of
// the allocation granularity (roughly speaking, the machine page size).
mapViewStartAddress = (PBYTE)MapViewOfFile(hFileMapping, // Handle to a memory-mapped file
FILE_MAP_READ | FILE_MAP_WRITE, // Maps the view for Read/Write access
MAP_OFFSET_UPPER_DW, // Offset in the file from which
MAP_OFFSET_LOWER_DW, // the view starts, split in DWORDs.
FILE_SIZE_MAX_LOWER_DW); // Size of the view (here, entire file)
if (mapViewStartAddress == 0)
{
CloseHandle(hFileMapping);
CloseHandle(hFile);
fprintf(stderr, "Couldn't map a view of the file.");
return 1;
}
// This is where actual business stuff belongs.
// This example application does iterations of reading and writing
// random numbers for the entire length of the file.
int16 value;
errno_t result = 0;
srand((int)time(NULL));
for (int i = 0; i < TEST_ITERATIONS; i++)
{
// Write
for (int j = 0; j < FILE_SIZE_MAX_LOWER_DW / INT16_SIZE; j++)
{
value = rand();
result = memcpy_s(mapViewStartAddress + j * INT16_SIZE, INT16_SIZE, &value, INT16_SIZE);
if (result != 0)
{
CloseHandle(hFileMapping);
CloseHandle(hFile);
fprintf(stderr, "File write error during iteration #%d, error %d", i, GetLastError());
return 1;
}
}
// Read
SetFilePointer(hFileMapping, 0, 0, FILE_BEGIN);
for (int j = 0; j < FILE_SIZE_MAX_LOWER_DW / sizeof(int); j++)
{
result = memcpy_s(&value, INT16_SIZE, mapViewStartAddress + j * INT16_SIZE, INT16_SIZE);
if (result != 0)
{
CloseHandle(hFileMapping);
CloseHandle(hFile);
fprintf(stderr, "File read error during iteration #%d, error %d", i, GetLastError());
return 1;
}
}
}
// End business stuff
CloseHandle(hFileMapping);
CloseHandle(hFile);
return 0;
}

Why is RemoveDirectory function not deleting the top most folder?

refer: codeguru.com/forum/showthread.php?t=239271
When using the function below to delete folders, all folders, subfolders and files are getting deleted except for the top most folder. Say for the path c:\folder1\folder2 every thing under folder2 is deleted except for folder2.
BOOL DeleteDirectory(const TCHAR* sPath)
{
HANDLE hFind; // file handle
WIN32_FIND_DATA FindFileData;
TCHAR DirPath[MAX_PATH];
TCHAR FileName[MAX_PATH];
_tcscpy(DirPath,sPath);
_tcscat(DirPath,_T("\\"));
_tcscpy(FileName,sPath);
_tcscat(FileName,_T("\\*")); // searching all files
int nRet = 0;
hFind = FindFirstFile(FileName, &FindFileData); // find the first file
if( hFind != INVALID_HANDLE_VALUE )
{
do
{
if( IsDots(FindFileData.cFileName) )
continue; //if not directory continue
_tcscpy(FileName + _tcslen(DirPath), FindFileData.cFileName);
if((FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
// we have found a directory, recurse
if( !DeleteDirectory(FileName) )
break; // directory couldn't be deleted
}
else
{
if(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
_wchmod(FileName, _S_IWRITE); // change read-only file mode
if( !DeleteFile(FileName) )
break; // file couldn't be deleted
}
}while( FindNextFile(hFind, &FindFileData) );
nRet = FindClose(hFind); // closing file handle
}
return RemoveDirectory(sPath); // remove the empty (maybe not) directory and returns zero when RemoveDirectory function fails
}
Any help in finding the issue is appreciated.
During debugging I noticed that the FindClose function was successfully closing the file handle but GetLastError was returning 32 ("The process cannot access the file because it is being used by another process") However I have no clue after trying with process explorer.
Whilst you can delete a directory this way, it's simpler to let the system do it for you by calling SHFileOperation passing FO_DELETE. Remember that you must double null-terminate the string you pass to this API.
I believe you have to close the file handle before the recursive call. Which means after exiting the recursive call you must again set your your file handle to something appropriate.
SHFileOperation may be a better solution; I am just answering the OP's question of why their code wasn't working as intended.
Refer:http://www.codeguru.com/forum/archive/index.php/t-337897.html
Given below is the code to delete directory using SHFileOperation
bool DeleteDirectory(LPCTSTR lpszDir, bool noRecycleBin = true)
{
int len = _tcslen(lpszDir);
TCHAR* pszFrom = new TCHAR[len+4]; //4 to handle wide char
//_tcscpy(pszFrom, lpszDir); //todo:remove warning//;//convet wchar to char*
wcscpy_s (pszFrom, len+2, lpszDir);
pszFrom[len] = 0;
pszFrom[len+1] = 0;
SHFILEOPSTRUCT fileop;
fileop.hwnd = NULL; // no status display
fileop.wFunc = FO_DELETE; // delete operation
fileop.pFrom = pszFrom; // source file name as double null terminated string
fileop.pTo = NULL; // no destination needed
fileop.fFlags = FOF_NOCONFIRMATION|FOF_SILENT; // do not prompt the user
if(!noRecycleBin)
fileop.fFlags |= FOF_ALLOWUNDO;
fileop.fAnyOperationsAborted = FALSE;
fileop.lpszProgressTitle = NULL;
fileop.hNameMappings = NULL;
int ret = SHFileOperation(&fileop); //SHFileOperation returns zero if successful; otherwise nonzero
delete [] pszFrom;
return (0 == ret);
}

Problems with Visual C++: Reading all files in a directory

I'm trying to read all files in a directory. I have the following code:
void scanDirectory(char* dir)
{
WIN32_FIND_DATA FindFileData;
HANDLE hFind = INVALID_HANDLE_VALUE;
char DirSpec[MAX_PATH]; // directory specification
strcpy(DirSpec, dir);
strcat(DirSpec, "\\*");
hFind = FindFirstFile(DirSpec, &FindFileData);
int i = 0;
do {
i++;
printf("%d \n", i);
if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
printf(" %s <DIR>\n", FindFileData.cFileName);
}
else
{
printf("File %s\n", FindFileData.cFileName);
}
} while(!FindNextFile(hFind, &FindFileData));
FindClose(hFind);
}
The problem is that when I execute the code it results in an infinite loop. Also the output characters are strange, like "File ".
I think you are not using chars and wide chars in a consequent way. You should either use functions with wide char and wchar_t type or vice versa. (But it was a compile error for me so it may depend on some kind of project settings as well.)
And your exit condition in the while loop is also wrong it should test for FindNextFile and not !FindNextFile. The infinite loop may be because of this condition as if it doesn't find any files it will run forever.
Also you should test for the return value of FindFirstFile and not go into the loop if it doesn't find any files.
You are calling !FindNextFile instead of FindNextFile, also you are not checking why
the FindNextFile fails, so you can't be sure if all the files were processed.
Use something like this.
WIN32_FIND_DATA stFindData;
HANDLE hFind = FindFirstFile(cSearchPattern, &stFindData);
if(hFind != INVALID_HANDLE_VALUE)
{
do
{
// Process File
}
while (FindNextFile(hFind, &stFindData) != 0);
DWORD dwError = GetLastError();
if (dwError != ERROR_NO_MORE_FILES)
{
// Not All Files processed, deal with Error
}
FindClose(hFind);
}
Can't you just use .Net like below:
System.IO.DirectoryInfo dir = new System.IO.DirectoryInfo(Path);
System.IO.FileInfo[] files = dir.GetFiles();
foreach (System.IO.FileInfo file in files)
{
// Do whatever you need with the file info...
string filename = file.Name;
string fullFilename = file.FullName;
}
This is a c# example but you can use for each in C++ the same. Hope this helps.