/*--------------------------------------------------------------
	File:		ndc95.c
	Function:	control-panel applet for BIND win95 version
	By:			l. kahn
	Created:	7/3/96

  becausae of bug of sending over each interface and the problem of
  not keeping track of id's in the outgoing direction close slots
  after every command

  don't let start/stop work on remote machine.. as it can't like nt

--------------------------------------------------------------*/
#include <windows.h>
#include <windowsx.h>
#include <cpl.h>
#include "ndc.h"
#include "resource.h"
#include "../conf/portability.h"
#include "../compat/lib/log.h"


#define              SZ_NAME_BUF 50
char    inbuf[160];
char    outbuf[160];
char    commonbuf[160];
DWORD   bytesRead, bytesWritten;
char *current_string;
BOOL    ret, ret2, ret3;
#define               SZ_SLOT_NAME_BUF 50
UCHAR   ucSlotNameBuf[SZ_SLOT_NAME_BUF] = "";
LPTSTR  lpszSlotName = (LPTSTR)&ucSlotNameBuf;
OSVERSIONINFO myver;
UCHAR   ucOperation = '\0';
UCHAR   ucMchNameBuf[SZ_NAME_BUF] = "";
LPTSTR  lpszMchName = (LPTSTR)&ucMchNameBuf;
char myname[100];
DWORD nsize = 99;
char myname2[102];
HANDLE outslot;
HANDLE inslot;
BOOL running;
char tickbuf[20];
BOOL handles_open = FALSE;
char dummy[200];
BOOL onnt;

typedef struct tagApplet
{
    int icon;           // icon resource identifier
    int namestring;     // name-string resource identifier
    int descstring;     // description-string resource identifier
    int dlgtemplate;    // dialog box template resource identifier
    DLGPROC dlgfn;      // dialog box procedure
} APPLET;

APPLET BindApplet =
{
    BIND_ICON, 
    BIND_NAME, 
    BIND_DESC,
    BIND_DLG,
    BindDlgProc,
};

HWND 			g_hwndDlg;
HANDLE 			hModule = NULL;
DWORD 			ControlCode;
SERVICE_STATUS 	ServiceStatus;
HANDLE 			hSCManager = NULL;
HANDLE			hDomainNameService = NULL;
BOOLEAN localmachine = TRUE;
BOOLEAN local_nolog_registry_flagset = FALSE;
BOOLEAN local_nolog_flagset = FALSE;

char szMsg[255];
char szCtlPanel[30];
char editor[100];
char server[50];
char image_path[300];
char image_path2[300];
char commandline[1000];
BOOLEAN server_up = FALSE;
BOOL onlocalmachine = FALSE;
HWND hBtnStart, hBtnStop, hBtnRestart, hBtnEditLog;
HWND hcbox;

static int  ndcStartService();
static int  ndcStopService();
static void ndcQueryToggle();
static void ndcTraceOff();
static void ndcTraceOn();
static void ndcReloadDatabase();
static void ndcDumpDatabase();
static void ndcStatusService();
static void ndcWriteStats();
static void ndcRestartService();
static void ndcEditLog();
static void process_nolog_flag();
static void logging();
static void nologging();

/*--------------------------------------------------------------
	Function:	DllMain
--------------------------------------------------------------*/
BOOL WINAPI DllMain(IN PVOID hmod,IN ULONG ulReason,
					IN PCONTEXT pctx OPTIONAL)
{
    if (ulReason != DLL_PROCESS_ATTACH)
        return TRUE;
    else
        hModule = hmod;

    return TRUE;
    UNREFERENCED_PARAMETER(pctx);
}


/*--------------------------------------------------------------
	Function:	InitBindApplet
	Synopsis:	load the caption string for Control Panel
--------------------------------------------------------------*/
BOOL InitBindApplet (HWND hwndParent)
{
    BOOL bResult = TRUE;
    onnt = OnWinnt();	
    LoadString (hModule,CPCAPTION,szCtlPanel,sizeof(szCtlPanel));
    return TRUE;
    UNREFERENCED_PARAMETER(hwndParent);
}

/*--------------------------------------------------------------
	Function:	TermBindApplet
	Synopsis:	terminate the applet:  do nothing
--------------------------------------------------------------*/
void TermBindApplet()
{
}


/*--------------------------------------------------------------
	Function:	CPIApplet
	Synopsis:	process messages for applet
--------------------------------------------------------------*/
LONG CALLBACK CPlApplet(HWND hwndCPL, UINT uMsg,
				    LONG lParam1, LONG lParam2)
{
    int iApplet;
    LPNEWCPLINFO lpNewCPlInfo;
    static iInitCount = 0;
            
    switch (uMsg) {
        case CPL_INIT:              // first message, sent once
            if (!iInitCount)
                if (!InitBindApplet(hwndCPL))
                    return FALSE;
            iInitCount++;
            return TRUE;

        case CPL_GETCOUNT:          // second message, sent once
            return 1L;
            break;

        case CPL_NEWINQUIRE:        // third message, sent once per app
            lpNewCPlInfo = (LPNEWCPLINFO) lParam2;

            iApplet = (int)(LONG)lParam1;
            lpNewCPlInfo->dwSize = (DWORD) sizeof(NEWCPLINFO);
            lpNewCPlInfo->dwFlags = 0;
            lpNewCPlInfo->dwHelpContext = 0;
            lpNewCPlInfo->lData = 0;
            lpNewCPlInfo->hIcon = LoadIcon (hModule,
                (LPCTSTR) MAKEINTRESOURCE(BindApplet.icon));
            lpNewCPlInfo->szHelpFile[0] = '\0';

            LoadString (hModule, BindApplet.namestring,
                        lpNewCPlInfo->szName, 32);

            LoadString (hModule, BindApplet.descstring,
                        lpNewCPlInfo->szInfo, 64);
            break;

        case CPL_SELECT:            // application icon selected
            break;

        case CPL_DBLCLK:            // application icon double-clicked
            iApplet = (int)(LONG)lParam1;
            DialogBox (hModule,
                       MAKEINTRESOURCE(BindApplet.dlgtemplate),
                       hwndCPL,
                       BindApplet.dlgfn);
            break;

         case CPL_STOP:              // sent once per app. before CPL_EXIT
            break;

         case CPL_EXIT:              // sent once before FreeLibrary called
            iInitCount--;
            if (!iInitCount)
                TermBindApplet();
            break;

         default:
            break;
    }
    return 0;
}

/*--------------------------------------------------------------
	Function:	AddToListBox
	Synopsis:	put the char string passed, in the list box
--------------------------------------------------------------*/
static void AddToListBox (LPCTSTR szBuffer)
{
   HWND hwndDataBox = GetDlgItem(g_hwndDlg, IDC_DATABOX);

   int x = ListBox_AddString(hwndDataBox, szBuffer);
   ListBox_SetCurSel(hwndDataBox, x);

   if (ListBox_GetCount(hwndDataBox) > 100)
      ListBox_DeleteString(hwndDataBox, 0);
}
 
void PrintToBox(char *newtext, int count)
{
     int ctr = 0;
     int ctr2;
     char *cstring_ptr;
     char letter;
     BOOLEAN pending = FALSE;
     int len1 = strlen(newtext);

     if (count != 0)
       len1 = count;
     
     if (current_string == NULL)
       current_string = malloc(3000);

      cstring_ptr = current_string;        
        
        // lgk we need to parse the string and replace tabs with 5 spaces and newlines
       *cstring_ptr = '\0';
       for (ctr=0; ctr <= len1; ctr++)
        {
         letter = (char)*newtext;
          if (letter == '\t')
           {
            pending = TRUE;
            for (ctr2 = 0; ctr2 < 5; ctr2++)
               *cstring_ptr++ = ' ';
           } 
         else  if (letter == '\n')
          {
            *cstring_ptr++ = '\0';
 	       AddToListBox(current_string);
            cstring_ptr = current_string;
            *cstring_ptr = '\0';
            pending = FALSE;
          }  
        else if (letter == '\0') // ignore
        { }
        else if (letter == '\r') // ignore
        {  
          pending = TRUE;
          *cstring_ptr++ = ' ';
        }

        else // process
         {   
          *cstring_ptr++ = letter;
          pending = TRUE;
         }
       ++newtext;

      }
  if (pending) 
     {
      *cstring_ptr++ = '\0';
      AddToListBox(current_string);
     }
}

/* edit the file */
int edit_it (char *filename,BOOL lookintemp, BOOL logfile)
{
   
    STARTUPINFO sui;
    PROCESS_INFORMATION proc_info;

     /* can edit non logs on local machine  */
     if ((!onlocalmachine) || ((onlocalmachine) && (onnt) && (logfile)))
     {
       sprintf(szMsg,"Cannot edit %s on a remote machine\n(or on an NT machine)!",filename);
       PrintToBox(szMsg,0);
       return -1;
     }

    strcpy(commandline,editor);
    strcat(commandline," ");

    if (lookintemp)
      strcat(commandline,image_path);
    else 
      strcat(commandline,image_path2);
  
    strcat(commandline,filename);

	memset((char *)&sui, 0,sizeof(STARTUPINFO));
	sui.cb = sizeof(STARTUPINFO);
    /* give the app about a second to make sure the file was generated */
    Sleep(1000);
    if (!CreateProcess(NULL, commandline, NULL, NULL, FALSE, DETACHED_PROCESS, NULL,
					   NULL, &sui, (LPPROCESS_INFORMATION)&proc_info))
      {

        sprintf(szMsg,"Execution of Command Failed: %s",commandline);
        AddToListBox(szMsg);
	    return -1;
	  }
  return 1;
}

/*--------------------------------------------------------------
	Function:	Getvalues
	Synopsis:	Look in the registry for the editor string.
--------------------------------------------------------------*/
static int GetEditor(char *editor)

{

  HKEY hk;                      /* registry key handle */
  BOOL bSuccess;
  DWORD  sizeofeditor    = 100;


  /* Create/open a new key for our application */
  bSuccess = RegCreateKey(HKEY_LOCAL_MACHINE,
      "SOFTWARE\\DomainNameService\\Parameters", &hk);
  if(bSuccess != ERROR_SUCCESS)
    {
      strcpy(editor,"notepad.exe");
      return -1;
    }

  /* get the entry */
  bSuccess = RegQueryValueEx(hk,  /* subkey handle         */
     "Editor",       /* value name            */
      NULL,                        /* must be zero          */
      NULL,                   /* value type          not required  */
      (LPBYTE)editor,        /* address of value data */
      &sizeofeditor);   /* length of value data  */
  if(bSuccess != ERROR_SUCCESS)
    {
      RegCloseKey(hk);
      strcpy(editor,"notepad.exe");
      return 1;
    }

  RegCloseKey(hk);
  return 0;
}


/*-----------------------------------------------------------------
	Function:	GetNoLogFlagSet
------------------------------------------------------------------*/
void GetNoLogFlag()

{

  HKEY hk;                      /* registry key handle */
  BOOL bSuccess;
  DWORD  sizeofnologflag    = 2;

  local_nolog_registry_flagset = FALSE;
  local_nolog_flagset = FALSE;

  /* Create/open a new key for our application */
if (!onnt)
  bSuccess = RegCreateKey(HKEY_LOCAL_MACHINE,
      "SOFTWARE\\DomainNameService\\Parameters", &hk);
else
  bSuccess = RegCreateKey(HKEY_LOCAL_MACHINE,
      "SYSTEM\\CurrentControlSet\\Services\\DomainNameService\\Parameters", &hk);

  if(bSuccess != ERROR_SUCCESS)
    {
      return;
    }
  
  //sizeofnologflag = sizeof(local_nolog_registry_flagset);
  sizeofnologflag = 4;

  bSuccess = RegQueryValueEx(hk,  /* subkey handle                */
      "NoLogFlagSet",             /* value name                   */
      NULL,                       /* must be zero                 */
      NULL,                       /* value type                   */
      (LPBYTE) &local_nolog_registry_flagset,   /* address of value data        */
      &sizeofnologflag);          /* length of value data         */
   if(bSuccess != ERROR_SUCCESS)
    {
      return;
    }

 RegCloseKey(hk);
 local_nolog_flagset = local_nolog_registry_flagset;
}

/*--------------------------------------------------------------
	Function:	Getvalues
	Synopsis:	Look in the registry for the server string.
--------------------------------------------------------------*/
static int GetServer(char *server)

{

  HKEY hk;                      /* registry key handle */
  BOOL bSuccess;
  DWORD  sizeofserver    = 50;


  /* Create/open a new key for our application */
  bSuccess = RegCreateKey(HKEY_LOCAL_MACHINE,
      "SOFTWARE\\DomainNameService\\Parameters", &hk);
  if(bSuccess != ERROR_SUCCESS)
    {
      strcpy(server,"\0");
      return -1;
    }

  /* get the entry */
  bSuccess = RegQueryValueEx(hk,  /* subkey handle         */
     "Server",       /* value name            */
      NULL,                        /* must be zero          */
      NULL,                   /* value type          not required  */
      (LPBYTE)server,        /* address of value data */
      &sizeofserver);   /* length of value data  */
  if(bSuccess != ERROR_SUCCESS)
    {
      RegCloseKey(hk);
      strcpy(server,"\0");
      return 1;
    }

  RegCloseKey(hk);
  return 0;
}

/* ------------------------------------------------------------------------------------- */
/* get the system path.. this fixes a bug where db files are dumped here regardless of what the image
 path is ... lgk */

static int GetTPath(char *imagepath)

{

  INT bSuccess = 0;
  UINT  sizeofimagepath   = 300;
  
  bSuccess = GetTempPath(sizeofimagepath, (LPSTR)imagepath);

  if(!bSuccess)
    {
      strcpy(imagepath,"");
      return -1;
    }
  strcat(imagepath,"\\");
  return 0;
}

/* ------------------------------------------------------------------------------------- */
/* get the system path.. this fixes a bug where db files are dumped here regardless of what the image
 path is ... lgk */

static int GetSystemPath(char *imagepath)

{

  INT bSuccess = 0;
  UINT  sizeofimagepath   = 300;
  
  bSuccess = GetSystemDirectory((LPSTR)imagepath,sizeofimagepath);

  if(!bSuccess)
    {
      strcpy(imagepath,"");
      return -1;
    }
  strcat(imagepath,"\\");
  return 0;
}


/*-----------------------------------------------------------------
	Function:	SetNoLogFlag
------------------------------------------------------------------*/
static int SetNoLogFlag(DWORD localflag)
{
    HKEY hk;
    BOOL bSuccess;

if (!onnt)
  bSuccess = RegCreateKey(HKEY_LOCAL_MACHINE,
      "SOFTWARE\\DomainNameService\\Parameters", &hk);
else
  bSuccess = RegCreateKey(HKEY_LOCAL_MACHINE,
      "SYSTEM\\CurrentControlSet\\Services\\DomainNameService\\Parameters", &hk);

  if(bSuccess != ERROR_SUCCESS)
    {
      sprintf(szMsg,"regcreatekey for parameters failed!");
      AddToListBox(szMsg);
      return -1;
    }

  /* Add the flag entry */
  bSuccess = RegSetValueEx(hk,  /* subkey handle         */
      "NoLogFlagSet",           /* value name            */
      0,                        /* must be zero          */
      REG_DWORD,                /* value type            */
      (LPBYTE)&localflag,       /* address of value data */
      sizeof(localflag));        /* length of value data  */
   if(bSuccess != ERROR_SUCCESS)
    {
      RegCloseKey(hk);
      sprintf(szMsg,"regsetvalueex for NoLogFlagSet failed!");
      AddToListBox(szMsg);
      return -1;
    }

 RegCloseKey(hk);
 return 0;
}

/*-----------------------------------------------------------------
	Function:	SetEditor
	Synopsis:	Set a value for the editor in the registry
------------------------------------------------------------------*/
static int SetEditor(const char *Editor)
{
    HKEY hk;
    BOOL bSuccess;
	
  /* Create/open a new key for our application */
  bSuccess = RegCreateKey(HKEY_LOCAL_MACHINE,
      "SOFTWARE\\DomainNameService\\Parameters", &hk);
  if(bSuccess != ERROR_SUCCESS)
    {
      return -1;
    }

  /* Add the phone entry */
  bSuccess = RegSetValueEx(hk,  /* subkey handle         */
      "Editor",       /* value name            */
      0,                        /* must be zero          */
      REG_SZ,                   /* value type            */
      (LPBYTE) Editor,        /* address of value data */
      strlen(Editor) + 1);   /* length of value data  */
   if(bSuccess != ERROR_SUCCESS)
    {
      RegCloseKey(hk);
      return -1;
    }

 RegCloseKey(hk);
 return 0;
}


void setbuttons_stopped()
{
       if ((onlocalmachine) && (!onnt))
       { 
         EnableWindow(hBtnStart,TRUE);
         EnableWindow(hBtnRestart,FALSE);
         EnableWindow(hBtnStop,FALSE);
       }
       else 
       {
         EnableWindow(hBtnStart,FALSE);
         EnableWindow(hBtnRestart,FALSE);
       }

       CheckDlgButton(g_hwndDlg,IDC_RUNNING,0);
       CheckDlgButton(g_hwndDlg,IDC_STOPPED,1);
       server_up = FALSE;

  if ((!onlocalmachine) || ((onlocalmachine) && (onnt)))
     EnableWindow(hBtnEditLog,FALSE);
  else EnableWindow(hBtnEditLog,TRUE);

}


void setnolog_button()
{   
          if (local_nolog_registry_flagset)
             CheckDlgButton(g_hwndDlg,IDC_NOLOGFLAG,1);
          else 
              CheckDlgButton(g_hwndDlg,IDC_NOLOGFLAG,0);
}

void setbuttons_running()
{

      if ((onlocalmachine) && (!onnt))
       { 
         EnableWindow(hBtnStart,FALSE);
         EnableWindow(hBtnStop,TRUE);
         EnableWindow(hBtnRestart,TRUE);
       }
       else
       {
         EnableWindow(hBtnStart,FALSE);
         EnableWindow(hBtnRestart,FALSE);
       }

       CheckDlgButton(g_hwndDlg,IDC_STOPPED,0);
       CheckDlgButton(g_hwndDlg,IDC_RUNNING,1);
       server_up = TRUE;

  if ((!onlocalmachine) || ((onlocalmachine) && (onnt)))
     EnableWindow(hBtnEditLog,FALSE);
  else EnableWindow(hBtnEditLog,TRUE);

}

/*-----------------------------------------------------------------
	Function:	SetServer
	Synopsis:	Set a value for the server in the registry
------------------------------------------------------------------*/
static int SetServer(const char *Server)
{
    HKEY hk;
    BOOL bSuccess;
	
  /* Create/open a new key for our application */
  bSuccess = RegCreateKey(HKEY_LOCAL_MACHINE,
      "SOFTWARE\\DomainNameService\\Parameters", &hk);
  if(bSuccess != ERROR_SUCCESS)
    {
      return -1;
    }

  bSuccess = RegSetValueEx(hk,  /* subkey handle         */
      "Server",       /* value name            */
      0,                        /* must be zero          */
      REG_SZ,                   /* value type            */
      (LPBYTE) Server,        /* address of value data */
      strlen(Server) + 1);   /* length of value data  */
   if(bSuccess != ERROR_SUCCESS)
    {
      RegCloseKey(hk);
      return -1;
    }

 RegCloseKey(hk);
 
  // reset our server
   if ((strncmp(Server,"  ",2) == 0) || (strlen(Server) <3))
         {
          /* no server */
          onlocalmachine = TRUE;
          localmachine = TRUE;
          strcpy(server,"\0");
          SetDlgItemText(g_hwndDlg,IDC_Server,server);
         }
    else localmachine = FALSE;
  
  if (localmachine)
     strcpy(lpszMchName,myname2);
   else
    {
     strcpy(lpszMchName,Server);
    }
 
   
  onlocalmachine = TRUE;
  if ((strcmp(myname2,lpszMchName) != 0) && (!onnt))
    {
       onlocalmachine = FALSE;
       EnableWindow(hBtnStart,FALSE);
       EnableWindow(hBtnRestart,FALSE);
    }
  else
  {
    EnableWindow(hBtnStart,TRUE);
    EnableWindow(hBtnRestart,TRUE);
  }
   
  if ((!onlocalmachine) || ((onlocalmachine) && (onnt)))
     EnableWindow(hBtnEditLog,FALSE);
  else EnableWindow(hBtnEditLog,TRUE);

  if (server_up)
    setbuttons_running();
  else setbuttons_stopped();

  
 return 0;
}



void CloseHandles()
{
     CloseHandle(outslot);
     CloseHandle(inslot);
     handles_open = FALSE;
}


/* ----------------------------------------- */

BOOL open_handles()

{

  if (handles_open)
     return TRUE;

  outbuf[0] = ucOperation;
  outbuf[1] = '\0';

  strcpy(commonbuf,myname);
  strcat(commonbuf," ");
  strcat(commonbuf,"sd_ndccp ");
  
  inslot = CreateMailslot("\\\\.\\mailslot\\sd_ndccp",0,7000,NULL);

  if (inslot == INVALID_HANDLE_VALUE)
      {
        sprintf(szMsg,"Unable to create outgoing mail slot!: %u",GetLastError());
        AddToListBox(szMsg);
	   return FALSE;
      }

  outslot = CreateFile(lpszSlotName,GENERIC_WRITE,FILE_SHARE_READ,NULL,OPEN_EXISTING,
                           FILE_ATTRIBUTE_NORMAL,NULL);
  if (outslot == INVALID_HANDLE_VALUE)
     {
       sprintf(szMsg,"Unable to open Outgoing Mail Slot (ie communicate with server): %u",GetLastError());
       AddToListBox(szMsg);
       AddToListBox("Check server Name!");
       CloseHandle(inslot);
       handles_open = FALSE;
       return FALSE;
     }

handles_open = TRUE;     
return TRUE;

}

/* ----------------------------------------- */

 /* open service */
 /* now init the service stuff */
 BOOL open_service()
 {
    // under win95 this is different
    BOOL rv = FALSE;
    nsize = 99;

  rv = GetComputerName((char *)&myname,&nsize);
  if (rv != TRUE)
    { 
       sprintf(szMsg,"GetComputerName failed: %d ",GetLastError());
       AddToListBox(szMsg);
    }

  strcpy(myname2, "\\\\");
  strcat(myname2,myname);

   if (localmachine)
     strcpy(lpszMchName,myname2);
   else
    {
     strcpy(lpszMchName,server);
    }


  onlocalmachine = TRUE;
  if (strcmp(myname2,lpszMchName) != 0)
    {
       onlocalmachine = FALSE;
       EnableWindow(hBtnStart,FALSE);
       EnableWindow(hBtnRestart,FALSE);
  }
  else
  {
    EnableWindow(hBtnStart,TRUE);
    EnableWindow(hBtnRestart,TRUE);
  }

  strcpy(lpszSlotName,lpszMchName);
  strcat(lpszSlotName,"\\mailslot\\sd_bind");
  return TRUE;

 }

/*-------------------------------------------------------- */
/* is running or not */
BOOL is_running(BOOL ignore_error)

{

  ret = FALSE;
  if (!handles_open)
  { 
    ret = open_handles();
  }

  if (!ret)
   return FALSE;
   
   strcpy(outbuf,commonbuf);
   strcat(outbuf,"status ");
   sprintf(tickbuf,"%d",GetTickCount());
   strcat(outbuf,tickbuf);

//  sprintf(szMsg,"command being sent is %s ",outbuf);
//  AddToListBox(szMsg);

  ret = FALSE;
  ret = WriteFile(
                  outslot,       // file to write to
                  &outbuf,         // address of output buffer
                  strlen(outbuf) + 1, // number of bytes to write
                  &bytesWritten,  // number of bytes written
                  NULL);          // overlapped stuff, not needed

  if (!ret) 
   {
     sprintf(szMsg,"writefile failed in is_running, etc = %d",GetLastError());
     AddToListBox(szMsg);
     CloseHandles();
     return FALSE;
   }

   ret2 = FALSE;
   ret2 = ReadFile(
                    inslot,     // file to read from
                    &inbuf,          // address of input buffer
                    sizeof(inbuf),  // number of bytes to read
                    &bytesRead,     // number of bytes read
                    NULL);          // overlapped stuff, not needed

   if (!ret2)
     {
      if (!ignore_error)  
       { sprintf(szMsg,"readfile failed in is_running ec = %d ",GetLastError());
         AddToListBox(szMsg);
       }
      CloseHandles();
      return FALSE;
     }

  CloseHandles();
  return TRUE;

 } // end of running

/*--------------------------------------------------------------
	Function:	Dlg_OnInitDialog
	Synopsis:	initialize dialog:  save handle in global,
				display "ready" message
--------------------------------------------------------------*/
BOOL Dlg_OnInitDialog (HWND hwnd, HWND hwndFocus, LPARAM lParam)
{
    g_hwndDlg = hwnd;

    GetEditor(editor);
    GetServer(server);
    GetTPath(image_path);
    GetSystemPath(image_path2);
    SetDlgItemText(g_hwndDlg,IDC_Editor,editor);
    SetDlgItemText(g_hwndDlg,IDC_Server,server);
    hBtnStart   = GetDlgItem(g_hwndDlg,IDC_STARTUP);
    hBtnRestart = GetDlgItem(g_hwndDlg,IDC_RESTART);
    hBtnEditLog = GetDlgItem(g_hwndDlg,IDC_EDIT_LOG);
    hBtnStop = GetDlgItem(g_hwndDlg,IDC_SHUTDOWN);
    hcbox       = GetDlgItem(g_hwndDlg,IDC_NOLOGFLAG);
    
    if (strncmp(editor,"  ",2) == 0)
      { 
        strcpy(editor,"notepad.exe");
        SetEditor(editor);
        SetDlgItemText(g_hwndDlg,IDC_Editor,editor);
      }
      if ((strncmp(server,"  ",2) == 0) || (strlen(server) <3))
         {
          /* no server */
          localmachine = TRUE;
          strcpy(server,"\0");
          SetServer(server);
          SetDlgItemText(g_hwndDlg,IDC_Server,server);
         }
       else localmachine = FALSE;
   
        if (open_service() == TRUE)
       	 AddToListBox("Ready for Request");

        /* now check the status of the server and activate the correct radiobutton */
	if (!is_running(TRUE))
	  {
           setbuttons_stopped();
        }      /* not running */
	else
  	{
          setbuttons_running();
	}


	/* get the flag */
       if (onlocalmachine)
        {
         GetNoLogFlag();
  	 setnolog_button();
        }
       else
        {
         // status is unknown
         local_nolog_registry_flagset = FALSE;
         local_nolog_flagset = FALSE;
         EnableWindow(hcbox,FALSE);
        }
	return(TRUE);
}

/*--------------------------------------------------------------
	Function:	Dlg_OnDestroy
	Synopsis:	dummy function for end of dialog
--------------------------------------------------------------*/
void Dlg_OnDestroy (HWND hwnd)
{
  CloseHandle(inslot);
  CloseHandle(outslot);
  handles_open = FALSE;
}


/*--------------------------------------------------------------
	Function:	Dlg_OnCommand
	Synopsis:	message handler for dialog
--------------------------------------------------------------*/
void Dlg_OnCommand (HWND hwnd,int id,HWND hwndCtl,UINT codeNotify)
{
   	switch (id)
   	{
        case IDC_RESTART:   ndcRestartService();	break;
        case IDC_STARTUP:   ndcStartService();	break;
        case IDC_SHUTDOWN:  ndcStopService();	break;
        case IDC_STATUS:    ndcStatusService();   break;
        case IDC_STATS:     ndcWriteStats();    	break;
        case IDC_DUMPDB:    ndcDumpDatabase();	break;
        case IDC_TRACE:	   ndcTraceOn();		break;
        case IDC_NOTRACE:   ndcTraceOff();		break;
        case IDC_RELOAD:    ndcReloadDatabase();	break;
        case IDC_QUERY:	   ndcQueryToggle();	break;
        case IDCANCEL:      EndDialog(hwnd, id);  break;
        case IDOK:	        EndDialog(hwnd,id);	break;
        case IDC_EDIT_LOG:  ndcEditLog();         break;
     case IDC_NOLOGFLAG: process_nolog_flag(hwnd,id);     break;
     case IDC_NOLOGGING: nologging();             break;
     case IDC_LOGGING:   logging();               break;
        default:	                                
	      /* kludge cannot determine how to make the radion buttons read only easily
	         so set it always */
          if (server_up)
             setbuttons_running();
           else setbuttons_stopped();
   	}
}


/*--------------------------------------------------------------
	Function:	BindDlgProc
	Synopsis:	processes messages sent to applet
	Comments:	Dialog presents buttons for the signals
				that named.exe understands.
--------------------------------------------------------------*/
BOOL APIENTRY BindDlgProc (	HWND hDlg, UINT message,
				UINT wParam, LONG lParam)
{
	BOOL fProcessed = TRUE;

    switch (message)
     {

      case WM_COMMAND:
       {
        switch(LOWORD(wParam))
           {
           case IDC_SET_EDITOR:
              {
                GetDlgItemText(g_hwndDlg,IDC_Editor,editor,100);
                SetEditor(editor);
               }
               break;
             case IDC_SET_SERVER:
              {
                GetDlgItemText(g_hwndDlg,IDC_Server,server,50);
                SetServer(server);
                if (open_service() == TRUE)
       	          AddToListBox("Ready for Request");

               }
               break;
            }
         }
       }

    switch (message)
    {
	    HANDLE_MSG(hDlg, WM_INITDIALOG,     Dlg_OnInitDialog);      
	    HANDLE_MSG(hDlg, WM_COMMAND, 	Dlg_OnCommand);      
	    HANDLE_MSG(hDlg, WM_DESTROY, 	Dlg_OnDestroy);
	default:	
	fProcessed = FALSE;
	break;
    }
    return (fProcessed);
}


/* ----------------------------------------------------------------------- */

void start_up_bind()
{

   STARTUPINFO StartInfo;
   BOOLEAN rvalue;
   PROCESS_INFORMATION phandle;
   static char cline[100] = "named95.exe";
  
    /* Set up members of STARTUPINFO structure. */

    StartInfo.cb = sizeof(STARTUPINFO);
    StartInfo.lpReserved = NULL;
    StartInfo.lpReserved2 = NULL;
    StartInfo.cbReserved2 = 0;
    StartInfo.lpDesktop = NULL;

    // set noshow in case it is a win app
    StartInfo.dwFlags = STARTF_USESHOWWINDOW | STARTF_USEPOSITION;

    StartInfo.lpTitle = NULL;
    StartInfo.dwX = 1000;
    StartInfo.dwY = 1000;
    StartInfo.dwXSize = 0;
    StartInfo.dwYSize = 0;
    StartInfo.dwXCountChars= 0;
    StartInfo.dwYCountChars = 0;
    StartInfo.dwFillAttribute = 0;
    StartInfo.hStdInput = NULL;
    StartInfo.hStdOutput = NULL;
    StartInfo.hStdError = NULL;
    StartInfo.wShowWindow = SW_HIDE;

     rvalue = CreateProcess(NULL,(LPSTR)&cline,NULL,NULL,FALSE,DETACHED_PROCESS,NULL,NULL,&StartInfo,&phandle);
 
	if (rvalue == FALSE)
	  {
 	   
        int ecode = GetLastError();
	   if (ecode == 2)
	     {
		  AddToListBox("Startup of named95.exe failed errorcode = 2 (FILE_NOT_FOUND)");
	     }
	   else
          {
           sprintf(szMsg,"Startup of named95.exe failed errorcode = %d",ecode);
           AddToListBox(szMsg);
	   	 }

	    fflush(stdout);
	    Sleep(10000);
	   }
	   
	     {
	      DWORD waitval = WaitForInputIdle(phandle.hProcess,5000);
	     }

  	   CloseHandle(phandle.hThread);
	   CloseHandle(phandle.hProcess);

	   }

/*--------------------------------------------------------------
	Function:	ndcStartService
	Synopsis:	start bind
--------------------------------------------------------------*/
static int ndcStartService(void)
{
           BOOL running = FALSE;

           // lgk first try status command to see if already running
           // so we don't start it again. ignore the error first time
           if (!is_running(TRUE))
             {
              // set to start
              start_up_bind();
              Sleep(2000);
              if (!is_running(FALSE))
                {
		       sprintf(szMsg,"Unable to start the Domain Name Service: %u", GetLastError());
		       AddToListBox(szMsg);
		       return(FALSE);
                }

               else
                { // started ok
                  setbuttons_running();
	          sprintf(szMsg, "Name Server Started.");
	          AddToListBox(szMsg);
	          return(TRUE);
	         }
	     } // not running
                
           else // already running
             {
	       sprintf(szMsg,"Domain Name Service already running!");
	       AddToListBox(szMsg);
               setbuttons_running();
             }
 return(FALSE);

}

/*--------------------------------------------------------------
	Function:	ndcStopService
	Synopsis:	send a STOP signal to DNS service
--------------------------------------------------------------*/
static int ndcStopService()
{

                if (!handles_open)
                  open_handles();

                 // stop it first
                 ret3 = FALSE;
                 strcpy(outbuf,commonbuf);
                 strcat(outbuf,"stop ");
                 sprintf(tickbuf,"%d",GetTickCount());
                 strcat(outbuf,tickbuf);

                 ret3 = WriteFile(
                        outslot,       // file to write to
                        &outbuf,         // address of output buffer
                        strlen(outbuf) + 1, // number of bytes to write
                        &bytesWritten,  // number of bytes written
                        NULL);          // overlapped stuff, not needed

                  if (!ret3)
                    {
 		           sprintf(szMsg,"Stop request failed:  %u",GetLastError());
		           AddToListBox(szMsg);
                     CloseHandles();
		           return(FALSE);
                    }  

     setbuttons_stopped();
	sprintf(szMsg,"Name Server stopped. \nWarning: if the remote server is running Windows NT\n This command will be ignored!");
	PrintToBox(szMsg,0);
     CloseHandles();
	return(TRUE);
}

/*--------------------------------------------------------------
	Function:	ndcrestart
	Synopsis:	restart the dns server...
	                you can use start and stop here.. but
	                to be consistend with the unix ndc I
	                have also implement restart.
--------------------------------------------------------------*/

static void ndcRestartService(void)
{
             if (!is_running(FALSE))
                {
		     sprintf(szMsg,"Unable to restart ... Domain Name Service is not running!");  
	             AddToListBox(szMsg);
                  setbuttons_stopped();
                  return;
                }
             else
               // aleady running stop/start it
               {

                 if (!handles_open)
                  open_handles();

                 // stop it first
                 ret3 = FALSE;
                 strcpy(outbuf,commonbuf);
                 strcat(outbuf,"stop ");
                 sprintf(tickbuf,"%d",GetTickCount());
                 strcat(outbuf,tickbuf);

                 ret3 = WriteFile(
                        outslot,       // file to write to
                        &outbuf,         // address of output buffer
                        strlen(outbuf) + 1, // number of bytes to write
                        &bytesWritten,  // number of bytes written
                        NULL);          // overlapped stuff, not needed

                 if (!ret3)
                    {
			         sprintf(szMsg,"Unable to restart the Domain Name Service: %u", GetLastError());
                        AddToListBox(szMsg);
                        setbuttons_stopped();
                        return;
                    }  
                  else // shutdown ok
                   {
                     // now give it time to stop
                     AddToListBox("Server stop signal sent...waiting for shutdown...");
                     CloseHandles();
                     Sleep(7000);
                     AddToListBox("Starting up server... Waiting for acknowledgement...");
                     start_up_bind();
                     Sleep(2000);

                     if (is_running(FALSE))
                      {
                        setbuttons_running();
	                   sprintf(szMsg, "Name Server Restarted.");
	                   AddToListBox(szMsg);
                      }

		     else // restart failed
		      {
 	                   sprintf(szMsg,"Restart Failed: %u", GetLastError());
                        AddToListBox(szMsg);
                        setbuttons_stopped();
                        return;
		      }

		   } // shutdown ok
	       } // already running		      
}


/*--------------------------------------------------------------
	Function:	send command
--------------------------------------------------------------*/

BOOL send_command(cmd,resval)

char *cmd;
char *resval;
 
  {
       if (!handles_open)
         open_handles();

         
       strcpy(outbuf,commonbuf);
       strcat(outbuf,cmd);
       strcat(outbuf," ");
       sprintf(tickbuf,"%d",GetTickCount());
       strcat(outbuf,tickbuf);

        //AddToListBox("sending command");
        //AddToListBox(outbuf);

            // now write the data
            ret = FALSE;
            ret = WriteFile(
                      outslot,       // file to write to
                      &outbuf,         // address of output buffer
                      strlen(outbuf) + 1, // number of bytes to write
                      &bytesWritten,  // number of bytes written
                      NULL);          // overlapped stuff, not needed


            if (!ret)
              {
             if (ERROR_ACCESS_DENIED == GetLastError())
               {
 	             sprintf(szMsg,"%s Command Send Failed (access denied)!", cmd);
                  AddToListBox(szMsg);  
                  CloseHandles();
                  return FALSE;
               }
              else if (ERROR_BAD_NETPATH == GetLastError())
               {
 	             sprintf(szMsg,"%s Command Send Failed (Bad Netpath)!", cmd);
                  AddToListBox(szMsg); 
                  CloseHandles();
                  return FALSE;
	       }
             else
             {
 	          sprintf(szMsg,"%s Command Send Failed: %u", cmd, GetLastError());
               AddToListBox(szMsg);
               CloseHandles();
               return FALSE;
             }
	   } // ret
	   
           strcpy(inbuf,"                                                  ");
           // now get the response via other mailslot
           ret2 = FALSE;
           ret2 = ReadFile(
                   inslot,     // file to read from
                   &inbuf,          // address of input buffer
                   sizeof(inbuf),  // number of bytes to read
                   &bytesRead,     // number of bytes read
                   NULL);          // overlapped stuff, not needed
                  
            /*
             sprintf(szMsg,"got value back %s",inbuf);
            AddToListBox(szMsg);
            sprintf(szMsg,"ret2 code = %d ",ret2);
            AddToListBox(szMsg);
            */

            CloseHandles();

            if (!ret2)
             {
               if (ERROR_BAD_NETPATH == GetLastError())
               {
 	          sprintf(szMsg,"%s Command Failed: (machine %s not found)!", cmd,lpszMchName);
               AddToListBox(szMsg);
               return FALSE;
               }
             else
              {
 	          sprintf(szMsg,"%s Command Failed: (trying to get response) %d!", cmd,GetLastError());
               AddToListBox(szMsg);
               return FALSE;
              }
             } // ret2
             
          if (strcmp(cmd,"status") == 0)
           {
             strncpy(resval,inbuf,bytesRead);
             return TRUE;
           }
           
          // if we get ok all is fine
          if (strncmp(inbuf,"Ok",2) == 0)
            {
              strncpy(resval,inbuf,bytesRead);
              return TRUE;
            }
          else
            {
 	          sprintf(szMsg,"%s Command Failed: (received invalid respose = %s)!",cmd);
               AddToListBox(szMsg);
               strcpy(resval,inbuf);
               return FALSE;
	    }
  }


#define LB_MSG(a,b)   sprintf(szMsg,a,b);   AddToListBox(szMsg);

/*--------------------------------------------------------------
	Function:	ndcWriteStats
	Synopsis:	send a WRITE_STATS signal to DNS service
--------------------------------------------------------------*/

static void ndcWriteStats()
{
        strcpy(dummy," ");
        if (!send_command("stats",dummy))
         {
	      sprintf(szMsg,"Stats request failed: %s  %u",dummy,GetLastError());
           AddToListBox(szMsg);
         }
	else
        {
  	   AddToListBox("Current Stats. written to file 'named.sts'.");

           if (!edit_it("named.sts",FALSE,FALSE))
             AddToListBox("Edit of Stats. file failed.");
        }
}
                                              

/*--------------------------------------------------------------
	Function:	ndcStatusService
	Synopsis:	print the service status
--------------------------------------------------------------*/
static void ndcStatusService()
{
        strcpy(dummy," ");
	/* refresh the running buttons based on the status */
	if (!send_command("status",dummy))
          {
		sprintf(szMsg,"Status request failed: %s %u",dummy,GetLastError());
		setbuttons_stopped();
	  }
	else
  	{
         setbuttons_running();
  	 AddToListBox("Status of Domain Name Service:");
         PrintToBox(dummy,0);
	}
}

/*--------------------------------------------------------------
	Function:	ndcDumpDatabase
	Synopsis:	send a DUMP signal to DNS service
--------------------------------------------------------------*/
static void ndcDumpDatabase()
{

        strcpy(dummy," ");
	if (!send_command("dumpdb",dummy))
	  {	
	   sprintf(szMsg,"Dump request failed: %s  %u",dummy,GetLastError());
           AddToListBox(szMsg);
          } 
	else
  	  {
  	   sprintf(szMsg,"Database dumped to file 'namdump.db'.");
	   AddToListBox(szMsg);

       /* now pull this up in the editor */
       if (!edit_it("namdump.db",FALSE,FALSE))
         AddToListBox("Edit of database dump failed.");
      }
}      

/*--------------------------------------------------------------
	Function:	ndcReloadDatabase
	Synopsis:	send a RELOAD signal to DNS service
--------------------------------------------------------------*/
static void ndcReloadDatabase()
{
        strcpy(dummy," ");
	if (!send_command("reload",dummy))
		sprintf(szMsg,"Reload request failed: %s  %u",dummy,GetLastError());
	else
  		sprintf(szMsg,"Database reloaded.");
	AddToListBox(szMsg);
}

/*--------------------------------------------------------------
	Function:	ndcTraceOn
	Synopsis:	send a TRACE ON signal to DNS service
--------------------------------------------------------------*/
static void ndcTraceOn()
{
        strcpy(dummy," ");
	if (!send_command("trace",dummy))
		sprintf(szMsg,"Trace request failed: %s  %u",dummy,GetLastError());
	else
  		sprintf(szMsg,"Tracing Level Incremented.");
	AddToListBox(szMsg);
}

/*--------------------------------------------------------------
	Function:	ndcTraceOff
	Synopsis:	send a TRACE OFF signal to DNS service
--------------------------------------------------------------*/
static void ndcTraceOff()
{
        strcpy(dummy," ");
	if (!send_command("notrace",dummy))
		sprintf(szMsg,"No-Trace request failed: %s %u",dummy,GetLastError());
	else
  		sprintf(szMsg,"Tracing turned off.");
	AddToListBox(szMsg);
}

/*--------------------------------------------------------------
	Function:	ndcQueryToggle
	Synopsis:	send a QRYLOG signal to DNS service
--------------------------------------------------------------*/
static void ndcQueryToggle()
{
        strcpy(dummy," ");
	if (!send_command("querylog",dummy))
		sprintf(szMsg,"Toggle Query Logging request failed: %s %u",dummy,GetLastError());
	else
  		sprintf(szMsg,"Query Logging toggled.");
	AddToListBox(szMsg);
}

/*--------------------------------------------------------------*/
/* lgk new for win95 edit the log as there is no application log  */

static void ndcEditLog()
{
       /* now pull this up in the editor */
       if (!edit_it("named95.log",FALSE,TRUE))
         AddToListBox("Edit of named log file failed.");
}      

/*--------------------------------------------------------------
	Function:	process_nologflag
	Synopsis:	send a QRYLOG signal to DNS service
--------------------------------------------------------------*/
static void process_nolog_flag(HWND hwnd,int id)
{
       // get the value of the control

       UINT rval = IsDlgButtonChecked(hwnd,id);
       
       if (rval == BST_CHECKED)
         {
          local_nolog_registry_flagset = TRUE;
          if (!send_command("nolog",dummy))
		sprintf(szMsg,"Set NoLog Flag request failed:  %u",GetLastError());
          else
  		sprintf(szMsg,"NoLog Flag Enabled.");
         }

       else
         {
          local_nolog_registry_flagset = FALSE;
          if (!send_command("log",dummy))
		sprintf(szMsg,"Set NoLog Flag request failed:  %u",GetLastError());
          else
  		sprintf(szMsg,"NoLog Flag Cleared.");
         }
       AddToListBox(szMsg);
       local_nolog_flagset = local_nolog_registry_flagset;
       (void)SetNoLogFlag((DWORD)local_nolog_registry_flagset);
}


static void nologging()
{
          local_nolog_flagset = TRUE;
          if (!send_command("nolog",dummy))
		  sprintf(szMsg,"Set NoLog Flag request failed:  %u",GetLastError());
          else
  		  sprintf(szMsg,"NoLog Flag Enabled.");
  	     AddToListBox(szMsg);
}


static void logging()
{
          local_nolog_flagset = FALSE;
          if (!send_command("log",dummy))
		  sprintf(szMsg,"Set NoLog Flag request failed:  %u",GetLastError());
          else
  		  sprintf(szMsg,"NoLog Flag Cleared.");
	     AddToListBox(szMsg);
}


