#include "shellprv.h" #include "filetype.h" #include "ftascstr.h" //for now, until CoCreateInstance #include "ftassoc.h" #include "fassoc.h" HIMAGELIST CFTAssocInfo::_himlSysSmall = NULL; HIMAGELIST CFTAssocInfo::_himlSysLarge = NULL; CFTAssocInfo::CFTAssocInfo() : _cRef(1) { } HRESULT CFTAssocInfo::Init(AIINIT aiinitFlags, LPTSTR pszStr) { HRESULT hres = E_INVALIDARG; _aiinitFlags1 = aiinitFlags; *_szInitStr2 = 0; _aiinitFlags2 = AIINIT_NONE; if (!pszStr && (AIINIT_PROGID == aiinitFlags)) { // This happens when we create a new ProgID hres = S_OK; } else { if (pszStr && *pszStr && (AIINIT_NONE != aiinitFlags)) { if ((AIINIT_EXT == aiinitFlags) && (TEXT('.') != *pszStr)) { *_szInitStr1 = TEXT('.'); StrCpyN(_szInitStr1 + 1, pszStr, ARRAYSIZE(_szInitStr1) - 1); } else StrCpyN(_szInitStr1, pszStr, ARRAYSIZE(_szInitStr1)); hres = S_OK; } } // set the info for the registry support RSInitRoot(HKEY_CLASSES_ROOT, _szInitStr1, NULL, REG_OPTION_NON_VOLATILE, REG_OPTION_NON_VOLATILE); return hres; } HRESULT CFTAssocInfo::InitComplex(AIINIT aiinitFlags1, LPTSTR pszStr1, AIINIT aiinitFlags2, LPTSTR pszStr2) { HRESULT hres = E_INVALIDARG; if ((pszStr1 && *pszStr1 && (AIINIT_NONE != aiinitFlags1)) && (pszStr2 && *pszStr2&& (AIINIT_NONE != aiinitFlags2))) { TCHAR szSubKey[MAX_PROGID + 7 + MAX_ACTION]; StrCpyN(_szInitStr1, pszStr1, ARRAYSIZE(_szInitStr1)); _aiinitFlags1 = aiinitFlags1; StrCpyN(_szInitStr2, pszStr2, ARRAYSIZE(_szInitStr2)); _aiinitFlags2 = aiinitFlags2; // set the info for the registry support StrCpyN(szSubKey, _szInitStr1, MAX_PROGID); lstrcat(szSubKey, TEXT("\\shell")); RSInitRoot(HKEY_CLASSES_ROOT, szSubKey, _szInitStr2, REG_OPTION_NON_VOLATILE, REG_OPTION_NON_VOLATILE); hres = S_OK; } return hres; } HRESULT CFTAssocInfo::GetString(AISTR aistrFlags, LPTSTR pszStr, DWORD* pcchStr) { HRESULT hres = E_FAIL; switch(_aiinitFlags1) { case AIINIT_EXT: { switch(aistrFlags) { case AISTR_APPFRIENDLY: hres = _GetOpenWithInfo(pszStr, pcchStr); break; case AISTR_EXT: StrCpyN(pszStr, _szInitStr1 + 1, *pcchStr); hres = S_OK; break; case AISTR_DOTEXT: StrCpyN(pszStr, _szInitStr1, *pcchStr); hres = S_OK; break; case AISTR_PROGID: hres = (RSGetTextValue(NULL, NULL, pszStr, pcchStr) ? S_OK : E_FAIL); break; // We fall back to using the progid for the AISTR_XXX's below case AISTR_ICONLOCATION: case AISTR_PROGIDDESCR: { TCHAR szProgID[MAX_PROGID]; DWORD cchProgID = ARRAYSIZE(szProgID); IAssocInfo* pAI = NULL; CFTAssocStore* pAssocStore = new CFTAssocStore(); if ( !pAssocStore ) { hres = E_OUTOFMEMORY; break; } hres = pAssocStore->GetAssocInfo(_szInitStr1, AIINIT_EXT, &pAI); if (SUCCEEDED(hres)) { hres = pAI->GetString(AISTR_PROGID, szProgID, &cchProgID); pAI->Release(); if (SUCCEEDED(hres)) { hres = pAssocStore->GetAssocInfo(szProgID, AIINIT_PROGID, &pAI); if (SUCCEEDED(hres)) { hres = pAI->GetString(aistrFlags, pszStr, pcchStr); pAI->Release(); } } } delete pAssocStore; break; } default: hres = E_INVALIDARG; break; } break; } case AIINIT_PROGID: { if (AIINIT_NONE == _aiinitFlags2) { switch(aistrFlags) { case AISTR_PROGIDDEFAULTACTION: hres = _GetProgIDDefaultAction(pszStr, pcchStr); break; case AISTR_ICONLOCATION: hres = _GetIconLocation(pszStr, pcchStr); break; case AISTR_PROGID: StrCpyN(pszStr, _szInitStr1, *pcchStr); hres = S_OK; break; case AISTR_PROGIDDESCR: hres = _GetProgIDDescr(pszStr, pcchStr); break; default: hres = E_INVALIDARG; break; } } else { if (AIINIT_ACTION == _aiinitFlags2) { switch (aistrFlags) { case AISTR_ACTION: { StrCpyN(pszStr, _szInitStr2, *pcchStr); hres = S_OK; break; } case AISTR_ACTIONFRIENDLY: { if (RSGetTextValue(NULL, NULL, pszStr, pcchStr)) { if (*pszStr) { hres = S_OK; } else { hres = S_FALSE; } } else { hres = S_FALSE; } break; } } } else hres = E_INVALIDARG; } break; } default: hres = E_INVALIDARG; break; } return hres; } HRESULT CFTAssocInfo::GetDWORD(AIDWORD aidwordFlags, DWORD* pdwData) { HRESULT hres = E_FAIL; switch(_aiinitFlags1) { case AIINIT_EXT: { switch(aidwordFlags) { case AIDWORD_DOCSMALLICON: case AIDWORD_DOCLARGEICON: { hres = _GetExtDocIcon(_szInitStr1, (AIDWORD_DOCSMALLICON == aidwordFlags), (int*)pdwData); if (FAILED(hres)) { TCHAR szProgID[MAX_PROGID]; DWORD cchProgID = ARRAYSIZE(szProgID); IAssocInfo* pAI = NULL; CFTAssocStore* pAssocStore = new CFTAssocStore(); if (pAssocStore) { hres = pAssocStore->GetAssocInfo(_szInitStr1, AIINIT_EXT, &pAI); if (SUCCEEDED(hres)) { hres = pAI->GetString(AISTR_PROGID, szProgID, &cchProgID); pAI->Release(); if (SUCCEEDED(hres)) { hres = pAssocStore->GetAssocInfo(szProgID, AIINIT_PROGID, &pAI); if (SUCCEEDED(hres)) { hres = pAI->GetDWORD(aidwordFlags, pdwData); pAI->Release(); } } } delete pAssocStore; } } break; } case AIDWORD_DOCSMALLICON | AIALL_PERUSER: case AIDWORD_APPSMALLICON: hres = _GetAppIcon(TRUE, (int*)pdwData); break; default: hres = E_INVALIDARG; break; } break; } case AIINIT_PROGID: { if (AIINIT_NONE == _aiinitFlags2) { switch(aidwordFlags) { case AIDWORD_PROGIDEDITFLAGS: hres = _GetProgIDEditFlags(pdwData); break; case AIDWORD_DOCSMALLICON: case AIDWORD_DOCLARGEICON: hres = _GetProgIDDocIcon((AIDWORD_DOCSMALLICON == aidwordFlags), (int*)pdwData); break; default: hres = E_INVALIDARG; break; } } else { hres = E_INVALIDARG; if (AIINIT_ACTION == _aiinitFlags2) if (AIDWORD_ACTIONATTRIBUTES == aidwordFlags) hres = _GetProgIDActionAttributes(pdwData); } break; } default: hres = E_INVALIDARG; break; } return hres; } HRESULT CFTAssocInfo::GetData(AIDWORD aidataFlags, PBYTE pbData, DWORD* pcbData) { HRESULT hres = E_INVALIDARG; if ((AIINIT_PROGID == _aiinitFlags1) && (AIINIT_ACTION == _aiinitFlags2) && (AIDATA_PROGIDACTION == aidataFlags)) { LPTSTR pszProgID = _szInitStr1; PROGIDACTION* pPIDA = (PROGIDACTION*)pbData; LPTSTR pszActionReg = _szInitStr2; DWORD cchStr = 0; pPIDA->fUseDDE = FALSE; StrCpyN(pPIDA->szActionReg, pszActionReg, ARRAYSIZE(pPIDA->szActionReg)); StrCpyN(pPIDA->szOldActionReg, pszActionReg, ARRAYSIZE(pPIDA->szOldActionReg)); cchStr = ARRAYSIZE(pPIDA->szAction); if (!RSGetTextValue(NULL, NULL, pPIDA->szAction, &cchStr)) { // By default the friendly name will be the same as the reg key name StrCpyN(pPIDA->szAction, pszActionReg, ARRAYSIZE(pPIDA->szAction)); } StrCpyN(pPIDA->szOldAction, pPIDA->szAction, ARRAYSIZE(pPIDA->szOldAction)); cchStr = ARRAYSIZE(pPIDA->szCmdLine); hres = AssocQueryString(0, ASSOCSTR_COMMAND, pszProgID, pszActionReg, pPIDA->szCmdLine, &cchStr); if (SUCCEEDED(hres)) { HRESULT hresTmp = E_FAIL; cchStr = ARRAYSIZE(pPIDA->szDDEMsg); hresTmp = AssocQueryString(0, ASSOCSTR_DDECOMMAND, pszProgID, pszActionReg, pPIDA->szDDEMsg, &cchStr); if (SUCCEEDED(hresTmp)) pPIDA->fUseDDE = TRUE; cchStr = ARRAYSIZE(pPIDA->szDDEApplication); hresTmp = AssocQueryString(0, ASSOCSTR_DDEAPPLICATION, pszProgID, pszActionReg, pPIDA->szDDEApplication, &cchStr); if (SUCCEEDED(hresTmp)) pPIDA->fUseDDE = TRUE; cchStr = ARRAYSIZE(pPIDA->szDDEAppNotRunning); hresTmp = AssocQueryString(0, ASSOCSTR_DDEIFEXEC, pszProgID, pszActionReg, pPIDA->szDDEAppNotRunning, &cchStr); if (SUCCEEDED(hresTmp)) pPIDA->fUseDDE = TRUE; cchStr = ARRAYSIZE(pPIDA->szDDETopic); hresTmp = AssocQueryString(0, ASSOCSTR_DDETOPIC, pszProgID, pszActionReg, pPIDA->szDDETopic, &cchStr); if (SUCCEEDED(hresTmp)) pPIDA->fUseDDE = TRUE; } } return hres; } HRESULT CFTAssocInfo::SetData(AIDWORD aidataFlags, PBYTE pbData, DWORD cbData) { HRESULT hres = E_INVALIDARG; if ((AIINIT_PROGID == _aiinitFlags1) && (AIINIT_ACTION == _aiinitFlags2) && (AIDATA_PROGIDACTION == aidataFlags)) { HKEY hProgIDKey = NULL; LONG lRes = RegOpenKeyEx(HKEY_CLASSES_ROOT, _szInitStr1, 0, KEY_WRITE, &hProgIDKey); hres = E_FAIL; // // |_ shell // |_ // | (Default): Fr&iendly name (value) (optional) (no UI to set it) // | "EditFlags": 0x000.... (value) (optional) (no UI to set it) // |_ Command // | (Default): e.g. c:\winnt\system32\notepad.exe "%1" // |_ ddeexec // | (Default): DDE msg // |_ Application // | (Default): Application // |_ IfExec // | (Default): ifexec // |_ Topic // (Default): topic if (ERROR_SUCCESS == lRes) { HKEY hShellKey = NULL; HKEY hActionKey = NULL; HKEY hCommandKey = NULL; HKEY hDDEKey = NULL; DWORD dwKey = 0; PROGIDACTION* pPIDA = (PROGIDACTION*)pbData; lRes = RegCreateKeyEx(hProgIDKey, TEXT("shell"), 0, NULL, REG_OPTION_NON_VOLATILE, MAXIMUM_ALLOWED, NULL, &hShellKey, &dwKey); RegCloseKey(hProgIDKey); if (ERROR_SUCCESS == lRes) { lRes = RegCreateKeyEx(hShellKey, _szInitStr2, 0, NULL, REG_OPTION_NON_VOLATILE, MAXIMUM_ALLOWED, NULL, &hActionKey, &dwKey); RegCloseKey(hShellKey); } if (ERROR_SUCCESS == lRes) { // Set the friendly name, if different if (lstrcmp(pPIDA->szAction, pPIDA->szActionReg)) { lRes = RegSetValueEx(hActionKey, NULL, NULL, REG_SZ, (PBYTE)pPIDA->szAction, lstrlen(pPIDA->szAction) * sizeof(TCHAR)); } if (ERROR_SUCCESS == lRes) { lRes = RegCreateKeyEx(hActionKey, TEXT("command"), 0, NULL, REG_OPTION_NON_VOLATILE, MAXIMUM_ALLOWED, NULL, &hCommandKey, &dwKey); } } if (ERROR_SUCCESS == lRes) { int iLen = lstrlen(pPIDA->szCmdLine); lRes = RegSetValueEx(hCommandKey, NULL, 0, REG_SZ, (PBYTE)(pPIDA->szCmdLine), iLen * sizeof(TCHAR)); } if (ERROR_SUCCESS == lRes) { if (pPIDA->fUseDDE) { lRes = RegCreateKeyEx(hActionKey, TEXT("ddeexec"), 0, NULL, REG_OPTION_NON_VOLATILE, MAXIMUM_ALLOWED, NULL, &hDDEKey, &dwKey); if (ERROR_SUCCESS == lRes) { HKEY hTmpKey = NULL; int iLen = 0; hres = S_OK; if (*(pPIDA->szDDEMsg)) { iLen = lstrlen(pPIDA->szDDEMsg); lRes = RegSetValueEx(hDDEKey, NULL, 0, REG_SZ, (PBYTE)(pPIDA->szDDEMsg), iLen * sizeof(TCHAR)); if (ERROR_SUCCESS != lRes) hres = E_FAIL; } if (*(pPIDA->szDDEApplication)) { lRes = RegCreateKeyEx(hDDEKey, TEXT("Application"), 0, NULL, REG_OPTION_NON_VOLATILE, MAXIMUM_ALLOWED, NULL, &hTmpKey, &dwKey); if (ERROR_SUCCESS == lRes) { iLen = lstrlen(pPIDA->szDDEApplication); lRes = RegSetValueEx(hTmpKey, NULL, 0, REG_SZ, (PBYTE)(pPIDA->szDDEApplication), iLen * sizeof(TCHAR)); if (ERROR_SUCCESS != lRes) hres = E_FAIL; RegCloseKey(hTmpKey); } } if (*(pPIDA->szDDEAppNotRunning)) { lRes = RegCreateKeyEx(hDDEKey, TEXT("IfExec"), 0, NULL, REG_OPTION_NON_VOLATILE, MAXIMUM_ALLOWED, NULL, &hTmpKey, &dwKey); if (ERROR_SUCCESS == lRes) { iLen = lstrlen(pPIDA->szDDEAppNotRunning); lRes = RegSetValueEx(hTmpKey, NULL, 0, REG_SZ, (PBYTE)(pPIDA->szDDEAppNotRunning), iLen * sizeof(TCHAR)); if (ERROR_SUCCESS != lRes) hres = E_FAIL; RegCloseKey(hTmpKey); } } if (*(pPIDA->szDDETopic)) { lRes = RegCreateKeyEx(hDDEKey, TEXT("Topic"), 0, NULL, REG_OPTION_NON_VOLATILE, MAXIMUM_ALLOWED, NULL, &hTmpKey, &dwKey); if (ERROR_SUCCESS == lRes) { iLen = lstrlen(pPIDA->szDDETopic); lRes = RegSetValueEx(hTmpKey, NULL, 0, REG_SZ, (PBYTE)(pPIDA->szDDETopic), iLen * sizeof(TCHAR)); if (ERROR_SUCCESS != lRes) hres = E_FAIL; RegCloseKey(hTmpKey); } } } } } if (hActionKey) RegCloseKey(hActionKey); if (hCommandKey) RegCloseKey(hCommandKey); if (hDDEKey) RegCloseKey(hDDEKey); } } return hres; } HRESULT CFTAssocInfo::SetDWORD(AIDWORD aidwordFlags, DWORD dwData) { return E_NOTIMPL; } HRESULT CFTAssocInfo::SetString(AISTR aistrFlags, LPTSTR pszStr) { HRESULT hres = E_FAIL; switch(_aiinitFlags1) { case AIINIT_PROGID: { if (AIINIT_NONE == _aiinitFlags2) { switch(aistrFlags) { case AISTR_PROGIDDEFAULTACTION: hres = _SetProgIDDefaultAction(pszStr); break; case AISTR_PROGIDDESCR: hres = (RSSetTextValue(NULL, NULL, pszStr) ? S_OK : E_FAIL); break; case AISTR_ICONLOCATION: hres = _SetIconLocation(pszStr); break; default: hres = E_INVALIDARG; break; } } else { hres = E_INVALIDARG; } break; } case AIINIT_EXT: { switch(aistrFlags) { case AISTR_PROGID: hres = (RSSetTextValue(NULL, NULL,pszStr) ? S_OK : E_FAIL); break; default: hres = E_INVALIDARG; break; } break; } default: hres = E_INVALIDARG; break; } return hres; } HRESULT CFTAssocInfo::GetBOOL(AIBOOL aiboolFlags, BOOL* pfBool) { HRESULT hres = E_FAIL; switch(_aiinitFlags1) { case AIINIT_EXT: { switch(aiboolFlags) { case AIBOOL_EXTEXIST: { HKEY hKey = NULL; if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT, _szInitStr1, 0, KEY_READ, &hKey)) { *pfBool = TRUE; RegCloseKey(hKey); } else *pfBool = FALSE; hres = S_OK; break; } case AIBOOL_EXTASSOCIATED: hres = _ExtIsAssociated(pfBool); break; case AIBOOL_PERUSERINFOAVAILABLE: { IQueryAssociations *pQA; WCHAR szwExt[MAX_EXT]; SHTCharToUnicode(_szInitStr1, szwExt, ARRAYSIZE(szwExt)); // This need to return FALSE on failure *pfBool = FALSE; if (SUCCEEDED(AssocCreate(CLSID_QueryAssociations, IID_IQueryAssociations, (void**)&pQA))) { pQA->Init(0, szwExt, NULL, NULL); if (pQA->GetData(0, ASSOCDATA_HASPERUSERASSOC, NULL, NULL, NULL) == S_OK) *pfBool = TRUE; pQA->Release(); hres = S_OK; } break; } case AIBOOL_EXCLUDE: { CFTAssocStore* pAssocStore = new CFTAssocStore(); if (pAssocStore) { IAssocInfo* pAI = NULL; hres = pAssocStore->GetAssocInfo(_szInitStr1, AIINIT_EXT, &pAI); if (SUCCEEDED(hres)) { TCHAR szProgID[MAX_PROGID]; DWORD cchProgID = ARRAYSIZE(szProgID); hres = pAI->GetString(AISTR_PROGID, szProgID, &cchProgID); pAI->Release(); if (SUCCEEDED(hres)) { hres = pAssocStore->GetAssocInfo(szProgID, AIINIT_PROGID, &pAI); if (SUCCEEDED(hres)) { hres = pAI->GetBOOL(aiboolFlags, pfBool); pAI->Release(); } } } delete pAssocStore; } break; } default: hres = E_INVALIDARG; break; } break; } case AIINIT_PROGID: { switch(aiboolFlags) { case AIBOOL_CONFIRMOPEN: case AIBOOL_EDITDESCR: case AIBOOL_EDITDOCICON: case AIBOOL_EDIT: case AIBOOL_EDITREMOVE: case AIBOOL_EXCLUDE: case AIBOOL_SHOW: case AIBOOL_PROGIDHASNOEXT: { hres = _IsEditFlagSet(aiboolFlags, pfBool); break; } case AIBOOL_BROWSEINPLACE: { hres = _IsBrowseInPlace(pfBool); break; } case AIBOOL_BROWSEINPLACEENABLED: { hres = _IsBrowseInPlaceEnabled(pfBool); break; } case AIBOOL_ALWAYSSHOWEXT: { *pfBool = RSValueExist(NULL, TEXT("AlwaysShowExt")); hres = S_OK; break; } default: hres = E_INVALIDARG; break; } break; } default: hres = E_INVALIDARG; break; } return hres; } HRESULT CFTAssocInfo::SetBOOL(AIBOOL aiboolFlags, BOOL fBool) { HRESULT hres = E_FAIL; switch(_aiinitFlags1) { case AIINIT_PROGID: { switch(aiboolFlags) { case AIBOOL_CONFIRMOPEN: { hres = _SetEditFlagSet(aiboolFlags, fBool); break; } case AIBOOL_BROWSEINPLACE: { hres = _SetBrowseInPlace(fBool); break; } case AIBOOL_ALWAYSSHOWEXT: { if (fBool) { RSDeleteValue(NULL, TEXT("NeverShowExt")); hres = (RSSetTextValue(NULL, TEXT("AlwaysShowExt"), TEXT("")) ? S_OK : E_FAIL); } else hres = (RSDeleteValue(NULL, TEXT("AlwaysShowExt")) ? S_OK : E_FAIL); break; } default: hres = E_INVALIDARG; break; } break; } default: hres = E_INVALIDARG; break; } return hres; } HRESULT CFTAssocInfo::Create() { HRESULT hres = E_FAIL; switch(_aiinitFlags1) { case AIINIT_EXT: { HKEY hKey = NULL; DWORD dwKey = 0; if (ERROR_SUCCESS == RegCreateKeyEx(HKEY_CLASSES_ROOT, _szInitStr1, 0, NULL, REG_OPTION_NON_VOLATILE, MAXIMUM_ALLOWED, NULL, &hKey, &dwKey)) { RegCloseKey(hKey); hres = S_OK; } break; } case AIINIT_PROGID: { hres = _CreateProgID(); break; } default: hres = E_INVALIDARG; break; } return hres; } HRESULT CFTAssocInfo::DelString(AISTR aistrFlags) { HRESULT hres = E_FAIL; switch(_aiinitFlags1) { case AIINIT_EXT: { switch(aistrFlags) { case AISTR_PROGID: { hres = (RSDeleteValue(NULL, NULL) ? S_OK : E_FAIL); break; } default: hres = E_INVALIDARG; break; } break; } default: hres = E_INVALIDARG; break; } return hres; } HRESULT CFTAssocInfo::Delete(AIALL aiallFlags) { HRESULT hres = E_INVALIDARG; switch (aiallFlags) { case AIALL_NONE: { LONG lRes = -1; if ((AIINIT_PROGID == _aiinitFlags1) && (AIINIT_ACTION == _aiinitFlags2)) { TCHAR szProgIDShell[MAX_PROGID + 1 + 5 + 1]; HKEY hProgIDKey = NULL; StrCpyN(szProgIDShell, _szInitStr1, ARRAYSIZE(szProgIDShell)); lstrcat(szProgIDShell, TEXT("\\shell")); lRes = RegOpenKeyEx(HKEY_CLASSES_ROOT, szProgIDShell, 0, KEY_ALL_ACCESS, &hProgIDKey); if (ERROR_SUCCESS == lRes) { lRes = SHDeleteKey(hProgIDKey, _szInitStr2); RegCloseKey(hProgIDKey); } } else { if (AIINIT_EXT == _aiinitFlags1) lRes = SHDeleteKey(HKEY_CLASSES_ROOT, _szInitStr1); } hres = (ERROR_SUCCESS == lRes) ? S_OK : E_FAIL; break; } case AIALL_PERUSER: { if (AIINIT_EXT == _aiinitFlags1) { UserAssocSet(UASET_CLEAR, _szInitStr1, NULL); hres = S_OK; } else { hres = E_NOTIMPL; } break; } } return hres; } HRESULT CFTAssocInfo::_CreateProgID() { HRESULT hres = E_FAIL; LRESULT lRes = -1; DWORD dwKey = REG_OPENED_EXISTING_KEY; int i = 1; do { HKEY hKey = NULL; wnsprintf(_szInitStr1, ARRAYSIZE(_szInitStr1), TEXT("ft%06d"), i); lRes = RegCreateKeyEx(HKEY_CLASSES_ROOT, _szInitStr1, 0, NULL, REG_OPTION_NON_VOLATILE, MAXIMUM_ALLOWED, NULL, &hKey, &dwKey); if (ERROR_SUCCESS == lRes) RegCloseKey(hKey); ++i; } while((ERROR_SUCCESS == lRes) && (REG_OPENED_EXISTING_KEY == dwKey)); if (REG_OPENED_EXISTING_KEY != dwKey) hres = S_OK; return hres; } HRESULT CFTAssocInfo::_SetIconLocation(LPTSTR pszStr) { HKEY hProgIDKey = NULL; LONG lRes = RegOpenKeyEx(HKEY_CLASSES_ROOT, _szInitStr1, 0, KEY_WRITE, &hProgIDKey); // ProgID // |_ DefaultIcon // |_ (Default) "path\filename.ext, index" // if (ERROR_SUCCESS == lRes) { HKEY hDefaultIconKey = NULL; DWORD dwKey = NULL; lRes = RegCreateKeyEx(hProgIDKey, TEXT("DefaultIcon"), 0, NULL, REG_OPTION_NON_VOLATILE, MAXIMUM_ALLOWED, NULL, &hDefaultIconKey, &dwKey); if (ERROR_SUCCESS == lRes) { lRes = RegSetValueEx(hDefaultIconKey, NULL, 0, REG_SZ, (PBYTE)pszStr, lstrlen(pszStr) * sizeof(TCHAR)); RegCloseKey(hDefaultIconKey); } RegCloseKey(hProgIDKey); } return ((ERROR_SUCCESS == lRes) ? S_OK : E_FAIL); } HRESULT CFTAssocInfo::_GetProgIDDefaultAction(LPTSTR pszStr, DWORD* pcchStr) { return (RSGetTextValue(TEXT("shell"), NULL, pszStr, pcchStr) ? S_OK : E_FAIL); } HRESULT CFTAssocInfo::_SetProgIDDefaultAction(LPTSTR pszStr) { return (RSSetTextValue(TEXT("shell"), NULL, pszStr) ? S_OK : E_FAIL); } HRESULT CFTAssocInfo::_IsBrowseInPlaceEnabled(BOOL* pfBool) { HRESULT hres = (RSSubKeyExist(TEXT("DocObject")) ? S_OK : E_FAIL); if (SUCCEEDED(hres)) *pfBool = TRUE; else *pfBool = FALSE; if (FAILED(hres)) hres = S_FALSE; return hres; } HRESULT CFTAssocInfo::_IsBrowseInPlace(BOOL* pfBool) { HRESULT hres = E_FAIL; LPTSTR pszProgID = _szInitStr1; ASSERT(_aiinitFlags1 == AIINIT_PROGID); *pfBool = FALSE; if (RSSubKeyExist(TEXT("DocObject"))) { DWORD dwValue; hres = (RSGetDWORDValue(NULL, TEXT("BrowserFlags"), &dwValue) ? S_OK : E_FAIL); if (SUCCEEDED(hres)) { *pfBool = IsFlagClear(dwValue, BROWSEHACK_DONTINPLACENAVIGATE); } else { *pfBool = TRUE; } } if (FAILED(hres)) hres = S_FALSE; return hres; } HRESULT CFTAssocInfo::_SetBrowseInPlace(BOOL fBool) { DWORD dwValue; DWORD cbSize = sizeof(dwValue); LPTSTR pszProgID = _szInitStr1; if (RSGetDWORDValue(NULL, TEXT("BrowserFlags"), &dwValue)) { // Watch out: Inverse of fBool if (fBool) ClearFlag(dwValue, BROWSEHACK_DONTINPLACENAVIGATE); else SetFlag(dwValue, BROWSEHACK_DONTINPLACENAVIGATE); } else { dwValue = fBool ? 0 : BROWSEHACK_DONTINPLACENAVIGATE; } if (dwValue) { RSSetDWORDValue(NULL, TEXT("BrowserFlags"), dwValue); } else { RSDeleteValue(NULL, TEXT("BrowserFlags")); } return S_OK; } HRESULT CFTAssocInfo::_IsEditFlagSet(DWORD dwMask, BOOL* pfBool) { DWORD dwEditFlags = 0; LPTSTR pszProgID = _szInitStr1; HRESULT hres = _GetProgIDEditFlags(&dwEditFlags); if (FAILED(hres)) { hres = S_FALSE; // let's put a default value dwEditFlags = 0; } switch(dwMask) { case AIBOOL_CONFIRMOPEN: *pfBool = IsFlagSet(dwEditFlags, FTA_OpenIsSafe); break; case AIBOOL_EDITDESCR: *pfBool = !(IsFlagSet(dwEditFlags, FTA_NoEditDesc)); break; case AIBOOL_EDITDOCICON: *pfBool = !(IsFlagSet(dwEditFlags, FTA_NoEditIcon)); break; case AIBOOL_EDIT: *pfBool = !(IsFlagSet(dwEditFlags, FTA_NoEdit)); break; case AIBOOL_EDITREMOVE: *pfBool = !(IsFlagSet(dwEditFlags, FTA_NoRemove)); break; case AIBOOL_EXCLUDE: *pfBool = IsFlagSet(dwEditFlags, FTA_Exclude); break; case AIBOOL_SHOW: *pfBool = IsFlagSet(dwEditFlags, FTA_Show); break; case AIBOOL_PROGIDHASNOEXT: *pfBool = !IsFlagSet(dwEditFlags, FTA_HasExtension); break; } return hres; } HRESULT CFTAssocInfo::_SetEditFlagSet(DWORD dwMask, BOOL fBool) { DWORD dwEditFlags = 0; DWORD dwToSet = 0; HRESULT hres = _GetProgIDEditFlags(&dwEditFlags); if (FAILED(hres)) dwEditFlags = 0; switch(dwMask) { case AIBOOL_CONFIRMOPEN: dwToSet = FTA_OpenIsSafe; hres = S_OK; break; default: hres = E_FAIL; break; } if (SUCCEEDED(hres)) { if (fBool) SetFlag(dwEditFlags, dwToSet); else ClearFlag(dwEditFlags, dwToSet); if (!RSSetDWORDValue(NULL, TEXT("EditFlags"), dwEditFlags)) { hres = E_FAIL; } } return hres; } HRESULT CFTAssocInfo::_GetProgIDActionAttributes(DWORD* pdwAttributes) { DWORD dwSize = sizeof(*pdwAttributes); HRESULT hres = E_FAIL; // Was there an EditFlags key? if (RSGetDWORDValue(NULL, TEXT("EditFlags"), pdwAttributes)) { // Yes hres = S_OK; } else { // No default to attributes = 0 *pdwAttributes = 0; hres = S_FALSE; } return hres; } HRESULT CFTAssocInfo::_GetProgIDEditFlags(DWORD* pdwEditFlags) { DWORD dwSize = sizeof(*pdwEditFlags); LPTSTR pszProgID = _szInitStr1; return (RSGetDWORDValue(NULL, TEXT("EditFlags"), pdwEditFlags) ? S_OK : E_FAIL); } HRESULT CFTAssocInfo::_GetIconLocation(LPTSTR pszStr, DWORD* pcchStr) { return (RSGetTextValue(TEXT("DefaultIcon"), NULL, pszStr, pcchStr) ? S_OK : E_FAIL); } HRESULT CFTAssocInfo::_GetOpenWithInfo(LPTSTR pszStr, DWORD* pcchStr) { int iRet = -1; LPTSTR pszExt = _szInitStr1; IQueryAssociations* pQA = NULL; HRESULT hres = AssocCreate(CLSID_QueryAssociations, IID_IQueryAssociations, (LPVOID*)&pQA); if (SUCCEEDED(hres)) { WCHAR szwExt[MAX_EXT]; SHTCharToUnicode(pszExt, szwExt, ARRAYSIZE(szwExt)); hres = pQA->Init(0, szwExt, NULL, NULL); if (SUCCEEDED(hres)) { WCHAR szwAppFriendlyName[MAX_APPFRIENDLYNAME]; DWORD cchAFName = ARRAYSIZE(szwAppFriendlyName); TCHAR szAppl[MAX_PATH]; HRESULT hresFriendlyName = pQA->GetString(ASSOCF_VERIFY | ASSOCF_OPEN_BYEXENAME, ASSOCSTR_FRIENDLYAPPNAME, NULL, szwAppFriendlyName, &cchAFName); // Did we get a friendly name? if (SUCCEEDED(hresFriendlyName)) { // Yes, use it SHUnicodeToTChar(szwAppFriendlyName, pszStr, *pcchStr); } // Reuse szwAppFriendlyName hres = pQA->GetString(ASSOCF_VERIFY, ASSOCSTR_EXECUTABLE, NULL, szwAppFriendlyName, &cchAFName); if (SUCCEEDED(hres)) { SHUnicodeToTChar(szwAppFriendlyName, szAppl, ARRAYSIZE(szAppl)); if (FAILED(hresFriendlyName)) { // We failed to get a friendly name, use the EXE name StrCpyN(pszStr, szAppl, *pcchStr); } } } pQA->Release(); } if (FAILED(hres)) *(pszStr) = 0; return hres; } HRESULT CFTAssocInfo::_GetAppIcon(BOOL fSmall, int* piIcon) { LPTSTR pszExt = _szInitStr1; IQueryAssociations* pQA = NULL; HRESULT hres = AssocCreate(CLSID_QueryAssociations, IID_IQueryAssociations, (LPVOID*)&pQA); if (SUCCEEDED(hres)) { WCHAR szwExt[MAX_EXT]; SHTCharToUnicode(pszExt, szwExt, ARRAYSIZE(szwExt)); hres = pQA->Init(0, szwExt, NULL, NULL); if (SUCCEEDED(hres)) { WCHAR szwExecutable[MAX_PATH]; DWORD cchExecutable = ARRAYSIZE(szwExecutable); hres = pQA->GetString(ASSOCF_VERIFY, ASSOCSTR_EXECUTABLE, NULL, szwExecutable, &cchExecutable); if (SUCCEEDED(hres)) { HIMAGELIST himl = fSmall ? _himlSysSmall : _himlSysLarge; int iImage = -1; TCHAR szExe[MAX_PATH]; SHUnicodeToTChar(szwExecutable, szExe, ARRAYSIZE(szExe)); SHFILEINFO sfi = {0}; UINT uFlags = SHGFI_USEFILEATTRIBUTES; uFlags |= (fSmall ? (SHGFI_SMALLICON|SHGFI_ICON) : SHGFI_ICON); if (SHGetFileInfo(szExe, FILE_ATTRIBUTE_NORMAL, &sfi, sizeof(SHFILEINFO), uFlags)) { *piIcon = sfi.iIcon; DestroyIcon(sfi.hIcon); hres = S_OK; } } } pQA->Release(); } return hres; } HRESULT CFTAssocInfo::_ExtIsAssociated(BOOL* pfIsAssociated) { TCHAR szProgID[MAX_PROGID]; DWORD cchProgID = ARRAYSIZE(szProgID); LPTSTR pszExt = _szInitStr1; if (RSGetTextValue(NULL, NULL, szProgID, &cchProgID) && szProgID[0]) { *pfIsAssociated = TRUE; } else { *pfIsAssociated = FALSE; } return S_OK; } HRESULT CFTAssocInfo::_GetExtDocIcon(LPTSTR pszExt, BOOL fSmall, int* piIcon) { HRESULT hres = E_FAIL; SHFILEINFO sfi = {0}; ASSERT(TEXT('.') == *pszExt); UINT uFlags = SHGFI_USEFILEATTRIBUTES; uFlags |= (fSmall ? (SHGFI_SMALLICON|SHGFI_ICON) : SHGFI_ICON); if (SHGetFileInfo(pszExt, FILE_ATTRIBUTE_NORMAL, &sfi, sizeof(SHFILEINFO), uFlags)) { *piIcon = sfi.iIcon; DestroyIcon(sfi.hIcon); hres = S_OK; } return hres; } HRESULT CFTAssocInfo::_GetProgIDDocIcon(BOOL fSmall, int* piIcon) { HRESULT hres = E_FAIL; SHFILEINFO sfi = {0}; LPTSTR pszProgID = _szInitStr1; HIMAGELIST himl = fSmall ? _himlSysSmall : _himlSysLarge; BOOL fHasNoExtension = FALSE; // Try the extension(s) first, unless this is a progID without extension IEnumAssocInfo* pEnum = NULL; if (AIINIT_PROGID == _aiinitFlags1) GetBOOL(AIBOOL_PROGIDHASNOEXT, &fHasNoExtension); if (!fHasNoExtension) { CFTAssocStore* pAssocStore = new CFTAssocStore(); if (pAssocStore) { hres = pAssocStore->EnumAssocInfo(ASENUM_EXT, pszProgID, AIINIT_PROGID, &pEnum); delete pAssocStore; } if (SUCCEEDED(hres)) { IAssocInfo* pAI = NULL; hres = E_FAIL; while (FAILED(hres) && (S_OK == pEnum->Next(&pAI))) { TCHAR szExt[MAX_EXT]; DWORD cchExt = ARRAYSIZE(szExt); hres = pAI->GetString(AISTR_DOTEXT, szExt, &cchExt); if (SUCCEEDED(hres)) hres = _GetExtDocIcon(szExt, fSmall, piIcon); pAI->Release(); } pEnum->Release(); } } // Did it fail? if (FAILED(hres)) { // Yes get it from the progID "DefaultIcon" key, if any hres = E_FAIL; TCHAR szDefaultIcon[MAX_ICONLOCATION]; DWORD cchDefaultIcon = ARRAYSIZE(szDefaultIcon); __InitImageLists(); if (RSGetTextValue(TEXT("DefaultIcon"), NULL, szDefaultIcon, &cchDefaultIcon) && szDefaultIcon[0]) { int iIndex = PathParseIconLocation(szDefaultIcon); *piIcon = Shell_GetCachedImageIndex(szDefaultIcon, iIndex, 0); hres = ((-1 == *piIcon) ? E_FAIL : S_OK); } } // Did it fail? if (FAILED(hres)) { // Yes, get simulated doc icon if from exe name IQueryAssociations* pQA = NULL; hres = AssocCreate(CLSID_QueryAssociations, IID_IQueryAssociations, (LPVOID*)&pQA); if (SUCCEEDED(hres)) { WCHAR szwProgID[MAX_PROGID]; SHTCharToUnicode(pszProgID, szwProgID, ARRAYSIZE(szwProgID)); hres = pQA->Init(0, szwProgID, NULL, NULL); if (SUCCEEDED(hres)) { TCHAR szExeName[MAX_PATH]; WCHAR szwExeName[MAX_PATH]; DWORD dwExeName = ARRAYSIZE(szwExeName); hres = pQA->GetString(ASSOCF_VERIFY, ASSOCSTR_EXECUTABLE, NULL, szwExeName, &dwExeName); if (SUCCEEDED(hres)) { int iImage = 0; SHUnicodeToTChar(szwExeName, szExeName, ARRAYSIZE(szExeName)); *piIcon = Shell_GetCachedImageIndex(szExeName, 0, GIL_SIMULATEDOC); } } pQA->Release(); } } // Did it fail? if (FAILED(hres)) { // Yes, get the shell's default icon *piIcon = II_DOCNOASSOC; hres = S_OK; } return hres; } //static HRESULT CFTAssocInfo::_GetProgIDDescr(LPTSTR pszProgIDDescr, DWORD* pcchProgIDdescr) { HRESULT hres = E_FAIL; IQueryAssociations* pQA = NULL; hres = AssocCreate(CLSID_QueryAssociations, IID_IQueryAssociations, (LPVOID*)&pQA); if (SUCCEEDED(hres)) { WCHAR szwProgID[MAX_PROGID]; SHTCharToUnicode(_szInitStr1, szwProgID, ARRAYSIZE(szwProgID)); hres = pQA->Init(0, szwProgID, NULL, NULL); if (SUCCEEDED(hres)) { WCHAR szwProgIDDescr[MAX_PROGIDDESCR]; // Prepare progID description // Reuse szwProgID hres = pQA->GetString(0, ASSOCSTR_FRIENDLYDOCNAME, NULL, szwProgIDDescr, (LPDWORD)MAKEINTRESOURCE(SIZECHARS(szwProgIDDescr))); if (SUCCEEDED(hres)) SHUnicodeToTChar(szwProgIDDescr, pszProgIDDescr, *pcchProgIDdescr); } pQA->Release(); } return hres; } HRESULT CFTAssocInfo::_OpenSubKey(LPTSTR pszSubKey, REGSAM samDesired, HKEY* phKey) { HRESULT hres = E_FAIL; HKEY hkeyRoot = RSDuplicateRootKey(); if (hkeyRoot) { if (ERROR_SUCCESS == RegOpenKeyEx(hkeyRoot, pszSubKey, 0, MAXIMUM_ALLOWED, phKey)) hres = S_OK; else hres = E_FAIL; RegCloseKey(hkeyRoot); } return hres; } HRESULT CFTAssocInfo::__InitImageLists() { if (!_himlSysLarge ||!_himlSysSmall) Shell_GetImageLists(&_himlSysLarge, &_himlSysSmall); return S_OK; } //IUnknown methods HRESULT CFTAssocInfo::QueryInterface(REFIID riid, PVOID* ppv) { #if 0 static const QITAB qit[] = { QITABENT(CFTAssocStore, IAssocStore), { 0 }, }; return QISearch(this, qit, riid, ppvObj); #endif if (IsEqualIID(riid, IID_IUnknown)) *ppv = static_cast(this); else *ppv = static_cast(this); return S_OK; } ULONG CFTAssocInfo::AddRef() { return InterlockedIncrement(&_cRef); } ULONG CFTAssocInfo::Release() { if (InterlockedDecrement(&_cRef) > 0) return _cRef; delete this; return 0; } // for C callers STDAPI_(BOOL) FT_GetIconLocationFromExt(LPTSTR pszExt, LPTSTR pszPath, DWORD cchPath, int* piIconIndex) { BOOL fRet = FALSE; CFTAssocStore* pAssocStore = new CFTAssocStore(); if (pAssocStore) { IAssocInfo* pAI = NULL; HRESULT hres = pAssocStore->GetAssocInfo(pszExt, AIINIT_EXT, &pAI); if (SUCCEEDED(hres)) { hres = pAI->GetString(AISTR_ICONLOCATION, pszPath, &cchPath); pAI->Release(); if (SUCCEEDED(hres)) { *piIconIndex = PathParseIconLocation(pszPath); fRet = TRUE; } } delete pAssocStore; } return fRet; }