[PATCH] localspl: Implement AddMonitor
Detlef Riekenberg
wine.dev at web.de
Thu Sep 18 15:35:29 CDT 2008
---
dlls/localspl/localspl_main.c | 321 +++++++++++++++++++++++++++++++++++++-
dlls/localspl/localspl_private.h | 7 +-
2 files changed, 326 insertions(+), 2 deletions(-)
diff --git a/dlls/localspl/localspl_main.c b/dlls/localspl/localspl_main.c
index a6a7980..dc18edb 100644
--- a/dlls/localspl/localspl_main.c
+++ b/dlls/localspl/localspl_main.c
@@ -40,6 +40,17 @@ WINE_DEFAULT_DEBUG_CHANNEL(localspl);
/* ############################### */
+static CRITICAL_SECTION monitor_handles_cs;
+static CRITICAL_SECTION_DEBUG monitor_handles_cs_debug =
+{
+ 0, 0, &monitor_handles_cs,
+ { &monitor_handles_cs_debug.ProcessLocksList, &monitor_handles_cs_debug.ProcessLocksList },
+ 0, 0, { (DWORD_PTR)(__FILE__ ": monitor_handles_cs") }
+};
+static CRITICAL_SECTION monitor_handles_cs = { &monitor_handles_cs_debug, -1, 0, 0, 0, 0 };
+
+/* ############################### */
+
typedef struct {
WCHAR src[MAX_PATH+MAX_PATH];
WCHAR dst[MAX_PATH+MAX_PATH];
@@ -71,6 +82,9 @@ typedef struct {
/* ############################### */
+static struct list monitor_handles = LIST_INIT( monitor_handles );
+static monitor_t * pm_localport;
+
HINSTANCE LOCALSPL_hInstance = NULL;
static const PRINTPROVIDOR * pp = NULL;
@@ -91,6 +105,7 @@ static const WCHAR fmt_driversW[] = { 'S','y','s','t','e','m','\\',
'%','s','\\','D','r','i','v','e','r','s','%','s',0 };
static const WCHAR hardwareidW[] = {'H','a','r','d','w','a','r','e','I','D',0};
static const WCHAR help_fileW[] = {'H','e','l','p',' ','F','i','l','e',0};
+static const WCHAR localportW[] = {'L','o','c','a','l',' ','P','o','r','t',0};
static const WCHAR locationW[] = {'L','o','c','a','t','i','o','n',0};
static const WCHAR manufacturerW[] = {'M','a','n','u','f','a','c','t','u','r','e','r',0};
static const WCHAR monitorW[] = {'M','o','n','i','t','o','r',0};
@@ -135,6 +150,25 @@ static const DWORD di_sizeof[] = {0, sizeof(DRIVER_INFO_1W), sizeof(DRIVER_INFO_
/******************************************************************
+ * strdupW [internal]
+ *
+ * create a copy of a unicode-string
+ *
+ */
+
+static LPWSTR strdupW(LPCWSTR p)
+{
+ LPWSTR ret;
+ DWORD len;
+
+ if(!p) return NULL;
+ len = (lstrlenW(p) + 1) * sizeof(WCHAR);
+ ret = heap_alloc(len);
+ memcpy(ret, p, len);
+ return ret;
+}
+
+/******************************************************************
* apd_copyfile [internal]
*
* Copy a file from the driverdirectory to the versioned directory
@@ -237,6 +271,190 @@ static LONG copy_servername_from_name(LPCWSTR name, LPWSTR target)
}
/******************************************************************
+ * monitor_unload [internal]
+ *
+ * release a printmonitor and unload it from memory, when needed
+ *
+ */
+static void monitor_unload(monitor_t * pm)
+{
+ if (pm == NULL) return;
+ TRACE("%p (refcount: %d) %s\n", pm, pm->refcount, debugstr_w(pm->name));
+
+ EnterCriticalSection(&monitor_handles_cs);
+
+ if (pm->refcount) pm->refcount--;
+
+ if (pm->refcount == 0) {
+ list_remove(&pm->entry);
+ FreeLibrary(pm->hdll);
+ heap_free(pm->name);
+ heap_free(pm->dllname);
+ heap_free(pm);
+ }
+ LeaveCriticalSection(&monitor_handles_cs);
+}
+
+/******************************************************************
+ * monitor_load [internal]
+ *
+ * load a printmonitor, get the dllname from the registry, when needed
+ * initialize the monitor and dump found function-pointers
+ *
+ * On failure, SetLastError() is called and NULL is returned
+ */
+
+static monitor_t * monitor_load(LPCWSTR name, LPWSTR dllname)
+{
+ LPMONITOR2 (WINAPI *pInitializePrintMonitor2) (PMONITORINIT, LPHANDLE);
+ PMONITORUI (WINAPI *pInitializePrintMonitorUI)(VOID);
+ LPMONITOREX (WINAPI *pInitializePrintMonitor) (LPWSTR);
+ DWORD (WINAPI *pInitializeMonitorEx)(LPWSTR, LPMONITOR);
+ DWORD (WINAPI *pInitializeMonitor) (LPWSTR);
+
+ monitor_t * pm = NULL;
+ monitor_t * cursor;
+ LPWSTR regroot = NULL;
+ LPWSTR driver = dllname;
+
+ TRACE("(%s, %s)\n", debugstr_w(name), debugstr_w(dllname));
+ /* Is the Monitor already loaded? */
+ EnterCriticalSection(&monitor_handles_cs);
+
+ if (name) {
+ LIST_FOR_EACH_ENTRY(cursor, &monitor_handles, monitor_t, entry)
+ {
+ if (cursor->name && (lstrcmpW(name, cursor->name) == 0)) {
+ pm = cursor;
+ break;
+ }
+ }
+ }
+
+ if (pm == NULL) {
+ pm = heap_alloc_zero(sizeof(monitor_t));
+ if (pm == NULL) goto cleanup;
+ list_add_tail(&monitor_handles, &pm->entry);
+ }
+ pm->refcount++;
+
+ if (pm->name == NULL) {
+ /* Load the monitor */
+ LPMONITOREX pmonitorEx;
+ DWORD len;
+
+ if (name) {
+ len = lstrlenW(monitorsW) + lstrlenW(name) + 2;
+ regroot = heap_alloc(len * sizeof(WCHAR));
+ }
+
+ 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 (RegQueryValueExW(hroot, driverW, NULL, NULL, NULL,
+ &namesize) == ERROR_SUCCESS) {
+ driver = heap_alloc(namesize);
+ RegQueryValueExW(hroot, driverW, NULL, NULL, (LPBYTE) driver, &namesize) ;
+ }
+ RegCloseKey(hroot);
+ }
+ }
+ }
+
+ pm->name = strdupW(name);
+ pm->dllname = strdupW(driver);
+
+ if ((name && (!regroot || !pm->name)) || !pm->dllname) {
+ monitor_unload(pm);
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ pm = NULL;
+ goto cleanup;
+ }
+
+ pm->hdll = LoadLibraryW(driver);
+ TRACE("%p: LoadLibrary(%s) => %d\n", pm->hdll, debugstr_w(driver), GetLastError());
+
+ if (pm->hdll == NULL) {
+ monitor_unload(pm);
+ SetLastError(ERROR_MOD_NOT_FOUND);
+ pm = NULL;
+ goto cleanup;
+ }
+
+ pInitializePrintMonitor2 = (void *)GetProcAddress(pm->hdll, "InitializePrintMonitor2");
+ pInitializePrintMonitorUI = (void *)GetProcAddress(pm->hdll, "InitializePrintMonitorUI");
+ pInitializePrintMonitor = (void *)GetProcAddress(pm->hdll, "InitializePrintMonitor");
+ pInitializeMonitorEx = (void *)GetProcAddress(pm->hdll, "InitializeMonitorEx");
+ pInitializeMonitor = (void *)GetProcAddress(pm->hdll, "InitializeMonitor");
+
+
+ TRACE("%p: %s,pInitializePrintMonitor2\n", pInitializePrintMonitor2, debugstr_w(driver));
+ TRACE("%p: %s,pInitializePrintMonitorUI\n", pInitializePrintMonitorUI, debugstr_w(driver));
+ TRACE("%p: %s,pInitializePrintMonitor\n", pInitializePrintMonitor, debugstr_w(driver));
+ TRACE("%p: %s,pInitializeMonitorEx\n", pInitializeMonitorEx, debugstr_w(driver));
+ TRACE("%p: %s,pInitializeMonitor\n", pInitializeMonitor, debugstr_w(driver));
+
+ if (pInitializePrintMonitorUI != NULL) {
+ pm->monitorUI = pInitializePrintMonitorUI();
+ TRACE("%p: MONITORUI from %s,InitializePrintMonitorUI()\n", pm->monitorUI, debugstr_w(driver));
+ if (pm->monitorUI) {
+ TRACE("0x%08x: dwMonitorSize (%d)\n",
+ pm->monitorUI->dwMonitorUISize, pm->monitorUI->dwMonitorUISize);
+
+ }
+ }
+
+ if (pInitializePrintMonitor && regroot) {
+ pmonitorEx = pInitializePrintMonitor(regroot);
+ TRACE("%p: LPMONITOREX from %s,InitializePrintMonitor(%s)\n",
+ pmonitorEx, debugstr_w(driver), debugstr_w(regroot));
+
+ if (pmonitorEx) {
+ pm->dwMonitorSize = pmonitorEx->dwMonitorSize;
+ pm->monitor = &(pmonitorEx->Monitor);
+ }
+ }
+
+ if (pm->monitor) {
+ 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) {
+ FIXME("%s,InitializeMonitorEx not implemented\n", debugstr_w(driver));
+ }
+ if (pInitializeMonitor != NULL) {
+ FIXME("%s,InitializeMonitor not implemented\n", debugstr_w(driver));
+ }
+ }
+ if (!pm->monitor && !pm->monitorUI) {
+ monitor_unload(pm);
+ SetLastError(ERROR_PROC_NOT_FOUND);
+ pm = NULL;
+ }
+ }
+cleanup:
+ if ((pm_localport == NULL) && (pm != NULL) && (lstrcmpW(pm->name, localportW) == 0)) {
+ pm->refcount++;
+ pm_localport = pm;
+ }
+ LeaveCriticalSection(&monitor_handles_cs);
+ if (driver != dllname) heap_free(driver);
+ heap_free(regroot);
+ TRACE("=> %p\n", pm);
+ return pm;
+}
+
+/******************************************************************
* Return the number of bytes for an multi_sz string.
* The result includes all \0s
* (specifically the extra \0, that is needed as multi_sz terminator).
@@ -663,6 +881,107 @@ static BOOL WINAPI myAddPrinterDriverEx(DWORD level, LPBYTE pDriverInfo, DWORD d
}
/******************************************************************************
+ * fpAddMonitor [exported through PRINTPROVIDOR]
+ *
+ * Install a Printmonitor
+ *
+ * PARAMS
+ * pName [I] Servername or NULL (local Computer)
+ * Level [I] Structure-Level (Must be 2)
+ * pMonitors [I] PTR to MONITOR_INFO_2
+ *
+ * RETURNS
+ * Success: TRUE
+ * Failure: FALSE
+ *
+ * NOTES
+ * All Files for the Monitor must already be copied to %winsysdir% ("%SystemRoot%\system32")
+ *
+ */
+BOOL WINAPI fpAddMonitor(LPWSTR pName, DWORD Level, LPBYTE pMonitors)
+{
+ monitor_t * pm = NULL;
+ LPMONITOR_INFO_2W mi2w;
+ HKEY hroot = NULL;
+ HKEY hentry = NULL;
+ DWORD disposition;
+ BOOL res = FALSE;
+
+ mi2w = (LPMONITOR_INFO_2W) pMonitors;
+ TRACE("(%s, %d, %p): %s %s %s\n", debugstr_w(pName), Level, pMonitors,
+ debugstr_w(mi2w ? mi2w->pName : NULL),
+ debugstr_w(mi2w ? mi2w->pEnvironment : NULL),
+ debugstr_w(mi2w ? mi2w->pDLLName : NULL));
+
+ if (copy_servername_from_name(pName, NULL)) {
+ FIXME("server %s not supported\n", debugstr_w(pName));
+ SetLastError(ERROR_ACCESS_DENIED);
+ return FALSE;
+ }
+
+ if (!mi2w->pName || (! mi2w->pName[0])) {
+ WARN("pName not valid : %s\n", debugstr_w(mi2w->pName));
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+ if (!mi2w->pEnvironment || lstrcmpW(mi2w->pEnvironment, x86_envnameW)) {
+ WARN("Environment %s requested (we support only %s)\n",
+ debugstr_w(mi2w->pEnvironment), debugstr_w(x86_envnameW));
+ SetLastError(ERROR_INVALID_ENVIRONMENT);
+ return FALSE;
+ }
+
+ if (!mi2w->pDLLName || (! mi2w->pDLLName[0])) {
+ WARN("pDLLName not valid : %s\n", debugstr_w(mi2w->pDLLName));
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ /* Load and initialize the monitor. SetLastError() is called on failure */
+ if ((pm = monitor_load(mi2w->pName, mi2w->pDLLName)) == NULL) {
+ return FALSE;
+ }
+ monitor_unload(pm);
+
+ if (RegCreateKeyW(HKEY_LOCAL_MACHINE, monitorsW, &hroot) != ERROR_SUCCESS) {
+ ERR("unable to create key %s\n", debugstr_w(monitorsW));
+ return FALSE;
+ }
+
+ if (RegCreateKeyExW(hroot, mi2w->pName, 0, NULL, REG_OPTION_NON_VOLATILE,
+ KEY_WRITE | KEY_QUERY_VALUE, NULL, &hentry,
+ &disposition) == ERROR_SUCCESS) {
+
+ /* Some installers set options for the port before calling AddMonitor.
+ We query the "Driver" entry to verify that the monitor is installed,
+ before we return an error.
+ When a user installs two print monitors at the same time with the
+ same name, a race condition is possible but silently ignored. */
+
+ DWORD namesize = 0;
+
+ if ((disposition == REG_OPENED_EXISTING_KEY) &&
+ (RegQueryValueExW(hentry, driverW, NULL, NULL, NULL,
+ &namesize) == ERROR_SUCCESS)) {
+ TRACE("monitor %s already exists\n", debugstr_w(mi2w->pName));
+ /* 9x use ERROR_ALREADY_EXISTS */
+ SetLastError(ERROR_PRINT_MONITOR_ALREADY_INSTALLED);
+ }
+ else
+ {
+ INT len;
+ len = (lstrlenW(mi2w->pDLLName) +1) * sizeof(WCHAR);
+ res = (RegSetValueExW(hentry, driverW, 0, REG_SZ,
+ (LPBYTE) mi2w->pDLLName, len) == ERROR_SUCCESS);
+ }
+ RegCloseKey(hentry);
+ }
+
+ RegCloseKey(hroot);
+ return (res);
+}
+
+/******************************************************************************
* fpAddPrinterDriverEx [exported through PRINTPROVIDOR]
*
* Install a Printer Driver with the Option to upgrade / downgrade the Files
@@ -879,7 +1198,7 @@ static const PRINTPROVIDOR * get_backend(void)
NULL, /* fpAddPrinterConnection */
NULL, /* fpDeletePrinterConnection */
NULL, /* fpPrinterMessageBox */
- NULL, /* fpAddMonitor */
+ fpAddMonitor,
fpDeleteMonitor,
NULL, /* fpResetPrinter */
NULL, /* fpGetPrinterDriverEx */
diff --git a/dlls/localspl/localspl_private.h b/dlls/localspl/localspl_private.h
index 614e108..8e67ed3 100644
--- a/dlls/localspl/localspl_private.h
+++ b/dlls/localspl/localspl_private.h
@@ -51,11 +51,16 @@ extern HINSTANCE LOCALSPL_hInstance;
/* ## Memory allocation functions ## */
-static inline void __WINE_ALLOC_SIZE(1) *heap_alloc( size_t len )
+static inline void * __WINE_ALLOC_SIZE(1) heap_alloc( size_t len )
{
return HeapAlloc( GetProcessHeap(), 0, len );
}
+static inline void * __WINE_ALLOC_SIZE(1) heap_alloc_zero( size_t len )
+{
+ return HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, len );
+}
+
static inline BOOL heap_free( void *mem )
{
return HeapFree( GetProcessHeap(), 0, mem );
--
1.5.4.3
--=-uuYeRvOLSvIGBA76lOJb--
More information about the wine-patches
mailing list