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.
\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
\c [/SHORT] user_var(output) path_or_file

View file

@ -12,6 +12,8 @@ Released on ? ?th, 2020
\S2{} Major Changes
\b Added \R{getknownfolderpath}{GetKnownFolderPath}
\S2{} Minor Changes
\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
!endif /* __WIN_WINDOWS__INC */

View file

@ -1390,7 +1390,7 @@ static int NSISCALL ExecuteEntry(entry *entry_)
else if (which==EW_FPUTS)
{
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);
}
#endif
@ -1704,6 +1704,32 @@ static int NSISCALL ExecuteEntry(entry *entry_)
break;
#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
case EW_LOCKWINDOW:
{

View file

@ -193,9 +193,8 @@ enum
// InstTypeGetFlags: 3: [idx, 1, output]
#endif
// instructions not actually implemented in exehead, but used in compiler.
EW_GETLABELADDR, // both of these get converted to EW_ASSIGNVAR
EW_GETFUNCTIONADDR,
EW_GETOSINFO, // 1+ [operation, ...]
EW_RESERVEDOPCODE, // Free slot, feel free to use it for something
#ifdef NSIS_LOCKWINDOW_SUPPORT
EW_LOCKWINDOW,
@ -207,6 +206,10 @@ enum
EW_FGETWS, // FileReadUTF16LE: 4 [handle, output, maxlen, ?getchar:gets]
#endif//NSIS_SUPPORT_FILEFUNCTIONS
#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

View file

@ -771,6 +771,30 @@ TCHAR * NSISCALL mystrcat(TCHAR *out, const TCHAR *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];
const TCHAR SYSREGKEY[] = _T("Software\\Microsoft\\Windows\\CurrentVersion");
@ -1145,6 +1169,7 @@ struct MGA_FUNC MGA_FUNCS[] = {
{"ADVAPI32", "RegDeleteKeyExW"},
#endif
{"ADVAPI32", "InitiateShutdownW"},
{"SHELL32", "SHGetKnownFolderPath"},
{"SHELL32", (CHAR*) 680}, // IsUserAnAdmin
#ifndef _WIN64
{"SHLWAPI", (CHAR*) 437}, // IsOS
@ -1163,6 +1188,7 @@ struct MGA_FUNC MGA_FUNCS[] = {
{"KERNEL32", "GetUserDefaultUILanguage"},
{"ADVAPI32", "RegDeleteKeyExA"},
{"ADVAPI32", "InitiateShutdownA"},
{"SHELL32", "SHGetKnownFolderPath"},
{"SHELL32", (CHAR*) 680}, // IsUserAnAdmin
#ifndef _WIN64
{"SHLWAPI", (CHAR*) 437}, // IsOS
@ -1234,7 +1260,7 @@ void * NSISCALL NSISGetProcAddress(HANDLE dllHandle, TCHAR* funcName)
{
#ifdef _UNICODE
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 NULL;
#else

View file

@ -40,7 +40,20 @@ TCHAR * NSISCALL mystrcpy(TCHAR *out, const TCHAR *in);
int NSISCALL mystrlen(const TCHAR *in);
TCHAR * NSISCALL mystrcat(TCHAR *out, const TCHAR *concat);
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
#define KEY_CREATE_LINK 0x0020
@ -154,6 +167,7 @@ enum myGetProcAddressFunctions {
MGA_RegDeleteKeyEx,
#endif
MGA_InitiateShutdown,
MGA_SHGetKnownFolderPath,
MGA_IsUserAnAdmin,
#ifndef _WIN64
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"));
}
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:
ent.which=EW_SEARCHPATH;
ent.offsets[0]=GetUserVarIndex(line, 1);
@ -4198,6 +4204,7 @@ int CEXEBuild::doCommand(int which_token, LineParser &line)
case TOK_SEARCHPATH:
case TOK_GETTEMPFILENAME:
case TOK_GETFULLPATHNAME:
case TOK_GETKNOWNFOLDERPATH:
ERROR_MSG(_T("Error: %") NPRIs _T(" specified, NSIS_SUPPORT_FNUTIL not defined.\n"), line.gettoken_str(0));
return PS_ERROR;
#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_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_GETKNOWNFOLDERPATH,_T("GetKnownFolderPath"),2,0,_T("$(user_var: result) knownfolderid"),TP_CODE},
{TOK_HIDEWINDOW,_T("HideWindow"),0,0,_T(""),TP_CODE},
{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},

View file

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