//======================================================================= // // 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 #include #include #include #include #include #include #include #include #include #include #include #include #define _ASSERTE(expr) ((void)0) #include #include "cdm.h" #include "cdmp.h" #include #include #include 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 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 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 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("\r\n\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\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\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\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\r\n"), (LPCTSTR) pszNextID)) { fXmlFileError = true; goto CloseXML; } } } } if (0 > _ftprintf(fOut, _T("\t\r\n"))) { fXmlFileError = true; goto CloseXML; } } } //for if(0 > _ftprintf(fOut, _T("\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; }