|
|
楼主 |
发表于 2011-7-15 17:28:52
|
显示全部楼层
以下有关upnp的接口来自emule,/ G: R/ v7 f; F5 Z8 x$ n6 r. f2 K
1 Q% n6 V! v/ \0 B# k; k1 r- m' [" u5 C0 c7 z1 v. d0 m
///////////////////////////////////////////; T5 n0 ~! a8 M
//upnp的抽象接口类,只需调用这些接口即可实现端口映射功能.
/ M6 E1 t, V+ V" K
* Y. e2 i2 ?) U, c# s3 V
3 k) e! D* h: c' g#pragma once
5 g/ J) V: o7 G# V; A5 G#include <exception>
' K+ j0 { A4 l/ N" t
( c, @' K( f/ f( f Z3 D$ d; a
# `' k Z6 X3 @ enum TRISTATE{9 H' X& R4 k' ]2 x! L
TRIS_FALSE,. ]% ^4 V; }0 u7 b1 C P2 x
TRIS_UNKNOWN,
1 F) T8 P7 e7 H+ L$ L+ N" @ TRIS_TRUE; N. y) D& ?* ?2 {! n ]' j! K8 C
};
8 K2 }7 F: f; {+ O* v" _% B' e5 u2 `5 w5 h' s
0 S# |. q; u5 O& c2 y
enum UPNP_IMPLEMENTATION{( ~& t! H% `. i+ L7 X7 U1 C
UPNP_IMPL_WINDOWSERVICE = 0,
& W& B. e! g1 d' i0 e y6 i! m6 D UPNP_IMPL_MINIUPNPLIB,: [6 d1 N% I4 g# [) s3 b
UPNP_IMPL_NONE /*last*/
+ I% F# Z; W, L};
; t, {/ _' @, H4 {$ z& R$ ^- f8 W n, S' K0 s- B& W: }; `
9 p, V: ]- S3 v$ X
+ o1 u4 u7 F0 t
G" b+ o: U& k8 V; ^, ]class CUPnPImpl8 f5 i7 l% t' ^. \1 |" I
{
1 z& P( \/ `5 z. jpublic:1 W7 R- F# |% W* Y1 i
CUPnPImpl();
( ?* r; T3 R% _3 ^1 @( |6 A* ^ virtual ~CUPnPImpl();
8 ]9 g4 r( U: e( M% m. K struct UPnPError : std::exception {};
& s; X+ q, S6 H. a enum {2 N4 t# ^) E3 q" Q
UPNP_OK,
! \5 ~0 V, c! y8 T* K2 _# `0 t UPNP_FAILED,
% [9 A l6 R0 S6 X# t UPNP_TIMEOUT
" f. z, N. b9 u# Z. B% X9 W1 F };
L, Z- s, ^2 I( j* D( i" I( X0 p/ P( K/ A; }0 }+ d
/ q4 U. B5 {% g/ {1 I
virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) = 0;
- @" y: e9 I- d1 ^, y virtual bool CheckAndRefresh() = 0;3 T* Q, `* ?8 j
virtual void StopAsyncFind() = 0;
3 J! g/ h/ i0 [# Y. E% z virtual void DeletePorts() = 0;1 W1 r& W( Z7 Z+ N c
virtual bool IsReady() = 0;
D$ {6 _+ {2 B* ?# M9 b3 G ` virtual int GetImplementationID() = 0;3 }0 r" V1 c1 L- ~/ w" N, m' d
" s0 f" I1 T, i
void LateEnableWebServerPort(uint16 nPort); // Add Webserverport on already installed portmapping" H' k R( H2 P" s* } {
# n! \+ Y+ {! y& d7 z7 R6 r7 m
- b7 n% z* z$ \, F. @ j5 m" `
void SetMessageOnResult(HWND hWindow, UINT nMessageID);; H4 v ~2 K. h/ {& I! ]
TRISTATE ArePortsForwarded() const { return m_bUPnPPortsForwarded; }. }+ X8 K+ o) z5 {& C. K" n0 h
uint16 GetUsedTCPPort() { return m_nTCPPort; }, @- x: j& E: ~0 K2 ?% H/ N
uint16 GetUsedUDPPort() { return m_nUDPPort; } 7 n4 u1 u( Z* D5 ?1 a) f9 {# e
: ?3 m2 x" G: v, e0 G! P/ G
3 L( ^ Q n' o D// Implementation% W" @5 _% m3 |: s
protected:
& L; Y( e$ l% [ volatile TRISTATE m_bUPnPPortsForwarded;/ M: _! R# ~9 u- n
void SendResultMessage();/ `$ v2 m) C- K1 e
uint16 m_nUDPPort;
7 Y6 ^* R6 f6 ~- M+ a uint16 m_nTCPPort;1 F. }! B: f- l% N' [1 m
uint16 m_nTCPWebPort; q9 V; Z7 I2 h% ~& t' k! B
bool m_bCheckAndRefresh;. n$ S1 r0 q* ^. Q; v
6 l( y# L- G" x: O" B" a! s8 J$ @! L
private:6 r( B; d5 B# {" N( u7 F* g; l
HWND m_hResultMessageWindow;
, \. g4 I; Y; i G8 _6 U% d UINT m_nResultMessageID;& {, o, Z! O9 t' o
& Z. h \. q0 Q8 o9 H; D; ?+ f; D$ S* _
};4 u0 |- f% O4 X3 F6 U) o
" x) [' \' V" O6 I2 p: \8 H! L) ~- ]0 ^
// Dummy Implementation to be used when no other implementation is available
$ Z3 P1 C% }0 N$ Zclass CUPnPImplNone: public CUPnPImpl
" l6 C4 d3 S8 d g; q1 ?{. E4 g/ J/ b9 Z
public:- X/ Z, Y. r" d# C
virtual void StartDiscovery(uint16, uint16, uint16) { ASSERT( false ); }+ A* @3 |; z' b# w
virtual bool CheckAndRefresh() { return false; }" B& _$ g9 r4 q9 T
virtual void StopAsyncFind() { } J9 I1 B( R& r
virtual void DeletePorts() { }
3 U* c* y8 e# C# a4 f& h; { virtual bool IsReady() { return false; }! Y. n T% J1 x, b' _4 z
virtual int GetImplementationID() { return UPNP_IMPL_NONE; }
5 r% ?" E; t# J3 A- g};5 h, T0 `9 y; b" l/ I
% \2 y4 G5 ~4 O; [6 r4 M7 c
5 e* W0 [7 A. O0 Z. [, x3 H$ W+ f/////////////////////////////////////
- N1 [- F, d1 m8 A0 O2 ?) n( W//下面是使用windows操作系统自带的UPNP功能的子类' {4 |, `; p L
* D7 D& y7 m$ L) V9 p2 s4 _- X& \- c4 d* g
#pragma once
' Q# d- L3 Q6 j* `- @' t#pragma warning( disable: 4355 )
4 k4 @! Q6 d* a1 ?6 w9 O0 ^& [: t' k" ?3 D
3 ?6 p* s9 o1 c' z3 p! Z& Q' W
#include "UPnPImpl.h"" A+ E+ b6 y, `8 y$ g
#include <upnp.h>6 k# r7 K8 h4 u' ~& k+ P
#include <iphlpapi.h>. A3 g2 r* D, q* B5 C" h
#include <comdef.h>
& E$ G5 B) S, e5 C! j1 ~% W#include <winsvc.h>
# v* i& g, T6 n: S! U' o- m, b% L" l% x3 C! D; p
D* K) X( A1 A( I- a) S$ g
#include <vector>
4 v. W5 D( w3 ~2 l" W5 Q$ K#include <exception>' @. k9 S2 q9 b$ l/ T8 R
#include <functional>. X' m+ d3 R6 M0 c# t/ S9 z
& C& q' f! F. J# E
6 W7 T9 y9 p7 p; P
5 d1 g6 l' W0 U, t! J5 r& v; o5 f5 _4 v9 ~5 N
typedef _com_ptr_t<_com_IIID<IUPnPDeviceFinder,&IID_IUPnPDeviceFinder> > FinderPointer;
6 K" D3 O4 r7 \- O. [! Ytypedef _com_ptr_t<_com_IIID<IUPnPDevice,&IID_IUPnPDevice> > DevicePointer;9 y& U- H6 K" l5 o
typedef _com_ptr_t<_com_IIID<IUPnPService,&IID_IUPnPService> > ServicePointer;
) R: L) K2 }# `+ ctypedef _com_ptr_t<_com_IIID<IUPnPDeviceFinderCallback,&IID_IUPnPDeviceFinderCallback> > DeviceFinderCallback;4 G- B( W7 C, n# {/ s9 i
typedef _com_ptr_t<_com_IIID<IUPnPServiceCallback,&IID_IUPnPServiceCallback> > ServiceCallback;
2 }7 ^ ?- l% H5 q/ X' Jtypedef _com_ptr_t<_com_IIID<IEnumUnknown,&IID_IEnumUnknown> > EnumUnknownPtr;
0 n+ H% I4 b9 c0 Z" S+ H2 ?typedef _com_ptr_t<_com_IIID<IUnknown,&IID_IUnknown> > UnknownPtr;
; O: \! E$ \$ s) P' a1 M0 c& o! H6 o& J
6 R$ p+ E& l! w- |& A" R
typedef DWORD (WINAPI* TGetBestInterface) (
) p; v+ F6 W3 v IPAddr dwDestAddr,
+ A- b, h5 _- R PDWORD pdwBestIfIndex
& P k2 k9 q7 H+ H! b6 m7 [# [8 m);- z, ~8 t5 b" e+ C7 j) {9 s" h
' N) w- x) b, a/ U
8 E6 z$ O R! m3 ?7 @4 etypedef DWORD (WINAPI* TGetIpAddrTable) (
% `6 {! g$ L) Z0 m0 q2 x PMIB_IPADDRTABLE pIpAddrTable,& d! e& p- `/ k& u7 X6 t8 I
PULONG pdwSize,9 O! }0 a' P1 e, `3 K0 ?
BOOL bOrder
+ E2 g0 R8 q0 ]);
4 G8 Y( Q/ S$ \9 d5 f7 _8 Q- F7 G, |! a9 m
" T' L+ c/ R, c* C9 X) `
typedef DWORD (WINAPI* TGetIfEntry) (
9 T/ D: V* z# W* K1 d4 ?% ^ PMIB_IFROW pIfRow& w+ g9 p) R6 R9 ?% A
);+ Z, l, k' y- l0 R3 v: \5 V, x
- g; i% Y% [3 f! c' u
" T" n( O/ V; h) n4 p$ A, N# }CString translateUPnPResult(HRESULT hr);
" t& w& l. ~* P$ D0 s6 f$ AHRESULT UPnPMessage(HRESULT hr);
( z6 H$ A8 V% ^, N; N* X3 d$ d% ^" y" ~7 H* }* A( r9 J1 A) X$ O4 }
7 }' k# a) c6 q/ Z( Q7 o1 m
class CUPnPImplWinServ: public CUPnPImpl
* h- R0 Z7 u- d- c{
2 E. W; h5 H# n9 t; | friend class CDeviceFinderCallback;' O% X4 t. W. @0 g6 T
friend class CServiceCallback;
9 x7 _' G1 N. n* ]; @: B( h// Construction
8 W, Z. o! w8 ^% a; q" H# x& y9 ^9 Ipublic:
4 S P9 z j! m6 b virtual ~CUPnPImplWinServ();
+ |: w, R) \4 ^: F' x( A% [' C CUPnPImplWinServ();
3 [6 _% O' H# j% ^- F' g k1 |6 z1 }. i6 M5 W
0 L1 S, J; y* R$ O5 U virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) { StartDiscovery(nTCPPort, nUDPPort, nTCPWebPort, false); }( Q j" a2 z+ V5 _+ E" C
virtual void StopAsyncFind();+ T8 M. s; |5 I/ A, }, n
virtual void DeletePorts();
! k; l& w# @. D# X: ~9 W9 G0 U virtual bool IsReady();
' Y6 M3 C. M* L* w6 u virtual int GetImplementationID() { return UPNP_IMPL_WINDOWSERVICE; }: U5 w, U: T& s- R/ T9 S0 J
: f% Y7 o( C& Q- n B z6 Q1 F" y
( X3 O. o# z4 h6 ~ // No Support for Refreshing on this (fallback) implementation yet - in many cases where it would be needed (router reset etc)
$ V# k! v# W7 S: t // the windows side of the implementation tends to get bugged untill reboot anyway. Still might get added later9 ]' V" S# T- _5 \# Y
virtual bool CheckAndRefresh() { return false; };
# l+ u Y6 ]: |, |1 V* l- h# L1 C9 v
, a; n4 N0 E6 k! p0 k
protected:9 S* b! t' B9 b; c
void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort, bool bSecondTry);2 J3 v( h% m# W) C; \
void AddDevice(DevicePointer pDevice, bool bAddChilds, int nLevel = 0);
& n/ r' V. N. |1 l2 B void RemoveDevice(CComBSTR bsUDN);5 @1 h, J, |$ d; g) D/ D2 j: E& `; L4 F5 ?
bool OnSearchComplete();
. n' x/ B2 b, o) l8 ]/ p a void Init();
+ F2 t' Q1 ^$ _1 S9 p6 T: t4 ]7 O# l: F! Q* g0 o, ?
" E M5 h m) ^- ^3 O
inline bool IsAsyncFindRunning() , D% X/ U7 }0 J3 g$ f5 X$ N8 c/ z
{
6 d5 M' \; M% v- Q if ( m_pDeviceFinder != NULL && m_bAsyncFindRunning && GetTickCount() - m_tLastEvent > 10000 )
4 n K5 q% {. O2 W$ X. t {
) c9 J/ Y0 ^0 z/ r4 T( C: _ m_pDeviceFinder->CancelAsyncFind( m_nAsyncFindHandle );
0 F& a, U& a( r m_bAsyncFindRunning = false;6 L9 L& n. E' Y! p& w. l
}
3 o: g* n$ S, w b D MSG msg;
, i) N: k2 X, k while ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )2 W: G) P |+ y. x& ^, e; t& `
{
* y1 s4 r, K$ D TranslateMessage( &msg );* m3 T s$ g ^8 _
DispatchMessage( &msg );' x7 r/ ?- u5 `2 H. m. `. f
}
7 _; |; t5 E/ Y0 z3 Z4 S" H5 x return m_bAsyncFindRunning;
# r( M3 I- C: I }
. I- r! n* W \4 _" r5 |7 w b* H- a; Y- O8 A) f
) A1 \" p: v0 ~+ K/ e/ y1 c: n- @
TRISTATE m_bUPnPDeviceConnected;* p' j$ F1 q! Q7 w$ D$ n. |! [
& x! v7 V( w. |2 n" F& A) q( e" ]: M2 M
// Implementation9 M4 f) ?! P4 s+ M+ W
// API functions" m1 I$ \% o' `9 O4 Y. C
SC_HANDLE (WINAPI *m_pfnOpenSCManager)(LPCTSTR, LPCTSTR, DWORD);
! P3 ^$ k) ]* D5 Y SC_HANDLE (WINAPI *m_pfnOpenService)(SC_HANDLE, LPCTSTR, DWORD);4 T) s& O! N7 d( W! h* P
BOOL (WINAPI *m_pfnQueryServiceStatusEx)(SC_HANDLE, SC_STATUS_TYPE, LPBYTE, DWORD, LPDWORD);
% m* _3 f5 C( z. a BOOL (WINAPI *m_pfnCloseServiceHandle)(SC_HANDLE);4 z3 P, T$ G+ S7 M& c
BOOL (WINAPI *m_pfnStartService)(SC_HANDLE, DWORD, LPCTSTR*);* @0 {2 d* p% k. `7 X0 X5 Q; J
BOOL (WINAPI *m_pfnControlService)(SC_HANDLE, DWORD, LPSERVICE_STATUS);5 N5 r. F# M- _' p0 b/ v
; Y6 l- Y* f/ @& X) u, y8 D
% \. X N$ r' @3 V& u
TGetBestInterface m_pfGetBestInterface;
" k$ z5 Y$ b) `+ V: ` TGetIpAddrTable m_pfGetIpAddrTable;
3 o( }4 ]; e# D, y5 v/ Q TGetIfEntry m_pfGetIfEntry;
2 U4 y6 _/ q4 X8 [% y \5 n# i/ }) z& u9 y. j5 T* a
`/ F4 O7 J! B- B static FinderPointer CreateFinderInstance();+ ^6 I& g* P. l. W0 E* x
struct FindDevice : std::unary_function< DevicePointer, bool >" H. d0 F& { m7 q9 `
{
( \. m' H8 C: E. { FindDevice(const CComBSTR& udn) : m_udn( udn ) {}
8 ?8 u9 S- H5 k p6 q result_type operator()(argument_type device) const
, g/ _6 s5 S9 x! e, o( D* F8 G {
& V( t: l5 X- t) b* v( I CComBSTR deviceName;
, N) [4 U0 G! ?' g0 p HRESULT hr = device->get_UniqueDeviceName( &deviceName );
# P! p5 @2 L" [- a. z) o8 Y9 a# |, P; q( e0 n. R2 y0 d0 v1 f& r
% M! I% ]$ s' |* K$ F8 \ if ( FAILED( hr ) )
1 n0 m/ ^; A4 h1 b7 r4 T return UPnPMessage( hr ), false;
6 [1 f- ^6 a, j8 P, ?+ T1 N p% E# M% u2 O; i
, K `; Z% Y5 z. ^
return wcscmp( deviceName.m_str, m_udn ) == 0;
5 h$ w# J& K7 W8 X' u s+ r" t- [ }) t8 a' s5 p* l5 f# j# r: V/ q
CComBSTR m_udn;
' z; u1 L" ?) R };
$ g' H: ^2 S: x6 d
% G9 r4 e% |" U8 C$ Z# @1 Y void ProcessAsyncFind(CComBSTR bsSearchType);* h E a2 n5 Z* u& @
HRESULT GetDeviceServices(DevicePointer pDevice);
+ S& @4 m+ `, C3 L void StartPortMapping();/ i) k# I' I' A- K' ^+ R7 z) y
HRESULT MapPort(const ServicePointer& service);
3 g- y- L5 Q! n( w7 i# R. s void DeleteExistingPortMappings(ServicePointer pService);
Z G# l! @, q" M void CreatePortMappings(ServicePointer pService);
8 e6 z3 j9 z; d1 a/ L1 A+ N HRESULT SaveServices(EnumUnknownPtr pEU, const LONG nTotalItems);+ K* o* S7 J8 ]- a
HRESULT InvokeAction(ServicePointer pService, CComBSTR action, 4 y; A2 f1 F$ E/ h% U7 y- d
LPCTSTR pszInArgString, CString& strResult);' ]+ t/ x/ P2 I) T
void StopUPnPService();
# j9 ?) a9 C3 D, h. M- G0 q
8 G( W7 o1 M7 o% L* V/ S; e
% j0 H& J1 F6 B2 ~+ A$ v" E2 m // Utility functions( }- f, L9 o7 @. E
HRESULT CreateSafeArray(const VARTYPE vt, const ULONG nArgs, SAFEARRAY** ppsa);, L0 \$ S) w5 @: t
INT_PTR CreateVarFromString(const CString& strArgs, VARIANT*** pppVars);# S( k2 i5 c. `
INT_PTR GetStringFromOutArgs(const VARIANT* pvaOutArgs, CString& strArgs);' m# y* ]0 q' ]! H6 O* i
void DestroyVars(const INT_PTR nCount, VARIANT*** pppVars);
1 {: O1 f4 t7 P HRESULT GetSafeArrayBounds(SAFEARRAY* psa, LONG* pLBound, LONG* pUBound);/ U; l6 `1 D4 c, L; T8 h
HRESULT GetVariantElement(SAFEARRAY* psa, LONG pos, VARIANT* pvar);5 h6 c* x* W$ ]2 {, y( D
CString GetLocalRoutableIP(ServicePointer pService);
7 _0 k/ s1 D* B3 h! ^' H3 j6 k2 V: ?
$ w3 H% k, s+ R4 i// Private members- t, t- I# [ a+ O
private:
$ o) w7 L$ s9 X9 A' n& ~# x9 [- ~ DWORD m_tLastEvent; // When the last event was received?5 {; {. o# q8 w/ X( Z; L. v. \
std::vector< DevicePointer > m_pDevices;
* W: M/ x1 j4 O4 w* ?2 Z std::vector< ServicePointer > m_pServices;/ J. `( ]2 G, y
FinderPointer m_pDeviceFinder;
) Y3 O. c4 [3 J2 t" G; Q- B DeviceFinderCallback m_pDeviceFinderCallback;
& Z$ Q" W& @+ i7 d ServiceCallback m_pServiceCallback;
- v2 M' q( ?& j# o0 ^7 c8 ?* s; K: }2 g
/ l0 `# G; w: C, [, e/ v3 T8 `
LONG m_nAsyncFindHandle;
1 ~7 \3 S8 v N) i. S- o bool m_bCOM;
4 i! r, H8 U& Z7 \# a9 b J2 c0 d bool m_bPortIsFree;1 s+ h8 u9 M$ `; I; {9 w4 b4 F) x
CString m_sLocalIP;9 c& h' L% a9 o: D
CString m_sExternalIP;
* M' @9 [' Q1 x# c bool m_bADSL; // Is the device ADSL?' [1 b# \, u6 ^/ N
bool m_ADSLFailed; // Did port mapping failed for the ADSL device?
5 d5 o0 P; S9 y1 o9 B. U& U bool m_bInited;
7 q( p1 j b9 j. p! L0 K bool m_bAsyncFindRunning;
1 l. I1 P5 Q6 I+ G3 m+ a HMODULE m_hADVAPI32_DLL;$ t3 d: V0 Y8 A0 r$ G; ]
HMODULE m_hIPHLPAPI_DLL;
3 {) M x2 K4 }2 f bool m_bSecondTry;* z2 {2 I: `" q, p4 I" {
bool m_bServiceStartedByEmule;& a1 K. B2 Z: o ~
bool m_bDisableWANIPSetup;5 b+ R; J( o z
bool m_bDisableWANPPPSetup;6 t! r4 g9 V% E. ]9 v8 B% ^
2 S, N* Z' Y# _3 ]2 z9 u7 Z; l. n2 e2 h4 g @( _. F9 ?
};
P/ x* D7 T# j: b1 L$ r
6 i5 z) u5 t) Z
: `% Q: h+ P8 h& f: n// DeviceFinder Callback
- X# \! Q9 b) H% C8 y. x. i6 Q; Bclass CDeviceFinderCallback) [8 D/ ]' l5 U; O- h
: public IUPnPDeviceFinderCallback( H; M0 r& P$ e, l$ u7 q4 p
{
0 }( M5 o" r9 {. L; K) opublic:; {* G& `( P( i" E( F3 ^
CDeviceFinderCallback(CUPnPImplWinServ& instance)' `( I$ e6 J' g' `& J
: m_instance( instance )
) O; d# ~* c0 y# [ { m_lRefCount = 0; }
, o0 n3 B' Q4 z8 j% L+ m. l0 O3 c" [2 O- ?* o7 p* w
: f- ?- J1 G; [' g3 h$ c STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);& a7 U. h' x# N" m
STDMETHODIMP_(ULONG) AddRef();1 E9 N- g6 W# V2 ]
STDMETHODIMP_(ULONG) Release();4 g, d( s) c1 I: z# [
! L6 B8 [; R; D/ ~+ h: T% N
! g7 A# W" a+ J/ j+ Q" |. p
// implementation
( n3 p- e& g; E2 j5 }; ~6 Uprivate:
& U) E% l$ b5 b% H, M" {) C HRESULT __stdcall DeviceAdded(LONG nFindData, IUPnPDevice* pDevice);
: o5 y& g7 g0 \$ r1 h' ] HRESULT __stdcall DeviceRemoved(LONG nFindData, BSTR bsUDN);
' V2 H* K) h2 H1 f- ? HRESULT __stdcall SearchComplete(LONG nFindData);
2 s5 \0 [) X+ Y- y! |& Z- a7 B- M
* v( P, E' p- K' m5 X0 X* i
private:
% G, ?7 O- q9 |" }0 P CUPnPImplWinServ& m_instance;
0 j s: B$ v( v! E2 L4 _* I LONG m_lRefCount;
( R4 n7 M1 J$ h2 v/ J};2 D) y- l5 v* x. N( p. g; ?7 g
8 ]& ]0 i2 T( d! o" E4 n
. Y: ~) n. j" z4 |9 {' F// Service Callback # F4 U) f! a" w+ g3 E
class CServiceCallback
5 F. {1 Z9 h2 y7 i : public IUPnPServiceCallback
2 \3 k/ d1 y, [, F{
2 _7 @- h& u! e+ d/ H; Tpublic:* t- h$ }6 p3 I! S; j! K4 B
CServiceCallback(CUPnPImplWinServ& instance)9 F5 K- T1 H p9 ?% A% K4 n
: m_instance( instance )' s c8 r7 O/ L
{ m_lRefCount = 0; }
) ~/ Q6 C: B @* ~ / `0 c9 _# K& |( {3 @+ h% ?
STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);
. |7 t7 k; c7 O STDMETHODIMP_(ULONG) AddRef();5 ] g5 L* ?& ^5 X @1 [+ O' B
STDMETHODIMP_(ULONG) Release();4 U& x) ^8 ]5 i T& l
6 K' w/ |4 }# n3 P. N
/ V2 z- E1 i W+ G! [; z O" }// implementation) \2 e, l4 l% c ?
private:' v# Z2 f8 W" F+ [; c( [5 V
HRESULT __stdcall StateVariableChanged(IUPnPService* pService, LPCWSTR pszStateVarName, VARIANT varValue);
! x2 C, ^1 R5 t6 ^9 r! S HRESULT __stdcall ServiceInstanceDied(IUPnPService* pService);) }2 F. h% H; ^- r' }0 T& O" m! Z
F; g# a8 N9 P1 R# L7 l4 y( ]
; `" i# r" {# E5 ~' Y
private:3 C& E9 L6 F8 ^9 K% Y
CUPnPImplWinServ& m_instance; v" F7 Q' f" _) `; E0 [
LONG m_lRefCount;) z& u4 R5 d2 I* K6 R' T6 H
};' D# W/ O8 N8 f2 P, \: ^ X, ~/ A+ z
0 [" B3 ~$ e* z9 Q# q8 q
4 w0 v! @0 n7 j; @- z- k: k2 r2 _/////////////////////////////////////////////////( O, C; S8 P5 L# A
# X/ V+ M# S* i A, o
2 p, X: l# k0 J; P使用时只需要使用抽象类的接口。
1 |: b. f& S$ f9 e1 W) CCUPnPImpl::SetMessageOnResult设置需要接受UPNP端口映射是否成功的窗口句柄和消息ID.1 p V' f( s! M" \+ P$ _
CUPnPImpl::StartDiscovery将开启一个异步设备查找并进行端口映射,其参数为需要映射的内网端口.+ C3 e5 `3 R9 I) m+ }
CUPnPImpl::StopAsyncFind停止设备查找.$ S& |' X! g0 c3 a, H
CUPnPImpl::DeletePorts删除端口映射. |
|