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
ff49652e
Commit
ff49652e
authored
Feb 05, 2004
by
Hans Leidekker
Committed by
Alexandre Julliard
Feb 05, 2004
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Improved error reporting.
Add some notification types and a test.
parent
3f789b1c
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
253 additions
and
1 deletion
+253
-1
.cvsignore
dlls/kernel/tests/.cvsignore
+1
-0
Makefile.in
dlls/kernel/tests/Makefile.in
+1
-0
change.c
dlls/kernel/tests/change.c
+237
-0
change.c
server/change.c
+14
-1
No files found.
dlls/kernel/tests/.cvsignore
View file @
ff49652e
Makefile
alloc.ok
atom.ok
change.ok
codepage.ok
comm.ok
console.ok
...
...
dlls/kernel/tests/Makefile.in
View file @
ff49652e
...
...
@@ -8,6 +8,7 @@ IMPORTS = kernel32
CTESTS
=
\
alloc.c
\
atom.c
\
change.c
\
codepage.c
\
comm.c
\
console.c
\
...
...
dlls/kernel/tests/change.c
0 → 100644
View file @
ff49652e
/*
* Tests for file change notification functions
*
* Copyright (c) 2004 Hans Leidekker
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* TODO: - security attribute changes
* - compound filter and multiple notifications
* - subtree notifications
* - non-documented flags FILE_NOTIFY_CHANGE_LAST_ACCESS and
* FILE_NOTIFY_CHANGE_CREATION
*/
#include <stdarg.h>
#include <stdio.h>
#include "wine/test.h"
#include <windef.h>
#include <winbase.h>
static
DWORD
CALLBACK
NotificationThread
(
LPVOID
arg
)
{
HANDLE
change
=
(
HANDLE
)
arg
;
BOOL
ret
=
FALSE
;
DWORD
status
;
status
=
WaitForSingleObject
(
change
,
100
);
if
(
status
==
WAIT_OBJECT_0
)
{
ret
=
FindNextChangeNotification
(
change
);
}
ok
(
FindCloseChangeNotification
(
change
),
"FindCloseChangeNotification error: %ld
\n
"
,
GetLastError
());
ExitThread
((
DWORD
)
ret
);
}
static
HANDLE
StartNotificationThread
(
LPCSTR
path
,
BOOL
subtree
,
DWORD
flags
)
{
HANDLE
change
,
thread
;
DWORD
threadId
;
change
=
FindFirstChangeNotificationA
(
path
,
subtree
,
flags
);
ok
(
change
!=
INVALID_HANDLE_VALUE
,
"FindFirstChangeNotification error: %ld
\n
"
,
GetLastError
());
thread
=
CreateThread
(
NULL
,
0
,
(
LPTHREAD_START_ROUTINE
)
NotificationThread
,
(
LPVOID
)
change
,
0
,
&
threadId
);
ok
(
thread
!=
INVALID_HANDLE_VALUE
,
"CreateThread error: %ld
\n
"
,
GetLastError
());
return
thread
;
}
static
DWORD
FinishNotificationThread
(
HANDLE
thread
)
{
DWORD
status
,
exitcode
;
status
=
WaitForSingleObject
(
thread
,
5000
);
ok
(
status
==
WAIT_OBJECT_0
,
"WaitForSingleObject status %ld error %ld
\n
"
,
status
,
GetLastError
());
ok
(
GetExitCodeThread
(
thread
,
&
exitcode
),
"Could not retrieve thread exit code
\n
"
);
return
exitcode
;
}
static
void
test_FindFirstChangeNotification
(
void
)
{
HANDLE
change
,
file
,
thread
;
DWORD
attributes
,
count
;
BOOL
ret
;
char
workdir
[
MAX_PATH
],
dirname1
[
MAX_PATH
],
dirname2
[
MAX_PATH
];
char
filename1
[
MAX_PATH
],
filename2
[
MAX_PATH
];
static
const
char
prefix
[]
=
"FCN"
;
char
buffer
[
2048
];
/* pathetic checks */
change
=
FindFirstChangeNotificationA
(
"not-a-file"
,
FALSE
,
FILE_NOTIFY_CHANGE_FILE_NAME
);
ok
(
change
==
INVALID_HANDLE_VALUE
&&
GetLastError
()
==
ERROR_FILE_NOT_FOUND
,
"FindFirstChangeNotification error: %ld
\n
"
,
GetLastError
());
if
(
0
)
/* This documents win2k behavior. It crashes on win98. */
{
change
=
FindFirstChangeNotificationA
(
NULL
,
FALSE
,
FILE_NOTIFY_CHANGE_FILE_NAME
);
ok
(
change
==
NULL
&&
GetLastError
()
==
ERROR_PATH_NOT_FOUND
,
"FindFirstChangeNotification error: %ld
\n
"
,
GetLastError
());
}
ret
=
FindNextChangeNotification
(
NULL
);
ok
(
!
ret
&&
GetLastError
()
==
ERROR_INVALID_HANDLE
,
"FindNextChangeNotification error: %ld
\n
"
,
GetLastError
());
ret
=
FindCloseChangeNotification
(
NULL
);
ok
(
!
ret
&&
GetLastError
()
==
ERROR_INVALID_HANDLE
,
"FindCloseChangeNotification error: %ld
\n
"
,
GetLastError
());
ret
=
GetTempPathA
(
MAX_PATH
,
workdir
);
ok
(
ret
,
"GetTempPathA error: %ld
\n
"
,
GetLastError
());
lstrcatA
(
workdir
,
"testFileChangeNotification"
);
ret
=
CreateDirectoryA
(
workdir
,
NULL
);
ok
(
ret
,
"CreateDirectoryA error: %ld
\n
"
,
GetLastError
());
ret
=
GetTempFileNameA
(
workdir
,
prefix
,
0
,
filename1
);
ok
(
ret
,
"GetTempFileNameA error: %ld
\n
"
,
GetLastError
());
file
=
CreateFileA
(
filename1
,
GENERIC_WRITE
|
GENERIC_READ
,
0
,
NULL
,
CREATE_ALWAYS
,
FILE_ATTRIBUTE_NORMAL
,
0
);
ok
(
file
!=
INVALID_HANDLE_VALUE
,
"CreateFileA error: %ld
\n
"
,
GetLastError
());
ok
(
CloseHandle
(
file
),
"CloseHandle error: %ld
\n
"
,
GetLastError
());
/* Try to register notification for a file. win98 and win2k behave differently here */
change
=
FindFirstChangeNotificationA
(
filename1
,
FALSE
,
FILE_NOTIFY_CHANGE_FILE_NAME
);
ok
(
change
==
INVALID_HANDLE_VALUE
&&
(
GetLastError
()
==
ERROR_DIRECTORY
||
GetLastError
()
==
ERROR_FILE_NOT_FOUND
),
"FindFirstChangeNotification error: %ld
\n
"
,
GetLastError
());
lstrcpyA
(
dirname1
,
filename1
);
lstrcatA
(
dirname1
,
"dir"
);
ret
=
CreateDirectoryA
(
dirname1
,
NULL
);
ok
(
ret
,
"CreateDirectoryA error: %ld"
,
GetLastError
());
/* What if we remove the directory we registered notification for? */
thread
=
StartNotificationThread
(
dirname1
,
FALSE
,
FILE_NOTIFY_CHANGE_DIR_NAME
);
ret
=
RemoveDirectoryA
(
dirname1
);
ok
(
ret
,
"RemoveDirectoryA error: %ld
\n
"
,
GetLastError
());
/* win98 and win2k behave differently here */
ret
=
FinishNotificationThread
(
thread
);
ok
(
ret
||
!
ret
,
"You'll never read this
\n
"
);
/* functional checks */
/* Create a directory */
thread
=
StartNotificationThread
(
workdir
,
FALSE
,
FILE_NOTIFY_CHANGE_DIR_NAME
);
ret
=
CreateDirectoryA
(
dirname1
,
NULL
);
ok
(
ret
,
"CreateDirectoryA error: %ld
\n
"
,
GetLastError
());
ok
(
FinishNotificationThread
(
thread
),
"Missed notification
\n
"
);
lstrcpyA
(
dirname2
,
dirname1
);
lstrcatA
(
dirname2
,
"new"
);
/* Rename a directory */
thread
=
StartNotificationThread
(
workdir
,
FALSE
,
FILE_NOTIFY_CHANGE_DIR_NAME
);
ret
=
MoveFileA
(
dirname1
,
dirname2
);
ok
(
ret
,
"MoveFileA error: %ld
\n
"
,
GetLastError
());
ok
(
FinishNotificationThread
(
thread
),
"Missed notification
\n
"
);
/* Delete a directory */
thread
=
StartNotificationThread
(
workdir
,
FALSE
,
FILE_NOTIFY_CHANGE_DIR_NAME
);
ret
=
RemoveDirectoryA
(
dirname2
);
ok
(
ret
,
"RemoveDirectoryA error: %ld
\n
"
,
GetLastError
());
ok
(
FinishNotificationThread
(
thread
),
"Missed notification
\n
"
);
lstrcpyA
(
filename2
,
filename1
);
lstrcatA
(
filename2
,
"new"
);
/* Rename a file */
thread
=
StartNotificationThread
(
workdir
,
FALSE
,
FILE_NOTIFY_CHANGE_FILE_NAME
);
ret
=
MoveFileA
(
filename1
,
filename2
);
ok
(
ret
,
"MoveFileA error: %ld
\n
"
,
GetLastError
());
ok
(
FinishNotificationThread
(
thread
),
"Missed notification
\n
"
);
/* Delete a file */
thread
=
StartNotificationThread
(
workdir
,
FALSE
,
FILE_NOTIFY_CHANGE_FILE_NAME
);
ret
=
DeleteFileA
(
filename2
);
ok
(
ret
,
"DeleteFileA error: %ld
\n
"
,
GetLastError
());
ok
(
FinishNotificationThread
(
thread
),
"Missed notification
\n
"
);
/* Create a file */
thread
=
StartNotificationThread
(
workdir
,
FALSE
,
FILE_NOTIFY_CHANGE_FILE_NAME
);
file
=
CreateFileA
(
filename2
,
GENERIC_WRITE
|
GENERIC_READ
,
0
,
NULL
,
CREATE_ALWAYS
,
FILE_ATTRIBUTE_NORMAL
,
0
);
ok
(
file
!=
INVALID_HANDLE_VALUE
,
"CreateFileA error: %ld
\n
"
,
GetLastError
());
ok
(
CloseHandle
(
file
),
"CloseHandle error: %ld
\n
"
,
GetLastError
());
ok
(
FinishNotificationThread
(
thread
),
"Missed notification
\n
"
);
attributes
=
GetFileAttributesA
(
filename2
);
ok
(
attributes
!=
INVALID_FILE_ATTRIBUTES
,
"GetFileAttributesA error: %ld
\n
"
,
GetLastError
());
attributes
&=
FILE_ATTRIBUTE_READONLY
;
/* Change file attributes */
thread
=
StartNotificationThread
(
workdir
,
FALSE
,
FILE_NOTIFY_CHANGE_ATTRIBUTES
);
ret
=
SetFileAttributesA
(
filename2
,
attributes
);
ok
(
ret
,
"SetFileAttributesA error: %ld
\n
"
,
GetLastError
());
ok
(
FinishNotificationThread
(
thread
),
"Missed notification
\n
"
);
/* Change last write time by writing to a file */
thread
=
StartNotificationThread
(
workdir
,
FALSE
,
FILE_NOTIFY_CHANGE_LAST_WRITE
);
file
=
CreateFileA
(
filename2
,
GENERIC_WRITE
,
0
,
NULL
,
CREATE_ALWAYS
,
FILE_ATTRIBUTE_NORMAL
,
0
);
ok
(
file
!=
INVALID_HANDLE_VALUE
,
"CreateFileA error: %ld
\n
"
,
GetLastError
());
ret
=
WriteFile
(
file
,
buffer
,
sizeof
(
buffer
),
&
count
,
NULL
);
ok
(
ret
&&
count
==
sizeof
(
buffer
),
"WriteFile error: %ld
\n
"
,
GetLastError
());
ok
(
CloseHandle
(
file
),
"CloseHandle error: %ld
\n
"
,
GetLastError
());
ok
(
FinishNotificationThread
(
thread
),
"Missed notification
\n
"
);
/* Change file size by truncating a file */
thread
=
StartNotificationThread
(
workdir
,
FALSE
,
FILE_NOTIFY_CHANGE_SIZE
);
file
=
CreateFileA
(
filename2
,
GENERIC_WRITE
,
0
,
NULL
,
CREATE_ALWAYS
,
FILE_ATTRIBUTE_NORMAL
,
0
);
ok
(
file
!=
INVALID_HANDLE_VALUE
,
"CreateFileA error: %ld
\n
"
,
GetLastError
());
ret
=
WriteFile
(
file
,
buffer
,
sizeof
(
buffer
)
/
2
,
&
count
,
NULL
);
ok
(
ret
&&
count
==
sizeof
(
buffer
)
/
2
,
"WriteFileA error: %ld
\n
"
,
GetLastError
());
ok
(
CloseHandle
(
file
),
"CloseHandle error: %ld
\n
"
,
GetLastError
());
ok
(
FinishNotificationThread
(
thread
),
"Missed notification
\n
"
);
/* clean up */
ret
=
DeleteFileA
(
filename2
);
ok
(
ret
,
"DeleteFileA error: %ld
\n
"
,
GetLastError
());
ret
=
RemoveDirectoryA
(
workdir
);
ok
(
ret
,
"RemoveDirectoryA error: %ld
\n
"
,
GetLastError
());
}
START_TEST
(
change
)
{
test_FindFirstChangeNotification
();
}
server/change.c
View file @
ff49652e
...
...
@@ -26,6 +26,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/stat.h>
#include "windef.h"
...
...
@@ -81,6 +82,10 @@ static void adjust_changes( int fd, unsigned int filter )
val
|=
DN_MODIFY
;
if
(
filter
&
FILE_NOTIFY_CHANGE_LAST_WRITE
)
val
|=
DN_MODIFY
;
if
(
filter
&
FILE_NOTIFY_CHANGE_LAST_ACCESS
)
val
|=
DN_ACCESS
;
if
(
filter
&
FILE_NOTIFY_CHANGE_CREATION
)
val
|=
DN_CREATE
;
if
(
filter
&
FILE_NOTIFY_CHANGE_SECURITY
)
val
|=
DN_ATTRIB
;
fcntl
(
fd
,
F_NOTIFY
,
val
);
...
...
@@ -114,6 +119,14 @@ static inline void remove_change( struct change *change )
static
struct
change
*
create_change_notification
(
struct
fd
*
fd
,
int
subtree
,
unsigned
int
filter
)
{
struct
change
*
change
;
struct
stat
st
;
int
unix_fd
=
get_unix_fd
(
fd
);
if
(
fstat
(
unix_fd
,
&
st
)
==
-
1
||
!
S_ISDIR
(
st
.
st_mode
))
{
set_error
(
STATUS_NOT_A_DIRECTORY
);
return
NULL
;
}
if
((
change
=
alloc_object
(
&
change_ops
)))
{
...
...
@@ -123,7 +136,7 @@ static struct change *create_change_notification( struct fd *fd, int subtree, un
change
->
notified
=
0
;
change
->
signaled
=
0
;
insert_change
(
change
);
adjust_changes
(
get_unix_fd
(
fd
)
,
filter
);
adjust_changes
(
unix_fd
,
filter
);
}
return
change
;
}
...
...
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