From 86864bbd093dbe324a3a3607b956881f8a9f32fb Mon Sep 17 00:00:00 2001 From: yyc12345 Date: Fri, 18 Feb 2022 14:53:49 +0800 Subject: [PATCH] add progId generator and example --- .gitignore | 7 ++ wfassoc.sln | 50 +++++---- wfassoc/wfassoc.c | 42 ++++++++ wfassoc/wfassoc.h | 47 +++++++- wfassoc/wfassoc.vcxproj | 2 + wfassoc_example/main.c | 46 ++++---- wfassoc_example/wfassoc_example.vcxproj | 138 +++++++++++++++++------- 7 files changed, 252 insertions(+), 80 deletions(-) diff --git a/.gitignore b/.gitignore index 426d76d..a332d81 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,10 @@ +# Custom ignore +# ignore build directory +builds/ +Debug_MB/ +Debug_UNICODE/ +Release_UNICODE/ + ## Ignore Visual Studio temporary files, build results, and ## files generated by popular Visual Studio add-ons. ## diff --git a/wfassoc.sln b/wfassoc.sln index 0902b60..2c9c25d 100644 --- a/wfassoc.sln +++ b/wfassoc.sln @@ -9,28 +9,38 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wfassoc_example", "wfassoc_ EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|x64 = Release|x64 - Release|x86 = Release|x86 + Debug_MB|x64 = Debug_MB|x64 + Debug_MB|x86 = Debug_MB|x86 + Debug_UNICODE|x64 = Debug_UNICODE|x64 + Debug_UNICODE|x86 = Debug_UNICODE|x86 + Release_UNICODE|x64 = Release_UNICODE|x64 + Release_UNICODE|x86 = Release_UNICODE|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {4AAC8F0C-3E1C-4584-B682-05BBF96A813F}.Debug|x64.ActiveCfg = Debug|x64 - {4AAC8F0C-3E1C-4584-B682-05BBF96A813F}.Debug|x64.Build.0 = Debug|x64 - {4AAC8F0C-3E1C-4584-B682-05BBF96A813F}.Debug|x86.ActiveCfg = Debug|Win32 - {4AAC8F0C-3E1C-4584-B682-05BBF96A813F}.Debug|x86.Build.0 = Debug|Win32 - {4AAC8F0C-3E1C-4584-B682-05BBF96A813F}.Release|x64.ActiveCfg = Release|x64 - {4AAC8F0C-3E1C-4584-B682-05BBF96A813F}.Release|x64.Build.0 = Release|x64 - {4AAC8F0C-3E1C-4584-B682-05BBF96A813F}.Release|x86.ActiveCfg = Release|Win32 - {4AAC8F0C-3E1C-4584-B682-05BBF96A813F}.Release|x86.Build.0 = Release|Win32 - {AD275AD7-CBD5-41CA-AB24-BB707B3F7534}.Debug|x64.ActiveCfg = Debug|x64 - {AD275AD7-CBD5-41CA-AB24-BB707B3F7534}.Debug|x64.Build.0 = Debug|x64 - {AD275AD7-CBD5-41CA-AB24-BB707B3F7534}.Debug|x86.ActiveCfg = Debug|Win32 - {AD275AD7-CBD5-41CA-AB24-BB707B3F7534}.Debug|x86.Build.0 = Debug|Win32 - {AD275AD7-CBD5-41CA-AB24-BB707B3F7534}.Release|x64.ActiveCfg = Release|x64 - {AD275AD7-CBD5-41CA-AB24-BB707B3F7534}.Release|x64.Build.0 = Release|x64 - {AD275AD7-CBD5-41CA-AB24-BB707B3F7534}.Release|x86.ActiveCfg = Release|Win32 - {AD275AD7-CBD5-41CA-AB24-BB707B3F7534}.Release|x86.Build.0 = Release|Win32 + {4AAC8F0C-3E1C-4584-B682-05BBF96A813F}.Debug_MB|x64.ActiveCfg = Debug|x64 + {4AAC8F0C-3E1C-4584-B682-05BBF96A813F}.Debug_MB|x64.Build.0 = Debug|x64 + {4AAC8F0C-3E1C-4584-B682-05BBF96A813F}.Debug_MB|x86.ActiveCfg = Debug|Win32 + {4AAC8F0C-3E1C-4584-B682-05BBF96A813F}.Debug_MB|x86.Build.0 = Debug|Win32 + {4AAC8F0C-3E1C-4584-B682-05BBF96A813F}.Debug_UNICODE|x64.ActiveCfg = Debug|x64 + {4AAC8F0C-3E1C-4584-B682-05BBF96A813F}.Debug_UNICODE|x64.Build.0 = Debug|x64 + {4AAC8F0C-3E1C-4584-B682-05BBF96A813F}.Debug_UNICODE|x86.ActiveCfg = Debug|Win32 + {4AAC8F0C-3E1C-4584-B682-05BBF96A813F}.Debug_UNICODE|x86.Build.0 = Debug|Win32 + {4AAC8F0C-3E1C-4584-B682-05BBF96A813F}.Release_UNICODE|x64.ActiveCfg = Release|x64 + {4AAC8F0C-3E1C-4584-B682-05BBF96A813F}.Release_UNICODE|x64.Build.0 = Release|x64 + {4AAC8F0C-3E1C-4584-B682-05BBF96A813F}.Release_UNICODE|x86.ActiveCfg = Release|Win32 + {4AAC8F0C-3E1C-4584-B682-05BBF96A813F}.Release_UNICODE|x86.Build.0 = Release|Win32 + {AD275AD7-CBD5-41CA-AB24-BB707B3F7534}.Debug_MB|x64.ActiveCfg = Debug_UNICODE|x64 + {AD275AD7-CBD5-41CA-AB24-BB707B3F7534}.Debug_MB|x64.Build.0 = Debug_UNICODE|x64 + {AD275AD7-CBD5-41CA-AB24-BB707B3F7534}.Debug_MB|x86.ActiveCfg = Debug_MB|Win32 + {AD275AD7-CBD5-41CA-AB24-BB707B3F7534}.Debug_MB|x86.Build.0 = Debug_MB|Win32 + {AD275AD7-CBD5-41CA-AB24-BB707B3F7534}.Debug_UNICODE|x64.ActiveCfg = Debug_UNICODE|x64 + {AD275AD7-CBD5-41CA-AB24-BB707B3F7534}.Debug_UNICODE|x64.Build.0 = Debug_UNICODE|x64 + {AD275AD7-CBD5-41CA-AB24-BB707B3F7534}.Debug_UNICODE|x86.ActiveCfg = Debug_UNICODE|Win32 + {AD275AD7-CBD5-41CA-AB24-BB707B3F7534}.Debug_UNICODE|x86.Build.0 = Debug_UNICODE|Win32 + {AD275AD7-CBD5-41CA-AB24-BB707B3F7534}.Release_UNICODE|x64.ActiveCfg = Release_UNICODE|x64 + {AD275AD7-CBD5-41CA-AB24-BB707B3F7534}.Release_UNICODE|x64.Build.0 = Release_UNICODE|x64 + {AD275AD7-CBD5-41CA-AB24-BB707B3F7534}.Release_UNICODE|x86.ActiveCfg = Release_UNICODE|Win32 + {AD275AD7-CBD5-41CA-AB24-BB707B3F7534}.Release_UNICODE|x86.Build.0 = Release_UNICODE|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/wfassoc/wfassoc.c b/wfassoc/wfassoc.c index d625d2a..46007a3 100644 --- a/wfassoc/wfassoc.c +++ b/wfassoc/wfassoc.c @@ -1,10 +1,26 @@ #include "wfassoc.h" #include +// private function and variable declearions. + +/// +/// Convert multi byte string to wide char string +/// Notice: this function will allocate memory for returns and it should be released safely. +/// +/// The string will be converted +/// The error happend during converting +/// The string has been converted. If return NULL, it mean that the converting failed. +WCHAR* ConvMultiByteToWideChar(CHAR* source); + #define LEGACY_PROGID_FORMATA "%s.%s.%d" #define LEGACY_PROGID_FORMATW L"%s.%s.%d" +#define SAFE_FREE(obj) if(obj!=NULL)free(obj); + +// public function implements. WFERROR WFInstallApplicationW(WFAPP_PROFILEW* profile) { + if (profile->WFVersion != WFVERSION) return WFERROR_INVALID_VERSION; + return WFERROR_OK; } @@ -13,6 +29,8 @@ WFERROR WFInstallApplicationA(WFAPP_PROFILEA* profile) { } WFERROR WFUninstallApplicationW(WFAPP_PROFILEW* profile) { + if (profile->WFVersion != WFVERSION) return WFERROR_INVALID_VERSION; + return WFERROR_OK; } @@ -41,3 +59,27 @@ WFERROR WFGenerateProgIDA(CHAR* vendor, CHAR* component, INT version, CHAR* resu } return WFERROR_OK; } + + +// private function and variable implements. + +WCHAR* ConvMultiByteToWideChar(CHAR* source) { + WCHAR* dest = NULL; + size_t sourceLength = strlen(source); + + int destLength = MultiByteToWideChar(CP_ACP, 0, source, sourceLength, NULL, 0); + if (destLength <= 0) return NULL; + destLength += 10; + + dest = (WCHAR*)malloc(sizeof(WCHAR) * destLength); + if (dest == NULL) return NULL; + + memset(dest, 0, sizeof(WCHAR) * destLength); + int error = MultiByteToWideChar(CP_ACP, 0, source, sourceLength, dest, destLength); + if (error <= 0) { + free(dest); + return NULL; + } + + return dest; +} \ No newline at end of file diff --git a/wfassoc/wfassoc.h b/wfassoc/wfassoc.h index 223ec39..fe7056c 100644 --- a/wfassoc/wfassoc.h +++ b/wfassoc/wfassoc.h @@ -4,6 +4,22 @@ #include #include +// quick marco for developer and should not be used in wfassoc self + +#ifdef UNICODE +#define WFAPP_PROFILE WFAPP_PROFILEW +#define WFInstallApplication WFInstallApplicationW +#define WFUninstallApplication WFUninstallApplicationW +#define WFGenerateProgID WFGenerateProgIDW +#else +#define WFAPP_PROFILE WFAPP_PROFILEA +#define WFInstallApplication WFInstallApplicationA +#define WFUninstallApplication WFUninstallApplicationA +#define WFGenerateProgID WFGenerateProgIDA +#endif + +// useful macro + #define WFVERSION 0 #define WFSUCCESS(expr) (!expr) #define WFFAILED(expr) expr @@ -25,9 +41,13 @@ typedef enum _WFERROR { /// WFERROR_INSUFFICIENT_BUFFER = 2, /// - /// Some essential pointer variable is NULL + /// Some essential pointer variable is NULL. /// - WFERROR_NULLPTR = 3 + WFERROR_NULLPTR = 3, + /// + /// The encoding of string has error. + /// + WFERROR_ENCODING = 4 }WFERROR; /// @@ -64,8 +84,29 @@ typedef struct _WFAPP_PROFILEW { /// wfassoc Narrow Character Set Profile Struct /// typedef struct _WFAPP_PROFILEA { + /// + /// wfassoc version. Fill it with `WFVERSION` in your application. This field is used for version checking. + /// INT WFVersion; - CHAR* ApplicationName; + /// + /// The path to locate your application. + /// + CHAR* AppPath; + /// + /// The command will be executed when opening files. + /// + CHAR* AppCommand; + /// + /// Your application's ProgID. + /// For more detail about how to create your ProgID, please browse: https://docs.microsoft.com/en-us/windows/win32/shell/fa-progids + /// We also provide a generator for creating legacy ProgID. Use `WFGenerateProgID` to create a legacy ProgID. + /// + CHAR* ProgID; + /// + /// Your application supported file extensions. + /// The structure of this field is connecting all supported extensions with dot(.) end to end. For example: + /// `.jpg\0.png\0.gif\0` + /// CHAR* SupportedTypes; }WFAPP_PROFILEA; diff --git a/wfassoc/wfassoc.vcxproj b/wfassoc/wfassoc.vcxproj index add0e66..8ac720e 100644 --- a/wfassoc/wfassoc.vcxproj +++ b/wfassoc/wfassoc.vcxproj @@ -72,9 +72,11 @@ true + $(SolutionDir)builds\Debug\ false + $(SolutionDir)builds\Release\ true diff --git a/wfassoc_example/main.c b/wfassoc_example/main.c index 89612c0..b62d0a3 100644 --- a/wfassoc_example/main.c +++ b/wfassoc_example/main.c @@ -1,25 +1,33 @@ #include "../wfassoc/wfassoc.h" #include +#include #define COMMAND_MAX_LENGTH 128 -WFAPP_PROFILEW* create_profile(); -WCHAR* create_progId(); -void* free_profile(WFAPP_PROFILEW* profile); +WFAPP_PROFILE* create_profile(); +TCHAR* create_progId(); +void free_profile(WFAPP_PROFILE* profile); int main(int argc, char* args[]) { + // alloc application profile + WFAPP_PROFILE* profile = create_profile(); + if (profile == NULL) { + puts("Error: Fail to allocating profile structure.\n"); + return 1; + } + // alloc input string and check it char* input_str = malloc(sizeof(char) * (COMMAND_MAX_LENGTH + 1)); if (input_str == NULL) return; - + // accept input while (TRUE) { gets_s(input_str, COMMAND_MAX_LENGTH); if (!strcmp(input_str, "install")) { - + _tprintf(TEXT("%s\n"), profile->ProgID); } else if (!strcmp(input_str, "uninstall")) { - + _tprintf(TEXT("%s\n"), profile->ProgID); } else if (!strcmp(input_str, "quit")) { break; } @@ -27,17 +35,18 @@ int main(int argc, char* args[]) { //free input string free(input_str); + return 0; } -WFAPP_PROFILEW* create_profile() { - WFAPP_PROFILEW* profile = (WFAPP_PROFILEW*)malloc(sizeof(WFAPP_PROFILEW)); +WFAPP_PROFILE* create_profile() { + WFAPP_PROFILE* profile = (WFAPP_PROFILE*)malloc(sizeof(WFAPP_PROFILE)); if (profile == NULL) return NULL; - memset(profile, 0, sizeof(WFAPP_PROFILEW)); + memset(profile, 0, sizeof(WFAPP_PROFILE)); profile->WFVersion = WFVERSION; - profile->AppPath = L""; - profile->AppCommand = L""; - profile->SupportedTypes = L".png\0.jpg\0"; + profile->AppPath = TEXT("E:\\pineapple-picture\\ppic.exe"); + profile->AppCommand = TEXT("E:\\pineapple-picture\\ppic.exe \"%1\""); + profile->SupportedTypes = TEXT(".png\0.jpg\0"); profile->ProgID = create_progId(); if (profile->ProgID == NULL) { free_profile(profile); @@ -47,17 +56,18 @@ WFAPP_PROFILEW* create_profile() { return profile; } -wchar_t* create_progId() { - WCHAR* progid; +TCHAR* create_progId() { + TCHAR* progid = NULL; int progIdSize; - if (WFFAILED(WFGenerateProgIDW(L"PineapplePicture", L"Image", 0, NULL, &progIdSize))) { + if (WFFAILED(WFGenerateProgID(TEXT("PineapplePicture"), TEXT("Image"), 0, NULL, &progIdSize))) { return NULL; } - progid = (WCHAR*)malloc(sizeof(WCHAR) * progIdSize); + progid = (TCHAR*)malloc(sizeof(TCHAR) * progIdSize); if (progid == NULL) return NULL; + memset(progid, 0, sizeof(TCHAR) * progIdSize); - if (WFFAILED(WFGenerateProgIDW(L"PineapplePicture", L"Image", 0, NULL, &progIdSize))) { + if (WFFAILED(WFGenerateProgID(TEXT("PineapplePicture"), TEXT("Image"), 0, progid, &progIdSize))) { free(progid); return NULL; } @@ -65,7 +75,7 @@ wchar_t* create_progId() { return progid; } -void* free_profile(WFAPP_PROFILEW* profile) { +void free_profile(WFAPP_PROFILE* profile) { if (profile->ProgID != NULL) free(profile->ProgID); free(profile); } diff --git a/wfassoc_example/wfassoc_example.vcxproj b/wfassoc_example/wfassoc_example.vcxproj index f8e05e8..d955c82 100644 --- a/wfassoc_example/wfassoc_example.vcxproj +++ b/wfassoc_example/wfassoc_example.vcxproj @@ -1,20 +1,28 @@ - - Debug + + Debug_MB Win32 - - Release - Win32 - - - Debug + + Debug_MB x64 - - Release + + Debug_UNICODE + Win32 + + + Release_UNICODE + Win32 + + + Debug_UNICODE + x64 + + + Release_UNICODE x64 @@ -26,26 +34,38 @@ 10.0 - - Application - true - v142 - NotSet - - - Application - false - v142 - true - NotSet - - + Application true v142 Unicode - + + Application + true + v142 + MultiByte + + + Application + false + v142 + true + Unicode + + + Application + true + v142 + Unicode + + + Application + true + v142 + Unicode + + Application false v142 @@ -57,32 +77,47 @@ - + - + - + - + + + + + + + - + + true + $(SolutionDir)builds\Debug\ + + + true + $(SolutionDir)builds\Debug\ + + + false + $(SolutionDir)builds\Release\ + + true - - false - - + true - + false - + Level3 true @@ -95,7 +130,20 @@ true - + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + CompileAsC + + + Console + true + + + Level3 true @@ -112,7 +160,7 @@ true - + Level3 true @@ -124,7 +172,19 @@ true - + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + Level3 true