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
e8a7246e
Commit
e8a7246e
authored
Aug 25, 2011
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
setupapi: Add support for creating WinSxS manifest files from fake dll resources.
parent
0decc777
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
281 additions
and
1 deletion
+281
-1
fakedll.c
dlls/setupapi/fakedll.c
+281
-1
No files found.
dlls/setupapi/fakedll.c
View file @
e8a7246e
/*
* Creation of Wine fake dlls for apps that access the dll file directly.
*
* Copyright 2006 Alexandre Julliard
* Copyright 2006
, 2011
Alexandre Julliard
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
...
...
@@ -470,6 +470,278 @@ static HANDLE create_dest_file( const WCHAR *name )
return
h
;
}
/* XML parsing code copied from ntdll */
typedef
struct
{
const
char
*
ptr
;
unsigned
int
len
;
}
xmlstr_t
;
typedef
struct
{
const
char
*
ptr
;
const
char
*
end
;
}
xmlbuf_t
;
static
inline
BOOL
xmlstr_cmp
(
const
xmlstr_t
*
xmlstr
,
const
char
*
str
)
{
return
!
strncmp
(
xmlstr
->
ptr
,
str
,
xmlstr
->
len
)
&&
!
str
[
xmlstr
->
len
];
}
static
inline
BOOL
isxmlspace
(
char
ch
)
{
return
(
ch
==
' '
||
ch
==
'\r'
||
ch
==
'\n'
||
ch
==
'\t'
);
}
static
BOOL
next_xml_elem
(
xmlbuf_t
*
xmlbuf
,
xmlstr_t
*
elem
)
{
const
char
*
ptr
;
for
(;;)
{
ptr
=
memchr
(
xmlbuf
->
ptr
,
'<'
,
xmlbuf
->
end
-
xmlbuf
->
ptr
);
if
(
!
ptr
)
{
xmlbuf
->
ptr
=
xmlbuf
->
end
;
return
FALSE
;
}
ptr
++
;
if
(
ptr
+
3
<
xmlbuf
->
end
&&
ptr
[
0
]
==
'!'
&&
ptr
[
1
]
==
'-'
&&
ptr
[
2
]
==
'-'
)
/* skip comment */
{
for
(
ptr
+=
3
;
ptr
+
3
<=
xmlbuf
->
end
;
ptr
++
)
if
(
ptr
[
0
]
==
'-'
&&
ptr
[
1
]
==
'-'
&&
ptr
[
2
]
==
'>'
)
break
;
if
(
ptr
+
3
>
xmlbuf
->
end
)
{
xmlbuf
->
ptr
=
xmlbuf
->
end
;
return
FALSE
;
}
xmlbuf
->
ptr
=
ptr
+
3
;
}
else
break
;
}
xmlbuf
->
ptr
=
ptr
;
while
(
ptr
<
xmlbuf
->
end
&&
!
isxmlspace
(
*
ptr
)
&&
*
ptr
!=
'>'
&&
(
*
ptr
!=
'/'
||
ptr
==
xmlbuf
->
ptr
))
ptr
++
;
elem
->
ptr
=
xmlbuf
->
ptr
;
elem
->
len
=
ptr
-
xmlbuf
->
ptr
;
xmlbuf
->
ptr
=
ptr
;
return
xmlbuf
->
ptr
!=
xmlbuf
->
end
;
}
static
BOOL
next_xml_attr
(
xmlbuf_t
*
xmlbuf
,
xmlstr_t
*
name
,
xmlstr_t
*
value
,
BOOL
*
error
,
BOOL
*
end
)
{
const
char
*
ptr
;
*
error
=
TRUE
;
while
(
xmlbuf
->
ptr
<
xmlbuf
->
end
&&
isxmlspace
(
*
xmlbuf
->
ptr
))
xmlbuf
->
ptr
++
;
if
(
xmlbuf
->
ptr
==
xmlbuf
->
end
)
return
FALSE
;
if
(
*
xmlbuf
->
ptr
==
'/'
)
{
xmlbuf
->
ptr
++
;
if
(
xmlbuf
->
ptr
==
xmlbuf
->
end
||
*
xmlbuf
->
ptr
!=
'>'
)
return
FALSE
;
xmlbuf
->
ptr
++
;
*
end
=
TRUE
;
*
error
=
FALSE
;
return
FALSE
;
}
if
(
*
xmlbuf
->
ptr
==
'>'
)
{
xmlbuf
->
ptr
++
;
*
error
=
FALSE
;
return
FALSE
;
}
ptr
=
xmlbuf
->
ptr
;
while
(
ptr
<
xmlbuf
->
end
&&
*
ptr
!=
'='
&&
*
ptr
!=
'>'
&&
!
isxmlspace
(
*
ptr
))
ptr
++
;
if
(
ptr
==
xmlbuf
->
end
||
*
ptr
!=
'='
)
return
FALSE
;
name
->
ptr
=
xmlbuf
->
ptr
;
name
->
len
=
ptr
-
xmlbuf
->
ptr
;
xmlbuf
->
ptr
=
ptr
;
ptr
++
;
if
(
ptr
==
xmlbuf
->
end
||
(
*
ptr
!=
'"'
&&
*
ptr
!=
'\''
))
return
FALSE
;
value
->
ptr
=
++
ptr
;
if
(
ptr
==
xmlbuf
->
end
)
return
FALSE
;
ptr
=
memchr
(
ptr
,
ptr
[
-
1
],
xmlbuf
->
end
-
ptr
);
if
(
!
ptr
)
{
xmlbuf
->
ptr
=
xmlbuf
->
end
;
return
FALSE
;
}
value
->
len
=
ptr
-
value
->
ptr
;
xmlbuf
->
ptr
=
ptr
+
1
;
if
(
xmlbuf
->
ptr
==
xmlbuf
->
end
)
return
FALSE
;
*
error
=
FALSE
;
return
TRUE
;
}
static
void
get_manifest_filename
(
const
xmlstr_t
*
arch
,
const
xmlstr_t
*
name
,
const
xmlstr_t
*
key
,
const
xmlstr_t
*
version
,
WCHAR
*
buffer
,
DWORD
size
)
{
static
const
WCHAR
trailerW
[]
=
{
'_'
,
'n'
,
'o'
,
'n'
,
'e'
,
'_'
,
'd'
,
'e'
,
'a'
,
'd'
,
'b'
,
'e'
,
'e'
,
'f'
,
0
};
DWORD
pos
;
pos
=
MultiByteToWideChar
(
CP_UTF8
,
0
,
arch
->
ptr
,
arch
->
len
,
buffer
,
size
);
buffer
[
pos
++
]
=
'_'
;
pos
+=
MultiByteToWideChar
(
CP_UTF8
,
0
,
name
->
ptr
,
name
->
len
,
buffer
+
pos
,
size
-
pos
);
buffer
[
pos
++
]
=
'_'
;
pos
+=
MultiByteToWideChar
(
CP_UTF8
,
0
,
key
->
ptr
,
key
->
len
,
buffer
+
pos
,
size
-
pos
);
buffer
[
pos
++
]
=
'_'
;
pos
+=
MultiByteToWideChar
(
CP_UTF8
,
0
,
version
->
ptr
,
version
->
len
,
buffer
+
pos
,
size
-
pos
);
memcpy
(
buffer
+
pos
,
trailerW
,
sizeof
(
trailerW
)
);
strlwrW
(
buffer
);
}
static
BOOL
create_winsxs_dll
(
const
WCHAR
*
dll_name
,
const
xmlstr_t
*
arch
,
const
xmlstr_t
*
name
,
const
xmlstr_t
*
key
,
const
xmlstr_t
*
version
,
const
void
*
dll_data
,
size_t
dll_size
)
{
static
const
WCHAR
winsxsW
[]
=
{
'w'
,
'i'
,
'n'
,
's'
,
'x'
,
's'
,
'\\'
};
WCHAR
*
path
;
const
WCHAR
*
filename
;
DWORD
pos
,
written
,
path_len
;
HANDLE
handle
;
BOOL
ret
=
FALSE
;
if
(
!
(
filename
=
strrchrW
(
dll_name
,
'\\'
)))
filename
=
dll_name
;
else
filename
++
;
path_len
=
GetWindowsDirectoryW
(
NULL
,
0
)
+
1
+
sizeof
(
winsxsW
)
/
sizeof
(
WCHAR
)
+
arch
->
len
+
name
->
len
+
key
->
len
+
version
->
len
+
18
+
strlenW
(
filename
)
+
1
;
path
=
HeapAlloc
(
GetProcessHeap
(),
0
,
path_len
*
sizeof
(
WCHAR
)
);
pos
=
GetWindowsDirectoryW
(
path
,
path_len
);
path
[
pos
++
]
=
'\\'
;
memcpy
(
path
+
pos
,
winsxsW
,
sizeof
(
winsxsW
)
);
pos
+=
sizeof
(
winsxsW
)
/
sizeof
(
WCHAR
);
get_manifest_filename
(
arch
,
name
,
key
,
version
,
path
+
pos
,
path_len
-
pos
);
pos
+=
strlenW
(
path
+
pos
);
path
[
pos
++
]
=
'\\'
;
strcpyW
(
path
+
pos
,
filename
);
handle
=
create_dest_file
(
path
);
if
(
handle
&&
handle
!=
INVALID_HANDLE_VALUE
)
{
TRACE
(
"creating %s
\n
"
,
debugstr_w
(
path
)
);
ret
=
(
WriteFile
(
handle
,
dll_data
,
dll_size
,
&
written
,
NULL
)
&&
written
==
dll_size
);
if
(
!
ret
)
ERR
(
"failed to write to %s (error=%u)
\n
"
,
debugstr_w
(
path
),
GetLastError
()
);
CloseHandle
(
handle
);
if
(
!
ret
)
DeleteFileW
(
path
);
}
HeapFree
(
GetProcessHeap
(),
0
,
path
);
return
ret
;
}
static
BOOL
create_manifest
(
const
xmlstr_t
*
arch
,
const
xmlstr_t
*
name
,
const
xmlstr_t
*
key
,
const
xmlstr_t
*
version
,
const
void
*
data
,
DWORD
len
)
{
static
const
WCHAR
winsxsW
[]
=
{
'w'
,
'i'
,
'n'
,
's'
,
'x'
,
's'
,
'\\'
,
'm'
,
'a'
,
'n'
,
'i'
,
'f'
,
'e'
,
's'
,
't'
,
's'
,
'\\'
};
static
const
WCHAR
extensionW
[]
=
{
'.'
,
'm'
,
'a'
,
'n'
,
'i'
,
'f'
,
'e'
,
's'
,
't'
,
0
};
WCHAR
*
path
;
DWORD
pos
,
written
,
path_len
;
HANDLE
handle
;
BOOL
ret
=
FALSE
;
path_len
=
GetWindowsDirectoryW
(
NULL
,
0
)
+
1
+
sizeof
(
winsxsW
)
/
sizeof
(
WCHAR
)
+
arch
->
len
+
name
->
len
+
key
->
len
+
version
->
len
+
18
+
sizeof
(
extensionW
)
/
sizeof
(
WCHAR
);
path
=
HeapAlloc
(
GetProcessHeap
(),
0
,
path_len
*
sizeof
(
WCHAR
)
);
pos
=
GetWindowsDirectoryW
(
path
,
MAX_PATH
);
path
[
pos
++
]
=
'\\'
;
memcpy
(
path
+
pos
,
winsxsW
,
sizeof
(
winsxsW
)
);
pos
+=
sizeof
(
winsxsW
)
/
sizeof
(
WCHAR
);
get_manifest_filename
(
arch
,
name
,
key
,
version
,
path
+
pos
,
MAX_PATH
-
pos
);
strcatW
(
path
+
pos
,
extensionW
);
handle
=
CreateFileW
(
path
,
GENERIC_WRITE
,
0
,
NULL
,
CREATE_ALWAYS
,
0
,
NULL
);
if
(
handle
==
INVALID_HANDLE_VALUE
&&
GetLastError
()
==
ERROR_PATH_NOT_FOUND
)
{
create_directories
(
path
);
handle
=
CreateFileW
(
path
,
GENERIC_WRITE
,
0
,
NULL
,
CREATE_ALWAYS
,
0
,
NULL
);
}
if
(
handle
!=
INVALID_HANDLE_VALUE
)
{
TRACE
(
"creating %s
\n
"
,
debugstr_w
(
path
)
);
ret
=
(
WriteFile
(
handle
,
data
,
len
,
&
written
,
NULL
)
&&
written
==
len
);
if
(
!
ret
)
ERR
(
"failed to write to %s (error=%u)
\n
"
,
debugstr_w
(
path
),
GetLastError
()
);
CloseHandle
(
handle
);
if
(
!
ret
)
DeleteFileW
(
path
);
}
HeapFree
(
GetProcessHeap
(),
0
,
path
);
return
ret
;
}
static
void
register_manifest
(
const
WCHAR
*
dll_name
,
const
char
*
manifest
,
DWORD
len
,
const
void
*
dll_data
,
size_t
dll_size
)
{
#ifdef __i386__
static
const
char
current_arch
[]
=
"x86"
;
#elif defined __x86_64__
static
const
char
current_arch
[]
=
"amd64"
;
#else
static
const
char
current_arch
[]
=
"none"
;
#endif
xmlbuf_t
buffer
;
xmlstr_t
elem
,
attr_name
,
attr_value
;
xmlstr_t
name
,
version
,
arch
,
key
;
BOOL
end
=
FALSE
,
error
;
buffer
.
ptr
=
manifest
;
buffer
.
end
=
manifest
+
len
;
name
.
ptr
=
version
.
ptr
=
arch
.
ptr
=
key
.
ptr
=
NULL
;
name
.
len
=
version
.
len
=
arch
.
len
=
key
.
len
=
0
;
while
(
next_xml_elem
(
&
buffer
,
&
elem
))
{
if
(
!
xmlstr_cmp
(
&
elem
,
"assemblyIdentity"
))
continue
;
while
(
next_xml_attr
(
&
buffer
,
&
attr_name
,
&
attr_value
,
&
error
,
&
end
))
{
if
(
xmlstr_cmp
(
&
attr_name
,
"name"
))
name
=
attr_value
;
else
if
(
xmlstr_cmp
(
&
attr_name
,
"version"
))
version
=
attr_value
;
else
if
(
xmlstr_cmp
(
&
attr_name
,
"processorArchitecture"
))
arch
=
attr_value
;
else
if
(
xmlstr_cmp
(
&
attr_name
,
"publicKeyToken"
))
key
=
attr_value
;
}
if
(
!
error
&&
name
.
ptr
&&
version
.
ptr
&&
arch
.
ptr
&&
key
.
ptr
)
{
if
(
!
arch
.
len
)
/* fixup the architecture */
{
char
*
new_buffer
=
HeapAlloc
(
GetProcessHeap
(),
0
,
len
+
sizeof
(
current_arch
)
);
memcpy
(
new_buffer
,
manifest
,
arch
.
ptr
-
manifest
);
strcpy
(
new_buffer
+
(
arch
.
ptr
-
manifest
),
current_arch
);
memcpy
(
new_buffer
+
strlen
(
new_buffer
),
arch
.
ptr
,
len
-
(
arch
.
ptr
-
manifest
)
);
arch
.
ptr
=
current_arch
;
arch
.
len
=
strlen
(
current_arch
);
if
(
create_winsxs_dll
(
dll_name
,
&
arch
,
&
name
,
&
key
,
&
version
,
dll_data
,
dll_size
))
create_manifest
(
&
arch
,
&
name
,
&
key
,
&
version
,
new_buffer
,
len
+
arch
.
len
);
HeapFree
(
GetProcessHeap
(),
0
,
new_buffer
);
}
else
{
if
(
create_winsxs_dll
(
dll_name
,
&
arch
,
&
name
,
&
key
,
&
version
,
dll_data
,
dll_size
))
create_manifest
(
&
arch
,
&
name
,
&
key
,
&
version
,
manifest
,
len
);
}
}
}
}
static
BOOL
CALLBACK
register_resource
(
HMODULE
module
,
LPCWSTR
type
,
LPWSTR
name
,
LONG_PTR
arg
)
{
HRESULT
*
hr
=
(
HRESULT
*
)
arg
;
...
...
@@ -493,10 +765,18 @@ static void register_fake_dll( const WCHAR *name, const void *data, size_t size
static
const
WCHAR
atlW
[]
=
{
'a'
,
't'
,
'l'
,
'.'
,
'd'
,
'l'
,
'l'
,
0
};
static
const
WCHAR
moduleW
[]
=
{
'M'
,
'O'
,
'D'
,
'U'
,
'L'
,
'E'
,
0
};
static
const
WCHAR
regtypeW
[]
=
{
'W'
,
'I'
,
'N'
,
'E'
,
'_'
,
'R'
,
'E'
,
'G'
,
'I'
,
'S'
,
'T'
,
'R'
,
'Y'
,
0
};
static
const
WCHAR
manifestW
[]
=
{
'W'
,
'I'
,
'N'
,
'E'
,
'_'
,
'M'
,
'A'
,
'N'
,
'I'
,
'F'
,
'E'
,
'S'
,
'T'
,
0
};
const
IMAGE_RESOURCE_DIRECTORY
*
resdir
;
LDR_RESOURCE_INFO
info
;
HRESULT
hr
=
S_OK
;
HMODULE
module
=
(
HMODULE
)((
ULONG_PTR
)
data
|
1
);
HRSRC
rsrc
;
if
((
rsrc
=
FindResourceW
(
module
,
manifestW
,
MAKEINTRESOURCEW
(
RT_MANIFEST
)
)))
{
char
*
manifest
=
LoadResource
(
module
,
rsrc
);
register_manifest
(
name
,
manifest
,
SizeofResource
(
module
,
rsrc
),
data
,
size
);
}
info
.
Type
=
(
ULONG_PTR
)
regtypeW
;
if
(
LdrFindResourceDirectory_U
(
module
,
&
info
,
1
,
&
resdir
))
return
;
...
...
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