I noticed that Wine will crash when loading some codecs that fail to fully initialize the structure ICINFO. According the docs, the drivers are not obliged to supply a value for szDriver in ICINFO. This causes some applications that rely on the value of this field to crash. After some short investigation, I realized that Windows seems to set szDriver equal to the driver's file name. The proposed correction to msvideo_main.c follows. Please notice that, because I made this patch with cvs diff -u, it also shows the corrections in, and therefore supersedes, the patch I sent you yesterday. I appologize for being too lazy to split it up.
Thank you and enjoy,
Waldeck
Index: wine/dlls/msvideo/msvideo_main.c =================================================================== RCS file: /home/wine/wine/dlls/msvideo/msvideo_main.c,v retrieving revision 1.45 diff -u -r1.45 msvideo_main.c --- wine/dlls/msvideo/msvideo_main.c 14 Jan 2003 23:43:42 -0000 1.45 +++ wine/dlls/msvideo/msvideo_main.c 20 Jan 2003 04:35:07 -0000 @@ -29,6 +29,7 @@ #include <string.h> #include "msvideo_private.h" +#include "winnls.h" #include "wingdi.h" #include "winuser.h" @@ -79,13 +80,16 @@ char buf[2000]; TRACE("(%.4s,%.4s,%p)\n", (char*)&fccType, (char*)&fccHandler, lpicinfo); + // The "Case of the missing codecs" + // A fix proposed by Waldeck Schutzer <waldeck@dm.ufscar.br> if (GetPrivateProfileStringA("drivers32", NULL, NULL, buf, sizeof(buf), "system.ini")) { char *s = buf; while (*s) { - if (!strncasecmp((char*)&fccType, s, 4) && s[4] == '.' && s[9] == '=') + if (!strncasecmp((char*)&fccType, s, 4) && s[4] == '.' /* && s[9] == '=' */ ) + // buf is a list of keys, not keys followed by their values! { if (!fccHandler--) { @@ -95,11 +99,16 @@ hic = ICOpen(fccType, lpicinfo->fccHandler, ICMODE_QUERY); if (hic) { + // Some bad codecs can make wine crash right here. + // It would be nice to know why and to find ways + // to preventing it from happening. I can't do it. ICGetInfo(hic, lpicinfo, lpicinfo->dwSize); ICClose(hic); return TRUE; } - return FALSE; + // return FALSE; + // This one failed to open, but keep going down the list! + fccHandler++; } } s += strlen(s) + 1; /* either next char or \0 */ @@ -251,9 +260,29 @@ */ LRESULT VFWAPI ICGetInfo(HIC hic,ICINFO *picinfo,DWORD cb) { LRESULT ret; + char codecname[10]; + char szDriver[128]; TRACE("(%p,%p,%ld)\n",hic,picinfo,cb); + + // The field szDriver should be initialized because the driver is + // not obliged and often do not do so! I have seen crashes due to + // this field going unitialized. + if (picinfo && cb >= sizeof(ICINFO)) + szDriver[0] = 0; // At first, set it to an empty string + ret = ICSendMessage(hic,ICM_GETINFO,(DWORD)picinfo,cb); + + // If szDriver is not supplied by the driver itself, it seems that + // Windows sets its value equal to the driver file name. That can + // be obtained from the registry as we do here. + if (picinfo && cb >= sizeof(ICINFO)) + if (szDriver[0] == 0) { // szDriver not supplied? + sprintf(codecname, "vidc.%.4s", (char*)&(picinfo->fccHandler)); + GetPrivateProfileStringA("drivers32", codecname, "", szDriver, sizeof(szDriver), "system.ini"); + MultiByteToWideChar(CP_ACP, 0, szDriver, -1, picinfo->szDriver, sizeof(picinfo->szDriver)/sizeof(WCHAR)); + } + TRACE(" -> 0x%08lx\n",ret); return ret; }