// setup.c - Winmain (built with win.bat, sr.bat (or sr2.bat) for resources)
//                   XP manifest included in setup.rc
 
// Copyright NAT Software, 2004

#include <windows.h>
#include <commctrl.h>
#include <commdlg.h>
#include <shlobj.h>
#include <ras.h>
#include "setup.h"

#define CSIDL_PROGRAM_FILES             0x0026        // C:\Program Files

// Browsing for directory.

#define BIF_RETURNONLYFSDIRS   0x0001  // For finding a folder to start document searching
#define BIF_DONTGOBELOWDOMAIN  0x0002  // For starting the Find Computer
#define BIF_STATUSTEXT         0x0004  // Top of the dialog has 2 lines of text for BROWSEINFO.lpszTitle and one line if
                                       // this flag is set.  Passing the message BFFM_SETSTATUSTEXTA to the hwnd can set the
                                       // rest of the text.  This is not used with BIF_USENEWUI and BROWSEINFO.lpszTitle gets
                                       // all three lines of text.
#define BIF_RETURNFSANCESTORS  0x0008
#define BIF_EDITBOX            0x0010   // Add an editbox to the dialog
#define BIF_VALIDATE           0x0020   // insist on valid result (or CANCEL)
                                                                                                                        
#define BIF_NEWDIALOGSTYLE     0x0040   // Use the new dialog layout with the ability to resize
                                        // Caller needs to call OleInitialize() before using this API
                                        
#define BIF_USENEWUI           (BIF_NEWDIALOGSTYLE | BIF_EDITBOX)

#define BIF_BROWSEINCLUDEURLS  0x0080   // Allow URLs to be displayed or entered. (Requires BIF_USENEWUI)

#define BIF_BROWSEFORCOMPUTER  0x1000  // Browsing for Computers.
#define BIF_BROWSEFORPRINTER   0x2000  // Browsing for Printers
#define BIF_BROWSEINCLUDEFILES 0x4000  // Browsing for Everything
#define BIF_SHAREABLE          0x8000  // sharable resources displayed (remote shares, requires BIF_USENEWUI)

// message from browser
#define BFFM_INITIALIZED        1
#define BFFM_SELCHANGED         2
#define BFFM_VALIDATEFAILEDA    3   // lParam:szPath ret:1(cont),0(EndDialog)
#define BFFM_VALIDATEFAILEDW    4   // lParam:wzPath ret:1(cont),0(EndDialog)

// messages to browser
#define BFFM_SETSTATUSTEXTA     (WM_USER + 100)
#define BFFM_ENABLEOK           (WM_USER + 101)
#define BFFM_SETSELECTIONA      (WM_USER + 102)
#define BFFM_SETSELECTIONW      (WM_USER + 103)
#define BFFM_SETSTATUSTEXTW     (WM_USER + 104)

                                        
int argc;
char *argv[4];

char desktop[1024];
char cur_dir[1024];
char sys_dir[1024];
char win_dir[1024];
char ins_dir[1024];
char dest[1024];
char tmp[1024];

HINSTANCE hInst;
HCURSOR hNewCursor;
HCURSOR hOldCursor;
HWND hList;
HWND hWnd;
HWND hAbout;
int hide_flag;
int idList;
HFONT hFont;

OSVERSIONINFO version;
int platform;
int platform2;
int installed;
int ndis3pkt_ok;
int completed;

OPENFILENAME ofn;

HINSTANCE hRasDll;
int ras_loaded;
char pbk_file[8192];

// RAS function prototypes

DWORD APIENTRY (*pRasEnumEntries)(LPTSTR, LPTSTR, LPRASENTRYNAME, LPDWORD, LPDWORD);

int done;

int CALLBACK BrowseCallbackProc(HWND hwnd,UINT uMsg,LPARAM lp, LPARAM pData) {

    TCHAR szDir[MAX_PATH];
    LPCITEMIDLIST pidl;

    switch(uMsg) {
        case BFFM_INITIALIZED: {
            SHGetSpecialFolderLocation(NULL, CSIDL_PROGRAM_FILES, &pidl);
            SendMessage(hwnd,BFFM_SETSELECTION,FALSE,(LPARAM) pidl);
            CenterWindow(hwnd);
            SetWindowText(hwnd, "NAT32 Installation Directory");
            break;
        }
        case BFFM_SELCHANGED: {
            if (SHGetPathFromIDList((LPITEMIDLIST) lp ,szDir)) {
                 SendMessage(hwnd,BFFM_SETSTATUSTEXT,0,(LPARAM)szDir);
            }
            break;
        }
        default:
            break;
    }
    return 0;
}

char msg1[] = "NAT32 Install Log";
char msg2[] = "=================";
char msg4[] = "Click OK to start, Cancel to exit..."; 
char msg5[] = "Click OK to UNINSTALL NAT32, Cancel to exit...";
char job1[] = "RunDll32 setupapi.dll,InstallHinfSection InstallNAT32 4 ";
char job2[] = "RunDll32 setupapi.dll,InstallHinfSection InstallNAT32 4 ";
char job3[] = "RunDll32 setupapi.dll,InstallHinfSection UninstallNAT32 4 ";
char job4[] = "RunDll32 setupapi.dll,InstallHinfSection UninstallNAT32 4 ";

char buf[4096];
int  uninst;

int wait();

// Function prototypes

BOOL APIENTRY MyDlgProc (HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
DWORD FindNet95(HKEY hStartKey , char *pKeyName, char *rbuf);

//
// kprintf - low-level printf
//
int kprintf(char *fmt, ...)
{
    va_list args;
    int i;
    int w;
    char buf[0x8000];

    va_start(args, fmt);
    vsprintf(buf, fmt, args);
    va_end(args);

    return MessageBox(hWnd, buf, "NAT32 Installer", MB_OKCANCEL | MB_SETFOREGROUND | MB_ICONWARNING);

}

int WINAPI WinMain(HINSTANCE hExe, HINSTANCE hPrev, LPSTR CmdLine, int CmdShow)
{
    char    *pstart;
    char    *pnext;
    int     count, i, result;

    INITCOMMONCONTROLSEX InitCtrls;

    hInst = hExe;
        
    InitCtrls.dwSize = sizeof(INITCOMMONCONTROLSEX);
    InitCtrls.dwICC = ICC_BAR_CLASSES | ICC_WIN95_CLASSES;
    InitCommonControlsEx(&InitCtrls);
    
    // generate standard string args
    
    argc = 1;
    argv[0] = "setup";
    pstart = CmdLine;
    
    while (strlen(pstart)) {

        argv[argc++] = pstart;
        pnext = strchr(pstart, ' ');

        if (pnext == 0)
            break;

        *pnext++ = 0;
        pstart = pnext;

        if (argc > 3)
            break;

        while (*pstart && isspace(*pstart)) pstart++;
    }

    if (argc > 2) {
        kprintf("Usage: setup [dir] | [-u]\n");
        return 0;
    }

    switch (argc) {
        
        case 1: uninst = FALSE;
                strcpy(ins_dir, "C:\\NAT32E");
                break;
                
        case 2: if (argv[1][0] == '-') {
                    uninst = TRUE;
                    break;
                }
                else {
                    strcpy(ins_dir, argv[1]);
                    uninst = FALSE;
                    break;
                }
                
        default:    kprintf("Usage: setup [dir] | [-u]\n");

                    return 0;
    }

    GetCurrentDirectory(1024, buf);
    GetShortPathName(buf, cur_dir, 1024);
    GetWindowsDirectory(win_dir, 1024);
    GetSystemDirectory(sys_dir, 1024);

    hNewCursor = LoadCursor(NULL, IDC_WAIT);

    EnterDialogBox();

    return 0;
}

// Display the dialog box

int EnterDialogBox()
{    
    int result;

    WNDCLASS wc;
      
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = DefDlgProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = DLGWINDOWEXTRA;
    wc.hInstance = hInst;
    wc.hIcon = LoadIcon(hInst, "MyIcon");
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = COLOR_WINDOW + 1;
    wc.lpszMenuName = NULL;
    wc.lpszClassName = "SetupClass";
    RegisterClass(&wc);

    result = DialogBox(hInst, "SETUP", NULL, MyDlgProc);
    if (result == -1) {
        kprintf("unable to create SETUP dialog\n");
        return -1;
    }

    return 1;
}

    
BOOL APIENTRY HelpDlgProc (HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
    int wmID;
        
    switch (msg) {              /* these values are defined in winuser.h */

        case WM_INITDIALOG:
            hAbout = hDlg;
            return TRUE;

        case WM_CTLCOLORDLG:
            SetBkMode((HDC) wParam, TRANSPARENT);
            SetTextColor((HDC) wParam, RGB(0, 0, 0));
            return (BOOL) GetCurrentObject((HDC) wParam, OBJ_BRUSH);
/*
        case WM_CTLCOLORSCROLLBAR:
            SetBkMode((HDC) wParam, TRANSPARENT);
            SetTextColor((HDC) wParam, RGB(0, 0, 0));
            return (BOOL) GetCurrentObject((HDC) wParam, OBJ_BRUSH);
*/
        case WM_CTLCOLORSTATIC:
            SetBkMode((HDC) wParam, TRANSPARENT);
            SetTextColor((HDC) wParam, RGB(0, 0, 0));
//            if(IDC_GROUPBOX37 == GetDlgCtrlID((HWND)lParam))
//                return (BOOL) GetSysColorBrush(COLOR_3DFACE);
            return (BOOL) GetCurrentObject((HDC) wParam, OBJ_BRUSH);
/*
        case WM_CTLCOLOREDIT:
            SetBkMode((HDC) wParam, TRANSPARENT);
            SetTextColor((HDC) wParam, RGB(0, 0, 0));
            return (BOOL) GetCurrentObject((HDC) wParam, OBJ_BRUSH);

        case WM_CTLCOLORBTN:
            SetBkMode((HDC) wParam, OPAQUE);
            SetTextColor((HDC) wParam, RGB(0, 0, 0));
            return (BOOL) GetSysColorBrush(COLOR_3DFACE);
//            return (BOOL) GetCurrentObject((HDC) wParam, OBJ_BRUSH);
*/
        case WM_DESTROY:
            break;

        case WM_COMMAND:

            wmID = LOWORD(wParam);
  
            switch (wmID) {

                case IDOK:
                case IDCANCEL:
                
                    EndDialog(hDlg, IDOK);
                    hAbout = 0;
                    return TRUE;

            }
            break;
    }
    return FALSE;
}

// Display the Help dialog box

int EnterDialogBoxAbout()
{    
    int result;

    result = DialogBox(hInst, "HELP", NULL, HelpDlgProc);
    if (result == -1) {
        kprintf("unable to create HELP dialog\n");
        return -1;
    }

    return 1;
}
                   
//
// MyDlgProc - all the work is done here
//

BOOL APIENTRY MyDlgProc (HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
    int  wmID, i, incr, index, result, tid;
    char *ptr, *ptr1;
    RECT rc;

    LPCITEMIDLIST pidl;
    BROWSEINFO bi;   
    LPMALLOC pMalloc;
    HWND hTmp;
                
    switch (msg) {

        case WM_INITDIALOG:

            hWnd = hDlg;

            version.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
            GetVersionEx(&version);

            if (version.dwPlatformId == VER_PLATFORM_WIN32_NT)
                platform = 1;

            if (version.dwMajorVersion == 5)
                platform2 = 1;          // Windows 2000

            CenterWindow(hDlg);
            
            hList = GetDlgItem(hDlg, IDC_LISTBOX);
            idList = GetDlgCtrlID(hList);
            
            hFont = CreateFont(12, 8, 0, 0, FW_NORMAL,
                               0, 0, 0, ANSI_CHARSET,
                               OUT_DEFAULT_PRECIS,
                               CLIP_DEFAULT_PRECIS,
                               DEFAULT_QUALITY,
                               FIXED_PITCH,
                               "Courier");
            SendDlgItemMessage(hDlg, idList, WM_SETFONT, (WPARAM) hFont, (LPARAM) TRUE);
            SendDlgItemMessage(hDlg, idList, LB_SETHORIZONTALEXTENT, (WPARAM) 4096, (LPARAM) 0);
            SendMessage(hList, LB_SETHORIZONTALEXTENT, (WPARAM) 800, (LPARAM) 0);

            SendMessage(hList, LB_ADDSTRING, 0, (LPARAM)(LPCSTR) msg1);  
            SendMessage(hList, LB_ADDSTRING, 0, (LPARAM)(LPCSTR) msg2);  
            if (uninst) {
                SendMessage(hList, LB_ADDSTRING, 0, (LPARAM)(LPCSTR) msg5);
                hTmp = GetDlgItem(hDlg, IDC_PUSHBUTTON2);
                EnableWindow(hTmp, FALSE);
                hTmp = GetDlgItem(hDlg, IDC_EDIT1);
                EnableWindow(hTmp, FALSE);
            }
            else 
                SendMessage(hList, LB_ADDSTRING, 0, (LPARAM)(LPCSTR) msg4);
                
            GetClientRect(hDlg, &rc);
            
            incr = 76;
            
            MoveWindow(hList, 0, incr, rc.right, rc.bottom - incr, TRUE);

            SetDlgItemText(hDlg, IDC_EDIT1, ins_dir);
                        
            return TRUE;

        case WM_CTLCOLORDLG:
            SetBkMode((HDC) wParam, TRANSPARENT);
            SetTextColor((HDC) wParam, RGB(0, 0, 0));
            return (BOOL) GetCurrentObject((HDC) wParam, OBJ_BRUSH);
/*
        case WM_CTLCOLORSCROLLBAR:
            SetBkMode((HDC) wParam, TRANSPARENT);
            SetTextColor((HDC) wParam, RGB(0, 0, 0));
            return (BOOL) GetCurrentObject((HDC) wParam, OBJ_BRUSH);
*/
        case WM_CTLCOLORSTATIC:
            SetBkMode((HDC) wParam, TRANSPARENT);
            SetTextColor((HDC) wParam, RGB(0, 0, 0));
//            if(IDC_GROUPBOX37 == GetDlgCtrlID((HWND)lParam))
//                return (BOOL) GetSysColorBrush(COLOR_3DFACE);
            return (BOOL) GetCurrentObject((HDC) wParam, OBJ_BRUSH);
/*
        case WM_CTLCOLOREDIT:
            SetBkMode((HDC) wParam, TRANSPARENT);
            SetTextColor((HDC) wParam, RGB(0, 0, 0));
            return (BOOL) GetCurrentObject((HDC) wParam, OBJ_BRUSH);

        case WM_CTLCOLORBTN:
            SetBkMode((HDC) wParam, OPAQUE);
            SetTextColor((HDC) wParam, RGB(0, 0, 0));
            return (BOOL) GetSysColorBrush(COLOR_3DFACE);
//            return (BOOL) GetCurrentObject((HDC) wParam, OBJ_BRUSH);
*/
        case WM_DESTROY:
            
            goto done;


        case WM_SIZE:
            if (wParam == 10) {
                ShowWindow(hDlg, SW_HIDE);
                hide_flag = 1;
                return TRUE;
            }

            if ((wParam == SIZE_MINIMIZED) && (hide_flag)) {
                ShowWindow(hDlg, SW_HIDE);
                return TRUE;
            }

            incr = 76;
            MoveWindow(hList, 0, incr, LOWORD(lParam), HIWORD(lParam)-incr, TRUE);
            break;
            
        case WM_COMMAND:

            wmID = LOWORD(wParam);

            SetCurrentDirectory(cur_dir);

            switch (wmID) {

                case IDC_PUSHBUTTON2:

                    OleInitialize(NULL);

                    SHGetMalloc(&pMalloc);

                    bi.hwndOwner = hDlg;
                    bi.pidlRoot =  NULL;
                    bi.pszDisplayName = NULL; // ins_dir;
                    bi.lpszTitle = "Please select a destination directory (folder) for the NAT32 files.";
                    bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_USENEWUI;
                    bi.lpfn = BrowseCallbackProc;
                    bi.lParam = 0;
                    bi.iImage = 0;  
            
                    pidl = SHBrowseForFolder(&bi);
                    if (pidl == 0) {
                        OleUninitialize();
                        break;
                    }
                    SHGetPathFromIDList(pidl, ins_dir);
                    pMalloc->lpVtbl->Free(pMalloc,pidl);
                    pMalloc->lpVtbl->Release(pMalloc);
                    OleUninitialize();
                    SetDlgItemText(hDlg, IDC_EDIT1, ins_dir);
                
                    break;
                    
                case IDOK:
                
                if (installed) {
                    if (ndis3pkt_ok && kprintf("Please click OK to run NAT32 now.") == IDOK) {
                        strcat(ins_dir, "\\nat32.exe");
                        exec(ins_dir);
                    }
                    goto done;
                }

                if (completed)
                    goto done;
                    
                // fall through
                
                if (uninst) {
                    if (platform)
                        strcpy(buf, job3);
                    else
                        strcpy(buf, job4);
                    strcat(buf, win_dir);
                    strcat(buf, "\\inf\\nat32e.inf");
                }
                else {
    
                    GetDlgItemText(hDlg, IDC_EDIT1, ins_dir, 512);

                    if (platform)
                        strcpy(buf, job1);
                    else
                        strcpy(buf, job2);
                    strcat(buf, cur_dir);
                    strcat(buf, "\\nat32e.inf");
                    strcpy(tmp, win_dir);
                    strcat(tmp, "\\inf\\nat32e.inf");
                    DeleteFile(tmp);
                    WritePrivateProfileString("Strings", "SOURCE", cur_dir, ".\\nat32e.inf");
                    WritePrivateProfileString("Strings", "DEST", ins_dir, ".\\nat32e.inf");
                }

                hOldCursor = SetCursor(hNewCursor);
                result = execw(buf);
                SetCursor(hOldCursor); 
                done = TRUE;
                
                if (uninst) {
                    int dlen = 1024;
                    GetDesktop(desktop, &dlen);
                    strcat(desktop, "\\NAT32E_RUN.lnk");
                    DeleteFile(desktop);
                    dlen = 1024;
                    GetDesktop(desktop, &dlen);
                    strcat(desktop, "\\NAT32E_CFG.lnk");
                    DeleteFile(desktop);
                }

                if (result) {
                    sprintf(buf, "ERROR: %d Operation aborted.", result);
                    SendMessage(hList, LB_ADDSTRING, 0, (LPARAM)(LPCSTR) buf);
                    installed = TRUE;
                    return TRUE;
                }

                if (uninst == 0)
                    SendMessage(hList, LB_ADDSTRING, 0, (LPARAM)(LPCSTR) "Adapter List:");

                if (platform) {

                    if (CheckNdis3Pkt() == 0) {
                        ndis3pkt_ok = TRUE;
                        if (uninst) {
                            result =  kprintf("Click OK to uninstall the NDIS3PKT Driver with Control Panel Network...\n");
                            if (result != IDCANCEL) {
                                strcpy(buf, "control.exe ");
                                strcat(buf, sys_dir);
                                strcat(buf, "\\ncpa.cpl");
                                hOldCursor = SetCursor(hNewCursor);
                                exec(buf);
                                SetCursor(hOldCursor); 
                            }
                            else
                                goto done;
                        }
                        else {
                            GetConf(buf);
                            ptr = &buf[0];
                    
                            for (i=0; i<20; i++) {
                                ptr1 = strstr(ptr, "\n");
                                if (ptr1) {
                                    *ptr1 = 0;
                                    if (strlen(ptr))
                                        SendMessage(hList, LB_ADDSTRING, 0, (LPARAM)(LPCSTR) ptr);
                                    ptr = ++ptr1;
                                }
                                else
                                    break;
                            }
                        }
                    }
                    else {
                        if (uninst == 0) {
                            SendMessage(hList, LB_ADDSTRING, 0, (LPARAM)(LPCSTR) "NDIS3PKT not installed");
                            Sleep(5000);
                            result =  kprintf("The NDIS3PKT Driver is not installed.\nClick OK to install it now...\n");
                            if (result != IDCANCEL) {
                                strcpy(buf, "control.exe ");
                                strcat(buf, sys_dir);
                                strcat(buf, "\\ncpa.cpl");
                    
                                hOldCursor = SetCursor(hNewCursor);
                                exec(buf);
                                SetCursor(hOldCursor); 

                                if (platform2)
                                    kprintf("The Network and Dial-up Connections window should now be visible.\n\nPlease right-click the Local Area Connection icon, then select:\n\nProperties/Install/Protocol/Add/Have Disk/Browse\n\nand install NDIS3PKT from directory %s\n\nA Windows REBOOT is then required to start the NDIS3PKT driver.", ins_dir);
                                else
                                    kprintf("Control Panel Network should now be running. Please click: \n\nProtocols/Add/Have Disk\n\nThen select directory: %s\n\nWhen NDIS3PKT has been installed, please click OK.", ins_dir);

                            } 
                        }
                    }
                }
                else {

                    if (CheckNdis3Pkt95("NDXPKT") == 1) {
                        ndis3pkt_ok = TRUE;
                        if (uninst) {
                            result =  kprintf("Click OK to uninstall the NDIS3PKT Driver...\n");
                            if (result != IDCANCEL) {
                                strcpy(buf, "control.exe ");
                                strcat(buf, sys_dir);
                                strcat(buf, "\\netcpl.cpl");
                                hOldCursor = SetCursor(hNewCursor);
                                exec(buf);
                                SetCursor(hOldCursor); 
                            }
                            else
                                goto done;
                        }
                        else {
                            GetConf(buf);
                            ptr = &buf[0];
                    
                            for (i=0; i<20; i++) {
                                ptr1 = strstr(ptr, "\n");
                                if (ptr1) {
                                    *ptr1 = 0;
                                    if (strlen(ptr))
                                        SendMessage(hList, LB_ADDSTRING, 0, (LPARAM)(LPCSTR) ptr);
                                    ptr = ++ptr1;
                                }
                                else
                                    break;
                            }
                        }
                    }
                    else {
                        if (uninst == 0) {
                            result =  kprintf("The NDIS3PKT Driver is not installed. Click OK to install it now...\n");
                            if (result != IDCANCEL) {
                                strcpy(buf, "control.exe ");
                                strcat(buf, sys_dir);
                                strcat(buf, "\\netcpl.cpl");
                                hOldCursor = SetCursor(hNewCursor);
                                exec(buf);
                                SetCursor(hOldCursor); 
                                kprintf("Control Panel Network should now be running. Please click: \n\nAdd/Protocol/Add/Have Disk\n\nThen select directory:\n\n%s\n\nWhen NDIS3PKT has been installed, please click OK.", ins_dir);
                            } 
                        }
                    }
                }
                SendMessage(hList, LB_SETTOPINDEX, 100, 0);
                if (uninst) {
                    SendMessage(hList, LB_ADDSTRING, 0, (LPARAM)(LPCSTR) "NAT32 Uninstall completed.");
                    SendMessage(hList, LB_ADDSTRING, 0, (LPARAM)(LPCSTR) "Please click OK to exit.");
                    installed = FALSE;
                    completed = TRUE;
                }
                else {
                    SendMessage(hList, LB_ADDSTRING, 0, (LPARAM)(LPCSTR) "NAT32 Installation completed.");
                    index = SendMessage(hList, LB_ADDSTRING, 0, (LPARAM)(LPCSTR) "Please click OK to finish.");
                    SendMessage(hList, LB_SETCURSEL, (WPARAM) index, (LPARAM) 0);
                    installed = TRUE;
                }
                
                return TRUE;  
                
                case IDCANCEL:
                            

done:
                if (hAbout) {
                    EndDialog(hAbout, IDOK);
                    hAbout = 0;
                }
                EndDialog(hDlg, IDOK);
                hWnd = 0;
                return TRUE;

                case IDC_PUSHBUTTON1:           // help
                    if (hAbout) {
                        EndDialog(hAbout, IDOK);
                        hAbout = 0;
                        return TRUE;
                    }
                    EnterDialogBoxAbout();
                    return TRUE;
                
            }
            break;
    }
    return FALSE;
}

//
// exec - execute an application and don't wait for completion
//
int exec(char *cmdline)
{
    BOOL result;
    STARTUPINFO si;
    PROCESS_INFORMATION pi;    

    GetStartupInfo(&si);
    ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
        
    result = CreateProcess(
    (LPCTSTR)               NULL,
    (LPTSTR)                cmdline,
    (LPSECURITY_ATTRIBUTES) NULL,
    (LPSECURITY_ATTRIBUTES) NULL,
    (BOOL)                  FALSE,
    (DWORD)                 CREATE_NEW_CONSOLE | HIGH_PRIORITY_CLASS,
    (LPVOID)                NULL,
    (LPCTSTR)               cur_dir,
    (LPSTARTUPINFO)         &si,
    (LPPROCESS_INFORMATION) &pi);
    
    if (result)
         return 0;

    return GetLastError();
}
//
// execw - execute an application and wait for completion 
//
int execw(char *cmdline)
{
    BOOL result;
    STARTUPINFO si;
    PROCESS_INFORMATION pi;    

    GetStartupInfo(&si);
    ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
        
    result = CreateProcess(
    (LPCTSTR)               NULL,
    (LPTSTR)                cmdline,
    (LPSECURITY_ATTRIBUTES) NULL,
    (LPSECURITY_ATTRIBUTES) NULL,
    (BOOL)                  TRUE,
    (DWORD)                 CREATE_NEW_CONSOLE | HIGH_PRIORITY_CLASS,
    (LPVOID)                NULL,
    (LPCTSTR)               cur_dir,
    (LPSTARTUPINFO)         &si,
    (LPPROCESS_INFORMATION) &pi);
    
    if (result) {
        WaitForSingleObject(pi.hProcess, INFINITE);
        return 0;
    }
    else
        return GetLastError();
}

BOOL CenterWindow(HWND hWin) 
{
    int result;
    HWND hDesktop;

    RECT rc;
    RECT rcd;
        
    hDesktop = GetDesktopWindow();
    result = GetWindowRect(hWin, &rc);

    if (result)
        result = GetWindowRect(hDesktop, &rcd);
    
    if (result == 0)
        return -1;
        
    SetWindowPos(hWin, HWND_TOP,
                 rcd.right/2 - (rc.right - rc.left)/2,
                 rcd.bottom/2 - (rc.bottom - rc.top)/2,
                 0, 0,
                 SWP_NOSIZE);
    return 0;
}

//
// GetConf - return a list of bound TCP/IP protocols
//

GetConf(char *buf)
{
    char rbuf[4096];
    int  rbuf_len = 4096;

    char *ptr = rbuf;
    
    buf[0] = 0;
    
    if (platform) {
        GetTcpipLinkageNT(rbuf, &rbuf_len);
        while (strlen(ptr)) {
            strcat(buf, ptr);
            strcat(buf, "\n");
            ptr+= strlen(ptr) + 1;
        }
        return 0;
    }
    GetNamesAndNetKeys(rbuf);
    strcat(buf, rbuf);
    strcat(buf, "\n");    
    return 0;
}

//
// GetNamesAndNetKeys - return a complete list of Adapter descriptive names, 
//                      Net keys and Binding keys in result buffer rbuf
//
int GetNamesAndNetKeys(char *rbuf) 
{
    char    buf[1024];
    int     i, j, result;
    HKEY    EnumKey;
    LONG    Status;
    DWORD   RegType;

    rbuf[0] = 0;
    i = 0;
                         
    Status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
                          TEXT("Enum"),
                          0,
                          KEY_READ,
                          &EnumKey);

    if (Status == ERROR_SUCCESS) {
        while (TRUE) {
            buf[0] = 0;
            Enum95(buf, i++);       // get the name of the next Enum key
            if (strlen(buf) == 0)
                break;              // done
                 
            FindNet95(EnumKey, buf, rbuf);  // cat name and net to rbuf
        }
        RegCloseKey(EnumKey);
    }
    return 0;
}
//
// FindNet95 - recursively search HKLM\Enum\pKeyName for a Network Adapter
//             name and its Net Key. 
//             Concatenates its findings to rbuf as a line of format:  
//             Ether 16 Example\Net\000x
//
DWORD FindNet95(HKEY hStartKey , char *pKeyName, char *rbuf) 
{

#define MAX_KEY_LENGTH 1024

    DWORD   dwRtn, dwSubKeyLength;
    TCHAR   szSubKey[MAX_KEY_LENGTH];
    HKEY    hKey;
    HKEY    BindingsKey;
    LONG    Status;
    DWORD   RegType;
    DWORD   tlen = 128;
    char    tmp[128];
                        
    // do not allow NULL or empty key name
    if (pKeyName && strlen(pKeyName)) {
        if( (dwRtn=RegOpenKeyEx(hStartKey,
                                pKeyName,
                                0, 
                                KEY_READ, 
                                &hKey )) == ERROR_SUCCESS)
        {
            int i = 0;
            Status = RegQueryValueEx(hKey,
                                     TEXT("Class"),
                                     NULL,
                                     &RegType,
                                     (LPBYTE)tmp,
                                     &tlen);
            if (Status == ERROR_SUCCESS) {
                if (strcmp(tmp, "Net") == 0) {
                    tlen = 128;
                    Status = RegQueryValueEx(hKey,
                                             TEXT("DeviceDesc"),
                                             NULL,
                                             &RegType,
                                             (LPBYTE)tmp,
                                             &tlen);
                    if (Status == ERROR_SUCCESS) {
                        strcat(rbuf, tmp);
                        strcat(rbuf, "\\");
                        tlen = 128;

                        Status = RegQueryValueEx(hKey,
                                                 TEXT("Driver"),
                                                 NULL,
                                                 &RegType,
                                                 (LPBYTE)tmp,
                                                 &tlen);
                        if (Status == ERROR_SUCCESS) {
                            strcat(rbuf, tmp);
                            tmp[0] = 0;
                            tlen = 128;
                            Status = RegOpenKeyEx(hKey,
                                                  "Bindings",
                                                  0, 
                                                  KEY_READ, 
                                                  &BindingsKey);
                            if (Status == ERROR_SUCCESS) {
                                int j = 0;
                                while (ERROR_NO_MORE_ITEMS != 
                                       RegEnumValue(BindingsKey,
                                                    j++,
                                                    tmp,
                                                    &tlen,
                                                    0,
                                                    0,
                                                    0,          
                                                    0)) {
                                    strcat(rbuf, "[");
                                    strcat(rbuf, tmp);
                                    strcat(rbuf, "]");
                                    tlen = 128;
                                }
                                if (j == 1)
                                    strcat(rbuf, "[empty]");
                                RegCloseKey(BindingsKey);
                            }
                            strcat(rbuf, "\n");
                        }
                    }
                }
            }                        
                                    
            while (dwRtn == ERROR_SUCCESS) {
                dwSubKeyLength = MAX_KEY_LENGTH;
                dwRtn=RegEnumKeyEx(
                      hKey,
                      i++,
                      szSubKey,
                      &dwSubKeyLength,
                      NULL,
                      NULL,
                      NULL,
                      NULL);

                if (dwRtn == ERROR_NO_MORE_ITEMS) {
                    dwRtn = ERROR_SUCCESS;
                    break;
                }
                else if(dwRtn == ERROR_SUCCESS) {
                        dwRtn=FindNet95(hKey, szSubKey, rbuf);
                    }
             }
             RegCloseKey(hKey);
             // Do not save return code because error
             // has already occurred
         }
    }
    else
        dwRtn = ERROR_BADKEY;
    return dwRtn;
}

//
// Enum95 - find a key in HKLM\Enum
//

int Enum95(char *buf, int i)
{

    HKEY    EnumKey;
    
    LONG    Status;

    char    tmp[128];
    DWORD   tlen = 128;

    Status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
                          TEXT("Enum"),
                          0,
                          KEY_READ,
                          &EnumKey);

    if (Status == ERROR_SUCCESS) {

        if (ERROR_NO_MORE_ITEMS != RegEnumKeyEx(EnumKey,
                                                i,
                                                tmp,
                                                &tlen,
                                                0,
                                                0,
                                                0,
                                                0)) {
            strcat(buf, tmp);
        }
        RegCloseKey(EnumKey);
    }
    return Status;
}

//
// CheckNdis3Pkt95 - return OK if named key (NDIS3PKT or NDXPKT) is found
//

int CheckNdis3Pkt95(char *name) 
{
    HKEY    EnumKey;
    HKEY    NetworkKey;
    HKEY    TargetKey;
    HKEY    UnitKey;
    LONG    Status;
    DWORD   RegType;

    Status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
                          TEXT("Enum"),
                          0,
                          KEY_READ,
                          &EnumKey);

    if (Status == ERROR_SUCCESS) {

        Status = RegOpenKeyEx(EnumKey,
                              TEXT("Network"),
                              0,
                              KEY_READ,
                              &NetworkKey);

        if (Status == ERROR_SUCCESS) {

            Status = RegOpenKeyEx(NetworkKey,
                                  name,
                                  0,
                                  KEY_READ,
                                  &TargetKey);

            if (Status == ERROR_SUCCESS) {
                Status = RegOpenKeyEx(TargetKey,
                                      TEXT("0000"),     // first Unit
                                      0,
                                      KEY_READ,
                                      &UnitKey);
                if (Status == ERROR_SUCCESS)
                    RegCloseKey(UnitKey);
                RegCloseKey(TargetKey);
            }
            RegCloseKey(NetworkKey);
        }
        RegCloseKey(EnumKey);
    }
    if (Status == ERROR_SUCCESS)
        return 1;

    return 0;
}

//
// CheckNdis3Pkt - is NDIS3PKT installed?
//

int CheckNdis3Pkt()
{

    HKEY    SystemKey;
    HKEY    ControlSetKey;
    HKEY    ServicesKey;
    HKEY    Ndis3PktKey;
    HKEY    NameKey;
    
    LONG    Status;

    DWORD   RegType;
    char    buf[128];
    int     len=128;
    
    Status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
                          TEXT("SYSTEM"),
                          0,
                          KEY_READ,
                          &SystemKey);

    if (Status == ERROR_SUCCESS) {

        Status = RegOpenKeyEx(SystemKey,
                              TEXT("CurrentControlSet"),
                              0,
                              KEY_READ,
                              &ControlSetKey);

        if (Status == ERROR_SUCCESS) {

            Status = RegOpenKeyEx(ControlSetKey,
                                  TEXT("Services"),
                                  0,
                                  KEY_READ,
                                  &ServicesKey);

            if (Status == ERROR_SUCCESS) {

                Status = RegOpenKeyEx(ServicesKey,
                                      TEXT("Ndis3pkt"),
                                      0,
                                      KEY_READ,
                                      &Ndis3PktKey);

                if (Status == ERROR_SUCCESS) {

                    Status = RegQueryValueEx(Ndis3PktKey,
                                             TEXT("DisplayName"),
                                             NULL,
                                             &RegType,
                                             (LPBYTE)buf,
                                             &len);
 
                    RegCloseKey(Ndis3PktKey);
                }
                RegCloseKey(ServicesKey);
            }
            RegCloseKey(ControlSetKey);
        }
        RegCloseKey(SystemKey);
    }
    return Status;
}

//
// GetTcpipLinkageNT - return a list of all MSTCP bindings
//

int GetTcpipLinkageNT(char *buf, int *plen)
{

    HKEY    SystemKey;
    HKEY    ControlSetKey;
    HKEY    ServicesKey;
    HKEY    TcpipKey;
    HKEY    LinkageKey;
        
    LONG    Status;

    DWORD   RegType;
    
    buf[0] = 0;
    
    Status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
                          TEXT("SYSTEM"),
                          0,
                          KEY_READ,
                          &SystemKey);

    if (Status == ERROR_SUCCESS) {

        Status = RegOpenKeyEx(SystemKey,
                              TEXT("CurrentControlSet"),
                              0,
                              KEY_READ,
                              &ControlSetKey);

        if (Status == ERROR_SUCCESS) {

            Status = RegOpenKeyEx(ControlSetKey,
                                  TEXT("Services"),
                                  0,
                                  KEY_READ,
                                  &ServicesKey);

            if (Status == ERROR_SUCCESS) {

                Status = RegOpenKeyEx(ServicesKey,
                                      TEXT("Tcpip"),
                                      0,
                                      KEY_READ,
                                      &TcpipKey);

                if (Status == ERROR_SUCCESS) {

                    Status = RegOpenKeyEx(TcpipKey,
                                          TEXT("Linkage"),
                                          0,
                                          KEY_READ,
                                          &LinkageKey);

                    if (Status == ERROR_SUCCESS) {

                        Status = RegQueryValueEx(LinkageKey,
                                             TEXT("Bind"),
                                             NULL,
                                             &RegType,
                                             (LPBYTE)buf,
                                             plen);

                        RegCloseKey(LinkageKey);
                    }
                    RegCloseKey(TcpipKey);
                }
                RegCloseKey(ServicesKey);
            }
            RegCloseKey(ControlSetKey);
        }
        RegCloseKey(SystemKey);
    }
    return Status;
}

//
// wait - wait for completion
//

int wait()
{
    while (!done) {
        FlashWindow(hWnd, TRUE);
        Sleep(1000);
    }
    FlashWindow(hWnd, FALSE);
    return 0;    
}

// get the current desktop from the registry

int GetDesktop(char *buf, int *pblen)
{

    HKEY    SoftwareKey;
    HKEY    MicrosoftKey;
    HKEY    WindowsKey;
    HKEY    CurrentVersionKey;
    HKEY    ExplorerKey;
    HKEY    ShellFoldersKey;
    
    LONG    Status;

    DWORD   RegType;

    Status = RegOpenKeyEx(HKEY_CURRENT_USER,
                          TEXT("Software"),
                          0,
                          KEY_READ,
                          &SoftwareKey);

    if (Status == ERROR_SUCCESS) {

        Status = RegOpenKeyEx(SoftwareKey,
                              TEXT("Microsoft"),
                              0,
                              KEY_READ,
                              &MicrosoftKey);

        if (Status == ERROR_SUCCESS) {

            Status = RegOpenKeyEx(MicrosoftKey,
                                  TEXT("Windows"),
                                  0,
                                  KEY_READ,
                                  &WindowsKey);

            if (Status == ERROR_SUCCESS) {

                Status = RegOpenKeyEx(WindowsKey,
                                      TEXT("CurrentVersion"),
                                      0,
                                      KEY_READ,
                                      &CurrentVersionKey);

                if (Status == ERROR_SUCCESS) {

                    Status = RegOpenKeyEx(CurrentVersionKey,
                                          TEXT("Explorer"),
                                          0,
                                          KEY_READ,
                                          &ExplorerKey);

                    if (Status == ERROR_SUCCESS) {

                        Status = RegOpenKeyEx(ExplorerKey,
                                              TEXT("Shell Folders"),
                                              0,
                                              KEY_READ,
                                              &ShellFoldersKey);

                        if (Status == ERROR_SUCCESS) {

                            Status = RegQueryValueEx(ShellFoldersKey,
                                                     TEXT("Desktop"),
                                                     NULL,
                                                     &RegType,
                                                     (LPBYTE)buf,
                                                     (LPDWORD)pblen);

                            RegCloseKey(ShellFoldersKey);
                        }
                        RegCloseKey(ExplorerKey);
                    }
                    RegCloseKey(CurrentVersionKey);
                }
                RegCloseKey(WindowsKey);
            }
            RegCloseKey(MicrosoftKey);
        }
        RegCloseKey(SoftwareKey);
    }
    return Status;
}


