Esempio n. 1
0
//
// Retrieves the 'negotiate' AuthPackage from the LSA. In this case, Kerberos
// For more information on auth packages see this msdn page:
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/secauthn/security/msv1_0_lm20_logon.asp
//
HRESULT RetrieveNegotiateAuthPackage(ULONG * pulAuthPackage)
{
    HRESULT hr;
    HANDLE hLsa;

    NTSTATUS status = LsaConnectUntrusted(&hLsa);
    if (SUCCEEDED(HRESULT_FROM_NT(status)))
    {

        ULONG ulAuthPackage;
        LSA_STRING lsaszKerberosName;
        LsaInitString(&lsaszKerberosName, NEGOSSP_NAME);

        status = LsaLookupAuthenticationPackage(hLsa, &lsaszKerberosName, &ulAuthPackage);
        if (SUCCEEDED(HRESULT_FROM_NT(status)))
        {
            *pulAuthPackage = ulAuthPackage;
            hr = S_OK;
        }
        else
        {
            hr = HRESULT_FROM_NT(status);
        }
        LsaDeregisterLogonProcess(hLsa);
    }
    else
    {
        hr= HRESULT_FROM_NT(status);
    }

    return hr;
}
Esempio n. 2
0
NTSTATUS kuhl_m_kerberos_init()
{
	NTSTATUS status = LsaConnectUntrusted(&g_hLSA);
	if(NT_SUCCESS(status))
	{
		status = LsaLookupAuthenticationPackage(g_hLSA, &kerberosPackageName, &g_AuthenticationPackageId_Kerberos);
		g_isAuthPackageKerberos = NT_SUCCESS(status);
	}
	return status;
}
Esempio n. 3
0
static
NTSTATUS
OpenLogonLsaHandle(VOID)
{
    LSA_STRING LogonProcessName;
    LSA_STRING PackageName;
    LSA_OPERATIONAL_MODE SecurityMode = 0;
    NTSTATUS Status;

    RtlInitAnsiString((PANSI_STRING)&LogonProcessName,
                      "User32LogonProcess");

    Status = LsaRegisterLogonProcess(&LogonProcessName,
                                     &LsaHandle,
                                     &SecurityMode);
    if (!NT_SUCCESS(Status))
    {
        TRACE("LsaRegisterLogonProcess failed (Status 0x%08lx)\n", Status);
        goto done;
    }

    RtlInitAnsiString((PANSI_STRING)&PackageName,
                      MSV1_0_PACKAGE_NAME);

    Status = LsaLookupAuthenticationPackage(LsaHandle,
                                            &PackageName,
                                            &AuthenticationPackage);
    if (!NT_SUCCESS(Status))
    {
        TRACE("LsaLookupAuthenticationPackage failed (Status 0x%08lx)\n", Status);
        goto done;
    }

    TRACE("AuthenticationPackage: 0x%08lx\n", AuthenticationPackage);

done:
    if (!NT_SUCCESS(Status))
    {
        if (LsaHandle != NULL)
        {
            Status = LsaDeregisterLogonProcess(LsaHandle);
            if (!NT_SUCCESS(Status))
            {
                TRACE("LsaDeregisterLogonProcess failed (Status 0x%08lx)\n", Status);
            }
        }
    }

    return Status;
}
Esempio n. 4
0
BOOL 
PackageConnectLookup(
    HANDLE *pLogonHandle, 
    ULONG *pPackageId
    )
{
    LSA_STRING Name;
    NTSTATUS Status;

    Status = LsaConnectUntrusted(
                pLogonHandle
                );

    if (!SEC_SUCCESS(Status))
    {
        ShowNTError("LsaConnectUntrusted", Status);
        return FALSE;
    }

    Name.Buffer = MICROSOFT_KERBEROS_NAME_A;
    Name.Length = strlen(Name.Buffer);
    Name.MaximumLength = Name.Length + 1;

    Status = LsaLookupAuthenticationPackage(
                *pLogonHandle,
                &Name,
                pPackageId
                );

    if (!SEC_SUCCESS(Status))
    {
        ShowNTError("LsaLookupAuthenticationPackage", Status);
        return FALSE;
    }

    return TRUE;

}
Esempio n. 5
0
static BOOL
GetLSAPrincipalName(char * pszUser, DWORD dwUserSize)
{
    KERB_QUERY_TKT_CACHE_REQUEST CacheRequest;
    PKERB_RETRIEVE_TKT_RESPONSE pTicketResponse = NULL;
    ULONG ResponseSize;
    PKERB_EXTERNAL_NAME pClientName = NULL;
    PUNICODE_STRING     pDomainName = NULL;
    LSA_STRING Name;
    HANDLE hLogon = INVALID_HANDLE_VALUE;
    ULONG PackageId;
    NTSTATUS ntStatus;
    NTSTATUS ntSubStatus = 0;
    WCHAR * wchUser = NULL;
    DWORD   dwSize;
    SHORT   sCount;
    BOOL bRet = FALSE;

    ntStatus = LsaConnectUntrusted( &hLogon);
    if (FAILED(ntStatus))
        goto cleanup;

    Name.Buffer = MICROSOFT_KERBEROS_NAME_A;
    Name.Length = (USHORT)(sizeof(MICROSOFT_KERBEROS_NAME_A) - sizeof(char));
    Name.MaximumLength = Name.Length;

    ntStatus = LsaLookupAuthenticationPackage( hLogon, &Name, &PackageId);
    if (FAILED(ntStatus))
        goto cleanup;

    memset(&CacheRequest, 0, sizeof(KERB_QUERY_TKT_CACHE_REQUEST));
    CacheRequest.MessageType = KerbRetrieveTicketMessage;
    CacheRequest.LogonId.LowPart = 0;
    CacheRequest.LogonId.HighPart = 0;

    ntStatus = LsaCallAuthenticationPackage( hLogon,
                                             PackageId,
                                             &CacheRequest,
                                             sizeof(CacheRequest),
                                             &pTicketResponse,
                                             &ResponseSize,
                                             &ntSubStatus);
    if (FAILED(ntStatus) || FAILED(ntSubStatus))
        goto cleanup;

    /* We have a ticket in the response */
    pClientName = pTicketResponse->Ticket.ClientName;
    pDomainName = &pTicketResponse->Ticket.DomainName;

    /* We want to return ClientName @ DomainName */

    dwSize = 0;
    for ( sCount = 0; sCount < pClientName->NameCount; sCount++)
    {
        dwSize += pClientName->Names[sCount].Length;
    }
    dwSize += pDomainName->Length + sizeof(WCHAR);

    if ( dwSize / sizeof(WCHAR) > dwUserSize )
        goto cleanup;

    wchUser = malloc(dwSize);
    if (wchUser == NULL)
        goto cleanup;

    for ( sCount = 0, wchUser[0] = L'\0'; sCount < pClientName->NameCount; sCount++)
    {
        StringCbCatNW( wchUser, dwSize,
                       pClientName->Names[sCount].Buffer,
                       pClientName->Names[sCount].Length);
    }
    StringCbCatNW( wchUser, dwSize,
                   pDomainName->Buffer,
                   pDomainName->Length);

    if ( !UnicodeToANSI( wchUser, pszUser, dwUserSize) )
        goto cleanup;

    bRet = TRUE;

  cleanup:

    if (wchUser)
        free(wchUser);

    if ( hLogon != INVALID_HANDLE_VALUE)
        LsaDeregisterLogonProcess(hLogon);

    if ( pTicketResponse ) {
        SecureZeroMemory(pTicketResponse,ResponseSize);
        LsaFreeReturnBuffer(pTicketResponse);
    }

    return bRet;
}
Esempio n. 6
0
int _tmain(int argc, TCHAR *argv[])
{
   BOOL bResult;
   NTSTATUS Status;
   NTSTATUS SubStatus;

   HANDLE hLsa = NULL;
   HANDLE hProcess = NULL;
   HANDLE hToken = NULL;
   HANDLE hTokenS4U = NULL;

   LSA_STRING Msv1_0Name = { 0 };
   LSA_STRING OriginName = { 0 };
   PMSV1_0_S4U_LOGON pS4uLogon = NULL;
   TOKEN_SOURCE TokenSource;
   ULONG ulAuthenticationPackage;
   DWORD dwMessageLength;

   PBYTE pbPosition;

   PROCESS_INFORMATION pi = { 0 };
   STARTUPINFO si = { 0 };

   PTOKEN_GROUPS pGroups = NULL;
   PSID pLogonSid = NULL;
   PSID pExtraSid = NULL;

   PVOID pvProfile = NULL;
   DWORD dwProfile = 0;
   LUID logonId = { 0 };
   QUOTA_LIMITS quotaLimits;

   LPTSTR szCommandLine = NULL;
   LPTSTR szSrcCommandLine = TEXT("%systemroot%\\system32\\cmd.exe");
   LPTSTR szDomain = NULL;
   LPTSTR szUsername = NULL;
   TCHAR seps[] = TEXT("\\");
   TCHAR *next_token = NULL;

   g_hHeap = GetProcessHeap();

   if (argc < 2)
   {
      fprintf(stderr, "Usage:\n   s4u.exe Domain\\Username [Extra SID]\n\n");
      goto End;
   }

   //
   // Get DOMAIN and USERNAME from command line.
   //
   szDomain = _tcstok_s(argv[1], seps, &next_token);
   if (szDomain == NULL)
   {
      fprintf(stderr, "Unable to parse command line.\n");
      goto End;
   }

   szUsername = _tcstok_s(NULL, seps, &next_token);
   if (szUsername == NULL)
   {
      fprintf(stderr, "Unable to parse command line.\n");
      goto End;
   }

   //
   // Activate the TCB privilege
   //
   hProcess = GetCurrentProcess();
   OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
   if (!SetPrivilege(hToken, SE_TCB_NAME, TRUE))
   {
      goto End;
   }

   //
   // Get logon SID
   //
   if (!GetLogonSID(hToken, &pLogonSid))
   {
      fprintf(stderr, "Unable to find logon SID.\n");
      goto End;
   }

   //
   // Connect (Untrusted) to LSA
   //
   Status = LsaConnectUntrusted(&hLsa);
   if (Status!=STATUS_SUCCESS)
   {
      fprintf(stderr, "LsaConnectUntrusted failed (error 0x%x).", Status);
      hLsa = NULL;
      goto End;
   }

   //
   // Lookup for the MSV1_0 authentication package (NTLMSSP)
   //
   InitLsaString(&Msv1_0Name, MSV1_0_PACKAGE_NAME);
   Status = LsaLookupAuthenticationPackage(hLsa, &Msv1_0Name, &ulAuthenticationPackage);
   if (Status!=STATUS_SUCCESS)
   {
      fprintf(stderr, "LsaLookupAuthenticationPackage failed (error 0x%x).", Status);
      hLsa = NULL;
      goto End;
   }

   //
   // Create MSV1_0_S4U_LOGON structure
   //
   dwMessageLength = sizeof(MSV1_0_S4U_LOGON) + (2 + wcslen(szDomain) + wcslen(szUsername)) * sizeof(WCHAR);
   pS4uLogon = (PMSV1_0_S4U_LOGON)HeapAlloc(g_hHeap, HEAP_ZERO_MEMORY, dwMessageLength);
   if (pS4uLogon == NULL)
   {
      fprintf(stderr, "HeapAlloc failed (error %u).", GetLastError());
      goto End;
   }

   pS4uLogon->MessageType = MsV1_0S4ULogon;
   pbPosition = (PBYTE)pS4uLogon + sizeof(MSV1_0_S4U_LOGON);
   pbPosition = InitUnicodeString(&pS4uLogon->UserPrincipalName, szUsername, pbPosition);
   pbPosition = InitUnicodeString(&pS4uLogon->DomainName, szDomain, pbPosition);

   //
   // Misc
   //
   strcpy_s(TokenSource.SourceName, TOKEN_SOURCE_LENGTH, "S4UWin");
   InitLsaString(&OriginName, "S4U for Windows");
   AllocateLocallyUniqueId(&TokenSource.SourceIdentifier);

   //
   // Add extra SID to token.
   //
   // If the application needs to connect to a Windows Desktop, Logon SID must be added to the Token.
   //
   pGroups = (PTOKEN_GROUPS)HeapAlloc(g_hHeap, HEAP_ZERO_MEMORY, sizeof(TOKEN_GROUPS) + 2*sizeof(SID_AND_ATTRIBUTES));
   if (pGroups == NULL)
   {
      fprintf(stderr, "HeapAlloc failed (error %u).", GetLastError());
      goto End;
   }

   pGroups->GroupCount = 1;
   pGroups->Groups[0].Attributes = SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY;
   pGroups->Groups[0].Sid = pLogonSid;

   //
   // If an extra SID is specified to command line, add it to the pGroups structure.
   //
   if (argc==3)
   {
      bResult = ConvertStringSidToSid(argv[2], &pExtraSid);

      if (bResult == TRUE)
      {
         pGroups->GroupCount = 2;
         pGroups->Groups[1].Attributes = SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY;
         pGroups->Groups[1].Sid = pExtraSid;
      }
      else
      {
         fprintf(stderr, "Unable to convert SID (error %u).", GetLastError());
      }
   }

   //
   // Call LSA
   //
   Status = LsaLogonUser(
      hLsa,
      &OriginName,
      Network,                // Or Batch
      ulAuthenticationPackage,
      pS4uLogon,
      dwMessageLength,
      pGroups,                // LocalGroups
      &TokenSource,           // SourceContext
      &pvProfile,
      &dwProfile,
      &logonId,
      &hTokenS4U,
      &quotaLimits,
      &SubStatus
      );
   if (Status!=STATUS_SUCCESS)
   {
      printf("LsaLogonUser failed (error 0x%x).\n", Status);
      goto End;
   }

   printf("LsaLogonUser: OK, LogonId: 0x%x-0x%x\n", logonId.HighPart, logonId.LowPart);

   //
   // Create process with S4U token.
   //
   si.cb = sizeof(STARTUPINFO);
   si.lpDesktop = TEXT("winsta0\\default");

   //
   // Warning: szCommandLine parameter of CreateProcessAsUser() must be writable
   //
   szCommandLine = (LPTSTR)HeapAlloc(g_hHeap, HEAP_ZERO_MEMORY, MAX_PATH * sizeof(TCHAR));
   if (szCommandLine == NULL)
   {
      fprintf(stderr, "HeapAlloc failed (error %u).", GetLastError());
      goto End;
   }

   if (ExpandEnvironmentStrings(szSrcCommandLine, szCommandLine, MAX_PATH) == 0)
   {
      fprintf(stderr, "ExpandEnvironmentStrings failed (error %u).", GetLastError());
      goto End;
   }

   //
   // CreateProcessAsUser required SeAssignPrimaryTokenPrivilege but no need to be activated.
   //
   bResult = CreateProcessAsUser(
      hTokenS4U,
      NULL,
      szCommandLine,
      NULL,
      NULL,
      FALSE,
      NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE,
      NULL,
      TEXT("c:\\"),
      &si,
      &pi
      );
   if (bResult == FALSE)
   {
      printf("CreateProcessAsUser failed (error %u).\n", GetLastError());
      goto End;
   }

End:
   //
   // Free resources
   //
   if (Msv1_0Name.Buffer)
      HeapFree(g_hHeap, 0, Msv1_0Name.Buffer);
   if (OriginName.Buffer)
      HeapFree(g_hHeap, 0, OriginName.Buffer);
   if (pLogonSid)
      HeapFree(g_hHeap, 0, pLogonSid);
   if (pExtraSid)
      LocalFree(pExtraSid);
   if (pS4uLogon)
      HeapFree(g_hHeap, 0, pS4uLogon);
   if (pGroups)
      HeapFree(g_hHeap, 0, pGroups);
   if (pvProfile)
      LsaFreeReturnBuffer(pvProfile);
   if (hLsa)
      LsaClose(hLsa);
   if (hToken)
      CloseHandle(hToken);
   if (hTokenS4U)
      CloseHandle(hTokenS4U);
   if (pi.hProcess)
      CloseHandle(pi.hProcess);
   if (pi.hThread)
      CloseHandle(pi.hThread);

   return EXIT_SUCCESS;
}
Esempio n. 7
0
//+-------------------------------------------------------------------------
//
//  Function:   CreateClient
//
//  Synopsis:   Creates a client representing this caller.  Establishes
//              a connection with the SPM.
//
//  Effects:
//
//  Arguments:
//
//  Requires:
//
//  Returns:
//
//  Notes:
//
//--------------------------------------------------------------------------
NTSTATUS
CreateClient(PClient *  ppClient)
{
    PClient     pClient;
    NTSTATUS    scRet;
    KIRQL       OldIrql;
    HANDLE      hEvent;
    STRING      LogonProcessName;
    STRING      PackageName;
    LSA_OPERATIONAL_MODE LsaMode;
    HANDLE      LsaHandle = NULL;




    if (!fInitialized)
    {
        if (!InitConnMgr())
        {
            DebugLog((DEB_ERROR,"InitConnMgr Failed!\n"));
            return(SEC_E_INTERNAL_ERROR);
        }
    }
    //
    // Call the LSA to register this logon process.
    //

    RtlInitString(
        &LogonProcessName,
        LogonProcessString
        );


    scRet = LsaRegisterLogonProcess(
                &LogonProcessName,
                &LsaHandle,
                &LsaMode
                );

    if (!NT_SUCCESS(scRet))
    {
        DebugLog((DEB_ERROR,"KSec: Connection failed, postponing\n"));
        return(SEC_E_INTERNAL_ERROR);
    }

    //
    // Lookup the authentication package.
    //

    RtlInitString(
        &PackageName,
        MSV1_0_PACKAGE_NAME
        );

    scRet = LsaLookupAuthenticationPackage(
                LsaHandle,
                &PackageName,
                &PackageId
                );
    if (!NT_SUCCESS(scRet))
    {
        NtClose(LsaHandle);
        return(SEC_E_INTERNAL_ERROR);
    }

    pClient = (PClient) ExAllocatePool(NonPagedPool, sizeof(Client));

    if (!pClient)
    {
        DebugLog((DEB_ERROR,"KSec:  ExAllocatePool returned NULL.\n"));
        NtClose(LsaHandle);
        return(SEC_E_INSUFFICIENT_MEMORY);
    }

    pClient->ProcessId    = PsGetCurrentProcess();
    pClient->fClient      = 0;
    pClient->hPort        = LsaHandle;
    pClient->cRefs        = 1;



    // Adding the connection in to the client list:
    //
    // This has got to be MT/MP safe, so first,

    // get exclusive access to the Connection list:

    KeAcquireSpinLock(&ConnectSpinLock, &OldIrql);

    // Now, add the entry:

    cClients++;
    pClient->pNext = pClientList;
    pClientList = pClient;

    // Now, free the spin lock:

    KeReleaseSpinLock(&ConnectSpinLock, OldIrql);

    *ppClient = pClient;

    return(STATUS_SUCCESS);

}
Esempio n. 8
0
int LsaLogon(HANDLE *hToken, char homeDir[MAX_PATH], char *user, 
                 char *pkBlob, int pkBlobSize, char *sign, int signSize, 
                     char *data, int dataSize, int dataFellow)
{
  int exitCode = 1;
  
  NTSTATUS ntStat = 0;
  
  LSA_STRING logonProcName;
  LSA_STRING originName;
  LSA_STRING authPckgName;
  
  HANDLE hLsa = NULL;
  
  LSA_OPERATIONAL_MODE securityMode;
  
  /*
   * Impersonation, "weak" token returned from network logon.
   * We can't create process as other user via this token.
   */
  
  HANDLE hWeakToken = NULL;
  
  /*
   * Login data.
   */
  
  LsaAuth *lsaAuth = NULL;

  ULONG lsaAuthSize = 0;

  ULONG authPckgId  = 0;
  
  TOKEN_SOURCE srcToken;
  
  PVOID profile = NULL;

  ULONG profileSize;
  
  LUID  logonId;
  
  QUOTA_LIMITS quotas;
  
  NTSTATUS loginStat;
  

  debug("-> LsaLogon()...");

  /*
   * We check only hToken arg, becouse other args are tested in AllocLsaAuth().
   */
  
  debug("Checking args...");
  
  FAIL(hToken == NULL);
  
  /*
   * Setup lsa strings.
   */

  debug("Setting up LSA Strings...");
  
  FAIL(InitLsaString(&logonProcName, "sshd-logon"));
  FAIL(InitLsaString(&originName, "NTLM"));
  FAIL(InitLsaString(&authPckgName, "SSH-LSA"));

  /*
   * Enable needed privilege to current running process.
   */

  EnablePrivilege("SeTcbPrivilege", 1);
  
  /*
   * Register new logon process.
   */
  
  debug("LsaRegisterLogonProcess()...");

  NTFAIL(LsaRegisterLogonProcess(&logonProcName, &hLsa, &securityMode));
  
  /*
   * Retrieve Authenticated Package ID.
   */
  
  debug("Retrieving Authentification Package ID...");
  
  NTFAIL(LsaLookupAuthenticationPackage(hLsa, &authPckgName, &authPckgId));
  
  /*
   * Allocate LsaAuth struct.
   */

  debug("Allocating LsaAuth struct...");
  
  FAIL(AllocLsaAuth(&lsaAuth, user, pkBlob, pkBlobSize,
                       sign, signSize, data, dataSize, dataFellow));
                       
  lsaAuthSize = lsaAuth -> totalSize_;                       

  /*
   * Create TOKEN_SOURCE part
   */
  
  debug("Setting up TOKEN_SOURCE...");
  
  FAIL(AllocateLocallyUniqueId(&srcToken.SourceIdentifier) == FALSE);
  
  memcpy(srcToken.SourceName, "**sshd**", 8);

  /*
   * Try to login using LsaAuth struct.
   */

  debug("Login attemp...");
  
  NTFAIL(LsaLogonUser(hLsa, &originName, Network,
                          authPckgId, lsaAuth, lsaAuthSize, NULL,
                              &srcToken, &profile, &profileSize,
                                  &logonId, &hWeakToken, &quotas, &loginStat));

  debug("login status: %x...", loginStat);
  
  
  //FAIL(WideCharToMultiByte( CP_UTF8, 0, profile, -1, homeDir, MAX_PATH, NULL, NULL)==0);
  //memcpy(homeDir, profile, MAX_PATH*sizeof(wchar_t));

  lstrcpyW(homeDir, profile);
  
  debug("homedir = [%ls]", (char *) homeDir);

  //strcpy(homeDir, profile);
  
  //PrintToken(hToken);
  
  /*
   * Duplicate 'weak' impersonation token into Primary Key token.
   * We can create process using duplicated token.
   */
  
  debug("Duplicating token...");
  
  FAIL(DuplicateTokenEx(hWeakToken, MAXIMUM_ALLOWED,
                            NULL, SecurityImpersonation,
                                TokenPrimary, hToken) == 0);
  
  exitCode = 0;
  
fail:

  if (exitCode)
  {
    switch(ntStat)
    {
      case STATUS_LOGON_FAILURE:
      {
        debug("SSH-LSA authorization failed. " 
                  "(err = %u, ntStat = %x).", GetLastError(), ntStat);

        exitCode = 0;

        break;
      }
      
      case STATUS_NO_SUCH_PACKAGE:
      {
        debug("SSH-LSA package not found. "
                  "(err = %u, ntStat = %x).", GetLastError(), ntStat);
                  
        break;          
      }
      
      default:
      {
        debug("Cannot logon using LSA package (err = %u, ntStat = %x).",
                  GetLastError(), ntStat);
      }
    }        
            
    hToken = NULL;
  }
  else
  {
    debug("LsaLogon : OK.");
  }

  /*
   * Clean up.
   */
  
  CloseHandle(hWeakToken);
  
  LsaFreeReturnBuffer(profile);
   
  EnablePrivilege("SeTcbPrivilege", 0);
  
  LsaDeregisterLogonProcess(hLsa);
  
  ClearLsaString(&logonProcName);
  ClearLsaString(&originName);
  ClearLsaString(&authPckgName);
         
  debug("<- LsaLogon()...");
  
  return exitCode;
}
Esempio n. 9
-2
int
WINAPI
WinMain(
    IN HINSTANCE hInstance,
    IN HINSTANCE hPrevInstance,
    IN LPSTR lpCmdLine,
    IN int nShowCmd)
{
#if 0
    LSA_STRING ProcessName, PackageName;
    HANDLE LsaHandle;
    LSA_OPERATIONAL_MODE Mode;
    BOOLEAN Old;
    ULONG AuthenticationPackage;
    NTSTATUS Status;
#endif
    ULONG HardErrorResponse;
    MSG Msg;

    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);
    UNREFERENCED_PARAMETER(nShowCmd);

    hAppInstance = hInstance;

    /* Make us critical */
    RtlSetProcessIsCritical(TRUE, NULL, FALSE);
    RtlSetThreadIsCritical(TRUE, NULL, FALSE);

    if (!RegisterLogonProcess(GetCurrentProcessId(), TRUE))
    {
        ERR("WL: Could not register logon process\n");
        NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0, 0, NULL, OptionOk, &HardErrorResponse);
        ExitProcess(1);
    }

    WLSession = (PWLSESSION)HeapAlloc(GetProcessHeap(), 0, sizeof(WLSESSION));
    if (!WLSession)
    {
        ERR("WL: Could not allocate memory for winlogon instance\n");
        NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0, 0, NULL, OptionOk, &HardErrorResponse);
        ExitProcess(1);
    }

    ZeroMemory(WLSession, sizeof(WLSESSION));
    WLSession->DialogTimeout = 120; /* 2 minutes */

    /* Initialize the dialog tracking list */
    InitDialogListHead();

    if (!CreateWindowStationAndDesktops(WLSession))
    {
        ERR("WL: Could not create window station and desktops\n");
        NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0, 0, NULL, OptionOk, &HardErrorResponse);
        ExitProcess(1);
    }

    LockWorkstation(WLSession);

    /* Load default keyboard layouts */
    if (!InitKeyboardLayouts())
    {
        ERR("WL: Could not preload keyboard layouts\n");
        NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0, 0, NULL, OptionOk, &HardErrorResponse);
        ExitProcess(1);
    }

    if (!StartRpcServer())
    {
        ERR("WL: Could not start the RPC server\n");
        NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0, 0, NULL, OptionOk, &HardErrorResponse);
        ExitProcess(1);
    }

    if (!StartServicesManager())
    {
        ERR("WL: Could not start services.exe\n");
        NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0, 0, NULL, OptionOk, &HardErrorResponse);
        ExitProcess(1);
    }

    if (!StartLsass())
    {
        ERR("WL: Failed to start lsass.exe service (error %lu)\n", GetLastError());
        NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0, 0, NULL, OptionOk, &HardErrorResponse);
        ExitProcess(1);
    }

    /* Wait for the LSA server */
    WaitForLsass();

    /* Init Notifications */
    InitNotifications();

    /* Load and initialize gina */
    if (!GinaInit(WLSession))
    {
        ERR("WL: Failed to initialize Gina\n");
        // FIXME: Retrieve the real name of the GINA DLL we were trying to load.
        // It is known only inside the GinaInit function...
        DialogBoxParam(hAppInstance, MAKEINTRESOURCE(IDD_GINALOADFAILED), GetDesktopWindow(), GinaLoadFailedWindowProc, (LPARAM)L"msgina.dll");
        HandleShutdown(WLSession, WLX_SAS_ACTION_SHUTDOWN_REBOOT);
        ExitProcess(1);
    }

    DisplayStatusMessage(WLSession, WLSession->WinlogonDesktop, IDS_REACTOSISSTARTINGUP);

#if 0
    /* Connect to NetLogon service (lsass.exe) */
    /* Real winlogon uses "Winlogon" */
    RtlInitUnicodeString((PUNICODE_STRING)&ProcessName, L"Winlogon");
    Status = LsaRegisterLogonProcess(&ProcessName, &LsaHandle, &Mode);
    if (Status == STATUS_PORT_CONNECTION_REFUSED)
    {
        /* Add the 'SeTcbPrivilege' privilege and try again */
        Status = RtlAdjustPrivilege(SE_TCB_PRIVILEGE, TRUE, TRUE, &Old);
        if (!NT_SUCCESS(Status))
        {
            ERR("RtlAdjustPrivilege() failed with error %lu\n", LsaNtStatusToWinError(Status));
            return 1;
        }

        Status = LsaRegisterLogonProcess(&ProcessName, &LsaHandle, &Mode);
    }

    if (!NT_SUCCESS(Status))
    {
        ERR("LsaRegisterLogonProcess() failed with error %lu\n", LsaNtStatusToWinError(Status));
        return 1;
    }

    RtlInitUnicodeString((PUNICODE_STRING)&PackageName, MICROSOFT_KERBEROS_NAME_W);
    Status = LsaLookupAuthenticationPackage(LsaHandle, &PackageName, &AuthenticationPackage);
    if (!NT_SUCCESS(Status))
    {
        ERR("LsaLookupAuthenticationPackage() failed with error %lu\n", LsaNtStatusToWinError(Status));
        LsaDeregisterLogonProcess(LsaHandle);
        return 1;
    }
#endif

    CallNotificationDlls(WLSession, StartupHandler);

    /* Create a hidden window to get SAS notifications */
    if (!InitializeSAS(WLSession))
    {
        ERR("WL: Failed to initialize SAS\n");
        ExitProcess(2);
    }

    // DisplayStatusMessage(Session, Session->WinlogonDesktop, IDS_PREPARENETWORKCONNECTIONS);
    // DisplayStatusMessage(Session, Session->WinlogonDesktop, IDS_APPLYINGCOMPUTERSETTINGS);

    /* Display logged out screen */
    WLSession->LogonState = STATE_INIT;
    RemoveStatusMessage(WLSession);

    /* Check for pending setup */
    if (GetSetupType() != 0)
    {
        /* Run setup and reboot when done */
        TRACE("WL: Setup mode detected\n");
        RunSetup();
    }
    else
    {
        PostMessageW(WLSession->SASWindow, WLX_WM_SAS, WLX_SAS_TYPE_CTRL_ALT_DEL, 0);
    }

    (void)LoadLibraryW(L"sfc_os.dll");

    /* Tell kernel that CurrentControlSet is good (needed
     * to support Last good known configuration boot) */
    NtInitializeRegistry(CM_BOOT_FLAG_ACCEPTED | 1);

    /* Message loop for the SAS window */
    while (GetMessageW(&Msg, WLSession->SASWindow, 0, 0))
    {
        TranslateMessage(&Msg);
        DispatchMessageW(&Msg);
    }

    CleanupNotifications();

    /* We never go there */

    return 0;
}