Signed-off-by: Dmitry Timoshkov dmitry@baikal.ru --- dlls/localspl/provider.c | 149 +++++++++++++++++++++++++++++---------- 1 file changed, 111 insertions(+), 38 deletions(-)
diff --git a/dlls/localspl/provider.c b/dlls/localspl/provider.c index 8e5e3428d5..2b3f9bac6e 100644 --- a/dlls/localspl/provider.c +++ b/dlls/localspl/provider.c @@ -66,9 +66,9 @@ typedef struct { LPWSTR dllname; PMONITORUI monitorUI; LPMONITOR monitor; + LPMONITOR2 monitor2; HMODULE hdll; DWORD refcount; - DWORD dwMonitorSize; } monitor_t;
typedef struct { @@ -327,6 +327,10 @@ static void monitor_unload(monitor_t * pm)
if (pm->refcount == 0) { list_remove(&pm->entry); + + if (pm->monitor2 && pm->monitor2->pfnShutdown) + pm->monitor2->pfnShutdown(0); + FreeLibrary(pm->hdll); heap_free(pm->name); heap_free(pm->dllname); @@ -378,6 +382,7 @@ static monitor_t * monitor_load(LPCWSTR name, LPWSTR dllname) monitor_t * cursor; LPWSTR regroot = NULL; LPWSTR driver = dllname; + HKEY hroot = 0;
TRACE("(%s, %s)\n", debugstr_w(name), debugstr_w(dllname)); /* Is the Monitor already loaded? */ @@ -402,7 +407,6 @@ static monitor_t * monitor_load(LPCWSTR name, LPWSTR dllname)
if (pm->name == NULL) { /* Load the monitor */ - LPMONITOREX pmonitorEx; DWORD len;
if (name) { @@ -413,19 +417,19 @@ static monitor_t * monitor_load(LPCWSTR name, LPWSTR dllname) if (regroot) { lstrcpyW(regroot, monitorsW); lstrcatW(regroot, name); - /* Get the Driver from the Registry */ - if (driver == NULL) { - HKEY hroot; - DWORD namesize; - if (RegOpenKeyW(HKEY_LOCAL_MACHINE, regroot, &hroot) == ERROR_SUCCESS) { + if (RegOpenKeyW(HKEY_LOCAL_MACHINE, regroot, &hroot) == ERROR_SUCCESS) { + /* Get the Driver from the Registry */ + if (driver == NULL) { + DWORD namesize; if (RegQueryValueExW(hroot, driverW, NULL, NULL, NULL, &namesize) == ERROR_SUCCESS) { driver = heap_alloc(namesize); RegQueryValueExW(hroot, driverW, NULL, NULL, (LPBYTE) driver, &namesize) ; } - RegCloseKey(hroot); } } + else + WARN("%s not found\n", debugstr_w(regroot)); }
pm->name = strdupW(name); @@ -471,26 +475,30 @@ static monitor_t * monitor_load(LPCWSTR name, LPWSTR dllname) } }
- if (pInitializePrintMonitor && regroot) { - pmonitorEx = pInitializePrintMonitor(regroot); - TRACE("%p: LPMONITOREX from %s,InitializePrintMonitor(%s)\n", - pmonitorEx, debugstr_w(driver), debugstr_w(regroot)); + if (pInitializePrintMonitor2 && hroot) { + MONITORINIT init; + HANDLE hmon;
- if (pmonitorEx) { - pm->dwMonitorSize = pmonitorEx->dwMonitorSize; - pm->monitor = &(pmonitorEx->Monitor); - } - } + memset(&init, 0, sizeof(init)); + init.cbSize = sizeof(init); + init.hckRegistryRoot = hroot; + init.bLocal = TRUE;
- if (pm->monitor) { - TRACE("0x%08x: dwMonitorSize (%d)\n", pm->dwMonitorSize, pm->dwMonitorSize); + pm->monitor2 = pInitializePrintMonitor2(&init, &hmon); + TRACE("%p: MONITOR2 from %s,InitializePrintMonitor2(%s)\n", + pm->monitor2, debugstr_w(driver), debugstr_w(regroot)); + } + else if (pInitializePrintMonitor && regroot) { + MONITOREX *pmonitorEx;
+ pmonitorEx = pInitializePrintMonitor(regroot); + TRACE("%p: LPMONITOREX from %s,InitializePrintMonitor(%s)\n", + pm->monitor, debugstr_w(driver), debugstr_w(regroot)); + if (pmonitorEx) + pm->monitor = &pmonitorEx->Monitor; }
- if (!pm->monitor && regroot) { - if (pInitializePrintMonitor2 != NULL) { - FIXME("%s,InitializePrintMonitor2 not implemented\n", debugstr_w(driver)); - } + if (!pm->monitor && !pm->monitor2 && regroot) { if (pInitializeMonitorEx != NULL) { FIXME("%s,InitializeMonitorEx not implemented\n", debugstr_w(driver)); } @@ -498,7 +506,7 @@ static monitor_t * monitor_load(LPCWSTR name, LPWSTR dllname) FIXME("%s,InitializeMonitor not implemented\n", debugstr_w(driver)); } } - if (!pm->monitor && !pm->monitorUI) { + if (!pm->monitor && !pm->monitor2 && !pm->monitorUI) { monitor_unload(pm); SetLastError(ERROR_PROC_NOT_FOUND); pm = NULL; @@ -511,6 +519,7 @@ cleanup: } LeaveCriticalSection(&monitor_handles_cs); if (driver != dllname) heap_free(driver); + if (hroot) RegCloseKey(hroot); heap_free(regroot); TRACE("=> %p\n", pm); return pm; @@ -577,6 +586,18 @@ static monitor_t * monitor_loadui(monitor_t * pm) }
/* query the userinterface-dllname from the Portmonitor */ + if (pm->monitor2 && pm->monitor2->pfnXcvDataPort) { + res = pm->monitor2->pfnXcvOpenPort(0, emptyW, SERVER_ACCESS_ADMINISTER, &hXcv); + TRACE("got %u with %p\n", res, hXcv); + if (res) { + res = pm->monitor2->pfnXcvDataPort(hXcv, monitorUIW, NULL, 0, (BYTE *) buffer, sizeof(buffer), &len); + TRACE("got %u with %s\n", res, debugstr_w(buffer)); + if (res == ERROR_SUCCESS) pui = monitor_load(NULL, buffer); + pm->monitor2->pfnXcvClosePort(hXcv); + } + return pui; + } + if ((pm->monitor) && (pm->monitor->pfnXcvDataPort)) { /* building (",XcvMonitor %s",pm->name) not needed yet */ res = pm->monitor->pfnXcvOpenPort(emptyW, SERVER_ACCESS_ADMINISTER, &hXcv); @@ -921,7 +942,6 @@ static DWORD get_ports_from_all_monitors(DWORD level, LPBYTE pPorts, DWORD cbBuf DWORD numentries; DWORD entrysize;
- TRACE("(%d, %p, %d, %p)\n", level, pPorts, cbBuf, lpreturned); entrysize = (level == 1) ? sizeof(PORT_INFO_1W) : sizeof(PORT_INFO_2W);
@@ -934,16 +954,23 @@ static DWORD get_ports_from_all_monitors(DWORD level, LPBYTE pPorts, DWORD cbBuf
LIST_FOR_EACH_ENTRY(pm, &monitor_handles, monitor_t, entry) { - if ((pm->monitor) && (pm->monitor->pfnEnumPorts)) { + BOOL (WINAPI *pEnumPorts)(LPWSTR,DWORD,LPBYTE,DWORD,LPDWORD,LPDWORD) = NULL; + + if (pm->monitor2) + pEnumPorts = pm->monitor2->pfnEnumPorts; + else if (pm->monitor) + pEnumPorts = pm->monitor->pfnEnumPorts; + + if (pEnumPorts) { pi_needed = 0; pi_returned = 0; - res = pm->monitor->pfnEnumPorts(NULL, level, pi_buffer, pi_allocated, &pi_needed, &pi_returned); + res = pEnumPorts(NULL, level, pi_buffer, pi_allocated, &pi_needed, &pi_returned); if (!res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) { /* Do not use heap_realloc (we do not need the old data in the buffer) */ heap_free(pi_buffer); pi_buffer = heap_alloc(pi_needed); pi_allocated = (pi_buffer) ? pi_needed : 0; - res = pm->monitor->pfnEnumPorts(NULL, level, pi_buffer, pi_allocated, &pi_needed, &pi_returned); + res = pEnumPorts(NULL, level, pi_buffer, pi_allocated, &pi_needed, &pi_returned); } TRACE("(%s) got %d with %d (need %d byte for %d entries)\n", debugstr_w(pm->name), res, GetLastError(), pi_needed, pi_returned); @@ -1144,7 +1171,12 @@ static HMODULE driver_load(const printenv_t * env, LPWSTR dllname) static VOID printer_free(printer_t * printer) { if (printer->hXcv) - printer->pm->monitor->pfnXcvClosePort(printer->hXcv); + { + if (printer->pm->monitor2) + printer->pm->monitor2->pfnXcvClosePort(printer->hXcv); + else if (printer->pm->monitor) + printer->pm->monitor->pfnXcvClosePort(printer->hXcv); + }
monitor_unload(printer->pm);
@@ -1224,11 +1256,14 @@ static HANDLE printer_alloc_handle(LPCWSTR name, LPPRINTER_DEFAULTSW pDefault) }
if (printer->pm) { - if ((printer->pm->monitor) && (printer->pm->monitor->pfnXcvOpenPort)) { + if (printer->pm->monitor2 && printer->pm->monitor2->pfnXcvOpenPort) + printer->pm->monitor2->pfnXcvOpenPort(0, &printername[len], + pDefault ? pDefault->DesiredAccess : 0, + &printer->hXcv); + else if (printer->pm->monitor && printer->pm->monitor->pfnXcvOpenPort) printer->pm->monitor->pfnXcvOpenPort(&printername[len], - pDefault ? pDefault->DesiredAccess : 0, - &printer->hXcv); - } + pDefault ? pDefault->DesiredAccess : 0, + &printer->hXcv); if (printer->hXcv == NULL) { printer_free(printer); SetLastError(ERROR_INVALID_PARAMETER); @@ -1587,7 +1622,13 @@ static BOOL WINAPI fpAddPort(LPWSTR pName, HWND hWnd, LPWSTR pMonitorName) }
pm = monitor_load(pMonitorName, NULL); - if (pm && pm->monitor && pm->monitor->pfnAddPort) { + if (!pm) return FALSE; + + if (pm->monitor2 && pm->monitor2->pfnAddPort) { + res = pm->monitor2->pfnAddPort(pName, hWnd, pMonitorName); + TRACE("got %d with %u (%s)\n", res, GetLastError(), debugstr_w(pm->dllname)); + } + else if (pm->monitor && pm->monitor->pfnAddPort) { res = pm->monitor->pfnAddPort(pName, hWnd, pMonitorName); TRACE("got %d with %u (%s)\n", res, GetLastError(), debugstr_w(pm->dllname)); } @@ -1664,7 +1705,15 @@ static BOOL WINAPI fpAddPortEx(LPWSTR pName, DWORD level, LPBYTE pBuffer, LPWSTR
/* load the Monitor */ pm = monitor_load(pMonitorName, NULL); - if (pm && pm->monitor && pm->monitor->pfnAddPortEx) { + if (!pm) return FALSE; + + if (pm->monitor2 && pm->monitor2->pfnAddPortEx) + { + res = pm->monitor2->pfnAddPortEx(pName, level, pBuffer, pMonitorName); + TRACE("got %d with %u (%s)\n", res, GetLastError(), debugstr_w(pm->dllname)); + } + else if (pm->monitor && pm->monitor->pfnAddPortEx) + { res = pm->monitor->pfnAddPortEx(pName, level, pBuffer, pMonitorName); TRACE("got %d with %u (%s)\n", res, GetLastError(), debugstr_w(pm->dllname)); } @@ -1778,7 +1827,17 @@ static BOOL WINAPI fpConfigurePort(LPWSTR pName, HWND hWnd, LPWSTR pPortName) }
pm = monitor_load_by_port(pPortName); - if (pm && pm->monitor && pm->monitor->pfnConfigurePort) { + if (!pm) return FALSE; + + if (pm->monitor2 && pm->monitor2->pfnConfigurePort) + { + TRACE("use %s for %s (monitor %p: %s)\n", debugstr_w(pm->name), + debugstr_w(pPortName), pm, debugstr_w(pm->dllname)); + res = pm->monitor2->pfnConfigurePort(pName, hWnd, pPortName); + TRACE("got %d with %u\n", res, GetLastError()); + } + else if (pm->monitor && pm->monitor->pfnConfigurePort) + { TRACE("use %s for %s (monitor %p: %s)\n", debugstr_w(pm->name), debugstr_w(pPortName), pm, debugstr_w(pm->dllname)); res = pm->monitor->pfnConfigurePort(pName, hWnd, pPortName); @@ -1908,7 +1967,17 @@ static BOOL WINAPI fpDeletePort(LPWSTR pName, HWND hWnd, LPWSTR pPortName) }
pm = monitor_load_by_port(pPortName); - if (pm && pm->monitor && pm->monitor->pfnDeletePort) { + if (!pm) return FALSE; + + if (pm->monitor2 && pm->monitor2->pfnDeletePort) + { + TRACE("use %s for %s (monitor %p: %s)\n", debugstr_w(pm->name), + debugstr_w(pPortName), pm, debugstr_w(pm->dllname)); + res = pm->monitor2->pfnDeletePort(pName, hWnd, pPortName); + TRACE("got %d with %u\n", res, GetLastError()); + } + else if (pm->monitor && pm->monitor->pfnDeletePort) + { TRACE("use %s for %s (monitor %p: %s)\n", debugstr_w(pm->name), debugstr_w(pPortName), pm, debugstr_w(pm->dllname)); res = pm->monitor->pfnDeletePort(pName, hWnd, pPortName); @@ -2338,7 +2407,11 @@ static BOOL WINAPI fpXcvData(HANDLE hXcv, LPCWSTR pszDataName, PBYTE pInputData,
*pcbOutputNeeded = 0;
- *pdwStatus = printer->pm->monitor->pfnXcvDataPort(printer->hXcv, pszDataName, + if (printer->pm->monitor2) + *pdwStatus = printer->pm->monitor2->pfnXcvDataPort(printer->hXcv, pszDataName, + pInputData, cbInputData, pOutputData, cbOutputData, pcbOutputNeeded); + else if (printer->pm->monitor) + *pdwStatus = printer->pm->monitor->pfnXcvDataPort(printer->hXcv, pszDataName, pInputData, cbInputData, pOutputData, cbOutputData, pcbOutputNeeded);
return TRUE;
On Fri, Aug 30, 2019 at 04:06:34PM +0800, Dmitry Timoshkov wrote:
Signed-off-by: Dmitry Timoshkov dmitry@baikal.ru
dlls/localspl/provider.c | 149 +++++++++++++++++++++++++++++---------- 1 file changed, 111 insertions(+), 38 deletions(-)
diff --git a/dlls/localspl/provider.c b/dlls/localspl/provider.c index 8e5e3428d5..2b3f9bac6e 100644 --- a/dlls/localspl/provider.c +++ b/dlls/localspl/provider.c @@ -66,9 +66,9 @@ typedef struct { LPWSTR dllname; PMONITORUI monitorUI; LPMONITOR monitor;
- LPMONITOR2 monitor2; HMODULE hdll; DWORD refcount;
- DWORD dwMonitorSize;
} monitor_t;
Hi Dmitry,
Is there a reason why we can't simply replace the MONITOR struct with a MONITOR2 struct? It would require a bit more work at initialisation but then calling the functions would be rather simpler.
Thanks, Huw.
Hi Huw,
Huw Davies huw@codeweavers.com wrote:
@@ -66,9 +66,9 @@ typedef struct { LPWSTR dllname; PMONITORUI monitorUI; LPMONITOR monitor;
- LPMONITOR2 monitor2; HMODULE hdll; DWORD refcount;
- DWORD dwMonitorSize;
} monitor_t;
Hi Dmitry,
Is there a reason why we can't simply replace the MONITOR struct with a MONITOR2 struct? It would require a bit more work at initialisation but then calling the functions would be rather simpler.
I considered that, and even have done an initial implementation that way. However, the structures have different prototypes for some callbacks, and in order to take care of this we'd need to create wrappers. I'd rather decided to use an appropriate table instead.
On Wed, Sep 04, 2019 at 04:34:14PM +0800, Dmitry Timoshkov wrote:
Hi Huw,
Huw Davies huw@codeweavers.com wrote:
@@ -66,9 +66,9 @@ typedef struct { LPWSTR dllname; PMONITORUI monitorUI; LPMONITOR monitor;
- LPMONITOR2 monitor2; HMODULE hdll; DWORD refcount;
- DWORD dwMonitorSize;
} monitor_t;
Hi Dmitry,
Is there a reason why we can't simply replace the MONITOR struct with a MONITOR2 struct? It would require a bit more work at initialisation but then calling the functions would be rather simpler.
I considered that, and even have done an initial implementation that way. However, the structures have different prototypes for some callbacks, and in order to take care of this we'd need to create wrappers. I'd rather decided to use an appropriate table instead.
It's only a couple of functions (OpenPortEx and XcvOpenPort) and all you'd need would be something like:
if (monitor.cbSize == sizeof(MONITOR)) monitor.pfnXcvOpenPort( old_args ); else monitor.pfnXcvOpenPort( new_args );
which is more or less what you're doing for every call at the moment.
This would also have to benefit of actually copying the fn ptrs returned by the init function, rather than assuming the driver keeps the structure available for its lifetime.
Huw.
On Wed, Sep 04, 2019 at 09:58:31AM +0100, Huw Davies wrote:
On Wed, Sep 04, 2019 at 04:34:14PM +0800, Dmitry Timoshkov wrote:
Hi Huw,
Huw Davies huw@codeweavers.com wrote:
@@ -66,9 +66,9 @@ typedef struct { LPWSTR dllname; PMONITORUI monitorUI; LPMONITOR monitor;
- LPMONITOR2 monitor2; HMODULE hdll; DWORD refcount;
- DWORD dwMonitorSize;
} monitor_t;
Hi Dmitry,
Is there a reason why we can't simply replace the MONITOR struct with a MONITOR2 struct? It would require a bit more work at initialisation but then calling the functions would be rather simpler.
I considered that, and even have done an initial implementation that way. However, the structures have different prototypes for some callbacks, and in order to take care of this we'd need to create wrappers. I'd rather decided to use an appropriate table instead.
It's only a couple of functions (OpenPortEx and XcvOpenPort) and all you'd need would be something like:
if (monitor.cbSize == sizeof(MONITOR)) monitor.pfnXcvOpenPort( old_args ); else monitor.pfnXcvOpenPort( new_args );
Of course it's a bit more complicated than this. What you could do is change monitor_t to something like:
... PMONITORUI monitorUI; MONITOR2 monitor; BOOL (WINAPI *old_open_port_ex)(LPWSTR, LPWSTR, PHANDLE, struct _MONITOR *); BOOL (WINAPI *old_xcv_open_port)(LPCWSTR, ACCESS_MASK, PHANDLE); HMODULE hdll; ...
On initialization set up the monitor fn ptrs as appropriate, then the call to XcvOpenPort looks like:
if (pm->monitor.old_xcv_open_port) pm->monitor.old_xcv_open_port( old_args ); else pm->monitor.pfnXcvOpenPort( new_args );
The call to OpenPortEx will be a little trickier, but we don't use that at the moment anyway.
Huw.
Huw Davies huw@codeweavers.com wrote:
Is there a reason why we can't simply replace the MONITOR struct with a MONITOR2 struct? It would require a bit more work at initialisation but then calling the functions would be rather simpler.
I considered that, and even have done an initial implementation that way. However, the structures have different prototypes for some callbacks, and in order to take care of this we'd need to create wrappers. I'd rather decided to use an appropriate table instead.
It's only a couple of functions (OpenPortEx and XcvOpenPort) and all you'd need would be something like:
if (monitor.cbSize == sizeof(MONITOR)) monitor.pfnXcvOpenPort( old_args ); else monitor.pfnXcvOpenPort( new_args );
Of course it's a bit more complicated than this. What you could do is change monitor_t to something like:
... PMONITORUI monitorUI; MONITOR2 monitor; BOOL (WINAPI *old_open_port_ex)(LPWSTR, LPWSTR, PHANDLE, struct _MONITOR *); BOOL (WINAPI *old_xcv_open_port)(LPCWSTR, ACCESS_MASK, PHANDLE); HMODULE hdll; ...
On initialization set up the monitor fn ptrs as appropriate, then the call to XcvOpenPort looks like:
if (pm->monitor.old_xcv_open_port) pm->monitor.old_xcv_open_port( old_args ); else pm->monitor.pfnXcvOpenPort( new_args );
The call to OpenPortEx will be a little trickier, but we don't use that at the moment anyway.
Now you see that it's similar level of complexity in comparison what I've implemented, and in addition there's a finished patch. I'd prefer to leave it as it is now, and change it later when it's really needed.
On Wed, Sep 04, 2019 at 06:38:49PM +0800, Dmitry Timoshkov wrote:
Huw Davies huw@codeweavers.com wrote:
Is there a reason why we can't simply replace the MONITOR struct with a MONITOR2 struct? It would require a bit more work at initialisation but then calling the functions would be rather simpler.
I considered that, and even have done an initial implementation that way. However, the structures have different prototypes for some callbacks, and in order to take care of this we'd need to create wrappers. I'd rather decided to use an appropriate table instead.
It's only a couple of functions (OpenPortEx and XcvOpenPort) and all you'd need would be something like:
if (monitor.cbSize == sizeof(MONITOR)) monitor.pfnXcvOpenPort( old_args ); else monitor.pfnXcvOpenPort( new_args );
Of course it's a bit more complicated than this. What you could do is change monitor_t to something like:
... PMONITORUI monitorUI; MONITOR2 monitor; BOOL (WINAPI *old_open_port_ex)(LPWSTR, LPWSTR, PHANDLE, struct _MONITOR *); BOOL (WINAPI *old_xcv_open_port)(LPCWSTR, ACCESS_MASK, PHANDLE); HMODULE hdll; ...
On initialization set up the monitor fn ptrs as appropriate, then the call to XcvOpenPort looks like:
if (pm->monitor.old_xcv_open_port) pm->monitor.old_xcv_open_port( old_args ); else pm->monitor.pfnXcvOpenPort( new_args );
The call to OpenPortEx will be a little trickier, but we don't use that at the moment anyway.
Now you see that it's similar level of complexity in comparison what I've implemented.
Well hardly. Sure it'll make initialization more complicated (though it's really not that bad) but each call-site (apart from one or two exceptions) is simple. Whereas your current patch has complications at every call-site, which won't scale well as we implement more functionality.
Huw.