#include "userwork.h"
#include "FormatError.h"
#include "HandleGuard.h"
#include "AutoArray.h"
#include "scoped_action.h"
#include "Lm.h"
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0500
#include "Sddl.h"
#undef _WIN32_WINNT
#else
#include "Sddl.h"
#endif
#include "Mq.h"
#include <wchar.h>
#define BOOST_BIND_ENABLE_STDCALL
#include "boost/bind.hpp"
namespace utils
{
void GetSidByName(const std::wstring& userName,auto_array<BYTE>* sid)
{
if(userName.size() == 0)
throw std::exception("User name can't be empty.");
std::wstring domainName;
DWORD dwSidBufferSize = 0;
DWORD dwDomainBufferSize = 0;
// Obtain SID and DomainName buffer size by passing NULL to pointer params
SID_NAME_USE eSidType;
LookupAccountNameW(NULL, // Local computer
userName.c_str(),
NULL,
&dwSidBufferSize,
NULL,
&dwDomainBufferSize,
&eSidType);
if(GetLastError() != ERROR_INSUFFICIENT_BUFFER)
throw std::runtime_error("Can't get user sid by name: " + GetLastErrorStr());
// Create buffers for the SID and the domain name.
sid->reset( new BYTE[dwSidBufferSize] );
domainName.resize(dwDomainBufferSize);
// Obtain the SID for the account name passed.
if (!LookupAccountNameW(NULL, // Local computer
userName.c_str(),
(PSID)sid->get(),
&dwSidBufferSize,
(LPWSTR)domainName.c_str(),
&dwDomainBufferSize,
&eSidType))
{
throw std::runtime_error("Can't get user sid by name: " + GetLastErrorStr());
}
if (IsValidSid((PSID)sid->get()) == FALSE)
throw std::exception("LookupAccountName() returned invalid SID");
}
void GetNameBySid(const auto_array<BYTE>& sid,std::wstring* userName)
{
std::wstring domainName;
DWORD dwNameBufferSize = 0;
DWORD dwDomainBufferSize = 0;
// Obtain SID and DomainName buffer size by passing NULL to pointer params
SID_NAME_USE eSidType;
LookupAccountSidW(NULL, // Local computer
(PSID)sid.get(),
NULL,
&dwNameBufferSize,
NULL,
&dwDomainBufferSize,
&eSidType);
if(GetLastError() != ERROR_INSUFFICIENT_BUFFER)
throw std::runtime_error("Can't get user name by SID: " + GetLastErrorStr());
// Create buffers for the name and the domain name.
userName->resize(dwNameBufferSize);
domainName.resize(dwDomainBufferSize);
// Obtain the name for the account SID passed.
if (!LookupAccountSidW(NULL, // Local computer
(PSID)sid.get(),
(LPWSTR)userName->c_str(),
&dwNameBufferSize,
(LPWSTR)domainName.c_str(),
&dwDomainBufferSize,
&eSidType))
{
throw std::runtime_error("Can't get user name by SID: " + GetLastErrorStr());
}
}
void GetUserNames(UserNameSidList* userList)
{
LPUSER_INFO_0 userInfo = NULL;
DWORD dwEntriesRead = 0;
DWORD dwTotalEntries = 0;
DWORD dwResumeHandle = 0;
NET_API_STATUS status;
do
{
status = NetUserEnum(NULL,
0,
FILTER_NORMAL_ACCOUNT, // global users
(LPBYTE*)&userInfo,
MAX_PREFERRED_LENGTH,
&dwEntriesRead,
&dwTotalEntries,
&dwResumeHandle);
if ( (status != NERR_Success) && (status != ERROR_MORE_DATA) )
throw std::runtime_error("Can't enum users: " + GetWinErrorText(status));
NetHandleGuard guard(userInfo);
//
// Loop through the entries.
//
LPUSER_INFO_0 userInfoPtrCopy = userInfo;
for (DWORD i = 0; (i < dwEntriesRead); ++i)
{
std::wstring userName(userInfoPtrCopy->usri0_name);
auto_array<BYTE> sid;
// Retrieve the SID of the user.
GetSidByName(userName,&sid);
LPWSTR sidString;
if( !ConvertSidToStringSidW( (PSID)sid.get(),&sidString) )
throw std::runtime_error("Can't convert SID to string: " + GetLastErrorStr());
LocalHandleGuard guard(sidString);
std::wstring sidStr((wchar_t*)sidString);
userList->push_back(UserNameSidPair(userName,sidStr));
++userInfoPtrCopy;
}
}
while (status == ERROR_MORE_DATA);
}
}//namespace utils