ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

localmon.c
Go to the documentation of this file.
00001 /*
00002  * Implementation of the Local Printmonitor
00003  *
00004  * Copyright 2006 Detlef Riekenberg
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00019  */
00020 
00021 #include <stdarg.h>
00022 
00023 #define COBJMACROS
00024 #define NONAMELESSUNION
00025 
00026 #include "windef.h"
00027 #include "winbase.h"
00028 #include "wingdi.h"
00029 #include "winuser.h"
00030 #include "winreg.h"
00031 
00032 #include "winspool.h"
00033 #include "ddk/winsplp.h"
00034 #include "localspl_private.h"
00035 
00036 #include "wine/debug.h"
00037 #include "wine/list.h"
00038 #include "wine/unicode.h"
00039 
00040 
00041 WINE_DEFAULT_DEBUG_CHANNEL(localspl);
00042 
00043 /*****************************************************/
00044 
00045 static CRITICAL_SECTION port_handles_cs;
00046 static CRITICAL_SECTION_DEBUG port_handles_cs_debug =
00047 {
00048     0, 0, &port_handles_cs,
00049     { &port_handles_cs_debug.ProcessLocksList, &port_handles_cs_debug.ProcessLocksList },
00050       0, 0, { (DWORD_PTR)(__FILE__ ": port_handles_cs") }
00051 };
00052 static CRITICAL_SECTION port_handles_cs = { &port_handles_cs_debug, -1, 0, 0, 0, 0 };
00053 
00054 
00055 static CRITICAL_SECTION xcv_handles_cs;
00056 static CRITICAL_SECTION_DEBUG xcv_handles_cs_debug =
00057 {
00058     0, 0, &xcv_handles_cs,
00059     { &xcv_handles_cs_debug.ProcessLocksList, &xcv_handles_cs_debug.ProcessLocksList },
00060       0, 0, { (DWORD_PTR)(__FILE__ ": xcv_handles_cs") }
00061 };
00062 static CRITICAL_SECTION xcv_handles_cs = { &xcv_handles_cs_debug, -1, 0, 0, 0, 0 };
00063 
00064 /* ############################### */
00065 
00066 typedef struct {
00067     struct list entry;
00068     DWORD   type;
00069     WCHAR   nameW[1];
00070 } port_t;
00071 
00072 typedef struct {
00073     struct list entry;
00074     ACCESS_MASK GrantedAccess;
00075     WCHAR       nameW[1];
00076 } xcv_t;
00077 
00078 static struct list port_handles = LIST_INIT( port_handles );
00079 static struct list xcv_handles = LIST_INIT( xcv_handles );
00080 
00081 /* ############################### */
00082 
00083 static const WCHAR cmd_AddPortW[] = {'A','d','d','P','o','r','t',0};
00084 static const WCHAR cmd_DeletePortW[] = {'D','e','l','e','t','e','P','o','r','t',0};
00085 static const WCHAR cmd_ConfigureLPTPortCommandOKW[] = {'C','o','n','f','i','g','u','r','e',
00086                                     'L','P','T','P','o','r','t',
00087                                     'C','o','m','m','a','n','d','O','K',0};
00088 
00089 static const WCHAR cmd_GetDefaultCommConfigW[] = {'G','e','t',
00090                                     'D','e','f','a','u','l','t',
00091                                     'C','o','m','m','C','o','n','f','i','g',0};
00092 
00093 static const WCHAR cmd_GetTransmissionRetryTimeoutW[] = {'G','e','t',
00094                                     'T','r','a','n','s','m','i','s','s','i','o','n',
00095                                     'R','e','t','r','y','T','i','m','e','o','u','t',0};
00096 
00097 static const WCHAR cmd_MonitorUIW[] = {'M','o','n','i','t','o','r','U','I',0};
00098 static const WCHAR cmd_PortIsValidW[] = {'P','o','r','t','I','s','V','a','l','i','d',0};
00099 static const WCHAR cmd_SetDefaultCommConfigW[] = {'S','e','t',
00100                                     'D','e','f','a','u','l','t',
00101                                     'C','o','m','m','C','o','n','f','i','g',0};
00102 
00103 static const WCHAR dllnameuiW[] = {'l','o','c','a','l','u','i','.','d','l','l',0};
00104 static const WCHAR emptyW[] = {0};
00105 static const WCHAR LocalPortW[] = {'L','o','c','a','l',' ','P','o','r','t',0};
00106 
00107 static const WCHAR portname_LPT[]  = {'L','P','T',0};
00108 static const WCHAR portname_COM[]  = {'C','O','M',0};
00109 static const WCHAR portname_FILE[] = {'F','I','L','E',':',0};
00110 static const WCHAR portname_CUPS[] = {'C','U','P','S',':',0};
00111 static const WCHAR portname_LPR[]  = {'L','P','R',':',0};
00112 
00113 static const WCHAR TransmissionRetryTimeoutW[] = {'T','r','a','n','s','m','i','s','s','i','o','n',
00114                                     'R','e','t','r','y','T','i','m','e','o','u','t',0};
00115 
00116 static const WCHAR WinNT_CV_PortsW[] = {'S','o','f','t','w','a','r','e','\\',
00117                                         'M','i','c','r','o','s','o','f','t','\\',
00118                                         'W','i','n','d','o','w','s',' ','N','T','\\',
00119                                         'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
00120                                         'P','o','r','t','s',0};
00121 
00122 static const WCHAR WinNT_CV_WindowsW[] = {'S','o','f','t','w','a','r','e','\\',
00123                                         'M','i','c','r','o','s','o','f','t','\\',
00124                                         'W','i','n','d','o','w','s',' ','N','T','\\',
00125                                         'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
00126                                         'W','i','n','d','o','w','s',0};
00127 
00128 
00129 /******************************************************************
00130  * does_port_exist (internal)
00131  *
00132  * returns TRUE, when the Port already exists
00133  *
00134  */
00135 static BOOL does_port_exist(LPCWSTR myname)
00136 {
00137 
00138     LPPORT_INFO_1W  pi;
00139     DWORD   needed = 0;
00140     DWORD   returned;
00141     DWORD   id;
00142 
00143     TRACE("(%s)\n", debugstr_w(myname));
00144 
00145     id = EnumPortsW(NULL, 1, NULL, 0, &needed, &returned);
00146     pi = heap_alloc(needed);
00147     returned = 0;
00148     if (pi)
00149         id = EnumPortsW(NULL, 1, (LPBYTE) pi, needed, &needed, &returned);
00150 
00151     if (id && returned > 0) {
00152         /* we got a number of valid names. */
00153         for (id = 0; id < returned; id++)
00154         {
00155             if (lstrcmpiW(myname, pi[id].pName) == 0) {
00156                 TRACE("(%u) found %s\n", id, debugstr_w(pi[id].pName));
00157                 heap_free(pi);
00158                 return TRUE;
00159             }
00160         }
00161     }
00162 
00163     heap_free(pi);
00164     return FALSE;
00165 }
00166 
00167 /******************************************************************
00168  * enumerate the local Ports from the Registry (internal)  
00169  *
00170  * See localmon_EnumPortsW.
00171  *
00172  * NOTES
00173  *  returns the needed size (in bytes) for pPorts
00174  *  and *lpreturned is set to number of entries returned in pPorts
00175  *
00176  */
00177 
00178 static DWORD get_ports_from_reg(DWORD level, LPBYTE pPorts, DWORD cbBuf, LPDWORD lpreturned)
00179 {
00180     HKEY    hroot = 0;
00181     LPWSTR  ptr;
00182     LPPORT_INFO_2W out;
00183     WCHAR   portname[MAX_PATH];
00184     WCHAR   res_PortW[IDS_LOCALPORT_MAXLEN];
00185     WCHAR   res_MonitorW[IDS_LOCALMONITOR_MAXLEN];
00186     INT     reslen_PortW;
00187     INT     reslen_MonitorW;
00188     DWORD   len;
00189     DWORD   res;
00190     DWORD   needed = 0;
00191     DWORD   numentries;
00192     DWORD   entrysize;
00193     DWORD   id = 0;
00194 
00195     TRACE("(%d, %p, %d, %p)\n", level, pPorts, cbBuf, lpreturned);
00196 
00197     entrysize = (level == 1) ? sizeof(PORT_INFO_1W) : sizeof(PORT_INFO_2W);
00198 
00199     numentries = *lpreturned;           /* this is 0, when we scan the registry */
00200     needed = entrysize * numentries;
00201     ptr = (LPWSTR) &pPorts[needed];
00202 
00203     if (needed > cbBuf) pPorts = NULL;  /* No buffer for the structs */
00204 
00205     numentries = 0;
00206     needed = 0;
00207 
00208     /* we do not check more parameters as done in windows */
00209     if ((level < 1) || (level > 2)) {
00210         goto getports_cleanup;
00211     }
00212 
00213     /* "+1" for '\0' */
00214     reslen_MonitorW = LoadStringW(LOCALSPL_hInstance, IDS_LOCALMONITOR, res_MonitorW, IDS_LOCALMONITOR_MAXLEN) + 1;  
00215     reslen_PortW = LoadStringW(LOCALSPL_hInstance, IDS_LOCALPORT, res_PortW, IDS_LOCALPORT_MAXLEN) + 1;  
00216 
00217     res = RegOpenKeyW(HKEY_LOCAL_MACHINE, WinNT_CV_PortsW, &hroot);
00218     if (res == ERROR_SUCCESS) {
00219 
00220         /* Scan all Port-Names */
00221         while (res == ERROR_SUCCESS) {
00222             len = MAX_PATH;
00223             portname[0] = '\0';
00224             res = RegEnumValueW(hroot, id, portname, &len, NULL, NULL, NULL, NULL);
00225 
00226             if ((res == ERROR_SUCCESS) && (portname[0])) {
00227                 numentries++;
00228                 /* calculate the required size */
00229                 needed += entrysize;
00230                 needed += (len + 1) * sizeof(WCHAR);
00231                 if (level > 1) {
00232                     needed += (reslen_MonitorW + reslen_PortW) * sizeof(WCHAR);
00233                 }
00234 
00235                 /* Now fill the user-buffer, if available */
00236                 if (pPorts && (cbBuf >= needed)){
00237                     out = (LPPORT_INFO_2W) pPorts;
00238                     pPorts += entrysize;
00239                     TRACE("%p: writing PORT_INFO_%dW #%d (%s)\n", out, level, numentries, debugstr_w(portname));
00240                     out->pPortName = ptr;
00241                     lstrcpyW(ptr, portname);            /* Name of the Port */
00242                     ptr += (len + 1);
00243                     if (level > 1) {
00244                         out->pMonitorName = ptr;
00245                         lstrcpyW(ptr, res_MonitorW);    /* Name of the Monitor */
00246                         ptr += reslen_MonitorW;
00247 
00248                         out->pDescription = ptr;
00249                         lstrcpyW(ptr, res_PortW);       /* Port Description */
00250                         ptr += reslen_PortW;
00251 
00252                         out->fPortType = PORT_TYPE_WRITE;
00253                         out->Reserved = 0;
00254                     }
00255                 }
00256                 id++;
00257             }
00258         }
00259         RegCloseKey(hroot);
00260     }
00261     else
00262     {
00263         ERR("failed with %d for %s\n", res, debugstr_w(WinNT_CV_PortsW));
00264         SetLastError(res);
00265     }
00266 
00267 getports_cleanup:
00268     *lpreturned = numentries;
00269     TRACE("need %d byte for %d entries (%d)\n", needed, numentries, GetLastError());
00270     return needed;
00271 }
00272 
00273 /*****************************************************
00274  * get_type_from_name (internal)
00275  * 
00276  */
00277 
00278 static DWORD get_type_from_name(LPCWSTR name)
00279 {
00280     HANDLE  hfile;
00281 
00282     if (!strncmpW(name, portname_LPT, sizeof(portname_LPT) / sizeof(WCHAR) -1))
00283         return PORT_IS_LPT;
00284 
00285     if (!strncmpW(name, portname_COM, sizeof(portname_COM) / sizeof(WCHAR) -1))
00286         return PORT_IS_COM;
00287 
00288     if (!strcmpW(name, portname_FILE))
00289         return PORT_IS_FILE;
00290 
00291     if (name[0] == '/')
00292         return PORT_IS_UNIXNAME;
00293 
00294     if (name[0] == '|')
00295         return PORT_IS_PIPE;
00296 
00297     if (!strncmpW(name, portname_CUPS, sizeof(portname_CUPS) / sizeof(WCHAR) -1))
00298         return PORT_IS_CUPS;
00299 
00300     if (!strncmpW(name, portname_LPR, sizeof(portname_LPR) / sizeof(WCHAR) -1))
00301         return PORT_IS_LPR;
00302 
00303     /* Must be a file or a directory. Does the file exist ? */
00304     hfile = CreateFileW(name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
00305     TRACE("%p for OPEN_EXISTING on %s\n", hfile, debugstr_w(name));
00306     if (hfile == INVALID_HANDLE_VALUE) {
00307         /* Can we create the file? */
00308         hfile = CreateFileW(name, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, NULL);
00309         TRACE("%p for OPEN_ALWAYS\n", hfile);
00310     }
00311     if (hfile != INVALID_HANDLE_VALUE) {
00312         CloseHandle(hfile);
00313         return PORT_IS_FILENAME;
00314     }
00315     /* We can't use the name. use GetLastError() for the reason */
00316     return PORT_IS_UNKNOWN;
00317 }
00318 
00319 /*****************************************************
00320  * get_type_from_local_name (internal)
00321  *
00322  */
00323 
00324 static DWORD get_type_from_local_name(LPCWSTR nameW)
00325 {
00326     LPPORT_INFO_1W  pi;
00327     LPWSTR  myname = NULL;
00328     DWORD   needed = 0;
00329     DWORD   numentries = 0;
00330     DWORD   id = 0;
00331 
00332     TRACE("(%s)\n", debugstr_w(myname));
00333 
00334     needed = get_ports_from_reg(1, NULL, 0, &numentries);
00335     pi = heap_alloc(needed);
00336     if (pi)
00337         needed = get_ports_from_reg(1, (LPBYTE) pi, needed, &numentries);
00338 
00339     if (pi && needed && numentries > 0) {
00340         /* we got a number of valid ports. */
00341 
00342         while ((myname == NULL) && (id < numentries))
00343         {
00344             if (lstrcmpiW(nameW, pi[id].pName) == 0) {
00345                 TRACE("(%u) found %s\n", id, debugstr_w(pi[id].pName));
00346                 myname = pi[id].pName;
00347             }
00348             id++;
00349         }
00350     }
00351 
00352     id = (myname) ? get_type_from_name(myname) : PORT_IS_UNKNOWN;
00353 
00354     heap_free(pi);
00355     return id;
00356 
00357 }
00358 /******************************************************************************
00359  *   localmon_AddPortExW [exported through MONITOREX]
00360  *
00361  * Add a Port, without presenting a user interface
00362  *
00363  * PARAMS
00364  *  pName         [I] Servername or NULL (local Computer)
00365  *  level         [I] Structure-Level (1) for pBuffer
00366  *  pBuffer       [I] PTR to the Input-Data (PORT_INFO_1)
00367  *  pMonitorName  [I] Name of the Monitor that manage the Port
00368  *
00369  * RETURNS
00370  *  Success: TRUE
00371  *  Failure: FALSE
00372  *
00373  * NOTES
00374  *  Level 2 is documented on MSDN for Portmonitors, but not supported by the
00375  *  "Local Port" Portmonitor (localspl.dll / localmon.dll)
00376  */
00377 static BOOL WINAPI localmon_AddPortExW(LPWSTR pName, DWORD level, LPBYTE pBuffer, LPWSTR pMonitorName)
00378 {
00379     PORT_INFO_1W * pi;
00380     HKEY  hroot;
00381     DWORD res;
00382 
00383     pi = (PORT_INFO_1W *) pBuffer;
00384     TRACE("(%s, %d, %p, %s) => %s\n", debugstr_w(pName), level, pBuffer,
00385             debugstr_w(pMonitorName), debugstr_w(pi ? pi->pName : NULL));
00386 
00387 
00388     if ((pMonitorName == NULL) || (lstrcmpiW(pMonitorName, LocalPortW) != 0 ) ||
00389         (pi == NULL) || (pi->pName == NULL) || (pi->pName[0] == '\0') ) {
00390         SetLastError(ERROR_INVALID_PARAMETER);
00391         return FALSE;
00392     }
00393 
00394     if (level != 1) {
00395         SetLastError(ERROR_INVALID_LEVEL);
00396         return FALSE;
00397     }
00398 
00399     res = RegOpenKeyW(HKEY_LOCAL_MACHINE, WinNT_CV_PortsW, &hroot);
00400     if (res == ERROR_SUCCESS) {
00401         if (does_port_exist(pi->pName)) {
00402             RegCloseKey(hroot);
00403             TRACE("=> FALSE with %u\n", ERROR_INVALID_PARAMETER);
00404             SetLastError(ERROR_INVALID_PARAMETER);
00405             return FALSE;
00406         }
00407         res = RegSetValueExW(hroot, pi->pName, 0, REG_SZ, (const BYTE *) emptyW, sizeof(emptyW));
00408         RegCloseKey(hroot);
00409     }
00410     if (res != ERROR_SUCCESS) SetLastError(ERROR_INVALID_PARAMETER);
00411     TRACE("=> %u with %u\n", (res == ERROR_SUCCESS), GetLastError());
00412     return (res == ERROR_SUCCESS);
00413 }
00414 
00415 /*****************************************************
00416  * localmon_ClosePort [exported through MONITOREX]
00417  *
00418  * Close a
00419  *
00420  * PARAMS
00421  *  hPort  [i] The Handle to close
00422  *
00423  * RETURNS
00424  *  Success: TRUE
00425  *  Failure: FALSE
00426  *
00427  */
00428 static BOOL WINAPI localmon_ClosePort(HANDLE hPort)
00429 {
00430     port_t * port = hPort;
00431 
00432     TRACE("(%p)\n", port);
00433     EnterCriticalSection(&port_handles_cs);
00434     list_remove(&port->entry);
00435     LeaveCriticalSection(&port_handles_cs);
00436     heap_free(port);
00437     return TRUE;
00438 }
00439 
00440 /*****************************************************
00441  *   localmon_EnumPortsW [exported through MONITOREX]
00442  *
00443  * Enumerate all local Ports
00444  *
00445  * PARAMS
00446  *  pName       [I] Servername (ignored)
00447  *  level       [I] Structure-Level (1 or 2)
00448  *  pPorts      [O] PTR to Buffer that receives the Result
00449  *  cbBuf       [I] Size of Buffer at pPorts
00450  *  pcbNeeded   [O] PTR to DWORD that receives the size in Bytes used / required for pPorts
00451  *  pcReturned  [O] PTR to DWORD that receives the number of Ports in pPorts
00452  *
00453  * RETURNS
00454  *  Success: TRUE
00455  *  Failure: FALSE and in pcbNeeded the Bytes required for pPorts, if cbBuf is too small
00456  *
00457  * NOTES
00458  *|  Windows ignores pName
00459  *|  Windows crash the app, when pPorts, pcbNeeded or pcReturned are NULL
00460  *|  Windows >NT4.0 does not check for illegal levels (TRUE is returned)
00461  *
00462  * ToDo
00463  *   "HCU\Software\Wine\Spooler<portname>" - redirection
00464  *
00465  */
00466 static BOOL WINAPI localmon_EnumPortsW(LPWSTR pName, DWORD level, LPBYTE pPorts,
00467                                        DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned)
00468 {
00469     BOOL    res = FALSE;
00470     DWORD   needed;
00471     DWORD   numentries;
00472 
00473     TRACE("(%s, %d, %p, %d, %p, %p)\n",
00474           debugstr_w(pName), level, pPorts, cbBuf, pcbNeeded, pcReturned);
00475 
00476     numentries = 0;
00477     needed = get_ports_from_reg(level, NULL, 0, &numentries);
00478     /* we calculated the needed buffersize. now do the error-checks */
00479     if (cbBuf < needed) {
00480         SetLastError(ERROR_INSUFFICIENT_BUFFER);
00481         goto cleanup;
00482     }
00483 
00484     /* fill the buffer with the Port-Names */
00485     needed = get_ports_from_reg(level, pPorts, cbBuf, &numentries);
00486     res = TRUE;
00487 
00488     if (pcReturned) *pcReturned = numentries;
00489 
00490 cleanup:
00491     if (pcbNeeded)  *pcbNeeded = needed;
00492 
00493     TRACE("returning %d with %d (%d byte for %d entries)\n", 
00494             res, GetLastError(), needed, numentries);
00495 
00496     return (res);
00497 }
00498 
00499 /*****************************************************
00500  * localmon_OpenPort [exported through MONITOREX]
00501  *
00502  * Open a Data-Channel for a Port
00503  *
00504  * PARAMS
00505  *  pName     [i] Name of selected Object
00506  *  phPort    [o] The resulting Handle is stored here
00507  *
00508  * RETURNS
00509  *  Success: TRUE
00510  *  Failure: FALSE
00511  *
00512  */
00513 static BOOL WINAPI localmon_OpenPortW(LPWSTR pName, PHANDLE phPort)
00514 {
00515     port_t * port;
00516     DWORD   len;
00517     DWORD   type;
00518 
00519     TRACE("%s, %p)\n", debugstr_w(pName), phPort);
00520 
00521     /* an empty name is invalid */
00522     if (!pName[0]) return FALSE;
00523 
00524     /* does the port exist? */
00525     type = get_type_from_local_name(pName);
00526     if (!type) return FALSE;
00527 
00528     len = (lstrlenW(pName) + 1) * sizeof(WCHAR);
00529     port = heap_alloc(sizeof(port_t) + len);
00530     if (!port) return FALSE;
00531 
00532     port->type = type;
00533     memcpy(port->nameW, pName, len);
00534     *phPort = port;
00535 
00536     EnterCriticalSection(&port_handles_cs);
00537     list_add_tail(&port_handles, &port->entry);
00538     LeaveCriticalSection(&port_handles_cs);
00539 
00540     TRACE("=> %p\n", port);
00541     return TRUE;
00542 }
00543 
00544 /*****************************************************
00545  * localmon_XcvClosePort [exported through MONITOREX]
00546  *
00547  * Close a Communication-Channel
00548  *
00549  * PARAMS
00550  *  hXcv  [i] The Handle to close
00551  *
00552  * RETURNS
00553  *  Success: TRUE
00554  *  Failure: FALSE
00555  *
00556  */
00557 static BOOL WINAPI localmon_XcvClosePort(HANDLE hXcv)
00558 {
00559     xcv_t * xcv = hXcv;
00560 
00561     TRACE("(%p)\n", xcv);
00562     /* No checks are done in Windows */
00563     EnterCriticalSection(&xcv_handles_cs);
00564     list_remove(&xcv->entry);
00565     LeaveCriticalSection(&xcv_handles_cs);
00566     heap_free(xcv);
00567     return TRUE;
00568 }
00569 
00570 /*****************************************************
00571  * localmon_XcvDataPort [exported through MONITOREX]
00572  *
00573  * Execute command through a Communication-Channel
00574  *
00575  * PARAMS
00576  *  hXcv            [i] The Handle to work with
00577  *  pszDataName     [i] Name of the command to execute
00578  *  pInputData      [i] Buffer for extra Input Data (needed only for some commands)
00579  *  cbInputData     [i] Size in Bytes of Buffer at pInputData
00580  *  pOutputData     [o] Buffer to receive additional Data (needed only for some commands)
00581  *  cbOutputData    [i] Size in Bytes of Buffer at pOutputData
00582  *  pcbOutputNeeded [o] PTR to receive the minimal Size in Bytes of the Buffer at pOutputData
00583  *
00584  * RETURNS
00585  *  Success: ERROR_SUCCESS
00586  *  Failure: win32 error code
00587  *
00588  * NOTES
00589  *
00590  *  Minimal List of commands, that every Printmonitor DLL should support:
00591  *
00592  *| "MonitorUI" : Return the Name of the Userinterface-DLL as WSTR in pOutputData
00593  *| "AddPort"   : Add a Port (Name as WSTR in pInputData)
00594  *| "DeletePort": Delete a Port (Name as WSTR in pInputData)
00595  *
00596  *
00597  */
00598 static DWORD WINAPI localmon_XcvDataPort(HANDLE hXcv, LPCWSTR pszDataName, PBYTE pInputData, DWORD cbInputData,
00599                                          PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded)
00600 {
00601     WCHAR   buffer[16];     /* buffer for a decimal number */
00602     LPWSTR  ptr;
00603     DWORD   res;
00604     DWORD   needed;
00605     HKEY    hroot;
00606 
00607     TRACE("(%p, %s, %p, %d, %p, %d, %p)\n", hXcv, debugstr_w(pszDataName),
00608           pInputData, cbInputData, pOutputData, cbOutputData, pcbOutputNeeded);
00609 
00610     if (!lstrcmpW(pszDataName, cmd_AddPortW)) {
00611         TRACE("InputData (%d): %s\n", cbInputData, debugstr_w( (LPWSTR) pInputData));
00612         res = RegOpenKeyW(HKEY_LOCAL_MACHINE, WinNT_CV_PortsW, &hroot);
00613         if (res == ERROR_SUCCESS) {
00614             if (does_port_exist((LPWSTR) pInputData)) {
00615                 RegCloseKey(hroot);
00616                 TRACE("=> %u\n", ERROR_ALREADY_EXISTS);
00617                 return ERROR_ALREADY_EXISTS;
00618             }
00619             res = RegSetValueExW(hroot, (LPWSTR) pInputData, 0, REG_SZ, (const BYTE *) emptyW, sizeof(emptyW));
00620             RegCloseKey(hroot);
00621         }
00622         TRACE("=> %u\n", res);
00623         return res;
00624     }
00625 
00626 
00627     if (!lstrcmpW(pszDataName, cmd_ConfigureLPTPortCommandOKW)) {
00628         TRACE("InputData (%d): %s\n", cbInputData, debugstr_w( (LPWSTR) pInputData));
00629         res = RegCreateKeyW(HKEY_LOCAL_MACHINE, WinNT_CV_WindowsW, &hroot);
00630         if (res == ERROR_SUCCESS) {
00631             res = RegSetValueExW(hroot, TransmissionRetryTimeoutW, 0, REG_SZ, pInputData, cbInputData);
00632             RegCloseKey(hroot);
00633         }
00634         return res;
00635     }
00636 
00637     if (!lstrcmpW(pszDataName, cmd_DeletePortW)) {
00638         TRACE("InputData (%d): %s\n", cbInputData, debugstr_w( (LPWSTR) pInputData));
00639         res = RegOpenKeyW(HKEY_LOCAL_MACHINE, WinNT_CV_PortsW, &hroot);
00640         if (res == ERROR_SUCCESS) {
00641             res = RegDeleteValueW(hroot, (LPWSTR) pInputData);
00642             RegCloseKey(hroot);
00643             TRACE("=> %u with %u\n", res, GetLastError() );
00644             return res;
00645         }
00646         return ERROR_FILE_NOT_FOUND;
00647     }
00648 
00649     if (!lstrcmpW(pszDataName, cmd_GetDefaultCommConfigW)) {
00650         TRACE("InputData (%d): %s\n", cbInputData, debugstr_w( (LPWSTR) pInputData));
00651         *pcbOutputNeeded = cbOutputData;
00652         res = GetDefaultCommConfigW((LPWSTR) pInputData, (LPCOMMCONFIG) pOutputData, pcbOutputNeeded);
00653         TRACE("got %u with %u\n", res, GetLastError() );
00654         return res ? ERROR_SUCCESS : GetLastError();
00655     }
00656 
00657     if (!lstrcmpW(pszDataName, cmd_GetTransmissionRetryTimeoutW)) {
00658         * pcbOutputNeeded = sizeof(DWORD);
00659         if (cbOutputData >= sizeof(DWORD)) {
00660             /* the w2k resource kit documented a default of 90, but that's wrong */
00661             *((LPDWORD) pOutputData) = 45;
00662 
00663             res = RegOpenKeyW(HKEY_LOCAL_MACHINE, WinNT_CV_WindowsW, &hroot);
00664             if (res == ERROR_SUCCESS) {
00665                 needed = sizeof(buffer) - sizeof(WCHAR);
00666                 res = RegQueryValueExW(hroot, TransmissionRetryTimeoutW, NULL, NULL, (LPBYTE) buffer, &needed);
00667                 if ((res == ERROR_SUCCESS) && (buffer[0])) {
00668                     *((LPDWORD) pOutputData) = strtoulW(buffer, NULL, 0);
00669                 }
00670                 RegCloseKey(hroot);
00671             }
00672             return ERROR_SUCCESS;
00673         }
00674         return ERROR_INSUFFICIENT_BUFFER;
00675     }
00676 
00677 
00678     if (!lstrcmpW(pszDataName, cmd_MonitorUIW)) {
00679         * pcbOutputNeeded = sizeof(dllnameuiW);
00680         if (cbOutputData >= sizeof(dllnameuiW)) {
00681             memcpy(pOutputData, dllnameuiW, sizeof(dllnameuiW));
00682             return ERROR_SUCCESS;
00683         }
00684         return ERROR_INSUFFICIENT_BUFFER;
00685     }
00686 
00687     if (!lstrcmpW(pszDataName, cmd_PortIsValidW)) {
00688         TRACE("InputData (%d): %s\n", cbInputData, debugstr_w( (LPWSTR) pInputData));
00689         res = get_type_from_name((LPCWSTR) pInputData);
00690         TRACE("detected as %u\n",  res);
00691         /* names, that we have recognized, are valid */
00692         if (res) return ERROR_SUCCESS;
00693 
00694         /* ERROR_ACCESS_DENIED, ERROR_PATH_NOT_FOUND or something else */
00695         TRACE("=> %u\n", GetLastError());
00696         return GetLastError();
00697     }
00698 
00699     if (!lstrcmpW(pszDataName, cmd_SetDefaultCommConfigW)) {
00700         /* get the portname from the Handle */
00701         ptr =  strchrW(((xcv_t *)hXcv)->nameW, ' ');
00702         if (ptr) {
00703             ptr++;  /* skip the space */
00704         }
00705         else
00706         {
00707             ptr =  ((xcv_t *)hXcv)->nameW;
00708         }
00709         lstrcpynW(buffer, ptr, sizeof(buffer)/sizeof(WCHAR));
00710         if (buffer[0]) buffer[lstrlenW(buffer)-1] = '\0';  /* remove the ':' */
00711         res = SetDefaultCommConfigW(buffer, (LPCOMMCONFIG) pInputData, cbInputData);
00712         TRACE("got %u with %u\n", res, GetLastError() );
00713         return res ? ERROR_SUCCESS : GetLastError();
00714     }
00715 
00716     FIXME("command not supported: %s\n", debugstr_w(pszDataName));
00717     return ERROR_INVALID_PARAMETER;
00718 }
00719 
00720 /*****************************************************
00721  * localmon_XcvOpenPort [exported through MONITOREX]
00722  *
00723  * Open a Communication-Channel
00724  *
00725  * PARAMS
00726  *  pName         [i] Name of selected Object
00727  *  GrantedAccess [i] Access-Rights to use
00728  *  phXcv         [o] The resulting Handle is stored here
00729  *
00730  * RETURNS
00731  *  Success: TRUE
00732  *  Failure: FALSE
00733  *
00734  */
00735 static BOOL WINAPI localmon_XcvOpenPort(LPCWSTR pName, ACCESS_MASK GrantedAccess, PHANDLE phXcv)
00736 {
00737     DWORD   len;
00738     xcv_t * xcv;
00739 
00740     TRACE("%s, 0x%x, %p)\n", debugstr_w(pName), GrantedAccess, phXcv);
00741     /* No checks for any field is done in Windows */
00742     len = (lstrlenW(pName) + 1) * sizeof(WCHAR);
00743     xcv = heap_alloc( sizeof(xcv_t) + len);
00744     if (xcv) {
00745         xcv->GrantedAccess = GrantedAccess;
00746         memcpy(xcv->nameW, pName, len);
00747         *phXcv = xcv;
00748         EnterCriticalSection(&xcv_handles_cs);
00749         list_add_tail(&xcv_handles, &xcv->entry);
00750         LeaveCriticalSection(&xcv_handles_cs);
00751         TRACE("=> %p\n", xcv);
00752         return TRUE;
00753     }
00754     else
00755     {
00756         *phXcv = NULL;
00757         return FALSE;
00758     }
00759 }
00760 
00761 /*****************************************************
00762  *      InitializePrintMonitor  (LOCALSPL.@)
00763  *
00764  * Initialize the Monitor for the Local Ports
00765  *
00766  * PARAMS
00767  *  regroot [I] Registry-Path, where the settings are stored
00768  *
00769  * RETURNS
00770  *  Success: Pointer to a MONITOREX Structure
00771  *  Failure: NULL
00772  *
00773  * NOTES
00774  *  The fixed location "HKLM\Software\Microsoft\Windows NT\CurrentVersion\Ports"
00775  *  is used to store the Ports (IniFileMapping from "win.ini", Section "Ports").
00776  *  Native localspl.dll fails, when no valid Port-Entry is present.
00777  *
00778  */
00779 
00780 LPMONITOREX WINAPI InitializePrintMonitor(LPWSTR regroot)
00781 {
00782     static MONITOREX mymonitorex =
00783     {
00784         sizeof(MONITOREX) - sizeof(DWORD),
00785         {
00786             localmon_EnumPortsW,
00787             localmon_OpenPortW,
00788             NULL,       /* localmon_OpenPortExW */ 
00789             NULL,       /* localmon_StartDocPortW */
00790             NULL,       /* localmon_WritePortW */
00791             NULL,       /* localmon_ReadPortW */
00792             NULL,       /* localmon_EndDocPortW */
00793             localmon_ClosePort,
00794             NULL,       /* Use AddPortUI in localui.dll */
00795             localmon_AddPortExW,
00796             NULL,       /* Use ConfigurePortUI in localui.dll */
00797             NULL,       /* Use DeletePortUI in localui.dll */
00798             NULL,       /* localmon_GetPrinterDataFromPort */
00799             NULL,       /* localmon_SetPortTimeOuts */
00800             localmon_XcvOpenPort,
00801             localmon_XcvDataPort,
00802             localmon_XcvClosePort
00803         }
00804     };
00805 
00806     TRACE("(%s)\n", debugstr_w(regroot));
00807     /* Parameter "regroot" is ignored on NT4.0 (localmon.dll) */
00808     if (!regroot || !regroot[0]) {
00809         SetLastError(ERROR_INVALID_PARAMETER);
00810         return NULL;
00811     }
00812     TRACE("=> %p\n", &mymonitorex);
00813     /* Native windows returns always the same pointer on success */
00814     return &mymonitorex;
00815 }

Generated on Fri May 25 2012 04:22:41 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.