/*++ Copyright (c) 2000 Microsoft Corporation Module Name: Casper.cpp Abstract: Casper copies a LNK file into %windir%\desktop. This file is hardcoded to point to c:\program files. The EXE that actually places the file into the wrong place is 16-bit, so we cannot use CorrectFilePaths to fix the problem. We hook IPersistFile::Save to accomplish the fixup of the incorrect link, IPersistFile::Save is not modified in any way. App uses some 16-bit stuff when showing the intro video (see #200495) which we have yet to fix (probably will never fix). After it calls CreateWindowEx to create the "Full-screen animation" window it assigns the return value to a variable. Later on the app plays videos in SmackWin windows. And it checks this var to see if it's 0 - if it is, it calls DestroyWindow on the SmackWin window. Now if the intro video were shown successfully it would have set this var to 0 when the video exits but since in this case the video is not shown, the variable still has the value equal to the "Full-screen animation" window handle. We fix this by setting the return value of the "Full-screen animation" window creation to 0. History: 1/21/1999 robkenny 03/15/2000 robkenny converted to use the CorrectPathChangesAllUser class 11/07/2000 maonis added hooks for CreateWindowExA and SetFocus (this is for the actual casper.exe) 01/04/2001 maonis tester found more problem with the smackwin windows. rewrote the fix to fix all of them. --*/ #include "precomp.h" #include "ClassCFP.h" IMPLEMENT_SHIM_BEGIN(Casper) #include "ShimHookMacro.h" APIHOOK_ENUM_BEGIN APIHOOK_ENUM_ENTRY(CreateDialogParamA) APIHOOK_ENUM_ENTRY(CreateWindowExA) APIHOOK_ENUM_END /*++ We return 0 when creating the "Full-screen animation" window. --*/ HWND APIHOOK(CreateWindowExA)( DWORD dwExStyle, // extended window style LPCSTR lpClassName, // registered class name LPCSTR lpWindowName, // window name DWORD dwStyle, // window style int x, // horizontal position of window int y, // vertical position of window int nWidth, // window width int nHeight, // window height HWND hWndParent, // handle to parent or owner window HMENU hMenu, // menu handle or child identifier HINSTANCE hInstance, // handle to application instance LPVOID lpParam // window-creation data ) { HWND hWnd = ORIGINAL_API(CreateWindowExA)( dwExStyle, lpClassName, lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam); if (lpWindowName) { CSTRING_TRY { CString csWindowName(lpWindowName); if (csWindowName.Compare(L"Full-screen animation") == 0) { hWnd = 0; } } CSTRING_CATCH { // Do nothing } } return hWnd; } /*++ Our path changing class. We want to convert paths to All User --*/ CorrectPathChangesAllUser * g_PathCorrector = NULL; static bool g_bLinkCorrected = false; /*++ Return a pointer to the PathCorrecting object --*/ inline CorrectPathChangesBase * GetPathcorrecter() { if (g_PathCorrector == NULL) { // Create our correct file path object g_PathCorrector = new CorrectPathChangesAllUser; g_PathCorrector->AddPathChangeW(L"\\MsM\\", L"\\MorningStar\\" ); } return g_PathCorrector; } /*++ Call CorrectPathAllocA and print a debug message if the two strings differ --*/ WCHAR * CorrectPathAllocDebugW(const WCHAR * uncorrect, const char * debugMsg) { if (uncorrect == NULL) return NULL; WCHAR * strCorrectFile = GetPathcorrecter()->CorrectPathAllocW(uncorrect); if (strCorrectFile && uncorrect && _wcsicmp(strCorrectFile, uncorrect) != 0) { DPFN( eDbgLevelInfo, "%s corrected path:\n %S\n %S\n", debugMsg, uncorrect, strCorrectFile); } else // Massive Spew: { DPFN( eDbgLevelSpew, "%s unchanged %S\n", debugMsg, uncorrect); } return strCorrectFile; } /*++ Casper *copies* a link to %windir%\Desktop; it contains hardcoded paths to incorrect places. Move the link to the proper desktop directory. Correct the Path, Working Directory, and Icon values--all which are wrong. --*/ void CorrectCasperLink() { if (!g_bLinkCorrected) { // The path to the incorrect desktop link WCHAR * lpIncorrectCasperPath = GetPathcorrecter()->ExpandEnvironmentValueW(L"%windir%\\Desktop\\casper.lnk"); // Correct the bad desktop link path WCHAR * lpCorrectCasperPath = GetPathcorrecter()->CorrectPathAllocW(lpIncorrectCasperPath); DPFN( eDbgLevelInfo, "CorrectCasperLink MoveFileW(%S, %S)\n", lpIncorrectCasperPath, lpCorrectCasperPath); // Move the file to the correct location. MoveFileW(lpIncorrectCasperPath, lpCorrectCasperPath); // All finished with the bad path, I never want to see it again. free(lpIncorrectCasperPath); HRESULT hres = CoInitialize(NULL); if (SUCCEEDED(hres)) { // Get a pointer to the IShellLink interface. IShellLinkW *psl; hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkW, (void **)&psl); if (SUCCEEDED(hres)) { // Get a pointer to the IPersistFile interface. IPersistFile *ppf; hres = psl->QueryInterface(IID_IPersistFile, (void **)&ppf); if (SUCCEEDED(hres)) { // Load the shortcut. hres = ppf->Load(lpCorrectCasperPath, STGM_READ); if (SUCCEEDED(hres)) { // We have successfully loaded the link g_bLinkCorrected = true; DPFN( eDbgLevelInfo, "CorrectCasperLink %S\n", lpCorrectCasperPath); // Correct the path to the shortcut target. WCHAR szBadPath[MAX_PATH]; WCHAR * szCorrectPath; WIN32_FIND_DATAW wfd; hres = psl->GetPath(szBadPath, MAX_PATH, &wfd, SLGP_UNCPRIORITY); if (SUCCEEDED(hres)) { szCorrectPath = CorrectPathAllocDebugW(szBadPath, "CorrectCasperLink, SetPath"); psl->SetPath(szCorrectPath); free(szCorrectPath); } // Correct the working directory hres = psl->GetWorkingDirectory(szBadPath, MAX_PATH); if (SUCCEEDED(hres)) { szCorrectPath = CorrectPathAllocDebugW(szBadPath, "CorrectCasperLink, SetWorkingDirectory"); psl->SetWorkingDirectory(szCorrectPath); free(szCorrectPath); } // Correct the icon int iIcon; hres = psl->GetIconLocation(szBadPath, MAX_PATH, &iIcon); if (SUCCEEDED(hres)) { szCorrectPath = CorrectPathAllocDebugW(szBadPath, "CorrectCasperLink, SetIconLocation"); psl->SetIconLocation(szCorrectPath, iIcon); free(szCorrectPath); } // Save the shortcut. ppf->Save(NULL, TRUE); } } // Release the pointer to IShellLink. ppf->Release(); } // Release the pointer to IPersistFile. psl->Release(); } CoUninitialize(); free(lpCorrectCasperPath); } } /*++ Do nothing to the CreateDialogParamA call, just an opportunity to correct the casper link --*/ HWND APIHOOK(CreateDialogParamA)( HINSTANCE hInstance, // handle to module LPCSTR lpTemplateName, // dialog box template HWND hWndParent, // handle to owner window DLGPROC lpDialogFunc, // dialog box procedure LPARAM dwInitParam // initialization value ) { CorrectCasperLink(); HWND returnValue = ORIGINAL_API(CreateDialogParamA)( hInstance, lpTemplateName, hWndParent, lpDialogFunc, dwInitParam); return returnValue; } /*++ Create the appropriate g_PathCorrector Return TRUE if we were successful in creating and initializing. --*/ BOOL InitPathcorrectorClass() { g_PathCorrector = new CorrectPathChangesAllUser; if (g_PathCorrector) { return g_PathCorrector->ClassInit(); } return FALSE; } /*++ Add all the path corrections to the path corrector. Call after SHIM_STATIC_DLLS_INITIALIZED --*/ void InitializePathCorrections() { g_PathCorrector->AddPathChangeW(L"\\MsM\\", L"\\MorningStar\\" ); } BOOL NOTIFY_FUNCTION( DWORD fdwReason ) { BOOL bSuccess = TRUE; if (fdwReason == DLL_PROCESS_ATTACH) { return InitPathcorrectorClass(); } else if (fdwReason == SHIM_STATIC_DLLS_INITIALIZED) { InitializePathCorrections(); } return bSuccess; } /*++ Register hooked functions --*/ HOOK_BEGIN APIHOOK_ENTRY(USER32.DLL, CreateDialogParamA) APIHOOK_ENTRY(USER32.DLL, CreateWindowExA) HOOK_END IMPLEMENT_SHIM_END