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
38 #include "wine/debug.h"
39 #include "hnetcfg_private.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(hnetcfg
);
63 BOOL winsock_initialized
;
65 HINTERNET session
, connection
;
66 WCHAR desc_urlpath
[128];
67 WCHAR control_url
[256];
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)
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 ); \
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
;
117 static BOOL
parse_search_response( char *response
, WCHAR
*locationW
, unsigned int location_size
)
119 char *saveptr
= NULL
, *tok
, *tok2
;
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
);
136 while ((tok
= strtok_s( NULL
, "\n", &saveptr
)))
138 tok2
= strtok( tok
, " " );
140 if (!stricmp( tok2
, "LOCATION:" ))
142 tok2
= strtok( NULL
, " \r" );
145 WARN( "Error parsing location.\n" );
148 return !!MultiByteToWideChar( CP_UTF8
, 0, tok2
, -1, locationW
, location_size
/ 2 );
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
;
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
);
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" );
190 if (node_type
== XmlNodeType_EndElement
)
192 if (!wcsicmp( value
, L
"service" )) break;
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
)
218 FIXME( "Found another WANIPConnection service, ignoring.\n" );
222 wcscpy( upnp_gateway_connection
.control_url
, control_url
);
223 upnp_gateway_connection
.version
= version
;
229 IXmlReader_Release( reader
);
230 IStream_Release( stream
);
234 static BOOL
get_xml_elements( const char *desc_xml
, struct xml_value_desc
*values
, unsigned int value_count
)
236 XmlNodeType node_type
;
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
);
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
"";
270 if (FAILED(IXmlReader_GetValue( reader
, &value
, NULL
))) goto done
;
274 WARN( "Duplicate value %s.\n", debugstr_w(values
[i
].name
) );
277 if (!(values
[i
].value
= SysAllocString( value
))) goto done
;
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
);
295 static BOOL
open_gateway_connection(void)
297 static const int timeout
= 3000;
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
))
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() );
328 static BOOL
get_control_url(void)
330 static const WCHAR
*accept_types
[] =
335 unsigned int desc_xml_size
, offset
;
336 DWORD size
, status
= 0;
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
);
351 if (!WinHttpReceiveResponse(request
, NULL
))
353 WARN( "Error receiving response %lu.\n", GetLastError() );
354 WinHttpCloseHandle( request
);
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
);
365 desc_xml_size
= 1024;
366 desc_xml
= malloc( desc_xml_size
);
368 while (WinHttpReadData( request
, desc_xml
+ offset
, desc_xml_size
- offset
- 1, &size
) && size
)
371 if (offset
+ 1 == desc_xml_size
)
376 if (!(new = realloc( desc_xml
, desc_xml_size
)))
378 ERR( "No memory.\n" );
384 desc_xml
[offset
] = 0;
385 WinHttpCloseHandle( request
);
386 ret
= parse_desc_xml( desc_xml
);
391 static void gateway_connection_cleanup(void)
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
[] =
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
;
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
;
438 snprintf( ptr
, request_data_size
, request_template_header
, function
, upnp_gateway_connection
.version
);
439 offset
= strlen( ptr
);
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
);
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() );
462 if (!WinHttpReceiveResponse(request
, NULL
))
464 WARN( "Error receiving response %lu.\n", GetLastError() );
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
)
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
)
484 if (offset
+ 1 == reply_buffer_size
)
488 reply_buffer_size
*= 2;
489 if (!(new = realloc( reply_buffer
, reply_buffer_size
))) goto done
;
493 reply_buffer
[offset
] = 0;
495 if (*http_status
== HTTP_STATUS_OK
) ret
= get_xml_elements( reply_buffer
, result
, result_count
);
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
;
505 free( reply_buffer
);
506 free( request_data
);
507 WinHttpCloseHandle( request
);
511 enum port_mapping_parameter
522 PM_REMOVE_PORT_LAST
= PM_INTERNAL
,
525 static struct xml_value_desc port_mapping_template
[] =
527 { L
"NewRemoteHost" },
528 { L
"NewExternalPort" },
530 { L
"NewInternalPort" },
531 { L
"NewInternalClient" },
533 { L
"NewPortMappingDescription" },
534 { L
"NewLeaseDuration" },
537 static LONG
long_from_bstr( BSTR s
)
543 static BSTR
mapping_move_bstr( BSTR
*s
)
552 else if (!(ret
= SysAllocString( L
"" )))
554 ERR( "No memory.\n" );
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
;
572 index_param
.name
= L
"NewPortMappingIndex";
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
);
588 if (status
!= HTTP_STATUS_OK
)
592 if (long_from_bstr( error_str
) != 713)
593 WARN( "Server returned error %s.\n", debugstr_w(error_str
) );
594 SysFreeString( error_str
);
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
;
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
];
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
);
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
);
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];
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
);
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
);
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"
709 "MAN:\"ssdp:discover\"\r\n"
712 const DWORD timeout
= 1000;
713 int len
, address_len
;
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() );
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() );
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
) )
738 ERR( "sendto failed, error %u\n", WSAGetLastError() );
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
);
752 if (WSAGetLastError() != WSAETIMEDOUT
)
754 WARN( "recvfrom error %u.\n", WSAGetLastError() );
764 TRACE( "No reply from router.\n" );
767 TRACE( "Received reply from gateway, len %d.\n", len
);
769 if (!parse_search_response( buffer
, upnp_gateway_connection
.locationW
, sizeof(upnp_gateway_connection
.locationW
) ))
771 WARN( "Error parsing response.\n" );
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" );
780 TRACE( "Opened gateway connection.\n" );
781 if (!get_control_url())
783 WARN( "Could not get_control URL.\n" );
784 gateway_connection_cleanup();
787 TRACE( "control_url %s, version %u.\n", debugstr_w(upnp_gateway_connection
.control_url
),
788 upnp_gateway_connection
.version
);
790 update_mapping_list();
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
);
803 ++upnp_gateway_connection
.refs
;
804 ReleaseSRWLockExclusive( &upnp_gateway_connection_lock
);
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
)
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
))
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
);
835 static unsigned int get_port_mapping_range( unsigned int index
, unsigned int count
, struct port_mapping
*ret
)
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" );
846 ReleaseSRWLockExclusive( &upnp_gateway_connection_lock
);
851 static unsigned int get_port_mapping_count(void)
855 AcquireSRWLockExclusive( &upnp_gateway_connection_lock
);
856 ret
= upnp_gateway_connection
.mapping_count
;
857 ReleaseSRWLockExclusive( &upnp_gateway_connection_lock
);
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
;
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
);
893 TRACE("destroying %p\n", mapping
);
894 free_port_mapping( &mapping
->data
);
900 static HRESULT WINAPI
static_port_mapping_QueryInterface(
901 IStaticPortMapping
*iface
,
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
) )
917 FIXME("interface %s not implemented\n", debugstr_guid(riid
));
918 return E_NOINTERFACE
;
920 IStaticPortMapping_AddRef( iface
);
924 static HRESULT WINAPI
static_port_mapping_GetTypeInfoCount(
925 IStaticPortMapping
*iface
,
928 struct static_port_mapping
*mapping
= impl_from_IStaticPortMapping( iface
);
930 TRACE("%p %p\n", mapping
, pctinfo
);
935 static HRESULT WINAPI
static_port_mapping_GetTypeInfo(
936 IStaticPortMapping
*iface
,
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
,
955 struct static_port_mapping
*mapping
= impl_from_IStaticPortMapping( iface
);
959 TRACE("%p %s %p %u %lu %p\n", mapping
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
961 hr
= get_typeinfo( IStaticPortMapping_tid
, &typeinfo
);
964 hr
= ITypeInfo_GetIDsOfNames( typeinfo
, rgszNames
, cNames
, rgDispId
);
965 ITypeInfo_Release( typeinfo
);
970 static HRESULT WINAPI
static_port_mapping_Invoke(
971 IStaticPortMapping
*iface
,
976 DISPPARAMS
*pDispParams
,
978 EXCEPINFO
*pExcepInfo
,
981 struct static_port_mapping
*mapping
= impl_from_IStaticPortMapping( iface
);
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
);
991 hr
= ITypeInfo_Invoke( typeinfo
, &mapping
->IStaticPortMapping_iface
, dispIdMember
,
992 wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
993 ITypeInfo_Release( typeinfo
);
998 static HRESULT WINAPI
static_port_mapping_get_ExternalIPAddress(
999 IStaticPortMapping
*iface
,
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
;
1012 static HRESULT WINAPI
static_port_mapping_get_ExternalPort(
1013 IStaticPortMapping
*iface
,
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
;
1025 static HRESULT WINAPI
static_port_mapping_get_InternalPort(
1026 IStaticPortMapping
*iface
,
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
;
1038 static HRESULT WINAPI
static_port_mapping_get_Protocol(
1039 IStaticPortMapping
*iface
,
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
;
1052 static HRESULT WINAPI
static_port_mapping_get_InternalClient(
1053 IStaticPortMapping
*iface
,
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
;
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
;
1079 static HRESULT WINAPI
static_port_mapping_get_Description(
1080 IStaticPortMapping
*iface
,
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
;
1093 static HRESULT WINAPI
static_port_mapping_EditInternalClient(
1094 IStaticPortMapping
*iface
,
1097 FIXME( "iface %p, value %s stub.\n", iface
, debugstr_w(value
) );
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
);
1111 static HRESULT WINAPI
static_port_mapping_EditDescription(
1112 IStaticPortMapping
*iface
,
1115 FIXME( "iface %p, value %s stub.\n", iface
, debugstr_w(value
) );
1120 static HRESULT WINAPI
static_port_mapping_EditInternalPort(
1121 IStaticPortMapping
*iface
,
1124 FIXME( "iface %p, value %ld stub.\n", iface
, value
);
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
;
1158 mapping
->IStaticPortMapping_iface
.lpVtbl
= &static_port_mapping_vtbl
;
1159 mapping
->data
= *mapping_data
;
1160 *ret
= &mapping
->IStaticPortMapping_iface
;
1164 struct port_mapping_enum
1166 IEnumVARIANT IEnumVARIANT_iface
;
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
);
1190 TRACE("destroying %p\n", mapping_enum
);
1191 free( mapping_enum
);
1192 release_gateway_connection();
1197 static HRESULT WINAPI
port_mapping_enum_QueryInterface(
1198 IEnumVARIANT
*iface
,
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
) )
1213 FIXME("interface %s not implemented\n", debugstr_guid(riid
));
1214 return E_NOINTERFACE
;
1216 IEnumVARIANT_AddRef( iface
);
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
;
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
] );
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;
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
);
1287 TRACE( "iface %p, ret %p.\n", iface
, ret
);
1289 if (!ret
) return E_POINTER
;
1291 if (FAILED(hr
= create_port_mapping_enum( (IUnknown
**)ret
))) return hr
;
1292 impl_from_IEnumVARIANT( *ret
)->index
= mapping_enum
->index
;
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
;
1322 struct static_port_mapping_collection
1324 IStaticPortMappingCollection IStaticPortMappingCollection_iface
;
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
);
1348 TRACE("destroying %p\n", ports
);
1349 release_gateway_connection();
1355 static HRESULT WINAPI
static_ports_QueryInterface(
1356 IStaticPortMappingCollection
*iface
,
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
) )
1372 FIXME("interface %s not implemented\n", debugstr_guid(riid
));
1373 return E_NOINTERFACE
;
1375 IStaticPortMappingCollection_AddRef( iface
);
1379 static HRESULT WINAPI
static_ports_GetTypeInfoCount(
1380 IStaticPortMappingCollection
*iface
,
1383 struct static_port_mapping_collection
*ports
= impl_from_IStaticPortMappingCollection( iface
);
1385 TRACE("%p %p\n", ports
, pctinfo
);
1390 static HRESULT WINAPI
static_ports_GetTypeInfo(
1391 IStaticPortMappingCollection
*iface
,
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
,
1405 LPOLESTR
*rgszNames
,
1410 struct static_port_mapping_collection
*ports
= impl_from_IStaticPortMappingCollection( iface
);
1411 ITypeInfo
*typeinfo
;
1414 TRACE("%p %s %p %u %lu %p\n", ports
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
1416 hr
= get_typeinfo( IStaticPortMappingCollection_tid
, &typeinfo
);
1419 hr
= ITypeInfo_GetIDsOfNames( typeinfo
, rgszNames
, cNames
, rgDispId
);
1420 ITypeInfo_Release( typeinfo
);
1425 static HRESULT WINAPI
static_ports_Invoke(
1426 IStaticPortMappingCollection
*iface
,
1427 DISPID dispIdMember
,
1431 DISPPARAMS
*pDispParams
,
1432 VARIANT
*pVarResult
,
1433 EXCEPINFO
*pExcepInfo
,
1436 struct static_port_mapping_collection
*ports
= impl_from_IStaticPortMappingCollection( iface
);
1437 ITypeInfo
*typeinfo
;
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
);
1446 hr
= ITypeInfo_Invoke( typeinfo
, &ports
->IStaticPortMappingCollection_iface
, dispIdMember
,
1447 wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1448 ITypeInfo_Release( typeinfo
);
1453 static HRESULT WINAPI
static_ports__NewEnum(
1454 IStaticPortMappingCollection
*iface
,
1457 TRACE( "iface %p, ret %p.\n", iface
, ret
);
1459 if (!ret
) return E_POINTER
;
1462 return create_port_mapping_enum( ret
);
1465 static HRESULT WINAPI
static_ports_get_Item(
1466 IStaticPortMappingCollection
*iface
,
1469 IStaticPortMapping
**mapping
)
1471 struct port_mapping mapping_data
;
1474 TRACE( "iface %p, port %ld, protocol %s.\n", iface
, port
, debugstr_w(protocol
) );
1476 if (!mapping
) return E_POINTER
;
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
);
1486 static HRESULT WINAPI
static_ports_get_Count(
1487 IStaticPortMappingCollection
*iface
,
1490 TRACE( "iface %p, count %p.\n", iface
, count
);
1492 if (!count
) return E_POINTER
;
1493 *count
= get_port_mapping_count();
1497 static HRESULT WINAPI
static_ports_Remove(
1498 IStaticPortMappingCollection
*iface
,
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
;
1512 static HRESULT WINAPI
static_ports_Add(
1513 IStaticPortMappingCollection
*iface
,
1518 VARIANT_BOOL enabled
,
1520 IStaticPortMapping
**mapping
)
1522 struct port_mapping mapping_data
;
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
),
1529 if (!mapping
) return E_POINTER
;
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
);
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
,
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())
1581 if (!(ports
= calloc( 1, sizeof(*ports
) )))
1583 release_gateway_connection();
1584 return E_OUTOFMEMORY
;
1587 ports
->IStaticPortMappingCollection_iface
.lpVtbl
= &static_ports_vtbl
;
1588 *object
= &ports
->IStaticPortMappingCollection_iface
;
1592 typedef struct fw_port
1594 INetFwOpenPort INetFwOpenPort_iface
;
1597 NET_FW_IP_PROTOCOL protocol
;
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
);
1620 TRACE("destroying %p\n", fw_port
);
1621 SysFreeString( fw_port
->name
);
1627 static HRESULT WINAPI
fw_port_QueryInterface(
1628 INetFwOpenPort
*iface
,
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
) )
1644 FIXME("interface %s not implemented\n", debugstr_guid(riid
));
1645 return E_NOINTERFACE
;
1647 INetFwOpenPort_AddRef( iface
);
1651 static HRESULT WINAPI
fw_port_GetTypeInfoCount(
1652 INetFwOpenPort
*iface
,
1655 fw_port
*This
= impl_from_INetFwOpenPort( iface
);
1657 TRACE("%p %p\n", This
, pctinfo
);
1662 static HRESULT WINAPI
fw_port_GetTypeInfo(
1663 INetFwOpenPort
*iface
,
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
,
1677 LPOLESTR
*rgszNames
,
1682 fw_port
*This
= impl_from_INetFwOpenPort( iface
);
1683 ITypeInfo
*typeinfo
;
1686 TRACE("%p %s %p %u %lu %p\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
1688 hr
= get_typeinfo( INetFwOpenPort_tid
, &typeinfo
);
1691 hr
= ITypeInfo_GetIDsOfNames( typeinfo
, rgszNames
, cNames
, rgDispId
);
1692 ITypeInfo_Release( typeinfo
);
1697 static HRESULT WINAPI
fw_port_Invoke(
1698 INetFwOpenPort
*iface
,
1699 DISPID dispIdMember
,
1703 DISPPARAMS
*pDispParams
,
1704 VARIANT
*pVarResult
,
1705 EXCEPINFO
*pExcepInfo
,
1708 fw_port
*This
= impl_from_INetFwOpenPort( iface
);
1709 ITypeInfo
*typeinfo
;
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
);
1718 hr
= ITypeInfo_Invoke( typeinfo
, &This
->INetFwOpenPort_iface
, dispIdMember
,
1719 wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1720 ITypeInfo_Release( typeinfo
);
1725 static HRESULT WINAPI
fw_port_get_Name(
1726 INetFwOpenPort
*iface
,
1729 fw_port
*This
= impl_from_INetFwOpenPort( iface
);
1731 FIXME("%p %p\n", This
, name
);
1735 static HRESULT WINAPI
fw_port_put_Name(
1736 INetFwOpenPort
*iface
,
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
);
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
);
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
);
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
);
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
;
1796 static HRESULT WINAPI
fw_port_get_Port(
1797 INetFwOpenPort
*iface
,
1800 fw_port
*This
= impl_from_INetFwOpenPort( iface
);
1802 FIXME("%p %p\n", This
, portNumber
);
1806 static HRESULT WINAPI
fw_port_put_Port(
1807 INetFwOpenPort
*iface
,
1810 fw_port
*This
= impl_from_INetFwOpenPort( iface
);
1812 TRACE("%p %ld\n", This
, portNumber
);
1813 This
->port
= portNumber
;
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
);
1827 static HRESULT WINAPI
fw_port_put_Scope(
1828 INetFwOpenPort
*iface
,
1831 fw_port
*This
= impl_from_INetFwOpenPort( iface
);
1833 FIXME("%p %u\n", This
, scope
);
1837 static HRESULT WINAPI
fw_port_get_RemoteAddresses(
1838 INetFwOpenPort
*iface
,
1841 fw_port
*This
= impl_from_INetFwOpenPort( iface
);
1843 FIXME("%p %p\n", This
, remoteAddrs
);
1847 static HRESULT WINAPI
fw_port_put_RemoteAddresses(
1848 INetFwOpenPort
*iface
,
1851 fw_port
*This
= impl_from_INetFwOpenPort( iface
);
1853 FIXME("%p %s\n", This
, debugstr_w(remoteAddrs
));
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
;
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
);
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
);
1889 static const struct INetFwOpenPortVtbl fw_port_vtbl
=
1891 fw_port_QueryInterface
,
1894 fw_port_GetTypeInfoCount
,
1895 fw_port_GetTypeInfo
,
1896 fw_port_GetIDsOfNames
,
1900 fw_port_get_IpVersion
,
1901 fw_port_put_IpVersion
,
1902 fw_port_get_Protocol
,
1903 fw_port_put_Protocol
,
1908 fw_port_get_RemoteAddresses
,
1909 fw_port_put_RemoteAddresses
,
1910 fw_port_get_Enabled
,
1911 fw_port_put_Enabled
,
1915 HRESULT
NetFwOpenPort_create( IUnknown
*pUnkOuter
, LPVOID
*ppObj
)
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
;
1927 fp
->protocol
= NET_FW_IP_PROTOCOL_TCP
;
1930 *ppObj
= &fp
->INetFwOpenPort_iface
;
1932 TRACE("returning iface %p\n", *ppObj
);
1936 typedef struct fw_ports
1938 INetFwOpenPorts INetFwOpenPorts_iface
;
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
);
1961 TRACE("destroying %p\n", fw_ports
);
1967 static HRESULT WINAPI
fw_ports_QueryInterface(
1968 INetFwOpenPorts
*iface
,
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
) )
1984 FIXME("interface %s not implemented\n", debugstr_guid(riid
));
1985 return E_NOINTERFACE
;
1987 INetFwOpenPorts_AddRef( iface
);
1991 static HRESULT WINAPI
fw_ports_GetTypeInfoCount(
1992 INetFwOpenPorts
*iface
,
1995 fw_ports
*This
= impl_from_INetFwOpenPorts( iface
);
1997 TRACE("%p %p\n", This
, pctinfo
);
2002 static HRESULT WINAPI
fw_ports_GetTypeInfo(
2003 INetFwOpenPorts
*iface
,
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
,
2017 LPOLESTR
*rgszNames
,
2022 fw_ports
*This
= impl_from_INetFwOpenPorts( iface
);
2023 ITypeInfo
*typeinfo
;
2026 TRACE("%p %s %p %u %lu %p\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
2028 hr
= get_typeinfo( INetFwOpenPorts_tid
, &typeinfo
);
2031 hr
= ITypeInfo_GetIDsOfNames( typeinfo
, rgszNames
, cNames
, rgDispId
);
2032 ITypeInfo_Release( typeinfo
);
2037 static HRESULT WINAPI
fw_ports_Invoke(
2038 INetFwOpenPorts
*iface
,
2039 DISPID dispIdMember
,
2043 DISPPARAMS
*pDispParams
,
2044 VARIANT
*pVarResult
,
2045 EXCEPINFO
*pExcepInfo
,
2048 fw_ports
*This
= impl_from_INetFwOpenPorts( iface
);
2049 ITypeInfo
*typeinfo
;
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
);
2058 hr
= ITypeInfo_Invoke( typeinfo
, &This
->INetFwOpenPorts_iface
, dispIdMember
,
2059 wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2060 ITypeInfo_Release( typeinfo
);
2065 static HRESULT WINAPI
fw_ports_get_Count(
2066 INetFwOpenPorts
*iface
,
2069 fw_ports
*This
= impl_from_INetFwOpenPorts( iface
);
2071 FIXME("%p, %p\n", This
, count
);
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
);
2087 static HRESULT WINAPI
fw_ports_Remove(
2088 INetFwOpenPorts
*iface
,
2090 NET_FW_IP_PROTOCOL ipProtocol
)
2092 fw_ports
*This
= impl_from_INetFwOpenPorts( iface
);
2094 FIXME("%p, %ld, %u\n", This
, portNumber
, ipProtocol
);
2098 static HRESULT WINAPI
fw_ports_Item(
2099 INetFwOpenPorts
*iface
,
2101 NET_FW_IP_PROTOCOL ipProtocol
,
2102 INetFwOpenPort
**openPort
)
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
);
2112 INetFwOpenPort_put_Protocol( *openPort
, ipProtocol
);
2113 INetFwOpenPort_put_Port( *openPort
, portNumber
);
2118 static HRESULT WINAPI
fw_ports_get__NewEnum(
2119 INetFwOpenPorts
*iface
,
2122 fw_ports
*This
= impl_from_INetFwOpenPorts( iface
);
2124 FIXME("%p, %p\n", This
, newEnum
);
2128 static const struct INetFwOpenPortsVtbl fw_ports_vtbl
=
2130 fw_ports_QueryInterface
,
2133 fw_ports_GetTypeInfoCount
,
2134 fw_ports_GetTypeInfo
,
2135 fw_ports_GetIDsOfNames
,
2141 fw_ports_get__NewEnum
2144 HRESULT
NetFwOpenPorts_create( IUnknown
*pUnkOuter
, LPVOID
*ppObj
)
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
;
2156 *ppObj
= &fp
->INetFwOpenPorts_iface
;
2158 TRACE("returning iface %p\n", *ppObj
);
2162 typedef struct _upnpnat
2164 IUPnPNAT IUPnPNAT_iface
;
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
) )
2185 else if(IsEqualGUID( riid
, &IID_IProvideClassInfo
))
2187 TRACE("IProvideClassInfo not supported.\n");
2188 return E_NOINTERFACE
;
2192 FIXME("interface %s not implemented\n", debugstr_guid(riid
));
2193 return E_NOINTERFACE
;
2195 IUPnPNAT_AddRef( iface
);
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
);
2216 static HRESULT WINAPI
upnpnat_GetTypeInfoCount(IUPnPNAT
*iface
, UINT
*pctinfo
)
2218 upnpnat
*This
= impl_from_IUPnPNAT( iface
);
2220 TRACE("%p %p\n", This
, pctinfo
);
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
;
2240 TRACE("%p %s %p %u %lu %p\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
2242 hr
= get_typeinfo( IUPnPNAT_tid
, &typeinfo
);
2245 hr
= ITypeInfo_GetIDsOfNames( typeinfo
, rgszNames
, cNames
, rgDispId
);
2246 ITypeInfo_Release( typeinfo
);
2251 static HRESULT WINAPI
upnpnat_Invoke(IUPnPNAT
*iface
, DISPID dispIdMember
, REFIID riid
, LCID lcid
,
2252 WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
,
2255 upnpnat
*This
= impl_from_IUPnPNAT( iface
);
2256 ITypeInfo
*typeinfo
;
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
);
2265 hr
= ITypeInfo_Invoke( typeinfo
, &This
->IUPnPNAT_iface
, dispIdMember
,
2266 wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2267 ITypeInfo_Release( typeinfo
);
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
);
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
);
2299 const static IUPnPNATVtbl upnpnat_vtbl
=
2301 upnpnat_QueryInterface
,
2304 upnpnat_GetTypeInfoCount
,
2305 upnpnat_GetTypeInfo
,
2306 upnpnat_GetIDsOfNames
,
2308 upnpnat_get_StaticPortMappingCollection
,
2309 upnpnat_get_DynamicPortMappingCollection
,
2310 upnpnat_get_NATEventManager
2314 HRESULT
IUPnPNAT_create(IUnknown
*outer
, void **object
)
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
;
2326 *object
= &nat
->IUPnPNAT_iface
;
2328 TRACE("returning iface %p\n", *object
);