profile.c
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 79k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. //*************************************************************
  2. //
  3. //  Profile.c   - User Profile tab
  4. //
  5. //  Microsoft Confidential
  6. //  Copyright (c) Microsoft Corporation 1996
  7. //  All rights reserved
  8. //
  9. //*************************************************************
  10. #include <nt.h>
  11. #include <ntrtl.h>
  12. #include <nturtl.h>
  13. #include "sysdm.h"
  14. #include <shellapi.h>
  15. #include <shlobj.h>
  16. #include <shlobjp.h>
  17. #include <userenv.h>
  18. #include <userenvp.h>
  19. #include <getuser.h>
  20. #define TEMP_PROFILE                 TEXT("Temp profile (sysdm.cpl)")
  21. #define PROFILE_MAPPING              TEXT("Software\Microsoft\Windows NT\CurrentVersion\ProfileList")
  22. #define WINLOGON_KEY                 TEXT("Software\Microsoft\Windows NT\CurrentVersion\Winlogon")
  23. #define SYSTEM_POLICIES_KEY          TEXT("Software\Policies\Microsoft\Windows\System")
  24. #define PRF_USERSID                  1
  25. //
  26. // Globals
  27. //
  28. const TCHAR c_szNTUserIni[] = TEXT("ntuser.ini");
  29. #define PROFILE_GENERAL_SECTION      TEXT("General")
  30. #define PROFILE_EXCLUSION_LIST       TEXT("ExclusionList")
  31. DWORD g_dwProfileSize;
  32. //
  33. // Help ID's
  34. //
  35. // IDH_USERPROFILE + 20 is used in the OpenUserBrowser routine.
  36. //
  37. DWORD aUserProfileHelpIds[] = {
  38.     IDC_UP_LISTVIEW,              (IDH_USERPROFILE + 0),
  39.     IDC_UP_DELETE,                (IDH_USERPROFILE + 1),
  40.     IDC_UP_TYPE,                  (IDH_USERPROFILE + 2),
  41.     IDC_UP_COPY,                  (IDH_USERPROFILE + 3),
  42.     IDC_UP_ICON,                  (DWORD) -1,
  43.     IDC_UP_TEXT,                  (DWORD) -1,
  44.     // Change Type dialog
  45.     IDC_UPTYPE_LOCAL,             (IDH_USERPROFILE + 4),
  46.     IDC_UPTYPE_FLOAT,             (IDH_USERPROFILE + 5),
  47.     IDC_UPTYPE_SLOW,              (IDH_USERPROFILE + 6),
  48.     IDC_UPTYPE_SLOW_TEXT,         (IDH_USERPROFILE + 6),
  49.     IDC_UPTYPE_GROUP,             (IDH_USERPROFILE + 12),
  50.     // Copy To dialog
  51.     IDC_COPY_PATH,                (IDH_USERPROFILE + 7),
  52.     IDC_COPY_BROWSE,              (IDH_USERPROFILE + 8),
  53.     IDC_COPY_USER,                (IDH_USERPROFILE + 9),
  54.     IDC_COPY_CHANGE,              (IDH_USERPROFILE + 10),
  55.     IDC_COPY_GROUP,               (IDH_USERPROFILE + 9),
  56.     0, 0
  57. };
  58. //
  59. // Local function proto-types
  60. //
  61. BOOL InitUserProfileDlg (HWND hDlg, LPARAM lParam);
  62. BOOL FillListView (HWND hDlg, BOOL bAdmin);
  63. LPTSTR CheckSlash (LPTSTR lpDir);
  64. BOOL RecurseDirectory (LPTSTR lpDir, LPTSTR lpExcludeList);
  65. VOID UPSave (HWND hDlg);
  66. VOID UPCleanUp (HWND hDlg);
  67. BOOL IsProfileInUse (LPTSTR lpSid);
  68. void UPDoItemChanged(HWND hDlg, int idCtl);
  69. void UPDeleteProfile(HWND hDlg);
  70. BOOL DeleteProfile (LPTSTR lpSidString, LPTSTR lpLocalProfile);
  71. void UPChangeType(HWND hDlg);
  72. INT_PTR APIENTRY ChangeTypeDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
  73. void UPCopyProfile(HWND hDlg);
  74. INT_PTR APIENTRY UPCopyDlgProc (HWND hDlg, UINT uMsg,WPARAM wParam, LPARAM lParam);
  75. BOOL UPCreateProfile (LPUPCOPYINFO lpUPCopyInfo, LPTSTR lpDest, PSECURITY_DESCRIPTOR pSecDesc);
  76. VOID UPDisplayErrorMessage(HWND hWnd, UINT uiSystemError);
  77. BOOL ApplyHiveSecurity(LPTSTR lpHiveName, PSID pSid);
  78. LPTSTR CheckSemicolon (LPTSTR lpDir);
  79. LPTSTR ConvertExclusionList (LPCTSTR lpSourceDir, LPCTSTR lpExclusionList);
  80. BOOL ReadExclusionList(LPTSTR szExcludeList, DWORD dwExclSize);
  81. BOOL ReadExclusionListFromIniFile(LPCTSTR lpSourceDir, LPTSTR szExcludeList, DWORD dwExclSize);
  82. //*************************************************************
  83. //
  84. //  CreateProfilePage()
  85. //
  86. //  Purpose:    Creates the profile page
  87. //
  88. //  Parameters: hInst   -   hInstance
  89. //
  90. //
  91. //  Return:     hPage if successful
  92. //              NULL if an error occurs
  93. //
  94. //  Comments:
  95. //
  96. //  History:    Date        Author     Comment
  97. //              10/11/95    ericflo    Created
  98. //
  99. //*************************************************************
  100. HPROPSHEETPAGE CreateProfilePage (HINSTANCE hInst)
  101. {
  102.     PROPSHEETPAGE psp;
  103.     psp.dwSize = sizeof(PROPSHEETPAGE);
  104.     psp.dwFlags = 0;
  105.     psp.hInstance = hInst;
  106.     psp.pszTemplate = MAKEINTRESOURCE(IDD_USERPROFILE);
  107.     psp.pfnDlgProc = UserProfileDlgProc;
  108.     psp.pszTitle = NULL;
  109.     psp.lParam = 0;
  110.     return CreatePropertySheetPage(&psp);
  111. }
  112. //*************************************************************
  113. //
  114. //  UserProfileDlgProc()
  115. //
  116. //  Purpose:    Dialog box procedure for profile tab
  117. //
  118. //  Parameters: hDlg    -   handle to the dialog box
  119. //              uMsg    -   window message
  120. //              wParam  -   wParam
  121. //              lParam  -   lParam
  122. //
  123. //  Return:     TRUE if message was processed
  124. //              FALSE if not
  125. //
  126. //  Comments:
  127. //
  128. //  History:    Date        Author     Comment
  129. //              10/11/95    ericflo    Created
  130. //
  131. //*************************************************************
  132. INT_PTR APIENTRY UserProfileDlgProc (HWND hDlg, UINT uMsg,
  133.                                   WPARAM wParam, LPARAM lParam)
  134. {
  135.     switch (uMsg) {
  136.         case WM_INITDIALOG:
  137.            if (!InitUserProfileDlg (hDlg, lParam)) {
  138.                EndDialog(hDlg, FALSE);
  139.            }
  140.            return TRUE;
  141.     case WM_NOTIFY:
  142.         switch (((NMHDR FAR*)lParam)->code)
  143.         {
  144.         case LVN_ITEMCHANGED:
  145.             UPDoItemChanged(hDlg, (int) wParam);
  146.             break;
  147.         case LVN_COLUMNCLICK:
  148.             break;
  149.         case PSN_APPLY:
  150.             {
  151.             PSHNOTIFY *lpNotify = (PSHNOTIFY *) lParam;
  152.             UPSave(hDlg);
  153.             }
  154.             break;
  155.         case PSN_RESET:
  156.             SetWindowLongPtr (hDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
  157.             return TRUE;
  158.         default:
  159.             return FALSE;
  160.         }
  161.         break;
  162.     case WM_DESTROY:
  163.         UPCleanUp (hDlg);
  164.         break;
  165.     case WM_COMMAND:
  166.         switch (LOWORD(wParam)) {
  167.             case IDC_UP_DELETE:
  168.                 UPDeleteProfile(hDlg);
  169.                 break;
  170.             case IDC_UP_TYPE:
  171.                 UPChangeType(hDlg);
  172.                 break;
  173.             case IDC_UP_COPY:
  174.                 UPCopyProfile(hDlg);
  175.                 break;
  176.             default:
  177.                 break;
  178.         }
  179.         break;
  180.     case WM_HELP:      // F1
  181.         WinHelp((HWND)((LPHELPINFO) lParam)->hItemHandle, HELP_FILE, HELP_WM_HELP,
  182.         (DWORD_PTR) (LPSTR) aUserProfileHelpIds);
  183.         break;
  184.     case WM_CONTEXTMENU:      // right mouse click
  185.         WinHelp((HWND) wParam, HELP_FILE, HELP_CONTEXTMENU,
  186.         (DWORD_PTR) (LPSTR) aUserProfileHelpIds);
  187.         return (TRUE);
  188.     }
  189.     return (FALSE);
  190. }
  191. //*************************************************************
  192. //
  193. //  InitUserProfileDlg()
  194. //
  195. //  Purpose:    Initializes the User Profiles page
  196. //
  197. //  Parameters: hDlg    -   Dialog box handle
  198. //
  199. //  Return:     TRUE if successful
  200. //              FALSE if an error occurs
  201. //
  202. //  Comments:
  203. //
  204. //  History:    Date        Author     Comment
  205. //              1/26/96     ericflo    Created
  206. //
  207. //*************************************************************
  208. BOOL InitUserProfileDlg (HWND hDlg, LPARAM lParam)
  209. {
  210.     TCHAR szHeaderName[30];
  211.     LV_COLUMN col;
  212.     RECT rc;
  213.     HWND hLV;
  214.     INT iTotal = 0, iCurrent;
  215.     HWND hwndTemp;
  216.     BOOL bAdmin;
  217.     HCURSOR hOldCursor;
  218.     hOldCursor = SetCursor (LoadCursor(NULL, IDC_WAIT));
  219.     hLV = GetDlgItem(hDlg, IDC_UP_LISTVIEW);
  220.     // Set extended LV style for whole line selection
  221.     SendMessage(hLV, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT);
  222.     //
  223.     // Insert Columns
  224.     //
  225.     GetClientRect (hLV, &rc);
  226.     LoadString(hInstance, IDS_UP_NAME, szHeaderName, 30);
  227.     col.mask = LVCF_FMT | LVCF_TEXT | LVCF_SUBITEM | LVCF_WIDTH;
  228.     col.fmt = LVCFMT_LEFT;
  229.     iCurrent = (int)(rc.right * .45);
  230.     iTotal += iCurrent;
  231.     col.cx = iCurrent;
  232.     col.pszText = szHeaderName;
  233.     col.iSubItem = 0;
  234.     ListView_InsertColumn (hLV, 0, &col);
  235.     LoadString(hInstance, IDS_UP_SIZE, szHeaderName, 30);
  236.     iCurrent = (int)(rc.right * .15);
  237.     iTotal += iCurrent;
  238.     col.cx = iCurrent;
  239.     col.fmt = LVCFMT_RIGHT;
  240.     col.iSubItem = 1;
  241.     ListView_InsertColumn (hLV, 1, &col);
  242.     LoadString(hInstance, IDS_UP_TYPE, szHeaderName, 30);
  243.     col.iSubItem = 2;
  244.     iCurrent = (int)(rc.right * .20);
  245.     iTotal += iCurrent;
  246.     col.cx = iCurrent;
  247.     col.fmt = LVCFMT_LEFT;
  248.     ListView_InsertColumn (hLV, 2, &col);
  249.     LoadString(hInstance, IDS_UP_MOD, szHeaderName, 30);
  250.     col.iSubItem = 3;
  251.     col.cx = rc.right - iTotal - GetSystemMetrics(SM_CYHSCROLL);
  252.     col.fmt = LVCFMT_LEFT;
  253.     ListView_InsertColumn (hLV, 3, &col);
  254.     bAdmin = IsUserAdmin();
  255.     if (!bAdmin) {
  256.         RECT rc;
  257.         POINT pt;
  258.         //
  259.         // If the user is not an admin, then we hide the
  260.         // delete and copy to buttons
  261.         //
  262.         hwndTemp = GetDlgItem (hDlg, IDC_UP_DELETE);
  263.         GetWindowRect (hwndTemp, &rc);
  264.         EnableWindow (hwndTemp, FALSE);
  265.         ShowWindow (hwndTemp, SW_HIDE);
  266.         hwndTemp = GetDlgItem (hDlg, IDC_UP_COPY);
  267.         EnableWindow (hwndTemp, FALSE);
  268.         ShowWindow (hwndTemp, SW_HIDE);
  269.         //
  270.         // Move the Change Type button over
  271.         //
  272.         pt.x = rc.left;
  273.         pt.y = rc.top;
  274.         ScreenToClient (hDlg, &pt);
  275.         SetWindowPos (GetDlgItem (hDlg, IDC_UP_TYPE),
  276.                       HWND_TOP, pt.x, pt.y, 0, 0,
  277.                       SWP_NOSIZE | SWP_NOZORDER);
  278.     }
  279.     //
  280.     // Fill the user accounts
  281.     //
  282.     if (!FillListView (hDlg, bAdmin)) {
  283.         SetCursor(hOldCursor);
  284.         return FALSE;
  285.     }
  286.     SetCursor(hOldCursor);
  287.     return TRUE;
  288. }
  289. //*************************************************************
  290. //
  291. //  AddUser()
  292. //
  293. //  Purpose:    Adds a new user to the listview
  294. //
  295. //
  296. //  Parameters: hDlg            -   handle to the dialog box
  297. //              lpSid           -   Sid (text form)
  298. //
  299. //
  300. //  Return:     TRUE if successful
  301. //              FALSE if an error occurs
  302. //
  303. //  Comments:
  304. //
  305. //  History:    Date        Author     Comment
  306. //              1/26/96     ericflo    Created
  307. //
  308. //*************************************************************
  309. BOOL AddUser (HWND hDlg, LPTSTR lpSid, DWORD dwFlags)
  310. {
  311.     LONG Error;
  312.     HKEY hKeyUser;
  313.     TCHAR szBuffer[MAX_PATH];
  314.     TCHAR szBuffer2[MAX_PATH];
  315.     TCHAR szTemp[100];
  316.     TCHAR szTemp2[100];
  317.     DWORD dwTempSize = 100, dwTemp2Size = 100;
  318.     PSID pSid;
  319.     DWORD dwSize, dwType;
  320.     SID_NAME_USE SidName;
  321.     LV_ITEM item;
  322.     INT iItem;
  323.     HWND hwndTemp;
  324.     HKEY hkeyUser;
  325.     HANDLE hFile;
  326.     WIN32_FIND_DATA fd;
  327.     LPTSTR lpEnd;
  328.     SYSTEMTIME systime;
  329.     TCHAR szProfileSize[20];
  330.     INT iTypeID;
  331.     DWORD dwProfileType;
  332.     LPUSERINFO lpUserInfo;
  333.     BOOL bCentralAvailable = FALSE;
  334.     TCHAR szExcludeList[2*MAX_PATH+1];
  335.     LPTSTR lpExcludeList = NULL;    
  336.     //
  337.     // Open the user's info
  338.     //
  339.     wsprintf (szBuffer, TEXT("%s\%s"), PROFILE_MAPPING, lpSid);
  340.     Error = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  341.                          szBuffer,
  342.                          0,
  343.                          KEY_READ,
  344.                          &hkeyUser);
  345.     if (Error != ERROR_SUCCESS) {
  346.         return FALSE;
  347.     }
  348.     //
  349.     // Query for the user's central profile location
  350.     //
  351.     dwSize = MAX_PATH * sizeof(TCHAR);
  352.     Error = RegQueryValueEx (hkeyUser,
  353.                              TEXT("CentralProfile"),
  354.                              NULL,
  355.                              &dwType,
  356.                              (LPBYTE) szBuffer2,
  357.                              &dwSize);
  358.     if ((Error == ERROR_SUCCESS) && (szBuffer2[0] != TEXT(''))) {
  359.         bCentralAvailable = TRUE;
  360.     }
  361.     //
  362.     // Query for the user's local profile
  363.     //
  364.     dwSize = MAX_PATH * sizeof(TCHAR);
  365.     Error = RegQueryValueEx (hkeyUser,
  366.                              TEXT("ProfileImagePath"),
  367.                              NULL,
  368.                              &dwType,
  369.                              (LPBYTE) szBuffer2,
  370.                              &dwSize);
  371.     if (Error != ERROR_SUCCESS) {
  372.         RegCloseKey (hkeyUser);
  373.         return FALSE;
  374.     }
  375.     //
  376.     // Profile paths need to be expanded
  377.     //
  378.     ExpandEnvironmentStrings (szBuffer2, szBuffer, MAX_PATH);
  379.     lstrcpy (szBuffer2, szBuffer);
  380.     //
  381.     // Test if the directory exists.
  382.     //
  383.     hFile = FindFirstFile (szBuffer, &fd);
  384.     if (hFile == INVALID_HANDLE_VALUE) {
  385.         RegCloseKey (hkeyUser);
  386.         return FALSE;
  387.     }
  388.     FindClose (hFile);
  389.     //
  390.     // Get the time stamp of the profile
  391.     //
  392.     lpEnd = CheckSlash (szBuffer);
  393.     lstrcpy (lpEnd, TEXT("ntuser.dat"));
  394.     //
  395.     // Look for a normal user profile
  396.     //
  397.     hFile = FindFirstFile (szBuffer, &fd);
  398.     if (hFile == INVALID_HANDLE_VALUE) {
  399.         //
  400.         // Try a mandatory user profile
  401.         //
  402.         lstrcpy (lpEnd, TEXT("ntuser.man"));
  403.         hFile = FindFirstFile (szBuffer, &fd);
  404.         if (hFile == INVALID_HANDLE_VALUE) {
  405.             RegCloseKey (hkeyUser);
  406.             return FALSE;
  407.         }
  408.     }
  409.     FindClose (hFile);
  410.     *lpEnd = TEXT('');
  411.     //
  412.     // Get the exclusionlist from the registry or ini files
  413.     //
  414.     if (dwFlags & PRF_USERSID)
  415.         ReadExclusionList(szExcludeList, 2*MAX_PATH);
  416.     else
  417.         ReadExclusionListFromIniFile(szBuffer, szExcludeList, 2*MAX_PATH);
  418.     //
  419.     // Convert the exclusionlist read from the registry to a Null terminated list
  420.     // readable by recursedirectory.
  421.     //
  422.     if (szExcludeList[0] != TEXT(''))
  423.         lpExcludeList = ConvertExclusionList (szBuffer, szExcludeList);
  424.     else
  425.         lpExcludeList = NULL;
  426.     //
  427.     // Get the profile size
  428.     //
  429.     g_dwProfileSize = 0;
  430.     *lpEnd = TEXT('');
  431.     if (!RecurseDirectory (szBuffer, lpExcludeList)) {
  432.         RegCloseKey (hkeyUser);
  433.         if (lpExcludeList) {
  434.             LocalFree (lpExcludeList);
  435.         }
  436.         return FALSE;
  437.     }
  438.     if (g_dwProfileSize < 1024) {
  439.         g_dwProfileSize = 1024;
  440.     }
  441.     g_dwProfileSize /= 1024;
  442.     if (g_dwProfileSize == 0) {
  443.         g_dwProfileSize = 1;
  444.     }
  445.     LoadString (hInstance, IDS_UP_KB, szTemp, 100);
  446.     wsprintf (szProfileSize, szTemp, g_dwProfileSize);
  447.     //
  448.     // Query for the profile type
  449.     //
  450.     dwSize = sizeof(dwProfileType);
  451.     Error = RegQueryValueEx (hkeyUser,
  452.                              TEXT("UserPreference"),
  453.                              NULL,
  454.                              &dwType,
  455.                              (LPBYTE) &dwProfileType,
  456.                              &dwSize);
  457.     if (Error != ERROR_SUCCESS) {
  458.         //
  459.         // The User hasn't specified options yet,
  460.         // so check out the state information
  461.         //
  462.         Error = RegQueryValueEx (hkeyUser,
  463.                                  TEXT("State"),
  464.                                  NULL,
  465.                                  &dwType,
  466.                                  (LPBYTE) &dwProfileType,
  467.                                  &dwSize);
  468.         if (Error != ERROR_SUCCESS) {
  469.             dwProfileType = 0;
  470.         }
  471.         //
  472.         // The constants being used come from
  473.         // windowsginauserenvprofile.h
  474.         //
  475.         if (dwProfileType & 0x00000001) {
  476.             dwProfileType = USERINFO_MANDATORY;
  477.         } else if (dwProfileType & 0x00000010) {
  478.             dwProfileType = USERINFO_FLOATING;
  479.         } else {
  480.             dwProfileType = USERINFO_LOCAL;
  481.         }
  482.     }
  483.     switch (dwProfileType) {
  484.         case USERINFO_MANDATORY:
  485.             iTypeID = IDS_UP_MANDATORY;
  486.             break;
  487.         case USERINFO_FLOATING:
  488.         case USERINFO_LOCAL_SLOW_LINK:
  489.             iTypeID = IDS_UP_FLOATING;
  490.             break;
  491.         default:
  492.             iTypeID = IDS_UP_LOCAL;
  493.             break;
  494.     }
  495.     //
  496.     // Get the friendly display name
  497.     //
  498.     Error = RegQueryValueEx (hkeyUser, TEXT("Sid"), NULL, &dwType, NULL, &dwSize);
  499.     if (Error != ERROR_SUCCESS) {
  500.         RegCloseKey (hkeyUser);
  501.         return FALSE;
  502.     }
  503.     pSid = MemAlloc (LPTR, dwSize);
  504.     if (!pSid) {
  505.         RegCloseKey (hkeyUser);
  506.         return FALSE;
  507.     }
  508.     Error = RegQueryValueEx (hkeyUser,
  509.                              TEXT("Sid"),
  510.                              NULL,
  511.                              &dwType,
  512.                              (LPBYTE)pSid,
  513.                              &dwSize);
  514.     if (Error != ERROR_SUCCESS) {
  515.         RegCloseKey (hkeyUser);
  516.         return FALSE;
  517.     }
  518.     //
  519.     // Get the friendly names
  520.     //
  521.     szTemp[0] = TEXT('');
  522.     if (!LookupAccountSid (NULL, pSid, szTemp, &dwTempSize,
  523.                            szTemp2, &dwTemp2Size, &SidName)) {
  524.         //
  525.         // Unknown account
  526.         //
  527.         LoadString (hInstance, IDS_UP_ACCUNKNOWN, szBuffer, MAX_PATH);
  528.     } else {
  529.         if (szTemp[0] != TEXT('')) {
  530.             //
  531.             // Build the display name
  532.             //
  533.             wsprintf (szBuffer, TEXT("%s\%s"), szTemp2, szTemp);
  534.         } else {
  535.             //
  536.             // Account deleted.
  537.             //
  538.             LoadString (hInstance, IDS_UP_ACCDELETED, szBuffer, MAX_PATH);
  539.         }
  540.     }
  541.     //
  542.     // Allocate a UserInfo structure
  543.     //
  544.     lpUserInfo = (LPUSERINFO) MemAlloc(LPTR, (sizeof(USERINFO) +
  545.                                        (lstrlen (lpSid) + 1) * sizeof(TCHAR) +
  546.                                        (lstrlen (szBuffer2) + 1) * sizeof(TCHAR)));
  547.     if (!lpUserInfo) {
  548.         MemFree (pSid);
  549.         RegCloseKey (hkeyUser);
  550.         return FALSE;
  551.     }
  552.     lpUserInfo->dwFlags = (bCentralAvailable ? USERINFO_FLAG_CENTRAL_AVAILABLE : 0);
  553.     lpUserInfo->lpSid = (LPTSTR)((LPBYTE)lpUserInfo + sizeof(USERINFO));
  554.     lpUserInfo->lpProfile = (LPTSTR) (lpUserInfo->lpSid + lstrlen(lpSid) + 1);
  555.     lstrcpy (lpUserInfo->lpSid, lpSid);
  556.     lstrcpy (lpUserInfo->lpProfile, szBuffer2);
  557.     lpUserInfo->dwProfileType = dwProfileType;
  558.     //
  559.     // Add the item to the listview
  560.     //
  561.     hwndTemp = GetDlgItem (hDlg, IDC_UP_LISTVIEW);
  562.     item.mask = LVIF_TEXT | LVIF_PARAM;
  563.     item.iItem = 0;
  564.     item.iSubItem = 0;
  565.     item.pszText = szBuffer;
  566.     item.lParam = (LPARAM) lpUserInfo;
  567.     iItem = ListView_InsertItem (hwndTemp, &item);
  568.     //
  569.     // Add the profile size
  570.     //
  571.     item.mask = LVIF_TEXT;
  572.     item.iItem = iItem;
  573.     item.iSubItem = 1;
  574.     item.pszText = szProfileSize;
  575.     SendMessage (hwndTemp, LVM_SETITEMTEXT, iItem, (LPARAM) &item);
  576.     //
  577.     // Add the profile type
  578.     //
  579.     LoadString (hInstance, iTypeID, szTemp, 100);
  580.     item.mask = LVIF_TEXT;
  581.     item.iItem = iItem;
  582.     item.iSubItem = 2;
  583.     item.pszText = szTemp;
  584.     SendMessage (hwndTemp, LVM_SETITEMTEXT, iItem, (LPARAM) &item);
  585.     //
  586.     // Add the time/date stamp
  587.     //
  588.     FileTimeToSystemTime (&fd.ftLastAccessTime, &systime);
  589.     GetDateFormat (LOCALE_USER_DEFAULT, DATE_SHORTDATE, &systime,
  590.                     NULL, szBuffer, MAX_PATH);
  591.     item.mask = LVIF_TEXT;
  592.     item.iItem = iItem;
  593.     item.iSubItem = 3;
  594.     item.pszText = szBuffer;
  595.     SendMessage (hwndTemp, LVM_SETITEMTEXT, iItem, (LPARAM) &item);
  596.     //
  597.     // Free the sid
  598.     //
  599.     MemFree (pSid);
  600.     if (lpExcludeList) {
  601.         LocalFree (lpExcludeList);
  602.     }
  603.     RegCloseKey (hkeyUser);
  604.     return TRUE;
  605. }
  606. //*************************************************************
  607. //
  608. //  FillListView()
  609. //
  610. //  Purpose:    Fills the listview with either all the profiles
  611. //              or just the current user profile depending if
  612. //              the user has Admin privilages
  613. //
  614. //  Parameters: hDlg            -   Dialog box handle
  615. //              bAdmin          -   User an admin
  616. //
  617. //
  618. //  Return:     TRUE if successful
  619. //              FALSE if an error occurs
  620. //
  621. //  Comments:
  622. //
  623. //  History:    Date        Author     Comment
  624. //              1/26/96     ericflo    Created
  625. //
  626. //*************************************************************
  627. BOOL FillListView (HWND hDlg, BOOL bAdmin)
  628. {
  629.     LV_ITEM item;
  630.     BOOL bRetVal = FALSE;
  631.     LPTSTR lpUserSid;
  632.     lpUserSid = GetSidString();
  633.     //
  634.     // If the current user has admin privilages, then
  635.     // he/she can see all the profiles on this machine,
  636.     // otherwise the user only gets their profile.
  637.     //
  638.     if (bAdmin) {
  639.         DWORD SubKeyIndex = 0;
  640.         TCHAR SubKeyName[100];
  641.         DWORD cchSubKeySize;
  642.         HKEY hkeyProfiles;
  643.         LONG Error;
  644.         //
  645.         // Open the profile list
  646.         //
  647.         Error = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  648.                              PROFILE_MAPPING,
  649.                              0,
  650.                              KEY_READ,
  651.                              &hkeyProfiles);
  652.         if (Error != ERROR_SUCCESS) {
  653.             if (lpUserSid)
  654.                 DeleteSidString (lpUserSid);
  655.             return FALSE;
  656.         }
  657.         cchSubKeySize = 100;
  658.         while (TRUE) {
  659.             //
  660.             // Get the next sub-key name
  661.             //
  662.             Error = RegEnumKey(hkeyProfiles, SubKeyIndex, SubKeyName, cchSubKeySize);
  663.             if (Error != ERROR_SUCCESS) {
  664.                 if (Error == ERROR_NO_MORE_ITEMS) {
  665.                     //
  666.                     // Successful end of enumeration
  667.                     //
  668.                     Error = ERROR_SUCCESS;
  669.                 }
  670.                 break;
  671.             }
  672.             if ((lpUserSid) && (lstrcmp(SubKeyName, lpUserSid) == 0))
  673.                 AddUser (hDlg, SubKeyName, PRF_USERSID);
  674.             else
  675.                 AddUser (hDlg, SubKeyName, 0);
  676.             //
  677.             // Go enumerate the next sub-key
  678.             //
  679.             SubKeyIndex ++;
  680.         }
  681.         //
  682.         // Close the registry
  683.         //
  684.         RegCloseKey (hkeyProfiles);
  685.         bRetVal = ((Error == ERROR_SUCCESS) ? TRUE : FALSE);
  686.     } else {
  687.         //
  688.         // The current user doesn't have admin privilages
  689.         //
  690.         if (lpUserSid) {
  691.             AddUser (hDlg, lpUserSid, PRF_USERSID);
  692.             bRetVal = TRUE;
  693.         }
  694.     }
  695.     if (bRetVal) {
  696.         //
  697.         // Select the first item
  698.         //
  699.         item.mask = LVIF_STATE;
  700.         item.iItem = 0;
  701.         item.iSubItem = 0;
  702.         item.state = LVIS_SELECTED | LVIS_FOCUSED;
  703.         item.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
  704.         SendDlgItemMessage (hDlg, IDC_UP_LISTVIEW,
  705.                             LVM_SETITEMSTATE, 0, (LPARAM) &item);
  706.     }
  707.     if (lpUserSid)
  708.         DeleteSidString (lpUserSid);
  709.     return (bRetVal);
  710. }
  711. //*************************************************************
  712. //
  713. //  CheckSemicolon()
  714. //
  715. //  Purpose:    Checks for an ending slash and adds one if
  716. //              it is missing.
  717. //
  718. //  Parameters: lpDir   -   directory
  719. //
  720. //  Return:     Pointer to the end of the string
  721. //
  722. //  Comments:
  723. //
  724. //  History:    Date        Author     Comment
  725. //              6/19/95     ericlfo    Created
  726. //
  727. //*************************************************************
  728. LPTSTR CheckSemicolon (LPTSTR lpDir)
  729. {
  730.     LPTSTR lpEnd;
  731.     lpEnd = lpDir + lstrlen(lpDir);
  732.     if (*(lpEnd - 1) != TEXT(';')) {
  733.         *lpEnd =  TEXT(';');
  734.         lpEnd++;
  735.         *lpEnd =  TEXT('');
  736.     }
  737.     return lpEnd;
  738. }
  739. //*************************************************************
  740. //
  741. //  ReadExclusionList()
  742. //
  743. //  Purpose:    Reads the exclusionlist for the user from the 
  744. //              hkcu part of the registry
  745. //
  746. //  Parameters: szExclusionList - Buffer for exclusionList to be read into
  747. //              dwSize          - Size of the buffer
  748. //
  749. //  Return:     FALSE on error
  750. //
  751. //*************************************************************
  752. BOOL ReadExclusionList(LPTSTR szExcludeList, DWORD dwExclSize)
  753. {
  754.     TCHAR szExcludeList2[MAX_PATH];
  755.     TCHAR szExcludeList1[MAX_PATH];
  756.     HKEY  hKey;
  757.     DWORD dwSize, dwType;
  758.     //
  759.     // Check for a list of directories to exclude both user preferences
  760.     // and user policy
  761.     //
  762.     szExcludeList1[0] = TEXT('');
  763.     if (RegOpenKeyEx (HKEY_CURRENT_USER,
  764.                       TEXT("Software\Microsoft\Windows NT\CurrentVersion\Winlogon"),
  765.                       0, KEY_READ, &hKey) == ERROR_SUCCESS) {
  766.         dwSize = sizeof(szExcludeList1);
  767.         RegQueryValueEx (hKey,
  768.                          TEXT("ExcludeProfileDirs"),
  769.                          NULL,
  770.                          &dwType,
  771.                          (LPBYTE) szExcludeList1,
  772.                          &dwSize);
  773.         RegCloseKey (hKey);
  774.     }
  775.     szExcludeList2[0] = TEXT('');
  776.     if (RegOpenKeyEx (HKEY_CURRENT_USER,
  777.                       TEXT("Software\Microsoft\Windows\CurrentVersion\Policies\System"), // systempolicies key
  778.                       0, KEY_READ, &hKey) == ERROR_SUCCESS) {
  779.         dwSize = sizeof(szExcludeList2);
  780.         RegQueryValueEx (hKey,
  781.                          TEXT("ExcludeProfileDirs"),
  782.                          NULL,
  783.                          &dwType,
  784.                          (LPBYTE) szExcludeList2,
  785.                          &dwSize);
  786.         RegCloseKey (hKey);
  787.     }
  788.     //
  789.     // Merge the user preferences and policy together
  790.     //
  791.     szExcludeList[0] = TEXT('');
  792.     if (szExcludeList1[0] != TEXT('')) {
  793.         CheckSemicolon(szExcludeList1);
  794.         lstrcpy (szExcludeList, szExcludeList1);
  795.     }
  796.     if (szExcludeList2[0] != TEXT('')) {
  797.         lstrcat (szExcludeList, szExcludeList2);
  798.     }
  799.     return TRUE;
  800. }
  801. //*************************************************************
  802. //
  803. //  ReadExclusionListFromIniFile()
  804. //
  805. //  Purpose:    Reads the exclusionlist for the user from the 
  806. //              ntuser.ini from the local profile
  807. //
  808. //  Parameters: 
  809. //              (in) lpSourceDir     - Profile Directory
  810. //                   szExclusionList - Buffer for exclusionList to be read into
  811. //                   dwSize          - Size of the buffer
  812. //
  813. //  Return:     FALSE on error
  814. //
  815. //
  816. //*************************************************************
  817. BOOL ReadExclusionListFromIniFile(LPCTSTR lpSourceDir, LPTSTR szExcludeList, DWORD dwExclSize)
  818. {
  819.     TCHAR szNTUserIni[MAX_PATH];
  820.     LPTSTR lpEnd;
  821.     //
  822.     // Get the exclusion list from the cache
  823.     //
  824.     szExcludeList[0] = TEXT('');
  825.     lstrcpy (szNTUserIni, lpSourceDir);
  826.     lpEnd = CheckSlash (szNTUserIni);
  827.     lstrcpy(lpEnd, c_szNTUserIni);
  828.     GetPrivateProfileString (PROFILE_GENERAL_SECTION,
  829.                              PROFILE_EXCLUSION_LIST,
  830.                              TEXT(""), szExcludeList,
  831.                              dwExclSize,
  832.                              szNTUserIni);
  833.     return TRUE;
  834. }
  835. //*************************************************************
  836. //
  837. //  ConvertExclusionList()
  838. //
  839. //  Purpose:    Converts the semi-colon profile relative exclusion
  840. //              list to fully qualified null terminated exclusion
  841. //              list
  842. //
  843. //  Parameters: lpSourceDir     -  Profile root directory
  844. //              lpExclusionList -  List of directories to exclude
  845. //
  846. //  Return:     List if successful
  847. //              NULL if an error occurs
  848. //
  849. //*************************************************************
  850. LPTSTR ConvertExclusionList (LPCTSTR lpSourceDir, LPCTSTR lpExclusionList)
  851. {
  852.     LPTSTR lpExcludeList = NULL, lpInsert, lpEnd, lpTempList;
  853.     LPCTSTR lpTemp, lpDir;
  854.     TCHAR szTemp[MAX_PATH];
  855.     DWORD dwSize = 2;  // double null terminator
  856.     DWORD dwStrLen;
  857.     //
  858.     // Setup a temp buffer to work with
  859.     //
  860.     lstrcpy (szTemp, lpSourceDir);
  861.     lpEnd = CheckSlash (szTemp);
  862.     //
  863.     // Loop through the list
  864.     //
  865.     lpTemp = lpDir = lpExclusionList;
  866.     while (*lpTemp) {
  867.         //
  868.         // Look for the semicolon separator
  869.         //
  870.         while (*lpTemp && ((*lpTemp) != TEXT(';'))) {
  871.             lpTemp++;
  872.         }
  873.         //
  874.         // Remove any leading spaces
  875.         //
  876.         while (*lpDir == TEXT(' ')) {
  877.             lpDir++;
  878.         }
  879.         //
  880.         // Put the directory name on the temp buffer
  881.         //
  882.         lstrcpyn (lpEnd, lpDir, (int)(lpTemp - lpDir + 1));
  883.         //
  884.         // Add the string to the exclusion list
  885.         //
  886.         if (lpExcludeList) {
  887.             dwStrLen = lstrlen (szTemp) + 1;
  888.             dwSize += dwStrLen;
  889.             lpTempList = LocalReAlloc (lpExcludeList, dwSize * sizeof(TCHAR),
  890.                                        LMEM_MOVEABLE | LMEM_ZEROINIT);
  891.             if (!lpTempList) {
  892.                 LocalFree (lpExcludeList);
  893.                 lpExcludeList = NULL;
  894.                 goto Exit;
  895.             }
  896.             lpExcludeList = lpTempList;
  897.             lpInsert = lpExcludeList + dwSize - dwStrLen - 1;
  898.             lstrcpy (lpInsert, szTemp);
  899.         } else {
  900.             dwSize += lstrlen (szTemp);
  901.             lpExcludeList = LocalAlloc (LPTR, dwSize * sizeof(TCHAR));
  902.             if (!lpExcludeList) {
  903.                 goto Exit;
  904.             }
  905.             lstrcpy (lpExcludeList, szTemp);
  906.         }
  907.         //
  908.         // If we are at the end of the exclusion list, we're done
  909.         //
  910.         if (!(*lpTemp)) {
  911.             goto Exit;
  912.         }
  913.         //
  914.         // Prep for the next entry
  915.         //
  916.         lpTemp++;
  917.         lpDir = lpTemp;
  918.     }
  919. Exit:
  920.     return lpExcludeList;
  921. }
  922. //*************************************************************
  923. //
  924. //  RecurseDirectory()
  925. //
  926. //  Purpose:    Recurses through the subdirectories counting the size.
  927. //
  928. //  Parameters: lpDir     -   Directory
  929. //
  930. //  Return:     TRUE if successful
  931. //              FALSE if an error occurs
  932. //
  933. //  Comments:
  934. //
  935. //  History:    Date        Author     Comment
  936. //              1/30/96     ericflo    Created
  937. //
  938. //*************************************************************
  939. BOOL RecurseDirectory (LPTSTR lpDir, LPTSTR lpExcludeList)
  940. {
  941.     HANDLE hFile = INVALID_HANDLE_VALUE;
  942.     WIN32_FIND_DATA fd;
  943.     LPTSTR lpEnd, lpTemp;
  944.     BOOL bResult = TRUE;
  945.     BOOL bSkip;
  946.     //
  947.     // Setup the ending pointer
  948.     //
  949.     lpEnd = CheckSlash (lpDir);
  950.     //
  951.     // Append *.* to the source directory
  952.     //
  953.     lstrcpy(lpEnd, TEXT("*.*"));
  954.     //
  955.     // Search through the source directory
  956.     //
  957.     hFile = FindFirstFile(lpDir, &fd);
  958.     if (hFile == INVALID_HANDLE_VALUE) {
  959.         if ( (GetLastError() == ERROR_FILE_NOT_FOUND) ||
  960.              (GetLastError() == ERROR_PATH_NOT_FOUND) ) {
  961.             //
  962.             // bResult is already initialized to TRUE, so
  963.             // just fall through.
  964.             //
  965.         } else {
  966.             bResult = FALSE;
  967.         }
  968.         goto RecurseDir_Exit;
  969.     }
  970.     do {
  971.         //
  972.         // Append the file / directory name to the working buffer
  973.         //
  974.         lstrcpy (lpEnd, fd.cFileName);
  975.         if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
  976.             //
  977.             // Check for "." and ".."
  978.             //
  979.             if (!lstrcmpi(fd.cFileName, TEXT("."))) {
  980.                 continue;
  981.             }
  982.             if (!lstrcmpi(fd.cFileName, TEXT(".."))) {
  983.                 continue;
  984.             }
  985.             //
  986.             // Check if this directory should be excluded
  987.             //
  988.             if (lpExcludeList) {
  989.                 bSkip = FALSE;
  990.                 lpTemp = lpExcludeList;
  991.                 while (*lpTemp) {
  992.                     if (lstrcmpi (lpTemp, lpDir) == 0) {
  993.                         bSkip = TRUE;
  994.                         break;
  995.                     }
  996.                     lpTemp += lstrlen (lpTemp) + 1;
  997.                 }
  998.                 if (bSkip) 
  999.                     continue;
  1000.             }
  1001.             //
  1002.             // Found a directory.
  1003.             //
  1004.             // 1)  Change into that subdirectory on the source drive.
  1005.             // 2)  Recurse down that tree.
  1006.             // 3)  Back up one level.
  1007.             //
  1008.             //
  1009.             // Recurse the subdirectory
  1010.             //
  1011.             if (!RecurseDirectory(lpDir, lpExcludeList)) {
  1012.                 bResult = FALSE;
  1013.                 goto RecurseDir_Exit;
  1014.             }
  1015.         } else {
  1016.             //
  1017.             // Found a file, add the filesize
  1018.             //
  1019.             g_dwProfileSize += fd.nFileSizeLow;
  1020.         }
  1021.         //
  1022.         // Find the next entry
  1023.         //
  1024.     } while (FindNextFile(hFile, &fd));
  1025. RecurseDir_Exit:
  1026.     //
  1027.     // Remove the file / directory name appended above
  1028.     //
  1029.     *lpEnd = TEXT('');
  1030.     //
  1031.     // Close the search handle
  1032.     //
  1033.     if (hFile != INVALID_HANDLE_VALUE) {
  1034.         FindClose(hFile);
  1035.     }
  1036.     return bResult;
  1037. }
  1038. //*************************************************************
  1039. //
  1040. //  UPCleanUp()
  1041. //
  1042. //  Purpose:    Free's resources for this dialog box
  1043. //
  1044. //  Parameters: hDlg    -   Dialog box handle
  1045. //
  1046. //  Return:     void
  1047. //
  1048. //  Comments:
  1049. //
  1050. //  History:    Date        Author     Comment
  1051. //              1/31/96     ericflo    Created
  1052. //
  1053. //*************************************************************
  1054. VOID UPCleanUp (HWND hDlg)
  1055. {
  1056.     int           i, n;
  1057.     HWND          hwndTemp;
  1058.     LPUSERINFO    lpUserInfo;
  1059.     LV_ITEM       item;
  1060.     //
  1061.     //  Free memory used for the listview items
  1062.     //
  1063.     hwndTemp = GetDlgItem (hDlg, IDC_UP_LISTVIEW);
  1064.     n = (int)SendMessage (hwndTemp, LVM_GETITEMCOUNT, 0, 0L);
  1065.     item.mask = LVIF_PARAM;
  1066.     item.iSubItem = 0;
  1067.     for (i = 0; i < n; i++) {
  1068.         item.iItem = i;
  1069.         if (SendMessage (hwndTemp, LVM_GETITEM, 0, (LPARAM) &item)) {
  1070.             lpUserInfo = (LPUSERINFO) item.lParam;
  1071.         } else {
  1072.             lpUserInfo = NULL;
  1073.         }
  1074.         if (lpUserInfo) {
  1075.             MemFree (lpUserInfo);
  1076.         }
  1077.     }
  1078. }
  1079. //*************************************************************
  1080. //
  1081. //  UPSave()
  1082. //
  1083. //  Purpose:    Saves the settings
  1084. //
  1085. //  Parameters: hDlg    -   Dialog box handle
  1086. //
  1087. //  Return:     void
  1088. //
  1089. //  Comments:
  1090. //
  1091. //  History:    Date        Author     Comment
  1092. //              1/31/96     ericflo    Created
  1093. //
  1094. //*************************************************************
  1095. VOID UPSave (HWND hDlg)
  1096. {
  1097.     int           i, n;
  1098.     HWND          hwndTemp;
  1099.     LPUSERINFO    lpUserInfo;
  1100.     LV_ITEM       item;
  1101.     TCHAR         szBuffer[MAX_PATH];
  1102.     HKEY          hkeyUser;
  1103.     LONG          Error;
  1104.     //
  1105.     //  Save type info
  1106.     //
  1107.     hwndTemp = GetDlgItem (hDlg, IDC_UP_LISTVIEW);
  1108.     n = (int)SendMessage (hwndTemp, LVM_GETITEMCOUNT, 0, 0L);
  1109.     item.mask = LVIF_PARAM;
  1110.     item.iSubItem = 0;
  1111.     for (i = 0; i < n; i++) {
  1112.         item.iItem = i;
  1113.         if (SendMessage (hwndTemp, LVM_GETITEM, 0, (LPARAM) &item)) {
  1114.             lpUserInfo = (LPUSERINFO) item.lParam;
  1115.         } else {
  1116.             lpUserInfo = NULL;
  1117.         }
  1118.         if (lpUserInfo) {
  1119.             if (lpUserInfo->dwFlags & USERINFO_FLAG_DIRTY) {
  1120.                 lpUserInfo->dwFlags &= ~USERINFO_FLAG_DIRTY;
  1121.                 wsprintf (szBuffer, TEXT("%s\%s"), PROFILE_MAPPING,
  1122.                           lpUserInfo->lpSid);
  1123.                 Error = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  1124.                                      szBuffer,
  1125.                                      0,
  1126.                                      KEY_WRITE,
  1127.                                      &hkeyUser);
  1128.                 if (Error != ERROR_SUCCESS) {
  1129.                     continue;
  1130.                 }
  1131.                 RegSetValueEx (hkeyUser,
  1132.                                TEXT("UserPreference"),
  1133.                                0,
  1134.                                REG_DWORD,
  1135.                                (LPBYTE) &lpUserInfo->dwProfileType,
  1136.                                sizeof(DWORD));
  1137.                 RegCloseKey(hkeyUser);
  1138.             }
  1139.         }
  1140.     }
  1141. }
  1142. //*************************************************************
  1143. //
  1144. //  IsProfileInUse()
  1145. //
  1146. //  Purpose:    Determines if the given profile is currently in use
  1147. //
  1148. //  Parameters: lpSid   -   Sid (text) to test
  1149. //
  1150. //  Return:     TRUE if in use
  1151. //              FALSE if not
  1152. //
  1153. //  Comments:
  1154. //
  1155. //  History:    Date        Author     Comment
  1156. //              2/7/96      ericflo    Created
  1157. //
  1158. //*************************************************************
  1159. BOOL IsProfileInUse (LPTSTR lpSid)
  1160. {
  1161.     LONG lResult;
  1162.     HKEY hkeyProfile;
  1163.     lResult = RegOpenKeyEx (HKEY_USERS, lpSid, 0, KEY_READ, &hkeyProfile);
  1164.     if (lResult == ERROR_SUCCESS) {
  1165.         RegCloseKey (hkeyProfile);
  1166.         return TRUE;
  1167.     }
  1168.     return FALSE;
  1169. }
  1170. void UPDoItemChanged(HWND hDlg, int idCtl)
  1171. {
  1172.     int     selection;
  1173.     HWND    hwndTemp;
  1174.     LPUSERINFO lpUserInfo;
  1175.     LV_ITEM item;
  1176.     hwndTemp = GetDlgItem (hDlg, idCtl);
  1177.     selection = GetSelectedItem (hwndTemp);
  1178.     if (selection != -1)
  1179.     {
  1180.         item.mask = LVIF_PARAM;
  1181.         item.iItem = selection;
  1182.         item.iSubItem = 0;
  1183.         if (SendMessage (hwndTemp, LVM_GETITEM, 0, (LPARAM) &item)) {
  1184.             lpUserInfo = (LPUSERINFO) item.lParam;
  1185.         } else {
  1186.             lpUserInfo = NULL;
  1187.         }
  1188.         if (lpUserInfo) {
  1189.             //
  1190.             //  Set the "Delete" button state
  1191.             //
  1192.             if (IsProfileInUse(lpUserInfo->lpSid)) {
  1193.                 EnableWindow (GetDlgItem (hDlg, IDC_UP_DELETE), FALSE);
  1194.             } else {
  1195.                 EnableWindow (GetDlgItem (hDlg, IDC_UP_DELETE), TRUE);
  1196.             }
  1197.             //
  1198.             // Set the "Change Type" button state
  1199.             //
  1200.             if (lpUserInfo->dwProfileType == USERINFO_MANDATORY) {
  1201.                 EnableWindow (GetDlgItem (hDlg, IDC_UP_TYPE), FALSE);
  1202.             } else {
  1203.                 EnableWindow (GetDlgItem (hDlg, IDC_UP_TYPE), TRUE);
  1204.             }
  1205.         }
  1206.     }
  1207. }
  1208. //*************************************************************
  1209. //
  1210. //  UPDeleteProfile()
  1211. //
  1212. //  Purpose:    Deletes a user's profile
  1213. //
  1214. //  Parameters: hDlg    -   Dialog box handle
  1215. //
  1216. //  Return:
  1217. //
  1218. //  Comments:
  1219. //
  1220. //  History:    Date        Author     Comment
  1221. //              2/8/96      ericflo    Created
  1222. //
  1223. //*************************************************************
  1224. void UPDeleteProfile(HWND hDlg)
  1225. {
  1226.     int     selection;
  1227.     HWND    hwndTemp;
  1228.     LPUSERINFO lpUserInfo;
  1229.     LV_ITEM item;
  1230.     TCHAR   szName[100];
  1231.     TCHAR   szBuffer1[100];
  1232.     TCHAR   szBuffer2[200];
  1233.     HCURSOR hOldCursor;
  1234.     //
  1235.     // Get the selected profile
  1236.     //
  1237.     hwndTemp = GetDlgItem (hDlg, IDC_UP_LISTVIEW);
  1238.     selection = GetSelectedItem (hwndTemp);
  1239.     if (selection == -1) {
  1240.         return;
  1241.     }
  1242.     item.mask = LVIF_PARAM;
  1243.     item.iItem = selection;
  1244.     item.iSubItem = 0;
  1245.     if (SendMessage (hwndTemp, LVM_GETITEM, 0, (LPARAM) &item)) {
  1246.         lpUserInfo = (LPUSERINFO) item.lParam;
  1247.     } else {
  1248.         lpUserInfo = NULL;
  1249.     }
  1250.     if (!lpUserInfo) {
  1251.         return;
  1252.     }
  1253.     //
  1254.     // Confirm that the user really wants to delete the profile
  1255.     //
  1256.     szBuffer1[0] = TEXT('');
  1257.     ListView_GetItemText (hwndTemp, selection, 0, szName, 100);
  1258.     LoadString (hInstance, IDS_UP_CONFIRM, szBuffer1, 100);
  1259.     wsprintf (szBuffer2, szBuffer1, szName);
  1260.     LoadString (hInstance, IDS_UP_CONFIRMTITLE, szBuffer1, 100);
  1261.     if (MessageBox (hDlg, szBuffer2, szBuffer1,
  1262.                     MB_ICONQUESTION | MB_DEFBUTTON2| MB_YESNO) == IDNO) {
  1263.         return;
  1264.     }
  1265.     //
  1266.     // Delete the profile and remove the entry from the listview
  1267.     //
  1268.     hOldCursor = SetCursor (LoadCursor(NULL, IDC_WAIT));
  1269.     DeleteProfile (lpUserInfo->lpSid, lpUserInfo->lpProfile);
  1270.     if (ListView_DeleteItem(hwndTemp, selection)) {
  1271.         MemFree (lpUserInfo);
  1272.     }
  1273.     //
  1274.     // Select another item
  1275.     //
  1276.     if (selection > 0) {
  1277.         selection--;
  1278.     }
  1279.     item.mask = LVIF_STATE;
  1280.     item.iItem = selection;
  1281.     item.iSubItem = 0;
  1282.     item.state = LVIS_SELECTED | LVIS_FOCUSED;
  1283.     item.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
  1284.     SendDlgItemMessage (hDlg, IDC_UP_LISTVIEW,
  1285.                         LVM_SETITEMSTATE, selection, (LPARAM) &item);
  1286.     SetCursor(hOldCursor);
  1287. }
  1288. //*************************************************************
  1289. //
  1290. //  DeleteProfile()
  1291. //
  1292. //  Purpose:    Deletes the specified profile from the
  1293. //              registry and disk.
  1294. //
  1295. //  Parameters: lpSidString     -   Registry subkey
  1296. //              lpProfileDir    -   Profile directory
  1297. //
  1298. //  Return:     TRUE if successful
  1299. //              FALSE if an error occurs
  1300. //
  1301. //  Comments:
  1302. //
  1303. //  History:    Date        Author     Comment
  1304. //              2/8/96      ericflo    Created
  1305. //
  1306. //*************************************************************
  1307. BOOL DeleteProfile (LPTSTR lpSidString, LPTSTR lpProfileDir)
  1308. {
  1309.     LONG lResult;
  1310.     TCHAR szTemp[MAX_PATH];
  1311.     //
  1312.     // Cleanup the registry first.
  1313.     //
  1314.     if (lpSidString && *lpSidString) {
  1315.         lstrcpy(szTemp, TEXT("Software\Microsoft\Windows NT\CurrentVersion\ProfileList\"));
  1316.         lstrcat(szTemp, lpSidString);
  1317.         lResult = RegDeleteKey(HKEY_LOCAL_MACHINE, szTemp);
  1318.         if (lResult != ERROR_SUCCESS) {
  1319.             return FALSE;
  1320.         }
  1321.     }
  1322.     //
  1323.     // Now delete the profile
  1324.     //
  1325.     if (!Delnode (lpProfileDir)) {
  1326.         return FALSE;
  1327.     }
  1328.     return TRUE;
  1329. }
  1330. //*************************************************************
  1331. //
  1332. //  UPChangeType()
  1333. //
  1334. //  Purpose:    Display the "Change Type" dialog box
  1335. //
  1336. //  Parameters: hDlg    -   Dialog box handle
  1337. //
  1338. //  Return:     void
  1339. //
  1340. //  Comments:
  1341. //
  1342. //  History:    Date        Author     Comment
  1343. //              2/09/96     ericflo    Created
  1344. //
  1345. //*************************************************************
  1346. void UPChangeType(HWND hDlg)
  1347. {
  1348.     int     selection, iTypeID;
  1349.     HWND    hwndTemp;
  1350.     LPUSERINFO lpUserInfo;
  1351.     LV_ITEM item;
  1352.     TCHAR   szType[100];
  1353.     //
  1354.     // Get the selected profile
  1355.     //
  1356.     hwndTemp = GetDlgItem (hDlg, IDC_UP_LISTVIEW);
  1357.     selection = GetSelectedItem (hwndTemp);
  1358.     if (selection == -1) {
  1359.         return;
  1360.     }
  1361.     item.mask = LVIF_PARAM;
  1362.     item.iItem = selection;
  1363.     item.iSubItem = 0;
  1364.     if (SendMessage (hwndTemp, LVM_GETITEM, 0, (LPARAM) &item)) {
  1365.         lpUserInfo = (LPUSERINFO) item.lParam;
  1366.     } else {
  1367.         lpUserInfo = NULL;
  1368.     }
  1369.     if (!lpUserInfo) {
  1370.         return;
  1371.     }
  1372.     //
  1373.     // Display the Change Type dialog
  1374.     //
  1375.     if (!DialogBoxParam (hInstance, MAKEINTRESOURCE(IDD_UP_TYPE), hDlg,
  1376.                          ChangeTypeDlgProc, (LPARAM)lpUserInfo)) {
  1377.         return;
  1378.     }
  1379.     //
  1380.     // Activate the Apply button
  1381.     //
  1382.     PropSheet_Changed(GetParent(hDlg), hDlg);
  1383.     //
  1384.     // Mark this item as 'dirty' so it will be saved
  1385.     //
  1386.     lpUserInfo->dwFlags |= USERINFO_FLAG_DIRTY;
  1387.     //
  1388.     // Fix the 'Type' field in the display
  1389.     //
  1390.     switch (lpUserInfo->dwProfileType) {
  1391.         case USERINFO_MANDATORY:
  1392.             iTypeID = IDS_UP_MANDATORY;
  1393.             break;
  1394.         case USERINFO_FLOATING:
  1395.         case USERINFO_LOCAL_SLOW_LINK:
  1396.             iTypeID = IDS_UP_FLOATING;
  1397.             break;
  1398.         default:
  1399.             iTypeID = IDS_UP_LOCAL;
  1400.             break;
  1401.     }
  1402.     LoadString (hInstance, iTypeID, szType, 100);
  1403.     item.mask = LVIF_TEXT;
  1404.     item.iItem = selection;
  1405.     item.iSubItem = 2;
  1406.     item.pszText = szType;
  1407.     SendMessage (hwndTemp, LVM_SETITEMTEXT, selection, (LPARAM) &item);
  1408. }
  1409. //*************************************************************
  1410. //
  1411. //  ChangeTypeDlgProc()
  1412. //
  1413. //  Purpose:    Dialog box procedure for changing the profile type
  1414. //
  1415. //  Parameters: hDlg    -   handle to the dialog box
  1416. //              uMsg    -   window message
  1417. //              wParam  -   wParam
  1418. //              lParam  -   lParam
  1419. //
  1420. //  Return:     TRUE if message was processed
  1421. //              FALSE if not
  1422. //
  1423. //  Comments:
  1424. //
  1425. //  History:    Date        Author     Comment
  1426. //              2/9/96      ericflo    Created
  1427. //
  1428. //*************************************************************
  1429. INT_PTR APIENTRY ChangeTypeDlgProc (HWND hDlg, UINT uMsg,
  1430.                                  WPARAM wParam, LPARAM lParam)
  1431. {
  1432.     LPUSERINFO lpUserInfo;
  1433.     switch (uMsg) {
  1434.         case WM_INITDIALOG:
  1435.            lpUserInfo = (LPUSERINFO) lParam;
  1436.            if (!lpUserInfo) {
  1437.                EndDialog(hDlg, FALSE);
  1438.            }
  1439.            SetWindowLongPtr (hDlg, GWLP_USERDATA, (LPARAM) lpUserInfo);
  1440.            if (lpUserInfo->dwFlags & USERINFO_FLAG_CENTRAL_AVAILABLE) {
  1441.                if (lpUserInfo->dwProfileType == USERINFO_LOCAL) {
  1442.                    CheckRadioButton (hDlg, IDC_UPTYPE_LOCAL, IDC_UPTYPE_FLOAT,
  1443.                                      IDC_UPTYPE_LOCAL);
  1444.                    EnableWindow (GetDlgItem(hDlg, IDC_UPTYPE_SLOW), FALSE);
  1445.                    EnableWindow (GetDlgItem(hDlg, IDC_UPTYPE_SLOW_TEXT), FALSE);
  1446.                } else if (lpUserInfo->dwProfileType == USERINFO_FLOATING) {
  1447.                    CheckRadioButton (hDlg, IDC_UPTYPE_LOCAL, IDC_UPTYPE_FLOAT,
  1448.                                      IDC_UPTYPE_FLOAT);
  1449.                } else {
  1450.                    CheckRadioButton (hDlg, IDC_UPTYPE_LOCAL, IDC_UPTYPE_FLOAT,
  1451.                                      IDC_UPTYPE_FLOAT);
  1452.                    CheckDlgButton (hDlg, IDC_UPTYPE_SLOW, 1);
  1453.                }
  1454.            } else {
  1455.                CheckRadioButton (hDlg, IDC_UPTYPE_LOCAL, IDC_UPTYPE_FLOAT,
  1456.                                  IDC_UPTYPE_LOCAL);
  1457.                EnableWindow (GetDlgItem(hDlg, IDC_UPTYPE_FLOAT), FALSE);
  1458.                EnableWindow (GetDlgItem(hDlg, IDC_UPTYPE_SLOW), FALSE);
  1459.                EnableWindow (GetDlgItem(hDlg, IDC_UPTYPE_SLOW_TEXT), FALSE);
  1460.                EnableWindow (GetDlgItem(hDlg, IDOK), FALSE);
  1461.            }
  1462.            return TRUE;
  1463.         case WM_COMMAND:
  1464.           switch (LOWORD(wParam)) {
  1465.               case IDOK:
  1466.                   lpUserInfo = (LPUSERINFO) GetWindowLongPtr(hDlg, GWLP_USERDATA);
  1467.                   if (!lpUserInfo) {
  1468.                       EndDialog (hDlg, FALSE);
  1469.                       break;
  1470.                   }
  1471.                   //
  1472.                   // Determine what the user wants
  1473.                   //
  1474.                   if (IsDlgButtonChecked(hDlg, IDC_UPTYPE_LOCAL)) {
  1475.                       lpUserInfo->dwProfileType = USERINFO_LOCAL;
  1476.                   } else if (IsDlgButtonChecked(hDlg, IDC_UPTYPE_SLOW)) {
  1477.                       lpUserInfo->dwProfileType = USERINFO_LOCAL_SLOW_LINK;
  1478.                   } else {
  1479.                       lpUserInfo->dwProfileType = USERINFO_FLOATING;
  1480.                   }
  1481.                   EndDialog(hDlg, TRUE);
  1482.                   break;
  1483.               case IDCANCEL:
  1484.                   EndDialog(hDlg, FALSE);
  1485.                   break;
  1486.               case IDC_UPTYPE_LOCAL:
  1487.                   if (HIWORD(wParam) == BN_CLICKED) {
  1488.                       CheckDlgButton (hDlg, IDC_UPTYPE_SLOW, 0);
  1489.                       EnableWindow (GetDlgItem(hDlg, IDC_UPTYPE_SLOW), FALSE);
  1490.                       EnableWindow (GetDlgItem(hDlg, IDC_UPTYPE_SLOW_TEXT), FALSE);
  1491.                   }
  1492.                   break;
  1493.               case IDC_UPTYPE_FLOAT:
  1494.                   if (HIWORD(wParam) == BN_CLICKED) {
  1495.                       EnableWindow (GetDlgItem(hDlg, IDC_UPTYPE_SLOW), TRUE);
  1496.                       EnableWindow (GetDlgItem(hDlg, IDC_UPTYPE_SLOW_TEXT), TRUE);
  1497.                   }
  1498.                   break;
  1499.               default:
  1500.                   break;
  1501.           }
  1502.           break;
  1503.         case WM_HELP:      // F1
  1504.             WinHelp((HWND)((LPHELPINFO) lParam)->hItemHandle, HELP_FILE, HELP_WM_HELP,
  1505.             (DWORD_PTR) (LPSTR) aUserProfileHelpIds);
  1506.             break;
  1507.         case WM_CONTEXTMENU:      // right mouse click
  1508.             WinHelp((HWND) wParam, HELP_FILE, HELP_CONTEXTMENU,
  1509.             (DWORD_PTR) (LPSTR) aUserProfileHelpIds);
  1510.             return (TRUE);
  1511.     }
  1512.     return (FALSE);
  1513. }
  1514. //*************************************************************
  1515. //
  1516. //  UPInitCopyDlg()
  1517. //
  1518. //  Purpose:    Initializes the copy profile dialog
  1519. //
  1520. //  Parameters: hDlg    -   Dialog box handle
  1521. //              lParam  -   lParam (lpUserInfo)
  1522. //
  1523. //  Return:     TRUE if successful
  1524. //              FALSE if an error occurs
  1525. //
  1526. //  Comments:
  1527. //
  1528. //  History:    Date        Author     Comment
  1529. //              2/26/96     ericflo    Created
  1530. //
  1531. //*************************************************************
  1532. BOOL UPInitCopyDlg (HWND hDlg, LPARAM lParam)
  1533. {
  1534.     LPUSERINFO lpUserInfo;
  1535.     LPUPCOPYINFO lpUPCopyInfo;
  1536.     HKEY hKey;
  1537.     LONG lResult;
  1538.     TCHAR szBuffer[MAX_PATH];
  1539.     TCHAR szTemp[100];
  1540.     TCHAR szTemp2[100];
  1541.     DWORD dwTempSize = 100, dwTemp2Size = 100;
  1542.     PSID pSid;
  1543.     DWORD dwSize, dwType;
  1544.     SID_NAME_USE SidName;
  1545.     lpUserInfo = (LPUSERINFO) lParam;
  1546.     if (!lpUserInfo) {
  1547.         return FALSE;
  1548.     }
  1549.     //
  1550.     // Create a CopyInfo structure
  1551.     //
  1552.     lpUPCopyInfo = MemAlloc(LPTR, sizeof(UPCOPYINFO));
  1553.     if (!lpUPCopyInfo) {
  1554.         return FALSE;
  1555.     }
  1556.     lpUPCopyInfo->dwFlags = 0;
  1557.     lpUPCopyInfo->lpUserInfo = lpUserInfo;
  1558.     //
  1559.     // Get the user's sid
  1560.     //
  1561.     wsprintf (szBuffer, TEXT("%s\%s"), PROFILE_MAPPING, lpUserInfo->lpSid);
  1562.     lResult = RegOpenKeyEx (HKEY_LOCAL_MACHINE,
  1563.                             szBuffer,
  1564.                             0,
  1565.                             KEY_READ,
  1566.                             &hKey);
  1567.     if (lResult != ERROR_SUCCESS) {
  1568.         MemFree (lpUPCopyInfo);
  1569.         return FALSE;
  1570.     }
  1571.     //
  1572.     // Query for the sid size
  1573.     //
  1574.     dwSize = 0;
  1575.     lResult = RegQueryValueEx (hKey,
  1576.                                TEXT("Sid"),
  1577.                                NULL,
  1578.                                &dwType,
  1579.                                NULL,
  1580.                                &dwSize);
  1581.     if (lResult != ERROR_SUCCESS) {
  1582.         RegCloseKey (hKey);
  1583.         MemFree (lpUPCopyInfo);
  1584.         return FALSE;
  1585.     }
  1586.     //
  1587.     // Actually get the sid
  1588.     //
  1589.     pSid = MemAlloc (LPTR, dwSize);
  1590.     if (!pSid) {
  1591.         RegCloseKey (hKey);
  1592.         MemFree (lpUPCopyInfo);
  1593.         return FALSE;
  1594.     }
  1595.     lResult = RegQueryValueEx (hKey,
  1596.                                TEXT("Sid"),
  1597.                                NULL,
  1598.                                &dwType,
  1599.                                (LPBYTE) pSid,
  1600.                                &dwSize);
  1601.     if (lResult != ERROR_SUCCESS) {
  1602.         RegCloseKey (hKey);
  1603.         MemFree (pSid);
  1604.         MemFree (lpUPCopyInfo);
  1605.         return FALSE;
  1606.     }
  1607.     lpUPCopyInfo->pSid = pSid;
  1608.     RegCloseKey (hKey);
  1609.     //
  1610.     // Get the friendly name
  1611.     //
  1612.     if (!LookupAccountSid (NULL, pSid, szTemp, &dwTempSize,
  1613.                            szTemp2, &dwTemp2Size, &SidName)) {
  1614.         MemFree (pSid);
  1615.         MemFree (lpUPCopyInfo);
  1616.         return FALSE;
  1617.     }
  1618.     //
  1619.     // Display the friendly name in the edit control
  1620.     //
  1621.     wsprintf (szBuffer, TEXT("%s\%s"), szTemp2, szTemp);
  1622.     SetDlgItemText (hDlg, IDC_COPY_USER, szBuffer);
  1623.     //
  1624.     // Save the copyinfo structure in the extra words
  1625.     //
  1626.     SetWindowLongPtr (hDlg, GWLP_USERDATA, (LPARAM) lpUPCopyInfo);
  1627.     EnableWindow (GetDlgItem(hDlg, IDOK), FALSE);
  1628.     return TRUE;
  1629. }
  1630. //*************************************************************
  1631. //
  1632. //  UPCopyProfile()
  1633. //
  1634. //  Purpose:    Displays the copy profile dialog box
  1635. //
  1636. //  Parameters: hDlg    -   Dialog box handle
  1637. //
  1638. //  Return:     void
  1639. //
  1640. //  Comments:
  1641. //
  1642. //  History:    Date        Author     Comment
  1643. //              2/13/96     ericflo    Created
  1644. //
  1645. //*************************************************************
  1646. void UPCopyProfile(HWND hDlg)
  1647. {
  1648.     int     selection, iTypeID;
  1649.     HWND    hwndTemp;
  1650.     LPUSERINFO lpUserInfo;
  1651.     LV_ITEM item;
  1652.     //
  1653.     // Get the selected profile
  1654.     //
  1655.     hwndTemp = GetDlgItem (hDlg, IDC_UP_LISTVIEW);
  1656.     selection = GetSelectedItem (hwndTemp);
  1657.     if (selection == -1) {
  1658.         return;
  1659.     }
  1660.     item.mask = LVIF_PARAM;
  1661.     item.iItem = selection;
  1662.     item.iSubItem = 0;
  1663.     if (SendMessage (hwndTemp, LVM_GETITEM, 0, (LPARAM) &item)) {
  1664.         lpUserInfo = (LPUSERINFO) item.lParam;
  1665.     } else {
  1666.         lpUserInfo = NULL;
  1667.     }
  1668.     if (!lpUserInfo) {
  1669.         return;
  1670.     }
  1671.     //
  1672.     // Display the Copy Profile dialog
  1673.     //
  1674.     if (!DialogBoxParam (hInstance, MAKEINTRESOURCE(IDD_UP_COPY), hDlg,
  1675.                          UPCopyDlgProc, (LPARAM)lpUserInfo)) {
  1676.         return;
  1677.     }
  1678. }
  1679. //*************************************************************
  1680. //
  1681. //  UPCopyDlgProc()
  1682. //
  1683. //  Purpose:    Dialog box procedure for copying a profile
  1684. //
  1685. //  Parameters: hDlg    -   handle to the dialog box
  1686. //              uMsg    -   window message
  1687. //              wParam  -   wParam
  1688. //              lParam  -   lParam
  1689. //
  1690. //  Return:     TRUE if message was processed
  1691. //              FALSE if not
  1692. //
  1693. //  Comments:
  1694. //
  1695. //  History:    Date        Author     Comment
  1696. //              2/13/96     ericflo    Created
  1697. //
  1698. //*************************************************************
  1699. INT_PTR APIENTRY UPCopyDlgProc (HWND hDlg, UINT uMsg,
  1700.                              WPARAM wParam, LPARAM lParam)
  1701. {
  1702.     LPUPCOPYINFO lpUPCopyInfo;
  1703.     switch (uMsg) {
  1704.         case WM_INITDIALOG:
  1705.            if (!UPInitCopyDlg(hDlg, lParam)) {
  1706.                EndDialog(hDlg, FALSE);
  1707.            }
  1708.            return TRUE;
  1709.         case WM_COMMAND:
  1710.           switch (LOWORD(wParam)) {
  1711.               case IDOK:
  1712.                   {
  1713.                   TCHAR szDir[MAX_PATH];
  1714.                   TCHAR szTemp[MAX_PATH];
  1715.                   HCURSOR hOldCursor;
  1716.                   lpUPCopyInfo = (LPUPCOPYINFO) GetWindowLongPtr(hDlg, GWLP_USERDATA);
  1717.                   if (!lpUPCopyInfo) {
  1718.                       EndDialog (hDlg, FALSE);
  1719.                       break;
  1720.                   }
  1721.                   GetDlgItemText (hDlg, IDC_COPY_PATH, szTemp, MAX_PATH);
  1722.                   if (ExpandEnvironmentStrings (szTemp, szDir, MAX_PATH) > MAX_PATH) {
  1723.                      lstrcpy (szDir, szTemp);
  1724.                   }
  1725.                   hOldCursor = SetCursor (LoadCursor(NULL, IDC_WAIT));
  1726.                   if (!UPCreateProfile (lpUPCopyInfo, szDir, NULL)) {
  1727.                       SetCursor(hOldCursor);
  1728.                       UPDisplayErrorMessage(hDlg, GetLastError());
  1729.                       break;
  1730.                   }
  1731.                   MemFree (lpUPCopyInfo->pSid);
  1732.                   MemFree (lpUPCopyInfo);
  1733.                   SetCursor(hOldCursor);
  1734.                   EndDialog(hDlg, TRUE);
  1735.                   }
  1736.                   break;
  1737.               case IDCANCEL:
  1738.                   lpUPCopyInfo = (LPUPCOPYINFO) GetWindowLongPtr(hDlg, GWLP_USERDATA);
  1739.                   if (lpUPCopyInfo) {
  1740.                       MemFree (lpUPCopyInfo->pSid);
  1741.                       MemFree(lpUPCopyInfo);
  1742.                   }
  1743.                   EndDialog(hDlg, FALSE);
  1744.                   break;
  1745.               case IDC_COPY_BROWSE:
  1746.                   {
  1747.                   BROWSEINFO BrowseInfo;
  1748.                   TCHAR      szBuffer[MAX_PATH];
  1749.                   LPITEMIDLIST pidl;
  1750.                   LoadString(hInstance, IDS_UP_DIRPICK, szBuffer, MAX_PATH);
  1751.                   BrowseInfo.hwndOwner = hDlg;
  1752.                   BrowseInfo.pidlRoot = NULL;
  1753.                   BrowseInfo.pszDisplayName = szBuffer;
  1754.                   BrowseInfo.lpszTitle = szBuffer;
  1755.                   BrowseInfo.ulFlags = BIF_RETURNONLYFSDIRS;
  1756.                   BrowseInfo.lpfn = NULL;
  1757.                   BrowseInfo.lParam = 0;
  1758.                   pidl = SHBrowseForFolder (&BrowseInfo);
  1759.                   if (pidl) {
  1760.                      SHGetPathFromIDList(pidl, szBuffer);
  1761.                      SHFree (pidl);
  1762.                      SetDlgItemText (hDlg, IDC_COPY_PATH, szBuffer);
  1763.                      SetFocus (GetDlgItem(hDlg, IDOK));
  1764.                   }
  1765.                   }
  1766.                   break;
  1767.               case IDC_COPY_PATH:
  1768.                   if (HIWORD(wParam) == EN_UPDATE) {
  1769.                       if (SendDlgItemMessage(hDlg, IDC_COPY_PATH,
  1770.                                              EM_LINELENGTH, 0, 0)) {
  1771.                           EnableWindow (GetDlgItem(hDlg, IDOK), TRUE);
  1772.                       } else {
  1773.                           EnableWindow (GetDlgItem(hDlg, IDOK), FALSE);
  1774.                       }
  1775.                   }
  1776.                   break;
  1777.               case IDC_COPY_CHANGE:
  1778.                   {
  1779.                   USERBROWSER UserParms;
  1780.                   HUSERBROW hBrowse;
  1781.                   LPUSERDETAILS lpUserDetails;
  1782.                   DWORD dwSize = 1024;
  1783.                   WCHAR szTitle[100];
  1784.                   TCHAR szUserName[200];
  1785.                   PSID pNewSid;
  1786.                   lpUPCopyInfo = (LPUPCOPYINFO) GetWindowLongPtr(hDlg, GWLP_USERDATA);
  1787.                   if (!lpUPCopyInfo) {
  1788.                       EndDialog (hDlg, FALSE);
  1789.                       break;
  1790.                   }
  1791.                   lpUserDetails = MemAlloc (LPTR, dwSize);
  1792.                   if (!lpUserDetails) {
  1793.                       break;
  1794.                   }
  1795.                   LoadStringW (hInstance, IDS_UP_PICKUSER, szTitle, 100);
  1796.                   UserParms.ulStructSize = sizeof(USERBROWSER);
  1797.                   UserParms.fExpandNames = FALSE;
  1798.                   UserParms.hwndOwner = hDlg;
  1799.                   UserParms.pszTitle = szTitle;
  1800.                   UserParms.pszInitialDomain = NULL;
  1801.                   UserParms.ulHelpContext = IDH_USERPROFILE + 20;
  1802.                   UserParms.pszHelpFileName = L"SYSDM.HLP";
  1803.                   UserParms.Flags = USRBROWS_SINGLE_SELECT |
  1804.                                     USRBROWS_INCL_REMOTE_USERS |
  1805.                                     USRBROWS_INCL_INTERACTIVE |
  1806.                                     USRBROWS_INCL_EVERYONE |
  1807.                                     USRBROWS_SHOW_ALL;
  1808.                   //
  1809.                   // Display the dialog box
  1810.                   //
  1811.                   hBrowse = OpenUserBrowser (&UserParms);
  1812.                   if (!hBrowse) {
  1813.                       MemFree (lpUserDetails);
  1814.                       break;
  1815.                   }
  1816.                   //
  1817.                   // Get the user's selection
  1818.                   //
  1819.                   if (!EnumUserBrowserSelection(hBrowse, lpUserDetails, &dwSize)) {
  1820.                       if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
  1821.                           MemFree (lpUserDetails);
  1822.                           CloseUserBrowser(hBrowse);
  1823.                           break;
  1824.                       }
  1825.                       MemFree (lpUserDetails);
  1826.                       lpUserDetails = MemAlloc(LPTR, dwSize + 2);
  1827.                       if (!lpUserDetails) {
  1828.                           MemFree (lpUserDetails);
  1829.                           CloseUserBrowser(hBrowse);
  1830.                           break;
  1831.                       }
  1832.                       if (!EnumUserBrowserSelection(hBrowse, lpUserDetails, &dwSize)) {
  1833.                           MemFree(lpUserDetails);
  1834.                           CloseUserBrowser(hBrowse);
  1835.                           break;
  1836.                       }
  1837.                   }
  1838.                   //
  1839.                   // Duplicate the sid
  1840.                   //
  1841.                   dwSize = GetLengthSid (lpUserDetails->psidUser);
  1842.                   pNewSid = MemAlloc (LPTR, dwSize);
  1843.                   if (!pNewSid) {
  1844.                       MemFree(lpUserDetails);
  1845.                       CloseUserBrowser(hBrowse);
  1846.                       break;
  1847.                   }
  1848.                   if (!CopySid (dwSize, pNewSid, lpUserDetails->psidUser)) {
  1849.                       MemFree (pNewSid);
  1850.                       MemFree(lpUserDetails);
  1851.                       CloseUserBrowser(hBrowse);
  1852.                       break;
  1853.                   }
  1854.                   //
  1855.                   // Save our new sid
  1856.                   //
  1857.                   MemFree (lpUPCopyInfo->pSid);
  1858.                   lpUPCopyInfo->pSid = pNewSid;
  1859.                   //
  1860.                   // Update the edit control
  1861.                   lstrcpy(szUserName, lpUserDetails->pszDomainName);
  1862.                   lstrcat(szUserName, TEXT("\"));
  1863.                   lstrcat(szUserName, lpUserDetails->pszAccountName);
  1864.                   SetDlgItemText (hDlg, IDC_COPY_USER, szUserName);
  1865.                   //
  1866.                   // Cleanup
  1867.                   //
  1868.                   CloseUserBrowser (hBrowse);
  1869.                   MemFree (lpUserDetails);
  1870.                   }
  1871.                   break;
  1872.               default:
  1873.                   break;
  1874.           }
  1875.           break;
  1876.         case WM_HELP:      // F1
  1877.             WinHelp((HWND)((LPHELPINFO) lParam)->hItemHandle, HELP_FILE, HELP_WM_HELP,
  1878.             (DWORD_PTR) (LPSTR) aUserProfileHelpIds);
  1879.             break;
  1880.         case WM_CONTEXTMENU:      // right mouse click
  1881.             WinHelp((HWND) wParam, HELP_FILE, HELP_CONTEXTMENU,
  1882.             (DWORD_PTR) (LPSTR) aUserProfileHelpIds);
  1883.             return (TRUE);
  1884.     }
  1885.     return (FALSE);
  1886. }
  1887. //*************************************************************
  1888. //
  1889. //  UPCreateProfile()
  1890. //
  1891. //  Purpose:    Creates a copy of the specified profile with
  1892. //              the correct security.
  1893. //
  1894. //  Parameters: lpUPCopyInfo  -   Copy Dialog information
  1895. //              lpDest      -   Destination directory
  1896. //              pNewSecDesc -   New security descriptor
  1897. //
  1898. //  Return:     TRUE if successful
  1899. //              FALSE if an error occurs
  1900. //
  1901. //  Comments:
  1902. //
  1903. //  History:    Date        Author     Comment
  1904. //              2/13/96     ericflo    Created
  1905. //
  1906. //*************************************************************
  1907. BOOL UPCreateProfile (LPUPCOPYINFO lpUPCopyInfo, LPTSTR lpDest,
  1908.                       PSECURITY_DESCRIPTOR pNewSecDesc)
  1909. {
  1910.     HKEY RootKey, hKey;
  1911.     SECURITY_DESCRIPTOR sd;
  1912.     SECURITY_ATTRIBUTES sa;
  1913.     SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY;
  1914.     PACL pAcl = NULL;
  1915.     PSID  psidUser = NULL, psidSystem = NULL, psidAdmin = NULL;
  1916.     DWORD cbAcl, AceIndex, dwSize, dwType;
  1917.     ACE_HEADER * lpAceHeader;
  1918.     HANDLE hFile;
  1919.     BOOL bMandatory = FALSE;
  1920.     TCHAR szTempPath[MAX_PATH];
  1921.     TCHAR szBuffer[MAX_PATH];
  1922.     TCHAR szHive[MAX_PATH];
  1923.     BOOL bRetVal = FALSE;
  1924.     HKEY hKeyProfile;
  1925.     LONG Error;
  1926.     LPTSTR lpEnd;
  1927.     TCHAR szExcludeList1[MAX_PATH];
  1928.     TCHAR szExcludeList2[MAX_PATH];
  1929.     TCHAR szExcludeList[2 * MAX_PATH];
  1930.     if (!lpDest || !(*lpDest)) {
  1931.         return FALSE;
  1932.     }
  1933.     //
  1934.     // Create the security descriptor
  1935.     //
  1936.     //
  1937.     // User Sid
  1938.     //
  1939.     psidUser = lpUPCopyInfo->pSid;
  1940.     //
  1941.     // Get the system sid
  1942.     //
  1943.     if (!AllocateAndInitializeSid(&authNT, 1, SECURITY_LOCAL_SYSTEM_RID,
  1944.                                   0, 0, 0, 0, 0, 0, 0, &psidSystem)) {
  1945.          goto Exit;
  1946.     }
  1947.     //
  1948.     // Get the admin sid
  1949.     //
  1950.     if (!AllocateAndInitializeSid(&authNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
  1951.                                   DOMAIN_ALIAS_RID_ADMINS, 0, 0,
  1952.                                   0, 0, 0, 0, &psidAdmin)) {
  1953.          goto Exit;
  1954.     }
  1955.     //
  1956.     // Allocate space for the ACL
  1957.     //
  1958.     cbAcl = (2 * GetLengthSid (psidUser)) + (2 * GetLengthSid (psidSystem)) +
  1959.             (2 * GetLengthSid (psidAdmin)) + sizeof(ACL) +
  1960.             (6 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)));
  1961.     pAcl = (PACL) MemAlloc(LPTR, cbAcl);
  1962.     if (!pAcl) {
  1963.         goto Exit;
  1964.     }
  1965.     if (!InitializeAcl(pAcl, cbAcl, ACL_REVISION)) {
  1966.         goto Exit;
  1967.     }
  1968.     //
  1969.     // Add Aces for User, System, and Admin.  Non-inheritable ACEs first
  1970.     //
  1971.     AceIndex = 0;
  1972.     if (!AddAccessAllowedAce(pAcl, ACL_REVISION, FILE_ALL_ACCESS, psidUser)) {
  1973.         goto Exit;
  1974.     }
  1975.     AceIndex++;
  1976.     if (!AddAccessAllowedAce(pAcl, ACL_REVISION, FILE_ALL_ACCESS, psidSystem)) {
  1977.         goto Exit;
  1978.     }
  1979.     AceIndex++;
  1980.     if (!AddAccessAllowedAce(pAcl, ACL_REVISION, FILE_ALL_ACCESS, psidAdmin)) {
  1981.         goto Exit;
  1982.     }
  1983.     //
  1984.     // Now the inheritable ACEs
  1985.     //
  1986.     AceIndex++;
  1987.     if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidUser)) {
  1988.         goto Exit;
  1989.     }
  1990.     if (!GetAce(pAcl, AceIndex, &lpAceHeader)) {
  1991.         goto Exit;
  1992.     }
  1993.     lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
  1994.     AceIndex++;
  1995.     if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidSystem)) {
  1996.         goto Exit;
  1997.     }
  1998.     if (!GetAce(pAcl, AceIndex, &lpAceHeader)) {
  1999.         goto Exit;
  2000.     }
  2001.     lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
  2002.     AceIndex++;
  2003.     if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidAdmin)) {
  2004.         goto Exit;
  2005.     }
  2006.     if (!GetAce(pAcl, AceIndex, &lpAceHeader)) {
  2007.         goto Exit;
  2008.     }
  2009.     lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
  2010.     //
  2011.     // Put together the security descriptor
  2012.     //
  2013.     if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) {
  2014.         goto Exit;
  2015.     }
  2016.     if (!SetSecurityDescriptorDacl(&sd, TRUE, pAcl, FALSE)) {
  2017.         goto Exit;
  2018.     }
  2019.     //
  2020.     // Add the security descriptor to the sa structure
  2021.     //
  2022.     sa.nLength = sizeof(sa);
  2023.     sa.lpSecurityDescriptor = &sd;
  2024.     sa.bInheritHandle = FALSE;
  2025.     //
  2026.     // Create the destination directory
  2027.     //
  2028.     if (!CreateNestedDirectory (lpDest, &sa)) {
  2029.         goto Exit;
  2030.     }
  2031.     //
  2032.     // Save/copy the user's profile to a temp file
  2033.     //
  2034.     if (!GetTempPath(MAX_PATH, szTempPath)) {
  2035.         goto Exit;
  2036.     }
  2037.     if (!GetTempFileName (szTempPath, TEXT("TMP"), 0, szBuffer)) {
  2038.         goto Exit;
  2039.     }
  2040.     DeleteFile (szBuffer);
  2041.     //
  2042.     // Determine if we are working with a mandatory profile
  2043.     //
  2044.     lstrcpy (szHive, lpUPCopyInfo->lpUserInfo->lpProfile);
  2045.     lpEnd = CheckSlash(szHive);
  2046.     lstrcpy (lpEnd, TEXT("ntuser.man"));
  2047.     hFile = CreateFile(szHive, GENERIC_READ, FILE_SHARE_READ, NULL,
  2048.                        OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  2049.     if (hFile != INVALID_HANDLE_VALUE) {
  2050.         CloseHandle (hFile);
  2051.         bMandatory = TRUE;
  2052.     }
  2053.     //
  2054.     // Test if the requested profile is in use.
  2055.     //
  2056.     if (IsProfileInUse (lpUPCopyInfo->lpUserInfo->lpSid)) {
  2057.         Error = RegOpenKeyEx (HKEY_USERS, lpUPCopyInfo->lpUserInfo->lpSid, 0,
  2058.                               KEY_READ, &hKeyProfile);
  2059.         if (Error != ERROR_SUCCESS) {
  2060.             goto Exit;
  2061.         }
  2062.         Error = MyRegSaveKey (hKeyProfile, szBuffer);
  2063.         RegCloseKey (hKeyProfile);
  2064.         if (Error != ERROR_SUCCESS) {
  2065.             DeleteFile (szBuffer);
  2066.             goto Exit;
  2067.         }
  2068.     } else {
  2069.        if (!bMandatory) {
  2070.            lstrcpy (lpEnd, TEXT("ntuser.dat"));
  2071.        }
  2072.        if (!CopyFile(szHive, szBuffer, FALSE)) {
  2073.            goto Exit;
  2074.        }
  2075.     }
  2076.     //
  2077.     // Apply security to the hive
  2078.     //
  2079.     Error = MyRegLoadKey (HKEY_USERS, TEMP_PROFILE, szBuffer);
  2080.     if (Error != ERROR_SUCCESS) {
  2081.         DeleteFile (szBuffer);
  2082.         goto Exit;
  2083.     }
  2084.     bRetVal = ApplyHiveSecurity(TEMP_PROFILE, psidUser);
  2085.     //
  2086.     // Query for the user's exclusion list
  2087.     //
  2088.     if (bRetVal) {
  2089.         //
  2090.         // Open the root of the user's profile
  2091.         //
  2092.         if (RegOpenKeyEx(HKEY_USERS, TEMP_PROFILE, 0, KEY_READ, &RootKey) == ERROR_SUCCESS) {
  2093.              //
  2094.              // Check for a list of directories to exclude both user preferences
  2095.              // and user policy
  2096.              //
  2097.              szExcludeList1[0] = TEXT('');
  2098.              if (RegOpenKeyEx (RootKey,
  2099.                                TEXT("Software\Microsoft\Windows NT\CurrentVersion\Winlogon"),
  2100.                                0, KEY_READ, &hKey) == ERROR_SUCCESS) {
  2101.                  dwSize = sizeof(szExcludeList1);
  2102.                  RegQueryValueEx (hKey,
  2103.                                   TEXT("ExcludeProfileDirs"),
  2104.                                   NULL,
  2105.                                   &dwType,
  2106.                                   (LPBYTE) szExcludeList1,
  2107.                                   &dwSize);
  2108.                  RegCloseKey (hKey);
  2109.              }
  2110.              szExcludeList2[0] = TEXT('');
  2111.              if (RegOpenKeyEx (RootKey,
  2112.                                TEXT("Software\Policies\Microsoft\Windows\System"),
  2113.                                0, KEY_READ, &hKey) == ERROR_SUCCESS) {
  2114.                  dwSize = sizeof(szExcludeList2);
  2115.                  RegQueryValueEx (hKey,
  2116.                                   TEXT("ExcludeProfileDirs"),
  2117.                                   NULL,
  2118.                                   &dwType,
  2119.                                   (LPBYTE) szExcludeList2,
  2120.                                   &dwSize);
  2121.                  RegCloseKey (hKey);
  2122.              }
  2123.              //
  2124.              // Merge the user preferences and policy together
  2125.              //
  2126.              szExcludeList[0] = TEXT('');
  2127.              if (szExcludeList1[0] != TEXT('')) {
  2128.                  lstrcpy (szExcludeList, szExcludeList1);
  2129.              }
  2130.              if (szExcludeList2[0] != TEXT('')) {
  2131.                  if (szExcludeList[0] != TEXT('')) {
  2132.                      lstrcat (szExcludeList, TEXT(";"));
  2133.                  }
  2134.                  lstrcat (szExcludeList, szExcludeList2);
  2135.              }
  2136.             RegCloseKey (RootKey);
  2137.         }
  2138.     }
  2139.     //
  2140.     // Unload the hive
  2141.     //
  2142.     MyRegUnLoadKey(HKEY_USERS, TEMP_PROFILE);
  2143.     if (!bRetVal) {
  2144.         DeleteFile (szBuffer);
  2145.         lstrcat (szBuffer, TEXT(".log"));
  2146.         DeleteFile (szBuffer);
  2147.         goto Exit;
  2148.     }
  2149.     //
  2150.     // Copy the profile without the hive
  2151.     //
  2152.     bRetVal = CopyProfileDirectoryEx (lpUPCopyInfo->lpUserInfo->lpProfile,
  2153.                                       lpDest,
  2154.                                       CPD_IGNOREHIVE |
  2155.                                       CPD_COPYIFDIFFERENT |
  2156.                                       CPD_SYNCHRONIZE |
  2157.                                       CPD_USEEXCLUSIONLIST |
  2158.                                       CPD_IGNORESECURITY |
  2159.                                       CPD_DELDESTEXCLUSIONS,
  2160.                                       NULL,
  2161.                                       (szExcludeList[0] != TEXT('')) ?
  2162.                                       szExcludeList : NULL);
  2163.     if (!bRetVal) {
  2164.         DeleteFile(szBuffer);
  2165.         lstrcat (szBuffer, TEXT(".log"));
  2166.         DeleteFile (szBuffer);
  2167.         goto Exit;
  2168.     }
  2169.     //
  2170.     // Now copy the hive
  2171.     //
  2172.     lstrcpy (szHive, lpDest);
  2173.     lpEnd = CheckSlash (szHive);
  2174.     if (bMandatory) {
  2175.         lstrcpy (lpEnd, TEXT("ntuser.man"));
  2176.     } else {
  2177.         lstrcpy (lpEnd, TEXT("ntuser.dat"));
  2178.     }
  2179.     bRetVal = CopyFile (szBuffer, szHive, FALSE);
  2180.     //
  2181.     // Delete the temp file (and log file)
  2182.     //
  2183.     DeleteFile (szBuffer);
  2184.     lstrcat (szBuffer, TEXT(".log"));
  2185.     DeleteFile (szBuffer);
  2186. Exit:
  2187.     //
  2188.     // Free the sids and acl
  2189.     //
  2190.     if (psidSystem) {
  2191.         FreeSid(psidSystem);
  2192.     }
  2193.     if (psidAdmin) {
  2194.         FreeSid(psidAdmin);
  2195.     }
  2196.     if (pAcl) {
  2197.         MemFree (pAcl);
  2198.     }
  2199.     return (bRetVal);
  2200. }
  2201. //*************************************************************
  2202. //
  2203. //  UPDisplayErrorMessage()
  2204. //
  2205. //  Purpose:    Display an error message
  2206. //
  2207. //  Parameters: hWnd            -   parent window handle
  2208. //              uiSystemError   -   Error code
  2209. //
  2210. //  Return:     void
  2211. //
  2212. //  Comments:
  2213. //
  2214. //  History:    Date        Author     Comment
  2215. //              2/14/96     ericflo    Created
  2216. //
  2217. //*************************************************************
  2218. VOID UPDisplayErrorMessage(HWND hWnd, UINT uiSystemError)
  2219. {
  2220.    TCHAR szMessage[MAX_PATH];
  2221.    TCHAR szTitle[100];
  2222.    //
  2223.    // retrieve the string matching the Win32 system error
  2224.    //
  2225.    FormatMessage(
  2226.             FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,
  2227.             NULL,
  2228.             uiSystemError,
  2229.             MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
  2230.             szMessage,
  2231.             MAX_PATH,
  2232.             NULL);
  2233.    //
  2234.    // display a message box with this error
  2235.    //
  2236.    LoadString (hInstance, IDS_UP_ERRORTITLE, szTitle, 100);
  2237.    MessageBox(hWnd, szMessage, szTitle, MB_OK | MB_ICONSTOP);
  2238.    return;
  2239. }
  2240. //*************************************************************
  2241. //
  2242. //  ApplySecurityToRegistryTree()
  2243. //
  2244. //  Purpose:    Applies the passed security descriptor to the passed
  2245. //              key and all its descendants.  Only the parts of
  2246. //              the descriptor inddicated in the security
  2247. //              info value are actually applied to each registry key.
  2248. //
  2249. //  Parameters: RootKey   -     Registry key
  2250. //              pSD       -     Security Descriptor
  2251. //
  2252. //  Return:     ERROR_SUCCESS if successful
  2253. //
  2254. //  Comments:
  2255. //
  2256. //  History:    Date        Author     Comment
  2257. //              7/19/95     ericflo    Created
  2258. //
  2259. //*************************************************************
  2260. DWORD ApplySecurityToRegistryTree(HKEY RootKey, PSECURITY_DESCRIPTOR pSD)
  2261. {
  2262.     DWORD Error;
  2263.     DWORD SubKeyIndex;
  2264.     LPTSTR SubKeyName;
  2265.     HKEY SubKey;
  2266.     DWORD cchSubKeySize = MAX_PATH + 1;
  2267.     //
  2268.     // First apply security
  2269.     //
  2270.     RegSetKeySecurity(RootKey, DACL_SECURITY_INFORMATION, pSD);
  2271.     //
  2272.     // Open each sub-key and apply security to its sub-tree
  2273.     //
  2274.     SubKeyIndex = 0;
  2275.     SubKeyName = MemAlloc (LPTR, cchSubKeySize * sizeof(TCHAR));
  2276.     if (!SubKeyName) {
  2277.         return GetLastError();
  2278.     }
  2279.     while (TRUE) {
  2280.         //
  2281.         // Get the next sub-key name
  2282.         //
  2283.         Error = RegEnumKey(RootKey, SubKeyIndex, SubKeyName, cchSubKeySize);
  2284.         if (Error != ERROR_SUCCESS) {
  2285.             if (Error == ERROR_NO_MORE_ITEMS) {
  2286.                 //
  2287.                 // Successful end of enumeration
  2288.                 //
  2289.                 Error = ERROR_SUCCESS;
  2290.             }
  2291.             break;
  2292.         }
  2293.         //
  2294.         // Open the sub-key
  2295.         //
  2296.         Error = RegOpenKeyEx(RootKey,
  2297.                              SubKeyName,
  2298.                              0,
  2299.                              WRITE_DAC | KEY_ENUMERATE_SUB_KEYS | READ_CONTROL,
  2300.                              &SubKey);
  2301.         if (Error == ERROR_SUCCESS) {
  2302.             //
  2303.             // Apply security to the sub-tree
  2304.             //
  2305.             ApplySecurityToRegistryTree(SubKey, pSD);
  2306.             //
  2307.             // We're finished with the sub-key
  2308.             //
  2309.             RegCloseKey(SubKey);
  2310.         }
  2311.         //
  2312.         // Go enumerate the next sub-key
  2313.         //
  2314.         SubKeyIndex ++;
  2315.     }
  2316.     MemFree (SubKeyName);
  2317.     return Error;
  2318. }
  2319. //*************************************************************
  2320. //
  2321. //  ApplyHiveSecurity()
  2322. //
  2323. //  Purpose:    Initializes the new user hive created by copying
  2324. //              the default hive.
  2325. //
  2326. //  Parameters: lpHiveName      -   Name of hive in HKEY_USERS
  2327. //              pSid            -   Sid (used by CreateNewUser)
  2328. //
  2329. //  Return:     TRUE if successful
  2330. //              FALSE if an error occurs
  2331. //
  2332. //  Comments:
  2333. //
  2334. //  History:    Date        Author     Comment
  2335. //              7/18/95     ericflo    Created
  2336. //
  2337. //*************************************************************
  2338. BOOL ApplyHiveSecurity(LPTSTR lpHiveName, PSID pSid)
  2339. {
  2340.     DWORD Error;
  2341.     HKEY RootKey;
  2342.     SECURITY_DESCRIPTOR sd;
  2343.     SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY;
  2344.     PACL pAcl = NULL;
  2345.     PSID  psidUser = pSid, psidSystem = NULL, psidAdmin = NULL;
  2346.     DWORD cbAcl, AceIndex;
  2347.     ACE_HEADER * lpAceHeader;
  2348.     BOOL bRetVal = FALSE;
  2349.     //
  2350.     // Get the system sid
  2351.     //
  2352.     if (!AllocateAndInitializeSid(&authNT, 1, SECURITY_LOCAL_SYSTEM_RID,
  2353.                                   0, 0, 0, 0, 0, 0, 0, &psidSystem)) {
  2354.          goto Exit;
  2355.     }
  2356.     //
  2357.     // Get the admin sid
  2358.     //
  2359.     if (!AllocateAndInitializeSid(&authNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
  2360.                                   DOMAIN_ALIAS_RID_ADMINS, 0, 0,
  2361.                                   0, 0, 0, 0, &psidAdmin)) {
  2362.          goto Exit;
  2363.     }
  2364.     //
  2365.     // Allocate space for the ACL
  2366.     //
  2367.     cbAcl = (2 * GetLengthSid (psidUser)) + (2 * GetLengthSid (psidSystem)) +
  2368.             (2 * GetLengthSid (psidAdmin)) + sizeof(ACL) +
  2369.             (6 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)));
  2370.     pAcl = (PACL) MemAlloc(LPTR, cbAcl);
  2371.     if (!pAcl) {
  2372.         goto Exit;
  2373.     }
  2374.     if (!InitializeAcl(pAcl, cbAcl, ACL_REVISION)) {
  2375.         goto Exit;
  2376.     }
  2377.     //
  2378.     // Add Aces for User, System, and Admin.  Non-inheritable ACEs first
  2379.     //
  2380.     AceIndex = 0;
  2381.     if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_ALL_ACCESS, psidUser)) {
  2382.         goto Exit;
  2383.     }
  2384.     AceIndex++;
  2385.     if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_ALL_ACCESS, psidSystem)) {
  2386.         goto Exit;
  2387.     }
  2388.     AceIndex++;
  2389.     if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_ALL_ACCESS, psidAdmin)) {
  2390.         goto Exit;
  2391.     }
  2392.     //
  2393.     // Now the inheritable ACEs
  2394.     //
  2395.     AceIndex++;
  2396.     if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidUser)) {
  2397.         goto Exit;
  2398.     }
  2399.     if (!GetAce(pAcl, AceIndex, &lpAceHeader)) {
  2400.         goto Exit;
  2401.     }
  2402.     lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
  2403.     AceIndex++;
  2404.     if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidSystem)) {
  2405.         goto Exit;
  2406.     }
  2407.     if (!GetAce(pAcl, AceIndex, &lpAceHeader)) {
  2408.         goto Exit;
  2409.     }
  2410.     lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
  2411.     AceIndex++;
  2412.     if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidAdmin)) {
  2413.         goto Exit;
  2414.     }
  2415.     if (!GetAce(pAcl, AceIndex, &lpAceHeader)) {
  2416.         goto Exit;
  2417.     }
  2418.     lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
  2419.     //
  2420.     // Put together the security descriptor
  2421.     //
  2422.     if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) {
  2423.         goto Exit;
  2424.     }
  2425.     if (!SetSecurityDescriptorDacl(&sd, TRUE, pAcl, FALSE)) {
  2426.         goto Exit;
  2427.     }
  2428.     //
  2429.     // Open the root of the user's profile
  2430.     //
  2431.     Error = RegOpenKeyEx(HKEY_USERS,
  2432.                          lpHiveName,
  2433.                          0,
  2434.                          WRITE_DAC | KEY_ENUMERATE_SUB_KEYS | READ_CONTROL,
  2435.                          &RootKey);
  2436.     if (Error == ERROR_SUCCESS) {
  2437.         //
  2438.         // Set the security descriptor on the entire tree
  2439.         //
  2440.         Error = ApplySecurityToRegistryTree(RootKey, &sd);
  2441.         if (Error == ERROR_SUCCESS) {
  2442.             bRetVal = TRUE;
  2443.         }
  2444.         RegFlushKey (RootKey);
  2445.         RegCloseKey(RootKey);
  2446.     }
  2447. Exit:
  2448.     //
  2449.     // Free the sids and acl
  2450.     //
  2451.     if (psidSystem) {
  2452.         FreeSid(psidSystem);
  2453.     }
  2454.     if (psidAdmin) {
  2455.         FreeSid(psidAdmin);
  2456.     }
  2457.     if (pAcl) {
  2458.         MemFree (pAcl);
  2459.     }
  2460.     return(bRetVal);
  2461. }