Category : C Source Code
Archive   : ADDMENU.ZIP
Filename : ADMNULIB.C

 
Output of file : ADMNULIB.C contained in archive : ADDMENU.ZIP
/**************************************************************************

This DLL is used to append two menu items to the system menu of an
application whose menu is invoked. The menu items are removed
when the menu is closed.

Two types of Windows hooks are used to accomplish this task.
WH_GETMESSAGE hook is used with its callback function GetMesgCallBackProc,
and WH_CALLWNDPROC hook is used with the function WndCallBackProc.

The menu items are appended to only top-level windows that are not
pop-ups. When one of the new menu items is selected, the DLL posts a
message to the application (ADMNUAPP.EXE) to display a dialog box.
The app in turn displays a System Modal dialog box since we do not
want the user to select another menu item while the dialog box is up.

The reason for using PostMessage() instead of SendMessage() when
passing the message to the app is that we don't want to create a
message dead-lock.

Some apps, like Excel and WinWord, make use of WM_MENUSELECT message
to update a status window. When this message is trapped inside the
WndCallBackProc function, a value of one of the original menu items
is sent to fool such an application.

Also inside GetMesgCallBackProc, WM_SYSCOMMAND message's wParam is
changed to a bogus value so the target app should not respond to it.
This value should not coincide with an existing menu ID that the
application is using.


**************************************************************************/


#include "windows.h"
#include "AdMnuLib.h"

typedef struct
{
LONG lParam;
WORD wParam;
WORD message;
HWND hwnd;
} CALLWND_MSG;

typedef CALLWND_MSG FAR *LPCALLWND_MSG;

MSG CallWndMsg; // Structure to copy stuff for WH_CALLWNDPROC

FARPROC lpWndCallBackProc;
FARPROC lpOldWndProc;

FARPROC lpGetMesgCallBackProc;
FARPROC lpOldMessageProc;

HMENU hTargetSysMenu;
BOOL bMenuAdded = FALSE;
HWND hMainWnd;
int OriginalID;

int FAR PASCAL LibMain(hModule, wDataSeg, cbHeapSize, lpszCmdLine)
HANDLE hModule;
WORD wDataSeg;
WORD cbHeapSize;
LPSTR lpszCmdLine;
{
return 1;
}


int FAR PASCAL WEP (bSystemExit)
int bSystemExit;
{
return(1);
}

/**************************************************************************

Called by the app to set the message hook.

**************************************************************************/
void FAR PASCAL SetHook (hwnd)
HWND hwnd;
{
hMainWnd = hwnd;

lpGetMesgCallBackProc = GetProcAddress (GetModuleHandle ("ADMNULIB.DLL"),
"GetMesgCallBackProc");
lpOldMessageProc = SetWindowsHook (WH_GETMESSAGE, lpGetMesgCallBackProc);


lpWndCallBackProc = GetProcAddress (GetModuleHandle ("ADMNULIB.DLL"),
"WndCallBackProc");

lpOldWndProc = SetWindowsHook (WH_CALLWNDPROC, lpWndCallBackProc);

}


/**************************************************************************

Called by the app to remove the message hook.

**************************************************************************/
void FAR PASCAL RemoveHook (void)
{
UnhookWindowsHook (WH_GETMESSAGE, lpGetMesgCallBackProc);

UnhookWindowsHook (WH_CALLWNDPROC, lpWndCallBackProc);
}

/**************************************************************************

Appends menu items to the target app's system menu.

**************************************************************************/
void AddNewMenu (hTargetAppWnd)
HWND hTargetAppWnd;
{
// Check to see if the new menu items already there
// Sometimes two WM_INITMENU are generated. If we don't
// have this test, extra items will be created
if (!bMenuAdded)
{
hTargetSysMenu = GetSystemMenu(hTargetAppWnd, FALSE);

// Get the ID of the first item of the original sys menu
// We need this value so we could pass it to the app
// when it needs WM_MENUSELECT
OriginalID = GetMenuItemID (hTargetSysMenu, 0);

AppendMenu (hTargetSysMenu, MF_SEPARATOR,0,"");
AppendMenu (hTargetSysMenu, MF_BYCOMMAND, IDM_BOGUS_ITEM1, FIRST_ITEM_STRING);
AppendMenu (hTargetSysMenu, MF_BYCOMMAND, IDM_BOGUS_ITEM2, SECOND_ITEM_STRING);

bMenuAdded = TRUE;
}
}


/**************************************************************************

Removes menu items from the target app's system menu.

**************************************************************************/
void RemoveNewMenu (void)
{
short nCount, nIndex;
char szMenuText [MENU_STRING_LENGTH];

nCount = GetMenuItemCount (hTargetSysMenu);

for( nIndex = nCount-1; nIndex >= 0; nIndex-- )
{
if( !GetMenuString (hTargetSysMenu, nIndex, szMenuText, MENU_STRING_LENGTH-1, MF_BYPOSITION))
continue;

if (!lstrcmp ((LPSTR) szMenuText, (LPSTR) SECOND_ITEM_STRING))
{
RemoveMenu (hTargetSysMenu, nIndex, MF_BYPOSITION);
RemoveMenu (hTargetSysMenu, nIndex-1, MF_BYPOSITION);
RemoveMenu (hTargetSysMenu, nIndex-2, MF_BYPOSITION);
break;
}
}

bMenuAdded = FALSE;
}


/**************************************************************************

Call-back for the message hook.

**************************************************************************/
DWORD FAR PASCAL GetMesgCallBackProc (nCode, wParam, lParam)
int nCode;
WORD wParam;
DWORD lParam;
{
MSG FAR *msg;
static POINT point;

if (nCode < 0)
{
return (DefHookProc (nCode, wParam, (LONG)lParam,
(FARPROC FAR *) &lpOldMessageProc));
}

msg = (MSG FAR *) lParam;

// If one of the new menu items are selected
if (msg->message == WM_SYSCOMMAND)
if (msg->wParam == IDM_BOGUS_ITEM1 || msg->wParam == IDM_BOGUS_ITEM2)
{
// Tell our app to display a system-modal dialog
PostMessage (hMainWnd, WM_NEWITEM, 0, 0);

// Fill wParam with a bogus value so the target app couldn't
// use it.
msg->wParam = 34997;

}

return (DefHookProc (nCode, wParam, (LONG)lParam,
(FARPROC FAR *) &lpOldMessageProc));
}


/**************************************************************************

Call-back for the window procedure hook.

**************************************************************************/
DWORD FAR PASCAL WndCallBackProc (nCode, wParam, lParam)
int nCode;
WORD wParam;
DWORD lParam;
{
LONG TheStyle;

if (nCode < 0)
{
return (DefHookProc (nCode,
wParam,
(LONG)lParam,
(FARPROC FAR *) &lpOldWndProc));
}

CallWndMsg.lParam = ((LPCALLWND_MSG) lParam)->lParam;
CallWndMsg.wParam = ((LPCALLWND_MSG) lParam)->wParam;
CallWndMsg.message = ((LPCALLWND_MSG) lParam)->message;
CallWndMsg.hwnd = ((LPCALLWND_MSG) lParam)->hwnd;

switch (CallWndMsg.message)
{
case WM_INITMENU:

// Time to add the menu items!!!
// But first, check if it's OK to do so

TheStyle = GetWindowLong (CallWndMsg.hwnd, GWL_STYLE);

// The target window should not be a child, pop-up or a dialog box
if (!GetParent (CallWndMsg.hwnd)
&& !(TheStyle & WS_POPUP)
&& (TheStyle & WS_SYSMENU))

AddNewMenu (CallWndMsg.hwnd);

break;

case WM_MENUSELECT:

// Menus have been closed. Remove the new items.
if (LOWORD (CallWndMsg.lParam) == -1
&& HIWORD (CallWndMsg.lParam) == 0
&& bMenuAdded)
RemoveNewMenu ();

// Some apps make use of this message. Change the wParam
// to fool them.

else if (CallWndMsg.lParam & MF_SYSMENU
&& (CallWndMsg.wParam == IDM_BOGUS_ITEM1
|| CallWndMsg.wParam == IDM_BOGUS_ITEM2))
((LPCALLWND_MSG) lParam)->wParam = OriginalID;

break;

}

return (DefHookProc (nCode,
wParam,
(LONG)lParam,
(FARPROC FAR *) &lpOldWndProc));
}


  3 Responses to “Category : C Source Code
Archive   : ADDMENU.ZIP
Filename : ADMNULIB.C

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/