Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
e98a102b
Commit
e98a102b
authored
Feb 02, 2022
by
Paul Gofman
Committed by
Alexandre Julliard
Feb 02, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
hnetcfg: Get port mapping list in init_gateway_connection().
Signed-off-by:
Paul Gofman
<
pgofman@codeweavers.com
>
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
42b2a69a
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
306 additions
and
0 deletions
+306
-0
port.c
dlls/hnetcfg/port.c
+306
-0
No files found.
dlls/hnetcfg/port.c
View file @
e98a102b
...
...
@@ -40,6 +40,23 @@
WINE_DEFAULT_DEBUG_CHANNEL
(
hnetcfg
);
struct
port_mapping
{
BSTR
external_ip
;
LONG
external
;
BSTR
protocol
;
LONG
internal
;
BSTR
client
;
VARIANT_BOOL
enabled
;
BSTR
descr
;
};
struct
xml_value_desc
{
const
WCHAR
*
name
;
BSTR
value
;
};
static
struct
{
LONG
refs
;
...
...
@@ -49,11 +66,32 @@ static struct
WCHAR
desc_urlpath
[
128
];
WCHAR
control_url
[
256
];
unsigned
int
version
;
struct
port_mapping
*
mappings
;
unsigned
int
mapping_count
;
}
upnp_gateway_connection
;
static
SRWLOCK
upnp_gateway_connection_lock
=
SRWLOCK_INIT
;
static
void
free_port_mapping
(
struct
port_mapping
*
mapping
)
{
SysFreeString
(
mapping
->
external_ip
);
SysFreeString
(
mapping
->
protocol
);
SysFreeString
(
mapping
->
client
);
SysFreeString
(
mapping
->
descr
);
}
static
void
free_mappings
(
void
)
{
unsigned
int
i
;
for
(
i
=
0
;
i
<
upnp_gateway_connection
.
mapping_count
;
++
i
)
free_port_mapping
(
&
upnp_gateway_connection
.
mappings
[
i
]
);
free
(
upnp_gateway_connection
.
mappings
);
upnp_gateway_connection
.
mappings
=
NULL
;
upnp_gateway_connection
.
mapping_count
=
0
;
}
static
BOOL
parse_search_response
(
char
*
response
,
WCHAR
*
locationW
,
unsigned
int
location_size
)
{
char
*
saveptr
=
NULL
,
*
tok
,
*
tok2
;
...
...
@@ -171,6 +209,64 @@ done:
return
ret
;
}
static
BOOL
get_xml_elements
(
const
char
*
desc_xml
,
struct
xml_value_desc
*
values
,
unsigned
int
value_count
)
{
XmlNodeType
node_type
;
IXmlReader
*
reader
;
const
WCHAR
*
value
;
BOOL
ret
=
FALSE
;
IStream
*
stream
;
unsigned
int
i
;
HRESULT
hr
;
for
(
i
=
0
;
i
<
value_count
;
++
i
)
assert
(
!
values
[
i
].
value
);
if
(
!
(
stream
=
SHCreateMemStream
(
(
BYTE
*
)
desc_xml
,
strlen
(
desc_xml
)
+
1
)))
return
FALSE
;
if
(
FAILED
(
hr
=
CreateXmlReader
(
&
IID_IXmlReader
,
(
void
**
)
&
reader
,
NULL
)))
{
IStream_Release
(
stream
);
return
FALSE
;
}
if
(
FAILED
(
hr
=
IXmlReader_SetInput
(
reader
,
(
IUnknown
*
)
stream
)))
goto
done
;
while
(
SUCCEEDED
(
IXmlReader_Read
(
reader
,
&
node_type
))
&&
node_type
!=
XmlNodeType_None
)
{
if
(
node_type
!=
XmlNodeType_Element
)
continue
;
if
(
FAILED
(
IXmlReader_GetQualifiedName
(
reader
,
&
value
,
NULL
)))
goto
done
;
for
(
i
=
0
;
i
<
value_count
;
++
i
)
if
(
!
wcsicmp
(
value
,
values
[
i
].
name
))
break
;
if
(
i
==
value_count
)
continue
;
if
(
FAILED
(
IXmlReader_Read
(
reader
,
&
node_type
)))
goto
done
;
if
(
node_type
!=
XmlNodeType_Text
)
{
if
(
node_type
==
XmlNodeType_EndElement
)
value
=
L""
;
else
goto
done
;
}
if
(
FAILED
(
IXmlReader_GetValue
(
reader
,
&
value
,
NULL
)))
goto
done
;
if
(
values
[
i
].
value
)
{
WARN
(
"Duplicate value %s.
\n
"
,
debugstr_w
(
values
[
i
].
name
)
);
goto
done
;
}
if
(
!
(
values
[
i
].
value
=
SysAllocString
(
value
)))
goto
done
;
}
ret
=
TRUE
;
done:
if
(
!
ret
)
{
for
(
i
=
0
;
i
<
value_count
;
++
i
)
{
SysFreeString
(
values
[
i
].
value
);
values
[
i
].
value
=
NULL
;
}
}
IXmlReader_Release
(
reader
);
IStream_Release
(
stream
);
return
ret
;
}
static
BOOL
open_gateway_connection
(
void
)
{
static
const
int
timeout
=
3000
;
...
...
@@ -270,12 +366,220 @@ static BOOL get_control_url(void)
static
void
gateway_connection_cleanup
(
void
)
{
TRACE
(
".
\n
"
);
free_mappings
();
WinHttpCloseHandle
(
upnp_gateway_connection
.
connection
);
WinHttpCloseHandle
(
upnp_gateway_connection
.
session
);
if
(
upnp_gateway_connection
.
winsock_initialized
)
WSACleanup
();
memset
(
&
upnp_gateway_connection
,
0
,
sizeof
(
upnp_gateway_connection
)
);
}
static
BOOL
request_service
(
const
WCHAR
*
function
,
const
struct
xml_value_desc
*
request_param
,
unsigned
int
request_param_count
,
struct
xml_value_desc
*
result
,
unsigned
int
result_count
,
DWORD
*
http_status
,
BSTR
*
server_error_code_str
)
{
static
const
char
request_template_header
[]
=
"<?xml version=
\"
1.0
\"
?>
\r\n
"
"<SOAP-ENV:Envelope xmlns:SOAP-ENV=
\"
http://schemas.xmlsoap.org/soap/envelope/
\"
"
"SOAP-ENV:encodingStyle=
\"
http://schemas.xmlsoap.org/soap/encoding/
\"
>
\r\n
"
" <SOAP-ENV:Body>
\r\n
"
" <m:%S xmlns:m=
\"
urn:schemas-upnp-org:service:WANIPConnection:%u
\"
>
\r\n
"
;
static
const
char
request_template_footer
[]
=
" </m:%S>
\r\n
"
" </SOAP-ENV:Body>
\r\n
"
"</SOAP-ENV:Envelope>
\r\n
"
;
unsigned
int
request_data_size
,
request_len
,
offset
,
i
,
reply_buffer_size
;
char
*
request_data
,
*
reply_buffer
=
NULL
,
*
ptr
;
struct
xml_value_desc
error_value_desc
;
WCHAR
request_headers
[
1024
];
HINTERNET
request
=
NULL
;
BOOL
ret
=
FALSE
;
DWORD
size
;
*
server_error_code_str
=
NULL
;
request_data_size
=
strlen
(
request_template_header
)
+
strlen
(
request_template_footer
)
+
2
*
wcslen
(
function
)
+
9
/* version + zero terminator */
;
for
(
i
=
0
;
i
<
request_param_count
;
++
i
)
{
request_data_size
+=
13
+
2
*
wcslen
(
request_param
[
i
].
name
)
+
wcslen
(
request_param
[
i
].
value
);
}
if
(
!
(
request_data
=
malloc
(
request_data_size
)))
return
FALSE
;
request
=
WinHttpOpenRequest
(
upnp_gateway_connection
.
connection
,
L"POST"
,
upnp_gateway_connection
.
control_url
,
NULL
,
WINHTTP_NO_REFERER
,
WINHTTP_DEFAULT_ACCEPT_TYPES
,
0
);
if
(
!
request
)
goto
done
;
ptr
=
request_data
;
snprintf
(
ptr
,
request_data_size
,
request_template_header
,
function
,
upnp_gateway_connection
.
version
);
offset
=
strlen
(
ptr
);
ptr
+=
offset
;
request_data_size
-=
offset
;
for
(
i
=
0
;
i
<
request_param_count
;
++
i
)
{
snprintf
(
ptr
,
request_data_size
,
" <%S>%S</%S>
\r\n
"
,
request_param
[
i
].
name
,
request_param
[
i
].
value
,
request_param
[
i
].
name
);
offset
=
strlen
(
ptr
);
ptr
+=
offset
;
request_data_size
-=
offset
;
}
snprintf
(
ptr
,
request_data_size
,
request_template_footer
,
function
);
request_len
=
strlen
(
request_data
);
swprintf
(
request_headers
,
ARRAY_SIZE
(
request_headers
),
L"SOAPAction:
\"
urn:schemas-upnp-org:service:WANIPConnection:%u#%s
\"\r\n
"
L"Content-Type: text/xml"
,
upnp_gateway_connection
.
version
,
function
);
if
(
!
WinHttpSendRequest
(
request
,
request_headers
,
-
1
,
request_data
,
request_len
,
request_len
,
0
))
{
WARN
(
"Error sending request %u.
\n
"
,
GetLastError
()
);
goto
done
;
}
if
(
!
WinHttpReceiveResponse
(
request
,
NULL
))
{
WARN
(
"Error receiving response %u.
\n
"
,
GetLastError
()
);
goto
done
;
}
size
=
sizeof
(
*
http_status
);
if
(
!
WinHttpQueryHeaders
(
request
,
WINHTTP_QUERY_STATUS_CODE
|
WINHTTP_QUERY_FLAG_NUMBER
,
NULL
,
http_status
,
&
size
,
NULL
)
||
*
http_status
!=
HTTP_STATUS_OK
)
{
if
(
*
http_status
!=
HTTP_STATUS_SERVER_ERROR
)
{
ret
=
TRUE
;
goto
done
;
}
}
offset
=
0
;
reply_buffer_size
=
1024
;
if
(
!
(
reply_buffer
=
malloc
(
reply_buffer_size
)))
goto
done
;
while
((
ret
=
WinHttpReadData
(
request
,
reply_buffer
+
offset
,
reply_buffer_size
-
offset
-
1
,
&
size
))
&&
size
)
{
offset
+=
size
;
if
(
offset
+
1
==
reply_buffer_size
)
{
char
*
new
;
reply_buffer_size
*=
2
;
if
(
!
(
new
=
realloc
(
reply_buffer
,
reply_buffer_size
)))
goto
done
;
reply_buffer
=
new
;
}
}
reply_buffer
[
offset
]
=
0
;
if
(
*
http_status
==
HTTP_STATUS_OK
)
ret
=
get_xml_elements
(
reply_buffer
,
result
,
result_count
);
else
{
error_value_desc
.
name
=
L"errorCode"
;
error_value_desc
.
value
=
NULL
;
if
((
ret
=
get_xml_elements
(
reply_buffer
,
&
error_value_desc
,
1
)))
*
server_error_code_str
=
error_value_desc
.
value
;
}
done:
free
(
reply_buffer
);
free
(
request_data
);
WinHttpCloseHandle
(
request
);
return
ret
;
}
enum
port_mapping_parameter
{
PM_EXTERNAL_IP
,
PM_EXTERNAL
,
PM_PROTOCOL
,
PM_INTERNAL
,
PM_CLIENT
,
PM_ENABLED
,
PM_DESC
,
PM_LEASE_DURATION
,
PM_LAST
};
static
struct
xml_value_desc
port_mapping_template
[]
=
{
{
L"NewRemoteHost"
},
{
L"NewExternalPort"
},
{
L"NewProtocol"
},
{
L"NewInternalPort"
},
{
L"NewInternalClient"
},
{
L"NewEnabled"
},
{
L"NewPortMappingDescription"
},
{
L"NewLeaseDuration"
},
};
static
LONG
long_from_bstr
(
BSTR
s
)
{
if
(
!
s
)
return
0
;
return
_wtoi
(
s
);
}
static
void
update_mapping_list
(
void
)
{
struct
xml_value_desc
mapping_desc
[
ARRAY_SIZE
(
port_mapping_template
)];
struct
xml_value_desc
index_param
;
struct
port_mapping
*
new_mappings
;
unsigned
int
i
,
index
;
WCHAR
index_str
[
9
];
BSTR
error_str
;
DWORD
status
;
BOOL
ret
;
free_mappings
();
index_param
.
name
=
L"NewPortMappingIndex"
;
index
=
0
;
while
(
1
)
{
new_mappings
=
realloc
(
upnp_gateway_connection
.
mappings
,
(
index
+
1
)
*
sizeof
(
*
new_mappings
)
);
if
(
!
new_mappings
)
break
;
upnp_gateway_connection
.
mappings
=
new_mappings
;
memcpy
(
mapping_desc
,
port_mapping_template
,
sizeof
(
mapping_desc
)
);
swprintf
(
index_str
,
ARRAY_SIZE
(
index_str
),
L"%u"
,
index
);
index_param
.
value
=
SysAllocString
(
index_str
);
ret
=
request_service
(
L"GetGenericPortMappingEntry"
,
&
index_param
,
1
,
mapping_desc
,
ARRAY_SIZE
(
mapping_desc
),
&
status
,
&
error_str
);
SysFreeString
(
index_param
.
value
);
if
(
!
ret
)
break
;
if
(
status
!=
HTTP_STATUS_OK
)
{
if
(
error_str
)
{
if
(
long_from_bstr
(
error_str
)
!=
713
)
WARN
(
"Server returned error %s.
\n
"
,
debugstr_w
(
error_str
)
);
SysFreeString
(
error_str
);
}
break
;
}
new_mappings
[
index
].
external_ip
=
mapping_desc
[
PM_EXTERNAL_IP
].
value
;
mapping_desc
[
PM_EXTERNAL_IP
].
value
=
NULL
;
new_mappings
[
index
].
external
=
long_from_bstr
(
mapping_desc
[
PM_EXTERNAL
].
value
);
new_mappings
[
index
].
protocol
=
mapping_desc
[
PM_PROTOCOL
].
value
;
mapping_desc
[
PM_PROTOCOL
].
value
=
NULL
;
new_mappings
[
index
].
internal
=
long_from_bstr
(
mapping_desc
[
PM_INTERNAL
].
value
);
new_mappings
[
index
].
client
=
mapping_desc
[
PM_CLIENT
].
value
;
mapping_desc
[
PM_CLIENT
].
value
=
NULL
;
if
(
!
wcsicmp
(
mapping_desc
[
PM_ENABLED
].
value
,
L"true"
)
||
long_from_bstr
(
mapping_desc
[
PM_ENABLED
].
value
))
new_mappings
[
index
].
enabled
=
VARIANT_TRUE
;
else
new_mappings
[
index
].
enabled
=
VARIANT_FALSE
;
new_mappings
[
index
].
descr
=
mapping_desc
[
PM_DESC
].
value
;
mapping_desc
[
PM_DESC
].
value
=
NULL
;
TRACE
(
"%s %s %s:%u -> %s:%u, enabled %d.
\n
"
,
debugstr_w
(
new_mappings
[
index
].
descr
),
debugstr_w
(
new_mappings
[
index
].
protocol
),
debugstr_w
(
new_mappings
[
index
].
external_ip
),
new_mappings
[
index
].
external
,
debugstr_w
(
new_mappings
[
index
].
client
),
new_mappings
[
index
].
internal
,
new_mappings
[
index
].
enabled
);
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
mapping_desc
);
++
i
)
SysFreeString
(
mapping_desc
[
i
].
value
);
upnp_gateway_connection
.
mappings
=
new_mappings
;
upnp_gateway_connection
.
mapping_count
=
++
index
;
}
}
static
BOOL
init_gateway_connection
(
void
)
{
static
const
char
upnp_search_request
[]
=
...
...
@@ -363,6 +667,8 @@ static BOOL init_gateway_connection(void)
}
TRACE
(
"control_url %s, version %u.
\n
"
,
debugstr_w
(
upnp_gateway_connection
.
control_url
),
upnp_gateway_connection
.
version
);
update_mapping_list
();
return
TRUE
;
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment