C++ Windows API over-riding? - winapi

In VS9, when i call the GetTickCount() function, it automatically converts it into the GetTickCount64() function upon compilation. This second function only works on Vista+, and thus my program errors when run on XP.
How can I 'over-ride' this so that it calls the original GetTickCount() ?
Thanks

Set WINVER to the version of windows you want to target. Or maybe it's _WIN32_WINNT or _WIN32_WINDOWS. Maybe even all of them...
Take a look at http://blogs.msdn.com/oldnewthing/archive/2007/04/11/2079137.aspx for details on that small mess-o-version macros.
However, I don't see that redefinition at all in the Windows SDK - could there be something else in our setup that's doing the redefinition (or maybe I'm missing it...)?

Remember that you're not compiling your application for Vista or Windows XP, rather you're compiling for a 32-bit or 64-bit operating system. If your application needs to support other versions of Windows than 64-bit Vista, then specify in your build options to be 32-bit.

I set the following inside targetver.h:
#define WINVER 0x0501
#define _WIN32_WINNT 0x0501
#define _WIN32_WINDOWS 0x0501
and it still gets re-defined. However, when i create a simple new project that prints out GetTickCount(), it works fine on XP even without me having to define the above.
I did not change anything in the project settings. The only difference between the sample GetTickCount() that works and the one that doesn't is that it has plenty of other code around it and using it, but none of that code should be changing anything.
What could be causing this?
EDIT: One of the other files I was using was calling GetTickCount64() directly, and I did not know about this, so I assumed it was my own GetTickCount() function. Please ignore what i wrote above

Related

Calling DCOM/COM+ methods with x86 binary targeting x64 server fails, any idea why?

Apologies for any foolish mistakes I've made in my code - I'm new to DCOM and VC++ as a whole. I know the basics but unfortunately not enough to figure this out.
Currently, I have some VC++ code that calls the equivalent of this in Powershell
$excel = [activator]::CreateInstance([type]::GetTypeFromProgID("Excel.Application", "127.0.0.1")); $excel.RegisterXLL("Path\to\x64\dll.dll"). Now if i use this PS Snippet on both x86 Powershell and x64 Powershell targeting an x64 COM server, it, well, suprinsingly works.
I then tried replicating it in C++, and got this far. For clarification, SimpleDLL is a extremely simple DLL that calls WinExec() in DLLmain and pops a calculator App.
https://gist.githubusercontent.com/realoriginal/4178718ee114e3e23c5ebe4651763044/raw/425ce397ed4788c9fac25ae39dcfe1db779c8d99/source.c
This code works fine if the server is x64 and its compiled as an x64 binary. Additionally, it also works if the server is x86 and the binary is compiled to x86.
The problems start arising if I target an x64 server with an x86 binary. I tried using CLSCTX_ACTIVATE_32_BIT_SERVER but that doesnt work at all, as the method is only available in x64.
On the other hand, if I keep it as it is, it sometimes works. To explain what I mean by sometimes, here are my results that I get from it x86 client targeting an x64 Windows server calling this method.
The client triggers an ACCESS VIOLATION with 0x000001 (no idea why)
The client errors at CoCreateInstanceEx() with 0x8007000E: Not enough storage is available to complete this operation.
It loads the x64 DLL and pops the calculator on the remote server
My question is, what could be causing it to fail in those instances that it did, and how could I make it work 100% of the time with x86 client towards x64 COM+ Windows Server?

GetProcAddress fails on Win 7 even though the DLL actually exports the function (works on Win 10)

I have a 32-bit application and I have a problem with it on Windows 7 x64. I'm loading a DLL. LoadLibraryW succeeds and the subsequent call to GetProcAddress fails with the error code 127 ("procedure not found" or something like that).
The funny part is that I know for a fact the function is exported by the DLL. I made no typos in the GetProcAddress call. I can see the function with Depends.exe and DllExp.exe. The exact same application binary successfully loads the function from the exact same DLL on Windows 10 x64, but not on Windows 7 x64.
Some more details: the library is dbghelp.dll and the "missing" function is MiniDumpWriteDump.
And the fun bit: dbghelp.dll provides API for inspecting the modules loaded into the process and for enumerating functions exported by those modules. So, first I took the HMODULE for this problematic dbghelp.dll and ran
auto ptrSymInitialize = (decltype(&SymInitialize))GetProcAddress(hDbgHelpDll, "SymInitialize");
It worked, this function did load! Then I loaded SymEnumSymbols, written the enumerator callback and finally ran the following to enumerate all the functions in this very `dbghelp.dll":
ptrSymEnum(GetCurrentProcess(), 0, "dbghelp*!*", &Enumerator, nullptr);
And what do you know, MiniDumpWriteDump is, in fact, listed there. Go figure.
Thoughts?
I can see your intent is to use MiniDumpWriteDump. We also make minidumps in our product, and I'm the one to support this.
I would suggest against using dbghelp.dll supplied with OS. First, they tend to be outdated and not support the latest minidump capabilities, which you would want to have. Second, they have proven to be rather unreliable. I believe they simply lack too many bugfixes.
What I found to work quite well is to take dbghelp.dll from Debugging Tools for Windows package (currently part of Windows SDK) and ship it along with our product. This way, I can be sure minidumps will have all the latest features and it works reliably on all OS. It has been some 8 years now, with OS ranging from WinXP to Win10, and I didn't have any issues.
I'm not exactly sure which version of SDK I used to extract the currently used dbghelp.dll, probably it was Win7 SDK. I simply didn't have a reason to update since then. However, we do use Debugging Tools for Windows package from Win10 SDK on Win7 without any issues, so I guess you can use Win10 version as well.
that's exactly what I've been doing, and I didn't bring dbgcore.dll
This was just a plain bad idea. Microsoft makes no effort to make the DLLs that are included with the OS to be backwards compatible. They don't have to. In their implementation, only the interface needs to be compatible. They do take advantage of new capabilities or design changes to improve the implementation.
Like you saw here, a side-effect of the MinWin project. There is no reasonable guess where that ended, if it happens to work now on the Win7 machine then you got lucky. Maybe you won't be so lucky on a Win7 machine without SP1, maybe some minwin glue DLLs are missing on a clean install, maybe the minidump itself is affected negatively some way. Impossible to predict.
So never do this. Afaik you should not be doing this at all, a Win7 machine already has dbghelp.dll available. Not 100% sure, it has been too long and Win7 is rapidly turning into the new XP. If you find it to be necessary then always use the redistributable version. Included with the SDK's Debugging Tools for Windows. Copy it into the same folder as the EXE that needs it so you don't mess up a machine.

Why does using "int 21h" on Assembly x86 MASM cause my program to crash?

I was trying to make my program accept input without the user having to press enter, so I tried the following:
mov ah,01h
int 21h
But it just crashes my program over an unhandled exception. This seems to be the way to do it according to much that I have read, so why isn't it working for me?
Now, I am fairly new to this language so I still do not exactly understand the process of how this piece of code works, so I would also appreciate what the logic is behind accepting input by pressing enter and accepting input without the user having to press enter.
MY OS is Windows, by the way.
Your code looks like MS-DOS-era assembly. VS2010 doesn't support generating DOS executables, and modern versions of Windows (the 64-bit kind) don't support running them, either. Looks like you were going by some old book or site, one that was written in late 80'es-early 90's. Back at that time, assembly was way more relevant and marketable as a job skill. Not so much these days, although some assembly knowledge won't hurt.
Decide what do you want to learn. If you want to learn modern assembly (and target Windows), get some recent guidance. The techniques are quite different, and int21h isn't among them :) If you're indeed after DOS-era assembly, set up a DOS virtual machine with DOSBox, and find some old free assembler. Visual Studio 2010 won't help you here. The latest version of Visual C++ that generated 16-bit executables was v1.5x.
Specifically why does your program crash. Int21h was how MS-DOS exposed its applciation program interface (API). Windows doesn't support it for Windows executables - there are other ways of invoking the API. When you assemble with Visual Studio 2010, you end up with a Windows executable, not a DOS one, and there's no option to generate a DOS one. As for the Windows executables, they're not supposed to invoke interrupts at all - that's a crash condition.
You need to obtain a tool set that can generate 16 MS-DOS programs. These should run on DOSBOX, or on a Virtual PC with MS-DOS installed on it. Microsoft included 16 bit tool sets up to Visual C / C++ 1.52, but Visual C / C++ 4.0 and 4.1 also contain the 1.52 16 bit tool set. The older version of the compilers would be named Microsoft C 8.xx or earlier version. I don't know if any the early versions of Visual Studio (2002 or 2003) include the 16 bit tool set.
Use the linker version 5.60 to generate 16-bit DOS applications. You can get this from:
http://download.microsoft.com/download/vc15/Update/1/WIN98/EN-US/Lnk563.exe
Dirk

What #if preprocessor directive to determine if OS is WIN 7 SP1?

I'd like conditional compilation based on whether the compiling machine is running Windows 7 SP1 or not.
We have a workaround for http://support.microsoft.com/kb/2517589 but I don't want to check the code in unless it is guarded by an #ifdef _WIN7_SP1 otherwise the other devs won't be able to compile it on their non win7-sp1 machines.
I've had a bit of a google but couldn't find anything useful.
You don't. Things in the environment of the build machine generally don't pollute compilation like that. (Imagine if that happened and what effects it would cause on reproducibility of builds.)
If you really need to, I'd instead have your build system (make, Visual Studio, whatever) execute a program that checks the current Windows version and fails as necessary (or possibly your build system can determine this already). Based on that, you then could conditionally make own WIN7_SP1 definition via a command-line argument to your compiler.

Is there a Windows API call that will tell me if I'm running on a 64-bit OS?

Is there a Windows API call that will tell me if I'm running on a 64-bit OS? I have some legacy c++ code that makes a call to GetVersionEx to fill in a OSVERSIONINFO structure, but that only tells me (AFAIK) the OS (Vista, V7, etc.), but not the processing architecture. I can hack around this by simply looking for the existence of "C:\Program Files (x86)...", but this seems ugly. I'm sure there must be an API to return this info.
IsWow64Process might be what you are looking for.
GetNativeSystemInfo()
I found this post that seems to provide a good answer: Detect whether current Windows version is 32 bit or 64 bit
I don't know why it didn't come up when I search Stack Overflow before posting.
Incidentally, the best solution for me is to simply check for the ProgramW6432 environment variable.
The solution is pretty straight-forward. If you are compiling for 64-bit, you already know that you are running on a 64-bit version of Windows. So you only need to call IsWow64Process when compiling for 32-bit. The following implementation returns true, if it is running on a 64-bit version of Windows:
bool Is64BitPlatform() {
#if defined(_WIN64)
return true; // 64-bit code implies a 64-bit OS
#elif defined(_WIN32)
// 32-bit code runs on a 64-bit OS, if IsWow64Process returns TRUE
BOOL f = FALSE;
return ::IsWow64Process(GetCurrentProcess(), &f) && f;
#else
#error Unexpected platform.
#endif
}
This answers the question you asked. The answer to the question you should have asked instead was posted in the response by Jerry Coffin already: Simply call GetNativeSystemInfo.

Resources