mirror of
https://github.com/fadden/ciderpress.git
synced 2024-11-26 17:49:21 +00:00
ef708f563e
The DeployMaster installer issue prevents the user from seeing more than nine of the 18 file extensions that CiderPress wants to handle, and I don't want to go stomping on file associations without some way to disable the behavior. So this returns to the previous behavior, where CiderPress directly manages the file associations. The CiderPress app is not able to modify HKEY_LOCAL_MACHINE (which it used to do via HKEY_CLASSES_ROOT) on recent versions of Windows -- tested in Win7, but it probably broke with Vista. So now we do everything in HKEY_CURRENT_USER. This works, more or less. We're not looking at the Windows shell overrides, which are made in yet another set of registry entries, so there are multiple reasons why the values reported by the Edit Associations dialog may now be inaccurate. I still favor eliminating the dialog as a long-term strategy. I took the opportunity to do some code cleanup in the registry code. I also added calls to SHChangeNotify() to tell the Windows shell when file associations change, so Windows Explorer windows get updated promptly.
194 lines
6.3 KiB
C++
194 lines
6.3 KiB
C++
/*
|
|
* CiderPress
|
|
* Copyright (C) 2007 by faddenSoft, LLC. All Rights Reserved.
|
|
* See the file LICENSE for distribution terms.
|
|
*/
|
|
/*
|
|
* A class representing the system registry.
|
|
*/
|
|
#ifndef APP_REGISTRY_H
|
|
#define APP_REGISTRY_H
|
|
|
|
#ifdef CAN_UPDATE_FILE_ASSOC
|
|
|
|
/*
|
|
* All access to the registry (except for GetProfileInt/GetProfileString)
|
|
* should go through this.
|
|
*/
|
|
class MyRegistry {
|
|
public:
|
|
MyRegistry(void) {}
|
|
~MyRegistry(void) {}
|
|
|
|
/*
|
|
typedef enum RegStatus {
|
|
kRegUnknown = 0,
|
|
kRegNotSet, // unregistered
|
|
kRegExpired, // unregistered, expired
|
|
kRegValid, // registration present and valid
|
|
kRegInvalid, // registration present, but invalid (!)
|
|
kRegFailed, // error occurred during registration
|
|
} RegStatus;
|
|
*/
|
|
|
|
/*
|
|
* This is called immediately after installation finishes.
|
|
*
|
|
* We want to snatch up any unused file type associations. We define them
|
|
* as "unused" if the entry does not exist in the registry at all. A more
|
|
* thorough installer would also verify that the ProgID actually existed
|
|
* and "steal" any apparent orphans, but we can let the user do that manually.
|
|
*/
|
|
void OneTimeInstall(void) const;
|
|
|
|
/*
|
|
* Remove things that the standard uninstall script won't.
|
|
*
|
|
* We want to un-set any of our file associations. We don't really need to
|
|
* clean up the ".xxx" entries, because removing their ProgID entries is enough
|
|
* to fry their little brains, but it's probably the right thing to do.
|
|
*
|
|
* We definitely want to strip out our ProgIDs.
|
|
*/
|
|
void OneTimeUninstall(void) const;
|
|
|
|
/*
|
|
int GetRegistration(CString* pUser, CString* pCompany,
|
|
CString* pReg, CString* pVersions, CString* pExpire);
|
|
int SetRegistration(const CString& user, const CString& company,
|
|
const CString& reg, const CString& versions, const CString& expire);
|
|
RegStatus CheckRegistration(CString* pResult);
|
|
bool IsValidRegistrationKey(const CString& user,
|
|
const CString& company, const CString& reg);
|
|
*/
|
|
|
|
/*
|
|
* Return the application's registry key. This is used as the argument to
|
|
* CWinApp::SetRegistryKey(). The GetProfile{Int,String} calls combine this
|
|
* (in m_pszRegistryKey) with the app name (in m_pszProfileName) and
|
|
* prepends "HKEY_CURRENT_USER\Software\".
|
|
*/
|
|
const WCHAR* GetAppRegistryKey(void) const;
|
|
|
|
// Fix basic settings, e.g. HKCU ProgID classes.
|
|
void FixBasicSettings(void) const;
|
|
|
|
/*
|
|
* Return the number of file type associations.
|
|
*/
|
|
int GetNumFileAssocs(void) const;
|
|
|
|
/*
|
|
* Return information on a file association.
|
|
*
|
|
* For the given index, return the extension, the ProgID key, and an
|
|
* indication of whether or not we believe this is ours. If nothing
|
|
* is associated with this extension, *pHandler receives an empty string.
|
|
*/
|
|
void GetFileAssoc(int idx, CString* pExt, CString* pHandler,
|
|
bool* pOurs) const;
|
|
|
|
/*
|
|
* Sets the state of a file association.
|
|
*/
|
|
int SetFileAssoc(int idx, bool wantIt) const;
|
|
|
|
//static uint16_t ComputeStringCRC(const char* str);
|
|
|
|
private:
|
|
typedef struct FileTypeAssoc {
|
|
const WCHAR* ext; // e.g. ".SHK"
|
|
const WCHAR* progId; // e.g. "CiderPress.NuFX.4"
|
|
} FileTypeAssoc;
|
|
|
|
static const FileTypeAssoc kFileTypeAssoc[];
|
|
|
|
/*
|
|
* See if a ProgID key is one we recognize.
|
|
*/
|
|
bool IsOurProgId(const WCHAR* progIdKeyName) const;
|
|
|
|
/*
|
|
* Set up the registry goodies for one ProgID.
|
|
*/
|
|
void ConfigureProgId(const WCHAR* progIdKeyName, const WCHAR* descr,
|
|
const WCHAR* exeName, int iconIdx) const;
|
|
|
|
/*
|
|
* Puts the "Open" command in "...\shell\open\command".
|
|
*/
|
|
void ConfigureProgIdCommand(HKEY hAppKey, const WCHAR* descr,
|
|
const WCHAR* exeName) const;
|
|
|
|
/*
|
|
* Given a ProgID, determine the application's name. The executable
|
|
* path will be stripped.
|
|
*
|
|
* This requires burrowing down into
|
|
* HKEY_CURRENT_USER\<ProgIdKey>\shell\open\command\.
|
|
*
|
|
* This does not currently take into account the Windows shell stuff, i.e.
|
|
* HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\<.ext>
|
|
* (and I'm not really sure we should).
|
|
*
|
|
* TODO: if we don't find an association in HKCU, do a lookup in HKCR.
|
|
* That could get confusing if there's an older CiderPress association
|
|
* lurking in HKLM, but it's at least as confusing to see "no
|
|
* association" when there's clearly an association.
|
|
*/
|
|
int GetAssocAppName(const CString& progIdKeyName, CString* pCmd) const;
|
|
|
|
/*
|
|
* Reduce a compound string to just its first token.
|
|
*/
|
|
void ReduceToToken(CString* pStr) const;
|
|
|
|
/*
|
|
* Determine whether or not the filetype described by "ext" is one that we
|
|
* currently manage.
|
|
*
|
|
* Returns "true" if so, "false" if not. Returns "false" on any errors
|
|
* encountered.
|
|
*/
|
|
bool GetAssocState(const WCHAR* ext) const;
|
|
|
|
/*
|
|
* Drop ownership of a file extension. We assume we own it.
|
|
*
|
|
* Returns 0 on success, -1 on error.
|
|
*/
|
|
int DisownExtension(const WCHAR* ext) const;
|
|
|
|
/*
|
|
* Take ownership of a file extension.
|
|
*
|
|
* Returns 0 on success, -1 on error.
|
|
*/
|
|
int OwnExtension(const WCHAR* ext, const WCHAR* progIdKeyName) const;
|
|
|
|
/*
|
|
* Open HKEY_CURRENT_USER\Software\Classes for reading.
|
|
*/
|
|
DWORD OpenHKCUSoftwareClasses(HKEY* phKey) const;
|
|
|
|
/*
|
|
* Recursively delete a key in the HKEY_CURRENT_USER\Software\Classes
|
|
* hierarchy.
|
|
*/
|
|
DWORD RegDeleteKeyHKCU(const WCHAR* partialKeyName) const;
|
|
|
|
DWORD RegDeleteKeyNT(HKEY hStartKey, LPCWSTR pKeyName) const;
|
|
|
|
/* key validation */
|
|
//static uint16_t CalcCRC16(uint16_t seed,
|
|
// const uint8_t* ptr, int count);
|
|
|
|
static char* StripStrings(const char* str1, const char* str2);
|
|
void ComputeKey(const char* chBuf, int salt, long* pKeyLo, long* pKeyHi);
|
|
int VerifyKey(const char* user, const char* company, const char* key);
|
|
};
|
|
|
|
#endif
|
|
|
|
#endif /*APP_REGISTRY_H*/
|