MCI #4: Add support for many MCIWNDM_ messages and some MCI_ commands
Dmitry Timoshkov
dmitry at baikal.ru
Tue Dec 30 10:48:06 CST 2003
Hello,
Please apply after MCI #3.
Changelog:
Dmitry Timoshkov <dmitry at codeweavers.com>
Add support for many MCIWNDM_ messages and some MCI_ commands
in the MCIWndClass implementation.
MCIWndRegisterClass() takes no parameters according to Platform SDK
headers.
diff -u cvs/hq/wine/dlls/msvideo/mciwnd.c wine/dlls/msvideo/mciwnd.c
--- cvs/hq/wine/dlls/msvideo/mciwnd.c 2003-12-30 22:44:20.000000000 +0800
+++ wine/dlls/msvideo/mciwnd.c 2003-12-30 23:28:23.000000000 +0800
@@ -17,14 +17,11 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* FIXME:
- * Add support for all remaining MCI_ and MCIWNDM_ messages.
- * Add support for MCIWNDF_NOTIFYMODE (all cases), MCIWNDF_NOTIFYPOS.
+ * Add support for all remaining MCI_ commands and MCIWNDM_ messages.
+ * Add support for all MCIWNDF_ flags.
*/
-#define COM_NO_WINDOWS_H
#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
#include "windef.h"
#include "winbase.h"
@@ -48,16 +45,31 @@ typedef struct
{
DWORD dwStyle;
MCIDEVICEID mci;
+ HDRVR hdrv;
+ int alias;
UINT dev_type;
+ UINT mode;
+ long position;
+ SIZE size; /* size of the original frame rect */
+ int zoom;
LPWSTR lpName;
HWND hWnd, hwndOwner;
UINT uTimer;
MCIERROR lasterror;
+ WCHAR return_string[128];
+ WORD active_timer, inactive_timer;
} MCIWndInfo;
#define MCIWND_NOTIFY_MODE(info) \
if ((info)->dwStyle & MCIWNDF_NOTIFYMODE) \
- SendMessageW((info)->hwndOwner, MCIWNDM_NOTIFYMODE, (WPARAM)(info)->hWnd, (LPARAM)SendMessageW((info)->hWnd, MCIWNDM_GETMODEW, 0, 0))
+ { \
+ UINT new_mode = SendMessageW((info)->hWnd, MCIWNDM_GETMODEW, 0, 0); \
+ if (new_mode != (info)->mode) \
+ { \
+ (info)->mode = new_mode; \
+ SendMessageW((info)->hwndOwner, MCIWNDM_NOTIFYMODE, (WPARAM)(info)->hWnd, new_mode); \
+ } \
+ }
#define MCIWND_NOTIFY_SIZE(info) \
if ((info)->dwStyle & MCIWNDF_NOTIFYSIZE) \
@@ -69,6 +81,17 @@ typedef struct
#define MCIWND_NOTIFY_MEDIA(info) MCIWND_notify_media(info)
+#define MCIWND_NOTIFY_POS(info) \
+ if ((info)->dwStyle & MCIWNDF_NOTIFYPOS) \
+ { \
+ long new_pos = SendMessageW((info)->hWnd, MCIWNDM_GETPOSITIONW, 0, 0); \
+ if (new_pos != (info)->position) \
+ { \
+ (info)->position = new_pos; \
+ SendMessageW((info)->hwndOwner, MCIWNDM_NOTIFYPOS, (WPARAM)(info)->hWnd, new_pos); \
+ } \
+ }
+
static LRESULT WINAPI MCIWndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam);
#define CTL_PLAYSTOP 0x3200
@@ -80,7 +103,7 @@ static LRESULT WINAPI MCIWndProc(HWND hW
*
* NOTE: Native always uses its own hInstance
*/
-BOOL VFWAPIV MCIWndRegisterClass(HINSTANCE hInst)
+BOOL VFWAPIV MCIWndRegisterClass(void)
{
WNDCLASSW wc;
@@ -115,11 +138,12 @@ HWND VFWAPIV MCIWndCreateW(HWND hwndPare
{
TRACE("%p %p %lx %s\n", hwndParent, hInstance, dwStyle, debugstr_w(szFile));
- MCIWndRegisterClass(hInstance);
+ MCIWndRegisterClass();
- /* window becomes visible after MCI_PLAY command in the case of MCIWNDF_NOOPEN */
- if (dwStyle & MCIWNDF_NOOPEN)
- dwStyle &= ~WS_VISIBLE;
+ if (hwndParent)
+ dwStyle |= WS_VISIBLE | WS_BORDER /*| WS_CHILD*/;
+ else
+ dwStyle |= WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
return CreateWindowExW(0, mciWndClassW, NULL,
dwStyle | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
@@ -148,10 +172,23 @@ HWND VFWAPIV MCIWndCreateA(HWND hwndPare
return ret;
}
-static void MCIWND_UpdateText(MCIWndInfo *mwi)
+static void MCIWND_UpdateState(MCIWndInfo *mwi)
{
WCHAR buffer[1024];
+ if (!mwi->mci)
+ {
+ /* FIXME: get this from resources */
+ static const WCHAR no_deviceW[] = {'N','o',' ','D','e','v','i','c','e',0};
+ SetWindowTextW(mwi->hWnd, no_deviceW);
+ return;
+ }
+
+ MCIWND_NOTIFY_POS(mwi);
+
+ if (!(mwi->dwStyle & MCIWNDF_NOPLAYBAR))
+ SendDlgItemMessageW(mwi->hWnd, CTL_TRACKBAR, TBM_SETPOS, TRUE, mwi->position);
+
if ((mwi->dwStyle & MCIWNDF_SHOWNAME) && mwi->lpName)
strcpyW(buffer, mwi->lpName);
else
@@ -168,8 +205,11 @@ static void MCIWND_UpdateText(MCIWndInfo
if (mwi->dwStyle & MCIWNDF_SHOWPOS)
{
- static const WCHAR formatW[] = {'%','l','d',0};
- sprintfW(buffer + strlenW(buffer), formatW, SendMessageW(mwi->hWnd, MCIWNDM_GETPOSITIONW, 0, 0));
+ WCHAR posW[64];
+
+ posW[0] = 0;
+ SendMessageW(mwi->hWnd, MCIWNDM_GETPOSITIONW, 64, (LPARAM)posW);
+ strcatW(buffer, posW);
}
if ((mwi->dwStyle & (MCIWNDF_SHOWPOS|MCIWNDF_SHOWMODE)) == (MCIWNDF_SHOWPOS|MCIWNDF_SHOWMODE))
@@ -180,32 +220,16 @@ static void MCIWND_UpdateText(MCIWndInfo
if (mwi->dwStyle & MCIWNDF_SHOWMODE)
{
- /* FIXME: get the status string from resources */
- static const WCHAR not_readyW[] = {'n','o','t',' ','r','e','a','d','y',0};
- static const WCHAR pausedW[] = {'p','a','u','s','e','d',0};
- static const WCHAR playingW[] = {'p','l','a','y','i','n','g',0};
- static const WCHAR stoppedW[] = {'s','t','o','p','p','e','d',0};
- static const WCHAR openW[] = {'o','p','e','n',0};
- static const WCHAR recordingW[] = {'r','e','c','o','r','d','i','n','g',0};
- static const WCHAR seekingW[] = {'s','e','e','k','i','n','g',0};
- static const WCHAR unknownW[] = {'?','?','?',0};
-
- switch (SendMessageW(mwi->hWnd, MCIWNDM_GETMODEW, 0, 0))
- {
- case MCI_MODE_NOT_READY: strcatW(buffer, not_readyW); break;
- case MCI_MODE_PAUSE: strcatW(buffer, pausedW); break;
- case MCI_MODE_PLAY: strcatW(buffer, playingW); break;
- case MCI_MODE_STOP: strcatW(buffer, stoppedW); break;
- case MCI_MODE_OPEN: strcatW(buffer, openW); break;
- case MCI_MODE_RECORD: strcatW(buffer, recordingW); break;
- case MCI_MODE_SEEK: strcatW(buffer, seekingW); break;
- default: strcatW(buffer, unknownW); break;
- }
+ WCHAR modeW[64];
+
+ modeW[0] = 0;
+ SendMessageW(mwi->hWnd, MCIWNDM_GETMODEW, 64, (LPARAM)modeW);
+ strcatW(buffer, modeW);
}
if (mwi->dwStyle & (MCIWNDF_SHOWPOS|MCIWNDF_SHOWMODE))
{
- static const WCHAR r_braceW[] = {' ',')',0};
+ static const WCHAR r_braceW[] = {')',0};
strcatW(buffer, r_braceW);
}
@@ -219,21 +243,19 @@ static LRESULT MCIWND_Create(HWND hWnd,
MCIWndInfo *mwi;
static const WCHAR buttonW[] = {'b','u','t','t','o','n',0};
- /* This sets the default window size */
- SendMessageW(hWnd, MCI_CLOSE, 0, 0);
-
- mwi = HeapAlloc(GetProcessHeap(), 0, sizeof(*mwi));
+ mwi = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*mwi));
if (!mwi) return -1;
SetWindowLongW(hWnd, 0, (LPARAM)mwi);
mwi->dwStyle = cs->style;
- mwi->mci = 0;
- mwi->lpName = NULL;
- mwi->uTimer = 0;
mwi->hWnd = hWnd;
mwi->hwndOwner = cs->hwndParent;
- mwi->lasterror = 0;
+ mwi->active_timer = 500;
+ mwi->inactive_timer = 2000;
+ mwi->mode = MCI_MODE_NOT_READY;
+ mwi->position = -1;
+ mwi->zoom = 100;
if (!(mwi->dwStyle & MCIWNDF_NOMENU))
{
@@ -263,9 +285,25 @@ static LRESULT MCIWND_Create(HWND hWnd,
TRACE("Get status: %p\n", hChld);
}
- SendMessageW(hWnd, MCIWNDM_OPENW, 0, (LPARAM)cs->lpCreateParams);
+ /* This sets the default window size */
+ SendMessageW(hWnd, MCI_CLOSE, 0, 0);
+
+ if (cs->lpCreateParams)
+ {
+ LPARAM lParam;
+
+ /* MCI wnd class is prepared to be embedded as an MDI child window */
+ if (cs->dwExStyle & WS_EX_MDICHILD)
+ {
+ MDICREATESTRUCTW *mdics = (MDICREATESTRUCTW *)cs->lpCreateParams;
+ lParam = mdics->lParam;
+ }
+ else
+ lParam = (LPARAM)cs->lpCreateParams;
+ /* yes, A variant of the message */
+ SendMessageW(hWnd, MCIWNDM_OPENA, 0, lParam);
+ }
- MCIWND_UpdateText(mwi);
return 0;
}
@@ -302,19 +340,11 @@ static LRESULT MCIWND_Command(MCIWndInfo
case CTL_MENU:
case CTL_TRACKBAR:
default:
- MessageBoxA(0, "ooch", "NIY", MB_OK);
+ FIXME("support for command %04x not implement yet\n", LOWORD(wParam));
}
return 0L;
}
-static void MCIWND_Timer(MCIWndInfo *mwi)
-{
- LONG pos = SendMessageW(mwi->hWnd, MCIWNDM_GETPOSITIONW, 0, 0);
- TRACE("%ld\n", pos);
- SendDlgItemMessageW(mwi->hWnd, CTL_TRACKBAR, TBM_SETPOS, TRUE, pos);
- MCIWND_UpdateText(mwi);
-}
-
static void MCIWND_notify_media(MCIWndInfo *mwi)
{
if (mwi->dwStyle & (MCIWNDF_NOTIFYMEDIAA | MCIWNDF_NOTIFYMEDIAW))
@@ -345,16 +375,49 @@ static void MCIWND_notify_media(MCIWndIn
}
}
+static MCIERROR mci_generic_command(MCIWndInfo *mwi, UINT cmd)
+{
+ MCI_GENERIC_PARMS mci_generic;
+
+ mci_generic.dwCallback = 0;
+ mwi->lasterror = mciSendCommandW(mwi->mci, cmd, 0, (DWORD_PTR)&mci_generic);
+
+ if (mwi->lasterror)
+ return mwi->lasterror;
+
+ MCIWND_NOTIFY_MODE(mwi);
+ MCIWND_UpdateState(mwi);
+ return 0;
+}
+
+static LRESULT mci_get_devcaps(MCIWndInfo *mwi, UINT cap)
+{
+ MCI_GETDEVCAPS_PARMS mci_devcaps;
+
+ mci_devcaps.dwItem = cap;
+ mwi->lasterror = mciSendCommandW(mwi->mci, MCI_GETDEVCAPS,
+ MCI_GETDEVCAPS_ITEM,
+ (DWORD_PTR)&mci_devcaps);
+ if (mwi->lasterror)
+ return 0;
+
+ return mci_devcaps.dwReturn;
+}
+
static LRESULT WINAPI MCIWndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
{
MCIWndInfo *mwi;
- if (wMsg == WM_CREATE)
- return MCIWND_Create(hWnd, (CREATESTRUCTW *)lParam);
+ TRACE("%p %04x %08x %08lx\n", hWnd, wMsg, wParam, lParam);
mwi = (MCIWndInfo*)GetWindowLongW(hWnd, 0);
if (!mwi)
+ {
+ if (wMsg == WM_CREATE)
+ return MCIWND_Create(hWnd, (CREATESTRUCTW *)lParam);
+
return DefWindowProcW(hWnd, wMsg, wParam, lParam);
+ }
switch (wMsg)
{
@@ -362,11 +425,14 @@ static LRESULT WINAPI MCIWndProc(HWND hW
if (mwi->uTimer)
KillTimer(hWnd, mwi->uTimer);
- SendMessageW(hWnd, MCI_CLOSE, 0, 0);
+ if (mwi->mci)
+ SendMessageW(hWnd, MCI_CLOSE, 0, 0);
- if (mwi->lpName)
- HeapFree(GetProcessHeap(), 0, mwi->lpName);
HeapFree(GetProcessHeap(), 0, mwi);
+
+ DestroyWindow(GetDlgItem(hWnd, CTL_MENU));
+ DestroyWindow(GetDlgItem(hWnd, CTL_PLAYSTOP));
+ DestroyWindow(GetDlgItem(hWnd, CTL_TRACKBAR));
return 0;
case WM_PAINT:
@@ -374,38 +440,46 @@ static LRESULT WINAPI MCIWndProc(HWND hW
HDC hdc;
PAINTSTRUCT ps;
- hdc = (wParam) ? (HDC)wParam : BeginPaint(mwi->hWnd, &ps);
+ hdc = (wParam) ? (HDC)wParam : BeginPaint(hWnd, &ps);
/* something to do ? */
- if (!wParam) EndPaint(mwi->hWnd, &ps);
+ if (!wParam) EndPaint(hWnd, &ps);
return 1;
}
case WM_COMMAND:
return MCIWND_Command(mwi, wParam, lParam);
+ case WM_NCACTIVATE:
+ if (mwi->uTimer)
+ {
+ KillTimer(hWnd, mwi->uTimer);
+ mwi->uTimer = SetTimer(hWnd, 1, wParam ? mwi->active_timer : mwi->inactive_timer, NULL);
+ }
+ break;
+
case WM_TIMER:
- MCIWND_Timer(mwi);
+ MCIWND_UpdateState(mwi);
return 0;
case WM_SIZE:
{
- MCIWND_NOTIFY_SIZE(mwi);
-
- if (wParam == SIZE_MINIMIZED) return 0;
-
SetWindowPos(GetDlgItem(hWnd, CTL_PLAYSTOP), 0, 0, HIWORD(lParam) - 32, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE);
SetWindowPos(GetDlgItem(hWnd, CTL_MENU), 0, 32, HIWORD(lParam) - 32, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE);
SetWindowPos(GetDlgItem(hWnd, CTL_TRACKBAR), 0, 64, HIWORD(lParam) - 32, LOWORD(lParam) - 64, 32, SWP_NOACTIVATE);
+
+ MCIWND_NOTIFY_SIZE(mwi);
return 0;
}
case MM_MCINOTIFY:
MCIWND_NOTIFY_MODE(mwi);
+ MCIWND_UpdateState(mwi);
return 0;
case MCIWNDM_OPENA:
{
UNICODE_STRING nameW;
+ TRACE("MCIWNDM_OPENA %s\n", debugstr_a((LPSTR)lParam));
RtlCreateUnicodeStringFromAsciiz(&nameW, (LPCSTR)lParam);
lParam = (LPARAM)nameW.Buffer;
}
@@ -413,6 +487,22 @@ static LRESULT WINAPI MCIWndProc(HWND hW
case MCIWNDM_OPENW:
{
RECT rc;
+ HCURSOR hCursor;
+ MCI_OPEN_PARMSW mci_open;
+ MCI_GETDEVCAPS_PARMS mci_devcaps;
+ WCHAR aliasW[64];
+ WCHAR drv_name[MAX_PATH];
+ static const WCHAR formatW[] = {'%','d',0};
+ static const WCHAR mci32W[] = {'m','c','i','3','2',0};
+ static const WCHAR system_iniW[] = {'s','y','s','t','e','m','.','i','n','i',0};
+
+ TRACE("MCIWNDM_OPENW %s\n", debugstr_w((LPWSTR)lParam));
+
+ if (wParam == MCIWNDOPENF_NEW)
+ {
+ SendMessageW(hWnd, MCIWNDM_NEWW, 0, lParam);
+ goto end_of_mci_open;
+ }
if (mwi->uTimer)
{
@@ -420,83 +510,97 @@ static LRESULT WINAPI MCIWndProc(HWND hW
mwi->uTimer = 0;
}
- if (lParam)
+ hCursor = LoadCursorW(0, (LPWSTR)IDC_WAIT);
+ hCursor = SetCursor(hCursor);
+
+ mci_open.lpstrElementName = (LPWSTR)lParam;
+ wsprintfW(aliasW, formatW, (int)hWnd + 1);
+ mci_open.lpstrAlias = aliasW;
+ mwi->lasterror = mciSendCommandW(mwi->mci, MCI_OPEN,
+ MCI_OPEN_ELEMENT | MCI_OPEN_ALIAS | MCI_WAIT,
+ (DWORD_PTR)&mci_open);
+ SetCursor(hCursor);
+
+ if (mwi->lasterror)
{
- HCURSOR hCursor;
- MCI_OPEN_PARMSW mci_open;
- MCI_GETDEVCAPS_PARMS mci_devcaps;
-
- hCursor = LoadCursorW(0, (LPWSTR)IDC_WAIT);
- hCursor = SetCursor(hCursor);
-
- mci_open.lpstrElementName = (LPWSTR)lParam;
- mwi->lasterror = mciSendCommandW(mwi->mci, MCI_OPEN,
- MCI_OPEN_ELEMENT | MCI_WAIT,
- (DWORD_PTR)&mci_open);
- SetCursor(hCursor);
+ /* FIXME: get the caption from resources */
+ static const WCHAR caption[] = {'M','C','I',' ','E','r','r','o','r',0};
+ WCHAR error_str[MAXERRORLENGTH];
- if (mwi->lasterror)
- {
- /* FIXME: get the caption from resources */
- static const WCHAR caption[] = {'M','C','I',' ','E','r','r','o','r',0};
- WCHAR error_str[MAXERRORLENGTH];
+ mciGetErrorStringW(mwi->lasterror, error_str, MAXERRORLENGTH);
+ MessageBoxW(hWnd, error_str, caption, MB_ICONEXCLAMATION | MB_OK);
+ MCIWND_NOTIFY_ERROR(mwi);
+ goto end_of_mci_open;
+ }
- mciGetErrorStringW(mwi->lasterror, error_str, MAXERRORLENGTH);
- MessageBoxW(hWnd, error_str, caption, MB_ICONEXCLAMATION | MB_OK);
- MCIWND_NOTIFY_ERROR(mwi);
- goto end_of_mci_open;
- }
+ mwi->mci = mci_open.wDeviceID;
+ mwi->alias = (int)hWnd + 1;
+ mwi->lpName = HeapAlloc(GetProcessHeap(), 0, (strlenW((LPWSTR)lParam) + 1) * sizeof(WCHAR));
+ strcpyW(mwi->lpName, (LPWSTR)lParam);
+
+ MCIWND_UpdateState(mwi);
+
+ mci_devcaps.dwItem = MCI_GETDEVCAPS_DEVICE_TYPE;
+ mwi->lasterror = mciSendCommandW(mwi->mci, MCI_GETDEVCAPS,
+ MCI_GETDEVCAPS_ITEM,
+ (DWORD_PTR)&mci_devcaps);
+ if (mwi->lasterror)
+ {
+ MCIWND_NOTIFY_ERROR(mwi);
+ goto end_of_mci_open;
+ }
+
+ mwi->dev_type = mci_devcaps.dwReturn;
+
+ drv_name[0] = 0;
+ SendMessageW(hWnd, MCIWNDM_GETDEVICEW, 256, (LPARAM)drv_name);
+ if (drv_name[0] && GetPrivateProfileStringW(mci32W, drv_name, NULL,
+ drv_name, MAX_PATH, system_iniW))
+ mwi->hdrv = OpenDriver(drv_name, NULL, 0);
+
+ if (mwi->dev_type == MCI_DEVTYPE_DIGITAL_VIDEO)
+ {
+ MCI_DGV_WINDOW_PARMSW mci_window;
- mwi->mci = mci_open.wDeviceID;
- mwi->lpName = HeapAlloc(GetProcessHeap(), 0, (strlenW((LPWSTR)lParam) + 1) * sizeof(WCHAR));
- strcpyW(mwi->lpName, (LPWSTR)lParam);
-
- mci_devcaps.dwItem = MCI_GETDEVCAPS_DEVICE_TYPE;
- mwi->lasterror = mciSendCommandW(mwi->mci, MCI_GETDEVCAPS,
- MCI_GETDEVCAPS_ITEM,
- (DWORD_PTR)&mci_devcaps);
+ mci_window.hWnd = hWnd;
+ mwi->lasterror = mciSendCommandW(mwi->mci, MCI_WINDOW,
+ MCI_DGV_WINDOW_HWND,
+ (DWORD_PTR)&mci_window);
if (mwi->lasterror)
{
MCIWND_NOTIFY_ERROR(mwi);
goto end_of_mci_open;
}
+ }
- mwi->dev_type = mci_devcaps.dwReturn;
-
- if (mwi->dev_type == MCI_DEVTYPE_DIGITAL_VIDEO)
- {
- MCI_DGV_WINDOW_PARMSW mci_window;
+ if (SendMessageW(hWnd, MCIWNDM_GET_DEST, 0, (LPARAM)&rc) == 0)
+ {
+ mwi->size.cx = rc.right - rc.left;
+ mwi->size.cy = rc.bottom - rc.top;
- mci_window.hWnd = hWnd;
- mwi->lasterror = mciSendCommandW(mwi->mci, MCI_WINDOW,
- MCI_DGV_WINDOW_HWND,
- (DWORD_PTR)&mci_window);
- if (mwi->lasterror)
- {
- MCIWND_NOTIFY_ERROR(mwi);
- goto end_of_mci_open;
- }
- }
+ rc.right = MulDiv(mwi->size.cx, mwi->zoom, 100);
+ rc.bottom = MulDiv(mwi->size.cy, mwi->zoom, 100);
+ SendMessageW(hWnd, MCIWNDM_PUT_DEST, 0, (LPARAM)&rc);
}
-
- if (SendMessageW(hWnd, MCIWNDM_GET_DEST, 0, (LPARAM)&rc) != 0)
+ else
{
GetClientRect(hWnd, &rc);
rc.bottom = rc.top;
}
- AdjustWindowRect(&rc, GetWindowLongW(hWnd, GWL_STYLE), FALSE);
if (!(mwi->dwStyle & MCIWNDF_NOPLAYBAR))
rc.bottom += 32; /* add the height of the playbar */
+ AdjustWindowRect(&rc, GetWindowLongW(hWnd, GWL_STYLE), FALSE);
SetWindowPos(hWnd, 0, 0, 0, rc.right - rc.left,
- rc.bottom - rc.top, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
-
- MCIWND_NOTIFY_MEDIA(mwi);
+ rc.bottom - rc.top, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
SendDlgItemMessageW(hWnd, CTL_TRACKBAR, TBM_SETRANGEMIN, 0L, 0L);
- SendDlgItemMessageW(hWnd, CTL_TRACKBAR, TBM_SETRANGEMAX, 1L, SendMessageW(mwi->hWnd, MCIWNDM_GETLENGTH, 0, 0));
- SetTimer(hWnd, 1, 500, NULL);
+ SendDlgItemMessageW(hWnd, CTL_TRACKBAR, TBM_SETRANGEMAX, 1,
+ SendMessageW(hWnd, MCIWNDM_GETLENGTH, 0, 0));
+ mwi->uTimer = SetTimer(hWnd, 1, mwi->active_timer, NULL);
+
+ MCIWND_NOTIFY_MEDIA(mwi);
end_of_mci_open:
if (wMsg == MCIWNDM_OPENA)
@@ -507,6 +611,9 @@ end_of_mci_open:
case MCIWNDM_GETDEVICEID:
return mwi->mci;
+ case MCIWNDM_GETALIAS:
+ return mwi->alias;
+
case MCIWNDM_GET_SOURCE:
{
MCI_DGV_RECT_PARMS mci_rect;
@@ -561,7 +668,7 @@ end_of_mci_open:
mci_put.rc = *(RECT *)lParam;
mwi->lasterror = mciSendCommandW(mwi->mci, MCI_PUT,
- MCI_DGV_PUT_DESTINATION,
+ MCI_DGV_PUT_DESTINATION | MCI_DGV_RECT,
(DWORD_PTR)&mci_put);
if (mwi->lasterror)
{
@@ -617,15 +724,37 @@ end_of_mci_open:
{
MCI_STATUS_PARMS mci_status;
+ /* get position string if requested */
+ if (wParam && lParam)
+ {
+ if (wMsg == MCIWNDM_GETPOSITIONA)
+ {
+ char cmd[64];
+
+ wsprintfA(cmd, "status %d position", mwi->alias);
+ mwi->lasterror = mciSendStringA(cmd, (LPSTR)lParam, wParam, 0);
+ }
+ else
+ {
+
+ WCHAR cmdW[64];
+ static const WCHAR formatW[] = {'s','t','a','t','u','s',' ','%','d',' ','p','o','s','i','t','i','o','n',0};
+
+ wsprintfW(cmdW, formatW, mwi->alias);
+ mwi->lasterror = mciSendStringW(cmdW, (LPWSTR)lParam, wParam, 0);
+ }
+
+ if (mwi->lasterror)
+ return 0;
+ }
+
mci_status.dwItem = MCI_STATUS_POSITION;
mwi->lasterror = mciSendCommandW(mwi->mci, MCI_STATUS,
MCI_STATUS_ITEM,
(DWORD_PTR)&mci_status);
if (mwi->lasterror)
- {
- MCIWND_NOTIFY_ERROR(mwi);
return 0;
- }
+
return mci_status.dwReturn;
}
@@ -634,6 +763,33 @@ end_of_mci_open:
{
MCI_STATUS_PARMS mci_status;
+ if (!mwi->mci)
+ return MCI_MODE_NOT_READY;
+
+ /* get mode string if requested */
+ if (wParam && lParam)
+ {
+ if (wMsg == MCIWNDM_GETMODEA)
+ {
+ char cmd[64];
+
+ wsprintfA(cmd, "status %d mode", mwi->alias);
+ mwi->lasterror = mciSendStringA(cmd, (LPSTR)lParam, wParam, 0);
+ }
+ else
+ {
+
+ WCHAR cmdW[64];
+ static const WCHAR formatW[] = {'s','t','a','t','u','s',' ','%','d',' ','m','o','d','e',0};
+
+ wsprintfW(cmdW, formatW, mwi->alias);
+ mwi->lasterror = mciSendStringW(cmdW, (LPWSTR)lParam, wParam, 0);
+ }
+
+ if (mwi->lasterror)
+ return MCI_MODE_NOT_READY;
+ }
+
mci_status.dwItem = MCI_STATUS_MODE;
mwi->lasterror = mciSendCommandW(mwi->mci, MCI_STATUS,
MCI_STATUS_ITEM,
@@ -644,6 +800,26 @@ end_of_mci_open:
return mci_status.dwReturn;
}
+ case MCIWNDM_PLAYFROM:
+ {
+ MCI_PLAY_PARMS mci_play;
+
+ mci_play.dwCallback = (DWORD_PTR)hWnd;
+ mci_play.dwFrom = lParam;
+ mwi->lasterror = mciSendCommandW(mwi->mci, MCI_PLAY,
+ MCI_FROM | MCI_NOTIFY,
+ (DWORD_PTR)&mci_play);
+ if (mwi->lasterror)
+ {
+ MCIWND_NOTIFY_ERROR(mwi);
+ return mwi->lasterror;
+ }
+
+ MCIWND_NOTIFY_MODE(mwi);
+ MCIWND_UpdateState(mwi);
+ return 0;
+ }
+
case MCIWNDM_PLAYTO:
{
MCI_PLAY_PARMS mci_play;
@@ -651,20 +827,67 @@ end_of_mci_open:
mci_play.dwCallback = (DWORD_PTR)hWnd;
mci_play.dwTo = lParam;
mwi->lasterror = mciSendCommandW(mwi->mci, MCI_PLAY,
- MCI_TO | MCI_NOTIFY, (DWORD_PTR)&mci_play);
+ MCI_TO | MCI_NOTIFY,
+ (DWORD_PTR)&mci_play);
if (mwi->lasterror)
{
MCIWND_NOTIFY_ERROR(mwi);
return mwi->lasterror;
}
+
+ MCIWND_NOTIFY_MODE(mwi);
+ MCIWND_UpdateState(mwi);
return 0;
}
- case MCIWNDM_RETURNSTRINGA:
+
+ case MCIWNDM_PLAYREVERSE:
+ {
+ MCI_PLAY_PARMS mci_play;
+ DWORD flags = MCI_NOTIFY;
+
+ mci_play.dwCallback = (DWORD_PTR)hWnd;
+ mci_play.dwFrom = lParam;
+ switch (mwi->dev_type)
+ {
+ default:
+ case MCI_DEVTYPE_ANIMATION:
+ flags |= MCI_ANIM_PLAY_REVERSE;
+ break;
+
+ case MCI_DEVTYPE_DIGITAL_VIDEO:
+ flags |= MCI_DGV_PLAY_REVERSE;
+ break;
+
+#ifdef MCI_VCR_PLAY_REVERSE
+ case MCI_DEVTYPE_VCR:
+ flags |= MCI_VCR_PLAY_REVERSE;
+ break;
+#endif
+
+ case MCI_DEVTYPE_VIDEODISC:
+ flags |= MCI_VD_PLAY_REVERSE;
+ break;
+
+ }
+ mwi->lasterror = mciSendCommandW(mwi->mci, MCI_PLAY,
+ flags, (DWORD_PTR)&mci_play);
+ if (mwi->lasterror)
+ {
+ MCIWND_NOTIFY_ERROR(mwi);
+ return mwi->lasterror;
+ }
+
+ MCIWND_NOTIFY_MODE(mwi);
+ MCIWND_UpdateState(mwi);
+ return 0;
+ }
+
+ case MCIWNDM_GETERRORA:
mciGetErrorStringA(mwi->lasterror, (LPSTR)lParam, wParam);
return mwi->lasterror;
- case MCIWNDM_RETURNSTRINGW:
+ case MCIWNDM_GETERRORW:
mciGetErrorStringW(mwi->lasterror, (LPWSTR)lParam, wParam);
return mwi->lasterror;
@@ -672,27 +895,292 @@ end_of_mci_open:
mwi->hwndOwner = (HWND)wParam;
return 0;
- case MCI_PLAY:
+ case MCIWNDM_SENDSTRINGA:
{
- LRESULT end = SendMessageW(hWnd, MCIWNDM_GETEND, 0, 0);
- return SendMessageW(hWnd, MCIWNDM_PLAYTO, 0, end);
+ UNICODE_STRING stringW;
+ RtlCreateUnicodeStringFromAsciiz(&stringW, (LPCSTR)lParam);
+ lParam = (LPARAM)stringW.Buffer;
}
+ /* fall through */
+ case MCIWNDM_SENDSTRINGW:
+ {
+ WCHAR *cmdW, *p;
- case MCI_STOP:
+ p = strchrW((LPCWSTR)lParam, ' ');
+ if (p)
+ {
+ static const WCHAR formatW[] = {'%','d',' ',0};
+ int len, pos;
+
+ pos = p - (WCHAR *)lParam + 1;
+ len = lstrlenW((LPCWSTR)lParam) + 64;
+
+ cmdW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+
+ memcpy(cmdW, (void *)lParam, pos * sizeof(WCHAR));
+ wsprintfW(cmdW + pos, formatW, mwi->alias);
+ strcatW(cmdW, (WCHAR *)lParam + pos);
+ }
+ else
+ cmdW = (LPWSTR)lParam;
+
+ mwi->lasterror = mciSendStringW(cmdW, mwi->return_string,
+ sizeof(mwi->return_string)/sizeof(mwi->return_string[0]),
+ 0);
+ if (mwi->lasterror)
+ MCIWND_NOTIFY_ERROR(mwi);
+
+ if (cmdW != (LPWSTR)lParam)
+ HeapFree(GetProcessHeap(), 0, cmdW);
+
+ if (wMsg == MCIWNDM_SENDSTRINGA)
+ HeapFree(GetProcessHeap(), 0, (void *)lParam);
+
+ MCIWND_UpdateState(mwi);
+ return mwi->lasterror;
+ }
+
+ case MCIWNDM_RETURNSTRINGA:
+ WideCharToMultiByte(CP_ACP, 0, mwi->return_string, -1, (LPSTR)lParam, wParam, NULL, NULL);
+ return mwi->lasterror;
+
+ case MCIWNDM_RETURNSTRINGW:
+ strncpyW((LPWSTR)lParam, mwi->return_string, wParam);
+ return mwi->lasterror;
+
+ case MCIWNDM_SETTIMERS:
+ mwi->active_timer = (WORD)wParam;
+ mwi->inactive_timer = (WORD)lParam;
+ return 0;
+
+ case MCIWNDM_SETACTIVETIMER:
+ mwi->active_timer = (WORD)wParam;
+ return 0;
+
+ case MCIWNDM_SETINACTIVETIMER:
+ mwi->inactive_timer = (WORD)wParam;
+ return 0;
+
+ case MCIWNDM_GETACTIVETIMER:
+ return mwi->active_timer;
+
+ case MCIWNDM_GETINACTIVETIMER:
+ return mwi->inactive_timer;
+
+ case MCIWNDM_CHANGESTYLES:
+ /* FIXME: update the visual window state as well:
+ * add/remove trackbar, autosize, etc.
+ */
+ mwi->dwStyle &= ~wParam;
+ mwi->dwStyle |= lParam & wParam;
+ return 0;
+
+ case MCIWNDM_GETSTYLES:
+ return mwi->dwStyle & 0xffff;
+
+ case MCIWNDM_GETDEVICEA:
{
- MCI_GENERIC_PARMS mci_generic;
+ MCI_SYSINFO_PARMSA mci_sysinfo;
+
+ mci_sysinfo.lpstrReturn = (LPSTR)lParam;
+ mci_sysinfo.dwRetSize = wParam;
+ mwi->lasterror = mciSendCommandA(mwi->mci, MCI_SYSINFO,
+ MCI_SYSINFO_INSTALLNAME,
+ (DWORD_PTR)&mci_sysinfo);
+ return 0;
+ }
+
+ case MCIWNDM_GETDEVICEW:
+ {
+ MCI_SYSINFO_PARMSW mci_sysinfo;
+
+ mci_sysinfo.lpstrReturn = (LPWSTR)lParam;
+ mci_sysinfo.dwRetSize = wParam;
+ mwi->lasterror = mciSendCommandW(mwi->mci, MCI_SYSINFO,
+ MCI_SYSINFO_INSTALLNAME,
+ (DWORD_PTR)&mci_sysinfo);
+ return 0;
+ }
+
+ case MCIWNDM_VALIDATEMEDIA:
+ if (mwi->mci)
+ {
+ SendMessageW(hWnd, MCIWNDM_GETSTART, 0, 0);
+ SendMessageW(hWnd, MCIWNDM_GETLENGTH, 0, 0);
+ }
+ return 0;
+
+ case MCIWNDM_GETFILENAMEA:
+ if (mwi->lpName)
+ WideCharToMultiByte(CP_ACP, 0, mwi->lpName, -1, (LPSTR)lParam, wParam, NULL, NULL);
+ return 0;
- mci_generic.dwCallback = 0;
- mwi->lasterror = mciSendCommandW(mwi->mci, MCI_STOP, 0, (DWORD_PTR)&mci_generic);
+ case MCIWNDM_GETFILENAMEW:
+ if (mwi->lpName)
+ strncpyW((LPWSTR)lParam, mwi->lpName, wParam);
+ return 0;
+
+ case MCIWNDM_GETTIMEFORMATA:
+ case MCIWNDM_GETTIMEFORMATW:
+ {
+ MCI_STATUS_PARMS mci_status;
+
+ /* get format string if requested */
+ if (wParam && lParam)
+ {
+ if (wMsg == MCIWNDM_GETTIMEFORMATA)
+ {
+ char cmd[64];
+
+ wsprintfA(cmd, "status %d time format", mwi->alias);
+ mwi->lasterror = mciSendStringA(cmd, (LPSTR)lParam, wParam, 0);
+ if (mwi->lasterror)
+ return 0;
+ }
+ else
+ {
+ WCHAR cmdW[64];
+ static const WCHAR formatW[] = {'s','t','a','t','u','s',' ','%','d',' ','t','i','m','e',' ','f','o','r','m','a','t',0};
+
+ wsprintfW(cmdW, formatW, mwi->alias);
+ mwi->lasterror = mciSendStringW(cmdW, (LPWSTR)lParam, wParam, 0);
+ if (mwi->lasterror)
+ return 0;
+ }
+ }
+ mci_status.dwItem = MCI_STATUS_TIME_FORMAT ;
+ mwi->lasterror = mciSendCommandW(mwi->mci, MCI_STATUS,
+ MCI_STATUS_ITEM,
+ (DWORD_PTR)&mci_status);
if (mwi->lasterror)
+ return 0;
+
+ return mci_status.dwReturn;
+ }
+
+ case MCIWNDM_SETTIMEFORMATA:
+ {
+ UNICODE_STRING stringW;
+
+ RtlCreateUnicodeStringFromAsciiz(&stringW, (LPCSTR)lParam);
+ lParam = (LPARAM)stringW.Buffer;
+ }
+ /* fall through */
+ case MCIWNDM_SETTIMEFORMATW:
+ {
+ static const WCHAR formatW[] = {'s','e','t',' ','%','d',' ','t','i','m','e',' ','f','o','r','m','a','t',' ',0};
+ WCHAR *cmdW;
+
+ if (mwi->mci)
{
- MCIWND_NOTIFY_ERROR(mwi);
- return mwi->lasterror;
+ cmdW = HeapAlloc(GetProcessHeap(), 0, (lstrlenW((LPCWSTR)lParam) + 64) * sizeof(WCHAR));
+ wsprintfW(cmdW, formatW, mwi->alias);
+ strcatW(cmdW, (WCHAR *)lParam);
+
+ mwi->lasterror = mciSendStringW(cmdW, NULL, 0, 0);
}
+
+ if (wMsg == MCIWNDM_SETTIMEFORMATA)
+ HeapFree(GetProcessHeap(), 0, (void *)lParam);
+
+ /* fix the range tracking according to the new time format */
+ if (!mwi->lasterror)
+ SendDlgItemMessageW(hWnd, CTL_TRACKBAR, TBM_SETRANGEMAX, 1,
+ SendMessageW(hWnd, MCIWNDM_GETLENGTH, 0, 0));
return 0;
}
+ case MCIWNDM_CAN_PLAY:
+ if (mwi->mci)
+ return mci_get_devcaps(mwi, MCI_GETDEVCAPS_CAN_PLAY);
+ return 0;
+
+ case MCIWNDM_CAN_RECORD:
+ if (mwi->mci)
+ return mci_get_devcaps(mwi, MCI_GETDEVCAPS_CAN_RECORD);
+ return 0;
+
+ case MCIWNDM_CAN_SAVE:
+ if (mwi->mci)
+ return mci_get_devcaps(mwi, MCI_GETDEVCAPS_CAN_SAVE);
+ return 0;
+
+ case MCIWNDM_CAN_EJECT:
+ if (mwi->mci)
+ return mci_get_devcaps(mwi, MCI_GETDEVCAPS_CAN_EJECT);
+ return 0;
+
+ case MCIWNDM_CAN_WINDOW:
+ switch (mwi->dev_type)
+ {
+ case MCI_DEVTYPE_ANIMATION:
+ case MCI_DEVTYPE_DIGITAL_VIDEO:
+ case MCI_DEVTYPE_OVERLAY:
+ return 1;
+ }
+ return 0;
+
+ case MCIWNDM_CAN_CONFIG:
+ if (mwi->hdrv)
+ return SendDriverMessage(mwi->hdrv, DRV_QUERYCONFIGURE, 0, 0);
+ return 0;
+
+ case MCIWNDM_SETZOOM:
+ mwi->zoom = lParam;
+
+ if (mwi->mci)
+ {
+ RECT rc;
+
+ SetRectEmpty(&rc);
+ rc.right = MulDiv(mwi->size.cx, mwi->zoom, 100);
+ rc.bottom = MulDiv(mwi->size.cy, mwi->zoom, 100);
+ SendMessageW(hWnd, MCIWNDM_PUT_DEST, 0, (LPARAM)&rc);
+
+ if (!(mwi->dwStyle & MCIWNDF_NOPLAYBAR))
+ rc.bottom += 32; /* add the height of the playbar */
+ AdjustWindowRect(&rc, GetWindowLongW(hWnd, GWL_STYLE), FALSE);
+ SetWindowPos(hWnd, 0, 0, 0, rc.right - rc.left, rc.bottom - rc.top,
+ SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
+ }
+ return 0;
+
+ case MCIWNDM_GETZOOM:
+ return mwi->zoom;
+
+ case MCIWNDM_EJECT:
+ {
+ MCI_SET_PARMS mci_set;
+
+ mwi->lasterror = mciSendCommandW(mwi->mci, MCI_SET,
+ MCI_SET_DOOR_OPEN | MCI_NOTIFY,
+ (DWORD_PTR)&mci_set);
+ return mwi->lasterror;
+ }
+
+ case MCIWNDM_SETVOLUME:
+ case MCIWNDM_GETVOLUME:
+ case MCIWNDM_SETSPEED:
+ case MCIWNDM_GETSPEED:
+ case MCIWNDM_SETREPEAT:
+ case MCIWNDM_GETREPEAT:
+ case MCIWNDM_REALIZE:
+ case MCIWNDM_GETPALETTE:
+ case MCIWNDM_SETPALETTE:
+ case MCIWNDM_NEWA:
+ case MCIWNDM_NEWW:
+ case MCIWNDM_PALETTEKICK:
+ case MCIWNDM_OPENINTERFACE:
+ FIXME("support for MCIWNDM_ message WM_USER+%d not implemented\n", wMsg - WM_USER);
+ return 0;
+
+ case MCI_PLAY:
+ {
+ LRESULT end = SendMessageW(hWnd, MCIWNDM_GETEND, 0, 0);
+ return SendMessageW(hWnd, MCIWNDM_PLAYTO, 0, end);
+ }
+
case MCI_SEEK:
{
MCI_SEEK_PARMS mci_seek;
@@ -721,25 +1209,106 @@ end_of_mci_open:
case MCI_CLOSE:
{
+ RECT rc;
MCI_GENERIC_PARMS mci_generic;
- mci_generic.dwCallback = 0;
- mwi->lasterror = mciSendCommandW(mwi->mci, MCI_CLOSE, 0, (DWORD_PTR)&mci_generic);
+ if (mwi->hdrv)
+ {
+ CloseDriver(mwi->hdrv, 0, 0);
+ mwi->hdrv = 0;
+ }
- if (mwi->lasterror)
+ if (mwi->mci)
{
- MCIWND_NOTIFY_ERROR(mwi);
- return mwi->lasterror;
+ mci_generic.dwCallback = 0;
+ mwi->lasterror = mciSendCommandW(mwi->mci, MCI_CLOSE,
+ 0, (DWORD_PTR)&mci_generic);
+ mwi->mci = 0;
+ }
+
+ mwi->mode = MCI_MODE_NOT_READY;
+ mwi->position = -1;
+
+ if (mwi->lpName)
+ {
+ HeapFree(GetProcessHeap(), 0, mwi->lpName);
+ mwi->lpName = NULL;
}
+ MCIWND_UpdateState(mwi);
+
+ GetClientRect(hWnd, &rc);
+ rc.bottom = rc.top;
+ if (!(mwi->dwStyle & MCIWNDF_NOPLAYBAR))
+ rc.bottom += 32; /* add the height of the playbar */
+ AdjustWindowRect(&rc, GetWindowLongW(hWnd, GWL_STYLE), FALSE);
+ SetWindowPos(hWnd, 0, 0, 0, rc.right - rc.left,
+ rc.bottom - rc.top, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
+
+ MCIWND_NOTIFY_MEDIA(mwi);
return 0;
}
+
+ case MCI_PAUSE:
+ case MCI_STEP:
+ case MCI_STOP:
+ case MCI_RESUME:
+ return mci_generic_command(mwi, wMsg);
+
+ case MCI_CONFIGURE:
+ if (mwi->hdrv)
+ SendDriverMessage(mwi->hdrv, DRV_CONFIGURE, (LPARAM)hWnd, 0);
+ return 0;
+
+ case MCI_BREAK:
+ case MCI_CAPTURE:
+ case MCI_COPY:
+ case MCI_CUE:
+ case MCI_CUT:
+ case MCI_DELETE:
+ case MCI_ESCAPE:
+ case MCI_FREEZE:
+ case MCI_GETDEVCAPS:
+ /*case MCI_INDEX:*/
+ case MCI_INFO:
+ case MCI_LIST:
+ case MCI_LOAD:
+ /*case MCI_MARK:*/
+ case MCI_MONITOR:
+ case MCI_OPEN:
+ case MCI_PASTE:
+ case MCI_PUT:
+ case MCI_QUALITY:
+ case MCI_REALIZE:
+ case MCI_RECORD:
+ case MCI_RESERVE:
+ case MCI_RESTORE:
+ case MCI_SAVE:
+ case MCI_SET:
+ case MCI_SETAUDIO:
+ /*case MCI_SETTIMECODE:*/
+ /*case MCI_SETTUNER:*/
+ case MCI_SETVIDEO:
+ case MCI_SIGNAL:
+ case MCI_SPIN:
+ case MCI_STATUS:
+ case MCI_SYSINFO:
+ case MCI_UNDO:
+ case MCI_UNFREEZE:
+ case MCI_UPDATE:
+ case MCI_WHERE:
+ case MCI_WINDOW:
+ FIXME("support for MCI_ command %04x not implemented\n", wMsg);
+ return 0;
}
- if ((wMsg >= WM_USER) && (wMsg < WM_APP))
+ if (wMsg >= WM_USER)
{
FIXME("support for MCIWNDM_ message WM_USER+%d not implemented\n", wMsg - WM_USER);
return 0;
}
+ if (GetWindowLongW(hWnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
+ return DefMDIChildProcW(hWnd, wMsg, wParam, lParam);
+
return DefWindowProcW(hWnd, wMsg, wParam, lParam);
}
diff -u cvs/hq/wine/include/vfw.h wine/include/vfw.h
--- cvs/hq/wine/include/vfw.h 2003-12-16 16:45:53.000000000 +0800
+++ wine/include/vfw.h 2003-12-30 23:28:23.000000000 +0800
@@ -1290,7 +1290,7 @@ BOOL WINAPI GetSaveFileNamePreviewW(LPOP
#define AVIERR_USERABORT MAKE_AVIERR(198)
#define AVIERR_ERROR MAKE_AVIERR(199)
-BOOL VFWAPIV MCIWndRegisterClass(HINSTANCE);
+BOOL VFWAPIV MCIWndRegisterClass(void);
HWND VFWAPIV MCIWndCreateA(HWND, HINSTANCE, DWORD, LPCSTR);
HWND VFWAPIV MCIWndCreateW(HWND, HINSTANCE, DWORD, LPCWSTR);
More information about the wine-patches
mailing list