Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
wine
Manage
Activity
Members
Labels
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Container Registry
Model registry
Operate
Terraform modules
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Sam Joan Roque-Worcel
wine
Commits
53f3a831
Commit
53f3a831
authored
25 years ago
by
Alexandre Julliard
Browse files
Options
Downloads
Patches
Plain Diff
Added support to the server for loading new format (version 2) files.
parent
b3d90e4b
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
misc/registry.c
+19
-0
19 additions, 0 deletions
misc/registry.c
server/registry.c
+374
-3
374 additions, 3 deletions
server/registry.c
with
393 additions
and
3 deletions
misc/registry.c
+
19
−
0
View file @
53f3a831
...
...
@@ -593,9 +593,28 @@ static int _wine_loadsubreg( FILE *F, HKEY hkey, const char *fn )
return
0
;
}
if
(
ver
!=
REGISTRY_SAVE_VERSION
)
{
if
(
ver
==
2
)
/* new version */
{
HANDLE
file
;
if
((
file
=
FILE_CreateFile
(
fn
,
GENERIC_READ
,
0
,
NULL
,
OPEN_EXISTING
,
FILE_ATTRIBUTE_NORMAL
,
-
1
))
!=
INVALID_HANDLE_VALUE
)
{
struct
load_registry_request
*
req
=
get_req_buffer
();
req
->
hkey
=
hkey
;
req
->
file
=
file
;
req
->
name
[
0
]
=
0
;
server_call
(
REQ_LOAD_REGISTRY
);
CloseHandle
(
file
);
}
free
(
buf
);
return
1
;
}
else
{
TRACE_
(
reg
)(
"Old format (%d) registry found, ignoring it. (buf was %s).
\n
"
,
ver
,
buf
);
free
(
buf
);
return
0
;
}
}
if
(
!
_wine_read_line
(
F
,
&
buf
,
&
buflen
))
{
free
(
buf
);
...
...
This diff is collapsed.
Click to expand it.
server/registry.c
+
374
−
3
View file @
53f3a831
...
...
@@ -89,6 +89,18 @@ static int saving_level;
static
int
saving_version
=
1
;
/* file format version */
/* information about a file being loaded */
struct
file_load_info
{
FILE
*
file
;
/* input file */
char
*
buffer
;
/* line buffer */
int
len
;
/* buffer length */
int
line
;
/* current input line */
char
*
tmp
;
/* temp buffer to use while parsing input */
int
tmplen
;
/* length of temp buffer */
};
static
void
key_dump
(
struct
object
*
obj
,
int
verbose
);
static
void
key_destroy
(
struct
object
*
obj
);
...
...
@@ -292,7 +304,11 @@ static void key_destroy( struct object *obj )
free
(
key
->
values
[
i
].
name
);
if
(
key
->
values
[
i
].
data
)
free
(
key
->
values
[
i
].
data
);
}
for
(
i
=
0
;
i
<=
key
->
last_subkey
;
i
++
)
release_object
(
key
->
subkeys
[
i
]
);
for
(
i
=
0
;
i
<=
key
->
last_subkey
;
i
++
)
{
key
->
subkeys
[
i
]
->
parent
=
NULL
;
release_object
(
key
->
subkeys
[
i
]
);
}
}
/* duplicate a key path from the request buffer */
...
...
@@ -870,7 +886,7 @@ void close_registry(void)
int
i
;
for
(
i
=
0
;
i
<
NB_ROOT_KEYS
;
i
++
)
{
if
(
root_keys
[
i
]
&&
!
root_keys
[
i
]
->
parent
)
release_object
(
root_keys
[
i
]
);
if
(
root_keys
[
i
])
release_object
(
root_keys
[
i
]
);
}
}
...
...
@@ -889,6 +905,360 @@ static struct key *get_hkey_obj( int hkey, unsigned int access )
return
key
;
}
/* read a line from the input file */
static
int
read_next_line
(
struct
file_load_info
*
info
)
{
char
*
newbuf
;
int
newlen
,
pos
=
0
;
info
->
line
++
;
for
(;;)
{
if
(
!
fgets
(
info
->
buffer
+
pos
,
info
->
len
-
pos
,
info
->
file
))
return
(
pos
!=
0
);
/* EOF */
pos
=
strlen
(
info
->
buffer
);
if
(
info
->
buffer
[
pos
-
1
]
==
'\n'
)
{
/* got a full line */
info
->
buffer
[
--
pos
]
=
0
;
if
(
pos
>
0
&&
info
->
buffer
[
pos
-
1
]
==
'\r'
)
info
->
buffer
[
pos
-
1
]
=
0
;
return
1
;
}
if
(
pos
<
info
->
len
-
1
)
return
1
;
/* EOF but something was read */
/* need to enlarge the buffer */
newlen
=
info
->
len
+
info
->
len
/
2
;
if
(
!
(
newbuf
=
realloc
(
info
->
buffer
,
newlen
)))
{
set_error
(
ERROR_OUTOFMEMORY
);
return
-
1
;
}
info
->
buffer
=
newbuf
;
info
->
len
=
newlen
;
}
}
/* make sure the temp buffer holds enough space */
static
int
get_file_tmp_space
(
struct
file_load_info
*
info
,
int
size
)
{
char
*
tmp
;
if
(
info
->
tmplen
>=
size
)
return
1
;
if
(
!
(
tmp
=
realloc
(
info
->
tmp
,
size
)))
{
set_error
(
ERROR_OUTOFMEMORY
);
return
0
;
}
info
->
tmp
=
tmp
;
info
->
tmplen
=
size
;
return
1
;
}
/* report an error while loading an input file */
static
void
file_read_error
(
const
char
*
err
,
struct
file_load_info
*
info
)
{
fprintf
(
stderr
,
"Line %d: %s '%s'
\n
"
,
info
->
line
,
err
,
info
->
buffer
);
}
/* parse an escaped string back into Unicode */
/* return the number of chars read from the input, or -1 on output overflow */
static
int
parse_strW
(
WCHAR
*
dest
,
int
*
len
,
const
char
*
src
,
char
endchar
)
{
int
count
=
sizeof
(
WCHAR
);
/* for terminating null */
const
char
*
p
=
src
;
while
(
*
p
&&
*
p
!=
endchar
)
{
if
(
*
p
!=
'\\'
)
*
dest
=
(
WCHAR
)
*
p
++
;
else
{
p
++
;
switch
(
*
p
)
{
case
'a'
:
*
dest
=
'\a'
;
p
++
;
break
;
case
'b'
:
*
dest
=
'\b'
;
p
++
;
break
;
case
'e'
:
*
dest
=
'\e'
;
p
++
;
break
;
case
'f'
:
*
dest
=
'\f'
;
p
++
;
break
;
case
'n'
:
*
dest
=
'\n'
;
p
++
;
break
;
case
'r'
:
*
dest
=
'\r'
;
p
++
;
break
;
case
't'
:
*
dest
=
'\t'
;
p
++
;
break
;
case
'v'
:
*
dest
=
'\v'
;
p
++
;
break
;
case
'x'
:
/* hex escape */
p
++
;
if
(
!
isxdigit
(
*
p
))
*
dest
=
'x'
;
else
{
*
dest
=
to_hex
(
*
p
++
);
if
(
isxdigit
(
*
p
))
*
dest
=
(
*
dest
*
16
)
+
to_hex
(
*
p
++
);
if
(
isxdigit
(
*
p
))
*
dest
=
(
*
dest
*
16
)
+
to_hex
(
*
p
++
);
if
(
isxdigit
(
*
p
))
*
dest
=
(
*
dest
*
16
)
+
to_hex
(
*
p
++
);
}
break
;
case
'0'
:
case
'1'
:
case
'2'
:
case
'3'
:
case
'4'
:
case
'5'
:
case
'6'
:
case
'7'
:
/* octal escape */
*
dest
=
*
p
++
-
'0'
;
if
(
*
p
>=
'0'
&&
*
p
<=
'7'
)
*
dest
=
(
*
dest
*
8
)
+
(
*
p
++
-
'0'
);
if
(
*
p
>=
'0'
&&
*
p
<=
'7'
)
*
dest
=
(
*
dest
*
8
)
+
(
*
p
++
-
'0'
);
break
;
default:
*
dest
=
(
WCHAR
)
*
p
++
;
break
;
}
}
if
((
count
+=
sizeof
(
WCHAR
))
>
*
len
)
return
-
1
;
/* dest buffer overflow */
dest
++
;
}
*
dest
=
0
;
if
(
!*
p
)
return
-
1
;
/* delimiter not found */
*
len
=
count
;
return
p
+
1
-
src
;
}
/* convert a data type tag to a value type */
static
int
get_data_type
(
const
char
*
buffer
,
int
*
type
,
int
*
parse_type
)
{
struct
data_type
{
const
char
*
tag
;
int
len
;
int
type
;
int
parse_type
;
};
static
const
struct
data_type
data_types
[]
=
{
/* actual type */
/* type to assume for parsing */
{
"
\"
"
,
1
,
REG_SZ
,
REG_SZ
},
{
"str:
\"
"
,
5
,
REG_SZ
,
REG_SZ
},
{
"str(2):
\"
"
,
8
,
REG_EXPAND_SZ
,
REG_SZ
},
{
"str(7):
\"
"
,
8
,
REG_MULTI_SZ
,
REG_SZ
},
{
"hex:"
,
4
,
REG_BINARY
,
REG_BINARY
},
{
"dword:"
,
6
,
REG_DWORD
,
REG_DWORD
},
{
"hex("
,
4
,
-
1
,
REG_BINARY
},
{
NULL
,
}
};
const
struct
data_type
*
ptr
;
char
*
end
;
for
(
ptr
=
data_types
;
ptr
->
tag
;
ptr
++
)
{
if
(
memcmp
(
ptr
->
tag
,
buffer
,
ptr
->
len
))
continue
;
*
parse_type
=
ptr
->
parse_type
;
if
((
*
type
=
ptr
->
type
)
!=
-
1
)
return
ptr
->
len
;
/* "hex(xx):" is special */
*
type
=
(
int
)
strtoul
(
buffer
+
4
,
&
end
,
16
);
if
((
end
<=
buffer
)
||
memcmp
(
end
,
"):"
,
2
))
return
0
;
return
end
+
2
-
buffer
;
}
return
0
;
}
/* load and create a key from the input file */
static
struct
key
*
load_key
(
struct
key
*
base
,
const
char
*
buffer
,
struct
file_load_info
*
info
)
{
WCHAR
*
p
;
int
res
,
len
,
modif
;
len
=
strlen
(
buffer
)
*
sizeof
(
WCHAR
);
if
(
!
get_file_tmp_space
(
info
,
len
))
return
NULL
;
if
((
res
=
parse_strW
(
(
WCHAR
*
)
info
->
tmp
,
&
len
,
buffer
,
']'
))
==
-
1
)
{
file_read_error
(
"Malformed key"
,
info
);
return
NULL
;
}
if
(
!
sscanf
(
buffer
+
res
,
" %d"
,
&
modif
))
modif
=
time
(
NULL
);
for
(
p
=
(
WCHAR
*
)
info
->
tmp
;
*
p
;
p
++
)
if
(
*
p
==
'\\'
)
{
p
++
;
break
;
}
return
create_key
(
base
,
p
,
len
-
((
char
*
)
p
-
info
->
tmp
),
NULL
,
0
,
modif
,
&
res
);
}
/* parse a comma-separated list of hex digits */
static
int
parse_hex
(
unsigned
char
*
dest
,
int
*
len
,
const
char
*
buffer
)
{
const
char
*
p
=
buffer
;
int
count
=
0
;
while
(
isxdigit
(
*
p
))
{
int
val
;
char
buf
[
3
];
memcpy
(
buf
,
p
,
2
);
buf
[
2
]
=
0
;
sscanf
(
buf
,
"%x"
,
&
val
);
if
(
count
++
>=
*
len
)
return
-
1
;
/* dest buffer overflow */
*
dest
++
=
(
unsigned
char
)
val
;
p
+=
2
;
if
(
*
p
==
','
)
p
++
;
}
*
len
=
count
;
return
p
-
buffer
;
}
/* parse a value name and create the corresponding value */
static
struct
key_value
*
parse_value_name
(
struct
key
*
key
,
const
char
*
buffer
,
int
*
len
,
struct
file_load_info
*
info
)
{
int
maxlen
=
strlen
(
buffer
)
*
sizeof
(
WCHAR
);
if
(
!
get_file_tmp_space
(
info
,
maxlen
))
return
NULL
;
if
(
buffer
[
0
]
==
'@'
)
{
info
->
tmp
[
0
]
=
info
->
tmp
[
1
]
=
0
;
*
len
=
1
;
}
else
{
if
((
*
len
=
parse_strW
(
(
WCHAR
*
)
info
->
tmp
,
&
maxlen
,
buffer
+
1
,
'\"'
))
==
-
1
)
goto
error
;
(
*
len
)
++
;
/* for initial quote */
}
if
(
buffer
[
*
len
]
!=
'='
)
goto
error
;
(
*
len
)
++
;
return
insert_value
(
key
,
(
WCHAR
*
)
info
->
tmp
);
error:
file_read_error
(
"Malformed value name"
,
info
);
return
NULL
;
}
/* load a value from the input file */
static
int
load_value
(
struct
key
*
key
,
const
char
*
buffer
,
struct
file_load_info
*
info
)
{
DWORD
dw
;
void
*
ptr
,
*
newptr
;
int
maxlen
,
len
,
res
;
int
type
,
parse_type
;
struct
key_value
*
value
;
if
(
!
(
value
=
parse_value_name
(
key
,
buffer
,
&
len
,
info
)))
return
0
;
if
(
!
(
res
=
get_data_type
(
buffer
+
len
,
&
type
,
&
parse_type
)))
goto
error
;
buffer
+=
len
+
res
;
switch
(
parse_type
)
{
case
REG_SZ
:
len
=
strlen
(
buffer
)
*
sizeof
(
WCHAR
);
if
(
!
get_file_tmp_space
(
info
,
len
))
return
0
;
if
((
res
=
parse_strW
(
(
WCHAR
*
)
info
->
tmp
,
&
len
,
buffer
,
'\"'
))
==
-
1
)
goto
error
;
ptr
=
info
->
tmp
;
break
;
case
REG_DWORD
:
dw
=
strtoul
(
buffer
,
NULL
,
16
);
ptr
=
&
dw
;
len
=
sizeof
(
dw
);
break
;
case
REG_BINARY
:
/* hex digits */
len
=
0
;
for
(;;)
{
maxlen
=
1
+
strlen
(
buffer
)
/
3
;
/* 3 chars for one hex byte */
if
(
!
get_file_tmp_space
(
info
,
len
+
maxlen
))
return
0
;
if
((
res
=
parse_hex
(
info
->
tmp
+
len
,
&
maxlen
,
buffer
))
==
-
1
)
goto
error
;
len
+=
maxlen
;
buffer
+=
res
;
while
(
isspace
(
*
buffer
))
buffer
++
;
if
(
!*
buffer
)
break
;
if
(
*
buffer
!=
'\\'
)
goto
error
;
if
(
read_next_line
(
info
)
!=
1
)
goto
error
;
buffer
=
info
->
buffer
;
while
(
isspace
(
*
buffer
))
buffer
++
;
}
ptr
=
info
->
tmp
;
break
;
default:
assert
(
0
);
ptr
=
NULL
;
/* keep compiler quiet */
break
;
}
if
(
!
len
)
newptr
=
NULL
;
else
if
(
!
(
newptr
=
memdup
(
ptr
,
len
)))
return
0
;
if
(
value
->
data
)
free
(
value
->
data
);
value
->
data
=
newptr
;
value
->
len
=
len
;
value
->
type
=
type
;
/* update the key level but not the modification time */
key
->
level
=
MAX
(
key
->
level
,
current_level
);
return
1
;
error:
file_read_error
(
"Malformed value"
,
info
);
return
0
;
}
/* load all the keys from the input file */
static
void
load_keys
(
struct
key
*
key
,
FILE
*
f
)
{
struct
key
*
subkey
=
NULL
;
struct
file_load_info
info
;
char
*
p
;
info
.
file
=
f
;
info
.
len
=
4
;
info
.
tmplen
=
4
;
info
.
line
=
0
;
if
(
!
(
info
.
buffer
=
mem_alloc
(
info
.
len
)))
return
;
if
(
!
(
info
.
tmp
=
mem_alloc
(
info
.
tmplen
)))
{
free
(
info
.
buffer
);
return
;
}
if
((
read_next_line
(
&
info
)
!=
1
)
||
strcmp
(
info
.
buffer
,
"WINE REGISTRY Version 2"
))
{
set_error
(
ERROR_NOT_REGISTRY_FILE
);
goto
done
;
}
while
(
read_next_line
(
&
info
)
==
1
)
{
for
(
p
=
info
.
buffer
;
*
p
&&
isspace
(
*
p
);
p
++
);
switch
(
*
p
)
{
case
'['
:
/* new key */
if
(
subkey
)
release_object
(
subkey
);
subkey
=
load_key
(
key
,
p
+
1
,
&
info
);
break
;
case
'@'
:
/* default value */
case
'\"'
:
/* value */
if
(
subkey
)
load_value
(
subkey
,
p
,
&
info
);
else
file_read_error
(
"Value without key"
,
&
info
);
break
;
case
'#'
:
/* comment */
case
';'
:
/* comment */
case
0
:
/* empty line */
break
;
default:
file_read_error
(
"Unrecognized input"
,
&
info
);
break
;
}
}
done:
if
(
subkey
)
release_object
(
subkey
);
free
(
info
.
buffer
);
free
(
info
.
tmp
);
}
/* load a part of the registry from a file */
static
void
load_registry
(
struct
key
*
key
,
int
handle
)
{
struct
object
*
obj
;
int
fd
;
if
(
!
(
obj
=
get_handle_obj
(
current
->
process
,
handle
,
GENERIC_READ
,
NULL
)))
return
;
fd
=
obj
->
ops
->
get_read_fd
(
obj
);
release_object
(
obj
);
if
(
fd
!=
-
1
)
{
FILE
*
f
=
fdopen
(
fd
,
"r"
);
if
(
f
)
{
load_keys
(
key
,
f
);
fclose
(
f
);
}
else
file_set_error
();
}
}
/* update the level of the parents of a key (only needed for the old format) */
static
int
update_level
(
struct
key
*
key
)
{
...
...
@@ -1139,7 +1509,8 @@ DECL_HANDLER(load_registry)
if
((
key
=
get_hkey_obj
(
req
->
hkey
,
KEY_SET_VALUE
|
KEY_CREATE_SUB_KEY
)))
{
set_error
(
ERROR_CALL_NOT_IMPLEMENTED
);
/* FIXME: use subkey name */
load_registry
(
key
,
req
->
file
);
release_object
(
key
);
}
}
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment