/*
 * Copyright 2007 Tim Schwartz
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#include <windows.h>
#include <lm.h>
#include <wine/unicode.h>
#include <wine/debug.h>

#include "resources.h"

WINE_DEFAULT_DEBUG_CHANNEL(net);

#define NET_START 0001
#define NET_STOP  0002

static int output_write(const WCHAR* str, int len)
{
    DWORD ret, count;
    ret = WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), str, len, &count, NULL);
    if (!ret)
    {
        DWORD lenA;
        char* strA;

        /* On Windows WriteConsoleW() fails if the output is redirected. So fall
         * back to WriteFile(), assuming the console encoding is still the right
         * one in that case.
         */
        lenA = WideCharToMultiByte(GetConsoleOutputCP(), 0, str, len,
                                   NULL, 0, NULL, NULL);
        strA = HeapAlloc(GetProcessHeap(), 0, lenA);
        if (!strA)
            return 0;

        WideCharToMultiByte(GetConsoleOutputCP(), 0, str, len, strA, lenA,
                            NULL, NULL);
        WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), strA, lenA, &count, FALSE);
        HeapFree(GetProcessHeap(), 0, strA);
    }
    return count;
}

static int output_vprintf(const WCHAR* fmt, __ms_va_list va_args)
{
    WCHAR str[8192];
    int len;

    SetLastError(NO_ERROR);
    len = FormatMessageW(FORMAT_MESSAGE_FROM_STRING, fmt, 0, 0, str,
                         sizeof(str)/sizeof(*str), &va_args);
    if (len == 0 && GetLastError() != NO_ERROR)
        WINE_FIXME("Could not format string: le=%u, fmt=%s\n", GetLastError(), wine_dbgstr_w(fmt));
    else
        output_write(str, len);
    return 0;
}

static int __cdecl output_printf(const WCHAR* fmt, ...)
{
    __ms_va_list arguments;

    __ms_va_start(arguments, fmt);
    output_vprintf(fmt, arguments);
    __ms_va_end(arguments);
    return 0;
}

static int __cdecl output_string(int msg, ...)
{
    WCHAR fmt[8192];
    __ms_va_list arguments;

    LoadStringW(GetModuleHandleW(NULL), msg, fmt, sizeof(fmt)/sizeof(fmt[0]));
    __ms_va_start(arguments, msg);
    output_vprintf(fmt, arguments);
    __ms_va_end(arguments);
    return 0;
}

static BOOL output_error_string(DWORD error)
{
    LPWSTR pBuffer;
    if (FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM |
            FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER,
            NULL, error, 0, (LPWSTR)&pBuffer, 0, NULL))
    {
        output_write(pBuffer, lstrlenW(pBuffer));
        LocalFree(pBuffer);
        return TRUE;
    }
    return FALSE;
}

static BOOL net_use(int argc, const WCHAR* argv[])
{
    USE_INFO_2 *buffer, *connection;
    DWORD read, total, resume_handle, rc, i;
    WCHAR* status[STRING_RECONN-STRING_OK+1];
    resume_handle = 0;
    buffer = NULL;

    if(argc<3)
    {
        HMODULE hmod = GetModuleHandleW(NULL);

        /* Load the status strings */
        for (i = 0; i < sizeof(status)/sizeof(*status); i++)
        {
            status[i] = HeapAlloc(GetProcessHeap(), 0, 1024 * sizeof(**status));
            LoadStringW(hmod, STRING_OK+i, status[i], 1024);
        }

        do {
            rc = NetUseEnum(NULL, 2, (BYTE **) &buffer, 2048, &read, &total, &resume_handle);
            if (rc != ERROR_MORE_DATA && rc != ERROR_SUCCESS)
            {
                break;
            }

	    if(total == 0)
	    {
	        output_string(STRING_NO_ENTRIES);
		break;
	    }

            output_string(STRING_USE_HEADER);
            for (i = 0, connection = buffer; i < read; ++i, ++connection)
                output_string(STRING_USE_ENTRY, status[connection->ui2_status], connection->ui2_local,
				connection->ui2_remote, connection->ui2_refcount);

            if (buffer != NULL) NetApiBufferFree(buffer);
        } while (rc == ERROR_MORE_DATA);

        /* Release the status strings */
        for (i = 0; i < sizeof(status)/sizeof(*status); i++)
            HeapFree(GetProcessHeap(), 0, status[i]);

	return TRUE;
    }

    return FALSE;
}

static BOOL net_enum_services(void)
{
    static const WCHAR runningW[]={' ',' ',' ',' ','%','1','\n',0};
    SC_HANDLE SCManager;
    LPENUM_SERVICE_STATUS_PROCESSW services;
    DWORD size, i, count, resume;
    BOOL success = FALSE;

    SCManager = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS);
    if(!SCManager)
    {
        output_string(STRING_NO_SCM);
        return FALSE;
    }

    EnumServicesStatusExW(SCManager, SC_ENUM_PROCESS_INFO, SERVICE_WIN32, SERVICE_ACTIVE, NULL, 0, &size, &count, NULL, NULL);
    if(GetLastError() != ERROR_MORE_DATA)
    {
        output_error_string(GetLastError());
        goto end;
    }
    services = HeapAlloc(GetProcessHeap(), 0, size);
    resume = 0;
    if(!EnumServicesStatusExW(SCManager, SC_ENUM_PROCESS_INFO, SERVICE_WIN32, SERVICE_ACTIVE, (LPBYTE)services, size, &size, &count, &resume, NULL))
    {
        output_error_string(GetLastError());
        goto end;
    }
    output_string(STRING_RUNNING_HEADER);
    for(i = 0; i < count; i++)
    {
        output_printf(runningW, services[i].lpDisplayName);
        WINE_TRACE("service=%s state=%d controls=%x\n",
                   wine_dbgstr_w(services[i].lpServiceName),
                   services[i].ServiceStatusProcess.dwCurrentState,
                   services[i].ServiceStatusProcess.dwControlsAccepted);
    }
    success = TRUE;

 end:
    CloseServiceHandle(SCManager);
    return success;
}

static BOOL StopService(SC_HANDLE SCManager, SC_HANDLE serviceHandle)
{
    LPENUM_SERVICE_STATUSW dependencies = NULL;
    DWORD buffer_size = 0;
    DWORD count = 0, counter;
    BOOL result;
    SC_HANDLE dependent_serviceHandle;
    SERVICE_STATUS_PROCESS ssp;

    result = EnumDependentServicesW(serviceHandle, SERVICE_ACTIVE, dependencies, buffer_size, &buffer_size, &count);

    if(!result && (GetLastError() == ERROR_MORE_DATA))
    {
        dependencies = HeapAlloc(GetProcessHeap(), 0, buffer_size);
        if(EnumDependentServicesW(serviceHandle, SERVICE_ACTIVE, dependencies, buffer_size, &buffer_size, &count))
        {
            for(counter = 0; counter < count; counter++)
            {
                output_string(STRING_STOP_DEP, dependencies[counter].lpDisplayName);
                dependent_serviceHandle = OpenServiceW(SCManager, dependencies[counter].lpServiceName, SC_MANAGER_ALL_ACCESS);
                if(dependent_serviceHandle)
                {
                    result = StopService(SCManager, dependent_serviceHandle);
                    CloseServiceHandle(dependent_serviceHandle);
                }
                if(!result) output_string(STRING_CANT_STOP, dependencies[counter].lpDisplayName);
           }
        }
    }

    if(result) result = ControlService(serviceHandle, SERVICE_CONTROL_STOP, (LPSERVICE_STATUS)&ssp);
    HeapFree(GetProcessHeap(), 0, dependencies);
    return result;
}

static BOOL net_service(int operation, const WCHAR* service_name)
{
    SC_HANDLE SCManager, serviceHandle;
    BOOL result = FALSE;
    WCHAR service_display_name[4096];
    DWORD buffer_size;

    SCManager = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS);
    if(!SCManager)
    {
        output_string(STRING_NO_SCM);
        return FALSE;
    }
    serviceHandle = OpenServiceW(SCManager, service_name, SC_MANAGER_ALL_ACCESS);
    if(!serviceHandle)
    {
        output_string(STRING_NO_SVCHANDLE);
        CloseServiceHandle(SCManager);
        return FALSE;
    }

    buffer_size = sizeof(service_display_name)/sizeof(*service_display_name);
    GetServiceDisplayNameW(SCManager, service_name, service_display_name, &buffer_size);
    if (!service_display_name[0]) lstrcpyW(service_display_name, service_name);

    switch(operation)
    {
    case NET_START:
        output_string(STRING_START_SVC, service_display_name);
        result = StartServiceW(serviceHandle, 0, NULL);

        if(result) output_string(STRING_START_SVC_SUCCESS, service_display_name);
        else
        {
            if (!output_error_string(GetLastError()))
                output_string(STRING_START_SVC_FAIL, service_display_name);
        }
        break;
    case NET_STOP:
        output_string(STRING_STOP_SVC, service_display_name);
        result = StopService(SCManager, serviceHandle);

        if(result) output_string(STRING_STOP_SVC_SUCCESS, service_display_name);
        else
        {
            if (!output_error_string(GetLastError()))
                output_string(STRING_STOP_SVC_FAIL, service_display_name);
        }
        break;
    }

    CloseServiceHandle(serviceHandle);
    CloseServiceHandle(SCManager);
    return result;
}

static BOOL arg_is(const WCHAR* str1, const WCHAR* str2)
{
    return CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE, str1, -1, str2, -1) == CSTR_EQUAL;
}

int wmain(int argc, const WCHAR* argv[])
{
    static const WCHAR helpW[]={'h','e','l','p',0};
    static const WCHAR shelpW[]={'/','h','e','l','p',0};
    static const WCHAR startW[]={'s','t','a','r','t',0};
    static const WCHAR stopW[]={'s','t','o','p',0};
    static const WCHAR useW[]={'u','s','e',0};

    if (argc < 2)
    {
        output_string(STRING_USAGE);
        return 1;
    }

    if(arg_is(argv[1], helpW))
    {
        if(argc > 3)
        {
            output_string(STRING_USAGE);
            return 1;
        }
        if(argc == 2)
            output_string(STRING_USAGE);
        else if(arg_is(argv[2], startW))
            output_string(STRING_START_USAGE);
        else if(arg_is(argv[2], stopW))
            output_string(STRING_STOP_USAGE);
        else
            output_string(STRING_USAGE);
    }
    else if(arg_is(argv[1], startW))
    {
        if(argc > 3)
        {
            output_string(STRING_START_USAGE);
            return 1;
        }
        if (argc == 2)
        {
            if (!net_enum_services())
                return 1;
        }
        else if(arg_is(argv[2], shelpW))
            output_string(STRING_START_USAGE);
        else if(!net_service(NET_START, argv[2]))
            return 1;
    }
    else if(arg_is(argv[1], stopW))
    {
        if(argc != 3)
        {
            output_string(STRING_STOP_USAGE);
            return 1;
        }
        if(arg_is(argv[2], shelpW))
            output_string(STRING_STOP_USAGE);
        else if(!net_service(NET_STOP, argv[2]))
            return 1;
    }
    else if(arg_is(argv[1], useW))
    {
        if(!net_use(argc, argv)) return 1;
    }
    else
        output_string(STRING_USAGE);

    return 0;
}
