home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
pmm100.zip
/
PMMMAN.TXT
< prev
next >
Wrap
Text File
|
1999-03-30
|
122KB
|
3,715 lines
Online document
────────────────────────────────────────────────────────────────────────────
PMM OS/2 Presentation Manager Monitor Version 1.0
J. Salvador Amoros, 1999
────────────────────────────────────────────────────────────────────────────
Table of Contents
─────────────────
1. PMM OS/2 Presentation Manager Monitor . . 1
2. Installing and Using PMM . . . . . . . . . 1
Installation Procedure . . . . . . . . . . 2
How to Use PMM in an Application . . . . . 2
Considerations About Debuggers . . . . . . 4
3. Using Hooks with PMM . . . . . . . . . . . 5
4. Subclassing Windows when Using PMM . . . . 6
5. Messages Traced by PMM . . . . . . . . . . 10
6. The PMM Interface . . . . . . . . . . . . 25
List of Functions . . . . . . . . . . . . 25
List of Errors and Warnings . . . . . . . 51
Errors Returned by Functions . . . . . 51
Errors Occurring when Using PMM . . . . 53
Warnings Occurring when Using PMM . . . 54
7. PMM Message Trace Format . . . . . . . . . 55
8. Notes About PMM . . . . . . . . . . . . . 59
9. Errors Detected in the Documentation . . . 61
10. PMM Limits . . . . . . . . . . . . . . . . 62
11. Tools Used in Creating PMM . . . . . . . . 62
12. Acknowledgments . . . . . . . . . . . . . 63
13. Disclaimer . . . . . . . . . . . . . . . . 63
14. Trademarks . . . . . . . . . . . . . . . . 63
i
1. PMM OS/2 Presentation Manager Monitor
═════════════════════════════════════════
PMM is a learning and debugging tool aimed to show the flow of
messages produced in a Presentation Manager (PM) application.
PMM monitors messages received by windows, writing them to a file.
Messages posted to a queue or a window and messages sent via
WinSendMsg or through a pointer are traced. Messages are
interpreted, formatted and shown as they occur in an application.
PMM gives you information about:
- The message stream
- The attributes of the destination window of a message
- The parameters of a message
- How a message reached the window procedure
- The return value of a message
PMM is a tool that works inside your application. It is not a
separate program running in the operating system. The PMM interface
is a set of functions that you must call from your code. You
control what messages to trace, how to trace them, when to trace
them and other important aspects of messages.
You use PMM by creating a trace session in your program and
customizing it to your learning/debugging needs. You can start and
stop tracing messages from inside your code as well as from the
keyboard. To help debugging, you can write text to the trace file
at any point in your code and at any time.
PM messages are divided into groups. You can select one or more
groups of messages, to selectively trace the messages that you are
interested in. You can trace messages related to one or more PM
controls and you can control most of the message information that
will be shown in the trace file.
2. Installing and Using PMM
═══════════════════════════
To install and use PMM, you will need:
1. OS/2 2.1 or higher.
2. A C/C++ compiler.
3. The "#include" files PMMPOS2.H and PMM.H.
4. The library file PMM.LIB.
5. The dynamic link library PMM.DLL.
- 1 -
Installation Procedure
──────────────────────
1. Copy the dynamic link library PMM.DLL to any directory listed in
the LIBPATH environment variable.
2. Copy the library file PMM.LIB to any directory listed in the LIB
environment variable.
3. Copy the include files PMMPOS2.H and PMM.H to any directory you
choose. Unless the directory is listed in the INCLUDE
environment variable, you will need to use a path when including
them.
4. If you have modified your CONFIG.SYS file you may need to reboot
OS/2 to activate the changes.
Here is an example. Let's assume that you decide to place PMM in
the directory C:\PMM. Do the following:
1. Create the directory
2. Copy all files included in the PMM package to this directory
3. Add C:\PMM to your LIBPATH environment variable:
LIBPATH=C:\IBMWF21\DLL;C:\PMM;
4. Add C:\PMM to your LIB environment variable:
SET LIB=C:\TOOLKT21\OS2LIB;C:\IBMCPP\LIB;C:\PMM;
5. Add C:\PMM to your INCLUDE environment variable:
SET INCLUDE=C:\TOOLKT21\C\OS2H;C:\IBMCPP\INCLUDE;C:\PMM;
6. Reboot OS/2 to activate the changes
How to Use PMM in an Application
────────────────────────────────
Follow these steps:
1. Include the file PMMPOS2.H immediately before the line that
includes OS2.H.
2. Include the file PMM.H at any point after the line that
includes OS2.H.
3. Code the functions needed to create a trace session, to start
tracing, to customize PMM, etc., as shown later in this section.
If you use hooks or subclass windows, you must read carefully the
sections "Using Hooks with PMM," and "Subclassing Windows when
Using PMM," in this manual.
4. Link your program with the library PMM.LIB.
5. Compile and run your program.
- 2 -
Example:
// Conditional compilation. Activate/deactivate PMM easily
#define USE_PMM 1
// Define some constants needed in your program
#define INCL_WININPUT
#define INCL_WINWINDOWMGR
// Include this file immediately before including "os2.h"
#if USE_PMM
#include "pmmpos2.h"
#endif
#include <os2.h>
// Include header files as needed
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// Include the "main" PMM file
#if USE_PMM
#include "pmm.h"
#endif
int main( int argc, char * argv[] )
{
HAB hab;
HMQ hmq;
QMSG qmsg;
#if USE_PMM
HPMMSESSION hpmms;
PMMRET pmmr;
#endif
hab = WinInitialize( 0 );
if ( !hab )
return 1; /* Error */
hmq = WinCreateMsgQueue( hab, 0 );
if ( !hmq )
{
WinTerminate( hab );
return 2; /* Error */
}
// Return codes from PMM are not tested in this example,
// they should be tested
- 3 -
// Create a trace session and start tracing
#if USE_PMM
pmmr = PMMCreateTraceSession( &hpmms, hab, "pmm.log" );
pmmr = PMMStartTracing( hpmms );
#endif
// Initialize resources
// Create the main window
while( WinGetMsg( hab, &qmsg, 0, 0, 0 ) )
WinDispatchMsg( hab, &qmsg );
// Destroy the main window if it exists
// Free resources
// Stop tracing and destroy the trace session
#if USE_PMM
pmmr = PMMStopTracing( hpmms );
pmmr = PMMDestroyTraceSession( hpmms );
#endif
WinDestroyMsgQueue( hmq );
WinTerminate( hab );
return 0; /* Success */
} // End of main
Considerations About Debuggers
──────────────────────────────
You can use any debugger when using PMM. Debuggers, in general,
intercept exceptions produced in an application and, when one is
detected, let you choose the next action to be performed. Then you
can, for instance, investigate the cause of the exception or run the
registered exception handlers. PMM tests all pointers involved in
a message and will report an access violation exception when a
memory address is inaccessible. At this point you should run the
registered exception handlers to inform PMM to handle the exception;
execution will continue. PMM will display the inaccessible pointer
in the message trace file.
See the function PMMShowPointers in the section "The PMM Interface."
- 4 -
3. Using Hooks with PMM
═══════════════════════
You can skip this section if your application doesn't use send
message hooks or input hooks.
PMM uses hooks and subclassing to keep track of all messages
occurring in an application. Currently, PMM uses a send message
hook and an input hook installed in an application message queue.
No system hooks are used. Hooks are called on a FIFO basis, that
is, the most recently installed hook is called first. Given this,
when using hooks with PMM you need to be aware of the following
facts:
- PMM introduces some messages in the message stream of an
application
- PMM temporarily alters messages sent by an application to windows
of another process.
Therefore, in a send message hook an application should:
- ignore some messages introduced by PMM
- process the unaltered messages, i.e. the messages received in the
hook as if the application were not using PMM.
An application does this by using the functions PMMQueryIfIgnoreMsg
and PMMSMHQueryMsg. See the example code in the function
PMMSMHQueryMsg.
A send message hook is installed when an application calls
PMMCreateTraceSession. From this point on, any send message hook,
whether installed *before* or installed *after* calling
PMMCreateTraceSession, may receive messages introduced by PMM or
messages modified by PMM. The send message hook is uninstalled when
an application calls PMMDestroyTraceSession.
If an application installs a send message hook and/or an input hook
after calling PMMCreateTraceSession, the calling order of the
hook(s) will be: the hook(s) installed by the application followed
by the hook(s) installed by PMMCreateTraceSession. In this case
note that:
- an application may modify any value in the structures received in
the hooks: SMHSTRUCT and QMSG
- in an input hook, an application may need not to pass on the
message to the next hook in the chain or to the application.
Assuming this,
- PMM will "receive" and trace any message modified by the
- 5 -
application's send message hook. The unaltered message (before
the application send message hook) cannot be traced
- PMM will not trace a message that is not passed on in an
input hook
- PMM intercepts the WM_TRANSLATEACCEL and the WM_CHAR messages in
order to start and stop tracing through the keyboard. An
application using hooks may modify or not pass on these messages.
Depending on the changes, the PMM logic to start and stop tracing
may not work.
4. Subclassing Windows when Using PMM
═════════════════════════════════════
You can skip this section if your application doesn't subclass
windows.
An application may receive messages sent by other applications in
the system. An example is the DM_PRINTOBJECT message. As
documentation states, this message is sent to a source application
that supports the DRM_PRINT rendering method when objects are
dropped on a printer object. Also, as mentioned in the
documentation when describing the SendMsgHook function, the send
message hook function is called *only* in the context of the sender,
i.e. if the sender has a queue hook installed it is called, but if
the receiver has a queue hook installed it is not called. That is,
*not* all messages that a window receives pass through a hook.
If the message trace has to be correct, i.e. intercept and show
*all* messages received by a window, the only real solution to this
problem is to subclass every window traced. This is what PMM does.
If a trace session has been created, PMM subclasses each window on
the first message that it intercepts for that window, and
unsubclasses it when the window or the trace session is destroyed.
An application may subclass freely a window when using PMM since
PMM maintains a linked list of window procedures and sends the
messages to the appropriate window procedure. To intercept all
messages that a window receives, PMM makes sure that the current
window procedure of a window is always a "PMM window procedure";
then the PMM window procedure sends the message to the "real"
(class or application) window procedure.
The PMM include file PMM.H creates some macros redefining
WinSubclassWindow as PMMSubclassWindow, WinSetWindowPtr as
PMMSetWindowPtr and WinQueryWindowPtr as PMMQueryWindowPtr.
By default, an application will use these macros when including
the file PMM.H. See the functions PMMSubclassWindow,
PMMSetWindowPtr and PMMQueryWindowPtr.
- 6 -
An example follows about subclassing:
1. Assume that a PMM trace session has been created
2. The application creates the window 'W'. The window procedure
of 'W' is, at create time, 'pfnwpApp0'
3. PMM intercepts the WM_CREATE message for the window 'W' and
subclasses the window with the window procedure 'pfnwpPMM0'.
The window procedures of 'W' are:
pfnwpApp0 -> pfnwpPMM0
where 'pfnwpPMM0' is the current window procedure of 'W'
4. The application subclasses the window 'W' with the window
procedure 'pfnwpApp1'. The old window procedure returned to the
application is 'pfnwpPMM0'. The window procedures of 'W' are:
pfnwpApp0 -> pfnwpPMM0 -> pfnwpApp1
Now, we have two cases:
4.1 The application has used the PMMSubclassWindow function to
subclass the window. PMM knows that a subclassing has been
made and subclasses the window again. The window procedures
of 'W' are:
pfnwpApp0 -> pfnwpPMM0 -> pfnwpApp1 -> pfnwpPMM1
From now on, all messages will be intercepted and shown in
the trace file as they were received in the window procedure.
4.2 The application has not used the PMMSubclassWindow function
to subclass the window. PMM doesn't know that a subclassing
has been made and does nothing. The window procedures of 'W'
do not change:
pfnwpApp0 -> pfnwpPMM0 -> pfnwpApp1 (same as before)
Suppose that a message is sent to the window 'W'. We have:
4.2.1 The message is sent using a pointer. For this example,
it must be 'pfnwpApp1'. We have two possibilities:
4.2.1.1 The message is processed by 'pfnwpApp1', i.e.
not passed to the old window procedure. The
window procedures of 'W' remain:
pfnwpApp0 -> pfnwpPMM0 -> pfnwpApp1
Since PMM is not aware that a subclassing has
been made, this message will not appear in the
- 7 -
trace file.
4.2.1.2 'pfnwpApp1' passes the message back to the old
window procedure, which is 'pfnwpPMM0'. PMM
subclasses 'W' with 'pfnwpPMM1' and sends the
message to 'pfnwpApp0'. Now, the window
procedures of 'W' are:
pfnwpApp0 -> pfnwpPMM0 -> pfnwpApp1 -> pfnwpPMM1
'pfnwpApp1' may modify the message before
passing it back to the old window procedure.
The message, whether modified or not, is shown
in the trace file. From now on, all messages
will be intercepted and shown in the trace file
as they were received in the window procedure.
4.2.2 The message is sent or posted using WinSendMsg or
WinPostMsg. PMM intercepts the message, subclasses
'W' with 'pfnwpPMM1' and sends the message to
'pfnwpApp0'. The window procedures of 'W' are:
pfnwpApp0 -> pfnwpPMM0 -> pfnwpApp1 -> pfnwpPMM1
All messages will be intercepted and shown in the trace
file as they were received in the window procedure.
Note that, in the case illustrated by 4.2.1.1 above, a message will
not be traced. An application may avoid this by using, whenever
possible, the function PMMSubclassWindow or the combination
PMMQueryWindowPtr/PMMSetWindowPtr.
Another example will clarify further the way PMM handles
subclassing. Assume that a window has the following chain of
window procedures:
pfnwpApp0 -> pfnwpPMM0 -> pfnwpApp1 -> pfnwpPMM1
A message is sent or posted to that window using WinSendMessage,
WinPostMsg or through a pointer. The message will arrive at
'pfnwpPMM1', which is the end of the chain of window procedures
associated with the window. 'pfnwpPMM1' logs the message, and
passes it on to 'pfnwpApp1', which may at its option pass the
message on to 'pfnwpPMM0'. In 'pfnwpPMM0', the message is logged
again if 'pfnwpApp1' has changed the message. In any event,
'pfnwpPMM0' then passes the message on to the original (create
time) window procedure, 'pfnwpApp0'.
Regarding an application, subclassing has several implications:
- A window may have one or more window procedures, each one of them
- 8 -
responding to some specific messages and passing the others to
another window procedure. For a window, OS/2 has only a pointer
to the "current" window procedure; that is, OS/2 doesn't maintain
a list of window procedures when an application is subclassing a
window. PMM cannot know the "history" of a window before a trace
session has been created. PMM knows only the last window procedure
that has been assigned to a window (when it is created or when is
subclassed) and, starting from this window procedure, maintains a
list of window procedures. All this adds up to the following:
some messages may not be traced if an application subclasses
windows and then creates a trace session.
- A window subclassed after calling PMMCreateTraceSession must be
unsubclassed, if it exists, before calling PMMDestroyTraceSession.
- There is a limit on the number of times that an application can
subclass a window. See the section "PMM Limits." Note, however,
that for practical purposes no such a limit exists.
- When not using PMM, given this sequence of calls:
pfnwpB = WinSubclassWindow( hwnd, pfnwpA );
pfnwpC = WinSubclassWindow( hwnd, pfnwpB );
'pfnwpA' is equal to 'pfnwpC', at end of execution.
This is not true when using PMM. Suppose that an application
executes this code:
/*
Assume that a trace session has been created.
PMM has subclassed 'hwnd' with 'pfnwpPMM0' (internal to PMM)
before the aplication uses WinSubclassWindow. We have:
pfnwpDefault -> pfnwpPMM0
The following code subclasses 'hwnd' with
a new window procedure: 'pfnwpA'.
The returned old window procedure is 'pfnwpB'.
*/
pfnwpB = WinSubclassWindow( hwnd, pfnwpA );
/*
At this point, if an application uses PMMSubclassWindow, the
window is subclassed with a new window procedure: 'pfnwpPMM1'
(internal to PMM). We have:
pfnwpDefault -> pfnwpPMM0 -> pfnwpA -> pfnwpPMM1
If an application does not use PMMSubclassWindow the window is
- 9 -
subclassed with 'pfnwpA'. We have:
pfnwpDefault -> pfnwpPMM0 -> pfnwpA
*/
/* This will generate a WM_SETWINDOWPARAMS message */
WinSetWindowText( hwnd, "sample" );
/*
At this point, if the application used PMMSubclassWindow, PMM does
nothing. If the application did not use PMMSubclassWindow, the
window is now subclassed with a new window procedure: 'pfnwpPMM1'.
In either case, we have:
pfnwpDefault -> pfnwpPMM0 -> pfnwpA -> pfnwpPMM1
*/
/* Undo the subclassing */
pfnwpC = WinSubclassWindow( hwnd, pfnwpB );
/*
If an application uses PMMSubclassWindow, PMM will undo the
subclassing: now 'hwnd' has the same window procedure that it had
before any subclassing has been done. The final situation is:
pfnwpDefault -> pfnwpPMM0
which is correct. At this point, however, 'pfnwpA' is *not* equal
to 'pfnwpC'. 'pfnwpC' is the window procedure that the window had
before undoing the subclassing, i.e. 'pfnwpPMM1', not the window
procedure that the window had before doing the first subclassing,
i.e. 'pfnwpPMM0'.
*/
5. Messages Traced by PMM
═════════════════════════
All the PM messages are divided into groups, and a group can have
subgroups. PMM considers the following groups and subgroups and
traces the following messages:
- Group: Window messages.
The following messages are traced:
WM_ACTIVATE
WM_ADJUSTWINDOWPOS
WM_CALCVALIDRECTS
WM_CLOSE
WM_COMMAND
WM_CREATE
- 10 -
WM_DESTROY
WM_ENABLE
WM_HELP
WM_INITDLG
WM_MATCHMNEMONIC
WM_MOVE
WM_NULL
WM_PACTIVATE
WM_PAINT
WM_PPAINT
WM_PRESPARAMCHANGED
WM_PSETFOCUS
WM_PSIZE
WM_QUERYDLGCODE
WM_QUERYWINDOWPARAMS
WM_QUIT
WM_SAVEAPPLICATION
WM_SETFOCUS
WM_SETSELECTION
WM_SETWINDOWPARAMS
WM_SHOW
WM_SIZE
WM_SUBSTITUTESTRING
WM_SYSCOMMAND
- Group: messages related to PM standard controls.
This group has subgroups. Below each subgroup are the messages
that PMM traces:
- Subgroup: messages related to the Frame control.
The following messages are traced:
WM_ADJUSTFRAMEPOS
WM_CALCFRAMERECT
WM_ERASEBACKGROUND
WM_ERROR
WM_FLASHWINDOW
WM_FOCUSCHANGE
WM_FORMATFRAME
WM_MINMAXFRAME
WM_OWNERPOSCHANGE
WM_QUERYACCELTABLE
WM_QUERYBORDERSIZE
WM_QUERYFOCUSCHAIN
WM_QUERYFRAMECTLCOUNT
WM_QUERYFRAMEINFO
WM_QUERYHELPINFO
WM_QUERYICON
WM_QUERYTRACKINFO
WM_SETACCELTABLE
WM_SETBORDERSIZE
- 11 -
WM_SETHELPINFO
WM_SETICON
WM_TRACKFRAME
WM_TRANSLATEACCEL
WM_TRANSLATEMNEMONIC (See Note)*
WM_UPDATEFRAME
WM_WINDOWPOSCHANGED
*Note: The WM_TRANSLATEMNEMONIC message doesn't appear in the
toolkit include files. Its value is 195 (hexadecimal).
- Subgroup: messages related to the Combo Box control.
The following messages are traced:
CBM_HILITE
CBM_ISLISTSHOWING
CBM_SHOWLIST
WM_CONTROL and WM_PCONTROL with these notifications:
CBN_EFCHANGE
CBN_EFSCROLL
CBN_ENTER
CBN_LBSCROLL
CBN_LBSELECT
CBN_MEMERROR
CBN_SHOWLIST
and unknown notifications
- Subgroup: messages related to the Button control.
The following messages are traced:
BM_CLICK
BM_QUERYCHECK
BM_QUERYCHECKINDEX
BM_QUERYHILITE
BM_SETCHECK
BM_SETDEFAULT
BM_SETHILITE
WM_CONTROL and WM_PCONTROL with these notifications:
BN_CLICKED
BN_DBLCLICKED
BN_PAINT
and unknown notifications
- Subgroup: messages related to the Menu control.
The following messages are traced:
MM_DELETEITEM
MM_ENDMENUMODE
MM_INSERTITEM
- 12 -
MM_ISITEMVALID
MM_ITEMIDFROMPOSITION
MM_ITEMPOSITIONFROMID
MM_QUERYDEFAULTITEMID
MM_QUERYITEM
MM_QUERYITEMATTR
MM_QUERYITEMCOUNT
MM_QUERYITEMRECT
MM_QUERYITEMTEXT
MM_QUERYITEMTEXTLENGTH
MM_QUERYSELITEMID
MM_REMOVEITEM
MM_SELECTITEM
MM_SETDEFAULTITEMID
MM_SETITEM
MM_SETITEMATTR
MM_SETITEMHANDLE
MM_SETITEMTEXT
MM_STARTMENUMODE
WM_DRAWITEM
WM_INITMENU
WM_MEASUREITEM
WM_MENUEND
WM_MENUSELECT
WM_NEXTMENU
- Subgroup: messages related to the Static control.
The following messages are traced:
SM_QUERYHANDLE
SM_SETHANDLE
- Subgroup: messages related to the Entry Field control.
The following messages are traced:
EM_CLEAR
EM_COPY
EM_CUT
EM_PASTE
EM_QUERYCHANGED
EM_QUERYFIRSTCHAR
EM_QUERYREADONLY
EM_QUERYSEL
EM_SETFIRSTCHAR
EM_SETINSERTMODE
EM_SETREADONLY
EM_SETSEL
EM_SETTEXTLIMIT
WM_CONTROL and WM_PCONTROL with these notifications:
EN_CHANGE
- 13 -
EN_INSERTMODETOGGLE
EN_KILLFOCUS
EN_MEMERROR
EN_OVERFLOW
EN_SCROLL
EN_SETFOCUS
and unknown notifications
- Subgroup: messages related to the List Box control.
The following messages are traced:
LM_DELETEALL
LM_DELETEITEM
LM_INSERTITEM
LM_QUERYITEMCOUNT
LM_QUERYITEMHANDLE
LM_QUERYITEMTEXT
LM_QUERYITEMTEXTLENGTH
LM_QUERYSELECTION
LM_QUERYTOPINDEX
LM_SEARCHSTRING
LM_SELECTITEM
LM_SETITEMHANDLE
LM_SETITEMHEIGHT
LM_SETITEMTEXT
LM_SETTOPINDEX
WM_CONTROL and WM_PCONTROL with these notifications:
LN_ENTER
LN_KILLFOCUS
LN_SCROLL
LN_SELECT
LN_SETFOCUS
and unknown notifications
WM_DRAWITEM
WM_MEASUREITEM
- Subgroup: messages related to the Scroll Bar control.
The following messages are traced:
SBM_QUERYPOS
SBM_QUERYRANGE
SBM_SETPOS
SBM_SETSCROLLBAR
SBM_SETTHUMBSIZE
WM_HSCROLL
WM_VSCROLL
- Subgroup: Messages related to the Title Bar control.
The following messages are traced:
- 14 -
TBM_QUERYHILITE
TBM_SETHILITE
- Subgroup: messages related to the Multi-Line Entry Field
control.
The following messages are traced:
MLM_CHARFROMLINE
MLM_CLEAR
MLM_COPY
MLM_CUT
MLM_DELETE
MLM_DISABLEREFRESH
MLM_ENABLEREFRESH
MLM_EXPORT
MLM_FORMAT
MLM_IMPORT
MLM_INSERT
MLM_LINEFROMCHAR
MLM_PASTE
MLM_QUERYBACKCOLOR
MLM_QUERYCHANGED
MLM_QUERYFIRSTCHAR
MLM_QUERYFONT
MLM_QUERYFORMATLINELENGTH
MLM_QUERYFORMATRECT
MLM_QUERYFORMATTEXTLENGTH
MLM_QUERYIMPORTEXPORT
MLM_QUERYLINECOUNT
MLM_QUERYLINELENGTH
MLM_QUERYREADONLY
MLM_QUERYSEL
MLM_QUERYSELTEXT
MLM_QUERYTABSTOP
MLM_QUERYTEXTCOLOR
MLM_QUERYTEXTLENGTH
MLM_QUERYTEXTLIMIT
MLM_QUERYUNDO
MLM_QUERYWRAP
MLM_RESETUNDO
MLM_SEARCH
MLM_SETBACKCOLOR
MLM_SETCHANGED
MLM_SETFIRSTCHAR
MLM_SETFONT
MLM_SETFORMATRECT
MLM_SETIMPORTEXPORT
MLM_SETREADONLY
MLM_SETSEL
MLM_SETTABSTOP
MLM_SETTEXTCOLOR
- 15 -
MLM_SETTEXTLIMIT
MLM_SETWRAP
MLM_UNDO
WM_CONTROL and WM_PCONTROL with these notifications:
MLN_CHANGE
MLN_CLPBDFAIL
MLN_HSCROLL
MLN_KILLFOCUS
MLN_MARGIN
MLN_MEMERROR
MLN_OVERFLOW
MLN_PIXHORZOVERFLOW
MLN_PIXVERTOVERFLOW
MLN_SEARCHPAUSE
MLN_SETFOCUS
MLN_TEXTOVERFLOW
MLN_UNDOOVERFLOW
MLN_VSCROLL
and unknown notifications
- Subgroup: messages related to the AppStat control.
No messages are traced.
- Subgroup: messages related to the KbdStat control.
No messages are traced.
- Subgroup: messages related to the Pecic control.
No messages are traced.
- Subgroup: messages related to the DBE_KKPopup control.
No messages are traced.
- Subgroup: messages related to the Spin Button control.
The following messages are traced:
SPBM_OVERRIDESETLIMITS
SPBM_QUERYLIMITS
SPBM_QUERYVALUE
SPBM_SETARRAY
SPBM_SETCURRENTVALUE
SPBM_SETLIMITS
SPBM_SETMASTER
SPBM_SETTEXTLIMIT
SPBM_SPINDOWN
SPBM_SPINUP
- 16 -
WM_CONTROL and WM_PCONTROL with these notifications:
SPBN_CHANGE
SPBN_DOWNARROW
SPBN_ENDSPIN
SPBN_KILLFOCUS
SPBN_SETFOCUS
SPBN_UPARROW
and unknown notifications
- Subgroup: messages related to the Container control.
The following messages are traced:
CM_ALLOCDETAILFIELDINFO
CM_ALLOCRECORD
CM_ARRANGE
CM_CLOSEEDIT
CM_COLLAPSETREE
CM_ERASERECORD
CM_EXPANDTREE
CM_FILTER
CM_FREEDETAILFIELDINFO
CM_FREERECORD
CM_HORZSCROLLSPLITWINDOW
CM_INSERTDETAILFIELDINFO
CM_INSERTRECORD
CM_INVALIDATEDETAILFIELDINFO
CM_INVALIDATERECORD
CM_OPENEDIT
CM_PAINTBACKGROUND
CM_QUERYCNRINFO
CM_QUERYDETAILFIELDINFO
CM_QUERYDRAGIMAGE
CM_QUERYRECORD
CM_QUERYRECORDEMPHASIS
CM_QUERYRECORDFROMRECT
CM_QUERYRECORDINFO
CM_QUERYRECORDRECT
CM_QUERYVIEWPORTRECT
CM_REMOVEDETAILFIELDINFO
CM_REMOVERECORD
CM_SCROLLWINDOW
CM_SEARCHSTRING
CM_SETCNRINFO
CM_SETRECORDEMPHASIS
CM_SORTRECORD
WM_CONTROL and WM_PCONTROL with these notifications:
CN_BEGINEDIT
CN_COLLAPSETREE
CN_CONTEXTMENU
- 17 -
CN_DRAGAFTER
CN_DRAGLEAVE
CN_DRAGOVER
CN_DROP
CN_DROPHELP
CN_EMPHASIS
CN_ENDEDIT
CN_ENTER
CN_EXPANDTREE
CN_HELP
CN_INITDRAG
CN_KILLFOCUS
CN_QUERYDELTA
CN_REALLOCPSZ
CN_SCROLL
CN_SETFOCUS
and unknown notifications
WM_DRAWITEM
- Subgroup: messages related to the Slider control.
The following messages are traced:
SLM_ADDDETENT
SLM_QUERYDETENTPOS
SLM_QUERYSCALETEXT
SLM_QUERYSLIDERINFO
SLM_QUERYTICKPOS
SLM_QUERYTICKSIZE
SLM_REMOVEDETENT
SLM_SETSCALETEXT
SLM_SETSLIDERINFO
SLM_SETTICKSIZE
WM_CONTROL and WM_PCONTROL with these notifications:
SLN_CHANGE
SLN_KILLFOCUS
SLN_SETFOCUS
SLN_SLIDERTRACK
and unknown notifications
WM_DRAWITEM
- Subgroup: messages related to the Value Set control.
The following messages are traced:
VM_QUERYITEM
VM_QUERYITEMATTR
VM_QUERYMETRICS
VM_QUERYSELECTEDITEM
VM_SELECTITEM
- 18 -
VM_SETITEM
VM_SETITEMATTR
VM_SETMETRICS
WM_CONTROL and WM_PCONTROL with these notifications:
VN_DRAGLEAVE
VN_DRAGOVER
VN_DROP
VN_DROPHELP
VN_ENTER
VN_HELP
VN_INITDRAG
VN_KILLFOCUS
VN_SELECT
VN_SETFOCUS
and unknown notifications
WM_DRAWITEM
- Subgroup: messages related to the Notebook control.
The following messages are traced:
BKM_CALCPAGERECT
BKM_DELETEPAGE
BKM_INSERTPAGE
BKM_INVALIDATETABS
BKM_QUERYPAGECOUNT
BKM_QUERYPAGEDATA
BKM_QUERYPAGEID
BKM_QUERYPAGESTYLE
BKM_QUERYPAGEWINDOWHWND
BKM_QUERYSTATUSLINETEXT
BKM_QUERYTABBITMAP
BKM_QUERYTABTEXT
BKM_SETDIMENSIONS
BKM_SETNOTEBOOKCOLORS
BKM_SETPAGEDATA
BKM_SETPAGEWINDOWHWND
BKM_SETSTATUSLINETEXT
BKM_SETTABBITMAP
BKM_SETTABTEXT
BKM_TURNTOPAGE
WM_CONTROL and WM_PCONTROL with these notifications:
BKN_HELP
BKN_NEWPAGESIZE
BKN_PAGEDELETED
BKN_PAGESELECTED
and unknown notifications
WM_DRAWITEM
- 19 -
- Subgroup: Other messages.
In this group are some WM_CONTROL, WM_PCONTROL, WM_MEASUREITEM
and WM_DRAWITEM messages that are erroneous, undocumented or
cannot be interpreted.
- Regarding WM_CONTROL and WM_PCONTROL:
WM_CONTROL messages are sent by a window to notify its owner
of significant events. Upon receiving one of them, they can
also be sent by a frame window to notify their client of the
same event. WM_PCONTROL messages are posted to the
application queue. A window whose class is not a:
Button
Combo Box
Container
Entry Field
List Box
Multi-Line Entry Field
Notebook
Slider
Spin Button
Value Set
generates a message traced in this group. Since no
notification is defined for a window of such a class, the
parameters of the WM_CONTROL or WM_PCONTROL message cannot
be interpreted.
- Regarding WM_MEASUREITEM:
When a window which is not a:
List Box
Menu
sends a WM_MEASUREITEM to its owner, the WM_MEASUREITEM
message is traced in this group because the second message
parameter cannot be interpreted.
- Regarding WM_DRAWITEM:
When a window which is not a:
Container
List Box
Menu
Notebook
Slider
Value Set
- 20 -
sends a WM_DRAWITEM to its owner, the WM_DRAWITEM message is
traced in this group because the second message parameter
cannot be interpreted.
- Group: Keyboard messages.
The following messages are traced:
WM_CHAR
WM_JOURNALNOTIFY
WM_VIOCHAR (See Note)*
*Note: The parameters of the WM_VIOCHAR message are undocumented.
- Group: Mouse messages.
The following messages are traced:
WM_BUTTON1CLICK
WM_BUTTON1DBLCLK
WM_BUTTON1DOWN
WM_BUTTON1UP
WM_BUTTON2CLICK
WM_BUTTON2DBLCLK
WM_BUTTON2DOWN
WM_BUTTON2UP
WM_BUTTON3CLICK
WM_BUTTON3DBLCLK
WM_BUTTON3DOWN
WM_BUTTON3UP
WM_CHORD (See Note)*
WM_CONTROLPOINTER
WM_HITTEST
WM_MOUSEMAP
WM_MOUSEMOVE
*Note: The first parameter of the WM_CHORD message is
undocumented. This message occurs when the operator presses both
button one and button two on the pointing device.
- Group: Clipboard messages.
The following messages are traced:
WM_DESTROYCLIPBOARD
WM_DRAWCLIPBOARD
WM_HSCROLLCLIPBOARD
WM_PAINTCLIPBOARD
WM_RENDERALLFMTS
WM_RENDERFMT
WM_SIZECLIPBOARD
WM_VSCROLLCLIPBOARD
- 21 -
- Group: Dynamic Data Exchange messages.
The following messages are traced:
WM_DDE_ACK
WM_DDE_ADVISE
WM_DDE_DATA
WM_DDE_EXECUTE
WM_DDE_INITIATE
WM_DDE_INITIATEACK
WM_DDE_POKE
WM_DDE_REQUEST
WM_DDE_TERMINATE
WM_DDE_UNADVISE
- Group: Help messages.
The following messages are traced:
HM_ACTIONBAR_COMMAND
HM_CONTROL
HM_CREATE_HELP_TABLE
HM_DISMISS_WINDOW
HM_DISPLAY_HELP
HM_ERROR
HM_EXT_HELP
HM_EXT_HELP_UNDEFINED
HM_HELPSUBITEM_NOT_FOUND
HM_HELP_CONTENTS
HM_HELP_INDEX
HM_INFORM
HM_INVALIDATE_DDF_DATA
HM_KEYS_HELP
HM_LOAD_HELP_TABLE
HM_NOTIFY
HM_QUERY
HM_QUERY_DDF_DATA
HM_QUERY_KEYS_HELP
HM_REPLACE_HELP_FOR_HELP
HM_SET_ACTIVE_WINDOW
HM_SET_COVERPAGE_SIZE
HM_SET_HELP_LIBRARY_NAME
HM_SET_HELP_WINDOW_TITLE
HM_SET_OBJCOM_WINDOW
HM_SET_SHOW_PANEL_ID
HM_SET_USERDATA
HM_TUTORIAL
HM_UPDATE_OBJCOM_WINDOW_CHAIN
- Group: Direct Manipulation (Drag & Drop) messages.
The following messages are traced:
DM_DISCARDOBJECT
- 22 -
DM_DRAGERROR
DM_DRAGFILECOMPLETE
DM_DRAGLEAVE
DM_DRAGOVER
DM_DRAGOVERNOTIFY
DM_DROP
DM_DROPHELP
DM_EMPHASIZETARGET
DM_ENDCONVERSATION
DM_FILERENDERED
DM_PRINT
DM_PRINTOBJECT
DM_RENDER
DM_RENDERCOMPLETE
DM_RENDERFILE
DM_RENDERPREPARE
WM_BEGINDRAG
WM_BUTTON1MOTIONEND
WM_BUTTON1MOTIONSTART
WM_BUTTON2MOTIONEND
WM_BUTTON2MOTIONSTART
WM_BUTTON3MOTIONEND
WM_BUTTON3MOTIONSTART
WM_ENDDRAG
- Group: Double-Byte Character Set messages.
The following messages are traced:
WM_DBE_KKCPARAMS
WM_DBE_SETAPPLSTAT
WM_QUERYCONVERTPOS
and all other messages, not appearing in the above list, in the
range from WM_DBCSFIRST to WM_DBCSLAST. The messages that do not
have a name are traced as "(DBCS?) MsgNumber", where MsgNumber is
shown in hexadecimal and decimal.
The messages traced are those defined in the toolkit include
files.
- Group: Pen messages.
No pen message is defined in Presentation Manager. Messages
falling in the range WM_PENFIRST thru WM_PENLAST will be traced
and named as "(PEN?) MsgNumber".
- Group: MultiMedia messages.
Multimedia messages are not interpreted in the current version
of PMM. Messages falling in the range WM_MMPMFIRST thru
WM_MMPMLAST will be traced and named as "(MM?) MsgNumber".
- 23 -
- Group: System messages.
The following messages are traced:
PL_ALTERED
WM_APPTERMINATENOTIFY
WM_PSYSCOLORCHANGE
WM_REALIZEPALETTE
WM_SYSCOLORCHANGE
WM_SYSVALUECHANGED
- Group: Miscellaneous messages.
The following messages are traced:
WM_BEGINSELECT
WM_CONTEXTMENU
WM_ENDSELECT
WM_OPEN
WM_SEM1
WM_SEM2
WM_SEM3
WM_SEM4
WM_SINGLESELECT
WM_TEXTEDIT
WM_TIMER
- Group: File Dialog messages.
The following messages are traced:
FDM_ERROR
FDM_FILTER
FDM_VALIDATE
- Group: Font Dialog messages.
The following messages are traced:
FNTM_COLORCHANGED (See Note)*
FNTM_FACENAMECHANGED
FNTM_FILTERLIST
FNTM_POINTSIZECHANGED
FNTM_STYLECHANGED
FNTM_UPDATEPREVIEW
*Note: The parameters of the FNTM_COLORCHANGED message are
undocumented.
- Group: Reserved messages.
The following messages are traced:
0x0054
0x005a
0x041a
- 24 -
0x041b
0x041c
0x041d
0x041e
0x041f
- Group: Undocumented messages.
Messages that do not belong to any of the above groups are traced.
All of these messages are undocumented. Also, included in this
group are the following three messages, whose name is known, but
not their parameters or usage:
PM_INVALIDATECELL = WM_USER + 1000 (decimal)
WM_CONTROLHEAP = 39 (hexadecimal)
WM_OTHERWINDOWDESTROYED = 3 (hexadecimal)
- Group: User messages.
User messages, i.e. messages greater than or equal to the WM_USER
constant (excluding the File Dialog messages, the Font Dialog
messages and the PM_INVALIDATECELL message).
6. The PMM Interface
════════════════════
This section describes the PMM interface to an application.
List of Functions
═════════════════
PMMCreateTraceSession
─────────────────────
This function creates a trace session. A message queue must exist
before invoking this function. Windows associated with the message
queue created by the calling thread will be traced. A line is
written to the trace file indicating that a trace session has been
created.
Function Syntax:
PMMRET pmmr;
HPMMSESSION hpmms;
PSZ pszTraceFileName = "pmm.log";
pmmr = PMMCreateTraceSession( &hpmms, hab, pszTraceFileName );
- 25 -
Parameters:
hpmms (HPMMSESSION) - output
Session handle returned by the function. Unaltered if the
function fails.
hab (HAB) - input
Anchor-block handle.
pszTraceFileName (PSZ) - input
Address of an ASCIIZ string with the path and filename of the
file into which the trace information will be written.
Return Values:
Success:
PMMESuccess
Error: one of the following:
PMMECannotQueryOS2Version
PMMECannotRunInThisOS2Version
PMMEMultipleSessionsNotAllowed
PMMECannotQueryDesktopWindow
PMMECannotQueryObjectWindow
PMMENotEnoughMemory
PMMECannotRegisterInternalClass
PMMECannotCreateInternalWindow
PMMECannotSetSendMsgHook
PMMECannotSetInputMsgHook
PMMECannotOpenTraceFile
PMMEWriteFailed
PMMECannotCloseTraceFile
PMMStartTracing
───────────────
This function opens the trace file and starts tracing messages. A
line is written to the trace file indicating that tracing has been
started. The trace file is opened using DosOpen. If the file does
not exist, it is created; if the file exists, its contents are
preserved and the trace information is appended at the end of the
file. Other applications cannot write to the file while the file is
open. This file is write-only.
Function Syntax:
PMMRET pmmr;
HPMMSESSION hpmms;
pmmr = PMMStartTracing( hpmms );
- 26 -
Parameters:
hpmms (HPMMSESSION) - input
Session handle returned by a previous call to
PMMCreateTraceSession.
Return Values:
Success:
PMMESuccess
Error: one of the following:
PMMETraceSessionNotCreated
PMMEInvalidHandle
PMMEAlreadyTracing
PMMECannotOpenTraceFile
PMMEWriteFailed
PMMStopTracing
──────────────
This function stops tracing messages. A line is written to the
trace file indicating that tracing has been stopped. The trace file
is closed and ready to be examined.
Function Syntax:
PMMRET pmmr;
HPMMSESSION hpmms;
pmmr = PMMStopTracing( hpmms );
Parameters:
hpmms (HPMMSESSION) - input
Session handle returned by a previous call to
PMMCreateTraceSession.
Return Values:
Success:
PMMESuccess
Error: one of the following:
PMMETraceSessionNotCreated
PMMEInvalidHandle
PMMENotTracingNow
PMMEWriteFailed
PMMECannotCloseTraceFile
- 27 -
PMMDestroyTraceSession
──────────────────────
This function destroys a trace session. A line is written to the
trace file indicating that a trace session has been destroyed.
Function Syntax:
PMMRET pmmr;
HPMMSESSION hpmms;
pmmr = PMMDestroyTraceSession( hpmms );
Parameters:
hpmms (HPMMSESSION) - input
Session handle returned by a previous call to
PMMCreateTraceSession.
Return Values:
Success:
PMMESuccess
Error: one of the following:
PMMETraceSessionNotCreated
PMMEInvalidHandle
PMMEWriteFailed
PMMECannotCloseTraceFile
PMMECannotReleaseInputMsgHook
PMMECannotReleaseSendMsgHook
PMMECannotDestroyInternalWindow
PMMECannotOpenTraceFile
PMMQueryVersion
───────────────
This function queries the current version of PMM.
Function Syntax:
PMMRET pmmr;
HPMMSESSION hpmms;
ULONG ulVersion;
pmmr = PMMQueryVersion( hpmms, &ulVersion );
Parameters:
hpmms (HPMMSESSION) - input
Session handle returned by a previous call to
PMMCreateTraceSession.
- 28 -
ulVersion (ULONG) - output
Current version of PMM. The major version is returned in the
higher 16 bits, the minor version in the lower 16 bits.
Return Values:
Success:
PMMESuccess
Error: one of the following:
PMMETraceSessionNotCreated
PMMEInvalidHandle
Notes:
Useful to determine the functionality that is currently supported
by PMM.
PMMQueryTraceFileHandle
───────────────────────
This function retrieves the handle of the trace file. An
application may write any text to the trace file using the OS/2 API
DosWrite, with the handle returned from this call. Since the trace
file is opened by PMMStartTracing and closed by PMMStopTracing, you
must be tracing at the time this function is invoked.
Function Syntax:
PMMRET pmmr;
HPMMSESSION hpmms;
HFILE hTraceFile;
pmmr = PMMQueryTraceFileHandle( hpmms, &hTraceFile );
Parameters:
hpmms (HPMMSESSION) - input
Session handle returned by a previous call to
PMMCreateTraceSession.
hTraceFile (HFILE) - output
Handle of the trace file. Unaltered if the function fails.
Return Values:
Success:
PMMESuccess
Error: one of the following:
PMMETraceSessionNotCreated
PMMEInvalidHandle
PMMENotTracingNow
- 29 -
Notes:
See the functions PMMStartTracing and PMMStopTracing.
PMMSetMsgGroupsToTrace
──────────────────────
For tracing purposes, all the PM messages are divided into
categories or groups, according to functionality. This function
sets the message groups to trace. A line is written to the trace
file when this function is called, indicating what groups are
currently being traced.
Function Syntax:
PMMRET pmmr;
HPMMSESSION hpmms;
ULONG ulMask;
ULONG ulFlags;
pmmr = PMMSetMsgGroupsToTrace( hpmms, ulMask, ulFlags );
Parameters:
hpmms (HPMMSESSION) - input
Session handle returned by a previous call to
PMMCreateTraceSession.
ulMask (ULONG) - input
The mask is formed by combining zero or more constants in a
logical OR operation. Its use is described in the ulFlags
section, below. The following constants, defined in PMM.H,
may be used in the mask:
PMMTMG_WINDOW
PMMTMG_CONTROLS
PMMTMG_KEYBOARD
PMMTMG_MOUSE
PMMTMG_CLIPBOARD
PMMTMG_DDE
PMMTMG_HELP
PMMTMG_DIRECT_MANIP
PMMTMG_DBCS
PMMTMG_PEN
PMMTMG_MULTIMEDIA
PMMTMG_SYSTEM
PMMTMG_OTHER
PMMTMG_FILE_DIALOG
PMMTMG_FONT_DIALOG
PMMTMG_RESERVED
PMMTMG_UNDOCUMENTED
- 30 -
PMMTMG_USER
PMMTMG_ALL
ulFlags (ULONG) - input
The ulFlags parameter is formed by combining zero or more
constants in a logical OR operation. If the corresponding
value in the mask is set, values present in this parameter
will be interpreted as TRUE (trace this group of messages)
while their absence will be interpreted as FALSE (do not
trace this group of messages). If a value is not present
in the parameter ulMask, the corresponding value in the
parameter ulFlags will be ignored. The same constants used
in the parameter ulMask may be used.
Return Values:
Success:
PMMESuccess
Error: one of the following:
PMMETraceSessionNotCreated
PMMEInvalidHandle
PMMECannotOpenTraceFile
PMMEWriteFailed
PMMECannotCloseTraceFile
Default values at startup:
PMMTMG_ALL for ulMask. All flags will be processed.
PMMTMG_ALL for ulFlags. All message groups will be traced.
Notes:
Undefined values in the parameters ulMask and ulFlags are
ignored. Because more groups may be added in the future, an
application should not use undefined values.
PMMSetControlsToTrace
─────────────────────
Messages related to PM controls are organized in groups. These
groups belong to the more general group of 'Controls'. This
function sets the PM controls to trace. For this function to have
any effect, the flag PMMTMG_CONTROLS (mentioned in the function
PMMSetMsgGroupsToTrace) must be set to trace the messages related
to one or more controls. A line is written to the trace file when
this function is invoked, indicating which controls are currently
being traced.
Function Syntax:
PMMRET pmmr;
HPMMSESSION hpmms;
ULONG ulMask;
- 31 -
ULONG ulFlags;
pmmr = PMMSetControlsToTrace( hpmms, ulMask, ulFlags );
Parameters:
hpmms (HPMMSESSION) - input
Session handle returned by a previous call to
PMMCreateTraceSession.
ulMask (ULONG) - input
The mask is formed by combining zero or more constants in a
logical OR operation. Its use is described in the ulFlags
section, below. The following constants, defined in PMM.H,
may be used in the mask:
PMMTCO_FRAME
PMMTCO_COMBOBOX
PMMTCO_BUTTON
PMMTCO_MENU
PMMTCO_STATIC
PMMTCO_ENTRYFIELD
PMMTCO_LISTBOX
PMMTCO_SCROLLBAR
PMMTCO_TITLEBAR
PMMTCO_MLE
PMMTCO_APPSTAT
PMMTCO_KBDSTAT
PMMTCO_PECIC
PMMTCO_DBE_KKPOPUP
PMMTCO_SPINBUTTON
PMMTCO_CONTAINER
PMMTCO_SLIDER
PMMTCO_VALUESET
PMMTCO_NOTEBOOK
PMMTCO_OTHER
PMMTCO_ALL
ulFlags (ULONG) - input
The ulFlags parameter is formed by combining zero or more
constants in a logical OR operation. If the corresponding
value in the mask is set, values present in this parameter
will be interpreted as TRUE (trace this group of messages)
while their absence will be interpreted as FALSE (do not
trace this group of messages). If a value is not present
in the parameter ulMask, the corresponding value in the
parameter ulFlags will be ignored. The same constants used
in the parameter ulMask may be used.
- 32 -
Return Values:
Success:
PMMESuccess
Error: one of the following:
PMMETraceSessionNotCreated
PMMEInvalidHandle
PMMECannotOpenTraceFile
PMMEWriteFailed
PMMECannotCloseTraceFile
Default values at startup:
PMMTCO_ALL for ulMask. All flags will be processed.
PMMTCO_ALL for ulFlags. All messages corresponding to the above
list of controls will be traced.
Notes:
Undefined values in the parameters ulMask and ulFlags are
ignored. Because more groups may be added in the future, an
application should not use undefined values.
PMMShowWindowText
─────────────────
This function controls whether PMM should show the text of a window
in a message. This is useful for identifying windows. Square
brackets denote optional items. The window text is shown in this
format:
"WindowText"[a][t]
where:
- 'WindowText' is the text of the window.
- The suffix 'a' means (a)ltered, i.e. the original window text has
been altered by PMM. Some windows have control characters like
CR, LF in their text. Showing the control characters in a text
file produces confusion since the trace line splits into several
parts. The suffix indicates that all HT, LF, CR and SUB characters
have been converted into spaces.
- The suffix 't' means (t)rimmed, i.e. the window text has been
trimmed. The maximum text length shown is 20 characters.
Function Syntax:
PMMRET pmmr;
HPMMSESSION hpmms;
BOOL bShow;
bShow = TRUE;
pmmr = PMMShowWindowText( hpmms, bShow );
- 33 -
Parameters:
hpmms (HPMMSESSION) - input
Session handle returned by a previous call to
PMMCreateTraceSession.
bShow (BOOL) - input
Show window text indicator:
TRUE
Show the window text.
FALSE
Do not show the window text.
Return Values:
Success:
PMMESuccess
Error: one of the following:
PMMETraceSessionNotCreated
PMMEInvalidHandle
Default value at startup:
The window text will be shown.
Notes:
Some windows do not have a "Text" property. The window text is
shown if the window has this property and the text is not an
empty string. If the text contains embedded double quotes, which
are used as a text delimiter, the embedded double quotes are
simply displayed. For instance, the following window text has
unbalanced quotes and is correct:
"Viewing "It is a Won"t
PMMShowClassName
────────────────
This function controls whether PMM should show the class name of a
window in a message. This is useful for identifying some windows
that do not have text. Square brackets denote optional items. The
class name is shown in this format:
(ClassName)[t][u]
where:
- 'ClassName' is the name of the class. The following literals are
used to identify standard PM classes:
Frame
ComboBox
- 34 -
Button
Menu
Static
EntryField
ListBox
ScrollBar
TitleBar
MLE
AppStat
KbdStat
Pecic
DBE_KKPopUp
SpinButton
Container
Slider
ValueSet
Notebook
- The suffix 't' means (t)rimmed, i.e. the class name has been
trimmed. The maximum class name length shown is 20 characters.
- The suffix 'u' means (u)ser. All classes that are not in the
above list are considered user defined, whether they are system
defined or user defined.
Function Syntax:
PMMRET pmmr;
HPMMSESSION hpmms;
BOOL bShow;
bShow = TRUE;
pmmr = PMMShowClassName( hpmms, bShow );
Parameters:
hpmms (HPMMSESSION) - input
Session handle returned by a previous call to
PMMCreateTraceSession.
bShow (BOOL) - input
Show class name indicator:
TRUE
Show the class name.
FALSE
Do not show the class name.
Return Values:
Success:
PMMESuccess
Error: one of the following:
PMMETraceSessionNotCreated
PMMEInvalidHandle
- 35 -
Default value at startup:
The class name will be shown.
Notes:
You can register, for instance, a class named "ListBox". The
suffix 'u' is intended to resolve any ambiguity between standard
PM classes and user defined classes.
PMMShowWindowID
───────────────
This function controls whether PMM should show the identifier (ID)
of a window in a message. If the window or control has a predefined
identifier, like FID_MENU, it will be shown; otherwise the window
identifier, a number, will be shown. This is useful for identifying
some windows that do not have text.
Function Syntax:
PMMRET pmmr;
HPMMSESSION hpmms;
BOOL bShow;
bShow = TRUE;
pmmr = PMMShowWindowID( hpmms, bShow );
Parameters:
hpmms (HPMMSESSION) - input
Session handle returned by a previous call to
PMMCreateTraceSession.
bShow (BOOL) - input
Show window ID indicator:
TRUE
Show the window ID.
FALSE
Do not show the window ID.
Return Values:
Success:
PMMESuccess
Error: one of the following:
PMMETraceSessionNotCreated
PMMEInvalidHandle
Default value at startup:
The window ID will not be shown.
- 36 -
Notes:
A window ID is always considered as a 16 bit signed number, in
the range -32768 to 32767.
PMMShowPointers
───────────────
This function controls whether PMM should show the pointers and
string handles that are used in a message. This is useful for
checking that pointers point to the intended objects.
PMM tests all pointers and string handles used in a message, whether
they are to be shown or not. PMM was designed to not introduce side
effects to an application. All pointers involved in a message are
tested since printing the value they point to would produce a
protection violation.
Testing a pointer means to make sure the object pointed to can be
accessed. For a string object, the "object size" is considered as
"all the characters up to the '\0' (included);" for all other
objects the object size is the size defined in PM include files.
Pointer names are displayed beginning with 'p' or 'ap'. 'p' stands
for (p)ointer, 'a' for (a)rray. String handles begin with 'hstr'.
A descriptive name follows the prefix. Pointer values are shown in
hexadecimal, string handles in decimal.
A pointer or string handle is shown using the format below. One of
a list of items enclosed in braces appears always. Square brackets
denote optional items. Vertical bars separating items indicate that
one of the items will appear. '->' is used as a continuation mark.
The format is:
{p | ap | hstr}DescriptiveName: [0xnnnnnnnn | NULL | 0] ->
[(Not allocated) | (Not accessible) | (Invalid) | (Size?)] ->
[(Out)]
where:
- '(Not allocated)' can be shown for any generic pointer (except
with pointers to a DRAGINFO structure).
- '(Not accessible)' can be shown for pointers that point to a
DRAGINFO structure (tested with DrgAccessDraginfo).
- '(Invalid)' can be shown for string handles.
- '(Size?) can be shown for pointers to a string if the string size
used in the message is zero. In this case the pointer cannot be
tested for accessibility.
If a pointer or string handle is "invalid" for some reason, PMM
shows its name and value, regardless of the setting of this
- 37 -
function. This is done to inform you that the value(s) pointed to
cannot be printed and that there is a potential problem with this
pointer.
Some message parameters are defined as output, so they are pointers
to an object. The parameter output value is printed on return from
the message handler. Failing to mention the parameter in the
message call would produce confusion when reading the message trace,
since the parameter would be missing. To avoid this, PMM ignores
the setting of this function; that is, on an output parameter the
pointer name is always printed, possibly followed of the pointer
value, and followed by the literal '(Out)'. Example ('->' is used
as a continuation mark, ellipsis indicates that some information is
not shown):
2147483839 (Container) CM_QUERYCNRINFO pCnrInfo: (Out) ->
Bytes to copy: 92 Sent
2147483839 (Container) CM_QUERYCNRINFO Returns Bytes ->
copied: 92 [CNRINFO: cb: 92 pSortRecord: NULL ... ->
xVertSplitbar: -1<No splitbar>]
Function Syntax:
PMMRET pmmr;
HPMMSESSION hpmms;
BOOL bShow;
bShow = TRUE;
pmmr = PMMShowPointers( hpmms, bShow );
Parameters:
hpmms (HPMMSESSION) - input
Session handle returned by a previous call to
PMMCreateTraceSession.
bShow (BOOL) - input
Show pointers indicator:
TRUE
Show the pointers and string handles.
FALSE
Do not show the pointers and string handles.
Return Values:
Success:
PMMESuccess
Error: one of the following:
PMMETraceSessionNotCreated
PMMEInvalidHandle
- 38 -
Default value at startup:
Pointers and string handles will not be shown.
Notes:
For purposes of this function, string handles are considered to
be pointers, even though they are not.
The following behavior, though rare, may occur:
Pointers to objects and pointers inside objects are always
tested before the message arrives at the destination window. It
may occur that, when sending a message, one of the parameters of
the message is a pointer, which points to an object that has more
pointers inside it, and so on. All these pointers are tested
before the final message call is done. The destination window
cannot modify the parameters of the message (passed by value) but
it can modify the pointers inside objects to point to
inaccessible objects. After returning from a message call, PMM
does not retest the pointers inside objects.
PMMShowAllArrayItems
────────────────────
This function controls whether PMM should show all the array items
when arrays appear in messages. By default, PMM will not show all
array items, i.e. it will show a maximum of five array items,
either:
- the first five, if they exist, or
- the first two and the last two, if the array has more than five
items.
If the second form is used, an ellipsis (...) is placed between the
first two items and the last two, to indicate that there are items
not shown. An array item is identified by its name and by an index,
zero based. The index, following the "C" syntax, is enclosed
between square brackets.
Function Syntax:
PMMRET pmmr;
HPMMSESSION hpmms;
BOOL bShow;
bShow = TRUE;
pmmr = PMMShowAllArrayItems( hpmms, bShow );
Parameters:
hpmms (HPMMSESSION) - input
- 39 -
Session handle returned by a previous call to
PMMCreateTraceSession.
bShow (BOOL) - input
Show all array items indicator:
TRUE
Show all array items.
FALSE
Do not show all array items, only some.
Return Values:
Success:
PMMESuccess
Error: one of the following:
PMMETraceSessionNotCreated
PMMEInvalidHandle
Default value at startup:
Not all array items will be shown, only some.
PMMShowAllLinkedListItems
─────────────────────────
This function controls whether PMM should show all the linked list
items when linked lists appear in messages. By default, PMM will
not show all linked list items, i.e. it will show a maximum of five
linked list items, either:
- the first five, if they exist, or
- the first two and the last two, if the linked list has more than
five items.
If the second form is used, an ellipsis (...) is placed between
the first two items and the last two, to indicate that there are
items not shown. A linked list item is identified by its name and
by an index, zero based. The index is enclosed between forward
slashes.
Function Syntax:
PMMRET pmmr;
HPMMSESSION hpmms;
BOOL bShow;
bShow = TRUE;
pmmr = PMMShowAllLinkedListItems( hpmms, bShow );
Parameters:
hpmms (HPMMSESSION) - input
- 40 -
Session handle returned by a previous call to
PMMCreateTraceSession.
bShow (BOOL) - input
Show all linked list items indicator:
TRUE
Show all linked list items.
FALSE
Do not show all linked list items, only some.
Return Values:
Success:
PMMESuccess
Error: one of the following:
PMMETraceSessionNotCreated
PMMEInvalidHandle
Default value at startup:
Not all linked list items will be shown, only some.
PMMShowFullMsgInfo
──────────────────
Sometimes, in order to show the maximum information for the
messages being traced, PMM needs to send a message to a window.
Such a message wouldn't have been sent if the application were not
using PMM, i.e. the message does not belong to the "normal"
application message stream. For instance, to interpret the return
value of a VM_QUERYITEM message, PMM needs to know the VIA_*
attribute of the value set. A VM_QUERYITEMATTR is sent to the
value set. This guarantees that the message is properly interpreted
and gives the maximum information for a message.
To obtain a "clean" message stream, or if you are experiencing any
trouble with messages, you can turn off this option.
This option is on by default because, for most applications, the
setting has not proved to cause undesirable effects.
The following messages, which are considered internal, are sent by
PMM to an application:
WM_QUERYWINDOWPARAMS
CM_QUERYCNRINFO
MM_QUERYITEM
VM_QUERYITEMATTR
You can always see when the above messages are sent by turning on
the option to show internal messages (See PMMShowInternalMessages).
- 41 -
Function Syntax:
PMMRET pmmr;
HPMMSESSION hpmms;
BOOL bShow;
bShow = TRUE;
pmmr = PMMShowFullMsgInfo( hpmms, bShow );
Parameters:
hpmms (HPMMSESSION) - input
Session handle returned by a previous call to
PMMCreateTraceSession.
bShow (BOOL) - input
Show full message information indicator:
TRUE
Show full information for messages being traced.
FALSE
Do not show full information for messages being traced.
Return Values:
Success:
PMMESuccess
Error: one of the following:
PMMETraceSessionNotCreated
PMMEInvalidHandle
Default value at startup:
Full message information will be shown.
Notes:
See PMMShowWindowText and PMMShowInternalMessages.
PMMShowInternalMessages
───────────────────────
PMM sends messages to windows to query the window text, and to get
some information to fully interpret a message. These messages are
called "internal", since they do not belong to the application
message stream. This function controls whether PMM should show
these messages in the trace file. PMM may send the following
messages to an application:
WM_QUERYWINDOWPARAMS
CM_QUERYCNRINFO
MM_QUERYITEM
VM_QUERYITEMATTR
- 42 -
In the trace file, an internal message is flagged with an initial
'i' and a final comment indicating the message source. The message
is shown above the message that has generated it (since it occurs
before). Also, it is shown with the same indentation that the
message that has generated it. Messages generated by internal
messages, also considered internal, are indented as usual, one level
to the right. An example follows (the '->' means that the next line
is to be interpreted as part of the current one):
...
i 2147483922 (Frame) 1 WM_QUERYWINDOWPARAMS [WNDPARAMS: ->
fsStatus: WPM_TEXT WPM_CCHTEXT cchText: 22 pszText: ->
0x006e000c (Out)] Sent by PMM
i 2147483923 (TitleBar) FID_TITLEBAR WM_QUERYWINDOWPARAMS ->
[WNDPARAMS: fsStatus: WPM_TEXT WPM_CCHTEXT cchText: 22 ->
pszText: 0x006e000c (Out)] Sent int.
i 2147483923 (TitleBar) FID_TITLEBAR WM_QUERYWINDOWPARAMS ->
Returns: Success [WNDPARAMS: fsStatus: WPM_TEXT WPM_CCHTEXT ->
cchText: 5 Text: "Style"]i
i 2147483922 (Frame) 1 WM_QUERYWINDOWPARAMS Returns: ->
Success [WNDPARAMS: fsStatus: WPM_TEXT WPM_CCHTEXT cchText: 5 ->
Text: "Style"]i
(Below is the message return that has generated the above lines)
2147483922 "Style" (Frame) 1 WM_SETWINDOWPARAMS ->
Returns: Success
...
In most cases you will not be interested in seeing internal
messages. However, this function is useful to:
- see when internal messages are sent and why. In the previous
example, on returning from a WM_SETWINDOWPARAMS call, PMM must
query the window text since it has (possibly) changed.
- identify some (rare) cases when sending an internal message
produces an exception, because the destination window is
unprepared to respond to the message at that time. If this
situation arises, depending on the message, you should turn off
the appropriate option: PMMShowWindowText or PMMShowFullMsgInfo.
Function Syntax:
PMMRET pmmr;
HPMMSESSION hpmms;
BOOL bShow;
bShow = TRUE;
pmmr = PMMShowInternalMessages( hpmms, bShow );
Parameters:
hpmms (HPMMSESSION) - input
- 43 -
Session handle returned by a previous call to
PMMCreateTraceSession.
bShow (BOOL) - input
Show internal messages indicator:
TRUE
Show internal messages.
FALSE
Do not show internal messages.
Return Values:
Success:
PMMESuccess
Error: one of the following:
PMMETraceSessionNotCreated
PMMEInvalidHandle
Default value at startup:
Internal messages will not be shown.
Notes:
See PMMShowWindowText.
PMMDefineStartStopTracingKeys
─────────────────────────────
You can start and stop tracing at any time and at any point in your
application by using the keyboard. PMM uses a key to start tracing,
and another key to stop tracing. These keys are, by default, F11 to
start tracing and F12 to stop tracing, since they are rarely used by
applications. If your application does use F11 or F12, you can use
this function to define other keys to start and/or stop tracing.
You can define the start key only, the stop key only, or both keys
at the same time.
Function Syntax:
('->' is used as a continuation mark).
PMMRET pmmr;
HPMMSESSION hpmms;
USHORT usStartKey;
USHORT usStopKey;
pmmr = PMMDefineStartStopTracingKeys( hpmms, usStartKey, ->
usStopKey );
Parameters:
hpmms (HPMMSESSION) - input
- 44 -
Session handle returned by a previous call to
PMMCreateTraceSession.
usStartKey (USHORT) - input
Key to start tracing. One of the following constants:
VK_F2
VK_F3
VK_F4
VK_F5
VK_F6
VK_F7
VK_F8
VK_F9
VK_F11
VK_F12
as defined by Presentation Manager.
Pass a 0 (zero) to leave this key unchanged.
usStopKey (USHORT) - input
Key to stop tracing. Use the same constants as defined in the
usStartKey parameter.
Pass a 0 (zero) to leave this key unchanged.
Return Values:
Success:
PMMESuccess
Error: one of the following:
PMMETraceSessionNotCreated
PMMEInvalidHandle
PMMEKeyNotDefinable
PMMEKeysCannotBeTheSame
PMMEKeyAlreadyDefined
Default value at startup:
The key to start tracing is F11. The key to stop tracing is F12.
Notes:
See PMMStartTracing and PMMStopTracing.
F1 and F10 are not allowed since they are defined by the system.
PMMQueryIfIgnoreMsg
───────────────────
PMM introduces some messages in an application message stream.
Messages are introduced as a result of:
- creating some internal windows
- querying the window text and other attributes of a window
- re-sending some messages to a window pertaining to another
process.
- 45 -
These messages do not belong to the application message stream and
should be ignored.
If you are using hooks of type HK_SENDMSG, you must use this
function in your hook handler to determine which messages belong in
the data stream you are watching. This will protect your code from
receiving messages that your application doesn't generate. Only
this type of hook needs to be protected.
Function Syntax:
PMMRET pmmr;
HPMMSESSION hpmms;
BOOL bIgnore;
pmmr = PMMQueryIfIgnoreMsg( hpmms, &bIgnore );
Parameters:
hpmms (HPMMSESSION) - input
Session handle returned by a previous call to
PMMCreateTraceSession.
bIgnore (PBOOL) - output
Indicates if the application should ignore the message
received in the hook.
Return Values:
Success:
PMMESuccess
Error: one of the following:
PMMETraceSessionNotCreated
PMMEInvalidHandle
Notes:
If you use this function, you need to use also the function
PMMSMHQueryMsg.
PMM uses queue hooks only, not system hooks. You cannot use PMM
together with software that uses hooks (or you suspect that it
uses hooks) if you do not have access to the source code. If you
use PMM with such software, the results are unpredictable.
Example:
See the example in the function PMMSMHQueryMsg.
PMMSMHQueryMsg
──────────────
In order to interpret all messages correctly PMM must alter
- 46 -
temporarily the messages sent by your application to windows of
another process. This is by design. If you are using hooks of type
HK_SENDMSG you must use this function in your hook handler to
determine whether PMM has changed the message you have just
received. Any other type of hook does not need this function.
If the message has been changed, this function tells you the message
that you should process, as it was before PMM changed it.
Function Syntax:
PMMRET pmmr;
HPMMSESSION hpmms;
PBOOL pbChanged;
PSMHSTRUCT psmh;
BOOL bChanged;
SMHSTRUCT smh;
pbChanged = &bChanged;
psmh = &smh;
pmmr = PMMSMHQueryMsg( hpmms, pbChanged, psmh );
Parameters:
hpmms (HPMMSESSION) - input
Session handle returned by a previous call to
PMMCreateTraceSession.
pbChanged (PBOOL) - output
Indicates if the message has been changed by PMM. If the
message has not been changed, the structure pointed to by the
psmh parameter is not altered.
psmh (PSMHSTRUCT) - output
If the message has been changed by PMM, this structure
contains the original values received in the send message
hook, i.e. the values that an application should process.
Return Values:
Success:
PMMESuccess
Error: one of the following:
PMMETraceSessionNotCreated
PMMEInvalidHandle
PMMEInvalidPointer
Notes:
Don't pass the same pointer that you have received as the second
parameter in the hook (psmh in the example) to this function.
This would produce an error and the structure SMHSTRUCT would not
be updated, since this would lead to an erroneous message trace.
Don't modify any of the values pointed to by the psmh pointer.
- 47 -
This would produce an erroneous message trace. See
PMMQueryIfIgnoreMsg.
Example:
VOID EXPENTRY MySendMsgHook( HAB hab
, PSMHSTRUCT psmh
, BOOL fInterTask )
{
PMMRET pmmr;
BOOL bIgnore;
BOOL bChanged;
SMHSTRUCT rSMH;
// Let's assume that hpmms is a global variable
// defined elsewhere in the application
pmmr = PMMQueryIfIgnoreMsg( hpmms, &bIgnore );
if ( pmmr == PMMESuccess )
{
// The trace session has been created,
// check whether we should ignore the message
if ( bIgnore )
return;
pmmr = PMMSMHQueryMsg( hpmms, &bChanged, &rSMH );
if ( bChanged )
{
// Changed, so we use the values in
// the rSMH structure
psmh = &rSMH;
}
}
else
{
// The trace session hasn't been created,
// so the message couldn't have been altered.
// Nothing to do here
}
// From now on, psmh points to the correct message that
// we should process
// Normal code here
} //end MySendMsgHook
PMMSubclassWindow
─────────────────
This function behaves almost exactly as the PM WinSubclassWindow
function. Note that the PMM include file PMM.H redefines
- 48 -
WinSubclassWindow as PMMSubclassWindow, so an application will use
this function instead of WinSubclassWindow. This function calls
WinSubclassWindow using the same parameters being passed to it and
returns the same value as returned by WinSubclassWindow. Before
returning, if a PMM trace session exists, it notifies PMM that a new
subclassing has been made, so as to keep track immediately of a new
window procedure.
See the section "Subclassing Windows when Using PMM," above.
Function Syntax:
HWND hwnd;
PFNWP pNewWindowProc;
PFNWP pOldWindowProc;
pOldWindowProc = PMMSubclassWindow( hwnd, pNewWindowProc );
Parameters:
hwnd (HWND) - input
Handle of window that is being subclassed.
pNewWindowProc (PFNWP) - input
New window procedure.
Return Values:
pOldWindowProc (PFNWP) - return
Old window procedure. Previous window procedure belonging
to hwnd.
If this function fails, 0L is returned.
PMMSetWindowPtr
───────────────
This function behaves almost exactly as the PM WinSetWindowPtr
function. Note that the PMM include file PMM.H redefines
WinSetWindowPtr as PMMSetWindowPtr, so an application will use this
function instead of WinSetWindowPtr. This function calls
WinSetWindowPtr using the same parameters being passed to it and
returns the same value as returned by WinSetWindowPtr. Before
returning, if a PMM trace session exists and the lb parameter is
QWP_PFNWP, it notifies PMM that a new subclassing has been made, so
as to keep track immediately of a new window procedure.
See the section "Subclassing Windows when Using PMM."
- 49 -
Function Syntax:
HWND hwnd;
LONG lb;
PVOID pp;
BOOL fSuccess;
fSuccess = PMMSetWindowPtr( hwnd, lb, pp );
Parameters:
hwnd (HWND) - input
Window handle.
lb (LONG) - input
Zero-based index into the window words. The units of b are
bytes. Valid values are zero through (cbWindowData - 4),
where cbWindowData is the parameter in WinRegisterClass that
specifies the number of bytes available for
application-defined storage.
The value QWP_PFNWP can be used as the index for the address
of the window procedure for the window.
pp (PVOID) - input
Pointer value to store in the window words.
Return Values:
fSuccess (BOOL) - return
Success indicator:
TRUE
Successful completion
FALSE
Error occurred.
PMMQueryWindowPtr
─────────────────
This function is included for completeness and for future expansion
of PMM. It behaves exactly as the PM WinQueryWindowPtr function.
Note that the PMM include file PMM.H redefines WinQueryWindowPtr as
PMMQueryWindowPtr, so an application will use this function instead
of WinQueryWindowPtr.
See the section "Subclassing Windows when Using PMM."
Function Syntax:
HWND hwnd;
- 50 -
LONG index;
PVOID pp;
pp = PMMQueryWindowPtr( hwnd, index );
Parameters:
hwnd (HWND) - input
Window handle which has the pointer to retrieve.
index (LONG) - input
Index. Zero-based index of the pointer value to retrieve.
The units of index are bytes. Valid values are zero through
(cbWindowData - 4), where cbWindowData is the parameter in
WinRegisterClass that specifies the number of bytes available
for application-defined storage.
The value QWP_PFNWP can be used for the address of the
window's window procedure.
Return Values:
pp (PVOID) - return
Pointer value.
NULL
Error occurred.
Other
Pointer value.
List of Errors and Warnings
═══════════════════════════
Errors Returned by Functions
────────────────────────────
PMMESuccess
The function has completed sucessfully.
PMMECannotQueryOS2Version
The current OS/2 version cannot be obtained. PMM currently
supports the OS/2 versions 2.1, 3.0 and 4.0.
PMMECannotRunInThisOS2Version
Your OS/2 version isn't 2.1, 3.0 or 4.0. PMM cannot run in any
other version.
PMMEMultipleSessionsNotAllowed
An application has attempted to create more than one PMM trace
session. This functionality is not supported.
PMMECannotQueryDesktopWindow
PMM has tried to query the desktop window handle and the function
has failed.
- 51 -
PMMECannotQueryObjectWindow
PMM has tried to query the desktop object window handle and the
function has failed.
PMMENotEnoughMemory
A request to allocate memory has failed.
PMMECannotRegisterInternalClass
PMM uses a window, whose class is "PMMWorkingWindow", to perform
most of its functions. The class couldn't be registered.
PMMECannotCreateInternalWindow
PMM uses a window to perform most of its functions. The window
couldn't be created.
PMMECannotSetSendMsgHook
PMM uses a queue hook to intercept messages sent by the
WinSendMsg function. The hook couldn't be set.
PMMECannotSetInputMsgHook
PMM uses a queue hook to intercept messages that are being posted
to an application queue. The hook couldn't be set.
PMMECannotOpenTraceFile
The trace file couldn't be opened.
PMMEWriteFailed
Writing to the trace file has failed. A common error is that the
disk is full.
PMMECannotCloseTraceFile
The trace file couldn't be closed.
PMMETraceSessionNotCreated
No trace session has been created.
PMMEInvalidHandle
An invalid trace session handle has been passed to a function.
PMMEAlreadyTracing
The application attempted to start tracing and PMM was already
tracing.
PMMENotTracingNow
The application attempted to stop tracing and PMM was not
tracing.
PMMECannotReleaseInputMsgHook
PMM uses a queue hook to intercept messages that are being posted
to an application queue. The hook couldn't be released.
PMMECannotReleaseSendMsgHook
PMM uses a queue hook to intercept messages sent by the
WinSendMsg function. The hook couldn't be released.
PMMECannotDestroyInternalWindow
PMM uses a window to perform most of its functions. The window
couldn't be destroyed.
PMMEKeyNotDefinable
The application attempted to define a key that isn't definable.
See the definable keys in the function
PMMDefineStartStopTracingKeys.
PMMEKeysCannotBeTheSame
The application attempted to define the same key to start and
stop tracing.
- 52 -
PMMEKeyAlreadyDefined
The application attempted to define a key to start/stop tracing
and this key was already defined.
PMMEInvalidPointer
The application is using a send message hook and has invoked the
function PMMSMHQueryMsg passing to it the pointer to a SMHSTRUCT
object that has received as the second parameter in the send
message hook function. This is not allowed. See the notes in the
function PMMSMHQueryMsg.
Errors Occurring when Using PMM
───────────────────────────────
These errors may occur at any time when running an application and
using PMM. All are critical, that is, PMM will write a message in
the trace file (if possible), will stop tracing and will destroy the
current trace session.
PMMECritWriteFailed
Error text:
"PMM: Error 1001: Writing to disk failed. Cannot continue
tracing"
Writing to the trace file has failed. Since that the basic
function of PMM is to trace messages and write them to disk,
PMM cannot continue.
PMMECritNotEnoughMemory
Error text:
"PMM: Error 1002: Not enough memory. Cannot continue tracing"
PMM allocates memory while running, if necessary. The memory
couldn't be allocated, so PMM cannot continue.
PMMECritCannotSubclassWindow
Error text:
"PMM: Error 1003: Cannot subclass a window. Cannot continue
tracing"
PMM subclasses windows as needed to keep track of all messages
occurring in an application. There is a limit to the number of
times that an application can subclass a window (see PMM limits).
This message indicates that this limit has been reached.
- 53 -
PMMECritTooManyNestedMsgCalls
Error text:
"PMM: Error 1004: Too many nested message calls. Cannot continue
tracing"
PMM maintains an internal structure to keep track of all messages
occurring in an application. There is a limit to the number of
messages that this structure can hold (see PMM limits). This
limit should be sufficient for virtually every application;
however, an (erroneous) infinite recursion procedure could lead
to this error.
Warnings Occurring when Using PMM
─────────────────────────────────
These warnings do not prevent PMM to continuing to do its functions.
They are reported to the user by writing a message to the trace
file.
PMMWInvalidWindow
Warning text:
"PMM: Warning 5001: A message has been sent through a
pointer to an invalid window. Address called: a.
Message: hwnd: h msg: m mp1: mp1 mp2: mp2.
The message will be ignored"
This indicates that the application sent a message to a window
using a pointer, which is supposed to point to a window
procedure of the window, and the window doesn't exist. This is
probably an application error.
PMMWInvalidWindowProc
Warning text:
"PMM: Warning 5002: A message has been sent through a
pointer using an address that is not a window procedure
address of the window w. Address called: a.
Message: hwnd: h msg: m mp1: mp1 mp2: mp2.
The message will be ignored"
PMM has intercepted a call to a window procedure that doesn't
belong to the actual window procedures of the window being
passed in the call. The message cannot perform its intended
function. This is probably an application error.
- 54 -
7. PMM Message Trace Format
═══════════════════════════
The following diagrams use the "railroad" syntax. The following
points show how to read them:
- Read the format diagrams from left to right, from top to bottom,
following the path of the line.
The ── symbol indicates the beginning of the information being
described.
The ── symbol indicates that the information is continued on the
next line.
The ── symbol indicates that the information is continued from
the previous line.
The ── symbol indicates the end of the information.
In the following diagrams an item represents a part of the
information that PMM shows.
- Items that always appear are shown on the horizontal line (the
main path).
─────────────hWnd────────────────────────────────────
- Optional items appear below the main path.
─────────────┬───────────┬───────────────────────────
└─ WindowId─┘
- If PMM shows you an item, choosing from a set of two or more
items, the set of items appears vertically, in a stack.
If one of the items is always shown, one item in the stack appears
on the main path.
──────────────┬─ Sent─────────────────┬──────────────
├─ Dispatched───────────┤
└─ Posted to queue──────┘
If showing one of the items is optional, the entire stack appears
below the main path.
──────────────┬─────────┬─────────────────────────────
├─ by PMM─┤
└─ int. ──┘
- 55 -
The item that is the default appears above the main path.
┌─ "WindowText"─┐
─────────────┴───────────────┴───────────────────────
- An arrow returning to the left above the main line indicates an
item that can be repeated.
┌─ Item: ItemValue─┐
────────────────────────────────┴────────────────────
This is the format of a message as shown by PMM:
Message Call:
─────────────
┌─ "WindowText"─┬───┬─┬───┬─┐
│ └─a─┘ └─t─┘ │
──Indent.──┬────┬──hWnd──┴───────────────────────────┴──
└─i ─┘
┌─ (ClassName)──┬───┬─┬───┬─┐
│ └─t─┘ └─u─┘ │
───┴───────────────────────────┴──┬─────┬─┬───────────┬──
└─ O.─┘ └─ WindowId─┘
─── MessageName────┬──────────┬───┬──────────┬──────────
└─ Param1─┘ └─ Param2─┘
───┬─ Sent───┬─────────┬─────┬─────────┬─────────┬─────
│ ├─ by PMM─┤ └─ It: n─┘ │
│ └─ int. ──┘ │
├─ Dispatched─────────────┬───────────────────┤
│ └─ fs: PM_NOREMOVE─┤
└─ Posted to queue────────────────────────────┘
Message Return:
───────────────
┌─ "WindowText"─┬───┬─┬───┬─┐
│ └─a─┘ └─t─┘ │
──Indent.──┬────┬──hWnd─────────────────────────────┴──
└─i ─┘
- 56 -
┌─ (ClassName)──┬───┬─┬───┬─┐
│ └─t─┘ └─u─┘ │
──────────────────────────────┴──┬─────┬─┬───────────┬──
└─ O.─┘ └─ WindowId─┘
┌─ Item: ItemValue─┐
─── MessageName──── Returns───────────────────────┼───
└───: RetValue─────┘
─────┬─────────────┬───┬─────────────┬──────────────────
└─ OutParam1─┘ └─ OutParam2─┘
where:
- 'Indent.' is the indentation showing the call and return nesting
of messages.
- 'i' means that this is an internal message.
- 'hWnd' is the destination window handle of a message.
- 'WindowText' is the window text of the destination window. If
the window doesn't have text or the text is a zero length string,
the quotes are not shown.
- 'a' means that the text has been altered.
- 't' means that the text has been trimmed.
- 'ClassName' is the class name of the destination window.
- 'u' means that this is an user class.
- 'O.' means that this is an object window.
- 'WindowId' is the window identifier.
- 'MessageName' is the name of the message.
- 'Param1' is the first parameter of a message. All values and
objects being passed in the first parameter of a message are
interpreted and displayed.
- 'Param2' is the second parameter of a message. All values and
objects being passed in the second parameter of a message are
interpreted and displayed.
- 'Sent' means that the message has been sent (using WinSendMsg or
using a pointer).
- 'Dispatched' means that the message has been retrieved from the
queue and dispatched by WinDispatchMsg.
- 'Posted to queue' means that the message has been posted to the
queue and the message will not be dispatched by WinDispatchMsg
(because the window handle is NULL; or it is a WM_QUIT message;
or the message is not being removed from the queue).
- 'by PMM' means that the message has been sent by PMM, i.e. it is
internal.
- 'int.' means internally, i.e. the message has been sent from
inside an internal message.
- 'It: n' means intertask. This item appears if the message has
been sent between tasks. If the item does not appear the message
has been sent within a task (intratask).
- 'fs: PM_NOREMOVE' are the message removal options received in the
- 57 -
third parameter of the input hook. This item appears only if the
message hasn't been removed from the queue, which is unusual.
- 'RetValue' is the value returned by a message, given that the
message name is clear and self-explanatory.
- 'Item: ItemValue' is a brief description of what a message
returns, plus the value returned.
- 'OutParam1' is the first parameter of a message, given that it is
an Input/Output or Output parameter.
- 'OutParam2' is the second parameter of a message, given that it is
an Input/Output or Output parameter.
C structures are shown in this way:
┌───┐
───[─┴──StructName──┬───────┬──:───────────────────────
├─[ai]──┤
└─/lle/─┘
┌────────────────────────────────┐ ┌───┐
──── VarName: VarValue─┬───────────┼────]─┴───┬───┬───
└─<Meaning>─┘ └─i─┘
where:
- 'StructName' is the structure name as defined in PM include files.
- 'ai' is the array index of the structure. The square brackets
around 'ai' indicate that the structure is an array item.
- 'lle' is the ith element of a linked list of structures. The
slashes around 'lle' indicate that the structure is a linked
list element.
- 'VarName' is the variable name.
- 'VarValue' is the value of the variable.
- 'Meaning' is a brief description of what the variable value means,
i.e. how the window should or will interpret the value.
- 'i' means incomplete, i.e. not all struct variables are shown.
This can be caused, for instance, because this is a call and some
variables are output variables or because some variable values do
not have meaningful values at the time the call is being made.
(You may see the trace generated for the message CM_SETCNRINFO.)
Initial and final square brackets may appear more than once,
indicating the structure nesting. For instance, the beginning and
end of a structure contained inside another structure are shown,
respectively, as '[[' and ']]'.
- 58 -
8. Notes About PMM
══════════════════
When examples are given, the arrow indicates that the next line
continues from the current one. Ellipsis, unless stated otherwise,
indicates that some information is not shown.
1. Any message parameter defined as "Reserved," which should have
a NULL value, is not shown, except when its value is not NULL.
2. PMM interprets only "as much as defined in the documentation" in
message parameters, structure variables and return values. For
instance, the parameter 1 in the WM_TIMER message is defined as a
timer id and a timer id uses only the lower 16 bits of the
parameter. No attempt is made to test and interpret the higher
16 bits. Note that if an application uses "empty" bits a message
may fail or produce unexpected results.
3. Every variable or item defined as having a boolean type is tested
against zero (0), meaning FALSE, and against non-zero, meaning
TRUE. The variable value is shown as FALSE, TRUE or it is
decoded to some meaning. If the variable value is not zero (0)
or one (1), PMM appends the literal "(Value: n)" to the variable
value, where 'n' is the real value of the variable.
Example:
2147484008 (Menu) MM_QUERYITEMRECT Item id: 300 Include ->
submenus: FALSE pRectl: 0x000b7e28 (Out) Sent
2147484008 (Menu) MM_QUERYITEMRECT ->
Returns: TRUE(Value: 2147484008)<Item found> ->
Rectl: (58,20)-(133,1)
4. Pointer values and undefined flags are shown in hexadecimal.
Hexadecimal numbers are denoted by the prefix '0x'.
Here is an example of an undefined flag:
2147484457 (Style)u WM_CHAR Flags: KC_VIRTUALKEY KC_SCANCODE ->
KC_KEYUP KC_LONEKEY 0x1000 Repeat count: 1 ...
2147484457 (Style)u WM_CHAR Returns: FALSE<Message ignored>
0x1000 is not defined in the PM include files.
5. Some "strings," those susceptible to have binary data, are shown
in hexadecimal. Every character of the string is translated
into 2 hexadecimal characters. This translation is denoted by
the suffix "(h)".
Example:
- 59 -
2147484120 (DDE-Sample)u WM_DDE_EXECUTE hwndServer: ->
2147484139 [DDESTRUCT: cbData: 9 [fsStatus: DDE_FACKREQ ->
DDE_FAPPSTATUS: 0] usFormat: CF_TEXT offszItemName: 12 ->
Item name: "Quote" offabData: 18 ->
Data: 5b434c4f534528295d(h)="[CLOSE()]"] Dispatched
2147484120 (DDE-Sample)u WM_DDE_EXECUTE Returns
6. The following is a table of abbreviations used in PMM:
Abbreviation Meaning
------------ -------
accel accelerator
app application
attr attribute
coor coordinate
id identifier
ipt insertion point
PDCIP Pointing device capture in progress
rectl rectangle
7. To avoid confusion, if a structure contains more than one
structure of the same type and the contained structures are not
an array, every contained structure is identified by the variable
name beside its name. An asterisk may appear before the variable
name, denoting 'the contents of'.
Example:
2147484101 (Container) 30 CM_QUERYCNRINFO pCnrInfo: (Out) ->
Bytes to copy: 92 Sent
2147484101 (Container) 30 CM_QUERYCNRINFO Returns Bytes ->
copied: 92 [CNRINFO: cb: 92 pSortRecord: NULL ->
*pFieldInfoLast: [[FIELDINFO: cb: 32 ...]] ->
*pFieldInfoObject: [[FIELDINFO: cb: 32 ...]] ->
...]
8. If a message has one or more output parameters and returns an
error, the output parameters are always shown, even if they are
not meaningful.
Example:
2147484113 (Menu) O. SC_SYSMENU MM_QUERYITEM Item id: -1 ->
Include submenus: FALSE pMenuItem: 0x00082380 (Output) Sent
2147484113 (Menu) O. SC_SYSMENU MM_QUERYITEM ->
Returns: Error [MENUITEM: iPosition: 0 afStyle: ->
MIS_BITMAP MIS_SUBMENU afAttribute: 0 id: SC_SYSMENU ->
hwndSubMenu: 2147484113 hItem: 67108870]
10. When the absence of some flag implies another action or meaning
and no constant exists for this action or meaning, PMM may
"create" a constant showing the intended action. An exclamation
- 60 -
point (!) will be appended to this undefined constant.
Example:
2147484094 (ListBox) DM_DRAGFILECOMPLETE File name: ->
"TEST.TXT" Flags: DF_COPY! DF_SOURCE DF_SUCCESSFUL Sent
2147484094 (ListBox) DM_DRAGFILECOMPLETE Returns: 0
The operation is not a move (if it were the flag would have been
DF_MOVE), so it is a copy. Note that DF_COPY is not defined as
a constant in the PM include files.
This interpretation is done on some messages only. Names have
been selected that are easy to interpret.
11. PMM detects automatically the File Dialog messages and the Font
Dialog messages when sent to these dialog windows, and
differentiates them from user messages with the same value.
12. The function WinCreateMsgQueue creates an object window whose
class is "#32767". This window, like any other window,
receives messages. Some of them are:
When the window is being created:
WM_CREATE
WM_ADJUSTWINDOWPOS
When the window is being destroyed:
WM_ADJUSTWINDOWPOS
WM_WINDOWPOSCHANGED
WM_SHOW
WM_DESTROY
Additionally, it may receive messages like this:
WM_FOCUSCHANGE
PMM does not trace the messages occurring at create or destroy
time for this window.
9. Errors Detected in the Documentation
═══════════════════════════════════════
1. DM_PRINTOBJECT. The documentation states that the first
parameter (param1) in the message DM_PRINTOBJECT is a pointer to
a DRAGINFO structure. This is incorrect. param1 is a pointer to
a DRAGITEM structure.
2. DM_DRAGOVER. The documentation states that, for a modified drag
operation, the field usOperation in the structure DRAGINFO must
- 61 -
have a value greater (>) than DO_UNKNOWN for an operation defined
by an application. When explaining the return values of this
message it states that usDrop must be greater than or equal (>=)
to DO_UNKNOWN. PMM considers values greater than or equal to
DO_UNKNOWN as application defined operations.
3. HM_QUERY. The parameters usmessageid and usselectionid do not
appear in the documented order:
param1
USHORT usmessageid
USHORT usselectionid
The correct order is:
param1
USHORT usselectionid
USHORT usmessageid
PMM shows the correct order.
4. HM_QUERY. The constant HMQW_VIEWEDPAGES used in the variable
usmessageid doesn't exist in the toolkit include files. The
correct constant is HMQW_VIEWPAGES.
10. PMM Limits
══════════════
The following are the PMM limits:
Number of PMM sessions running in OS/2 (different tasks): no limit.
Number of PMM sessions per task: 1.
Number of PM message queues per session: 1.
Number of windows handled per session: no limit.
Number of times that an application can subclass a window: 20.
Number of nested messages that a window can receive: 200.
11. Tools Used in Creating PMM
══════════════════════════════
PMM has been written using the following tools:
The IBM C/C++ Tools Version 2.01.
The IBM Developer's Toolkit for OS/2 Version 2.1.
- 62 -
PMM has been tested on OS/2 Version 2.1, 3.0 and 4.0. No patches
have been added to any of these versions of OS/2.
12. Acknowledgments
═══════════════════
My special thanks to B.D. (name withheld), David Johnston, Jon
Saxton, Martin Schaffoener and Charles Wangersky, who reviewed
the documentation and offered valuable comments and suggestions
about this program. I hope they know how much I appreciate
their fine work.
13. Disclaimer
══════════════
PMM is distributed "as is." No warranty of any kind is expressed
or implied. You use it at your own risk. The author will not be
liable for data loss, damages, loss of profits or any other kind
of loss while using this software.
14. Trademarks
══════════════
The following terms used in this manual are trademarks or service
marks of IBM Corporation.
IBM
OS/2
Presentation Manager
- 63 -