/*
 * 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, len, &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 = 0;
    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 int 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;
}
