实现文件关联踩的各种坑

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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值