/*++ Copyright (c) 2001 Microsoft Corporation Module Name : urlscan.cpp Abstract: Replace Dll, and retrieve URLScan Path Author: Christopher Achille (cachille) Project: URLScan Update Revision History: March 2002: Created --*/ #include "stdafx.h" #include "windows.h" #include "urlscan.h" #include "updateini.h" #include "service.h" #include "resource.h" #include #include "initguid.h" #include #include "iadmw.h" #include "iiscnfg.h" // GetUrlScanPath // // Get the path to URLScan // // Parameters: // pAdminBase - [in] Pointer to AdminBase Class // szPath - [out] Path to urlscan // dwCharsinBuff - [in] Size of buffer BOOL GetUrlScanPath( IMSAdminBase *pAdminBase, LPTSTR szPath, DWORD dwCharsinBuff ) { METADATA_RECORD mdrData; DWORD dwRequiredSize; BOOL bRet = TRUE; mdrData.dwMDIdentifier = MD_FILTER_IMAGE_PATH; mdrData.dwMDAttributes = METADATA_NO_ATTRIBUTES; mdrData.dwMDUserType = IIS_MD_UT_SERVER; mdrData.dwMDDataType = STRING_METADATA; mdrData.dwMDDataLen = ( dwCharsinBuff * sizeof( TCHAR ) ); mdrData.pbMDData = (UCHAR *) szPath; if ( FAILED( pAdminBase->GetData( METADATA_MASTER_ROOT_HANDLE, METABASE_URLSCANFILT_LOC, &mdrData, &dwRequiredSize ) ) ) { bRet = FALSE; } return bRet; } // IsURLScanInstalled // // Determine if URLScan is installed. // // Parameters: // szPath - The path to where URLScan is installed // // Return: // TRUE - Yes, it is installed, and szPath points to it // FALSE - It is not installed as a global filter // BOOL IsUrlScanInstalled( LPTSTR szPath, DWORD dwCharsinBuff ) { HRESULT hRes; IMSAdminBase *pAdminBase = NULL; IClassFactory *pcsfFactory = NULL; if ( FAILED( CoInitializeEx(NULL, COINIT_MULTITHREADED) ) ) { // Could not initialize COM return FALSE; } hRes = CoGetClassObject( GETAdminBaseCLSID(TRUE), CLSCTX_SERVER, NULL, IID_IClassFactory, (void**) &pcsfFactory); if ( SUCCEEDED(hRes) ) { hRes = pcsfFactory->CreateInstance(NULL, IID_IMSAdminBase, (void **) &pAdminBase); pcsfFactory->Release(); } if ( SUCCEEDED(hRes) ) { if ( !GetUrlScanPath( pAdminBase, szPath, dwCharsinBuff ) ) { hRes = E_FAIL; } } if ( pAdminBase ) { pAdminBase->Release(); } CoUninitialize(); return ( SUCCEEDED( hRes ) ); } // InstallURLSCanFix // // Install the fix for URLScan // DWORD InstallURLScanFix( LPTSTR szUrlScanPath ) { BOOL bServiceWasRunning; DWORD dwRet = ERROR_SUCCESS; // Stop web Service if ( !StopWebSerivce( &bServiceWasRunning ) ) { // Error Message about service not stopping return IDS_ERROR_WEBSERVICE; } // Update the Inf if ( !UpdateIni( szUrlScanPath ) ) { dwRet = IDS_ERROR_INIUPDATE; } // Update Executable if ( ( dwRet == ERROR_SUCCESS ) && ( !MoveOldUrlScan( szUrlScanPath ) || !ExtractUrlScanFile( szUrlScanPath ) ) ) { dwRet = IDS_ERROR_DLLUPDATE; } // Restart web service if it was running before, // even if there was a failure along the way if ( bServiceWasRunning && !StartWebSerivce() ) { // Error Message about not being able to start service if ( dwRet == ERROR_SUCCESS ) { dwRet = IDS_ERROR_RESTARTWEB; } } return dwRet; } // ExtractUrlScanFile // // Extract the URLScan File to the FileSystem // // Parameters: // szPath - Path to expand to // // Return: // TRUE - Success // FALSE - Failure BOOL ExtractUrlScanFile( LPTSTR szPath ) { HRSRC hrDllResource; HGLOBAL hDllResource; LPVOID pDllData; HANDLE hFile; DWORD dwBytesWritten; DWORD dwSize; BOOL bRet = FALSE; DWORD dwTryCount = 0; if ( ( ( hrDllResource = FindResource( NULL, (LPCWSTR) IDR_DATA1, RT_RCDATA) ) == NULL ) || ( ( dwSize = SizeofResource( NULL, hrDllResource ) ) == 0 ) || ( ( hDllResource = LoadResource( NULL, hrDllResource) ) == NULL ) || ( ( pDllData = LockResource( hDllResource ) ) == NULL ) ) { // Could not load resource return FALSE; } do { hFile = CreateFile( szPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if ( GetLastError() == ERROR_SHARING_VIOLATION ) { // If we are getting a sharing violation, it is possible that inetinfo.exe // has released the handle, but the OS hasn't totally released it yet, // so lets wait 5 seconds Sleep( URLSCAN_DLL_INSTALL_INTERVAL ); } dwTryCount++; } while ( ( hFile == INVALID_HANDLE_VALUE) && ( GetLastError() == ERROR_SHARING_VIOLATION ) && ( dwTryCount < URLSCAN_DLL_INSTALL_MAXTRIES ) ); if ( hFile != INVALID_HANDLE_VALUE ) { if ( WriteFile( hFile, pDllData, dwSize, &dwBytesWritten, NULL) ) { bRet = TRUE; } CloseHandle(hFile); if ( dwBytesWritten != dwSize ) { bRet = FALSE; } } return bRet; } // MoveOldUrlScan // // This will backup the old urlscan into a backup file location // // Parameters: // szCurrentPath - The current path to urlscan // BOOL MoveOldUrlScan( LPTSTR szCurrentPath ) { TCHAR szBackupLocation[ MAX_PATH ]; LPTSTR szCurrentPos; DWORD dwPathLength = (DWORD) _tcslen( szCurrentPath ); if ( ( dwPathLength >= ( MAX_PATH - _tcslen(URLSCAN_DEFAULT_FILENAME) - _tcslen(URLSCAN_BACKUPKEY) - 1 ) ) || ( dwPathLength == 0 ) ) { return FALSE; } // Copy Filelocation over _tcscpy( szBackupLocation, szCurrentPath ); // Find Last '\' szCurrentPos = _tcsrchr( szBackupLocation, '\\' ); // If there is not slash, then reset to begining of string if ( szCurrentPos == NULL ) { szCurrentPos = szBackupLocation; } if ( *szCurrentPos == '\\' ) { // Move forward one character to the first letter szCurrentPos++; } // Append New FileName _tcscpy( szCurrentPos, URLSCAN_BACKUPKEY); _tcscat( szCurrentPos, URLSCAN_DEFAULT_FILENAME); // Ignore Failure, since failure is most likely because we have done this // before, and the backup file already exists MoveFileEx( szCurrentPath, szBackupLocation, MOVEFILE_COPY_ALLOWED ); return TRUE; } // IsAdministrator // // Return whether the user is an administrator or not // BOOL IsAdministrator() { SC_HANDLE hSCManager; BOOL bRet; hSCManager = OpenSCManager( NULL, NULL, SC_MANAGER_CREATE_SERVICE ); bRet = hSCManager != NULL; if ( hSCManager ) { CloseServiceHandle( hSCManager ); } return bRet; } // UpdateRegistryforAddRemove // // Update the registry to reflect the new name for the uninstall // program // BOOL UpdateRegistryforAddRemove() { HKEY hRegKey; BOOL bRet; LPWSTR szValue = URLSCAN_TOOL_KEY_NEWVALUE; if ( RegOpenKey( HKEY_LOCAL_MACHINE, URLSCAN_TOOL_REGPATH, &hRegKey ) != ERROR_SUCCESS ) { // Failure to open registry key // We will return success though, since they could of never installed // the installer, but only the file by itself manually. return TRUE; } bRet = RegSetValueEx( hRegKey, URLSCAN_TOOL_KEY_NAME, // Value Name NULL, // Reserved REG_SZ, // String Value (LPBYTE) szValue, // Value to set ( ( (DWORD) wcslen(szValue) + 1) * sizeof(WCHAR) ) ) == ERROR_SUCCESS; RegCloseKey( hRegKey ); return bRet; }