wscript: Fix tests on wow64.
[wine] / programs / net / net.c
1 /*
2  * Copyright 2007 Tim Schwartz
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18
19 #include <windows.h>
20 #include <lm.h>
21 #include <wine/unicode.h>
22
23 #include "resources.h"
24
25 #define NET_START 0001
26 #define NET_STOP  0002
27
28 static int output_write(WCHAR* str, int len)
29 {
30     DWORD ret, count;
31     ret = WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), str, len, &count, NULL);
32     if (!ret)
33     {
34         DWORD lenA;
35         char* strA;
36
37         /* On Windows WriteConsoleW() fails if the output is redirected. So fall
38          * back to WriteFile(), assuming the console encoding is still the right
39          * one in that case.
40          */
41         lenA = WideCharToMultiByte(GetConsoleOutputCP(), 0, str, len,
42                                    NULL, 0, NULL, NULL);
43         strA = HeapAlloc(GetProcessHeap(), 0, lenA);
44         if (!strA)
45             return 0;
46
47         WideCharToMultiByte(GetConsoleOutputCP(), 0, str, len, strA, lenA,
48                             NULL, NULL);
49         WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), strA, len, &count, FALSE);
50         HeapFree(GetProcessHeap(), 0, strA);
51     }
52     return count;
53 }
54
55 static int output_string(int msg, ...)
56 {
57     WCHAR fmt[8192];
58     WCHAR str[8192];
59     int len;
60     va_list arguments;
61
62     LoadStringW(GetModuleHandleW(NULL), msg, fmt, sizeof(fmt));
63     va_start(arguments, msg);
64     len = vsprintfW(str, fmt, arguments);
65     output_write(str, len);
66     va_end(arguments);
67     return 0;
68 }
69
70 static BOOL output_error_string(DWORD error)
71 {
72     LPWSTR pBuffer;
73     if (FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM |
74             FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER,
75             NULL, error, 0, (LPWSTR)&pBuffer, 0, NULL))
76     {
77         output_write(pBuffer, lstrlenW(pBuffer));
78         LocalFree(pBuffer);
79         return TRUE;
80     }
81     return FALSE;
82 }
83
84 static BOOL net_use(int argc, const WCHAR* argv[])
85 {
86     USE_INFO_2 *buffer, *connection;
87     DWORD read, total, resume_handle, rc, i;
88     WCHAR* status[STRING_RECONN-STRING_OK+1];
89     resume_handle = 0;
90     buffer = NULL;
91
92     if(argc<3)
93     {
94         HMODULE hmod = GetModuleHandleW(NULL);
95
96         /* Load the status strings */
97         for (i = 0; i < sizeof(status)/sizeof(*status); i++)
98         {
99             status[i] = HeapAlloc(GetProcessHeap(), 0, 1024 * sizeof(**status));
100             LoadStringW(hmod, STRING_OK+i, status[i], 1024);
101         }
102
103         do {
104             rc = NetUseEnum(NULL, 2, (BYTE **) &buffer, 2048, &read, &total, &resume_handle);
105             if (rc != ERROR_MORE_DATA && rc != ERROR_SUCCESS)
106             {
107                 break;
108             }
109
110             if(total == 0)
111             {
112                 output_string(STRING_NO_ENTRIES);
113                 break;
114             }
115
116             output_string(STRING_USE_HEADER);
117             for (i = 0, connection = buffer; i < read; ++i, ++connection)
118                 output_string(STRING_USE_ENTRY, status[connection->ui2_status], connection->ui2_local,
119                                 connection->ui2_remote, connection->ui2_refcount);
120
121             if (buffer != NULL) NetApiBufferFree(buffer);
122         } while (rc == ERROR_MORE_DATA);
123
124         /* Release the status strings */
125         for (i = 0; i < sizeof(status)/sizeof(*status); i++)
126             HeapFree(GetProcessHeap(), 0, status[i]);
127
128         return TRUE;
129     }
130
131     return FALSE;
132 }
133
134 static BOOL StopService(SC_HANDLE SCManager, SC_HANDLE serviceHandle)
135 {
136     LPENUM_SERVICE_STATUSW dependencies = NULL;
137     DWORD buffer_size = 0;
138     DWORD count = 0, counter;
139     BOOL result;
140     SC_HANDLE dependent_serviceHandle;
141     SERVICE_STATUS_PROCESS ssp;
142
143     result = EnumDependentServicesW(serviceHandle, SERVICE_ACTIVE, dependencies, buffer_size, &buffer_size, &count);
144
145     if(!result && (GetLastError() == ERROR_MORE_DATA))
146     {
147         dependencies = HeapAlloc(GetProcessHeap(), 0, buffer_size);
148         if(EnumDependentServicesW(serviceHandle, SERVICE_ACTIVE, dependencies, buffer_size, &buffer_size, &count))
149         {
150             for(counter = 0; counter < count; counter++)
151             {
152                 output_string(STRING_STOP_DEP, dependencies[counter].lpDisplayName);
153                 dependent_serviceHandle = OpenServiceW(SCManager, dependencies[counter].lpServiceName, SC_MANAGER_ALL_ACCESS);
154                 if(dependent_serviceHandle) result = StopService(SCManager, dependent_serviceHandle);
155                 CloseServiceHandle(dependent_serviceHandle);
156                 if(!result) output_string(STRING_CANT_STOP, dependencies[counter].lpDisplayName);
157            }
158         }
159     }
160
161     if(result) result = ControlService(serviceHandle, SERVICE_CONTROL_STOP, (LPSERVICE_STATUS)&ssp);
162     HeapFree(GetProcessHeap(), 0, dependencies);
163     return result;
164 }
165
166 static BOOL net_service(int operation, const WCHAR* service_name)
167 {
168     SC_HANDLE SCManager, serviceHandle;
169     BOOL result = 0;
170     WCHAR service_display_name[4096];
171     DWORD buffer_size;
172
173     SCManager = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS);
174     if(!SCManager)
175     {
176         output_string(STRING_NO_SCM);
177         return FALSE;
178     }
179     serviceHandle = OpenServiceW(SCManager, service_name, SC_MANAGER_ALL_ACCESS);
180     if(!serviceHandle)
181     {
182         output_string(STRING_NO_SVCHANDLE);
183         CloseServiceHandle(SCManager);
184         return FALSE;
185     }
186
187     buffer_size = sizeof(service_display_name)/sizeof(*service_display_name);
188     GetServiceDisplayNameW(SCManager, service_name, service_display_name, &buffer_size);
189     if (!service_display_name[0]) lstrcpyW(service_display_name, service_name);
190
191     switch(operation)
192     {
193     case NET_START:
194         output_string(STRING_START_SVC, service_display_name);
195         result = StartServiceW(serviceHandle, 0, NULL);
196
197         if(result) output_string(STRING_START_SVC_SUCCESS, service_display_name);
198         else
199         {
200             if (!output_error_string(GetLastError()))
201                 output_string(STRING_START_SVC_FAIL, service_display_name);
202         }
203         break;
204     case NET_STOP:
205         output_string(STRING_STOP_SVC, service_display_name);
206         result = StopService(SCManager, serviceHandle);
207
208         if(result) output_string(STRING_STOP_SVC_SUCCESS, service_display_name);
209         else
210         {
211             if (!output_error_string(GetLastError()))
212                 output_string(STRING_STOP_SVC_FAIL, service_display_name);
213         }
214         break;
215     }
216
217     CloseServiceHandle(serviceHandle);
218     CloseServiceHandle(SCManager);
219     return result;
220 }
221
222 static int arg_is(const WCHAR* str1, const WCHAR* str2)
223 {
224     return CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE, str1, -1, str2, -1) == CSTR_EQUAL;
225 }
226
227 int wmain(int argc, const WCHAR* argv[])
228 {
229     static const WCHAR helpW[]={'h','e','l','p',0};
230     static const WCHAR startW[]={'s','t','a','r','t',0};
231     static const WCHAR stopW[]={'s','t','o','p',0};
232     static const WCHAR useW[]={'u','s','e',0};
233     if (argc < 2)
234     {
235         output_string(STRING_USAGE);
236         return 1;
237     }
238
239     if(arg_is(argv[1], helpW))
240     {
241         output_string(STRING_HELP_USAGE);
242     }
243
244     if(arg_is(argv[1], startW))
245     {
246         if(argc < 3)
247         {
248             output_string(STRING_START_USAGE);
249             return 1;
250         }
251
252         if(!net_service(NET_START, argv[2]))
253         {
254             return 1;
255         }
256         return 0;
257     }
258
259     if(arg_is(argv[1], stopW))
260     {
261         if(argc < 3)
262         {
263             output_string(STRING_STOP_USAGE);
264             return 1;
265         }
266
267         if(!net_service(NET_STOP, argv[2]))
268         {
269             return 1;
270         }
271         return 0;
272     }
273
274     if(arg_is(argv[1], useW))
275     {
276         if(!net_use(argc, argv)) return 1;
277     }
278
279     return 0;
280 }