add install code WITHOUT safety check!
This commit is contained in:
@ -1,7 +1,10 @@
|
||||
#include "wfassoc.h"
|
||||
#include <strsafe.h>
|
||||
#include <ShlObj.h>
|
||||
|
||||
// private function and variable declearions.
|
||||
// the function with _AL tail mean that the value returned by function is allocated from heap and should be free manually.
|
||||
// otherwise, the tail of _NAL mean this function will not allocate any new memeory.
|
||||
|
||||
/// <summary>
|
||||
/// Convert multi byte string to wide char string
|
||||
@ -10,18 +13,186 @@
|
||||
/// <param name="source">The string will be converted</param>
|
||||
/// <param name="error">The error happend during converting</param>
|
||||
/// <returns>The string has been converted. If return NULL, it mean that the converting failed.</returns>
|
||||
WCHAR* ConvMultiByteToWideChar(CHAR* source);
|
||||
WCHAR* ConvMultiByteToWideChar_AL(CHAR* source);
|
||||
WCHAR* GetAppNameFromAppPath_NAL(WCHAR* path);
|
||||
WCHAR* Strcat_AL(WCHAR* str1, WCHAR* str2);
|
||||
WCHAR* GetPathFromAppPath_AL(WCHAR* path);
|
||||
WCHAR* IterateSupportedTypesString_NAL(WCHAR* typesString, WCHAR* prev);
|
||||
|
||||
void WFPrintflnInDebug();
|
||||
|
||||
// some effective reg function
|
||||
LSTATUS WFRegOpenKeyWithCreation(HKEY hkey, LPCWSTR lpSubKey, PHKEY phkResult);
|
||||
LSTATUS WFRegSetStringValue(HKEY hkey, LPCWSTR lpValueName, const WCHAR* data);
|
||||
|
||||
#define LEGACY_PROGID_FORMATA "%s.%s.%d"
|
||||
#define LEGACY_PROGID_FORMATW L"%s.%s.%d"
|
||||
#define SAFE_FREE(obj) if(obj!=NULL)free(obj);
|
||||
#define WFALLOC(type,count) (type*)malloc(sizeof(type)*count);
|
||||
#define SAFE_EXEC_WIN32(wfError, recvError, skipLabel, function) recvError=function; if(recvError!=ERROR_SUCCESS) {wfError = WFERROR_WIN32_ERROR;goto skipLabel;}
|
||||
#define SAFE_EXEC_STRALLOC(wfError, skipLabel, vStr, function) vStr=function; if(vStr==NULL) {wfError = WFERROR_ALLOC;goto skipLabel;}
|
||||
#define SAFE_FREE_PTR(obj) if(obj!=NULL){free(obj);obj=NULL;}
|
||||
#define SAFE_FREE_HKEY(hkey) if(hkey!=NULL&&hkey!=INVALID_HANDLE_VALUE){RegCloseKey(hkey);hkey=NULL;}
|
||||
|
||||
// public function implements.
|
||||
|
||||
WFERROR WFInstallApplicationW(WFAPP_PROFILEW* profile) {
|
||||
if (profile->WFVersion != WFVERSION) return WFERROR_INVALID_VERSION;
|
||||
|
||||
return WFERROR_OK;
|
||||
WFERROR error = WFERROR_OK;
|
||||
LSTATUS win32_error;
|
||||
WCHAR* itemSupportedTypes = NULL;
|
||||
|
||||
// generate necessary strings
|
||||
WCHAR* strAppPath = NULL,
|
||||
* strPath = NULL,
|
||||
* strApplications = NULL,
|
||||
* strProgID = NULL,
|
||||
* strOpenWithList = NULL;
|
||||
SAFE_EXEC_STRALLOC(error, final_process,
|
||||
strPath, GetPathFromAppPath_AL(profile->AppPath)
|
||||
);
|
||||
SAFE_EXEC_STRALLOC(error, final_process,
|
||||
strAppPath, Strcat_AL(
|
||||
L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\",
|
||||
GetAppNameFromAppPath_NAL(profile->AppPath)
|
||||
)
|
||||
);
|
||||
SAFE_EXEC_STRALLOC(error, final_process,
|
||||
strProgID, Strcat_AL(
|
||||
L"SOFTWARE\\Classes\\Applications\\",
|
||||
profile->ProgID
|
||||
)
|
||||
);
|
||||
SAFE_EXEC_STRALLOC(error, final_process,
|
||||
strApplications, Strcat_AL(
|
||||
L"SOFTWARE\\Classes\\Applications\\",
|
||||
GetAppNameFromAppPath_NAL(profile->AppPath)
|
||||
)
|
||||
);
|
||||
|
||||
// generate necessary HKEY
|
||||
HKEY nodeAppPath = NULL,
|
||||
nodeApplications = NULL,
|
||||
nodeApplications_Verb = NULL,
|
||||
nodeApplications_SupportedTypes = NULL,
|
||||
nodeProgID = NULL,
|
||||
nodeProgID_Verb = NULL,
|
||||
nodeClasses = NULL,
|
||||
nodeExt = NULL,
|
||||
nodeExt_OpenWithProgIds = NULL,
|
||||
nodeExt_OpenWithList = NULL;
|
||||
|
||||
// register in `App Paths`
|
||||
SAFE_EXEC_WIN32(error, win32_error, final_process,
|
||||
WFRegOpenKeyWithCreation(profile->RegisterForAllUsers ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER, strAppPath, &nodeAppPath)
|
||||
);
|
||||
SAFE_EXEC_WIN32(error, win32_error, final_process,
|
||||
WFRegOpenKeyWithCreation(profile->RegisterForAllUsers ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER, strApplications, &nodeApplications)
|
||||
);
|
||||
SAFE_EXEC_WIN32(error, win32_error, final_process,
|
||||
WFRegOpenKeyWithCreation(nodeApplications, L"shell\\open\\command", &nodeApplications_Verb)
|
||||
);
|
||||
SAFE_EXEC_WIN32(error, win32_error, final_process,
|
||||
WFRegOpenKeyWithCreation(nodeApplications, L"SupportedTypes", &nodeApplications_SupportedTypes)
|
||||
);
|
||||
SAFE_EXEC_WIN32(error, win32_error, final_process,
|
||||
WFRegOpenKeyWithCreation(profile->RegisterForAllUsers ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER, strProgID, &nodeProgID)
|
||||
);
|
||||
SAFE_EXEC_WIN32(error, win32_error, final_process,
|
||||
WFRegOpenKeyWithCreation(nodeProgID, L"shell\\open\\command", &nodeProgID_Verb)
|
||||
);
|
||||
SAFE_EXEC_WIN32(error, win32_error, final_process,
|
||||
WFRegOpenKeyWithCreation(profile->RegisterForAllUsers ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER, L"SOFTWARE\\Classes", &nodeClasses)
|
||||
);
|
||||
|
||||
// operate HKEY
|
||||
SAFE_EXEC_WIN32(error, win32_error, final_process,
|
||||
WFRegSetStringValue(nodeAppPath, NULL, profile->AppPath) // visit Default key
|
||||
);
|
||||
SAFE_EXEC_WIN32(error, win32_error, final_process,
|
||||
WFRegSetStringValue(nodeAppPath, L"Path", strPath)
|
||||
);
|
||||
|
||||
SAFE_EXEC_WIN32(error, win32_error, final_process,
|
||||
WFRegSetStringValue(nodeApplications_Verb, NULL, profile->AppCommand) // visit Default key
|
||||
);
|
||||
|
||||
SAFE_EXEC_WIN32(error, win32_error, final_process,
|
||||
WFRegSetStringValue(nodeProgID_Verb, NULL, profile->AppCommand) // visit Default key
|
||||
);
|
||||
|
||||
|
||||
while ((itemSupportedTypes = IterateSupportedTypesString_NAL(profile->SupportedTypes, itemSupportedTypes)) != NULL) {
|
||||
SAFE_EXEC_WIN32(error, win32_error, final_process,
|
||||
WFRegSetStringValue(nodeApplications_SupportedTypes, itemSupportedTypes, NULL) // register supported type with blank item
|
||||
);
|
||||
|
||||
SAFE_EXEC_WIN32(error, win32_error, final_process,
|
||||
WFRegOpenKeyWithCreation(nodeClasses, itemSupportedTypes, &nodeExt)
|
||||
);
|
||||
if (profile->SetAsDefault) {
|
||||
SAFE_EXEC_WIN32(error, win32_error, final_process,
|
||||
WFRegSetStringValue(nodeExt, NULL, profile->ProgID) // visit Default key
|
||||
);
|
||||
}
|
||||
if (profile->ShowInOpenWithMenu) {
|
||||
if (profile->UseOpenWithList) {
|
||||
// use Windows XP node
|
||||
SAFE_EXEC_STRALLOC(error, final_process,
|
||||
strOpenWithList, Strcat_AL(
|
||||
L"OpenWithList\\",
|
||||
GetAppNameFromAppPath_NAL(profile->AppPath)
|
||||
)
|
||||
);
|
||||
SAFE_EXEC_WIN32(error, win32_error, final_process,
|
||||
WFRegOpenKeyWithCreation(nodeExt, itemSupportedTypes, &nodeExt_OpenWithList);
|
||||
);
|
||||
|
||||
SAFE_FREE_PTR(strOpenWithList);
|
||||
SAFE_FREE_HKEY(nodeExt_OpenWithList);
|
||||
} else {
|
||||
// use Windows Vista node
|
||||
SAFE_EXEC_WIN32(error, win32_error, final_process,
|
||||
WFRegOpenKeyWithCreation(nodeExt, itemSupportedTypes, &nodeExt_OpenWithProgIds);
|
||||
);
|
||||
SAFE_EXEC_WIN32(error, win32_error, final_process,
|
||||
WFRegSetStringValue(nodeExt_OpenWithProgIds, profile->ProgID, NULL)
|
||||
);
|
||||
|
||||
SAFE_FREE_HKEY(nodeExt_OpenWithProgIds);
|
||||
}
|
||||
}
|
||||
SAFE_FREE_HKEY(nodeExt);
|
||||
}
|
||||
|
||||
final_process:
|
||||
// free HKEY and strings
|
||||
SAFE_FREE_HKEY(nodeAppPath);
|
||||
SAFE_FREE_HKEY(nodeApplications);
|
||||
SAFE_FREE_HKEY(nodeApplications_Verb);
|
||||
SAFE_FREE_HKEY(nodeApplications_SupportedTypes);
|
||||
SAFE_FREE_HKEY(nodeProgID);
|
||||
SAFE_FREE_HKEY(nodeProgID_Verb);
|
||||
SAFE_FREE_HKEY(nodeClasses);
|
||||
SAFE_FREE_HKEY(nodeExt);
|
||||
SAFE_FREE_HKEY(nodeExt_OpenWithProgIds);
|
||||
SAFE_FREE_HKEY(nodeExt_OpenWithList);
|
||||
|
||||
SAFE_FREE_PTR(strAppPath);
|
||||
SAFE_FREE_PTR(strPath);
|
||||
SAFE_FREE_PTR(strApplications);
|
||||
SAFE_FREE_PTR(strProgID);
|
||||
|
||||
// order uninstall to wipe out all written data
|
||||
// if function failed
|
||||
if (error != WFERROR_OK)
|
||||
WFUninstallApplicationW(profile);
|
||||
|
||||
// active changes
|
||||
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);
|
||||
|
||||
// return error
|
||||
return error;
|
||||
}
|
||||
|
||||
WFERROR WFInstallApplicationA(WFAPP_PROFILEA* profile) {
|
||||
@ -63,7 +234,7 @@ WFERROR WFGenerateProgIDA(CHAR* vendor, CHAR* component, INT version, CHAR* resu
|
||||
|
||||
// private function and variable implements.
|
||||
|
||||
WCHAR* ConvMultiByteToWideChar(CHAR* source) {
|
||||
WCHAR* ConvMultiByteToWideChar_AL(CHAR* source) {
|
||||
WCHAR* dest = NULL;
|
||||
size_t sourceLength = strlen(source);
|
||||
|
||||
@ -71,7 +242,7 @@ WCHAR* ConvMultiByteToWideChar(CHAR* source) {
|
||||
if (destLength <= 0) return NULL;
|
||||
destLength += 10;
|
||||
|
||||
dest = (WCHAR*)malloc(sizeof(WCHAR) * destLength);
|
||||
dest = WFALLOC(WCHAR, destLength);
|
||||
if (dest == NULL) return NULL;
|
||||
|
||||
memset(dest, 0, sizeof(WCHAR) * destLength);
|
||||
@ -82,4 +253,92 @@ WCHAR* ConvMultiByteToWideChar(CHAR* source) {
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
WCHAR* GetAppNameFromAppPath_NAL(WCHAR* path) {
|
||||
WCHAR* lastSlash = path;
|
||||
while (*path != L'\0') {
|
||||
if (*path == L'\\' || *path == L'/') {
|
||||
lastSlash = path;
|
||||
}
|
||||
path++;
|
||||
}
|
||||
|
||||
return ++lastSlash;
|
||||
}
|
||||
|
||||
WCHAR* GetPathFromAppPath_AL(WCHAR* path) {
|
||||
size_t length = wsclen(path);
|
||||
|
||||
WCHAR* dest = NULL;
|
||||
dest = WFALLOC(WCHAR, length);
|
||||
if (dest == NULL) return NULL;
|
||||
wcscpy(dest, path);
|
||||
|
||||
// get the last slash.
|
||||
// if this path do not contain slash, then lastSlash == dest, the path is not existed, return full path instead.
|
||||
// otherwise, set lastSlash is zero to indicate the end of string
|
||||
WCHAR* lastSlash = GetAppNameFromAppPath(dest);
|
||||
if (lastSlash != dest) {
|
||||
*(lastSlash - 1) = L'\0';
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
WCHAR* Strcat_AL(WCHAR* str1, WCHAR* str2) {
|
||||
size_t length = wcslen(str1) + wcslen(str2) + 10;
|
||||
|
||||
WCHAR* dest = NULL;
|
||||
dest = WFALLOC(WCHAR, length);
|
||||
if (dest == NULL) return NULL;
|
||||
|
||||
wcscpy(dest, str1);
|
||||
wcscat(dest, str2);
|
||||
return dest;
|
||||
}
|
||||
|
||||
WCHAR* IterateSupportedTypesString_NAL(WCHAR* typesString, WCHAR* prev) {
|
||||
if (typesString == NULL || *typesString == L'\0') return NULL;
|
||||
if (prev == NULL) return typesString;
|
||||
|
||||
// skip prev string
|
||||
while (*prev != L'\0') {
|
||||
prev++;
|
||||
}
|
||||
|
||||
// if the next string is start with zero, it mean that the full string is over and return NULL to terminate analyse.
|
||||
// otherwise return next string
|
||||
prev++;
|
||||
if (*prev == L'\0') return NULL;
|
||||
else return prev;
|
||||
}
|
||||
|
||||
void WFPrintflnInDebug() {
|
||||
|
||||
}
|
||||
|
||||
LSTATUS WFRegOpenKeyWithCreation(HKEY hkey, LPCWSTR lpSubKey, PHKEY phkResult) {
|
||||
return RegCreateKeyExW(
|
||||
hkey,
|
||||
lpSubKey,
|
||||
0,
|
||||
NULL,
|
||||
REG_OPTION_NON_VOLATILE,
|
||||
KEY_ALL_ACCESS,
|
||||
NULL,
|
||||
phkResult,
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
LSTATUS WFRegSetStringValue(HKEY hkey, LPCWSTR lpValueName, const WCHAR* data) {
|
||||
return RegSetValueExW(
|
||||
hkey,
|
||||
lpValueName,
|
||||
0,
|
||||
REG_SZ,
|
||||
data,
|
||||
data == NULL ? 0 : ((wcslen(data) + 1) * sizeof(WCHAR))
|
||||
);
|
||||
}
|
@ -6,12 +6,12 @@
|
||||
|
||||
// quick marco for developer and should not be used in wfassoc self
|
||||
|
||||
#ifdef UNICODE
|
||||
#if defined(_UNICODE)
|
||||
#define WFAPP_PROFILE WFAPP_PROFILEW
|
||||
#define WFInstallApplication WFInstallApplicationW
|
||||
#define WFUninstallApplication WFUninstallApplicationW
|
||||
#define WFGenerateProgID WFGenerateProgIDW
|
||||
#else
|
||||
#elif defined(_MBCS)
|
||||
#define WFAPP_PROFILE WFAPP_PROFILEA
|
||||
#define WFInstallApplication WFInstallApplicationA
|
||||
#define WFUninstallApplication WFUninstallApplicationA
|
||||
@ -47,7 +47,10 @@ typedef enum _WFERROR {
|
||||
/// <summary>
|
||||
/// The encoding of string has error.
|
||||
/// </summary>
|
||||
WFERROR_ENCODING = 4
|
||||
WFERROR_ENCODING = 4,
|
||||
WFERROR_WIN32_ERROR = 5,
|
||||
WFERROR_ASSERT_ERROR = 6,
|
||||
WFERROR_ALLOC = 7
|
||||
}WFERROR;
|
||||
|
||||
/// <summary>
|
||||
@ -78,6 +81,10 @@ typedef struct _WFAPP_PROFILEW {
|
||||
/// `.jpg\0.png\0.gif\0`
|
||||
/// </summary>
|
||||
WCHAR* SupportedTypes;
|
||||
BOOL RegisterForAllUsers;
|
||||
BOOL SetAsDefault;
|
||||
BOOL ShowInOpenWithMenu;
|
||||
BOOL UseOpenWithList;
|
||||
}WFAPP_PROFILEW;
|
||||
|
||||
/// <summary>
|
||||
|
Reference in New Issue
Block a user