/* * persist.cpp - IPersist, IPersistFile implementations for * CFusionShortcut class. */ /* Headers **********/ #include "project.hpp" // for GetLastWin32Error /* Global Constants *******************/ const WCHAR g_cwzDefaultFileNamePrompt[] = L"*.manifest"; // ---------------------------------------------------------------------------- HRESULT STDMETHODCALLTYPE CFusionShortcut::GetCurFile(LPWSTR pwzFile, UINT ucbLen) { HRESULT hr=S_OK; if (m_pwzShortcutFile) { wcsncpy(pwzFile, m_pwzShortcutFile, ucbLen-1); pwzFile[ucbLen-1] = L'\0'; } else hr = S_FALSE; ASSERT(hr == S_OK || hr == S_FALSE); return(hr); } HRESULT STDMETHODCALLTYPE CFusionShortcut::Dirty(BOOL bDirty) { HRESULT hr=S_OK; if (bDirty) { SET_FLAG(m_dwFlags, FUSSHCUT_FL_DIRTY); //m_dwFlags = FUSSHCUT_FL_DIRTY; } else { CLEAR_FLAG(m_dwFlags, FUSSHCUT_FL_DIRTY); //m_dwFlags = FUSSHCUT_FL_NOTDIRTY; } return(hr); } HRESULT STDMETHODCALLTYPE CFusionShortcut::GetClassID(CLSID* pclsid) { HRESULT hr=S_OK; if (pclsid == NULL) hr = E_INVALIDARG; else *pclsid = CLSID_FusionShortcut; return(hr); } HRESULT STDMETHODCALLTYPE CFusionShortcut::IsDirty(void) { HRESULT hr; if (IS_FLAG_SET(m_dwFlags, FUSSHCUT_FL_DIRTY)) //if (m_dwFlags == FUSSHCUT_FL_DIRTY) // modified hr = S_OK; else // not modified hr = S_FALSE; return(hr); } HRESULT STDMETHODCALLTYPE CFusionShortcut::Save(LPCOLESTR pcwszFile, BOOL bRemember) { // BUGBUG: no save for now! return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CFusionShortcut::SaveCompleted(LPCOLESTR pcwszFile) { // BUGBUG: no save for now! return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CFusionShortcut::Load(LPCOLESTR pcwszFile, DWORD dwMode) { HRESULT hr = S_OK; LPWSTR pwzWorkingDir = NULL; LPWSTR pwzValue = NULL; DWORD dwCC = 0, dwCB = 0, dwFlag = 0; LPASSEMBLY_MANIFEST_IMPORT pManImport = NULL; LPASSEMBLY_CACHE_IMPORT pCacheImport = NULL; IManifestInfo *pAppInfo = NULL; IManifestInfo *pDependAsmInfo = NULL; // FEATURE: Validate dwMode here. // FEAUTRE: Implement dwMode flag support. if (!pcwszFile) { hr = E_INVALIDARG; goto exit; } // a hack check // BUGBUG?: this shouldn't be called more than once? // BUT: the rest of this code works even if called multiple times if (m_pwzWorkingDirectory) { hr = E_FAIL; goto exit; } // store the shortcut file name if (m_pwzShortcutFile) delete [] m_pwzShortcutFile; // (+ 1) for null terminator. m_pwzShortcutFile = new(WCHAR[wcslen(pcwszFile) + 1]); if (m_pwzShortcutFile) { wcscpy(m_pwzShortcutFile, pcwszFile); } else { hr = E_OUTOFMEMORY; goto exit; } if (FAILED(hr = CreateAssemblyManifestImport(&pManImport, m_pwzShortcutFile, NULL, 0))) goto exit; // check this 1st for pref... if (FAILED(hr=pManImport->GetManifestApplicationInfo(&pAppInfo))) goto exit; // can't continue without this... if (hr==S_FALSE) { hr = E_FAIL; goto exit; } if (m_pIdentity) m_pIdentity->Release(); if (FAILED(hr = pManImport->GetAssemblyIdentity(&m_pIdentity))) goto exit; // can't continue without a cache dir, 'cos otherwise unknown behavior // BUGBUG: should check/code to ensure some continue to work // even without the complete name, eg. shell icon path, part of infotip if (FAILED(hr = CreateAssemblyCacheImport(&pCacheImport, m_pIdentity, CACHEIMP_CREATE_RESOLVE_REF_EX))) goto exit; pCacheImport->GetManifestFileDir(&pwzWorkingDir, &dwCC); if (dwCC < 2) { // this should never happen hr = E_UNEXPECTED; goto exit; } // remove last L'\\' *(pwzWorkingDir+dwCC-2) = L'\0'; if (FAILED(hr=SetWorkingDirectory(pwzWorkingDir))) goto exit; // ignore failure pAppInfo->Get(MAN_INFO_APPLICATION_SHOWCOMMAND, (LPVOID *)&pwzValue, &dwCB, &dwFlag); if (pwzValue != NULL) { // default is normal int nShowCmd = SW_SHOWNORMAL; if (!_wcsicmp(pwzValue, L"maximized")) { nShowCmd = SW_SHOWMAXIMIZED; } else if (!_wcsicmp(pwzValue, L"minimized")) { nShowCmd = SW_SHOWMINIMIZED; } if (FAILED(hr=SetShowCmd(nShowCmd))) goto exit; delete [] pwzValue; } // ignore failure pAppInfo->Get(MAN_INFO_APPLICATION_ENTRYPOINT, (LPVOID *)&pwzValue, &dwCB, &dwFlag); if (pwzValue != NULL) { size_t ccWorkingDir = wcslen(pwzWorkingDir)+1; size_t ccEntryPoint = wcslen(pwzValue)+1; LPWSTR pwzTemp = new WCHAR[ccWorkingDir+ccEntryPoint]; // 2 strings + '\\' + '\0' // like .lnk or .url, entry point is under wzWorkingDir // 'path' is the target file of the shortcut, ie. the entry point of the app in this case if (pwzTemp == NULL) { hr = E_OUTOFMEMORY; goto exit; } memcpy(pwzTemp, pwzWorkingDir, ccWorkingDir * sizeof(WCHAR)); if (!PathAppend(pwzTemp, pwzValue)) hr = E_FAIL; else hr=SetPath(pwzTemp); delete [] pwzTemp; if (FAILED(hr)) goto exit; delete [] pwzValue; } //else // ... if no entry point leave it blank so that the default icon will be used // ignore failure pAppInfo->Get(MAN_INFO_APPLICATION_FRIENDLYNAME, (LPVOID *)&pwzValue, &dwCB, &dwFlag); if (pwzValue != NULL) { if (FAILED(hr=SetDescription(pwzValue))) goto exit; delete [] pwzValue; } // ignore failure pAppInfo->Get(MAN_INFO_APPLICATION_ICONFILE, (LPVOID *)&pwzValue, &dwCB, &dwFlag); if (pwzValue != NULL) { LPWSTR pwzValue2 = NULL; pAppInfo->Get(MAN_INFO_APPLICATION_ICONINDEX, (LPVOID *)&pwzValue2, &dwCB, &dwFlag); if (pwzValue2 != NULL) { LPWSTR pwzStopString = NULL; hr=SetIconLocation(pwzValue, (int) wcstol(pwzValue2, &pwzStopString, 10)); delete [] pwzValue2; if (FAILED(hr)) goto exit; } delete [] pwzValue; } // ignore failure pAppInfo->Get(MAN_INFO_APPLICATION_HOTKEY, (LPVOID *)&pwzValue, &dwCB, &dwFlag); if (pwzValue != NULL) { LPWSTR pwzStopString = NULL; if (FAILED(hr=SetHotkey((WORD) wcstol(pwzValue, &pwzStopString, 10)))) goto exit; delete [] pwzValue; } // note: this method of getting the codebase is only valid for desktop (and subscription) manifests // thus the hardcoded index '0' // ignore failure pManImport->GetNextAssembly(0, &pDependAsmInfo); if (pDependAsmInfo != NULL) { pDependAsmInfo->Get(MAN_INFO_DEPENDENT_ASM_CODEBASE, (LPVOID *)&pwzValue, &dwCB, &dwFlag); if (pwzValue != NULL) { if (FAILED(hr=SetCodebase(pwzValue))) goto exit; delete [] pwzValue; } } pwzValue = NULL; exit: if (pwzValue != NULL) delete [] pwzValue; if (pwzWorkingDir != NULL) delete [] pwzWorkingDir; if (pDependAsmInfo != NULL) pDependAsmInfo->Release(); if (pAppInfo != NULL) pAppInfo->Release(); if (pCacheImport != NULL) pCacheImport->Release(); if (pManImport != NULL) pManImport->Release(); return(hr); } HRESULT STDMETHODCALLTYPE CFusionShortcut::GetCurFile(LPOLESTR *ppwszFile) { HRESULT hr = S_OK; LPOLESTR pwszTempFile; if (ppwszFile == NULL) { hr = E_INVALIDARG; goto exit; } // BUGBUG?: ensure *ppwszFile NULL? if (m_pwzShortcutFile) { pwszTempFile = m_pwzShortcutFile; } else { pwszTempFile = (LPWSTR) g_cwzDefaultFileNamePrompt; hr = S_FALSE; } *ppwszFile = (LPOLESTR) CoTaskMemAlloc((wcslen(pwszTempFile) + 1) * sizeof(*pwszTempFile)); if (*ppwszFile) wcscpy(*ppwszFile, pwszTempFile); else hr = E_OUTOFMEMORY; exit: return(hr); }