windows-nt/Source/XPSP1/NT/base/remoteboot/rbinstal/setup.cpp
2020-09-26 16:20:57 +08:00

793 lines
22 KiB
C++

/****************************************************************************
Copyright (c) Microsoft Corporation 1997
All rights reserved
***************************************************************************/
#include "pch.h"
#include <shlobj.h>
#include <setupapi.h>
#include <advpub.h>
#include <lm.h>
#include "dialogs.h"
DEFINE_MODULE("Setup");
#define SMALL_BUFFER_SIZE 256
#define MAX_FILES_SIZE 640000
static const TCHAR chSlash = TEXT('\\');
//
// Opens the layout.inf file for a particular platform.
//
HINF
OpenLayoutInf( )
{
TCHAR szFilename[ MAX_PATH ];
HANDLE hFile;
UINT uErr;
DWORD dwLen;
DWORD dw;
lstrcpy( szFilename, g_Options.szSourcePath );
dwLen = lstrlen( szFilename );
szFilename[ dwLen++ ] = chSlash;
dw = LoadString( g_hinstance, IDS_NTSETUPINFFILENAME,
&szFilename[ dwLen ], ARRAYSIZE( szFilename ) - dwLen );
Assert( dw );
hFile = SetupOpenInfFile( szFilename, NULL, INF_STYLE_WIN4, &uErr );
return hFile;
}
//
// Creates the RemoteBoot directory tree.
//
HRESULT
CreateDirectories( HWND hDlg )
{
BOOL fReturn = FALSE;
TCHAR szPath[ MAX_PATH ];
TCHAR szCreating[ SMALL_BUFFER_SIZE ];
HWND hProg = GetDlgItem( hDlg, IDC_P_METER );
DWORD dwLen;
DWORD dw;
SendMessage( hProg, PBM_SETRANGE, 0,
MAKELPARAM(0, 4 + ( g_Options.fCreateDirectory ? 1 : 0 )) );
SendMessage( hProg, PBM_SETSTEP, 1, 0 );
dw = LoadString( g_hinstance, IDS_CREATINGDIRECTORIES, szCreating,
ARRAYSIZE( szCreating ) );
Assert( dw );
SetWindowText( GetDlgItem( hDlg, IDC_S_OPERATION ), szCreating );
if ( g_Options.fCreateDirectory )
{
fReturn = CreateDirectory( g_Options.szRemoteBootPath, NULL );
SendMessage( hProg, PBM_DELTAPOS, 1, 0 );
if ( !fReturn )
goto Finish;
}
lstrcpy( szPath, g_Options.szRemoteBootPath );
dwLen = lstrlen( szPath );
szPath[ dwLen ] = chSlash;
dwLen++;
dw = LoadString( g_hinstance, IDS_IMAGES, &szPath[ dwLen ],
ARRAYSIZE( szPath ) - dwLen );
Assert( dw );
CreateDirectory( szPath, NULL );
SendMessage( hProg, PBM_DELTAPOS, 1, 0 );
lstrcpy( g_Options.szImagesPath, szPath );
dw = LoadString( g_hinstance, IDS_TEMPLATEPATH, &szPath[ dwLen ],
ARRAYSIZE( szPath )- dwLen );
Assert( dw );
CreateDirectory( szPath, NULL );
SendMessage( hProg, PBM_DELTAPOS, 1, 0 );
dw = LoadString( g_hinstance, IDS_SETUP, &szPath[ dwLen ],
ARRAYSIZE( szPath ) - dwLen );
Assert( dw );
CreateDirectory( szPath, NULL );
SendMessage( hProg, PBM_DELTAPOS, 1, 0 );
dwLen = lstrlen( szPath );
szPath[ dwLen ] = chSlash;
dwLen++;
lstrcpy( &szPath[ dwLen ], g_Options.szName );
CreateDirectory( szPath, NULL );
SendMessage( hProg, PBM_DELTAPOS, 1, 0 );
/*
// add '\i386'
dwLen = lstrlen( szPath );
szPath[ dwLen ] = chSlash;
dwLen++;
dw = LoadString( g_hinstance, IDS_INTELPATH, &szPath[ dwLen ], ARRAYSIZE( szPath ) - dwLen );
Assert( dw );
*/
lstrcpy( g_Options.szSetupPath, szPath );
fReturn = TRUE;
Finish:
g_Options.fError = !fReturn;
return fReturn ? S_OK : E_FAIL;
}
//
// Find the filename part from a complete path.
//
LPTSTR FilenameOnly( LPTSTR pszPath )
{
LPTSTR psz = pszPath;
// find the end
while ( *psz )
psz++;
// find the slash
while ( psz > pszPath && *psz != chSlash )
psz--;
// move in front of the slash
if ( psz != pszPath )
psz++;
return psz;
}
typedef struct {
PVOID pContext; // "Context" for DefaultQueueCallback
HWND hProg; // hwnd to the progress meter
HWND hOperation; // hwnd to the "current operation"
DWORD nCopied; // number of files copied
DWORD nToBeCopied; // number of file to be copied
DWORD dwCopyingLength; // length of the IDS_COPYING
TCHAR szCopyingString[ SMALL_BUFFER_SIZE ]; // buffer to create "Copying file.ext..."
} MYCONTEXT, *LPMYCONTEXT;
//
//
//
UINT CALLBACK
CopyFilesCallback(
IN PVOID Context,
IN UINT Notification,
IN UINT Param1,
IN UINT Param2
)
{
MSG Msg;
LPMYCONTEXT pMyContext = (LPMYCONTEXT) Context;
DWORD dw;
// process some messages
if ( PeekMessage( &Msg, NULL, 0, 0, PM_REMOVE ) )
{
TranslateMessage( &Msg );
DispatchMessage( &Msg );
}
if ( g_Options.fAbort )
{
if ( !g_Options.fError )
{
TCHAR szAbort[ SMALL_BUFFER_SIZE ];
// change filename text to aborting...
dw = LoadString( g_hinstance, IDS_ABORTING, szAbort,
ARRAYSIZE( szAbort ) );
Assert( dw );
SetWindowText( pMyContext->hOperation, szAbort );
g_Options.fError = TRUE;
}
SetLastError(ERROR_CANCELLED);
return FILEOP_ABORT;
}
switch ( Notification )
{
case SPFILENOTIFY_ENDCOPY:
pMyContext->nCopied++;
SendMessage( pMyContext->hProg, PBM_SETPOS,
(1000 * pMyContext->nCopied) / pMyContext->nToBeCopied, 0 );
break;
case SPFILENOTIFY_STARTCOPY:
{
DWORD dwLen;
LPTSTR * ppszCopyingFile = (LPTSTR *) Param1;
lstrcpy( &pMyContext->szCopyingString[ pMyContext->dwCopyingLength ],
FilenameOnly( *ppszCopyingFile ) );
dwLen = lstrlen( pMyContext->szCopyingString );
lstrcpy( &pMyContext->szCopyingString[ dwLen ], TEXT("...") );
SetWindowText( pMyContext->hOperation, pMyContext->szCopyingString );
}
break;
case SPFILENOTIFY_RENAMEERROR:
case SPFILENOTIFY_DELETEERROR:
case SPFILENOTIFY_COPYERROR:
case SPFILENOTIFY_NEEDMEDIA:
case SPFILENOTIFY_LANGMISMATCH:
case SPFILENOTIFY_TARGETEXISTS:
case SPFILENOTIFY_TARGETNEWER:
return SetupDefaultQueueCallback( pMyContext->pContext, Notification,
Param1, Param2 );
}
return FILEOP_DOIT;
}
//
// Find a character in a NULL terminated string.
//
// Returns NULL is not found.
//
LPTSTR
FindChar( LPTSTR pszSrc, TCHAR ch )
{
if ( pszSrc )
{
while ( *pszSrc )
{
if ( *pszSrc == ch )
return pszSrc;
pszSrc++;
}
}
return NULL;
}
//
// change layout format to double-null list
//
void
LayoutToDoubleNullList( LPTSTR pszList )
{
/*
Borrowed from LAYOUT.INF for reference
;
; filename_on_source = diskid,subdir,size,checksum,spare,spare
; extra fields are nt-specific
; bootmediaord: _1 (floppy #1)
; _2 (floppy #2)
; _3 (floppy #3)
; _x (textmode setup)
; nothing (gui mode setup)
; targetdirectory : 1 - 41 (see "WinntDirectories", above)
; upgradedisposition : 0 (always copy)
; 1 (copy if present)
; 2 (copy if not present)
; 3 (never copy)
; textmodedisposition:
; targetname
;
*/
static const TCHAR chComma = TEXT(',');
LPTSTR pszFile = pszList;
LPTSTR pszCopyHere = pszList;
while ( *pszFile )
{
MSG Msg;
DWORD dwToNextFile = lstrlen( pszFile );
LPTSTR pszNext;
LPTSTR psz = FindChar( pszFile, TEXT('=') );
Assert( psz );
// process some messages
if ( PeekMessage( &Msg, NULL, 0, 0, PM_REMOVE ) )
{
TranslateMessage( &Msg );
DispatchMessage( &Msg );
}
*psz = 0;
psz++;
pszNext = FindChar( psz, chComma );
*pszNext = 0;
// must be "1"
if ( !lstrcmp( psz, TEXT("1") ) )
{
// copy file name
lstrcpy( pszCopyHere, pszFile );
// advance copy pointer
pszCopyHere += 1 + lstrlen( pszCopyHere );
}
else
{
AssertMsg( FALSE, "Now what?!" );
}
// advanced file pointer
pszFile += dwToNextFile + 1;
}
*pszCopyHere = 0;
}
//
// change semicolon delinated list to double-null list
//
void
SemiColonToDoubleNullList( LPTSTR pszList )
{
while ( *pszList )
{
if ( *pszList == TEXT(';') )
{
*pszList = 0;
}
pszList++;
}
pszList++;
*pszList = 0; // double the null.
}
//
// Adds double-null terminated list of file name to the Queue. The filename
// can have a comma in it indicating a rename operation:
// optionalpath\newname.ext,optionalpath\sourcefil.ext
//
// Returns the number of files added to the Queue.
//
DWORD
CopyFilesAddToQueue(
HSPFILEQ Queue, // setup Queue
LPTSTR pszSource, // source directory
LPTSTR pszDest, // destination directory
LPTSTR pszFiles, // Double-null terminated file list
LPTSTR pszSubpath, // optional sub-path
DWORD dwCopyStyle) // flags
{
DWORD dwCount = 0;
LPTSTR psz = pszFiles;
static const TCHAR chComma = TEXT(',');
while ( *pszFiles )
{
DWORD dwLen;
psz = pszFiles;
// check for comma which indicates rename
while (*psz && *psz != chComma)
psz++;
if ( *psz == chComma )
{
*psz= 0; // terminate
psz++;
}
else
{ // sources name is dest name
psz = pszFiles;
}
SetupQueueCopy(
Queue,
pszSource,
pszSubpath,
psz,
NULL,
NULL,
pszDest,
pszFiles,
dwCopyStyle );
// get next file
pszFiles = psz + lstrlen( psz ) + 1;
dwCount++;
}
return dwCount;
}
//
// Copies the files into the setup directory.
//
HRESULT
CopyFiles( HWND hDlg )
{
TCHAR szLayoutFilename[ MAX_PATH ];
TCHAR szSystemPath[ MAX_PATH ];
DWORD dwLen;
LPTSTR psz;
BOOL fReturn = FALSE;
HWND hProg = GetDlgItem( hDlg, IDC_P_METER );
LPTSTR pszFiles = (LPTSTR) TraceAlloc( GMEM_FIXED, MAX_FILES_SIZE );
DWORD dwCount = 0;
DWORD dw;
HSPFILEQ Queue;
MYCONTEXT MyContext;
if ( !pszFiles || g_Options.fAbort )
goto Finish;
// Setup and display next section of dialog
SendMessage( hProg, PBM_SETRANGE, 0, MAKELPARAM(0, 1000 ));
SendMessage( hProg, PBM_SETPOS, 0, 0 );
dw = LoadString( g_hinstance, IDS_BUILDINGFILELIST, szLayoutFilename, ARRAYSIZE( szLayoutFilename ));
Assert( dw );
SetDlgItemText( hDlg, IDC_S_OPERATION, szLayoutFilename );
// Create layout filepath
lstrcpy( szLayoutFilename, g_Options.szSourcePath );
dwLen = lstrlen( szLayoutFilename );
szLayoutFilename[ dwLen ] = chSlash;
dwLen++;
dw = LoadString( g_hinstance, IDS_NTSETUPINFFILENAME,
&szLayoutFilename[ dwLen ], ARRAYSIZE( szLayoutFilename )- dwLen );
Assert( dw );
Queue = SetupOpenFileQueue( );
// add the files from the INF to the Queue
GetPrivateProfileSection( TEXT("SourceDisksFiles"), pszFiles, MAX_FILES_SIZE,
szLayoutFilename );
LayoutToDoubleNullList( pszFiles );
if ( g_Options.fIntel )
{
TCHAR szPath[ MAX_PATH ];
DWORD dwLen;
lstrcpy( szPath, g_Options.szSetupPath );
dwLen = lstrlen( szPath );
szPath[ dwLen++ ] = chSlash;
dw = LoadString( g_hinstance, IDS_INTELPATH, &szPath[ dwLen ], ARRAYSIZE( szPath ) - dwLen );
Assert( dw );
dwCount += CopyFilesAddToQueue( Queue, g_Options.szSourcePath, szPath,
pszFiles, NULL, SP_COPY_NEWER | SP_COPY_WARNIFSKIP );
// add the processor dependant files from the INF to the Queue
GetPrivateProfileSection( TEXT("SourceDisksFiles.x86"), pszFiles, MAX_FILES_SIZE,
szLayoutFilename );
LayoutToDoubleNullList( pszFiles );
dwCount += CopyFilesAddToQueue( Queue, g_Options.szSourcePath, szPath,
pszFiles, NULL, SP_COPY_NEWER | SP_COPY_WARNIFSKIP );
// additional files not listed
dw = LoadString( g_hinstance, IDS_FILESTOBECOPIED, pszFiles, MAX_FILES_SIZE );
SemiColonToDoubleNullList( pszFiles );
dwCount += CopyFilesAddToQueue( Queue, g_Options.szSourcePath, szPath, pszFiles, NULL,
SP_COPY_NEWER | SP_COPY_WARNIFSKIP );
}
if ( g_Options.fAlpha )
{
TCHAR szPath[ MAX_PATH ];
DWORD dwLen;
lstrcpy( szPath, g_Options.szSetupPath );
dwLen = lstrlen( szPath );
szPath[ dwLen++ ] = chSlash;
dw = LoadString( g_hinstance, IDS_ALPHAPATH, &szPath[ dwLen ], ARRAYSIZE( szPath ) - dwLen );
Assert( dw );
dwCount += CopyFilesAddToQueue( Queue, g_Options.szSourcePath, szPath,
pszFiles, NULL, SP_COPY_NEWER | SP_COPY_WARNIFSKIP );
// add the processor dependant files from the INF to the Queue
GetPrivateProfileSection( TEXT("SourceDisksFiles.Alpha"), pszFiles, MAX_FILES_SIZE,
szLayoutFilename );
LayoutToDoubleNullList( pszFiles );
dwCount += CopyFilesAddToQueue( Queue, g_Options.szSourcePath, szPath,
pszFiles, NULL, SP_COPY_NEWER | SP_COPY_WARNIFSKIP );
// additional files not listed
dw = LoadString( g_hinstance, IDS_FILESTOBECOPIED, pszFiles, MAX_FILES_SIZE );
Assert( dw );
SemiColonToDoubleNullList( pszFiles );
dwCount += CopyFilesAddToQueue( Queue, g_Options.szSourcePath, szPath, pszFiles, NULL,
SP_COPY_NEWER | SP_COPY_WARNIFSKIP );
}
// add template files
if ( g_Options.fIntel )
{
TCHAR szPath[ MAX_PATH ];
DWORD dwLen;
lstrcpy( szPath, g_Options.szRemoteBootPath );
dwLen = lstrlen( szPath );
szPath[ dwLen++ ] = chSlash;
dw = LoadString( g_hinstance, IDS_TEMPLATEPATH, &szPath[ dwLen ], ARRAYSIZE( szPath ) - dwLen );
Assert( szPath );
dwLen = lstrlen( szPath );
szPath[ dwLen++ ] = chSlash;
dw = LoadString( g_hinstance, IDS_INTELPATH, &szPath[ dwLen ], ARRAYSIZE( szPath ) - dwLen );
Assert( dw );
dw = LoadString( g_hinstance, IDS_TEMPLATEFILES_INTEL, pszFiles, MAX_FILES_SIZE );
Assert( dw );
SemiColonToDoubleNullList( pszFiles );
dwCount += CopyFilesAddToQueue( Queue, g_Options.szSourcePath, szPath,
pszFiles, NULL, SP_COPY_NEWER | SP_COPY_NOOVERWRITE | SP_COPY_WARNIFSKIP );
}
if ( g_Options.fAlpha )
{
TCHAR szPath[ MAX_PATH ];
DWORD dwLen;
lstrcpy( szPath, g_Options.szRemoteBootPath );
dwLen = lstrlen( szPath );
szPath[ dwLen++ ] = chSlash;
dw = LoadString( g_hinstance, IDS_TEMPLATEPATH, &szPath[ dwLen ], ARRAYSIZE( szPath ) - dwLen );
Assert( dw );
dwLen = lstrlen( szPath );
szPath[ dwLen++ ] = chSlash;
dw = LoadString( g_hinstance, IDS_INTELPATH, &szPath[ dwLen ], ARRAYSIZE( szPath ) - dwLen );
Assert( dw );
dw = LoadString( g_hinstance, IDS_TEMPLATEFILES_ALPHA, pszFiles, MAX_FILES_SIZE );
Assert( dw );
dwCount += CopyFilesAddToQueue( Queue, g_Options.szSourcePath, szPath,
pszFiles, NULL, SP_COPY_NEWER | SP_COPY_NOOVERWRITE | SP_COPY_WARNIFSKIP );
}
/* BEGIN
ADD/REMOVE PROGRAMS SHOULD DO THIS PART
// add the services to the Queue
GetSystemDirectory( szSystemPath, MAX_PATH );
dw = LoadString( g_hinstance, IDS_SERVICESFILES, pszFiles, MAX_FILES_SIZE );
Assert( dw );
SemiColonToDoubleNullList( pszFiles );
dwCount += CopyFilesAddToQueue( Queue, g_Options.szSourcePath, szSystemPath, pszFiles, NULL,
SP_COPY_NEWER | SP_COPY_NOOVERWRITE | SP_COPY_WARNIFSKIP );
END */
// This information will be passed to CopyFileCallback() as
// the Context.
MyContext.nToBeCopied = dwCount;
MyContext.nCopied = 0;
MyContext.pContext = SetupInitDefaultQueueCallback( hDlg );
MyContext.hProg = hProg;
MyContext.hOperation = GetDlgItem( hDlg, IDC_S_OPERATION );
MyContext.dwCopyingLength =
LoadString( g_hinstance, IDS_COPYING, MyContext.szCopyingString,
ARRAYSIZE( MyContext.szCopyingString ) );
Assert( MyContext.dwCopyingLength );
// Start copying
fReturn = SetupCommitFileQueue( hDlg, Queue, (PSP_FILE_CALLBACK) CopyFilesCallback,
(PVOID) &MyContext );
Finish:
SendMessage( hProg, PBM_SETPOS, 1000, 0 );
if ( Queue )
SetupCloseFileQueue( Queue );
if ( pszFiles )
TraceFree( pszFiles );
g_Options.fError = !fReturn;
return fReturn ? S_OK : E_FAIL;
}
//
// Modifies registry entries from the SELFREG.INF resource
//
HRESULT
ModifyRegistry( HWND hDlg )
{
HRESULT hr = E_FAIL;
char szRemoteBootPath[ MAX_PATH ];
TCHAR szText[ SMALL_BUFFER_SIZE ];
STRENTRY seReg[] = {
{ "25", "%SystemRoot%" }, // NT-specific
{ "11", "%SystemRoot%\\system32" }, // NT-specific
{ "RemoteBoot", szRemoteBootPath },
};
STRTABLE stReg = { ARRAYSIZE(seReg), seReg };
HWND hProg = GetDlgItem( hDlg, IDC_P_METER );
DWORD dw;
SendMessage( hProg, PBM_SETRANGE, 0, MAKELPARAM(0, 1 ));
SendMessage( hProg, PBM_SETPOS, 0, 0 );
dw = LoadString( g_hinstance, IDS_UPDATING_REGISTRY, szText, ARRAYSIZE( szText ) );
Assert( dw );
SetWindowText( GetDlgItem( hDlg, IDC_S_OPERATION ), szText );
// fill in substitution variables
WideCharToMultiByte( CP_ACP, 0, g_Options.szRemoteBootPath, -1,
szRemoteBootPath, ARRAYSIZE( szRemoteBootPath ), NULL, NULL );
hr = THR( RegInstall( g_hinstance, "InstallRemoteBoot", &stReg) );
SendMessage( hProg, PBM_SETPOS, 1 , 0 );
return hr;
}
//
// Creates the services needed for remote boot.
//
HRESULT
StartRemoteBootServices( HWND hDlg )
{
TCHAR szTFTPD[ SMALL_BUFFER_SIZE ];
TCHAR szBINL[ SMALL_BUFFER_SIZE ];
TCHAR szTFTPDName[ SMALL_BUFFER_SIZE ];
TCHAR szBINLName[ SMALL_BUFFER_SIZE ];
TCHAR szText[ SMALL_BUFFER_SIZE ];
SC_HANDLE schSystem;
SC_HANDLE schTFTPD;
SC_HANDLE schTCPService;
DWORD dwErr = S_OK;
HWND hProg = GetDlgItem( hDlg, IDC_P_METER );
DWORD dw;
SendMessage( hProg, PBM_SETRANGE, 0, MAKELPARAM(0, 1 ));
SendMessage( hProg, PBM_SETPOS, 0, 0 );
dw = LoadString( g_hinstance, IDS_STARTING_SERVICES, szText, ARRAYSIZE( szText ) );
Assert( dw );
SetDlgItemText( hDlg, IDC_S_OPERATION, szText );
dw = LoadString( g_hinstance, IDS_TFTPD, szTFTPD,
ARRAYSIZE( szTFTPD ) );
Assert( dw );
dw = LoadString( g_hinstance, IDS_BINL, szBINL,
ARRAYSIZE( szBINL ) );
Assert( dw );
dw = LoadString( g_hinstance, IDS_TFTPD_SERVICENAME, szTFTPDName,
ARRAYSIZE( szTFTPDName ) );
Assert( dw );
dw = LoadString( g_hinstance, IDS_BINL_SERVICENAME, szBINLName,
ARRAYSIZE( szBINLName ) );
Assert( dw );
schSystem = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS );
Assert( schSystem );
if ( !schSystem )
goto Cleanup;
schTFTPD = OpenService( schSystem, szTFTPD,
STANDARD_RIGHTS_REQUIRED | SERVICE_START );
schTCPService = OpenService( schSystem, szBINL,
STANDARD_RIGHTS_REQUIRED | SERVICE_START );
// start TFTPD
if ( !StartService( schTFTPD, 0, NULL ) )
{
dwErr = GetLastError( );
switch ( dwErr )
{
default:
dw = LoadString( g_hinstance, IDS_ERROR_STARTING_SERVICE, szText,
ARRAYSIZE( szText ) );
Assert( dw );
MessageBox( hDlg, szText, szTFTPDName, MB_OK );
break;
case ERROR_SERVICE_ALREADY_RUNNING:
break;
}
}
// start TCP services
dw = LoadString( g_hinstance, IDS_STARTING_SERVICES, szText, ARRAYSIZE( szText ) );
Assert( dw );
SetDlgItemText( hDlg, IDC_S_OPERATION, szText );
if ( !StartService( schTCPService, 0, NULL ) )
{
dwErr = GetLastError( );
switch ( dwErr )
{
default:
dw = LoadString( g_hinstance, IDS_ERROR_STARTING_SERVICE, szText,
ARRAYSIZE( szText ) );
Assert( dw );
MessageBox( hDlg, szText, szBINLName, MB_OK );
break;
case ERROR_SERVICE_ALREADY_RUNNING:
break;
}
}
SendMessage( hProg, PBM_SETPOS, 1 , 0 );
Cleanup:
if ( schTCPService )
CloseServiceHandle( schTCPService );
if ( schTFTPD )
CloseServiceHandle( schTFTPD );
if ( schSystem )
CloseServiceHandle( schSystem );
return dwErr;
}
//
// create RemoteBoot share
//
HRESULT
CreateRemoteBootShare( HWND hDlg )
{
SHARE_INFO_502 si502;
TCHAR szRemark[ SMALL_BUFFER_SIZE ];
TCHAR szRemoteBoot[ SMALL_BUFFER_SIZE ];
TCHAR szText[ SMALL_BUFFER_SIZE ];
DWORD dwErr;
HWND hProg = GetDlgItem( hDlg, IDC_P_METER );
DWORD dw;
dw = LoadString( g_hinstance, IDS_CREATINGSHARES, szText, ARRAYSIZE( szText ) );
Assert( dw );
SetDlgItemText( hDlg, IDC_S_OPERATION, szText );
dw = LoadString( g_hinstance, IDS_REMOTEBOOTSHAREREMARK, szRemark,
ARRAYSIZE( szRemark ) );
Assert( dw );
dw = LoadString( g_hinstance, IDS_REMOTEBOOTSHARENAME, szRemoteBoot,
ARRAYSIZE( szRemoteBoot ) );
Assert( dw );
si502.shi502_netname = szRemoteBoot;
si502.shi502_type = STYPE_DISKTREE;
si502.shi502_remark = szRemark;
si502.shi502_permissions = ACCESS_ALL;
si502.shi502_max_uses = -1; // unlimited
si502.shi502_current_uses = 0;
si502.shi502_path = g_Options.szRemoteBootPath;
si502.shi502_passwd = NULL; // ignored
si502.shi502_reserved = 0; // must be zero
si502.shi502_security_descriptor = NULL;
NetShareAdd( NULL, 502, (LPBYTE) &si502, &dwErr );
switch ( dwErr )
{
// ignore these
case NERR_Success:
case NERR_DuplicateShare:
break;
default:
MessageBoxFromStrings( hDlg, IDS_SHAREERRORCAPTION, IDS_SHAREERRORTEXT, MB_OK );
}
SendMessage( hProg, PBM_DELTAPOS, 1 , 0 );
return dwErr;
}