d3dx9: Unify calling parse_mesh helper functions.
[wine.git] / dlls / hnetcfg / port.c
blob61513f97746fff69f45c62f3ed41abad054e98bf
1 /*
2 * Copyright 2009 Hans Leidekker for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include <stdarg.h>
20 #include <stdio.h>
22 #define COBJMACROS
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winuser.h"
27 #include "string.h"
28 #include "initguid.h"
29 #include "assert.h"
30 #include "winsock2.h"
31 #include "winhttp.h"
32 #include "shlwapi.h"
33 #include "xmllite.h"
34 #include "ole2.h"
35 #include "netfw.h"
36 #include "natupnp.h"
38 #include "wine/debug.h"
39 #include "hnetcfg_private.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(hnetcfg);
43 struct port_mapping
45 BSTR external_ip;
46 LONG external;
47 BSTR protocol;
48 LONG internal;
49 BSTR client;
50 VARIANT_BOOL enabled;
51 BSTR descr;
54 struct xml_value_desc
56 const WCHAR *name;
57 BSTR value;
60 static struct
62 LONG refs;
63 BOOL winsock_initialized;
64 WCHAR locationW[256];
65 HINTERNET session, connection;
66 WCHAR desc_urlpath[128];
67 WCHAR control_url[256];
68 unsigned int version;
69 struct port_mapping *mappings;
70 unsigned int mapping_count;
72 upnp_gateway_connection;
74 static SRWLOCK upnp_gateway_connection_lock = SRWLOCK_INIT;
76 static void free_port_mapping( struct port_mapping *mapping )
78 SysFreeString( mapping->external_ip );
79 SysFreeString( mapping->protocol );
80 SysFreeString( mapping->client );
81 SysFreeString( mapping->descr );
84 static void free_mappings(void)
86 unsigned int i;
88 for (i = 0; i < upnp_gateway_connection.mapping_count; ++i)
89 free_port_mapping( &upnp_gateway_connection.mappings[i] );
90 free( upnp_gateway_connection.mappings );
91 upnp_gateway_connection.mappings = NULL;
92 upnp_gateway_connection.mapping_count = 0;
95 static BOOL copy_port_mapping( struct port_mapping *dst, const struct port_mapping *src )
97 memset( dst, 0, sizeof(*dst) );
99 #define COPY_BSTR_CHECK(name) if (src->name && !(dst->name = SysAllocString( src->name ))) \
101 free_port_mapping( dst ); \
102 return FALSE; \
105 COPY_BSTR_CHECK( external_ip );
106 COPY_BSTR_CHECK( protocol );
107 COPY_BSTR_CHECK( client );
108 COPY_BSTR_CHECK( descr );
109 #undef COPY_BSTR_CHECK
111 dst->external = src->external;
112 dst->internal = src->internal;
113 dst->enabled = src->enabled;
114 return TRUE;
117 static BOOL parse_search_response( char *response, WCHAR *locationW, unsigned int location_size )
119 char *saveptr = NULL, *tok, *tok2;
120 unsigned int status;
122 tok = strtok_s( response, "\n", &saveptr );
123 if (!tok) return FALSE;
125 /* HTTP/1.1 200 OK */
126 tok2 = strtok( tok, " " );
127 if (!tok2) return FALSE;
128 tok2 = strtok( NULL, " " );
129 if (!tok2) return FALSE;
130 status = atoi( tok2 );
131 if (status != HTTP_STATUS_OK)
133 WARN( "status %u.\n", status );
134 return FALSE;
136 while ((tok = strtok_s( NULL, "\n", &saveptr )))
138 tok2 = strtok( tok, " " );
139 if (!tok2) continue;
140 if (!stricmp( tok2, "LOCATION:" ))
142 tok2 = strtok( NULL, " \r" );
143 if (!tok2)
145 WARN( "Error parsing location.\n" );
146 return FALSE;
148 return !!MultiByteToWideChar( CP_UTF8, 0, tok2, -1, locationW, location_size / 2 );
151 return FALSE;
154 static BOOL parse_desc_xml( const char *desc_xml )
156 static const WCHAR urn_wanipconnection[] = L"urn:schemas-upnp-org:service:WANIPConnection:";
157 WCHAR control_url[ARRAY_SIZE(upnp_gateway_connection.control_url)];
158 BOOL service_type_matches, control_url_found, found = FALSE;
159 unsigned int version = 0;
160 XmlNodeType node_type;
161 IXmlReader *reader;
162 const WCHAR *value;
163 BOOL ret = FALSE;
164 IStream *stream;
165 HRESULT hr;
167 if (!(stream = SHCreateMemStream( (BYTE *)desc_xml, strlen( desc_xml ) + 1 ))) return FALSE;
168 if (FAILED(hr = CreateXmlReader( &IID_IXmlReader, (void **)&reader, NULL )))
170 IStream_Release( stream );
171 return FALSE;
173 if (FAILED(hr = IXmlReader_SetInput( reader, (IUnknown*)stream ))) goto done;
175 while (SUCCEEDED(IXmlReader_Read( reader, &node_type )) && node_type != XmlNodeType_None)
177 if (node_type != XmlNodeType_Element) continue;
179 if (FAILED(IXmlReader_GetLocalName( reader, &value, NULL ))) goto done;
180 if (wcsicmp( value, L"service" )) continue;
181 control_url_found = service_type_matches = FALSE;
182 while (SUCCEEDED(IXmlReader_Read( reader, &node_type )))
184 if (node_type != XmlNodeType_Element && node_type != XmlNodeType_EndElement) continue;
185 if (FAILED(IXmlReader_GetLocalName( reader, &value, NULL )))
187 WARN( "IXmlReader_GetLocalName failed.\n" );
188 goto done;
190 if (node_type == XmlNodeType_EndElement)
192 if (!wcsicmp( value, L"service" )) break;
193 continue;
195 if (!wcsicmp( value, L"serviceType" ))
197 if (FAILED(IXmlReader_Read(reader, &node_type ))) goto done;
198 if (node_type != XmlNodeType_Text) goto done;
199 if (FAILED(IXmlReader_GetValue( reader, &value, NULL ))) goto done;
200 if (wcsnicmp( value, urn_wanipconnection, ARRAY_SIZE(urn_wanipconnection) - 1 )) break;
201 version = _wtoi( value + ARRAY_SIZE(urn_wanipconnection) - 1 );
202 service_type_matches = version >= 1;
204 else if (!wcsicmp( value, L"controlURL" ))
206 if (FAILED(IXmlReader_Read(reader, &node_type ))) goto done;
207 if (node_type != XmlNodeType_Text) goto done;
208 if (FAILED(IXmlReader_GetValue( reader, &value, NULL ))) goto done;
209 if (wcslen( value ) + 1 > ARRAY_SIZE(control_url)) goto done;
210 wcscpy( control_url, value );
211 control_url_found = TRUE;
214 if (service_type_matches && control_url_found)
216 if (found)
218 FIXME( "Found another WANIPConnection service, ignoring.\n" );
219 continue;
221 found = TRUE;
222 wcscpy( upnp_gateway_connection.control_url, control_url );
223 upnp_gateway_connection.version = version;
227 ret = found;
228 done:
229 IXmlReader_Release( reader );
230 IStream_Release( stream );
231 return ret;
234 static BOOL get_xml_elements( const char *desc_xml, struct xml_value_desc *values, unsigned int value_count )
236 XmlNodeType node_type;
237 IXmlReader *reader;
238 const WCHAR *value;
239 BOOL ret = FALSE;
240 IStream *stream;
241 unsigned int i;
242 HRESULT hr;
244 for (i = 0; i < value_count; ++i) assert( !values[i].value );
246 if (!(stream = SHCreateMemStream( (BYTE *)desc_xml, strlen( desc_xml ) + 1 ))) return FALSE;
247 if (FAILED(hr = CreateXmlReader( &IID_IXmlReader, (void **)&reader, NULL )))
249 IStream_Release( stream );
250 return FALSE;
252 if (FAILED(hr = IXmlReader_SetInput( reader, (IUnknown*)stream ))) goto done;
254 while (SUCCEEDED(IXmlReader_Read( reader, &node_type )) && node_type != XmlNodeType_None)
256 if (node_type != XmlNodeType_Element) continue;
258 if (FAILED(IXmlReader_GetQualifiedName( reader, &value, NULL ))) goto done;
259 for (i = 0; i < value_count; ++i)
260 if (!wcsicmp( value, values[i].name )) break;
261 if (i == value_count) continue;
262 if (FAILED(IXmlReader_Read(reader, &node_type ))) goto done;
263 if (node_type != XmlNodeType_Text)
265 if (node_type == XmlNodeType_EndElement) value = L"";
266 else goto done;
268 else
270 if (FAILED(IXmlReader_GetValue( reader, &value, NULL ))) goto done;
272 if (values[i].value)
274 WARN( "Duplicate value %s.\n", debugstr_w(values[i].name) );
275 goto done;
277 if (!(values[i].value = SysAllocString( value ))) goto done;
279 ret = TRUE;
281 done:
282 if (!ret)
284 for (i = 0; i < value_count; ++i)
286 SysFreeString( values[i].value );
287 values[i].value = NULL;
290 IXmlReader_Release( reader );
291 IStream_Release( stream );
292 return ret;
295 static BOOL open_gateway_connection(void)
297 static const int timeout = 3000;
299 WCHAR hostname[64];
300 URL_COMPONENTS url;
302 memset( &url, 0, sizeof(url) );
303 url.dwStructSize = sizeof(url);
304 url.lpszHostName = hostname;
305 url.dwHostNameLength = ARRAY_SIZE(hostname);
306 url.lpszUrlPath = upnp_gateway_connection.desc_urlpath;
307 url.dwUrlPathLength = ARRAY_SIZE(upnp_gateway_connection.desc_urlpath);
309 if (!WinHttpCrackUrl( upnp_gateway_connection.locationW, 0, 0, &url )) return FALSE;
311 upnp_gateway_connection.session = WinHttpOpen( L"hnetcfg", WINHTTP_ACCESS_TYPE_NO_PROXY,
312 WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0 );
313 if (!upnp_gateway_connection.session) return FALSE;
314 if (!WinHttpSetTimeouts( upnp_gateway_connection.session, timeout, timeout, timeout, timeout ))
315 return FALSE;
317 TRACE( "hostname %s, urlpath %s, port %u.\n",
318 debugstr_w(hostname), debugstr_w(upnp_gateway_connection.desc_urlpath), url.nPort );
319 upnp_gateway_connection.connection = WinHttpConnect ( upnp_gateway_connection.session, hostname, url.nPort, 0 );
320 if (!upnp_gateway_connection.connection)
322 WARN( "WinHttpConnect error %lu.\n", GetLastError() );
323 return FALSE;
325 return TRUE;
328 static BOOL get_control_url(void)
330 static const WCHAR *accept_types[] =
332 L"text/xml",
333 NULL
335 unsigned int desc_xml_size, offset;
336 DWORD size, status = 0;
337 HINTERNET request;
338 char *desc_xml;
339 BOOL ret;
341 request = WinHttpOpenRequest( upnp_gateway_connection.connection, NULL, upnp_gateway_connection.desc_urlpath, NULL,
342 WINHTTP_NO_REFERER, accept_types, 0 );
343 if (!request) return FALSE;
345 if (!WinHttpSendRequest( request, WINHTTP_NO_ADDITIONAL_HEADERS, 0, NULL, 0, 0, 0 ))
347 WARN( "Error sending request %lu.\n", GetLastError() );
348 WinHttpCloseHandle( request );
349 return FALSE;
351 if (!WinHttpReceiveResponse(request, NULL))
353 WARN( "Error receiving response %lu.\n", GetLastError() );
354 WinHttpCloseHandle( request );
355 return FALSE;
357 size = sizeof(status);
358 if (!WinHttpQueryHeaders( request, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
359 NULL, &status, &size, NULL) || status != HTTP_STATUS_OK )
361 WARN( "Error response from server, error %lu, http status %lu.\n", GetLastError(), status );
362 WinHttpCloseHandle( request );
363 return FALSE;
365 desc_xml_size = 1024;
366 desc_xml = malloc( desc_xml_size );
367 offset = 0;
368 while (WinHttpReadData( request, desc_xml + offset, desc_xml_size - offset - 1, &size ) && size)
370 offset += size;
371 if (offset + 1 == desc_xml_size)
373 char *new;
375 desc_xml_size *= 2;
376 if (!(new = realloc( desc_xml, desc_xml_size )))
378 ERR( "No memory.\n" );
379 break;
381 desc_xml = new;
384 desc_xml[offset] = 0;
385 WinHttpCloseHandle( request );
386 ret = parse_desc_xml( desc_xml );
387 free( desc_xml );
388 return ret;
391 static void gateway_connection_cleanup(void)
393 TRACE( ".\n" );
394 free_mappings();
395 WinHttpCloseHandle( upnp_gateway_connection.connection );
396 WinHttpCloseHandle( upnp_gateway_connection.session );
397 if (upnp_gateway_connection.winsock_initialized) WSACleanup();
398 memset( &upnp_gateway_connection, 0, sizeof(upnp_gateway_connection) );
401 static BOOL request_service( const WCHAR *function, const struct xml_value_desc *request_param,
402 unsigned int request_param_count, struct xml_value_desc *result,
403 unsigned int result_count, DWORD *http_status, BSTR *server_error_code_str )
405 static const char request_template_header[] =
406 "<?xml version=\"1.0\"?>\r\n"
407 "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" "
408 "SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\r\n"
409 " <SOAP-ENV:Body>\r\n"
410 " <m:%S xmlns:m=\"urn:schemas-upnp-org:service:WANIPConnection:%u\">\r\n";
411 static const char request_template_footer[] =
412 " </m:%S>\r\n"
413 " </SOAP-ENV:Body>\r\n"
414 "</SOAP-ENV:Envelope>\r\n";
416 unsigned int request_data_size, request_len, offset, i, reply_buffer_size;
417 char *request_data, *reply_buffer = NULL, *ptr;
418 struct xml_value_desc error_value_desc;
419 WCHAR request_headers[1024];
420 HINTERNET request = NULL;
421 BOOL ret = FALSE;
422 DWORD size;
424 *server_error_code_str = NULL;
425 request_data_size = strlen(request_template_header) + strlen(request_template_footer) + 2 * wcslen( function )
426 + 9 /* version + zero terminator */;
427 for (i = 0; i < request_param_count; ++i)
429 request_data_size += 13 + 2 * wcslen( request_param[i].name ) + wcslen( request_param[i].value );
431 if (!(request_data = malloc( request_data_size ))) return FALSE;
433 request = WinHttpOpenRequest( upnp_gateway_connection.connection, L"POST", upnp_gateway_connection.control_url,
434 NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, 0 );
435 if (!request) goto done;
437 ptr = request_data;
438 snprintf( ptr, request_data_size, request_template_header, function, upnp_gateway_connection.version );
439 offset = strlen( ptr );
440 ptr += offset;
441 request_data_size -= offset;
442 for (i = 0; i < request_param_count; ++i)
444 snprintf( ptr, request_data_size, " <%S>%S</%S>\r\n",
445 request_param[i].name, request_param[i].value, request_param[i].name);
446 offset = strlen( ptr );
447 ptr += offset;
448 request_data_size -= offset;
450 snprintf( ptr, request_data_size, request_template_footer, function );
452 request_len = strlen( request_data );
453 swprintf( request_headers, ARRAY_SIZE(request_headers),
454 L"SOAPAction: \"urn:schemas-upnp-org:service:WANIPConnection:%u#%s\"\r\n"
455 L"Content-Type: text/xml",
456 upnp_gateway_connection.version, function );
457 if (!WinHttpSendRequest( request, request_headers, -1, request_data, request_len, request_len, 0 ))
459 WARN( "Error sending request %lu.\n", GetLastError() );
460 goto done;
462 if (!WinHttpReceiveResponse(request, NULL))
464 WARN( "Error receiving response %lu.\n", GetLastError() );
465 goto done;
467 size = sizeof(*http_status);
468 if (!WinHttpQueryHeaders( request, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
469 NULL, http_status, &size, NULL) || *http_status != HTTP_STATUS_OK )
471 if (*http_status != HTTP_STATUS_SERVER_ERROR)
473 ret = TRUE;
474 goto done;
478 offset = 0;
479 reply_buffer_size = 1024;
480 if (!(reply_buffer = malloc( reply_buffer_size ))) goto done;
481 while ((ret = WinHttpReadData( request, reply_buffer + offset, reply_buffer_size - offset - 1, &size )) && size)
483 offset += size;
484 if (offset + 1 == reply_buffer_size)
486 char *new;
488 reply_buffer_size *= 2;
489 if (!(new = realloc( reply_buffer, reply_buffer_size ))) goto done;
490 reply_buffer = new;
493 reply_buffer[offset] = 0;
495 if (*http_status == HTTP_STATUS_OK) ret = get_xml_elements( reply_buffer, result, result_count );
496 else
498 error_value_desc.name = L"errorCode";
499 error_value_desc.value = NULL;
500 if ((ret = get_xml_elements( reply_buffer, &error_value_desc, 1 )))
501 *server_error_code_str = error_value_desc.value;
504 done:
505 free( reply_buffer );
506 free( request_data );
507 WinHttpCloseHandle( request );
508 return ret;
511 enum port_mapping_parameter
513 PM_EXTERNAL_IP,
514 PM_EXTERNAL,
515 PM_PROTOCOL,
516 PM_INTERNAL,
517 PM_CLIENT,
518 PM_ENABLED,
519 PM_DESC,
520 PM_LEASE_DURATION,
521 PM_LAST,
522 PM_REMOVE_PORT_LAST = PM_INTERNAL,
525 static struct xml_value_desc port_mapping_template[] =
527 { L"NewRemoteHost" },
528 { L"NewExternalPort" },
529 { L"NewProtocol" },
530 { L"NewInternalPort" },
531 { L"NewInternalClient" },
532 { L"NewEnabled" },
533 { L"NewPortMappingDescription" },
534 { L"NewLeaseDuration" },
537 static LONG long_from_bstr( BSTR s )
539 if (!s) return 0;
540 return _wtoi( s );
543 static BSTR mapping_move_bstr( BSTR *s )
545 BSTR ret;
547 if (*s)
549 ret = *s;
550 *s = NULL;
552 else if (!(ret = SysAllocString( L"" )))
554 ERR( "No memory.\n" );
556 return ret;
559 static void update_mapping_list(void)
561 struct xml_value_desc mapping_desc[ARRAY_SIZE(port_mapping_template)];
562 struct xml_value_desc index_param;
563 struct port_mapping *new_mappings;
564 unsigned int i, index;
565 WCHAR index_str[9];
566 BSTR error_str;
567 DWORD status;
568 BOOL ret;
570 free_mappings();
572 index_param.name = L"NewPortMappingIndex";
574 index = 0;
575 while (1)
577 new_mappings = realloc( upnp_gateway_connection.mappings, (index + 1) * sizeof(*new_mappings) );
578 if (!new_mappings) break;
579 upnp_gateway_connection.mappings = new_mappings;
581 memcpy( mapping_desc, port_mapping_template, sizeof(mapping_desc) );
582 swprintf( index_str, ARRAY_SIZE(index_str), L"%u", index );
583 index_param.value = SysAllocString( index_str );
584 ret = request_service( L"GetGenericPortMappingEntry", &index_param, 1,
585 mapping_desc, ARRAY_SIZE(mapping_desc), &status, &error_str );
586 SysFreeString( index_param.value );
587 if (!ret) break;
588 if (status != HTTP_STATUS_OK)
590 if (error_str)
592 if (long_from_bstr( error_str ) != 713)
593 WARN( "Server returned error %s.\n", debugstr_w(error_str) );
594 SysFreeString( error_str );
596 break;
598 new_mappings[index].external_ip = mapping_move_bstr( &mapping_desc[PM_EXTERNAL_IP].value );
599 new_mappings[index].external = long_from_bstr( mapping_desc[PM_EXTERNAL].value );
600 new_mappings[index].protocol = mapping_move_bstr( &mapping_desc[PM_PROTOCOL].value );
601 new_mappings[index].internal = long_from_bstr( mapping_desc[PM_INTERNAL].value );
602 new_mappings[index].client = mapping_move_bstr( &mapping_desc[PM_CLIENT].value );
603 if (mapping_desc[PM_ENABLED].value && (!wcsicmp( mapping_desc[PM_ENABLED].value, L"true" )
604 || long_from_bstr( mapping_desc[PM_ENABLED].value )))
605 new_mappings[index].enabled = VARIANT_TRUE;
606 else
607 new_mappings[index].enabled = VARIANT_FALSE;
608 new_mappings[index].descr = mapping_move_bstr( &mapping_desc[PM_DESC].value );
610 TRACE( "%s %s %s:%lu -> %s:%lu, enabled %d.\n", debugstr_w(new_mappings[index].descr),
611 debugstr_w(new_mappings[index].protocol), debugstr_w(new_mappings[index].external_ip),
612 new_mappings[index].external, debugstr_w(new_mappings[index].client),
613 new_mappings[index].internal, new_mappings[index].enabled );
615 for (i = 0; i < ARRAY_SIZE(mapping_desc); ++i)
616 SysFreeString( mapping_desc[i].value );
617 upnp_gateway_connection.mappings = new_mappings;
618 upnp_gateway_connection.mapping_count = ++index;
622 static BOOL remove_port_mapping( LONG port, BSTR protocol )
624 struct xml_value_desc mapping_desc[PM_REMOVE_PORT_LAST];
625 DWORD status = 0;
626 BSTR error_str;
627 WCHAR portW[6];
628 BOOL ret;
630 AcquireSRWLockExclusive( &upnp_gateway_connection_lock );
631 memcpy( mapping_desc, port_mapping_template, sizeof(mapping_desc) );
632 swprintf( portW, ARRAY_SIZE(portW), L"%u", port );
633 mapping_desc[PM_EXTERNAL_IP].value = SysAllocString( L"" );
634 mapping_desc[PM_EXTERNAL].value = SysAllocString( portW );
635 mapping_desc[PM_PROTOCOL].value = protocol;
637 ret = request_service( L"DeletePortMapping", mapping_desc, PM_REMOVE_PORT_LAST,
638 NULL, 0, &status, &error_str );
639 if (ret && status != HTTP_STATUS_OK)
641 WARN( "status %lu, server returned error %s.\n", status, debugstr_w(error_str) );
642 SysFreeString( error_str );
643 ret = FALSE;
645 else if (!ret)
647 WARN( "Request failed.\n" );
649 update_mapping_list();
650 ReleaseSRWLockExclusive( &upnp_gateway_connection_lock );
652 SysFreeString( mapping_desc[PM_EXTERNAL_IP].value );
653 SysFreeString( mapping_desc[PM_EXTERNAL].value );
654 return ret;
657 static BOOL add_port_mapping( LONG external, BSTR protocol, LONG internal, BSTR client,
658 VARIANT_BOOL enabled, BSTR description )
660 struct xml_value_desc mapping_desc[PM_LAST];
661 WCHAR externalW[6], internalW[6];
662 DWORD status = 0;
663 BSTR error_str;
664 BOOL ret;
666 AcquireSRWLockExclusive( &upnp_gateway_connection_lock );
667 memcpy( mapping_desc, port_mapping_template, sizeof(mapping_desc) );
668 swprintf( externalW, ARRAY_SIZE(externalW), L"%u", external );
669 swprintf( internalW, ARRAY_SIZE(internalW), L"%u", internal );
670 mapping_desc[PM_EXTERNAL_IP].value = SysAllocString( L"" );
671 mapping_desc[PM_EXTERNAL].value = SysAllocString( externalW );
672 mapping_desc[PM_PROTOCOL].value = protocol;
673 mapping_desc[PM_INTERNAL].value = SysAllocString( internalW );
674 mapping_desc[PM_CLIENT].value = client;
675 mapping_desc[PM_ENABLED].value = SysAllocString( enabled ? L"1" : L"0" );
676 mapping_desc[PM_DESC].value = description;
677 mapping_desc[PM_LEASE_DURATION].value = SysAllocString( L"0" );
679 ret = request_service( L"AddPortMapping", mapping_desc, PM_LAST,
680 NULL, 0, &status, &error_str );
681 if (ret && status != HTTP_STATUS_OK)
683 WARN( "status %lu, server returned error %s.\n", status, debugstr_w(error_str) );
684 SysFreeString( error_str );
685 ret = FALSE;
687 else if (!ret)
689 WARN( "Request failed.\n" );
691 update_mapping_list();
692 ReleaseSRWLockExclusive( &upnp_gateway_connection_lock );
694 SysFreeString( mapping_desc[PM_EXTERNAL_IP].value );
695 SysFreeString( mapping_desc[PM_EXTERNAL].value );
696 SysFreeString( mapping_desc[PM_INTERNAL].value );
697 SysFreeString( mapping_desc[PM_ENABLED].value );
698 SysFreeString( mapping_desc[PM_LEASE_DURATION].value );
699 return ret;
702 static BOOL init_gateway_connection(void)
704 static const char upnp_search_request[] =
705 "M-SEARCH * HTTP/1.1\r\n"
706 "HOST:239.255.255.250:1900\r\n"
707 "ST:upnp:rootdevice\r\n"
708 "MX:2\r\n"
709 "MAN:\"ssdp:discover\"\r\n"
710 "\r\n";
712 const DWORD timeout = 1000;
713 int len, address_len;
714 char buffer[2048];
715 SOCKADDR_IN addr;
716 WSADATA wsa_data;
717 unsigned int i;
718 SOCKET s;
720 upnp_gateway_connection.winsock_initialized = WSAStartup( MAKEWORD( 2, 2 ), &wsa_data );
721 if ((s = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP )) == -1)
723 ERR( "Failed to create socket, error %u.\n", WSAGetLastError() );
724 return FALSE;
726 if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (const char *)&timeout, sizeof(timeout)) == SOCKET_ERROR)
728 ERR( "setsockopt(SO_RCVTIME0) failed, error %u.\n", WSAGetLastError() );
729 closesocket( s );
730 return FALSE;
732 addr.sin_family = AF_INET;
733 addr.sin_port = htons( 1900 );
734 addr.sin_addr.S_un.S_addr = inet_addr( "239.255.255.250" );
735 if (sendto( s, upnp_search_request, strlen( upnp_search_request ), 0, (SOCKADDR *)&addr, sizeof(addr) )
736 == SOCKET_ERROR)
738 ERR( "sendto failed, error %u\n", WSAGetLastError() );
739 closesocket( s );
740 return FALSE;
742 /* Windows has a dedicated SSDP discovery service which maintains gateway device info and does
743 * not usually delay in get_StaticPortMappingCollection(). Although it may still delay depending
744 * on network connection state and always delays in IUPnPNAT_get_NATEventManager(). */
745 FIXME( "Waiting for reply from router.\n" );
746 for (i = 0; i < 2; ++i)
748 address_len = sizeof(addr);
749 len = recvfrom( s, buffer, sizeof(buffer) - 1, 0, (SOCKADDR *)&addr, &address_len );
750 if (len == -1)
752 if (WSAGetLastError() != WSAETIMEDOUT)
754 WARN( "recvfrom error %u.\n", WSAGetLastError() );
755 closesocket( s );
756 return FALSE;
759 else break;
761 closesocket( s );
762 if (i == 2)
764 TRACE( "No reply from router.\n" );
765 return FALSE;
767 TRACE( "Received reply from gateway, len %d.\n", len );
768 buffer[len] = 0;
769 if (!parse_search_response( buffer, upnp_gateway_connection.locationW, sizeof(upnp_gateway_connection.locationW) ))
771 WARN( "Error parsing response.\n" );
772 return FALSE;
774 TRACE( "Gateway description location %s.\n", debugstr_w(upnp_gateway_connection.locationW) );
775 if (!open_gateway_connection())
777 WARN( "Error opening gateway connection.\n" );
778 return FALSE;
780 TRACE( "Opened gateway connection.\n" );
781 if (!get_control_url())
783 WARN( "Could not get_control URL.\n" );
784 gateway_connection_cleanup();
785 return FALSE;
787 TRACE( "control_url %s, version %u.\n", debugstr_w(upnp_gateway_connection.control_url),
788 upnp_gateway_connection.version );
790 update_mapping_list();
791 return TRUE;
794 static BOOL grab_gateway_connection(void)
796 AcquireSRWLockExclusive( &upnp_gateway_connection_lock );
797 if (!upnp_gateway_connection.refs && !init_gateway_connection())
799 gateway_connection_cleanup();
800 ReleaseSRWLockExclusive( &upnp_gateway_connection_lock );
801 return FALSE;
803 ++upnp_gateway_connection.refs;
804 ReleaseSRWLockExclusive( &upnp_gateway_connection_lock );
805 return TRUE;
808 static void release_gateway_connection(void)
810 AcquireSRWLockExclusive( &upnp_gateway_connection_lock );
811 assert( upnp_gateway_connection.refs );
812 if (!--upnp_gateway_connection.refs)
813 gateway_connection_cleanup();
814 ReleaseSRWLockExclusive( &upnp_gateway_connection_lock );
817 static BOOL find_port_mapping( LONG port, BSTR protocol, struct port_mapping *ret )
819 unsigned int i;
820 BOOL found;
822 AcquireSRWLockExclusive( &upnp_gateway_connection_lock );
823 for (i = 0; i < upnp_gateway_connection.mapping_count; ++i)
825 if (upnp_gateway_connection.mappings[i].external == port
826 && !wcscmp( upnp_gateway_connection.mappings[i].protocol, protocol ))
827 break;
829 found = i < upnp_gateway_connection.mapping_count;
830 if (found) copy_port_mapping( ret, &upnp_gateway_connection.mappings[i] );
831 ReleaseSRWLockExclusive( &upnp_gateway_connection_lock );
832 return found;
835 static unsigned int get_port_mapping_range( unsigned int index, unsigned int count, struct port_mapping *ret )
837 unsigned int i;
839 AcquireSRWLockExclusive( &upnp_gateway_connection_lock );
840 for (i = 0; i < count && index + i < upnp_gateway_connection.mapping_count; ++i)
841 if (!copy_port_mapping( &ret[i], &upnp_gateway_connection.mappings[index + i] ))
843 ERR( "No memory.\n" );
844 break;
846 ReleaseSRWLockExclusive( &upnp_gateway_connection_lock );
848 return i;
851 static unsigned int get_port_mapping_count(void)
853 unsigned int ret;
855 AcquireSRWLockExclusive( &upnp_gateway_connection_lock );
856 ret = upnp_gateway_connection.mapping_count;
857 ReleaseSRWLockExclusive( &upnp_gateway_connection_lock );
858 return ret;
861 static BOOL is_valid_protocol( BSTR protocol )
863 if (!protocol) return FALSE;
864 return !wcscmp( protocol, L"UDP" ) || !wcscmp( protocol, L"TCP" );
867 struct static_port_mapping
869 IStaticPortMapping IStaticPortMapping_iface;
870 LONG refs;
871 struct port_mapping data;
874 static inline struct static_port_mapping *impl_from_IStaticPortMapping( IStaticPortMapping *iface )
876 return CONTAINING_RECORD(iface, struct static_port_mapping, IStaticPortMapping_iface);
879 static ULONG WINAPI static_port_mapping_AddRef(
880 IStaticPortMapping *iface )
882 struct static_port_mapping *mapping = impl_from_IStaticPortMapping( iface );
883 return InterlockedIncrement( &mapping->refs );
886 static ULONG WINAPI static_port_mapping_Release(
887 IStaticPortMapping *iface )
889 struct static_port_mapping *mapping = impl_from_IStaticPortMapping( iface );
890 LONG refs = InterlockedDecrement( &mapping->refs );
891 if (!refs)
893 TRACE("destroying %p\n", mapping);
894 free_port_mapping( &mapping->data );
895 free( mapping );
897 return refs;
900 static HRESULT WINAPI static_port_mapping_QueryInterface(
901 IStaticPortMapping *iface,
902 REFIID riid,
903 void **ppvObject )
905 struct static_port_mapping *mapping = impl_from_IStaticPortMapping( iface );
907 TRACE("%p %s %p\n", mapping, debugstr_guid( riid ), ppvObject );
909 if ( IsEqualGUID( riid, &IID_IStaticPortMapping ) ||
910 IsEqualGUID( riid, &IID_IDispatch ) ||
911 IsEqualGUID( riid, &IID_IUnknown ) )
913 *ppvObject = iface;
915 else
917 FIXME("interface %s not implemented\n", debugstr_guid(riid));
918 return E_NOINTERFACE;
920 IStaticPortMapping_AddRef( iface );
921 return S_OK;
924 static HRESULT WINAPI static_port_mapping_GetTypeInfoCount(
925 IStaticPortMapping *iface,
926 UINT *pctinfo )
928 struct static_port_mapping *mapping = impl_from_IStaticPortMapping( iface );
930 TRACE("%p %p\n", mapping, pctinfo);
931 *pctinfo = 1;
932 return S_OK;
935 static HRESULT WINAPI static_port_mapping_GetTypeInfo(
936 IStaticPortMapping *iface,
937 UINT iTInfo,
938 LCID lcid,
939 ITypeInfo **ppTInfo )
941 struct static_port_mapping *mapping = impl_from_IStaticPortMapping( iface );
943 TRACE("%p %u %lu %p\n", mapping, iTInfo, lcid, ppTInfo);
944 return get_typeinfo( IStaticPortMapping_tid, ppTInfo );
947 static HRESULT WINAPI static_port_mapping_GetIDsOfNames(
948 IStaticPortMapping *iface,
949 REFIID riid,
950 LPOLESTR *rgszNames,
951 UINT cNames,
952 LCID lcid,
953 DISPID *rgDispId )
955 struct static_port_mapping *mapping = impl_from_IStaticPortMapping( iface );
956 ITypeInfo *typeinfo;
957 HRESULT hr;
959 TRACE("%p %s %p %u %lu %p\n", mapping, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
961 hr = get_typeinfo( IStaticPortMapping_tid, &typeinfo );
962 if (SUCCEEDED(hr))
964 hr = ITypeInfo_GetIDsOfNames( typeinfo, rgszNames, cNames, rgDispId );
965 ITypeInfo_Release( typeinfo );
967 return hr;
970 static HRESULT WINAPI static_port_mapping_Invoke(
971 IStaticPortMapping *iface,
972 DISPID dispIdMember,
973 REFIID riid,
974 LCID lcid,
975 WORD wFlags,
976 DISPPARAMS *pDispParams,
977 VARIANT *pVarResult,
978 EXCEPINFO *pExcepInfo,
979 UINT *puArgErr )
981 struct static_port_mapping *mapping = impl_from_IStaticPortMapping( iface );
982 ITypeInfo *typeinfo;
983 HRESULT hr;
985 TRACE("%p %ld %s %ld %d %p %p %p %p\n", mapping, dispIdMember, debugstr_guid(riid),
986 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
988 hr = get_typeinfo( IStaticPortMapping_tid, &typeinfo );
989 if (SUCCEEDED(hr))
991 hr = ITypeInfo_Invoke( typeinfo, &mapping->IStaticPortMapping_iface, dispIdMember,
992 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr );
993 ITypeInfo_Release( typeinfo );
995 return hr;
998 static HRESULT WINAPI static_port_mapping_get_ExternalIPAddress(
999 IStaticPortMapping *iface,
1000 BSTR *value )
1002 struct static_port_mapping *mapping = impl_from_IStaticPortMapping( iface );
1004 TRACE( "iface %p, value %p.\n", iface, value );
1006 if (!value) return E_POINTER;
1007 *value = SysAllocString( mapping->data.external_ip );
1008 if (mapping->data.external_ip && !*value) return E_OUTOFMEMORY;
1009 return S_OK;
1012 static HRESULT WINAPI static_port_mapping_get_ExternalPort(
1013 IStaticPortMapping *iface,
1014 LONG *value )
1016 struct static_port_mapping *mapping = impl_from_IStaticPortMapping( iface );
1018 TRACE( "iface %p, value %p.\n", iface, value );
1020 if (!value) return E_POINTER;
1021 *value = mapping->data.external;
1022 return S_OK;
1025 static HRESULT WINAPI static_port_mapping_get_InternalPort(
1026 IStaticPortMapping *iface,
1027 LONG *value )
1029 struct static_port_mapping *mapping = impl_from_IStaticPortMapping( iface );
1031 TRACE( "iface %p, value %p.\n", iface, value );
1033 if (!value) return E_POINTER;
1034 *value = mapping->data.internal;
1035 return S_OK;
1038 static HRESULT WINAPI static_port_mapping_get_Protocol(
1039 IStaticPortMapping *iface,
1040 BSTR *value )
1042 struct static_port_mapping *mapping = impl_from_IStaticPortMapping( iface );
1044 TRACE( "iface %p, value %p.\n", iface, value );
1046 if (!value) return E_POINTER;
1047 *value = SysAllocString( mapping->data.protocol );
1048 if (mapping->data.protocol && !*value) return E_OUTOFMEMORY;
1049 return S_OK;
1052 static HRESULT WINAPI static_port_mapping_get_InternalClient(
1053 IStaticPortMapping *iface,
1054 BSTR *value )
1056 struct static_port_mapping *mapping = impl_from_IStaticPortMapping( iface );
1058 TRACE( "iface %p, value %p.\n", iface, value );
1060 if (!value) return E_POINTER;
1061 *value = SysAllocString( mapping->data.client );
1062 if (mapping->data.client && !*value) return E_OUTOFMEMORY;
1063 return S_OK;
1066 static HRESULT WINAPI static_port_mapping_get_Enabled(
1067 IStaticPortMapping *iface,
1068 VARIANT_BOOL *value )
1070 struct static_port_mapping *mapping = impl_from_IStaticPortMapping( iface );
1072 TRACE( "iface %p, value %p.\n", iface, value );
1074 if (!value) return E_POINTER;
1075 *value = mapping->data.enabled;
1076 return S_OK;
1079 static HRESULT WINAPI static_port_mapping_get_Description(
1080 IStaticPortMapping *iface,
1081 BSTR *value )
1083 struct static_port_mapping *mapping = impl_from_IStaticPortMapping( iface );
1085 TRACE( "iface %p, value %p.\n", iface, value );
1087 if (!value) return E_POINTER;
1088 *value = SysAllocString( mapping->data.descr );
1089 if (mapping->data.descr && !*value) return E_OUTOFMEMORY;
1090 return S_OK;
1093 static HRESULT WINAPI static_port_mapping_EditInternalClient(
1094 IStaticPortMapping *iface,
1095 BSTR value )
1097 FIXME( "iface %p, value %s stub.\n", iface, debugstr_w(value) );
1099 return E_NOTIMPL;
1102 static HRESULT WINAPI static_port_mapping_Enable(
1103 IStaticPortMapping *iface,
1104 VARIANT_BOOL value )
1106 FIXME( "iface %p, value %d stub.\n", iface, value );
1108 return E_NOTIMPL;
1111 static HRESULT WINAPI static_port_mapping_EditDescription(
1112 IStaticPortMapping *iface,
1113 BSTR value )
1115 FIXME( "iface %p, value %s stub.\n", iface, debugstr_w(value) );
1117 return E_NOTIMPL;
1120 static HRESULT WINAPI static_port_mapping_EditInternalPort(
1121 IStaticPortMapping *iface,
1122 LONG value )
1124 FIXME( "iface %p, value %ld stub.\n", iface, value );
1126 return E_NOTIMPL;
1129 static const IStaticPortMappingVtbl static_port_mapping_vtbl =
1131 static_port_mapping_QueryInterface,
1132 static_port_mapping_AddRef,
1133 static_port_mapping_Release,
1134 static_port_mapping_GetTypeInfoCount,
1135 static_port_mapping_GetTypeInfo,
1136 static_port_mapping_GetIDsOfNames,
1137 static_port_mapping_Invoke,
1138 static_port_mapping_get_ExternalIPAddress,
1139 static_port_mapping_get_ExternalPort,
1140 static_port_mapping_get_InternalPort,
1141 static_port_mapping_get_Protocol,
1142 static_port_mapping_get_InternalClient,
1143 static_port_mapping_get_Enabled,
1144 static_port_mapping_get_Description,
1145 static_port_mapping_EditInternalClient,
1146 static_port_mapping_Enable,
1147 static_port_mapping_EditDescription,
1148 static_port_mapping_EditInternalPort,
1151 static HRESULT static_port_mapping_create( const struct port_mapping *mapping_data, IStaticPortMapping **ret )
1153 struct static_port_mapping *mapping;
1155 if (!(mapping = calloc( 1, sizeof(*mapping) ))) return E_OUTOFMEMORY;
1157 mapping->refs = 1;
1158 mapping->IStaticPortMapping_iface.lpVtbl = &static_port_mapping_vtbl;
1159 mapping->data = *mapping_data;
1160 *ret = &mapping->IStaticPortMapping_iface;
1161 return S_OK;
1164 struct port_mapping_enum
1166 IEnumVARIANT IEnumVARIANT_iface;
1167 LONG refs;
1168 unsigned int index;
1171 static inline struct port_mapping_enum *impl_from_IEnumVARIANT( IEnumVARIANT *iface )
1173 return CONTAINING_RECORD(iface, struct port_mapping_enum, IEnumVARIANT_iface);
1176 static ULONG WINAPI port_mapping_enum_AddRef(
1177 IEnumVARIANT *iface )
1179 struct port_mapping_enum *mapping_enum = impl_from_IEnumVARIANT( iface );
1180 return InterlockedIncrement( &mapping_enum->refs );
1183 static ULONG WINAPI port_mapping_enum_Release(
1184 IEnumVARIANT *iface )
1186 struct port_mapping_enum *mapping_enum = impl_from_IEnumVARIANT( iface );
1187 LONG refs = InterlockedDecrement( &mapping_enum->refs );
1188 if (!refs)
1190 TRACE("destroying %p\n", mapping_enum);
1191 free( mapping_enum );
1192 release_gateway_connection();
1194 return refs;
1197 static HRESULT WINAPI port_mapping_enum_QueryInterface(
1198 IEnumVARIANT *iface,
1199 REFIID riid,
1200 void **ppvObject )
1202 struct port_mapping_enum *mapping_enum = impl_from_IEnumVARIANT( iface );
1204 TRACE("%p %s %p\n", mapping_enum, debugstr_guid( riid ), ppvObject );
1206 if ( IsEqualGUID( riid, &IID_IEnumVARIANT ) ||
1207 IsEqualGUID( riid, &IID_IUnknown ) )
1209 *ppvObject = iface;
1211 else
1213 FIXME("interface %s not implemented\n", debugstr_guid(riid));
1214 return E_NOINTERFACE;
1216 IEnumVARIANT_AddRef( iface );
1217 return S_OK;
1220 static HRESULT WINAPI port_mapping_enum_Next( IEnumVARIANT *iface, ULONG celt, VARIANT *var, ULONG *fetched )
1222 struct port_mapping_enum *mapping_enum = impl_from_IEnumVARIANT( iface );
1223 struct port_mapping *data;
1224 IStaticPortMapping *pm;
1225 unsigned int i, count;
1226 HRESULT ret;
1228 TRACE( "iface %p, celt %lu, var %p, fetched %p.\n", iface, celt, var, fetched );
1230 if (fetched) *fetched = 0;
1231 if (!celt) return S_OK;
1232 if (!var) return E_POINTER;
1234 if (!(data = calloc( 1, celt * sizeof(*data) ))) return E_OUTOFMEMORY;
1235 count = get_port_mapping_range( mapping_enum->index, celt, data );
1236 TRACE( "count %u.\n", count );
1237 for (i = 0; i < count; ++i)
1239 if (FAILED(static_port_mapping_create( &data[i], &pm ))) break;
1241 V_VT(&var[i]) = VT_DISPATCH;
1242 V_DISPATCH(&var[i]) = (IDispatch *)pm;
1244 mapping_enum->index += i;
1245 if (fetched) *fetched = i;
1246 ret = (i < celt) ? S_FALSE : S_OK;
1247 for ( ; i < count; ++i)
1249 free_port_mapping( &data[i] );
1250 VariantInit( &var[i] );
1252 for ( ; i < celt; ++i)
1253 VariantInit( &var[i] );
1255 free( data );
1256 return ret;
1259 static HRESULT WINAPI port_mapping_enum_Skip( IEnumVARIANT *iface, ULONG celt )
1261 struct port_mapping_enum *mapping_enum = impl_from_IEnumVARIANT( iface );
1262 unsigned int count = get_port_mapping_count();
1264 TRACE( "iface %p, celt %lu.\n", iface, celt );
1266 mapping_enum->index += celt;
1267 return mapping_enum->index <= count ? S_OK : S_FALSE;
1270 static HRESULT WINAPI port_mapping_enum_Reset( IEnumVARIANT *iface )
1272 struct port_mapping_enum *mapping_enum = impl_from_IEnumVARIANT( iface );
1274 TRACE( "iface %p.\n", iface );
1276 mapping_enum->index = 0;
1277 return S_OK;
1280 static HRESULT create_port_mapping_enum( IUnknown **ret );
1282 static HRESULT WINAPI port_mapping_enum_Clone( IEnumVARIANT *iface, IEnumVARIANT **ret )
1284 struct port_mapping_enum *mapping_enum = impl_from_IEnumVARIANT( iface );
1285 HRESULT hr;
1287 TRACE( "iface %p, ret %p.\n", iface, ret );
1289 if (!ret) return E_POINTER;
1290 *ret = NULL;
1291 if (FAILED(hr = create_port_mapping_enum( (IUnknown **)ret ))) return hr;
1292 impl_from_IEnumVARIANT( *ret )->index = mapping_enum->index;
1293 return S_OK;
1296 static const IEnumVARIANTVtbl port_mapping_enum_vtbl =
1298 port_mapping_enum_QueryInterface,
1299 port_mapping_enum_AddRef,
1300 port_mapping_enum_Release,
1301 port_mapping_enum_Next,
1302 port_mapping_enum_Skip,
1303 port_mapping_enum_Reset,
1304 port_mapping_enum_Clone,
1307 static HRESULT create_port_mapping_enum( IUnknown **ret )
1309 struct port_mapping_enum *mapping_enum;
1311 if (!(mapping_enum = calloc( 1, sizeof(*mapping_enum) ))) return E_OUTOFMEMORY;
1313 grab_gateway_connection();
1315 mapping_enum->refs = 1;
1316 mapping_enum->IEnumVARIANT_iface.lpVtbl = &port_mapping_enum_vtbl;
1317 mapping_enum->index = 0;
1318 *ret = (IUnknown *)&mapping_enum->IEnumVARIANT_iface;
1319 return S_OK;
1322 struct static_port_mapping_collection
1324 IStaticPortMappingCollection IStaticPortMappingCollection_iface;
1325 LONG refs;
1328 static inline struct static_port_mapping_collection *impl_from_IStaticPortMappingCollection
1329 ( IStaticPortMappingCollection *iface )
1331 return CONTAINING_RECORD(iface, struct static_port_mapping_collection, IStaticPortMappingCollection_iface);
1334 static ULONG WINAPI static_ports_AddRef(
1335 IStaticPortMappingCollection *iface )
1337 struct static_port_mapping_collection *ports = impl_from_IStaticPortMappingCollection( iface );
1338 return InterlockedIncrement( &ports->refs );
1341 static ULONG WINAPI static_ports_Release(
1342 IStaticPortMappingCollection *iface )
1344 struct static_port_mapping_collection *ports = impl_from_IStaticPortMappingCollection( iface );
1345 LONG refs = InterlockedDecrement( &ports->refs );
1346 if (!refs)
1348 TRACE("destroying %p\n", ports);
1349 release_gateway_connection();
1350 free( ports );
1352 return refs;
1355 static HRESULT WINAPI static_ports_QueryInterface(
1356 IStaticPortMappingCollection *iface,
1357 REFIID riid,
1358 void **ppvObject )
1360 struct static_port_mapping_collection *ports = impl_from_IStaticPortMappingCollection( iface );
1362 TRACE("%p %s %p\n", ports, debugstr_guid( riid ), ppvObject );
1364 if ( IsEqualGUID( riid, &IID_IStaticPortMappingCollection ) ||
1365 IsEqualGUID( riid, &IID_IDispatch ) ||
1366 IsEqualGUID( riid, &IID_IUnknown ) )
1368 *ppvObject = iface;
1370 else
1372 FIXME("interface %s not implemented\n", debugstr_guid(riid));
1373 return E_NOINTERFACE;
1375 IStaticPortMappingCollection_AddRef( iface );
1376 return S_OK;
1379 static HRESULT WINAPI static_ports_GetTypeInfoCount(
1380 IStaticPortMappingCollection *iface,
1381 UINT *pctinfo )
1383 struct static_port_mapping_collection *ports = impl_from_IStaticPortMappingCollection( iface );
1385 TRACE("%p %p\n", ports, pctinfo);
1386 *pctinfo = 1;
1387 return S_OK;
1390 static HRESULT WINAPI static_ports_GetTypeInfo(
1391 IStaticPortMappingCollection *iface,
1392 UINT iTInfo,
1393 LCID lcid,
1394 ITypeInfo **ppTInfo )
1396 struct static_port_mapping_collection *ports = impl_from_IStaticPortMappingCollection( iface );
1398 TRACE("%p %u %lu %p\n", ports, iTInfo, lcid, ppTInfo);
1399 return get_typeinfo( IStaticPortMappingCollection_tid, ppTInfo );
1402 static HRESULT WINAPI static_ports_GetIDsOfNames(
1403 IStaticPortMappingCollection *iface,
1404 REFIID riid,
1405 LPOLESTR *rgszNames,
1406 UINT cNames,
1407 LCID lcid,
1408 DISPID *rgDispId )
1410 struct static_port_mapping_collection *ports = impl_from_IStaticPortMappingCollection( iface );
1411 ITypeInfo *typeinfo;
1412 HRESULT hr;
1414 TRACE("%p %s %p %u %lu %p\n", ports, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
1416 hr = get_typeinfo( IStaticPortMappingCollection_tid, &typeinfo );
1417 if (SUCCEEDED(hr))
1419 hr = ITypeInfo_GetIDsOfNames( typeinfo, rgszNames, cNames, rgDispId );
1420 ITypeInfo_Release( typeinfo );
1422 return hr;
1425 static HRESULT WINAPI static_ports_Invoke(
1426 IStaticPortMappingCollection *iface,
1427 DISPID dispIdMember,
1428 REFIID riid,
1429 LCID lcid,
1430 WORD wFlags,
1431 DISPPARAMS *pDispParams,
1432 VARIANT *pVarResult,
1433 EXCEPINFO *pExcepInfo,
1434 UINT *puArgErr )
1436 struct static_port_mapping_collection *ports = impl_from_IStaticPortMappingCollection( iface );
1437 ITypeInfo *typeinfo;
1438 HRESULT hr;
1440 TRACE("%p %ld %s %ld %d %p %p %p %p\n", ports, dispIdMember, debugstr_guid(riid),
1441 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1443 hr = get_typeinfo( IStaticPortMappingCollection_tid, &typeinfo );
1444 if (SUCCEEDED(hr))
1446 hr = ITypeInfo_Invoke( typeinfo, &ports->IStaticPortMappingCollection_iface, dispIdMember,
1447 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr );
1448 ITypeInfo_Release( typeinfo );
1450 return hr;
1453 static HRESULT WINAPI static_ports__NewEnum(
1454 IStaticPortMappingCollection *iface,
1455 IUnknown **ret )
1457 TRACE( "iface %p, ret %p.\n", iface, ret );
1459 if (!ret) return E_POINTER;
1461 *ret = NULL;
1462 return create_port_mapping_enum( ret );
1465 static HRESULT WINAPI static_ports_get_Item(
1466 IStaticPortMappingCollection *iface,
1467 LONG port,
1468 BSTR protocol,
1469 IStaticPortMapping **mapping )
1471 struct port_mapping mapping_data;
1472 HRESULT ret;
1474 TRACE( "iface %p, port %ld, protocol %s.\n", iface, port, debugstr_w(protocol) );
1476 if (!mapping) return E_POINTER;
1477 *mapping = NULL;
1478 if (!is_valid_protocol( protocol )) return E_INVALIDARG;
1479 if (port < 0 || port > 65535) return E_INVALIDARG;
1481 if (!find_port_mapping( port, protocol, &mapping_data )) return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
1482 if (FAILED(ret = static_port_mapping_create( &mapping_data, mapping ))) free_port_mapping( &mapping_data );
1483 return ret;
1486 static HRESULT WINAPI static_ports_get_Count(
1487 IStaticPortMappingCollection *iface,
1488 LONG *count )
1490 TRACE( "iface %p, count %p.\n", iface, count );
1492 if (!count) return E_POINTER;
1493 *count = get_port_mapping_count();
1494 return S_OK;
1497 static HRESULT WINAPI static_ports_Remove(
1498 IStaticPortMappingCollection *iface,
1499 LONG port,
1500 BSTR protocol )
1502 TRACE( "iface %p, port %ld, protocol %s.\n", iface, port, debugstr_w(protocol) );
1504 if (!is_valid_protocol( protocol )) return E_INVALIDARG;
1505 if (port < 0 || port > 65535) return E_INVALIDARG;
1507 if (!remove_port_mapping( port, protocol )) return E_FAIL;
1509 return S_OK;
1512 static HRESULT WINAPI static_ports_Add(
1513 IStaticPortMappingCollection *iface,
1514 LONG external,
1515 BSTR protocol,
1516 LONG internal,
1517 BSTR client,
1518 VARIANT_BOOL enabled,
1519 BSTR description,
1520 IStaticPortMapping **mapping )
1522 struct port_mapping mapping_data;
1523 HRESULT ret;
1525 TRACE( "iface %p, external %ld, protocol %s, internal %ld, client %s, enabled %d, description %s, mapping %p.\n",
1526 iface, external, debugstr_w(protocol), internal, debugstr_w(client), enabled, debugstr_w(description),
1527 mapping );
1529 if (!mapping) return E_POINTER;
1530 *mapping = NULL;
1532 if (!is_valid_protocol( protocol )) return E_INVALIDARG;
1533 if (external < 0 || external > 65535) return E_INVALIDARG;
1534 if (internal < 0 || internal > 65535) return E_INVALIDARG;
1535 if (!client || !description) return E_INVALIDARG;
1537 if (!add_port_mapping( external, protocol, internal, client, enabled, description )) return E_FAIL;
1539 mapping_data.external_ip = NULL;
1540 mapping_data.external = external;
1541 mapping_data.protocol = SysAllocString( protocol );
1542 mapping_data.internal = internal;
1543 mapping_data.client = SysAllocString( client );
1544 mapping_data.enabled = enabled;
1545 mapping_data.descr = SysAllocString( description );
1546 if (!mapping_data.protocol || !mapping_data.client || !mapping_data.descr)
1548 free_port_mapping( &mapping_data );
1549 return E_OUTOFMEMORY;
1551 if (FAILED(ret = static_port_mapping_create( &mapping_data, mapping ))) free_port_mapping( &mapping_data );
1552 return ret;
1555 static const IStaticPortMappingCollectionVtbl static_ports_vtbl =
1557 static_ports_QueryInterface,
1558 static_ports_AddRef,
1559 static_ports_Release,
1560 static_ports_GetTypeInfoCount,
1561 static_ports_GetTypeInfo,
1562 static_ports_GetIDsOfNames,
1563 static_ports_Invoke,
1564 static_ports__NewEnum,
1565 static_ports_get_Item,
1566 static_ports_get_Count,
1567 static_ports_Remove,
1568 static_ports_Add,
1571 static HRESULT static_port_mapping_collection_create(IStaticPortMappingCollection **object)
1573 struct static_port_mapping_collection *ports;
1575 if (!object) return E_POINTER;
1576 if (!grab_gateway_connection())
1578 *object = NULL;
1579 return S_OK;
1581 if (!(ports = calloc( 1, sizeof(*ports) )))
1583 release_gateway_connection();
1584 return E_OUTOFMEMORY;
1586 ports->refs = 1;
1587 ports->IStaticPortMappingCollection_iface.lpVtbl = &static_ports_vtbl;
1588 *object = &ports->IStaticPortMappingCollection_iface;
1589 return S_OK;
1592 typedef struct fw_port
1594 INetFwOpenPort INetFwOpenPort_iface;
1595 LONG refs;
1596 BSTR name;
1597 NET_FW_IP_PROTOCOL protocol;
1598 LONG port;
1599 } fw_port;
1601 static inline fw_port *impl_from_INetFwOpenPort( INetFwOpenPort *iface )
1603 return CONTAINING_RECORD(iface, fw_port, INetFwOpenPort_iface);
1606 static ULONG WINAPI fw_port_AddRef(
1607 INetFwOpenPort *iface )
1609 fw_port *fw_port = impl_from_INetFwOpenPort( iface );
1610 return InterlockedIncrement( &fw_port->refs );
1613 static ULONG WINAPI fw_port_Release(
1614 INetFwOpenPort *iface )
1616 fw_port *fw_port = impl_from_INetFwOpenPort( iface );
1617 LONG refs = InterlockedDecrement( &fw_port->refs );
1618 if (!refs)
1620 TRACE("destroying %p\n", fw_port);
1621 SysFreeString( fw_port->name );
1622 free( fw_port );
1624 return refs;
1627 static HRESULT WINAPI fw_port_QueryInterface(
1628 INetFwOpenPort *iface,
1629 REFIID riid,
1630 void **ppvObject )
1632 fw_port *This = impl_from_INetFwOpenPort( iface );
1634 TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject );
1636 if ( IsEqualGUID( riid, &IID_INetFwOpenPort ) ||
1637 IsEqualGUID( riid, &IID_IDispatch ) ||
1638 IsEqualGUID( riid, &IID_IUnknown ) )
1640 *ppvObject = iface;
1642 else
1644 FIXME("interface %s not implemented\n", debugstr_guid(riid));
1645 return E_NOINTERFACE;
1647 INetFwOpenPort_AddRef( iface );
1648 return S_OK;
1651 static HRESULT WINAPI fw_port_GetTypeInfoCount(
1652 INetFwOpenPort *iface,
1653 UINT *pctinfo )
1655 fw_port *This = impl_from_INetFwOpenPort( iface );
1657 TRACE("%p %p\n", This, pctinfo);
1658 *pctinfo = 1;
1659 return S_OK;
1662 static HRESULT WINAPI fw_port_GetTypeInfo(
1663 INetFwOpenPort *iface,
1664 UINT iTInfo,
1665 LCID lcid,
1666 ITypeInfo **ppTInfo )
1668 fw_port *This = impl_from_INetFwOpenPort( iface );
1670 TRACE("%p %u %lu %p\n", This, iTInfo, lcid, ppTInfo);
1671 return get_typeinfo( INetFwOpenPort_tid, ppTInfo );
1674 static HRESULT WINAPI fw_port_GetIDsOfNames(
1675 INetFwOpenPort *iface,
1676 REFIID riid,
1677 LPOLESTR *rgszNames,
1678 UINT cNames,
1679 LCID lcid,
1680 DISPID *rgDispId )
1682 fw_port *This = impl_from_INetFwOpenPort( iface );
1683 ITypeInfo *typeinfo;
1684 HRESULT hr;
1686 TRACE("%p %s %p %u %lu %p\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
1688 hr = get_typeinfo( INetFwOpenPort_tid, &typeinfo );
1689 if (SUCCEEDED(hr))
1691 hr = ITypeInfo_GetIDsOfNames( typeinfo, rgszNames, cNames, rgDispId );
1692 ITypeInfo_Release( typeinfo );
1694 return hr;
1697 static HRESULT WINAPI fw_port_Invoke(
1698 INetFwOpenPort *iface,
1699 DISPID dispIdMember,
1700 REFIID riid,
1701 LCID lcid,
1702 WORD wFlags,
1703 DISPPARAMS *pDispParams,
1704 VARIANT *pVarResult,
1705 EXCEPINFO *pExcepInfo,
1706 UINT *puArgErr )
1708 fw_port *This = impl_from_INetFwOpenPort( iface );
1709 ITypeInfo *typeinfo;
1710 HRESULT hr;
1712 TRACE("%p %ld %s %ld %d %p %p %p %p\n", This, dispIdMember, debugstr_guid(riid),
1713 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1715 hr = get_typeinfo( INetFwOpenPort_tid, &typeinfo );
1716 if (SUCCEEDED(hr))
1718 hr = ITypeInfo_Invoke( typeinfo, &This->INetFwOpenPort_iface, dispIdMember,
1719 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr );
1720 ITypeInfo_Release( typeinfo );
1722 return hr;
1725 static HRESULT WINAPI fw_port_get_Name(
1726 INetFwOpenPort *iface,
1727 BSTR *name)
1729 fw_port *This = impl_from_INetFwOpenPort( iface );
1731 FIXME("%p %p\n", This, name);
1732 return E_NOTIMPL;
1735 static HRESULT WINAPI fw_port_put_Name(
1736 INetFwOpenPort *iface,
1737 BSTR name)
1739 fw_port *This = impl_from_INetFwOpenPort( iface );
1741 TRACE("%p %s\n", This, debugstr_w(name));
1743 if (!(name = SysAllocString( name )))
1744 return E_OUTOFMEMORY;
1746 SysFreeString( This->name );
1747 This->name = name;
1748 return S_OK;
1751 static HRESULT WINAPI fw_port_get_IpVersion(
1752 INetFwOpenPort *iface,
1753 NET_FW_IP_VERSION *ipVersion)
1755 fw_port *This = impl_from_INetFwOpenPort( iface );
1757 FIXME("%p %p\n", This, ipVersion);
1758 return E_NOTIMPL;
1761 static HRESULT WINAPI fw_port_put_IpVersion(
1762 INetFwOpenPort *iface,
1763 NET_FW_IP_VERSION ipVersion)
1765 fw_port *This = impl_from_INetFwOpenPort( iface );
1767 FIXME("%p %u\n", This, ipVersion);
1768 return E_NOTIMPL;
1771 static HRESULT WINAPI fw_port_get_Protocol(
1772 INetFwOpenPort *iface,
1773 NET_FW_IP_PROTOCOL *ipProtocol)
1775 fw_port *This = impl_from_INetFwOpenPort( iface );
1777 FIXME("%p %p\n", This, ipProtocol);
1778 return E_NOTIMPL;
1781 static HRESULT WINAPI fw_port_put_Protocol(
1782 INetFwOpenPort *iface,
1783 NET_FW_IP_PROTOCOL ipProtocol)
1785 fw_port *This = impl_from_INetFwOpenPort( iface );
1787 TRACE("%p %u\n", This, ipProtocol);
1789 if (ipProtocol != NET_FW_IP_PROTOCOL_TCP && ipProtocol != NET_FW_IP_PROTOCOL_UDP)
1790 return E_INVALIDARG;
1792 This->protocol = ipProtocol;
1793 return S_OK;
1796 static HRESULT WINAPI fw_port_get_Port(
1797 INetFwOpenPort *iface,
1798 LONG *portNumber)
1800 fw_port *This = impl_from_INetFwOpenPort( iface );
1802 FIXME("%p %p\n", This, portNumber);
1803 return E_NOTIMPL;
1806 static HRESULT WINAPI fw_port_put_Port(
1807 INetFwOpenPort *iface,
1808 LONG portNumber)
1810 fw_port *This = impl_from_INetFwOpenPort( iface );
1812 TRACE("%p %ld\n", This, portNumber);
1813 This->port = portNumber;
1814 return S_OK;
1817 static HRESULT WINAPI fw_port_get_Scope(
1818 INetFwOpenPort *iface,
1819 NET_FW_SCOPE *scope)
1821 fw_port *This = impl_from_INetFwOpenPort( iface );
1823 FIXME("%p %p\n", This, scope);
1824 return E_NOTIMPL;
1827 static HRESULT WINAPI fw_port_put_Scope(
1828 INetFwOpenPort *iface,
1829 NET_FW_SCOPE scope)
1831 fw_port *This = impl_from_INetFwOpenPort( iface );
1833 FIXME("%p %u\n", This, scope);
1834 return E_NOTIMPL;
1837 static HRESULT WINAPI fw_port_get_RemoteAddresses(
1838 INetFwOpenPort *iface,
1839 BSTR *remoteAddrs)
1841 fw_port *This = impl_from_INetFwOpenPort( iface );
1843 FIXME("%p %p\n", This, remoteAddrs);
1844 return E_NOTIMPL;
1847 static HRESULT WINAPI fw_port_put_RemoteAddresses(
1848 INetFwOpenPort *iface,
1849 BSTR remoteAddrs)
1851 fw_port *This = impl_from_INetFwOpenPort( iface );
1853 FIXME("%p %s\n", This, debugstr_w(remoteAddrs));
1854 return E_NOTIMPL;
1857 static HRESULT WINAPI fw_port_get_Enabled(
1858 INetFwOpenPort *iface,
1859 VARIANT_BOOL *enabled)
1861 fw_port *This = impl_from_INetFwOpenPort( iface );
1863 FIXME("%p %p\n", This, enabled);
1865 *enabled = VARIANT_TRUE;
1866 return S_OK;
1869 static HRESULT WINAPI fw_port_put_Enabled(
1870 INetFwOpenPort *iface,
1871 VARIANT_BOOL enabled)
1873 fw_port *This = impl_from_INetFwOpenPort( iface );
1875 FIXME("%p %d\n", This, enabled);
1876 return S_OK;
1879 static HRESULT WINAPI fw_port_get_BuiltIn(
1880 INetFwOpenPort *iface,
1881 VARIANT_BOOL *builtIn)
1883 fw_port *This = impl_from_INetFwOpenPort( iface );
1885 FIXME("%p %p\n", This, builtIn);
1886 return E_NOTIMPL;
1889 static const struct INetFwOpenPortVtbl fw_port_vtbl =
1891 fw_port_QueryInterface,
1892 fw_port_AddRef,
1893 fw_port_Release,
1894 fw_port_GetTypeInfoCount,
1895 fw_port_GetTypeInfo,
1896 fw_port_GetIDsOfNames,
1897 fw_port_Invoke,
1898 fw_port_get_Name,
1899 fw_port_put_Name,
1900 fw_port_get_IpVersion,
1901 fw_port_put_IpVersion,
1902 fw_port_get_Protocol,
1903 fw_port_put_Protocol,
1904 fw_port_get_Port,
1905 fw_port_put_Port,
1906 fw_port_get_Scope,
1907 fw_port_put_Scope,
1908 fw_port_get_RemoteAddresses,
1909 fw_port_put_RemoteAddresses,
1910 fw_port_get_Enabled,
1911 fw_port_put_Enabled,
1912 fw_port_get_BuiltIn
1915 HRESULT NetFwOpenPort_create( IUnknown *pUnkOuter, LPVOID *ppObj )
1917 fw_port *fp;
1919 TRACE("(%p,%p)\n", pUnkOuter, ppObj);
1921 fp = malloc( sizeof(*fp) );
1922 if (!fp) return E_OUTOFMEMORY;
1924 fp->INetFwOpenPort_iface.lpVtbl = &fw_port_vtbl;
1925 fp->refs = 1;
1926 fp->name = NULL;
1927 fp->protocol = NET_FW_IP_PROTOCOL_TCP;
1928 fp->port = 0;
1930 *ppObj = &fp->INetFwOpenPort_iface;
1932 TRACE("returning iface %p\n", *ppObj);
1933 return S_OK;
1936 typedef struct fw_ports
1938 INetFwOpenPorts INetFwOpenPorts_iface;
1939 LONG refs;
1940 } fw_ports;
1942 static inline fw_ports *impl_from_INetFwOpenPorts( INetFwOpenPorts *iface )
1944 return CONTAINING_RECORD(iface, fw_ports, INetFwOpenPorts_iface);
1947 static ULONG WINAPI fw_ports_AddRef(
1948 INetFwOpenPorts *iface )
1950 fw_ports *fw_ports = impl_from_INetFwOpenPorts( iface );
1951 return InterlockedIncrement( &fw_ports->refs );
1954 static ULONG WINAPI fw_ports_Release(
1955 INetFwOpenPorts *iface )
1957 fw_ports *fw_ports = impl_from_INetFwOpenPorts( iface );
1958 LONG refs = InterlockedDecrement( &fw_ports->refs );
1959 if (!refs)
1961 TRACE("destroying %p\n", fw_ports);
1962 free( fw_ports );
1964 return refs;
1967 static HRESULT WINAPI fw_ports_QueryInterface(
1968 INetFwOpenPorts *iface,
1969 REFIID riid,
1970 void **ppvObject )
1972 fw_ports *This = impl_from_INetFwOpenPorts( iface );
1974 TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject );
1976 if ( IsEqualGUID( riid, &IID_INetFwOpenPorts ) ||
1977 IsEqualGUID( riid, &IID_IDispatch ) ||
1978 IsEqualGUID( riid, &IID_IUnknown ) )
1980 *ppvObject = iface;
1982 else
1984 FIXME("interface %s not implemented\n", debugstr_guid(riid));
1985 return E_NOINTERFACE;
1987 INetFwOpenPorts_AddRef( iface );
1988 return S_OK;
1991 static HRESULT WINAPI fw_ports_GetTypeInfoCount(
1992 INetFwOpenPorts *iface,
1993 UINT *pctinfo )
1995 fw_ports *This = impl_from_INetFwOpenPorts( iface );
1997 TRACE("%p %p\n", This, pctinfo);
1998 *pctinfo = 1;
1999 return S_OK;
2002 static HRESULT WINAPI fw_ports_GetTypeInfo(
2003 INetFwOpenPorts *iface,
2004 UINT iTInfo,
2005 LCID lcid,
2006 ITypeInfo **ppTInfo )
2008 fw_ports *This = impl_from_INetFwOpenPorts( iface );
2010 TRACE("%p %u %lu %p\n", This, iTInfo, lcid, ppTInfo);
2011 return get_typeinfo( INetFwOpenPorts_tid, ppTInfo );
2014 static HRESULT WINAPI fw_ports_GetIDsOfNames(
2015 INetFwOpenPorts *iface,
2016 REFIID riid,
2017 LPOLESTR *rgszNames,
2018 UINT cNames,
2019 LCID lcid,
2020 DISPID *rgDispId )
2022 fw_ports *This = impl_from_INetFwOpenPorts( iface );
2023 ITypeInfo *typeinfo;
2024 HRESULT hr;
2026 TRACE("%p %s %p %u %lu %p\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
2028 hr = get_typeinfo( INetFwOpenPorts_tid, &typeinfo );
2029 if (SUCCEEDED(hr))
2031 hr = ITypeInfo_GetIDsOfNames( typeinfo, rgszNames, cNames, rgDispId );
2032 ITypeInfo_Release( typeinfo );
2034 return hr;
2037 static HRESULT WINAPI fw_ports_Invoke(
2038 INetFwOpenPorts *iface,
2039 DISPID dispIdMember,
2040 REFIID riid,
2041 LCID lcid,
2042 WORD wFlags,
2043 DISPPARAMS *pDispParams,
2044 VARIANT *pVarResult,
2045 EXCEPINFO *pExcepInfo,
2046 UINT *puArgErr )
2048 fw_ports *This = impl_from_INetFwOpenPorts( iface );
2049 ITypeInfo *typeinfo;
2050 HRESULT hr;
2052 TRACE("%p %ld %s %ld %d %p %p %p %p\n", This, dispIdMember, debugstr_guid(riid),
2053 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2055 hr = get_typeinfo( INetFwOpenPorts_tid, &typeinfo );
2056 if (SUCCEEDED(hr))
2058 hr = ITypeInfo_Invoke( typeinfo, &This->INetFwOpenPorts_iface, dispIdMember,
2059 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr );
2060 ITypeInfo_Release( typeinfo );
2062 return hr;
2065 static HRESULT WINAPI fw_ports_get_Count(
2066 INetFwOpenPorts *iface,
2067 LONG *count)
2069 fw_ports *This = impl_from_INetFwOpenPorts( iface );
2071 FIXME("%p, %p\n", This, count);
2073 *count = 0;
2074 return S_OK;
2077 static HRESULT WINAPI fw_ports_Add(
2078 INetFwOpenPorts *iface,
2079 INetFwOpenPort *port)
2081 fw_ports *This = impl_from_INetFwOpenPorts( iface );
2083 FIXME("%p, %p\n", This, port);
2084 return S_OK;
2087 static HRESULT WINAPI fw_ports_Remove(
2088 INetFwOpenPorts *iface,
2089 LONG portNumber,
2090 NET_FW_IP_PROTOCOL ipProtocol)
2092 fw_ports *This = impl_from_INetFwOpenPorts( iface );
2094 FIXME("%p, %ld, %u\n", This, portNumber, ipProtocol);
2095 return E_NOTIMPL;
2098 static HRESULT WINAPI fw_ports_Item(
2099 INetFwOpenPorts *iface,
2100 LONG portNumber,
2101 NET_FW_IP_PROTOCOL ipProtocol,
2102 INetFwOpenPort **openPort)
2104 HRESULT hr;
2105 fw_ports *This = impl_from_INetFwOpenPorts( iface );
2107 FIXME("%p, %ld, %u, %p\n", This, portNumber, ipProtocol, openPort);
2109 hr = NetFwOpenPort_create( NULL, (void **)openPort );
2110 if (SUCCEEDED(hr))
2112 INetFwOpenPort_put_Protocol( *openPort, ipProtocol );
2113 INetFwOpenPort_put_Port( *openPort, portNumber );
2115 return hr;
2118 static HRESULT WINAPI fw_ports_get__NewEnum(
2119 INetFwOpenPorts *iface,
2120 IUnknown **newEnum)
2122 fw_ports *This = impl_from_INetFwOpenPorts( iface );
2124 FIXME("%p, %p\n", This, newEnum);
2125 return E_NOTIMPL;
2128 static const struct INetFwOpenPortsVtbl fw_ports_vtbl =
2130 fw_ports_QueryInterface,
2131 fw_ports_AddRef,
2132 fw_ports_Release,
2133 fw_ports_GetTypeInfoCount,
2134 fw_ports_GetTypeInfo,
2135 fw_ports_GetIDsOfNames,
2136 fw_ports_Invoke,
2137 fw_ports_get_Count,
2138 fw_ports_Add,
2139 fw_ports_Remove,
2140 fw_ports_Item,
2141 fw_ports_get__NewEnum
2144 HRESULT NetFwOpenPorts_create( IUnknown *pUnkOuter, LPVOID *ppObj )
2146 fw_ports *fp;
2148 TRACE("(%p,%p)\n", pUnkOuter, ppObj);
2150 fp = malloc( sizeof(*fp) );
2151 if (!fp) return E_OUTOFMEMORY;
2153 fp->INetFwOpenPorts_iface.lpVtbl = &fw_ports_vtbl;
2154 fp->refs = 1;
2156 *ppObj = &fp->INetFwOpenPorts_iface;
2158 TRACE("returning iface %p\n", *ppObj);
2159 return S_OK;
2162 typedef struct _upnpnat
2164 IUPnPNAT IUPnPNAT_iface;
2165 LONG ref;
2166 } upnpnat;
2168 static inline upnpnat *impl_from_IUPnPNAT( IUPnPNAT *iface )
2170 return CONTAINING_RECORD(iface, upnpnat, IUPnPNAT_iface);
2173 static HRESULT WINAPI upnpnat_QueryInterface(IUPnPNAT *iface, REFIID riid, void **object)
2175 upnpnat *This = impl_from_IUPnPNAT( iface );
2177 TRACE("%p %s %p\n", This, debugstr_guid( riid ), object );
2179 if ( IsEqualGUID( riid, &IID_IUPnPNAT ) ||
2180 IsEqualGUID( riid, &IID_IDispatch ) ||
2181 IsEqualGUID( riid, &IID_IUnknown ) )
2183 *object = iface;
2185 else if(IsEqualGUID( riid, &IID_IProvideClassInfo))
2187 TRACE("IProvideClassInfo not supported.\n");
2188 return E_NOINTERFACE;
2190 else
2192 FIXME("interface %s not implemented\n", debugstr_guid(riid));
2193 return E_NOINTERFACE;
2195 IUPnPNAT_AddRef( iface );
2196 return S_OK;
2199 static ULONG WINAPI upnpnat_AddRef(IUPnPNAT *iface)
2201 upnpnat *This = impl_from_IUPnPNAT( iface );
2202 return InterlockedIncrement( &This->ref );
2205 static ULONG WINAPI upnpnat_Release(IUPnPNAT *iface)
2207 upnpnat *This = impl_from_IUPnPNAT( iface );
2208 LONG refs = InterlockedDecrement( &This->ref );
2209 if (!refs)
2211 free( This );
2213 return refs;
2216 static HRESULT WINAPI upnpnat_GetTypeInfoCount(IUPnPNAT *iface, UINT *pctinfo)
2218 upnpnat *This = impl_from_IUPnPNAT( iface );
2220 TRACE("%p %p\n", This, pctinfo);
2221 *pctinfo = 1;
2222 return S_OK;
2225 static HRESULT WINAPI upnpnat_GetTypeInfo(IUPnPNAT *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
2227 upnpnat *This = impl_from_IUPnPNAT( iface );
2229 TRACE("%p %u %lu %p\n", This, iTInfo, lcid, ppTInfo);
2230 return get_typeinfo( IUPnPNAT_tid, ppTInfo );
2233 static HRESULT WINAPI upnpnat_GetIDsOfNames(IUPnPNAT *iface, REFIID riid, LPOLESTR *rgszNames,
2234 UINT cNames, LCID lcid, DISPID *rgDispId)
2236 upnpnat *This = impl_from_IUPnPNAT( iface );
2237 ITypeInfo *typeinfo;
2238 HRESULT hr;
2240 TRACE("%p %s %p %u %lu %p\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
2242 hr = get_typeinfo( IUPnPNAT_tid, &typeinfo );
2243 if (SUCCEEDED(hr))
2245 hr = ITypeInfo_GetIDsOfNames( typeinfo, rgszNames, cNames, rgDispId );
2246 ITypeInfo_Release( typeinfo );
2248 return hr;
2251 static HRESULT WINAPI upnpnat_Invoke(IUPnPNAT *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
2252 WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo,
2253 UINT *puArgErr)
2255 upnpnat *This = impl_from_IUPnPNAT( iface );
2256 ITypeInfo *typeinfo;
2257 HRESULT hr;
2259 TRACE("%p %ld %s %ld %d %p %p %p %p\n", This, dispIdMember, debugstr_guid(riid),
2260 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2262 hr = get_typeinfo( IUPnPNAT_tid, &typeinfo );
2263 if (SUCCEEDED(hr))
2265 hr = ITypeInfo_Invoke( typeinfo, &This->IUPnPNAT_iface, dispIdMember,
2266 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr );
2267 ITypeInfo_Release( typeinfo );
2269 return hr;
2272 static HRESULT WINAPI upnpnat_get_StaticPortMappingCollection(IUPnPNAT *iface, IStaticPortMappingCollection **collection)
2274 upnpnat *This = impl_from_IUPnPNAT( iface );
2276 TRACE("%p, %p\n", This, collection);
2278 return static_port_mapping_collection_create( collection );
2281 static HRESULT WINAPI upnpnat_get_DynamicPortMappingCollection(IUPnPNAT *iface, IDynamicPortMappingCollection **collection)
2283 upnpnat *This = impl_from_IUPnPNAT( iface );
2284 FIXME("%p, %p\n", This, collection);
2285 if(collection)
2286 *collection = NULL;
2287 return E_NOTIMPL;
2290 static HRESULT WINAPI upnpnat_get_NATEventManager(IUPnPNAT *iface, INATEventManager **manager)
2292 upnpnat *This = impl_from_IUPnPNAT( iface );
2293 FIXME("%p, %p\n", This, manager);
2294 if(manager)
2295 *manager = NULL;
2296 return E_NOTIMPL;
2299 const static IUPnPNATVtbl upnpnat_vtbl =
2301 upnpnat_QueryInterface,
2302 upnpnat_AddRef,
2303 upnpnat_Release,
2304 upnpnat_GetTypeInfoCount,
2305 upnpnat_GetTypeInfo,
2306 upnpnat_GetIDsOfNames,
2307 upnpnat_Invoke,
2308 upnpnat_get_StaticPortMappingCollection,
2309 upnpnat_get_DynamicPortMappingCollection,
2310 upnpnat_get_NATEventManager
2314 HRESULT IUPnPNAT_create(IUnknown *outer, void **object)
2316 upnpnat *nat;
2318 TRACE("(%p,%p)\n", outer, object);
2320 nat = malloc( sizeof(*nat) );
2321 if (!nat) return E_OUTOFMEMORY;
2323 nat->IUPnPNAT_iface.lpVtbl = &upnpnat_vtbl;
2324 nat->ref = 1;
2326 *object = &nat->IUPnPNAT_iface;
2328 TRACE("returning iface %p\n", *object);
2329 return S_OK;