Fix modifying file type associations under MSW as non-admin
The existing code tried writing to HKEY_CLASSES_ROOT which doesn't work, in general, for normal, i.e. non administrator, users, under any post-XP versions of Windows. Fix it to write to HKEY_CURRENT_USER\Software\Classes, which is the part of HKEY_CLASSES_ROOT for the current user and to which we do have write access, and only continue to use HKEY_CLASSES_ROOT itself for reading.
This commit is contained in:
parent
058e35c0ec
commit
0ed580f451
@ -81,6 +81,17 @@ class WXDLLIMPEXP_FWD_CORE wxIcon;
|
||||
// to open/print the file (the positional parameters are introduced by %1,
|
||||
// %2, ... in these strings, we change them to %s ourselves)
|
||||
|
||||
// Notice that HKCR can be used only when reading from the registry, when
|
||||
// writing to it, we need to write to HKCU\Software\Classes instead as HKCR is
|
||||
// a merged view of that location and HKLM\Software\Classes that we generally
|
||||
// wouldn't have the write permissions to but writing to HKCR will try writing
|
||||
// to the latter unless the key being written to already exists under the
|
||||
// former, resulting in a "Permission denied" error without administrative
|
||||
// permissions. So the right thing to do is to use HKCR when reading, to
|
||||
// respect both per-user and machine-global associations, but only write under
|
||||
// HKCU.
|
||||
static const wxChar *CLASSES_ROOT_KEY = wxS("Software\\Classes\\");
|
||||
|
||||
// although I don't know of any official documentation which mentions this
|
||||
// location, uses it, so it isn't likely to change
|
||||
static const wxChar *MIME_DATABASE_KEY = wxT("MIME\\Database\\Content Type\\");
|
||||
@ -205,7 +216,7 @@ size_t wxFileTypeImpl::GetAllCommands(wxArrayString *verbs,
|
||||
|
||||
bool wxFileTypeImpl::EnsureExtKeyExists()
|
||||
{
|
||||
wxRegKey rkey(wxRegKey::HKCR, m_ext);
|
||||
wxRegKey rkey(wxRegKey::HKCU, CLASSES_ROOT_KEY + m_ext);
|
||||
if ( !rkey.Exists() )
|
||||
{
|
||||
if ( !rkey.Create() || !rkey.SetValue(wxEmptyString, m_strFileType) )
|
||||
@ -553,11 +564,11 @@ wxFileType *wxMimeTypesManagerImpl::Associate(const wxFileTypeInfo& ftInfo)
|
||||
extWithDot = wxT('.');
|
||||
extWithDot += ext;
|
||||
|
||||
// start by setting the HKCR\\.ext entries
|
||||
// start by setting the entries under ".ext"
|
||||
// default is filetype; content type is mimetype
|
||||
const wxString& filetypeOrig = ftInfo.GetShortDesc();
|
||||
|
||||
wxRegKey key(wxRegKey::HKCR, extWithDot);
|
||||
wxRegKey key(wxRegKey::HKCU, CLASSES_ROOT_KEY + extWithDot);
|
||||
if ( !key.Exists() )
|
||||
{
|
||||
// create the mapping from the extension to the filetype
|
||||
@ -605,7 +616,7 @@ wxFileType *wxMimeTypesManagerImpl::Associate(const wxFileTypeInfo& ftInfo)
|
||||
// create the MIME key
|
||||
wxString strKey = MIME_DATABASE_KEY;
|
||||
strKey << mimetype;
|
||||
wxRegKey keyMIME(wxRegKey::HKCR, strKey);
|
||||
wxRegKey keyMIME(wxRegKey::HKCU, CLASSES_ROOT_KEY + strKey);
|
||||
ok = keyMIME.Create();
|
||||
|
||||
if ( ok )
|
||||
@ -626,7 +637,7 @@ wxFileType *wxMimeTypesManagerImpl::Associate(const wxFileTypeInfo& ftInfo)
|
||||
extWithDot = wxT('.');
|
||||
extWithDot += ext;
|
||||
|
||||
wxRegKey key2(wxRegKey::HKCR, extWithDot);
|
||||
wxRegKey key2(wxRegKey::HKCU, CLASSES_ROOT_KEY + extWithDot);
|
||||
if ( !key2.Exists() )
|
||||
key2.Create();
|
||||
key2.SetValue(wxEmptyString, filetype);
|
||||
@ -643,7 +654,7 @@ wxFileType *wxMimeTypesManagerImpl::Associate(const wxFileTypeInfo& ftInfo)
|
||||
// create the MIME key
|
||||
wxString strKey = MIME_DATABASE_KEY;
|
||||
strKey << mimetype2;
|
||||
wxRegKey keyMIME(wxRegKey::HKCR, strKey);
|
||||
wxRegKey keyMIME(wxRegKey::HKCU, CLASSES_ROOT_KEY + strKey);
|
||||
ok = keyMIME.Create();
|
||||
|
||||
if ( ok )
|
||||
@ -654,11 +665,11 @@ wxFileType *wxMimeTypesManagerImpl::Associate(const wxFileTypeInfo& ftInfo)
|
||||
}
|
||||
}
|
||||
|
||||
} // end of for loop; all extensions now point to HKCR\.ext\Default
|
||||
} // end of for loop; all extensions now point to .ext\Default
|
||||
|
||||
// create the filetype key itself (it will be empty for now, but
|
||||
// SetCommand(), SetDefaultIcon() &c will use it later)
|
||||
wxRegKey keyFT(wxRegKey::HKCR, filetype);
|
||||
wxRegKey keyFT(wxRegKey::HKCU, CLASSES_ROOT_KEY + filetype);
|
||||
keyFT.Create();
|
||||
|
||||
wxFileType *ft = CreateFileType(filetype, extWithDot);
|
||||
@ -686,7 +697,7 @@ bool wxFileTypeImpl::SetCommand(const wxString& cmd,
|
||||
if ( !EnsureExtKeyExists() )
|
||||
return false;
|
||||
|
||||
wxRegKey rkey(wxRegKey::HKCR, GetVerbPath(verb));
|
||||
wxRegKey rkey(wxRegKey::HKCU, CLASSES_ROOT_KEY + GetVerbPath(verb));
|
||||
|
||||
// TODO:
|
||||
// 1. translate '%s' to '%1' instead of always adding it
|
||||
@ -704,7 +715,8 @@ bool wxFileTypeImpl::SetDefaultIcon(const wxString& cmd, int index)
|
||||
if ( !EnsureExtKeyExists() )
|
||||
return false;
|
||||
|
||||
wxRegKey rkey(wxRegKey::HKCR, m_strFileType + wxT("\\DefaultIcon"));
|
||||
wxRegKey rkey(wxRegKey::HKCU,
|
||||
CLASSES_ROOT_KEY + m_strFileType + wxT("\\DefaultIcon"));
|
||||
|
||||
return rkey.Create() &&
|
||||
rkey.SetValue(wxEmptyString,
|
||||
@ -719,7 +731,7 @@ bool wxFileTypeImpl::SetDescription (const wxString& desc)
|
||||
if ( !EnsureExtKeyExists() )
|
||||
return false;
|
||||
|
||||
wxRegKey rkey(wxRegKey::HKCR, m_strFileType );
|
||||
wxRegKey rkey(wxRegKey::HKCU, CLASSES_ROOT_KEY + m_strFileType );
|
||||
|
||||
return rkey.Create() &&
|
||||
rkey.SetValue(wxEmptyString, desc);
|
||||
@ -754,7 +766,7 @@ bool wxFileTypeImpl::RemoveCommand(const wxString& verb)
|
||||
wxCHECK_MSG( !m_ext.empty() && !verb.empty(), false,
|
||||
wxT("RemoveCommand() needs an extension and a verb") );
|
||||
|
||||
wxRegKey rkey(wxRegKey::HKCR, GetVerbPath(verb));
|
||||
wxRegKey rkey(wxRegKey::HKCU, CLASSES_ROOT_KEY + GetVerbPath(verb));
|
||||
|
||||
// if the key already doesn't exist, it's a success
|
||||
return !rkey.Exists() || rkey.DeleteSelf();
|
||||
@ -764,7 +776,7 @@ bool wxFileTypeImpl::RemoveMimeType()
|
||||
{
|
||||
wxCHECK_MSG( !m_ext.empty(), false, wxT("RemoveMimeType() needs extension") );
|
||||
|
||||
wxRegKey rkey(wxRegKey::HKCR, m_ext);
|
||||
wxRegKey rkey(wxRegKey::HKCU, CLASSES_ROOT_KEY + m_ext);
|
||||
return !rkey.Exists() || rkey.DeleteSelf();
|
||||
}
|
||||
|
||||
@ -773,7 +785,8 @@ bool wxFileTypeImpl::RemoveDefaultIcon()
|
||||
wxCHECK_MSG( !m_ext.empty(), false,
|
||||
wxT("RemoveDefaultIcon() needs extension") );
|
||||
|
||||
wxRegKey rkey (wxRegKey::HKCR, m_strFileType + wxT("\\DefaultIcon"));
|
||||
wxRegKey rkey (wxRegKey::HKCU,
|
||||
CLASSES_ROOT_KEY + m_strFileType + wxT("\\DefaultIcon"));
|
||||
return !rkey.Exists() || rkey.DeleteSelf();
|
||||
}
|
||||
|
||||
@ -782,7 +795,7 @@ bool wxFileTypeImpl::RemoveDescription()
|
||||
wxCHECK_MSG( !m_ext.empty(), false,
|
||||
wxT("RemoveDescription() needs extension") );
|
||||
|
||||
wxRegKey rkey (wxRegKey::HKCR, m_strFileType );
|
||||
wxRegKey rkey (wxRegKey::HKCU, CLASSES_ROOT_KEY + m_strFileType );
|
||||
return !rkey.Exists() || rkey.DeleteSelf();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user