localspl: Add support for monitors providing the MONITOR2 interface.

Signed-off-by: Dmitry Timoshkov <dmitry@baikal.ru>
Signed-off-by: Huw Davies <huw@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Dmitry Timoshkov 2019-09-06 12:01:02 +08:00 committed by Alexandre Julliard
parent 64a5720d25
commit d9518240c3
1 changed files with 82 additions and 55 deletions

View File

@ -65,10 +65,10 @@ typedef struct {
LPWSTR name; LPWSTR name;
LPWSTR dllname; LPWSTR dllname;
PMONITORUI monitorUI; PMONITORUI monitorUI;
LPMONITOR monitor; MONITOR2 monitor;
BOOL (WINAPI *old_XcvOpenPort)(LPCWSTR,ACCESS_MASK,PHANDLE);
HMODULE hdll; HMODULE hdll;
DWORD refcount; DWORD refcount;
DWORD dwMonitorSize;
} monitor_t; } monitor_t;
typedef struct { typedef struct {
@ -327,6 +327,10 @@ static void monitor_unload(monitor_t * pm)
if (pm->refcount == 0) { if (pm->refcount == 0) {
list_remove(&pm->entry); list_remove(&pm->entry);
if (pm->monitor.pfnShutdown)
pm->monitor.pfnShutdown(0);
FreeLibrary(pm->hdll); FreeLibrary(pm->hdll);
heap_free(pm->name); heap_free(pm->name);
heap_free(pm->dllname); heap_free(pm->dllname);
@ -352,7 +356,7 @@ static void monitor_unloadall(void)
LIST_FOR_EACH_ENTRY_SAFE(pm, next, &monitor_handles, monitor_t, entry) LIST_FOR_EACH_ENTRY_SAFE(pm, next, &monitor_handles, monitor_t, entry)
{ {
/* skip monitorui dlls */ /* skip monitorui dlls */
if (pm->monitor) monitor_unload(pm); if (pm->monitor.cbSize) monitor_unload(pm);
} }
LeaveCriticalSection(&monitor_handles_cs); LeaveCriticalSection(&monitor_handles_cs);
} }
@ -378,6 +382,7 @@ static monitor_t * monitor_load(LPCWSTR name, LPWSTR dllname)
monitor_t * cursor; monitor_t * cursor;
LPWSTR regroot = NULL; LPWSTR regroot = NULL;
LPWSTR driver = dllname; LPWSTR driver = dllname;
HKEY hroot = 0;
TRACE("(%s, %s)\n", debugstr_w(name), debugstr_w(dllname)); TRACE("(%s, %s)\n", debugstr_w(name), debugstr_w(dllname));
/* Is the Monitor already loaded? */ /* Is the Monitor already loaded? */
@ -402,7 +407,6 @@ static monitor_t * monitor_load(LPCWSTR name, LPWSTR dllname)
if (pm->name == NULL) { if (pm->name == NULL) {
/* Load the monitor */ /* Load the monitor */
LPMONITOREX pmonitorEx;
DWORD len; DWORD len;
if (name) { if (name) {
@ -413,19 +417,19 @@ static monitor_t * monitor_load(LPCWSTR name, LPWSTR dllname)
if (regroot) { if (regroot) {
lstrcpyW(regroot, monitorsW); lstrcpyW(regroot, monitorsW);
lstrcatW(regroot, name); lstrcatW(regroot, name);
/* Get the Driver from the Registry */ if (RegOpenKeyW(HKEY_LOCAL_MACHINE, regroot, &hroot) == ERROR_SUCCESS) {
if (driver == NULL) { /* Get the Driver from the Registry */
HKEY hroot; if (driver == NULL) {
DWORD namesize; DWORD namesize;
if (RegOpenKeyW(HKEY_LOCAL_MACHINE, regroot, &hroot) == ERROR_SUCCESS) {
if (RegQueryValueExW(hroot, driverW, NULL, NULL, NULL, if (RegQueryValueExW(hroot, driverW, NULL, NULL, NULL,
&namesize) == ERROR_SUCCESS) { &namesize) == ERROR_SUCCESS) {
driver = heap_alloc(namesize); driver = heap_alloc(namesize);
RegQueryValueExW(hroot, driverW, NULL, NULL, (LPBYTE) driver, &namesize) ; RegQueryValueExW(hroot, driverW, NULL, NULL, (LPBYTE) driver, &namesize) ;
} }
RegCloseKey(hroot);
} }
} }
else
WARN("%s not found\n", debugstr_w(regroot));
} }
pm->name = strdupW(name); pm->name = strdupW(name);
@ -471,26 +475,38 @@ static monitor_t * monitor_load(LPCWSTR name, LPWSTR dllname)
} }
} }
if (pInitializePrintMonitor && regroot) { if (pInitializePrintMonitor2 && hroot) {
MONITORINIT init;
MONITOR2 *monitor2;
HANDLE hmon;
memset(&init, 0, sizeof(init));
init.cbSize = sizeof(init);
init.hckRegistryRoot = hroot;
init.bLocal = TRUE;
monitor2 = pInitializePrintMonitor2(&init, &hmon);
TRACE("%p: MONITOR2 from %s,InitializePrintMonitor2(%s)\n",
monitor2, debugstr_w(driver), debugstr_w(regroot));
if (monitor2)
memcpy(&pm->monitor, monitor2, min(monitor2->cbSize, sizeof(pm->monitor)));
}
else if (pInitializePrintMonitor && regroot) {
MONITOREX *pmonitorEx;
pmonitorEx = pInitializePrintMonitor(regroot); pmonitorEx = pInitializePrintMonitor(regroot);
TRACE("%p: LPMONITOREX from %s,InitializePrintMonitor(%s)\n", TRACE("%p: LPMONITOREX from %s,InitializePrintMonitor(%s)\n",
pmonitorEx, debugstr_w(driver), debugstr_w(regroot)); pmonitorEx, debugstr_w(driver), debugstr_w(regroot));
if (pmonitorEx)
if (pmonitorEx) { {
pm->dwMonitorSize = pmonitorEx->dwMonitorSize; /* Layout of MONITOREX and MONITOR2 mostly matches */
pm->monitor = &(pmonitorEx->Monitor); memcpy(&pm->monitor, pmonitorEx, min(pmonitorEx->dwMonitorSize + sizeof(DWORD), sizeof(pm->monitor)));
pm->old_XcvOpenPort = pmonitorEx->Monitor.pfnXcvOpenPort;
pm->monitor.pfnXcvOpenPort = NULL;
} }
} }
if (pm->monitor) { if (!pm->monitor.cbSize && regroot) {
TRACE("0x%08x: dwMonitorSize (%d)\n", pm->dwMonitorSize, pm->dwMonitorSize);
}
if (!pm->monitor && regroot) {
if (pInitializePrintMonitor2 != NULL) {
FIXME("%s,InitializePrintMonitor2 not implemented\n", debugstr_w(driver));
}
if (pInitializeMonitorEx != NULL) { if (pInitializeMonitorEx != NULL) {
FIXME("%s,InitializeMonitorEx not implemented\n", debugstr_w(driver)); FIXME("%s,InitializeMonitorEx not implemented\n", debugstr_w(driver));
} }
@ -498,7 +514,7 @@ static monitor_t * monitor_load(LPCWSTR name, LPWSTR dllname)
FIXME("%s,InitializeMonitor not implemented\n", debugstr_w(driver)); FIXME("%s,InitializeMonitor not implemented\n", debugstr_w(driver));
} }
} }
if (!pm->monitor && !pm->monitorUI) { if (!pm->monitor.cbSize && !pm->monitorUI) {
monitor_unload(pm); monitor_unload(pm);
SetLastError(ERROR_PROC_NOT_FOUND); SetLastError(ERROR_PROC_NOT_FOUND);
pm = NULL; pm = NULL;
@ -511,6 +527,7 @@ cleanup:
} }
LeaveCriticalSection(&monitor_handles_cs); LeaveCriticalSection(&monitor_handles_cs);
if (driver != dllname) heap_free(driver); if (driver != dllname) heap_free(driver);
if (hroot) RegCloseKey(hroot);
heap_free(regroot); heap_free(regroot);
TRACE("=> %p\n", pm); TRACE("=> %p\n", pm);
return pm; return pm;
@ -563,7 +580,7 @@ static monitor_t * monitor_loadui(monitor_t * pm)
WCHAR buffer[MAX_PATH]; WCHAR buffer[MAX_PATH];
HANDLE hXcv; HANDLE hXcv;
DWORD len; DWORD len;
DWORD res; DWORD res = 0;
if (pm == NULL) return NULL; if (pm == NULL) return NULL;
TRACE("(%p) => dllname: %s\n", pm, debugstr_w(pm->dllname)); TRACE("(%p) => dllname: %s\n", pm, debugstr_w(pm->dllname));
@ -577,16 +594,17 @@ static monitor_t * monitor_loadui(monitor_t * pm)
} }
/* query the userinterface-dllname from the Portmonitor */ /* query the userinterface-dllname from the Portmonitor */
if ((pm->monitor) && (pm->monitor->pfnXcvDataPort)) { /* building (",XcvMonitor %s",pm->name) not needed yet */
/* building (",XcvMonitor %s",pm->name) not needed yet */ if (pm->monitor.pfnXcvOpenPort)
res = pm->monitor->pfnXcvOpenPort(emptyW, SERVER_ACCESS_ADMINISTER, &hXcv); res = pm->monitor.pfnXcvOpenPort(0, emptyW, SERVER_ACCESS_ADMINISTER, &hXcv);
TRACE("got %u with %p\n", res, hXcv); else if (pm->old_XcvOpenPort)
if (res) { res = pm->old_XcvOpenPort(emptyW, SERVER_ACCESS_ADMINISTER, &hXcv);
res = pm->monitor->pfnXcvDataPort(hXcv, monitorUIW, NULL, 0, (BYTE *) buffer, sizeof(buffer), &len); TRACE("got %u with %p\n", res, hXcv);
TRACE("got %u with %s\n", res, debugstr_w(buffer)); if (res) {
if (res == ERROR_SUCCESS) pui = monitor_load(NULL, buffer); res = pm->monitor.pfnXcvDataPort(hXcv, monitorUIW, NULL, 0, (BYTE *) buffer, sizeof(buffer), &len);
pm->monitor->pfnXcvClosePort(hXcv); TRACE("got %u with %s\n", res, debugstr_w(buffer));
} if (res == ERROR_SUCCESS) pui = monitor_load(NULL, buffer);
pm->monitor.pfnXcvClosePort(hXcv);
} }
return pui; return pui;
} }
@ -921,7 +939,6 @@ static DWORD get_ports_from_all_monitors(DWORD level, LPBYTE pPorts, DWORD cbBuf
DWORD numentries; DWORD numentries;
DWORD entrysize; DWORD entrysize;
TRACE("(%d, %p, %d, %p)\n", level, pPorts, cbBuf, lpreturned); TRACE("(%d, %p, %d, %p)\n", level, pPorts, cbBuf, lpreturned);
entrysize = (level == 1) ? sizeof(PORT_INFO_1W) : sizeof(PORT_INFO_2W); entrysize = (level == 1) ? sizeof(PORT_INFO_1W) : sizeof(PORT_INFO_2W);
@ -934,16 +951,16 @@ static DWORD get_ports_from_all_monitors(DWORD level, LPBYTE pPorts, DWORD cbBuf
LIST_FOR_EACH_ENTRY(pm, &monitor_handles, monitor_t, entry) LIST_FOR_EACH_ENTRY(pm, &monitor_handles, monitor_t, entry)
{ {
if ((pm->monitor) && (pm->monitor->pfnEnumPorts)) { if (pm->monitor.pfnEnumPorts) {
pi_needed = 0; pi_needed = 0;
pi_returned = 0; pi_returned = 0;
res = pm->monitor->pfnEnumPorts(NULL, level, pi_buffer, pi_allocated, &pi_needed, &pi_returned); res = pm->monitor.pfnEnumPorts(NULL, level, pi_buffer, pi_allocated, &pi_needed, &pi_returned);
if (!res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) { if (!res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) {
/* Do not use heap_realloc (we do not need the old data in the buffer) */ /* Do not use heap_realloc (we do not need the old data in the buffer) */
heap_free(pi_buffer); heap_free(pi_buffer);
pi_buffer = heap_alloc(pi_needed); pi_buffer = heap_alloc(pi_needed);
pi_allocated = (pi_buffer) ? pi_needed : 0; pi_allocated = (pi_buffer) ? pi_needed : 0;
res = pm->monitor->pfnEnumPorts(NULL, level, pi_buffer, pi_allocated, &pi_needed, &pi_returned); res = pm->monitor.pfnEnumPorts(NULL, level, pi_buffer, pi_allocated, &pi_needed, &pi_returned);
} }
TRACE("(%s) got %d with %d (need %d byte for %d entries)\n", TRACE("(%s) got %d with %d (need %d byte for %d entries)\n",
debugstr_w(pm->name), res, GetLastError(), pi_needed, pi_returned); debugstr_w(pm->name), res, GetLastError(), pi_needed, pi_returned);
@ -1144,7 +1161,10 @@ static HMODULE driver_load(const printenv_t * env, LPWSTR dllname)
static VOID printer_free(printer_t * printer) static VOID printer_free(printer_t * printer)
{ {
if (printer->hXcv) if (printer->hXcv)
printer->pm->monitor->pfnXcvClosePort(printer->hXcv); {
if (printer->pm->monitor.pfnXcvClosePort)
printer->pm->monitor.pfnXcvClosePort(printer->hXcv);
}
monitor_unload(printer->pm); monitor_unload(printer->pm);
@ -1224,11 +1244,14 @@ static HANDLE printer_alloc_handle(LPCWSTR name, LPPRINTER_DEFAULTSW pDefault)
} }
if (printer->pm) { if (printer->pm) {
if ((printer->pm->monitor) && (printer->pm->monitor->pfnXcvOpenPort)) { if (printer->pm->monitor.pfnXcvOpenPort)
printer->pm->monitor->pfnXcvOpenPort(&printername[len], printer->pm->monitor.pfnXcvOpenPort(0, &printername[len],
pDefault ? pDefault->DesiredAccess : 0, pDefault ? pDefault->DesiredAccess : 0,
&printer->hXcv); &printer->hXcv);
} else if (printer->pm->old_XcvOpenPort)
printer->pm->old_XcvOpenPort(&printername[len],
pDefault ? pDefault->DesiredAccess : 0,
&printer->hXcv);
if (printer->hXcv == NULL) { if (printer->hXcv == NULL) {
printer_free(printer); printer_free(printer);
SetLastError(ERROR_INVALID_PARAMETER); SetLastError(ERROR_INVALID_PARAMETER);
@ -1588,8 +1611,8 @@ static BOOL WINAPI fpAddPort(LPWSTR pName, HWND hWnd, LPWSTR pMonitorName)
} }
pm = monitor_load(pMonitorName, NULL); pm = monitor_load(pMonitorName, NULL);
if (pm && pm->monitor && pm->monitor->pfnAddPort) { if (pm && pm->monitor.pfnAddPort) {
res = pm->monitor->pfnAddPort(pName, hWnd, pMonitorName); res = pm->monitor.pfnAddPort(pName, hWnd, pMonitorName);
TRACE("got %d with %u (%s)\n", res, GetLastError(), debugstr_w(pm->dllname)); TRACE("got %d with %u (%s)\n", res, GetLastError(), debugstr_w(pm->dllname));
} }
else else
@ -1665,8 +1688,9 @@ static BOOL WINAPI fpAddPortEx(LPWSTR pName, DWORD level, LPBYTE pBuffer, LPWSTR
/* load the Monitor */ /* load the Monitor */
pm = monitor_load(pMonitorName, NULL); pm = monitor_load(pMonitorName, NULL);
if (pm && pm->monitor && pm->monitor->pfnAddPortEx) { if (pm && pm->monitor.pfnAddPortEx)
res = pm->monitor->pfnAddPortEx(pName, level, pBuffer, pMonitorName); {
res = pm->monitor.pfnAddPortEx(pName, level, pBuffer, pMonitorName);
TRACE("got %d with %u (%s)\n", res, GetLastError(), debugstr_w(pm->dllname)); TRACE("got %d with %u (%s)\n", res, GetLastError(), debugstr_w(pm->dllname));
} }
else else
@ -1779,10 +1803,11 @@ static BOOL WINAPI fpConfigurePort(LPWSTR pName, HWND hWnd, LPWSTR pPortName)
} }
pm = monitor_load_by_port(pPortName); pm = monitor_load_by_port(pPortName);
if (pm && pm->monitor && pm->monitor->pfnConfigurePort) { if (pm && pm->monitor.pfnConfigurePort)
{
TRACE("use %s for %s (monitor %p: %s)\n", debugstr_w(pm->name), TRACE("use %s for %s (monitor %p: %s)\n", debugstr_w(pm->name),
debugstr_w(pPortName), pm, debugstr_w(pm->dllname)); debugstr_w(pPortName), pm, debugstr_w(pm->dllname));
res = pm->monitor->pfnConfigurePort(pName, hWnd, pPortName); res = pm->monitor.pfnConfigurePort(pName, hWnd, pPortName);
TRACE("got %d with %u\n", res, GetLastError()); TRACE("got %d with %u\n", res, GetLastError());
} }
else else
@ -1909,10 +1934,11 @@ static BOOL WINAPI fpDeletePort(LPWSTR pName, HWND hWnd, LPWSTR pPortName)
} }
pm = monitor_load_by_port(pPortName); pm = monitor_load_by_port(pPortName);
if (pm && pm->monitor && pm->monitor->pfnDeletePort) { if (pm && pm->monitor.pfnDeletePort)
{
TRACE("use %s for %s (monitor %p: %s)\n", debugstr_w(pm->name), TRACE("use %s for %s (monitor %p: %s)\n", debugstr_w(pm->name),
debugstr_w(pPortName), pm, debugstr_w(pm->dllname)); debugstr_w(pPortName), pm, debugstr_w(pm->dllname));
res = pm->monitor->pfnDeletePort(pName, hWnd, pPortName); res = pm->monitor.pfnDeletePort(pName, hWnd, pPortName);
TRACE("got %d with %u\n", res, GetLastError()); TRACE("got %d with %u\n", res, GetLastError());
} }
else else
@ -2339,7 +2365,8 @@ static BOOL WINAPI fpXcvData(HANDLE hXcv, LPCWSTR pszDataName, PBYTE pInputData,
*pcbOutputNeeded = 0; *pcbOutputNeeded = 0;
*pdwStatus = printer->pm->monitor->pfnXcvDataPort(printer->hXcv, pszDataName, if (printer->pm->monitor.pfnXcvDataPort)
*pdwStatus = printer->pm->monitor.pfnXcvDataPort(printer->hXcv, pszDataName,
pInputData, cbInputData, pOutputData, cbOutputData, pcbOutputNeeded); pInputData, cbInputData, pOutputData, cbOutputData, pcbOutputNeeded);
return TRUE; return TRUE;