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
11f4b444
Commit
11f4b444
authored
Nov 25, 2002
by
Mike McCormack
Committed by
Alexandre Julliard
Nov 25, 2002
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implemented registry change notifications.
parent
c124fd6f
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
209 additions
and
8 deletions
+209
-8
registry.c
dlls/advapi32/registry.c
+25
-2
server_protocol.h
include/wine/server_protocol.h
+18
-1
winnt.h
include/winnt.h
+4
-1
handle.c
server/handle.c
+2
-0
object.h
server/object.h
+1
-0
protocol.def
server/protocol.def
+8
-0
registry.c
server/registry.c
+138
-4
request.h
server/request.h
+2
-0
trace.c
server/trace.c
+11
-0
No files found.
dlls/advapi32/registry.c
View file @
11f4b444
...
...
@@ -1841,7 +1841,30 @@ LONG WINAPI RegNotifyChangeKeyValue( HKEY hkey, BOOL fWatchSubTree,
DWORD
fdwNotifyFilter
,
HANDLE
hEvent
,
BOOL
fAsync
)
{
FIXME
(
"(%p,%i,%ld,%p,%i): stub
\n
"
,
hkey
,
fWatchSubTree
,
fdwNotifyFilter
,
LONG
ret
;
TRACE
(
"(%p,%i,%ld,%p,%i)
\n
"
,
hkey
,
fWatchSubTree
,
fdwNotifyFilter
,
hEvent
,
fAsync
);
return
ERROR_SUCCESS
;
if
(
!
fAsync
)
hEvent
=
CreateEventA
(
NULL
,
0
,
0
,
NULL
);
SERVER_START_REQ
(
set_registry_notification
)
{
req
->
hkey
=
hkey
;
req
->
event
=
hEvent
;
req
->
subtree
=
fWatchSubTree
;
req
->
filter
=
fdwNotifyFilter
;
ret
=
RtlNtStatusToDosError
(
wine_server_call
(
req
)
);
}
SERVER_END_REQ
;
if
(
!
fAsync
)
{
if
(
ret
==
ERROR_SUCCESS
)
WaitForSingleObject
(
hEvent
,
INFINITE
);
CloseHandle
(
hEvent
);
}
return
ret
;
}
include/wine/server_protocol.h
View file @
11f4b444
...
...
@@ -1893,6 +1893,20 @@ struct set_registry_levels_reply
};
struct
set_registry_notification_request
{
struct
request_header
__header
;
obj_handle_t
hkey
;
obj_handle_t
event
;
int
subtree
;
unsigned
int
filter
;
};
struct
set_registry_notification_reply
{
struct
reply_header
__header
;
};
struct
create_timer_request
{
...
...
@@ -3044,6 +3058,7 @@ enum request
REQ_save_registry
,
REQ_save_registry_atexit
,
REQ_set_registry_levels
,
REQ_set_registry_notification
,
REQ_create_timer
,
REQ_open_timer
,
REQ_set_timer
,
...
...
@@ -3220,6 +3235,7 @@ union generic_request
struct
save_registry_request
save_registry_request
;
struct
save_registry_atexit_request
save_registry_atexit_request
;
struct
set_registry_levels_request
set_registry_levels_request
;
struct
set_registry_notification_request
set_registry_notification_request
;
struct
create_timer_request
create_timer_request
;
struct
open_timer_request
open_timer_request
;
struct
set_timer_request
set_timer_request
;
...
...
@@ -3394,6 +3410,7 @@ union generic_reply
struct
save_registry_reply
save_registry_reply
;
struct
save_registry_atexit_reply
save_registry_atexit_reply
;
struct
set_registry_levels_reply
set_registry_levels_reply
;
struct
set_registry_notification_reply
set_registry_notification_reply
;
struct
create_timer_reply
create_timer_reply
;
struct
open_timer_reply
open_timer_reply
;
struct
set_timer_reply
set_timer_reply
;
...
...
@@ -3462,6 +3479,6 @@ union generic_reply
struct
get_next_hook_reply
get_next_hook_reply
;
};
#define SERVER_PROTOCOL_VERSION 9
1
#define SERVER_PROTOCOL_VERSION 9
2
#endif
/* __WINE_WINE_SERVER_PROTOCOL_H */
include/winnt.h
View file @
11f4b444
...
...
@@ -3360,7 +3360,10 @@ typedef enum tagSID_NAME_USE {
#define REG_OPENED_EXISTING_KEY 0x00000002
/* For RegNotifyChangeKeyValue */
#define REG_NOTIFY_CHANGE_NAME 0x1
#define REG_NOTIFY_CHANGE_NAME 0x01
#define REG_NOTIFY_CHANGE_ATTRIBUTES 0x02
#define REG_NOTIFY_CHANGE_LAST_SET 0x04
#define REG_NOTIFY_CHANGE_SECURITY 0x08
#define KEY_QUERY_VALUE 0x00000001
#define KEY_SET_VALUE 0x00000002
...
...
server/handle.c
View file @
11f4b444
...
...
@@ -332,6 +332,8 @@ int close_handle( struct process *process, obj_handle_t handle, int *fd )
table
=
handle_is_global
(
handle
)
?
global_table
:
process
->
handles
;
if
(
entry
<
table
->
entries
+
table
->
free
)
table
->
free
=
entry
-
table
->
entries
;
if
(
entry
==
table
->
entries
+
table
->
last
)
shrink_handle_table
(
table
);
/* hack: windows seems to treat registry handles differently */
registry_close_handle
(
obj
,
handle
);
release_object
(
obj
);
return
1
;
}
...
...
server/object.h
View file @
11f4b444
...
...
@@ -195,6 +195,7 @@ extern int get_page_size(void);
extern
void
init_registry
(
void
);
extern
void
flush_registry
(
void
);
extern
void
close_registry
(
void
);
extern
void
registry_close_handle
(
struct
object
*
obj
,
obj_handle_t
hkey
);
/* atom functions */
...
...
server/protocol.def
View file @
11f4b444
...
...
@@ -1358,6 +1358,14 @@ enum char_info_mode
@END
@REQ(set_registry_notification)
obj_handle_t hkey; /* key to watch for changes */
obj_handle_t event; /* event to set */
int subtree; /* should we watch the whole subtree? */
unsigned int filter; /* things to watch */
@END
/* Create a waitable timer */
@REQ(create_timer)
int inherit; /* inherit flag */
...
...
server/registry.c
View file @
11f4b444
...
...
@@ -48,6 +48,16 @@
#include "winternl.h"
#include "wine/library.h"
struct
notify
{
struct
event
*
event
;
/* event to set when changing this key */
int
subtree
;
/* true if subtree notification */
unsigned
int
filter
;
/* which events to notify on */
obj_handle_t
hkey
;
/* hkey associated with this notification */
struct
notify
*
next
;
/* list of notifications */
struct
notify
*
prev
;
/* list of notifications */
};
/* a registry key */
struct
key
{
...
...
@@ -64,6 +74,8 @@ struct key
short
flags
;
/* flags */
short
level
;
/* saving level */
time_t
modif
;
/* last modification time */
struct
notify
*
first_notify
;
/* list of notifications */
struct
notify
*
last_notify
;
/* list of notifications */
};
/* key flags */
...
...
@@ -284,6 +296,53 @@ static void key_dump( struct object *obj, int verbose )
fprintf
(
stderr
,
"
\n
"
);
}
/* notify waiter and maybe delete the notification */
static
void
do_notification
(
struct
key
*
key
,
struct
notify
*
notify
,
int
del
)
{
if
(
notify
->
event
)
{
set_event
(
notify
->
event
);
release_object
(
notify
->
event
);
notify
->
event
=
NULL
;
}
if
(
!
del
)
return
;
if
(
notify
->
next
)
notify
->
next
->
prev
=
notify
->
prev
;
else
key
->
last_notify
=
notify
->
prev
;
if
(
notify
->
prev
)
notify
->
prev
->
next
=
notify
->
next
;
else
key
->
first_notify
=
notify
->
next
;
free
(
notify
);
}
static
struct
notify
*
find_notify
(
struct
key
*
key
,
obj_handle_t
hkey
)
{
struct
notify
*
n
;
for
(
n
=
key
->
first_notify
;
n
;
n
=
n
->
next
)
if
(
n
->
hkey
==
hkey
)
break
;
return
n
;
}
/* close the notification associated with a handle */
void
registry_close_handle
(
struct
object
*
obj
,
obj_handle_t
hkey
)
{
struct
key
*
key
=
(
struct
key
*
)
obj
;
struct
notify
*
notify
;
if
(
obj
->
ops
!=
&
key_ops
)
return
;
notify
=
find_notify
(
key
,
hkey
);
if
(
!
notify
)
return
;
do_notification
(
key
,
notify
,
1
);
}
static
void
key_destroy
(
struct
object
*
obj
)
{
int
i
;
...
...
@@ -302,6 +361,9 @@ static void key_destroy( struct object *obj )
key
->
subkeys
[
i
]
->
parent
=
NULL
;
release_object
(
key
->
subkeys
[
i
]
);
}
/* unconditionally notify everything waiting on this key */
while
(
key
->
first_notify
)
do_notification
(
key
,
key
->
first_notify
,
1
);
}
/* duplicate a key path */
...
...
@@ -389,6 +451,8 @@ static struct key *alloc_key( const WCHAR *name, time_t modif )
key
->
level
=
current_level
;
key
->
modif
=
modif
;
key
->
parent
=
NULL
;
key
->
first_notify
=
NULL
;
key
->
last_notify
=
NULL
;
if
(
!
(
key
->
name
=
strdupW
(
name
)))
{
release_object
(
key
);
...
...
@@ -420,12 +484,32 @@ static void make_clean( struct key *key )
for
(
i
=
0
;
i
<=
key
->
last_subkey
;
i
++
)
make_clean
(
key
->
subkeys
[
i
]
);
}
/* go through all the notifications and send them if necessary */
void
check_notify
(
struct
key
*
key
,
unsigned
int
change
,
int
not_subtree
)
{
struct
notify
*
n
=
key
->
first_notify
;
while
(
n
)
{
struct
notify
*
next
=
n
->
next
;
if
(
(
not_subtree
||
n
->
subtree
)
&&
(
change
&
n
->
filter
)
)
do_notification
(
key
,
n
,
0
);
n
=
next
;
}
}
/* update key modification time */
static
void
touch_key
(
struct
key
*
key
)
static
void
touch_key
(
struct
key
*
key
,
unsigned
int
change
)
{
struct
key
*
k
;
key
->
modif
=
time
(
NULL
);
key
->
level
=
max
(
key
->
level
,
current_level
);
make_dirty
(
key
);
/* do notifications */
check_notify
(
key
,
change
,
1
);
for
(
k
=
key
->
parent
;
k
;
k
=
k
->
parent
)
check_notify
(
k
,
change
&
~
REG_NOTIFY_CHANGE_LAST_SET
,
0
);
}
/* try to grow the array of subkeys; return 1 if OK, 0 on error */
...
...
@@ -583,6 +667,7 @@ static struct key *create_key( struct key *key, WCHAR *name, WCHAR *class,
if
(
!*
path
)
goto
done
;
*
created
=
1
;
touch_key
(
key
,
REG_NOTIFY_CHANGE_NAME
);
/* FIXME: is this right? */
if
(
flags
&
KEY_DIRTY
)
make_dirty
(
key
);
base
=
key
;
base_idx
=
index
;
...
...
@@ -718,7 +803,7 @@ static void delete_key( struct key *key )
}
if
(
debug_level
>
1
)
dump_operation
(
key
,
NULL
,
"Delete"
);
free_subkey
(
parent
,
index
);
touch_key
(
parent
);
touch_key
(
parent
,
REG_NOTIFY_CHANGE_NAME
);
}
/* try to grow the array of values; return 1 if OK, 0 on error */
...
...
@@ -821,7 +906,7 @@ static void set_value( struct key *key, WCHAR *name, int type, const void *data,
value
->
type
=
type
;
value
->
len
=
len
;
value
->
data
=
ptr
;
touch_key
(
key
);
touch_key
(
key
,
REG_NOTIFY_CHANGE_LAST_SET
);
if
(
debug_level
>
1
)
dump_operation
(
key
,
value
,
"Set"
);
}
...
...
@@ -912,7 +997,7 @@ static void delete_value( struct key *key, const WCHAR *name )
if
(
value
->
data
)
free
(
value
->
data
);
for
(
i
=
index
;
i
<
key
->
last_value
;
i
++
)
key
->
values
[
i
]
=
key
->
values
[
i
+
1
];
key
->
last_value
--
;
touch_key
(
key
);
touch_key
(
key
,
REG_NOTIFY_CHANGE_LAST_SET
);
/* try to shrink the array */
nb_values
=
key
->
nb_values
;
...
...
@@ -1817,3 +1902,52 @@ DECL_HANDLER(save_registry_atexit)
release_object
(
key
);
}
}
/* add a registry key change notification */
DECL_HANDLER
(
set_registry_notification
)
{
struct
key
*
key
;
struct
event
*
event
;
struct
notify
*
notify
;
key
=
get_hkey_obj
(
req
->
hkey
,
KEY_NOTIFY
);
if
(
key
)
{
event
=
get_event_obj
(
current
->
process
,
req
->
event
,
SYNCHRONIZE
);
if
(
event
)
{
notify
=
find_notify
(
key
,
req
->
hkey
);
if
(
notify
)
{
release_object
(
notify
->
event
);
grab_object
(
event
);
notify
->
event
=
event
;
}
else
{
notify
=
(
struct
notify
*
)
malloc
(
sizeof
*
notify
);
if
(
notify
)
{
grab_object
(
event
);
notify
->
event
=
event
;
notify
->
subtree
=
req
->
subtree
;
notify
->
filter
=
req
->
filter
;
notify
->
hkey
=
req
->
hkey
;
/* add to linked list */
notify
->
prev
=
NULL
;
notify
->
next
=
key
->
first_notify
;
if
(
notify
->
next
)
notify
->
next
->
prev
=
notify
;
else
key
->
last_notify
=
notify
;
key
->
first_notify
=
notify
;
}
else
set_error
(
STATUS_NO_MEMORY
);
}
release_object
(
event
);
}
release_object
(
key
);
}
}
server/request.h
View file @
11f4b444
...
...
@@ -206,6 +206,7 @@ DECL_HANDLER(load_registry);
DECL_HANDLER
(
save_registry
);
DECL_HANDLER
(
save_registry_atexit
);
DECL_HANDLER
(
set_registry_levels
);
DECL_HANDLER
(
set_registry_notification
);
DECL_HANDLER
(
create_timer
);
DECL_HANDLER
(
open_timer
);
DECL_HANDLER
(
set_timer
);
...
...
@@ -381,6 +382,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
(
req_handler
)
req_save_registry
,
(
req_handler
)
req_save_registry_atexit
,
(
req_handler
)
req_set_registry_levels
,
(
req_handler
)
req_set_registry_notification
,
(
req_handler
)
req_create_timer
,
(
req_handler
)
req_open_timer
,
(
req_handler
)
req_set_timer
,
...
...
server/trace.c
View file @
11f4b444
...
...
@@ -1569,6 +1569,14 @@ static void dump_set_registry_levels_request( const struct set_registry_levels_r
fprintf
(
stderr
,
" period=%d"
,
req
->
period
);
}
static
void
dump_set_registry_notification_request
(
const
struct
set_registry_notification_request
*
req
)
{
fprintf
(
stderr
,
" hkey=%p,"
,
req
->
hkey
);
fprintf
(
stderr
,
" event=%p,"
,
req
->
event
);
fprintf
(
stderr
,
" subtree=%d,"
,
req
->
subtree
);
fprintf
(
stderr
,
" filter=%08x"
,
req
->
filter
);
}
static
void
dump_create_timer_request
(
const
struct
create_timer_request
*
req
)
{
fprintf
(
stderr
,
" inherit=%d,"
,
req
->
inherit
);
...
...
@@ -2445,6 +2453,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(
dump_func
)
dump_save_registry_request
,
(
dump_func
)
dump_save_registry_atexit_request
,
(
dump_func
)
dump_set_registry_levels_request
,
(
dump_func
)
dump_set_registry_notification_request
,
(
dump_func
)
dump_create_timer_request
,
(
dump_func
)
dump_open_timer_request
,
(
dump_func
)
dump_set_timer_request
,
...
...
@@ -2617,6 +2626,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
,
...
...
@@ -2789,6 +2799,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
"save_registry"
,
"save_registry_atexit"
,
"set_registry_levels"
,
"set_registry_notification"
,
"create_timer"
,
"open_timer"
,
"set_timer"
,
...
...
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