https://blog.youkuaiyun.com/winxsm/article/details/82501974
//#include <windows.h>
#include <stdio.h>
#include <afxwin.h>
#include <winreg.h>
//#include <Winerror.h>
//#include <wtsapi32.h>
//#include <userenv.h>
//#include <WinBase.h>
#include <shlobj.h>
using namespace std;
// hide console window
#pragma comment( linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" )
#define TYPENUMS 6
struct AssociateType
{
const char * defaultIconNum; // DefaultIcon num in exe file
const char * extention; // extention name
const char *associateKey; // form like "CAJViewer70 + extention"
const char *contentType; // form like "application/extention"
bool isAssociate; // TRUE if need to be associated
};
// function prototype
bool associateFile(const struct AssociateType &, const char *);
bool removeAssocaiteFile(const struct AssociateType &);
bool EnablePriviledge(TCHAR *lpSystemName);
// parameter
// argc: the number of the parameter
// argv: the first is name of exefile, then the extensions and iconPath,
// the last is exeFile path associate with the specified extension
int main(int argc, char **argv)
{
struct AssociateType key[TYPENUMS] = { { "5", ".caa", "CAJViewer70.CAA", "application/caa" , FALSE },
{ "1", ".caj", "CAJViewer70.CAJ", "application/caj", FALSE },
{ "6", ".teb", "CAJViewer70.TEB", "application/teb", FALSE },
{ "4", ".kdh", "CAJViewer70.KDH", "application/kdh", FALSE },
{ "3", ".nh", "CAJViewer70.NH" , "application/nh" , FALSE },
{ "2", ".pdf", "CAJViewer70.PDF", "application/pdf", FALSE }
};
// set isAssociate that extentions to be associated exists to TRUE
for (int i = 1; i < argc - 1; i += 2) {
for (int j = 0; j < TYPENUMS; j++) {
if (strcmp(argv[i], key[j].extention) == 0)
key[j].isAssociate = TRUE;
}
}
for (int i = 0; i < TYPENUMS; i++) {
if (key[i].isAssociate == TRUE)
associateFile(key[i], argv[argc - 1]);
else
removeAssocaiteFile(key[i]);
}
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, 0, 0);
return 0;
}
bool EnablePriviledge(TCHAR *lpSystemName) {
HANDLE hToken;
TOKEN_PRIVILEGES tkp = { 1 };
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
if (LookupPrivilegeValue(NULL, lpSystemName, &tkp.Privileges[0].Luid)) {
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
if (GetLastError() != ERROR_SUCCESS) {
CloseHandle(hToken);
return false;
}
}
CloseHandle(hToken);
}
return true;
}
bool associateFile(const struct AssociateType &keyInfo, const char *exePath)
{
HKEY hKey;
char *lpszShellOpen = "\\shell\\open\\command";
char *lpszDefaultIcon = "\\DefaultIcon";
char *lpszClass = "Software\\CLASSES\\";
//TCHAR *lpszMime = _T("Software\\CLASSES\\MIME\\Database\\Content Type");
char *lpszExplorer = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts\\";
char *contentType = "Content Type";
int retVal = 0;
int lengthExePath = strlen(exePath);
int lengthAssociateKey = strlen(keyInfo.associateKey);
int lengthContentType = strlen(keyInfo.contentType);
// set form like .caa
if ((retVal = (RegCreateKeyExA(HKEY_CLASSES_ROOT, keyInfo.extention, 0, REG_NONE,
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL))) != ERROR_SUCCESS) {
fprintf(stderr, "Create key %s failed! ErrorCode is %d.\n", keyInfo.extention, retVal);
exit(0);
}
if ((retVal = RegSetValueExA(hKey, NULL, 0, REG_SZ, (const BYTE *)keyInfo.associateKey,
lengthAssociateKey + 1)) != ERROR_SUCCESS) {
fprintf(stderr, "Set processKey \"%s\" key failed! ErrorCode is %d.\n", keyInfo.associateKey, retVal);
exit(0);
}
if ((retVal = RegSetValueExA(hKey, contentType, 0, REG_SZ, (const BYTE *)keyInfo.contentType,
lengthContentType + 1)) != ERROR_SUCCESS) {
fprintf(stderr, "Set processKey \"%s\" key failed! ErrorCode is %d\n", keyInfo.contentType, retVal);
exit(0);
}
// create or open DefaultIcon key
int lengthCompleteDefaultIcon = lengthAssociateKey + strlen(lpszDefaultIcon) + 1;
char *completeDefaultIcon = new char[lengthCompleteDefaultIcon];
strcpy_s(completeDefaultIcon, lengthCompleteDefaultIcon, keyInfo.associateKey);
strcat_s(completeDefaultIcon, lengthCompleteDefaultIcon, lpszDefaultIcon);
if ((retVal = RegCreateKeyExA(HKEY_CLASSES_ROOT, completeDefaultIcon, 0, REG_NONE,
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL)) != ERROR_SUCCESS) {
fprintf(stderr, "Create defaultIcon \"%s\" key failed!\nError_code is %d\n", completeDefaultIcon);
exit(0);
}
int lengthValueDefaultIcon = lengthExePath + 3;
char *ValueDefaultIcon = new char[lengthValueDefaultIcon];
strcpy_s(ValueDefaultIcon, lengthValueDefaultIcon, exePath);
strcat_s(ValueDefaultIcon, lengthValueDefaultIcon, ",");
strcat_s(ValueDefaultIcon, lengthValueDefaultIcon, keyInfo.defaultIconNum);
if ((retVal = RegSetValueExA(hKey, NULL, 0, REG_SZ, (const BYTE *)ValueDefaultIcon, lengthValueDefaultIcon)) != ERROR_SUCCESS) {
fprintf(stderr, "Set defaultIcon \"%s\" key failed!\nError_code is %d\n", ValueDefaultIcon, retVal);
exit(0);
}
RegCloseKey(hKey);
// set form like "\\shell\\open\\command"
int lengthCompleteShellOpen = lengthAssociateKey + strlen(lpszShellOpen) + 1;
char *completeShellOpen = new char[lengthCompleteShellOpen];
strcpy_s(completeShellOpen, lengthCompleteShellOpen, keyInfo.associateKey);
strcat_s(completeShellOpen, lengthCompleteShellOpen, lpszShellOpen);
if ((retVal = (RegCreateKeyExA(HKEY_CLASSES_ROOT, completeShellOpen, 0, REG_NONE,
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL))) != ERROR_SUCCESS) {
fprintf(stderr, "Create key %s failed! ErrorCode is %d.\n", keyInfo.extention, retVal);
exit(0);
}
//"exepath" "%1"
int lengthValueShellOpen = lengthExePath + strlen("\"\" \"%1\"") + 1;
char *ValueShellOpen = new char[lengthValueShellOpen];
strcpy_s(ValueShellOpen, lengthValueShellOpen, "\"");
strcat_s(ValueShellOpen, lengthValueShellOpen, exePath);
strcat_s(ValueShellOpen, lengthValueShellOpen, "\" \"%1\"");
if ((retVal = RegSetValueExA(hKey, NULL, 0, REG_SZ, (const BYTE *)ValueShellOpen,
lengthValueShellOpen)) != ERROR_SUCCESS) {
fprintf(stderr, "Set processKey \"%s\" key failed! ErrorCode is %d.\n", ValueShellOpen, retVal);
exit(0);
}
RegCloseKey(hKey);
// HKEY_CURRENT_USER
int lengthHKCUExtention = strlen(lpszClass) + strlen(keyInfo.extention) + 1;
char *completeHKCUExtention = new char[lengthHKCUExtention];
strcpy_s(completeHKCUExtention, lengthHKCUExtention, lpszClass);
strcat_s(completeHKCUExtention, lengthHKCUExtention, keyInfo.extention);
if ((retVal = (RegCreateKeyExA(HKEY_CURRENT_USER, completeHKCUExtention, 0, REG_NONE,
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL))) != ERROR_SUCCESS) { // Software\\CLASSES
fprintf(stderr, "Create \"%s\" key failed! ErrorCode is %d.\n", completeHKCUExtention, retVal);
exit(0);
}
if ((retVal = RegSetValueExA(hKey, NULL, 0, REG_SZ, (const BYTE *)keyInfo.associateKey,
lengthAssociateKey + 1)) != ERROR_SUCCESS) {
fprintf(stderr, "Set processKey \"%s\" key failed! ErrorCode is %d.\n", keyInfo.associateKey, retVal);
exit(0);
}
if ((retVal = RegSetValueExA(hKey, contentType, 0, REG_SZ, (const BYTE *)keyInfo.contentType,
lengthContentType + 1)) != ERROR_SUCCESS) {
fprintf(stderr, "Set processKey \"%s\" key failed! ErrorCode is %d\n", keyInfo.contentType, retVal);
exit(0);
}
RegCloseKey(hKey);
delete[] completeHKCUExtention;
// create or open DefaultIcon key
int lengthHKCUCompleteDefaultIcon = strlen(lpszClass) + lengthAssociateKey + strlen(lpszDefaultIcon) + 1;
char *completeHKCUDefaultIcon = new char[lengthHKCUCompleteDefaultIcon];
strcpy_s(completeHKCUDefaultIcon, lengthHKCUCompleteDefaultIcon, lpszClass);
strcat_s(completeHKCUDefaultIcon, lengthHKCUCompleteDefaultIcon, keyInfo.associateKey);
strcat_s(completeHKCUDefaultIcon, lengthHKCUCompleteDefaultIcon, lpszDefaultIcon);
if ((retVal = RegCreateKeyExA(HKEY_CURRENT_USER, completeHKCUDefaultIcon, 0, REG_NONE,
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL)) != ERROR_SUCCESS) {
fprintf(stderr, "Create defaultIcon \"%s\" key failed!\nError_code is %d\n", completeHKCUDefaultIcon);
exit(0);
}
if ((retVal = RegSetValueExA(hKey, NULL, 0, REG_SZ, (const BYTE *)ValueDefaultIcon, lengthValueDefaultIcon)) != ERROR_SUCCESS) {
fprintf(stderr, "Set defaultIcon \"%s\" key failed!\nError_code is %d\n", ValueDefaultIcon, retVal);
exit(0);
}
RegCloseKey(hKey);
delete[] completeHKCUDefaultIcon;
// set form like "\\shell\\open\\command"
int lengthHKCUCompleteShellOpen = strlen(lpszClass) + lengthAssociateKey + strlen(lpszShellOpen) + 1;
char *completeHKCUShellOpen = new char[lengthHKCUCompleteShellOpen];
strcpy_s(completeHKCUShellOpen, lengthHKCUCompleteShellOpen, lpszClass);
strcat_s(completeHKCUShellOpen, lengthHKCUCompleteShellOpen, keyInfo.associateKey);
strcat_s(completeHKCUShellOpen, lengthHKCUCompleteShellOpen, lpszShellOpen);
if ((retVal = (RegCreateKeyExA(HKEY_CURRENT_USER, completeHKCUShellOpen, 0, REG_NONE,
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL))) != ERROR_SUCCESS) {
fprintf(stderr, "Create key %s failed! ErrorCode is %d.\n", completeHKCUShellOpen, retVal);
exit(0);
}
//"exepath" "%1"
if ((retVal = RegSetValueExA(hKey, NULL, 0, REG_SZ, (const BYTE *)ValueShellOpen,
lengthValueShellOpen)) != ERROR_SUCCESS) {
fprintf(stderr, "Set processKey \"%s\" key failed! ErrorCode is %d.\n", ValueShellOpen, retVal);
exit(0);
}
RegCloseKey(hKey);
delete[] completeHKCUShellOpen;
// Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts\\
int lengthHKCUChoice = strlen(lpszExplorer) + strlen(keyInfo.extention) + strlen("\\UserChoice") + 10;
char *completeHKCUChoice = new char[lengthHKCUChoice];
strcpy_s(completeHKCUChoice, lengthHKCUChoice, lpszExplorer);
strcat_s(completeHKCUChoice, lengthHKCUChoice, keyInfo.extention);
strcat_s(completeHKCUChoice, lengthHKCUChoice, "\\UserChoice");
LONG lResult;
EnablePriviledge(SE_BACKUP_NAME);//这个函数是重点,让当前进程具备备份/还原的特权。
EnablePriviledge(SE_RESTORE_NAME);
DWORD dwDisposition;
if ((retVal = (RegCreateKeyExA(HKEY_CURRENT_USER, completeHKCUChoice, 0, NULL,
REG_OPTION_BACKUP_RESTORE, KEY_ALL_ACCESS, NULL, &hKey, (LPDWORD)&dwDisposition))) != ERROR_SUCCESS) {
fprintf(stderr, "Create \"%s\" key failed! ErrorCode is %d.\n", completeHKCUChoice, retVal);
exit(0);
}
lResult = RegSetValueExA(hKey, "Progid", NULL, REG_SZ, (LPBYTE)keyInfo.associateKey, lengthAssociateKey + 1);
RegCloseKey(hKey);
delete[] completeHKCUChoice;
return 0;
}
bool removeAssocaiteFile(const struct AssociateType &keyInfo)
{
HKEY hKey;
char *lpszClass = "Software\\CLASSES\\";
//TCHAR *lpszMime = _T("Software\\CLASSES\\MIME\\Database\\Content Type");
char *lpszExplorer = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts\\";
int retVal = 0;
// if open associate key success, then delete defaultIcon
if (RegOpenKeyExA(HKEY_CLASSES_ROOT, keyInfo.associateKey, 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS) {
// delete in HKEY_CLASSES_ROOT
RegDeleteKeyA(HKEY_CLASSES_ROOT, keyInfo.extention);
RegDeleteTreeA(HKEY_CLASSES_ROOT, keyInfo.associateKey);
}
int lengthHKCUAssociate = strlen(lpszClass) + strlen(keyInfo.associateKey) + 1;
char *completeHKCUAssociate = new char[lengthHKCUAssociate];
strcpy_s(completeHKCUAssociate, lengthHKCUAssociate, lpszClass);
strcat_s(completeHKCUAssociate, lengthHKCUAssociate, keyInfo.associateKey);
if (RegOpenKeyExA(HKEY_CURRENT_USER, completeHKCUAssociate, 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS) {
// delete in HKEY_CURRENT_USER
int lengthHKCUExtention = strlen(lpszClass) + strlen(keyInfo.extention) + 1;
char *completeHKCUExtention = new char[lengthHKCUExtention];
strcpy_s(completeHKCUExtention, lengthHKCUExtention, lpszClass);
strcat_s(completeHKCUExtention, lengthHKCUExtention, keyInfo.extention);
RegDeleteKeyA(HKEY_CURRENT_USER, completeHKCUExtention);
RegDeleteTreeA(HKEY_CURRENT_USER, completeHKCUAssociate);
}
delete[] completeHKCUAssociate;
int lengthHKCUChoice = strlen(lpszExplorer) + strlen(keyInfo.extention) + strlen("\\UserChoice") + 1;
char *completeHKCUChoice = new char[lengthHKCUChoice];
strcpy_s(completeHKCUChoice, lengthHKCUChoice, lpszExplorer);
strcat_s(completeHKCUChoice, lengthHKCUChoice, keyInfo.extention);
strcat_s(completeHKCUChoice, lengthHKCUChoice, "\\UserChoice");
RegDeleteKeyA(HKEY_CURRENT_USER, completeHKCUChoice);
delete [] completeHKCUChoice;
return 0;
}