#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../conf/portability.h"
#include "../compat/lib/log.h"

SC_HANDLE schService;
SC_HANDLE bindService;

// ---------------------------------------------------------------------------------------

LONG APIENTRY CreateBINDService(HWND hwnd, LPLONG lpIValue, LPSTR serviceexe)
{
  LPCTSTR serviceName = "DomainNameService";
  LPCTSTR lpszBinaryPathName = serviceexe;
  LPTSTR  lpszRootPathName="?:\\";
  HANDLE hSCManager = NULL;

  if ( (':' != *(lpszBinaryPathName+1)) || ('\\' != *(lpszBinaryPathName+2)) )
  {
    return 101;
  }

  #define DRIVE_TYPE_INDETERMINATE 0
  #define ROOT_DIR_DOESNT_EXIST    1

  *lpszRootPathName = *(lpszBinaryPathName+0) ;

  switch (  GetDriveType(lpszRootPathName)  )
  {
    case DRIVE_FIXED :
    { // OK
      break;
    }
    case  ROOT_DIR_DOESNT_EXIST :
    {
      return 101;
    }
    case  DRIVE_TYPE_INDETERMINATE :
    case  DRIVE_REMOVABLE          :
    case  DRIVE_REMOTE             :
    case  DRIVE_CDROM              :
    case  DRIVE_RAMDISK            :
    {
      return 101;
    }
    default :
    {
      return 101;
    }
  }

  if (INVALID_HANDLE_VALUE == CreateFile(lpszBinaryPathName,
                                         GENERIC_READ,
                                         FILE_SHARE_READ,
                                         NULL,
                                         OPEN_EXISTING,
                                         FILE_ATTRIBUTE_NORMAL,
                                         NULL))
  { 
    return 101;
  }
   
	if((hSCManager = OpenSCManager(
			NULL, 
     		NULL,
     		SC_MANAGER_ALL_ACCESS)) == NULL) {
		return 11;
	}

  schService = CreateService(
        hSCManager,                 // SCManager database
        serviceName,                // name of service
        serviceName,                // name to display (new parameter after october beta)
        SERVICE_ALL_ACCESS,         // desired access
        SERVICE_WIN32_OWN_PROCESS,  // service type
        SERVICE_AUTO_START,         // start type
        SERVICE_ERROR_NORMAL,       // error control type
        lpszBinaryPathName,         // service's binary
        NULL,                       // no load ordering group
        NULL,                       // no tag identifier
        NULL,                       // no dependencies
        NULL,                       // Local System account
        NULL);                      // null password

  if (NULL == schService)
  { switch (GetLastError())
    {
      case ERROR_ACCESS_DENIED :
      { 
        CloseServiceHandle(hSCManager);
        return 102;
        break;
      }
      case ERROR_SERVICE_EXISTS :
      {
        CloseServiceHandle(hSCManager);
        return 103;
        break;
      }
      default :
      {
      }
    }
    CloseServiceHandle(hSCManager);
    return 104;
  }
  else

  CloseServiceHandle(schService);
  CloseServiceHandle(hSCManager);

  return 0;
}

// ---------------------------------------------------------------------------------------


LONG APIENTRY RemoveBINDService(HWND hwnd, LPLONG lpIValue, LPSTR serviceName)
  {
    HANDLE hSCManager = NULL;

	if((hSCManager = OpenSCManager(
			NULL, 
     		NULL,
     		SC_MANAGER_ALL_ACCESS)) == NULL) {
		return 11;
	}

    
  bindService = OpenService(hSCManager,serviceName,SERVICE_ALL_ACCESS);
  if (NULL == bindService)
  { switch (GetLastError())
    {
      case ERROR_ACCESS_DENIED :
      { 
             
         CloseServiceHandle(hSCManager);
         return 102;
        break;
      }
      case ERROR_SERVICE_DOES_NOT_EXIST :
      { 
         CloseServiceHandle(hSCManager);
         return 106;
        break;
      }
      default :
       {
           CloseServiceHandle(hSCManager);
           return 105;
      }
    }
  
           CloseServiceHandle(hSCManager);
           return 105;
  }

  if (DeleteService(bindService))
  {
   CloseServiceHandle(bindService);
   CloseServiceHandle(hSCManager);
   return 0;
  }
  else
  { switch (GetLastError())
    {
      case ERROR_ACCESS_DENIED :
      { 
        CloseServiceHandle(bindService);
        CloseServiceHandle(hSCManager);
        return 102;
        break;
      }
      default :
      { 
         CloseServiceHandle(bindService);
         CloseServiceHandle(hSCManager);
         return 105;
      }
    }
   return 105;
  }
  CloseServiceHandle(bindService);
  CloseServiceHandle(hSCManager);
 }


LONG APIENTRY StartBINDService(HWND hwnd, LPLONG lpIValue, LPSTR bs)
  {

HANDLE hSCManager = NULL, hDomainNameService = NULL;

	if((hSCManager = OpenSCManager(
			NULL, 
     		NULL,
     		SC_MANAGER_ALL_ACCESS)) == NULL) {
		return 11;
	}

  	if((hDomainNameService = OpenService(
       		hSCManager,                              
       		TEXT("DomainNameService"),               
       		SERVICE_ALL_ACCESS)) == NULL) {
                CloseServiceHandle(hSCManager);
		return 12;
	}

	if(!StartService(hDomainNameService, 0, NULL))
                 {
		 if(GetLastError() == ERROR_SERVICE_ALREADY_RUNNING)
          { 
          }
		   else
          {
                   CloseServiceHandle(hDomainNameService);
                   CloseServiceHandle(hSCManager);
		    return 50;
		  }
		 }
		 
       CloseServiceHandle(hDomainNameService);
       CloseServiceHandle(hSCManager);
        return 0;

}

LONG APIENTRY StopBINDService(HWND hwnd, LPLONG lpIValue, LPSTR bs)
  {


DWORD ControlCode = SERVICE_CONTROL_STOP;
HANDLE hSCManager = NULL, hDomainNameService = NULL;
SERVICE_STATUS ServiceStatus;

	if((hSCManager = OpenSCManager(
			NULL,
     		NULL,
     		SC_MANAGER_ALL_ACCESS)) == NULL) {
		return 11;
	}

  	if((hDomainNameService = OpenService(
       		hSCManager,                              
       		TEXT("DomainNameService"),               
       		SERVICE_ALL_ACCESS)) == NULL) {
                CloseServiceHandle(hSCManager);
		return 12;
	}

	if (!ControlService(hDomainNameService, ControlCode, &ServiceStatus))
         {
                CloseServiceHandle(hDomainNameService);
                CloseServiceHandle(hSCManager);
		return 19;
  	 }
	
  CloseServiceHandle(hDomainNameService);
  CloseServiceHandle(hSCManager);
  return 0;

}


LONG APIENTRY addKeysToRegistry(HWND hwnd, LPLONG lpIValue, LPSTR bs)

{
  HKEY hk;                      /* registry key handle */
  BOOL bSuccess;
  UCHAR   myarray[200];
  char *lpmyarray = myarray;
  int arsize = 0;

 /* now add the depends on service key */
 
  /* Create a new key for our application */
  bSuccess = RegCreateKey(HKEY_LOCAL_MACHINE,
      "SYSTEM\\CurrentControlSet\\Services\\DomainNameService", &hk);
  if(bSuccess != ERROR_SUCCESS)
    {
      return 1;
    }

  strcpy(lpmyarray,"TcpIp");
  lpmyarray = lpmyarray + 6;
  arsize = arsize + 6;
  strcpy(lpmyarray,"Afd");
  lpmyarray = lpmyarray + 4;
  arsize = arsize + 4;
  strcpy(lpmyarray,"LanManWorkstation");
  lpmyarray = lpmyarray + 18;
  arsize = arsize + 19;
  strcpy(lpmyarray,"\0\0");
  
  bSuccess = RegSetValueEx(hk,  /* subkey handle         */
      "DependOnService",                 /* value name            */
      0,                        /* must be zero          */
      REG_MULTI_SZ,                   /* value type            */
      (LPBYTE) &myarray,        /* address of value data */
      arsize);   /* length of value data  */
   if(bSuccess != ERROR_SUCCESS)
    {
      return 1;
    }

  RegCloseKey(hk);
  return 0;
}



void main(argc,argv)
int argc;
char *argv[];
{
 LONG rvalue;
 HWND bshwnd;
 LPLONG bsval;
 char bs[255];

  if (argc != 2)
    {
         printf("error for testing one test argument must be passed:\n");
         printf("start stop install remove addkeys\n");
         exit(1);
    }
    ++argc;
    if (strcmp((char *)argv[1],"start") == 0)
      {
        rvalue = StartBINDService(bshwnd,bsval,bs);
        if (rvalue != 0)
           { printf("startup failed ecode = %d \n",rvalue);
           }
        else printf("Startup ok!");
      }
      
 else if (strcmp((char *)argv[1],"stop") == 0)
      {
  rvalue = StopBINDService(bshwnd,bsval,bs);
        if (rvalue != 0)
           { printf("stop failed ecode = %d \n",rvalue);
           }
        else printf("Stop ok!");
      }
      
 else if (strcmp((char *)argv[1],"install") == 0)
      {

  strcpy(bs,"i:\\winnt\\system32\\named.exe");
  rvalue = CreateBINDService(bshwnd,bsval,bs);
        if (rvalue != 0)
           { printf("install failed ecode = %d \n",rvalue);
           }
        else printf("install ok!");
      }

 else if (strcmp((char *)argv[1],"remove") == 0)
      {
  strcpy(bs,"DomainNameService");
  rvalue = RemoveBINDService(bshwnd,bsval,bs);
        if (rvalue != 0)
           { printf("remove failed ecode = %d \n",rvalue);
           }
        else printf("remove ok!");
      }

 else if (strcmp((char *)argv[1],"addkeys") == 0)
      {

  rvalue = addKeysToRegistry(bshwnd,bsval,bs);
        if (rvalue != 0)
           { printf("addkeys failed ecode = %d \n",rvalue);
           }
        else printf("addkeys ok!");
      }

else printf("unknown test option %s \n",argv[2]);

}
