Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2205 lines
64 KiB

//****************************************************************************
//
// Module: MMSE.DLL
// File: mmse.c
// Content: This file contains the moudle initialization.
// History:
// 06/1994 -By- Vij Rajarajan (VijR)
//
// Copyright (c) Microsoft Corporation 1991-1994
//
//****************************************************************************
#define INITGUID
#include "mmcpl.h"
#include <coguid.h>
#include <oleguid.h>
#include <shlguid.h>
#include <mmddk.h>
#include <mmreg.h>
#include <msacm.h>
#include <msacmdrv.h>
#include <vfw.h>
#include <shlobj.h>
#undef INITGUID
#include <shlobjp.h>
//****************************************************************************
// Initialize GUIDs (should be done only and at-least once per DLL/EXE)
//****************************************************************************
#include <commctrl.h>
#include <prsht.h>
#include "draw.h"
#include "utils.h"
#include "medhelp.h"
/*
***************************************************************
* Typedefs
***************************************************************
*/
typedef HWND (VFWAPIV * FN_MCIWNDCREATE)();
//---------------------------------------------------------------------------
// MMPSH class
//---------------------------------------------------------------------------
typedef struct _mmInfoList MMINFOLIST;
typedef MMINFOLIST * PMMINFOLIST;
typedef struct _mmInfoList
{
TCHAR szInfoDesc[80];
LPSTR pszInfo;
FOURCC ckid;
PMMINFOLIST pNext;
};
// mmse class structure. This is used for instances of
// IPersistFolder, IShellFolder, and IShellDetails.
typedef struct _mmpsh
{
// We use the pf also as our IUnknown interface
IShellExtInit sei; // 1st base class
IShellPropSheetExt pse; // 2nd base class
LPDATAOBJECT pdtobj;
UINT cRef; // reference count
LPTSTR pszFileObj;
UINT uLen;
short iMediaType;
PVOID pAudioFormatInfo;
PVOID pVideoFormatInfo;
HPALETTE hPal;
HBITMAP hDispBMP;
HICON hIcon;
PMMINFOLIST pInfoList;
} mmpsh, * PMMPSH;
/*
***************************************************************
* Defines
***************************************************************
*/
#define MIDICOPYRIGHTSTR pAudioFormatInfo
#define MIDISEQNAMESTR pVideoFormatInfo
#define MAXNUMSTREAMS 50
/*
***************************************************************
* File Globals
***************************************************************
*/
int g_cRef = 0;
SZCODE cszWavExt[] = TEXT(".WAV");
SZCODE cszMIDIExt[] = TEXT(".MID");
SZCODE cszRMIExt[] = TEXT(".RMI");
SZCODE cszAVIExt[] = TEXT(".AVI");
SZCODE cszASFExt[] = TEXT(".ASF");
SZCODE cszSlash[] = TEXT("\\");
static SZCODE aszMIDIDev[] = TEXT("sequencer");
static TCHAR szDetailsTab[64];
static TCHAR szPreviewTab[64];
/*
***************************************************************
* Prototypes
***************************************************************
*/
LPTSTR PASCAL NiceName(LPTSTR sz, BOOL fNukePath);
/*
***************************************************************
***************************************************************
*/
DWORD mmpshGetFileSize(LPTSTR szFile)
{
HANDLE hFile;
OFSTRUCT of;
DWORD dwSize = 0;
hFile = CreateFile(szFile, GENERIC_READ, FILE_SHARE_READ,NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (INVALID_HANDLE_VALUE != hFile)
{
dwSize = GetFileSize(hFile, NULL);
CloseHandle(hFile);
}
return dwSize;
}
STATIC void ReleaseInfoList(PMMPSH pmmpsh)
{
PMMINFOLIST pCur;
pCur = pmmpsh->pInfoList;
while (pCur)
{
PMMINFOLIST pTmp;
pTmp = pCur;
pCur = pCur->pNext;
LocalFree((HLOCAL)pTmp->pszInfo);
LocalFree((HLOCAL)pTmp);
}
pmmpsh->pInfoList = NULL;
}
STATIC BOOL AddInfoToList(PMMPSH pmmpsh, LPSTR pInfo, FOURCC ckid)
{
PMMINFOLIST pCur;
int idStr;
for (pCur = pmmpsh->pInfoList; pCur && pCur->pNext ; pCur = pCur->pNext)
if (pCur->ckid == ckid)
return TRUE;
if (!pCur)
{
pCur = pmmpsh->pInfoList = (PMMINFOLIST)LocalAlloc(LPTR, sizeof(MMINFOLIST));
}
else
{
pCur->pNext = (PMMINFOLIST)LocalAlloc(LPTR, sizeof(MMINFOLIST));
pCur = pCur->pNext;
}
if (!pCur)
return FALSE;
pCur->ckid = ckid;
pCur->pszInfo = pInfo;
switch (ckid)
{
case FOURCC_INAM:
idStr = IDS_FOURCC_INAM;
break;
case FOURCC_ICOP:
idStr = IDS_FOURCC_ICOP;
break;
case FOURCC_ICMT:
idStr = IDS_FOURCC_ICMT;
break;
case FOURCC_ISBJ:
idStr = IDS_FOURCC_ISBJ;
break;
case FOURCC_ICRD:
idStr = IDS_FOURCC_ICRD;
break;
case FOURCC_IART:
idStr = IDS_FOURCC_IART;
break;
case FOURCC_DISP:
idStr = IDS_FOURCC_DISP;
break;
case FOURCC_ICMS:
idStr = IDS_FOURCC_ICMS;
break;
case FOURCC_ICRP:
idStr = IDS_FOURCC_ICRP;
break;
case FOURCC_IDIM:
idStr = IDS_FOURCC_IDIM;
break;
case FOURCC_IDPI:
idStr = IDS_FOURCC_IDPI;
break;
case FOURCC_IENG:
idStr = IDS_FOURCC_IENG;
break;
case FOURCC_IGNR:
idStr = IDS_FOURCC_IGNR;
break;
case FOURCC_IKEY:
idStr = IDS_FOURCC_IKEY;
break;
case FOURCC_ILGT:
idStr = IDS_FOURCC_ILGT;
break;
case FOURCC_IARL:
idStr = IDS_FOURCC_IARL;
break;
case FOURCC_IMED:
idStr = IDS_FOURCC_IMED;
break;
case FOURCC_IPLT:
idStr = IDS_FOURCC_IPLT;
break;
case FOURCC_IPRD:
idStr = IDS_FOURCC_IPRD;
break;
case FOURCC_ISFT:
idStr = IDS_FOURCC_ISFT;
break;
case FOURCC_ISHP:
idStr = IDS_FOURCC_ISHP;
break;
case FOURCC_ISRC:
idStr = IDS_FOURCC_ISRC;
break;
case FOURCC_ISRF:
idStr = IDS_FOURCC_ISRF;
break;
case FOURCC_ITCH:
idStr = IDS_FOURCC_ITCH;
break;
}
if (idStr)
LoadString(ghInstance, idStr, pCur->szInfoDesc, sizeof(pCur->szInfoDesc)/sizeof(TCHAR));
return TRUE;
}
typedef struct tagWaveDesc
{
DWORD dSize;
WORD wFormatSize;
NPWAVEFORMATEX pwavefmt;
} WAVEDESC,* PWAVEDESC;
STATIC BOOL PASCAL NEAR ReadWaveHeader(HMMIO hmmio,
PWAVEDESC pwd)
{
MMCKINFO mmckRIFF;
MMCKINFO mmck;
MMRESULT wError;
mmckRIFF.fccType = mmioWAVE;
if (wError = mmioDescend(hmmio, &mmckRIFF, NULL, MMIO_FINDRIFF))
{
return FALSE;
}
mmck.ckid = mmioFMT;
if (wError = mmioDescend(hmmio, &mmck, &mmckRIFF, MMIO_FINDCHUNK))
{
return FALSE;
}
if (mmck.cksize < sizeof(WAVEFORMAT))
{
return FALSE;
}
pwd->wFormatSize = (WORD)mmck.cksize;
pwd->pwavefmt = (NPWAVEFORMATEX)LocalAlloc(LPTR, pwd->wFormatSize);
if (!pwd->pwavefmt)
{
return FALSE;
}
if ((DWORD)mmioRead(hmmio, (HPSTR)pwd->pwavefmt, mmck.cksize) != mmck.cksize)
{
goto RetErr;
}
if (pwd->pwavefmt->wFormatTag == WAVE_FORMAT_PCM)
{
if (pwd->wFormatSize < sizeof(PCMWAVEFORMAT))
{
goto RetErr;
}
}
else if ((pwd->wFormatSize < sizeof(WAVEFORMATEX)) || (pwd->wFormatSize < sizeof(WAVEFORMATEX) + pwd->pwavefmt->cbSize))
{
goto RetErr;
}
if (wError = mmioAscend(hmmio, &mmck, 0))
{
goto RetErr;
}
mmck.ckid = mmioDATA;
if (wError = mmioDescend(hmmio, &mmck, &mmckRIFF, MMIO_FINDCHUNK))
{
goto RetErr;
}
pwd->dSize = mmck.cksize;
return TRUE;
RetErr:
LocalFree((HLOCAL)pwd->pwavefmt);
pwd->pwavefmt = NULL;
return FALSE;
}
STATIC void GetWaveInfo(HMMIO hmmio, PMMPSH pmmpsh)
{
WAVEDESC wd;
if (!ReadWaveHeader(hmmio, &wd))
return;
pmmpsh->uLen = (UINT)MulDiv(wd.dSize, 1000, wd.pwavefmt->nAvgBytesPerSec);
pmmpsh->pAudioFormatInfo = (PVOID)wd.pwavefmt;
}
STATIC void GetMCIInfo(LPTSTR pszFile, PMMPSH pmmpsh)
{
TCHAR szMIDIInfo[MAXSTR];
MCI_OPEN_PARMS mciOpen; /* Structure for MCI_OPEN command */
DWORD dwFlags;
DWORD dw;
UINT wDevID;
MCI_STATUS_PARMS mciStatus;
MCI_SET_PARMS mciSet; /* Structure for MCI_SET command */
MCI_INFO_PARMS mciInfo;
/* Open a file with an explicitly specified device */
memset(&mciOpen, 0x00, sizeof(mciOpen));
mciOpen.lpstrDeviceType = aszMIDIDev;
mciOpen.lpstrElementName = pszFile;
dwFlags = MCI_WAIT | MCI_OPEN_ELEMENT | MCI_OPEN_TYPE;
dw = mciSendCommand((MCIDEVICEID)0, MCI_OPEN, dwFlags,(DWORD_PTR)(LPVOID)&mciOpen);
if (dw)
return;
wDevID = mciOpen.wDeviceID;
mciSet.dwTimeFormat = MCI_FORMAT_MILLISECONDS;
dw = mciSendCommand(wDevID, MCI_SET, MCI_SET_TIME_FORMAT,
(DWORD_PTR) (LPVOID) &mciSet);
if (dw)
{
mciSendCommand(wDevID, MCI_CLOSE, 0L, (DWORD_PTR)0);
return;
}
mciStatus.dwItem = MCI_STATUS_LENGTH;
dw = mciSendCommand(wDevID, MCI_STATUS, MCI_STATUS_ITEM,
(DWORD_PTR) (LPTSTR) &mciStatus);
if (dw)
pmmpsh->uLen = 0;
else
pmmpsh->uLen = (UINT)mciStatus.dwReturn;
mciInfo.dwCallback = 0;
mciInfo.lpstrReturn = szMIDIInfo;
mciInfo.dwRetSize = sizeof(szMIDIInfo);
szMIDIInfo[0] = TEXT('\0');
dw = mciSendCommand(wDevID, MCI_INFO, MCI_INFO_COPYRIGHT, (DWORD_PTR)(LPVOID)&mciInfo);
if (dw == 0 && lstrlen(szMIDIInfo))
{
pmmpsh->MIDICOPYRIGHTSTR = LocalAlloc(LPTR, lstrlen(szMIDIInfo) + 1);
if (pmmpsh->MIDICOPYRIGHTSTR)
{
lstrcpy((LPTSTR)pmmpsh->MIDICOPYRIGHTSTR, szMIDIInfo);
}
}
mciInfo.lpstrReturn = szMIDIInfo;
mciInfo.dwRetSize = sizeof(szMIDIInfo);
szMIDIInfo[0] = TEXT('\0');
dw = mciSendCommand(wDevID, MCI_INFO, MCI_INFO_NAME, (DWORD_PTR)(LPVOID)&mciInfo);
if (dw == 0 && lstrlen(szMIDIInfo))
{
pmmpsh->MIDISEQNAMESTR = LocalAlloc(LPTR, lstrlen(szMIDIInfo) + 1);
if (pmmpsh->MIDISEQNAMESTR)
{
lstrcpy((LPTSTR)pmmpsh->MIDISEQNAMESTR, szMIDIInfo);
}
}
mciSendCommand(wDevID, MCI_CLOSE, 0L, (DWORD)0);
}
STATIC void GetMIDIInfo(LPTSTR pszFile, PMMPSH pmmpsh)
{
GetMCIInfo(pszFile, pmmpsh);
}
STATIC void ReadAviStreams(LPTSTR pszFile, PMMPSH pmmpsh)
{
HRESULT hr;
PAVIFILE pfile;
int i;
PAVISTREAM pavi;
PAVISTREAM apavi[MAXNUMSTREAMS]; // the current streams
AVISTREAMINFO avis;
LONG timeStart; // cached start, end, length
LONG timeEnd;
int cpavi;
TCHAR szDecSep[10];
TCHAR szListSep[10];
hr = (HRESULT)AVIFileOpen(&pfile, pszFile, 0, 0L);
if (FAILED(hr))
{
DPF("Unable to open %s", pszFile);
return;
}
for (i = 0; i <= MAXNUMSTREAMS; i++)
{
if (AVIFileGetStream(pfile, &pavi, 0L, i) != AVIERR_OK)
break;
if (i == MAXNUMSTREAMS)
{
AVIStreamRelease(pavi);
DPF("Exceeded maximum number of streams");
break;
}
apavi[i] = pavi;
}
//
// Couldn't get any streams out of this file
//
if (i == 0)
{
DPF("Unable to open any streams in %s", pszFile);
if (pfile)
AVIFileRelease(pfile);
return;
}
cpavi = i;
//
// Start with bogus times
//
timeStart = 0x7FFFFFFF;
timeEnd = 0;
//bug 141733, get the local decimal and list separators
GetLocaleInfo( GetUserDefaultLCID(), LOCALE_SDECIMAL, szDecSep, sizeof(szDecSep)/sizeof(TCHAR) );
GetLocaleInfo( GetUserDefaultLCID(), LOCALE_SLIST, szListSep, sizeof(szListSep)/sizeof(TCHAR) );
//
// Walk through and init all streams loaded
//
for (i = 0; i < cpavi; i++)
{
AVIStreamInfo(apavi[i], &avis, sizeof(avis));
switch(avis.fccType)
{
case streamtypeVIDEO:
{
LONG cbFormat;
LPVOID lpFormat;
ICINFO icInfo;
HIC hic;
DWORD dwTimeLen;
DWORD dwSize;
int iFrameRate;
TCHAR szFormat[MAXSTR];
if (pmmpsh->pVideoFormatInfo)
break;
AVIStreamFormatSize(apavi[i], 0, &cbFormat);
pmmpsh->pVideoFormatInfo = (PVOID)LocalAlloc(LPTR, MAX_PATH);
if (!pmmpsh->pVideoFormatInfo)
break;
dwSize = mmpshGetFileSize(pszFile);
dwTimeLen = (DWORD)(AVIStreamEndTime(apavi[i]) - AVIStreamStartTime(apavi[i]));
iFrameRate = MulDiv(avis.dwLength, 1000000, dwTimeLen);
lpFormat = (LPVOID)LocalAlloc(LPTR, cbFormat);
if (!lpFormat)
{
goto BadFormat;
}
AVIStreamReadFormat(apavi[i], 0, lpFormat, &cbFormat);
hic = (HIC)ICLocate(FOURCC_VIDC, avis.fccHandler, lpFormat, NULL, (WORD)ICMODE_DECOMPRESS);
if (hic || ((LPBITMAPINFOHEADER)lpFormat)->biCompression == 0)
{
TCHAR szName[48];
if (((LPBITMAPINFOHEADER)lpFormat)->biCompression)
{
ICGetInfo(hic, &icInfo, sizeof(ICINFO));
ICClose(hic);
//WideCharToMultiByte(CP_ACP, 0, icInfo.szName, -1, szName, sizeof(szName), NULL, NULL);
wcscpy(szName,icInfo.szName);
}
else
{
LoadString(ghInstance, IDS_UNCOMPRESSED, szName, sizeof(szName)/sizeof(TCHAR));
}
LoadString(ghInstance, IDS_GOODFORMAT, szFormat, sizeof(szFormat)/sizeof(TCHAR));
wsprintf((LPTSTR)pmmpsh->pVideoFormatInfo, szFormat, (avis.rcFrame.right - avis.rcFrame.left),
(avis.rcFrame.bottom - avis.rcFrame.top), szListSep, ((LPBITMAPINFOHEADER)lpFormat)->biBitCount, szListSep,
avis.dwLength, szListSep, (UINT)(iFrameRate/1000), szDecSep, (UINT)(iFrameRate%1000), szListSep, MulDiv(dwSize, 1000,dwTimeLen)/1024, szListSep, szName);
goto GoodFormat;
}
BadFormat:
LoadString(ghInstance, IDS_BADFORMAT, szFormat, sizeof(szFormat)/sizeof(TCHAR));
wsprintf((LPTSTR)pmmpsh->pVideoFormatInfo, szFormat, (avis.rcFrame.right - avis.rcFrame.left),
(avis.rcFrame.bottom - avis.rcFrame.top), szListSep,
avis.dwLength, szListSep, (UINT)(iFrameRate/1000), szDecSep, (UINT)(iFrameRate%1000), szListSep, MulDiv(dwSize, 1000,dwTimeLen)/1024, szListSep);
GoodFormat:
LocalFree((HLOCAL)lpFormat);
break;
}
case streamtypeAUDIO:
{
LONG cbFormat;
AVIStreamFormatSize(apavi[i], 0, &cbFormat);
pmmpsh->pAudioFormatInfo = (LPVOID)LocalAlloc(LPTR, cbFormat);
if (!pmmpsh->pAudioFormatInfo)
break;
AVIStreamReadFormat(apavi[i], 0, pmmpsh->pAudioFormatInfo, &cbFormat);
break;
}
default:
break;
}
//
// We're finding the earliest and latest start and end points for
// our scrollbar.
//
timeStart = (LONG)min(timeStart, AVIStreamStartTime(apavi[i]));
timeEnd = (LONG)max(timeEnd, AVIStreamEndTime(apavi[i]));
}
pmmpsh->uLen = (UINT)(timeEnd - timeStart);
DPF("The file length is %d \r\n", pmmpsh->uLen);
for (i = 0; i < cpavi; i++)
{
AVIStreamRelease(apavi[i]);
}
AVIFileRelease(pfile);
}
STATIC void GetAVIInfo(LPTSTR pszFile, PMMPSH pmmpsh)
{
if (!LoadAVI())
{
DPF("****Load AVI failed**\r\n");
ASSERT(FALSE);
return;
}
if (!LoadVFW())
{
DPF("****Load VFW failed**\r\n");
ASSERT(FALSE);
FreeAVI();
return;
}
AVIFileInit();
ReadAviStreams(pszFile, pmmpsh);
AVIFileExit();
if (!FreeVFW())
{
DPF("****Free VFW failed**\r\n");
ASSERT(FALSE);
}
if (!FreeAVI())
{
DPF("****Free AVI failed**\r\n");
ASSERT(FALSE);
}
}
STATIC void GetASFInfo(LPTSTR pszFile, PMMPSH pmmpsh)
{
}
STATIC void GetMediaInfo(HMMIO hmmio, PMMPSH pmmpsh)
{
switch (pmmpsh->iMediaType)
{
case MT_WAVE:
GetWaveInfo(hmmio, pmmpsh);
break;
case MT_MIDI:
GetMIDIInfo(pmmpsh->pszFileObj, pmmpsh);
break;
case MT_AVI:
GetAVIInfo(pmmpsh->pszFileObj, pmmpsh);
break;
case MT_ASF:
GetASFInfo(pmmpsh->pszFileObj, pmmpsh);
break;
}
}
STATIC HANDLE PASCAL GetRiffAll(PMMPSH pmmpsh)
{
MMCKINFO ck;
MMCKINFO ckINFO;
MMCKINFO ckRIFF;
HANDLE h = NULL;
LONG lSize;
DWORD dw;
HMMIO hmmio;
BOOL fDoneDISP;
BOOL fDoneINFO;
BOOL fDoneName;
LPSTR pInfo;
hmmio = mmioOpen(pmmpsh->pszFileObj, NULL, MMIO_ALLOCBUF | MMIO_READ);
if (!hmmio)
goto error;
GetMediaInfo(hmmio, pmmpsh);
if (pmmpsh->uLen == 0)
goto error;
mmioSeek(hmmio, 0, SEEK_SET);
/* descend the input file into the RIFF chunk */
if (mmioDescend(hmmio, &ckRIFF, NULL, 0) != 0)
goto error;
if (ckRIFF.ckid != FOURCC_RIFF)
goto error;
fDoneDISP = fDoneINFO = fDoneName = FALSE;
while (!(fDoneDISP && fDoneINFO) && !mmioDescend(hmmio, &ck, &ckRIFF, 0))
{
if (ck.ckid == FOURCC_DISP)
{
/* Read dword into dw, break if read unsuccessful */
if (mmioRead(hmmio, (LPVOID)&dw, sizeof(dw)) != (LONG)sizeof(dw))
goto error;
/* Find out how much memory to allocate */
lSize = ck.cksize - sizeof(dw);
if ((int)dw == CF_DIB && h == NULL)
{
/* get a handle to memory to hold the description and
lock it down */
if ((h = GlobalAlloc(GHND, lSize+4)) == NULL)
goto error;
if (mmioRead(hmmio, GlobalLock(h), lSize) != lSize)
goto error;
fDoneDISP = TRUE;
}
else if ((int)dw == CF_TEXT)
{
pInfo = (LPSTR)LocalAlloc(LPTR, lSize+1);//+1 not required I think
if (!pInfo)
goto error;
if (!mmioRead(hmmio, pInfo, lSize))
goto error;
AddInfoToList(pmmpsh, pInfo, ck.ckid );
fDoneName = TRUE;
}
}
else if (ck.ckid == FOURCC_LIST &&
ck.fccType == FOURCC_INFO &&
!fDoneINFO)
{
while (!mmioDescend(hmmio, &ckINFO, &ck, 0))
{
switch (ckINFO.ckid)
{
case FOURCC_ISBJ:
case FOURCC_INAM:
case FOURCC_ICOP:
case FOURCC_ICRD:
case FOURCC_IART:
case FOURCC_ICMS:
case FOURCC_ICMT:
case FOURCC_ICRP:
case FOURCC_IDIM:
case FOURCC_IARL:
case FOURCC_IDPI:
case FOURCC_IENG:
case FOURCC_IGNR:
case FOURCC_IKEY:
case FOURCC_ILGT:
case FOURCC_IMED:
case FOURCC_IPLT:
case FOURCC_IPRD:
case FOURCC_ISFT:
case FOURCC_ISHP:
case FOURCC_ISRC:
case FOURCC_ISRF:
case FOURCC_ITCH:
pInfo = (LPSTR)LocalAlloc(LPTR, ck.cksize+1);//+1 not required I think
if (!pInfo)
goto error;
if (!mmioRead(hmmio, pInfo, ck.cksize))
goto error;
AddInfoToList(pmmpsh, pInfo, ckINFO.ckid);
if (ckINFO.ckid == FOURCC_INAM)
fDoneName = TRUE;
break;
}
if (mmioAscend(hmmio, &ckINFO, 0))
break;
}
}
/* Ascend so that we can descend into next chunk
*/
if (mmioAscend(hmmio, &ck, 0))
break;
}
goto exit;
error:
if (h)
{
GlobalUnlock(h);
GlobalFree(h);
}
h = NULL;
ReleaseInfoList(pmmpsh);
exit:
if (hmmio)
mmioClose(hmmio,0);
return h;
}
STATIC BOOL PASCAL WaveGetFormatDescription
(
LPWAVEFORMATEX pwfx,
LPTSTR pszDesc
)
{
UINT_PTR mmr;
TCHAR pszFormatTag[ACMFORMATTAGDETAILS_FORMATTAG_CHARS];
TCHAR pszFormat[ACMFORMATDETAILS_FORMAT_CHARS];
BOOL bRet = FALSE;
TCHAR szListSep[10];
//
// get the name for the format tag of the specified format
//
if (!pwfx)
{
pszDesc[0] = TEXT('\0');
return TRUE;
}
if (!LoadACM())
{
DPF("****Load ACM failed**\r\n");
ASSERT(FALSE);
return FALSE;
}
if (NULL != pszFormatTag)
{
PACMFORMATTAGDETAILSW paftd;
//
// initialize all unused members of the ACMFORMATTAGDETAILS
// structure to zero
//
paftd = (PACMFORMATTAGDETAILSW)LocalAlloc(LPTR, sizeof(ACMFORMATTAGDETAILSW));
if (!paftd)
goto RetErr;
//
// fill in the required members of the ACMFORMATTAGDETAILS
// structure for the ACM_FORMATTAGDETAILSF_FORMATTAG query
//
paftd->cbStruct = sizeof(ACMFORMATTAGDETAILSW);
paftd->dwFormatTag = pwfx->wFormatTag;
//
// ask the ACM to find the first available driver that
// supports the specified format tag
//
mmr = acmFormatTagDetails(NULL,
paftd,
ACM_FORMATTAGDETAILSF_FORMATTAG);
if (MMSYSERR_NOERROR == mmr)
{
//
// copy the format tag name into the caller's buffer
//
lstrcpy(pszFormatTag, paftd->szFormatTag);
}
else
{
static const struct _wfm_names {
UINT uFormatTag;
UINT uIDS;
} aWaveFmtNames[] = {
WAVE_FORMAT_PCM, IDS_FORMAT_PCM,
WAVE_FORMAT_ADPCM, IDS_FORMAT_ADPCM,
WAVE_FORMAT_IBM_CVSD, IDS_FORMAT_IBM_CVSD,
WAVE_FORMAT_ALAW, IDS_FORMAT_ALAW,
WAVE_FORMAT_MULAW, IDS_FORMAT_MULAW,
WAVE_FORMAT_OKI_ADPCM, IDS_FORMAT_OKI_ADPCM,
WAVE_FORMAT_IMA_ADPCM, IDS_FORMAT_IMA_ADPCM,
WAVE_FORMAT_MEDIASPACE_ADPCM, IDS_FORMAT_MEDIASPACE_ADPCM,
WAVE_FORMAT_SIERRA_ADPCM, IDS_FORMAT_SIERRA_ADPCM,
WAVE_FORMAT_G723_ADPCM, IDS_FORMAT_G723_ADPCM,
WAVE_FORMAT_DIGISTD, IDS_FORMAT_DIGISTD,
WAVE_FORMAT_DIGIFIX, IDS_FORMAT_DIGIFIX,
WAVE_FORMAT_YAMAHA_ADPCM, IDS_FORMAT_YAMAHA_ADPCM,
WAVE_FORMAT_SONARC, IDS_FORMAT_SONARC,
WAVE_FORMAT_DSPGROUP_TRUESPEECH, IDS_FORMAT_DSPGROUP_TRUESPEECH,
WAVE_FORMAT_ECHOSC1, IDS_FORMAT_ECHOSC1,
WAVE_FORMAT_AUDIOFILE_AF36, IDS_FORMAT_AUDIOFILE_AF36,
WAVE_FORMAT_APTX, IDS_FORMAT_APTX,
WAVE_FORMAT_AUDIOFILE_AF10, IDS_FORMAT_AUDIOFILE_AF10,
WAVE_FORMAT_DOLBY_AC2, IDS_FORMAT_DOLBY_AC2,
WAVE_FORMAT_GSM610, IDS_FORMAT_GSM610,
WAVE_FORMAT_G721_ADPCM, IDS_FORMAT_G721_ADPCM,
WAVE_FORMAT_CREATIVE_ADPCM, IDS_FORMAT_CREATIVE_ADPCM,
0, IDS_UNKFORMAT,
};
UINT ii;
//
// no ACM driver is available that supports the
// specified format tag. look up the tag id
// in our table of tag names (above)
//
for (ii = 0; aWaveFmtNames[ii].uFormatTag; ii++)
if (pwfx->wFormatTag == aWaveFmtNames[ii].uFormatTag)
break;
LoadString(ghInstance, aWaveFmtNames[ii].uIDS, pszFormatTag, ACMFORMATTAGDETAILS_FORMATTAG_CHARS);
}
LocalFree((HLOCAL)paftd);
}
//
// get the description of the attributes for the specified
// format
//
if (NULL != pszFormat)
{
PACMFORMATDETAILSW pafd;
//
// initialize all unused members of the ACMFORMATDETAILS
// structure to zero
//
pafd = (PACMFORMATDETAILSW)LocalAlloc(LPTR, sizeof(ACMFORMATDETAILSW));
if (!pafd)
goto RetErr;
//
// fill in the required members of the ACMFORMATDETAILS
// structure for the ACM_FORMATDETAILSF_FORMAT query
//
pafd->cbStruct = sizeof(ACMFORMATDETAILSW);
pafd->dwFormatTag = pwfx->wFormatTag;
pafd->pwfx = pwfx;
//
// the cbwfx member must be initialized to the total size
// in bytes needed for the specified format. for a PCM
// format, the cbSize member of the WAVEFORMATEX structure
// is not valid.
//
if (WAVE_FORMAT_PCM == pwfx->wFormatTag)
{
pafd->cbwfx = sizeof(PCMWAVEFORMAT);
}
else
{
pafd->cbwfx = sizeof(WAVEFORMATEX) + pwfx->cbSize;
}
//
// ask the ACM to find the first available driver that
// supports the specified format
//
mmr = acmFormatDetails(NULL, pafd, ACM_FORMATDETAILSF_FORMAT);
if (MMSYSERR_NOERROR == mmr)
{
//
// copy the format attributes description into the caller's
// buffer
//
lstrcpy(pszFormat, pafd->szFormat);
}
else
{
pszFormat[0] = TEXT('\0');
}
LocalFree((HLOCAL)pafd);
}
//bug 141733, get the local decimal and list separators
GetLocaleInfo( GetUserDefaultLCID(), LOCALE_SLIST, szListSep, sizeof(szListSep)/sizeof(TCHAR) );
wsprintf(pszDesc, TEXT("%s%s %s"), pszFormatTag, szListSep, pszFormat);
bRet = TRUE;
RetErr:
if (!FreeACM())
{
DPF("****Free ACM failed**\r\n");
ASSERT(FALSE);
}
return bRet;
} // AcmAppGetFormatDescription()
STATIC void ShowInfoList(PMMPSH pmmpsh, HWND hDlg)
{
PMMINFOLIST pCur;
TCHAR* szTemp;
HWND hwndLB = GetDlgItem(hDlg, IDD_INFO_NAME);
TCHAR szNoCopyRight[MAXSTR];
int iIndex;
LoadString(ghInstance, IDS_NOCOPYRIGHT, szNoCopyRight, sizeof(szNoCopyRight)/sizeof(TCHAR));
SetDlgItemText(hDlg, IDD_COPYRIGHT, szNoCopyRight);
if (!pmmpsh->pInfoList)
{
DestroyWindow(GetDlgItem(hDlg, IDC_DETAILSINFO_GRP));
DestroyWindow(GetDlgItem(hDlg, IDC_ITEMSLABEL));
DestroyWindow(GetDlgItem(hDlg, IDC_DESCLABEL));
DestroyWindow(GetDlgItem(hDlg, IDD_INFO_NAME));
DestroyWindow(GetDlgItem(hDlg, IDD_INFO_VALUE));
return;
}
for (pCur = pmmpsh->pInfoList; pCur; pCur = pCur->pNext)
{
int nTempSize = (strlen(pCur->pszInfo)*sizeof(TCHAR))+sizeof(TCHAR);
szTemp = (LPTSTR)LocalAlloc(LPTR, nTempSize);
if (!szTemp) return;
MultiByteToWideChar(GetACP(), 0,
pCur->pszInfo, -1,
szTemp, nTempSize);
if (pCur->ckid == FOURCC_ICOP)
{
SetDlgItemText(hDlg, IDD_COPYRIGHT, szTemp);
LocalFree(szTemp);
continue;
}
iIndex = ListBox_AddString(hwndLB, pCur->szInfoDesc);
if (iIndex != LB_ERR)
{
//reassigning wide pointer back into "info" so it will get cleaned up later
pCur->pszInfo = (LPSTR)szTemp;
ListBox_SetItemData(hwndLB, iIndex, (LPARAM)pCur->pszInfo);
}
}
SetFocus(hwndLB);
if (ListBox_SetCurSel(hwndLB, 0) != LB_ERR)
FORWARD_WM_COMMAND(hDlg, IDD_INFO_NAME, hwndLB, LBN_SELCHANGE, PostMessage);
}
BOOL PASCAL DoDetailsCommand(HWND hDlg, int id, HWND hwndCtl, UINT codeNotify)
{
switch (id)
{
case ID_APPLY:
return TRUE;
case IDOK:
break;
case IDCANCEL:
break;
case ID_INIT:
{
PMMPSH pmmpsh = (PMMPSH)GetWindowLongPtr(hDlg, DWLP_USER);
if (pmmpsh->hDispBMP)
{
HWND hwndDisp = GetDlgItem(hDlg,IDD_DISPFRAME);
HDC hdc;
HPALETTE hpalT;
int i;
SendMessage(hwndDisp, (UINT)DF_PM_SETBITMAP, (WPARAM)pmmpsh->hDispBMP,
(LPARAM)pmmpsh->hPal);
/*
* If realizing the palette causes the palette to change,
* redraw completely.
*/
hdc = GetDC(hwndDisp);
hpalT = SelectPalette (hdc, pmmpsh->hPal, FALSE);
i = RealizePalette(hdc); /* i == entries that changed */
SelectPalette (hdc, hpalT, FALSE);
ReleaseDC(hwndDisp, hdc);
/* If any palette entries changed, repaint the window. */
if (i > 0)
{
InvalidateRect(hwndDisp, NULL, TRUE);
}
}
break;
}
case IDD_INFO_NAME:
if (codeNotify == LBN_SELCHANGE)
{
int iIndex = ListBox_GetCurSel(hwndCtl);
LPTSTR pszInfo = (LPTSTR)ListBox_GetItemData(hwndCtl, iIndex);
SetDlgItemText(hDlg, IDD_INFO_VALUE, pszInfo);
}
break;
}
return FALSE;
}
STATIC void ShowMediaLen(PMMPSH pmmpsh, HWND hwnd)
{
TCHAR szBuf[MAXSTR];
TCHAR szFmt[MAXSTR];
UINT uMin;
UINT uSec;
UINT umSec;
UINT uLen;
TCHAR szDecSep[10];
uLen = pmmpsh->uLen;
if ((!uLen && pmmpsh->iMediaType != MT_WAVE) || (!pmmpsh->pAudioFormatInfo && pmmpsh->iMediaType != MT_MIDI && pmmpsh->iMediaType != MT_AVI && pmmpsh->iMediaType != MT_ASF))
{
LoadString(ghInstance, IDS_BADFILE, szBuf, sizeof(szBuf)/sizeof(TCHAR));
SetWindowText(hwnd, szBuf);
return;
}
uMin = (UINT)(uLen/60000);
uSec = (UINT)((uLen/1000) % 60);
umSec = (UINT)(uLen % 1000);
//bug 141733, get the local decimal separator
GetLocaleInfo( GetUserDefaultLCID(), LOCALE_SDECIMAL, szDecSep, sizeof(szDecSep)/sizeof(TCHAR) );
if (uMin)
{
LoadString(ghInstance, IDS_MINFMT, szFmt, sizeof(szFmt)/sizeof(TCHAR));
wsprintf(szBuf, szFmt, uMin, uSec, szDecSep, umSec);
}
else
{
LoadString(ghInstance, IDS_SECFMT, szFmt, sizeof(szFmt)/sizeof(TCHAR));
wsprintf(szBuf, szFmt, uSec, szDecSep, umSec);
}
SetWindowText(hwnd, szBuf);
}
STATIC void ShowMediaFormat(PMMPSH pmmpsh, HWND hDlg)
{
switch (pmmpsh->iMediaType)
{
case MT_WAVE:
{
TCHAR szDesc[MAX_PATH];
szDesc[0] = TEXT('\0');
WaveGetFormatDescription((LPWAVEFORMATEX)pmmpsh->pAudioFormatInfo, szDesc);
SetDlgItemText(hDlg, IDD_AUDIOFORMAT, szDesc);
DestroyWindow(GetDlgItem(hDlg, IDD_VIDEOFORMAT));
DestroyWindow(GetDlgItem(hDlg, IDD_VIDEOFORMATLABEL));
DestroyWindow(GetDlgItem(hDlg, IDD_MIDISEQUENCELABEL));
DestroyWindow(GetDlgItem(hDlg, IDD_MIDISEQUENCENAME));
break;
}
case MT_MIDI:
DestroyWindow(GetDlgItem(hDlg, IDD_AUDIOFORMAT));
DestroyWindow(GetDlgItem(hDlg, IDD_AUDIOFORMATLABEL));
DestroyWindow(GetDlgItem(hDlg, IDD_VIDEOFORMAT));
DestroyWindow(GetDlgItem(hDlg, IDD_VIDEOFORMATLABEL));
if (pmmpsh->MIDICOPYRIGHTSTR)
SetDlgItemText(hDlg, IDD_COPYRIGHT, (LPTSTR)pmmpsh->MIDICOPYRIGHTSTR);
if (pmmpsh->MIDISEQNAMESTR)
SetDlgItemText(hDlg, IDD_MIDISEQUENCENAME, (LPTSTR)pmmpsh->MIDISEQNAMESTR);
else
{
DestroyWindow(GetDlgItem(hDlg, IDD_MIDISEQUENCELABEL));
DestroyWindow(GetDlgItem(hDlg, IDD_MIDISEQUENCENAME));
}
break;
case MT_AVI:
{
TCHAR szDesc[MAX_PATH];
DestroyWindow(GetDlgItem(hDlg, IDD_MIDISEQUENCELABEL));
DestroyWindow(GetDlgItem(hDlg, IDD_MIDISEQUENCENAME));
szDesc[0] = TEXT('\0');
if (pmmpsh->pVideoFormatInfo)
SetDlgItemText(hDlg, IDD_VIDEOFORMAT, (LPTSTR)pmmpsh->pVideoFormatInfo);
else
SetDlgItemText(hDlg, IDD_VIDEOFORMAT, (LPTSTR)szDesc);
WaveGetFormatDescription((LPWAVEFORMATEX)pmmpsh->pAudioFormatInfo, szDesc);
SetDlgItemText(hDlg, IDD_AUDIOFORMAT, szDesc);
break;
}
case MT_ASF:
{
break;
}
}
}
const static DWORD aFileDetailsIds[] = { // Context Help IDs
IDD_DISPFRAME, NO_HELP,
IDD_DISP_ICON, IDH_FPROP_GEN_ICON,
IDD_FILENAME, IDH_FPROP_GEN_NAME,
IDD_CRLABEL, IDH_FCAB_MM_COPYRIGHT,
IDD_COPYRIGHT, IDH_FCAB_MM_COPYRIGHT,
IDD_LENLABEL, IDH_FCAB_MM_FILELEN,
IDD_FILELEN, IDH_FCAB_MM_FILELEN,
IDD_AUDIOFORMATLABEL, IDH_FCAB_MM_AUDIOFORMAT,
IDD_AUDIOFORMAT, IDH_FCAB_MM_AUDIOFORMAT,
IDD_MIDISEQUENCELABEL, IDH_FCAB_MM_MIDISEQUENCENAME,
IDD_MIDISEQUENCENAME, IDH_FCAB_MM_MIDISEQUENCENAME,
IDD_VIDEOFORMATLABEL, IDH_FCAB_MM_VIDEOFORMAT,
IDD_VIDEOFORMAT, IDH_FCAB_MM_VIDEOFORMAT,
IDC_DETAILSINFO_GRP, IDH_FCAB_MM_DETAILSINFO,
IDC_ITEMSLABEL, IDH_FCAB_MM_DETAILSINFO,
IDC_DESCLABEL, IDH_FCAB_MM_DETAILSINFO,
IDD_INFO_NAME, IDH_FCAB_MM_DETAILSINFO,
IDD_INFO_VALUE, IDH_FCAB_MM_DETAILSINFO,
0, 0
};
INT_PTR CALLBACK FileDetailsDlg(HWND hDlg, UINT uMsg, WPARAM wParam,
LPARAM lParam)
{
NMHDR FAR *lpnm;
switch (uMsg)
{
case WM_NOTIFY:
lpnm = (NMHDR FAR *)lParam;
switch(lpnm->code)
{
case PSN_KILLACTIVE:
FORWARD_WM_COMMAND(hDlg, IDOK, 0, 0, SendMessage);
break;
case PSN_APPLY:
FORWARD_WM_COMMAND(hDlg, ID_APPLY, 0, 0, SendMessage);
break;
case PSN_SETACTIVE:
FORWARD_WM_COMMAND(hDlg, ID_INIT, 0, 0, SendMessage);
break;
case PSN_RESET:
FORWARD_WM_COMMAND(hDlg, IDCANCEL, 0, 0, SendMessage);
break;
}
break;
case WM_INITDIALOG:
{
PMMPSH pmmpsh = (PMMPSH)(((LPPROPSHEETPAGE)lParam)->lParam);
TCHAR szFile[MAX_PATH];
HANDLE hDib = NULL;
HCURSOR hCursor;
hCursor = SetCursor(LoadCursor(NULL,IDC_WAIT));
SetWindowLongPtr(hDlg, DWLP_USER, (LPARAM)pmmpsh);
if (!pmmpsh->pInfoList)
{
hDib = GetRiffAll(pmmpsh);
}
if (!hDib)
break;
pmmpsh->hPal = bmfCreateDIBPalette(hDib);
pmmpsh->hDispBMP = bmfBitmapFromDIB(hDib, pmmpsh->hPal);
if (hDib)
{
GlobalUnlock(hDib);
hDib = GlobalFree(hDib);
}
if (!pmmpsh->hDispBMP)
{
int iIconID;
switch (pmmpsh->iMediaType)
{
case MT_WAVE:
iIconID = IDI_DWAVE;
break;
case MT_MIDI:
iIconID = IDI_DMIDI;
break;
case MT_AVI:
case MT_ASF:
iIconID = IDI_DVIDEO;
break;
}
DestroyWindow(GetDlgItem(hDlg,IDD_DISPFRAME));
pmmpsh->hIcon = LoadIcon(ghInstance, MAKEINTRESOURCE(iIconID));
Static_SetIcon(GetDlgItem(hDlg, IDD_DISP_ICON), pmmpsh->hIcon);
}
else
{
DestroyWindow(GetDlgItem(hDlg,IDD_DISP_ICON));
//SendDlgItemMessage(hDlg, (int)IDD_DISPFRAME, (UINT)DF_PM_SETBITMAP, (WPARAM)pmmpsh->hDispBMP,
// (LPARAM)pmmpsh->hPal);
}
lstrcpy(szFile, pmmpsh->pszFileObj);
NiceName(szFile, TRUE);
SetDlgItemText(hDlg, IDD_FILENAME, szFile);
ShowMediaLen(pmmpsh, GetDlgItem(hDlg, IDD_FILELEN));
ShowInfoList(pmmpsh, hDlg);
ShowMediaFormat(pmmpsh, hDlg);
SetCursor(hCursor);
break;
}
case WM_DESTROY:
{
PMMPSH pmmpsh = (PMMPSH)GetWindowLongPtr(hDlg, DWLP_USER);
if (pmmpsh->hDispBMP)
DeleteObject(pmmpsh->hDispBMP);
if (pmmpsh->hIcon)
DestroyIcon(pmmpsh->hIcon);
if (pmmpsh->hPal)
DeleteObject(pmmpsh->hPal);
if (pmmpsh->pAudioFormatInfo)
LocalFree((HLOCAL)pmmpsh->pAudioFormatInfo);
if (pmmpsh->pVideoFormatInfo)
LocalFree((HLOCAL)pmmpsh->pVideoFormatInfo);
break;
}
case WM_CONTEXTMENU:
WinHelp((HWND)wParam, gszWindowsHlp, HELP_CONTEXTMENU,
(UINT_PTR)(LPTSTR)aFileDetailsIds);
return TRUE;
case WM_HELP:
WinHelp(((LPHELPINFO)lParam)->hItemHandle, gszWindowsHlp, HELP_WM_HELP
, (UINT_PTR)(LPTSTR)aFileDetailsIds);
return TRUE;
case WM_COMMAND:
HANDLE_WM_COMMAND(hDlg, wParam, lParam, DoDetailsCommand);
break;
}
return FALSE;
}
static DWORD aPreviewIds[] = { // Context Help IDs
0, IDH_FCAB_MM_PREVIEW_CONTROL,
IDD_DISP_ICON, IDH_FPROP_GEN_ICON,
IDD_FILENAME, IDH_FPROP_GEN_NAME,
0, 0
};
INT_PTR CALLBACK PreviewDlg(HWND hDlg, UINT uMsg, WPARAM wParam,
LPARAM lParam)
{
static BOOL fLoadedVFW;
static HICON hIcon;
switch (uMsg)
{
case WM_NOTIFY:
{
NMHDR FAR *lpnm;
lpnm = (NMHDR FAR *)lParam;
switch(lpnm->code)
{
case PSN_KILLACTIVE:
{
HWND hwndMCI = (HWND)GetWindowLongPtr(hDlg, DWLP_USER);
DPF("***PSN_KILLACTIVE***\r\n");
if (IsWindow(hwndMCI))
MCIWndStop(hwndMCI);
break;
}
case PSN_APPLY:
DPF("***PSN_APPLY***\r\n");
return TRUE;
}
break;
}
case WM_INITDIALOG:
{
PMMPSH pmmpsh = (PMMPSH)(((LPPROPSHEETPAGE)lParam)->lParam);
HCURSOR hCursor;
HWND hwndMCI;
HWND hwndTitle;
RECT rcWnd;
RECT rcDlg;
TCHAR szFile[MAX_PATH];
TCHAR szTitle[MAXSTR];
TCHAR szTmp[MAXSTR];
#ifndef DEBUG_BUILT_LINKED
FN_MCIWNDCREATE fnMCIWndCreate;
#endif
hCursor = SetCursor(LoadCursor(NULL,IDC_WAIT));
lstrcpy(szFile, pmmpsh->pszFileObj);
NiceName(szFile, TRUE);
LoadString(ghInstance, IDS_PREVIEWOF, szTmp, sizeof(szTmp)/sizeof(TCHAR));
wsprintf(szTitle, szTmp, szFile);
hwndTitle = GetDlgItem(hDlg, IDD_FILENAME);
SetWindowText(hwndTitle, szTitle);
fLoadedVFW = FALSE;
if (!LoadVFW())
{
DPF("****Load VFW failed**\r\n");
ASSERT(FALSE);
break;
}
fLoadedVFW = TRUE;
#ifndef DEBUG_BUILT_LINKED
fnMCIWndCreate = (FN_MCIWNDCREATE)MCIWndCreateW;
hwndMCI = fnMCIWndCreate(hDlg, ghInstance, (DWORD)MCIWNDF_NOMENU, (LPCTSTR)pmmpsh->pszFileObj);
#else
hwndMCI = MCIWndCreateW(hDlg, ghInstance, (DWORD)MCIWNDF_NOMENU, (LPCTSTR)pmmpsh->pszFileObj);
#endif
aPreviewIds[0] = GetDlgCtrlID(hwndMCI);
GetWindowRect(hwndMCI, &rcWnd);
MapWindowPoints(NULL, hDlg, (LPPOINT)&rcWnd, 2);
GetWindowRect(hDlg, &rcDlg);
MapWindowPoints(NULL, hDlg, (LPPOINT)&rcDlg, 2);
hIcon = NULL;
switch (pmmpsh->iMediaType)
{
case MT_WAVE:
case MT_MIDI:
{
int ircWndTop;
ircWndTop = (int)((rcDlg.bottom - rcDlg.top)/2) - 50;
rcWnd.top += ircWndTop;
rcWnd.bottom += ircWndTop;
rcWnd.left = 20;
rcWnd.right = rcDlg.right - 20;
MoveWindow(hwndMCI, rcWnd.left, rcWnd.top, (rcWnd.right - rcWnd.left),
(rcWnd.bottom - rcWnd.top), FALSE);
GetWindowRect(hwndTitle, &rcWnd);
MapWindowPoints(NULL, hDlg, (LPPOINT)&rcWnd, 2);
OffsetRect(&rcWnd, 52, 36);
MoveWindow(hwndTitle, rcWnd.left, rcWnd.top, (rcWnd.right - rcWnd.left),
(rcWnd.bottom - rcWnd.top), FALSE);
hIcon = LoadIcon(ghInstance, MAKEINTRESOURCE(IDI_DWAVE+pmmpsh->iMediaType-1));
Static_SetIcon(GetDlgItem(hDlg, IDD_DISP_ICON),hIcon);
break;
}
case MT_AVI:
{
int iDlgHt = rcDlg.bottom - rcDlg.top -15; //15 for the title
int iDlgWth = rcDlg.right - rcDlg.left;
int iWndHt = rcWnd.bottom - rcWnd.top;
int iWndWth = rcWnd.right - rcWnd.left;
DestroyWindow(GetDlgItem(hDlg, IDD_DISP_ICON));
if (iWndWth < iDlgWth && iWndHt < iDlgHt)
{
int ixOff = (int)((iDlgWth - iWndWth)/2);
int iyOff = (int)((iDlgHt - iWndHt)/2) + 15;
OffsetRect(&rcWnd, ixOff, iyOff);
MoveWindow(hwndMCI, rcWnd.left, rcWnd.top, (rcWnd.right - rcWnd.left),
(rcWnd.bottom - rcWnd.top), FALSE);
}
else
{
int ixExcess = iWndWth - iDlgWth;
int iyExcess = iWndHt - (iDlgHt - 15); //Take another 15 off
int ixOff;
int iyOff;
RECT rcSource;
RECT rcDest;
RECT rcDestWnd;
MCIWndGetDest(hwndMCI, &rcSource);
//DPF("The Video Window is too big: SHRINKING\r\nrcSource = %d,%d,%d%d ** rcWnd=%d,%d,%d,%d ** rcDlg=%d,%d,%d,%d\r\n",
// rcSource.left,rcSource.top,rcSource.right,rcSource.bottom,
// rcWnd.left,rcWnd.top,rcWnd.right,rcWnd.bottom,
// rcDlg.left,rcDlg.top,rcDlg.right,rcDlg.bottom);
rcDest.top = rcSource.top; // new boundaries
rcDest.left = rcSource.left;
if (ixExcess > iyExcess)
{
rcDest.right = rcSource.left +
(((rcSource.right - rcSource.left)*(iDlgWth - 20))/iWndWth);
rcDest.bottom = rcSource.top +
(((rcSource.bottom - rcSource.top)*(iDlgWth - 20))/iWndWth);
//DPF("rcDest = %d,%d,%d,%d\r\n",rcDest.left,rcDest.top,rcDest.right,rcDest.bottom);
}
else
{
rcDest.right = rcSource.left +
(((rcSource.right - rcSource.left)*(iDlgHt - 20))/iWndHt);
rcDest.bottom = rcSource.top +
(((rcSource.bottom - rcSource.top)*(iDlgHt - 20))/iWndHt);
}
rcDestWnd.top = rcWnd.top;
rcDestWnd.left = rcWnd.left;
rcDestWnd.right = rcWnd.left + (rcDest.right - rcDest.left);
rcDestWnd.bottom = rcWnd.top + (rcDest.bottom - rcDest.top)
+ (iWndHt - (rcSource.bottom - rcSource.top));
//DPF("rcDestWnd = %d,%d,%d,%d\r\n",rcDestWnd.left,rcDestWnd.top,rcDestWnd.right,rcDestWnd.bottom);
ixOff = (int)((iDlgWth - (rcDestWnd.right - rcDestWnd.left))/2);
iyOff = (int)((iDlgHt - (rcDestWnd.bottom - rcDestWnd.top))/2) + 15;
//DPF("ixOff = %, iyOff = %d\r\n", ixOff, iyOff);
OffsetRect(&rcDestWnd, ixOff, iyOff);
MCIWndPutDest(hwndMCI, &rcDest);
MoveWindow(hwndMCI, rcDestWnd.left, rcDestWnd.top, (rcDestWnd.right - rcDestWnd.left),
(rcDestWnd.bottom - rcDestWnd.top), FALSE);
}
break;
case MT_ASF:
break;
}
}
SetWindowLongPtr(hDlg, DWLP_USER, (LPARAM)hwndMCI);
SetCursor(hCursor);
break;
}
case WM_CLOSE:
DPF("***WM_CLOSE***\r\n");
break;
case WM_DESTROY:
{
HWND hwndMCI = (HWND)GetWindowLongPtr(hDlg, DWLP_USER);
DPF("***WM_DESTROY***\r\n");
if (hIcon)
{
DestroyIcon(hIcon);
hIcon = NULL;
}
if (IsWindow(hwndMCI))
MCIWndDestroy(hwndMCI);
SetWindowLongPtr(hDlg, DWLP_USER, (LPARAM)NULL);
if (!fLoadedVFW)
break;
if (!FreeVFW())
{
DPF("****Free VFW failed**\r\n");
ASSERT(FALSE);
}
fLoadedVFW = FALSE;
break;
}
case WM_CONTEXTMENU:
WinHelp((HWND)wParam, gszWindowsHlp, HELP_CONTEXTMENU,
(UINT_PTR)(LPTSTR)aPreviewIds);
return TRUE;
case WM_HELP:
WinHelp(((LPHELPINFO)lParam)->hItemHandle, gszWindowsHlp, HELP_WM_HELP
, (UINT_PTR)(LPTSTR)aPreviewIds);
return TRUE;
case WM_QUERYNEWPALETTE:
case WM_PALETTECHANGED:
{
HWND hwndMCI = (HWND)GetWindowLongPtr(hDlg, DWLP_USER);
SendMessage(hwndMCI, uMsg, wParam, lParam);
break;
}
}
return FALSE;
}
//---------------------------------------------------------------------------
// mmse IUnknown base member functions
//---------------------------------------------------------------------------
/*----------------------------------------------------------
Purpose: IUnknown::QueryInterface
Returns: standard
Cond: --
*/
STDMETHODIMP mmpsh_QueryInterface(
LPUNKNOWN punk,
REFIID riid,
LPVOID FAR* ppvOut)
{
PMMPSH this = IToClass(mmpsh, sei, punk);
HRESULT hres = ResultFromScode(E_NOINTERFACE);
*ppvOut = NULL;
if (IsEqualIID(riid, &IID_IUnknown) ||
IsEqualIID(riid, &IID_IShellExtInit))
{
// We use the sei field as our IUnknown as well
*ppvOut = &this->sei;
this->cRef++;
hres = NOERROR;
}
else if (IsEqualIID(riid, &IID_IShellPropSheetExt))
{
(LPSHELLPROPSHEETEXT)*ppvOut = &this->pse;
this->cRef++;
hres = NOERROR;
}
return hres;
}
/*----------------------------------------------------------
Purpose: IUnknown::AddRef
Returns: new reference count
Cond: --
*/
STDMETHODIMP_(UINT) mmpsh_AddRef(
LPUNKNOWN punk)
{
PMMPSH this = IToClass(mmpsh, sei, punk);
return ++this->cRef;
}
/*----------------------------------------------------------
Purpose: IUnknown::Release
Returns: new reference count
Cond: --
*/
STDMETHODIMP_(UINT) mmpsh_Release(
LPUNKNOWN punk)
{
PMMPSH this = IToClass(mmpsh, sei, punk);
if (--this->cRef)
{
return this->cRef;
}
DPF_T("*^*^*^*^*^*^*^*^*^MMPSH nuked , RefCnt = %d *^*^*^*^ \r\n", (g_cRef - 1));
if (this->pdtobj)
{
this->pdtobj->lpVtbl->Release(this->pdtobj);
}
if (this->pszFileObj)
{
LocalFree((HLOCAL)this->pszFileObj);
}
ReleaseInfoList(this);
LocalFree((HLOCAL)this);
--g_cRef;
return 0;
}
/*----------------------------------------------------------
Purpose: IShellExtInit::QueryInterface
Returns: standard
Cond: --
*/
STDMETHODIMP mmpsh_SEI_QueryInterface(
LPSHELLEXTINIT psei,
REFIID riid,
LPVOID FAR* ppvOut)
{
PMMPSH this = IToClass(mmpsh, sei, psei);
return mmpsh_QueryInterface((LPUNKNOWN)&this->sei, riid, ppvOut);
}
/*----------------------------------------------------------
Purpose: IShellExtInit::AddRef
Returns: new reference count
Cond: --
*/
STDMETHODIMP_(UINT) mmpsh_SEI_AddRef(
LPSHELLEXTINIT psei)
{
PMMPSH this = IToClass(mmpsh, sei, psei);
return mmpsh_AddRef((LPUNKNOWN)&this->sei);
}
/*----------------------------------------------------------
Purpose: IShellExtInit::Release
Returns: new reference count
Cond: --
*/
STDMETHODIMP_(UINT) mmpsh_SEI_Release(
LPSHELLEXTINIT psei)
{
PMMPSH this = IToClass(mmpsh, sei, psei);
return mmpsh_Release((LPUNKNOWN)&this->sei);
}
/*----------------------------------------------------------
Purpose: MMPSHReleaseStgMedium
Returns: NOERROR
Cond: --
*/
HRESULT MMPSHReleaseStgMedium(LPSTGMEDIUM pmedium)
{
//
// Double-check pUnkForRelease in case we're not supposed to
// release the medium.
//
if (NULL == pmedium->pUnkForRelease)
{
switch(pmedium->tymed)
{
case TYMED_HGLOBAL:
GlobalFree(pmedium->hGlobal);
break;
case TYMED_ISTORAGE:
pmedium->pstg->lpVtbl->Release(pmedium->pstg);
break;
case TYMED_ISTREAM:
pmedium->pstm->lpVtbl->Release(pmedium->pstm);
break;
default:
ASSERT(FALSE); // unknown type
break;
}
}
return NOERROR;
}
/*----------------------------------------------------------
Purpose: IShellExtInit::Initialize
Returns: noerror
Cond: --
*/
STDMETHODIMP mmpsh_SEI_Initialize(
LPSHELLEXTINIT psei,
LPCITEMIDLIST pidlObj,
LPDATAOBJECT pdtobj,
HKEY hkeyProgID)
{
HRESULT hres = NOERROR;
PMMPSH this = IToClass(mmpsh, sei, psei);
DPF("mmpsh_SEI_Initialize called\n");
if (pdtobj)
{
STGMEDIUM medium;
FORMATETC fmte = {CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
if (this->pdtobj)
{
this->pdtobj->lpVtbl->Release(this->pdtobj);
}
this->pdtobj = pdtobj;
pdtobj->lpVtbl->AddRef(pdtobj);
hres = pdtobj->lpVtbl->GetData(pdtobj, &fmte, &medium);
if(SUCCEEDED(hres))
{
if (DragQueryFile(medium.hGlobal, (UINT)-1, NULL, 0))
{
TCHAR szPath[MAX_PATH];
int iIndex;
DWORD dwSize = 0;
szPath[0] = '\0';
DragQueryFile(medium.hGlobal, 0, szPath, sizeof(szPath)/sizeof(TCHAR));
dwSize = mmpshGetFileSize(szPath);
if (dwSize != 0)
{
iIndex = lstrlen(szPath) - 4;
if (!lstrcmpi((LPTSTR)(szPath+iIndex), cszWavExt))
this->iMediaType = MT_WAVE;
else if (!lstrcmpi((LPTSTR)(szPath+iIndex), cszMIDIExt))
this->iMediaType = MT_MIDI;
else if (!lstrcmpi((LPTSTR)(szPath+iIndex), cszRMIExt))
this->iMediaType = MT_MIDI;
else if (!lstrcmpi((LPTSTR)(szPath+iIndex), cszAVIExt))
this->iMediaType = MT_AVI;
else if (!lstrcmpi((LPTSTR)(szPath+iIndex), cszASFExt))
this->iMediaType = MT_ASF;
else
this->iMediaType = MT_ERROR;
if (!this->pszFileObj || lstrcmpi(this->pszFileObj, szPath))
{
if (this->pszFileObj)
LocalFree((HLOCAL)this->pszFileObj);
ReleaseInfoList(this);
if (this->iMediaType)
{
this->pszFileObj = (LPTSTR)LocalAlloc(LPTR, (lstrlen(szPath)*sizeof(TCHAR))+sizeof(TCHAR));
if (this->pszFileObj) lstrcpy(this->pszFileObj , szPath);
}
else
hres = ResultFromScode(E_FAIL);
}
}
else
hres = ResultFromScode(E_FAIL);
}
//
// Release STGMEDIUM if we're responsible for doing that.
//
if (NULL == medium.pUnkForRelease)
MMPSHReleaseStgMedium(&medium);
}
else
return hres;
}
return hres;
}
/*----------------------------------------------------------
Purpose: IShellPropSheetExt::QueryInterface
Returns: standard
Cond: --
*/
STDMETHODIMP mmpsh_PSE_QueryInterface(
LPSHELLPROPSHEETEXT ppse,
REFIID riid,
LPVOID FAR* ppvOut)
{
PMMPSH this = IToClass(mmpsh, pse, ppse);
return mmpsh_QueryInterface((LPUNKNOWN)&this->sei, riid, ppvOut);
}
/*----------------------------------------------------------
Purpose: IShellPropSheetExt::AddRef
Returns: new reference count
Cond: --
*/
STDMETHODIMP_(UINT) mmpsh_PSE_AddRef(
LPSHELLPROPSHEETEXT ppse)
{
PMMPSH this = IToClass(mmpsh, pse, ppse);
return mmpsh_AddRef((LPUNKNOWN)&this->sei);
}
/*----------------------------------------------------------
Purpose: IShellPropSheetExt::Release
Returns: new reference count
Cond: --
*/
STDMETHODIMP_(UINT) mmpsh_PSE_Release(
LPSHELLPROPSHEETEXT ppse)
{
PMMPSH this = IToClass(mmpsh, pse, ppse);
return mmpsh_Release((LPUNKNOWN)&this->sei);
}
/*==========================================================================*/
UINT CALLBACK DetailsPageCallback(
HWND hwnd,
UINT uMsg,
LPPROPSHEETPAGE ppsp)
{
if (uMsg == PSPCB_RELEASE)
if (((PMMPSH)(ppsp->lParam))->pse.lpVtbl)
((PMMPSH)(ppsp->lParam))->pse.lpVtbl->Release(&(((PMMPSH)(ppsp->lParam))->pse));
else
{
LocalFree((HLOCAL)((PMMPSH)(ppsp->lParam))->pszFileObj);
LocalFree((HLOCAL)ppsp->lParam);
}
return 1;
}
BOOL AddDetailsPage(
LPTSTR pszTitle,
LPFNADDPROPSHEETPAGE lpfnAddPropSheetPage,
LPARAM lDlgParam,
LPARAM lParam)
{
PROPSHEETPAGE psp;
HPROPSHEETPAGE hpsp;
psp.dwSize = sizeof(PROPSHEETPAGE);
psp.dwFlags = PSP_USETITLE | PSP_USECALLBACK;
psp.hInstance = ghInstance;
psp.pszTemplate = MAKEINTRESOURCE(DLG_FILE_DETAILS);
psp.pszIcon = NULL;
psp.pszTitle = pszTitle;
psp.pfnDlgProc = FileDetailsDlg;
psp.lParam = lDlgParam;
psp.pfnCallback = DetailsPageCallback;
psp.pcRefParent = NULL;
if (hpsp = CreatePropertySheetPage(&psp))
{
if (lpfnAddPropSheetPage(hpsp, lParam))
return TRUE;
DestroyPropertySheetPage(hpsp);
}
return FALSE;
}
UINT CALLBACK PreviewPageCallback(
HWND hwnd,
UINT uMsg,
LPPROPSHEETPAGE ppsp)
{
return 1;
}
BOOL AddPreviewPage(
LPTSTR pszTitle,
LPFNADDPROPSHEETPAGE lpfnAddPropSheetPage,
LPARAM lDlgParam,
LPARAM lParam)
{
PROPSHEETPAGE psp;
HPROPSHEETPAGE hpsp;
psp.dwSize = sizeof(PROPSHEETPAGE);
psp.dwFlags = PSP_USETITLE | PSP_USECALLBACK;
psp.hInstance = ghInstance;
psp.pszTemplate = MAKEINTRESOURCE(PREVIEW_DLG);
psp.pszIcon = NULL;
psp.pszTitle = pszTitle;
psp.pfnDlgProc = PreviewDlg;
psp.lParam = lDlgParam;
psp.pfnCallback = PreviewPageCallback;
psp.pcRefParent = NULL;
if (hpsp = CreatePropertySheetPage(&psp))
{
if (lpfnAddPropSheetPage(hpsp, lParam))
return TRUE;
DestroyPropertySheetPage(hpsp);
}
return FALSE;
}
/*----------------------------------------------------------
Purpose: IShellPropSheetExt::AddPages
Returns: NOERROR
Cond: --
*/
STDMETHODIMP mmpsh_PSE_AddPages(
LPSHELLPROPSHEETEXT ppse,
LPFNADDPROPSHEETPAGE lpfnAddPage,
LPARAM lParam)
{
PMMPSH this = IToClass(mmpsh, pse, ppse);
/* BOOL fAddPreview = FALSE;
LoadString(ghInstance, IDS_DETAILS, szDetailsTab, sizeof(szDetailsTab)/sizeof(TCHAR));
RegSndCntrlClass((LPCTSTR)DISPFRAMCLASS);
AddDetailsPage(szDetailsTab,lpfnAddPage,(LPARAM)this, lParam);
switch (this->iMediaType)
{
case MT_AVI:
fAddPreview = TRUE;
break;
case MT_WAVE:
if (waveOutGetNumDevs() > 0)
fAddPreview = TRUE;
break;
case MT_MIDI:
if (midiOutGetNumDevs() > 0)
fAddPreview = TRUE;
break;
}
if (fAddPreview)
{
LoadString(ghInstance, IDS_PREVIEW, szPreviewTab, sizeof(szPreviewTab)/sizeof(TCHAR));
AddPreviewPage(szPreviewTab,lpfnAddPage,(LPARAM)this, lParam);
} */
ppse->lpVtbl->AddRef(ppse);
return NOERROR;
}
/*----------------------------------------------------------
Purpose: IShellPropSheetExt::ReplacePage
Returns: E_NOTIMPL
Cond: --
*/
STDMETHODIMP mmpsh_PSE_ReplacePage(
LPSHELLPROPSHEETEXT ppse,
UINT uPageID,
LPFNADDPROPSHEETPAGE lpfnReplaceWith,
LPARAM lParam)
{
return ResultFromScode(E_NOTIMPL);
}
IShellExtInitVtbl c_mmpshSEIVtbl =
{
mmpsh_SEI_QueryInterface,
mmpsh_SEI_AddRef,
mmpsh_SEI_Release,
mmpsh_SEI_Initialize
};
IShellPropSheetExtVtbl c_mmpshPSEVtbl =
{
mmpsh_PSE_QueryInterface,
mmpsh_PSE_AddRef,
mmpsh_PSE_Release,
mmpsh_PSE_AddPages,
mmpsh_PSE_ReplacePage
} ;
HRESULT CALLBACK mmpsh_CreatePSHInstance(
LPUNKNOWN punkOuter,
REFIID riid,
LPVOID FAR* ppvOut)
{
HRESULT hres;
PMMPSH this;
DPF_T("*^*^*^*^*^*^*^*^mmpsh_CreatePSHInstance*^*^*^*^*^*^*^*^\r\n");
// The handler does not support aggregation.
if (punkOuter)
{
hres = ResultFromScode(CLASS_E_NOAGGREGATION);
goto Leave;
}
this = LocalAlloc(LPTR, sizeof(*this));
if (!this)
{
hres = ResultFromScode(E_OUTOFMEMORY);
goto Leave;
}
this->sei.lpVtbl = &c_mmpshSEIVtbl;
this->pse.lpVtbl = &c_mmpshPSEVtbl;
this->cRef = 1;
++g_cRef;
// Note that the Release member will free the object, if
// QueryInterface failed.
hres = this->sei.lpVtbl->QueryInterface(&this->sei, riid, ppvOut);
this->sei.lpVtbl->Release(&this->sei);
Leave:
return hres; // S_OK or E_NOINTERFACE
}
BOOL mmpsh_ShowFileDetails(LPTSTR pszCaption,
HWND hwndParent,
LPTSTR pszFile,
short iMediaType)
{
PMMPSH pmmpsh;
TCHAR szTabName[64];
pmmpsh = (PMMPSH)LocalAlloc(LPTR, sizeof(*pmmpsh));
if (!pmmpsh)
return FALSE;
pmmpsh->pszFileObj = (LPTSTR)LocalAlloc(LPTR, (lstrlen(pszFile)*sizeof(TCHAR))+sizeof(TCHAR));
if (!pmmpsh->pszFileObj)
{
LocalFree((HLOCAL)pmmpsh);
return FALSE;
}
lstrcpy(pmmpsh->pszFileObj , pszFile);
pmmpsh->iMediaType = iMediaType;
LoadString(ghInstance, IDS_DETAILS, szTabName, sizeof(szTabName)/sizeof(TCHAR));
ShowPropSheet(szTabName,FileDetailsDlg,DLG_FILE_DETAILS,hwndParent,pszCaption,(LPARAM)pmmpsh);
return TRUE;
}
BOOL ResolveLink(LPTSTR szPath, LPTSTR szResolved, LONG cbSize)
{
IShellLink *psl = NULL;
HRESULT hres;
hres = SHCoCreateInstance(NULL, &CLSID_ShellLink, NULL, &IID_IShellLink, &psl);
if (SUCCEEDED(hres))
{
WCHAR wszPath[MAX_PATH];
IPersistFile *ppf;
psl->lpVtbl->QueryInterface(psl, &IID_IPersistFile, &ppf);
if (ppf)
{
wcscpy(wszPath, szPath);
hres = ppf->lpVtbl->Load(ppf, wszPath, 0);
ppf->lpVtbl->Release(ppf);
if (FAILED(hres))
{
psl->lpVtbl->Release(psl);
psl = NULL;
}
}
else
{
psl = NULL;
}
}
if (psl)
{
// this reslve could fail.. should we really do NOUI?
psl->lpVtbl->Resolve(psl, NULL, SLR_NO_UI);
psl->lpVtbl->GetPath(psl, szResolved, cbSize, NULL,
SLGP_SHORTPATH);
psl->lpVtbl->Release(psl);
}
if (SUCCEEDED(hres))
return TRUE;
return FALSE;
}
//---------------------------------------------------------------------------
// EXPORTED API
//---------------------------------------------------------------------------
/*----------------------------------------------------------
Purpose: Standard shell entry-point
Returns: standard
Cond: --
*/
STDAPI DllGetClassObject(
REFCLSID rclsid,
REFIID riid,
LPVOID FAR* ppv)
{
// We are supposed return the class object for this class. Instead
// of fully implementing it in this DLL, we just call a helper
// function in the shell DLL which creates a default class factory
// object for us. When its CreateInstance member is called, it
// will call back our create instance function.
//
if (IsEqualIID(rclsid, &CLSID_mmsePropSheetHandler))
{
return SHCreateDefClassObject(
riid, // Interface ID
ppv, // Non-null to aggregate
mmpsh_CreatePSHInstance, // Callback function
&g_cRef, // Reference count of this DLL
&IID_IShellExtInit); // Init interface
}
return ResultFromScode(REGDB_E_CLASSNOTREG);
}
//****************************************************************************
// STDAPI DllCanUnLoadNow()
//
// This function is called by shell
//
//****************************************************************************
STDAPI DllCanUnloadNow(void)
{
HRESULT hr;
if (0 == g_cRef)
{
DPF("DllCanUnloadNow says OK (Ref=%d)",
g_cRef);
hr = ResultFromScode(S_OK);
}
else
{
DPF("DllCanUnloadNow says FALSE (Ref=%d)",
g_cRef);
hr = ResultFromScode(S_FALSE);
}
return hr;
}