Article View: borland.public.cppbuilder.nativeapi
Article #10759GINA Dev, userinit.exe and Exception (0xc0000142)
From: Mike Collins
Date: Wed, 24 Mar 2004 12:34
Date: Wed, 24 Mar 2004 12:34
215 lines
8722 bytes
8722 bytes
Hi all, sorry about the following post, I know it's very long and very
specific but I can't get any help from the
microsoft.public.platformsdk.security and I'm starting to pull hairs. I
might add I'm using C++Builder 6 Enterprise so it's not surprising that I've
had no response from MS groups :-)
I'm writing a GINA (GinaStub) where I CAN overriding the WlxLoggedOutSAS to
enhance the logon options. After a bit of trial and error I got it to work
more or less but I discovered that I had to code my own implementation of
WlxActivateUserShall as relaying the original call on to MSGina seemed to
fail i.e. if I override WlxLoggedOutSAS I have to override
WlxActivateUserShall, if I relay WlxLoggedOutSAS then I can relay
WlxActivateUserShall.
So having coded my own implementation all seemed well, CreateProcessAsUser
executes ok with no errors and WlxActivateUserShell returns ok. However, I
then get an exception / access violation being caused within the
initialisation of userinit.exe. The exception is :
"Userinint.exe - Application Error"
"The application failed to initialize properly (0xc0000142)"
From a search on google under "userinit.exe and (0xc0000142)" if suggests
that this is a problem with the ACL.
The SID that I'm returning from WlxLoggedOutSAS looks like this:
S-1-5-5-0-47048.
My code is pretty much a copy of the example that appeared in MSDN under the
replacement Gina. I have my main Gina.dll which exposes / exports the
various Wlx functions, these are then passed to on to a class that I have
defined that deals with the actual "nitty-gritty" i.e.
Gina.dll -> WlxLoggedOutSAS -> TMainStub::LogOnUser <- this has identical
parameters to WlxLoggedOutSAS.
My actual code for TMainStub::LogOnUser looks like this:
int TMainStub::LogOnUser(PVOID pWlxContext, DWORD dwSasType, PLUID
pAuthenticationId, PSID pLogonSid, PDWORD pdwOptions, PHANDLE phToken,
PWLX_MPR_NOTIFY_INFO pMprNotifyInfo, PVOID *pProfile)
{
int iRtn = WLX_SAS_ACTION_NONE;
try
{
EnterCriticalSection(&lpCritSect);
// Just for test purposes....
strAuthData.szUsername = "mikec";
strAuthData.szDomain = "HADES";
strAuthData.szPassword = "come-death";
HANDLE hUser = NULL;
TOKEN_STATISTICS strTokenStats;
TOKEN_GROUPS *pGroups;
if (LogonUser((LPTSTR)strAuthData.szUsername.c_str(),
(LPTSTR)strAuthData.szDomain.c_str(),
(LPTSTR)strAuthData.szPassword.c_str(),
LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT,
&hUser))
{
// Test the token for validity, just to be safe
if (hUser)
{
DWORD dwSize;
GetTokenInformation(hUser,
TokenStatistics,
&strTokenStats,
sizeof(strTokenStats),
&dwSize);
*pAuthenticationId = strTokenStats.AuthenticationId;
pGroups = (_TOKEN_GROUPS*)LocalAlloc(LMEM_FIXED, 1024);
//<-might need to check casting
if (pGroups)
{
GetTokenInformation(hUser,
TokenGroups,
pGroups,
1024,
&dwSize);
if (dwSize > 1024)
{
pGroups = (_TOKEN_GROUPS*)LocalReAlloc(pGroups,
LMEM_FIXED, dwSize);
GetTokenInformation(hUser,
TokenGroups,
pGroups,
dwSize,
&dwSize);
}
for (DWORD i=0; i<pGroups->GroupCount; ++i)
{
if ((pGroups->Groups[i].Attributes &
SE_GROUP_LOGON_ID)
== SE_GROUP_LOGON_ID)
{
CopySid(GetLengthSid(pLogonSid),
pLogonSid,pGroups->Groups[i].Sid);
break;
}
}
LocalFree(pGroups);
// It all looks good... Save the token to our structure for
future reference / access
strAuthData.hUserToken = hUser;
// Assign the token to the passed pointer...
*phToken = hUser;
// Pass back null profile and options.
*pdwOptions = 0;
*pProfile =NULL;
// Pass back multiple provider information.
pMprNotifyInfo->pszUserName =
(WideString)strAuthData.szUsername;
pMprNotifyInfo->pszDomain =
(WideString)strAuthData.szDomain;
pMprNotifyInfo->pszPassword =
(WideString)strAuthData.szPassword;
pMprNotifyInfo->pszOldPassword = NULL;
iRtn = WLX_SAS_ACTION_LOGON;
}
else
{
CloseHandle(hUser);
}
}
}
__finally
{
LeaveCriticalSection(&lpCritSect);
}
return iRtn;
}
As for my WlxActiveUserShell ->TMainStub::ActiveUserShell, it's taken mostly
from the example of implementing WlxActiveUserShell from MSDN website (I
didn't use the example that was given with the Gina replacement because I
was getting rubbish returned from GetProfileString, I know that there can be
multiple entries in the registry for Userinit - on my test box there isn't
so I'll deal with that later):
BOOL TMainStub::ActiveUserShell(PVOID pWlxContext, PWSTR pszDesktopName,
PWSTR pszMprLogonScript, PVOID pEnvironment)
{
BOOL bRtn = 0;
STARTUPINFO si;
PROCESS_INFORMATION pi;
// Setup STARTUPINFO to pass to CreateProcessAsUser.
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(STARTUPINFO);
si.lpReserved = NULL;
si.lpTitle = "userinit.exe";
si.dwX = si.dwY = si.dwXSize = si.dwYSize = 0L;
si.dwFlags = 0;
si.wShowWindow = SW_SHOW;
si.lpReserved2 = NULL;
si.cbReserved2 = 0;
si.lpDesktop = (LPSTR)pszDesktopName;
// AnsiString szUserInitApp = "E:\\WIN2003\\System32\\userinit.exe";
AnsiString szUserInitApp = "userinit.exe";
try
{
// Not sure why it is necessary to call ImpersonateLoggedOnUser
ImpersonateLoggedOnUser(strAuthData.hUserToken);
bRtn = CreateProcessAsUser(strAuthData.hUserToken,
(LPCTSTR)szUserInitApp.c_str(),
NULL,
NULL,
NULL,
FALSE,
CREATE_UNICODE_ENVIRONMENT,
pEnvironment,
NULL,
&si,
&pi);
if (bRtn)
{
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
else
{
ShowMessage(SysErrorMessage(GetLastError()).c_str());
}
}
__finally
{
RevertToSelf();
}
// Release the memory winlogon allocated for the environment.
VirtualFree(pEnvironment, 0, MEM_RELEASE);
return bRtn;
}
This one's got me totally stumped, I've read all the documentation (and it's
pretty crap) and nothing, no response from the MS groups and almost
impossible to debug, help pleassssssssse :-)
Thanks in advance,
Mike C
Technical Details
Message-ID:
<40617991@newsgroups.borland.com>Path:
arc1-ca.pugleaf.net!archiver1.google.com!news2.google.com!news.maxwell.syr.edu!newsfeed00.sul.t-online.de!newsfeed01.sul.t-online.de!t-online.de!newsgroups.borland.com!not-for-mailShow Full Headers
Complete Article Headers
X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 10cc67,b4e1a882d3f44f75,start X-Google-Attributes: gid10cc67,public X-Google-ArrivalTime: 2004-03-24 04:09:47 PST Reply-To: "Mike Collins" <mikec@kr8.co.uk> From: "Mike Collins" <mikec@kr8.co.uk> Newsgroups: borland.public.cppbuilder.nativeapi Subject: GINA Dev, userinit.exe and Exception (0xc0000142) Date: Wed, 24 Mar 2004 12:34:25 -0000 Lines: 220 Organization: kr8 X-Priority: 3 X-MSMail-Priority: Normal X-Newsreader: Microsoft Outlook Express 6.00.2800.1158 X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1165 NNTP-Posting-Host: 81.2.78.34 Message-ID: <40617991@newsgroups.borland.com> X-Trace: newsgroups.borland.com 1080129937 81.2.78.34 (24 Mar 2004 04:05:37 -0800) Path: arc1-ca.pugleaf.net!archiver1.google.com!news2.google.com!news.maxwell.syr.edu!newsfeed00.sul.t-online.de!newsfeed01.sul.t-online.de!t-online.de!newsgroups.borland.com!not-for-mail