Sample Code

windows driver samples/ AC97 Driver Sample/ C++/ cpl/ ac97cpl.cpp/

/********************************************************************************
**    Copyright (c) 2000 Microsoft Corporation. All Rights Reserved.
********************************************************************************/

#include <windows.h>
#include <cpl.h>
#include <ks.h>
#include <ksmedia.h>
#include <setupapi.h>
#include <strsafe.h>
#include "resource.h"
#include "prvprop.h"

_Analysis_mode_(_Analysis_code_type_user_driver_)

//
//  Global Variables.
//
HINSTANCE                   ghInstance = NULL;      // module handle.
const TCHAR AppletName[] = TEXT("AC97 control panel");


#if (DBG)
/////////////////////////////////////////////////////////////////////////////////
// dbgError
/////////////////////////////////////////////////////////////////////////////////
// This function prints an error message.
// It prints first the string passed and then the error that it gets with
// GetLastError as a string.
//
// Arguments:
//    szMsg - message to print.
//
// Return Value:
//    None.
//
void dbgError (LPCTSTR szMsg)
{
    LPTSTR errorMessage;
    DWORD  count;

    // Get the error message from the system.
    count = FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |
                FORMAT_MESSAGE_FROM_SYSTEM |
                FORMAT_MESSAGE_IGNORE_INSERTS,
                NULL,
                GetLastError (),
                MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
                (LPTSTR)&errorMessage,
                0,
                NULL);

    // Print the msg + error + \n\r.
    if (count)
    {
        OutputDebugString (szMsg);
        OutputDebugString (errorMessage);
        OutputDebugString (TEXT("\n\r"));

        // This is for those without a debugger.
        // MessageBox (NULL, szErrorMessage, szMsg, MB_OK | MB_ICONSTOP);

        LocalFree (errorMessage);
    }
    else
    {
        OutputDebugString (AppletName);
        OutputDebugString (TEXT(": Low memory condition. Cannot ")
                TEXT("print error message.\n\r"));
    }
}
#else
#define dbgError(a) 0;
#endif


/////////////////////////////////////////////////////////////////////////////////
// DllMain
/////////////////////////////////////////////////////////////////////////////////
// Main enty point of the DLL.
// Save the instance handle; it is needed for property sheet creation.
//
// Arguments:
//    hModule            - instance data, is equal to module handle
//    ul_reason_for_call - the reason for the call
//    lpReserved         - some additional parameter.
//
// Return Value:
//    BOOL: FALSE if DLL should fail, TRUE on success
//
BOOL APIENTRY DllMain (HANDLE hModule, ULONG ul_reason_for_call, LPVOID lpReserved)
{
    UNREFERENCED_PARAMETER(ul_reason_for_call);
    UNREFERENCED_PARAMETER(lpReserved);

    ghInstance = (HINSTANCE) hModule;
    return TRUE;
}


/////////////////////////////////////////////////////////////////////////////////
// FindAC97Device
/////////////////////////////////////////////////////////////////////////////////
// This function stores the device info and device data of the "ac97smpl" driver.
// It first creates a list of all devices that have a topology filter exposed
// and then searches through the list to find the device with the service
// "ac97smpl". The information is stored in pspRequest.
//
// For simplicity we search for the service name "ac97smpl".
// Alternately, one could get more information about the device or driver,
// then decide if it is suitable (regardless of its name).
//
// Arguments:
//    pspRequest        pointer to Property sheet page request structure.
//    DeviceInfoData    pointer to Device info data structure.
//
// Return Value:
//    TRUE on success, otherwise FALSE.
//    Note: on success that we have the device list still open - we have to destroy
//    the list later. The handle is stored at pspRequest->DeviceInfoSet.
//
BOOL FindAC97Device (PSP_PROPSHEETPAGE_REQUEST  pspRequest,
                     PSP_DEVINFO_DATA DeviceInfoData)
{
    TCHAR           szServiceName[128];

    //
    // Prepare the pspRequest structure...
    //
    pspRequest->cbSize = sizeof (SP_PROPSHEETPAGE_REQUEST);
    pspRequest->DeviceInfoData = DeviceInfoData;
    pspRequest->PageRequested = SPPSR_ENUM_ADV_DEVICE_PROPERTIES;

    // ...and the DeviceInfoData structure.
    DeviceInfoData->cbSize = sizeof (SP_DEVINFO_DATA);

    // Create a list of devices with Topology interface.
    pspRequest->DeviceInfoSet = SetupDiGetClassDevs (&KSCATEGORY_TOPOLOGY,
                                     NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);

    // None found?
    if (pspRequest->DeviceInfoSet == INVALID_HANDLE_VALUE)
    {
        dbgError (TEXT("Test: SetupDiGetClassDevs: "));
        return FALSE;
    }

    //
    // Go through the list of all devices found.
    //
    int nIndex = 0;

    while (SetupDiEnumDeviceInfo (pspRequest->DeviceInfoSet, nIndex, DeviceInfoData))
    {
        //
        // Get the service name for that device.
        //
        if (!SetupDiGetDeviceRegistryProperty (pspRequest->DeviceInfoSet, DeviceInfoData,
                                               SPDRP_SERVICE, NULL, (PBYTE)szServiceName,
                                               sizeof (szServiceName), NULL))
        {
            dbgError (TEXT("Test: SetupDiGetDeviceRegistryProperty: "));
            SetupDiDestroyDeviceInfoList (pspRequest->DeviceInfoSet);
            return FALSE;
        }

        //
        // We only care about service "ac97smpl"
        //
        DWORD lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
        if (CompareString (lcid, NORM_IGNORECASE, szServiceName,
                            -1, TEXT("AC97SMPL"), -1) == CSTR_EQUAL)
        {
            //
            // We found it! The information is already stored, just return.
            // Note that we have the device list still open - we have to destroy
            // the list later.
            //
            return TRUE;
        }

        // Take the next in the list.
        nIndex++;
    }

    //
    // We did not find the service.
    //
    SetupDiDestroyDeviceInfoList (pspRequest->DeviceInfoSet);
    return FALSE;
}


/////////////////////////////////////////////////////////////////////////////////
// AddPropSheet
/////////////////////////////////////////////////////////////////////////////////
// This function is a callback that is passed to the "AC97PropPageProvider"
// function of "ac97prop.dll". It is used to add the property page sheet
// to the property dialog.
// What we do here is store the property sheet handle and return.
//
// Arguments:
//    hPSP       property sheet handle
//    lParam     parameter that we passed to "AC97PropPageProvider".
//
// Return Value:
//    TRUE on success, otherwise FALSE.
//
BOOL APIENTRY AddPropSheet (HPROPSHEETPAGE hPSP, LPARAM lParam)
{
    HPROPSHEETPAGE **pphPropSheet = (HPROPSHEETPAGE **)lParam;
    HPROPSHEETPAGE *phPropSheetPage;

    // Check the parameters
    if (!pphPropSheet)
        return FALSE;

    // Allocate the space for the handle.
    phPropSheetPage = (HPROPSHEETPAGE *)LocalAlloc (LPTR, sizeof(HPROPSHEETPAGE));
    if (!phPropSheetPage)
        return FALSE;

    *phPropSheetPage = hPSP;
    *pphPropSheet = phPropSheetPage;

    return TRUE;
}


/////////////////////////////////////////////////////////////////////////////////
// GetDLLInfo
/////////////////////////////////////////////////////////////////////////////////
// This function loads the library and gets the entry point address.
// With the information returned we can create the property dialog.
//
// For simplicity reasons we load the DLL "ac97prop" and call the function
// "AC97PropPageProvider". A more flexible course of action is to get this
// information from the registry.  To do this, we read the "EnumPropPages32"
// entry in the drivers section to obtain a registry path (read the "drivers"
// entry in the device section to get the registry path of the drivers section)
// -- this path leads to a key and entry which specifies the DLL and entry point.
//
// Arguments:
//    *phDLL                     pointer to module handle of loaded DLL.
//    *pAC97PropPageProvider     pointer to "AC97PropPageProvider" in loaded DLL
//
// Return Value:
//    TRUE on success, otherwise FALSE.
//    Note: on success the library is still loaded.
//
BOOL GetDLLInfo (HMODULE *phDLL, LPFNADDPROPSHEETPAGES *pAC97PropPageProvider)
{
    TCHAR                   szLoadPath[MAX_PATH];
    TCHAR                   szWinSysPath[MAX_PATH];

    GetSystemDirectory(szWinSysPath, MAX_PATH);
    if(FAILED(StringCbPrintf(szLoadPath, MAX_PATH * sizeof(TCHAR), TEXT("%s\\%s"), szWinSysPath, TEXT("ac97prop.dll"))))
    {
        dbgError (TEXT("DisplayPropertySheet: Can't build DLL path\n"));
        return FALSE;
    }

    // Load the library.
    *phDLL = LoadLibrary (szLoadPath);
    if (!*phDLL)
    {
        dbgError (TEXT("DisplayPropertySheet: LoadLibrary"));
        return FALSE;
    }

    // Get the address of the function.
    *pAC97PropPageProvider = (LPFNADDPROPSHEETPAGES)GetProcAddress (*phDLL,
                                                      "AC97PropPageProvider");
    if (!*pAC97PropPageProvider)
    {
        dbgError (TEXT("DisplayPropertySheet: GetProcAddress"));
        FreeLibrary (*phDLL);
        return FALSE;
    }

    return TRUE;
}


/////////////////////////////////////////////////////////////////////////////////
// DisplayPropertySheet
/////////////////////////////////////////////////////////////////////////////////
// This function displays the property dialog.
// It is called by CPlApplet when the ac97cpl icon gets a double click.
//
// Arguments:
//    hWnd      parent window handle
//
// Return Value:
//    None.
//
void DisplayPropertySheet (HWND hWnd)
{
    SP_PROPSHEETPAGE_REQUEST    pspRequest;         // structure passed to ac97prop
    SP_DEVINFO_DATA             DeviceInfoData;     // pspRequest points to it.
    HMODULE                     hDLL;               // Module handle of library
    LPFNADDPROPSHEETPAGES       AC97PropPageProvider; // function to be called.
    PROPSHEETHEADER             psh;
    WCHAR                       wszFormat[128];
    size_t                      iRes;

    // You could move this to CPL_INIT, then it would be called
    // before the control panel window appears.
    // In case of an failure the icon would not be displayed. In our sample
    // however, the icon will be displayed and when the user clicks on it he
    // gets the error message.
    if (!FindAC97Device(&pspRequest, &DeviceInfoData))
    {
        iRes = LoadString(ghInstance, IDS_AC97_WARNING_MUST_INSTALL_DRIVER, wszFormat, ARRAYSIZE(wszFormat));
        if (iRes >0)
        {
            MessageBox (hWnd, wszFormat, AppletName, MB_ICONSTOP | MB_OK);
        }
        return;
    }

    // Load the library and get the function pointer.
    if (!GetDLLInfo (&hDLL, &AC97PropPageProvider))
    {
        iRes = LoadString(ghInstance, IDS_AC97_WARNING_PROPERTYPAGE_DLL_COULD_NOT_LOAD, wszFormat, ARRAYSIZE(wszFormat));
        if (iRes >0)
        {
            MessageBox (hWnd, wszFormat, AppletName, MB_ICONSTOP | MB_OK);
        }

        SetupDiDestroyDeviceInfoList (pspRequest.DeviceInfoSet);
        return;
    }

    //
    // Prepare the header for the property sheet.
    //
    psh.nStartPage = 0;
    psh.dwSize = sizeof(psh);
    psh.dwFlags = PSH_PROPTITLE | PSH_NOAPPLYNOW;
    psh.hwndParent = hWnd;
    psh.hInstance = ghInstance;
    psh.pszIcon = NULL;
    psh.pszCaption = MAKEINTRESOURCE(IDS_AC97CPL);
    psh.nPages = 1;

    // Call the function to request the property sheet page.
    if (!(*AC97PropPageProvider) ((LPVOID)&pspRequest, AddPropSheet, (LPARAM)&psh.phpage))
    {
        iRes = LoadString(ghInstance, IDS_AC97_WARNING_PROPERTYPAGEPROVIDER_FAILURE, wszFormat, ARRAYSIZE(wszFormat));
        if (iRes >0)
        {
            MessageBox (hWnd, wszFormat, AppletName, MB_ICONSTOP | MB_OK);
        }
        FreeLibrary (hDLL);
        SetupDiDestroyDeviceInfoList (pspRequest.DeviceInfoSet);
        return;
    }

    // Create the dialog. The function returns when the dialog is closed.
    if (PropertySheet (&psh) < 0)
    {
        //
        // Dialog closed abnormally. This might be a system failure.
        //
        iRes = LoadString(ghInstance, IDS_AC97_WARNING_REINSTALL_DRIVER, wszFormat, ARRAYSIZE(wszFormat));
        if (iRes >0)
        {
            MessageBox (hWnd, wszFormat, AppletName, MB_ICONSTOP | MB_OK);
        }
    }

    // Clean up.
    FreeLibrary (hDLL);
    LocalFree (psh.phpage);
    SetupDiDestroyDeviceInfoList (pspRequest.DeviceInfoSet);
}


/////////////////////////////////////////////////////////////////////////////////
// CPlApplet
/////////////////////////////////////////////////////////////////////////////////
// This function is called by the control panel manager. It is very similar to
// a Windows message handler (search for CplApplet in MSDN for description).
//
// Arguments:
//    HWND hWnd         Parent window handle
//    UINT uMsg         The message
//    LPARAM lParam1    depends on message
//    LPARAM lParam2    depends on message
//
// Return Value:
//    LONG (depends on message; in general 0 means failure).
//
LONG APIENTRY CPlApplet (HWND hWnd, UINT uMsg, LPARAM lParam1, LPARAM lParam2)
{
    switch (uMsg)
    {
        // Initialize. You can allocate memory here.
        case CPL_INIT:
            return TRUE;

        //  How many applets are in this DLL?
        case CPL_GETCOUNT:
            return 1;

        // Requesting information about the dialog box.
        // lParam1 is the dialog box number (we have only one) and
        // lParam2 is the pointer to a CPLINFO structure.
        // There is no return value.
        case CPL_INQUIRE:
        {
            UINT      uAppNum = (UINT)lParam1;
            LPCPLINFO pCplInfo = (LPCPLINFO)lParam2;

            if (!pCplInfo)
                return TRUE;    // unsuccessful

            if (uAppNum == 0)   // first Applet?
            {
                pCplInfo->idIcon = IDI_AC97CPL;
                pCplInfo->idName = IDS_AC97CPL;
                pCplInfo->idInfo = IDS_AC97CPLINFO;
            }
            break;
        }

        // This is basically the same as CPL_INQUIRE, but passes a pointer
        // to a different structure.
        // This function is called before CPL_INQUIRE and if we return zero
        // here, then CPL_INQUIRE is called.
        case CPL_NEWINQUIRE:
            break;

        // One of these messages are sent when we should display the dialog box.
        // There is no return value.
        // lParam1 is the dialog box number (we have only one)
        case CPL_DBLCLK:
        case CPL_STARTWPARMS:
        {
            UINT    uAppNum = (UINT)lParam1;

            if (uAppNum == 0)   // first Applet?
                DisplayPropertySheet (hWnd);
            break;
        }

        // We get unloaded in a second.
        // There is no return value.
        case CPL_EXIT:
            break;

        default:    // Who knows?
            break;
    }

    return 0;
}

Our Services

  • What our customers say about us?

© 2011-2025 All Rights Reserved. Joya Systems. 4425 South Mopac Building II Suite 101 Austin, TX 78735 Tel: 800-DEV-KERNEL

Privacy Policy. Terms of use. Valid XHTML & CSS