Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers...
[reactos.git] / dll / win32 / advapi32 / misc / logon.c
diff --git a/dll/win32/advapi32/misc/logon.c b/dll/win32/advapi32/misc/logon.c
new file mode 100644 (file)
index 0000000..8b3b6b4
--- /dev/null
@@ -0,0 +1,608 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS system libraries
+ * FILE:        lib/advapi32/misc/logon.c
+ * PURPOSE:     Logon functions
+ * PROGRAMMER:  Eric Kohl
+ */
+
+#include <advapi32.h>
+WINE_DEFAULT_DEBUG_CHANNEL(advapi);
+
+/* GLOBALS *****************************************************************/
+
+HANDLE LsaHandle = NULL;
+ULONG AuthenticationPackage = 0;
+
+/* FUNCTIONS ***************************************************************/
+
+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;
+}
+
+
+NTSTATUS
+CloseLogonLsaHandle(VOID)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+
+    if (LsaHandle != NULL)
+    {
+        Status = LsaDeregisterLogonProcess(LsaHandle);
+        if (!NT_SUCCESS(Status))
+        {
+            TRACE("LsaDeregisterLogonProcess failed (Status 0x%08lx)\n", Status);
+        }
+    }
+
+    return Status;
+}
+
+
+/*
+ * @implemented
+ */
+BOOL WINAPI DECLSPEC_HOTPATCH
+CreateProcessAsUserA(HANDLE hToken,
+                     LPCSTR lpApplicationName,
+                     LPSTR lpCommandLine,
+                     LPSECURITY_ATTRIBUTES lpProcessAttributes,
+                     LPSECURITY_ATTRIBUTES lpThreadAttributes,
+                     BOOL bInheritHandles,
+                     DWORD dwCreationFlags,
+                     LPVOID lpEnvironment,
+                     LPCSTR lpCurrentDirectory,
+                     LPSTARTUPINFOA lpStartupInfo,
+                     LPPROCESS_INFORMATION lpProcessInformation)
+{
+    PROCESS_ACCESS_TOKEN AccessToken;
+    NTSTATUS Status;
+
+    TRACE("%p %s %s %p %p %d 0x%08x %p %s %p %p\n", hToken, debugstr_a(lpApplicationName),
+        debugstr_a(lpCommandLine), lpProcessAttributes, lpThreadAttributes, bInheritHandles,
+        dwCreationFlags, lpEnvironment, debugstr_a(lpCurrentDirectory), lpStartupInfo, lpProcessInformation);
+
+    /* Create the process with a suspended main thread */
+    if (!CreateProcessA(lpApplicationName,
+                        lpCommandLine,
+                        lpProcessAttributes,
+                        lpThreadAttributes,
+                        bInheritHandles,
+                        dwCreationFlags | CREATE_SUSPENDED,
+                        lpEnvironment,
+                        lpCurrentDirectory,
+                        lpStartupInfo,
+                        lpProcessInformation))
+    {
+        ERR("CreateProcessA failed! GLE: %d\n", GetLastError());
+        return FALSE;
+    }
+
+    if (hToken != NULL)
+    {
+        AccessToken.Token = hToken;
+        AccessToken.Thread = NULL;
+
+        /* Set the new process token */
+        Status = NtSetInformationProcess(lpProcessInformation->hProcess,
+                                         ProcessAccessToken,
+                                         (PVOID)&AccessToken,
+                                         sizeof(AccessToken));
+        if (!NT_SUCCESS (Status))
+        {
+            ERR("NtSetInformationProcess failed: 0x%08x\n", Status);
+            TerminateProcess(lpProcessInformation->hProcess, Status);
+            SetLastError(RtlNtStatusToDosError(Status));
+            return FALSE;
+        }
+    }
+
+    /* Resume the main thread */
+    if (!(dwCreationFlags & CREATE_SUSPENDED))
+    {
+        ResumeThread(lpProcessInformation->hThread);
+    }
+
+    return TRUE;
+}
+
+
+/*
+ * @implemented
+ */
+BOOL WINAPI DECLSPEC_HOTPATCH
+CreateProcessAsUserW(HANDLE hToken,
+                     LPCWSTR lpApplicationName,
+                     LPWSTR lpCommandLine,
+                     LPSECURITY_ATTRIBUTES lpProcessAttributes,
+                     LPSECURITY_ATTRIBUTES lpThreadAttributes,
+                     BOOL bInheritHandles,
+                     DWORD dwCreationFlags,
+                     LPVOID lpEnvironment,
+                     LPCWSTR lpCurrentDirectory,
+                     LPSTARTUPINFOW lpStartupInfo,
+                     LPPROCESS_INFORMATION lpProcessInformation)
+{
+    PROCESS_ACCESS_TOKEN AccessToken;
+    NTSTATUS Status;
+
+    TRACE("%p %s %s %p %p %d 0x%08x %p %s %p %p\n", hToken, debugstr_w(lpApplicationName),
+        debugstr_w(lpCommandLine), lpProcessAttributes, lpThreadAttributes, bInheritHandles,
+        dwCreationFlags, lpEnvironment, debugstr_w(lpCurrentDirectory), lpStartupInfo, lpProcessInformation);
+
+    /* Create the process with a suspended main thread */
+    if (!CreateProcessW(lpApplicationName,
+                        lpCommandLine,
+                        lpProcessAttributes,
+                        lpThreadAttributes,
+                        bInheritHandles,
+                        dwCreationFlags | CREATE_SUSPENDED,
+                        lpEnvironment,
+                        lpCurrentDirectory,
+                        lpStartupInfo,
+                        lpProcessInformation))
+    {
+        ERR("CreateProcessW failed! GLE: %d\n", GetLastError());
+        return FALSE;
+    }
+
+    if (hToken != NULL)
+    {
+        AccessToken.Token = hToken;
+        AccessToken.Thread = NULL;
+
+        /* Set the new process token */
+        Status = NtSetInformationProcess(lpProcessInformation->hProcess,
+                                         ProcessAccessToken,
+                                         (PVOID)&AccessToken,
+                                         sizeof(AccessToken));
+        if (!NT_SUCCESS (Status))
+        {
+            ERR("NtSetInformationProcess failed: 0x%08x\n", Status);
+            TerminateProcess(lpProcessInformation->hProcess, Status);
+            SetLastError(RtlNtStatusToDosError(Status));
+            return FALSE;
+        }
+    }
+
+    /* Resume the main thread */
+    if (!(dwCreationFlags & CREATE_SUSPENDED))
+    {
+        ResumeThread(lpProcessInformation->hThread);
+    }
+
+    return TRUE;
+}
+
+
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+LogonUserA(
+    _In_ LPSTR lpszUsername,
+    _In_opt_ LPSTR lpszDomain,
+    _In_opt_ LPSTR lpszPassword,
+    _In_ DWORD dwLogonType,
+    _In_ DWORD dwLogonProvider,
+    _Out_opt_ PHANDLE phToken)
+{
+    return LogonUserExA(lpszUsername,
+                        lpszDomain,
+                        lpszPassword,
+                        dwLogonType,
+                        dwLogonProvider,
+                        phToken,
+                        NULL,
+                        NULL,
+                        NULL,
+                        NULL);
+}
+
+
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+LogonUserExA(
+    _In_ LPSTR lpszUsername,
+    _In_opt_ LPSTR lpszDomain,
+    _In_opt_ LPSTR lpszPassword,
+    _In_ DWORD dwLogonType,
+    _In_ DWORD dwLogonProvider,
+    _Out_opt_ PHANDLE phToken,
+    _Out_opt_ PSID *ppLogonSid,
+    _Out_opt_ PVOID *ppProfileBuffer,
+    _Out_opt_ LPDWORD pdwProfileLength,
+    _Out_opt_ PQUOTA_LIMITS pQuotaLimits)
+{
+    UNICODE_STRING UserName;
+    UNICODE_STRING Domain;
+    UNICODE_STRING Password;
+    BOOL ret = FALSE;
+
+    UserName.Buffer = NULL;
+    Domain.Buffer = NULL;
+    Password.Buffer = NULL;
+
+    if (!RtlCreateUnicodeStringFromAsciiz(&UserName, lpszUsername))
+    {
+        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+        goto UsernameDone;
+    }
+
+    if (!RtlCreateUnicodeStringFromAsciiz(&Domain, lpszDomain))
+    {
+        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+        goto DomainDone;
+    }
+
+    if (!RtlCreateUnicodeStringFromAsciiz(&Password, lpszPassword))
+    {
+        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+        goto PasswordDone;
+    }
+
+    ret = LogonUserExW(UserName.Buffer,
+                       Domain.Buffer,
+                       Password.Buffer,
+                       dwLogonType,
+                       dwLogonProvider,
+                       phToken,
+                       ppLogonSid,
+                       ppProfileBuffer,
+                       pdwProfileLength,
+                       pQuotaLimits);
+
+    if (Password.Buffer != NULL)
+        RtlFreeUnicodeString(&Password);
+
+PasswordDone:
+    if (Domain.Buffer != NULL)
+        RtlFreeUnicodeString(&Domain);
+
+DomainDone:
+    if (UserName.Buffer != NULL)
+        RtlFreeUnicodeString(&UserName);
+
+UsernameDone:
+    return ret;
+}
+
+
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+LogonUserW(
+    _In_ LPWSTR lpszUsername,
+    _In_opt_ LPWSTR lpszDomain,
+    _In_opt_ LPWSTR lpszPassword,
+    _In_ DWORD dwLogonType,
+    _In_ DWORD dwLogonProvider,
+    _Out_opt_ PHANDLE phToken)
+{
+    return LogonUserExW(lpszUsername,
+                        lpszDomain,
+                        lpszPassword,
+                        dwLogonType,
+                        dwLogonProvider,
+                        phToken,
+                        NULL,
+                        NULL,
+                        NULL,
+                        NULL);
+}
+
+
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+LogonUserExW(
+    _In_ LPWSTR lpszUsername,
+    _In_opt_ LPWSTR lpszDomain,
+    _In_opt_ LPWSTR lpszPassword,
+    _In_ DWORD dwLogonType,
+    _In_ DWORD dwLogonProvider,
+    _Out_opt_ PHANDLE phToken,
+    _Out_opt_ PSID *ppLogonSid,
+    _Out_opt_ PVOID *ppProfileBuffer,
+    _Out_opt_ LPDWORD pdwProfileLength,
+    _Out_opt_ PQUOTA_LIMITS pQuotaLimits)
+{
+    SID_IDENTIFIER_AUTHORITY LocalAuthority = {SECURITY_LOCAL_SID_AUTHORITY};
+    SID_IDENTIFIER_AUTHORITY SystemAuthority = {SECURITY_NT_AUTHORITY};
+    PSID LogonSid = NULL;
+    PSID LocalSid = NULL;
+    LSA_STRING OriginName;
+    UNICODE_STRING DomainName;
+    UNICODE_STRING UserName;
+    UNICODE_STRING Password;
+    PMSV1_0_INTERACTIVE_LOGON AuthInfo = NULL;
+    ULONG AuthInfoLength;
+    ULONG_PTR Ptr;
+    TOKEN_SOURCE TokenSource;
+    PTOKEN_GROUPS TokenGroups = NULL;
+    PMSV1_0_INTERACTIVE_PROFILE ProfileBuffer = NULL;
+    ULONG ProfileBufferLength = 0;
+    LUID Luid = {0, 0};
+    LUID LogonId = {0, 0};
+    HANDLE TokenHandle = NULL;
+    QUOTA_LIMITS QuotaLimits;
+    SECURITY_LOGON_TYPE LogonType;
+    NTSTATUS SubStatus = STATUS_SUCCESS;
+    NTSTATUS Status;
+
+    *phToken = NULL;
+
+    switch (dwLogonType)
+    {
+        case LOGON32_LOGON_INTERACTIVE:
+            LogonType = Interactive;
+            break;
+
+        case LOGON32_LOGON_NETWORK:
+            LogonType = Network;
+            break;
+
+        case LOGON32_LOGON_BATCH:
+            LogonType = Batch;
+            break;
+
+        case LOGON32_LOGON_SERVICE:
+            LogonType = Service;
+            break;
+
+       default:
+            ERR("Invalid logon type: %ul\n", dwLogonType);
+            Status = STATUS_INVALID_PARAMETER;
+            goto done;
+    }
+
+    if (LsaHandle == NULL)
+    {
+        Status = OpenLogonLsaHandle();
+        if (!NT_SUCCESS(Status))
+            goto done;
+    }
+
+    RtlInitAnsiString((PANSI_STRING)&OriginName,
+                      "Advapi32 Logon");
+
+    RtlInitUnicodeString(&DomainName,
+                         lpszDomain);
+
+    RtlInitUnicodeString(&UserName,
+                         lpszUsername);
+
+    RtlInitUnicodeString(&Password,
+                         lpszPassword);
+
+    AuthInfoLength = sizeof(MSV1_0_INTERACTIVE_LOGON)+
+                     DomainName.MaximumLength +
+                     UserName.MaximumLength +
+                     Password.MaximumLength;
+
+    AuthInfo = RtlAllocateHeap(RtlGetProcessHeap(),
+                               HEAP_ZERO_MEMORY,
+                               AuthInfoLength);
+    if (AuthInfo == NULL)
+    {
+        Status = STATUS_INSUFFICIENT_RESOURCES;
+        goto done;
+    }
+
+    AuthInfo->MessageType = MsV1_0InteractiveLogon;
+
+    Ptr = (ULONG_PTR)AuthInfo + sizeof(MSV1_0_INTERACTIVE_LOGON);
+
+    AuthInfo->LogonDomainName.Length = DomainName.Length;
+    AuthInfo->LogonDomainName.MaximumLength = DomainName.MaximumLength;
+    AuthInfo->LogonDomainName.Buffer = (DomainName.Buffer == NULL) ? NULL : (PWCHAR)Ptr;
+    if (DomainName.MaximumLength > 0)
+    {
+        RtlCopyMemory(AuthInfo->LogonDomainName.Buffer,
+                      DomainName.Buffer,
+                      DomainName.MaximumLength);
+
+        Ptr += DomainName.MaximumLength;
+    }
+
+    AuthInfo->UserName.Length = UserName.Length;
+    AuthInfo->UserName.MaximumLength = UserName.MaximumLength;
+    AuthInfo->UserName.Buffer = (PWCHAR)Ptr;
+    if (UserName.MaximumLength > 0)
+        RtlCopyMemory(AuthInfo->UserName.Buffer,
+                      UserName.Buffer,
+                      UserName.MaximumLength);
+
+    Ptr += UserName.MaximumLength;
+
+    AuthInfo->Password.Length = Password.Length;
+    AuthInfo->Password.MaximumLength = Password.MaximumLength;
+    AuthInfo->Password.Buffer = (PWCHAR)Ptr;
+    if (Password.MaximumLength > 0)
+        RtlCopyMemory(AuthInfo->Password.Buffer,
+                      Password.Buffer,
+                      Password.MaximumLength);
+
+    /* Create the Logon SID*/
+    AllocateLocallyUniqueId(&LogonId);
+    Status = RtlAllocateAndInitializeSid(&SystemAuthority,
+                                         SECURITY_LOGON_IDS_RID_COUNT,
+                                         SECURITY_LOGON_IDS_RID,
+                                         LogonId.HighPart,
+                                         LogonId.LowPart,
+                                         SECURITY_NULL_RID,
+                                         SECURITY_NULL_RID,
+                                         SECURITY_NULL_RID,
+                                         SECURITY_NULL_RID,
+                                         SECURITY_NULL_RID,
+                                         &LogonSid);
+    if (!NT_SUCCESS(Status))
+        goto done;
+
+    /* Create the Local SID*/
+    Status = RtlAllocateAndInitializeSid(&LocalAuthority,
+                                         1,
+                                         SECURITY_LOCAL_RID,
+                                         SECURITY_NULL_RID,
+                                         SECURITY_NULL_RID,
+                                         SECURITY_NULL_RID,
+                                         SECURITY_NULL_RID,
+                                         SECURITY_NULL_RID,
+                                         SECURITY_NULL_RID,
+                                         SECURITY_NULL_RID,
+                                         &LocalSid);
+    if (!NT_SUCCESS(Status))
+        goto done;
+
+    /* Allocate and set the token groups */
+    TokenGroups = RtlAllocateHeap(RtlGetProcessHeap(),
+                                  HEAP_ZERO_MEMORY,
+                                  sizeof(TOKEN_GROUPS) + ((2 - ANYSIZE_ARRAY) * sizeof(SID_AND_ATTRIBUTES)));
+    if (TokenGroups == NULL)
+    {
+        Status = STATUS_INSUFFICIENT_RESOURCES;
+        goto done;
+    }
+
+    TokenGroups->GroupCount = 2;
+    TokenGroups->Groups[0].Sid = LogonSid;
+    TokenGroups->Groups[0].Attributes = SE_GROUP_MANDATORY | SE_GROUP_ENABLED |
+                                        SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_LOGON_ID;
+    TokenGroups->Groups[1].Sid = LocalSid;
+    TokenGroups->Groups[1].Attributes = SE_GROUP_MANDATORY | SE_GROUP_ENABLED |
+                                        SE_GROUP_ENABLED_BY_DEFAULT;
+
+    /* Set the token source */
+    strncpy(TokenSource.SourceName, "Advapi  ", sizeof(TokenSource.SourceName));
+    AllocateLocallyUniqueId(&TokenSource.SourceIdentifier);
+
+    Status = LsaLogonUser(LsaHandle,
+                          &OriginName,
+                          LogonType,
+                          AuthenticationPackage,
+                          (PVOID)AuthInfo,
+                          AuthInfoLength,
+                          TokenGroups,
+                          &TokenSource,
+                          (PVOID*)&ProfileBuffer,
+                          &ProfileBufferLength,
+                          &Luid,
+                          &TokenHandle,
+                          &QuotaLimits,
+                          &SubStatus);
+    if (!NT_SUCCESS(Status))
+    {
+        ERR("LsaLogonUser failed (Status 0x%08lx)\n", Status);
+        goto done;
+    }
+
+    if (ProfileBuffer != NULL)
+    {
+        TRACE("ProfileBuffer: %p\n", ProfileBuffer);
+        TRACE("MessageType: %u\n", ProfileBuffer->MessageType);
+
+        TRACE("FullName: %p\n", ProfileBuffer->FullName.Buffer);
+        TRACE("FullName: %S\n", ProfileBuffer->FullName.Buffer);
+
+        TRACE("LogonServer: %p\n", ProfileBuffer->LogonServer.Buffer);
+        TRACE("LogonServer: %S\n", ProfileBuffer->LogonServer.Buffer);
+    }
+
+    TRACE("Luid: 0x%08lx%08lx\n", Luid.HighPart, Luid.LowPart);
+
+    if (TokenHandle != NULL)
+    {
+        TRACE("TokenHandle: %p\n", TokenHandle);
+    }
+
+    *phToken = TokenHandle;
+
+    /* FIXME: return ppLogonSid, ppProfileBuffer, pdwProfileLength and pQuotaLimits */
+
+done:
+    if (ProfileBuffer != NULL)
+        LsaFreeReturnBuffer(ProfileBuffer);
+
+    if (!NT_SUCCESS(Status))
+    {
+        if (TokenHandle != NULL)
+            CloseHandle(TokenHandle);
+    }
+
+    if (TokenGroups != NULL)
+        RtlFreeHeap(RtlGetProcessHeap(), 0, TokenGroups);
+
+    if (LocalSid != NULL)
+        RtlFreeSid(LocalSid);
+
+    if (LogonSid != NULL)
+        RtlFreeSid(LogonSid);
+
+    if (AuthInfo != NULL)
+        RtlFreeHeap(RtlGetProcessHeap(), 0, AuthInfo);
+
+    if (!NT_SUCCESS(Status))
+    {
+        SetLastError(RtlNtStatusToDosError(Status));
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+/* EOF */