Added GetKnownFolderPath

git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@7154 212acab6-be3b-0410-9dea-997c60f758d6
This commit is contained in:
anders_k 2020-03-12 23:43:51 +00:00
parent 1f355d992c
commit 68db5f04ee
10 changed files with 128 additions and 5 deletions

View file

@ -81,6 +81,17 @@ Gets the last write time of "filename". Sets the user output variables with the
This is similar to \R{getfiletime}{GetFileTime}, only it acts on the system building the installer (it actually compiles into two \R{StrCpy}{StrCpy} commands). Sets the two output variables with the file timestamp of the file on the build system. This is similar to \R{getfiletime}{GetFileTime}, only it acts on the system building the installer (it actually compiles into two \R{StrCpy}{StrCpy} commands). Sets the two output variables with the file timestamp of the file on the build system.
\S2{getknownfolderpath} GetKnownFolderPath
\c user_var(output) knownfolderid
Get the path of a \W{https://docs.microsoft.com/en-us/windows/win32/shell/knownfolderid}{known folder}. The error flag is set and the output variable is empty if the call fails or the knownfolderid guid is not available. This function is only able to resolve known folders Windows Vista or higher.
\c !include WinCore.nsh
\c GetKnownFolderPath $InstDir ${FOLDERID_UserProgramFiles}
\c StrCmp $InstDir "" 0 +2
\c StrCpy $InstDir "$LocalAppData\Programs"
\S2{getfullpathname} GetFullPathName \S2{getfullpathname} GetFullPathName
\c [/SHORT] user_var(output) path_or_file \c [/SHORT] user_var(output) path_or_file

View file

@ -12,6 +12,8 @@ Released on ? ?th, 2020
\S2{} Major Changes \S2{} Major Changes
\b Added \R{getknownfolderpath}{GetKnownFolderPath}
\S2{} Minor Changes \S2{} Minor Changes
\b Added \R{ifshellvarcontextall}{IfShellVarContextAll} and \R{ifrtllanguage}{IfRtlLanguage} \b Added \R{ifshellvarcontextall}{IfShellVarContextAll} and \R{ifrtllanguage}{IfRtlLanguage}

View file

@ -227,5 +227,37 @@ Shobjidl.h
/**************************************************
ShlGuid.h
**************************************************/
!ifndef __WIN_NOINC_SHLGUID
!define FOLDERID_Public {DFDF76A2-C82A-4D63-906A-5644AC457385} ; Vista+ Fixed=%SystemDrive%\Users\Public
!define FOLDERID_Games {CAC52C1A-B53D-4edc-92D7-6B2E8AC19434} ; Vista+ && < 10 (1803) Virtual
!define FOLDERID_SavedGames {4C5C32FF-BB9D-43b0-B5B4-2D72E54EAAA4} ; Vista+ PerUser=%USERPROFILE%\Saved Games
!define FOLDERID_GameTasks {054FAE61-4DD8-4787-80B6-090220C4B700} ; Vista+ PerUser=%LOCALAPPDATA%\Microsoft\Windows\GameExplorer
!define FOLDERID_PublicGameTasks {DEBF2536-E1A8-4c59-B6A2-414586476AEA} ; Vista+ Common=%ALLUSERSPROFILE%\Microsoft\Windows\GameExplorer
!define FOLDERID_Contacts {56784854-C6CB-462b-8169-88E350ACB882} ; Vista+ PerUser=%USERPROFILE%\Contacts
!define FOLDERID_Downloads {374DE290-123F-4565-9164-39C4925E467B} ; Vista+ PerUser=%USERPROFILE%\Downloads
!define FOLDERID_PublicDownloads {3D644C9B-1FB8-4f30-9B45-F670235F79C0} ; Vista+ Common=%PUBLIC%\Downloads
!define FOLDERID_UserProfiles {0762D272-C50A-4BB0-A382-697DCD729B80} ; Vista+ Fixed=%SystemDrive%\Users
!define FOLDERID_UserProgramFiles {5CD7AEE2-2219-4A67-B85D-6C9CE15660CB} ; 7+ PerUser=%LOCALAPPDATA%\Programs
!define FOLDERID_UserProgramFilesCommon {BCBD3057-CA5C-4622-B42D-BC56DB0AE516} ; 7+ PerUser=%LOCALAPPDATA%\Programs\Common
!define FOLDERID_PublicLibraries {48DAF80B-E6CF-4F4E-B800-0E69D84EE384} ; 7+ Common=%ALLUSERSPROFILE%\Microsoft\Windows\Libraries
!define FOLDERID_UserPinned {9E3995AB-1F9C-4F13-B827-48B24B6C7174} ; 7+ PerUser=%APPDATA%\Microsoft\Internet Explorer\Quick Launch\User Pinned
!define FOLDERID_ImplicitAppShortcuts {BCB5256F-79F6-4CEE-B725-DC34E402FD46} ; 7+ PerUser=%APPDATA%\Microsoft\Internet Explorer\Quick Launch\User Pinned\ImplicitAppShortcuts
!define FOLDERID_DeviceMetadataStore {5CE4A5E9-E4EB-479D-B89F-130C02886155} ; 7+ Common=%ALLUSERSPROFILE%\Microsoft\Windows\DeviceMetadataStore
!define FOLDERID_ApplicationShortcuts {A3918781-E5F2-4890-B3D9-A7E54332328C} ; 8.0+ PerUser=%LOCALAPPDATA%\Microsoft\Windows\Application Shortcuts
!define FOLDERID_RoamingTiles {00BCFC5A-ED94-4e48-96A1-3F6217F21990} ; 8.0+ PerUser=%LOCALAPPDATA%\Microsoft\Windows\RoamingTiles
!define FOLDERID_RoamedTileImages {AAA8D5A5-F1D6-4259-BAA8-78E7EF60835E} ; 8.0+ PerUser=%LOCALAPPDATA%\Microsoft\Windows\RoamedTileImages
!define FOLDERID_PublicUserTiles {0482af6c-08f1-4c34-8c90-e17ec98b1e17} ; 8.0+ Common=%PUBLIC%\AccountPictures
!define FOLDERID_AccountPictures {008ca0b1-55b4-4c56-b8a8-4de4b299d3be} ; 8.0+ PerUser=%APPDATA%\Microsoft\Windows\AccountPictures
!define FOLDERID_Screenshots {b7bede81-df94-4682-a7d8-57a52620b86f} ; 8.0+ PerUser=%USERPROFILE%\Pictures\Screenshots
!define FOLDERID_SkyDrive {A52BBA46-E9E1-435f-B3D9-28DAA648C0F6} ; 8.1+ PerUser=%USERPROFILE%\OneDrive
!define FOLDERID_AppDataProgramData {559D40A3-A036-40FA-AF61-84CB430A4D34} ; 10 (1709)+ PerUser=%LOCALAPPDATA%\ProgramData
!endif /* __WIN_NOINC_SHLGUID */
!verbose pop !verbose pop
!endif /* __WIN_WINDOWS__INC */ !endif /* __WIN_WINDOWS__INC */

View file

@ -1390,7 +1390,7 @@ static int NSISCALL ExecuteEntry(entry *entry_)
else if (which==EW_FPUTS) else if (which==EW_FPUTS)
{ {
GetStringFromParm(0x21); // load string in buf2, convert it to ANSI in buf1 GetStringFromParm(0x21); // load string in buf2, convert it to ANSI in buf1
WideCharToMultiByte(CP_ACP, 0, buf2, -1, (LPSTR) buf1, NSIS_MAX_STRLEN, NULL, NULL); StrWideToACP(buf2, (LPSTR) buf1, NSIS_MAX_STRLEN);
l=lstrlenA((LPCSTR)buf1); l=lstrlenA((LPCSTR)buf1);
} }
#endif #endif
@ -1704,6 +1704,32 @@ static int NSISCALL ExecuteEntry(entry *entry_)
break; break;
#endif//NSIS_CONFIG_COMPONENTPAGE #endif//NSIS_CONFIG_COMPONENTPAGE
case EW_GETOSINFO:
{
//switch(parm0)
{
#ifdef NSIS_SUPPORT_FNUTIL
//case 0:
{
TCHAR *outstr = var1;
IID kfid;
HRESULT(WINAPI*SHGKFP)(REFIID,DWORD,HANDLE,PWSTR*) = (HRESULT(WINAPI*)(REFIID,DWORD,HANDLE,PWSTR*)) myGetProcAddress(MGA_SHGetKnownFolderPath);
TCHAR *buf2 = GetStringFromParm(0x22), succ = FALSE;
if (SHGKFP && SUCCEEDED(ComIIDFromString(buf2, &kfid)))
{
PWSTR path;
HRESULT hr = SHGKFP(&kfid, parm3, NULL, &path);
if (SUCCEEDED(hr))
strcpyWideToT(outstr, path), CoTaskMemFree(path), ++succ;
}
if (!succ)
exec_error++, *outstr = _T('\0');
}
//break;
#endif
}
}
break;
#ifdef NSIS_LOCKWINDOW_SUPPORT #ifdef NSIS_LOCKWINDOW_SUPPORT
case EW_LOCKWINDOW: case EW_LOCKWINDOW:
{ {

View file

@ -193,9 +193,8 @@ enum
// InstTypeGetFlags: 3: [idx, 1, output] // InstTypeGetFlags: 3: [idx, 1, output]
#endif #endif
// instructions not actually implemented in exehead, but used in compiler. EW_GETOSINFO, // 1+ [operation, ...]
EW_GETLABELADDR, // both of these get converted to EW_ASSIGNVAR EW_RESERVEDOPCODE, // Free slot, feel free to use it for something
EW_GETFUNCTIONADDR,
#ifdef NSIS_LOCKWINDOW_SUPPORT #ifdef NSIS_LOCKWINDOW_SUPPORT
EW_LOCKWINDOW, EW_LOCKWINDOW,
@ -207,6 +206,10 @@ enum
EW_FGETWS, // FileReadUTF16LE: 4 [handle, output, maxlen, ?getchar:gets] EW_FGETWS, // FileReadUTF16LE: 4 [handle, output, maxlen, ?getchar:gets]
#endif//NSIS_SUPPORT_FILEFUNCTIONS #endif//NSIS_SUPPORT_FILEFUNCTIONS
#endif #endif
// Opcodes listed here are not actually used in exehead. No exehead opcodes should be present after these!
EW_GETLABELADDR, // --> EW_ASSIGNVAR
EW_GETFUNCTIONADDR, // --> EW_ASSIGNVAR
}; };
#pragma pack(push, 1) // fileform.cpp assumes no padding/alignment #pragma pack(push, 1) // fileform.cpp assumes no padding/alignment

View file

@ -771,6 +771,30 @@ TCHAR * NSISCALL mystrcat(TCHAR *out, const TCHAR *concat)
return lstrcat(out, concat); return lstrcat(out, concat);
} }
int StrWideToACP(LPCWSTR Src, char* Dst, int DstCap)
{
return WideCharToMultiByte(CP_ACP, 0, Src, -1, Dst, DstCap, NULL, NULL);
}
#ifndef UNICODE
void strcpyWideToT(TCHAR *out, LPCWSTR in)
{
StrWideToACP(in, out, NSIS_MAX_STRLEN);
}
#endif
#if !defined(_WIN64) && !defined(UNICODE)
HRESULT ComIIDFromString(LPCTSTR str, IID*out)
{
WCHAR buf[130];
signed char i;
for (i = 0; i >= 0; ++i)
if (!(buf[i] = str[i]))
return IIDFromString(buf, out);
return E_FAIL;
}
#endif
TCHAR ps_tmpbuf[NSIS_MAX_STRLEN*2]; TCHAR ps_tmpbuf[NSIS_MAX_STRLEN*2];
const TCHAR SYSREGKEY[] = _T("Software\\Microsoft\\Windows\\CurrentVersion"); const TCHAR SYSREGKEY[] = _T("Software\\Microsoft\\Windows\\CurrentVersion");
@ -1145,6 +1169,7 @@ struct MGA_FUNC MGA_FUNCS[] = {
{"ADVAPI32", "RegDeleteKeyExW"}, {"ADVAPI32", "RegDeleteKeyExW"},
#endif #endif
{"ADVAPI32", "InitiateShutdownW"}, {"ADVAPI32", "InitiateShutdownW"},
{"SHELL32", "SHGetKnownFolderPath"},
{"SHELL32", (CHAR*) 680}, // IsUserAnAdmin {"SHELL32", (CHAR*) 680}, // IsUserAnAdmin
#ifndef _WIN64 #ifndef _WIN64
{"SHLWAPI", (CHAR*) 437}, // IsOS {"SHLWAPI", (CHAR*) 437}, // IsOS
@ -1163,6 +1188,7 @@ struct MGA_FUNC MGA_FUNCS[] = {
{"KERNEL32", "GetUserDefaultUILanguage"}, {"KERNEL32", "GetUserDefaultUILanguage"},
{"ADVAPI32", "RegDeleteKeyExA"}, {"ADVAPI32", "RegDeleteKeyExA"},
{"ADVAPI32", "InitiateShutdownA"}, {"ADVAPI32", "InitiateShutdownA"},
{"SHELL32", "SHGetKnownFolderPath"},
{"SHELL32", (CHAR*) 680}, // IsUserAnAdmin {"SHELL32", (CHAR*) 680}, // IsUserAnAdmin
#ifndef _WIN64 #ifndef _WIN64
{"SHLWAPI", (CHAR*) 437}, // IsOS {"SHLWAPI", (CHAR*) 437}, // IsOS
@ -1234,7 +1260,7 @@ void * NSISCALL NSISGetProcAddress(HANDLE dllHandle, TCHAR* funcName)
{ {
#ifdef _UNICODE #ifdef _UNICODE
char ansiName[256]; char ansiName[256];
if (WideCharToMultiByte(CP_ACP, 0, funcName, -1, ansiName, 256, NULL, NULL) != 0) if (StrWideToACP(funcName, ansiName, 256) != 0)
return GetProcAddress(dllHandle, ansiName); return GetProcAddress(dllHandle, ansiName);
return NULL; return NULL;
#else #else

View file

@ -40,7 +40,20 @@ TCHAR * NSISCALL mystrcpy(TCHAR *out, const TCHAR *in);
int NSISCALL mystrlen(const TCHAR *in); int NSISCALL mystrlen(const TCHAR *in);
TCHAR * NSISCALL mystrcat(TCHAR *out, const TCHAR *concat); TCHAR * NSISCALL mystrcat(TCHAR *out, const TCHAR *concat);
TCHAR * NSISCALL mystrstr(TCHAR *a, TCHAR *b); TCHAR * NSISCALL mystrstr(TCHAR *a, TCHAR *b);
int StrWideToACP(LPCWSTR Src, char* Dst, int DstCap);
#ifdef UNICODE
#define strcpyWideToT mystrcpy
#else
void strcpyWideToT(TCHAR *out, LPCWSTR in);
#endif
#ifdef _WIN64
#define ComIIDFromString(s,out) SHCLSIDFromString((s),(CLSID*)(out))
#elif defined(UNICODE)
#define ComIIDFromString(s,out) IIDFromString((s), (IID*)(out))
#else
HRESULT ComIIDFromString(LPCTSTR str, IID*out);
#endif
#ifndef KEY_CREATE_LINK #ifndef KEY_CREATE_LINK
#define KEY_CREATE_LINK 0x0020 #define KEY_CREATE_LINK 0x0020
@ -154,6 +167,7 @@ enum myGetProcAddressFunctions {
MGA_RegDeleteKeyEx, MGA_RegDeleteKeyEx,
#endif #endif
MGA_InitiateShutdown, MGA_InitiateShutdown,
MGA_SHGetKnownFolderPath,
MGA_IsUserAnAdmin, MGA_IsUserAnAdmin,
#ifndef _WIN64 #ifndef _WIN64
MGA_IsOS, MGA_IsOS,

View file

@ -4187,6 +4187,12 @@ int CEXEBuild::doCommand(int which_token, LineParser &line)
line.gettoken_str(2+a),line.gettoken_str(1+a),a?_T("sfn"):_T("lfn")); line.gettoken_str(2+a),line.gettoken_str(1+a),a?_T("sfn"):_T("lfn"));
} }
return add_entry(&ent); return add_entry(&ent);
case TOK_GETKNOWNFOLDERPATH:
ent.which=EW_GETOSINFO;
ent.offsets[0]=0; // Operation
ent.offsets[1]=GetUserVarIndex(line, 1);
ent.offsets[2]=add_string(line.gettoken_str(2));
return add_entry(&ent);
case TOK_SEARCHPATH: case TOK_SEARCHPATH:
ent.which=EW_SEARCHPATH; ent.which=EW_SEARCHPATH;
ent.offsets[0]=GetUserVarIndex(line, 1); ent.offsets[0]=GetUserVarIndex(line, 1);
@ -4198,6 +4204,7 @@ int CEXEBuild::doCommand(int which_token, LineParser &line)
case TOK_SEARCHPATH: case TOK_SEARCHPATH:
case TOK_GETTEMPFILENAME: case TOK_GETTEMPFILENAME:
case TOK_GETFULLPATHNAME: case TOK_GETFULLPATHNAME:
case TOK_GETKNOWNFOLDERPATH:
ERROR_MSG(_T("Error: %") NPRIs _T(" specified, NSIS_SUPPORT_FNUTIL not defined.\n"), line.gettoken_str(0)); ERROR_MSG(_T("Error: %") NPRIs _T(" specified, NSIS_SUPPORT_FNUTIL not defined.\n"), line.gettoken_str(0));
return PS_ERROR; return PS_ERROR;
#endif //~ NSIS_SUPPORT_FNUTIL #endif //~ NSIS_SUPPORT_FNUTIL

View file

@ -110,6 +110,7 @@ static tokenType tokenlist[TOK__LAST] =
{TOK_GETDLGITEM,_T("GetDlgItem"),3,0,_T("$(user_var: handle output) dialog item_id"),TP_CODE}, {TOK_GETDLGITEM,_T("GetDlgItem"),3,0,_T("$(user_var: handle output) dialog item_id"),TP_CODE},
{TOK_GETFULLPATHNAME,_T("GetFullPathName"),2,1,_T("[/SHORT] $(user_var: result) path_or_file"),TP_CODE}, {TOK_GETFULLPATHNAME,_T("GetFullPathName"),2,1,_T("[/SHORT] $(user_var: result) path_or_file"),TP_CODE},
{TOK_GETTEMPFILENAME,_T("GetTempFileName"),1,1,_T("$(user_var: name output) [base_dir]"),TP_CODE}, {TOK_GETTEMPFILENAME,_T("GetTempFileName"),1,1,_T("$(user_var: name output) [base_dir]"),TP_CODE},
{TOK_GETKNOWNFOLDERPATH,_T("GetKnownFolderPath"),2,0,_T("$(user_var: result) knownfolderid"),TP_CODE},
{TOK_HIDEWINDOW,_T("HideWindow"),0,0,_T(""),TP_CODE}, {TOK_HIDEWINDOW,_T("HideWindow"),0,0,_T(""),TP_CODE},
{TOK_ICON,_T("Icon"),1,0,_T("local_icon.ico"),TP_GLOBAL}, {TOK_ICON,_T("Icon"),1,0,_T("local_icon.ico"),TP_GLOBAL},
{TOK_IFABORT,_T("IfAbort"),1,1,_T("label_to_goto_if_abort [label_to_goto_if_no_abort]"),TP_CODE}, {TOK_IFABORT,_T("IfAbort"),1,1,_T("label_to_goto_if_abort [label_to_goto_if_no_abort]"),TP_CODE},

View file

@ -280,6 +280,7 @@ enum
#endif #endif
TOK_FILESEEK, TOK_FILESEEK,
TOK_GETFULLPATHNAME, TOK_GETFULLPATHNAME,
TOK_GETKNOWNFOLDERPATH,
TOK_REBOOT, TOK_REBOOT,
TOK_IFREBOOTFLAG, TOK_IFREBOOTFLAG,
TOK_SETREBOOTFLAG, TOK_SETREBOOTFLAG,