Leaked source code of windows server 2003
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.

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