From 29a634728d8968cf296ee77e7a2ab4e2b33ec4e5 Mon Sep 17 00:00:00 2001 From: Mikolaj Zalewski Date: Thu, 20 Sep 2007 13:01:06 -0700 Subject: [PATCH] winex11.drv/wintab32: Make wintab strings in winex11.drv Unicode, implement WTInfoW. --- dlls/winex11.drv/winex11.drv.spec | 2 +- dlls/winex11.drv/wintab.c | 93 +++++++++++++++++++++---------- dlls/wintab32/context.c | 87 +++++++++++++++++++++++------ dlls/wintab32/wintab32.c | 4 +- dlls/wintab32/wintab_internal.h | 2 +- 5 files changed, 137 insertions(+), 51 deletions(-) diff --git a/dlls/winex11.drv/winex11.drv.spec b/dlls/winex11.drv/winex11.drv.spec index ad9c9894ed0..05c7f72b9f1 100644 --- a/dlls/winex11.drv/winex11.drv.spec +++ b/dlls/winex11.drv/winex11.drv.spec @@ -119,7 +119,7 @@ @ cdecl AttachEventQueueToTablet(long) X11DRV_AttachEventQueueToTablet @ cdecl GetCurrentPacket(ptr) X11DRV_GetCurrentPacket @ cdecl LoadTabletInfo(long) X11DRV_LoadTabletInfo -@ cdecl WTInfoA(long long ptr) X11DRV_WTInfoA +@ cdecl WTInfoW(long long ptr) X11DRV_WTInfoW # X11 locks @ cdecl -norelay wine_tsx11_lock() diff --git a/dlls/winex11.drv/wintab.c b/dlls/winex11.drv/wintab.c index 3d40955118f..db78a9182d7 100644 --- a/dlls/winex11.drv/wintab.c +++ b/dlls/winex11.drv/wintab.c @@ -22,18 +22,24 @@ #include "wine/port.h" #include +#include #include "windef.h" +#include "winbase.h" +#include "winnls.h" #include "x11drv.h" #include "wine/library.h" +#include "wine/unicode.h" #include "wine/debug.h" #include "wintab.h" WINE_DEFAULT_DEBUG_CHANNEL(wintab32); +#define WT_MAX_NAME_LEN 256 + typedef struct tagWTI_CURSORS_INFO { - CHAR NAME[256]; + WCHAR NAME[WT_MAX_NAME_LEN]; /* a displayable zero-terminated string containing the name of the * cursor. */ @@ -47,7 +53,8 @@ typedef struct tagWTI_CURSORS_INFO /* the number of buttons on this cursor. */ BYTE BUTTONBITS; /* the number of bits of raw button data returned by the hardware.*/ - CHAR BTNNAMES[1024]; /* FIXME: make this dynamic */ + DWORD cchBTNNAMES; + WCHAR *BTNNAMES; /* a list of zero-terminated strings containing the names of the * cursor's buttons. The number of names in the list is the same as the * number of buttons on the cursor. The names are separated by a single @@ -129,7 +136,7 @@ typedef struct tagWTI_CURSORS_INFO typedef struct tagWTI_DEVICES_INFO { - CHAR NAME[256]; + WCHAR NAME[WT_MAX_NAME_LEN]; /* a displayable null- terminated string describing the device, * manufacturer, and revision level. */ @@ -191,7 +198,7 @@ typedef struct tagWTI_DEVICES_INFO /* a 3-element array describing the tablet's rotation range and * resolution capabilities. */ - CHAR PNPID[256]; + WCHAR PNPID[WT_MAX_NAME_LEN]; /* a null-terminated string containing the devices Plug and Play ID.*/ } WTI_DEVICES_INFO, *LPWTI_DEVICES_INFO; @@ -233,7 +240,7 @@ static INT button_state[10]; #define CURSORMAX 10 -static LOGCONTEXTA gSysContext; +static LOGCONTEXTW gSysContext; static WTI_DEVICES_INFO gSysDevice; static WTI_CURSORS_INFO gSysCursor[CURSORMAX]; static INT gNumCursors; @@ -281,6 +288,10 @@ static int Tablet_ErrorHandler(Display *dpy, XErrorEvent *event, void* arg) void X11DRV_LoadTabletInfo(HWND hwnddefault) { + const WCHAR SZ_CONTEXT_NAME[] = {'W','i','n','e',' ','T','a','b','l','e','t',' ','C','o','n','t','e','x','t',0}; + const WCHAR SZ_DEVICE_NAME[] = {'W','i','n','e',' ','T','a','b','l','e','t',' ','D','e','v','i','c','e',0}; + const WCHAR SZ_NON_PLUGINPLAY[] = {'n','o','n','-','p','l','u','g','i','n','p','l','a','y',0}; + struct x11drv_thread_data *data = x11drv_thread_data(); int num_devices; int loop; @@ -305,8 +316,8 @@ void X11DRV_LoadTabletInfo(HWND hwnddefault) hwndTabletDefault = hwnddefault; /* Do base initializaion */ - strcpy(gSysContext.lcName, "Wine Tablet Context"); - strcpy(gSysDevice.NAME,"Wine Tablet Device"); + strcpyW(gSysContext.lcName, SZ_CONTEXT_NAME); + strcpyW(gSysDevice.NAME, SZ_DEVICE_NAME); gSysContext.lcOptions = CXO_SYSTEM; gSysContext.lcLocks = CXL_INSIZE | CXL_INASPECT | CXL_MARGIN | @@ -337,7 +348,7 @@ void X11DRV_LoadTabletInfo(HWND hwnddefault) gSysDevice.PKTDATA = PK_CONTEXT | PK_STATUS | PK_SERIAL_NUMBER| PK_TIME | PK_CURSOR | PK_BUTTONS | PK_X | PK_Y | PK_NORMAL_PRESSURE | PK_ORIENTATION; - strcpy(gSysDevice.PNPID,"non-pluginplay"); + strcpyW(gSysDevice.PNPID, SZ_NON_PLUGINPLAY); wine_tsx11_lock(); @@ -363,6 +374,13 @@ void X11DRV_LoadTabletInfo(HWND hwnddefault) target = &devices[loop]; cursor = &gSysCursor[cursor_target]; + if (strlen(target->name) >= WT_MAX_NAME_LEN) + { + ERR("Input device '%s' name too long - skipping\n", wine_dbgstr_a(target->name)); + cursor_target--; + continue; + } + X11DRV_expect_error(data->display, Tablet_ErrorHandler, NULL); opendevice = pXOpenDevice(data->display,target->id); if (!X11DRV_check_error() && opendevice) @@ -394,8 +412,7 @@ void X11DRV_LoadTabletInfo(HWND hwnddefault) cursor_target --; continue; } - - strcpy(cursor->NAME,target->name); + MultiByteToWideChar(CP_UNIXCP, 0, target->name, -1, cursor->NAME, WT_MAX_NAME_LEN); cursor->ACTIVE = 1; cursor->PKTDATA = PK_TIME | PK_CURSOR | PK_BUTTONS | PK_X | PK_Y | @@ -407,9 +424,9 @@ void X11DRV_LoadTabletInfo(HWND hwnddefault) cursor->NPBTNMARKS[0] = 0 ; cursor->NPBTNMARKS[1] = 1 ; cursor->CAPABILITIES = CRC_MULTIMODE; - if (strcasecmp(cursor->NAME,"stylus")==0) + if (strcasecmp(target->name,"stylus")==0) cursor->TYPE = 0x4825; - if (strcasecmp(cursor->NAME,"eraser")==0) + if (strcasecmp(target->name,"eraser")==0) cursor->TYPE = 0xc85a; @@ -488,16 +505,29 @@ void X11DRV_LoadTabletInfo(HWND hwnddefault) break; case ButtonClass: { - CHAR *ptr = cursor->BTNNAMES; + int cchBuf = 512; + int cchPos = 0; int i; Button = (XButtonInfoPtr) any; cursor->BUTTONS = Button->num_buttons; + cursor->BTNNAMES = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*cchBuf); for (i = 0; i < cursor->BUTTONS; i++) { - strcpy(ptr,cursor->NAME); - ptr+=8; + /* FIXME - these names are probably incorrect */ + int cch = strlenW(cursor->NAME) + 1; + while (cch > cchBuf - cchPos - 1) /* we want one extra byte for the last NUL */ + { + cchBuf *= 2; + cursor->BTNNAMES = HeapReAlloc(GetProcessHeap(), 0, cursor->BTNNAMES, sizeof(WCHAR)*cchBuf); + } + + strcpyW(cursor->BTNNAMES + cchPos, cursor->NAME); + cchPos += cch; } + cursor->BTNNAMES[cchPos++] = 0; + cursor->BTNNAMES = HeapReAlloc(GetProcessHeap(), 0, cursor->BTNNAMES, sizeof(WCHAR)*cchPos); + cursor->cchBTNNAMES = cchPos; } break; } @@ -695,10 +725,13 @@ int X11DRV_AttachEventQueueToTablet(HWND hOwner) X11DRV_expect_error(data->display,Tablet_ErrorHandler,NULL); for (cur_loop=0; cur_loop < gNumCursors; cur_loop++) { + char cursorNameA[WT_MAX_NAME_LEN]; int event_number=0; + /* the cursor name fits in the buffer because too long names are skipped */ + WideCharToMultiByte(CP_UNIXCP, 0, gSysCursor[cur_loop].NAME, -1, cursorNameA, WT_MAX_NAME_LEN, NULL, NULL); for (loop=0; loop < num_devices; loop ++) - if (strcmp(devices[loop].name,gSysCursor[cur_loop].NAME)==0) + if (strcmp(devices[loop].name, cursorNameA) == 0) target = &devices[loop]; TRACE("Opening cursor %i id %i\n",cur_loop,(INT)target->id); @@ -754,7 +787,7 @@ int X11DRV_GetCurrentPacket(LPWTPACKET *packet) } -static inline int CopyTabletData(LPVOID target, LPVOID src, INT size) +static inline int CopyTabletData(LPVOID target, LPCVOID src, INT size) { /* * It is valid to call CopyTabletData with NULL. @@ -766,9 +799,9 @@ static inline int CopyTabletData(LPVOID target, LPVOID src, INT size) } /*********************************************************************** - * X11DRV_WTInfoA (X11DRV.@) + * X11DRV_WTInfoW (X11DRV.@) */ -UINT X11DRV_WTInfoA(UINT wCategory, UINT nIndex, LPVOID lpOutput) +UINT X11DRV_WTInfoW(UINT wCategory, UINT nIndex, LPVOID lpOutput) { /* * It is valid to call WTInfoA with lpOutput == NULL, as per standard. @@ -798,9 +831,11 @@ UINT X11DRV_WTInfoA(UINT wCategory, UINT nIndex, LPVOID lpOutput) { WORD version; case IFC_WINTABID: - strcpy(lpOutput,"Wine Wintab 1.1"); - rc = 16; + { + static const WCHAR driver[] = {'W','i','n','e',' ','W','i','n','t','a','b',' ','1','.','1',0}; + rc = CopyTabletData(lpOutput, driver, (strlenW(driver) + 1) * sizeof(WCHAR)); break; + } case IFC_SPECVERSION: version = (0x01) | (0x01 << 8); rc = CopyTabletData(lpOutput, &version,sizeof(WORD)); @@ -821,11 +856,11 @@ UINT X11DRV_WTInfoA(UINT wCategory, UINT nIndex, LPVOID lpOutput) { case 0: rc = CopyTabletData(lpOutput, &gSysContext, - sizeof(LOGCONTEXTA)); + sizeof(LOGCONTEXTW)); break; case CTX_NAME: rc = CopyTabletData(lpOutput, &gSysContext.lcName, - strlen(gSysContext.lcName)+1); + (strlenW(gSysContext.lcName)+1) * sizeof(WCHAR)); break; case CTX_OPTIONS: rc = CopyTabletData(lpOutput, &gSysContext.lcOptions, @@ -979,7 +1014,7 @@ UINT X11DRV_WTInfoA(UINT wCategory, UINT nIndex, LPVOID lpOutput) { case CSR_NAME: rc = CopyTabletData(lpOutput, &tgtcursor->NAME, - strlen(tgtcursor->NAME)+1); + (strlenW(tgtcursor->NAME)+1) * sizeof(WCHAR)); break; case CSR_ACTIVE: rc = CopyTabletData(lpOutput,&tgtcursor->ACTIVE, @@ -1000,7 +1035,7 @@ UINT X11DRV_WTInfoA(UINT wCategory, UINT nIndex, LPVOID lpOutput) case CSR_BTNNAMES: FIXME("Button Names not returned correctly\n"); rc = CopyTabletData(lpOutput,&tgtcursor->BTNNAMES, - strlen(tgtcursor->BTNNAMES)+1); + tgtcursor->cchBTNNAMES*sizeof(WCHAR)); break; case CSR_BUTTONMAP: rc = CopyTabletData(lpOutput,&tgtcursor->BUTTONMAP, @@ -1071,7 +1106,7 @@ UINT X11DRV_WTInfoA(UINT wCategory, UINT nIndex, LPVOID lpOutput) { case DVC_NAME: rc = CopyTabletData(lpOutput,gSysDevice.NAME, - strlen(gSysDevice.NAME)+1); + (strlenW(gSysDevice.NAME)+1) * sizeof(WCHAR)); break; case DVC_HARDWARE: rc = CopyTabletData(lpOutput,&gSysDevice.HARDWARE, @@ -1155,7 +1190,7 @@ UINT X11DRV_WTInfoA(UINT wCategory, UINT nIndex, LPVOID lpOutput) break; case DVC_PNPID: rc = CopyTabletData(lpOutput,gSysDevice.PNPID, - strlen(gSysDevice.PNPID)+1); + (strlenW(gSysDevice.PNPID)+1)*sizeof(WCHAR)); break; default: FIXME("WTI_DEVICES unhandled index %i\n",nIndex); @@ -1194,9 +1229,9 @@ void X11DRV_LoadTabletInfo(HWND hwnddefault) } /*********************************************************************** - * WTInfoA (X11DRV.@) + * WTInfoW (X11DRV.@) */ -UINT X11DRV_WTInfoA(UINT wCategory, UINT nIndex, LPVOID lpOutput) +UINT X11DRV_WTInfoW(UINT wCategory, UINT nIndex, LPVOID lpOutput) { return 0; } diff --git a/dlls/wintab32/context.c b/dlls/wintab32/context.c index 5b538ad10fc..4c08083a930 100644 --- a/dlls/wintab32/context.c +++ b/dlls/wintab32/context.c @@ -28,6 +28,7 @@ #include "winerror.h" #include "winbase.h" #include "winuser.h" +#include "winnls.h" #include "wintab.h" #include "wintab_internal.h" @@ -45,6 +46,32 @@ static BOOL gLoaded; static LPOPENCONTEXT gOpenContexts; static HCTX gTopContext = (HCTX)0xc00; +static void LOGCONTEXTWtoA(const LOGCONTEXTW *in, LOGCONTEXTA *out) +{ + WideCharToMultiByte(CP_ACP, 0, in->lcName, LCNAMELEN, out->lcName, LCNAMELEN, NULL, NULL); + out->lcName[LCNAMELEN - 1] = 0; + /* we use the fact that the fields after lcName are the same in LOGCONTEXTA and W */ + memcpy(&out->lcOptions, &in->lcOptions, sizeof(LOGCONTEXTW) - FIELD_OFFSET(LOGCONTEXTW, lcOptions)); +} + +static BOOL is_logcontext_category(UINT wCategory) +{ + return wCategory == WTI_DEFSYSCTX || wCategory == WTI_DEFCONTEXT || wCategory == WTI_DDCTXS; +} + +static BOOL is_string_field(UINT wCategory, UINT nIndex) +{ + if (wCategory == WTI_INTERFACE && nIndex == IFC_WINTABID) + return TRUE; + if (is_logcontext_category(wCategory) && nIndex == CTX_NAME) + return TRUE; + if (wCategory >= WTI_CURSORS && wCategory <= WTI_CURSORS + 9) + return TRUE; + if (wCategory == WTI_DEVICES && (nIndex == DVC_NAME || nIndex == DVC_PNPID)) + return TRUE; + return FALSE; +} + static char* DUMPBITS(int x, char* buf) { strcpy(buf,"{"); @@ -346,10 +373,7 @@ static VOID TABLET_BlankPacketData(LPOPENCONTEXT context, LPVOID lpPkt, INT n) } -/*********************************************************************** - * WTInfoA (WINTAB32.20) - */ -UINT WINAPI WTInfoA(UINT wCategory, UINT nIndex, LPVOID lpOutput) +UINT WINAPI WTInfoT(UINT wCategory, UINT nIndex, LPVOID lpOutput, BOOL bUnicode) { UINT result; if (gLoaded == FALSE) @@ -374,30 +398,57 @@ UINT WINAPI WTInfoA(UINT wCategory, UINT nIndex, LPVOID lpOutput) } } - result = pWTInfoA( wCategory, nIndex, lpOutput ); - - /* - * Handle system extents here, as we can use user32.dll code to set them. - */ - if(wCategory == WTI_DEFSYSCTX && nIndex == 0) + if (is_logcontext_category(wCategory) && nIndex == 0) { - LPLOGCONTEXTA lpCtx = (LPLOGCONTEXTA)lpOutput; - lpCtx->lcSysExtX = GetSystemMetrics(SM_CXSCREEN); - lpCtx->lcSysExtY = GetSystemMetrics(SM_CYSCREEN); + if (lpOutput) + { + LOGCONTEXTW buf; + pWTInfoW(wCategory, nIndex, &buf); + + /* Handle system extents here, as we can use user32.dll code to set them */ + if(wCategory == WTI_DEFSYSCTX && nIndex == 0) + { + buf.lcSysExtX = GetSystemMetrics(SM_CXSCREEN); + buf.lcSysExtY = GetSystemMetrics(SM_CYSCREEN); + } + + if (bUnicode) + memcpy(lpOutput, &buf, sizeof(buf)); + else + LOGCONTEXTWtoA(&buf, lpOutput); + } + + return bUnicode ? sizeof(LOGCONTEXTW) : sizeof(LOGCONTEXTA); } + else if (is_string_field(wCategory, nIndex) && !bUnicode) + { + int size = pWTInfoW(wCategory, nIndex, NULL); + WCHAR *buf = HeapAlloc(GetProcessHeap(), 0, size); + pWTInfoW(wCategory, nIndex, buf); + result = WideCharToMultiByte(CP_ACP, 0, buf, size/sizeof(WCHAR), lpOutput, lpOutput ? 2*size : 0, NULL, NULL); + HeapFree(GetProcessHeap(), 0, buf); + } + else + result = pWTInfoW(wCategory, nIndex, lpOutput); + return result; } +/*********************************************************************** + * WTInfoA (WINTAB32.20) + */ +UINT WINAPI WTInfoA(UINT wCategory, UINT nIndex, LPVOID lpOutput) +{ + return WTInfoT(wCategory, nIndex, lpOutput, FALSE); +} + + /*********************************************************************** * WTInfoW (WINTAB32.1020) */ UINT WINAPI WTInfoW(UINT wCategory, UINT nIndex, LPVOID lpOutput) { - FIXME("(%u, %u, %p): stub\n", wCategory, nIndex, lpOutput); - - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return 0; + return WTInfoT(wCategory, nIndex, lpOutput, TRUE); } /*********************************************************************** diff --git a/dlls/wintab32/wintab32.c b/dlls/wintab32/wintab32.c index c34a681ed1c..8c7c2f7703f 100644 --- a/dlls/wintab32/wintab32.c +++ b/dlls/wintab32/wintab32.c @@ -39,7 +39,7 @@ CRITICAL_SECTION csTablet; int (*pLoadTabletInfo)(HWND hwnddefault) = NULL; int (*pGetCurrentPacket)(LPWTPACKET packet) = NULL; int (*pAttachEventQueueToTablet)(HWND hOwner) = NULL; -UINT (*pWTInfoA)(UINT wCategory, UINT nIndex, LPVOID lpOutput) = NULL; +UINT (*pWTInfoW)(UINT wCategory, UINT nIndex, LPVOID lpOutput) = NULL; static LRESULT WINAPI TABLET_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); @@ -81,7 +81,7 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpReserved) pLoadTabletInfo = (void *)GetProcAddress(hx11drv, "LoadTabletInfo"); pAttachEventQueueToTablet = (void *)GetProcAddress(hx11drv, "AttachEventQueueToTablet"); pGetCurrentPacket = (void *)GetProcAddress(hx11drv, "GetCurrentPacket"); - pWTInfoA = (void *)GetProcAddress(hx11drv, "WTInfoA"); + pWTInfoW = (void *)GetProcAddress(hx11drv, "WTInfoW"); TABLET_Register(); hwndDefault = CreateWindowW(WC_TABLETCLASSNAME, name, WS_POPUPWINDOW,0,0,0,0,0,0,hInstDLL,0); diff --git a/dlls/wintab32/wintab_internal.h b/dlls/wintab32/wintab_internal.h index 711a48ff79c..71a68ab7e48 100644 --- a/dlls/wintab32/wintab_internal.h +++ b/dlls/wintab32/wintab_internal.h @@ -155,7 +155,7 @@ LPOPENCONTEXT FindOpenContext(HWND hwnd); extern int (*pLoadTabletInfo)(HWND hwnddefault); extern int (*pGetCurrentPacket)(LPWTPACKET packet); extern int (*pAttachEventQueueToTablet)(HWND hOwner); -extern UINT (*pWTInfoA)(UINT wCategory, UINT nIndex, LPVOID lpOutput); +extern UINT (*pWTInfoW)(UINT wCategory, UINT nIndex, LPVOID lpOutput); extern HWND hwndDefault; extern CRITICAL_SECTION csTablet;