postagnt.cpp
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 32k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. // 
  2. // Pei-Hwa Lin (peiwhal), Feb 3, 1997
  3. //
  4. #include "private.h"
  5. #include "downld.h"
  6. #include "urlmon.h"
  7. #undef TF_THISMODULE
  8. #define TF_THISMODULE   TF_POSTAGENT
  9. // Advanced inetcpl setting to disable channel logging
  10. const TCHAR c_szNoChannelLogging[] = TEXT("NoChannelLogging");
  11. const char c_szHeaders[] = "Content-Type: application/x-www-form-urlencodedrn";
  12. #define c_ccHearders  (ARRAYSIZE(c_szHeaders) - 1)
  13. #define ENCODE_LOG
  14. #ifdef ENCODE_LOG
  15. const char c_szEncodeHeader[] = "Content-Transfer-Encoding: x-";
  16. #define c_ccEncodeHeader (ARRAYSIZE(c_szEncodeHeader) - 1)
  17. #endif  //ENCODE_LOG
  18. // *** W3C extended log format *** //
  19. // text strings definitions
  20. const char c_szUrlFields[] = "#Fields: s-URI";
  21. #define c_ccUrlFields  (ARRAYSIZE(c_szUrlFields) - 1)
  22. const char c_szLogFields[] = "#Fields: x-context x-cache x-date x-time x-duration x-meta";
  23. #define c_ccLogFields  (ARRAYSIZE(c_szLogFields) - 1);
  24. // *** W3C extended log format *** //
  25. const TCHAR c_szPostRetryReg[] = TEXT("PostRetry");
  26. const TCHAR c_szUserAgent[] = TEXT("User Agent");
  27. extern TCHAR szInternetSettings[];
  28. //-----------------------------------------------------------------------------
  29. //
  30. // CTrackingStg implementation
  31. //
  32. //-----------------------------------------------------------------------------
  33. // this will empty log contents without removing the entry
  34. //
  35. HRESULT CTrackingStg::EmptyCacheEntry(GROUPID enumId)
  36. {
  37.     HANDLE      hEnum, hFile;
  38.     LPINTERNET_CACHE_ENTRY_INFOA lpCE = NULL;
  39.     DWORD       cbSize;
  40.     HRESULT     hr = S_OK;
  41.     ASSERT(enumId);
  42.     lpCE = (LPINTERNET_CACHE_ENTRY_INFOA)MemAlloc(LPTR, MY_MAX_CACHE_ENTRY_INFO);
  43.     if (!lpCE)
  44.         return E_OUTOFMEMORY;
  45.     cbSize = MY_MAX_CACHE_ENTRY_INFO;
  46.     hEnum = FindFirstUrlCacheEntryExA(_lpPfx,
  47.                                      0,              //dwFlags
  48.                                      URLCACHE_FIND_DEFAULT_FILTER,  //dwFilters,
  49.                                      0,             //enumId, IE50:wininet change, not support group in extensible cache
  50.                                      lpCE,
  51.                                      &cbSize,
  52.                                      NULL, NULL, NULL);
  53.     if (hEnum)
  54.     {
  55.         FILETIME    ftModified;
  56.         ftModified.dwHighDateTime = (DWORD)(enumId >> 32);
  57.         ftModified.dwLowDateTime = (DWORD)(0x00000000ffffffff & enumId);
  58.         for(;;)
  59.         {
  60.             if (lpCE->LastModifiedTime.dwLowDateTime == ftModified.dwLowDateTime &&
  61.                 lpCE->LastModifiedTime.dwHighDateTime == ftModified.dwHighDateTime)
  62.             {
  63.                 hFile = OpenItemLogFile(lpCE->lpszLocalFileName);
  64.                 if (hFile != INVALID_HANDLE_VALUE)
  65.                 {
  66.                     CloseHandle(hFile);
  67.                     DeleteFileA(lpCE->lpszLocalFileName);
  68.                     DeleteUrlCacheEntryA(lpCE->lpszSourceUrlName);
  69.                     
  70.                     TCHAR   szUrl[INTERNET_MAX_URL_LENGTH];
  71.                     SHAnsiToTChar(lpCE->lpszSourceUrlName, szUrl, ARRAYSIZE(szUrl));
  72.                     CreateLogCacheEntry(szUrl, lpCE->ExpireTime,
  73.                                          ftModified, lpCE->CacheEntryType);
  74.                 }
  75.             }
  76.             
  77.             // reuse lpCE
  78.             if (!FindNextUrlCacheEntryExA(hEnum, lpCE, &cbSize, NULL, NULL, NULL))
  79.             {
  80.                 if (GetLastError() == ERROR_NO_MORE_ITEMS)
  81.                     break;
  82.             }
  83.         }
  84.         FindCloseUrlCache(hEnum);
  85.     }
  86.     SAFELOCALFREE(lpCE);
  87.     return hr;
  88. }
  89. // this will delete url cache entries 
  90. // and delete url cache group
  91. HRESULT CTrackingStg::RemoveCacheEntry(GROUPID enumId)
  92. {
  93.     HANDLE      hEnum;
  94.     LPINTERNET_CACHE_ENTRY_INFOA lpCE = NULL;
  95.     DWORD       cbSize;
  96.     PROPVARIANT vProp = {0};
  97.     HRESULT     hr = S_OK;
  98.     ASSERT(enumId);
  99.     lpCE = (LPINTERNET_CACHE_ENTRY_INFOA)MemAlloc(LPTR, MY_MAX_CACHE_ENTRY_INFO);
  100.     if (!lpCE)
  101.         return E_OUTOFMEMORY;
  102.     cbSize = MY_MAX_CACHE_ENTRY_INFO;
  103.     hEnum = FindFirstUrlCacheEntryExA(_lpPfx,
  104.                                      0,              //dwFlags
  105.                                      URLCACHE_FIND_DEFAULT_FILTER,   //dwFilters,
  106.                                      0,              //enumId, IE50: wininet change
  107.                                      lpCE,
  108.                                      &cbSize,
  109.                                      NULL, NULL, NULL);
  110.     if (hEnum)
  111.     {
  112.         FILETIME    ftModified;
  113.         ftModified.dwHighDateTime = (DWORD)(enumId >> 32);
  114.         ftModified.dwLowDateTime = (DWORD)(0x00000000ffffffff & enumId);
  115.         for(;;)
  116.         {
  117.             if (lpCE->LastModifiedTime.dwLowDateTime == ftModified.dwLowDateTime &&
  118.                 lpCE->LastModifiedTime.dwHighDateTime == ftModified.dwHighDateTime)
  119.             {
  120.                 DeleteUrlCacheEntryA(lpCE->lpszSourceUrlName);
  121.                 vProp.vt = VT_UI4;
  122.                 vProp.ulVal = 0;            // clear tracking flag
  123.                 TCHAR szUrl[INTERNET_MAX_URL_LENGTH];
  124.                 SHAnsiToTChar(lpCE->lpszSourceUrlName+lstrlenA(_lpPfx), szUrl, ARRAYSIZE(szUrl));
  125.                 hr = IntSiteHelper(szUrl,
  126.                                    &c_rgPropRead[PROP_TRACKING], &vProp, 1, TRUE);
  127.                 PropVariantClear( &vProp );        
  128.             }
  129.             
  130.             // reuse lpCE
  131.             if (!FindNextUrlCacheEntryExA(hEnum, lpCE, &cbSize, NULL, NULL, NULL))
  132.             {
  133.                 if (GetLastError() == ERROR_NO_MORE_ITEMS)
  134.                     break;
  135.             }
  136.         }
  137.         FindCloseUrlCache(hEnum);
  138.     }
  139.     SAFELOCALFREE(lpCE);
  140.     return hr;
  141. }
  142. HANDLE CTrackingStg::OpenItemLogFile(LPCSTR lpFile)
  143. {
  144.    HANDLE   hFile = NULL;
  145.     hFile = CreateFileA(lpFile, 
  146.                 GENERIC_READ | GENERIC_WRITE,
  147.                 0,                              //no sharing
  148.                 NULL,
  149.                 OPEN_EXISTING,
  150.                 FILE_ATTRIBUTE_NORMAL,
  151.                 NULL);
  152.     return hFile;
  153. }
  154. DWORD CTrackingStg::ReadLogFile(LPCSTR lpFile, LPSTR* lplpbuf)
  155. {
  156.     HANDLE  hFile = NULL;
  157.     DWORD   cbFile = 0;
  158.     DWORD   cbRead;
  159.     hFile = OpenItemLogFile(lpFile);
  160.     if (hFile == INVALID_HANDLE_VALUE) 
  161.         return 0;
  162.     cbFile = GetFileSize(hFile, NULL);
  163.     if (cbFile == 0xFFFFFFFF)
  164.     {
  165.         CloseHandle(hFile);
  166.         return 0;
  167.     }
  168.         
  169.     *lplpbuf = (LPSTR)MemAlloc(LPTR, (cbFile + 2) * sizeof(CHAR));
  170.     cbRead = 0;
  171.     if (!ReadFile(hFile, *lplpbuf, cbFile, &cbRead, NULL))
  172.     {
  173.         cbRead = 0;
  174.     }    
  175.         
  176.     ASSERT((cbRead == cbFile));
  177.     CloseHandle(hFile);
  178.     return cbRead;
  179. }
  180. void CTrackingStg::AppendLogEntries(LPINTERNET_CACHE_ENTRY_INFOA lpce)
  181. {
  182.     LPSTR  lpbuf = NULL;
  183.     DWORD   cbsize, cbWritten;
  184.     
  185.     cbsize = ReadLogFile(lpce->lpszLocalFileName, &lpbuf);
  186.     cbWritten = 0;
  187.     if (lpbuf && (cbsize > c_ccEmptyLog))   //change this threshold if modify
  188.     {                                       //CreatePrefixedCacheEntry in trkcache.cpp
  189.         AppendLogUrlField(lpce);            
  190.         WriteFile(_hLogFile, lpbuf, cbsize, &cbWritten, NULL);
  191.         ASSERT((cbsize == cbWritten));
  192.     }
  193.     SAFELOCALFREE(lpbuf);
  194.     
  195.     return;
  196. }
  197. void CTrackingStg::AppendLogUrlField(LPINTERNET_CACHE_ENTRY_INFOA lpce)
  198. {
  199.     DWORD dwWritten = 0;
  200.     LPSTR lpbuf = NULL;
  201.     DWORD cb;
  202.     // lpce->lpszSourcesUrlName contains prefixed string
  203.     DWORD cchAlloc = lstrlenA(lpce->lpszSourceUrlName) - lstrlenA(_lpPfx) + c_ccUrlFields 
  204.                         + c_ccLogFields;
  205.     cb = (cchAlloc + 7) * sizeof(CHAR);
  206.     lpbuf = (LPSTR)MemAlloc(LPTR, cb);
  207.     if (lpbuf)
  208.     {
  209.         wnsprintfA(lpbuf, cb, "%srn%srn%srn", c_szUrlFields, 
  210.                  lpce->lpszSourceUrlName+lstrlenA(_lpPfx), c_szLogFields);
  211.         WriteFile(_hLogFile, lpbuf, lstrlenA(lpbuf), &dwWritten, NULL);
  212.     }
  213.     
  214.     SAFELOCALFREE(lpbuf);
  215.     return;
  216. }
  217. HRESULT CTrackingStg::Enumeration(LONGLONG enumId)
  218. {
  219.     HRESULT hr = E_FAIL;
  220.     HANDLE  hEnum;
  221.     LPINTERNET_CACHE_ENTRY_INFOA lpCE = NULL;
  222.     lpCE = (LPINTERNET_CACHE_ENTRY_INFOA)MemAlloc(LPTR, MY_MAX_CACHE_ENTRY_INFO);
  223.     if (!lpCE)
  224.         return E_OUTOFMEMORY;
  225.     DWORD   cbSize = MY_MAX_CACHE_ENTRY_INFO;
  226.     hEnum = FindFirstUrlCacheEntryExA(_lpPfx,
  227.                                     0,              //dwFlags
  228.                                     URLCACHE_FIND_DEFAULT_FILTER,              //dwFilters,
  229.                                     0,              //enumId, IE50: wininet change, not support group in extensible cache
  230.                                     lpCE,
  231.                                     &cbSize,
  232.                                     NULL, NULL, NULL);
  233.     if (hEnum)
  234.     {
  235.         FILETIME    ftModified;
  236.     
  237.         ftModified.dwHighDateTime = (DWORD)(enumId >> 32);
  238.         ftModified.dwLowDateTime = (DWORD)(0x00000000ffffffff & enumId);
  239.         for(;;)
  240.         {
  241.             if (!StrCmpNIA(lpCE->lpszSourceUrlName, _lpPfx, lstrlenA(_lpPfx))
  242.                 && lpCE->LastModifiedTime.dwLowDateTime == ftModified.dwLowDateTime 
  243.                 && lpCE->LastModifiedTime.dwHighDateTime == ftModified.dwHighDateTime)
  244.             {    
  245.                 AppendLogEntries(lpCE);
  246.             }
  247.             
  248.             // reuse lpCE
  249.             cbSize = MY_MAX_CACHE_ENTRY_INFO;
  250.             if (!FindNextUrlCacheEntryExA(hEnum, lpCE, &cbSize, NULL, NULL, NULL))
  251.             {
  252.                 if (GetLastError() == ERROR_NO_MORE_ITEMS)
  253.                     break;
  254.             }
  255.         }
  256.         FindCloseUrlCache(hEnum);
  257.         hr = S_OK;
  258.     }
  259.     SAFELOCALFREE(lpCE);
  260.     return hr;
  261. }
  262. HRESULT CTrackingStg::RetrieveLogData(ISubscriptionItem* pCDFItem)
  263. {
  264.     HRESULT hr = E_FAIL;
  265.     // heck: wininet does not support multiple groups to same URL
  266.     // have to enumerate new and old groups to cover
  267.     GROUPID newId;
  268.     ReadLONGLONG(pCDFItem, c_szTrackingCookie, &newId);
  269.     if (newId)
  270.     {
  271.         hr = Enumeration(newId);
  272.     }
  273.     // heck: end
  274.     hr = Enumeration(_groupId);
  275.     CloseLogFile();
  276.     return hr;
  277. }
  278. HRESULT CTrackingStg::RetrieveAllLogStream(ISubscriptionItem* pCDFItem, LPCSTR lpFile)
  279. {
  280.     HRESULT hr = E_FAIL;
  281.     LPTSTR  lpPfx = ReadTrackingPrefix();
  282. #ifdef UNICODE
  283.     if (lpPfx)
  284.     {
  285.         int len = lstrlenW(lpPfx) + 1;
  286.         
  287.         _lpPfx = (LPSTR)MemAlloc(LPTR, len * sizeof(CHAR));
  288.         if (_lpPfx)
  289.         {
  290.             SHUnicodeToAnsi(lpPfx, _lpPfx, len);
  291.         }
  292.         MemFree(lpPfx);
  293.     }
  294. #else
  295.     _lpPfx = lpPfx;
  296. #endif
  297.     _hLogFile = CreateFileA(lpFile, 
  298.                 GENERIC_WRITE,
  299.                 0,                              //no sharing
  300.                 NULL,
  301.                 CREATE_ALWAYS,
  302.                 FILE_ATTRIBUTE_NORMAL,
  303.                 NULL);
  304.     if (_hLogFile == INVALID_HANDLE_VALUE)      //turn-around is read into a buffer.
  305.         return hr;
  306.     hr = RetrieveLogData(pCDFItem);
  307.     return S_OK;    
  308. }
  309. //  
  310. //  Validate the Posting by
  311. //  1. attempt to post this log does not exceed limits set in registry
  312. //  2. the log itself is valid
  313. //
  314. BOOL CTrackingStg::IsExpired(ISubscriptionItem* pItem)
  315. {
  316.     BOOL    bret;
  317.     DWORD   regRetry = 3;   // Intelligent default so we don't need the registry value set.
  318.         
  319.     ReadRegValue(HKEY_LOCAL_MACHINE, MY_WEBCHECK_POST_REG,
  320.                      c_szPostRetryReg, (void *)&regRetry, sizeof(regRetry));
  321.                      
  322.     bret = (_dwRetry < regRetry) ? FALSE : TRUE;
  323.     if (bret) return bret;
  324.     // read the purgetime from subscription property bag
  325.     DATE        dt = 0.0;
  326.     if (SUCCEEDED(ReadDATE(pItem, c_szPostPurgeTime, &dt)) && dt != 0)
  327.     {
  328.         SYSTEMTIME  st, expiredst;
  329.         FILETIME    ft, expiredft;
  330.         VariantTimeToSystemTime(dt, &expiredst);
  331.         SystemTimeToFileTime(&expiredst, &expiredft);
  332.         GetLocalTime(&st);
  333.         SystemTimeToFileTime(&st, &ft);
  334.         bret = (CompareFileTime(&ft, &expiredft) > 0) ? TRUE : FALSE;
  335.     }
  336.     return bret;
  337. }
  338. CTrackingStg::CTrackingStg
  339. (
  340. )
  341. {
  342.     _pwszURL = NULL;
  343.     _groupId = 0;
  344.     _dwRetry = 0;
  345.     _lpPfx = NULL;
  346. }
  347. CTrackingStg::~CTrackingStg()
  348. {
  349.     //
  350.     // Release/delete any resources
  351.     //
  352.     DBG("CTrackingStg d'tor");
  353.     SAFEFREEOLESTR(_pwszURL);
  354.     SAFELOCALFREE(_lpPfx);
  355.     
  356.     if (_hLogFile)
  357.         CloseHandle(_hLogFile);
  358. }
  359. //------------------------------------------------------------
  360. //
  361. // Private member functions
  362. //
  363. //------------------------------------------------------------
  364. #if 0
  365. void CALLBACK CWCPostAgent::PostCallback
  366. (
  367.     HINTERNET hInternet,
  368.     DWORD     dwContext,
  369.     DWORD     dwInternetStatus,
  370.     LPVOID    lpvStatusInfo,
  371.     DWORD     dwInfoLen
  372. )
  373. {
  374.     DWORD dwLen;
  375.     TraceMsg(TF_THISMODULE, "PostAgent Callback: of %d (looking for 31)", dwContext);
  376.     if ( (dwInternetStatus == INTERNET_STATUS_REQUEST_SENT) && 
  377.          (dwLen == (DWORD)lpvStatusInfo) )
  378.     {
  379.         OnUploadComplete();
  380.     }
  381.     else
  382.         UpdateStatus();
  383. }
  384. #endif
  385. //------------------------------------------------------------
  386. //
  387. //  CWCPostAgent implementation
  388. //
  389. //------------------------------------------------------------
  390. //------------------------------------------------------------
  391. // virtual functions overriding CDeliveryAgent
  392. //------------------------------------------------------------
  393. ISubscriptionMgr2 *
  394. CWCPostAgent::GetSubscriptionMgr()
  395. {
  396.     ISubscriptionMgr2* pSubsMgr=NULL;
  397.     CoCreateInstance(CLSID_SubscriptionMgr, NULL, CLSCTX_INPROC_SERVER,
  398.                     IID_ISubscriptionMgr2, (void**)&pSubsMgr);
  399.     return pSubsMgr;
  400. }
  401. //
  402. // Re-stamp a set of tracking URLs from old group to new group
  403. // without losing logging data
  404. //
  405. void
  406. CWCPostAgent :: MergeGroupOldToNew()
  407. {
  408.     GROUPID newId;
  409.     HANDLE  hEnum;
  410.     LPINTERNET_CACHE_ENTRY_INFO lpCE = NULL;
  411.     DWORD   cbSize;
  412.     LPTSTR  lpPfx = NULL;
  413.     newId = 0;
  414.     ReadLONGLONG(_pCDFItem, c_szTrackingCookie, &newId);
  415.     if (!newId && !_pUploadStream->_groupId)
  416.         return;
  417.     
  418.     ASSERT(newId);
  419.     lpCE = (LPINTERNET_CACHE_ENTRY_INFO)MemAlloc(LPTR, MY_MAX_CACHE_ENTRY_INFO);
  420.     if (!lpCE)
  421.     {
  422.         SetLastError(ERROR_OUTOFMEMORY);
  423.         return;
  424.     }
  425.     lpPfx = ReadTrackingPrefix();
  426.     if (!lpPfx)
  427.         return;
  428.     cbSize = MY_MAX_CACHE_ENTRY_INFO;
  429.     hEnum = FindFirstUrlCacheEntryEx(lpPfx,
  430.                                     0,              //dwFlags
  431.                                     URLCACHE_FIND_DEFAULT_FILTER,              //dwFilters,
  432.                                     0,              //_pUploadStream->_groupId, IE50 changed
  433.                                     lpCE,
  434.                                     &cbSize,
  435.                                     NULL, NULL, NULL);
  436.     if (hEnum)
  437.     {
  438.         FILETIME    ftModified, ftOld;
  439.         ftModified.dwHighDateTime = (DWORD)(newId >> 32);
  440.         ftModified.dwLowDateTime = (DWORD)(0x00000000ffffffff & newId);
  441.         ftOld.dwHighDateTime = (DWORD)(_pUploadStream->_groupId >> 32);
  442.         ftOld.dwLowDateTime = (DWORD)(0x00000000ffffffff & _pUploadStream->_groupId);
  443.         for(;;)
  444.         {
  445.             if (!StrCmpNI(lpCE->lpszSourceUrlName, lpPfx, lstrlen(lpPfx))
  446.                 && lpCE->LastModifiedTime.dwLowDateTime == ftOld.dwLowDateTime 
  447.                 && lpCE->LastModifiedTime.dwHighDateTime == ftOld.dwHighDateTime)
  448.             {
  449.                 // commit changes to url cache
  450.                 lpCE->LastModifiedTime.dwHighDateTime = ftModified.dwHighDateTime;
  451.                 lpCE->LastModifiedTime.dwLowDateTime = ftModified.dwLowDateTime;
  452.                 
  453.                 SetUrlCacheEntryInfo(lpCE->lpszSourceUrlName, lpCE, CACHE_ENTRY_MODTIME_FC);
  454.             }
  455.             // reuse lpCE
  456.             cbSize = MY_MAX_CACHE_ENTRY_INFO;
  457.             if (!FindNextUrlCacheEntryEx(hEnum, lpCE, &cbSize, NULL, NULL, NULL))
  458.             {
  459.                 if (GetLastError() == ERROR_NO_MORE_ITEMS)
  460.                     break;
  461.             }
  462.         }
  463.         FindCloseUrlCache(hEnum);
  464.     }
  465.     SAFELOCALFREE(lpCE);
  466.     return;
  467. }
  468. HRESULT CWCPostAgent::InitRequest
  469. (
  470.     LPCSTR lpszVerb
  471. )
  472. {
  473.     char    hostName[INTERNET_MAX_HOST_NAME_LENGTH+1];
  474.     char    userName[INTERNET_MAX_USER_NAME_LENGTH+1];
  475.     char    password[INTERNET_MAX_PASSWORD_LENGTH+1];
  476.     char    urlPath[INTERNET_MAX_PATH_LENGTH+1];
  477.     URL_COMPONENTSA     uc;
  478.     BOOL    bRet;
  479.     LPSTR   pszPostURL;
  480.     int     iLen;
  481.     TCHAR   pszUA[128];
  482.     HRESULT hr = E_FAIL;
  483.     if ( !_pUploadStream->_pwszURL )
  484.         return S_OK;             //do nothing if post url doesn't exist
  485.     iLen = lstrlenW(_pUploadStream->_pwszURL) + 1;
  486.     pszPostURL = new CHAR[iLen];
  487.     if (!pszPostURL)
  488.         return E_OUTOFMEMORY;
  489.     SHUnicodeToAnsi(_pUploadStream->_pwszURL, pszPostURL, iLen);
  490.     memset(&uc, 0, sizeof(URL_COMPONENTS));
  491.     uc.dwStructSize = sizeof(URL_COMPONENTS);
  492.     uc.lpszHostName = hostName;
  493.     uc.dwHostNameLength = sizeof(hostName);
  494.     uc.nPort = INTERNET_INVALID_PORT_NUMBER;
  495.     uc.lpszUserName = userName;
  496.     uc.dwUserNameLength = sizeof(userName);
  497.     uc.lpszPassword = password;
  498.     uc.dwPasswordLength = sizeof(password);
  499.     uc.lpszUrlPath = urlPath;
  500.     uc.dwUrlPathLength = sizeof(urlPath);
  501.     
  502.     bRet = InternetCrackUrlA(pszPostURL, lstrlenA(pszPostURL), 
  503.                             ICU_DECODE, &uc);
  504.     if (!bRet)
  505.     {
  506.         DBG("InternetCrackUrl failed");
  507.         goto _exitInit;
  508.     }
  509.     // read User Agent string
  510.     if (!ReadRegValue(HKEY_CURRENT_USER, szInternetSettings, c_szUserAgent, pszUA, sizeof(pszUA)))
  511.         StrCpy(pszUA, TEXT("PostAgent"));
  512.     _hSession = InternetOpen(pszUA,                  // used in User-Agent: header 
  513.                             INTERNET_OPEN_TYPE_PRECONFIG,  //INTERNET_OPEN_TYPE_DIRECT, 
  514.                             NULL,
  515.                             NULL, 
  516.                             //INTERNET_FLAG_ASYNC);  
  517.                             0);         //synchronous operation
  518.     if ( !_hSession )
  519.     {
  520.         DBG("!_hSession");
  521.         goto _exitInit;
  522.     }
  523.     _hHttpSession = InternetConnectA(_hSession, 
  524.                                     uc.lpszHostName,    //"peihwalap", 
  525.                                     uc.nPort,           //INTERNET_INVALID_PORT_NUMBER,
  526.                                     uc.lpszUserName,    //NULL, 
  527.                                     uc.lpszPassword,    //NULL, 
  528.                                     INTERNET_SERVICE_HTTP, 
  529.                                     INTERNET_FLAG_KEEP_CONNECTION, 
  530.                                     0); 
  531.                                     //(DWORD)this); //dwContext.
  532. //    InternetSetStatusCallback(m_hSession, CWCPostAgent::PostCallback);
  533.                                 
  534.     if ( !_hHttpSession )
  535.     {
  536.         DBG( "!_hHttpSession");
  537.         CloseRequest();
  538.         goto _exitInit;
  539.     }                                    
  540.     
  541.     // ignore security problem
  542.     _hHttpRequest = HttpOpenRequestA(_hHttpSession, lpszVerb, 
  543.                                     uc.lpszUrlPath,
  544.                                     HTTP_VERSIONA, 
  545.                                     NULL,                             //lpszReferer
  546.                                     NULL,                             //lpszAcceptTyypes
  547.                                     //INTERNET_FLAG_IGNORE_CERT_CN_INVALID |
  548.                                     //INTERNET_FLAG_IGNORE_CERT_DATE_INVALID |
  549.                                     //INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS |
  550.                                     //INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP |
  551.                                     INTERNET_FLAG_NO_COOKIES, 
  552.                                     0);
  553.                                     //(DWORD)this); //dwContext
  554.                             
  555.     if ( !_hHttpRequest )
  556.     {
  557.         DBG_WARN("Post Agent: !_hHttpRequest");
  558.         CloseRequest();
  559.         goto _exitInit;
  560.     }
  561.     else
  562.         hr = S_OK;
  563. _exitInit:
  564.     delete [] pszPostURL;
  565.     return hr;
  566.     
  567. }                                                                
  568.     
  569. HRESULT CWCPostAgent::SendRequest
  570. (
  571.     LPCSTR     lpszHeaders,
  572.     LPDWORD    lpdwHeadersLength,
  573.     LPCSTR     lpszOption,
  574.     LPDWORD    lpdwOptionLength
  575. )
  576. {
  577.     BOOL bRet=FALSE;
  578.     HttpAddRequestHeadersA(_hHttpRequest, 
  579.                            (LPCSTR)c_szHeaders, 
  580.                            (DWORD)-1L, 
  581.                            HTTP_ADDREQ_FLAG_ADD);
  582.     if (lpszHeaders && *lpszHeaders)        // don't bother if it's empty
  583.         bRet = HttpAddRequestHeadersA(_hHttpRequest, 
  584.                           (LPCSTR)lpszHeaders, 
  585.                           *lpdwHeadersLength, 
  586.                           HTTP_ADDREQ_FLAG_ADD | HTTP_ADDREQ_FLAG_REPLACE);
  587. /*
  588.     bRet = HttpSendRequest(_hHttpRequest, 
  589.                           (LPCTSTR)lpszHeaders,           //HEADER_ENCTYPE, 
  590.                           *lpdwHeadersLength,              //sizeof(HEADER_ENCTYPE), 
  591.                           (LPVOID)lpszOption, 
  592.                           *lpdwOptionLength);
  593. */
  594.     bRet = HttpSendRequest(_hHttpRequest, 
  595.                           NULL,                            //HEADER_ENCTYPE, 
  596.                           0,                               //sizeof(HEADER_ENCTYPE), 
  597.                           (LPVOID)lpszOption, 
  598.                           *lpdwOptionLength);
  599.     if ( !bRet )
  600.     {
  601.         DWORD dwLastError = GetLastError();
  602.         TraceMsg(TF_ERROR, "HttpSendRequest failed: Error = %lx", dwLastError);
  603.         DBG_WARN("Post Agent: HttpSendRequest failed");
  604.         return E_FAIL;
  605.     }
  606.     DWORD dwBuffLen;
  607.     TCHAR buff[1024];
  608.     dwBuffLen = sizeof(buff);
  609.     bRet = HttpQueryInfo(_hHttpRequest,
  610.                         //HTTP_QUERY_CONTENT_TYPE,  //HTTP_QUERY_REQUEST_METHOD,
  611.                         HTTP_QUERY_STATUS_CODE,   //HTTP_QUERY_RAW_HEADERS,
  612.                         buff,
  613.                         &dwBuffLen,
  614.                         NULL);
  615.  
  616.     //verify request response here
  617.     //
  618.     int iretcode = StrToInt(buff);
  619.     if (iretcode == 200)   // || iretcode == 100)   //HTTP_STATUS_OK
  620.         return S_OK;             //100: too many semaphors
  621.                                  //501: required not supported
  622.                                  //502: bad gateway
  623.     return E_FAIL;
  624.     
  625. }                                                                
  626. HRESULT CWCPostAgent::CloseRequest
  627. (
  628.     void
  629. )
  630. {
  631.     InternetCloseHandle(_hSession);
  632.     _hSession = _hHttpSession = _hHttpRequest = 0;
  633.     return S_OK;
  634. }
  635. // Called if upload failed
  636. //   just increase retry number
  637. HRESULT CWCPostAgent::OnPostFailed()
  638. {
  639.     WriteDWORD(_pCDFItem, c_szPostingRetry, _pUploadStream->_dwRetry+1);
  640.     MergeGroupOldToNew();
  641.     return S_OK;
  642. }
  643. // Called if upload succeeded
  644. //   1) remove PostUrl from item
  645. //   2) delete tracking cache entry  (Doh!)
  646. HRESULT CWCPostAgent::OnPostSuccess()
  647. {
  648.     GROUPID newId = 0;
  649.     if (!_pCDFItem)
  650.         return E_INVALIDARG;
  651.     ReadLONGLONG(_pCDFItem, c_szTrackingCookie, &newId);
  652.     _pUploadStream->RemoveCacheEntry(_pUploadStream->_groupId);
  653.     if (newId == _pUploadStream->_groupId)
  654.     {
  655.         BSTR  bstrURL = NULL;
  656.         ReadBSTR(_pCDFItem, c_szTrackingPostURL, &bstrURL);
  657.         if (!StrCmpIW(bstrURL, _pUploadStream->_pwszURL))
  658.         {
  659.             WriteOLESTR(_pCDFItem, c_szTrackingPostURL, bstrURL);
  660.         }
  661.         SAFEFREEBSTR(bstrURL);
  662.     }
  663.     else
  664.         _pUploadStream->EmptyCacheEntry(newId);
  665.     return S_OK;
  666. }
  667. HRESULT
  668. CWCPostAgent::FindCDFStartItem()
  669. {
  670.     IServiceProvider    *pSP;
  671.     
  672.     if (_pCDFItem)
  673.         return S_OK;
  674.     
  675.     if (SUCCEEDED(m_pAgentEvents->QueryInterface(IID_IServiceProvider, (void **)&pSP)) && pSP)
  676.     {
  677.         pSP->QueryService(CLSID_ChannelAgent, IID_ISubscriptionItem, (void **)&_pCDFItem);
  678.         pSP->Release();
  679.     }
  680.     if (NULL == _pCDFItem)
  681.     {
  682.         TraceMsg(TF_THISMODULE, "PostAgent : FindCDFStartItem failed");
  683.     }
  684.     return (_pCDFItem) ? S_OK : E_NOINTERFACE;
  685. }
  686. HRESULT CWCPostAgent::DoFileUpload()
  687. {
  688.     HRESULT hr;
  689.     DWORD   dwLen, dwHdr;
  690.     SAFELOCALFREE(_pszPostStream);
  691.     dwLen = _pUploadStream->ReadLogFile(_lpLogFile, &_pszPostStream);
  692.     if (dwLen == 0)
  693.     {
  694.         // no log to post, should clean up cache entries for this group.
  695.         OnPostSuccess();
  696.         return S_OK;
  697.     }
  698.   
  699.     if (FAILED(hr = InitRequest("POST")))
  700.         return hr;
  701. #ifdef ENCODE_LOG
  702.     CHAR   lpEncodeHdr[c_ccEncodeHeader+MAX_PATH];
  703.     lpEncodeHdr[0] = '';
  704.     if (SUCCEEDED(ReadBSTR(m_pSubscriptionItem, c_szPostHeader, &_pwszEncoding)))
  705.     {
  706.         if (_pwszEncoding && *_pwszEncoding)
  707.         {
  708.             IEncodingFilterFactory* pEflt = NULL;
  709.             IDataFilter*    pDF = NULL;
  710.                  
  711.             CoCreateInstance(CLSID_StdEncodingFilterFac, NULL, CLSCTX_INPROC_SERVER,
  712.                                     IID_IEncodingFilterFactory, (void**)&pEflt);
  713.             if (pEflt)
  714.             {
  715.                 pEflt->GetDefaultFilter(_pwszEncoding, L"text", &pDF);
  716.                 if (pDF)
  717.                 {
  718.                     LONG lInUsed = 0;
  719.                     LONG lOutUsed = 0;
  720.                     LPSTR  pInBuf = _pszPostStream;
  721.                     LPSTR  pOutBuf = NULL;
  722.                     HRESULT hrCode = NOERROR;
  723.                     pOutBuf = (LPSTR)MemAlloc(LPTR, dwLen);
  724.                     if (pOutBuf == NULL)
  725.                         goto do_upload;
  726.                     hrCode = pDF->DoEncode(
  727.                                             0,
  728.                                             dwLen,
  729.                                             (BYTE *)pInBuf, 
  730.                                             dwLen,
  731.                                             (BYTE *)pOutBuf, 
  732.                                             dwLen,
  733.                                             &lInUsed,
  734.                                             &lOutUsed,
  735.                                             0);
  736.                     if (SUCCEEDED(hrCode))
  737.                     {
  738.                         // add encoding header information, e.g.
  739.                         // "Content-Transfer-Encoding: x-gziprn"
  740.                         wnsprintfA(lpEncodeHdr, ARRAYSIZE(lpEncodeHdr), "%s%Srn", 
  741.                                    c_szEncodeHeader, _pwszEncoding);
  742.                         
  743.                         SAFELOCALFREE(_pszPostStream);
  744.                         _pszPostStream = (LPSTR)MemAlloc(LPTR, lOutUsed+2);
  745.                         ASSERT(_pszPostStream);
  746.                         memcpy(_pszPostStream, pOutBuf, lOutUsed);  //do I need to append CR?
  747.                         dwLen = (DWORD)lOutUsed;
  748.                     }
  749.                     pDF->Release();
  750.                     SAFELOCALFREE(pOutBuf);
  751.                 }
  752.                 pEflt->Release();
  753.             }
  754.         }   // if (_pwszEncoding && *_pwszEncoding)
  755.     }   //ReadBSTR
  756. do_upload:
  757.     dwHdr = lstrlenA(lpEncodeHdr);
  758.     hr = SendRequest(lpEncodeHdr, &dwHdr, _pszPostStream, &dwLen);
  759. #else
  760.     dwHdr = lstrlenA("");
  761.     hr = SendRequest(NULL, &dwHdr, _pszPostStream, &dwLen);
  762. #endif  //ENCODE_LOG
  763.     CloseRequest();
  764.     if (FAILED(hr))
  765.     {
  766.         TraceMsg(TF_THISMODULE, "PostAgent failed to SendRequest");
  767.         OnPostFailed();
  768.     }
  769.     else
  770.     {
  771.         TraceMsg(TF_THISMODULE, "PostAgent Posted data");
  772.         OnPostSuccess();
  773.     }
  774.     return hr;
  775. }
  776. BOOL CWCPostAgent::GetTmpLogFileName()
  777. {
  778.     char   szPath[MAX_PATH];
  779.     
  780.     if (GetTempPathA(MAX_PATH, szPath) > 0)
  781.     {
  782.         _lpLogFile = (LPSTR)MemAlloc(LPTR, MAX_PATH+1);
  783.         if (GetTempFileNameA(szPath, "trk", 0, _lpLogFile))
  784.         {
  785.             return TRUE;
  786.         }
  787.     }
  788.     return FALSE;
  789. }
  790.     
  791. HRESULT CWCPostAgent::DoPost()
  792. {
  793.     HRESULT hr = E_FAIL;
  794.     
  795.     _pUploadStream->_groupId = 0L;
  796.     if (FAILED(ReadLONGLONG(m_pSubscriptionItem, c_szTrackingCookie, &_pUploadStream->_groupId)))
  797.         return hr;
  798.     if (FAILED(ReadDWORD(m_pSubscriptionItem, c_szPostingRetry, &_pUploadStream->_dwRetry)))
  799.         _pUploadStream->_dwRetry = 0;
  800.     if (_pUploadStream->IsExpired(m_pSubscriptionItem))
  801.     {
  802.         // post is expired, clean up log cache entries
  803.         OnPostSuccess();
  804.         return hr;
  805.     }
  806.     if (!GetTmpLogFileName())
  807.     {
  808.         if (NULL != _lpLogFile)
  809.         {
  810.             MemFree(_lpLogFile);
  811.         }
  812.         _lpLogFile = (LPSTR)MemAlloc(LPTR, (MAX_PATH + 1) * sizeof(CHAR));
  813.         if (_lpLogFile)
  814.         {
  815.             lstrcpyA(_lpLogFile, "trkad.tmp");
  816.         }
  817.     }
  818.         
  819.     if (FAILED(hr = _pUploadStream->RetrieveAllLogStream(_pCDFItem, _lpLogFile)))
  820.         return hr;
  821.     hr = DoFileUpload();
  822.     if (_lpLogFile)
  823.         DeleteFileA(_lpLogFile);
  824.     
  825.     return hr;
  826. }
  827. // OnInetOnline
  828. HRESULT CWCPostAgent::StartDownload()
  829. {
  830.     HRESULT hr;
  831.     ASSERT(_pUploadStream && _pUploadStream->_pwszURL);
  832.     hr = FindCDFStartItem();
  833.     if (SUCCEEDED(hr))
  834.     {
  835.         BSTR bstrChannelURL = NULL;
  836.         hr = ReadBSTR(m_pSubscriptionItem, c_szPropURL, &bstrChannelURL);
  837.         ASSERT(SUCCEEDED(hr) && *bstrChannelURL);
  838.         if (SUCCEEDED(hr) && !SHRestricted2W(REST_NoChannelLogging, bstrChannelURL, 0)
  839.             && !ReadRegDWORD(HKEY_CURRENT_USER, c_szRegKey, c_szNoChannelLogging))
  840.         {
  841.             hr = DoPost();
  842.         }
  843.         else
  844.         {
  845.             OnPostSuccess();                // log is off, clean up log cache entries
  846.         }
  847.         SAFEFREEBSTR(bstrChannelURL);
  848.     }
  849.     SAFERELEASE(_pCDFItem);
  850.     SetEndStatus(S_OK);
  851.     CleanUp();
  852.     return S_OK;
  853. }
  854. // OnAgentStart
  855. HRESULT CWCPostAgent::StartOperation()
  856. {
  857.     if (_pUploadStream)
  858.     {
  859.         DBG_WARN("Agent busy, returning failure");
  860.         SetEndStatus(E_FAIL);
  861.         SendUpdateNone();
  862.         return E_FAIL;
  863.     }
  864.     _pUploadStream = NULL;
  865.     _pUploadStream = new CTrackingStg();
  866.     if (!_pUploadStream)
  867.     {
  868.         DBG("failed to allocate CTrackStg");
  869.         SetEndStatus(E_OUTOFMEMORY);
  870.         SendUpdateNone();
  871.         return E_OUTOFMEMORY;
  872.     }
  873.     SAFEFREEOLESTR(_pUploadStream->_pwszURL);
  874.     if (FAILED(ReadOLESTR(m_pSubscriptionItem, c_szTrackingPostURL, &_pUploadStream->_pwszURL)) ||
  875.         !CUrlDownload::IsValidURL(_pUploadStream->_pwszURL))
  876.     {
  877.         DBG_WARN("Couldn't get valid URL from start item (aborting)");
  878.         SetEndStatus(E_INVALIDARG);
  879.         SendUpdateNone();
  880.         return E_INVALIDARG;
  881.     }
  882.     // After calling this, we'll reenter either in "StartDownload" or in 
  883.     // "AbortUpdate" with m_scEndStatus = E_ACCESSDENIED
  884.     return CDeliveryAgent::StartOperation();
  885. }
  886. //------------------------------------------------------------
  887. //
  888. // override CDeliveryAgent virtual functions
  889. //
  890. //------------------------------------------------------------
  891. // OnInetOffline
  892. // Forcibly abort current operation
  893. HRESULT CWCPostAgent::AgentAbort(DWORD dwFlags)
  894. {
  895.     DBG("CWCPostAgent::AbortUpdate");
  896.     if (_pUploadStream)
  897.     {
  898.         if (SUCCEEDED(FindCDFStartItem()))
  899.         {
  900.             OnPostFailed();
  901.         }
  902.     }
  903.     return CDeliveryAgent::AgentAbort(dwFlags);
  904. }
  905. void CWCPostAgent::CleanUp()
  906. {
  907.     SAFEDELETE(_pUploadStream);
  908.     if (_lpLogFile)
  909.         DeleteFileA(_lpLogFile);
  910.     SAFEFREEBSTR(_pwszEncoding);
  911.     SAFELOCALFREE(_lpLogFile);
  912.     SAFELOCALFREE(_pszPostStream);
  913.     
  914.     CDeliveryAgent::CleanUp();
  915. }
  916. //------------------------------------------------------------
  917. //
  918. // CWCPostAgent Constructor/D'Constr
  919. //
  920. //------------------------------------------------------------
  921. CWCPostAgent::CWCPostAgent()
  922. {
  923.     DBG("Creating CWCPostAgent object");
  924.     //
  925.     // Maintain global count of objects in webcheck.dll
  926.     //
  927.     DllAddRef();
  928.     //
  929.     // Initialize object member variables
  930.     //
  931.     _pUploadStream = NULL;
  932.     _pwszEncoding = NULL;
  933.     _pszPostStream = NULL;
  934.     _lpLogFile = NULL;
  935.     _hSession = _hHttpSession = _hHttpRequest = 0;
  936. }
  937. CWCPostAgent::~CWCPostAgent()
  938. {
  939.     SAFERELEASE(_pCDFItem);
  940.     //
  941.     // Maintain global count of objects
  942.     //
  943.     DllRelease();
  944.     //
  945.     // Release/delete any resources
  946.     //
  947.     DBG("Destroyed CWCPostAgent object");
  948. }