//+---------------------------------------------------------------------------- // // 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"); BOOL CleanUpCMDLArgs(ArgsStruct *pasArgs); // // Include the shared source code for SuppressInetAutoDial and SetInetStateConnected // #include "inetopt.cpp" 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); // // Make sure that WinInet isn't in offline mode // (VOID)SetInetStateConnected(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; } } } // 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); } // // 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;dwIdxdwArgsCnt;dwIdx++) { DownloadArgs *pdaArgs; UINT i; BOOL bInstallOk = FALSE; BOOL bRes = TRUE; pdaArgs = pArgs->pdaArgs + dwIdx; pdaArgs->dwBubbledUpError = 0; // Only perform if the rename worked. if (bRes) { for (i=0; idwNumFilesToProcess; 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) { 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) { // // 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); 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("0"), 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; } lstrcpy(szPbk, pdaArgs->szCabDir); 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; } lstrcpy(szPbr, pdaArgs->szCabDir); 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; } } // switch (pdaArgs->rgfpiFileProcessInfo[i].itType) } // for (i=0; idwNumFilesToProcess; i++) } // if (bRes) // 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 != CmCompareString(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; } //+---------------------------------------------------------------------------- // // Function: IsConnectionAlive // // Synopsis: Gets the active RAS connection list from RasEnumConnections and // checks to see if the passed in Connection Name is in the list. // Note that because of the naming of the tunnel connectoid on Win9x // (connection name + Tunnel), we also check for any connections // that start with the connection name. If we get this wrong, the // http requests will error out anyway, but we are just trying to // figure it out ahead of time. The /LAN switch should be used to bypass // this check. // // Arguments: LPCSTR pszConnectionName - name of the connection to look for // // Returns: BOOL - whether the connection is active or not // // History: quintinb Created Header 08/22/01 // //+---------------------------------------------------------------------------- BOOL IsConnectionAlive(LPCSTR pszConnectionName) { BOOL fConnected = FALSE; // return value RASCONN RasConn, *prgRasConn; DWORD cb, cConnections; PVOID pRasEnumMem = NULL; if ((NULL == pszConnectionName) || (TEXT('\0') == pszConnectionName[0])) { CMASSERTMSG(FALSE, TEXT("IsConnectionAlive -- Invalid Connection name passed into function.")); return FALSE; } cb = sizeof(RasConn); prgRasConn = &RasConn; prgRasConn->dwSize = cb; DWORD dwRes = RasEnumConnections(prgRasConn, &cb, &cConnections); if (dwRes == ERROR_BUFFER_TOO_SMALL) { pRasEnumMem = CmMalloc(cb); if (pRasEnumMem == NULL) { MYDBG(("IsConnectionAlive() failed. Out of memory")); dwRes = ERROR_NOT_ENOUGH_MEMORY; } else { 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; PTCHAR pszTruncatedRasEntryName = NULL; DWORD dwServiceNameLen = 0; DWORD dwRasEntryNameLen = 0; dwServiceNameLen = lstrlen(pszConnectionName); pszTruncatedRasEntryName = (PTCHAR)CmMalloc((dwServiceNameLen + 1) * sizeof(TCHAR)); for (iConn = 0; iConn < cConnections; iConn++) { dwRasEntryNameLen = lstrlen(prgRasConn[iConn].szEntryName); if ((dwServiceNameLen < dwRasEntryNameLen) && pszTruncatedRasEntryName) { ZeroMemory((PVOID)pszTruncatedRasEntryName, (dwServiceNameLen + 1) * sizeof(TCHAR)); // // dwServiceNameLen + 1 to copy the null character // lstrcpyn(pszTruncatedRasEntryName, prgRasConn[iConn].szEntryName, dwServiceNameLen + 1); if (lstrcmpi(pszConnectionName, pszTruncatedRasEntryName) == 0) { fConnected = TRUE; break; } } else { if (lstrcmpi(pszConnectionName, prgRasConn[iConn].szEntryName) == 0) { fConnected = TRUE; break; } } } CmFree(pszTruncatedRasEntryName); pszTruncatedRasEntryName = NULL; } if (pRasEnumMem != NULL) { CmFree(pRasEnumMem); } return fConnected; } //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; // 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)) { if (FALSE == IsConnectionAlive(epParam.pArgs->pszServiceName)) { MYDBG(("InetThreadFunc() aborted. No connection")); epParam.pArgs->bAbort = TRUE; goto done; } } // // Make sure we haven't aborted before starting... // if (epParam.pArgs->bAbort) { MYDBG(("InetThreadFunc() aborted.")); goto done; } for (epParam.dwIdx=0;epParam.dwIdxdwArgsCnt;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; } // 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); } PostMessage(epParam.pArgs->hwndDlg,epParam.pArgs->nMsgId,etDone,0); return (GetLastError()); } // // The main dlg // INT_PTR 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; } case WM_QUERYENDSESSION: { MYDBG(("MainDlgProc -- Got WM_QUERYENDSESSION message")); if (pArgs) { pArgs->bAbort = TRUE; } break; } case WM_ENDSESSION: { MYDBG(("MainDlgProc -- Got WM_ENDSESSION message")); // // Check the WPARAM. If it's TRUE then we are ending the session // and need to clean up. // if ((BOOL)wParam && pArgs) { pArgs->bAbort = TRUE; CleanUpCMDLArgs(pArgs); } EndDialog(hwndDlg,FALSE); 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; 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: 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; ipdaArgs,(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 // [pszCmsPath] - path to CMS file // // 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, LPCTSTR pszCmsPath) { 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, pszCmsPath); } // // To get MaxSize, we have the code equivalent of IniService // dwMaxSize = GetPrivateProfileInt(c_pszCmSectionLogging, c_pszCmEntryMaxLogFileSize, c_dwMaxFileSize, pszCmsPath); // // LogFileDirectory is also obtained via IniService // GetPrivateProfileString(c_pszCmSectionLogging, c_pszCmEntryLogFileDirectory, c_szLogFileDirectory, szFileDir, sizeof(szFileDir) / sizeof(TCHAR) - 1, pszCmsPath); // // In the /VPN case, some of the code that populates pArgs is skipped, so // we must get the ServiceName ourselves. // CHAR szServiceName[MAX_PATH + 1]; GetPrivateProfileString(c_pszCmSection, c_pszCmEntryServiceName, TEXT(""), szServiceName, MAX_PATH, pszCmsPath); if (TEXT('\0') == szServiceName[0]) { // without a service name, we're not going to log much. CMTRACE(TEXT("InitLogging - could not find servicename in .CMS file, exiting.")); return FALSE; } // // Use these values to initialize logging // pArgs->Log.Init(pArgs->hInst, fAllUser, szServiceName); pArgs->Log.SetParams(fEnabled, dwMaxSize, szFileDir); if (pArgs->Log.IsEnabled()) { pArgs->Log.Start(FALSE); // FALSE => no banner } else { pArgs->Log.Stop(); } return TRUE; } // can't #include "gppswithalloc.cpp" twice LPTSTR GetPrivateProfileStringWithAlloc(LPCTSTR pszSection, LPCTSTR pszKey, LPCTSTR pszDefault, LPCTSTR pszFile); 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; LPTSTR pszService = NULL; LPTSTR pszCmsPath = NULL; // // 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())); if (!InitArgs(&asArgs)) { goto done; } // // Both UpdateVpn and InitLogging need the .CMS file, so get that now // pszService = GetPrivateProfileStringWithAlloc(c_pszCmSection, c_pszCmEntryCmsFile, TEXT(""), asArgs.pszProfile); if (NULL == pszService) { goto done; } pszCmsPath = CmBuildFullPathFromRelative(asArgs.pszProfile, pszService); if (NULL == pszCmsPath) { goto done; } // // Initialize Logging // if (!InitLogging(&asArgs, pszCmsPath)) { goto done; } /////////////////////////////////////////////////////////////////////////////////// if (asArgs.dwAppFlags & AF_VPN) { iRes = UpdateVpnFileForProfile(asArgs.pszProfile, pszCmsPath, &asArgs.Log, !(asArgs.dwAppFlags & AF_LAN)); // if /LAN flag is set, don't check the connection. 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(); iRes = DialogBoxParam(asArgs.hInst,MAKEINTRESOURCE(IDD_MAIN),NULL, MainDlgProc,(LPARAM) &asArgs); MYDBGTST(iRes == -1, ("WinMain() - DialogBoxParam(0x%x, 0x%x, NULL, MainDlgProc, 0x%x) - failed",asArgs.hInst, MAKEINTRESOURCE(IDD_MAIN), &asArgs)); done: CmFree(pszService); CmFree(pszCmsPath); CleanUpCMDLArgs(&asArgs); // // 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); } //+---------------------------------------------------------------------------- // // Func: CleanUpCMDLArgs // // Desc: Cleans up the CMDL arguments and any sessions or handles that are // open. // // Args: [pArgs] - args struct to pick up stuff from // // Return: BOOL (TRUE for success) // // History: 08/01/2001 tomkel Created // //----------------------------------------------------------------------------- BOOL CleanUpCMDLArgs(ArgsStruct *pasArgs) { BOOL fRetVal = FALSE; DWORD dwIdx = 0; BOOL bRes = FALSE; if (NULL == pasArgs) { return fRetVal; } MYDBG(("CleanUpCMDLArgs -- BEGIN")); // // Close any handles created during WININET session // The InternetCloseHandle function terminates any pending operations on // the handle and discards any outstanding data. If a thread is blocking // a call to Wininet.dll, another thread in the application can call // InternetCloseHandle on the Internet handle being used by the first thread // to cancel the operation and unblock the first thread. // for (dwIdx=0;dwIdxdwArgsCnt;dwIdx++) { DownloadArgs *pdaArgs; pdaArgs = pasArgs->pdaArgs + dwIdx; if (pdaArgs->hReq) { bRes = InternetCloseHandle(pdaArgs->hReq); MYDBGTST(!bRes,("CleanUpCMDLArgs() InternetCloseHandle(asArgs.pdaArgs[%u].hReq) failed, GLE=%u.",dwIdx,GetLastError())); pdaArgs->hReq = NULL; } if (pdaArgs->hConn) { bRes = InternetCloseHandle(pdaArgs->hConn); MYDBGTST(!bRes,("CleanUpCMDLArgs() InternetCloseHandle(asArgs.pdaArgs[%u].hConn) failed, GLE=%u.",dwIdx,GetLastError())); pdaArgs->hConn = NULL; } if (pdaArgs->hInet) { bRes = InternetCloseHandle(pdaArgs->hInet); MYDBGTST(!bRes,("CleanUpCMDLArgs() InternetCloseHandle(asArgs.pdaArgs[%u].hInet) failed, GLE=%u.",dwIdx,GetLastError())); pdaArgs->hInet = NULL; } } // // Wait for thread to terminate // if (pasArgs->ahHandles[IDX_INETTHREAD_HANDLE]) { long lRes; lRes = WaitForSingleObject(pasArgs->ahHandles[IDX_INETTHREAD_HANDLE],45*1000); MYDBGTST(lRes!=WAIT_OBJECT_0,("CleanUpCMDLArgs() WaitForSingleObject() failed, GLE=%u.",lRes)); } // // Free profile and service data // if (pasArgs->pszProfile) { CmFree(pasArgs->pszProfile); pasArgs->pszProfile = NULL; } if (pasArgs->pszServiceName) { CmFree(pasArgs->pszServiceName); pasArgs->pszServiceName = NULL; } // // Cleanup for each argument // for (dwIdx=0;dwIdxdwArgsCnt;dwIdx++) { DownloadArgs *pdaArgs; UINT i; pdaArgs = pasArgs->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; idwNumFilesToProcess; 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 (!(pasArgs->dwAppFlags & AF_NO_DELETE)) { if (pdaArgs->szFile[0]) { bRes = DeleteFile(pdaArgs->szFile); MYDBGTST(!bRes,("CleanUpCMDLArgs() DeleteFile(asArgs[pdaArgs[%lu].szFile=%s) failed, GLE=%u.",dwIdx,pdaArgs->szFile,GetLastError())); } if (pdaArgs->szCabDir[0]) { ZapDir(pdaArgs->szCabDir); } } } // // Release download args // if (pasArgs->pdaArgs) { CmFree(pasArgs->pdaArgs); pasArgs->pdaArgs = NULL; } for (dwIdx=0;dwIdxahHandles)/sizeof(pasArgs->ahHandles[0]);dwIdx++) { if (pasArgs->ahHandles[dwIdx]) { bRes = CloseHandle(pasArgs->ahHandles[dwIdx]); MYDBGTST(!bRes,("WinMain() CloseHandle(asArgs.ahHandles[%u]) failed, GLE=%u.",dwIdx,GetLastError())); pasArgs->ahHandles[dwIdx] = NULL; } } MYDBG(("CleanUpCMDLArgs -- END")); fRetVal = TRUE; return fRetVal; }