Jump to content


This is a ready-only archive of the InstallSite Forum. You cannot post any new content here. / Dies ist ein Archiv des InstallSite Forums. Hier können keine neuen Beiträge veröffentlicht werden.
Photo

Guest account name


11 replies to this topic

Pizzero

Pizzero
  • Full Members
  • 22 posts

Posted 05 December 2007 - 11:09

Hello,

I would like to activate the guest account during my install ("net user guest /active:on") and I want to work this command in any language, as the guest account changes in localized OSs.

I already looked at the SIDLookup package, which would be the right tool, but unfortunately it doesnt have a [SID_GUEST]... :-(

(BTW, in the Security Policy (secpol.msc) under "local security options" the name can be found localized: "Accounts: Rename guest account".)

How could I get a localized string for the guest account user name (e.g. Invitado, Invité, Gast, ...) in a simple way?

Thank you in advance!

VBScab

VBScab
  • Full Members
  • 436 posts

Posted 05 December 2007 - 11:36

I don't know for sure but there has to be a way to do that with ADSI or WMI. There are a gazillion scripts here. Bear in mind that they're designed for stand-alone running and may need editing for use in a CA (removing any WScript directives, for example).
- Don't know why 'x' happened? Want to know why 'y' happened? ProcMon will tell you.
- Try using http://www.google.com before posting.
- I answer questions only via forums. Please appreciate the time I give here and don't send me personal emails.

Pizzero

Pizzero
  • Full Members
  • 22 posts

Posted 05 December 2007 - 13:39

Thanks VBScab - but scripts are not, what I'm looking for. There are a lot of posts in the forum related to what technologies could and should be used in what circumstances, and in my case I have designed my installations from scratch to never use scripts - and I would not like to change that...

Well-known OS resources (exe, registry, ...) and any DLL would be okay.

VBScab

VBScab
  • Full Members
  • 436 posts

Posted 06 December 2007 - 19:51

Best of luck with THAT, then. There's probably a function in the Windows API to do that but I'm trying VERY hard to think what the difference would be between getting that functionality into your MSI and using a script, other than adding months to your delivery time...
- Don't know why 'x' happened? Want to know why 'y' happened? ProcMon will tell you.
- Try using http://www.google.com before posting.
- I answer questions only via forums. Please appreciate the time I give here and don't send me personal emails.

Zweitze

Zweitze
  • Full Members
  • 522 posts

Posted 07 December 2007 - 11:33

Windows has a list of well-known SIDs for all built in accounts called RIDs, (domain) relative identifiers. They're a bunch of consts inside one of the .h files of the Platform SDK. Using that RID, construct a SID with information of the target system, then call LookupAccountSid to get the logon name.

This method can deal with localizations (builtin accounts have names in the language of the OS) and accounts that were renamed by an admin. On the MSDN library, look for articles on "well known SIDs" and "LookupAccountSID". I believe it even has sample code to retrieve the name of the builtin Administrators group, which is close to what you want.

Note this method fails when the account was deleted. You're better off creating a new account for your purposes.


Pizzero

Pizzero
  • Full Members
  • 22 posts

Posted 10 January 2008 - 18:29

With the encouragement of Zweitze, I chanced to write some code - which I'd like to post here and to share for discussion. It's working and production quality, however it's a debut feature for me, being Linux developer...

It gives the localized string for the guest account (RID=501) in the installer property GUEST_ACCOUNT_NAME as result.

(I start with return value 4444 for errors, the only thing I'm not 100% sure about, but these codes are not in use according to the MSDN documentation.)


#include <windows.h>
#include <tchar.h>
#include <Sddl.h>
#include <Msiquery.h>



#ifdef __cplusplus /* If used by C++ code, */
extern "C" { /* we need to export the C interface */
#endif



UINT __stdcall GuestAccountName( MSIHANDLE hInstall )
{
TCHAR computerName[MAX_COMPUTERNAME_LENGTH+1]; /* NetBIOS Computer name */
PSID NewSid = NULL;
PSID Sid = NULL;
DWORD cbSid = 0;
LPTSTR ReferencedDomainName = NULL;
DWORD cbReferencedDomainName = 0;
LPTSTR accountName = NULL;
DWORD dwSize, dwResult = 0;
SID_NAME_USE SidType;

UINT ret = 0;


/**********************************************************************
* Obtain computer name (Kernel32.lib) *
***************************************/

dwSize = MAX_COMPUTERNAME_LENGTH+1;
if( !GetComputerName(computerName, &dwSize) )
return 4444;


/**********************************************************************
* Obtain computer SID (Advapi32.lib) *
**************************************/

/* 1st call: Determine string sizes, without error handling */

LookupAccountName(
NULL, /* __in_opt Machine to lookup account on. */
computerName, /* __in Address of string for account name. */
NULL, /* __out_opt Address of security identifier. */
&cbSid, /* __inout Address of size (bytes) of security identifier. */
NULL, /* __out_opt Address of string for referenced domain. */
&cbReferencedDomainName,/* __inout Address of size (TCHARs) of domain string. */
&SidType /* __out Address of SID-type indicator. */
);

Sid = (PSID)malloc( cbSid );
ReferencedDomainName = (LPTSTR)malloc( cbReferencedDomainName * sizeof(TCHAR) );

/* 2nd call: Read strings */

if( !LookupAccountName(
NULL, /* __in_opt Machine to lookup account on. */
computerName, /* __in Address of string for account name. */
Sid, /* __out_opt Address of security identifier. */
&cbSid, /* __inout Address of size (bytes) of security identifier. */
ReferencedDomainName, /* __out_opt Address of string for referenced domain. */
&cbReferencedDomainName,/* __inout Address of size (TCHARs) of domain string. */
&SidType /* __out Address of SID-type indicator. */
))
return 4445;

/* Should never fail: Computer SID must be of type "SidTypeDomain" */

if( SidType != SidTypeDomain )
return 4446;


/**********************************************************************
* Create Guest SID (well-known) (Advapi32.lib) *
************************************************/

/* Following code taken from MSDN "CreateWellKnownSid" example */

cbSid = SECURITY_MAX_SID_SIZE;
/* Allocate enough memory for the largest possible SID. */
if( !(NewSid = LocalAlloc(LMEM_FIXED, cbSid)) )
return 4447;

/* WinBuiltinGuestsSid -> Guests (group)
* WinAccountGuestSid -> computer SID requiered
* WinAccountDomainGuestsSid -> computer SID required */

if( !CreateWellKnownSid(
WinAccountGuestSid, /* __in WELL_KNOWN_SID_TYPE member*/
Sid, /* __in_opt DomainSid, identifies domain control */
NewSid, /* __out_opt pSid, output variable */
&cbSid /* __inout cbSid, no. of bytes available for pSid */
))
return 4448;


/**********************************************************************
* Obtain Guest account name (Advapi32.lib) *
********************************************/

free((void *)ReferencedDomainName);
ReferencedDomainName = 0;

/* 1st call: Determine string sizes, without error handling */

cbReferencedDomainName = 0;
dwSize = 0;

LookupAccountSid(
NULL, /* __in_opt Machine to lookup account on. */
NewSid, /* __in Address of security identifier. */
NULL, /* __out_opt Address of string for account name. */
&dwSize, /* __inout Address of size of security identifier. */
NULL, /* __out_opt Address of string for referenced domain. */
&cbReferencedDomainName,/* __inout Address of size of domain string. */
&SidType /* __out Address of SID-type indicator. */
);

accountName = (LPTSTR)malloc( dwSize * sizeof(TCHAR) );
ReferencedDomainName = (LPSTR)malloc( cbReferencedDomainName * sizeof(TCHAR) );

/* 2nd call: Read strings */

if( !LookupAccountSid(
NULL, /* __in_opt Machine to lookup account on. */
NewSid, /* __in Address of security identifier. */
accountName, /* __out_opt Address of string for account name. */
&dwSize, /* __inout Address of size of security identifier. */
ReferencedDomainName, /* __out_opt Address of string for referenced domain. */
&cbReferencedDomainName,/* __inout Address of size of domain string. */
&SidType /* __out Address of SID-type indicator. */
))
return 4449;


/**********************************************************************
* Set MSI Property (Msi.lib) *
******************************/

ret = MsiSetProperty (hInstall, _T("GUEST_ACCOUNT_NAME"), accountName);
if(ret != ERROR_SUCCESS)
return 4450;

if (NewSid)
LocalFree( NewSid );
if (Sid)
free((void *)Sid);
if (ReferencedDomainName)
free((void *)ReferencedDomainName);
if (accountName)
free((void *)accountName);

return ERROR_SUCCESS;
}


#ifdef __cplusplus
}
#endif


VBScab

VBScab
  • Full Members
  • 436 posts

Posted 11 January 2008 - 10:04

LOL...laugh.gif For someone who wanted to avoid script, you sure went to a whole heap of trouble! smile.gif

In the meantime, for us mere mortals, here's a script which could easily be adapted for this purpose. 'strUser' will contain the localised name.

Edited by VBScab, 11 January 2008 - 14:01.

- Don't know why 'x' happened? Want to know why 'y' happened? ProcMon will tell you.
- Try using http://www.google.com before posting.
- I answer questions only via forums. Please appreciate the time I give here and don't send me personal emails.

Pizzero

Pizzero
  • Full Members
  • 22 posts

Posted 11 January 2008 - 15:29

As an experienced C programmer I did not have the trouble as you might have expected VBScab. And script programmers surely are a bit lazy with writing code at low level. tongue.gif

Before writing my code, originally I had a simple dialogue prompt in my installation, where the user had to give the information.

On the other hand I would have a problem, if the script engine would not run and if the installation would fail exactly because of this. I deploy code to sensible areas as hospital systems, where "script processing" could have been switched off for some reason, or where anti-virus software could block execution.

No, I'm really better off with this rooted to the soil and robust solution! smile.gif

Best regards,
Pizzero


VBScab

VBScab
  • Full Members
  • 436 posts

Posted 11 January 2008 - 17:15

QUOTE
As an experienced C programmer I did not have the trouble as you might have expected VBScab.
We can see that smile.gif

QUOTE
And script programmers surely are a bit lazy with writing code at low level.
"Surely"? Bit of a sweeping generalisation there, eh, what? *SOME* script writers are lazy but then I wouldn't use the term 'programmer' for such people. If I were you, I'd now be expecting flames from assembly language programmers who would probably regard themselves as the real low-level bit twiddlers.

QUOTE
if the script engine would not run and if the installation would fail exactly because of this. I deploy code to sensible areas as hospital systems, where "script processing" could have been switched off for some reason, or where anti-virus software could block execution.
Most MSI authoring tools allow you to embed the script (strictly speaking, embedded scripts are restricted in length but in practise, they're not), meaning that normal script blocking is bypassed, because WScript isn't the host, the Windows Installer engine is. Anti-virus s/w would likely not be an issue either, as MSIExec.EXE is - we hope - trusted.

Anyway, the point of my post was to assist those who might search the archive and be disappointed to discover only C code, when a less complex and more easily accessible solution was sought. No slight was intended, as I'm sure you realise.

Happy coding! smile.gif
- Don't know why 'x' happened? Want to know why 'y' happened? ProcMon will tell you.
- Try using http://www.google.com before posting.
- I answer questions only via forums. Please appreciate the time I give here and don't send me personal emails.

Zweitze

Zweitze
  • Full Members
  • 522 posts

Posted 12 January 2008 - 17:13

QUOTE
Most MSI authoring tools allow you to embed the script (strictly speaking, embedded scripts are restricted in length but in practise, they're not), meaning that normal script blocking is bypassed, because WScript isn't the host, the Windows Installer engine is. Anti-virus s/w would likely not be an issue either, as MSIExec.EXE is - we hope - trusted.

In so-called 'locked down systems' all scripting is disabled: not just in WScript/CScript, but also in IExplore, Msiexec, etc. In fact no host can do any scripting, as I found out the hard way - I developed software with a script host, and even a script debugger, included.
The anti-virus software 'blocking' solutions are in my opinion very poor: at least a few of them re-register the 'FileSystemObject' class to a class of their own. In their implementation they forward the call to the real FileSystemObject, but known harmful calls are intercepted. Nothing else is checked, so any WMI goes ahead.

Edited by Zweitze, 12 January 2008 - 17:13.


Zweitze

Zweitze
  • Full Members
  • 522 posts

Posted 12 January 2008 - 17:27

QUOTE
I chanced to write some code - which I'd like to post here and to share for discussion. It's working and production quality, however it's a debut feature for me, being Linux developer...


It appears OK, but it may not work on Domain Controllers - DCs do not have accounts of their own, only Domain accounts. Therefore you cannot use the computer name to construct the SID, instead use the domain name. In other words, on a DC you should be looking for a domain guest account instead of a local guest account.

QUOTE
(I start with return value 4444 for errors, the only thing I'm not 100% sure about, but these codes are not in use according to the MSDN documentation.)

Well, your code 4449 just means that the account does not exist (probably deleted). But for general reference, look up whether the failing calls support GetLastError(), in that case just return that error. And when MsiSetProperty fails, consider to just return the return value of MsiSetProperty instead of 4450.

Oh, BTW when the code does fail you're stuck with a memory leak. It's not that bad when this happens in the UI sequence, but when this happens in the Execute sequence its worse (this is hosted by a service, to recover the memory you've got to restart it).

VBScab

VBScab
  • Full Members
  • 436 posts

Posted 14 January 2008 - 09:55

QUOTE
In so-called 'locked down systems' all scripting is disabled <snip>
In the overwhelming majority of such environments, though, MSIs would be being delivered by a deployment system like SMS, Group Policy, etc. etc. meaning that any script would be authored to run in System context, allowing the installation to do more or less what it wants. I've never had any difficulty with MSI-hosted scripts in these environments.

Edited by VBScab, 14 January 2008 - 15:40.

- Don't know why 'x' happened? Want to know why 'y' happened? ProcMon will tell you.
- Try using http://www.google.com before posting.
- I answer questions only via forums. Please appreciate the time I give here and don't send me personal emails.