I switched my project to x64 and got an error - c++

I have this project that I'm working on for a while now, and it was working just fine before I switched from releasing an x86 version to an x64 one.
This is the line of code where the error appeared:
ReadProcessMemory(a.hProcess, LPCVOID(b->Ebx + 8), LPVOID(&c), 4, 0);
I don't understand assembly but when the Error appeared at b->Ebx I changed it to b->Rbx. and it compiled and run but it didn't do the job it was supposed to do.
Am I using the wrong register?
After a little bit of debugging
pe_dos_h = PIMAGE_DOS_HEADER(pe_image);
pe_nt_h = PIMAGE_NT_HEADERS(DWORD(pe_image) + pe_dos_h->e_lfanew);
//error when trying to assign a value or access the signature in nt-headers
//ERROR: read access violation
IMAGE_NT_HEADERS* pe_nt_h->Signature == IMAGE_NT_SIGNATURE;//0x00004550-PE00
The pe_image is raw data copied from a PE(.exe) file. Is the difference is in handling x86 PE image vs x64 one?
This is a simplified version of the code. If you think the problem is out of the scope of this piece of code let me know.

The problem was in the way I was defining the IMAGE_SECTION_HEADER, In x64 architecture, I had to use the x64-specific datatype IMAGE_SECTION_HEADER64.
and also when casting pe_nt_h = PIMAGE_NT_HEADERS(DWORD_PTR(pe_image) + pe_dos_h->e_lfanew);
I had to use DWORD_PTR instead of just DWORD because it was missing some bits.
here is the solution code for the simplified version I provided in the post:
PIMAGE_DOS_HEADER pe_dos_h = PIMAGE_DOS_HEADER(pe_image);
PIMAGE_NT_HEADERS64 pe_nt_h = PIMAGE_NT_HEADERS(DWORD_PTR(pe_image) + pe_dos_h->e_lfanew);

Related

After installing the 1.1.92.1 VulkanSDK xmemory0 and vector errors

After installing the 1.1.92.1 VulkanSDK xmemory0 and vector errors popped up and the project does not compile any more, bellow are the output errors from Visual Studio 2017. Going back to the previous 1.1.85.0 sdk version thought, it works again. Any idea what happens? Thanks.
Edit
<https://pastebin.com/94x8Lerq>
the error list is too big to include here, i m using this link
Edit2
It seems the way to enumerate stuff (at least the way i did it), has changed a bit, thus it explains those vector error i was getting.
Old way:
uint32_t gpuCount = 0;
vulkan.instance.enumeratePhysicalDevices(&gpuCount, nullptr);
std::vector<vk::PhysicalDevice> gpuList(gpuCount);
vulkan.instance.enumeratePhysicalDevices(&gpuCount, gpuList.data());
New way:
std::vector<vk::PhysicalDevice> gpuList = vulkan.instance.enumeratePhysicalDevices().value;
Since you are using vulkan.hpp, you could ask about this on their GitHub site. You could also diff vulkan.hpp between the two SDKs and note that there are differences in the file where enumeratePhysicalDevices is concerned.

After recompiling our FORTRAN-code and using it in C++ our system() or c_str() command don`t work properly

Hi I have a big problem: We created a program in C++/Qt 4.8.4 /Qt Creator 2.8.1 years ago that while executing runs another executable (written and compiled in FORTRAN). Everything worked well.
We recompiled our Fortran-Code with the new version of Visual studio and now suddenly it doesn`t work any more. I looked into my C++-Code and found the position where the program crashes:
std::string Executable = ApplicationName.toStdString();
bool RunOK= system((Executable+" > "+"X.out2").c_str());
QString ExeName = (Executable+" > "+"X.out2").c_str();
QString tf = QString::number(qweee);
if(system((Executable+" > "+"X.out2").c_str()))
{
msg.showMessage("msg.showMessage("An XXX error occured during calculation......((Executable+ > +X.out2).c_str(): "+ExeName +"......(system((Executable+ > +X.out2).c_str()): "+ QString::number(RunOK));
if(QFile(OutputFiles[0]).exists())
QFile(OutputFiles[0]).remove();
}
Somehow system((Executable+" > "+"X.out2").c_str()) gets to be true which didn`t happen before.
This seems to happen either in the c_str-command or in the system()-command.
We had some missing dll-issues before. Is this another dll-problem and if so which?
Can anybody help us on this?
Thank you
The return value of system is an integer, not a boolean. Its value is only defined for one very special case, system(nullptr). That's not the case here. So whether you get a zero or non-zero result depends on your particular C++ implementation, which has indeed changed. ("New visual studio version"). You can't rely on non-zero means error
c_str() is not a suspect at all.

VC++ Exception Handling differ on x86 and x64 for IBPP / Firebird client

I am hacking around with IBPP on Visual Studio 2015 / VC++. IBPP is a c++ wrapper for the firebird / interbase API.
IBPP, a C++ Client Interface to Firebird Server
Part of this package is a little test-suite, you may download it here:
ibpp-2-5-3-1-src.zip
To start with the test-suite you will find a simple batchfile to compile it under
x:...\ibpp-2-5-3-1-src\tests\vs2005\simplest-build.bat
It compiles fine with the native x86 and x64 toolchains of vc++ 2015.
Before compiling you need to edit lines 84 to 86 of
x:...\ibpp-2-5-3-1-src\tests\tests.cpp
const char* DbName = "x:/ibpptest/test.fdb"; // FDB extension (GDB is hacked by Windows Me/XP "System Restore")
const char* BkName = "x:/ibpptest/test.fbk";
const std::string ServerName = ""; //"localhost"; // Change to "" for local protocol / embedded
Please keep mind to create the directory x:\ibpptest\.
Furthermore you need to download the fblient files which are not available on its own but as part of the entire server archive. Get these both files:
32-bit Embedded
and
64-bit Embedded
.
For simplifying create two directories besides x:\...\ibpp-2-5-3-1-src\tests\vs2005\:
x:\...\ibpp-2-5-3-1-src\tests\vs2015x86\
x:\...\ibpp-2-5-3-1-src\tests\vs2015x84\
and copy x:\...\ibpp-2-5-3-1-src\tests\vs2005\simplest-build.bat into them. Now copy the fbclient files (32 Bit to x86, 64 Bit to x64) in these directories:
intl/*
udf/*
fbembed.dll
firebird.msg
ib_util.dll
icudt30.dll
icuin30.dll
icuuc30.dll
msvcp80.dll
msvcr80.dll
Now you can compile and start tests.exe. The x86 binary generates some errors in Test 6, that's OK because you are using the embedded version of the fblient files. The x64 binary will end up in a Windows program failure screen. This happens in Test3 when the test suite activates an exception:
try
{
#if defined(IBPP_WINDOWS) && defined(_DEBUG)
OutputDebugString(_("An exception will now get logged in the debugger: this is expected.\n"));
#endif
st1->ExecuteImmediate( "CREATE SYNTAX ERROR(X, Y) AS "
"SELECT ERRONEOUS FROM MUSTFAIL M" );
}
catch(IBPP::SQLException& e)
{
//~ std::cout<< e.what();
if (e.EngineCode() != 335544569)
{
_Success = false;
printf(_("The error code returned by the engine during a\n"
"voluntary statement syntax error is unexpected.\n"));
}
}
In the x86 binary this exception was caught as expected but in the x64 binary it will not. Does anybody knows how to achive similar exception handeling in the x64 binary?
Thanks in advance for any help!
Caveat: I used the Visual Studio 2017 environment to run the simplest-build.bat file.
It appears from the evidence I provide below that there is a fork or other compiling difference between the 32 bit and 64 bit versions of the Firebird service that causes this problem.
Solution: The EngineCode() member function does not exist in the 64 bit version. You must use the exception's what() member function as shown in the commented out line inside the Test3() catch block. If you desire to use EngineCode information you will have to parse it out of the what() string, because that contains all of the information that was originally provided as individual data members in the IBPP::SQLExceptionImpl class for 32 bit.
try
{
#if defined(IBPP_WINDOWS) && defined(_DEBUG)
OutputDebugString(_("An exception will now get logged in the debugger: this is expected.\n"));
#endif
st1->ExecuteImmediate( "CREATE SYNTAX ERROR(X, Y) AS "
"SELECT ERRONEOUS FROM MUSTFAIL M" );
}
catch(IBPP::SQLException& e)
{
//~ std::cout<< e.what();
printf(e.what());
//if (e.EngineCode() != 335544569)
//{
// _Success = false;
// printf(_("The error code returned by the engine during a\n"
// "voluntary statement syntax error is unexpected.\n"));
//}
}
Result of what() call.
*** IBPP::SQLException ***
Context: Statement::ExecuteImmediate( CREATE SYNTAX ERROR(X, Y) AS SELECT ERRONEOUS FROM MUSTFAIL M )
Message: isc_dsql_execute_immediate failed
SQL Message : -104
can't format message 13:896 -- message file C:\WINDOWS\SYSTEM32\firebird.msg not found
Engine Code : 335544569
Engine Message :
Dynamic SQL Error
SQL error code = -104
Token unknown - line 1, column 8
SYNTAX
Puzzle: statement.cpp shows the use of IBPP::SQLExceptionImpl and other ...ExceptionImpl usage, so I have to believe this source code is the 32 bit branch. If this is supposed to be a common branch for both 32 and 64 bit, then I don't see how it can work.
There are two header files that define exception classes. I believe that _ibbp.h was used to compile the 32 bit client and ibbp.h was used for the 64 bit client. I came to these conclusions by changing the catch clause in Test3() to see what possible exceptions could be happening. The ...ExceptionImpl classes would only compile with the 32 bit client dlls and they would not compile with the 64 bit dlls.
From _ibpp.h (32bit fbclient dlls recognize these classes. 64bit fbclient dlls do not.)
///////////////////////////////////////////////////////////////////////////////
//
// Implementation of the "hidden" classes associated with their public
// counterparts. Their private data and methods can freely change without
// breaking the compatibility of the DLL. If they receive new public methods,
// and those methods are reflected in the public class, then the compatibility
// is broken.
//
///////////////////////////////////////////////////////////////////////////////
//
// Hidden implementation of Exception classes.
//
/*
std::exception
|
IBPP::Exception
/ \
/ \
IBPP::LogicException ExceptionBase IBPP::SQLException
| \ / | \ /
| LogicExceptionImpl | SQLExceptionImpl
| |
IBPP::WrongType |
\ |
IBPP::WrongTypeImpl
*/
From ibpp.h (both fbclient dll sets recognize these classes)
/* IBPP never return any error codes. It throws exceptions.
* On database engine reported errors, an IBPP::SQLException is thrown.
* In all other cases, IBPP throws IBPP::LogicException.
* Also note that the runtime and the language might also throw exceptions
* while executing some IBPP methods. A failing new operator will throw
* std::bad_alloc, IBPP does nothing to alter the standard behaviour.
*
* std::exception
* |
* IBPP::Exception
* / \
* IBPP::LogicException IBPP::SQLException
* |
* IBPP::WrongType
*/
In all of tests.cpp, the only catch for IBPP::SQLException is in Test3(). Every other catch uses IBPP::Exception.
So this problem will only show up in Test3() when compiling for 64 bit, but I think it would manifest itself whenever IBPP::SQLException is used in a 64 bit implementation.
After a lot of more research I found the cause. I was wrong beliving that the exception handling in x86 and x64 differ. The IBPP library contains a bug (since 10 years!) which only happens in the x64/windows szenario when the firebird library reports an (complex) error condition to the caller.
So what happens is:
The test programm calls the IBPP libarary. The IBPP library calls the firebird API / library. The firebird library reports its results of calls in a array[20] of longs, they call it "ISC_STATUS vector". The IBPP library checks this results and in a case of an error it throws an exception. The test program catches such exceptions and reports them to the use.
So far, so good. But the bug is, that IBPP defines ISC_STATUS as an array[20] of longs as firebird it also did until v2.0 - which only support x86 windows. Beginning with v2.1 firebird supports x64 windows an defines ISC_STATUS as an array of intptr_t which leads to "long long" on windows x64 LLP64 compilers and to long on LP64 linux compilers - both are 64 bit wide. On ILP32 windows and linux x86 compilers intptr_t is 32 bit wide.
IBPP doesn't closed the gap to firebird and stays on its definition of ISC_STATUS as long - which leads to a 32 bit wide data type on LLP64 windows x64 systems (but to 64 bit on linux, as gcc on linux uses a LP64 system, so the bug only happens on windows).
So the firebird x64 API reports up to 20 status integers to the "by reference parameter" array[20] of 64 Bit integers. The FBPP library passes an array[20] of 32 Bit integers. When the firebird API stores values in second half of the array it overwrites memory of the caller. In this case the next bytes after the ISC_STATUS vector are occupied by a c++ string object. Both, the status array and the string a part of the IBS (interbase status) class. Many of the IBPP functions often instantiating a local object of this class to manage the firebird API results and a error descriping string. When the functions exits the framework cleans up such local objects and tries to free the string but its metadata in memory was overwritten by the firebird API.
So the cleanup of the local IBS object leads to an unknown software exceptions which overdrives the exceptions thrown by the IBPP framework. And this exception is not catched by the test program but by windows / dr. watson.
I fixed the definition of ISC_STATUS from "long" to "intptr_t" and all works as expected.
Thank you all for your hints.

How can I detect, programmatically, whether a DLL is compiled 32bit or 64bit in .NET?

So far I have been able to load the dll using the following code:
Assembly^ assembly = Assembly::LoadFrom(pathDll);
But I don't know how to detect whether it's 32 or 64 bits.
I think that I've found the answer. Off course, first of all you must get the assembly associated with the dll though the following line of code:
Assembly^ assembly = Assembly::LoadFrom(pathDll);
Then you can get the information about the platform through the following code:
ProcessorArchitecture processor_architecture = assembly->GetName()->ProcessorArchitecture;
if (ProcessorArchitecture::Amd64 == processor_architecture)
{
// 64bits
}
if (ProcessorArchitecture::X86 == processor_architecture)
{
//32 bits
}

Installer::OpenDatabase() produces a type error with msiOpenDatabaseModeTransact

The following code produces an error hr=0x80020005 (wrong type).
#import <msi.dll>
using namespace WindowsInstaller;
main()
{
::CoInitialize(NULL);
InstallerPtr pInstaller("WindowsInstaller.Installer");
DatabasePtr pDB = pInstaller->OpenDatabase(
"c:\\foo\\bar.msi",
msiOpenDatabaseModeTransact);
}
I think the reason is that behind the scene, there is MsiOpenDatabase(), which
take a LPCTSTR as second argument.
This second argument can be MSIDBOPEN_TRANSACT whose definition is
#define MSIDBOPEN_TRANSACT (LPCTSTR)1
I do not know if it is possible to give a variant with the good inner type as second argument. The _variant_t constructor does many checks, so I can't disguise an int into
a char* so easily.
Has anyone tried to use this method in C++?
Edit:
My version of msi.dll is 3.1.4000.2805, my system is XP SP 2, and the code is supposed to run on any machine with XP or Vista.
urls to MSDN articles are welcome.
On the same machine, the call to the low-level equivalent:
MsiOpenDatabase("c:\\foo\\bar.msi", MSIDBOPEN_TRANSACT);
works perfectly.
I finally got the answer on msdn forums
DatabasePtr pDB = pInstaller->OpenDatabase(
"c:\\foo\\bar.msi",
(long)msiOpenDatabaseModeTransact);
MSDN says OpenDatabase is available from MSI version 4.0 onwards, transactions in general from MSI 4.5 onwards. Just a hunch, but could it be that your MSI is outdated? I once had some mysterious trouble with an outdated MSI version.