How to get known folder path (Windows Vista/7)?

 
Windows Vista and above supports independent software vendors (ISV) to add support for custom known folder locations. Previously a fixed set of IDs were provided to use with SHGetFolderPath, SHGetFolderLocation and SHSetFolderPath APIs.
For adding this flexibility, the known file APIs has been rename and designed with COM Interfaces.
New Shell APIs and COM Interfaces are introduced to replace the old Shell APIs

New Function Replaces COM Equivalent
SHGetKnownFolderPath SHGetFolderPath IKnownFolder::GetPath
SHGetKnownFolderIDList SHGetFolderLocation IKnownFolder::GetIDList
SHSetKnownFolderPath SHSetFolderPath IKnownFolder::SetPath

Old APIs were using CSIDL for representing the known location identifier. This has been replaced by KNOWFOLDERID. However Windows Vista and 7 still supports CSIDL and associated APIs for compatibility reasons. The new applications has to use the new APIs or COM Interface. When using both COM/New Shell API, you’ve to ensure that CoTaskMemFree function is called to release the output resources. Otherwise memory leak may occur. Also don’t call any other memory release function like free or delete operator. It may cause undefined behavior

How to Enumerate All Known Folders?

void EnumerateAllKnownFolders(CStringArray& strArray)
{
	CStringArray strPathRet;
	IKnownFolderManager* pkfm = NULL;
	HRESULT hr = CoCreateInstance(CLSID_KnownFolderManager, NULL,
		CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pkfm));

	if( SUCCEEDED(hr))
	{
		KNOWNFOLDERID* rfid;
		UINT uCount = 0;

		if( FAILED( pkfm->GetFolderIds( &rfid, &uCount )))
			return;

		for (UINT uIdx = 0; uIdx < uCount; ++uIdx )
		{
			IKnownFolder* pFolder;
			pkfm->GetFolder( rfid[uIdx], &pFolder );
			LPWSTR szPath;
			pFolder->GetPath(0, &szPath );
			strArray.Add( szPath );
			CoTaskMemFree( szPath );
			pFolder->Release();
		}

		CoTaskMemFree( rfid );
		pkfm->Release();
	}
}

How to get the path of a specific known folder using new COM Interface?

CString GetKnownFolderIDCOM( KNOWNFOLDERID rfid )
{
	CString strPathRet;
	LPWSTR szPath;
	IKnownFolderManager* pkfm = NULL;
	HRESULT hr = CoCreateInstance(CLSID_KnownFolderManager, NULL,
		CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pkfm));

	if( SUCCEEDED(hr))
	{
		IKnownFolder* pFolder;
		pkfm->GetFolder( rfid, &pFolder );

		pFolder->GetPath(0, &szPath );
		strPathRet = szPath;
		CoTaskMemFree( szPath );
		pFolder->Release();
	}
	pkfm->Release();
	return strPathRet;
}

How to get path of a specific known folder Shell API?

CString GetKnownPathShell( KNOWNFOLDERID rfid )
{
	CString strPath;
	LPWSTR szPath;
	SHGetKnownFolderPath( rfid, 0, 0, &szPath );
	strPath = szPath;
	CoTaskMemFree( szPath );
	return strPath;
}
 

Getting Processor architecture in x86 and x64 bit platform.

 

GetSystemInfo provides the basic system information and processor architecture of the underlying platform. This API can be used successfully in both x64 and x86 platform. But, under 64-bit WIndows, we can run 32 bit Applications( WOW64). If a WOW64 process call GetSystemInfo API, it will return the processor architecture as x86. Of course it should be the way, this API act otherwise there could compatibility problems may arise and application could act weird and show undefined behavior.

If the WOW64 process want to know the original platform it’s running, it must call GetNativeSystemInfo. When we’ve to use this? I’ve a realworld example. When we spawn process explorer (procexp.exe, it realize the underlying platform and create another exe procexp64.exe (64bit version) to iterate all process information in the system. Note that the GetNativeSystemInfo need to be called only if you 32bit application wants to run under 64 bit platform and need to care about the true underlying platform. In all other cases, call GetSystemInfo, which works across platforms uniquely. See the snippet below

#include "stdafx.h"
#include 

void displayPrcessorInfo( SYSTEM_INFO &stInfo )
{
        switch( stInfo.wProcessorArchitecture )
        {
        case PROCESSOR_ARCHITECTURE_INTEL:
                printf( "Processor Architecture: Intel x86\n");
                break;
        case PROCESSOR_ARCHITECTURE_IA64:
                printf( "Processor Type: Intel x64\n");
                break;
        case PROCESSOR_ARCHITECTURE_AMD64:
                printf( "Processor Type: AMD 64\n");
                break;
        default:
                printf( "Unknown processor architecture\n");
        }
}

int _tmain(int argc, _TCHAR* argv[])
{
        SYSTEM_INFO stInfo;
        GetSystemInfo( &stInfo );
        displayPrcessorInfo(stInfo);

        GetNativeSystemInfo( &stInfo );
        displayPrcessorInfo(stInfo);
        return 0;
}

To know more about the different processor architecture in abstract level, please do check one of my previous posts.

 

How to restrict Window Movement?

 

This is beginner level post. How we can make a Window immovable?

Roughly we’ve two methods to do this.

Method #1. Handle the NCHITTEST message and ignore while user click on the caption area (Titlebar). This method doesn’t work well in Windows 7/Vista if Aero is enabled. This method works with any type of Window having titlebar. The disadvantage of this method is , the user will still able to move using keyboard, if system menu is available.

 

LRESULT CMoveWindowSampleDlg::OnNcHitTest(CPoint point)
{
    UINT nHitTest = CDialogEx::OnNcHitTest(point);

    if( HTCAPTION == nHitTest )
        nHitTest = HTNOWHERE;

    return nHitTest;
}

Method #2 – Remove the Move command from System Menu (Works with windows having system menu stle (WS_SYSMENU) ). The the Move command in the system menu will be removed in this case. Windows will internally disable the movement of this kind of Windows.

BOOL CMoveWindowSampleDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();

    CMenu* pSysMenu = GetSystemMenu(FALSE);

    if (pSysMenu != NULL)
    {
        pSysMenu->RemoveMenu( SC_MOVE, MF_BYCOMMAND );
       }
...

       return TRUE;
}

PS: Using method 2, this is the same method we use to disable the close button of a Window. For disabling a menu/titlebar button. Call EnableMenu function with relevant parameters.