/*++

 Copyright (c) 2001 Microsoft Corporation

 Module Name:

    NewShenDiaoXiaLv.cpp

 Abstract:

    On NT, when there is no CD in the CDROM, and the app sends a MCI_OPEN 
    command to the CDAUDIO device, the app has fully exclusive control of the 
    CDROM. When later on user inserts CD, the app will not receive 
    WM_DEVICECHANGE message. And this app relies on the message to know if 
    there is a new CD inserted. 
    
    The fix is check whether the CD is there when we do MCI_OPEN command, if 
    there is not CD, we will close the device.

 Notes: 
  
    This is an app specific shim.

 History:

    05/28/2001 xiaoz    Created

--*/

#include "precomp.h"

IMPLEMENT_SHIM_BEGIN(NewShenDiaoXiaLv)
#include "ShimHookMacro.h"

APIHOOK_ENUM_BEGIN
    APIHOOK_ENUM_ENTRY(mciSendCommandA) 
APIHOOK_ENUM_END

/*++

 Close the device if we get hardware error(CD is not there).

--*/

MCIERROR 
APIHOOK(mciSendCommandA)(
    MCIDEVICEID IDDevice,  
    UINT uMsg,             
    DWORD fdwCommand,      
    DWORD dwParam          
    )
{
    MCIERROR mciErr, mciError;
    MCI_STATUS_PARMS mciStatus;
    LPMCI_OPEN_PARMSA lpmciOpenParam;
    CString cstrDeviveType;
    
    mciErr = ORIGINAL_API(mciSendCommandA)(IDDevice, uMsg, fdwCommand, dwParam);
    
    // We are only interested in a successful MCI_OPEN Message  
    if (mciErr || (uMsg != MCI_OPEN) || IsBadReadPtr((CONST VOID*)(ULONG_PTR)dwParam, 1))
    {
        goto End;
    }  

    // We are only interested in MCI message sent to CDAUDIO
    lpmciOpenParam = (LPMCI_OPEN_PARMSA) dwParam;
    if ((ULONG_PTR) lpmciOpenParam->lpstrDeviceType <= 0xffff)
    {
        if ((ULONG_PTR)lpmciOpenParam->lpstrDeviceType != MCI_DEVTYPE_CD_AUDIO)
        {
            goto End;
        }
    }
    else
    {
        CString cstrDeviveType(lpmciOpenParam->lpstrDeviceType);
        if (cstrDeviveType.CompareNoCase(L"cdaudio"))
        {
            goto End;
        }
    }
    
    // Send an MCI_STATUS 
    mciStatus.dwItem = MCI_STATUS_LENGTH ;
    mciError = mciSendCommandA(lpmciOpenParam->wDeviceID, MCI_STATUS, 
        MCI_STATUS_ITEM | MCI_TRACK | MCI_WAIT, (DWORD_PTR) &mciStatus);

    if (MCIERR_HARDWARE == mciError)
    {        
        //
        // If we get hardware error, it means CD is not there, close the device
        // and return error
        //
        mciSendCommandA(lpmciOpenParam->wDeviceID, MCI_CLOSE, 0, 0);
        mciErr = MCIERR_DEVICE_NOT_READY;
    }

End:
    return mciErr;
}

/*++

 Register hooked functions

--*/

HOOK_BEGIN
    APIHOOK_ENTRY(WINMM.DLL, mciSendCommandA)        
HOOK_END

IMPLEMENT_SHIM_END