[PATCH v2 5/5] kernel32/tests: add IOCTL_COPYCHUNK test
Alex Xu (Hello71)
alex_y_xu at yahoo.ca
Wed Aug 4 11:40:13 CDT 2021
---
dlls/kernel32/tests/file.c | 137 +++++++++++++++++++++++++++++++++++++
1 file changed, 137 insertions(+)
diff --git a/dlls/kernel32/tests/file.c b/dlls/kernel32/tests/file.c
index ea0a32f258d..76a762a62e6 100644
--- a/dlls/kernel32/tests/file.c
+++ b/dlls/kernel32/tests/file.c
@@ -31,9 +31,13 @@
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
+#include "winioctl.h"
#include "winternl.h"
#include "winnls.h"
#include "fileapi.h"
+#include "lmaccess.h"
+#include "lmshare.h"
+#include "lmerr.h"
#undef DeleteFile /* needed for FILE_DISPOSITION_INFO */
@@ -59,6 +63,7 @@ static void (WINAPI *pRtlInitAnsiString)(PANSI_STRING,PCSZ);
static void (WINAPI *pRtlFreeUnicodeString)(PUNICODE_STRING);
static BOOL (WINAPI *pSetFileCompletionNotificationModes)(HANDLE, UCHAR);
static HANDLE (WINAPI *pFindFirstStreamW)(LPCWSTR filename, STREAM_INFO_LEVELS infolevel, void *data, DWORD flags);
+static const char * (CDECL *pwine_get_version)(void);
static char filename[MAX_PATH];
static const char sillytext[] =
@@ -108,6 +113,7 @@ static void InitFunctionPointers(void)
pReOpenFile = (void *) GetProcAddress(hkernel32, "ReOpenFile");
pSetFileCompletionNotificationModes = (void *)GetProcAddress(hkernel32, "SetFileCompletionNotificationModes");
pFindFirstStreamW = (void *)GetProcAddress(hkernel32, "FindFirstStreamW");
+ pwine_get_version = (void *)GetProcAddress(hntdll, "wine_get_version");
}
static void create_file( const char *path )
@@ -6109,6 +6115,136 @@ static void test_eof(void)
ok(ret, "failed to delete %s, error %u\n", debugstr_a(filename), GetLastError());
}
+static void test_copychunk(void)
+{
+ static const char testString[] = "hello world";
+ char testBuf[sizeof(testString)-1];
+ WCHAR temp_path[MAX_PATH];
+ WCHAR temp_file[MAX_PATH];
+ WCHAR share_name[MAX_PATH];
+ WCHAR share_path[MAX_PATH];
+ HANDLE src, dest;
+ int ret;
+ DWORD written, count;
+ FILE_END_OF_FILE_INFO info;
+ SRV_COPYCHUNK_COPY copychunk;
+ SRV_COPYCHUNK_RESPONSE copychunk_resp;
+ SRV_REQUEST_RESUME_KEY key;
+ NET_API_STATUS (NET_API_FUNCTION *pNetShareAdd)(LMSTR, DWORD, LPBYTE, LPDWORD);
+ NET_API_STATUS (NET_API_FUNCTION *pNetShareDel)(LMSTR, LMSTR, DWORD);
+ GetTempPathW(MAX_PATH, temp_path);
+
+ if (pwine_get_version == NULL)
+ {
+ HMODULE hnetapi32;
+ SHARE_INFO_2 shi2 = {
+ .shi2_type = STYPE_DISKTREE | STYPE_TEMPORARY | STYPE_SPECIAL,
+ .shi2_permissions = ACCESS_ALL,
+ .shi2_max_uses = -1,
+ };
+ hnetapi32 = LoadLibraryA("netapi32");
+ if (hnetapi32 == NULL)
+ {
+ win_skip("could not find hnetapi32\n");
+ return;
+ }
+ pNetShareAdd = (void *)GetProcAddress(hnetapi32, "NetShareAdd");
+ if (pNetShareAdd == NULL)
+ {
+ win_skip("could not find NetShareAdd\n");
+ return;
+ }
+ pNetShareDel = (void *)GetProcAddress(hnetapi32, "NetShareDel");
+ if (pNetShareDel == NULL)
+ {
+ win_skip("could not find NetShareDel\n");
+ return;
+ }
+ srand((unsigned)time(NULL));
+ do {
+ int r = rand();
+ swprintf(share_path, MAX_PATH, L"%lswinetest%d", temp_path, r);
+ swprintf(share_name, MAX_PATH, L"winetest%d$", r);
+ ret = CreateDirectoryW(share_path, NULL);
+ if (ret == 0 && GetLastError() != ERROR_ALREADY_EXISTS)
+ {
+ ok(ret != 0, "CreateDirectoryW error %d\n", GetLastError());
+ return;
+ }
+ } while (ret == 0);
+ shi2.shi2_netname = share_name;
+ shi2.shi2_path = share_path;
+ ret = pNetShareAdd(NULL, 2, (BYTE *)&shi2, NULL);
+ if (ret == ERROR_ACCESS_DENIED)
+ {
+ win_skip("windows IOCTL_COPYCHUNK needs admin for NetShareAdd\n");
+ RemoveDirectoryW(share_path);
+ return;
+ }
+ ok(ret == NERR_Success || ret == ERROR_ACCESS_DENIED, "NetShareAdd error %d\n", ret);
+ swprintf(temp_file, MAX_PATH, L"\\\\localhost\\%ls\\file", share_name);
+ }
+ else
+ {
+ ret = GetTempFileNameW(temp_path, L"tmp", 0, temp_file);
+ ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError());
+ }
+
+ src = CreateFileW(temp_file, GENERIC_READ | GENERIC_WRITE, 0, NULL,
+ OPEN_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, NULL);
+ ok(src != INVALID_HANDLE_VALUE, "CreateFileW error %d\n", GetLastError());
+
+ ret = WriteFile(src, testString, sizeof(testString) - 1, &written, NULL);
+ ok(ret != 0, "WriteFile error %d\n", GetLastError());
+ ok(written == sizeof(testString) - 1, "short write to regular file\n");
+
+ ret = FlushFileBuffers(src);
+ ok(ret != 0, "FlushFileBuffers error %d\n", GetLastError());
+
+ wcscat(temp_file, L"2");
+ dest = CreateFileW(temp_file, GENERIC_READ | GENERIC_WRITE, 0, NULL,
+ CREATE_NEW, FILE_FLAG_DELETE_ON_CLOSE, NULL);
+ ok(dest != INVALID_HANDLE_VALUE, "CreateFileW error %d\n", GetLastError());
+
+ info.EndOfFile.QuadPart = written;
+ ret = SetFileInformationByHandle(dest, FileEndOfFileInfo, &info, sizeof(info));
+ ok(ret != 0, "set EOF failed: %d\n", GetLastError());
+
+ ret = DeviceIoControl( src, IOCTL_PREPARE_COPYCHUNK, NULL, 0, &key,
+ sizeof(key), &count, NULL );
+ ok(ret != 0, "IOCTL_PREPARE_COPYCHUNK error %d\n", GetLastError());
+ ok(count != 0, "IOCTL_PREPARE_COPYCHUNK wrong return size: %d\n", count);
+
+ copychunk.SourceFile = key.Key;
+ copychunk.ChunkCount = 1;
+ copychunk.Chunk[0].Length = written;
+ copychunk.Chunk[0].SourceOffset.QuadPart = 0;
+ copychunk.Chunk[0].DestinationOffset.QuadPart = 0;
+ ret = DeviceIoControl( dest, IOCTL_COPYCHUNK, ©chunk, sizeof(copychunk),
+ ©chunk_resp, sizeof(copychunk_resp), &count, NULL );
+ ok(ret != 0, "IOCTL_COPYCHUNK error %d\n", GetLastError());
+ ok(count == sizeof(copychunk_resp), "IOCTL_COPYCHUNK wrong return size: %d\n", count);
+ ok(copychunk_resp.ChunksWritten == 1,
+ "wrong chunks count: %d, should be 1\n", copychunk_resp.ChunksWritten);
+ ok(copychunk_resp.ChunkBytesWritten == 0,
+ "wrong chunk bytes written: %d, should be 0\n", copychunk_resp.ChunkBytesWritten);
+ ok(copychunk_resp.TotalBytesWritten == written,
+ "wrong total bytes written: %d, should be %d\n", copychunk_resp.TotalBytesWritten, written);
+
+ ret = ReadFile(dest, testBuf, sizeof(testBuf), &count, NULL);
+ ok(ret != 0, "ReadFile error %d\n", GetLastError());
+ ok(count == sizeof(testBuf), "short read from regular file\n");
+ ok(!memcmp(testString, testBuf, sizeof(testBuf)), "copied contents not identical to original\n");
+
+ CloseHandle(dest);
+ CloseHandle(src);
+ if (pwine_get_version == NULL)
+ {
+ pNetShareDel(NULL, share_name, 0);
+ RemoveDirectoryW(share_path);
+ }
+}
+
START_TEST(file)
{
char temp_path[MAX_PATH];
@@ -6187,4 +6323,5 @@ START_TEST(file)
test_hard_link();
test_move_file();
test_eof();
+ test_copychunk();
}
--
2.32.0
More information about the wine-devel
mailing list