1 /*
2  * COPYRIGHT:       See COPYING in the top level directory
3  * PROJECT:         ReactOS net command
4  * FILE:            base/applications/network/net/cmdGroup.c
5  * PROGRAMMERS:     Eric Kohl <eric.kohl@reactos.org>
6  */
7 
8 #include "net.h"
9 
10 
11 static
12 int
13 CompareInfo(const void *a,
14             const void *b)
15 {
16     return _wcsicmp(((PGROUP_INFO_0)a)->grpi0_name,
17                     ((PGROUP_INFO_0)b)->grpi0_name);
18 }
19 
20 
21 static
22 NET_API_STATUS
23 EnumerateGroups(VOID)
24 {
25     PGROUP_INFO_0 pBuffer = NULL;
26     PSERVER_INFO_100 pServer = NULL;
27     DWORD dwRead = 0, dwTotal = 0;
28     DWORD i;
29     DWORD_PTR ResumeHandle = 0;
30     NET_API_STATUS Status;
31 
32     Status = NetServerGetInfo(NULL,
33                               100,
34                               (LPBYTE*)&pServer);
35     if (Status != NERR_Success)
36         return Status;
37 
38     ConPuts(StdOut, L"\n");
39     ConResPrintf(StdOut, IDS_GROUP_GROUPS, pServer->sv100_name);
40     ConPuts(StdOut, L"\n\n");
41     PrintPadding(L'-', 79);
42     ConPuts(StdOut, L"\n");
43 
44     NetApiBufferFree(pServer);
45 
46     Status = NetGroupEnum(NULL,
47                           0,
48                           (LPBYTE*)&pBuffer,
49                           MAX_PREFERRED_LENGTH,
50                           &dwRead,
51                           &dwTotal,
52                           &ResumeHandle);
53     if (Status != NERR_Success)
54         return Status;
55 
56     qsort(pBuffer,
57           dwRead,
58           sizeof(PGROUP_INFO_0),
59           CompareInfo);
60 
61     for (i = 0; i < dwRead; i++)
62     {
63         if (pBuffer[i].grpi0_name)
64             ConPrintf(StdOut, L"*%s\n", pBuffer[i].grpi0_name);
65     }
66 
67     NetApiBufferFree(pBuffer);
68 
69     return NERR_Success;
70 }
71 
72 
73 static
74 NET_API_STATUS
75 DisplayGroup(LPWSTR lpGroupName)
76 {
77     PGROUP_INFO_1 pGroupInfo = NULL;
78     PGROUP_USERS_INFO_0 pUsers = NULL;
79     LPWSTR *pNames = NULL;
80     DWORD dwRead = 0;
81     DWORD dwTotal = 0;
82     DWORD_PTR ResumeHandle = 0;
83     DWORD i;
84     INT nPaddedLength = 15;
85     NET_API_STATUS Status;
86 
87     Status = NetGroupGetInfo(NULL,
88                              lpGroupName,
89                              1,
90                              (LPBYTE*)&pGroupInfo);
91     if (Status != NERR_Success)
92         return Status;
93 
94     Status = NetGroupGetUsers(NULL,
95                               lpGroupName,
96                               0,
97                               (LPBYTE*)&pUsers,
98                               MAX_PREFERRED_LENGTH,
99                               &dwRead,
100                               &dwTotal,
101                               &ResumeHandle);
102     if (Status != NERR_Success)
103         goto done;
104 
105     pNames = RtlAllocateHeap(RtlGetProcessHeap(),
106                              HEAP_ZERO_MEMORY,
107                              dwRead * sizeof(LPWSTR));
108     if (pNames == NULL)
109     {
110         Status = ERROR_OUTOFMEMORY;
111         goto done;
112     }
113 
114     for (i = 0; i < dwRead; i++)
115     {
116         pNames[i] = pUsers[i].grui0_name;
117     }
118 
119     PrintPaddedResourceString(IDS_GROUP_NAME, nPaddedLength);
120     ConPrintf(StdOut, L"%s\n", pGroupInfo->grpi1_name);
121 
122     PrintPaddedResourceString(IDS_GROUP_COMMENT, nPaddedLength);
123     ConPrintf(StdOut, L"%s\n", pGroupInfo->grpi1_comment);
124 
125     ConPuts(StdOut, L"\n");
126 
127     ConResPuts(StdOut, IDS_GROUP_MEMBERS);
128     ConPuts(StdOut, L"\n\n");
129 
130     PrintPadding(L'-', 79);
131     ConPuts(StdOut, L"\n");
132 
133     for (i = 0; i < dwRead; i++)
134     {
135         if (pNames[i])
136             ConPrintf(StdOut, L"%s\n", pNames[i]);
137     }
138 
139 done:
140     if (pNames != NULL)
141         RtlFreeHeap(RtlGetProcessHeap(), 0, pNames);
142 
143     if (pUsers != NULL)
144         NetApiBufferFree(pUsers);
145 
146     if (pGroupInfo != NULL)
147         NetApiBufferFree(pGroupInfo);
148 
149     return Status;
150 }
151 
152 
153 INT
154 cmdGroup(
155     INT argc,
156     WCHAR **argv)
157 {
158     INT i, j;
159     INT result = 0;
160     ULONG dwUserCount = 0;
161     BOOL bAdd = FALSE;
162     BOOL bDelete = FALSE;
163 #if 0
164     BOOL bDomain = FALSE;
165 #endif
166     PWSTR pGroupName = NULL;
167     PWSTR pComment = NULL;
168     PWSTR *pUsers = NULL;
169     GROUP_INFO_0 Info0;
170     GROUP_INFO_1 Info1;
171     GROUP_INFO_1002 Info1002;
172     NET_API_STATUS Status;
173 
174     if (argc == 2)
175     {
176         Status = EnumerateGroups();
177         ConPrintf(StdOut, L"Status: %lu\n", Status);
178         return 0;
179     }
180     else if (argc == 3)
181     {
182         Status = DisplayGroup(argv[2]);
183         ConPrintf(StdOut, L"Status: %lu\n", Status);
184         return 0;
185     }
186 
187     i = 2;
188     if (argv[i][0] != L'/')
189     {
190         pGroupName = argv[i];
191         i++;
192     }
193 
194     for (j = i; j < argc; j++)
195     {
196         if (argv[j][0] == L'/')
197             break;
198 
199         dwUserCount++;
200     }
201 
202     if (dwUserCount > 0)
203     {
204         pUsers = RtlAllocateHeap(RtlGetProcessHeap(),
205                                  HEAP_ZERO_MEMORY,
206                                  dwUserCount * sizeof(PGROUP_USERS_INFO_0));
207         if (pUsers == NULL)
208             return 0;
209     }
210 
211     j = 0;
212     for (; i < argc; i++)
213     {
214         if (argv[i][0] == L'/')
215             break;
216 
217         pUsers[j] = argv[i];
218         j++;
219     }
220 
221     for (; i < argc; i++)
222     {
223         if (_wcsicmp(argv[i], L"/help") == 0)
224         {
225             ConResPuts(StdOut, IDS_GENERIC_SYNTAX);
226             PrintNetMessage(MSG_GROUP_SYNTAX);
227             PrintNetMessage(MSG_GROUP_HELP);
228             ConResPuts(StdOut, IDS_GENERIC_PAGE);
229             return 0;
230         }
231         else if (_wcsicmp(argv[i], L"/add") == 0)
232         {
233             bAdd = TRUE;
234         }
235         else if (_wcsicmp(argv[i], L"/delete") == 0)
236         {
237             bDelete = TRUE;
238         }
239         else if (_wcsnicmp(argv[i], L"/comment:", 9) == 0)
240         {
241             pComment = &argv[i][9];
242         }
243         else if (_wcsicmp(argv[i], L"/domain") == 0)
244         {
245             ConResPrintf(StdErr, IDS_ERROR_OPTION_NOT_SUPPORTED, L"/DOMAIN");
246 #if 0
247             bDomain = TRUE;
248 #endif
249         }
250         else
251         {
252             PrintErrorMessage(3506/*, argv[i]*/);
253             result = 1;
254             goto done;
255         }
256     }
257 
258     if (pGroupName == NULL)
259     {
260         result = 1;
261         goto done;
262     }
263 
264     if (bAdd && bDelete)
265     {
266         result = 1;
267         goto done;
268     }
269 
270     if (pUsers == NULL)
271     {
272         if (!bAdd && !bDelete && pComment != NULL)
273         {
274             /* Set group comment */
275             Info1002.grpi1002_comment = pComment;
276             Status = NetGroupSetInfo(NULL,
277                                      pGroupName,
278                                      1002,
279                                      (LPBYTE)&Info1002,
280                                      NULL);
281             ConPrintf(StdOut, L"Status: %lu\n", Status);
282         }
283         else if (bAdd && !bDelete)
284         {
285             /* Add the group */
286             if (pComment == NULL)
287             {
288                 Info0.grpi0_name = pGroupName;
289             }
290             else
291             {
292                 Info1.grpi1_name = pGroupName;
293                 Info1.grpi1_comment = pComment;
294             }
295 
296             Status = NetGroupAdd(NULL,
297                                  (pComment == NULL) ? 0 : 1,
298                                  (pComment == NULL) ? (LPBYTE)&Info0 : (LPBYTE)&Info1,
299                                  NULL);
300             ConPrintf(StdOut, L"Status: %lu\n", Status);
301         }
302         else if (!bAdd && bDelete && pComment == NULL)
303         {
304             /* Delete the group */
305             Status = NetGroupDel(NULL,
306                                  pGroupName);
307             ConPrintf(StdOut, L"Status: %lu\n", Status);
308         }
309         else
310         {
311             result = 1;
312         }
313     }
314     else
315     {
316         if (bAdd && !bDelete && pComment == NULL)
317         {
318             /* Add group user */
319             for (i = 0; i < dwUserCount; i++)
320             {
321                 Status = NetGroupAddUser(NULL,
322                                          pGroupName,
323                                          pUsers[i]);
324                 if (Status != NERR_Success)
325                     break;
326             }
327             ConPrintf(StdOut, L"Status: %lu\n", Status);
328         }
329         else if (!bAdd && bDelete && pComment == NULL)
330         {
331             /* Delete group members */
332             for (i = 0; i < dwUserCount; i++)
333             {
334                 Status = NetGroupDelUser(NULL,
335                                          pGroupName,
336                                          pUsers[i]);
337                 if (Status != NERR_Success)
338                     break;
339             }
340             ConPrintf(StdOut, L"Status: %lu\n", Status);
341         }
342         else
343         {
344             result = 1;
345         }
346     }
347 
348 done:
349     if (pUsers != NULL)
350         RtlFreeHeap(RtlGetProcessHeap(), 0, pUsers);
351 
352     if (result != 0)
353     {
354         ConResPuts(StdOut, IDS_GENERIC_SYNTAX);
355         PrintNetMessage(MSG_GROUP_SYNTAX);
356     }
357 
358     return result;
359 }
360 
361 /* EOF */
362