1155 lines
32 KiB
C++
1155 lines
32 KiB
C++
|
//=======================================================================
|
||
|
//
|
||
|
// Copyright (c) 1998-1999 Microsoft Corporation. All Rights Reserved.
|
||
|
//
|
||
|
// File: cdm.cpp
|
||
|
//
|
||
|
// Owner: YanL
|
||
|
//
|
||
|
// Description:
|
||
|
//
|
||
|
// Functions exported by CDM
|
||
|
//
|
||
|
// DownloadIsInternetAvailable
|
||
|
// OpenCDMContext
|
||
|
// OpenCDMContextEx
|
||
|
// QueryDetectionFiles
|
||
|
// FindMatchingDriver
|
||
|
// DownloadUpdatedFiles
|
||
|
// DetFilesDownloaded
|
||
|
// LogDriverNotFound
|
||
|
// CloseCDMContext
|
||
|
// GetPackage
|
||
|
// InternalQueryDetectionFiles
|
||
|
// InternalFindMatchingDriver
|
||
|
// InternalDetFilesDownloaded
|
||
|
// InternalLogDriverNotFound
|
||
|
//
|
||
|
//=======================================================================
|
||
|
#include <windows.h>
|
||
|
#include <osdet.h>
|
||
|
#include <setupapi.h>
|
||
|
#include <shlwapi.h>
|
||
|
#include <tchar.h>
|
||
|
|
||
|
#include <wustl.h>
|
||
|
#include <log.h>
|
||
|
#include <wuv3cdm.h>
|
||
|
#include <bucket.h>
|
||
|
#include <newtrust.h>
|
||
|
#include <download.h>
|
||
|
#include <diamond.h>
|
||
|
|
||
|
#include <atlconv.h>
|
||
|
#define _ASSERTE(expr) ((void)0)
|
||
|
#include <atlconv.cpp>
|
||
|
|
||
|
#include "cdm.h"
|
||
|
#include "cdmp.h"
|
||
|
#include <drvinfo.h>
|
||
|
#include <cfgmgr32.h>
|
||
|
#include <shellapi.h>
|
||
|
|
||
|
typedef struct _CONTEXTHANDLE
|
||
|
{
|
||
|
bool fCloseConnection; //Tracks if the connection to the internet was opened by CDM.DLL
|
||
|
bool fNeedUpdate; //TRUE if we need to update CDM.DLL when its connection is closed.
|
||
|
TCHAR szSiteServer[MAX_PATH]; //Description server name.
|
||
|
TCHAR szDownloadServer[MAX_PATH]; //Download server name.
|
||
|
} CONTEXTHANDLE, *PCONTEXTHANDLE;
|
||
|
|
||
|
static frozen_array<CONTEXTHANDLE> g_handleArray;
|
||
|
static HMODULE g_hModule;
|
||
|
static bool g_fNeedUpdate; //Flag that indicates that cdm.dll needs updating.
|
||
|
|
||
|
static int GetHandleIndex(IN HANDLE hConnection);
|
||
|
|
||
|
|
||
|
BOOL APIENTRY DllMain(
|
||
|
HANDLE hModule,
|
||
|
DWORD ul_reason_for_call,
|
||
|
LPVOID /*lpReserved*/
|
||
|
) {
|
||
|
switch (ul_reason_for_call)
|
||
|
{
|
||
|
case DLL_PROCESS_ATTACH:
|
||
|
g_fNeedUpdate = FALSE;
|
||
|
g_hModule = (HMODULE)hModule; // to return to findoem;
|
||
|
break;
|
||
|
case DLL_THREAD_ATTACH:
|
||
|
case DLL_THREAD_DETACH:
|
||
|
break;
|
||
|
case DLL_PROCESS_DETACH:
|
||
|
//If we have downloaded a new dll then we need to update it.
|
||
|
//Note: passing a global to a function is bad form as it can
|
||
|
//cause problems. The only reason that I'm doing this is so
|
||
|
//that the UpdateCDMDll API can be moved to other programs
|
||
|
//since this ability to make a dll or exe self updating is
|
||
|
//very usefull.
|
||
|
if (g_fNeedUpdate)
|
||
|
g_fNeedUpdate = !UpdateCdmDll();
|
||
|
break;
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
//This function determines if this client can connect to the internet.
|
||
|
|
||
|
BOOL DownloadIsInternetAvailable(
|
||
|
void
|
||
|
) {
|
||
|
LOG_block("DownloadIsInternetAvailable");
|
||
|
|
||
|
int iDun = GetDUNConnections();
|
||
|
bool bWizard = IsInternetConnectionWizardCompleted();
|
||
|
bool bConnect = IsInternetConnected();
|
||
|
|
||
|
if (!bConnect && iDun <= 0)
|
||
|
{
|
||
|
LOG_error("if (!!bConnect && iDun <= 0) return false");
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
if (!bWizard)
|
||
|
{
|
||
|
LOG_error("if (!bWizard) return false");
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
LOG_out("return true");
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
//This function Opens an internet connection for download. This connection
|
||
|
//context information is tracked though the returned handle.
|
||
|
//This functon returns a handle a CDM file download context if successful or
|
||
|
//NULL if not. If this function fails GetLastError() can be used to return
|
||
|
//the error code indicating the reason for failure.
|
||
|
|
||
|
HANDLE WINAPI OpenCDMContext(
|
||
|
IN HWND /*hwnd*/ //Window handle to use for any UI that needs to be presented.
|
||
|
) {
|
||
|
LOG_block("OpenCDMContext");
|
||
|
return OpenCDMContextEx(TRUE);
|
||
|
}
|
||
|
|
||
|
HANDLE WINAPI OpenCDMContextEx(
|
||
|
IN BOOL fConnectIfNotConnected
|
||
|
) {
|
||
|
LOG_block("OpenCDMContextEx");
|
||
|
|
||
|
//Initialize context handle array entry and mark it as is use.
|
||
|
CONTEXTHANDLE cth;
|
||
|
ZeroMemory(&cth, sizeof(cth));
|
||
|
|
||
|
bool fConnected = IsInternetConnected();
|
||
|
#ifdef _WUV3TEST
|
||
|
if (fConnected)
|
||
|
{
|
||
|
// catalog spoofing
|
||
|
DWORD dwIsInternetConnected = 1;
|
||
|
DWORD dwSize = sizeof(dwIsInternetConnected);
|
||
|
auto_hkey hkey;
|
||
|
if (NO_ERROR == RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGKEY_WUV3TEST, 0, KEY_READ, &hkey)) {
|
||
|
RegQueryValueEx(hkey, _T("IsInternetConnected"), 0, 0, (LPBYTE)&dwIsInternetConnected, &dwSize);
|
||
|
}
|
||
|
// only then do normal
|
||
|
if (0 == dwIsInternetConnected)
|
||
|
{
|
||
|
fConnected = false;
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
if (fConnectIfNotConnected || fConnected)
|
||
|
{
|
||
|
|
||
|
//Assume that we do not need to connect to the internet
|
||
|
cth.fCloseConnection = !IsInternetConnected();
|
||
|
|
||
|
|
||
|
//If we are not already connected to the internet and
|
||
|
//we fail in the attempt then we cannot download any
|
||
|
//drivers so quit.
|
||
|
if (InternetAttemptConnect(0) != NO_ERROR)
|
||
|
{
|
||
|
LOG_error("No internet connection");
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
TCHAR szSecurityServer[MAX_PATH] = {0};
|
||
|
lstrcpy(szSecurityServer, SZ_SECURITY_SERVER);
|
||
|
|
||
|
/* Test redirect*/{
|
||
|
auto_hkey hkey;
|
||
|
if (NO_ERROR == RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WindowsUpdate"), 0, KEY_READ, &hkey)) {
|
||
|
DWORD dwSize = sizeof(szSecurityServer);
|
||
|
RegQueryValueEx(hkey, _T("SecurityServer"), 0, 0, (LPBYTE)&szSecurityServer, &dwSize);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//Connect to and get server context.
|
||
|
CDownload download;
|
||
|
if (download.Connect(szSecurityServer))
|
||
|
{
|
||
|
LOG_out("Connected to SecurityServer '%s'", szSecurityServer);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
LOG_error("No connection to SecurityServer '%s'", szSecurityServer);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
//Init download
|
||
|
CDiamond diamond;
|
||
|
if (!diamond.valid()) {
|
||
|
SetLastError(ERROR_GEN_FAILURE);
|
||
|
LOG_error("cannot init diamond");
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
// do security url verification and get server locations
|
||
|
if (!ProcessIdent(download, diamond, szSecurityServer, cth.szSiteServer, cth.szDownloadServer))
|
||
|
{
|
||
|
SetLastError(ERROR_ACCESS_DENIED);
|
||
|
LOG_error("invalid identcdm.cab");
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
// reconnect fo Site server if we need to
|
||
|
if (0 != lstrcmpi(cth.szSiteServer, szSecurityServer))
|
||
|
{
|
||
|
if (download.Connect(cth.szSiteServer))
|
||
|
{
|
||
|
LOG_out("Connected to SiteServer '%s'", cth.szSiteServer);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
LOG_error("No connection to SiteServer '%s'", cth.szSiteServer);
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
LOG_out("SiteServer is %s", szSecurityServer);
|
||
|
}
|
||
|
|
||
|
if (!DownloadCdmCab(download, diamond, cth.fNeedUpdate))
|
||
|
{
|
||
|
LOG_error("Failed to download cdm.cab");
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return LongToHandle(g_handleArray.add(cth) + 1);
|
||
|
}
|
||
|
|
||
|
//This function downloads the specified CDM package. The hConnection handle must have
|
||
|
//been returned from the OpenCDMContext() API.
|
||
|
//
|
||
|
//This function Returns TRUE if download is successful GetLastError() will return
|
||
|
//the error code indicating the reason that the call failed.
|
||
|
|
||
|
BOOL WINAPI DownloadUpdatedFiles(
|
||
|
IN HANDLE hConnection, //Connection handle from OpenCDMContext() API.
|
||
|
IN HWND hwnd, //Window handle for call context
|
||
|
IN PDOWNLOADINFO pDownloadInfo, //download information structure describing
|
||
|
//package to be read from server
|
||
|
OUT LPWSTR lpDownloadPath, //local computer directory location of the
|
||
|
//downloaded files
|
||
|
IN UINT uSize, //size of the download path buffer. If this
|
||
|
//buffer is to small to contain the complete
|
||
|
//path and file name no file will be downloaded.
|
||
|
//The PUINT puReguiredSize parameter can be checked
|
||
|
//to determine the size of buffer necessary to
|
||
|
//perform the download.
|
||
|
OUT PUINT puRequiredSize //required lpDownloadPath buffer size. This
|
||
|
//parameter is filled in with the minimum size
|
||
|
//that is required to place the complete path
|
||
|
//file name of the downloaded file. If this
|
||
|
//parameter is NULL no size is returned.
|
||
|
) {
|
||
|
LOG_block("DownloadUpdatedFiles");
|
||
|
|
||
|
int index = GetHandleIndex(hConnection);
|
||
|
if (-1 == index)
|
||
|
{
|
||
|
LOG_error("invalid handle");
|
||
|
SetLastError(ERROR_INVALID_HANDLE);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (NULL == puRequiredSize)
|
||
|
{
|
||
|
LOG_error("puRequiredSize == NULL");
|
||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
//Check and see if the download path is large enough to contain the return
|
||
|
//directory where we will put the download cab files.
|
||
|
TCHAR szTmpPath[MAX_PATH];
|
||
|
int iLengthNeeded = GetDownloadPath(szTmpPath);
|
||
|
|
||
|
if (lpDownloadPath == NULL || iLengthNeeded > (int)uSize)
|
||
|
{
|
||
|
LOG_error("uSize < then needed");
|
||
|
*puRequiredSize = iLengthNeeded;
|
||
|
SetLastError(ERROR_BUFFER_OVERFLOW);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
// Declared locally
|
||
|
typedef long (*PFN_GETPACKAGE)(PCONTEXTHANDLE pContextHandle, PDOWNLOADINFO pDownloadInfo, LPTSTR lpDownloadPath);
|
||
|
PFN_GETPACKAGE pfnGetPackage = NULL;//Entry point in cdm.dll that actually performs the download
|
||
|
|
||
|
|
||
|
// If there is cdmnew.dll in system directory use it
|
||
|
auto_hlib hlib = LoadCdmnewDll();
|
||
|
if (hlib.valid())
|
||
|
{
|
||
|
pfnGetPackage = (PFN_GETPACKAGE)GetProcAddress(hlib,"GetPackage");
|
||
|
if (NULL == pfnGetPackage)
|
||
|
{
|
||
|
//if we cannot find our download function we need to return fail and not attempt
|
||
|
//to download the update package.
|
||
|
LOG_error("cannot find function 'GetPackage'");
|
||
|
return FALSE;
|
||
|
}
|
||
|
LOG_out("Calling GetPackage() from cdmnew.dll");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Declared locally
|
||
|
long GetPackage(IN PCONTEXTHANDLE pContextHandle, IN PDOWNLOADINFO pDownloadInfo, OUT LPTSTR lpDownloadPath);
|
||
|
pfnGetPackage = GetPackage;
|
||
|
LOG_out("Calling internal GetPackage()");
|
||
|
}
|
||
|
int iError = (pfnGetPackage)(&g_handleArray[index], pDownloadInfo, szTmpPath);
|
||
|
|
||
|
if (iError != NO_ERROR)
|
||
|
{
|
||
|
SetLastError(iError);
|
||
|
return FALSE;
|
||
|
}
|
||
|
*puRequiredSize = iLengthNeeded;
|
||
|
lstrcpyW(lpDownloadPath, T2W(szTmpPath));
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
//This API closes the internet connection opened with the OpenCDMContext() API.
|
||
|
//If CDM did not open the internet connection this API simply returns. The CDM
|
||
|
//context handle must have been the same handle that was returned from
|
||
|
//the OpenCDMContext() API.
|
||
|
//
|
||
|
//This call cannot fail. If the pConnection handle is invalid this function
|
||
|
//simply ignores it.
|
||
|
|
||
|
VOID WINAPI CloseCDMContext (
|
||
|
IN HANDLE hConnection //CDM Connection handle returned with OpenCDMContext.
|
||
|
) {
|
||
|
LOG_block("CloseCDMContext");
|
||
|
|
||
|
int index = GetHandleIndex(hConnection);
|
||
|
|
||
|
if ( -1 == index)
|
||
|
{
|
||
|
LOG_error("invalid handle");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//If CDM.DLL opened this internet connection and if this connection is
|
||
|
//for a modem then we need to close the internet connection. Note:
|
||
|
//the Open context function only sets fCloseConnection for modem
|
||
|
//connections.
|
||
|
|
||
|
if (g_handleArray[index].fCloseConnection)
|
||
|
InternetAutodialHangup(0);
|
||
|
|
||
|
if (g_handleArray[index].fNeedUpdate)
|
||
|
{
|
||
|
//if any dll needs to be updated then
|
||
|
//we set the global update flag. This will
|
||
|
//force cdm.dll to be replaced when the last
|
||
|
//process detaches.
|
||
|
g_fNeedUpdate = true;
|
||
|
}
|
||
|
|
||
|
g_handleArray.remove(index);
|
||
|
}
|
||
|
|
||
|
int WINAPI QueryDetectionFiles(
|
||
|
IN HANDLE hConnection,
|
||
|
IN void* pCallbackParam,
|
||
|
IN PFN_QueryDetectionFilesCallback pCallback
|
||
|
) {
|
||
|
LOG_block("QueryDetectionFiles");
|
||
|
|
||
|
int index = GetHandleIndex(hConnection);
|
||
|
if (-1 == index)
|
||
|
{
|
||
|
LOG_error("invalid handle");
|
||
|
SetLastError(ERROR_INVALID_HANDLE);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
// Call external/internal implementetion
|
||
|
typedef int (*PFN_InternalQueryDetectionFiles)(IN PCONTEXTHANDLE pContextHandle, IN void* pCallbackParam, IN PFN_QueryDetectionFilesCallback pCallback);
|
||
|
PFN_InternalQueryDetectionFiles pfnInternalQueryDetectionFiles = NULL;
|
||
|
|
||
|
auto_hlib hlib = LoadCdmnewDll();
|
||
|
if (hlib.valid())
|
||
|
{
|
||
|
pfnInternalQueryDetectionFiles = (PFN_InternalQueryDetectionFiles)GetProcAddress(hlib, "InternalQueryDetectionFiles");
|
||
|
if (NULL == pfnInternalQueryDetectionFiles)
|
||
|
{
|
||
|
LOG_error("cannot find function 'InternalQueryDetectionFiles'");
|
||
|
return FALSE;
|
||
|
}
|
||
|
LOG_out("Calling InternalQueryDetectionFiles() from cdmnew.dll");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Declared locally
|
||
|
int InternalQueryDetectionFiles(IN PCONTEXTHANDLE pContextHandle, IN void* pCallbackParam, IN PFN_QueryDetectionFilesCallback pCallback);
|
||
|
pfnInternalQueryDetectionFiles = InternalQueryDetectionFiles;
|
||
|
LOG_out("Calling internal InternalQueryDetectionFiles()");
|
||
|
}
|
||
|
return (pfnInternalQueryDetectionFiles)(&g_handleArray[index], pCallbackParam, pCallback);
|
||
|
}
|
||
|
|
||
|
void WINAPI DetFilesDownloaded(
|
||
|
IN HANDLE hConnection
|
||
|
) {
|
||
|
LOG_block("DetFilesDownloaded");
|
||
|
|
||
|
int index = GetHandleIndex(hConnection);
|
||
|
if (-1 == index)
|
||
|
{
|
||
|
LOG_error("invalid handle");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Call external/internal implementetion
|
||
|
typedef void (*PFN_InternalDetFilesDownloaded)(IN PCONTEXTHANDLE pContextHandle);
|
||
|
PFN_InternalDetFilesDownloaded pfnInternalDetFilesDownloaded = NULL;
|
||
|
|
||
|
auto_hlib hlib = LoadCdmnewDll();
|
||
|
if (hlib.valid())
|
||
|
{
|
||
|
pfnInternalDetFilesDownloaded = (PFN_InternalDetFilesDownloaded)GetProcAddress(hlib, "InternalDetFilesDownloaded");
|
||
|
if (NULL == pfnInternalDetFilesDownloaded)
|
||
|
{
|
||
|
LOG_error("cannot find function 'InternalDetFilesDownloaded'");
|
||
|
return;
|
||
|
}
|
||
|
LOG_out("Calling InternalDetFilesDownloaded() from cdmnew.dll");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Declared locally
|
||
|
void InternalDetFilesDownloaded(IN PCONTEXTHANDLE pContextHandle);
|
||
|
pfnInternalDetFilesDownloaded = InternalDetFilesDownloaded;
|
||
|
LOG_out("Calling internal InternalDetFilesDownloaded()");
|
||
|
}
|
||
|
(pfnInternalDetFilesDownloaded)(&g_handleArray[index]);
|
||
|
}
|
||
|
|
||
|
// supports offline logging
|
||
|
// hConnection NOT used at all
|
||
|
// no network connection or osdet.dll needed for languauge, SKU, platform detection
|
||
|
void WINAPI LogDriverNotFound(
|
||
|
IN HANDLE hConnection,
|
||
|
IN LPCWSTR lpDeviceInstanceID,
|
||
|
IN DWORD dwFlags
|
||
|
) {
|
||
|
LOG_block("LogDriverNotFound");
|
||
|
|
||
|
// Call external/internal implementetion
|
||
|
typedef void (*PFN_InternalLogDriverNotFound)(IN PCONTEXTHANDLE pContextHandle, IN LPCWSTR lpDeviceInstanceID, IN DWORD dwFlags);
|
||
|
PFN_InternalLogDriverNotFound pfnInternalLogDriverNotFound = NULL;
|
||
|
CONTEXTHANDLE cth;
|
||
|
|
||
|
ZeroMemory(&cth, sizeof(cth));
|
||
|
|
||
|
auto_hlib hlib = LoadCdmnewDll();
|
||
|
if (hlib.valid())
|
||
|
{
|
||
|
pfnInternalLogDriverNotFound = (PFN_InternalLogDriverNotFound)GetProcAddress(hlib, "InternalLogDriverNotFound");
|
||
|
if (NULL == pfnInternalLogDriverNotFound)
|
||
|
{
|
||
|
LOG_error("cannot find function 'InternalLogDriverNotFound'");
|
||
|
return;
|
||
|
}
|
||
|
LOG_out("Calling InternalLogDriverNotFound() from cdmnew.dll");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Declared locally
|
||
|
void InternalLogDriverNotFound(IN PCONTEXTHANDLE pContextHandle, IN LPCWSTR lpDeviceInstanceID, IN DWORD dwFlags);
|
||
|
pfnInternalLogDriverNotFound = InternalLogDriverNotFound;
|
||
|
LOG_out("Calling internal InternalLogDriverNotFound()");
|
||
|
}
|
||
|
// pass in dummy contexthandle
|
||
|
(pfnInternalLogDriverNotFound)(&cth, lpDeviceInstanceID, dwFlags);
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL WINAPI FindMatchingDriver(
|
||
|
IN HANDLE hConnection,
|
||
|
IN PDOWNLOADINFO pDownloadInfo,
|
||
|
OUT PWUDRIVERINFO pWuDriverInfo
|
||
|
) {
|
||
|
LOG_block("FindMatchingDriver");
|
||
|
|
||
|
int index = GetHandleIndex(hConnection);
|
||
|
if (-1 == index)
|
||
|
{
|
||
|
LOG_error("invalid handle");
|
||
|
SetLastError(ERROR_INVALID_HANDLE);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
// Call external/internal implementetion
|
||
|
typedef BOOL (*PFN_InternalFindMatchingDriver)(IN PCONTEXTHANDLE pContextHandle, IN PDOWNLOADINFO pDownloadInfo, OUT PWUDRIVERINFO pWuDriverInfo);
|
||
|
PFN_InternalFindMatchingDriver pfnInternalFindMatchingDriver = NULL;
|
||
|
|
||
|
auto_hlib hlib = LoadCdmnewDll();
|
||
|
if (hlib.valid())
|
||
|
{
|
||
|
pfnInternalFindMatchingDriver = (PFN_InternalFindMatchingDriver)GetProcAddress(hlib,"InternalFindMatchingDriver");
|
||
|
if (NULL == pfnInternalFindMatchingDriver)
|
||
|
{
|
||
|
LOG_error("cannot find function 'InternalFindMatchingDriver'");
|
||
|
return FALSE;
|
||
|
}
|
||
|
LOG_out("Calling InternalFindMatchingDriver() from cdmnew.dll");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Declared locally
|
||
|
BOOL InternalFindMatchingDriver(IN PCONTEXTHANDLE pContextHandle, IN PDOWNLOADINFO pDownloadInfo, OUT PWUDRIVERINFO pWuDriverInfo);
|
||
|
pfnInternalFindMatchingDriver = InternalFindMatchingDriver;
|
||
|
LOG_out("Calling internal InternalFindMatchingDriver()");
|
||
|
}
|
||
|
return (pfnInternalFindMatchingDriver)(&g_handleArray[index], pDownloadInfo, pWuDriverInfo);
|
||
|
}
|
||
|
|
||
|
|
||
|
//This function is called to download the actual package. What happens is that the
|
||
|
//cdm.dll is copied from the server. This dll is then dynamically loaded by the
|
||
|
//DownloadGetUpdatedFiles() API and called. This allows the most recent cdm.dll
|
||
|
//to be used even if the client has an out dated version on their system.
|
||
|
//
|
||
|
//If this function is successfull then it returns NO_ERROR. If the case of a
|
||
|
//failure this function returns an error code.
|
||
|
|
||
|
long GetPackage(
|
||
|
IN PCONTEXTHANDLE pContextHandle, //Pointer Context handle structure that contains the server and dll information needed to perform the download.
|
||
|
IN PDOWNLOADINFO pDownloadInfo, //download information structure describing package to be read from server
|
||
|
OUT LPTSTR lpDownloadPath //Poitner to local directory on the client computer system where the downloaded files are to be stored.
|
||
|
) {
|
||
|
LOG_block("GetPackage");
|
||
|
|
||
|
USES_CONVERSION;
|
||
|
|
||
|
SHelper helper;
|
||
|
//
|
||
|
// NTRAID#NTBUG9-185297-2000/11/21-waltw Fixed: bufBucket must have same scope as SHelper
|
||
|
//
|
||
|
byte_buffer bufBucket;
|
||
|
DWORD dwError = PrepareCatalog(pContextHandle->szSiteServer, helper);
|
||
|
if (NO_ERROR != dwError)
|
||
|
{
|
||
|
SetLastError(dwError);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
//Clear out any files that might be in the temp download directory.
|
||
|
if (!DeleteNode(lpDownloadPath))
|
||
|
{
|
||
|
LOG_out("DeleteNode(%s) failed last error %d", lpDownloadPath, GetLastError());
|
||
|
}
|
||
|
if (!CreateDirectory(lpDownloadPath, NULL))
|
||
|
{
|
||
|
LOG_out("CreateDirectory(%s) failed last error %d", lpDownloadPath, GetLastError());
|
||
|
}
|
||
|
|
||
|
|
||
|
bool fPlist = (
|
||
|
NULL != pDownloadInfo->lpHardwareIDs &&
|
||
|
0 == lstrcmpiW(L"3FBF5B30-DEB4-11D1-AC97-00A0C903492B", pDownloadInfo->lpHardwareIDs)
|
||
|
);
|
||
|
|
||
|
// Get to and from information
|
||
|
TCHAR szCabLocalFile[MAX_PATH];
|
||
|
GetWindowsUpdateDirectory(szCabLocalFile);
|
||
|
|
||
|
if (fPlist) {
|
||
|
TCHAR szCabServerFile[MAX_PATH];
|
||
|
wsprintf(szCabServerFile, _T("%d_%#08x.plist"), helper.enPlatform, helper.dwLangID);
|
||
|
LOG_out("getting PLIST %s", szCabServerFile);
|
||
|
|
||
|
PathAppend(szCabLocalFile, szCabServerFile);
|
||
|
|
||
|
// Now we can say that we are ready
|
||
|
if (!helper.download.Copy(szCabServerFile, szCabLocalFile))
|
||
|
{
|
||
|
LOG_error("%s failed to download", szCabServerFile);
|
||
|
return ERROR_FILE_NOT_FOUND;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
TCHAR szCabFileTitle[MAX_PATH];
|
||
|
if (!FindUpdate(pDownloadInfo, helper, bufBucket))
|
||
|
{
|
||
|
LOG_error("no update has been found");
|
||
|
return ERROR_FILE_NOT_FOUND;
|
||
|
}
|
||
|
LOG_out("PUID %d is found", helper.puid);
|
||
|
|
||
|
CDownload downloadCabpool;
|
||
|
if (downloadCabpool.Connect(pContextHandle->szDownloadServer))
|
||
|
{
|
||
|
LOG_out("Connected to DownloadServer '%s'", pContextHandle->szDownloadServer);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
LOG_error("No connection to DownloadServer '%s'", pContextHandle->szDownloadServer);
|
||
|
return ERROR_GEN_FAILURE;
|
||
|
}
|
||
|
TCHAR szCabServerFile[MAX_PATH];
|
||
|
lstrcpy(szCabServerFile, _T("CabPool/"));
|
||
|
lstrcat(szCabServerFile, A2T(helper.DriverMatchInfo.pszCabFileTitle));
|
||
|
|
||
|
PathAppend(szCabLocalFile, A2T(helper.DriverMatchInfo.pszCabFileTitle));
|
||
|
|
||
|
// Now we can say that we are ready
|
||
|
if (!downloadCabpool.Copy(szCabServerFile, szCabLocalFile))
|
||
|
{
|
||
|
LOG_error("%s failed to download", szCabServerFile);
|
||
|
URLPingReport(helper, URLPING_FAILED);
|
||
|
return ERROR_FILE_NOT_FOUND;
|
||
|
}
|
||
|
|
||
|
// Verify if it's not webntprn.cab
|
||
|
HRESULT hr = VerifyFile(szCabLocalFile, FALSE);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
LOG_error("signature verification failed");
|
||
|
DeleteFile(szCabLocalFile);
|
||
|
URLPingReport(helper, URLPING_FAILED);
|
||
|
return hr;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
TCHAR szDownloadFiles[MAX_PATH];
|
||
|
lstrcpy(szDownloadFiles, lpDownloadPath);
|
||
|
PathAppend(szDownloadFiles, _T("*"));
|
||
|
if (!helper.diamond.Decompress(szCabLocalFile, szDownloadFiles))
|
||
|
{
|
||
|
LOG_error("Decompress failed");
|
||
|
if (!fPlist)
|
||
|
URLPingReport(helper, URLPING_FAILED);
|
||
|
return ERROR_FILE_NOT_FOUND;
|
||
|
}
|
||
|
LOG_out("Download to %s completed OK", lpDownloadPath);
|
||
|
DeleteFile(szCabLocalFile);
|
||
|
if (!fPlist)
|
||
|
URLPingReport(helper, URLPING_SUCCESS);
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
static void UrlAppend(LPTSTR pszURL, LPCTSTR pszPath)
|
||
|
{
|
||
|
if ('/' != pszURL[lstrlen(pszURL) - 1])
|
||
|
lstrcat(pszURL, _T("/"));
|
||
|
lstrcat(pszURL, pszPath);
|
||
|
}
|
||
|
|
||
|
|
||
|
inline bool IsNewer(
|
||
|
IN LPCTSTR szFileName1,
|
||
|
IN LPCTSTR szFileName2
|
||
|
) {
|
||
|
LOG_block("IsNewer");
|
||
|
auto_hfile hFile1 = CreateFile(szFileName1, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||
|
if (!hFile1.valid())
|
||
|
{
|
||
|
LOG_error("CreateFile(%s, ...) failed, error %d", szFileName1, GetLastError());
|
||
|
return true;
|
||
|
}
|
||
|
auto_hfile hFile2 = CreateFile(szFileName2, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||
|
if (!hFile2.valid())
|
||
|
{
|
||
|
LOG_error("CreateFile(%s, ...) failed, error %d", szFileName2, GetLastError());
|
||
|
return false;
|
||
|
}
|
||
|
FILETIME ft1;
|
||
|
if (!GetFileTime(hFile1, NULL, NULL, &ft1))
|
||
|
{
|
||
|
LOG_error("GetFileTime(%s, ...) failed, error %d", szFileName1, GetLastError());
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
FILETIME ft2;
|
||
|
if (!GetFileTime(hFile2, NULL, NULL, &ft2))
|
||
|
{
|
||
|
LOG_error("GetFileTime(%s, ...) failed, error %d", szFileName2, GetLastError());
|
||
|
return false;
|
||
|
}
|
||
|
return CompareFileTime(&ft1, &ft2) < 0;
|
||
|
|
||
|
}
|
||
|
|
||
|
void DoCallback(
|
||
|
IN void* pCallbackParam, IN PFN_QueryDetectionFilesCallback pCallback,
|
||
|
SHelper& helper, LPCTSTR pszSiteServer, LPCTSTR pszFileTitle, bool fInCatalog = true
|
||
|
) {
|
||
|
USES_CONVERSION;
|
||
|
|
||
|
TCHAR szCatalog[32];
|
||
|
wsprintf(szCatalog, _T("%d"), helper.puidCatalog);
|
||
|
|
||
|
TCHAR szURL[INTERNET_MAX_URL_LENGTH];
|
||
|
lstrcpy(szURL, pszSiteServer);
|
||
|
if (fInCatalog)
|
||
|
UrlAppend(szURL, szCatalog);
|
||
|
UrlAppend(szURL, pszFileTitle);
|
||
|
|
||
|
TCHAR szLocalFile[MAX_PATH];
|
||
|
GetWindowsUpdateDirectory(szLocalFile);
|
||
|
PathAppend(szLocalFile, pszFileTitle);
|
||
|
|
||
|
pCallback(pCallbackParam, T2W(szURL), T2W(szLocalFile));
|
||
|
}
|
||
|
|
||
|
|
||
|
int InternalQueryDetectionFiles(IN PCONTEXTHANDLE pContextHandle, IN void* pCallbackParam, IN PFN_QueryDetectionFilesCallback pCallback)
|
||
|
{
|
||
|
LOG_block("InternalQueryDetectionFiles");
|
||
|
|
||
|
SHelper helper;
|
||
|
DWORD dwError = PrepareCatalog(pContextHandle->szSiteServer, helper);
|
||
|
if (NO_ERROR != dwError)
|
||
|
{
|
||
|
SetLastError(dwError);
|
||
|
return -1;
|
||
|
}
|
||
|
#if 0
|
||
|
// Get CDM inventory
|
||
|
TCHAR szPath[MAX_PATH];
|
||
|
wsprintf(szPath, _T("%d/%d.cab"), helper.puidCatalog, helper.puidCatalog);
|
||
|
|
||
|
TCHAR szURL[INTERNET_MAX_URL_LENGTH];
|
||
|
lstrcpy(szURL, pContextHandle->szSiteServer);
|
||
|
UrlAppend(szURL, szPath);
|
||
|
|
||
|
GetWindowsUpdateDirectory(szPath);
|
||
|
PathAppend(szPath, _T("buckets.cab"));
|
||
|
|
||
|
pCallback(pCallbackParam, T2W(szURL), T2W(szPath));
|
||
|
return 1;
|
||
|
#else
|
||
|
// Get CDM inventory
|
||
|
TCHAR szPath[MAX_PATH];
|
||
|
wsprintf(szPath, _T("%d/inventory.cdm"), helper.puidCatalog);
|
||
|
|
||
|
byte_buffer bufInventory;
|
||
|
if (!DownloadToBuffer(helper, szPath, bufInventory))
|
||
|
{
|
||
|
LOG_error("Dowload inventory failed");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
//Here we need a trick to determine if we need to do anything: we do if inventory.cdm is a newer then inventory.cdm.last
|
||
|
GetWindowsUpdateDirectory(szPath);
|
||
|
PathAppend(szPath, _T("inventory.cdm"));
|
||
|
TCHAR szPathLast[MAX_PATH];
|
||
|
lstrcpy(szPathLast, szPath);
|
||
|
lstrcat(szPathLast, _T(".last"));
|
||
|
if (!IsNewer(szPathLast, szPath))
|
||
|
{
|
||
|
LOG_out("inventory.cdm is up to date");
|
||
|
return 0;
|
||
|
}
|
||
|
CopyFile(szPath, szPathLast, FALSE);
|
||
|
|
||
|
PCDM_HASHTABLE pHashTable = (PCDM_HASHTABLE)(LPBYTE)bufInventory;
|
||
|
|
||
|
int nCount = 0;
|
||
|
DoCallback(pCallbackParam, pCallback, helper, pContextHandle->szSiteServer, _T("oeminfo.bin"), false);
|
||
|
nCount ++;
|
||
|
DoCallback(pCallbackParam, pCallback, helper, pContextHandle->szSiteServer, _T("bitmask.cdm"));
|
||
|
nCount ++;
|
||
|
|
||
|
for (ULONG ulHashIndex = 0; ulHashIndex < pHashTable->hdr.iTableSize; ulHashIndex ++)
|
||
|
{
|
||
|
if(GETBIT(pHashTable->pData, ulHashIndex))
|
||
|
{
|
||
|
TCHAR szTitle[16];
|
||
|
wsprintf(szTitle, _T("%d.bkf"), ulHashIndex);
|
||
|
DoCallback(pCallbackParam, pCallback, helper, pContextHandle->szSiteServer, szTitle);
|
||
|
nCount ++;
|
||
|
}
|
||
|
}
|
||
|
return nCount;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
void InternalDetFilesDownloaded(IN PCONTEXTHANDLE pContextHandle)
|
||
|
{
|
||
|
LOG_block("InternalDetFilesDownloaded");
|
||
|
#if 0
|
||
|
TCHAR szPath[MAX_PATH];
|
||
|
GetWindowsUpdateDirectory(szPath);
|
||
|
PathAppend(szPath, _T("buckets.cab"));
|
||
|
|
||
|
CDiamond diamond;
|
||
|
diamond.Decompress(szPath, _T("*"));
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
|
||
|
// pContextHandle not used.
|
||
|
// dwFlags could be either 0 or BEGINLOGFLAG
|
||
|
void InternalLogDriverNotFound(IN PCONTEXTHANDLE pContextHandle, IN LPCWSTR lpDeviceInstanceID, IN DWORD dwFlags)
|
||
|
{
|
||
|
LOG_block("InternalLogDriverNotFound");
|
||
|
LOG_out("DeviceInstanceID is %s", lpDeviceInstanceID);
|
||
|
|
||
|
using std::vector;
|
||
|
|
||
|
DWORD bytes;
|
||
|
//auto_pointer<IDrvInfo> pDrvInfo;
|
||
|
tchar_buffer bufText;
|
||
|
TCHAR tszFilename[MAX_PATH];
|
||
|
TCHAR tszUniqueFilename[MAX_PATH];
|
||
|
TCHAR tszBuffer[32];
|
||
|
DEVINST devinst;
|
||
|
HRESULT hr = E_FAIL;
|
||
|
bool fXmlFileError = false;
|
||
|
static vector<WCHAR*> vDIDList; //device instance id list
|
||
|
LPWSTR pDID = NULL; //Device Instance ID
|
||
|
FILE * fOut = NULL; //for XML file
|
||
|
SHelper helper;
|
||
|
HANDLE hFile = NULL;
|
||
|
|
||
|
|
||
|
lstrcpy(tszFilename, _T("")); //initialize tszFilename
|
||
|
if (lpDeviceInstanceID != NULL)
|
||
|
{ //append the new device instance id into internal list
|
||
|
pDID = (LPWSTR) malloc((wcslen(lpDeviceInstanceID)+1) * sizeof(WCHAR));
|
||
|
if (NULL == pDID)
|
||
|
{
|
||
|
LOG_error("memory allocation failed for new DeviceInstanceID");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
lstrcpyW(pDID, lpDeviceInstanceID);
|
||
|
vDIDList.push_back(pDID);
|
||
|
LOG_out("new DeviceInstanceID added to internal list");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (0 == (dwFlags & BEGINLOGFLAG) || 0 == vDIDList.size())
|
||
|
{ // not last log request or nothing to log
|
||
|
LOG_out("Won't log to hardware_XXX.xml");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
GetWindowsUpdateDirectory(tszFilename);
|
||
|
hr = GetUniqueFileName(tszFilename,tszUniqueFilename, MAX_PATH, hFile);
|
||
|
if (S_OK != hr)
|
||
|
{
|
||
|
LOG_error("fail to get unique file name");
|
||
|
fXmlFileError = true;
|
||
|
goto CloseXML;
|
||
|
}
|
||
|
lstrcat(tszFilename, tszUniqueFilename);
|
||
|
CloseHandle(hFile);
|
||
|
fOut = _tfopen(tszFilename, _T("wb"));
|
||
|
if (! fOut)
|
||
|
{
|
||
|
LOG_error("_tfopen failed");
|
||
|
fXmlFileError = true;
|
||
|
DeleteFile(tszFilename);
|
||
|
goto CloseXML;
|
||
|
}
|
||
|
|
||
|
LOG_out("Logging to %s", tszFilename);
|
||
|
|
||
|
|
||
|
// Don't need to get langID and platformID from catalog
|
||
|
// get it offline using osdet.dll
|
||
|
if (S_OK != ProcessOsdetOffline(helper))
|
||
|
{
|
||
|
LOG_error("platform and language detection failed");
|
||
|
fXmlFileError = true;
|
||
|
goto CloseXML;
|
||
|
}
|
||
|
|
||
|
_tstrdate(tszBuffer);
|
||
|
|
||
|
#ifdef _UNICODE
|
||
|
fwprintf(fOut, _T("%c"), (int) 0xFEFF);
|
||
|
#else
|
||
|
#error _UNICODE must be defined for InternalLogDriverNotFound
|
||
|
#endif
|
||
|
|
||
|
TCHAR tszSKU[SKU_STRING_MAX_LENGTH];
|
||
|
hr = GetSKUString(tszSKU, SKU_STRING_MAX_LENGTH);
|
||
|
if (S_OK != hr)
|
||
|
{
|
||
|
LOG_error("Fail to get SKU string");
|
||
|
fXmlFileError = true;
|
||
|
goto CloseXML;
|
||
|
}
|
||
|
if (0 > _ftprintf(fOut, _T("<?xml version=\"1.0\"?>\r\n<inventory date=\"%s\" locale=\"%p\" platform=\"%d\" sku=\"%s\">\r\n"), tszBuffer, helper.dwLangID, helper.enPlatform, tszSKU))
|
||
|
{
|
||
|
fXmlFileError = true;
|
||
|
goto CloseXML;
|
||
|
}
|
||
|
|
||
|
for (int i = 0; i < vDIDList.size(); i++)
|
||
|
{
|
||
|
pDID = vDIDList[i];
|
||
|
|
||
|
//
|
||
|
// NTBUG9#151928 - Log both hardware and compatible IDs of the device that matches lpDeviceInstanceID
|
||
|
//
|
||
|
|
||
|
LOG_out("Log device instance with id %s", pDID);
|
||
|
if (CR_SUCCESS == CM_Locate_DevNode(&devinst, (LPWSTR) pDID, 0))
|
||
|
{
|
||
|
if (0 > _ftprintf(fOut, _T("\t<device>\r\n")))
|
||
|
{
|
||
|
fXmlFileError = true;
|
||
|
goto CloseXML;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Log device description
|
||
|
//
|
||
|
ULONG ulLength = 0;
|
||
|
if (CR_BUFFER_SMALL == CM_Get_DevNode_Registry_Property(devinst, CM_DRP_DEVICEDESC, NULL, NULL, &ulLength, 0))
|
||
|
{
|
||
|
bufText.resize(ulLength);
|
||
|
|
||
|
if (bufText.valid() &&
|
||
|
CR_SUCCESS == CM_Get_DevNode_Registry_Property(devinst, CM_DRP_DEVICEDESC, NULL, bufText, &ulLength, 0))
|
||
|
{
|
||
|
if (0 > _ftprintf(fOut, _T("\t\t<description><![CDATA[%s]]></description>\r\n"), (LPCTSTR) bufText))
|
||
|
{
|
||
|
fXmlFileError = true;
|
||
|
goto CloseXML;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//
|
||
|
// Log all the hardware IDs
|
||
|
//
|
||
|
ulLength = 0;
|
||
|
if (CR_BUFFER_SMALL == CM_Get_DevNode_Registry_Property(devinst, CM_DRP_HARDWAREID, NULL, NULL, &ulLength, 0))
|
||
|
{
|
||
|
bufText.resize(ulLength);
|
||
|
|
||
|
if (bufText.valid() &&
|
||
|
CR_SUCCESS == CM_Get_DevNode_Registry_Property(devinst, CM_DRP_HARDWAREID, NULL, bufText, &ulLength, 0))
|
||
|
{
|
||
|
for (TCHAR* pszNextID = (TCHAR*) bufText; *pszNextID; pszNextID += (lstrlen(pszNextID) + 1))
|
||
|
{
|
||
|
if (0 > _ftprintf(fOut, _T("\t\t<hwid><![CDATA[%s]]></hwid>\r\n"), (LPCTSTR) pszNextID))
|
||
|
{
|
||
|
fXmlFileError = true;
|
||
|
goto CloseXML;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Log all the compatible IDs
|
||
|
//
|
||
|
ulLength = 0;
|
||
|
if (CR_BUFFER_SMALL == CM_Get_DevNode_Registry_Property(devinst, CM_DRP_COMPATIBLEIDS, NULL, NULL, &ulLength, 0))
|
||
|
{
|
||
|
bufText.resize(ulLength);
|
||
|
|
||
|
if (bufText.valid() &&
|
||
|
CR_SUCCESS == CM_Get_DevNode_Registry_Property(devinst, CM_DRP_COMPATIBLEIDS, NULL, bufText, &ulLength, 0))
|
||
|
{
|
||
|
for (TCHAR* pszNextID = (TCHAR*) bufText; *pszNextID; pszNextID += (lstrlen(pszNextID) + 1))
|
||
|
{
|
||
|
if (0 > _ftprintf(fOut, _T("\t\t<compid><![CDATA[%s]]></compid>\r\n"), (LPCTSTR) pszNextID))
|
||
|
{
|
||
|
fXmlFileError = true;
|
||
|
goto CloseXML;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (0 > _ftprintf(fOut, _T("\t</device>\r\n")))
|
||
|
{
|
||
|
fXmlFileError = true;
|
||
|
goto CloseXML;
|
||
|
}
|
||
|
}
|
||
|
} //for
|
||
|
|
||
|
if(0 > _ftprintf(fOut, _T("</inventory>\r\n")))
|
||
|
{
|
||
|
fXmlFileError = true;
|
||
|
}
|
||
|
|
||
|
CloseXML:
|
||
|
if (fOut != NULL) fclose(fOut);
|
||
|
for (int i = 0; i < vDIDList.size(); i++)
|
||
|
{//free memory
|
||
|
free(vDIDList[i]);
|
||
|
}
|
||
|
vDIDList.clear();
|
||
|
|
||
|
//
|
||
|
// Open Help Center only if we have valid xml
|
||
|
//
|
||
|
if (!fXmlFileError)
|
||
|
{
|
||
|
// open help center
|
||
|
const static TCHAR szBase[] = _T("hcp://services/layout/contentonly?topic=hcp://system/dfs/uplddrvinfo.htm%3f"); //hardcode '?' escaping
|
||
|
tchar_buffer tchCName(MAX_PATH); //file name canonicalized once
|
||
|
tchar_buffer tchC2Name(INTERNET_MAX_URL_LENGTH); //file name canonicalized twice
|
||
|
tchar_buffer tchFinalUrl;
|
||
|
DWORD dwLen = 0;
|
||
|
BOOL fBufferResized = FALSE;
|
||
|
|
||
|
GetWindowsUpdateDirectory(tszFilename);
|
||
|
lstrcat(tszFilename, tszUniqueFilename);
|
||
|
|
||
|
LOG_out("Canonicalize %s", tszFilename);
|
||
|
|
||
|
if (FAILED(CdmCanonicalizeUrl(tszFilename, tchCName, MAX_PATH, 0)))
|
||
|
{
|
||
|
goto CleanUp;
|
||
|
}
|
||
|
|
||
|
LOG_out("File name canonicalized %s", (LPTSTR) tchCName);
|
||
|
LOG_out("Canonicalize file name %s AGAIN", (LPTSTR)tchCName);
|
||
|
|
||
|
if (FAILED(CdmCanonicalizeUrl((LPCTSTR)tchCName, tchC2Name, INTERNET_MAX_URL_LENGTH, ICU_ENCODE_PERCENT)))
|
||
|
{
|
||
|
goto CleanUp;
|
||
|
}
|
||
|
|
||
|
LOG_out("File name canonicalized twice %s", (LPTSTR)tchC2Name);
|
||
|
|
||
|
//need one extra character space
|
||
|
//for the ending null
|
||
|
tchFinalUrl.resize(lstrlen(szBase) + lstrlen((LPCTSTR) tchC2Name) + 1);
|
||
|
if (!tchFinalUrl.valid())
|
||
|
{
|
||
|
LOG_error("Out of memory for FinalUrl buffer");
|
||
|
goto CleanUp;
|
||
|
}
|
||
|
|
||
|
wsprintf(tchFinalUrl, _T("%s%s"), szBase, (LPCTSTR) tchC2Name);
|
||
|
|
||
|
LOG_out("Opening HelpCenter: \"%s\"", (LPCTSTR) tchFinalUrl);
|
||
|
ShellExecute(NULL, NULL, (LPCTSTR) tchFinalUrl, NULL, NULL, SW_SHOWNORMAL);
|
||
|
return; //keep the file and return
|
||
|
}
|
||
|
|
||
|
//remove the file generated
|
||
|
CleanUp:
|
||
|
if (fOut != NULL)
|
||
|
{
|
||
|
DeleteFile(tszFilename);
|
||
|
fOut = NULL;
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
BOOL InternalFindMatchingDriver(IN PCONTEXTHANDLE pContextHandle, IN PDOWNLOADINFO pDownloadInfo, OUT PWUDRIVERINFO pWuDriverInfo)
|
||
|
{
|
||
|
LOG_block("InternalFindMatchingDriver");
|
||
|
|
||
|
bool fConnected = IsInternetConnected();
|
||
|
#ifdef _WUV3TEST
|
||
|
if (fConnected)
|
||
|
{
|
||
|
// catalog spoofing
|
||
|
DWORD dwIsInternetConnected = 1;
|
||
|
DWORD dwSize = sizeof(dwIsInternetConnected);
|
||
|
auto_hkey hkey;
|
||
|
if (NO_ERROR == RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGKEY_WUV3TEST, 0, KEY_READ, &hkey)) {
|
||
|
RegQueryValueEx(hkey, _T("IsInternetConnected"), 0, 0, (LPBYTE)&dwIsInternetConnected, &dwSize);
|
||
|
}
|
||
|
// only then do normal
|
||
|
if (0 == dwIsInternetConnected)
|
||
|
{
|
||
|
fConnected = false;
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
SHelper helper;
|
||
|
//
|
||
|
// NTRAID#NTBUG9-185297-2000/11/21-waltw Fixed: bufBucket must have same scope as SHelper
|
||
|
//
|
||
|
byte_buffer bufBucket;
|
||
|
DWORD dwError = PrepareCatalog(fConnected ? pContextHandle->szSiteServer : NULL, helper);
|
||
|
if (NO_ERROR != dwError)
|
||
|
{
|
||
|
SetLastError(dwError);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (!FindUpdate(pDownloadInfo, helper, bufBucket))
|
||
|
{
|
||
|
LOG_out("NO UPDATE IS FOUND");
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
LOG_out("PUID %d IS FOUND", helper.puid);
|
||
|
// Fill out info
|
||
|
if (
|
||
|
0 == MultiByteToWideChar(CP_ACP, 0, helper.DriverMatchInfo.pszHardwareID, -1, pWuDriverInfo->wszHardwareID, HWID_LEN) ||
|
||
|
0 == MultiByteToWideChar(CP_ACP, 0, helper.DriverMatchInfo.pszDescription, -1, pWuDriverInfo->wszDescription, LINE_LEN) ||
|
||
|
0 == MultiByteToWideChar(CP_ACP, 0, helper.DriverMatchInfo.pszMfgName, -1, pWuDriverInfo->wszMfgName, LINE_LEN) ||
|
||
|
0 == MultiByteToWideChar(CP_ACP, 0, helper.DriverMatchInfo.pszProviderName, -1, pWuDriverInfo->wszProviderName, LINE_LEN) ||
|
||
|
0 == MultiByteToWideChar(CP_ACP, 0, helper.DriverMatchInfo.pszDriverVer, -1, pWuDriverInfo->wszDriverVer, LINE_LEN)
|
||
|
) {
|
||
|
LOG_error("MultiByteToWideChar failed");
|
||
|
return FALSE;
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
//This API gets the context handle array index from a connection handle.
|
||
|
//The connection context handle is checked if found invalid then -1 is
|
||
|
//returned. Otherwise the index that this handle references is returned.
|
||
|
|
||
|
int GetHandleIndex(
|
||
|
IN HANDLE hConnection //CDM Connect handle
|
||
|
) {
|
||
|
int index = HandleToLong(hConnection) - 1;
|
||
|
|
||
|
//If handle is invalid or not in use then return as nothing to do.
|
||
|
if (!g_handleArray.valid_index(index))
|
||
|
return -1;
|
||
|
|
||
|
return index;
|
||
|
}
|
||
|
|
||
|
// for findoem
|
||
|
HMODULE GetModule()
|
||
|
{
|
||
|
return g_hModule;
|
||
|
}
|