|
|
#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); StringCchCat(szSubKey, ARRAYSIZE(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;
// <ProgID>
// |_ shell
// |_ <action>
// | (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)); StringCchCat(szProgIDShell, ARRAYSIZE(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::__InitImageLists() { if (!_himlSysLarge ||!_himlSysSmall) Shell_GetImageLists(&_himlSysLarge, &_himlSysSmall);
return S_OK; }
//IUnknown methods
HRESULT CFTAssocInfo::QueryInterface(REFIID riid, PVOID* ppv) { if (IsEqualIID(riid, IID_IUnknown)) *ppv = static_cast<IUnknown*>(this); else *ppv = static_cast<IAssocInfo*>(this);
return S_OK; }
ULONG CFTAssocInfo::AddRef() { return InterlockedIncrement(&_cRef); }
ULONG CFTAssocInfo::Release() { ASSERT( 0 != _cRef ); ULONG cRef = InterlockedDecrement(&_cRef); if ( 0 == cRef ) { delete this; } return cRef; }
|