Monday, November 19, 2007

Setting an user breakpoint to debug a memory allocation

When tracking down memory leaks using the debug C-Runtime (CRT), it is often useful to set a breakpoint immediately before allocating the memory that causes the leak. By setting _crtBreakAlloc, you can cause a user-defined breakpoint at a specific point of memory allocation.

When tracking memory leaks with Debug-CRT functions, such as _CrtDumpMemoryLeaks, an allocation number enclosed in braces ({}) often appears. For example, the following is a memory leak at allocation number 18:

Detected memory leaks! Dumping objects -> {18} normal block at 0x00660BE4, 10 bytes long Data: < > CD CD CD CD CD CD CD CD CD CD Object dump complete.

It is useful to set a breakpoint right before this memory gets allocated so you can step through the callstack and see what functions are causing this memory to get allocated.We can use the Watch window and set the allocation breakpoint dynamically. This method has the advantage of not requiring any source code changes or recompiling.

To set a allocation breakpoint dynamically, perform the following steps:

1.

Start your debugging session. From the Build menu, choose Debug -> Step-Into. If you are using the "Debug Single-Threaded" or "Debug Multi- Threaded" option , follow step 1a. Otherwise, follow step 1b.

a.

Type _crtBreakAlloc in the Watch window. This shows the current allocation number at which your program will stop. This allocation number should be -1 when your program first starts.

b.

Type {,,msvcrtd.dll}*__p__crtBreakAlloc() in the Watch window. This shows the current allocation number at which your program will stop. This allocation number should be -1 when your program first starts.

2.

Double click on the -1 value, and enter the new allocation number that causes a user-defined breakpoint.

3.

From the Debug menu, choose Debug -> Go

Now the application will cause an user breakpoint just before allocating memory corresponding to the specified allocation number.

For more information about _crtBreakAlloc, please search "Tracking Heap Allocation Requests" in MSDN.

Retrieving a List of All ODBC Data Sources

The Open Database Connectivity (ODBC) API contains a function called SQLDataSources() which can be used to retrieve information about data sources which are available to an application. Below is a code snippet which fills a CStringArray with the names of all available ODBC data sources in the system.

Please include ODBC32.lib in your application before building.

   #include "sqlext.h"
 
   #define MAX_DSN_LENGTH 30
   #define MAX_DSN_DESC_LENGTH 300

HENV hEnv;

char szDSN[MAX_DSN_LENGTH];

SWORD cbDSN;

UCHAR szDescription[MAX_DSN_DESC_LENGTH];

SWORD cbDescription;

RETCODE retcode;

CStringArray * pArray= new CStringArray;

SQLAllocEnv(&hEnv);

while (retcode=SQLDataSources(hEnv, SQL_FETCH_NEXT,

(UCHAR FAR *) &szDSN, MAX_DSN_LENGTH, &cbDSN,

(UCHAR FAR *) &szDescription,MAX_DSN_DESC_LENGTH,

&cbDescription) != SQL_NO_DATA_FOUND

&&retcode!=SQL_ERROR)

{

pArray->Add( szDSN );

}

Now pArray contains the names of all the ODBC data sources available in the system.

Getting the current application path

Have u ever confronted with the need of getting the path of the current application? One method is of course to use the function GetModuleFileName(). But there is another easier method. It is figured out below:

In Win32 application, you can get to the program name through the variable __argv. You can just reference __argv directly. It is declared in stdlib.h

Test this out by adding the following simple line in your application:

   MessageBox( NULL, __argv[0], "App Path", MB_OK ); 

Thursday, November 15, 2007

Deal menus dynamically!!

Many commercial applications developed for Windows allow the user to customize the menus of the application. This ability introduces some complexity when the application must update particular menu items at certain times. Here we discuss how to perform this task.

Windows sends a WM_INITMENUPOPUP message just before a pop-up menu is displayed.We can modify menus dynamically by handling WM_INITMENUPOPUP message on our own. A sample code to achieve this is shown below:

// OnInitMenuPopup() is the framework provided handling function for WM_INITMENUPOPUP

void CMainFrame::OnInitMenuPopup(CMenu* pPopupMenu, UINT nIndex, BOOL bSysMenu)

{

CFrameWnd::OnInitMenuPopup(pPopupMenu, nIndex, bSysMenu);

if(if( m_bFirstTime )

{

if( 0 == nIndex ) // Menu index....

pPopupMenu->InsertMenu(0, // Position to insert

MF_BYPOSITION,

1000 // ID of the new menu item…This should be unique..

_T("My menu item") );

m_bFirstTime = false;

}

}

The above code will insert the specified string into the menu with index 0( Usually File menu ). In OnInitMenuPopup() function, we receive the pointer to the menu that is being expanded. So we can use this pointer to add, insert or delete items from that menu at will.

Now there is a question of how to add a command-handler for this new item. We can’t add code into the message map since the menu is added dynamically. For that we may resort to the OnCmdMsg() viirtual function provided by the framework. We have to override it in our application. This function is called by the framework, each time a user selects a menu command or the menu is being updated. So we can handle menu commands as well as enable/disable menu items using this function. The following is a glance on how to implement this function ourselves:

BOOL CMainFrame::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo)

{

if(1000 == nID && CN_COMMAND == nCode )

AfxMessageBox( "My menu item accessed. ");

return CFrameWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);

}

Size of an empty class

Most of us are aware that the size of object of an empty class is 1 byte( It is !! ). Have you ever thought why it is so? It is implemented likewise to ensure that the addresses of two different objects will be different. For the same reason, "new" for an empty class always returns pointers to distinct objects. For example :

               class Empty { };
 
               void f()
               {
                               Empty a, b;
                               if (&a == &b) cout << "Change your object concepts";
 
                               Empty* p1 = new Empty;
                               Empty* p2 = new Empty;
                               if (p1 == p2) cout << " Which new is this?? ";
               }              
 

There is another interesting rule that says that an empty base class need not be represented by a separate byte:

               struct X : Empty
              {          
                   int a;
              };
 
               void f(X* p)
               {
                               void* p1 = p;
                               void* p2 = &p->a;
                               if (p1 == p2) cout << "Well, the base class has no bytes";
               }
 

This optimization is safe and can be most useful. It allows a programmer to use empty classes to represent very simple concepts without overhead. Some current compilers provide this "empty base class optimization".

Rename the Start button!

Here’s a method to rename the ‘Start’ button of Windows. I haven’t tried this myself. You may try this based on your convenience.

To rename the start button, you will need a hex editor.For example you can use UltraEdit. Then perform the following steps:

  1. Copy the \windows\explore.exe file to a new name (e.g. explorer_1.exe)
  2. With the hex editor, open that file and go to offset 412b6
  3. You will see the word start with blanks between each letter
  4. Edit it be any 5 characters or less
  5. Save the file
  6. Boot to DOS
  7. Copy the existing c:\windows\explorer.exe to explorer.org
  8. Copy explorer_1.exe to explorer.exe
  9. You will also need to replace the explorer.exe in the c:\windows\system32\dllcache file as well with the new one.

Note: If the partition is NTFS and you can't access the files from DOS:

  1. Start Regedit
  2. Go to HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows NT \ CurrentVersion \ Winlogon.
  3. Change the value of Shell from Explorer.exe to explorer_1.exe

Create a shortcut programatically.

Have you ever tried to create a shortcut programmatically? Here’s a way to achieve it:

CoInitialize( NULL );

IShellLink* psl;

CString PathLink = "C:\\Link.lnk";

// Get a pointer to the IShellLink interface.

HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,

IID_IShellLink, (PVOID *) &psl);

if (SUCCEEDED(hres))

{

IPersistFile* ppf;

// Set the path to the shortcut target and add the

// description.

psl->SetPath((LPCSTR) "D:\\My Folder\\MyFile.txt");

psl->SetWorkingDirectory((LPCSTR) " D:\\My Folder ");

psl->SetDescription((LPCSTR) "Programmatic shortcut!!!" );

hres = psl->QueryInterface(IID_IPersistFile, (PVOID *) &ppf);

if (SUCCEEDED(hres))

{

WORD wsz[MAX_PATH];

MultiByteToWideChar(CP_ACP, 0, (LPCSTR) PathLink, -1, wsz, MAX_PATH);

hres = ppf->Save(wsz, TRUE);

ppf->Release();

}

psl->Release();

}

CoUninitialize();

Using this method you can create shortcuts for any file or folder.

Determine the path of special folders

Here’s one method to determine the path of special folders (e.g. the Desktop folder, the Start Menu folder, etc).

      #include 
      #include 
 

LPITEMIDLIST pidl;

HRESULT hr = SHGetSpecialFolderLocation(NULL, CSIDL_DESKTOP, &pidl);

if (SUCCEEDED(hr))

{

// Convert the item ID list's binary

// representation into a file system path

char szPath[_MAX_PATH];

if (SHGetPathFromIDList(pidl, szPath))

{

AfxMessageBox(szPath );

}

else

{

ASSERT(FALSE);

}

}

else

{

ASSERT(FALSE);

}

For a list of CSIDL values corresponding to different special folders, please refer “CSIDL Values” in MSDN documentation.

Disable the task manager

Here’s a tip to disable the task manager

1. Start Regedit

2. Go to HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\System

3. Create the Dword value DisableTaskMgr

4. Give it a value of 1 to disable task manager.

5. To enable it again, either set the value to zero or delete the DisableTaskMgr flag.

Calling a Function Before Program's Startup

Here’s one method of calling a function even before program’s start-up. The easiest way to achieve this is by calling these functions from a constructor of a global object. Because global objects are conceptually constructed before the program's outset, these functions will run before main() starts. For example:

class Logger
{
public:
Logger()
{
StartLOgger();
}
};
Logger log; /*global instance*/

int main()
{
// Application code.
}


Here the global object log is created first of all. So the function StartLOgger() which is called in the class’s constructor is executed well before the execution of main().



Well that’s one method..There should be many others ways to achieve the same. If you are aware of other methods, please share it among us.

Why non-static member functions are not used as callback functions?

Here’s a small but useful tip. All of us are familiar with call-back functions. Normally in C++, if we are using a class member function as callback function, it should be a static function. Below mentioned is the reason for this :

There's an invisible parameter (this) required on the stack when calling class member functions. Windows is fundamentally C based, and doesn't know anything about objects and "this" pointers, so the callbacks don't use them. You can use a static member function or a simple global function as a callback, because they're not associated with a specific class instance, so no "this" is used when calling them. In such cases if we want to access class member functions, the “this” pointer is usually passed to callback functions, like we normally do.

Get the name of the EXE associated with a given window

Here is one method to find the EXE name corresponding to a window with given handle:

#include

HANDLE hProc;

HMODULE ahMod [10];

DWORD dwNeeded;

DWORD dwPid;

BOOL bResult = FALSE;

char * pszFilename = new char[ MAX_PATH ];

HWND hWnd = ( HWND )0x0003064C; // Window handle obtained using the Spy++ tool. Replace this with appropriate value.

// Get ProcessID corresponding to this window handle.

GetWindowThreadProcessId ( hWnd, &dwPid);

hProc = OpenProcess (PROCESS_QUERY_INFORMATION|PROCESS_VM_READ,

FALSE,

dwPid);

if (hProc)

{

if (EnumProcessModules(hProc, ahMod, sizeof(ahMod), &dwNeeded))

{

// we're only interested in the first module.

// pszFilename will contain the EXE name.

if (GetModuleBaseName(hProc, ahMod[0], pszFilename, MAX_PATH ))

{

bResult = TRUE;

}

}

CloseHandle (hProc);

}

Note : Psapi.lib should be included in the project settings.

EnumProcessModules() function stores a handle for each module in the specified process to the specified array. Out of these, the first handle will be the handle of the application. The rest will be other modules loaded in the process. So you can also use this code to find the modules associated with a specific process.

Find the logical drives within your system

Here is a way to find out the hard-disk drives within your system:

int iStrsLen;

char smzDrives [(3+1)*26+1];

char szDrive [3+1];

int i;

iStrsLen = GetLogicalDriveStrings (sizeof(smzDrives), smzDrives);

if( iStrsLen )

{

if (iStrsLen > sizeof(smzDrives))

{

// Buffer not big enough... eh?

}

else

{

// Parse the returned multi-string array.

i = 0;

while (smzDrives[i])

{

strcpy (szDrive, &(smzDrives[i]));

AfxMessageBox(szDrive);

while (smzDrives[i]) i++;

i++;

}

}

}

Instead of the function GetLogicalDriveStrings(), you can also use the function GetLogicalDrives() for this purpose.

Search the network for the presence of a machine

Check out the following function, which can be used to check whether a given machine is present in the primary domain:

// Include Netapi32.lib in the project settings

#include

BOOL FindServer (const CString& rcsTarget )

{

NET_API_STATUS nas ;

NET_DISPLAY_MACHINE * pndm;

SERVER_INFO_101 * pSI_101 ;

DWORD dwEntriesRead;

DWORD dwTotalEntries;

DWORD dwRetVal = ERROR_SUCCESS;

DWORD dwNdmCount;

int iCount;

char szServer [64];

WCHAR wcServer [64];

CString csServer;

CString csTarget = rcsTarget;

BOOL bFound = FALSE;

nas = NetServerEnum (NULL,

101,

(LPBYTE*)&pSI_101,

MAX_PREFERRED_LENGTH,

&dwEntriesRead,

&dwTotalEntries,

SV_TYPE_SERVER, // type you're looking for.

NULL,

0);

if (nas == NERR_Success)

{

TRACE( "NetServerEnum found %u server(s)\n", dwEntriesRead);

for (iCount=0; iCount<(int)dwEntriesRead; iCount++)

{

WideCharToMultiByte (CP_ACP,

WC_COMPOSITECHECK,

(LPCWSTR)(pSI_101[iCount].sv101_name),

-1,

szServer,

sizeof(szServer),

NULL,

NULL);

TRACE( szServer );

TRACE( _T( "\n") );

csServer = szServer;

csServer.MakeUpper();

csTarget.MakeUpper();

if (csServer == csTarget)

{

// The browse info will continue to report machines

// for ages after they've been switched off, so try to

// talk direct to the machine.

wcscpy (wcServer, L"\\\\");

wcscat (wcServer, (LPCWSTR)(pSI_101[iCount].sv101_name));

nas = NetQueryDisplayInformation (wcServer,

2,

0,

1,

sizeof(NET_DISPLAY_MACHINE),

&dwNdmCount,

(PVOID*)&pndm);

switch (nas)

{

case NERR_Success:

case ERROR_MORE_DATA:

bFound = TRUE;

break;

default:

TRACE( "NQDI gave error %u\n", nas);

dwRetVal = nas;

break;

}

NetApiBufferFree ((PVOID)pndm);

if (bFound)

break;

}

}

NetApiBufferFree (pSI_101);

}

return bFound;

}

Handling system tray icons

All of you will be pretty familiar with System Tray icons. Today let’s see how we can create one of our own and handle notifications from it.

The following code snippet can be used to create a icon in the system tray:

#define MY_SYSTEM_TRAY_MSG WM_USER + 50

#define TRAY_ICON_01 1

NOTIFYICONDATA nid;

nid.cbSize = sizeof(NOTIFYICONDATA);

nid.hWnd = GetSafeHwnd();

nid.uID = TRAY_ICON_01;

nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;

nid.uCallbackMessage = MY_SYSTEM_TRAY_MSG;

nid.hIcon = LoadIcon( AfxGetInstanceHandle(), MAKEINTRESOURCE( IDR_MAINFRAME )); // Use any icon you want

lstrcpy( nid.szTip, _T( "Trayed my application!"));

Shell_NotifyIcon(NIM_ADD, &nid);

Now comes the chore of handling the notifications from the icon. For this first add the following entry in the message map:

ON_MESSAGE (MY_SYSTEM_TRAY_MSG, OnSystemTrayIconClick)

Now implement OnSystemTrayIconClick() as follows:

LONG MyClass::OnSystemTrayIconClick (WPARAM wParam, LPARAM lParam)

{

switch (wParam)

{

case TRAY_ICON_01:

switch (lParam)

{

case WM_LBUTTONDOWN:

case WM_RBUTTONDOWN:

AfxMessageBox( _T( "You may implement a context menu here" ));

break ;

}

break ;

default:

AfxMessageBox("invalid icon id from tray\n");

break ;

}

return 1;

}