/*****************************************************************************\ * 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; }