Hi,
You have to to use the connection manager api from microsoft. I have
translated some parts of it to object pascal (source is attached). The
source is not well tested now, but it works for me. For a simple
connection to the internet you can use the following code.
Cheers, Adrian.
var
ConnInfo: CONNMGR_CONNECTIONINFO;
begin
ZeroMemory(@ConnInfo, sizeof(ConnInfo));
ConnInfo.cbSize:= sizeof(ConnInfo);
ConnInfo.dwParams:= CONNMGR_PARAM_GUIDDESTNET;
ConnInfo.dwPriority:= CONNMGR_PRIORITY_USERBACKGROUND ;
ConnInfo.guidDestNet:= IID_DestNetInternet;
if ConnMgrEstablishConnectionSync(ConnInfo, FConnection, 60000,
FStatus) <> S_OK
then
raise Exception.Create('No connection');
John vd Waeter schrieb:
Hi all,
With the INet components, I managed to use a UDP-component to
frequently ask an internetserver for some data.
However, no traffic is generated when the handheld is powered up. I
first have to initiate internet explorer, ask for some trivial page
and after that my application can continu its UDP traffic.
I guess starting IE opened a networkpath and takes care of obtaining
an ipnr etc.
What do I have to call to ensure a networkpath (GPRS, WiFi, whatever
is available) is opened the same way IE does?
tia!
John
_________________________________________________________________
To unsubscribe: mail [EMAIL PROTECTED] with
"unsubscribe" as the Subject
archives at http://www.lazarus.freepascal.org/mailarchives
unit connmgr;
interface
uses
Windows;
const
External_library='cellcore'; {Setup as you need}
{$IFDEF FPC}
{$PACKRECORDS C}
{$ENDIF}
{ 436EF144-B4FB-4863-A041-8F905A62C572 }
{DEFINE_GUID(IID_DestNetInternet, 0x436ef144, 0xb4fb, 0x4863, 0xa0, 0x41,
0x8f, 0x90, 0x5a, 0x62, 0xc5, 0x72); }
{ A1182988-0D73-439e-87AD-2A5B369F808B }
{DEFINE_GUID(IID_DestNetCorp, 0xa1182988, 0x0d73, 0x439e, 0x87, 0xad,
0x2a, 0x5b, 0x36, 0x9f, 0x80, 0x8b); }
{ 7022E968-5A97-4051-BC1C-C578E2FBA5D9 }
{DEFINE_GUID(IID_DestNetWAP, 0x7022e968, 0x5a97, 0x4051, 0xbc, 0x1c,
0xc5, 0x78, 0xe2, 0xfb, 0xa5, 0xd9); }
{ F28D1F74-72BE-4394-A4A7-4E296219390C }
{DEFINE_GUID(IID_DestNetSecureWAP, 0xf28d1f74, 0x72be, 0x4394, 0xa4, 0xa7,
0x4e, 0x29, 0x62, 0x19, 0x39, 0x0c); }
{ }
const
IID_DestNetInternet: GUID = (D1: $436ef144; D2: $b4fb; D3: $4863 ;D4: ($a0,
$41, $8f, $90, $5a, $62, $c5, $72));
IID_DestNetCorp: GUID = (D1: $a1182988; D2: $0d73; D3: $439e; D4: ($87,
$ad, $2a, $5b, $36, $9f, $80, $8b));
IID_DestNetWAP: GUID = (D1: $7022e968; D2: $5a97; D3: $4051; D4: ($bc, $1c,
$c5, $78, $e2, $fb, $a5, $d9));
IID_DestNetSecureWAP: GUID = (D1: $f28d1f74; D2: $72be; D3: $4394; D4:
($a4, $a7, $4e, $29, $62, $19, $39, $0c));
CONNMGR_PARAM_GUIDDESTNET = $1; { @constdefine guidDestNet field is
valid }
CONNMGR_PARAM_MAXCOST = $2; { @constdefine MaxCost field is valid }
CONNMGR_PARAM_MINRCVBW = $4; { @constdefine MinRcvBw field is valid }
CONNMGR_PARAM_MAXCONNLATENCY = $8; { @constdefine MaxConnLatency field
is valid }
{
----------------------------------------------------------------------------- }
CONNMGR_FLAG_PROXY_HTTP = $1; { @constdefine HTTP Proxy supported }
CONNMGR_FLAG_PROXY_WAP = $2; { @constdefine WAP Proxy (gateway)
supported }
CONNMGR_FLAG_PROXY_SOCKS4 = $4; { @constdefine SOCKS4 Proxy supported }
CONNMGR_FLAG_PROXY_SOCKS5 = $8; { @constdefine SOCKS5 Proxy supported }
{
----------------------------------------------------------------------------- }
CONNMGR_FLAG_SUSPEND_AWARE = $10; { @constdefine suspended connections
supported }
CONNMGR_FLAG_REGISTERED_HOME = $20; { @constdefine only dial out if
we're registered on the home network }
CONNMGR_FLAG_NO_ERROR_MSGS = $40; { @constdefine don't show any error
messages for failed connections }
CONNMGR_FLAG_WAKE_ON_INCOMING = $80; { @constdefine to satisfy request
use only those interfaces that can wake the system on incoming traffic }
{
----------------------------------------------------------------------------- }
CONNMGR_PRIORITY_VOICE = $20000;
{ @constdefine Voice, highest priority, reserved for internal use only. }
CONNMGR_PRIORITY_USERINTERACTIVE = $08000;
{ @constdefine User initiated action caused this request, and UI is
}
{ currently pending on the creation of this connection. }
{ This is appropriate for an interactive browsing session, }
{ or if the user selects "MORE" at the bottom of a truncated }
{ mail message, etc. }
CONNMGR_PRIORITY_USERBACKGROUND = $02000;
{ @constdefine User initiated connection which has recently become idle. }
{ A connection should be marked as idle when it is no }
{ longer the user's current task. }
CONNMGR_PRIORITY_USERIDLE = $0800;
{ @constdefine Interactive user task which has been idle for an application }
{ specified time. The application should toggle the state }
{ between CONNMGR_PRIORITY_USERIDLE and CONNMGR_PRIORITY_USERINTERACTIVE as
the user }
{ uses the application. This helps ConnectionManager }
{ optimize responsiveness to the interactive application, }
{ while sharing the connection with background applications. }
CONNMGR_PRIORITY_HIPRIBKGND = $0200;
{ @constdefine High priority background connection }
CONNMGR_PRIORITY_IDLEBKGND = $0080;
{ @constdefine Idle priority background connection }
CONNMGR_PRIORITY_EXTERNALINTERACTIVE = $0020;
{ @constdefine Connection is requested on behalf of an external entity, but }
{ is an interactive session (e.g. AT Command Iterpreter) }
CONNMGR_PRIORITY_LOWBKGND = $0008;
{ @constdefine Lowest priority. Only connects if another higher priority
client is already using the same path. }
CONNMGR_PRIORITY_CACHED = $0002;
{ @constdefine Cached connection, reserved for internal use only. }
CONNMGR_PRIORITY_ALWAYS_ON = $0001;
{ @constdefine Always on connection, reserved for internal use only. }
{
----------------------------------------------------------------------------- }
{ }
{ @doc EXTERNAL }
{ }
{ @struct CONNMGR_CONNECTIONINFO | Information about connection request }
{ }
{ @comm None }
{ }
{
----------------------------------------------------------------------------- }
{ @field Size of this structure }
{ @field Valid parms, set of CONNMGR_PARAM_* }
{ @field Connection flags, set of CONNMGR_FLAG_* }
{ @field Priority, one of CONNMGR_PRIORITY_* }
{ @field Connection is exclusive, see comments }
{ @field Don't actually connect }
{ @field GUID of network to connect to }
{ @field hWnd to post status change messages to }
{ @field Msg to use when posting status changes }
{ @field lParam to use when posting status changes }
{ @field Max acceptable cost of connection }
{ @field Min acceptable receive bandwidth of connection }
{ @field Max acceptable connect latency }
type
_CONNMGR_CONNECTIONINFO = record
cbSize : DWORD;
dwParams : DWORD;
dwFlags : DWORD;
dwPriority : DWORD;
bExclusive : BOOL;
bDisabled : BOOL;
guidDestNet : GUID;
hWnd : HWND;
uMsg : UINT;
lParam : LPARAM;
ulMaxCost : ULONG;
ulMinRcvBw : ULONG;
ulMaxConnLatency : ULONG;
end;
CONNMGR_CONNECTIONINFO = _CONNMGR_CONNECTIONINFO;
{ @comm bExclusive: If false, the connection is shared among all
applications, and other }
{ applications with an interest in a connection to this network will be
notified that }
{ the connection is available. If true, then this connection can not be
shared with other }
{ applications, and no other applications will be notified, and any
application requesting }
{ a connection to the same network will be treated as a contender for }
{ the same resource, and not permitted to share the existing connection. A
decision will be made }
{ between this connection and the others based on connection priority. }
{
----------------------------------------------------------------------------- }
{ }
{ @doc EXTERNAL }
{ }
{ @func Creates a connection request. }
{ }
{ @comm Return Value: S_OK if success, error code otherwise }
{ }
{
----------------------------------------------------------------------------- }
{ @parm Params describing requested connection }
{ @parm Returned connection handle }
function ConnMgrEstablishConnection(var pConnInfo:CONNMGR_CONNECTIONINFO; var
phConnection:HANDLE):HRESULT;external External_library name
'ConnMgrEstablishConnection';
{
----------------------------------------------------------------------------- }
{ }
{ @doc EXTERNAL }
{ }
{ @func Creates a connection request. }
{ }
{ @comm Return Value: Same as ConnMgrEstablishConnection, but doesn't return
}
{ until connection has either been established or failed. }
{ }
{
----------------------------------------------------------------------------- }
{ @parm Params describing requested connection }
{ @parm Returned connection handle }
{ @parm Timeout }
{ @parm Final status value, one of CONNMGR_STATUS_* }
function ConnMgrEstablishConnectionSync(var pConnInfo:CONNMGR_CONNECTIONINFO;
var phConnection:HANDLE; dwTimeout:DWORD; var pdwStatus:DWORD):HRESULT;external
External_library name 'ConnMgrEstablishConnectionSync';
{
----------------------------------------------------------------------------- }
{ }
{ @doc EXTERNAL }
{ }
{ @constants Status values | Describes the current status of the connection }
{ }
{ @comm none }
{ }
{
----------------------------------------------------------------------------- }
const
CONNMGR_STATUS_UNKNOWN = $00; { @constdefine Unknown status }
CONNMGR_STATUS_CONNECTED = $10; { @constdefine Connection is up }
CONNMGR_STATUS_SUSPENDED = $11; { @constdefine Connection is up but
suspended }
CONNMGR_STATUS_DISCONNECTED = $20; { @constdefine Connection is
disconnected }
CONNMGR_STATUS_CONNECTIONFAILED = $21; { @constdefine Connection
failed and cannot not be reestablished }
CONNMGR_STATUS_CONNECTIONCANCELED = $22; { @constdefine User aborted
connection }
CONNMGR_STATUS_CONNECTIONDISABLED = $23; { @constdefine Connection is
ready to connect but disabled }
CONNMGR_STATUS_NOPATHTODESTINATION = $24; { @constdefine No path could
be found to destination }
CONNMGR_STATUS_WAITINGFORPATH = $25; { @constdefine Waiting for a path
to the destination }
CONNMGR_STATUS_WAITINGFORPHONE = $26; { @constdefine Voice call is in
progress }
CONNMGR_STATUS_PHONEOFF = $27; { @constdefine Phone resource needed
and phone is off }
CONNMGR_STATUS_EXCLUSIVECONFLICT = $28; { @constdefine the connection
could not be established because it would multi-home an exclusive connection }
CONNMGR_STATUS_NORESOURCES = $29; { @constdefine Failed to allocate
resources to make the connection. }
CONNMGR_STATUS_CONNECTIONLINKFAILED = $2A; { @constdefine Connection
link disconnected prematurely. }
CONNMGR_STATUS_AUTHENTICATIONFAILED = $2B; { @constdefine Failed to
authenticate user. }
CONNMGR_STATUS_NOPATHWITHPROPERTY = $2C; { @constdefine Path with
connection having requested property, ex. WAKE_ON_INCOMING, is not available. }
CONNMGR_STATUS_WAITINGCONNECTION = $40; { @constdefine Attempting to
connect }
CONNMGR_STATUS_WAITINGFORRESOURCE = $41; { @constdefine Resource is in
use by another connection }
CONNMGR_STATUS_WAITINGFORNETWORK = $42; { @constdefine Network is used
by higher priority thread or device is roaming. }
CONNMGR_STATUS_WAITINGDISCONNECTION = $80; { @constdefine Connection
is being brought down }
CONNMGR_STATUS_WAITINGCONNECTIONABORT = $81; { @constdefine Aborting
connection attempt }
{
----------------------------------------------------------------------------- }
{ }
{ @doc EXTERNAL }
{ }
{ @func Returns status about the current connection. }
{ }
{ @comm none }
{ }
{
----------------------------------------------------------------------------- }
{ @parm Handle to connection, returned from ConnMgrEstablishConnection }
{ @parm Returns current connection status, one of CONNMGR_STATUS_* }
function ConnMgrConnectionStatus(hConnection:HANDLE; var
pdwStatus:DWORD):HRESULT;external External_library name
'ConnMgrConnectionStatus';
{
----------------------------------------------------------------------------- }
{ }
{ @doc EXTERNAL }
{ }
{ @func Deletes specified connection request, potentially dropping the
physical connection. }
{ }
{ @comm none }
{ }
{
----------------------------------------------------------------------------- }
{ @parm Handle to connection, returned from ConnMgrEstablishConnection }
{ @parm ConnMgr can cache connection }
function ConnMgrReleaseConnection(hConnection:HANDLE;
lCache:LONG):HRESULT;external External_library name 'ConnMgrReleaseConnection';
{
----------------------------------------------------------------------------- }
{ }
{ @doc EXTERNAL }
{ }
{ @func Changes a connection's priority. }
{ }
{ @comm none }
{ }
{
----------------------------------------------------------------------------- }
{ @parm Handle to connection, returned from ConnMgrEstablishConnection }
{ @parm New priority }
function ConnMgrSetConnectionPriority(hConnection:HANDLE;
dwPriority:DWORD):HRESULT;external External_library name
'ConnMgrSetConnectionPriority';
{
----------------------------------------------------------------------------- }
{ }
{ @doc EXTERNAL }
{ }
{ @func General purpose (backdoor) API for exchanging information with
planner or providers. }
{ }
{ @comm none }
{ }
{
----------------------------------------------------------------------------- }
{ @parm Optional, Handle to connection }
(* Const before type ignored *)
{ @parm Provider GUID }
{ @parm Optional index, used to address multiple providers associated with
connection }
{ @parm General param 1 }
{ @parm General param 2 }
{ @param Pointer to params structure }
{ @param size of params structure }
function ConnMgrProviderMessage(hConnection:HANDLE; var pguidProvider:GUID;
pdwIndex:PDWORD; dwMsg1:DWORD; dwMsg2:DWORD;
pParams:PBYTE; cbParamSize:ULONG):HRESULT;external
External_library name 'ConnMgrProviderMessage';
const
CONNMGR_MAX_DESC = 128; { @constdefine Max size of a network
description }
{
----------------------------------------------------------------------------- }
{ }
{ @doc EXTERNAL }
{ }
{ @struct CONNMGR_DESTINATION_INFO | Information about a specific network }
{ }
{ @comm None }
{ }
{
----------------------------------------------------------------------------- }
{ @field GUID associated with network }
{ @field Description of network }
{ @field Is it OK to allow multi-homing on the network }
type
_CONNMGR_DESTINATION_INFO = record
guid : GUID;
szDescription : array[0..(CONNMGR_MAX_DESC)-1] of TCHAR;
fSecure : BOOL;
end;
CONNMGR_DESTINATION_INFO = _CONNMGR_DESTINATION_INFO;
{
----------------------------------------------------------------------------- }
{ }
{ @doc EXTERNAL }
{ }
{ @func Enumerates available networks. }
{ }
{ @comm none }
{ }
{
----------------------------------------------------------------------------- }
{ @param Index of network }
{ @param ptr to structure to fill in with info about network }
function ConnMgrEnumDestinations(nIndex:longint; var
pDestInfo:CONNMGR_DESTINATION_INFO):HRESULT;external External_library name
'ConnMgrEnumDestinations';
{
----------------------------------------------------------------------------- }
{ }
{ @doc EXTERNAL }
{ }
{ @struct SCHEDULEDCONNECTIONINFO | Information about a scheduled connection }
{ }
{ @comm None }
{ }
{
----------------------------------------------------------------------------- }
{ @field Guid of network }
{ @field Starting time, same ref as filetime }
{ @field Ending time, same ref as filetime }
{ @field Period between schedule attempts }
{ @field App name to execute when scheduled }
{ @field Cmd line to execute when scheduled }
{ @field Unique token identifying this scheduled connection }
{ @field If true, execute app whenever network is available }
type
_SCHEDULEDCONNECTIONINFO = record
guidDest : GUID;
uiStartTime : UINT64;
uiEndTime : UINT64;
uiPeriod : UINT64;
szAppName : array[0..(MAX_PATH)-1] of TCHAR;
szCmdLine : array[0..(MAX_PATH)-1] of TCHAR;
szToken : array[0..31] of TCHAR;
bPiggyback : BOOL;
end;
SCHEDULEDCONNECTIONINFO = _SCHEDULEDCONNECTIONINFO;
{
----------------------------------------------------------------------------- }
{ }
{ @doc EXTERNAL }
{ }
{ @func Registers a scheduled connection }
{ }
{ @comm none }
{ }
{
----------------------------------------------------------------------------- }
{ @param Ptr to struct describing scheduled connection }
function ConnMgrRegisterScheduledConnection(var
pSCI:SCHEDULEDCONNECTIONINFO):HRESULT;external External_library name
'ConnMgrRegisterScheduledConnection';
{
----------------------------------------------------------------------------- }
{ }
{ @doc EXTERNAL }
{ }
{ @func Unregisters a scheduled connection }
{ }
{ @comm none }
{ }
{
----------------------------------------------------------------------------- }
{ @param Token of scheduled connection to unregister }
function
ConnMgrUnregisterScheduledConnection(pwszToken:LPCTSTR):HRESULT;external
External_library name 'ConnMgrUnregisterScheduledConnection';
{
----------------------------------------------------------------------------- }
{ }
{ @doc EXTERNAL }
{ }
{ @func Maps a URL to a destination network GUID }
{ }
{ @comm none }
{ }
{
----------------------------------------------------------------------------- }
{ @parm URL to map }
{ @parm Returned network GUID }
{ @parm Index in table for next search }
function ConnMgrMapURL(pwszURL:LPCTSTR; var pguid:GUID; pdwIndex:
PDWORD):HRESULT;external External_library name 'ConnMgrMapURL';
{
----------------------------------------------------------------------------- }
{ }
{ @doc EXTERNAL }
{ }
{ @func Returns a handle to an event which becomes signaled when the ConnMgr
API }
{ is ready to be used. Caller is responsible for calling CloseHandle on the
returned event. }
{ }
{ @comm none }
{ }
{
----------------------------------------------------------------------------- }
function ConnMgrApiReadyEvent:HANDLE;external External_library name
'ConnMgrApiReadyEvent';
{
----------------------------------------------------------------------------- }
{ }
{ @doc EXTERNAL }
{ }
{ @constants Defines the type of a connection reference }
{ }
{ @comm none }
{ }
{
----------------------------------------------------------------------------- }
{ @constdefine NAP connection reference }
{ @constdefine PROXY connection reference }
type
_ConnMgrConRefTypeEnum = (ConRefType_NAP = 0,ConRefType_PROXY
);
ConnMgrConRefTypeEnum = _ConnMgrConRefTypeEnum;
{
----------------------------------------------------------------------------- }
{ }
{ @doc EXTERNAL }
{ }
{ @func Maps a connection reference to its corresponding GUID }
{ }
{ @comm none }
{ }
{
----------------------------------------------------------------------------- }
{ @parm Specify type of connection reference }
{ @parm Connection reference to map }
{ @parm Returned connection reference GUID }
function ConnMgrMapConRef(e:ConnMgrConRefTypeEnum; szConRef:LPCTSTR; var
pGUID:GUID):HRESULT;external External_library name 'ConnMgrMapConRef';
const
CMPROXY_PROXYSERVER_MAXSIZE = 256;
CMPROXY_USERNAME_MAXSIZE = 32;
CMPROXY_PASSWORD_MAXSIZE = 32;
CMPROXY_EXTRAINFO_MAXSIZE = 256;
CMPROXY_PROXYOVERRIDE_MAXSIZE = 64;
IID_ConnPrv_IProxyExtension: GUID = (D1: $af96b0bd; D2: $a481; D3: $482c;
D4: ($a0, $94, $a8, $44, $87, $67, $a0, $c0));
type
_PROXY_CONFIG = record
dwType : DWORD;
dwEnable : DWORD;
szProxyServer : array[0..(CMPROXY_PROXYSERVER_MAXSIZE)-1] of TCHAR;
szUsername : array[0..(CMPROXY_USERNAME_MAXSIZE)-1] of TCHAR;
szPassword : array[0..(CMPROXY_PASSWORD_MAXSIZE)-1] of TCHAR;
szProxyOverride : array[0..(CMPROXY_PROXYOVERRIDE_MAXSIZE)-1] of
TCHAR;
szExtraInfo : array[0..(CMPROXY_EXTRAINFO_MAXSIZE)-1] of TCHAR;
end;
PROXY_CONFIG = _PROXY_CONFIG;
{ TConnection }
TConnection = class
private
FPath: WideString;
FWithProxy: Boolean;
FhConnection: HANDLE; // Connection Manager Handle
FUseCache: Boolean; // should we cache this connection when we
'hangup'
FNetwork: GUID; // the GUID for the network we are connecting to.
FStatus: DWORD; // last connection status
FThreadStopEvent: HANDLE; // Event
FConnectionThread: HANDLE; // Thread
FProxyRequired: Boolean;
FProxyInfo: PROXY_CONFIG;
function CheckForRequiredProxy(hConn: HANDLE): Boolean;
function GetCorpNetPath: Widestring;
function GetInternetPath: Widestring;
function GetProxyServer: Widestring;
protected
function DoStatusUpdate(dwStatus: DWORD): HRESULT; virtual;
//
// Override these methods
//
//
// Called when we
//
function DoEstablishingConnection: HRESULT; virtual;
//
// Called when there was an error while connecting
// generally due to network connection not being available (no modem, no
nic etc).
//
function DoConnectingError: HRESULT; virtual;
//
// Called when a connection is now available.
//
function DoConnected: HRESULT; virtual;
//
// Called when the existing connection has been disconnected
// by another network request. we return E_FAIL to hangup here
//
function DoDisconnected: HRESULT; virtual;
//
// Called when we are waiting for the network to become available.
//
function DoWaitingForConnection: HRESULT; virtual;
//
// Called when we have released the connection
//
function DoReleaseConnection: HRESULT; virtual;
//
// Sets the network GUID from a path.
//
function GetNetworkFromPath(const sPath: Widestring): HRESULT;
//
// Thread proc
// Starts a connection to the network
//
function ConnectionThread: DWORD;
public
constructor Create;
destructor Destroy; override;
function IsAvailable(const sPath: Widestring = ''; bProxy: Boolean =
FALSE): HRESULT;
function AttemptConnect(const sPath: Widestring = ''; bProxy: Boolean
=FALSE ): HRESULT;
function HangupConnection: HRESULT;
function IsProxyRequired: Boolean;
property Connection: HANDLE read FhConnection;
property Status: DWORD read FStatus;
property UseCache: Boolean read FUseCache write FUseCache;
property NetworkGuid: GUID read FNetwork;
property WithProxy: Boolean read FWithProxy write FWithProxy;
property NetworkPath: WideString read FPath;
property ProxyServer: Widestring read GetProxyServer; //() { }
property InternetPath: Widestring read GetInternetPath;
property CorpNetPath: Widestring read GetCorpNetPath;
end;
implementation
// Rigged paths that will map to the correct GUID.
var
TConnection_InternetPath: Widestring;
TConnection_CorpNetPath: Widestring;
function SUCCEEDED(hr: HANDLE): Boolean; inline;
begin
Result:= hr >= 0;
end;
function FAILED(hr: HANDLE): Boolean; inline;
begin
Result:= hr < 0;
end;
{ TConnection }
function TConnection.CheckForRequiredProxy(hConn: HANDLE): Boolean;
begin
FProxyRequired:= False;
ZeroMemory(@FProxyInfo, sizeof(FProxyInfo));
FProxyInfo.dwType:= CONNMGR_FLAG_PROXY_HTTP;
if (SUCCEEDED(ConnMgrProviderMessage( hConn,
IID_ConnPrv_IProxyExtension,
nil,
0,
0,
PBYTE(@FProxyInfo),
sizeof(FProxyInfo))))
then begin
if (FProxyInfo.dwType = CONNMGR_FLAG_PROXY_HTTP)
then begin
FProxyRequired:= TRUE;
// SECURITY: Zero out the username/password from memory.
ZeroMemory(@FProxyInfo.szUsername, sizeof(FProxyInfo.szUsername));
ZeroMemory(@FProxyInfo.szPassword, sizeof(FProxyInfo.szPassword));
end;
end;
Result:= FProxyRequired;
end;
function TConnection.GetCorpNetPath: Widestring;
begin
Result:= TConnection_CorpNetPath;
end;
function TConnection.GetInternetPath: Widestring;
begin
Result:= TConnection_InternetPath;
end;
function TConnection.GetProxyServer: Widestring;
begin
if FProxyRequired then
Result:= FProxyInfo.szProxyServer
else
Result:= '';
end;
function TConnection.DoStatusUpdate(dwStatus: DWORD): HRESULT;
begin
Result:= S_OK;
if (dwStatus and CONNMGR_STATUS_DISCONNECTED <> 0)
then begin
if ( dwStatus <> CONNMGR_STATUS_DISCONNECTED ) then
Result:= DoConnectingError()
else
Result:= DoDisconnected();
UseCache:= dwStatus = CONNMGR_STATUS_DISCONNECTED;
end else if ( dwStatus = CONNMGR_STATUS_CONNECTED )
then begin
Result:= DoConnected();
end else if ( dwStatus and CONNMGR_STATUS_WAITINGCONNECTION <> 0)
then begin
Result:= DoWaitingForConnection();
end;
end;
function TConnection.DoEstablishingConnection: HRESULT;
begin
Result:= S_OK;
end;
function TConnection.DoConnectingError: HRESULT;
begin
Result:= E_FAIL;
end;
function TConnection.DoConnected: HRESULT;
begin
CheckForRequiredProxy(Connection);
Result:= S_OK;
end;
function TConnection.DoDisconnected: HRESULT;
begin
Result:= E_FAIL;
end;
function TConnection.DoWaitingForConnection: HRESULT;
begin
Result:= S_OK;
end;
function TConnection.DoReleaseConnection: HRESULT;
begin
Result:= S_OK;
end;
function TConnection.GetNetworkFromPath(const sPath: Widestring): HRESULT;
begin
if sPath <> ''
then begin
FPath:= sPath;;
end;
Result:= ConnMgrMapURL(PWideChar(sPath), FNetwork, nil);
end;
function s_ConnectionThread(pData: Pointer): DWORD;
begin
if TObject(pData) is TConnection then
Result:= TConnection(pData).ConnectionThread
else
Result:= -1;
end;
function TConnection.ConnectionThread: DWORD;
var
hThisThread: Handle;
ConnInfo: CONNMGR_CONNECTIONINFO;
hr: HRESULT;
hObjects: array[0..1] of HANDLE;
bStop: Boolean;
dwResult: DWORD;
const
cCacheTime: array[Boolean] of Integer = (0, 1);
begin
hThisThread:= FConnectionThread;
ZeroMemory(@ConnInfo, sizeof(ConnInfo));
ConnInfo.cbSize:= sizeof(ConnInfo);
ConnInfo.dwParams:= CONNMGR_PARAM_GUIDDESTNET;
if WithProxy then
ConnInfo.dwFlags:= CONNMGR_FLAG_PROXY_HTTP
else
ConnInfo.dwFlags:= 0;
ConnInfo.dwPriority:= CONNMGR_PRIORITY_USERINTERACTIVE ;
ConnInfo.guidDestNet:= NetworkGuid;
hr:= ConnMgrEstablishConnection(ConnInfo, FhConnection);
if FAILED( hr )
then begin
DoConnectingError();
UseCache:= FALSE;
end else begin
DoEstablishingConnection();
hObjects[0]:= FhConnection;
hObjects[1]:= FThreadStopEvent;
bStop:=FALSE;
ResetEvent(FThreadStopEvent);
while( bStop = FALSE )
do begin
case WaitForMultipleObjects( 2, @hObjects, FALSE, INFINITE) of
WAIT_OBJECT_0: begin
hr:= ConnMgrConnectionStatus(FhConnection, FStatus);
if( SUCCEEDED(hr))
then begin
if DoStatusUpdate(Status) <> S_OK then
bStop:= TRUE;
end else begin
FStatus:= hr;
bStop:= TRUE;
end;
end;
else begin // failures, or signalled to stop.
bStop:= TRUE;
ResetEvent(FThreadStopEvent);
end;
end;
end;
end;
DoReleaseConnection();
// Release the connection, caching if we should.
if( FhConnection <> 0 )
then begin
ConnMgrReleaseConnection(FhConnection, cCacheTime[UseCache]);
end;
CloseHandle(hThisThread);
Result:= Status;
end;
constructor TConnection.Create;
begin
FThreadStopEvent := CreateEvent(nil, FALSE, FALSE, nil);
FConnectionThread := 0;
FPath := '';
end;
destructor TConnection.Destroy;
begin
HangupConnection();
if( FThreadStopEvent <> 0 )
then begin
CloseHandle( FThreadStopEvent );
FThreadStopEvent:= 0;
end;
inherited Destroy;
end;
function TConnection.IsAvailable(const sPath: Widestring; bProxy: Boolean
): HRESULT;
var
bAvailable: Boolean;
hConn: HANDLE;
ci: CONNMGR_CONNECTIONINFO;
dwStatus: DWORD;
begin
Result:= GetNetworkFromPath(sPath);
WithProxy:= bProxy;
if (SUCCEEDED(Result))
then begin
bAvailable := FALSE;
hConn := 0;
ZeroMemory(@ci, sizeof(ci));
ci.cbSize := sizeof(ci);
ci.dwParams := CONNMGR_PARAM_GUIDDESTNET
or CONNMGR_PARAM_MAXCONNLATENCY;
if bProxy then ci.dwFlags:= CONNMGR_FLAG_PROXY_HTTP else ci.dwFlags:= 0;
ci.ulMaxConnLatency := 4000; // 4 second
ci.bDisabled := TRUE;
ci.dwPriority := CONNMGR_PRIORITY_USERINTERACTIVE;
ci.guidDestNet := NetworkGuid;
Result:= ConnMgrEstablishConnection(ci, hConn);
if (SUCCEEDED(Result))
then begin
case WaitForSingleObject(hConn, 400) of
WAIT_OBJECT_0: begin
if ( SUCCEEDED(ConnMgrConnectionStatus(hConn, dwStatus)) and
( (dwStatus = CONNMGR_STATUS_CONNECTED) or (dwStatus =
CONNMGR_STATUS_CONNECTIONDISABLED) ))
then begin
Result:= S_OK;
CheckForRequiredProxy(hConn);
end else begin
Result:= S_FALSE;
end;
end;
WAIT_TIMEOUT:
Result:= E_FAIL;
end;
ConnMgrReleaseConnection(hConn, 0);
end;
end;
end;
function TConnection.AttemptConnect(const sPath: Widestring; bProxy: Boolean
): HRESULT;
var
dwDummy: DWORD;
begin
Result:= GetNetworkFromPath(sPath);
WithProxy:= bProxy;
if ( FThreadStopEvent = 0 )
then begin
Result:= E_INVALIDARG;
exit;
end;
if( SUCCEEDED(Result) )
then begin
Result:= HangupConnection();
if( SUCCEEDED ( Result ))
then begin
// kick off new thread,
FConnectionThread := CreateThread(nil, 0, @s_ConnectionThread,
Pointer(self), 0, dwDummy);
if ( FConnectionThread = 0 ) then
Result:= E_FAIL;
end;
end;
end;
function TConnection.HangupConnection: HRESULT;
begin
if ( FConnectionThread <> 0 )
then begin
SetEvent(FThreadStopEvent);
//wait a few seconds at most for the thread to die
WaitForSingleObject(FConnectionThread, 3000);
FConnectionThread:= 0;
end;
Result:= S_OK;
end;
function TConnection.IsProxyRequired: Boolean;
begin
Result:= FProxyRequired;
end;
end.