Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1360 lines
38 KiB

/*****************************************************************************\
* MODULE: portmgr.cxx
*
* The module contains routines for handling the http port connection
* for internet priting
*
* Copyright (C) 1996-1998 Microsoft Corporation
*
* History:
* 22-Jul-1996 WeihaiC Created
*
\*****************************************************************************/
#include "precomp.h"
#include "priv.h"
// This the length used to fetch the authentication scheme. I don't see any reason
// that the authentication scheme could be longer.
#define MAX_SCHEME_LEN 255
CPortMgr::CPortMgr ():
// Put all the private member variable here
m_hSession (NULL),
m_hConnect (NULL),
m_lpszPassword (NULL),
m_lpszUserName (NULL),
m_lpszHostName (NULL),
m_lpszUri (NULL),
m_lpszPortName (NULL),
m_bPortCreate (FALSE),
m_bForceAuthSupported (TRUE), //We set it to be TRUE so that we will always try it.
m_pPortSettingMgr (NULL),
m_bSecure (FALSE),
m_nPort (0),
m_bValid (FALSE)
{
}
CPortMgr::~CPortMgr ()
{
LocalFree (m_lpszPassword);
LocalFree (m_lpszUserName);
LocalFree (m_lpszHostName);
LocalFree (m_lpszUri);
LocalFree (m_lpszPortName);
m_hSession = NULL;
m_hConnect = NULL;
}
HINTERNET
CPortMgr::_OpenRequest (
CAnyConnection *pConnection)
{
HINTERNET hReq = NULL;
if (pConnection && pConnection->OpenSession ()) {
if (pConnection->Connect (m_lpszHostName)) {
hReq = pConnection->OpenRequest (m_lpszUri);
}
}
return hReq;
}
BOOL
CPortMgr::_CloseRequest (
CAnyConnection *pConnection,
HINTERNET hReq)
{
BOOL bRet = FALSE;
if (pConnection->CloseRequest (hReq)) {
if (pConnection->Disconnect ()) {
bRet = pConnection->CloseSession();
}
}
return bRet;
}
/*****************************************************************************\
* Function: SendRequest
*
* This function is to send an IPP request to an established connection
*
* The intension of the function is to send the request with specified
* authentication instead of anonymous even if anonymous is enabled.
* The alogortihm is as following
* 1. If it is anonymous, just send the request and return
* 2. Otherwise,
* 3. If m_bForceAuthSupported, send ForceAuth to turn off anonymous, otherwise, goto 4
* 3.a. Issue Force Authentication
* 3.b. If the return value is 401 access denied, perform proper retry and return
* 3.c. Otherwise, (We don't get 401 access denied). If we get other errors, return FALSE
* 3.d. Check the IPP response of the Forth Authentication
* 3.e. If the IPP response is OK, we return TRUE
* 3.f. Otherwise, (Not Supported), we assume that the server does not
* support Force Authentication, so we marek m_bForceAuthSupported as FALSE
* and move on by returning a FALSE.
*
* 4. Send the real IPP request.
*
\*****************************************************************************/
BOOL
CPortMgr::_SendRequest (
CAnyConnection *pConnection,
HINTERNET hJobReq,
CStream *pStream)
{
BOOL bRet = FALSE;
DWORD cbData;
// Generate the Http header and indicate the size
// of the data we're sending.
//
if (pStream->GetTotalSize (&cbData) && cbData) {
DWORD dwLE = ERROR_SUCCESS;
DWORD dwAuthMethod = pConnection->GetAuthMethod ();
// We need to force authentication if the method is NTLM or others
if (m_bForceAuthSupported &&
( dwAuthMethod == AUTH_OTHER || dwAuthMethod == AUTH_NT)) {
HINTERNET hReq;
// Open a request and send force authentication IPP request
if (hReq = pConnection->OpenRequest (m_lpszUri)) {
bRet = _IppForceAuth (pConnection,
hReq,
m_lpszPortName,
&dwAuthMethod);
if (!bRet) {
dwLE = GetLastError ();
}
pConnection->CloseRequest (hReq);
}
if (m_bForceAuthSupported && !bRet && dwLE == ERROR_ACCESS_DENIED) {
// If forth authentication is supported but the server authentication fails, we return an error
DBG_MSG(DBG_LEV_ERROR, (TEXT("CPortMgr::_SendRequest : Failed (lasterror=%d)"), dwLE));
SetLastError (dwLE);
return bRet;
}
}
if (pConnection->SendRequest (hJobReq,
g_szContentType,
pStream)) {
bRet = TRUE;
}
else {
DBG_MSG(DBG_LEV_ERROR, (TEXT("CPortMgr::_SendRequest : pConnection->SendRequest Failed (lasterror=%d)"),
GetLastError ()));
}
}
return bRet;
}
BOOL
CPortMgr::ReadFile (
CAnyConnection *pConnection,
HINTERNET hReq,
LPVOID lpvBuffer,
DWORD cbBuffer,
LPDWORD lpcbRd)
{
BOOL bRet = FALSE;
if (m_bValid && pConnection) {
bRet = pConnection->ReadFile (hReq, lpvBuffer, cbBuffer, lpcbRd);
}
return bRet;
}
/*****************************************************************************\
* _IppForceAuthRsp (Local Callback Routine)
*
* Retrieves a forth-authentication response from the IPP server
*
\*****************************************************************************/
BOOL
CPortMgr::_IppForceAuthRsp(
CAnyConnection *pConnection,
HINTERNET hReq,
LPARAM lParam)
{
HANDLE hIpp;
DWORD dwRet;
DWORD cbRd;
LPBYTE lpDta;
DWORD cbDta;
LPIPPRET_PRN lpRsp;
DWORD cbRsp;
BYTE bBuf[MAX_IPP_BUFFER];
BOOL bRet = FALSE;
if (hIpp = WebIppRcvOpen(IPP_RET_FORCEAUTH)) {
while (TRUE) {
cbRd = 0;
if (pConnection->ReadFile (hReq, (LPVOID)bBuf, sizeof(bBuf), &cbRd) && cbRd) {
dwRet = WebIppRcvData(hIpp, bBuf, cbRd, (LPBYTE*)&lpRsp, &cbRsp, &lpDta, &cbDta);
switch (dwRet) {
case WEBIPP_OK:
if (!lpRsp) {
SetLastError (ERROR_INVALID_DATA);
}
else if ((bRet = lpRsp->bRet) == TRUE)
// This is from our server. We have already had the authentication
// established
bRet = TRUE;
else
SetLastError(lpRsp->dwLastError);
WebIppFreeMem(lpRsp);
goto EndValRsp;
case WEBIPP_MOREDATA:
// Need to do another read to fullfill our header-response.
//
break;
default:
DBG_MSG(DBG_LEV_ERROR, (TEXT("CPortMgr::_IppForceAuthRsp Err : Receive Data Error (dwRet=%d, LE=%d)"),
dwRet, WebIppGetError(hIpp)));
SetLastError(ERROR_INVALID_DATA);
goto EndValRsp;
}
} else {
goto EndValRsp;
}
}
EndValRsp:
WebIppRcvClose(hIpp);
} else {
SetLastError(ERROR_OUTOFMEMORY);
}
return bRet;
}
BOOL
CPortMgr::_IppForceAuth (
CAnyConnection *pConnection,
HINTERNET hReq,
LPCTSTR lpszPortName,
PDWORD pdwAuthMethod)
{
LPIPPREQ_GETPRN pgp;
REQINFO ri;
DWORD dwRet;
LPBYTE lpIpp;
DWORD cbIpp;
DWORD dwLE = ERROR_SUCCESS;
BOOL bRet = FALSE;
DWORD dwAuthMethod = pConnection->GetAuthMethod ();
if (pgp = WebIppCreateGetPrnReq(0, lpszPortName)) {
// Convert the request to IPP, and perform the
// post.
//
ZeroMemory(&ri, sizeof(REQINFO));
ri.cpReq = CP_UTF8;
ri.idReq = IPP_REQ_FORCEAUTH;
ri.fReq[0] = IPP_REQALL;
ri.fReq[1] = IPP_REQALL;
dwRet = WebIppSndData(IPP_REQ_FORCEAUTH,
&ri,
(LPBYTE)pgp,
pgp->cbSize,
&lpIpp,
&cbIpp);
// The request-structure has been converted
// to IPP format, so it is ready to go to
// the server.
//
//
if (dwRet == WEBIPP_OK) {
bRet = pConnection->SendRequest (hReq, g_szContentType, cbIpp, lpIpp);
if (!bRet) {
// Check if it is an access denied or some other error
dwLE = GetLastError();
if (dwLE == ERROR_ACCESS_DENIED && dwAuthMethod == AUTH_UNKNOWN) {
CHAR szAuthScheme[MAX_SCHEME_LEN];
static CHAR szNTLM[] = "NTLM";
static CHAR szKerbero[] = "Kerbero";
static CHAR szNegotiate[] = "Negotiate";
if (pConnection->GetAuthSchem (hReq, szAuthScheme, MAX_SCHEME_LEN)) {
// We've got the scheme
if (! (*szAuthScheme)) {
// It does not have authentication enabled, only Anonymous is supported
*pdwAuthMethod = AUTH_ANONYMOUS;
}
if (strstr (szAuthScheme, szNTLM) ||
strstr (szAuthScheme, szKerbero) ||
strstr (szAuthScheme, szNegotiate)) {
// We have authentication scheme that can authentication with no
// popup, let's use it.
*pdwAuthMethod = AUTH_NT;
}
else {
// We have an authentications scheme, but we need to popup for username
// and password
*pdwAuthMethod = AUTH_OTHER;
}
bRet = TRUE;
}
}
}
else {
// It means somehow, either the authentication is done,
// or we get unsupported operation
bRet = _IppForceAuthRsp(pConnection, hReq, 0L);
if (!bRet) {
// the response from the server does not seem to be OK, so
// we mark m_bForceAuthSupported as FALSE so that we will not
// send the ForceAuth request to the server again.
m_bForceAuthSupported = FALSE;
}
if (bRet && dwAuthMethod == AUTH_UNKNOWN) {
// The authentication is done, so let's use NTLM authentication
*pdwAuthMethod = AUTH_NT;
}
// else degrade to old logic
}
WebIppFreeMem(lpIpp);
}
WebIppFreeMem(pgp);
}
if (dwLE == ERROR_INVALID_DATA) {
dwLE = ERROR_INVALID_PRINTER_NAME;
}
if ((bRet == FALSE) && (dwLE != ERROR_SUCCESS))
SetLastError(dwLE);
return bRet;
}
BOOL
CPortMgr::_ForceAuth (
CAnyConnection *pConnection,
LPCTSTR lpszPortName,
LPTSTR lpszHost,
LPTSTR lpszUri,
PDWORD pdwAuthMethod)
{
HINTERNET hReq;
DWORD dwLE = ERROR_SUCCESS;
BOOL bRet = FALSE;
if (pConnection->OpenSession()) {
if (pConnection->Connect (lpszHost)) {
// Make the request.
//
if (hReq = pConnection->OpenRequest (lpszUri)) {
// If request handle is established, then all
// is OK so far.
//
bRet = _IppForceAuth (pConnection,
hReq,
lpszPortName,
pdwAuthMethod);
dwLE = GetLastError();
pConnection->CloseRequest (hReq);
}
pConnection->Disconnect ();
}
pConnection->CloseSession ();
}
if ((bRet == FALSE) && (dwLE != ERROR_SUCCESS))
SetLastError(dwLE);
return bRet;
}
/*****************************************************************************\
* _IppValRsp (Local Callback Routine)
*
* Retrieves a get-printer-attributes response from the IPP server
*
\*****************************************************************************/
BOOL
CPortMgr::_IppValRsp(
CAnyConnection *pConnection,
HINTERNET hReq,
LPARAM lParam)
{
HANDLE hIpp;
DWORD dwRet;
DWORD cbRd;
LPBYTE lpDta;
DWORD cbDta;
LPIPPRET_PRN lpRsp;
DWORD cbRsp;
BYTE bBuf[MAX_IPP_BUFFER];
BOOL bRet = FALSE;
if (hIpp = WebIppRcvOpen(IPP_RET_GETPRN)) {
while (TRUE) {
cbRd = 0;
if (pConnection->ReadFile (hReq, (LPVOID)bBuf, sizeof(bBuf), &cbRd) && cbRd) {
dwRet = WebIppRcvData(hIpp, bBuf, cbRd, (LPBYTE*)&lpRsp, &cbRsp, &lpDta, &cbDta);
switch (dwRet) {
case WEBIPP_OK:
if (!lpRsp) {
SetLastError (ERROR_INVALID_DATA);
}
else if ((bRet = lpRsp->bRet) == FALSE)
SetLastError(lpRsp->dwLastError);
WebIppFreeMem(lpRsp);
goto EndValRsp;
case WEBIPP_MOREDATA:
// Need to do another read to fullfill our header-response.
//
break;
default:
DBG_MSG(DBG_LEV_ERROR, (TEXT("CPortMgr::_IppValRsp - Err : Receive Data Error (dwRet=%d, LE=%d)"),
dwRet, WebIppGetError(hIpp)));
SetLastError(ERROR_INVALID_DATA);
goto EndValRsp;
}
} else {
goto EndValRsp;
}
}
EndValRsp:
WebIppRcvClose(hIpp);
} else {
SetLastError(ERROR_OUTOFMEMORY);
}
return bRet;
}
BOOL
CPortMgr::_IppValidate (
CAnyConnection *pConnection,
HINTERNET hReq,
LPCTSTR lpszPortName)
{
LPIPPREQ_GETPRN pgp;
REQINFO ri;
DWORD dwRet;
LPBYTE lpIpp;
DWORD cbIpp;
DWORD dwLE = ERROR_SUCCESS;
BOOL bRet = FALSE;
if (pgp = WebIppCreateGetPrnReq(0, lpszPortName)) {
// Convert the request to IPP, and perform the
// post.
//
ZeroMemory(&ri, sizeof(REQINFO));
ri.cpReq = CP_UTF8;
ri.idReq = IPP_REQ_GETPRN;
ri.fReq[0] = IPP_REQALL;
ri.fReq[1] = IPP_REQALL;
dwRet = WebIppSndData(IPP_REQ_GETPRN,
&ri,
(LPBYTE)pgp,
pgp->cbSize,
&lpIpp,
&cbIpp);
// The request-structure has been converted
// to IPP format, so it is ready to go to
// the server.
//
//
if (dwRet == WEBIPP_OK) {
CMemStream *pStream = new CMemStream (lpIpp, cbIpp);
if (pStream) {
bRet = _SendRequest (pConnection, hReq, pStream);
delete pStream;
}
if (bRet)
bRet = _IppValRsp(pConnection, hReq, 0L);
if (!bRet) {
dwLE = GetLastError();
}
WebIppFreeMem(lpIpp);
}
WebIppFreeMem(pgp);
}
if (dwLE == ERROR_INVALID_DATA) {
dwLE = ERROR_INVALID_PRINTER_NAME;
}
if ((bRet == FALSE) && (dwLE != ERROR_SUCCESS))
SetLastError(dwLE);
return bRet;
}
BOOL
CPortMgr::_CheckConnection (
CAnyConnection *pConnection,
LPCTSTR lpszPortName,
LPTSTR lpszHost,
LPTSTR lpszUri)
{
HINTERNET hReq;
DWORD dwLE = ERROR_SUCCESS;
BOOL bRet = FALSE;
if (pConnection->OpenSession()) {
if (pConnection->Connect (lpszHost)) {
// Make the request.
//
if (hReq = pConnection->OpenRequest (lpszUri)) {
// If request handle is established, then all
// is OK so far.
//
bRet = _IppValidate (pConnection,
hReq,
lpszPortName);
dwLE = GetLastError();
pConnection->CloseRequest (hReq);
}
pConnection->Disconnect ();
}
pConnection->CloseSession ();
}
if ((bRet == FALSE) && (dwLE != ERROR_SUCCESS))
SetLastError(dwLE);
return bRet;
}
BOOL
CPortMgr::CheckConnection (void)
{
HINTERNET hReq;
BOOL bRet = FALSE;
DWORD dwLE = ERROR_SUCCESS;
CAnyConnection *pConnection = NULL;
DBG_MSG(DBG_LEV_CALLTREE, (TEXT("Enter CheckConnection")));
if (m_bValid) {
pConnection = _GetCurrentConnection ();
if (hReq = _OpenRequest (pConnection)) {
bRet = _IppValidate (pConnection,
hReq,
m_lpszPortName);
if (!bRet) {
dwLE = GetLastError();
}
_CloseRequest (pConnection, hReq);
}
if (pConnection) {
delete pConnection;
}
if (!bRet && dwLE != ERROR_SUCCESS) {
DBG_MSG(DBG_LEV_ERROR, (TEXT("CPortMgr::CheckConnection : Failed (lasterror=%d)"), dwLE));
SetLastError (dwLE);
}
}
else
SetLastError (ERROR_INVALID_HANDLE);
DBG_MSG(DBG_LEV_CALLTREE, (TEXT("Leave CheckConnection ret=%d, lasterror=%d"), bRet, GetLastError ()));
return bRet;
}
/*****************************************************************************\
* Function: Create
*
* This function is to establish the network connection with the given port name
*
* The intension of the function is to establish a network connection with
* authentication instead of anonymous. The alogortihm is as following
* 1. Try Anonymous
* 2. If anonymous connection is NOT possible, go to step 5
* 3. Try Force Authentication (Call _ForceAuth)
* 3.a. Issue Force Authentication
* 3.b. If the return value is 401 access denied, we start to check the
* authentication scheme, otherwise, mark m_dwAuthMethod
* as AUTH_ANONYMOUS and return TRUE
* 3.c. If either NTLM, Kerbero or Negotiate is in the scheme, we mark
* m_dwAuthMethod as AUTH_NT
* Otherwise, we mark it as AUTH_OTHER
* return TRUE
* 3.d. (We don't get 401 access denied). If we get other errors, return FALSE
* 3.e. Check the IPP response of the Forth Authentication
* 3.f. If the IPP response is OK, we know we have established authentication
* (This should not happen in the first time, but will happen afterward)
* but we will mark m_dwAuthMethod as AUTH_NT anyway and return TRUE.
* 3.g. Otherwise, (Not Supported), we assume that the server does not
* support Force Authentication, so we move on by returning a FALSE.
*
* 4. If it returns OK, we start to use the authentication method indicated
* in m_dwAuthMethod
* 5. Try NTLM or other no-popup authentication
* 6. Try Other popup authentications
*
* If the connection is established, the function returns TRUE.
*
\*****************************************************************************/
BOOL
CPortMgr::Create (
LPCTSTR lpszPortName)
{
LPTSTR lpszHost = NULL;
LPTSTR lpszShare = NULL;
INTERNET_PORT nPort;
CAnyConnection *pConnection = NULL;
BOOL bRet = FALSE;
DWORD dwLE = 0;
BOOL bDone;
BOOL bSecure;
BOOL bAnonymous = FALSE;
DWORD dwAuthMethod;
// Try to find out if the server can be accessed without going
// through Proxy Server
//
if ( utlParseHostShare(lpszPortName,
&lpszHost,
&lpszShare,
&nPort,
&bSecure)) {
bDone = ! (AssignString (m_lpszHostName, lpszHost) &&
AssignString (m_lpszUri, lpszShare) &&
AssignString (m_lpszPortName, lpszPortName));
m_bSecure = bSecure;
m_nPort = nPort;
// Set the flag to indicate it is creation time.
//
m_bPortCreate = TRUE;
// Try connect and the get the proxy
if (!bDone) {
// We don't care about if the reset succeeded or not
EndBrowserSession ();
}
// Try anonymous with/without proxy
if (!bDone && (pConnection = new CAnonymousConnection (bSecure, nPort, FALSE))
&& pConnection->IsValid ()) {
bDone = TRUE;
if (_CheckConnection(pConnection, lpszPortName, lpszHost, lpszShare)) {
bAnonymous = TRUE;
}
else {
dwLE = GetLastError ();
if (dwLE == ERROR_INTERNET_NAME_NOT_RESOLVED) {
// The server name is wrong, reset tht last error
// to invalid printer name
//
SetLastError (ERROR_INVALID_PRINTER_NAME);
}
else if (dwLE == HTTP_STATUS_FORBIDDEN) {
SetLastError (ERROR_ACCESS_DENIED);
}
else if (dwLE != ERROR_INVALID_PRINTER_NAME)
bDone = FALSE; // Cont to the next mode
}
if (bAnonymous) {
// We've got an anonymous authentication
if (_ForceAuth(pConnection, lpszPortName, lpszHost, lpszShare, &dwAuthMethod)) {
// We've got an authentication method
if (dwAuthMethod != AUTH_ANONYMOUS) {
bDone = FALSE;
SetLastError (ERROR_ACCESS_DENIED);
if (dwAuthMethod == AUTH_OTHER) {
bDone = TRUE;
//weihaic goto TryOther;
}
}
else
bRet = TRUE;
}
else {
// We've got anonymous, and the serve does not support FORCE_AUTH
// so let us use it.
dwAuthMethod = AUTH_ANONYMOUS;
bRet = TRUE;
}
}
}
// You must have got access denied in this case
// Let's try again without any password, it will work if the server has NTLM/Kerbero enabled.
//
if (!bDone && GetLastError () == ERROR_ACCESS_DENIED) {
if (pConnection) {
delete (pConnection);
pConnection = NULL;
}
bDone = TRUE;
if ( (pConnection = new CNTConnection (bSecure, nPort, FALSE) )
&& pConnection->IsValid ()) {
if (_CheckConnection(pConnection, lpszPortName, lpszHost, lpszShare)) {
dwAuthMethod = AUTH_NT;
bRet = TRUE;
}
else {
dwLE = GetLastError ();
if (dwLE != ERROR_INVALID_PRINTER_NAME)
bDone = FALSE; // Cont to the next mode
}
}
}
if (!bDone && GetLastError () == ERROR_ACCESS_DENIED && bAnonymous) {
// We know that anonymous is enabled, so let us degrade the connection to anonymous
if (pConnection) {
delete (pConnection);
pConnection = NULL;
}
// We must reset m_dwAuthMethod since when we try other authentication
// m_dwAuthMethod is set to AUTH_OTHER, if we do not reset the value
// when we try to send request to the server, it will fail with access
// denied.
//
dwAuthMethod = AUTH_UNKNOWN;
if (!bDone && (pConnection = new CAnonymousConnection (bSecure, nPort, FALSE))
&& pConnection->IsValid ()) {
bDone = TRUE;
if (_CheckConnection(pConnection, lpszPortName, lpszHost, lpszShare)) {
bRet = TRUE;
dwAuthMethod = AUTH_ANONYMOUS;
}
}
}
}
// Exit point
//
// We need to create the port at first if we get access denied
// then users can configure the port using a different user name
// and password
//
if (!bRet && GetLastError () == ERROR_ACCESS_DENIED) {
//
// Force anonymous connection. This will fail anyway.
//
dwAuthMethod = AUTH_ACCESS_DENIED;
bRet = TRUE;
}
if (bRet) {
m_bValid = TRUE;
m_pPortSettingMgr = new CPortConfigDataMgr (lpszPortName);
if (m_pPortSettingMgr && m_pPortSettingMgr->bValid ()) {
CPortConfigData ConfigData;
ConfigData.SetAuthMethod (dwAuthMethod);
bRet = m_pPortSettingMgr->SetPerPortSettings (ConfigData);
}
else
bRet = FALSE;
}
if (lpszHost) {
memFreeStr (lpszHost);
}
if (lpszShare) {
memFreeStr (lpszShare);
}
if (!bRet) {
// Clean up the connection class
if (pConnection) {
delete (pConnection);
pConnection = NULL;
}
if (GetLastError () != ERROR_ACCESS_DENIED) {
// Invalid Printer Name
// The NT router expects inetpp to returen ERROR_INVALID_NAME,
// if we return ERROR_INVALID_PRINTER_NAME, the router will return
// this error back to the user
//
SetLastError (ERROR_INVALID_NAME);
}
}
m_bPortCreate = FALSE;
return bRet;
}
BOOL
CPortMgr::ConfigurePort (
PINET_XCV_CONFIGURATION pXcvConfigurePortReqData,
PINET_CONFIGUREPORT_RESPDATA pXcvAddPortRespData,
DWORD cbSize,
PDWORD cbSizeNeeded)
{
LPTSTR lpszHost = NULL;
LPTSTR lpszShare = NULL;
INTERNET_PORT nPort;
CAnyConnection *pConnection = NULL;
BOOL bRet = FALSE;
DWORD dwLE = 0;
BOOL bDone;
BOOL bSecure;
BOOL bAnonymous = FALSE;
CPortConfigData OldConfigData;
LPCTSTR pPassword = NULL;
// Reset everything
EndBrowserSession ();
//
// We must retry force authentication when configuration changes
//
m_bForceAuthSupported = TRUE;
BOOL bIgnoreSecurityDlg = pXcvConfigurePortReqData->bIgnoreSecurityDlg;
DWORD dwAuthMethod = pXcvConfigurePortReqData->dwAuthMethod;
switch (dwAuthMethod) {
case AUTH_ANONYMOUS:
pConnection = new CAnonymousConnection (m_bSecure, m_nPort, bIgnoreSecurityDlg);
break;
case AUTH_NT:
pConnection = new CNTConnection (m_bSecure, m_nPort, bIgnoreSecurityDlg);
break;
case AUTH_OTHER:
if (m_pPortSettingMgr->GetCurrentSettings (&OldConfigData))
pPassword = OldConfigData.GetPassword();
pPassword = (pXcvConfigurePortReqData->bPasswordChanged)?pXcvConfigurePortReqData->szPassword:pPassword;
pConnection = new COtherConnection (m_bSecure, m_nPort,
pXcvConfigurePortReqData->szUserName,
pPassword,
bIgnoreSecurityDlg);
default:
break;
}
if (pConnection && pConnection->IsValid()) {
if (_CheckConnection(pConnection, m_lpszPortName, m_lpszHostName, m_lpszUri)) {
bRet = TRUE;
}
else {
dwLE = GetLastError ();
if (dwLE == ERROR_INTERNET_NAME_NOT_RESOLVED) {
// The server name is wrong, reset tht last error
// to invalid printer name
//
SetLastError (ERROR_INVALID_PRINTER_NAME);
}
else if (dwLE == HTTP_STATUS_FORBIDDEN) {
SetLastError (ERROR_ACCESS_DENIED);
}
else if (dwLE != ERROR_INVALID_PRINTER_NAME)
SetLastError (dwLE);
}
}
// Exit point
if (bRet) {
m_bValid = TRUE;
CPortConfigData ConfigData;
bRet = ConfigData.SetAuthMethod (dwAuthMethod);
if (bRet) {
if (dwAuthMethod == AUTH_OTHER) {
bRet = ConfigData.SetUserName (pXcvConfigurePortReqData->szUserName) &&
ConfigData.SetPassword (pPassword);
}
else
bRet = ConfigData.SetUserName(NULL) && ConfigData.SetPassword(NULL);
if (bRet) {
bRet = m_pPortSettingMgr->SetPerUserSettings (ConfigData);
}
if (bRet && pXcvConfigurePortReqData->bSettingForAll)
bRet = m_pPortSettingMgr->SetPerPortSettings (ConfigData);
}
}
return bRet;
}
BOOL
CPortMgr::GetCurrentConfiguration (
PINET_XCV_CONFIGURATION pXcvConfiguration)
{
CPortConfigData ConfigData;
ZeroMemory (pXcvConfiguration, sizeof (INET_XCV_CONFIGURATION));
m_pPortSettingMgr->GetCurrentSettings (&ConfigData);
pXcvConfiguration->dwVersion = 1;
pXcvConfiguration->dwAuthMethod = ConfigData.GetAuthMethod ();
if (pXcvConfiguration->dwAuthMethod == AUTH_OTHER) {
if (ConfigData.GetUserName()) {
StringCchCopy(pXcvConfiguration->szUserName, COUNTOF(pXcvConfiguration->szUserName), ConfigData.GetUserName());
}
}
pXcvConfiguration->bIgnoreSecurityDlg = ConfigData.GetIgnoreSecurityDlg();
return TRUE;
}
BOOL
CPortMgr::Init (
LPCTSTR lpszPortName)
{
LPTSTR lpszHost = NULL;
LPTSTR lpszShare = NULL;
INTERNET_PORT nPort;
BOOL bRet = FALSE;
BOOL bSecure = FALSE;
if ( utlParseHostShare(lpszPortName,
&lpszHost,
&lpszShare,
&nPort,
&bSecure)) {
m_pPortSettingMgr = new CPortConfigDataMgr (lpszPortName);
if (m_pPortSettingMgr && m_pPortSettingMgr->bValid ()) {
bRet = TRUE;
}
}
if (bRet) {
m_bValid = TRUE;
m_bSecure = bSecure;
m_nPort = nPort;
bRet = AssignString (m_lpszHostName, lpszHost) &&
AssignString (m_lpszUri, lpszShare) &&
AssignString (m_lpszPortName, lpszPortName);
}
if (lpszHost) {
memFreeStr (lpszHost);
}
if (lpszShare) {
memFreeStr (lpszShare);
}
return bRet;
}
BOOL
CPortMgr::Remove (void)
{
if (m_pPortSettingMgr) {
m_pPortSettingMgr->DeleteAllSettings ();
}
return TRUE;
}
CAnyConnection *
CPortMgr::_GetCurrentConnection ()
{
CPortConfigData ConfigData;
CAnyConnection *pConnection = NULL;
if (m_pPortSettingMgr->GetCurrentSettings (&ConfigData)) {
switch (ConfigData.GetAuthMethod ()) {
case AUTH_ANONYMOUS:
pConnection = new CAnonymousConnection (m_bSecure, m_nPort, ConfigData.GetIgnoreSecurityDlg());
break;
case AUTH_NT:
pConnection = new CNTConnection (m_bSecure, m_nPort, ConfigData.GetIgnoreSecurityDlg());
break;
case AUTH_OTHER:
pConnection = new COtherConnection (m_bSecure, m_nPort,
ConfigData.GetUserName(), ConfigData.GetPassword(),
ConfigData.GetIgnoreSecurityDlg());
break;
case AUTH_ACCESS_DENIED:
SetLastError (ERROR_ACCESS_DENIED);
break;
default:
SetLastError (ERROR_INVALID_HANDLE);
break;
}
}
else {
DBG_MSG(DBG_LEV_ERROR, (TEXT("_GetCurrentConnection - Err GetCurrentSettings failed (LE=%d)"), GetLastError ()));
SetLastError (ERROR_INVALID_HANDLE);
}
return pConnection;
}
BOOL
CPortMgr::SendRequest(
PCINETMONPORT pIniPort,
LPBYTE lpIpp,
DWORD cbIpp,
IPPRSPPROC pfnRsp,
LPARAM lParam)
{
BOOL bRet = FALSE;
CMemStream *pStream;
pStream = new CMemStream (lpIpp, cbIpp);
if (pStream && pStream->bValid ()){
bRet = SendRequest (pIniPort, pStream, pfnRsp, lParam);
}
if (pStream) {
delete pStream;
}
return bRet;
}
BOOL
CPortMgr::SendRequest(
PCINETMONPORT pIniPort,
CStream *pStream,
IPPRSPPROC pfnRsp,
LPARAM lParam)
{
HINTERNET hReq;
DWORD dwLE = ERROR_SUCCESS;
BOOL bRet = FALSE;
if (m_bValid) {
CAnyConnection * pConnection;
pConnection = _GetCurrentConnection ();
if (pConnection) {
hReq = _OpenRequest (pConnection);
// If succeeded, then build the content-length-header.
//
if (hReq) {
bRet = _SendRequest (pConnection, hReq, pStream);
if (bRet)
bRet = (pfnRsp ? (*pfnRsp)(pConnection, hReq, pIniPort, lParam) : TRUE);
dwLE = GetLastError();
_CloseRequest (pConnection, hReq);
}
}
else
dwLE = GetLastError ();
if ((bRet == FALSE) && (dwLE != ERROR_SUCCESS)) {
if (dwLE == HTTP_STATUS_FORBIDDEN) {
SetLastError (ERROR_ACCESS_DENIED);
}
else
SetLastError(dwLE);
}
}
else {
SetLastError (ERROR_INVALID_HANDLE);
}
return bRet;
}
DWORD
CPortMgr::IncreaseUserRefCount(
CLogonUserData *pUser)
/*++
Routine Description:
Increase the Ref Count for the current user in the Port Manager.
Arguments:
pUser - The user that we want to increment the RefCount for.
Return Value:
The current refcount for the user, or MAXDWORD if the user could not be found.
--*/
{
CLogonUserData *pPortUser = NULL;
CLogonUserData *pNewUser = NULL;
DWORD dwRefCount = MAXDWORD;
DBG_ASSERT( pUser , (TEXT("CPortMgr::IncreaseUserRefCount - pUser is NULL.")) );
DBG_ASSERT( pUser->bValid(), (TEXT("CPortMgr::IncreaseUserRefCount - pUser is invalid.")) );
m_UserList.Lock(); // We need to be sure only one CurUser is considered per port per time.
if (pPortUser = m_UserList.Find( pUser )) {
// We have found the port user, increment their refcount.
dwRefCount = pPortUser->IncRefCount();
DBG_MSG(DBG_LEV_INFO,
(TEXT("Info: IncRef to (%d), User (%p)"), dwRefCount, pPortUser ) );
} else {
pNewUser = new CLogonUserData; // A new user automatically has a ref-count of 1.
if (pNewUser != NULL) {
*pNewUser = *pUser; // Assign data across
if (!pNewUser->bValid() ||
!m_UserList.Insert( pNewUser )) {
delete pNewUser;
pNewUser = NULL;
SetLastError( ERROR_INVALID_PARAMETER );
} else
dwRefCount = 1;
}
}
m_UserList.Unlock();
return dwRefCount;
}
CLogonUserData*
CPortMgr::GetUserIfLastDecRef(
CLogonUserData *pUser)
/*++
Routine Description:
This routine finds the reference count for the current user. If the reference count is
zero we return a pointer to the user, otherwise we return NULL. This will be used by
the Cache Manager to invalid the cache for the particular user.
NOTE: Caller must Free the pUser.
Arguments:
None
Return Value:
A pointer to the user if their RefCount has gone to Zero, NULL otherwise.
--*/
{
CLogonUserData *pPortUser = NULL;
CLogonUserData *pNewUser = NULL;
DWORD dwRefCount;
DBG_ASSERT( pUser , (TEXT("CPortMgr::GetUserIfLastDecRef - pUser is NULL.")) );
DBG_ASSERT( pUser->bValid(), (TEXT("CPortMgr::GetUserIfLastDecRef - pUser is invalid.")) );
m_UserList.Lock();
if (pPortUser = m_UserList.Find( pUser )) {
// We have found the port user, increment their refcount.
// Make sure that two threads aren't handling the RefCount at the same
// time
dwRefCount = pPortUser->DecRefCount();
DBG_MSG(DBG_LEV_INFO,
(TEXT("Info: DecRef to (%d), User (%p)"), dwRefCount, pPortUser ) );
if (dwRefCount == 0) {
pNewUser = new CLogonUserData;
if (pNewUser != NULL) {
*pNewUser = *pPortUser;
}
m_UserList.Delete( pPortUser ); // We don't need him in the list anymore
}
}
m_UserList.Unlock();
return pNewUser;
}