Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
36bf71c1
Commit
36bf71c1
authored
Jun 15, 2006
by
James Hawkins
Committed by
Alexandre Julliard
Jun 15, 2006
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
msi: Add tests for MsiInstallProduct.
parent
7f8c29a4
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
652 additions
and
1 deletion
+652
-1
.gitignore
dlls/msi/tests/.gitignore
+1
-0
Makefile.in
dlls/msi/tests/Makefile.in
+2
-1
install.c
dlls/msi/tests/install.c
+649
-0
No files found.
dlls/msi/tests/.gitignore
View file @
36bf71c1
Makefile
db.ok
format.ok
install.ok
msi.ok
package.ok
record.ok
...
...
dlls/msi/tests/Makefile.in
View file @
36bf71c1
...
...
@@ -3,11 +3,12 @@ TOPOBJDIR = ../../..
SRCDIR
=
@srcdir@
VPATH
=
@srcdir@
TESTDLL
=
msi.dll
IMPORTS
=
msi
kernel32
IMPORTS
=
cabinet msi advapi32
kernel32
CTESTS
=
\
db.c
\
format.c
\
install.c
\
msi.c
\
package.c
\
record.c
\
...
...
dlls/msi/tests/install.c
0 → 100644
View file @
36bf71c1
/*
* Copyright (C) 2006 James Hawkins
*
* A test program for installing MSI products.
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdio.h>
#include <windows.h>
#include <msiquery.h>
#include <msidefs.h>
#include <msi.h>
#include <fci.h>
#include "wine/test.h"
static
const
char
*
msifile
=
"winetest.msi"
;
CHAR
CURR_DIR
[
MAX_PATH
];
CHAR
PROG_FILES_DIR
[
MAX_PATH
];
/* msi database data */
static
const
CHAR
admin_exec_seq_dat
[]
=
"Action
\t
Condition
\t
Sequence
\n
"
"s72
\t
S255
\t
I2
\n
"
"AdminExecuteSequence
\t
Action
\n
"
"CostFinalize
\t\t
1000
\n
"
"CostInitialize
\t\t
800
\n
"
"FileCost
\t\t
900
\n
"
"InstallAdminPackage
\t\t
3900
\n
"
"InstallFiles
\t\t
4000
\n
"
"InstallFinalize
\t\t
6600
\n
"
"InstallInitialize
\t\t
1500
\n
"
"InstallValidate
\t\t
1400"
;
static
const
CHAR
advt_exec_seq_dat
[]
=
"Action
\t
Condition
\t
Sequence
\n
"
"s72
\t
S255
\t
I2
\n
"
"AdvtExecuteSequence
\t
Action
\n
"
"CostFinalize
\t\t
1000
\n
"
"CostInitialize
\t\t
800
\n
"
"CreateShortcuts
\t\t
4500
\n
"
"InstallFinalize
\t\t
6600
\n
"
"InstallInitialize
\t\t
1500
\n
"
"InstallValidate
\t\t
1400
\n
"
"PublishComponents
\t\t
6200
\n
"
"PublishFeatures
\t\t
6300
\n
"
"PublishProduct
\t\t
6400
\n
"
"RegisterClassInfo
\t\t
4600
\n
"
"RegisterExtensionInfo
\t\t
4700
\n
"
"RegisterMIMEInfo
\t\t
4900
\n
"
"RegisterProgIdInfo
\t\t
4800"
;
static
const
CHAR
component_dat
[]
=
"Component
\t
ComponentId
\t
Directory_
\t
Attributes
\t
Condition
\t
KeyPath
\n
"
"s72
\t
S38
\t
s72
\t
i2
\t
S255
\t
S72
\n
"
"Component
\t
Component
\n
"
"Five
\t
{8CC92E9D-14B2-4CA4-B2AA-B11D02078087}
\t
NEWDIR
\t
2
\t\t
five.txt
\n
"
"Four
\t
{FD37B4EA-7209-45C0-8917-535F35A2F080}
\t
CABOUTDIR
\t
2
\t\t
four.txt
\n
"
"One
\t
{783B242E-E185-4A56-AF86-C09815EC053C}
\t
MSITESTDIR
\t
2
\t\t
one.txt
\n
"
"Three
\t
{010B6ADD-B27D-4EDD-9B3D-34C4F7D61684}
\t
CHANGEDDIR
\t
2
\t\t
three.txt
\n
"
"Two
\t
{BF03D1A6-20DA-4A65-82F3-6CAC995915CE}
\t
FIRSTDIR
\t
2
\t\t
two.txt"
;
static
const
CHAR
directory_dat
[]
=
"Directory
\t
Directory_Parent
\t
DefaultDir
\n
"
"s72
\t
S72
\t
l255
\n
"
"Directory
\t
Directory
\n
"
"CABOUTDIR
\t
MSITESTDIR
\t
cabout
\n
"
"CHANGEDDIR
\t
MSITESTDIR
\t
changed:second
\n
"
"FIRSTDIR
\t
MSITESTDIR
\t
first
\n
"
"MSITESTDIR
\t
ProgramFilesFolder
\t
msitest
\n
"
"NEWDIR
\t
CABOUTDIR
\t
new
\n
"
"ProgramFilesFolder
\t
TARGETDIR
\t
.
\n
"
"TARGETDIR
\t\t
SourceDir"
;
static
const
CHAR
feature_dat
[]
=
"Feature
\t
Feature_Parent
\t
Title
\t
Description
\t
Display
\t
Level
\t
Directory_
\t
Attributes
\n
"
"s38
\t
S38
\t
L64
\t
L255
\t
I2
\t
i2
\t
S72
\t
i2
\n
"
"Feature
\t
Feature
\n
"
"Five
\t\t
Five
\t
The Five Feature
\t
5
\t
3
\t
NEWDIR
\t
0
\n
"
"Four
\t\t
Four
\t
The Four Feature
\t
4
\t
3
\t
CABOUTDIR
\t
0
\n
"
"One
\t\t
One
\t
The One Feature
\t
1
\t
3
\t
MSITESTDIR
\t
0
\n
"
"Three
\t\t
Three
\t
The Three Feature
\t
3
\t
3
\t
CHANGEDDIR
\t
0
\n
"
"Two
\t\t
Two
\t
The Two Feature
\t
2
\t
3
\t
FIRSTDIR
\t
0"
;
static
const
CHAR
feature_comp_dat
[]
=
"Feature_
\t
Component_
\n
"
"s38
\t
s72
\n
"
"FeatureComponents
\t
Feature_
\t
Component_
\n
"
"Five
\t
Five
\n
"
"Four
\t
Four
\n
"
"One
\t
One
\n
"
"Three
\t
Three
\n
"
"Two
\t
Two"
;
static
const
CHAR
file_dat
[]
=
"File
\t
Component_
\t
FileName
\t
FileSize
\t
Version
\t
Language
\t
Attributes
\t
Sequence
\n
"
"s72
\t
s72
\t
l255
\t
i4
\t
S72
\t
S20
\t
I2
\t
i2
\n
"
"File
\t
File
\n
"
"five.txt
\t
Five
\t
five.txt
\t
1000
\t\t\t
16384
\t
5
\n
"
"four.txt
\t
Four
\t
four.txt
\t
1000
\t\t\t
16384
\t
4
\n
"
"one.txt
\t
One
\t
one.txt
\t
1000
\t\t\t
0
\t
1
\n
"
"three.txt
\t
Three
\t
three.txt
\t
1000
\t\t\t
0
\t
3
\n
"
"two.txt
\t
Two
\t
two.txt
\t
1000
\t\t\t
0
\t
2"
;
static
const
CHAR
install_exec_seq_dat
[]
=
"Action
\t
Condition
\t
Sequence
\n
"
"s72
\t
S255
\t
I2
\n
"
"InstallExecuteSequence
\t
Action
\n
"
"AllocateRegistrySpace
\t
NOT Installed
\t
1550
\n
"
"CostFinalize
\t\t
1000
\n
"
"CostInitialize
\t\t
800
\n
"
"FileCost
\t\t
900
\n
"
"InstallFiles
\t\t
4000
\n
"
"InstallFinalize
\t\t
6600
\n
"
"InstallInitialize
\t\t
1500
\n
"
"InstallValidate
\t\t
1400
\n
"
"LaunchConditions
\t\t
100
\n
"
"WriteRegistryValues
\t\t
5000"
;
static
const
CHAR
media_dat
[]
=
"DiskId
\t
LastSequence
\t
DiskPrompt
\t
Cabinet
\t
VolumeLabel
\t
Source
\n
"
"i2
\t
i2
\t
L64
\t
S255
\t
S32
\t
S72
\n
"
"Media
\t
DiskId
\n
"
"1
\t
3
\t\t\t
DISK1
\t\n
"
"2
\t
5
\t\t
msitest.cab
\t
DISK2
\t\n
"
;
static
const
CHAR
property_dat
[]
=
"Property
\t
Value
\n
"
"s72
\t
l0
\n
"
"Property
\t
Property
\n
"
"DefaultUIFont
\t
DlgFont8
\n
"
"INSTALLLEVEL
\t
3
\n
"
"InstallMode
\t
Typical
\n
"
"Manufacturer
\t
Wine
\n
"
"PIDTemplate
\t
12345<###-%%%%%%%>@@@@@
\n
"
"ProductCode
\t
{F1C3AF50-8B56-4A69-A00C-00773FE42F30}
\n
"
"ProductID
\t
none
\n
"
"ProductLanguage
\t
1033
\n
"
"ProductName
\t
MSITEST
\n
"
"ProductVersion
\t
1.1.1
\n
"
"PROMPTROLLBACKCOST
\t
P
\n
"
"Setup
\t
Setup
\n
"
"UpgradeCode
\t
{CE067E8D-2E1A-4367-B734-4EB2BDAD6565}"
;
static
const
CHAR
registry_dat
[]
=
"Registry
\t
Root
\t
Key
\t
Name
\t
Value
\t
Component_
\n
"
"s72
\t
i2
\t
l255
\t
L255
\t
L0
\t
s72
\n
"
"Registry
\t
Registry
\n
"
"Apples
\t
2
\t
SOFTWARE
\\
Wine
\\
msitest
\t
Name
\t
imaname
\t
One
\n
"
"Oranges
\t
2
\t
SOFTWARE
\\
Wine
\\
msitest
\t
number
\t
#314
\t
Two"
;
typedef
struct
_msi_table
{
const
CHAR
*
filename
;
const
CHAR
*
data
;
int
size
;
}
msi_table
;
#define ADD_TABLE(x) {#x".idt", x##_dat, sizeof(x##_dat)}
static
const
msi_table
tables
[]
=
{
ADD_TABLE
(
admin_exec_seq
),
ADD_TABLE
(
advt_exec_seq
),
ADD_TABLE
(
component
),
ADD_TABLE
(
directory
),
ADD_TABLE
(
feature
),
ADD_TABLE
(
feature_comp
),
ADD_TABLE
(
file
),
ADD_TABLE
(
install_exec_seq
),
ADD_TABLE
(
media
),
ADD_TABLE
(
property
),
ADD_TABLE
(
registry
)
};
/* cabinet definitions */
/* make the max size large so there is only one cab file */
#define MEDIA_SIZE 999999999
#define FOLDER_THRESHOLD 900000
/* The following defintions were copied from dlls/cabinet/cabinet.h
* because they are undocumented in windows.
*/
/* EXTRACTdest flags */
#define EXTRACT_FILLFILELIST 0x00000001
#define EXTRACT_EXTRACTFILES 0x00000002
struct
ExtractFileList
{
LPSTR
filename
;
struct
ExtractFileList
*
next
;
BOOL
unknown
;
/* always 1L */
};
/* the first parameter of the function extract */
typedef
struct
{
long
result1
;
/* 0x000 */
long
unknown1
[
3
];
/* 0x004 */
struct
ExtractFileList
*
filelist
;
/* 0x010 */
long
filecount
;
/* 0x014 */
long
flags
;
/* 0x018 */
char
directory
[
0x104
];
/* 0x01c */
char
lastfile
[
0x20c
];
/* 0x120 */
}
EXTRACTDEST
;
/* cabinet function pointers */
HMODULE
hCabinet
;
static
HRESULT
(
WINAPI
*
pExtract
)(
EXTRACTDEST
*
,
LPCSTR
);
/* the FCI callbacks */
static
void
*
mem_alloc
(
ULONG
cb
)
{
return
HeapAlloc
(
GetProcessHeap
(),
0
,
cb
);
}
static
void
mem_free
(
void
*
memory
)
{
HeapFree
(
GetProcessHeap
(),
0
,
memory
);
}
static
BOOL
get_next_cabinet
(
PCCAB
pccab
,
ULONG
cbPrevCab
,
void
*
pv
)
{
return
TRUE
;
}
static
long
progress
(
UINT
typeStatus
,
ULONG
cb1
,
ULONG
cb2
,
void
*
pv
)
{
return
0
;
}
static
int
file_placed
(
PCCAB
pccab
,
char
*
pszFile
,
long
cbFile
,
BOOL
fContinuation
,
void
*
pv
)
{
return
0
;
}
static
INT_PTR
fci_open
(
char
*
pszFile
,
int
oflag
,
int
pmode
,
int
*
err
,
void
*
pv
)
{
HANDLE
handle
;
DWORD
dwAccess
=
0
;
DWORD
dwShareMode
=
0
;
DWORD
dwCreateDisposition
=
OPEN_EXISTING
;
dwAccess
=
GENERIC_READ
|
GENERIC_WRITE
;
dwShareMode
=
FILE_SHARE_READ
|
FILE_SHARE_WRITE
|
FILE_SHARE_DELETE
;
if
(
GetFileAttributesA
(
pszFile
)
!=
INVALID_FILE_ATTRIBUTES
)
dwCreateDisposition
=
OPEN_EXISTING
;
else
dwCreateDisposition
=
CREATE_NEW
;
handle
=
CreateFileA
(
pszFile
,
dwAccess
,
dwShareMode
,
NULL
,
dwCreateDisposition
,
0
,
NULL
);
ok
(
handle
!=
INVALID_HANDLE_VALUE
,
"Failed to CreateFile %s
\n
"
,
pszFile
);
return
(
INT_PTR
)
handle
;
}
static
UINT
fci_read
(
INT_PTR
hf
,
void
*
memory
,
UINT
cb
,
int
*
err
,
void
*
pv
)
{
HANDLE
handle
=
(
HANDLE
)
hf
;
DWORD
dwRead
;
BOOL
res
;
res
=
ReadFile
(
handle
,
memory
,
cb
,
&
dwRead
,
NULL
);
ok
(
res
,
"Failed to ReadFile
\n
"
);
return
dwRead
;
}
static
UINT
fci_write
(
INT_PTR
hf
,
void
*
memory
,
UINT
cb
,
int
*
err
,
void
*
pv
)
{
HANDLE
handle
=
(
HANDLE
)
hf
;
DWORD
dwWritten
;
BOOL
res
;
res
=
WriteFile
(
handle
,
memory
,
cb
,
&
dwWritten
,
NULL
);
ok
(
res
,
"Failed to WriteFile
\n
"
);
return
dwWritten
;
}
static
int
fci_close
(
INT_PTR
hf
,
int
*
err
,
void
*
pv
)
{
HANDLE
handle
=
(
HANDLE
)
hf
;
ok
(
CloseHandle
(
handle
),
"Failed to CloseHandle
\n
"
);
return
0
;
}
static
long
fci_seek
(
INT_PTR
hf
,
long
dist
,
int
seektype
,
int
*
err
,
void
*
pv
)
{
HANDLE
handle
=
(
HANDLE
)
hf
;
DWORD
ret
;
ret
=
SetFilePointer
(
handle
,
dist
,
NULL
,
seektype
);
ok
(
ret
!=
INVALID_SET_FILE_POINTER
,
"Failed to SetFilePointer
\n
"
);
return
ret
;
}
static
int
fci_delete
(
char
*
pszFile
,
int
*
err
,
void
*
pv
)
{
BOOL
ret
=
DeleteFileA
(
pszFile
);
ok
(
ret
,
"Failed to DeleteFile %s
\n
"
,
pszFile
);
return
0
;
}
static
BOOL
get_temp_file
(
char
*
pszTempName
,
int
cbTempName
,
void
*
pv
)
{
LPSTR
tempname
;
tempname
=
HeapAlloc
(
GetProcessHeap
(),
0
,
MAX_PATH
);
GetTempFileNameA
(
"."
,
"xx"
,
0
,
tempname
);
if
(
tempname
&&
(
strlen
(
tempname
)
<
(
unsigned
)
cbTempName
))
{
lstrcpyA
(
pszTempName
,
tempname
);
HeapFree
(
GetProcessHeap
(),
0
,
tempname
);
return
TRUE
;
}
HeapFree
(
GetProcessHeap
(),
0
,
tempname
);
return
FALSE
;
}
static
INT_PTR
get_open_info
(
char
*
pszName
,
USHORT
*
pdate
,
USHORT
*
ptime
,
USHORT
*
pattribs
,
int
*
err
,
void
*
pv
)
{
BY_HANDLE_FILE_INFORMATION
finfo
;
FILETIME
filetime
;
HANDLE
handle
;
DWORD
attrs
;
BOOL
res
;
handle
=
CreateFile
(
pszName
,
GENERIC_READ
,
FILE_SHARE_READ
,
NULL
,
OPEN_EXISTING
,
FILE_ATTRIBUTE_NORMAL
|
FILE_FLAG_SEQUENTIAL_SCAN
,
NULL
);
ok
(
handle
!=
INVALID_HANDLE_VALUE
,
"Failed to CreateFile %s
\n
"
,
pszName
);
res
=
GetFileInformationByHandle
(
handle
,
&
finfo
);
ok
(
res
,
"Expected GetFileInformationByHandle to succeed
\n
"
);
FileTimeToLocalFileTime
(
&
finfo
.
ftLastWriteTime
,
&
filetime
);
FileTimeToDosDateTime
(
&
filetime
,
pdate
,
ptime
);
attrs
=
GetFileAttributes
(
pszName
);
ok
(
attrs
!=
INVALID_FILE_ATTRIBUTES
,
"Failed to GetFileAttributes
\n
"
);
return
(
INT_PTR
)
handle
;
}
static
void
add_file
(
HFCI
hfci
,
char
*
file
)
{
char
path
[
MAX_PATH
];
BOOL
res
;
lstrcpyA
(
path
,
CURR_DIR
);
lstrcatA
(
path
,
"
\\
"
);
lstrcatA
(
path
,
file
);
res
=
FCIAddFile
(
hfci
,
path
,
file
,
FALSE
,
get_next_cabinet
,
progress
,
get_open_info
,
tcompTYPE_MSZIP
);
ok
(
res
,
"Expected FCIAddFile to succeed
\n
"
);
}
static
void
set_cab_parameters
(
PCCAB
pCabParams
,
const
CHAR
*
name
)
{
ZeroMemory
(
pCabParams
,
sizeof
(
CCAB
));
pCabParams
->
cb
=
MEDIA_SIZE
;
pCabParams
->
cbFolderThresh
=
FOLDER_THRESHOLD
;
pCabParams
->
setID
=
0xbeef
;
lstrcpyA
(
pCabParams
->
szCabPath
,
CURR_DIR
);
lstrcatA
(
pCabParams
->
szCabPath
,
"
\\
"
);
lstrcpyA
(
pCabParams
->
szCab
,
name
);
}
static
void
create_cab_file
(
const
CHAR
*
name
)
{
CCAB
cabParams
;
HFCI
hfci
;
ERF
erf
;
BOOL
res
;
set_cab_parameters
(
&
cabParams
,
name
);
hfci
=
FCICreate
(
&
erf
,
file_placed
,
mem_alloc
,
mem_free
,
fci_open
,
fci_read
,
fci_write
,
fci_close
,
fci_seek
,
fci_delete
,
get_temp_file
,
&
cabParams
,
NULL
);
ok
(
hfci
!=
NULL
,
"Failed to create an FCI context
\n
"
);
add_file
(
hfci
,
"four.txt"
);
add_file
(
hfci
,
"five.txt"
);
res
=
FCIFlushCabinet
(
hfci
,
FALSE
,
get_next_cabinet
,
progress
);
ok
(
res
,
"Failed to flush the cabinet
\n
"
);
res
=
FCIDestroy
(
hfci
);
ok
(
res
,
"Failed to destroy the cabinet
\n
"
);
}
static
BOOL
init_function_pointers
(
void
)
{
hCabinet
=
LoadLibraryA
(
"cabinet.dll"
);
if
(
!
hCabinet
)
return
FALSE
;
pExtract
=
(
void
*
)
GetProcAddress
(
hCabinet
,
"Extract"
);
if
(
!
pExtract
)
return
FALSE
;
return
TRUE
;
}
static
BOOL
get_program_files_dir
(
LPSTR
buf
)
{
HKEY
hkey
;
CHAR
temp
[
MAX_PATH
];
DWORD
type
=
REG_EXPAND_SZ
,
size
;
if
(
RegOpenKey
(
HKEY_LOCAL_MACHINE
,
"Software
\\
Microsoft
\\
Windows
\\
CurrentVersion"
,
&
hkey
))
return
FALSE
;
size
=
MAX_PATH
;
if
(
RegQueryValueEx
(
hkey
,
"ProgramFilesPath"
,
0
,
&
type
,
(
LPBYTE
)
temp
,
&
size
))
return
FALSE
;
ExpandEnvironmentStrings
(
temp
,
buf
,
MAX_PATH
);
RegCloseKey
(
hkey
);
return
TRUE
;
}
static
void
create_file
(
const
CHAR
*
name
)
{
HANDLE
file
;
DWORD
written
;
file
=
CreateFileA
(
name
,
GENERIC_WRITE
,
0
,
NULL
,
CREATE_ALWAYS
,
0
,
NULL
);
ok
(
file
!=
INVALID_HANDLE_VALUE
,
"Failure to open file %s
\n
"
,
name
);
WriteFile
(
file
,
name
,
strlen
(
name
),
&
written
,
NULL
);
WriteFile
(
file
,
"
\n
"
,
strlen
(
"
\n
"
),
&
written
,
NULL
);
CloseHandle
(
file
);
}
static
void
create_test_files
(
void
)
{
int
len
;
GetCurrentDirectoryA
(
MAX_PATH
,
CURR_DIR
);
len
=
lstrlenA
(
CURR_DIR
);
if
(
len
&&
(
CURR_DIR
[
len
-
1
]
==
'\\'
))
CURR_DIR
[
len
-
1
]
=
0
;
get_program_files_dir
(
PROG_FILES_DIR
);
CreateDirectoryA
(
"msitest"
,
NULL
);
create_file
(
"msitest
\\
one.txt"
);
CreateDirectoryA
(
"msitest
\\
first"
,
NULL
);
create_file
(
"msitest
\\
first
\\
two.txt"
);
CreateDirectoryA
(
"msitest
\\
second"
,
NULL
);
create_file
(
"msitest
\\
second
\\
three.txt"
);
create_file
(
"four.txt"
);
create_file
(
"five.txt"
);
create_cab_file
(
"msitest.cab"
);
DeleteFileA
(
"four.txt"
);
DeleteFileA
(
"five.txt"
);
}
static
BOOL
delete_pf
(
const
CHAR
*
rel_path
,
BOOL
is_file
)
{
CHAR
path
[
MAX_PATH
];
lstrcpyA
(
path
,
PROG_FILES_DIR
);
lstrcatA
(
path
,
"
\\
"
);
lstrcatA
(
path
,
rel_path
);
if
(
is_file
)
return
DeleteFileA
(
path
);
else
return
RemoveDirectoryA
(
path
);
}
static
void
delete_test_files
(
void
)
{
DeleteFileA
(
"msitest.msi"
);
DeleteFileA
(
"msitest.cab"
);
DeleteFileA
(
"msitest
\\
second
\\
three.txt"
);
DeleteFileA
(
"msitest
\\
first
\\
two.txt"
);
DeleteFileA
(
"msitest
\\
one.txt"
);
RemoveDirectoryA
(
"msitest
\\
second"
);
RemoveDirectoryA
(
"msitest
\\
first"
);
RemoveDirectoryA
(
"msitest"
);
}
static
void
write_file
(
const
CHAR
*
filename
,
const
char
*
data
,
int
data_size
)
{
DWORD
size
;
HANDLE
hf
=
CreateFile
(
filename
,
GENERIC_WRITE
,
0
,
NULL
,
CREATE_ALWAYS
,
FILE_ATTRIBUTE_NORMAL
,
NULL
);
WriteFile
(
hf
,
data
,
data_size
,
&
size
,
NULL
);
CloseHandle
(
hf
);
}
static
void
write_msi_summary_info
(
MSIHANDLE
db
)
{
MSIHANDLE
summary
;
UINT
r
;
r
=
MsiGetSummaryInformationA
(
db
,
NULL
,
4
,
&
summary
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %u
\n
"
,
r
);
r
=
MsiSummaryInfoSetPropertyA
(
summary
,
PID_TEMPLATE
,
VT_LPSTR
,
0
,
NULL
,
";1033"
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %u
\n
"
,
r
);
r
=
MsiSummaryInfoSetPropertyA
(
summary
,
PID_REVNUMBER
,
VT_LPSTR
,
0
,
NULL
,
"{004757CA-5092-49c2-AD20-28E1CE0DF5F2}"
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %u
\n
"
,
r
);
r
=
MsiSummaryInfoSetPropertyA
(
summary
,
PID_PAGECOUNT
,
VT_I4
,
100
,
NULL
,
NULL
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %u
\n
"
,
r
);
r
=
MsiSummaryInfoSetPropertyA
(
summary
,
PID_WORDCOUNT
,
VT_I4
,
0
,
NULL
,
NULL
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %u
\n
"
,
r
);
/* write the summary changes back to the stream */
r
=
MsiSummaryInfoPersist
(
summary
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %u
\n
"
,
r
);
MsiCloseHandle
(
summary
);
}
static
void
create_database
(
const
CHAR
*
name
,
const
msi_table
*
tables
,
int
num_tables
)
{
MSIHANDLE
db
;
UINT
r
;
int
j
;
r
=
MsiOpenDatabaseA
(
name
,
MSIDBOPEN_CREATE
,
&
db
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %u
\n
"
,
r
);
/* import the tables into the database */
for
(
j
=
0
;
j
<
num_tables
;
j
++
)
{
const
msi_table
*
table
=
&
tables
[
j
];
write_file
(
table
->
filename
,
table
->
data
,
(
table
->
size
-
1
)
*
sizeof
(
char
));
r
=
MsiDatabaseImportA
(
db
,
CURR_DIR
,
table
->
filename
);
todo_wine
{
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %u
\n
"
,
r
);
}
DeleteFileA
(
table
->
filename
);
}
write_msi_summary_info
(
db
);
r
=
MsiDatabaseCommit
(
db
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %u
\n
"
,
r
);
MsiCloseHandle
(
db
);
}
static
void
test_MsiInstallProduct
(
void
)
{
UINT
r
;
CHAR
path
[
MAX_PATH
];
LONG
res
;
HKEY
hkey
;
DWORD
num
,
size
,
type
;
r
=
MsiInstallProductA
(
msifile
,
NULL
);
todo_wine
{
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %u
\n
"
,
r
);
}
todo_wine
{
ok
(
delete_pf
(
"msitest
\\
cabout
\\
new
\\
five.txt"
,
TRUE
),
"File not installed
\n
"
);
ok
(
delete_pf
(
"msitest
\\
cabout
\\
new"
,
FALSE
),
"File not installed
\n
"
);
ok
(
delete_pf
(
"msitest
\\
cabout
\\
four.txt"
,
TRUE
),
"File not installed
\n
"
);
ok
(
delete_pf
(
"msitest
\\
cabout"
,
FALSE
),
"File not installed
\n
"
);
ok
(
delete_pf
(
"msitest
\\
changed
\\
three.txt"
,
TRUE
),
"File not installed
\n
"
);
ok
(
delete_pf
(
"msitest
\\
changed"
,
FALSE
),
"File not installed
\n
"
);
ok
(
delete_pf
(
"msitest
\\
first
\\
two.txt"
,
TRUE
),
"File not installed
\n
"
);
ok
(
delete_pf
(
"msitest
\\
first"
,
FALSE
),
"File not installed
\n
"
);
ok
(
delete_pf
(
"msitest
\\
one.txt"
,
TRUE
),
"File not installed
\n
"
);
ok
(
delete_pf
(
"msitest"
,
FALSE
),
"File not installed
\n
"
);
}
res
=
RegOpenKey
(
HKEY_LOCAL_MACHINE
,
"SOFTWARE
\\
Wine
\\
msitest"
,
&
hkey
);
todo_wine
{
ok
(
res
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %ld
\n
"
,
res
);
}
size
=
MAX_PATH
;
type
=
REG_SZ
;
res
=
RegQueryValueExA
(
hkey
,
"Name"
,
NULL
,
&
type
,
(
LPBYTE
)
path
,
&
size
);
todo_wine
{
ok
(
res
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %ld
\n
"
,
res
);
ok
(
!
lstrcmpA
(
path
,
"imaname"
),
"Expected imaname, got %s
\n
"
,
path
);
}
size
=
sizeof
(
num
);
type
=
REG_DWORD
;
res
=
RegQueryValueExA
(
hkey
,
"number"
,
NULL
,
&
type
,
(
LPBYTE
)
&
num
,
&
size
);
todo_wine
{
ok
(
res
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %ld
\n
"
,
res
);
ok
(
num
==
314
,
"Expected 314, got %ld
\n
"
,
num
);
}
RegDeleteKeyA
(
HKEY_LOCAL_MACHINE
,
"SOFTWARE
\\
Wine
\\
msitest"
);
}
START_TEST
(
install
)
{
if
(
!
init_function_pointers
())
return
;
create_test_files
();
create_database
(
msifile
,
tables
,
sizeof
(
tables
)
/
sizeof
(
msi_table
));
test_MsiInstallProduct
();
delete_test_files
();
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment