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