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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With