![]() |
|
||||
How to Work with DAPI_EVENT StructureFirst of all, a few words of caution. If the structure is allocated you must eventually free it with DAPIFreeMemory call - that's what Microsoft recommends. My two illustrative samples in previous subsections don't do that, but production code perhaps should. I use the opportunity to emphasize here again, that the samples in this work are "illustrative". They show how you could accomplish certain tasks, but they are obviously not rock-solid. Here is the definition of DAPI_EVENT structure: typedef struct _DAPI_EVENT
The most important component of this structure is its first element - message identifier. This number identifies an error message string. The last element of the structure is also very useful. It hosts a pointer to the next related event. A function returning DAPI_EVENT may in fact report "many" errors. Suppose you want to modify a directory object with the DAPIWrite function and supply invalid arguments. For example, you may supply "read-only" attributes, and omit a required one. In such case the DAPI_EVENT will individually report each error (quite a nice feature!) in a list of related DAPI_EVENTs. You may easily traverse this list and view it during debugging in the Watch window. Our major concern here is how to deal with errors. How can we obtain
text description of an error? There are a few ways of doing this.
Examining DAPIMSG.H fileThe simplest thing to do is to open the DAPIMSG.H file, find message ID there, and look at text description of an error. For example, for dwDAPIError being equal to 0xC0000081 you should be able to find the following fragment in this file://
Take a look at text description of the error preceding #define statement. Obviously, a bad handle was used with the call. This is exactly what happened with me when I mistakenly supplied address of DAPI handle instead of real handle to the DAPIRead function. DAPIMSG.H file may be found in the Include directory of your Platform
SDK.
Using the FormatMessage FunctionSecond way of dealing with DAPI_EVENT error codes is to use the FormatMessage Win32 function. In fact, it is a very useful general-purpose function. For example, here is the sample showing how you can display Win32 error codes, obtained via the GetLastError():LPVOID lpMsgBuf;
The above sample may be found in Dir/FormatMessage directory of my collection of sample code. In our particular case of DAPI errors, we need to use slightly different parameters. First of all, we need to change FORMAT_MESSAGE_FROM_SYSTEM flag to FORMAT_MESSAGE_FROM_HMODULE, pass DAPI.DLL handle in second parameter, and error ID in the third. The following sample demonstrates how you can use it. Notice that I call DAPIRead without first calling DAPIStart, this causes it to fail with invalid handle error. Notice the use of DAPIFreeMemory for DAPI_EVENT structure as well. The sample below is located in Dir/FormatMessageDAPI subdirectory. #include <afxwin.h>
int main( void )
DAPI_ENTRY * pdeValues = NULL;
if ( pDAPIEvent ) { LPVOID lpMsgBuf;
// Display the string.
::DAPIFreeMemory( pDAPIEvent
);
return ( 0 );
For many application working co-operatively with MS Exchange server
it would be more appropriate to log messages to Windows NT event log, rather
than displaying them on the desktop. Once you have collected the message
with the FormatMessage function as described above, you can log it into
Event log by either using standard Win32 event logging techniques or a
collection of functions in Exchange Development Kit (such as EventLogMsg).
|