Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

598 lines
25 KiB

//***************************************************************************
//* Copyright (c) Microsoft Corporation 1995-1996. All rights reserved. *
//***************************************************************************
//* *
//* NTAPI.C - *
//* *
//***************************************************************************
//***************************************************************************
//* INCLUDE FILES *
//***************************************************************************
#include "ntapi.h"
#include <winnt.h>
#include "advpack.h"
#include "advpub.h"
#include "globals.h"
#include "resource.h"
UINT WINAPI AIFSetupQueueCallback(PVOID Context, UINT Notification, UINT_PTR Param1, UINT_PTR Param2);
UINT WINAPI AIFQuietSetupQueueCallback(PVOID Context, UINT Notification, UINT_PTR Param1, UINT_PTR Param2);
UINT WINAPI MyFileQueueCallback2( PVOID Context,UINT Notification,UINT_PTR parm1,UINT_PTR parm2 );
void MakeRootDir(LPSTR pszPath);
//***************************************************************************
//* GLOBAL VARIABLES *
//***************************************************************************
PFSetupDefaultQueueCallback pfSetupDefaultQueueCallback = NULL;
PFSetupInstallFromInfSection pfSetupInstallFromInfSection = NULL;
PFSetupOpenInfFile pfSetupOpenInfFile = NULL;
PFSetupOpenAppendInfFile pfSetupOpenAppendInfFile = NULL;
PFSetupCloseInfFile pfSetupCloseInfFile = NULL;
PFSetupInitDefaultQueueCallbackEx pfSetupInitDefaultQueueCallbackEx = NULL;
PFSetupTermDefaultQueueCallback pfSetupTermDefaultQueueCallback = NULL;
PFSetupSetDirectoryId pfSetupSetDirectoryId = NULL;
PFSetupGetLineText pfSetupGetLineText = NULL;
PFSetupGetLineByIndex pfSetupGetLineByIndex = NULL;
PFSetupFindFirstLine pfSetupFindFirstLine = NULL;
PFSetupFindNextLine pfSetupFindNextLine = NULL;
PFSetupOpenFileQueue pfSetupOpenFileQueue = NULL;
PFSetupCloseFileQueue pfSetupCloseFileQueue = NULL;
PFSetupQueueCopy pfSetupQueueCopy = NULL;
PFSetupCommitFileQueue pfSetupCommitFileQueue = NULL;
PFSetupGetStringField pfSetupGetStringField = NULL;
//***************************************************************************
//* *
//* NAME: *
//* *
//* SYNOPSIS: *
//* *
//* REQUIRES: *
//* *
//* RETURNS: *
//* *
//***************************************************************************
BOOL LoadSetupAPIFuncs( VOID )
{
pfSetupGetStringField = (PFSetupGetStringField) GetProcAddress( ctx.hSetupLibrary, c_szSetupGetStringField );
pfSetupDefaultQueueCallback = (PFSetupDefaultQueueCallback) GetProcAddress( ctx.hSetupLibrary, c_szSetupDefaultQueueCallback );
pfSetupInstallFromInfSection = (PFSetupInstallFromInfSection) GetProcAddress( ctx.hSetupLibrary, c_szSetupInstallFromInfSection );
pfSetupOpenInfFile = (PFSetupOpenInfFile) GetProcAddress( ctx.hSetupLibrary, c_szSetupOpenInfFile );
pfSetupOpenAppendInfFile = (PFSetupOpenAppendInfFile) GetProcAddress( ctx.hSetupLibrary, c_szSetupOpenAppendInfFile );
pfSetupCloseInfFile = (PFSetupCloseInfFile) GetProcAddress( ctx.hSetupLibrary, c_szSetupCloseInfFile );
pfSetupInitDefaultQueueCallbackEx = (PFSetupInitDefaultQueueCallbackEx) GetProcAddress( ctx.hSetupLibrary, c_szSetupInitDefaultQueueCallbackEx );
pfSetupTermDefaultQueueCallback = (PFSetupTermDefaultQueueCallback) GetProcAddress( ctx.hSetupLibrary, c_szSetupTermDefaultQueueCallback );
pfSetupSetDirectoryId = (PFSetupSetDirectoryId) GetProcAddress( ctx.hSetupLibrary, c_szSetupSetDirectoryId );
pfSetupGetLineText = (PFSetupGetLineText) GetProcAddress( ctx.hSetupLibrary, c_szSetupGetLineText );
pfSetupGetLineByIndex = (PFSetupGetLineByIndex) GetProcAddress( ctx.hSetupLibrary, c_szSetupGetLineByIndex );
pfSetupFindFirstLine = (PFSetupFindFirstLine) GetProcAddress( ctx.hSetupLibrary, c_szSetupFindFirstLine );
pfSetupFindNextLine = (PFSetupFindNextLine) GetProcAddress( ctx.hSetupLibrary, c_szSetupFindNextLine );
pfSetupOpenFileQueue = (PFSetupOpenFileQueue) GetProcAddress( ctx.hSetupLibrary, c_szSetupOpenFileQueue );
pfSetupCloseFileQueue = (PFSetupCloseFileQueue) GetProcAddress( ctx.hSetupLibrary, c_szSetupCloseFileQueue );
pfSetupQueueCopy = (PFSetupQueueCopy) GetProcAddress( ctx.hSetupLibrary, c_szSetupQueueCopy );
pfSetupCommitFileQueue = (PFSetupCommitFileQueue) GetProcAddress( ctx.hSetupLibrary, c_szSetupCommitFileQueue );
if (pfSetupDefaultQueueCallback == NULL
|| pfSetupInstallFromInfSection == NULL
|| pfSetupOpenInfFile == NULL
|| pfSetupCloseInfFile == NULL
|| pfSetupInitDefaultQueueCallbackEx == NULL
|| pfSetupTermDefaultQueueCallback == NULL
|| pfSetupSetDirectoryId == NULL
|| pfSetupGetLineText == NULL
|| pfSetupGetLineByIndex == NULL
|| pfSetupFindFirstLine == NULL
|| pfSetupFindNextLine == NULL
|| pfSetupOpenFileQueue == NULL
|| pfSetupCloseFileQueue == NULL
|| pfSetupQueueCopy == NULL
|| pfSetupCommitFileQueue == NULL
|| pfSetupGetStringField == NULL )
{
return FALSE;
}
return TRUE;
}
//***************************************************************************
//* *
//* NAME: InstallOnNT *
//* *
//* SYNOPSIS: This function will make all the calls to WinNT SUR's *
//* SETUPAPI.DLL to do the installation on NT SUR. *
//* *
//* REQUIRES: pszSection: Section to install *
//* pszSourceDir: Directory to CABs or expanded files *
//* *
//* RETURNS: *
//* *
//***************************************************************************
HRESULT InstallOnNT( PSTR pszSection, PSTR pszSourceDir )
{
PVOID pContext = NULL;
HRESULT hReturnCode = S_OK;
HSPFILEQ hFileQueue = NULL;
UINT uFlags;
// Install Files
// Setup Context data structure initialized for us for default UI provided by Setup API.
pContext = pfSetupInitDefaultQueueCallbackEx( NULL, (ctx.wQuietMode) ?
INVALID_HANDLE_VALUE : NULL,
0, 0, NULL );
if ( pContext == NULL ) {
hReturnCode = HRESULT_FROM_SETUPAPI(GetLastError());
goto done;
}
if ( ! pfSetupInstallFromInfSection( NULL, ctx.hInf, pszSection, SPINST_FILES, NULL,
pszSourceDir, SP_COPY_NEWER,
MyFileQueueCallback2,
pContext, NULL, NULL ) )
{
hReturnCode = HRESULT_FROM_SETUPAPI(GetLastError());
pfSetupTermDefaultQueueCallback( pContext );
goto done;
}
// Free Context Data structure
pfSetupTermDefaultQueueCallback( pContext );
uFlags = SPINST_REGISTRY | SPINST_INIFILES;
if ( ctx.wOSVer >= _OSVER_WINNT50 )
uFlags = uFlags | SPINST_PROFILEITEMS;
// Install registry entries
if ( ! pfSetupInstallFromInfSection( NULL, ctx.hInf, pszSection,
uFlags,
HKEY_LOCAL_MACHINE, NULL, 0, NULL,
NULL, NULL, NULL ) )
{
hReturnCode = HRESULT_FROM_SETUPAPI(GetLastError());
goto done;
}
done:
return hReturnCode;
}
//***************************************************************************
//* *
//* NAME: MySetupOpenInfFile *
//* *
//* SYNOPSIS: This function will map to a function in setupapi.dll which *
//* will open the INF file. *
//* *
//* REQUIRES: pszInfFilename: *
//* *
//* RETURNS: DWORD: Return value - OK means successfull. *
//* *
//***************************************************************************
HRESULT MySetupOpenInfFile( PCSTR pszInfFilename )
{
UINT line;
if ( ctx.hInf == NULL )
{
ctx.hInf = pfSetupOpenInfFile( pszInfFilename, NULL, INF_STYLE_WIN4, NULL );
if ( ctx.hInf == NULL || ctx.hInf == INVALID_HANDLE_VALUE )
{
ctx.hInf = NULL;
return HRESULT_FROM_SETUPAPI(GetLastError());
}
// process LayoutFile line of [version] section if any
pfSetupOpenAppendInfFile( NULL, ctx.hInf, &line );
}
return S_OK;
}
//***************************************************************************
//* *
//* NAME: MySetupCloseInfFile *
//* *
//* SYNOPSIS: This function will map to an API function in setupapi.dll. *
//* *
//* REQUIRES: *
//* *
//* RETURNS: VOID *
//* *
//***************************************************************************
VOID MySetupCloseInfFile( VOID )
{
if ( ctx.hInf )
{
pfSetupCloseInfFile( ctx.hInf );
ctx.hInf = NULL;
}
}
//***************************************************************************
//* *
//* NAME: MySetupSetDirectoryId *
//* *
//* SYNOPSIS: This function will map to a function in setupapi.dll to *
//* set the directory ID's that are used in our INF. *
//* *
//* REQUIRES: dwDirID: Numerical value used to define the DirID *
//* pszPath: DirID will point to this path. *
//* *
//* RETURNS: DWORD: Error value (OK if successfull) *
//* *
//***************************************************************************
HRESULT MySetupSetDirectoryId( DWORD dwDirID, PSTR pszPath )
{
if ( ! pfSetupSetDirectoryId( ctx.hInf, dwDirID, pszPath ) ) {
return HRESULT_FROM_SETUPAPI(GetLastError());
}
return S_OK;
}
//***************************************************************************
//* *
//* NAME: MySetupGetLineText *
//* *
//* SYNOPSIS: *
//* *
//* REQUIRES: *
//* *
//* RETURNS: *
//* *
//***************************************************************************
HRESULT MySetupGetLineText( PCSTR pszSection, PCSTR pszKey, PSTR pszReturnBuffer,
DWORD dwReturnBufferSize, PDWORD pdwRequiredSize )
{
if ( ! pfSetupGetLineText( NULL, ctx.hInf, pszSection, pszKey,
pszReturnBuffer, dwReturnBufferSize,
pdwRequiredSize ) )
{
return HRESULT_FROM_SETUPAPI(GetLastError());
}
return S_OK;
}
//***************************************************************************
//* *
//* NAME: MySetupGetLineByIndex *
//* *
//* SYNOPSIS: *
//* *
//* REQUIRES: *
//* *
//* RETURNS: *
//* *
//***************************************************************************
HRESULT MySetupGetLineByIndex( PCSTR c_pszSection, DWORD dwIndex,
PSTR pszBuffer, DWORD dwBufferSize,
PDWORD pdwRequiredSize )
{
HRESULT hReturnCode = S_OK;
INFCONTEXT InfContext;
DWORD i = 0;
if ( ! pfSetupFindFirstLine( ctx.hInf, c_pszSection, NULL, &InfContext ) ) {
hReturnCode = HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS);
goto done;
}
for ( i = 0; i < dwIndex; i += 1 ) {
if ( !pfSetupFindNextLine( &InfContext, &InfContext ) ) {
hReturnCode = HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS);
goto done;
}
}
#if 0
if ( ! pfSetupGetLineByIndex( ctx.hInf, c_pszSection, dwIndex, &InfContext ) )
{
hReturnCode = HRESULT_FROM_SETUPAPI(GetLastError());
goto done;
}
#endif
if ( ! pfSetupGetLineText( &InfContext, NULL, NULL, NULL,
pszBuffer, dwBufferSize, pdwRequiredSize ) )
{
hReturnCode = HRESULT_FROM_SETUPAPI(GetLastError());
goto done;
}
done:
return hReturnCode;
}
//***************************************************************************
//* *
//* NAME: MySetupGetStringField *
//* *
//* SYNOPSIS: *
//* *
//* REQUIRES: *
//* *
//* RETURNS: *
//* *
//***************************************************************************
HRESULT MySetupGetStringField( PCSTR c_pszSection, DWORD dwLineIndex, DWORD dwFieldIndex,
PSTR pszBuffer, DWORD dwBufferSize, PDWORD pdwRequiredSize )
{
HRESULT hReturnCode = S_OK;
INFCONTEXT InfContext;
DWORD i = 0;
if ( !pfSetupFindFirstLine( ctx.hInf, c_pszSection, NULL, &InfContext ) ) {
hReturnCode = HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS);
goto done;
}
for ( i = 0; i < dwLineIndex; i += 1 )
{
if ( !pfSetupFindNextLine( &InfContext, &InfContext ) )
{
hReturnCode = HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS);
goto done;
}
}
if ( !pfSetupGetStringField( &InfContext, dwFieldIndex,
pszBuffer, dwBufferSize, pdwRequiredSize ) )
{
hReturnCode = HRESULT_FROM_SETUPAPI(GetLastError());
goto done;
}
done:
return hReturnCode;
}
HRESULT WINAPI AdvInstallFile(HWND hwnd, LPCSTR lpszSourceDir, LPCSTR lpszSourceFile,
LPCSTR lpszDestDir, LPCSTR lpszDestFile, DWORD dwFlags, DWORD dwReserved)
{
HRESULT hr = E_FAIL;
HSPFILEQ FileQueue;
char szSrcDrv[MAX_PATH];
LPCSTR lpSrcPath;
LPVOID lpContext;
DWORD dwCopyFlags;
DWORD dwRebootCheck;
if ( (lpszSourceDir == NULL) || (*lpszSourceDir == '\0') ||
(lpszSourceFile == NULL) || (*lpszSourceFile == '\0') ||
(lstrlen(lpszSourceDir) < 3) ||
(lpszDestDir == NULL) )
return E_INVALIDARG;
if (!SaveGlobalContext())
return hr;
ctx.hWnd = hwnd;
if ( !CheckOSVersion() )
{
RestoreGlobalContext();
return HRESULT_FROM_WIN32(ERROR_OLD_WIN_VERSION);
}
dwRebootCheck = InternalNeedRebootInit( ctx.wOSVer );
// LoadLibrary for setupapi.dll
ctx.hSetupLibrary = MyLoadLibrary( SETUPAPIDLL );
if ( ctx.hSetupLibrary == NULL )
{
ErrorMsg1Param( NULL, IDS_ERR_LOAD_DLL, SETUPAPIDLL );
hr = HRESULT_FROM_WIN32(ERROR_DLL_NOT_FOUND);
goto Cleanup;
}
if ( ! LoadSetupAPIFuncs() )
{
ErrorMsg( NULL, IDS_ERR_GET_PROC_ADDR );
hr = HRESULT_FROM_WIN32(ERROR_PROC_NOT_FOUND);
goto Cleanup;
}
// SetupOpenFileQueue
FileQueue = pfSetupOpenFileQueue();
if (FileQueue == INVALID_HANDLE_VALUE)
{
ErrorMsg1Param( NULL, IDS_ERR_LOAD_DLL, c_szSetupOpenFileQueue );
hr = HRESULT_FROM_SETUPAPI(GetLastError());
goto Cleanup;
}
lstrcpy(szSrcDrv, lpszSourceDir);
MakeRootDir(szSrcDrv);
lpSrcPath = lpszSourceDir + lstrlen(szSrcDrv); // This will point to the first subdir.
dwCopyFlags = SP_COPY_SOURCE_ABSOLUTE |
SP_COPY_IN_USE_NEEDS_REBOOT|
SP_COPY_NEWER |
SP_COPY_LANGUAGEAWARE;
if (dwFlags & AIF_FORCE_FILE_IN_USE)
dwCopyFlags |= SP_COPY_FORCE_IN_USE;
if (dwFlags & AIF_NOVERSIONCHECK)
dwCopyFlags &= ~SP_COPY_NEWER;
if (dwFlags & AIF_NOLANGUAGECHECK)
dwCopyFlags &= ~SP_COPY_LANGUAGEAWARE;
if (dwFlags & AIF_NO_VERSION_DIALOG)
dwCopyFlags |= SP_COPY_FORCE_NEWER;
if (dwFlags & AIF_REPLACEONLY)
dwCopyFlags |= SP_COPY_REPLACEONLY;
if (dwFlags & AIF_NOOVERWRITE)
dwCopyFlags |= SP_COPY_NOOVERWRITE;
if (dwFlags & AIF_NOSKIP)
dwCopyFlags |= SP_COPY_NOSKIP;
if (dwFlags & AIF_WARNIFSKIP)
dwCopyFlags |= SP_COPY_WARNIFSKIP;
if (pfSetupQueueCopy(FileQueue,
szSrcDrv,
lpSrcPath,
lpszSourceFile,
NULL,
NULL,
lpszDestDir,
lpszDestFile,
dwCopyFlags))
{
lpContext = pfSetupInitDefaultQueueCallbackEx(hwnd, INVALID_HANDLE_VALUE, 0, 0, NULL);
hr = S_OK;
//
// SetupCommitFileQueue
if (!pfSetupCommitFileQueue( hwnd, FileQueue,
(dwFlags & AIF_QUIET)?AIFQuietSetupQueueCallback:AIFSetupQueueCallback,
lpContext))
{
hr = HRESULT_FROM_SETUPAPI(GetLastError());
}
pfSetupTermDefaultQueueCallback(lpContext);
}
else
hr = HRESULT_FROM_SETUPAPI(GetLastError());
// SetupCloseFileQueue
pfSetupCloseFileQueue(FileQueue);
if ( SUCCEEDED(hr) &&
InternalNeedReboot( dwRebootCheck, ctx.wOSVer ) )
{
hr = ERROR_SUCCESS_REBOOT_REQUIRED;
}
Cleanup:
RestoreGlobalContext();
return hr;
}
// This callback will display error messages, but will not show any progress dialog
UINT WINAPI AIFSetupQueueCallback(PVOID Context, // context used by the default callback routine
UINT Notification, // queue notification
UINT_PTR Param1, // additional notification information
UINT_PTR Param2 // additional notification information
)
{
switch (Notification)
{
case SPFILENOTIFY_STARTQUEUE:
case SPFILENOTIFY_ENDQUEUE:
case SPFILENOTIFY_STARTSUBQUEUE:
case SPFILENOTIFY_ENDSUBQUEUE:
case SPFILENOTIFY_STARTRENAME:
case SPFILENOTIFY_ENDRENAME:
case SPFILENOTIFY_STARTDELETE:
case SPFILENOTIFY_ENDDELETE:
case SPFILENOTIFY_STARTCOPY:
case SPFILENOTIFY_ENDCOPY:
return FILEOP_DOIT;
default:
return (pfSetupDefaultQueueCallback(Context, Notification, Param1, Param2));
}
}
// This callback will not display any dialog
UINT WINAPI AIFQuietSetupQueueCallback(PVOID Context, // context used by the default callback routine
UINT Notification, // queue notification
UINT_PTR Param1, // additional notification information
UINT_PTR Param2 // additional notification information
)
{
return FILEOP_DOIT;
}
UINT WINAPI MyFileQueueCallback2( PVOID Context,UINT Notification,UINT_PTR parm1,UINT_PTR parm2 )
{
switch(Notification)
{
case SPFILENOTIFY_NEEDMEDIA:
{
CHAR szDrv[5];
PSOURCE_MEDIA psrcMed;
psrcMed = (PSOURCE_MEDIA)parm1;
if ( lstrlen( psrcMed->SourcePath ) > 3 )
{
lstrcpyn( szDrv, psrcMed->SourcePath, 4 );
if ( (szDrv[1] == ':') && (GetDriveType( szDrv ) == DRIVE_REMOVABLE) )
{
CHAR szFile[MAX_PATH];
lstrcpy( szFile, psrcMed->SourcePath );
if ( psrcMed->Tagfile && *psrcMed->Tagfile )
AddPath( szFile, psrcMed->Tagfile );
else
AddPath( szFile, psrcMed->SourceFile );
if ( FileExists( szFile ) )
{
lstrcpy( (PSTR)parm2, psrcMed->SourcePath );
return ( FILEOP_NEWPATH );
}
}
}
}
default:
return ( pfSetupDefaultQueueCallback( Context, Notification, parm1, parm2 ) );
}
}
void MakeRootDir(LPSTR pszPath)
{
LPSTR pTmp;
if (pszPath[1] == ':')
pszPath[3] = '\0';
else if ((pszPath[0] == '\\') && (pszPath[1]=='\\'))
{
pTmp = &pszPath[2];
// Find the sever share separation
while ((*pTmp) && (*pTmp != '\\'))
pTmp = CharNext(pTmp);
if (*pTmp)
{
pTmp = CharNext(pTmp);
// Find the end of the share
while ((*pTmp) && (*pTmp != '\\'))
pTmp = CharNext(pTmp);
if (*pTmp == '\\')
{
pTmp = CharNext(pTmp);
*pTmp ='\0';
}
}
}
}