Understanding Asynchronous / Overlapped IO - c++

I am learning about Asynchronous / Overlapped IO in windows. I have written the following code, but it doesn't compile. Where is my mistake? I don't know why we need to call something as FileIoCompletionRoutine and how should I define it?
#include <windows.h>
#include <iostream>
VOID WINAPI FileIOCompletionRoutine(DWORD, DWORD, LPOVERLAPPED);
HANDLE g_HandleEvent;
wchar_t string_data[] = L"Garbage data is absloute thing";
int main(int argc, char* argv[])
{
g_HandleEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
auto file_name = L"Cayot.txt";
auto handle_file = CreateFile(file_name, GENERIC_WRITE, FILE_SHARE_WRITE, 0, CREATE_ALWAYS, FILE_FLAG_OVERLAPPED, 0);
if (handle_file == INVALID_HANDLE_VALUE)
{
std::cout << "File creation is failed." << std::endl;
return -1;
}
OVERLAPPED overlapped_instance = { 0 };
overlapped_instance.hEvent = g_HandleEvent;
WriteFileEx(handle_file, string_data, sizeof(string_data), &overlapped_instance, FileIOCompletionRoutine);
SleepEx(INFINITE, TRUE);
return 0;
}
Error compiler:
error LNK2001: unresolved external symbol "void __stdcall
FileIOCompletionRoutine(unsigned long,unsigned long,struct _OVERLAPPED
*)" (?FileIOCompletionRoutine##YGXKKPAU_OVERLAPPED###Z)

You have merely forward-declared the FileIOCompletionRoutine() function, which satisfies the compiler, but you have not actually implemented the function, so the linker fails to find it.
#include <windows.h>
#include <iostream>
VOID WINAPI FileIOCompletionRoutine(DWORD, DWORD, LPOVERLAPPED);
HANDLE g_HandleEvent;
wchar_t string_data[] = L"Garbage data is absloute thing";
int main(int argc, char* argv[])
{
g_HandleEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
auto file_name = L"Cayot.txt";
auto handle_file = CreateFile(file_name, GENERIC_WRITE, FILE_SHARE_WRITE, 0, CREATE_ALWAYS, FILE_FLAG_OVERLAPPED, 0);
if (handle_file == INVALID_HANDLE_VALUE)
{
std::cout << "File creation is failed." << std::endl;
return -1;
}
OVERLAPPED overlapped_instance = { 0 };
overlapped_instance.hEvent = g_HandleEvent;
WriteFileEx(handle_file, string_data, sizeof(string_data), &overlapped_instance, FileIOCompletionRoutine);
SleepEx(INFINITE, TRUE);
return 0;
}
VOID WINAPI FileIOCompletionRoutine(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped)
{
// Do something here...
}

Related

Using file as a mutex with CreateFile()

I've been given a task to create 2 processes. First one opens a file "log.txt" and adds the input given by user to it.
The second process is meant to be a "monitor" of that file. It checks if it exists, gives its size and gives the number of characters entered by user since the start of the second process. I'm using the GetFileSize() function to it so it's not a problem.
I'm slighty confused by the CreateProcess() and CreateFile() functions as I'm not sure how to connect it with one another.
I've read that the CreateFile() function can be used as a mutex by changing its flags. I've come up with something like this:
HANDLE hFile = CreateFile(
"log.txt",
FILE_APPEND_DATA,
FILE_SHARE_WRITE | FILE_SHARE_READ,
0,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
0);
Now I'm not really sure how to connect it to processes and where to start the processes from. And also I have no idea how to check how many characters were given since the start of the second process.
Can someone explain to me when to start those 2 processes and how to connect the CreateFile() function to them?
FILE_SHARE_WRITE | FILE_SHARE_READ will allow other processes to open and share the read and write access. You need to open the file exclusively (with dwShareMode = 0), but this requires process2 to try to open the file exclusively in a loop.
Instead, use CreateMutex to create a mutex, then process1 uses WaitForSingleObject to take up the mutex, do something and then ReleaseMutex, process2 uses WaitForSingleObject waits for released mutex, and then reads the file. (One synchronization is completed)
process 2:
#include <windows.h>
#include <iostream>
int wmain(int argc, wchar_t* argv[])
{
HANDLE hMutex = OpenMutex(MUTEX_ALL_ACCESS, false, L"MyMutex");
DWORD dwWaitResult = WaitForSingleObject(hMutex, INFINITE);
if (dwWaitResult == WAIT_OBJECT_0)
{
HANDLE hFile = CreateFile(L"log.txt", FILE_READ_ATTRIBUTES, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if (hFile == INVALID_HANDLE_VALUE)
{
std::cout << "CreateFile error " << GetLastError() << std::endl;
ReleaseMutex(hMutex);
}
else
{
DWORD size = GetFileSize(hFile, NULL);
std::cout << "File Size: " << size << std::endl;
CloseHandle(hFile);
ReleaseMutex(hMutex);
}
}
return 0;
}
process 1:
#include <windows.h>
#include <iostream>
int wmain(int argc, wchar_t* argv[])
{
HANDLE hMutex = CreateMutex(NULL, false, L"MyMutex");
DWORD dwWaitResult = WaitForSingleObject(hMutex, INFINITE);
if (dwWaitResult == WAIT_OBJECT_0)
{
STARTUPINFO si = { 0 };
si.cb = sizeof(si);
PROCESS_INFORMATION pi = { 0 };
CreateProcess(L"process2.exe",
NULL,
NULL,
NULL,
false,
CREATE_NEW_CONSOLE,
NULL,
NULL,
&si,
&pi);
std::string buffer;
std::cin >> buffer;
HANDLE hFile = CreateFile(L"log.txt", FILE_APPEND_DATA, 0, 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
DWORD written = 0;
WriteFile(hFile, buffer.c_str(), buffer.size(), &written, NULL);
CloseHandle(hFile);
ReleaseMutex(hMutex);
}
return 0;
}
But this is more troublesome, because you need to synchronize the two processes every time.
As #Remy Lebeau said, use ReadDirectoryChangesW in process2:
#include <windows.h>
#include <iostream>
int wmain(int argc, wchar_t* argv[])
{
FILE_NOTIFY_INFORMATION* pInfo = NULL;
HANDLE hFile = CreateFile(L"Directory of log.txt", GENERIC_READ, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, 0);
while (1)
{
DWORD returned = 0;
DWORD dwOffset = 0;
BYTE szBuffer[1024] = { 0 };
ReadDirectoryChangesW(hFile, szBuffer, sizeof(szBuffer), false, FILE_NOTIFY_CHANGE_SIZE, &returned, NULL, NULL);
do
{
pInfo = (FILE_NOTIFY_INFORMATION*)&szBuffer[dwOffset];
if (wcscmp(pInfo->FileName, L"log.txt") == 0)
{
HANDLE hFile = CreateFile(L"path\\log.txt", FILE_APPEND_DATA, 0, 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
DWORD size = GetFileSize(hFile, NULL);
std::cout << "File Size: " << size << std::endl;
CloseHandle(hFile);
}
dwOffset += pInfo->NextEntryOffset;
} while (pInfo->NextEntryOffset != 0);
}
return 0;
}
And process 1 only need to get user input and write to the file:
#include <windows.h>
#include <iostream>
int wmain(int argc, wchar_t* argv[])
{
std::string buffer;
while (1)
{
std::cin >> buffer;
HANDLE hFile = CreateFile(L"log.txt", FILE_APPEND_DATA, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
DWORD written = 0;
WriteFile(hFile, buffer.c_str(), buffer.size(), &written, NULL);
CloseHandle(hFile);
}
return 0;
}
It appears that you want to synchronize these two proccesses so that the second one waits for the first one to complete writing to "log.txt".
For that, you would need to open that file in the first process with exclusive access (no FILE_SHARE_WRITE | FILE_SHARE_READ), and close it when it's done writing.
The second process would try to open that same file, also with exclusive access. CreateFile() would fail with "access denied" error if that file is still in use by the first process. This is an essence of "mutually exclusive" concept of mutex. You would then wait a little and try again.
Contrary to synchronization objects, I am not aware of the way to wait for the file to become available (easily done with WaitForSingleObject for mutex).
So I've managed to make something out of your precious comments. I'm not sure if it is a right way to solve this task. It would be nice if someone could review my code and give me some additional tips.
Here is my code
int main(int argc, char *argv[])
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
ZeroMemory(&pi, sizeof(pi));
si.cb = sizeof(si);
CreateProcess("process2.exe",
NULL,
NULL,
NULL,
false,
CREATE_NEW_CONSOLE,
NULL,
NULL,
&si,
&pi);
std::string buffer;
std::cout << "Enter your text:" << std::endl;
getline(std::cin, buffer);
HANDLE hFile = CreateFile("log.txt", FILE_APPEND_DATA, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
DWORD written = 0;
WriteFile(hFile, buffer.c_str(), buffer.size(), &written, NULL);
hFile = CreateFile("log.txt", FILE_READ_ATTRIBUTES, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if (hFile == INVALID_HANDLE_VALUE)
{
std::cout << "CreateFile error " << GetLastError() << std::endl;
}
else
{
DWORD size = GetFileSize(hFile, NULL);
std::cout << "\nCurrent file size: " << size << std::endl;
CloseHandle(hFile);
}
int stringLenght = 0;
for(int i=0; buffer[i]; i++)
stringLenght++;
std::cout << "\nCharacters given since last startup: " << stringLenght << std::endl;
return 0;
}
I'm not sure if that was the point in this task or should it check the file size and ask user for input in a while loop and if it's possible to do without a mutex.

C++ - Unresolved External in DLL Injector [duplicate]

This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 6 years ago.
I can't really see the reason I am getting this error, I have had a look arround and apparently it's something to do with defining a function that does nothing? I can't really tell what the issue is here unfortunately so any help would be appreciated.
Here is my source code:
main.cpp
#include <Windows.h>
#include <tlhelp32.h>
#include <shlwapi.h>
#include <conio.h>
#include <stdio.h>
#include <iostream>
using namespace std;
#define WIN32_LEAN_AND_MEAN
#define CREATE_THREAD_ACCESS (PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ)
BOOL Inject(DWORD pID, const char * DLL_NAME);
DWORD GetTargetThreadIDFromProcName(const char * ProcName);
using namespace std;
char buf[MAX_PATH];
LPVOID RemoteString, LoadLib;
HANDLE Proc;
DWORD pID;
__int32 main()
{
pID = GetTargetThreadIDFromProcName("Program.exe");
buf[MAX_PATH] = {0};
GetFullPathName("DLL.dll", MAX_PATH, buf, NULL);
if(!Inject(pID, buf)) cout << ("Failed to inject!\n\n\n");
system("pause");
return 0;
}
BOOL Inject(DWORD pID, const char * DLL_NAME)
{
char buf[50] = {0};
if(!pID) return false;
Proc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pID);
if(!Proc) return false;
LoadLib = (LPVOID)GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
RemoteString = (LPVOID)VirtualAllocEx(Proc, NULL, strlen(DLL_NAME), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
WriteProcessMemory(Proc, (LPVOID)RemoteString, DLL_NAME, strlen(DLL_NAME), NULL);
CreateRemoteThread(Proc, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLib, (LPVOID)RemoteString, NULL, NULL);
CloseHandle(Proc);
return true;
}
DWORD GetTargetThreadIDFromProcName(const char * ProcName)
{
PROCESSENTRY32 pe;
HANDLE thSnapShot;
BOOL retval, ProcFound = false;
thSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if(thSnapShot == INVALID_HANDLE_VALUE) return false;
pe.dwSize = sizeof(PROCESSENTRY32);
retval = Process32First(thSnapShot, &pe);
while(retval)
{
if(StrStrI(pe.szExeFile, ProcName)) return pe.th32ProcessID;
retval = Process32Next(thSnapShot, &pe);
}
return 0;
}
The error I am getting is the following:
main.obj
unresolved external symbol __imp__StrStrIA#8 referenced in function "unsigned long __cdecl GetTargetThreadIDFromProcName(char const *)" (?GetTargetThreadIDFromProcName##YAKPBD#Z)
Injector.exe
1 unresolved externals
Any solutions or just some help on understanding why this occurs would be great!
As mentioned in the comments, it looks like you are not linking with shlwapi.lib. You need to do this in order to call StrStrI.

Read tails bytes from a binary file in visual c++

Here is my attempt:
// ConsoleApplication1.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <windows.h>
#include <tlhelp32.h>
#include <tchar.h>
#include <iostream>
#include <string>
// Forward declarations:
void append(LPCTSTR, LPCVOID, DWORD);
void readTail(LPCTSTR, LPVOID, DWORD);
int main()
{
LPCTSTR fn = L"C:/kaiyin/kybig.out";
LPCVOID buf = "eeeee";
append(fn, buf, 5);
LPVOID buf1 = "";
readTail(fn, buf1, 5);
std::cout << (char*) buf1 << std::endl;
printf("hello world\n");
std::string s = "";
std::getline(std::cin, s);
return 0;
}
void append(LPCTSTR filename, LPCVOID buf, DWORD writeSize) {
LARGE_INTEGER size;
size.QuadPart = 0;
HANDLE fh = CreateFile(filename, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
GetFileSizeEx(fh, &size);
SetFilePointerEx(fh, size, NULL, FILE_BEGIN);
WriteFile(fh, buf, writeSize, NULL, NULL);
CloseHandle(fh);
}
void readTail(LPCTSTR filename, LPVOID buf, DWORD readSize) {
LARGE_INTEGER size;
size.QuadPart = 0;
HANDLE fh = CreateFile(filename, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
GetFileSizeEx(fh, &size);
size.QuadPart -= readSize;
SetFilePointerEx(fh, size, NULL, FILE_BEGIN);
ReadFile(fh, buf, readSize, NULL, NULL);
CloseHandle(fh);
}
The append function seems to increase the file size by the correct number (5 bytes), but printing the last 5 byte to in the console doesn't show anything.
What went wrong?
You have not allocated buffer for your result:
LPVOID buf1 = "";
readTail(fn, buf1, 5);
buf1 is only a pointer to empty string, what you want is some buffer where to put your results:
BYTE buf1[10] = { 0 };
readTail(fn, buf1, 5);
Also, you are appending initialy to existing file (due to OPEN_EXISTING),so makesure you have an empty C:/kaiyin/kybig.out file.
Just for the record, here is the modified code according to suggestions from #marcinj :
// ConsoleApplication1.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <windows.h>
#include <tlhelp32.h>
#include <tchar.h>
#include <iostream>
#include <string>
// Forward declarations:
void append(LPCTSTR, LPCVOID, DWORD);
void readTail(LPCTSTR, LPVOID, DWORD);
void truncateTail(LPCTSTR, long);
int main()
{
LPCTSTR fn = L"C:/kaiyin/kybig.out";
char buf[] = "helloWorld";
append(fn, buf, 10);
BYTE buf1[10] = {0};
readTail(fn, buf1, 5);
std::cout << (char*) buf1 << std::endl;
truncateTail(fn, 5);
for (int i = 0; i < 10; i++) {
buf1[i] = 0;
}
readTail(fn, buf1, 5);
std::cout << (char*) buf1 << std::endl;
printf("End of program\n");
std::string s = "";
std::getline(std::cin, s);
return 0;
}
void append(LPCTSTR filename, LPCVOID buf, DWORD writeSize) {
LARGE_INTEGER size;
size.QuadPart = 0;
HANDLE fh = CreateFile(filename, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
GetFileSizeEx(fh, &size);
SetFilePointerEx(fh, size, NULL, FILE_BEGIN);
WriteFile(fh, buf, writeSize, NULL, NULL);
CloseHandle(fh);
}
void readTail(LPCTSTR filename, LPVOID buf, DWORD readSize) {
LARGE_INTEGER size;
size.QuadPart = 0;
HANDLE fh = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
GetFileSizeEx(fh, &size);
size.QuadPart -= readSize;
SetFilePointerEx(fh, size, NULL, FILE_BEGIN);
ReadFile(fh, buf, readSize, NULL, NULL);
CloseHandle(fh);
}
void truncateTail(LPCTSTR filename, long truncateSize) {
LARGE_INTEGER size;
size.QuadPart = 0;
HANDLE fh = CreateFile(filename, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (fh == INVALID_HANDLE_VALUE) {
std::cerr << GetLastError();
return;
}
GetFileSizeEx(fh, &size);
size.QuadPart -= truncateSize;
SetFilePointerEx(fh, size, NULL, FILE_BEGIN);
if (SetEndOfFile(fh) == 0) {
std::cerr << GetLastError();
return;
}
CloseHandle(fh);
}

Link to unresolved symbol while injecting dll [duplicate]

This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 9 years ago.
I'm trying to inject a dll into a process, but after compiling I get
TestMain.obj : error LNK2019: link to unresolved external symbol __imp__StrStrIA#8 in function "unsigned long __cdecl GetPid(char *)" (?GetPid##YAKPAD#Z). After years of trying find my problem in my code and trying to google it , and meditating with Shaolin monks, I failed.
This is my code:
#include <windows.h>
#include <stdio.h>
#include <tlhelp32.h>
#include <shlwapi.h>
#include <iostream>
#include <conio.h>
using namespace std;
#define CREATE_THREAD_ACCESS (PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ)
bool IsWindowsNT()
{
// check current version of Windows
DWORD version = GetVersion();
// parse return
DWORD majorVersion = (DWORD)(LOBYTE(LOWORD(version)));
DWORD minorVersion = (DWORD)(HIBYTE(LOWORD(version)));
return (version < 0x80000000);
}
BOOL InjectDLL(DWORD ProcessID,char* DLL_NAME)
{
HANDLE Proc;
char buf[50]={0};
LPVOID RemoteString, LoadLibAddy;
if(!ProcessID)
return false;
Proc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcessID);
LoadLibAddy = (LPVOID)GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
RemoteString = (LPVOID)VirtualAllocEx(Proc, NULL, strlen(DLL_NAME), MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
WriteProcessMemory(Proc, (LPVOID)RemoteString, DLL_NAME,strlen(DLL_NAME), NULL);
CreateRemoteThread(Proc, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibAddy, (LPVOID)RemoteString, NULL, NULL);
CloseHandle(Proc);
return true;
}
DWORD GetPid(char *procName)
{
PROCESSENTRY32 pe;
HANDLE thSnapshot;
BOOL retval, ProcFound = false;
thSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if(thSnapshot == INVALID_HANDLE_VALUE)
{
cout << "Error: unable to create toolhelp snapshot" << endl;
// MessageBox(NULL, "Error: unable to create toolhelp snapshot", "Loader", NULL);
return false;
}
pe.dwSize = sizeof(PROCESSENTRY32);
retval = Process32First(thSnapshot, &pe);
while(retval)
{
if(StrStrI(pe.szExeFile, procName) )
{
ProcFound = true;
break;
}
retval = Process32Next(thSnapshot,&pe);
pe.dwSize = sizeof(PROCESSENTRY32);
}
if (!ProcFound) return 0;
return pe.th32ProcessID;
}
BOOL LoadDll(char *procName, char *dllName)
{
DWORD ProcID = 0;
ProcID = GetPid(procName);
if(!(InjectDLL(ProcID, dllName)))
{
cout << "Process located, but injection failed" << endl;
_getch();
exit(1);
} // MessageBox(NULL, "Process located, but injection failed", "Loader", NULL);
else
{
cout << " Injection successfull!" << endl;
_getch();
}
return true;
}
int main()
{
char* ProcName = "notepad.exe";
char* DllName = "Main.dll";
LoadDll( ProcName, DllName );
return 0;
}
And my dll:
#include <Windows.h>
DWORD APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved )
{
switch( ul_reason_for_call )
{
case DLL_PROCESS_ATTACH:
// hInstance = (HINSTANCE) hModule;
MessageBox( 0, "HOHOHOOHOHOHO!", "DLLHOOK", MB_OK );
return TRUE;
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
So the main problem is that error.Thanks for answering.
Try adding
#pragma comment (lib, 'Shlwapi.lib')
below your other #includes

ask : memmove() and memcpy() on QT (c++)

simple question, I have problem with memmove() and memcpy() when i'm using it. I really don't understand what wrong with my code. by the way i use QT.
HANDLE hFile;
HANDLE hMapFile;
HANDLE hMapView;
hFile = CreateFileW((const wchar_t*) objPath.constData(), GENERIC_READ , 0, NULL, OPEN_EXISTING, 0, NULL);
if (hFile != INVALID_HANDLE_VALUE){
hMapFile = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if (hMapFile != INVALID_HANDLE_VALUE){
hMapView = MapViewOfFile(hMapFile, GENERIC_READ, 0, 0,0);
if (hMapView != INVALID_HANDLE_VALUE){
uint DefineWord;
memmove((void *) &DefineWord, hMapView,2); // <- always error right here
qDebug()<<DefineWord;
}
}
}
hMapView is not a pointer. memmove requires two pointers. Fix this by declaring hMapView properly. It should be a LPVOID.
MapViewOfFile returns a pointer, or NULL (0) when there is an error, not INVALID_HANDLE_VALUE (-1).
Edit: There was a lot of other problems with your code:
QString::constData() returns QChar*, not wchar_t*, you have to use QString::utf16() instead.
If CreateFileMappingW fails it returns NULL, not INVALID_HANDLE_VALUE.
MapViewOfFile access parameter is FILE_MAP_READ, not GENERIC_READ.
uint is often bigger than 2 bytes, so you should initialize the variable to 0 before memmove if you only read 2 bytes.
Here is a minimal code that should work (only tested on wineg++/wine):
#include <windows.h>
#include <QtCore/QString>
#include <QtCore/QDebug>
#include <QtCore/QTextStream>
int main(int argc, char const *argv[])
{
if (argc < 2) {
QTextStream(stdout) << "Usage :" << argv[0] << " filename" << endl;
return 1;
}
QString objPath(argv[1]);
// Qt source uses C-Style cast from utf16() to (wchar_t*),
// so it should be safe
HANDLE hFile = CreateFileW((const wchar_t *) objPath.utf16(), GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
qDebug() << qt_error_string();
} else {
HANDLE hMapFile = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if (!hMapFile) {
qDebug() << qt_error_string();
} else {
void *pMapView = MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0);
if (!pMapView) {
qDebug() << qt_error_string();
} else {
uint DefineWord = 0;
memmove((void *) &DefineWord, pMapView, 2);
qDebug() << DefineWord;
}
CloseHandle(hMapFile);
}
CloseHandle(hFile);
}
return 0;
}
PS: QString qt_error_string(int errorCode = -1) is an apparently undocumented Qt function that returns the error string of the last error (from the error code returned from GetLastError() or errno).
If you are using Qt, you can map a file to memory with QFile::map().
To do what your initial code was supposed to do, you only had to add 2 lines to the code sample you found (plus the error checking):
QFile file("foo");
if(!file.open(QFile::ReadOnly)) {
qDebug() << file.errorString();
} else {
uchar *memory = file.map(0, file.size());
if (!memory) {
qDebug() << file.errorString();
} else {
uint DefineWord = 0;
memmove(&DefineWord, memory, 2);
file.unmap();
}
}
by the way i use QT.
You aren't really using it in your example.
Qt has QFile::map method which can (and in my opinion should) be used instead of platform-specific MapViewOfFile.