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

  1. //****************************************************************************
  2. //
  3. // Module: MMSE.DLL
  4. // File: mmse.c
  5. // Content: This file contains the moudle initialization.
  6. // History:
  7. // 06/1994 -By- Vij Rajarajan (VijR)
  8. //
  9. // Copyright (c) Microsoft Corporation 1991-1994
  10. //
  11. //****************************************************************************
  12. #define INITGUID
  13. #include "mmcpl.h"
  14. #include <coguid.h>
  15. #include <oleguid.h>
  16. #include <shlguid.h>
  17. #include <mmddk.h>
  18. #include <mmreg.h>
  19. #include <msacm.h>
  20. #include <msacmdrv.h>
  21. #include <vfw.h>
  22. #include <shlobj.h>
  23. #undef INITGUID
  24. #include <shlobjp.h>
  25. //****************************************************************************
  26. // Initialize GUIDs (should be done only and at-least once per DLL/EXE)
  27. //****************************************************************************
  28. #include <commctrl.h>
  29. #include <prsht.h>
  30. #include "draw.h"
  31. #include "utils.h"
  32. #include "medhelp.h"
  33. /*
  34. ***************************************************************
  35. * Typedefs
  36. ***************************************************************
  37. */
  38. typedef HWND (VFWAPIV * FN_MCIWNDCREATE)();
  39. //---------------------------------------------------------------------------
  40. // MMPSH class
  41. //---------------------------------------------------------------------------
  42. typedef struct _mmInfoList MMINFOLIST;
  43. typedef MMINFOLIST * PMMINFOLIST;
  44. typedef struct _mmInfoList
  45. {
  46. TCHAR szInfoDesc[80];
  47. LPSTR pszInfo;
  48. FOURCC ckid;
  49. PMMINFOLIST pNext;
  50. };
  51. // mmse class structure. This is used for instances of
  52. // IPersistFolder, IShellFolder, and IShellDetails.
  53. typedef struct _mmpsh
  54. {
  55. // We use the pf also as our IUnknown interface
  56. IShellExtInit sei; // 1st base class
  57. IShellPropSheetExt pse; // 2nd base class
  58. LPDATAOBJECT pdtobj;
  59. UINT cRef; // reference count
  60. LPTSTR pszFileObj;
  61. UINT uLen;
  62. short iMediaType;
  63. PVOID pAudioFormatInfo;
  64. PVOID pVideoFormatInfo;
  65. HPALETTE hPal;
  66. HBITMAP hDispBMP;
  67. HICON hIcon;
  68. PMMINFOLIST pInfoList;
  69. } mmpsh, * PMMPSH;
  70. /*
  71. ***************************************************************
  72. * Defines
  73. ***************************************************************
  74. */
  75. #define MIDICOPYRIGHTSTR pAudioFormatInfo
  76. #define MIDISEQNAMESTR pVideoFormatInfo
  77. #define MAXNUMSTREAMS 50
  78. /*
  79. ***************************************************************
  80. * File Globals
  81. ***************************************************************
  82. */
  83. int g_cRef = 0;
  84. SZCODE cszWavExt[] = TEXT(".WAV");
  85. SZCODE cszMIDIExt[] = TEXT(".MID");
  86. SZCODE cszRMIExt[] = TEXT(".RMI");
  87. SZCODE cszAVIExt[] = TEXT(".AVI");
  88. SZCODE cszASFExt[] = TEXT(".ASF");
  89. SZCODE cszSlash[] = TEXT("\\");
  90. static SZCODE aszMIDIDev[] = TEXT("sequencer");
  91. static TCHAR szDetailsTab[64];
  92. static TCHAR szPreviewTab[64];
  93. /*
  94. ***************************************************************
  95. * Prototypes
  96. ***************************************************************
  97. */
  98. LPTSTR PASCAL NiceName(LPTSTR sz, BOOL fNukePath);
  99. /*
  100. ***************************************************************
  101. ***************************************************************
  102. */
  103. DWORD mmpshGetFileSize(LPTSTR szFile)
  104. {
  105. HANDLE hFile;
  106. OFSTRUCT of;
  107. DWORD dwSize = 0;
  108. hFile = CreateFile(szFile, GENERIC_READ, FILE_SHARE_READ,NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  109. if (INVALID_HANDLE_VALUE != hFile)
  110. {
  111. dwSize = GetFileSize(hFile, NULL);
  112. CloseHandle(hFile);
  113. }
  114. return dwSize;
  115. }
  116. STATIC void ReleaseInfoList(PMMPSH pmmpsh)
  117. {
  118. PMMINFOLIST pCur;
  119. pCur = pmmpsh->pInfoList;
  120. while (pCur)
  121. {
  122. PMMINFOLIST pTmp;
  123. pTmp = pCur;
  124. pCur = pCur->pNext;
  125. LocalFree((HLOCAL)pTmp->pszInfo);
  126. LocalFree((HLOCAL)pTmp);
  127. }
  128. pmmpsh->pInfoList = NULL;
  129. }
  130. STATIC BOOL AddInfoToList(PMMPSH pmmpsh, LPSTR pInfo, FOURCC ckid)
  131. {
  132. PMMINFOLIST pCur;
  133. int idStr;
  134. for (pCur = pmmpsh->pInfoList; pCur && pCur->pNext ; pCur = pCur->pNext)
  135. if (pCur->ckid == ckid)
  136. return TRUE;
  137. if (!pCur)
  138. {
  139. pCur = pmmpsh->pInfoList = (PMMINFOLIST)LocalAlloc(LPTR, sizeof(MMINFOLIST));
  140. }
  141. else
  142. {
  143. pCur->pNext = (PMMINFOLIST)LocalAlloc(LPTR, sizeof(MMINFOLIST));
  144. pCur = pCur->pNext;
  145. }
  146. if (!pCur)
  147. return FALSE;
  148. pCur->ckid = ckid;
  149. pCur->pszInfo = pInfo;
  150. switch (ckid)
  151. {
  152. case FOURCC_INAM:
  153. idStr = IDS_FOURCC_INAM;
  154. break;
  155. case FOURCC_ICOP:
  156. idStr = IDS_FOURCC_ICOP;
  157. break;
  158. case FOURCC_ICMT:
  159. idStr = IDS_FOURCC_ICMT;
  160. break;
  161. case FOURCC_ISBJ:
  162. idStr = IDS_FOURCC_ISBJ;
  163. break;
  164. case FOURCC_ICRD:
  165. idStr = IDS_FOURCC_ICRD;
  166. break;
  167. case FOURCC_IART:
  168. idStr = IDS_FOURCC_IART;
  169. break;
  170. case FOURCC_DISP:
  171. idStr = IDS_FOURCC_DISP;
  172. break;
  173. case FOURCC_ICMS:
  174. idStr = IDS_FOURCC_ICMS;
  175. break;
  176. case FOURCC_ICRP:
  177. idStr = IDS_FOURCC_ICRP;
  178. break;
  179. case FOURCC_IDIM:
  180. idStr = IDS_FOURCC_IDIM;
  181. break;
  182. case FOURCC_IDPI:
  183. idStr = IDS_FOURCC_IDPI;
  184. break;
  185. case FOURCC_IENG:
  186. idStr = IDS_FOURCC_IENG;
  187. break;
  188. case FOURCC_IGNR:
  189. idStr = IDS_FOURCC_IGNR;
  190. break;
  191. case FOURCC_IKEY:
  192. idStr = IDS_FOURCC_IKEY;
  193. break;
  194. case FOURCC_ILGT:
  195. idStr = IDS_FOURCC_ILGT;
  196. break;
  197. case FOURCC_IARL:
  198. idStr = IDS_FOURCC_IARL;
  199. break;
  200. case FOURCC_IMED:
  201. idStr = IDS_FOURCC_IMED;
  202. break;
  203. case FOURCC_IPLT:
  204. idStr = IDS_FOURCC_IPLT;
  205. break;
  206. case FOURCC_IPRD:
  207. idStr = IDS_FOURCC_IPRD;
  208. break;
  209. case FOURCC_ISFT:
  210. idStr = IDS_FOURCC_ISFT;
  211. break;
  212. case FOURCC_ISHP:
  213. idStr = IDS_FOURCC_ISHP;
  214. break;
  215. case FOURCC_ISRC:
  216. idStr = IDS_FOURCC_ISRC;
  217. break;
  218. case FOURCC_ISRF:
  219. idStr = IDS_FOURCC_ISRF;
  220. break;
  221. case FOURCC_ITCH:
  222. idStr = IDS_FOURCC_ITCH;
  223. break;
  224. }
  225. if (idStr)
  226. LoadString(ghInstance, idStr, pCur->szInfoDesc, sizeof(pCur->szInfoDesc)/sizeof(TCHAR));
  227. return TRUE;
  228. }
  229. typedef struct tagWaveDesc
  230. {
  231. DWORD dSize;
  232. WORD wFormatSize;
  233. NPWAVEFORMATEX pwavefmt;
  234. } WAVEDESC,* PWAVEDESC;
  235. STATIC BOOL PASCAL NEAR ReadWaveHeader(HMMIO hmmio,
  236. PWAVEDESC pwd)
  237. {
  238. MMCKINFO mmckRIFF;
  239. MMCKINFO mmck;
  240. MMRESULT wError;
  241. mmckRIFF.fccType = mmioWAVE;
  242. if (wError = mmioDescend(hmmio, &mmckRIFF, NULL, MMIO_FINDRIFF))
  243. {
  244. return FALSE;
  245. }
  246. mmck.ckid = mmioFMT;
  247. if (wError = mmioDescend(hmmio, &mmck, &mmckRIFF, MMIO_FINDCHUNK))
  248. {
  249. return FALSE;
  250. }
  251. if (mmck.cksize < sizeof(WAVEFORMAT))
  252. {
  253. return FALSE;
  254. }
  255. pwd->wFormatSize = (WORD)mmck.cksize;
  256. pwd->pwavefmt = (NPWAVEFORMATEX)LocalAlloc(LPTR, pwd->wFormatSize);
  257. if (!pwd->pwavefmt)
  258. {
  259. return FALSE;
  260. }
  261. if ((DWORD)mmioRead(hmmio, (HPSTR)pwd->pwavefmt, mmck.cksize) != mmck.cksize)
  262. {
  263. goto RetErr;
  264. }
  265. if (pwd->pwavefmt->wFormatTag == WAVE_FORMAT_PCM)
  266. {
  267. if (pwd->wFormatSize < sizeof(PCMWAVEFORMAT))
  268. {
  269. goto RetErr;
  270. }
  271. }
  272. else if ((pwd->wFormatSize < sizeof(WAVEFORMATEX)) || (pwd->wFormatSize < sizeof(WAVEFORMATEX) + pwd->pwavefmt->cbSize))
  273. {
  274. goto RetErr;
  275. }
  276. if (wError = mmioAscend(hmmio, &mmck, 0))
  277. {
  278. goto RetErr;
  279. }
  280. mmck.ckid = mmioDATA;
  281. if (wError = mmioDescend(hmmio, &mmck, &mmckRIFF, MMIO_FINDCHUNK))
  282. {
  283. goto RetErr;
  284. }
  285. pwd->dSize = mmck.cksize;
  286. return TRUE;
  287. RetErr:
  288. LocalFree((HLOCAL)pwd->pwavefmt);
  289. pwd->pwavefmt = NULL;
  290. return FALSE;
  291. }
  292. STATIC void GetWaveInfo(HMMIO hmmio, PMMPSH pmmpsh)
  293. {
  294. WAVEDESC wd;
  295. if (!ReadWaveHeader(hmmio, &wd))
  296. return;
  297. pmmpsh->uLen = (UINT)MulDiv(wd.dSize, 1000, wd.pwavefmt->nAvgBytesPerSec);
  298. pmmpsh->pAudioFormatInfo = (PVOID)wd.pwavefmt;
  299. }
  300. STATIC void GetMCIInfo(LPTSTR pszFile, PMMPSH pmmpsh)
  301. {
  302. TCHAR szMIDIInfo[MAXSTR];
  303. MCI_OPEN_PARMS mciOpen; /* Structure for MCI_OPEN command */
  304. DWORD dwFlags;
  305. DWORD dw;
  306. UINT wDevID;
  307. MCI_STATUS_PARMS mciStatus;
  308. MCI_SET_PARMS mciSet; /* Structure for MCI_SET command */
  309. MCI_INFO_PARMS mciInfo;
  310. /* Open a file with an explicitly specified device */
  311. memset(&mciOpen, 0x00, sizeof(mciOpen));
  312. mciOpen.lpstrDeviceType = aszMIDIDev;
  313. mciOpen.lpstrElementName = pszFile;
  314. dwFlags = MCI_WAIT | MCI_OPEN_ELEMENT | MCI_OPEN_TYPE;
  315. dw = mciSendCommand((MCIDEVICEID)0, MCI_OPEN, dwFlags,(DWORD_PTR)(LPVOID)&mciOpen);
  316. if (dw)
  317. return;
  318. wDevID = mciOpen.wDeviceID;
  319. mciSet.dwTimeFormat = MCI_FORMAT_MILLISECONDS;
  320. dw = mciSendCommand(wDevID, MCI_SET, MCI_SET_TIME_FORMAT,
  321. (DWORD_PTR) (LPVOID) &mciSet);
  322. if (dw)
  323. {
  324. mciSendCommand(wDevID, MCI_CLOSE, 0L, (DWORD_PTR)0);
  325. return;
  326. }
  327. mciStatus.dwItem = MCI_STATUS_LENGTH;
  328. dw = mciSendCommand(wDevID, MCI_STATUS, MCI_STATUS_ITEM,
  329. (DWORD_PTR) (LPTSTR) &mciStatus);
  330. if (dw)
  331. pmmpsh->uLen = 0;
  332. else
  333. pmmpsh->uLen = (UINT)mciStatus.dwReturn;
  334. mciInfo.dwCallback = 0;
  335. mciInfo.lpstrReturn = szMIDIInfo;
  336. mciInfo.dwRetSize = sizeof(szMIDIInfo);
  337. szMIDIInfo[0] = TEXT('\0');
  338. dw = mciSendCommand(wDevID, MCI_INFO, MCI_INFO_COPYRIGHT, (DWORD_PTR)(LPVOID)&mciInfo);
  339. if (dw == 0 && lstrlen(szMIDIInfo))
  340. {
  341. pmmpsh->MIDICOPYRIGHTSTR = LocalAlloc(LPTR, lstrlen(szMIDIInfo) + 1);
  342. if (pmmpsh->MIDICOPYRIGHTSTR)
  343. {
  344. lstrcpy((LPTSTR)pmmpsh->MIDICOPYRIGHTSTR, szMIDIInfo);
  345. }
  346. }
  347. mciInfo.lpstrReturn = szMIDIInfo;
  348. mciInfo.dwRetSize = sizeof(szMIDIInfo);
  349. szMIDIInfo[0] = TEXT('\0');
  350. dw = mciSendCommand(wDevID, MCI_INFO, MCI_INFO_NAME, (DWORD_PTR)(LPVOID)&mciInfo);
  351. if (dw == 0 && lstrlen(szMIDIInfo))
  352. {
  353. pmmpsh->MIDISEQNAMESTR = LocalAlloc(LPTR, lstrlen(szMIDIInfo) + 1);
  354. if (pmmpsh->MIDISEQNAMESTR)
  355. {
  356. lstrcpy((LPTSTR)pmmpsh->MIDISEQNAMESTR, szMIDIInfo);
  357. }
  358. }
  359. mciSendCommand(wDevID, MCI_CLOSE, 0L, (DWORD)0);
  360. }
  361. STATIC void GetMIDIInfo(LPTSTR pszFile, PMMPSH pmmpsh)
  362. {
  363. GetMCIInfo(pszFile, pmmpsh);
  364. }
  365. STATIC void ReadAviStreams(LPTSTR pszFile, PMMPSH pmmpsh)
  366. {
  367. HRESULT hr;
  368. PAVIFILE pfile;
  369. int i;
  370. PAVISTREAM pavi;
  371. PAVISTREAM apavi[MAXNUMSTREAMS]; // the current streams
  372. AVISTREAMINFO avis;
  373. LONG timeStart; // cached start, end, length
  374. LONG timeEnd;
  375. int cpavi;
  376. TCHAR szDecSep[10];
  377. TCHAR szListSep[10];
  378. hr = (HRESULT)AVIFileOpen(&pfile, pszFile, 0, 0L);
  379. if (FAILED(hr))
  380. {
  381. DPF("Unable to open %s", pszFile);
  382. return;
  383. }
  384. for (i = 0; i <= MAXNUMSTREAMS; i++)
  385. {
  386. if (AVIFileGetStream(pfile, &pavi, 0L, i) != AVIERR_OK)
  387. break;
  388. if (i == MAXNUMSTREAMS)
  389. {
  390. AVIStreamRelease(pavi);
  391. DPF("Exceeded maximum number of streams");
  392. break;
  393. }
  394. apavi[i] = pavi;
  395. }
  396. //
  397. // Couldn't get any streams out of this file
  398. //
  399. if (i == 0)
  400. {
  401. DPF("Unable to open any streams in %s", pszFile);
  402. if (pfile)
  403. AVIFileRelease(pfile);
  404. return;
  405. }
  406. cpavi = i;
  407. //
  408. // Start with bogus times
  409. //
  410. timeStart = 0x7FFFFFFF;
  411. timeEnd = 0;
  412. //bug 141733, get the local decimal and list separators
  413. GetLocaleInfo( GetUserDefaultLCID(), LOCALE_SDECIMAL, szDecSep, sizeof(szDecSep)/sizeof(TCHAR) );
  414. GetLocaleInfo( GetUserDefaultLCID(), LOCALE_SLIST, szListSep, sizeof(szListSep)/sizeof(TCHAR) );
  415. //
  416. // Walk through and init all streams loaded
  417. //
  418. for (i = 0; i < cpavi; i++)
  419. {
  420. AVIStreamInfo(apavi[i], &avis, sizeof(avis));
  421. switch(avis.fccType)
  422. {
  423. case streamtypeVIDEO:
  424. {
  425. LONG cbFormat;
  426. LPVOID lpFormat;
  427. ICINFO icInfo;
  428. HIC hic;
  429. DWORD dwTimeLen;
  430. DWORD dwSize;
  431. int iFrameRate;
  432. TCHAR szFormat[MAXSTR];
  433. if (pmmpsh->pVideoFormatInfo)
  434. break;
  435. AVIStreamFormatSize(apavi[i], 0, &cbFormat);
  436. pmmpsh->pVideoFormatInfo = (PVOID)LocalAlloc(LPTR, MAX_PATH);
  437. if (!pmmpsh->pVideoFormatInfo)
  438. break;
  439. dwSize = mmpshGetFileSize(pszFile);
  440. dwTimeLen = (DWORD)(AVIStreamEndTime(apavi[i]) - AVIStreamStartTime(apavi[i]));
  441. iFrameRate = MulDiv(avis.dwLength, 1000000, dwTimeLen);
  442. lpFormat = (LPVOID)LocalAlloc(LPTR, cbFormat);
  443. if (!lpFormat)
  444. {
  445. goto BadFormat;
  446. }
  447. AVIStreamReadFormat(apavi[i], 0, lpFormat, &cbFormat);
  448. hic = (HIC)ICLocate(FOURCC_VIDC, avis.fccHandler, lpFormat, NULL, (WORD)ICMODE_DECOMPRESS);
  449. if (hic || ((LPBITMAPINFOHEADER)lpFormat)->biCompression == 0)
  450. {
  451. TCHAR szName[48];
  452. if (((LPBITMAPINFOHEADER)lpFormat)->biCompression)
  453. {
  454. ICGetInfo(hic, &icInfo, sizeof(ICINFO));
  455. ICClose(hic);
  456. //WideCharToMultiByte(CP_ACP, 0, icInfo.szName, -1, szName, sizeof(szName), NULL, NULL);
  457. wcscpy(szName,icInfo.szName);
  458. }
  459. else
  460. {
  461. LoadString(ghInstance, IDS_UNCOMPRESSED, szName, sizeof(szName)/sizeof(TCHAR));
  462. }
  463. LoadString(ghInstance, IDS_GOODFORMAT, szFormat, sizeof(szFormat)/sizeof(TCHAR));
  464. wsprintf((LPTSTR)pmmpsh->pVideoFormatInfo, szFormat, (avis.rcFrame.right - avis.rcFrame.left),
  465. (avis.rcFrame.bottom - avis.rcFrame.top), szListSep, ((LPBITMAPINFOHEADER)lpFormat)->biBitCount, szListSep,
  466. avis.dwLength, szListSep, (UINT)(iFrameRate/1000), szDecSep, (UINT)(iFrameRate%1000), szListSep, MulDiv(dwSize, 1000,dwTimeLen)/1024, szListSep, szName);
  467. goto GoodFormat;
  468. }
  469. BadFormat:
  470. LoadString(ghInstance, IDS_BADFORMAT, szFormat, sizeof(szFormat)/sizeof(TCHAR));
  471. wsprintf((LPTSTR)pmmpsh->pVideoFormatInfo, szFormat, (avis.rcFrame.right - avis.rcFrame.left),
  472. (avis.rcFrame.bottom - avis.rcFrame.top), szListSep,
  473. avis.dwLength, szListSep, (UINT)(iFrameRate/1000), szDecSep, (UINT)(iFrameRate%1000), szListSep, MulDiv(dwSize, 1000,dwTimeLen)/1024, szListSep);
  474. GoodFormat:
  475. LocalFree((HLOCAL)lpFormat);
  476. break;
  477. }
  478. case streamtypeAUDIO:
  479. {
  480. LONG cbFormat;
  481. AVIStreamFormatSize(apavi[i], 0, &cbFormat);
  482. pmmpsh->pAudioFormatInfo = (LPVOID)LocalAlloc(LPTR, cbFormat);
  483. if (!pmmpsh->pAudioFormatInfo)
  484. break;
  485. AVIStreamReadFormat(apavi[i], 0, pmmpsh->pAudioFormatInfo, &cbFormat);
  486. break;
  487. }
  488. default:
  489. break;
  490. }
  491. //
  492. // We're finding the earliest and latest start and end points for
  493. // our scrollbar.
  494. //
  495. timeStart = (LONG)min(timeStart, AVIStreamStartTime(apavi[i]));
  496. timeEnd = (LONG)max(timeEnd, AVIStreamEndTime(apavi[i]));
  497. }
  498. pmmpsh->uLen = (UINT)(timeEnd - timeStart);
  499. DPF("The file length is %d \r\n", pmmpsh->uLen);
  500. for (i = 0; i < cpavi; i++)
  501. {
  502. AVIStreamRelease(apavi[i]);
  503. }
  504. AVIFileRelease(pfile);
  505. }
  506. STATIC void GetAVIInfo(LPTSTR pszFile, PMMPSH pmmpsh)
  507. {
  508. if (!LoadAVI())
  509. {
  510. DPF("****Load AVI failed**\r\n");
  511. ASSERT(FALSE);
  512. return;
  513. }
  514. if (!LoadVFW())
  515. {
  516. DPF("****Load VFW failed**\r\n");
  517. ASSERT(FALSE);
  518. FreeAVI();
  519. return;
  520. }
  521. AVIFileInit();
  522. ReadAviStreams(pszFile, pmmpsh);
  523. AVIFileExit();
  524. if (!FreeVFW())
  525. {
  526. DPF("****Free VFW failed**\r\n");
  527. ASSERT(FALSE);
  528. }
  529. if (!FreeAVI())
  530. {
  531. DPF("****Free AVI failed**\r\n");
  532. ASSERT(FALSE);
  533. }
  534. }
  535. STATIC void GetASFInfo(LPTSTR pszFile, PMMPSH pmmpsh)
  536. {
  537. }
  538. STATIC void GetMediaInfo(HMMIO hmmio, PMMPSH pmmpsh)
  539. {
  540. switch (pmmpsh->iMediaType)
  541. {
  542. case MT_WAVE:
  543. GetWaveInfo(hmmio, pmmpsh);
  544. break;
  545. case MT_MIDI:
  546. GetMIDIInfo(pmmpsh->pszFileObj, pmmpsh);
  547. break;
  548. case MT_AVI:
  549. GetAVIInfo(pmmpsh->pszFileObj, pmmpsh);
  550. break;
  551. case MT_ASF:
  552. GetASFInfo(pmmpsh->pszFileObj, pmmpsh);
  553. break;
  554. }
  555. }
  556. STATIC HANDLE PASCAL GetRiffAll(PMMPSH pmmpsh)
  557. {
  558. MMCKINFO ck;
  559. MMCKINFO ckINFO;
  560. MMCKINFO ckRIFF;
  561. HANDLE h = NULL;
  562. LONG lSize;
  563. DWORD dw;
  564. HMMIO hmmio;
  565. BOOL fDoneDISP;
  566. BOOL fDoneINFO;
  567. BOOL fDoneName;
  568. LPSTR pInfo;
  569. hmmio = mmioOpen(pmmpsh->pszFileObj, NULL, MMIO_ALLOCBUF | MMIO_READ);
  570. if (!hmmio)
  571. goto error;
  572. GetMediaInfo(hmmio, pmmpsh);
  573. if (pmmpsh->uLen == 0)
  574. goto error;
  575. mmioSeek(hmmio, 0, SEEK_SET);
  576. /* descend the input file into the RIFF chunk */
  577. if (mmioDescend(hmmio, &ckRIFF, NULL, 0) != 0)
  578. goto error;
  579. if (ckRIFF.ckid != FOURCC_RIFF)
  580. goto error;
  581. fDoneDISP = fDoneINFO = fDoneName = FALSE;
  582. while (!(fDoneDISP && fDoneINFO) && !mmioDescend(hmmio, &ck, &ckRIFF, 0))
  583. {
  584. if (ck.ckid == FOURCC_DISP)
  585. {
  586. /* Read dword into dw, break if read unsuccessful */
  587. if (mmioRead(hmmio, (LPVOID)&dw, sizeof(dw)) != (LONG)sizeof(dw))
  588. goto error;
  589. /* Find out how much memory to allocate */
  590. lSize = ck.cksize - sizeof(dw);
  591. if ((int)dw == CF_DIB && h == NULL)
  592. {
  593. /* get a handle to memory to hold the description and
  594. lock it down */
  595. if ((h = GlobalAlloc(GHND, lSize+4)) == NULL)
  596. goto error;
  597. if (mmioRead(hmmio, GlobalLock(h), lSize) != lSize)
  598. goto error;
  599. fDoneDISP = TRUE;
  600. }
  601. else if ((int)dw == CF_TEXT)
  602. {
  603. pInfo = (LPSTR)LocalAlloc(LPTR, lSize+1);//+1 not required I think
  604. if (!pInfo)
  605. goto error;
  606. if (!mmioRead(hmmio, pInfo, lSize))
  607. goto error;
  608. AddInfoToList(pmmpsh, pInfo, ck.ckid );
  609. fDoneName = TRUE;
  610. }
  611. }
  612. else if (ck.ckid == FOURCC_LIST &&
  613. ck.fccType == FOURCC_INFO &&
  614. !fDoneINFO)
  615. {
  616. while (!mmioDescend(hmmio, &ckINFO, &ck, 0))
  617. {
  618. switch (ckINFO.ckid)
  619. {
  620. case FOURCC_ISBJ:
  621. case FOURCC_INAM:
  622. case FOURCC_ICOP:
  623. case FOURCC_ICRD:
  624. case FOURCC_IART:
  625. case FOURCC_ICMS:
  626. case FOURCC_ICMT:
  627. case FOURCC_ICRP:
  628. case FOURCC_IDIM:
  629. case FOURCC_IARL:
  630. case FOURCC_IDPI:
  631. case FOURCC_IENG:
  632. case FOURCC_IGNR:
  633. case FOURCC_IKEY:
  634. case FOURCC_ILGT:
  635. case FOURCC_IMED:
  636. case FOURCC_IPLT:
  637. case FOURCC_IPRD:
  638. case FOURCC_ISFT:
  639. case FOURCC_ISHP:
  640. case FOURCC_ISRC:
  641. case FOURCC_ISRF:
  642. case FOURCC_ITCH:
  643. pInfo = (LPSTR)LocalAlloc(LPTR, ck.cksize+1);//+1 not required I think
  644. if (!pInfo)
  645. goto error;
  646. if (!mmioRead(hmmio, pInfo, ck.cksize))
  647. goto error;
  648. AddInfoToList(pmmpsh, pInfo, ckINFO.ckid);
  649. if (ckINFO.ckid == FOURCC_INAM)
  650. fDoneName = TRUE;
  651. break;
  652. }
  653. if (mmioAscend(hmmio, &ckINFO, 0))
  654. break;
  655. }
  656. }
  657. /* Ascend so that we can descend into next chunk
  658. */
  659. if (mmioAscend(hmmio, &ck, 0))
  660. break;
  661. }
  662. goto exit;
  663. error:
  664. if (h)
  665. {
  666. GlobalUnlock(h);
  667. GlobalFree(h);
  668. }
  669. h = NULL;
  670. ReleaseInfoList(pmmpsh);
  671. exit:
  672. if (hmmio)
  673. mmioClose(hmmio,0);
  674. return h;
  675. }
  676. STATIC BOOL PASCAL WaveGetFormatDescription
  677. (
  678. LPWAVEFORMATEX pwfx,
  679. LPTSTR pszDesc
  680. )
  681. {
  682. UINT_PTR mmr;
  683. TCHAR pszFormatTag[ACMFORMATTAGDETAILS_FORMATTAG_CHARS];
  684. TCHAR pszFormat[ACMFORMATDETAILS_FORMAT_CHARS];
  685. BOOL bRet = FALSE;
  686. TCHAR szListSep[10];
  687. //
  688. // get the name for the format tag of the specified format
  689. //
  690. if (!pwfx)
  691. {
  692. pszDesc[0] = TEXT('\0');
  693. return TRUE;
  694. }
  695. if (!LoadACM())
  696. {
  697. DPF("****Load ACM failed**\r\n");
  698. ASSERT(FALSE);
  699. return FALSE;
  700. }
  701. if (NULL != pszFormatTag)
  702. {
  703. PACMFORMATTAGDETAILSW paftd;
  704. //
  705. // initialize all unused members of the ACMFORMATTAGDETAILS
  706. // structure to zero
  707. //
  708. paftd = (PACMFORMATTAGDETAILSW)LocalAlloc(LPTR, sizeof(ACMFORMATTAGDETAILSW));
  709. if (!paftd)
  710. goto RetErr;
  711. //
  712. // fill in the required members of the ACMFORMATTAGDETAILS
  713. // structure for the ACM_FORMATTAGDETAILSF_FORMATTAG query
  714. //
  715. paftd->cbStruct = sizeof(ACMFORMATTAGDETAILSW);
  716. paftd->dwFormatTag = pwfx->wFormatTag;
  717. //
  718. // ask the ACM to find the first available driver that
  719. // supports the specified format tag
  720. //
  721. mmr = acmFormatTagDetails(NULL,
  722. paftd,
  723. ACM_FORMATTAGDETAILSF_FORMATTAG);
  724. if (MMSYSERR_NOERROR == mmr)
  725. {
  726. //
  727. // copy the format tag name into the caller's buffer
  728. //
  729. lstrcpy(pszFormatTag, paftd->szFormatTag);
  730. }
  731. else
  732. {
  733. static const struct _wfm_names {
  734. UINT uFormatTag;
  735. UINT uIDS;
  736. } aWaveFmtNames[] = {
  737. WAVE_FORMAT_PCM, IDS_FORMAT_PCM,
  738. WAVE_FORMAT_ADPCM, IDS_FORMAT_ADPCM,
  739. WAVE_FORMAT_IBM_CVSD, IDS_FORMAT_IBM_CVSD,
  740. WAVE_FORMAT_ALAW, IDS_FORMAT_ALAW,
  741. WAVE_FORMAT_MULAW, IDS_FORMAT_MULAW,
  742. WAVE_FORMAT_OKI_ADPCM, IDS_FORMAT_OKI_ADPCM,
  743. WAVE_FORMAT_IMA_ADPCM, IDS_FORMAT_IMA_ADPCM,
  744. WAVE_FORMAT_MEDIASPACE_ADPCM, IDS_FORMAT_MEDIASPACE_ADPCM,
  745. WAVE_FORMAT_SIERRA_ADPCM, IDS_FORMAT_SIERRA_ADPCM,
  746. WAVE_FORMAT_G723_ADPCM, IDS_FORMAT_G723_ADPCM,
  747. WAVE_FORMAT_DIGISTD, IDS_FORMAT_DIGISTD,
  748. WAVE_FORMAT_DIGIFIX, IDS_FORMAT_DIGIFIX,
  749. WAVE_FORMAT_YAMAHA_ADPCM, IDS_FORMAT_YAMAHA_ADPCM,
  750. WAVE_FORMAT_SONARC, IDS_FORMAT_SONARC,
  751. WAVE_FORMAT_DSPGROUP_TRUESPEECH, IDS_FORMAT_DSPGROUP_TRUESPEECH,
  752. WAVE_FORMAT_ECHOSC1, IDS_FORMAT_ECHOSC1,
  753. WAVE_FORMAT_AUDIOFILE_AF36, IDS_FORMAT_AUDIOFILE_AF36,
  754. WAVE_FORMAT_APTX, IDS_FORMAT_APTX,
  755. WAVE_FORMAT_AUDIOFILE_AF10, IDS_FORMAT_AUDIOFILE_AF10,
  756. WAVE_FORMAT_DOLBY_AC2, IDS_FORMAT_DOLBY_AC2,
  757. WAVE_FORMAT_GSM610, IDS_FORMAT_GSM610,
  758. WAVE_FORMAT_G721_ADPCM, IDS_FORMAT_G721_ADPCM,
  759. WAVE_FORMAT_CREATIVE_ADPCM, IDS_FORMAT_CREATIVE_ADPCM,
  760. 0, IDS_UNKFORMAT,
  761. };
  762. UINT ii;
  763. //
  764. // no ACM driver is available that supports the
  765. // specified format tag. look up the tag id
  766. // in our table of tag names (above)
  767. //
  768. for (ii = 0; aWaveFmtNames[ii].uFormatTag; ii++)
  769. if (pwfx->wFormatTag == aWaveFmtNames[ii].uFormatTag)
  770. break;
  771. LoadString(ghInstance, aWaveFmtNames[ii].uIDS, pszFormatTag, ACMFORMATTAGDETAILS_FORMATTAG_CHARS);
  772. }
  773. LocalFree((HLOCAL)paftd);
  774. }
  775. //
  776. // get the description of the attributes for the specified
  777. // format
  778. //
  779. if (NULL != pszFormat)
  780. {
  781. PACMFORMATDETAILSW pafd;
  782. //
  783. // initialize all unused members of the ACMFORMATDETAILS
  784. // structure to zero
  785. //
  786. pafd = (PACMFORMATDETAILSW)LocalAlloc(LPTR, sizeof(ACMFORMATDETAILSW));
  787. if (!pafd)
  788. goto RetErr;
  789. //
  790. // fill in the required members of the ACMFORMATDETAILS
  791. // structure for the ACM_FORMATDETAILSF_FORMAT query
  792. //
  793. pafd->cbStruct = sizeof(ACMFORMATDETAILSW);
  794. pafd->dwFormatTag = pwfx->wFormatTag;
  795. pafd->pwfx = pwfx;
  796. //
  797. // the cbwfx member must be initialized to the total size
  798. // in bytes needed for the specified format. for a PCM
  799. // format, the cbSize member of the WAVEFORMATEX structure
  800. // is not valid.
  801. //
  802. if (WAVE_FORMAT_PCM == pwfx->wFormatTag)
  803. {
  804. pafd->cbwfx = sizeof(PCMWAVEFORMAT);
  805. }
  806. else
  807. {
  808. pafd->cbwfx = sizeof(WAVEFORMATEX) + pwfx->cbSize;
  809. }
  810. //
  811. // ask the ACM to find the first available driver that
  812. // supports the specified format
  813. //
  814. mmr = acmFormatDetails(NULL, pafd, ACM_FORMATDETAILSF_FORMAT);
  815. if (MMSYSERR_NOERROR == mmr)
  816. {
  817. //
  818. // copy the format attributes description into the caller's
  819. // buffer
  820. //
  821. lstrcpy(pszFormat, pafd->szFormat);
  822. }
  823. else
  824. {
  825. pszFormat[0] = TEXT('\0');
  826. }
  827. LocalFree((HLOCAL)pafd);
  828. }
  829. //bug 141733, get the local decimal and list separators
  830. GetLocaleInfo( GetUserDefaultLCID(), LOCALE_SLIST, szListSep, sizeof(szListSep)/sizeof(TCHAR) );
  831. wsprintf(pszDesc, TEXT("%s%s %s"), pszFormatTag, szListSep, pszFormat);
  832. bRet = TRUE;
  833. RetErr:
  834. if (!FreeACM())
  835. {
  836. DPF("****Free ACM failed**\r\n");
  837. ASSERT(FALSE);
  838. }
  839. return bRet;
  840. } // AcmAppGetFormatDescription()
  841. STATIC void ShowInfoList(PMMPSH pmmpsh, HWND hDlg)
  842. {
  843. PMMINFOLIST pCur;
  844. TCHAR* szTemp;
  845. HWND hwndLB = GetDlgItem(hDlg, IDD_INFO_NAME);
  846. TCHAR szNoCopyRight[MAXSTR];
  847. int iIndex;
  848. LoadString(ghInstance, IDS_NOCOPYRIGHT, szNoCopyRight, sizeof(szNoCopyRight)/sizeof(TCHAR));
  849. SetDlgItemText(hDlg, IDD_COPYRIGHT, szNoCopyRight);
  850. if (!pmmpsh->pInfoList)
  851. {
  852. DestroyWindow(GetDlgItem(hDlg, IDC_DETAILSINFO_GRP));
  853. DestroyWindow(GetDlgItem(hDlg, IDC_ITEMSLABEL));
  854. DestroyWindow(GetDlgItem(hDlg, IDC_DESCLABEL));
  855. DestroyWindow(GetDlgItem(hDlg, IDD_INFO_NAME));
  856. DestroyWindow(GetDlgItem(hDlg, IDD_INFO_VALUE));
  857. return;
  858. }
  859. for (pCur = pmmpsh->pInfoList; pCur; pCur = pCur->pNext)
  860. {
  861. int nTempSize = (strlen(pCur->pszInfo)*sizeof(TCHAR))+sizeof(TCHAR);
  862. szTemp = (LPTSTR)LocalAlloc(LPTR, nTempSize);
  863. if (!szTemp) return;
  864. MultiByteToWideChar(GetACP(), 0,
  865. pCur->pszInfo, -1,
  866. szTemp, nTempSize);
  867. if (pCur->ckid == FOURCC_ICOP)
  868. {
  869. SetDlgItemText(hDlg, IDD_COPYRIGHT, szTemp);
  870. LocalFree(szTemp);
  871. continue;
  872. }
  873. iIndex = ListBox_AddString(hwndLB, pCur->szInfoDesc);
  874. if (iIndex != LB_ERR)
  875. {
  876. //reassigning wide pointer back into "info" so it will get cleaned up later
  877. pCur->pszInfo = (LPSTR)szTemp;
  878. ListBox_SetItemData(hwndLB, iIndex, (LPARAM)pCur->pszInfo);
  879. }
  880. }
  881. SetFocus(hwndLB);
  882. if (ListBox_SetCurSel(hwndLB, 0) != LB_ERR)
  883. FORWARD_WM_COMMAND(hDlg, IDD_INFO_NAME, hwndLB, LBN_SELCHANGE, PostMessage);
  884. }
  885. BOOL PASCAL DoDetailsCommand(HWND hDlg, int id, HWND hwndCtl, UINT codeNotify)
  886. {
  887. switch (id)
  888. {
  889. case ID_APPLY:
  890. return TRUE;
  891. case IDOK:
  892. break;
  893. case IDCANCEL:
  894. break;
  895. case ID_INIT:
  896. {
  897. PMMPSH pmmpsh = (PMMPSH)GetWindowLongPtr(hDlg, DWLP_USER);
  898. if (pmmpsh->hDispBMP)
  899. {
  900. HWND hwndDisp = GetDlgItem(hDlg,IDD_DISPFRAME);
  901. HDC hdc;
  902. HPALETTE hpalT;
  903. int i;
  904. SendMessage(hwndDisp, (UINT)DF_PM_SETBITMAP, (WPARAM)pmmpsh->hDispBMP,
  905. (LPARAM)pmmpsh->hPal);
  906. /*
  907. * If realizing the palette causes the palette to change,
  908. * redraw completely.
  909. */
  910. hdc = GetDC(hwndDisp);
  911. hpalT = SelectPalette (hdc, pmmpsh->hPal, FALSE);
  912. i = RealizePalette(hdc); /* i == entries that changed */
  913. SelectPalette (hdc, hpalT, FALSE);
  914. ReleaseDC(hwndDisp, hdc);
  915. /* If any palette entries changed, repaint the window. */
  916. if (i > 0)
  917. {
  918. InvalidateRect(hwndDisp, NULL, TRUE);
  919. }
  920. }
  921. break;
  922. }
  923. case IDD_INFO_NAME:
  924. if (codeNotify == LBN_SELCHANGE)
  925. {
  926. int iIndex = ListBox_GetCurSel(hwndCtl);
  927. LPTSTR pszInfo = (LPTSTR)ListBox_GetItemData(hwndCtl, iIndex);
  928. SetDlgItemText(hDlg, IDD_INFO_VALUE, pszInfo);
  929. }
  930. break;
  931. }
  932. return FALSE;
  933. }
  934. STATIC void ShowMediaLen(PMMPSH pmmpsh, HWND hwnd)
  935. {
  936. TCHAR szBuf[MAXSTR];
  937. TCHAR szFmt[MAXSTR];
  938. UINT uMin;
  939. UINT uSec;
  940. UINT umSec;
  941. UINT uLen;
  942. TCHAR szDecSep[10];
  943. uLen = pmmpsh->uLen;
  944. if ((!uLen && pmmpsh->iMediaType != MT_WAVE) || (!pmmpsh->pAudioFormatInfo && pmmpsh->iMediaType != MT_MIDI && pmmpsh->iMediaType != MT_AVI && pmmpsh->iMediaType != MT_ASF))
  945. {
  946. LoadString(ghInstance, IDS_BADFILE, szBuf, sizeof(szBuf)/sizeof(TCHAR));
  947. SetWindowText(hwnd, szBuf);
  948. return;
  949. }
  950. uMin = (UINT)(uLen/60000);
  951. uSec = (UINT)((uLen/1000) % 60);
  952. umSec = (UINT)(uLen % 1000);
  953. //bug 141733, get the local decimal separator
  954. GetLocaleInfo( GetUserDefaultLCID(), LOCALE_SDECIMAL, szDecSep, sizeof(szDecSep)/sizeof(TCHAR) );
  955. if (uMin)
  956. {
  957. LoadString(ghInstance, IDS_MINFMT, szFmt, sizeof(szFmt)/sizeof(TCHAR));
  958. wsprintf(szBuf, szFmt, uMin, uSec, szDecSep, umSec);
  959. }
  960. else
  961. {
  962. LoadString(ghInstance, IDS_SECFMT, szFmt, sizeof(szFmt)/sizeof(TCHAR));
  963. wsprintf(szBuf, szFmt, uSec, szDecSep, umSec);
  964. }
  965. SetWindowText(hwnd, szBuf);
  966. }
  967. STATIC void ShowMediaFormat(PMMPSH pmmpsh, HWND hDlg)
  968. {
  969. switch (pmmpsh->iMediaType)
  970. {
  971. case MT_WAVE:
  972. {
  973. TCHAR szDesc[MAX_PATH];
  974. szDesc[0] = TEXT('\0');
  975. WaveGetFormatDescription((LPWAVEFORMATEX)pmmpsh->pAudioFormatInfo, szDesc);
  976. SetDlgItemText(hDlg, IDD_AUDIOFORMAT, szDesc);
  977. DestroyWindow(GetDlgItem(hDlg, IDD_VIDEOFORMAT));
  978. DestroyWindow(GetDlgItem(hDlg, IDD_VIDEOFORMATLABEL));
  979. DestroyWindow(GetDlgItem(hDlg, IDD_MIDISEQUENCELABEL));
  980. DestroyWindow(GetDlgItem(hDlg, IDD_MIDISEQUENCENAME));
  981. break;
  982. }
  983. case MT_MIDI:
  984. DestroyWindow(GetDlgItem(hDlg, IDD_AUDIOFORMAT));
  985. DestroyWindow(GetDlgItem(hDlg, IDD_AUDIOFORMATLABEL));
  986. DestroyWindow(GetDlgItem(hDlg, IDD_VIDEOFORMAT));
  987. DestroyWindow(GetDlgItem(hDlg, IDD_VIDEOFORMATLABEL));
  988. if (pmmpsh->MIDICOPYRIGHTSTR)
  989. SetDlgItemText(hDlg, IDD_COPYRIGHT, (LPTSTR)pmmpsh->MIDICOPYRIGHTSTR);
  990. if (pmmpsh->MIDISEQNAMESTR)
  991. SetDlgItemText(hDlg, IDD_MIDISEQUENCENAME, (LPTSTR)pmmpsh->MIDISEQNAMESTR);
  992. else
  993. {
  994. DestroyWindow(GetDlgItem(hDlg, IDD_MIDISEQUENCELABEL));
  995. DestroyWindow(GetDlgItem(hDlg, IDD_MIDISEQUENCENAME));
  996. }
  997. break;
  998. case MT_AVI:
  999. {
  1000. TCHAR szDesc[MAX_PATH];
  1001. DestroyWindow(GetDlgItem(hDlg, IDD_MIDISEQUENCELABEL));
  1002. DestroyWindow(GetDlgItem(hDlg, IDD_MIDISEQUENCENAME));
  1003. szDesc[0] = TEXT('\0');
  1004. if (pmmpsh->pVideoFormatInfo)
  1005. SetDlgItemText(hDlg, IDD_VIDEOFORMAT, (LPTSTR)pmmpsh->pVideoFormatInfo);
  1006. else
  1007. SetDlgItemText(hDlg, IDD_VIDEOFORMAT, (LPTSTR)szDesc);
  1008. WaveGetFormatDescription((LPWAVEFORMATEX)pmmpsh->pAudioFormatInfo, szDesc);
  1009. SetDlgItemText(hDlg, IDD_AUDIOFORMAT, szDesc);
  1010. break;
  1011. }
  1012. case MT_ASF:
  1013. {
  1014. break;
  1015. }
  1016. }
  1017. }
  1018. const static DWORD aFileDetailsIds[] = { // Context Help IDs
  1019. IDD_DISPFRAME, NO_HELP,
  1020. IDD_DISP_ICON, IDH_FPROP_GEN_ICON,
  1021. IDD_FILENAME, IDH_FPROP_GEN_NAME,
  1022. IDD_CRLABEL, IDH_FCAB_MM_COPYRIGHT,
  1023. IDD_COPYRIGHT, IDH_FCAB_MM_COPYRIGHT,
  1024. IDD_LENLABEL, IDH_FCAB_MM_FILELEN,
  1025. IDD_FILELEN, IDH_FCAB_MM_FILELEN,
  1026. IDD_AUDIOFORMATLABEL, IDH_FCAB_MM_AUDIOFORMAT,
  1027. IDD_AUDIOFORMAT, IDH_FCAB_MM_AUDIOFORMAT,
  1028. IDD_MIDISEQUENCELABEL, IDH_FCAB_MM_MIDISEQUENCENAME,
  1029. IDD_MIDISEQUENCENAME, IDH_FCAB_MM_MIDISEQUENCENAME,
  1030. IDD_VIDEOFORMATLABEL, IDH_FCAB_MM_VIDEOFORMAT,
  1031. IDD_VIDEOFORMAT, IDH_FCAB_MM_VIDEOFORMAT,
  1032. IDC_DETAILSINFO_GRP, IDH_FCAB_MM_DETAILSINFO,
  1033. IDC_ITEMSLABEL, IDH_FCAB_MM_DETAILSINFO,
  1034. IDC_DESCLABEL, IDH_FCAB_MM_DETAILSINFO,
  1035. IDD_INFO_NAME, IDH_FCAB_MM_DETAILSINFO,
  1036. IDD_INFO_VALUE, IDH_FCAB_MM_DETAILSINFO,
  1037. 0, 0
  1038. };
  1039. INT_PTR CALLBACK FileDetailsDlg(HWND hDlg, UINT uMsg, WPARAM wParam,
  1040. LPARAM lParam)
  1041. {
  1042. NMHDR FAR *lpnm;
  1043. switch (uMsg)
  1044. {
  1045. case WM_NOTIFY:
  1046. lpnm = (NMHDR FAR *)lParam;
  1047. switch(lpnm->code)
  1048. {
  1049. case PSN_KILLACTIVE:
  1050. FORWARD_WM_COMMAND(hDlg, IDOK, 0, 0, SendMessage);
  1051. break;
  1052. case PSN_APPLY:
  1053. FORWARD_WM_COMMAND(hDlg, ID_APPLY, 0, 0, SendMessage);
  1054. break;
  1055. case PSN_SETACTIVE:
  1056. FORWARD_WM_COMMAND(hDlg, ID_INIT, 0, 0, SendMessage);
  1057. break;
  1058. case PSN_RESET:
  1059. FORWARD_WM_COMMAND(hDlg, IDCANCEL, 0, 0, SendMessage);
  1060. break;
  1061. }
  1062. break;
  1063. case WM_INITDIALOG:
  1064. {
  1065. PMMPSH pmmpsh = (PMMPSH)(((LPPROPSHEETPAGE)lParam)->lParam);
  1066. TCHAR szFile[MAX_PATH];
  1067. HANDLE hDib = NULL;
  1068. HCURSOR hCursor;
  1069. hCursor = SetCursor(LoadCursor(NULL,IDC_WAIT));
  1070. SetWindowLongPtr(hDlg, DWLP_USER, (LPARAM)pmmpsh);
  1071. if (!pmmpsh->pInfoList)
  1072. {
  1073. hDib = GetRiffAll(pmmpsh);
  1074. }
  1075. if (!hDib)
  1076. break;
  1077. pmmpsh->hPal = bmfCreateDIBPalette(hDib);
  1078. pmmpsh->hDispBMP = bmfBitmapFromDIB(hDib, pmmpsh->hPal);
  1079. if (hDib)
  1080. {
  1081. GlobalUnlock(hDib);
  1082. hDib = GlobalFree(hDib);
  1083. }
  1084. if (!pmmpsh->hDispBMP)
  1085. {
  1086. int iIconID;
  1087. switch (pmmpsh->iMediaType)
  1088. {
  1089. case MT_WAVE:
  1090. iIconID = IDI_DWAVE;
  1091. break;
  1092. case MT_MIDI:
  1093. iIconID = IDI_DMIDI;
  1094. break;
  1095. case MT_AVI:
  1096. case MT_ASF:
  1097. iIconID = IDI_DVIDEO;
  1098. break;
  1099. }
  1100. DestroyWindow(GetDlgItem(hDlg,IDD_DISPFRAME));
  1101. pmmpsh->hIcon = LoadIcon(ghInstance, MAKEINTRESOURCE(iIconID));
  1102. Static_SetIcon(GetDlgItem(hDlg, IDD_DISP_ICON), pmmpsh->hIcon);
  1103. }
  1104. else
  1105. {
  1106. DestroyWindow(GetDlgItem(hDlg,IDD_DISP_ICON));
  1107. //SendDlgItemMessage(hDlg, (int)IDD_DISPFRAME, (UINT)DF_PM_SETBITMAP, (WPARAM)pmmpsh->hDispBMP,
  1108. // (LPARAM)pmmpsh->hPal);
  1109. }
  1110. lstrcpy(szFile, pmmpsh->pszFileObj);
  1111. NiceName(szFile, TRUE);
  1112. SetDlgItemText(hDlg, IDD_FILENAME, szFile);
  1113. ShowMediaLen(pmmpsh, GetDlgItem(hDlg, IDD_FILELEN));
  1114. ShowInfoList(pmmpsh, hDlg);
  1115. ShowMediaFormat(pmmpsh, hDlg);
  1116. SetCursor(hCursor);
  1117. break;
  1118. }
  1119. case WM_DESTROY:
  1120. {
  1121. PMMPSH pmmpsh = (PMMPSH)GetWindowLongPtr(hDlg, DWLP_USER);
  1122. if (pmmpsh->hDispBMP)
  1123. DeleteObject(pmmpsh->hDispBMP);
  1124. if (pmmpsh->hIcon)
  1125. DestroyIcon(pmmpsh->hIcon);
  1126. if (pmmpsh->hPal)
  1127. DeleteObject(pmmpsh->hPal);
  1128. if (pmmpsh->pAudioFormatInfo)
  1129. LocalFree((HLOCAL)pmmpsh->pAudioFormatInfo);
  1130. if (pmmpsh->pVideoFormatInfo)
  1131. LocalFree((HLOCAL)pmmpsh->pVideoFormatInfo);
  1132. break;
  1133. }
  1134. case WM_CONTEXTMENU:
  1135. WinHelp((HWND)wParam, gszWindowsHlp, HELP_CONTEXTMENU,
  1136. (UINT_PTR)(LPTSTR)aFileDetailsIds);
  1137. return TRUE;
  1138. case WM_HELP:
  1139. WinHelp(((LPHELPINFO)lParam)->hItemHandle, gszWindowsHlp, HELP_WM_HELP
  1140. , (UINT_PTR)(LPTSTR)aFileDetailsIds);
  1141. return TRUE;
  1142. case WM_COMMAND:
  1143. HANDLE_WM_COMMAND(hDlg, wParam, lParam, DoDetailsCommand);
  1144. break;
  1145. }
  1146. return FALSE;
  1147. }
  1148. static DWORD aPreviewIds[] = { // Context Help IDs
  1149. 0, IDH_FCAB_MM_PREVIEW_CONTROL,
  1150. IDD_DISP_ICON, IDH_FPROP_GEN_ICON,
  1151. IDD_FILENAME, IDH_FPROP_GEN_NAME,
  1152. 0, 0
  1153. };
  1154. INT_PTR CALLBACK PreviewDlg(HWND hDlg, UINT uMsg, WPARAM wParam,
  1155. LPARAM lParam)
  1156. {
  1157. static BOOL fLoadedVFW;
  1158. static HICON hIcon;
  1159. switch (uMsg)
  1160. {
  1161. case WM_NOTIFY:
  1162. {
  1163. NMHDR FAR *lpnm;
  1164. lpnm = (NMHDR FAR *)lParam;
  1165. switch(lpnm->code)
  1166. {
  1167. case PSN_KILLACTIVE:
  1168. {
  1169. HWND hwndMCI = (HWND)GetWindowLongPtr(hDlg, DWLP_USER);
  1170. DPF("***PSN_KILLACTIVE***\r\n");
  1171. if (IsWindow(hwndMCI))
  1172. MCIWndStop(hwndMCI);
  1173. break;
  1174. }
  1175. case PSN_APPLY:
  1176. DPF("***PSN_APPLY***\r\n");
  1177. return TRUE;
  1178. }
  1179. break;
  1180. }
  1181. case WM_INITDIALOG:
  1182. {
  1183. PMMPSH pmmpsh = (PMMPSH)(((LPPROPSHEETPAGE)lParam)->lParam);
  1184. HCURSOR hCursor;
  1185. HWND hwndMCI;
  1186. HWND hwndTitle;
  1187. RECT rcWnd;
  1188. RECT rcDlg;
  1189. TCHAR szFile[MAX_PATH];
  1190. TCHAR szTitle[MAXSTR];
  1191. TCHAR szTmp[MAXSTR];
  1192. #ifndef DEBUG_BUILT_LINKED
  1193. FN_MCIWNDCREATE fnMCIWndCreate;
  1194. #endif
  1195. hCursor = SetCursor(LoadCursor(NULL,IDC_WAIT));
  1196. lstrcpy(szFile, pmmpsh->pszFileObj);
  1197. NiceName(szFile, TRUE);
  1198. LoadString(ghInstance, IDS_PREVIEWOF, szTmp, sizeof(szTmp)/sizeof(TCHAR));
  1199. wsprintf(szTitle, szTmp, szFile);
  1200. hwndTitle = GetDlgItem(hDlg, IDD_FILENAME);
  1201. SetWindowText(hwndTitle, szTitle);
  1202. fLoadedVFW = FALSE;
  1203. if (!LoadVFW())
  1204. {
  1205. DPF("****Load VFW failed**\r\n");
  1206. ASSERT(FALSE);
  1207. break;
  1208. }
  1209. fLoadedVFW = TRUE;
  1210. #ifndef DEBUG_BUILT_LINKED
  1211. fnMCIWndCreate = (FN_MCIWNDCREATE)MCIWndCreateW;
  1212. hwndMCI = fnMCIWndCreate(hDlg, ghInstance, (DWORD)MCIWNDF_NOMENU, (LPCTSTR)pmmpsh->pszFileObj);
  1213. #else
  1214. hwndMCI = MCIWndCreateW(hDlg, ghInstance, (DWORD)MCIWNDF_NOMENU, (LPCTSTR)pmmpsh->pszFileObj);
  1215. #endif
  1216. aPreviewIds[0] = GetDlgCtrlID(hwndMCI);
  1217. GetWindowRect(hwndMCI, &rcWnd);
  1218. MapWindowPoints(NULL, hDlg, (LPPOINT)&rcWnd, 2);
  1219. GetWindowRect(hDlg, &rcDlg);
  1220. MapWindowPoints(NULL, hDlg, (LPPOINT)&rcDlg, 2);
  1221. hIcon = NULL;
  1222. switch (pmmpsh->iMediaType)
  1223. {
  1224. case MT_WAVE:
  1225. case MT_MIDI:
  1226. {
  1227. int ircWndTop;
  1228. ircWndTop = (int)((rcDlg.bottom - rcDlg.top)/2) - 50;
  1229. rcWnd.top += ircWndTop;
  1230. rcWnd.bottom += ircWndTop;
  1231. rcWnd.left = 20;
  1232. rcWnd.right = rcDlg.right - 20;
  1233. MoveWindow(hwndMCI, rcWnd.left, rcWnd.top, (rcWnd.right - rcWnd.left),
  1234. (rcWnd.bottom - rcWnd.top), FALSE);
  1235. GetWindowRect(hwndTitle, &rcWnd);
  1236. MapWindowPoints(NULL, hDlg, (LPPOINT)&rcWnd, 2);
  1237. OffsetRect(&rcWnd, 52, 36);
  1238. MoveWindow(hwndTitle, rcWnd.left, rcWnd.top, (rcWnd.right - rcWnd.left),
  1239. (rcWnd.bottom - rcWnd.top), FALSE);
  1240. hIcon = LoadIcon(ghInstance, MAKEINTRESOURCE(IDI_DWAVE+pmmpsh->iMediaType-1));
  1241. Static_SetIcon(GetDlgItem(hDlg, IDD_DISP_ICON),hIcon);
  1242. break;
  1243. }
  1244. case MT_AVI:
  1245. {
  1246. int iDlgHt = rcDlg.bottom - rcDlg.top -15; //15 for the title
  1247. int iDlgWth = rcDlg.right - rcDlg.left;
  1248. int iWndHt = rcWnd.bottom - rcWnd.top;
  1249. int iWndWth = rcWnd.right - rcWnd.left;
  1250. DestroyWindow(GetDlgItem(hDlg, IDD_DISP_ICON));
  1251. if (iWndWth < iDlgWth && iWndHt < iDlgHt)
  1252. {
  1253. int ixOff = (int)((iDlgWth - iWndWth)/2);
  1254. int iyOff = (int)((iDlgHt - iWndHt)/2) + 15;
  1255. OffsetRect(&rcWnd, ixOff, iyOff);
  1256. MoveWindow(hwndMCI, rcWnd.left, rcWnd.top, (rcWnd.right - rcWnd.left),
  1257. (rcWnd.bottom - rcWnd.top), FALSE);
  1258. }
  1259. else
  1260. {
  1261. int ixExcess = iWndWth - iDlgWth;
  1262. int iyExcess = iWndHt - (iDlgHt - 15); //Take another 15 off
  1263. int ixOff;
  1264. int iyOff;
  1265. RECT rcSource;
  1266. RECT rcDest;
  1267. RECT rcDestWnd;
  1268. MCIWndGetDest(hwndMCI, &rcSource);
  1269. //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",
  1270. // rcSource.left,rcSource.top,rcSource.right,rcSource.bottom,
  1271. // rcWnd.left,rcWnd.top,rcWnd.right,rcWnd.bottom,
  1272. // rcDlg.left,rcDlg.top,rcDlg.right,rcDlg.bottom);
  1273. rcDest.top = rcSource.top; // new boundaries
  1274. rcDest.left = rcSource.left;
  1275. if (ixExcess > iyExcess)
  1276. {
  1277. rcDest.right = rcSource.left +
  1278. (((rcSource.right - rcSource.left)*(iDlgWth - 20))/iWndWth);
  1279. rcDest.bottom = rcSource.top +
  1280. (((rcSource.bottom - rcSource.top)*(iDlgWth - 20))/iWndWth);
  1281. //DPF("rcDest = %d,%d,%d,%d\r\n",rcDest.left,rcDest.top,rcDest.right,rcDest.bottom);
  1282. }
  1283. else
  1284. {
  1285. rcDest.right = rcSource.left +
  1286. (((rcSource.right - rcSource.left)*(iDlgHt - 20))/iWndHt);
  1287. rcDest.bottom = rcSource.top +
  1288. (((rcSource.bottom - rcSource.top)*(iDlgHt - 20))/iWndHt);
  1289. }
  1290. rcDestWnd.top = rcWnd.top;
  1291. rcDestWnd.left = rcWnd.left;
  1292. rcDestWnd.right = rcWnd.left + (rcDest.right - rcDest.left);
  1293. rcDestWnd.bottom = rcWnd.top + (rcDest.bottom - rcDest.top)
  1294. + (iWndHt - (rcSource.bottom - rcSource.top));
  1295. //DPF("rcDestWnd = %d,%d,%d,%d\r\n",rcDestWnd.left,rcDestWnd.top,rcDestWnd.right,rcDestWnd.bottom);
  1296. ixOff = (int)((iDlgWth - (rcDestWnd.right - rcDestWnd.left))/2);
  1297. iyOff = (int)((iDlgHt - (rcDestWnd.bottom - rcDestWnd.top))/2) + 15;
  1298. //DPF("ixOff = %, iyOff = %d\r\n", ixOff, iyOff);
  1299. OffsetRect(&rcDestWnd, ixOff, iyOff);
  1300. MCIWndPutDest(hwndMCI, &rcDest);
  1301. MoveWindow(hwndMCI, rcDestWnd.left, rcDestWnd.top, (rcDestWnd.right - rcDestWnd.left),
  1302. (rcDestWnd.bottom - rcDestWnd.top), FALSE);
  1303. }
  1304. break;
  1305. case MT_ASF:
  1306. break;
  1307. }
  1308. }
  1309. SetWindowLongPtr(hDlg, DWLP_USER, (LPARAM)hwndMCI);
  1310. SetCursor(hCursor);
  1311. break;
  1312. }
  1313. case WM_CLOSE:
  1314. DPF("***WM_CLOSE***\r\n");
  1315. break;
  1316. case WM_DESTROY:
  1317. {
  1318. HWND hwndMCI = (HWND)GetWindowLongPtr(hDlg, DWLP_USER);
  1319. DPF("***WM_DESTROY***\r\n");
  1320. if (hIcon)
  1321. {
  1322. DestroyIcon(hIcon);
  1323. hIcon = NULL;
  1324. }
  1325. if (IsWindow(hwndMCI))
  1326. MCIWndDestroy(hwndMCI);
  1327. SetWindowLongPtr(hDlg, DWLP_USER, (LPARAM)NULL);
  1328. if (!fLoadedVFW)
  1329. break;
  1330. if (!FreeVFW())
  1331. {
  1332. DPF("****Free VFW failed**\r\n");
  1333. ASSERT(FALSE);
  1334. }
  1335. fLoadedVFW = FALSE;
  1336. break;
  1337. }
  1338. case WM_CONTEXTMENU:
  1339. WinHelp((HWND)wParam, gszWindowsHlp, HELP_CONTEXTMENU,
  1340. (UINT_PTR)(LPTSTR)aPreviewIds);
  1341. return TRUE;
  1342. case WM_HELP:
  1343. WinHelp(((LPHELPINFO)lParam)->hItemHandle, gszWindowsHlp, HELP_WM_HELP
  1344. , (UINT_PTR)(LPTSTR)aPreviewIds);
  1345. return TRUE;
  1346. case WM_QUERYNEWPALETTE:
  1347. case WM_PALETTECHANGED:
  1348. {
  1349. HWND hwndMCI = (HWND)GetWindowLongPtr(hDlg, DWLP_USER);
  1350. SendMessage(hwndMCI, uMsg, wParam, lParam);
  1351. break;
  1352. }
  1353. }
  1354. return FALSE;
  1355. }
  1356. //---------------------------------------------------------------------------
  1357. // mmse IUnknown base member functions
  1358. //---------------------------------------------------------------------------
  1359. /*----------------------------------------------------------
  1360. Purpose: IUnknown::QueryInterface
  1361. Returns: standard
  1362. Cond: --
  1363. */
  1364. STDMETHODIMP mmpsh_QueryInterface(
  1365. LPUNKNOWN punk,
  1366. REFIID riid,
  1367. LPVOID FAR* ppvOut)
  1368. {
  1369. PMMPSH this = IToClass(mmpsh, sei, punk);
  1370. HRESULT hres = ResultFromScode(E_NOINTERFACE);
  1371. *ppvOut = NULL;
  1372. if (IsEqualIID(riid, &IID_IUnknown) ||
  1373. IsEqualIID(riid, &IID_IShellExtInit))
  1374. {
  1375. // We use the sei field as our IUnknown as well
  1376. *ppvOut = &this->sei;
  1377. this->cRef++;
  1378. hres = NOERROR;
  1379. }
  1380. else if (IsEqualIID(riid, &IID_IShellPropSheetExt))
  1381. {
  1382. (LPSHELLPROPSHEETEXT)*ppvOut = &this->pse;
  1383. this->cRef++;
  1384. hres = NOERROR;
  1385. }
  1386. return hres;
  1387. }
  1388. /*----------------------------------------------------------
  1389. Purpose: IUnknown::AddRef
  1390. Returns: new reference count
  1391. Cond: --
  1392. */
  1393. STDMETHODIMP_(UINT) mmpsh_AddRef(
  1394. LPUNKNOWN punk)
  1395. {
  1396. PMMPSH this = IToClass(mmpsh, sei, punk);
  1397. return ++this->cRef;
  1398. }
  1399. /*----------------------------------------------------------
  1400. Purpose: IUnknown::Release
  1401. Returns: new reference count
  1402. Cond: --
  1403. */
  1404. STDMETHODIMP_(UINT) mmpsh_Release(
  1405. LPUNKNOWN punk)
  1406. {
  1407. PMMPSH this = IToClass(mmpsh, sei, punk);
  1408. if (--this->cRef)
  1409. {
  1410. return this->cRef;
  1411. }
  1412. DPF_T("*^*^*^*^*^*^*^*^*^MMPSH nuked , RefCnt = %d *^*^*^*^ \r\n", (g_cRef - 1));
  1413. if (this->pdtobj)
  1414. {
  1415. this->pdtobj->lpVtbl->Release(this->pdtobj);
  1416. }
  1417. if (this->pszFileObj)
  1418. {
  1419. LocalFree((HLOCAL)this->pszFileObj);
  1420. }
  1421. ReleaseInfoList(this);
  1422. LocalFree((HLOCAL)this);
  1423. --g_cRef;
  1424. return 0;
  1425. }
  1426. /*----------------------------------------------------------
  1427. Purpose: IShellExtInit::QueryInterface
  1428. Returns: standard
  1429. Cond: --
  1430. */
  1431. STDMETHODIMP mmpsh_SEI_QueryInterface(
  1432. LPSHELLEXTINIT psei,
  1433. REFIID riid,
  1434. LPVOID FAR* ppvOut)
  1435. {
  1436. PMMPSH this = IToClass(mmpsh, sei, psei);
  1437. return mmpsh_QueryInterface((LPUNKNOWN)&this->sei, riid, ppvOut);
  1438. }
  1439. /*----------------------------------------------------------
  1440. Purpose: IShellExtInit::AddRef
  1441. Returns: new reference count
  1442. Cond: --
  1443. */
  1444. STDMETHODIMP_(UINT) mmpsh_SEI_AddRef(
  1445. LPSHELLEXTINIT psei)
  1446. {
  1447. PMMPSH this = IToClass(mmpsh, sei, psei);
  1448. return mmpsh_AddRef((LPUNKNOWN)&this->sei);
  1449. }
  1450. /*----------------------------------------------------------
  1451. Purpose: IShellExtInit::Release
  1452. Returns: new reference count
  1453. Cond: --
  1454. */
  1455. STDMETHODIMP_(UINT) mmpsh_SEI_Release(
  1456. LPSHELLEXTINIT psei)
  1457. {
  1458. PMMPSH this = IToClass(mmpsh, sei, psei);
  1459. return mmpsh_Release((LPUNKNOWN)&this->sei);
  1460. }
  1461. /*----------------------------------------------------------
  1462. Purpose: MMPSHReleaseStgMedium
  1463. Returns: NOERROR
  1464. Cond: --
  1465. */
  1466. HRESULT MMPSHReleaseStgMedium(LPSTGMEDIUM pmedium)
  1467. {
  1468. //
  1469. // Double-check pUnkForRelease in case we're not supposed to
  1470. // release the medium.
  1471. //
  1472. if (NULL == pmedium->pUnkForRelease)
  1473. {
  1474. switch(pmedium->tymed)
  1475. {
  1476. case TYMED_HGLOBAL:
  1477. GlobalFree(pmedium->hGlobal);
  1478. break;
  1479. case TYMED_ISTORAGE:
  1480. pmedium->pstg->lpVtbl->Release(pmedium->pstg);
  1481. break;
  1482. case TYMED_ISTREAM:
  1483. pmedium->pstm->lpVtbl->Release(pmedium->pstm);
  1484. break;
  1485. default:
  1486. ASSERT(FALSE); // unknown type
  1487. break;
  1488. }
  1489. }
  1490. return NOERROR;
  1491. }
  1492. /*----------------------------------------------------------
  1493. Purpose: IShellExtInit::Initialize
  1494. Returns: noerror
  1495. Cond: --
  1496. */
  1497. STDMETHODIMP mmpsh_SEI_Initialize(
  1498. LPSHELLEXTINIT psei,
  1499. LPCITEMIDLIST pidlObj,
  1500. LPDATAOBJECT pdtobj,
  1501. HKEY hkeyProgID)
  1502. {
  1503. HRESULT hres = NOERROR;
  1504. PMMPSH this = IToClass(mmpsh, sei, psei);
  1505. DPF("mmpsh_SEI_Initialize called\n");
  1506. if (pdtobj)
  1507. {
  1508. STGMEDIUM medium;
  1509. FORMATETC fmte = {CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
  1510. if (this->pdtobj)
  1511. {
  1512. this->pdtobj->lpVtbl->Release(this->pdtobj);
  1513. }
  1514. this->pdtobj = pdtobj;
  1515. pdtobj->lpVtbl->AddRef(pdtobj);
  1516. hres = pdtobj->lpVtbl->GetData(pdtobj, &fmte, &medium);
  1517. if(SUCCEEDED(hres))
  1518. {
  1519. if (DragQueryFile(medium.hGlobal, (UINT)-1, NULL, 0))
  1520. {
  1521. TCHAR szPath[MAX_PATH];
  1522. int iIndex;
  1523. DWORD dwSize = 0;
  1524. szPath[0] = '\0';
  1525. DragQueryFile(medium.hGlobal, 0, szPath, sizeof(szPath)/sizeof(TCHAR));
  1526. dwSize = mmpshGetFileSize(szPath);
  1527. if (dwSize != 0)
  1528. {
  1529. iIndex = lstrlen(szPath) - 4;
  1530. if (!lstrcmpi((LPTSTR)(szPath+iIndex), cszWavExt))
  1531. this->iMediaType = MT_WAVE;
  1532. else if (!lstrcmpi((LPTSTR)(szPath+iIndex), cszMIDIExt))
  1533. this->iMediaType = MT_MIDI;
  1534. else if (!lstrcmpi((LPTSTR)(szPath+iIndex), cszRMIExt))
  1535. this->iMediaType = MT_MIDI;
  1536. else if (!lstrcmpi((LPTSTR)(szPath+iIndex), cszAVIExt))
  1537. this->iMediaType = MT_AVI;
  1538. else if (!lstrcmpi((LPTSTR)(szPath+iIndex), cszASFExt))
  1539. this->iMediaType = MT_ASF;
  1540. else
  1541. this->iMediaType = MT_ERROR;
  1542. if (!this->pszFileObj || lstrcmpi(this->pszFileObj, szPath))
  1543. {
  1544. if (this->pszFileObj)
  1545. LocalFree((HLOCAL)this->pszFileObj);
  1546. ReleaseInfoList(this);
  1547. if (this->iMediaType)
  1548. {
  1549. this->pszFileObj = (LPTSTR)LocalAlloc(LPTR, (lstrlen(szPath)*sizeof(TCHAR))+sizeof(TCHAR));
  1550. if (this->pszFileObj) lstrcpy(this->pszFileObj , szPath);
  1551. }
  1552. else
  1553. hres = ResultFromScode(E_FAIL);
  1554. }
  1555. }
  1556. else
  1557. hres = ResultFromScode(E_FAIL);
  1558. }
  1559. //
  1560. // Release STGMEDIUM if we're responsible for doing that.
  1561. //
  1562. if (NULL == medium.pUnkForRelease)
  1563. MMPSHReleaseStgMedium(&medium);
  1564. }
  1565. else
  1566. return hres;
  1567. }
  1568. return hres;
  1569. }
  1570. /*----------------------------------------------------------
  1571. Purpose: IShellPropSheetExt::QueryInterface
  1572. Returns: standard
  1573. Cond: --
  1574. */
  1575. STDMETHODIMP mmpsh_PSE_QueryInterface(
  1576. LPSHELLPROPSHEETEXT ppse,
  1577. REFIID riid,
  1578. LPVOID FAR* ppvOut)
  1579. {
  1580. PMMPSH this = IToClass(mmpsh, pse, ppse);
  1581. return mmpsh_QueryInterface((LPUNKNOWN)&this->sei, riid, ppvOut);
  1582. }
  1583. /*----------------------------------------------------------
  1584. Purpose: IShellPropSheetExt::AddRef
  1585. Returns: new reference count
  1586. Cond: --
  1587. */
  1588. STDMETHODIMP_(UINT) mmpsh_PSE_AddRef(
  1589. LPSHELLPROPSHEETEXT ppse)
  1590. {
  1591. PMMPSH this = IToClass(mmpsh, pse, ppse);
  1592. return mmpsh_AddRef((LPUNKNOWN)&this->sei);
  1593. }
  1594. /*----------------------------------------------------------
  1595. Purpose: IShellPropSheetExt::Release
  1596. Returns: new reference count
  1597. Cond: --
  1598. */
  1599. STDMETHODIMP_(UINT) mmpsh_PSE_Release(
  1600. LPSHELLPROPSHEETEXT ppse)
  1601. {
  1602. PMMPSH this = IToClass(mmpsh, pse, ppse);
  1603. return mmpsh_Release((LPUNKNOWN)&this->sei);
  1604. }
  1605. /*==========================================================================*/
  1606. UINT CALLBACK DetailsPageCallback(
  1607. HWND hwnd,
  1608. UINT uMsg,
  1609. LPPROPSHEETPAGE ppsp)
  1610. {
  1611. if (uMsg == PSPCB_RELEASE)
  1612. if (((PMMPSH)(ppsp->lParam))->pse.lpVtbl)
  1613. ((PMMPSH)(ppsp->lParam))->pse.lpVtbl->Release(&(((PMMPSH)(ppsp->lParam))->pse));
  1614. else
  1615. {
  1616. LocalFree((HLOCAL)((PMMPSH)(ppsp->lParam))->pszFileObj);
  1617. LocalFree((HLOCAL)ppsp->lParam);
  1618. }
  1619. return 1;
  1620. }
  1621. BOOL AddDetailsPage(
  1622. LPTSTR pszTitle,
  1623. LPFNADDPROPSHEETPAGE lpfnAddPropSheetPage,
  1624. LPARAM lDlgParam,
  1625. LPARAM lParam)
  1626. {
  1627. PROPSHEETPAGE psp;
  1628. HPROPSHEETPAGE hpsp;
  1629. psp.dwSize = sizeof(PROPSHEETPAGE);
  1630. psp.dwFlags = PSP_USETITLE | PSP_USECALLBACK;
  1631. psp.hInstance = ghInstance;
  1632. psp.pszTemplate = MAKEINTRESOURCE(DLG_FILE_DETAILS);
  1633. psp.pszIcon = NULL;
  1634. psp.pszTitle = pszTitle;
  1635. psp.pfnDlgProc = FileDetailsDlg;
  1636. psp.lParam = lDlgParam;
  1637. psp.pfnCallback = DetailsPageCallback;
  1638. psp.pcRefParent = NULL;
  1639. if (hpsp = CreatePropertySheetPage(&psp))
  1640. {
  1641. if (lpfnAddPropSheetPage(hpsp, lParam))
  1642. return TRUE;
  1643. DestroyPropertySheetPage(hpsp);
  1644. }
  1645. return FALSE;
  1646. }
  1647. UINT CALLBACK PreviewPageCallback(
  1648. HWND hwnd,
  1649. UINT uMsg,
  1650. LPPROPSHEETPAGE ppsp)
  1651. {
  1652. return 1;
  1653. }
  1654. BOOL AddPreviewPage(
  1655. LPTSTR pszTitle,
  1656. LPFNADDPROPSHEETPAGE lpfnAddPropSheetPage,
  1657. LPARAM lDlgParam,
  1658. LPARAM lParam)
  1659. {
  1660. PROPSHEETPAGE psp;
  1661. HPROPSHEETPAGE hpsp;
  1662. psp.dwSize = sizeof(PROPSHEETPAGE);
  1663. psp.dwFlags = PSP_USETITLE | PSP_USECALLBACK;
  1664. psp.hInstance = ghInstance;
  1665. psp.pszTemplate = MAKEINTRESOURCE(PREVIEW_DLG);
  1666. psp.pszIcon = NULL;
  1667. psp.pszTitle = pszTitle;
  1668. psp.pfnDlgProc = PreviewDlg;
  1669. psp.lParam = lDlgParam;
  1670. psp.pfnCallback = PreviewPageCallback;
  1671. psp.pcRefParent = NULL;
  1672. if (hpsp = CreatePropertySheetPage(&psp))
  1673. {
  1674. if (lpfnAddPropSheetPage(hpsp, lParam))
  1675. return TRUE;
  1676. DestroyPropertySheetPage(hpsp);
  1677. }
  1678. return FALSE;
  1679. }
  1680. /*----------------------------------------------------------
  1681. Purpose: IShellPropSheetExt::AddPages
  1682. Returns: NOERROR
  1683. Cond: --
  1684. */
  1685. STDMETHODIMP mmpsh_PSE_AddPages(
  1686. LPSHELLPROPSHEETEXT ppse,
  1687. LPFNADDPROPSHEETPAGE lpfnAddPage,
  1688. LPARAM lParam)
  1689. {
  1690. PMMPSH this = IToClass(mmpsh, pse, ppse);
  1691. /* BOOL fAddPreview = FALSE;
  1692. LoadString(ghInstance, IDS_DETAILS, szDetailsTab, sizeof(szDetailsTab)/sizeof(TCHAR));
  1693. RegSndCntrlClass((LPCTSTR)DISPFRAMCLASS);
  1694. AddDetailsPage(szDetailsTab,lpfnAddPage,(LPARAM)this, lParam);
  1695. switch (this->iMediaType)
  1696. {
  1697. case MT_AVI:
  1698. fAddPreview = TRUE;
  1699. break;
  1700. case MT_WAVE:
  1701. if (waveOutGetNumDevs() > 0)
  1702. fAddPreview = TRUE;
  1703. break;
  1704. case MT_MIDI:
  1705. if (midiOutGetNumDevs() > 0)
  1706. fAddPreview = TRUE;
  1707. break;
  1708. }
  1709. if (fAddPreview)
  1710. {
  1711. LoadString(ghInstance, IDS_PREVIEW, szPreviewTab, sizeof(szPreviewTab)/sizeof(TCHAR));
  1712. AddPreviewPage(szPreviewTab,lpfnAddPage,(LPARAM)this, lParam);
  1713. } */
  1714. ppse->lpVtbl->AddRef(ppse);
  1715. return NOERROR;
  1716. }
  1717. /*----------------------------------------------------------
  1718. Purpose: IShellPropSheetExt::ReplacePage
  1719. Returns: E_NOTIMPL
  1720. Cond: --
  1721. */
  1722. STDMETHODIMP mmpsh_PSE_ReplacePage(
  1723. LPSHELLPROPSHEETEXT ppse,
  1724. UINT uPageID,
  1725. LPFNADDPROPSHEETPAGE lpfnReplaceWith,
  1726. LPARAM lParam)
  1727. {
  1728. return ResultFromScode(E_NOTIMPL);
  1729. }
  1730. IShellExtInitVtbl c_mmpshSEIVtbl =
  1731. {
  1732. mmpsh_SEI_QueryInterface,
  1733. mmpsh_SEI_AddRef,
  1734. mmpsh_SEI_Release,
  1735. mmpsh_SEI_Initialize
  1736. };
  1737. IShellPropSheetExtVtbl c_mmpshPSEVtbl =
  1738. {
  1739. mmpsh_PSE_QueryInterface,
  1740. mmpsh_PSE_AddRef,
  1741. mmpsh_PSE_Release,
  1742. mmpsh_PSE_AddPages,
  1743. mmpsh_PSE_ReplacePage
  1744. } ;
  1745. HRESULT CALLBACK mmpsh_CreatePSHInstance(
  1746. LPUNKNOWN punkOuter,
  1747. REFIID riid,
  1748. LPVOID FAR* ppvOut)
  1749. {
  1750. HRESULT hres;
  1751. PMMPSH this;
  1752. DPF_T("*^*^*^*^*^*^*^*^mmpsh_CreatePSHInstance*^*^*^*^*^*^*^*^\r\n");
  1753. // The handler does not support aggregation.
  1754. if (punkOuter)
  1755. {
  1756. hres = ResultFromScode(CLASS_E_NOAGGREGATION);
  1757. goto Leave;
  1758. }
  1759. this = LocalAlloc(LPTR, sizeof(*this));
  1760. if (!this)
  1761. {
  1762. hres = ResultFromScode(E_OUTOFMEMORY);
  1763. goto Leave;
  1764. }
  1765. this->sei.lpVtbl = &c_mmpshSEIVtbl;
  1766. this->pse.lpVtbl = &c_mmpshPSEVtbl;
  1767. this->cRef = 1;
  1768. ++g_cRef;
  1769. // Note that the Release member will free the object, if
  1770. // QueryInterface failed.
  1771. hres = this->sei.lpVtbl->QueryInterface(&this->sei, riid, ppvOut);
  1772. this->sei.lpVtbl->Release(&this->sei);
  1773. Leave:
  1774. return hres; // S_OK or E_NOINTERFACE
  1775. }
  1776. BOOL mmpsh_ShowFileDetails(LPTSTR pszCaption,
  1777. HWND hwndParent,
  1778. LPTSTR pszFile,
  1779. short iMediaType)
  1780. {
  1781. PMMPSH pmmpsh;
  1782. TCHAR szTabName[64];
  1783. pmmpsh = (PMMPSH)LocalAlloc(LPTR, sizeof(*pmmpsh));
  1784. if (!pmmpsh)
  1785. return FALSE;
  1786. pmmpsh->pszFileObj = (LPTSTR)LocalAlloc(LPTR, (lstrlen(pszFile)*sizeof(TCHAR))+sizeof(TCHAR));
  1787. if (!pmmpsh->pszFileObj)
  1788. {
  1789. LocalFree((HLOCAL)pmmpsh);
  1790. return FALSE;
  1791. }
  1792. lstrcpy(pmmpsh->pszFileObj , pszFile);
  1793. pmmpsh->iMediaType = iMediaType;
  1794. LoadString(ghInstance, IDS_DETAILS, szTabName, sizeof(szTabName)/sizeof(TCHAR));
  1795. ShowPropSheet(szTabName,FileDetailsDlg,DLG_FILE_DETAILS,hwndParent,pszCaption,(LPARAM)pmmpsh);
  1796. return TRUE;
  1797. }
  1798. BOOL ResolveLink(LPTSTR szPath, LPTSTR szResolved, LONG cbSize)
  1799. {
  1800. IShellLink *psl = NULL;
  1801. HRESULT hres;
  1802. hres = SHCoCreateInstance(NULL, &CLSID_ShellLink, NULL, &IID_IShellLink, &psl);
  1803. if (SUCCEEDED(hres))
  1804. {
  1805. WCHAR wszPath[MAX_PATH];
  1806. IPersistFile *ppf;
  1807. psl->lpVtbl->QueryInterface(psl, &IID_IPersistFile, &ppf);
  1808. if (ppf)
  1809. {
  1810. wcscpy(wszPath, szPath);
  1811. hres = ppf->lpVtbl->Load(ppf, wszPath, 0);
  1812. ppf->lpVtbl->Release(ppf);
  1813. if (FAILED(hres))
  1814. {
  1815. psl->lpVtbl->Release(psl);
  1816. psl = NULL;
  1817. }
  1818. }
  1819. else
  1820. {
  1821. psl = NULL;
  1822. }
  1823. }
  1824. if (psl)
  1825. {
  1826. // this reslve could fail.. should we really do NOUI?
  1827. psl->lpVtbl->Resolve(psl, NULL, SLR_NO_UI);
  1828. psl->lpVtbl->GetPath(psl, szResolved, cbSize, NULL,
  1829. SLGP_SHORTPATH);
  1830. psl->lpVtbl->Release(psl);
  1831. }
  1832. if (SUCCEEDED(hres))
  1833. return TRUE;
  1834. return FALSE;
  1835. }
  1836. //---------------------------------------------------------------------------
  1837. // EXPORTED API
  1838. //---------------------------------------------------------------------------
  1839. /*----------------------------------------------------------
  1840. Purpose: Standard shell entry-point
  1841. Returns: standard
  1842. Cond: --
  1843. */
  1844. STDAPI DllGetClassObject(
  1845. REFCLSID rclsid,
  1846. REFIID riid,
  1847. LPVOID FAR* ppv)
  1848. {
  1849. // We are supposed return the class object for this class. Instead
  1850. // of fully implementing it in this DLL, we just call a helper
  1851. // function in the shell DLL which creates a default class factory
  1852. // object for us. When its CreateInstance member is called, it
  1853. // will call back our create instance function.
  1854. //
  1855. if (IsEqualIID(rclsid, &CLSID_mmsePropSheetHandler))
  1856. {
  1857. return SHCreateDefClassObject(
  1858. riid, // Interface ID
  1859. ppv, // Non-null to aggregate
  1860. mmpsh_CreatePSHInstance, // Callback function
  1861. &g_cRef, // Reference count of this DLL
  1862. &IID_IShellExtInit); // Init interface
  1863. }
  1864. return ResultFromScode(REGDB_E_CLASSNOTREG);
  1865. }
  1866. //****************************************************************************
  1867. // STDAPI DllCanUnLoadNow()
  1868. //
  1869. // This function is called by shell
  1870. //
  1871. //****************************************************************************
  1872. STDAPI DllCanUnloadNow(void)
  1873. {
  1874. HRESULT hr;
  1875. if (0 == g_cRef)
  1876. {
  1877. DPF("DllCanUnloadNow says OK (Ref=%d)",
  1878. g_cRef);
  1879. hr = ResultFromScode(S_OK);
  1880. }
  1881. else
  1882. {
  1883. DPF("DllCanUnloadNow says FALSE (Ref=%d)",
  1884. g_cRef);
  1885. hr = ResultFromScode(S_FALSE);
  1886. }
  1887. return hr;
  1888. }