|
|
楼主 |
发表于 2011-7-15 17:28:52
|
显示全部楼层
以下有关upnp的接口来自emule,) g! F! r, [/ h! W% ~
1 Q; n( ]/ S. W. I, O6 v( \% ~1 r) _1 x$ Z- O; X. g* [5 d
///////////////////////////////////////////; D; r* x8 l8 {/ w
//upnp的抽象接口类,只需调用这些接口即可实现端口映射功能.
: ?& X% b% Q! k* S4 r* W; L& h+ v% H6 b3 q6 ^2 @: ^$ Q
8 l# i- D5 P8 W* H- N( C9 W
#pragma once3 g( c) G* `8 P! R& f
#include <exception>
/ z0 M8 n( M5 A( d V
0 I0 d. r* L# V0 |8 J6 G; D6 n; V4 F( a
enum TRISTATE{
. X1 x2 A& S' V( y9 b2 ^ TRIS_FALSE,+ h! Q" e: f* n+ B: A; t
TRIS_UNKNOWN,; Z2 H4 q: }( d2 k# j! z* M
TRIS_TRUE; U( Y8 n N B
};
0 G, j' j3 W5 `! `9 h
" c2 }) H% \9 ~ c8 c/ q
) i& a4 C3 f" u; S* benum UPNP_IMPLEMENTATION{
; Q5 r- \8 X6 ]5 d% Y; T$ i& r UPNP_IMPL_WINDOWSERVICE = 0,
3 a, Q/ p. a6 a, ~$ ] UPNP_IMPL_MINIUPNPLIB,
) P: _( z8 g( E$ j8 m0 C, c UPNP_IMPL_NONE /*last*/
9 }3 g& Y( l' e$ G};1 [+ t; T' S5 `7 d3 F
F3 {, h) Y: T3 |/ S1 Q
6 ?; f( g/ G9 s4 |' ~) v6 \# u3 h& e$ \) K8 l, C) d0 B/ X7 u8 z8 a
- C, g2 B& t6 _) F& S/ Tclass CUPnPImpl
# v( [$ \4 l) {2 n{8 P, c# H9 w& @0 v) r* s2 ]
public:' B- z( a& Q2 d
CUPnPImpl();; B9 J0 A* c' Z5 E
virtual ~CUPnPImpl();" ]* f5 I) g* ~; \ ^! ? J7 D
struct UPnPError : std::exception {};6 H- z6 D. C2 n% G# x4 O
enum {$ m( N1 ~7 c. y9 K" M" L$ Z- ?. G
UPNP_OK,! o' @+ r2 s8 [8 q7 R4 Q( Y
UPNP_FAILED,
6 l2 [" m+ L0 X2 V; x8 H UPNP_TIMEOUT
7 G8 V* g8 m; K" u/ x };$ m: Z6 {; L" B2 [
1 ~% Y# i, V4 j9 x3 T) |" {" v
- V' Q$ n( j A$ G virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) = 0;
2 r! }3 ]5 f+ `8 K8 v/ S virtual bool CheckAndRefresh() = 0;
& e/ N4 a' K* C! _" `, Z virtual void StopAsyncFind() = 0;" I. y$ ~* Y; c9 N1 {
virtual void DeletePorts() = 0;4 _: }* H. d ?1 t Z5 F* P
virtual bool IsReady() = 0;& G5 G1 K. @2 o1 |, Y
virtual int GetImplementationID() = 0;
% I/ K3 V4 j+ G, O: u8 ~7 P9 m; W 0 E& |$ C3 k" F1 N0 s. H
void LateEnableWebServerPort(uint16 nPort); // Add Webserverport on already installed portmapping9 a1 U. ?! D: V4 X. Z
! a! s" c- O: {% V5 ?$ e' S2 }5 H0 T' T h$ L
void SetMessageOnResult(HWND hWindow, UINT nMessageID);
. B* t" h2 ?. H/ v. @ TRISTATE ArePortsForwarded() const { return m_bUPnPPortsForwarded; }
* D1 s) V- c9 P3 g9 @; I uint16 GetUsedTCPPort() { return m_nTCPPort; }
9 O" C( W2 x9 c* ~6 h8 b' f) H uint16 GetUsedUDPPort() { return m_nUDPPort; }
# R* f7 q' _. Y# M( \+ s5 ]
! d8 S; T7 r2 ^8 }( O$ H6 j7 r5 D# M7 e
// Implementation
9 d0 G1 F0 b( o( K: {8 w/ d6 aprotected:
7 P6 l+ v0 k* Z volatile TRISTATE m_bUPnPPortsForwarded;2 m' y3 k8 w, ]% t
void SendResultMessage();
2 V7 @. t: w% d( {3 W' I# g+ X/ V uint16 m_nUDPPort;% e' t& F4 s; _& m6 G8 }
uint16 m_nTCPPort;! I. W; M2 n: a
uint16 m_nTCPWebPort;
! `: l) O$ [; n$ \ bool m_bCheckAndRefresh;: _ U3 `+ Q" n. ~4 n, b( i5 e
( `4 }7 ]5 c5 L. M* J; r
- D, j. L& q1 `7 Oprivate:
# R' d- G' _: a- T6 k HWND m_hResultMessageWindow;
; G* N( b8 e% H: v% r/ m- x0 b UINT m_nResultMessageID;/ z9 e* {6 j( p0 Y
1 Y* B4 Y1 X' _. i4 v {
8 r# r0 p9 d, y! C9 B& _; ]' p
};
5 B9 S j2 j. E/ v7 k% n& x" e
( o% Z' @& U- P$ H! r# T
. ]- n2 I c4 \ P; o: n2 ~5 j// Dummy Implementation to be used when no other implementation is available
' ?! x) F4 c& t" s/ Y* Jclass CUPnPImplNone: public CUPnPImpl
4 A( w, M, g+ Q) S* k3 g{
* X+ J. z" M9 y/ y# G& ^public:
4 T: ^ \" x! O' S R8 h2 s virtual void StartDiscovery(uint16, uint16, uint16) { ASSERT( false ); }% U% B! ]3 T' m- [
virtual bool CheckAndRefresh() { return false; }
; o' C, ^6 g- F2 r8 m9 _0 X- ` virtual void StopAsyncFind() { }% E9 o! p* i$ r
virtual void DeletePorts() { }
: N! E" b% @' q0 j' O6 W* A virtual bool IsReady() { return false; }3 K5 M5 Z8 K. K( o0 W' D4 l+ E' D
virtual int GetImplementationID() { return UPNP_IMPL_NONE; }7 a$ b0 I: D' q- C/ y. M
};7 ~- n" h8 t4 j6 }/ r& |. z+ q
$ @+ d, P# F. R; J4 E9 M k5 c4 r* b) x6 ^# {
/////////////////////////////////////
* E$ q% |( N) Q! i# U7 b//下面是使用windows操作系统自带的UPNP功能的子类" I7 g' ^3 V# L! e- A4 ]# d' S' M
3 E! v; U; r+ p4 [
+ ?; G$ l- B8 ~# l2 v, m' u! t
#pragma once
" l8 S& }- I1 c* `% |#pragma warning( disable: 4355 )
, S9 S7 @: t/ Z7 J* Z" k4 g+ z- R2 V8 A7 I0 X$ W1 I+ O" h- X
8 p, t) [; j3 G% @, A#include "UPnPImpl.h"
, E. J8 O) n* E k#include <upnp.h>& n8 U' Q* h+ P$ W& C
#include <iphlpapi.h> X& J2 M- P, V8 @/ h! X
#include <comdef.h>
2 q7 z! g8 e% }7 a#include <winsvc.h>/ l5 _/ ]5 T6 e! i
# s& S2 G0 c4 N" g/ U( W: J
$ r# B: S _+ d: `/ c
#include <vector>2 N- U! { F9 h% `1 {- m# V
#include <exception>
# Q* Q* T. a" G' c; N1 |#include <functional>* U& m5 w2 x- ?8 `9 G x: W
; {* S, }1 R6 F, g* }" T
3 v, c+ o+ J M; l
; ^1 y$ y% F) D- B/ {( ]
$ C+ ^" w8 D) ~typedef _com_ptr_t<_com_IIID<IUPnPDeviceFinder,&IID_IUPnPDeviceFinder> > FinderPointer;
. w: n8 j" ?2 W4 Wtypedef _com_ptr_t<_com_IIID<IUPnPDevice,&IID_IUPnPDevice> > DevicePointer;
; i( j% J: ~5 l' n( K+ `4 Htypedef _com_ptr_t<_com_IIID<IUPnPService,&IID_IUPnPService> > ServicePointer;( w7 }) C- e) Z! u9 Z( ^& o0 [6 p5 }
typedef _com_ptr_t<_com_IIID<IUPnPDeviceFinderCallback,&IID_IUPnPDeviceFinderCallback> > DeviceFinderCallback;
$ r3 ~# a8 w: f' Ztypedef _com_ptr_t<_com_IIID<IUPnPServiceCallback,&IID_IUPnPServiceCallback> > ServiceCallback;$ O+ f: r: ^# _( h3 C8 e
typedef _com_ptr_t<_com_IIID<IEnumUnknown,&IID_IEnumUnknown> > EnumUnknownPtr;
4 X# G7 ]5 x4 C$ ~0 mtypedef _com_ptr_t<_com_IIID<IUnknown,&IID_IUnknown> > UnknownPtr;
: ` W! u2 w- x
" l2 |7 M7 v |) G& o( _2 c
+ M- }. ]: m$ X" Jtypedef DWORD (WINAPI* TGetBestInterface) (
j7 h& l% ?1 s- _8 P IPAddr dwDestAddr,# Z7 u0 M: [" ^) e$ X5 t
PDWORD pdwBestIfIndex% `9 Q+ b& T; Q* T8 v/ i6 p
);7 T& I. B. B' G1 d/ V4 `+ Q
) o$ r: R7 x" o0 G7 R& y6 {, J! K
" T" y1 _/ ^; U; ?, o( u$ Ytypedef DWORD (WINAPI* TGetIpAddrTable) (
; H) e+ ]( y4 o/ s: p PMIB_IPADDRTABLE pIpAddrTable,- i5 r3 z3 s, R. h% P* i* \
PULONG pdwSize,7 Q( [4 {4 o: U
BOOL bOrder
0 h' j8 O9 Z% l4 X) X);
; V) f5 E3 J& @) p9 d" a& I4 F5 l+ K+ n
* ~: t" l- S7 u6 `/ x' i, atypedef DWORD (WINAPI* TGetIfEntry) (
+ A H5 o; O5 F' l$ @ PMIB_IFROW pIfRow
" S$ k7 y" {# j$ v6 E" s0 h) T, n);
- G4 h; p8 l' m" e% ~" f
; o4 n' l/ B8 H1 h6 U' S& j
# E8 A3 c, K* e T7 ^- _0 o eCString translateUPnPResult(HRESULT hr);4 L# S) j' e. G3 x
HRESULT UPnPMessage(HRESULT hr);
3 j2 c; Y! i( }& z: R$ R
4 u! w, o! q# c$ c( V& ^4 D+ r% s# E7 b" \0 ]1 m
class CUPnPImplWinServ: public CUPnPImpl
& J% C$ N& ^, A) U( }+ j{, }" s* f9 D% H1 m
friend class CDeviceFinderCallback;
1 t5 @+ N k [/ s' l9 ~2 ^ friend class CServiceCallback;
. `0 S: P4 p8 B- \9 L3 ~5 j// Construction
) N9 e: `- O) E! V2 K: A& Bpublic:
/ B6 P* f. o/ H; Z5 D: Q1 S virtual ~CUPnPImplWinServ();
- E2 E: @' y8 q& a CUPnPImplWinServ();9 A4 M3 h8 R7 w
7 X3 X: A9 }& v$ |, C9 V$ _& Z0 c% I% |7 a& L5 H% V
virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) { StartDiscovery(nTCPPort, nUDPPort, nTCPWebPort, false); }6 b2 S6 F+ ~9 @; w* h( O+ [8 o s
virtual void StopAsyncFind();. F1 C8 L% p. y
virtual void DeletePorts();
8 N }# E3 `" H5 O6 l) n virtual bool IsReady();6 S- l' P+ Z: @3 F H* x
virtual int GetImplementationID() { return UPNP_IMPL_WINDOWSERVICE; }
6 q& o, |! G# ~; V3 ?; A( F5 v, ^! E3 e X8 \0 D
" a5 e2 U; m/ F
// No Support for Refreshing on this (fallback) implementation yet - in many cases where it would be needed (router reset etc): d \- T v- f! \$ T/ T
// the windows side of the implementation tends to get bugged untill reboot anyway. Still might get added later4 l4 M7 g* G: v, c
virtual bool CheckAndRefresh() { return false; };
_1 ^, y. L6 T, b2 ^4 z. Z
# ^5 @: F3 q8 ~" R# Z4 k. v- W
protected:
( s) X$ W" m8 A6 U% A+ k5 k2 C void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort, bool bSecondTry);- p8 s; j6 C n8 ?, M) h1 a( C
void AddDevice(DevicePointer pDevice, bool bAddChilds, int nLevel = 0);
) H$ {; F% B" i4 ^0 n/ g0 d/ d void RemoveDevice(CComBSTR bsUDN);& b% f3 R1 r" J) u4 j2 {
bool OnSearchComplete();
B& S2 a4 u3 Q, L1 W void Init();# E% ^" ]# E( V8 }
1 X; \5 N# f2 H# q0 w" }
/ K N, j. \" d: o% o) }2 P inline bool IsAsyncFindRunning()
C! f2 ~# Q2 V1 P2 m {
: W- Y9 N3 O7 l* ]* F if ( m_pDeviceFinder != NULL && m_bAsyncFindRunning && GetTickCount() - m_tLastEvent > 10000 ). M8 [3 N" f6 P6 T0 {! ^! K
{+ C. z5 x- ]; C& T9 G* D5 O4 N
m_pDeviceFinder->CancelAsyncFind( m_nAsyncFindHandle );
4 v- w0 ] d% L m_bAsyncFindRunning = false;6 {6 g& ~2 R! y5 `" e1 [6 T4 g3 W
}3 y( G, E4 O, P- _3 X4 _4 \9 Q0 s4 Q
MSG msg;6 J, n. J* z; a$ i& }' k
while ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
; {! c. R+ u$ o8 u) i {
% ?. F3 K3 V: d2 E% w( f TranslateMessage( &msg );
# w5 t0 |2 K# h; B _' w DispatchMessage( &msg );. s' q" I, p2 [" c. r$ R' B
}
$ ^; X; W! u3 f: S* j: x6 U3 _ return m_bAsyncFindRunning;. l& E2 Q( V# l; I
}2 L t6 c: |6 O) @) b0 O2 k( |
) Y, x# ~( a+ g+ B: G! i. K9 \/ a6 J+ ~+ y! x( \0 |; [0 h0 k
TRISTATE m_bUPnPDeviceConnected;* n# c7 e" ]. g
R$ e1 o& _8 J$ `! {
; A; C( u0 T! E% s' d// Implementation
! j) g) S' \: ?1 A, I3 x. W // API functions
- w# |; y' k' Y0 T$ v SC_HANDLE (WINAPI *m_pfnOpenSCManager)(LPCTSTR, LPCTSTR, DWORD);
, e: S+ z: S9 _6 }7 k SC_HANDLE (WINAPI *m_pfnOpenService)(SC_HANDLE, LPCTSTR, DWORD);, n+ s$ B5 s, J& ]; o4 K8 T
BOOL (WINAPI *m_pfnQueryServiceStatusEx)(SC_HANDLE, SC_STATUS_TYPE, LPBYTE, DWORD, LPDWORD);
3 R( W6 S* ?$ `0 Q* I BOOL (WINAPI *m_pfnCloseServiceHandle)(SC_HANDLE);# A/ \4 b2 `- _9 d- H# W+ l
BOOL (WINAPI *m_pfnStartService)(SC_HANDLE, DWORD, LPCTSTR*);1 `9 A" z0 u Z9 x) s6 E3 b
BOOL (WINAPI *m_pfnControlService)(SC_HANDLE, DWORD, LPSERVICE_STATUS);" d9 ?+ X b7 M1 v, l/ z5 w5 @, a# `
9 V0 D% ]5 D$ k3 O& ?$ U! E. g/ Q+ n P9 p3 R w9 r
TGetBestInterface m_pfGetBestInterface;
2 A# v! K! [* P! I# u' `* S" L1 I1 G TGetIpAddrTable m_pfGetIpAddrTable;( i' O0 q. F L( i
TGetIfEntry m_pfGetIfEntry;
) W- d; ~. I: @$ E$ i+ h. H8 E& m
( t) e: [- |" k9 A: |) t: }4 i& D
) p- M' L& J& N; r! g7 J {3 i static FinderPointer CreateFinderInstance(); k" K8 S2 Y$ n- a
struct FindDevice : std::unary_function< DevicePointer, bool > @. W& J$ k6 s& J, T4 |2 E) g
{
) I0 u$ Z5 p0 M/ \8 a FindDevice(const CComBSTR& udn) : m_udn( udn ) {}
' t O N) ?' Q/ } J+ Q result_type operator()(argument_type device) const8 @2 x) k! J0 b% P9 O! r; H
{
' i% p% O8 f/ B' F% ?% i( n CComBSTR deviceName;* r+ b/ C; z0 K* J% P
HRESULT hr = device->get_UniqueDeviceName( &deviceName );
, Z5 L" e. ~7 H5 B. ?" s: |: ^! {" c) L3 b, F+ l2 P4 t5 Z3 p" `
$ @) z: a& \! S' r
if ( FAILED( hr ) )2 g5 c$ n7 [/ d9 ]7 M. E
return UPnPMessage( hr ), false; H& r. X7 ^* h1 U: ~2 n# ~
* H5 U$ N' Z \9 E9 W, B
* f8 `. T9 l6 C2 T, r5 E return wcscmp( deviceName.m_str, m_udn ) == 0;
+ {2 d! u: {, n }: Z" Y) A% C* R) w/ }
CComBSTR m_udn;
1 j- U/ f7 Z+ A; W5 D };& V6 j) y* E# a' \( F! b
8 A0 t/ `8 k0 Z% [2 M4 n void ProcessAsyncFind(CComBSTR bsSearchType);
: O" t! a+ l, T6 N HRESULT GetDeviceServices(DevicePointer pDevice);
' _5 E$ E3 w% \' A- l void StartPortMapping();
7 q$ J- I9 i+ n% e' Z. _6 W3 W HRESULT MapPort(const ServicePointer& service);( L0 D V( s4 W( E% K; v
void DeleteExistingPortMappings(ServicePointer pService);$ R9 r9 E2 V9 V; E
void CreatePortMappings(ServicePointer pService);, w9 B5 C* V& S& A% S
HRESULT SaveServices(EnumUnknownPtr pEU, const LONG nTotalItems);
, W% ]6 R; V( S* x HRESULT InvokeAction(ServicePointer pService, CComBSTR action,
3 q# l6 G* O/ P- o4 _% ~2 D# f( P LPCTSTR pszInArgString, CString& strResult);6 `* M* G) W( X1 F: _
void StopUPnPService();
* V( ], }6 u* C, g
( ?" ?( A p/ W. [; V& ]" B
' i; L, N2 p. R // Utility functions- U4 Q* ^$ M" h0 b$ E0 k
HRESULT CreateSafeArray(const VARTYPE vt, const ULONG nArgs, SAFEARRAY** ppsa);
8 A) O' O) l) i8 ^4 J INT_PTR CreateVarFromString(const CString& strArgs, VARIANT*** pppVars);8 ?: w" H& b$ @# O( S
INT_PTR GetStringFromOutArgs(const VARIANT* pvaOutArgs, CString& strArgs);1 j5 H3 b$ _" V
void DestroyVars(const INT_PTR nCount, VARIANT*** pppVars);8 {, X# z2 t+ ^
HRESULT GetSafeArrayBounds(SAFEARRAY* psa, LONG* pLBound, LONG* pUBound);" r' G7 Q' Z4 ?5 d/ Q+ ^
HRESULT GetVariantElement(SAFEARRAY* psa, LONG pos, VARIANT* pvar);
: o- T9 X* e1 q6 i( t E CString GetLocalRoutableIP(ServicePointer pService);
. f# b3 ]9 [1 l- E2 _" z/ U
! t2 l0 E/ c9 Q: i' A. R. E& r
( o' b. _' N5 R! _( k: Z// Private members9 y% m: G6 e5 p
private:& j. G2 z7 S6 B. x/ d5 n
DWORD m_tLastEvent; // When the last event was received?6 K2 q8 z, H2 c$ c7 V# z6 G
std::vector< DevicePointer > m_pDevices;
2 {% g# r! @; u {$ m8 S' T4 S std::vector< ServicePointer > m_pServices;& R' K' q6 T5 V
FinderPointer m_pDeviceFinder;
8 N3 X0 ^& b4 z! E, S0 g DeviceFinderCallback m_pDeviceFinderCallback;1 y: g2 c. G) W _" m% {
ServiceCallback m_pServiceCallback;
w& \# {% i- ~) W3 y: M2 l/ V$ f8 x1 a
, e: P0 ]8 J8 U LONG m_nAsyncFindHandle;6 {$ E5 K6 T" g. P6 \
bool m_bCOM;
P6 E2 U+ A9 O bool m_bPortIsFree;# C9 X0 _* v& X+ V% g4 e/ E! y
CString m_sLocalIP;
* H, z$ ?+ v$ Y5 U6 f y! W CString m_sExternalIP; k# J$ `0 z2 r
bool m_bADSL; // Is the device ADSL?7 G4 g5 b' o, {; P8 P4 S3 |* @
bool m_ADSLFailed; // Did port mapping failed for the ADSL device?
8 H5 R# j b$ ?6 Z bool m_bInited;
1 D5 u3 l6 e1 p, \! H; E3 ?6 | bool m_bAsyncFindRunning;3 C4 \4 S, _5 m
HMODULE m_hADVAPI32_DLL;& k3 }+ f2 l+ n2 \7 F7 b
HMODULE m_hIPHLPAPI_DLL;
0 x% r+ A1 x( H- ]$ t! `& j bool m_bSecondTry;5 _0 ?4 \) {5 v, n* G
bool m_bServiceStartedByEmule;
1 ` l0 D. P/ a% v0 ?( p# L bool m_bDisableWANIPSetup;5 Q5 D5 I& o2 v7 R |' d
bool m_bDisableWANPPPSetup;
# F% K) h& I/ {
3 i) K9 I* K. ~8 K2 j8 l' r: u9 R) P8 z x
};
; u7 C9 n* r0 p: F2 B L& b5 _ x5 ~ t! k
: _1 t2 ]( X. |5 \
// DeviceFinder Callback I. c4 A% h6 m" K0 i5 D* M6 W
class CDeviceFinderCallback
- F4 ~9 r6 {( H( n- g : public IUPnPDeviceFinderCallback
! q+ @: w/ K$ Y{
3 G4 X, @! f3 Qpublic:
1 B/ s+ t2 h' G. K" N9 O/ j CDeviceFinderCallback(CUPnPImplWinServ& instance)' O1 G! q' \2 V' b9 X
: m_instance( instance )
# D, E6 i0 \% K9 E* A { m_lRefCount = 0; }
$ H) q( `5 g' | F0 u2 P0 w# N$ r }. w& G
1 }& e, q2 p/ i! A: V
STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);; s/ r' x) O a
STDMETHODIMP_(ULONG) AddRef();7 z+ I$ Q# j/ d0 @! B- g
STDMETHODIMP_(ULONG) Release();
# o! i, h) {3 b! {' i8 ?" Z/ I+ ?
3 D/ B4 k' B% u2 a) n6 R// implementation7 E0 J& N! _0 T* j7 S6 l2 h
private:
0 m/ ]9 W: r G/ K6 _ HRESULT __stdcall DeviceAdded(LONG nFindData, IUPnPDevice* pDevice);
( ~- a. V% k! p2 C* X4 w HRESULT __stdcall DeviceRemoved(LONG nFindData, BSTR bsUDN);
4 o! v! ~. O! u HRESULT __stdcall SearchComplete(LONG nFindData);
, y7 s+ Q4 {/ X8 ]* f% ~- @* }* c7 C7 B8 b
5 I |" T+ Z0 q; V3 e/ c/ q) y
private:: Y. @* V7 B2 V9 z, G
CUPnPImplWinServ& m_instance;
5 q( G6 _$ H* O0 B; L LONG m_lRefCount;$ V4 I/ Q9 S/ b) v7 A& T$ r
};) E" E( n) @' C- C T) i& y
; p A0 d8 O) H/ {1 `) p) w! q) r% L
// Service Callback / _) K3 A) |0 q: i( [6 U- Y. [
class CServiceCallback
1 {$ c, ?" r1 s; [# F$ _$ ` : public IUPnPServiceCallback
3 ^; h; {. _) c* n; u{$ t$ Q7 S; e# j0 z% k+ \- Z. c7 B
public:! ~( q& {. t5 h; Z
CServiceCallback(CUPnPImplWinServ& instance)! c4 x. x. p! C
: m_instance( instance )
: q& m4 ?9 F. v# s* }, P { m_lRefCount = 0; }
/ q% J0 d/ E" B& q. [
- R; `5 [. `8 ~ h4 m6 d, o7 d0 I% T STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);% K) n: j0 R1 k% X: L
STDMETHODIMP_(ULONG) AddRef();
- w. u8 d" j/ ]; E5 |% W2 O STDMETHODIMP_(ULONG) Release();
; o" J7 B" c+ a3 A/ x
% I0 i$ r& d! H5 K0 f9 E+ k8 R0 h% R; o, m
// implementation% k3 g/ | j! \0 c9 O9 ~: F
private:
+ Q8 ?6 i1 e1 Z- I8 \8 l7 e$ J HRESULT __stdcall StateVariableChanged(IUPnPService* pService, LPCWSTR pszStateVarName, VARIANT varValue);' B: h _3 n( E. {9 H( P
HRESULT __stdcall ServiceInstanceDied(IUPnPService* pService);
5 C. W* g- N0 x1 R% {8 N! ]0 }- X$ h
/ J+ J8 |* {, o% i7 I9 r( n* d9 m, f. K2 O; z! Z
private:+ ?- H- g- ^) n6 o
CUPnPImplWinServ& m_instance;
+ @) S" l) f# l2 Z' `1 | LONG m_lRefCount;" l0 B: c' V0 L, ?( B8 w* s
};
- f0 Z$ x4 W$ K$ f% V% {" r6 ]" t( T6 Q- u! ]
6 _# d) [2 A5 U4 W/////////////////////////////////////////////////
, u! s3 N6 f5 u) N+ {. \) F+ q( y+ o5 W* H3 w" y4 T- w
+ n6 z0 M5 ?# b# |; F
使用时只需要使用抽象类的接口。
. r, u+ M: w+ f3 \CUPnPImpl::SetMessageOnResult设置需要接受UPNP端口映射是否成功的窗口句柄和消息ID.
& d6 J" J, i2 ]CUPnPImpl::StartDiscovery将开启一个异步设备查找并进行端口映射,其参数为需要映射的内网端口., {% ?- w/ s. Q) d) u- P& P# [
CUPnPImpl::StopAsyncFind停止设备查找.) V: E/ L2 {, ]% w# A* Y, k4 N; c
CUPnPImpl::DeletePorts删除端口映射. |
|