/*++

    Copyright (c) 1994  Microsoft Corporation

Module Name:

    MakeFLOP.C

Abstract:

    Boot Floppy disk creation setup dialog

Author:

    Bob Watson (a-robw)

Revision History:

    17 Feb 94    Written

--*/
//
//  Windows Include Files
//

#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>
#include <tchar.h>      // unicode macros
//
//  app include files
//
#include "otnboot.h"
#include "otnbtdlg.h"

// local windows message

#define     NCDU_START_FILE_COPY    (WM_USER +1)

//
//  Module Static Data
//
static  BOOL    bCopying;    // TRUE when copying files, FALSE to abort

static
BOOL
IsZeroIpAddr (
    IN  PUSHORT pwIpVal
)
/*++

Routine Description:

    evaluates an IP address array structure to determine if it's all
        zeroes

Arguments:

    IN  PUSHORT pwIpVal
        pointer to an IP address array of integers

Return Value:

    TRUE if all 4 elements in the array are 0, otherwise
    FALSE

--*/
{
    PUSHORT pwTest;
    int     nElem;

    pwTest = pwIpVal;
    nElem = 0;
    while (nElem < 4) {
        if (*pwTest == 0) {
            pwTest++;
            nElem++;
        } else {
            return FALSE;
        }
    }
    return TRUE;
}

static
LPCTSTR
GetDirPathFromUnc (
    IN  LPCTSTR  szPath
)
/*++

Routine Description:

    Parses the Directories from a UNC path specification, removing the
        Server and share point.

Arguments:

    IN LPCTSTR   szPath
        pointer to a zero terminated UNC path specification.

Return Value:

    Pointer to somewhere in the string passed in the argument list where
        the directory path begins or a pointer to an empty string if
        the path specified contains only a server and sharepoint.

--*/
{
    int nSlashCount = 0;

    LPTSTR  szPathPtr;

    szPathPtr = (LPTSTR)szPath;

    if (IsUncPath(szPath)) {
        while (szPathPtr != 0) {
            if (*szPathPtr == cBackslash) nSlashCount++;
            ++szPathPtr;
            if (nSlashCount == 4) {
                break;  // exit loop
            }
        }
    }

    if (nSlashCount != 4) {
        return cszEmptyString;
    } else {
        return szPathPtr;
    }
}

static
BOOL
GetServerAndSharepointFromUnc (
    IN  LPCTSTR  szPath,
    OUT LPTSTR  szServer
)
/*++

Routine Description:

    copies only the server and share point to the buffer provided
        by the caller.

Arguments:

    IN  LPCTSTR  szPath
        UNC path to parse

    OUT LPCTSTR  szServer
        buffer provided to receive the Server and sharepoint. The buffer
        is assumed to be large enough to recieve the data.

Return Value:

    TRUE    if successful
    FALSE   if error

--*/
{
    int nSlashCount = 0;

    LPTSTR  szPathPtr;
    LPTSTR  szServPtr;

    szPathPtr = (LPTSTR)szPath;
    szServPtr = szServer;

    if (IsUncPath(szPath)) {
        while (szPathPtr != 0) {
            if (*szPathPtr == cBackslash) nSlashCount++;
            if (nSlashCount < 4) {
                *szServPtr++ = *szPathPtr++;
            } else {
                break;  // exit loop
            }
        }
    }

    *szServPtr = 0; // terminate server name

    if (szServPtr == szServer) {
        return FALSE;
    } else {
        return TRUE;
    }
}

static
DWORD
UpdatePercentComplete (
    IN  HWND    hwndDlg,
    IN  DWORD   dwDone,
    IN  DWORD   dwTotal
)
/*++

Routine Description:

    Update's the percent complete text in the dialog box using the
        information from the argument list.

Arguments:

    IN  HWND    hwndDlg
        Handle to the dialog box window

    IN  DWORD   dwDone
        Units completed  (Must be less than 42,949,671)

    IN  DWORD   dwTotal
        Total Units  (must be less than 4,394,967,296)

Return Value:

    Percent completed.

--*/
{
    DWORD   dwPercent = 0;
    LPTSTR  szOutBuff;

    szOutBuff = (LPTSTR)GlobalAlloc(GPTR, MAX_PATH_BYTES);

    if (szOutBuff != NULL) {
        dwPercent = ((dwDone * 100) + 50) / dwTotal;
        if (dwPercent > 100) dwPercent = 100;
        _stprintf (szOutBuff,
            GetStringResource (FMT_PERCENT_COMPLETE), dwPercent);
        SetDlgItemText (hwndDlg, NCDU_PERCENT_COMPLETE, szOutBuff);
        FREE_IF_ALLOC (szOutBuff);
    }

    return dwPercent;
}

static
BOOL
IsDestBootableDosFloppy (
)
/*++

Routine Description:

    Checks device in boot file path (from global structure) to see any
        of the "signature" boot files are present

Arguments:

    None

Return Value:

    TRUE if any of the boot files were found on the poot file path drive
    FALSE if not

--*/
{
    LPTSTR  szTestFileName;
    LPTSTR  *pszThisFile;
    LPTSTR  szNameStart;
    BOOL    bReturn = FALSE;

    szTestFileName = (LPTSTR)GlobalAlloc (GPTR, MAX_PATH_BYTES);

    if (szTestFileName == NULL) return FALSE;

    if (!IsUncPath(pAppInfo->szBootFilesPath)) {
        lstrcpy (szTestFileName, pAppInfo->szBootFilesPath);
        if (szTestFileName[lstrlen(szTestFileName)-1] == cBackslash) lstrcat(szTestFileName, cszBackslash);
        szNameStart = &szTestFileName[lstrlen(szTestFileName)];
        // go through list of "test files" and see if any are present
        for (pszThisFile = (LPTSTR *)&szBootIdFiles[0];
            *pszThisFile != NULL;
            pszThisFile++) {
            lstrcpy (szNameStart, *pszThisFile);
            if (FileExists(szTestFileName)) bReturn = TRUE;
        }
        // if here then none of the files could be found.
    } else {
        // if a UNC name return false
    }

    FREE_IF_ALLOC (szTestFileName);
    return bReturn;
}

static
BOOL
WriteMszToFile (
    IN  HWND    hwndDlg,
    IN  LPCTSTR  mszList,
    IN  LPCTSTR  szFileName,
    IN  DWORD   dwCreateFlags
)
/*++

Routine Description:

    Function to output each entry in the "list" as a record in the "file"
        Entries that start with a left "square bracket" ([) will be
        prefixed with a new line. (for INF file formatting);

    NOTE: this function outputs ANSI characters to an ANSI file regardless
        if the _UNICODE flags are set or not.

Arguments:

    IN  HWND    hwndDlg
        Handle to dialog box window

    IN  LPCTSTR  mszList
        Multi SZ list to write to the files

    IN  LPCTSTR  szFileName
        file name & path to write data to

    IN  DWORD   dwCreateFlags
        flags used by CreateFile function to open file.

Return Value:

    TRUE    no errors
    FALSE   error (use GetLastError() to get more error data)

--*/
{
    HANDLE  hFile;
    LPTSTR  szEntry;
    DWORD   dwBytes;
    LPSTR   szAnsiBuffer;
    BOOL    bReturn;

    MSG     msg;

#if _UNICODE
    szAnsiBuffer = (LPSTR)GlobalAlloc(GPTR, SMALL_BUFFER_SIZE);

    if (szAnsiBuffer == NULL) return FALSE;

    *(PDWORD)szAnsiBuffer = 0L;
#endif

    hFile = CreateFile (
        szFileName,
        GENERIC_WRITE,
        (FILE_SHARE_READ | FILE_SHARE_WRITE),
        NULL,
        dwCreateFlags,
        FILE_ATTRIBUTE_NORMAL,
        NULL);

    if (hFile != INVALID_HANDLE_VALUE) {
        for (szEntry = (LPTSTR)mszList;
            *szEntry != 0;
            szEntry += lstrlen(szEntry) + 1) {
#if _UNICODE
            // convert output buffer to ANSI
            wcstombs (szAnsiBuffer, szEntry, SMALL_BUFFER_SIZE);
#else
            // copy ansi data to output buffer
            szAnsiBuffer = szEntry;
#endif
            // output to dialog box
            SetDlgItemText (hwndDlg, NCDU_FROM_PATH,
                GetStringResource (FMT_INTERNAL_BUFFER));
            SetDlgItemText (hwndDlg, NCDU_TO_PATH, _tcslwr((LPTSTR)szFileName));

            if (*szAnsiBuffer == '[') {
                WriteFile (hFile, "\r\n", 2, &dwBytes, NULL);
            }
            WriteFile (hFile, szAnsiBuffer, strlen(szAnsiBuffer),
                &dwBytes, NULL);
            WriteFile (hFile, "\r\n", 2, &dwBytes, NULL);

            // check for messages

            while (PeekMessage (&msg, 0, 0, 0, PM_REMOVE)) {
                TranslateMessage (&msg);
                DispatchMessage (&msg);
            }
        }
        CloseHandle (hFile);
        bReturn = TRUE;
    } else {
        bReturn = FALSE;
    }

#if _UNICODE
    FREE_IF_ALLOC(szAnsiBuffer);
#endif

    return bReturn;
}

static
BOOL
LoadProtocolIni (
    OUT LPTSTR  mszProtocolIni,
    OUT LPTSTR  mszNetFileList,
    OUT PDWORD  pdwNetFileCount
)
/*++

Routine Description:

    Creates the Protocol.Ini file using information from the user specified
        configuration

Arguments:

    OUT LPTSTR  mszProtocolIni
        buffer to receive the file data

    OUT LPTSTR  mszNetFileList
        buffer to recieve the list of files to copy as determined by
        scanning the INF based on the selected protocol & driver info.

    OUT PDWORD  pdwNetFileCount
        pointer to DWORD variable used to maintain a running total count of
        the number of files to copy for the % done calculation.

Return Value:

    TRUE if Protocol.INI file contents were generated
    FALSE if an error occured.

--*/
{
    LPTSTR  szThisString;
    LPTSTR  szTemp;
    LPTSTR  szTemp2;
    LPTSTR  szNifKey;
    LPTSTR  szSectionBuffer;
    LPCTSTR  szDefaultValue = cszEmptyString;
    BOOL    bTcp;   // TRUE if protocol is TCP
    BOOL    bIpx;   // TRUE if protocol is IPX

    szSectionBuffer = (LPTSTR)GlobalAlloc(GPTR, SMALL_BUFFER_SIZE * sizeof(TCHAR));
    szTemp = (LPTSTR)GlobalAlloc (GPTR, MAX_PATH_BYTES);
    szTemp2 = (LPTSTR)GlobalAlloc (GPTR, MAX_PATH_BYTES);
    szNifKey = (LPTSTR)GlobalAlloc (GPTR, MAX_PATH_BYTES);

    if ((szSectionBuffer == NULL) ||
        (szTemp == NULL) ||
        (szTemp2 == NULL) ||
        (szNifKey == NULL)) {
        return FALSE;
    }

    //
    //  TCP/IP & IPX are special cases, so detect them here
    //
    if (_tcsnicmp(pAppInfo->piFloppyProtocol.szKey, cszTcpKey, lstrlen(cszTcpKey)) == 0) {
        bTcp = TRUE;
        bIpx = FALSE;
    } else if (_tcsnicmp(pAppInfo->piFloppyProtocol.szName, cszIpxKey, lstrlen(cszTcpKey)) == 0) {
        bTcp = FALSE;
        bIpx = TRUE;
    } else { // it's neither
        bTcp = FALSE;
        bIpx = FALSE;
    }

    if (szSectionBuffer != NULL) {
        *(PDWORD)szSectionBuffer = 0;
    } else {
        return FALSE;
    }
    //fill in text of protocol ini file
    //
    //  add common files to Net dir list
    //
    lstrcpy (szTemp, pAppInfo->szDistPath);
    if (szTemp[lstrlen(szTemp)-1] != cBackslash) lstrcat (szTemp, cszBackslash);
    lstrcat (szTemp, cszOtnBootInf);

    GetPrivateProfileSection (cszOTNCommonFiles,
        szSectionBuffer, SMALL_BUFFER_SIZE, szTemp);

    for (szThisString = szSectionBuffer;
        *szThisString != 0;
        szThisString += (lstrlen(szThisString)+1)) {
        AddStringToMultiSz (mszNetFileList, GetKeyFromEntry (szThisString));
        *pdwNetFileCount += 1;
    }

    //
    //  add in protocol specific files here
    //

    GetPrivateProfileSection (pAppInfo->piFloppyProtocol.szKey,
        szSectionBuffer, SMALL_BUFFER_SIZE, szTemp);

    for (szThisString = szSectionBuffer;
        *szThisString != 0;
        szThisString += (lstrlen(szThisString)+1)) {
        AddStringToMultiSz (mszNetFileList, GetKeyFromEntry (szThisString));
        *pdwNetFileCount += 1;
    }

    // [network.setup] section

    AddStringToMultiSz (mszProtocolIni, cszNetworkSetup);
    AddStringToMultiSz (mszProtocolIni, cszInfVersion);

    // examine & log netcard info
    lstrcpy (szTemp2, pAppInfo->niNetCard.szInfKey);
    _tcsupr (szTemp2);

    _stprintf (szTemp, fmtNetcardDefEntry,
        pAppInfo->niNetCard.szInfKey,
        szTemp2);
    AddStringToMultiSz (mszProtocolIni, szTemp);

    // load transport information
    if (!bTcp) {
        // load the ndishlp transport
        AddStringToMultiSz (mszProtocolIni, fmtTransportDefEntry);
    }

    // load transport from listbox
    lstrcpy (szTemp2, pAppInfo->piFloppyProtocol.szKey);
    _tcsupr (szTemp2);
    _stprintf (szTemp, fmtTransportItem,
        pAppInfo->piFloppyProtocol.szKey,
        szTemp2);
    AddStringToMultiSz (mszProtocolIni, szTemp);

    // format the bindings
    _stprintf (szTemp, fmtLana0Entry,
        pAppInfo->niNetCard.szInfKey,
        pAppInfo->piFloppyProtocol.szKey);
    AddStringToMultiSz (mszProtocolIni, szTemp);
    if (!bTcp) {
        _stprintf (szTemp, fmtLana1Entry,
            pAppInfo->niNetCard.szInfKey);
        AddStringToMultiSz (mszProtocolIni, szTemp);
    }

    // format the netcard settings to the default values
    // add the net card driver file to the list of NetDir files
    QuietGetPrivateProfileString (pAppInfo->niNetCard.szDeviceKey,
        cszNdis2, cszEmptyString,
        szTemp2, MAX_PATH,
        pAppInfo->niNetCard.szInf);
    // save filename
    lstrcpy (pAppInfo->niNetCard.szDriverFile, GetFileNameFromEntry(szTemp2));
    AddStringToMultiSz (mszNetFileList, pAppInfo->niNetCard.szDriverFile);
    *pdwNetFileCount += 1;

    // output section with default values

    _stprintf (szTemp2, fmtIniSection, pAppInfo->niNetCard.szInfKey);
    AddStringToMultiSz (mszProtocolIni,  szTemp2);

    // lookup parameters
    GetPrivateProfileSection (pAppInfo->niNetCard.szNifKey,
        szSectionBuffer, MEDIUM_BUFFER_SIZE,
        pAppInfo->niNetCard.szInf);

    // process section. Format of each line is:
    //  entry=IniName,DescriptionString,Type,OptionRange,Default,?
    //  for each entry, I'll print:
    //      IniName=Default
    //  in the protocol.ini file
    //
    for (szThisString = szSectionBuffer;
        *szThisString != 0;
        szThisString += lstrlen(szThisString) +1) {
        if (_tcsnicmp(szThisString, cszDrivername, 10) == 0) {
            // drivername entry is a special case
            AddStringToMultiSz (mszProtocolIni, szThisString);
        } else {
            szDefaultValue = GetItemFromEntry(szThisString, 5);
            _stprintf (szTemp, fmtCmntIniKeyEntry,
                GetItemFromEntry(szThisString, 1),
                szDefaultValue);
            AddStringToMultiSz (mszProtocolIni, szTemp);
        }
    }
    //
    //  add protman files to the list
    //
    QuietGetPrivateProfileString (cszProtmanInstall,
        cszNetdir, cszEmptyString,
        szSectionBuffer, MEDIUM_BUFFER_SIZE,
        pAppInfo->niNetCard.szInf);

    // add all files to the list

    szThisString = _tcstok (szSectionBuffer, cszComma);
    while (szThisString != NULL ) {
        AddStringToMultiSz (mszNetFileList, GetFileNameFromEntry (szThisString));
        *pdwNetFileCount += 1;
        szThisString = _tcstok (NULL, cszComma);
    }

    // do protman entry

    AddStringToMultiSz (mszProtocolIni, fmtProtmanSection);
    lstrcpy (szNifKey, cszProtman);

    GetPrivateProfileSection (szNifKey,
        szSectionBuffer, MEDIUM_BUFFER_SIZE,
        pAppInfo->niNetCard.szInf);

    // process section. Format of each line is:
    //  entry=IniName,DescriptionString,Type,Default
    //  for each entry, I'll print:
    //      IniName=Default
    //  in the protocol.ini file
    //
    for (szThisString = szSectionBuffer;
        *szThisString != 0;
        szThisString += lstrlen(szThisString) +1) {
        if (_tcsnicmp(szThisString, cszDrivername, lstrlen(cszDrivername)) == 0) {
            // drivername entry is a special case
            AddStringToMultiSz (mszProtocolIni, szThisString);
        } else {
            szDefaultValue = GetItemFromEntry(szThisString, 4);
            if (lstrlen(szDefaultValue) > 0) {
                _stprintf (szTemp, fmtIniKeyEntry,
                    GetItemFromEntry(szThisString, 1),
                    szDefaultValue);
                AddStringToMultiSz (mszProtocolIni, szTemp);
            }
        }
    }

    if (!bTcp) {
        // do NdisHlp section

        AddStringToMultiSz (mszProtocolIni, cszMsNdisHlp);
        lstrcpy (szNifKey, cszMsNdisHlpXif);

        GetPrivateProfileSection (szNifKey,
            szSectionBuffer, MEDIUM_BUFFER_SIZE,
            pAppInfo->niNetCard.szInf);

        // process section. Format of each line is:
        //  drivername=name
        //
        for (szThisString = szSectionBuffer;
            *szThisString != 0;
            szThisString += lstrlen(szThisString) +1) {
            if (_tcsnicmp(szThisString, cszDrivername, lstrlen(cszDrivername)) == 0) {
                // drivername entry is a special case
                AddStringToMultiSz (mszProtocolIni, szThisString);
            } else {
                _stprintf (szTemp, fmtIniKeyEntry,
                    GetKeyFromEntry(szThisString),
                    GetItemFromEntry(szThisString, 1));
                AddStringToMultiSz (mszProtocolIni, szTemp);
            }
        }
        // do bindings

        _stprintf (szTemp, fmtBindingsEntry, pAppInfo->niNetCard.szInfKey);
        AddStringToMultiSz (mszProtocolIni, szTemp);
    }

    // do Protocol configuration

    _stprintf (szTemp2, fmtIniSection, pAppInfo->piFloppyProtocol.szKey);
    AddStringToMultiSz (mszProtocolIni, szTemp2);
    _stprintf (szNifKey, fmtXifEntry, pAppInfo->piFloppyProtocol.szKey);

    if (bTcp) {
        // format the TCP/IP protocol section here using information
        // from the previous dialog boxes
        AddStringToMultiSz (mszProtocolIni, fmtNBSessions);
        if (IsZeroIpAddr (&pAppInfo->tiTcpIpInfo.DefaultGateway[0])) {
            _stprintf (szTemp, fmtEmptyParam, cszDefaultGateway);
        } else {
            _stprintf (szTemp, fmtIpParam, cszDefaultGateway,
                pAppInfo->tiTcpIpInfo.DefaultGateway[0],
                pAppInfo->tiTcpIpInfo.DefaultGateway[1],
                pAppInfo->tiTcpIpInfo.DefaultGateway[2],
                pAppInfo->tiTcpIpInfo.DefaultGateway[3]);
        }
        AddStringToMultiSz (mszProtocolIni, szTemp);

        if (IsZeroIpAddr (&pAppInfo->tiTcpIpInfo.SubNetMask[0])) {
            _stprintf (szTemp, fmtEmptyParam, cszSubNetMask);
        } else {
            _stprintf (szTemp, fmtIpParam, cszSubNetMask,
                pAppInfo->tiTcpIpInfo.SubNetMask[0],
                pAppInfo->tiTcpIpInfo.SubNetMask[1],
                pAppInfo->tiTcpIpInfo.SubNetMask[2],
                pAppInfo->tiTcpIpInfo.SubNetMask[3]);
        }
        AddStringToMultiSz (mszProtocolIni, szTemp);

        if (IsZeroIpAddr (&pAppInfo->tiTcpIpInfo.IpAddr[0])) {
            _stprintf (szTemp, fmtEmptyParam, cszIPAddress);
        } else {
            _stprintf (szTemp, fmtIpParam, cszIPAddress,
                pAppInfo->tiTcpIpInfo.IpAddr[0],
                pAppInfo->tiTcpIpInfo.IpAddr[1],
                pAppInfo->tiTcpIpInfo.IpAddr[2],
                pAppInfo->tiTcpIpInfo.IpAddr[3]);
        }
        AddStringToMultiSz (mszProtocolIni, szTemp);

        _stprintf (szTemp, fmtIniKeyEntry,
            cszDisableDHCP,
            ((pAppInfo->bUseDhcp) ? csz0 : csz1));
        AddStringToMultiSz (mszProtocolIni, szTemp);
        AddStringToMultiSz (mszProtocolIni, cszTcpIpDriver);
    } else {
        // for Protocols other than TCP/IP get the info from the INF

        GetPrivateProfileSection (szNifKey,
            szSectionBuffer, MEDIUM_BUFFER_SIZE,
            pAppInfo->niNetCard.szInf);

        // process section. Format of each line is:
        //  entry=IniName,DescriptionString,Type,OptionRange,Default
        //  for each entry, I'll print:
        //      IniName=Default
        //  in the protocol.ini file
        //
        for (szThisString = szSectionBuffer;
            *szThisString != 0;
            szThisString += lstrlen(szThisString) +1) {
            if (_tcsnicmp(szThisString, cszDrivername, lstrlen(cszDrivername)) == 0) {
                // drivername entry is a special case
                AddStringToMultiSz (mszProtocolIni, szThisString);
            } else {
                if (bIpx && pAppInfo->niNetCard.bTokenRing) {
                // another special case is when IPX is used with Token Ring
                // cards.
                    if (_tcsnicmp(GetItemFromEntry(szThisString,1),
                        cszFrame, lstrlen(cszFrame)) == 0) {
                        szDefaultValue = cszTokenRingEntry;
                    }
                } else {
                    szDefaultValue = GetItemFromEntry(szThisString, 5);
                }
                // only write parameters that actually have a default value
                // to write
                if (lstrlen(szDefaultValue) > 0) {
                    _stprintf (szTemp, fmtIniKeyEntry,
                        GetItemFromEntry(szThisString, 1),
                        szDefaultValue);
                    AddStringToMultiSz (mszProtocolIni, szTemp);
                }
            }
        }
    }


    _stprintf (szTemp, fmtBindingsEntry, pAppInfo->niNetCard.szInfKey);
    AddStringToMultiSz (mszProtocolIni, szTemp);

    // IPX does not get a LANABASE entry

    if (_tcsnicmp(pAppInfo->piFloppyProtocol.szKey, cszIpxKey, lstrlen(cszIpxKey)) != 0) {
        AddStringToMultiSz (mszProtocolIni, fmtLanabase0);
    }

    FREE_IF_ALLOC (szSectionBuffer);
    FREE_IF_ALLOC (szTemp);
    FREE_IF_ALLOC (szTemp2);
    FREE_IF_ALLOC (szNifKey);

    return TRUE;

}

static
BOOL
LoadSystemIni (
    OUT  LPTSTR  mszList
)
/*++

Routine Description:

    Routine to generate the System.INI file for the boot floppy

Arguments:

    OUT LPTSTR   mszList
        buffer to fill with system.INI records
        NOTE: BUFFER SIZE is assumed to be sufficient (i.e. it's not checked!)

Return Value:

    TRUE    if entries generated
    FALSE   if error

--*/
{
    LPTSTR  szTemp1;
    LPTSTR  szTemp2;
    LPSTR   szAnsi1;
    BOOL    bReturn;

    szTemp1 = (LPTSTR)GlobalAlloc (GPTR, MAX_PATH_BYTES);
    szTemp2 = (LPTSTR)GlobalAlloc (GPTR, MAX_PATH_BYTES);
    szAnsi1 = (LPSTR)GlobalAlloc (GPTR, MAX_PATH);

    if ((szTemp1 != NULL) &&
        (szTemp2 != NULL) &&
        (szAnsi1 != NULL))  {
        AddStringToMultiSz (mszList, cszNetworkSection);
        AddStringToMultiSz (mszList, fmtNoFilesharing);
        AddStringToMultiSz (mszList, fmtNoPrintsharing);
        AddStringToMultiSz (mszList, fmtYesAutologon);
        _stprintf (szTemp1, fmtComputernameEntry, pAppInfo->szComputerName);
        CharToOemBuff (szTemp1, szAnsi1, (DWORD)(lstrlen(szTemp1)+1));
#ifdef UNICODE
        mbstowcs (szTemp2, szAnsi1, MAX_PATH);
#else
        lstrcpy (szTemp2, szAnsi1);
#endif
        AddStringToMultiSz (mszList, szTemp2);
        AddStringToMultiSz (mszList, fmtLanaRootOnA);
        _stprintf (szTemp1, fmtUsernameEntry, pAppInfo->szUsername);
        CharToOemBuff (szTemp1, szAnsi1, (DWORD)(lstrlen(szTemp1)+1));
#ifdef UNICODE
        mbstowcs (szTemp2, szAnsi1, MAX_PATH);
#else
        lstrcpy (szTemp2, szAnsi1);
#endif
        AddStringToMultiSz (mszList, szTemp2);
        _stprintf (szTemp1, fmtWorkgroupEntry, pAppInfo->szDomain);
        CharToOemBuff (szTemp1, szAnsi1, (DWORD)(lstrlen(szTemp1)+1));
#ifdef UNICODE
        mbstowcs (szTemp2, szAnsi1, MAX_PATH);
#else
        lstrcpy (szTemp2, szAnsi1);
#endif
        AddStringToMultiSz (mszList, szTemp2);
        AddStringToMultiSz (mszList, fmtNoReconnect);
        if (_tcsnicmp(pAppInfo->piFloppyProtocol.szName, cszNetbeuiKey, lstrlen(cszNetbeuiKey)) == 0) {
            // only NetBEUI gets this
            AddStringToMultiSz (mszList, fmtNoDirectHost);
        }
        AddStringToMultiSz (mszList, fmtNoDosPopHotKey);
        if (_tcsnicmp(pAppInfo->piFloppyProtocol.szKey, cszIpxKey, lstrlen(cszIpxKey)) == 0) {
            AddStringToMultiSz (mszList, fmtLmLogon1);
        } else {
            AddStringToMultiSz (mszList, fmtLmLogon0);
        }
        _stprintf (szTemp1, fmtLogonDomainEntry, pAppInfo->szDomain);
        CharToOemBuff (szTemp1, szAnsi1, (DWORD)(lstrlen(szTemp1)+1));
#ifdef UNICODE
        mbstowcs (szTemp2, szAnsi1, MAX_PATH);
#else
        lstrcpy (szTemp2, szAnsi1);
#endif
        AddStringToMultiSz (mszList, szTemp2);
        AddStringToMultiSz (mszList, fmtPreferredRedirFull);
        AddStringToMultiSz (mszList, fmtAutostartFull);
        AddStringToMultiSz (mszList, fmtMaxConnections);

        // network driver section

        AddStringToMultiSz (mszList, fmtNetworkDriversSection);
        _stprintf (szTemp1, fmtNetcardEntry, pAppInfo->niNetCard.szDriverFile);
        CharToOemBuff (szTemp1, szAnsi1, (DWORD)(lstrlen(szTemp1)+1));
#ifdef UNICODE
        mbstowcs (szTemp2, szAnsi1, MAX_PATH);
#else
        lstrcpy (szTemp2, szAnsi1);
#endif
        AddStringToMultiSz (mszList, szTemp2);
        if (_tcsnicmp(pAppInfo->piFloppyProtocol.szName, cszTCP, lstrlen(cszTCP)) == 0 ) {
            // tcpip Transport
            lstrcpy (szTemp1, fmtTcpTransportEntry);
        } else {
            lstrcpy (szTemp1, fmtNdisTransportEntry);
            if (_tcsnicmp(pAppInfo->piFloppyProtocol.szName, cszNetbeui, lstrlen(cszNetbeui)) == 0 ) {
                // add NetBEUI string
                lstrcat (szTemp1, fmtNetbeuiAddon);
            }
        }
        AddStringToMultiSz (mszList, szTemp1);
        AddStringToMultiSz (mszList, fmtDevdir);
        AddStringToMultiSz (mszList, fmtLoadRmDrivers);

        // password file list (header only)
        AddStringToMultiSz (mszList, fmtPasswordListSection);
        bReturn = TRUE;
    } else {
        bReturn = FALSE;
    }

    FREE_IF_ALLOC (szTemp1);
    FREE_IF_ALLOC (szTemp2);
    FREE_IF_ALLOC (szAnsi1);

    return bReturn;
}

static
BOOL
LoadAutoexecBat (
    OUT LPTSTR mszList
)
/*++

Routine Description:

    Routine to generate the Autoexec.bat file for the boot floppy

Arguments:

    OUT  LPTSTR  mszList
        Buffer to write autoexec.bat entries into
        NOTE: BUFFER SIZE is assumed to be sufficient (i.e. it's not checked!)


Return Value:

    TRUE    if entries generated
    FALSE   if error

--*/
{
    LPTSTR  szTemp;
    LPTSTR  szTemp2;
    LPTSTR  szSectionBuffer;
    LPTSTR  szDir;
    LPTSTR  szEntry;

    szSectionBuffer = GlobalAlloc (GPTR, (SMALL_BUFFER_SIZE * sizeof(TCHAR)));
    szTemp = (LPTSTR)GlobalAlloc (GPTR, MAX_PATH_BYTES);
    szTemp2 = (LPTSTR)GlobalAlloc (GPTR, MAX_PATH_BYTES);

    if ((szSectionBuffer == NULL) ||
        (szTemp == NULL) ||
        (szTemp2 == NULL)) {
        return FALSE;
    }

    AddStringToMultiSz (mszList, fmtPathSpec);

    // load network starting commands from INF
    // get commands from INF for this protocol

    //
    //  put INF filename into szTemp
    //
    lstrcpy (szTemp, pAppInfo->szDistPath);
    if (szTemp[lstrlen(szTemp)-1] != cBackslash) lstrcat (szTemp, cszBackslash);
    lstrcat (szTemp, cszAppInfName);
    //
    //  put key name made from protocol and "_autoexec" into szTemp2
    //
    lstrcpy (szTemp2, pAppInfo->piFloppyProtocol.szKey);
    lstrcat (szTemp2, fmtAutoexec);

    GetPrivateProfileSection (szTemp2, szSectionBuffer,
        SMALL_BUFFER_SIZE, szTemp);

    for (szEntry = szSectionBuffer;
         *szEntry != 0;
         szEntry += (lstrlen(szEntry) + 1)) {
        lstrcpy (szTemp, fmtNetPrefix);
        lstrcat (szTemp, GetKeyFromEntry(szEntry));
        AddStringToMultiSz (mszList, szTemp);
    }

    // create network connection commands

    if (GetServerAndSharepointFromUnc(pAppInfo->piTargetProtocol.szDir, szTemp2)) {
        _stprintf (szTemp, fmtNetUseDrive, szTemp2);
        AddStringToMultiSz (mszList, szTemp);
    } else {
        AddStringToMultiSz (mszList,
            GetStringResource (FMT_CONNECTING_COMMENT));
    }

    // create setup command

    szDir = (LPTSTR)GetDirPathFromUnc(pAppInfo->piTargetProtocol.szDir);
    if (lstrlen(szDir) > 0) {
        AddStringToMultiSz (mszList,
            GetStringResource (FMT_RUNNING_SETUP_COMMENT));
        _stprintf (szTemp, fmtSetupCommand,
            szDir, pAppInfo->szTargetSetupCmd);
        AddStringToMultiSz (mszList, szTemp);
    } else {
        AddStringToMultiSz (mszList,
            GetStringResource (FMT_OTN_COMMENT));
    }

    FREE_IF_ALLOC (szSectionBuffer);
    FREE_IF_ALLOC (szTemp);
    FREE_IF_ALLOC (szTemp2);

    return TRUE;
}

static
BOOL
LoadConfigSys (
    OUT LPTSTR mszList
)
/*++

Routine Description:

    Routine to write Config.Sys entries for the Boot Floppy.

Arguments:

    OUT LPTSTR mszList
        Buffer to write Config.sys commands into
        NOTE: BUFFER SIZE is assumed to be sufficient (i.e. it's not checked!)


Return Value:

    TRUE

--*/
{
    AddStringToMultiSz (mszList, fmtFilesParam);
    AddStringToMultiSz (mszList, fmtDeviceIfsHlpSys);
    AddStringToMultiSz (mszList, fmtLastDrive);
    if (GetBootDiskDosVersion (pAppInfo->szBootFilesPath) >= 5) {
        AddStringToMultiSz (mszList, fmtLoadHiMem);
        AddStringToMultiSz (mszList, fmtLoadEMM386);
        AddStringToMultiSz (mszList, fmtDosHigh);
    }

    return TRUE;
}

static
BOOL
MakeFlopDlg_NCDU_START_FILE_COPY (
    IN  HWND    hwndDlg,
    IN  WPARAM  wParam,
    IN  LPARAM  lParam
)
/*++

Routine Description:

    Processes NCDU_START_FILE_COPY message. Allocates buffers to be
        used in creating boot and network configuration files. Fills
        them in using information from the pAppInfo struct then
        writes them to the output files on the destination drive.
        Once the generated files have been written, the other
        files are copied from the OTN dir to the destination drive.
        If all goes well, then the dialog box is closed.

Arguments:

    IN  HWND    hwndDlg
        Handle to dialog box window

    IN  WPARAM  wParam
        Not Used

    IN  LPARAM  lParam
        Not Used

Return Value:

    FALSE.

--*/
{
    LPTSTR  mszNetFileList;
    LPTSTR  mszProtocolIni;
    LPTSTR  mszSystemIni;
    LPTSTR  mszAutoexecBat;
    LPTSTR  mszConfigSys;
    DWORD   dwNetFileCount = 0;
    DWORD   dwFilesCopied = 0;
    DWORD   dwDestClusterSize = 0;

    DWORD   dwFileBytesToCopy = 0;
    DWORD   dwDestFreeSpace = 0;
    DWORD   dwFileSize;

    LPTSTR  szSrcFile;
    LPTSTR  szSrcFilePart;

    LPTSTR  szDestFile;
    LPTSTR  szDestFilePart;

    LPTSTR  szThisFile;
    LPTSTR  szInfFile;

    int     nMbResult;
    BOOL    bBootable;
    BOOL    bAborted = FALSE;

    DWORD   dwSystemFileSize;

    MSG     msg;
    UINT    nExitCode = IDOK;

    mszNetFileList = (LPTSTR)GlobalAlloc(GPTR, MEDIUM_BUFFER_SIZE);
    mszProtocolIni = (LPTSTR)GlobalAlloc(GPTR, MEDIUM_BUFFER_SIZE);
    mszSystemIni = (LPTSTR)GlobalAlloc(GPTR, MEDIUM_BUFFER_SIZE);
    mszAutoexecBat = (LPTSTR)GlobalAlloc(GPTR, SMALL_BUFFER_SIZE);
    mszConfigSys = (LPTSTR)GlobalAlloc(GPTR, SMALL_BUFFER_SIZE);
    szSrcFile = (LPTSTR)GlobalAlloc(GPTR, MAX_PATH_BYTES);
    szDestFile = (LPTSTR)GlobalAlloc(GPTR, MAX_PATH_BYTES);
    szInfFile = (LPTSTR)GlobalAlloc(GPTR, MAX_PATH_BYTES);

    if ((mszNetFileList != NULL) &&
        (mszProtocolIni != NULL) &&
        (mszConfigSys != NULL) &&
        (mszAutoexecBat != NULL) &&
        (szSrcFile != NULL) &&
        (szDestFile != NULL) &&
        (szInfFile != NULL) &&
        (mszSystemIni != NULL)) {

        *(PDWORD)mszNetFileList = 0L;
        *(PDWORD)mszProtocolIni = 0L;
        *(PDWORD)mszSystemIni = 0L;
        *(PDWORD)mszAutoexecBat = 0L;
        *(PDWORD)mszConfigSys = 0L;

        szDestFilePart = szDestFile;    // to initialize the var

        lstrcpy (szInfFile, pAppInfo->szDistPath);
        if (szInfFile[lstrlen(szInfFile)-1] != cBackslash)
            lstrcat (szInfFile, cszBackslash);
        lstrcat (szInfFile, cszAppInfName);

        if (GetPrivateProfileString (cszSizes, csz_SystemFileSize_,
            cszEmptyString, szSrcFile, MAX_PATH, szInfFile) > 0) {
            // a value was found so get the filesize value from the string
            dwSystemFileSize = GetSizeFromInfString (szSrcFile);
        } else {
            dwSystemFileSize = 0;
        }

        if (!(bBootable = IsDestBootableDosFloppy())) {
            AddMessageToExitList (pAppInfo, NCDU_COPY_TO_FLOPPY);
        }

        // generate protocol.ini

        LoadProtocolIni (
            mszProtocolIni,
            mszNetFileList,
            &dwNetFileCount);
        dwNetFileCount += 1;     // account for protocol.ini file

        // generate system.ini
        LoadSystemIni (mszSystemIni);
        dwNetFileCount += 1;

        // generate autoexec.bat
        LoadAutoexecBat (mszAutoexecBat);
        dwNetFileCount += 1;

        // generate config.sys
        LoadConfigSys (mszConfigSys);
        dwNetFileCount += 1;

        // determine number of bytes to copy to destination

        dwDestClusterSize = GetClusterSizeOfDisk (pAppInfo->szBootFilesPath);

        dwFileBytesToCopy = 0;  // clear

        // get size of file that will be written
        dwFileBytesToCopy += GetMultiSzLen (mszProtocolIni);
        // and round up to the next sector size
        dwFileBytesToCopy += dwDestClusterSize -
            (dwFileBytesToCopy % dwDestClusterSize);

        // get size of file that will be written
        dwFileBytesToCopy += GetMultiSzLen (mszSystemIni);
        // and round up to the next sector size
        dwFileBytesToCopy += dwDestClusterSize -
            (dwFileBytesToCopy % dwDestClusterSize);

        // get size of file that will be written
        dwFileBytesToCopy += GetMultiSzLen (mszAutoexecBat);
        // and round up to the next sector size
        dwFileBytesToCopy += dwDestClusterSize -
            (dwFileBytesToCopy % dwDestClusterSize);

        // get size of file that will be written
        dwFileBytesToCopy += GetMultiSzLen (mszConfigSys);
        // and round up to the next sector size
        dwFileBytesToCopy += dwDestClusterSize -
            (dwFileBytesToCopy % dwDestClusterSize);

        // get size of files in copy list and add to internally created files

        lstrcpy (szSrcFile, pAppInfo->piFloppyProtocol.szDir);
        if (szSrcFile[lstrlen(szSrcFile)-1] != cBackslash) lstrcat (szSrcFile, cszBackslash);
        szSrcFilePart = &szSrcFile[lstrlen(szSrcFile)];

        for (szThisFile = mszNetFileList;
            *szThisFile != 0;
            szThisFile += (lstrlen(szThisFile) + 1)) {
            // make full path of filename
            lstrcpy (szSrcFilePart, szThisFile);
            // get the size of the file and add it to the total
            dwFileSize = QuietGetFileSize (szSrcFile);
            if (dwFileSize != 0xFFFFFFFF) {
                dwFileBytesToCopy += dwFileSize;
                // and round to the next larger allocation unit
                dwFileBytesToCopy += dwDestClusterSize -
                    (dwFileBytesToCopy % dwDestClusterSize);
            }
        }

        dwDestFreeSpace = ComputeFreeSpace (pAppInfo->szBootFilesPath);

        if (dwDestFreeSpace < dwFileBytesToCopy) {
            DisplayMessageBox (hwndDlg,
                NCDU_INSUFFICIENT_DISK_SPACE,
                0,
                MB_OK_TASK_EXCL);
            bCopying = FALSE;
            bAborted = TRUE;
            nExitCode = IDCANCEL; // operation ended in error
        } else {
            if (!bBootable) {
                // see if there will be room to add the system files
                // later...
                dwFileBytesToCopy += dwSystemFileSize;
                if (dwDestFreeSpace < dwFileBytesToCopy) {
                   if (DisplayMessageBox (hwndDlg,
                        NCDU_SYSTEM_MAY_NOT_FIT,
                        0,
                        MB_OKCANCEL_TASK_INFO | MB_DEFBUTTON2) == IDCANCEL) {
                        bCopying = FALSE;
                        bAborted = TRUE;
                        nExitCode = IDCANCEL; // operation ended in error
                    } else {
                        // they want to continue so stick a message in the
                        // exit messages
                        AddMessageToExitList (pAppInfo, NCDU_SMALL_DISK_WARN);
                    }
                }
            }
        }

        if (bCopying) {
            // write files to root directory
            lstrcpy (szDestFile, pAppInfo->szBootFilesPath);
            if (szDestFile[lstrlen(szDestFile)-1] != cBackslash) lstrcat (szDestFile, cszBackslash);
            szDestFilePart = &szDestFile[lstrlen(szDestFile)];

            // make sure destination path exists
            CreateDirectoryFromPath (szDestFile, NULL);

            // config.sys
            lstrcpy (szDestFilePart, cszConfigSys);
            if (WriteMszToFile (hwndDlg, mszConfigSys, szDestFile, CREATE_ALWAYS)) {
                UpdatePercentComplete (hwndDlg, ++dwFilesCopied, dwNetFileCount);
            } else {
                // bail out here since there was a copy error
                nMbResult = MessageBox (
                    hwndDlg,
                    GetStringResource (CSZ_UNABLE_COPY),
                    szDestFile,
                    MB_OKCANCEL_TASK_EXCL);
                if (nMbResult == IDCANCEL) {
                    bCopying = FALSE;
                    nExitCode = IDCANCEL; // operation ended in error
                } else {
                    AddMessageToExitList (pAppInfo, NCDU_FLOPPY_NOT_COMPLETE);
                }
            }
        }

        if (bCopying) {
            // autoexec.bat
            lstrcpy (szDestFilePart, cszAutoexecBat);
            if (WriteMszToFile (hwndDlg, mszAutoexecBat, szDestFile, CREATE_ALWAYS)) {
                UpdatePercentComplete (hwndDlg, ++dwFilesCopied, dwNetFileCount);
            } else {
                // bail out here since there was a copy error
                nMbResult = MessageBox (
                    hwndDlg,
                    GetStringResource (CSZ_UNABLE_COPY),
                    szDestFile,
                    MB_OKCANCEL_TASK_EXCL);
                if (nMbResult == IDCANCEL) {
                    bCopying = FALSE;
                    nExitCode = IDCANCEL; // operation ended in error
                } else {
                    AddMessageToExitList (pAppInfo, NCDU_FLOPPY_NOT_COMPLETE);
                }
            }
        }


        if (bCopying) {
            // write INI files
            // make NET subdir
            lstrcpy (szDestFilePart, cszNet);
            CreateDirectory (szDestFile, NULL);
            // add net sub dir to dest path
            if (szDestFile[lstrlen(szDestFile)-1] != cBackslash) lstrcat (szDestFile, cszBackslash);
            szDestFilePart = &szDestFile[lstrlen(szDestFile)];
            lstrcpy (szDestFilePart, cszSystemIni);

            if (WriteMszToFile (hwndDlg, mszSystemIni, szDestFile, CREATE_ALWAYS)) {
                UpdatePercentComplete (hwndDlg, ++dwFilesCopied, dwNetFileCount);
            } else {
                // bail out here since there was a copy error
                nMbResult = MessageBox (
                    hwndDlg,
                    GetStringResource (CSZ_UNABLE_COPY),
                    szDestFile,
                    MB_OKCANCEL_TASK_EXCL);
                if (nMbResult == IDCANCEL) {
                    bCopying = FALSE;
                    nExitCode = IDCANCEL; // operation ended in error
                } else {
                    AddMessageToExitList (pAppInfo, NCDU_FLOPPY_NOT_COMPLETE);
                }
            }
        }

        if (bCopying) {
            lstrcpy (szDestFilePart, cszProtocolIni);
            if (WriteMszToFile (hwndDlg, mszProtocolIni, szDestFile, CREATE_ALWAYS)) {
                UpdatePercentComplete (hwndDlg, ++dwFilesCopied, dwNetFileCount);
            } else {
                // bail out here since there was a copy error
                nMbResult = MessageBox (
                    hwndDlg,
                    GetStringResource (CSZ_UNABLE_COPY),
                    szDestFile,
                    MB_OKCANCEL_TASK_EXCL);
                if (nMbResult == IDCANCEL) {
                    bCopying = FALSE;
                    nExitCode = IDCANCEL; // operation ended in error
                } else {
                    AddMessageToExitList (pAppInfo, NCDU_FLOPPY_NOT_COMPLETE);
                }
            }
        }

        if (bCopying) {
            // copy files in list from ??? to destination dir
            lstrcpy (szSrcFile, pAppInfo->piFloppyProtocol.szDir);
            if (szSrcFile[lstrlen(szSrcFile)-1] != cBackslash) lstrcat (szSrcFile, cszBackslash);
            szSrcFilePart = &szSrcFile[lstrlen(szSrcFile)];

            for (szThisFile = mszNetFileList;
                *szThisFile != 0;
                szThisFile += (lstrlen(szThisFile) + 1)) {
                lstrcpy (szSrcFilePart, szThisFile);
                lstrcpy (szDestFilePart, szThisFile);

                if (bCopying) {
                    SetDlgItemText (hwndDlg, NCDU_FROM_PATH, szSrcFile);
                    SetDlgItemText (hwndDlg, NCDU_TO_PATH, szDestFile);

                    if (!CopyFile (szSrcFile, szDestFile, FALSE)) {
                        // error in file copy so bail out here
                        // bail out here since there was a copy error
                        nMbResult = MessageBox (
                            hwndDlg,
                            GetStringResource (CSZ_UNABLE_COPY),
                            szSrcFile,
                            MB_OKCANCEL_TASK_EXCL);
                        if (nMbResult == IDCANCEL) {
                            bCopying = FALSE;
                            nExitCode = IDCANCEL; // operation ended in error
                        } else {
                            AddMessageToExitList (pAppInfo, NCDU_FLOPPY_NOT_COMPLETE);
                        }
                    } else {
                        // copy was successful so update the  % complete
                        // and Set destination File attributest to NORMAL
                        SetFileAttributes (szDestFile, FILE_ATTRIBUTE_NORMAL);
                        UpdatePercentComplete (hwndDlg, ++dwFilesCopied, dwNetFileCount);
                    }

                    // check for messages

                    while (PeekMessage (&msg, 0, 0, 0, PM_REMOVE)) {
                        TranslateMessage (&msg);
                        DispatchMessage (&msg);
                    }
                } else {
                    break;
                }
            }
        }
    }

    if (bCopying) {
        // files copied completely, but check params.
        AddMessageToExitList (pAppInfo, NCDU_CHECK_PROTOCOL_INI);
        DisplayMessageBox (
            hwndDlg,
            NCDU_FLOPPY_COMPLETE,
            0,
            MB_OK_TASK_INFO);
    } else {
        if (!bAborted) {
            // don't show "not copied" dialog since they know
            // this
            // floppy not copied completely
            AddMessageToExitList (pAppInfo, NCDU_FLOPPY_NOT_COMPLETE);
            DisplayMessageBox (
                hwndDlg,
                NCDU_FLOPPY_NOT_COMPLETE,
                0,
                MB_OK_TASK_EXCL);
        }
    }

    if (nExitCode == IDOK) {
        // enable display of exit messages since a floppy was created
        EnableExitMessage(TRUE);
    }

    EndDialog (hwndDlg, nExitCode);

    FREE_IF_ALLOC (mszNetFileList);
    FREE_IF_ALLOC (mszProtocolIni);
    FREE_IF_ALLOC (mszSystemIni);
    FREE_IF_ALLOC (mszConfigSys);
    FREE_IF_ALLOC (mszAutoexecBat);
    FREE_IF_ALLOC (szSrcFile);
    FREE_IF_ALLOC (szDestFile);
    FREE_IF_ALLOC (szInfFile);

    return TRUE;
}

static
BOOL
MakeFlopDlg_WM_INITDIALOG (
    IN  HWND    hwndDlg,
    IN  WPARAM  wParam,
    IN  LPARAM  lParam
)
/*++

Routine Description:

    Initializes the text fields of the dialog box and post's the
        "start copying" message

Arguments:

    IN  HWND    hwndDlg
        Handle to dialog box window

    IN  WPARAM  wParam
        Not Used

    IN  LPARAM  lParam
        Not Used

Return Value:

--*/
{
    // intialize Global data
     bCopying = TRUE;

    RemoveMaximizeFromSysMenu (hwndDlg);
    PositionWindow  (hwndDlg);
    SetDlgItemText (hwndDlg, NCDU_COPY_APPNAME,
        GetStringResource (FMT_OTN_BOOT_FILES));
    SetDlgItemText (hwndDlg, NCDU_FROM_PATH, cszEmptyString);
    SetDlgItemText (hwndDlg, NCDU_TO_PATH, cszEmptyString);
    SetDlgItemText (hwndDlg, NCDU_PERCENT_COMPLETE,
        GetStringResource (FMT_ZERO_PERCENT_COMPLETE));
    SetFocus (GetDlgItem(hwndDlg, IDCANCEL));

    // start copying files
    PostMessage (hwndDlg, NCDU_START_FILE_COPY, 0, lParam);
    // clear old Dialog and register current
    PostMessage (GetParent(hwndDlg), NCDU_CLEAR_DLG, (WPARAM)hwndDlg, IDOK);
    PostMessage (GetParent(hwndDlg), NCDU_REGISTER_DLG,
        NCDU_COPYING_FILES_DLG, (LPARAM)hwndDlg);
    SetCursor(LoadCursor(NULL, IDC_ARROW));

    return FALSE;
}

static
BOOL
MakeFlopDlg_WM_COMMAND (
    IN  HWND    hwndDlg,
    IN  WPARAM  wParam,
    IN  LPARAM  lParam
)
/*++

Routine Description:

    Process WM_COMMAND message. Stops copying if the Cancel (abort)
        button is pressed.

Arguments:

    IN  HWND    hwndDlg
        Handle to dialog box procedure

    IN  WPARAM  wParam
        LOWORD contains the id of the control that initiated this message

    IN  LPARAM  lParam
        Not Used

Return Value:

--*/
{
    switch (LOWORD(wParam)) {
        case IDCANCEL:
            bCopying = FALSE;
            return TRUE;

        default:    return FALSE;
    }
}

BOOL CALLBACK
MakeFlopDlgProc (
    IN  HWND    hwndDlg,
    IN  UINT    message,
    IN  WPARAM  wParam,
    IN  LPARAM  lParam
)
/*++

Routine Description:

    Main Dialog Box Procedure. Dispatches Windows messages to the appropriate
        processing routine. The following windows messages are processed
        by this module:

            WM_INITDIALOG:      dialog initialization routine
            WM_COMMAND:         user input
            NCDU_START_FILE_COPY:   local windows message to start copy op.


Arguments:

    Standard WNDPROC arguments

Return Value:

    FALSE  if message is not processed by this routine, otherwise
        the value returned by the dispatched routine.

--*/
{
    switch (message) {
        case WM_INITDIALOG: return (MakeFlopDlg_WM_INITDIALOG (hwndDlg, wParam, lParam));
        case WM_COMMAND:    return (MakeFlopDlg_WM_COMMAND (hwndDlg, wParam, lParam));
        case NCDU_START_FILE_COPY: return (MakeFlopDlg_NCDU_START_FILE_COPY (hwndDlg, wParam, lParam));
        case WM_PAINT:      return (Dlg_WM_PAINT (hwndDlg, wParam, lParam));
        case WM_MOVE:       return (Dlg_WM_MOVE (hwndDlg, wParam, lParam));
        case WM_SYSCOMMAND: return (Dlg_WM_SYSCOMMAND (hwndDlg, wParam, lParam));
        default:            return FALSE;
    }
}

