[prev in list] [next in list] [prev in thread] [next in thread] 

List:       wine-devel
Subject:    Re: WineHQ upgrade breaking dinput8:dinput?
From:       Bernhard_Übelacker <bernhardu () mailbox ! org>
Date:       2016-07-27 0:36:30
Message-ID: 063b9166-ff69-3543-7aa6-7143d0d20e24 () mailbox ! org
[Download RAW message or body]

Hello Francois,
"DirectX Software Development Kit" offers in
"DirectX Control Panel" to increase the
"Debug Output Level".

That way one can get another hint from dinput:
DINPUT8: ERROR IDirectInput8::EnumDevicesBySemantics: arg 2: invalid UNICODE string 

First I tried to build a dinput8.dll that just dumps the
data it gets from dinput-mini.exe, but could not
find any difference.

So I did some tests with DIACTIONA.lptszActionName member.

When the two last characters get replaced by \0 no fault
is reported anymore.
That way a succeeding exe and the failing differ (nearly)
just in the two replaced bytes in lptszActionName.

Therefore can we assume that it is not the compilers
fault, instead it uncovered a hidden bug either in
the test or dinput?

Kind regards,
Bernhard



dinput.c:
-  { 4, DIMOUSE_YAXIS,                               0, { "Y Axis" }  }
+  { 4, DIMOUSE_YAXIS,                               0, { "Y Ax\0\0" }  }



Am 17.07.2016 um 21:02 schrieb Bernhard Übelacker:
> Hello,
> just tried to find out when this started exactly.
> 
> 
> First by using old packages from snapshot.debian.org.
> That revealed it started between packages:
> gcc-mingw-w64-i686_4.6.4-4+9_i386.deb
> gcc-mingw-w64-i686_4.8.2-5+10_i386.deb
> 
> 
> A git bisect of gcc history points to this commit:
> https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=ff2a5adaa72fef87cac689a40c23258a30b304c8
>  
> 
> ff2a5adaa72fef87cac689a40c23258a30b304c8 is the first bad commit
> commit ff2a5adaa72fef87cac689a40c23258a30b304c8
> Author: hubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
> Date:   Sun Apr 22 21:28:07 2012 +0000
> 
> * lto-symtab.c (lto_varpool_replace_node): Do not merge needed flags.
> (...much longer commit message...)    
> 
> git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@186687 \
> 138bc75d-0d04-0410-961f-82ee72b054a4 
> > 040000 040000 d706bdeafbddb9f5f02474e39a245dca08f3334a \
> > 508082a31919fe9e907f70b3b3278d4f8d953fac M      gcc
> 
> 
> 
> Testbot runs:
> Good: (gcc 62c34bf, last one before ff2a5ad)
> https://testbot.winehq.org/JobDetails.pl?Key=24283
> Bad:  (gcc ff2a5ad)
> https://testbot.winehq.org/JobDetails.pl?Key=24280
> 
> 
> 
> Hope this could be of any help to identify the issue.
> 
> 
> Kind regards,
> Bernhard
> 
> 
> Notes:
> - Did not install gcc build system wide. Instead set the PATH
> that i686-w64-mingw32-gcc was taken from there.
> - Initial wine configure step was done using Jessie default
> gcc-mingw-w64-i686 4.9.1-19+14.3.
> Then the iterations were just done by removing objects
> from dlls/dinput8/tests and make dinput8_crosstest.exe.
> - GCC history before 1e37e371 did segfault while building,
> therefore started from there.
> 
> 
> 
> 
> Am 24.04.2016 um 20:30 schrieb Francois Gouget:
> > 
> > I have rechecked this to make sure the test does not have a subtle bug 
> > that causes it to depend on the stack layout.
> > 
> > 
> > In the process I have reduced the test to the minimum set necessary to 
> > reproduce the bug (see attachment). But in the end I did not find 
> > anything wrong so it does look like a compiler bug.
> > 
> > I don't know how to proceed from there.
> > 
> > * I think it would be better if someone more knowlegeable than me 
> > reported this bug to the MinGW guys. Maybe someone who could undertand 
> > what happens in the assembly code?
> > 
> > * On the Wine side it would really be nice to get this test (and 
> > the three others that are impacted) to stop failing. But removing all 
> > the static directives really does not feel right. Would it be better 
> > to arrange for these tests to be compiled with -O0? Any other cleaner 
> > workaround.
> > 
> > So I'm really hoping someone can step up and move this forward.
> > 
> > 
> > Here are the relevant bugs:
> > * dinput8:dinput regression caused by new compiler
> > https://bugs.winehq.org/show_bug.cgi?id=40384
> > 
> > * usp10:usp10 regression caused by new cross-compiler
> > https://bugs.winehq.org/show_bug.cgi?id=40385
> > 
> > * wininet:url regression caused by new cross-compiler
> > https://bugs.winehq.org/show_bug.cgi?id=40386
> > 
> > * Unexplained new random comctl32:header failure (cross-compiler issue?)
> > https://bugs.winehq.org/show_bug.cgi?id=40442
> > 
> > 
> > 
> > 
> 
> 
> 


["libtest.c" (text/x-csrc)]

/*
i686-w64-mingw32-gcc -shared -Wl,--exclude-all-symbols -Wl,--kill-at \
/home/bernhard/data/entwicklung/2016/wine/mingw-dinput/2016-07-16/wine-build/dlls/dinput8/libdinput8.def \
                libtest.c -o dinput8.dll -g -O3
*/


#include <stdio.h>

void* malloc(unsigned int);

typedef unsigned int DWORD, *PDWORD, *LPDWORD;
typedef unsigned long UINT_PTR, *PUINT_PTR;
typedef char CHAR, *PCHAR;
typedef const CHAR *PCSTR, *LPCSTR;
typedef unsigned int UINT, *PUINT;
typedef int LONG, *PLONG;
typedef struct HINSTANCE__ { int unused; } *HINSTANCE;
typedef LONG HRESULT;
typedef unsigned int ULONG, *PULONG;
typedef int BOOL, *PBOOL, *LPBOOL;
typedef unsigned short WORD, *PWORD, *LPWORD;
typedef void *LPVOID;
typedef struct HWND__ { int unused; } *HWND;
typedef CHAR *PSTR, *LPSTR, *NPSTR;
typedef DWORD D3DCOLOR;

typedef struct IUnknown IUnknown;
typedef IUnknown *LPUNKNOWN;

typedef struct _FILETIME {
    DWORD dwLowDateTime;
    DWORD dwHighDateTime;
} FILETIME, *PFILETIME, *LPFILETIME;

typedef struct _GUID
{
    unsigned int Data1;
    unsigned short Data2;
    unsigned short Data3;
    unsigned char Data4[ 8 ];
} GUID;
typedef GUID IID,*LPIID;
typedef GUID *LPGUID;

typedef struct _DIACTIONA {
 UINT_PTR uAppData;
 DWORD dwSemantic;
 DWORD dwFlags;
 union {
  LPCSTR lptszActionName;
  UINT uResIdString;
 } ;
 GUID guidInstance;
 DWORD dwObjID;
 DWORD dwHow;
} DIACTIONA, *LPDIACTIONA;

typedef struct _DIACTIONFORMATA {
 DWORD dwSize;
 DWORD dwActionSize;
 DWORD dwDataSize;
 DWORD dwNumActions;
 LPDIACTIONA rgoAction;
 GUID guidActionMap;
 DWORD dwGenre;
 DWORD dwBufferSize;
 LONG lAxisMin;
 LONG lAxisMax;
 HINSTANCE hInstString;
 FILETIME ftTimeStamp;
 DWORD dwCRC;
 CHAR tszActionMap[260];
} DIACTIONFORMATA, *LPDIACTIONFORMATA;
typedef const DIACTIONFORMATA *LPCDIACTIONFORMATA;

typedef struct _DICOLORSET {
 DWORD dwSize;
 D3DCOLOR cTextFore;
 D3DCOLOR cTextHighlight;
 D3DCOLOR cCalloutLine;
 D3DCOLOR cCalloutHighlight;
 D3DCOLOR cBorder;
 D3DCOLOR cControlFill;
 D3DCOLOR cHighlightFill;
 D3DCOLOR cAreaFill;
} DICOLORSET, *LPDICOLORSET;
typedef const DICOLORSET *LPCDICOLORSET;

typedef struct _DICONFIGUREDEVICESPARAMSA {
 DWORD dwSize;
 DWORD dwcUsers;
 LPSTR lptszUserNames;
 DWORD dwcFormats;
 LPDIACTIONFORMATA lprgFormats;
 HWND hwnd;
 DICOLORSET dics;
 LPUNKNOWN lpUnkDDSTarget;
} DICONFIGUREDEVICESPARAMSA, *LPDICONFIGUREDEVICESPARAMSA;
typedef const DICONFIGUREDEVICESPARAMSA *LPCDICONFIGUREDEVICESPARAMSA;

typedef struct IDirectInputDevice8A *LPDIRECTINPUTDEVICE8A;

typedef struct DIDEVICEINSTANCEA {
    DWORD dwSize;
    GUID guidInstance;
    GUID guidProduct;
    DWORD dwDevType;
    CHAR tszInstanceName[260];
    CHAR tszProductName[260];
    GUID guidFFDriver;
    WORD wUsagePage;
    WORD wUsage;
} DIDEVICEINSTANCEA, *LPDIDEVICEINSTANCEA;
typedef const DIDEVICEINSTANCEA *LPCDIDEVICEINSTANCEA;

typedef BOOL (__attribute__((__stdcall__)) \
*LPDIENUMDEVICESCALLBACKA)(LPCDIDEVICEINSTANCEA,LPVOID); typedef BOOL \
(__attribute__((__stdcall__)) *LPDICONFIGUREDEVICESCALLBACK)(LPUNKNOWN,LPVOID); \
typedef BOOL (__attribute__((__stdcall__)) \
*LPDIENUMDEVICESBYSEMANTICSCBA)(LPCDIDEVICEINSTANCEA,LPDIRECTINPUTDEVICE8A,DWORD,DWORD,LPVOID);


typedef struct IDirectInput8A { const struct IDirectInput8AVtbl *lpVtbl; } \
IDirectInput8A; typedef struct IDirectInput8AVtbl IDirectInput8AVtbl; struct \
IDirectInput8AVtbl {

    HRESULT (__attribute__((__stdcall__)) *QueryInterface)(IDirectInput8A *This, \
const IID* const riid, void** ppvObject) ;  ULONG (__attribute__((__stdcall__)) \
*AddRef)(IDirectInput8A *This) ;  ULONG (__attribute__((__stdcall__)) \
*Release)(IDirectInput8A *This) ;

    HRESULT (__attribute__((__stdcall__)) *CreateDevice)(IDirectInput8A *This, const \
GUID* const rguid, LPDIRECTINPUTDEVICE8A *lplpDirectInputDevice, LPUNKNOWN pUnkOuter) \
;  HRESULT (__attribute__((__stdcall__)) *EnumDevices)(IDirectInput8A *This, DWORD \
dwDevType, LPDIENUMDEVICESCALLBACKA lpCallback, LPVOID pvRef, DWORD dwFlags) ;  \
HRESULT (__attribute__((__stdcall__)) *GetDeviceStatus)(IDirectInput8A *This, const \
GUID* const rguidInstance) ;  HRESULT (__attribute__((__stdcall__)) \
*RunControlPanel)(IDirectInput8A *This, HWND hwndOwner, DWORD dwFlags) ;  HRESULT \
(__attribute__((__stdcall__)) *Initialize)(IDirectInput8A *This, HINSTANCE hinst, \
DWORD dwVersion) ;  HRESULT (__attribute__((__stdcall__)) *FindDevice)(IDirectInput8A \
*This, const GUID* const rguid, LPCSTR pszName, LPGUID pguidInstance) ;  HRESULT \
(__attribute__((__stdcall__)) *EnumDevicesBySemantics)(IDirectInput8A *This, LPCSTR \
ptszUserName, LPDIACTIONFORMATA lpdiActionFormat, LPDIENUMDEVICESBYSEMANTICSCBA \
lpCallback, LPVOID pvRef, DWORD dwFlags) ;  HRESULT (__attribute__((__stdcall__)) \
*ConfigureDevices)(IDirectInput8A *This, LPDICONFIGUREDEVICESCALLBACK lpdiCallback, \
LPDICONFIGUREDEVICESPARAMSA lpdiCDParams, DWORD dwFlags, LPVOID pvRefData) ; };

HRESULT __attribute__((__stdcall__)) my_EnumDevicesBySemantics(IDirectInput8A *This, \
LPCSTR ptszUserName, LPDIACTIONFORMATA lpdiActionFormat, \
LPDIENUMDEVICESBYSEMANTICSCBA lpCallback, LPVOID pvRef, DWORD dwFlags) {
    fprintf(stderr, "%s:%d:   This=%p, ptszUserName=%p, lpdiActionFormat=%p, \
lpCallback=%p, pvRef=%p, dwFlags=%d\n", __FUNCTION__, __LINE__, This, ptszUserName, \
lpdiActionFormat, lpCallback, pvRef, dwFlags); fflush(stderr);  fprintf(stderr, \
"%s:%d lpdiActionFormat=%p lpdiActionFormat->tszActionMap=%p %s\n", __FUNCTION__, \
__LINE__, lpdiActionFormat, lpdiActionFormat->tszActionMap, \
lpdiActionFormat->tszActionMap); fflush(stderr);  fprintf(stderr, "%s:%d \
lpdiActionFormat=%p lpdiActionFormat->guidActionMap=%p\n", __FUNCTION__, __LINE__, \
lpdiActionFormat, lpdiActionFormat->guidActionMap); fflush(stderr);  {
        unsigned char* x = (unsigned char*) lpdiActionFormat;
        int i;
        fprintf(stderr, "%s:%d lpdiActionFormat->tszActionMap=%s \
sizeof(*lpdiActionFormat)=%d\n", __FUNCTION__, __LINE__, \
lpdiActionFormat->tszActionMap, sizeof(*lpdiActionFormat)); fflush(stderr);  for (i = \
0; i < sizeof(*lpdiActionFormat); i++)  fprintf(stderr, "%2.2x ", x[i]);
        fprintf(stderr, "\n"); fflush(stderr);
    }
    {
        int i, j;
        for (i = 0; i < lpdiActionFormat->dwNumActions; i++) {
            unsigned char* x = (unsigned char*) &lpdiActionFormat->rgoAction[i];
            fprintf(stderr, "%s:%d lpdiActionFormat->rgoAction[%d]=%p \
sizeof(lpdiActionFormat->rgoAction[i])=%d\n", __FUNCTION__, __LINE__, i, \
&lpdiActionFormat->rgoAction[i], sizeof(lpdiActionFormat->rgoAction[i])); \
fflush(stderr);  for (j = 0; j < sizeof(lpdiActionFormat->rgoAction[i]); j++)
                fprintf(stderr, "%2.2x ", x[j]);
            fprintf(stderr, "\n"); fflush(stderr);

            x = (unsigned char*) lpdiActionFormat->rgoAction[i].lptszActionName;
            fprintf(stderr, "%s:%d lpdiActionFormat->rgoAction[i].lptszActionName=%p \
%s\n", __FUNCTION__, __LINE__, lpdiActionFormat->rgoAction[i].lptszActionName, \
lpdiActionFormat->rgoAction[i].lptszActionName); fflush(stderr);  for (j = 0; j < 30; \
j++)  fprintf(stderr, "%2.2x ", x[j]);
            fprintf(stderr, "\n"); fflush(stderr);
        }
    }
    return lpdiActionFormat->dwSize;
}

const IDirectInput8AVtbl myVtbl = { 0, 0, 0, 0, 0, 0, 0, 0, 0, \
my_EnumDevicesBySemantics, 0 };

int __attribute__((__stdcall__)) DirectInput8Create(void * p, int dwVersion, void* \
riid, IDirectInput8A** ppDI, void* punkOuter) {
    fprintf(stderr, "%s:%d ppDI=%p\n", __FUNCTION__, __LINE__, ppDI); fflush(stderr);
    fprintf(stderr, "%s:%d\n", __FUNCTION__, __LINE__); fflush(stderr);
    *ppDI = (IDirectInput8A*)malloc(sizeof(IDirectInput8A));
    fprintf(stderr, "%s:%d\n", __FUNCTION__, __LINE__); fflush(stderr);
    (*ppDI)->lpVtbl = &myVtbl;
    fprintf(stderr, "%s:%d\n", __FUNCTION__, __LINE__); fflush(stderr);
}

int __attribute__((__stdcall__)) DllCanUnloadNow(void)
{
    return 0;
}

int __attribute__((__stdcall__)) DllGetClassObject(void* rclsid, void* riid, void* \
ppv) {
    return 0;
}

int __attribute__((__stdcall__)) DllRegisterServer(void)
{
    return 0;
}

int __attribute__((__stdcall__)) DllUnregisterServer(void)
{
    return 0;
}


["dinput-mini.c" (text/x-csrc)]

/*
 * Copyright (c) 2011 Andrew Nguyen
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

/*

i686-w64-mingw32-gcc -c -o dinput-mini.o \
    /home/bernhard/data/entwicklung/2016/wine/mingw-dinput/wine-git/dlls/dinput8/tests/dinput-mini.c \
                \
    -I. -I/home/bernhard/data/entwicklung/2016/wine/mingw-dinput/wine-git/dlls/dinput8/tests \
                \
    -I../../../include \
                -I/home/bernhard/data/entwicklung/2016/wine/mingw-dinput/wine-git/include \
                \
    -D__WINESRC__ -DWINE_CROSSTEST -g -O3
i686-w64-mingw32-gcc -mconsole -o dinput-mini.exe dinput-mini.o \
    ../../../dlls/dinput8/libdinput8.cross.a \
    ../../../dlls/ole32/libole32.cross.a

Install "DirectX Software Development Kit", 571.7 MB
    a7fa610b1791d873162b9e33007a6777  DXSDK_Jun10.exe

"DirectX Control Panel"
 - tab DirectInput
 - "Debug Output Level" to More
 - "Use Debug Version of DirectInput"
 - OK

Start "Dbgview.exe" from SysinternalsSuite to get output from OutputDebugString.

dinput-mini.exe

The output in Dbgview.exe should now include following lines:
    [3784] test_EnumDevicesBySemantics:93 hr=00000000
    [3784] DINPUT8: ERROR IDirectInput8::EnumDevicesBySemantics: arg 2: invalid \
UNICODE string   [3784] test_EnumDevicesBySemantics:95 hr=80070057

*/

#define DIRECTINPUT_VERSION 0x0800

#define COBJMACROS
#include <initguid.h>
#include <windows.h>
#include <dinput.h>
int __attribute__((__cdecl__)) printf(const char * __restrict__ _Format,...);
int __attribute__((__cdecl__)) sprintf(char * __restrict__ _Dest,const char * \
__restrict__ _Format,...) ; int __attribute__((__cdecl__)) fflush(void/*FILE*/ \
*_File);

#if 1
static const char steer[]   = { 'S','t','e','e','r',0   };    /* fails */
#else
static const char steer[]   = { 'S','t','e', 0,  0, 0   };    /* succeeds */
#endif
static DIACTIONA actionMapping[]=
{
  /* Removing any of these fixes the test */
  { 0, 0x01008A01 /* DIAXIS_DRIVINGR_STEER */,      0, steer   },
  { 1, DIKEYBOARD_SPACE,                            0, { "Missile"  } },
  { 2, DIMOUSE_BUTTON0,                             0, { "Select"   } }
};

static char dbgstr[1000];

static BOOL CALLBACK enum_semantics_callback(const DIDEVICEINSTANCEA *lpddi, \
IDirectInputDevice8A *lpdid, DWORD dwFlags, DWORD dwRemaining, void *context) {
    return DIENUM_STOP;
}

static int test_EnumDevicesBySemantics(void)
{
    IDirectInput8A *pDI;
    HRESULT hr;
    DIACTIONFORMATA diaf;
    const GUID ACTION_MAPPING_GUID = { 0x1, 0x2, 0x3, { 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, \
0xa, 0xb } };

    hr = DirectInput8Create(GetModuleHandleA(NULL), DIRECTINPUT_VERSION, \
&IID_IDirectInput8A, (void **)&pDI, NULL);  if (FAILED(hr))
        return;

    memset (&diaf, 0, sizeof(diaf));
    diaf.dwSize = sizeof(diaf);
    diaf.dwActionSize = sizeof(DIACTIONA);
    diaf.dwNumActions = sizeof(actionMapping) / sizeof(actionMapping[0]);
    diaf.rgoAction = actionMapping;
    diaf.dwDataSize = 4 * diaf.dwNumActions;
    diaf.guidActionMap = ACTION_MAPPING_GUID;
    diaf.dwGenre = 0x01000000; /* DIVIRTUAL_DRIVING_RACE */
    diaf.dwBufferSize = 32;

    sprintf(dbgstr, "%s:%d hr=%08x\n", __FUNCTION__, __LINE__, hr); \
OutputDebugStringA(dbgstr); printf(dbgstr); fflush(NULL);  hr = \
IDirectInput8_EnumDevicesBySemantics(pDI, NULL, &diaf, enum_semantics_callback, NULL, \
DIEDBSFL_ATTACHEDONLY);  sprintf(dbgstr, "%s:%d hr=%08x\n", __FUNCTION__, __LINE__, \
hr); OutputDebugStringA(dbgstr); printf(dbgstr); fflush(NULL);

    return hr;
}

int main()
{
    CoInitialize(NULL);
    return test_EnumDevicesBySemantics();
}


[Attachment #5 (text/plain)]




[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic