[MPLAY32]
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Wed, 4 Feb 2015 01:36:17 +0000 (01:36 +0000)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Wed, 4 Feb 2015 01:36:17 +0000 (01:36 +0000)
Build the Open-File filter mask in runtime, according to the supported extensions and media devices registered in the registry.
Patch by Ricardo Hanke.
CORE-7883 #resolve #comment Committed, with number-of-chars vs. number-of-bytes fixes by me, plus minor modification to build the filter only once when mplay32 is launched, and use a default filter if runtime filter build fails.

svn path=/trunk/; revision=66152

24 files changed:
reactos/base/applications/mplay32/lang/bg-BG.rc
reactos/base/applications/mplay32/lang/cs-CZ.rc
reactos/base/applications/mplay32/lang/de-DE.rc
reactos/base/applications/mplay32/lang/en-US.rc
reactos/base/applications/mplay32/lang/es-ES.rc
reactos/base/applications/mplay32/lang/fr-FR.rc
reactos/base/applications/mplay32/lang/he-IL.rc
reactos/base/applications/mplay32/lang/it-IT.rc
reactos/base/applications/mplay32/lang/ja-JP.rc
reactos/base/applications/mplay32/lang/nl-NL.rc
reactos/base/applications/mplay32/lang/no-NO.rc
reactos/base/applications/mplay32/lang/pl-PL.rc
reactos/base/applications/mplay32/lang/pt-BR.rc
reactos/base/applications/mplay32/lang/ro-RO.rc
reactos/base/applications/mplay32/lang/ru-RU.rc
reactos/base/applications/mplay32/lang/sk-SK.rc
reactos/base/applications/mplay32/lang/sq-AL.rc
reactos/base/applications/mplay32/lang/sv-SE.rc
reactos/base/applications/mplay32/lang/tr-TR.rc
reactos/base/applications/mplay32/lang/uk-UA.rc
reactos/base/applications/mplay32/lang/zh-CN.rc
reactos/base/applications/mplay32/lang/zh-TW.rc
reactos/base/applications/mplay32/mplay32.c
reactos/base/applications/mplay32/mplay32.h

index df8b8f9..ff835f4 100644 (file)
@@ -47,7 +47,7 @@ END
 
 STRINGTABLE
 BEGIN
-    IDS_ALL_TYPES_FILTER "Всички поддържани (*.wav, *.cda, *.midi, *.mid, *.avi)\0*.wav;*.cda;*.midi;*.mid;*.avi\0"
+    IDS_ALL_TYPES_FILTER "Всички поддържани"
     IDS_TOOLTIP_PLAY "Пускане"
     IDS_TOOLTIP_STOP "Спиране"
     IDS_TOOLTIP_EJECT "Изваждане"
index f07af4b..27c80f2 100644 (file)
@@ -48,7 +48,7 @@ END
 
 STRINGTABLE
 BEGIN
-    IDS_ALL_TYPES_FILTER "Všechny podporované (*.wav, *.cda, *.midi, *.mid, *.avi)\0*.wav;*.cda;*.midi;*.mid;*.avi\0"
+    IDS_ALL_TYPES_FILTER "Všechny podporované"
     IDS_TOOLTIP_PLAY "Přehrát"
     IDS_TOOLTIP_STOP "Zastavit"
     IDS_TOOLTIP_EJECT "Vysunout"
index 21a3312..4547e79 100644 (file)
@@ -43,7 +43,7 @@ END
 
 STRINGTABLE
 BEGIN
-    IDS_ALL_TYPES_FILTER "Alle unterstützten (*.wav, *.cda, *.midi, *.mid, *.avi)\0*.wav;*.cda;*.midi;*.mid;*.avi\0"
+    IDS_ALL_TYPES_FILTER "Alle unterstützten"
     IDS_TOOLTIP_PLAY "Wiedergabe"
     IDS_TOOLTIP_STOP "Stopp"
     IDS_TOOLTIP_EJECT "Auswerfen"
index 714f235..9f0b0e5 100644 (file)
@@ -43,7 +43,7 @@ END
 
 STRINGTABLE
 BEGIN
-    IDS_ALL_TYPES_FILTER "All Supported (*.wav, *.cda, *.midi, *.mid, *.avi)\0*.wav;*.cda;*.midi;*.mid;*.avi\0"
+    IDS_ALL_TYPES_FILTER "All Supported"
     IDS_TOOLTIP_PLAY "Play"
     IDS_TOOLTIP_STOP "Stop"
     IDS_TOOLTIP_EJECT "Eject"
index c2b04e1..3d24798 100644 (file)
@@ -43,7 +43,7 @@ END
 
 STRINGTABLE
 BEGIN
-    IDS_ALL_TYPES_FILTER "Todos los archivos soportados (*.wav, *.cda, *.midi, *.mid, *.avi)\0*.wav;*.cda;*.midi;*.mid;*.avi\0"
+    IDS_ALL_TYPES_FILTER "Todos los archivos soportados"
     IDS_TOOLTIP_PLAY     "Reproducir"
     IDS_TOOLTIP_STOP     "Detener"
     IDS_TOOLTIP_EJECT    "Expulsar"
index 3bfd61d..b4cc64a 100644 (file)
@@ -43,7 +43,7 @@ END
 
 STRINGTABLE
 BEGIN
-    IDS_ALL_TYPES_FILTER "Tous les types supportés (*.wav, *.cda, *.midi, *.mid, *.avi)\0*.wav;*.cda;*.midi;*.mid;*.avi\0"
+    IDS_ALL_TYPES_FILTER "Tous les types supportés"
     IDS_TOOLTIP_PLAY "Lecture"
     IDS_TOOLTIP_STOP "Stop"
     IDS_TOOLTIP_EJECT "Éjecter"
index 37339dc..5e52c04 100644 (file)
@@ -43,7 +43,7 @@ END
 
 STRINGTABLE
 BEGIN
-    IDS_ALL_TYPES_FILTER "כל הקבצים הנתמכים (*.wav, *.cda, *.midi, *.mid, *.avi)\0*.wav;*.cda;*.midi;*.mid;*.avi\0"
+    IDS_ALL_TYPES_FILTER "כל הקבצים הנתמכים"
     IDS_TOOLTIP_PLAY "נגן"
     IDS_TOOLTIP_STOP "עצור"
     IDS_TOOLTIP_EJECT "הוצא"
index a1aba1d..3cc8ad6 100644 (file)
@@ -43,7 +43,7 @@ END
 
 STRINGTABLE
 BEGIN
-    IDS_ALL_TYPES_FILTER "Tutti i tipi supportati (*.wav, *.cda, *.midi, *.mid, *.avi)\0*.wav;*.cda;*.midi;*.mid;*.avi\0"
+    IDS_ALL_TYPES_FILTER "Tutti i tipi supportati"
     IDS_TOOLTIP_PLAY "Riproduci"
     IDS_TOOLTIP_STOP "Interrompi"
     IDS_TOOLTIP_EJECT "Espelli"
index 9e3b248..104f6b0 100644 (file)
@@ -43,7 +43,7 @@ END
 
 STRINGTABLE
 BEGIN
-    IDS_ALL_TYPES_FILTER "すべてのサポートされたファイル (*.wav, *.cda, *.midi, *.mid, *.avi)\0*.wav;*.cda;*.midi;*.mid;*.avi\0"
+    IDS_ALL_TYPES_FILTER "すべてのサポートされたファイル"
     IDS_TOOLTIP_PLAY "再生"
     IDS_TOOLTIP_STOP "停止"
     IDS_TOOLTIP_EJECT "取り出し"
index 4f9056f..8ff7025 100644 (file)
@@ -43,7 +43,7 @@ END
 
 STRINGTABLE
 BEGIN
-    IDS_ALL_TYPES_FILTER "Mediabestanden (*.wav, *.cda, *.midi, *.mid, *.avi)\0*.wav;*.cda;*.midi;*.mid;*.avi\0"
+    IDS_ALL_TYPES_FILTER "Mediabestanden"
     IDS_TOOLTIP_PLAY "Afspelen"
     IDS_TOOLTIP_STOP "Stoppen"
     IDS_TOOLTIP_EJECT "Uitwerpen"
index ff5f317..b142f91 100644 (file)
@@ -43,7 +43,7 @@ END
 
 STRINGTABLE
 BEGIN
-    IDS_ALL_TYPES_FILTER "Alle kompaktible filer  (*.wav, *.cda, *.midi, *.mid, *.avi)\0*.wav;*.cda;*.midi;*.mid;*.avi\0"
+    IDS_ALL_TYPES_FILTER "Alle kompaktible filer"
     IDS_TOOLTIP_PLAY "Spill av"
     IDS_TOOLTIP_STOP "Stopp"
     IDS_TOOLTIP_EJECT "Løs ut"
index 797877b..61b9331 100644 (file)
@@ -51,7 +51,7 @@ END
 
 STRINGTABLE
 BEGIN
-    IDS_ALL_TYPES_FILTER "Wszystkie formaty (*.wav, *.cda, *.midi, *.mid, *.avi)\0*.wav;*.cda;*.midi;*.mid;*.avi\0"
+    IDS_ALL_TYPES_FILTER "Wszystkie formaty"
     IDS_TOOLTIP_PLAY "Odtwarzaj"
     IDS_TOOLTIP_STOP "Zatrzymaj"
     IDS_TOOLTIP_EJECT "Wysuń"
index c53668a..e92be6b 100644 (file)
@@ -45,7 +45,7 @@ END
 
 STRINGTABLE
 BEGIN
-    IDS_ALL_TYPES_FILTER "Todos os formatos (*.wav, *.cda, *.midi, *.mid, *.avi)\0*.wav;*.cda;*.midi;*.mid;*.avi\0"
+    IDS_ALL_TYPES_FILTER "Todos os formatos"
     IDS_TOOLTIP_PLAY "Executar"
     IDS_TOOLTIP_STOP "Pausar"
     IDS_TOOLTIP_EJECT "Ejetar"
index d2d4d75..e863e02 100644 (file)
@@ -49,7 +49,7 @@ END
 
 STRINGTABLE
 BEGIN
-    IDS_ALL_TYPES_FILTER "Toate admisibile (*.wav, *.cda, *.midi, *.mid, *.avi)\0*.wav;*.cda;*.midi;*.mid;*.avi\0"
+    IDS_ALL_TYPES_FILTER "Toate admisibile"
     IDS_TOOLTIP_PLAY "Redare conținut multimedia"
     IDS_TOOLTIP_STOP "Oprirea lecturii"
     IDS_TOOLTIP_EJECT "Scoate"
index ab746af..defc6a5 100644 (file)
@@ -43,7 +43,7 @@ END
 
 STRINGTABLE
 BEGIN
-    IDS_ALL_TYPES_FILTER "Все поддерживаемые (*.wav, *.cda, *.midi, *.mid, *.avi)\0*.wav;*.cda;*.midi;*.mid;*.avi\0"
+    IDS_ALL_TYPES_FILTER "Все поддерживаемые"
     IDS_TOOLTIP_PLAY "Воспроизведение"
     IDS_TOOLTIP_STOP "Остановить"
     IDS_TOOLTIP_EJECT "Извлечь"
index 90c391a..f79d6a6 100644 (file)
@@ -48,7 +48,7 @@ END
 
 STRINGTABLE
 BEGIN
-    IDS_ALL_TYPES_FILTER "Všetky podporované (*.wav, *.cda, *.midi, *.mid, *.avi)\0*.wav;*.cda;*.midi;*.mid;*.avi\0"
+    IDS_ALL_TYPES_FILTER "Všetky podporované"
     IDS_TOOLTIP_PLAY "Prehrať"
     IDS_TOOLTIP_STOP "Zastaviť"
     IDS_TOOLTIP_EJECT "Vysunúť"
index b3a827e..aa1eaef 100644 (file)
@@ -47,7 +47,7 @@ END
 
 STRINGTABLE
 BEGIN
-    IDS_ALL_TYPES_FILTER "Të gjith suportimet (*.wav, *.cda, *.midi, *.mid, *.avi)\0*.wav;*.cda;*.midi;*.mid;*.avi\0"
+    IDS_ALL_TYPES_FILTER "Të gjith suportimet"
     IDS_TOOLTIP_PLAY "Fillo"
     IDS_TOOLTIP_STOP "Ndalo"
     IDS_TOOLTIP_EJECT "Nxjerr"
index d7e58aa..9dde053 100644 (file)
@@ -50,7 +50,7 @@ END
 
 STRINGTABLE
 BEGIN
-    IDS_ALL_TYPES_FILTER "Alla kompaktibla filer  (*.wav, *.cda, *.midi, *.mid, *.avi)\0*.wav;*.cda;*.midi;*.mid;*.avi\0"
+    IDS_ALL_TYPES_FILTER "Alla kompaktibla filer"
     IDS_TOOLTIP_PLAY "Spela upp"
     IDS_TOOLTIP_STOP "Stopp"
     IDS_TOOLTIP_EJECT "Mata ut"
index 71b2eb9..9f4d46e 100644 (file)
@@ -45,7 +45,7 @@ END
 
 STRINGTABLE
 BEGIN
-    IDS_ALL_TYPES_FILTER "Desteklenen Kütükler (*.wav, *.cda, *.mid, *.midi, *.avi)\0*.wav;*.cda;*.mid;*.midi;*.avi\0"
+    IDS_ALL_TYPES_FILTER "Desteklenen Kütükler"
     IDS_TOOLTIP_PLAY "Çal"
     IDS_TOOLTIP_STOP "Durdur"
     IDS_TOOLTIP_EJECT "Çıkart"
index 54cddbd..d02cdb5 100644 (file)
@@ -51,7 +51,7 @@ END
 
 STRINGTABLE
 BEGIN
-    IDS_ALL_TYPES_FILTER "Всі підтримувані (*.wav, *.cda, *.midi, *.mid, *.avi)\0*.wav;*.cda;*.midi;*.mid;*.avi\0"
+    IDS_ALL_TYPES_FILTER "Всі підтримувані"
     IDS_TOOLTIP_PLAY "Відтворення"
     IDS_TOOLTIP_STOP "Зупинити"
     IDS_TOOLTIP_EJECT "Витягти"
index acc9362..d024d59 100644 (file)
@@ -45,7 +45,7 @@ END
 
 STRINGTABLE
 BEGIN
-    IDS_ALL_TYPES_FILTER "所有支持的格式 (*.wav, *.cda, *.midi, *.mid, *.avi)\0*.wav;*.cda;*.midi;*.mid;*.avi\0"
+    IDS_ALL_TYPES_FILTER "所有支持的格式"
     IDS_TOOLTIP_PLAY "播放"
     IDS_TOOLTIP_STOP "停止"
     IDS_TOOLTIP_EJECT "弹出"
index 0a118d8..3010b5b 100644 (file)
@@ -51,7 +51,7 @@ END
 
 STRINGTABLE
 BEGIN
-    IDS_ALL_TYPES_FILTER "所有支援格式 (*.wav, *.cda, *.midi, *.mid, *.avi)\0*.wav;*.cda;*.midi;*.mid;*.avi\0"
+    IDS_ALL_TYPES_FILTER "所有支援格式"
     IDS_TOOLTIP_PLAY "播放"
     IDS_TOOLTIP_STOP "停止"
     IDS_TOOLTIP_EJECT "卸載"
index f983ca0..d19de85 100644 (file)
@@ -8,13 +8,18 @@
 
 #define MAIN_WINDOW_HEIGHT    125
 #define MAIN_WINDOW_MIN_WIDTH 250
+#define MAX_MCISTR            256
 
 HINSTANCE hInstance = NULL;
 HWND hTrackBar = NULL;
 HWND hToolBar = NULL;
 HMENU hMainMenu = NULL;
+
 TCHAR szAppTitle[256] = _T("");
-TCHAR szPrevFile[MAX_PATH] = _T("\0");
+TCHAR szPrevFile[MAX_PATH] = _T("");
+TCHAR szDefaultFilter[MAX_PATH] = _T("");
+TCHAR *szFilter = NULL;
+
 WORD wDeviceId;
 BOOL bIsOpened = FALSE;
 BOOL bIsPaused = FALSE;
@@ -152,12 +157,12 @@ SetImageList(HWND hwnd)
 static VOID
 ShowMCIError(HWND hwnd, DWORD dwError)
 {
-    TCHAR szErrorMessage[256];
-    TCHAR szTempMessage[300];
+    TCHAR szErrorMessage[MAX_MCISTR];
+    TCHAR szTempMessage[MAX_MCISTR + 44];
 
-    if (mciGetErrorString(dwError, szErrorMessage, sizeof(szErrorMessage) / sizeof(TCHAR)) == FALSE)
+    if (mciGetErrorString(dwError, szErrorMessage, sizeof(szErrorMessage) / sizeof(szErrorMessage[0])) == FALSE)
     {
-        LoadString(hInstance, IDS_DEFAULTMCIERRMSG, szErrorMessage, sizeof(szErrorMessage) / sizeof(TCHAR));
+        LoadString(hInstance, IDS_DEFAULTMCIERRMSG, szErrorMessage, sizeof(szErrorMessage) / sizeof(szErrorMessage[0]));
     }
 
     _stprintf(szTempMessage, _T("MMSYS%lu: %s"), dwError, szErrorMessage);
@@ -320,6 +325,69 @@ SwitchViewMode(HWND hwnd)
     }
 }
 
+static DWORD
+GetNumDevices(VOID)
+{
+    MCI_SYSINFO_PARMS mciSysInfo;
+    DWORD dwNumDevices = 0;
+
+    mciSysInfo.dwCallback  = 0;
+    mciSysInfo.lpstrReturn = (LPTSTR)&dwNumDevices;
+    mciSysInfo.dwRetSize   = sizeof(dwNumDevices);
+    mciSysInfo.dwNumber    = 0;
+    mciSysInfo.wDeviceType = MCI_ALL_DEVICE_ID;
+
+    mciSendCommand(MCI_ALL_DEVICE_ID, MCI_SYSINFO, MCI_SYSINFO_QUANTITY, (DWORD_PTR)&mciSysInfo);
+
+    return *(DWORD*)mciSysInfo.lpstrReturn;
+}
+
+static DWORD
+GetDeviceName(DWORD dwDeviceIndex, LPTSTR lpDeviceName, DWORD dwDeviceNameSize)
+{
+    MCI_SYSINFO_PARMS mciSysInfo;
+
+    mciSysInfo.dwCallback  = 0;
+    mciSysInfo.lpstrReturn = lpDeviceName;
+    mciSysInfo.dwRetSize   = dwDeviceNameSize;
+    mciSysInfo.dwNumber    = dwDeviceIndex;
+    mciSysInfo.wDeviceType = MCI_DEVTYPE_WAVEFORM_AUDIO;
+
+    return mciSendCommand(MCI_ALL_DEVICE_ID, MCI_SYSINFO, MCI_SYSINFO_NAME, (DWORD_PTR)&mciSysInfo);
+}
+
+static DWORD
+GetDeviceFriendlyName(LPTSTR lpDeviceName, LPTSTR lpFriendlyName, DWORD dwFriendlyNameSize)
+{
+    MCIERROR mciError;
+    MCI_OPEN_PARMS mciOpen;
+    MCI_INFO_PARMS mciInfo;
+    MCI_GENERIC_PARMS mciGeneric;
+
+    mciOpen.dwCallback = 0;
+    mciOpen.wDeviceID  = 0;
+    mciOpen.lpstrDeviceType  = lpDeviceName;
+    mciOpen.lpstrElementName = NULL;
+    mciOpen.lpstrAlias = NULL;
+
+    mciError = mciSendCommand(0, MCI_OPEN, MCI_OPEN_TYPE | MCI_WAIT, (DWORD_PTR)&mciOpen);
+    if (mciError)
+    {
+        return mciError;
+    }
+
+    mciInfo.dwCallback  = 0;
+    mciInfo.lpstrReturn = lpFriendlyName;
+    mciInfo.dwRetSize   = dwFriendlyNameSize;
+
+    mciError = mciSendCommand(mciOpen.wDeviceID, MCI_INFO, MCI_INFO_PRODUCT, (DWORD_PTR)&mciInfo);
+
+    mciGeneric.dwCallback = 0;
+    mciSendCommand(mciOpen.wDeviceID, MCI_CLOSE, MCI_WAIT, (DWORD_PTR)&mciGeneric);
+
+    return mciError;
+}
+
 static DWORD
 CloseMciDevice(VOID)
 {
@@ -607,7 +675,7 @@ PlayFile(HWND hwnd, LPTSTR lpFileName)
     {
         TCHAR szErrorMessage[256];
 
-        LoadString(hInstance, IDS_UNKNOWNFILEEXT, szErrorMessage, sizeof(szErrorMessage) / sizeof(TCHAR));
+        LoadString(hInstance, IDS_UNKNOWNFILEEXT, szErrorMessage, sizeof(szErrorMessage) / sizeof(szErrorMessage[0]));
         MessageBox(hwnd, szErrorMessage, szAppTitle, MB_OK | MB_ICONEXCLAMATION);
         return;
     }
@@ -639,18 +707,216 @@ PlayFile(HWND hwnd, LPTSTR lpFileName)
     }
 }
 
+static VOID
+BuildFileFilter(VOID)
+{
+    TCHAR szDeviceName[MAX_MCISTR];
+    TCHAR szFriendlyName[MAX_MCISTR];
+    TCHAR *szDevice = NULL;
+    static TCHAR szDefaultExtension[] = _T("*.*");
+    TCHAR *szExtensionList = NULL;
+    TCHAR *szExtension = NULL;
+    TCHAR *c = NULL;
+    TCHAR *d = NULL;
+    DWORD dwNumValues;
+    DWORD dwNumDevices;
+    DWORD dwValueNameLen;
+    DWORD dwValueDataSize;
+    DWORD dwMaskLen;
+    DWORD dwFilterSize;
+    DWORD dwDeviceSize;
+    DWORD dwExtensionLen;
+    DWORD i;
+    DWORD j;
+    UINT uSizeRemain;
+    UINT uMaskRemain;
+    HKEY hKey = NULL;
+
+    /* Always load the default (all files) filter */
+    LoadString(hInstance, IDS_ALL_TYPES_FILTER, szDefaultFilter, sizeof(szDefaultFilter) / sizeof(szDefaultFilter[0]));
+
+    if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\MCI Extensions"), 0, KEY_READ, &hKey) != ERROR_SUCCESS)
+    {
+        goto Failure;
+    }
+
+    if (RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL, NULL, NULL, &dwNumValues, &dwValueNameLen, &dwValueDataSize, NULL, NULL) != ERROR_SUCCESS)
+    {
+        goto Failure;
+    }
+
+    dwMaskLen = ((dwValueNameLen + 3) * dwNumValues) + 1;
+
+    szExtensionList = malloc(dwMaskLen * sizeof(TCHAR));
+    if (!szExtensionList)
+    {
+        goto Failure;
+    }
+
+    dwNumDevices = GetNumDevices();
+
+    /* Allocate space for every pair of Device and Extension Filter */
+    dwFilterSize = (MAX_MCISTR + (dwMaskLen * 2) + 5) * dwNumDevices;
+
+    /* Add space for the "All supported" entry */
+    dwFilterSize = (dwFilterSize + (dwMaskLen * 2) + 7) * sizeof(TCHAR) + sizeof(szDefaultFilter);
+
+    szFilter = malloc(dwFilterSize);
+    if (!szFilter)
+    {
+        goto Failure;
+    }
+
+    szExtension = malloc((dwValueNameLen + 1) * sizeof(TCHAR));
+    if (!szExtension)
+    {
+        goto Failure;
+    }
+
+    szDevice = malloc(dwValueDataSize + sizeof(TCHAR));
+    if (!szDevice)
+    {
+        goto Failure;
+    }
+
+    ZeroMemory(szFilter, dwFilterSize);
+
+    uSizeRemain = dwFilterSize;
+    c = szFilter;
+
+    for (j = 1; j <= dwNumDevices; j++)
+    {
+        if (GetDeviceName(j, szDeviceName, sizeof(szDeviceName)))
+        {
+            continue;
+        }
+
+        if (GetDeviceFriendlyName(szDeviceName, szFriendlyName, sizeof(szFriendlyName)))
+        {
+            continue;
+        }
+
+        /* Copy the default extension list, that may be overwritten after... */
+        StringCbCopy(szExtensionList, dwMaskLen * sizeof(TCHAR), szDefaultExtension);
+
+        /* Try to determine the real extension list */
+        uMaskRemain = dwMaskLen * sizeof(TCHAR);
+        d = szExtensionList;
+
+        for (i = 0; i < dwNumValues; i++)
+        {
+            dwExtensionLen = dwValueNameLen + 1;
+            dwDeviceSize   = dwValueDataSize + sizeof(TCHAR);
+
+            ZeroMemory(szDevice, dwDeviceSize);
+
+            if (RegEnumValue(hKey, i, szExtension, &dwExtensionLen, NULL, NULL, (LPBYTE)szDevice, &dwDeviceSize) == ERROR_SUCCESS)
+            {
+                CharLowerBuff(szDevice, dwDeviceSize / sizeof(TCHAR));
+                CharLowerBuff(szDeviceName, sizeof(szDeviceName) / sizeof(szDeviceName[0]));
+                if (_tcscmp(szDeviceName, szDevice) == 0)
+                {
+                     CharLowerBuff(szExtension, dwExtensionLen);
+                     StringCbPrintfEx(d, uMaskRemain, &d, &uMaskRemain, 0, _T("%s%s%s"), _T("*."), szExtension, _T(";"));
+                }
+            }
+        }
+
+        /* Remove the last separator */
+        d--;
+        uSizeRemain += sizeof(*d);
+        *d = _T('\0');
+
+        /* Add the description */
+        StringCbPrintfEx(c, uSizeRemain, &c, &uSizeRemain, 0, _T("%s (%s)"), szFriendlyName, szExtensionList);
+
+        /* Skip one char to seperate the description from the filter mask */
+        c++;
+        uSizeRemain -= sizeof(*c);
+
+        /* Append the filter mask */
+        StringCbCopyEx(c, uSizeRemain, szExtensionList, &c, &uSizeRemain, 0); 
+
+        /* Skip another char to seperate the elements of the filter mask */
+        c++;
+        uSizeRemain -= sizeof(*c);
+    }
+
+    /* Build the full list of supported extensions */
+    uMaskRemain = dwMaskLen * sizeof(TCHAR);
+    d = szExtensionList;
+
+    for (i = 0; i < dwNumValues; i++)
+    {
+        dwExtensionLen = dwValueNameLen + 1;
+
+        if (RegEnumValue(hKey, i, szExtension, &dwExtensionLen, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
+        {
+            CharLowerBuff(szExtension, dwExtensionLen);
+            StringCbPrintfEx(d, uMaskRemain, &d, &uMaskRemain, 0, _T("%s%s%s"), _T("*."), szExtension, _T(";"));
+        }
+    }
+
+    /* Remove the last separator */
+    d--;
+    uSizeRemain += sizeof(*d);
+    *d = _T('\0');
+
+    /* Add the default (all files) description */
+    StringCbPrintfEx(c, uSizeRemain, &c, &uSizeRemain, 0, _T("%s (%s)"), szDefaultFilter, szExtensionList);
+
+    /* Skip one char to seperate the description from the filter mask */
+    c++;
+    uSizeRemain -= sizeof(*c);
+
+    /* Append the filter mask */
+    StringCbCopyEx(c, uSizeRemain, szExtensionList, &c, &uSizeRemain, 0); 
+
+Cleanup:
+    if (szExtensionList) free(szExtensionList);
+    if (szExtension)     free(szExtension);
+    if (szDevice)        free(szDevice);
+    RegCloseKey(hKey);
+
+    return;
+
+Failure:
+    /* We failed at retrieving the supported files, so use the default filter */
+    if (szFilter) free(szFilter);
+    szFilter = szDefaultFilter;
+
+    uSizeRemain = sizeof(szDefaultFilter);
+    c = szFilter;
+
+    /* Add the default (all files) description */
+    StringCbPrintfEx(c, uSizeRemain, &c, &uSizeRemain, 0, _T("%s (%s)"), szDefaultFilter, szDefaultExtension);
+
+    /* Skip one char to seperate the description from the filter mask */
+    c++;
+    uSizeRemain -= sizeof(*c);
+
+    /* Append the filter mask */
+    StringCbCopyEx(c, uSizeRemain, szDefaultExtension, &c, &uSizeRemain, 0); 
+
+    goto Cleanup;
+}
+
+static VOID
+CleanupFileFilter(VOID)
+{
+    if (szFilter && szFilter != szDefaultFilter) free(szFilter);
+}
+
 static VOID
 OpenFileDialog(HWND hwnd)
 {
     OPENFILENAME OpenFileName;
-    TCHAR szFile[MAX_PATH + 1] = _T("\0");
-    TCHAR szFilter[MAX_PATH], szCurrentDir[MAX_PATH];
+    TCHAR szFile[MAX_PATH + 1] = _T("");
+    TCHAR szCurrentDir[MAX_PATH];
 
     ZeroMemory(&OpenFileName, sizeof(OpenFileName));
 
-    LoadString(hInstance, IDS_ALL_TYPES_FILTER, szFilter, sizeof(szFilter) / sizeof(TCHAR));
-
-    if (!GetCurrentDirectory(sizeof(szCurrentDir) / sizeof(TCHAR), szCurrentDir))
+    if (!GetCurrentDirectory(sizeof(szCurrentDir) / sizeof(szCurrentDir[0]), szCurrentDir))
     {
         _tcscpy(szCurrentDir, _T("c:\\"));
     }
@@ -660,7 +926,7 @@ OpenFileDialog(HWND hwnd)
     OpenFileName.hInstance       = hInstance;
     OpenFileName.lpstrFilter     = szFilter;
     OpenFileName.lpstrFile       = szFile;
-    OpenFileName.nMaxFile        = sizeof(szFile) / sizeof((szFile)[0]);
+    OpenFileName.nMaxFile        = sizeof(szFile) / sizeof(szFile[0]);
     OpenFileName.lpstrInitialDir = szCurrentDir;
     OpenFileName.Flags           = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_SHAREAWARE;
     OpenFileName.lpstrDefExt     = _T("\0");
@@ -689,7 +955,7 @@ MainWndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
             TCHAR droppedfile[MAX_PATH];
 
             drophandle = (HDROP)wParam;
-            DragQueryFile(drophandle, 0, droppedfile, sizeof(droppedfile) / sizeof(TCHAR));
+            DragQueryFile(drophandle, 0, droppedfile, sizeof(droppedfile) / sizeof(droppedfile[0]));
             DragFinish(drophandle);
             PlayFile(hwnd, droppedfile);
             break;
@@ -862,7 +1128,7 @@ MainWndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
 
                 case IDM_CLOSE_FILE:
                     StopPlayback(hwnd);
-                    _tcscpy(szPrevFile, _T("\0"));
+                    szPrevFile[0] = _T('\0');
                     break;
 
                 case IDM_REPEAT:
@@ -928,7 +1194,7 @@ _tWinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPTSTR lpCmdLine, INT nCmdShow)
 
     hInstance = hInst;
 
-    LoadString(hInstance, IDS_APPTITLE, szAppTitle, sizeof(szAppTitle) / sizeof(TCHAR));
+    LoadString(hInstance, IDS_APPTITLE, szAppTitle, sizeof(szAppTitle) / sizeof(szAppTitle[0]));
 
     WndClass.cbSize            = sizeof(WNDCLASSEX);
     WndClass.lpszClassName     = szClassName;
@@ -965,6 +1231,8 @@ _tWinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPTSTR lpCmdLine, INT nCmdShow)
 
     hAccel = LoadAccelerators(hInstance, MAKEINTRESOURCE(ID_ACCELERATORS));
 
+    BuildFileFilter();
+
     DragAcceptFiles(hwnd, TRUE);
 
     DisableMenuItems();
@@ -991,6 +1259,8 @@ _tWinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPTSTR lpCmdLine, INT nCmdShow)
         }
     }
 
+    CleanupFileFilter();
+
     DestroyAcceleratorTable(hAccel);
 
     return (INT)msg.wParam;
index 77c68ae..6d092d4 100644 (file)
@@ -1,4 +1,5 @@
 #include <stdarg.h>
+#include <stdlib.h>
 #include <windef.h>
 #include <winbase.h>
 #include <winuser.h>
@@ -10,6 +11,7 @@
 #include <digitalv.h>
 #include <commctrl.h>
 #include <tchar.h>
+#include <strsafe.h>
 
 #include "resource.h"