|
楼主 |
发表于 2011-7-15 17:28:52
|
显示全部楼层
以下有关upnp的接口来自emule,
! q) _. x( |: Q E3 v! C7 \
+ P1 C3 m: e2 ?. x8 F) O7 U
7 N, U6 j' G0 F///////////////////////////////////////////2 z& G. M Q# _( w# q9 t+ E
//upnp的抽象接口类,只需调用这些接口即可实现端口映射功能.. a, B, t4 p! [
5 l! M& Z, N" i! R5 }; f; Y4 e0 [3 P
#pragma once
9 \- Y, g2 {9 p1 V#include <exception>) {' c$ t+ T, u3 D: D6 K$ G( g
1 y2 o( y+ p1 @- M: o; T3 Z! f
/ i& @- L9 a' x! r$ m
enum TRISTATE{# b) ?3 U! v3 d; t' H, B
TRIS_FALSE,7 l/ b$ C% U3 A
TRIS_UNKNOWN,( T7 H' ^# }9 U \2 m
TRIS_TRUE
& ^, T0 H5 I$ @% a' P7 E9 }6 W, M! x};0 J3 \7 b- M1 B4 w4 s
4 ~& q2 B% e. S i- d6 J% [+ u) @, B% B/ y3 z
enum UPNP_IMPLEMENTATION{! ?6 r# }1 O1 i% w, {' Z
UPNP_IMPL_WINDOWSERVICE = 0,
( ~; K; o2 ]* e- P# Y UPNP_IMPL_MINIUPNPLIB,
1 j0 X# V. U# p3 D% K* k9 v4 b UPNP_IMPL_NONE /*last*/% w# Q+ G7 m/ R) j; S- X7 W% ~
};9 k7 K, Z; T! q, i! ~# K
) q9 h5 o, M' d$ V& n& ]4 |5 t- X/ k! w
" Y6 \( P( \0 p1 r2 G
6 y* a9 _2 g5 D |. K
class CUPnPImpl
+ c: P% {( i- n& M- O8 e0 X; W{( L8 T' ?2 P2 y, u5 I
public:
7 b' d% \) d) e$ y1 U5 | CUPnPImpl();- d, t, T8 T+ `5 Y" B T' O
virtual ~CUPnPImpl();
& ]1 I; C( p7 P* \9 G, ^: U struct UPnPError : std::exception {};0 I# p2 i7 M8 Y1 u5 Q* l
enum {* d) i9 a" R" w, u3 x- O" f
UPNP_OK,% Y! t- J( v7 j; g; `
UPNP_FAILED,
1 p7 s8 h' n0 V* ^6 G UPNP_TIMEOUT: t; n/ C" C0 _5 S. _2 z) [/ P0 q2 V: [/ F
};
" n: n- _! N% p3 J8 w6 J& Q- r1 o! }8 I$ T9 n p
+ u1 @8 a5 s7 i
virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) = 0;
$ q5 t) l# d$ ^, T. k virtual bool CheckAndRefresh() = 0;& y N6 V* @; y& s% x4 u
virtual void StopAsyncFind() = 0;, G- D8 K# ]( { e
virtual void DeletePorts() = 0;
, ]: M5 s$ H" s virtual bool IsReady() = 0;
% A: w0 o% @: L virtual int GetImplementationID() = 0;
+ x' z% P& p: p . N7 Y& X; Y8 a) u7 i* Z
void LateEnableWebServerPort(uint16 nPort); // Add Webserverport on already installed portmapping
# @5 c$ w6 J+ R, l7 b9 J+ ~/ K. O- u" E! _5 Y9 N1 j
% V& o7 u8 B8 V+ q# a! z
void SetMessageOnResult(HWND hWindow, UINT nMessageID); T2 N% k& c3 |* U
TRISTATE ArePortsForwarded() const { return m_bUPnPPortsForwarded; }
. H8 ?& J. A# G uint16 GetUsedTCPPort() { return m_nTCPPort; }
" P% ^. `8 S. J/ v0 v6 E uint16 GetUsedUDPPort() { return m_nUDPPort; } " l' o* {" |! F7 d: `7 ]
3 t5 G" q3 z, |
; j$ f) }8 n! l( |. M1 ^" b& l// Implementation, y! m5 b' s6 p9 s' l
protected:
8 x' T+ {2 ~3 a- i volatile TRISTATE m_bUPnPPortsForwarded;
[# ] ~' y/ }; o$ S, R- Y void SendResultMessage();
( |. @0 K5 `- t' ]! r) ^' `* T uint16 m_nUDPPort;% o3 e7 r0 h4 i9 r! s. |5 |5 m
uint16 m_nTCPPort;
& C$ C# ]& o$ [6 ^ uint16 m_nTCPWebPort;! C& C5 g$ A0 s Q- p
bool m_bCheckAndRefresh;& s; n2 Y" r9 z2 d) k' D/ u
' A( d# g2 A' s/ n1 Z* U2 \& B* M }! m# ` z
private:. _! V8 P a0 u' I" z
HWND m_hResultMessageWindow;$ h. V/ X0 U) z- |" a
UINT m_nResultMessageID;3 M& {$ ^7 ~% N Y3 x- `3 _
. t% @8 I) }& E: W8 @
b- E, ~* R0 R6 s! c
};
7 a/ [" k$ \- Q% L& z, d# g! b7 ]3 S: W: R
7 L9 q3 K6 j, Y" t) _// Dummy Implementation to be used when no other implementation is available: P: P% l* m1 q0 z# H
class CUPnPImplNone: public CUPnPImpl+ V( G# x1 w+ e. @6 ~2 i3 w
{
% e3 x7 w+ z) Vpublic:
4 @# ~' ^- {9 Q7 O$ S, o0 a virtual void StartDiscovery(uint16, uint16, uint16) { ASSERT( false ); }( A+ n7 l+ v& d( c: }/ ^1 S0 d
virtual bool CheckAndRefresh() { return false; }" l1 ~5 ?4 Z. i1 M
virtual void StopAsyncFind() { }, `' l: U- z& B
virtual void DeletePorts() { }
% Q: N% T! ?+ o! z* Z: L- D- v virtual bool IsReady() { return false; }
$ B3 }7 B& w+ E7 [/ [2 E virtual int GetImplementationID() { return UPNP_IMPL_NONE; }+ M; T0 h+ g7 [7 n5 @# b# w
};' K7 i" m: h: j" a- g$ x
7 v% l3 j( F: q7 y3 t1 f2 S' b5 x) S. s, l+ v1 b
/////////////////////////////////////
, n% e3 q# i3 b0 v8 e2 T9 k//下面是使用windows操作系统自带的UPNP功能的子类2 U, [2 r+ }, B6 x, I, t
) c+ D: \7 `( P! T. F4 H, Q
* X! h% h, ]# |4 d
#pragma once) ^' v8 Q4 p4 B- x3 @ i
#pragma warning( disable: 4355 )
- L& P" V) D$ A
# U$ u2 Q* s$ s1 R
2 |- Q6 a) K& K- d" G; u#include "UPnPImpl.h"
: O+ ?- ?/ _# d9 \6 u" b#include <upnp.h>$ r7 B) z9 a( A& m- k1 h6 Z# O% d
#include <iphlpapi.h>
2 j- ^% c1 c' m; y. |#include <comdef.h>$ p) ]0 X' Z9 P. J
#include <winsvc.h>/ g) y2 r' J l5 p) s0 m7 O2 c
+ q/ r9 c. x. x/ R& Z
2 e! o$ d6 A& W6 d7 k. k& _9 T! H# }0 f
#include <vector>8 y- C f' F5 ]& {, H( b+ c
#include <exception>2 a7 ]2 \: [$ U
#include <functional># V% q6 E: h/ M- @5 R
$ U1 a* h. d2 ?/ }5 `- M! X
/ X( M' W: [5 M0 C8 ~& C1 w3 |$ t
: z5 m' A0 ]; S4 h9 d' N: O: V7 H* l' j: d
typedef _com_ptr_t<_com_IIID<IUPnPDeviceFinder,&IID_IUPnPDeviceFinder> > FinderPointer;- g! a$ k9 R/ }, U
typedef _com_ptr_t<_com_IIID<IUPnPDevice,&IID_IUPnPDevice> > DevicePointer;
) w, T! k& W8 g5 W8 j' }typedef _com_ptr_t<_com_IIID<IUPnPService,&IID_IUPnPService> > ServicePointer;4 M, M4 t" A s6 k9 ~& _
typedef _com_ptr_t<_com_IIID<IUPnPDeviceFinderCallback,&IID_IUPnPDeviceFinderCallback> > DeviceFinderCallback;
" B6 ]5 l/ D5 A. {2 ~; w( Ttypedef _com_ptr_t<_com_IIID<IUPnPServiceCallback,&IID_IUPnPServiceCallback> > ServiceCallback;
9 u1 L+ g3 z+ V- m) }; Wtypedef _com_ptr_t<_com_IIID<IEnumUnknown,&IID_IEnumUnknown> > EnumUnknownPtr;% {* c1 S- A2 K3 u6 N: Y8 j; `$ n
typedef _com_ptr_t<_com_IIID<IUnknown,&IID_IUnknown> > UnknownPtr;* m& D4 Z' E5 J1 g
: j: g1 R3 W+ X" M' t" M7 y/ H% r: j, q$ g* t
typedef DWORD (WINAPI* TGetBestInterface) (& s/ U' I' U8 E
IPAddr dwDestAddr,; X% l$ m& p' [* T* N
PDWORD pdwBestIfIndex% u; W( w3 D+ H+ }, F E
);
2 a1 o, O4 _2 A# e# N3 ]/ o7 T) F) P: m( e# j3 g! I
9 t8 f0 M! ?1 F- r; I7 N
typedef DWORD (WINAPI* TGetIpAddrTable) (
4 D4 w4 [, Y2 d7 u: @/ M* j PMIB_IPADDRTABLE pIpAddrTable,
. T+ A* n1 g! u( L1 I* b, B2 z PULONG pdwSize,% \2 {% O$ T! @ S6 u m( I5 ?
BOOL bOrder5 Y3 v$ a I Q/ B1 [# k2 r( z1 ^( O
);
7 I$ v7 C3 @0 H }; U$ b6 U8 t0 m+ f# \$ r
4 `# o4 }' h# I% etypedef DWORD (WINAPI* TGetIfEntry) (+ `2 B0 x' d6 n/ g; O- F8 z
PMIB_IFROW pIfRow
7 f) U* X* y' D q& Z$ G); @+ c- {- Y4 g: H1 p6 g
+ w' e5 W! M# o( a" \% O6 l
5 H% C) p7 y/ [4 R6 P) z ?# ~
CString translateUPnPResult(HRESULT hr);
( r: W# X5 L7 N& b8 S& aHRESULT UPnPMessage(HRESULT hr);9 e( ]7 R z$ k- _& T' Y
+ Z- c' m' D, a# W3 B7 w6 x5 I5 e* B0 J: ^- ?; p
class CUPnPImplWinServ: public CUPnPImpl
4 a, D! G5 @% ~{
; U2 Y1 h, {/ a* u4 j7 A n' ^4 U friend class CDeviceFinderCallback;! ^" [5 b) Z% a/ ~6 f& ]! i
friend class CServiceCallback;
z* O0 y; a& ?4 ~( w% a) A// Construction
. C9 P' K, A) |4 |public:, t2 T; H* S1 V9 C
virtual ~CUPnPImplWinServ();
. g7 u: t# U! I* A CUPnPImplWinServ();
( L. A: M, `) I0 D1 z/ G; Z! }* i
3 f G( g4 B: a4 G5 F' Y5 m8 E- n7 c4 O* _1 q
virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) { StartDiscovery(nTCPPort, nUDPPort, nTCPWebPort, false); }
/ S3 h' H1 u: ~0 P& t virtual void StopAsyncFind();
) g* k+ Z! o# i0 K virtual void DeletePorts();
/ g+ ?5 K" G$ s4 i. S; M virtual bool IsReady();6 X+ O) Y* F( w
virtual int GetImplementationID() { return UPNP_IMPL_WINDOWSERVICE; }
: R8 Y1 O9 I* l( S' L* H1 y! v$ w
9 S% l: ]; X; u( K0 u# w# I7 G. D% t
6 a8 B6 U3 V+ L& E" o5 N6 I8 Y) u- g // No Support for Refreshing on this (fallback) implementation yet - in many cases where it would be needed (router reset etc)
9 {8 v" x3 i* \+ J- t // the windows side of the implementation tends to get bugged untill reboot anyway. Still might get added later
6 B2 h, ]7 V6 g) x b* \: b+ n virtual bool CheckAndRefresh() { return false; };* @6 u$ ~, c8 U' T' E; d% S, s" }
* F" r2 S N/ l y0 c; a N5 q, v
protected:% u" n/ Z- D8 N4 G, u
void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort, bool bSecondTry);
+ u) P2 K. n" e n+ ^4 A4 h void AddDevice(DevicePointer pDevice, bool bAddChilds, int nLevel = 0);; k- z, _% m; ?4 J3 n
void RemoveDevice(CComBSTR bsUDN);, l. Q& d! n# j, x, P# v( w9 v. @3 L
bool OnSearchComplete();
$ `/ ^. q) p4 i1 R void Init();% r5 G( I8 q0 z5 |; U( R
3 } G) }2 F# H( n
% N$ F8 I; ^/ ~/ x& A4 j' k inline bool IsAsyncFindRunning() $ ~, I+ q- }. _' V. \9 R$ M
{
, ^8 e& t+ q" e; o& K if ( m_pDeviceFinder != NULL && m_bAsyncFindRunning && GetTickCount() - m_tLastEvent > 10000 ): P9 ^; |, k9 A0 U5 P8 ?& J
{, e) `! v t, P9 a2 e
m_pDeviceFinder->CancelAsyncFind( m_nAsyncFindHandle );
) U+ B1 D3 K& \ m_bAsyncFindRunning = false;' p% W% E9 n* s: C
}
& T9 {) ]! m1 c' t MSG msg;* v6 L F! h# [
while ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
% W5 g- }& _ v6 D0 V& O {0 Z7 k% e% K9 S Z) V6 f( g
TranslateMessage( &msg );) h* ?- r# c: s7 p
DispatchMessage( &msg );
; J d' ~! ^8 D/ C }; A) D- u" l4 ~ m- e6 y
return m_bAsyncFindRunning;
4 ~2 n; y2 c; u/ I% V( j0 R }6 }. [" M1 _2 c0 H+ ^; y
& J0 [) c( [8 f) n% v! x- e* o
/ Z S7 c% ]4 ? TRISTATE m_bUPnPDeviceConnected;
! F2 I! n+ v# I& v N
. q i! u' E: m+ A4 Z& K1 g h- b" b. V: G5 D5 Q4 u' {+ ?( o
// Implementation5 q0 A. x% ~+ B; |, r0 V
// API functions
. f: _3 Y" Q' O$ X4 M1 f SC_HANDLE (WINAPI *m_pfnOpenSCManager)(LPCTSTR, LPCTSTR, DWORD);- l/ @5 f9 \# o2 j9 b0 X
SC_HANDLE (WINAPI *m_pfnOpenService)(SC_HANDLE, LPCTSTR, DWORD);. X& {( y* I; n
BOOL (WINAPI *m_pfnQueryServiceStatusEx)(SC_HANDLE, SC_STATUS_TYPE, LPBYTE, DWORD, LPDWORD);. o. e7 Z( G( ^% c
BOOL (WINAPI *m_pfnCloseServiceHandle)(SC_HANDLE);
, m9 ?7 c0 w) q% B& U BOOL (WINAPI *m_pfnStartService)(SC_HANDLE, DWORD, LPCTSTR*);
; ~: z }2 G, e3 l9 M3 _/ c s BOOL (WINAPI *m_pfnControlService)(SC_HANDLE, DWORD, LPSERVICE_STATUS);
4 m; u1 L" K$ X+ G% L. m% p& u" n2 W# }2 z8 A* k, P
0 z6 J' I! I: p- N2 Z
TGetBestInterface m_pfGetBestInterface;) F6 a( N4 L4 A! Z1 E" k/ r9 ^
TGetIpAddrTable m_pfGetIpAddrTable;8 B1 t& c9 D/ V' R; ?4 c
TGetIfEntry m_pfGetIfEntry;
3 S6 T9 k2 g5 d9 g% G+ N! E$ ~0 o7 ?$ H5 Y* H; F
* G: S& A9 g4 X; e$ o static FinderPointer CreateFinderInstance();' {1 F$ |! w2 ~
struct FindDevice : std::unary_function< DevicePointer, bool >
) }3 B2 j- [ b) N5 }& {5 A' U$ a {" [, ~ j" i. h& q
FindDevice(const CComBSTR& udn) : m_udn( udn ) {}: u: r/ L* C# L7 }5 e, U* X
result_type operator()(argument_type device) const( {) v$ O$ D, b/ m7 W* N
{ d) v: i- Z' |( y
CComBSTR deviceName;% W! \ ?' k9 f$ Q- T2 t0 R; w
HRESULT hr = device->get_UniqueDeviceName( &deviceName );1 c {+ l$ N: S9 k3 Z1 W
) y0 k0 B0 Z2 m/ M
/ ]6 C3 R5 {2 h if ( FAILED( hr ) )2 z' c0 t/ x9 n* j
return UPnPMessage( hr ), false;$ R0 W. ~7 k2 p, r
+ V* O5 Y+ V' v: d7 `
7 c$ Q& G" k3 P9 k return wcscmp( deviceName.m_str, m_udn ) == 0;
" i; B& f, h- }3 b9 D, O }
! e, I# k- L- @% u CComBSTR m_udn;" ?* W1 r; R' L
};5 e- P5 Q2 q( n F+ i& s9 g j
4 w0 X; B& B( I5 E
void ProcessAsyncFind(CComBSTR bsSearchType);* H9 B) O" P- T: b
HRESULT GetDeviceServices(DevicePointer pDevice);
0 G7 N) r( G; I8 u# h void StartPortMapping();" _: T5 ]/ F9 m, r7 f! L3 P% n
HRESULT MapPort(const ServicePointer& service);
# s2 w8 g6 ?5 Z6 U7 Z! w2 t) E4 b" I void DeleteExistingPortMappings(ServicePointer pService);
6 \8 K, Q) C/ J* d- Y1 p8 L, G# g void CreatePortMappings(ServicePointer pService);
% |4 E7 H' V$ p2 n2 z. @) I HRESULT SaveServices(EnumUnknownPtr pEU, const LONG nTotalItems);4 P- H* U8 s5 M; u! V
HRESULT InvokeAction(ServicePointer pService, CComBSTR action, ( u0 y( G3 I1 e3 ~! ~
LPCTSTR pszInArgString, CString& strResult);
* Y( H' u* j, F3 ?/ J5 m void StopUPnPService();
1 ^, U+ d: c4 e2 S# }+ K7 E2 A) N' U2 v& U9 `: a# W9 {( |4 a
0 M) D6 h3 V: S4 k
// Utility functions$ }" @3 ^7 J6 S/ Y$ o- c
HRESULT CreateSafeArray(const VARTYPE vt, const ULONG nArgs, SAFEARRAY** ppsa);* [' T8 `+ Q/ W1 L1 N. q8 ]6 Z
INT_PTR CreateVarFromString(const CString& strArgs, VARIANT*** pppVars);5 y6 s; I( B* ^
INT_PTR GetStringFromOutArgs(const VARIANT* pvaOutArgs, CString& strArgs); M8 q. a, D1 t2 ~6 Q% @' v) L
void DestroyVars(const INT_PTR nCount, VARIANT*** pppVars);0 F4 ]) }# t$ z7 ~$ R; X1 ]
HRESULT GetSafeArrayBounds(SAFEARRAY* psa, LONG* pLBound, LONG* pUBound); n1 a" X2 G ~6 v) C# e
HRESULT GetVariantElement(SAFEARRAY* psa, LONG pos, VARIANT* pvar);
, q6 n( ?5 e, z+ h6 U$ H5 C CString GetLocalRoutableIP(ServicePointer pService);
* b$ g6 ^5 e/ O* \2 s0 g) R3 c f# b4 l) p: z* Y6 L
0 {% N' v1 B9 F+ m- g9 X, L// Private members
- V4 S& Y& M% T: g! \' r, N$ f; bprivate:- }* j8 j$ F; k) T0 Z `
DWORD m_tLastEvent; // When the last event was received?
8 k H, |2 ~# B std::vector< DevicePointer > m_pDevices;2 `% X/ k- b) a! K0 l; e. {6 J& o
std::vector< ServicePointer > m_pServices;
6 W6 g7 b: D9 r' M z! N4 ^* }$ _ FinderPointer m_pDeviceFinder;
2 Y1 c% M" W: ~. o* o DeviceFinderCallback m_pDeviceFinderCallback;2 [) p4 w' P2 d* U9 w" m4 x
ServiceCallback m_pServiceCallback;
/ ^0 @: `) n3 w5 y4 P! [" G) |% I1 R3 ~/ q6 l4 P n D; E
' g- O; p, ] t7 t6 j m LONG m_nAsyncFindHandle;4 d- S* |5 @8 [' k3 @7 f2 l! V
bool m_bCOM;
/ T, h0 Q! P8 h( Y5 j bool m_bPortIsFree;9 q! n3 `1 L+ j7 z1 Q5 N" u& `7 Y
CString m_sLocalIP;$ x4 Q. u# H" G' ^- U% d2 g" A
CString m_sExternalIP;8 h8 m# l9 }. g6 W6 q* D
bool m_bADSL; // Is the device ADSL?
% z {! A; \& a2 J2 Y bool m_ADSLFailed; // Did port mapping failed for the ADSL device?
4 D- r7 r' j# v9 | bool m_bInited;
! p+ n* r/ b# t( I bool m_bAsyncFindRunning;
3 ^/ s$ o( i' @" W/ M$ c HMODULE m_hADVAPI32_DLL;
1 v W4 S: L! Z7 j# m: j; Y HMODULE m_hIPHLPAPI_DLL;
+ C: r$ s) m8 G3 V$ p5 F) p bool m_bSecondTry;* c$ d* z+ g8 ?. G& C
bool m_bServiceStartedByEmule;7 L1 I: a. e- t/ Z
bool m_bDisableWANIPSetup;4 K4 m* N( F3 Y! R1 b
bool m_bDisableWANPPPSetup;
& W3 b7 V7 g! ]3 c+ x! p5 g$ [! c# n% u) j: i6 p
# {4 ?! x$ v" m/ e& l8 h};3 c9 k* d( W6 D; J4 u. v" s
( n! E/ k3 K5 f# Y, S
1 }+ F& B/ t# |, d9 @2 P// DeviceFinder Callback/ z/ c' S4 e) m$ |
class CDeviceFinderCallback
" a7 t7 R; z! y( ~$ s( L" M3 W) t : public IUPnPDeviceFinderCallback
& D" u$ M6 L- B2 i. `1 l/ U5 Q1 N% _{
2 u3 ^, H; S8 K3 M6 c2 Wpublic:
9 Z9 k( {; d9 S' I; w& s, X CDeviceFinderCallback(CUPnPImplWinServ& instance)6 o" F* H0 x# g
: m_instance( instance )9 K5 O$ _# N( t: _
{ m_lRefCount = 0; }
: r; B J4 F, I ~6 s- o) v0 o6 T) q1 A5 R6 l* E! E5 A
" C1 R, @2 D# J4 p& I STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);
4 k! _- r5 U( Z5 {8 v; A9 b STDMETHODIMP_(ULONG) AddRef();% b* o( W0 H+ T: J3 F, K0 Y9 n
STDMETHODIMP_(ULONG) Release();& O0 P8 y% ?* N5 P+ x6 c& t$ K
2 U/ L. O5 D0 a& h) P4 j& V4 i9 U+ p
9 K+ L* s0 S; M7 \3 z// implementation
6 _8 V6 j v3 N% e5 T/ pprivate:
) O% ~8 K2 {( E HRESULT __stdcall DeviceAdded(LONG nFindData, IUPnPDevice* pDevice);
' }3 Q+ r f% a6 q, p7 i HRESULT __stdcall DeviceRemoved(LONG nFindData, BSTR bsUDN);$ [8 s- }) R1 V* v, n* M1 k: a
HRESULT __stdcall SearchComplete(LONG nFindData);
( |: G/ ]) C# s3 N* d4 A4 Z) H2 s) U5 h. o8 N5 s4 J
5 i: |3 K- ^: o. ~% t) }+ y: Aprivate:
* s4 B5 x! ^" A+ L- Q# j CUPnPImplWinServ& m_instance;, r0 @+ H) K3 ~
LONG m_lRefCount;
& k5 m* f5 t; | Q1 g- M3 \};
' y# h) ?" e0 H R" c) d- e6 n
: @% ^( r, A9 O4 V$ b' @" F! G: z+ H- T+ y8 R4 Z
// Service Callback 4 ?/ G4 K6 j% K0 a5 f# J
class CServiceCallback
4 u* j$ o, ?& i W, t }5 q& F : public IUPnPServiceCallback
( K' {1 E* g. r, n, m3 K{% w+ O/ B, F$ S2 L4 N: q
public:
. v4 C6 z) {, S7 \% Q$ O CServiceCallback(CUPnPImplWinServ& instance)( C' r5 ^; }! Q4 c* n y
: m_instance( instance )
5 t0 w% r0 M) m3 Y/ W( { { m_lRefCount = 0; }0 z8 Z9 g+ @& M; B/ k$ N
0 \: j9 D( `2 u. k/ ~. O3 e) h
STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);, s1 w& T1 S' n" A
STDMETHODIMP_(ULONG) AddRef();
q8 }+ @. i/ l3 u$ X% | STDMETHODIMP_(ULONG) Release();
9 N% u% ? f- a4 `- t5 E
v* v1 \. P4 n) f/ _
( I+ O( Z* I1 Z// implementation2 E' o m Y/ T- w7 ]" o
private:2 v8 G% L" L1 M# p( a" b
HRESULT __stdcall StateVariableChanged(IUPnPService* pService, LPCWSTR pszStateVarName, VARIANT varValue); J. {) R$ `: }
HRESULT __stdcall ServiceInstanceDied(IUPnPService* pService);. N7 z$ D& Q3 [6 V. C( c
$ H3 l8 o) h [/ D
) Y! ~/ N( Z) g$ \# W: oprivate:' }6 f* y3 K, w" N7 A; \
CUPnPImplWinServ& m_instance;0 |7 }3 C- W: G# K
LONG m_lRefCount;
0 \& z0 ^3 q0 z* c/ I4 X" c6 c" U};
6 W+ c5 p* {. Y$ W. @3 K
5 y4 ?: ]( q% ]& K: }$ M; q3 H
1 N* O+ V8 i9 \ P/////////////////////////////////////////////////9 P5 z9 n: M: E w
4 H$ q2 m9 b2 r% }- e
0 j* v @; Y4 h/ |# X; Z5 O使用时只需要使用抽象类的接口。( C( Q1 w0 e3 t$ y' A# y! ]
CUPnPImpl::SetMessageOnResult设置需要接受UPNP端口映射是否成功的窗口句柄和消息ID.
0 Q y! Y: o2 B4 WCUPnPImpl::StartDiscovery将开启一个异步设备查找并进行端口映射,其参数为需要映射的内网端口. v% d2 M k5 o1 n! C( G
CUPnPImpl::StopAsyncFind停止设备查找.
0 s w% q: }8 f# FCUPnPImpl::DeletePorts删除端口映射. |
|