Real fix for the broken netapi32.dll.
[reactos.git] / reactos / dll / cpl / usrmgr / userprops.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS User Manager Control Panel
4 * FILE: dll/cpl/usrmgr/userprops.c
5 * PURPOSE: User property sheet
6 *
7 * PROGRAMMERS: Eric Kohl
8 */
9
10 #include "usrmgr.h"
11
12 typedef struct _GENERAL_USER_DATA
13 {
14 DWORD dwFlags;
15 DWORD dwPasswordExpired;
16 TCHAR szUserName[1];
17 } GENERAL_USER_DATA, *PGENERAL_USER_DATA;
18
19 #define VALID_GENERAL_FLAGS (UF_PASSWD_CANT_CHANGE | UF_DONT_EXPIRE_PASSWD | UF_ACCOUNTDISABLE | UF_LOCKOUT)
20
21
22
23 static VOID
24 GetProfileData(HWND hwndDlg, LPTSTR lpUserName)
25 {
26 PUSER_INFO_3 userInfo = NULL;
27 NET_API_STATUS status;
28 BOOL bLocal;
29 TCHAR szDrive[8];
30 INT i;
31 INT nSel;
32
33 status = NetUserGetInfo(NULL, lpUserName, 3, (LPBYTE*)&userInfo);
34 if (status != NERR_Success)
35 return;
36
37 SetDlgItemText(hwndDlg, IDC_USER_PROFILE_PATH, userInfo->usri3_profile);
38 SetDlgItemText(hwndDlg, IDC_USER_PROFILE_SCRIPT, userInfo->usri3_script_path);
39
40
41 bLocal = (userInfo->usri3_home_dir_drive == NULL) ||
42 (_tcslen(userInfo->usri3_home_dir_drive) == 0);
43 CheckRadioButton(hwndDlg, IDC_USER_PROFILE_LOCAL, IDC_USER_PROFILE_REMOTE,
44 bLocal ? IDC_USER_PROFILE_LOCAL : IDC_USER_PROFILE_REMOTE);
45
46 for (i = 0; i < 26; i++)
47 {
48 wsprintf(szDrive, _T("%c:"), (TCHAR)('A' + i));
49 nSel = SendMessage(GetDlgItem(hwndDlg, IDC_USER_PROFILE_DRIVE),
50 CB_INSERTSTRING, -1, (LPARAM)szDrive);
51 }
52
53 if (bLocal)
54 {
55 SetDlgItemText(hwndDlg, IDC_USER_PROFILE_LOCAL_PATH, userInfo->usri3_home_dir);
56 EnableWindow(GetDlgItem(hwndDlg, IDC_USER_PROFILE_DRIVE), FALSE);
57 EnableWindow(GetDlgItem(hwndDlg, IDC_USER_PROFILE_REMOTE_PATH), FALSE);
58 }
59 else
60 {
61 SetDlgItemText(hwndDlg, IDC_USER_PROFILE_REMOTE_PATH, userInfo->usri3_home_dir);
62 nSel = SendMessage(GetDlgItem(hwndDlg, IDC_USER_PROFILE_DRIVE),
63 CB_FINDSTRINGEXACT, -1, (LPARAM)userInfo->usri3_home_dir_drive);
64 }
65
66 SendMessage(GetDlgItem(hwndDlg, IDC_USER_PROFILE_DRIVE),
67 CB_SETCURSEL, nSel, 0);
68
69 NetApiBufferFree(userInfo);
70 }
71
72
73 INT_PTR CALLBACK
74 UserProfilePageProc(HWND hwndDlg,
75 UINT uMsg,
76 WPARAM wParam,
77 LPARAM lParam)
78 {
79
80 UNREFERENCED_PARAMETER(lParam);
81 UNREFERENCED_PARAMETER(wParam);
82 UNREFERENCED_PARAMETER(hwndDlg);
83
84 switch (uMsg)
85 {
86 case WM_INITDIALOG:
87 GetProfileData(hwndDlg,
88 (LPTSTR)((PROPSHEETPAGE *)lParam)->lParam);
89 break;
90
91 case WM_COMMAND:
92 switch (LOWORD(wParam))
93 {
94 case IDC_USER_PROFILE_LOCAL:
95 EnableWindow(GetDlgItem(hwndDlg, IDC_USER_PROFILE_LOCAL_PATH), TRUE);
96 EnableWindow(GetDlgItem(hwndDlg, IDC_USER_PROFILE_DRIVE), FALSE);
97 EnableWindow(GetDlgItem(hwndDlg, IDC_USER_PROFILE_REMOTE_PATH), FALSE);
98 break;
99
100 case IDC_USER_PROFILE_REMOTE:
101 EnableWindow(GetDlgItem(hwndDlg, IDC_USER_PROFILE_LOCAL_PATH), FALSE);
102 EnableWindow(GetDlgItem(hwndDlg, IDC_USER_PROFILE_DRIVE), TRUE);
103 EnableWindow(GetDlgItem(hwndDlg, IDC_USER_PROFILE_REMOTE_PATH), TRUE);
104 break;
105 }
106 break;
107 }
108
109 return FALSE;
110 }
111
112
113 static VOID
114 GetMembershipData(HWND hwndDlg, LPTSTR lpUserName)
115 {
116 PLOCALGROUP_USERS_INFO_0 usersInfo = NULL;
117 NET_API_STATUS status;
118 DWORD dwRead;
119 DWORD dwTotal;
120 DWORD i;
121 HIMAGELIST hImgList;
122 HICON hIcon;
123 LV_ITEM lvi;
124 HWND hwndLV;
125 LV_COLUMN column;
126 RECT rect;
127
128
129 hwndLV = GetDlgItem(hwndDlg, IDC_USER_MEMBERSHIP_LIST);
130
131 /* Create the image list */
132 hImgList = ImageList_Create(16, 16, ILC_COLOR8 | ILC_MASK, 5, 5);
133 hIcon = LoadImage(hApplet, MAKEINTRESOURCE(IDI_GROUP), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
134 ImageList_AddIcon(hImgList, hIcon);
135 DestroyIcon(hIcon);
136 (void)ListView_SetImageList(hwndLV, hImgList, LVSIL_SMALL);
137
138 /* Set the list column */
139 GetClientRect(hwndLV, &rect);
140
141 memset(&column, 0x00, sizeof(column));
142 column.mask = LVCF_FMT | LVCF_WIDTH | LVCF_SUBITEM;
143 column.fmt = LVCFMT_LEFT;
144 column.cx = (INT)(rect.right - rect.left);
145 column.iSubItem = 0;
146 (void)ListView_InsertColumn(hwndLV, 0, &column);
147
148
149 status = NetUserGetLocalGroups(NULL, lpUserName, 0, 0,
150 (LPBYTE*)&usersInfo,
151 MAX_PREFERRED_LENGTH,
152 &dwRead,
153 &dwTotal);
154 if (status != NERR_Success)
155 return;
156
157 for (i = 0; i < dwRead; i++)
158 {
159 ZeroMemory(&lvi, sizeof(lvi));
160 lvi.mask = LVIF_TEXT | LVIF_STATE | LVIF_IMAGE;
161 lvi.pszText = usersInfo[i].lgrui0_name;
162 lvi.state = 0;
163 lvi.iImage = 0;
164
165 (void)ListView_InsertItem(hwndLV, &lvi);
166 }
167
168
169 NetApiBufferFree(usersInfo);
170
171 }
172
173
174 INT_PTR CALLBACK
175 UserMembershipPageProc(HWND hwndDlg,
176 UINT uMsg,
177 WPARAM wParam,
178 LPARAM lParam)
179 {
180
181 UNREFERENCED_PARAMETER(lParam);
182 UNREFERENCED_PARAMETER(wParam);
183 UNREFERENCED_PARAMETER(hwndDlg);
184
185 switch (uMsg)
186 {
187 case WM_INITDIALOG:
188 GetMembershipData(hwndDlg,
189 (LPTSTR)((PROPSHEETPAGE *)lParam)->lParam);
190 break;
191
192 }
193
194 return FALSE;
195 }
196
197
198 static VOID
199 UpdateUserOptions(HWND hwndDlg,
200 PGENERAL_USER_DATA pUserData,
201 BOOL bInit)
202 {
203 EnableWindow(GetDlgItem(hwndDlg, IDC_USER_GENERAL_CANNOT_CHANGE),
204 !pUserData->dwPasswordExpired);
205 EnableWindow(GetDlgItem(hwndDlg, IDC_USER_GENERAL_NEVER_EXPIRES),
206 !pUserData->dwPasswordExpired);
207 EnableWindow(GetDlgItem(hwndDlg, IDC_USER_GENERAL_FORCE_CHANGE),
208 (pUserData->dwFlags & (UF_PASSWD_CANT_CHANGE | UF_DONT_EXPIRE_PASSWD)) == 0);
209
210 EnableWindow(GetDlgItem(hwndDlg, IDC_USER_GENERAL_LOCKED),
211 (pUserData->dwFlags & UF_LOCKOUT) != 0);
212
213 if (bInit)
214 {
215 CheckDlgButton(hwndDlg, IDC_USER_GENERAL_FORCE_CHANGE,
216 pUserData->dwPasswordExpired ? BST_CHECKED : BST_UNCHECKED);
217
218 CheckDlgButton(hwndDlg, IDC_USER_GENERAL_CANNOT_CHANGE,
219 (pUserData->dwFlags & UF_PASSWD_CANT_CHANGE) ? BST_CHECKED : BST_UNCHECKED);
220
221 CheckDlgButton(hwndDlg, IDC_USER_GENERAL_NEVER_EXPIRES,
222 (pUserData->dwFlags & UF_DONT_EXPIRE_PASSWD) ? BST_CHECKED : BST_UNCHECKED);
223
224 CheckDlgButton(hwndDlg, IDC_USER_GENERAL_DISABLED,
225 (pUserData->dwFlags & UF_ACCOUNTDISABLE) ? BST_CHECKED : BST_UNCHECKED);
226
227 CheckDlgButton(hwndDlg, IDC_USER_GENERAL_LOCKED,
228 (pUserData->dwFlags & UF_LOCKOUT) ? BST_CHECKED : BST_UNCHECKED);
229 }
230 }
231
232
233 static VOID
234 GetGeneralUserData(HWND hwndDlg,
235 PGENERAL_USER_DATA pUserData)
236 {
237 PUSER_INFO_3 pUserInfo = NULL;
238
239 SetDlgItemText(hwndDlg, IDC_USER_GENERAL_NAME, pUserData->szUserName);
240
241 NetUserGetInfo(NULL, pUserData->szUserName, 3, (LPBYTE*)&pUserInfo);
242
243 SetDlgItemText(hwndDlg, IDC_USER_GENERAL_FULL_NAME, pUserInfo->usri3_full_name);
244 SetDlgItemText(hwndDlg, IDC_USER_GENERAL_DESCRIPTION, pUserInfo->usri3_comment);
245
246 pUserData->dwFlags = pUserInfo->usri3_flags;
247 pUserData->dwPasswordExpired = pUserInfo->usri3_password_expired;
248
249 NetApiBufferFree(pUserInfo);
250
251 UpdateUserOptions(hwndDlg, pUserData, TRUE);
252 }
253
254
255 static BOOL
256 SetGeneralUserData(HWND hwndDlg,
257 PGENERAL_USER_DATA pUserData)
258 {
259 PUSER_INFO_3 pUserInfo = NULL;
260 LPTSTR pszFullName = NULL;
261 LPTSTR pszComment = NULL;
262 NET_API_STATUS status;
263 #if 0
264 DWORD dwIndex;
265 #endif
266 INT nLength;
267
268 NetUserGetInfo(NULL, pUserData->szUserName, 3, (LPBYTE*)&pUserInfo);
269
270 pUserInfo->usri3_flags =
271 (pUserData->dwFlags & VALID_GENERAL_FLAGS) |
272 (pUserInfo->usri3_flags & ~VALID_GENERAL_FLAGS);
273
274 pUserInfo->usri3_password_expired = pUserData->dwPasswordExpired;
275
276 nLength = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_USER_GENERAL_FULL_NAME));
277 if (nLength == 0)
278 {
279 pUserInfo->usri3_full_name = NULL;
280 }
281 else
282 {
283 pszFullName = HeapAlloc(GetProcessHeap(), 0, (nLength + 1) * sizeof(TCHAR));
284 GetDlgItemText(hwndDlg, IDC_USER_GENERAL_FULL_NAME, pszFullName, nLength + 1);
285 pUserInfo->usri3_full_name = pszFullName;
286 }
287
288 nLength = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_USER_GENERAL_DESCRIPTION));
289 if (nLength == 0)
290 {
291 pUserInfo->usri3_full_name = NULL;
292 }
293 else
294 {
295 pszComment = HeapAlloc(GetProcessHeap(), 0, (nLength + 1) * sizeof(TCHAR));
296 GetDlgItemText(hwndDlg, IDC_USER_GENERAL_DESCRIPTION, pszComment, nLength + 1);
297 pUserInfo->usri3_comment = pszComment;
298 }
299
300 #if 0
301 status = NetUserSetInfo(NULL, pUserData->szUserName, 3, (LPBYTE)pUserInfo, &dwIndex);
302 if (status != NERR_Success)
303 {
304 DebugPrintf(_T("Status: %lu Index: %lu"), status, dwIndex);
305 }
306 #else
307 status = NERR_Success;
308 #endif
309
310 if (pszFullName)
311 HeapFree(GetProcessHeap(), 0, pszFullName);
312
313 NetApiBufferFree(pUserInfo);
314
315 return (status == NERR_Success);
316 }
317
318
319 INT_PTR CALLBACK
320 UserGeneralPageProc(HWND hwndDlg,
321 UINT uMsg,
322 WPARAM wParam,
323 LPARAM lParam)
324 {
325 PGENERAL_USER_DATA pUserData;
326
327 UNREFERENCED_PARAMETER(lParam);
328 UNREFERENCED_PARAMETER(wParam);
329 UNREFERENCED_PARAMETER(hwndDlg);
330
331 pUserData= (PGENERAL_USER_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
332
333 switch (uMsg)
334 {
335 case WM_INITDIALOG:
336 pUserData = (PGENERAL_USER_DATA)HeapAlloc(GetProcessHeap(),
337 HEAP_ZERO_MEMORY,
338 sizeof(GENERAL_USER_DATA) +
339 lstrlen((LPTSTR)((PROPSHEETPAGE *)lParam)->lParam) * sizeof(TCHAR));
340 lstrcpy(pUserData->szUserName, (LPTSTR)((PROPSHEETPAGE *)lParam)->lParam);
341
342 GetGeneralUserData(hwndDlg,
343 pUserData);
344
345 SetWindowLongPtr(hwndDlg, DWLP_USER, (INT_PTR)pUserData);
346 break;
347
348 case WM_COMMAND:
349 switch (LOWORD(wParam))
350 {
351 case IDC_USER_GENERAL_FORCE_CHANGE:
352 pUserData->dwPasswordExpired = !pUserData->dwPasswordExpired;
353 UpdateUserOptions(hwndDlg, pUserData, FALSE);
354 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
355 break;
356
357 case IDC_USER_GENERAL_CANNOT_CHANGE:
358 pUserData->dwFlags ^= UF_PASSWD_CANT_CHANGE;
359 UpdateUserOptions(hwndDlg, pUserData, FALSE);
360 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
361 break;
362
363 case IDC_USER_GENERAL_NEVER_EXPIRES:
364 pUserData->dwFlags ^= UF_DONT_EXPIRE_PASSWD;
365 UpdateUserOptions(hwndDlg, pUserData, FALSE);
366 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
367 break;
368
369 case IDC_USER_GENERAL_DISABLED:
370 pUserData->dwFlags ^= UF_ACCOUNTDISABLE;
371 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
372 break;
373
374 case IDC_USER_GENERAL_LOCKED:
375 pUserData->dwFlags ^= UF_LOCKOUT;
376 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
377 break;
378 }
379 break;
380
381 case WM_NOTIFY:
382 if (((LPPSHNOTIFY)lParam)->hdr.code == PSN_APPLY)
383 {
384 SetGeneralUserData(hwndDlg, pUserData);
385 return TRUE;
386 }
387 break;
388
389 case WM_DESTROY:
390 HeapFree(GetProcessHeap(), 0, pUserData);
391 break;
392 }
393
394 return FALSE;
395 }
396
397
398 static VOID
399 InitPropSheetPage(PROPSHEETPAGE *psp, WORD idDlg, DLGPROC DlgProc, LPTSTR pszUser)
400 {
401 ZeroMemory(psp, sizeof(PROPSHEETPAGE));
402 psp->dwSize = sizeof(PROPSHEETPAGE);
403 psp->dwFlags = PSP_DEFAULT;
404 psp->hInstance = hApplet;
405 psp->pszTemplate = MAKEINTRESOURCE(idDlg);
406 psp->pfnDlgProc = DlgProc;
407 psp->lParam = (LPARAM)pszUser;
408 }
409
410
411 BOOL
412 UserProperties(HWND hwndDlg)
413 {
414 PROPSHEETPAGE psp[3];
415 PROPSHEETHEADER psh;
416 TCHAR szUserName[UNLEN];
417 INT nItem;
418 HWND hwndLV;
419
420 hwndLV = GetDlgItem(hwndDlg, IDC_USERS_LIST);
421 nItem = ListView_GetNextItem(hwndLV, -1, LVNI_SELECTED);
422 if (nItem == -1)
423 return FALSE;
424
425 /* Get the new user name */
426 ListView_GetItemText(hwndLV,
427 nItem, 0,
428 szUserName,
429 UNLEN);
430
431 ZeroMemory(&psh, sizeof(PROPSHEETHEADER));
432 psh.dwSize = sizeof(PROPSHEETHEADER);
433 psh.dwFlags = PSH_PROPSHEETPAGE | PSH_PROPTITLE;
434 psh.hwndParent = hwndDlg;
435 psh.hInstance = hApplet;
436 psh.hIcon = NULL;
437 psh.pszCaption = szUserName;
438 psh.nPages = sizeof(psp) / sizeof(PROPSHEETPAGE);
439 psh.nStartPage = 0;
440 psh.ppsp = psp;
441
442 InitPropSheetPage(&psp[0], IDD_USER_GENERAL, (DLGPROC)UserGeneralPageProc, szUserName);
443 InitPropSheetPage(&psp[1], IDD_USER_MEMBERSHIP, (DLGPROC)UserMembershipPageProc, szUserName);
444 InitPropSheetPage(&psp[2], IDD_USER_PROFILE, (DLGPROC)UserProfilePageProc, szUserName);
445
446 return (PropertySheet(&psh) == IDOK);
447 }