2000-01-29 22:09:02 +01:00
/*
* SETUPX library
*
2000-09-27 00:46:36 +02:00
* Copyright 1998 , 2000 Andreas Mohr
2000-01-29 22:09:02 +01:00
*
* FIXME : Rather non - functional functions for now .
2000-09-27 00:46:36 +02:00
*
* See :
* http : //www.geocities.com/SiliconValley/Network/5317/drivers.html
2000-11-04 03:57:18 +01:00
* http : //willemer.de/informatik/windows/inf_info.htm (German)
2000-09-27 00:46:36 +02:00
* http : //www.microsoft.com/ddk/ddkdocs/win98ddk/devinst_12uw.htm
* DDK : setupx . h
* http : //mmatrix.tripod.com/customsystemfolder/infsysntaxfull.html
* http : //www.rdrop.com/~cary/html/inf_faq.html
2000-12-13 22:31:37 +01:00
* http : //support.microsoft.com/support/kb/articles/q194/6/40.asp
2000-09-27 00:46:36 +02:00
*
2000-11-29 00:50:34 +01:00
* Stuff tested with :
* - rs405deu . exe ( German Acroread 4.05 setup )
* - ie5setup . exe
* - Netmeeting
*
* FIXME :
2000-12-13 22:31:37 +01:00
* - string handling is . . . weird ; ) ( buflen etc . )
* - memory leaks ?
* - separate that mess ( but probably only when it ' s done completely )
*
* SETUPX consists of several parts with the following acronyms / prefixes :
* Di device installer ( devinst . c ? )
* Gen generic installer ( geninst . c ? )
* Ip . INF parsing ( infparse . c )
* LDD logical device descriptor ( ldd . c ? )
2001-09-11 02:32:32 +02:00
* LDID logical device ID
2000-12-13 22:31:37 +01:00
* SU setup ( setup . c ? )
* Tp text processing ( textproc . c ? )
* Vcp virtual copy module ( vcp . c ? )
* . . .
*
* The SETUPX DLL is NOT thread - safe . That ' s why many installers urge you to
* " close all open applications " .
* All in all the design of it seems to be a bit weak .
* Not sure whether my implementation of it is better , though ; - )
2000-01-29 22:09:02 +01:00
*/
2000-11-04 03:57:18 +01:00
# include <stdlib.h>
2000-11-29 00:50:34 +01:00
# include <stdio.h>
2001-01-22 03:17:29 +01:00
# include <string.h>
2000-09-27 00:20:14 +02:00
# include "winreg.h"
# include "wine/winuser16.h"
2000-09-27 00:46:36 +02:00
# include "setupx16.h"
2001-04-17 19:39:35 +02:00
# include "setupapi_private.h"
2000-11-04 03:57:18 +01:00
# include "winerror.h"
2000-01-29 22:09:02 +01:00
# include "debugtools.h"
2001-04-17 19:39:35 +02:00
DEFAULT_DEBUG_CHANNEL ( setupapi ) ;
2000-01-29 22:09:02 +01:00
2000-03-28 22:22:59 +02:00
/***********************************************************************
2001-06-19 20:20:47 +02:00
* SURegOpenKey ( SETUPX .47 )
2000-03-28 22:22:59 +02:00
*/
2000-01-29 22:09:02 +01:00
DWORD WINAPI SURegOpenKey ( HKEY hkey , LPCSTR lpszSubKey , LPHKEY retkey )
{
FIXME ( " (%x,%s,%p), semi-stub. \n " , hkey , debugstr_a ( lpszSubKey ) , retkey ) ;
return RegOpenKeyA ( hkey , lpszSubKey , retkey ) ;
}
2000-03-28 22:22:59 +02:00
/***********************************************************************
2001-06-19 20:20:47 +02:00
* SURegQueryValueEx ( SETUPX .50 )
2000-03-28 22:22:59 +02:00
*/
2000-01-29 22:09:02 +01:00
DWORD WINAPI SURegQueryValueEx ( HKEY hkey , LPSTR lpszValueName ,
LPDWORD lpdwReserved , LPDWORD lpdwType ,
LPBYTE lpbData , LPDWORD lpcbData )
{
FIXME ( " (%x,%s,%p,%p,%p,%ld), semi-stub. \n " , hkey , debugstr_a ( lpszValueName ) ,
lpdwReserved , lpdwType , lpbData , lpcbData ? * lpcbData : 0 ) ;
return RegQueryValueExA ( hkey , lpszValueName , lpdwReserved , lpdwType ,
lpbData , lpcbData ) ;
}
2000-07-23 16:20:34 +02:00
2000-12-13 22:31:37 +01:00
/*
* Returns pointer to a string list with the first entry being number
* of strings .
*
* Hmm . Should this be InitSubstrData ( ) , GetFirstSubstr ( ) and GetNextSubstr ( )
* instead ?
*/
static LPSTR * SETUPX_GetSubStrings ( LPSTR start , char delimiter )
{
LPSTR p , q ;
LPSTR * res = NULL ;
DWORD count = 0 ;
int len ;
p = start ;
while ( 1 )
{
/* find beginning of real substring */
while ( ( * p = = ' ' ) | | ( * p = = ' \t ' ) | | ( * p = = ' " ' ) ) p + + ;
/* find end of real substring */
q = p ;
while ( ( * q )
& & ( * q ! = ' ' ) & & ( * q ! = ' \t ' ) & & ( * q ! = ' " ' )
& & ( * q ! = ' ; ' ) & & ( * q ! = delimiter ) ) q + + ;
if ( q = = p )
break ;
len = ( int ) q - ( int ) p ;
/* alloc entry for new substring in steps of 32 units and copy over */
if ( count % 32 = = 0 )
{ /* 1 for count field + current count + 32 */
res = HeapReAlloc ( GetProcessHeap ( ) , 0 , res , ( 1 + count + 32 ) * sizeof ( LPSTR ) ) ;
}
* ( res + 1 + count ) = HeapAlloc ( GetProcessHeap ( ) , 0 , len + 1 ) ;
strncpy ( * ( res + 1 + count ) , p , len ) ;
( * ( res + 1 + count ) ) [ len ] = ' \0 ' ;
count + + ;
/* we are still within last substring (before delimiter),
* so get out of it */
while ( ( * q ) & & ( * q ! = ' ; ' ) & & ( * q ! = delimiter ) ) q + + ;
if ( ( ! * q ) | | ( * q = = ' ; ' ) )
break ;
p = q + 1 ;
}
2001-09-11 02:32:32 +02:00
2000-12-13 22:31:37 +01:00
/* put number of entries at beginning of list */
* ( DWORD * ) res = count ;
return res ;
}
static void SETUPX_FreeSubStrings ( LPSTR * substr )
{
DWORD count = * ( DWORD * ) substr ;
LPSTR * pStrings = substr + 1 ;
DWORD n ;
for ( n = 0 ; n < count ; n + + )
HeapFree ( GetProcessHeap ( ) , 0 , * pStrings + + ) ;
HeapFree ( GetProcessHeap ( ) , 0 , substr ) ;
}
static void SETUPX_IsolateSubString ( LPSTR * begin , LPSTR * end )
{
LPSTR p , q ;
p = * begin ;
q = * end ;
while ( ( p < q ) & & ( ( * p = = ' ' ) | | ( * p = = ' \t ' ) ) ) p + + ;
while ( ( p < q ) & & ( * p = = ' " ' ) ) p + + ;
while ( ( q - 1 > = p ) & & ( ( * ( q - 1 ) = = ' ' ) | | ( * ( q - 1 ) = = ' \t ' ) ) ) q - - ;
while ( ( q - 1 > = p ) & & ( * ( q - 1 ) = = ' " ' ) ) q - - ;
* begin = p ;
* end = q ;
}
/*
* Example : HKLM , " Software \ Microsoft \ Windows \ CurrentVersion " , " ProgramFilesDir " , , " C: \"
* FIXME : use SETUPX_GetSubStrings ( ) instead .
* Hmm , but on the other hand SETUPX_GetSubStrings ( ) will probably
* soon be replaced by InitSubstrData ( ) etc . anyway .
2001-09-11 02:32:32 +02:00
*
2000-12-13 22:31:37 +01:00
*/
static BOOL SETUPX_LookupRegistryString ( LPSTR regstr , LPSTR buffer , DWORD buflen )
{
HANDLE heap = GetProcessHeap ( ) ;
LPSTR items [ 5 ] ;
LPSTR p , q , next ;
int len , n ;
HKEY hkey , hsubkey ;
DWORD dwType ;
TRACE ( " retrieving '%s' \n " , regstr ) ;
p = regstr ;
/* isolate root key, subkey, value, flag, defval */
for ( n = 0 ; n < 5 ; n + + )
{
q = strchr ( p , ' , ' ) ;
if ( ! q )
{
if ( n = = 4 )
q = p + strlen ( p ) ;
else
return FALSE ;
}
next = q + 1 ;
if ( q < regstr )
return FALSE ;
SETUPX_IsolateSubString ( & p , & q ) ;
len = ( int ) q - ( int ) p ;
items [ n ] = HeapAlloc ( heap , 0 , len + 1 ) ;
strncpy ( items [ n ] , p , len ) ;
items [ n ] [ len ] = ' \0 ' ;
p = next ;
}
TRACE ( " got '%s','%s','%s','%s','%s' \n " ,
items [ 0 ] , items [ 1 ] , items [ 2 ] , items [ 3 ] , items [ 4 ] ) ;
2001-09-11 02:32:32 +02:00
2000-12-13 22:31:37 +01:00
/* check root key */
if ( ! strcasecmp ( items [ 0 ] , " HKCR " ) )
hkey = HKEY_CLASSES_ROOT ;
else
if ( ! strcasecmp ( items [ 0 ] , " HKCU " ) )
hkey = HKEY_CURRENT_USER ;
else
if ( ! strcasecmp ( items [ 0 ] , " HKLM " ) )
hkey = HKEY_LOCAL_MACHINE ;
else
if ( ! strcasecmp ( items [ 0 ] , " HKU " ) )
hkey = HKEY_USERS ;
else
{ /* HKR ? -> relative to key passed to GenInstallEx */
FIXME ( " unsupported regkey '%s' \n " , items [ 0 ] ) ;
goto regfailed ;
}
if ( RegOpenKeyA ( hkey , items [ 1 ] , & hsubkey ) ! = ERROR_SUCCESS )
goto regfailed ;
if ( RegQueryValueExA ( hsubkey , items [ 2 ] , NULL , & dwType , buffer , & buflen )
! = ERROR_SUCCESS )
goto regfailed ;
goto done ;
regfailed :
if ( buffer ) strcpy ( buffer , items [ 4 ] ) ; /* I don't care about buflen */
done :
for ( n = 0 ; n < 5 ; n + + )
HeapFree ( heap , 0 , items [ n ] ) ;
if ( buffer )
TRACE ( " return '%s' \n " , buffer ) ;
return TRUE ;
}
static LPSTR SETUPX_GetSections ( LPCSTR filename )
{
LPSTR buf = NULL ;
DWORD len = 1024 , res ;
do {
buf = HeapReAlloc ( GetProcessHeap ( ) , 0 , buf , len ) ;
res = GetPrivateProfileStringA ( NULL , NULL , NULL , buf , len , filename ) ;
len * = 2 ;
} while ( ( ! res ) & & ( len < 1048576 ) ) ;
if ( ! res )
{
HeapFree ( GetProcessHeap ( ) , 0 , buf ) ;
return NULL ;
}
return buf ;
}
static LPSTR SETUPX_GetSectionEntries ( LPCSTR filename , LPCSTR section )
{
LPSTR buf = NULL ;
DWORD len = 1024 , res ;
do {
buf = HeapReAlloc ( GetProcessHeap ( ) , 0 , buf , len ) ;
res = GetPrivateProfileSectionA ( section , buf , len , filename ) ;
len * = 2 ;
} while ( ( ! res ) & & ( len < 1048576 ) ) ;
if ( ! res )
{
HeapFree ( GetProcessHeap ( ) , 0 , buf ) ;
return NULL ;
}
return buf ;
}
2000-12-02 00:54:51 +01:00
/***********************************************************************
2001-07-11 20:56:41 +02:00
* InstallHinfSection ( SETUPX .527 )
2000-12-02 00:54:51 +01:00
*
2000-07-23 16:20:34 +02:00
* hwnd = parent window
* hinst = instance of SETUPX . DLL
* lpszCmdLine = e . g . " DefaultInstall 132 C: \ MYINSTALL \ MYDEV.INF "
* Here " DefaultInstall " is the . inf file section to be installed ( optional ) .
2000-12-13 22:31:37 +01:00
* The 132 value is made of the HOW_xxx flags and sometimes 128 ( - > setupx16 . h ) .
2001-09-11 02:32:32 +02:00
*
2000-07-23 16:20:34 +02:00
* nCmdShow = nCmdShow of CreateProcess
*/
2000-12-13 22:31:37 +01:00
RETERR16 WINAPI InstallHinfSection16 ( HWND16 hwnd , HINSTANCE16 hinst , LPCSTR lpszCmdLine , INT16 nCmdShow )
2000-07-23 16:20:34 +02:00
{
2000-12-13 22:31:37 +01:00
LPSTR * pSub ;
DWORD count ;
HINF16 hInf = 0 ;
2001-04-17 19:39:35 +02:00
RETERR16 res = OK , tmp ;
2000-12-13 22:31:37 +01:00
WORD wFlags ;
BOOL reboot = FALSE ;
2001-09-11 02:32:32 +02:00
2000-12-13 22:31:37 +01:00
TRACE ( " (%04x, %04x, %s, %d); \n " , hwnd , hinst , lpszCmdLine , nCmdShow ) ;
2001-09-11 02:32:32 +02:00
2000-12-13 22:31:37 +01:00
pSub = SETUPX_GetSubStrings ( ( LPSTR ) lpszCmdLine , ' ' ) ;
count = * ( DWORD * ) pSub ;
if ( count < 2 ) /* invalid number of arguments ? */
goto end ;
if ( IpOpen16 ( * ( pSub + count ) , & hInf ) ! = OK )
{
res = ERROR_FILE_NOT_FOUND ; /* yes, correct */
goto end ;
}
2001-04-17 19:39:35 +02:00
if ( VcpOpen16 ( NULL , 0 ) )
goto end ;
2000-12-13 22:31:37 +01:00
if ( GenInstall16 ( hInf , * ( pSub + count - 2 ) , GENINSTALL_DO_ALL ) ! = OK )
goto end ;
wFlags = atoi ( * ( pSub + count - 1 ) ) & ~ 128 ;
switch ( wFlags )
{
case HOW_ALWAYS_SILENT_REBOOT :
case HOW_SILENT_REBOOT :
reboot = TRUE ;
break ;
case HOW_ALWAYS_PROMPT_REBOOT :
case HOW_PROMPT_REBOOT :
2001-09-19 22:34:17 +02:00
if ( MessageBoxA ( hwnd , " You must restart Wine before the new settings will take effect. \n \n Do you want to exit Wine now ? " , " Systems Settings Change " , MB_YESNO | MB_ICONQUESTION ) = = IDYES )
reboot = TRUE ;
2000-12-13 22:31:37 +01:00
break ;
default :
ERR ( " invalid flags %d ! \n " , wFlags ) ;
goto end ;
}
2001-09-11 02:32:32 +02:00
2000-12-13 22:31:37 +01:00
res = OK ;
end :
2001-04-17 19:39:35 +02:00
tmp = VcpClose16 ( VCPFL_ALL , NULL ) ;
if ( tmp ! = OK )
res = tmp ;
tmp = IpClose16 ( hInf ) ;
if ( tmp ! = OK )
res = tmp ;
2000-12-13 22:31:37 +01:00
SETUPX_FreeSubStrings ( pSub ) ;
if ( reboot )
{
/* FIXME: we should have a means of terminating all wine + wineserver */
MESSAGE ( " Program or user told me to restart. Exiting Wine... \n " ) ;
ExitProcess ( 1 ) ;
}
return res ;
2000-09-27 00:46:36 +02:00
}
2000-11-04 03:57:18 +01:00
typedef struct
{
LPCSTR RegValName ;
LPCSTR StdString ; /* fallback string; sub dir of windows directory */
} LDID_DATA ;
2000-11-29 00:50:34 +01:00
static const LDID_DATA LDID_Data [ 34 ] =
2000-11-04 03:57:18 +01:00
{
{ /* 0 (LDID_NULL) -- not defined */
NULL ,
NULL
} ,
{ /* 1 (LDID_SRCPATH) = source of installation. hmm, what to do here ? */
" SourcePath " , /* hmm, does SETUPX have to care about updating it ?? */
NULL
} ,
{ /* 2 (LDID_SETUPTEMP) = setup temp dir */
" SetupTempDir " ,
NULL
} ,
{ /* 3 (LDID_UNINSTALL) = uninstall backup dir */
" UninstallDir " ,
NULL
} ,
{ /* 4 (LDID_BACKUP) = backup dir */
" BackupDir " ,
NULL
} ,
{ /* 5 (LDID_SETUPSCRATCH) = setup scratch dir */
" SetupScratchDir " ,
NULL
} ,
{ /* 6 -- not defined */
NULL ,
NULL
} ,
{ /* 7 -- not defined */
NULL ,
NULL
} ,
{ /* 8 -- not defined */
NULL ,
NULL
} ,
{ /* 9 -- not defined */
NULL ,
NULL
} ,
{ /* 10 (LDID_WIN) = windows dir */
" WinDir " ,
" "
} ,
{ /* 11 (LDID_SYS) = system dir */
" SysDir " ,
NULL /* call GetSystemDirectory() instead */
} ,
{ /* 12 (LDID_IOS) = IOSubSys dir */
NULL , /* FIXME: registry string ? */
" SYSTEM \\ IOSUBSYS "
} ,
{ /* 13 (LDID_CMD) = COMMAND dir */
NULL , /* FIXME: registry string ? */
" COMMAND "
} ,
{ /* 14 (LDID_CPL) = control panel dir */
NULL ,
" "
} ,
{ /* 15 (LDID_PRINT) = windows printer dir */
NULL ,
" SYSTEM " /* correct ?? */
} ,
{ /* 16 (LDID_MAIL) = destination mail dir */
NULL ,
" "
} ,
{ /* 17 (LDID_INF) = INF dir */
" SetupScratchDir " , /* correct ? */
" INF "
} ,
{ /* 18 (LDID_HELP) = HELP dir */
NULL , /* ??? */
" HELP "
} ,
{ /* 19 (LDID_WINADMIN) = Admin dir */
" WinAdminDir " ,
" "
} ,
{ /* 20 (LDID_FONTS) = Fonts dir */
NULL , /* ??? */
" FONTS "
} ,
{ /* 21 (LDID_VIEWERS) = Viewers */
NULL , /* ??? */
" SYSTEM \\ VIEWERS "
} ,
{ /* 22 (LDID_VMM32) = VMM32 dir */
NULL , /* ??? */
" SYSTEM \\ VMM32 "
} ,
{ /* 23 (LDID_COLOR) = ICM dir */
" ICMPath " ,
" SYSTEM \\ COLOR "
} ,
{ /* 24 (LDID_APPS) = root of boot drive ? */
" AppsDir " ,
" C: \\ "
} ,
{ /* 25 (LDID_SHARED) = shared dir */
" SharedDir " ,
" "
} ,
{ /* 26 (LDID_WINBOOT) = Windows boot dir */
" WinBootDir " ,
" "
} ,
{ /* 27 (LDID_MACHINE) = machine specific files */
" MachineDir " ,
NULL
} ,
{ /* 28 (LDID_HOST_WINBOOT) = Host Windows boot dir */
" HostWinBootDir " ,
NULL
} ,
{ /* 29 -- not defined */
NULL ,
NULL
} ,
{ /* 30 (LDID_BOOT) = Root of boot drive */
" BootDir " ,
NULL
} ,
{ /* 31 (LDID_BOOT_HOST) = Root of boot drive host */
" BootHost " ,
NULL
} ,
{ /* 32 (LDID_OLD_WINBOOT) = subdir of root */
" OldWinBootDir " ,
NULL
} ,
{ /* 33 (LDID_OLD_WIN) = old win dir */
" OldWinDir " ,
NULL
}
/* the rest (34-38) isn't too interesting, so I'll forget about it */
} ;
2000-09-27 00:46:36 +02:00
2001-09-11 02:32:32 +02:00
/*
2000-12-13 22:31:37 +01:00
* LDD = = Logical Device Descriptor
* LDID = = Logical Device ID
*
* The whole LDD / LDID business might go into a separate file named
2001-04-17 19:39:35 +02:00
* ldd . c .
2000-12-13 22:31:37 +01:00
* At the moment I don ' t know what the hell these functions are really doing .
* That ' s why I added reporting stubs .
* The only thing I do know is that I need them for the LDD / LDID infrastructure .
* That ' s why I implemented them in a way that ' s suitable for my purpose .
*/
static LDD_LIST * pFirstLDD = NULL ;
static BOOL std_LDDs_done = FALSE ;
void SETUPX_CreateStandardLDDs ( void )
2000-11-29 00:50:34 +01:00
{
2000-12-13 22:31:37 +01:00
HKEY hKey = 0 ;
WORD n ;
DWORD type , len ;
LOGDISKDESC_S ldd ;
char buffer [ MAX_PATH ] ;
2000-11-29 00:50:34 +01:00
2000-12-13 22:31:37 +01:00
/* has to be here, otherwise loop */
std_LDDs_done = TRUE ;
2000-11-29 00:50:34 +01:00
2000-12-13 22:31:37 +01:00
RegOpenKeyA ( HKEY_LOCAL_MACHINE , " SOFTWARE \\ Microsoft \\ Windows \\ CurrentVersion \\ Setup " , & hKey ) ;
2000-11-29 00:50:34 +01:00
2000-12-13 22:31:37 +01:00
for ( n = 0 ; n < sizeof ( LDID_Data ) / sizeof ( LDID_DATA ) ; n + + )
{
buffer [ 0 ] = ' \0 ' ;
2000-11-29 00:50:34 +01:00
2000-12-13 22:31:37 +01:00
len = MAX_PATH ;
if ( ( hKey ) & & ( LDID_Data [ n ] . RegValName )
& & ( RegQueryValueExA ( hKey , LDID_Data [ n ] . RegValName ,
NULL , & type , buffer , & len ) = = ERROR_SUCCESS )
& & ( type = = REG_SZ ) )
{
TRACE ( " found value '%s' for LDID %d \n " , buffer , n ) ;
}
else
switch ( n )
{
case LDID_SRCPATH :
FIXME ( " LDID_SRCPATH: what exactly do we have to do here ? \n " ) ;
strcpy ( buffer , " X: \\ FIXME " ) ;
break ;
case LDID_SYS :
GetSystemDirectoryA ( buffer , MAX_PATH ) ;
break ;
case LDID_APPS :
case LDID_MACHINE :
case LDID_HOST_WINBOOT :
case LDID_BOOT :
case LDID_BOOT_HOST :
strcpy ( buffer , " C: \\ " ) ;
break ;
default :
if ( LDID_Data [ n ] . StdString )
{
DWORD len = GetWindowsDirectoryA ( buffer , MAX_PATH ) ;
LPSTR p ;
p = buffer + len ;
* p + + = ' \\ ' ;
strcpy ( p , LDID_Data [ n ] . StdString ) ;
}
break ;
}
if ( buffer [ 0 ] )
{
INIT_LDD ( ldd , n ) ;
ldd . pszPath = buffer ;
TRACE ( " LDID %d -> '%s' \n " , ldd . ldid , ldd . pszPath ) ;
CtlSetLdd16 ( & ldd ) ;
}
}
if ( hKey ) RegCloseKey ( hKey ) ;
}
2001-09-11 02:32:32 +02:00
2000-12-16 22:55:05 +01:00
/***********************************************************************
2000-12-13 22:31:37 +01:00
* CtlDelLdd ( SETUPX .37 )
*
* RETURN
* ERR_VCP_LDDINVALID if ldid < LDID_ASSIGN_START .
*/
RETERR16 SETUPX_DelLdd ( LOGDISKID16 ldid )
{
2000-12-16 21:16:33 +01:00
LDD_LIST * pCurr , * pPrev = NULL ;
2000-12-13 22:31:37 +01:00
TRACE ( " (%d) \n " , ldid ) ;
if ( ! std_LDDs_done )
SETUPX_CreateStandardLDDs ( ) ;
if ( ldid < LDID_ASSIGN_START )
return ERR_VCP_LDDINVALID ;
2000-12-16 21:16:33 +01:00
pCurr = pFirstLDD ;
2000-12-13 22:31:37 +01:00
/* search until we find the appropriate LDD or hit the end */
while ( ( pCurr ! = NULL ) & & ( ldid > pCurr - > pldd - > ldid ) )
{
pPrev = pCurr ;
pCurr = pCurr - > next ;
}
if ( ( pCurr = = NULL ) /* hit end of list */
| | ( ldid ! = pCurr - > pldd - > ldid ) )
return ERR_VCP_LDDFIND ; /* correct ? */
/* ok, found our victim: eliminate it */
if ( pPrev )
pPrev - > next = pCurr - > next ;
if ( pCurr = = pFirstLDD )
pFirstLDD = NULL ;
HeapFree ( GetProcessHeap ( ) , 0 , pCurr ) ;
2001-09-11 02:32:32 +02:00
2000-12-13 22:31:37 +01:00
return OK ;
}
2000-12-16 22:55:05 +01:00
/***********************************************************************
* CtlDelLdd ( SETUPX .37 )
*/
2000-12-13 22:31:37 +01:00
RETERR16 WINAPI CtlDelLdd16 ( LOGDISKID16 ldid )
{
FIXME ( " (%d); - please report to a.mohr@mailto.de !!! \n " , ldid ) ;
return SETUPX_DelLdd ( ldid ) ;
2000-11-29 00:50:34 +01:00
}
2000-12-16 22:55:05 +01:00
/***********************************************************************
2000-12-13 22:31:37 +01:00
* CtlFindLdd ( SETUPX .35 )
*
* doesn ' t check pldd ptr validity : crash ( W98SE )
*
* RETURN
* ERR_VCP_LDDINVALID if pldd - > cbSize ! = structsize
* 1 in all other cases ? ?
2001-09-11 02:32:32 +02:00
*
2000-11-29 00:50:34 +01:00
*/
2000-12-13 22:31:37 +01:00
RETERR16 WINAPI CtlFindLdd16 ( LPLOGDISKDESC pldd )
2000-11-29 00:50:34 +01:00
{
2000-12-16 21:16:33 +01:00
LDD_LIST * pCurr , * pPrev = NULL ;
2000-11-29 00:50:34 +01:00
2000-12-13 22:31:37 +01:00
TRACE ( " (%p) \n " , pldd ) ;
2001-09-11 02:32:32 +02:00
2000-12-13 22:31:37 +01:00
if ( ! std_LDDs_done )
SETUPX_CreateStandardLDDs ( ) ;
2000-11-29 00:50:34 +01:00
2000-12-13 22:31:37 +01:00
if ( pldd - > cbSize ! = sizeof ( LOGDISKDESC_S ) )
return ERR_VCP_LDDINVALID ;
2000-11-29 00:50:34 +01:00
2000-12-16 21:16:33 +01:00
pCurr = pFirstLDD ;
2000-12-13 22:31:37 +01:00
/* search until we find the appropriate LDD or hit the end */
while ( ( pCurr ! = NULL ) & & ( pldd - > ldid > pCurr - > pldd - > ldid ) )
2000-11-29 00:50:34 +01:00
{
2000-12-16 21:16:33 +01:00
pPrev = pCurr ;
pCurr = pCurr - > next ;
2000-12-13 22:31:37 +01:00
}
if ( ( pCurr = = NULL ) /* hit end of list */
| | ( pldd - > ldid ! = pCurr - > pldd - > ldid ) )
return ERR_VCP_LDDFIND ; /* correct ? */
memcpy ( pldd , pCurr - > pldd , pldd - > cbSize ) ;
/* hmm, we probably ought to strcpy() the string ptrs here */
2001-09-11 02:32:32 +02:00
2000-12-13 22:31:37 +01:00
return 1 ; /* what is this ?? */
}
2000-12-16 22:55:05 +01:00
/***********************************************************************
2000-12-13 22:31:37 +01:00
* CtlSetLdd ( SETUPX .33 )
*
* Set an LDD entry .
*
* RETURN
* ERR_VCP_LDDINVALID if pldd . cbSize ! = sizeof ( LOGDISKDESC_S )
*
*/
RETERR16 WINAPI CtlSetLdd16 ( LPLOGDISKDESC pldd )
{
2000-12-16 21:16:33 +01:00
LDD_LIST * pCurr , * pPrev = NULL ;
2000-12-13 22:31:37 +01:00
LPLOGDISKDESC pCurrLDD ;
HANDLE heap ;
BOOL is_new = FALSE ;
TRACE ( " (%p) \n " , pldd ) ;
if ( ! std_LDDs_done )
SETUPX_CreateStandardLDDs ( ) ;
if ( pldd - > cbSize ! = sizeof ( LOGDISKDESC_S ) )
return ERR_VCP_LDDINVALID ;
heap = GetProcessHeap ( ) ;
2000-12-16 21:16:33 +01:00
pCurr = pFirstLDD ;
2000-12-13 22:31:37 +01:00
/* search until we find the appropriate LDD or hit the end */
while ( ( pCurr ! = NULL ) & & ( pldd - > ldid > pCurr - > pldd - > ldid ) )
{
pPrev = pCurr ;
pCurr = pCurr - > next ;
}
if ( pCurr = = NULL ) /* hit end of list */
{
is_new = TRUE ;
pCurr = HeapAlloc ( heap , 0 , sizeof ( LDD_LIST ) ) ;
pCurr - > pldd = HeapAlloc ( heap , 0 , sizeof ( LOGDISKDESC_S ) ) ;
pCurr - > next = NULL ;
pCurrLDD = pCurr - > pldd ;
}
else
{
pCurrLDD = pCurr - > pldd ;
if ( pCurrLDD - > pszPath ) HeapFree ( heap , 0 , pCurrLDD - > pszPath ) ;
if ( pCurrLDD - > pszVolLabel ) HeapFree ( heap , 0 , pCurrLDD - > pszVolLabel ) ;
if ( pCurrLDD - > pszDiskName ) HeapFree ( heap , 0 , pCurrLDD - > pszDiskName ) ;
}
memcpy ( pCurrLDD , pldd , sizeof ( LOGDISKDESC_S ) ) ;
if ( pldd - > pszPath )
2001-07-24 23:45:22 +02:00
{
pCurrLDD - > pszPath = HeapAlloc ( heap , 0 , strlen ( pldd - > pszPath ) + 1 ) ;
strcpy ( pCurrLDD - > pszPath , pldd - > pszPath ) ;
}
2000-12-13 22:31:37 +01:00
if ( pldd - > pszVolLabel )
2001-07-24 23:45:22 +02:00
{
pCurrLDD - > pszVolLabel = HeapAlloc ( heap , 0 , strlen ( pldd - > pszVolLabel ) + 1 ) ;
strcpy ( pCurrLDD - > pszVolLabel , pldd - > pszVolLabel ) ;
}
2000-12-13 22:31:37 +01:00
if ( pldd - > pszDiskName )
2001-07-24 23:45:22 +02:00
{
pCurrLDD - > pszDiskName = HeapAlloc ( heap , 0 , strlen ( pldd - > pszDiskName ) + 1 ) ;
strcpy ( pCurrLDD - > pszDiskName , pldd - > pszDiskName ) ;
}
2000-12-13 22:31:37 +01:00
if ( is_new ) /* link into list */
{
if ( pPrev )
2000-11-29 00:50:34 +01:00
{
2000-12-13 22:31:37 +01:00
pCurr - > next = pPrev - > next ;
pPrev - > next = pCurr ;
2000-11-29 00:50:34 +01:00
}
2000-12-13 22:31:37 +01:00
if ( ! pFirstLDD )
pFirstLDD = pCurr ;
2000-11-29 00:50:34 +01:00
}
2001-09-11 02:32:32 +02:00
2000-12-13 22:31:37 +01:00
return OK ;
}
2000-12-16 22:55:05 +01:00
/***********************************************************************
2000-12-13 22:31:37 +01:00
* CtlAddLdd ( SETUPX .36 )
*
* doesn ' t check pldd ptr validity : crash ( W98SE )
*
*/
static LOGDISKID16 ldid_to_add = LDID_ASSIGN_START ;
RETERR16 WINAPI CtlAddLdd16 ( LPLOGDISKDESC pldd )
{
pldd - > ldid = ldid_to_add + + ;
return CtlSetLdd16 ( pldd ) ;
}
2000-12-16 22:55:05 +01:00
/***********************************************************************
2000-12-13 22:31:37 +01:00
* CtlGetLdd ( SETUPX .34 )
*
* doesn ' t check pldd ptr validity : crash ( W98SE )
* What the ! @ # $ % & * ( is the difference between CtlFindLdd ( ) and CtlGetLdd ( ) ? ?
*
* RETURN
* ERR_VCP_LDDINVALID if pldd - > cbSize ! = structsize
2001-09-11 02:32:32 +02:00
*
2000-12-13 22:31:37 +01:00
*/
static RETERR16 SETUPX_GetLdd ( LPLOGDISKDESC pldd )
{
2000-12-16 21:16:33 +01:00
LDD_LIST * pCurr , * pPrev = NULL ;
2000-12-13 22:31:37 +01:00
if ( ! std_LDDs_done )
SETUPX_CreateStandardLDDs ( ) ;
if ( pldd - > cbSize ! = sizeof ( LOGDISKDESC_S ) )
return ERR_VCP_LDDINVALID ;
2000-12-16 21:16:33 +01:00
pCurr = pFirstLDD ;
2000-12-13 22:31:37 +01:00
/* search until we find the appropriate LDD or hit the end */
while ( ( pCurr ! = NULL ) & & ( pldd - > ldid > pCurr - > pldd - > ldid ) )
{
pPrev = pCurr ;
pCurr = pCurr - > next ;
2000-11-29 00:50:34 +01:00
}
2000-12-13 22:31:37 +01:00
if ( pCurr = = NULL ) /* hit end of list */
return ERR_VCP_LDDFIND ; /* correct ? */
2000-11-29 00:50:34 +01:00
2000-12-13 22:31:37 +01:00
memcpy ( pldd , pCurr - > pldd , pldd - > cbSize ) ;
/* hmm, we probably ought to strcpy() the string ptrs here */
2000-11-29 00:50:34 +01:00
2000-12-13 22:31:37 +01:00
return OK ;
}
2000-11-29 00:50:34 +01:00
2000-12-16 22:55:05 +01:00
/**********************************************************************/
2000-12-13 22:31:37 +01:00
RETERR16 WINAPI CtlGetLdd16 ( LPLOGDISKDESC pldd )
{
FIXME ( " (%p); - please report to a.mohr@mailto.de !!! \n " , pldd ) ;
return SETUPX_GetLdd ( pldd ) ;
}
/***********************************************************************
* CtlGetLddPath ( SETUPX .38 )
*
* Gets the path of an LDD .
* No crash if szPath = = NULL .
* szPath has to be at least MAX_PATH_LEN bytes long .
* RETURN
* ERR_VCP_LDDUNINIT if LDD for LDID not found .
*/
RETERR16 WINAPI CtlGetLddPath16 ( LOGDISKID16 ldid , LPSTR szPath )
{
TRACE ( " (%d, %p); \n " , ldid , szPath ) ;
if ( szPath )
{
LOGDISKDESC_S ldd ;
INIT_LDD ( ldd , ldid ) ;
if ( CtlFindLdd16 ( & ldd ) = = ERR_VCP_LDDFIND )
return ERR_VCP_LDDUNINIT ;
SETUPX_GetLdd ( & ldd ) ;
strcpy ( szPath , ldd . pszPath ) ;
TRACE ( " ret '%s' for LDID %d \n " , szPath , ldid ) ;
}
return OK ;
}
/***********************************************************************
* CtlSetLddPath ( SETUPX .508 )
*
* Sets the path of an LDD .
* Creates LDD for LDID if not existing yet .
*/
RETERR16 WINAPI CtlSetLddPath16 ( LOGDISKID16 ldid , LPSTR szPath )
{
LOGDISKDESC_S ldd ;
TRACE ( " (%d, '%s'); \n " , ldid , szPath ) ;
2001-09-11 02:32:32 +02:00
2000-12-13 22:31:37 +01:00
INIT_LDD ( ldd , ldid ) ;
ldd . pszPath = szPath ;
return CtlSetLdd16 ( & ldd ) ;
2000-11-29 00:50:34 +01:00
}
/*
* Find the value of a custom LDID in a . inf file
* e . g . for 49301 :
* 49300 , 49301 = ProgramFilesDir , 5
* - - profile section lookup - - >
* [ ProgramFilesDir ]
* HKLM , " Software \ Microsoft \ Windows \ CurrentVersion " , " ProgramFilesDir " , , " %24% "
* - - GenFormStrWithoutPlaceHolders16 - - >
* HKLM , " Software \ Microsoft \ Windows \ CurrentVersion " , " ProgramFilesDir " , , " C: \"
* - - registry lookup - - >
* C : \ Program Files ( or C : \ if not found in registry )
2001-09-11 02:32:32 +02:00
*
2000-11-29 00:50:34 +01:00
* FIXME :
* - maybe we ought to add a caching array for speed ? - I don ' t care : )
* - not sure whether the processing is correct - sometimes there are equal
* LDIDs for both install and removal sections .
2000-12-13 22:31:37 +01:00
* - probably the whole function can be removed as installers add that on their
2001-09-11 02:32:32 +02:00
* own
2000-11-29 00:50:34 +01:00
*/
2000-12-13 22:31:37 +01:00
static BOOL SETUPX_AddCustomLDID ( int ldid , INT16 hInf )
2000-11-29 00:50:34 +01:00
{
2000-12-13 22:31:37 +01:00
char ldidstr [ 6 ] ;
LPSTR sectionbuf = NULL , entrybuf = NULL , regsectionbuf = NULL ;
2000-11-29 00:50:34 +01:00
LPCSTR filename ;
2000-12-13 22:31:37 +01:00
LPSTR pSec , pEnt , pEqual , p , * pSub = NULL ;
2000-11-29 00:50:34 +01:00
BOOL ret = FALSE ;
2000-12-13 22:31:37 +01:00
char buffer [ MAX_PATH ] ;
LOGDISKDESC_S ldd ;
2000-11-29 00:50:34 +01:00
sprintf ( ldidstr , " %d " , ldid ) ;
filename = IP_GetFileName ( hInf ) ;
2000-12-13 22:31:37 +01:00
if ( ! ( sectionbuf = SETUPX_GetSections ( filename ) ) )
2000-11-29 00:50:34 +01:00
{
2000-12-13 22:31:37 +01:00
ERR ( " couldn't get sections ! \n " ) ;
2000-11-29 00:50:34 +01:00
return FALSE ;
}
for ( pSec = sectionbuf ; * pSec ; pSec + = strlen ( pSec ) + 1 )
{
2000-12-13 22:31:37 +01:00
if ( ! ( entrybuf = SETUPX_GetSectionEntries ( filename , pSec ) ) )
2000-11-29 00:50:34 +01:00
{
2000-12-13 22:31:37 +01:00
ERR ( " couldn't get section entries ! \n " ) ;
goto end ;
2000-11-29 00:50:34 +01:00
}
for ( pEnt = entrybuf ; * pEnt ; pEnt + = strlen ( pEnt ) + 1 )
{
if ( strstr ( pEnt , ldidstr ) )
{
pEqual = strchr ( pEnt , ' = ' ) ;
if ( ! pEqual ) /* crippled entry ?? */
continue ;
/* make sure we found the LDID on left side of the equation */
if ( pEnt + strlen ( ldidstr ) < = pEqual )
{ /* found */
/* but we don't want entries in the strings section */
2001-09-11 02:32:32 +02:00
if ( ! strcasecmp ( pSec , " Strings " ) ) continue ;
2000-11-29 00:50:34 +01:00
p = pEqual + 1 ;
goto found ;
}
}
}
}
2000-12-13 22:31:37 +01:00
goto end ;
2000-11-29 00:50:34 +01:00
found :
TRACE ( " found entry '%s' \n " , p ) ;
2000-12-13 22:31:37 +01:00
pSub = SETUPX_GetSubStrings ( p , ' , ' ) ;
if ( * ( DWORD * ) pSub > 2 )
{
ERR ( " malformed entry '%s' ? \n " , p ) ;
goto end ;
}
TRACE ( " found section '%s' \n " , * ( pSub + 1 ) ) ;
/* FIXME: what are the optional flags at the end of an entry used for ?? */
2000-11-29 00:50:34 +01:00
/* get the location of the registry key from that section */
2000-12-13 22:31:37 +01:00
if ( ! ( regsectionbuf = SETUPX_GetSectionEntries ( filename , * ( pSub + 1 ) ) ) )
2000-11-29 00:50:34 +01:00
{
2000-12-13 22:31:37 +01:00
ERR ( " couldn't get registry section entries ! \n " ) ;
goto end ;
2000-11-29 00:50:34 +01:00
}
2000-12-13 22:31:37 +01:00
/* sectionbuf is > 1024 bytes anyway, so use it */
GenFormStrWithoutPlaceHolders16 ( sectionbuf , regsectionbuf , hInf ) ;
ret = SETUPX_LookupRegistryString ( sectionbuf , buffer , MAX_PATH ) ;
2000-11-29 00:50:34 +01:00
TRACE ( " return '%s' \n " , buffer ) ;
2000-12-13 22:31:37 +01:00
INIT_LDD ( ldd , ldid ) ;
ldd . pszPath = buffer ;
CtlSetLdd16 ( & ldd ) ;
end :
SETUPX_FreeSubStrings ( pSub ) ;
if ( sectionbuf ) HeapFree ( GetProcessHeap ( ) , 0 , sectionbuf ) ;
if ( entrybuf ) HeapFree ( GetProcessHeap ( ) , 0 , entrybuf ) ;
if ( regsectionbuf ) HeapFree ( GetProcessHeap ( ) , 0 , regsectionbuf ) ;
2000-11-29 00:50:34 +01:00
return ret ;
}
2000-09-27 00:46:36 +02:00
/*
2000-11-04 03:57:18 +01:00
* Translate a logical disk identifier ( LDID ) into its string representation
2000-12-13 22:31:37 +01:00
* I ' m afraid this can be totally replaced by CtlGetLddPath ( ) .
2000-11-04 03:57:18 +01:00
*/
2000-12-13 22:31:37 +01:00
static BOOL SETUPX_IP_TranslateLDID ( int ldid , LPSTR * p , HINF16 hInf )
2000-11-04 03:57:18 +01:00
{
BOOL handled = FALSE ;
2000-12-13 22:31:37 +01:00
LOGDISKDESC_S ldd ;
2000-11-04 03:57:18 +01:00
2000-12-13 22:31:37 +01:00
ldd . cbSize = sizeof ( LOGDISKDESC_S ) ;
ldd . ldid = ldid ;
if ( CtlFindLdd16 ( & ldd ) = = ERR_VCP_LDDFIND )
2000-11-04 03:57:18 +01:00
{
2000-12-13 22:31:37 +01:00
/* hmm, it seems the installers already do the work for us
* ( by calling CtlSetLddPath ) that SETUPX_AddCustomLDID
* is supposed to do . Grmbl ; - )
* Well , I ' ll leave it here anyway , but print error . . . */
ERR ( " hmm, LDID %d not registered yet !? \n " , ldid ) ;
handled = SETUPX_AddCustomLDID ( ldid , hInf ) ;
2000-11-04 03:57:18 +01:00
}
2000-12-13 22:31:37 +01:00
else
handled = TRUE ;
2001-09-11 02:32:32 +02:00
2000-12-13 22:31:37 +01:00
SETUPX_GetLdd ( & ldd ) ;
2001-09-11 02:32:32 +02:00
2000-11-04 03:57:18 +01:00
if ( ! handled )
{
2000-12-13 22:31:37 +01:00
FIXME ( " What is LDID %d ?? \n " , ldid ) ;
* p = " LDID_FIXME " ;
2000-11-04 03:57:18 +01:00
}
2000-12-13 22:31:37 +01:00
else
* p = ldd . pszPath ;
2000-11-04 03:57:18 +01:00
return handled ;
}
2000-12-02 00:54:51 +01:00
/***********************************************************************
2001-07-11 20:56:41 +02:00
* GenFormStrWithoutPlaceHolders ( SETUPX .103 )
2000-12-13 22:31:37 +01:00
*
* ought to be pretty much implemented , I guess . . .
2000-09-27 00:46:36 +02:00
*/
void WINAPI GenFormStrWithoutPlaceHolders16 ( LPSTR szDst , LPCSTR szSrc , HINF16 hInf )
{
2000-11-04 03:57:18 +01:00
LPCSTR pSrc = szSrc , pSrcEnd = szSrc + strlen ( szSrc ) ;
LPSTR pDst = szDst , p , pPHBegin ;
int count ;
2001-09-11 02:32:32 +02:00
2000-12-13 22:31:37 +01:00
TRACE ( " (%p, '%s', %04x); \n " , szDst , szSrc , hInf ) ;
2000-11-04 03:57:18 +01:00
while ( pSrc < pSrcEnd )
{
p = strchr ( pSrc , ' % ' ) ;
if ( p )
{
count = ( int ) p - ( int ) pSrc ;
strncpy ( pDst , pSrc , count ) ;
pSrc + = count ;
pDst + = count ;
pPHBegin = p + 1 ;
p = strchr ( pPHBegin , ' % ' ) ;
if ( p )
{
char placeholder [ 80 ] ; /* that really ought to be enough ;) */
int ldid ;
BOOL done = TRUE ;
count = ( int ) p - ( int ) pPHBegin ;
strncpy ( placeholder , pPHBegin , count ) ;
placeholder [ count ] = ' \0 ' ;
ldid = atoi ( placeholder ) ;
if ( ldid )
{
2000-12-13 22:31:37 +01:00
LPSTR p ;
done = SETUPX_IP_TranslateLDID ( ldid , & p , hInf ) ;
strcpy ( pDst , p ) ;
2000-11-04 03:57:18 +01:00
if ( done )
pDst + = strlen ( pDst ) ;
}
else
{ /* hmm, string placeholder. Need to look up
in the [ strings ] section of the hInf */
DWORD ret ;
char buf [ 256 ] ; /* long enough ? */
2001-09-11 02:32:32 +02:00
2000-11-04 03:57:18 +01:00
ret = GetPrivateProfileStringA ( " strings " , placeholder , " " ,
buf , 256 , IP_GetFileName ( hInf ) ) ;
if ( ret )
{
strcpy ( pDst , buf ) ;
pDst + = strlen ( buf ) ;
}
else
{
ERR ( " placeholder string '%s' not found ! \n " , placeholder ) ;
done = FALSE ;
}
}
if ( ! done )
{ /* copy raw placeholder string over */
count = ( int ) p - ( int ) pPHBegin + 2 ;
strncpy ( pDst , pPHBegin - 1 , count ) ;
pDst + = count ;
2001-09-11 02:32:32 +02:00
2000-11-04 03:57:18 +01:00
}
pSrc = p + 1 ;
continue ;
}
}
/* copy the remaining source string over */
strncpy ( pDst , pSrc , ( int ) pSrcEnd - ( int ) pSrc + 1 ) ;
break ;
}
TRACE ( " ret '%s' \n " , szDst ) ;
2000-09-27 00:46:36 +02:00
}
2000-12-13 22:31:37 +01:00
/*
* Copy all items in a CopyFiles entry over to the destination
2000-12-02 00:54:51 +01:00
*
2000-12-13 22:31:37 +01:00
* - VNLP_xxx is what is given as flags for a . INF CopyFiles section
2000-11-29 00:50:34 +01:00
*/
2000-12-13 22:31:37 +01:00
static BOOL SETUPX_CopyFiles ( LPSTR * pSub , HINF16 hInf )
2000-09-27 00:46:36 +02:00
{
2001-04-17 19:39:35 +02:00
BOOL bSingle = FALSE ;
2000-12-13 22:31:37 +01:00
unsigned int n ;
LPCSTR filename = IP_GetFileName ( hInf ) ;
LPSTR pCopyEntry ;
2001-04-17 19:39:35 +02:00
char pDstStr [ MAX_PATH ] ;
2000-12-13 22:31:37 +01:00
LPSTR pSrcDir , pDstDir ;
LPSTR pFileEntries , p ;
WORD ldid ;
LOGDISKDESC_S ldd ;
LPSTR * pSubFile ;
LPSTR pSrcFile , pDstFile ;
2001-04-17 19:39:35 +02:00
WORD flag ;
2000-09-27 00:46:36 +02:00
2000-12-13 22:31:37 +01:00
for ( n = 0 ; n < * ( DWORD * ) pSub ; n + + )
{
pCopyEntry = * ( pSub + 1 + n ) ;
if ( * pCopyEntry = = ' @ ' )
{
2001-04-17 19:39:35 +02:00
pCopyEntry + + ;
bSingle = TRUE ;
2000-12-13 22:31:37 +01:00
}
2001-04-17 19:39:35 +02:00
else
bSingle = FALSE ;
2000-12-13 22:31:37 +01:00
/* get source directory for that entry */
INIT_LDD ( ldd , LDID_SRCPATH ) ;
SETUPX_GetLdd ( & ldd ) ;
pSrcDir = ldd . pszPath ;
2001-09-11 02:32:32 +02:00
2000-12-13 22:31:37 +01:00
/* get destination directory for that entry */
if ( ! ( GetPrivateProfileStringA ( " DestinationDirs " , pCopyEntry , " " ,
2001-04-17 19:39:35 +02:00
pDstStr , sizeof ( pDstStr ) , filename ) ) )
{
/* hmm, not found; try the default entry */
if ( ! ( GetPrivateProfileStringA ( " DestinationDirs " , " DefaultDestDir " , " " , pDstStr , sizeof ( pDstStr ) , filename ) ) )
{
WARN ( " DefaultDestDir not found. \n " ) ;
continue ;
}
}
2000-12-13 22:31:37 +01:00
/* translate destination dir if given as LDID */
2001-04-17 19:39:35 +02:00
ldid = atoi ( pDstStr ) ;
2000-12-13 22:31:37 +01:00
if ( ldid )
{
if ( ! ( SETUPX_IP_TranslateLDID ( ldid , & pDstDir , hInf ) ) )
continue ;
}
else
2001-04-17 19:39:35 +02:00
pDstDir = pDstStr ;
2001-09-11 02:32:32 +02:00
2001-04-17 19:39:35 +02:00
/* now that we have the destination dir, register file copying */
if ( bSingle )
{
VcpQueueCopy16 ( pCopyEntry , pCopyEntry , pSrcDir , pDstDir , LDID_SRCPATH , ldid ? ldid : 0xffff , 0 , VFNL_COPY , 0 ) ;
return TRUE ;
}
/* entry wasn't a single file, so let's iterate over section */
2000-12-13 22:31:37 +01:00
pFileEntries = SETUPX_GetSectionEntries ( filename , pCopyEntry ) ;
for ( p = pFileEntries ; * p ; p + = strlen ( p ) + 1 )
{
pSubFile = SETUPX_GetSubStrings ( p , ' , ' ) ;
pSrcFile = * ( pSubFile + 1 ) ;
pDstFile = ( * ( DWORD * ) pSubFile > 1 ) ? * ( pSubFile + 2 ) : pSrcFile ;
TRACE ( " copying file '%s \\ %s' to '%s \\ %s' \n " , pSrcDir , pSrcFile , pDstDir , pDstFile ) ;
2001-04-17 19:39:35 +02:00
flag = 0 ;
2000-12-13 22:31:37 +01:00
if ( * ( DWORD * ) pSubFile > 2 )
{
if ( ( flag = atoi ( * ( pSubFile + 3 ) ) ) ) /* ah, flag */
{
if ( flag & 0x2c )
FIXME ( " VNLP_xxx flag %d not handled yet. \n " , flag ) ;
}
else
2001-04-17 19:39:35 +02:00
{
FIXME ( " temp file name '%s' given. Need to register in wininit.ini ! \n " , * ( pSubFile + 3 ) ) ;
/* we probably need to set VIRTNODE.vhstrDstFinalName to
* the final destination name , and the temp name is merely
* the copy destination */
}
2000-12-13 22:31:37 +01:00
}
2001-04-17 19:39:35 +02:00
VcpQueueCopy16 ( pSrcFile , pDstFile , pSrcDir , pDstDir , LDID_SRCPATH , ldid ? ldid : 0xffff , 0 , VFNL_COPY | flag , 0 ) ;
2000-12-13 22:31:37 +01:00
SETUPX_FreeSubStrings ( pSubFile ) ;
}
}
2001-09-11 02:32:32 +02:00
2001-04-17 19:39:35 +02:00
return TRUE ;
2000-09-27 00:46:36 +02:00
}
2000-12-02 00:54:51 +01:00
/***********************************************************************
2001-07-11 20:56:41 +02:00
* GenInstall ( SETUPX .101 )
2000-12-13 22:31:37 +01:00
*
2001-04-17 19:39:35 +02:00
* generic installer function for . INF file sections
2000-12-13 22:31:37 +01:00
*
* This is not perfect - patch whenever you can !
2001-09-11 02:32:32 +02:00
*
2000-12-13 22:31:37 +01:00
* wFlags = = GENINSTALL_DO_xxx
* e . g . NetMeeting :
* first call GENINSTALL_DO_REGSRCPATH | GENINSTALL_DO_FILES ,
* second call GENINSTALL_DO_LOGCONFIG | CFGAUTO | INI2REG | REG | INI
2000-12-02 00:54:51 +01:00
*/
2000-09-27 00:46:36 +02:00
RETERR16 WINAPI GenInstall16 ( HINF16 hInfFile , LPCSTR szInstallSection , WORD wFlags )
{
2000-12-13 22:31:37 +01:00
LPCSTR filename = IP_GetFileName ( hInfFile ) ;
LPSTR pEntries , p , pEnd ;
DWORD len ;
LPSTR * pSub ;
FIXME ( " (%04x, '%s', %04x), semi-stub. Please implement additional operations here ! \n " , hInfFile , szInstallSection , wFlags ) ;
pEntries = SETUPX_GetSectionEntries ( filename , szInstallSection ) ;
if ( ! pEntries )
{
ERR ( " couldn't find entries for section '%s' ! \n " , szInstallSection ) ;
return ERR_IP_SECT_NOT_FOUND ;
}
for ( p = pEntries ; * p ; p + = strlen ( p ) + 1 )
{
pEnd = strchr ( p , ' = ' ) ;
if ( ! pEnd ) continue ;
pSub = SETUPX_GetSubStrings ( pEnd + 1 , ' , ' ) ; /* split entries after the '=' */
SETUPX_IsolateSubString ( & p , & pEnd ) ;
len = ( int ) pEnd - ( int ) p ;
if ( wFlags & GENINSTALL_DO_FILES )
{
if ( ! strncasecmp ( p , " CopyFiles " , len ) )
{
SETUPX_CopyFiles ( pSub , hInfFile ) ;
continue ;
}
# if IMPLEMENT_THAT
else
if ( ! strncasecmp ( p , " DelFiles " , len ) )
{
SETUPX_DelFiles ( filename , szInstallSection , pSub ) ;
continue ;
}
# endif
}
if ( wFlags & GENINSTALL_DO_INI )
{
# if IMPLEMENT_THAT
if ( ! strncasecmp ( p , " UpdateInis " , len ) )
{
SETUPX_UpdateInis ( filename , szInstallSection , pSub ) ;
continue ;
}
# endif
}
if ( wFlags & GENINSTALL_DO_REG )
{
# if IMPLEMENT_THAT
/* probably use SUReg*() functions here */
if ( ! strncasecmp ( p , " AddReg " , len ) )
{
SETUPX_AddReg ( filename , szInstallSection , pSub ) ;
continue ;
}
else
if ( ! strncasecmp ( p , " DelReg " , len ) )
{
SETUPX_DelReg ( filename , szInstallSection , pSub ) ;
continue ;
}
# endif
}
2001-09-11 02:32:32 +02:00
2000-12-13 22:31:37 +01:00
SETUPX_FreeSubStrings ( pSub ) ;
}
HeapFree ( GetProcessHeap ( ) , 0 , pEntries ) ;
2000-09-27 00:46:36 +02:00
return OK ;
2000-07-23 16:20:34 +02:00
}