Get file size using GetFileSize reports a segv on a valid file - c++

I have an application that scans file and collects meta data about a file. One function is to get the file size of a file. To do so, I am using the winapi function GetFileSizeEx(Handle, PLARGE_INTEGER). The parameters require a file HANDLE and a reference to a PLARGE_INTEGER aka (*LARGE_INTEGER).
To get a file HANDLE in Qt, it is suggested here to get the file handle using QFile::handle() and pass the result into _get_osfhandle(int) and cast it as a HANDLE.
HANDLE handle = (HANDLE) _get_osfhandle(file.handle()).
Using this handle, pass it with a PLARGE_INTEGER variable into the [GetFileSizeEx(Handle, PLARGE_INTEGER)] which returns 0 if the operation failed or != 0 if the operation succeeded.
GetFileSize(HANDLE, PLARGE_INTEGER) returns with:
0 (or failure), one can use GetLastError in accordance with this list of error codes (as a start, there are many more) to help.
any non-zero value indicating success
Problem:
Using this approach, I attempt the same on a valid file, however I get a SEGV when calling GetFileSizeEx(Handle, PLARGE_INTEGER). I attempted this before and after calling QFile::open(QIODevice::ReadOnly) as a test, however it fails non the less.
int localHandle = file.handle(); // handle returns -1 as expected
bool localOpen = file.open(QIODevice::ReadOnly);
if (localOpen) {
int localFileHandle = file.handle(); // returns a valid >0 handle value
HANDLE handle = (HANDLE) _get_osfhandle(localFileHandle); // returns a valid > 0 handle value
PLARGE_INTEGER l = PLARGE_INTEGER(); // representation value of 0
BOOL b = GetFileSizeEx(handle, l); // segv
if (!b) {
qDebug() << getLastErrorMsg();
return QFileInfo(filepath).size();
}
return l->QuadPart;
}
Did I do something wrong?
See attached screenshot
MVCE
#include <QCoreApplication>
#include "windows.h"
#include <comdef.h>
#include <QFile>
#include <QDebug>
#include <QString>
#include <QFileInfo>
#include <windows.h>
#include <fileapi.h>
#include <io.h>
static QString toString(HRESULT hr)
{
_com_error err{hr};
const TCHAR* lastError = err.ErrorMessage();
return QStringLiteral("Error 0x%1: %2").arg((quint32)hr, 8, 16, QLatin1Char('0'))
.arg(lastError);
}
static QString getLastErrorMsg()
{
DWORD lastError = GetLastError();
QString s = toString(HRESULT_FROM_WIN32(lastError));
return s;
}
static qint64 getWinAPIFileSize(QString filepath)
{
QFile file(filepath);
if (!file.exists()) {
return 0;
}
int localHandle = file.handle(); // handle returns -1 as expected
bool localOpen = file.open(QIODevice::ReadOnly);
if (localOpen) {
int localFileHandle = file.handle(); // returns a valid >0 handle value
HANDLE handle = (HANDLE) _get_osfhandle(localFileHandle); // returns a valid > 0 handle value
PLARGE_INTEGER l = PLARGE_INTEGER(); // representation value of 0
BOOL b = GetFileSizeEx(handle, l); // segv
if (!b) {
qDebug() << getLastErrorMsg();
return QFileInfo(filepath).size();
}
return l->QuadPart;
}
return QFileInfo(filepath).size();
}
int main(int argc, char* argv[])
{
QCoreApplication a(argc, argv);
QString src = QString("C:/Users/CybeX/.bash_history"); // change path to a valid file on your PC
qint64 size = getWinAPIFileSize(src);
qDebug() << size;
return a.exec();
}

The type PLARGE_INTEGER is an alias for "pointer to LARGE_INTEGER". And PLARGE_INTEGER() is a default value initialization for the type "pointer to LARGE_INTEGER". And for all pointers such an initialization is a null pointer.
That means the definition
PLARGE_INTEGER l = PLARGE_INTEGER();
is equivalent to
LARGE_INTEGER* l = nullptr;
Which means you pass a null-pointer to GetFileSizeEx.
You need to create an actual LARGE_INTEGER object, and pass a pointer to that object using the address-of operator &:
LARGE_INTEGER l;
GetFileSizeEx(handle, &l); // Pass pointer to the variable l

The problem is that you are mishandling the PLARGE_INTEGER. You are creating a PLARGE_INTEGER (aka LARGE_INTEGER*) pointer that doesn't actually point anywhere, which is why GetFileSizeEx() crashes when it tries to write out the file size.
You need to allocate a LARGE_INTEGER (not a PLARGE_INTEGER) and then pass its memory address to GetFileSizeEx(), eg:
static qint64 getWinAPIFileSize(QString filepath)
{
QFile file(filepath);
if (file.open(QIODevice::ReadOnly)) {
int localFileHandle = file.handle();
HANDLE handle = (HANDLE) _get_osfhandle(localFileHandle);
LARGE_INTEGER l;
if (GetFileSizeEx(handle, &l)) {
return l.QuadPart;
}
qDebug() << getLastErrorMsg();
}
return QFileInfo(file).size();
}
That being said, there is really no point in using GetFileSizeEx() manually at all in this situation. Depending on its implementation (which I can't check), QFileInfo.size() will either open the file for you, or it will simply query the file's size directly from the filesystem's metadata and not actually open the file at all:
static qint64 getWinAPIFileSize(QString filepath)
{
return QFileInfo(filepath).size();
}

Related

What's the actual size of PSAPI_WORKING_SET_INFORMATION buffer used in QueryWorkingSet function of PSAPI.h

I'd like to use the function QueryWorkingSet available in PSAPI, but I'm having trouble to actually define the size of the buffer pv. Here is the code :
#include <Windows.h>
#include <Psapi.h>
#include <iostream>
void testQueryWorkingSet()
{
unsigned int counter;
HANDLE thisProcess = GetCurrentProcess();
SYSTEM_INFO si;
PSAPI_WORKING_SET_INFORMATION wsi, wsi2;
GetSystemInfo(&si);
QueryWorkingSet(thisProcess, &wsi, sizeof(wsi));
DWORD wsi2_buffer_size = (wsi.NumberOfEntries) * sizeof(PSAPI_WORKING_SET_BLOCK);
if (!QueryWorkingSet(thisProcess, &wsi2, wsi2_buffer_size))
{
std::cout << "ERROR CODE : " << GetLastError() << std::endl;
abort();
}
}
int main(int argc, char * argv[])
{
testQueryWorkingSet();
int* test = new int[1000000];
testQueryWorkingSet();
}
I keep ending up with abort() being called and either an error code 24 or 998 during the first call to testQueryWorkingSet(). that I interpret respectively as : wsi2_buffer_size is too low and wsi2_buffer_size is too big.
Now I have no idea of the value this variable should take, I tried :
counting everything including the NumberOfEntries field, that is DWORD wsi2_buffer_size = sizeof(wsi.NumberOfEntries) + wsi.NumberOfEntries * sizeof(PSAPI_WORKING_SET_BLOCK); => error 998;
counting only the number of entries, that is the code given above => error 998;
the size of the variable wsi2, that is DWORD wsi2_buffer_size = sizeof(wsi2); => error 24;
There has to be something I do not understand in the way we're supposed to use this function but I can't find what. I tried to adapt the code given there, that is :
#include <Windows.h>
#include <Psapi.h>
#include <iostream>
void testQueryWorkingSet()
{
unsigned int counter;
HANDLE thisProcess = GetCurrentProcess();
SYSTEM_INFO si;
PSAPI_WORKING_SET_INFORMATION wsi_1, * wsi;
DWORD wsi_size;
GetSystemInfo(&si);
wsi_1.NumberOfEntries = 0;
QueryWorkingSet(thisProcess, (LPVOID)&wsi_1, sizeof(wsi));
#if !defined(_WIN64)
wsi_1.NumberOfEntries--;
#endif
wsi_size = sizeof(PSAPI_WORKING_SET_INFORMATION)
+ sizeof(PSAPI_WORKING_SET_BLOCK) * wsi_1.NumberOfEntries;
wsi = (PSAPI_WORKING_SET_INFORMATION*)HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY, wsi_size);
if (!QueryWorkingSet(thisProcess, (LPVOID)wsi, wsi_size)) {
printf("# Second QueryWorkingSet failed: %lu\n"
, GetLastError());
abort();
}
}
int main(int argc, char * argv[])
{
testQueryWorkingSet();
int* test = new int[1000000];
testQueryWorkingSet();
}
This code is working for only 1 call to testQueryWorkingSet(), the second one is aborting with error code 24. Here are the questions in brief :
How would you use QueryWorkingSet in a function that you could call multiple times successively?
What is representing the value of the parameter cb of the documentation given a PSAPI_WORKING_SET_INFORMATION?
Both examples are completely ignoring the return value and error code of the 1st call of QueryWorkingSet(). You are doing error handling only on the 2nd call.
Your 1st example fails because you are not taking into account the entire size of the PSAPI_WORKING_SET_INFORMATION when calculating wsi2_buffer_size for the 2nd call of QueryWorkingSet(). Even if the 1st call were successful, you are not allocating any additional memory for the 2nd call to fill in, if the NumberOfEntries returned is > 1.
Your 2nd example is passing in the wrong buffer size value to the cb parameter of the 1st call of QueryWorkingSet(). You are passing in just the size of a single pointer, not the size of the entire PSAPI_WORKING_SET_INFORMATION. Error 24 is ERROR_BAD_LENGTH. You need to use sizeof(wsi_1) instead of sizeof(wsi).
I would suggest calling QueryWorkingSet() in a loop, in case the working set actually changes in between the call to query its size and the call to get its data.
Also, be sure you free the memory you allocate when you are done using it.
With that said, try something more life this:
void testQueryWorkingSet()
{
HANDLE thisProcess = GetCurrentProcess();
PSAPI_WORKING_SET_INFORMATION *wsi, *wsi_new;
DWORD wsi_size;
ULONG_PTR count = 1; // or whatever initial size you want...
do
{
wsi_size = offsetof(PSAPI_WORKING_SET_INFORMATION, WorkingSetInfo[count]);
wsi = (PSAPI_WORKING_SET_INFORMATION*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, wsi_size);
if (!wsi)
{
printf("HeapAlloc failed: %lu\n", GetLastError());
abort();
}
if (QueryWorkingSet(thisProcess, wsi, wsi_size))
break;
if (GetLastError() != ERROR_BAD_LENGTH)
{
printf("QueryWorkingSet failed: %lu\n", GetLastError());
HeapFree(GetProcessHeap(), 0, wsi);
abort();
}
count = wsi->NumberOfEntries;
HeapFree(GetProcessHeap(), 0, wsi);
}
while (true);
// use wsi as needed...
HeapFree(GetProcessHeap(), 0, wsi);
}

Stackwalk get Function Name, Line number and File Name, in debug

Quick summary
In a nut shell i wish to access the debug information regarding the stack, preferably for passing information to Logger.
I wish for the information to tell me the Function Name, Line Number and File Name.
I've got the symbols and i'm attempting to access the junk values in them and turn them in to English. However nothing seems to work.
I have commented the code for people to read and see if they can help me effectively walk the stack to pull the information out i need.
So far i can point out SymGetModuleBase() does not return a positive number only 0, according to MSDN it fails if returns 0. Which is correct as it returns a memory address.
SymGetSymFromAddr() fails to return true, which i'm assuming gets the name of the stack frame/function
SymGetLineFromAddr() goes on to fail as well and doesn't return the line number location in the file and also doesn't gather the file path.
I believe this is due to the process parameter being invalid. I will elaborate below.
Attempts to locate and fix the problem
I have read the MSDN documentation repeatedly and feel like i'm banging my head off the wall, i've done pretty much what it said and i feel like it's just not working.
However i have noticed SymInitialize() should be called prior to attempting this, which i do call. This changed the GetLastError() value from 6 ERROR_INVALID_HANDLE to 0 ERROR_SUCCESS. Yet SymGetModuleBase() still returns 0 no matter if SymInitialize() although GetLastError() reports different error codes depending on SymInitialize() use. It should return a valid virtual memory address this is where i think the main problem lies in the code.
HANDLE process = ::GetCurrentProcess(); this line in the code below returns 0xffffffffffffffff very suspect if you ask me. This should return a pseudo virtual memory address but it to me anyway looks like a false result. This happens every time i run the program which leads me to think ::GetCurrentProcess() this is either got a bug, or doesn't work somehow. According to MSDN this is the correct a up to date way of getting the current process and i don't know how to get a valid HANDLE to a the process another way. So i can't pass the first parameter in SymGetModuleBase() the correct process, although i maybe wrong.
Full code for the function
void Logger::WriteStackFrames(log::TextColor tc)
{
// Initalize some memory
DWORD machine = IMAGE_FILE_MACHINE_AMD64;
HANDLE process = ::GetCurrentProcess();
HANDLE thread = GetCurrentThread();
// Initalize more memory
CONTEXT context;
STACKFRAME stack_frame;
// Set some memory
memset(&context, 0, sizeof(CONTEXT));
memset(&stack_frame, 0, sizeof(STACKFRAME));
// Capture the context
RtlCaptureContext(&context);
// Initalize a few things here and there
stack_frame.AddrPC.Offset = context.Rip;
stack_frame.AddrPC.Mode = AddrModeFlat;
stack_frame.AddrStack.Offset = context.Rsp;
stack_frame.AddrStack.Mode = AddrModeFlat;
stack_frame.AddrFrame.Offset = context.Rbp;
stack_frame.AddrFrame.Mode = AddrModeFlat;
// Randomly saw this was supposed to be called prior to StackWalk so tried it
if (!SymInitialize(process, 0, false))
{
wprintf(L"SymInitialize unable to find process!! Error: %d\r\n", GetLastError());
}
for (ULONG frame = 0; ; frame++)
{
// Set text color
SetTextColor(tc);
// Check for frames
BOOL result = StackWalk(machine, process, thread, &stack_frame, &context, 0,
SymFunctionTableAccess, SymGetModuleBase, 0);
// Get memory address of base module. Returns 0 although when SymInitialize is called before it the GetLastError returns 0 without return 6
DWORD64 module_base = SymGetModuleBase(process, stack_frame.AddrPC.Offset);
if (module_base == 0) {
wprintf(L"SymGetModuleBase is unable to get virutal address!! Error: %d\r\n", GetLastError());
}
// Initalize more memory
MODULEINFO module_info;
SecureZeroMemory(&module_info, sizeof(MODULEINFO));
// Get the file name of the file containing the function
TCHAR module_buffer[log::MaxPath];
DWORD mod_file = GetModuleFileName((HINSTANCE)module_base, module_buffer, log::MaxPath);
if ((module_base != 0) && (mod_file != 0))
{
module_info.module_name = module_buffer;
}
// Initalize more memory and clear it out
PIMAGEHLP_SYMBOL64 symbol;
IMAGEHLP_LINE64 line_num;
SecureZeroMemory(&symbol, sizeof(PIMAGEHLP_SYMBOL64));
SecureZeroMemory(&symbol, sizeof(IMAGEHLP_LINE64));
// Get the symbol
TCHAR symbol_buffer[log::MaxPath];
symbol = (PIMAGEHLP_SYMBOL)symbol_buffer;
symbol->SizeOfStruct = (sizeof(IMAGEHLP_SYMBOL) + log::MaxPath);
symbol->MaxNameLength = 254;
// Attempt to get name from symbol (fails)
LPSTR name_buffer = new CHAR[254];
if (SymGetSymFromAddr(process, stack_frame.AddrPC.Offset, 0, symbol))
{
name_buffer = symbol->Name;
}
// Set the size of something
DWORD offset = 0;
line_num.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
// Attempt to get the line and file name of where the symbol is
if (SymGetLineFromAddr(process, stack_frame.AddrPC.Offset, &offset, &line_num))
{
module_info.line = line_num.LineNumber;
module_info.file = line_num.FileName;
}
// Initalize memory
LPWSTR console_message = new TCHAR[log::MaxMsgLength];
LPWSTR file_message = new TCHAR[log::MaxMsgLength];
// Set some strings
swprintf(console_message, log::MaxMsgLength, L">> Frame %02lu: called from: %016X Stack: %016X Frame: %016X Address return: %016X\r\n",
frame, stack_frame.AddrPC.Offset, stack_frame.AddrStack.Offset, stack_frame.AddrFrame.Offset, stack_frame.AddrReturn.Offset);
swprintf(file_message, log::MaxMsgLength, L"Frame %02lu: called from: %016X Stack: %016X Frame: %016X Address return: %016X\r\n",
frame, stack_frame.AddrPC.Offset, stack_frame.AddrStack.Offset, stack_frame.AddrFrame.Offset, stack_frame.AddrReturn.Offset);
/* When the symbol can yield the name, line and file name the above strings
will also include that information */
// To go here . . .
// Write some strings
wprintf(console_message);
WriteAsync(file_message);
// Delete some memory
if (console_message) {
delete[] console_message; console_message = nullptr;
}
if (file_message) {
delete[] file_message; file_message = nullptr;
}
// If nothing else to do break loop
if (!result) {
break;
}
}
}
What i hope to achieve
Although i realize this will only work in debug mode that is fine, and i know i could write a macro using the __LINE__ __FUNCTION__ __FILE__ macros but that isn't what i'm looking for.
The results should be a wind up from the bottom stack showing the memory addresses of the calling PC, stack and frame. This works.
However it should also show me which the Name of the function, the Line number and the File path. This doesn't work.
FYI: I realize i need to add the code in to the generate the string and output it, but the code isn't capable of getting the information for the strings so that isn't coded in yet.
Please if anyone can help me, it would be fantastic all the code is focused around the "DbgHelp.h" windows file and most information is available on MSDN. So for the long question but i felt i should provide everything i know.
::GetCurrentProcess() = 0xffffffffffffffff
is not suspicious.
I tried a few variations on your code pulling bits from here and there - in the end I could not get it to work as I was using clang/mingw and it was not generating .pdb files. However, maybe the code will work for you as you are using MSVC. Anyway, here it is, in case it helps
I also noticed you hard coded machine type to AMD - I assume that is correct for you, but below I have an ifdef I found that sets it for other archs.
#include <windows.h>
#include <excpt.h>
#include <imagehlp.h>
#include <binutils/bfd.h>
#include <psapi.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <stdbool.h>
#include <psapi.h>
#include <dbghelp.h>
#define MAX_SYMBOL_LEN 1024
typedef struct CallstackEntry
{
DWORD64 offset; // if 0, we have no valid entry
CHAR name[MAX_SYMBOL_LEN];
CHAR undName[MAX_SYMBOL_LEN];
CHAR undFullName[MAX_SYMBOL_LEN];
DWORD64 offsetFromSmybol;
DWORD offsetFromLine;
DWORD lineNumber;
CHAR lineFileName[MAX_SYMBOL_LEN];
DWORD symType;
LPCSTR symTypeString;
CHAR moduleName[MAX_SYMBOL_LEN];
DWORD64 baseOfImage;
CHAR loadedImageName[MAX_SYMBOL_LEN];
} CallstackEntry;
typedef enum CallstackEntryType
{
firstEntry,
nextEntry,
lastEntry
} CallstackEntryType;
void _backtrace (void)
{
HANDLE process = ::GetCurrentProcess();
HANDLE thread = GetCurrentThread();
if (!SymInitialize(process, 0, true)) {
wprintf(L"SymInitialize unable to find process!! Error: %d\r\n",~
GetLastError());
}
DWORD symOptions = SymGetOptions();
symOptions |= SYMOPT_LOAD_LINES;
symOptions |= SYMOPT_FAIL_CRITICAL_ERRORS;
symOptions = SymSetOptions(symOptions);
char szSearchPath[MAX_SYMBOL_LEN] = {0};
SymGetSearchPath(process, szSearchPath, MAX_SYMBOL_LEN);
char szUserName[MAX_SYMBOL_LEN] = {0};
DWORD dwSize = MAX_SYMBOL_LEN;
GetUserNameA(szUserName, &dwSize);
CHAR search_path_debug[MAX_SYMBOL_LEN];
size_t maxLen = MAX_SYMBOL_LEN;
#if _MSC_VER >= 1400
maxLen = _TRUNCATE;
#endif
_snprintf_s(search_path_debug, maxLen,~
"SymInit: Symbol-SearchPath: '%s', symOptions: %d, UserName: '%s'\n",
szSearchPath, symOptions, szUserName);
search_path_debug[MAX_SYMBOL_LEN - 1] = 0;
printf(search_path_debug);
// Initalize more memory
CONTEXT context;
memset(&context, 0, sizeof(CONTEXT));
context.ContextFlags = CONTEXT_FULL;
RtlCaptureContext(&context);
// Initalize a few things here and there
STACKFRAME stack;
memset(&stack, 0, sizeof(STACKFRAME));
stack.AddrPC.Offset = context.Rip;
stack.AddrPC.Mode = AddrModeFlat;
stack.AddrStack.Offset = context.Rsp;
stack.AddrStack.Mode = AddrModeFlat;
stack.AddrFrame.Offset = context.Rbp;
stack.AddrFrame.Mode = AddrModeFlat;
#ifdef _M_IX86
auto machine = IMAGE_FILE_MACHINE_I386;
#elif _M_X64
auto machine = IMAGE_FILE_MACHINE_AMD64;
#elif _M_IA64
auto machine = IMAGE_FILE_MACHINE_IA64;
#else
#error "platform not supported!"
#endif
for (ULONG frame = 0; ; frame++) {
BOOL result = StackWalk(machine,~
process,~
thread,~
&stack,
&context,
0,
SymFunctionTableAccess,~
SymGetModuleBase,~
0);
CallstackEntry csEntry;
csEntry.offset = stack.AddrPC.Offset;
csEntry.name[0] = 0;
csEntry.undName[0] = 0;
csEntry.undFullName[0] = 0;
csEntry.offsetFromSmybol = 0;
csEntry.offsetFromLine = 0;
csEntry.lineFileName[0] = 0;
csEntry.lineNumber = 0;
csEntry.loadedImageName[0] = 0;
csEntry.moduleName[0] = 0;
IMAGEHLP_SYMBOL64 symbol {};
symbol.SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
symbol.MaxNameLength = MAX_SYMBOL_LEN;
// Initalize more memory and clear it out
if (SymGetSymFromAddr64(process,~
stack.AddrPC.Offset,
&csEntry.offsetFromSmybol,~
&symbol)) {
}
IMAGEHLP_LINE64 line {};
line.SizeOfStruct = sizeof(line);
if (SymGetLineFromAddr64(process,~
stack.AddrPC.Offset,
&csEntry.offsetFromLine,~
&line)) {
}
printf("Frame %lu:\n"
" Symbol name: %s\n"
" PC address: 0x%08LX\n"
" Stack address: 0x%08LX\n"
" Frame address: 0x%08LX\n"
"\n",
frame,
symbol.Name,
(ULONG64)stack.AddrPC.Offset,
(ULONG64)stack.AddrStack.Offset,
(ULONG64)stack.AddrFrame.Offset
);
// If nothing else to do break loop
if (!result) {
break;
}
}
}

How to register custom exception in Intel SGX?

I'm having difficulty to get my custom exception handler to work.
This is the Enclave code:
#include "Enclave_DivideZero_t.h"
#include "sgx_trts_exception.h"
#include "sgx_trts.h"
#include <string>
static char buf[200] = "Handler not called";
int divide_by_zero_handler(sgx_exception_info_t* info) {
buf[0] = '1';
return EXCEPTION_CONTINUE_EXECUTION;
}
void Enclave_DivideByZero() {
Ocall_printf(buf);
if (sgx_register_exception_handler(1, divide_by_zero_handler) == NULL) {
Ocall_printf("register failed");
} else {
Ocall_printf("register success");
}
int a(1);
int b(3/(a-a));
(void) a;
(void) b;
Ocall_printf(buf);
}
We used buf as an indication of whether the handler has been actually executed. However, the output is this:
Enclave created!
[Ocall printf] - Handler not called
[Ocall printf] - register success
[Ocall printf] - Handler not called <-- should be: "1andler not called" ("1andler" instead of "Handler")
Also, here is the App code (i.e. the untrusted code)
#include "stdafx.h"
#include "sgx_urts.h"
#include "Enclave_DivideZero_u.h"
#define ENCLAVE_FILE _T("Enclave_DivideZero.signed.dll")
sgx_status_t createEnclave(sgx_enclave_id_t *eid) {
sgx_status_t ret = SGX_SUCCESS;
sgx_launch_token_t token = {0};
int updated = 0;
ret = sgx_create_enclave(ENCLAVE_FILE, SGX_DEBUG_FLAG, &token, &updated, eid, NULL);
return ret;
}
void Ocall_printf( char* str) {
printf("[Ocall printf] - %s\n", str);
}
int _tmain(int argc, _TCHAR* argv[]) {
sgx_enclave_id_t eid;
sgx_status_t res = createEnclave(&eid);
if (res != SGX_SUCCESS) {
printf("App: error-, failed to create enclave.\n");
return -1;
} else {
printf("Enclave created!\n");
}
Enclave_DivideByZero(eid);
return 0;
}
The Problem: As you can see from the output indicates that the handler is registered successfully, but is not executed.
1- Why the registration doesn't work?
2- I tried to put the registeration with the App code, and for this I had to add the handler in the edl, the problem for this is passing the sgx_exception_info_t *info param, which is not clear which flags it needs (i.e. [in, .. <'flags'>]). So, is it correct to define it inside the Enclave?
p.s. I ran the code with Prerelease Mode.
[EDIT] I documented the project + code that I conducted on SGX here
So the question is a bit old now, but I got stuck at the same place, so maybe someone can still use my insight.
In trts_veh.cpp, where it is checked whether the exception was handled, it says in a comment that the "instruction triggering the exception will be executed again". This leads to the exception handling loop, as you noticed yourself.
However, you can increase the rip yourself, as it is stored in the pointer to the sgx_exception_info_t, by using "info->cpu_context.rip += 2;". Adding this inside your exception handler should do the trick.

C++ - Serial (COM) port - asio | VS2015 error(s)

1. What are we trying to achieve (and why)
We're currently trying to communicate with an industrial robot over USB(COM)<->serial(RS232). We would like to control the robot from a C++ application.
2. What setup do we have
We're using Visual Studio C++ 2015 with the built-in C++ compiler. Creating a "Win32 Console Application".
3. What steps have we taken?
We've got the connection working in Processing (Java) using Serial but we would like to implement it in C++.
3.1 Boost ASIO
We're using Boost ASIO (installed with NuGet package manager).
At this point we get 2 compile errors indicating the same problem:
Error C2694 'const char *asio::detail::system_category::name(void) const': overriding virtual function has less restrictive exception specification than base class virtual member function 'const char *std::error_category::name(void) noexcept const'
I figured that this error is most likely not caused by my code (I haven't changed the library). So I believe the VS21015 C++ compiler is not fully compatible with boost::asio?
I've found two other links/posts with somewhat the same error:
https://github.com/chriskohlhoff/asio/issues/35
And I tried the following define:
#ifndef ASIO_ERROR_CATEGORY_NOEXCEPT
#define ASIO_ERROR_CATEGORY_NOEXCEPT noexcept(true)
#endif // !defined(ASIO_ERROR_CATEGORY_NOEXCEPT)
Error in websocketpp library and boost in windows Visual Studio 2015
With the following define:
#define ASIO_ERROR_CATEGORY_NOEXCEPT noexcept(true)
//or
#define ASIO_ERROR_CATEGORY_NOEXCEPT 1
But it did not resolve the errors. The even caused a lot of random syntax errors and undeclared identifiers (which would indicate missing the include of iterator.
3.2 Windows(base) and C
We've used some C code (and added in a little C++ Debugging) to detect COM ports. But it simply doesn't show them (however it does in device explorer). We even had to convert a LPCWSTR to char array (wtf?).
#include <stdio.h>
#include <cstdio>
#include <iostream>
#include <windows.h>
#include <winbase.h>
wchar_t *convertCharArrayToLPCWSTR(const char* charArray)
{
wchar_t* wString = new wchar_t[4096];
MultiByteToWideChar(CP_ACP, 0, charArray, -1, wString, 4096);
return wString;
}
BOOL COM_exists(int port)
{
char buffer[7];
COMMCONFIG CommConfig;
DWORD size;
if (!(1 <= port && port <= 255))
{
return FALSE;
}
snprintf(buffer, sizeof buffer, "COM%d", port);
size = sizeof CommConfig;
// COM port exists if GetDefaultCommConfig returns TRUE
// or changes <size> to indicate COMMCONFIG buffer too small.
std::cout << "COM" << port << " | " << (GetDefaultCommConfig(convertCharArrayToLPCWSTR(buffer), &CommConfig, &size)
|| size > sizeof CommConfig) << std::endl;
return (GetDefaultCommConfig(convertCharArrayToLPCWSTR(buffer), &CommConfig, &size)
|| size > sizeof CommConfig);
}
int main()
{
int i;
for (i = 1; i < 256; ++i)
{
if (COM_exists(i))
{
printf("COM%d exists\n", i);
}
}
std::cin.get();
return 0;
}
3.3 Another Serial.h from the internet
I believe it was from: http://www.codeguru.com/cpp/i-n/network/serialcommunications/article.php/c2503/CSerial--A-C-Class-for-Serial-Communications.htm
Same rules, I include the library, everything compiles fine. (Test written below)
#include <iostream>
#include <string>
#include "Serial.h"
int main(void)
{
CSerial serial;
if (serial.Open(8, 9600))
std::cout << "Port opened successfully" << std::endl;
else
std::cout << "Failed to open port!" << std::endl;
std::cin.get();
return 0;
}
But it still doesn't show my COM ports... (They do show up in device explorer though.)
4 So what is actually working?
This particular piece of code WILL display the right COM port...
TCHAR lpTargetPath[5000]; // buffer to store the path of the COMPORTS
DWORD test;
for (int i = 0; i<255; i++) // checking ports from COM0 to COM255
{
CString str;
str.Format(_T("%d"), i);
CString ComName = CString("COM") + CString(str); // converting to COM0, COM1, COM2
test = QueryDosDevice(ComName, lpTargetPath, 5000);
// Test the return value and error if any
if (test != 0) //QueryDosDevice returns zero if it didn't find an object
{
std::cout << "COM" << i << std::endl; // add to the ComboBox
}
}
Maybe you need to update to a more recent version of boost if you have not already.
The issue with the second part is you naming of the COM port. Only COM1 to 4 can be a 'bald' name. You need to format it like this:
\\.\COM9
Clearly take care of escape sequences here:
snprintf(buffer, sizeof(buffer), "\\\\.\\COM%d", port);
EDIT: Actually you don't need to do that with GetCommConfig, only with CreateFile for opening the port. It should work. I'd suspect your conversion to wide string.
You may also find a performance enhancement of you load the cfgmgr32.dll library first.
Using CreateFile for COM port detection can result in in BSODs on some Windows systems. Particular culprits are some software modems and some bluetooth devices which show up s COM ports. So using GetDefaultCommConfig is the way to go generally though it may not work for all ports.
So what else can you do? Use setupapi.dll. Sadly this is not completely trivial..
namespace {
typedef HKEY (__stdcall *OpenDevRegKey)(HDEVINFO, PSP_DEVINFO_DATA, DWORD, DWORD, DWORD, REGSAM);
typedef BOOL (__stdcall *ClassGuidsFromName)(LPCTSTR, LPGUID, DWORD, PDWORD);
typedef BOOL (__stdcall *DestroyDeviceInfoList)(HDEVINFO);
typedef BOOL (__stdcall *EnumDeviceInfo)(HDEVINFO, DWORD, PSP_DEVINFO_DATA);
typedef HDEVINFO (__stdcall *GetClassDevs)(LPGUID, LPCTSTR, HWND, DWORD);
typedef BOOL (__stdcall *GetDeviceRegistryProperty)(HDEVINFO, PSP_DEVINFO_DATA, DWORD, PDWORD, PBYTE, DWORD, PDWORD);
} // namespace
typedef std::basic_string<TCHAR> tstring;
struct PortEntry
{
tstring dev;
tstring name;
bool operator== (tstring const& device) const {
return dev == device; // TODO maybe use case-insentitive compare.
}
bool operator!= (tstring const& device) const {
return !(*this == device);
}
};
typedef std::vector<PortEntry> PortList;
// ...
DllHandler setupapi; // RAII class for LoadLibrary / FreeLibrary
if (!setupapi.load(_T("SETUPAPI.DLL"))) {
throw std::runtime_error("Can\'t open setupapi.dll");
}
OpenDevRegKey fnOpenDevRegKey =
setupapi.GetProc("SetupDiOpenDevRegKey");
ClassGuidsFromName fnClassGuidsFromName =
#ifdef UNICODE
setupapi.GetProc("SetupDiClassGuidsFromNameW");
#else
setupapi.GetProc("SetupDiClassGuidsFromNameA");
#endif
DestroyDeviceInfoList fnDestroyDeviceInfoList =
setupapi.GetProc("SetupDiDestroyDeviceInfoList");
EnumDeviceInfo fnEnumDeviceInfo =
setupapi.GetProc("SetupDiEnumDeviceInfo");
GetClassDevs fnGetClassDevs =
#ifdef UNICODE
setupapi.GetProc("SetupDiGetClassDevsW");
#else
setupapi.GetProc("SetupDiGetClassDevsA");
#endif
GetDeviceRegistryProperty fnGetDeviceRegistryProperty =
#ifdef UNICODE
setupapi.GetProc("SetupDiGetDeviceRegistryPropertyW");
#else
setupapi.GetProc("SetupDiGetDeviceRegistryPropertyA");
#endif
if ((fnOpenDevRegKey == 0) ||
(fnClassGuidsFromName == 0) ||
(fnDestroyDeviceInfoList == 0) ||
(fnEnumDeviceInfo == 0) ||
(fnGetClassDevs == 0) ||
(fnGetDeviceRegistryProperty == 0)
) {
throw std:runtime_error(
"Could not locate required functions in setupapi.dll"
);
}
// First need to get the GUID from the name "Ports"
//
DWORD dwGuids = 0;
(*fnClassGuidsFromName)(_T("Ports"), NULL, 0, &dwGuids);
if (dwGuids == 0)
{
throw std::runtime_error("Can\'t get GUIDs from \'Ports\' key in the registry");
}
// Allocate the needed memory
std::vector<GUID> guids(dwGuids);
// Get the GUIDs
if (!(*fnClassGuidsFromName)(_T("Ports"), &guids[0], dwGuids, &dwGuids))
{
throw std::runtime_error("Can\'t get GUIDs from \'Ports\' key in the registry");
}
// Now create a "device information set" which is required to enumerate all the ports
HDEVINFO hdevinfoset = (*fnGetClassDevs)(&guids[0], NULL, NULL, DIGCF_PRESENT);
if (hdevinfoset == INVALID_HANDLE_VALUE)
{
throw std::runtime_error("Can\'t get create device information set.");
}
// Finished with the guids.
guids.clear();
// Finally do the enumeration
bool more = true;
int index = 0;
SP_DEVINFO_DATA devinfo;
while (more)
{
//Enumerate the current device
devinfo.cbSize = sizeof(SP_DEVINFO_DATA);
more = (0 != (*fnEnumDeviceInfo)(hdevinfoset, index, &devinfo));
if (more)
{
PortEntry entry;
//Did we find a serial port for this device
bool added = false;
//Get the registry key which stores the ports settings
HKEY hdevkey = (*fnOpenDevRegKey)(
hdevinfoset,
&devinfo,
DICS_FLAG_GLOBAL,
0,
DIREG_DEV,
KEY_QUERY_VALUE
);
if (hdevkey)
{
//Read in the name of the port
TCHAR port_name[256];
DWORD size = sizeof(port_name);
DWORD type = 0;
if ((::RegQueryValueEx(
hdevkey,
_T("PortName"),
NULL,
&type,
(LPBYTE) port_name,
&size
) == ERROR_SUCCESS) &&
(type == REG_SZ)
) {
// If it looks like "COMX" then
// add it to the array which will be returned
tstring s = port_name;
size_t len = s.length();
String const cmp(s, 0, 3);
if (CaseInsensitiveCompareEqual(String("COM"), cmp)) {
entry.name = s;
entry.dev = "\\\\.\\" + s;
added = true;
}
}
// Close the key now that we are finished with it
::RegCloseKey(hdevkey);
}
// If the port was a serial port, then also try to get its friendly name
if (added)
{
TCHAR friendly_name[256];
DWORD size = sizeof(friendly_name);
DWORD type = 0;
if ((fnGetDeviceRegistryProperty)(
hdevinfoset,
&devinfo,
SPDRP_DEVICEDESC,
&type,
(PBYTE)friendly_name,
size,
&size
) &&
(type == REG_SZ)
) {
entry.name += _T(" (");
entry.name += friendly_name;
entry.name += _T(")");
}
//
// Add the port to our vector.
//
// If we already have an entry for the given device, then
// overwrite it (this will add the friendly name).
//
PortList::iterator i = std::find(
ports.begin(),
ports.end(),
entry.dev
);
if (i == ports.end()) {
ports.push_back(entry);
}
else {
(*i) = entry;
}
}
}
++index;
}
// Free up the "device information set" now that we are finished with it
(*fnDestroyDeviceInfoList)(hdevinfoset);
You'll need to do a bit of work to make that compilable but it should work.
See https://support.microsoft.com/en-us/kb/259695

Dll injection with GetFullPathNameA not working?

If I explicitly write the address the dll injection works
char s[1000]="E:\\worldisnotenough.dll"; //Works
If I use GetFullPathNameA DLL injections do not work, and they do not give any runtime or compile time errors. I checked this:
char s[1000];
int ax =GetFullPathNameA("worldisnotenough.dll",
1000,
s, //Output to save the full DLL path
NULL);
std::cout<<s; //prints the correct path. Working.
The line cout << s prints the correct path, but DLL injection doesn't happen. No errors occur. I checked VirtualAllocEx, WriteProcessMemory, and CreateRemoteThread, and all of them are working properly.
Edit: complete code
#include <QCoreApplication>
#include<windows.h>
#include<tchar.h>
#include<iostream>
#include "E:/Users/Gen/qt project freiza/FreizaLibrary/freizalibrary.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
// FreizaLibrary lib;
// QTextStream s(stdin);
// QString value = s.readLine();
// lib.injection(value.toInt());
int procID = 13044;
HANDLE hHandle = OpenProcess( PROCESS_CREATE_THREAD |
PROCESS_QUERY_INFORMATION |
PROCESS_VM_OPERATION |
PROCESS_VM_WRITE |
PROCESS_VM_READ,
FALSE,
procID );
QString dllName = "worldisnotenough.dll";
QFile myDllFile(dllName);
QFileInfo dllInfo(dllName);
QString str =dllInfo.absoluteFilePath();
char s[]="E:\\Users\\Gen\\qt project freiza\\build-libtester-FreizaKit-Release\\release\\worldisnotenough.dll";
std::cout<<strlen(s)<<"\n";
int ax =GetFullPathNameA("worldisnotenough.dll",
86, //I set it to 1000 before posting this question.
s, //Output to save the full DLL path
NULL);
//qDebug()<< QString::fromUtf8(s) <<" "<< ax;
std::cout<<s<<"size "<<ax;
LPVOID dllPathAddr = VirtualAllocEx(hHandle,
0,
strlen(s),
MEM_RESERVE|MEM_COMMIT,
PAGE_EXECUTE_READWRITE);
std::cout<<" test \n";
std::cout<<(int*)dllPathAddr<<endl;
if(dllPathAddr==NULL)
{
qDebug()<<"virtual failed";
}
size_t x;
int n= WriteProcessMemory(hHandle,
dllPathAddr,
s,
strlen(s),
&x);
if(n==0)
{
qDebug()<<"write failed";
}
std::cout<<endl<<n<<"\t"<<x;
LPVOID addr = (LPVOID)GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryA");
if(addr==NULL)
{
qDebug()<<"get proc failed";
}
HANDLE rThread = CreateRemoteThread(hHandle, NULL, 0, (LPTHREAD_START_ROUTINE)addr,dllPathAddr, 0, NULL);
if(rThread==NULL)
{
qDebug()<<"create remote failed";
}
WaitForSingleObject(rThread, INFINITE);
VirtualFreeEx(hHandle, dllPathAddr, 0, MEM_RELEASE);
CloseHandle(hHandle);
qDebug()<< "done";
return a.exec();
}
And why negative votes?
When I post full code. People say only post the segment of code which is not working.
And I explained the situation to its fullest. Because of these negative votes now I won't be able to ask questions on stackoverflow. Thank you.
Your problem is you are trying to use a statically defined character array as a buffer for GetFullPathNameA!
See here:
char s[]="E:\\Users\\Gen\\qt project freiza\\build-libtester-FreizaKit-Release\\release\\worldisnotenough.dll";
std::cout<<strlen(s)<<"\n";
int ax =GetFullPathNameA("worldisnotenough.dll",
86, //1000 is no good, MAX_PATH is 260
s, //Using 's' as a buffer? Don't do that please!
NULL);
Furthermore when using the ANSI version which you are as denoted by the 'A' a maximum path length of 260 characters is the maximum. MAX_PATH==260
"In the ANSI version of this function, the name is limited to MAX_PATH characters. To extend this limit to 32,767 wide characters, call the Unicode version of the function and prepend "\?\" "
Fixed code: (However I don't use QT so that is missing from here, shouldn't matter though as it wasn't used for anything needed for the injecting to work)
#include <windows.h>
#include <iostream>
#include <tlhelp32.h>
HANDLE GetProcessHandle(wchar_t *ProcessName,ULONG *ReturnedProcessId);
int main(int argc, char *argv[])
{
ULONG procID;
HANDLE hHandle=GetProcessHandle(L"ExeToInjectInto.exe",&procID);
/*HANDLE hHandle=OpenProcess(PROCESS_CREATE_THREAD|PROCESS_QUERY_INFORMATION|PROCESS_VM_OPERATION|
PROCESS_VM_WRITE|PROCESS_VM_READ,FALSE,procID);*/
std::cout<<"handle: "<<hHandle<<" process ID: "<<procID<<"\n";
char s[]="C:\\Users\\DBVM_OS\\CodeBlocksProjects\\HelpFreizaProject\\bin\\Debug\\mytestdll.dll";
std::cout<<s<<"\n"<<strlen(s)<<"\n";
//First Problem:
/*In the ANSI version of this function, the name is limited to MAX_PATH characters.
To extend this limit to 32,767 wide characters, call the Unicode version of the function and prepend "\\?\"
*/
//Second Problem:
/* Don't use a defined static char[] as a buffer! allocate some memory or use the stack */
//char s2[MAX_PATH];
//int ax=GetFullPathNameA("mytestdll.dll",MAX_PATH,s2,0);
char *s2=new char[MAX_PATH];
if(s2==0) return 0;
int ax=GetFullPathNameA("mytestdll.dll",MAX_PATH,s2,0);
std::cout<<s2<<"\nsize returned: "<<ax<<" strlen: "<<strlen(s2)<<"\n";
LPVOID dllPathAddr=VirtualAllocEx(hHandle,0,(strlen(s2)+1),MEM_COMMIT,PAGE_EXECUTE_READWRITE);
std::cout<<"Remotely Allocated String Address: \n";
std::cout<<(int*)dllPathAddr<<"\n";
if(dllPathAddr==0)
{
OutputDebugStringA("VirtualAllocEx failed...");
return 0;
}
SIZE_T x;
BOOL n=WriteProcessMemory(hHandle,dllPathAddr,s2,(strlen(s2)+1),&x);
if(n==FALSE)
{
OutputDebugStringA("write failed");
VirtualFreeEx(hHandle,dllPathAddr,0,MEM_RELEASE);
CloseHandle(hHandle);
return 0;
}
std::cout<<"WriteProcessMemory Success: "<<n<<", Bytes Written: "<<x<<"\n";
LPVOID addr=(LPVOID)GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "LoadLibraryA");
if(addr==0)
{
OutputDebugStringA("get proc failed");
VirtualFreeEx(hHandle,dllPathAddr,0,MEM_RELEASE);
CloseHandle(hHandle);
return 0;
}
std::cout<<"LoadLibraryA: "<<addr<<"\n";
HANDLE rThread=CreateRemoteThread(hHandle,0,0,(LPTHREAD_START_ROUTINE)addr,dllPathAddr,0,0);
if(rThread==0)
{
OutputDebugStringA("create remote failed");
VirtualFreeEx(hHandle,dllPathAddr,0,MEM_RELEASE);
CloseHandle(hHandle);
return 0;
}
WaitForSingleObject(rThread,INFINITE);
std::cout<<"DLL Should have been injected successfully at this point...\nFreeing remote string";
BOOL freed=VirtualFreeEx(hHandle,dllPathAddr,0,MEM_RELEASE);
if(freed==0) OutputDebugStringA("Freeing Remote String Failed...");
delete[] s2; //if you dynamically allocated s2 like I've done...
CloseHandle(hHandle);
return 0;
}
HANDLE GetProcessHandle(wchar_t *ProcessName,ULONG *ReturnedProcessId)
{
PROCESSENTRY32W pe;
HANDLE Snap;
ZeroMemory(&pe, sizeof(PROCESSENTRY32W));
pe.dwSize=sizeof(PROCESSENTRY32W);
Snap=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
if(Snap==INVALID_HANDLE_VALUE) return 0;
BOOL bProcess=Process32FirstW(Snap,&pe);
while(bProcess)
{
if(_wcsicmp(pe.szExeFile,ProcessName)==0)
{
HANDLE ProcessHandle=OpenProcess(PROCESS_CREATE_THREAD|PROCESS_QUERY_INFORMATION|PROCESS_VM_OPERATION|
PROCESS_VM_WRITE|PROCESS_VM_READ,FALSE,pe.th32ProcessID);
if(ReturnedProcessId!=0)
*ReturnedProcessId=pe.th32ProcessID;
CloseHandle(Snap);
return ProcessHandle;
}
bProcess=Process32NextW(Snap, &pe);
}
if(ReturnedProcessId!=0) *ReturnedProcessId=0;
CloseHandle(Snap);
return 0;
}
you need to use
strlen(s)+1
cause it returnes the lenght of the string without including the terminating null character itself! So VirtualAllocEx and WriteProcessMemory will not write the '\0' char and the filename will terminate at a "random" position in memory.
Also
char s[]="E:\\Users\\Gen\\qt project freiza\\build-libtester-FreizaKit-Release\\release\\worldisnotenough.dll"; //- Length: 93+1
int ax =GetFullPathNameA("worldisnotenough.dll",
sizeof(s), //<-- old: 86 but s[] is 93 + 1 if this has to hold the total path may it was to small?
s, //Output to save the full DLL path
NULL);
looks wong?!