NTFS Links: List junction points under certain directory

While NTFS junction points are powerful to relink files without duplicating data and/or moving between disks, they are treated as regular directories by most of software and it may unexpectedly result in conversion of a junction point into a regular directory with implied duplication of data and disk space waste.

This is a quick fix for the NTFS Links shell extension that allows to quickly list created junction points under certain directory, and delete if necessary. The update adds a property page Junction Points to NTFS non-UNC directory properties:

Directory Junction Points Property Page

This is a quick update, so be aware (also my TO DO list):

  • no Russian localization, sorry
  • context menu should also be given another item Open Containing Directory
  • does not work for root directories
  • list items should be OLE draggable
  • there should be a junction point validation feature that checks availability of substitution path and indicates result by an icon
  • I should remove the mess between “soft link” and”junction point” in favor of the latter

Release information:

DHCP Server: VoIP Configuration Server Address Options 66 and 150

Alax.Info DHCP Server was updated and received a new feature to send TFTP Server Name (DHCP option 66) and TFTP Server IP Addresses (DHCP option 150) so much required to automatically configure VoIP hardware.

DHCP Server TFTP Server Options

Option 150 is defined by internet draft “VoIP Configuration Server Address Option”:

   This memo documents existing usage for the "VoIP Configuration Server
   Address Option" (previously known as the "TFTP Server IP Address
   Option").  The option number currently in use is 150.  This memo
   documents the current usage of the option in agreement with RFC 3942
   [RFC3942], which declares that any pre-existing usages of option
   numbers in the range 128 - 223 should be documented and the working
   group will try to officially assign those numbers to those options.

Release information:

Visual Studio .NET 2008 freeze on opening a setup project

Some time ago I faced an annoying problem with a freeze of Visual Studio opening a solution with a Setup Project. I found that the problem was related to setup projects (.vdproj) that time and it was something with Visual Studio update, but I was of an opinion that Visual Studio .NET 2008 has problems opening projects created by version 2005. Compatibility or something… however the problem appeared that it cannot even create a new Setup Project with again a freeze.

Luckily, I found a hint on MSDN Forums, and although the solution/workaround was not detailed enough, it worked for me from the first guess. Here it goes:

  1. Start Component Services (dcomcnfg) from command line
  2. Right-click My Computer, and click Properties:

    Component Services, My Computer, Properties

    In the popped up window uncheck additional security box:

    My Computer Properties

It appears to be sufficient for the Visual Studio .NET 2008 to start loading .vdproj projects again.

MediaTools: HTTP Stream File Renderer Filter and more

In order to better troubleshoot network cameras and other devices, I added a new DirectShow filter to write HTTP response headers and body into a single file, one file (actually a pairs of files, the second file contains UTF-8 formatted HTTP response headers) per HTTP response.

While troubleshootting JPEG artefact issue with I used the following graph:

HTTP Stream File Renderer Filter in Filter Graph

which started M-JPEG streaming from a camera and had entire stream written into Response-01586228-0001-0001-Headers.txt (Headers) and Response-01586228-0001-0001.dat (Data) files, while parsed JPEG frames were also written into individual files and were available for comparison.

Other changes include:

  • new HTTP Stream File Renderer Filter (details are below)
  • attachable media types on internally used memory allocators, which enable filters to effectively reagree media types in running state
  • workaround for Panasonic BL-C140 camera (may be also helpful for other models), details here

There also seems to be a bug in Intel IPP 6.0 JPEG decoder that leaves bottom right image block incorrectly decoded, only when a sequence of images is decoded and the frame is not the first in the sequence.

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

Continue reading →

Two mouse clicks 7-Zip archives for a developer

I have been frequently troubleshooting remote systems and otherwise provide various temporary binary files to remote production sites with fixes or beta versions of new features etc. The software  is such that that customer sites have specific combination of hardware, configuration, hardware on LAN, software conflicts and there is a number of things that are very much easier troubleshooted directly on the production server, through remote connection. Typically I am using TightVNC and Windows Remote Desktop, sometimes LogMeIn, RAdmin and more rare alternatives (among such I would like to specially note TeamViewer).

Obviously except for released versions of binaries (which also exist in several versions from different configuration builds), there appear a number of intermediate files, DLLs and EXEs which are addressed to specific problems and fixes. The problem with multitude of different versions of the same DLL is widely known as DLL hell.

It is not actually a big hell since we are trying to follow simple rules:

  • DLLs should be backward compatible, or if the compatibility is ever broken, DLL version mismatch scenario should be handled as gracefully as possible
  • DLLs and other binaries should have VERSIONINFO resource
  • version information file version’s least significant number is incremented with each and every build; in particular this allows to keep privately program databases (PDB) and immediately find the corresponding database by file version
  • newer binaries should always have greated file version than older ones

The problem however has been that the typical process of building a temporary build of a library and uploading it to remote location required too many clicks. Considering a number of times I have been through these operations, an automation and a productivity tool should have appeared long ago. Finally this is solved by a shell extension that compresses binaries into a transferrable archive in two clicks:

Context Menu Shell Extension

Compression formats of 7-Zip (.7z), 7-ZIP SFX (.exe) and ZIP (.zip) are at user’s choice.

Continue reading →

Developer Goodies: ListResources to create an XML file from binary resources

At some point you might need to start paying special care for resources. Why? Perhaps there might be a number of reasons, I had to when I was dealing with first OEM versions of software and then internationalization. The whole idea is to let development team keep on working on regular version of software, in English language, while build OEM versions and localized versions of software by only manipulation with resources. It is an extremely important aspect of development because engineers always have full hands of work to do and there is no justification for getting extra work for them to deal with.

The first stage is development of regular English version of software and then other people replace resources to achieve desired branding (strings, titles, messages, icons, logos, version information, digital signatures; localized version whether they are resource duplicates for other languages or satellite DLLs), synchronize translations, prepare setup and distribution files.

One of the really simple and useful utilities on this way is the one that converts linked resources into a human readable file, so that it is possible to search for specific string through all resources of a binary (and actually all resources of the package if a batch makes such text files out of all binaries and then Find in Files Visual Studio .NET IDE feature is used).

ListResources writes an XML formatted file and prints infomration about:

  • resource types, identifiers and languages
  • extended information about:
    • menus RT_MENU
    • dialog templates RT_DIALOG
    • string tables RT_STRING
    • message tables RT_MESSAGETABLE
    • version information RT_VERSION
C:\ListResources "%WINDIR%\system32\winhttp.dll" >winhttp.xml

Continue reading →

More on DirectShow Filter Graph Spy

Having DirectShow Filter Graph Spy installed in the system, I noticed a new and weird effect that when Media Player Classic plays a list of files and each MP3 file being currently decoded shows decoder’s system tray icon, a switch to a new file leaves an old icon in place and adds a new icon for a new decoder.  I thought this might be also a decoder’s problem which I also recently updated to a new version, but then I noticed other artifacts, with other software and again with Media Player Classic, that if I drop a new file onto the player and it starts playing it, old file is still being played as if player just releases all referenced to the graph and never calls IMediaControl::Stop to force stop of playback.

It was clear at that point that it is related to filter graph spy and the problem needs a fix. The problem definitely looked like the spy leave outstanding references to the filter graph and when the application releases graph and it is supposed to be automatically destroyed, it is still being alive and possibly, such as in case of Media Player Classic, even running.

The first clue was that being published to running object table (ROT), the object gets more than one additional reference on it and as such it never gets removed from ROT until application terminates as ROT keeps a reference to the graph and there is noone to remove it. By original design spy published filter graph on ROT and removed one reference immediately after that to compensate the ROT’s reference (one only) making it a weak reference. So when all references are released from the filter graph but ROT reference, the graph gets destroyed and in FinalRelease class on the COM object we re-add the reference back and automatically remove the object from ROT as well. The whole scheme works in assumption that ROT adds one reference only, if there are more then the object is referenced by the ROT forever.

Debugging however showed that ROT adds a single reference and there is no problem from this side. However I immediately noticed  another weird behavior in the same method FinalConstruct. An underlying (real) filter graph object, i.e. CFilterGraph from quartz.dll, is adding a reference on the outer COM object when being queried for a private interface from implicit (also known as main, raw) IUnknown when created as aggregated object. And it is not exactly the behavior one would expect from aggregated object because it basically break proper reference counting. I realize that aggregating is a rather rare technique and DirectShow COM base is one of the very first COM bases at all which then stopped being developed, so perhaps this problem was not identified on time and later left unfixed at all, so in present situation there should rather be a workaround.

It is also worth mentioning that there are two scenarios involved. My CSpy object creates DirectShow CFilterGraph as an aggregated object. And CSpy in its turn may be created as aggregated too. For example, Windows Media Player creates (as most applications in this universe do) filter graph object the regular way, as a standalone COM object. However it appears that Media Player Classic creates filter graph as aggregated, for whatever it needs it for. Because of the discovered problem inner CFilterGraph adds an outstanding reference on the top level “controlling IUnknown”, which is either CSpy’s private IUnkown in case of Windows Media Player, or higher level IUnknown in case of Media Player Classic.

So the proper workaround is to release unwanted references from controlling unknown rather than self:

CComPtr<IUnknown> pUnknown;
ATLENSURE_SUCCEEDED(pClassFactory->CreateInstance(pControllingUnknown, __uuidof(IUnknown), (VOID**) &pUnknown));
// NOTE: DirectShow FilterGraph is incorrectly implementing COM aggregation adding outer reference to interfaces queried from private IUnknown
CComQIPtr<IFilterGraph2> pFilterGraph2 = pUnknown;
ATLENSURE_THROW(pFilterGraph2, E_NOINTERFACE);
pFilterGraph2.p->Release(); // <<--------------------------

It looked like the problem is finally worked around but in aggregated creation scenario it brought another problem up. Since instantiation of inner CFilterGraph takes place in FinalConstruct and CSpy is also being instantiated as aggregated, it appears that outer COM object is sensible to manipulation with its reference counter. CFilterGraph added a reference it should not, CSpy released it in compensation but on this early stage the compensating Release might zero reference counter and might initiate unexpected object destruction. It is not necessarily this way as it depends on outer COM object base, but it seems that Media Player Classic does not do DECLARE_PROTECT_FINAL_CONSTRUCT or its equavalent and things go the worst scenario.

CSpy is an inner object and we don’t have any external instance to hold a temporary reference for us while outer COM object is being created, so a workround for this is to temporarily hold a circular reference to an outer object to let it complete its instanatiation and pass another reference higher up to the controlling application. At which point we are going to be safe to release the temporary reference and normalize reference counters.

if(m_bIsAggregated)
{
    pControllingUnknown.p->AddRef();
    const ULONG nReferenceCount = pControllingUnknown.p->Release();
    if(nReferenceCount == 1)
        m_pTemporaryUnknown = pControllingUnknown;
}

The only thing is left is to release the temporary reference early enough, but we have a filter graph, don’t we? What is typically done with a filter graph, adding a filter right? And it is a controlling application which has its own reference, who adds filters so we are safe to release temporary reference in IFilterGraph::AddFilter or IGraphBuilder::AddSourceFilter (actually it would not hurt to add this in other methods as well):

STDMETHOD(AddFilter)(IBaseFilter* pFilter, LPCWSTR pszName) throw()
{
    _Z4(atlTraceCOM, 4, _T("pszName \"%s\"\n"), CString(pszName));
    ReleaseTemporaryUnknown(); // <<--------------------------
    return m_pInnerFilterGraph2->AddFilter(pFilter, pszName);
}

Additionally, the spy also implements now IMediaControl interface and traces calls to log file, it is convenient.

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

reg-FilterGraphSpy.dll.bat and unreg-FilterGraphSpy.dll.bat files in SVN are convenient batch files to register and unregister the spy with the operating system.