1 /* 2 * PROJECT: ReactOS System Control Panel Applet 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: dll/cpl/sysdm/userprofile.c 5 * PURPOSE: Computer settings for networking 6 * COPYRIGHT: Copyright Thomas Weidenmueller <w3seek@reactos.org> 7 * Copyright 2006 Ged Murphy <gedmurphy@gmail.com> 8 * 9 */ 10 11 #include "precomp.h" 12 #include <sddl.h> 13 14 15 typedef struct _PROFILEDATA 16 { 17 BOOL bMyProfile; 18 PWSTR pszFullName; 19 } PROFILEDATA, *PPROFILEDATA; 20 21 22 static VOID 23 SetListViewColumns(HWND hwndListView) 24 { 25 LV_COLUMN column; 26 RECT rect; 27 TCHAR szStr[32]; 28 29 GetClientRect(hwndListView, &rect); 30 31 SendMessage(hwndListView, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT); 32 33 memset(&column, 0x00, sizeof(column)); 34 column.mask = LVCF_FMT | LVCF_WIDTH | LVCF_SUBITEM | LVCF_TEXT; 35 column.fmt = LVCFMT_LEFT; 36 column.cx = (INT)((rect.right - rect.left) * 0.40); 37 column.iSubItem = 0; 38 LoadString(hApplet, IDS_USERPROFILE_NAME, szStr, ARRAYSIZE(szStr)); 39 column.pszText = szStr; 40 (void)ListView_InsertColumn(hwndListView, 0, &column); 41 42 column.fmt = LVCFMT_RIGHT; 43 column.cx = (INT)((rect.right - rect.left) * 0.15); 44 column.iSubItem = 1; 45 LoadString(hApplet, IDS_USERPROFILE_SIZE, szStr, ARRAYSIZE(szStr)); 46 column.pszText = szStr; 47 (void)ListView_InsertColumn(hwndListView, 1, &column); 48 49 column.fmt = LVCFMT_LEFT; 50 column.cx = (INT)((rect.right - rect.left) * 0.15); 51 column.iSubItem = 2; 52 LoadString(hApplet, IDS_USERPROFILE_TYPE, szStr, ARRAYSIZE(szStr)); 53 column.pszText = szStr; 54 (void)ListView_InsertColumn(hwndListView, 2, &column); 55 56 column.fmt = LVCFMT_LEFT; 57 column.cx = (INT)((rect.right - rect.left) * 0.15); 58 column.iSubItem = 3; 59 LoadString(hApplet, IDS_USERPROFILE_STATUS, szStr, ARRAYSIZE(szStr)); 60 column.pszText = szStr; 61 (void)ListView_InsertColumn(hwndListView, 3, &column); 62 63 column.fmt = LVCFMT_LEFT; 64 column.cx = (INT)((rect.right - rect.left) * 0.15) - GetSystemMetrics(SM_CYHSCROLL); 65 column.iSubItem = 4; 66 LoadString(hApplet, IDS_USERPROFILE_MODIFIED, szStr, ARRAYSIZE(szStr)); 67 column.pszText = szStr; 68 (void)ListView_InsertColumn(hwndListView, 4, &column); 69 } 70 71 72 static VOID 73 AddUserProfile( 74 _In_ HWND hwndListView, 75 _In_ LPTSTR lpProfileSid, 76 _In_ PSID pMySid) 77 { 78 PPROFILEDATA pProfileData = NULL; 79 PWSTR pszAccountName = NULL; 80 PWSTR pszDomainName = NULL; 81 SID_NAME_USE Use; 82 DWORD dwAccountNameSize, dwDomainNameSize; 83 DWORD dwProfileData; 84 PWSTR ptr; 85 PSID pSid = NULL; 86 LV_ITEM lvi; 87 88 if (!ConvertStringSidToSid(lpProfileSid, 89 &pSid)) 90 return; 91 92 dwAccountNameSize = 0; 93 dwDomainNameSize = 0; 94 LookupAccountSidW(NULL, 95 pSid, 96 NULL, 97 &dwAccountNameSize, 98 NULL, 99 &dwDomainNameSize, 100 &Use); 101 102 pszDomainName = HeapAlloc(GetProcessHeap(), 103 0, 104 dwDomainNameSize * sizeof(WCHAR)); 105 if (pszDomainName == NULL) 106 goto done; 107 108 pszAccountName = HeapAlloc(GetProcessHeap(), 109 0, 110 dwAccountNameSize * sizeof(WCHAR)); 111 if (pszAccountName == NULL) 112 goto done; 113 114 if (!LookupAccountSidW(NULL, 115 pSid, 116 pszAccountName, 117 &dwAccountNameSize, 118 pszDomainName, 119 &dwDomainNameSize, 120 &Use)) 121 goto done; 122 123 /* Show only the user accounts */ 124 if (Use != SidTypeUser) 125 goto done; 126 127 dwProfileData = sizeof(PROFILEDATA) + 128 ((wcslen(pszDomainName) + wcslen(pszAccountName) + 2) * sizeof(WCHAR)); 129 pProfileData = HeapAlloc(GetProcessHeap(), 130 0, 131 dwProfileData); 132 if (pProfileData == NULL) 133 goto done; 134 135 pProfileData->bMyProfile = EqualSid(pMySid, pSid); 136 137 ptr = (PWSTR)((ULONG_PTR)pProfileData + sizeof(PROFILEDATA)); 138 pProfileData->pszFullName = ptr; 139 140 wsprintf(pProfileData->pszFullName, L"%s\\%s", pszDomainName, pszAccountName); 141 142 memset(&lvi, 0x00, sizeof(lvi)); 143 lvi.mask = LVIF_TEXT | LVIF_STATE | LVIF_PARAM; 144 lvi.pszText = pProfileData->pszFullName; 145 lvi.state = 0; 146 lvi.lParam = (LPARAM)pProfileData; 147 ListView_InsertItem(hwndListView, &lvi); 148 149 done: 150 if (pszDomainName != NULL) 151 HeapFree(GetProcessHeap(), 0, pszDomainName); 152 153 if (pszAccountName != NULL) 154 HeapFree(GetProcessHeap(), 0, pszAccountName); 155 156 if (pSid != NULL) 157 LocalFree(pSid); 158 } 159 160 161 static VOID 162 AddUserProfiles(HWND hwndListView) 163 { 164 HKEY hKeyUserProfiles = INVALID_HANDLE_VALUE; 165 DWORD dwIndex; 166 WCHAR szProfileSid[64]; 167 DWORD dwSidLength; 168 FILETIME ftLastWrite; 169 DWORD dwSize; 170 HANDLE hToken = NULL; 171 PTOKEN_USER pTokenUser = NULL; 172 173 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) 174 return; 175 176 GetTokenInformation(hToken, TokenUser, NULL, 0, &dwSize); 177 if (dwSize == 0) 178 goto done; 179 180 pTokenUser = HeapAlloc(GetProcessHeap(), 0, dwSize); 181 if (pTokenUser == NULL) 182 goto done; 183 184 if (!GetTokenInformation(hToken, TokenUser, pTokenUser, dwSize, &dwSize)) 185 goto done; 186 187 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, 188 L"Software\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList", 189 0, 190 KEY_READ, 191 &hKeyUserProfiles)) 192 goto done; 193 194 for (dwIndex = 0; ; dwIndex++) 195 { 196 dwSidLength = ARRAYSIZE(szProfileSid); 197 if (RegEnumKeyExW(hKeyUserProfiles, 198 dwIndex, 199 szProfileSid, 200 &dwSidLength, 201 NULL, 202 NULL, 203 NULL, 204 &ftLastWrite)) 205 break; 206 207 AddUserProfile(hwndListView, szProfileSid, pTokenUser->User.Sid); 208 } 209 210 if (ListView_GetItemCount(hwndListView) != 0) 211 ListView_SetItemState(hwndListView, 0, LVIS_SELECTED, LVIS_SELECTED); 212 213 done: 214 if (hKeyUserProfiles != INVALID_HANDLE_VALUE) 215 RegCloseKey(hKeyUserProfiles); 216 217 if (pTokenUser != NULL) 218 HeapFree(GetProcessHeap(), 0, pTokenUser); 219 220 if (hToken != NULL) 221 CloseHandle(hToken); 222 } 223 224 225 static VOID 226 OnInitUserProfileDialog(HWND hwndDlg) 227 { 228 /* Initialize the list view control */ 229 SetListViewColumns(GetDlgItem(hwndDlg, IDC_USERPROFILE_LIST)); 230 231 AddUserProfiles(GetDlgItem(hwndDlg, IDC_USERPROFILE_LIST)); 232 233 /* Disable the "Delete" and "Copy To" buttons if the user is not an admin */ 234 if (!IsUserAnAdmin()) 235 { 236 EnableWindow(GetDlgItem(hwndDlg, IDC_USERPROFILE_DELETE), FALSE); 237 EnableWindow(GetDlgItem(hwndDlg, IDC_USERPROFILE_COPY), FALSE); 238 } 239 } 240 241 242 static 243 VOID 244 OnDestroy( 245 _In_ HWND hwndDlg) 246 { 247 HWND hwndList; 248 INT nItems, i; 249 LVITEM Item; 250 251 hwndList = GetDlgItem(hwndDlg, IDC_USERPROFILE_LIST); 252 253 nItems = ListView_GetItemCount(hwndList); 254 for (i = 0; i < nItems; i++) 255 { 256 Item.iItem = i; 257 Item.iSubItem = 0; 258 if (ListView_GetItem(hwndList, &Item)) 259 { 260 if (Item.lParam != 0) 261 HeapFree(GetProcessHeap(), 0, (PVOID)Item.lParam); 262 } 263 } 264 } 265 266 267 static 268 VOID 269 OnNotify( 270 _In_ HWND hwndDlg, 271 _In_ NMHDR *nmhdr) 272 { 273 if (nmhdr->idFrom == IDC_USERACCOUNT_LINK && nmhdr->code == NM_CLICK) 274 { 275 ShellExecuteW(hwndDlg, NULL, L"usrmgr.cpl", NULL, NULL, 0); 276 } 277 else if (nmhdr->idFrom == IDC_USERPROFILE_LIST && nmhdr->code == LVN_ITEMCHANGED) 278 { 279 if (ListView_GetSelectedCount(nmhdr->hwndFrom) == 0) 280 { 281 EnableWindow(GetDlgItem(hwndDlg, IDC_USERPROFILE_CHANGE), FALSE); 282 EnableWindow(GetDlgItem(hwndDlg, IDC_USERPROFILE_DELETE), FALSE); 283 EnableWindow(GetDlgItem(hwndDlg, IDC_USERPROFILE_COPY), FALSE); 284 } 285 else 286 { 287 LVITEM Item; 288 INT iSelected; 289 BOOL bMyProfile = FALSE; 290 291 iSelected = ListView_GetNextItem(nmhdr->hwndFrom, -1, LVNI_SELECTED); 292 if (iSelected != -1) 293 { 294 Item.iItem = iSelected; 295 Item.iSubItem = 0; 296 if (ListView_GetItem(nmhdr->hwndFrom, &Item)) 297 { 298 if (Item.lParam != 0) 299 { 300 bMyProfile = ((PPROFILEDATA)Item.lParam)->bMyProfile; 301 } 302 } 303 } 304 305 EnableWindow(GetDlgItem(hwndDlg, IDC_USERPROFILE_CHANGE), TRUE); 306 if (IsUserAnAdmin() && !bMyProfile) 307 { 308 EnableWindow(GetDlgItem(hwndDlg, IDC_USERPROFILE_DELETE), TRUE); 309 EnableWindow(GetDlgItem(hwndDlg, IDC_USERPROFILE_COPY), TRUE); 310 } 311 } 312 } 313 } 314 315 316 /* Property page dialog callback */ 317 INT_PTR CALLBACK 318 UserProfileDlgProc(HWND hwndDlg, 319 UINT uMsg, 320 WPARAM wParam, 321 LPARAM lParam) 322 { 323 switch (uMsg) 324 { 325 case WM_INITDIALOG: 326 OnInitUserProfileDialog(hwndDlg); 327 break; 328 329 case WM_DESTROY: 330 OnDestroy(hwndDlg); 331 break; 332 333 case WM_COMMAND: 334 switch (LOWORD(wParam)) 335 { 336 case IDOK: 337 case IDCANCEL: 338 EndDialog(hwndDlg, 339 LOWORD(wParam)); 340 return TRUE; 341 342 case IDC_USERPROFILE_DELETE: 343 break; 344 } 345 break; 346 347 case WM_NOTIFY: 348 OnNotify(hwndDlg, (NMHDR *)lParam); 349 break; 350 } 351 352 return FALSE; 353 } 354