mirror of
https://github.com/reactos/reactos.git
synced 2024-10-15 21:56:40 +00:00
Started porting Setupapi.dll from WINE to ReactOS.
svn path=/trunk/; revision=7863
This commit is contained in:
parent
7fd96c83a7
commit
ed4bb6a2cd
22
reactos/include/wine/setupapi.h
Normal file
22
reactos/include/wine/setupapi.h
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
/*
|
||||||
|
* Compatibility header
|
||||||
|
*
|
||||||
|
* This header is wrapper to allow compilation of Wine DLLs under ReactOS
|
||||||
|
* build system. It contains definitions commonly refered to as Wineisms
|
||||||
|
* and definitions that are missing in w32api.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __WINE_SETUPAPI_H
|
||||||
|
#define __WINE_SETUPAPI_H
|
||||||
|
|
||||||
|
#include_next <setupapi.h>
|
||||||
|
|
||||||
|
#define FLG_ADDREG_DELREG_BIT 0x00008000
|
||||||
|
#define FLG_DELREG_KEYONLY_COMMON FLG_ADDREG_KEYONLY_COMMON
|
||||||
|
#define FLG_DELREG_MULTI_SZ_DELSTRING (FLG_DELREG_TYPE_MULTI_SZ | FLG_ADDREG_DELREG_BIT | 0x00000002)
|
||||||
|
#define FLG_DELREG_TYPE_MULTI_SZ FLG_ADDREG_TYPE_MULTI_SZ
|
||||||
|
#define FLG_ADDREG_KEYONLY_COMMON 0x00002000
|
||||||
|
#define FLG_ADDREG_DELREG_BIT 0x00008000
|
||||||
|
#define SPINST_COPYINF 0x00000200
|
||||||
|
|
||||||
|
#endif /* __WINE_SETUPAPI_H */
|
32
reactos/lib/setupapi/Makefile.in
Normal file
32
reactos/lib/setupapi/Makefile.in
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
EXTRADEFS = -D_SETUPAPI_
|
||||||
|
TOPSRCDIR = @top_srcdir@
|
||||||
|
TOPOBJDIR = ../..
|
||||||
|
SRCDIR = @srcdir@
|
||||||
|
VPATH = @srcdir@
|
||||||
|
MODULE = setupapi.dll
|
||||||
|
IMPORTS = user32 version advapi32 kernel32 ntdll
|
||||||
|
ALTNAMES = setupx.dll
|
||||||
|
EXTRALIBS = $(LIBUNICODE)
|
||||||
|
|
||||||
|
SPEC_SRCS16 = $(ALTNAMES:.dll=.spec)
|
||||||
|
|
||||||
|
C_SRCS = \
|
||||||
|
devinst.c \
|
||||||
|
dirid.c \
|
||||||
|
install.c \
|
||||||
|
parser.c \
|
||||||
|
queue.c \
|
||||||
|
setupcab.c \
|
||||||
|
stubs.c
|
||||||
|
|
||||||
|
C_SRCS16 = \
|
||||||
|
devinst16.c \
|
||||||
|
infparse.c \
|
||||||
|
setupx_main.c \
|
||||||
|
virtcopy.c
|
||||||
|
|
||||||
|
RC_SRCS= setupapi.rc
|
||||||
|
|
||||||
|
@MAKE_DLL_RULES@
|
||||||
|
|
||||||
|
### Dependencies:
|
21
reactos/lib/setupapi/Makefile.ros-template
Normal file
21
reactos/lib/setupapi/Makefile.ros-template
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
# $Id: Makefile.ros-template,v 1.1 2004/01/24 15:39:18 sedwards Exp $
|
||||||
|
|
||||||
|
TARGET_NAME = setupapi
|
||||||
|
|
||||||
|
TARGET_OBJECTS = @C_SRCS@
|
||||||
|
|
||||||
|
TARGET_CFLAGS = @EXTRADEFS@ -D__REACTOS__
|
||||||
|
|
||||||
|
TARGET_SDKLIBS = @IMPORTS@ libwine.a ntdll.a libwine_unicode.a
|
||||||
|
|
||||||
|
TARGET_BASE = 0x76160000
|
||||||
|
|
||||||
|
TARGET_RC_SRCS = @RC_SRCS@
|
||||||
|
TARGET_RC_BINSRC = @RC_BINSRC@
|
||||||
|
TARGET_RC_BINARIES = @RC_BINARIES@
|
||||||
|
|
||||||
|
default: all
|
||||||
|
|
||||||
|
DEP_OBJECTS = $(TARGET_OBJECTS)
|
||||||
|
|
||||||
|
include $(TOOLS_PATH)/depend.mk
|
149
reactos/lib/setupapi/devinst.c
Normal file
149
reactos/lib/setupapi/devinst.c
Normal file
|
@ -0,0 +1,149 @@
|
||||||
|
/*
|
||||||
|
* SetupAPI device installer
|
||||||
|
*
|
||||||
|
* Copyright 2000 Andreas Mohr for CodeWeavers
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#include "windef.h"
|
||||||
|
#include "winbase.h"
|
||||||
|
#include "wingdi.h"
|
||||||
|
#include "winuser.h"
|
||||||
|
#include "winnls.h"
|
||||||
|
#include "winreg.h"
|
||||||
|
#include "setupapi.h"
|
||||||
|
#include "wine/debug.h"
|
||||||
|
|
||||||
|
|
||||||
|
WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
|
||||||
|
*/
|
||||||
|
BOOL WINAPI SetupDiGetDeviceInterfaceDetailA(
|
||||||
|
HDEVINFO DeviceInfoSet,
|
||||||
|
PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
|
||||||
|
PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData,
|
||||||
|
DWORD DeviceInterfaceDetailDataSize,
|
||||||
|
PDWORD RequiredSize,
|
||||||
|
PSP_DEVINFO_DATA DeviceInfoData )
|
||||||
|
{
|
||||||
|
FIXME("\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
|
||||||
|
*/
|
||||||
|
BOOL WINAPI SetupDiGetDeviceInterfaceDetailW(
|
||||||
|
HDEVINFO DeviceInfoSet,
|
||||||
|
PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
|
||||||
|
PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData,
|
||||||
|
DWORD DeviceInterfaceDetailDataSize,
|
||||||
|
PDWORD RequiredSize,
|
||||||
|
PSP_DEVINFO_DATA DeviceInfoData )
|
||||||
|
{
|
||||||
|
FIXME("\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* SetupDiEnumDeviceInterfaces (SETUPAPI.@)
|
||||||
|
*/
|
||||||
|
BOOL WINAPI SetupDiEnumDeviceInterfaces(
|
||||||
|
HDEVINFO DeviceInfoSet,
|
||||||
|
PSP_DEVINFO_DATA DeviceInfoData,
|
||||||
|
CONST GUID * InterfaceClassGuid,
|
||||||
|
DWORD MemberIndex,
|
||||||
|
PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
|
||||||
|
{
|
||||||
|
FIXME("\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* SetupDiGetClassDevsA (SETUPAPI.@)
|
||||||
|
*/
|
||||||
|
HDEVINFO WINAPI SetupDiGetClassDevsA(
|
||||||
|
CONST GUID *class,
|
||||||
|
LPCSTR enumstr,
|
||||||
|
HWND parent,
|
||||||
|
DWORD flags)
|
||||||
|
{
|
||||||
|
FIXME("%s %s %p %08lx\n",debugstr_guid(class),enumstr,parent,flags);
|
||||||
|
|
||||||
|
return (HDEVINFO) INVALID_HANDLE_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* SetupDiGetClassDevsW (SETUPAPI.@)
|
||||||
|
*/
|
||||||
|
HDEVINFO WINAPI SetupDiGetClassDevsW(
|
||||||
|
CONST GUID *class,
|
||||||
|
LPCWSTR enumstr,
|
||||||
|
HWND parent,
|
||||||
|
DWORD flags)
|
||||||
|
{
|
||||||
|
FIXME("%s %s %p %08lx\n",debugstr_guid(class),debugstr_w(enumstr),parent,flags);
|
||||||
|
|
||||||
|
return (HDEVINFO) INVALID_HANDLE_VALUE;
|
||||||
|
}
|
||||||
|
/***********************************************************************
|
||||||
|
* SetupDiEnumDeviceInfo (SETUPAPI.@)
|
||||||
|
*/
|
||||||
|
BOOL WINAPI SetupDiEnumDeviceInfo(
|
||||||
|
HDEVINFO devinfo,
|
||||||
|
DWORD index,
|
||||||
|
PSP_DEVINFO_DATA info)
|
||||||
|
{
|
||||||
|
FIXME("%p %ld %p\n", devinfo, index, info );
|
||||||
|
|
||||||
|
if(info==NULL)
|
||||||
|
return FALSE;
|
||||||
|
if(info->cbSize < sizeof(*info))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* SetupDiDestroyDeviceInfoList (SETUPAPI.@)
|
||||||
|
*/
|
||||||
|
BOOL WINAPI SetupDiDestroyDeviceInfoList( HDEVINFO devinfo )
|
||||||
|
{
|
||||||
|
FIXME("%04lx\n", (DWORD)devinfo);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
|
||||||
|
*/
|
||||||
|
BOOL WINAPI SetupDiGetDeviceRegistryPropertyA(
|
||||||
|
HDEVINFO devinfo,
|
||||||
|
PSP_DEVINFO_DATA DeviceInfoData,
|
||||||
|
DWORD Property,
|
||||||
|
PDWORD PropertyRegDataType,
|
||||||
|
PBYTE PropertyBuffer,
|
||||||
|
DWORD PropertyBufferSize,
|
||||||
|
PDWORD RequiredSize)
|
||||||
|
{
|
||||||
|
FIXME("%04lx %p %ld %p %p %ld %p\n", (DWORD)devinfo, DeviceInfoData,
|
||||||
|
Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
|
||||||
|
RequiredSize);
|
||||||
|
return FALSE;
|
||||||
|
}
|
124
reactos/lib/setupapi/devinst16.c
Normal file
124
reactos/lib/setupapi/devinst16.c
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
/*
|
||||||
|
* SetupAPI device installer
|
||||||
|
*
|
||||||
|
* Copyright 2000 Andreas Mohr for CodeWeavers
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#include "windef.h"
|
||||||
|
#include "winbase.h"
|
||||||
|
#include "setupx16.h"
|
||||||
|
#include "wine/debug.h"
|
||||||
|
|
||||||
|
WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* DiGetClassDevs (SETUPX.304)
|
||||||
|
* Return a list of installed system devices.
|
||||||
|
* Uses HKLM\\ENUM to list devices.
|
||||||
|
*/
|
||||||
|
RETERR16 WINAPI DiGetClassDevs16(LPLPDEVICE_INFO16 lplpdi,
|
||||||
|
LPCSTR lpszClassName, HWND16 hwndParent, INT16 iFlags)
|
||||||
|
{
|
||||||
|
LPDEVICE_INFO16 lpdi;
|
||||||
|
|
||||||
|
FIXME("(%p, '%s', %04x, %04x), semi-stub.\n",
|
||||||
|
lplpdi, lpszClassName, hwndParent, iFlags);
|
||||||
|
lpdi = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DEVICE_INFO16));
|
||||||
|
lpdi->cbSize = sizeof(DEVICE_INFO16);
|
||||||
|
*lplpdi = (LPDEVICE_INFO16)MapLS(lpdi);
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* DiBuildCompatDrvList (SETUPX.300)
|
||||||
|
*/
|
||||||
|
RETERR16 WINAPI DiBuildCompatDrvList16(LPDEVICE_INFO16 lpdi)
|
||||||
|
{
|
||||||
|
FIXME("(%p): stub\n", lpdi);
|
||||||
|
lpdi->lpCompatDrvList = NULL;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* DiCallClassInstaller (SETUPX.308)
|
||||||
|
*/
|
||||||
|
RETERR16 WINAPI DiCallClassInstaller16(/*DI_FUNCTIONS*/WORD diFctn, LPDEVICE_INFO16 lpdi)
|
||||||
|
{
|
||||||
|
FIXME("(%x, %p): stub\n", diFctn, lpdi);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* DiCreateDevRegKey (SETUPX.318)
|
||||||
|
*/
|
||||||
|
RETERR16 WINAPI DiCreateDevRegKey16(LPDEVICE_INFO16 lpdi,
|
||||||
|
VOID* p2, WORD w3,
|
||||||
|
LPCSTR s4, WORD w5)
|
||||||
|
{
|
||||||
|
FIXME("(%p, %p, %x, %s, %x): stub\n", lpdi, p2, w3, debugstr_a(s4), w5);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* DiDeleteDevRegKey (SETUPX.344)
|
||||||
|
*/
|
||||||
|
RETERR16 WINAPI DiDeleteDevRegKey16(LPDEVICE_INFO16 lpdi, INT16 iFlags)
|
||||||
|
{
|
||||||
|
FIXME("(%p, %x): stub\n", lpdi, iFlags);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* DiCreateDeviceInfo (SETUPX.303)
|
||||||
|
*/
|
||||||
|
RETERR16 WINAPI DiCreateDeviceInfo16(LPLPDEVICE_INFO16 lplpdi,
|
||||||
|
LPCSTR lpszDescription, DWORD dnDevnode,
|
||||||
|
HKEY16 hkey, LPCSTR lpszRegsubkey,
|
||||||
|
LPCSTR lpszClassName, HWND16 hwndParent)
|
||||||
|
{
|
||||||
|
LPDEVICE_INFO16 lpdi;
|
||||||
|
FIXME("(%p %s %08lx %x %s %s %x): stub\n", lplpdi,
|
||||||
|
debugstr_a(lpszDescription), dnDevnode, hkey,
|
||||||
|
debugstr_a(lpszRegsubkey), debugstr_a(lpszClassName), hwndParent);
|
||||||
|
lpdi = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DEVICE_INFO16));
|
||||||
|
lpdi->cbSize = sizeof(DEVICE_INFO16);
|
||||||
|
strcpy(lpdi->szClassName, lpszClassName);
|
||||||
|
lpdi->hwndParent = hwndParent;
|
||||||
|
*lplpdi = (LPDEVICE_INFO16)MapLS(lpdi);
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* DiDestroyDeviceInfoList (SETUPX.305)
|
||||||
|
*/
|
||||||
|
RETERR16 WINAPI DiDestroyDeviceInfoList16(LPDEVICE_INFO16 lpdi)
|
||||||
|
{
|
||||||
|
FIXME("(%p): stub\n", lpdi);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* DiOpenDevRegKey (SETUPX.319)
|
||||||
|
*/
|
||||||
|
RETERR16 WINAPI DiOpenDevRegKey16(LPDEVICE_INFO16 lpdi,
|
||||||
|
LPHKEY16 lphk,INT16 iFlags)
|
||||||
|
{
|
||||||
|
FIXME("(%p %p %d): stub\n", lpdi, lphk, iFlags);
|
||||||
|
return FALSE;
|
||||||
|
}
|
260
reactos/lib/setupapi/dirid.c
Normal file
260
reactos/lib/setupapi/dirid.c
Normal file
|
@ -0,0 +1,260 @@
|
||||||
|
/*
|
||||||
|
* Directory id handling
|
||||||
|
*
|
||||||
|
* Copyright 2002 Alexandre Julliard for CodeWeavers
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "wine/port.h"
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#include "windef.h"
|
||||||
|
#include "winbase.h"
|
||||||
|
#include "winreg.h"
|
||||||
|
#include "winternl.h"
|
||||||
|
#include "winerror.h"
|
||||||
|
#include "wingdi.h"
|
||||||
|
#include "winuser.h"
|
||||||
|
#include "winnls.h"
|
||||||
|
#include "setupapi.h"
|
||||||
|
#include "wine/unicode.h"
|
||||||
|
#include "setupapi_private.h"
|
||||||
|
#include "wine/debug.h"
|
||||||
|
|
||||||
|
WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
|
||||||
|
|
||||||
|
#define MAX_SYSTEM_DIRID DIRID_PRINTPROCESSOR
|
||||||
|
|
||||||
|
struct user_dirid
|
||||||
|
{
|
||||||
|
int id;
|
||||||
|
WCHAR *str;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int nb_user_dirids; /* number of user dirids in use */
|
||||||
|
static int alloc_user_dirids; /* number of allocated user dirids */
|
||||||
|
static struct user_dirid *user_dirids;
|
||||||
|
static const WCHAR *system_dirids[MAX_SYSTEM_DIRID+1];
|
||||||
|
|
||||||
|
/* retrieve the string for unknown dirids */
|
||||||
|
static const WCHAR *get_unknown_dirid(void)
|
||||||
|
{
|
||||||
|
static WCHAR *unknown_dirid;
|
||||||
|
static const WCHAR unknown_str[] = {'\\','u','n','k','n','o','w','n',0};
|
||||||
|
|
||||||
|
if (!unknown_dirid)
|
||||||
|
{
|
||||||
|
UINT len = GetSystemDirectoryW( NULL, 0 ) + strlenW(unknown_str);
|
||||||
|
if (!(unknown_dirid = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return NULL;
|
||||||
|
GetSystemDirectoryW( unknown_dirid, len );
|
||||||
|
strcatW( unknown_dirid, unknown_str );
|
||||||
|
}
|
||||||
|
return unknown_dirid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create the string for a system dirid */
|
||||||
|
static const WCHAR *create_system_dirid( int dirid )
|
||||||
|
{
|
||||||
|
static const WCHAR Null[] = {0};
|
||||||
|
static const WCHAR C_Root[] = {'C',':','\\',0};
|
||||||
|
static const WCHAR Drivers[] = {'\\','d','r','i','v','e','r','s',0};
|
||||||
|
static const WCHAR Inf[] = {'\\','i','n','f',0};
|
||||||
|
static const WCHAR Help[] = {'\\','h','e','l','p',0};
|
||||||
|
static const WCHAR Fonts[] = {'\\','f','o','n','t','s',0};
|
||||||
|
static const WCHAR Viewers[] = {'\\','v','i','e','w','e','r','s',0};
|
||||||
|
static const WCHAR System[] = {'\\','s','y','s','t','e','m',0};
|
||||||
|
static const WCHAR Spool[] = {'\\','s','p','o','o','l',0};
|
||||||
|
|
||||||
|
WCHAR buffer[MAX_PATH+16], *str;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
switch(dirid)
|
||||||
|
{
|
||||||
|
case DIRID_NULL:
|
||||||
|
return Null;
|
||||||
|
case DIRID_WINDOWS:
|
||||||
|
GetWindowsDirectoryW( buffer, MAX_PATH );
|
||||||
|
break;
|
||||||
|
case DIRID_SYSTEM:
|
||||||
|
GetSystemDirectoryW( buffer, MAX_PATH );
|
||||||
|
break;
|
||||||
|
case DIRID_DRIVERS:
|
||||||
|
GetSystemDirectoryW( buffer, MAX_PATH );
|
||||||
|
strcatW( buffer, Drivers );
|
||||||
|
break;
|
||||||
|
case DIRID_INF:
|
||||||
|
GetWindowsDirectoryW( buffer, MAX_PATH );
|
||||||
|
strcatW( buffer, Inf );
|
||||||
|
break;
|
||||||
|
case DIRID_HELP:
|
||||||
|
GetWindowsDirectoryW( buffer, MAX_PATH );
|
||||||
|
strcatW( buffer, Help );
|
||||||
|
break;
|
||||||
|
case DIRID_FONTS:
|
||||||
|
GetWindowsDirectoryW( buffer, MAX_PATH );
|
||||||
|
strcatW( buffer, Fonts );
|
||||||
|
break;
|
||||||
|
case DIRID_VIEWERS:
|
||||||
|
GetSystemDirectoryW( buffer, MAX_PATH );
|
||||||
|
strcatW( buffer, Viewers );
|
||||||
|
break;
|
||||||
|
case DIRID_APPS:
|
||||||
|
return C_Root; /* FIXME */
|
||||||
|
case DIRID_SHARED:
|
||||||
|
GetWindowsDirectoryW( buffer, MAX_PATH );
|
||||||
|
break;
|
||||||
|
case DIRID_BOOT:
|
||||||
|
return C_Root; /* FIXME */
|
||||||
|
case DIRID_SYSTEM16:
|
||||||
|
GetWindowsDirectoryW( buffer, MAX_PATH );
|
||||||
|
strcatW( buffer, System );
|
||||||
|
break;
|
||||||
|
case DIRID_SPOOL:
|
||||||
|
case DIRID_SPOOLDRIVERS: /* FIXME */
|
||||||
|
GetWindowsDirectoryW( buffer, MAX_PATH );
|
||||||
|
strcatW( buffer, Spool );
|
||||||
|
break;
|
||||||
|
case DIRID_LOADER:
|
||||||
|
return C_Root; /* FIXME */
|
||||||
|
case DIRID_USERPROFILE: /* FIXME */
|
||||||
|
case DIRID_COLOR: /* FIXME */
|
||||||
|
case DIRID_PRINTPROCESSOR: /* FIXME */
|
||||||
|
default:
|
||||||
|
FIXME( "unknown dirid %d\n", dirid );
|
||||||
|
return get_unknown_dirid();
|
||||||
|
}
|
||||||
|
len = (strlenW(buffer) + 1) * sizeof(WCHAR);
|
||||||
|
if ((str = HeapAlloc( GetProcessHeap(), 0, len ))) memcpy( str, buffer, len );
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* retrieve the string corresponding to a dirid, or NULL if none */
|
||||||
|
const WCHAR *DIRID_get_string( HINF hinf, int dirid )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (dirid == DIRID_ABSOLUTE || dirid == DIRID_ABSOLUTE_16BIT) dirid = DIRID_NULL;
|
||||||
|
|
||||||
|
if (dirid >= DIRID_USER)
|
||||||
|
{
|
||||||
|
for (i = 0; i < nb_user_dirids; i++)
|
||||||
|
if (user_dirids[i].id == dirid) return user_dirids[i].str;
|
||||||
|
ERR("user id %d not found\n", dirid );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (dirid > MAX_SYSTEM_DIRID) return get_unknown_dirid();
|
||||||
|
if (dirid == DIRID_SRCPATH) return PARSER_get_src_root( hinf );
|
||||||
|
if (!system_dirids[dirid]) system_dirids[dirid] = create_system_dirid( dirid );
|
||||||
|
return system_dirids[dirid];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* store a user dirid string */
|
||||||
|
static BOOL store_user_dirid( HINF hinf, int id, WCHAR *str )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < nb_user_dirids; i++) if (user_dirids[i].id == id) break;
|
||||||
|
|
||||||
|
if (i < nb_user_dirids) HeapFree( GetProcessHeap(), 0, user_dirids[i].str );
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (nb_user_dirids >= alloc_user_dirids)
|
||||||
|
{
|
||||||
|
int new_size = max( 32, alloc_user_dirids * 2 );
|
||||||
|
|
||||||
|
struct user_dirid *new;
|
||||||
|
|
||||||
|
if (user_dirids)
|
||||||
|
new = HeapReAlloc( GetProcessHeap(), 0, user_dirids,
|
||||||
|
new_size * sizeof(*new) );
|
||||||
|
else
|
||||||
|
new = HeapAlloc( GetProcessHeap(), 0,
|
||||||
|
new_size * sizeof(*new) );
|
||||||
|
|
||||||
|
if (!new) return FALSE;
|
||||||
|
user_dirids = new;
|
||||||
|
alloc_user_dirids = new_size;
|
||||||
|
}
|
||||||
|
nb_user_dirids++;
|
||||||
|
}
|
||||||
|
user_dirids[i].id = id;
|
||||||
|
user_dirids[i].str = str;
|
||||||
|
TRACE("id %d -> %s\n", id, debugstr_w(str) );
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* SetupSetDirectoryIdA (SETUPAPI.@)
|
||||||
|
*/
|
||||||
|
BOOL WINAPI SetupSetDirectoryIdA( HINF hinf, DWORD id, PCSTR dir )
|
||||||
|
{
|
||||||
|
UNICODE_STRING dirW;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!id) /* clear everything */
|
||||||
|
{
|
||||||
|
for (i = 0; i < nb_user_dirids; i++) HeapFree( GetProcessHeap(), 0, user_dirids[i].str );
|
||||||
|
nb_user_dirids = 0;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
if (id < DIRID_USER)
|
||||||
|
{
|
||||||
|
SetLastError( ERROR_INVALID_PARAMETER );
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* duplicate the string */
|
||||||
|
if (!RtlCreateUnicodeStringFromAsciiz( &dirW, dir ))
|
||||||
|
{
|
||||||
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return store_user_dirid( hinf, id, dirW.Buffer );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* SetupSetDirectoryIdW (SETUPAPI.@)
|
||||||
|
*/
|
||||||
|
BOOL WINAPI SetupSetDirectoryIdW( HINF hinf, DWORD id, PCWSTR dir )
|
||||||
|
{
|
||||||
|
int i, len;
|
||||||
|
WCHAR *str;
|
||||||
|
|
||||||
|
if (!id) /* clear everything */
|
||||||
|
{
|
||||||
|
for (i = 0; i < nb_user_dirids; i++) HeapFree( GetProcessHeap(), 0, user_dirids[i].str );
|
||||||
|
nb_user_dirids = 0;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
if (id < DIRID_USER)
|
||||||
|
{
|
||||||
|
SetLastError( ERROR_INVALID_PARAMETER );
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* duplicate the string */
|
||||||
|
len = (strlenW(dir)+1) * sizeof(WCHAR);
|
||||||
|
if (!(str = HeapAlloc( GetProcessHeap(), 0, len ))) return FALSE;
|
||||||
|
memcpy( str, dir, len );
|
||||||
|
return store_user_dirid( hinf, id, str );
|
||||||
|
}
|
198
reactos/lib/setupapi/infparse.c
Normal file
198
reactos/lib/setupapi/infparse.c
Normal file
|
@ -0,0 +1,198 @@
|
||||||
|
/*
|
||||||
|
* SetupX .inf file parsing functions
|
||||||
|
*
|
||||||
|
* Copyright 2000 Andreas Mohr for CodeWeavers
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* FIXME:
|
||||||
|
* - return values ???
|
||||||
|
* - this should be reimplemented at some point to have its own
|
||||||
|
* file parsing instead of using profile functions,
|
||||||
|
* as some SETUPX exports probably demand that
|
||||||
|
* (IpSaveRestorePosition, IpFindNextMatchLine, ...).
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "windef.h"
|
||||||
|
#include "winbase.h"
|
||||||
|
#include "winreg.h"
|
||||||
|
#include "winternl.h"
|
||||||
|
#include "wingdi.h"
|
||||||
|
#include "winuser.h"
|
||||||
|
#include "winnls.h"
|
||||||
|
#include "setupapi.h"
|
||||||
|
#include "setupx16.h"
|
||||||
|
#include "setupapi_private.h"
|
||||||
|
#include "wine/debug.h"
|
||||||
|
|
||||||
|
WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
|
||||||
|
|
||||||
|
#define MAX_HANDLES 16384
|
||||||
|
#define FIRST_HANDLE 32
|
||||||
|
|
||||||
|
static HINF handles[MAX_HANDLES];
|
||||||
|
|
||||||
|
|
||||||
|
static RETERR16 alloc_hinf16( HINF hinf, HINF16 *hinf16 )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < MAX_HANDLES; i++)
|
||||||
|
{
|
||||||
|
if (!handles[i])
|
||||||
|
{
|
||||||
|
handles[i] = hinf;
|
||||||
|
*hinf16 = i + FIRST_HANDLE;
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ERR_IP_OUT_OF_HANDLES;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HINF get_hinf( HINF16 hinf16 )
|
||||||
|
{
|
||||||
|
int idx = hinf16 - FIRST_HANDLE;
|
||||||
|
if (idx < 0 || idx >= MAX_HANDLES) return 0;
|
||||||
|
return handles[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static HINF free_hinf16( HINF16 hinf16 )
|
||||||
|
{
|
||||||
|
HINF ret;
|
||||||
|
int idx = hinf16 - FIRST_HANDLE;
|
||||||
|
|
||||||
|
if (idx < 0 || idx >= MAX_HANDLES) return 0;
|
||||||
|
ret = handles[idx];
|
||||||
|
handles[idx] = 0;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* convert last error code to a RETERR16 value */
|
||||||
|
static RETERR16 get_last_error(void)
|
||||||
|
{
|
||||||
|
switch(GetLastError())
|
||||||
|
{
|
||||||
|
case ERROR_EXPECTED_SECTION_NAME:
|
||||||
|
case ERROR_BAD_SECTION_NAME_LINE:
|
||||||
|
case ERROR_SECTION_NAME_TOO_LONG: return ERR_IP_INVALID_SECT_NAME;
|
||||||
|
case ERROR_SECTION_NOT_FOUND: return ERR_IP_SECT_NOT_FOUND;
|
||||||
|
case ERROR_LINE_NOT_FOUND: return ERR_IP_LINE_NOT_FOUND;
|
||||||
|
default: return IP_ERROR; /* FIXME */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* IpOpen (SETUPX.2)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
RETERR16 WINAPI IpOpen16( LPCSTR filename, HINF16 *hinf16 )
|
||||||
|
{
|
||||||
|
HINF hinf = SetupOpenInfFileA( filename, NULL, INF_STYLE_WIN4, NULL );
|
||||||
|
if (hinf == (HINF)INVALID_HANDLE_VALUE) return get_last_error();
|
||||||
|
return alloc_hinf16( hinf, hinf16 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* IpClose (SETUPX.4)
|
||||||
|
*/
|
||||||
|
RETERR16 WINAPI IpClose16( HINF16 hinf16 )
|
||||||
|
{
|
||||||
|
HINF hinf = free_hinf16( hinf16 );
|
||||||
|
if (!hinf) return ERR_IP_INVALID_HINF;
|
||||||
|
SetupCloseInfFile( hinf );
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* IpGetProfileString (SETUPX.210)
|
||||||
|
*/
|
||||||
|
RETERR16 WINAPI IpGetProfileString16( HINF16 hinf16, LPCSTR section, LPCSTR entry,
|
||||||
|
LPSTR buffer, WORD buflen )
|
||||||
|
{
|
||||||
|
DWORD required_size;
|
||||||
|
HINF hinf = get_hinf( hinf16 );
|
||||||
|
|
||||||
|
if (!hinf) return ERR_IP_INVALID_HINF;
|
||||||
|
if (!SetupGetLineTextA( NULL, hinf, section, entry, buffer, buflen, &required_size ))
|
||||||
|
return get_last_error();
|
||||||
|
TRACE("%p: section %s entry %s ret %s\n",
|
||||||
|
hinf, debugstr_a(section), debugstr_a(entry), debugstr_a(buffer) );
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* GenFormStrWithoutPlaceHolders (SETUPX.103)
|
||||||
|
*
|
||||||
|
* ought to be pretty much implemented, I guess...
|
||||||
|
*/
|
||||||
|
void WINAPI GenFormStrWithoutPlaceHolders16( LPSTR dst, LPCSTR src, HINF16 hinf16 )
|
||||||
|
{
|
||||||
|
UNICODE_STRING srcW;
|
||||||
|
HINF hinf = get_hinf( hinf16 );
|
||||||
|
|
||||||
|
if (!hinf) return;
|
||||||
|
|
||||||
|
if (!RtlCreateUnicodeStringFromAsciiz( &srcW, src )) return;
|
||||||
|
PARSER_string_substA( hinf, srcW.Buffer, dst, MAX_INF_STRING_LENGTH );
|
||||||
|
RtlFreeUnicodeString( &srcW );
|
||||||
|
TRACE( "%s -> %s\n", debugstr_a(src), debugstr_a(dst) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* GenInstall (SETUPX.101)
|
||||||
|
*
|
||||||
|
* generic installer function for .INF file sections
|
||||||
|
*
|
||||||
|
* This is not perfect - patch whenever you can !
|
||||||
|
*
|
||||||
|
* wFlags == GENINSTALL_DO_xxx
|
||||||
|
* e.g. NetMeeting:
|
||||||
|
* first call GENINSTALL_DO_REGSRCPATH | GENINSTALL_DO_FILES,
|
||||||
|
* second call GENINSTALL_DO_LOGCONFIG | CFGAUTO | INI2REG | REG | INI
|
||||||
|
*/
|
||||||
|
RETERR16 WINAPI GenInstall16( HINF16 hinf16, LPCSTR section, WORD genflags )
|
||||||
|
{
|
||||||
|
UINT flags = 0;
|
||||||
|
HINF hinf = get_hinf( hinf16 );
|
||||||
|
RETERR16 ret = OK;
|
||||||
|
void *context;
|
||||||
|
|
||||||
|
if (!hinf) return ERR_IP_INVALID_HINF;
|
||||||
|
|
||||||
|
if (genflags & GENINSTALL_DO_FILES) flags |= SPINST_FILES;
|
||||||
|
if (genflags & GENINSTALL_DO_INI) flags |= SPINST_INIFILES;
|
||||||
|
if (genflags & GENINSTALL_DO_REG) flags |= SPINST_REGISTRY;
|
||||||
|
if (genflags & GENINSTALL_DO_INI2REG) flags |= SPINST_INI2REG;
|
||||||
|
if (genflags & GENINSTALL_DO_LOGCONFIG) flags |= SPINST_LOGCONFIG;
|
||||||
|
if (genflags & GENINSTALL_DO_REGSRCPATH) FIXME( "unsupported flag: GENINSTALL_DO_REGSRCPATH\n" );
|
||||||
|
if (genflags & GENINSTALL_DO_CFGAUTO) FIXME( "unsupported flag: GENINSTALL_DO_CFGAUTO\n" );
|
||||||
|
if (genflags & GENINSTALL_DO_PERUSER) FIXME( "unsupported flag: GENINSTALL_DO_PERUSER\n" );
|
||||||
|
|
||||||
|
context = SetupInitDefaultQueueCallback( 0 );
|
||||||
|
if (!SetupInstallFromInfSectionA( 0, hinf, section, flags, 0, NULL,
|
||||||
|
SP_COPY_NEWER_OR_SAME, SetupDefaultQueueCallbackA,
|
||||||
|
context, 0, 0 ))
|
||||||
|
ret = get_last_error();
|
||||||
|
|
||||||
|
SetupTermDefaultQueueCallback( context );
|
||||||
|
return ret;
|
||||||
|
}
|
675
reactos/lib/setupapi/install.c
Normal file
675
reactos/lib/setupapi/install.c
Normal file
|
@ -0,0 +1,675 @@
|
||||||
|
/*
|
||||||
|
* Setupapi install routines
|
||||||
|
*
|
||||||
|
* Copyright 2002 Alexandre Julliard for CodeWeavers
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "wine/port.h"
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#include "windef.h"
|
||||||
|
#include "winbase.h"
|
||||||
|
#include "winreg.h"
|
||||||
|
#include "winternl.h"
|
||||||
|
#include "winerror.h"
|
||||||
|
#include "wingdi.h"
|
||||||
|
#include "winuser.h"
|
||||||
|
#include "winnls.h"
|
||||||
|
#include "setupapi.h"
|
||||||
|
#include "setupapi_private.h"
|
||||||
|
#include "wine/unicode.h"
|
||||||
|
#include "wine/debug.h"
|
||||||
|
|
||||||
|
WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
|
||||||
|
|
||||||
|
/* info passed to callback functions dealing with files */
|
||||||
|
struct files_callback_info
|
||||||
|
{
|
||||||
|
HSPFILEQ queue;
|
||||||
|
PCWSTR src_root;
|
||||||
|
UINT copy_flags;
|
||||||
|
HINF layout;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* info passed to callback functions dealing with the registry */
|
||||||
|
struct registry_callback_info
|
||||||
|
{
|
||||||
|
HKEY default_root;
|
||||||
|
BOOL delete;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef BOOL (*iterate_fields_func)( HINF hinf, PCWSTR field, void *arg );
|
||||||
|
|
||||||
|
/* Unicode constants */
|
||||||
|
static const WCHAR CopyFiles[] = {'C','o','p','y','F','i','l','e','s',0};
|
||||||
|
static const WCHAR DelFiles[] = {'D','e','l','F','i','l','e','s',0};
|
||||||
|
static const WCHAR RenFiles[] = {'R','e','n','F','i','l','e','s',0};
|
||||||
|
static const WCHAR Ini2Reg[] = {'I','n','i','2','R','e','g',0};
|
||||||
|
static const WCHAR LogConf[] = {'L','o','g','C','o','n','f',0};
|
||||||
|
static const WCHAR AddReg[] = {'A','d','d','R','e','g',0};
|
||||||
|
static const WCHAR DelReg[] = {'D','e','l','R','e','g',0};
|
||||||
|
static const WCHAR UpdateInis[] = {'U','p','d','a','t','e','I','n','i','s',0};
|
||||||
|
static const WCHAR UpdateIniFields[] = {'U','p','d','a','t','e','I','n','i','F','i','e','l','d','s',0};
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* get_field_string
|
||||||
|
*
|
||||||
|
* Retrieve the contents of a field, dynamically growing the buffer if necessary.
|
||||||
|
*/
|
||||||
|
static WCHAR *get_field_string( INFCONTEXT *context, DWORD index, WCHAR *buffer,
|
||||||
|
WCHAR *static_buffer, DWORD *size )
|
||||||
|
{
|
||||||
|
DWORD required;
|
||||||
|
|
||||||
|
if (SetupGetStringFieldW( context, index, buffer, *size, &required )) return buffer;
|
||||||
|
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
|
||||||
|
{
|
||||||
|
/* now grow the buffer */
|
||||||
|
if (buffer != static_buffer) HeapFree( GetProcessHeap(), 0, buffer );
|
||||||
|
if (!(buffer = HeapAlloc( GetProcessHeap(), 0, required*sizeof(WCHAR) ))) return NULL;
|
||||||
|
*size = required;
|
||||||
|
if (SetupGetStringFieldW( context, index, buffer, *size, &required )) return buffer;
|
||||||
|
}
|
||||||
|
if (buffer != static_buffer) HeapFree( GetProcessHeap(), 0, buffer );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* copy_files_callback
|
||||||
|
*
|
||||||
|
* Called once for each CopyFiles entry in a given section.
|
||||||
|
*/
|
||||||
|
static BOOL copy_files_callback( HINF hinf, PCWSTR field, void *arg )
|
||||||
|
{
|
||||||
|
struct files_callback_info *info = arg;
|
||||||
|
|
||||||
|
if (field[0] == '@') /* special case: copy single file */
|
||||||
|
SetupQueueDefaultCopyW( info->queue, info->layout, info->src_root, NULL, field, info->copy_flags );
|
||||||
|
else
|
||||||
|
SetupQueueCopySectionW( info->queue, info->src_root, info->layout, hinf, field, info->copy_flags );
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* delete_files_callback
|
||||||
|
*
|
||||||
|
* Called once for each DelFiles entry in a given section.
|
||||||
|
*/
|
||||||
|
static BOOL delete_files_callback( HINF hinf, PCWSTR field, void *arg )
|
||||||
|
{
|
||||||
|
struct files_callback_info *info = arg;
|
||||||
|
SetupQueueDeleteSectionW( info->queue, hinf, 0, field );
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* rename_files_callback
|
||||||
|
*
|
||||||
|
* Called once for each RenFiles entry in a given section.
|
||||||
|
*/
|
||||||
|
static BOOL rename_files_callback( HINF hinf, PCWSTR field, void *arg )
|
||||||
|
{
|
||||||
|
struct files_callback_info *info = arg;
|
||||||
|
SetupQueueRenameSectionW( info->queue, hinf, 0, field );
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* get_root_key
|
||||||
|
*
|
||||||
|
* Retrieve the registry root key from its name.
|
||||||
|
*/
|
||||||
|
static HKEY get_root_key( const WCHAR *name, HKEY def_root )
|
||||||
|
{
|
||||||
|
static const WCHAR HKCR[] = {'H','K','C','R',0};
|
||||||
|
static const WCHAR HKCU[] = {'H','K','C','U',0};
|
||||||
|
static const WCHAR HKLM[] = {'H','K','L','M',0};
|
||||||
|
static const WCHAR HKU[] = {'H','K','U',0};
|
||||||
|
static const WCHAR HKR[] = {'H','K','R',0};
|
||||||
|
|
||||||
|
if (!strcmpiW( name, HKCR )) return HKEY_CLASSES_ROOT;
|
||||||
|
if (!strcmpiW( name, HKCU )) return HKEY_CURRENT_USER;
|
||||||
|
if (!strcmpiW( name, HKLM )) return HKEY_LOCAL_MACHINE;
|
||||||
|
if (!strcmpiW( name, HKU )) return HKEY_USERS;
|
||||||
|
if (!strcmpiW( name, HKR )) return def_root;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* append_multi_sz_value
|
||||||
|
*
|
||||||
|
* Append a multisz string to a multisz registry value.
|
||||||
|
*/
|
||||||
|
static void append_multi_sz_value( HKEY hkey, const WCHAR *value, const WCHAR *strings,
|
||||||
|
DWORD str_size )
|
||||||
|
{
|
||||||
|
DWORD size, type, total;
|
||||||
|
WCHAR *buffer, *p;
|
||||||
|
|
||||||
|
if (RegQueryValueExW( hkey, value, NULL, &type, NULL, &size )) return;
|
||||||
|
if (type != REG_MULTI_SZ) return;
|
||||||
|
|
||||||
|
if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (size + str_size) * sizeof(WCHAR) ))) return;
|
||||||
|
if (RegQueryValueExW( hkey, value, NULL, NULL, (BYTE *)buffer, &size )) goto done;
|
||||||
|
|
||||||
|
/* compare each string against all the existing ones */
|
||||||
|
total = size;
|
||||||
|
while (*strings)
|
||||||
|
{
|
||||||
|
int len = strlenW(strings) + 1;
|
||||||
|
|
||||||
|
for (p = buffer; *p; p += strlenW(p) + 1)
|
||||||
|
if (!strcmpiW( p, strings )) break;
|
||||||
|
|
||||||
|
if (!*p) /* not found, need to append it */
|
||||||
|
{
|
||||||
|
memcpy( p, strings, len * sizeof(WCHAR) );
|
||||||
|
p[len] = 0;
|
||||||
|
total += len;
|
||||||
|
}
|
||||||
|
strings += len;
|
||||||
|
}
|
||||||
|
if (total != size)
|
||||||
|
{
|
||||||
|
TRACE( "setting value %s to %s\n", debugstr_w(value), debugstr_w(buffer) );
|
||||||
|
RegSetValueExW( hkey, value, 0, REG_MULTI_SZ, (BYTE *)buffer, total );
|
||||||
|
}
|
||||||
|
done:
|
||||||
|
HeapFree( GetProcessHeap(), 0, buffer );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* delete_multi_sz_value
|
||||||
|
*
|
||||||
|
* Remove a string from a multisz registry value.
|
||||||
|
*/
|
||||||
|
static void delete_multi_sz_value( HKEY hkey, const WCHAR *value, const WCHAR *string )
|
||||||
|
{
|
||||||
|
DWORD size, type;
|
||||||
|
WCHAR *buffer, *src, *dst;
|
||||||
|
|
||||||
|
if (RegQueryValueExW( hkey, value, NULL, &type, NULL, &size )) return;
|
||||||
|
if (type != REG_MULTI_SZ) return;
|
||||||
|
/* allocate double the size, one for value before and one for after */
|
||||||
|
if (!(buffer = HeapAlloc( GetProcessHeap(), 0, size * 2 * sizeof(WCHAR) ))) return;
|
||||||
|
if (RegQueryValueExW( hkey, value, NULL, NULL, (BYTE *)buffer, &size )) goto done;
|
||||||
|
src = buffer;
|
||||||
|
dst = buffer + size;
|
||||||
|
while (*src)
|
||||||
|
{
|
||||||
|
int len = strlenW(src) + 1;
|
||||||
|
if (strcmpiW( src, string ))
|
||||||
|
{
|
||||||
|
memcpy( dst, src, len * sizeof(WCHAR) );
|
||||||
|
dst += len;
|
||||||
|
}
|
||||||
|
src += len;
|
||||||
|
}
|
||||||
|
*dst++ = 0;
|
||||||
|
if (dst != buffer + 2*size) /* did we remove something? */
|
||||||
|
{
|
||||||
|
TRACE( "setting value %s to %s\n", debugstr_w(value), debugstr_w(buffer + size) );
|
||||||
|
RegSetValueExW( hkey, value, 0, REG_MULTI_SZ,
|
||||||
|
(BYTE *)(buffer + size), dst - (buffer + size) );
|
||||||
|
}
|
||||||
|
done:
|
||||||
|
HeapFree( GetProcessHeap(), 0, buffer );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* do_reg_operation
|
||||||
|
*
|
||||||
|
* Perform an add/delete registry operation depending on the flags.
|
||||||
|
*/
|
||||||
|
static BOOL do_reg_operation( HKEY hkey, const WCHAR *value, INFCONTEXT *context, INT flags )
|
||||||
|
{
|
||||||
|
DWORD type, size;
|
||||||
|
|
||||||
|
if (flags & (FLG_ADDREG_DELREG_BIT | FLG_ADDREG_DELVAL)) /* deletion */
|
||||||
|
{
|
||||||
|
if (*value && !(flags & FLG_DELREG_KEYONLY_COMMON))
|
||||||
|
{
|
||||||
|
if ((flags & FLG_DELREG_MULTI_SZ_DELSTRING) == FLG_DELREG_MULTI_SZ_DELSTRING)
|
||||||
|
{
|
||||||
|
WCHAR *str;
|
||||||
|
|
||||||
|
if (!SetupGetStringFieldW( context, 5, NULL, 0, &size ) || !size) return TRUE;
|
||||||
|
if (!(str = HeapAlloc( GetProcessHeap(), 0, size * sizeof(WCHAR) ))) return FALSE;
|
||||||
|
SetupGetStringFieldW( context, 5, str, size, NULL );
|
||||||
|
delete_multi_sz_value( hkey, value, str );
|
||||||
|
HeapFree( GetProcessHeap(), 0, str );
|
||||||
|
}
|
||||||
|
else RegDeleteValueW( hkey, value );
|
||||||
|
}
|
||||||
|
else RegDeleteKeyW( hkey, NULL );
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & (FLG_ADDREG_KEYONLY|FLG_ADDREG_KEYONLY_COMMON)) return TRUE;
|
||||||
|
|
||||||
|
if (flags & (FLG_ADDREG_NOCLOBBER|FLG_ADDREG_OVERWRITEONLY))
|
||||||
|
{
|
||||||
|
BOOL exists = !RegQueryValueExW( hkey, value, NULL, NULL, NULL, NULL );
|
||||||
|
if (exists && (flags & FLG_ADDREG_NOCLOBBER)) return TRUE;
|
||||||
|
if (!exists & (flags & FLG_ADDREG_OVERWRITEONLY)) return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(flags & FLG_ADDREG_TYPE_MASK)
|
||||||
|
{
|
||||||
|
case FLG_ADDREG_TYPE_SZ: type = REG_SZ; break;
|
||||||
|
case FLG_ADDREG_TYPE_MULTI_SZ: type = REG_MULTI_SZ; break;
|
||||||
|
case FLG_ADDREG_TYPE_EXPAND_SZ: type = REG_EXPAND_SZ; break;
|
||||||
|
case FLG_ADDREG_TYPE_BINARY: type = REG_BINARY; break;
|
||||||
|
case FLG_ADDREG_TYPE_DWORD: type = REG_DWORD; break;
|
||||||
|
case FLG_ADDREG_TYPE_NONE: type = REG_NONE; break;
|
||||||
|
default: type = flags >> 16; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(flags & FLG_ADDREG_BINVALUETYPE) ||
|
||||||
|
(type == REG_DWORD && SetupGetFieldCount(context) == 5))
|
||||||
|
{
|
||||||
|
static const WCHAR empty;
|
||||||
|
WCHAR *str = NULL;
|
||||||
|
|
||||||
|
if (type == REG_MULTI_SZ)
|
||||||
|
{
|
||||||
|
if (!SetupGetMultiSzFieldW( context, 5, NULL, 0, &size )) size = 0;
|
||||||
|
if (size)
|
||||||
|
{
|
||||||
|
if (!(str = HeapAlloc( GetProcessHeap(), 0, size * sizeof(WCHAR) ))) return FALSE;
|
||||||
|
SetupGetMultiSzFieldW( context, 5, str, size, NULL );
|
||||||
|
}
|
||||||
|
if (flags & FLG_ADDREG_APPEND)
|
||||||
|
{
|
||||||
|
if (!str) return TRUE;
|
||||||
|
append_multi_sz_value( hkey, value, str, size );
|
||||||
|
HeapFree( GetProcessHeap(), 0, str );
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
/* else fall through to normal string handling */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!SetupGetStringFieldW( context, 5, NULL, 0, &size )) size = 0;
|
||||||
|
if (size)
|
||||||
|
{
|
||||||
|
if (!(str = HeapAlloc( GetProcessHeap(), 0, size * sizeof(WCHAR) ))) return FALSE;
|
||||||
|
SetupGetStringFieldW( context, 5, str, size, NULL );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == REG_DWORD)
|
||||||
|
{
|
||||||
|
DWORD dw = str ? strtoulW( str, NULL, 16 ) : 0;
|
||||||
|
TRACE( "setting dword %s to %lx\n", debugstr_w(value), dw );
|
||||||
|
RegSetValueExW( hkey, value, 0, type, (BYTE *)&dw, sizeof(dw) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TRACE( "setting value %s to %s\n", debugstr_w(value), debugstr_w(str) );
|
||||||
|
if (str) RegSetValueExW( hkey, value, 0, type, (BYTE *)str, size * sizeof(WCHAR) );
|
||||||
|
else RegSetValueExW( hkey, value, 0, type, (BYTE *)&empty, sizeof(WCHAR) );
|
||||||
|
}
|
||||||
|
HeapFree( GetProcessHeap(), 0, str );
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
else /* get the binary data */
|
||||||
|
{
|
||||||
|
BYTE *data = NULL;
|
||||||
|
|
||||||
|
if (!SetupGetBinaryField( context, 5, NULL, 0, &size )) size = 0;
|
||||||
|
if (size)
|
||||||
|
{
|
||||||
|
if (!(data = HeapAlloc( GetProcessHeap(), 0, size ))) return FALSE;
|
||||||
|
TRACE( "setting binary data %s len %ld\n", debugstr_w(value), size );
|
||||||
|
SetupGetBinaryField( context, 5, data, size, NULL );
|
||||||
|
}
|
||||||
|
RegSetValueExW( hkey, value, 0, type, data, size );
|
||||||
|
HeapFree( GetProcessHeap(), 0, data );
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* registry_callback
|
||||||
|
*
|
||||||
|
* Called once for each AddReg and DelReg entry in a given section.
|
||||||
|
*/
|
||||||
|
static BOOL registry_callback( HINF hinf, PCWSTR field, void *arg )
|
||||||
|
{
|
||||||
|
struct registry_callback_info *info = arg;
|
||||||
|
INFCONTEXT context;
|
||||||
|
HKEY root_key, hkey;
|
||||||
|
|
||||||
|
BOOL ok = SetupFindFirstLineW( hinf, field, NULL, &context );
|
||||||
|
|
||||||
|
for (; ok; ok = SetupFindNextLine( &context, &context ))
|
||||||
|
{
|
||||||
|
WCHAR buffer[MAX_INF_STRING_LENGTH];
|
||||||
|
INT flags;
|
||||||
|
|
||||||
|
/* get root */
|
||||||
|
if (!SetupGetStringFieldW( &context, 1, buffer, sizeof(buffer)/sizeof(WCHAR), NULL ))
|
||||||
|
continue;
|
||||||
|
if (!(root_key = get_root_key( buffer, info->default_root )))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* get key */
|
||||||
|
if (!SetupGetStringFieldW( &context, 2, buffer, sizeof(buffer)/sizeof(WCHAR), NULL ))
|
||||||
|
*buffer = 0;
|
||||||
|
|
||||||
|
/* get flags */
|
||||||
|
if (!SetupGetIntField( &context, 4, &flags )) flags = 0;
|
||||||
|
|
||||||
|
if (!info->delete)
|
||||||
|
{
|
||||||
|
if (flags & FLG_ADDREG_DELREG_BIT) continue; /* ignore this entry */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!flags) flags = FLG_ADDREG_DELREG_BIT;
|
||||||
|
else if (!(flags & FLG_ADDREG_DELREG_BIT)) continue; /* ignore this entry */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info->delete || (flags & FLG_ADDREG_OVERWRITEONLY))
|
||||||
|
{
|
||||||
|
if (RegOpenKeyW( root_key, buffer, &hkey )) continue; /* ignore if it doesn't exist */
|
||||||
|
}
|
||||||
|
else if (RegCreateKeyW( root_key, buffer, &hkey ))
|
||||||
|
{
|
||||||
|
ERR( "could not create key %p %s\n", root_key, debugstr_w(buffer) );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
TRACE( "key %p %s\n", root_key, debugstr_w(buffer) );
|
||||||
|
|
||||||
|
/* get value name */
|
||||||
|
if (!SetupGetStringFieldW( &context, 3, buffer, sizeof(buffer)/sizeof(WCHAR), NULL ))
|
||||||
|
*buffer = 0;
|
||||||
|
|
||||||
|
/* and now do it */
|
||||||
|
if (!do_reg_operation( hkey, buffer, &context, flags ))
|
||||||
|
{
|
||||||
|
RegCloseKey( hkey );
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
RegCloseKey( hkey );
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static BOOL update_ini_callback( HINF hinf, PCWSTR field, void *arg )
|
||||||
|
{
|
||||||
|
INFCONTEXT context;
|
||||||
|
|
||||||
|
BOOL ok = SetupFindFirstLineW( hinf, field, NULL, &context );
|
||||||
|
|
||||||
|
for (; ok; ok = SetupFindNextLine( &context, &context ))
|
||||||
|
{
|
||||||
|
WCHAR buffer[MAX_INF_STRING_LENGTH];
|
||||||
|
WCHAR filename[MAX_INF_STRING_LENGTH];
|
||||||
|
WCHAR section[MAX_INF_STRING_LENGTH];
|
||||||
|
WCHAR entry[MAX_INF_STRING_LENGTH];
|
||||||
|
WCHAR string[MAX_INF_STRING_LENGTH];
|
||||||
|
LPWSTR divider;
|
||||||
|
|
||||||
|
if (!SetupGetStringFieldW( &context, 1, filename,
|
||||||
|
sizeof(filename)/sizeof(WCHAR), NULL ))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!SetupGetStringFieldW( &context, 2, section,
|
||||||
|
sizeof(section)/sizeof(WCHAR), NULL ))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!SetupGetStringFieldW( &context, 4, buffer,
|
||||||
|
sizeof(buffer)/sizeof(WCHAR), NULL ))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
divider = strchrW(buffer,'=');
|
||||||
|
if (divider)
|
||||||
|
{
|
||||||
|
*divider = 0;
|
||||||
|
strcpyW(entry,buffer);
|
||||||
|
divider++;
|
||||||
|
strcpyW(string,divider);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
strcpyW(entry,buffer);
|
||||||
|
string[0]=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE("Writing %s = %s in %s of file %s\n",debugstr_w(entry),
|
||||||
|
debugstr_w(string),debugstr_w(section),debugstr_w(filename));
|
||||||
|
WritePrivateProfileStringW(section,entry,string,filename);
|
||||||
|
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL update_ini_fields_callback( HINF hinf, PCWSTR field, void *arg )
|
||||||
|
{
|
||||||
|
FIXME( "should update ini fields %s\n", debugstr_w(field) );
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL ini2reg_callback( HINF hinf, PCWSTR field, void *arg )
|
||||||
|
{
|
||||||
|
FIXME( "should do ini2reg %s\n", debugstr_w(field) );
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL logconf_callback( HINF hinf, PCWSTR field, void *arg )
|
||||||
|
{
|
||||||
|
FIXME( "should do logconf %s\n", debugstr_w(field) );
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* iterate_section_fields
|
||||||
|
*
|
||||||
|
* Iterate over all fields of a certain key of a certain section
|
||||||
|
*/
|
||||||
|
static BOOL iterate_section_fields( HINF hinf, PCWSTR section, PCWSTR key,
|
||||||
|
iterate_fields_func callback, void *arg )
|
||||||
|
{
|
||||||
|
WCHAR static_buffer[200];
|
||||||
|
WCHAR *buffer = static_buffer;
|
||||||
|
DWORD size = sizeof(static_buffer)/sizeof(WCHAR);
|
||||||
|
INFCONTEXT context;
|
||||||
|
BOOL ret = FALSE;
|
||||||
|
|
||||||
|
BOOL ok = SetupFindFirstLineW( hinf, section, key, &context );
|
||||||
|
while (ok)
|
||||||
|
{
|
||||||
|
UINT i, count = SetupGetFieldCount( &context );
|
||||||
|
for (i = 1; i <= count; i++)
|
||||||
|
{
|
||||||
|
if (!(buffer = get_field_string( &context, i, buffer, static_buffer, &size )))
|
||||||
|
goto done;
|
||||||
|
if (!callback( hinf, buffer, arg ))
|
||||||
|
{
|
||||||
|
ERR("callback failed for %s %s\n", debugstr_w(section), debugstr_w(buffer) );
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ok = SetupFindNextMatchLineW( &context, key, &context );
|
||||||
|
}
|
||||||
|
ret = TRUE;
|
||||||
|
done:
|
||||||
|
if (buffer && buffer != static_buffer) HeapFree( GetProcessHeap(), 0, buffer );
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* SetupInstallFilesFromInfSectionA (SETUPAPI.@)
|
||||||
|
*/
|
||||||
|
BOOL WINAPI SetupInstallFilesFromInfSectionA( HINF hinf, HINF hlayout, HSPFILEQ queue,
|
||||||
|
PCSTR section, PCSTR src_root, UINT flags )
|
||||||
|
{
|
||||||
|
UNICODE_STRING sectionW;
|
||||||
|
BOOL ret = FALSE;
|
||||||
|
|
||||||
|
if (!RtlCreateUnicodeStringFromAsciiz( §ionW, section ))
|
||||||
|
{
|
||||||
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (!src_root)
|
||||||
|
ret = SetupInstallFilesFromInfSectionW( hinf, hlayout, queue, sectionW.Buffer,
|
||||||
|
NULL, flags );
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UNICODE_STRING srcW;
|
||||||
|
if (RtlCreateUnicodeStringFromAsciiz( &srcW, src_root ))
|
||||||
|
{
|
||||||
|
ret = SetupInstallFilesFromInfSectionW( hinf, hlayout, queue, sectionW.Buffer,
|
||||||
|
srcW.Buffer, flags );
|
||||||
|
RtlFreeUnicodeString( &srcW );
|
||||||
|
}
|
||||||
|
else SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
||||||
|
}
|
||||||
|
RtlFreeUnicodeString( §ionW );
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* SetupInstallFilesFromInfSectionW (SETUPAPI.@)
|
||||||
|
*/
|
||||||
|
BOOL WINAPI SetupInstallFilesFromInfSectionW( HINF hinf, HINF hlayout, HSPFILEQ queue,
|
||||||
|
PCWSTR section, PCWSTR src_root, UINT flags )
|
||||||
|
{
|
||||||
|
struct files_callback_info info;
|
||||||
|
|
||||||
|
info.queue = queue;
|
||||||
|
info.src_root = src_root;
|
||||||
|
info.copy_flags = flags;
|
||||||
|
info.layout = hlayout;
|
||||||
|
return iterate_section_fields( hinf, section, CopyFiles, copy_files_callback, &info );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* SetupInstallFromInfSectionA (SETUPAPI.@)
|
||||||
|
*/
|
||||||
|
BOOL WINAPI SetupInstallFromInfSectionA( HWND owner, HINF hinf, PCSTR section, UINT flags,
|
||||||
|
HKEY key_root, PCSTR src_root, UINT copy_flags,
|
||||||
|
PSP_FILE_CALLBACK_A callback, PVOID context,
|
||||||
|
HDEVINFO devinfo, PSP_DEVINFO_DATA devinfo_data )
|
||||||
|
{
|
||||||
|
UNICODE_STRING sectionW, src_rootW;
|
||||||
|
struct callback_WtoA_context ctx;
|
||||||
|
BOOL ret = FALSE;
|
||||||
|
|
||||||
|
src_rootW.Buffer = NULL;
|
||||||
|
if (src_root && !RtlCreateUnicodeStringFromAsciiz( &src_rootW, src_root ))
|
||||||
|
{
|
||||||
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RtlCreateUnicodeStringFromAsciiz( §ionW, section ))
|
||||||
|
{
|
||||||
|
ctx.orig_context = context;
|
||||||
|
ctx.orig_handler = callback;
|
||||||
|
ret = SetupInstallFromInfSectionW( owner, hinf, sectionW.Buffer, flags, key_root,
|
||||||
|
src_rootW.Buffer, copy_flags, QUEUE_callback_WtoA,
|
||||||
|
&ctx, devinfo, devinfo_data );
|
||||||
|
RtlFreeUnicodeString( §ionW );
|
||||||
|
}
|
||||||
|
else SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
||||||
|
|
||||||
|
RtlFreeUnicodeString( &src_rootW );
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* SetupInstallFromInfSectionW (SETUPAPI.@)
|
||||||
|
*/
|
||||||
|
BOOL WINAPI SetupInstallFromInfSectionW( HWND owner, HINF hinf, PCWSTR section, UINT flags,
|
||||||
|
HKEY key_root, PCWSTR src_root, UINT copy_flags,
|
||||||
|
PSP_FILE_CALLBACK_W callback, PVOID context,
|
||||||
|
HDEVINFO devinfo, PSP_DEVINFO_DATA devinfo_data )
|
||||||
|
{
|
||||||
|
if (flags & SPINST_FILES)
|
||||||
|
{
|
||||||
|
struct files_callback_info info;
|
||||||
|
HSPFILEQ queue;
|
||||||
|
BOOL ret;
|
||||||
|
|
||||||
|
if (!(queue = SetupOpenFileQueue())) return FALSE;
|
||||||
|
info.queue = queue;
|
||||||
|
info.src_root = src_root;
|
||||||
|
info.copy_flags = copy_flags;
|
||||||
|
info.layout = hinf;
|
||||||
|
ret = (iterate_section_fields( hinf, section, CopyFiles, copy_files_callback, &info ) &&
|
||||||
|
iterate_section_fields( hinf, section, DelFiles, delete_files_callback, &info ) &&
|
||||||
|
iterate_section_fields( hinf, section, RenFiles, rename_files_callback, &info ) &&
|
||||||
|
SetupCommitFileQueueW( owner, queue, callback, context ));
|
||||||
|
SetupCloseFileQueue( queue );
|
||||||
|
if (!ret) return FALSE;
|
||||||
|
}
|
||||||
|
if (flags & SPINST_INIFILES)
|
||||||
|
{
|
||||||
|
if (!iterate_section_fields( hinf, section, UpdateInis, update_ini_callback, NULL ) ||
|
||||||
|
!iterate_section_fields( hinf, section, UpdateIniFields,
|
||||||
|
update_ini_fields_callback, NULL ))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (flags & SPINST_INI2REG)
|
||||||
|
{
|
||||||
|
if (!iterate_section_fields( hinf, section, Ini2Reg, ini2reg_callback, NULL ))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & SPINST_LOGCONFIG)
|
||||||
|
{
|
||||||
|
if (!iterate_section_fields( hinf, section, LogConf, logconf_callback, NULL ))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & SPINST_REGISTRY)
|
||||||
|
{
|
||||||
|
struct registry_callback_info info;
|
||||||
|
|
||||||
|
info.default_root = key_root;
|
||||||
|
info.delete = TRUE;
|
||||||
|
if (!iterate_section_fields( hinf, section, DelReg, registry_callback, &info ))
|
||||||
|
return FALSE;
|
||||||
|
info.delete = FALSE;
|
||||||
|
if (!iterate_section_fields( hinf, section, AddReg, registry_callback, &info ))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (flags & (SPINST_BITREG|SPINST_REGSVR|SPINST_UNREGSVR|SPINST_PROFILEITEMS|SPINST_COPYINF))
|
||||||
|
FIXME( "unsupported flags %x\n", flags );
|
||||||
|
return TRUE;
|
||||||
|
}
|
9
reactos/lib/setupapi/makefile
Normal file
9
reactos/lib/setupapi/makefile
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
# $Id: makefile,v 1.1 2004/01/24 15:39:18 sedwards Exp $
|
||||||
|
|
||||||
|
PATH_TO_TOP = ../..
|
||||||
|
|
||||||
|
TARGET_TYPE = winedll
|
||||||
|
|
||||||
|
include $(PATH_TO_TOP)/rules.mak
|
||||||
|
|
||||||
|
include $(TOOLS_PATH)/helper.mk
|
1797
reactos/lib/setupapi/parser.c
Normal file
1797
reactos/lib/setupapi/parser.c
Normal file
File diff suppressed because it is too large
Load diff
1376
reactos/lib/setupapi/queue.c
Normal file
1376
reactos/lib/setupapi/queue.c
Normal file
File diff suppressed because it is too large
Load diff
38
reactos/lib/setupapi/setupapi.rc
Normal file
38
reactos/lib/setupapi/setupapi.rc
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
#include <defines.h>
|
||||||
|
#include <reactos/resource.h>
|
||||||
|
|
||||||
|
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||||
|
|
||||||
|
VS_VERSION_INFO VERSIONINFO
|
||||||
|
FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD
|
||||||
|
PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD
|
||||||
|
FILEFLAGSMASK 0x3fL
|
||||||
|
#ifdef _DEBUG
|
||||||
|
FILEFLAGS 0x1L
|
||||||
|
#else
|
||||||
|
FILEFLAGS 0x0L
|
||||||
|
#endif
|
||||||
|
FILEOS 0x40004L
|
||||||
|
FILETYPE 0x2L
|
||||||
|
FILESUBTYPE 0x0L
|
||||||
|
BEGIN
|
||||||
|
BLOCK "StringFileInfo"
|
||||||
|
BEGIN
|
||||||
|
BLOCK "040904b0"
|
||||||
|
BEGIN
|
||||||
|
VALUE "CompanyName", RES_STR_COMPANY_NAME
|
||||||
|
VALUE "FileDescription", "WINE IMM32 API Client DLL\0"
|
||||||
|
VALUE "FileVersion", RES_STR_FILE_VERSION
|
||||||
|
VALUE "InternalName", "imm32\0"
|
||||||
|
VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT
|
||||||
|
VALUE "OriginalFilename", "imm32.dll\0"
|
||||||
|
VALUE "ProductName", RES_STR_PRODUCT_NAME
|
||||||
|
VALUE "ProductVersion", RES_STR_PRODUCT_VERSION
|
||||||
|
END
|
||||||
|
END
|
||||||
|
BLOCK "VarFileInfo"
|
||||||
|
BEGIN
|
||||||
|
VALUE "Translation", 0x409, 1200
|
||||||
|
END
|
||||||
|
END
|
||||||
|
|
329
reactos/lib/setupapi/setupapi.spec
Normal file
329
reactos/lib/setupapi/setupapi.spec
Normal file
|
@ -0,0 +1,329 @@
|
||||||
|
@ stdcall CM_Connect_MachineW(wstr ptr)
|
||||||
|
@ stdcall CM_Disconnect_Machine(long)
|
||||||
|
@ stub CM_Free_Log_Conf_Handle
|
||||||
|
@ stub CM_Free_Res_Des_Handle
|
||||||
|
@ stub CM_Get_DevNode_Status_Ex
|
||||||
|
@ stub CM_Get_Device_ID_ExW
|
||||||
|
@ stub CM_Get_First_Log_Conf_Ex
|
||||||
|
@ stub CM_Get_Next_Res_Des_Ex
|
||||||
|
@ stub CM_Get_Res_Des_Data_Ex
|
||||||
|
@ stub CM_Get_Res_Des_Data_Size_Ex
|
||||||
|
@ stub CM_Locate_DevNode_ExW
|
||||||
|
@ stub CM_Reenumerate_DevNode_Ex
|
||||||
|
@ stub CaptureAndConvertAnsiArg
|
||||||
|
@ stub CaptureStringArg
|
||||||
|
@ stub CenterWindowRelativeToParent
|
||||||
|
@ stub ConcatenatePaths
|
||||||
|
@ stub DelayedMove
|
||||||
|
@ stub DelimStringToMultiSz
|
||||||
|
@ stub DestroyTextFileReadBuffer
|
||||||
|
@ stub DoesUserHavePrivilege
|
||||||
|
@ stub DuplicateString
|
||||||
|
@ stub EnablePrivilege
|
||||||
|
@ stub ExtensionPropSheetPageProc
|
||||||
|
@ stub FileExists
|
||||||
|
@ stub FreeStringArray
|
||||||
|
@ stub GetNewInfName
|
||||||
|
@ stub GetSetFileTimestamp
|
||||||
|
@ stub GetVersionInfoFromImage
|
||||||
|
@ stub InfIsFromOemLocation
|
||||||
|
@ stdcall InstallHinfSection(long long str long)
|
||||||
|
@ stub InstallHinfSectionA
|
||||||
|
@ stub InstallHinfSectionW
|
||||||
|
@ stub InstallStop
|
||||||
|
@ stub IsUserAdmin
|
||||||
|
@ stub LookUpStringInTable
|
||||||
|
@ stub MemoryInitialize
|
||||||
|
@ stub MultiByteToUnicode
|
||||||
|
@ stub MultiSzFromSearchControl
|
||||||
|
@ stub MyFree
|
||||||
|
@ stub MyGetFileTitle
|
||||||
|
@ stub MyMalloc
|
||||||
|
@ stub MyRealloc
|
||||||
|
@ stub OpenAndMapFileForRead
|
||||||
|
@ stub OutOfMemory
|
||||||
|
@ stub QueryMultiSzValueToArray
|
||||||
|
@ stub QueryRegistryValue
|
||||||
|
@ stub ReadAsciiOrUnicodeTextFile
|
||||||
|
@ stub RegistryDelnode
|
||||||
|
@ stub RetreiveFileSecurity
|
||||||
|
@ stub RetrieveServiceConfig
|
||||||
|
@ stub SearchForInfFile
|
||||||
|
@ stub SetArrayToMultiSzValue
|
||||||
|
@ stub SetupAddInstallSectionToDiskSpaceListA
|
||||||
|
@ stub SetupAddInstallSectionToDiskSpaceListW
|
||||||
|
@ stub SetupAddSectionToDiskSpaceListA
|
||||||
|
@ stub SetupAddSectionToDiskSpaceListW
|
||||||
|
@ stub SetupAddToDiskSpaceListA
|
||||||
|
@ stub SetupAddToDiskSpaceListW
|
||||||
|
@ stub SetupAddToSourceListA
|
||||||
|
@ stub SetupAddToSourceListW
|
||||||
|
@ stub SetupAdjustDiskSpaceListA
|
||||||
|
@ stub SetupAdjustDiskSpaceListW
|
||||||
|
@ stub SetupCancelTemporarySourceList
|
||||||
|
@ stdcall SetupCloseFileQueue(ptr)
|
||||||
|
@ stdcall SetupCloseInfFile(long)
|
||||||
|
@ stub SetupCommitFileQueue
|
||||||
|
@ stdcall SetupCommitFileQueueA(long long ptr ptr)
|
||||||
|
@ stdcall SetupCommitFileQueueW(long long ptr ptr)
|
||||||
|
@ stub SetupCopyErrorA
|
||||||
|
@ stub SetupCopyErrorW
|
||||||
|
@ stdcall SetupCopyOEMInfA(str str long long ptr long ptr ptr)
|
||||||
|
@ stub SetupCopyOEMInfW
|
||||||
|
@ stub SetupCreateDiskSpaceListA
|
||||||
|
@ stub SetupCreateDiskSpaceListW
|
||||||
|
@ stub SetupDecompressOrCopyFileA
|
||||||
|
@ stub SetupDecompressOrCopyFileW
|
||||||
|
@ stub SetupDefaultQueueCallback
|
||||||
|
@ stdcall SetupDefaultQueueCallbackA(ptr long long long)
|
||||||
|
@ stdcall SetupDefaultQueueCallbackW(ptr long long long)
|
||||||
|
@ stub SetupDeleteErrorA
|
||||||
|
@ stub SetupDeleteErrorW
|
||||||
|
@ stub SetupDestroyDiskSpaceList
|
||||||
|
@ stub SetupDiAskForOEMDisk
|
||||||
|
@ stub SetupDiBuildClassInfoList
|
||||||
|
@ stdcall SetupDiBuildClassInfoListExW(long ptr long ptr wstr ptr)
|
||||||
|
@ stub SetupDiBuildDriverInfoList
|
||||||
|
@ stub SetupDiCallClassInstaller
|
||||||
|
@ stub SetupDiCancelDriverInfoSearch
|
||||||
|
@ stub SetupDiChangeState
|
||||||
|
@ stub SetupDiClassGuidsFromNameA
|
||||||
|
@ stdcall SetupDiClassGuidsFromNameExW(wstr ptr long ptr wstr ptr)
|
||||||
|
@ stub SetupDiClassGuidsFromNameW
|
||||||
|
@ stub SetupDiClassNameFromGuidA
|
||||||
|
@ stdcall SetupDiClassNameFromGuidExW(ptr ptr long ptr wstr ptr)
|
||||||
|
@ stub SetupDiClassNameFromGuidW
|
||||||
|
@ stub SetupDiCreateDevRegKeyA
|
||||||
|
@ stub SetupDiCreateDevRegKeyW
|
||||||
|
@ stub SetupDiCreateDeviceInfoA
|
||||||
|
@ stdcall SetupDiCreateDeviceInfoList(ptr ptr)
|
||||||
|
@ stdcall SetupDiCreateDeviceInfoListExW(ptr long str ptr)
|
||||||
|
@ stub SetupDiCreateDeviceInfoW
|
||||||
|
@ stub SetupDiDeleteDevRegKey
|
||||||
|
@ stub SetupDiDeleteDeviceInfo
|
||||||
|
@ stub SetupDiDestroyClassImageList
|
||||||
|
@ stdcall SetupDiDestroyDeviceInfoList(long)
|
||||||
|
@ stub SetupDiDestroyDriverInfoList
|
||||||
|
@ stub SetupDiDrawMiniIcon
|
||||||
|
@ stdcall SetupDiEnumDeviceInfo(long long ptr)
|
||||||
|
@ stdcall SetupDiEnumDeviceInterfaces(long ptr ptr long ptr)
|
||||||
|
@ stub SetupDiEnumDriverInfoA
|
||||||
|
@ stub SetupDiEnumDriverInfoW
|
||||||
|
@ stub SetupDiGetActualSectionToInstallA
|
||||||
|
@ stub SetupDiGetActualSectionToInstallW
|
||||||
|
@ stub SetupDiGetClassBitmapIndex
|
||||||
|
@ stub SetupDiGetClassDescriptionA
|
||||||
|
@ stdcall SetupDiGetClassDescriptionExW(ptr ptr long ptr wstr ptr)
|
||||||
|
@ stub SetupDiGetClassDescriptionW
|
||||||
|
@ stub SetupDiGetClassDevPropertySheetsA
|
||||||
|
@ stub SetupDiGetClassDevPropertySheetsW
|
||||||
|
@ stdcall SetupDiGetClassDevsA(ptr ptr long long)
|
||||||
|
@ stdcall SetupDiGetClassDevsExA(ptr str ptr long ptr str ptr)
|
||||||
|
@ stdcall SetupDiGetClassDevsExW(ptr wstr ptr long ptr wstr ptr)
|
||||||
|
@ stdcall SetupDiGetClassDevsW(ptr ptr long long)
|
||||||
|
@ stub SetupDiGetClassImageIndex
|
||||||
|
@ stub SetupDiGetClassImageList
|
||||||
|
@ stub SetupDiGetClassImageListExW
|
||||||
|
@ stub SetupDiGetClassInstallParamsA
|
||||||
|
@ stub SetupDiGetClassInstallParamsW
|
||||||
|
@ stub SetupDiGetDeviceInfoListClass
|
||||||
|
@ stdcall SetupDiGetDeviceInfoListDetailA(ptr ptr)
|
||||||
|
@ stdcall SetupDiGetDeviceInfoListDetailW(ptr ptr)
|
||||||
|
@ stub SetupDiGetDeviceInstallParamsA
|
||||||
|
@ stub SetupDiGetDeviceInstallParamsW
|
||||||
|
@ stub SetupDiGetDeviceInstanceIdA
|
||||||
|
@ stub SetupDiGetDeviceInstanceIdW
|
||||||
|
@ stdcall SetupDiGetDeviceRegistryPropertyA(long ptr long ptr ptr long ptr)
|
||||||
|
@ stub SetupDiGetDeviceRegistryPropertyW
|
||||||
|
@ stub SetupDiGetDriverInfoDetailA
|
||||||
|
@ stub SetupDiGetDriverInfoDetailW
|
||||||
|
@ stub SetupDiGetDriverInstallParamsA
|
||||||
|
@ stub SetupDiGetDriverInstallParamsW
|
||||||
|
@ stub SetupDiGetDeviceInterfaceAlias
|
||||||
|
@ stdcall SetupDiGetDeviceInterfaceDetailA(long ptr ptr long ptr ptr)
|
||||||
|
@ stdcall SetupDiGetDeviceInterfaceDetailW(long ptr ptr long ptr ptr)
|
||||||
|
@ stub SetupDiGetHwProfileFriendlyNameA
|
||||||
|
@ stub SetupDiGetHwProfileFriendlyNameW
|
||||||
|
@ stub SetupDiGetHwProfileList
|
||||||
|
@ stub SetupDiGetINFClassA
|
||||||
|
@ stub SetupDiGetINFClassW
|
||||||
|
@ stub SetupDiGetSelectedDevice
|
||||||
|
@ stub SetupDiGetSelectedDriverA
|
||||||
|
@ stub SetupDiGetSelectedDriverW
|
||||||
|
@ stub SetupDiGetWizardPage
|
||||||
|
@ stub SetupDiInstallClassA
|
||||||
|
@ stub SetupDiInstallClassW
|
||||||
|
@ stub SetupDiInstallDevice
|
||||||
|
@ stub SetupDiInstallDriverFiles
|
||||||
|
@ stub SetupDiLoadClassIcon
|
||||||
|
@ stub SetupDiMoveDuplicateDevice
|
||||||
|
@ stub SetupDiOpenClassRegKey
|
||||||
|
@ stdcall SetupDiOpenClassRegKeyExW(ptr long long wstr ptr)
|
||||||
|
@ stub SetupDiOpenDevRegKey
|
||||||
|
@ stub SetupDiOpenDeviceInfoA
|
||||||
|
@ stub SetupDiOpenDeviceInfoW
|
||||||
|
@ stub SetupDiOpenDeviceInterfaceRegKey
|
||||||
|
@ stub SetupDiRegisterDeviceInfo
|
||||||
|
@ stub SetupDiRemoveDevice
|
||||||
|
@ stub SetupDiSelectDevice
|
||||||
|
@ stub SetupDiSelectOEMDrv
|
||||||
|
@ stub SetupDiSetClassInstallParamsA
|
||||||
|
@ stub SetupDiSetClassInstallParamsW
|
||||||
|
@ stub SetupDiSetDeviceInstallParamsA
|
||||||
|
@ stub SetupDiSetDeviceInstallParamsW
|
||||||
|
@ stub SetupDiSetDeviceRegistryPropertyA
|
||||||
|
@ stub SetupDiSetDeviceRegistryPropertyW
|
||||||
|
@ stub SetupDiSetDriverInstallParamsA
|
||||||
|
@ stub SetupDiSetDriverInstallParamsW
|
||||||
|
@ stub SetupDiSetSelectedDevice
|
||||||
|
@ stub SetupDiSetSelectedDriverA
|
||||||
|
@ stub SetupDiSetSelectedDriverW
|
||||||
|
@ stub SetupDuplicateDiskSpaceListA
|
||||||
|
@ stub SetupDuplicateDiskSpaceListW
|
||||||
|
@ stdcall SetupFindFirstLineA(long str str ptr)
|
||||||
|
@ stdcall SetupFindFirstLineW(long wstr wstr ptr)
|
||||||
|
@ stdcall SetupFindNextLine(ptr ptr)
|
||||||
|
@ stdcall SetupFindNextMatchLineA(ptr str ptr)
|
||||||
|
@ stdcall SetupFindNextMatchLineW(ptr wstr ptr)
|
||||||
|
@ stub SetupFreeSourceListA
|
||||||
|
@ stub SetupFreeSourceListW
|
||||||
|
@ stdcall SetupGetBinaryField(ptr long ptr long ptr)
|
||||||
|
@ stdcall SetupGetFieldCount(ptr)
|
||||||
|
@ stub SetupGetFileCompressionInfoA
|
||||||
|
@ stub SetupGetFileCompressionInfoW
|
||||||
|
@ stdcall SetupGetFileQueueCount(long long ptr)
|
||||||
|
@ stdcall SetupGetFileQueueFlags(long ptr)
|
||||||
|
@ stub SetupGetInfFileListA
|
||||||
|
@ stub SetupGetInfFileListW
|
||||||
|
@ stub SetupGetInfInformationA
|
||||||
|
@ stub SetupGetInfInformationW
|
||||||
|
@ stdcall SetupGetIntField(ptr long ptr)
|
||||||
|
@ stdcall SetupGetLineByIndexA(long str long ptr)
|
||||||
|
@ stdcall SetupGetLineByIndexW(long wstr long ptr)
|
||||||
|
@ stdcall SetupGetLineCountA(long str)
|
||||||
|
@ stdcall SetupGetLineCountW(long wstr)
|
||||||
|
@ stdcall SetupGetLineTextA(ptr long str str ptr long ptr)
|
||||||
|
@ stdcall SetupGetLineTextW(ptr long wstr wstr ptr long ptr)
|
||||||
|
@ stdcall SetupGetMultiSzFieldA(ptr long ptr long ptr)
|
||||||
|
@ stdcall SetupGetMultiSzFieldW(ptr long ptr long ptr)
|
||||||
|
@ stub SetupGetSourceFileLocationA
|
||||||
|
@ stub SetupGetSourceFileLocationW
|
||||||
|
@ stub SetupGetSourceFileSizeA
|
||||||
|
@ stub SetupGetSourceFileSizeW
|
||||||
|
@ stub SetupGetSourceInfoA
|
||||||
|
@ stub SetupGetSourceInfoW
|
||||||
|
@ stdcall SetupGetStringFieldA(ptr long ptr long ptr)
|
||||||
|
@ stdcall SetupGetStringFieldW(ptr long ptr long ptr)
|
||||||
|
@ stub SetupGetTargetPathA
|
||||||
|
@ stub SetupGetTargetPathW
|
||||||
|
@ stdcall SetupInitDefaultQueueCallback(long)
|
||||||
|
@ stdcall SetupInitDefaultQueueCallbackEx(long long long long ptr)
|
||||||
|
@ stub SetupInitializeFileLogA
|
||||||
|
@ stub SetupInitializeFileLogW
|
||||||
|
@ stub SetupInstallFileA
|
||||||
|
@ stub SetupInstallFileExA
|
||||||
|
@ stub SetupInstallFileExW
|
||||||
|
@ stub SetupInstallFileW
|
||||||
|
@ stdcall SetupInstallFilesFromInfSectionA(long long long str str long)
|
||||||
|
@ stdcall SetupInstallFilesFromInfSectionW(long long long wstr wstr long)
|
||||||
|
@ stdcall SetupInstallFromInfSectionA(long long str long long str long ptr ptr long ptr)
|
||||||
|
@ stdcall SetupInstallFromInfSectionW(long long wstr long long wstr long ptr ptr long ptr)
|
||||||
|
@ stub SetupInstallServicesFromInfSectionA
|
||||||
|
@ stub SetupInstallServicesFromInfSectionW
|
||||||
|
@ stdcall SetupIterateCabinetA(str long ptr ptr)
|
||||||
|
@ stdcall SetupIterateCabinetW(wstr long ptr ptr)
|
||||||
|
@ stub SetupLogFileA
|
||||||
|
@ stub SetupLogFileW
|
||||||
|
@ stdcall SetupOpenAppendInfFileA(str long ptr)
|
||||||
|
@ stdcall SetupOpenAppendInfFileW(wstr long ptr)
|
||||||
|
@ stdcall SetupOpenFileQueue()
|
||||||
|
@ stdcall SetupOpenInfFileA(str str long ptr)
|
||||||
|
@ stdcall SetupOpenInfFileW(wstr wstr long ptr)
|
||||||
|
@ stub SetupOpenMasterInf
|
||||||
|
@ stub SetupPromptForDiskA
|
||||||
|
@ stub SetupPromptForDiskW
|
||||||
|
@ stub SetupPromptReboot
|
||||||
|
@ stub SetupQueryDrivesInDiskSpaceListA
|
||||||
|
@ stub SetupQueryDrivesInDiskSpaceListW
|
||||||
|
@ stub SetupQueryFileLogA
|
||||||
|
@ stub SetupQueryFileLogW
|
||||||
|
@ stub SetupQueryInfFileInformationA
|
||||||
|
@ stub SetupQueryInfFileInformationW
|
||||||
|
@ stub SetupQueryInfVersionInformationA
|
||||||
|
@ stub SetupQueryInfVersionInformationW
|
||||||
|
@ stub SetupQueryInfOriginalFileInformationW
|
||||||
|
@ stub SetupQuerySourceListA
|
||||||
|
@ stub SetupQuerySourceListW
|
||||||
|
@ stub SetupQuerySpaceRequiredOnDriveA
|
||||||
|
@ stub SetupQuerySpaceRequiredOnDriveW
|
||||||
|
@ stdcall SetupQueueCopyA(long str str str str str str str long)
|
||||||
|
@ stdcall SetupQueueCopyIndirectA(ptr)
|
||||||
|
@ stdcall SetupQueueCopyIndirectW(ptr)
|
||||||
|
@ stdcall SetupQueueCopySectionA(long str long long str long)
|
||||||
|
@ stdcall SetupQueueCopySectionW(long wstr long long wstr long)
|
||||||
|
@ stdcall SetupQueueCopyW(long wstr wstr wstr wstr wstr wstr wstr long)
|
||||||
|
@ stdcall SetupQueueDefaultCopyA(long long str str str long)
|
||||||
|
@ stdcall SetupQueueDefaultCopyW(long long wstr wstr wstr long)
|
||||||
|
@ stdcall SetupQueueDeleteA(long str str)
|
||||||
|
@ stdcall SetupQueueDeleteSectionA(long long long str)
|
||||||
|
@ stdcall SetupQueueDeleteSectionW(long long long wstr)
|
||||||
|
@ stdcall SetupQueueDeleteW(long wstr wstr)
|
||||||
|
@ stdcall SetupQueueRenameA(long str str str str)
|
||||||
|
@ stdcall SetupQueueRenameSectionA(long long long str)
|
||||||
|
@ stdcall SetupQueueRenameSectionW(long long long wstr)
|
||||||
|
@ stdcall SetupQueueRenameW(long wstr wstr wstr wstr)
|
||||||
|
@ stub SetupRemoveFileLogEntryA
|
||||||
|
@ stub SetupRemoveFileLogEntryW
|
||||||
|
@ stub SetupRemoveFromDiskSpaceListA
|
||||||
|
@ stub SetupRemoveFromDiskSpaceListW
|
||||||
|
@ stub SetupRemoveFromSourceListA
|
||||||
|
@ stub SetupRemoveFromSourceListW
|
||||||
|
@ stub SetupRemoveInstallSectionFromDiskSpaceListA
|
||||||
|
@ stub SetupRemoveInstallSectionFromDiskSpaceListW
|
||||||
|
@ stub SetupRemoveSectionFromDiskSpaceListA
|
||||||
|
@ stub SetupRemoveSectionFromDiskSpaceListW
|
||||||
|
@ stub SetupRenameErrorA
|
||||||
|
@ stub SetupRenameErrorW
|
||||||
|
@ stub SetupScanFileQueue
|
||||||
|
@ stdcall SetupScanFileQueueA(long long long ptr ptr ptr)
|
||||||
|
@ stdcall SetupScanFileQueueW(long long long ptr ptr ptr)
|
||||||
|
@ stdcall SetupSetDirectoryIdA(long long str)
|
||||||
|
@ stub SetupSetDirectoryIdExA
|
||||||
|
@ stub SetupSetDirectoryIdExW
|
||||||
|
@ stdcall SetupSetDirectoryIdW(long long wstr)
|
||||||
|
@ stdcall SetupSetFileQueueFlags(long long long)
|
||||||
|
@ stub SetupSetPlatformPathOverrideA
|
||||||
|
@ stub SetupSetPlatformPathOverrideW
|
||||||
|
@ stub SetupSetSourceListA
|
||||||
|
@ stub SetupSetSourceListW
|
||||||
|
@ stdcall SetupTermDefaultQueueCallback(ptr)
|
||||||
|
@ stub SetupTerminateFileLog
|
||||||
|
@ stub ShouldDeviceBeExcluded
|
||||||
|
@ stub StampFileSecurity
|
||||||
|
@ stub StringTableAddString
|
||||||
|
@ stub StringTableAddStringEx
|
||||||
|
@ stub StringTableDestroy
|
||||||
|
@ stub StringTableDuplicate
|
||||||
|
@ stub StringTableEnum
|
||||||
|
@ stub StringTableGetExtraData
|
||||||
|
@ stub StringTableInitialize
|
||||||
|
@ stub StringTableInitializeEx
|
||||||
|
@ stub StringTableLookUpString
|
||||||
|
@ stub StringTableLookUpStringEx
|
||||||
|
@ stub StringTableSetExtraData
|
||||||
|
@ stub StringTableStringFromId
|
||||||
|
@ stub StringTableTrim
|
||||||
|
@ stub TakeOwnershipOfFile
|
||||||
|
@ stub UnicodeToMultiByte
|
||||||
|
@ stub UnmapAndCloseFile
|
||||||
|
@ stub pSetupAddMiniIconToList
|
||||||
|
@ stub pSetupAddTagToGroupOrderListEntry
|
||||||
|
@ stub pSetupAppendStringToMultiSz
|
||||||
|
@ stub pSetupDirectoryIdToPath
|
||||||
|
@ stub pSetupGetField
|
||||||
|
@ stub pSetupGetOsLoaderDriveAndPath
|
||||||
|
@ stub pSetupGetVersionDatum
|
||||||
|
@ stub pSetupGuidFromString
|
||||||
|
@ stub pSetupIsGuidNull
|
||||||
|
@ stub pSetupMakeSurePathExists
|
||||||
|
@ stub pSetupStringFromGuid
|
56
reactos/lib/setupapi/setupapi_private.h
Normal file
56
reactos/lib/setupapi/setupapi_private.h
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2001 Andreas Mohr
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __SETUPAPI_PRIVATE_H
|
||||||
|
#define __SETUPAPI_PRIVATE_H
|
||||||
|
|
||||||
|
#define COPYFILEDLGORD 1000
|
||||||
|
#define SOURCESTRORD 500
|
||||||
|
#define DESTSTRORD 501
|
||||||
|
#define PROGRESSORD 502
|
||||||
|
|
||||||
|
|
||||||
|
#define REG_INSTALLEDFILES "System\\CurrentControlSet\\Control\\InstalledFiles"
|
||||||
|
#define REGPART_RENAME "\\Rename"
|
||||||
|
#define REG_VERSIONCONFLICT "Software\\Microsoft\\VersionConflictManager"
|
||||||
|
|
||||||
|
/* string substitutions */
|
||||||
|
|
||||||
|
struct inf_file;
|
||||||
|
extern const WCHAR *DIRID_get_string( HINF hinf, int dirid );
|
||||||
|
extern unsigned int PARSER_string_substA( struct inf_file *file, const WCHAR *text,
|
||||||
|
char *buffer, unsigned int size );
|
||||||
|
extern unsigned int PARSER_string_substW( struct inf_file *file, const WCHAR *text,
|
||||||
|
WCHAR *buffer, unsigned int size );
|
||||||
|
extern const WCHAR *PARSER_get_src_root( HINF hinf );
|
||||||
|
|
||||||
|
/* support for Ascii queue callback functions */
|
||||||
|
|
||||||
|
struct callback_WtoA_context
|
||||||
|
{
|
||||||
|
void *orig_context;
|
||||||
|
PSP_FILE_CALLBACK_A orig_handler;
|
||||||
|
};
|
||||||
|
|
||||||
|
UINT CALLBACK QUEUE_callback_WtoA( void *context, UINT notification, UINT_PTR, UINT_PTR );
|
||||||
|
|
||||||
|
/* from msvcrt/sys/stat.h */
|
||||||
|
#define _S_IWRITE 0x0080
|
||||||
|
#define _S_IREAD 0x0100
|
||||||
|
|
||||||
|
#endif /* __SETUPAPI_PRIVATE_H */
|
686
reactos/lib/setupapi/setupcab.c
Normal file
686
reactos/lib/setupapi/setupcab.c
Normal file
|
@ -0,0 +1,686 @@
|
||||||
|
/*
|
||||||
|
* Setupapi cabinet routines
|
||||||
|
*
|
||||||
|
* Copyright 2003 Gregory M. Turner
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Many useful traces are commented in code, uncomment them if you have
|
||||||
|
* trouble and run with --debugmsg +setupapi
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include "string.h"
|
||||||
|
#include "stdlib.h"
|
||||||
|
|
||||||
|
#include "wine/debug.h"
|
||||||
|
#include "windef.h"
|
||||||
|
#include "winbase.h"
|
||||||
|
#include "wingdi.h"
|
||||||
|
#include "winuser.h"
|
||||||
|
#include "winnls.h"
|
||||||
|
#include "winreg.h"
|
||||||
|
#include "setupapi.h"
|
||||||
|
#include "setupapi_private.h"
|
||||||
|
#include "fdi.h"
|
||||||
|
#include "wine/unicode.h"
|
||||||
|
|
||||||
|
#include "fcntl.h"
|
||||||
|
#include "share.h"
|
||||||
|
|
||||||
|
#include "wine/debug.h"
|
||||||
|
|
||||||
|
static HINSTANCE CABINET_hInstance = 0;
|
||||||
|
|
||||||
|
static HFDI (__cdecl *sc_FDICreate)(PFNALLOC, PFNFREE, PFNOPEN,
|
||||||
|
PFNREAD, PFNWRITE, PFNCLOSE, PFNSEEK, int, PERF);
|
||||||
|
|
||||||
|
static BOOL (__cdecl *sc_FDICopy)(HFDI, char *, char *, int,
|
||||||
|
PFNFDINOTIFY, PFNFDIDECRYPT, void *);
|
||||||
|
|
||||||
|
static BOOL (__cdecl *sc_FDIDestroy)(HFDI);
|
||||||
|
|
||||||
|
#define SC_HSC_A_MAGIC 0xACABFEED
|
||||||
|
typedef struct {
|
||||||
|
UINT magic;
|
||||||
|
HFDI hfdi;
|
||||||
|
PSP_FILE_CALLBACK_A msghandler;
|
||||||
|
PVOID context;
|
||||||
|
CHAR most_recent_cabinet_name[MAX_PATH];
|
||||||
|
} SC_HSC_A, *PSC_HSC_A;
|
||||||
|
|
||||||
|
#define SC_HSC_W_MAGIC 0x0CABFEED
|
||||||
|
typedef struct {
|
||||||
|
UINT magic;
|
||||||
|
HFDI hfdi;
|
||||||
|
PSP_FILE_CALLBACK_W msghandler;
|
||||||
|
PVOID context;
|
||||||
|
WCHAR most_recent_cabinet_name[MAX_PATH];
|
||||||
|
} SC_HSC_W, *PSC_HSC_W;
|
||||||
|
|
||||||
|
WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
|
||||||
|
|
||||||
|
static BOOL LoadCABINETDll(void)
|
||||||
|
{
|
||||||
|
if (!CABINET_hInstance) {
|
||||||
|
CABINET_hInstance = LoadLibraryA("cabinet.dll");
|
||||||
|
if (CABINET_hInstance) {
|
||||||
|
sc_FDICreate = (void *)GetProcAddress(CABINET_hInstance, "FDICreate");
|
||||||
|
sc_FDICopy = (void *)GetProcAddress(CABINET_hInstance, "FDICopy");
|
||||||
|
sc_FDIDestroy = (void *)GetProcAddress(CABINET_hInstance, "FDIDestroy");
|
||||||
|
return TRUE;
|
||||||
|
} else {
|
||||||
|
ERR("load cabinet dll failed.\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void UnloadCABINETDll(void)
|
||||||
|
{
|
||||||
|
if (CABINET_hInstance) {
|
||||||
|
FreeLibrary(CABINET_hInstance);
|
||||||
|
CABINET_hInstance = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FDICreate callbacks */
|
||||||
|
|
||||||
|
static void *sc_cb_alloc(ULONG cb)
|
||||||
|
{
|
||||||
|
return malloc(cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sc_cb_free(void *pv)
|
||||||
|
{
|
||||||
|
free(pv);
|
||||||
|
}
|
||||||
|
|
||||||
|
static INT_PTR sc_cb_open(char *pszFile, int oflag, int pmode)
|
||||||
|
{
|
||||||
|
DWORD creation = 0, sharing = 0;
|
||||||
|
int ioflag = 0;
|
||||||
|
INT_PTR ret = 0;
|
||||||
|
SECURITY_ATTRIBUTES sa;
|
||||||
|
|
||||||
|
/* TRACE("(pszFile == %s, oflag == %d, pmode == %d)\n", debugstr_a(pszFile), oflag, pmode); */
|
||||||
|
|
||||||
|
switch(oflag & (_O_RDONLY | _O_WRONLY | _O_RDWR)) {
|
||||||
|
case _O_RDONLY:
|
||||||
|
ioflag |= GENERIC_READ;
|
||||||
|
break;
|
||||||
|
case _O_WRONLY:
|
||||||
|
ioflag |= GENERIC_WRITE;
|
||||||
|
break;
|
||||||
|
case _O_RDWR:
|
||||||
|
ioflag |= GENERIC_READ & GENERIC_WRITE;
|
||||||
|
break;
|
||||||
|
case _O_WRONLY | _O_RDWR: /* hmmm.. */
|
||||||
|
ERR("_O_WRONLY & _O_RDWR in oflag?\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oflag & _O_CREAT) {
|
||||||
|
if (oflag & _O_EXCL)
|
||||||
|
creation = CREATE_NEW;
|
||||||
|
else if (oflag & _O_TRUNC)
|
||||||
|
creation = CREATE_ALWAYS;
|
||||||
|
else
|
||||||
|
creation = OPEN_ALWAYS;
|
||||||
|
} else /* no _O_CREAT */ {
|
||||||
|
if (oflag & _O_TRUNC)
|
||||||
|
creation = TRUNCATE_EXISTING;
|
||||||
|
else
|
||||||
|
creation = OPEN_EXISTING;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch( pmode & 0x70 ) {
|
||||||
|
case _SH_DENYRW:
|
||||||
|
sharing = 0L;
|
||||||
|
break;
|
||||||
|
case _SH_DENYWR:
|
||||||
|
sharing = FILE_SHARE_READ;
|
||||||
|
break;
|
||||||
|
case _SH_DENYRD:
|
||||||
|
sharing = FILE_SHARE_WRITE;
|
||||||
|
break;
|
||||||
|
case _SH_COMPAT:
|
||||||
|
case _SH_DENYNO:
|
||||||
|
sharing = FILE_SHARE_READ | FILE_SHARE_WRITE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ERR("<-- -1 (Unhandled pmode 0x%x)\n", pmode);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oflag & ~(_O_BINARY | _O_TRUNC | _O_EXCL | _O_CREAT | _O_RDWR | _O_WRONLY | _O_NOINHERIT))
|
||||||
|
WARN("unsupported oflag 0x%04x\n",oflag);
|
||||||
|
|
||||||
|
sa.nLength = sizeof( SECURITY_ATTRIBUTES );
|
||||||
|
sa.lpSecurityDescriptor = NULL;
|
||||||
|
sa.bInheritHandle = (ioflag & _O_NOINHERIT) ? FALSE : TRUE;
|
||||||
|
|
||||||
|
ret = (INT_PTR) CreateFileA(pszFile, ioflag, sharing, &sa, creation, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
|
|
||||||
|
/* TRACE("<-- %d\n", ret); */
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static UINT sc_cb_read(INT_PTR hf, void *pv, UINT cb)
|
||||||
|
{
|
||||||
|
DWORD num_read;
|
||||||
|
BOOL rslt;
|
||||||
|
|
||||||
|
/* TRACE("(hf == %d, pv == ^%p, cb == %u)\n", hf, pv, cb); */
|
||||||
|
|
||||||
|
rslt = ReadFile((HANDLE) hf, pv, cb, &num_read, NULL);
|
||||||
|
|
||||||
|
|
||||||
|
/* eof and failure both give "-1" return */
|
||||||
|
if ((! rslt) || ((cb > 0) && (num_read == 0))) {
|
||||||
|
/* TRACE("<-- -1\n"); */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TRACE("<-- %lu\n", num_read); */
|
||||||
|
return num_read;
|
||||||
|
}
|
||||||
|
|
||||||
|
static UINT sc_cb_write(INT_PTR hf, void *pv, UINT cb)
|
||||||
|
{
|
||||||
|
DWORD num_written;
|
||||||
|
/* BOOL rv; */
|
||||||
|
|
||||||
|
/* TRACE("(hf == %d, pv == ^%p, cb == %u)\n", hf, pv, cb); */
|
||||||
|
|
||||||
|
if ( /* (rv = */ WriteFile((HANDLE) hf, pv, cb, &num_written, NULL) /* ) */
|
||||||
|
&& (num_written == cb)) {
|
||||||
|
/* TRACE("<-- %lu\n", num_written); */
|
||||||
|
return num_written;
|
||||||
|
} else {
|
||||||
|
/* TRACE("rv == %d, num_written == %lu, cb == %u\n", rv, num_written,cb); */
|
||||||
|
/* TRACE("<-- -1\n"); */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sc_cb_close(INT_PTR hf)
|
||||||
|
{
|
||||||
|
/* TRACE("(hf == %d)\n", hf); */
|
||||||
|
|
||||||
|
if (CloseHandle((HANDLE) hf))
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long sc_cb_lseek(INT_PTR hf, long dist, int seektype)
|
||||||
|
{
|
||||||
|
DWORD ret;
|
||||||
|
|
||||||
|
/* TRACE("(hf == %d, dist == %ld, seektype == %d)\n", hf, dist, seektype); */
|
||||||
|
|
||||||
|
if (seektype < 0 || seektype > 2)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (((ret = SetFilePointer((HANDLE) hf, dist, NULL, seektype)) != INVALID_SET_FILE_POINTER) || !GetLastError()) {
|
||||||
|
/* TRACE("<-- %lu\n", ret); */
|
||||||
|
return ret;
|
||||||
|
} else {
|
||||||
|
/* TRACE("<-- -1\n"); */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SIZEOF_MYSTERIO (MAX_PATH*3)
|
||||||
|
|
||||||
|
/* FDICopy callbacks */
|
||||||
|
|
||||||
|
static INT_PTR sc_FNNOTIFY_A(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin)
|
||||||
|
{
|
||||||
|
FILE_IN_CABINET_INFO_A fici;
|
||||||
|
PSC_HSC_A phsc;
|
||||||
|
CABINET_INFO_A ci;
|
||||||
|
FILEPATHS_A fp;
|
||||||
|
UINT err;
|
||||||
|
|
||||||
|
CHAR mysterio[SIZEOF_MYSTERIO]; /* how big? undocumented! probably 256... */
|
||||||
|
|
||||||
|
memset(&(mysterio[0]), 0, SIZEOF_MYSTERIO);
|
||||||
|
|
||||||
|
TRACE("(fdint == %d, pfdin == ^%p)\n", fdint, pfdin);
|
||||||
|
|
||||||
|
if (pfdin && pfdin->pv && (*((void **) pfdin->pv) == (void *)SC_HSC_A_MAGIC))
|
||||||
|
phsc = (PSC_HSC_A) pfdin->pv;
|
||||||
|
else {
|
||||||
|
ERR("pv %p is not an SC_HSC_A.\n", (pfdin) ? pfdin->pv : NULL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (fdint) {
|
||||||
|
case fdintCABINET_INFO:
|
||||||
|
TRACE("Cabinet info notification\n");
|
||||||
|
/* TRACE(" Cabinet name: %s\n", debugstr_a(pfdin->psz1));
|
||||||
|
TRACE(" Cabinet disk: %s\n", debugstr_a(pfdin->psz2));
|
||||||
|
TRACE(" Cabinet path: %s\n", debugstr_a(pfdin->psz3));
|
||||||
|
TRACE(" Cabinet Set#: %d\n", pfdin->setID);
|
||||||
|
TRACE(" Cabinet Cab#: %d\n", pfdin->iCabinet); */
|
||||||
|
WARN("SPFILENOTIFY_CABINETINFO undocumented: guess implementation.\n");
|
||||||
|
ci.CabinetFile = &(phsc->most_recent_cabinet_name[0]);
|
||||||
|
ci.CabinetPath = pfdin->psz3;
|
||||||
|
ci.DiskName = pfdin->psz2;
|
||||||
|
ci.SetId = pfdin->setID;
|
||||||
|
ci.CabinetNumber = pfdin->iCabinet;
|
||||||
|
phsc->msghandler(phsc->context, SPFILENOTIFY_CABINETINFO, (UINT) &ci, 0);
|
||||||
|
return 0;
|
||||||
|
case fdintPARTIAL_FILE:
|
||||||
|
TRACE("Partial file notification\n");
|
||||||
|
/* TRACE(" Partial file name: %s\n", debugstr_a(pfdin->psz1)); */
|
||||||
|
return 0;
|
||||||
|
case fdintCOPY_FILE:
|
||||||
|
TRACE("Copy file notification\n");
|
||||||
|
TRACE(" File name: %s\n", debugstr_a(pfdin->psz1));
|
||||||
|
/* TRACE(" File size: %ld\n", pfdin->cb);
|
||||||
|
TRACE(" File date: %u\n", pfdin->date);
|
||||||
|
TRACE(" File time: %u\n", pfdin->time);
|
||||||
|
TRACE(" File attr: %u\n", pfdin->attribs); */
|
||||||
|
fici.NameInCabinet = pfdin->psz1;
|
||||||
|
fici.FileSize = pfdin->cb;
|
||||||
|
fici.Win32Error = 0;
|
||||||
|
fici.DosDate = pfdin->date;
|
||||||
|
fici.DosTime = pfdin->time;
|
||||||
|
fici.DosAttribs = pfdin->attribs;
|
||||||
|
memset(&(fici.FullTargetName[0]), 0, MAX_PATH);
|
||||||
|
err = phsc->msghandler(phsc->context, SPFILENOTIFY_FILEINCABINET,
|
||||||
|
(UINT) &fici, (UINT) pfdin->psz1);
|
||||||
|
if (err == FILEOP_DOIT) {
|
||||||
|
TRACE(" Callback specified filename: %s\n", debugstr_a(&(fici.FullTargetName[0])));
|
||||||
|
if (!fici.FullTargetName[0]) {
|
||||||
|
WARN(" Empty return string causing abort.");
|
||||||
|
SetLastError(ERROR_PATH_NOT_FOUND);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return sc_cb_open(&(fici.FullTargetName[0]), _O_BINARY | _O_CREAT | _O_WRONLY, _S_IREAD | _S_IWRITE);
|
||||||
|
} else {
|
||||||
|
TRACE(" Callback skipped file.\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
case fdintCLOSE_FILE_INFO:
|
||||||
|
TRACE("Close file notification\n");
|
||||||
|
/* TRACE(" File name: %s\n", debugstr_a(pfdin->psz1));
|
||||||
|
TRACE(" Exec file? %s\n", (pfdin->cb) ? "Yes" : "No");
|
||||||
|
TRACE(" File hndl: %d\n", pfdin->hf); */
|
||||||
|
fp.Source = &(phsc->most_recent_cabinet_name[0]);
|
||||||
|
fp.Target = pfdin->psz1;
|
||||||
|
fp.Win32Error = 0;
|
||||||
|
fp.Flags = 0;
|
||||||
|
/* the following should be a fixme -- but it occurs too many times */
|
||||||
|
WARN("Should set file date/time/attribs (and execute files?)\n");
|
||||||
|
err = phsc->msghandler(phsc->context, SPFILENOTIFY_FILEEXTRACTED, (UINT) &fp, 0);
|
||||||
|
if (sc_cb_close(pfdin->hf))
|
||||||
|
WARN("_close failed.\n");
|
||||||
|
if (err) {
|
||||||
|
SetLastError(err);
|
||||||
|
return FALSE;
|
||||||
|
} else
|
||||||
|
return TRUE;
|
||||||
|
case fdintNEXT_CABINET:
|
||||||
|
TRACE("Next cabinet notification\n");
|
||||||
|
/* TRACE(" Cabinet name: %s\n", debugstr_a(pfdin->psz1));
|
||||||
|
TRACE(" Cabinet disk: %s\n", debugstr_a(pfdin->psz2));
|
||||||
|
TRACE(" Cabinet path: %s\n", debugstr_a(pfdin->psz3));
|
||||||
|
TRACE(" Cabinet Set#: %d\n", pfdin->setID);
|
||||||
|
TRACE(" Cabinet Cab#: %d\n", pfdin->iCabinet); */
|
||||||
|
ci.CabinetFile = pfdin->psz1;
|
||||||
|
ci.CabinetPath = pfdin->psz3;
|
||||||
|
ci.DiskName = pfdin->psz2;
|
||||||
|
ci.SetId = pfdin->setID;
|
||||||
|
ci.CabinetNumber = pfdin->iCabinet;
|
||||||
|
/* remember the new cabinet name */
|
||||||
|
strcpy(&(phsc->most_recent_cabinet_name[0]), pfdin->psz1);
|
||||||
|
err = phsc->msghandler(phsc->context, SPFILENOTIFY_NEEDNEWCABINET, (UINT) &ci, (UINT) &(mysterio[0]));
|
||||||
|
if (err) {
|
||||||
|
SetLastError(err);
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
if (mysterio[0]) {
|
||||||
|
/* some easy paranoia. no such carefulness exists on the wide API IIRC */
|
||||||
|
mysterio[SIZEOF_MYSTERIO - 1] = '\0';
|
||||||
|
strncpy(pfdin->psz3, &(mysterio[0]), 255);
|
||||||
|
mysterio[255] = '\0';
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
FIXME("Unknown notification type %d.\n", fdint);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static INT_PTR sc_FNNOTIFY_W(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin)
|
||||||
|
{
|
||||||
|
FILE_IN_CABINET_INFO_W fici;
|
||||||
|
PSC_HSC_W phsc;
|
||||||
|
CABINET_INFO_W ci;
|
||||||
|
FILEPATHS_W fp;
|
||||||
|
UINT err;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
WCHAR mysterio[SIZEOF_MYSTERIO]; /* how big? undocumented! */
|
||||||
|
WCHAR buf[MAX_PATH], buf2[MAX_PATH];
|
||||||
|
CHAR charbuf[MAX_PATH];
|
||||||
|
|
||||||
|
memset(&(mysterio[0]), 0, SIZEOF_MYSTERIO * sizeof(WCHAR));
|
||||||
|
memset(&(buf[0]), 0, MAX_PATH * sizeof(WCHAR));
|
||||||
|
memset(&(buf2[0]), 0, MAX_PATH * sizeof(WCHAR));
|
||||||
|
memset(&(charbuf[0]), 0, MAX_PATH);
|
||||||
|
|
||||||
|
TRACE("(fdint == %d, pfdin == ^%p)\n", fdint, pfdin);
|
||||||
|
|
||||||
|
if (pfdin && pfdin->pv && (*((void **) pfdin->pv) == (void *)SC_HSC_W_MAGIC))
|
||||||
|
phsc = (PSC_HSC_W) pfdin->pv;
|
||||||
|
else {
|
||||||
|
ERR("pv %p is not an SC_HSC_W.\n", (pfdin) ? pfdin->pv : NULL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (fdint) {
|
||||||
|
case fdintCABINET_INFO:
|
||||||
|
TRACE("Cabinet info notification\n");
|
||||||
|
/* TRACE(" Cabinet name: %s\n", debugstr_a(pfdin->psz1));
|
||||||
|
TRACE(" Cabinet disk: %s\n", debugstr_a(pfdin->psz2));
|
||||||
|
TRACE(" Cabinet path: %s\n", debugstr_a(pfdin->psz3));
|
||||||
|
TRACE(" Cabinet Set#: %d\n", pfdin->setID);
|
||||||
|
TRACE(" Cabinet Cab#: %d\n", pfdin->iCabinet); */
|
||||||
|
WARN("SPFILENOTIFY_CABINETINFO undocumented: guess implementation.\n");
|
||||||
|
ci.CabinetFile = &(phsc->most_recent_cabinet_name[0]);
|
||||||
|
len = 1 + MultiByteToWideChar(CP_ACP, 0, pfdin->psz3, -1, &(buf[0]), MAX_PATH);
|
||||||
|
if ((len > MAX_PATH) || (len <= 1))
|
||||||
|
buf[0] = '\0';
|
||||||
|
ci.CabinetPath = &(buf[0]);
|
||||||
|
len = 1 + MultiByteToWideChar(CP_ACP, 0, pfdin->psz2, -1, &(buf2[0]), MAX_PATH);
|
||||||
|
if ((len > MAX_PATH) || (len <= 1))
|
||||||
|
buf2[0] = '\0';
|
||||||
|
ci.DiskName = &(buf2[0]);
|
||||||
|
ci.SetId = pfdin->setID;
|
||||||
|
ci.CabinetNumber = pfdin->iCabinet;
|
||||||
|
phsc->msghandler(phsc->context, SPFILENOTIFY_CABINETINFO, (UINT) &ci, 0);
|
||||||
|
return 0;
|
||||||
|
case fdintPARTIAL_FILE:
|
||||||
|
TRACE("Partial file notification\n");
|
||||||
|
/* TRACE(" Partial file name: %s\n", debugstr_a(pfdin->psz1)); */
|
||||||
|
return 0;
|
||||||
|
case fdintCOPY_FILE:
|
||||||
|
TRACE("Copy file notification\n");
|
||||||
|
TRACE(" File name: %s\n", debugstr_a(pfdin->psz1));
|
||||||
|
/* TRACE(" File size: %ld\n", pfdin->cb);
|
||||||
|
TRACE(" File date: %u\n", pfdin->date);
|
||||||
|
TRACE(" File time: %u\n", pfdin->time);
|
||||||
|
TRACE(" File attr: %u\n", pfdin->attribs); */
|
||||||
|
len = 1 + MultiByteToWideChar(CP_ACP, 0, pfdin->psz1, -1, &(buf2[0]), MAX_PATH);
|
||||||
|
if ((len > MAX_PATH) || (len <= 1))
|
||||||
|
buf2[0] = '\0';
|
||||||
|
fici.NameInCabinet = &(buf2[0]);
|
||||||
|
fici.FileSize = pfdin->cb;
|
||||||
|
fici.Win32Error = 0;
|
||||||
|
fici.DosDate = pfdin->date;
|
||||||
|
fici.DosTime = pfdin->time;
|
||||||
|
fici.DosAttribs = pfdin->attribs;
|
||||||
|
memset(&(fici.FullTargetName[0]), 0, MAX_PATH * sizeof(WCHAR));
|
||||||
|
err = phsc->msghandler(phsc->context, SPFILENOTIFY_FILEINCABINET,
|
||||||
|
(UINT) &fici, (UINT) pfdin->psz1);
|
||||||
|
if (err == FILEOP_DOIT) {
|
||||||
|
TRACE(" Callback specified filename: %s\n", debugstr_w(&(fici.FullTargetName[0])));
|
||||||
|
if (fici.FullTargetName[0]) {
|
||||||
|
len = strlenW(&(fici.FullTargetName[0])) + 1;
|
||||||
|
if ((len > MAX_PATH ) || (len <= 1))
|
||||||
|
return 0;
|
||||||
|
if (!WideCharToMultiByte(CP_ACP, 0, &(fici.FullTargetName[0]), len, &(charbuf[0]), MAX_PATH, 0, 0))
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
WARN("Empty buffer string caused abort.\n");
|
||||||
|
SetLastError(ERROR_PATH_NOT_FOUND);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return sc_cb_open(&(charbuf[0]), _O_BINARY | _O_CREAT | _O_WRONLY, _S_IREAD | _S_IWRITE);
|
||||||
|
} else {
|
||||||
|
TRACE(" Callback skipped file.\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
case fdintCLOSE_FILE_INFO:
|
||||||
|
TRACE("Close file notification\n");
|
||||||
|
/* TRACE(" File name: %s\n", debugstr_a(pfdin->psz1));
|
||||||
|
TRACE(" Exec file? %s\n", (pfdin->cb) ? "Yes" : "No");
|
||||||
|
TRACE(" File hndl: %d\n", pfdin->hf); */
|
||||||
|
fp.Source = &(phsc->most_recent_cabinet_name[0]);
|
||||||
|
len = 1 + MultiByteToWideChar(CP_ACP, 0, pfdin->psz1, -1, &(buf[0]), MAX_PATH);
|
||||||
|
if ((len > MAX_PATH) || (len <= 1))
|
||||||
|
buf[0] = '\0';
|
||||||
|
fp.Target = &(buf[0]);
|
||||||
|
fp.Win32Error = 0;
|
||||||
|
fp.Flags = 0;
|
||||||
|
/* a valid fixme -- but occurs too many times */
|
||||||
|
/* FIXME("Should set file date/time/attribs (and execute files?)\n"); */
|
||||||
|
err = phsc->msghandler(phsc->context, SPFILENOTIFY_FILEEXTRACTED, (UINT) &fp, 0);
|
||||||
|
if (sc_cb_close(pfdin->hf))
|
||||||
|
WARN("_close failed.\n");
|
||||||
|
if (err) {
|
||||||
|
SetLastError(err);
|
||||||
|
return FALSE;
|
||||||
|
} else
|
||||||
|
return TRUE;
|
||||||
|
case fdintNEXT_CABINET:
|
||||||
|
TRACE("Next cabinet notification\n");
|
||||||
|
/* TRACE(" Cabinet name: %s\n", debugstr_a(pfdin->psz1));
|
||||||
|
TRACE(" Cabinet disk: %s\n", debugstr_a(pfdin->psz2));
|
||||||
|
TRACE(" Cabinet path: %s\n", debugstr_a(pfdin->psz3));
|
||||||
|
TRACE(" Cabinet Set#: %d\n", pfdin->setID);
|
||||||
|
TRACE(" Cabinet Cab#: %d\n", pfdin->iCabinet); */
|
||||||
|
/* remember the new cabinet name */
|
||||||
|
len = 1 + MultiByteToWideChar(CP_ACP, 0, pfdin->psz1, -1, &(phsc->most_recent_cabinet_name[0]), MAX_PATH);
|
||||||
|
if ((len > MAX_PATH) || (len <= 1))
|
||||||
|
phsc->most_recent_cabinet_name[0] = '\0';
|
||||||
|
ci.CabinetFile = &(phsc->most_recent_cabinet_name[0]);
|
||||||
|
len = 1 + MultiByteToWideChar(CP_ACP, 0, pfdin->psz3, -1, &(buf[0]), MAX_PATH);
|
||||||
|
if ((len > MAX_PATH) || (len <= 1))
|
||||||
|
buf[0] = '\0';
|
||||||
|
ci.CabinetPath = &(buf[0]);
|
||||||
|
len = 1 + MultiByteToWideChar(CP_ACP, 0, pfdin->psz2, -1, &(buf2[0]), MAX_PATH);
|
||||||
|
if ((len > MAX_PATH) || (len <= 1))
|
||||||
|
buf2[0] = '\0';
|
||||||
|
ci.DiskName = &(buf2[0]);
|
||||||
|
ci.SetId = pfdin->setID;
|
||||||
|
ci.CabinetNumber = pfdin->iCabinet;
|
||||||
|
err = phsc->msghandler(phsc->context, SPFILENOTIFY_NEEDNEWCABINET, (UINT) &ci, (UINT) &(mysterio[0]));
|
||||||
|
if (err) {
|
||||||
|
SetLastError(err);
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
if (mysterio[0]) {
|
||||||
|
len = strlenW(&(mysterio[0])) + 1;
|
||||||
|
if ((len > 255) || (len <= 1))
|
||||||
|
return 0;
|
||||||
|
if (!WideCharToMultiByte(CP_ACP, 0, &(mysterio[0]), len, pfdin->psz3, 255, 0, 0))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
FIXME("Unknown notification type %d.\n", fdint);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* SetupIterateCabinetA (SETUPAPI.@)
|
||||||
|
*/
|
||||||
|
BOOL WINAPI SetupIterateCabinetA(PCSTR CabinetFile, DWORD Reserved,
|
||||||
|
PSP_FILE_CALLBACK_A MsgHandler, PVOID Context)
|
||||||
|
{
|
||||||
|
|
||||||
|
SC_HSC_A my_hsc;
|
||||||
|
ERF erf;
|
||||||
|
CHAR pszCabinet[MAX_PATH], pszCabPath[MAX_PATH], *p;
|
||||||
|
DWORD fpnsize;
|
||||||
|
BOOL ret;
|
||||||
|
|
||||||
|
|
||||||
|
TRACE("(CabinetFile == %s, Reserved == %lu, MsgHandler == ^%p, Context == ^%p)\n",
|
||||||
|
debugstr_a(CabinetFile), Reserved, MsgHandler, Context);
|
||||||
|
|
||||||
|
if (! LoadCABINETDll())
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
memset(&my_hsc, 0, sizeof(SC_HSC_A));
|
||||||
|
pszCabinet[0] = '\0';
|
||||||
|
pszCabPath[0] = '\0';
|
||||||
|
|
||||||
|
fpnsize = strlen(CabinetFile);
|
||||||
|
if (fpnsize >= MAX_PATH) {
|
||||||
|
SetLastError(ERROR_BAD_PATHNAME);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
fpnsize = GetFullPathNameA(CabinetFile, MAX_PATH, &(pszCabPath[0]), &p);
|
||||||
|
if (fpnsize > MAX_PATH) {
|
||||||
|
SetLastError(ERROR_BAD_PATHNAME);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p) {
|
||||||
|
strcpy(pszCabinet, p);
|
||||||
|
*p = '\0';
|
||||||
|
} else {
|
||||||
|
strcpy(pszCabinet, CabinetFile);
|
||||||
|
pszCabPath[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE("path: %s, cabfile: %s\n", debugstr_a(pszCabPath), debugstr_a(pszCabinet));
|
||||||
|
|
||||||
|
/* remember the cabinet name */
|
||||||
|
strcpy(&(my_hsc.most_recent_cabinet_name[0]), pszCabinet);
|
||||||
|
|
||||||
|
my_hsc.magic = SC_HSC_A_MAGIC;
|
||||||
|
my_hsc.msghandler = MsgHandler;
|
||||||
|
my_hsc.context = Context;
|
||||||
|
my_hsc.hfdi = sc_FDICreate( sc_cb_alloc, sc_cb_free, sc_cb_open, sc_cb_read,
|
||||||
|
sc_cb_write, sc_cb_close, sc_cb_lseek, cpuUNKNOWN, &erf );
|
||||||
|
|
||||||
|
if (!my_hsc.hfdi) return FALSE;
|
||||||
|
|
||||||
|
ret = ( sc_FDICopy(my_hsc.hfdi, pszCabinet, pszCabPath,
|
||||||
|
0, sc_FNNOTIFY_A, NULL, &my_hsc) ) ? TRUE : FALSE;
|
||||||
|
|
||||||
|
sc_FDIDestroy(my_hsc.hfdi);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* SetupIterateCabinetW (SETUPAPI.@)
|
||||||
|
*/
|
||||||
|
BOOL WINAPI SetupIterateCabinetW(PCWSTR CabinetFile, DWORD Reserved,
|
||||||
|
PSP_FILE_CALLBACK_W MsgHandler, PVOID Context)
|
||||||
|
{
|
||||||
|
CHAR CabinetFile_A[MAX_PATH];
|
||||||
|
unsigned int len;
|
||||||
|
SC_HSC_W my_hsc;
|
||||||
|
ERF erf;
|
||||||
|
CHAR pszCabinet[MAX_PATH], pszCabPath[MAX_PATH], *p;
|
||||||
|
DWORD fpnsize;
|
||||||
|
BOOL ret;
|
||||||
|
|
||||||
|
TRACE("(CabinetFile == %s, Reserved == %lu, MsgHandler == ^%p, Context == ^%p)\n",
|
||||||
|
debugstr_w(CabinetFile), Reserved, MsgHandler, Context);
|
||||||
|
|
||||||
|
if (!LoadCABINETDll())
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (!CabinetFile) return FALSE;
|
||||||
|
if (!WideCharToMultiByte(CP_ACP, 0, CabinetFile, -1, CabinetFile_A, MAX_PATH, 0, 0))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
memset(&my_hsc, 0, sizeof(SC_HSC_W));
|
||||||
|
pszCabinet[0] = '\0';
|
||||||
|
pszCabPath[0] = '\0';
|
||||||
|
|
||||||
|
fpnsize = GetFullPathNameA(CabinetFile_A, MAX_PATH, &(pszCabPath[0]), &p);
|
||||||
|
if (fpnsize > MAX_PATH) {
|
||||||
|
SetLastError(ERROR_BAD_PATHNAME);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p) {
|
||||||
|
strcpy(pszCabinet, p);
|
||||||
|
*p = '\0';
|
||||||
|
} else {
|
||||||
|
strcpy(pszCabinet, CabinetFile_A);
|
||||||
|
pszCabPath[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE("path: %s, cabfile: %s\n", debugstr_a(pszCabPath), debugstr_a(pszCabinet));
|
||||||
|
|
||||||
|
/* remember the cabinet name */
|
||||||
|
len = 1 + MultiByteToWideChar(CP_ACP, 0, pszCabinet, -1,
|
||||||
|
&(my_hsc.most_recent_cabinet_name[0]), MAX_PATH);
|
||||||
|
if (len > MAX_PATH)
|
||||||
|
return FALSE;
|
||||||
|
else if (len <= 1)
|
||||||
|
my_hsc.most_recent_cabinet_name[0] = '\0';
|
||||||
|
my_hsc.magic = SC_HSC_W_MAGIC;
|
||||||
|
my_hsc.msghandler = MsgHandler;
|
||||||
|
my_hsc.context = Context;
|
||||||
|
my_hsc.hfdi = sc_FDICreate( sc_cb_alloc, sc_cb_free, sc_cb_open, sc_cb_read,
|
||||||
|
sc_cb_write, sc_cb_close, sc_cb_lseek, cpuUNKNOWN, &erf );
|
||||||
|
|
||||||
|
if (!my_hsc.hfdi) return FALSE;
|
||||||
|
|
||||||
|
ret = ( sc_FDICopy(my_hsc.hfdi, pszCabinet, pszCabPath,
|
||||||
|
0, sc_FNNOTIFY_W, NULL, &my_hsc) ) ? TRUE : FALSE;
|
||||||
|
|
||||||
|
sc_FDIDestroy(my_hsc.hfdi);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* DllMain
|
||||||
|
*
|
||||||
|
* PARAMS
|
||||||
|
* hinstDLL [I] handle to the DLL's instance
|
||||||
|
* fdwReason [I]
|
||||||
|
* lpvReserved [I] reserved, must be NULL
|
||||||
|
*
|
||||||
|
* RETURNS
|
||||||
|
* Success: TRUE
|
||||||
|
* Failure: FALSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
||||||
|
{
|
||||||
|
switch (fdwReason) {
|
||||||
|
case DLL_PROCESS_ATTACH:
|
||||||
|
DisableThreadLibraryCalls(hinstDLL);
|
||||||
|
break;
|
||||||
|
case DLL_PROCESS_DETACH:
|
||||||
|
UnloadCABINETDll();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
562
reactos/lib/setupapi/setupx16.h
Normal file
562
reactos/lib/setupapi/setupx16.h
Normal file
|
@ -0,0 +1,562 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2000 Andreas Mohr for CodeWeavers
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __SETUPX16_H
|
||||||
|
#define __SETUPX16_H
|
||||||
|
|
||||||
|
#include "wine/windef16.h"
|
||||||
|
|
||||||
|
typedef UINT16 HINF16;
|
||||||
|
typedef UINT16 LOGDISKID16;
|
||||||
|
typedef UINT16 VHSTR;
|
||||||
|
|
||||||
|
#define LINE_LEN 256
|
||||||
|
|
||||||
|
/* error codes stuff */
|
||||||
|
|
||||||
|
typedef UINT16 RETERR16;
|
||||||
|
#define OK 0
|
||||||
|
#define IP_ERROR (UINT16)100
|
||||||
|
#define TP_ERROR (UINT16)200
|
||||||
|
#define VCP_ERROR (UINT16)300
|
||||||
|
#define GEN_ERROR (UINT16)400
|
||||||
|
#define DI_ERROR (UINT16)500
|
||||||
|
|
||||||
|
enum {
|
||||||
|
ERR_IP_INVALID_FILENAME = IP_ERROR+1,
|
||||||
|
ERR_IP_ALLOC_ERR,
|
||||||
|
ERR_IP_INVALID_SECT_NAME,
|
||||||
|
ERR_IP_OUT_OF_HANDLES,
|
||||||
|
ERR_IP_INF_NOT_FOUND,
|
||||||
|
ERR_IP_INVALID_INFFILE,
|
||||||
|
ERR_IP_INVALID_HINF,
|
||||||
|
ERR_IP_INVALID_FIELD,
|
||||||
|
ERR_IP_SECT_NOT_FOUND,
|
||||||
|
ERR_IP_END_OF_SECTION,
|
||||||
|
ERR_IP_PROFILE_NOT_FOUND,
|
||||||
|
ERR_IP_LINE_NOT_FOUND,
|
||||||
|
ERR_IP_FILEREAD,
|
||||||
|
ERR_IP_TOOMANYINFFILES,
|
||||||
|
ERR_IP_INVALID_SAVERESTORE,
|
||||||
|
ERR_IP_INVALID_INFTYPE
|
||||||
|
};
|
||||||
|
|
||||||
|
/****** virtual copy operations ******/
|
||||||
|
|
||||||
|
typedef DWORD LPEXPANDVTBL;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
DWORD dwSoFar;
|
||||||
|
DWORD dwTotal;
|
||||||
|
} VCPPROGRESS, *LPVCPPROGRESS;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
WORD cbSize;
|
||||||
|
LOGDISKID16 ldid;
|
||||||
|
VHSTR vhstrRoot;
|
||||||
|
VHSTR vhstrVolumeLabel;
|
||||||
|
VHSTR vhstrDiskName;
|
||||||
|
WORD wVolumeTime;
|
||||||
|
WORD wVolumeDate;
|
||||||
|
DWORD dwSerialNumber;
|
||||||
|
WORD fl;
|
||||||
|
LPARAM lparamRef;
|
||||||
|
|
||||||
|
VCPPROGRESS prgFileRead;
|
||||||
|
VCPPROGRESS prgByteRead;
|
||||||
|
|
||||||
|
VCPPROGRESS prgFileWrite;
|
||||||
|
VCPPROGRESS prgByteWrite;
|
||||||
|
} VCPDISKINFO, *LPVCPDISKINFO;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
LOGDISKID16 ldid;
|
||||||
|
VHSTR vhstrDir;
|
||||||
|
VHSTR vhstrFileName;
|
||||||
|
} VCPFILESPEC, *LPVCPFILESPEC;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UINT16 uiMDate;
|
||||||
|
UINT16 uiMTime;
|
||||||
|
UINT16 uiADate;
|
||||||
|
UINT16 uiATime;
|
||||||
|
UINT16 uiAttr;
|
||||||
|
DWORD llenIn;
|
||||||
|
DWORD llenOut;
|
||||||
|
} VCPFATTR, *LPVCPFATTR;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UINT16 uDate;
|
||||||
|
UINT16 uTime;
|
||||||
|
DWORD dwSize;
|
||||||
|
} VCPFILESTAT, *LPVCPFILESTAT;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
HFILE16 hFileSrc;
|
||||||
|
HFILE16 hFileDst;
|
||||||
|
VCPFATTR fAttr;
|
||||||
|
WORD dosError;
|
||||||
|
VHSTR vhstrFileName;
|
||||||
|
WPARAM vcpm;
|
||||||
|
} VIRTNODEEX, *LPVIRTNODEEX;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
WORD cbSize;
|
||||||
|
VCPFILESPEC vfsSrc;
|
||||||
|
VCPFILESPEC vfsDst;
|
||||||
|
WORD fl;
|
||||||
|
LPARAM lParam;
|
||||||
|
LPEXPANDVTBL lpExpandVtbl;
|
||||||
|
LPVIRTNODEEX lpvnex;
|
||||||
|
VHSTR vhstrDstFinalName;
|
||||||
|
VCPFILESTAT vFileStat;
|
||||||
|
} VIRTNODE, *LPVIRTNODE;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
WORD cbSize;
|
||||||
|
VCPPROGRESS prgDiskRead;
|
||||||
|
VCPPROGRESS prgFileRead;
|
||||||
|
VCPPROGRESS prgByteRead;
|
||||||
|
|
||||||
|
VCPPROGRESS prgDiskWrite;
|
||||||
|
VCPPROGRESS prgFileWrite;
|
||||||
|
VCPPROGRESS prgByteWrite;
|
||||||
|
|
||||||
|
LPVCPDISKINFO lpvdiIn;
|
||||||
|
LPVCPDISKINFO lpvdiOut;
|
||||||
|
LPVIRTNODE lpvn;
|
||||||
|
} VCPSTATUS, *LPVCPSTATUS;
|
||||||
|
|
||||||
|
#define CNFL_BACKUP 0x0001
|
||||||
|
#define CNFL_DELETEONFAILURE 0x0002
|
||||||
|
#define CNFL_RENAMEONSUCCESS 0x0004
|
||||||
|
#define CNFL_CONTINUATION 0x0008
|
||||||
|
#define CNFL_SKIPPED 0x0010
|
||||||
|
#define CNFL_IGNOREERRORS 0x0020
|
||||||
|
#define CNFL_RETRYFILE 0x0040
|
||||||
|
#define CNFL_COPIED 0x0080
|
||||||
|
#define VNFL_UNIQUE 0x0000
|
||||||
|
#define VNFL_MULTIPLEOK 0x0100
|
||||||
|
#define VNFL_DESTROYOLD 0x0200
|
||||||
|
#define VNFL_COPY 0x0000
|
||||||
|
#define VNFL_DELETE 0x0800
|
||||||
|
#define VNFL_RENAME 0x1000
|
||||||
|
#define VNFL_NODE_TYPE (VNFL_RENAME|VNFL_DELETE|VNFL_COPY)
|
||||||
|
#define VNFL_CREATED 0x2000
|
||||||
|
#define VNFL_REJECTED 0x4000
|
||||||
|
#define VNFL_DEVICEINSTALLER 0x8000
|
||||||
|
|
||||||
|
enum {
|
||||||
|
ERR_VCP_IOFAIL = VCP_ERROR+1,
|
||||||
|
ERR_VCP_STRINGTOOLONG,
|
||||||
|
ERR_VCP_NOMEM,
|
||||||
|
ERR_VCP_QUEUEFULL,
|
||||||
|
ERR_VCP_NOVHSTR,
|
||||||
|
ERR_VCP_OVERFLOW,
|
||||||
|
ERR_VCP_BADARG,
|
||||||
|
ERR_VCP_UNINIT,
|
||||||
|
ERR_VCP_NOTFOUND,
|
||||||
|
ERR_VCP_BUSY,
|
||||||
|
ERR_VCP_INTERRUPTED,
|
||||||
|
ERR_VCP_BADDEST,
|
||||||
|
ERR_VCP_SKIPPED,
|
||||||
|
ERR_VCP_IO,
|
||||||
|
ERR_VCP_LOCKED,
|
||||||
|
ERR_VCP_WRONGDISK,
|
||||||
|
ERR_VCP_CHANGEMODE,
|
||||||
|
ERR_VCP_LDDINVALID,
|
||||||
|
ERR_VCP_LDDFIND,
|
||||||
|
ERR_VCP_LDDUNINIT,
|
||||||
|
ERR_VCP_LDDPATH_INVALID,
|
||||||
|
ERR_VCP_NOEXPANSION,
|
||||||
|
ERR_VCP_NOTOPEN,
|
||||||
|
ERR_VCP_NO_DIGITAL_SIGNATURE_CATALOG,
|
||||||
|
ERR_VCP_NO_DIGITAL_SIGNATURE_FILE
|
||||||
|
};
|
||||||
|
|
||||||
|
#define VCPN_OK 0
|
||||||
|
#define VCPN_PROCEED 0
|
||||||
|
#define VCPN_ABORT -1
|
||||||
|
#define VCPN_RETRY -2
|
||||||
|
#define VCPN_IGNORE -3
|
||||||
|
#define VCPN_SKIP -4
|
||||||
|
#define VCPN_FORCE -5
|
||||||
|
#define VCPN_DEFER -6
|
||||||
|
#define VCPN_FAIL -7
|
||||||
|
#define VCPN_RETRYFILE -8
|
||||||
|
|
||||||
|
#define VCPFL_ABANDON 0x00
|
||||||
|
#define VCPFL_BACKUP 0x01
|
||||||
|
#define VCPFL_COPY 0x02
|
||||||
|
#define VCPFL_BACKUPANDCOPY (VCPFL_BACKUP|VCPFL_COPY)
|
||||||
|
#define VCPFL_INSPECIFIEDORDER 0x04
|
||||||
|
#define VCPFL_DELETE 0x08
|
||||||
|
#define VCPFL_RENAME 0x10
|
||||||
|
#define VCPFL_ALL (VCPFL_COPY|VCPFL_DELETE|VCPFL_RENAME)
|
||||||
|
|
||||||
|
#define CFNL_BACKUP 0x0001
|
||||||
|
#define CFNL_DELETEONFAILURE 0x0002
|
||||||
|
#define CFNL_RENAMEONSUCCESS 0x0004
|
||||||
|
#define CFNL_CONTINUATION 0x0008
|
||||||
|
#define CFNL_SKIPPED 0x0010
|
||||||
|
#define CFNL_IGNOREERRORS 0x0020
|
||||||
|
#define CFNL_RETRYFILE 0x0040
|
||||||
|
#define CFNL_COPIED 0x0080
|
||||||
|
#define VFNL_MULTIPLEOK 0x0100
|
||||||
|
#define VFNL_DESTROYOLD 0x0200
|
||||||
|
#define VFNL_NOW 0x0400
|
||||||
|
#define VFNL_COPY 0x0000
|
||||||
|
#define VFNL_DELETE 0x0800
|
||||||
|
#define VFNL_RENAME 0x1000
|
||||||
|
#define VFNL_CREATED 0x2000
|
||||||
|
#define VFNL_REJECTED 0x4000
|
||||||
|
#define VCPM_DISKCLASS 0x01
|
||||||
|
#define VCPM_DISKFIRST 0x0100
|
||||||
|
#define VCPM_DISKLAST 0x01ff
|
||||||
|
|
||||||
|
enum {
|
||||||
|
VCPM_DISKCREATEINFO = VCPM_DISKFIRST,
|
||||||
|
VCPM_DISKGETINFO,
|
||||||
|
VCPM_DISKDESTROYINFO,
|
||||||
|
VCPM_DISKPREPINFO,
|
||||||
|
VCPM_DISKENSURE,
|
||||||
|
VCPM_DISKPROMPT,
|
||||||
|
VCPM_DISKFORMATBEGIN,
|
||||||
|
VCPM_DISKFORMATTING,
|
||||||
|
VCPM_DISKFORMATEND
|
||||||
|
};
|
||||||
|
|
||||||
|
#define VCPM_FILEINCLASS 0x02
|
||||||
|
#define VCPM_FILEOUTCLASS 0x03
|
||||||
|
#define VCPM_FILEFIRSTIN 0x0200
|
||||||
|
#define VCPM_FILEFIRSTOUT 0x0300
|
||||||
|
#define VCPM_FILELAST 0x03ff
|
||||||
|
|
||||||
|
enum {
|
||||||
|
VCPM_FILEOPENIN = VCPM_FILEFIRSTIN,
|
||||||
|
VCPM_FILEGETFATTR,
|
||||||
|
VCPM_FILECLOSEIN,
|
||||||
|
VCPM_FILECOPY,
|
||||||
|
VCPM_FILENEEDED,
|
||||||
|
|
||||||
|
VCPM_FILEOPENOUT = VCPM_FILEFIRSTOUT,
|
||||||
|
VCPM_FILESETFATTR,
|
||||||
|
VCPM_FILECLOSEOUT,
|
||||||
|
VCPM_FILEFINALIZE,
|
||||||
|
VCPM_FILEDELETE,
|
||||||
|
VCPM_FILERENAME
|
||||||
|
};
|
||||||
|
|
||||||
|
#define VCPM_NODECLASS 0x04
|
||||||
|
#define VCPM_NODEFIRST 0x0400
|
||||||
|
#define VCPM_NODELAST 0x04ff
|
||||||
|
|
||||||
|
enum {
|
||||||
|
VCPM_NODECREATE = VCPM_NODEFIRST,
|
||||||
|
VCPM_NODEACCEPT,
|
||||||
|
VCPM_NODEREJECT,
|
||||||
|
VCPM_NODEDESTROY,
|
||||||
|
VCPM_NODECHANGEDESTDIR,
|
||||||
|
VCPM_NODECOMPARE
|
||||||
|
};
|
||||||
|
|
||||||
|
#define VCPM_TALLYCLASS 0x05
|
||||||
|
#define VCPM_TALLYFIRST 0x0500
|
||||||
|
#define VCPM_TALLYLAST 0x05ff
|
||||||
|
|
||||||
|
enum {
|
||||||
|
VCPM_TALLYSTART = VCPM_TALLYFIRST,
|
||||||
|
VCPM_TALLYEND,
|
||||||
|
VCPM_TALLYFILE,
|
||||||
|
VCPM_TALLYDISK
|
||||||
|
};
|
||||||
|
|
||||||
|
#define VCPM_VERCLASS 0x06
|
||||||
|
#define VCPM_VERFIRST 0x0600
|
||||||
|
#define VCPM_VERLAST 0x06ff
|
||||||
|
|
||||||
|
enum {
|
||||||
|
VCPM_VERCHECK = VCPM_VERFIRST,
|
||||||
|
VCPM_VERCHECKDONE,
|
||||||
|
VCPM_VERRESOLVECONFLICT
|
||||||
|
};
|
||||||
|
|
||||||
|
#define VCPM_VSTATCLASS 0x07
|
||||||
|
#define VCPM_VSTATFIRST 0x0700
|
||||||
|
#define VCPM_VSTATLAST 0x07ff
|
||||||
|
|
||||||
|
enum {
|
||||||
|
VCPM_VSTATSTART = VCPM_VSTATFIRST,
|
||||||
|
VCPM_VSTATEND,
|
||||||
|
VCPM_VSTATREAD,
|
||||||
|
VCPM_VSTATWRITE,
|
||||||
|
VCPM_VSTATNEWDISK,
|
||||||
|
VCPM_VSTATCLOSESTART,
|
||||||
|
VCPM_VSTATCLOSEEND,
|
||||||
|
VCPM_VSTATBACKUPSTART,
|
||||||
|
VCPM_VSTATBACKUPEND,
|
||||||
|
VCPM_VSTATRENAMESTART,
|
||||||
|
VCPM_VSTATRENAMEEND,
|
||||||
|
VCPM_VSTATCOPYSTART,
|
||||||
|
VCPM_VSTATCOPYEND,
|
||||||
|
VCPM_VSTATDELETESTART,
|
||||||
|
VCPM_VSTATDELETEEND,
|
||||||
|
VCPM_VSTATPATHCHECKSTART,
|
||||||
|
VCPM_VSTATPATHCHECKEND,
|
||||||
|
VCPM_VSTATCERTIFYSTART,
|
||||||
|
VCPM_VSTATCERTIFYEND,
|
||||||
|
VCPM_VSTATUSERABORT,
|
||||||
|
VCPM_VSTATYIELD
|
||||||
|
};
|
||||||
|
|
||||||
|
#define VCPM_PATHCLASS 0x08
|
||||||
|
#define VCPM_PATHFIRST 0x0800
|
||||||
|
#define VCPM_PATHLAST 0x08ff
|
||||||
|
|
||||||
|
enum {
|
||||||
|
VCPM_BUILDPATH = VCPM_PATHFIRST,
|
||||||
|
VCPM_UNIQUEPATH,
|
||||||
|
VCPM_CHECKPATH
|
||||||
|
};
|
||||||
|
|
||||||
|
#define VCPM_PATCHCLASS 0x09
|
||||||
|
#define VCPM_PATCHFIRST 0x0900
|
||||||
|
#define VCPM_PATCHLAST 0x09ff
|
||||||
|
|
||||||
|
enum {
|
||||||
|
VCPM_FILEPATCHBEFORECPY = VCPM_PATCHFIRST,
|
||||||
|
VCPM_FILEPATCHAFTERCPY,
|
||||||
|
VCPM_FILEPATCHINFOPEN,
|
||||||
|
VCPM_FILEPATCHINFCLOSE
|
||||||
|
};
|
||||||
|
|
||||||
|
#define VCPM_CERTCLASS 0x0a
|
||||||
|
#define VCPM_CERTFIRST 0x0a00
|
||||||
|
#define VCPM_CERTLAST 0x0aff
|
||||||
|
|
||||||
|
enum {
|
||||||
|
VCPM_FILECERTIFY = VCPM_CERTFIRST,
|
||||||
|
VCPM_FILECERTIFYWARN
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef LRESULT (CALLBACK *VIFPROC)(LPVOID lpvObj, UINT16 uMsg, WPARAM wParam, LPARAM lParam, LPARAM lparamRef);
|
||||||
|
|
||||||
|
typedef int (CALLBACK *VCPENUMPROC)(LPVIRTNODE lpvn, LPARAM lparamRef);
|
||||||
|
|
||||||
|
RETERR16 WINAPI VcpOpen16(VIFPROC vifproc, LPARAM lparamMsgRef);
|
||||||
|
|
||||||
|
/* VcpQueueCopy flags */
|
||||||
|
#define VNLP_SYSCRITICAL 0x0001
|
||||||
|
#define VNLP_SETUPCRITICAL 0x0002
|
||||||
|
#define VNLP_NOVERCHECK 0x0004
|
||||||
|
#define VNLP_FORCETEMP 0x0008
|
||||||
|
#define VNLP_IFEXISTS 0x0010
|
||||||
|
#define VNLP_KEEPNEWER 0x0020
|
||||||
|
#define VNLP_PATCHIFEXIST 0x0040
|
||||||
|
#define VNLP_NOPATCH 0x0080
|
||||||
|
#define VNLP_CATALOGCERT 0x0100
|
||||||
|
#define VNLP_NEEDCERTIFY 0x0200
|
||||||
|
#define VNLP_COPYIFEXISTS 0x0400
|
||||||
|
|
||||||
|
RETERR16 WINAPI VcpQueueCopy16(
|
||||||
|
LPCSTR lpszSrcFileName, LPCSTR lpszDstFileName,
|
||||||
|
LPCSTR lpszSrcDir, LPCSTR lpszDstDir,
|
||||||
|
LOGDISKID16 ldidSrc, LOGDISKID16 ldidDst,
|
||||||
|
LPEXPANDVTBL lpExpandVtbl,
|
||||||
|
WORD fl, LPARAM lParam
|
||||||
|
);
|
||||||
|
RETERR16 VcpFlush16(WORD fl, LPCSTR lpszBackupDest);
|
||||||
|
RETERR16 WINAPI VcpClose16(WORD fl, LPCSTR lpszBackupDest);
|
||||||
|
|
||||||
|
/* VcpExplain flags */
|
||||||
|
enum {
|
||||||
|
VCPEX_SRC_DISK,
|
||||||
|
VCPEX_SRC_CABINET,
|
||||||
|
VCPEX_SRC_LOCN,
|
||||||
|
VCPEX_DST_LOCN,
|
||||||
|
VCPEX_SRC_FILE,
|
||||||
|
VCPEX_DST_FILE,
|
||||||
|
VCPEX_DST_FILE_FINAL,
|
||||||
|
VCPEX_DOS_ERROR,
|
||||||
|
VCPEX_MESSAGE,
|
||||||
|
VCPEX_DOS_SOLUTION,
|
||||||
|
VCPEX_SRC_FULL,
|
||||||
|
VCPEX_DST_FULL,
|
||||||
|
VCPEX_DST_FULL_FINAL
|
||||||
|
};
|
||||||
|
|
||||||
|
LPCSTR WINAPI VcpExplain16(LPVIRTNODE lpVn, DWORD dwWhat);
|
||||||
|
|
||||||
|
/****** logical disk management ******/
|
||||||
|
|
||||||
|
typedef struct _LOGDISKDESC_S { /* ldd */
|
||||||
|
WORD cbSize; /* struct size */
|
||||||
|
LOGDISKID16 ldid; /* logical disk ID */
|
||||||
|
LPSTR pszPath; /* path this descriptor points to */
|
||||||
|
LPSTR pszVolLabel; /* volume label of the disk related to it */
|
||||||
|
LPSTR pszDiskName; /* name of this disk */
|
||||||
|
WORD wVolTime; /* modification time of volume label */
|
||||||
|
WORD wVolDate; /* modification date */
|
||||||
|
DWORD dwSerNum; /* serial number of disk */
|
||||||
|
WORD wFlags;
|
||||||
|
} LOGDISKDESC_S, *LPLOGDISKDESC;
|
||||||
|
|
||||||
|
/** logical disk identifiers (LDID) **/
|
||||||
|
|
||||||
|
/* predefined LDIDs */
|
||||||
|
#define LDID_PREDEF_START 0x0001
|
||||||
|
#define LDID_PREDEF_END 0x7fff
|
||||||
|
|
||||||
|
/* registry-assigned LDIDs */
|
||||||
|
#define LDID_VAR_START 0x7000
|
||||||
|
#define LDID_VAR_END 0x7fff
|
||||||
|
|
||||||
|
/* dynamically assigned LDIDs */
|
||||||
|
#define LDID_ASSIGN_START 0x8000
|
||||||
|
#define LDID_ASSIGN_END 0xbfff
|
||||||
|
|
||||||
|
#define LDID_NULL 0
|
||||||
|
#define LDID_ABSOLUTE ((UINT)-1)
|
||||||
|
#define LDID_SRCPATH 1 /* setup source path */
|
||||||
|
#define LDID_SETUPTEMP 2 /* setup temp dir */
|
||||||
|
#define LDID_UNINSTALL 3 /* uninstall dir */
|
||||||
|
#define LDID_BACKUP 4 /* backup dir */
|
||||||
|
#define LDID_SETUPSCRATCH 5 /* setup scratch dir */
|
||||||
|
#define LDID_WIN 10 /* win dir */
|
||||||
|
#define LDID_SYS 11 /* win system dir */
|
||||||
|
#define LDID_IOS 12 /* win Iosubsys dir */
|
||||||
|
#define LDID_CMD 13 /* win command dir */
|
||||||
|
#define LDID_CPL 14 /* win control panel dir */
|
||||||
|
#define LDID_PRINT 15 /* win printer dir */
|
||||||
|
#define LDID_MAIL 16 /* win mail dir */
|
||||||
|
#define LDID_INF 17 /* win inf dir */
|
||||||
|
#define LDID_HELP 18 /* win help dir */
|
||||||
|
#define LDID_WINADMIN 19 /* admin dir */
|
||||||
|
#define LDID_FONTS 20 /* win fonts dir */
|
||||||
|
#define LDID_VIEWERS 21 /* win viewers dir */
|
||||||
|
#define LDID_VMM32 22 /* win VMM32 dir */
|
||||||
|
#define LDID_COLOR 23 /* win color mngment dir */
|
||||||
|
#define LDID_APPS 24 /* win apps dir */
|
||||||
|
#define LDID_SHARED 25 /* win shared dir */
|
||||||
|
#define LDID_WINBOOT 26 /* guaranteed win boot drive */
|
||||||
|
#define LDID_MACHINE 27 /* machine specific files */
|
||||||
|
#define LDID_HOST_WINBOOT 28
|
||||||
|
#define LDID_BOOT 30 /* boot drive root dir */
|
||||||
|
#define LDID_BOOT_HOST 31 /* boot drive host root dir */
|
||||||
|
#define LDID_OLD_WINBOOT 32 /* root subdir */
|
||||||
|
#define LDID_OLD_WIN 33 /* old windows dir */
|
||||||
|
|
||||||
|
/* flags for GenInstall() */
|
||||||
|
#define GENINSTALL_DO_FILES 1
|
||||||
|
#define GENINSTALL_DO_INI 2
|
||||||
|
#define GENINSTALL_DO_REG 4
|
||||||
|
#define GENINSTALL_DO_INI2REG 8
|
||||||
|
#define GENINSTALL_DO_CFGAUTO 16
|
||||||
|
#define GENINSTALL_DO_LOGCONFIG 32
|
||||||
|
#define GENINSTALL_DO_REGSRCPATH 64
|
||||||
|
#define GENINSTALL_DO_PERUSER 128
|
||||||
|
|
||||||
|
#define GEINISTALL_DO_INIREG 14
|
||||||
|
#define GENINSTALL_DO_ALL 255
|
||||||
|
|
||||||
|
/*
|
||||||
|
* flags for InstallHinfSection()
|
||||||
|
* 128 can be added, too. This means that the .inf file is provided by you
|
||||||
|
* instead of being a 32 bit file (i.e. Windows .inf file).
|
||||||
|
* In this case all files you install must be in the same dir
|
||||||
|
* as your .inf file on the install disk.
|
||||||
|
*/
|
||||||
|
#define HOW_NEVER_REBOOT 0
|
||||||
|
#define HOW_ALWAYS_SILENT_REBOOT 1
|
||||||
|
#define HOW_ALWAYS_PROMPT_REBOOT 2
|
||||||
|
#define HOW_SILENT_REBOOT 3
|
||||||
|
#define HOW_PROMPT_REBOOT 4
|
||||||
|
|
||||||
|
/****** device installation stuff ******/
|
||||||
|
|
||||||
|
#define MAX_CLASS_NAME_LEN 32
|
||||||
|
#define MAX_DEVNODE_ID_LEN 256
|
||||||
|
#define MAX_GUID_STR 50
|
||||||
|
|
||||||
|
typedef struct _DEVICE_INFO
|
||||||
|
{
|
||||||
|
UINT16 cbSize;
|
||||||
|
struct _DEVICE_INFO *lpNextDi;
|
||||||
|
char szDescription[LINE_LEN];
|
||||||
|
DWORD dnDevnode;
|
||||||
|
HKEY hRegKey;
|
||||||
|
char szRegSubkey[MAX_DEVNODE_ID_LEN];
|
||||||
|
char szClassName[MAX_CLASS_NAME_LEN];
|
||||||
|
DWORD Flags;
|
||||||
|
HWND16 hwndParent;
|
||||||
|
/*LPDRIVER_NODE*/ LPVOID lpCompatDrvList;
|
||||||
|
/*LPDRIVER_NODE*/ LPVOID lpClassDrvList;
|
||||||
|
/*LPDRIVER_NODE*/ LPVOID lpSelectedDriver;
|
||||||
|
ATOM atDriverPath;
|
||||||
|
ATOM atTempInfFile;
|
||||||
|
HINSTANCE16 hinstClassInstaller;
|
||||||
|
HINSTANCE16 hinstClassPropProvidor;
|
||||||
|
HINSTANCE16 hinstDevicePropProvidor;
|
||||||
|
HINSTANCE16 hinstBasicPropProvidor;
|
||||||
|
FARPROC16 fpClassInstaller;
|
||||||
|
FARPROC16 fpClassEnumPropPages;
|
||||||
|
FARPROC16 fpDeviceEnumPropPages;
|
||||||
|
FARPROC16 fpEnumBasicProperties;
|
||||||
|
DWORD dwSetupReserved;
|
||||||
|
DWORD dwClassInstallReserved;
|
||||||
|
/*GENCALLBACKPROC*/ LPVOID gicpGenInstallCallBack;
|
||||||
|
|
||||||
|
LPARAM gicplParam;
|
||||||
|
UINT16 InfType;
|
||||||
|
|
||||||
|
HINSTANCE16 hinstPrivateProblemHandler;
|
||||||
|
FARPROC16 fpPrivateProblemHandler;
|
||||||
|
LPARAM lpClassInstallParams;
|
||||||
|
struct _DEVICE_INFO *lpdiChildList;
|
||||||
|
DWORD dwFlagsEx;
|
||||||
|
/*LPDRIVER_INFO*/ LPVOID lpCompatDrvInfoList;
|
||||||
|
/*LPDRIVER_INFO*/ LPVOID lpClassDrvInfoList;
|
||||||
|
char szClassGUID[MAX_GUID_STR];
|
||||||
|
} DEVICE_INFO16, *LPDEVICE_INFO16, **LPLPDEVICE_INFO16;
|
||||||
|
|
||||||
|
|
||||||
|
extern void WINAPI GenFormStrWithoutPlaceHolders16(LPSTR,LPCSTR,HINF16);
|
||||||
|
extern RETERR16 WINAPI IpOpen16(LPCSTR,HINF16 *);
|
||||||
|
extern RETERR16 WINAPI IpClose16(HINF16);
|
||||||
|
extern RETERR16 WINAPI CtlSetLdd16(LPLOGDISKDESC);
|
||||||
|
extern RETERR16 WINAPI CtlGetLdd16(LPLOGDISKDESC);
|
||||||
|
extern RETERR16 WINAPI CtlFindLdd16(LPLOGDISKDESC);
|
||||||
|
extern RETERR16 WINAPI CtlAddLdd16(LPLOGDISKDESC);
|
||||||
|
extern RETERR16 WINAPI CtlDelLdd16(LOGDISKID16);
|
||||||
|
extern RETERR16 WINAPI CtlGetLddPath16(LOGDISKID16 ldid, LPSTR szPath);
|
||||||
|
extern RETERR16 WINAPI GenInstall16(HINF16,LPCSTR,WORD);
|
||||||
|
|
||||||
|
typedef struct tagLDD_LIST {
|
||||||
|
LPLOGDISKDESC pldd;
|
||||||
|
struct tagLDD_LIST *next;
|
||||||
|
} LDD_LIST;
|
||||||
|
|
||||||
|
#define INIT_LDD(ldd, LDID) \
|
||||||
|
do { \
|
||||||
|
memset(&(ldd), 0, sizeof(LOGDISKDESC_S)); \
|
||||||
|
(ldd).cbSize = sizeof(LOGDISKDESC_S); \
|
||||||
|
ldd.ldid = LDID; \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#endif /* __SETUPX16_H */
|
736
reactos/lib/setupapi/setupx_main.c
Normal file
736
reactos/lib/setupapi/setupx_main.c
Normal file
|
@ -0,0 +1,736 @@
|
||||||
|
/*
|
||||||
|
* SETUPX library
|
||||||
|
*
|
||||||
|
* Copyright 1998,2000 Andreas Mohr
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* FIXME: Rather non-functional functions for now.
|
||||||
|
*
|
||||||
|
* See:
|
||||||
|
* http://www.geocities.com/SiliconValley/Network/5317/drivers.html
|
||||||
|
* http://willemer.de/informatik/windows/inf_info.htm (German)
|
||||||
|
* 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
|
||||||
|
* http://support.microsoft.com/support/kb/articles/q194/6/40.asp
|
||||||
|
*
|
||||||
|
* Stuff tested with:
|
||||||
|
* - rs405deu.exe (German Acroread 4.05 setup)
|
||||||
|
* - ie5setup.exe
|
||||||
|
* - Netmeeting
|
||||||
|
*
|
||||||
|
* FIXME:
|
||||||
|
* - 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 ?)
|
||||||
|
* LDID logical device ID
|
||||||
|
* 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 ;-)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "windef.h"
|
||||||
|
#include "winbase.h"
|
||||||
|
#include "winreg.h"
|
||||||
|
#include "winerror.h"
|
||||||
|
#include "wine/winuser16.h"
|
||||||
|
#include "wownt32.h"
|
||||||
|
#include "wingdi.h"
|
||||||
|
#include "winuser.h"
|
||||||
|
#include "winnls.h"
|
||||||
|
#include "setupapi.h"
|
||||||
|
#include "setupx16.h"
|
||||||
|
#include "setupapi_private.h"
|
||||||
|
#include "winerror.h"
|
||||||
|
#include "wine/debug.h"
|
||||||
|
|
||||||
|
WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* SURegOpenKey (SETUPX.47)
|
||||||
|
*/
|
||||||
|
DWORD WINAPI SURegOpenKey( HKEY hkey, LPCSTR lpszSubKey, PHKEY retkey )
|
||||||
|
{
|
||||||
|
FIXME("(%p,%s,%p), semi-stub.\n",hkey,debugstr_a(lpszSubKey),retkey);
|
||||||
|
return RegOpenKeyA( hkey, lpszSubKey, retkey );
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* SURegQueryValueEx (SETUPX.50)
|
||||||
|
*/
|
||||||
|
DWORD WINAPI SURegQueryValueEx( HKEY hkey, LPSTR lpszValueName,
|
||||||
|
LPDWORD lpdwReserved, LPDWORD lpdwType,
|
||||||
|
LPBYTE lpbData, LPDWORD lpcbData )
|
||||||
|
{
|
||||||
|
FIXME("(%p,%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 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 */
|
||||||
|
if (res)
|
||||||
|
res = HeapReAlloc(GetProcessHeap(), 0, res, (1+count+32)*sizeof(LPSTR));
|
||||||
|
else
|
||||||
|
res = HeapAlloc(GetProcessHeap(), 0, (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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* InstallHinfSection (SETUPX.527)
|
||||||
|
*
|
||||||
|
* 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).
|
||||||
|
* The 132 value is made of the HOW_xxx flags and sometimes 128 (-> setupx16.h).
|
||||||
|
*
|
||||||
|
* nCmdShow = nCmdShow of CreateProcess
|
||||||
|
*/
|
||||||
|
RETERR16 WINAPI InstallHinfSection16( HWND16 hwnd, HINSTANCE16 hinst, LPCSTR lpszCmdLine, INT16 nCmdShow)
|
||||||
|
{
|
||||||
|
LPSTR *pSub;
|
||||||
|
DWORD count;
|
||||||
|
HINF16 hInf = 0;
|
||||||
|
RETERR16 res = OK, tmp;
|
||||||
|
WORD wFlags;
|
||||||
|
BOOL reboot = FALSE;
|
||||||
|
|
||||||
|
TRACE("(%04x, %04x, %s, %d);\n", hwnd, hinst, lpszCmdLine, nCmdShow);
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
if (VcpOpen16(NULL, 0))
|
||||||
|
goto end;
|
||||||
|
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:
|
||||||
|
if (MessageBoxA(HWND_32(hwnd), "You must restart Wine before the new settings will take effect.\n\nDo you want to exit Wine now ?", "Systems Settings Change", MB_YESNO|MB_ICONQUESTION) == IDYES)
|
||||||
|
reboot = TRUE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ERR("invalid flags %d !\n", wFlags);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = OK;
|
||||||
|
end:
|
||||||
|
tmp = VcpClose16(VCPFL_ALL, NULL);
|
||||||
|
if (tmp != OK)
|
||||||
|
res = tmp;
|
||||||
|
tmp = IpClose16(hInf);
|
||||||
|
if (tmp != OK)
|
||||||
|
res = tmp;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
LPCSTR RegValName;
|
||||||
|
LPCSTR StdString; /* fallback string; sub dir of windows directory */
|
||||||
|
} LDID_DATA;
|
||||||
|
|
||||||
|
static const LDID_DATA LDID_Data[34] =
|
||||||
|
{
|
||||||
|
{ /* 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 */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* LDD == Logical Device Descriptor
|
||||||
|
* LDID == Logical Device ID
|
||||||
|
*
|
||||||
|
* The whole LDD/LDID business might go into a separate file named
|
||||||
|
* ldd.c.
|
||||||
|
* 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)
|
||||||
|
{
|
||||||
|
HKEY hKey = 0;
|
||||||
|
WORD n;
|
||||||
|
DWORD type, len;
|
||||||
|
LOGDISKDESC_S ldd;
|
||||||
|
char buffer[MAX_PATH];
|
||||||
|
|
||||||
|
/* has to be here, otherwise loop */
|
||||||
|
std_LDDs_done = TRUE;
|
||||||
|
|
||||||
|
RegOpenKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Setup", &hKey);
|
||||||
|
|
||||||
|
for (n=0; n < sizeof(LDID_Data)/sizeof(LDID_DATA); n++)
|
||||||
|
{
|
||||||
|
buffer[0] = '\0';
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* CtlDelLdd (SETUPX.37)
|
||||||
|
*
|
||||||
|
* RETURN
|
||||||
|
* ERR_VCP_LDDINVALID if ldid < LDID_ASSIGN_START.
|
||||||
|
*/
|
||||||
|
RETERR16 SETUPX_DelLdd(LOGDISKID16 ldid)
|
||||||
|
{
|
||||||
|
LDD_LIST *pCurr, *pPrev = NULL;
|
||||||
|
|
||||||
|
TRACE("(%d)\n", ldid);
|
||||||
|
|
||||||
|
if (!std_LDDs_done)
|
||||||
|
SETUPX_CreateStandardLDDs();
|
||||||
|
|
||||||
|
if (ldid < LDID_ASSIGN_START)
|
||||||
|
return ERR_VCP_LDDINVALID;
|
||||||
|
|
||||||
|
pCurr = pFirstLDD;
|
||||||
|
/* 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);
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* CtlDelLdd (SETUPX.37)
|
||||||
|
*/
|
||||||
|
RETERR16 WINAPI CtlDelLdd16(LOGDISKID16 ldid)
|
||||||
|
{
|
||||||
|
FIXME("(%d); - please report this!\n", ldid);
|
||||||
|
return SETUPX_DelLdd(ldid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* CtlFindLdd (SETUPX.35)
|
||||||
|
*
|
||||||
|
* doesn't check pldd ptr validity: crash (W98SE)
|
||||||
|
*
|
||||||
|
* RETURN
|
||||||
|
* ERR_VCP_LDDINVALID if pldd->cbSize != structsize
|
||||||
|
* 1 in all other cases ??
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
RETERR16 WINAPI CtlFindLdd16(LPLOGDISKDESC pldd)
|
||||||
|
{
|
||||||
|
LDD_LIST *pCurr, *pPrev = NULL;
|
||||||
|
|
||||||
|
TRACE("(%p)\n", pldd);
|
||||||
|
|
||||||
|
if (!std_LDDs_done)
|
||||||
|
SETUPX_CreateStandardLDDs();
|
||||||
|
|
||||||
|
if (pldd->cbSize != sizeof(LOGDISKDESC_S))
|
||||||
|
return ERR_VCP_LDDINVALID;
|
||||||
|
|
||||||
|
pCurr = pFirstLDD;
|
||||||
|
/* 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 */
|
||||||
|
|| (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 */
|
||||||
|
|
||||||
|
return 1; /* what is this ?? */
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* CtlSetLdd (SETUPX.33)
|
||||||
|
*
|
||||||
|
* Set an LDD entry.
|
||||||
|
*
|
||||||
|
* RETURN
|
||||||
|
* ERR_VCP_LDDINVALID if pldd.cbSize != sizeof(LOGDISKDESC_S)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
RETERR16 WINAPI CtlSetLdd16(LPLOGDISKDESC pldd)
|
||||||
|
{
|
||||||
|
LDD_LIST *pCurr, *pPrev = NULL;
|
||||||
|
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();
|
||||||
|
pCurr = pFirstLDD;
|
||||||
|
/* 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 || pldd->ldid != pCurr->pldd->ldid)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
pCurrLDD->pszPath = HeapAlloc( heap, 0, strlen(pldd->pszPath)+1 );
|
||||||
|
strcpy( pCurrLDD->pszPath, pldd->pszPath );
|
||||||
|
}
|
||||||
|
if (pldd->pszVolLabel)
|
||||||
|
{
|
||||||
|
pCurrLDD->pszVolLabel = HeapAlloc( heap, 0, strlen(pldd->pszVolLabel)+1 );
|
||||||
|
strcpy( pCurrLDD->pszVolLabel, pldd->pszVolLabel );
|
||||||
|
}
|
||||||
|
if (pldd->pszDiskName)
|
||||||
|
{
|
||||||
|
pCurrLDD->pszDiskName = HeapAlloc( heap, 0, strlen(pldd->pszDiskName)+1 );
|
||||||
|
strcpy( pCurrLDD->pszDiskName, pldd->pszDiskName );
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_new) /* link into list */
|
||||||
|
{
|
||||||
|
if (pPrev)
|
||||||
|
{
|
||||||
|
pCurr->next = pPrev->next;
|
||||||
|
pPrev->next = pCurr;
|
||||||
|
}
|
||||||
|
if (!pFirstLDD)
|
||||||
|
pFirstLDD = pCurr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static RETERR16 SETUPX_GetLdd(LPLOGDISKDESC pldd)
|
||||||
|
{
|
||||||
|
LDD_LIST *pCurr, *pPrev = NULL;
|
||||||
|
|
||||||
|
if (!std_LDDs_done)
|
||||||
|
SETUPX_CreateStandardLDDs();
|
||||||
|
|
||||||
|
if (pldd->cbSize != sizeof(LOGDISKDESC_S))
|
||||||
|
return ERR_VCP_LDDINVALID;
|
||||||
|
|
||||||
|
pCurr = pFirstLDD;
|
||||||
|
/* 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 */
|
||||||
|
return ERR_VCP_LDDFIND; /* correct ? */
|
||||||
|
|
||||||
|
memcpy(pldd, pCurr->pldd, pldd->cbSize);
|
||||||
|
/* hmm, we probably ought to strcpy() the string ptrs here */
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************************************************************/
|
||||||
|
|
||||||
|
RETERR16 WINAPI CtlGetLdd16(LPLOGDISKDESC pldd)
|
||||||
|
{
|
||||||
|
FIXME("(%p); - please report this!\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);
|
||||||
|
|
||||||
|
SetupSetDirectoryIdA( 0, ldid, szPath );
|
||||||
|
INIT_LDD(ldd, ldid);
|
||||||
|
ldd.pszPath = szPath;
|
||||||
|
return CtlSetLdd16(&ldd);
|
||||||
|
}
|
197
reactos/lib/setupapi/stubs.c
Normal file
197
reactos/lib/setupapi/stubs.c
Normal file
|
@ -0,0 +1,197 @@
|
||||||
|
/*
|
||||||
|
* SetupAPI stubs
|
||||||
|
*
|
||||||
|
* Copyright 2000 James Hatheway
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#include "wine/debug.h"
|
||||||
|
#include "windef.h"
|
||||||
|
#include "winbase.h"
|
||||||
|
#include "wingdi.h"
|
||||||
|
#include "winuser.h"
|
||||||
|
#include "winnls.h"
|
||||||
|
#include "winreg.h"
|
||||||
|
#include "setupapi.h"
|
||||||
|
|
||||||
|
WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* TPWriteProfileString (SETUPX.62)
|
||||||
|
*/
|
||||||
|
BOOL WINAPI TPWriteProfileString16( LPCSTR section, LPCSTR entry, LPCSTR string )
|
||||||
|
{
|
||||||
|
FIXME( "%s %s %s: stub\n", debugstr_a(section), debugstr_a(entry), debugstr_a(string) );
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* suErrorToIds (SETUPX.61)
|
||||||
|
*/
|
||||||
|
DWORD WINAPI suErrorToIds16( WORD w1, WORD w2 )
|
||||||
|
{
|
||||||
|
FIXME( "%x %x: stub\n", w1, w2 );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* SetupDiOpenClassRegKeyExW (SETUPAPI.@)
|
||||||
|
*
|
||||||
|
* WINAPI in description not given
|
||||||
|
*/
|
||||||
|
HKEY WINAPI SetupDiOpenClassRegKeyExW(const GUID* class, REGSAM access, DWORD flags, PCWSTR machine, PVOID reserved)
|
||||||
|
{
|
||||||
|
FIXME("\n");
|
||||||
|
return INVALID_HANDLE_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* SetupDiGetClassDescriptionExW (SETUPAPI.@)
|
||||||
|
*/
|
||||||
|
BOOL WINAPI SetupDiGetClassDescriptionExW (const GUID* class, PWSTR desc, DWORD size, PDWORD required, PCWSTR machine, PVOID reserved)
|
||||||
|
{
|
||||||
|
FIXME("\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* SetupDiClassNameFromGuidExW (SETUPAPI.@)
|
||||||
|
*/
|
||||||
|
BOOL WINAPI SetupDiClassNameFromGuidExW (const GUID* class, PWSTR desc, DWORD size, PDWORD required, PCWSTR machine, PVOID reserved)
|
||||||
|
{
|
||||||
|
FIXME("\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* SetupDiBuildClassInfoListExW (SETUPAPI.@)
|
||||||
|
*/
|
||||||
|
BOOL WINAPI SetupDiBuildClassInfoListExW(DWORD flags, LPGUID list, DWORD size, PDWORD required, LPCWSTR machine, PVOID reserved)
|
||||||
|
{
|
||||||
|
FIXME("\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* SetupDiGetDeviceInfoListDetailA (SETUPAPI.@)
|
||||||
|
*/
|
||||||
|
BOOL WINAPI SetupDiGetDeviceInfoListDetailA(HDEVINFO devinfo, PSP_DEVINFO_LIST_DETAIL_DATA_A devinfo_data )
|
||||||
|
{
|
||||||
|
FIXME("\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* SetupDiGetDeviceInfoListDetailW (SETUPAPI.@)
|
||||||
|
*/
|
||||||
|
BOOL WINAPI SetupDiGetDeviceInfoListDetailW(HDEVINFO devinfo, PSP_DEVINFO_LIST_DETAIL_DATA_W devinfo_data )
|
||||||
|
{
|
||||||
|
FIXME("\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* SetupDiCreateDeviceInfoListA (SETUPAPI.@)
|
||||||
|
*/
|
||||||
|
HDEVINFO WINAPI SetupDiCreateDeviceInfoList(const GUID *class, HWND parend)
|
||||||
|
{
|
||||||
|
FIXME("\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
|
||||||
|
*/
|
||||||
|
HDEVINFO WINAPI SetupDiCreateDeviceInfoListExW(const GUID *class, HWND parend , PCWSTR machine, PVOID reserved)
|
||||||
|
{
|
||||||
|
FIXME("\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* (SETUPAPI.@)
|
||||||
|
*
|
||||||
|
* NO WINAPI in description given
|
||||||
|
*/
|
||||||
|
HDEVINFO WINAPI SetupDiGetClassDevsExA(const GUID *class, PCSTR filter, HWND parent, DWORD flags, HDEVINFO deviceset, PCSTR machine, PVOID reserved)
|
||||||
|
{
|
||||||
|
FIXME("filter %s machine %s\n",debugstr_a(filter),debugstr_a(machine));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* (SETUPAPI.@)
|
||||||
|
*
|
||||||
|
* NO WINAPI in description given
|
||||||
|
*/
|
||||||
|
HDEVINFO WINAPI SetupDiGetClassDevsExW(const GUID *class, PCWSTR filter, HWND parent, DWORD flags, HDEVINFO deviceset, PCWSTR machine, PVOID reserved)
|
||||||
|
{
|
||||||
|
FIXME("\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* SetupDiClassGuidsFromNameExW (SETUPAPI.@)
|
||||||
|
*/
|
||||||
|
BOOL WINAPI SetupDiClassGuidsFromNameExW(LPCWSTR class, LPGUID list, DWORD size, PDWORD required, LPCWSTR machine, PVOID reserved)
|
||||||
|
{
|
||||||
|
FIXME("\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* CM_Connect_MachineW (SETUPAPI.@)
|
||||||
|
*/
|
||||||
|
DWORD WINAPI CM_Connect_MachineW(LPCWSTR name, void * machine)
|
||||||
|
{
|
||||||
|
#define CR_SUCCESS 0x00000000
|
||||||
|
#define CR_ACCESS_DENIED 0x00000033
|
||||||
|
FIXME("\n");
|
||||||
|
return CR_ACCESS_DENIED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* CM_Disconnect_Machine (SETUPAPI.@)
|
||||||
|
*/
|
||||||
|
DWORD WINAPI CM_Disconnect_Machine(DWORD handle)
|
||||||
|
{
|
||||||
|
FIXME("\n");
|
||||||
|
return CR_SUCCESS;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* SetupCopyOEMInfA (SETUPAPI.@)
|
||||||
|
*/
|
||||||
|
BOOL WINAPI SetupCopyOEMInfA(PCSTR sourceinffile, PCSTR sourcemedialoc,
|
||||||
|
DWORD mediatype, DWORD copystyle, PSTR destinfname,
|
||||||
|
DWORD destnamesize, PDWORD required,
|
||||||
|
PSTR *destinfnamecomponent)
|
||||||
|
{
|
||||||
|
FIXME("stub: source %s location %s ...\n",sourceinffile, sourcemedialoc);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* InstallHinfSection (SETUPAPI.@)
|
||||||
|
*/
|
||||||
|
void WINAPI InstallHinfSection(HWND hwnd, HINSTANCE handle, LPCSTR cmdline, INT show)
|
||||||
|
{
|
||||||
|
FIXME("stub, hwnd %p, handle %p, cmdline %s\n", hwnd, handle, debugstr_a(cmdline));
|
||||||
|
}
|
789
reactos/lib/setupapi/virtcopy.c
Normal file
789
reactos/lib/setupapi/virtcopy.c
Normal file
|
@ -0,0 +1,789 @@
|
||||||
|
/*
|
||||||
|
* SetupAPI virtual copy operations
|
||||||
|
*
|
||||||
|
* Copyright 2001 Andreas Mohr
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* FIXME: we now rely on builtin setupapi.dll for dialog resources.
|
||||||
|
* This is bad ! We ought to have 16bit resource handling working.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "windef.h"
|
||||||
|
#include "winbase.h"
|
||||||
|
#include "winuser.h"
|
||||||
|
#include "winreg.h"
|
||||||
|
#include "wownt32.h"
|
||||||
|
#include "wingdi.h"
|
||||||
|
#include "winnls.h"
|
||||||
|
#include "setupapi.h"
|
||||||
|
#include "setupx16.h"
|
||||||
|
#include "setupapi_private.h"
|
||||||
|
#include "wine/debug.h"
|
||||||
|
|
||||||
|
WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
|
||||||
|
|
||||||
|
static FARPROC16 VCP_Proc = NULL;
|
||||||
|
static LPARAM VCP_MsgRef = 0;
|
||||||
|
|
||||||
|
static BOOL VCP_opened = FALSE;
|
||||||
|
|
||||||
|
static VCPSTATUS vcp_status;
|
||||||
|
|
||||||
|
static HINSTANCE SETUPAPI_hInstance;
|
||||||
|
|
||||||
|
static WORD VCP_Callback( LPVOID obj, UINT16 msg, WPARAM16 wParam, LPARAM lParam, LPARAM lParamRef )
|
||||||
|
{
|
||||||
|
WORD args[8];
|
||||||
|
DWORD ret = OK;
|
||||||
|
if (VCP_Proc)
|
||||||
|
{
|
||||||
|
args[7] = HIWORD(obj);
|
||||||
|
args[6] = LOWORD(obj);
|
||||||
|
args[5] = msg;
|
||||||
|
args[4] = wParam;
|
||||||
|
args[3] = HIWORD(lParam);
|
||||||
|
args[2] = LOWORD(lParam);
|
||||||
|
args[1] = HIWORD(lParamRef);
|
||||||
|
args[0] = LOWORD(lParamRef);
|
||||||
|
WOWCallback16Ex( (DWORD)VCP_Proc, WCB16_PASCAL, sizeof(args), args, &ret );
|
||||||
|
}
|
||||||
|
return (WORD)ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************** VHSTR management ******************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is a totally braindead implementation for now;
|
||||||
|
* I don't care about speed at all ! Size and implementation time
|
||||||
|
* is much more important IMHO. I could have created some sophisticated
|
||||||
|
* tree structure, but... what the hell ! :-)
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
DWORD refcount;
|
||||||
|
LPCSTR pStr;
|
||||||
|
} VHSTR_STRUCT;
|
||||||
|
|
||||||
|
static VHSTR_STRUCT **vhstrlist = NULL;
|
||||||
|
static VHSTR vhstr_alloc = 0;
|
||||||
|
|
||||||
|
#define VALID_VHSTR(x) ((x < vhstr_alloc) && (vhstrlist[x]) && (vhstrlist[x]->refcount))
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* vsmStringAdd (SETUPX.207)
|
||||||
|
*/
|
||||||
|
VHSTR WINAPI vsmStringAdd16(LPCSTR lpszName)
|
||||||
|
{
|
||||||
|
VHSTR n;
|
||||||
|
VHSTR index = 0xffff;
|
||||||
|
HANDLE heap;
|
||||||
|
|
||||||
|
TRACE("add string '%s'\n", lpszName);
|
||||||
|
/* search whether string already inserted */
|
||||||
|
TRACE("searching for existing string...\n");
|
||||||
|
for (n = 0; n < vhstr_alloc; n++)
|
||||||
|
{
|
||||||
|
if ((vhstrlist[n]) && (vhstrlist[n]->refcount))
|
||||||
|
{
|
||||||
|
TRACE("checking item: %d\n", n);
|
||||||
|
if (!strcmp(vhstrlist[n]->pStr, lpszName))
|
||||||
|
{
|
||||||
|
TRACE("found\n");
|
||||||
|
vhstrlist[n]->refcount++;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* hmm, not found yet, let's insert it */
|
||||||
|
TRACE("inserting item\n");
|
||||||
|
for (n = 0; n < vhstr_alloc; n++)
|
||||||
|
{
|
||||||
|
if ((!(vhstrlist[n])) || (!(vhstrlist[n]->refcount)))
|
||||||
|
{
|
||||||
|
index = n;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
heap = GetProcessHeap();
|
||||||
|
if (n == vhstr_alloc) /* hmm, no free index found yet */
|
||||||
|
{
|
||||||
|
index = vhstr_alloc;
|
||||||
|
vhstr_alloc += 20;
|
||||||
|
|
||||||
|
if (vhstrlist)
|
||||||
|
vhstrlist = HeapReAlloc(heap, HEAP_ZERO_MEMORY, vhstrlist,
|
||||||
|
sizeof(VHSTR_STRUCT *) * vhstr_alloc);
|
||||||
|
else
|
||||||
|
vhstrlist = HeapAlloc(heap, HEAP_ZERO_MEMORY,
|
||||||
|
sizeof(VHSTR_STRUCT *) * vhstr_alloc);
|
||||||
|
}
|
||||||
|
if (index == 0xffff)
|
||||||
|
return 0xffff; /* failure */
|
||||||
|
if (!vhstrlist[index])
|
||||||
|
vhstrlist[index] = HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(VHSTR_STRUCT));
|
||||||
|
vhstrlist[index]->refcount = 1;
|
||||||
|
vhstrlist[index]->pStr = HeapAlloc(heap, 0, strlen(lpszName)+1);
|
||||||
|
strcpy((LPSTR)vhstrlist[index]->pStr, lpszName);
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* vsmStringDelete (SETUPX.206)
|
||||||
|
*/
|
||||||
|
INT16 WINAPI vsmStringDelete16(VHSTR vhstr)
|
||||||
|
{
|
||||||
|
if (VALID_VHSTR(vhstr))
|
||||||
|
{
|
||||||
|
vhstrlist[vhstr]->refcount--;
|
||||||
|
if (!vhstrlist[vhstr]->refcount)
|
||||||
|
{
|
||||||
|
HeapFree(GetProcessHeap(), 0, (LPSTR)vhstrlist[vhstr]->pStr);
|
||||||
|
vhstrlist[vhstr]->pStr = NULL;
|
||||||
|
}
|
||||||
|
return VCPN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* string not found */
|
||||||
|
return VCPN_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* vsmStringFind() - not exported from a standard SETUPX.DLL, it seems
|
||||||
|
*/
|
||||||
|
VHSTR WINAPI vsmStringFind16(LPCSTR lpszName)
|
||||||
|
{
|
||||||
|
WORD n;
|
||||||
|
for (n = 0; n < vhstr_alloc; n++)
|
||||||
|
if ((vhstrlist[n]) && (vhstrlist[n]->refcount) && (!strcmp(vhstrlist[n]->pStr, lpszName)))
|
||||||
|
return n;
|
||||||
|
return 0xffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* vsmGetStringName (SETUPX.205)
|
||||||
|
*
|
||||||
|
* Pretty correct, I guess
|
||||||
|
*/
|
||||||
|
INT16 WINAPI vsmGetStringName16(VHSTR vhstr, LPSTR lpszBuffer, int cbBuffer)
|
||||||
|
{
|
||||||
|
if (VALID_VHSTR(vhstr))
|
||||||
|
{
|
||||||
|
int len = strlen(vhstrlist[vhstr]->pStr)+1;
|
||||||
|
if (cbBuffer >= len)
|
||||||
|
{
|
||||||
|
if (lpszBuffer)
|
||||||
|
strcpy(lpszBuffer, vhstrlist[vhstr]->pStr);
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return VCPN_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* vsmStringCompare (not exported from a standard SETUPX.DLL, it seems)
|
||||||
|
*/
|
||||||
|
INT16 WINAPI vsmStringCompare16(VHSTR vhstrA, VHSTR vhstrB)
|
||||||
|
{
|
||||||
|
if ((!VALID_VHSTR(vhstrA)) || (!VALID_VHSTR(vhstrB)))
|
||||||
|
return VCPN_FAIL; /* correct ? */
|
||||||
|
return strcmp(vhstrlist[vhstrA]->pStr, vhstrlist[vhstrB]->pStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* vsmGetStringRawName (SETUPX.208)
|
||||||
|
*/
|
||||||
|
LPCSTR WINAPI vsmGetStringRawName16(VHSTR vhstr)
|
||||||
|
{
|
||||||
|
return (VALID_VHSTR(vhstr)) ? vhstrlist[vhstr]->pStr : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***************************** VIRTNODE management ****************************/
|
||||||
|
static LPVIRTNODE *pvnlist = NULL;
|
||||||
|
static DWORD vn_num = 0;
|
||||||
|
static DWORD vn_last = 0;
|
||||||
|
|
||||||
|
RETERR16 VCP_VirtnodeCreate(LPVCPFILESPEC vfsSrc, LPVCPFILESPEC vfsDst, WORD fl, LPARAM lParam, LPEXPANDVTBL lpExpandVtbl)
|
||||||
|
{
|
||||||
|
HANDLE heap;
|
||||||
|
LPVIRTNODE lpvn;
|
||||||
|
RETERR16 cbres;
|
||||||
|
|
||||||
|
while (vn_last < vn_num)
|
||||||
|
{
|
||||||
|
if (pvnlist[vn_last] == NULL)
|
||||||
|
break;
|
||||||
|
vn_last++;
|
||||||
|
}
|
||||||
|
heap = GetProcessHeap();
|
||||||
|
if (vn_last == vn_num)
|
||||||
|
{
|
||||||
|
vn_num += 20;
|
||||||
|
if (pvnlist)
|
||||||
|
pvnlist = HeapReAlloc(heap, HEAP_ZERO_MEMORY, pvnlist,
|
||||||
|
sizeof(LPVIRTNODE *) * vn_num);
|
||||||
|
else
|
||||||
|
pvnlist = HeapAlloc(heap, HEAP_ZERO_MEMORY,
|
||||||
|
sizeof(LPVIRTNODE *) * vn_num);
|
||||||
|
}
|
||||||
|
pvnlist[vn_last] = HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(VIRTNODE));
|
||||||
|
lpvn = pvnlist[vn_last];
|
||||||
|
vn_last++;
|
||||||
|
|
||||||
|
lpvn->cbSize = sizeof(VIRTNODE);
|
||||||
|
|
||||||
|
if (vfsSrc)
|
||||||
|
memcpy(&lpvn->vfsSrc, vfsSrc, sizeof(VCPFILESPEC));
|
||||||
|
|
||||||
|
if (vfsDst)
|
||||||
|
memcpy(&lpvn->vfsDst, vfsDst, sizeof(VCPFILESPEC));
|
||||||
|
|
||||||
|
lpvn->fl = fl;
|
||||||
|
lpvn->lParam = lParam;
|
||||||
|
lpvn->lpExpandVtbl = lpExpandVtbl;
|
||||||
|
|
||||||
|
lpvn->vhstrDstFinalName = 0xffff; /* FIXME: what is this ? */
|
||||||
|
|
||||||
|
cbres = VCP_Callback(lpvn, VCPM_NODECREATE, 0, 0, VCP_MsgRef);
|
||||||
|
lpvn->fl |= VFNL_CREATED;
|
||||||
|
cbres = VCP_Callback(lpvn, VCPM_NODEACCEPT, 0, 0, VCP_MsgRef);
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL VCP_VirtnodeDelete(LPVIRTNODE lpvnDel)
|
||||||
|
{
|
||||||
|
DWORD n;
|
||||||
|
RETERR16 cbres;
|
||||||
|
|
||||||
|
for (n = 0; n < vn_last; n++)
|
||||||
|
{
|
||||||
|
if (pvnlist[n] == lpvnDel)
|
||||||
|
{
|
||||||
|
cbres = VCP_Callback(lpvnDel, VCPM_NODEDESTROY, 0, 0, VCP_MsgRef);
|
||||||
|
HeapFree(GetProcessHeap(), 0, lpvnDel);
|
||||||
|
pvnlist[n] = NULL;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* VcpOpen (SETUPX.200)
|
||||||
|
*
|
||||||
|
* Sets up a virtual copy operation.
|
||||||
|
* This means that functions such as GenInstall()
|
||||||
|
* create a VIRTNODE struct for every file to be touched in a .INF file
|
||||||
|
* instead of actually touching the file.
|
||||||
|
* The actual copy/move/rename gets started when VcpClose or
|
||||||
|
* VcpFlush is called; several different callbacks are made
|
||||||
|
* (copy, rename, open, close, version conflicts, ...) on every file copied.
|
||||||
|
*/
|
||||||
|
RETERR16 WINAPI VcpOpen16(VIFPROC vifproc, LPARAM lparamMsgRef)
|
||||||
|
{
|
||||||
|
TRACE("(%p, %08lx)\n", vifproc, lparamMsgRef);
|
||||||
|
if (VCP_opened)
|
||||||
|
return ERR_VCP_BUSY;
|
||||||
|
|
||||||
|
VCP_Proc = (FARPROC16)vifproc;
|
||||||
|
VCP_MsgRef = lparamMsgRef;
|
||||||
|
|
||||||
|
/* load SETUPAPI needed for dialog resources etc. */
|
||||||
|
SETUPAPI_hInstance = LoadLibraryA("setupapi.dll");
|
||||||
|
if (!SETUPAPI_hInstance)
|
||||||
|
{
|
||||||
|
ERR("Could not load sibling setupapi.dll\n");
|
||||||
|
return ERR_VCP_NOMEM;
|
||||||
|
}
|
||||||
|
VCP_opened = TRUE;
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* VcpQueueCopy [SETUPX.13]
|
||||||
|
*
|
||||||
|
* lpExpandVtbl seems to be deprecated.
|
||||||
|
* fl are the CNFL_xxx and VNFL_xxx flags.
|
||||||
|
* lParam are the VNLP_xxx flags.
|
||||||
|
*/
|
||||||
|
RETERR16 WINAPI VcpQueueCopy16(
|
||||||
|
LPCSTR lpszSrcFileName, LPCSTR lpszDstFileName,
|
||||||
|
LPCSTR lpszSrcDir, LPCSTR lpszDstDir,
|
||||||
|
LOGDISKID16 ldidSrc, LOGDISKID16 ldidDst,
|
||||||
|
LPEXPANDVTBL lpExpandVtbl,
|
||||||
|
WORD fl, LPARAM lParam
|
||||||
|
)
|
||||||
|
{
|
||||||
|
VCPFILESPEC vfsSrc, vfsDst;
|
||||||
|
|
||||||
|
if (!VCP_opened)
|
||||||
|
return ERR_VCP_NOTOPEN;
|
||||||
|
|
||||||
|
TRACE("srcdir: %s, srcfile: %s, dstdir: %s, dstfile: %s\n",
|
||||||
|
lpszSrcDir, lpszSrcFileName, lpszDstDir, lpszDstFileName);
|
||||||
|
|
||||||
|
TRACE("ldidSrc == %d, ldidDst == %d\n", ldidSrc, ldidDst);
|
||||||
|
|
||||||
|
vfsSrc.ldid = ldidSrc;
|
||||||
|
vfsSrc.vhstrDir = vsmStringAdd16(lpszSrcDir);
|
||||||
|
vfsSrc.vhstrFileName = vsmStringAdd16(lpszSrcFileName);
|
||||||
|
|
||||||
|
vfsDst.ldid = ldidDst;
|
||||||
|
vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
|
||||||
|
vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);
|
||||||
|
|
||||||
|
return VCP_VirtnodeCreate(&vfsSrc, &vfsDst, fl, lParam,
|
||||||
|
lpExpandVtbl);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* VcpQueueDelete [SETUPX.17]
|
||||||
|
*
|
||||||
|
* Is lParamRef the same as lParam in VcpQueueCopy ?
|
||||||
|
* Damn docu !! Err... which docu ?
|
||||||
|
*/
|
||||||
|
RETERR16 WINAPI VcpQueueDelete16(
|
||||||
|
LPCSTR lpszDstFileName,
|
||||||
|
LPCSTR lpszDstDir,
|
||||||
|
LOGDISKID16 ldidDst,
|
||||||
|
LPARAM lParamRef
|
||||||
|
)
|
||||||
|
{
|
||||||
|
VCPFILESPEC vfsDst;
|
||||||
|
|
||||||
|
if (!VCP_opened)
|
||||||
|
return ERR_VCP_NOTOPEN;
|
||||||
|
|
||||||
|
vfsDst.ldid = ldidDst;
|
||||||
|
vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
|
||||||
|
vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);
|
||||||
|
|
||||||
|
return VCP_VirtnodeCreate(NULL, &vfsDst, VNFL_DELETE, lParamRef, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* VcpQueueRename [SETUPX.204]
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
RETERR16 WINAPI VcpQueueRename16(
|
||||||
|
LPCSTR lpszSrcFileName, LPCSTR lpszDstFileName,
|
||||||
|
LPCSTR lpszSrcDir, LPCSTR lpszDstDir,
|
||||||
|
LOGDISKID16 ldidSrc, LOGDISKID16 ldidDst,
|
||||||
|
LPARAM lParam
|
||||||
|
)
|
||||||
|
{
|
||||||
|
VCPFILESPEC vfsSrc, vfsDst;
|
||||||
|
|
||||||
|
if (!VCP_opened)
|
||||||
|
return ERR_VCP_NOTOPEN;
|
||||||
|
|
||||||
|
vfsSrc.ldid = ldidSrc;
|
||||||
|
vfsSrc.vhstrDir = vsmStringAdd16(lpszSrcDir);
|
||||||
|
vfsSrc.vhstrFileName = vsmStringAdd16(lpszSrcFileName);
|
||||||
|
|
||||||
|
vfsDst.ldid = ldidDst;
|
||||||
|
vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
|
||||||
|
vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);
|
||||||
|
|
||||||
|
return VCP_VirtnodeCreate(&vfsSrc, &vfsDst, VNFL_RENAME, lParam,
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* VcpEnumFiles (SETUPX.@)
|
||||||
|
*/
|
||||||
|
INT16 WINAPI VcpEnumFiles(VCPENUMPROC vep, LPARAM lParamRef)
|
||||||
|
{
|
||||||
|
WORD n;
|
||||||
|
|
||||||
|
for (n = 0; n < vn_last; n++)
|
||||||
|
vep(pvnlist[n], lParamRef);
|
||||||
|
|
||||||
|
return 0; /* FIXME: return value ? */
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* VcpExplain (SETUPX.411)
|
||||||
|
*/
|
||||||
|
LPCSTR WINAPI VcpExplain16(LPVIRTNODE lpVn, DWORD dwWhat)
|
||||||
|
{
|
||||||
|
static char buffer[MAX_PATH]; /* FIXME: is this how it's done ? */
|
||||||
|
buffer[0] = '\0';
|
||||||
|
switch (dwWhat)
|
||||||
|
{
|
||||||
|
case VCPEX_SRC_FULL:
|
||||||
|
case VCPEX_DST_FULL:
|
||||||
|
{
|
||||||
|
LPVCPFILESPEC lpvfs =
|
||||||
|
(dwWhat == VCPEX_SRC_FULL) ? &lpVn->vfsSrc : &lpVn->vfsDst;
|
||||||
|
|
||||||
|
/* if we have an ldid, use it, otherwise use the string */
|
||||||
|
/* from the vhstrlist array */
|
||||||
|
if (lpvfs->ldid != 0xffff)
|
||||||
|
CtlGetLddPath16(lpvfs->ldid, buffer);
|
||||||
|
else
|
||||||
|
strcat(buffer, vsmGetStringRawName16(lpvfs->vhstrDir));
|
||||||
|
|
||||||
|
strcat(buffer, "\\");
|
||||||
|
strcat(buffer, vsmGetStringRawName16(lpvfs->vhstrFileName));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
FIXME("%ld unimplemented !\n", dwWhat);
|
||||||
|
strcpy(buffer, "Unknown error");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
RETERR16 VCP_CheckPaths(void)
|
||||||
|
{
|
||||||
|
DWORD n;
|
||||||
|
LPVIRTNODE lpvn;
|
||||||
|
RETERR16 cbres;
|
||||||
|
|
||||||
|
cbres = VCP_Callback(&vcp_status, VCPM_VSTATPATHCHECKSTART, 0, 0, VCP_MsgRef);
|
||||||
|
for (n = 0; n < vn_num; n++)
|
||||||
|
{
|
||||||
|
lpvn = pvnlist[n];
|
||||||
|
if (!lpvn) continue;
|
||||||
|
/* FIXME: check paths of all VIRTNODEs here ! */
|
||||||
|
cbres = VCP_Callback(&lpvn->vfsDst, VCPM_CHECKPATH, 0, (DWORD)lpvn, VCP_MsgRef);
|
||||||
|
}
|
||||||
|
cbres = VCP_Callback(&vcp_status, VCPM_VSTATPATHCHECKEND, 0, 0, VCP_MsgRef);
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
RETERR16 VCP_CopyFiles(void)
|
||||||
|
{
|
||||||
|
char fn_src[MAX_PATH], fn_dst[MAX_PATH];
|
||||||
|
RETERR16 res = OK, cbres;
|
||||||
|
DWORD n;
|
||||||
|
LPVIRTNODE lpvn;
|
||||||
|
|
||||||
|
cbres = VCP_Callback(&vcp_status, VCPM_VSTATCOPYSTART, 0, 0, VCP_MsgRef);
|
||||||
|
for (n = 0; n < vn_num; n++)
|
||||||
|
{
|
||||||
|
lpvn = pvnlist[n];
|
||||||
|
if ((!lpvn) || ((lpvn->fl & VNFL_NODE_TYPE) != VNFL_COPY)) continue;
|
||||||
|
/* FIXME: need to send VCPM_VSTATNEWDISK notification sometimes */
|
||||||
|
strcpy(fn_src, VcpExplain16(lpvn, VCPEX_SRC_FULL));
|
||||||
|
strcpy(fn_dst, VcpExplain16(lpvn, VCPEX_DST_FULL));
|
||||||
|
/* FIXME: what is this VCPM_VSTATWRITE here for ?
|
||||||
|
* I guess it's to signal successful destination file creation */
|
||||||
|
cbres = VCP_Callback(&vcp_status, VCPM_VSTATWRITE, 0, 0, VCP_MsgRef);
|
||||||
|
|
||||||
|
/* FIXME: need to do the file copy in small chunks for notifications */
|
||||||
|
TRACE("copying '%s' to '%s'\n", fn_src, fn_dst);
|
||||||
|
/* perform the file copy */
|
||||||
|
if (!(CopyFileA(fn_src, fn_dst,
|
||||||
|
(lpvn->fl & VNLP_COPYIFEXISTS) ? FALSE : TRUE )))
|
||||||
|
{
|
||||||
|
ERR("error copying, src: %s -> dst: %s\n", fn_src, fn_dst);
|
||||||
|
res = ERR_VCP_IOFAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
vcp_status.prgFileRead.dwSoFar++;
|
||||||
|
cbres = VCP_Callback(&vcp_status, VCPM_VSTATREAD, 0, 0, VCP_MsgRef);
|
||||||
|
vcp_status.prgFileWrite.dwSoFar++;
|
||||||
|
cbres = VCP_Callback(&vcp_status, VCPM_VSTATWRITE, 0, 0, VCP_MsgRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
cbres = VCP_Callback(&vcp_status, VCPM_VSTATCOPYEND, 0, 0, VCP_MsgRef);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* VcpFlush - internal (not exported), but documented
|
||||||
|
*
|
||||||
|
* VNFL_NOW is used for VcpFlush.
|
||||||
|
*/
|
||||||
|
RETERR16 VcpFlush16(WORD fl, LPCSTR lpszBackupDest)
|
||||||
|
{
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* VcpClose (SETUPX.201)
|
||||||
|
*
|
||||||
|
* Does callbacks (-> vifproc) with VCPM_VSTATCLOSESTART,
|
||||||
|
* VCPM_VSTATCLOSEEND.
|
||||||
|
*
|
||||||
|
* fl gets VCPFL_xxx flags to indicate what to do with the
|
||||||
|
* VIRTNODEs (files to mess with) created by e.g. GenInstall()
|
||||||
|
*/
|
||||||
|
RETERR16 WINAPI VcpClose16(WORD fl, LPCSTR lpszBackupDest)
|
||||||
|
{
|
||||||
|
RETERR16 res = OK;
|
||||||
|
WORD cbres = VCPN_PROCEED;
|
||||||
|
|
||||||
|
TRACE("(%04x, '%s')\n", fl, lpszBackupDest);
|
||||||
|
|
||||||
|
/* FIXME: needs to sort virtnodes in case VCPFL_INSPECIFIEDORDER
|
||||||
|
* is not set. This is done by VCP_Callback(VCPM_NODECOMPARE) */
|
||||||
|
|
||||||
|
TRACE("#1\n");
|
||||||
|
memset(&vcp_status, 0, sizeof(VCPSTATUS));
|
||||||
|
/* yes, vcp_status.cbSize is 0 ! */
|
||||||
|
TRACE("#2\n");
|
||||||
|
cbres = VCP_Callback(&vcp_status, VCPM_VSTATCLOSESTART, 0, 0, VCP_MsgRef);
|
||||||
|
TRACE("#3\n");
|
||||||
|
|
||||||
|
res = VCP_CheckPaths();
|
||||||
|
TRACE("#4\n");
|
||||||
|
if (res != OK)
|
||||||
|
return res; /* is this ok ? */
|
||||||
|
VCP_CopyFiles();
|
||||||
|
|
||||||
|
TRACE("#5\n");
|
||||||
|
cbres = VCP_Callback(&vcp_status, VCPM_VSTATCLOSEEND, 0, 0, VCP_MsgRef);
|
||||||
|
TRACE("#6\n");
|
||||||
|
VCP_Proc = NULL;
|
||||||
|
FreeLibrary(SETUPAPI_hInstance);
|
||||||
|
VCP_opened = FALSE;
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
RETERR16 VCP_RenameFiles(void)
|
||||||
|
{
|
||||||
|
char fn_src[MAX_PATH], fn_dst[MAX_PATH];
|
||||||
|
RETERR16 res = OK, cbres;
|
||||||
|
DWORD n;
|
||||||
|
LPVIRTNODE lpvn;
|
||||||
|
|
||||||
|
cbres = VCP_Callback(&vcp_status, VCPM_VSTATRENAMESTART, 0, 0, VCP_MsgRef);
|
||||||
|
for (n = 0; n < vn_num; n++)
|
||||||
|
{
|
||||||
|
lpvn = pvnlist[n];
|
||||||
|
if ((!lpvn) || ((lpvn->fl & VNFL_NODE_TYPE) != VNFL_RENAME)) continue;
|
||||||
|
strcpy(fn_src, VcpExplain16(lpvn, VCPEX_SRC_FULL));
|
||||||
|
strcpy(fn_dst, VcpExplain16(lpvn, VCPEX_DST_FULL));
|
||||||
|
cbres = VCP_Callback(&lpvn->vfsDst, VCPM_FILEOPENOUT, 0, (LPARAM)lpvn, VCP_MsgRef);
|
||||||
|
if (!(MoveFileExA(fn_src, fn_dst, MOVEFILE_REPLACE_EXISTING)))
|
||||||
|
res = ERR_VCP_IOFAIL;
|
||||||
|
else
|
||||||
|
VCP_VirtnodeDelete(lpvn);
|
||||||
|
}
|
||||||
|
cbres = VCP_Callback(&vcp_status, VCPM_VSTATRENAMEEND, 0, 0, VCP_MsgRef);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* vcpDefCallbackProc (SETUPX.202)
|
||||||
|
*/
|
||||||
|
RETERR16 WINAPI vcpDefCallbackProc16(LPVOID lpvObj, UINT16 uMsg, WPARAM wParam,
|
||||||
|
LPARAM lParam, LPARAM lParamRef)
|
||||||
|
{
|
||||||
|
static int count = 0;
|
||||||
|
if (count < 10)
|
||||||
|
FIXME("(%p, %04x, %04x, %08lx, %08lx) - what to do here ?\n",
|
||||||
|
lpvObj, uMsg, wParam, lParam, lParamRef);
|
||||||
|
count++;
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************* point-and-click stuff from here ***********************/
|
||||||
|
|
||||||
|
static HWND hDlgCopy = 0;
|
||||||
|
static HKEY hKeyFiles = 0, hKeyRename = 0, hKeyConflict = 0;
|
||||||
|
static char BackupDir[12];
|
||||||
|
|
||||||
|
static INT_PTR CALLBACK VCP_UI_FileCopyDlgProc(HWND hWndDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
INT_PTR retval = FALSE;
|
||||||
|
|
||||||
|
if (iMsg == WM_INITDIALOG)
|
||||||
|
{
|
||||||
|
ShowWindow(hWndDlg, SW_SHOWNORMAL);
|
||||||
|
UpdateWindow(hWndDlg);
|
||||||
|
retval = TRUE;
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL VCP_UI_GetDialogTemplate(LPCVOID *template32)
|
||||||
|
{
|
||||||
|
HRSRC hResInfo;
|
||||||
|
HGLOBAL hDlgTmpl32;
|
||||||
|
|
||||||
|
if (!(hResInfo = FindResourceA(SETUPAPI_hInstance, MAKEINTRESOURCEA(COPYFILEDLGORD), (LPSTR)RT_DIALOG)))
|
||||||
|
return FALSE;
|
||||||
|
if (!(hDlgTmpl32 = LoadResource(SETUPAPI_hInstance, hResInfo )) ||
|
||||||
|
!(*template32 = LockResource( hDlgTmpl32 )))
|
||||||
|
return FALSE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static LRESULT WINAPI
|
||||||
|
VCP_UI_FileCopyWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
if (uMsg != WM_CREATE)
|
||||||
|
return DefWindowProcA (hwnd, uMsg, wParam, lParam);
|
||||||
|
|
||||||
|
switch (uMsg)
|
||||||
|
{
|
||||||
|
case WM_CREATE:
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
FIXME("%04x: unhandled.\n", uMsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VCP_UI_RegisterProgressClass(void)
|
||||||
|
{
|
||||||
|
static BOOL registered = FALSE;
|
||||||
|
WNDCLASSA wndClass;
|
||||||
|
|
||||||
|
if (registered)
|
||||||
|
return;
|
||||||
|
|
||||||
|
registered = TRUE;
|
||||||
|
ZeroMemory (&wndClass, sizeof(WNDCLASSA));
|
||||||
|
wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
|
||||||
|
wndClass.lpfnWndProc = (WNDPROC)VCP_UI_FileCopyWndProc;
|
||||||
|
wndClass.cbClsExtra = 0;
|
||||||
|
wndClass.cbWndExtra = 0;
|
||||||
|
wndClass.hCursor = LoadCursorA (0, (LPSTR)IDC_ARROW);
|
||||||
|
wndClass.hbrBackground = NULL;
|
||||||
|
wndClass.lpszClassName = "setupx_progress";
|
||||||
|
|
||||||
|
RegisterClassA (&wndClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
RETERR16 VCP_UI_NodeCompare(LPVIRTNODE vn1, LPVIRTNODE vn2)
|
||||||
|
{
|
||||||
|
LPCSTR file1, file2;
|
||||||
|
file1 = vsmGetStringRawName16(vn1->vfsSrc.vhstrFileName);
|
||||||
|
file2 = vsmGetStringRawName16(vn2->vfsSrc.vhstrFileName);
|
||||||
|
return (RETERR16)strcmp(file1, file2);
|
||||||
|
}
|
||||||
|
|
||||||
|
RETERR16 VCP_UI_CopyStart(void)
|
||||||
|
{
|
||||||
|
LPCVOID template32;
|
||||||
|
char buf[256]; /* plenty */
|
||||||
|
BOOL dirty;
|
||||||
|
DWORD len;
|
||||||
|
|
||||||
|
/* FIXME: should be registered at DLL startup instead */
|
||||||
|
VCP_UI_RegisterProgressClass();
|
||||||
|
if (!(VCP_UI_GetDialogTemplate(&template32)))
|
||||||
|
return VCPN_FAIL;
|
||||||
|
|
||||||
|
if (vn_num > 10) /* hack */
|
||||||
|
{
|
||||||
|
hDlgCopy = CreateDialogIndirectParamA(SETUPAPI_hInstance, template32, 0,
|
||||||
|
VCP_UI_FileCopyDlgProc, 0);
|
||||||
|
if (!hDlgCopy)
|
||||||
|
return VCPN_FAIL;
|
||||||
|
SetDlgItemTextA(hDlgCopy, SOURCESTRORD, "Scanning ...");
|
||||||
|
SetDlgItemTextA(hDlgCopy, DESTSTRORD, "NOT_IMPLEMENTED_YET");
|
||||||
|
}
|
||||||
|
strcpy(buf, REG_INSTALLEDFILES);
|
||||||
|
if (RegCreateKeyA(HKEY_LOCAL_MACHINE, buf, &hKeyFiles))
|
||||||
|
return VCPN_FAIL;
|
||||||
|
strcat(buf, REGPART_RENAME);
|
||||||
|
if (RegCreateKeyA(HKEY_LOCAL_MACHINE, buf, &hKeyRename))
|
||||||
|
return VCPN_FAIL;
|
||||||
|
if (RegCreateKeyA(HKEY_LOCAL_MACHINE, REG_VERSIONCONFLICT, &hKeyConflict))
|
||||||
|
return VCPN_FAIL;
|
||||||
|
len = 1;
|
||||||
|
if (!(RegQueryValueExA(hKeyConflict, "Dirty", NULL, 0, (LPBYTE)&dirty, &len)))
|
||||||
|
{
|
||||||
|
/* FIXME: what does SETUPX.DLL do in this case ? */
|
||||||
|
MESSAGE("Warning: another program using SETUPX is already running ! Failed.\n");
|
||||||
|
return VCPN_FAIL;
|
||||||
|
}
|
||||||
|
dirty = TRUE;
|
||||||
|
if (RegSetValueExA(hKeyConflict, "Dirty", 0, REG_BINARY, (LPBYTE)&dirty, 1))
|
||||||
|
return VCPN_FAIL;
|
||||||
|
len = 12;
|
||||||
|
if (!(RegQueryValueExA(hKeyConflict, "BackupDirectory", NULL, 0, BackupDir, &len)))
|
||||||
|
strcpy(BackupDir, "VCM");
|
||||||
|
|
||||||
|
/* create C:\WINDOWS\[BackupDir] and set registry key to it */
|
||||||
|
GetWindowsDirectoryA(buf, 256);
|
||||||
|
strcat(buf, "\\");
|
||||||
|
strcat(buf, BackupDir);
|
||||||
|
if (!(CreateDirectoryA(buf, NULL)))
|
||||||
|
return VCPN_FAIL;
|
||||||
|
if (RegSetValueExA(hKeyConflict, "BackupDirectory", 0, REG_SZ, (LPBYTE)buf, strlen(buf)+1))
|
||||||
|
return VCPN_FAIL;
|
||||||
|
RegCloseKey(hKeyConflict);
|
||||||
|
|
||||||
|
return VCPN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* vcpUICallbackProc (SETUPX.213)
|
||||||
|
*/
|
||||||
|
RETERR16 WINAPI vcpUICallbackProc16(LPVOID lpvObj, UINT16 uMsg, WPARAM wParam,
|
||||||
|
LPARAM lParam, LPARAM lParamRef)
|
||||||
|
{
|
||||||
|
static int count = 0;
|
||||||
|
RETERR16 res = VCPN_OK, cbres;
|
||||||
|
|
||||||
|
if (count < 5)
|
||||||
|
FIXME("(%p, %04x, %04x, %08lx, %08lx) - semi-stub\n",
|
||||||
|
lpvObj, uMsg, wParam, lParam, lParamRef);
|
||||||
|
count++;
|
||||||
|
switch (uMsg)
|
||||||
|
{
|
||||||
|
/* unused messages, it seems */
|
||||||
|
case VCPM_DISKPREPINFO:
|
||||||
|
|
||||||
|
case VCPM_FILENEEDED:
|
||||||
|
|
||||||
|
case VCPM_NODECREATE:
|
||||||
|
case VCPM_NODEACCEPT:
|
||||||
|
|
||||||
|
case VCPM_VSTATCLOSESTART:
|
||||||
|
case VCPM_VSTATPATHCHECKSTART:
|
||||||
|
case VCPM_VSTATPATHCHECKEND:
|
||||||
|
|
||||||
|
case VCPM_CHECKPATH:
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* the real stuff */
|
||||||
|
case VCPM_NODECOMPARE:
|
||||||
|
res = VCP_UI_NodeCompare((LPVIRTNODE)lpvObj, (LPVIRTNODE)lParam);
|
||||||
|
break;
|
||||||
|
case VCPM_VSTATREAD:
|
||||||
|
break;
|
||||||
|
case VCPM_VSTATWRITE:
|
||||||
|
cbres = VCP_Callback(&vcp_status, VCPM_DISKPREPINFO, 0, 0, VCP_MsgRef);
|
||||||
|
break;
|
||||||
|
case VCPM_VSTATCLOSEEND:
|
||||||
|
RegCloseKey(hKeyFiles);
|
||||||
|
RegCloseKey(hKeyRename);
|
||||||
|
RegDeleteKeyA(HKEY_LOCAL_MACHINE, REG_VERSIONCONFLICT);
|
||||||
|
break;
|
||||||
|
case VCPM_VSTATCOPYSTART:
|
||||||
|
res = VCP_UI_CopyStart();
|
||||||
|
break;
|
||||||
|
case VCPM_VSTATCOPYEND:
|
||||||
|
if (hDlgCopy) DestroyWindow(hDlgCopy);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
FIXME("unhandled msg 0x%04x\n", uMsg);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
Loading…
Reference in a new issue