Tuesday, October 27, 2009

Found my first bug in Windows 7 APIs: PdhBrowseCounters requires Elevation

I just found out the following, which does not seem to be documented anywhere:

The Windows API has a function for displaying a dialog that lets the user select a specific performance counter from all counters available on the local or a remote computer. The dialog is used by perfmon.exe, for example, and looks like this:



This dialog is instantiated by calling the API function PdhBrowseCounters. This works well enough - the dialog displays all objects, counters and instances, the user is able to select a specific counter and clicks on "OK".

The bad thing is that PdhBrowseCounters always returns an empty string instead of the counter path selected by the user. This happens if the application does not run elevated (i.e. with admin rights).

I have two problems with that:
  1. It is documented nowhere that elevation is required for PdhBrowseCounters.
  2. Why is elevation necessary? The user can see all objects, counters and their instances without elevation, so why not return the path selected?
For theses reasons I think this is a bug.

By the way, how does perfmon.exe work around this? It requires elevation...

I have tested this on Windows 7 x64 German RTM with all patches till 10/27/2009.

And here is the code I used for testing (from my free tool DiskLED):

void CDialogConfig::OnBnClickedCounterpathSelect()
{
PDH_STATUS pdhStatus;
PDH_BROWSE_DLG_CONFIG oPDHBrowseDialogCfg;
TCHAR sBuffer[PDH_MAX_COUNTER_PATH + 1];

// Zero memory structures
ZeroMemory (&oPDHBrowseDialogCfg, sizeof (PDH_BROWSE_DLG_CONFIG));

// Initialize the path buffer
ZeroMemory (&sBuffer, sizeof (sBuffer));
//_tcscpy_s (sBuffer, PDH_MAX_COUNTER_PATH + 1, m_sCounterPath);

// Initialize the browser dialog window settings
oPDHBrowseDialogCfg.bIncludeInstanceIndex = FALSE;
oPDHBrowseDialogCfg.bSingleCounterPerAdd = TRUE;
oPDHBrowseDialogCfg.bSingleCounterPerDialog = TRUE;
oPDHBrowseDialogCfg.bLocalCountersOnly = FALSE;
oPDHBrowseDialogCfg.bWildCardInstances = TRUE;
oPDHBrowseDialogCfg.bHideDetailBox = TRUE;
oPDHBrowseDialogCfg.bInitializePath = FALSE;
oPDHBrowseDialogCfg.bDisableMachineSelection = FALSE;
oPDHBrowseDialogCfg.bIncludeCostlyObjects = FALSE;
oPDHBrowseDialogCfg.bShowObjectBrowser = FALSE;
oPDHBrowseDialogCfg.hWndOwner = m_hWnd;
oPDHBrowseDialogCfg.szReturnPathBuffer = sBuffer;
oPDHBrowseDialogCfg.cchReturnPathLength = sizeof (sBuffer) / sizeof (TCHAR);
oPDHBrowseDialogCfg.pCallBack = NULL;
oPDHBrowseDialogCfg.dwCallBackArg = 0;
oPDHBrowseDialogCfg.CallBackStatus = ERROR_SUCCESS;
oPDHBrowseDialogCfg.dwDefaultDetailLevel = PERF_DETAIL_WIZARD;
oPDHBrowseDialogCfg.szDialogBoxCaption = TEXT ("Select a counter for DiskLED");

// Display the counter browser window. The dialog is configured
// to return a single selection from the counter list.
pdhStatus = PdhBrowseCounters (&oPDHBrowseDialogCfg);
if (pdhStatus != ERROR_SUCCESS)
{
if (pdhStatus != PDH_DIALOG_CANCELLED)
{
m_pMainFrame->LogError (TEXT ("OnBnClickedCounterpathSelect"), TEXT ("PdhBrowseCounters"), pdhStatus);
}
}
else
{
m_sCounterPath = sBuffer;

// Update the dialog with the new data
UpdateData (FALSE);
}
}

Saturday, October 24, 2009

Radio Buttons in MFC (Visual Studio 2008 / C++)

This is a quick and dirty description of how to use radio buttons in MFC, written because I could not find this information in a single place on the web.

In the dialog editor:
  • Create a new group with the group box control and set a meaningful caption
  • Add radio button controls inside the group
  • The radio buttons must have ascending tab order
  • The first radio button (in tab order) must have the property "Group" set to True
  • All other radio buttons must have the property "Group" set to False
It should look similar to this:



In the header file defining the dialog class:
  • Add a member variable of type int that will store which radio button is selected (none: -1, first: 0, second: 1, and so on).
    Example:
    int m_nLEDType;
In the cpp file implementing the dialog class:
  • In the constructor initialize the member variable (with 0)
    Example:
    CDialogConfig::CDialogConfig(CMainFrame* pMainFrame) : CDialog(CDialogConfig::IDD, pMainFrame), m_nLEDType(0)
  • In DoDataExchange add a call to DDX_Radio similar to the following (where IDC_RADIO_LEDTYPE1 is the ID of the first radio button):
    DDX_Radio(pDX, IDC_RADIO_LEDTYPE1, m_nLEDType);
When you want to read which radio button is selected:
  • Call UpdateData with a parameter of true (indicates reading):
    UpdateData (TRUE);
  • After UpdateData has been called, the member variable (m_nLEDType in this example) has the current state of the buttons.
When you want to select one of the buttons programmatically:
  • Set the member variable to the correct value (none selected: -1, first button selected: 0, second button selected: 1, and so on)
  • Call UpdateData with a parameter of false (indicates writing):
    UpdateData (FALSE);

Wednesday, October 21, 2009

On the Usefulness of self-extracting Archives

I just found out that the new firmware version 2.1 for my digital camera Panasonic Lumix LX3 has been published. Very nice, especially the speed improvements.

So I downloaded the firmware, a self-extracting archive, started the executable and had it uncompress the actual firmware file (a .bin file). Interestingly, the "compressed" .exe file is larger than the uncompressed .bin file:



So why, o gods of common sense, make the file available as an executable, which might even be blocked by company policy or virus scanners?

Friday, September 25, 2009

Support Case: Windows Hangs During Shutdown and Weird USB Problems

A couple of months ago, my wife's laptop started displaying symptoms of old age. More often than not, it would not shut down properly, but remain indefinitely in that 99% finished state Windows enters right before the computer is actually turned off. And there were other anomalies: the (USB) mouse would cease to function intermittently, and sometimes USB flash drives would not be recognized.

After she had suffered from these problems long enough, my wife opened a support case (with me, of course). She was most concerned with data loss because of Windows not shutting down properly at least once a day, so I started out with a search for a solution to that problem. Since I hoped this would be a software rather than hardware failure, I crossed my fingers this would turn out to be a more generally applicable issue. One, that would be described in the Microsoft Knowledge Base, along with a nice and easy solution, that is.

Googling for "site:support.microsoft.com windows xp shutdown hang" produced several interesting results, but none seemed to apply to my wife's specific situation. Then I clicked on the ninth URL, Computer does not shut down properly if Selective Suspend is enabled. I had no clue what "selective suspend" could be. As it turned out, it is an energy saving feature that allows the operating system to selectively switch off USB ports individually. The article recommended to turn this off:


  1. Right-click My Computer, click Properties, click the Hardware tab, and then click Device Manager.

  2. Double-click Universal Serial Bus controllers to expand it, right-click USB Root Hub, and then click Properties.

  3. Click the Power Management tab.

  4. Click to clear the Allow the computer to turn off this device to save power check box, and then click OK.



This sounded as if all problems could be solved with a few simple clicks. And indeed, that is how it was. Once the OS did not try to selectively suspend USB ports, the problems went away.

You may wonder why selective suspend just stopped working one day, after it had not caused any problems for years. I do, too, but frankly I do not care. The problem has gone away and fixing it did not even cost me money. In this case, that is enough for me.

Monday, September 14, 2009

How to Convert Videos from Panasonic's Lumix DMC-TZ7 from MOV to MPEG-2

This is an update to my post on how to convert Quicktime videos in MOV format to MPEG-2.

Recently a friend of mine asked me how my conversion script could be used for a slightly different camera model. While I use it for the videos from my Lumix LX3, he owns a TZ7, which uses slightly different parameters that make it necessary to tweak the script. Luckily those changes are small.

Differences:

The LX3 records 24 fps, the TZ7 30 fps. The former only has one audio channel, the latter has two (stereo). Those are the only differences I know of.

With this in mind, we know how to tweak the script.

Changes to the conversion script:

In the variables section at the top of the script, replace the original lines with the following:

set FRAMERATE=30
set AUDIO_BITRATE=224
set AUDIO_CHANNELS=2

That should be all.

Sample conversion output:

Here is some sample output I got when converting a 15s video from my friend's TZ7:

MEncoder 1.0rc2-4.2.1 (C) 2000-2007 MPlayer Team
CPU: Intel(R) Core(TM)2 Duo CPU T8100 @ 2.10GHz (Family: 6, Model: 23, Stepping: 6)
CPUflags: Type: 6 MMX: 1 MMX2: 1 3DNow: 0 3DNow2: 0 SSE: 1 SSE2: 1
Compiled with runtime CPU detection.
success: format: 0 data: 0x0 - 0x3842de2
ISO: File Type Major Brand: Original QuickTime
Quicktime/MOV file format detected.
[mov] Video stream found, -vid 0
[mov] Audio stream found, -aid 1
VIDEO: [jpeg] 1280x720 24bpp 30.000 fps 0.0 kbps ( 0.0 kbyte/s)
[V] filefmt:7 fourcc:0x6765706A size:1280x720 fps:30.00 ftime:=0.0333
==========================================================================
Opening audio decoder: [pcm] Uncompressed PCM audio decoder
AUDIO: 16000 Hz, 2 ch, s16be, 512.0 kbit/100.00% (ratio: 64000->64000)
Selected audio codec: [pcm] afm: pcm (Uncompressed PCM)
==========================================================================
PACKET SIZE: 2048 bytes, deltascr: 43885
MPEG MUXER, patching resolution to 1280x720 framerate to 30 fps aspect ratio to 16/9
Opening video filter: [expand osd=1]
Expand: -1 x -1, -1 ; -1, osd: 1, aspect: 0.000000, round: 1
==========================================================================
Opening video decoder: [ffmpeg] FFmpeg's libavcodec codec family
Selected video codec: [ffmjpeg] vfm: ffmpeg (FFmpeg MJPEG decoder)
==========================================================================
Limiting audio preload to 0.4s.
Increasing audio density to 4.
VDec: vo config request - 1280 x 720 (preferred colorspace: Planar YV12)
VDec: using Planar YV12 as output csp (no 3)
Movie-Aspect is undefined - no prescaling applied.
videocodec: libavcodec (1280x720 fourcc=3267706d [mpg2])
[VE_LAVC] High quality encoding selected (non-realtime)!
Writing header...
INITV: 0.200, 0.167, fps: 30.000
Pos: 0.8s 24f ( 0%) 2.21fps Trem: 0min 0mb A-V:0.031 [0:224]
BUFFER UNDEFLOW at stream 0, raising muxrate to 11088 kb/s, delta_scr: 39896

BUFFER UNDEFLOW at stream 0, raising muxrate to 12196 kb/s, delta_scr: 36269

BUFFER UNDEFLOW at stream 0, raising muxrate to 13416 kb/s, delta_scr: 32971

BUFFER UNDEFLOW at stream 0, raising muxrate to 14758 kb/s, delta_scr: 29974

BUFFER UNDEFLOW at stream 0, raising muxrate to 16233 kb/s, delta_scr: 27249

BUFFER UNDEFLOW at stream 0, raising muxrate to 17857 kb/s, delta_scr: 24772

BUFFER UNDEFLOW at stream 0, raising muxrate to 19643 kb/s, delta_scr: 22520
Pos: 15.0s 450f ( 0%) 11.10fps Trem: 0min 0mb A-V:0.033 [11959:224]
Flushing video frames.
Writing index...

Overhead: 1.560% (345455 / 22147729)
Writing header...

Video stream: 11959.702 kbit/s (1494962 B/s) size: 22424441 bytes 15.000 secs 450 frames

Audio stream: 224.000 kbit/s (28000 B/s) size: 420000 bytes 15.000 secs

Monday, August 24, 2009

Moving the Firefox Cache Directory and Profile Separately

On my computers I try to keep my data on its own partition, well away from program files and other stuff that gets (re-) created anyway when I install a new OS. Separation of data from all the other stuff is an old principle and makes it possible to just delete the OS partition whenever you feel like it without giving the safety of your precious data too much thought.

Moving the Firefox Profile to a Different Drive

Most programs store their settings in the user user profile, which is typically located in the OS partition (on Windows Vista and 7 the location would be C:\Users\Username). While I do not bother with most program's settings, some applications I configure and tune heavily. Needless to say, I do not want to lose that config work when I change the OS along with the user profile. That makes it necessary to move the config data from the user profile to my data partition. How exactly to accomplish this move is different from application to application. With Firefox (at least from version 2.x to 3.5.x) it goes like this:
  1. Open the file profiles.ini which is located in your user profile (%userprofile%\AppData\Roaming\Mozilla\Firefox).
  2. By default there is only once section [Profile0] that contains the location of your default (and probably only) profile.
  3. Change the entry IsRelative to 0
  4. Enter the absolute Path to where you want to Firefox profile to be stored
Your profiles.ini should now look similar to this:

[General]
StartWithLastProfile=1

[Profile0]
Name=default
IsRelative=0
Path=D:\Data\Programs\Firefox\Notebook

With the entire profile on your data partition, you can now safely delete drive C: without losing your Firefox configuration. Once you reinstall your OS, you just have to install Firefox, repeat the steps above (point it to its profile on your data drive) and you have everything back, including all plugins.

Moving the Cache Directory Back

There is only one problem. The Firefox profile contains the Cache subdirectory, and cached data is not what I regard as worthy to occupy space on my backup solution. So why not just move the cache back into the user profile, preferably the non-roaming local part of it?

This is the way to do it:
  1. In Firefox open the configuration page by typing about:config into the address bar
  2. Right-click into the window and create a new string
  3. Enter the name browser.cache.disk.parent_directory
  4. Enter the path to the cache directory
Please note that Firefox appends "Cache" to the path you enter.

Unfortunately Firefox does not expand environment variables for the cache path. I would have preferred to use a path like "%userprofile%\AppData\Local\Mozilla\Firefox", but such a path is ignored by the application. Instead I had to use the absolute path to my user profile, which I do not like very much because user names can change and with them changes the path to the profile.

Once you have made sure that Firefox uses the new cache path, do not forget to delete the old cache location.

Saturday, August 1, 2009

How to Easily Fix Wrong Timestamps on Files from your Digital Camera

Ever had the situation where by some mishap the file times on your digital images got changed and there seemingly was no way of knowing when a picture was taken any more? In most cases that can be remedied easily.

Most digital cameras write an astounding number of things directly into the image file, into a special section called EXIF. Among that information is the date and time the image was taken! You can check if your images have this information by opening a file in IrfanView and pressing "i".

Now the hard part. How to transfer the time stored in the file to the file itself? With the right tool, it is amazingly eazy. Download the great ExifTool and use the following command to have the times of all image files of an entire directory corrected:

"exiftool(-k).exe" "-DateTimeOriginal>FileModifyDate" "Path to a directory"