warning C4996: 'GetVersionExW': was declared deprecated - visual-c++

I am working on VS 2013 in Win 8.1.
How to solve this warning?

The basic question is "why are you calling GetVersionExW in the first place?" The answer to that question determines what you should do instead.
The deprecation warning is there to give developers a heads-up about the appcompat behavior change that started in Windows 8.1. See Windows and Windows Server compatibility cookbook: Windows 8, Windows 8.1, and Windows Server 2012. In short, that function doesn't return what you think it returns by default.
Historically, badly written OS version checks are the primary source of appcompat bugs for Windows OS upgrades. There've been a number of different approaches to trying to mitigate this problem (the AppVerifier version lie, the VerifyVersionInfo API, etc.), and this is the most aggressive to date.
The VersionHelpers.h mentioned in the comments are in the Windows 8.1 SDK that comes with Visual Studio 2013. They are not a new API; they are just utility code that makes use of the VerifyVersionInfo API introduced back in Windows 2000. These functions are for doing "You must be this high to ride this ride" style checks which are the class of version checks that are most often badly written. The code is pretty simple. For example, the IsWindowsVistaSP2OrGreater test is:
VERSIONHELPERAPI
IsWindowsVersionOrGreater(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor)
{
OSVERSIONINFOEXW osvi = {};
osvi.dwOSVersionInfoSize = sizeof(osvi);
DWORDLONG const dwlConditionMask = VerSetConditionMask(
VerSetConditionMask(
VerSetConditionMask(
0, VER_MAJORVERSION, VER_GREATER_EQUAL),
VER_MINORVERSION, VER_GREATER_EQUAL),
VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
osvi.dwMajorVersion = wMajorVersion;
osvi.dwMinorVersion = wMinorVersion;
osvi.wServicePackMajor = wServicePackMajor;
return VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR, dwlConditionMask) != FALSE;
}
VERSIONHELPERAPI
IsWindowsVistaSP2OrGreater()
{
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 2);
}
You don't need to use VersionHelpers.h as you could just do this kind of code yourself, but they are convenient if you are already using the VS 2013 compiler. For games, I have an article What's in a version number? which uses VerifyVersionInfo to do the kind of reasonable checks one should for game deployment.
Note if you are using VS 2013 with the v120_xp platform toolset to target Windows XP, you'll actually be using the Windows 7.1A SDK and #include <VersionHelpers.h> won't work. You can of course use VerifyVersionInfo directly.
The other major use of GetVersionExW is diagnostic logs and telemetry. In this case, one option is to continue to use that API and make sure you have the right manifest entries in your application to ensure reasonably accurate results. See Manifest Madness for details on what you do here to achieve this. The main thing to keep in mind is that unless you routinely update your code, you will eventually stop getting fully accurate information in a future version of the OS.
Note that it is recommended you put the <compatibility> section in an embedded manifest whether or not you care about the results of GetVersionEx as general best practice. This allows the OS to automatically apply future appcompat fixes based on knowing how the app was originally tested.
For diagnostic logs, another approach that might be a bit more robust is to grab the version number out of a system DLL like kernel32.dll using GetFileVersionInfoW. This approach has a major caveat: Do not try parsing, doing comparisons, or making code assumptions based on the file version you obtain this way; just write it out somewhere. Otherwise you risk recreating the same bad OS version check problem that is better solved with VerifyVersionInfo. This option is not available to Windows Store apps, Windows phone apps, etc. but should work for Win32 desktop apps.
#include <Windows.h>
#include <cstdint>
#include <memory>
#pragma comment(lib, "version.lib" )
bool GetOSVersionString( WCHAR* version, size_t maxlen )
{
WCHAR path[ _MAX_PATH ] = {};
if ( !GetSystemDirectoryW( path, _MAX_PATH ) )
return false;
wcscat_s( path, L"\\kernel32.dll" );
//
// Based on example code from this article
// http://support.microsoft.com/kb/167597
//
DWORD handle;
#if (_WIN32_WINNT >= _WIN32_WINNT_VISTA)
DWORD len = GetFileVersionInfoSizeExW( FILE_VER_GET_NEUTRAL, path, &handle );
#else
DWORD len = GetFileVersionInfoSizeW( path, &handle );
#endif
if ( !len )
return false;
std::unique_ptr<uint8_t> buff( new (std::nothrow) uint8_t[ len ] );
if ( !buff )
return false;
#if (_WIN32_WINNT >= _WIN32_WINNT_VISTA)
if ( !GetFileVersionInfoExW( FILE_VER_GET_NEUTRAL, path, 0, len, buff.get() ) )
#else
if ( !GetFileVersionInfoW( path, 0, len, buff.get() ) )
#endif
return false;
VS_FIXEDFILEINFO *vInfo = nullptr;
UINT infoSize;
if ( !VerQueryValueW( buff.get(), L"\\", reinterpret_cast<LPVOID*>( &vInfo ), &infoSize ) )
return false;
if ( !infoSize )
return false;
swprintf_s( version, maxlen, L"%u.%u.%u.%u",
HIWORD( vInfo->dwFileVersionMS ),
LOWORD(vInfo->dwFileVersionMS),
HIWORD(vInfo->dwFileVersionLS),
LOWORD(vInfo->dwFileVersionLS) );
return true;
}
If there is some other reason you are calling GetVersionExW, you probably shouldn't be calling it. Checking for a component that might be missing shouldn't be tied to a version check. For example, if your application requires Media Foundation, you should set a "You must be this high to ride this ride check" like the VersionHelpers.h IsWindowsVistaOrGreater for deployment, but at runtime you should use explicit linking via LoadLibrary or LoadLibaryEx to report an error or use a fallback if MFPLAT.DLL is not found.
Explicit linking is not an option for Windows Store apps. Windows 8.x solves this
particular problem by having a stub MFPLAT.DLL and MFStartUp will return E_NOTIMPL.
See "Who moved my [Windows Media] Cheese"?
Another example: if your application wants to use Direct3D 11.2 if it is available and otherwise uses DirectX 11.0, you'd use set a IsWindowsVistaSP2OrGreater minimum bar for deployment perhaps using the D3D11InstallHelper. Then at runtime, you'd create the DirectX 11.0 device and if it fails, you'd report an error. If you obtain a ID3D11Device, then you'd QueryInterface for a ID3D11Device2 which if it succeeds means you are using an OS that supports DirectX 11.2. See Anatomy of Direct3D 11 Create Device.
If this hypothetical Direct3D application supports Windows XP, you'd use a deployment bar of IsWindowsXPSP2OrGreater or IsWindowsXPSP3OrGreater, and then at run time use explicit linking to try to find the D3D11.DLL. If it wasn't present, you'd fall back to using Direct3D 9--since we set the minimum bar, we know that DirectX 9.0c or later is always present.
They key point here is that in most cases, you should not use GetVersionEx.
Note that with Windows 10, VerifyVersionInfo and getting the file version stamp via GetFileVersionInfo for kernel32.lib are now subject to the same manifest based behavior as GetVersionEx (i.e. without the manifest GUID for Windows 10, it returns results as if the OS version were 6.2 rather than 10.0).
For universal Windows apps on Windows 10, you can a new WinRT API AnalyticsInfo to get a version stamp string for diagnostic logs and telemetry.

you can disable this warning and use GetVersionEx anyway by adding:
#pragma warning(disable : 4996)

While GetVersionEx was declared deprecated, if you toss in a proper compatibility manifest declaring compatibility with Windows 8.1 and Windows 10, GetVersionEx will return the correct version number. I use GetVersionEx to detect Windows 8 or greater, and because Windows 8 is the last version of Windows to not require a manifest to return the proper Windows version, my code works fine regardless of whether the API returns Windows 6.2, 6.3, 6.4 (for early Windows 10 previews), or 10.0.
With all that said, Microsoft deprecated this API in part due to bad usage of it. Take for instance this attempt to detect Windows XP or greater:
BOOL IsXPOrGreater;
OSVERSIONINFO osver;
osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&osver);
if((osver.dwMajorVersion >= 5) && (osver.dwMinorVersion >=1) IsXPOrGreater = TRUE;
else IsXPOrGreater = FALSE;
This sample would return TRUE on Windows XP, Server 2003, 7, 8, and 8.1 but would return FALSE on Windows Vista or 10. Adding one line would fix this:
BOOL IsXPOrGreater;
OSVERSIONINFO osver;
osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&osver);
if((osver.dwMajorVersion >= 5) && (osver.dwMinorVersion >=1) IsXPOrGreater = TRUE;
else if(osver.dwMajorVersion >= 6) IsXPOrGreater = TRUE;
else IsXPOrGreater = FALSE;
This sample would function correctly because it knows that if the major version is 6 or greater than it is greater than XP.

if you look at sysinfoapi.h you will find the following
NOT_BUILD_WINDOWS_DEPRECATE
WINBASEAPI
__drv_preferredFunction("IsWindows*", "Deprecated. Use VerifyVersionInfo* or IsWindows* macros from VersionHelpers.")
BOOL
WINAPI
GetVersionExW(
_Inout_ LPOSVERSIONINFOW lpVersionInformation
);
#ifdef UNICODE
#define GetVersionEx GetVersionExW
#else
#define GetVersionEx GetVersionExA
#endif // !UNICODE
if you track the NOT_BUILD_WINDOWS_DEPRECATE in the same header file you will find
#if defined(FKG_FORCED_USAGE) || defined(WINPHONE) || defined(BUILD_WINDOWS)
# define NOT_BUILD_WINDOWS_DEPRECATE
#else
# define NOT_BUILD_WINDOWS_DEPRECATE __declspec(deprecated)
#endif
the above code mean in simple words if you define one of the following
BUILD_WINDOWS or WINPHONE or FKG_FORCED_USAGE it will not show the deprecated error
so in your code you could do thing like this :
#define BUILD_WINDOWS before #include <windows.h>
and that should solve it for you.

Related

How to get a working x64 THREADSAFE Ghostscript DLL

Main context
We're actually trying to get a multi-threading version of Ghostscript x64 DLL, to make use of it through Ghostscript .NET. This component is supposed to "allow runing multiple Ghostscript instances simultaneously within a single process", but, as we have checked in our project, works fine until concurrent requests are made to the application. Same behavior can be replicated lauching same method using Tasks. The error description that raises in both cases, just when a call to the process is made until the last is being executed, is:
An error occured when call to 'gsapi_new_instance' is made: -100
Even it does no seem to be related with .NET directly, I will post a sample of our C# method code, just for contextualize.
// Define switches...
string[] switchesArray = switches.ToArray();
using (GhostscriptProcessor procesador = new GhostscriptProcessor())
{
try
{
procesador.StartProcessing(switchesArray, null);
byte[] destinationFile = System.IO.File.ReadAllBytes(destinationPath);
return destinationFile;
}
catch (Exception ex)
{
throw ex;
}
finally
{
System.IO.File.Delete(sourceFile);
}
}
THREADSAFE solution
Starting our investigation, we found this KenS's answer on this post, indicating that Ghostscript DLL must be generated with GS_THREADSAFE compiler definition.
To clarify, as we make use of Ghostscript 9.52 x64 to generate our PDFs, we need this x64 DLL compiled for Release configuration. After trying to compile Ghostscript sources on Windows 10 x64 machine, using Visual Studio Community 2017 and Visual Studio Community 2019, we finally managed to build and generate all items (only with VS Community 2019) without GS_THREADSAFE parameter, just to confirm that compilation is fine, and we check that the DLLs and executables are working. For this process we took in mind all we found in Ghostscript official documentation.
As we have no other guide to include this GS_THREADSAFE parameter, we followed the instructions given in this solution, including XCFLAGS="-DGS_THREADSAFE=1" on nmake build commands, usign this sentence for Rebuild all option:
cd .. && nmake -f psi\msvc32.mak WIN64= SBR=1 DEVSTUDIO= XCFLAGS=-DGS_THREADSAFE=1 && nmake -f psi\msvc32.mak WIN64= DEVSTUDIO= XCFLAGS=-DGS_THREADSAFE=1 bsc
This approach, rises an error during build:
Error LNK2019 unresolved external symbol errprintf_nomem referenced in
function gs_log_error File \mkromfs.obj 1
As it seems, the file mkromfs.c has a method called errprintf_nomem, which can't be found when GS_THREADSAFE is set.
Questions
1 - Is there any public release of Ghostscript that include x64 DLLs compiled to be THREADSAFE?
And, if not (that's what I'm guessing...)
2 - Is it possible to get this DLL to be THREADSAFE without changing the source code?
3- Could anyone provide, please, a step by step guide or walkthrough to build a x64 Ghostscript DLL using GS_THREADSAFE using Visual Studio (or even any other possible alternative) over Windows 10 x64?
4 - A few posts talk about people achive to manage multithreading using Ghostscript .NET. I assume this examples are all using a GS_THREADSAFE DLL... Is any other workaround we have passed?
Thank a lot in advance.
To summarize all this questions, and as a guide for future developers having this same trouble, these are the answers we've found until now:
AS #KenS mentions in his reply: "No, the Ghostscript developers don't actually build thread-safe versions of the binaries."
At this very moment, clearly not, as it has been reported on this opened bug.
As it seems to be a matter of commercial licensing support, we avoid comment on this point anymore.
Thanks again to #HABJAN. I absolutely take back what I've stated on my question, as it is possible to have Ghostscript .NET working on multi-threading scenarios. Below comes the solution we applied, in case it could be useful for someone.
Based on HABJAN example, what we have done to achieve this was to create a custom class to capture Ghostscript logging:
protected class ConsoleStdIO : Ghostscript.NET.GhostscriptStdIO
{
public ConsoleStdIO(bool handleStdIn, bool handleStdOut, bool handleStdErr) : base(handleStdIn, handleStdOut, handleStdErr)
{
}
public override void StdIn(out string input, int count)
{
char[] userInput = new char[count];
Console.In.ReadBlock(userInput, 0, count);
input = new string(userInput);
}
public override void StdOut(string output)
{
//log
}
public override void StdError(string error)
{
//log
}
}
For our previous method, we simple include a call to this class and this avoids errors when multiple tasks are executed at the same time:
// Define switches...
string[] switchesArray = switches.ToArray();
using (GhostscriptProcessor procesador = new GhostscriptProcessor())
{
try
{
procesador.StartProcessing(switchesArray, new ConsoleStdIO(true, true, true));
byte[] destinationFile = System.IO.File.ReadAllBytes(destinationPath);
return destinationFile;
}
catch (Exception ex)
{
throw ex;
}
finally
{
System.IO.File.Delete(sourceFile);
}
}
Well, it seems to me that you are asking here for technical support.
You clearly want to use Ghostscript in a commercial undertaking, indeed one might reasonably say you want an enterprise version of Ghostscript. Presumably you don't want to alter the source in order to permit you to use an open source license, because you don't want to pay for a commercial license.
With that in mind the answers to your questions are:
No, the Ghostscript developers don't actually build thread-safe versions of the binaries.
Currently, no. That's probably an oversight.
That would be a technical support question, there's no guarantee of technical support to free users, it's the one of the few areas of leverage for dual license vendors to persuade people to take up a commercial license. So I hope you will understand that I'm not going to provide that.
as far as I can see, no.

Visual Studio 2015 doesn't honour _Check_return_ or _Must_inspect_result_

I have a cross-platform build. On a *nix platform using GCC, I use the __attribute__((warn_unused_result)) to notify the consumer of my API if a return value is not checked. I assumed that _Check_return does the same thing on MSVC, but it doesn't appear to be working the way I expect.
The following code does not produce a warning as I expect. Warnings are set to /Wall.
_Check_return_ _Must_inspect_result_ int foo()
{
return 100;
}
int main()
{
foo();
return 0;
}
Code compiles without warnings. What am I doing wrong (or what should I be using to generate warnings for unchecked return codes)?
SAL annotations like _Check_return_ and _Must_inspect_result_ are only checked during code analysis builds (either by starting a code analysis build in the IDE or by building with the /analyze flag on the command line).
See "Understanding SAL" on MSDN for more information.

MFC CRecordset heap corruption detected at Close()

I recently upgraded my operating system from Windows XP to Windows 7 SP1 64 bit. We are using Visual Studio 2008 Professional Edition and Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - 64bit Production.
When I try to execute this code I am getting the below exceptions
try
{
CDatabase *pDatabase = CDatabaseConnection::getDatabaseConnectionProcessLog();
ORSProcessLog rsProcessLog(pDatabase);
CString strFilter = _T("SELECT PROCESS_ID, MESSAGE FROM OP_PROCESS_LOG");
rsProcessLog.SetRowsetSize(1);
if( !rsProcessLog.Open(CRecordset::dynaset, strFilter, CRecordset::appendOnly) )
return;
if( !rsProcessLog.CanAppend() )
return;
rsProcessLog.AddNew();
rsProcessLog.m_PROCESS_ID = gcsProcessID;
rsProcessLog.m_MESSAGE = csMessageA;
rsProcessLog.Update();
rsProcessLog.Close();
}
catch ( CDBException* pEx )
{
bException = true;
pEx->GetErrorMessage(szCause, 255);
}
catch( CException* pEx )
{
bException = true;
pEx->GetErrorMessage(szCause, 255);
}
where rsProcessLog is the CRecordset object using a successfully connected database pointer pDatabase
In 32- bit Debug version I get a message box at rsProcessLog.Close(); with the below text
Debug Error
Program: ......\Test.exe
HEAP CORRUPTION DETECTED: after Normal block (#506) at 0x0087F628. CRT detected that the application wrote to memory after end of heap buffer.
Memory allocated at f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\dbcore.cpp(2626)
(Please Retry to debug the application)
In 32- bit Release version I get a message box at rsProcessLog.Close(); with the below text
Windows has triggered a breakpoint in Test.exe
This may be due to a corruption of the heap, which indicates a bug in Test.exe or any of the DLLS it has loaded.
This may also be due to the user pressing F12 while Test.exe has focus.
The output window may have more diagnostic information.
The above code was a working code in Windows XP with the rest of the env remaining the same and it continues to run in Windows XP but not in Windows 7. Any help will be greatly appreciated.
After some analysis of MFC CRecordest class I noticed that the problem appears after call to ::SqlSetPos where m_rgRowStatus array allocated on the heap become damaged (one byte more is written on the heap).
First and clean approach to problem is to force CRecordset class to use update/delete SQL statements instead of ::SqlSetPos function. To achive this you need to open your database using OpenEx method with CDatabase::userCursorLib option.
CDatabase db;
db.OpenEx(ConnectionString, CDatabase:useCursorLib);
This will change some CRecordset functionalities. See more at: http://msdn.microsoft.com/en-us/library/c689y99f.aspx
Second approach (dirty) is to reallocate m_rgRowStatus field, to use more memory on the heap, so call to ::SqlSetPos will not write to unallocated memory.
One way to do that is to override CRecordset::PreBindFields function:
void CMyDerivedRecordset::PreBindFields()
{
if ( ! (m_dwOptions & useMultiRowFetch) )
{
delete [] m_rgRowStatus;
m_rgRowStatus = new WORD[2];
}
CRecordset::PreBindFields();
}
You can do that in all of your CRecordset derived classes, or you can make one new CRecordset derived class which will become base class for all of your existing CRecordsetderived classes.

string too long with MsiGetProperty with Installshield Installscript

I am using MsiGetProperty to get string parameter value from the installer.
And after that I am calling a managed dll and I pass the that value:
nvBufferSize = MAX_STRING;
MsiGetProperty (hMSI, "DBHMS", sDbHost, nvBufferSize);
when I pass the value of sDbHost is like this when I receive it from managed code:
srvdata-02NULNULNULNULNULNUL......
however in the interface I wrote just "srvdata-02".
With that same code it was fine with Installshield 2010, now I am upgrading it to installshield 2012.
Do you have any solution with that please?
There were some behavior changes to MsiGetProperty awhile back. Try setting nvBufferSize to MAX_SIZE instead of MAX_STRING. Also check the return code of MsiGetProperty to see if it equals ERROR_MORE_DATA or if it's returning some other code. Finally check the value of nvBufferSize to see how many bytes are needed.
BTW, if you are just trying to marshal a property over to managed code, you might want to conisder looking into Deployment Tools Framework (DTF) in Windows Installer XML (WiX). This is a very nice SDK that allows you to write managed code custom actions and package them up as if they are native Win32 libraries. InstallShield can then easily use this as an MSI DLL custom action.
DTF provides an interop library and a session object that can be used like:
Deployment Tools Foundation (DTF) Managed Custom Actions
Reasons DTF is Better
As ridiculous as it may seem, here's a working InstallScript solution for you:
nvBufferSize = MAX_STRING;
nResult = MsiGetProperty( ISMSI_HANDLE, szPropertyName, svValue, nvBufferSize );
if( nResult = ERROR_MORE_DATA ) then
MsiGetProperty( ISMSI_HANDLE, szPropertyName, svValue, nvBufferSize );
endif;
The first attempt returns the actual buffer size needed. If it is more then max string (1024?), the second call gets the whole thing.
Alternatively, I found I could assign nvBufferSize to larger value right off the bat e.g. 4096 and use that with a single call (assuming the data was no longer that limit). The double call, however, is more fool proof.
According to: https://msdn.microsoft.com/en-us/library/aa370134(v=vs.85).aspx the api function is actually designed to return the buffersize by passing an empty literal ("") instead of a string variable. InstallScript 2013 throws a compilation error at you if you try that though...

Visual C++ 6.0 on Windows 8

Visual C++ 6.0 is not supported on Windows 8, but we have a couple of legacy apps that still needs to be compiled with Visual C++ 6.0. :-(
It is possible to install Visual C++ 6.0 on Windows 8 by unchecking Data Access -> Change Options -> ADO, RDS and OLE DB Providers. See this SU-question and this thread. You also need to install SP6 afterwards.
Visual C++ 6.0 works perfectly on one computer, but two others cannot use the debugger. The same hardware, same version of Windows, same person doing the installation, same project. There must be some difference...
On the computers with the problem you can set a break point and the debugger will break into the IDE, but when you try do step, step into or run the code will crash with Unhandled exception in EXENAME.EXE (OLE32.DLL): 0xC0000005: Access Violation.
Walter Oney reports the exact same problem on MSDN forums, but they have no solution as VC++ 6.0 is unsupported.
As we have Visual C++ 6.0 working on one Win8 computer there is apparently way to do it. Any ideas on what the difference could be?
Turning off OLE RPC debugging (Tools / Options / Debug) works for me (Windows 8 Pro 64 bit, Visual C++ 6.0 with SP6). This solution was suggested (later) within the above-mentioned MSDN forum thread.
I was eventually able to get VS 6 working on Win 8 and Win 10. The basic steps were these:
Create a dummy file named msjava.dll in \Windows. (E.g., "echo >msjava.dll") Without this step, the VS 6 installer can't get very far.
Install VS 6 and SP 6.
Rename MSDEV.EXE to something else, such as MSDEVQ.EXE.
Create a compatibility database for MSDEVQ that excludes the fault-tolerant heap shim. Without this step, debugging a program that makes heavy use of HeapAlloc, etc., is excruciatingly slow.
For debugging, ensure that a breakpoint is tripped before any calls to OLE32 can occur. I include the following header early in the main program or (for an MFC app) the InitInstance function:
X64DebugHack.h:
#ifdef _DEBUG
// In order to be able to debug this application on x64, we need to single
// step across at least one statement before ole32.dll gets loaded. So
// always leave this breakpoint in place.
requiredbreakpoint:
int junkola = 42;
// Check to see that there was a breakpoint...
PUCHAR pjunk;
_asm lea eax, requiredbreakpoint
_asm mov pjunk, eax
if (*pjunk != 0xCC)
AfxMessageBox("Required breakpoint was not set prior to loading OLE32.DLL -- single stepping will not be possible during this debugging session.", MB_OK | MB_ICONHAND, 0);
LoadLibrary("OLE32");
#endif
Write an extension DLL that provides a "Stop Debugging" button. The extension has to search and destroy debug handles, which have a different handle type in Win64 than in Win32. The mechanics of writing the extension are beyond the scope of this forum, but the code that does the actual work is here:
CCommands::HelpAssistantKill:
typedef LONG NTSTATUS;
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L)
enum SYSTEM_INFORMATION_CLASS {
SystemHandleInformation = 16,
};
typedef NTSTATUS(NTAPI *PNTQUERYSYSTEMINFORMATION)(SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG);
typedef struct _SYSTEM_HANDLE_INFORMATION {
ULONG ProcessId;
UCHAR ObjectTypeNumber;
UCHAR Flags;
USHORT Handle;
PVOID Object;
ACCESS_MASK GrantedAccess;
} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;
typedef struct _SYSTEM_HANDLE_INFORMATION_DATA {
ULONG HandleCount;
SYSTEM_HANDLE_INFORMATION HandleInformation[1];
} SYSTEM_HANDLE_INFORMATION_DATA, *PSYSTEM_HANDLE_INFORMATION_DATA;
#define HANDLE_TYPE_DEBUG_OBJECT 11 // correct value for Win8 x64
STDMETHODIMP CCommands::HelpAssistantKill()
{ // CCommands::HelpAssistantKill
AFX_MANAGE_STATE(AfxGetStaticModuleState());
BOOL didit = FALSE;
HMODULE hDll = NULL;
PSYSTEM_HANDLE_INFORMATION_DATA phi = NULL;
do { // do once
HRESULT hr;
// Locate NtQuerySystemInformation within NTDLL.DLL
hDll = LoadLibrary("NTDLL");
if (!hDll)
break;
PNTQUERYSYSTEMINFORMATION NtQuerySystemInformation = (PNTQUERYSYSTEMINFORMATION) GetProcAddress(hDll, "NtQuerySystemInformation");
if (!NtQuerySystemInformation)
break;
// Do an initial query to get the number of handles presently open in the system.
// This is a large number. The returned length value is meaningless for this query.
SYSTEM_HANDLE_INFORMATION_DATA hid;
DWORD junk;
NTSTATUS status = (*NtQuerySystemInformation)(SystemHandleInformation, &hid, sizeof(hid), &junk);
if (!NT_SUCCESS(status) && status != STATUS_INFO_LENGTH_MISMATCH)
break;
ULONG length = sizeof(SYSTEM_HANDLE_INFORMATION_DATA) + (hid.HandleCount - 1) * sizeof(SYSTEM_HANDLE_INFORMATION);
phi = (PSYSTEM_HANDLE_INFORMATION_DATA) new UCHAR[length];
if (!phi)
break;
// Get a list of all handles open in the system
status = (*NtQuerySystemInformation)(SystemHandleInformation, phi, length, &junk);
if (!NT_SUCCESS(status))
break;
// Find and close any debug objects that are open in this instance of Visual Studio.
DWORD pid = GetCurrentProcessId();
ULONG ihandle;
for (ihandle = 0; ihandle < hid.HandleCount; ++ihandle)
{ // for each open handle
PSYSTEM_HANDLE_INFORMATION p = phi->HandleInformation + ihandle;
if (p->ProcessId != pid || p->ObjectTypeNumber != HANDLE_TYPE_DEBUG_OBJECT)
continue;
if (CloseHandle((HANDLE) p->Handle))
didit = TRUE;
} // for each open handle
// Instruct DevStudio to stop
BSTR bsStopDebugging = SysAllocString(L"DebugStopDebugging");
if (!bsStopDebugging)
break;
hr = m_pApplication->ExecuteCommand(bsStopDebugging);
SysFreeString(bsStopDebugging);
if (hr != 0)
break;
} // do once
while (FALSE);
if (phi)
delete[] phi;
if (hDll)
FreeLibrary(hDll);
if (!didit)
{ // didn't do anything
MessageBox(NULL, "Unable to find and close any debug object handles", "HelpAssistant", MB_OK | MB_ICONINFORMATION);
} // didn't do anything
return S_OK;
} // CCommands::HelpAssistantKill
This felt like a pretty heroic effort, but I had about a million lines of code built on VS 6 that I had to keep working. Now that I've built myself a workable macro processor for VS 2015, I may undertake a conversion of this application.
One wrinkle -- I had the very same same issue with the Visual C++ 6.0 debugger on Windows 8.1 . But I could not find the RPC debug option under the Tools/Options/ Debug option described in the answer above. Instead I had to go into the registry editor and delete the RPC Debug key that is mentioned in the same MSDN thread referenced above (maybe it was there because I had already installed later versions of Microsoft Visual Studio before I had installed 6.0) . The debugger works great now, and thanks to previous posters!
The issue is due to incompatible “ADO, RDS and OLE DB Providers” comes along with the Visual C++ 6.0.
Please follow the below mentioned steps to disable ADO, RDS and OLE DB Providers and install the Visual C++ 6.0 –
1) Start the installation as usual.
2) Click on Custom installation when installer will ask for type of installation.
3) Click on Data Access from available items and then click on ‘Change Option’.
4) In new window de-select “ADO, RDS and OLE DB Providers” and click OK (ignore the warning).
5) Click on continue to proceed with the installation.
6) Installer will not freeze during ‘Updating components’ and will install successfully.
7) Now install the service pack ‘Vs6sp6’ and it will also install successfully.
Non of above answers work for me.
Solution from this site fix my problem.
Re-register ole32.dll file and check if it helps.
Click Start, type cmd in the Start search.
Right click on cmd and click on Run as administrator.
In the Command prompt, type the following commands and hit ENTER
after each command.
takeown /f ole32.dll
regsvr32 ole32.dll
Close the Command prompt after running the above two commands.
Try to run the application and check is the issue persists.

Resources