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
9e6b1d14
Commit
9e6b1d14
authored
Dec 11, 1999
by
Juergen Schmied
Committed by
Alexandre Julliard
Dec 11, 1999
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added loader for NT registry files.
parent
044db464
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
423 additions
and
3 deletions
+423
-3
wine.conf.man.in
documentation/wine.conf.man.in
+59
-0
registry.c
misc/registry.c
+356
-1
wine.ini
wine.ini
+8
-2
No files found.
documentation/wine.conf.man.in
View file @
9e6b1d14
...
@@ -253,6 +253,65 @@ default: none
...
@@ -253,6 +253,65 @@ default: none
default: Win31
default: Win31
.br
.br
Use Win95-like window displays or Win3.1-like window displays.
Use Win95-like window displays or Win3.1-like window displays.
.PP
.B [Registry]
.br
.I format: AltCurrentUserFile=<filename>
.br
alternate registry file name: HKEY_CURRENT_USER
.PP
.I format: AltUserFile=<filename>
.br
alternate registry file name: HKKEY_USERS
.PP
.I format: AltLocalMachineFile=<filename>
.br
alternate registry file name: HKEY_LOCAL_MASCHINE
.PP
.I format: LoadAltRegistryFiles=<boolean>
.br
Load above registries.
.PP
.I format: WritetoAltRegistryFiles=<boolean>
.br
TRY to write all changes to alt registries
.PP
.I format: LoadGlobalRegistryFiles=<boolean>
.br
Global registries (stored in /etc)
.PP
.I format: LoadHomeRegistryFiles=<boolean>
.br
Home registries (stored in ~user/.wine/)
.PP
.I format: WritetoHomeRegistryFiles=<boolean>
.br
TRY to write all changes to alt registries
.PP
.I format: LoadWin311RegistryFiles=<boolean>
.br
Windows 3.1 registry files stored in windows directory
.PP
.I format: LoadWin95RegistryFiles=<boolean>
.br
Windows 95 registry files stored in windows directory and c:
.PP
.I format: LoadWinNTRegistryFiles=<boolean>
.br
Windows NT registry files stored in <windows directory>/system32/config and <windows directory>/<profiles>/user.dat. (not yet completely implemented)
.PP
.I format: NTUser=<username>
.br
Needed for building path to the user registry file: <windows directory>/profiles/<username>/ntuser.dat
.PP
To avoid interferences between all registrys you should only activate the win311, win95 or the winnt registry.
.PP
booleans: Y/y/T/t/1 are true, N/n/F/f/0 are false.
.br
Defaults are read all, write to Home and Alt
.PP
Note: it is pointless to specify alt files and neither load nor write to them.
.PP
.SH SAMPLE CONFIGURATION FILE
.SH SAMPLE CONFIGURATION FILE
A sample configuration file is distributed as
A sample configuration file is distributed as
.B wine.ini
.B wine.ini
...
...
misc/registry.c
View file @
9e6b1d14
...
@@ -732,7 +732,322 @@ static void _copy_registry( HKEY from, HKEY to )
...
@@ -732,7 +732,322 @@ static void _copy_registry( HKEY from, HKEY to )
}
}
}
}
}
}
/* NT REGISTRY LOADER */
#include <sys/mman.h>
#ifndef MAP_FAILED
#define MAP_FAILED ((LPVOID)-1)
#endif
#define LONG_DUMP 1
#define REG_BLOCK_SIZE 0x1000
#define REG_HEADER_BLOCK_ID 0x66676572
/* regf */
#define REG_POOL_BLOCK_ID 0x6E696268
/* hbin */
#define REG_KEY_BLOCK_ID 0x6b6e
#define REG_VALUE_BLOCK_ID 0x6b76
#define REG_HASH_BLOCK_ID 0x666c
#define REG_NOHASH_BLOCK_ID 0x696c
#define REG_KEY_BLOCK_TYPE 0x20
#define REG_ROOT_KEY_BLOCK_TYPE 0x2c
typedef
struct
{
DWORD
id
;
/* 0x66676572 'regf'*/
DWORD
uk1
;
/* 0x04 */
DWORD
uk2
;
/* 0x08 */
FILETIME
DateModified
;
/* 0x0c */
DWORD
uk3
;
/* 0x14 */
DWORD
uk4
;
/* 0x18 */
DWORD
uk5
;
/* 0x1c */
DWORD
uk6
;
/* 0x20 */
DWORD
RootKeyBlock
;
/* 0x24 */
DWORD
BlockSize
;
/* 0x28 */
DWORD
uk7
[
116
];
DWORD
Checksum
;
/* at offset 0x1FC */
}
nt_regf
;
typedef
struct
{
DWORD
blocksize
;
BYTE
data
[
1
];
}
nt_hbin_sub
;
typedef
struct
{
DWORD
id
;
/* 0x6E696268 'hbin' */
DWORD
off_prev
;
DWORD
off_next
;
DWORD
uk1
;
DWORD
uk2
;
/* 0x10 */
DWORD
uk3
;
/* 0x14 */
DWORD
uk4
;
/* 0x18 */
DWORD
size
;
/* 0x1C */
nt_hbin_sub
hbin_sub
;
/* 0x20 */
}
nt_hbin
;
/*
* the value_list consists of offsets to the values (vk)
*/
typedef
struct
{
WORD
SubBlockId
;
/* 0x00 0x6B6E */
WORD
Type
;
/* 0x02 for the root-key: 0x2C, otherwise 0x20*/
FILETIME
writetime
;
/* 0x04 */
DWORD
uk1
;
/* 0x0C */
DWORD
parent_off
;
/* 0x10 Offset of Owner/Parent key */
DWORD
nr_subkeys
;
/* 0x14 number of sub-Keys */
DWORD
uk8
;
/* 0x18 */
DWORD
lf_off
;
/* 0x1C Offset of the sub-key lf-Records */
DWORD
uk2
;
/* 0x20 */
DWORD
nr_values
;
/* 0x24 number of values */
DWORD
valuelist_off
;
/* 0x28 Offset of the Value-List */
DWORD
off_sk
;
/* 0x2c Offset of the sk-Record */
DWORD
off_class
;
/* 0x30 Offset of the Class-Name */
DWORD
uk3
;
/* 0x34 */
DWORD
uk4
;
/* 0x38 */
DWORD
uk5
;
/* 0x3c */
DWORD
uk6
;
/* 0x40 */
DWORD
uk7
;
/* 0x44 */
WORD
name_len
;
/* 0x48 name-length */
WORD
class_len
;
/* 0x4a class-name length */
char
name
[
1
];
/* 0x4c key-name */
}
nt_nk
;
typedef
struct
{
DWORD
off_nk
;
/* 0x00 */
DWORD
name
;
/* 0x04 */
}
hash_rec
;
typedef
struct
{
WORD
id
;
/* 0x00 0x666c */
WORD
nr_keys
;
/* 0x06 */
hash_rec
hash_rec
[
1
];
}
nt_lf
;
typedef
struct
{
WORD
id
;
/* 0x00 0x696c */
WORD
nr_keys
;
DWORD
off_nk
[
1
];
}
nt_il
;
typedef
struct
{
WORD
id
;
/* 0x00 'vk' */
WORD
nam_len
;
DWORD
data_len
;
DWORD
data_off
;
DWORD
type
;
WORD
flag
;
WORD
uk1
;
char
name
[
1
];
}
nt_vk
;
#define vk_sz 0x0001
#define vk_expsz 0x0002
#define vk_bin 0x0003
#define vk_dword 0x0004
#define vk_multisz 0x0007
#define vk_u2 0x0008
#define vk_u1 0x000a
LPSTR
_strdupnA
(
LPCSTR
str
,
int
len
)
{
LPSTR
ret
;
if
(
!
str
)
return
NULL
;
ret
=
malloc
(
len
+
1
);
lstrcpynA
(
ret
,
str
,
len
);
ret
[
len
]
=
0x00
;
return
ret
;
}
int
_nt_parse_nk
(
HKEY
hkey
,
char
*
base
,
nt_nk
*
nk
,
int
level
);
int
_nt_parse_vk
(
HKEY
hkey
,
char
*
base
,
nt_vk
*
vk
,
int
level
);
int
_nt_parse_lf
(
HKEY
hkey
,
char
*
base
,
nt_lf
*
lf
,
int
level
);
/*
* gets a value
*
* vk->flag:
* 0 value is a default value
* 1 the value has a name
*
* vk->data_len
* len of the whole data block
* - reg_sz (unicode)
* bytes including the terminating \0 = 2*(number_of_chars+1)
* - reg_dword, reg_binary:
* if highest bit of data_len is set data_off contains the value
*/
int
_nt_parse_vk
(
HKEY
hkey
,
char
*
base
,
nt_vk
*
vk
,
int
level
)
{
WCHAR
name
[
256
];
BYTE
*
pdata
=
(
BYTE
*
)(
base
+
vk
->
data_off
+
4
);
/* start of data */
if
(
vk
->
id
!=
REG_VALUE_BLOCK_ID
)
goto
error
;
lstrcpynAtoW
(
name
,
vk
->
name
,
vk
->
nam_len
+
1
);
if
(
RegSetValueExW
(
hkey
,
(
vk
->
flag
&
0x00000001
)
?
name
:
NULL
,
0
,
vk
->
type
,
(
vk
->
data_len
&
0x80000000
)
?
(
LPBYTE
)
&
(
vk
->
data_off
)
:
pdata
,
(
vk
->
data_len
&
0x7fffffff
)
))
goto
error
;
return
TRUE
;
error:
ERR_
(
reg
)(
"vk block invalid
\n
"
);
return
FALSE
;
}
/*
* get the subkeys
*
* this structure contains the hash of a keyname and points to all
* subkeys
*
* exception: if the id is 'il' there are no hash values and every
* dword is a offset
*/
int
_nt_parse_lf
(
HKEY
hkey
,
char
*
base
,
nt_lf
*
lf
,
int
level
)
{
int
i
;
if
(
lf
->
id
==
REG_HASH_BLOCK_ID
)
{
for
(
i
=
0
;
i
<
lf
->
nr_keys
;
i
++
)
{
if
(
!
_nt_parse_nk
(
hkey
,
base
,
(
nt_nk
*
)(
base
+
lf
->
hash_rec
[
i
].
off_nk
+
4
),
level
))
goto
error
;
}
}
else
if
(
lf
->
id
==
REG_NOHASH_BLOCK_ID
)
{
for
(
i
=
0
;
i
<
lf
->
nr_keys
;
i
++
)
{
if
(
!
_nt_parse_nk
(
hkey
,
base
,
(
nt_nk
*
)(
base
+
((
nt_il
*
)
lf
)
->
off_nk
[
i
]
+
4
),
level
))
goto
error
;
}
}
return
TRUE
;
error:
ERR_
(
reg
)(
"error reading lf block
\n
"
);
return
FALSE
;
}
int
_nt_parse_nk
(
HKEY
hkey
,
char
*
base
,
nt_nk
*
nk
,
int
level
)
{
char
*
name
;
int
i
;
DWORD
*
vl
;
HKEY
subkey
;
if
(
nk
->
SubBlockId
!=
REG_KEY_BLOCK_ID
)
goto
error
;
if
((
nk
->
Type
!=
REG_ROOT_KEY_BLOCK_TYPE
)
&&
(((
nt_nk
*
)(
base
+
nk
->
parent_off
+
4
))
->
SubBlockId
!=
REG_KEY_BLOCK_ID
))
goto
error
;
/* create the new key */
name
=
_strdupnA
(
nk
->
name
,
nk
->
name_len
+
1
);
if
(
RegCreateKeyA
(
hkey
,
name
,
&
subkey
))
{
free
(
name
);
goto
error
;
}
free
(
name
);
/* loop through the subkeys */
if
(
nk
->
nr_subkeys
)
{
nt_lf
*
lf
=
(
nt_lf
*
)(
base
+
nk
->
lf_off
+
4
);
if
(
nk
->
nr_subkeys
!=
lf
->
nr_keys
)
goto
error1
;
if
(
!
_nt_parse_lf
(
subkey
,
base
,
lf
,
level
+
1
))
goto
error1
;
}
/* loop trough the value list */
vl
=
(
DWORD
*
)(
base
+
nk
->
valuelist_off
+
4
);
for
(
i
=
0
;
i
<
nk
->
nr_values
;
i
++
)
{
nt_vk
*
vk
=
(
nt_vk
*
)(
base
+
vl
[
i
]
+
4
);
if
(
!
_nt_parse_vk
(
subkey
,
base
,
vk
,
level
+
1
))
goto
error1
;
}
RegCloseKey
(
subkey
);
return
TRUE
;
error1:
RegCloseKey
(
subkey
);
error:
ERR_
(
reg
)(
"error reading nk block
\n
"
);
return
FALSE
;
}
/*
* this function intentionally uses unix file functions to make it possible
* to move it to a seperate registry helper programm
*/
static
int
_nt_loadreg
(
HKEY
hkey
,
char
*
fn
)
{
void
*
base
;
int
len
,
fd
;
struct
stat
st
;
nt_regf
*
regf
;
nt_hbin
*
hbin
;
nt_hbin_sub
*
hbin_sub
;
nt_nk
*
nk
;
DOS_FULL_NAME
full_name
;
if
(
!
DOSFS_GetFullName
(
fn
,
0
,
&
full_name
));
TRACE_
(
reg
)(
"Loading NT registry database '%s' '%s'
\n
"
,
fn
,
full_name
.
long_name
);
if
((
fd
=
open
(
full_name
.
long_name
,
O_RDONLY
|
O_NONBLOCK
))
==
-
1
)
return
FALSE
;
if
(
fstat
(
fd
,
&
st
)
==
-
1
)
goto
error1
;
len
=
st
.
st_size
;
if
((
base
=
mmap
(
NULL
,
len
,
PROT_READ
,
MAP_PRIVATE
,
fd
,
0
))
==
MAP_FAILED
)
goto
error1
;
/* start block */
regf
=
base
;
if
(
regf
->
id
!=
REG_HEADER_BLOCK_ID
)
/* 'regf' */
{
ERR
(
"%s is not a nt-registry
\n
"
,
fn
);
goto
error
;
}
TRACE_
(
reg
)(
"%p [regf] offset=%lx size=%lx
\n
"
,
regf
,
regf
->
RootKeyBlock
,
regf
->
BlockSize
);
/* hbin block */
hbin
=
base
+
0x1000
;
if
(
hbin
->
id
!=
REG_POOL_BLOCK_ID
)
{
ERR_
(
reg
)(
"%s hbin block invalid
\n
"
,
fn
);
goto
error
;
}
TRACE_
(
reg
)(
"%p [hbin] prev=%lx next=%lx size=%lx
\n
"
,
hbin
,
hbin
->
off_prev
,
hbin
->
off_next
,
hbin
->
size
);
/* hbin_sub block */
hbin_sub
=
(
nt_hbin_sub
*
)
&
(
hbin
->
hbin_sub
);
if
((
hbin_sub
->
data
[
0
]
!=
'n'
)
||
(
hbin_sub
->
data
[
1
]
!=
'k'
))
{
ERR_
(
reg
)(
"%s hbin_sub block invalid
\n
"
,
fn
);
goto
error
;
}
TRACE_
(
reg
)(
"%p [hbin sub] size=%lx
\n
"
,
hbin_sub
,
hbin_sub
->
blocksize
);
/* nk block */
nk
=
(
nt_nk
*
)
&
(
hbin_sub
->
data
[
0
]);
if
(
nk
->
Type
!=
REG_ROOT_KEY_BLOCK_TYPE
)
{
ERR_
(
reg
)(
"%s special nk block not found
\n
"
,
fn
);
goto
error
;
}
_nt_parse_nk
(
hkey
,
base
+
0x1000
,
nk
,
0
);
munmap
(
base
,
len
);
close
(
fd
);
return
1
;
error:
munmap
(
base
,
len
);
error1:
close
(
fd
);
ERR_
(
reg
)(
"error reading registry file
\n
"
);
return
0
;
}
/* end nt loader */
/* WINDOWS 95 REGISTRY LOADER */
/* WINDOWS 95 REGISTRY LOADER */
/*
/*
...
@@ -1302,15 +1617,55 @@ void SHELL_LoadRegistry( void )
...
@@ -1302,15 +1617,55 @@ void SHELL_LoadRegistry( void )
req
->
version
=
1
;
req
->
version
=
1
;
server_call
(
REQ_SET_REGISTRY_LEVELS
);
server_call
(
REQ_SET_REGISTRY_LEVELS
);
if
(
PROFILE_GetWineIniBool
(
"registry"
,
"LoadWin
dows
RegistryFiles"
,
1
))
if
(
PROFILE_GetWineIniBool
(
"registry"
,
"LoadWin
311
RegistryFiles"
,
1
))
{
{
/* Load windows 3.1 entries */
/* Load windows 3.1 entries */
_w31_loadreg
();
_w31_loadreg
();
}
if
(
PROFILE_GetWineIniBool
(
"registry"
,
"LoadWin95RegistryFiles"
,
1
))
{
/* Load windows 95 entries */
/* Load windows 95 entries */
_w95_loadreg
(
"C:
\\
system.1st"
,
HKEY_LOCAL_MACHINE
);
_w95_loadreg
(
"C:
\\
system.1st"
,
HKEY_LOCAL_MACHINE
);
_w95_loadreg
(
"system.dat"
,
HKEY_LOCAL_MACHINE
);
_w95_loadreg
(
"system.dat"
,
HKEY_LOCAL_MACHINE
);
_w95_loadreg
(
"user.dat"
,
HKEY_USERS
);
_w95_loadreg
(
"user.dat"
,
HKEY_USERS
);
}
}
if
(
PROFILE_GetWineIniBool
(
"registry"
,
"LoadWinNTRegistryFiles"
,
1
))
{
fn
=
xmalloc
(
MAX_PATHNAME_LEN
);
home
=
xmalloc
(
MAX_PATHNAME_LEN
);
if
(
PROFILE_GetWineIniString
(
"registry"
,
"NTUser"
,
""
,
home
,
MAX_PATHNAME_LEN
-
1
))
{
GetWindowsDirectoryA
(
fn
,
MAX_PATHNAME_LEN
);
strncat
(
fn
,
"
\\
Profiles
\\
"
,
MAX_PATHNAME_LEN
-
strlen
(
fn
)
-
1
);
strncat
(
fn
,
home
,
MAX_PATHNAME_LEN
-
strlen
(
fn
)
-
1
);
strncat
(
fn
,
"
\\
ntuser.dat"
,
MAX_PATHNAME_LEN
-
strlen
(
fn
)
-
1
);
_nt_loadreg
(
HKEY_USERS
,
fn
);
}
/*
* FIXME
* map HLM\System\ControlSet001 to HLM\System\CurrentControlSet
*/
GetSystemDirectoryA
(
fn
,
MAX_PATHNAME_LEN
);
strcpy
(
home
,
fn
);
strncat
(
home
,
"
\\
config
\\
system"
,
MAX_PATHNAME_LEN
-
strlen
(
home
)
-
1
);
_nt_loadreg
(
HKEY_LOCAL_MACHINE
,
home
);
strcpy
(
home
,
fn
);
strncat
(
home
,
"
\\
config
\\
software"
,
MAX_PATHNAME_LEN
-
strlen
(
home
)
-
1
);
_nt_loadreg
(
HKEY_LOCAL_MACHINE
,
home
);
strcpy
(
home
,
fn
);
strncat
(
home
,
"
\\
config
\\
sam"
,
MAX_PATHNAME_LEN
-
strlen
(
home
)
-
1
);
_nt_loadreg
(
HKEY_LOCAL_MACHINE
,
home
);
strcpy
(
home
,
fn
);
strncat
(
home
,
"
\\
config
\\
security"
,
MAX_PATHNAME_LEN
-
strlen
(
home
)
-
1
);
_nt_loadreg
(
HKEY_LOCAL_MACHINE
,
home
);
free
(
home
);
free
(
fn
);
}
if
(
PROFILE_GetWineIniBool
(
"registry"
,
"LoadGlobalRegistryFiles"
,
1
))
if
(
PROFILE_GetWineIniBool
(
"registry"
,
"LoadGlobalRegistryFiles"
,
1
))
{
{
...
...
wine.ini
View file @
9e6b1d14
...
@@ -144,8 +144,6 @@ AltLocalMachineFile=
...
@@ -144,8 +144,6 @@ AltLocalMachineFile=
LoadGlobalRegistryFiles
=
Y
LoadGlobalRegistryFiles
=
Y
; Home registries (stored in ~user/.wine/)
; Home registries (stored in ~user/.wine/)
LoadHomeRegistryFiles
=
Y
LoadHomeRegistryFiles
=
Y
; Windows registries in windows path, above
LoadWindowsRegistryFiles
=
Y
; Load above registries.
; Load above registries.
LoadAltRegistryFiles
=
Y
LoadAltRegistryFiles
=
Y
; TRY to write all changes to home registries
; TRY to write all changes to home registries
...
@@ -157,6 +155,14 @@ UseNewFormat=N
...
@@ -157,6 +155,14 @@ UseNewFormat=N
; Registry periodic save timeout in seconds
; Registry periodic save timeout in seconds
; PeriodicSave=600
; PeriodicSave=600
; Windows registries in windows path
LoadWin311RegistryFiles
=
Y
LoadWin95RegistryFiles
=
Y
LoadWinNTRegistryFiles
=
N
;user the private registry is taken from
;(profiles/<username>/ntuser.dat)
;NTUser=username
[Tweak.Layout]
[Tweak.Layout]
;; WineLook=xxx (supported styles are 'Win31'(default), 'Win95', 'Win98')
;; WineLook=xxx (supported styles are 'Win31'(default), 'Win95', 'Win98')
;WineLook=Win95
;WineLook=Win95
...
...
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