windows-nt/Source/XPSP1/NT/net/rras/cm/cmdl/main.cpp

3415 lines
107 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
//+----------------------------------------------------------------------------
//
// File: main.cpp
//
// Module: CMDL32.EXE
//
// Synopsis: Main source for PhoneBook download connect action
//
// Copyright (c) 1996-1999 Microsoft Corporation
//
// Author: nickball Created Header 04/08/98
//
//+----------------------------------------------------------------------------
#include "cmmaster.h"
#include "shlobj.h"
const TCHAR* const c_pszIConnDwnMsg = TEXT("IConnDwn Message"); // for RegisterWindowMessage() for event messages
const TCHAR* const c_pszIConnDwnAgent = TEXT("Microsoft Connection Manager"); // agent for InternetOpen()
const TCHAR* const c_pszIConnDwnContent = TEXT("application/octet-stream"); // content type for HttpOpenRequest()
const TCHAR* const c_pszCmEntryHideDelay = TEXT("HideDelay");
const TCHAR* const c_pszCmEntryDownloadDelay = TEXT("DownLoadDelay");
const TCHAR* const c_pszCmEntryPbUpdateMessage = TEXT("PBUpdateMessage");
#ifdef EXTENDED_CAB_CONTENTS
//
// SPECIAL NOTE:
//
// Be careful here. If you re-enable EXTENDED_CAB_CONTENTS, then you must
// address the possibility that different instances might be doing updates
// simultaneously in which case a common name such as "PBUPDATE.DIR" is not
// appropriate. Because we do not implement this feature, we do not concern
// ourselves with it for the simple PBK case. Thus we copy the .PBK, .PBR,
// etc. directly from the original tmp dir to the profile directory when
// updating.
//
const TCHAR* const c_pszDirName = TEXT("PBUPDATE.DIR"); // directory to expand .CAB into
const TCHAR* const c_pszInfInDir = TEXT("PBUPDATE.DIR\\PBUPDATE.INF");
const TCHAR* const c_pszPbdInDir = TEXT("PBUPDATE.DIR\\PBUPDATE.PBD");
static LPVOID MyAdvPackLoadAndLink(ArgsStruct *pArgs, LPCTSTR pszFunc)
{
LPVOID pvFunc;
if (!pArgs->hAdvPack)
{
pArgs->hAdvPack = LoadLibrary(TEXT("advpack.dll"));
if (!pArgs->hAdvPack)
{
MYDBG(("MyAdvPackLoadAndLink() LoadLibrary() failed, GLE=%u.",GetLastError()));
return (NULL);
}
}
pvFunc = GetProcAddress(pArgs->hAdvPack,pszFunc);
MYDBGTST(!pvFunc,("MyAdvPackLoadAndLink() GetProcAddress(%s) failed, GLE=%u.",pszFunc,GetLastError()));
return (pvFunc);
}
#define RSC_FLAG_INF 1
static HRESULT MyRunSetupCommand(ArgsStruct *pArgs,
HWND hwndParent,
LPCSTR pszCmdName,
LPCSTR pszInfSection,
LPCSTR pszDir,
LPCSTR pszTitle,
HANDLE *phExe,
DWORD dwFlags,
LPVOID pvRsvd)
{
HRESULT (WINAPI *pfn)(HWND,LPCSTR,LPCSTR,LPCSTR,LPCSTR,HANDLE,DWORD,LPVOID);
pfn = (HRESULT (WINAPI *)(HWND,LPCSTR,LPCSTR,LPCSTR,LPCSTR,HANDLE,DWORD,LPVOID)) MyAdvPackLoadAndLink(pArgs,TEXT("RunSetupCommand"));
if (!pfn)
{
return (HRESULT_FROM_WIN32(GetLastError()));
}
return (pfn(hwndParent,pszCmdName,pszInfSection,pszDir,pszTitle,phExe,dwFlags,pvRsvd));
}
static DWORD MyNeedRebootInit(ArgsStruct *pArgs)
{
DWORD (WINAPI *pfn)(VOID);
pfn = (DWORD (WINAPI *)(VOID)) MyAdvPackLoadAndLink(pArgs,TEXT("NeedRebootInit"));
if (!pfn)
{
return (0);
}
return (pfn());
}
static BOOL MyNeedReboot(ArgsStruct *pArgs, DWORD dwCookie)
{
BOOL (WINAPI *pfn)(DWORD);
pfn = (BOOL (WINAPI *)(DWORD)) MyAdvPackLoadAndLink(pArgs,TEXT("NeedReboot"));
if (!pfn)
{
return (FALSE);
}
return (pfn(dwCookie));
}
#endif // EXTENDED_CAB_CONTENTS
//+----------------------------------------------------------------------------
//
// Function: SuppressInetAutoDial
//
// Synopsis: Sets Inet Option to turn off auto-dial for requests made by this
// process. This prevents multiple instances of CM popping up to
// service CMDL initiated requests if the user disconnects CM
// immediately after getting connected.
//
// Arguments: None
//
// Returns: Nothing
//
// History: nickball Created Header 6/3/99
//
//+----------------------------------------------------------------------------
static void SuppressInetAutoDial(HINTERNET hInternet)
{
DWORD dwTurnOff = 1;
//
// The flag only exists for IE5, this call
// will have no effect if IE5 is not present.
//
BOOL bTmp = InternetSetOption(hInternet, INTERNET_OPTION_DISABLE_AUTODIAL, &dwTurnOff, sizeof(DWORD));
MYDBGTST(FALSE == bTmp, ("InternetSetOption() returned %d, GLE=%u.", bTmp, GetLastError()));
}
static BOOL CmFreeIndirect(LPVOID *ppvBuffer)
{
CmFree(*ppvBuffer);
*ppvBuffer = NULL;
return TRUE;
}
static BOOL CmFreeIndirect(LPTSTR *ppszBuffer)
{
return (CmFreeIndirect((LPVOID *) ppszBuffer));
}
static LPURL_COMPONENTS MyInternetCrackUrl(LPTSTR pszUrl, DWORD dwOptions)
{
struct _sRes
{
URL_COMPONENTS sUrl;
TCHAR szScheme[INTERNET_MAX_SCHEME_LENGTH];
TCHAR szHostName[INTERNET_MAX_HOST_NAME_LENGTH+1];
TCHAR szUserName[INTERNET_MAX_USER_NAME_LENGTH+1];
TCHAR szPassword[INTERNET_MAX_PASSWORD_LENGTH+1];
TCHAR szUrlPath[INTERNET_MAX_PATH_LENGTH+1];
TCHAR szExtraInfo[INTERNET_MAX_PATH_LENGTH+1];
} *psRes;
BOOL bRes;
UINT nIdx;
UINT nSpaces;
if (!pszUrl)
{
MYDBG(("MyInternetCrackUrl() invalid parameter."));
SetLastError(ERROR_INVALID_PARAMETER);
return (NULL);
}
psRes = (struct _sRes *) CmMalloc(sizeof(*psRes));
if (!psRes)
{
return (NULL);
}
psRes->sUrl.dwStructSize = sizeof(psRes->sUrl);
psRes->sUrl.lpszScheme = psRes->szScheme;
psRes->sUrl.dwSchemeLength = sizeof(psRes->szScheme);
psRes->sUrl.lpszHostName = psRes->szHostName;
psRes->sUrl.dwHostNameLength = sizeof(psRes->szHostName);
psRes->sUrl.lpszUserName = psRes->szUserName;
psRes->sUrl.dwUserNameLength = sizeof(psRes->szUserName);
psRes->sUrl.lpszPassword = psRes->szPassword;
psRes->sUrl.dwPasswordLength = sizeof(psRes->szPassword);
psRes->sUrl.lpszUrlPath = psRes->szUrlPath;
psRes->sUrl.dwUrlPathLength = sizeof(psRes->szUrlPath);
psRes->sUrl.lpszExtraInfo = psRes->szExtraInfo;
psRes->sUrl.dwExtraInfoLength = sizeof(psRes->szExtraInfo);
bRes = InternetCrackUrl(pszUrl,0,dwOptions,&psRes->sUrl);
if (!bRes)
{
MYDBG(("MyInternetCrackUrl() InternetCrackUrl(pszUrl=%s) failed, GLE=%u.",pszUrl,GetLastError()));
CmFree(psRes);
return (NULL);
}
nSpaces = 0;
for (nIdx=0;psRes->szExtraInfo[nIdx];nIdx++)
{
if (psRes->szExtraInfo[nIdx] == ' ')
{
nSpaces++;
}
}
if (nSpaces)
{
TCHAR szQuoted[sizeof(psRes->szExtraInfo)/sizeof(TCHAR)];
if (lstrlen(psRes->szExtraInfo)+nSpaces*2 > sizeof(psRes->szExtraInfo)/sizeof(TCHAR)-1)
{
MYDBG(("MyInternetCrackUrl() quoting spaces will exceed buffer size."));
CmFree(psRes);
return (NULL);
}
ZeroMemory(szQuoted,sizeof(szQuoted));
nSpaces = 0;
for (nIdx=0,nSpaces=0;psRes->szExtraInfo[nIdx];nIdx++,nSpaces++)
{
if (psRes->szExtraInfo[nIdx] == ' ')
{
szQuoted[nSpaces++] = '%';
szQuoted[nSpaces++] = '2';
szQuoted[nSpaces] = '0';
}
else
{
szQuoted[nSpaces] = psRes->szExtraInfo[nIdx];
}
}
lstrcpy(psRes->szExtraInfo,szQuoted);
}
return (&psRes->sUrl);
}
static BOOL DownloadFileFtp(DownloadArgs *pdaArgs, HANDLE hFile)
{
BOOL bRes = FALSE;
WIN32_FIND_DATA wfdData;
LPBYTE pbData = NULL;
LPTSTR pszObject = (LPTSTR) CmMalloc((INTERNET_MAX_PATH_LENGTH*2) + 1);
if (NULL == pszObject)
{
MYDBG(("DownloadFileFtp() aborted."));
goto done;
}
pdaArgs->hInet = InternetOpen(c_pszIConnDwnAgent,INTERNET_OPEN_TYPE_PRECONFIG,NULL,NULL,0);
if (*(pdaArgs->pbAbort))
{
MYDBG(("DownloadFileFtp() aborted."));
goto done;
}
if (!pdaArgs->hInet)
{
MYDBG(("DownloadFileFtp() InternetOpen() failed, GLE=%u.",GetLastError()));
goto done;
}
pdaArgs->hConn = InternetConnect(pdaArgs->hInet,
pdaArgs->psUrl->lpszHostName,
pdaArgs->psUrl->nPort,
pdaArgs->psUrl->lpszUserName&&*pdaArgs->psUrl->lpszUserName?pdaArgs->psUrl->lpszUserName:NULL,
pdaArgs->psUrl->lpszPassword&&*pdaArgs->psUrl->lpszPassword?pdaArgs->psUrl->lpszPassword:NULL,
INTERNET_SERVICE_FTP,
0,
0);
if (*(pdaArgs->pbAbort))
{
MYDBG(("DownloadFileFtp() aborted."));
goto done;
}
if (!pdaArgs->hConn)
{
MYDBG(("DownloadFileFtp() InternetConnect(pszHostName=%s) failed, GLE=%u.",pdaArgs->psUrl->lpszHostName,GetLastError()));
goto done;
}
lstrcpy(pszObject,pdaArgs->psUrl->lpszUrlPath);
// lstrcat(pszObject,pdaArgs->psUrl->lpszExtraInfo);
ZeroMemory(&wfdData,sizeof(wfdData));
pdaArgs->hReq = FtpFindFirstFile(pdaArgs->hConn,pszObject,&wfdData,INTERNET_FLAG_RELOAD|INTERNET_FLAG_DONT_CACHE,0);
if (*(pdaArgs->pbAbort))
{
MYDBG(("DownloadFileFtp() aborted."));
goto done;
}
if (!pdaArgs->hReq)
{
MYDBG(("DownloadFileFtp() FtpFindFirstFile() failed, GLE=%u.",GetLastError()));
goto done;
}
bRes = InternetFindNextFile(pdaArgs->hReq,&wfdData);
if (*(pdaArgs->pbAbort))
{
MYDBG(("DownloadFileFtp() aborted."));
goto done;
}
if (bRes || (GetLastError() != ERROR_NO_MORE_FILES))
{
MYDBG(("DownloadFileFtp() InternetFindNextFile() returned unexpected result, bRes=%u, GetLastError()=%u.",bRes,bRes?0:GetLastError()));
bRes = FALSE;
goto done;
}
InternetCloseHandle(pdaArgs->hReq);
if (*(pdaArgs->pbAbort))
{
MYDBG(("DownloadFileFtp() aborted."));
goto done;
}
pdaArgs->dwTotalSize = wfdData.nFileSizeLow;
pdaArgs->hReq = FtpOpenFile(pdaArgs->hConn,pszObject,GENERIC_READ,FTP_TRANSFER_TYPE_BINARY,0);
if (*(pdaArgs->pbAbort))
{
MYDBG(("DownloadFileFtp() aborted."));
goto done;
}
if (!pdaArgs->hReq)
{
MYDBG(("DownloadFileFtp() FtpOpenFile() failed, GLE=%u.",GetLastError()));
goto done;
}
pbData = (LPBYTE) CmMalloc(BUFFER_LENGTH);
if (!pbData)
{
goto done;
}
while (1)
{
DWORD dwBytesRead;
DWORD dwBytesWritten;
bRes = InternetReadFile(pdaArgs->hReq,pbData,BUFFER_LENGTH,&dwBytesRead);
if (*(pdaArgs->pbAbort))
{
MYDBG(("DownloadFileFtp() aborted."));
goto done;
}
if (!bRes)
{
MYDBG(("DownloadFileFtp() InternetReadFile() failed, GLE=%u.",GetLastError()));
goto done;
}
if (!dwBytesRead)
{
break;
}
bRes = WriteFile(hFile,pbData,dwBytesRead,&dwBytesWritten,NULL);
if (*(pdaArgs->pbAbort))
{
MYDBG(("DownloadFileFtp() aborted."));
goto done;
}
if (!bRes)
{
MYDBG(("DownloadFileFtp() WriteFile() failed, GLE=%u.",GetLastError()));
goto done;
}
if (dwBytesRead != dwBytesWritten)
{
MYDBG(("DownloadFileFtp() dwBytesRead=%u, dwBytesWritten=%u.",dwBytesRead,dwBytesWritten));
SetLastError(ERROR_DISK_FULL);
goto done;
}
pdaArgs->dwTransferred += dwBytesRead;
if (pdaArgs->pfnEvent)
{
pdaArgs->pfnEvent(pdaArgs->dwTransferred,pdaArgs->dwTotalSize,pdaArgs->pvEventParam);
}
if (*(pdaArgs->pbAbort))
{
MYDBG(("DownloadFileFtp() aborted."));
goto done;
}
}
bRes = TRUE;
done:
if (pbData)
{
CmFree(pbData);
}
if (pdaArgs->hReq)
{
InternetCloseHandle(pdaArgs->hReq);
pdaArgs->hReq = NULL;
}
if (pdaArgs->hConn)
{
InternetCloseHandle(pdaArgs->hConn);
pdaArgs->hConn = NULL;
}
if (pdaArgs->hInet)
{
InternetCloseHandle(pdaArgs->hInet);
pdaArgs->hInet = NULL;
}
if (pszObject)
{
CmFree(pszObject);
}
return (bRes);
}
static BOOL DownloadFileFile(DownloadArgs *pdaArgs, HANDLE hFile)
{
BOOL bRes = FALSE;
HANDLE hInFile = INVALID_HANDLE_VALUE;
LPBYTE pbData = NULL;
hInFile = CreateFile(pdaArgs->psUrl->lpszUrlPath,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if (*(pdaArgs->pbAbort))
{
MYDBG(("DownloadFileFile() aborted."));
goto done;
}
if (hInFile == INVALID_HANDLE_VALUE)
{
MYDBG(("DownloadFileFile() CreateFile(pszFile=%s) failed, GLE=%u.",pdaArgs->psUrl->lpszUrlPath,GetLastError()));
goto done;
}
pdaArgs->dwTotalSize = GetFileSize(hInFile,NULL);
if (*(pdaArgs->pbAbort))
{
MYDBG(("DownloadFileFile() aborted."));
goto done;
}
if (pdaArgs->dwTotalSize == -1)
{
MYDBG(("DownloadFileFile() GetFileSize() failed, GLE=%u.",GetLastError()));
goto done;
}
pbData = (LPBYTE) CmMalloc(BUFFER_LENGTH);
if (!pbData)
{
goto done;
}
while (1)
{
DWORD dwBytesRead;
DWORD dwBytesWritten;
bRes = ReadFile(hInFile,pbData,BUFFER_LENGTH,&dwBytesRead,NULL);
if (*(pdaArgs->pbAbort))
{
MYDBG(("DownloadFileFile() aborted."));
goto done;
}
if (!bRes)
{
MYDBG(("DownloadFileFile() ReadFile() failed, GLE=%u.",GetLastError()));
goto done;
}
if (!dwBytesRead)
{
break;
}
bRes = WriteFile(hFile,pbData,dwBytesRead,&dwBytesWritten,NULL);
if (*(pdaArgs->pbAbort))
{
MYDBG(("DownloadFileFile() aborted."));
goto done;
}
if (!bRes)
{
MYDBG(("DownloadFileFile() WriteFile() failed, GLE=%u.",GetLastError()));
goto done;
}
if (dwBytesRead != dwBytesWritten)
{
MYDBG(("DownloadFileFile() dwBytesRead=%u, dwBytesWritten=%u.",dwBytesRead,dwBytesWritten));
SetLastError(ERROR_DISK_FULL);
goto done;
}
pdaArgs->dwTransferred += dwBytesWritten;
if (pdaArgs->pfnEvent)
{
pdaArgs->pfnEvent(pdaArgs->dwTransferred,pdaArgs->dwTotalSize,pdaArgs->pvEventParam);
}
if (*(pdaArgs->pbAbort))
{
MYDBG(("DownloadFileFile() aborted."));
goto done;
}
}
bRes = TRUE;
done:
if (pbData)
{
CmFree(pbData);
}
if (hInFile != INVALID_HANDLE_VALUE)
{
CloseHandle(hInFile);
}
return (bRes);
}
static BOOL DownloadFileHttp(DownloadArgs *pdaArgs, HANDLE hFile)
{
BOOL bRes = FALSE;
LPBYTE pbData = NULL;
DWORD dwTmpLen;
DWORD dwTmpIdx;
DWORD dwStatus;
LPCTSTR apszContent[] = {c_pszIConnDwnContent,NULL};
LPTSTR pszObject = (LPTSTR) CmMalloc(INTERNET_MAX_PATH_LENGTH + 1);
if (NULL == pszObject)
{
MYDBG(("DownloadFileHttp() aborted."));
goto done;
}
pdaArgs->dwBubbledUpError = 0;
pdaArgs->hInet = InternetOpen(c_pszIConnDwnAgent,INTERNET_OPEN_TYPE_PRECONFIG,NULL,NULL,0);
//
// Supress auto-dial calls to CM from WININET now that we have a handle
//
SuppressInetAutoDial(pdaArgs->hInet);
if (*(pdaArgs->pbAbort))
{
MYDBG(("DownloadFileHttp() aborted."));
goto done;
}
if (!pdaArgs->hInet)
{
pdaArgs->dwBubbledUpError = GetLastError();
MYDBG(("DownloadFileHttp() InternetOpen() failed, GLE=%u.", pdaArgs->dwBubbledUpError));
goto done;
}
pdaArgs->hConn = InternetConnect(pdaArgs->hInet,
pdaArgs->psUrl->lpszHostName,
pdaArgs->psUrl->nPort,
pdaArgs->psUrl->lpszUserName&&*pdaArgs->psUrl->lpszUserName?pdaArgs->psUrl->lpszUserName:NULL,
pdaArgs->psUrl->lpszPassword&&*pdaArgs->psUrl->lpszPassword?pdaArgs->psUrl->lpszPassword:NULL,
INTERNET_SERVICE_HTTP,
0,
0);
if (*(pdaArgs->pbAbort))
{
MYDBG(("DownloadFileHttp() aborted."));
goto done;
}
if (!pdaArgs->hConn)
{
pdaArgs->dwBubbledUpError = GetLastError();
MYDBG(("DownloadFileHttp() InternetConnect(pszHostName=%s) failed, GLE=%u.", pdaArgs->psUrl->lpszHostName, pdaArgs->dwBubbledUpError));
goto done;
}
lstrcpy(pszObject,pdaArgs->psUrl->lpszUrlPath);
lstrcat(pszObject,pdaArgs->psUrl->lpszExtraInfo);
MYDBG(("DownloadFileHttp() - HttpOpenRequest - %s", pszObject));
pdaArgs->hReq = HttpOpenRequest(pdaArgs->hConn,
NULL,
pszObject,
NULL,
NULL,
apszContent,
INTERNET_FLAG_RELOAD|INTERNET_FLAG_DONT_CACHE|(pdaArgs->psUrl->nScheme==INTERNET_SCHEME_HTTPS?INTERNET_FLAG_SECURE:0),
0);
if (*(pdaArgs->pbAbort))
{
MYDBG(("DownloadFileHttp() aborted."));
goto done;
}
if (!pdaArgs->hReq)
{
pdaArgs->dwBubbledUpError = GetLastError();
MYDBG(("DownloadFileHttp() HttpOpenRequest() failed, GLE=%u.", pdaArgs->dwBubbledUpError));
goto done;
}
bRes = HttpSendRequest(pdaArgs->hReq,NULL,0,NULL,0);
if (*(pdaArgs->pbAbort))
{
MYDBG(("DownloadFileHttp() aborted."));
goto done;
}
if (!bRes)
{
pdaArgs->dwBubbledUpError = GetLastError();
MYDBG(("DownloadFileHttp() HttpSendRequest() failed, GLE=%u.", pdaArgs->dwBubbledUpError));
goto done;
}
pbData = (LPBYTE) CmMalloc(BUFFER_LENGTH);
if (!pbData)
{
goto done;
}
while (1)
{
DWORD dwBytesRead;
DWORD dwBytesWritten;
bRes = InternetReadFile(pdaArgs->hReq,pbData,BUFFER_LENGTH,&dwBytesRead);
if (*(pdaArgs->pbAbort))
{
MYDBG(("DownloadFileHttp() aborted."));
goto done;
}
if (!bRes)
{
pdaArgs->dwBubbledUpError = GetLastError();
MYDBG(("DownloadFileHttp() InternetReadFile() failed, GLE=%u.", pdaArgs->dwBubbledUpError));
goto done;
}
if (!dwBytesRead)
{
break;
}
bRes = WriteFile(hFile,pbData,dwBytesRead,&dwBytesWritten,NULL);
if (*(pdaArgs->pbAbort))
{
MYDBG(("DownloadFileHttp() aborted."));
goto done;
}
if (!bRes)
{
pdaArgs->dwBubbledUpError = GetLastError();
MYDBG(("DownloadFileHttp() WriteFile() failed, GLE=%u.", pdaArgs->dwBubbledUpError));
goto done;
}
if (dwBytesRead != dwBytesWritten)
{
MYDBG(("DownloadFileHttp() dwBytesRead=%u, dwBytesWritten=%u.",dwBytesRead,dwBytesWritten));
SetLastError(ERROR_DISK_FULL);
goto done;
}
if (!pdaArgs->dwTransferred)
{
dwTmpLen = sizeof(pdaArgs->dwTotalSize);
dwTmpIdx = 0;
bRes = HttpQueryInfo(pdaArgs->hReq,HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_CONTENT_LENGTH,&pdaArgs->dwTotalSize,&dwTmpLen,&dwTmpIdx);
if (*(pdaArgs->pbAbort))
{
MYDBG(("DownloadFileHttp() aborted."));
goto done;
}
MYDBGTST(!bRes,("DownloadFileHttp() HttpQueryInfo() failed, GLE=%u.",GetLastError()));
if (!bRes)
{
pdaArgs->dwBubbledUpError = GetLastError();
}
}
pdaArgs->dwTransferred += dwBytesRead;
if (pdaArgs->pfnEvent)
{
pdaArgs->pfnEvent(pdaArgs->dwTransferred,pdaArgs->dwTotalSize,pdaArgs->pvEventParam);
}
if (*(pdaArgs->pbAbort))
{
MYDBG(("DownloadFileHttp() aborted."));
goto done;
}
}
dwTmpLen = sizeof(dwStatus);
dwTmpIdx = 0;
bRes = HttpQueryInfo(pdaArgs->hReq,HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_STATUS_CODE,&dwStatus,&dwTmpLen,&dwTmpIdx);
if (!bRes)
{
pdaArgs->dwBubbledUpError = GetLastError();
MYDBG(("DownloadFileHttp() HttpQueryInfo() failed, GLE=%u.", pdaArgs->dwBubbledUpError));
goto done;
}
switch (dwStatus)
{
case HTTP_STATUS_OK:
break;
case HTTP_STATUS_NO_CONTENT:
case HTTP_STATUS_BAD_REQUEST:
case HTTP_STATUS_NOT_FOUND:
case HTTP_STATUS_SERVER_ERROR:
default:
pdaArgs->dwBubbledUpError = dwStatus;
MYDBG(("DownloadFileHttp() HTTP status code = %u.",dwStatus));
bRes = FALSE;
SetLastError(ERROR_FILE_NOT_FOUND);
goto done;
}
bRes = TRUE;
done:
if ((0 == pdaArgs->dwBubbledUpError) && !*(pdaArgs->pbAbort))
{
//
// If the error value hasn't been set yet, and isn't the Abort case (which
// is logged separately) try to get it from GetLastError().
//
pdaArgs->dwBubbledUpError = GetLastError();
}
if (pbData)
{
CmFree(pbData);
}
if (pdaArgs->hReq)
{
InternetCloseHandle(pdaArgs->hReq);
pdaArgs->hReq = NULL;
}
if (pdaArgs->hConn)
{
InternetCloseHandle(pdaArgs->hConn);
pdaArgs->hConn = NULL;
}
if (pdaArgs->hInet)
{
InternetCloseHandle(pdaArgs->hInet);
pdaArgs->hInet = NULL;
}
if (bRes && (pdaArgs->dwTransferred > pdaArgs->dwTotalSize))
{
pdaArgs->dwTotalSize = pdaArgs->dwTransferred;
}
if (pszObject)
{
CmFree(pszObject);
}
return (bRes);
}
static BOOL DownloadFile(DownloadArgs *pdaArgs, HANDLE hFile)
{
BOOL bRes = FALSE;
pdaArgs->psUrl = MyInternetCrackUrl((LPTSTR) pdaArgs->pszUrl,ICU_ESCAPE);
if (!pdaArgs->psUrl)
{
return (NULL);
}
switch (pdaArgs->psUrl->nScheme)
{
case INTERNET_SCHEME_FTP:
bRes = DownloadFileFtp(pdaArgs,hFile);
break;
case INTERNET_SCHEME_HTTP:
case INTERNET_SCHEME_HTTPS:
bRes = DownloadFileHttp(pdaArgs,hFile);
break;
case INTERNET_SCHEME_FILE:
bRes = DownloadFileFile(pdaArgs,hFile);
break;
default:
MYDBG(("DownloadFile() unhandled scheme (%u).",pdaArgs->psUrl->nScheme));
SetLastError(ERROR_INTERNET_UNRECOGNIZED_SCHEME);
break;
}
// useful for logging
lstrcpyn(pdaArgs->szHostName, pdaArgs->psUrl->lpszHostName, MAX_PATH);
CmFree(pdaArgs->psUrl);
pdaArgs->psUrl = NULL;
return (bRes);
}
typedef struct _EventParam
{
ArgsStruct *pArgs;
DWORD dwIdx;
} EventParam;
static void EventFunc(DWORD dwCompleted, DWORD dwTotal, LPVOID pvParam)
{
EventParam *pepParam = (EventParam *) pvParam;
MYDBG(("EventFunc() dwCompleted=%u, dwTotal=%u.",dwCompleted,dwTotal));
pepParam->pArgs->dwDataCompleted = dwCompleted;
pepParam->pArgs->dwDataTotal = dwTotal;
PostMessage(pepParam->pArgs->hwndDlg,pepParam->pArgs->nMsgId,etDataReceived,0);
}
static BOOL ProcessCabinet(DownloadArgs *pdaArgs, DWORD dwAppFlags)
{
BOOL fRet = TRUE;
if (!pdaArgs->bTransferOk)
return (TRUE); // If the transfer failed, just leave the install type as itInvalid.
{
HFDI hfdi;
ERF erf;
FDICABINETINFO info;
BOOL bRes;
NotifyArgs naArgs = {dwAppFlags,pdaArgs};
bRes = CreateTempDir(pdaArgs->szCabDir);
if (bRes)
{
hfdi = FDICreate(fdi_alloc,fdi_free,fdi_open,fdi_read,fdi_write,fdi_close,fdi_seek,cpu80386,&erf);
MYDBGTST(!hfdi,("ProcessCabinet() FDICreate() failed, fError=%u, erfOper=%u, erfType=%u.",erf.fError,erf.fError?erf.erfOper:0,erf.fError?erf.erfType:0));
if (hfdi)
{
// Open the suspected cab file
CFDIFileFile fff;
bRes = fff.CreateFile(pdaArgs->szFile,GENERIC_READ,FILE_SHARE_READ,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
if (bRes)
{
// Verify that this is in fact a cabinet file
bRes = FDIIsCabinet(hfdi,(INT_PTR) &fff, &info);
MYDBGTST(!bRes,("ProcessCabinet() FDIIsCabinet() failed, fError=%u, erfOper=%u, erfType=%u.",erf.fError,erf.fError?erf.erfOper:0,erf.fError?erf.erfType:0));
fff.Close();
if (bRes)
{
// Do the FDI copy
bRes = FDICopy(hfdi,pdaArgs->szFile,TEXT(""),0,(PFNFDINOTIFY)fdi_notify,NULL,&naArgs);
if (!bRes)
{
MYDBG(("ProcessCabinet() FDICopy() failed, fError=%u, erfOper=%u, erfType=%u.",erf.fError,erf.fError?erf.erfOper:0,erf.fError?erf.erfType:0));
//pdaArgs->itType = itInvalid;
}
}
#ifdef EXTENDED_CAB_CONTENTS
else
{
// Not a Cab file, assume exe
if (OS_NT)
{
BOOL bExe = FALSE;
DWORD dwExe = 0;
// GetBinaryType() is not supported under Win95.
bExe = GetBinaryType(pdaArgs->szFile,&dwExe);
MYDBG(("ProcessCabinet() GetBinaryType() return %u, dwExe=%u.",bExe,dwExe));
if (!(bExe && ((dwExe & SCS_32BIT_BINARY) || (dwExe & SCS_DOS_BINARY))))
{
fRet = FALSE;
// if it's not either a win32 or dos exe, then just cleanup and abort
goto destroy_fdi;
}
}
MYDBGASSERT(!pdaArgs->rgfpiFileProcessInfo && !pdaArgs->dwNumFilesToProcess);
pdaArgs->rgfpiFileProcessInfo = (PFILEPROCESSINFO)CmMalloc(sizeof(FILEPROCESSINFO));
if (!pdaArgs->rgfpiFileProcessInfo)
{
MYDBG((TEXT("ProcessCabinet: Malloc() failed.")));
fRet = FALSE;
goto destroy_fdi;
}
pdaArgs->dwNumFilesToProcess++;
pdaArgs->rgfpiFileProcessInfo[0].itType = itExe;
pdaArgs->rgfpiFileProcessInfo[0].pszFile = CmStrCpyAlloc(pdaArgs->szFile);
pdaArgs->szCabDir[0] = TEXT('\0');
// pdaArgs->itType = itExe;
}
destroy_fdi:
#endif // EXTENDED_CAB_CONTENTS
}
// Destroy the FDI context
bRes = FDIDestroy(hfdi);
MYDBGTST(!bRes,("ProcessCabinet() FDIDestroy() failed."));
}
}
}
return fRet;
}
//
// Recursively deletes the contents of a directory(pszDir). Changes the file
// attributes from RO to RW if necessary.
//
static BOOL ZapDir(LPCTSTR pszDir)
{
HANDLE hFind = NULL;
TCHAR szTmp[MAX_PATH+1];
BOOL bRes;
// If pszDir format is not appropriate, bail out
if (!pszDir || !*pszDir || (lstrlen(pszDir)+2 > sizeof(szTmp)/sizeof(TCHAR)-1))
{
SetLastError(ERROR_BAD_PATHNAME);
return (FALSE);
}
lstrcpy(szTmp,pszDir);
if (GetLastChar(szTmp) != '\\')
{
lstrcat(szTmp,TEXT("\\"));
}
lstrcat(szTmp,TEXT("*"));
// Traverse directory
WIN32_FIND_DATA wfdData;
hFind = FindFirstFile(szTmp,&wfdData);
MYDBGTST((hFind==INVALID_HANDLE_VALUE)&&(GetLastError()!=ERROR_FILE_NOT_FOUND)&&(GetLastError()!=ERROR_NO_MORE_FILES)&&(GetLastError()!=ERROR_PATH_NOT_FOUND),("ZapDir() FindFirstFile() failed, GLE=%u.",GetLastError()));
if (hFind != INVALID_HANDLE_VALUE)
{
while (1)
{
MYDBGTST(lstrlen(pszDir)+lstrlen(wfdData.cFileName)+1 > sizeof(szTmp)/sizeof(TCHAR)-1,("ZapDir() pszDir=%s+cFileName=%s exceeds %u.",pszDir,wfdData.cFileName,sizeof(szTmp)/sizeof(TCHAR)-1));
if (lstrlen(pszDir)+lstrlen(wfdData.cFileName)+1 <= sizeof(szTmp)/sizeof(TCHAR)-1)
{
if ((lstrcmp(wfdData.cFileName,TEXT(".")) != 0) && (lstrcmp(wfdData.cFileName,TEXT("..")) != 0))
{
lstrcpy(szTmp,pszDir);
if (GetLastChar(szTmp) != '\\')
{
lstrcat(szTmp,TEXT("\\"));
}
lstrcat(szTmp,wfdData.cFileName);
// If the file is read-only, attrib writeable so we can delete it
if (wfdData.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
{
bRes = SetFileAttributes(szTmp,wfdData.dwFileAttributes & ~FILE_ATTRIBUTE_READONLY);
MYDBGTST(!bRes,("ZapDir() SetFileAttributes(szTmp=%s) failed, GLE=%u.",szTmp,GetLastError()));
}
// Found a dir entry, recurse down a level
if (wfdData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
ZapDir(szTmp);
}
else
{
bRes = DeleteFile(szTmp);
MYDBGTST(!bRes,("ZapDir() DeleteFile(szTmp=%s) failed, GLE=%u.",szTmp,GetLastError()));
}
}
}
// Go to next file
bRes = FindNextFile(hFind,&wfdData);
if (!bRes)
{
MYDBGTST((GetLastError()!=ERROR_FILE_NOT_FOUND)&&(GetLastError()!=ERROR_NO_MORE_FILES),("ZapDir() FindNextFile() failed, GLE=%u.",GetLastError()));
break;
}
}
bRes = FindClose(hFind);
MYDBGTST(!bRes,("ZapDir() FindClose() failed, GLE=%u.",GetLastError()));
}
// Now that the files have been removed, delete the directory
bRes = RemoveDirectory(pszDir);
MYDBGTST(!bRes&&(GetLastError()!=ERROR_PATH_NOT_FOUND),("ZapDir() RemoveDirectory(pszDir=%s) failed, GLE=%u.",pszDir,GetLastError()));
return (bRes);
}
#ifdef EXTENDED_CAB_CONTENTS
static long MyMsgWaitDlg(HWND hwndMsg, DWORD dwHandles, HANDLE *phHandles, DWORD dwTimeout)
{
long lRes;
if (hwndMsg)
{
HCURSOR hPrev;
MSG msg;
hPrev = SetCursor(LoadCursor(NULL,IDC_WAIT));
ShowCursor(TRUE);
while (1)
{
lRes = MsgWaitForMultipleObjects(dwHandles,phHandles,FALSE,dwTimeout,QS_ALLINPUT);
if (lRes == WAIT_TIMEOUT)
{
break;
}
if (lRes != (long) (WAIT_OBJECT_0+dwHandles))
{
MYDBGTST(-1 == lRes,("MyMsgWaitDlg() MsgWaitForMultipleObjects() failed, GLE=%u.",GetLastError()));
break;
}
PeekMessage(&msg,hwndMsg,0,0,PM_NOREMOVE);
}
ShowCursor(FALSE);
SetCursor(hPrev);
}
else
{
lRes = WaitForMultipleObjects(dwHandles,phHandles,FALSE,dwTimeout);
}
return (lRes);
}
#endif // EXTENDED_CAB_CONTENTS
//
// Executes installation of phone book update based upon download file
//
static BOOL DoInstall(ArgsStruct *pArgs, HWND hwndParent, DWORD dwAppFlags)
{
DWORD dwIdx;
// If no install, we are done
if (dwAppFlags & AF_NO_INSTALL)
{
return (TRUE);
}
// For each arg, handle installation
for (dwIdx=0;dwIdx<pArgs->dwArgsCnt;dwIdx++)
{
DownloadArgs *pdaArgs;
UINT i;
BOOL bInstallOk = FALSE;
BOOL bRes = TRUE;
pdaArgs = pArgs->pdaArgs + dwIdx;
pdaArgs->dwBubbledUpError = 0;
#ifdef EXTENDED_CAB_CONTENTS
BOOL fCabDirRenamed = FALSE;
// rename the dir the downloaded file is not an EXE
if (pdaArgs->szCabDir[0])
{
ZapDir(c_pszDirName);
bRes = MoveFile(pdaArgs->szCabDir,c_pszDirName);
MYDBGTST(!bRes,("DoInstall() MoveFile(szCabDir=%s,c_pszDirName) failed, GLE=%u.",pdaArgs->szCabDir,GetLastError()));
if (bRes)
{
fCabDirRenamed = TRUE;
}
}
#endif // EXTENDED_CAB_CONTENTS
// Only perform if the rename worked.
if (bRes)
{
for (i=0; i<pdaArgs->dwNumFilesToProcess; i++)
{
//
// Reset install flag for each file that is processed,
// otherwise a single success will cause us to interpret
// the entire install as successful. #5887
//
bInstallOk = FALSE;
switch (pdaArgs->rgfpiFileProcessInfo[i].itType)
{
#ifdef EXTENDED_CAB_CONTENTS
case itExeInCab:
case itExe:
{
STARTUPINFO siInfo;
PROCESS_INFORMATION piInfo;
ZeroMemory(&siInfo,sizeof(siInfo));
ZeroMemory(&piInfo,sizeof(piInfo));
siInfo.cb = sizeof(siInfo);
bRes = CreateProcess(pdaArgs->rgfpiFileProcessInfo[i].pszFile,
NULL,NULL,NULL,FALSE,0,NULL,NULL,&siInfo,&piInfo);
MYDBGTST(!bRes,("DoInstall() CreateProcess(pszExe=%s) failed, GLE=%u.",pdaArgs->rgfpiFileProcessInfo[i].pszFile,GetLastError()));
// If CreateProcess worked, wait for process to terminate before continuing
if (bRes)
{
CloseHandle(piInfo.hThread);
MyMsgWaitDlg(hwndParent,1,&piInfo.hProcess,INFINITE);
CloseHandle(piInfo.hProcess);
bInstallOk = TRUE;
}
break;
}
case itInfInCab: // .INF file
{
TCHAR szCabDir[MAX_PATH+1];
DWORD dwRes;
HRESULT hRes;
ZeroMemory(szCabDir,sizeof(szCabDir));
dwRes = GetCurrentDirectory(sizeof(szCabDir)/sizeof(TCHAR)-1,szCabDir);
MYDBGTST(!dwRes,("DoInstall() GetCurrentDirectory() failed, GLE=%u.",GetLastError()));
if (GetLastChar(szCabDir) != '\\')
{
lstrcat(szCabDir,TEXT("\\"));
}
lstrcat(szCabDir,c_pszDirName);
// Since RunSetupCommand() has problems with long file names, we'll
// convert the path just to be sure.
dwRes = GetShortPathName(szCabDir,szCabDir,sizeof(szCabDir)/sizeof(TCHAR)-1);
MYDBGTST(!dwRes,("DoInstall() GetShortPathName() failed, GLE=%u.",GetLastError()));
// TBD: Initialize pArgs->szInstallTitle from service file instead of from resource.
LPTSTR pszTmp = CmFmtMsg(pArgs->hInst,IDMSG_PBTITLE);
lstrcpy(pArgs->szInstallTitle,pszTmp);
CmFree(pszTmp);
hRes = MyRunSetupCommand(pArgs,
hwndParent,
c_pszInfInDir,
NULL,
szCabDir,
pArgs->szInstallTitle,
NULL,
RSC_FLAG_INF,
NULL);
if (!HRESULT_SEVERITY(hRes))
{
bInstallOk = TRUE;
}
break;
}
#endif // EXTENDED_CAB_CONTENTS
case itPbdInCab: // Delta phonebook file
// if the CAB contains an EXE or an INF, then we don't do PBD
if (pdaArgs->fContainsExeOrInf)
{
continue;
}
if (pdaArgs->pszCMSFile)
{
HRESULT hRes;
DWORD_PTR dwPb;
// Update the Phonebook using API calls
hRes = PhoneBookLoad(pdaArgs->pszCMSFile, &dwPb);
MYDBGTST(hRes!=ERROR_SUCCESS,("DoInstall() PhoneBookLoad(pszCMSFile=%s) failed, GLE=%u.", pdaArgs->pszCMSFile, hRes));
if (hRes == ERROR_SUCCESS)
{
#ifdef EXTENDED_CAB_CONTENTS
hRes = PhoneBookMergeChanges(dwPb, c_pszPbdInDir);
#else
//
// Build path to delta file, to be passed to phonebook merge
//
TCHAR szPbd[MAX_PATH+1];
lstrcpy(szPbd, pdaArgs->szCabDir);
lstrcat(szPbd, TEXT("\\"));
lstrcat(szPbd, c_pszPbdFile);
hRes = PhoneBookMergeChanges(dwPb, szPbd);
#endif // EXTENDED_CAB_CONTENTS
MYDBGTST(hRes!=ERROR_SUCCESS,("DoInstall() PhoneBookMergeChanges() failed, GLE=%u.",hRes));
if (hRes == ERROR_SUCCESS)
{
bInstallOk = TRUE;
}
else
{
pdaArgs->dwBubbledUpError = hRes;
}
hRes = PhoneBookUnload(dwPb);
MYDBGTST(hRes!=ERROR_SUCCESS,("DoInstall() PhoneBookUnload() failed, GLE=%u.",hRes));
}
if (!bInstallOk && !(dwAppFlags & AF_NO_VER))
{
// We currently zap the version string on any failure. This should cause
// the phone book to get completely update the next time around.
WritePrivateProfileString(c_pszCmSection,
c_pszVersion,
TEXT(""),
pdaArgs->pszCMSFile);
}
}
break;
case itPbkInCab: // Phone book file
{
TCHAR szPbk[MAX_PATH+1];
// if the CAB contains an EXE or an INF, then we don't do PBK
if (pdaArgs->fContainsExeOrInf)
{
continue;
}
#ifdef EXTENDED_CAB_CONTENTS
lstrcpy(szPbk, c_pszDirName);
#else // EXTENDED_CAB_CONTENTS
lstrcpy(szPbk, pdaArgs->szCabDir);
#endif
lstrcat(szPbk, TEXT("\\"));
lstrcat(szPbk, pdaArgs->rgfpiFileProcessInfo[i].pszFile);
// Try to copy the phonebook file directly
if (!CopyFile(szPbk, pdaArgs->pszPbkFile, FALSE))
{
pdaArgs->dwBubbledUpError = GetLastError();
MYDBG((TEXT("DoInstall() itPbkInCab, CopyFile() failed, GLE=%u."), pdaArgs->dwBubbledUpError));
}
else
{
bInstallOk = TRUE;
}
break;
}
case itPbrInCab: // Region file
{
TCHAR szPbr[MAX_PATH+1];
// if the CAB contains an EXE or an INF, then we don't do PBD
if (pdaArgs->fContainsExeOrInf)
{
continue;
}
#ifdef EXTENDED_CAB_CONTENTS
lstrcpy(szPbr, c_pszDirName);
#else // EXTENDED_CAB_CONTENTS
lstrcpy(szPbr, pdaArgs->szCabDir);
#endif
lstrcat(szPbr, TEXT("\\"));
lstrcat(szPbr, pdaArgs->rgfpiFileProcessInfo[i].pszFile);
// Try to copy the region file directly
if (!CopyFile(szPbr, pdaArgs->pszPbrFile, FALSE))
{
MYDBG((TEXT("DoInstall() itPbrInCab, CopyFile() failed, GLE=%u."), GetLastError()));
}
else
{
bInstallOk = TRUE;
}
break;
}
#ifdef EXTENDED_CAB_CONTENTS
case itShlInCab: // Shell execute target
{
TCHAR szShl[MAX_PATH+1];
lstrcpy(szShl,c_pszDirName);
lstrcat(szShl,TEXT("\\"));
lstrcat(szShl,pdaArgs->rgfpiFileProcessInfo[i].pszFile);
SHELLEXECUTEINFO seiInfo;
ZeroMemory(&seiInfo,sizeof(seiInfo));
seiInfo.cbSize = sizeof(seiInfo);
seiInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
seiInfo.hwnd = hwndParent;
seiInfo.lpFile = szShl;
seiInfo.nShow = SW_SHOWNORMAL;
bRes = ShellExecuteEx(&seiInfo);
MYDBGTST(!bRes,("DoInstall() ShellExecuteEx(szShl=%s) failed, GLE=%u.",szShl,GetLastError()));
// If it worked, wait for termination
if (bRes)
{
MyMsgWaitDlg(hwndParent,1,&seiInfo.hProcess,INFINITE);
CloseHandle(seiInfo.hProcess);
bInstallOk = TRUE;
}
break;
} // case itShlInCab
#endif // EXTENDED_CAB_CONTENTS
} // switch (pdaArgs->rgfpiFileProcessInfo[i].itType)
} // for (i=0; i<pdaArgs->dwNumFilesToProcess; i++)
} // if (bRes)
#ifdef EXTENDED_CAB_CONTENTS
if (fCabDirRenamed)
{
// Copy the Cab directory back to tmp name
bRes = MoveFile(c_pszDirName,pdaArgs->szCabDir);
MYDBGTST(!bRes,("DoInstall() MoveFile(c_pszDirName,szCabDir=%s) failed, GLE=%u.",pdaArgs->szCabDir,GetLastError()));
}
#endif // EXTENDED_CAB_CONTENTS
// Update version info in CMS
if (bInstallOk && !(dwAppFlags & AF_NO_VER) && pdaArgs->pszVerNew && pdaArgs->pszCMSFile)
{
WritePrivateProfileString(c_pszCmSection,
c_pszVersion,
pdaArgs->pszVerNew,
pdaArgs->pszCMSFile);
}
}
return (TRUE);
}
//+----------------------------------------------------------------------------
//
// Func: CheckFileForPBSErrors
//
// Desc: Scan the downloaded file for PBS errors
//
// Args: [hFile] - handle to the already opened tempfile
//
// Return: LONG (0 = no download needed, +ve = PBS error code, -1 = other error)
//
// Notes:
//
// History: 14-Apr-2001 SumitC Created
//
//-----------------------------------------------------------------------------
static LONG CheckFileForPBSErrors(HANDLE hFile)
{
LONG lRet = -1;
MYDBGASSERT(hFile);
if (hFile && (INVALID_HANDLE_VALUE != hFile))
{
TCHAR szFirstThree[4] = {0};
DWORD dwBytesRead;
SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
if (ReadFile(hFile, szFirstThree, 3, &dwBytesRead, NULL) &&
(dwBytesRead >= 3))
{
if (0 == lstrcmpi(szFirstThree, TEXT("204")))
{
//
// "204" => no download necessary
//
lRet = 0;
}
else if (0 != lstrcmpi(szFirstThree, TEXT("MSC")))
{
//
// "MSC" => we have a phonebook. If *not* MSC, get the error number
//
LONG lVal = 0;
for (int i = 0 ; i < 3; ++i)
{
if ((szFirstThree[i] >= TEXT('0')) && (szFirstThree[i] <= TEXT('9')))
{
lVal = (lVal *10) + (szFirstThree[i] - TEXT('0'));
}
else
{
break;
}
}
if (lVal)
{
lRet = lVal;
}
}
}
}
return lRet;
}
//static unsigned __stdcall InetThreadFunc(void *pvParam)
DWORD WINAPI InetThreadFunc(void *pvParam)
{
EventParam epParam = {(ArgsStruct *) pvParam,0};
BOOL bRes = FALSE;
BOOL bSuccess = FALSE;
DWORD dwFileIdx;
HANDLE hFile = INVALID_HANDLE_VALUE;
RASCONN RasConn, *prgRasConn;
DWORD cb, cConnections;
PVOID pRasEnumMem = NULL;
// Wait for delay period to expire
DWORD dwRes = WaitForSingleObject(epParam.pArgs->ahHandles[1], epParam.pArgs->dwDownloadDelay);
MYDBGTST(dwRes==WAIT_FAILED,("InetThreadFunc() WaitForMultipleObjects() failed, GLE=%u.",GetLastError()));
//
// Check if connection is still valid before starting the download
// on NT5 we depend on setting the don't autodial flag for InternetSetOptions()
// Unless, of course, the /LAN flag was specified in which case we don't want
// this connection check to happen because the caller is telling us this is happening
// over a LAN connection.
//
if (!(epParam.pArgs->dwAppFlags & AF_LAN))
{
cb = sizeof(RasConn);
prgRasConn = &RasConn;
prgRasConn->dwSize = cb;
dwRes = RasEnumConnections(prgRasConn, &cb, &cConnections);
if (dwRes == ERROR_BUFFER_TOO_SMALL)
{
pRasEnumMem = CmMalloc(cb);
if (pRasEnumMem == NULL)
{
MYDBG(("InetThreadFunc() aborted. Out of memory"));
epParam.pArgs->bAbort = TRUE;
goto done;
}
prgRasConn = (RASCONN *) pRasEnumMem;
prgRasConn[0].dwSize = sizeof(RASCONN);
dwRes = RasEnumConnections(prgRasConn, &cb, &cConnections);
}
//
// Iterate through connections to check if our's is active
// if there is a problem getting this list we don't abort?
//
if (dwRes == ERROR_SUCCESS)
{
DWORD iConn;
BOOL fConnected = FALSE;
for (iConn = 0; iConn < cConnections; iConn++)
{
if (lstrcmpi(epParam.pArgs->pszServiceName, prgRasConn[iConn].szEntryName) == 0)
{
fConnected = TRUE;
break;
}
}
if (fConnected == FALSE)
{
MYDBG(("InetThreadFunc() aborted. No connection"));
epParam.pArgs->bAbort = TRUE;
goto done;
}
}
}
if (epParam.pArgs->bAbort)
{
MYDBG(("InetThreadFunc() aborted."));
}
for (epParam.dwIdx=0;epParam.dwIdx<epParam.pArgs->dwArgsCnt;epParam.dwIdx++)
{
int i = 0;
UINT uReturn = 0;
DownloadArgs * pDA = &(epParam.pArgs->pdaArgs[epParam.dwIdx]);
while (i++ < 3)
{
//
// On Win9x and/or slow machines, GetTempFileName sometimes fails,
// and cmdl32 errors all the way out. In the debugger, if the call
// is retried, it will invariably succeed. This sounds like a timing
// issue with the OS. We do 3 tries, separated by a 1-second sleep.
//
uReturn = GetTempFileName(TEXT("."), TEXT("000"), 0, epParam.pArgs->pdaArgs[epParam.dwIdx].szFile);
if (uReturn)
{
break;
}
Sleep(1000);
}
if (0 == uReturn)
{
DWORD dwError = GetLastError();
MYDBG(("InetThreadFunc() GetTempFileName failed, GLE=%u.", dwError));
epParam.pArgs->Log.Log(PB_DOWNLOAD_FAILURE, dwError, pDA->pszPhoneBookName, pDA->szHostName);
goto done;
}
else
{
hFile = CreateFile(epParam.pArgs->pdaArgs[epParam.dwIdx].szFile,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (INVALID_HANDLE_VALUE == hFile)
{
DWORD dwError = GetLastError();
MYDBG(("InetThreadFunc() CreateFile(szFile=%s) failed, GLE=%u.", epParam.pArgs->pdaArgs[epParam.dwIdx].szFile, dwError));
epParam.pArgs->Log.Log(PB_DOWNLOAD_FAILURE, dwError, pDA->pszPhoneBookName, pDA->szHostName);
goto done;
}
}
//
// Check to make sure we haven't been aborted
//
if (epParam.pArgs->bAbort)
{
MYDBG(("InetThreadFunc() aborted."));
goto done;
}
// We have a valid tmp file name, download phonebook update into it.
epParam.pArgs->pdaArgs[epParam.dwIdx].pfnEvent = EventFunc;
epParam.pArgs->pdaArgs[epParam.dwIdx].pvEventParam = &epParam;
epParam.pArgs->pdaArgs[epParam.dwIdx].pbAbort = &epParam.pArgs->bAbort;
PostMessage(epParam.pArgs->hwndDlg,epParam.pArgs->nMsgId,etDataBegin,0);
bRes = DownloadFile(&epParam.pArgs->pdaArgs[epParam.dwIdx],hFile);
FlushFileBuffers(hFile);
LONG lResult = CheckFileForPBSErrors(hFile);
CloseHandle(hFile);
hFile = INVALID_HANDLE_VALUE;
if (epParam.pArgs->bAbort)
{
MYDBG(("InetThreadFunc() aborted."));
goto done;
}
PostMessage(epParam.pArgs->hwndDlg,epParam.pArgs->nMsgId,etDataEnd,0);
#if 0
/*
if (!bRes && !epParam.dwIdx)
{
// TBD: Currently, a failure to update the primary phonebook prevents any
// secondary phonebooks from being updated. But a failure to update one
// secondary does not prevent other secondaries from being updated.
goto done;
}
*/
#endif
//
// If download failed (either cpserver thinks that we don't need to update
// the phone book or the phone book doesn't exist on the server), just keep
// on downloading the phone books for other profiles.
//
if (!bRes)
{
if (lResult < 0)
{
//
// we parsed the downloaded file and got some error other than
// the 2 cases handled below
//
epParam.pArgs->Log.Log(PB_DOWNLOAD_FAILURE, pDA->dwBubbledUpError, pDA->pszPhoneBookName, pDA->szHostName);
}
else
{
//
// we contacted the web server successfully, and...
//
epParam.pArgs->Log.Log(PB_DOWNLOAD_SUCCESS, pDA->pszPhoneBookName, pDA->pszVerCurr, pDA->szHostName);
if (lResult > 0)
{
//
// ... (case 1) the web server or PBS reported an error
//
epParam.pArgs->Log.Log(PB_UPDATE_FAILURE_PBS, lResult, pDA->pszPhoneBookName);
}
else
{
//
// ... (case 2) PBS said no download necessary
//
MYDBGASSERT(0 == lResult);
LPTSTR pszText = CmFmtMsg(epParam.pArgs->hInst, IDMSG_LOG_NO_UPDATE_REQUIRED);
epParam.pArgs->Log.Log(PB_UPDATE_SUCCESS,
SAFE_LOG_ARG(pszText),
pDA->pszPhoneBookName,
pDA->pszVerCurr,
pDA->pszVerCurr, // for no-download case, these are the same
pDA->szHostName);
CmFree(pszText);
}
}
continue;
}
if (bRes && epParam.pArgs->pdaArgs[epParam.dwIdx].dwTotalSize)
{
epParam.pArgs->pdaArgs[epParam.dwIdx].bTransferOk = TRUE;
}
if (epParam.pArgs->bAbort)
{
MYDBG(("InetThreadFunc() aborted."));
goto done;
}
//
// Phonebook download was successful, log this and proceed to unpack/update
//
epParam.pArgs->Log.Log(PB_DOWNLOAD_SUCCESS, pDA->pszPhoneBookName, pDA->pszVerCurr, pDA->szHostName);
bRes = ProcessCabinet(&epParam.pArgs->pdaArgs[epParam.dwIdx],epParam.pArgs->dwAppFlags);
if (bRes && (NULL == pDA->rgfpiFileProcessInfo))
{
MYDBGASSERT(FALSE);
// strange case. set error here so that we log something sensible later
pDA->dwBubbledUpError = ERROR_INVALID_DATA; // yes. we know this is lame.
}
if (bRes && pDA->rgfpiFileProcessInfo)
{
//
// figure out if this was a full or delta download
//
BOOL fFoundFullCab = FALSE;
BOOL fFoundDeltaCab = FALSE;
for (DWORD dwFileIndex = 0; dwFileIndex < pDA->dwNumFilesToProcess; ++dwFileIndex)
{
switch (pDA->rgfpiFileProcessInfo[dwFileIndex].itType)
{
case itPbkInCab:
fFoundFullCab = TRUE;
break;
case itPbdInCab:
fFoundDeltaCab = TRUE;
break;
}
}
if (fFoundFullCab ^ fFoundDeltaCab)
{
// the cab should contain one or the other, but not both
LPTSTR pszTemp = NULL;
if (fFoundFullCab)
{
pszTemp = CmFmtMsg(epParam.pArgs->hInst, IDMSG_LOG_FULL_UPDATE);
}
else if (fFoundDeltaCab)
{
pszTemp = CmFmtMsg(epParam.pArgs->hInst, IDMSG_LOG_DELTA_UPDATE);
}
MYDBGASSERT(pszTemp);
if (pszTemp)
{
epParam.pArgs->Log.Log(PB_UPDATE_SUCCESS,
SAFE_LOG_ARG(pszTemp),
pDA->pszPhoneBookName,
pDA->pszVerCurr,
pDA->pszVerNew,
pDA->szHostName);
CmFree(pszTemp);
}
}
else
{
// strange cab (or at least, doesn't contain what we expected)
// both full and delta
CMASSERTMSG(!(fFoundFullCab && fFoundDeltaCab), TEXT("This cab has both full and delta phonebooks!!"));
// neither full nor delta
CMASSERTMSG(! (!fFoundFullCab && !fFoundDeltaCab), TEXT("This cab has neither a full nor a delta phonebook!!"));
pDA->dwBubbledUpError = ERROR_BAD_FORMAT;
epParam.pArgs->Log.Log(PB_UPDATE_FAILURE_CMPBK, pDA->dwBubbledUpError, pDA->pszPhoneBookName);
}
}
else
{
epParam.pArgs->Log.Log(PB_UPDATE_FAILURE_CMPBK, pDA->dwBubbledUpError, pDA->pszPhoneBookName);
}
if (!bRes)
{
goto done;
}
bSuccess = TRUE; // We have at least one successful download #5635
#if 0
/*
if (!epParam.dwIdx &&
epParam.pArgs->pdaArgs[epParam.dwIdx].dwTotalSize &&
(epParam.pArgs->pdaArgs[epParam.dwIdx].itType != itInvalid) &&
(epParam.pArgs->pdaArgs[epParam.dwIdx].itType != itPbdInCab))
{
// TBD: Currently, if the primary service is being updated in any way other than
// a simple phone number delta, we do *not* update any of the secondary phonebooks
// this time around.
break;
}
*/
#endif
}
//
// If no download attempts succeeded, bail completely
//
if (!bSuccess)
{
MYDBG(("InetThreadFunc() no download success."));
goto done;
}
if (epParam.pArgs->bAbort)
{
MYDBG(("InetThreadFunc() aborted."));
goto done;
}
#ifdef EXTENDED_CAB_CONTENTS
// At this point, all of the downloads are complete. We post a message to the main
// window, asking it to call WinVerifyTrust() as appropriate for all of the downloaded
// blobs. The main window will post the event back to us when it is done.
PostMessage(epParam.pArgs->hwndDlg,epParam.pArgs->nMsgId,etVerifyTrust,0);
dwRes = WaitForSingleObject(epParam.pArgs->ahHandles[IDX_EVENT_HANDLE],INFINITE);
if (epParam.pArgs->bAbort)
{
MYDBG(("InetThreadFunc() aborted."));
goto done;
}
#endif // EXTENDED_CAB_CONTENTS
// At this point, everything is all set - we're ready to perform the actual installs. So
// send a message to the main window telling it to do the installs, and wait until it
// signals success back.
PostMessage(epParam.pArgs->hwndDlg,epParam.pArgs->nMsgId,etInstall,0);
dwRes = WaitForSingleObject(epParam.pArgs->ahHandles[IDX_EVENT_HANDLE],INFINITE);
if (epParam.pArgs->bAbort)
{
MYDBG(("InetThreadFunc() aborted."));
goto done;
}
SetLastError(ERROR_SUCCESS);
done:
if (epParam.pArgs->bAbort)
{
epParam.pArgs->Log.Log(PB_ABORTED);
}
if (hFile != INVALID_HANDLE_VALUE)
{
CloseHandle(hFile);
}
if (pRasEnumMem != NULL)
{
CmFree(pRasEnumMem);
}
PostMessage(epParam.pArgs->hwndDlg,epParam.pArgs->nMsgId,etDone,0);
return (GetLastError());
}
//
// The main dlg
//
BOOL CALLBACK MainDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
ArgsStruct *pArgs = (ArgsStruct *) GetWindowLongPtr(hwndDlg,DWLP_USER);
static UINT uTimerID = 0;
switch (uMsg)
{
case WM_INITDIALOG:
{
RECT rDlg;
RECT rWorkArea;
DWORD dwThreadId = 0;
SetWindowLongPtr(hwndDlg,DWLP_USER,(LONG_PTR)lParam);
pArgs = (ArgsStruct *) lParam;
pArgs->hwndDlg = hwndDlg;
MYDBG(("MainDlgProc() - WM_INITDIALOG."));
// Get the dialog rect and the available work area.
GetWindowRect(hwndDlg,&rDlg);
if (SystemParametersInfoA(SPI_GETWORKAREA,0,&rWorkArea,0))
{
// Move the dialog to the bottom right of the screen
MoveWindow(hwndDlg,
rWorkArea.left + ((rWorkArea.right-rWorkArea.left) - (rDlg.right-rDlg.left) - GetSystemMetrics(SM_CXBORDER)),
rWorkArea.top + ((rWorkArea.bottom-rWorkArea.top) - (rDlg.bottom-rDlg.top) - GetSystemMetrics(SM_CYBORDER)),
rDlg.right-rDlg.left,
rDlg.bottom-rDlg.top,
FALSE);
}
// Get update message from ini
if (pArgs->pszProfile)
{
TCHAR szTmp1[MAX_PATH+1];
TCHAR szTmp2[MAX_PATH+1];
GetDlgItemText(hwndDlg,IDC_MAIN_MESSAGE,szTmp2,sizeof(szTmp2)/sizeof(TCHAR)-1);
GetPrivateProfileString(c_pszCmSection,
c_pszCmEntryPbUpdateMessage,
szTmp2,
szTmp1,
sizeof(szTmp1)/sizeof(TCHAR)-1,
pArgs->pdaArgs->pszCMSFile);
SetDlgItemText(hwndDlg,IDC_MAIN_MESSAGE,szTmp1);
}
// Spin download thread (InetThreadFunc)
pArgs->dwHandles = sizeof(pArgs->ahHandles) / sizeof(pArgs->ahHandles[0]);
pArgs->ahHandles[IDX_EVENT_HANDLE] = CreateEvent(NULL,FALSE,FALSE,NULL);
if (!pArgs->ahHandles[IDX_EVENT_HANDLE])
{
MYDBG(("MainDlgProc() CreateEvent() failed, GLE=%u.",GetLastError()));
EndDialog(hwndDlg,FALSE);
}
//pArgs->ahHandles[IDX_INETTHREAD_HANDLE] = (HANDLE) _beginthreadex(NULL,0,InetThreadFunc,pArgs,0,&nThreadId);
pArgs->ahHandles[IDX_INETTHREAD_HANDLE] = (HANDLE) CreateThread(0,0,InetThreadFunc,pArgs,0,&dwThreadId);
if (!pArgs->ahHandles[IDX_INETTHREAD_HANDLE])
{
MYDBG(("MainDlgProc() CreateThread() failed, GLE=%u.",GetLastError()));
EndDialog(hwndDlg,FALSE);
}
SetFocus((HWND) wParam);
return (FALSE);
}
case WM_WINDOWPOSCHANGING:
// Until we set pArgs->bShow to TRUE, we prevent the window from
// ever being shown.
if (!pArgs->bShow && (((LPWINDOWPOS) lParam)->flags & SWP_SHOWWINDOW))
{
((LPWINDOWPOS) lParam)->flags &= ~SWP_SHOWWINDOW;
((LPWINDOWPOS) lParam)->flags |= SWP_HIDEWINDOW;
}
break;
case WM_INITMENUPOPUP:
{
HMENU hMenu = (HMENU) wParam;
// UINT nPos = (UINT) LOWORD(lParam);
BOOL fSysMenu = (BOOL) HIWORD(lParam);
if (fSysMenu)
{
EnableMenuItem(hMenu,SC_MAXIMIZE,MF_BYCOMMAND|MF_GRAYED);
}
break;
}
case WM_DESTROY:
{
// Kill timer if we have one
if (uTimerID)
{
KillTimer(hwndDlg, uTimerID);
}
// If we have args, set bAbort true
if (pArgs)
{
pArgs->bAbort = TRUE;
}
else
{
MYDBGASSERT(FALSE); // should not happen if dailog loads
}
break;
}
default:
break;
}
// Check for custom messages
if (pArgs && (uMsg == pArgs->nMsgId))
{
LPTSTR pszMsg;
MYDBG(("Custom arg - %u received.", (DWORD) wParam));
//
// Setup FirstEvent time for tracking delays
//
if (!pArgs->dwFirstEventTime)
{
pArgs->dwFirstEventTime = GetTickCount();
MYDBG(("Setting FirstEventTime to %u.", pArgs->dwFirstEventTime));
}
if (!pArgs->bShow && (GetTickCount() - pArgs->dwFirstEventTime > pArgs->dwHideDelay))
{
MYDBG(("HideDelay of %u expired, displaying dlg now.", pArgs->dwHideDelay));
pArgs->bShow = TRUE;
ShowWindow(hwndDlg,SW_SHOWNA);
}
// Handle specific message
switch (wParam)
{
case etDataBegin:
pArgs->dwDataStepSize = 0;
SendDlgItemMessage(hwndDlg,IDC_MAIN_PROGRESS,PBM_SETRANGE,0,MAKELPARAM(0,100));
SendDlgItemMessage(hwndDlg,IDC_MAIN_PROGRESS,PBM_SETPOS,0,0);
pszMsg = CmFmtMsg(pArgs->hInst,IDMSG_PERCENT_COMPLETE,0);
SetWindowText(hwndDlg,pszMsg);
CmFree(pszMsg);
break;
case etDataReceived:
if (pArgs->dwDataTotal) // PREVENT DIVIDE BY ZERO
{
if (!pArgs->dwDataStepSize )
{
//
// Progress controls have a limit to there maximum
// integral value so calculate an aproximate step size.
//
//
pArgs->dwDataStepSize = (pArgs->dwDataTotal / 65535) + 1;
SendDlgItemMessage(hwndDlg,
IDC_MAIN_PROGRESS,
PBM_SETRANGE,
0,
MAKELPARAM(0,pArgs->dwDataTotal/pArgs->dwDataStepSize));
}
if (pArgs->dwDataStepSize)
{
SendDlgItemMessage(hwndDlg,IDC_MAIN_PROGRESS,PBM_SETPOS,(WORD) (pArgs->dwDataCompleted / pArgs->dwDataStepSize),0);
pszMsg = CmFmtMsg(pArgs->hInst,IDMSG_PERCENT_COMPLETE,(pArgs->dwDataCompleted*100)/pArgs->dwDataTotal);
SetWindowText(hwndDlg,pszMsg);
CmFree(pszMsg);
}
}
break;
case etDataEnd:
pszMsg = CmFmtMsg(pArgs->hInst,IDMSG_PERCENT_COMPLETE,100);
SetWindowText(hwndDlg,pszMsg);
CmFree(pszMsg);
break;
#ifdef EXTENDED_CAB_CONTENTS
case etVerifyTrust:
{
DWORD dwIdx;
UINT i;
for (dwIdx=0;dwIdx<pArgs->dwArgsCnt;dwIdx++)
{
DownloadArgs *pdaArgs;
LONG lRes = ERROR_INVALID_PARAMETER;
WCHAR szPath[MAX_PATH+1];
GUID gCabSubjectType = WIN_TRUST_SUBJTYPE_CABINET;
GUID gExeSubjectType = WIN_TRUST_SUBJTYPE_PE_IMAGE;
WIN_TRUST_SUBJECT_FILE sSubject = {INVALID_HANDLE_VALUE,szPath};
GUID gActionID = WIN_SPUB_ACTION_PUBLISHED_SOFTWARE;
WIN_TRUST_ACTDATA_CONTEXT_WITH_SUBJECT sActionData = {NULL,&gCabSubjectType,&sSubject};
int iRes;
BOOL fStandaloneExe;
pdaArgs = pArgs->pdaArgs + dwIdx;
ZeroMemory(szPath,sizeof(szPath));
pszMsg = CmFmtMsg(pArgs->hInst,IDMSG_PBTITLEMSG);
iRes = MultiByteToWideChar(CP_OEMCP,0,pszMsg,-1,szPath,sizeof(szPath)/sizeof(WCHAR)-1);
MYDBGTST(!iRes,("MainDlgProc() MultiByteToWideChar() failed, GLE=%u.",GetLastError()));
CmFree(pszMsg);
fStandaloneExe = (pdaArgs->dwNumFilesToProcess == 1 &&
pdaArgs->rgfpiFileProcessInfo[0].itType == itExe);
if (fStandaloneExe || pdaArgs->fContainsExeOrInf || pdaArgs->fContainsShl)
{
HRESULT hRes;
if (fStandaloneExe)
sActionData.SubjectType = &gExeSubjectType;
#ifdef DEBUG
if (!(pArgs->dwAppFlags & AF_NO_VERIFY))
{
#endif
sSubject.hFile = CreateFile(pdaArgs->szFile,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
0,
NULL);
MYDBGTST(sSubject.hFile==INVALID_HANDLE_VALUE,("MainDlgProc() CreateFile(szFile=%s) failed, GLE=%u.",pdaArgs->szFile,GetLastError()));
if (sSubject.hFile != INVALID_HANDLE_VALUE)
{
//
// Now that we know we're going to do something, show the window #6335
//
pArgs->bShow = TRUE;
ShowWindow(hwndDlg,SW_SHOWNA);
//
// Perform verification
//
hRes = WinVerifyTrust(hwndDlg,&gActionID,&sActionData);
if (!HRESULT_SEVERITY(hRes))
{
lRes = ERROR_SUCCESS;
}
else
{
MYDBG(("MainDlgProc() WinVerifyTrust(pszFile=%s) failed, GLE=%u.",pdaArgs->szFile,hRes));
lRes = HRESULT_CODE(hRes);
}
CloseHandle(sSubject.hFile);
}
#ifdef DEBUG
}
else
{
lRes = ERROR_SUCCESS;
}
#endif
}
else // we don't do signing of other files
lRes = ERROR_SUCCESS;
if (lRes != ERROR_SUCCESS)
{
// pdaArgs->itType = itInvalid;
pArgs->bAbort = TRUE;
}
}
#ifdef EXTENDED_CAB_CONTENTS
pArgs->bVerified = TRUE;
#endif // EXTENDED_CAB_CONTENTS
ShowWindow(hwndDlg,SW_HIDE);
SetEvent(pArgs->ahHandles[IDX_EVENT_HANDLE]);
break;
}
#endif // EXTENDED_CAB_CONTENTS
case etInstall:
{
CNamedMutex PbMutex;
//
// Hide the window, we're ready to install
//
pArgs->bShow = TRUE;
ShowWindow(hwndDlg,SW_HIDE);
//
// Grab the mutex before we begin PB updates. If it fails then
// abort the install, we'll try again next time the user connects.
if (PbMutex.Lock(c_pszCMPhoneBookMutex))
{
DoInstall(pArgs,hwndDlg,pArgs->dwAppFlags);
PbMutex.Unlock();
}
SetEvent(pArgs->ahHandles[IDX_EVENT_HANDLE]);
ShowWindow(hwndDlg,SW_HIDE);
break;
}
case etDone:
EndDialog(hwndDlg,TRUE);
break;
case etICMTerm:
#ifdef EXTENDED_CAB_CONTENTS
if (!pArgs->bVerified)
{
pArgs->bAbort = TRUE;
EndDialog(hwndDlg,FALSE);
}
#endif // EXTENDED_CAB_CONTENTS
SetEvent(pArgs->ahHandles[IDX_EVENT_HANDLE]);
break;
}
}
return (FALSE);
}
static void AddToUrl(LPTSTR pszUrl, LPTSTR pszVersion, LPTSTR pszService)
{
TCHAR szHttpstr[MAX_PATH];
TCHAR szChar[16];
int i,len;
if (!CmStrchr(pszUrl,'?'))
{
lstrcat(pszUrl,TEXT("?"));
}
else
{
if (pszUrl[lstrlen(pszUrl)-1] != '&')
{
lstrcat(pszUrl,TEXT("&"));
}
}
// TBD Maybe get more info to send to the server. We currently send
// OSArch, OSType, LCID, OSVer, CMVer, PBVer, and ServiceName.
SYSTEM_INFO siInfo;
OSVERSIONINFO oviInfo;
GetSystemInfo(&siInfo);
ZeroMemory(&oviInfo,sizeof(oviInfo));
oviInfo.dwOSVersionInfoSize = sizeof(oviInfo);
GetVersionEx(&oviInfo);
// #pragma message("ALERT - Resolution required - need to remove ISBU_VERSION." __FILE__)
wsprintf(pszUrl+lstrlen(pszUrl),
TEXT("OSArch=%u&OSType=%u&LCID=%u&OSVer=%u.%u.%u&CMVer=%s"),
siInfo.wProcessorArchitecture,
oviInfo.dwPlatformId,
ConvertDefaultLocale(LOCALE_SYSTEM_DEFAULT),
oviInfo.dwMajorVersion,
oviInfo.dwMinorVersion,
(oviInfo.dwPlatformId==VER_PLATFORM_WIN32_WINDOWS)?LOWORD(oviInfo.dwBuildNumber):oviInfo.dwBuildNumber,
VER_PRODUCTVERSION_STR);
if (pszVersion && *pszVersion)
{
wsprintf(pszUrl+lstrlen(pszUrl),TEXT("&PBVer=%s"),pszVersion);
}
if (pszService && *pszService)
{
// replace spaces with %20 for HTTP - 10216
len = strlen(pszService);
szHttpstr[0] = 0;
szChar[1] = 0;
for (i=0; i<len; ++i)
{
if (pszService[i] == ' ')
{
lstrcat(szHttpstr,"%20");
}
else
{
szChar[0] = pszService[i];
lstrcat(szHttpstr,szChar);
}
}
wsprintf(pszUrl+lstrlen(pszUrl),TEXT("&PB=%s"),szHttpstr);
}
}
static BOOL WINAPI RefFunc(LPCTSTR pszFile,
LPCTSTR pszURL,
PPBFS , // pFilterA,
PPBFS , // pFilterB,
DWORD_PTR dwParam)
{
ArgsStruct *pArgs = (ArgsStruct *) dwParam;
DownloadArgs *pdaArgsTmp;
TCHAR szTmp[MAX_PATH+1];
BOOL bOk = FALSE;
LPTSTR pszSlash;
LPTSTR pszDot;
pdaArgsTmp = (DownloadArgs *) CmRealloc(pArgs->pdaArgs,(pArgs->dwArgsCnt+1)*sizeof(DownloadArgs));
if (pdaArgsTmp)
{
pArgs->pdaArgs = pdaArgsTmp;
pdaArgsTmp += pArgs->dwArgsCnt;
pdaArgsTmp->pszCMSFile = CmStrCpyAlloc(pszFile);
if (pdaArgsTmp->pszCMSFile)
{
// If get the version number from the CMS file
GetPrivateProfileString(c_pszCmSection,
c_pszVersion,
TEXT(""),
szTmp,
(sizeof(szTmp)/sizeof(TCHAR))-1,
pdaArgsTmp->pszCMSFile);
pdaArgsTmp->pszVerCurr = CmStrCpyAlloc(szTmp);
// get the PBK filename from the CMS file
GetPrivateProfileString(c_pszCmSectionIsp,
c_pszCmEntryIspPbFile,
TEXT(""),
szTmp,
sizeof(szTmp)/sizeof(TCHAR)-1,
pdaArgsTmp->pszCMSFile);
pdaArgsTmp->pszPbkFile = CmStrCpyAlloc(szTmp);
// get the PDR filename from the CMS file
GetPrivateProfileString(c_pszCmSectionIsp,
c_pszCmEntryIspRegionFile,
TEXT(""),
szTmp,
sizeof(szTmp)/sizeof(TCHAR)-1,
pdaArgsTmp->pszCMSFile);
pdaArgsTmp->pszPbrFile = CmStrCpyAlloc(szTmp);
// get the phone book name
if (!(pszSlash = CmStrrchr(pdaArgsTmp->pszPbkFile, TEXT('\\'))))
{
MYDBG((TEXT("RefFunc() bad PBK FILE - no backslash.")));
goto parse_err;
}
if (!(pszDot = CmStrchr(pszSlash, TEXT('.'))))
{
MYDBG((TEXT("Reffunc() bad PBK FILE - no dot.")));
goto parse_err;
}
*pszDot = TEXT('\0');
if (!(pdaArgsTmp->pszPhoneBookName = CmStrCpyAlloc(pszSlash+1)))
{
MYDBG((TEXT("Reffunc() out of memory.")));
}
// restore the slash
*pszDot = TEXT('.');
goto next_param;
parse_err:
pdaArgsTmp->pszPhoneBookName = CmStrCpyAlloc(TEXT(""));
next_param:
if (pdaArgsTmp->pszVerCurr)
{
// Build URL with version number and service name
pdaArgsTmp->pszUrl = (LPTSTR) CmMalloc((INTERNET_MAX_URL_LENGTH+1)*sizeof(TCHAR));
if (pdaArgsTmp->pszUrl)
{
lstrcpy(pdaArgsTmp->pszUrl,pszURL);
AddToUrl(pdaArgsTmp->pszUrl,pdaArgsTmp->pszVerCurr,pdaArgsTmp->pszPhoneBookName);
pArgs->dwArgsCnt++;
bOk = TRUE;
}
}
}
}
// Cleanup
if (!bOk && pdaArgsTmp)
{
CmFreeIndirect(&pdaArgsTmp->pszCMSFile);
CmFreeIndirect(&pdaArgsTmp->pszVerCurr);
CmFreeIndirect(&pdaArgsTmp->pszUrl);
}
return (TRUE);
}
//
// cmmgr32.exe passes cmdl32.exe the cmp filename in full path.
//
static BOOL InitArgs(ArgsStruct *pArgs)
{
static struct
{
LPTSTR pszFlag;
DWORD dwFlag;
} asFlags[] = {{TEXT("/no_delete"),AF_NO_DELETE},
{TEXT("/no_install"),AF_NO_INSTALL},
#ifdef DEBUG
{TEXT("/no_verify"),AF_NO_VERIFY},
#endif
{TEXT("/url"),AF_URL},
{TEXT("/no_profile"),AF_NO_PROFILE},
{TEXT("/no_exe"),AF_NO_EXE},
{TEXT("/no_exeincab"),AF_NO_EXEINCAB},
{TEXT("/no_infincab"),AF_NO_INFINCAB},
{TEXT("/no_pbdincab"),AF_NO_PBDINCAB},
{TEXT("/no_shlincab"),AF_NO_SHLINCAB},
{TEXT("/no_ver"),AF_NO_VER},
{TEXT("/LAN"),AF_LAN},
{TEXT("/VPN"),AF_VPN},
{NULL,0}};
DWORD dwIdx;
BOOL bInUrl;
LPTSTR pszUrl = NULL;
BOOL bRes = FALSE;
TCHAR szPath[MAX_PATH+1];
DWORD dwRes;
// LPTSTR pszFileInPath;
//
// Get simulated ArgV
//
LPTSTR pszCmdLine = CmStrCpyAlloc(GetCommandLine());
LPTSTR *ppszArgv = GetCmArgV(pszCmdLine);
if (!ppszArgv || !ppszArgv[0])
{
MYDBG(("InitArgs() invalid parameter."));
goto done;
}
//
// Proces arguments
//
bInUrl = FALSE;
for (dwIdx=1;ppszArgv[dwIdx];dwIdx++)
{
DWORD dwFlagIdx;
for (dwFlagIdx=0;asFlags[dwFlagIdx].pszFlag;dwFlagIdx++)
{
if (lstrcmpi(asFlags[dwFlagIdx].pszFlag,ppszArgv[dwIdx]) == 0)
{
if (bInUrl)
{
MYDBG(("InitArgs() URL expected after AF_URL flag."));
goto done;
}
switch (asFlags[dwFlagIdx].dwFlag)
{
case AF_URL:
bInUrl = TRUE;
break;
case AF_NO_PROFILE:
if (pArgs->pszProfile)
{
MYDBG(("InitArgs() argument number %u (%s) is invalid.",dwIdx,ppszArgv[dwIdx]));
goto done;
}
// fall through
default:
pArgs->dwAppFlags |= asFlags[dwFlagIdx].dwFlag;
break;
}
break;
}
}
if (!asFlags[dwFlagIdx].pszFlag)
{
if (bInUrl)
{
if (pszUrl)
{
MYDBG(("InitArgs() argument number %u (%s) is invalid.",dwIdx,ppszArgv[dwIdx]));
goto done;
}
bInUrl = FALSE;
pszUrl = (LPTSTR) CmMalloc((INTERNET_MAX_URL_LENGTH+1)*sizeof(TCHAR));
if (!pszUrl)
{
goto done;
}
lstrcpy(pszUrl,ppszArgv[dwIdx]);
}
else
{
if (pArgs->pszProfile || (pArgs->dwAppFlags & AF_NO_PROFILE))
{
MYDBG(("InitArgs() argument number %u (%s) is invalid.",dwIdx,ppszArgv[dwIdx]));
goto done;
}
/*
ZeroMemory(szPath,sizeof(szPath));
dwRes = GetFullPathName(ppszArgv[dwIdx],sizeof(szPath)/sizeof(TCHAR)-1,szPath,&pszFileInPath);
MYDBGTST(!dwRes,("InitArgs() GetFullPathName() failed, GLE=%u.",GetLastError()));
*/
//
// the cmp filename is always in full path.
//
lstrcpy(szPath, ppszArgv[dwIdx]);
pArgs->pszProfile = CmStrCpyAlloc(szPath);
if (!pArgs->pszProfile)
{
goto done;
}
else
{
//
// Set the current dir to the profile dir
// If the szPath contains only the file name, then
// assume that the current dir is the profile dir
//
char *pszTemp = NULL;
pszTemp = CmStrrchr(szPath, TEXT('\\'));
if (NULL != pszTemp)
{
*pszTemp = TEXT('\0');
MYVERIFY(SetCurrentDirectory(szPath));
}
}
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////
if (pArgs->dwAppFlags & AF_VPN)
{
//
// They have asked for a VPN download. Let's make sure that the only other flags
// they have specified are /LAN or /NO_DELETE
//
DWORD dwAllowedFlags = AF_VPN | AF_LAN | AF_NO_DELETE;
if ((dwAllowedFlags | pArgs->dwAppFlags) != dwAllowedFlags)
{
CMASSERTMSG(FALSE, TEXT("InitArgs in cmdl32.exe -- VPN flag specified with other non supported flags, exiting."));
goto done;
}
bRes = TRUE;
CMTRACE(TEXT("InitArgs - /VPN flag detected going into VPN file download mode."));
goto done;
}
////////////////////////////////////////////////////////////////////////////////////////////
if (bInUrl)
{
MYDBG(("InitArgs() URL expected after AF_URL flag."));
goto done;
}
if (!pArgs->pszProfile && !(pArgs->dwAppFlags & AF_NO_PROFILE))
{
MYDBG(("InitArgs() must use AF_NO_PROFILE if no profile given on command line."));
goto done;
}
if (pArgs->pszProfile && pszUrl)
{
MYDBG(("InitArgs() can't give both a profile and a URL on the command line."));
goto done;
}
pArgs->pdaArgs = (DownloadArgs *) CmMalloc(sizeof(DownloadArgs));
if (!pArgs->pdaArgs)
{
goto done;
}
pArgs->dwArgsCnt++;
if (!pszUrl)
{
TCHAR szTmp[MAX_PATH+1];
PhoneBookParseInfoStruct pbpisInfo;
LPTSTR pszSlash;
LPTSTR pszDot;
int nVal = 0;
if (!pArgs->pszProfile)
{
MYDBG(("InitArgs() must give AF_URL on command line when AF_NO_PROFILE is given."));
goto done;
}
// Get CMS file name
GetPrivateProfileString(c_pszCmSection,
c_pszCmEntryCmsFile,
TEXT(""),
szTmp,
sizeof(szTmp)/sizeof(TCHAR)-1,
pArgs->pszProfile);
if (!szTmp[0])
{
MYDBG(("InitArgs() [Connection Manager] CMSFile= entry not found in %s.",pArgs->pszProfile));
goto done;
}
/*
ZeroMemory(szPath,sizeof(szPath));
dwRes = GetFullPathName(szTmp,sizeof(szPath)/sizeof(TCHAR)-1,szPath,&pszFileInPath);
MYDBGTST(!dwRes,("InitArgs() GetFullPathName() failed, GLE=%u.",GetLastError()));
*/
//
// we simply append the relative path of the cms file to the profile dir to
// construct the cms path.
//
lstrcat(szPath, TEXT("\\"));
lstrcat(szPath, szTmp);
pArgs->pdaArgs->pszCMSFile = CmStrCpyAlloc(szPath);
if (!pArgs->pdaArgs->pszCMSFile)
{
goto done;
}
// get the PBK filename from the CMS file
GetPrivateProfileString(c_pszCmSectionIsp,
c_pszCmEntryIspPbFile,
TEXT(""),
szTmp,
sizeof(szTmp)/sizeof(TCHAR)-1,
pArgs->pdaArgs->pszCMSFile);
if (!*szTmp)
{
MYDBG(("InitArgs() [ISP Info] RegionFile= entry not found in %s.",pArgs->pdaArgs->pszCMSFile));
pArgs->pdaArgs->pszPhoneBookName = CmStrCpyAlloc(TEXT(""));
}
else
{
if (!(pArgs->pdaArgs->pszPbkFile = CmStrCpyAlloc(szTmp)))
goto done;
// get the phone book name
if (!(pszSlash = CmStrrchr(pArgs->pdaArgs->pszPbkFile, TEXT('\\'))))
{
MYDBG((TEXT("InitArgs() bad PBKFILE - no backslash.")));
goto done;
}
if (!(pszDot = CmStrchr(pszSlash, TEXT('.'))))
{
MYDBG((TEXT("InitArgs() bad PBKFILE - no dot.")));
goto done;
}
*pszDot = TEXT('\0');
if (!(pArgs->pdaArgs->pszPhoneBookName = CmStrCpyAlloc(pszSlash+1)))
goto done;
// restore the slash
*pszDot = TEXT('.');
}
// get the PBR filename from the CMS file
GetPrivateProfileString(c_pszCmSectionIsp,
c_pszCmEntryIspRegionFile,
TEXT(""),
szTmp,
sizeof(szTmp)/sizeof(TCHAR)-1,
pArgs->pdaArgs->pszCMSFile);
MYDBGTST(!*szTmp, ("InitArgs() [ISP Info] RegionFile= entry not found in %s.",pArgs->pdaArgs->pszCMSFile));
if (!(pArgs->pdaArgs->pszPbrFile = CmStrCpyAlloc(szTmp)))
goto done;
GetPrivateProfileString(c_pszCmSection,
c_pszVersion,
TEXT(""),
szTmp,
sizeof(szTmp)/sizeof(TCHAR)-1,
pArgs->pdaArgs->pszCMSFile);
pArgs->pdaArgs->pszVerCurr = CmStrCpyAlloc(szTmp);
if (!pArgs->pdaArgs->pszVerCurr)
{
goto done;
}
pArgs->pdaArgs->pszUrl = (LPTSTR) CmMalloc((INTERNET_MAX_URL_LENGTH+1)*sizeof(TCHAR));
if (!pArgs->pdaArgs->pszUrl)
{
goto done;
}
ZeroMemory(&pbpisInfo,sizeof(pbpisInfo));
pbpisInfo.dwSize = sizeof(pbpisInfo);
pbpisInfo.pszURL = pArgs->pdaArgs->pszUrl;
pbpisInfo.dwURL = INTERNET_MAX_URL_LENGTH;
pbpisInfo.pfnRef = RefFunc;
pbpisInfo.dwRefParam = (DWORD_PTR) pArgs;
bRes = PhoneBookParseInfo(pArgs->pdaArgs->pszCMSFile,&pbpisInfo);
if (!bRes)
{
MYDBG(("InitArgs() PhoneBookParseInfo() failed, GLE=%u.",GetLastError()));
goto done;
}
PhoneBookFreeFilter(pbpisInfo.pFilterA);
PhoneBookFreeFilter(pbpisInfo.pFilterB);
//
// Bug fix #3064, a-nichb - HideDelay & DownloadDelay
// Use nVal while retrieving entries, then assign to global
//
// Get Download delay
nVal = GetPrivateProfileInt(c_pszCmSection,
c_pszCmEntryDownloadDelay,
DEFAULT_DELAY,
pArgs->pdaArgs->pszCMSFile);
// Convert to milliseconds
pArgs->dwDownloadDelay = ((DWORD) nVal * (DWORD) 1000);
MYDBG(("Download delay is %u millisseconds.", pArgs->dwDownloadDelay));
// Get Hide delay
nVal = GetPrivateProfileInt(c_pszCmSection,
c_pszCmEntryHideDelay,
-1,
pArgs->pdaArgs->pszCMSFile);
//
// Convert to milliseconds
//
if (nVal < 0)
{
pArgs->dwHideDelay = DEFAULT_HIDE;
}
else
{
pArgs->dwHideDelay = ((DWORD) nVal * (DWORD) 1000);
}
MYDBG(("Hide delay is %u milliseconds.", pArgs->dwHideDelay));
#if 0
/*
// we don't support SuppressUpdates anymore
if (GetPrivateProfileInt(c_pszCmSection, //13226
TEXT("SuppressUpdates"),
0,
pArgs->pszProfile))
{
pArgs->dwAppFlags |= AF_NO_UPDATE;
}
*/
#endif
}
else
{
pArgs->pdaArgs[0].pszUrl = pszUrl;
pszUrl = NULL;
}
if (pArgs->pszProfile)
{
TCHAR szTmp1[MAX_PATH+1];
TCHAR szTmp2[MAX_PATH+1];
pArgs->pszServiceName = (LPTSTR) CmMalloc((MAX_PATH+1)*sizeof(TCHAR));
if (!pArgs->pszServiceName)
{
goto done;
}
lstrcpy(szTmp1,pArgs->pdaArgs->pszCMSFile);
if (CmStrrchr(szTmp1,'.'))
{
*CmStrrchr(szTmp1,'.') = 0;
}
if (CmStrrchr(szTmp1,'\\'))
{
lstrcpy(szTmp1,CmStrrchr(szTmp1,'\\')+1);
}
GetPrivateProfileString(c_pszCmSection,
c_pszCmEntryServiceName,
szTmp1,
pArgs->pszServiceName,
MAX_PATH,
pArgs->pdaArgs->pszCMSFile);
// Get the name of the large icon
GetPrivateProfileString(c_pszCmSection,
c_pszCmEntryBigIcon,
TEXT(""),
szTmp2,
sizeof(szTmp2)/sizeof(TCHAR)-1,
pArgs->pdaArgs->pszCMSFile);
// If we have a name, load the large icon
if (szTmp2[0])
{
pArgs->hIcon = CmLoadIcon(pArgs->hInst,szTmp2);
}
// Get the name of the small icon
GetPrivateProfileString(c_pszCmSection,
c_pszCmEntrySmallIcon,
TEXT(""),
szTmp2,
sizeof(szTmp2)/sizeof(TCHAR)-1,
pArgs->pdaArgs->pszCMSFile);
// If we have a name, load the small icon
if (szTmp2[0])
{
pArgs->hSmallIcon = CmLoadSmallIcon(pArgs->hInst,szTmp2);
}
}
//
// If the name based icon loads were not successful, load defaults from EXE
//
if (!pArgs->hIcon)
{
pArgs->hIcon = CmLoadIcon(pArgs->hInst, MAKEINTRESOURCE(IDI_APP));
}
if (!pArgs->hSmallIcon)
{
pArgs->hSmallIcon = CmLoadSmallIcon(pArgs->hInst,MAKEINTRESOURCE(IDI_APP));
}
AddToUrl(pArgs->pdaArgs->pszUrl,pArgs->pdaArgs->pszVerCurr,pArgs->pdaArgs->pszPhoneBookName);
bRes = TRUE;
done:
//
// Cleanup
//
if (pszUrl)
{
CmFree(pszUrl);
}
if (pszCmdLine)
{
CmFree(pszCmdLine);
}
if (ppszArgv)
{
CmFree(ppszArgv);
}
return (bRes);
}
static BOOL InitApplication(ArgsStruct *pArgs)
{
WNDCLASSEX wcDlg;
wcDlg.cbSize = sizeof(wcDlg);
if (FALSE == GetClassInfoEx(NULL, WC_DIALOG, &wcDlg))
{
MYDBG(("InitApplication() GetClassInfoEx() failed, GLE=%u.",GetLastError()));
return (FALSE);
}
wcDlg.lpszClassName = ICONNDWN_CLASS;
wcDlg.hIcon = pArgs->hIcon;
wcDlg.hIconSm = pArgs->hSmallIcon;
wcDlg.hInstance = pArgs->hInst;
pArgs->hIcon = NULL;
pArgs->hSmallIcon = NULL;
//
// We have our class data setup, register the class
//
ATOM aRes = RegisterClassEx(&wcDlg);
if (!aRes)
{
//
// We may have more than one instance, so check the error case
//
DWORD dwError = GetLastError();
if (ERROR_ALREADY_EXISTS != dwError)
{
MYDBG(("InitApplication() RegisterClassEx() failed, GLE=%u.",GetLastError()));
return (FALSE);
}
}
MYDBG(("InitApplication() Class %s is registered.", wcDlg.lpszClassName));
return TRUE;
}
static BOOL InitInstance(ArgsStruct *pArgs)
{
pArgs->nMsgId = RegisterWindowMessage(c_pszIConnDwnMsg);
if (!pArgs->nMsgId)
{
MYDBG(("InitInstance() RegisterWindowMessage() failed."));
return (FALSE);
}
return (TRUE);
}
//+----------------------------------------------------------------------------
//
// Func: InitLogging
//
// Desc: Initializes logging functionality for the CMDL32 module
//
// Args: [pArgs] - args struct to pick up stuff from
//
// Return: BOOL (TRUE for success)
//
// Notes: IMPORTANT: note that CMDL32 is compiled Ansi whereas CMUTIL, which
// contains the logging functionality, is Unicode. CmLogFile exposes both
// Ansi and Unicode variants for member functions that take strings.
// However, the arguments passed to the Log calls are Ansi - they are
// handled correctly by using %S (note, capital S) in the corresponding
// format strings in cmlog.rc.
//
// History: 11-Apr-2001 SumitC Created
//
//-----------------------------------------------------------------------------
static BOOL InitLogging(ArgsStruct * pArgs)
{
BOOL fAllUser = TRUE;
BOOL fEnabled = FALSE;
DWORD dwMaxSize = 0;
CHAR szFileDir[MAX_PATH + 1] = {0};
//
// First figure out if this profile is AllUsers or Single User
//
if (!OS_W9X)
{
HMODULE hShell32 = LoadLibraryExA("Shell32.dll", NULL, 0);
if (hShell32)
{
typedef DWORD (WINAPI *pfnSHGetSpecialFolderPathASpec)(HWND, CHAR*, int, BOOL);
pfnSHGetSpecialFolderPathASpec pfnSHGetSpecialFolderPathA;
pfnSHGetSpecialFolderPathA = (pfnSHGetSpecialFolderPathASpec)
GetProcAddress(hShell32,
"SHGetSpecialFolderPathA");
if (pfnSHGetSpecialFolderPathA)
{
CHAR szPath[MAX_PATH+1];
if (TRUE == pfnSHGetSpecialFolderPathA(NULL, szPath, CSIDL_APPDATA, FALSE))
{
CHAR szProfile[MAX_PATH + 1];
lstrcpyn(szProfile, pArgs->pszProfile, MAX_PATH);
szProfile[ lstrlen(szPath) ] = '\0';
if (0 == lstrcmpi(szProfile, szPath))
{
fAllUser = FALSE;
}
}
}
FreeLibrary(hShell32);
}
}
//
// To get Enabled, we have the code equivalent of IniBoth
//
fEnabled = c_fEnableLogging;
BOOL bGotValueFromReg = FALSE;
HKEY hkey;
CHAR szRegPath[2 * MAX_PATH];
lstrcpy(szRegPath, fAllUser ? "SOFTWARE\\Microsoft\\Connection Manager\\UserInfo\\" :
"SOFTWARE\\Microsoft\\Connection Manager\\SingleUserInfo\\");
if ( (lstrlen(szRegPath) + 1 + lstrlen(pArgs->pszServiceName) + 1) > (2 * MAX_PATH))
{
return FALSE;
}
lstrcat(szRegPath, "\\");
lstrcat(szRegPath, pArgs->pszServiceName);
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER,
szRegPath,
0,
KEY_QUERY_VALUE,
&hkey))
{
DWORD dwType;
DWORD bEnabled;
DWORD dwSize = sizeof(DWORD);
if (ERROR_SUCCESS == RegQueryValueEx(hkey,
c_pszCmEntryEnableLogging,
NULL,
&dwType,
(PBYTE) &bEnabled,
&dwSize))
{
fEnabled = bEnabled ? TRUE : FALSE;
bGotValueFromReg = TRUE;
}
RegCloseKey(hkey);
}
//
// To *exactly* mimic pIniBoth we should check the .CMP here too. However,
// the moment the user brings up the UI we will write this value to the
// registry if it was in the .CMP. So, skip the CMP step.
//
if (FALSE == bGotValueFromReg)
{
fEnabled = (BOOL ) GetPrivateProfileInt(c_pszCmSection,
c_pszCmEntryEnableLogging,
c_fEnableLogging,
pArgs->pdaArgs->pszCMSFile);
}
//
// To get MaxSize, we have the code equivalent of IniService
//
dwMaxSize = GetPrivateProfileInt(c_pszCmSectionLogging,
c_pszCmEntryMaxLogFileSize,
c_dwMaxFileSize,
pArgs->pdaArgs->pszCMSFile);
//
// LogFileDirectory is also obtained via IniService
//
GetPrivateProfileString(c_pszCmSectionLogging,
c_pszCmEntryLogFileDirectory,
c_szLogFileDirectory,
szFileDir,
sizeof(szFileDir) / sizeof(TCHAR) - 1,
pArgs->pdaArgs->pszCMSFile);
//
// Use these values to initialize logging
//
pArgs->Log.Init(pArgs->hInst, fAllUser, pArgs->pszServiceName);
pArgs->Log.SetParams(fEnabled, dwMaxSize, szFileDir);
if (pArgs->Log.IsEnabled())
{
pArgs->Log.Start(FALSE); // FALSE => no banner
}
else
{
pArgs->Log.Stop();
}
return TRUE;
}
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR , int )
{
MYDBG(("====================================================="));
MYDBG((" CMDL32.EXE - LOADING - Process ID is 0x%x ", GetCurrentProcessId()));
MYDBG(("====================================================="));
INT_PTR iRes = 1;
ArgsStruct asArgs;
DWORD dwIdx = 0;
BOOL bRes = FALSE;
//
// Initialize app-wide arguments
//
ZeroMemory(&asArgs,sizeof(asArgs));
//
// We can't use hInst param if we're not linked with libc.
// libc uses GetModuleHandle(NULL), so we will too.
//
asArgs.hInst = GetModuleHandleA(NULL); // hInst;
MYDBGTST(NULL == asArgs.hInst, ("WinMain - GetModuleHandle(NULL) returned 0x%x, GLE=%u.", asArgs.hInst, GetLastError()));
#ifdef EXTENDED_CAB_CONTENTS
asArgs.dwRebootCookie = MyNeedRebootInit(&asArgs); //must init flag or else will ask for reboot with no args or other errors
#endif // EXTENDED_CAB_CONTENTS
if (!InitArgs(&asArgs))
{
goto done;
}
///////////////////////////////////////////////////////////////////////////////////
if (asArgs.dwAppFlags & AF_VPN)
{
iRes = UpdateVpnFileForProfile(asArgs.pszProfile);
goto done;
}
///////////////////////////////////////////////////////////////////////////////////
// Set UPDATE flag
// if (asArgs.dwAppFlags & AF_NO_UPDATE)
// {
// MYDBG(("WinMain() user has disabled updates."));
// goto done;
// }
// Initialize the app.
if (!InitApplication(&asArgs))
{
goto done;
}
// Setup this instance
if (!InitInstance(&asArgs))
{
goto done;
}
InitCommonControls();
#ifdef EXTENDED_CAB_CONTENTS
asArgs.dwRebootCookie = MyNeedRebootInit(&asArgs);
#endif // EXTENDED_CAB_CONTENTS
//
// Initialize Logging
//
if (!InitLogging(&asArgs))
{
goto done;
}
iRes = DialogBoxParam(asArgs.hInst,MAKEINTRESOURCE(IDD_MAIN),NULL, (DLGPROC)MainDlgProc,(LPARAM) &asArgs);
MYDBGTST(iRes == -1, ("WinMain() - DialogBoxParam(0x%x, 0x%x, NULL, MainDlgProc, 0x%x) - failed",asArgs.hInst, MAKEINTRESOURCE(IDD_MAIN), &asArgs));
done:
// Close any handles created during WININET session
for (dwIdx=0;dwIdx<asArgs.dwArgsCnt;dwIdx++)
{
DownloadArgs *pdaArgs;
pdaArgs = asArgs.pdaArgs + dwIdx;
if (pdaArgs->hReq)
{
bRes = InternetCloseHandle(pdaArgs->hReq);
MYDBGTST(!bRes,("WinMain() InternetCloseHandle(asArgs.pdaArgs[%u].hReq) failed, GLE=%u.",dwIdx,GetLastError()));
pdaArgs->hReq = NULL;
}
if (pdaArgs->hConn)
{
bRes = InternetCloseHandle(pdaArgs->hConn);
MYDBGTST(!bRes,("WinMain() InternetCloseHandle(asArgs.pdaArgs[%u].hConn) failed, GLE=%u.",dwIdx,GetLastError()));
pdaArgs->hConn = NULL;
}
if (pdaArgs->hInet)
{
bRes = InternetCloseHandle(pdaArgs->hInet);
MYDBGTST(!bRes,("WinMain() InternetCloseHandle(asArgs.pdaArgs[%u].hInet) failed, GLE=%u.",dwIdx,GetLastError()));
pdaArgs->hInet = NULL;
}
}
// Wait for thread to terminate
if (asArgs.ahHandles[IDX_INETTHREAD_HANDLE])
{
long lRes;
lRes = WaitForSingleObject(asArgs.ahHandles[IDX_INETTHREAD_HANDLE],45*1000);
MYDBGTST(lRes!=WAIT_OBJECT_0,("WinMain() WaitForSingleObject() failed, GLE=%u.",lRes));
}
// Free profile and service data
if (asArgs.pszProfile)
{
CmFree(asArgs.pszProfile);
asArgs.pszProfile = NULL;
}
if (asArgs.pszServiceName)
{
CmFree(asArgs.pszServiceName);
asArgs.pszServiceName = NULL;
}
// Cleanup for each argument
for (dwIdx=0;dwIdx<asArgs.dwArgsCnt;dwIdx++)
{
DownloadArgs *pdaArgs;
UINT i;
pdaArgs = asArgs.pdaArgs + dwIdx;
CmFreeIndirect(&pdaArgs->pszCMSFile);
CmFreeIndirect(&pdaArgs->pszPbkFile);
CmFreeIndirect(&pdaArgs->pszPbrFile);
CmFreeIndirect(&pdaArgs->pszUrl);
CmFreeIndirect(&pdaArgs->pszVerCurr);
CmFreeIndirect(&pdaArgs->pszVerNew);
//CmFreeIndirect(&pdaArgs->pszNewPbrFile);
CmFreeIndirect(&pdaArgs->pszPhoneBookName);
if (pdaArgs->psUrl)
{
CmFree(pdaArgs->psUrl);
pdaArgs->psUrl = NULL;
}
for (i=0; i<pdaArgs->dwNumFilesToProcess; i++)
CmFree(pdaArgs->rgfpiFileProcessInfo[i].pszFile);
CmFree(pdaArgs->rgfpiFileProcessInfo);
// As long as AF_NO_DELETE is NOT set, clean up temp files and dirs
if (!(asArgs.dwAppFlags & AF_NO_DELETE))
{
if (pdaArgs->szFile[0])
{
bRes = DeleteFile(pdaArgs->szFile);
MYDBGTST(!bRes,("WinMain() DeleteFile(asArgs[pdaArgs[%lu].szFile=%s) failed, GLE=%u.",dwIdx,pdaArgs->szFile,GetLastError()));
}
if (pdaArgs->szCabDir[0])
{
ZapDir(pdaArgs->szCabDir);
}
}
}
// Release download args
if (asArgs.pdaArgs)
{
CmFree(asArgs.pdaArgs);
asArgs.pdaArgs = NULL;
}
for (dwIdx=0;dwIdx<sizeof(asArgs.ahHandles)/sizeof(asArgs.ahHandles[0]);dwIdx++)
{
if (asArgs.ahHandles[dwIdx])
{
bRes = CloseHandle(asArgs.ahHandles[dwIdx]);
MYDBGTST(!bRes,("WinMain() CloseHandle(asArgs.ahHandles[%u]) failed, GLE=%u.",dwIdx,GetLastError()));
asArgs.ahHandles[dwIdx] = NULL;
}
}
#ifdef EXTENDED_CAB_CONTENTS
// If we need a re-boot, prompt the user
if (MyNeedReboot(&asArgs,asArgs.dwRebootCookie))
{
LPTSTR pszCaption;
LPTSTR pszText;
int iMBRes;
pszText = CmFmtMsg(asArgs.hInst,IDMSG_REBOOT_TEXT);
pszCaption = CmFmtMsg(asArgs.hInst,IDMSG_REBOOT_CAPTION);
iMBRes = MessageBoxEx(NULL,pszText,pszCaption,MB_YESNO|MB_ICONEXCLAMATION|MB_DEFBUTTON2,LANG_USER_DEFAULT);
MYDBGTST(!iMBRes,("WinMain() MessageBoxEx() failed, GLE=%u.",GetLastError()));
CmFree(pszText);
CmFree(pszCaption);
if (iMBRes == IDYES)
{
bRes = ExitWindowsEx(EWX_REBOOT,0);
MYDBGTST(!bRes,("WinMain() ExitWindowsEx() failed, GLE=%u.",GetLastError()));
}
}
// If advpack was used, release it
if (asArgs.hAdvPack)
{
bRes = FreeLibrary(asArgs.hAdvPack);
MYDBGTST(!bRes,("WinMain() FreeLibrary() failed, GLE=%u.",GetLastError()));
asArgs.hAdvPack = NULL;
}
#endif // EXTENDED_CAB_CONTENTS
//
// Uninitialize logging
//
asArgs.Log.DeInit();
//
// the C runtine uses ExitProcess() to exit.
//
MYDBG(("====================================================="));
MYDBG((" CMDL32.EXE - UNLOADING - Process ID is 0x%x ", GetCurrentProcessId()));
MYDBG(("====================================================="));
ExitProcess((UINT)iRes);
return ((int)iRes);
}