Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenlocalmon.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
1.7.6.1
|