🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: borland.public.cppbuilder.nativeapi
Article #10759

GINA Dev, userinit.exe and Exception (0xc0000142)

#10759
From: Mike Collins
Date: Wed, 24 Mar 2004 12:34
215 lines
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-mail

Show 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