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
*
2002-03-10 00:29:33 +01:00
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation ; either
* version 2.1 of the License , or ( at your option ) any later version .
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*
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"
2002-04-02 04:57:50 +02:00
# include "winerror.h"
2000-09-27 00:20:14 +02:00
# include "wine/winuser16.h"
2002-04-02 04:57:50 +02:00
# include "setupapi.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"
2002-03-10 00:29:33 +01:00
# include "wine/debug.h"
2000-01-29 22:09:02 +01:00
2002-03-10 00:29:33 +01:00
WINE_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 ) ;
}
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 )
{
2002-05-23 04:41:46 +02:00
FIXME ( " (%d); - please report this! \n " , ldid ) ;
2000-12-13 22:31:37 +01:00
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 ;
}
2002-04-02 04:57:50 +02:00
if ( ! pCurr | | pldd - > ldid ! = pCurr - > pldd - > ldid )
2000-12-13 22:31:37 +01:00
{
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 )
{
2002-05-23 04:41:46 +02:00
FIXME ( " (%p); - please report this! \n " , pldd ) ;
2000-12-13 22:31:37 +01:00
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
2002-04-02 04:57:50 +02:00
SetupSetDirectoryIdA ( 0 , ldid , szPath ) ;
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
}