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_LOCALGROUP_HELP);
246             return 0;
247         }
248         else if (_wcsicmp(argv[i], L"/add") == 0)
249         {
250             bAdd = TRUE;
251         }
252         else if (_wcsicmp(argv[i], L"/delete") == 0)
253         {
254             bDelete = TRUE;
255         }
256         else if (_wcsnicmp(argv[i], L"/comment:", 9) == 0)
257         {
258             lpComment = &argv[i][9];
259         }
260         else if (_wcsicmp(argv[i], L"/domain") == 0)
261         {
262             ConResPrintf(StdErr, IDS_ERROR_OPTION_NOT_SUPPORTED, L"/DOMAIN");
263 #if 0
264             bDomain = TRUE;
265 #endif
266         }
267         else
268         {
269             result = 1;
270             goto done;
271         }
272     }
273 
274     if (lpGroupName == NULL)
275     {
276         result = 1;
277         goto done;
278     }
279 
280     if (bAdd && bDelete)
281     {
282         result = 1;
283         goto done;
284     }
285 
286 #if 0
287     ConPrintf(StdOut, L"Group:\n  %s\n", lpGroupName);
288 
289     if (lpMembers != NULL)
290     {
291         ConPuts(StdOut, L"\nMembers:\n");
292         for (i = 0; i < dwMemberCount; i++)
293             ConPrintf(StdOut, L"  %s\n", lpMembers[i].lgrmi3_domainandname);
294     }
295 
296     if (lpComment != NULL)
297     {
298         ConPrintf(StdOut, L"\nComment:\n  %s\n", lpComment);
299     }
300 #endif
301 
302     if (lpMembers == NULL)
303     {
304         if (!bAdd && !bDelete && lpComment != NULL)
305         {
306             /* Set group comment */
307             Info1002.lgrpi1002_comment = lpComment;
308             Status = NetLocalGroupSetInfo(NULL,
309                                           lpGroupName,
310                                           1002,
311                                           (LPBYTE)&Info1002,
312                                           NULL);
313             ConPrintf(StdOut, L"Status: %lu\n", Status);
314         }
315         else if (bAdd && !bDelete)
316         {
317             /* Add the group */
318             if (lpComment == NULL)
319             {
320                 Info0.lgrpi0_name = lpGroupName;
321             }
322             else
323             {
324                 Info1.lgrpi1_name = lpGroupName;
325                 Info1.lgrpi1_comment = lpComment;
326             }
327 
328             Status = NetLocalGroupAdd(NULL,
329                              (lpComment == NULL) ? 0 : 1,
330                              (lpComment == NULL) ? (LPBYTE)&Info0 : (LPBYTE)&Info1,
331                              NULL);
332             ConPrintf(StdOut, L"Status: %lu\n", Status);
333         }
334         else if (!bAdd && bDelete && lpComment == NULL)
335         {
336             /* Delete the group */
337             Status = NetLocalGroupDel(NULL,
338                                       lpGroupName);
339             ConPrintf(StdOut, L"Status: %lu\n", Status);
340         }
341         else
342         {
343             result = 1;
344         }
345     }
346     else
347     {
348         if (bAdd && !bDelete && lpComment == NULL)
349         {
350             /* Add group members */
351             Status = NetLocalGroupAddMembers(NULL,
352                                     lpGroupName,
353                                     3,
354                                     (LPBYTE)lpMembers,
355                                     dwMemberCount);
356             ConPrintf(StdOut, L"Status: %lu\n", Status);
357         }
358         else if (!bAdd && bDelete && lpComment == NULL)
359         {
360             /* Delete group members */
361             Status = NetLocalGroupDelMembers(NULL,
362                                     lpGroupName,
363                                     3,
364                                     (LPBYTE)lpMembers,
365                                     dwMemberCount);
366             ConPrintf(StdOut, L"Status: %lu\n", Status);
367         }
368         else
369         {
370             result = 1;
371         }
372     }
373 
374 done:
375     if (lpMembers != NULL)
376         RtlFreeHeap(RtlGetProcessHeap(), 0, lpMembers);
377 
378     if (result != 0)
379     {
380         ConResPuts(StdOut, IDS_GENERIC_SYNTAX);
381         ConResPuts(StdOut, IDS_LOCALGROUP_SYNTAX);
382     }
383 
384     return result;
385 }
386 
387 /* EOF */
388