Category Archives: Seriously - Page 2

LogProcessExceptions: Automatically Create Minidump Files on C++ Exception in Monitored Process

LogProcessExceptions utility implements a very basic debugger which attaches (see DebugActiveProcess on MSDN) to a running process and monitors its exceptions. Once exception takes place the utility creates a minidump file for the process (see MiniDumpWriteDump on MSDN) so that exception condition could be investigated off-site using debugger.

If you throw C++ exceptions in your C++ code in exceptional cases which indicate necessity to log the condition and possibly check it later, the utility will get the vital information for the application running at production location in environment without fully featured debugger (note that the utility is a simple download-and-run “wizard” style application, with no installation required), or will simply track the error letting the application continue execution without pretty much of an interruption.

The tool will prompt for debuggee process, and follow with minidump type choices and the debugging operation.

Read more »

Your ATL service C++ project might need some extra care after upgrade to Visual Studio 2010

If you dare to convert your C++ ATL Service project created with an earlier version of Visual Studio to version 2010, as I recently did, you might find yourself surprised with why the hell the bloody thing does not work anymore as a regular executable.

After passing compiler/linker and SDK update issues, which you possibly might have too, the started executable will stumble on ATL error/exception with CO_E_NOTINITIALIZED (0x800401F0 “CoInitialize has not been called.”). Luckily the error code is good enough for quickly locating the problem and the reason is that the one you trusted, that is ATL, introduced an small improvement which is good for running as service but it not initializing COM anymore if you run your .EXE in application mode.

The bug is on MS Connect since August 3, 2010 closed as if it is going to be fixed some time in future when the fix is propagated to end developers. If you are in a rush and would like to write some code before the event, here are the details.

Previously, COM was initialized right in module constructor, in CAtlExeModuleT. CAtlServiceModuleT class just inherited from there. Later on, someone smart decided that it was not so cool and moved initialization to a later point into CAtlExeModuleT::WinMain. Well, this makes sense as you might (a) end up not needing COM at all, or (b) you want to do some important things before even initializing COM.

Unfortunately, the fact that CAtlServiceModuleT is inherited and relies on base class was not paid too much attention. CAtlServiceModuleT is not getting COM initialization from constructor any longer, CAtlServiceModuleT::WinMain is overridden in full and does not receive initialization from new location either. So well, it does not receive it at all unless run as service, which code execution branch looks still heatlhy here and exhibits another issue later soon.

To resolve the problem, the fragment in CAtlServiceModuleT::Start needs the correction as shown below (within #pragma region):

        if (::StartServiceCtrlDispatcher(st) == 0)
                m_status.dwWin32ExitCode = GetLastError();
            return m_status.dwWin32ExitCode;
        }

        // local server - call Run() directly, rather than
        // from ServiceMain()
        #pragma region Run wrapped by InitializeCom/UninitializeCom
        // FIX: See http://connect.microsoft.com/VisualStudio/feedback/details/582774/catlservicemodulet-winmain-coinitialize-not-called-800401f0
#ifndef _ATL_NO_COM_SUPPORT
        HRESULT hr = E_FAIL;
        hr = T::InitializeCom();
        if (FAILED(hr))
        {
            // Ignore RPC_E_CHANGED_MODE if CLR is loaded. Error is due to CLR initializing
            // COM and InitializeCOM trying to initialize COM with different flags.
            if (hr != RPC_E_CHANGED_MODE || GetModuleHandle(_T("Mscoree.dll")) == NULL)
                return hr;
        } else
            m_bComInitialized = true;
        m_status.dwWin32ExitCode = pT->Run(nShowCmd);
        if (m_bComInitialized)
            T::UninitializeCom();
#else
        m_status.dwWin32ExitCode = pT->Run(nShowCmd);
#endif
        #pragma endregion 

        return m_status.dwWin32ExitCode;
    }

Going further from there, the introduced optimization also removed COM initialization from main process thread module Run function. Provided there earlier too through module constructor it is not longer there. So if you are doing something in application’s run when the application is set to run as service and is executed in application (where you might want to start application as a sort of a helper, or otherwise in specific mode), you need COM initialization there too.

Read more »

If your application is looking for network adapters, it may be blind to see

A really long and annoying troubleshooting of a problem finally ended with a bug found in GetAdaptersInfo/GetAdaptersAddresses API.

It may unexpectedly fail under the following conditions:

  • 32-bit application
  • 64-bit operating system or /3GB feature enabled on 32-bit operating system
  • hosting process is linked with /LARGEADDRESSAWARE flag or has otherwise set it in binary header
  • over 2GB of RAM (in terms of Private Bytes/Virtual Size performance counters) consumed by the hosting process

The application might unexpectedly start getting ERROR_NO_DATA (232) or ERROR_NOACCESS (998) error codes instead of list of adapters. Supposedly, the responsible Microsoft component iplhlpapi.dll or one of the underlying components/APIs are incompatible with such environments (such as for example, treating 32-bit pointer with the most significant bit set as invalid or compares such pointers as signed values).

A test Visual C++ .NET 2010 application is available from SVN. More bug details on Microsoft Connect.

NOTE 1: You need to run “GetAdaptersAddressesTest /regserver” once to register the app before running it for the test.

NOTE 2: The problem does not seem to take place with 32-bit operating systems with /3GB tuning enabled.

Obtaining number of thread context switches programmatically

Previous post on thread synchronization and context switches used number of thread context switches as one of the performance indicators. One might have hard times getting the number from operating system though.

The only well documented access to amount of context switches seems to be accessing corresponding performance counters. Thread performance counter will list available thread instances and counters “Thread(<process-name>/<thread-number>)/Context Switches/sec” will provide context switch rate per second.

While access to performance counters is far not the most convenient API, to access data programmatically one would really prefer absolute number of switches rather than rate per second (which is still good for interactive monitoring).

A gate into kernel world to grab the data of interest is provided with NtQuerySystemInformation function. Although mentioned in documentation, it is marked as unreliable for use, and Windows SDK static library is missing it so one has to obtain it using GetModuleHandle/GetProcAddress it explicity.

typedef NTSTATUS (WINAPI *NTQUERYSYSTEMINFORMATION)(SYSTEM_INFORMATION_CLASS SystemInformationClass, PVOID SystemInformation, ULONG SystemInformationLength, PULONG ReturnLength);
NTQUERYSYSTEMINFORMATION NtQuerySystemInformation = (NTQUERYSYSTEMINFORMATION) GetProcAddress(GetModuleHandle(_T("ntdll.dll")), "NtQuerySystemInformation");
ATLASSERT(NtQuerySystemInformation);
ATLVERIFY(NtQuerySystemInformation(...) == 0);

Having this done, the function is capable of providing SystemProcessInformation/SYSTEM_PROCESS_INFORMATION data about running processes.

Read more »

How to get HMODULE of msvcr90.dll

Because Microsoft C++ Runtime library is distributed as a side-by-side assembly, GetModuleHandle and LoadLibrary is no longer available to locate the library within the process. Both API calls would return NULL handle.

HMODULE hModule = GetModuleHandle(_T("msvcr90.dll"));
HMODULE hModule = LoadLibrary(_T("msvcr90.dll"));

Still, how to locate the modules in order to, for example, be able to check DLL version? Process Status API (PSAPI) can help:

#include <psapi.h>
#pragma comment(lib, "psapi.lib")

...

DWORD nDataSize = 4 << 10; // 4K
EnumProcessModules(GetCurrentProcess(), NULL, 0, &nDataSize);
nDataSize += nDataSize / 2;
CTempBuffer<HMODULE> phModules;
ATLENSURE_THROW(phModules.AllocateBytes(nDataSize), E_OUTOFMEMORY);
if(EnumProcessModules(GetCurrentProcess(), phModules, nDataSize, &nDataSize))
{
    const SIZE_T nCount = nDataSize / sizeof *phModules;
    for(SIZE_T nIndex = 0; nIndex < nCount; nIndex++)
    {
        CPath sPath = _VersionInfoHelper::GetModulePath(phModules[nIndex]); // uses GetModuleFileName
        if(_tcsicmp(FindFileName(sPath), _T("msvcr90.dll")) == 0)
        {
            // NOTE: Here we found it
            ATLTRACE2(atlTraceGeneral, 2, _T("msvcr90.dll version is %s\n"), _VersionInfoHelper::GetVersionString(_VersionInfoHelper::GetFileVersion(sPath)));
            break;
        }
    }
}

Attributed ATL: Accessing BLOB with ISequentialStream

Before attributed ATL was deprecated, it was a convenient way to access databases using attributed classes on top of OLEDB Consumer Templates. Does not it look nice?

[
    db_command("SELECT ServerData FROM Server WHERE Server = ?")
]
class CGetServerData
{
public:
    [ db_param(1) ] LONG m_nServer;
    [ db_column(1, length = "m_nDataLength") ] ISequentialStream* m_pDataStream; DBLENGTH m_nDataLength;
};

It worked great with Visual Studio .NET 2003 and it failed to work with later releases. There are questions on internet about the problem, but there few answers if any. As I recently had to convert a project from 2003 version of the compiler to Visual Studio 2008, the problem was finally to be resolved.

Read more »

Another third party DirectShow filter that may break your very own application

One of the DirectShow’s most important features is Intelligent Connect, which allows Filter Graph Manager to build graphs out of independent filters trying to connect them together including options to fall back to originally non-preferred alternatives and so on.

It is however important that filters are properly registered with the Filter Mapper. For the developers to do so, there are special guidelines for registering filters. Unfortunately it is not always the case that developers carefully take them into consideration, and so we have compatibility issues. In particular a faulty filter may break an application it is not intended to be used in in first place. Some examples were already mentioned: Ahead Nero NeResize Filter, FFDShow Video Decoder Filter, PICVideo MJPEG Decompressor Filter.

As we are moving on, the brilliant collection is expanding. New entry on the list:

MainConcept Color Space Converter Filter

Friendly Name: MainConcept Color Space Converter
File Name: mccsc.ax
File Version: 1.0.103.60203 (note that other versions might be hopefully free from this problem)
Merit: 0×00600000 (MERIT_NORMAL)

Symptoms: registers itself under higher merit and takes over standard Color Space Converter Filter. As such, might be used in various applications including those, where it is not supposed to appear. Does not fully implement functionality of the filter being replaced and can crash breaking expected operation of third party application.