|
|
/****************************************************************************
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; }
|