Published by alax on 22 Nov 2008

Time Zone Information & Monitor Information

I am sharing a couple of utilities to be able to quick check system settings. TimeZoneInformation prints in a human friendly style TIME_ZONE_INFORMATION structure as reported by Windows through GetTimeZoneInformation API.

TIME_ZONE_INFORMATION:
.Bias: -120
.StandardName: FLE Standard Time
.StandardDate: { .wYear 0, .wMonth 10, .wDay 5, .wDayOfWeek 0, .wHour 4, .wMinute 0, .wSecond 0, .wMilliseconds 0 }
.StandardBias: 0
.DaylightName: FLE Daylight Time
.DaylightDate: { .wYear 0, .wMonth 3, .wDay 5, .wDayOfWeek 0, .wHour 3, .wMinute 0, .wSecond 0, .wMilliseconds 0 }
.DaylightBias: -60
[...]

A Visual C++ .NET 2008 source code is available from SVN, release binary included.

And the second utility is MonitorInformation to print multi-monitor related information again as reported by Windows, GetSystemMetrics and EnumDisplayMonitors APIs.

System Metrics:
  SM_XVIRTUALSCREEN: 0
  SM_YVIRTUALSCREEN: 0
  SM_CXVIRTUALSCREEN: 1680
  SM_CYVIRTUALSCREEN: 1050
  SM_CMONITORS: 1
  SM_SAMEDISPLAYFORMAT: 1

Monitor 0 at (0, 0) - (1680, 1050):
  Coordinates (rcMonitor): (0, 0) - (1680, 1050)
  Work Area (rcWork): (0, 0) - (1680, 1026)
  Flags (dwFlags): 0x1
  Device Name (szDevice): \\.\DISPLAY1

A Visual C++ .NET 2008 source code is available from SVN, release binary included.

Published by alax on 19 Nov 2008

Multiple Windowless Video Mixing Renderers (VMR9) Sample

This is a begged MFC code for multiple windowless video renderers. MFC project, two independent video renderers hosted by the same parent window (actually through owned controls but this makes no major difference), VMR9 in windowless mode.

There are no WM_PAINT/WM_ERASEBKGND handlers, IVMRWindowlessControl9::RepaintVideo calls and other basically required code, instead a minimalistic snippet to make video rendered the requested way.

A Visual C++ .NET 2008 source code is available from SVN, release binary included.

Published by alax on 11 Nov 2008

DirectSound play buffer notification (IDirectSoundNotify8)

IDirectSoundNotify8 is an interface to get notified on playback on capture audio buffer reaching certain position in the buffer. It is a must thing when implementing ring buffers with new data continuously added to the buffer for seamless playback (continuously copied from in case of capture).

This project is a minimalistic C++ sample code to illustrate the API. To initialize the DirectSound subsystem it is required to provide a window handle, which is created using ATL’s CWindowImpl (CMessageOnlyWindowImpl).

...
ATLENSURE_SUCCEEDED(DirectSoundCreate8(NULL, &pDirectSound8, NULL));
...
ATLENSURE_SUCCEEDED(pDirectSound8->SetCooperativeLevel(Window, DSSCL_PRIORITY));
...
ATLENSURE_SUCCEEDED(pDirectSound8->CreateSoundBuffer(&BufferDescriptor, &pDirectSoundBuffer, NULL));
...
CComQIPtr<IDirectSoundNotify8, &IID_IDirectSoundNotify8> pDirectSoundNotify8 = pDirectSoundBuffer;
...
ATLENSURE_SUCCEEDED(pDirectSoundNotify8->SetNotificationPositions(g_nPositionCount, pPositionNotify));
ATLENSURE_SUCCEEDED(pDirectSoundBuffer->Play(0, 0, DSBPLAY_LOOPING));

Continue Reading »

Published by alax on 14 Oct 2008

ProcessSnapshot to take a snapshot of process modules, threads, stacks and performance

While troubleshooting released application on remote production site, it is very useful to grasp a state of the process for further analysis. There are several scenarios in which the following information about process state is helpful:

  • modules (DLLs) loaded into process and their versions
  • threads and their call stacks
  • process and thread performance

An utility ProcessSnapshot takes advantage of Debugging Tools API (dbghelp.dll - note the dialog also displays DLL version in the right bottom corner) and writes this helpful information to text file and it can also take a sequence of the snapshots to compare thread performance and/or stacks and check the difference.

The generated file is in the directory of the utility application and looks like:

Snapshot
  System Time: 10/14/2008 8:46:33 PM
  Local Time: 10/14/2008 11:46:33 PM

Performance
  Creation System Time: 10/14/2008 8:46:28 PM
  Kernel Time: 0.094 s
  User Time: 0.031 s

Modules

  Module: ProcessSnapshot.exe @00400000
    Base Address: 0x00400000
    Base Size: 0x0005b000 (372736)
    Name: ProcessSnapshot.exe
    Path: D:\Projects\Utilities\ProcessSnapshot\Release\ProcessSnapshot.exe
    Product Version: 1.0.0.1
    File Version: 1.0.0.125

  Module: ntdll.dll @7c900000
    Base Address: 0x7c900000
    Base Size: 0x000af000 (716800)
    Name: ntdll.dll
    Path: C:\WINDOWS\system32\ntdll.dll
    Product Version: 5.1.2600.5512
    File Version: 5.1.2600.5512
[...]

Threads

  Thread: 3824
    Base Priority: 8
    Creation System Time: 10/14/2008 8:46:57 PM
    Kernel Time: 0.063 s
    User Time: 0.031 s
    Call Stack
      ntdll!7c90e4f4 KiFastSystemCallRet (+ 0) @7c900000
      USER32!7e4249c4 GetCursorFrameInfo (+ 460) @7e410000
      USER32!7e424a06 DialogBoxIndirectParamAorW (+ 54) @7e410000
      USER32!7e4247ea DialogBoxParamW (+ 63) @7e410000
      ProcessSnapshot!00403f45 ATL::CDialogImpl<CMainDialog,ATL::CWindow>::DoModal (+ 67) [c:\program files\microsoft visual studio 9.0\vc\atlmfc\include\atlwin.h, 3478] (+ 28) @00400000
      ProcessSnapshot!00403b6f CProcessSnapshotModule::RunMessageLoop (+ 74) [d:\projects\utilities\processsnapshot\processsnapshot.cpp, 67] (+ 0) @00400000
      ProcessSnapshot!004049b9 ATL::CAtlExeModuleT<CProcessSnapshotModule>::Run (+ 17) [c:\program files\microsoft visual studio 9.0\vc\atlmfc\include\atlbase.h, 3552] (+ 0) @00400000
      ProcessSnapshot!004041c3 ATL::CAtlExeModuleT<CProcessSnapshotModule>::WinMain (+ 48) [c:\program files\microsoft visual studio 9.0\vc\atlmfc\include\atlbase.h, 3364] (+ 5) @00400000
      ProcessSnapshot!00434477 wWinMain (+ 5) [*d:\projects\utilities\processsnapshot\release\processsnapshot.inj:5, 14] (+ 0) @00400000
      ProcessSnapshot!00415058 __tmainCRTStartup (+ 274) [f:\dd\vctools\crt_bld\self_x86\crt\src\crt0.c, 263] (+ 27) @00400000
      !00360033

Continue Reading »

Published by alax on 29 Sep 2008

/GS Buffer Security Check

Microsoft C++ compiler offers a buffer security check option since quite a long ago. It adds so called “security cookies” onto stack and checks them to be not modified by code in order to early-detect stack buffer overflow conditions. The compiler option /GS is enabled by default in Release configurations and is not applicable to debug code (which has optimizations disabled).

Here comes the trouble: release code might show unexpected message box “Buffer overrun detected!”. I have never seen such after years of development and tens of thousands of lines of code written, but luckily there are colleagues who can contribute a challenging issue to investigate.

The message is shown through C runtime’s __crtMessageBoxA function and is not only annoying and angering the customer, it also stops application operation and terminates it:

By default, an application that fails a security check displays a dialog box that states “Buffer overrun detected!” When the dialog box is closed, the application terminates.

However it is possible to override this behavior:

The CRT library offers the developer an option to use a different handler that would react to the buffer overrun in a manner more sensible to the application. The function, __set_security_error_handler, is used to install the user handler by storing the user-defined handler in the user_handler variable

In my case we would be overriding this to trace call stack at the issue point. However, let us see first what other conditions might cause a message box. CRT source has the following occurrences for__crtMessageBoxA:

  • assert.c - assertion failure, which normally only applies to debug code
  • crt0msg.c - _NMSG_WRITE function, typically for a fatal run time error messages
  • crtlib.c - _CRTDLL_INIT fails to start on a Win32s system (VER_PLATFORM_WIN32s)
  • crtmbox.c - implementation of __crtMessageBoxA (which is, among other things binds to API functions on runtime instead of static linking)
  • dbgrpt.c - CrtMessageWindow function, applies to debug code only
  • secfail.c - __security_error_handler function, the /GS thing

So it appears that hopefully /GS failure is the only surprising condition to display an unexpected message box.

OK, let us just see what we got finally here. Using the MSDN sample code and overriding default check failure handler:

int main()
{
	_set_security_error_handler(report_failure); // <<---------------- Override
	// declare buffer that is bigger than expected
	char large_buffer[] = "This string is longer than 10 characters!!";
	vulnerable(large_buffer);
}

Private handler is:

void __cdecl report_failure(int code, void*)
{
	ATLTRACE2(atlTraceGeneral, 0, _T("Security Error Handler: Code %d\n"), code);
	CONTEXT Context = { CONTEXT_CONTROL };
	if(GetCurrentThreadContext(&Context))
		CDebugTraceCallStack::TraceCallStack(Context);
}

and finally output:

BufferSecurityCheckSample.cpp(20): report_failure: Security Error Handler: Code 1
  BufferSecurityCheckSample!0x00402a2d report_failure (+ 125) [c:\buffersecuritychecksample\buffersecuritychecksample.cpp, 22] (+ 10) @00400000
  BufferSecurityCheckSample!0x00403d56 __security_error_handler (+ 48) [f:\vs70builds\6030\vc\crtbld\crt\src\secfail.c, 79] (+ 6) @00400000
  BufferSecurityCheckSample!0x00402e1d report_failure (+ 25) [f:\vs70builds\6030\vc\crtbld\crt\src\secchk.c, 117] (+ 9) @00400000
  BufferSecurityCheckSample!0x0040142c vulnerable (+ 44) [c:\buffersecuritychecksample\buffersecuritychecksample.cpp, 36] (+ 11) @00400000
  BufferSecurityCheckSample!0x00404019 mainCRTStartup (+ 371) [f:\vs70builds\6030\vc\crtbld\crt\src\crt0.c, 259] (+ 18) @00400000
  kernel32!0x7c817067 RegisterWaitForInputIdle (+ 73) @7c800000

The log file would immediately show the source of the run time problem.

See Also:

Published by alax on 06 Sep 2008

ATL Registration Script

Since ATL version 3, and actually it probably existed even since even earlier time, I have seen Microsoft Visual Studio (and its predecessor Visual C++) generating .RGS registration script with hardcoded CLSID value, ProgID values and other strings entered through IDE wizard. While it seems to work nice at the moment of generation, it still gives the problem to lose sync between identifiers if code is copied between projects or a different way. It might be an oversight originally, but was not it the obvious thing to do later to avoid possible typos of inaccurate user? Microsoft Visua Studio 2008 still generates the same code.

Previous versions of development environment offered attributed code option which in fact took care of this problem very well. Although there has been a lot of negative feedback written about C++ attributes, this was a kind of problem attributes left no chances to break: CLSID was specified once only in C++ COM class attribute and the rest of the deal was generated automatically, including IDL and registration sequence.

It is especially unclear why it was left this way because internal ATL classes already have all necessary capabilities to process wildcards. For example, default .RGS script contains an entry for COM class type library, HKCR\CLSID\{…} key, “TypeLib” value. Why would hardcode it if it can be specified through a replacement:

HKCR
{
	NoRemove CLSID
	{
		ForceRemove %CLSID% = s '...'
		{
			'TypeLib' = s '%LIBID%'

And the replacement is so easily added overriding CAtlModule’s virtual AddCommonRGSReplacements:

class CFooModule :
	public CAtlDllModuleT<CFooModule>
{
...
// CAtlModule
	HRESULT AddCommonRGSReplacements(IRegistrarBase* pRegistrar) throw()
	{
		_ATLTRY
		{
			ATLENSURE_SUCCEEDED(__super::AddCommonRGSReplacements(pRegistrar));
			ATLASSERT(!IsEqualGUID(m_libid, GUID_NULL));
			ATLENSURE_SUCCEEDED(pRegistrar->AddReplacement(L"LIBID", StringFromIdentifier(m_libid)));
		}
		_ATLCATCH(Exception)
		{
			return Exception;
		}
		return S_OK;
	}

I thought it would be implemented natively in ATL long ago, along with per-coclass replacements like %CLSID%.

This is how I like my registration script:

HKCR
{
	%PROGID% = s '%DESCRIPTION%'
	{
		CLSID = s '%CLSID%'
	}
	%VIPROGID% = s '%DESCRIPTION%'
	{
		CLSID = s '%CLSID%'
		CurVer = s '%PROGID%'
	}
	NoRemove CLSID
	{
		ForceRemove %CLSID% = s '%DESCRIPTION%'
		{
			ProgID = s '%PROGID%'
			VersionIndependentProgID = s '%VIPROGID%'
			ForceRemove 'Programmable'
			InprocServer32 = s '%MODULE%'
			{
				val ThreadingModel = s 'Both'
			}
			TypeLib = s '%LIBID%'
		}
	}
}

Published by alax on 27 Aug 2008

How To: Take care of DirectShow filters that impose unreasonable requirements

Although I personally have no experience with tricky DirectShow filters that decide on possibility of connection not only looking at media type and other capabilities, there has been a number of cases mentioned that certain video decoders will only connect to renderers or video renderers in order to avoid interception of decoded data.

It was recently mentioned that one of such filters checked Misc Flags obtained through IAMFilterMiscFlags interface to make sure it is connected to renderer downstream. Before we proceed, let us make it clear that it is silly and can only protect from beginner, a complete newbie. At the very least it should have checked peer filter’s CLSID and compare against white list of stock video renderer: Video Renderer, Video Mixing Rendeder 7, Video Mixing Rendeder 9, Enhanced Video Renderer. A custom video renderer or even just a transformation filter with a renderer flag would be able to receive decoded data and make it available for any further processing.

What I am going to do is to take Sample Grabber Filter as a base and make a new filter from it which will only connect to renderer (it will check the flags as described above). Then another filter, which will also use Sample Grabber Filter base, will accurately fool the first one and connect to output of the first filter and will render video to complete the graph.

Continue Reading »

Next »