Creating a DirectSetup Callback Function

In order to customize the setup process, you must first create a callback function that conforms to the DirectXSetupCallbackFunction prototype, as in the following declaration:

DWORD WINAPI DirectXSetupCallbackFunction(
        DWORD dwReason,  
        DWORD dwMsgType, 
        LPSTR szMessage, 
        LPSTR szName, 
        void *pInfo);
 

In this example, adapted from the Dinstall sample application, the name of the function is the same as that of the prototype, but this is optional. The parameter names differ slightly from those in the prototype declared in Dsetup.h, and will be used throughout the following discussion.

Parameters

The dwReason parameter indicates why the callback function has been called. The possible values are listed and explained in the reference for DirectXSetupCallbackFunction.

The dwMsgType parameter receives flags equivalent to those that DirectSetup would, by default, pass to MessageBox, such as those controlling what buttons and icon are displayed. Of special interest to you are the button flags, which you use to determine what return values are expected. If this value is 0, the event never requires user input and DirectSetup would normally display a status message.

The szMessage parameter receives the same text that DirectSetup would otherwise pass to the status dialog or to MessageBox.

When a driver is a candidate for upgrading, its name is passed in the szName parameter and pInfo points to information about the how the upgrade will or should be handled—for example, whether DirectSetup recommends that the old driver be kept or upgraded. For more information, see Using Upgrade Flags in the Callback Function.

The way your callback function interprets the parameters is entirely up to you. Typically you would choose which messages to display (based on dwReason) and when to present the user with alternatives, and you would modify the interface accordingly.

Return Value

The value returned by your callback function must conform to the following rules:

To determine the appropriate return value in the second case, you must test dwMsgType for the buttons that would normally have been put in a message box. The following example, from the GetReply function in Dinstall, shows how this can be done:

/* The global g_wReply identifies the custom dialog button
   that has been selected by the user. */
 
switch (dwMsgType & 0x0000000F)
{
   / * There would normally have been an OK and a Cancel button.
       Our IDBUT1 is equivalent to the OK button. If the user didn't
       choose that, it was a Cancel. */
    case MB_OKCANCEL:
        wDefaultButton = (g_wReply == IDBUT1) ? IDOK : IDCANCEL;
        break;
 
    / * And so on with the other button combinations. */
    case MB_OK:
        wDefaultButton = IDOK;
        break;
    case MB_RETRYCANCEL:
        wDefaultButton = (g_wReply == IDBUT1) ? IDRETRY : IDCANCEL;
        break;
    case MB_ABORTRETRYIGNORE:
        if (g_wReply == IDBUT1)
            wDefaultButton = IDABORT;
        else if (g_wReply == IDBUT2)
            wDefaultButton = IDRETRY;
        else
            wDefaultButton = IDIGNORE;
        break;
    case MB_YESNOCANCEL:
        if (g_wReply == IDBUT1)
            wDefaultButton = IDYES;
        else if (g_wReply == IDBUT2)
            wDefaultButton = IDNO;
        else
            wDefaultButton = IDCANCEL;
        break;
    case MB_YESNO:
        wDefaultButton = (g_wReply == IDBUT1) ? IDYES : IDNO;
        break;
    default:
        wDefaultButton = IDOK;
}
 

This routine translates button clicks from the custom interface into the equivalent button identifiers in the standard dialog box that DirectSetup would otherwise create. The wDefaultButton variable is set to the identifier of the equivalent standard dialog box button, and it is this value that will ultimately be returned from the callback function.

Remember, you don't necessarily have to give the user a choice even when dwMsgType is nonzero. You might decide, for example, to upgrade drivers automatically in a case where DirectSetup would normally ask for confirmation from the user. The Dinstall sample does this when the user has asked to see only problem messages and the driver upgrade is considered safe:

case DSETUP_CB_UPGRADE_SAFE:
    switch (dwMsgType & 0x0000000F)
    {
        case MB_YESNO:
        case MB_YESNOCANCEL:
            return IDYES;
        case MB_OKCANCEL:
        case MB_OK:
        default:
            return IDOK;
    }
    break;
 

The callback function returns either IDYES or IDOK, depending on which button would have represented a positive choice in a dialog box asking the user whether or not the upgrade should proceed.