git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@5033 212acab6-be3b-0410-9dea-997c60f758d6
This commit is contained in:
parent
78f805da52
commit
0cb1253452
2 changed files with 133 additions and 94 deletions
|
@ -1,5 +1,7 @@
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include "../ExDLL/exdll.h"
|
#include "../ExDLL/exdll.h"
|
||||||
|
typedef BOOL (WINAPI*CHECKTOKENMEMBERSHIP)(HANDLE TokenHandle,PSID SidToCheck,PBOOL IsMember);
|
||||||
|
CHECKTOKENMEMBERSHIP _CheckTokenMembership=NULL;
|
||||||
|
|
||||||
void __declspec(dllexport) GetName(HWND hwndParent, int string_size,
|
void __declspec(dllexport) GetName(HWND hwndParent, int string_size,
|
||||||
char *variables, stack_t **stacktop)
|
char *variables, stack_t **stacktop)
|
||||||
|
@ -17,102 +19,127 @@ void __declspec(dllexport) GetName(HWND hwndParent, int string_size,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char* GetAccountTypeHelper(BOOL CheckTokenForGroupDeny)
|
||||||
|
{
|
||||||
|
char *group;
|
||||||
|
HANDLE hToken = NULL;
|
||||||
|
struct group
|
||||||
|
{
|
||||||
|
DWORD auth_id;
|
||||||
|
char *name;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct group groups[] =
|
||||||
|
{
|
||||||
|
{DOMAIN_ALIAS_RID_USERS, "User"},
|
||||||
|
// every user belongs to the users group, hence users come before guests
|
||||||
|
{DOMAIN_ALIAS_RID_GUESTS, "Guest"},
|
||||||
|
{DOMAIN_ALIAS_RID_POWER_USERS, "Power"},
|
||||||
|
{DOMAIN_ALIAS_RID_ADMINS, "Admin"}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (GetVersion() & 0x80000000) // Not NT
|
||||||
|
{
|
||||||
|
return "Admin";
|
||||||
|
}
|
||||||
|
|
||||||
|
// First we must open a handle to the access token for this thread.
|
||||||
|
if (OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &hToken) ||
|
||||||
|
OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
|
||||||
|
{
|
||||||
|
SID_IDENTIFIER_AUTHORITY SystemSidAuthority = {SECURITY_NT_AUTHORITY};
|
||||||
|
TOKEN_GROUPS *ptg = NULL;
|
||||||
|
BOOL ValidTokenGroups = FALSE;
|
||||||
|
DWORD cbTokenGroups;
|
||||||
|
DWORD i, j;
|
||||||
|
|
||||||
|
|
||||||
|
if (CheckTokenForGroupDeny)
|
||||||
|
// GetUserName is in advapi32.dll so we can avoid Load/Freelibrary
|
||||||
|
_CheckTokenMembership=
|
||||||
|
(CHECKTOKENMEMBERSHIP) GetProcAddress(
|
||||||
|
GetModuleHandle("ADVAPI32"), "CheckTokenMembership");
|
||||||
|
|
||||||
|
// Use "old school" membership check?
|
||||||
|
if (!CheckTokenForGroupDeny || _CheckTokenMembership == NULL)
|
||||||
|
{
|
||||||
|
// We must query the size of the group information associated with
|
||||||
|
// the token. Note that we expect a FALSE result from GetTokenInformation
|
||||||
|
// because we've given it a NULL buffer. On exit cbTokenGroups will tell
|
||||||
|
// the size of the group information.
|
||||||
|
if (!GetTokenInformation(hToken, TokenGroups, NULL, 0, &cbTokenGroups) &&
|
||||||
|
GetLastError() == ERROR_INSUFFICIENT_BUFFER)
|
||||||
|
{
|
||||||
|
// Allocate buffer and ask for the group information again.
|
||||||
|
// This may fail if an administrator has added this account
|
||||||
|
// to an additional group between our first call to
|
||||||
|
// GetTokenInformation and this one.
|
||||||
|
if ((ptg = GlobalAlloc(GPTR, cbTokenGroups)) &&
|
||||||
|
GetTokenInformation(hToken, TokenGroups, ptg, cbTokenGroups, &cbTokenGroups))
|
||||||
|
{
|
||||||
|
ValidTokenGroups=TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ValidTokenGroups || (CheckTokenForGroupDeny && _CheckTokenMembership))
|
||||||
|
{
|
||||||
|
PSID psid;
|
||||||
|
for (i = 0; i < sizeof(groups)/sizeof(struct group); i++)
|
||||||
|
{
|
||||||
|
// Create a SID for the local group and then check if it exists in our token
|
||||||
|
if (AllocateAndInitializeSid(
|
||||||
|
&SystemSidAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID,
|
||||||
|
groups[i].auth_id, 0, 0, 0, 0, 0, 0,&psid))
|
||||||
|
{
|
||||||
|
BOOL IsMember = FALSE;
|
||||||
|
if (CheckTokenForGroupDeny && _CheckTokenMembership)
|
||||||
|
{
|
||||||
|
_CheckTokenMembership(0, psid, &IsMember);
|
||||||
|
}
|
||||||
|
else if (ValidTokenGroups)
|
||||||
|
{
|
||||||
|
for (j = 0; j < ptg->GroupCount; j++)
|
||||||
|
{
|
||||||
|
if (EqualSid(ptg->Groups[j].Sid, psid))
|
||||||
|
{
|
||||||
|
IsMember = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsMember) group=groups[i].name;
|
||||||
|
FreeSid(psid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ptg)
|
||||||
|
GlobalFree(ptg);
|
||||||
|
CloseHandle(hToken);
|
||||||
|
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
void __declspec(dllexport) GetAccountType(HWND hwndParent, int string_size,
|
void __declspec(dllexport) GetAccountType(HWND hwndParent, int string_size,
|
||||||
char *variables, stack_t **stacktop)
|
char *variables, stack_t **stacktop)
|
||||||
{
|
{
|
||||||
EXDLL_INIT();
|
EXDLL_INIT();
|
||||||
|
pushstring(GetAccountTypeHelper(TRUE));
|
||||||
|
}
|
||||||
|
|
||||||
{
|
void __declspec(dllexport) GetOriginalAccountType(HWND hwndParent, int string_size,
|
||||||
HANDLE hThread;
|
char *variables, stack_t **stacktop)
|
||||||
TOKEN_GROUPS *ptg = NULL;
|
{
|
||||||
DWORD cbTokenGroups;
|
EXDLL_INIT();
|
||||||
DWORD i, j;
|
pushstring(GetAccountTypeHelper(FALSE));
|
||||||
|
|
||||||
SID_IDENTIFIER_AUTHORITY SystemSidAuthority = {SECURITY_NT_AUTHORITY};
|
|
||||||
|
|
||||||
char *group = "";
|
|
||||||
|
|
||||||
if (GetVersion() & 0x80000000) // Not NT
|
|
||||||
{
|
|
||||||
group = "Admin";
|
|
||||||
}
|
|
||||||
|
|
||||||
// First we must open a handle to the access token for this thread.
|
|
||||||
|
|
||||||
else if (OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &hThread) ||
|
|
||||||
OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hThread))
|
|
||||||
{
|
|
||||||
// Then we must query the size of the group information associated with
|
|
||||||
// the token. Note that we expect a FALSE result from GetTokenInformation
|
|
||||||
// because we've given it a NULL buffer. On exit cbTokenGroups will tell
|
|
||||||
// the size of the group information.
|
|
||||||
|
|
||||||
if (!GetTokenInformation (hThread, TokenGroups, NULL, 0, &cbTokenGroups) &&
|
|
||||||
GetLastError() == ERROR_INSUFFICIENT_BUFFER)
|
|
||||||
{
|
|
||||||
|
|
||||||
// Now we allocate a buffer for the group information.
|
|
||||||
// Since _alloca allocates on the stack, we don't have
|
|
||||||
// to explicitly deallocate it. That happens automatically
|
|
||||||
// when we exit this function.
|
|
||||||
|
|
||||||
if ((ptg = GlobalAlloc(GPTR, cbTokenGroups)))
|
|
||||||
{
|
|
||||||
|
|
||||||
// Now we ask for the group information again.
|
|
||||||
// This may fail if an administrator has added this account
|
|
||||||
// to an additional group between our first call to
|
|
||||||
// GetTokenInformation and this one.
|
|
||||||
|
|
||||||
if (GetTokenInformation(hThread, TokenGroups, ptg, cbTokenGroups, &cbTokenGroups))
|
|
||||||
{
|
|
||||||
|
|
||||||
struct group
|
|
||||||
{
|
|
||||||
DWORD auth_id;
|
|
||||||
char *name;
|
|
||||||
} groups[] = {
|
|
||||||
{DOMAIN_ALIAS_RID_USERS, "User"},
|
|
||||||
// every user belongs to the users group, hence users comes before guests
|
|
||||||
{DOMAIN_ALIAS_RID_GUESTS, "Guest"},
|
|
||||||
{DOMAIN_ALIAS_RID_POWER_USERS, "Power"},
|
|
||||||
{DOMAIN_ALIAS_RID_ADMINS, "Admin"}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Finally we'll iterate through the list of groups for this access
|
|
||||||
// token looking for a match against the SID we created above.
|
|
||||||
|
|
||||||
for (i = 0; i < sizeof(groups)/sizeof(struct group); i++)
|
|
||||||
{
|
|
||||||
PSID psid = 0;
|
|
||||||
AllocateAndInitializeSid(
|
|
||||||
&SystemSidAuthority,
|
|
||||||
2,
|
|
||||||
SECURITY_BUILTIN_DOMAIN_RID,
|
|
||||||
groups[i].auth_id,
|
|
||||||
0, 0, 0, 0, 0, 0,
|
|
||||||
&psid
|
|
||||||
);
|
|
||||||
if (psid == 0) continue;
|
|
||||||
for (j = 0; j < ptg->GroupCount; j++)
|
|
||||||
if (EqualSid(ptg->Groups[j].Sid, psid))
|
|
||||||
group = groups[i].name;
|
|
||||||
FreeSid(psid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GlobalFree(ptg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CloseHandle(hThread);
|
|
||||||
}
|
|
||||||
|
|
||||||
pushstring(group);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL WINAPI DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
|
BOOL WINAPI DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
|
||||||
{
|
{
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
Name "UserInfo.dll test"
|
Name "UserInfo.dll test"
|
||||||
OutFile UserInfo.exe
|
OutFile UserInfo.exe
|
||||||
|
|
||||||
|
!define REALMSG "$\nOriginal non-restricted account type: $2"
|
||||||
|
|
||||||
Section
|
Section
|
||||||
ClearErrors
|
ClearErrors
|
||||||
UserInfo::GetName
|
UserInfo::GetName
|
||||||
|
@ -8,17 +10,26 @@ Section
|
||||||
Pop $0
|
Pop $0
|
||||||
UserInfo::GetAccountType
|
UserInfo::GetAccountType
|
||||||
Pop $1
|
Pop $1
|
||||||
|
# GetOriginalAccountType will check the tokens of the original user of the
|
||||||
|
# current thread/process. If the user tokens were elevated or limited for
|
||||||
|
# this process, GetOriginalAccountType will return the non-restricted
|
||||||
|
# account type.
|
||||||
|
# On Vista with UAC, for example, this is not the same value when running
|
||||||
|
# with `RequestExecutionLevel user`. GetOriginalAccountType will return
|
||||||
|
# "admin" while GetAccountType will return "user".
|
||||||
|
UserInfo::GetOriginalAccountType
|
||||||
|
Pop $2
|
||||||
StrCmp $1 "Admin" 0 +3
|
StrCmp $1 "Admin" 0 +3
|
||||||
MessageBox MB_OK 'User "$0" is in the Administrators group'
|
MessageBox MB_OK 'User "$0" is in the Administrators group${REALMSG}'
|
||||||
Goto done
|
Goto done
|
||||||
StrCmp $1 "Power" 0 +3
|
StrCmp $1 "Power" 0 +3
|
||||||
MessageBox MB_OK 'User "$0" is in the Power Users group'
|
MessageBox MB_OK 'User "$0" is in the Power Users group${REALMSG}'
|
||||||
Goto done
|
Goto done
|
||||||
StrCmp $1 "User" 0 +3
|
StrCmp $1 "User" 0 +3
|
||||||
MessageBox MB_OK 'User "$0" is just a regular user'
|
MessageBox MB_OK 'User "$0" is just a regular user${REALMSG}'
|
||||||
Goto done
|
Goto done
|
||||||
StrCmp $1 "Guest" 0 +3
|
StrCmp $1 "Guest" 0 +3
|
||||||
MessageBox MB_OK 'User "$0" is a guest'
|
MessageBox MB_OK 'User "$0" is a guest${REALMSG}'
|
||||||
Goto done
|
Goto done
|
||||||
MessageBox MB_OK "Unknown error"
|
MessageBox MB_OK "Unknown error"
|
||||||
Goto done
|
Goto done
|
||||||
|
@ -29,4 +40,5 @@ Section
|
||||||
MessageBox MB_OK "Error! This DLL can't run under Windows 9x!"
|
MessageBox MB_OK "Error! This DLL can't run under Windows 9x!"
|
||||||
|
|
||||||
done:
|
done:
|
||||||
SectionEnd
|
SectionEnd
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue