d3dcompiler: Fix tracing of expression operators.
[wine/multimedia.git] / dlls / localspl / localmon.c
blob8737a060be2b8208b40d25ee8679ab9123d6ac26
1 /*
2 * Implementation of the Local Printmonitor
4 * Copyright 2006 Detlef Riekenberg
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <stdarg.h>
23 #define COBJMACROS
24 #define NONAMELESSUNION
26 #include "windef.h"
27 #include "winbase.h"
28 #include "wingdi.h"
29 #include "winuser.h"
30 #include "winreg.h"
32 #include "winspool.h"
33 #include "ddk/winsplp.h"
34 #include "localspl_private.h"
36 #include "wine/debug.h"
37 #include "wine/list.h"
38 #include "wine/unicode.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(localspl);
43 /*****************************************************/
45 static CRITICAL_SECTION port_handles_cs;
46 static CRITICAL_SECTION_DEBUG port_handles_cs_debug =
48 0, 0, &port_handles_cs,
49 { &port_handles_cs_debug.ProcessLocksList, &port_handles_cs_debug.ProcessLocksList },
50 0, 0, { (DWORD_PTR)(__FILE__ ": port_handles_cs") }
52 static CRITICAL_SECTION port_handles_cs = { &port_handles_cs_debug, -1, 0, 0, 0, 0 };
55 static CRITICAL_SECTION xcv_handles_cs;
56 static CRITICAL_SECTION_DEBUG xcv_handles_cs_debug =
58 0, 0, &xcv_handles_cs,
59 { &xcv_handles_cs_debug.ProcessLocksList, &xcv_handles_cs_debug.ProcessLocksList },
60 0, 0, { (DWORD_PTR)(__FILE__ ": xcv_handles_cs") }
62 static CRITICAL_SECTION xcv_handles_cs = { &xcv_handles_cs_debug, -1, 0, 0, 0, 0 };
64 /* ############################### */
66 typedef struct {
67 struct list entry;
68 DWORD type;
69 WCHAR nameW[1];
70 } port_t;
72 typedef struct {
73 struct list entry;
74 ACCESS_MASK GrantedAccess;
75 WCHAR nameW[1];
76 } xcv_t;
78 static struct list port_handles = LIST_INIT( port_handles );
79 static struct list xcv_handles = LIST_INIT( xcv_handles );
81 /* ############################### */
83 static const WCHAR cmd_AddPortW[] = {'A','d','d','P','o','r','t',0};
84 static const WCHAR cmd_DeletePortW[] = {'D','e','l','e','t','e','P','o','r','t',0};
85 static const WCHAR cmd_ConfigureLPTPortCommandOKW[] = {'C','o','n','f','i','g','u','r','e',
86 'L','P','T','P','o','r','t',
87 'C','o','m','m','a','n','d','O','K',0};
89 static const WCHAR cmd_GetDefaultCommConfigW[] = {'G','e','t',
90 'D','e','f','a','u','l','t',
91 'C','o','m','m','C','o','n','f','i','g',0};
93 static const WCHAR cmd_GetTransmissionRetryTimeoutW[] = {'G','e','t',
94 'T','r','a','n','s','m','i','s','s','i','o','n',
95 'R','e','t','r','y','T','i','m','e','o','u','t',0};
97 static const WCHAR cmd_MonitorUIW[] = {'M','o','n','i','t','o','r','U','I',0};
98 static const WCHAR cmd_PortIsValidW[] = {'P','o','r','t','I','s','V','a','l','i','d',0};
99 static const WCHAR cmd_SetDefaultCommConfigW[] = {'S','e','t',
100 'D','e','f','a','u','l','t',
101 'C','o','m','m','C','o','n','f','i','g',0};
103 static const WCHAR dllnameuiW[] = {'l','o','c','a','l','u','i','.','d','l','l',0};
104 static const WCHAR emptyW[] = {0};
105 static const WCHAR LocalPortW[] = {'L','o','c','a','l',' ','P','o','r','t',0};
107 static const WCHAR portname_LPT[] = {'L','P','T',0};
108 static const WCHAR portname_COM[] = {'C','O','M',0};
109 static const WCHAR portname_FILE[] = {'F','I','L','E',':',0};
110 static const WCHAR portname_CUPS[] = {'C','U','P','S',':',0};
111 static const WCHAR portname_LPR[] = {'L','P','R',':',0};
113 static const WCHAR TransmissionRetryTimeoutW[] = {'T','r','a','n','s','m','i','s','s','i','o','n',
114 'R','e','t','r','y','T','i','m','e','o','u','t',0};
116 static const WCHAR WinNT_CV_PortsW[] = {'S','o','f','t','w','a','r','e','\\',
117 'M','i','c','r','o','s','o','f','t','\\',
118 'W','i','n','d','o','w','s',' ','N','T','\\',
119 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
120 'P','o','r','t','s',0};
122 static const WCHAR WinNT_CV_WindowsW[] = {'S','o','f','t','w','a','r','e','\\',
123 'M','i','c','r','o','s','o','f','t','\\',
124 'W','i','n','d','o','w','s',' ','N','T','\\',
125 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
126 'W','i','n','d','o','w','s',0};
129 /******************************************************************
130 * does_port_exist (internal)
132 * returns TRUE, when the Port already exists
135 static BOOL does_port_exist(LPCWSTR myname)
138 LPPORT_INFO_1W pi;
139 DWORD needed = 0;
140 DWORD returned;
141 DWORD id;
143 TRACE("(%s)\n", debugstr_w(myname));
145 id = EnumPortsW(NULL, 1, NULL, 0, &needed, &returned);
146 pi = heap_alloc(needed);
147 returned = 0;
148 if (pi)
149 id = EnumPortsW(NULL, 1, (LPBYTE) pi, needed, &needed, &returned);
151 if (id && returned > 0) {
152 /* we got a number of valid names. */
153 for (id = 0; id < returned; id++)
155 if (lstrcmpiW(myname, pi[id].pName) == 0) {
156 TRACE("(%u) found %s\n", id, debugstr_w(pi[id].pName));
157 heap_free(pi);
158 return TRUE;
163 heap_free(pi);
164 return FALSE;
167 /******************************************************************
168 * enumerate the local Ports from the Registry (internal)
170 * See localmon_EnumPortsW.
172 * NOTES
173 * returns the needed size (in bytes) for pPorts
174 * and *lpreturned is set to number of entries returned in pPorts
178 static DWORD get_ports_from_reg(DWORD level, LPBYTE pPorts, DWORD cbBuf, LPDWORD lpreturned)
180 HKEY hroot = 0;
181 LPWSTR ptr;
182 LPPORT_INFO_2W out;
183 WCHAR portname[MAX_PATH];
184 WCHAR res_PortW[IDS_LOCALPORT_MAXLEN];
185 WCHAR res_MonitorW[IDS_LOCALMONITOR_MAXLEN];
186 INT reslen_PortW;
187 INT reslen_MonitorW;
188 DWORD len;
189 DWORD res;
190 DWORD needed = 0;
191 DWORD numentries;
192 DWORD entrysize;
193 DWORD id = 0;
195 TRACE("(%d, %p, %d, %p)\n", level, pPorts, cbBuf, lpreturned);
197 entrysize = (level == 1) ? sizeof(PORT_INFO_1W) : sizeof(PORT_INFO_2W);
199 numentries = *lpreturned; /* this is 0, when we scan the registry */
200 needed = entrysize * numentries;
201 ptr = (LPWSTR) &pPorts[needed];
203 if (needed > cbBuf) pPorts = NULL; /* No buffer for the structs */
205 numentries = 0;
206 needed = 0;
208 /* we do not check more parameters as done in windows */
209 if ((level < 1) || (level > 2)) {
210 goto getports_cleanup;
213 /* "+1" for '\0' */
214 reslen_MonitorW = LoadStringW(LOCALSPL_hInstance, IDS_LOCALMONITOR, res_MonitorW, IDS_LOCALMONITOR_MAXLEN) + 1;
215 reslen_PortW = LoadStringW(LOCALSPL_hInstance, IDS_LOCALPORT, res_PortW, IDS_LOCALPORT_MAXLEN) + 1;
217 res = RegOpenKeyW(HKEY_LOCAL_MACHINE, WinNT_CV_PortsW, &hroot);
218 if (res == ERROR_SUCCESS) {
220 /* Scan all Port-Names */
221 while (res == ERROR_SUCCESS) {
222 len = MAX_PATH;
223 portname[0] = '\0';
224 res = RegEnumValueW(hroot, id, portname, &len, NULL, NULL, NULL, NULL);
226 if ((res == ERROR_SUCCESS) && (portname[0])) {
227 numentries++;
228 /* calculate the required size */
229 needed += entrysize;
230 needed += (len + 1) * sizeof(WCHAR);
231 if (level > 1) {
232 needed += (reslen_MonitorW + reslen_PortW) * sizeof(WCHAR);
235 /* Now fill the user-buffer, if available */
236 if (pPorts && (cbBuf >= needed)){
237 out = (LPPORT_INFO_2W) pPorts;
238 pPorts += entrysize;
239 TRACE("%p: writing PORT_INFO_%dW #%d (%s)\n", out, level, numentries, debugstr_w(portname));
240 out->pPortName = ptr;
241 lstrcpyW(ptr, portname); /* Name of the Port */
242 ptr += (len + 1);
243 if (level > 1) {
244 out->pMonitorName = ptr;
245 lstrcpyW(ptr, res_MonitorW); /* Name of the Monitor */
246 ptr += reslen_MonitorW;
248 out->pDescription = ptr;
249 lstrcpyW(ptr, res_PortW); /* Port Description */
250 ptr += reslen_PortW;
252 out->fPortType = PORT_TYPE_WRITE;
253 out->Reserved = 0;
256 id++;
259 RegCloseKey(hroot);
261 else
263 ERR("failed with %d for %s\n", res, debugstr_w(WinNT_CV_PortsW));
264 SetLastError(res);
267 getports_cleanup:
268 *lpreturned = numentries;
269 TRACE("need %d byte for %d entries (%d)\n", needed, numentries, GetLastError());
270 return needed;
273 /*****************************************************
274 * get_type_from_name (internal)
278 static DWORD get_type_from_name(LPCWSTR name)
280 HANDLE hfile;
282 if (!strncmpW(name, portname_LPT, sizeof(portname_LPT) / sizeof(WCHAR) -1))
283 return PORT_IS_LPT;
285 if (!strncmpW(name, portname_COM, sizeof(portname_COM) / sizeof(WCHAR) -1))
286 return PORT_IS_COM;
288 if (!strcmpW(name, portname_FILE))
289 return PORT_IS_FILE;
291 if (name[0] == '/')
292 return PORT_IS_UNIXNAME;
294 if (name[0] == '|')
295 return PORT_IS_PIPE;
297 if (!strncmpW(name, portname_CUPS, sizeof(portname_CUPS) / sizeof(WCHAR) -1))
298 return PORT_IS_CUPS;
300 if (!strncmpW(name, portname_LPR, sizeof(portname_LPR) / sizeof(WCHAR) -1))
301 return PORT_IS_LPR;
303 /* Must be a file or a directory. Does the file exist ? */
304 hfile = CreateFileW(name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
305 TRACE("%p for OPEN_EXISTING on %s\n", hfile, debugstr_w(name));
306 if (hfile == INVALID_HANDLE_VALUE) {
307 /* Can we create the file? */
308 hfile = CreateFileW(name, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, NULL);
309 TRACE("%p for OPEN_ALWAYS\n", hfile);
311 if (hfile != INVALID_HANDLE_VALUE) {
312 CloseHandle(hfile);
313 return PORT_IS_FILENAME;
315 /* We can't use the name. use GetLastError() for the reason */
316 return PORT_IS_UNKNOWN;
319 /*****************************************************
320 * get_type_from_local_name (internal)
324 static DWORD get_type_from_local_name(LPCWSTR nameW)
326 LPPORT_INFO_1W pi;
327 LPWSTR myname = NULL;
328 DWORD needed = 0;
329 DWORD numentries = 0;
330 DWORD id = 0;
332 TRACE("(%s)\n", debugstr_w(myname));
334 needed = get_ports_from_reg(1, NULL, 0, &numentries);
335 pi = heap_alloc(needed);
336 if (pi)
337 needed = get_ports_from_reg(1, (LPBYTE) pi, needed, &numentries);
339 if (pi && needed && numentries > 0) {
340 /* we got a number of valid ports. */
342 while ((myname == NULL) && (id < numentries))
344 if (lstrcmpiW(nameW, pi[id].pName) == 0) {
345 TRACE("(%u) found %s\n", id, debugstr_w(pi[id].pName));
346 myname = pi[id].pName;
348 id++;
352 id = (myname) ? get_type_from_name(myname) : PORT_IS_UNKNOWN;
354 heap_free(pi);
355 return id;
358 /******************************************************************************
359 * localmon_AddPortExW [exported through MONITOREX]
361 * Add a Port, without presenting a user interface
363 * PARAMS
364 * pName [I] Servername or NULL (local Computer)
365 * level [I] Structure-Level (1) for pBuffer
366 * pBuffer [I] PTR to the Input-Data (PORT_INFO_1)
367 * pMonitorName [I] Name of the Monitor that manage the Port
369 * RETURNS
370 * Success: TRUE
371 * Failure: FALSE
373 * NOTES
374 * Level 2 is documented on MSDN for Portmonitors, but not supported by the
375 * "Local Port" Portmonitor (localspl.dll / localmon.dll)
377 static BOOL WINAPI localmon_AddPortExW(LPWSTR pName, DWORD level, LPBYTE pBuffer, LPWSTR pMonitorName)
379 PORT_INFO_1W * pi;
380 HKEY hroot;
381 DWORD res;
383 pi = (PORT_INFO_1W *) pBuffer;
384 TRACE("(%s, %d, %p, %s) => %s\n", debugstr_w(pName), level, pBuffer,
385 debugstr_w(pMonitorName), debugstr_w(pi ? pi->pName : NULL));
388 if ((pMonitorName == NULL) || (lstrcmpiW(pMonitorName, LocalPortW) != 0 ) ||
389 (pi == NULL) || (pi->pName == NULL) || (pi->pName[0] == '\0') ) {
390 SetLastError(ERROR_INVALID_PARAMETER);
391 return FALSE;
394 if (level != 1) {
395 SetLastError(ERROR_INVALID_LEVEL);
396 return FALSE;
399 res = RegOpenKeyW(HKEY_LOCAL_MACHINE, WinNT_CV_PortsW, &hroot);
400 if (res == ERROR_SUCCESS) {
401 if (does_port_exist(pi->pName)) {
402 RegCloseKey(hroot);
403 TRACE("=> FALSE with %u\n", ERROR_INVALID_PARAMETER);
404 SetLastError(ERROR_INVALID_PARAMETER);
405 return FALSE;
407 res = RegSetValueExW(hroot, pi->pName, 0, REG_SZ, (const BYTE *) emptyW, sizeof(emptyW));
408 RegCloseKey(hroot);
410 if (res != ERROR_SUCCESS) SetLastError(ERROR_INVALID_PARAMETER);
411 TRACE("=> %u with %u\n", (res == ERROR_SUCCESS), GetLastError());
412 return (res == ERROR_SUCCESS);
415 /*****************************************************
416 * localmon_ClosePort [exported through MONITOREX]
418 * Close a
420 * PARAMS
421 * hPort [i] The Handle to close
423 * RETURNS
424 * Success: TRUE
425 * Failure: FALSE
428 static BOOL WINAPI localmon_ClosePort(HANDLE hPort)
430 port_t * port = hPort;
432 TRACE("(%p)\n", port);
433 EnterCriticalSection(&port_handles_cs);
434 list_remove(&port->entry);
435 LeaveCriticalSection(&port_handles_cs);
436 heap_free(port);
437 return TRUE;
440 /*****************************************************
441 * localmon_EnumPortsW [exported through MONITOREX]
443 * Enumerate all local Ports
445 * PARAMS
446 * pName [I] Servername (ignored)
447 * level [I] Structure-Level (1 or 2)
448 * pPorts [O] PTR to Buffer that receives the Result
449 * cbBuf [I] Size of Buffer at pPorts
450 * pcbNeeded [O] PTR to DWORD that receives the size in Bytes used / required for pPorts
451 * pcReturned [O] PTR to DWORD that receives the number of Ports in pPorts
453 * RETURNS
454 * Success: TRUE
455 * Failure: FALSE and in pcbNeeded the Bytes required for pPorts, if cbBuf is too small
457 * NOTES
458 *| Windows ignores pName
459 *| Windows crash the app, when pPorts, pcbNeeded or pcReturned are NULL
460 *| Windows >NT4.0 does not check for illegal levels (TRUE is returned)
462 * ToDo
463 * "HCU\Software\Wine\Spooler\<portname>" - redirection
466 static BOOL WINAPI localmon_EnumPortsW(LPWSTR pName, DWORD level, LPBYTE pPorts,
467 DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned)
469 BOOL res = FALSE;
470 DWORD needed;
471 DWORD numentries;
473 TRACE("(%s, %d, %p, %d, %p, %p)\n",
474 debugstr_w(pName), level, pPorts, cbBuf, pcbNeeded, pcReturned);
476 numentries = 0;
477 needed = get_ports_from_reg(level, NULL, 0, &numentries);
478 /* we calculated the needed buffersize. now do the error-checks */
479 if (cbBuf < needed) {
480 SetLastError(ERROR_INSUFFICIENT_BUFFER);
481 goto cleanup;
484 /* fill the buffer with the Port-Names */
485 needed = get_ports_from_reg(level, pPorts, cbBuf, &numentries);
486 res = TRUE;
488 if (pcReturned) *pcReturned = numentries;
490 cleanup:
491 if (pcbNeeded) *pcbNeeded = needed;
493 TRACE("returning %d with %d (%d byte for %d entries)\n",
494 res, GetLastError(), needed, numentries);
496 return (res);
499 /*****************************************************
500 * localmon_OpenPort [exported through MONITOREX]
502 * Open a Data-Channel for a Port
504 * PARAMS
505 * pName [i] Name of selected Object
506 * phPort [o] The resulting Handle is stored here
508 * RETURNS
509 * Success: TRUE
510 * Failure: FALSE
513 static BOOL WINAPI localmon_OpenPortW(LPWSTR pName, PHANDLE phPort)
515 port_t * port;
516 DWORD type;
518 TRACE("%s, %p)\n", debugstr_w(pName), phPort);
520 /* an empty name is invalid */
521 if (!pName[0]) return FALSE;
523 /* does the port exist? */
524 type = get_type_from_local_name(pName);
525 if (!type) return FALSE;
527 port = heap_alloc(FIELD_OFFSET(port_t, nameW[lstrlenW(pName) + 1]));
528 if (!port) return FALSE;
530 port->type = type;
531 lstrcpyW(port->nameW, pName);
532 *phPort = port;
534 EnterCriticalSection(&port_handles_cs);
535 list_add_tail(&port_handles, &port->entry);
536 LeaveCriticalSection(&port_handles_cs);
538 TRACE("=> %p\n", port);
539 return TRUE;
542 /*****************************************************
543 * localmon_XcvClosePort [exported through MONITOREX]
545 * Close a Communication-Channel
547 * PARAMS
548 * hXcv [i] The Handle to close
550 * RETURNS
551 * Success: TRUE
552 * Failure: FALSE
555 static BOOL WINAPI localmon_XcvClosePort(HANDLE hXcv)
557 xcv_t * xcv = hXcv;
559 TRACE("(%p)\n", xcv);
560 /* No checks are done in Windows */
561 EnterCriticalSection(&xcv_handles_cs);
562 list_remove(&xcv->entry);
563 LeaveCriticalSection(&xcv_handles_cs);
564 heap_free(xcv);
565 return TRUE;
568 /*****************************************************
569 * localmon_XcvDataPort [exported through MONITOREX]
571 * Execute command through a Communication-Channel
573 * PARAMS
574 * hXcv [i] The Handle to work with
575 * pszDataName [i] Name of the command to execute
576 * pInputData [i] Buffer for extra Input Data (needed only for some commands)
577 * cbInputData [i] Size in Bytes of Buffer at pInputData
578 * pOutputData [o] Buffer to receive additional Data (needed only for some commands)
579 * cbOutputData [i] Size in Bytes of Buffer at pOutputData
580 * pcbOutputNeeded [o] PTR to receive the minimal Size in Bytes of the Buffer at pOutputData
582 * RETURNS
583 * Success: ERROR_SUCCESS
584 * Failure: win32 error code
586 * NOTES
588 * Minimal List of commands, that every Printmonitor DLL should support:
590 *| "MonitorUI" : Return the Name of the Userinterface-DLL as WSTR in pOutputData
591 *| "AddPort" : Add a Port (Name as WSTR in pInputData)
592 *| "DeletePort": Delete a Port (Name as WSTR in pInputData)
596 static DWORD WINAPI localmon_XcvDataPort(HANDLE hXcv, LPCWSTR pszDataName, PBYTE pInputData, DWORD cbInputData,
597 PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded)
599 WCHAR buffer[16]; /* buffer for a decimal number */
600 LPWSTR ptr;
601 DWORD res;
602 DWORD needed;
603 HKEY hroot;
605 TRACE("(%p, %s, %p, %d, %p, %d, %p)\n", hXcv, debugstr_w(pszDataName),
606 pInputData, cbInputData, pOutputData, cbOutputData, pcbOutputNeeded);
608 if (!lstrcmpW(pszDataName, cmd_AddPortW)) {
609 TRACE("InputData (%d): %s\n", cbInputData, debugstr_w( (LPWSTR) pInputData));
610 res = RegOpenKeyW(HKEY_LOCAL_MACHINE, WinNT_CV_PortsW, &hroot);
611 if (res == ERROR_SUCCESS) {
612 if (does_port_exist((LPWSTR) pInputData)) {
613 RegCloseKey(hroot);
614 TRACE("=> %u\n", ERROR_ALREADY_EXISTS);
615 return ERROR_ALREADY_EXISTS;
617 res = RegSetValueExW(hroot, (LPWSTR) pInputData, 0, REG_SZ, (const BYTE *) emptyW, sizeof(emptyW));
618 RegCloseKey(hroot);
620 TRACE("=> %u\n", res);
621 return res;
625 if (!lstrcmpW(pszDataName, cmd_ConfigureLPTPortCommandOKW)) {
626 TRACE("InputData (%d): %s\n", cbInputData, debugstr_w( (LPWSTR) pInputData));
627 res = RegCreateKeyW(HKEY_LOCAL_MACHINE, WinNT_CV_WindowsW, &hroot);
628 if (res == ERROR_SUCCESS) {
629 res = RegSetValueExW(hroot, TransmissionRetryTimeoutW, 0, REG_SZ, pInputData, cbInputData);
630 RegCloseKey(hroot);
632 return res;
635 if (!lstrcmpW(pszDataName, cmd_DeletePortW)) {
636 TRACE("InputData (%d): %s\n", cbInputData, debugstr_w( (LPWSTR) pInputData));
637 res = RegOpenKeyW(HKEY_LOCAL_MACHINE, WinNT_CV_PortsW, &hroot);
638 if (res == ERROR_SUCCESS) {
639 res = RegDeleteValueW(hroot, (LPWSTR) pInputData);
640 RegCloseKey(hroot);
641 TRACE("=> %u with %u\n", res, GetLastError() );
642 return res;
644 return ERROR_FILE_NOT_FOUND;
647 if (!lstrcmpW(pszDataName, cmd_GetDefaultCommConfigW)) {
648 TRACE("InputData (%d): %s\n", cbInputData, debugstr_w( (LPWSTR) pInputData));
649 *pcbOutputNeeded = cbOutputData;
650 res = GetDefaultCommConfigW((LPWSTR) pInputData, (LPCOMMCONFIG) pOutputData, pcbOutputNeeded);
651 TRACE("got %u with %u\n", res, GetLastError() );
652 return res ? ERROR_SUCCESS : GetLastError();
655 if (!lstrcmpW(pszDataName, cmd_GetTransmissionRetryTimeoutW)) {
656 * pcbOutputNeeded = sizeof(DWORD);
657 if (cbOutputData >= sizeof(DWORD)) {
658 /* the w2k resource kit documented a default of 90, but that's wrong */
659 *((LPDWORD) pOutputData) = 45;
661 res = RegOpenKeyW(HKEY_LOCAL_MACHINE, WinNT_CV_WindowsW, &hroot);
662 if (res == ERROR_SUCCESS) {
663 needed = sizeof(buffer) - sizeof(WCHAR);
664 res = RegQueryValueExW(hroot, TransmissionRetryTimeoutW, NULL, NULL, (LPBYTE) buffer, &needed);
665 if ((res == ERROR_SUCCESS) && (buffer[0])) {
666 *((LPDWORD) pOutputData) = strtoulW(buffer, NULL, 0);
668 RegCloseKey(hroot);
670 return ERROR_SUCCESS;
672 return ERROR_INSUFFICIENT_BUFFER;
676 if (!lstrcmpW(pszDataName, cmd_MonitorUIW)) {
677 * pcbOutputNeeded = sizeof(dllnameuiW);
678 if (cbOutputData >= sizeof(dllnameuiW)) {
679 memcpy(pOutputData, dllnameuiW, sizeof(dllnameuiW));
680 return ERROR_SUCCESS;
682 return ERROR_INSUFFICIENT_BUFFER;
685 if (!lstrcmpW(pszDataName, cmd_PortIsValidW)) {
686 TRACE("InputData (%d): %s\n", cbInputData, debugstr_w( (LPWSTR) pInputData));
687 res = get_type_from_name((LPCWSTR) pInputData);
688 TRACE("detected as %u\n", res);
689 /* names, that we have recognized, are valid */
690 if (res) return ERROR_SUCCESS;
692 /* ERROR_ACCESS_DENIED, ERROR_PATH_NOT_FOUND or something else */
693 TRACE("=> %u\n", GetLastError());
694 return GetLastError();
697 if (!lstrcmpW(pszDataName, cmd_SetDefaultCommConfigW)) {
698 /* get the portname from the Handle */
699 ptr = strchrW(((xcv_t *)hXcv)->nameW, ' ');
700 if (ptr) {
701 ptr++; /* skip the space */
703 else
705 ptr = ((xcv_t *)hXcv)->nameW;
707 lstrcpynW(buffer, ptr, sizeof(buffer)/sizeof(WCHAR));
708 if (buffer[0]) buffer[lstrlenW(buffer)-1] = '\0'; /* remove the ':' */
709 res = SetDefaultCommConfigW(buffer, (LPCOMMCONFIG) pInputData, cbInputData);
710 TRACE("got %u with %u\n", res, GetLastError() );
711 return res ? ERROR_SUCCESS : GetLastError();
714 FIXME("command not supported: %s\n", debugstr_w(pszDataName));
715 return ERROR_INVALID_PARAMETER;
718 /*****************************************************
719 * localmon_XcvOpenPort [exported through MONITOREX]
721 * Open a Communication-Channel
723 * PARAMS
724 * pName [i] Name of selected Object
725 * GrantedAccess [i] Access-Rights to use
726 * phXcv [o] The resulting Handle is stored here
728 * RETURNS
729 * Success: TRUE
730 * Failure: FALSE
733 static BOOL WINAPI localmon_XcvOpenPort(LPCWSTR pName, ACCESS_MASK GrantedAccess, PHANDLE phXcv)
735 xcv_t * xcv;
737 TRACE("%s, 0x%x, %p)\n", debugstr_w(pName), GrantedAccess, phXcv);
738 /* No checks for any field is done in Windows */
739 xcv = heap_alloc(FIELD_OFFSET(xcv_t, nameW[lstrlenW(pName) + 1]));
740 if (xcv) {
741 xcv->GrantedAccess = GrantedAccess;
742 lstrcpyW(xcv->nameW, pName);
743 *phXcv = xcv;
744 EnterCriticalSection(&xcv_handles_cs);
745 list_add_tail(&xcv_handles, &xcv->entry);
746 LeaveCriticalSection(&xcv_handles_cs);
747 TRACE("=> %p\n", xcv);
748 return TRUE;
750 else
752 *phXcv = NULL;
753 return FALSE;
757 /*****************************************************
758 * InitializePrintMonitor (LOCALSPL.@)
760 * Initialize the Monitor for the Local Ports
762 * PARAMS
763 * regroot [I] Registry-Path, where the settings are stored
765 * RETURNS
766 * Success: Pointer to a MONITOREX Structure
767 * Failure: NULL
769 * NOTES
770 * The fixed location "HKLM\Software\Microsoft\Windows NT\CurrentVersion\Ports"
771 * is used to store the Ports (IniFileMapping from "win.ini", Section "Ports").
772 * Native localspl.dll fails, when no valid Port-Entry is present.
776 LPMONITOREX WINAPI InitializePrintMonitor(LPWSTR regroot)
778 static MONITOREX mymonitorex =
780 sizeof(MONITOREX) - sizeof(DWORD),
782 localmon_EnumPortsW,
783 localmon_OpenPortW,
784 NULL, /* localmon_OpenPortExW */
785 NULL, /* localmon_StartDocPortW */
786 NULL, /* localmon_WritePortW */
787 NULL, /* localmon_ReadPortW */
788 NULL, /* localmon_EndDocPortW */
789 localmon_ClosePort,
790 NULL, /* Use AddPortUI in localui.dll */
791 localmon_AddPortExW,
792 NULL, /* Use ConfigurePortUI in localui.dll */
793 NULL, /* Use DeletePortUI in localui.dll */
794 NULL, /* localmon_GetPrinterDataFromPort */
795 NULL, /* localmon_SetPortTimeOuts */
796 localmon_XcvOpenPort,
797 localmon_XcvDataPort,
798 localmon_XcvClosePort
802 TRACE("(%s)\n", debugstr_w(regroot));
803 /* Parameter "regroot" is ignored on NT4.0 (localmon.dll) */
804 if (!regroot || !regroot[0]) {
805 SetLastError(ERROR_INVALID_PARAMETER);
806 return NULL;
808 TRACE("=> %p\n", &mymonitorex);
809 /* Native windows returns always the same pointer on success */
810 return &mymonitorex;