Save the registry on server exit without client intervention.
Removed "alt" registry files since we now have symlinks and WINEPREFIX to replace them.
This commit is contained in:
parent
fa8b7281cd
commit
c970904c2c
|
@ -270,26 +270,6 @@ 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)
|
||||
|
@ -308,9 +288,7 @@ Load Windows registry from the current Windows directory.
|
|||
.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.
|
||||
Defaults are read all, write to Home
|
||||
.PP
|
||||
.SH SAMPLE CONFIGURATION FILE
|
||||
A sample configuration file is distributed as
|
||||
|
|
|
@ -996,12 +996,21 @@ struct save_registry_request
|
|||
};
|
||||
|
||||
|
||||
/* Save a registry branch at server exit */
|
||||
struct save_registry_atexit_request
|
||||
{
|
||||
IN int hkey; /* key to save */
|
||||
IN char file[1]; /* file to save to */
|
||||
};
|
||||
|
||||
|
||||
/* Set the current and saving level for the registry */
|
||||
struct set_registry_levels_request
|
||||
{
|
||||
IN int current; /* new current level */
|
||||
IN int saving; /* new saving level */
|
||||
IN int version; /* file format version for saving */
|
||||
IN int period; /* duration between periodic saves (milliseconds) */
|
||||
};
|
||||
|
||||
|
||||
|
@ -1194,6 +1203,7 @@ enum request
|
|||
REQ_DELETE_KEY_VALUE,
|
||||
REQ_LOAD_REGISTRY,
|
||||
REQ_SAVE_REGISTRY,
|
||||
REQ_SAVE_REGISTRY_ATEXIT,
|
||||
REQ_SET_REGISTRY_LEVELS,
|
||||
REQ_CREATE_TIMER,
|
||||
REQ_OPEN_TIMER,
|
||||
|
@ -1209,7 +1219,7 @@ enum request
|
|||
REQ_NB_REQUESTS
|
||||
};
|
||||
|
||||
#define SERVER_PROTOCOL_VERSION 7
|
||||
#define SERVER_PROTOCOL_VERSION 8
|
||||
|
||||
/* ### make_requests end ### */
|
||||
/* Everything above this line is generated automatically by tools/make_requests */
|
||||
|
|
|
@ -14,8 +14,6 @@ extern "C" {
|
|||
* shell 16
|
||||
*/
|
||||
extern void SHELL_LoadRegistry(void);
|
||||
extern void SHELL_SaveRegistry(void);
|
||||
extern void SHELL_InitRegistrySaving(void);
|
||||
|
||||
/* global functions used from shell32 */
|
||||
extern HINSTANCE SHELL_FindExecutable(LPCSTR,LPCSTR ,LPSTR);
|
||||
|
|
|
@ -97,8 +97,6 @@ BOOL MAIN_MainInit( int argc, char *argv[], BOOL win32 )
|
|||
|
||||
if (!LoadLibraryA( "x11drv" )) return FALSE;
|
||||
|
||||
SHELL_InitRegistrySaving();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -180,8 +178,6 @@ void WINAPI ExitKernel16( void )
|
|||
/* Do the clean-up stuff */
|
||||
|
||||
WriteOutProfiles16();
|
||||
SHELL_SaveRegistry();
|
||||
|
||||
TerminateProcess( GetCurrentProcess(), 0 );
|
||||
}
|
||||
|
||||
|
|
237
misc/registry.c
237
misc/registry.c
|
@ -149,155 +149,6 @@ static void REGISTRY_Init(void) {
|
|||
}
|
||||
|
||||
|
||||
/************************ SAVE Registry Function ****************************/
|
||||
|
||||
#define REGISTRY_SAVE_VERSION 0x00000001
|
||||
|
||||
/* Registry saveformat:
|
||||
* If you change it, increase above number by 1, which will flush
|
||||
* old registry database files.
|
||||
*
|
||||
* Global:
|
||||
* "WINE REGISTRY Version %d"
|
||||
* subkeys....
|
||||
* Subkeys:
|
||||
* keyname
|
||||
* valuename=lastmodified,type,data
|
||||
* ...
|
||||
* subkeys
|
||||
* ...
|
||||
* keyname,valuename,stringdata:
|
||||
* the usual ascii characters from 0x00-0xff (well, not 0x00)
|
||||
* and \uXXXX as UNICODE value XXXX with XXXX>0xff
|
||||
* ( "=\\\t" escaped in \uXXXX form.)
|
||||
* type,lastmodified:
|
||||
* int
|
||||
*
|
||||
* FIXME: doesn't save 'class' (what does it mean anyway?), nor flags.
|
||||
*
|
||||
* [HKEY_CURRENT_USER\\Software\\The WINE team\\WINE\\Registry]
|
||||
* SaveOnlyUpdatedKeys=yes
|
||||
*/
|
||||
|
||||
/* Same as RegSaveKey but with Unix pathnames */
|
||||
static void save_key( HKEY hkey, const char *filename )
|
||||
{
|
||||
struct save_registry_request *req = get_req_buffer();
|
||||
int count = 0;
|
||||
DWORD ret;
|
||||
HANDLE handle;
|
||||
char *p;
|
||||
char *rname = HeapAlloc( GetProcessHeap(), 0, PATH_MAX );
|
||||
char *name;
|
||||
|
||||
/* use realpath to resolve any symlinks
|
||||
* I assume that rname is filled in correctly if the error is ENOENT */
|
||||
if ((realpath(filename, rname) == NULL) && (errno != ENOENT))
|
||||
{
|
||||
ERR( "Failed to find real path of %s: ", filename );
|
||||
perror( "realpath" );
|
||||
HeapFree( GetProcessHeap(), 0, rname );
|
||||
return;
|
||||
}
|
||||
|
||||
name = HeapAlloc( GetProcessHeap(), 0, strlen(rname) + 20 );
|
||||
|
||||
if (!name) return;
|
||||
strcpy( name, rname );
|
||||
if ((p = strrchr( name, '/' ))) p++;
|
||||
else p = name;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
sprintf( p, "reg%04x.tmp", count++ );
|
||||
handle = FILE_CreateFile( name, GENERIC_WRITE, 0, NULL,
|
||||
CREATE_NEW, FILE_ATTRIBUTE_NORMAL, -1, TRUE );
|
||||
if (handle != INVALID_HANDLE_VALUE) break;
|
||||
if ((ret = GetLastError()) != ERROR_ALREADY_EXISTS) break;
|
||||
}
|
||||
|
||||
if (handle != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
req->hkey = hkey;
|
||||
req->file = handle;
|
||||
ret = server_call_noerr( REQ_SAVE_REGISTRY );
|
||||
CloseHandle( handle );
|
||||
if (ret) unlink( name );
|
||||
else if (rename( name, rname ) == -1)
|
||||
{
|
||||
ERR( "Failed to move %s to %s: ", name, rname );
|
||||
perror( "rename" );
|
||||
unlink( name );
|
||||
}
|
||||
}
|
||||
else ERR( "Failed to save registry to %s, err %ld\n", name, GetLastError() );
|
||||
|
||||
HeapFree( GetProcessHeap(), 0, rname );
|
||||
HeapFree( GetProcessHeap(), 0, name );
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* SHELL_SaveRegistry [Internal]
|
||||
*/
|
||||
void SHELL_SaveRegistry( void )
|
||||
{
|
||||
const char *confdir = get_config_dir();
|
||||
struct set_registry_levels_request *req = get_req_buffer();
|
||||
char *fn;
|
||||
|
||||
int all = PROFILE_GetWineIniBool( "registry", "SaveOnlyUpdatedKeys", 1 );
|
||||
int version = PROFILE_GetWineIniBool( "registry", "UseNewFormat", 1 ) ? 2 : 1;
|
||||
|
||||
/* set saving level (0 for saving everything, 1 for saving only modified keys) */
|
||||
req->current = 1;
|
||||
req->saving = !all;
|
||||
req->version = version;
|
||||
server_call( REQ_SET_REGISTRY_LEVELS );
|
||||
|
||||
if (!(fn = HeapAlloc( GetProcessHeap(), 0, MAX_PATHNAME_LEN )))
|
||||
{
|
||||
ERR( "Not enough memory to save registry\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
if (PROFILE_GetWineIniBool("registry","WritetoAltRegistries",1))
|
||||
{
|
||||
if (PROFILE_GetWineIniString( "registry", "AltCurrentUserFile", "", fn, MAX_PATHNAME_LEN ))
|
||||
save_key( HKEY_CURRENT_USER, fn );
|
||||
if (PROFILE_GetWineIniString( "Registry", "AltLocalMachineFile", "", fn, MAX_PATHNAME_LEN ))
|
||||
save_key( HKEY_LOCAL_MACHINE, fn );
|
||||
if (PROFILE_GetWineIniString( "Registry", "AltUserFile", "", fn, MAX_PATHNAME_LEN ))
|
||||
save_key( HKEY_USERS, fn );
|
||||
|
||||
}
|
||||
|
||||
if (PROFILE_GetWineIniBool("registry","WritetoHomeRegistries",1))
|
||||
{
|
||||
char *str;
|
||||
strcpy( fn, confdir );
|
||||
str = fn + strlen(fn);
|
||||
*str++ = '/';
|
||||
|
||||
strcpy( str, SAVE_CURRENT_USER );
|
||||
save_key( HKEY_CURRENT_USER, fn );
|
||||
|
||||
strcpy( str, SAVE_LOCAL_MACHINE );
|
||||
save_key( HKEY_LOCAL_MACHINE, fn );
|
||||
|
||||
strcpy( str, SAVE_LOCAL_USERS_DEFAULT );
|
||||
save_key( HKEY_USERS, fn );
|
||||
}
|
||||
|
||||
HeapFree( GetProcessHeap(), 0, fn );
|
||||
}
|
||||
|
||||
/* Periodic save callback */
|
||||
static void CALLBACK periodic_save( ULONG_PTR dummy )
|
||||
{
|
||||
SHELL_SaveRegistry();
|
||||
}
|
||||
|
||||
/************************ LOAD Registry Function ****************************/
|
||||
|
||||
|
||||
|
@ -554,7 +405,7 @@ static int _wine_loadsubreg( FILE *F, HKEY hkey, const char *fn )
|
|||
free(buf);
|
||||
return 0;
|
||||
}
|
||||
if (ver!=REGISTRY_SAVE_VERSION) {
|
||||
if (ver!=1) {
|
||||
if (ver == 2) /* new version */
|
||||
{
|
||||
HANDLE file;
|
||||
|
@ -1482,6 +1333,53 @@ void _w31_loadreg(void) {
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
/* configure save files and start the periodic saving timer */
|
||||
static void SHELL_InitRegistrySaving(void)
|
||||
{
|
||||
struct set_registry_levels_request *req = get_req_buffer();
|
||||
|
||||
int all = PROFILE_GetWineIniBool( "registry", "SaveOnlyUpdatedKeys", 1 );
|
||||
int version = PROFILE_GetWineIniBool( "registry", "UseNewFormat", 1 ) ? 2 : 1;
|
||||
int period = PROFILE_GetWineIniInt( "registry", "PeriodicSave", 0 );
|
||||
|
||||
/* set saving level (0 for saving everything, 1 for saving only modified keys) */
|
||||
req->current = 1;
|
||||
req->saving = !all;
|
||||
req->version = version;
|
||||
req->period = period * 1000;
|
||||
server_call( REQ_SET_REGISTRY_LEVELS );
|
||||
|
||||
if (PROFILE_GetWineIniBool("registry","WritetoHomeRegistries",1))
|
||||
{
|
||||
struct save_registry_atexit_request *req = get_req_buffer();
|
||||
const char *confdir = get_config_dir();
|
||||
char *str = req->file + strlen(confdir);
|
||||
|
||||
if (str + 20 > req->file + server_remaining(req->file))
|
||||
{
|
||||
ERR("config dir '%s' too long\n", confdir );
|
||||
return;
|
||||
}
|
||||
|
||||
strcpy( req->file, confdir );
|
||||
strcpy( str, "/" SAVE_CURRENT_USER );
|
||||
req->hkey = HKEY_CURRENT_USER;
|
||||
server_call( REQ_SAVE_REGISTRY_ATEXIT );
|
||||
|
||||
strcpy( req->file, confdir );
|
||||
strcpy( str, "/" SAVE_LOCAL_MACHINE );
|
||||
req->hkey = HKEY_LOCAL_MACHINE;
|
||||
server_call( REQ_SAVE_REGISTRY_ATEXIT );
|
||||
|
||||
strcpy( req->file, confdir );
|
||||
strcpy( str, "/" SAVE_LOCAL_USERS_DEFAULT );
|
||||
req->hkey = HKEY_USERS;
|
||||
server_call( REQ_SAVE_REGISTRY_ATEXIT );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************************
|
||||
* SetLoadLevel [Internal]
|
||||
*
|
||||
|
@ -1495,6 +1393,7 @@ static void SetLoadLevel(int level)
|
|||
req->current = level;
|
||||
req->saving = 0;
|
||||
req->version = 1;
|
||||
req->period = 0;
|
||||
server_call( REQ_SET_REGISTRY_LEVELS );
|
||||
}
|
||||
|
||||
|
@ -1693,46 +1592,10 @@ void SHELL_LoadRegistry( void )
|
|||
if (fn != path) HeapFree( GetProcessHeap(), 0, fn );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Load HKCU, get the registry location from the config
|
||||
* file, if exist, load and keep going.
|
||||
*/
|
||||
if (PROFILE_GetWineIniBool ( "registry", "LoadAltRegistryFiles", 1))
|
||||
{
|
||||
if (PROFILE_GetWineIniString( "registry", "AltCurrentUserFile", "", path, sizeof(path) ))
|
||||
_wine_loadreg( HKEY_CURRENT_USER, path );
|
||||
|
||||
/*
|
||||
* Load HKU, get the registry location from the config
|
||||
* file, if exist, load and keep going.
|
||||
*/
|
||||
if (PROFILE_GetWineIniString ( "registry", "AltUserFile", "", path, sizeof(path) ))
|
||||
_wine_loadreg( HKEY_USERS, path );
|
||||
|
||||
/*
|
||||
* Load HKLM, get the registry location from the config
|
||||
* file, if exist, load and keep going.
|
||||
*/
|
||||
if (PROFILE_GetWineIniString ( "registry", "AltLocalMachineFile", "", path, sizeof(path) ))
|
||||
_wine_loadreg( HKEY_LOCAL_MACHINE, path );
|
||||
}
|
||||
SHELL_InitRegistrySaving();
|
||||
}
|
||||
|
||||
/* start the periodic saving timer */
|
||||
void SHELL_InitRegistrySaving(void)
|
||||
{
|
||||
int save_timeout;
|
||||
|
||||
if (!CLIENT_IsBootThread()) return;
|
||||
|
||||
if ((save_timeout = PROFILE_GetWineIniInt( "registry", "PeriodicSave", 0 )))
|
||||
{
|
||||
SERVICE_AddTimer( save_timeout * 1000000, periodic_save, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/********************* API FUNCTIONS ***************************************/
|
||||
|
||||
|
||||
|
|
|
@ -77,10 +77,10 @@ int main( int argc, char *argv[] )
|
|||
|
||||
if (debug_level) fprintf( stderr, "Server: starting (pid=%ld)\n", (long) getpid() );
|
||||
select_loop();
|
||||
close_registry();
|
||||
if (debug_level) fprintf( stderr, "Server: exiting (pid=%ld)\n", (long) getpid() );
|
||||
|
||||
#ifdef DEBUG_OBJECTS
|
||||
close_registry();
|
||||
close_atom_table();
|
||||
dump_objects(); /* dump any remaining objects */
|
||||
#endif
|
||||
|
|
|
@ -11,9 +11,13 @@
|
|||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <pwd.h>
|
||||
#include "object.h"
|
||||
|
@ -89,6 +93,21 @@ static int saving_level;
|
|||
|
||||
static int saving_version = 1; /* file format version */
|
||||
|
||||
static struct timeval next_save_time; /* absolute time of next periodic save */
|
||||
static int save_period; /* delay between periodic saves (ms) */
|
||||
static struct timeout_user *save_timeout_user; /* saving timer */
|
||||
|
||||
/* information about where to save a registry branch */
|
||||
struct save_branch_info
|
||||
{
|
||||
struct key *key;
|
||||
char *path;
|
||||
};
|
||||
|
||||
#define MAX_SAVE_BRANCH_INFO 8
|
||||
static int save_branch_count;
|
||||
static struct save_branch_info save_branch_info[MAX_SAVE_BRANCH_INFO];
|
||||
|
||||
|
||||
/* information about a file being loaded */
|
||||
struct file_load_info
|
||||
|
@ -886,16 +905,6 @@ static struct key *create_root_key( int hkey )
|
|||
return key;
|
||||
}
|
||||
|
||||
/* close the top-level keys; used on server exit */
|
||||
void close_registry(void)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < NB_ROOT_KEYS; i++)
|
||||
{
|
||||
if (root_keys[i]) release_object( root_keys[i] );
|
||||
}
|
||||
}
|
||||
|
||||
/* get the registry key corresponding to an hkey handle */
|
||||
static struct key *get_hkey_obj( int hkey, unsigned int access )
|
||||
{
|
||||
|
@ -1361,6 +1370,136 @@ static void save_registry( struct key *key, int handle )
|
|||
}
|
||||
}
|
||||
|
||||
/* register a key branch for being saved on exit */
|
||||
static void register_branch_for_saving( struct key *key, const char *path, size_t len )
|
||||
{
|
||||
if (save_branch_count >= MAX_SAVE_BRANCH_INFO)
|
||||
{
|
||||
set_error( STATUS_NO_MORE_ENTRIES );
|
||||
return;
|
||||
}
|
||||
if (!(save_branch_info[save_branch_count].path = memdup( path, len+1 ))) return;
|
||||
save_branch_info[save_branch_count].path[len] = 0;
|
||||
save_branch_info[save_branch_count].key = (struct key *)grab_object( key );
|
||||
save_branch_count++;
|
||||
}
|
||||
|
||||
/* save a registry branch to a file */
|
||||
static int save_branch( struct key *key, const char *path )
|
||||
{
|
||||
char *p, *real, *tmp = NULL;
|
||||
int fd, count = 0, ret = 0;
|
||||
FILE *f;
|
||||
|
||||
/* get the real path */
|
||||
|
||||
if (!(real = malloc( PATH_MAX ))) return 0;
|
||||
if (!realpath( path, real ))
|
||||
{
|
||||
free( real );
|
||||
real = NULL;
|
||||
}
|
||||
else path = real;
|
||||
|
||||
/* test the file type */
|
||||
|
||||
if ((fd = open( path, O_WRONLY )) != -1)
|
||||
{
|
||||
struct stat st;
|
||||
/* if file is not a regular file or has multiple links,
|
||||
write directly into it; otherwise use a temp file */
|
||||
if (!fstat( fd, &st ) && (!S_ISREG(st.st_mode) || st.st_nlink > 1))
|
||||
{
|
||||
ftruncate( fd, 0 );
|
||||
goto save;
|
||||
}
|
||||
close( fd );
|
||||
}
|
||||
|
||||
/* create a temp file in the same directory */
|
||||
|
||||
if (!(tmp = malloc( strlen(path) + 20 ))) goto done;
|
||||
strcpy( tmp, path );
|
||||
if ((p = strrchr( tmp, '/' ))) p++;
|
||||
else p = tmp;
|
||||
for (;;)
|
||||
{
|
||||
sprintf( p, "reg%x%04x.tmp", getpid(), count++ );
|
||||
if ((fd = open( tmp, O_CREAT | O_EXCL | O_WRONLY, 0666 )) != -1) break;
|
||||
if (errno != EEXIST) goto done;
|
||||
close( fd );
|
||||
}
|
||||
|
||||
/* now save to it */
|
||||
|
||||
save:
|
||||
if (!(f = fdopen( fd, "w" )))
|
||||
{
|
||||
if (tmp) unlink( tmp );
|
||||
close( fd );
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (debug_level > 1)
|
||||
{
|
||||
fprintf( stderr, "%s: ", path );
|
||||
dump_operation( key, NULL, "saving" );
|
||||
}
|
||||
|
||||
fprintf( f, "WINE REGISTRY Version %d\n", saving_version );
|
||||
if (saving_version == 2) save_subkeys( key, key, f );
|
||||
else
|
||||
{
|
||||
update_level( key );
|
||||
save_subkeys_v1( key, 0, f );
|
||||
}
|
||||
ret = !fclose(f);
|
||||
|
||||
if (tmp)
|
||||
{
|
||||
/* if successfully written, rename to final name */
|
||||
if (ret) ret = !rename( tmp, path );
|
||||
if (!ret) unlink( tmp );
|
||||
free( tmp );
|
||||
}
|
||||
|
||||
done:
|
||||
if (real) free( real );
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* periodic saving of the registry */
|
||||
static void periodic_save( void *arg )
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < save_branch_count; i++)
|
||||
save_branch( save_branch_info[i].key, save_branch_info[i].path );
|
||||
add_timeout( &next_save_time, save_period );
|
||||
save_timeout_user = add_timeout_user( &next_save_time, periodic_save, 0 );
|
||||
}
|
||||
|
||||
/* save the registry and close the top-level keys; used on server exit */
|
||||
void close_registry(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < save_branch_count; i++)
|
||||
{
|
||||
if (!save_branch( save_branch_info[i].key, save_branch_info[i].path ))
|
||||
{
|
||||
fprintf( stderr, "wineserver: could not save registry branch to %s",
|
||||
save_branch_info[i].path );
|
||||
perror( " " );
|
||||
}
|
||||
release_object( save_branch_info[i].key );
|
||||
}
|
||||
for (i = 0; i < NB_ROOT_KEYS; i++)
|
||||
{
|
||||
if (root_keys[i]) release_object( root_keys[i] );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* create a registry key */
|
||||
DECL_HANDLER(create_key)
|
||||
{
|
||||
|
@ -1544,5 +1683,31 @@ DECL_HANDLER(set_registry_levels)
|
|||
current_level = req->current;
|
||||
saving_level = req->saving;
|
||||
saving_version = req->version;
|
||||
|
||||
/* set periodic save timer */
|
||||
|
||||
if (save_timeout_user)
|
||||
{
|
||||
remove_timeout_user( save_timeout_user );
|
||||
save_timeout_user = NULL;
|
||||
}
|
||||
if ((save_period = req->period))
|
||||
{
|
||||
if (save_period < 10000) save_period = 10000; /* limit rate */
|
||||
gettimeofday( &next_save_time, 0 );
|
||||
add_timeout( &next_save_time, save_period );
|
||||
save_timeout_user = add_timeout_user( &next_save_time, periodic_save, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
/* save a registry branch at server exit */
|
||||
DECL_HANDLER(save_registry_atexit)
|
||||
{
|
||||
struct key *key;
|
||||
|
||||
if ((key = get_hkey_obj( req->hkey, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS )))
|
||||
{
|
||||
register_branch_for_saving( key, req->file, get_req_strlen( req, req->file ) );
|
||||
release_object( key );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -157,6 +157,7 @@ DECL_HANDLER(enum_key_value);
|
|||
DECL_HANDLER(delete_key_value);
|
||||
DECL_HANDLER(load_registry);
|
||||
DECL_HANDLER(save_registry);
|
||||
DECL_HANDLER(save_registry_atexit);
|
||||
DECL_HANDLER(set_registry_levels);
|
||||
DECL_HANDLER(create_timer);
|
||||
DECL_HANDLER(open_timer);
|
||||
|
@ -262,6 +263,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
|
|||
(req_handler)req_delete_key_value,
|
||||
(req_handler)req_load_registry,
|
||||
(req_handler)req_save_registry,
|
||||
(req_handler)req_save_registry_atexit,
|
||||
(req_handler)req_set_registry_levels,
|
||||
(req_handler)req_create_timer,
|
||||
(req_handler)req_open_timer,
|
||||
|
|
|
@ -1167,11 +1167,19 @@ static void dump_save_registry_request( const struct save_registry_request *req
|
|||
fprintf( stderr, " file=%d", req->file );
|
||||
}
|
||||
|
||||
static void dump_save_registry_atexit_request( const struct save_registry_atexit_request *req )
|
||||
{
|
||||
fprintf( stderr, " hkey=%d,", req->hkey );
|
||||
fprintf( stderr, " file=" );
|
||||
dump_string( req, req->file );
|
||||
}
|
||||
|
||||
static void dump_set_registry_levels_request( const struct set_registry_levels_request *req )
|
||||
{
|
||||
fprintf( stderr, " current=%d,", req->current );
|
||||
fprintf( stderr, " saving=%d,", req->saving );
|
||||
fprintf( stderr, " version=%d", req->version );
|
||||
fprintf( stderr, " version=%d,", req->version );
|
||||
fprintf( stderr, " period=%d", req->period );
|
||||
}
|
||||
|
||||
static void dump_create_timer_request( const struct create_timer_request *req )
|
||||
|
@ -1375,6 +1383,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
|
|||
(dump_func)dump_delete_key_value_request,
|
||||
(dump_func)dump_load_registry_request,
|
||||
(dump_func)dump_save_registry_request,
|
||||
(dump_func)dump_save_registry_atexit_request,
|
||||
(dump_func)dump_set_registry_levels_request,
|
||||
(dump_func)dump_create_timer_request,
|
||||
(dump_func)dump_open_timer_request,
|
||||
|
@ -1478,6 +1487,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
|
|||
(dump_func)0,
|
||||
(dump_func)0,
|
||||
(dump_func)0,
|
||||
(dump_func)0,
|
||||
(dump_func)dump_create_timer_reply,
|
||||
(dump_func)dump_open_timer_reply,
|
||||
(dump_func)0,
|
||||
|
@ -1579,6 +1589,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
|
|||
"delete_key_value",
|
||||
"load_registry",
|
||||
"save_registry",
|
||||
"save_registry_atexit",
|
||||
"set_registry_levels",
|
||||
"create_timer",
|
||||
"open_timer",
|
||||
|
|
13
wine.ini
13
wine.ini
|
@ -134,27 +134,16 @@ Exclude=WM_SIZE;WM_TIMER;
|
|||
; Paths must be given in /dir/dir/file.reg format.
|
||||
; Wine will not understand dos file names here...
|
||||
|
||||
; alternate registry file name: HKCU
|
||||
AltCurrentUserFile=
|
||||
; alternate registry file name: HKU
|
||||
AltUserFile=
|
||||
; alternate registry file name: HKLM
|
||||
AltLocalMachineFile=
|
||||
;These are all booleans. Y/y/T/t/1 are true, N/n/F/f/0 are false.
|
||||
;Defaults are read all, write to Home and Alt
|
||||
;Note: it is pointless to specify alt files and neither load nor write to them.
|
||||
;Defaults are read all, write to Home
|
||||
; Global registries (stored in /etc)
|
||||
LoadGlobalRegistryFiles=Y
|
||||
; Home registries (stored in ~user/.wine/)
|
||||
LoadHomeRegistryFiles=Y
|
||||
; Load above registries.
|
||||
LoadAltRegistryFiles=Y
|
||||
; Load Windows registries from the Windows directory
|
||||
LoadWindowsRegistryFiles=Y
|
||||
; TRY to write all changes to home registries
|
||||
WritetoHomeRegistryFiles=Y
|
||||
; TRY to write all changes to alt registries
|
||||
WritetoAltRegistryFiles=Y
|
||||
; Use new file format
|
||||
UseNewFormat=Y
|
||||
; Registry periodic save timeout in seconds
|
||||
|
|
Loading…
Reference in New Issue