Remove outdated profile path postfix.
[reactos.git] / reactos / lib / userenv / profile.c
index 951ddc6..b81ec8b 100644 (file)
@@ -1,4 +1,22 @@
-/* $Id: profile.c,v 1.3 2004/01/16 15:31:53 ekohl Exp $
+/*
+ *  ReactOS kernel
+ *  Copyright (C) 2004 ReactOS Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/* $Id: profile.c,v 1.15 2004/10/05 13:39:42 ekohl Exp $
  *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS system libraries
@@ -7,13 +25,7 @@
  * PROGRAMMER:      Eric Kohl
  */
 
-#include <ntos.h>
-#include <windows.h>
-#include <string.h>
-
-#include <userenv.h>
-
-#include "internal.h"
+#include "precomp.h"
 
 
 /* FUNCTIONS ***************************************************************/
@@ -23,10 +35,8 @@ AppendSystemPostfix (LPWSTR lpName,
                     DWORD dwMaxLength)
 {
   WCHAR szSystemRoot[MAX_PATH];
-  WCHAR szDrivePostfix[3];
   LPWSTR lpszPostfix;
   LPWSTR lpszPtr;
-  DWORD dwPostfixLength;
 
   /* Build profile name postfix */
   if (!ExpandEnvironmentStringsW (L"%SystemRoot%",
@@ -50,28 +60,40 @@ AppendSystemPostfix (LPWSTR lpName,
       lpszPtr++;
     }
 
-  dwPostfixLength = wcslen (lpszPostfix);
-  if (szSystemRoot[0] != L'C')
-    {
-      dwPostfixLength += 2;
-      szDrivePostfix[0] = L'_';
-      szDrivePostfix[1] = szSystemRoot[0];
-      szDrivePostfix[2] = (WCHAR)0;
-    }
-
-  if (wcslen (lpName) + dwPostfixLength >= dwMaxLength)
+  if (wcslen(lpName) + wcslen(lpszPostfix) >= dwMaxLength)
     {
       DPRINT1("Error: buffer overflow\n");
       return FALSE;
     }
 
-  wcscat (lpName, lpszPostfix);
-  if (szSystemRoot[0] != L'C')
+  wcscat(lpName, lpszPostfix);
+
+  return TRUE;
+}
+
+
+BOOL WINAPI
+CreateUserProfileA (PSID Sid,
+                   LPCSTR lpUserName)
+{
+  UNICODE_STRING UserName;
+  BOOL bResult;
+  NTSTATUS Status;
+
+  Status = RtlCreateUnicodeStringFromAsciiz (&UserName,
+                                            (LPSTR)lpUserName);
+  if (!NT_SUCCESS(Status))
     {
-      wcscat (lpName, szDrivePostfix);
+      SetLastError (RtlNtStatusToDosError (Status));
+      return FALSE;
     }
 
-  return TRUE;
+  bResult = CreateUserProfileW (Sid,
+                               UserName.Buffer);
+
+  RtlFreeUnicodeString (&UserName);
+
+  return bResult;
 }
 
 
@@ -90,6 +112,7 @@ CreateUserProfileW (PSID Sid,
   HKEY hKey;
   NTSTATUS Status;
 
+  DPRINT("CreateUserProfileW() called\n");
 
   if (RegOpenKeyExW (HKEY_LOCAL_MACHINE,
                     L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
@@ -244,21 +267,21 @@ CreateUserProfileW (PSID Sid,
   RegCloseKey (hKey);
 
   /* Create user hive name */
-  wcscat (szUserProfilePath, L"\\ntuser.dat");
+  wcscpy (szBuffer, szUserProfilePath);
+  wcscat (szBuffer, L"\\ntuser.dat");
 
-#if 0
   /* Create new user hive */
   if (RegLoadKeyW (HKEY_USERS,
                   SidString.Buffer,
-                  szUserProfilePath))
+                  szBuffer))
     {
       DPRINT1("Error: %lu\n", GetLastError());
       RtlFreeUnicodeString (&SidString);
       return FALSE;
     }
 
-  /* Create user hive */
-  if (!CreateUserHive (SidString.Buffer))
+  /* Initialize user hive */
+  if (!CreateUserHive (SidString.Buffer, szUserProfilePath))
     {
       DPRINT1("Error: %lu\n", GetLastError());
       RtlFreeUnicodeString (&SidString);
@@ -267,14 +290,47 @@ CreateUserProfileW (PSID Sid,
 
   RegUnLoadKeyW (HKEY_USERS,
                 SidString.Buffer);
-#endif
 
   RtlFreeUnicodeString (&SidString);
 
+  DPRINT("CreateUserProfileW() done\n");
+
   return TRUE;
 }
 
 
+BOOL WINAPI
+GetAllUsersProfileDirectoryA (LPSTR lpProfileDir,
+                             LPDWORD lpcchSize)
+{
+  LPWSTR lpBuffer;
+  BOOL bResult;
+
+  lpBuffer = GlobalAlloc (GMEM_FIXED,
+                         *lpcchSize * sizeof(WCHAR));
+  if (lpBuffer == NULL)
+    return FALSE;
+
+  bResult = GetAllUsersProfileDirectoryW (lpBuffer,
+                                         lpcchSize);
+  if (bResult)
+    {
+      WideCharToMultiByte (CP_ACP,
+                          0,
+                          lpBuffer,
+                          -1,
+                          lpProfileDir,
+                          *lpcchSize,
+                          NULL,
+                          NULL);
+    }
+
+  GlobalFree (lpBuffer);
+
+  return bResult;
+}
+
+
 BOOL WINAPI
 GetAllUsersProfileDirectoryW (LPWSTR lpProfileDir,
                              LPDWORD lpcchSize)
@@ -356,6 +412,38 @@ GetAllUsersProfileDirectoryW (LPWSTR lpProfileDir,
 }
 
 
+BOOL WINAPI
+GetDefaultUserProfileDirectoryA (LPSTR lpProfileDir,
+                                LPDWORD lpcchSize)
+{
+  LPWSTR lpBuffer;
+  BOOL bResult;
+
+  lpBuffer = GlobalAlloc (GMEM_FIXED,
+                         *lpcchSize * sizeof(WCHAR));
+  if (lpBuffer == NULL)
+    return FALSE;
+
+  bResult = GetDefaultUserProfileDirectoryW (lpBuffer,
+                                            lpcchSize);
+  if (bResult)
+    {
+      WideCharToMultiByte (CP_ACP,
+                          0,
+                          lpBuffer,
+                          -1,
+                          lpProfileDir,
+                          *lpcchSize,
+                          NULL,
+                          NULL);
+    }
+
+  GlobalFree (lpBuffer);
+
+  return bResult;
+}
+
+
 BOOL WINAPI
 GetDefaultUserProfileDirectoryW (LPWSTR lpProfileDir,
                                 LPDWORD lpcchSize)
@@ -437,6 +525,38 @@ GetDefaultUserProfileDirectoryW (LPWSTR lpProfileDir,
 }
 
 
+BOOL WINAPI
+GetProfilesDirectoryA (LPSTR lpProfileDir,
+                      LPDWORD lpcchSize)
+{
+  LPWSTR lpBuffer;
+  BOOL bResult;
+
+  lpBuffer = GlobalAlloc (GMEM_FIXED,
+                         *lpcchSize * sizeof(WCHAR));
+  if (lpBuffer == NULL)
+    return FALSE;
+
+  bResult = GetProfilesDirectoryW (lpBuffer,
+                                  lpcchSize);
+  if (bResult)
+    {
+      WideCharToMultiByte (CP_ACP,
+                          0,
+                          lpBuffer,
+                          -1,
+                          lpProfileDir,
+                          *lpcchSize,
+                          NULL,
+                          NULL);
+    }
+
+  GlobalFree (lpBuffer);
+
+  return bResult;
+}
+
+
 BOOL WINAPI
 GetProfilesDirectoryW (LPWSTR lpProfilesDir,
                       LPDWORD lpcchSize)
@@ -500,13 +620,292 @@ GetProfilesDirectoryW (LPWSTR lpProfilesDir,
 }
 
 
+BOOL WINAPI
+GetUserProfileDirectoryA (HANDLE hToken,
+                         LPSTR lpProfileDir,
+                         LPDWORD lpcchSize)
+{
+  LPWSTR lpBuffer;
+  BOOL bResult;
+
+  lpBuffer = GlobalAlloc (GMEM_FIXED,
+                         *lpcchSize * sizeof(WCHAR));
+  if (lpBuffer == NULL)
+    return FALSE;
+
+  bResult = GetUserProfileDirectoryW (hToken,
+                                     lpBuffer,
+                                     lpcchSize);
+  if (bResult)
+    {
+      WideCharToMultiByte (CP_ACP,
+                          0,
+                          lpBuffer,
+                          -1,
+                          lpProfileDir,
+                          *lpcchSize,
+                          NULL,
+                          NULL);
+    }
+
+  GlobalFree (lpBuffer);
+
+  return bResult;
+}
+
+
 BOOL WINAPI
 GetUserProfileDirectoryW (HANDLE hToken,
                          LPWSTR lpProfileDir,
                          LPDWORD lpcchSize)
 {
-  /* FIXME */
-  return GetDefaultUserProfileDirectoryW (lpProfileDir, lpcchSize);
+  UNICODE_STRING SidString;
+  WCHAR szKeyName[MAX_PATH];
+  WCHAR szRawImagePath[MAX_PATH];
+  WCHAR szImagePath[MAX_PATH];
+  DWORD dwLength;
+  HKEY hKey;
+
+  if (!GetUserSidFromToken (hToken,
+                           &SidString))
+    {
+      DPRINT1 ("GetUserSidFromToken() failed\n");
+      return FALSE;
+    }
+
+  DPRINT ("SidString: '%wZ'\n", &SidString);
+
+  wcscpy (szKeyName,
+         L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\");
+  wcscat (szKeyName,
+         SidString.Buffer);
+
+  RtlFreeUnicodeString (&SidString);
+
+  DPRINT ("KeyName: '%S'\n", szKeyName);
+
+  if (RegOpenKeyExW (HKEY_LOCAL_MACHINE,
+                    szKeyName,
+                    0,
+                    KEY_ALL_ACCESS,
+                    &hKey))
+    {
+      DPRINT1 ("Error: %lu\n", GetLastError());
+      return FALSE;
+    }
+
+  dwLength = MAX_PATH * sizeof(WCHAR);
+  if (RegQueryValueExW (hKey,
+                       L"ProfileImagePath",
+                       NULL,
+                       NULL,
+                       (LPBYTE)szRawImagePath,
+                       &dwLength))
+    {
+      DPRINT1 ("Error: %lu\n", GetLastError());
+      RegCloseKey (hKey);
+      return FALSE;
+    }
+
+  RegCloseKey (hKey);
+
+  DPRINT ("RawImagePath: '%S'\n", szRawImagePath);
+
+  /* Expand it */
+  if (!ExpandEnvironmentStringsW (szRawImagePath,
+                                 szImagePath,
+                                 MAX_PATH))
+    {
+      DPRINT1 ("Error: %lu\n", GetLastError());
+      return FALSE;
+    }
+
+  DPRINT ("ImagePath: '%S'\n", szImagePath);
+
+  dwLength = wcslen (szImagePath);
+  if (dwLength > *lpcchSize)
+    {
+      DPRINT1 ("Buffer too small\n");
+      SetLastError (ERROR_INSUFFICIENT_BUFFER);
+      return FALSE;
+    }
+
+  *lpcchSize = dwLength;
+  wcscpy (lpProfileDir,
+         szImagePath);
+
+  return TRUE;
+}
+
+
+static BOOL
+CheckForLoadedProfile (HANDLE hToken)
+{
+  UNICODE_STRING SidString;
+  HKEY hKey;
+
+  DPRINT ("CheckForLoadedProfile() called \n");
+
+  if (!GetUserSidFromToken (hToken,
+                           &SidString))
+    {
+      DPRINT1 ("GetUserSidFromToken() failed\n");
+      return FALSE;
+    }
+
+  if (RegOpenKeyExW (HKEY_USERS,
+                    SidString.Buffer,
+                    0,
+                    KEY_ALL_ACCESS,
+                    &hKey))
+    {
+      DPRINT ("Profile not loaded\n");
+      RtlFreeUnicodeString (&SidString);
+      return FALSE;
+    }
+
+  RegCloseKey (hKey);
+
+  RtlFreeUnicodeString (&SidString);
+
+  DPRINT ("Profile already loaded\n");
+
+  return TRUE;
+}
+
+
+BOOL WINAPI
+LoadUserProfileA (HANDLE hToken,
+                 LPPROFILEINFOA lpProfileInfo)
+{
+  DPRINT ("LoadUserProfileA() not implemented\n");
+  return FALSE;
+}
+
+
+BOOL WINAPI
+LoadUserProfileW (HANDLE hToken,
+                 LPPROFILEINFOW lpProfileInfo)
+{
+  WCHAR szUserHivePath[MAX_PATH];
+  UNICODE_STRING SidString;
+  DWORD dwLength;
+
+  DPRINT ("LoadUserProfileW() called\n");
+
+  /* Check profile info */
+  if (lpProfileInfo->dwSize != sizeof(PROFILEINFOW) ||
+      lpProfileInfo->lpUserName == NULL ||
+      lpProfileInfo->lpUserName[0] == 0)
+    {
+      SetLastError (ERROR_INVALID_PARAMETER);
+      return FALSE;
+    }
+
+  /* Don't load a profile twice */
+  if (CheckForLoadedProfile (hToken))
+    {
+      DPRINT ("Profile already loaded\n");
+      lpProfileInfo->hProfile = NULL;
+      return TRUE;
+    }
+
+  if (!GetProfilesDirectoryW (szUserHivePath,
+                             &dwLength))
+    {
+      DPRINT1("GetProfilesDirectoryW() failed\n", GetLastError());
+      return FALSE;
+    }
+
+  wcscat (szUserHivePath, L"\\");
+  wcscat (szUserHivePath, lpProfileInfo->lpUserName);
+  if (!AppendSystemPostfix (szUserHivePath, MAX_PATH))
+    {
+      DPRINT1("AppendSystemPostfix() failed\n", GetLastError());
+      return FALSE;
+    }
+
+  /* Create user hive name */
+  wcscat (szUserHivePath, L"\\ntuser.dat");
+
+  DPRINT ("szUserHivePath: %S\n", szUserHivePath);
+
+  if (!GetUserSidFromToken (hToken,
+                           &SidString))
+    {
+      DPRINT1 ("GetUserSidFromToken() failed\n");
+      return FALSE;
+    }
+
+  DPRINT ("SidString: '%wZ'\n", &SidString);
+
+  if (RegLoadKeyW (HKEY_USERS,
+                  SidString.Buffer,
+                  szUserHivePath))
+    {
+      DPRINT1 ("RegLoadKeyW() failed (Error %ld)\n", GetLastError());
+      RtlFreeUnicodeString (&SidString);
+      return FALSE;
+    }
+
+  if (RegOpenKeyExW (HKEY_USERS,
+                    SidString.Buffer,
+                    0,
+                    KEY_ALL_ACCESS,
+                    (PHKEY)&lpProfileInfo->hProfile))
+    {
+      DPRINT1 ("RegOpenKeyExW() failed (Error %ld)\n", GetLastError());
+      RtlFreeUnicodeString (&SidString);
+      return FALSE;
+    }
+
+  RtlFreeUnicodeString (&SidString);
+
+  DPRINT ("LoadUserProfileW() done\n");
+
+  return TRUE;
+}
+
+
+BOOL WINAPI
+UnloadUserProfile (HANDLE hToken,
+                  HANDLE hProfile)
+{
+  UNICODE_STRING SidString;
+
+  DPRINT ("UnloadUserProfile() called\n");
+
+  if (hProfile == NULL)
+    {
+      DPRINT1 ("Invalide profile handle\n");
+      SetLastError (ERROR_INVALID_PARAMETER);
+      return FALSE;
+    }
+
+  RegCloseKey (hProfile);
+
+  if (!GetUserSidFromToken (hToken,
+                           &SidString))
+    {
+      DPRINT1 ("GetUserSidFromToken() failed\n");
+      return FALSE;
+    }
+
+  DPRINT ("SidString: '%wZ'\n", &SidString);
+
+  if (RegUnLoadKeyW (HKEY_USERS,
+                    SidString.Buffer))
+    {
+      DPRINT1 ("RegUnLoadKeyW() failed (Error %ld)\n", GetLastError());
+      RtlFreeUnicodeString (&SidString);
+      return FALSE;
+    }
+
+  RtlFreeUnicodeString (&SidString);
+
+  DPRINT ("UnloadUserProfile() done\n");
+
+  return TRUE;
 }
 
 /* EOF */